Merge branch 'sg/test-atexit'
authorJunio C Hamano <gitster@pobox.com>
Thu, 25 Apr 2019 07:41:12 +0000 (16:41 +0900)
committerJunio C Hamano <gitster@pobox.com>
Thu, 25 Apr 2019 07:41:12 +0000 (16:41 +0900)
Test framework update to more robustly clean up leftover files and
processes after tests are done.

* sg/test-atexit:
t9811-git-p4-label-import: fix pipeline negation
git p4 test: disable '-x' tracing in the p4d watchdog loop
git p4 test: simplify timeout handling
git p4 test: clean up the p4d cleanup functions
git p4 test: use 'test_atexit' to kill p4d and the watchdog process
t0301-credential-cache: use 'test_atexit' to stop the credentials helper
tests: use 'test_atexit' to stop httpd
git-daemon: use 'test_atexit` to stop 'git-daemon'
test-lib: introduce 'test_atexit'
t/lib-git-daemon: make sure to kill the 'git-daemon' process
test-lib: fix interrupt handling with 'dash' and '--verbose-log -x'

1  2 
t/README
t/t5500-fetch-pack.sh
t/t5539-fetch-http-shallow.sh
t/t5541-http-push-smart.sh
t/t5550-http-fetch-dumb.sh
t/t5551-http-fetch-smart.sh
t/t5601-clone.sh
t/t5700-protocol-v1.sh
t/test-lib-functions.sh
t/test-lib.sh
diff --combined t/README
index af1243eb49efab5e5763c54e82697bf277be0adf,0b03175c7d5f0474d26cfc529b9379727acbec58..6404f33e19421c47999518138ed6f46a066921c0
+++ b/t/README
@@@ -196,10 -196,11 +196,10 @@@ appropriately before running "make"
        variable to "1" or "0", respectively.
  
  --stress::
 ---stress=<N>::
        Run the test script repeatedly in multiple parallel jobs until
        one of them fails.  Useful for reproducing rare failures in
        flaky tests.  The number of parallel jobs is, in order of
 -      precedence: <N>, or the value of the GIT_TEST_STRESS_LOAD
 +      precedence: the value of the GIT_TEST_STRESS_LOAD
        environment variable, or twice the number of available
        processors (as shown by the 'getconf' utility), or 8.
        Implies `--verbose -x --immediate` to get the most information
        '.stress-<nr>' suffix, and the trash directory of the failed
        test job is renamed to end with a '.stress-failed' suffix.
  
 +--stress-jobs=<N>::
 +      Override the number of parallel jobs. Implies `--stress`.
 +
  --stress-limit=<N>::
        When combined with --stress run the test script repeatedly
        this many times in each of the parallel jobs or until one of
 -      them fails, whichever comes first.
 +      them fails, whichever comes first. Implies `--stress`.
  
  You can also set the GIT_TEST_INSTALLED environment variable to
  the bindir of an existing git installation to test that installation.
@@@ -343,9 -341,6 +343,9 @@@ marked strings" in po/README for detail
  GIT_TEST_SPLIT_INDEX=<boolean> forces split-index mode on the whole
  test suite. Accept any boolean values that are accepted by git-config.
  
 +GIT_TEST_PROTOCOL_VERSION=<n>, when set, overrides the
 +'protocol.version' setting to n if it is less than n.
 +
  GIT_TEST_FULL_IN_PACK_ARRAY=<boolean> exercises the uncommon
  pack-objects code path where there are more than 1024 packs even if
  the actual number of packs in repository is below this limit. Accept
@@@ -384,8 -379,8 +384,8 @@@ the --no-sparse command-line argument
  GIT_TEST_PRELOAD_INDEX=<boolean> exercises the preload-index code path
  by overriding the minimum number of cache entries required per thread.
  
 -GIT_TEST_REBASE_USE_BUILTIN=<boolean>, when false, disables the
 -builtin version of git-rebase. See 'rebase.useBuiltin' in
 +GIT_TEST_STASH_USE_BUILTIN=<boolean>, when false, disables the
 +built-in version of git-stash. See 'stash.useBuiltin' in
  git-config(1).
  
  GIT_TEST_INDEX_THREADS=<n> enables exercising the multi-threaded loading
@@@ -402,10 -397,6 +402,10 @@@ GIT_TEST_SIDEBAND_ALL=<boolean>, when t
  fetch-pack to not request sideband-all (even if the server advertises
  sideband-all).
  
 +GIT_TEST_DISALLOW_ABBREVIATED_OPTIONS=<boolean>, when true (which is
 +the default when running tests), errors out when an abbreviated option
 +is used.
 +
  Naming Tests
  ------------
  
@@@ -871,6 -862,26 +871,26 @@@ library for your script to use
                ...
        '
  
+  - test_atexit <script>
+    Prepend <script> to a list of commands to run unconditionally to
+    clean up before the test script exits, e.g. to stop a daemon:
+       test_expect_success 'test git daemon' '
+               git daemon &
+               daemon_pid=$! &&
+               test_atexit 'kill $daemon_pid' &&
+               hello world
+       '
+    The commands will be executed before the trash directory is removed,
+    i.e. the atexit commands will still be able to access any pidfiles or
+    socket files.
+    Note that these commands will be run even when a test script run
+    with '--immediate' fails.  Be careful with your atexit commands to
+    minimize any changes to the failed state.
   - test_write_lines <lines>
  
     Write <lines> on standard output, one line per argument.
diff --combined t/t5500-fetch-pack.sh
index 0ef4d6f20c226d544daa4ea62adf19e4ec946ce4,32426fa5d1d4e62450f97543b72623fea2b00189..1c71c0ec770cd54505f65bf83eca91f153cdf785
@@@ -636,9 -636,7 +636,9 @@@ test_expect_success 'fetch-pack cannot 
        test_commit -C server 6 &&
  
        git init client &&
 -      test_must_fail git -C client fetch-pack ../server \
 +      # Some protocol versions (e.g. 2) support fetching
 +      # unadvertised objects, so restrict this test to v0.
 +      test_must_fail env GIT_TEST_PROTOCOL_VERSION= git -C client fetch-pack ../server \
                $(git -C server rev-parse refs/heads/master^) 2>err &&
        test_i18ngrep "Server does not allow request for unadvertised object" err
  '
@@@ -920,7 -918,4 +920,4 @@@ test_expect_success 'fetch with --filte
        fetch_filter_blob_limit_zero "$HTTPD_DOCUMENT_ROOT_PATH/server" "$HTTPD_URL/smart/server"
  '
  
- stop_httpd
  test_done
index cdb687b93aa1fe541a8c1b98a7dff0f4caf4c376,98f028f2036e3b0c8712790b93b760d164bd3628..b4ad81f00635efc144a3b531a939e5fc34d5c14f
@@@ -67,10 -67,7 +67,10 @@@ test_expect_success 'no shallow lines a
                cd clone &&
                git checkout --orphan newnew &&
                test_commit new-too &&
 -              GIT_TRACE_PACKET="$TRASH_DIRECTORY/trace" git fetch --depth=2 &&
 +              # NEEDSWORK: If the overspecification of the expected result is reduced, we
 +              # might be able to run this test in all protocol versions.
 +              GIT_TRACE_PACKET="$TRASH_DIRECTORY/trace" GIT_TEST_PROTOCOL_VERSION= \
 +                      git fetch --depth=2 &&
                grep "fetch-pack< ACK .* ready" ../trace &&
                ! grep "fetch-pack> done" ../trace
        )
@@@ -149,5 -146,4 +149,4 @@@ test_expect_success 'fetching deepen' 
        )
  '
  
- stop_httpd
  test_done
index 0e3055ab98b94596eb5f7ac65e9dc35c58cd24c2,bdf40f445e969502e0a52b925acc8d6d0b9d49da..8ef8763e063cf30da8af4a80079458cf8e18c56d
@@@ -47,12 -47,7 +47,12 @@@ test_expect_success 'no empty path comp
        cd "$ROOT_PATH" &&
        git clone $HTTPD_URL/smart/test_repo.git/ test_repo_clone &&
  
 -      check_access_log exp
 +      # NEEDSWORK: If the overspecification of the expected result is reduced, we
 +      # might be able to run this test in all protocol versions.
 +      if test -z "$GIT_TEST_PROTOCOL_VERSION"
 +      then
 +              check_access_log exp
 +      fi
  '
  
  test_expect_success 'clone remote repository' '
@@@ -133,12 -128,7 +133,12 @@@ GET  /smart/test_repo.git/info/refs?ser
  POST /smart/test_repo.git/git-receive-pack HTTP/1.1 200
  EOF
  test_expect_success 'used receive-pack service' '
 -      check_access_log exp
 +      # NEEDSWORK: If the overspecification of the expected result is reduced, we
 +      # might be able to run this test in all protocol versions.
 +      if test -z "$GIT_TEST_PROTOCOL_VERSION"
 +      then
 +              check_access_log exp
 +      fi
  '
  
  test_http_push_nonff "$HTTPD_DOCUMENT_ROOT_PATH"/test_repo.git \
@@@ -383,5 -373,4 +383,4 @@@ test_expect_success 'colorize errors/hi
        test_i18ngrep ! "^hint: " decoded
  '
  
- stop_httpd
  test_done
index 694b77c8556d45ca594375683b1fd2209a346947,57f6f8c6286774815e00e038a9683e0afafbe409..b811d89cfd6df25fb2e42db6f05a69cf0b7a6c3b
@@@ -408,21 -408,4 +408,20 @@@ test_expect_success 'print HTTP error w
        test_i18ngrep "unable to access.*/redir-to/502" stderr
  '
  
- stop_httpd
 +test_expect_success 'fetching via http alternates works' '
 +      parent=$HTTPD_DOCUMENT_ROOT_PATH/alt-parent.git &&
 +      git init --bare "$parent" &&
 +      git -C "$parent" --work-tree=. commit --allow-empty -m foo &&
 +      git -C "$parent" update-server-info &&
 +      commit=$(git -C "$parent" rev-parse HEAD) &&
 +
 +      child=$HTTPD_DOCUMENT_ROOT_PATH/alt-child.git &&
 +      git init --bare "$child" &&
 +      echo "../../alt-parent.git/objects" >"$child/objects/info/alternates" &&
 +      git -C "$child" update-ref HEAD $commit &&
 +      git -C "$child" update-server-info &&
 +
 +      git -c http.followredirects=true clone "$HTTPD_URL/dumb/alt-child.git"
 +'
 +
  test_done
index c760514716e37868feb1bd6be94b05912999df85,9faf6349cf1c606ba1efa622d294cff174b368ec..ac74626a7b667c3723569cfbca9c77bc264c6728
@@@ -43,8 -43,7 +43,8 @@@ test_expect_success 'clone http reposit
        < Cache-Control: no-cache, max-age=0, must-revalidate
        < Content-Type: application/x-git-upload-pack-result
        EOF
 -      GIT_TRACE_CURL=true git clone --quiet $HTTPD_URL/smart/repo.git clone 2>err &&
 +      GIT_TRACE_CURL=true GIT_TEST_PROTOCOL_VERSION= \
 +              git clone --quiet $HTTPD_URL/smart/repo.git clone 2>err &&
        test_cmp file clone/file &&
        tr '\''\015'\'' Q <err |
        sed -e "
                /^< Content-Length: /d
                /^< Transfer-Encoding: /d
        " >actual &&
 -      sed -e "s/^> Accept-Encoding: .*/> Accept-Encoding: ENCODINGS/" \
 -                      actual >actual.smudged &&
 -      test_cmp exp actual.smudged &&
  
 -      grep "Accept-Encoding:.*gzip" actual >actual.gzip &&
 -      test_line_count = 2 actual.gzip
 +      # NEEDSWORK: If the overspecification of the expected result is reduced, we
 +      # might be able to run this test in all protocol versions.
 +      if test -z "$GIT_TEST_PROTOCOL_VERSION"
 +      then
 +              sed -e "s/^> Accept-Encoding: .*/> Accept-Encoding: ENCODINGS/" \
 +                              actual >actual.smudged &&
 +              test_cmp exp actual.smudged &&
 +
 +              grep "Accept-Encoding:.*gzip" actual >actual.gzip &&
 +              test_line_count = 2 actual.gzip
 +      fi
  '
  
  test_expect_success 'fetch changes via http' '
