Skip to content

Commit 5a96c93

Browse files
committed
FIX race condition in test finish/begin
Avoid using two different channels to process test begin events and test finish events. This avoids a race between seeing a test begin and seeing it finish. Thanks to Comron for reporting this bug.
1 parent 7c5bcf2 commit 5a96c93

File tree

1 file changed

+29
-26
lines changed

1 file changed

+29
-26
lines changed

src/qa/suite/suite.go

+29-26
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,9 @@ import (
1212
"qa/tapjio"
1313
)
1414

15-
type testResult struct {
16-
testEvent tapjio.TestEvent
15+
type testEventUnion struct {
16+
testBegan *tapjio.TestStartedEvent
17+
testEvent *tapjio.TestEvent
1718
testError error
1819
}
1920

@@ -83,8 +84,7 @@ func (self *testSuiteRunner) Run(
8384

8485
var abort = false
8586
var traceChan = make(chan tapjio.TraceEvent, numWorkers)
86-
var testResultChan = make(chan testResult, numWorkers)
87-
var testStartChan = make(chan tapjio.TestStartedEvent, numWorkers)
87+
var testChan = make(chan testEventUnion, numWorkers)
8888

8989
var awaitJobs sync.WaitGroup
9090
awaitJobs.Add(numWorkers)
@@ -96,7 +96,7 @@ func (self *testSuiteRunner) Run(
9696
for testRunner := range testRunnerChan {
9797
if abort {
9898
for i := testRunner.TestCount(); i > 0; i-- {
99-
testResultChan <- testResult{testError: errors.New("already aborted")}
99+
testChan <- testEventUnion{testError: errors.New("already aborted")}
100100
}
101101
} else {
102102
var awaitRun sync.WaitGroup
@@ -105,18 +105,18 @@ func (self *testSuiteRunner) Run(
105105
env,
106106
tapjio.DecodingCallbacks{
107107
OnTestBegin: func(test tapjio.TestStartedEvent) error {
108-
testStartChan <- test
108+
testChan <- testEventUnion{&test, nil, nil}
109109
return nil
110110
},
111111
OnTest: func(test tapjio.TestEvent) error {
112-
testResultChan <- testResult{test, nil}
112+
testChan <- testEventUnion{nil, &test, nil}
113113
return nil
114114
},
115115
OnTrace: func(trace tapjio.TraceEvent) error {
116116
traceChan <- trace
117117
return nil
118118
},
119-
OnFinal: func(final tapjio.FinalEvent) error {
119+
OnEnd: func(reason error) error {
120120
awaitRun.Done()
121121
return nil
122122
},
@@ -144,28 +144,31 @@ func (self *testSuiteRunner) Run(
144144
if err != nil {
145145
return
146146
}
147-
case testStart := <-testStartChan:
148-
err = visitor.TestStarted(testStart)
149-
if err != nil {
150-
return
151-
}
152-
case testResult := <-testResultChan:
153-
err = testResult.testError
154-
if err == nil {
155-
test := testResult.testEvent
156-
final.Counts.Increment(test.Status)
157-
158-
err = visitor.TestFinished(test)
147+
case testEventUnion := <-testChan:
148+
begin := testEventUnion.testBegan
149+
if begin != nil {
150+
err = visitor.TestStarted(*begin)
159151
if err != nil {
160152
return
161153
}
162-
}
154+
} else {
155+
err = testEventUnion.testError
156+
if err == nil {
157+
test := testEventUnion.testEvent
158+
final.Counts.Increment(test.Status)
159+
160+
err = visitor.TestFinished(*test)
161+
if err != nil {
162+
return
163+
}
164+
}
163165

164-
if err != nil {
165-
abort = true
166-
final.Counts.Increment(tapjio.Error)
167-
fmt.Fprintln(os.Stderr, "Error:", err)
168-
return
166+
if err != nil {
167+
abort = true
168+
final.Counts.Increment(tapjio.Error)
169+
fmt.Fprintln(os.Stderr, "Error:", err)
170+
return
171+
}
169172
}
170173
}
171174
}

0 commit comments

Comments
 (0)