paraslash 0.7.3
[paraslash.git] / t / test-lib.sh
1 #!/bin/bash
2
3 # Test suite helper functions, uses ideas and code from git's test-lib.sh,
4 # Copyright (c) 2005 Junio C Hamano. Licensed under the GPL v2, see file
5 # COPYING.
6
7 get_audio_file_paths()
8 {
9         local suffix="$1"
10
11         if (($# == 0)); then
12                 result=$(find "$test_audio_file_dir" -type f)
13         else
14                 result=$(find "$test_audio_file_dir" -type f -name "*.$suffix")
15         fi
16 }
17
18 say_color()
19 {
20         local severity=$1
21
22         shift
23         if [[ "$o_nocolor" != "true" && -n "$1" ]]; then
24                 export TERM=$ORIGINAL_TERM
25                 case "$severity" in
26                         error) tput $C_BOLD; tput $C_SETAF 1;;
27                         skip)  tput $C_SETAF 5;;
28                         ok)
29                                 (($o_verbose == 0)) && return
30                                 tput $C_SETAF 2;;
31                         pass)  tput $C_BOLD; tput $C_SETAF 2;;
32                         info)  tput $C_SETAF 3;;
33                         run)
34                                 (($o_verbose == 0)) && return
35                                 tput $C_SETAF 6;;
36                 esac
37         fi
38         if [[ "$severity" == 'error' ]]; then
39                 printf "%s\n" "$*" 1>&2
40         else
41                 printf "%s\n" "$*"
42         fi
43         if [[ "$o_nocolor" != "true" && -n "$1" ]]; then
44                 tput $C_SGR0
45                 export TERM=dumb
46         fi
47 }
48
49 die()
50 {
51         local code=$?
52         [[ "$exit_ok" == "true" ]] && exit $code
53         say_color error "FATAL: Unexpected exit with code $code"
54         exit 1
55 }
56
57 error()
58 {
59         say_color error "error: $*"
60         exit_ok="true"
61         exit 1
62 }
63
64 say()
65 {
66         say_color info "$*"
67 }
68
69 retval_ok()
70 {
71         local rv="$1" expectation="$2"
72
73         if [[ "$expectation" == "success" ]]; then
74                 (($rv == 0)) && return 0 || return 1
75         fi
76         if (($rv > 129 && $rv <= 192)); then
77                 echo >&2 "died by signal"
78                 return 1
79         fi
80         if (($rv == 127)); then
81                 echo >&2 "command not found"
82                 return 1
83         fi
84         if (($rv == 0)); then
85                 echo >&2 "command was supposed to fail but succeeded"
86                 return 1
87         fi
88         return 0
89 }
90
91 _test_run()
92 {
93         local f expectation="$3" ret
94
95         let test_count++
96         eval >&3 2>&4 "$2"
97         ret=$?
98         if retval_ok "$ret" "$expectation"; then
99                 let test_success++
100                 say_color ok "ok $test_count - $1"
101                 return
102         fi
103         let test_failure++
104         say_color error "not ok - $test_count $1"
105         f="$o_results_dir/${0##*/}-$$.out"
106         if [[ -s "$f" ]]; then
107                 sed -e 's/^/#   /' < "$f"
108         else
109                 sed -e 's/^/#   /' <<< "$2"
110         fi
111         [[ "$o_immediate" != "true" ]] && return
112         exit_ok="true"
113         exit 1
114 }
115
116 test_skip()
117 {
118         (($# != 2)) && error "bug: not 2 parameters to test_skip()"
119         let test_count++
120         let test_skipped++
121         say_color skip >&3 "skipping test $this_test.$test_count ($1): $2"
122         say_color skip "ok $test_count - $1 # skipped ($2)"
123 }
124
125 test_require_objects()
126 {
127         local o1 o2 found
128
129         result=
130         # if no objects were given, we assume this test is run manually
131         # rather than via "make test". We won't check anything in this case
132         [[ -z "$o_objects" ]] && return
133
134         for o1 in $1; do
135                 found=
136                 for o2 in $o_objects; do
137                         [[ "$o1" != "$o2" ]] && continue
138                         found="true"
139                         break
140                 done
141                 [[ "$found" == "true" ]] && continue
142                 [[ -n "$result" ]] && result+=" "
143                 result+="$o1"
144         done
145         [[ -z "$result" ]]
146 }
147
148 test_require_executables()
149 {
150         local i
151
152         result=
153         for i in "$@"; do
154                 [[ -n "$(builtin type -t "$i")" ]] && continue
155                 [[ -n "$result" ]] && result+=" "
156                 result+="$i"
157         done
158         [[ -z "$result" ]]
159 }
160
161 test_duration()
162 {
163         local t=$(exec 2>&1 1>/dev/null; time -p "$@")
164         result=$(awk '{print $2 * 1000; exit 0}' <<< "$t")
165 }
166
167 test_expect_success()
168 {
169         (($# != 2)) && error "bug: not 2 parameters to test_expect_success()"
170         echo >&3 "expecting success: $2"
171         _test_run "$1" "$2" "success"
172         echo >&3 ""
173 }
174
175 test_expect_failure()
176 {
177         (($# != 2)) && error "bug: not 2 parameters to test_expect_failure()"
178         echo >&3 "expecting failure: $2"
179         _test_run "$1" "$2" "failure"
180         echo >&3 ""
181 }
182
183 test_done()
184 {
185         test_results_path="$o_results_dir/${0##*/}-$$.counts"
186         {
187                 echo "total $test_count"
188                 echo "success $test_success"
189                 echo "failed $test_failure"
190                 echo "skipped $test_skipped"
191                 echo
192         } > $test_results_path
193
194         exit_ok="true"
195         msg="$test_count test(s) ($test_skipped test(s) skipped)"
196         if (($test_failure == 0)); then
197                 say_color pass "# ${0##*/}: passed all $msg"
198                 exit 0
199         else
200                 say_color error "# ${0##*/}: failed $test_failure among $msg"
201                 exit 1
202         fi
203 }
204
205 sanitize_environment()
206 {
207         export LANG=C
208         export LC_ALL=C
209         export PAGER=cat
210         export TZ=UTC
211         export TERM=dumb
212         export EDITOR=:
213         export HOME=$(pwd)
214
215         unset VISUAL
216         unset EMAIL
217         unset CDPATH
218         unset GREP_OPTIONS
219 }
220
221 can_use_colors()
222 {
223         result="false"
224         [[ "$TERM" == "dumb" ]] && return
225         [[ -t 1 ]] || return
226         C_BOLD='bold'
227         tput $C_BOLD &>/dev/null || {
228                 C_BOLD='md'
229                 tput $C_BOLD &>/dev/null
230         } || return
231         C_SETAF='setaf'
232         tput $C_SETAF 1 &>/dev/null || {
233                 C_SETAF='AF'
234                 tput $C_SETAF 1 &>/dev/null
235         } || return
236         C_SGR0='sgr0'
237         tput $C_SGR0 >/dev/null 2>&1 || {
238                 C_SGR0='me'
239                 tput $C_SGR0 &>/dev/null
240         } || return
241         result="true"
242 }
243
244 parse_options()
245 {
246         while (($# > 0)); do
247                 case "$1" in
248                 -i|--immediate) o_immediate="true"; shift;;
249                 -l|--long) export o_long="true"; shift;;
250                 -h|--help) o_help="true"; shift;;
251                 -v=0|--verbose=0) o_verbose="0"; shift;;
252                 -v=1|--verbose=1) o_verbose="1"; shift;;
253                 -v|--verbose|-v=2|--verbose=2) o_verbose="2"; shift;;
254                 --no-color) o_nocolor="true"; shift;;
255                 --man-dir) export o_man_dir="$2"; shift; shift;;
256                 --results-dir) o_results_dir="$2"; shift; shift;;
257                 --trash-dir) o_trash_dir="$2"; shift; shift;;
258                 --executables-dir) export o_executables_dir="$2"; shift; shift;;
259                 --executables) export o_executables="$2"; shift; shift;;
260                 --objects) export o_objects="$2"; shift; shift;;
261                 *) echo "error: unknown test option '$1'" >&2; exit 1;;
262                 esac
263         done
264         [[ -z "$o_verbose" ]] && o_verbose=1
265 }
266
267 create_trash_dir_and_cd()
268 {
269         local trash="$o_trash_dir/trash-dir.${0##*/}"
270
271         rm -rf "$trash" || error "could not remove trash dir"
272         mkdir -p "$trash" || error "could not make trash dir"
273         cd "$trash" || error "could not change to trash dir"
274 }
275
276 fixup_dirs()
277 {
278         local wd=$(pwd)
279
280         test_dir="$(realpath $wd/${0%/*})"
281         test_audio_file_dir="$test_dir/audio_files"
282
283         [[ -z "$o_results_dir" ]] && o_results_dir="$test_dir/test-results"
284         [[ -z "$o_executables_dir" ]] && o_executables_dir="$test_dir/.."
285         [[ -z "$o_trash_dir" ]] && o_trash_dir="$test_dir/trashes"
286         [[ -z "$o_man_dir" ]] && o_man_dir="$test_dir/../build/man/man1"
287
288         # we want absolute paths because relative paths become invalid
289         # after changing to the trash dir
290         [[ -n "${o_results_dir##/*}" ]] && o_results_dir="$wd/$o_results_dir"
291         [[ -n "${o_executables_dir##/*}" ]] && o_executables_dir="$wd/$o_results_dir"
292         [[ -n "${o_man_dir##/*}" ]] && o_man_dir="$wd/$o_man_dir"
293         [[ -n "${o_trash_dir##/*}" ]] && o_trash_dir="$wd/$o_trash_dir"
294
295         mkdir -p "$o_results_dir"
296 }
297
298 parse_options "$@"
299 if [[ "$o_nocolor" != "true" ]]; then
300         can_use_colors
301         [[ "$result" != "true" ]] && o_nocolor="true"
302 fi
303
304 # Each test must set test_description
305 [[ -z "${test_description}" ]] && error "${0##*/} did not set test_description"
306 if [[ "$o_help" == "true" ]]; then
307         printf "${0##*/}: "
308         sed -e '1!d' <<< "$test_description"
309         if (($o_verbose >= 2)); then
310                 echo
311                 sed -e '1,2d' -e 's/^/  /g' <<<"$test_description"
312                 echo
313         fi
314         exit 0
315 fi
316 fixup_dirs
317
318 [[ -z "$o_executables" ]] && o_executables="para_afh para_audioc para_audiod
319         para_client para_mixer para_filter para_gui para_recv para_server
320         para_write"
321 for exe in $o_executables; do
322         export $(tr 'a-z' 'A-Z' <<< $exe)="$o_executables_dir/$exe"
323 done
324
325 test_failure=0
326 test_count=0
327 test_success=0
328 test_skipped=0
329
330 ORIGINAL_TERM=$TERM
331 sanitize_environment
332 create_trash_dir_and_cd
333
334 if (($o_verbose >= 2)); then
335         exec 4>&2 3>&1
336 else
337         exec 4>$o_results_dir/${0##*/}-$$.out 3>&4
338 fi
339
340 exit_ok=
341 trap 'die' EXIT
342
343 say_color run "# running ${0##*/}"