Merge branch 'maint-1.6.1' into maint-1.6.2
[gitweb.git] / t / test-lib.sh
index c861141667eb03eb42f559cbe174c6a76dd704c9..59d82d25e9ad586ff43a4a9485d348492fb36d19 100644 (file)
@@ -35,6 +35,7 @@ unset GIT_WORK_TREE
 unset GIT_EXTERNAL_DIFF
 unset GIT_INDEX_FILE
 unset GIT_OBJECT_DIRECTORY
+unset GIT_CEILING_DIRECTORIES
 unset SHA1_FILE_DIRECTORIES
 unset SHA1_FILE_DIRECTORY
 GIT_MERGE_VERBOSITY=5
@@ -80,6 +81,8 @@ do
                debug=t; shift ;;
        -i|--i|--im|--imm|--imme|--immed|--immedi|--immedia|--immediat|--immediate)
                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 ;;
        -h|--h|--he|--hel|--help)
                help=t; shift ;;
        -v|--v|--ve|--ver|--verb|--verbo|--verbos|--verbose)
@@ -109,8 +112,9 @@ if test -n "$color"; then
                        *) test -n "$quiet" && return;;
                esac
                shift
-               echo "* $*"
+               printf "* %s" "$*"
                tput sgr0
+               echo
                )
        }
 else
@@ -123,7 +127,7 @@ fi
 
 error () {
        say_color error "error: $*"
-       trap - exit
+       trap - EXIT
        exit 1
 }
 
@@ -152,13 +156,14 @@ test_failure=0
 test_count=0
 test_fixed=0
 test_broken=0
+test_success=0
 
 die () {
        echo >&5 "FATAL: Unexpected exit with code $?"
        exit 1
 }
 
-trap 'die' exit
+trap 'die' EXIT
 
 # The semantics of the editor variables are that of invoking
 # sh -c "$EDITOR \"$@\"" files ...
@@ -188,11 +193,37 @@ test_tick () {
        export GIT_COMMITTER_DATE GIT_AUTHOR_DATE
 }
 
+# Call test_commit with the arguments "<message> [<file> [<contents>]]"
+#
+# This will commit a file with the given contents and the given commit
+# message.  It will also add a tag with <message> as name.
+#
+# Both <file> and <contents> default to <message>.
+
+test_commit () {
+       file=${2:-"$1.t"}
+       echo "${3-$1}" > "$file" &&
+       git add "$file" &&
+       test_tick &&
+       git commit -m "$1" &&
+       git tag "$1"
+}
+
+# Call test_merge with the arguments "<message> <commit>", where <commit>
+# can be a tag pointing to the commit-to-merge.
+
+test_merge () {
+       test_tick &&
+       git merge -m "$1" "$2" &&
+       git tag "$1"
+}
+
 # You are not expected to call test_ok_ and test_failure_ directly, use
 # the text_expect_* functions instead.
 
 test_ok_ () {
        test_count=$(expr "$test_count" + 1)
+       test_success=$(expr "$test_success" + 1)
        say_color "" "  ok $test_count: $@"
 }
 
