summaryrefslogtreecommitdiff
path: root/t/test-lib.sh
diff options
context:
space:
mode:
Diffstat (limited to 't/test-lib.sh')
-rw-r--r--t/test-lib.sh953
1 files changed, 638 insertions, 315 deletions
diff --git a/t/test-lib.sh b/t/test-lib.sh
index 44df51b..042f557 100644
--- a/t/test-lib.sh
+++ b/t/test-lib.sh
@@ -13,19 +13,26 @@
# 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/ .
+# along with this program. If not, see https://www.gnu.org/licenses/ .
# 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"
then
- # We allow tests to override this, in case they want to run tests
- # outside of t/, e.g. for running tests on the test library
- # itself.
- TEST_DIRECTORY=$(pwd)
-else
# ensure that TEST_DIRECTORY is an absolute path so that it
# is valid even if the current working directory is changed
+ TEST_DIRECTORY=$(pwd)
+else
+ # The TEST_DIRECTORY will always be the path to the "t"
+ # directory in the git.git checkout. This is overridden by
+ # e.g. t/lib-subtest.sh, but only because its $(pwd) is
+ # different. Those tests still set "$TEST_DIRECTORY" to the
+ # same path.
+ #
+ # See use of "$GIT_BUILD_DIR" and "$TEST_DIRECTORY" below for
+ # hard assumptions about "$GIT_BUILD_DIR/t" existing and being
+ # the "$TEST_DIRECTORY", and e.g. "$TEST_DIRECTORY/helper"
+ # needing to exist.
TEST_DIRECTORY=$(cd "$TEST_DIRECTORY" && pwd) || exit 1
fi
if test -z "$TEST_OUTPUT_DIRECTORY"
@@ -34,21 +41,57 @@ then
# elsewhere
TEST_OUTPUT_DIRECTORY=$TEST_DIRECTORY
fi
-GIT_BUILD_DIR="$TEST_DIRECTORY"/..
+GIT_BUILD_DIR="${TEST_DIRECTORY%/t}"
+if test "$TEST_DIRECTORY" = "$GIT_BUILD_DIR"
+then
+ echo "PANIC: Running in a $TEST_DIRECTORY that doesn't end in '/t'?" >&2
+ exit 1
+fi
+if test -f "$GIT_BUILD_DIR/GIT-BUILD-DIR"
+then
+ GIT_BUILD_DIR="$(cat "$GIT_BUILD_DIR/GIT-BUILD-DIR")" || exit 1
+ # On Windows, we must convert Windows paths lest they contain a colon
+ case "$(uname -s)" in
+ *MINGW*)
+ GIT_BUILD_DIR="$(cygpath -au "$GIT_BUILD_DIR")"
+ ;;
+ esac
+fi
+
+# Prepend a string to a VAR using an arbitrary ":" delimiter, not
+# adding the delimiter if VAR or VALUE is empty. I.e. a generalized:
+#
+# VAR=$1${VAR:+${1:+$2}$VAR}
+#
+# Usage (using ":" as the $2 delimiter):
+#
+# prepend_var VAR : VALUE
+prepend_var () {
+ eval "$1=\"$3\${$1:+${3:+$2}\$$1}\""
+}
+
+# If [AL]SAN is in effect we want to abort so that we notice
+# problems. The GIT_SAN_OPTIONS variable can be used to set common
+# defaults shared between [AL]SAN_OPTIONS.
+prepend_var GIT_SAN_OPTIONS : abort_on_error=1
+prepend_var GIT_SAN_OPTIONS : strip_path_prefix="$GIT_BUILD_DIR/"
# If we were built with ASAN, it may complain about leaks
# of program-lifetime variables. Disable it by default to lower
# the noise level. This needs to happen at the start of the script,
# before we even do our "did we build git yet" check (since we don't
# want that one to complain to stderr).
-: ${ASAN_OPTIONS=detect_leaks=0:abort_on_error=1}
+prepend_var ASAN_OPTIONS : $GIT_SAN_OPTIONS
+prepend_var ASAN_OPTIONS : detect_leaks=0
export ASAN_OPTIONS
-# If LSAN is in effect we _do_ want leak checking, but we still
-# want to abort so that we notice the problems.
-: ${LSAN_OPTIONS=abort_on_error=1}
+prepend_var LSAN_OPTIONS : $GIT_SAN_OPTIONS
+prepend_var LSAN_OPTIONS : fast_unwind_on_malloc=0
export LSAN_OPTIONS
+prepend_var UBSAN_OPTIONS : $GIT_SAN_OPTIONS
+export UBSAN_OPTIONS
+
if test ! -f "$GIT_BUILD_DIR"/GIT-BUILD-OPTIONS
then
echo >&2 'error: GIT-BUILD-OPTIONS missing (has Git been built?).'
@@ -57,6 +100,15 @@ fi
. "$GIT_BUILD_DIR"/GIT-BUILD-OPTIONS
export PERL_PATH SHELL_PATH
+# In t0000, we need to override test directories of nested testcases. In case
+# the developer has TEST_OUTPUT_DIRECTORY part of his build options, then we'd
+# reset this value to instead contain what the developer has specified. We thus
+# have this knob to allow overriding the directory.
+if test -n "${TEST_OUTPUT_DIRECTORY_OVERRIDE}"
+then
+ TEST_OUTPUT_DIRECTORY="${TEST_OUTPUT_DIRECTORY_OVERRIDE}"
+fi
+
# Disallow the use of abbreviated options in the test suite by default
if test -z "${GIT_TEST_DISALLOW_ABBREVIATED_OPTIONS}"
then
@@ -64,6 +116,11 @@ then
export GIT_TEST_DISALLOW_ABBREVIATED_OPTIONS
fi
+# Explicitly set the default branch name for testing, to avoid the
+# transitory "git init" warning under --verbose.
+: ${GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME:=master}
+export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
+
################################################################
# It appears that people try to run tests without building...
"${GIT_TEST_INSTALLED:-$GIT_BUILD_DIR}/git$X" >/dev/null
@@ -78,20 +135,29 @@ then
exit 1
fi
-# Parse options while taking care to leave $@ intact, so we will still
-# have all the original command line options when executing the test
-# script again for '--tee' and '--verbose-log' below.
store_arg_to=
-prev_opt=
-for opt
-do
- if test -n "$store_arg_to"
+opt_required_arg=
+# $1: option string
+# $2: name of the var where the arg will be stored
+mark_option_requires_arg () {
+ if test -n "$opt_required_arg"
then
- eval $store_arg_to=\$opt
- store_arg_to=
- prev_opt=
- continue
+ echo "error: options that require args cannot be bundled" \
+ "together: '$opt_required_arg' and '$1'" >&2
+ exit 1
fi
+ opt_required_arg=$1
+ store_arg_to=$2
+}
+
+# These functions can be overridden e.g. to output JUnit XML
+start_test_output () { :; }
+start_test_case_output () { :; }
+finalize_test_case_output () { :; }
+finalize_test_output () { :; }
+
+parse_option () {
+ local opt="$1"
case "$opt" in
-d|--d|--de|--deb|--debu|--debug)
@@ -101,7 +167,7 @@ do
-l|--l|--lo|--lon|--long|--long-|--long-t|--long-te|--long-tes|--long-test|--long-tests)
GIT_TEST_LONG=t; export GIT_TEST_LONG ;;
-r)
- store_arg_to=run_list
+ mark_option_requires_arg "$opt" run_list
;;
--run=*)
run_list=${opt#--*=} ;;
@@ -149,7 +215,10 @@ do
tee=t
;;
--write-junit-xml)
- write_junit_xml=t
+ . "$TEST_DIRECTORY/test-lib-junit.sh"
+ ;;
+ --github-workflow-markup)
+ . "$TEST_DIRECTORY/test-lib-github-workflow-markup.sh"
;;
--stress)
stress=t ;;
@@ -160,8 +229,8 @@ do
;;
--stress-jobs=*)
stress=t;
- stress=${opt#--*=}
- case "$stress" in
+ stress_jobs=${opt#--*=}
+ case "$stress_jobs" in
*[!0-9]*|0*|"")
echo "error: --stress-jobs=<N> requires the number of jobs to run" >&2
exit 1
@@ -182,15 +251,48 @@ do
;;
esac
;;
+ --invert-exit-code)
+ invert_exit_code=t
+ ;;
*)
echo "error: unknown test option '$opt'" >&2; exit 1 ;;
esac
+}
+
+# Parse options while taking care to leave $@ intact, so we will still
+# have all the original command line options when executing the test
+# script again for '--tee' and '--verbose-log' later.
+for opt
+do
+ if test -n "$store_arg_to"
+ then
+ eval $store_arg_to=\$opt
+ store_arg_to=
+ opt_required_arg=
+ continue
+ fi
- prev_opt=$opt
+ case "$opt" in
+ --*|-?)
+ parse_option "$opt" ;;
+ -?*)
+ # bundled short options must be fed separately to parse_option
+ opt=${opt#-}
+ while test -n "$opt"
+ do
+ extra=${opt#?}
+ this=${opt%$extra}
+ opt=$extra
+ parse_option "-$this"
+ done
+ ;;
+ *)
+ echo "error: unknown test option '$opt'" >&2; exit 1 ;;
+ esac
done
if test -n "$store_arg_to"
then
- echo "error: $prev_opt requires an argument" >&2
+ echo "error: $opt_required_arg requires an argument" >&2
exit 1
fi
@@ -216,6 +318,11 @@ TEST_NUMBER="${TEST_NAME%%-*}"
TEST_NUMBER="${TEST_NUMBER#t}"
TEST_RESULTS_DIR="$TEST_OUTPUT_DIRECTORY/test-results"
TEST_RESULTS_BASE="$TEST_RESULTS_DIR/$TEST_NAME$TEST_STRESS_JOB_SFX"
+TEST_RESULTS_SAN_FILE_PFX=trace
+TEST_RESULTS_SAN_DIR_SFX=leak
+TEST_RESULTS_SAN_FILE=
+TEST_RESULTS_SAN_DIR="$TEST_RESULTS_DIR/$TEST_NAME.$TEST_RESULTS_SAN_DIR_SFX"
+TEST_RESULTS_SAN_DIR_NR_LEAKS_STARTUP=
TRASH_DIRECTORY="trash directory.$TEST_NAME$TEST_STRESS_JOB_SFX"
test -n "$root" && TRASH_DIRECTORY="$root/$TRASH_DIRECTORY"
case "$TRASH_DIRECTORY" in
@@ -223,15 +330,26 @@ case "$TRASH_DIRECTORY" in
*) TRASH_DIRECTORY="$TEST_OUTPUT_DIRECTORY/$TRASH_DIRECTORY" ;;
esac
+# Utility functions using $TEST_RESULTS_* variables
+nr_san_dir_leaks_ () {
+ # stderr piped to /dev/null because the directory may have
+ # been "rmdir"'d already.
+ find "$TEST_RESULTS_SAN_DIR" \
+ -type f \
+ -name "$TEST_RESULTS_SAN_FILE_PFX.*" 2>/dev/null |
+ xargs grep -lv "Unable to get registers from thread" |
+ wc -l
+}
+
# If --stress was passed, run this test repeatedly in several parallel loops.
if test "$GIT_TEST_STRESS_STARTED" = "done"
then
: # Don't stress test again.
elif test -n "$stress"
then
- if test "$stress" != t
+ if test -n "$stress_jobs"
then
- job_count=$stress
+ job_count=$stress_jobs
elif test -n "$GIT_TEST_STRESS_LOAD"
then
job_count="$GIT_TEST_STRESS_LOAD"
@@ -362,29 +480,27 @@ then
verbose=t
fi
+# Since bash 5.0, checkwinsize is enabled by default which does
+# update the COLUMNS variable every time a non-builtin command
+# completes, even for non-interactive shells.
+# Disable that since we are aiming for repeatability.
+test -n "$BASH_VERSION" && shopt -u checkwinsize 2>/dev/null
+
# 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
-export LANG LC_ALL PAGER TZ
+COLUMNS=80
+export LANG LC_ALL PAGER TZ COLUMNS
EDITOR=:
-# GIT_TEST_GETTEXT_POISON should not influence git commands executed
-# during initialization of test-lib and the test repo. Back it up,
-# unset and then restore after initialization is finished.
-if test -n "$GIT_TEST_GETTEXT_POISON"
-then
- GIT_TEST_GETTEXT_POISON_ORIG=$GIT_TEST_GETTEXT_POISON
- unset GIT_TEST_GETTEXT_POISON
-fi
-
# 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
# deriving from the command substitution clustered with the other
# ones.
-unset VISUAL EMAIL LANGUAGE COLUMNS $("$PERL_PATH" -e '
+unset VISUAL EMAIL LANGUAGE $("$PERL_PATH" -e '
my @env = keys %ENV;
my $ok = join("|", qw(
TRACE
@@ -404,54 +520,43 @@ unset VISUAL EMAIL LANGUAGE COLUMNS $("$PERL_PATH" -e '
unset XDG_CACHE_HOME
unset XDG_CONFIG_HOME
unset GITPERLLIB
+unset GIT_TRACE2_PARENT_NAME
+unset GIT_TRACE2_PARENT_SID
TEST_AUTHOR_LOCALNAME=author
TEST_AUTHOR_DOMAIN=example.com
GIT_AUTHOR_EMAIL=${TEST_AUTHOR_LOCALNAME}@${TEST_AUTHOR_DOMAIN}
GIT_AUTHOR_NAME='A U Thor'
+GIT_AUTHOR_DATE='1112354055 +0200'
TEST_COMMITTER_LOCALNAME=committer
TEST_COMMITTER_DOMAIN=example.com
GIT_COMMITTER_EMAIL=${TEST_COMMITTER_LOCALNAME}@${TEST_COMMITTER_DOMAIN}
GIT_COMMITTER_NAME='C O Mitter'
+GIT_COMMITTER_DATE='1112354055 +0200'
GIT_MERGE_VERBOSITY=5
GIT_MERGE_AUTOEDIT=no
export GIT_MERGE_VERBOSITY GIT_MERGE_AUTOEDIT
export GIT_AUTHOR_EMAIL GIT_AUTHOR_NAME
export GIT_COMMITTER_EMAIL GIT_COMMITTER_NAME
+export GIT_COMMITTER_DATE GIT_AUTHOR_DATE
export EDITOR
+GIT_DEFAULT_HASH="${GIT_TEST_DEFAULT_HASH:-sha1}"
+export GIT_DEFAULT_HASH
+GIT_DEFAULT_REF_FORMAT="${GIT_TEST_DEFAULT_REF_FORMAT:-files}"
+export GIT_DEFAULT_REF_FORMAT
+GIT_TEST_MERGE_ALGORITHM="${GIT_TEST_MERGE_ALGORITHM:-ort}"
+export GIT_TEST_MERGE_ALGORITHM
+
# Tests using GIT_TRACE typically don't want <timestamp> <file>:<line> output
GIT_TRACE_BARE=1
export GIT_TRACE_BARE
-check_var_migration () {
- # the warnings and hints given from this helper depends
- # on end-user settings, which will disrupt the self-test
- # done on the test framework itself.
- case "$GIT_TEST_FRAMEWORK_SELFTEST" in
- t) return ;;
- esac
-
- old_name=$1 new_name=$2
- eval "old_isset=\${${old_name}:+isset}"
- eval "new_isset=\${${new_name}:+isset}"
-
- case "$old_isset,$new_isset" in
- isset,)
- echo >&2 "warning: $old_name is now $new_name"
- echo >&2 "hint: set $new_name too during the transition period"
- eval "$new_name=\$$old_name"
- ;;
- isset,isset)
- # do this later
- # echo >&2 "warning: $old_name is now $new_name"
- # echo >&2 "hint: remove $old_name"
- ;;
- esac
-}
-
-check_var_migration GIT_FSMONITOR_TEST GIT_TEST_FSMONITOR
-check_var_migration TEST_GIT_INDEX_VERSION GIT_TEST_INDEX_VERSION
-check_var_migration GIT_FORCE_PRELOAD_TEST GIT_TEST_PRELOAD_INDEX
+# Some tests scan the GIT_TRACE2_EVENT feed for events, but the
+# default depth is 2, which frequently causes issues when the
+# events are wrapped in new regions. Set it to a sufficiently
+# large depth to avoid custom changes in the test suite.
+GIT_TRACE2_EVENT_NESTING=100
+export GIT_TRACE2_EVENT_NESTING
# Use specific version of the index file format
if test -n "${GIT_TEST_INDEX_VERSION:+isset}"
@@ -460,9 +565,25 @@ then
export GIT_INDEX_VERSION
fi
-# Add libc MALLOC and MALLOC_PERTURB test
-# only if we are not executing the test with valgrind
+if test -n "$GIT_TEST_PERL_FATAL_WARNINGS"
+then
+ GIT_PERL_FATAL_WARNINGS=1
+ export GIT_PERL_FATAL_WARNINGS
+fi
+
+case $GIT_TEST_FSYNC in
+'')
+ GIT_TEST_FSYNC=0
+ export GIT_TEST_FSYNC
+ ;;
+esac
+
+# Add libc MALLOC and MALLOC_PERTURB test only if we are not executing
+# the test with valgrind and have not compiled with conflict SANITIZE
+# options.
if test -n "$valgrind" ||
+ test -n "$SANITIZE_ADDRESS" ||
+ test -n "$SANITIZE_LEAK" ||
test -n "$TEST_NO_MALLOC_CHECK"
then
setup_malloc_check () {
@@ -472,12 +593,35 @@ then
: nothing
}
else
+ _USE_GLIBC_TUNABLES=
+ if _GLIBC_VERSION=$(getconf GNU_LIBC_VERSION 2>/dev/null) &&
+ _GLIBC_VERSION=${_GLIBC_VERSION#"glibc "} &&
+ expr 2.34 \<= "$_GLIBC_VERSION" >/dev/null
+ then
+ _USE_GLIBC_TUNABLES=YesPlease
+ fi
setup_malloc_check () {
+ local g
+ local t
MALLOC_CHECK_=3 MALLOC_PERTURB_=165
export MALLOC_CHECK_ MALLOC_PERTURB_
+ if test -n "$_USE_GLIBC_TUNABLES"
+ then
+ g=
+ LD_PRELOAD="libc_malloc_debug.so.0"
+ for t in \
+ glibc.malloc.check=1 \
+ glibc.malloc.perturb=165
+ do
+ g="${g#:}:$t"
+ done
+ GLIBC_TUNABLES=$g
+ export LD_PRELOAD GLIBC_TUNABLES
+ fi
}
teardown_malloc_check () {
unset MALLOC_CHECK_ MALLOC_PERTURB_
+ unset LD_PRELOAD GLIBC_TUNABLES
}
fi
@@ -494,21 +638,6 @@ case $(echo $GIT_TRACE |tr "[A-Z]" "[a-z]") in
;;
esac
-# Convenience
-#
-# A regexp to match 5, 35 and 40 hexdigits
-_x05='[0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f]'
-_x35="$_x05$_x05$_x05$_x05$_x05$_x05$_x05"
-_x40="$_x35$_x05"
-
-# Zero SHA-1
-_z40=0000000000000000000000000000000000000000
-
-OID_REGEX="$_x40"
-ZERO_OID=$_z40
-EMPTY_TREE=4b825dc642cb6eb9a060e54bf8d69288fbee4904
-EMPTY_BLOB=e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
-
# Line feed
LF='
'
@@ -520,14 +649,8 @@ SQ=\'
# when case-folding filenames
u200c=$(printf '\342\200\214')
-export _x05 _x35 _x40 _z40 LF u200c EMPTY_TREE EMPTY_BLOB ZERO_OID OID_REGEX
+export _x05 _x35 LF u200c EMPTY_TREE EMPTY_BLOB ZERO_OID OID_REGEX
-# Each test should start with something like this, after copyright notices:
-#
-# test_description='Description of this test...
-# This test checks if command xyzzy does the right thing...
-# '
-# . ./test-lib.sh
test "x$TERM" != "xdumb" && (
test -t 1 &&
tput bold >/dev/null 2>&1 &&
@@ -571,20 +694,46 @@ else
}
fi
+USER_TERM="$TERM"
TERM=dumb
-export TERM
+export TERM USER_TERM
-error () {
- say_color error "error: $*"
- finalize_junit_xml
+# What is written by tests to stdout and stderr is sent to different places
+# depending on the test mode (e.g. /dev/null in non-verbose mode, piped to tee
+# with --tee option, etc.). We save the original stdin to FD #6 and stdout and
+# stderr to #5 and #7, so that the test framework can use them (e.g. for
+# printing errors within the test framework) independently of the test mode.
+exec 5>&1
+exec 6<&0
+exec 7>&2
+
+_error_exit () {
+ finalize_test_output
GIT_EXIT_OK=t
exit 1
}
+error () {
+ say_color error "error: $*"
+ _error_exit
+}
+
BUG () {
error >&7 "bug in the test script: $*"
}
+BAIL_OUT () {
+ test $# -ne 1 && BUG "1 param"
+
+ # Do not change "Bail out! " string. It's part of TAP syntax:
+ # https://testanything.org/tap-specification.html
+ local bail_out="Bail out! "
+ local message="$1"
+
+ say_color >&5 error $bail_out "$message"
+ _error_exit
+}
+
say () {
say_color info "$*"
}
@@ -593,9 +742,7 @@ if test -n "$HARNESS_ACTIVE"
then
if test "$verbose" = t || test -n "$verbose_only"
then
- printf 'Bail out! %s\n' \
- 'verbose mode forbidden under TAP harness; try --verbose-log'
- exit 1
+ BAIL_OUT 'verbose mode forbidden under TAP harness; try --verbose-log'
fi
fi
@@ -608,9 +755,6 @@ then
exit 0
fi
-exec 5>&1
-exec 6<&0
-exec 7>&2
if test "$verbose_log" = "t"
then
exec 3>>"$GIT_TEST_TEE_OUTPUT_FILE" 4>&3
@@ -640,6 +784,8 @@ test_fixed=0
test_broken=0
test_success=0
+test_missing_prereq=
+
test_external_has_tap=0
die () {
@@ -672,58 +818,51 @@ trap '{ code=$?; set +x; } 2>/dev/null; exit $code' INT TERM HUP
# the test_expect_* functions instead.
test_ok_ () {
- if test -n "$write_junit_xml"
- then
- write_junit_xml_testcase "$*"
- fi
test_success=$(($test_success + 1))
say_color "" "ok $test_count - $@"
+ finalize_test_case_output ok "$@"
+}
+
+_invert_exit_code_failure_end_blurb () {
+ say_color warn "# faked up failures as TODO & now exiting with 0 due to --invert-exit-code"
}
test_failure_ () {
- if test -n "$write_junit_xml"
+ failure_label=$1
+ test_failure=$(($test_failure + 1))
+ local pfx=""
+ if test -n "$invert_exit_code" # && test -n "$HARNESS_ACTIVE"
then
- junit_insert="<failure message=\"not ok $test_count -"
- junit_insert="$junit_insert $(xml_attr_encode "$1")\">"
- junit_insert="$junit_insert $(xml_attr_encode \
- "$(if test -n "$GIT_TEST_TEE_OUTPUT_FILE"
- then
- test-tool path-utils skip-n-bytes \
- "$GIT_TEST_TEE_OUTPUT_FILE" $GIT_TEST_TEE_OFFSET
- else
- printf '%s\n' "$@" | sed 1d
- fi)")"
- junit_insert="$junit_insert</failure>"
- if test -n "$GIT_TEST_TEE_OUTPUT_FILE"
- then
- junit_insert="$junit_insert<system-err>$(xml_attr_encode \
- "$(cat "$GIT_TEST_TEE_OUTPUT_FILE")")</system-err>"
- fi
- write_junit_xml_testcase "$1" " $junit_insert"
+ pfx="# TODO induced breakage (--invert-exit-code):"
fi
- test_failure=$(($test_failure + 1))
- say_color error "not ok $test_count - $1"
+ say_color error "not ok $test_count - ${pfx:+$pfx }$1"
shift
printf '%s\n' "$*" | sed -e 's/^/# /'
- test "$immediate" = "" || { finalize_junit_xml; GIT_EXIT_OK=t; exit 1; }
+ if test -n "$immediate"
+ then
+ say_color error "1..$test_count"
+ if test -n "$invert_exit_code"
+ then
+ finalize_test_output
+ _invert_exit_code_failure_end_blurb
+ GIT_EXIT_OK=t
+ exit 0
+ fi
+ _error_exit
+ fi
+ finalize_test_case_output failure "$failure_label" "$@"
}
test_known_broken_ok_ () {
- if test -n "$write_junit_xml"
- then
- write_junit_xml_testcase "$* (breakage fixed)"
- fi
test_fixed=$(($test_fixed+1))
- say_color error "ok $test_count - $@ # TODO known breakage vanished"
+ say_color error "ok $test_count - $1 # TODO known breakage vanished"
+ finalize_test_case_output fixed "$1"
}
test_known_broken_failure_ () {
- if test -n "$write_junit_xml"
- then
- write_junit_xml_testcase "$* (known breakage)"
- fi
test_broken=$(($test_broken+1))
- say_color warn "not ok $test_count - $@ # TODO known breakage"
+ say_color warn "not ok $test_count - $1 # TODO known breakage"
+ finalize_test_case_output broken "$1"
}
test_debug () {
@@ -734,26 +873,38 @@ match_pattern_list () {
arg="$1"
shift
test -z "$*" && return 1
- for pattern_
- do
- case "$arg" in
- $pattern_)
- return 0
- esac
- done
- return 1
+ # We need to use "$*" to get field-splitting, but we want to
+ # disable globbing, since we are matching against an arbitrary
+ # $arg, not what's in the filesystem. Using "set -f" accomplishes
+ # that, but we must do it in a subshell to avoid impacting the
+ # rest of the script. The exit value of the subshell becomes
+ # the function's return value.
+ (
+ set -f
+ for pattern_ in $*
+ do
+ case "$arg" in
+ $pattern_)
+ exit 0
+ ;;
+ esac
+ done
+ exit 1
+ )
}
match_test_selector_list () {
+ operation="$1"
+ shift
title="$1"
shift
arg="$1"
shift
test -z "$1" && return 0
- # Both commas and whitespace are accepted as separators.
+ # Commas are accepted as separators.
OLDIFS=$IFS
- IFS=' ,'
+ IFS=','
set -- $1
IFS=$OLDIFS
@@ -781,13 +932,13 @@ match_test_selector_list () {
*-*)
if expr "z${selector%%-*}" : "z[0-9]*[^0-9]" >/dev/null
then
- echo "error: $title: invalid non-numeric in range" \
+ echo "error: $operation: 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" \
+ echo "error: $operation: invalid non-numeric in range" \
"end: '$orig_selector'" >&2
exit 1
fi
@@ -795,9 +946,11 @@ match_test_selector_list () {
*)
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
+ case "$title" in *${selector}*)
+ include=$positive
+ ;;
+ esac
+ continue
fi
esac
@@ -846,7 +999,7 @@ maybe_teardown_verbose () {
last_verbose=t
maybe_setup_verbose () {
test -z "$verbose_only" && return
- if match_pattern_list $test_count $verbose_only
+ if match_pattern_list $test_count "$verbose_only"
then
exec 4>&2 3>&1
# Emit a delimiting blank line when going from
@@ -876,12 +1029,13 @@ maybe_setup_valgrind () {
return
fi
GIT_VALGRIND_ENABLED=
- if match_pattern_list $test_count $valgrind_only
+ if match_pattern_list $test_count "$valgrind_only"
then
GIT_VALGRIND_ENABLED=t
fi
}
+trace_level_=0
want_trace () {
test "$trace" = t && {
test "$verbose" = t || test "$verbose_log" = t
@@ -893,10 +1047,7 @@ want_trace () {
# (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
- $*"
+ eval "$*"
}
test_eval_ () {
@@ -921,12 +1072,16 @@ test_eval_ () {
# be _inside_ the block to avoid polluting the "set -x" output
#
- test_eval_inner_ "$@" </dev/null >&3 2>&4
+ # Do not add anything extra (including LF) after '$*'
+ test_eval_inner_ </dev/null >&3 2>&4 "
+ want_trace && trace_level_=$(($trace_level_+1)) && set -x
+ $*"
{
test_eval_ret_=$?
if want_trace
then
- set +x
+ test 1 = $trace_level_ && set +x
+ trace_level_=$(($trace_level_-1))
fi
} 2>/dev/null 4>&2
@@ -937,23 +1092,22 @@ test_eval_ () {
return $test_eval_ret_
}
+fail_117 () {
+ return 117
+}
+
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
- if $(printf '%s\n' "$1" | sed -f "$GIT_BUILD_DIR/t/chainlint.sed" | grep -q '?![A-Z][A-Z]*?!') ||
- test "OK-117" != "$(test_eval_ "(exit 117) && $1${LF}${LF}echo OK-\$?" 3>&1)"
+ test_eval_inner_ "fail_117 && $1" </dev/null >&3 2>&4
+ if test $? != 117
then
- BUG "broken &&-chain or run-away HERE-DOC: $1"
+ BUG "broken &&-chain: $1"
fi
- trace=$trace_tmp
fi
setup_malloc_check
@@ -979,10 +1133,7 @@ test_start_ () {
test_count=$(($test_count+1))
maybe_setup_verbose
maybe_setup_valgrind
- if test -n "$write_junit_xml"
- then
- junit_start=$(test-tool date getnanos)
- fi
+ start_test_case_output "$@"
}
test_finish_ () {
@@ -999,13 +1150,13 @@ test_finish_ () {
test_skip () {
to_skip=
skipped_reason=
- if match_pattern_list $this_test.$test_count $GIT_SKIP_TESTS
+ 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 "$run_list" &&
- ! match_test_selector_list '--run' $test_count "$run_list"
+ ! match_test_selector_list '--run' "$1" $test_count "$run_list"
then
to_skip=t
skipped_reason="--run"
@@ -1021,20 +1172,22 @@ test_skip () {
of_prereq=" of $test_prereq"
fi
skipped_reason="missing $missing_prereq${of_prereq}"
+
+ # Keep a list of all the missing prereq for result aggregation
+ if test -z "$missing_prereq"
+ then
+ test_missing_prereq=$missing_prereq
+ else
+ test_missing_prereq="$test_missing_prereq,$missing_prereq"
+ fi
fi
case "$to_skip" in
t)
- if test -n "$write_junit_xml"
- then
- message="$(xml_attr_encode "$skipped_reason")"
- write_junit_xml_testcase "$1" \
- " <skipped message=\"$message\" />"
- fi
- say_color skip >&3 "skipping test: $@"
say_color skip "ok $test_count # skip $1 ($skipped_reason)"
: true
+ finalize_test_case_output skip "$@"
;;
*)
false
@@ -1047,51 +1200,6 @@ test_at_end_hook_ () {
:
}
-write_junit_xml () {
- case "$1" in
- --truncate)
- >"$junit_xml_path"
- junit_have_testcase=
- shift
- ;;
- esac
- printf '%s\n' "$@" >>"$junit_xml_path"
-}
-
-xml_attr_encode () {
- printf '%s\n' "$@" | test-tool xml-encode
-}
-
-write_junit_xml_testcase () {
- junit_attrs="name=\"$(xml_attr_encode "$this_test.$test_count $1")\""
- shift
- junit_attrs="$junit_attrs classname=\"$this_test\""
- junit_attrs="$junit_attrs time=\"$(test-tool \
- date getnanos $junit_start)\""
- write_junit_xml "$(printf '%s\n' \
- " <testcase $junit_attrs>" "$@" " </testcase>")"
- junit_have_testcase=t
-}
-
-finalize_junit_xml () {
- if test -n "$write_junit_xml" && test -n "$junit_xml_path"
- then
- test -n "$junit_have_testcase" || {
- junit_start=$(test-tool date getnanos)
- write_junit_xml_testcase "all tests skipped"
- }
-
- # adjust the overall time
- junit_time=$(test-tool date getnanos $junit_suite_start)
- sed "s/<testsuite [^>]*/& time=\"$junit_time\"/" \
- <"$junit_xml_path" >"$junit_xml_path.new"
- mv "$junit_xml_path.new" "$junit_xml_path"
-
- write_junit_xml " </testsuite>" "</testsuites>"
- write_junit_xml=
- fi
-}
-
test_atexit_cleanup=:
test_atexit_handler () {
# In a succeeding test script 'test_atexit_handler' is invoked
@@ -1107,14 +1215,72 @@ test_atexit_handler () {
teardown_malloc_check
}
-test_done () {
- GIT_EXIT_OK=t
+sanitize_leak_log_message_ () {
+ local new="$1" &&
+ local old="$2" &&
+ local file="$3" &&
+ printf "With SANITIZE=leak at exit we have %d leak logs, but started with %d
+
+This means that we have a blindspot where git is leaking but we're
+losing the exit code somewhere, or not propagating it appropriately
+upwards!
+
+See the logs at \"%s.*\";
+those logs are reproduced below." \
+ "$new" "$old" "$file"
+}
+
+check_test_results_san_file_ () {
+ if test -z "$TEST_RESULTS_SAN_FILE"
+ then
+ return
+ fi &&
+ local old="$TEST_RESULTS_SAN_DIR_NR_LEAKS_STARTUP" &&
+ local new="$(nr_san_dir_leaks_)" &&
+
+ if test $new -le $old
+ then
+ return
+ fi &&
+ local out="$(sanitize_leak_log_message_ "$new" "$old" "$TEST_RESULTS_SAN_FILE")" &&
+ say_color error "$out" &&
+ if test "$old" != 0
+ then
+ echo &&
+ say_color error "The logs include output from past runs to avoid" &&
+ say_color error "that remove 'test-results' between runs."
+ fi &&
+ say_color error "$(cat "$TEST_RESULTS_SAN_FILE".*)" &&
+
+ if test -n "$passes_sanitize_leak" && test "$test_failure" = 0
+ then
+ say "As TEST_PASSES_SANITIZE_LEAK=true and our logs show we're leaking, exit non-zero!" &&
+ invert_exit_code=t
+ elif test -n "$passes_sanitize_leak"
+ then
+ say "As TEST_PASSES_SANITIZE_LEAK=true and our logs show we're leaking, and we're failing for other reasons too..." &&
+ invert_exit_code=
+ elif test -n "$sanitize_leak_check" && test "$test_failure" = 0
+ then
+ say "As TEST_PASSES_SANITIZE_LEAK=true isn't set the above leak is 'ok' with GIT_TEST_PASSING_SANITIZE_LEAK=check" &&
+ invert_exit_code=
+ elif test -n "$sanitize_leak_check"
+ then
+ say "As TEST_PASSES_SANITIZE_LEAK=true isn't set the above leak is 'ok' with GIT_TEST_PASSING_SANITIZE_LEAK=check" &&
+ invert_exit_code=t
+ else
+ say "With GIT_TEST_SANITIZE_LEAK_LOG=true our logs revealed a memory leak, exit non-zero!" &&
+ invert_exit_code=t
+ fi
+}
+
+test_done () {
# Run the atexit commands _before_ the trash directory is
# removed, so the commands can access pidfiles and socket files.
test_atexit_handler
- finalize_junit_xml
+ finalize_test_output
if test -z "$HARNESS_ACTIVE"
then
@@ -1126,10 +1292,16 @@ test_done () {
fixed $test_fixed
broken $test_broken
failed $test_failure
+ missing_prereq $test_missing_prereq
EOF
fi
+ if test -z "$passes_sanitize_leak" && test_bool_env TEST_PASSES_SANITIZE_LEAK false
+ then
+ BAIL_OUT "Please, set TEST_PASSES_SANITIZE_LEAK before sourcing test-lib.sh"
+ fi
+
if test "$test_fixed" != 0
then
say_color error "# $test_fixed known breakage(s) vanished; please update test(s)"
@@ -1148,28 +1320,32 @@ test_done () {
fi
case "$test_failure" in
0)
- if test $test_external_has_tap -eq 0
+ if test $test_remaining -gt 0
then
- if test $test_remaining -gt 0
- then
- say_color pass "# passed all $msg"
- fi
-
- # Maybe print SKIP message
- test -z "$skip_all" || skip_all="# SKIP $skip_all"
- case "$test_count" in
- 0)
- say "1..$test_count${skip_all:+ $skip_all}"
- ;;
- *)
- test -z "$skip_all" ||
- say_color warn "$skip_all"
- say "1..$test_count"
- ;;
- esac
+ say_color pass "# passed all $msg"
fi
- if test -z "$debug"
+ # Maybe print SKIP message
+ test -z "$skip_all" || skip_all="# SKIP $skip_all"
+ case "$test_count" in
+ 0)
+ say "1..$test_count${skip_all:+ $skip_all}"
+ ;;
+ *)
+ test -z "$skip_all" ||
+ say_color warn "$skip_all"
+ say "1..$test_count"
+ ;;
+ esac
+
+ if test -n "$stress" && test -n "$invert_exit_code"
+ then
+ # We're about to move our "$TRASH_DIRECTORY"
+ # to "$TRASH_DIRECTORY.stress-failed" if
+ # --stress is combined with
+ # --invert-exit-code.
+ say "with --stress and --invert-exit-code we're not removing '$TRASH_DIRECTORY'"
+ elif test -z "$debug" && test -n "$remove_trash"
then
test -d "$TRASH_DIRECTORY" ||
error "Tests passed but trash directory already removed before test cleanup; aborting"
@@ -1182,17 +1358,35 @@ test_done () {
} ||
error "Tests passed but test cleanup failed; aborting"
fi
+
+ check_test_results_san_file_ "$test_failure"
+
+ if test -z "$skip_all" && test -n "$invert_exit_code"
+ then
+ say_color warn "# faking up non-zero exit with --invert-exit-code"
+ GIT_EXIT_OK=t
+ exit 1
+ fi
+
test_at_end_hook_
+ GIT_EXIT_OK=t
exit 0 ;;
*)
- if test $test_external_has_tap -eq 0
+ say_color error "# failed $test_failure among $msg"
+ say "1..$test_count"
+
+ check_test_results_san_file_ "$test_failure"
+
+ if test -n "$invert_exit_code"
then
- say_color error "# failed $test_failure among $msg"
- say "1..$test_count"
+ _invert_exit_code_failure_end_blurb
+ GIT_EXIT_OK=t
+ exit 0
fi
+ GIT_EXIT_OK=t
exit 1 ;;
esac
@@ -1309,7 +1503,8 @@ fi
GIT_TEMPLATE_DIR="$GIT_BUILD_DIR"/templates/blt
GIT_CONFIG_NOSYSTEM=1
GIT_ATTR_NOSYSTEM=1
-export PATH GIT_EXEC_PATH GIT_TEMPLATE_DIR GIT_CONFIG_NOSYSTEM GIT_ATTR_NOSYSTEM
+GIT_CEILING_DIRECTORIES="$TRASH_DIRECTORY/.."
+export PATH GIT_EXEC_PATH GIT_TEMPLATE_DIR GIT_CONFIG_NOSYSTEM GIT_ATTR_NOSYSTEM GIT_CEILING_DIRECTORIES
if test -z "$GIT_TEST_CMP"
then
@@ -1324,63 +1519,150 @@ fi
GITPERLLIB="$GIT_BUILD_DIR"/perl/build/lib
export GITPERLLIB
test -d "$GIT_BUILD_DIR"/templates/blt || {
- error "You haven't built things yet, have you?"
+ BAIL_OUT "You haven't built things yet, have you?"
}
if ! test -x "$GIT_BUILD_DIR"/t/helper/test-tool$X
then
- echo >&2 'You need to build test-tool:'
- echo >&2 'Run "make t/helper/test-tool" in the source (toplevel) directory'
- exit 1
+ BAIL_OUT 'You need to build test-tool; Run "make t/helper/test-tool" in the source (toplevel) directory'
fi
-# Test repository
-rm -fr "$TRASH_DIRECTORY" || {
- GIT_EXIT_OK=t
- echo >&5 "FATAL: Cannot prepare test area"
- exit 1
+# Are we running this test at all?
+remove_trash=
+this_test=${0##*/}
+this_test=${this_test%%-*}
+if match_pattern_list "$this_test" "$GIT_SKIP_TESTS"
+then
+ say_color info >&3 "skipping test $this_test altogether"
+ skip_all="skip all tests in $this_test"
+ test_done
+fi
+
+BAIL_OUT_ENV_NEEDS_SANITIZE_LEAK () {
+ BAIL_OUT "$1 has no effect except when compiled with SANITIZE=leak"
}
+if test -n "$SANITIZE_LEAK"
+then
+ # Normalize with test_bool_env
+ passes_sanitize_leak=
+
+ # We need to see TEST_PASSES_SANITIZE_LEAK in "test-tool
+ # env-helper" (via test_bool_env)
+ export TEST_PASSES_SANITIZE_LEAK
+ if test_bool_env TEST_PASSES_SANITIZE_LEAK false
+ then
+ passes_sanitize_leak=t
+ fi
+
+ if test "$GIT_TEST_PASSING_SANITIZE_LEAK" = "check"
+ then
+ sanitize_leak_check=t
+ if test -n "$invert_exit_code"
+ then
+ BAIL_OUT "cannot use --invert-exit-code under GIT_TEST_PASSING_SANITIZE_LEAK=check"
+ fi
+
+ if test -z "$passes_sanitize_leak"
+ then
+ say "in GIT_TEST_PASSING_SANITIZE_LEAK=check mode, setting --invert-exit-code for TEST_PASSES_SANITIZE_LEAK != true"
+ invert_exit_code=t
+ fi
+ elif test -z "$passes_sanitize_leak" &&
+ test_bool_env GIT_TEST_PASSING_SANITIZE_LEAK false
+ then
+ skip_all="skipping $this_test under GIT_TEST_PASSING_SANITIZE_LEAK=true"
+ test_done
+ fi
+
+ if test_bool_env GIT_TEST_SANITIZE_LEAK_LOG false
+ then
+ if ! mkdir -p "$TEST_RESULTS_SAN_DIR"
+ then
+ BAIL_OUT "cannot create $TEST_RESULTS_SAN_DIR"
+ fi &&
+ TEST_RESULTS_SAN_FILE="$TEST_RESULTS_SAN_DIR/$TEST_RESULTS_SAN_FILE_PFX"
+
+ # In case "test-results" is left over from a previous
+ # run: Only report if new leaks show up.
+ TEST_RESULTS_SAN_DIR_NR_LEAKS_STARTUP=$(nr_san_dir_leaks_)
+
+ # Don't litter *.leak dirs if there was nothing to report
+ test_atexit "rmdir \"$TEST_RESULTS_SAN_DIR\" 2>/dev/null || :"
+
+ prepend_var LSAN_OPTIONS : dedup_token_length=9999
+ prepend_var LSAN_OPTIONS : log_exe_name=1
+ prepend_var LSAN_OPTIONS : log_path=\"$TEST_RESULTS_SAN_FILE\"
+ export LSAN_OPTIONS
+ fi
+elif test "$GIT_TEST_PASSING_SANITIZE_LEAK" = "check" ||
+ test_bool_env GIT_TEST_PASSING_SANITIZE_LEAK false
+then
+ BAIL_OUT_ENV_NEEDS_SANITIZE_LEAK "GIT_TEST_PASSING_SANITIZE_LEAK=true"
+elif test_bool_env GIT_TEST_SANITIZE_LEAK_LOG false
+then
+ BAIL_OUT_ENV_NEEDS_SANITIZE_LEAK "GIT_TEST_SANITIZE_LEAK_LOG=true"
+fi
+
+if test "${GIT_TEST_CHAIN_LINT:-1}" != 0 &&
+ test "${GIT_TEST_EXT_CHAIN_LINT:-1}" != 0
+then
+ "$PERL_PATH" "$TEST_DIRECTORY/chainlint.pl" "$0" ||
+ BUG "lint error (see '?!...!? annotations above)"
+fi
+
+# Last-minute variable setup
+USER_HOME="$HOME"
HOME="$TRASH_DIRECTORY"
GNUPGHOME="$HOME/gnupg-home-not-used"
-export HOME GNUPGHOME
+export HOME GNUPGHOME USER_HOME
+
+# "rm -rf" existing trash directory, even if a previous run left it
+# with bad permissions.
+remove_trash_directory () {
+ dir="$1"
+ if ! rm -rf "$dir" 2>/dev/null
+ then
+ chmod -R u+rwx "$dir"
+ rm -rf "$dir"
+ fi
+ ! test -d "$dir"
+}
+
+# Test repository
+remove_trash_directory "$TRASH_DIRECTORY" || {
+ BAIL_OUT 'cannot prepare test area'
+}
+remove_trash=t
if test -z "$TEST_NO_CREATE_REPO"
then
- test_create_repo "$TRASH_DIRECTORY"
+ git init \
+ ${TEST_CREATE_REPO_NO_TEMPLATE:+--template=} \
+ "$TRASH_DIRECTORY" >&3 2>&4 ||
+ error "cannot run git init"
else
mkdir -p "$TRASH_DIRECTORY"
fi
# Use -P to resolve symlinks in our working directory so that the cwd
# in subprocesses like git equals our $PWD (for pathname comparisons).
-cd -P "$TRASH_DIRECTORY" || exit 1
+cd -P "$TRASH_DIRECTORY" || BAIL_OUT "cannot cd -P to \"$TRASH_DIRECTORY\""
-this_test=${0##*/}
-this_test=${this_test%%-*}
-if match_pattern_list "$this_test" $GIT_SKIP_TESTS
-then
- say_color info >&3 "skipping test $this_test altogether"
- skip_all="skip all tests in $this_test"
- test_done
-fi
+start_test_output "$0"
-if test -n "$write_junit_xml"
-then
- junit_xml_dir="$TEST_OUTPUT_DIRECTORY/out"
- mkdir -p "$junit_xml_dir"
- junit_xml_base=${0##*/}
- junit_xml_path="$junit_xml_dir/TEST-${junit_xml_base%.sh}.xml"
- junit_attrs="name=\"${junit_xml_base%.sh}\""
- junit_attrs="$junit_attrs timestamp=\"$(TZ=UTC \
- date +%Y-%m-%dT%H:%M:%S)\""
- write_junit_xml --truncate "<testsuites>" " <testsuite $junit_attrs>"
- junit_suite_start=$(test-tool date getnanos)
- if test -n "$GIT_TEST_TEE_OUTPUT_FILE"
- then
- GIT_TEST_TEE_OFFSET=0
- fi
-fi
+# Convenience
+# A regexp to match 5 and 35 hexdigits
+_x05='[0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f]'
+_x35="$_x05$_x05$_x05$_x05$_x05$_x05$_x05"
+
+test_oid_init
+
+ZERO_OID=$(test_oid zero)
+OID_REGEX=$(echo $ZERO_OID | sed -e 's/0/[0-9a-f]/g')
+OIDPATH_REGEX=$(test_oid_to_path $ZERO_OID | sed -e 's/0/[0-9a-f]/g')
+EMPTY_TREE=$(test_oid empty_tree)
+EMPTY_BLOB=$(test_oid empty_blob)
# Provide an implementation of the 'yes' utility; the upper bound
# limit is there to help Windows that cannot stop this loop from
@@ -1406,7 +1688,7 @@ yes () {
# The GIT_TEST_FAIL_PREREQS code hooks into test_set_prereq(), and
# thus needs to be set up really early, and set an internal variable
# for convenience so the hot test_set_prereq() codepath doesn't need
-# to call "git env--helper" (via test_bool_env). Only do that work
+# to call "test-tool env-helper" (via test_bool_env). Only do that work
# if needed by seeing if GIT_TEST_FAIL_PREREQS is set at all.
GIT_TEST_FAIL_PREREQS_INTERNAL=
if test -n "$GIT_TEST_FAIL_PREREQS"
@@ -1444,7 +1726,8 @@ case $uname_s in
test_set_prereq NATIVE_CRLF
test_set_prereq SED_STRIPS_CR
test_set_prereq GREP_STRIPS_CR
- GIT_TEST_CMP=mingw_test_cmp
+ test_set_prereq WINDOWS
+ GIT_TEST_CMP="GIT_DIR=/dev/null git diff --no-index --ignore-cr-at-eol --"
;;
*CYGWIN*)
test_set_prereq POSIXPERM
@@ -1452,39 +1735,42 @@ case $uname_s in
test_set_prereq CYGWIN
test_set_prereq SED_STRIPS_CR
test_set_prereq GREP_STRIPS_CR
+ test_set_prereq WINDOWS
;;
-FreeBSD)
- test_set_prereq REGEX_ILLSEQ
+*)
test_set_prereq POSIXPERM
test_set_prereq BSLASHPSPEC
test_set_prereq EXECKEEPSPID
;;
+esac
+
+# Detect arches where a few things don't work
+uname_m=$(uname -m)
+case $uname_m in
+parisc* | hppa*)
+ test_set_prereq HPPA
+ ;;
+esac
+
+case "$GIT_DEFAULT_REF_FORMAT" in
+files)
+ test_set_prereq REFFILES;;
*)
- test_set_prereq POSIXPERM
- test_set_prereq BSLASHPSPEC
- test_set_prereq EXECKEEPSPID
+ echo 2>&1 "error: unknown ref format $GIT_DEFAULT_REF_FORMAT"
+ exit 1
;;
esac
( COLUMNS=1 && test $COLUMNS = 1 ) && test_set_prereq COLUMNS_CAN_BE_1
+test -z "$NO_CURL" && test_set_prereq LIBCURL
test -z "$NO_PERL" && test_set_prereq PERL
test -z "$NO_PTHREADS" && test_set_prereq PTHREADS
test -z "$NO_PYTHON" && test_set_prereq PYTHON
-test -n "$USE_LIBPCRE1$USE_LIBPCRE2" && test_set_prereq PCRE
-test -n "$USE_LIBPCRE1" && test_set_prereq LIBPCRE1
+test -n "$USE_LIBPCRE2" && test_set_prereq PCRE
test -n "$USE_LIBPCRE2" && test_set_prereq LIBPCRE2
test -z "$NO_GETTEXT" && test_set_prereq GETTEXT
-
-if test -n "$GIT_TEST_GETTEXT_POISON_ORIG"
-then
- GIT_TEST_GETTEXT_POISON=$GIT_TEST_GETTEXT_POISON_ORIG
- export GIT_TEST_GETTEXT_POISON
- unset GIT_TEST_GETTEXT_POISON_ORIG
-fi
-
-test_lazy_prereq C_LOCALE_OUTPUT '
- ! test_bool_env GIT_TEST_GETTEXT_POISON false
-'
+test -n "$SANITIZE_LEAK" && test_set_prereq SANITIZE_LEAK
+test -n "$GIT_VALGRIND_ENABLED" && test_set_prereq VALGRIND
if test -z "$GIT_TEST_CHECK_CACHE_TREE"
then
@@ -1503,6 +1789,12 @@ test_lazy_prereq SYMLINKS '
ln -s x y && test -h y
'
+test_lazy_prereq SYMLINKS_WINDOWS '
+ # test whether symbolic links are enabled on Windows
+ test_have_prereq MINGW &&
+ cmd //c "mklink y x" &> /dev/null && test -h y
+'
+
test_lazy_prereq FILEMODE '
test "$(git config --bool core.filemode)" = true
'
@@ -1605,7 +1897,7 @@ run_with_limited_cmdline () {
}
test_lazy_prereq CMDLINE_LIMIT '
- test_have_prereq !MINGW,!CYGWIN &&
+ test_have_prereq !HPPA,!MINGW,!CYGWIN &&
run_with_limited_cmdline true
'
@@ -1614,15 +1906,28 @@ run_with_limited_stack () {
}
test_lazy_prereq ULIMIT_STACK_SIZE '
- test_have_prereq !MINGW,!CYGWIN &&
+ test_have_prereq !HPPA,!MINGW,!CYGWIN &&
run_with_limited_stack true
'
+run_with_limited_open_files () {
+ (ulimit -n 32 && "$@")
+}
+
+test_lazy_prereq ULIMIT_FILE_DESCRIPTORS '
+ test_have_prereq !MINGW,!CYGWIN &&
+ run_with_limited_open_files true
+'
+
build_option () {
git version --build-options |
sed -ne "s/^$1: //p"
}
+test_lazy_prereq SIZE_T_IS_64BIT '
+ test 8 -eq "$(build_option sizeof-size_t)"
+'
+
test_lazy_prereq LONG_IS_64BIT '
test 8 -le "$(build_option sizeof-long)"
'
@@ -1638,9 +1943,27 @@ test_lazy_prereq CURL '
# which will not work with other hash algorithms and tests that work but don't
# test anything meaningful (e.g. special values which cause short collisions).
test_lazy_prereq SHA1 '
- test $(git hash-object /dev/null) = e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
+ case "$GIT_DEFAULT_HASH" in
+ sha1) true ;;
+ "") test $(git hash-object /dev/null) = e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 ;;
+ *) false ;;
+ esac
'
-test_lazy_prereq REBASE_P '
- test -z "$GIT_TEST_SKIP_REBASE_P"
+test_lazy_prereq DEFAULT_REPO_FORMAT '
+ test_have_prereq SHA1,REFFILES
+'
+
+# Ensure that no test accidentally triggers a Git command
+# that runs the actual maintenance scheduler, affecting a user's
+# system permanently.
+# Tests that verify the scheduler integration must set this locally
+# to avoid errors.
+GIT_TEST_MAINT_SCHEDULER="none:exit 1"
+
+# Does this platform support `git fsmonitor--daemon`
+#
+test_lazy_prereq FSMONITOR_DAEMON '
+ git version --build-options >output &&
+ grep "feature: fsmonitor--daemon" output
'