$include_dir="/home/hyper-archives/boost/include"; include("$include_dir/msg-header.inc") ?>
From: Gennadiy Rozental (gennadiy.rozental_at_[hidden])
Date: 2005-12-20 19:47:21
"Daniel James" <daniel_at_[hidden]> wrote in message 
news:doa5fo$fd6$1_at_sea.gmane.org...
> Gennadiy Rozental wrote:
>> To check basic ES you don't need to catch any exceptions. Framework will
>> check that you do unwinding properly by making sure you are not leaking 
>> any
>> resources.
>
> That isn't exactly true. The class still needs to meet it's invariants.
No. This is not what a definition says.
> For example, if an exception is thrown while rehashing a hash table, it
> will probably be left with only some of its elements - so the test needs
> to check that the size has been changed to match the decreased number of
> elements. Of course, that's possible within your framework.
This is requirement for strong guarantee
> I'll try to give you an idea about what I'm doing. The example I gave
[...]
> Another version would be to have two separate tests, the first to test
> for basic safety:
>
>     unordered_set<test::mock_object,
>         test::hash, test::equal, test::allocator> x;
>     x.insert(1);
>
> and one to test for strong safety, with a non-throwing hash:
>
>     boost::unordered_set<test::mock_object,
>         test::hash_nothrow, test::equal, test::allocator> x;
>     unordered_strong_test tester(x);
>     try {
>         x.insert(1);
>     } catch(...) {
>         tester.test();
>         throw;
>     }
This is a correct way of structuring your tests. Don't mix basic and strong 
test withing the same test case. TDD actually recommends to have separate 
test case for every single assertion. And in this design you do not need to 
know where exception was thrown from.  It's possible that your class needs 
to check different invariants depending on where the failure occur. Do NOT 
do this within same test case. Use two - with different mocks throwing 
exceptions in different locations and different invariants checks.
> Incidently, my tests aren't actually written like this.
> unordered_strong_test works more like a scope guard, something like:
>
>     unordered_strong_test tester(x);
>     try {
>         x.insert(1);
>         tester.dismiss();
>     }
>     catch(hash_exception) {
>         tester.dismiss();
>         throw;
>     }
>
> I also have a similar class which tests the class invariants - in order
> to test basic exception safety.
This statement is self-conflicting or what the word.
> It doesn't have a 'dismiss' method as I
> want to run the test regardless.
> This is why I would like to be able to use BOOST_CHECK
> in the destructor, but that's more of a convenience than anything.
I gather you do invariants checks in destructor of your scope guard like 
tester class. I don't think this is good idea to do anything smart in 
destructors (with rare exceptions). I don't really see why is it better 
then:
tester t(x)
try {
    // test case body
}
catch(...) {
   t.check_invariants();
   throw;
}
Gennadiy