mirror of
https://github.com/golang/go.git
synced 2025-12-08 06:10:04 +00:00
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. Fixes #37551 Change-Id: Ic33963eb338aec228964b95f7c34a0d207b91e00 Reviewed-on: https://go-review.googlesource.com/c/go/+/221322 Run-TryBot: Ian Lance Taylor <iant@golang.org> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Ian Lance Taylor <iant@golang.org>
This commit is contained in:
parent
a4c48d61f5
commit
93a9561b23
2 changed files with 35 additions and 6 deletions
30
src/cmd/go/testdata/script/test_main_panic.txt
vendored
Normal file
30
src/cmd/go/testdata/script/test_main_panic.txt
vendored
Normal file
|
|
@ -0,0 +1,30 @@
|
||||||
|
[short] skip
|
||||||
|
[!race] skip
|
||||||
|
|
||||||
|
! go test -v -race main_panic/testmain_parallel_sub_panic_test.go
|
||||||
|
! stdout 'DATA RACE'
|
||||||
|
-- main_panic/testmain_parallel_sub_panic_test.go --
|
||||||
|
package testmain_parallel_sub_panic_test
|
||||||
|
|
||||||
|
import "testing"
|
||||||
|
|
||||||
|
func setup() { println("setup()") }
|
||||||
|
func teardown() { println("teardown()") }
|
||||||
|
func TestA(t *testing.T) {
|
||||||
|
t.Run("1", func(t *testing.T) {
|
||||||
|
t.Run("1", func(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
panic("A/1/1 panics")
|
||||||
|
})
|
||||||
|
t.Run("2", func(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
println("A/1/2 is ok")
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestMain(m *testing.M) {
|
||||||
|
setup()
|
||||||
|
defer teardown()
|
||||||
|
m.Run()
|
||||||
|
}
|
||||||
|
|
@ -928,16 +928,15 @@ func tRunner(t *T, fn func(t *T)) {
|
||||||
t.Logf("cleanup panicked with %v", r)
|
t.Logf("cleanup panicked with %v", r)
|
||||||
}
|
}
|
||||||
// Flush the output log up to the root before dying.
|
// Flush the output log up to the root before dying.
|
||||||
t.mu.Lock()
|
for root := &t.common; root.parent != nil; root = root.parent {
|
||||||
root := &t.common
|
root.mu.Lock()
|
||||||
for ; root.parent != nil; root = root.parent {
|
|
||||||
root.duration += time.Since(root.start)
|
root.duration += time.Since(root.start)
|
||||||
fmt.Fprintf(root.parent.w, "--- FAIL: %s (%s)\n", root.name, fmtDuration(root.duration))
|
d := root.duration
|
||||||
|
root.mu.Unlock()
|
||||||
|
root.flushToParent("--- FAIL: %s (%s)\n", root.name, fmtDuration(d))
|
||||||
if r := root.parent.runCleanup(recoverAndReturnPanic); r != nil {
|
if r := root.parent.runCleanup(recoverAndReturnPanic); r != nil {
|
||||||
fmt.Fprintf(root.parent.w, "cleanup panicked with %v", r)
|
fmt.Fprintf(root.parent.w, "cleanup panicked with %v", r)
|
||||||
}
|
}
|
||||||
root.parent.mu.Lock()
|
|
||||||
io.Copy(root.parent.w, bytes.NewReader(root.output))
|
|
||||||
}
|
}
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue