Skip to content

Commit 817c09b

Browse files
committed
Ensure CurrentSpecReport and AddReportEntry are thread-safe
1 parent e5dfce4 commit 817c09b

File tree

2 files changed

+90
-24
lines changed

2 files changed

+90
-24
lines changed
Lines changed: 75 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,35 +1,92 @@
11
package internal_integration_test
22

33
import (
4+
"fmt"
5+
"time"
6+
47
. "github.com/onsi/ginkgo/v2"
58
"github.com/onsi/ginkgo/v2/types"
69
. "github.com/onsi/gomega"
710
)
811

912
var _ = Describe("ReportEntries", func() {
10-
BeforeEach(func() {
11-
success, _ := RunFixture("Report Entries", func() {
12-
BeforeSuite(func() {
13-
AddReportEntry("bridge", "engaged")
14-
})
13+
Context("happy path", func() {
14+
BeforeEach(func() {
15+
success, _ := RunFixture("Report Entries", func() {
16+
BeforeSuite(func() {
17+
AddReportEntry("bridge", "engaged")
18+
})
19+
20+
It("adds-entries", func() {
21+
AddReportEntry("medical", "healthy")
22+
AddReportEntry("engineering", "on fire")
23+
})
1524

16-
It("adds-entries", func() {
17-
AddReportEntry("medical", "healthy")
18-
AddReportEntry("engineering", "on fire")
25+
It("adds-no-entries", func() {})
1926
})
27+
Ω(success).Should(BeTrue())
28+
})
2029

21-
It("adds-no-entries", func() {})
30+
It("attaches entries to the report", func() {
31+
Ω(reporter.Did.Find("adds-entries").ReportEntries[0].Name).Should(Equal("medical"))
32+
Ω(reporter.Did.Find("adds-entries").ReportEntries[0].Value.String()).Should(Equal("healthy"))
33+
Ω(reporter.Did.Find("adds-entries").ReportEntries[1].Name).Should(Equal("engineering"))
34+
Ω(reporter.Did.Find("adds-entries").ReportEntries[1].Value.String()).Should(Equal("on fire"))
35+
Ω(reporter.Did.Find("adds-no-entries").ReportEntries).Should(BeEmpty())
36+
Ω(reporter.Did.FindByLeafNodeType(types.NodeTypeBeforeSuite).ReportEntries[0].Name).Should(Equal("bridge"))
37+
Ω(reporter.Did.FindByLeafNodeType(types.NodeTypeBeforeSuite).ReportEntries[0].Value.String()).Should(Equal("engaged"))
2238
})
23-
Ω(success).Should(BeTrue())
2439
})
2540

26-
It("attaches entries to the report", func() {
27-
Ω(reporter.Did.Find("adds-entries").ReportEntries[0].Name).Should(Equal("medical"))
28-
Ω(reporter.Did.Find("adds-entries").ReportEntries[0].Value.String()).Should(Equal("healthy"))
29-
Ω(reporter.Did.Find("adds-entries").ReportEntries[1].Name).Should(Equal("engineering"))
30-
Ω(reporter.Did.Find("adds-entries").ReportEntries[1].Value.String()).Should(Equal("on fire"))
31-
Ω(reporter.Did.Find("adds-no-entries").ReportEntries).Should(BeEmpty())
32-
Ω(reporter.Did.FindByLeafNodeType(types.NodeTypeBeforeSuite).ReportEntries[0].Name).Should(Equal("bridge"))
33-
Ω(reporter.Did.FindByLeafNodeType(types.NodeTypeBeforeSuite).ReportEntries[0].Value.String()).Should(Equal("engaged"))
41+
Context("avoiding races", func() {
42+
BeforeEach(func() {
43+
success, _ := RunFixture("Report Entries - but no races", func() {
44+
BeforeEach(func() {
45+
stop := make(chan interface{})
46+
done := make(chan interface{})
47+
ticker := time.NewTicker(10 * time.Millisecond)
48+
i := 0
49+
go func() {
50+
for {
51+
select {
52+
case <-ticker.C:
53+
AddReportEntry(fmt.Sprintf("report-%d", i))
54+
i++
55+
case <-stop:
56+
ticker.Stop()
57+
close(done)
58+
return
59+
}
60+
}
61+
}()
62+
DeferCleanup(func() {
63+
close(stop)
64+
<-done
65+
})
66+
})
67+
68+
It("reporter", func() {
69+
for i := 0; i < 5; i++ {
70+
time.Sleep(20 * time.Millisecond)
71+
AddReportEntry(fmt.Sprintf("waiting... %d", i))
72+
Ω(len(CurrentSpecReport().ReportEntries)).Should(BeNumerically("<", (i+1)*10))
73+
}
74+
})
75+
76+
ReportAfterEach(func(report SpecReport) {
77+
//no races here, either
78+
Ω(len(report.ReportEntries)).Should(BeNumerically(">", 5))
79+
})
80+
81+
})
82+
Ω(success).Should(BeTrue())
83+
})
84+
85+
It("attaches entries without racing", func() {
86+
Ω(reporter.Did.Find("reporter").ReportEntries).Should(ContainElement(HaveField("Name", "report-0")))
87+
Ω(reporter.Did.Find("reporter").ReportEntries).Should(ContainElement(HaveField("Name", "report-2")))
88+
Ω(reporter.Did.Find("reporter").ReportEntries).Should(ContainElement(HaveField("Name", "waiting... 1")))
89+
Ω(reporter.Did.Find("reporter").ReportEntries).Should(ContainElement(HaveField("Name", "waiting... 3")))
90+
})
3491
})
3592
})

internal/suite.go

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package internal
22

33
import (
44
"fmt"
5+
"sync"
56
"time"
67

78
"github.com/onsi/ginkgo/v2/formatter"
@@ -35,18 +36,20 @@ type Suite struct {
3536
interruptHandler interrupt_handler.InterruptHandlerInterface
3637
config types.SuiteConfig
3738

38-
skipAll bool
39-
report types.Report
40-
currentSpecReport types.SpecReport
41-
currentNode Node
39+
skipAll bool
40+
report types.Report
41+
currentSpecReport types.SpecReport
42+
currentSpecReportUserAccessLock *sync.Mutex
43+
currentNode Node
4244

4345
client parallel_support.Client
4446
}
4547

4648
func NewSuite() *Suite {
4749
return &Suite{
48-
tree: &TreeNode{},
49-
phase: PhaseBuildTopLevel,
50+
tree: &TreeNode{},
51+
phase: PhaseBuildTopLevel,
52+
currentSpecReportUserAccessLock: &sync.Mutex{},
5053
}
5154
}
5255

@@ -212,14 +215,20 @@ func (suite *Suite) pushCleanupNode(node Node) error {
212215
Spec Running methods - used during PhaseRun
213216
*/
214217
func (suite *Suite) CurrentSpecReport() types.SpecReport {
218+
suite.currentSpecReportUserAccessLock.Lock()
219+
defer suite.currentSpecReportUserAccessLock.Unlock()
215220
report := suite.currentSpecReport
216221
if suite.writer != nil {
217222
report.CapturedGinkgoWriterOutput = string(suite.writer.Bytes())
218223
}
224+
report.ReportEntries = make([]ReportEntry, len(report.ReportEntries))
225+
copy(report.ReportEntries, suite.currentSpecReport.ReportEntries)
219226
return report
220227
}
221228

222229
func (suite *Suite) AddReportEntry(entry ReportEntry) error {
230+
suite.currentSpecReportUserAccessLock.Lock()
231+
defer suite.currentSpecReportUserAccessLock.Unlock()
223232
if suite.phase != PhaseRun {
224233
return types.GinkgoErrors.AddReportEntryNotDuringRunPhase(entry.Location)
225234
}

0 commit comments

Comments
 (0)