]> asedeno.scripts.mit.edu Git - git.git/blobdiff - t/test-lib.sh
fast-import: export correctly marks larger than 2^20-1
[git.git] / t / test-lib.sh
index f2ca5364722e9c85a23bdfdcf1e24122fd5e3a0f..e8f21d577ce4da474e2a9545a667ff5dc6dc145f 100644 (file)
@@ -2,6 +2,18 @@
 #
 # Copyright (c) 2005 Junio C Hamano
 #
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see http://www.gnu.org/licenses/ .
 
 # if --tee was passed, write the output not only to the terminal, but
 # additionally to the file test-results/$BASENAME.out, too.
@@ -30,7 +42,7 @@ TZ=UTC
 TERM=dumb
 export LANG LC_ALL PAGER TERM TZ
 EDITOR=:
-VISUAL=:
+unset VISUAL
 unset GIT_EDITOR
 unset AUTHOR_DATE
 unset AUTHOR_EMAIL
@@ -54,17 +66,22 @@ unset GIT_OBJECT_DIRECTORY
 unset GIT_CEILING_DIRECTORIES
 unset SHA1_FILE_DIRECTORIES
 unset SHA1_FILE_DIRECTORY
+unset GIT_NOTES_REF
+unset GIT_NOTES_DISPLAY_REF
+unset GIT_NOTES_REWRITE_REF
+unset GIT_NOTES_REWRITE_MODE
 GIT_MERGE_VERBOSITY=5
 export GIT_MERGE_VERBOSITY
 export GIT_AUTHOR_EMAIL GIT_AUTHOR_NAME
 export GIT_COMMITTER_EMAIL GIT_COMMITTER_NAME
-export EDITOR VISUAL
-GIT_TEST_CMP=${GIT_TEST_CMP:-diff -u}
+export EDITOR
 
 # Protect ourselves from common misconfiguration to export
 # CDPATH into the environment
 unset CDPATH
 
+unset GREP_OPTIONS
+
 case $(echo $GIT_TRACE |tr "[A-Z]" "[a-z]") in
        1|2|true)
                echo "* warning: Some tests will not work if GIT_TRACE" \
@@ -74,6 +91,12 @@ case $(echo $GIT_TRACE |tr "[A-Z]" "[a-z]") in
                ;;
 esac
 
+# Convenience
+#
+# A regexp to match 5 and 40 hexdigits
+_x05='[0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f]'
+_x40="$_x05$_x05$_x05$_x05$_x05$_x05$_x05$_x05"
+
 # Each test should start with something like this, after copyright notices:
 #
 # test_description='Description of this test...
@@ -104,12 +127,13 @@ do
        -v|--v|--ve|--ver|--verb|--verbo|--verbos|--verbose)
                verbose=t; shift ;;
        -q|--q|--qu|--qui|--quie|--quiet)
-               quiet=t; shift ;;
+               # Ignore --quiet under a TAP::Harness. Saying how many tests
+               # passed without the ok/not ok details is always an error.
+               test -z "$HARNESS_ACTIVE" && quiet=t; shift ;;
+       --with-dashes)
+               with_dashes=t; shift ;;
        --no-color)
                color=; shift ;;
-       --no-python)
-               # noop now...
-               shift ;;
        --va|--val|--valg|--valgr|--valgri|--valgrin|--valgrind)
                valgrind=t; verbose=t; shift ;;
        --tee)
@@ -135,7 +159,7 @@ if test -n "$color"; then
                        *) test -n "$quiet" && return;;
                esac
                shift
-               printf "%s" "$*"
+               printf "%s" "$*"
                tput sgr0
                echo
                )
@@ -144,7 +168,7 @@ else
        say_color() {
                test -z "$1" && test -n "$quiet" && return
                shift
-               echo "$*"
+               echo "$*"
        }
 fi
 
@@ -181,6 +205,8 @@ test_fixed=0
 test_broken=0
 test_success=0
 
