Merge branch 'jc/gettext-test-fix'
authorJunio C Hamano <gitster@pobox.com>
Thu, 25 Apr 2019 07:41:23 +0000 (16:41 +0900)
committerJunio C Hamano <gitster@pobox.com>
Thu, 25 Apr 2019 07:41:23 +0000 (16:41 +0900)
The GETTEXT_POISON test option has been quite broken ever since it
was made runtime-tunable, which has been fixed.

* jc/gettext-test-fix:
gettext tests: export the restored GIT_TEST_GETTEXT_POISON

1  2 
t/test-lib.sh
diff --combined t/test-lib.sh
index d18387c255413cfe85b3e25f81e2dc70fcd8b4fa,b3d995f562a4228fb0f934907804f7aa40b8824e..908ddb9c46630d8d9678f610cfde7617bc38514c
@@@ -57,13 -57,6 +57,13 @@@ f
  . "$GIT_BUILD_DIR"/GIT-BUILD-OPTIONS
  export PERL_PATH SHELL_PATH
  
 +# Disallow the use of abbreviated options in the test suite by default
 +if test -z "${GIT_TEST_DISALLOW_ABBREVIATED_OPTIONS}"
 +then
 +      GIT_TEST_DISALLOW_ABBREVIATED_OPTIONS=true
 +      export GIT_TEST_DISALLOW_ABBREVIATED_OPTIONS
 +fi
 +
  ################################################################
  # It appears that people try to run tests without building...
  "${GIT_TEST_INSTALLED:-$GIT_BUILD_DIR}/git$X" >/dev/null
