git.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Jonathan Nieder <jrnieder@gmail.com>
To: Jeff King <peff@peff.net>
Cc: Junio C Hamano <gitster@pobox.com>, git@vger.kernel.org
Subject: [PATCH] test-lib: some shells do not let $? propagate into an eval
Date: Thu, 6 May 2010 03:41:10 -0500	[thread overview]
Message-ID: <20100506084045.GA25917@progeny.tock> (raw)
In-Reply-To: <20100506065419.GA21009@coredump.intra.peff.net>

Jeff King wrote:
> On Thu, May 06, 2010 at 01:44:28AM -0500, Jonathan Nieder wrote:

>>  test_when_finished () {
>> 	test_cleanup="$* && $test_cleanup"
>>  }
>
> Doesn't that violate your rule that the cleanup will _always_ be run?

Thanks for the sanity check.

> Perhaps the simplest would be to just keep a cleanup_ret in the second
> eval (where you have eval_ret in the original patch), and then act
> appropriately after the eval finishes. That would be easier on the eyes,
> too, I think.

I tried the cleanup_ret idea; test_run_ ended up looking like this:

	test_cleanup=:
	eval >&3 2>&4 "$1"
	eval_ret=$?
	eval >&3 2>&4 ":; $test_cleanup"
	cleanup_ret=?
	(exit "$test_ret") && (exit "$cleanup_ret")
	eval_ret=$?
	return 0

That breaks the principle of keeping the ugliness in test_when_finished.
So here’s the minimal fix.

-- 8< --
Subject: test-lib: some shells do not let $? propagate into an eval

In 3bf7886 (test-lib: Let tests specify commands to be run at end of
test, 2010-05-02), the git test harness learned to run cleanup
commands unconditionally at the end of a test.  During each test,
the intended cleanup actions are collected in the test_cleanup variable
and evaluated.  That variable looks something like this:

	eval_ret=$?; clean_something && (exit "$eval_ret")
	eval_ret=$?; clean_something_else && (exit "$eval_ret")
	eval_ret=$?; final_cleanup && (exit "$eval_ret")
	eval_ret=$?

All cleanup actions are run unconditionally but if one of them fails
it is properly reported through $eval_ret.

On FreeBSD, unfortunately, $? is set at the beginning of an ‘eval’
to 0 instead of the exit status of the previous command.  This results
in tests using test_expect_code appearing to fail and all others
appearing to pass, unless their cleanup fails.  Avoid the problem by
setting eval_ret before the ‘eval’ begins.

Thanks to Jeff King for the explanation.

Cc: Jeff King <peff@peff.net>
Cc: Johannes Sixt <j6t@kdbg.org>
Signed-off-by: Jonathan Nieder <jrnieder@gmail.com>
---
I was also surprised to see this migrate to maint so quickly, but I
was happy to see it broke early and loudly.

Because there is some unhappiness with the feature[1], it might make
more sense to revert it for now.  If that discussion can be taken as
license to write tests that take down other tests with them on
failure, then such a revert would not interfere with other work.

[1] http://thread.gmane.org/gmane.comp.version-control.git/146375/focus=146451

 t/t0000-basic.sh |   21 +++++++++++++++++++++
 t/test-lib.sh    |    7 ++++---
 2 files changed, 25 insertions(+), 3 deletions(-)

diff --git a/t/t0000-basic.sh b/t/t0000-basic.sh
index f4ca4fc..3ec9cbe 100755
--- a/t/t0000-basic.sh
+++ b/t/t0000-basic.sh
@@ -73,6 +73,27 @@ then
 	exit 1
 fi
 
+clean=no
+test_expect_success 'tests clean up after themselves' '
+    test_when_finished clean=yes
+'
+
+cleaner=no
+test_expect_code 1 'tests clean up even after a failure' '
+    test_when_finished cleaner=yes &&
+    (exit 1)
+'
+
+if test $clean$cleaner != yesyes
+then
+	say "bug in test framework: cleanup commands do not work reliably"
+	exit 1
+fi
+
+test_expect_code 2 'failure to clean up causes the test to fail' '
+    test_when_finished "(exit 2)"
+'
+
 ################################################################
 # Basics of the basics
 
diff --git a/t/test-lib.sh b/t/test-lib.sh
index acce3d0..7422bba 100644
--- a/t/test-lib.sh
+++ b/t/test-lib.sh
@@ -366,8 +366,9 @@ test_debug () {
 }
 
 test_run_ () {
-	test_cleanup='eval_ret=$?'
+	test_cleanup=:
 	eval >&3 2>&4 "$1"
+	eval_ret=$?
 	eval >&3 2>&4 "$test_cleanup"
 	return 0
 }
@@ -567,8 +568,8 @@ test_cmp() {
 # the test to pass.
 
 test_when_finished () {
-	test_cleanup="eval_ret=\$?; { $*
-		} && (exit \"\$eval_ret\"); $test_cleanup"
+	test_cleanup="{ $*
+		} && (exit \"\$eval_ret\"); eval_ret=\$?; $test_cleanup"
 }
 
 # Most tests can use the created repository, but some may need to create more.
-- 
1.7.1

  reply	other threads:[~2010-05-06  8:40 UTC|newest]

Thread overview: 11+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2010-05-05  5:39 1.7.2 cycle will open soon Junio C Hamano
2010-05-06  5:52 ` Jeff King
2010-05-06  6:44   ` Jonathan Nieder
2010-05-06  6:54     ` Jeff King
2010-05-06  8:41       ` Jonathan Nieder [this message]
2010-05-06  8:57         ` [PATCH] test-lib: some shells do not let $? propagate into an eval Jeff King
2010-05-06 20:20           ` Junio C Hamano
2010-05-06  7:06     ` 1.7.2 cycle will open soon Johannes Sixt
2010-05-06  7:49       ` Jeff King
2010-05-06  8:01       ` Jonathan Nieder
2010-05-06  6:57   ` Johannes Sixt

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20100506084045.GA25917@progeny.tock \
    --to=jrnieder@gmail.com \
    --cc=git@vger.kernel.org \
    --cc=gitster@pobox.com \
    --cc=peff@peff.net \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).