[Please do not mail me a copy of your followup]
boost-users@lists.boost.org spake the secret code
Richard
writes: I want to make custom assertion methods that report the failure location as the place where the custom assertion is invoked, not the location where the BOOST_REQUIRE_xxx macros are used in the implementation of the custom assertion.
Hi Richard,
Frankly I do not follow what you want exactly. BOOST_REQUIRE reports a location of that statement. What do you want to report?
I don't propose to change BOOST_REQUIRE; I want a macro just below BOOST_REQUIRE (and _CHECK, etc.) that allows me to supply the file and line number for the purposes of reporting failures. This is already done several layers below in the existing macros.
If this is the case, I'd rather you use new BOOST_TEST_CONTEXT facility and implement check_op1 like this:
void check_op1( char const* f, int l ) { BOOST_TEST_CONTEXT( "Testing invoked from: " << f << "(" << l << ")" ) { BOOST_REQUIRE( expr1 ); BOOST_REQUIRE( expr2 ); } }
My version of Boost.Test doesn't have BOOST_TEST_CONTEXT, so I can't use that. However, from looking at http://lists.boost.org/boost-commit/2011/09/36947.php it seems way more mechanism than I need and more importantly isn't the mechanism I want from what I can tell. I shouldn't have to decorate my test code with extra messaging context just because I'm invoking a custom assertion. A custom assertion should be just as usable as the built-in assertions to Boost.Test, i.e. it should require nothing more than using BOOST_REQUIRE requires right now. All I need is for __FILE__ and __LINE__ to be substituted in at the first level of macro expansion. BOOST_REQUIRE expands to a call to BOOST_CHECK_IMPL: #define BOOST_REQUIRE( P ) \ BOOST_CHECK_IMPL( (P), BOOST_TEST_STRINGIZE( P ), REQUIRE, CHECK_PRED ) BOOST_CHECK_IMPL expands to a call to BOOST_TEST_TOOL_IMPL: #define BOOST_CHECK_IMPL( P, check_descr, TL, CT ) \ do { \ BOOST_TEST_PASSPOINT(); \ BOOST_TEST_TOOL_IMPL( check_impl, P, check_descr, TL, CT ), 0 );\ } while( ::boost::test_tools::dummy_cond ) \ /**/ BOOST_TEST_TOOL_IMPL is where __FILE__ and __LINE__ finally appear: #define BOOST_TEST_TOOL_IMPL( func, P, check_descr, TL, CT ) \ ::boost::test_tools::tt_detail::func( \ P, \ ::boost::unit_test::lazy_ostream::instance() << check_descr, \ BOOST_TEST_L(__FILE__), \ static_caststd::size_t(__LINE__), \ ::boost::test_tools::tt_detail::TL, \ ::boost::test_tools::tt_detail::CT \ /**/ I propose a refactoring like: #define BOOST_REQUIRE( P ) BOOST_REQUIRE_FL( P, __FILE__, __LINE__ ) #define BOOST_REQUIRE_FL(P, F, L) \ BOOST_CHECK_IMPL( (P), BOOST_TEST_STRINGIZE( P ), REQUIRE, CHECK_PRED, F, L ) #define BOOST_CHECK_IMPL( P, check_descr, TL, CT, F, L ) \ do { \ BOOST_TEST_PASSPOINT(); \ BOOST_TEST_TOOL_IMPL( check_impl, P, check_descr, TL, CT, F, L ), 0 );\ } while( ::boost::test_tools::dummy_cond ) \ /**/ #define BOOST_TEST_TOOL_IMPL( func, P, check_descr, TL, CT, F, L ) \ ::boost::test_tools::tt_detail::func( \ P, \ ::boost::unit_test::lazy_ostream::instance() << check_descr, \ BOOST_TEST_L(F), \ static_caststd::size_t(L), \ ::boost::test_tools::tt_detail::TL, \ ::boost::test_tools::tt_detail::CT \ /**/ There may be other places where F,L need to be passed down; it looks like BOOST_TEST_PASSPOINT uses it as well. -- "The Direct3D Graphics Pipeline" free book http://tinyurl.com/d3d-pipeline The Computer Graphics Museum http://computergraphicsmuseum.org The Terminals Wiki http://terminals.classiccmp.org Legalize Adulthood! (my blog) http://legalizeadulthood.wordpress.com