Boost logo

Boost :

From: Daniel James (daniel_at_[hidden])
Date: 2005-12-22 13:49:30


Gennadiy Rozental wrote:
> "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.

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


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk