range-diff: allow to diff files regardless of submodule config
[gitweb.git] / t / test-lib-functions.sh
index 8a8a9329eeaa322121ecdbb3cd1f5fa6c9ecc94c..78d8c3783bd301a3dd2bf7061f04e08368d7ca37 100644 (file)
@@ -42,6 +42,8 @@ test_decode_color () {
                function name(n) {
                        if (n == 0) return "RESET";
                        if (n == 1) return "BOLD";
+                       if (n == 2) return "FAINT";
+                       if (n == 3) return "ITALIC";
                        if (n == 7) return "REVERSE";
                        if (n == 30) return "BLACK";
                        if (n == 31) return "RED";
@@ -145,12 +147,28 @@ test_pause () {
        "$SHELL_PATH" <&6 >&5 2>&7
 }
 
-# Wrap git in gdb. Adding this to a command can make it easier to
-# understand what is going on in a failing test.
+# Wrap git with a debugger. Adding this to a command can make it easier
+# to understand what is going on in a failing test.
 #
-# Example: "debug git checkout master".
+# Examples:
+#     debug git checkout master
+#     debug --debugger=nemiver git $ARGS
+#     debug -d "valgrind --tool=memcheck --track-origins=yes" git $ARGS
 debug () {
-        GIT_TEST_GDB=1 "$@" <&6 >&5 2>&7
+       case "$1" in
+       -d)
+               GIT_DEBUGGER="$2" &&
+               shift 2
+               ;;
+       --debugger=*)
+               GIT_DEBUGGER="${1#*=}" &&
+               shift 1
+               ;;
+       *)
+               GIT_DEBUGGER=1
+               ;;
+       esac &&
+       GIT_DEBUGGER="${GIT_DEBUGGER}" "$@" <&6 >&5 2>&7
 }
 
 # Call test_commit with the arguments
@@ -278,8 +296,20 @@ write_script () {
 # The single parameter is the prerequisite tag (a simple word, in all
 # capital letters by convention).
 
+test_unset_prereq () {
+       ! test_have_prereq "$1" ||
+       satisfied_prereq="${satisfied_prereq% $1 *} ${satisfied_prereq#* $1 }"
+}
+
 test_set_prereq () {
-       satisfied_prereq="$satisfied_prereq$1 "
+       case "$1" in
+       !*)
+               test_unset_prereq "${1#!}"
+               ;;
+       *)
+               satisfied_prereq="$satisfied_prereq$1 "
+               ;;
+       esac
 }
 satisfied_prereq=" "
 lazily_testable_prereq= lazily_tested_prereq=
@@ -537,6 +567,14 @@ test_path_is_dir () {
        fi
 }
 
+test_path_exists () {
+       if ! test -e "$1"
+       then
+               echo "Path $1 doesn't exist. $2"
+               false
+       fi
+}
+
 # Check if the directory exists and is empty as expected, barf otherwise.
 test_dir_is_empty () {
        test_path_is_dir "$1" &&
@@ -629,30 +667,30 @@ test_must_fail () {
                _test_ok=
                ;;
        esac
-       "$@"
+       "$@" 2>&7
        exit_code=$?
        if test $exit_code -eq 0 && ! list_contains "$_test_ok" success
        then
-               echo >&2 "test_must_fail: command succeeded: $*"
+               echo >&4 "test_must_fail: command succeeded: $*"
                return 1
        elif test_match_signal 13 $exit_code && list_contains "$_test_ok" sigpipe
        then
                return 0
        elif test $exit_code -gt 129 && test $exit_code -le 192
        then
-               echo >&2 "test_must_fail: died by signal $(($exit_code - 128)): $*"
+               echo >&4 "test_must_fail: died by signal $(($exit_code - 128)): $*"
                return 1
        elif test $exit_code -eq 127
        then
-               echo >&2 "test_must_fail: command not found: $*"
+               echo >&4 "test_must_fail: command not found: $*"
                return 1
        elif test $exit_code -eq 126
        then
-               echo >&2 "test_must_fail: valgrind error: $*"
+               echo >&4 "test_must_fail: valgrind error: $*"
                return 1
        fi
        return 0
-}
+} 7>&2 2>&4
 
 # Similar to test_must_fail, but tolerates success, too.  This is
 # meant to be used in contexts like:
@@ -668,8 +706,8 @@ test_must_fail () {
 # Accepts the same options as test_must_fail.
 
 test_might_fail () {
-       test_must_fail ok=success "$@"
-}
+       test_must_fail ok=success "$@" 2>&7
+} 7>&2 2>&4
 
 # Similar to test_must_fail and test_might_fail, but check that a
 # given command exited with a given exit code. Meant to be used as:
@@ -681,16 +719,16 @@ test_might_fail () {
 test_expect_code () {
        want_code=$1
        shift
-       "$@"
+       "$@" 2>&7
        exit_code=$?
        if test $exit_code = $want_code
        then
                return 0
        fi
 
-       echo >&2 "test_expect_code: command exited with $exit_code, we wanted $want_code $*"
+       echo >&4 "test_expect_code: command exited with $exit_code, we wanted $want_code $*"
        return 1
-}
+} 7>&2 2>&4
 
 # test_cmp is a helper function to compare actual and expected output.
 # You can use it like:
