mirror of
https://github.com/mat007/turtle.git
synced 2026-06-22 12:13:43 +00:00
An expectation is a functor
git-svn-id: https://svn.code.sf.net/p/turtle/code/trunk@18 860be788-9bd5-4423-9f1e-828f051e677b
This commit is contained in:
parent
135846946f
commit
60d5c263a6
2 changed files with 174 additions and 111 deletions
|
|
@ -32,172 +32,229 @@ namespace mock
|
||||||
typename ErrorPolicy = boost_test_error_policy<
|
typename ErrorPolicy = boost_test_error_policy<
|
||||||
BOOST_DEDUCED_TYPENAME boost::function<
|
BOOST_DEDUCED_TYPENAME boost::function<
|
||||||
Signature >::result_type > > // $$$$ MAT : concept check Signature is actually a signature
|
Signature >::result_type > > // $$$$ MAT : concept check Signature is actually a signature
|
||||||
class expectation : private verifiable
|
class expectation
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
typedef BOOST_DEDUCED_TYPENAME
|
typedef BOOST_DEDUCED_TYPENAME
|
||||||
boost::function< Signature >::result_type result_type;
|
boost::function< Signature >::result_type result_type;
|
||||||
|
|
||||||
|
private:
|
||||||
typedef detail::matcher< result_type,
|
typedef detail::matcher< result_type,
|
||||||
Signature,
|
Signature,
|
||||||
ErrorPolicy,
|
ErrorPolicy,
|
||||||
boost::function< Signature >::arity >
|
boost::function< Signature >::arity >
|
||||||
matcher_type;
|
matcher_type;
|
||||||
|
|
||||||
|
public:
|
||||||
expectation( node& parent = root, const std::string& name = "?" )
|
expectation( node& parent = root, const std::string& name = "?" )
|
||||||
: name_( name )
|
: impl_( new expectation_impl( parent, name ) )
|
||||||
, parent_( &parent )
|
{}
|
||||||
, valid_( true )
|
|
||||||
{
|
|
||||||
parent_->add( *this );
|
|
||||||
}
|
|
||||||
expectation( const std::string& name )
|
expectation( const std::string& name )
|
||||||
: name_( name )
|
: impl_( new expectation_impl( root, name ) )
|
||||||
, parent_( &root )
|
{}
|
||||||
, valid_( true )
|
|
||||||
{
|
|
||||||
parent_->add( *this );
|
|
||||||
}
|
|
||||||
virtual ~expectation()
|
|
||||||
{
|
|
||||||
parent_->remove( *this );
|
|
||||||
if( ! std::uncaught_exception() )
|
|
||||||
for( matchers_cit it = matchers_.begin();
|
|
||||||
it != matchers_.end(); ++it )
|
|
||||||
if( valid_ && ! it->verify() )
|
|
||||||
ErrorPolicy::untriggered_expectation(
|
|
||||||
context(), it->file(), it->line() );
|
|
||||||
}
|
|
||||||
|
|
||||||
expectation& set_name( const std::string& name )
|
expectation& set_name( const std::string& name )
|
||||||
{
|
{
|
||||||
name_ = name;
|
impl_->set_name( name );
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
expectation& set_parent( node& parent )
|
expectation& set_parent( node& parent )
|
||||||
{
|
{
|
||||||
parent_->remove( *this );
|
impl_->set_parent( parent );
|
||||||
parent.add( *this );
|
|
||||||
parent_ = &parent;
|
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual bool verify()
|
bool verify()
|
||||||
{
|
{
|
||||||
for( matchers_cit it = matchers_.begin();
|
return impl_->verify();
|
||||||
it != matchers_.end(); ++it )
|
|
||||||
if( !it->verify() )
|
|
||||||
{
|
|
||||||
valid_ = false;
|
|
||||||
ErrorPolicy::verification_failed( context(),
|
|
||||||
it->file(), it->line() );
|
|
||||||
}
|
|
||||||
return valid_;
|
|
||||||
}
|
}
|
||||||
virtual void reset()
|
void reset()
|
||||||
{
|
{
|
||||||
valid_ = true;
|
impl_->reset();
|
||||||
matchers_.clear();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
matcher_type& expect( const std::string& file, int line )
|
matcher_type& expect( const std::string& file, int line )
|
||||||
{
|
{
|
||||||
matchers_.push_back( matcher_type() );
|
return impl_->expect( file, line );
|
||||||
matchers_.back().set_location( file, line );
|
|
||||||
valid_ = true;
|
|
||||||
return matchers_.back();
|
|
||||||
}
|
}
|
||||||
matcher_type& expect()
|
matcher_type& expect()
|
||||||
{
|
{
|
||||||
matchers_.push_back( matcher_type() );
|
return impl_->expect();
|
||||||
valid_ = true;
|
|
||||||
return matchers_.back();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
result_type operator()() const
|
result_type operator()() const
|
||||||
{
|
{
|
||||||
for( matchers_cit it = matchers_.begin();
|
return (*impl_)();
|
||||||
it != matchers_.end(); ++it )
|
}
|
||||||
if( it->is_valid() )
|
|
||||||
{
|
#define MOCK_EXPECTATION_OPERATOR(z, n, d) \
|
||||||
if( !it->invoke() )
|
template< BOOST_PP_ENUM_PARAMS(n, typename A) > \
|
||||||
|
result_type operator()( BOOST_PP_ENUM_BINARY_PARAMS(n, const A, & a) ) const \
|
||||||
|
{ \
|
||||||
|
return (*impl_)( BOOST_PP_ENUM_PARAMS(n, a) ); \
|
||||||
|
}
|
||||||
|
BOOST_PP_REPEAT_FROM_TO(1, MOCK_MAX_ARGS, MOCK_EXPECTATION_OPERATOR, BOOST_PP_EMPTY)
|
||||||
|
#undef MOCK_EXPECTATION_OPERATOR
|
||||||
|
|
||||||
|
friend std::ostream& operator<<( std::ostream& s, const expectation& e )
|
||||||
|
{
|
||||||
|
return s << *e.impl_;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
class expectation_impl : private verifiable
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
expectation_impl( node& parent, const std::string& name )
|
||||||
|
: name_( name )
|
||||||
|
, parent_( &parent )
|
||||||
|
, valid_( true )
|
||||||
|
{
|
||||||
|
parent_->add( *this );
|
||||||
|
}
|
||||||
|
virtual ~expectation_impl()
|
||||||
|
{
|
||||||
|
parent_->remove( *this );
|
||||||
|
if( ! std::uncaught_exception() )
|
||||||
|
for( matchers_cit it = matchers_.begin();
|
||||||
|
it != matchers_.end(); ++it )
|
||||||
|
if( valid_ && ! it->verify() )
|
||||||
|
ErrorPolicy::untriggered_expectation(
|
||||||
|
context(), it->file(), it->line() );
|
||||||
|
}
|
||||||
|
|
||||||
|
void set_name( const std::string& name )
|
||||||
|
{
|
||||||
|
name_ = name;
|
||||||
|
}
|
||||||
|
void set_parent( node& parent )
|
||||||
|
{
|
||||||
|
parent_->remove( *this );
|
||||||
|
parent.add( *this );
|
||||||
|
parent_ = &parent;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual bool verify()
|
||||||
|
{
|
||||||
|
for( matchers_cit it = matchers_.begin();
|
||||||
|
it != matchers_.end(); ++it )
|
||||||
|
if( !it->verify() )
|
||||||
{
|
{
|
||||||
valid_ = false;
|
valid_ = false;
|
||||||
ErrorPolicy::sequence_failed( context( "" ),
|
ErrorPolicy::verification_failed( context(),
|
||||||
it->file(), it->line() );
|
it->file(), it->line() );
|
||||||
}
|
}
|
||||||
return it->functor()();
|
return valid_;
|
||||||
}
|
}
|
||||||
valid_ = false;
|
virtual void reset()
|
||||||
return ErrorPolicy::no_match( context( "" ) );
|
{
|
||||||
}
|
valid_ = true;
|
||||||
|
matchers_.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
matcher_type& expect( const std::string& file, int line )
|
||||||
|
{
|
||||||
|
matchers_.push_back( matcher_type() );
|
||||||
|
matchers_.back().set_location( file, line );
|
||||||
|
valid_ = true;
|
||||||
|
return matchers_.back();
|
||||||
|
}
|
||||||
|
matcher_type& expect()
|
||||||
|
{
|
||||||
|
matchers_.push_back( matcher_type() );
|
||||||
|
valid_ = true;
|
||||||
|
return matchers_.back();
|
||||||
|
}
|
||||||
|
|
||||||
|
result_type operator()() const
|
||||||
|
{
|
||||||
|
for( matchers_cit it = matchers_.begin();
|
||||||
|
it != matchers_.end(); ++it )
|
||||||
|
if( it->is_valid() )
|
||||||
|
{
|
||||||
|
if( !it->invoke() )
|
||||||
|
{
|
||||||
|
valid_ = false;
|
||||||
|
ErrorPolicy::sequence_failed( context( "" ),
|
||||||
|
it->file(), it->line() );
|
||||||
|
}
|
||||||
|
return it->functor()();
|
||||||
|
}
|
||||||
|
valid_ = false;
|
||||||
|
return ErrorPolicy::no_match( context( "" ) );
|
||||||
|
}
|
||||||
|
|
||||||
#define MOCK_EXPECTATION_PARAMETER(z, n, d) BOOST_PP_COMMA_IF(n) const_cast< A##n & >( a##n )
|
#define MOCK_EXPECTATION_PARAMETER(z, n, d) BOOST_PP_COMMA_IF(n) const_cast< A##n & >( a##n )
|
||||||
#define MOCK_EXPECTATION_DETAIL(z, n, d) + ", " + format( a##n )
|
#define MOCK_EXPECTATION_DETAIL(z, n, d) + ", " + format( a##n )
|
||||||
#define MOCK_EXPECTATION_PARAMETERS(n) \
|
#define MOCK_EXPECTATION_PARAMETERS(n) \
|
||||||
format( a0 ) BOOST_PP_REPEAT_FROM_TO(1, n, MOCK_EXPECTATION_DETAIL, BOOST_PP_EMPTY)
|
format( a0 ) BOOST_PP_REPEAT_FROM_TO(1, n, MOCK_EXPECTATION_DETAIL, BOOST_PP_EMPTY)
|
||||||
#define MOCK_EXPECTATION_OPERATOR(z, n, d) \
|
#define MOCK_EXPECTATION_OPERATOR(z, n, d) \
|
||||||
template< BOOST_PP_ENUM_PARAMS(n, typename A) > \
|
template< BOOST_PP_ENUM_PARAMS(n, typename A) > \
|
||||||
result_type operator()( BOOST_PP_ENUM_BINARY_PARAMS(n, const A, & a) ) const \
|
result_type operator()( BOOST_PP_ENUM_BINARY_PARAMS(n, const A, & a) ) const \
|
||||||
{ \
|
{ \
|
||||||
for( matchers_cit it = matchers_.begin(); it != matchers_.end(); ++it ) \
|
for( matchers_cit it = matchers_.begin(); it != matchers_.end(); ++it ) \
|
||||||
if( it->is_valid( BOOST_PP_REPEAT_FROM_TO(0, n, MOCK_EXPECTATION_PARAMETER, BOOST_PP_EMPTY) ) ) \
|
if( it->is_valid( BOOST_PP_REPEAT_FROM_TO(0, n, MOCK_EXPECTATION_PARAMETER, BOOST_PP_EMPTY) ) ) \
|
||||||
{ \
|
|
||||||
if( !it->invoke() ) \
|
|
||||||
{ \
|
{ \
|
||||||
valid_ = false; \
|
if( !it->invoke() ) \
|
||||||
ErrorPolicy::sequence_failed( context( MOCK_EXPECTATION_PARAMETERS(n) ), it->file(), it->line() ); \
|
{ \
|
||||||
|
valid_ = false; \
|
||||||
|
ErrorPolicy::sequence_failed( context( MOCK_EXPECTATION_PARAMETERS(n) ), it->file(), it->line() ); \
|
||||||
|
} \
|
||||||
|
return it->functor()( BOOST_PP_REPEAT_FROM_TO(0, n, MOCK_EXPECTATION_PARAMETER, BOOST_PP_EMPTY) ); \
|
||||||
} \
|
} \
|
||||||
return it->functor()( BOOST_PP_REPEAT_FROM_TO(0, n, MOCK_EXPECTATION_PARAMETER, BOOST_PP_EMPTY) ); \
|
valid_ = false; \
|
||||||
} \
|
return ErrorPolicy::no_match( context( MOCK_EXPECTATION_PARAMETERS(n) ) ); \
|
||||||
valid_ = false; \
|
}
|
||||||
return ErrorPolicy::no_match( context( MOCK_EXPECTATION_PARAMETERS(n) ) ); \
|
BOOST_PP_REPEAT_FROM_TO(1, MOCK_MAX_ARGS, MOCK_EXPECTATION_OPERATOR, BOOST_PP_EMPTY)
|
||||||
}
|
|
||||||
BOOST_PP_REPEAT_FROM_TO(1, MOCK_MAX_ARGS, MOCK_EXPECTATION_OPERATOR, BOOST_PP_EMPTY)
|
|
||||||
#undef MOCK_EXPECTATION_PARAMETER
|
#undef MOCK_EXPECTATION_PARAMETER
|
||||||
#undef MOCK_EXPECTATION_PARAMETERS
|
#undef MOCK_EXPECTATION_PARAMETERS
|
||||||
#undef MOCK_EXPECTATION_DETAIL
|
#undef MOCK_EXPECTATION_DETAIL
|
||||||
#undef MOCK_EXPECTATION_OPERATOR
|
#undef MOCK_EXPECTATION_OPERATOR
|
||||||
|
|
||||||
friend std::ostream& operator<<( std::ostream& s, const expectation& e )
|
friend std::ostream& operator<<( std::ostream& s, const expectation_impl& e )
|
||||||
{
|
{
|
||||||
return s << e.context();
|
return s << e.context();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
typedef std::list< matcher_type > matchers_type;
|
||||||
|
typedef BOOST_DEDUCED_TYPENAME
|
||||||
|
matchers_type::const_iterator matchers_cit;
|
||||||
|
|
||||||
|
void serialize( std::ostream& s ) const
|
||||||
|
{
|
||||||
|
for( matchers_cit it = matchers_.begin();
|
||||||
|
it != matchers_.end(); ++it )
|
||||||
|
s << std::endl << *it;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string context() const
|
||||||
|
{
|
||||||
|
std::stringstream s;
|
||||||
|
s << *parent_ << name_;
|
||||||
|
serialize( s );
|
||||||
|
return s.str();
|
||||||
|
}
|
||||||
|
std::string context( const std::string& parameters ) const
|
||||||
|
{
|
||||||
|
std::stringstream s;
|
||||||
|
s << *parent_ << name_;
|
||||||
|
if( parameters.empty() )
|
||||||
|
s << "()";
|
||||||
|
else
|
||||||
|
s << "( " << parameters << " )";
|
||||||
|
serialize( s );
|
||||||
|
return s.str();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string name_;
|
||||||
|
node* parent_;
|
||||||
|
mutable bool valid_;
|
||||||
|
matchers_type matchers_;
|
||||||
|
};
|
||||||
|
|
||||||
private:
|
private:
|
||||||
typedef std::list< matcher_type > matchers_type;
|
boost::shared_ptr< expectation_impl > impl_;
|
||||||
typedef BOOST_DEDUCED_TYPENAME
|
|
||||||
matchers_type::const_iterator matchers_cit;
|
|
||||||
|
|
||||||
void serialize( std::ostream& s ) const
|
|
||||||
{
|
|
||||||
for( matchers_cit it = matchers_.begin();
|
|
||||||
it != matchers_.end(); ++it )
|
|
||||||
s << std::endl << *it;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string context() const
|
|
||||||
{
|
|
||||||
std::stringstream s;
|
|
||||||
s << *parent_ << name_;
|
|
||||||
serialize( s );
|
|
||||||
return s.str();
|
|
||||||
}
|
|
||||||
std::string context( const std::string& parameters ) const
|
|
||||||
{
|
|
||||||
std::stringstream s;
|
|
||||||
s << *parent_ << name_;
|
|
||||||
if( parameters.empty() )
|
|
||||||
s << "()";
|
|
||||||
else
|
|
||||||
s << "( " << parameters << " )";
|
|
||||||
serialize( s );
|
|
||||||
return s.str();
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string name_;
|
|
||||||
node* parent_;
|
|
||||||
mutable bool valid_;
|
|
||||||
matchers_type matchers_;
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -26,6 +26,12 @@ namespace
|
||||||
|
|
||||||
// functor
|
// functor
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE( an_expectation_can_be_passed_as_functor )
|
||||||
|
{
|
||||||
|
mock::expectation< void() > e;
|
||||||
|
boost::function< void() > f = e;
|
||||||
|
}
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE( an_expectation_can_be_passed_as_functor_using_boost_bind_and_boost_ref )
|
BOOST_AUTO_TEST_CASE( an_expectation_can_be_passed_as_functor_using_boost_bind_and_boost_ref )
|
||||||
{
|
{
|
||||||
mock::expectation< void() > e;
|
mock::expectation< void() > e;
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue