2 # tapview - a TAP (Test Anything Protocol) viewer in pure POSIX shell
4 # This code is intended to be embedded in your project. The author
5 # grants permission for it to be distributed under the prevailing
6 # license of your project if you choose, provided that license is
7 # OSD-compliant; otherwise the following SPDX tag incorporates the
8 # MIT No Attribution license by reference.
10 # SPDX-FileCopyrightText: (C) Eric S. Raymond <esr@thyrsus.com>
11 # SPDX-License-Identifier: MIT-0
13 # A newer version may be available at https://gitlab.com/esr/tapview
14 # Check your last commit date for this file against the commit list
15 # there to see if it might be a good idea to update.
27 # shellcheck disable=SC2039
28 printf '%s' "$1" # https://www.etalabs.net/sh_tricks.html
32 report="${report}${1}$LF"
36 # Terminate dot display and bail out with error
37 if [ "${testcount}" -gt 0 ]
41 report="${report}${1}$LF"
56 # shellcheck disable=SC2086
57 context_get () { printenv "ctx_${1}${depth}"; }
58 context_set () { export "ctx_${1}${depth}=${2}"; }
63 context_set test_before_plan no
64 context_set test_after_plan no
71 if [ "$(context_get count)" -gt 0 ] && [ -z "$(context_get plan)" ]
73 ship_line "Missing a plan at line ${ln}."
75 elif [ "$(context_get test_before_plan)" = "yes" ] && [ "$(context_get test_after_plan)" = "yes" ]
77 ship_line "A plan line may only be placed before or after all tests."
79 elif [ "$(context_get plan)" != "" ] && [ "$(context_get expect)" -gt "$(context_get count)" ]
81 ship_line "Expected $(context_get expect) tests but only ${testcount} ran."
83 elif [ "$(context_get plan)" != "" ] && [ "$(context_get expect)" -lt "$(context_get count)" ]
85 ship_line "${testcount} ran but $(context_get expect) expected."
97 if expr "$line" : "Bail out!" >/dev/null
103 # Use the current indent to choose a scope level
104 indent=$(expr "$line" : '[ ]*')
105 if [ "${indent}" -lt "${depth}" ]
109 elif [ "${indent}" -gt "${depth}" ]
114 # Process a plan line
115 if expr "$line" : '[ ]*1\.\.[0-9][0-9]*' >/dev/null
117 if [ "$(context_get plan)" != "" ]
119 ship_error "tapview: cannot have more than one plan line."
121 if expr "$line" : ".* *SKIP" >/dev/null || expr "$line" : ".* *skip" >/dev/null
125 exit 1 # Not specified in the standard whether this should exit 1 or 0
127 context_set plan "${line}"
128 context_set expect "$(expr "$line" : '[ ]*1\.\.\([0-9][0-9]*\)')"
130 elif expr "$line" : '[ ]*[0-9][0-9]*\.\.[0-9][0-9]*' >/dev/null
132 echo "Ill-formed plan line at ${ln}"
135 # Check for out-of-order test point numbers with the sequence (TAP 14)
136 testpoint=$(expr "$line" : '.*ok *\([0-9][0-9]*\)')
137 if [ "${testpoint}" != "" ] && [ "$(context_get expect)" != "" ] && [ "${testpoint}" -gt "$(context_get expect)" ]
139 ship_error "tapview: testpoint number ${testpoint} is out of range for plan $(context_get plan)."
142 if expr "$line" : "[ ]*ok" >/dev/null
144 context_set count $(($(context_get count) + 1))
145 testcount=$((testcount + 1))
146 if [ "$(context_get plan)" = "" ]
148 context_set test_before_plan yes
150 context_set test_after_plan yes
152 if expr "$line" : "[^#]* # *TODO" >/dev/null || expr "$line" : "[^#]* # *todo" >/dev/null
156 todocount=$((todocount + 1))
157 if expr "$line" : "[^#]*#[^ ]" >/dev/null
159 ship_line "Suspicious comment leader at ${ln}"
161 elif expr "$line" : "[^#]* # *SKIP" >/dev/null || expr "$line" : "[^#]* # *skip" >/dev/null
165 skipcount=$((skipcount + 1))
166 if expr "$line" : "[^#]*#[^ ]" >/dev/null
168 ship_line "Suspicious comment leader at ${ln}"
176 # Process a not-ok line
177 if expr "$line" : "[ ]*not ok" >/dev/null
179 context_set count $(($(context_get count) + 1))
180 testcount=$((testcount + 1))
181 if [ "$(context_get plan)" = "" ]
183 context_set test_before_plan yes
185 context_set test_after_plan yes
187 if expr "$line" : "[^#]* # *SKIP" >/dev/null || expr "$line" : "[^#]* # *skip" >/dev/null
191 skipcount=$((skipcount + 1))
192 if expr "$line" : "[^#]* #[^ ]" >/dev/null
194 ship_line "Suspicious comment leader at lime ${ln}"
198 if expr "$line" : "[^#]* # *TODO" >/dev/null || expr "$line" : "[^#]* # *todo" >/dev/null
200 ship_char ${TODO_NOT_OK}
202 todocount=$((todocount + 1))
203 if expr "$line" : "[^#]* #[^ ]" >/dev/null
205 ship_line "Suspicious comment leader at line ${ln}"
212 failcount=$((failcount + 1))
214 if [ "$(context_get bail)" = yes ]
216 ship_line "Bailing out on line ${ln} due to +bail pragma."
221 # Process a TAP 14 pragma
222 if expr "$line" : "pragma" >/dev/null
225 # shellcheck disable=SC2086
228 +bail) context_set bail yes;;
229 -bail) context_set bail yes;;
230 +strict) context_set strict yes;;
231 -strict) context_set strict yes;;
232 *) ship_line "Pragma '$line' ignored";;
237 # shellcheck disable=SC2166
238 if [ "${state}" = "yaml" ]
241 if expr "$line" : '[ ]*\.\.\.' >/dev/null
247 elif expr "$line" : "[ ]*---" >/dev/null
253 # Ignore blank lines and comments
254 if [ -z "$line" ] || expr "$line" : '[ ]+$' >/dev/null || expr "$line" : "#" >/dev/null
258 # Any line that is not a valid plan, test result, pragma,
259 # or comment lands here.
260 if [ "$(context_get strict)" = yes ]
262 ship_line "Bailing out on line ${ln} due to +strict pragma"
273 report="${report}${testcount} tests, ${failcount} failures"
274 if [ "$todocount" != 0 ]
276 report="${report}, ${todocount} TODOs"
278 if [ "$skipcount" != 0 ]
280 report="${report}, ${skipcount} SKIPs"