diff options
Diffstat (limited to 'src/testing/testing.go')
| -rw-r--r-- | src/testing/testing.go | 17 |
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) } |
