test-lib: introduce 'test_atexit'

When running Apache, 'git daemon', or p4d, we want to kill them at the end of the test script, otherwise a leftover daemon process will keep its port open indefinitely, and thus will interfere with subsequent executions of the same test script. So far, we stop these daemon processes "manually", i.e.: - by registering functions or commands in the trap on EXIT to stop the daemon while preserving the last seen exit code before the trap (to deal with a failure when run with '--immediate' or with interrupts by ctrl-C), - and by invoking these functions/commands last thing before 'test_done' (and sometimes restoring the test framework's default trap on EXIT, to prevent the daemons from being killed twice). On one hand, we do this inconsistently, e.g. 'git p4' tests invoke different functions in the trap on EXIT and in the last test before 'test_done', and they neither restore the test framework's default trap on EXIT nor preserve the last seen exit code. On the other hand, this is error prone, because, as shown in a previous patch in this series, any output from the cleanup commands in the trap on EXIT can prevent a proper cleanup when a test script run with '--verbose-log' and certain shells, notably 'dash', is interrupted. Let's introduce 'test_atexit', which is loosely modeled after 'test_when_finished', but has a broader scope: rather than running the commands after the current test case, run them when the test script finishes, and also run them when the test is interrupted, or exits early in case of a failure while the '--immediate' option is in effect. When running the cleanup commands at the end of a successful test, then they will be run in 'test_done' before it removes the trash directory, i.e. the cleanup commands will still be able to access any pidfiles or socket files in there. When running the cleanup commands after an interrupt or failure with '--immediate', then they will be run in the trap on EXIT. In both cases they will be run in 'test_eval_', i.e. both standard error and output of all cleanup commands will go where they should according to the '-v' or '--verbose-log' options, and thus won't cause any troubles when interrupting a test script run with '--verbose-log'. Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de> Signed-off-by: SZEDER Gábor <szeder.dev@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Johannes Schindelin committed Mar 13, 2019 at 13:24 UTC 900721e15c43742955878dbbdb24c5a2ce262630
4 files changed +89
t/README
+20
@@ -862,6 +862,26 @@ library for your script to use.
862 ...
863 '
864
865 + - test_atexit <script>
866 +
867 + Prepend <script> to a list of commands to run unconditionally to
868 + clean up before the test script exits, e.g. to stop a daemon:
869 +
870 + test_expect_success 'test git daemon' '
871 + git daemon &
872 + daemon_pid=$! &&
873 + test_atexit 'kill $daemon_pid' &&
874 + hello world
875 + '
876 +
877 + The commands will be executed before the trash directory is removed,
878 + i.e. the atexit commands will still be able to access any pidfiles or
879 + socket files.
880 +
881 + Note that these commands will be run even when a test script run
882 + with '--immediate' fails. Be careful with your atexit commands to
883 + minimize any changes to the failed state.
884 +
885 - test_write_lines <lines>
886
887 Write <lines> on standard output, one line per argument.
t/t0000-basic.sh
+18
@@ -825,6 +825,24 @@ test_expect_success 'tests clean up even on failures' "
825 EOF
826 "
827
828 +test_expect_success 'test_atexit is run' "
829 + test_must_fail run_sub_test_lib_test \
830 + atexit-cleanup 'Run atexit commands' -i <<-\\EOF &&
831 + test_expect_success 'tests clean up even after a failure' '
832 + > ../../clean-atexit &&
833 + test_atexit rm ../../clean-atexit &&
834 + > ../../also-clean-atexit &&
835 + test_atexit rm ../../also-clean-atexit &&
836 + > ../../dont-clean-atexit &&
837 + (exit 1)
838 + '
839 + test_done
840 + EOF
841 + test_path_is_file dont-clean-atexit &&
842 + test_path_is_missing clean-atexit &&
843 + test_path_is_missing also-clean-atexit
844 +"
845 +
846 test_expect_success 'test_oid setup' '
847 test_oid_init
848 '
t/test-lib-functions.sh
+28
@@ -934,6 +934,34 @@ test_when_finished () {
934 } && (exit \"\$eval_ret\"); eval_ret=\$?; $test_cleanup"
935 }
936
937 +# This function can be used to schedule some commands to be run
938 +# unconditionally at the end of the test script, e.g. to stop a daemon:
939 +#
940 +# test_expect_success 'test git daemon' '
941 +# git daemon &
942 +# daemon_pid=$! &&
943 +# test_atexit 'kill $daemon_pid' &&
944 +# hello world
945 +# '
946 +#
947 +# The commands will be executed before the trash directory is removed,
948 +# i.e. the atexit commands will still be able to access any pidfiles or
949 +# socket files.
950 +#
951 +# Note that these commands will be run even when a test script run
952 +# with '--immediate' fails. Be careful with your atexit commands to
953 +# minimize any changes to the failed state.
954 +
955 +test_atexit () {
956 + # We cannot detect when we are in a subshell in general, but by
957 + # doing so on Bash is better than nothing (the test will
958 + # silently pass on other shells).
959 + test "${BASH_SUBSHELL-0}" = 0 ||
960 + error "bug in test script: test_atexit does nothing in a subshell"
961 + test_atexit_cleanup="{ $*
962 + } && (exit \"\$eval_ret\"); eval_ret=\$?; $test_atexit_cleanup"
963 +}
964 +
965 # Most tests can use the created repository, but some may need to create more.
966 # Usage: test_create_repo <directory>
967 test_create_repo () {
t/test-lib.sh
+23
@@ -620,6 +620,10 @@ test_external_has_tap=0
620
621 die () {
622 code=$?
623 + # This is responsible for running the atexit commands even when a
624 + # test script run with '--immediate' fails, or when the user hits
625 + # ctrl-C, i.e. when 'test_done' is not invoked at all.
626 + test_atexit_handler || code=$?
627 if test -n "$GIT_EXIT_OK"
628 then
629 exit $code
@@ -1045,9 +1049,28 @@ write_junit_xml_testcase () {
1049 junit_have_testcase=t
1050 }
1051
1052 +test_atexit_cleanup=:
1053 +test_atexit_handler () {
1054 + # In a succeeding test script 'test_atexit_handler' is invoked
1055 + # twice: first from 'test_done', then from 'die' in the trap on
1056 + # EXIT.
1057 + # This condition and resetting 'test_atexit_cleanup' below makes
1058 + # sure that the registered cleanup commands are run only once.
1059 + test : != "$test_atexit_cleanup" || return 0
1060 +
1061 + setup_malloc_check
1062 + test_eval_ "$test_atexit_cleanup"
1063 + test_atexit_cleanup=:
1064 + teardown_malloc_check
1065 +}
1066 +
1067 test_done () {
1068 GIT_EXIT_OK=t
1069
1070 + # Run the atexit commands _before_ the trash directory is
1071 + # removed, so the commands can access pidfiles and socket files.
1072 + test_atexit_handler
1073 +
1074 if test -n "$write_junit_xml" && test -n "$junit_xml_path"
1075 then
1076 test -n "$junit_have_testcase" || {