uatomic: Fix header guard comment
[urcu.git] / tests / utils / tap.sh
CommitLineData
da56d5ca 1#!/usr/bin/env bash
1b387491 2#
d001c886 3# SPDX-License-Identifier: GPL-3.0-or-later
1b387491 4#
d001c886 5# SPDX-FileCopyrightText: 2010 Patrick LeBoutillier <patrick.leboutillier@gmail.com>
1b387491 6#
1b387491
MJ
7
8_version='1.01'
9
10_plan_set=0
11_no_plan=0
12_skip_all=0
13_test_died=0
14_expected_tests=0
15_executed_tests=0
16_failed_tests=0
17TODO=
18
19
20usage(){
21 cat <<'USAGE'
22tap-functions: A TAP-producing BASH library
23
24PLAN:
25 plan_no_plan
26 plan_skip_all [REASON]
27 plan_tests NB_TESTS
28
29TEST:
30 ok RESULT [NAME]
31 okx COMMAND
32 is RESULT EXPECTED [NAME]
33 isnt RESULT EXPECTED [NAME]
34 like RESULT PATTERN [NAME]
35 unlike RESULT PATTERN [NAME]
36 pass [NAME]
37 fail [NAME]
38
39SKIP:
40 skip [CONDITION] [REASON] [NB_TESTS=1]
41
42 skip $feature_not_present "feature not present" 2 || {
43 is $a "a"
44 is $b "b"
45 }
46
47TODO:
48 Specify TODO mode by setting $TODO:
49 TODO="not implemented yet"
50 ok $result "some not implemented test"
51 unset TODO
52
53OTHER:
54 diag MSG
55
56EXAMPLE:
da56d5ca 57 #!/usr/bin/env bash
1b387491
MJ
58
59 . tap-functions
60
61 plan_tests 7
62
63 me=$USER
64 is $USER $me "I am myself"
65 like $HOME $me "My home is mine"
66 like "`id`" $me "My id matches myself"
67
68 /bin/ls $HOME 1>&2
69 ok $? "/bin/ls $HOME"
70 # Same thing using okx shortcut
71 okx /bin/ls $HOME
72
73 [[ "`id -u`" != "0" ]]
74 i_am_not_root=$?
75 skip $i_am_not_root "Must be root" || {
76 okx ls /root
77 }
78
79 TODO="figure out how to become root..."
80 okx [ "$HOME" == "/root" ]
81 unset TODO
82USAGE
83 exit
84}
85
86opt=
87set_u=
88while getopts ":sx" opt ; do
89 case $_opt in
90 u) set_u=1 ;;
91 *) usage ;;
92 esac
93done
94shift $(( OPTIND - 1 ))
95# Don't allow uninitialized variables if requested
96[[ -n "$set_u" ]] && set -u
97unset opt set_u
98
99# Used to call _cleanup on shell exit
100trap _exit EXIT
101
102
103plan_no_plan(){
104 (( _plan_set != 0 )) && "You tried to plan twice!"
105
106 _plan_set=1
107 _no_plan=1
108
109 return 0
110}
111
112
113plan_skip_all(){
114 local reason=${1:-''}
115
116 (( _plan_set != 0 )) && _die "You tried to plan twice!"
117
118 _print_plan 0 "Skip $reason"
119
120 _skip_all=1
121 _plan_set=1
122 _exit 0
123
124 return 0
125}
126
127plan_tests(){
128 local tests=${1:?}
129
130 (( _plan_set != 0 )) && _die "You tried to plan twice!"
131 (( tests == 0 )) && _die "You said to run 0 tests! You've got to run something."
132
133 _print_plan $tests
134 _expected_tests=$tests
135 _plan_set=1
136
137 return $tests
138}
139
140
141_print_plan(){
142 local tests=${1:?}
143 local directive=${2:-''}
144
145 echo -n "1..$tests"
146 [[ -n "$directive" ]] && echo -n " # $directive"
147 echo
148}
149
150
151pass(){
152 local name=$1
153 ok 0 "$name"
154}
155
156
157fail(){
158 local name=$1
159 ok 1 "$name"
160}
161
162# This is the workhorse method that actually
163# prints the tests result.
164ok(){
165 local result=${1:?}
166 local name=${2:-''}
167
168 (( _plan_set == 0 )) && _die "You tried to run a test without a plan! Gotta have a plan."
169
170 _executed_tests=$(( $_executed_tests + 1 ))
171
172 if [[ -n "$name" ]] ; then
173 if _matches "$name" "^[0-9]+$" ; then
174 diag " You named your test '$name'. You shouldn't use numbers for your test names."
175 diag " Very confusing."
176 fi
177 fi
178
179 if (( result != 0 )) ; then
180 echo -n "not "
181 _failed_tests=$(( _failed_tests + 1 ))
182 fi
183 echo -n "ok $_executed_tests"
184
185 if [[ -n "$name" ]] ; then
186 local ename=${name//\#/\\#}
187 echo -n " - $ename"
188 fi
189
190 if [[ -n "$TODO" ]] ; then
191 echo -n " # TODO $TODO" ;
192 if (( result != 0 )) ; then
193 _failed_tests=$(( _failed_tests - 1 ))
194 fi
195 fi
196
197 echo
198 if (( result != 0 )) ; then
199 local file='tap-functions'
200 local func=
201 local line=
202
203 local i=0
204 local bt=$(caller $i)
205 while _matches "$bt" "tap-functions$" ; do
206 i=$(( $i + 1 ))
207 bt=$(caller $i)
208 done
209 local backtrace=
210 eval $(caller $i | (read line func file ; echo "backtrace=\"$file:$func() at line $line.\""))
211
212 local t=
213 [[ -n "$TODO" ]] && t="(TODO) "
214
215 if [[ -n "$name" ]] ; then
216 diag " Failed ${t}test '$name'"
217 diag " in $backtrace"
218 else
219 diag " Failed ${t}test in $backtrace"
220 fi
221 fi
222
223 return $result
224}
225
226
227okx(){
228 local command="$@"
229
230 local line=
231 diag "Output of '$command':"
232 "$@" | while read line ; do
233 diag "$line"
234 done
235 ok ${PIPESTATUS[0]} "$command"
236}
237
238
239_equals(){
240 local result=${1:?}
241 local expected=${2:?}
242
243 if [[ "$result" == "$expected" ]] ; then
244 return 0
245 else
246 return 1
247 fi
248}
249
250
251# Thanks to Aaron Kangas for the patch to allow regexp matching
252# under bash < 3.
253 _bash_major_version=${BASH_VERSION%%.*}
254_matches(){
255 local result=${1:?}
256 local pattern=${2:?}
257
258 if [[ -z "$result" || -z "$pattern" ]] ; then
259 return 1
260 else
261 if (( _bash_major_version >= 3 )) ; then
262 [[ "$result" =~ "$pattern" ]]
263 else
264 echo "$result" | egrep -q "$pattern"
265 fi
266 fi
267}
268
269
270_is_diag(){
271 local result=${1:?}
272 local expected=${2:?}
273
274 diag " got: '$result'"
275 diag " expected: '$expected'"
276}
277
278
279is(){
280 local result=${1:?}
281 local expected=${2:?}
282 local name=${3:-''}
283
284 _equals "$result" "$expected"
285 (( $? == 0 ))
286 ok $? "$name"
287 local r=$?
288 (( r != 0 )) && _is_diag "$result" "$expected"
289 return $r
290}
291
292
293isnt(){
294 local result=${1:?}
295 local expected=${2:?}
296 local name=${3:-''}
297
298 _equals "$result" "$expected"
299 (( $? != 0 ))
300 ok $? "$name"
301 local r=$?
302 (( r != 0 )) && _is_diag "$result" "$expected"
303 return $r
304}
305
306
307like(){
308 local result=${1:?}
309 local pattern=${2:?}
310 local name=${3:-''}
311
312 _matches "$result" "$pattern"
313 (( $? == 0 ))
314 ok $? "$name"
315 local r=$?
316 (( r != 0 )) && diag " '$result' doesn't match '$pattern'"
317 return $r
318}
319
320
321unlike(){
322 local result=${1:?}
323 local pattern=${2:?}
324 local name=${3:-''}
325
326 _matches "$result" "$pattern"
327 (( $? != 0 ))
328 ok $? "$name"
329 local r=$?
330 (( r != 0 )) && diag " '$result' matches '$pattern'"
331 return $r
332}
333
334
335skip(){
336 local condition=${1:?}
337 local reason=${2:-''}
338 local n=${3:-1}
339
340 if (( condition == 0 )) ; then
341 local i=
342 for (( i=0 ; i<$n ; i++ )) ; do
343 _executed_tests=$(( _executed_tests + 1 ))
344 echo "ok $_executed_tests # skip: $reason"
345 done
346 return 0
347 else
348 return
349 fi
350}
351
352
353diag(){
354 local msg=${1:?}
355
356 if [[ -n "$msg" ]] ; then
357 echo "# $msg"
358 fi
359
360 return 1
361}
362
363
364_die(){
365 local reason=${1:-'<unspecified error>'}
366
367 echo "$reason" >&2
368 _test_died=1
369 _exit 255
370}
371
372
373BAIL_OUT(){
374 local reason=${1:-''}
375
376 echo "Bail out! $reason" >&2
377 _exit 255
378}
379
380
381_cleanup(){
382 local rc=0
383
384 if (( _plan_set == 0 )) ; then
385 diag "Looks like your test died before it could output anything."
386 return $rc
387 fi
388
389 if (( _test_died != 0 )) ; then
390 diag "Looks like your test died just after $_executed_tests."
391 return $rc
392 fi
393
394 if (( _skip_all == 0 && _no_plan != 0 )) ; then
395 _print_plan $_executed_tests
396 fi
397
398 local s=
399 if (( _no_plan == 0 && _expected_tests < _executed_tests )) ; then
400 s= ; (( _expected_tests > 1 )) && s=s
401 local extra=$(( _executed_tests - _expected_tests ))
402 diag "Looks like you planned $_expected_tests test$s but ran $extra extra."
403 rc=1 ;
404 fi
405
406 if (( _no_plan == 0 && _expected_tests > _executed_tests )) ; then
407 s= ; (( _expected_tests > 1 )) && s=s
408 diag "Looks like you planned $_expected_tests test$s but only ran $_executed_tests."
409 fi
410
411 if (( _failed_tests > 0 )) ; then
412 s= ; (( _failed_tests > 1 )) && s=s
413 diag "Looks like you failed $_failed_tests test$s of $_executed_tests."
414 fi
415
416 return $rc
417}
418
419
420_exit_status(){
421 if (( _no_plan != 0 || _plan_set == 0 )) ; then
422 return $_failed_tests
423 fi
424
425 if (( _expected_tests < _executed_tests )) ; then
426 return $(( _executed_tests - _expected_tests ))
427 fi
428
429 return $(( _failed_tests + ( _expected_tests - _executed_tests )))
430}
431
432
433_exit(){
434 local rc=${1:-''}
435 if [[ -z "$rc" ]] ; then
436 _exit_status
437 rc=$?
438 fi
439
440 _cleanup
441 local alt_rc=$?
442 (( alt_rc != 0 )) && rc=$alt_rc
443 trap - EXIT
444 exit $rc
445}
This page took 0.053343 seconds and 4 git commands to generate.