
"Daniel James" <daniel@calamity.org.uk> wrote in message news:doa5fo$fd6$1@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