Merged refactoring branch

git-svn-id: https://svn.code.sf.net/p/turtle/code/trunk@379 860be788-9bd5-4423-9f1e-828f051e677b
This commit is contained in:
mat007 2011-07-09 15:16:03 +00:00
parent bec0c8aafa
commit a7c62e523a
19 changed files with 558 additions and 263 deletions

View file

@ -168,6 +168,14 @@
RelativePath="..\..\src\libraries\turtle\check.hpp"
>
</File>
<File
RelativePath="..\..\src\libraries\turtle\child.hpp"
>
</File>
<File
RelativePath="..\..\src\libraries\turtle\cleanup.hpp"
>
</File>
<File
RelativePath="..\..\src\libraries\turtle\config.hpp"
>
@ -180,6 +188,10 @@
RelativePath="..\..\src\libraries\turtle\constraints.hpp"
>
</File>
<File
RelativePath="..\..\src\libraries\turtle\context.hpp"
>
</File>
<File
RelativePath="..\..\src\libraries\turtle\default_error.hpp"
>
@ -196,6 +208,10 @@
RelativePath="..\..\src\libraries\turtle\function.hpp"
>
</File>
<File
RelativePath="..\..\src\libraries\turtle\group.hpp"
>
</File>
<File
RelativePath="..\..\src\libraries\turtle\invocation.hpp"
>
@ -216,10 +232,6 @@
RelativePath="..\..\src\libraries\turtle\mock.hpp"
>
</File>
<File
RelativePath="..\..\src\libraries\turtle\node.hpp"
>
</File>
<File
RelativePath="..\..\src\libraries\turtle\object.hpp"
>
@ -228,6 +240,10 @@
RelativePath="..\..\src\libraries\turtle\operators.hpp"
>
</File>
<File
RelativePath="..\..\src\libraries\turtle\parent.hpp"
>
</File>
<File
RelativePath="..\..\src\libraries\turtle\root.hpp"
>

View file

@ -95,7 +95,7 @@
/>
<Tool
Name="VCPostBuildEventTool"
CommandLine="cd ../../run/vc80&#x0D;&#x0A;&quot;$(TargetDir)$(TargetName).exe&quot; --result_code=no --report_level=no --log_level=warning --data_directory=../../data/tests/$(ProjectName)&#x0D;&#x0A;"
CommandLine="cd ../../run/vc80&#x0D;&#x0A;&quot;$(TargetDir)$(TargetName).exe&quot; --result_code=no --report_level=no --log_level=warning"
/>
</Configuration>
<Configuration
@ -179,7 +179,7 @@
/>
<Tool
Name="VCPostBuildEventTool"
CommandLine="cd ../../run/vc80&#x0D;&#x0A;&quot;$(TargetDir)$(TargetName).exe&quot; --result_code=no --report_level=no --log_level=warning --data_directory=../../data/tests/$(ProjectName)&#x0D;&#x0A;"
CommandLine="cd ../../run/vc80&#x0D;&#x0A;&quot;$(TargetDir)$(TargetName).exe&quot; --result_code=no --report_level=no --log_level=warning"
/>
</Configuration>
</Configurations>

View file

@ -9,7 +9,6 @@
#ifndef MOCK_BOOST_TEST_ERROR_POLICY_HPP_INCLUDED
#define MOCK_BOOST_TEST_ERROR_POLICY_HPP_INCLUDED
#include "root.hpp"
#include <boost/test/framework.hpp>
#include <boost/test/test_tools.hpp>
#include <boost/test/unit_test_suite.hpp>
@ -87,16 +86,6 @@ namespace mock
fail( "untriggered expectation", context, file, line );
}
};
struct cleanup
{
~cleanup()
{
//mock::verify(); // $$$$ MAT : because of a bug in Boost.Test this will crash if anything needs to be logged
mock::reset();
}
};
BOOST_GLOBAL_FIXTURE( cleanup );
}
#endif // MOCK_BOOST_TEST_ERROR_POLICY_HPP_INCLUDED

View file

@ -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_CHILD_HPP_INCLUDED
#define MOCK_CHILD_HPP_INCLUDED
#include "parent.hpp"
#include <ostream>
#include <string>
namespace mock
{
namespace detail
{
class child
{
public:
child()
: parent_( 0 )
{}
void update( parent& p, const std::string& instance,
const std::string& type, const std::string& name )
{
if( instance != "?" || name_.empty() )
p = parent( instance, type );
parent_ = &p;
name_ = name;
}
friend std::ostream& operator<<( std::ostream& s, const child& c )
{
if( c.parent_ )
s << *c.parent_;
return s << c.name_;
}
private:
const parent* parent_;
std::string name_;
};
}
}
#endif // MOCK_CHILD_HPP_INCLUDED

View file

@ -0,0 +1,37 @@
//
// 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_CLEANUP_HPP_INCLUDED
#define MOCK_CLEANUP_HPP_INCLUDED
#include "config.hpp"
#ifdef MOCK_USE_BOOST_TEST
#include "root.hpp"
#include <boost/test/unit_test_suite.hpp>
namespace mock
{
namespace detail
{
struct cleanup
{
~cleanup()
{
//mock::verify(); // $$$$ MAT : because of a bug in Boost.Test this will crash if anything needs to be logged
mock::reset();
}
};
BOOST_GLOBAL_FIXTURE( cleanup );
}
}
#endif
#endif // MOCK_CLEANUP_HPP_INCLUDED

