
Gennadiy Rozental wrote:
"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.
I think we're using jargon a bit differently here. When I'm writing about a class invariant, I mean the requirements that it must always meet - such as having a correct size. This is a pretty common usage. http://en.wikipedia.org/wiki/Class_invariant
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
This is definitely the basic guarantee. From http://www.stlport.org/doc/exception_safety.html: "Containers continue to fulfill all of their requirements, even after an exception occurs during a mutating function. For example, a map will never give an inaccurate report of its size, or fail to meet its performance requirements because the tree that implements it has become unbalanced."
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.
That seems very dogmatic. Personally, I find the other styles more expressive. And while you might not need to know where the exception is thrown from, you need to control where it can be thrown from, which seems like more of an effort to me. Some of the other exception specifications details which methods exceptions can be thrown from, so you need quite fine-grained control. Daniel