Assert and the optional Message

Jonathan M Davis jmdavisProg at gmx.com
Sat Mar 10 09:08:56 PST 2012


On Saturday, March 10, 2012 17:03:43 Jacob Carlborg wrote:
> On 2012-03-09 20:06, Jonathan M Davis wrote:
> > In what way? Yes, they're _catchable_, but everything that was on the
> > unwound portion of the stack is now in an undefined state. So, recovering
> > from the AssertError and continuing execution doesn't work. So, a handler
> > can catch the AssertError and do something before letting it kill the
> > program, but portions of the program are definitely in an undefined state
> > when an AssertError is caught. The closer the catch point is to the throw
> > point, the less of an issue that is, but unless you can guarantee that no
> > destructors, scope statements, or finally blocks were between the throw
> > point and the catch point, then some portion of the program is in an
> > undefined state, and continuing program execution is a bad idea. It _is_
> > possible to catch an AssertError, but you have to be very careful about
> > what you do after that.
> > 
> > I'm not aware of anything in contracts which would involve catching an
> > AssertError and then continuing execution. When a contract fails, it's
> > going to kill the program just like any other assertion failure does. So,
> > I'm not quite sure what you're referring to.
> > 
> > - Jonathan M Davis
> 
> This might be how it works today, but I think it's a broken design.
> AssertError MUST be SAFELY catchable to be able to write unit testing
> frameworks.

I honestly don't think that Walter even considered unit testing frameworks 
when he came up with the design. He built unit tests into the language. So, 
from his point of view, why would you need a unit testing framework? He 
probably didn't even consider it.

And AssertErrors _are_ catchable. You just have to deal with the fact that 
destructors, scope statements, and finally blocks all get skipped by them. So, 
cleanup doesn't tend to happen in their presence. That's more of an issue with 
a general unit testing framework than it would be if you were doing it closer 
to the throw point, but it doesn't necessarily make it so that the unit test 
framework doesn't work. It _does_ risk making it flakier though. What would be 
particularly risky is trying to continue a particular unit test block after a 
failed assertion, since the failures wouldn't be isolated (though personally, 
I think that that would be a bad idea even AssertErrors _didn't_ skip 
anything, simply because the failures aren't isolated, and you get a bunch of 
failures simply because you already had one). Running subsequent unittest 
blocks should be less risky (though not necessarily without risk), because 
unittest blocks are normally isolated.

Regardless, if you don't like the fact that there's no guarantee that 
AssertErrors execute finally blocks, scope statements, and destructors, take it 
up with Walter. I'm just pointing out what the design is. I didn't make the 
decision - though in general, I do think that it was the correct one. It's 
just that there are a few cases (e.g. some unit testing stuff) where it can 
become an issue.

And if you really want to do your own unit testing framework, maybe you should 
just create your own custom assertion functions which throw something other 
than AssertError - though if they don't throw Errors, then any unittest blocks 
with a catch(Exception() {} in them may not work properly, so that's not 
necessarily all that great a solution either, depending.

- Jonathan M Davis


More information about the Digitalmars-d-learn mailing list