3 # Setup test environment.
5 # Copyright (c) 2014 Jonas Fonseca <jonas.fonseca@gmail.com>
7 # This program is free software; you can redistribute it and/or
8 # modify it under the terms of the GNU General Public License as
9 # published by the Free Software Foundation; either version 2 of
10 # the License, or (at your option) any later version.
12 # This program is distributed in the hope that it will be useful,
13 # but WITHOUT ANY WARRANTY; without even the implied warranty of
14 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 # GNU General Public License for more details.
18 if [ -n "${BASH_VERSION:-}" ]; then
23 test="$(basename "$0")"
24 source_dir
="$(cd $(dirname "$0") >/dev/null && pwd)"
25 base_dir
="$(echo "$source_dir" | sed -n 's#\(.*/test\)\([/].*\)*#\1#p')"
26 prefix_dir
="$(echo "$source_dir" | sed -n 's#\(.*/test/\)\([/].*\)*#\2#p')"
27 output_dir
="$base_dir/tmp/$prefix_dir/$test"
28 tmp_dir
="$base_dir/tmp"
29 output_dir
="$tmp_dir/$prefix_dir/$test"
32 # The locale must specify UTF-8 for Ncurses to output correctly. Since C.UTF-8
33 # does not exist on Mac OS X, we end up with en_US as the only sane choice.
34 export LANG
=en_US.UTF-8
35 export LC_ALL
=en_US.UTF-8
40 export HOME
="$output_dir"
45 export GIT_CONFIG_NOSYSTEM
46 unset GIT_CONFIG GIT_DIR GIT_WORK_TREE GIT_INDEX_FILE
47 unset GIT_AUTHOR_NAME GIT_AUTHOR_EMAIL GIT_AUTHOR_DATE
48 unset GIT_COMMITTER_NAME GIT_COMMITTER_EMAIL GIT_COMMITTER_DATE
49 unset GIT_EDITOR GIT_SEQUENCE_EDITOR GIT_PAGER GIT_EXTERNAL_DIFF
50 unset GIT_NOTES_REF GIT_NOTES_DISPLAY_REF
63 # A comma-separated list of options. See docs in test/README.
64 export TEST_OPTS
="${TEST_OPTS:-}"
65 # Used by tig_script to set the test "scope" used by test_tig.
68 [ -e "$output_dir" ] && rm -rf "$output_dir"
69 mkdir
-p "$output_dir/$work_dir"
71 if [ ! -d "$tmp_dir/.git" ]; then
72 # Create a dummy repository to avoid reading .git/config
73 # settings from the tig repository.
74 git init
-q "$tmp_dir"
77 # For any utilities used in Tig scripts
80 export PATH
="$BIN_DIR:$PATH"
83 path
="$BIN_DIR/$1"; shift
87 stdin|expected
*) cat ;;
91 printf '%s' "$@" > "$path"
98 executable
'vim' <<EOF
102 lineno="\$(expr "\$1" : '+\([0-9]*\)')"
103 if [ -n "\$lineno" ]; then
107 echo "\$@" >> "$HOME/editor.log"
108 sed -n -e "\${lineno}p" "\$file" >> "$HOME/editor.log" 2>&1
126 mkdir
-p "$(dirname "$path")"
127 if [ "$#" = 0 ]; then
129 stdin|expected
*) cat ;;
133 printf '%s' "$@" > "$path"
139 prefix
="${name:+$name.}"
141 export TIG_SCRIPT
="$HOME/${prefix}steps"
142 export TEST_NAME
="$name"
144 # Ensure that the steps finish by quitting
145 printf '%s\n:quit\n' "$@" \
146 |
sed -e 's/^[ ]*//' -e '/^$/d' \
147 |
sed "s|:save-display\s\+\(\S*\)|:save-display $HOME/\1|" \
160 file "$HOME/.tigrc" "$@"
164 file "$HOME/.gitconfig" "$@"
169 (cd "$work_dir" && $@
)
172 auto_detect_debugger
() {
173 for dbg
in gdb lldb
; do
174 dbg
="$(command -v "$dbg" 2>/dev/null || true)"
175 if [ -n "$dbg" ]; then
181 die
"Failed to detect a supported debugger"
188 expected_status_code
=0
190 [ -t 1 ] && diff_color_arg
=--color
198 set -- $TIG_TEST_OPTS $TEST_OPTS
200 while [ $# -gt 0 ]; do
203 verbose
) verbose
=yes ;;
204 no-indent
) indent
= ;;
205 debugger
=*) debugger
=$
(expr "$arg" : 'debugger=\(.*\)') ;;
206 debugger
) debugger
="$(auto_detect_debugger)" ;;
208 valgrind
) valgrind
="$HOME/valgrind.log" ;;
213 # Test runners and assertion checking.
220 if [ ! -s "expected/$file" ]; then
221 file "expected/$file"
224 if [ -e "$file" ]; then
225 git
diff -w --no-index $diff_color_arg "expected/$file" "$file" > "$file.diff" || true
226 if [ -s "$file.diff" ]; then
227 echo "[FAIL] $file != expected/$file" >> .test-result
228 while [ $# -gt 0 ]; do
230 echo "[NOTE] $msg" >> .test-result
232 cat "$file.diff" >> .test-result
234 echo " [OK] $file assertion" >> .test-result
238 echo "[FAIL] $file not found" >> .test-result
246 if [ -e "$file" ]; then
247 echo "[FAIL] $file should not exist" >> .test-result
249 echo " [OK] $file does not exist" >> .test-result
254 expected_var_file
="$HOME/expected/$vars_file"
256 executable
'assert-var' <<EOF
259 mkdir -p "$(dirname "$expected_var_file")"
260 while [ \$# -gt 0 ]; do
265 *) echo "\$arg" >> "$HOME/$vars_file" ;;
268 echo "\$@" >> "$expected_var_file"
273 if [ -e "$expected_var_file" ]; then
274 assert_equals
"$vars_file" < "$expected_var_file"
276 echo "[FAIL] $expected_var_file not found" >> .test-result
282 if [ -e .test-skipped
]; then
283 sed "s/^/$indent[skipped] /" < .test-skipped
286 if [ -n "$trace" -a -n "$TIG_TRACE" -a -e "$TIG_TRACE" ]; then
287 sed "s/^/$indent[trace] /" < "$TIG_TRACE"
289 if [ -n "$valgrind" -a -e "$valgrind" ]; then
290 sed "s/^/$indent[valgrind] /" < "$valgrind"
292 if [ ! -d "$HOME" ] ||
[ ! -e .test-result
]; then
294 sed "s/^/[stderr] /" < stderr
295 [ -e stderr.orig
] &&
296 sed "s/^/[stderr] /" < stderr.orig
297 echo "No test results found"
298 elif grep FAIL
-q < .test-result
; then
299 failed
="$(grep FAIL < .test-result | wc -l)"
300 count
="$(sed -n '/\(FAIL\|OK\)/p' < .test-result | wc -l)"
302 printf "Failed %d out of %d test(s)%s\n" $failed $count
304 # Show output from stderr if no output is expected
305 if [ -e stderr
]; then
306 [ -e expected
/stderr
] ||
307 sed "s/^/[stderr] /" < stderr
310 # Replace CR used by Git progress messages
311 tr '\r' '\n' < .test-result
312 elif [ "$verbose" ]; then
313 count
="$(sed -n '/\(OK\)/p' < .test-result | wc -l)"
314 printf "Passed %d assertions\n" $count
315 fi |
sed "s/^/$indent| /"
318 trap 'show_test_results' EXIT
322 echo "$@" >> .test-skipped
325 require_git_version
()
327 git_version
="$(git version | sed 's/git version \([0-9\.]*\).*/\1/')"
328 actual_major
="$(expr "$git_version" : '\([0-9]*\).*')"
329 actual_minor
="$(expr "$git_version" : '[0-9]*\.\([0-9]*\).*')"
331 required_version
="$1"; shift
332 required_major
="$(expr "$required_version" : '\([0-9]*\).*')"
333 required_minor
="$(expr "$required_version" : '[0-9]*\.\([0-9]*\).*')"
335 if [ "$required_major" -gt "$actual_major" ] ||
336 [ "$required_minor" -gt "$actual_minor" ]; then
343 while [ $# -gt 0 ]; do
348 require_git_version
2.5 \
349 "The test requires git-worktree, available in git version 2.5 or newer"
352 if [ "${TIG_ADDRESS_SANITIZER_ENABLED:-no}" != yes ]; then
353 test_skip
"The test requires clang and is only run via \`make test-address-sanitizer\`"
357 test_skip
"Unknown feature requirement: $feature"
364 echo "=== $@ ===" >> "$HOME/test-exec.log"
365 test_exec_log
="$HOME/test-exec.log.tmp"
366 rm -f "$test_exec_log"
369 in_work_dir
"$@" 1>>"$test_exec_log" 2>>"$test_exec_log"
370 test_exec_exit_code
=$?
373 cat "$test_exec_log" >> "$HOME/test-exec.log"
374 if [ "$test_exec_exit_code" != 0 ]; then
376 echo "[FAIL] unexpected exit code while executing '$cmd': $test_exec_exit_code" >> .test-result
377 cat "$test_exec_log" >> .test-result
378 # Exit gracefully to allow additional tests to run
385 if [ -e .test-skipped
]; then
389 run_setup
="$(type test_setup_work_dir 2>/dev/null | grep 'function' || true)"
391 if [ -n "$run_setup" ]; then
392 if test ! -e "$HOME/test-exec.log" ||
! grep -q test_setup_work_dir
"$HOME/test-exec.log"; then
393 test_exec_work_dir test_setup_work_dir
400 kernel
="$(uname -s 2>/dev/null || echo unknown)"
401 kernel_supp
="test/tools/valgrind-$kernel.supp"
404 if [ -e "$kernel_supp" ]; then
405 valgrind_ops
="$valgrind_ops --suppresions='$kernel_supp'"
408 valgrind
-q --gen-suppressions=all
--track-origins=yes --error-exitcode=1 \
409 --log-file="$valgrind.orig" $valgrind_ops \
413 Darwin
) grep -v "mach_msg unhandled MACH_SEND_TRAILER option" < "$valgrind.orig" > "$valgrind" ;;
414 *) mv "$valgrind.orig" "$valgrind" ;;
417 rm -f "$valgrind.orig"
423 prefix
="${name:+$name.}"
426 export TIG_NO_DISPLAY
=
427 if [ -n "$trace" ]; then
428 export TIG_TRACE
="$HOME/${prefix}tig-trace"
430 touch "${prefix}stdin" "${prefix}stderr"
431 if [ -n "$debugger" ]; then
432 echo "*** Running tests in '$(pwd)/$work_dir'"
433 if [ -s "$work_dir/${prefix}stdin" ]; then
434 echo "*** - This test requires data to be injected via stdin."
435 echo "*** The expected input file is: '../${prefix}stdin'"
437 if [ "$#" -gt 0 ]; then
438 echo "*** - This test expects the following arguments: $@"
440 (cd "$work_dir" && $debugger tig
"$@")
444 # FIXME: Tell Valgrind to forward status code
445 if [ "$expected_status_code" = 0 -a -n "$valgrind" ]; then
448 if [ -s "${prefix}stdin" ]; then
449 (cd "$work_dir" && $runner tig
"$@") < "${prefix}stdin" > "${prefix}stdout" 2> "${prefix}stderr.orig"
451 (cd "$work_dir" && $runner tig
"$@") > "${prefix}stdout" 2> "${prefix}stderr.orig"
454 if [ "$status_code" != "$expected_status_code" ]; then
455 echo "[FAIL] unexpected status code: $status_code (should be $expected_status_code)" >> .test-result
459 # Normalize paths in stderr output
460 if [ -e "${prefix}stderr.orig" ]; then
461 sed "s#$output_dir#HOME#" < "${prefix}stderr.orig" > "${prefix}stderr"
462 rm -f "${prefix}stderr.orig"
464 if [ -n "$trace" ]; then
465 export TIG_TRACE
="$HOME/.tig-trace"
466 if [ -n "$name" ]; then
467 sed "s#^#[$name] #" < "$HOME/${prefix}tig-trace" >> "$HOME/.tig-trace"
469 mv "$HOME/${prefix}tig-trace" "$HOME/.tig-trace"
472 if [ -n "$prefix" ]; then
473 sed "s#^#[$name] #" < "${prefix}stderr" >> "stderr"
479 test-graph $@
> stdout
2> stderr.orig
486 echo "$name" >> test-cases
487 cat > "$name.expected"
489 touch "$name-before" "$name-after" "$name.script" "$name-args"
491 while [ "$#" -gt 0 ]; do
493 key
="$(expr "X
$arg" : 'X--\([^=]*\).*')"
494 value
="$(expr "X
$arg" : 'X--[^=]*=\(.*\)')"
497 before|after|
script|args|cwd
)
498 echo "$value" > "$name-$key" ;;
499 *) die
"Unknown test_case argument: $arg"
506 if [ ! -e test-cases
]; then
510 for name
in $
(cat test-cases
); do
512 $(if [ -e "$name-script" ]; then cat "$name-script"; fi)
513 :save-display $name.screen
515 if [ -e "$name-before" ]; then
516 test_exec_work_dir
"$SHELL" "$HOME/$name-before"
518 old_work_dir
="$work_dir"
519 if [ -e "$name-cwd" ]; then
520 work_dir
="$work_dir/$(cat "$name-cwd")"
524 test_tig $
(if [ -e "$name-args" ]; then cat "$name-args"; fi)
526 work_dir
="$old_work_dir"
527 if [ -e "$name-after" ]; then
528 test_exec_work_dir
"$SHELL" "$HOME/$name-after"
531 assert_equals
"$name.screen" < "$name.expected"
532 assert_equals
"$name.stderr" < /dev
/null