diff --git a/internal/leafnodes/runner.go b/internal/leafnodes/runner.go index 04ec6dbf8..003f85160 100644 --- a/internal/leafnodes/runner.go +++ b/internal/leafnodes/runner.go @@ -68,8 +68,10 @@ func (r *runner) runAsync() (outcome types.SpecState, failure types.SpecFailure) done := make(chan interface{}, 1) go func() { + finished := false + defer func() { - if e := recover(); e != nil { + if e := recover(); e != nil || !finished { r.failer.Panic(codelocation.New(2), e) select { case <-done: @@ -81,6 +83,7 @@ func (r *runner) runAsync() (outcome types.SpecState, failure types.SpecFailure) }() r.asyncFunc(done) + finished = true }() select { @@ -93,8 +96,10 @@ func (r *runner) runAsync() (outcome types.SpecState, failure types.SpecFailure) return } func (r *runner) runSync() (outcome types.SpecState, failure types.SpecFailure) { + finished := false + defer func() { - if e := recover(); e != nil { + if e := recover(); e != nil || !finished { r.failer.Panic(codelocation.New(2), e) } @@ -102,6 +107,7 @@ func (r *runner) runSync() (outcome types.SpecState, failure types.SpecFailure) }() r.syncFunc() + finished = true return } diff --git a/internal/leafnodes/shared_runner_test.go b/internal/leafnodes/shared_runner_test.go index 9007d1ba7..f27fc55e1 100644 --- a/internal/leafnodes/shared_runner_test.go +++ b/internal/leafnodes/shared_runner_test.go @@ -96,6 +96,24 @@ func SynchronousSharedRunnerBehaviors(build func(body interface{}, timeout time. Ω(failure.ForwardedPanic).Should(Equal("ack!")) }) }) + + Context("when a panic occurs with a nil value", func() { + BeforeEach(func() { + outcome, failure = build(func() { + didRun = true + innerCodeLocation = codelocation.New(0) + panic(nil) + }, 0, failer, componentCodeLocation).Run() + }) + + It("should return the nil-valued panic", func() { + Ω(didRun).Should(BeTrue()) + + Ω(outcome).Should(Equal(types.SpecStatePanicked)) + Ω(failure.ForwardedPanic).Should(Equal("")) + }) + }) + }) } @@ -230,6 +248,23 @@ func AsynchronousSharedRunnerBehaviors(build func(body interface{}, timeout time Ω(failure.ForwardedPanic).Should(Equal("ack!")) }) }) + + Context("when the function panics with a nil value", func() { + BeforeEach(func() { + outcome, failure = build(func(done Done) { + didRun = true + innerCodeLocation = codelocation.New(0) + panic(nil) + }, 100*time.Millisecond, failer, componentCodeLocation).Run() + }) + + It("should return the nil-valued panic", func() { + Ω(didRun).Should(BeTrue()) + + Ω(outcome).Should(Equal(types.SpecStatePanicked)) + Ω(failure.ForwardedPanic).Should(Equal("")) + }) + }) }) }