testmark-bash

tests: when a script dies, show its last captured stderr before the scratch dir goes.

commit 1fa208e6909124884d3641d0730846c95732076a · parent c28251e29f · browse this tree
Ximianth, 2026-10-23 14:46:43 UTC

The EXIT trap deleted $work/err, where expect_fail and dump_parse had sent the message of whatever killed the shell, so a death was silent.
The trap also runs with the dying command's redirects still in place, so it writes to a copy of stderr saved at startup.
diff --git a/tests/lib.sh b/tests/lib.sh
index 54f633b..58081a8 100644
--- a/tests/lib.sh
+++ b/tests/lib.sh
@@ -12,11 +12,21 @@ TESTDATA=$ROOT/tests/testdata
 # shellcheck source=lib/testmark.bash
 source "$ROOT/lib/testmark.bash"
 
+RESULT=0
 work=$(mktemp -d)
-trap 'rm -rf "$work"' EXIT
+exec {stderr}>&2
+trap _exit EXIT
 cd "$work"
 
-RESULT=0
+## A nonzero exit with no FAIL row means the script died, maybe with the library's message in $work/err; this shows it before deleting $work.
+## It writes to the saved stderr: a shell that dies inside a redirect runs this trap with the redirect still in place.
+_exit() {
+	local rc=$?
+	if ((rc != 0 && RESULT == 0)) && [[ -s $work/err ]]; then
+		>&"$stderr" printf 'died (exit %s); last captured stderr:\n%s\n' "$rc" "$(<"$work/err")"
+	fi
+	rm -rf "$work"
+}
 
 _pass() {
 	printf 'PASS  %s\n' "$1"