Unit tests and verifying pre/post-conditions and invariants
Lutger
lutger.blijdestijn at gmail.com
Sun Aug 15 15:06:12 PDT 2010
Jonathan M Davis wrote:
> Is there a standard and/or acceptable way to make sure that pre-conditions,
> post-conditions, or invariants _fail_ when running unit tests? That is, lets
> say I had a function like this
>
> void func(int x)
> in
> {
> assert(x < 8);
> }
> body
> {
> //...
> }
>
>
> and I wanted to test to make sure that func() couldn't be called with any int
> greater or equal to 8, what would I do? The best that I can think of is to
> catch an AssertError and ignore it. e.g.
>
> unittest
> {
> try
> {
> func(8);
> assert(0);
> }
> catch(AssertionError ae)
> {}
> }
>
>
> But catching AssertionErrors is generally a bad idea. As I understand it, when
> anything derived from Error is thrown, code is not left in a proper state,
> with stuff like destructors being skipped. Would it be okay to catch it in a
> case like this, or is it a really bad idea? If it's a bad idea, I haven't a
> clue how to verify that pre-condition, post-conditions, and invariants are
> correct.
>
> - Jonathan M Davis
Thats a good one. It used to be so that dmd would assume a halt and you could
get segfaults for continuing on. I *believe* this has changed and it is ok to
catch AssertError in this scenario. The only thing I can think of is that
nothrow functions can be optimized by the compiler, but are not typechecked for
throwing Error.
Even if this is correct, you still have the problem foo could call other
functions that assert, which invalidates at least two contract checks. This may
require some care. Perhaps an idea is to define a PreconditionError and
PostconditionError and wrap them in a function similar to enforce, so you can
differentiate more easily where the error is coming from. This way you also get
better error messages and have one point where to change the behavior if this
may be required.
More information about the Digitalmars-d-learn
mailing list