SZEDER Gábor <[email protected]> writes:
> +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"
> +}
This chaining is modelled after how $test_cleaup is built and
maintained by test_when_finished. Use of eval_ret makes sense in
that original context as eval_ret _is_ used to keep track of the
result of 'test_eval_ "$1"' in test_run_ that executed the body
of a single test_expect_$something, and $test_cleanup would want to
keep the resulting status from that body when clean-up succeeds (or
otherwise, make that failure to clean-up visible as $eval_ret).
But does it make sense in the context of the whole test script to
try maintaining $eval_ret?
> # Most tests can use the created repository, but some may need to create
> more.
> # Usage: test_create_repo <directory>
> test_create_repo () {
> diff --git a/t/test-lib.sh b/t/test-lib.sh
> index db3875d1e4..b35881696f 100644
> --- a/t/test-lib.sh
> +++ b/t/test-lib.sh
> @@ -620,6 +620,10 @@ test_external_has_tap=0
>
> 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
> @@ -1045,9 +1049,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.
We are guaranteed to still have the trash directory when we are run
in the exit handler after getting interrupted or test_failure_()
exits under the "-i" option, and when test_done() calls us. What
will cause us trouble is the exit handler at the end of a successful
run after test_done() finishes. At that point, test_done would have
already cleared the trash directory, so we may not have enough state
to allow us to clean-up at exit.
Clearing the exit trap in test_done after it calls us might be an
alternative, but I think it is equivalent to clearing the
test_atexit_cleanup variable, and it is cleaner, so I think I agree
with the approach this patch uses.
> + # 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
I think test_when_finished uses a special value in $test_cleanup in
a similar way but it even skips when there is no point doing the
test_eval_ of the "accumulated" scriptlet when it is empty.
Shouldn't we be doing the same thing, i.e.
if test -z "$test_atexit_cleanup"
then
return 0
fi
... do the heavy lifting ...
test_atexit_cleanup=
That will make the handler truly a no-op when there is no atexit
defined.
> + 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" || {