diff options
Diffstat (limited to 't/test-lib.sh')
-rw-r--r-- | t/test-lib.sh | 217 |
1 files changed, 193 insertions, 24 deletions
diff --git a/t/test-lib.sh b/t/test-lib.sh index b25249ec4..79e8a33d0 100644 --- a/t/test-lib.sh +++ b/t/test-lib.sh @@ -1,4 +1,4 @@ -#!/bin/sh +# Test framework for git. See t/README for usage. # # Copyright (c) 2005 Junio C Hamano # @@ -26,6 +26,10 @@ then # outside of t/, e.g. for running tests on the test library # itself. TEST_DIRECTORY=$(pwd) +else + # ensure that TEST_DIRECTORY is an absolute path so that it + # is valid even if the current working directory is changed + TEST_DIRECTORY=$(cd "$TEST_DIRECTORY" && pwd) || exit 1 fi if test -z "$TEST_OUTPUT_DIRECTORY" then @@ -87,6 +91,7 @@ unset VISUAL EMAIL LANGUAGE COLUMNS $("$PERL_PATH" -e ' VALGRIND UNZIP PERF_ + CURL_VERBOSE )); my @vars = grep(/^GIT_/ && !/^GIT_($ok)/o, @env); print join("\n", @vars); @@ -104,6 +109,16 @@ export GIT_AUTHOR_EMAIL GIT_AUTHOR_NAME export GIT_COMMITTER_EMAIL GIT_COMMITTER_NAME export EDITOR +# Tests using GIT_TRACE typically don't want <timestamp> <file>:<line> output +GIT_TRACE_BARE=1 +export GIT_TRACE_BARE + +if test -n "${TEST_GIT_INDEX_VERSION:+isset}" +then + GIT_INDEX_VERSION="$TEST_GIT_INDEX_VERSION" + export GIT_INDEX_VERSION +fi + # Add libc MALLOC and MALLOC_PERTURB test # only if we are not executing the test with valgrind if expr " $GIT_TEST_OPTS " : ".* --valgrind " >/dev/null || @@ -154,7 +169,11 @@ _z40=0000000000000000000000000000000000000000 LF=' ' -export _x05 _x40 _z40 LF +# UTF-8 ZERO WIDTH NON-JOINER, which HFS+ ignores +# when case-folding filenames +u200c=$(printf '\342\200\214') + +export _x05 _x40 _z40 LF u200c # Each test should start with something like this, after copyright notices: # @@ -181,6 +200,14 @@ do immediate=t; shift ;; -l|--l|--lo|--lon|--long|--long-|--long-t|--long-te|--long-tes|--long-test|--long-tests) GIT_TEST_LONG=t; export GIT_TEST_LONG; shift ;; + -r) + shift; test "$#" -ne 0 || { + echo 'error: -r requires an argument' >&2; + exit 1; + } + run_list=$1; shift ;; + --run=*) + run_list=$(expr "z$1" : 'z[^=]*=\(.*\)'); shift ;; -h|--h|--he|--hel|--help) help=t; shift ;; -v|--v|--ve|--ver|--verb|--verbo|--verbos|--verbose) @@ -210,6 +237,10 @@ do --root=*) root=$(expr "z$1" : 'z[^=]*=\(.*\)') shift ;; + -x) + trace=t + verbose=t + shift ;; *) echo "error: unknown test option '$1'" >&2; exit 1 ;; esac @@ -273,7 +304,7 @@ error "Test script did not set test_description." if test "$help" = "t" then - echo "$test_description" + printf '%s\n' "$test_description" exit 0 fi @@ -324,7 +355,7 @@ test_failure_ () { test_failure=$(($test_failure + 1)) say_color error "not ok $test_count - $1" shift - echo "$@" | sed -e 's/^/# /' + printf '%s\n' "$*" | sed -e 's/^/# /' test "$immediate" = "" || { GIT_EXIT_OK=t; exit 1; } } @@ -356,6 +387,99 @@ match_pattern_list () { return 1 } +match_test_selector_list () { + title="$1" + shift + arg="$1" + shift + test -z "$1" && return 0 + + # Both commas and whitespace are accepted as separators. + OLDIFS=$IFS + IFS=' ,' + set -- $1 + IFS=$OLDIFS + + # If the first selector is negative we include by default. + include= + case "$1" in + !*) include=t ;; + esac + + for selector + do + orig_selector=$selector + + positive=t + case "$selector" in + !*) + positive= + selector=${selector##?} + ;; + esac + + test -z "$selector" && continue + + case "$selector" in + *-*) + if expr "z${selector%%-*}" : "z[0-9]*[^0-9]" >/dev/null + then + echo "error: $title: invalid non-numeric in range" \ + "start: '$orig_selector'" >&2 + exit 1 + fi + if expr "z${selector#*-}" : "z[0-9]*[^0-9]" >/dev/null + then + echo "error: $title: invalid non-numeric in range" \ + "end: '$orig_selector'" >&2 + exit 1 + fi + ;; + *) + if expr "z$selector" : "z[0-9]*[^0-9]" >/dev/null + then + echo "error: $title: invalid non-numeric in test" \ + "selector: '$orig_selector'" >&2 + exit 1 + fi + esac + + # Short cut for "obvious" cases + test -z "$include" && test -z "$positive" && continue + test -n "$include" && test -n "$positive" && continue + + case "$selector" in + -*) + if test $arg -le ${selector#-} + then + include=$positive + fi + ;; + *-) + if test $arg -ge ${selector%-} + then + include=$positive + fi + ;; + *-*) + if test ${selector%%-*} -le $arg \ + && test $arg -le ${selector#*-} + then + include=$positive + fi + ;; + *) + if test $arg -eq $selector + then + include=$positive + fi + ;; + esac + done + + test -n "$include" +} + maybe_teardown_verbose () { test -z "$verbose_only" && return exec 4>/dev/null 3>/dev/null @@ -401,10 +525,39 @@ maybe_setup_valgrind () { fi } +# This is a separate function because some tests use +# "return" to end a test_expect_success block early +# (and we want to make sure we run any cleanup like +# "set +x"). +test_eval_inner_ () { + # Do not add anything extra (including LF) after '$*' + eval " + test \"$trace\" = t && set -x + $*" +} + test_eval_ () { - # This is a separate function because some tests use - # "return" to end a test_expect_success block early. - eval </dev/null >&3 2>&4 "$*" + # We run this block with stderr redirected to avoid extra cruft + # during a "-x" trace. Once in "set -x" mode, we cannot prevent + # the shell from printing the "set +x" to turn it off (nor the saving + # of $? before that). But we can make sure that the output goes to + # /dev/null. + # + # The test itself is run with stderr put back to &4 (so either to + # /dev/null, or to the original stderr if --verbose was used). + { + test_eval_inner_ "$@" </dev/null >&3 2>&4 + test_eval_ret_=$? + if test "$trace" = t + then + set +x + if test "$test_eval_ret_" != 0 + then + say_color error >&4 "error: last command exited with \$?=$test_eval_ret_" + fi + fi + } 2>/dev/null + return $test_eval_ret_ } test_run_ () { @@ -415,7 +568,8 @@ test_run_ () { eval_ret=$? teardown_malloc_check - if test -z "$immediate" || test $eval_ret = 0 || test -n "$expecting_failure" + if test -z "$immediate" || test $eval_ret = 0 || + test -n "$expecting_failure" && test "$test_cleanup" != ":" then setup_malloc_check test_eval_ "$test_cleanup" @@ -442,25 +596,35 @@ test_finish_ () { test_skip () { to_skip= + skipped_reason= if match_pattern_list $this_test.$test_count $GIT_SKIP_TESTS then to_skip=t + skipped_reason="GIT_SKIP_TESTS" fi if test -z "$to_skip" && test -n "$test_prereq" && ! test_have_prereq "$test_prereq" then to_skip=t - fi - case "$to_skip" in - t) + of_prereq= if test "$missing_prereq" != "$test_prereq" then of_prereq=" of $test_prereq" fi + skipped_reason="missing $missing_prereq${of_prereq}" + fi + if test -z "$to_skip" && test -n "$run_list" && + ! match_test_selector_list '--run' $test_count "$run_list" + then + to_skip=t + skipped_reason="--run" + fi + case "$to_skip" in + t) say_color skip >&3 "skipping test: $@" - say_color skip "ok $test_count # skip $1 (missing $missing_prereq${of_prereq})" + say_color skip "ok $test_count # skip $1 ($skipped_reason)" : true ;; *) @@ -477,8 +641,6 @@ test_at_end_hook_ () { test_done () { GIT_EXIT_OK=t - # Note: t0000 relies on $HARNESS_ACTIVE disabling the .counts - # output file if test -z "$HARNESS_ACTIVE" then test_results_dir="$TEST_OUTPUT_DIRECTORY/test-results" @@ -573,11 +735,9 @@ then make_valgrind_symlink () { # handle only executables, unless they are shell libraries that - # need to be in the exec-path. We will just use "#!" as a - # guess for a shell-script, since we have no idea what the user - # may have configured as the shell path. + # need to be in the exec-path. test -x "$1" || - test "#!" = "$(head -c 2 <"$1")" || + test "# " = "$(head -c 2 <"$1")" || return; base=$(basename "$1") @@ -649,7 +809,6 @@ else # normal case, use ../bin-wrappers only unless $with_dashes: fi fi GIT_TEMPLATE_DIR="$GIT_BUILD_DIR"/templates/blt -unset GIT_CONFIG GIT_CONFIG_NOSYSTEM=1 GIT_ATTR_NOSYSTEM=1 export PATH GIT_EXEC_PATH GIT_TEMPLATE_DIR GIT_CONFIG_NOSYSTEM GIT_ATTR_NOSYSTEM @@ -692,7 +851,8 @@ rm -fr "$TRASH_DIRECTORY" || { } HOME="$TRASH_DIRECTORY" -export HOME +GNUPGHOME="$HOME/gnupg-home-not-used" +export HOME GNUPGHOME if test -z "$TEST_NO_CREATE_REPO" then @@ -749,7 +909,7 @@ case $(uname -s) in # backslashes in pathspec are converted to '/' # exec does not inherit the PID test_set_prereq MINGW - test_set_prereq NOT_CYGWIN + test_set_prereq NATIVE_CRLF test_set_prereq SED_STRIPS_CR test_set_prereq GREP_STRIPS_CR GIT_TEST_CMP=mingw_test_cmp @@ -757,7 +917,6 @@ case $(uname -s) in *CYGWIN*) test_set_prereq POSIXPERM test_set_prereq EXECKEEPSPID - test_set_prereq NOT_MINGW test_set_prereq CYGWIN test_set_prereq SED_STRIPS_CR test_set_prereq GREP_STRIPS_CR @@ -766,8 +925,6 @@ case $(uname -s) in test_set_prereq POSIXPERM test_set_prereq BSLASHPSPEC test_set_prereq EXECKEEPSPID - test_set_prereq NOT_MINGW - test_set_prereq NOT_CYGWIN ;; esac @@ -830,6 +987,10 @@ test_lazy_prereq SYMLINKS ' ln -s x y && test -h y ' +test_lazy_prereq FILEMODE ' + test "$(git config --bool core.filemode)" = true +' + test_lazy_prereq CASE_INSENSITIVE_FS ' echo good >CamelCase && echo bad >camelcase && @@ -855,6 +1016,14 @@ test_lazy_prereq AUTOIDENT ' git var GIT_AUTHOR_IDENT ' +test_lazy_prereq EXPENSIVE ' + test -n "$GIT_TEST_LONG" +' + +test_lazy_prereq USR_BIN_TIME ' + test -x /usr/bin/time +' + # When the tests are run as root, permission tests will report that # things are writable when they shouldn't be. test -w / || test_set_prereq SANITY |