tests: rename 'tests/' => 't/', '*.test' => '*.sh'
[platform/upstream/automake.git] / t / ax / tap-functions.sh
1 # -*- shell-script -*-
2 #
3 # Copyright (C) 2011-2012 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 # The first "test -n" tries to avoid extra forks when possible.
35 if test -n "${ZSH_VERSION}${BASH_VERSION}" \
36      || (eval 'test $((1 + 1)) = 2') >/dev/null 2>&1
37 then
38   # Outer use of 'eval' needed to protect dumber shells from parsing
39   # errors.
40   eval 'incr_ () { eval "$1=\$((\${$1} + 1))"; }'
41 else
42   incr_ () { eval "$1=\`expr \${$1} + 1\`"; }
43 fi
44
45 # not COMMAND [ARGS...]
46 # ---------------------
47 # Run the given command and invert its exit status.
48 not ()
49 {
50   if "$@"; then return 1; else return 0; fi
51 }
52
53 # plan_ [unknown|later|lazy|now|NUMBER-OF-PLANNED-TESTS]
54 # ------------------------------------------------------
55 # Print a TAP plan for the given number of tests.  This must be called
56 # before reporting any test result.  If called with the special argument
57 # "unknown" or "later", it will do nothing, expecting the calling script
58 # to declare the plan later.  If called with the special argument "lazy"
59 # or "now", it will print a TAP plan that accounts for the number of tests
60 # seen so far.
61 plan_ ()
62 {
63   if test $# -eq 0; then
64     bailout_ "plan_: missing argument"
65   elif test $# -ge 2; then
66     bailout_ "plan_: too many arguments"
67   elif test x"$planned_" != x"none" && test x"$planned_" != x"later"; then
68     bailout_ "plan_: called to many times"
69   elif test x"$1" = x"unknown" || test x"$1" = x"later"; then
70     # This means we want to get back later to declaring the TAP plan.
71     planned_=later
72     return 0
73   elif test x"$1" = x"lazy" || test x"$1" = x"now"; then
74     planned_=$tap_count_ # Number of test results seen so far.
75   elif test $1 -ge 0; then
76     planned_=$1
77   else
78     bailout_ "plan_: invalid argument '$1'"
79   fi
80   echo "1..$planned_"
81 }
82 planned_=none
83
84 # diag_ [EXPLANATION]
85 # ------------------
86 # Report the given text as TAP diagnostic.  Assumes the string denoting
87 # TAP diagnostic lines is stored in the '$diag_string_' variable; this is
88 # done to allow better interplay with TAP drivers that allow such a string
89 # to be configured.
90 diag_ ()
91 {
92   test $# -eq 0 || echo "$diag_string_ $*"
93 }
94
95 # Used by the 'diag_' function above.  User-overridable.
96 diag_string_="#"
97
98 # warn_ [EXPLANATION]
99 # ------------------
100 # Give a warning (using TAP diagnostic).
101 warn_ ()
102 {
103   case $# in
104     0) diag_ "WARNING: (unknown warning)";;
105     *) diag_ "WARNING: $*";;
106   esac
107 }
108
109 # result_ RESULT [-D DIRECTIVE] [-r REASON] [--] [DESCRIPTION...]
110 # ---------------------------------------------------------------
111 # Report a test case with the given RESULT (valid values are "ok" and
112 # "not ok") and the given DESCRIPTION (if any).  If DIRECTIVE is given
113 # and non-empty (valid values being "TODO" and "SKIP"), it will be
114 # reported too, with the REASON (if given) appended.
115 result_ ()
116 {
117   set +x # Don't pollute the log files.
118   test $# -gt 0 || bailout_ "result_: missing argument"
119   tap_result_=$1; shift
120   case $tap_result_ in
121     "ok"|"not ok") ;;
122     *) bailout_ "result_: invalid result '$tap_result'" ;;
123   esac
124   tap_directive_= tap_reason_=
125   while test $# -gt 0; do
126     case $1 in
127       -D|--directive) tap_directive_=$2; shift;;
128       -r|--reason) tap_reason_=$2; shift;;
129       --) shift; break;;
130       -*) bailout_ "result_: invalid option '$1'";;
131        *) break;;
132     esac
133     shift
134   done
135   case $tap_directive_ in
136     ""|TODO|SKIP) ;;
137     *) bailout_ "result_: invalid directive '$directive_'" ;;
138   esac
139   incr_ tap_count_
140   case $tap_result_,$tap_directive_ in
141     ok,) incr_ tap_pass_count_;;                # Passed.
142     not\ ok,TODO) incr_ tap_xfail_count_;;      # Expected failure.
143     not\ ok,*) incr_ tap_fail_count_ ;;         # Failed.
144     ok,TODO) incr_ tap_xpass_count_ ;;          # Unexpected pass.
145     ok,SKIP) incr_ tap_skip_count_ ;;           # Skipped.
146     *) bailout_ "internal error in 'result_'";; # Can't happen.
147   esac
148   tap_text_="$tap_result_ $tap_count_"
149   if test x"$*" != x; then
150     tap_text_="$tap_text_ - $*"
151   fi
152   if test x"$tap_directive_" != x; then
153     tap_text_="$tap_text_ # $tap_directive_"${tap_reason_:+" $tap_reason_"}
154   fi
155   printf '%s\n' "$tap_text_"
156   set -x # Restore shell xtraces.
157 }
158
159 #  Shorthands for common usages of 'result_'.
160 ok_ () { result_ 'ok' ${1+"$@"}; }
161 not_ok_ () { result_ 'not ok' ${1+"$@"}; }
162 skip_ () { result_ 'ok' -D SKIP ${1+"$@"}; }
163
164 # skip_row_ COUNT [-r REASON] [--] [DESCRIPTION...]
165 # -------------------------------------------------
166 # Report a COUNT of skipped test, with the given reason and descriptions
167 # (if any).  Useful to avoid cascade failures in case a fair number of
168 # tests depend on an earlier one that failed.
169 skip_row_ ()
170 {
171   skip_count_=$1; shift
172   for i_ in `seq_ $skip_count_`; do skip_ ${1+"$@"}; done
173 }
174
175 # skip_all_ [REASON ...]
176 # ----------------------
177 # Skip all the tests in a test script.  Must be used before calling 'plan_'
178 # or reporting any test result.  Can't be used from within a subshell.
179 skip_all_ ()
180 {
181   echo "1..0 # SKIP" ${1+"$@"}
182   planned_=0
183   Exit 0
184 }
185
186 # bailout_ [REASON ...]
187 # ---------------------
188 # Stop the execution of the current test suite right now, due to an
189 # unrecoverable error.  Can be called at any point, but cannot be used
190 # from within a subshell.
191 bailout_ ()
192 {
193   echo 'Bail out!' ${1+"$@"}
194   Exit 99
195 }
196
197 # fatal_ [REASON ...]
198 # -------------------
199 # Same as 'bailout_'; for compatibility with 'plain-functions.sh'.
200 fatal_ ()
201 {
202   bailout_ ${1+"$@"}
203 }
204
205 # framework_failure_ [REASON ...]
206 # -------------------------------
207 # Stop the execution of the current test suite right now, due to an
208 # unrecoverable error in the set-up of the test case.  Can be called
209 # at any point, but cannot be used from within a subshell.
210 framework_failure_ ()
211 {
212   bailout_ "set-up failure"${1+": $*"}
213 }
214
215 # command_ok_ TEST-DESCRIPTION [OPTIONS..] [--] CMD [ARGS...]
216 # -----------------------------------------------------------
217 # Helper subroutine for when a TAP result must be determined by the
218 # outcome of a command.
219 command_ok_ ()
220 {
221   tap_directive_= tap_reason_=
222   test $# -gt 0 || bailout_ "command_ok_: missing argument"
223   tap_description_=$1; shift
224   while test $# -gt 0; do
225     case $1 in
226       -D|--directive) tap_directive_=$2; shift;;
227       -r|--reason) tap_reason_=$2; shift;;
228       --) shift; break;;
229       -*) bailout_ "command_ok_: invalid option '$1'";;
230        *) break;;
231     esac
232     shift
233   done
234   tap_result_="ok"; "$@" || tap_result_="not ok"
235   result_ "$tap_result_" -D "$tap_directive_" -r "$tap_reason_" \
236           -- "$tap_description_"
237 }
238
239 :