diff --git a/build/vc100/turtle.vcxproj b/build/vc100/turtle.vcxproj
index da3c4dd..488e168 100644
--- a/build/vc100/turtle.vcxproj
+++ b/build/vc100/turtle.vcxproj
@@ -150,7 +150,9 @@
+
+
diff --git a/build/vc100/turtle.vcxproj.filters b/build/vc100/turtle.vcxproj.filters
index bbfd10d..b1a367e 100644
--- a/build/vc100/turtle.vcxproj.filters
+++ b/build/vc100/turtle.vcxproj.filters
@@ -73,5 +73,11 @@
Source Files
+
+ Source Files
+
+
+ Source Files
+
\ No newline at end of file
diff --git a/build/vc100/turtle_test.vcxproj b/build/vc100/turtle_test.vcxproj
index ca7de70..2e9efb0 100644
--- a/build/vc100/turtle_test.vcxproj
+++ b/build/vc100/turtle_test.vcxproj
@@ -18,6 +18,26 @@
x64
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
{74810A2A-33D8-47D6-9A50-71261F1683F5}
turtle_test
@@ -194,24 +214,6 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/build/vc100/turtle_test.vcxproj.filters b/build/vc100/turtle_test.vcxproj.filters
index f489b3d..bee76d5 100644
--- a/build/vc100/turtle_test.vcxproj.filters
+++ b/build/vc100/turtle_test.vcxproj.filters
@@ -7,15 +7,6 @@
-
- Source Files
-
-
- Source Files
-
-
- Source Files
-
Source Files
@@ -25,9 +16,18 @@
Source Files
+
+ Source Files
+
Source Files
+
+ Source Files
+
+
+ Source Files
+
Source Files
@@ -40,7 +40,13 @@
Source Files
-
+
+ Source Files
+
+
+ Source Files
+
+
Source Files
diff --git a/build/vc80/turtle.vcproj b/build/vc80/turtle.vcproj
index 549e207..a311d55 100644
--- a/build/vc80/turtle.vcproj
+++ b/build/vc80/turtle.vcproj
@@ -196,10 +196,22 @@
RelativePath="..\..\src\libraries\turtle\invocation.hpp"
>
+
+
+
+
+
+
@@ -228,6 +240,10 @@
RelativePath="..\..\src\libraries\turtle\sequence.hpp"
>
+
+
@@ -236,6 +252,10 @@
RelativePath="..\..\src\libraries\turtle\verifiable.hpp"
>
+
+
diff --git a/build/vc80/turtle_test.vcproj b/build/vc80/turtle_test.vcproj
index 492812c..8c02089 100644
--- a/build/vc80/turtle_test.vcproj
+++ b/build/vc80/turtle_test.vcproj
@@ -214,10 +214,22 @@
RelativePath="..\..\src\tests\turtle_test\invocation_test.cpp"
>
+
+
+
+
+
+
diff --git a/src/libraries/turtle/check.hpp b/src/libraries/turtle/check.hpp
index 0314036..90ce0ca 100644
--- a/src/libraries/turtle/check.hpp
+++ b/src/libraries/turtle/check.hpp
@@ -10,14 +10,12 @@
#define MOCK_CHECK_HPP_INCLUDED
#include "is_functor.hpp"
+#include "is_comparable.hpp"
#include "constraints.hpp"
#include "operators.hpp"
#include "format.hpp"
-#include
#include
#include
-#include
-#include
namespace mock
{
@@ -30,8 +28,8 @@ namespace detail
BOOST_CONCEPT_USAGE( FunctorCompatible )
{
boost::require_boolean_expr(
- // if an error is generated by the line below it means an argument
- // passed to 'with' was of the wrong type.
+ // if an error is generated by the line below it means
+ // an argument passed to 'with' was of the wrong type.
functor_accepts( actual_argument_type )
);
}
@@ -48,8 +46,8 @@ namespace detail
BOOST_CONCEPT_USAGE( EqualityComparable )
{
boost::require_boolean_expr(
- // if an error is generated by the line below it means an argument
- // passed to 'with' was of the wrong type.
+ // if an error is generated by the line below it means
+ // an argument passed to 'with' was of the wrong type.
actual_argument_type == expected_argument_type
);
}
@@ -60,56 +58,96 @@ namespace detail
};
template< typename Actual >
- class check
+ class check_base : boost::noncopyable
{
public:
- template< typename Functor >
- explicit check( const Functor& f,
- BOOST_DEDUCED_TYPENAME boost::enable_if<
- BOOST_DEDUCED_TYPENAME detail::is_functor< Functor >
- >::type* = 0 )
- : desc_( mock::format( f ) )
+ virtual ~check_base() {}
+
+ virtual bool operator()( Actual ) const = 0;
+
+ friend std::ostream& operator<<( std::ostream& s, const check_base& c )
{
- BOOST_CONCEPT_ASSERT(( FunctorCompatible< Functor, Actual > ));
- f_ = f;
- if( ! f_ )
- std::invalid_argument( "invalid constraint" );
+ c.format( s );
+ return s;
}
- template< typename Expected >
- explicit check( const Expected& expected,
- BOOST_DEDUCED_TYPENAME boost::disable_if<
- BOOST_DEDUCED_TYPENAME detail::is_functor< Expected >
- >::type* = 0 )
- : desc_( mock::format( expected ) )
+ private:
+ virtual void format( std::ostream& ) const = 0;
+ };
+
+ template< typename Actual, typename Expected, typename Enable = void >
+ class check : public check_base< Actual >
+ {
+ public:
+ explicit check( Expected expected )
+ : expected_( expected )
{
BOOST_CONCEPT_ASSERT(( EqualityComparable< Expected, Actual > ));
- f_ = mock::equal( expected ).f_;
- if( ! f_ )
- std::invalid_argument( "invalid constraint" );
}
- template< typename Functor >
- explicit check( const constraint< Functor >& ph )
- : desc_( mock::format( ph.f_ ) )
+ private:
+ virtual bool operator()( Actual actual ) const
+ {
+ return actual == expected_;
+ }
+ virtual void format( std::ostream& s ) const
+ {
+ s << mock::format( expected_ );
+ }
+ private:
+ Expected expected_;
+ };
+
+ template< typename Actual, typename Constraint >
+ class check< Actual, mock::constraint< Constraint > >
+ : public check_base< Actual >
+ {
+ public:
+ explicit check( const constraint< Constraint >& c )
+ : c_( c.f_ )
+ {
+ BOOST_CONCEPT_ASSERT(( FunctorCompatible< Constraint, Actual > ));
+ }
+ private:
+ virtual bool operator()( Actual actual ) const
+ {
+ return c_( actual );
+ }
+ virtual void format( std::ostream& s ) const
+ {
+ s << mock::format( c_ );
+ }
+ private:
+ Constraint c_;
+ };
+
+ template< typename Actual, typename Functor >
+ class check< Actual, Functor,
+ BOOST_DEDUCED_TYPENAME boost::enable_if<
+ boost::mpl::or_<
+ detail::is_functor< Functor >,
+ boost::mpl::not_<
+ detail::is_comparable< Actual, Functor >
+ >
+ >
+ >::type
+ > : public check_base< Actual >
+ {
+ public:
+ explicit check( const Functor& f )
+ : f_( f )
{
BOOST_CONCEPT_ASSERT(( FunctorCompatible< Functor, Actual > ));
- f_ = ph.f_;
- if( ! f_ )
- std::invalid_argument( "invalid constraint" );
}
-
- bool operator()( Actual actual ) const
+ private:
+ virtual bool operator()( Actual actual ) const
{
return f_( actual );
}
-
- friend std::ostream& operator<<( std::ostream& s, const check& c )
+ virtual void format( std::ostream& s ) const
{
- return s << c.desc_;
+ s << mock::format( f_ );
}
-
private:
- boost::function< bool( Actual ) > f_;
- std::string desc_;
+ Functor f_;
};
}
}
diff --git a/src/libraries/turtle/constraint.hpp b/src/libraries/turtle/constraint.hpp
index 577f104..3912548 100644
--- a/src/libraries/turtle/constraint.hpp
+++ b/src/libraries/turtle/constraint.hpp
@@ -19,6 +19,8 @@ namespace mock
{}
Constraint f_;
};
+ template< typename T, typename Constraint >
+ bool operator==( const T&, const constraint< Constraint >& );
}
#endif // #ifndef MOCK_CONSTRAINT_HPP_INCLUDED
diff --git a/src/libraries/turtle/error.hpp b/src/libraries/turtle/error.hpp
index 8f145fa..7c9c4fa 100644
--- a/src/libraries/turtle/error.hpp
+++ b/src/libraries/turtle/error.hpp
@@ -37,27 +37,27 @@ namespace mock
throw boost::enable_current_exception( exception() );
}
+ template< typename Context >
static void fail(
- const std::string& message, const std::string& context,
+ const std::string& message, const Context& context,
const std::string& file = "unknown location", int line = 0 )
{
boost::unit_test::framework::assertion_result( false );
boost::unit_test::unit_test_log
<< boost::unit_test::log::begin( file, (std::size_t)line )
<< boost::unit_test::log_all_errors
- << boost::unit_test::lazy_ostream::instance()
<< message << ": " << context
<< boost::unit_test::log::end();
}
- static void expected_call( const std::string& context,
+ template< typename Context >
+ static void expected_call( const Context& context,
const std::string& file, int line )
{
boost::unit_test::framework::assertion_result( true );
boost::unit_test::unit_test_log
<< boost::unit_test::log::begin( file, (std::size_t)line )
<< boost::unit_test::log_successful_tests
- << boost::unit_test::lazy_ostream::instance()
<< "mock expectation fulfilled: " << context
<< boost::unit_test::log::end();
}
@@ -75,40 +75,47 @@ namespace mock
throw exception();
}
+ template< typename Context >
static void fail(
- const std::string& message, const std::string& context,
+ const std::string& message, const Context& context,
const std::string& file = "unknown location", int line = 0 )
{
std::cerr << file << '(' << line << "): "
<< message << ": " << context << std::endl;
}
- static void expected_call( const std::string& /*context*/,
+ template< typename Context >
+ static void expected_call( const Context& /*context*/,
const std::string& /*file*/, int /*line*/ )
{}
#endif // MOCK_USE_BOOST_TEST
- static void missing_action( const std::string& context,
+ template< typename Context >
+ static void missing_action( const Context& context,
const std::string& file, int line )
{
fail( "missing action", context, file, line );
}
- static void unexpected_call( const std::string& context )
+ template< typename Context >
+ static void unexpected_call( const Context& context )
{
fail( "unexpected call", context );
}
- static void sequence_failed( const std::string& context,
+ template< typename Context >
+ static void sequence_failed( const Context& context,
const std::string& /*file*/, int /*line*/ )
{
fail( "sequence failed", context );
}
- static void verification_failed( const std::string& context,
+ template< typename Context >
+ static void verification_failed( const Context& context,
const std::string& file, int line )
{
fail( "verification failed", context, file, line );
}
- static void untriggered_expectation( const std::string& context,
+ template< typename Context >
+ static void untriggered_expectation( const Context& context,
const std::string& file, int line )
{
fail( "untriggered expectation", context, file, line );
diff --git a/src/libraries/turtle/expectation.hpp b/src/libraries/turtle/expectation.hpp
index 4c2aa62..96afbae 100644
--- a/src/libraries/turtle/expectation.hpp
+++ b/src/libraries/turtle/expectation.hpp
@@ -172,14 +172,13 @@ namespace detail
BOOST_DEDUCED_TYPENAME \
boost::function_types::parameter_types< Signature >, \
n \
- >::type arg##n##_type; \
- typedef detail::check< arg##n##_type > constraint##n##_type;
-#define MOCK_EXPECTATION_CONSTRUCTOR(z, n, d) BOOST_PP_COMMA_IF(n) c##n##_( mock::any )
-#define MOCK_EXPECTATION_WITH(z, n, d) c##n##_ = constraint##n##_type( c##n );
-#define MOCK_EXPECTATION_MEMBER(z, n, d) constraint##n##_type c##n##_;
+ >::type arg##n##_type;
+#define MOCK_EXPECTATION_CONSTRUCTOR(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_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 > \
@@ -193,7 +192,7 @@ namespace detail
: BOOST_PP_REPEAT_FROM_TO(0, n, MOCK_EXPECTATION_CONSTRUCTOR, BOOST_PP_EMPTY) \
{} \
template< BOOST_PP_ENUM_PARAMS(n, typename Constraint) > \
- expectation& with( BOOST_PP_ENUM_BINARY_PARAMS(n, const Constraint, & c) ) \
+ expectation& with( BOOST_PP_ENUM_BINARY_PARAMS(n, Constraint, c) ) \
{ \
BOOST_PP_REPEAT_FROM_TO(0, n, MOCK_EXPECTATION_WITH, BOOST_PP_EMPTY) \
return *this; \
diff --git a/src/libraries/turtle/format.hpp b/src/libraries/turtle/format.hpp
index 3c6eb75..d73f952 100644
--- a/src/libraries/turtle/format.hpp
+++ b/src/libraries/turtle/format.hpp
@@ -9,122 +9,127 @@
#ifndef MOCK_FORMAT_HPP_INCLUDED
#define MOCK_FORMAT_HPP_INCLUDED
-#include
+#include "is_serializable.hpp"
+#include "is_formattable.hpp"
+#include
#include
-#include
-#ifndef MOCK_NO_STL_FORMAT
-#include
-#endif // MOCK_NO_STL_FORMAT
-#include
+#include
#include
+#include
namespace mock
{
+ template< typename T >
+ class formatter
+ {
+ public:
+ explicit formatter( const T& t )
+ : t_( &t )
+ {}
+ const T& operator*() const
+ {
+ return *t_;
+ }
+ const T* operator->() const
+ {
+ return t_;
+ }
+ private:
+ const T* t_;
+ };
+
namespace detail
{
template< typename T >
- std::string serialize( const T& t,
+ void serialize( std::ostream& s, const T& t,
BOOST_DEDUCED_TYPENAME boost::enable_if<
- BOOST_DEDUCED_TYPENAME boost::is_output_streamable< T > >::type* = 0 )
+ BOOST_DEDUCED_TYPENAME protect::is_serializable< std::ostream, T > >::type* = 0 )
{
- std::stringstream s;
- s << std::boolalpha << t;
- return s.str();
+ s << t;
}
template< typename T >
- std::string serialize( const T&,
+ void serialize( std::ostream& s, const T&,
BOOST_DEDUCED_TYPENAME boost::disable_if<
- BOOST_DEDUCED_TYPENAME boost::is_output_streamable< T > >::type* = 0 )
+ BOOST_DEDUCED_TYPENAME protect::is_serializable< std::ostream, T > >::type* = 0 )
{
- return "?";
+ s << "?";
}
}
template< typename T >
- std::string format( const T& t )
+ BOOST_DEDUCED_TYPENAME boost::enable_if<
+ BOOST_DEDUCED_TYPENAME mock::detail::is_formattable< std::ostream, T >,
+ std::ostream&
+ >::type
+ operator<<( std::ostream& s, const formatter< T >& f )
{
- return detail::serialize( t );
- }
-
- inline std::string format( const char* s )
- {
- return '"' + std::string( s ) + '"';
- }
-
-#ifndef MOCK_NO_STL_FORMAT
- inline std::string format( const std::string& s )
- {
- return '"' + s + '"';
- }
- template< typename T1, typename T2 >
- inline std::string format( const std::pair< T1, T2 >& p )
- {
- return '(' + mock::format( p.first ) + ',' + mock::format( p.second ) + ')';
+ format( s, *f );
+ return s;
}
template< typename T >
- std::string format( const T& begin, const T& end )
+ BOOST_DEDUCED_TYPENAME boost::disable_if<
+ BOOST_DEDUCED_TYPENAME mock::detail::is_formattable< std::ostream, T >,
+ std::ostream&
+ >::type
+ operator<<( std::ostream& s, const formatter< T >& f )
+ {
+ mock::detail::serialize( s, *f );
+ return s;
+ }
+
+ inline std::ostream& operator<<( std::ostream& s, const formatter< bool >& f )
+ {
+ return s << std::boolalpha << *f;
+ }
+ inline std::ostream& operator<<( std::ostream& s, const formatter< std::string >& f )
+ {
+ return s << '"' << *f << '"';
+ }
+ inline std::ostream& operator<<( std::ostream& s, const formatter< const char* >& f )
+ {
+ return s << '"' << *f << '"';
+ }
+
+ template< typename T >
+ formatter< T > format( const T& t )
+ {
+ return formatter< T >( t );
+ }
+
+ template< typename Container >
+ void format( std::ostream& s, const Container& c,
+ BOOST_DEDUCED_TYPENAME Container::const_iterator* = 0 )
{
- std::stringstream s;
s << '(';
- for( T it = begin; it != end; ++it )
- s << (it == begin ? "" : ",") << mock::format( *it );
+ // if an error is generated by the line below it means Container is
+ // being mismatched for a container because it has a typedef
+ // const_iterator : the easiest solution would be to add a format
+ // function for Container as well.
+ for( BOOST_DEDUCED_TYPENAME Container::const_iterator it = c.begin();
+ it != c.end(); ++it )
+ {
+ if( it != c.begin() )
+ s << ',';
+ s << mock::format( *it );
+ }
s << ')';
- return s.str();
}
- template< typename T, typename A >
- std::string format( const std::deque< T, A >& d )
- {
- return format( d.begin(), d.end() );
- }
- template< typename T, typename A >
- std::string format( const std::list< T, A >& l )
- {
- return format( l.begin(), l.end() );
- }
- template< typename T, typename A >
- std::string format( const std::vector< T, A >& v )
- {
- return format( v.begin(), v.end() );
- }
- template< typename K, typename T, typename C, typename A >
- std::string format( const std::map< K, T, C, A >& m )
- {
- return format( m.begin(), m.end() );
- }
- template< typename K, typename T, typename C, typename A >
- std::string format( const std::multimap< K, T, C, A >& m )
- {
- return format( m.begin(), m.end() );
- }
- template< typename T, typename C, typename A >
- std::string format( const std::set< T, C, A >& s )
- {
- return format( s.begin(), s.end() );
- }
- template< typename T, typename C, typename A >
- std::string format( const std::multiset< T, C, A >& s )
- {
- return format( s.begin(), s.end() );
- }
-#endif // MOCK_NO_STL_FORMAT
-}
-#ifndef MOCK_NO_BOOST_FORMAT
-namespace boost
-{
-namespace assign_detail
-{
- template< typename T > class generic_list;
-}
-}
-namespace mock
-{
- template< typename T >
- std::string format( const boost::assign_detail::generic_list< T >& l )
+ template< typename T1, typename T2 >
+ void format( std::ostream& s, const std::pair< T1, T2 >& p )
{
- return format( l.begin(), l.end() );
+ s << '(' << mock::format( p.first )
+ << ',' << mock::format( p.second ) << ')';
+ }
+
+ template< typename T >
+ void format( std::ostream& s, T,
+ BOOST_DEDUCED_TYPENAME boost::enable_if<
+ BOOST_DEDUCED_TYPENAME
+ boost::function_types::is_callable_builtin< T > >::type* = 0 )
+ {
+ s << '?';
}
}
-#endif // MOCK_NO_BOOST_FORMAT
#endif // #ifndef MOCK_FORMAT_HPP_INCLUDED
diff --git a/src/libraries/turtle/function.hpp b/src/libraries/turtle/function.hpp
index 5c151ab..11264d2 100644
--- a/src/libraries/turtle/function.hpp
+++ b/src/libraries/turtle/function.hpp
@@ -21,6 +21,8 @@
#include
#include
#include
+#include
+#include
#include
#include
#include
@@ -132,13 +134,45 @@ namespace mock
{
if( ! it->verify() )
ErrorPolicy::untriggered_expectation(
- context(), it->file(), it->line() );
+ boost::unit_test::lazy_ostream::instance()
+ << lazy_context( this )
+ << lazy_expectations( this ),
+ it->file(), it->line() );
else if( ! it->invoked() )
ErrorPolicy::expected_call(
- context(), it->file(), it->line() );
+ boost::unit_test::lazy_ostream::instance()
+ << lazy_context( this )
+ << lazy_expectations( this ),
+ it->file(), it->line() );
}
}
+ virtual bool verify() const
+ {
+ for( expectations_cit it = expectations_.begin();
+ it != expectations_.end(); ++it )
+ if( !it->verify() )
+ {
+ valid_ = false;
+ ErrorPolicy::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;
+ expectations_.clear();
+ }
+ virtual void untie()
+ {
+ parent_ = 0;
+ }
+
void tag( const std::string& name )
{
name_ = name;
@@ -155,28 +189,6 @@ namespace mock
parent_ = &parent;
}
- virtual bool verify() const
- {
- for( expectations_cit it = expectations_.begin();
- it != expectations_.end(); ++it )
- if( !it->verify() )
- {
- valid_ = false;
- ErrorPolicy::verification_failed( context(),
- it->file(), it->line() );
- }
- return valid_;
- }
- virtual void reset()
- {
- valid_ = true;
- expectations_.clear();
- }
- virtual void untie()
- {
- parent_ = 0;
- }
-
expectation_type& expect( const std::string& file, int line )
{
expectation_type& e = expect();
@@ -192,26 +204,14 @@ namespace mock
return expectations_.back();
}
- struct no_throw_abort
- {
- static void abort() {}
- };
- void test() const
- {
- invoke< no_throw_abort >();
- }
-
- result_type operator()() const
- {
- return invoke< ErrorPolicy >();
- }
-
-#define MOCK_EXPECTATION_FORMAT(z, n, d) \
- BOOST_PP_IF(n, + ", " +,) mock::format( p##n )
-#define MOCK_EXPECTATION_CONTEXT(n) \
- context( BOOST_PP_REPEAT_FROM_TO(0, n, MOCK_EXPECTATION_FORMAT, BOOST_PP_EMPTY) )
-#define MOCK_EXPECTATION_OPERATOR(z, n, d) \
- MOCK_DECL(operator(), n, Signature, const, BOOST_DEDUCED_TYPENAME) \
+#define MOCK_EXPECTATION_FORMAT(z, n, N) \
+ << " " << mock::format( p##n ) << BOOST_PP_IF(BOOST_PP_EQUAL(N,n), " ", ",")
+#define MOCK_EXPECTATION_CALL_CONTEXT(n) \
+ boost::unit_test::lazy_ostream::instance() \
+ << lazy_context( this ) \
+ << "(" BOOST_PP_REPEAT_FROM_TO(0, n, MOCK_EXPECTATION_FORMAT, BOOST_PP_DEC(n)) << ")" \
+ << lazy_expectations( this )
+#define MOCK_EXPECTATION_INVOKE(z, n, A) \
{ \
for( expectations_cit it = expectations_.begin(); it != expectations_.end(); ++it ) \
if( it->is_valid( BOOST_PP_ENUM_PARAMS(n, p) ) ) \
@@ -219,96 +219,77 @@ namespace mock
if( ! it->invoke() ) \
{ \
valid_ = false; \
- ErrorPolicy::sequence_failed( MOCK_EXPECTATION_CONTEXT(n), it->file(), it->line() ); \
- return ErrorPolicy::abort(); \
+ ErrorPolicy::sequence_failed( MOCK_EXPECTATION_CALL_CONTEXT(n), it->file(), it->line() ); \
+ return A; \
} \
if( ! it->functor() ) \
{ \
- ErrorPolicy::missing_action( MOCK_EXPECTATION_CONTEXT(n), it->file(), it->line() ); \
- return ErrorPolicy::abort(); \
+ ErrorPolicy::missing_action( MOCK_EXPECTATION_CALL_CONTEXT(n), it->file(), it->line() ); \
+ return A; \
} \
- ErrorPolicy::expected_call( MOCK_EXPECTATION_CONTEXT(n), it->file(), it->line() ); \
+ ErrorPolicy::expected_call( MOCK_EXPECTATION_CALL_CONTEXT(n), it->file(), it->line() ); \
return it->functor()( BOOST_PP_ENUM_PARAMS(n, p) ); \
} \
valid_ = false; \
- ErrorPolicy::unexpected_call( MOCK_EXPECTATION_CONTEXT(n) ); \
- return ErrorPolicy::abort(); \
+ ErrorPolicy::unexpected_call( MOCK_EXPECTATION_CALL_CONTEXT(n) ); \
+ return A; \
}
- BOOST_PP_REPEAT_FROM_TO(1, MOCK_NUM_ARGS, MOCK_EXPECTATION_OPERATOR, BOOST_PP_EMPTY)
-#undef MOCK_EXPECTATION_CONTEXT
+#define MOCK_EXPECTATION_OPERATOR(z, n, P) \
+ MOCK_DECL(operator(), n, Signature, const, BOOST_DEDUCED_TYPENAME) \
+ MOCK_EXPECTATION_INVOKE(z, n, P)
+
+ BOOST_PP_REPEAT_FROM_TO(0, MOCK_NUM_ARGS, MOCK_EXPECTATION_OPERATOR, ErrorPolicy::abort())
+
+ void test() const
+ MOCK_EXPECTATION_INVOKE(, 0,)
+
#undef MOCK_EXPECTATION_FORMAT
#undef MOCK_EXPECTATION_OPERATOR
+#undef MOCK_EXPECTATION_INVOKE
+#undef MOCK_EXPECTATION_CALL_CONTEXT
friend std::ostream& operator<<( std::ostream& s, const function_impl& e )
{
- return s << e.context();
+ return s << lazy_context( &e ) << lazy_expectations( &e );
}
- private:
- template< typename T >
- result_type invoke() const
+ struct lazy_context
{
- for( expectations_cit it = expectations_.begin();
- it != expectations_.end(); ++it )
- if( it->is_valid() )
- {
- if( ! it->invoke() )
- {
- valid_ = false;
- ErrorPolicy::sequence_failed( context( "" ),
- it->file(), it->line() );
- return T::abort();
- }
- if( ! it->functor() )
- {
- ErrorPolicy::missing_action( context( "" ),
- it->file(), it->line() );
- return T::abort();
- }
- ErrorPolicy::expected_call( context( "" ),
- it->file(), it->line() );
- return it->functor()();
- }
- valid_ = false;
- ErrorPolicy::unexpected_call( context( "" ) );
- return T::abort();
- }
+ lazy_context( const function_impl* impl )
+ : impl_( impl )
+ {}
+ friend std::ostream& operator<<( std::ostream& s, const lazy_context& e )
+ {
+ if( e.impl_->parent_ )
+ s << e.impl_->parent_->tag();
+ return s << e.impl_->name_;
+ }
+ 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_;
+ };
- private:
typedef std::list< expectation_type > expectations_type;
typedef BOOST_DEDUCED_TYPENAME
expectations_type::const_iterator expectations_cit;
- std::string context() const
- {
- std::stringstream s;
- serialize( s, "" );
- return s.str();
- }
- std::string context( const std::string& parameters ) const
- {
- std::stringstream s;
- if( parameters.empty() )
- serialize( s, "()" );
- else
- serialize( s, "( " + parameters + " )" );
- return s.str();
- }
- void serialize( std::ostream& s,
- const std::string& parameters ) const
- {
- if( parent_ )
- s << parent_->tag();
- s << name_ << parameters;
- for( expectations_cit it = expectations_.begin();
- it != expectations_.end(); ++it )
- s << std::endl << *it;
- }
-
+ expectations_type expectations_;
std::string name_;
node* parent_;
mutable bool valid_;
- expectations_type expectations_;
};
private:
diff --git a/src/libraries/turtle/is_comparable.hpp b/src/libraries/turtle/is_comparable.hpp
new file mode 100644
index 0000000..24348cc
--- /dev/null
+++ b/src/libraries/turtle/is_comparable.hpp
@@ -0,0 +1,50 @@
+//
+// Copyright Mathieu Champlon 2011
+//
+// 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_IS_COMPARABLE_HPP_INCLUDED
+#define MOCK_IS_COMPARABLE_HPP_INCLUDED
+
+#include "yes_no_type.hpp"
+#include "sink.hpp"
+#include
+#include
+#include
+
+#ifdef _MSC_VER
+#pragma warning( push )
+#pragma warning( disable: 4913 )
+#endif
+
+namespace mock
+{
+namespace detail
+{
+namespace comparable
+{
+ yes_type operator==( sink, sink );
+
+ template< typename L, typename R >
+ struct impl
+ {
+ static BOOST_DEDUCED_TYPENAME boost::remove_reference< L >::type* l;
+ static BOOST_DEDUCED_TYPENAME boost::remove_reference< R >::type* r;
+ enum { value = sizeof( yes_type(), *l == *r, yes_type() ) == sizeof( yes_type ) };
+ };
+}
+
+ template< typename L, typename R >
+ struct is_comparable : boost::mpl::bool_< comparable::impl< L, R >::value >
+ {};
+}
+}
+
+#ifdef _MSC_VER
+#pragma warning( pop )
+#endif
+
+#endif // #ifndef MOCK_IS_COMPARABLE_HPP_INCLUDED
diff --git a/src/libraries/turtle/is_formattable.hpp b/src/libraries/turtle/is_formattable.hpp
new file mode 100644
index 0000000..78162ac
--- /dev/null
+++ b/src/libraries/turtle/is_formattable.hpp
@@ -0,0 +1,44 @@
+//
+// Copyright Mathieu Champlon 2011
+//
+// 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_IS_FORMATABLE_HPP_INCLUDED
+#define MOCK_IS_FORMATABLE_HPP_INCLUDED
+
+#include "yes_no_type.hpp"
+#include "sink.hpp"
+
+#ifdef _MSC_VER
+#pragma warning( push )
+#pragma warning( disable: 4913 )
+#endif
+
+namespace mock
+{
+ template< typename S >
+ detail::yes_type format( S&, detail::sink );
+
+namespace detail
+{
+ template< typename S, typename T >
+ struct is_formattable
+ {
+ static S* s;
+ static T* t;
+ // if an error is generated by the line below it means T has more than
+ // one conversion to other types which are formattable : the easiest
+ // solution would be to add a format function for T as well.
+ enum { value = sizeof( yes_type(), format( *s, *t ), yes_type() ) == sizeof( yes_type ) };
+ };
+}
+}
+
+#ifdef _MSC_VER
+#pragma warning( pop )
+#endif
+
+#endif // #ifndef MOCK_IS_FORMATABLE_HPP_INCLUDED
diff --git a/src/libraries/turtle/is_functor.hpp b/src/libraries/turtle/is_functor.hpp
index e7e8296..e8d1d42 100644
--- a/src/libraries/turtle/is_functor.hpp
+++ b/src/libraries/turtle/is_functor.hpp
@@ -9,6 +9,7 @@
#ifndef MOCK_IS_FUNCTOR_HPP_INCLUDED
#define MOCK_IS_FUNCTOR_HPP_INCLUDED
+#include "yes_no_type.hpp"
#include
#include
#include
@@ -18,9 +19,6 @@ namespace mock
{
namespace detail
{
- typedef boost::type_traits::yes_type yes_type;
- typedef boost::type_traits::no_type no_type;
-
#define MOCK_IS_FUNCTION_HELPER(N, M) \
template< typename T > yes_type& N##_helper( BOOST_DEDUCED_TYPENAME T::M* ); \
template< typename T > no_type& N##_helper( ... ); \
diff --git a/src/libraries/turtle/is_serializable.hpp b/src/libraries/turtle/is_serializable.hpp
new file mode 100644
index 0000000..73dd874
--- /dev/null
+++ b/src/libraries/turtle/is_serializable.hpp
@@ -0,0 +1,47 @@
+//
+// Copyright Mathieu Champlon 2011
+//
+// 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_IS_SERIALIZABLE_HPP_INCLUDED
+#define MOCK_IS_SERIALIZABLE_HPP_INCLUDED
+
+#include "yes_no_type.hpp"
+#include "sink.hpp"
+
+#ifdef _MSC_VER
+#pragma warning( push )
+#pragma warning( disable: 4913 )
+#endif
+
+namespace mock
+{
+namespace detail
+{
+namespace protect
+{
+ template< typename S >
+ yes_type operator<<( S&, sink );
+
+ template< typename S, typename T >
+ struct is_serializable
+ {
+ static S* s;
+ static T* t;
+ // if an error is generated by the line below it means T has more than
+ // one conversion to other types which are serializable : the easiest
+ // solution would be to add a format function for T.
+ enum { value = sizeof( yes_type(), (*s << *t), yes_type() ) == sizeof( yes_type ) };
+ };
+}
+}
+}
+
+#ifdef _MSC_VER
+#pragma warning( pop )
+#endif
+
+#endif // #ifndef MOCK_IS_SERIALIZABLE_HPP_INCLUDED
diff --git a/src/libraries/turtle/lambda.hpp b/src/libraries/turtle/lambda.hpp
index 9c17844..01019c0 100644
--- a/src/libraries/turtle/lambda.hpp
+++ b/src/libraries/turtle/lambda.hpp
@@ -69,8 +69,7 @@ namespace detail
throw t;
}
static void do_nothing()
- {
- }
+ {}
};
}
}
diff --git a/src/libraries/turtle/object.hpp b/src/libraries/turtle/object.hpp
index 37294d8..548019a 100644
--- a/src/libraries/turtle/object.hpp
+++ b/src/libraries/turtle/object.hpp
@@ -12,7 +12,6 @@
#include "node.hpp"
#include "root.hpp"
#include
-#include
#include
namespace mock
diff --git a/src/libraries/turtle/operators.hpp b/src/libraries/turtle/operators.hpp
index 562c306..12ded04 100644
--- a/src/libraries/turtle/operators.hpp
+++ b/src/libraries/turtle/operators.hpp
@@ -10,60 +10,63 @@
#define MOCK_OPERATORS_HPP_INCLUDED
#include "constraint.hpp"
+#include "format.hpp"
namespace mock
{
namespace detail
{
- template< typename Functor1, typename Functor2 >
+ template< typename Constraint1, typename Constraint2 >
class and_
{
public:
- and_( const Functor1& f1, const Functor2& f2 )
- : f1_( f1 )
- , f2_( f2 )
+ and_( const Constraint1& c1, const Constraint2& c2 )
+ : c1_( c1 )
+ , c2_( c2 )
{}
template< typename Actual >
bool operator()( const Actual& actual ) const
{
- return f1_( actual ) && f2_( actual );
+ return c1_( actual ) && c2_( actual );
}
friend std::ostream& operator<<( std::ostream& s, const and_& a )
{
- return s << "( " << a.f1_ << " && " << a.f2_ << " )";
+ return s << "( " << mock::format( a.c1_ )
+ << " && " << mock::format( a.c2_ ) << " )";
}
private:
- Functor1 f1_;
- Functor2 f2_;
+ Constraint1 c1_;
+ Constraint2 c2_;
};
- template< typename Functor1, typename Functor2 >
+ template< typename Constraint1, typename Constraint2 >
class or_
{
public:
- or_( const Functor1& f1, const Functor2& f2 )
- : f1_( f1 )
- , f2_( f2 )
+ or_( const Constraint1& c1, const Constraint2& c2 )
+ : c1_( c1 )
+ , c2_( c2 )
{}
template< typename Actual >
bool operator()( const Actual& actual ) const
{
- return f1_( actual ) || f2_( actual );
+ return c1_( actual ) || c2_( actual );
}
friend std::ostream& operator<<( std::ostream& s, const or_& o )
{
- return s << "( " << o.f1_ << " || " << o.f2_ << " )";
+ return s << "( " << mock::format( o.c1_ )
+ << " || " << mock::format( o.c2_ )<< " )";
}
private:
- Functor1 f1_;
- Functor2 f2_;
+ Constraint1 c1_;
+ Constraint2 c2_;
};
- template< typename Functor >
+ template< typename Constraint >
class not_
{
public:
- explicit not_( const Functor& f )
+ explicit not_( const Constraint& f )
: f_( f )
{}
template< typename Actual >
@@ -73,34 +76,34 @@ namespace detail
}
friend std::ostream& operator<<( std::ostream& s, const not_& n )
{
- return s << "! " << n.f_;
+ return s << "! " << mock::format( n.f_ );
}
private:
- Functor f_;
+ Constraint f_;
};
}
- template< typename Functor1, typename Functor2 >
- const constraint< detail::or_< Functor1, Functor2 > >
- operator||( const constraint< Functor1 >& lhs,
- const constraint< Functor2 >& rhs )
+ template< typename Constraint1, typename Constraint2 >
+ const constraint< detail::or_< Constraint1, Constraint2 > >
+ operator||( const constraint< Constraint1 >& lhs,
+ const constraint< Constraint2 >& rhs )
{
- return detail::or_< Functor1, Functor2 >( lhs.f_, rhs.f_ );
+ return detail::or_< Constraint1, Constraint2 >( lhs.f_, rhs.f_ );
}
- template< typename Functor1, typename Functor2 >
- const constraint< detail::and_< Functor1, Functor2 > >
- operator&&( const constraint< Functor1 >& lhs,
- const constraint< Functor2 >& rhs )
+ template< typename Constraint1, typename Constraint2 >
+ const constraint< detail::and_< Constraint1, Constraint2 > >
+ operator&&( const constraint< Constraint1 >& lhs,
+ const constraint< Constraint2 >& rhs )
{
- return detail::and_< Functor1, Functor2 >( lhs.f_, rhs.f_ );
+ return detail::and_< Constraint1, Constraint2 >( lhs.f_, rhs.f_ );
}
- template< typename Functor >
- const constraint< detail::not_< Functor > >
- operator!( const constraint< Functor >& c )
+ template< typename Constraint >
+ const constraint< detail::not_< Constraint > >
+ operator!( const constraint< Constraint >& c )
{
- return detail::not_< Functor >( c.f_ );
+ return detail::not_< Constraint >( c.f_ );
}
}
diff --git a/src/libraries/turtle/sink.hpp b/src/libraries/turtle/sink.hpp
new file mode 100644
index 0000000..0002caa
--- /dev/null
+++ b/src/libraries/turtle/sink.hpp
@@ -0,0 +1,24 @@
+//
+// Copyright Mathieu Champlon 2011
+//
+// 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_ANY_HPP_INCLUDED
+#define MOCK_ANY_HPP_INCLUDED
+
+namespace mock
+{
+namespace detail
+{
+ struct sink
+ {
+ template< typename T >
+ sink( const T& );
+ };
+}
+}
+
+#endif // #ifndef MOCK_ANY_HPP_INCLUDED
diff --git a/src/libraries/turtle/yes_no_type.hpp b/src/libraries/turtle/yes_no_type.hpp
new file mode 100644
index 0000000..9ec6063
--- /dev/null
+++ b/src/libraries/turtle/yes_no_type.hpp
@@ -0,0 +1,31 @@
+//
+// Copyright Mathieu Champlon 2011
+//
+// 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_YES_NO_TYPE_HPP_INCLUDED
+#define MOCK_YES_NO_TYPE_HPP_INCLUDED
+
+#include
+
+namespace mock
+{
+namespace detail
+{
+ typedef char no_type;
+ struct yes_type
+ {
+ char no_type[2];
+ };
+ BOOST_STATIC_ASSERT( sizeof( yes_type ) != sizeof( no_type ) );
+
+ template< typename T > void operator,( yes_type, const T& );
+ no_type operator,( yes_type, yes_type );
+ no_type operator,( no_type, yes_type );
+}
+}
+
+#endif // #ifndef MOCK_YES_NO_TYPE_HPP_INCLUDED
diff --git a/src/tests/turtle_test/format_test.cpp b/src/tests/turtle_test/format_test.cpp
index 25ea2ac..4507e72 100644
--- a/src/tests/turtle_test/format_test.cpp
+++ b/src/tests/turtle_test/format_test.cpp
@@ -8,10 +8,9 @@
#include
#include
-#include
+#include
#include
#include
-#include
#include