Assert and the optional Message
Steven Schveighoffer
schveiguy at yahoo.com
Mon Mar 12 07:08:35 PDT 2012
On Sat, 10 Mar 2012 11:03:43 -0500, Jacob Carlborg <doob at me.com> 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.
There was a period of time where unit test asserts were handled
differently than normal asserts. The unit tests would continue even if a
unit test asserted. This is no longer the case.
The issue was that sometimes when you have one small problem in your code,
you get thousands of asserts from different unit tests, making it
impossible to find the "real issue".
I contended that unit test asserts should result in a hook that by default
kills the program, but could be hooked into a unit testing handler. But
the consensus was just to switch back to the original behavior (all
asserts kill the program). If you look through the phobos or druntime
mailing list archives you might find the relevant conversations. It may
even be so old that the archives don't have it (it was on a private
mailing list on Andrei's server for a time).
My thoughts on assert/unit test:
1. AssertError (and any other Error) should not be caught by normal user
code. Ever. It should only be caught by the runtime. However, the
handler in the runtime could provide a hook specific to the OS/application
and whether it is running unit tests. Obviously the hook would have to be
set up before main runs, so that is an issue, but you may just need to
alter the runtime in that case.
2. Any assert in a unit test block should halt execution in the unit test
block. Often subsequent asserts are just noise because you are depending
on the conditions that make the prior asserts pass.
3. unit test blocks should be tested individually, not on a module-level
IMO. I'm not sure if this currently is the case.
4. Jonathan's statement that the program is in an "undefined state" is not
quite true. It's in an unwound state, but not undefined. Certainly, you
should be able to continue running more unit tests. Unit tests should be
a) unaffected by other unit test blocks, and b) should not affect the
running of any other code in any way. Otherwise, a program would run
differently depending on whether unit tests ran.
5. If *any* unit tests fail, the main() function should not be run. If an
assert is triggered while running main(), the program should exit.
-Steve
More information about the Digitalmars-d-learn
mailing list