Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

panic(nil) in a test results in it immediately passing #167

Merged
merged 1 commit into from
Jun 10, 2015
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 8 additions & 2 deletions internal/leafnodes/runner.go
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand All @@ -81,6 +83,7 @@ func (r *runner) runAsync() (outcome types.SpecState, failure types.SpecFailure)
}()

r.asyncFunc(done)
finished = true
}()

select {
Expand All @@ -93,15 +96,18 @@ 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)
}

failure, outcome = r.failer.Drain(r.nodeType, r.componentIndex, r.codeLocation)
}()

r.syncFunc()
finished = true

return
}
35 changes: 35 additions & 0 deletions internal/leafnodes/shared_runner_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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("<nil>"))

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is this preferable to a more explicit, hardcoded error like test executed panic(nil) or runtime.Goexit in the standard library?

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok, it's getting wrapped with the "Test Panicked" message in failer.go. That looks good.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I went back and forth on whether this message should be more verbose. On one hand, <nil> is consistent with how Ginkgo normally behaves when you panic (and as you mentioned, Ginkgo already indicates that the test panicked). On the other hand, you'll get this same message when you call runtime.Goexit(), and that could be confusing.

})
})

})
}

Expand Down Expand Up @@ -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("<nil>"))
})
})
})
}

Expand Down