From ff2dd31209cac24dc26abbe6146158de62393fec Mon Sep 17 00:00:00 2001 From: "Eric S. Raymond" Date: Tue, 28 Feb 2023 15:04:42 -0500 Subject: [PATCH] Update our tapview copy. --- tests/tapview | 223 +++++++++++++++++++++++++++++++++++--------------- 1 file changed, 156 insertions(+), 67 deletions(-) diff --git a/tests/tapview b/tests/tapview index 9acd0c4..ca984eb 100755 --- a/tests/tapview +++ b/tests/tapview @@ -6,28 +6,14 @@ # 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 applies. +# OSD-compliant; otherwise the following SPDX tag incorporates a +# license by reference. # # SPDX-License-Identifier: BSD-2-Clause # -# This is version 1.0 +# This is version 1.6 # A newer version may be available at https://gitlab.com/esr/tapview # -# POSIX allows but does not mandate that -n suppresses emission of a -# trailing newline in echo. Thus, some shell builtin echos don't do -# that. Cope gracefully. -# shellcheck disable=SC2039 -if [ "$(echo -n "a"; echo "b")" != "ab" ] -then - ECHO="echo" -elif [ "$(/bin/echo -n "a"; /bin/echo "b")" = "ab" ] -then - ECHO="/bin/echo" -else - echo "tapview: bailing out, your echo lacks -n support." - exit 3 -fi - OK="." FAIL="F" SKIP="s" @@ -36,44 +22,94 @@ TODO_OK="u" ship_char() { # shellcheck disable=SC2039 - "${ECHO}" -n "$1" + printf '%s' "$1" # https://www.etalabs.net/sh_tricks.html } ship_line() { report="${report}${1}\n" } +ship_error() { + # Terminate dot display and bail out with error + if [ "${testcount}" -gt 0 ] + then + echo "" + fi + report="${report}${1}\n" + echo "${report}" + exit 1 +} + testcount=0 failcount=0 skipcount=0 todocount=0 -test_before_plan=no -test_after_plan=no -expect="" status=0 - report="" IFS="" -state=start +ln=0 +state=plaintext + +# shellcheck disable=SC2086 +context_get () { printenv "ctx_${1}${depth}"; } +context_set () { export "ctx_${1}${depth}=${2}"; } + +context_push () { + context_set plan "" + context_set count 0 + context_set test_before_plan no + context_set test_after_plan no + context_set expect "" + context_set bail no + context_set strict no +} + +context_pop () { + if [ "$(context_get count)" -gt 0 ] && [ -z "$(context_get plan)" ] + then + ship_line "Missing a plan at line ${ln}." + status=1 + elif [ "$(context_get test_before_plan)" = "yes" ] && [ "$(context_get test_after_plan)" = "yes" ] + then + ship_line "A plan line may only be placed before or after all tests." + status=1 + elif [ "$(context_get plan)" != "" ] && [ "$(context_get expect)" -gt "$(context_get count)" ] + then + ship_line "Expected $(context_get expect) tests but only ${testcount} ran." + status=1 + fi +} + +depth=0 +context_push + while read -r line do + ln=$((ln + 1)) + # Process bailout if expr "$line" : "Bail out!" >/dev/null then ship_line "$line" status=2 break fi - if expr "$line" : '1\.\.[0-9][0-9]*' >/dev/null >/dev/null + # Use the current indent to choose a scope level + indent=$(expr "$line" : '[ ]*') + if [ "${indent}" -lt "${depth}" ] then - if [ "$expect" != "" ] + context_pop + depth="${indent}" + elif [ "${indent}" -gt "${depth}" ] + then + 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 - if [ "${testcount}" -gt 0 ] - then - echo "" - fi - ship_line "Cannot have more than one plan line." - echo "${report}" - exit 1 + ship_error "tapview: cannot have more than one plan line." fi if expr "$line" : ".* *SKIP" >/dev/null || expr "$line" : ".* *skip" >/dev/null then @@ -81,62 +117,114 @@ do echo "${report}" exit 1 # Not specified in the standard whether this should exit 1 or 0 fi - expect=$(expr "$line" : '1\.\.\([0-9][0-9]*\)') + 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 - if expr "$line" : "ok" >/dev/null + # 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 an ok line + if expr "$line" : "[ ]*ok" >/dev/null + then + context_set count $(($(context_get count) + 1)) testcount=$((testcount + 1)) - if [ "$expect" = "" ] + if [ "$(context_get plan)" = "" ] then - test_before_plan=yes + context_set test_before_plan yes else - test_after_plan=yes + context_set test_after_plan yes fi - if expr "$line" : ".*# *TODO" >/dev/null || expr "$line" : ".*# *todo" >/dev/null + if expr "$line" : "[^#]* # *TODO" >/dev/null || expr "$line" : "[^#]* # *todo" >/dev/null then ship_char ${TODO_OK} ship_line "$line" todocount=$((todocount + 1)) - elif expr "$line" : ".*# *SKIP" >/dev/null || expr "$line" : ".*# *skip" >/dev/null + 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 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 - state=ok + state=plaintext continue fi - if expr "$line" : "not ok" >/dev/null + # Process a not-ok line + if expr "$line" : "[ ]*not ok" >/dev/null then + context_set count $(($(context_get count) + 1)) testcount=$((testcount + 1)) - if [ "$expect" = "" ] + if [ "$(context_get plan)" = "" ] then - test_before_plan=yes + context_set test_before_plan yes else - test_after_plan=yes + context_set test_after_plan yes fi - if expr "$line" : ".*# *SKIP" >/dev/null || expr "$line" : ".*# *skip" >/dev/null + if expr "$line" : "[^#]* # *SKIP" >/dev/null || expr "$line" : "[^#]* # *skip" >/dev/null then ship_char "${SKIP}" - state=ok + 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 expr "$line" : "[^#]* # *TODO" >/dev/null || expr "$line" : "[^#]* # *todo" >/dev/null then ship_char ${TODO_NOT_OK} - state=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}" ship_line "$line" - state=not_ok + state=plaintext failcount=$((failcount + 1)) status=1 + if [ "$(context_get bail)" = yes ] + then + ship_line "Bailing out on line ${ln} due to +bail pragma." + break + fi + 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;; + *) ship_line "Pragma '$line' ignored";; + esac + IFS="" continue fi # shellcheck disable=SC2166 @@ -145,34 +233,35 @@ do ship_line "$line" if expr "$line" : '[ ]*\.\.\.' >/dev/null then - state=ok + state=plaintext + else + continue fi elif expr "$line" : "[ ]*---" >/dev/null 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 ] + then + ship_line "Bailing out on line ${ln} due to +strict pragma" + status=1 + break fi done /bin/echo "" -if [ -z "$expect" ] -then - ship_line "Missing a plan." - status=1 -elif [ "$test_before_plan" = "yes" ] && [ "$test_after_plan" = "yes" ] -then - ship_line "A plan line may only be placed before or after all tests." - status=1 -elif [ "${expect}" -gt "${testcount}" ] -then - ship_line "Expected ${expect} tests but only ${testcount} ran." - status=1 -elif [ "${expect}" -lt "${testcount}" ] -then - ship_line "Expected ${expect} tests but ${testcount} ran." - status=1 -fi +depth=0 +context_pop report="${report}${testcount} tests, ${failcount} failures" if [ "$todocount" != 0 ] -- 2.31.1