Skip to content

Commit 78f1660

Browse files
committed
Correctly handle assertion failure panics for eventually/consistnetly "g Gomega"s in a goroutine
1 parent 6ebc0bf commit 78f1660

File tree

4 files changed

+33
-2
lines changed

4 files changed

+33
-2
lines changed

go.mod

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ go 1.18
55
require (
66
github.com/golang/protobuf v1.5.2
77
github.com/google/go-cmp v0.5.9
8-
github.com/onsi/ginkgo/v2 v2.5.1
8+
github.com/onsi/ginkgo/v2 v2.6.1
99
golang.org/x/net v0.4.0
1010
gopkg.in/yaml.v3 v3.0.1
1111
)

go.sum

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,10 @@ github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
88
github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
99
github.com/onsi/ginkgo/v2 v2.5.1 h1:auzK7OI497k6x4OvWq+TKAcpcSAlod0doAH72oIN0Jw=
1010
github.com/onsi/ginkgo/v2 v2.5.1/go.mod h1:63DOGlLAH8+REH8jUGdL3YpCpu7JODesutUjdENfUAc=
11+
github.com/onsi/ginkgo/v2 v2.6.0 h1:9t9b9vRUbFq3C4qKFCGkVuq/fIHji802N1nrtkh1mNc=
12+
github.com/onsi/ginkgo/v2 v2.6.0/go.mod h1:63DOGlLAH8+REH8jUGdL3YpCpu7JODesutUjdENfUAc=
13+
github.com/onsi/ginkgo/v2 v2.6.1 h1:1xQPCjcqYw/J5LchOcp4/2q/jzJFjiAOc25chhnDw+Q=
14+
github.com/onsi/ginkgo/v2 v2.6.1/go.mod h1:yjiuMwPokqY1XauOgju45q3sJt6VzQ/Fict1LFVcsAo=
1115
golang.org/x/net v0.4.0 h1:Q5QPcMlvfxFTAPV0+07Xz/MpK9NTXu2VDUuy0FeMfaU=
1216
golang.org/x/net v0.4.0/go.mod h1:MBQ8lrhLObU/6UmLb4fmbmk5OcyYmqtbGd/9yIeKjEE=
1317
golang.org/x/sys v0.3.0 h1:w8ZOecv6NaNa/zC8944JTU3vz4u6Lagfk4RPQxv92NQ=

internal/async_assertion.go

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,17 @@ type contextWithAttachProgressReporter interface {
2020
AttachProgressReporter(func() string) func()
2121
}
2222

23+
type asyncGomegaHaltExecutionError struct{}
24+
25+
func (a asyncGomegaHaltExecutionError) GinkgoRecoverShouldIgnoreThisPanic() {}
26+
func (a asyncGomegaHaltExecutionError) Error() string {
27+
return `An assertion has failed in a goroutine. You should call
28+
29+
defer GinkgoRecover()
30+
31+
at the top of the goroutine that caused this panic. This will allow Ginkgo and Gomega to correctly capture and manage this panic.`
32+
}
33+
2334
type AsyncAssertionType uint
2435

2536
const (
@@ -229,7 +240,8 @@ func (assertion *AsyncAssertion) buildActualPoller() (func() (interface{}, error
229240
}
230241
_, file, line, _ := runtime.Caller(skip + 1)
231242
assertionFailure = fmt.Errorf("Assertion in callback at %s:%d failed:\n%s", file, line, message)
232-
panic("stop execution")
243+
// we throw an asyncGomegaHaltExecutionError so that defer GinkgoRecover() can catch this error if the user makes an assertion in a goroutine
244+
panic(asyncGomegaHaltExecutionError{})
233245
})))
234246
}
235247
if takesContext {

internal/async_assertion_test.go

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -696,6 +696,21 @@ var _ = Describe("Asynchronous Assertions", func() {
696696
Ω(ig.FailureMessage).Should(BeEmpty())
697697
})
698698

699+
It("correctly handles the case (in concert with Ginkgo) when an assertion fails in a goroutine", func() {
700+
count := 0
701+
ig.G.Eventually(func(g Gomega) {
702+
c := make(chan interface{})
703+
go func() {
704+
defer GinkgoRecover()
705+
defer close(c)
706+
count += 1
707+
g.Expect(count).To(Equal(3)) //panics!
708+
}()
709+
<-c
710+
}).WithTimeout(30 * time.Millisecond).WithPolling(10 * time.Millisecond).Should(Succeed())
711+
Ω(count).Should(Equal(3))
712+
})
713+
699714
Context("when making a ShouldNot assertion", func() {
700715
It("doesn't succeed until all extra values are zero, there are no failed assertions, and the matcher is (not) satisfied", func() {
701716
counter, s, f, err := 0, "hi", Foo{Bar: "hi"}, errors.New("hi")

0 commit comments

Comments
 (0)