File tree 2 files changed +31
-2
lines changed 2 files changed +31
-2
lines changed Original file line number Diff line number Diff line change @@ -307,6 +307,27 @@ func TestTRun(t *T) {
307
307
f : func (t * T ) {
308
308
t .Skip ()
309
309
},
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
+ },
310
331
}}
311
332
for _ , tc := range testCases {
312
333
ctx := newTestContext (tc .maxPar , newMatcher (regexp .MatchString , "" , "" ))
Original file line number Diff line number Diff line change @@ -196,13 +196,14 @@ var (
196
196
// common holds the elements common between T and B and
197
197
// captures common methods such as Errorf.
198
198
type common struct {
199
- mu sync.RWMutex // guards output and failed
199
+ mu sync.RWMutex // guards output, failed, and done.
200
200
output []byte // Output generated by test or benchmark.
201
201
w io.Writer // For flushToParent.
202
202
chatty bool // A copy of the chatty flag.
203
203
failed bool // Test or benchmark has failed.
204
204
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.
206
207
207
208
parent * common
208
209
level int // Nesting depth of test or benchmark.
@@ -351,6 +352,10 @@ func (c *common) Fail() {
351
352
}
352
353
c .mu .Lock ()
353
354
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
+ }
354
359
c .failed = true
355
360
}
356
361
@@ -540,6 +545,9 @@ func tRunner(t *T, fn func(t *T)) {
540
545
}
541
546
t .report () // Report after all subtests have finished.
542
547
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
543
551
t .signal <- true
544
552
}()
545
553
You can’t perform that action at this time.
0 commit comments