Closed mdwhatcott closed 10 years ago
@swaits - Ok, this is a really "fun" one. It turns out that your code was calling panic(nil)
. Stated in a different way, the error your code was passing into the panic function was nil
. So, when GoConvey calls recover()
to maintain control of execution it appeared that there was no panic because what the recover
function returned was nil! So, the moral of the story here is don't ever call panic
with nil
. It prevents the recovering method from knowing anything interesting about what has happened. I promise I'm not making this up :)
The only way I was able to discover this was by commenting out the panics in the Read
method and return dummy values. Then the tests started failing (which is better than passing for no good reason) and I knew I was on to something.
I wish there was something more I could do here to help but unfortunately, there simply is no way to know that panic
was called if the "error" it receives is nil
. I've added this to the wiki as a warning to future users of GoConvey and Go in general. At least we can say we've learned something interesting about Go. Thanks for providing the learning opportunity.
Well, 10 years later with the release of Go 1.21, we finally have closure!
Go 1.21 now defines that if a goroutine is panicking and recover was called directly by a deferred function, the return value of recover is guaranteed not to be nil. To ensure this, calling panic with a nil interface value (or an untyped nil) causes a run-time panic of type *runtime.PanicNilError.
Wow, nice @mdwhatcott!
@swaits submitted an example that called
panic
yet GoConvey calmly reported no errors. As expected, execution stopped after thepanic
because none of the assertions that followed the panic were executed or reported. Very strange.