Skip to content

Commit ab9d037

Browse files
changkunianlancetaylor
authored andcommitted
[release-branch.go1.14] testing: fix data race between parallel subtests
This CL fixes a race condition if there are two subtests, and one finishing but the other is panicking. For #37551 Fixes #37959 Change-Id: Ic33963eb338aec228964b95f7c34a0d207b91e00 Reviewed-on: https://go-review.googlesource.com/c/go/+/221322 Run-TryBot: Ian Lance Taylor <[email protected]> TryBot-Result: Gobot Gobot <[email protected]> Reviewed-by: Ian Lance Taylor <[email protected]> (cherry picked from commit 93a9561) Reviewed-on: https://go-review.googlesource.com/c/go/+/224257 Reviewed-by: Emmanuel Odeke <[email protected]> Reviewed-by: Changkun Ou <[email protected]>
1 parent 564c76a commit ab9d037

File tree

2 files changed

+35
-6
lines changed

2 files changed

+35
-6
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
[short] skip
2+
[!race] skip
3+
4+
! go test -v -race main_panic/testmain_parallel_sub_panic_test.go
5+
! stdout 'DATA RACE'
6+
-- main_panic/testmain_parallel_sub_panic_test.go --
7+
package testmain_parallel_sub_panic_test
8+
9+
import "testing"
10+
11+
func setup() { println("setup()") }
12+
func teardown() { println("teardown()") }
13+
func TestA(t *testing.T) {
14+
t.Run("1", func(t *testing.T) {
15+
t.Run("1", func(t *testing.T) {
16+
t.Parallel()
17+
panic("A/1/1 panics")
18+
})
19+
t.Run("2", func(t *testing.T) {
20+
t.Parallel()
21+
println("A/1/2 is ok")
22+
})
23+
})
24+
}
25+
26+
func TestMain(m *testing.M) {
27+
setup()
28+
defer teardown()
29+
m.Run()
30+
}

src/testing/testing.go

+5-6
Original file line numberDiff line numberDiff line change
@@ -927,16 +927,15 @@ func tRunner(t *T, fn func(t *T)) {
927927
t.Logf("cleanup panicked with %v", r)
928928
}
929929
// Flush the output log up to the root before dying.
930-
t.mu.Lock()
931-
root := &t.common
932-
for ; root.parent != nil; root = root.parent {
930+
for root := &t.common; root.parent != nil; root = root.parent {
931+
root.mu.Lock()
933932
root.duration += time.Since(root.start)
934-
fmt.Fprintf(root.parent.w, "--- FAIL: %s (%s)\n", root.name, fmtDuration(root.duration))
933+
d := root.duration
934+
root.mu.Unlock()
935+
root.flushToParent("--- FAIL: %s (%s)\n", root.name, fmtDuration(d))
935936
if r := root.parent.runCleanup(recoverAndReturnPanic); r != nil {
936937
fmt.Fprintf(root.parent.w, "cleanup panicked with %v", r)
937938
}
938-
root.parent.mu.Lock()
939-
io.Copy(root.parent.w, bytes.NewReader(root.output))
940939
}
941940
panic(err)
942941
}

0 commit comments

Comments
 (0)