View file

@ -38,4 +38,8 @@
# endif
#endif
#ifdef BOOST_TEST_DECL
# define MOCK_USE_BOOST_TEST
#endif
#endif // MOCK_CONFIG_HPP_INCLUDED

View file

@ -0,0 +1,38 @@
//
// 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_CONTEXT_HPP_INCLUDED
#define MOCK_CONTEXT_HPP_INCLUDED
#include <boost/noncopyable.hpp>
#include <ostream>
#include <string>
namespace mock
{
class verifiable;
namespace detail
{
class context : boost::noncopyable
{
public:
context() {}
virtual ~context() {}
virtual void add( const void* p, verifiable& v, const std::string& instance,
const std::string& type, const std::string& name ) = 0;
virtual void add( verifiable& v ) = 0;
virtual void remove( verifiable& v ) = 0;
virtual void serialize( std::ostream& s, const verifiable& v ) const = 0;
};
}
}
#endif // MOCK_CONTEXT_HPP_INCLUDED

View file

@ -12,7 +12,7 @@
#include "config.hpp"
#ifndef MOCK_ERROR_POLICY
# if defined(BOOST_TEST_DECL) || defined(MOCK_USE_BOOST_TEST)
# ifdef MOCK_USE_BOOST_TEST
# define MOCK_ERROR_POLICY boost_test_error_policy
# include "boost_test_error.hpp"
# else

View file

@ -11,8 +11,9 @@
#include "config.hpp"
#include "error.hpp"
#include "context.hpp"
#include "expectation.hpp"
#include "root.hpp"
#include "verifiable.hpp"
#include "log.hpp"
#include "args.hpp"
#include <boost/function_types/result_type.hpp>
@ -29,10 +30,7 @@
namespace mock
{
template< typename Signature,
typename ErrorPolicy = MOCK_ERROR_POLICY<
BOOST_DEDUCED_TYPENAME
boost::function_types::result_type< Signature >::type > >
template< typename Signature >
class function
{
public:
@ -52,27 +50,10 @@ namespace mock
detail::expectation< Signature, arity::value > expectation_type;
public:
struct function_tag
{};
function_tag exp_;
function()
: impl_( new function_impl() )
{}
void tag( const std::string& name )
{
impl_->tag( name );
}
const std::string& tag() const
{
return impl_->tag();
}
void set_parent( node& parent )
{
impl_->set_parent( parent );
}
bool verify() const
{
return impl_->verify();
@ -114,36 +95,57 @@ namespace mock
return s << *e.impl_;
}
private:
class function_impl : private verifiable
function& _( detail::context& c, const std::string& instance )
{
if( ! impl_->context_ )
c.add( *impl_ );
c.add( impl_.get(), *impl_, instance, "", "" );
impl_->context_ = &c;
return *this;
}
void configure( detail::context& c, const void* p,
const std::string& instance, const std::string& type,
const std::string& name ) const
{
if( ! impl_->context_ )
c.add( *impl_ );
c.add( p, *impl_, instance, type, name );
impl_->context_ = &c;
}
private:
class function_impl : public verifiable
{
private:
typedef MOCK_ERROR_POLICY< result_type > error_type;
public:
function_impl()
: name_( "?" )
, parent_( 0 )
: context_( 0 )
, valid_( true )
{}
virtual ~function_impl()
{
if( parent_ )
parent_->remove( *this );
if( valid_ && ! std::uncaught_exception() )
for( expectations_cit it = expectations_.begin();
it != expectations_.end(); ++it )
{
if( ! it->verify() )
ErrorPolicy::untriggered_expectation(
error_type::untriggered_expectation(
boost::unit_test::lazy_ostream::instance()
<< lazy_context( this )
<< lazy_expectations( this ),
it->file(), it->line() );
else if( ! it->invoked() )
ErrorPolicy::expected_call(
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
@ -153,7 +155,7 @@ namespace mock
if( !it->verify() )
{
valid_ = false;
ErrorPolicy::verification_failed(
error_type::verification_failed(
boost::unit_test::lazy_ostream::instance()
<< lazy_context( this )
<< lazy_expectations( this ),
@ -167,26 +169,6 @@ namespace mock
valid_ = true;
expectations_.clear();
}
virtual void untie()
{
parent_ = 0;
}
void tag( const std::string& name )
{
name_ = name;
}
const std::string& tag() const
{
return name_;
}
void set_parent( node& parent )
{
if( parent_ )
parent_->remove( *this );
parent.add( *this );
parent_ = &parent;
}
expectation_type& expect( const std::string& file, int line )
{
@ -196,8 +178,6 @@ namespace mock
}
expectation_type& expect()
{
if( ! parent_ )
set_parent( mock::detail::root );
expectations_.push_back( expectation_type() );
valid_ = true;
return expectations_.back();
@ -218,26 +198,26 @@ namespace mock
if( ! it->invoke() ) \
{ \
valid_ = false; \
ErrorPolicy::sequence_failed( MOCK_EXPECTATION_CALL_CONTEXT(n), it->file(), it->line() ); \
error_type::sequence_failed( MOCK_EXPECTATION_CALL_CONTEXT(n), it->file(), it->line() ); \
return A; \
} \
if( ! it->functor() ) \
{ \
ErrorPolicy::missing_action( MOCK_EXPECTATION_CALL_CONTEXT(n), it->file(), it->line() ); \
error_type::missing_action( MOCK_EXPECTATION_CALL_CONTEXT(n), it->file(), it->line() ); \
return A; \
} \
ErrorPolicy::expected_call( MOCK_EXPECTATION_CALL_CONTEXT(n), it->file(), it->line() ); \
error_type::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_CALL_CONTEXT(n) ); \
error_type::unexpected_call( MOCK_EXPECTATION_CALL_CONTEXT(n) ); \
return A; \
}
#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(BOOST_PP_INC(MOCK_MAX_ARGS), MOCK_EXPECTATION_OPERATOR, ErrorPolicy::abort())
BOOST_PP_REPEAT(BOOST_PP_INC(MOCK_MAX_ARGS), MOCK_EXPECTATION_OPERATOR, error_type::abort())
void test() const
MOCK_EXPECTATION_INVOKE(, 0,)
@ -259,11 +239,13 @@ namespace mock
{}
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_;
if( e.impl_->context_ )
e.impl_->context_->serialize( s, *e.impl_ );
else
s << "?";
return s;
}
const function_impl* impl_;
const function_impl* impl_; // $$$$ MAT : use detail::context directly
};
struct lazy_expectations
@ -286,12 +268,10 @@ namespace mock
expectations_type::const_iterator expectations_cit;
expectations_type expectations_;
std::string name_;
node* parent_;
detail::context* context_;
mutable bool valid_;
};
private:
boost::shared_ptr< function_impl > impl_;
};
}

View file

@ -0,0 +1,60 @@
//
// 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_GROUP_HPP_INCLUDED
#define MOCK_GROUP_HPP_INCLUDED
#include "verifiable.hpp"
#include <functional>
#include <algorithm>
#include <vector>
namespace mock
{
namespace detail
{
class group
{
public:
void add( verifiable& v )
{
verifiables_.push_back( &v );
}
void remove( verifiable& v )
{
verifiables_.erase(
std::remove( verifiables_.begin(), verifiables_.end(), &v ),
verifiables_.end() );
}
bool verify() const
{
bool valid = true;
for( verifiables_cit it = verifiables_.begin();
it != verifiables_.end(); ++it )
if( ! (*it)->verify() )
valid = false;
return valid;
}
void reset() const
{
std::for_each( verifiables_.begin(), verifiables_.end(),
std::mem_fun( &verifiable::reset ) );
}
private:
typedef std::vector< verifiable* > verifiables_t;
typedef verifiables_t::iterator verifiables_it;
typedef verifiables_t::const_iterator verifiables_cit;
verifiables_t verifiables_;
};
}
}
#endif // MOCK_GROUP_HPP_INCLUDED

View file

@ -10,6 +10,7 @@
#define MOCK_MOCK_HPP_INCLUDED
#include "config.hpp"
#include "cleanup.hpp"
#include "object.hpp"
#include "function.hpp"
#include "type_name.hpp"
@ -19,7 +20,6 @@
#include <boost/function_types/parameter_types.hpp>
#include <boost/function_types/function_type.hpp>
#include <boost/function_types/result_type.hpp>
#include <boost/type_traits/is_base_of.hpp>
#include <boost/mpl/joint_view.hpp>
#include <boost/mpl/single_view.hpp>
#include <boost/mpl/pop_front.hpp>
@ -81,43 +81,6 @@ namespace detail
>
{};
template< typename E >
void set_parent( E& e, const std::string& prefix,
const std::string& name, const object& o )
{
o.set_child( e );
o.tag( prefix );
e.tag( name );
}
template< typename E, typename T >
void set_parent( E& e, const std::string& prefix,
const std::string& name, const T&,
BOOST_DEDUCED_TYPENAME boost::disable_if<
BOOST_DEDUCED_TYPENAME boost::is_base_of< object, T >
>::type* = 0 )
{
e.tag( prefix + name );
}
template< typename E >
E& configure( BOOST_DEDUCED_TYPENAME E::function_tag,
const std::string& parent, const std::string& /*name*/, E& e )
{
if( parent != "?" || e.tag() == "?" )
e.tag( parent );
return e;
}
template< typename E, typename T >
E& configure( E& e, const std::string& parent,
const std::string& name, const T& t )
{
if( parent != "?" || e.tag() == "?" )
mock::detail::set_parent( e,
parent + " " + mock::detail::type_name( typeid( T ) ) + "::",
name, t );
return e;
}
template< typename T >
struct base
{
@ -134,22 +97,29 @@ namespace detail
mock::function< S >
#define MOCK_MOCKER(o, t) \
mock::detail::configure( mock::detail::deref( o ).exp##t, \
BOOST_PP_STRINGIZE(o), BOOST_PP_STRINGIZE(t), \
mock::detail::deref( o ) )
#define MOCK_ANONYMOUS_MOCKER(o, M, t) \
mock::detail::configure( mock::detail::deref( o ).exp##t, \
"?", BOOST_PP_STRINGIZE(M), mock::detail::deref( o ) )
mock::detail::deref( o ).t( mock::detail::root, \
BOOST_PP_STRINGIZE(o) )
#define MOCK_ANONYMOUS_MOCKER(o, t) \
mock::detail::deref( o ).t( mock::detail::root, "?" )
#define MOCK_METHOD_EXPECTATION(S, t) \
mutable mock::function< S > exp##t;
mutable mock::function< S > t##expectation; \
mock::function< S >& t( const mock::detail::context&, \
const std::string& instance ) const \
{ \
mock::detail::configure( *this, t##expectation, instance, \
mock::detail::type_name( typeid( *this ) ), \
BOOST_PP_STRINGIZE(t) ); \
return t##expectation; \
}
#define MOCK_SIGNATURE(M) \
mock::detail::signature< BOOST_TYPEOF(&base_type::M) >::type
mock::detail::signature< BOOST_TYPEOF(&base_type::M) >::type // $$$$ MAT inline mock::detail::signature
#define MOCK_METHOD_STUB(M, n, S, t, c, tpn) \
MOCK_DECL(M, n, S, c, tpn) \
{ \
return MOCK_ANONYMOUS_MOCKER(this, t, t)( \
return MOCK_ANONYMOUS_MOCKER(this, t)( \
BOOST_PP_ENUM_PARAMS(n, p) ); \
}
@ -178,18 +148,18 @@ namespace detail
MOCK_METHOD_EXPECTATION(S, t)
#define MOCK_DESTRUCTOR(T, t) \
~T() { MOCK_ANONYMOUS_MOCKER(this, ~T, t).test(); } \
~T() { MOCK_ANONYMOUS_MOCKER(this, t).test(); } \
MOCK_METHOD_EXPECTATION(void(), t)
#define MOCK_CONST_CONVERSION_OPERATOR(T, t) \
operator T() const { return MOCK_ANONYMOUS_MOCKER(this, operator T, t)(); } \
operator T() const { return MOCK_ANONYMOUS_MOCKER(this, t)(); } \
MOCK_METHOD_EXPECTATION(T(), t)
#define MOCK_NON_CONST_CONVERSION_OPERATOR(T, t) \
operator T() { return MOCK_ANONYMOUS_MOCKER(this, operator T, t)(); } \
operator T() { return MOCK_ANONYMOUS_MOCKER(this, t)(); } \
MOCK_METHOD_EXPECTATION(T(), t)
#define MOCK_CONVERSION_OPERATOR(T, t) \
operator T() const { return MOCK_ANONYMOUS_MOCKER(this, operator T, t)(); } \
operator T() { return MOCK_ANONYMOUS_MOCKER(this, operator T, t)(); } \
operator T() const { return MOCK_ANONYMOUS_MOCKER(this, t)(); } \
operator T() { return MOCK_ANONYMOUS_MOCKER(this, t)(); } \
MOCK_METHOD_EXPECTATION(T(), t)
#define MOCK_EXPECT(o,t) MOCK_MOCKER(o,t).expect( __FILE__, __LINE__ )

View file

@ -17,24 +17,9 @@
namespace mock
{
class node : protected verifiable
class node
{
public:
virtual ~node()
{
std::for_each( v_.begin(), v_.end(),
std::mem_fun( &verifiable::untie ) );
}
void tag( const std::string& name )
{
name_ = name;
}
const std::string& tag() const
{
return name_;
}
void add( verifiable& v )
{
v_.push_back( &v );

View file

@ -9,8 +9,12 @@
#ifndef MOCK_OBJECT_HPP_INCLUDED
#define MOCK_OBJECT_HPP_INCLUDED
#include "node.hpp"
#include "root.hpp"
#include "context.hpp"
#include "parent.hpp"
#include "child.hpp"
#include <boost/type_traits/is_base_of.hpp>
#include <boost/utility/enable_if.hpp>
#include <boost/shared_ptr.hpp>
#include <string>
@ -23,60 +27,101 @@ namespace mock
: impl_( new object_impl() )
{}
template< typename T >
void set_child( T& t ) const
{
impl_->set_child( t );
}
void tag( const std::string& name ) const
{
impl_->tag( name );
}
bool verify() const
bool verify() const // $$$$ MAT : to be deprecated
{
return impl_->verify();
}
void reset()
void reset() // $$$$ MAT : to be deprecated
{
impl_->reset();
}
private:
class object_impl : public node
class object_impl : public detail::context, private verifiable
{
public:
object_impl()
: parent_( 0 )
{}
virtual ~object_impl()
{
if( parent_ )
parent_->remove( *this );
}
template< typename T >
void set_child( T& t )
{
if( ! parent_ )
virtual void add( const void* /*p*/, verifiable& v,
const std::string& instance, const std::string& type,
const std::string& name )
{
if( children_.empty() )
mock::detail::root.add( *this );
parent_ = &mock::detail::root;
children_[ &v ].update( parent_, instance, type, name );
}
t.set_parent( *this );
}
private:
virtual void untie()
virtual void add( verifiable& v )
{
parent_ = 0;
group_.add( v );
}
virtual void remove( verifiable& v )
{
group_.remove( v );
children_.erase( &v );
if( children_.empty() )
mock::detail::root.remove( *this );
}
virtual void serialize( std::ostream& s,
const verifiable& v ) const
{
children_cit it = children_.find( &v );
if( it != children_.end() )
s << it->second;
else
s << "?";
}
virtual bool verify() const
{
return group_.verify();
}
virtual void reset()
{
group_.reset();
}
private:
node* parent_;
typedef std::map< const verifiable*, detail::child > children_t;
typedef children_t::const_iterator children_cit;
detail::group group_;
detail::parent parent_;
children_t children_;
};
public:
boost::shared_ptr< object_impl > impl_;
};
namespace detail
{
template< typename E >
E& configure( const object& o, E& e, const std::string& instance,
const std::string& type, const std::string& name )
{
e.configure( *o.impl_, o.impl_.get(), instance, type, name );
return e;
}
template< typename E, typename T >
E& configure( const T& t, E& e, const std::string& instance,
const std::string& type, const std::string& name,
BOOST_DEDUCED_TYPENAME boost::disable_if<
BOOST_DEDUCED_TYPENAME boost::is_base_of< object, T >
>::type* = 0 )
{
e.configure( mock::detail::root, &t, instance, type, name );
return e;
}
}
inline bool verify( const object& o )
{
return o.impl_->verify();
}
inline void reset( object& o )
{
o.impl_->reset();
}
}
#endif // MOCK_OBJECT_HPP_INCLUDED

View file

@ -0,0 +1,42 @@
//
// 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_PARENT_HPP_INCLUDED
#define MOCK_PARENT_HPP_INCLUDED
#include <ostream>
#include <string>
namespace mock
{
namespace detail
{
class parent
{
public:
parent()
{}
parent( const std::string& instance, const std::string& type )
: instance_( instance )
, type_( type )
{}
friend std::ostream& operator<<( std::ostream& s, const parent& p )
{
s << p.instance_;
if( ! p.type_.empty() )
s << " " + p.type_ + "::";
return s;
}
private:
std::string instance_;
std::string type_;
};
}
}
#endif // MOCK_PARENT_HPP_INCLUDED

View file

@ -9,19 +9,118 @@
#ifndef MOCK_ROOT_HPP_INCLUDED
#define MOCK_ROOT_HPP_INCLUDED
#include "config.hpp"
#include "node.hpp"
#include "group.hpp"
#include "context.hpp"
#include "parent.hpp"
#include "child.hpp"
#include "function.hpp"
#include <boost/test/utils/trivial_singleton.hpp>
#include <ostream>
#include <string>
#include <map>
namespace mock
{
namespace detail
{
class root_t : public boost::unit_test::singleton< root_t >, public node
class root_t : public boost::unit_test::singleton< root_t >,
public detail::context
{
public:
virtual void add( const void* p, verifiable& v,
const std::string& instance, const std::string& type,
const std::string& name )
{
children_it it = children_.lower_bound( &v );
if( it == children_.end() ||
children_.key_comp()( &v, it->first ) )
it = children_.insert( it,
std::make_pair( &v, counter_child( parents_, p ) ) );
it->second.update( instance, type, name );
}
virtual void add( verifiable& v )
{
group_.add( v );
}
virtual void remove( verifiable& v )
{
group_.remove( v );
children_.erase( &v );
}
bool verify() const
{
return group_.verify();
}
void reset() const
{
group_.reset();
}
virtual void serialize( std::ostream& s, const verifiable& v ) const
{
children_cit it = children_.find( &v );
if( it != children_.end() )
s << it->second;
else
s << "?";
}
private:
virtual void untie()
{}
typedef std::map< const void*,
std::pair< parent, std::size_t > > parents_t;
typedef parents_t::iterator parents_it;
class counter_child
{
public:
counter_child( parents_t& parents, const void* p )
: parents_( &parents )
, it_( parents.insert(
std::make_pair( p, parents_t::mapped_type() ) ).first )
{
++it_->second.second;
}
counter_child( const counter_child& rhs )
: parents_( rhs.parents_ )
, it_( rhs.it_ )
, child_( rhs.child_ )
{
++it_->second.second;
}
~counter_child()
{
if( --it_->second.second == 0 )
parents_->erase( it_ );
}
void update( const std::string& instance, const std::string& type,
const std::string& name )
{
child_.update( it_->second.first, instance, type, name );
}
friend std::ostream& operator<<( std::ostream& s,
const counter_child& c )
{
return s << c.child_;
}
private:
counter_child& operator=( const counter_child& );
parents_t* parents_;
parents_it it_;
child child_;
};
typedef std::map< const verifiable*, counter_child > children_t;
typedef children_t::const_iterator children_cit;
typedef children_t::iterator children_it;
parents_t parents_;
children_t children_;
group group_;
private:
BOOST_TEST_SINGLETON_CONS( root_t );
};

View file

@ -22,8 +22,6 @@ namespace mock
virtual bool verify() const = 0;
virtual void reset() = 0;
virtual void untie() = 0;
};
}

View file

@ -629,11 +629,10 @@ BOOST_FIXTURE_TEST_CASE( expectation_can_be_serialized_to_be_human_readable, err
{
{
mock::function< void( int ) > f;
f.tag( "my function" );
f.expect().once().with( 1 );
f.expect().once().with( 2 );
BOOST_CHECK_NO_THROW( f( 2 ) );
const std::string expected = "my function\n"
const std::string expected = "?\n"
". once().with( 1 )\n"
"v once().with( 2 )";
BOOST_CHECK_EQUAL( expected, to_string( f ) );
@ -642,9 +641,8 @@ BOOST_FIXTURE_TEST_CASE( expectation_can_be_serialized_to_be_human_readable, err
}
{
mock::function< void( int ) > f;
f.tag( "my function" );
f.expect().never().with( 1 );
const std::string expected = "my function\n"
const std::string expected = "?\n"
"v never().with( 1 )";
BOOST_CHECK_EQUAL( expected, to_string( f ) );
f.reset();
@ -672,36 +670,32 @@ BOOST_FIXTURE_TEST_CASE( expectation_can_be_serialized_to_be_human_readable, err
}
{
mock::function< void( int ) > f;
f.tag( "my function" );
f.expect().once();
const std::string expected = "my function\n"
const std::string expected = "?\n"
". once().with( any )";
BOOST_CHECK_EQUAL( expected, to_string( f ) );
f.reset();
}
{
mock::function< void( int ) > f;
f.tag( "my function" );
f.expect().once().with( mock::any );
const std::string expected = "my function\n"
const std::string expected = "?\n"
". once().with( any )";
BOOST_CHECK_EQUAL( expected, to_string( f ) );
f.reset();
}
{
mock::function< void( int ) > f;
f.tag( "my function" );
f.expect().once();
const std::string expected = "my function\n"
const std::string expected = "?\n"
". once().with( any )";
BOOST_CHECK_EQUAL( expected, to_string( f ) );
f.reset();
}
{
mock::function< void( int ) > f;
f.tag( "my function" );
f.expect().once().with( &custom_constraint );
const std::string expected = "my function\n"
const std::string expected = "?\n"
". once().with( ? )";
BOOST_CHECK_EQUAL( expected, to_string( f ) );
f.reset();

View file

@ -160,53 +160,50 @@ namespace
}
}
#define MOCK_ANONYMOUS_MOCKER_EXT(o, t) \
MOCK_ANONYMOUS_MOCKER( o, t, t )
BOOST_AUTO_TEST_CASE( mock_object_is_named )
{
my_mock m;
BOOST_CHECK_EQUAL( "? my_mock::my_method", to_string( MOCK_ANONYMOUS_MOCKER_EXT( m, my_method ) ) );
BOOST_CHECK_EQUAL( "? my_mock::my_method_2", to_string( MOCK_ANONYMOUS_MOCKER_EXT( m, my_method_2 ) ) );
BOOST_CHECK_EQUAL( "? my_mock::my_method", to_string( MOCK_ANONYMOUS_MOCKER( m, my_method ) ) );
BOOST_CHECK_EQUAL( "? my_mock::my_method_2", to_string( MOCK_ANONYMOUS_MOCKER( m, my_method_2 ) ) );
BOOST_CHECK_EQUAL( "m my_mock::my_method", to_string( MOCK_MOCKER( m, my_method ) ) );
BOOST_CHECK_EQUAL( "m my_mock::my_method_2", to_string( MOCK_ANONYMOUS_MOCKER_EXT( m, my_method_2 ) ) );
BOOST_CHECK_EQUAL( "m my_mock::my_method", to_string( MOCK_ANONYMOUS_MOCKER_EXT( m, my_method ) ) );
BOOST_CHECK_EQUAL( "m my_mock::my_method_2", to_string( MOCK_ANONYMOUS_MOCKER( m, my_method_2 ) ) );
BOOST_CHECK_EQUAL( "m my_mock::my_method", to_string( MOCK_ANONYMOUS_MOCKER( m, my_method ) ) );
BOOST_CHECK_EQUAL( "m my_mock::my_method", to_string( MOCK_MOCKER( m, my_method ) ) );
}
BOOST_AUTO_TEST_CASE( mock_object_auto_pointer_is_named )
{
std::auto_ptr< my_mock > m( new my_mock );
BOOST_CHECK_EQUAL( "? my_mock::my_method", to_string( MOCK_ANONYMOUS_MOCKER_EXT( m, my_method ) ) );
BOOST_CHECK_EQUAL( "? my_mock::my_method", to_string( MOCK_ANONYMOUS_MOCKER( m, my_method ) ) );
BOOST_CHECK_EQUAL( "m my_mock::my_method", to_string( MOCK_MOCKER( m, my_method ) ) );
BOOST_CHECK_EQUAL( "m my_mock::my_method", to_string( MOCK_ANONYMOUS_MOCKER_EXT( m, my_method ) ) );
BOOST_CHECK_EQUAL( "m my_mock::my_method", to_string( MOCK_ANONYMOUS_MOCKER( m, my_method ) ) );
BOOST_CHECK_EQUAL( "m my_mock::my_method", to_string( MOCK_MOCKER( m, my_method ) ) );
}
BOOST_AUTO_TEST_CASE( mock_object_const_auto_pointer_is_named )
{
const std::auto_ptr< my_mock > m( new my_mock );
BOOST_CHECK_EQUAL( "? my_mock::my_method", to_string( MOCK_ANONYMOUS_MOCKER_EXT( m, my_method ) ) );
BOOST_CHECK_EQUAL( "? my_mock::my_method", to_string( MOCK_ANONYMOUS_MOCKER( m, my_method ) ) );
BOOST_CHECK_EQUAL( "m my_mock::my_method", to_string( MOCK_MOCKER( m, my_method ) ) );
BOOST_CHECK_EQUAL( "m my_mock::my_method", to_string( MOCK_ANONYMOUS_MOCKER_EXT( m, my_method ) ) );
BOOST_CHECK_EQUAL( "m my_mock::my_method", to_string( MOCK_ANONYMOUS_MOCKER( m, my_method ) ) );
BOOST_CHECK_EQUAL( "m my_mock::my_method", to_string( MOCK_MOCKER( m, my_method ) ) );
}
BOOST_AUTO_TEST_CASE( mock_object_shared_pointer_is_named )
{
boost::shared_ptr< my_mock > m( new my_mock );
BOOST_CHECK_EQUAL( "? my_mock::my_method", to_string( MOCK_ANONYMOUS_MOCKER_EXT( m, my_method ) ) );
BOOST_CHECK_EQUAL( "? my_mock::my_method", to_string( MOCK_ANONYMOUS_MOCKER( m, my_method ) ) );
BOOST_CHECK_EQUAL( "m my_mock::my_method", to_string( MOCK_MOCKER( m, my_method ) ) );
BOOST_CHECK_EQUAL( "m my_mock::my_method", to_string( MOCK_ANONYMOUS_MOCKER_EXT( m, my_method ) ) );
BOOST_CHECK_EQUAL( "m my_mock::my_method", to_string( MOCK_ANONYMOUS_MOCKER( m, my_method ) ) );
BOOST_CHECK_EQUAL( "m my_mock::my_method", to_string( MOCK_MOCKER( m, my_method ) ) );
}
BOOST_AUTO_TEST_CASE( mock_object_const_shared_pointer_is_named )
{
const boost::shared_ptr< my_mock > m( new my_mock );
BOOST_CHECK_EQUAL( "? my_mock::my_method", to_string( MOCK_ANONYMOUS_MOCKER_EXT( m, my_method ) ) );
BOOST_CHECK_EQUAL( "? my_mock::my_method", to_string( MOCK_ANONYMOUS_MOCKER( m, my_method ) ) );
BOOST_CHECK_EQUAL( "m my_mock::my_method", to_string( MOCK_MOCKER( m, my_method ) ) );
BOOST_CHECK_EQUAL( "m my_mock::my_method", to_string( MOCK_ANONYMOUS_MOCKER_EXT( m, my_method ) ) );
BOOST_CHECK_EQUAL( "m my_mock::my_method", to_string( MOCK_ANONYMOUS_MOCKER( m, my_method ) ) );
BOOST_CHECK_EQUAL( "m my_mock::my_method", to_string( MOCK_MOCKER( m, my_method ) ) );
}
@ -222,11 +219,11 @@ namespace
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_ANONYMOUS_MOCKER_EXT( m, my_method ) ) );
BOOST_CHECK_EQUAL( "? my_custom_mock::my_method_2", to_string( MOCK_ANONYMOUS_MOCKER_EXT( m, my_method_2 ) ) );
BOOST_CHECK_EQUAL( "? my_custom_mock::my_method", to_string( MOCK_ANONYMOUS_MOCKER( m, my_method ) ) );
BOOST_CHECK_EQUAL( "? my_custom_mock::my_method_2", to_string( MOCK_ANONYMOUS_MOCKER( m, my_method_2 ) ) );
BOOST_CHECK_EQUAL( "m my_custom_mock::my_method", to_string( MOCK_MOCKER( m, my_method ) ) );
BOOST_CHECK_EQUAL( "? my_custom_mock::my_method_2", to_string( MOCK_ANONYMOUS_MOCKER_EXT( m, my_method_2 ) ) );
BOOST_CHECK_EQUAL( "m my_custom_mock::my_method", to_string( MOCK_ANONYMOUS_MOCKER_EXT( m, my_method ) ) );
BOOST_CHECK_EQUAL( "m my_custom_mock::my_method_2", to_string( MOCK_ANONYMOUS_MOCKER( m, my_method_2 ) ) );
BOOST_CHECK_EQUAL( "m my_custom_mock::my_method", to_string( MOCK_ANONYMOUS_MOCKER( m, my_method ) ) );
BOOST_CHECK_EQUAL( "m my_custom_mock::my_method", to_string( MOCK_MOCKER( m, my_method ) ) );
}
@ -242,11 +239,11 @@ namespace
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_ANONYMOUS_MOCKER_EXT( m, my_method ) ) );
BOOST_CHECK_EQUAL( "? my_custom_mock_object::my_method_2", to_string( MOCK_ANONYMOUS_MOCKER_EXT( m, my_method_2 ) ) );
BOOST_CHECK_EQUAL( "? my_custom_mock_object::my_method", to_string( MOCK_ANONYMOUS_MOCKER( m, my_method ) ) );
BOOST_CHECK_EQUAL( "? my_custom_mock_object::my_method_2", to_string( MOCK_ANONYMOUS_MOCKER( m, my_method_2 ) ) );
BOOST_CHECK_EQUAL( "m my_custom_mock_object::my_method", to_string( MOCK_MOCKER( m, my_method ) ) );
BOOST_CHECK_EQUAL( "m my_custom_mock_object::my_method_2", to_string( MOCK_ANONYMOUS_MOCKER_EXT( m, my_method_2 ) ) );
BOOST_CHECK_EQUAL( "m my_custom_mock_object::my_method", to_string( MOCK_ANONYMOUS_MOCKER_EXT( m, my_method ) ) );
BOOST_CHECK_EQUAL( "m my_custom_mock_object::my_method_2", to_string( MOCK_ANONYMOUS_MOCKER( m, my_method_2 ) ) );
BOOST_CHECK_EQUAL( "m my_custom_mock_object::my_method", to_string( MOCK_ANONYMOUS_MOCKER( m, my_method ) ) );
BOOST_CHECK_EQUAL( "m my_custom_mock_object::my_method", to_string( MOCK_MOCKER( m, my_method ) ) );
}

View file

@ -19,39 +19,43 @@ namespace
BOOST_AUTO_TEST_CASE( verifying_an_empty_object_succeeds )
{
mock::object o;
BOOST_CHECK( o.verify() );
BOOST_CHECK( mock::verify( o ) );
}
BOOST_AUTO_TEST_CASE( verifying_an_object_containing_a_failing_expectation_fails )
namespace
{
struct fixture
{
fixture()
{
mock::detail::configure( o, e, "instance", "type", "name" );
}
mock::object o;
mock::function< void() > e;
o.set_child( e );
};
}
BOOST_FIXTURE_TEST_CASE( verifying_an_object_containing_a_failing_expectation_fails, fixture )
{
e.expect().once();
BOOST_CHECK( ! o.verify() );
o.reset();
BOOST_CHECK( o.verify() );
BOOST_CHECK( ! mock::verify( o ) );
mock::reset( o );
BOOST_CHECK( mock::verify( o ) );
}
BOOST_AUTO_TEST_CASE( verifying_all_objects_with_one_of_them_containing_a_failing_expectation_fails )
BOOST_FIXTURE_TEST_CASE( verifying_all_objects_with_one_of_them_containing_a_failing_expectation_fails, fixture )
{
mock::object o;
mock::function< void() > e;
o.set_child( e );
e.expect().once();
BOOST_CHECK( ! mock::verify() );
mock::reset();
BOOST_CHECK( mock::verify() );
}
BOOST_AUTO_TEST_CASE( resetting_an_object_containing_a_failing_expectation_and_verifying_it_succeeds )
BOOST_FIXTURE_TEST_CASE( resetting_an_object_containing_a_failing_expectation_and_verifying_it_succeeds, fixture )
{
mock::object o;
mock::function< void() > e;
o.set_child( e );
e.expect().once();
o.reset();
BOOST_CHECK( o.verify() );
mock::reset( o );
BOOST_CHECK( mock::verify( o ) );
}
BOOST_AUTO_TEST_CASE( an_object_is_assignable_by_sharing_its_state )
@ -60,13 +64,13 @@ BOOST_AUTO_TEST_CASE( an_object_is_assignable_by_sharing_its_state )
mock::function< void() > e;
{
mock::object o2;
o2.set_child( e );
mock::detail::configure( o2, e, "instance", "type", "name" );
e.expect().once();
o1 = o2;
BOOST_CHECK( ! o2.verify() );
BOOST_CHECK( ! o1.verify() );
BOOST_CHECK( ! mock::verify( o2 ) );
BOOST_CHECK( ! mock::verify( o1 ) );
}
BOOST_CHECK( ! o1.verify() );
BOOST_CHECK( ! mock::verify( o1 ) );
}
BOOST_AUTO_TEST_CASE( an_object_is_copiable_by_sharing_its_state )
@ -74,20 +78,10 @@ BOOST_AUTO_TEST_CASE( an_object_is_copiable_by_sharing_its_state )
std::auto_ptr< mock::object > o2( new mock::object );
const mock::object o1( *o2 );
mock::function< void() > e;
o2->set_child( e );
mock::detail::configure( *o2, e, "instance", "type", "name" );
e.expect().once();
BOOST_CHECK( ! o2->verify() );
BOOST_CHECK( ! o1.verify() );
BOOST_CHECK( ! mock::verify( *o2 ) );
BOOST_CHECK( ! mock::verify( o1 ) );
o2.reset();
BOOST_CHECK( ! o1.verify() );
}
BOOST_AUTO_TEST_CASE( an_object_can_be_destroyed_before_its_children_functions )
{
mock::function< void() > f;
{
mock::object o;
o.set_child( f );
}
f.test();
BOOST_CHECK( ! mock::verify( o1 ) );
}