diff options
Diffstat (limited to 't/test-lib.sh')
-rw-r--r-- | t/test-lib.sh | 306 |
1 files changed, 262 insertions, 44 deletions
diff --git a/t/test-lib.sh b/t/test-lib.sh index ca6bdef63d..b1bc65bfb5 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 @@ -54,8 +58,8 @@ done,*) # do not redirect again ;; *' --tee '*|*' --va'*) - mkdir -p test-results - BASE=test-results/$(basename "$0" .sh) + mkdir -p "$TEST_OUTPUT_DIRECTORY/test-results" + BASE="$TEST_OUTPUT_DIRECTORY/test-results/$(basename "$0" .sh)" (GIT_TEST_TEE_STARTED=done ${SHELL_PATH} "$0" "$@" 2>&1; echo $? > $BASE.exit) | tee $BASE.out test "$(cat $BASE.exit)" = 0 @@ -87,11 +91,13 @@ 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); ') unset XDG_CONFIG_HOME +unset GITPERLLIB GIT_AUTHOR_EMAIL=author@example.com GIT_AUTHOR_NAME='A U Thor' GIT_COMMITTER_EMAIL=committer@example.com @@ -103,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 || @@ -180,10 +196,21 @@ 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) verbose=t; shift ;; + --verbose-only=*) + verbose_only=$(expr "z$1" : 'z[^=]*=\(.*\)') + shift ;; -q|--q|--qu|--qui|--quie|--quiet) # Ignore --quiet under a TAP::Harness. Saying how many tests # passed without the ok/not ok details is always an error. @@ -198,6 +225,9 @@ do --valgrind=*) valgrind=$(expr "z$1" : 'z[^=]*=\(.*\)') shift ;; + --valgrind-only=*) + valgrind_only=$(expr "z$1" : 'z[^=]*=\(.*\)') + shift ;; --tee) shift ;; # was handled already --root=*) @@ -208,7 +238,14 @@ do esac done -test -n "$valgrind" && verbose=t +if test -n "$valgrind_only" +then + test -z "$valgrind" && valgrind=memcheck + test -z "$verbose" && verbose_only="$valgrind_only" +elif test -n "$valgrind" +then + verbose=t +fi if test -n "$color" then @@ -259,7 +296,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 @@ -299,7 +336,7 @@ trap 'die' EXIT . "$TEST_DIRECTORY/test-lib-functions.sh" # You are not expected to call test_ok_ and test_failure_ directly, use -# the text_expect_* functions instead. +# the test_expect_* functions instead. test_ok_ () { test_success=$(($test_success + 1)) @@ -310,7 +347,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; } } @@ -328,6 +365,158 @@ test_debug () { test "$debug" = "" || eval "$1" } +match_pattern_list () { + arg="$1" + shift + test -z "$*" && return 1 + for pattern_ + do + case "$arg" in + $pattern_) + return 0 + esac + done + 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 + verbose= +} + +last_verbose=t +maybe_setup_verbose () { + test -z "$verbose_only" && return + if match_pattern_list $test_count $verbose_only + then + exec 4>&2 3>&1 + # Emit a delimiting blank line when going from + # non-verbose to verbose. Within verbose mode the + # delimiter is printed by test_expect_*. The choice + # of the initial $last_verbose is such that before + # test 1, we do not print it. + test -z "$last_verbose" && echo >&3 "" + verbose=t + else + exec 4>/dev/null 3>/dev/null + verbose= + fi + last_verbose=$verbose +} + +maybe_teardown_valgrind () { + test -z "$GIT_VALGRIND" && return + GIT_VALGRIND_ENABLED= +} + +maybe_setup_valgrind () { + test -z "$GIT_VALGRIND" && return + if test -z "$valgrind_only" + then + GIT_VALGRIND_ENABLED=t + return + fi + GIT_VALGRIND_ENABLED= + if match_pattern_list $test_count $valgrind_only + then + GIT_VALGRIND_ENABLED=t + fi +} + test_eval_ () { # This is a separate function because some tests use # "return" to end a test_expect_success block early. @@ -337,8 +526,10 @@ test_eval_ () { test_run_ () { test_cleanup=: expecting_failure=$2 + setup_malloc_check test_eval_ "$1" eval_ret=$? + teardown_malloc_check if test -z "$immediate" || test $eval_ret = 0 || test -n "$expecting_failure" then @@ -353,32 +544,49 @@ test_run_ () { return "$eval_ret" } -test_skip () { +test_start_ () { test_count=$(($test_count+1)) + maybe_setup_verbose + maybe_setup_valgrind +} + +test_finish_ () { + echo >&3 "" + maybe_teardown_valgrind + maybe_teardown_verbose +} + +test_skip () { to_skip= - for skp in $GIT_SKIP_TESTS - do - case $this_test.$test_count in - $skp) - to_skip=t - break - esac - done + 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 ;; *) @@ -489,11 +697,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") @@ -538,6 +744,9 @@ then export GIT_VALGRIND GIT_VALGRIND_MODE="$valgrind" export GIT_VALGRIND_MODE + GIT_VALGRIND_ENABLED=t + test -n "$valgrind_only" && GIT_VALGRIND_ENABLED= + export GIT_VALGRIND_ENABLED elif test -n "$GIT_TEST_INSTALLED" then GIT_EXEC_PATH=$($GIT_TEST_INSTALLED/git --exec-path) || @@ -562,7 +771,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 @@ -583,15 +791,6 @@ test -d "$GIT_BUILD_DIR"/templates/blt || { error "You haven't built things yet, have you?" } -if test -z "$GIT_TEST_INSTALLED" && test -z "$NO_PYTHON" -then - GITPYTHONLIB="$GIT_BUILD_DIR/git_remote_helpers/build/lib" - export GITPYTHONLIB - test -d "$GIT_BUILD_DIR"/git_remote_helpers/build || { - error "You haven't built git_remote_helpers yet, have you?" - } -fi - if ! test -x "$GIT_BUILD_DIR"/test-chmtime then echo >&2 'You need to build test-chmtime:' @@ -628,15 +827,12 @@ cd -P "$TRASH_DIRECTORY" || exit 1 this_test=${0##*/} this_test=${this_test%%-*} -for skp in $GIT_SKIP_TESTS -do - case "$this_test" in - $skp) - say_color info >&3 "skipping test $this_test altogether" - skip_all="skip all tests in $this_test" - test_done - esac -done +if match_pattern_list "$this_test" $GIT_SKIP_TESTS +then + say_color info >&3 "skipping test $this_test altogether" + skip_all="skip all tests in $this_test" + test_done +fi # Provide an implementation of the 'yes' utility yes () { @@ -676,6 +872,8 @@ case $(uname -s) in test_set_prereq MINGW test_set_prereq NOT_CYGWIN test_set_prereq SED_STRIPS_CR + test_set_prereq GREP_STRIPS_CR + GIT_TEST_CMP=mingw_test_cmp ;; *CYGWIN*) test_set_prereq POSIXPERM @@ -683,6 +881,7 @@ case $(uname -s) in test_set_prereq NOT_MINGW test_set_prereq CYGWIN test_set_prereq SED_STRIPS_CR + test_set_prereq GREP_STRIPS_CR ;; *) test_set_prereq POSIXPERM @@ -737,7 +936,14 @@ test_i18ngrep () { test_lazy_prereq PIPE ' # test whether the filesystem supports FIFOs - rm -f testfifo && mkfifo testfifo + case $(uname -s) in + CYGWIN*) + false + ;; + *) + rm -f testfifo && mkfifo testfifo + ;; + esac ' test_lazy_prereq SYMLINKS ' @@ -745,6 +951,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 && @@ -770,6 +980,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 |