diff --git a/build/vc80/turtle.vcproj b/build/vc80/turtle.vcproj
index 11b973e..9276e53 100644
--- a/build/vc80/turtle.vcproj
+++ b/build/vc80/turtle.vcproj
@@ -220,6 +220,10 @@
RelativePath="..\..\src\libraries\turtle\sequence.hpp"
>
+
+
diff --git a/build/vc80/turtle_test.vcproj b/build/vc80/turtle_test.vcproj
index 574846f..6816e39 100644
--- a/build/vc80/turtle_test.vcproj
+++ b/build/vc80/turtle_test.vcproj
@@ -204,6 +204,10 @@
RelativePath="..\..\src\tests\turtle_test\format_test.cpp"
>
+
+
@@ -220,18 +224,6 @@
RelativePath="..\..\src\tests\turtle_test\object_test.cpp"
>
-
-
-
-
-
diff --git a/src/libraries/turtle/error.hpp b/src/libraries/turtle/error.hpp
index 374b51d..37bcbf6 100644
--- a/src/libraries/turtle/error.hpp
+++ b/src/libraries/turtle/error.hpp
@@ -9,8 +9,6 @@
#ifndef MOCK_ERROR_HPP_INCLUDED
#define MOCK_ERROR_HPP_INCLUDED
-#include
-#include
#include
#include
#include
@@ -22,13 +20,8 @@ namespace detail
{
class errors_t : public boost::unit_test::singleton< errors_t >
{
- public:
- long count_;
private:
friend class boost::unit_test::singleton< errors_t >;
- errors_t()
- : count_( 0 )
- {}
};
BOOST_TEST_SINGLETON_INST( errors )
}
@@ -46,7 +39,6 @@ namespace detail
{
static void missing_result_specification()
{
- ++detail::errors.count_;
static std::string m;
m = "mock error : missing result specification";
throw boost::enable_current_exception( mock::exception( m ) );
@@ -54,7 +46,6 @@ namespace detail
static Result no_match( const std::string& context )
{
- ++detail::errors.count_;
static std::string m;
m = "mock error : unexpected call : " + context;
throw boost::enable_current_exception( mock::exception( m ) );
@@ -63,7 +54,6 @@ namespace detail
static void sequence_failed( const std::string& context,
const std::string& /*file*/, int /*line*/ )
{
- ++detail::errors.count_;
static std::string m;
m = "mock error : sequence failed : " + context;
throw boost::enable_current_exception( mock::exception( m ) );
@@ -78,8 +68,7 @@ namespace detail
static void untriggered_expectation( const std::string& context,
const std::string& file, int line )
{
- if( detail::errors.count_ == 0 )
- notify( "untriggered expectation : " + context, file, line );
+ notify( "untriggered expectation : " + context, file, line );
}
static void notify( const std::string& message,
diff --git a/src/libraries/turtle/expectation.hpp b/src/libraries/turtle/expectation.hpp
index c3937a5..837cdae 100644
--- a/src/libraries/turtle/expectation.hpp
+++ b/src/libraries/turtle/expectation.hpp
@@ -46,25 +46,24 @@ namespace mock
matcher_type;
public:
- expectation( node& parent = root, const std::string& name = "?" )
- : impl_( new expectation_impl( parent, name ) )
- {}
- expectation( const std::string& name )
+ struct expectation_tag
+ {};
+ expectation_tag operator_exp;
+
+ expectation( const std::string& name = "?" )
: impl_( new expectation_impl( root, name ) )
{}
- expectation& set_name( const std::string& name )
+ void set_name( const std::string& name )
{
impl_->set_name( name );
- return *this;
}
- expectation& set_parent( node& parent )
+ void set_parent( node& parent )
{
impl_->set_parent( parent );
- return *this;
}
- bool verify()
+ bool verify() const
{
return impl_->verify();
}
@@ -134,7 +133,7 @@ namespace mock
parent_ = &parent;
}
- virtual bool verify()
+ virtual bool verify() const
{
for( matchers_cit it = matchers_.begin();
it != matchers_.end(); ++it )
@@ -231,14 +230,14 @@ namespace mock
std::string context() const
{
std::stringstream s;
- s << *parent_ << name_;
+ s << name_;
serialize( s );
return s.str();
}
std::string context( const std::string& parameters ) const
{
std::stringstream s;
- s << *parent_ << name_;
+ s << name_;
if( parameters.empty() )
s << "()";
else
diff --git a/src/libraries/turtle/mock.hpp b/src/libraries/turtle/mock.hpp
index e2b474c..1fc9091 100644
--- a/src/libraries/turtle/mock.hpp
+++ b/src/libraries/turtle/mock.hpp
@@ -12,6 +12,7 @@
#include "error.hpp"
#include "object.hpp"
#include "expectation.hpp"
+#include "type_name.hpp"
#include
#include
#include
@@ -60,36 +61,7 @@ namespace detail
throw std::invalid_argument( "derefencing null pointer" );
return *t;
}
-}
-}
-#define MOCK_MIXIN(T) \
- template< typename U > struct T##_mock_mixin : U \
- { \
- explicit T##_mock_mixin( const std::string& tag = "" ) \
- { \
- mock::object::set_name( BOOST_PP_STRINGIZE(T) + tag ); \
- } \
- explicit T##_mock_mixin( mock::node& parent, const std::string& tag = "" ) \
- { \
- mock::object::set_name( BOOST_PP_STRINGIZE(T) + tag ); \
- mock::node::set_parent( parent ); \
- } \
- }; \
- struct T##_super_class; \
- typedef T##_mock_mixin< T##_super_class > T;
-#define MOCK_BASE_CLASS(T, I) \
- MOCK_MIXIN(T) \
- struct T##_typedef { typedef I interface_type; }; \
- struct T##_super_class : I, mock::object, private T##_typedef
-#define MOCK_CLASS(T) \
- MOCK_MIXIN(T) \
- struct T##_super_class : mock::object
-
-namespace mock
-{
-namespace detail
-{
template< typename M >
struct signature
{
@@ -112,45 +84,116 @@ namespace detail
>::type
>::type type;
};
+
+ template< typename E >
+ void set_parent( E& e, const object& o )
+ {
+ o.set_parent( e );
+ }
+ template< typename E, typename T >
+ void set_parent( E&, const T&,
+ BOOST_DEDUCED_TYPENAME boost::disable_if<
+ BOOST_DEDUCED_TYPENAME boost::is_base_of< object, T >::type
+ >::type* = 0 )
+ {}
+ template< typename E >
+ void tag( E& e, const object& o, const std::string& type_name, const std::string& name )
+ {
+ e.set_name( type_name + o.tag() + "::" + name );
+ }
+ template< typename E, typename T >
+ void tag( E& e, const T&, const std::string& type_name, const std::string& name,
+ BOOST_DEDUCED_TYPENAME boost::disable_if<
+ BOOST_DEDUCED_TYPENAME boost::is_base_of< object, T >::type
+ >::type* = 0 )
+ {
+ e.set_name( type_name + "::" + name );
+ }
+
+ template< typename E >
+ E& configure( typename E::expectation_tag, const std::string& name, E& e )
+ {
+ e.set_name( name );
+ return e;
+ }
+ template< typename E, typename T >
+ E& configure( E& e, const std::string& name, const T& t )
+ {
+ set_parent( e, t );
+ tag( e, t, type_name< T >(), name );
+ return e;
+ }
+
+ template< typename T >
+ struct base
+ {
+ typedef T base_type;
+ };
}
}
-#define MOCK_METHOD_ARG(z, n, S) BOOST_PP_COMMA_IF(n) \
- BOOST_PP_CAT(BOOST_PP_CAT(boost::function< S >::arg, BOOST_PP_INC(n)),_type) \
+#define MOCK_BASE_CLASS(T, I) \
+ struct T : I, mock::object, mock::detail::base< I >
+#define MOCK_CLASS(T) \
+ struct T : mock::object
+#define MOCK_FUNCTOR(S) \
+ mock::expectation< S >
+
+#define MOCK_MOCKER(o, t) \
+ mock::detail::configure( mock::detail::ref( o ).t##_exp, \
+ BOOST_PP_STRINGIZE(t), mock::detail::ref( o ) )
+
+#define MOCK_METHOD_ARG(z, n, arg) BOOST_PP_COMMA_IF(n) \
+ BOOST_PP_CAT(BOOST_PP_CAT(arg, BOOST_PP_INC(n)),_type) \
BOOST_PP_CAT(a, BOOST_PP_INC(n))
-#define MOCK_METHOD_ARGS(n, S) \
- BOOST_PP_REPEAT_FROM_TO(0, n, MOCK_METHOD_ARG, S)
+#define MOCK_METHOD_ARGS(n, arg) \
+ BOOST_PP_REPEAT_FROM_TO(0, n, MOCK_METHOD_ARG, arg)
#define MOCK_MOCKER_ARG(z, n, d) \
BOOST_PP_COMMA_IF(n) BOOST_PP_CAT(a, BOOST_PP_INC(n))
-#define MOCK_MOCKER_ARGS(n, M) \
+#define MOCK_MOCKER_ARGS(n) \
BOOST_PP_REPEAT_FROM_TO(0, n, MOCK_MOCKER_ARG, BOOST_PP_EMPTY)
-#define MOCK_METHOD_STUB(M, n, S, t, c) \
- boost::function< S >::result_type M( MOCK_METHOD_ARGS(n, S) ) c \
- { \
- return MOCK_MOCKER(*this, t)( MOCK_MOCKER_ARGS(n, M) ); \
- }
#define MOCK_METHOD_EXPECTATION(S, t) \
mutable mock::expectation< S > t##_exp;
+
+#define MOCK_METHOD_STUB(M, n, S, t, c, tpn) \
+ tpn boost::function< S >::result_type M( \
+ MOCK_METHOD_ARGS(n, tpn boost::function< S >::arg) ) c \
+ { \
+ return MOCK_MOCKER(this, t)( MOCK_MOCKER_ARGS(n) ); \
+ }
+#define MOCK_SIGNATURE(M) \
+ mock::detail::signature< BOOST_TYPEOF(&base_type::M) >::type
+#define MOCK_SIGNATURE_TPL(M) \
+ BOOST_DEDUCED_TYPENAME mock::detail::signature< BOOST_TYPEOF_TPL(&base_type::M) >::type
+
#define MOCK_METHOD_EXT(M, n, S, t) \
- MOCK_METHOD_STUB(M, n, S, t,) \
- MOCK_METHOD_STUB(M, n, S, t, const) \
+ MOCK_METHOD_STUB(M, n, S, t,,) \
+ MOCK_METHOD_STUB(M, n, S, t, const,) \
MOCK_METHOD_EXPECTATION(S, t)
#define MOCK_CONST_METHOD_EXT(M, n, S, t) \
- MOCK_METHOD_STUB(M, n, S, t, const) \
+ MOCK_METHOD_STUB(M, n, S, t, const,) \
MOCK_METHOD_EXPECTATION(S, t)
#define MOCK_NON_CONST_METHOD_EXT(M, n, S, t) \
- MOCK_METHOD_STUB(M, n, S, t,) \
+ MOCK_METHOD_STUB(M, n, S, t,,) \
MOCK_METHOD_EXPECTATION(S, t)
#define MOCK_METHOD(M, n) \
- MOCK_METHOD_EXT(M, n, MOCK_SIGNATURE(&interface_type::M), M)
-#define MOCK_SIGNATURE(pM) \
- mock::detail::signature< BOOST_TYPEOF(pM) >::type
-#define MOCK_MOCKER(m, t) \
- mock::detail::ref( m ).t##_exp.set_name( BOOST_PP_STRINGIZE(t) ).set_parent( \
- const_cast< mock::object& >( dynamic_cast< const mock::object& >( mock::detail::ref( m ) ) ) )
+ MOCK_METHOD_EXT(M, n, MOCK_SIGNATURE(M), M)
-#define MOCK_EXPECT(m,t) MOCK_MOCKER(m,t).expect( __FILE__, __LINE__ )
-#define MOCK_RESET(m,t) MOCK_MOCKER(m,t).reset()
-#define MOCK_VERIFY(m,t) MOCK_MOCKER(m,t).verify()
+#define MOCK_METHOD_EXT_TPL(M, n, S, t) \
+ MOCK_METHOD_STUB(M, n, S, t,,BOOST_DEDUCED_TYPENAME) \
+ MOCK_METHOD_STUB(M, n, S, t, const,BOOST_DEDUCED_TYPENAME) \
+ MOCK_METHOD_EXPECTATION(S, t)
+#define MOCK_CONST_METHOD_EXT_TPL(M, n, S, t) \
+ MOCK_METHOD_STUB(M, n, S, t, const,BOOST_DEDUCED_TYPENAME) \
+ MOCK_METHOD_EXPECTATION(S, t)
+#define MOCK_NON_CONST_METHOD_EXT_TPL(M, n, S, t) \
+ MOCK_METHOD_STUB(M, n, S, t,,BOOST_DEDUCED_TYPENAME) \
+ MOCK_METHOD_EXPECTATION(S, t)
+#define MOCK_METHOD_TPL(M, n) \
+ MOCK_METHOD_EXT_TPL(M, n, MOCK_SIGNATURE_TPL(M), M)
+
+#define MOCK_EXPECT(o,t) MOCK_MOCKER(o,t).expect( __FILE__, __LINE__ )
+#define MOCK_RESET(o,t) MOCK_MOCKER(o,t).reset()
+#define MOCK_VERIFY(o,t) MOCK_MOCKER(o,t).verify()
#endif // #ifndef MOCK_MOCK_HPP_INCLUDED
diff --git a/src/libraries/turtle/node.hpp b/src/libraries/turtle/node.hpp
index 859e613..1d88477 100644
--- a/src/libraries/turtle/node.hpp
+++ b/src/libraries/turtle/node.hpp
@@ -10,41 +10,18 @@
#define MOCK_NODE_HPP_INCLUDED
#include "verifiable.hpp"
-#include
-#include
+#include
#include
-#include
+#include
#include
+#include
+#include
namespace mock
{
- class node : private verifiable
+ class node : private boost::noncopyable
{
public:
- node()
- : parent_( 0 )
- {}
- explicit node( node& parent )
- : verifiable()
- , parent_( &parent )
- {
- if( parent_ )
- parent_->add( *this );
- }
- virtual ~node()
- {
- if( parent_ )
- parent_->remove( *this );
- }
-
- void set_parent( node& parent )
- {
- if( parent_ )
- parent_->remove( *this );
- parent_ = &parent;
- parent_->add( *this );
- }
-
void add( verifiable& e )
{
v_.push_back( &e );
@@ -54,7 +31,7 @@ namespace mock
v_.erase( std::remove( v_.begin(), v_.end(), &e ), v_.end() );
}
- virtual bool verify()
+ bool verify() const
{
bool valid = true;
for( verifiables_cit it = v_.begin(); it != v_.end(); ++it )
@@ -62,7 +39,7 @@ namespace mock
valid = false;
return valid;
}
- virtual void reset()
+ void reset()
{
std::for_each( v_.begin(), v_.end(),
std::mem_fun( &verifiable::reset ) );
@@ -70,20 +47,20 @@ namespace mock
friend std::ostream& operator<<( std::ostream& s, const node& n )
{
- if( n.parent_ )
- s << *n.parent_;
n.serialize( s );
return s;
}
protected:
+ virtual ~node()
+ {}
+
virtual void serialize( std::ostream& s ) const = 0;
private:
typedef std::vector< verifiable* > verifiables_type;
typedef verifiables_type::const_iterator verifiables_cit;
- node* parent_;
std::vector< verifiable* > v_;
};
}
diff --git a/src/libraries/turtle/object.hpp b/src/libraries/turtle/object.hpp
index e180c41..79e4858 100644
--- a/src/libraries/turtle/object.hpp
+++ b/src/libraries/turtle/object.hpp
@@ -11,36 +11,61 @@
#include "node.hpp"
#include "root.hpp"
-#include
+#include
#include
+#include
namespace mock
{
- class object : public node
+ class object
{
public:
- explicit object( node& parent = root, const std::string& name = "" )
- : node( parent )
- , name_( name )
- {}
- explicit object( const std::string& name )
- : node( root )
- , name_( name )
+ explicit object( const std::string& name = "" )
+ : impl_( new object_impl( name ) )
{}
- void set_name( const std::string& name )
+ void tag( const std::string& name )
{
- name_ = name;
+ impl_->name_ = name;
+ }
+ const std::string& tag() const
+ {
+ return impl_->name_;
+ }
+
+ template< typename T >
+ void set_parent( T& t ) const
+ {
+ t.set_parent( *impl_ );
+ }
+
+ bool verify() const
+ {
+ return impl_->verify();
+ }
+ void reset()
+ {
+ impl_->reset();
}
private:
- virtual void serialize( std::ostream& s ) const
+ class object_impl : public node
{
- s << (name_.empty() ? "?" : name_) << "::";
- }
+ public:
+ explicit object_impl( const std::string& name )
+ : name_( name )
+ {}
- private:
- std::string name_;
+ std::string name_;
+
+ private:
+ virtual void serialize( std::ostream& s ) const
+ {
+ s << (name_.empty() ? "?" : name_) << "::";
+ }
+ };
+
+ boost::shared_ptr< object_impl > impl_;
};
}
diff --git a/src/libraries/turtle/type_name.hpp b/src/libraries/turtle/type_name.hpp
new file mode 100644
index 0000000..856afdb
--- /dev/null
+++ b/src/libraries/turtle/type_name.hpp
@@ -0,0 +1,71 @@
+//
+// Copyright Mathieu Champlon 2009
+//
+// 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_TYPE_NAME_HPP_INCLUDED
+#define MOCK_TYPE_NAME_HPP_INCLUDED
+
+#include
+#include
+#ifdef __GNUC__
+#include
+#include
+#endif
+
+namespace mock
+{
+namespace detail
+{
+ struct guard
+ {
+ explicit guard( char* p )
+ : p_( p )
+ {}
+ ~guard()
+ {
+ free( p_ );
+ }
+ private:
+ char* p_;
+ };
+
+ inline std::string type_full_name( const std::type_info& info )
+ {
+ const char* name = info.name();
+#ifdef __GNUC__
+ size_t size = 0;
+ int status = 0;
+ char* result = abi::__cxa_demangle( name, NULL, &size, &status );
+ guard g( result );
+ if( result )
+ return result;
+ else
+ return name;
+#else
+ return name;
+#endif
+ }
+
+ template< typename T >
+ std::string type_full_name()
+ {
+ return type_full_name( typeid( T ) );
+ }
+
+ template< typename T >
+ std::string type_name()
+ {
+ const std::string name = type_full_name< T >();
+ std::size_t p = name.rfind( "::" );
+ if( p != std::string::npos )
+ return name.substr( p + 2 );
+ return "";
+ }
+}
+}
+
+#endif // #ifndef MOCK_TYPE_NAME_HPP_INCLUDED
diff --git a/src/libraries/turtle/verifiable.hpp b/src/libraries/turtle/verifiable.hpp
index 48da575..7069b5d 100644
--- a/src/libraries/turtle/verifiable.hpp
+++ b/src/libraries/turtle/verifiable.hpp
@@ -20,7 +20,7 @@ namespace mock
virtual ~verifiable() {}
// return false if verification fails
- virtual bool verify() = 0;
+ virtual bool verify() const = 0;
// return to the initial state
virtual void reset() = 0;
diff --git a/src/tests/turtle_test/constraint_test.cpp b/src/tests/turtle_test/constraint_test.cpp
index d4fe4f1..e9a64af 100644
--- a/src/tests/turtle_test/constraint_test.cpp
+++ b/src/tests/turtle_test/constraint_test.cpp
@@ -14,9 +14,6 @@
BOOST_AUTO_TEST_CASE( all_comparison_constraints_can_be_instanciated )
{
- mock::any;
- mock::negate;
- mock::evaluate;
mock::equal( 0 );
mock::less( 0 );
mock::greater( 0 );
diff --git a/src/tests/turtle_test/expectation_test.cpp b/src/tests/turtle_test/expectation_test.cpp
index f3c1dcb..f019ea4 100644
--- a/src/tests/turtle_test/expectation_test.cpp
+++ b/src/tests/turtle_test/expectation_test.cpp
@@ -580,6 +580,17 @@ BOOST_AUTO_TEST_CASE( best_matcher_is_selected_first )
// error report
+namespace
+{
+ template< typename T >
+ std::string to_string( const T& t )
+ {
+ std::stringstream s;
+ s << t;
+ return s.str();
+ }
+}
+
BOOST_AUTO_TEST_CASE( expectation_can_be_serialized_to_be_human_readable )
{
{
@@ -587,22 +598,18 @@ BOOST_AUTO_TEST_CASE( expectation_can_be_serialized_to_be_human_readable )
e.expect().once().with( 1 );
e.expect().once().with( 2 );
BOOST_CHECK_NO_THROW( e( 2 ) );
- std::stringstream s;
- s << e;
const std::string expected = "my expectation\n"
". expect( once() ).with( 1 )\n"
"v expect( once() ).with( 2 )";
- BOOST_CHECK_EQUAL( expected, s.str() );
+ BOOST_CHECK_EQUAL( expected, to_string( e ) );
e.reset();
}
{
mock::expectation< void( int ) > e( "my expectation" );
e.expect().never().with( 1 );
- std::stringstream s;
- s << e;
const std::string expected = "my expectation\n"
"v expect( never() ).with( 1 )";
- BOOST_CHECK_EQUAL( expected, s.str() );
+ BOOST_CHECK_EQUAL( expected, to_string( e ) );
e.reset();
}
{
@@ -611,82 +618,66 @@ BOOST_AUTO_TEST_CASE( expectation_can_be_serialized_to_be_human_readable )
e.expect().exactly( 2 ).with( "second" );
BOOST_CHECK_NO_THROW( e( "second" ) );
{
- std::stringstream s;
- s << e;
const std::string expected = "?\n"
"v expect( never() ).with( less( \"first\" ) )\n"
". expect( exactly( 1/2 ) ).with( \"second\" )";
- BOOST_CHECK_EQUAL( expected, s.str() );
+ BOOST_CHECK_EQUAL( expected, to_string( e ) );
}
BOOST_CHECK_NO_THROW( e( "second" ) );
{
- std::stringstream s;
- s << e;
const std::string expected = "?\n"
"v expect( never() ).with( less( \"first\" ) )\n"
"v expect( exactly( 2/2 ) ).with( \"second\" )";
- BOOST_CHECK_EQUAL( expected, s.str() );
+ BOOST_CHECK_EQUAL( expected, to_string( e ) );
}
e.reset();
}
{
mock::expectation< void( int ) > e( "my expectation" );
e.expect().once();
- std::stringstream s;
- s << e;
const std::string expected = "my expectation\n"
". expect( once() ).with( any )";
- BOOST_CHECK_EQUAL( expected, s.str() );
+ BOOST_CHECK_EQUAL( expected, to_string( e ) );
e.reset();
}
{
mock::expectation< void( int ) > e( "my expectation" );
e.expect().once().with( mock::any );
- std::stringstream s;
- s << e;
const std::string expected = "my expectation\n"
". expect( once() ).with( any )";
- BOOST_CHECK_EQUAL( expected, s.str() );
+ BOOST_CHECK_EQUAL( expected, to_string( e ) );
e.reset();
}
{
mock::expectation< void( int ) > e( "my expectation" );
e.expect().once();
- std::stringstream s;
- s << e;
const std::string expected = "my expectation\n"
". expect( once() ).with( any )";
- BOOST_CHECK_EQUAL( expected, s.str() );
+ BOOST_CHECK_EQUAL( expected, to_string( e ) );
e.reset();
}
{
mock::expectation< void( int ) > e( "my expectation" );
e.expect().once().with( &custom_constraint );
- std::stringstream s;
- s << e;
const std::string expected = "my expectation\n"
". expect( once() ).with( ? )";
- BOOST_CHECK_EQUAL( expected, s.str() );
+ BOOST_CHECK_EQUAL( expected, to_string( e ) );
e.reset();
}
{
mock::expectation< void( int ) > e( "my expectation" );
e.expect().once().with( mock::constraint( &custom_constraint, "custom constraint" ) );
- std::stringstream s;
- s << e;
const std::string expected = "my expectation\n"
". expect( once() ).with( custom constraint )";
- BOOST_CHECK_EQUAL( expected, s.str() );
+ BOOST_CHECK_EQUAL( expected, to_string( e ) );
e.reset();
}
{
mock::expectation< void( int ) > e( "my expectation" );
e.expect().once().with( mock::constraint( &custom_constraint, true ) );
- std::stringstream s;
- s << e;
const std::string expected = "my expectation\n"
". expect( once() ).with( true )";
- BOOST_CHECK_EQUAL( expected, s.str() );
+ BOOST_CHECK_EQUAL( expected, to_string( e ) );
e.reset();
}
}
diff --git a/src/tests/turtle_test/samples_test.cpp b/src/tests/turtle_test/integration_test.cpp
similarity index 59%
rename from src/tests/turtle_test/samples_test.cpp
rename to src/tests/turtle_test/integration_test.cpp
index fb2eb72..ec69e5d 100644
--- a/src/tests/turtle_test/samples_test.cpp
+++ b/src/tests/turtle_test/integration_test.cpp
@@ -19,6 +19,21 @@
# pragma warning( disable : 4355 4505 )
#endif
+namespace
+{
+ struct my_custom_mock
+ {
+ MOCK_METHOD_EXT( my_method, 0, void(), my_method )
+ };
+}
+
+BOOST_AUTO_TEST_CASE( custom_mock_object_without_macros_and_without_inheriting_from_object )
+{
+ my_custom_mock m;
+ MOCK_EXPECT( m, my_method ).once();
+ m.my_method();
+}
+
namespace
{
struct my_custom_mock_object : mock::object
@@ -32,9 +47,9 @@ namespace
BOOST_AUTO_TEST_CASE( custom_mock_object_without_macros )
{
- my_custom_mock_object mock;
- MOCK_EXPECT( mock, my_method );
- mock.my_method();
+ my_custom_mock_object m;
+ MOCK_EXPECT( m, my_method ).once();
+ m.my_method();
}
namespace
@@ -51,7 +66,7 @@ BOOST_AUTO_TEST_CASE( basic_mock_object_usage )
MOCK_EXPECT( m, my_method ).once().returns( 0 );
BOOST_CHECK_EQUAL( 0, m.my_method( 13 ) );
mock::verify();
- mock::reset(); // $$$$ MAT : shouldn't reset implicitly call verify ?
+ mock::reset();
MOCK_EXPECT( m, my_method ).once().with( 42 ).returns( 7 );
BOOST_CHECK_EQUAL( 7, m.my_method( 42 ) );
mock::verify();
@@ -60,73 +75,6 @@ BOOST_AUTO_TEST_CASE( basic_mock_object_usage )
BOOST_CHECK_EQUAL( 51, m.my_method( 27 ) );
}
-namespace
-{
- class my_observer : boost::noncopyable
- {
- public:
- virtual ~my_observer() {}
-
- virtual void notify( int value ) = 0;
- };
-
- class my_manager : boost::noncopyable
- {
- public:
- virtual ~my_manager() {}
-
- virtual my_observer& get_observer() const = 0;
- };
-
- class my_subject : boost::noncopyable
- {
- public:
- explicit my_subject( my_manager& f )
- : o_( f.get_observer() )
- , value_( 0 )
- {}
- void increment()
- {
- o_.notify( ++value_ );
- }
- private:
- my_observer& o_;
- int value_;
- };
-
- MOCK_BASE_CLASS( my_mock_observer, my_observer )
- {
- MOCK_METHOD( notify, 1 )
- };
-
- MOCK_BASE_CLASS( my_mock_manager, my_manager )
- {
- MOCK_METHOD( get_observer, 0 )
- };
-
- class fixture
- {
- public:
- fixture()
- : manager( "(the only one)" )
- {}
- my_mock_manager manager;
- my_mock_observer observer;
- };
-}
-
-BOOST_FIXTURE_TEST_CASE( basic_mock_object_collaboration_usage, fixture )
-{
- MOCK_EXPECT( manager, get_observer ).returns( boost::ref( observer ) );
- my_subject subject( manager );
- MOCK_EXPECT( observer, notify ).once().with( 1 );
- subject.increment();
- MOCK_EXPECT( observer, notify ).once().with( 2 );
- subject.increment();
- MOCK_EXPECT( observer, notify ).once().with( 3 );
- subject.increment();
-}
-
namespace
{
class my_ambiguited_interface : boost::noncopyable
@@ -179,3 +127,148 @@ BOOST_AUTO_TEST_CASE( mock_object_method_const_disambiguation )
const my_const_ambiguited_mock const_mock;
BOOST_CHECK_THROW( const_mock.my_method(), mock::exception );
}
+
+BOOST_AUTO_TEST_CASE( mock_functor_in_function_is_supported )
+{
+ boost::function< int( float, const std::string& ) > func;
+ {
+ MOCK_FUNCTOR( int( float, const std::string& ) ) f;
+ MOCK_EXPECT(f, operator).once().with( 3, "op" ).returns( 42 );
+ func = f;
+ }
+ BOOST_CHECK_EQUAL( 42, func( 3, "op" ) );
+}
+
+BOOST_AUTO_TEST_CASE( mock_functor_name_can_be_customised )
+{
+ MOCK_FUNCTOR( int( float, const std::string& ) ) f( "my functor" );
+}
+
+namespace
+{
+ struct functor_fixture
+ {
+ MOCK_FUNCTOR( int( float, const std::string& ) ) f;
+ };
+}
+
+BOOST_FIXTURE_TEST_CASE( mock_functor_in_fixture_is_supported, functor_fixture )
+{
+ MOCK_EXPECT(f, operator).once().with( 3, "op" ).returns( 42 );
+ BOOST_CHECK_EQUAL( 42, f( 3.f, "op" ) );
+}
+
+namespace
+{
+ template< typename T >
+ struct my_template_mock
+ {
+ MOCK_METHOD_EXT( my_method, 0, void(), my_method )
+ MOCK_METHOD_EXT_TPL( my_method, 2, void( T, std::string ), my_method_t )
+ MOCK_METHOD_EXT_TPL( my_other_method, 0, void(), my_other_method )
+ };
+}
+
+BOOST_AUTO_TEST_CASE( mocking_a_template_class_method_is_supported )
+{
+ my_template_mock< int > m;
+ MOCK_EXPECT( m, my_method_t ).with( 3, "" );
+ m.my_method( 3, "" );
+}
+
+namespace
+{
+ template< typename T >
+ struct my_template_base_class
+ {
+ virtual ~my_template_base_class()
+ {}
+ virtual void my_method( T ) = 0;
+ virtual void my_other_method() = 0;
+ };
+ template< typename T >
+ MOCK_BASE_CLASS( my_template_base_class_mock, my_template_base_class< T > )
+ {
+#if (defined __CYGWIN__) && (__GNUC__ == 3)
+ MOCK_METHOD_EXT_TPL( my_method, 1, void( T ), my_method )
+ MOCK_METHOD_EXT_TPL( my_other_method, 0, void(), my_other_method )
+#else
+ MOCK_METHOD_TPL( my_method, 1 )
+ MOCK_METHOD_TPL( my_other_method, 0 )
+#endif
+ };
+}
+
+BOOST_AUTO_TEST_CASE( mocking_a_template_base_class_method_is_supported )
+{
+ my_template_base_class_mock< int > m;
+ MOCK_EXPECT( m, my_method ).once().with( 3 );
+ m.my_method( 3 );
+}
+
+namespace
+{
+ class my_observer : boost::noncopyable
+ {
+ public:
+ virtual ~my_observer() {}
+
+ virtual void notify( int value ) = 0;
+ };
+
+ class my_manager : boost::noncopyable
+ {
+ public:
+ virtual ~my_manager() {}
+
+ virtual my_observer& get_observer() const = 0;
+ };
+
+ class my_subject : boost::noncopyable
+ {
+ public:
+ explicit my_subject( my_manager& f )
+ : o_( f.get_observer() )
+ , value_( 0 )
+ {}
+ void increment()
+ {
+ o_.notify( ++value_ );
+ }
+ private:
+ my_observer& o_;
+ int value_;
+ };
+
+ MOCK_BASE_CLASS( my_mock_observer, my_observer )
+ {
+ MOCK_METHOD( notify, 1 )
+ };
+
+ MOCK_BASE_CLASS( my_mock_manager, my_manager )
+ {
+ MOCK_METHOD( get_observer, 0 )
+ };
+
+ struct fixture
+ {
+ fixture()
+ {
+ manager.tag( "(the only one)" );
+ }
+ my_mock_manager manager;
+ my_mock_observer observer;
+ };
+}
+
+BOOST_FIXTURE_TEST_CASE( basic_mock_object_collaboration_usage, fixture )
+{
+ MOCK_EXPECT( manager, get_observer ).returns( boost::ref( observer ) );
+ my_subject subject( manager );
+ MOCK_EXPECT( observer, notify ).once().with( 1 );
+ subject.increment();
+ MOCK_EXPECT( observer, notify ).once().with( 2 );
+ subject.increment();
+ MOCK_EXPECT( observer, notify ).once().with( 3 );
+ subject.increment();
+}
diff --git a/src/tests/turtle_test/mock_test.cpp b/src/tests/turtle_test/mock_test.cpp
index dbb2f88..48fc094 100644
--- a/src/tests/turtle_test/mock_test.cpp
+++ b/src/tests/turtle_test/mock_test.cpp
@@ -141,3 +141,55 @@ BOOST_AUTO_TEST_CASE( MOCK_EXPECT_macro )
MOCK_EXPECT( m, my_method ).once().with( 42 );
m.my_method( 42 );
}
+
+namespace
+{
+ template< typename T >
+ std::string to_string( const T& t )
+ {
+ std::stringstream s;
+ s << t;
+ return s.str();
+ }
+}
+
+BOOST_AUTO_TEST_CASE( mock_object_is_named )
+{
+ my_mock m;
+ BOOST_CHECK_EQUAL( "my_mock::my_method", to_string( MOCK_MOCKER( m, my_method ) ) );
+}
+
+BOOST_AUTO_TEST_CASE( mock_object_with_tag_is_named )
+{
+ my_mock m;
+ m.tag( "(my tag)" );
+ BOOST_CHECK_EQUAL( "my_mock(my tag)::my_method", to_string( MOCK_MOCKER( m, my_method ) ) );
+}
+
+namespace
+{
+ struct my_custom_mock
+ {
+ MOCK_METHOD_EXT( my_method, 0, void(), my_method )
+ };
+}
+
+BOOST_AUTO_TEST_CASE( custom_mock_object_without_macros_and_without_inheriting_from_object_is_named )
+{
+ my_custom_mock m;
+ BOOST_CHECK_EQUAL( "my_custom_mock::my_method", to_string( MOCK_MOCKER( m, my_method ) ) );
+}
+
+namespace
+{
+ struct my_custom_mock_object : mock::object
+ {
+ MOCK_METHOD_EXT( my_method, 0, void(), my_method )
+ };
+}
+
+BOOST_AUTO_TEST_CASE( custom_mock_object_without_macros_is_named )
+{
+ my_custom_mock_object m;
+ BOOST_CHECK_EQUAL( "my_custom_mock_object::my_method", to_string( MOCK_MOCKER( m, my_method ) ) );
+}
diff --git a/src/tests/turtle_test/object_test.cpp b/src/tests/turtle_test/object_test.cpp
index 3005a9d..291836d 100644
--- a/src/tests/turtle_test/object_test.cpp
+++ b/src/tests/turtle_test/object_test.cpp
@@ -35,7 +35,8 @@ namespace
BOOST_AUTO_TEST_CASE( verifying_an_object_containing_a_failing_expectation_fails )
{
mock::object o;
- mock::expectation< void(), silent_error > e( o );
+ mock::expectation< void(), silent_error > e;
+ o.set_parent( e );
e.expect().once();
BOOST_CHECK( ! o.verify() );
}
@@ -43,30 +44,37 @@ BOOST_AUTO_TEST_CASE( verifying_an_object_containing_a_failing_expectation_fails
BOOST_AUTO_TEST_CASE( resetting_an_object_containing_a_failing_expectation_and_verifying_it_succeeds )
{
mock::object o;
- mock::expectation< void() > e( o );
+ mock::expectation< void() > e;
+ o.set_parent( e );
e.expect().once();
o.reset();
BOOST_CHECK( o.verify() );
- BOOST_CHECK( e.verify() );
}
-BOOST_AUTO_TEST_CASE( verifying_an_object_containing_another_object_with_a_failing_expectation_fails )
+BOOST_AUTO_TEST_CASE( an_object_is_assignable_by_sharing_its_state )
{
mock::object o1;
- mock::object o2( o1 );
- mock::expectation< void(), silent_error > e( o2 );
- e.expect().once();
+ mock::expectation< void(), silent_error > e;
+ {
+ mock::object o2;
+ o2.set_parent( e );
+ e.expect().once();
+ o1 = o2;
+ BOOST_CHECK( ! o2.verify() );
+ BOOST_CHECK( ! o1.verify() );
+ }
BOOST_CHECK( ! o1.verify() );
}
-BOOST_AUTO_TEST_CASE( resetting_an_object_containing_another_object_with_a_failing_expectation_and_verifying_it_succeeds )
+BOOST_AUTO_TEST_CASE( an_object_is_copiable_by_sharing_its_state )
{
- mock::object o1;
- mock::object o2( o1 );
- mock::expectation< void() > e( o2 );
+ std::auto_ptr< mock::object > o2( new mock::object );
+ const mock::object o1( *o2 );
+ mock::expectation< void(), silent_error > e;
+ o2->set_parent( e );
e.expect().once();
- o1.reset();
- BOOST_CHECK( o1.verify() );
- BOOST_CHECK( o2.verify() );
- BOOST_CHECK( e.verify() );
+ BOOST_CHECK( ! o2->verify() );
+ BOOST_CHECK( ! o1.verify() );
+ o2.reset();
+ BOOST_CHECK( ! o1.verify() );
}