@@ -202,7 +233,7 @@ test_failure_ () {
        say_color error "FAIL $test_count: $1"
        shift
        echo "$@" | sed -e 's/^/        /'
-       test "$immediate" = "" || { trap - exit; exit 1; }
+       test "$immediate" = "" || { trap - EXIT; exit 1; }
 }
 
 test_known_broken_ok_ () {
@@ -302,6 +333,64 @@ test_expect_code () {
        echo >&3 ""
 }
 
+# test_external runs external test scripts that provide continuous
+# test output about their progress, and succeeds/fails on
+# zero/non-zero exit code.  It outputs the test output on stdout even
+# in non-verbose mode, and announces the external script with "* run
+# <n>: ..." before running it.  When providing relative paths, keep in
+# mind that all scripts run in "trash directory".
+# Usage: test_external description command arguments...
+# Example: test_external 'Perl API' perl ../path/to/test.pl
+test_external () {
+       test "$#" -eq 3 ||
+       error >&5 "bug in the test script: not 3 parameters to test_external"
+       descr="$1"
+       shift
+       if ! test_skip "$descr" "$@"
+       then
+               # Announce the script to reduce confusion about the
+               # test output that follows.
+               say_color "" " run $(expr "$test_count" + 1): $descr ($*)"
+               # Run command; redirect its stderr to &4 as in
+               # test_run_, but keep its stdout on our stdout even in
+               # non-verbose mode.
+               "$@" 2>&4
+               if [ "$?" = 0 ]
+               then
+                       test_ok_ "$descr"
+               else
+                       test_failure_ "$descr" "$@"
+               fi
+       fi
+}
+
+# Like test_external, but in addition tests that the command generated
+# no output on stderr.
+test_external_without_stderr () {
+       # The temporary file has no (and must have no) security
+       # implications.
+       tmp="$TMPDIR"; if [ -z "$tmp" ]; then tmp=/tmp; fi
+       stderr="$tmp/git-external-stderr.$$.tmp"
+       test_external "$@" 4> "$stderr"
+       [ -f "$stderr" ] || error "Internal error: $stderr disappeared."
+       descr="no stderr: $1"
+       shift
+       say >&3 "expecting no stderr from previous command"
+       if [ ! -s "$stderr" ]; then
+               rm "$stderr"
+               test_ok_ "$descr"
+       else
+               if [ "$verbose" = t ]; then
+                       output=`echo; echo Stderr is:; cat "$stderr"`
+               else
+                       output=
+               fi
+               # rm first in case test_failure exits.
+               rm "$stderr"
+               test_failure_ "$descr" "$@" "$output"
+       fi
+}
+
 # This is not among top-level (test_expect_success | test_expect_failure)
 # but is a prefix that can be used in the test script, like:
 #
@@ -316,7 +405,7 @@ test_expect_code () {
 
 test_must_fail () {
        "$@"
-       test $? -gt 0 -a $? -le 129
+       test $? -gt 0 -a $? -le 129 -o $? -gt 192
 }
 
 # test_cmp is a helper function to compare actual and expected output.
@@ -343,16 +432,26 @@ test_create_repo () {
        error "bug in the test script: not 1 parameter to test-create-repo"
        owd=`pwd`
        repo="$1"
-       mkdir "$repo"
+       mkdir -p "$repo"
        cd "$repo" || error "Cannot setup test environment"
-       "$GIT_EXEC_PATH/git" init "--template=$GIT_EXEC_PATH/templates/blt/" >/dev/null 2>&1 ||
+       "$GIT_EXEC_PATH/git" init "--template=$GIT_EXEC_PATH/templates/blt/" >&3 2>&4 ||
        error "cannot run git init -- have you built things yet?"
        mv .git/hooks .git/hooks-disabled
        cd "$owd"
 }
 
 test_done () {
-       trap - exit
+       trap - EXIT
+       test_results_dir="$TEST_DIRECTORY/test-results"
+       mkdir -p "$test_results_dir"
+       test_results_path="$test_results_dir/${0%-*}-$$"
+
+       echo "total $test_count" >> $test_results_path
+       echo "success $test_success" >> $test_results_path
+       echo "fixed $test_fixed" >> $test_results_path
+       echo "broken $test_broken" >> $test_results_path
+       echo "failed $test_failure" >> $test_results_path
+       echo "" >> $test_results_path
 
        if test "$test_fixed" != 0
        then
@@ -367,15 +466,12 @@ test_done () {
        fi
        case "$test_failure" in
        0)
-               # We could:
-               # cd .. && rm -fr 'trash directory'
-               # but that means we forbid any tests that use their own
-               # subdirectory from calling test_done without coming back
-               # to where they started from.
-               # The Makefile provided will clean this test area so
-               # we will leave things as they are.
-
                say_color pass "passed all $msg"
+
+               test -d "$remove_trash" &&
+               cd "$(dirname "$remove_trash")" &&
+               rm -rf "$(basename "$remove_trash")"
+
                exit 0 ;;
 
        *)
@@ -387,11 +483,11 @@ test_done () {
 
 # Test the binaries we have just built.  The tests are kept in
 # t/ subdirectory and are run in 'trash directory' subdirectory.
-PATH=$(pwd)/..:$PATH
+TEST_DIRECTORY=$(pwd)
+PATH=$TEST_DIRECTORY/..:$PATH
 GIT_EXEC_PATH=$(pwd)/..
 GIT_TEMPLATE_DIR=$(pwd)/../templates/blt
 unset GIT_CONFIG
-unset GIT_CONFIG_LOCAL
 GIT_CONFIG_NOSYSTEM=1
 GIT_CONFIG_NOGLOBAL=1
 export PATH GIT_EXEC_PATH GIT_TEMPLATE_DIR GIT_CONFIG_NOSYSTEM GIT_CONFIG_NOGLOBAL
@@ -411,9 +507,10 @@ fi
 . ../GIT-BUILD-OPTIONS
 
 # Test repository
-test="trash directory"
+test="trash directory.$(basename "$0" .sh)"
+test ! -z "$debug" || remove_trash="$TEST_DIRECTORY/$test"
 rm -fr "$test" || {
-       trap - exit
+       trap - EXIT
        echo >&5 "FATAL: Cannot prepare test area"
        exit 1
 }