Code

Merge branch 'jc/cache-tree'
[git.git] / t / test-lib.sh
index 7ff75644c056f8fc9ea3017ca369e6f58161f4e5..5fdc5d94a20cfcf231bf23590784c5146a3e44bc 100644 (file)
@@ -115,7 +115,7 @@ do
        --tee)
                shift ;; # was handled already
        *)
-               break ;;
+               echo "error: unknown test option '$1'" >&2; exit 1 ;;
        esac
 done
 
@@ -147,7 +147,7 @@ fi
 
 error () {
        say_color error "error: $*"
-       trap - EXIT
+       GIT_EXIT_OK=t
        exit 1
 }
 
@@ -179,10 +179,17 @@ test_broken=0
 test_success=0
 
 die () {
-       echo >&5 "FATAL: Unexpected exit with code $?"
-       exit 1
+       code=$?
+       if test -n "$GIT_EXIT_OK"
+       then
+               exit $code
+       else
+               echo >&5 "FATAL: Unexpected exit with code $code"
+               exit 1
+       fi
 }
 
+GIT_EXIT_OK=
 trap 'die' EXIT
 
 # The semantics of the editor variables are that of invoking
@@ -247,6 +254,31 @@ test_chmod () {
        git update-index --add "--chmod=$@"
 }
 
+# Use test_set_prereq to tell that a particular prerequisite is available.
+# The prerequisite can later be checked for in two ways:
+#
+# - Explicitly using test_have_prereq.
+#
+# - Implicitly by specifying the prerequisite tag in the calls to
+#   test_expect_{success,failure,code}.
+#
+# The single parameter is the prerequisite tag (a simple word, in all
+# capital letters by convention).
+
+test_set_prereq () {
+       satisfied="$satisfied$1 "
+}
+satisfied=" "
+
+test_have_prereq () {
+       case $satisfied in
+       *" $1 "*)
+               : yes, have it ;;
+       *)
+               ! : nope ;;
+       esac
+}
+
 # You are not expected to call test_ok_ and test_failure_ directly, use
 # the text_expect_* functions instead.
 
@@ -260,7 +292,7 @@ test_failure_ () {
        say_color error "FAIL $test_count: $1"
        shift
        echo "$@" | sed -e 's/^/        /'
-       test "$immediate" = "" || { trap - EXIT; exit 1; }
+       test "$immediate" = "" || { GIT_EXIT_OK=t; exit 1; }
 }
 
 test_known_broken_ok_ () {
@@ -293,6 +325,11 @@ test_skip () {
                        to_skip=t
                esac
        done
+       if test -z "$to_skip" && test -n "$prereq" &&
+          ! test_have_prereq "$prereq"
+       then
+               to_skip=t
+       fi
        case "$to_skip" in
        t)
                say_color skip >&3 "skipping test: $@"
@@ -306,8 +343,9 @@ test_skip () {
 }
 
 test_expect_failure () {
+       test "$#" = 3 && { prereq=$1; shift; } || prereq=
        test "$#" = 2 ||
-       error "bug in the test script: not 2 parameters to test-expect-failure"
+       error "bug in the test script: not 2 or 3 parameters to test-expect-failure"
        if ! test_skip "$@"
        then
                say >&3 "checking known breakage: $2"
@@ -316,15 +354,16 @@ test_expect_failure () {
                then
                        test_known_broken_ok_ "$1"
                else
-                   test_known_broken_failure_ "$1"
+                       test_known_broken_failure_ "$1"
                fi
        fi
        echo >&3 ""
 }
 
 test_expect_success () {
+       test "$#" = 3 && { prereq=$1; shift; } || prereq=
        test "$#" = 2 ||
-       error "bug in the test script: not 2 parameters to test-expect-success"
+       error "bug in the test script: not 2 or 3 parameters to test-expect-success"
        if ! test_skip "$@"
        then
                say >&3 "expecting success: $2"
@@ -340,8 +379,9 @@ test_expect_success () {
 }
 
 test_expect_code () {
+       test "$#" = 4 && { prereq=$1; shift; } || prereq=
        test "$#" = 3 ||
-       error "bug in the test script: not 3 parameters to test-expect-code"
+       error "bug in the test script: not 3 or 4 parameters to test-expect-code"
        if ! test_skip "$@"
        then
                say >&3 "expecting exit code $1: $3"
@@ -365,8 +405,9 @@ test_expect_code () {
 # 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"
+       test "$#" = 4 && { prereq=$1; shift; } || prereq=
+       test "$#" = 3 ||
+       error >&5 "bug in the test script: not 3 or 4 parameters to test_external"
        descr="$1"
        shift
        if ! test_skip "$descr" "$@"
@@ -457,14 +498,14 @@ test_create_repo () {
        repo="$1"
        mkdir -p "$repo"
        cd "$repo" || error "Cannot setup test environment"
-       "$GIT_EXEC_PATH/git-init" "--template=$owd/../templates/blt/" >&3 2>&4 ||
+       "$GIT_EXEC_PATH/git-init" "--template=$TEST_DIRECTORY/../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
+       GIT_EXIT_OK=t
        test_results_dir="$TEST_DIRECTORY/test-results"
        mkdir -p "$test_results_dir"
        test_results_path="$test_results_dir/${0%.sh}-$$"
@@ -489,14 +530,6 @@ 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" &&
@@ -614,7 +647,7 @@ fi
 test="trash directory.$(basename "$0" .sh)"
 test ! -z "$debug" || remove_trash="$TEST_DIRECTORY/$test"
 rm -fr "$test" || {
-       trap - EXIT
+       GIT_EXIT_OK=t
        echo >&5 "FATAL: Cannot prepare test area"
        exit 1
 }
@@ -643,3 +676,37 @@ do
                test_done
        esac
 done
+
+# Fix some commands on Windows
+case $(uname -s) in
+*MINGW*)
+       # Windows has its own (incompatible) sort and find
+       sort () {
+               /usr/bin/sort "$@"
+       }
+       find () {
+               /usr/bin/find "$@"
+       }
+       sum () {
+               md5sum "$@"
+       }
+       # git sees Windows-style pwd
+       pwd () {
+               builtin pwd -W
+       }
+       # no POSIX permissions
+       # backslashes in pathspec are converted to '/'
+       # exec does not inherit the PID
+       ;;
+*)
+       test_set_prereq POSIXPERM
+       test_set_prereq BSLASHPSPEC
+       test_set_prereq EXECKEEPSPID
+       ;;
+esac
+
+test -z "$NO_PERL" && test_set_prereq PERL
+
+# test whether the filesystem supports symbolic links
+ln -s x y 2>/dev/null && test -h y 2>/dev/null && test_set_prereq SYMLINKS
+rm -f y