Skip to content

Commit 7b9d3ff

Browse files
committed
testing: don't be silent if a test's goroutine fails a test after test exits
Fixes #15654 Change-Id: I9bdaa9b76d480d75f24d95f0235efd4a79e3593e Reviewed-on: https://go-review.googlesource.com/23320 Reviewed-by: Russ Cox <[email protected]> Run-TryBot: Marcel van Lohuizen <[email protected]> TryBot-Result: Gobot Gobot <[email protected]> Reviewed-by: Joe Tsai <[email protected]>
1 parent dcc42c7 commit 7b9d3ff

File tree

2 files changed

+31
-2
lines changed

2 files changed

+31
-2
lines changed

src/testing/sub_test.go

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -307,6 +307,27 @@ func TestTRun(t *T) {
307307
f: func(t *T) {
308308
t.Skip()
309309
},
310+
}, {
311+
desc: "panic on goroutine fail after test exit",
312+
ok: false,
313+
maxPar: 4,
314+
f: func(t *T) {
315+
ch := make(chan bool)
316+
t.Run("", func(t *T) {
317+
go func() {
318+
<-ch
319+
defer func() {
320+
if r := recover(); r == nil {
321+
realTest.Errorf("expected panic")
322+
}
323+
ch <- true
324+
}()
325+
t.Errorf("failed after success")
326+
}()
327+
})
328+
ch <- true
329+
<-ch
330+
},
310331
}}
311332
for _, tc := range testCases {
312333
ctx := newTestContext(tc.maxPar, newMatcher(regexp.MatchString, "", ""))

src/testing/testing.go

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -196,13 +196,14 @@ var (
196196
// common holds the elements common between T and B and
197197
// captures common methods such as Errorf.
198198
type common struct {
199-
mu sync.RWMutex // guards output and failed
199+
mu sync.RWMutex // guards output, failed, and done.
200200
output []byte // Output generated by test or benchmark.
201201
w io.Writer // For flushToParent.
202202
chatty bool // A copy of the chatty flag.
203203
failed bool // Test or benchmark has failed.
204204
skipped bool // Test of benchmark has been skipped.
205-
finished bool
205+
finished bool // Test function has completed.
206+
done bool // Test is finished and all subtests have completed.
206207

207208
parent *common
208209
level int // Nesting depth of test or benchmark.
@@ -351,6 +352,10 @@ func (c *common) Fail() {
351352
}
352353
c.mu.Lock()
353354
defer c.mu.Unlock()
355+
// c.done needs to be locked to synchronize checks to c.done in parent tests.
356+
if c.done {
357+
panic("Fail in goroutine after " + c.name + " has completed")
358+
}
354359
c.failed = true
355360
}
356361

@@ -540,6 +545,9 @@ func tRunner(t *T, fn func(t *T)) {
540545
}
541546
t.report() // Report after all subtests have finished.
542547

548+
// Do not lock t.done to allow race detector to detect race in case
549+
// the user does not appropriately synchronizes a goroutine.
550+
t.done = true
543551
t.signal <- true
544552
}()
545553

0 commit comments

Comments
 (0)