[Boost.Test] BOOST_CHECK_THROW behaviour
Hello, Sorry for the long post! I have a simple class, which I am posting a fraction of here for discussion sake: ------------------------------------------------------ class AsciiTableRow { public: void setCol( std::size_t colIdx, std::string const& newContent ); void setCol( std::size_t colIdx, const char* newContent ); private: void checkIdxBound_( std::size_t colIdx, std::string const& msg ); std::vector< std::string > data_; bool maxColWidthIsValid_; } inline void AsciiTableRow::setCol( std::size_t colIdx, std::string const& newVal ) { checkIdxBound_( colIdx, "setCol" ); maxColWidthIsValid_ = false; data_[colIdx] = newVal; } inline void AsciiTableRow::setCol( std::size_t colIdx, const char* newContent ) { setCol( colIdx, std::string( newContent ) ); } inline void AsciiTableRow::checkIdxBound_( std::size_t colIdx, std::string const& msg ) { if( colIdx > data_.size() ) { throw std::out_of_range( "AsciiTableRow::" + msg + " : colIdx out of range" ); } } ------------------------------------------------------ The code above should be sufficient for the discussion and I don’t think any other code is relevant. Should you need to see my constructor and destructor, nothing is virtual so I just copy every value and set some defaults. Nothing fancy, but I will gladly post the code if need be. What I do then is try and devise a test to see if the exception is indeed thrown and if it is the correct one. Here is the code I use: AsciiTableRow testRow; // empty, so any index will throw BOOST_CHECK_THROW( testRow.setCol( 30, 12 ), std::out_of_range ); BOOST_CHECK_THROW( testRow.setCol( 30, 12l ), std::out_of_range ); This works fine. Then, I had the idea to check what the behaviour would be if the wrong exception is thrown. I simply changed the first call like this : BOOST_CHECK_THROW( testRow.setCol( 30, 12 ), std::runtime_error ); BOOST_CHECK_THROW( testRow.setCol( 30, 12l ), std::out_of_range ); I was under the impression (and I might be wrong here, sorry :-( ) that the Boost.Test library would (the numbers are not to mean that order, simply there for enumeration): 1- output a message saying the test has failed, that an exception was indeed thrown, but it was not a runtime_error 2- continue the rest of the test (single test currently) 3- terminate but I actually never get the message of step 1, the execution of the rest of the test seems never occur (the second BOOST_CHECK_THROW) and the program terminate because of my exception and not very gracefully. I guess my questions to the other users here are: - Was my understanding of what BOOST_CHECK_THROW does flawed ? - Is the behaviour normal ? - Is there an obvious problem I am missing with the design of my simple class ? In case it is useful, I am on OSX 10.9. I have compiled boost myself (sources of version 1.55 downloaded from the Boost site). I compile my work with C++11 enabled. I am using GCC 4.7 installed via Macports. Anyhow, any insight will be appreciated. As everyone is busy, thanks in advance to anybody for any time spent on this. Ghyslain
On 20/06/2014 01:03, Ghyslain Leclerc wrote:
Then, I had the idea to check what the behaviour would be if the wrong exception is thrown. I simply changed the first call like this :
BOOST_CHECK_THROW( testRow.setCol( 30, 12 ), std::runtime_error ); BOOST_CHECK_THROW( testRow.setCol( 30, 12l ), std::out_of_range );
I was under the impression (and I might be wrong here, sorry :-( ) that the Boost.Test library would (the numbers are not to mean that order, simply there for enumeration): 1- output a message saying the test has failed, that an exception was indeed thrown, but it was not a runtime_error 2- continue the rest of the test (single test currently) 3- terminate
but I actually never get the message of step 1, the execution of the rest of the test seems never occur (the second BOOST_CHECK_THROW) and the program terminate because of my exception and not very gracefully.
I guess my questions to the other users here are: - Was my understanding of what BOOST_CHECK_THROW does flawed ? - Is the behaviour normal ? - Is there an obvious problem I am missing with the design of my simple class ?
If you look at the definition of BOOST_*_THROW in boost/test/test_tools.hpp, you can see that it only tries to catch the named exception; any other exceptions will be left to bubble up (and will likely be uncaught and result in terminate() getting called). So it sounds like it's behaving as expected from that viewpoint. (Having said that, there is some evidence of plumbing to catch all exception types at a higher level and do something more useful than calling terminate(); I haven't looked too closely at it so I don't know if it's involved in the behaviour you're seeing or not. Related docs at http://www.boost.org/doc/libs/1_55_0/libs/test/doc/html/execution-monitor.ht... suggest that this is optional and must be explicitly enabled to operate, though, but I could easily be missing something. But even if it's "working", it would still result in aborting at least the test case despite the CHECK level.) I agree with you that it would be more useful for this to be handled locally. You could try submitting that as a bug report in Trac (if it's not already there), or waiting for Gennadiy Rozental's response. In the meantime, you'd need to write a more intelligent test yourself. (I consider it a bug rather than a feature request because the reference docs for BOOST_*_THROW state that "check fails" if an unrelated exception is thrown, which is at least misleading at present if not incorrect.)
participants (2)
-
Gavin Lambert
-
Ghyslain Leclerc