# You should have received a copy of the GNU General Public License
# along with this program. If not, see http://www.gnu.org/licenses/ .
-# Keep the original TERM for say_color
-ORIGINAL_TERM=$TERM
-
# Test the binaries we have just built. The tests are kept in
# t/ subdirectory and are run in 'trash directory' subdirectory.
if test -z "$TEST_DIRECTORY"
esac
# For repeatability, reset the environment to known value.
+# TERM is sanitized below, after saving color control sequences.
LANG=C
LC_ALL=C
PAGER=cat
TZ=UTC
-TERM=dumb
-export LANG LC_ALL PAGER TERM TZ
+export LANG LC_ALL PAGER TZ
EDITOR=:
# A call to "unset" with no arguments causes at least Solaris 10
# /usr/xpg4/bin/sh and /bin/ksh to bail out. So keep the unsets
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"
}
fi
+: ${ASAN_OPTIONS=detect_leaks=0}
+export ASAN_OPTIONS
+
# Protect ourselves from common misconfiguration to export
# CDPATH into the environment
unset CDPATH
case $(echo $GIT_TRACE |tr "[A-Z]" "[a-z]") in
1|2|true)
- echo "* warning: Some tests will not work if GIT_TRACE" \
- "is set as to trace on STDERR ! *"
- echo "* warning: Please set GIT_TRACE to something" \
- "other than 1, 2 or true ! *"
+ GIT_TRACE=4
;;
esac
LF='
'
-export _x05 _x40 _z40 LF
+# UTF-8 ZERO WIDTH NON-JOINER, which HFS+ ignores
+# when case-folding filenames
+u200c=$(printf '\342\200\214')
+
+export _x05 _x40 _z40 LF u200c
# Each test should start with something like this, after copyright notices:
#
# This test checks if command xyzzy does the right thing...
# '
# . ./test-lib.sh
-[ "x$ORIGINAL_TERM" != "xdumb" ] && (
- TERM=$ORIGINAL_TERM &&
- export TERM &&
- [ -t 1 ] &&
+test "x$TERM" != "xdumb" && (
+ test -t 1 &&
tput bold >/dev/null 2>&1 &&
tput setaf 1 >/dev/null 2>&1 &&
tput sgr0 >/dev/null 2>&1
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=${1#--*=}; 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[^=]*=\(.*\)')
+ verbose_only=${1#--*=}
shift ;;
-q|--q|--qu|--qui|--quie|--quiet)
# Ignore --quiet under a TAP::Harness. Saying how many tests
valgrind=memcheck
shift ;;
--valgrind=*)
- valgrind=$(expr "z$1" : 'z[^=]*=\(.*\)')
+ valgrind=${1#--*=}
shift ;;
--valgrind-only=*)
- valgrind_only=$(expr "z$1" : 'z[^=]*=\(.*\)')
+ valgrind_only=${1#--*=}
shift ;;
--tee)
shift ;; # was handled already
--root=*)
- root=$(expr "z$1" : 'z[^=]*=\(.*\)')
+ root=${1#--*=}
+ shift ;;
+ --chain-lint)
+ GIT_TEST_CHAIN_LINT=1
+ shift ;;
+ --no-chain-lint)
+ GIT_TEST_CHAIN_LINT=0
+ shift ;;
+ -x)
+ trace=t
+ verbose=t
shift ;;
*)
echo "error: unknown test option '$1'" >&2; exit 1 ;;
if test -n "$color"
then
+ # Save the color control sequences now rather than run tput
+ # each time say_color() is called. This is done for two
+ # reasons:
+ # * TERM will be changed to dumb
+ # * HOME will be changed to a temporary directory and tput
+ # might need to read ~/.terminfo from the original HOME
+ # directory to get the control sequences
+ # Note: This approach assumes the control sequences don't end
+ # in a newline for any terminal of interest (command
+ # substitutions strip trailing newlines). Given that most
+ # (all?) terminals in common use are related to ECMA-48, this
+ # shouldn't be a problem.
+ say_color_error=$(tput bold; tput setaf 1) # bold red
+ say_color_skip=$(tput setaf 4) # blue
+ say_color_warn=$(tput setaf 3) # brown/yellow
+ say_color_pass=$(tput setaf 2) # green
+ say_color_info=$(tput setaf 6) # cyan
+ say_color_reset=$(tput sgr0)
+ say_color_="" # no formatting for normal text
say_color () {
- (
- TERM=$ORIGINAL_TERM
- export TERM
- case "$1" in
- error)
- tput bold; tput setaf 1;; # bold red
- skip)
- tput setaf 4;; # blue
- warn)
- tput setaf 3;; # brown/yellow
- pass)
- tput setaf 2;; # green
- info)
- tput setaf 6;; # cyan
- *)
- test -n "$quiet" && return;;
- esac
+ test -z "$1" && test -n "$quiet" && return
+ eval "say_color_color=\$say_color_$1"
shift
- printf "%s" "$*"
- tput sgr0
- echo
- )
+ printf "%s\\n" "$say_color_color$*$say_color_reset"
}
else
say_color() {
}
fi
+TERM=dumb
+export TERM
+
error () {
say_color error "error: $*"
GIT_EXIT_OK=t
exec 4>/dev/null 3>/dev/null
fi
+# Send any "-x" output directly to stderr to avoid polluting tests
+# which capture stderr. We can do this unconditionally since it
+# has no effect if tracing isn't turned on.
+#
+# Note that this sets up the trace fd as soon as we assign the variable, so it
+# must come after the creation of descriptor 4 above. Likewise, we must never
+# unset this, as it has the side effect of closing descriptor 4, which we
+# use to show verbose tests to the user.
+#
+# Note also that we don't need or want to export it. The tracing is local to
+# this shell, and we would not want to influence any shells we exec.
+BASH_XTRACEFD=4
+
test_failure=0
test_count=0
test_fixed=0
GIT_EXIT_OK=
trap 'die' EXIT
+trap 'exit $?' INT
# The user-facing functions are loaded from a separate file so that
# test_perf subshells can have them too
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
fi
}
+want_trace () {
+ test "$trace" = t && test "$verbose" = t
+}
+
+# This is a separate function because some tests use
+# "return" to end a test_expect_success block early
+# (and we want to make sure we run any cleanup like
+# "set +x").
+test_eval_inner_ () {
+ # Do not add anything extra (including LF) after '$*'
+ eval "
+ want_trace && set -x
+ $*"
+}
+
test_eval_ () {
- # This is a separate function because some tests use
- # "return" to end a test_expect_success block early.
- eval </dev/null >&3 2>&4 "$*"
+ # We run this block with stderr redirected to avoid extra cruft
+ # during a "-x" trace. Once in "set -x" mode, we cannot prevent
+ # the shell from printing the "set +x" to turn it off (nor the saving
+ # of $? before that). But we can make sure that the output goes to
+ # /dev/null.
+ #
+ # The test itself is run with stderr put back to &4 (so either to
+ # /dev/null, or to the original stderr if --verbose was used).
+ {
+ test_eval_inner_ "$@" </dev/null >&3 2>&4
+ test_eval_ret_=$?
+ if want_trace
+ then
+ set +x
+ if test "$test_eval_ret_" != 0
+ then
+ say_color error >&4 "error: last command exited with \$?=$test_eval_ret_"
+ fi
+ fi
+ } 2>/dev/null
+ return $test_eval_ret_
}
test_run_ () {
test_cleanup=:
expecting_failure=$2
+
+ if test "${GIT_TEST_CHAIN_LINT:-1}" != 0; then
+ # turn off tracing for this test-eval, as it simply creates
+ # confusing noise in the "-x" output
+ trace_tmp=$trace
+ trace=
+ # 117 is magic because it is unlikely to match the exit
+ # code of other programs
+ test_eval_ "(exit 117) && $1"
+ if test "$?" != 117; then
+ error "bug in the test script: broken &&-chain: $1"
+ fi
+ trace=$trace_tmp
+ fi
+
setup_malloc_check
test_eval_ "$1"
eval_ret=$?
teardown_malloc_check
- if test -z "$immediate" || test $eval_ret = 0 || test -n "$expecting_failure"
+ if test -z "$immediate" || test $eval_ret = 0 ||
+ test -n "$expecting_failure" && test "$test_cleanup" != ":"
then
setup_malloc_check
test_eval_ "$test_cleanup"
test_skip () {
to_skip=
+ 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
;;
*)
then
error "Can't use skip_all after running some tests"
fi
- [ -z "$skip_all" ] || skip_all=" # SKIP $skip_all"
+ test -z "$skip_all" || skip_all=" # SKIP $skip_all"
if test $test_external_has_tap -eq 0
then
}
HOME="$TRASH_DIRECTORY"
-export HOME
+GNUPGHOME="$HOME/gnupg-home-not-used"
+export HOME GNUPGHOME
if test -z "$TEST_NO_CREATE_REPO"
then
y="$*"
fi
- while echo "$y"
+ i=0
+ while test $i -lt 99
do
- :
+ echo "$y"
+ i=$(($i+1))
done
}
# backslashes in pathspec are converted to '/'
# exec does not inherit the PID
test_set_prereq MINGW
- test_set_prereq NOT_CYGWIN
+ test_set_prereq NATIVE_CRLF
test_set_prereq SED_STRIPS_CR
test_set_prereq GREP_STRIPS_CR
GIT_TEST_CMP=mingw_test_cmp
*CYGWIN*)
test_set_prereq POSIXPERM
test_set_prereq EXECKEEPSPID
- 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
test_set_prereq BSLASHPSPEC
test_set_prereq EXECKEEPSPID
- test_set_prereq NOT_MINGW
- test_set_prereq NOT_CYGWIN
;;
esac
test_lazy_prereq PIPE '
# test whether the filesystem supports FIFOs
case $(uname -s) in
- CYGWIN*)
+ CYGWIN*|MINGW*)
false
;;
*)
git var GIT_AUTHOR_IDENT
'
-# 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
+test_lazy_prereq EXPENSIVE '
+ test -n "$GIT_TEST_LONG"
+'
+
+test_lazy_prereq USR_BIN_TIME '
+ test -x /usr/bin/time
+'
+
+test_lazy_prereq NOT_ROOT '
+ uid=$(id -u) &&
+ test "$uid" != 0
+'
+
+# SANITY is about "can you correctly predict what the filesystem would
+# do by only looking at the permission bits of the files and
+# directories?" A typical example of !SANITY is running the test
+# suite as root, where a test may expect "chmod -r file && cat file"
+# to fail because file is supposed to be unreadable after a successful
+# chmod. In an environment (i.e. combination of what filesystem is
+# being used and who is running the tests) that lacks SANITY, you may
+# be able to delete or create a file when the containing directory
+# doesn't have write permissions, or access a file even if the
+# containing directory doesn't have read or execute permissions.
+
+test_lazy_prereq SANITY '
+ mkdir SANETESTD.1 SANETESTD.2 &&
+
+ chmod +w SANETESTD.1 SANETESTD.2 &&
+ >SANETESTD.1/x 2>SANETESTD.2/x &&
+ chmod -w SANETESTD.1 &&
+ chmod -r SANETESTD.1/x &&
+ chmod -rx SANETESTD.2 ||
+ error "bug in test sript: cannot prepare SANETESTD"
+
+ ! test -r SANETESTD.1/x &&
+ ! rm SANETESTD.1/x && ! test -f SANETESTD.2/x
+ status=$?
+
+ chmod +rwx SANETESTD.1 SANETESTD.2 &&
+ rm -rf SANETESTD.1 SANETESTD.2 ||
+ error "bug in test sript: cannot clean SANETESTD"
+ return $status
+'
GIT_UNZIP=${GIT_UNZIP:-unzip}
test_lazy_prereq UNZIP '
"$GIT_UNZIP" -v
test $? -ne 127
'
+
+run_with_limited_cmdline () {
+ (ulimit -s 128 && "$@")
+}
+
+test_lazy_prereq CMDLINE_LIMIT 'run_with_limited_cmdline true'