@@ -752,18 +790,18 @@ test_i18ngrep () {
                shift
                ! grep "$@" && return 0
 
-               echo >&2 "error: '! grep $@' did find a match in:"
+               echo >&4 "error: '! grep $@' did find a match in:"
        else
                grep "$@" && return 0
 
-               echo >&2 "error: 'grep $@' didn't find a match in:"
+               echo >&4 "error: 'grep $@' didn't find a match in:"
        fi
 
        if test -s "$last_arg"
        then
-               cat >&2 "$last_arg"
+               cat >&4 "$last_arg"
        else
-               echo >&2 "<File '$last_arg' is empty>"
+               echo >&4 "<File '$last_arg' is empty>"
        fi
 
        return 1
@@ -774,7 +812,7 @@ test_i18ngrep () {
 # not output anything when they fail.
 verbose () {
        "$@" && return 0
-       echo >&2 "command failed: $(git rev-parse --sq-quote "$@")"
+       echo >&4 "command failed: $(git rev-parse --sq-quote "$@")"
        return 1
 }
 
@@ -782,6 +820,7 @@ verbose () {
 # otherwise.
 
 test_must_be_empty () {
+       test_path_is_file "$1" &&
        if test -s "$1"
        then
                echo "'$1' is not empty, it contains:"
@@ -892,8 +931,8 @@ test_write_lines () {
 }
 
 perl () {
-       command "$PERL_PATH" "$@"
-}
+       command "$PERL_PATH" "$@" 2>&7
+} 7>&2 2>&4
 
 # Is the value one of the various ways to spell a boolean true/false?
 test_normalize_bool () {
@@ -1033,13 +1072,13 @@ test_env () {
                                shift
                                ;;
                        *)
-                               "$@"
+                               "$@" 2>&7
                                exit
                                ;;
                        esac
                done
        )
-}
+} 7>&2 2>&4
 
 # Returns true if the numeric exit code in "$2" represents the expected signal
 # in "$1". Signals should be given numerically.
@@ -1081,9 +1120,9 @@ nongit () {
                GIT_CEILING_DIRECTORIES=$(pwd) &&
                export GIT_CEILING_DIRECTORIES &&
                cd non-repo &&
-               "$@"
+               "$@" 2>&7
        )
-}
+} 7>&2 2>&4
 
 # convert stdin to pktline representation; note that empty input becomes an
 # empty packet, not a flush packet (for that you can just print 0000 yourself).
@@ -1118,3 +1157,72 @@ depacketize () {
                }
        '
 }
+
+# Set the hash algorithm in use to $1.  Only useful when testing the testsuite.
+test_set_hash () {
+       test_hash_algo="$1"
+}
+
+# Detect the hash algorithm in use.
+test_detect_hash () {
+       # Currently we only support SHA-1, but in the future this function will
+       # actually detect the algorithm in use.
+       test_hash_algo='sha1'
+}
+
+# Load common hash metadata and common placeholder object IDs for use with
+# test_oid.
+test_oid_init () {
+       test -n "$test_hash_algo" || test_detect_hash &&
+       test_oid_cache <"$TEST_DIRECTORY/oid-info/hash-info" &&
+       test_oid_cache <"$TEST_DIRECTORY/oid-info/oid"
+}
+
+# Load key-value pairs from stdin suitable for use with test_oid.  Blank lines
+# and lines starting with "#" are ignored.  Keys must be shell identifier
+# characters.
+#
+# Examples:
+# rawsz sha1:20
+# rawsz sha256:32
+test_oid_cache () {
+       local tag rest k v &&
+
+       { test -n "$test_hash_algo" || test_detect_hash; } &&
+       while read tag rest
+       do
+               case $tag in
+               \#*)
+                       continue;;
+               ?*)
+                       # non-empty
+                       ;;
+               *)
+                       # blank line
+                       continue;;
+               esac &&
+
+               k="${rest%:*}" &&
+               v="${rest#*:}" &&
+
+               if ! expr "$k" : '[a-z0-9][a-z0-9]*$' >/dev/null
+               then
+                       error 'bug in the test script: bad hash algorithm'
+               fi &&
+               eval "test_oid_${k}_$tag=\"\$v\""
+       done
+}
+
+# Look up a per-hash value based on a key ($1).  The value must have been loaded
+# by test_oid_init or test_oid_cache.
+test_oid () {
+       local var="test_oid_${test_hash_algo}_$1" &&
+
+       # If the variable is unset, we must be missing an entry for this
+       # key-hash pair, so exit with an error.
+       if eval "test -z \"\${$var+set}\""
+       then
+               error "bug in the test script: undefined key '$1'" >&2
+       fi &&
+       eval "printf '%s' \"\${$var}\""
+}