mirror of
https://github.com/mat007/turtle.git
synced 2026-06-22 12:13:43 +00:00
Toying with PP
git-svn-id: https://svn.code.sf.net/p/turtle/code/trunk@480 860be788-9bd5-4423-9f1e-828f051e677b
This commit is contained in:
parent
cf264cd31e
commit
f2a617882b
9 changed files with 563 additions and 552 deletions
|
|
@ -96,7 +96,7 @@
|
||||||
</target>
|
</target>
|
||||||
|
|
||||||
<target name="reports" description="generate code analysis reports">
|
<target name="reports" description="generate code analysis reports">
|
||||||
<headers name="turtle"/>
|
<headers name="turtle" excludes="*_iterate.hpp,*_template.hpp"/>
|
||||||
<check name="turtle"/>
|
<check name="turtle"/>
|
||||||
</target>
|
</target>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -39,8 +39,11 @@
|
||||||
<ClInclude Include="..\..\turtle\detail\verifiable.hpp" />
|
<ClInclude Include="..\..\turtle\detail\verifiable.hpp" />
|
||||||
<ClInclude Include="..\..\turtle\detail\yes_no_type.hpp" />
|
<ClInclude Include="..\..\turtle\detail\yes_no_type.hpp" />
|
||||||
<ClInclude Include="..\..\turtle\error.hpp" />
|
<ClInclude Include="..\..\turtle\error.hpp" />
|
||||||
<ClInclude Include="..\..\turtle\expectation.hpp" />
|
<ClInclude Include="..\..\turtle\expectation_base.hpp" />
|
||||||
|
<ClInclude Include="..\..\turtle\expectation_template.hpp" />
|
||||||
<ClInclude Include="..\..\turtle\function.hpp" />
|
<ClInclude Include="..\..\turtle\function.hpp" />
|
||||||
|
<ClInclude Include="..\..\turtle\function_iterate.hpp" />
|
||||||
|
<ClInclude Include="..\..\turtle\function_template.hpp" />
|
||||||
<ClInclude Include="..\..\turtle\invocation.hpp" />
|
<ClInclude Include="..\..\turtle\invocation.hpp" />
|
||||||
<ClInclude Include="..\..\turtle\is_functor.hpp" />
|
<ClInclude Include="..\..\turtle\is_functor.hpp" />
|
||||||
<ClInclude Include="..\..\turtle\log.hpp" />
|
<ClInclude Include="..\..\turtle\log.hpp" />
|
||||||
|
|
|
||||||
|
|
@ -25,9 +25,6 @@
|
||||||
<ClInclude Include="..\..\turtle\error.hpp">
|
<ClInclude Include="..\..\turtle\error.hpp">
|
||||||
<Filter>Source Files</Filter>
|
<Filter>Source Files</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
<ClInclude Include="..\..\turtle\expectation.hpp">
|
|
||||||
<Filter>Source Files</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="..\..\turtle\function.hpp">
|
<ClInclude Include="..\..\turtle\function.hpp">
|
||||||
<Filter>Source Files</Filter>
|
<Filter>Source Files</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
|
|
@ -97,5 +94,17 @@
|
||||||
<ClInclude Include="..\..\turtle\detail\parameters.hpp">
|
<ClInclude Include="..\..\turtle\detail\parameters.hpp">
|
||||||
<Filter>Source Files\detail</Filter>
|
<Filter>Source Files\detail</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
|
<ClInclude Include="..\..\turtle\function_template.hpp">
|
||||||
|
<Filter>Source Files</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="..\..\turtle\expectation_base.hpp">
|
||||||
|
<Filter>Source Files</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="..\..\turtle\expectation_template.hpp">
|
||||||
|
<Filter>Source Files</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="..\..\turtle\function_iterate.hpp">
|
||||||
|
<Filter>Source Files</Filter>
|
||||||
|
</ClInclude>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
</Project>
|
</Project>
|
||||||
|
|
@ -1,261 +0,0 @@
|
||||||
// http://turtle.sourceforge.net
|
|
||||||
//
|
|
||||||
// Copyright Mathieu Champlon 2008
|
|
||||||
//
|
|
||||||
// Distributed under the Boost Software License, Version 1.0.
|
|
||||||
// (See accompanying file LICENSE_1_0.txt or copy at
|
|
||||||
// http://www.boost.org/LICENSE_1_0.txt)
|
|
||||||
|
|
||||||
#ifndef MOCK_EXPECTATION_HPP_INCLUDED
|
|
||||||
#define MOCK_EXPECTATION_HPP_INCLUDED
|
|
||||||
|
|
||||||
#include "config.hpp"
|
|
||||||
#include "invocation.hpp"
|
|
||||||
#include "action.hpp"
|
|
||||||
#include "sequence.hpp"
|
|
||||||
#include "check.hpp"
|
|
||||||
#include "constraints.hpp"
|
|
||||||
#include <boost/shared_ptr.hpp>
|
|
||||||
#include <boost/preprocessor/repetition/repeat_from_to.hpp>
|
|
||||||
#include <boost/preprocessor/repetition/enum_params.hpp>
|
|
||||||
#include <boost/preprocessor/repetition/enum_binary_params.hpp>
|
|
||||||
#include <boost/function_types/parameter_types.hpp>
|
|
||||||
#include <boost/function_types/result_type.hpp>
|
|
||||||
#include <boost/mpl/at.hpp>
|
|
||||||
#include <ostream>
|
|
||||||
#include <vector>
|
|
||||||
|
|
||||||
namespace mock
|
|
||||||
{
|
|
||||||
namespace detail
|
|
||||||
{
|
|
||||||
class expectation_base
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
expectation_base()
|
|
||||||
: i_( new detail::unlimited() )
|
|
||||||
, file_( "unknown location" )
|
|
||||||
, line_( 0 )
|
|
||||||
{}
|
|
||||||
void set_location( const char* file, int line )
|
|
||||||
{
|
|
||||||
file_ = file;
|
|
||||||
line_ = line;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool verify() const
|
|
||||||
{
|
|
||||||
return i_->verify();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool invoke() const
|
|
||||||
{
|
|
||||||
for( sequences_cit it = sequences_.begin();
|
|
||||||
it != sequences_.end(); ++it )
|
|
||||||
if( ! (*it)->is_valid( this ) )
|
|
||||||
return false;
|
|
||||||
bool result = i_->invoke();
|
|
||||||
for( sequences_cit it = sequences_.begin();
|
|
||||||
it != sequences_.end(); ++it )
|
|
||||||
(*it)->invalidate( this );
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool invoked() const
|
|
||||||
{
|
|
||||||
return i_->invoked();
|
|
||||||
}
|
|
||||||
|
|
||||||
const char* file() const
|
|
||||||
{
|
|
||||||
return file_;
|
|
||||||
}
|
|
||||||
int line() const
|
|
||||||
{
|
|
||||||
return line_;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected:
|
|
||||||
~expectation_base()
|
|
||||||
{
|
|
||||||
for( sequences_cit it = sequences_.begin();
|
|
||||||
it != sequences_.end(); ++it )
|
|
||||||
(*it)->remove( this );
|
|
||||||
}
|
|
||||||
|
|
||||||
void expect( detail::invocation* i )
|
|
||||||
{
|
|
||||||
i_.reset( i );
|
|
||||||
}
|
|
||||||
|
|
||||||
void add( boost::shared_ptr< detail::sequence_impl > s )
|
|
||||||
{
|
|
||||||
s->add( this );
|
|
||||||
sequences_.push_back( s );
|
|
||||||
}
|
|
||||||
|
|
||||||
boost::shared_ptr< detail::invocation > i_;
|
|
||||||
|
|
||||||
private:
|
|
||||||
typedef std::vector<
|
|
||||||
boost::shared_ptr< detail::sequence_impl >
|
|
||||||
> sequences_type;
|
|
||||||
typedef sequences_type::const_iterator sequences_cit;
|
|
||||||
|
|
||||||
sequences_type sequences_;
|
|
||||||
const char* file_;
|
|
||||||
int line_;
|
|
||||||
};
|
|
||||||
|
|
||||||
template< typename Signature, int Arity >
|
|
||||||
class expectation
|
|
||||||
{
|
|
||||||
};
|
|
||||||
|
|
||||||
#define MOCK_EXPECTATION_METHODS \
|
|
||||||
expectation& in( sequence& s ) \
|
|
||||||
{ \
|
|
||||||
add( s.impl_ ); \
|
|
||||||
return *this; \
|
|
||||||
} \
|
|
||||||
expectation& once() \
|
|
||||||
{ \
|
|
||||||
expect( new detail::once() ); \
|
|
||||||
return *this; \
|
|
||||||
} \
|
|
||||||
expectation& never() \
|
|
||||||
{ \
|
|
||||||
expect( new detail::never() ); \
|
|
||||||
return *this; \
|
|
||||||
} \
|
|
||||||
expectation& exactly( std::size_t count ) \
|
|
||||||
{ \
|
|
||||||
expect( new detail::exactly( count ) ); \
|
|
||||||
return *this; \
|
|
||||||
} \
|
|
||||||
expectation& at_least( std::size_t min ) \
|
|
||||||
{ \
|
|
||||||
expect( new detail::at_least( min ) ); \
|
|
||||||
return *this; \
|
|
||||||
} \
|
|
||||||
expectation& at_most( std::size_t max ) \
|
|
||||||
{ \
|
|
||||||
expect( new detail::at_most( max ) ); \
|
|
||||||
return *this; \
|
|
||||||
} \
|
|
||||||
expectation& between( std::size_t min, std::size_t max ) \
|
|
||||||
{ \
|
|
||||||
expect( new detail::between( min, max ) ); \
|
|
||||||
return *this; \
|
|
||||||
}
|
|
||||||
|
|
||||||
template< typename Signature >
|
|
||||||
class expectation< Signature, 0 >
|
|
||||||
: public expectation_base
|
|
||||||
, public action< BOOST_DEDUCED_TYPENAME
|
|
||||||
boost::function_types::result_type< Signature >::type, Signature >
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
bool is_valid() const
|
|
||||||
{
|
|
||||||
return ! i_->exhausted();
|
|
||||||
}
|
|
||||||
|
|
||||||
MOCK_EXPECTATION_METHODS
|
|
||||||
|
|
||||||
friend std::ostream& operator<<( std::ostream& s,
|
|
||||||
const expectation& m )
|
|
||||||
{
|
|
||||||
return s << (m.i_->exhausted() ? 'v' : '.') << ' ' << *m.i_;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
#define MOCK_EXPECTATION_TYPEDEF(z, n, d) \
|
|
||||||
typedef BOOST_DEDUCED_TYPENAME \
|
|
||||||
boost::mpl::at_c< \
|
|
||||||
BOOST_DEDUCED_TYPENAME \
|
|
||||||
boost::function_types::parameter_types< Signature >, \
|
|
||||||
n \
|
|
||||||
>::type arg##n##_type;
|
|
||||||
#define MOCK_EXPECTATION_INITIALIZE(z, n, d) \
|
|
||||||
BOOST_PP_COMMA_IF(n) c##n##_( \
|
|
||||||
new detail::check< \
|
|
||||||
arg##n##_type, \
|
|
||||||
constraint< detail::any > \
|
|
||||||
>( mock::any ) )
|
|
||||||
#define MOCK_EXPECTATION_WITH(z, n, d) \
|
|
||||||
c##n##_.reset( \
|
|
||||||
new detail::check< \
|
|
||||||
arg##n##_type, \
|
|
||||||
Constraint_##n \
|
|
||||||
>( c##n ) );
|
|
||||||
#define MOCK_EXPECTATION_MEMBER(z, n, d) \
|
|
||||||
boost::shared_ptr< detail::check_base< arg##n##_type > > c##n##_;
|
|
||||||
#define MOCK_EXPECTATION_ARGS(z, n, d) \
|
|
||||||
BOOST_PP_COMMA_IF(n) arg##n##_type a##n
|
|
||||||
#define MOCK_EXPECTATION_IS_VALID(z, n, d) \
|
|
||||||
&& (*c##n##_)( a##n )
|
|
||||||
#define MOCK_EXPECTATION_SERIALIZE(z, n, d) \
|
|
||||||
BOOST_PP_IF(n, << ", " <<,) *m.c##n##_
|
|
||||||
#define MOCK_EXPECTATION(z, n, d) \
|
|
||||||
template< typename Signature > \
|
|
||||||
class expectation< Signature, n > \
|
|
||||||
: public expectation_base \
|
|
||||||
, public action< \
|
|
||||||
BOOST_DEDUCED_TYPENAME \
|
|
||||||
boost::function_types::result_type< Signature >::type, \
|
|
||||||
Signature \
|
|
||||||
> \
|
|
||||||
{ \
|
|
||||||
BOOST_PP_REPEAT(n, MOCK_EXPECTATION_TYPEDEF, BOOST_PP_EMPTY) \
|
|
||||||
public: \
|
|
||||||
expectation() \
|
|
||||||
: BOOST_PP_REPEAT(n, MOCK_EXPECTATION_INITIALIZE, BOOST_PP_EMPTY) \
|
|
||||||
{} \
|
|
||||||
template< BOOST_PP_ENUM_PARAMS(n, typename Constraint_) > \
|
|
||||||
expectation& with( BOOST_PP_ENUM_BINARY_PARAMS(n, Constraint_, c) ) \
|
|
||||||
{ \
|
|
||||||
BOOST_PP_REPEAT(n, MOCK_EXPECTATION_WITH, BOOST_PP_EMPTY) \
|
|
||||||
return *this; \
|
|
||||||
} \
|
|
||||||
bool is_valid( \
|
|
||||||
BOOST_PP_REPEAT(n, MOCK_EXPECTATION_ARGS, BOOST_PP_EMPTY) ) const \
|
|
||||||
{ \
|
|
||||||
return ! i_->exhausted() \
|
|
||||||
BOOST_PP_REPEAT(n, \
|
|
||||||
MOCK_EXPECTATION_IS_VALID, BOOST_PP_EMPTY); \
|
|
||||||
} \
|
|
||||||
MOCK_EXPECTATION_METHODS \
|
|
||||||
friend std::ostream& operator<<( \
|
|
||||||
std::ostream& s, const expectation& m ) \
|
|
||||||
{ \
|
|
||||||
return s << (m.i_->exhausted() ? 'v' : '.') \
|
|
||||||
<< ' ' << *m.i_ << ".with( " \
|
|
||||||
<< BOOST_PP_REPEAT(n, \
|
|
||||||
MOCK_EXPECTATION_SERIALIZE, BOOST_PP_EMPTY) \
|
|
||||||
<< " )"; \
|
|
||||||
} \
|
|
||||||
private: \
|
|
||||||
BOOST_PP_REPEAT(n, MOCK_EXPECTATION_MEMBER, BOOST_PP_EMPTY) \
|
|
||||||
};
|
|
||||||
|
|
||||||
BOOST_PP_REPEAT_FROM_TO(
|
|
||||||
1,
|
|
||||||
BOOST_PP_INC(MOCK_MAX_ARGS),
|
|
||||||
MOCK_EXPECTATION,
|
|
||||||
BOOST_PP_EMPTY)
|
|
||||||
|
|
||||||
#undef MOCK_EXPECTATION_METHODS
|
|
||||||
#undef MOCK_EXPECTATION_TYPEDEF
|
|
||||||
#undef MOCK_EXPECTATION_INITIALIZE
|
|
||||||
#undef MOCK_EXPECTATION_WITH
|
|
||||||
#undef MOCK_EXPECTATION_MEMBER
|
|
||||||
#undef MOCK_EXPECTATION_ARGS
|
|
||||||
#undef MOCK_EXPECTATION_IS_VALID
|
|
||||||
#undef MOCK_EXPECTATION_SERIALIZE
|
|
||||||
#undef MOCK_EXPECTATION
|
|
||||||
|
|
||||||
}
|
|
||||||
} // mock
|
|
||||||
|
|
||||||
#endif // MOCK_EXPECTATION_HPP_INCLUDED
|
|
||||||
101
turtle/expectation_base.hpp
Normal file
101
turtle/expectation_base.hpp
Normal file
|
|
@ -0,0 +1,101 @@
|
||||||
|
// http://turtle.sourceforge.net
|
||||||
|
//
|
||||||
|
// Copyright Mathieu Champlon 2012
|
||||||
|
//
|
||||||
|
// Distributed under the Boost Software License, Version 1.0.
|
||||||
|
// (See accompanying file LICENSE_1_0.txt or copy at
|
||||||
|
// http://www.boost.org/LICENSE_1_0.txt)
|
||||||
|
|
||||||
|
#ifndef MOCK_EXPECTATION_BASE_HPP_INCLUDED
|
||||||
|
#define MOCK_EXPECTATION_BASE_HPP_INCLUDED
|
||||||
|
|
||||||
|
#include "invocation.hpp"
|
||||||
|
#include "sequence.hpp"
|
||||||
|
#include <boost/shared_ptr.hpp>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
namespace mock
|
||||||
|
{
|
||||||
|
namespace detail
|
||||||
|
{
|
||||||
|
class expectation_base
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
expectation_base()
|
||||||
|
: i_( new detail::unlimited() )
|
||||||
|
, file_( "unknown location" )
|
||||||
|
, line_( 0 )
|
||||||
|
{}
|
||||||
|
void set_location( const char* file, int line )
|
||||||
|
{
|
||||||
|
file_ = file;
|
||||||
|
line_ = line;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool verify() const
|
||||||
|
{
|
||||||
|
return i_->verify();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool invoke() const
|
||||||
|
{
|
||||||
|
for( sequences_cit it = sequences_.begin();
|
||||||
|
it != sequences_.end(); ++it )
|
||||||
|
if( ! (*it)->is_valid( this ) )
|
||||||
|
return false;
|
||||||
|
bool result = i_->invoke();
|
||||||
|
for( sequences_cit it = sequences_.begin();
|
||||||
|
it != sequences_.end(); ++it )
|
||||||
|
(*it)->invalidate( this );
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool invoked() const
|
||||||
|
{
|
||||||
|
return i_->invoked();
|
||||||
|
}
|
||||||
|
|
||||||
|
const char* file() const
|
||||||
|
{
|
||||||
|
return file_;
|
||||||
|
}
|
||||||
|
int line() const
|
||||||
|
{
|
||||||
|
return line_;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
~expectation_base()
|
||||||
|
{
|
||||||
|
for( sequences_cit it = sequences_.begin();
|
||||||
|
it != sequences_.end(); ++it )
|
||||||
|
(*it)->remove( this );
|
||||||
|
}
|
||||||
|
|
||||||
|
void expect( detail::invocation* i )
|
||||||
|
{
|
||||||
|
i_.reset( i );
|
||||||
|
}
|
||||||
|
|
||||||
|
void add( boost::shared_ptr< detail::sequence_impl > s )
|
||||||
|
{
|
||||||
|
s->add( this );
|
||||||
|
sequences_.push_back( s );
|
||||||
|
}
|
||||||
|
|
||||||
|
boost::shared_ptr< detail::invocation > i_;
|
||||||
|
|
||||||
|
private:
|
||||||
|
typedef std::vector<
|
||||||
|
boost::shared_ptr< detail::sequence_impl >
|
||||||
|
> sequences_type;
|
||||||
|
typedef sequences_type::const_iterator sequences_cit;
|
||||||
|
|
||||||
|
sequences_type sequences_;
|
||||||
|
const char* file_;
|
||||||
|
int line_;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
} // mock
|
||||||
|
|
||||||
|
#endif // MOCK_EXPECTATION_BASE_HPP_INCLUDED
|
||||||
141
turtle/expectation_template.hpp
Normal file
141
turtle/expectation_template.hpp
Normal file
|
|
@ -0,0 +1,141 @@
|
||||||
|
// http://turtle.sourceforge.net
|
||||||
|
//
|
||||||
|
// Copyright Mathieu Champlon 2012
|
||||||
|
//
|
||||||
|
// Distributed under the Boost Software License, Version 1.0.
|
||||||
|
// (See accompanying file LICENSE_1_0.txt or copy at
|
||||||
|
// http://www.boost.org/LICENSE_1_0.txt)
|
||||||
|
|
||||||
|
#include "expectation_base.hpp"
|
||||||
|
|
||||||
|
#define MOCK_EXPECTATION_TYPEDEF(z, n, d) \
|
||||||
|
typedef T##n arg##n##_type;
|
||||||
|
|
||||||
|
#define MOCK_EXPECTATION_INITIALIZE(z, n, d) \
|
||||||
|
BOOST_PP_COMMA_IF(n) c##n##_( \
|
||||||
|
new detail::check< \
|
||||||
|
arg##n##_type, \
|
||||||
|
constraint< detail::any > \
|
||||||
|
>( mock::any ) )
|
||||||
|
|
||||||
|
#define MOCK_EXPECTATION_WITH(z, n, d) \
|
||||||
|
c##n##_.reset( \
|
||||||
|
new detail::check< \
|
||||||
|
arg##n##_type, \
|
||||||
|
Constraint_##n \
|
||||||
|
>( c##n ) );
|
||||||
|
|
||||||
|
#define MOCK_EXPECTATION_MEMBER(z, n, d) \
|
||||||
|
boost::shared_ptr< detail::check_base< arg##n##_type > > c##n##_;
|
||||||
|
|
||||||
|
#define MOCK_EXPECTATION_ARGS(z, n, d) \
|
||||||
|
BOOST_PP_COMMA_IF(n) arg##n##_type a##n
|
||||||
|
|
||||||
|
#define MOCK_EXPECTATION_IS_VALID(z, n, d) \
|
||||||
|
&& (*c##n##_)( a##n )
|
||||||
|
|
||||||
|
#define MOCK_EXPECTATION_SERIALIZE(z, n, d) \
|
||||||
|
BOOST_PP_IF(n, << ", " <<,) *m.c##n##_
|
||||||
|
|
||||||
|
namespace mock
|
||||||
|
{
|
||||||
|
namespace detail
|
||||||
|
{
|
||||||
|
template< typename Signature > class expectation;
|
||||||
|
|
||||||
|
template< typename R BOOST_PP_COMMA_IF(MOCK_NUM_ARGS)
|
||||||
|
BOOST_PP_ENUM_PARAMS(MOCK_NUM_ARGS, typename T) >
|
||||||
|
class expectation< R (BOOST_PP_ENUM_PARAMS(MOCK_NUM_ARGS,T)) >
|
||||||
|
: public expectation_base
|
||||||
|
, public action< R, R (BOOST_PP_ENUM_PARAMS(MOCK_NUM_ARGS,T)) >
|
||||||
|
{
|
||||||
|
BOOST_PP_REPEAT(MOCK_NUM_ARGS,
|
||||||
|
MOCK_EXPECTATION_TYPEDEF, BOOST_PP_EMPTY)
|
||||||
|
public:
|
||||||
|
#ifndef MOCK_NUM_ARGS_0
|
||||||
|
expectation()
|
||||||
|
:
|
||||||
|
BOOST_PP_REPEAT(MOCK_NUM_ARGS,
|
||||||
|
MOCK_EXPECTATION_INITIALIZE, BOOST_PP_EMPTY)
|
||||||
|
{}
|
||||||
|
template< BOOST_PP_ENUM_PARAMS(MOCK_NUM_ARGS, typename Constraint_) >
|
||||||
|
expectation& with(
|
||||||
|
BOOST_PP_ENUM_BINARY_PARAMS(MOCK_NUM_ARGS, Constraint_, c) )
|
||||||
|
{
|
||||||
|
BOOST_PP_REPEAT(MOCK_NUM_ARGS,
|
||||||
|
MOCK_EXPECTATION_WITH, BOOST_PP_EMPTY)
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
bool is_valid(
|
||||||
|
BOOST_PP_REPEAT(MOCK_NUM_ARGS,
|
||||||
|
MOCK_EXPECTATION_ARGS, BOOST_PP_EMPTY) ) const
|
||||||
|
{
|
||||||
|
return ! i_->exhausted()
|
||||||
|
BOOST_PP_REPEAT(MOCK_NUM_ARGS,
|
||||||
|
MOCK_EXPECTATION_IS_VALID, BOOST_PP_EMPTY);
|
||||||
|
}
|
||||||
|
|
||||||
|
expectation& in( sequence& s )
|
||||||
|
{
|
||||||
|
add( s.impl_ );
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
expectation& once()
|
||||||
|
{
|
||||||
|
expect( new detail::once() );
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
expectation& never()
|
||||||
|
{
|
||||||
|
expect( new detail::never() );
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
expectation& exactly( std::size_t count )
|
||||||
|
{
|
||||||
|
expect( new detail::exactly( count ) );
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
expectation& at_least( std::size_t min )
|
||||||
|
{
|
||||||
|
expect( new detail::at_least( min ) );
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
expectation& at_most( std::size_t max )
|
||||||
|
{
|
||||||
|
expect( new detail::at_most( max ) );
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
expectation& between( std::size_t min, std::size_t max )
|
||||||
|
{
|
||||||
|
expect( new detail::between( min, max ) );
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
friend std::ostream& operator<<(
|
||||||
|
std::ostream& s, const expectation& m )
|
||||||
|
{
|
||||||
|
return s << (m.i_->exhausted() ? 'v' : '.')
|
||||||
|
<< ' ' << *m.i_
|
||||||
|
#ifndef MOCK_NUM_ARGS_0
|
||||||
|
<< ".with( "
|
||||||
|
<< BOOST_PP_REPEAT(MOCK_NUM_ARGS,
|
||||||
|
MOCK_EXPECTATION_SERIALIZE, BOOST_PP_EMPTY)
|
||||||
|
<< " )"
|
||||||
|
#endif
|
||||||
|
;
|
||||||
|
}
|
||||||
|
private:
|
||||||
|
BOOST_PP_REPEAT(MOCK_NUM_ARGS, MOCK_EXPECTATION_MEMBER, BOOST_PP_EMPTY)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
} // mock
|
||||||
|
|
||||||
|
#undef MOCK_EXPECTATION_TYPEDEF
|
||||||
|
#undef MOCK_EXPECTATION_INITIALIZE
|
||||||
|
#undef MOCK_EXPECTATION_WITH
|
||||||
|
#undef MOCK_EXPECTATION_MEMBER
|
||||||
|
#undef MOCK_EXPECTATION_ARGS
|
||||||
|
#undef MOCK_EXPECTATION_IS_VALID
|
||||||
|
#undef MOCK_EXPECTATION_SERIALIZE
|
||||||
|
#undef MOCK_EXPECTATION
|
||||||
|
|
@ -11,309 +11,41 @@
|
||||||
|
|
||||||
#include "config.hpp"
|
#include "config.hpp"
|
||||||
#include "error.hpp"
|
#include "error.hpp"
|
||||||
#include "expectation.hpp"
|
|
||||||
#include "log.hpp"
|
#include "log.hpp"
|
||||||
|
#include "check.hpp"
|
||||||
|
#include "action.hpp"
|
||||||
|
#include "invocation.hpp"
|
||||||
|
#include "constraints.hpp"
|
||||||
|
#include "sequence.hpp"
|
||||||
#include "detail/verifiable.hpp"
|
#include "detail/verifiable.hpp"
|
||||||
#include "detail/type_name.hpp"
|
#include "detail/type_name.hpp"
|
||||||
#include "detail/context.hpp"
|
#include "detail/context.hpp"
|
||||||
#include "detail/args.hpp"
|
|
||||||
#include <boost/function_types/result_type.hpp>
|
|
||||||
#include <boost/function_types/function_arity.hpp>
|
|
||||||
#include <boost/function_types/parameter_types.hpp>
|
|
||||||
#include <boost/preprocessor/repetition/repeat_from_to.hpp>
|
#include <boost/preprocessor/repetition/repeat_from_to.hpp>
|
||||||
#include <boost/preprocessor/repetition/enum_params.hpp>
|
#include <boost/preprocessor/repetition/enum_params.hpp>
|
||||||
#include <boost/preprocessor/repetition/enum_binary_params.hpp>
|
#include <boost/preprocessor/repetition/enum_binary_params.hpp>
|
||||||
#include <boost/preprocessor/comparison/equal.hpp>
|
#include <boost/preprocessor/comparison/equal.hpp>
|
||||||
#include <boost/test/utils/basic_cstring/basic_cstring.hpp>
|
#include <boost/test/utils/basic_cstring/basic_cstring.hpp>
|
||||||
#include <boost/test/utils/lazy_ostream.hpp>
|
#include <boost/test/utils/lazy_ostream.hpp>
|
||||||
|
#include <boost/function_types/result_type.hpp>
|
||||||
#include <boost/enable_shared_from_this.hpp>
|
#include <boost/enable_shared_from_this.hpp>
|
||||||
#include <boost/shared_ptr.hpp>
|
|
||||||
#include <boost/optional.hpp>
|
#include <boost/optional.hpp>
|
||||||
#include <ostream>
|
#include <ostream>
|
||||||
|
#include <vector>
|
||||||
#include <list>
|
#include <list>
|
||||||
|
|
||||||
|
#define MOCK_NUM_ARGS 0
|
||||||
|
#define MOCK_NUM_ARGS_0
|
||||||
|
#include "function_template.hpp"
|
||||||
|
#undef MOCK_NUM_ARGS_0
|
||||||
|
#undef MOCK_NUM_ARGS
|
||||||
|
|
||||||
|
#define BOOST_PP_ITERATION_PARAMS_1 \
|
||||||
|
(3,(1,MOCK_MAX_ARGS,"function_iterate.hpp"))
|
||||||
|
#include BOOST_PP_ITERATE()
|
||||||
|
#undef BOOST_PP_ITERATION_PARAMS_1
|
||||||
|
|
||||||
namespace mock
|
namespace mock
|
||||||
{
|
{
|
||||||
template< typename Signature >
|
|
||||||
class function
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
typedef BOOST_DEDUCED_TYPENAME
|
|
||||||
boost::function_types::result_type< Signature >::type result_type;
|
|
||||||
|
|
||||||
template< typename Args >
|
|
||||||
struct sig
|
|
||||||
{
|
|
||||||
typedef result_type type;
|
|
||||||
};
|
|
||||||
|
|
||||||
private:
|
|
||||||
typedef BOOST_DEDUCED_TYPENAME
|
|
||||||
boost::function_types::function_arity< Signature > arity;
|
|
||||||
typedef BOOST_DEDUCED_TYPENAME
|
|
||||||
detail::expectation< Signature, arity::value > expectation_type;
|
|
||||||
|
|
||||||
public:
|
|
||||||
function()
|
|
||||||
: impl_( new function_impl() )
|
|
||||||
{}
|
|
||||||
|
|
||||||
bool verify() const
|
|
||||||
{
|
|
||||||
return impl_->verify();
|
|
||||||
}
|
|
||||||
bool verify( const char* file, int line ) const
|
|
||||||
{
|
|
||||||
function_impl::error_type::checkpoint( file, line );
|
|
||||||
return impl_->verify();
|
|
||||||
}
|
|
||||||
void reset()
|
|
||||||
{
|
|
||||||
impl_->reset();
|
|
||||||
}
|
|
||||||
void reset( const char* file, int line )
|
|
||||||
{
|
|
||||||
function_impl::error_type::checkpoint( file, line );
|
|
||||||
return impl_->reset();
|
|
||||||
}
|
|
||||||
|
|
||||||
expectation_type& expect( const char* file, int line )
|
|
||||||
{
|
|
||||||
function_impl::error_type::checkpoint( file, line );
|
|
||||||
return impl_->expect();
|
|
||||||
}
|
|
||||||
expectation_type& expect()
|
|
||||||
{
|
|
||||||
return impl_->expect();
|
|
||||||
}
|
|
||||||
|
|
||||||
void test() const
|
|
||||||
{
|
|
||||||
impl_->test();
|
|
||||||
}
|
|
||||||
|
|
||||||
result_type operator()() const
|
|
||||||
{
|
|
||||||
return (*impl_)();
|
|
||||||
}
|
|
||||||
|
|
||||||
#define MOCK_FUNCTION_OPERATOR(z, n, d) \
|
|
||||||
MOCK_DECL(operator(), n, Signature, const, BOOST_DEDUCED_TYPENAME) \
|
|
||||||
{ \
|
|
||||||
return (*impl_)( BOOST_PP_ENUM_PARAMS(n, p) ); \
|
|
||||||
}
|
|
||||||
|
|
||||||
BOOST_PP_REPEAT_FROM_TO(
|
|
||||||
1,
|
|
||||||
BOOST_PP_INC(MOCK_MAX_ARGS),
|
|
||||||
MOCK_FUNCTION_OPERATOR,
|
|
||||||
BOOST_PP_EMPTY)
|
|
||||||
|
|
||||||
#undef MOCK_FUNCTION_OPERATOR
|
|
||||||
|
|
||||||
friend std::ostream& operator<<( std::ostream& s, const function& e )
|
|
||||||
{
|
|
||||||
return s << *e.impl_;
|
|
||||||
}
|
|
||||||
|
|
||||||
function& operator()( detail::context& c,
|
|
||||||
boost::unit_test::const_string instance )
|
|
||||||
{
|
|
||||||
if( ! impl_->context_ )
|
|
||||||
c.add( *impl_ );
|
|
||||||
c.add( impl_.get(), *impl_, instance,
|
|
||||||
boost::optional< detail::type_name >(), "" );
|
|
||||||
impl_->context_ = &c;
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
void configure( detail::context& c, const void* p,
|
|
||||||
boost::unit_test::const_string instance,
|
|
||||||
const boost::optional< detail::type_name >& type,
|
|
||||||
boost::unit_test::const_string name ) const
|
|
||||||
{
|
|
||||||
if( ! impl_->context_ )
|
|
||||||
c.add( *impl_ );
|
|
||||||
c.add( p, *impl_, instance, type, name );
|
|
||||||
impl_->context_ = &c;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
class function_impl : public detail::verifiable,
|
|
||||||
public boost::enable_shared_from_this< function_impl >
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
typedef MOCK_ERROR_POLICY< result_type > error_type;
|
|
||||||
|
|
||||||
public:
|
|
||||||
function_impl()
|
|
||||||
: context_( 0 )
|
|
||||||
, valid_( true )
|
|
||||||
{}
|
|
||||||
virtual ~function_impl()
|
|
||||||
{
|
|
||||||
if( valid_ && ! std::uncaught_exception() )
|
|
||||||
for( expectations_cit it = expectations_.begin();
|
|
||||||
it != expectations_.end(); ++it )
|
|
||||||
{
|
|
||||||
if( ! it->verify() )
|
|
||||||
error_type::untriggered_expectation(
|
|
||||||
boost::unit_test::lazy_ostream::instance()
|
|
||||||
<< lazy_context( this )
|
|
||||||
<< lazy_expectations( this ),
|
|
||||||
it->file(), it->line() );
|
|
||||||
else if( ! it->invoked() )
|
|
||||||
error_type::expected_call(
|
|
||||||
boost::unit_test::lazy_ostream::instance()
|
|
||||||
<< lazy_context( this )
|
|
||||||
<< lazy_expectations( this ),
|
|
||||||
it->file(), it->line() );
|
|
||||||
}
|
|
||||||
if( context_ )
|
|
||||||
context_->remove( *this );
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual bool verify() const
|
|
||||||
{
|
|
||||||
for( expectations_cit it = expectations_.begin();
|
|
||||||
it != expectations_.end(); ++it )
|
|
||||||
if( !it->verify() )
|
|
||||||
{
|
|
||||||
valid_ = false;
|
|
||||||
error_type::verification_failed(
|
|
||||||
boost::unit_test::lazy_ostream::instance()
|
|
||||||
<< lazy_context( this )
|
|
||||||
<< lazy_expectations( this ),
|
|
||||||
it->file(), it->line() );
|
|
||||||
}
|
|
||||||
return valid_;
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual void reset()
|
|
||||||
{
|
|
||||||
valid_ = true;
|
|
||||||
boost::shared_ptr< function_impl > guard =
|
|
||||||
this->shared_from_this();
|
|
||||||
expectations_.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
expectation_type& expect( const char* file, int line )
|
|
||||||
{
|
|
||||||
expectation_type& e = expect();
|
|
||||||
e.set_location( file, line );
|
|
||||||
return e;
|
|
||||||
}
|
|
||||||
expectation_type& expect()
|
|
||||||
{
|
|
||||||
expectations_.push_back( expectation_type() );
|
|
||||||
valid_ = true;
|
|
||||||
return expectations_.back();
|
|
||||||
}
|
|
||||||
|
|
||||||
#define MOCK_FUNCTION_FORMAT(z, n, N) \
|
|
||||||
<< " " << mock::format( p##n ) \
|
|
||||||
<< BOOST_PP_IF(BOOST_PP_EQUAL(N,n), " ", ",")
|
|
||||||
#define MOCK_FUNCTION_CONTEXT(n) \
|
|
||||||
boost::unit_test::lazy_ostream::instance() \
|
|
||||||
<< lazy_context( this ) \
|
|
||||||
<< "(" BOOST_PP_REPEAT(n, MOCK_FUNCTION_FORMAT, BOOST_PP_DEC(n)) \
|
|
||||||
<< ")" \
|
|
||||||
<< lazy_expectations( this )
|
|
||||||
#define MOCK_FUNCTION_INVOKE(z, n, A) \
|
|
||||||
{ \
|
|
||||||
valid_ = false; \
|
|
||||||
for( expectations_cit it = expectations_.begin(); \
|
|
||||||
it != expectations_.end(); ++it ) \
|
|
||||||
if( it->is_valid( BOOST_PP_ENUM_PARAMS(n, p) ) ) \
|
|
||||||
{ \
|
|
||||||
if( ! it->invoke() ) \
|
|
||||||
{ \
|
|
||||||
error_type::sequence_failed( \
|
|
||||||
MOCK_FUNCTION_CONTEXT(n), it->file(), it->line() ); \
|
|
||||||
return A; \
|
|
||||||
} \
|
|
||||||
if( ! it->functor() ) \
|
|
||||||
{ \
|
|
||||||
error_type::missing_action( \
|
|
||||||
MOCK_FUNCTION_CONTEXT(n), it->file(), it->line() ); \
|
|
||||||
return A; \
|
|
||||||
} \
|
|
||||||
valid_ = true; \
|
|
||||||
error_type::expected_call( \
|
|
||||||
MOCK_FUNCTION_CONTEXT(n), it->file(), it->line() ); \
|
|
||||||
return it->functor()( BOOST_PP_ENUM_PARAMS(n, p) ); \
|
|
||||||
} \
|
|
||||||
error_type::unexpected_call( MOCK_FUNCTION_CONTEXT(n) ); \
|
|
||||||
return A; \
|
|
||||||
}
|
|
||||||
#define MOCK_FUNCTION_OPERATOR(z, n, P) \
|
|
||||||
MOCK_DECL(operator(), n, Signature, const, BOOST_DEDUCED_TYPENAME) \
|
|
||||||
MOCK_FUNCTION_INVOKE(z, n, P)
|
|
||||||
|
|
||||||
BOOST_PP_REPEAT(
|
|
||||||
BOOST_PP_INC(MOCK_MAX_ARGS),
|
|
||||||
MOCK_FUNCTION_OPERATOR,
|
|
||||||
error_type::abort())
|
|
||||||
|
|
||||||
void test() const
|
|
||||||
MOCK_FUNCTION_INVOKE(, 0,)
|
|
||||||
|
|
||||||
#undef MOCK_FUNCTION_FORMAT
|
|
||||||
#undef MOCK_FUNCTION_OPERATOR
|
|
||||||
#undef MOCK_FUNCTION_INVOKE
|
|
||||||
#undef MOCK_FUNCTION_CONTEXT
|
|
||||||
|
|
||||||
friend std::ostream& operator<<(
|
|
||||||
std::ostream& s, const function_impl& e )
|
|
||||||
{
|
|
||||||
return s << lazy_context( &e ) << lazy_expectations( &e );
|
|
||||||
}
|
|
||||||
|
|
||||||
struct lazy_context
|
|
||||||
{
|
|
||||||
lazy_context( const function_impl* impl )
|
|
||||||
: impl_( impl )
|
|
||||||
{}
|
|
||||||
friend std::ostream& operator<<(
|
|
||||||
std::ostream& s, const lazy_context& c )
|
|
||||||
{
|
|
||||||
if( c.impl_->context_ )
|
|
||||||
c.impl_->context_->serialize( s, *c.impl_ );
|
|
||||||
else
|
|
||||||
s << "?";
|
|
||||||
return s;
|
|
||||||
}
|
|
||||||
const function_impl* impl_;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct lazy_expectations
|
|
||||||
{
|
|
||||||
lazy_expectations( const function_impl* impl )
|
|
||||||
: impl_( impl )
|
|
||||||
{}
|
|
||||||
friend std::ostream& operator<<(
|
|
||||||
std::ostream& s, const lazy_expectations& e )
|
|
||||||
{
|
|
||||||
for( expectations_cit it = e.impl_->expectations_.begin();
|
|
||||||
it != e.impl_->expectations_.end(); ++it )
|
|
||||||
s << std::endl << *it;
|
|
||||||
return s;
|
|
||||||
}
|
|
||||||
const function_impl* impl_;
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef std::list< expectation_type > expectations_type;
|
|
||||||
typedef BOOST_DEDUCED_TYPENAME
|
|
||||||
expectations_type::const_iterator expectations_cit;
|
|
||||||
|
|
||||||
expectations_type expectations_;
|
|
||||||
detail::context* context_;
|
|
||||||
mutable bool valid_;
|
|
||||||
};
|
|
||||||
|
|
||||||
boost::shared_ptr< function_impl > impl_;
|
|
||||||
};
|
|
||||||
|
|
||||||
template< typename Signature >
|
template< typename Signature >
|
||||||
bool verify( const function< Signature >& f )
|
bool verify( const function< Signature >& f )
|
||||||
{
|
{
|
||||||
|
|
|
||||||
11
turtle/function_iterate.hpp
Normal file
11
turtle/function_iterate.hpp
Normal file
|
|
@ -0,0 +1,11 @@
|
||||||
|
// http://turtle.sourceforge.net
|
||||||
|
//
|
||||||
|
// Copyright Mathieu Champlon 2012
|
||||||
|
//
|
||||||
|
// Distributed under the Boost Software License, Version 1.0.
|
||||||
|
// (See accompanying file LICENSE_1_0.txt or copy at
|
||||||
|
// http://www.boost.org/LICENSE_1_0.txt)
|
||||||
|
|
||||||
|
#define MOCK_NUM_ARGS BOOST_PP_ITERATION()
|
||||||
|
#include "function_template.hpp"
|
||||||
|
#undef MOCK_NUM_ARGS
|
||||||
275
turtle/function_template.hpp
Normal file
275
turtle/function_template.hpp
Normal file
|
|
@ -0,0 +1,275 @@
|
||||||
|
// http://turtle.sourceforge.net
|
||||||
|
//
|
||||||
|
// Copyright Mathieu Champlon 2008
|
||||||
|
//
|
||||||
|
// Distributed under the Boost Software License, Version 1.0.
|
||||||
|
// (See accompanying file LICENSE_1_0.txt or copy at
|
||||||
|
// http://www.boost.org/LICENSE_1_0.txt)
|
||||||
|
|
||||||
|
#include "expectation_template.hpp"
|
||||||
|
|
||||||
|
namespace mock
|
||||||
|
{
|
||||||
|
template< typename Signature > class function;
|
||||||
|
|
||||||
|
template< typename R BOOST_PP_COMMA_IF(MOCK_NUM_ARGS)
|
||||||
|
BOOST_PP_ENUM_PARAMS(MOCK_NUM_ARGS, typename T) >
|
||||||
|
class function< R ( BOOST_PP_ENUM_PARAMS(MOCK_NUM_ARGS, T) ) >
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
typedef R result_type;
|
||||||
|
|
||||||
|
template< typename Args >
|
||||||
|
struct sig
|
||||||
|
{
|
||||||
|
typedef R type;
|
||||||
|
};
|
||||||
|
|
||||||
|
private:
|
||||||
|
typedef detail::expectation<
|
||||||
|
R ( BOOST_PP_ENUM_PARAMS(MOCK_NUM_ARGS, T) )
|
||||||
|
> expectation_type;
|
||||||
|
|
||||||
|
public:
|
||||||
|
function()
|
||||||
|
: impl_( new function_impl() )
|
||||||
|
{}
|
||||||
|
|
||||||
|
bool verify() const
|
||||||
|
{
|
||||||
|
return impl_->verify();
|
||||||
|
}
|
||||||
|
bool verify( const char* file, int line ) const
|
||||||
|
{
|
||||||
|
function_impl::error_type::checkpoint( file, line );
|
||||||
|
return impl_->verify();
|
||||||
|
}
|
||||||
|
void reset()
|
||||||
|
{
|
||||||
|
impl_->reset();
|
||||||
|
}
|
||||||
|
void reset( const char* file, int line )
|
||||||
|
{
|
||||||
|
function_impl::error_type::checkpoint( file, line );
|
||||||
|
return impl_->reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
expectation_type& expect( const char* file, int line )
|
||||||
|
{
|
||||||
|
function_impl::error_type::checkpoint( file, line );
|
||||||
|
return impl_->expect();
|
||||||
|
}
|
||||||
|
expectation_type& expect()
|
||||||
|
{
|
||||||
|
return impl_->expect();
|
||||||
|
}
|
||||||
|
|
||||||
|
void test() const
|
||||||
|
{
|
||||||
|
impl_->test();
|
||||||
|
}
|
||||||
|
|
||||||
|
R operator()( BOOST_PP_ENUM_BINARY_PARAMS(MOCK_NUM_ARGS, T, t) ) const
|
||||||
|
{
|
||||||
|
return (*impl_)( BOOST_PP_ENUM_PARAMS(MOCK_NUM_ARGS, t) );
|
||||||
|
}
|
||||||
|
|
||||||
|
friend std::ostream& operator<<( std::ostream& s, const function& e )
|
||||||
|
{
|
||||||
|
return s << *e.impl_;
|
||||||
|
}
|
||||||
|
|
||||||
|
function& operator()( detail::context& c,
|
||||||
|
boost::unit_test::const_string instance )
|
||||||
|
{
|
||||||
|
if( ! impl_->context_ )
|
||||||
|
c.add( *impl_ );
|
||||||
|
c.add( impl_.get(), *impl_, instance,
|
||||||
|
boost::optional< detail::type_name >(), "" );
|
||||||
|
impl_->context_ = &c;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
void configure( detail::context& c, const void* p,
|
||||||
|
boost::unit_test::const_string instance,
|
||||||
|
const boost::optional< detail::type_name >& type,
|
||||||
|
boost::unit_test::const_string name ) const
|
||||||
|
{
|
||||||
|
if( ! impl_->context_ )
|
||||||
|
c.add( *impl_ );
|
||||||
|
c.add( p, *impl_, instance, type, name );
|
||||||
|
impl_->context_ = &c;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
class function_impl : public detail::verifiable,
|
||||||
|
public boost::enable_shared_from_this< function_impl >
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
typedef MOCK_ERROR_POLICY< result_type > error_type;
|
||||||
|
|
||||||
|
public:
|
||||||
|
function_impl()
|
||||||
|
: context_( 0 )
|
||||||
|
, valid_( true )
|
||||||
|
{}
|
||||||
|
virtual ~function_impl()
|
||||||
|
{
|
||||||
|
if( valid_ && ! std::uncaught_exception() )
|
||||||
|
for( expectations_cit it = expectations_.begin();
|
||||||
|
it != expectations_.end(); ++it )
|
||||||
|
{
|
||||||
|
if( ! it->verify() )
|
||||||
|
error_type::untriggered_expectation(
|
||||||
|
boost::unit_test::lazy_ostream::instance()
|
||||||
|
<< lazy_context( this )
|
||||||
|
<< lazy_expectations( this ),
|
||||||
|
it->file(), it->line() );
|
||||||
|
else if( ! it->invoked() )
|
||||||
|
error_type::expected_call(
|
||||||
|
boost::unit_test::lazy_ostream::instance()
|
||||||
|
<< lazy_context( this )
|
||||||
|
<< lazy_expectations( this ),
|
||||||
|
it->file(), it->line() );
|
||||||
|
}
|
||||||
|
if( context_ )
|
||||||
|
context_->remove( *this );
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual bool verify() const
|
||||||
|
{
|
||||||
|
for( expectations_cit it = expectations_.begin();
|
||||||
|
it != expectations_.end(); ++it )
|
||||||
|
if( !it->verify() )
|
||||||
|
{
|
||||||
|
valid_ = false;
|
||||||
|
error_type::verification_failed(
|
||||||
|
boost::unit_test::lazy_ostream::instance()
|
||||||
|
<< lazy_context( this )
|
||||||
|
<< lazy_expectations( this ),
|
||||||
|
it->file(), it->line() );
|
||||||
|
}
|
||||||
|
return valid_;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void reset()
|
||||||
|
{
|
||||||
|
valid_ = true;
|
||||||
|
boost::shared_ptr< function_impl > guard =
|
||||||
|
this->shared_from_this();
|
||||||
|
expectations_.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
expectation_type& expect( const char* file, int line )
|
||||||
|
{
|
||||||
|
expectation_type& e = expect();
|
||||||
|
e.set_location( file, line );
|
||||||
|
return e;
|
||||||
|
}
|
||||||
|
expectation_type& expect()
|
||||||
|
{
|
||||||
|
expectations_.push_back( expectation_type() );
|
||||||
|
valid_ = true;
|
||||||
|
return expectations_.back();
|
||||||
|
}
|
||||||
|
|
||||||
|
#define MOCK_FORMAT(z, n, N) \
|
||||||
|
<< " " << mock::format( t##n ) \
|
||||||
|
<< BOOST_PP_IF(BOOST_PP_EQUAL(N,n), " ", ",")
|
||||||
|
#define MOCK_CONTEXT(n) \
|
||||||
|
boost::unit_test::lazy_ostream::instance() \
|
||||||
|
<< lazy_context( this ) \
|
||||||
|
<< "(" BOOST_PP_REPEAT(n, MOCK_FORMAT, BOOST_PP_DEC(n)) \
|
||||||
|
<< ")" \
|
||||||
|
<< lazy_expectations( this )
|
||||||
|
#define MOCK_INVOKE(z, n, A) \
|
||||||
|
{ \
|
||||||
|
valid_ = false; \
|
||||||
|
for( expectations_cit it = expectations_.begin(); \
|
||||||
|
it != expectations_.end(); ++it ) \
|
||||||
|
if( it->is_valid( BOOST_PP_ENUM_PARAMS(n, t) ) ) \
|
||||||
|
{ \
|
||||||
|
if( ! it->invoke() ) \
|
||||||
|
{ \
|
||||||
|
error_type::sequence_failed( \
|
||||||
|
MOCK_CONTEXT(n), it->file(), it->line() ); \
|
||||||
|
return A; \
|
||||||
|
} \
|
||||||
|
if( ! it->functor() ) \
|
||||||
|
{ \
|
||||||
|
error_type::missing_action( \
|
||||||
|
MOCK_CONTEXT(n), it->file(), it->line() ); \
|
||||||
|
return A; \
|
||||||
|
} \
|
||||||
|
valid_ = true; \
|
||||||
|
error_type::expected_call( \
|
||||||
|
MOCK_CONTEXT(n), it->file(), it->line() ); \
|
||||||
|
return it->functor()( BOOST_PP_ENUM_PARAMS(n, t) ); \
|
||||||
|
} \
|
||||||
|
error_type::unexpected_call( MOCK_CONTEXT(n) ); \
|
||||||
|
return A; \
|
||||||
|
}
|
||||||
|
|
||||||
|
result_type operator()(
|
||||||
|
BOOST_PP_ENUM_BINARY_PARAMS(MOCK_NUM_ARGS, T, t) ) const
|
||||||
|
MOCK_INVOKE(, MOCK_NUM_ARGS, error_type::abort())
|
||||||
|
|
||||||
|
void test() const
|
||||||
|
MOCK_INVOKE(, 0,)
|
||||||
|
|
||||||
|
#undef MOCK_FORMAT
|
||||||
|
#undef MOCK_OPERATOR
|
||||||
|
#undef MOCK_INVOKE
|
||||||
|
#undef MOCK_CONTEXT
|
||||||
|
|
||||||
|
friend std::ostream& operator<<(
|
||||||
|
std::ostream& s, const function_impl& e )
|
||||||
|
{
|
||||||
|
return s << lazy_context( &e ) << lazy_expectations( &e );
|
||||||
|
}
|
||||||
|
|
||||||
|
struct lazy_context
|
||||||
|
{
|
||||||
|
lazy_context( const function_impl* impl )
|
||||||
|
: impl_( impl )
|
||||||
|
{}
|
||||||
|
friend std::ostream& operator<<(
|
||||||
|
std::ostream& s, const lazy_context& c )
|
||||||
|
{
|
||||||
|
if( c.impl_->context_ )
|
||||||
|
c.impl_->context_->serialize( s, *c.impl_ );
|
||||||
|
else
|
||||||
|
s << "?";
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
const function_impl* impl_;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct lazy_expectations
|
||||||
|
{
|
||||||
|
lazy_expectations( const function_impl* impl )
|
||||||
|
: impl_( impl )
|
||||||
|
{}
|
||||||
|
friend std::ostream& operator<<(
|
||||||
|
std::ostream& s, const lazy_expectations& e )
|
||||||
|
{
|
||||||
|
for( expectations_cit it = e.impl_->expectations_.begin();
|
||||||
|
it != e.impl_->expectations_.end(); ++it )
|
||||||
|
s << std::endl << *it;
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
const function_impl* impl_;
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef std::list< expectation_type > expectations_type;
|
||||||
|
typedef BOOST_DEDUCED_TYPENAME
|
||||||
|
expectations_type::const_iterator expectations_cit;
|
||||||
|
|
||||||
|
expectations_type expectations_;
|
||||||
|
detail::context* context_;
|
||||||
|
mutable bool valid_;
|
||||||
|
};
|
||||||
|
|
||||||
|
boost::shared_ptr< function_impl > impl_;
|
||||||
|
};
|
||||||
|
} // mock
|
||||||
Loading…
Add table
Add a link
Reference in a new issue