git/list[1] front-page[2] threads[3] people[4] search[5] about
 

Re: [PATCH 03/11] test-lib: introduce 'test_atexit'

From
Junio C Hamano <gitster@pobox.com>
Date
Mar 14, 2019, 03:21 UTC
Message-ID
<xmqqh8c6b0pv.fsf@gitster-ct.c.googlers.com>
In-Reply-To
<20190313122419.2210-4-szeder.dev@gmail.com>
SZEDER Gábor <szeder.dev@gmail.com> writes:
Show 9 quoted lines
> +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?

Show 27 quoted lines
>  # 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.

Show 16 quoted lines
> +	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" || {
Previous: SZEDER GáborNext: SZEDER Gábor
Message 9 of 21 in “tests: introduce 'test_atexit'”
  1. 00/11 tests: introduce 'test_atexit'SZEDER Gábor, Mar 13, 2019
  2. 01/11 test-lib: fix interrupt handling with 'dash' and '--verbose-log -x'SZEDER Gábor, Mar 13, 2019
  3. Junio C HamanoMar 14, 2019
  4. SZEDER GáborMar 14, 2019
  5. 02/11 t/lib-git-daemon: make sure to kill the 'git-daemon' processSZEDER Gábor, Mar 13, 2019
  6. Junio C HamanoMar 14, 2019
  7. 04/11 git-daemon: use 'test_atexit` to stop 'git-daemon'SZEDER Gábor, Mar 13, 2019
  8. 03/11 test-lib: introduce 'test_atexit'SZEDER Gábor, Mar 13, 2019
  9. Junio C HamanoMar 14, 2019
  10. SZEDER GáborMar 14, 2019
  11. Junio C HamanoMar 18, 2019
  12. 05/11 tests: use 'test_atexit' to stop httpdSZEDER Gábor, Mar 13, 2019
  13. Junio C HamanoMar 14, 2019
  14. Junio C HamanoMar 14, 2019
  15. SZEDER GáborMar 14, 2019
  16. 06/11 t0301-credential-cache: use 'test_atexit' to stop the credentials helperSZEDER Gábor, Mar 13, 2019
  17. 07/11 git p4 test: use 'test_atexit' to kill p4d and the watchdog processSZEDER Gábor, Mar 13, 2019
  18. 10/11 git p4 test: disable '-x' tracing in the p4d watchdog loopSZEDER Gábor, Mar 13, 2019
  19. 09/11 git p4 test: simplify timeout handlingSZEDER Gábor, Mar 13, 2019
  20. 11/11 t9811-git-p4-label-import: fix pipeline negationSZEDER Gábor, Mar 13, 2019
  21. 08/11 git p4 test: clean up the p4d cleanup functionsSZEDER Gábor, Mar 13, 2019

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.