diff --git a/bin/tapview b/bin/tapview index 5a76741..38fda8d 100755 --- a/bin/tapview +++ b/bin/tapview @@ -1,25 +1,24 @@ #! /bin/sh # tapview - a TAP (Test Anything Protocol) viewer in pure POSIX shell # -# SPDX-FileCopyrightText: Eric S. Raymond -# SPDX-License-Identifier: MIT-0 -# # This code is intended to be embedded in your project. The author # grants permission for it to be distributed under the prevailing # license of your project if you choose, provided that license is # OSD-compliant; otherwise the following SPDX tag incorporates the # MIT No Attribution license by reference. # -# A newer version may be available at https://gitlab.com/esr/tapview -# Check your last commit dqte for this file against the commit list -# there to see if it might be a good idea to update. +# SPDX-FileCopyrightText: (C) Eric S. Raymond +# SPDX-License-Identifier: MIT-0 # +# This version shipped on 2024-01-31. A newer version may be available +# at https://gitlab.com/esr/tapview; check the ship date oagainst the +# commit list there to see if it might be a good idea to update. + OK="." FAIL="F" SKIP="s" TODO_NOT_OK="x" TODO_OK="u" - LF=' ' @@ -49,7 +48,6 @@ skipcount=0 todocount=0 status=0 report="" -IFS="" ln=0 state=plaintext @@ -80,24 +78,47 @@ context_pop () { then ship_line "Expected $(context_get expect) tests but only ${testcount} ran." status=1 + elif [ "$(context_get plan)" != "" ] && [ "$(context_get expect)" -lt "$(context_get count)" ] + then + ship_line "${testcount} ran but $(context_get expect) expected." + status=1 fi } +directive () { + case "$1" in + *[[:space:]]#[[:space:]]*$2*) return 0;; + *) return 1;; + esac +} + depth=0 context_push - while read -r line do ln=$((ln + 1)) + IFS=" " + # shellcheck disable=SC2086 + set -- $line + tok1="$1" + tok2="$2" + tok3="$3" + IFS="" + # Ignore blank lines and comments + if [ -z "$tok1" ] || [ "$tok1" = '#' ] + then + continue + fi # Process bailout - if expr "$line" : "Bail out!" >/dev/null + if [ "$tok1" = "Bail" ] && [ "$tok2" = "out!" ] then ship_line "$line" status=2 break fi # Use the current indent to choose a scope level - indent=$(expr "$line" : '[ ]*') + leading_spaces="${line%%[! ]*}" + indent=${#leading_spaces} if [ "${indent}" -lt "${depth}" ] then context_pop @@ -107,35 +128,45 @@ do depth="${indent}" context_push fi - # Process a plan line - if expr "$line" : '[ ]*1\.\.[0-9][0-9]*' >/dev/null - then - if [ "$(context_get plan)" != "" ] - then - ship_error "tapview: cannot have more than one plan line." - fi - if expr "$line" : ".* *SKIP" >/dev/null || expr "$line" : ".* *skip" >/dev/null - then - ship_line "$line" - echo "${report}" - exit 1 # Not specified in the standard whether this should exit 1 or 0 - fi - context_set plan "${line}" - context_set expect "$(expr "$line" : '[ ]*1\.\.\([0-9][0-9]*\)')" - continue - elif expr "$line" : '[ ]*[0-9][0-9]*\.\.[0-9][0-9]*' >/dev/null - then - echo "Ill-formed plan line at ${ln}" - exit 1 - fi - # Check for out-of-order test point numbers with the sequence (TAP 14) - testpoint=$(expr "$line" : '.*ok *\([0-9][0-9]*\)') - if [ "${testpoint}" != "" ] && [ "$(context_get expect)" != "" ] && [ "${testpoint}" -gt "$(context_get expect)" ] - then - ship_error "tapview: testpoint number ${testpoint} is out of range for plan $(context_get plan)." - fi + # Process a plan line (outer case is because expr is expensive) + case "$tok1" in + [0123456789]*) + if expr "$line" : '[ ]*1\.\.[0-9][0-9]*' >/dev/null + then + if [ "$(context_get plan)" != "" ] + then + ship_error "tapview: cannot have more than one plan line." + fi + if directive "$line" [Ss][Kk][Ii][Pp] + then + ship_line "$line" + echo "${report}" + exit 1 # Not specified in the standard whether this should exit 1 or 0 + fi + context_set plan "${line}" + context_set expect "$(expr "$line" : '[ ]*1\.\.\([0-9][0-9]*\)')" + continue + elif expr "$line" : '[ ]*[0-9][0-9]*\.\.[0-9][0-9]*' >/dev/null + then + echo "Ill-formed plan line at ${ln}" + exit 1 + fi + ;; esac + # Check for test point numbers out-of-order with the sequence (TAP 14) + testpoint="" + case "$tok1" in + ok) testpoint="$tok2";; + not) testpoint="$tok3";; + esac + case "$testpoint" in + *[0123456789]*) + if [ "${testpoint}" != "" ] && [ "$(context_get expect)" != "" ] && [ "${testpoint}" -gt "$(context_get expect)" ] + then + ship_error "tapview: testpoint number ${testpoint} is out of range for plan $(context_get plan)." + fi + ;; esac # Process an ok line - if expr "$line" : "[ ]*ok" >/dev/null + if [ "$tok1" = "ok" ] then context_set count $(($(context_get count) + 1)) testcount=$((testcount + 1)) @@ -145,24 +176,16 @@ do else context_set test_after_plan yes fi - if expr "$line" : "[^#]* # *TODO" >/dev/null || expr "$line" : "[^#]* # *todo" >/dev/null + if directive "$line" [Tt][Oo][Dd][Oo] then ship_char ${TODO_OK} ship_line "$line" todocount=$((todocount + 1)) - if expr "$line" : "[^#]*#[^ ]" >/dev/null - then - ship_line "Suspicious comment leader at ${ln}" - fi - elif expr "$line" : "[^#]* # *SKIP" >/dev/null || expr "$line" : "[^#]* # *skip" >/dev/null + elif directive "$line" [Ss][Kk][Ii][Pp] then ship_char ${SKIP} ship_line "$line" skipcount=$((skipcount + 1)) - if expr "$line" : "[^#]*#[^ ]" >/dev/null - then - ship_line "Suspicious comment leader at ${ln}" - fi else ship_char ${OK} fi @@ -170,7 +193,7 @@ do continue fi # Process a not-ok line - if expr "$line" : "[ ]*not ok" >/dev/null + if [ "$tok1" = "not" ] && [ "$tok2" = "ok" ] then context_set count $(($(context_get count) + 1)) testcount=$((testcount + 1)) @@ -180,26 +203,18 @@ do else context_set test_after_plan yes fi - if expr "$line" : "[^#]* # *SKIP" >/dev/null || expr "$line" : "[^#]* # *skip" >/dev/null + if directive "$line" [Ss][Kk][Ii][Pp] then ship_char "${SKIP}" state=plaintext skipcount=$((skipcount + 1)) - if expr "$line" : "[^#]* #[^ ]" >/dev/null - then - ship_line "Suspicious comment leader at lime ${ln}" - fi continue fi - if expr "$line" : "[^#]* # *TODO" >/dev/null || expr "$line" : "[^#]* # *todo" >/dev/null + if directive "$line" [Tt][Oo][Dd][Oo] then ship_char ${TODO_NOT_OK} state=plaintext todocount=$((todocount + 1)) - if expr "$line" : "[^#]* #[^ ]" >/dev/null - then - ship_line "Suspicious comment leader at line ${ln}" - fi continue fi ship_char "${FAIL}" @@ -215,42 +230,34 @@ do continue fi # Process a TAP 14 pragma - if expr "$line" : "pragma" >/dev/null - then - unset IFS - # shellcheck disable=SC2086 - set -- $line - case "$2" in - +bail) context_set bail yes;; - -bail) context_set bail yes;; - +strict) context_set strict yes;; - -strict) context_set strict yes;; + case "$line" in + pragma*) + case "$line" in + *+bail*) context_set bail yes;; + *-bail*) context_set bail yes;; + *+strict*) context_set strict yes;; + *-strict*) context_set strict yes;; *) ship_line "Pragma '$line' ignored";; esac - IFS="" continue - fi + ;; + esac # shellcheck disable=SC2166 if [ "${state}" = "yaml" ] then ship_line "$line" - if expr "$line" : '[ ]*\.\.\.' >/dev/null + if [ "$tok1" = "..." ] then state=plaintext else continue fi - elif expr "$line" : "[ ]*---" >/dev/null + elif [ "$tok1" = "---" ] then ship_line "$line" state=yaml continue fi - # Ignore blank lines and comments - if [ -z "$line" ] || expr "$line" : '[ ]+$' >/dev/null || expr "$line" : "#" >/dev/null - then - continue - fi # Any line that is not a valid plan, test result, pragma, # or comment lands here. if [ "$(context_get strict)" = yes ] @@ -262,10 +269,8 @@ do done /bin/echo "" - depth=0 context_pop - report="${report}${testcount} tests, ${failcount} failures" if [ "$todocount" != 0 ] then @@ -277,7 +282,6 @@ then fi echo "${report}." - exit "${status}" # end