@@@ -110,13 -103,7 +110,13 @@@ test_expect_success 'used upload-pack s
        GET  /smart/repo.git/info/refs?service=git-upload-pack HTTP/1.1 200
        POST /smart/repo.git/git-upload-pack HTTP/1.1 200
        EOF
 -      check_access_log exp
 +
 +      # NEEDSWORK: If the overspecification of the expected result is reduced, we
 +      # might be able to run this test in all protocol versions.
 +      if test -z "$GIT_TEST_PROTOCOL_VERSION"
 +      then
 +              check_access_log exp
 +      fi
  '
  
  test_expect_success 'follow redirects (301)' '
@@@ -164,17 -151,7 +164,17 @@@ test_expect_success 'clone from auth-on
  
  test_expect_success 'no-op half-auth fetch does not require a password' '
        set_askpass wrong &&
 -      git --git-dir=half-auth fetch &&
 +
 +      # NEEDSWORK: When using HTTP(S), protocol v0 supports a "half-auth"
 +      # configuration with authentication required only when downloading
 +      # objects and not refs, by having the HTTP server only require
 +      # authentication for the "git-upload-pack" path and not "info/refs".
 +      # This is not possible with protocol v2, since both objects and refs
 +      # are obtained from the "git-upload-pack" path. A solution to this is
 +      # to teach the server and client to be able to inline ls-refs requests
 +      # as an Extra Parameter (see pack-protocol.txt), so that "info/refs"
 +      # can serve refs, just like it does in protocol v0.
 +      GIT_TEST_PROTOCOL_VERSION=0 git --git-dir=half-auth fetch &&
        expect_askpass none
  '
  
@@@ -238,14 -215,8 +238,14 @@@ test_expect_success 'cookies stored in 
        git config http.cookiefile cookies.txt &&
        git config http.savecookies true &&
        git ls-remote $HTTPD_URL/smart_cookies/repo.git master &&
 -      tail -3 cookies.txt | sort >cookies_tail.txt &&
 -      test_cmp expect_cookies.txt cookies_tail.txt
 +
 +      # NEEDSWORK: If the overspecification of the expected result is reduced, we
 +      # might be able to run this test in all protocol versions.
 +      if test -z "$GIT_TEST_PROTOCOL_VERSION"
 +      then
 +              tail -3 cookies.txt | sort >cookies_tail.txt &&
 +              test_cmp expect_cookies.txt cookies_tail.txt
 +      fi
  '
  
  test_expect_success 'transfer.hiderefs works over smart-http' '
@@@ -335,10 -306,7 +335,10 @@@ test_expect_success 'test allowreachabl
  
        git init --bare test_reachable.git &&
        git -C test_reachable.git remote add origin "$HTTPD_URL/smart/repo.git" &&
 -      test_must_fail git -C test_reachable.git fetch origin "$(git rev-parse HEAD)"
 +      # Some protocol versions (e.g. 2) support fetching
 +      # unadvertised objects, so restrict this test to v0.
 +      test_must_fail env GIT_TEST_PROTOCOL_VERSION= \
 +              git -C test_reachable.git fetch origin "$(git rev-parse HEAD)"
  '
  
  test_expect_success 'test allowanysha1inwant with unreachable' '
  
        git init --bare test_reachable.git &&
        git -C test_reachable.git remote add origin "$HTTPD_URL/smart/repo.git" &&
 -      test_must_fail git -C test_reachable.git fetch origin "$(git rev-parse HEAD)" &&
 +      # Some protocol versions (e.g. 2) support fetching
 +      # unadvertised objects, so restrict this test to v0.
 +      test_must_fail env GIT_TEST_PROTOCOL_VERSION= \
 +              git -C test_reachable.git fetch origin "$(git rev-parse HEAD)" &&
  
        git -C "$server" config uploadpack.allowanysha1inwant 1 &&
        git -C test_reachable.git fetch origin "$(git rev-parse HEAD)"
