|
Boost Users : |
Subject: Re: [Boost-users] [Boost.Test] What's the best way to make custom assertions?
From: Richard (legalize+jeeves_at_[hidden])
Date: 2012-10-23 15:05:28
[Please do not mail me a copy of your followup]
boost-users_at_[hidden] spake the secret code
<loom.20121023T190432-653_at_[hidden]> thusly:
>Richard <legalize+jeeves <at> mail.xmission.com> 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_cast<std::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_cast<std::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>
Boost-users list run by williamkempf at hotmail.com, kalb at libertysoft.com, bjorn.karlsson at readsoft.com, gregod at cs.rpi.edu, wekempf at cox.net