@@ -395,10 +395,10 @@ type common struct {
395
395
cleanups []func () // optional functions to be called at the end of the test
396
396
cleanupName string // Name of the cleanup function.
397
397
cleanupPc []uintptr // The stack trace at the point where Cleanup was called.
398
+ finished bool // Test function has completed.
398
399
399
400
chatty * chattyPrinter // A copy of chattyPrinter, if the chatty flag is set.
400
401
bench bool // Whether the current test is a benchmark.
401
- finished bool // Test function has completed.
402
402
hasSub int32 // Written atomically.
403
403
raceErrors int // Number of races detected during test.
404
404
runner string // Function name of tRunner running the test.
@@ -738,7 +738,9 @@ func (c *common) FailNow() {
738
738
// it would run on a test failure. Because we send on c.signal during
739
739
// a top-of-stack deferred function now, we know that the send
740
740
// only happens after any other stacked defers have completed.
741
+ c .mu .Lock ()
741
742
c .finished = true
743
+ c .mu .Unlock ()
742
744
runtime .Goexit ()
743
745
}
744
746
@@ -837,15 +839,11 @@ func (c *common) Skipf(format string, args ...interface{}) {
837
839
// other goroutines created during the test. Calling SkipNow does not stop
838
840
// those other goroutines.
839
841
func (c * common ) SkipNow () {
840
- c .skip ()
841
- c .finished = true
842
- runtime .Goexit ()
843
- }
844
-
845
- func (c * common ) skip () {
846
842
c .mu .Lock ()
847
- defer c .mu .Unlock ()
848
843
c .skipped = true
844
+ c .finished = true
845
+ c .mu .Unlock ()
846
+ runtime .Goexit ()
849
847
}
850
848
851
849
// Skipped reports whether the test was skipped.
@@ -1138,10 +1136,16 @@ func tRunner(t *T, fn func(t *T)) {
1138
1136
err := recover ()
1139
1137
signal := true
1140
1138
1141
- if ! t .finished && err == nil {
1139
+ t .mu .RLock ()
1140
+ finished := t .finished
1141
+ t .mu .RUnlock ()
1142
+ if ! finished && err == nil {
1142
1143
err = errNilPanicOrGoexit
1143
1144
for p := t .parent ; p != nil ; p = p .parent {
1144
- if p .finished {
1145
+ p .mu .RLock ()
1146
+ finished = p .finished
1147
+ p .mu .RUnlock ()
1148
+ if finished {
1145
1149
t .Errorf ("%v: subtest may have called FailNow on a parent test" , err )
1146
1150
err = nil
1147
1151
signal = false
@@ -1235,7 +1239,9 @@ func tRunner(t *T, fn func(t *T)) {
1235
1239
fn (t )
1236
1240
1237
1241
// code beyond here will not be executed when FailNow is invoked
1242
+ t .mu .Lock ()
1238
1243
t .finished = true
1244
+ t .mu .Unlock ()
1239
1245
}
1240
1246
1241
1247
// Run runs f as a subtest of t called name. It runs f in a separate goroutine
0 commit comments