+test_external_has_tap=0
+
 die () {
        code=$?
        if test -n "$GIT_EXIT_OK"
@@ -207,8 +233,35 @@ trap 'die' EXIT
 test_set_editor () {
        FAKE_EDITOR="$1"
        export FAKE_EDITOR
-       VISUAL='"$FAKE_EDITOR"'
-       export VISUAL
+       EDITOR='"$FAKE_EDITOR"'
+       export EDITOR
+}
+
+test_decode_color () {
+       sed     -e 's/.\[1m/<WHITE>/g' \
+               -e 's/.\[31m/<RED>/g' \
+               -e 's/.\[32m/<GREEN>/g' \
+               -e 's/.\[33m/<YELLOW>/g' \
+               -e 's/.\[34m/<BLUE>/g' \
+               -e 's/.\[35m/<MAGENTA>/g' \
+               -e 's/.\[36m/<CYAN>/g' \
+               -e 's/.\[m/<RESET>/g'
+}
+
+q_to_nul () {
+       perl -pe 'y/Q/\000/'
+}
+
+q_to_cr () {
+       tr Q '\015'
+}
+
+append_cr () {
+       sed -e 's/$/Q/' | tr Q '\015'
+}
+
+remove_cr () {
+       tr '\015' Q | sed -e 's/Q$//'
 }
 
 test_tick () {
@@ -287,25 +340,25 @@ test_have_prereq () {
 
 test_ok_ () {
        test_success=$(($test_success + 1))
-       say_color "" "  ok $test_count: $@"
+       say_color "" "ok $test_count - $@"
 }
 
 test_failure_ () {
        test_failure=$(($test_failure + 1))
-       say_color error "FAIL $test_count: $1"
+       say_color error "not ok - $test_count $1"
        shift
-       echo "$@" | sed -e 's/^/        /'
+       echo "$@" | sed -e 's/^/#       /'
        test "$immediate" = "" || { GIT_EXIT_OK=t; exit 1; }
 }
 
 test_known_broken_ok_ () {
        test_fixed=$(($test_fixed+1))
-       say_color "" "  FIXED $test_count: $@"
+       say_color "" "ok $test_count - $@ # TODO known breakage"
 }
 
 test_known_broken_failure_ () {
        test_broken=$(($test_broken+1))
-       say_color skip "  still broken $test_count: $@"
+       say_color skip "not ok $test_count - $@ # TODO known breakage"
 }
 
 test_debug () {
@@ -313,8 +366,13 @@ test_debug () {
 }
 
 test_run_ () {
+       test_cleanup=:
        eval >&3 2>&4 "$1"
-       eval_ret="$?"
+       eval_ret=$?
+       eval >&3 2>&4 "$test_cleanup"
+       if test "$verbose" = "t" && test -n "$HARNESS_ACTIVE"; then
+               echo ""
+       fi
        return 0
 }
 
@@ -326,6 +384,7 @@ test_skip () {
                case $this_test.$test_count in
                $skp)
                        to_skip=t
+                       break
                esac
        done
        if test -z "$to_skip" && test -n "$prereq" &&
@@ -336,7 +395,7 @@ test_skip () {
        case "$to_skip" in
        t)
                say_color skip >&3 "skipping test: $@"
-               say_color skip "skip $test_count: $1"
+               say_color skip "ok $test_count # skip $1"
                : true
                ;;
        *)
@@ -402,7 +461,7 @@ test_expect_code () {
 # 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
+# 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...
@@ -417,16 +476,29 @@ test_external () {
        then
                # Announce the script to reduce confusion about the
                # test output that follows.
-               say_color "" " run $test_count: $descr ($*)"
+               say_color "" "# run $test_count: $descr ($*)"
+               # Export TEST_DIRECTORY, TRASH_DIRECTORY and GIT_TEST_LONG
+               # to be able to use them in script
+               export TEST_DIRECTORY TRASH_DIRECTORY GIT_TEST_LONG
                # 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"
+                       if test $test_external_has_tap -eq 0; then
+                               test_ok_ "$descr"
+                       else
+                               say_color "" "# test_external test $descr was ok"
+                               test_success=$(($test_success + 1))
+                       fi
                else
-                       test_failure_ "$descr" "$@"
+                       if test $test_external_has_tap -eq 0; then
+                               test_failure_ "$descr" "$@"
+                       else
+                               say_color error "# test_external test $descr failed: $@"
+                               test_failure=$(($test_failure + 1))
+                       fi
                fi
        fi
 }
@@ -442,19 +514,30 @@ test_external_without_stderr () {
        [ -f "$stderr" ] || error "Internal error: $stderr disappeared."
        descr="no stderr: $1"
        shift
-       say >&3 "expecting no stderr from previous command"
+       say >&3 "expecting no stderr from previous command"
        if [ ! -s "$stderr" ]; then
                rm "$stderr"
-               test_ok_ "$descr"
+
+               if test $test_external_has_tap -eq 0; then
+                       test_ok_ "$descr"
+               else
+                       say_color "" "# test_external_without_stderr test $descr was ok"
+                       test_success=$(($test_success + 1))
+               fi
        else
                if [ "$verbose" = t ]; then
-                       output=`echo; echo Stderr is:; cat "$stderr"`
+                       output=`echo; echo "# Stderr is:"; cat "$stderr"`
                else
                        output=
                fi
                # rm first in case test_failure exits.
                rm "$stderr"
-               test_failure_ "$descr" "$@" "$output"
+               if test $test_external_has_tap -eq 0; then
+                       test_failure_ "$descr" "$@" "$output"
+               else
+                       say_color error "# test_external_without_stderr test $descr failed: $@: $output"
+                       test_failure=$(($test_failure + 1))
+               fi
        fi
 }
 
@@ -475,6 +558,22 @@ test_must_fail () {
        test $? -gt 0 -a $? -le 129 -o $? -gt 192
 }
 
+# Similar to test_must_fail, but tolerates success, too.  This is
+# meant to be used in contexts like:
+#
+#      test_expect_success 'some command works without configuration' '
+#              test_might_fail git config --unset all.configuration &&
+#              do something
+#      '
+#
+# Writing "git config --unset all.configuration || :" would be wrong,
+# because we want to notice if it fails due to segv.
+
+test_might_fail () {
+       "$@"
+       test $? -ge 0 -a $? -le 129 -o $? -gt 192
+}
+
 # test_cmp is a helper function to compare actual and expected output.
 # You can use it like:
 #
@@ -492,6 +591,31 @@ test_cmp() {
        $GIT_TEST_CMP "$@"
 }
 
+# This function can be used to schedule some commands to be run
+# unconditionally at the end of the test to restore sanity:
+#
+#      test_expect_success 'test core.capslock' '
+#              git config core.capslock true &&
+#              test_when_finished "git config --unset core.capslock" &&
+#              hello world
+#      '
+#
+# That would be roughly equivalent to
+#
+#      test_expect_success 'test core.capslock' '
+#              git config core.capslock true &&
+#              hello world
+#              git config --unset core.capslock
+#      '
+#
+# except that the greeting and config --unset must both succeed for
+# the test to pass.
+
+test_when_finished () {
+       test_cleanup="{ $*
+               } && (exit \"\$eval_ret\"); eval_ret=\$?; $test_cleanup"
+}
+
 # Most tests can use the created repository, but some may need to create more.
 # Usage: test_create_repo <directory>
 test_create_repo () {
@@ -511,7 +635,7 @@ test_done () {
        GIT_EXIT_OK=t
        test_results_dir="$TEST_DIRECTORY/test-results"
        mkdir -p "$test_results_dir"
-       test_results_path="$test_results_dir/${0%.sh}-$$"
+       test_results_path="$test_results_dir/${0%.sh}-$$.counts"
 
        echo "total $test_count" >> $test_results_path
        echo "success $test_success" >> $test_results_path
@@ -522,18 +646,24 @@ test_done () {
 
        if test "$test_fixed" != 0
        then
-               say_color pass "fixed $test_fixed known breakage(s)"
+               say_color pass "fixed $test_fixed known breakage(s)"
        fi
        if test "$test_broken" != 0
        then
-               say_color error "still have $test_broken known breakage(s)"
+               say_color error "still have $test_broken known breakage(s)"
                msg="remaining $(($test_count-$test_broken)) test(s)"
        else
                msg="$test_count test(s)"
        fi
        case "$test_failure" in
        0)
-               say_color pass "passed all $msg"
+               # Maybe print SKIP message
+               [ -z "$skip_all" ] || skip_all=" # SKIP $skip_all"
+
+               if test $test_external_has_tap -eq 0; then
+                       say_color pass "# passed all $msg"
+                       say "1..$test_count$skip_all"
+               fi
 
                test -d "$remove_trash" &&
                cd "$(dirname "$remove_trash")" &&
@@ -542,7 +672,11 @@ test_done () {
                exit 0 ;;
 
        *)
-               say_color error "failed $test_failure among $msg"
+               if test $test_external_has_tap -eq 0; then
+                       say_color error "# failed $test_failure among $msg"
+                       say "1..$test_count"
+               fi
+
                exit 1 ;;
 
        esac
@@ -551,19 +685,8 @@ test_done () {
 # Test the binaries we have just built.  The tests are kept in
 # t/ subdirectory and are run in 'trash directory' subdirectory.
 TEST_DIRECTORY=$(pwd)
-if test -z "$valgrind"
+if test -n "$valgrind"
 then
-       if test -z "$GIT_TEST_INSTALLED"
-       then
-               PATH=$TEST_DIRECTORY/..:$PATH
-               GIT_EXEC_PATH=$TEST_DIRECTORY/..
-       else
-               GIT_EXEC_PATH=$($GIT_TEST_INSTALLED/git --exec-path)  ||
-               error "Cannot run git from $GIT_TEST_INSTALLED."
-               PATH=$GIT_TEST_INSTALLED:$TEST_DIRECTORY/..:$PATH
-               GIT_EXEC_PATH=${GIT_TEST_EXEC_PATH:-$GIT_EXEC_PATH}
-       fi
-else
        make_symlink () {
                test -h "$2" &&
                test "$1" = "$(readlink "$2")" || {
@@ -625,6 +748,24 @@ else
        PATH=$GIT_VALGRIND/bin:$PATH
        GIT_EXEC_PATH=$GIT_VALGRIND/bin
        export GIT_VALGRIND
+elif test -n "$GIT_TEST_INSTALLED" ; then
+       GIT_EXEC_PATH=$($GIT_TEST_INSTALLED/git --exec-path)  ||
+       error "Cannot run git from $GIT_TEST_INSTALLED."
+       PATH=$GIT_TEST_INSTALLED:$TEST_DIRECTORY/..:$PATH
+       GIT_EXEC_PATH=${GIT_TEST_EXEC_PATH:-$GIT_EXEC_PATH}
+else # normal case, use ../bin-wrappers only unless $with_dashes:
+       git_bin_dir="$TEST_DIRECTORY/../bin-wrappers"
+       if ! test -x "$git_bin_dir/git" ; then
+               if test -z "$with_dashes" ; then
+                       say "$git_bin_dir/git is not executable; using GIT_EXEC_PATH"
+               fi
+               with_dashes=t
+       fi
+       PATH="$git_bin_dir:$PATH"
+       GIT_EXEC_PATH=$TEST_DIRECTORY/..
+       if test -n "$with_dashes" ; then
+               PATH="$TEST_DIRECTORY/..:$PATH"
+       fi
 fi
 GIT_TEMPLATE_DIR=$(pwd)/../templates/blt
 unset GIT_CONFIG
@@ -632,20 +773,39 @@ GIT_CONFIG_NOSYSTEM=1
 GIT_CONFIG_NOGLOBAL=1
 export PATH GIT_EXEC_PATH GIT_TEMPLATE_DIR GIT_CONFIG_NOSYSTEM GIT_CONFIG_NOGLOBAL
 
+. ../GIT-BUILD-OPTIONS
+
+if test -z "$GIT_TEST_CMP"
+then
+       if test -n "$GIT_TEST_CMP_USE_COPIED_CONTEXT"
+       then
+               GIT_TEST_CMP="$DIFF -c"
+       else
+               GIT_TEST_CMP="$DIFF -u"
+       fi
+fi
+
 GITPERLLIB=$(pwd)/../perl/blib/lib:$(pwd)/../perl/blib/arch/auto/Git
 export GITPERLLIB
 test -d ../templates/blt || {
        error "You haven't built things yet, have you?"
 }
 
+if test -z "$GIT_TEST_INSTALLED" && test -z "$NO_PYTHON"
+then
+       GITPYTHONLIB="$(pwd)/../git_remote_helpers/build/lib"
+       export GITPYTHONLIB
+       test -d ../git_remote_helpers/build || {
+               error "You haven't built git_remote_helpers yet, have you?"
+       }
+fi
+
 if ! test -x ../test-chmtime; then
        echo >&2 'You need to build test-chmtime:'
        echo >&2 'Run "make test-chmtime" in the source (toplevel) directory'
        exit 1
 fi
 
-. ../GIT-BUILD-OPTIONS
-
 # Test repository
 test="trash directory.$(basename "$0" .sh)"
 test -n "$root" && test="$root/$test"
@@ -669,18 +829,10 @@ this_test=${0##*/}
 this_test=${this_test%%-*}
 for skp in $GIT_SKIP_TESTS
 do
-       to_skip=
-       for skp in $GIT_SKIP_TESTS
-       do
-               case "$this_test" in
-               $skp)
-                       to_skip=t
-               esac
-       done
-       case "$to_skip" in
-       t)
+       case "$this_test" in
+       $skp)
                say_color skip >&3 "skipping test $this_test altogether"
-               say_color skip "skip all tests in $this_test"
+               skip_all="skip all tests in $this_test"
                test_done
        esac
 done
@@ -729,6 +881,7 @@ case $(uname -s) in
 esac
 
 test -z "$NO_PERL" && test_set_prereq PERL
+test -z "$NO_PYTHON" && test_set_prereq PYTHON
 
 # test whether the filesystem supports symbolic links
 ln -s x y 2>/dev/null && test -h y 2>/dev/null && test_set_prereq SYMLINKS