Commit 66155134 authored by Rob Pike's avatar Rob Pike

testing: make signalling safer for parallel tests

Each test gets a private signal channel.
Also fix a bug that prevented parallel tests from running.

R=r, r
CC=golang-dev
https://golang.org/cl/5505061
parent b5216e2e
...@@ -182,7 +182,7 @@ func (c *common) Fatalf(format string, args ...interface{}) { ...@@ -182,7 +182,7 @@ func (c *common) Fatalf(format string, args ...interface{}) {
// Parallel signals that this test is to be run in parallel with (and only with) // Parallel signals that this test is to be run in parallel with (and only with)
// other parallel tests in this CPU group. // other parallel tests in this CPU group.
func (t *T) Parallel() { func (t *T) Parallel() {
t.signal <- nil // Release main testing loop t.signal <- (*T)(nil) // Release main testing loop
<-t.startParallel // Wait for serial tests to finish <-t.startParallel // Wait for serial tests to finish
} }
...@@ -236,11 +236,14 @@ func RunTests(matchString func(pat, str string) (bool, error), tests []InternalT ...@@ -236,11 +236,14 @@ func RunTests(matchString func(pat, str string) (bool, error), tests []InternalT
fmt.Fprintln(os.Stderr, "testing: warning: no tests to run") fmt.Fprintln(os.Stderr, "testing: warning: no tests to run")
return return
} }
// TODO: each test should have its own channel, although that means
// keeping track of the channels when we're running parallel tests.
signal := make(chan interface{})
for _, procs := range cpuList { for _, procs := range cpuList {
runtime.GOMAXPROCS(procs) runtime.GOMAXPROCS(procs)
// We build a new channel tree for each run of the loop.
// collector merges in one channel all the upstream signals from parallel tests.
// If all tests pump to the same channel, a bug can occur where a goroutine
// kicks off a test, fails, and still delivers a completion signal, which skews the
// counting.
var collector = make(chan interface{})
numParallel := 0 numParallel := 0
startParallel := make(chan bool) startParallel := make(chan bool)
...@@ -260,7 +263,7 @@ func RunTests(matchString func(pat, str string) (bool, error), tests []InternalT ...@@ -260,7 +263,7 @@ func RunTests(matchString func(pat, str string) (bool, error), tests []InternalT
} }
t := &T{ t := &T{
common: common{ common: common{
signal: signal, signal: make(chan interface{}),
}, },
name: testName, name: testName,
startParallel: startParallel, startParallel: startParallel,
...@@ -272,6 +275,9 @@ func RunTests(matchString func(pat, str string) (bool, error), tests []InternalT ...@@ -272,6 +275,9 @@ func RunTests(matchString func(pat, str string) (bool, error), tests []InternalT
go tRunner(t, &tests[i]) go tRunner(t, &tests[i])
out := (<-t.signal).(*T) out := (<-t.signal).(*T)
if out == nil { // Parallel run. if out == nil { // Parallel run.
go func() {
collector <- <-t.signal
}()
numParallel++ numParallel++
continue continue
} }
...@@ -287,7 +293,7 @@ func RunTests(matchString func(pat, str string) (bool, error), tests []InternalT ...@@ -287,7 +293,7 @@ func RunTests(matchString func(pat, str string) (bool, error), tests []InternalT
numParallel-- numParallel--
continue continue
} }
t := (<-signal).(*T) t := (<-collector).(*T)
t.report() t.report()
ok = ok && !t.failed ok = ok && !t.failed
running-- running--
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment