On Sat, 10 Mar 2012 11:03:43 -0500, Jacob Carlborg <d...@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