Improve copyright lines.
[open-adventure.git] / tests / tapview
1 #! /bin/sh
2 # tapview - a TAP (Test Anything Protocol) viewer in pure POSIX shell
3 #
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 a
8 # license by reference.
9 #
10 # SPDX-FileCopyrightText: Eric S. Raymond <esr@thyrsus.com>
11 # SPDX-License-Identifier: BSD-2-Clause
12 #
13 # This is version 1.6
14 # A newer version may be available at https://gitlab.com/esr/tapview
15 #
16 OK="."
17 FAIL="F"
18 SKIP="s"
19 TODO_NOT_OK="x"
20 TODO_OK="u"
21
22 ship_char() {
23     # shellcheck disable=SC2039
24     printf '%s' "$1"    # https://www.etalabs.net/sh_tricks.html
25 }
26
27 ship_line() {
28     report="${report}${1}\n"
29 }
30
31 ship_error() {
32     # Terminate dot display and bail out with error
33     if [ "${testcount}" -gt 0 ]
34     then
35         echo ""
36     fi
37     report="${report}${1}\n"
38     echo "${report}"
39     exit 1
40 }
41
42 testcount=0
43 failcount=0
44 skipcount=0
45 todocount=0
46 status=0
47 report=""
48 IFS=""
49 ln=0
50 state=plaintext
51
52 # shellcheck disable=SC2086
53 context_get () { printenv "ctx_${1}${depth}"; }
54 context_set () { export "ctx_${1}${depth}=${2}"; }
55
56 context_push () {
57     context_set plan ""
58     context_set count 0
59     context_set test_before_plan no
60     context_set test_after_plan no
61     context_set expect ""
62     context_set bail no
63     context_set strict no
64 }
65
66 context_pop () {
67     if [ "$(context_get count)" -gt 0 ] && [ -z "$(context_get plan)" ]
68     then
69         ship_line "Missing a plan at line ${ln}."
70         status=1
71     elif [ "$(context_get test_before_plan)" = "yes" ] && [ "$(context_get test_after_plan)" = "yes" ] 
72     then
73         ship_line "A plan line may only be placed before or after all tests."
74         status=1
75     elif [ "$(context_get plan)" != "" ] && [ "$(context_get expect)" -gt "$(context_get count)" ]
76     then
77         ship_line "Expected $(context_get expect) tests but only ${testcount} ran."
78         status=1
79     fi
80 }
81
82 depth=0
83 context_push
84
85 while read -r line
86 do
87     ln=$((ln + 1))
88     # Process bailout
89     if expr "$line" : "Bail out!" >/dev/null
90     then
91         ship_line "$line"
92         status=2
93         break
94     fi
95     # Use the current indent to choose a scope level
96     indent=$(expr "$line" : '[  ]*')
97     if [ "${indent}" -lt "${depth}" ]
98     then
99         context_pop
100         depth="${indent}"
101     elif [ "${indent}" -gt "${depth}" ]
102     then
103         depth="${indent}"
104         context_push
105     fi
106     # Process a plan line
107     if expr "$line" : '[        ]*1\.\.[0-9][0-9]*' >/dev/null
108     then
109         if [ "$(context_get plan)" != "" ]
110         then
111             ship_error "tapview: cannot have more than one plan line."
112         fi
113         if expr "$line" : ".* *SKIP" >/dev/null || expr "$line" : ".* *skip" >/dev/null
114         then
115             ship_line "$line"
116             echo "${report}"
117             exit 1      # Not specified in the standard whether this should exit 1 or 0
118         fi
119         context_set plan "${line}"
120         context_set expect "$(expr "$line" : '[         ]*1\.\.\([0-9][0-9]*\)')"
121         continue
122     elif expr "$line" : '[      ]*[0-9][0-9]*\.\.[0-9][0-9]*' >/dev/null
123     then
124          echo "Ill-formed plan line at ${ln}"
125          exit 1
126     fi
127     # Check for out-of-order test point numbers with the sequence (TAP 14)
128     testpoint=$(expr "$line" : '.*ok  *\([0-9][0-9]*\)')
129     if [ "${testpoint}" != "" ] && [ "$(context_get expect)" != "" ] && [ "${testpoint}" -gt "$(context_get expect)" ]
130     then
131         ship_error "tapview: testpoint number ${testpoint} is out of range for plan $(context_get plan)."
132     fi
133     # Process an ok line
134     if expr "$line" : "[        ]*ok" >/dev/null
135     then
136         context_set count $(($(context_get count) + 1)) 
137         testcount=$((testcount + 1))
138         if [ "$(context_get plan)" = "" ]
139         then
140             context_set test_before_plan yes
141         else
142             context_set test_after_plan yes
143         fi
144         if expr "$line" : "[^#]* # *TODO" >/dev/null || expr "$line" : "[^#]* # *todo" >/dev/null
145         then
146             ship_char ${TODO_OK}
147             ship_line "$line"
148             todocount=$((todocount + 1))
149             if expr "$line" : "[^#]*#[^ ]" >/dev/null
150             then
151                 ship_line "Suspicious comment leader at ${ln}"
152             fi
153         elif expr "$line" : "[^#]* # *SKIP" >/dev/null || expr "$line" : "[^#]* # *skip" >/dev/null
154         then
155             ship_char ${SKIP}
156             ship_line "$line"
157             skipcount=$((skipcount + 1))
158             if expr "$line" : "[^#]*#[^ ]" >/dev/null
159             then
160                 ship_line "Suspicious comment leader at ${ln}"
161             fi
162         else
163             ship_char ${OK}
164         fi
165         state=plaintext
166         continue
167     fi
168     # Process a not-ok line
169     if expr "$line" : "[        ]*not ok" >/dev/null
170     then
171         context_set count $(($(context_get count) + 1)) 
172         testcount=$((testcount + 1))
173         if [ "$(context_get plan)" = "" ]
174         then
175             context_set test_before_plan yes
176         else
177             context_set test_after_plan yes
178         fi
179         if expr "$line" : "[^#]* # *SKIP" >/dev/null || expr "$line" : "[^#]* # *skip" >/dev/null
180         then
181             ship_char "${SKIP}"
182             state=plaintext
183             skipcount=$((skipcount + 1))
184             if expr "$line" : "[^#]* #[^ ]" >/dev/null
185             then
186                 ship_line "Suspicious comment leader at lime ${ln}"
187             fi
188             continue
189         fi
190         if expr "$line" : "[^#]* # *TODO" >/dev/null || expr "$line" : "[^#]* # *todo" >/dev/null
191         then
192             ship_char ${TODO_NOT_OK}
193             state=plaintext
194             todocount=$((todocount + 1))
195             if expr "$line" : "[^#]* #[^ ]" >/dev/null
196             then
197                 ship_line "Suspicious comment leader at line ${ln}"
198             fi
199             continue
200         fi
201         ship_char "${FAIL}"
202         ship_line "$line"
203         state=plaintext
204         failcount=$((failcount + 1))
205         status=1
206         if [ "$(context_get bail)" = yes ]
207         then
208             ship_line "Bailing out on line ${ln} due to +bail pragma."
209             break
210         fi
211         continue
212     fi
213     # Process a TAP 14 pragma
214     if expr "$line" : "pragma" >/dev/null
215     then
216         unset IFS
217         # shellcheck disable=SC2086
218         set -- $line
219         case "$2" in
220             +bail) context_set bail yes;;
221             -bail) context_set bail yes;;
222             +strict) context_set strict yes;;
223             -strict) context_set strict yes;;
224             *) ship_line "Pragma '$line' ignored";;
225         esac
226         IFS=""
227         continue
228     fi
229     # shellcheck disable=SC2166
230     if [ "${state}" = "yaml" ]
231     then
232         ship_line "$line"
233         if expr "$line" : '[    ]*\.\.\.' >/dev/null
234         then
235             state=plaintext
236         else
237             continue
238         fi
239     elif expr "$line" : "[      ]*---" >/dev/null
240     then
241         ship_line "$line"
242         state=yaml
243         continue
244     fi
245     # Ignore blank lines and comments
246     if [ -z "$line" ] || expr "$line" : '[      ]+$' >/dev/null || expr "$line" : "#" >/dev/null
247     then
248         continue
249     fi
250     # Any line that is not a valid plan, test result, pragma,
251     # or comment lands here.
252     if [ "$(context_get strict)" = yes ]
253     then
254         ship_line "Bailing out on line ${ln} due to +strict pragma"
255         status=1
256         break
257     fi
258 done
259
260 /bin/echo ""
261
262 depth=0
263 context_pop
264
265 report="${report}${testcount} tests, ${failcount} failures"
266 if [ "$todocount" != 0 ]
267 then
268     report="${report}, ${todocount} TODOs"
269 fi
270 if [ "$skipcount" != 0 ]
271 then
272     report="${report}, ${skipcount} SKIPs"
273 fi
274
275 echo "${report}."
276
277 exit "${status}"
278
279 # end