On Friday, March 09, 2012 22:03:11 Timon Gehr wrote: > On 03/09/2012 08:29 PM, H. S. Teoh wrote: > > On Fri, Mar 09, 2012 at 01:37:38PM -0500, Jonathan M Davis wrote: > >> On Friday, March 09, 2012 09:59:42 H. S. Teoh wrote: > > [...] > > > >>> This opens up the question of, what's the *recommended* way of > >>> writing unittests that check for these sorts of stuff? > >>> > >>> For example, I believe in being thorough in unit tests, so I like to > >>> use them to verify that the complicated in-contract I just wrote > >>> actually prevents the erroneous calls that I *think* it prevents. > >>> But if catching AssertError's may leave the program in an undefined > >>> state, then that pretty much invalidates any further testing past > >>> that point (the program may appear to work when compiled with > >>> -funittest but actually fail in release mode). > >> > >> If you're testing that contracts throw when they're supposed to, > >> you're going to have to be very careful. Depending on what code is > >> involved, catching the AssertError could have no problems whatsoever. > >> For example > >> > >> assertThrown!AssertError(func(5)); > >> > >> void func(int i) > >> in > >> { > >> > >> assert(i == 2); > >> > >> } > >> body > >> {} > >> > >> wouldn't be a problem at all. There are no destructors, scope > >> statements, or finally blocks involved. But something like > >> > >> assertThrown!AssertError(foo(5)); > >> > >> int foo(int i) > >> out(result) > >> { > >> > >> assert(result = == 2); > >> > >> } > >> body > >> { > >> > >> Bar bar; > >> > >> return i; > >> > >> } > >> > >> could have issues if Bar has a constructor than needs to run. You just > >> need to understand that destructors, scope statements, and finally > >> blocks are not guaranteed to be run if an Error is thrown and avoid > >> catching Errors in cases where they'd be skipped (or know enough about > >> the state that the program would be in if they _were_ skipped to know > >> that it's not going to cause problems). > >> > >> Personally, I think that checking contracts is overkill, but you can > >> do it if you're careful. > > > > [...] > > > > Hmph. Well, then that defeats the purpose of checking contracts, because > > checking contracts is only justifiable if it's complex enough, which > > means that it's liable to involve things like dtors and scope > > statements. It's silly to want to check a trivial contract like > > assert(x>0);, because if something *that* simple can go wrong, then so > > can the unittest, so you're not proving anything at all. > > > > But this isn't that big a deal. One could argue that if a contract is > > convoluted enough to warrant a unit test, then perhaps most (or all) of > > its complexity should be factored out into a separate, unit tested > > function, which is then just invoked from the contract. > > > > (I find this a bit ironic, since TDPL states that the reason contracts > > allow statements is so that complicated conditions can be tested for, > > rather than being limited to just a single expression, as is the case in > > most other languages that support DbC. Now it seems that simple > > contracts are the way to go.) > > > > > > T > > Jonathan is just speculating. And I think he is wrong.
Speculating about what? - Jonathan M Davis