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