@@@ -78,248 -71,19 +78,248 @@@ the
        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"
 +      then
 +              eval $store_arg_to=\$opt
 +              store_arg_to=
 +              prev_opt=
 +              continue
 +      fi
 +
 +      case "$opt" in
 +      -d|--d|--de|--deb|--debu|--debug)
 +              debug=t ;;
 +      -i|--i|--im|--imm|--imme|--immed|--immedi|--immedia|--immediat|--immediate)
 +              immediate=t ;;
 +      -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
 +              ;;
 +      --run=*)
 +              run_list=${opt#--*=} ;;
 +      -h|--h|--he|--hel|--help)
 +              help=t ;;
 +      -v|--v|--ve|--ver|--verb|--verbo|--verbos|--verbose)
 +              verbose=t ;;
 +      --verbose-only=*)
 +              verbose_only=${opt#--*=}
 +              ;;
 +      -q|--q|--qu|--qui|--quie|--quiet)
 +              # 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 ;;
 +      --with-dashes)
 +              with_dashes=t ;;
 +      --no-bin-wrappers)
 +              no_bin_wrappers=t ;;
 +      --no-color)
 +              color= ;;
 +      --va|--val|--valg|--valgr|--valgri|--valgrin|--valgrind)
 +              valgrind=memcheck
 +              tee=t
 +              ;;
 +      --valgrind=*)
 +              valgrind=${opt#--*=}
 +              tee=t
 +              ;;
 +      --valgrind-only=*)
 +              valgrind_only=${opt#--*=}
 +              tee=t
 +              ;;
 +      --tee)
 +              tee=t ;;
 +      --root=*)
 +              root=${opt#--*=} ;;
 +      --chain-lint)
 +              GIT_TEST_CHAIN_LINT=1 ;;
 +      --no-chain-lint)
 +              GIT_TEST_CHAIN_LINT=0 ;;
 +      -x)
 +              trace=t ;;
 +      -V|--verbose-log)
 +              verbose_log=t
 +              tee=t
 +              ;;
 +      --write-junit-xml)
 +              write_junit_xml=t
 +              ;;
 +      --stress)
 +              stress=t ;;
 +      --stress=*)
 +              echo "error: --stress does not accept an argument: '$opt'" >&2
 +              echo "did you mean --stress-jobs=${opt#*=} or --stress-limit=${opt#*=}?" >&2
 +              exit 1
 +              ;;
 +      --stress-jobs=*)
 +              stress=t;
 +              stress=${opt#--*=}
 +              case "$stress" in
 +              *[!0-9]*|0*|"")
 +                      echo "error: --stress-jobs=<N> requires the number of jobs to run" >&2
 +                      exit 1
 +                      ;;
 +              *)      # Good.
 +                      ;;
 +              esac
 +              ;;
 +      --stress-limit=*)
 +              stress=t;
 +              stress_limit=${opt#--*=}
 +              case "$stress_limit" in
 +              *[!0-9]*|0*|"")
 +                      echo "error: --stress-limit=<N> requires the number of repetitions" >&2
 +                      exit 1
 +                      ;;
 +              *)      # Good.
 +                      ;;
 +              esac
 +              ;;
 +      *)
 +              echo "error: unknown test option '$opt'" >&2; exit 1 ;;
 +      esac
 +
 +      prev_opt=$opt
 +done
 +if test -n "$store_arg_to"
 +then
 +      echo "error: $prev_opt requires an argument" >&2
 +      exit 1
 +fi
 +
 +if test -n "$valgrind_only"
 +then
 +      test -z "$valgrind" && valgrind=memcheck
 +      test -z "$verbose" && verbose_only="$valgrind_only"
 +elif test -n "$valgrind"
 +then
 +      test -z "$verbose_log" && verbose=t
 +fi
 +
 +if test -n "$stress"
 +then
 +      verbose=t
 +      trace=t
 +      immediate=t
 +fi
 +
 +TEST_STRESS_JOB_SFX="${GIT_TEST_STRESS_JOB_NR:+.stress-$GIT_TEST_STRESS_JOB_NR}"
 +TEST_NAME="$(basename "$0" .sh)"
 +TEST_RESULTS_DIR="$TEST_OUTPUT_DIRECTORY/test-results"
 +TEST_RESULTS_BASE="$TEST_RESULTS_DIR/$TEST_NAME$TEST_STRESS_JOB_SFX"
 +TRASH_DIRECTORY="trash directory.$TEST_NAME$TEST_STRESS_JOB_SFX"
 +test -n "$root" && TRASH_DIRECTORY="$root/$TRASH_DIRECTORY"
 +case "$TRASH_DIRECTORY" in
 +/*) ;; # absolute path is good
 + *) TRASH_DIRECTORY="$TEST_OUTPUT_DIRECTORY/$TRASH_DIRECTORY" ;;
 +esac
 +
 +# 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
 +      then
 +              job_count=$stress
 +      elif test -n "$GIT_TEST_STRESS_LOAD"
 +      then
 +              job_count="$GIT_TEST_STRESS_LOAD"
 +      elif job_count=$(getconf _NPROCESSORS_ONLN 2>/dev/null) &&
 +           test -n "$job_count"
 +      then
 +              job_count=$((2 * $job_count))
 +      else
 +              job_count=8
 +      fi
 +
 +      mkdir -p "$TEST_RESULTS_DIR"
 +      stressfail="$TEST_RESULTS_BASE.stress-failed"
 +      rm -f "$stressfail"
 +
 +      stress_exit=0
 +      trap '
 +              kill $job_pids 2>/dev/null
 +              wait
 +              stress_exit=1
 +      ' TERM INT HUP
 +
 +      job_pids=
 +      job_nr=0
 +      while test $job_nr -lt "$job_count"
 +      do
 +              (
 +                      GIT_TEST_STRESS_STARTED=done
 +                      GIT_TEST_STRESS_JOB_NR=$job_nr
 +                      export GIT_TEST_STRESS_STARTED GIT_TEST_STRESS_JOB_NR
 +
 +                      trap '
 +                              kill $test_pid 2>/dev/null
 +                              wait
 +                              exit 1
 +                      ' TERM INT
 +
 +                      cnt=1
 +                      while ! test -e "$stressfail" &&
 +                            { test -z "$stress_limit" ||
 +                              test $cnt -le $stress_limit ; }
 +                      do
 +                              $TEST_SHELL_PATH "$0" "$@" >"$TEST_RESULTS_BASE.stress-$job_nr.out" 2>&1 &
 +                              test_pid=$!
 +
 +                              if wait $test_pid
 +                              then
 +                                      printf "OK   %2d.%d\n" $GIT_TEST_STRESS_JOB_NR $cnt
 +                              else
 +                                      echo $GIT_TEST_STRESS_JOB_NR >>"$stressfail"
 +                                      printf "FAIL %2d.%d\n" $GIT_TEST_STRESS_JOB_NR $cnt
 +                              fi
 +                              cnt=$(($cnt + 1))
 +                      done
 +              ) &
 +              job_pids="$job_pids $!"
 +              job_nr=$(($job_nr + 1))
 +      done
 +
 +      wait
 +
 +      if test -f "$stressfail"
 +      then
 +              stress_exit=1
 +              echo "Log(s) of failed test run(s):"
 +              for failed_job_nr in $(sort -n "$stressfail")
 +              do
 +                      echo "Contents of '$TEST_RESULTS_BASE.stress-$failed_job_nr.out':"
 +                      cat "$TEST_RESULTS_BASE.stress-$failed_job_nr.out"
 +              done
 +              rm -rf "$TRASH_DIRECTORY.stress-failed"
 +              # Move the last one.
 +              mv "$TRASH_DIRECTORY.stress-$failed_job_nr" "$TRASH_DIRECTORY.stress-failed"
 +      fi
 +
 +      exit $stress_exit
 +fi
 +
  # if --tee was passed, write the output not only to the terminal, but
  # additionally to the file test-results/$BASENAME.out, too.
 -case "$GIT_TEST_TEE_STARTED, $* " in
 -done,*)
 -      # do not redirect again
 -      ;;
 -*' --tee '*|*' --va'*|*' -V '*|*' --verbose-log '*)
 -      mkdir -p "$TEST_OUTPUT_DIRECTORY/test-results"
 -      BASE="$TEST_OUTPUT_DIRECTORY/test-results/$(basename "$0" .sh)"
 +if test "$GIT_TEST_TEE_STARTED" = "done"
 +then
 +      : # do not redirect again
 +elif test -n "$tee"
 +then
 +      mkdir -p "$TEST_RESULTS_DIR"
  
        # Make this filename available to the sub-process in case it is using
        # --verbose-log.
 -      GIT_TEST_TEE_OUTPUT_FILE=$BASE.out
 +      GIT_TEST_TEE_OUTPUT_FILE=$TEST_RESULTS_BASE.out
        export GIT_TEST_TEE_OUTPUT_FILE
  
        # Truncate before calling "tee -a" to get rid of the results
        >"$GIT_TEST_TEE_OUTPUT_FILE"
  
        (GIT_TEST_TEE_STARTED=done ${TEST_SHELL_PATH} "$0" "$@" 2>&1;
 -       echo $? >"$BASE.exit") | tee -a "$GIT_TEST_TEE_OUTPUT_FILE"
 -      test "$(cat "$BASE.exit")" = 0
 +       echo $? >"$TEST_RESULTS_BASE.exit") | tee -a "$GIT_TEST_TEE_OUTPUT_FILE"
 +      test "$(cat "$TEST_RESULTS_BASE.exit")" = 0
        exit
 -      ;;
 -esac
 +fi
 +
 +if test -n "$trace" && test -n "$test_untraceable"
 +then
 +      # '-x' tracing requested, but this test script can't be reliably
 +      # traced, unless it is run with a Bash version supporting
 +      # BASH_XTRACEFD (introduced in Bash v4.1).
 +      #
 +      # Perform this version check _after_ the test script was
 +      # potentially re-executed with $TEST_SHELL_PATH for '--tee' or
 +      # '--verbose-log', so the right shell is checked and the
 +      # warning is issued only once.
 +      if test -n "$BASH_VERSION" && eval '
 +           test ${BASH_VERSINFO[0]} -gt 4 || {
 +             test ${BASH_VERSINFO[0]} -eq 4 &&
 +             test ${BASH_VERSINFO[1]} -ge 1
 +           }
 +         '
 +      then
 +              : Executed by a Bash version supporting BASH_XTRACEFD.  Good.
 +      else
 +              echo >&2 "warning: ignoring -x; '$0' is untraceable without BASH_XTRACEFD"
 +              trace=
 +      fi
 +fi
 +if test -n "$trace" && test -z "$verbose_log"
 +then
 +      verbose=t
 +fi
  
  # For repeatability, reset the environment to known value.
  # TERM is sanitized below, after saving color control sequences.
@@@ -386,7 -123,6 +386,7 @@@ unset VISUAL EMAIL LANGUAGE COLUMNS $("
        my @env = keys %ENV;
        my $ok = join("|", qw(
                TRACE
 +              TR2_
                DEBUG
                TEST
                .*_TEST
@@@ -457,7 -193,7 +457,7 @@@ f
  
  # Add libc MALLOC and MALLOC_PERTURB test
  # only if we are not executing the test with valgrind
 -if expr " $GIT_TEST_OPTS " : ".* --valgrind " >/dev/null ||
 +if test -n "$valgrind" ||
     test -n "$TEST_NO_MALLOC_CHECK"
  then
        setup_malloc_check () {
@@@ -528,6 -264,100 +528,6 @@@ test "x$TERM" != "xdumb" && 
        ) &&
        color=t
  
 -while test "$#" -ne 0
 -do
 -      case "$1" in
 -      -d|--d|--de|--deb|--debu|--debug)
 -              debug=t; shift ;;
 -      -i|--i|--im|--imm|--imme|--immed|--immedi|--immedia|--immediat|--immediate)
 -              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=${1#--*=}
 -              shift ;;
 -      -q|--q|--qu|--qui|--quie|--quiet)
 -              # 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 ;;
 -      --va|--val|--valg|--valgr|--valgri|--valgrin|--valgrind)
 -              valgrind=memcheck
 -              shift ;;
 -      --valgrind=*)
 -              valgrind=${1#--*=}
 -              shift ;;
 -      --valgrind-only=*)
 -              valgrind_only=${1#--*=}
 -              shift ;;
 -      --tee)
 -              shift ;; # was handled already
 -      --root=*)
 -              root=${1#--*=}
 -              shift ;;
 -      --chain-lint)
 -              GIT_TEST_CHAIN_LINT=1
 -              shift ;;
 -      --no-chain-lint)
 -              GIT_TEST_CHAIN_LINT=0
 -              shift ;;
 -      -x)
 -              # Some test scripts can't be reliably traced  with '-x',
 -              # unless the test is run with a Bash version supporting
 -              # BASH_XTRACEFD (introduced in Bash v4.1).  Check whether
 -              # this test is marked as such, and ignore '-x' if it
 -              # isn't executed with a suitable Bash version.
 -              if test -z "$test_untraceable" || {
 -                   test -n "$BASH_VERSION" && {
 -                     test ${BASH_VERSINFO[0]} -gt 4 || {
 -                       test ${BASH_VERSINFO[0]} -eq 4 &&
 -                       test ${BASH_VERSINFO[1]} -ge 1
 -                     }
 -                   }
 -                 }
 -              then
 -                      trace=t
 -              else
 -                      echo >&2 "warning: ignoring -x; '$0' is untraceable without BASH_XTRACEFD"
 -              fi
 -              shift ;;
 -      -V|--verbose-log)
 -              verbose_log=t
 -              shift ;;
 -      *)
 -              echo "error: unknown test option '$1'" >&2; exit 1 ;;
 -      esac
 -done
 -
 -if test -n "$valgrind_only"
 -then
 -      test -z "$valgrind" && valgrind=memcheck
 -      test -z "$verbose" && verbose_only="$valgrind_only"
 -elif test -n "$valgrind"
 -then
 -      test -z "$verbose_log" && verbose=t
 -fi
 -
 -if test -n "$trace" && test -z "$verbose_log"
 -then
 -      verbose=t
 -fi
 -
  if test -n "$color"
  then
        # Save the color control sequences now rather than run tput
@@@ -635,10 -465,6 +635,10 @@@ test_external_has_tap=
  
  die () {
        code=$?
 +      # This is responsible for running the atexit commands even when a
 +      # test script run with '--immediate' fails, or when the user hits
 +      # ctrl-C, i.e. when 'test_done' is not invoked at all.
 +      test_atexit_handler || code=$?
        if test -n "$GIT_EXIT_OK"
        then
                exit $code
  
  GIT_EXIT_OK=
  trap 'die' EXIT
 -trap 'exit $?' INT
 +# Disable '-x' tracing, because with some shells, notably dash, it
 +# prevents running the cleanup commands when a test script run with
 +# '--verbose-log -x' is interrupted.
 +trap '{ code=$?; set +x; } 2>/dev/null; exit $code' INT TERM HUP
  
  # The user-facing functions are loaded from a separate file so that
  # test_perf subshells can have them too
  # 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 - $@"
  }
  
  test_failure_ () {
 +      if test -n "$write_junit_xml"
 +      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"
 +      fi
        test_failure=$(($test_failure + 1))
        say_color error "not ok $test_count - $1"
        shift
  }
  
  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"
  }
  
  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"
  }
@@@ -970,21 -761,12 +970,21 @@@ 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
  }
  
  test_finish_ () {
        echo >&3 ""
        maybe_teardown_valgrind
        maybe_teardown_verbose
 +      if test -n "$GIT_TEST_TEE_OFFSET"
 +      then
 +              GIT_TEST_TEE_OFFSET=$(test-tool path-utils file-size \
 +                      "$GIT_TEST_TEE_OUTPUT_FILE")
 +      fi
  }
  
  test_skip () {
  
        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
@@@ -1038,75 -813,17 +1038,75 @@@ 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
 +}
 +
 +test_atexit_cleanup=:
 +test_atexit_handler () {
 +      # In a succeeding test script 'test_atexit_handler' is invoked
 +      # twice: first from 'test_done', then from 'die' in the trap on
 +      # EXIT.
 +      # This condition and resetting 'test_atexit_cleanup' below makes
 +      # sure that the registered cleanup commands are run only once.
 +      test : != "$test_atexit_cleanup" || return 0
 +
 +      setup_malloc_check
 +      test_eval_ "$test_atexit_cleanup"
 +      test_atexit_cleanup=:
 +      teardown_malloc_check
 +}
 +
  test_done () {
        GIT_EXIT_OK=t
  
 +      # Run the atexit commands _before_ the trash directory is
 +      # removed, so the commands can access pidfiles and socket files.
 +      test_atexit_handler
 +
 +      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>"
 +      fi
 +
        if test -z "$HARNESS_ACTIVE"
        then
 -              test_results_dir="$TEST_OUTPUT_DIRECTORY/test-results"
 -              mkdir -p "$test_results_dir"
 -              base=${0##*/}
 -              test_results_path="$test_results_dir/${base%.sh}.counts"
 +              mkdir -p "$TEST_RESULTS_DIR"
  
 -              cat >"$test_results_path" <<-EOF
 +              cat >"$TEST_RESULTS_BASE.counts" <<-EOF
                total $test_count
                success $test_success
                fixed $test_fixed
                        error "Tests passed but trash directory already removed before test cleanup; aborting"
  
                        cd "$TRASH_DIRECTORY/.." &&
 -                      rm -fr "$TRASH_DIRECTORY" ||
 +                      rm -fr "$TRASH_DIRECTORY" || {
 +                              # try again in a bit
 +                              sleep 5;
 +                              rm -fr "$TRASH_DIRECTORY"
 +                      } ||
                        error "Tests passed but test cleanup failed; aborting"
                fi
                test_at_end_hook_
        PATH=$GIT_TEST_INSTALLED:$GIT_BUILD_DIR/t/helper:$PATH
        GIT_EXEC_PATH=${GIT_TEST_EXEC_PATH:-$GIT_EXEC_PATH}
  else # normal case, use ../bin-wrappers only unless $with_dashes:
 -      git_bin_dir="$GIT_BUILD_DIR/bin-wrappers"
 -      if ! test -x "$git_bin_dir/git"
 +      if test -n "$no_bin_wrappers"
        then
 -              if test -z "$with_dashes"
 +              with_dashes=t
 +      else
 +              git_bin_dir="$GIT_BUILD_DIR/bin-wrappers"
 +              if ! test -x "$git_bin_dir/git"
                then
 -                      say "$git_bin_dir/git is not executable; using GIT_EXEC_PATH"
 +                      if test -z "$with_dashes"
 +                      then
 +                              say "$git_bin_dir/git is not executable; using GIT_EXEC_PATH"
 +                      fi
 +                      with_dashes=t
                fi
 -              with_dashes=t
 +              PATH="$git_bin_dir:$PATH"
        fi
 -      PATH="$git_bin_dir:$PATH"
        GIT_EXEC_PATH=$GIT_BUILD_DIR
        if test -n "$with_dashes"
        then
 -              PATH="$GIT_BUILD_DIR:$PATH"
 +              PATH="$GIT_BUILD_DIR:$GIT_BUILD_DIR/t/helper:$PATH"
        fi
  fi
  GIT_TEMPLATE_DIR="$GIT_BUILD_DIR"/templates/blt
