]> git.draconx.ca Git - liblbx.git/blob - tests/util/tap-functions.sh
tests: First stab at a proper test suite.
[liblbx.git] / tests / util / tap-functions.sh
1 # -*- shell-script -*-
2 #
3 # Copyright (C) 2011-2013 Free Software Foundation, Inc.
4 #
5 # This program is free software; you can redistribute it and/or modify
6 # it under the terms of the GNU General Public License as published by
7 # the Free Software Foundation; either version 2, or (at your option)
8 # any later version.
9 #
10 # This program is distributed in the hope that it will be useful,
11 # but WITHOUT ANY WARRANTY; without even the implied warranty of
12 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 # GNU General Public License for more details.
14 #
15 # You should have received a copy of the GNU General Public License
16 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
17
18 # Helper functions used by TAP-producing tests of the Automake testsuite.
19
20 #
21 # IMPORTANT: All the functions defined in this file can *not* be used
22 #            from within a subshell, unless explicitly noted otherwise.
23 #
24
25 # The counts of the TAP test results seen so far: total count and
26 # per-result counts.
27 tap_count_=0
28 tap_pass_count_=0
29 tap_skip_count_=0
30 tap_fail_count_=0
31 tap_xfail_count_=0
32 tap_xpass_count_=0
33
34 # not COMMAND [ARGS...]
35 # ---------------------
36 # Run the given command and invert its exit status.
37 not () { ! "$@"; }
38
39 # plan_ [unknown|later|lazy|now|NUMBER-OF-PLANNED-TESTS]
40 # ------------------------------------------------------
41 # Print a TAP plan for the given number of tests.  This must be called
42 # before reporting any test result.  If called with the special argument
43 # "unknown" or "later", it will do nothing, expecting the calling script
44 # to declare the plan later.  If called with the special argument "lazy"
45 # or "now", it will print a TAP plan that accounts for the number of tests
46 # seen so far.
47 plan_ ()
48 {
49   if test $# -eq 0; then
50     bailout_ "plan_: missing argument"
51   elif test $# -ge 2; then
52     bailout_ "plan_: too many arguments"
53   elif test x"$planned_" != x"none" && test x"$planned_" != x"later"; then
54     bailout_ "plan_: called to many times"
55   elif test x"$1" = x"unknown" || test x"$1" = x"later"; then
56     # This means we want to get back later to declaring the TAP plan.
57     planned_=later
58     return 0
59   elif test x"$1" = x"lazy" || test x"$1" = x"now"; then
60     planned_=$tap_count_ # Number of test results seen so far.
61   elif test $1 -ge 0; then
62     planned_=$1
63   else
64     bailout_ "plan_: invalid argument '$1'"
65   fi
66   echo "1..$planned_"
67 }
68 planned_=none
69
70 # diag_ [EXPLANATION]
71 # ------------------
72 # Report the given text as TAP diagnostic.  Assumes the string denoting
73 # TAP diagnostic lines is stored in the '$diag_string_' variable; this is
74 # done to allow better interplay with TAP drivers that allow such a string
75 # to be configured.
76 diag_ ()
77 {
78   test $# -eq 0 || echo "$diag_string_ $*"
79 }
80
81 # Used by the 'diag_' function above.  User-overridable.
82 diag_string_="#"
83
84 # warn_ [EXPLANATION]
85 # ------------------
86 # Give a warning (using TAP diagnostic).
87 warn_ ()
88 {
89   case $# in
90     0) diag_ "WARNING: (unknown warning)";;
91     *) diag_ "WARNING: $*";;
92   esac
93 }
94
95 # result_ RESULT [-D DIRECTIVE] [-r REASON] [--] [DESCRIPTION...]
96 # ---------------------------------------------------------------
97 # Report a test case with the given RESULT (valid values are "ok" and
98 # "not ok") and the given DESCRIPTION (if any).  If DIRECTIVE is given
99 # and non-empty (valid values being "TODO" and "SKIP"), it will be
100 # reported too, with the REASON (if given) appended.
101 result_ ()
102 {
103   set +x # Don't pollute the log files.
104   test $# -gt 0 || bailout_ "result_: missing argument"
105   tap_result_=$1; shift
106   case $tap_result_ in
107     "ok"|"not ok") ;;
108     *) bailout_ "result_: invalid result '$tap_result'" ;;
109   esac
110   tap_directive_= tap_reason_=
111   while test $# -gt 0; do
112     case $1 in
113       -D|--directive) tap_directive_=$2; shift;;
114       -r|--reason) tap_reason_=$2; shift;;
115       --) shift; break;;
116       -*) bailout_ "result_: invalid option '$1'";;
117        *) break;;
118     esac
119     shift
120   done
121   case $tap_directive_ in
122     ""|TODO|SKIP) ;;
123     *) bailout_ "result_: invalid directive '$directive_'" ;;
124   esac
125   tap_count_=$(($tap_count_ + 1))
126   case $tap_result_,$tap_directive_ in
127     ok,)                                                # Passed.
128       tap_pass_count_=$(($tap_pass_count_ + 1))         ;;
129     not\ ok,TODO)                                       # Expected failure.
130       tap_xfail_count_=$(($tap_xfail_count_ + 1))       ;;
131     not\ ok,*)                                          # Failed.
132       tap_fail_count_=$(($tap_fail_count_ + 1))         ;;
133     ok,TODO)                                            # Unexpected pass.
134       tap_xpass_count_=$(($tap_xpass_count_ + 1))       ;;
135     ok,SKIP)                                            # Skipped.
136       tap_skip_count_=$(($tap_skip_count_ + 1))         ;;
137     *)                                                  # Can't happen.
138       bailout_ "internal error in 'result_'"            ;;
139   esac
140   tap_text_="$tap_result_ $tap_count_"
141   if test x"$*" != x; then
142     tap_text_="$tap_text_ - $*"
143   fi
144   if test x"$tap_directive_" != x; then
145     tap_text_="$tap_text_ # $tap_directive_"${tap_reason_:+" $tap_reason_"}
146   fi
147   printf '%s\n' "$tap_text_"
148   set -x # Restore shell xtraces.
149 }
150
151 #  Shorthands for common usages of 'result_'.
152 ok_ () { result_ 'ok' ${1+"$@"}; }
153 not_ok_ () { result_ 'not ok' ${1+"$@"}; }
154 skip_ () { result_ 'ok' -D SKIP ${1+"$@"}; }
155
156 # skip_row_ COUNT [-r REASON] [--] [DESCRIPTION...]
157 # -------------------------------------------------
158 # Report a COUNT of skipped test, with the given reason and descriptions
159 # (if any).  Useful to avoid cascade failures in case a fair number of
160 # tests depend on an earlier one that failed.
161 skip_row_ ()
162 {
163   skip_count_=$1; shift
164   for i_ in $(seq_ $skip_count_); do skip_ ${1+"$@"}; done
165 }
166
167 # skip_all_ [REASON ...]
168 # ----------------------
169 # Skip all the tests in a test script.  Must be used before calling 'plan_'
170 # or reporting any test result.  Can't be used from within a subshell.
171 skip_all_ ()
172 {
173   echo "1..0 # SKIP" ${1+"$@"}
174   planned_=0
175   exit 0
176 }
177
178 # bailout_ [REASON ...]
179 # ---------------------
180 # Stop the execution of the current test suite right now, due to an
181 # unrecoverable error.  Can be called at any point, but cannot be used
182 # from within a subshell.
183 bailout_ ()
184 {
185   echo 'Bail out!' ${1+"$@"}
186   exit 99
187 }
188
189 # fatal_ [REASON ...]
190 # -------------------
191 # Same as 'bailout_'; for compatibility with 'plain-functions.sh'.
192 fatal_ ()
193 {
194   bailout_ ${1+"$@"}
195 }
196
197 # framework_failure_ [REASON ...]
198 # -------------------------------
199 # Stop the execution of the current test suite right now, due to an
200 # unrecoverable error in the set-up of the test case.  Can be called
201 # at any point, but cannot be used from within a subshell.
202 framework_failure_ ()
203 {
204   bailout_ "set-up failure"${1+": $*"}
205 }
206
207 # command_ok_ TEST-DESCRIPTION [OPTIONS..] [--] CMD [ARGS...]
208 # -----------------------------------------------------------
209 # Helper subroutine for when a TAP result must be determined by the
210 # outcome of a command.
211 command_ok_ ()
212 {
213   tap_directive_= tap_reason_=
214   test $# -gt 0 || bailout_ "command_ok_: missing argument"
215   tap_description_=$1; shift
216   while test $# -gt 0; do
217     case $1 in
218       -D|--directive) tap_directive_=$2; shift;;
219       -r|--reason) tap_reason_=$2; shift;;
220       --) shift; break;;
221       -*) bailout_ "command_ok_: invalid option '$1'";;
222        *) break;;
223     esac
224     shift
225   done
226   tap_result_="ok"; "$@" || tap_result_="not ok"
227   result_ "$tap_result_" -D "$tap_directive_" -r "$tap_reason_" \
228           -- "$tap_description_"
229 }
230
231 :