@@@ -469,5 -434,4 +469,4 @@@ test_expect_success 'server-side error 
        grep "server-side error" actual
  '
  
- stop_httpd
  test_done
diff --combined t/t5601-clone.sh
index a454b143ea820392a8d41712d587cb144fc9a3df,b04d66868490e2db67ceee695498c921237b30ba..23854cab263d467ba189879add1fb6b408e00792
@@@ -345,7 -345,7 +345,7 @@@ expect_ssh () 
  }
  
  test_expect_success 'clone myhost:src uses ssh' '
 -      git clone myhost:src ssh-clone &&
 +      GIT_TEST_PROTOCOL_VERSION=0 git clone myhost:src ssh-clone &&
        expect_ssh myhost src
  '
  
@@@ -356,12 -356,12 +356,12 @@@ test_expect_success !MINGW,!CYGWIN 'clo
  '
  
  test_expect_success 'bracketed hostnames are still ssh' '
 -      git clone "[myhost:123]:src" ssh-bracket-clone &&
 +      GIT_TEST_PROTOCOL_VERSION=0 git clone "[myhost:123]:src" ssh-bracket-clone &&
        expect_ssh "-p 123" myhost src
  '
  
  test_expect_success 'OpenSSH variant passes -4' '
 -      git clone -4 "[myhost:123]:src" ssh-ipv4-clone &&
 +      GIT_TEST_PROTOCOL_VERSION=0 git clone -4 "[myhost:123]:src" ssh-ipv4-clone &&
        expect_ssh "-4 -p 123" myhost src
  '
  
@@@ -405,7 -405,7 +405,7 @@@ test_expect_success 'OpenSSH-like uplin
        test_when_finished "rm -f \"\$TRASH_DIRECTORY/uplink\"" &&
        GIT_SSH="$TRASH_DIRECTORY/uplink" &&
        test_when_finished "GIT_SSH=\"\$TRASH_DIRECTORY/ssh\$X\"" &&
 -      git clone "[myhost:123]:src" ssh-bracket-clone-sshlike-uplink &&
 +      GIT_TEST_PROTOCOL_VERSION=0 git clone "[myhost:123]:src" ssh-bracket-clone-sshlike-uplink &&
        expect_ssh "-p 123" myhost src
  '
  
@@@ -444,14 -444,14 +444,14 @@@ test_expect_success 'single quoted plin
  
  test_expect_success 'GIT_SSH_VARIANT overrides plink detection' '
        copy_ssh_wrapper_as "$TRASH_DIRECTORY/plink" &&
 -      GIT_SSH_VARIANT=ssh \
 -      git clone "[myhost:123]:src" ssh-bracket-clone-variant-1 &&
 +      GIT_TEST_PROTOCOL_VERSION=0 GIT_SSH_VARIANT=ssh \
 +              git clone "[myhost:123]:src" ssh-bracket-clone-variant-1 &&
        expect_ssh "-p 123" myhost src
  '
  
  test_expect_success 'ssh.variant overrides plink detection' '
        copy_ssh_wrapper_as "$TRASH_DIRECTORY/plink" &&
 -      git -c ssh.variant=ssh \
 +      GIT_TEST_PROTOCOL_VERSION=0 git -c ssh.variant=ssh \
                clone "[myhost:123]:src" ssh-bracket-clone-variant-2 &&
        expect_ssh "-p 123" myhost src
  '
@@@ -482,7 -482,7 +482,7 @@@ counter=
  # $3 path
  test_clone_url () {
        counter=$(($counter + 1))
 -      test_might_fail git clone "$1" tmp$counter &&
 +      test_might_fail env GIT_TEST_PROTOCOL_VERSION=0 git clone "$1" tmp$counter &&
        shift &&
        expect_ssh "$@"
  }
@@@ -733,6 -733,4 +733,4 @@@ test_expect_success 'partial clone usin
        partial_clone "$HTTPD_DOCUMENT_ROOT_PATH/server" "$HTTPD_URL/smart/server"
  '
  
- stop_httpd
  test_done
diff --combined t/t5700-protocol-v1.sh
index d5ed196bfd096f1153c392f25a841aff3a84d7ca,b0e4752232cdf1d6807a78968c1f9c22f507f217..7c9511c593c175b5065970b75319c6da03d68b31
@@@ -4,9 -4,6 +4,9 @@@ test_description='test git wire-protoco
  
  TEST_NO_CREATE_REPO=1
  
 +# This is a protocol-specific test.
 +GIT_TEST_PROTOCOL_VERSION=
 +
  . ./test-lib.sh
  
  # Test protocol v1 with 'git://' transport
@@@ -292,6 -289,4 +292,4 @@@ test_expect_success 'push with http:// 
        grep "git< version 1" log
  '
  
- stop_httpd
  test_done
diff --combined t/test-lib-functions.sh
index 681c41ba329a90db8c668fde4640025872f1e622,6a50dba39067a975b307410ff01eb83f27d11427..788ea1f18b99c5edacd9ae0ee81310141c799c6e
@@@ -593,15 -593,6 +593,15 @@@ test_dir_is_empty () 
        fi
  }
  
 +# Check if the file exists and has a size greater than zero
 +test_file_not_empty () {
 +      if ! test -s "$1"
 +      then
 +              echo "'$1' is not a non-empty file."
 +              false
 +      fi
 +}
 +
  test_path_is_missing () {
        if test -e "$1"
        then
@@@ -943,6 -934,34 +943,34 @@@ test_when_finished () 
                } && (exit \"\$eval_ret\"); eval_ret=\$?; $test_cleanup"
  }
  
+ # This function can be used to schedule some commands to be run
+ # unconditionally at the end of the test script, e.g. to stop a daemon:
+ #
+ #     test_expect_success 'test git daemon' '
+ #             git daemon &
+ #             daemon_pid=$! &&
+ #             test_atexit 'kill $daemon_pid' &&
+ #             hello world
+ #     '
+ #
+ # The commands will be executed before the trash directory is removed,
+ # i.e. the atexit commands will still be able to access any pidfiles or
+ # socket files.
+ #
+ # Note that these commands will be run even when a test script run
+ # with '--immediate' fails.  Be careful with your atexit commands to
+ # minimize any changes to the failed state.
+ test_atexit () {
+       # We cannot detect when we are in a subshell in general, but by
+       # doing so on Bash is better than nothing (the test will
+       # silently pass on other shells).
+       test "${BASH_SUBSHELL-0}" = 0 ||
+       error "bug in test script: test_atexit does nothing in a subshell"
+       test_atexit_cleanup="{ $*
+               } && (exit \"\$eval_ret\"); eval_ret=\$?; $test_atexit_cleanup"
+ }
  # Most tests can use the created repository, but some may need to create more.
  # Usage: test_create_repo <directory>
  test_create_repo () {
diff --combined t/test-lib.sh
index c14ebe68d3d1d1493ccf1aa220e0940597257ef8,ac3df9efd4d1463ddd8484e86af1d6b6f6e13765..38b157075a79bb7674394f4856a9781e2db22cae
@@@ -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
        --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=<N> requires the number of jobs to run" >&2
 +                      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*|"")
@@@ -634,6 -620,10 +634,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 TERM HUP
+ # 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
@@@ -1056,9 -1049,28 +1063,28 @@@ write_junit_xml_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" || {