@@@ -1313,7 -1021,7 +1313,7 @@@ test -d "$GIT_BUILD_DIR"/templates/blt 
        error "You haven't built things yet, have you?"
  }
  
 -if ! test -x "$GIT_BUILD_DIR"/t/helper/test-tool
 +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'
  fi
  
  # Test repository
 -TRASH_DIRECTORY="trash directory.$(basename "$0" .sh)"
 -test -n "$root" && TRASH_DIRECTORY="$root/$TRASH_DIRECTORY"
 -case "$TRASH_DIRECTORY" in
 -/*) ;; # absolute path is good
 - *) TRASH_DIRECTORY="$TEST_OUTPUT_DIRECTORY/$TRASH_DIRECTORY" ;;
 -esac
  rm -fr "$TRASH_DIRECTORY" || {
        GIT_EXIT_OK=t
        echo >&5 "FATAL: Cannot prepare test area"
@@@ -1337,7 -1051,6 +1337,7 @@@ the
  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
        test_done
  fi
  
 -# Provide an implementation of the 'yes' utility
 +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
 +
 +# Provide an implementation of the 'yes' utility; the upper bound
 +# limit is there to help Windows that cannot stop this loop from
 +# wasting cycles when the downstream stops reading, so do not be
 +# tempted to turn it into an infinite loop. cf. 6129c930 ("test-lib:
 +# limit the output of the yes utility", 2016-02-02)
  yes () {
        if test $# = 0
        then
@@@ -1439,6 -1131,7 +1439,7 @@@ test -z "$NO_GETTEXT" && test_set_prere
  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