6 | 6 |
# GitHub: https://github.com/aureliojargas/clitest
|
7 | 7 |
#
|
8 | 8 |
# POSIX shell script:
|
9 | |
# This script was coded to be compatible with POSIX shells.
|
10 | |
# Tested in Bash 3.2, dash 0.5.5.1, ksh 93u 2011-02-08.
|
11 | |
# Note: Can't set -o posix nor POSIXLY_CORRECT: test env must be intact.
|
|
9 |
# This script is carefully coded to be compatible with POSIX shells.
|
|
10 |
# It is currently tested in bash, dash, ksh, zsh and busybox's sh.
|
12 | 11 |
#
|
13 | 12 |
# Exit codes:
|
14 | 13 |
# 0 All tests passed, or normal operation (--help, --list, ...)
|
|
18 | 17 |
# Test environment:
|
19 | 18 |
# By default, the tests will run in the current working directory ($PWD).
|
20 | 19 |
# You can change to another dir normally using 'cd' inside the test file.
|
21 | |
# All the tests are executed in the same shell, using eval. Test data
|
22 | |
# such as variables and working directory will persist between tests.
|
|
20 |
# All the tests are executed in the same shell session, using eval. Test
|
|
21 |
# data such as variables and working directory will persist between tests.
|
23 | 22 |
#
|
24 | 23 |
# Namespace:
|
25 | 24 |
# All variables and functions in this script are prefixed by 'tt_' to
|
26 | 25 |
# avoid clashing with test's variables, functions, aliases and commands.
|
27 | 26 |
|
28 | 27 |
tt_my_name="$(basename "$0")"
|
29 | |
tt_my_version='HEAD'
|
30 | |
tt_my_version_url="https://github.com/aureliojargas/clitest/tree/$tt_my_version"
|
|
28 |
tt_my_url='https://github.com/aureliojargas/clitest'
|
|
29 |
tt_my_version='0.4.0'
|
31 | 30 |
|
32 | 31 |
# Customization (if needed, edit here or use the command line options)
|
33 | 32 |
tt_prefix=''
|
|
59 | 58 |
--diff-options OPTIONS Set diff command options (default: '$tt_diff_options')
|
60 | 59 |
--inline-prefix PREFIX Set inline output prefix (default: '$tt_inline_prefix')
|
61 | 60 |
--prefix PREFIX Set command line prefix (default: '$tt_prefix')
|
62 | |
--prompt STRING Set prompt string (default: '$tt_prompt')"
|
|
61 |
--prompt STRING Set prompt string (default: '$tt_prompt')
|
|
62 |
|
|
63 |
See also: $tt_my_url"
|
63 | 64 |
|
64 | 65 |
# Flags (0=off, 1=on), most can be altered by command line options
|
65 | 66 |
tt_debug=0
|
|
108 | 109 |
tt_nl='
|
109 | 110 |
'
|
110 | 111 |
|
111 | |
|
112 | 112 |
### Utilities
|
113 | 113 |
|
114 | |
tt_clean_up ()
|
115 | |
{
|
|
114 |
tt_clean_up() {
|
116 | 115 |
rm -rf "$tt_temp_dir"
|
117 | 116 |
}
|
118 | |
tt_message ()
|
119 | |
{
|
|
117 |
tt_message() {
|
120 | 118 |
test "$tt_output_mode" = 'quiet' && return 0
|
121 | 119 |
test $tt_missing_nl -eq 1 && echo
|
122 | 120 |
printf '%s\n' "$*"
|
123 | 121 |
tt_separator_line_shown=0
|
124 | 122 |
tt_missing_nl=0
|
125 | 123 |
}
|
126 | |
tt_message_part () # no line break
|
127 | |
{
|
|
124 |
tt_message_part() { # no line break
|
128 | 125 |
test "$tt_output_mode" = 'quiet' && return 0
|
129 | 126 |
printf '%s' "$*"
|
130 | 127 |
tt_separator_line_shown=0
|
131 | 128 |
tt_missing_nl=1
|
132 | 129 |
}
|
133 | |
tt_error ()
|
134 | |
{
|
|
130 |
tt_error() {
|
135 | 131 |
test $tt_missing_nl -eq 1 && echo
|
136 | 132 |
printf '%s\n' "$tt_my_name: Error: $1" >&2
|
137 | 133 |
tt_clean_up
|
138 | 134 |
exit 2
|
139 | 135 |
}
|
140 | |
tt_debug () # $1=id, $2=contents
|
141 | |
{
|
|
136 |
tt_debug() { # $1=id, $2=contents
|
142 | 137 |
test $tt_debug -ne 1 && return 0
|
143 | |
if test INPUT_LINE = "$1"
|
144 | |
then
|
|
138 |
if test INPUT_LINE = "$1"; then
|
145 | 139 |
# Original input line is all blue
|
146 | 140 |
printf "${tt_color_blue}[%10s: %s]${tt_color_off}\n" "$1" "$2"
|
147 | 141 |
else
|
|
151 | 145 |
sed "s/$tt_tab/${tt_color_green}<tab>${tt_color_off}/g"
|
152 | 146 |
fi
|
153 | 147 |
}
|
154 | |
tt_separator_line ()
|
155 | |
{
|
|
148 |
tt_separator_line() {
|
156 | 149 |
printf "%${COLUMNS}s" ' ' | tr ' ' -
|
157 | 150 |
}
|
158 | |
tt_list_test () # $1=normal|list|ok|fail
|
159 | |
{
|
|
151 |
tt_list_test() { # $1=normal|list|ok|fail
|
160 | 152 |
# Show the test command in normal mode, --list and --list-run
|
161 | 153 |
case "$1" in
|
162 | 154 |
normal | list)
|
163 | 155 |
# Normal line, no color, no stamp (--list)
|
164 | 156 |
tt_message "#${tt_test_number}${tt_tab}${tt_test_command}"
|
165 | |
;;
|
|
157 |
;;
|
166 | 158 |
ok)
|
167 | 159 |
# Green line or OK stamp (--list-run)
|
168 | |
if test $tt_use_colors -eq 1
|
169 | |
then
|
|
160 |
if test $tt_use_colors -eq 1; then
|
170 | 161 |
tt_message "${tt_color_green}#${tt_test_number}${tt_tab}${tt_test_command}${tt_color_off}"
|
171 | 162 |
else
|
172 | 163 |
tt_message "#${tt_test_number}${tt_tab}OK${tt_tab}${tt_test_command}"
|
173 | 164 |
fi
|
174 | |
;;
|
|
165 |
;;
|
175 | 166 |
fail)
|
176 | 167 |
# Red line or FAIL stamp (--list-run)
|
177 | |
if test $tt_use_colors -eq 1
|
178 | |
then
|
|
168 |
if test $tt_use_colors -eq 1; then
|
179 | 169 |
tt_message "${tt_color_red}#${tt_test_number}${tt_tab}${tt_test_command}${tt_color_off}"
|
180 | 170 |
else
|
181 | 171 |
tt_message "#${tt_test_number}${tt_tab}FAIL${tt_tab}${tt_test_command}"
|
182 | 172 |
fi
|
183 | |
;;
|
|
173 |
;;
|
184 | 174 |
esac
|
185 | 175 |
}
|
186 | |
tt_parse_range () # $1=range
|
187 | |
{
|
|
176 |
tt_parse_range() { # $1=range
|
188 | 177 |
# Parse numeric ranges and output them in an expanded format
|
189 | 178 |
#
|
190 | 179 |
# Supported formats Expanded
|
|
198 | 187 |
# Later we will just grep for :number: in each test.
|
199 | 188 |
|
200 | 189 |
case "$1" in
|
201 | |
# No range, nothing to do
|
202 | 190 |
0 | '')
|
|
191 |
# No range, nothing to do
|
203 | 192 |
return 0
|
204 | |
;;
|
205 | |
# Error: strange chars, not 0123456789,-
|
|
193 |
;;
|
206 | 194 |
*[!0-9,-]*)
|
|
195 |
# Error: strange chars, not 0123456789,-
|
207 | 196 |
return 1
|
208 | |
;;
|
|
197 |
;;
|
209 | 198 |
esac
|
210 | 199 |
|
211 | 200 |
# OK, all valid chars in range, let's parse them
|
|
213 | 202 |
tt_part=
|
214 | 203 |
tt_n1=
|
215 | 204 |
tt_n2=
|
216 | |
tt_operation=
|
|
205 |
tt_swap=
|
217 | 206 |
tt_range_data=':' # :1:2:4:7:
|
218 | 207 |
|
219 | 208 |
# Loop each component: a number or a range
|
220 | |
for tt_part in $(echo "$1" | tr , ' ')
|
221 | |
do
|
|
209 |
for tt_part in $(echo "$1" | tr , ' '); do
|
222 | 210 |
# If there's an hyphen, it's a range
|
223 | 211 |
case "$tt_part" in
|
224 | 212 |
*-*)
|
|
228 | 216 |
tt_n1=${tt_part%-*}
|
229 | 217 |
tt_n2=${tt_part#*-}
|
230 | 218 |
|
231 | |
tt_operation='+'
|
232 | |
test $tt_n1 -gt $tt_n2 && tt_operation='-'
|
|
219 |
# Negative range, let's just reverse it (5-1 => 1-5)
|
|
220 |
if test "$tt_n1" -gt "$tt_n2"; then
|
|
221 |
tt_swap=$tt_n1
|
|
222 |
tt_n1=$tt_n2
|
|
223 |
tt_n2=$tt_swap
|
|
224 |
fi
|
233 | 225 |
|
234 | 226 |
# Expand the range (1-4 => 1:2:3:4)
|
235 | 227 |
tt_part=$tt_n1:
|
236 | |
while test $tt_n1 -ne $tt_n2
|
237 | |
do
|
238 | |
tt_n1=$(($tt_n1 $tt_operation 1))
|
|
228 |
while test "$tt_n1" -ne "$tt_n2"; do
|
|
229 |
tt_n1=$((tt_n1 + 1))
|
239 | 230 |
tt_part=$tt_part$tt_n1:
|
240 | 231 |
done
|
241 | 232 |
tt_part=${tt_part%:}
|
242 | |
;;
|
|
233 |
;;
|
243 | 234 |
esac
|
244 | 235 |
|
245 | 236 |
# Append the number or expanded range to the holder
|
246 | |
test $tt_part != 0 && tt_range_data=$tt_range_data$tt_part:
|
|
237 |
test "$tt_part" != 0 && tt_range_data=$tt_range_data$tt_part:
|
247 | 238 |
done
|
248 | 239 |
|
249 | |
test $tt_range_data != ':' && echo $tt_range_data
|
|
240 |
test "$tt_range_data" != ':' && echo "$tt_range_data"
|
250 | 241 |
return 0
|
251 | 242 |
}
|
252 | |
tt_reset_test_data ()
|
253 | |
{
|
|
243 |
tt_reset_test_data() {
|
254 | 244 |
tt_test_command=
|
255 | 245 |
tt_test_inline=
|
256 | 246 |
tt_test_mode=
|
|
259 | 249 |
tt_test_diff=
|
260 | 250 |
tt_test_ok_text=
|
261 | 251 |
}
|
262 | |
tt_run_test ()
|
263 | |
{
|
264 | |
tt_test_number=$(($tt_test_number + 1))
|
265 | |
tt_nr_total_tests=$(($tt_nr_total_tests + 1))
|
266 | |
tt_nr_file_tests=$(($tt_nr_file_tests + 1))
|
|
252 |
tt_run_test() {
|
|
253 |
tt_test_number=$((tt_test_number + 1))
|
|
254 |
tt_nr_total_tests=$((tt_nr_total_tests + 1))
|
|
255 |
tt_nr_file_tests=$((tt_nr_file_tests + 1))
|
267 | 256 |
|
268 | 257 |
# Run range on: skip this test if it's not listed in $tt_run_range_data
|
269 | |
if test -n "$tt_run_range_data" && test "$tt_run_range_data" = "${tt_run_range_data#*:$tt_test_number:}"
|
270 | |
then
|
271 | |
tt_nr_total_skips=$(($tt_nr_total_skips + 1))
|
272 | |
tt_nr_file_skips=$(($tt_nr_file_skips + 1))
|
|
258 |
if test -n "$tt_run_range_data" && test "$tt_run_range_data" = "${tt_run_range_data#*:$tt_test_number:}"; then
|
|
259 |
tt_nr_total_skips=$((tt_nr_total_skips + 1))
|
|
260 |
tt_nr_file_skips=$((tt_nr_file_skips + 1))
|
273 | 261 |
tt_reset_test_data
|
274 | 262 |
return 0
|
275 | 263 |
fi
|
276 | 264 |
|
277 | 265 |
# Skip range on: skip this test if it's listed in $tt_skip_range_data
|
278 | 266 |
# Note: --skip always wins over --test, regardless of order
|
279 | |
if test -n "$tt_skip_range_data" && test "$tt_skip_range_data" != "${tt_skip_range_data#*:$tt_test_number:}"
|
280 | |
then
|
281 | |
tt_nr_total_skips=$(($tt_nr_total_skips + 1))
|
282 | |
tt_nr_file_skips=$(($tt_nr_file_skips + 1))
|
|
267 |
if test -n "$tt_skip_range_data" && test "$tt_skip_range_data" != "${tt_skip_range_data#*:$tt_test_number:}"; then
|
|
268 |
tt_nr_total_skips=$((tt_nr_total_skips + 1))
|
|
269 |
tt_nr_file_skips=$((tt_nr_file_skips + 1))
|
283 | 270 |
tt_reset_test_data
|
284 | 271 |
return 0
|
285 | 272 |
fi
|
|
290 | 277 |
case "$tt_progress" in
|
291 | 278 |
test)
|
292 | 279 |
tt_list_test normal
|
293 | |
;;
|
|
280 |
;;
|
294 | 281 |
number)
|
295 | 282 |
tt_message_part "$tt_test_number "
|
296 | |
;;
|
|
283 |
;;
|
297 | 284 |
none)
|
298 | 285 |
:
|
299 | |
;;
|
|
286 |
;;
|
300 | 287 |
*)
|
301 | 288 |
tt_message_part "$tt_progress"
|
302 | |
;;
|
|
289 |
;;
|
303 | 290 |
esac
|
304 | |
;;
|
|
291 |
;;
|
305 | 292 |
list)
|
306 | 293 |
# List mode: just show the command and return (no execution)
|
307 | 294 |
tt_list_test list
|
308 | 295 |
tt_reset_test_data
|
309 | 296 |
return 0
|
310 | |
;;
|
|
297 |
;;
|
311 | 298 |
esac
|
312 | 299 |
|
313 | 300 |
#tt_debug EVAL "$tt_test_command"
|
|
324 | 311 |
printf %s "$tt_test_ok_text" > "$tt_test_ok_file"
|
325 | 312 |
tt_test_diff=$(diff $tt_diff_options "$tt_test_ok_file" "$tt_test_output_file")
|
326 | 313 |
tt_test_status=$?
|
327 | |
;;
|
|
314 |
;;
|
328 | 315 |
text)
|
329 | 316 |
# Inline OK text represents a full line, with \n
|
330 | 317 |
printf '%s\n' "$tt_test_inline" > "$tt_test_ok_file"
|
331 | 318 |
tt_test_diff=$(diff $tt_diff_options "$tt_test_ok_file" "$tt_test_output_file")
|
332 | 319 |
tt_test_status=$?
|
333 | |
;;
|
|
320 |
;;
|
334 | 321 |
eval)
|
335 | 322 |
eval "$tt_test_inline" > "$tt_test_ok_file"
|
336 | 323 |
tt_test_diff=$(diff $tt_diff_options "$tt_test_ok_file" "$tt_test_output_file")
|
337 | 324 |
tt_test_status=$?
|
338 | |
;;
|
|
325 |
;;
|
339 | 326 |
lines)
|
340 | 327 |
tt_test_output=$(sed -n '$=' "$tt_test_output_file")
|
341 | 328 |
test -z "$tt_test_output" && tt_test_output=0
|
342 | 329 |
test "$tt_test_output" -eq "$tt_test_inline"
|
343 | 330 |
tt_test_status=$?
|
344 | 331 |
tt_test_diff="Expected $tt_test_inline lines, got $tt_test_output."
|
345 | |
;;
|
|
332 |
;;
|
346 | 333 |
file)
|
347 | 334 |
# If path is relative, make it relative to the test file path, not $PWD
|
348 | |
if test $tt_test_inline = ${tt_test_inline#/}
|
349 | |
then
|
|
335 |
if test "$tt_test_inline" = "${tt_test_inline#/}"; then
|
350 | 336 |
tt_test_inline="$(dirname "$tt_test_file")/$tt_test_inline"
|
351 | 337 |
fi
|
352 | 338 |
# Abort when ok file not found/readable
|
353 | |
if test ! -f "$tt_test_inline" || test ! -r "$tt_test_inline"
|
354 | |
then
|
|
339 |
if test ! -f "$tt_test_inline" || test ! -r "$tt_test_inline"; then
|
355 | 340 |
tt_error "cannot read inline output file '$tt_test_inline', from line $tt_line_number of $tt_test_file"
|
356 | 341 |
fi
|
357 | 342 |
|
358 | 343 |
tt_test_diff=$(diff $tt_diff_options "$tt_test_inline" "$tt_test_output_file")
|
359 | 344 |
tt_test_status=$?
|
360 | |
;;
|
|
345 |
;;
|
361 | 346 |
egrep)
|
362 | |
egrep "$tt_test_inline" "$tt_test_output_file" > /dev/null
|
|
347 |
grep -E "$tt_test_inline" "$tt_test_output_file" > /dev/null
|
363 | 348 |
tt_test_status=$?
|
364 | 349 |
|
365 | 350 |
# Test failed: the regex not matched
|
366 | |
if test $tt_test_status -eq 1
|
367 | |
then
|
|
351 |
if test $tt_test_status -eq 1; then
|
368 | 352 |
tt_test_diff="egrep '$tt_test_inline' failed in:$tt_nl$(cat "$tt_test_output_file")"
|
369 | 353 |
|
370 | 354 |
# Regex errors are common and user must take action to fix them
|
371 | |
elif test $tt_test_status -gt 1
|
372 | |
then
|
|
355 |
elif test $tt_test_status -gt 1; then
|
373 | 356 |
tt_error "check your inline egrep regex at line $tt_line_number of $tt_test_file"
|
374 | 357 |
fi
|
375 | |
;;
|
|
358 |
;;
|
376 | 359 |
perl | regex)
|
377 | 360 |
# Escape regex delimiter (if any) inside the regex: ' => \'
|
378 | |
if test "$tt_test_inline" != "${tt_test_inline#*\'}"
|
379 | |
then
|
|
361 |
if test "$tt_test_inline" != "${tt_test_inline#*\'}"; then
|
380 | 362 |
tt_test_inline=$(printf %s "$tt_test_inline" | sed "s/'/\\\\'/g")
|
381 | 363 |
fi
|
382 | 364 |
|
|
387 | 369 |
case $tt_test_status in
|
388 | 370 |
0) # Test matched, nothing to do
|
389 | 371 |
:
|
390 | |
;;
|
|
372 |
;;
|
391 | 373 |
1) # Test failed: the regex not matched
|
392 | 374 |
tt_test_diff="Perl regex '$tt_test_inline' not matched in:$tt_nl$(cat "$tt_test_output_file")"
|
393 | |
;;
|
|
375 |
;;
|
394 | 376 |
127) # Perl not found :(
|
395 | 377 |
tt_error "Perl not found. It's needed by --$tt_test_mode at line $tt_line_number of $tt_test_file"
|
396 | |
;;
|
|
378 |
;;
|
397 | 379 |
255) # Regex syntax errors are common and user must take action to fix them
|
398 | 380 |
tt_error "check your inline Perl regex at line $tt_line_number of $tt_test_file"
|
399 | |
;;
|
|
381 |
;;
|
400 | 382 |
*)
|
401 | 383 |
tt_error "unknown error when running Perl for --$tt_test_mode at line $tt_line_number of $tt_test_file"
|
402 | |
;;
|
|
384 |
;;
|
403 | 385 |
esac
|
404 | |
;;
|
|
386 |
;;
|
405 | 387 |
exit)
|
406 | 388 |
test "$tt_test_exit_code" -eq "$tt_test_inline"
|
407 | 389 |
tt_test_status=$?
|
408 | 390 |
tt_test_diff="Expected exit code $tt_test_inline, got $tt_test_exit_code"
|
409 | |
;;
|
|
391 |
;;
|
410 | 392 |
*)
|
411 | 393 |
tt_error "unknown test mode '$tt_test_mode'"
|
412 | |
;;
|
|
394 |
;;
|
413 | 395 |
esac
|
414 | 396 |
|
415 | 397 |
# Test failed :(
|
416 | |
if test $tt_test_status -ne 0
|
417 | |
then
|
418 | |
tt_nr_file_fails=$(($tt_nr_file_fails + 1))
|
419 | |
tt_nr_total_fails=$(($tt_nr_total_fails + 1))
|
|
398 |
if test $tt_test_status -ne 0; then
|
|
399 |
tt_nr_file_fails=$((tt_nr_file_fails + 1))
|
|
400 |
tt_nr_total_fails=$((tt_nr_total_fails + 1))
|
420 | 401 |
tt_failed_range="$tt_failed_range$tt_test_number,"
|
421 | 402 |
|
422 | 403 |
# Decide the message format
|
423 | |
if test "$tt_output_mode" = 'list-run'
|
424 | |
then
|
|
404 |
if test "$tt_output_mode" = 'list-run'; then
|
425 | 405 |
# List mode
|
426 | 406 |
tt_list_test fail
|
427 | 407 |
else
|
428 | 408 |
# Normal mode: show FAILED message and the diff
|
429 | |
if test $tt_separator_line_shown -eq 0 # avoid dups
|
430 | |
then
|
|
409 |
if test $tt_separator_line_shown -eq 0; then # avoid dups
|
431 | 410 |
tt_message "${tt_color_red}$(tt_separator_line)${tt_color_off}"
|
432 | 411 |
fi
|
433 | 412 |
tt_message "${tt_color_red}[FAILED #$tt_test_number, line $tt_test_line_number] $tt_test_command${tt_color_off}"
|
|
437 | 416 |
fi
|
438 | 417 |
|
439 | 418 |
# Should I abort now?
|
440 | |
if test $tt_stop_on_first_fail -eq 1
|
441 | |
then
|
|
419 |
if test $tt_stop_on_first_fail -eq 1; then
|
442 | 420 |
tt_clean_up
|
443 | 421 |
exit 1
|
444 | 422 |
fi
|
|
450 | 428 |
|
451 | 429 |
tt_reset_test_data
|
452 | 430 |
}
|
453 | |
tt_process_test_file ()
|
454 | |
{
|
|
431 |
tt_process_test_file() {
|
455 | 432 |
# Reset counters
|
456 | 433 |
tt_nr_file_tests=0
|
457 | 434 |
tt_nr_file_fails=0
|
|
462 | 439 |
# Loop for each line of input file
|
463 | 440 |
# Note: changing IFS to avoid right-trimming of spaces/tabs
|
464 | 441 |
# Note: read -r to preserve the backslashes
|
465 | |
while IFS='' read -r tt_input_line || test -n "$tt_input_line"
|
466 | |
do
|
467 | |
tt_line_number=$(($tt_line_number + 1))
|
|
442 |
while IFS='' read -r tt_input_line || test -n "$tt_input_line"; do
|
|
443 |
tt_line_number=$((tt_line_number + 1))
|
468 | 444 |
#tt_debug INPUT_LINE "$tt_input_line"
|
469 | 445 |
|
470 | 446 |
case "$tt_input_line" in
|
471 | 447 |
|
472 | |
# Prompt alone: closes previous command line (if any)
|
473 | 448 |
"$tt_prefix$tt_prompt" | "$tt_prefix${tt_prompt% }" | "$tt_prefix$tt_prompt ")
|
|
449 |
# Prompt alone: closes previous command line (if any)
|
|
450 |
|
474 | 451 |
#tt_debug 'LINE_$' "$tt_input_line"
|
475 | 452 |
|
476 | 453 |
# Run pending tests
|
477 | 454 |
test -n "$tt_test_command" && tt_run_test
|
478 | |
;;
|
479 | |
|
480 | |
# This line is a command line to be tested
|
|
455 |
;;
|
|
456 |
|
481 | 457 |
"$tt_prefix$tt_prompt"*)
|
|
458 |
# This line is a command line to be tested
|
|
459 |
|
482 | 460 |
#tt_debug LINE_CMD "$tt_input_line"
|
483 | 461 |
|
484 | 462 |
# Run pending tests
|
|
491 | 469 |
tt_test_line_number=$tt_line_number
|
492 | 470 |
|
493 | 471 |
# This is a special test with inline output?
|
494 | |
if printf '%s\n' "$tt_test_command" | grep "$tt_inline_prefix" > /dev/null
|
495 | |
then
|
|
472 |
if printf '%s\n' "$tt_test_command" | grep "$tt_inline_prefix" > /dev/null; then
|
496 | 473 |
# Separate command from inline output
|
497 | 474 |
tt_test_command="${tt_test_command%"$tt_inline_prefix"*}"
|
498 | 475 |
tt_test_inline="${tt_input_line##*"$tt_inline_prefix"}"
|
|
505 | 482 |
'--egrep '*)
|
506 | 483 |
tt_test_inline=${tt_test_inline#--egrep }
|
507 | 484 |
tt_test_mode='egrep'
|
508 | |
;;
|
|
485 |
;;
|
509 | 486 |
'--regex '*) # alias to --perl
|
510 | 487 |
tt_test_inline=${tt_test_inline#--regex }
|
511 | 488 |
tt_test_mode='regex'
|
512 | |
;;
|
|
489 |
;;
|
513 | 490 |
'--perl '*)
|
514 | 491 |
tt_test_inline=${tt_test_inline#--perl }
|
515 | 492 |
tt_test_mode='perl'
|
516 | |
;;
|
|
493 |
;;
|
517 | 494 |
'--file '*)
|
518 | 495 |
tt_test_inline=${tt_test_inline#--file }
|
519 | 496 |
tt_test_mode='file'
|
520 | |
;;
|
|
497 |
;;
|
521 | 498 |
'--lines '*)
|
522 | 499 |
tt_test_inline=${tt_test_inline#--lines }
|
523 | 500 |
tt_test_mode='lines'
|
524 | |
;;
|
|
501 |
;;
|
525 | 502 |
'--exit '*)
|
526 | 503 |
tt_test_inline=${tt_test_inline#--exit }
|
527 | 504 |
tt_test_mode='exit'
|
528 | |
;;
|
|
505 |
;;
|
529 | 506 |
'--eval '*)
|
530 | 507 |
tt_test_inline=${tt_test_inline#--eval }
|
531 | 508 |
tt_test_mode='eval'
|
532 | |
;;
|
|
509 |
;;
|
533 | 510 |
'--text '*)
|
534 | 511 |
tt_test_inline=${tt_test_inline#--text }
|
535 | 512 |
tt_test_mode='text'
|
536 | |
;;
|
|
513 |
;;
|
537 | 514 |
*)
|
538 | 515 |
tt_test_mode='text'
|
539 | |
;;
|
|
516 |
;;
|
540 | 517 |
esac
|
541 | 518 |
|
542 | 519 |
#tt_debug OK_TEXT "$tt_test_inline"
|
543 | 520 |
|
544 | 521 |
# There must be a number in --lines and --exit
|
545 | |
if test "$tt_test_mode" = 'lines' || test "$tt_test_mode" = 'exit'
|
546 | |
then
|
|
522 |
if test "$tt_test_mode" = 'lines' || test "$tt_test_mode" = 'exit'; then
|
547 | 523 |
case "$tt_test_inline" in
|
548 | 524 |
'' | *[!0-9]*)
|
549 | 525 |
tt_error "--$tt_test_mode requires a number. See line $tt_line_number of $tt_test_file"
|
550 | |
;;
|
|
526 |
;;
|
551 | 527 |
esac
|
552 | 528 |
fi
|
553 | 529 |
|
554 | 530 |
# An empty inline parameter is an error user must see
|
555 | |
if test -z "$tt_test_inline" && test "$tt_test_mode" != 'text'
|
556 | |
then
|
|
531 |
if test -z "$tt_test_inline" && test "$tt_test_mode" != 'text'; then
|
557 | 532 |
tt_error "empty --$tt_test_mode at line $tt_line_number of $tt_test_file"
|
558 | 533 |
fi
|
559 | 534 |
|
|
565 | 540 |
|
566 | 541 |
#tt_debug NEW_CMD "$tt_test_command"
|
567 | 542 |
fi
|
568 | |
;;
|
569 | |
|
570 | |
# Test output, blank line or comment
|
|
543 |
;;
|
|
544 |
|
571 | 545 |
*)
|
|
546 |
# Test output, blank line or comment
|
|
547 |
|
572 | 548 |
#tt_debug 'LINE_*' "$tt_input_line"
|
573 | 549 |
|
574 | 550 |
# Ignore this line if there's no pending test
|
575 | 551 |
test -n "$tt_test_command" || continue
|
576 | 552 |
|
577 | 553 |
# Required prefix is missing: we just left a command block
|
578 | |
if test -n "$tt_prefix" && test "${tt_input_line#"$tt_prefix"}" = "$tt_input_line"
|
579 | |
then
|
|
554 |
if test -n "$tt_prefix" && test "${tt_input_line#"$tt_prefix"}" = "$tt_input_line"; then
|
580 | 555 |
#tt_debug BLOCK_OUT "$tt_input_line"
|
581 | 556 |
|
582 | 557 |
# Run the pending test and we're done in this line
|
|
588 | 563 |
tt_test_ok_text="$tt_test_ok_text${tt_input_line#"$tt_prefix"}$tt_nl"
|
589 | 564 |
|
590 | 565 |
#tt_debug OK_TEXT "${tt_input_line#"$tt_prefix"}"
|
591 | |
;;
|
|
566 |
;;
|
592 | 567 |
esac
|
593 | 568 |
done < "$tt_temp_file"
|
594 | 569 |
|
|
597 | 572 |
# Run pending tests
|
598 | 573 |
test -n "$tt_test_command" && tt_run_test
|
599 | 574 |
}
|
600 | |
tt_make_temp_dir ()
|
601 | |
{
|
|
575 |
tt_make_temp_dir() {
|
602 | 576 |
# Create private temporary dir and sets global $tt_temp_dir.
|
603 | 577 |
# http://mywiki.wooledge.org/BashFAQ/062
|
604 | 578 |
|
|
606 | 580 |
tt_temp_dir=$(mktemp -d "${TMPDIR:-/tmp}/clitest.XXXXXX" 2> /dev/null) && return 0
|
607 | 581 |
|
608 | 582 |
# No mktemp, let's create the dir manually
|
|
583 |
# shellcheck disable=SC2015
|
609 | 584 |
tt_temp_dir="${TMPDIR:-/tmp}/clitest.$(awk 'BEGIN { srand(); print rand() }').$$" &&
|
610 | |
mkdir -m 700 "$tt_temp_dir" || tt_error "cannot create temporary dir: $tt_temp_dir"
|
611 | |
}
|
612 | |
|
|
585 |
mkdir -m 700 "$tt_temp_dir" ||
|
|
586 |
tt_error "cannot create temporary dir: $tt_temp_dir"
|
|
587 |
}
|
613 | 588 |
|
614 | 589 |
### Init process
|
615 | 590 |
|
|
617 | 592 |
tt_temp_dir=
|
618 | 593 |
tt_make_temp_dir # sets global $tt_temp_dir
|
619 | 594 |
tt_temp_file="$tt_temp_dir/temp.txt"
|
|
595 |
tt_stdin_file="$tt_temp_dir/stdin.txt"
|
620 | 596 |
tt_test_ok_file="$tt_temp_dir/ok.txt"
|
621 | 597 |
tt_test_output_file="$tt_temp_dir/output.txt"
|
622 | 598 |
|
623 | 599 |
# Handle command line options
|
624 | |
while test "${1#-}" != "$1"
|
625 | |
do
|
|
600 |
while test "${1#-}" != "$1"; do
|
626 | 601 |
case "$1" in
|
627 | |
-1|--first ) shift; tt_stop_on_first_fail=1 ;;
|
628 | |
-l|--list ) shift; tt_output_mode='list' ;;
|
629 | |
-L|--list-run ) shift; tt_output_mode='list-run' ;;
|
630 | |
-q|--quiet ) shift; tt_output_mode='quiet' ;;
|
631 | |
-t|--test ) shift; tt_run_range="$1"; shift ;;
|
632 | |
-s|--skip ) shift; tt_skip_range="$1"; shift ;;
|
633 | |
--pre-flight ) shift; tt_pre_command="$1"; shift ;;
|
634 | |
--post-flight ) shift; tt_post_command="$1"; shift ;;
|
635 | |
--debug ) shift; tt_debug=1 ;;
|
636 | |
-P|--progress ) shift; tt_progress="$1"; tt_output_mode='normal'; shift ;;
|
637 | |
--color|--colour) shift; tt_color_mode="$1"; shift ;;
|
638 | |
--diff-options ) shift; tt_diff_options="$1"; shift ;;
|
639 | |
--inline-prefix ) shift; tt_inline_prefix="$1"; shift ;;
|
640 | |
--prefix ) shift; tt_prefix="$1"; shift ;;
|
641 | |
--prompt ) shift; tt_prompt="$1"; shift ;;
|
642 | |
-h|--help)
|
|
602 |
-1 | --first)
|
|
603 |
shift
|
|
604 |
tt_stop_on_first_fail=1
|
|
605 |
;;
|
|
606 |
-l | --list)
|
|
607 |
shift
|
|
608 |
tt_output_mode='list'
|
|
609 |
;;
|
|
610 |
-L | --list-run)
|
|
611 |
shift
|
|
612 |
tt_output_mode='list-run'
|
|
613 |
;;
|
|
614 |
-q | --quiet)
|
|
615 |
shift
|
|
616 |
tt_output_mode='quiet'
|
|
617 |
;;
|
|
618 |
-t | --test)
|
|
619 |
shift
|
|
620 |
tt_run_range="$1"
|
|
621 |
shift
|
|
622 |
;;
|
|
623 |
-s | --skip)
|
|
624 |
shift
|
|
625 |
tt_skip_range="$1"
|
|
626 |
shift
|
|
627 |
;;
|
|
628 |
--pre-flight)
|
|
629 |
shift
|
|
630 |
tt_pre_command="$1"
|
|
631 |
shift
|
|
632 |
;;
|
|
633 |
--post-flight)
|
|
634 |
shift
|
|
635 |
tt_post_command="$1"
|
|
636 |
shift
|
|
637 |
;;
|
|
638 |
--debug)
|
|
639 |
shift
|
|
640 |
tt_debug=1
|
|
641 |
;;
|
|
642 |
-P | --progress)
|
|
643 |
shift
|
|
644 |
tt_progress="$1"
|
|
645 |
tt_output_mode='normal'
|
|
646 |
shift
|
|
647 |
;;
|
|
648 |
--color | --colour)
|
|
649 |
shift
|
|
650 |
tt_color_mode="$1"
|
|
651 |
shift
|
|
652 |
;;
|
|
653 |
--diff-options)
|
|
654 |
shift
|
|
655 |
tt_diff_options="$1"
|
|
656 |
shift
|
|
657 |
;;
|
|
658 |
--inline-prefix)
|
|
659 |
shift
|
|
660 |
tt_inline_prefix="$1"
|
|
661 |
shift
|
|
662 |
;;
|
|
663 |
--prefix)
|
|
664 |
shift
|
|
665 |
tt_prefix="$1"
|
|
666 |
shift
|
|
667 |
;;
|
|
668 |
--prompt)
|
|
669 |
shift
|
|
670 |
tt_prompt="$1"
|
|
671 |
shift
|
|
672 |
;;
|
|
673 |
-h | --help)
|
643 | 674 |
printf '%s\n' "$tt_my_help"
|
644 | 675 |
exit 0
|
645 | |
;;
|
646 | |
-V|--version)
|
647 | |
printf '%s %s\n%s\n' $tt_my_name $tt_my_version $tt_my_version_url
|
|
676 |
;;
|
|
677 |
-V | --version)
|
|
678 |
printf '%s %s\n' "$tt_my_name" "$tt_my_version"
|
648 | 679 |
exit 0
|
649 | |
;;
|
|
680 |
;;
|
650 | 681 |
--)
|
651 | 682 |
# No more options to process
|
652 | 683 |
shift
|
653 | 684 |
break
|
654 | |
;;
|
|
685 |
;;
|
655 | 686 |
-)
|
656 | |
# Argument - means "read from STDIN" (not supported)
|
|
687 |
# Argument - means "read test file from STDIN"
|
657 | 688 |
break
|
658 | |
;;
|
|
689 |
;;
|
659 | 690 |
*)
|
660 | 691 |
tt_error "invalid option $1"
|
661 | |
;;
|
|
692 |
;;
|
662 | 693 |
esac
|
663 | 694 |
done
|
664 | 695 |
|
|
666 | 697 |
tt_nr_files=$#
|
667 | 698 |
|
668 | 699 |
# No files?
|
669 | |
if test $tt_nr_files -eq 0
|
670 | |
then
|
|
700 |
if test $tt_nr_files -eq 0; then
|
671 | 701 |
tt_error 'no test file informed (try --help)'
|
672 | 702 |
fi
|
673 | 703 |
|
|
675 | 705 |
case "$tt_prefix" in
|
676 | 706 |
tab)
|
677 | 707 |
tt_prefix="$tt_tab"
|
678 | |
;;
|
|
708 |
;;
|
679 | 709 |
0)
|
680 | 710 |
tt_prefix=''
|
681 | |
;;
|
|
711 |
;;
|
682 | 712 |
[1-9] | [1-9][0-9]) # 1-99
|
683 | 713 |
# convert number to spaces: 2 => ' '
|
684 | 714 |
tt_prefix=$(printf "%${tt_prefix}s" ' ')
|
685 | |
;;
|
|
715 |
;;
|
686 | 716 |
*\\*)
|
687 | 717 |
tt_prefix="$(printf %b "$tt_prefix")" # expand \t and others
|
688 | |
;;
|
|
718 |
;;
|
689 | 719 |
esac
|
690 | 720 |
|
691 | 721 |
# Validate and normalize progress value
|
692 | |
if test "$tt_output_mode" = 'normal'
|
693 | |
then
|
|
722 |
if test "$tt_output_mode" = 'normal'; then
|
694 | 723 |
case "$tt_progress" in
|
695 | 724 |
test)
|
696 | 725 |
:
|
697 | |
;;
|
|
726 |
;;
|
698 | 727 |
number | n | [0-9])
|
699 | 728 |
tt_progress='number'
|
700 | |
;;
|
|
729 |
;;
|
701 | 730 |
dot | .)
|
702 | 731 |
tt_progress='.'
|
703 | |
;;
|
|
732 |
;;
|
704 | 733 |
none | no)
|
705 | 734 |
tt_progress='none'
|
706 | |
;;
|
|
735 |
;;
|
707 | 736 |
?) # Single char, use it as the progress
|
708 | 737 |
:
|
709 | |
;;
|
|
738 |
;;
|
710 | 739 |
*)
|
711 | 740 |
tt_error "invalid value '$tt_progress' for --progress. Use: test, number, dot or none."
|
712 | |
;;
|
|
741 |
;;
|
713 | 742 |
esac
|
714 | 743 |
fi
|
715 | 744 |
|
|
717 | 746 |
case "$tt_color_mode" in
|
718 | 747 |
always | yes | y)
|
719 | 748 |
tt_use_colors=1
|
720 | |
;;
|
|
749 |
;;
|
721 | 750 |
never | no | n)
|
722 | 751 |
tt_use_colors=0
|
723 | |
;;
|
|
752 |
;;
|
724 | 753 |
auto | a)
|
725 | 754 |
# The auto mode will use colors if the output is a terminal
|
726 | 755 |
# Note: test -t is in POSIX
|
727 | |
if test -t 1
|
728 | |
then
|
|
756 |
if test -t 1; then
|
729 | 757 |
tt_use_colors=1
|
730 | 758 |
else
|
731 | 759 |
tt_use_colors=0
|
732 | 760 |
fi
|
733 | |
;;
|
|
761 |
;;
|
734 | 762 |
*)
|
735 | 763 |
tt_error "invalid value '$tt_color_mode' for --color. Use: auto, always or never."
|
736 | |
;;
|
|
764 |
;;
|
737 | 765 |
esac
|
738 | 766 |
|
739 | 767 |
# Set colors
|
740 | 768 |
# Remember: colors must be readable in dark and light backgrounds
|
741 | 769 |
# Customization: tweak the numbers after [ to adjust the colors
|
742 | |
if test $tt_use_colors -eq 1
|
743 | |
then
|
|
770 |
if test $tt_use_colors -eq 1; then
|
744 | 771 |
tt_color_red=$( printf '\033[31m') # fail
|
745 | 772 |
tt_color_green=$(printf '\033[32m') # ok
|
746 | 773 |
tt_color_blue=$( printf '\033[34m') # debug
|
|
753 | 780 |
# In other shells, try to use 'tput cols' (not POSIX).
|
754 | 781 |
# If not, defaults to 50 columns, a conservative amount.
|
755 | 782 |
: ${COLUMNS:=$(tput cols 2> /dev/null)}
|
756 | |
: ${COLUMNS:=50}
|
|
783 |
: "${COLUMNS:=50}"
|
757 | 784 |
|
758 | 785 |
# Parse and validate --test option value, if informed
|
759 | 786 |
tt_run_range_data=$(tt_parse_range "$tt_run_range")
|
760 | |
if test $? -ne 0
|
761 | |
then
|
|
787 |
if test $? -ne 0; then
|
762 | 788 |
tt_error "invalid argument for -t or --test: $tt_run_range"
|
763 | 789 |
fi
|
764 | 790 |
|
765 | 791 |
# Parse and validate --skip option value, if informed
|
766 | 792 |
tt_skip_range_data=$(tt_parse_range "$tt_skip_range")
|
767 | |
if test $? -ne 0
|
768 | |
then
|
|
793 |
if test $? -ne 0; then
|
769 | 794 |
tt_error "invalid argument for -s or --skip: $tt_skip_range"
|
770 | 795 |
fi
|
771 | 796 |
|
772 | |
|
773 | 797 |
### Real execution begins here
|
774 | 798 |
|
775 | 799 |
# Some preparing command to run before all the tests?
|
776 | |
if test -n "$tt_pre_command"
|
777 | |
then
|
|
800 |
if test -n "$tt_pre_command"; then
|
778 | 801 |
eval "$tt_pre_command" ||
|
779 | 802 |
tt_error "pre-flight command failed with status=$?: $tt_pre_command"
|
780 | 803 |
fi
|
781 | 804 |
|
782 | 805 |
# For each input file in $@
|
783 | |
for tt_test_file
|
784 | |
do
|
|
806 |
for tt_test_file; do
|
785 | 807 |
# Some tests may 'cd' to another dir, we need to get back
|
786 | 808 |
# to preserve the relative paths of the input files
|
787 | |
cd "$tt_original_dir"
|
|
809 |
cd "$tt_original_dir" ||
|
|
810 |
tt_error "cannot enter starting directory $tt_original_dir"
|
|
811 |
|
|
812 |
# Support using '-' to read the test file from STDIN
|
|
813 |
if test "$tt_test_file" = '-'; then
|
|
814 |
tt_test_file="$tt_stdin_file"
|
|
815 |
cat > "$tt_test_file"
|
|
816 |
fi
|
|
817 |
|
|
818 |
# Abort when test file is a directory
|
|
819 |
if test -d "$tt_test_file"; then
|
|
820 |
tt_error "input file is a directory: $tt_test_file"
|
|
821 |
fi
|
788 | 822 |
|
789 | 823 |
# Abort when test file not found/readable
|
790 | |
if test ! -f "$tt_test_file" || test ! -r "$tt_test_file"
|
791 | |
then
|
|
824 |
if test ! -r "$tt_test_file"; then
|
792 | 825 |
tt_error "cannot read input file: $tt_test_file"
|
793 | 826 |
fi
|
794 | 827 |
|
795 | 828 |
# In multifile mode, identify the current file
|
796 | |
if test $tt_nr_files -gt 1
|
797 | |
then
|
|
829 |
if test $tt_nr_files -gt 1; then
|
798 | 830 |
case "$tt_output_mode" in
|
799 | 831 |
normal)
|
800 | 832 |
# Normal mode, show message with filename
|
801 | 833 |
case "$tt_progress" in
|
802 | 834 |
test | none)
|
803 | 835 |
tt_message "Testing file $tt_test_file"
|
804 | |
;;
|
|
836 |
;;
|
805 | 837 |
*)
|
806 | 838 |
test $tt_missing_nl -eq 1 && echo
|
807 | 839 |
tt_message_part "Testing file $tt_test_file "
|
808 | |
;;
|
|
840 |
;;
|
809 | 841 |
esac
|
810 | |
;;
|
|
842 |
;;
|
811 | 843 |
list | list-run)
|
812 | 844 |
# List mode, show ------ and the filename
|
813 | 845 |
tt_message "$(tt_separator_line | cut -c 1-40)" "$tt_test_file"
|
814 | |
;;
|
|
846 |
;;
|
815 | 847 |
esac
|
816 | 848 |
fi
|
817 | 849 |
|
|
824 | 856 |
tt_process_test_file
|
825 | 857 |
|
826 | 858 |
# Abort when no test found (and no active range with --test or --skip)
|
827 | |
if test $tt_nr_file_tests -eq 0 && test -z "$tt_run_range_data" && test -z "$tt_skip_range_data"
|
828 | |
then
|
|
859 |
if test $tt_nr_file_tests -eq 0 && test -z "$tt_run_range_data" && test -z "$tt_skip_range_data"; then
|
829 | 860 |
tt_error "no test found in input file: $tt_test_file"
|
830 | 861 |
fi
|
831 | 862 |
|
832 | 863 |
# Save file stats
|
833 | |
tt_nr_file_ok=$(($tt_nr_file_tests - $tt_nr_file_fails - $tt_nr_file_skips))
|
|
864 |
tt_nr_file_ok=$((tt_nr_file_tests - tt_nr_file_fails - tt_nr_file_skips))
|
834 | 865 |
tt_files_stats="$tt_files_stats$tt_nr_file_ok $tt_nr_file_fails $tt_nr_file_skips$tt_nl"
|
835 | 866 |
|
836 | 867 |
# Dots mode: any missing new line?
|
|
841 | 872 |
tt_clean_up
|
842 | 873 |
|
843 | 874 |
# Some clean up command to run after all the tests?
|
844 | |
if test -n "$tt_post_command"
|
845 | |
then
|
846 | |
eval "$tt_post_command"
|
|
875 |
if test -n "$tt_post_command"; then
|
|
876 |
eval "$tt_post_command" ||
|
|
877 |
tt_error "post-flight command failed with status=$?: $tt_post_command"
|
847 | 878 |
fi
|
848 | 879 |
|
849 | 880 |
#-----------------------------------------------------------------------
|
|
851 | 882 |
#-----------------------------------------------------------------------
|
852 | 883 |
|
853 | 884 |
# Range active, but no test matched :(
|
854 | |
if test $tt_nr_total_tests -eq $tt_nr_total_skips
|
855 | |
then
|
856 | |
if test -n "$tt_run_range_data" && test -n "$tt_skip_range_data"
|
857 | |
then
|
|
885 |
if test $tt_nr_total_tests -eq $tt_nr_total_skips; then
|
|
886 |
if test -n "$tt_run_range_data" && test -n "$tt_skip_range_data"; then
|
858 | 887 |
tt_error "no test found. The combination of -t and -s resulted in no tests."
|
859 | |
elif test -n "$tt_run_range_data"
|
860 | |
then
|
|
888 |
elif test -n "$tt_run_range_data"; then
|
861 | 889 |
tt_error "no test found for the specified number or range '$tt_run_range'"
|
862 | |
elif test -n "$tt_skip_range_data"
|
863 | |
then
|
|
890 |
elif test -n "$tt_skip_range_data"; then
|
864 | 891 |
tt_error "no test found. Maybe '--skip $tt_skip_range' was too much?"
|
865 | 892 |
fi
|
866 | 893 |
fi
|
867 | 894 |
|
868 | 895 |
# List mode has no stats
|
869 | |
if test "$tt_output_mode" = 'list' || test "$tt_output_mode" = 'list-run'
|
870 | |
then
|
871 | |
if test $tt_nr_total_fails -eq 0
|
872 | |
then
|
|
896 |
if test "$tt_output_mode" = 'list' || test "$tt_output_mode" = 'list-run'; then
|
|
897 |
if test $tt_nr_total_fails -eq 0; then
|
873 | 898 |
exit 0
|
874 | 899 |
else
|
875 | 900 |
exit 1
|
|
884 | 909 |
# ok fail skip
|
885 | 910 |
# 100 0 23 foo.sh
|
886 | 911 |
# 12 34 0 bar.sh
|
887 | |
if test $tt_nr_files -gt 1 && test "$tt_output_mode" != 'quiet'
|
888 | |
then
|
|
912 |
if test $tt_nr_files -gt 1 && test "$tt_output_mode" != 'quiet'; then
|
889 | 913 |
echo
|
890 | 914 |
printf ' %5s %5s %5s\n' ok fail skip
|
891 | |
printf %s "$tt_files_stats" | while read ok fail skip
|
892 | |
do
|
893 | |
printf ' %5s %5s %5s %s\n' $ok $fail $skip "$1"
|
|
915 |
printf %s "$tt_files_stats" | while read -r ok fail skip; do
|
|
916 |
printf ' %5s %5s %5s %s\n' "$ok" "$fail" "$skip" "$1"
|
894 | 917 |
shift
|
895 | 918 |
done | sed 's/ 0/ -/g' # hide zeros
|
896 | 919 |
echo
|
|
902 | 925 |
# FAIL: 123 of 123 tests failed
|
903 | 926 |
# FAIL: 100 of 123 tests failed (23 skipped)
|
904 | 927 |
skips=
|
905 | |
if test $tt_nr_total_skips -gt 0
|
906 | |
then
|
|
928 |
if test $tt_nr_total_skips -gt 0; then
|
907 | 929 |
skips=" ($tt_nr_total_skips skipped)"
|
908 | 930 |
fi
|
909 | |
if test $tt_nr_total_fails -eq 0
|
910 | |
then
|
|
931 |
if test $tt_nr_total_fails -eq 0; then
|
911 | 932 |
stamp="${tt_color_green}OK:${tt_color_off}"
|
912 | |
stats="$(($tt_nr_total_tests - $tt_nr_total_skips)) of $tt_nr_total_tests tests passed"
|
|
933 |
stats="$((tt_nr_total_tests - tt_nr_total_skips)) of $tt_nr_total_tests tests passed"
|
913 | 934 |
test $tt_nr_total_tests -eq 1 && stats=$(echo "$stats" | sed 's/tests /test /')
|
914 | 935 |
tt_message "$stamp $stats$skips"
|
915 | 936 |
exit 0
|