aboutsummaryrefslogtreecommitdiff
path: root/src/testing/testing.go
diff options
context:
space:
mode:
Diffstat (limited to 'src/testing/testing.go')
-rw-r--r--src/testing/testing.go17
1 files changed, 16 insertions, 1 deletions
diff --git a/src/testing/testing.go b/src/testing/testing.go
index ed8b3630f1..5c06aea5f8 100644
--- a/src/testing/testing.go
+++ b/src/testing/testing.go
@@ -1638,15 +1638,22 @@ func tRunner(t *T, fn func(t *T)) {
if len(t.sub) > 0 {
// Run parallel subtests.
- // Decrease the running count for this test.
+
+ // Decrease the running count for this test and mark it as no longer running.
t.context.release()
+ running.Delete(t.name)
+
// Release the parallel subtests.
close(t.barrier)
// Wait for subtests to complete.
for _, sub := range t.sub {
<-sub.signal
}
+
+ // Run any cleanup callbacks, marking the test as running
+ // in case the cleanup hangs.
cleanupStart := time.Now()
+ running.Store(t.name, cleanupStart)
err := t.runCleanup(recoverAndReturnPanic)
t.duration += time.Since(cleanupStart)
if err != nil {
@@ -1733,11 +1740,19 @@ func (t *T) Run(name string, f func(t *T)) bool {
// without being preempted, even when their parent is a parallel test. This
// may especially reduce surprises if *parallel == 1.
go tRunner(t, f)
+
+ // The parent goroutine will block until the subtest either finishes or calls
+ // Parallel, but in general we don't know whether the parent goroutine is the
+ // top-level test function or some other goroutine it has spawned.
+ // To avoid confusing false-negatives, we leave the parent in the running map
+ // even though in the typical case it is blocked.
+
if !<-t.signal {
// At this point, it is likely that FailNow was called on one of the
// parent tests by one of the subtests. Continue aborting up the chain.
runtime.Goexit()
}
+
if t.chatty != nil && t.chatty.json {
t.chatty.Updatef(t.parent.name, "=== NAME %s\n", t.parent.name)
}