mirror of
https://github.com/mat007/turtle.git
synced 2026-06-22 12:13:43 +00:00
Changed project layout to boost layout
git-svn-id: https://svn.code.sf.net/p/turtle/code/trunk@459 860be788-9bd5-4423-9f1e-828f051e677b
This commit is contained in:
parent
cb6204b399
commit
b22842eade
89 changed files with 353 additions and 295 deletions
220
turtle/action.hpp
Normal file
220
turtle/action.hpp
Normal file
|
|
@ -0,0 +1,220 @@
|
|||
//
|
||||
// Copyright Mathieu Champlon 2008
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
// See http://turtle.sf.net for documentation.
|
||||
|
||||
#ifndef MOCK_ACTION_HPP_INCLUDED
|
||||
#define MOCK_ACTION_HPP_INCLUDED
|
||||
|
||||
#include "lambda.hpp"
|
||||
#include <boost/type_traits/remove_reference.hpp>
|
||||
#include <boost/type_traits/remove_const.hpp>
|
||||
#include <boost/shared_ptr.hpp>
|
||||
#include <boost/function.hpp>
|
||||
#include <boost/ref.hpp>
|
||||
|
||||
namespace mock
|
||||
{
|
||||
namespace detail
|
||||
{
|
||||
template< typename Result, typename Signature >
|
||||
class action
|
||||
{
|
||||
typedef BOOST_DEDUCED_TYPENAME
|
||||
boost::function< Signature > functor_type;
|
||||
typedef BOOST_DEDUCED_TYPENAME
|
||||
boost::remove_reference<
|
||||
BOOST_DEDUCED_TYPENAME boost::remove_const< Result >::type
|
||||
>::type result_type;
|
||||
|
||||
typedef lambda< Result, Signature > lambda_type;
|
||||
|
||||
public:
|
||||
template< typename Value >
|
||||
void returns( Value v )
|
||||
{
|
||||
// if an error is generated by the line below it means a value
|
||||
// passed to 'returns' was of the wrong type as it cannot be
|
||||
// used to copy construct a Result
|
||||
r_.reset( new result_type( v ) );
|
||||
f_ = lambda_type::make_val( boost::ref( *r_ ) );
|
||||
}
|
||||
template< typename Y >
|
||||
void returns( boost::reference_wrapper< Y > r )
|
||||
{
|
||||
f_ = lambda_type::make_val( r );
|
||||
}
|
||||
|
||||
void calls( const functor_type& f )
|
||||
{
|
||||
if( !f )
|
||||
throw std::invalid_argument( "null functor" );
|
||||
f_ = f;
|
||||
}
|
||||
|
||||
template< typename Exception >
|
||||
void throws( Exception e )
|
||||
{
|
||||
f_ = lambda_type::make_throw( e );
|
||||
}
|
||||
|
||||
const functor_type& functor() const
|
||||
{
|
||||
return f_;
|
||||
}
|
||||
|
||||
private:
|
||||
boost::shared_ptr< result_type > r_;
|
||||
functor_type f_;
|
||||
};
|
||||
|
||||
template< typename Result, typename Signature >
|
||||
class action< Result*, Signature >
|
||||
{
|
||||
typedef BOOST_DEDUCED_TYPENAME
|
||||
boost::function< Signature > functor_type;
|
||||
|
||||
typedef lambda< Result*, Signature > lambda_type;
|
||||
|
||||
public:
|
||||
void returns( Result* r )
|
||||
{
|
||||
f_ = lambda_type::make_val( r );
|
||||
}
|
||||
template< typename Y >
|
||||
void returns( boost::reference_wrapper< Y > r )
|
||||
{
|
||||
f_ = lambda_type::make_val( r );
|
||||
}
|
||||
|
||||
void calls( const functor_type& f )
|
||||
{
|
||||
if( !f )
|
||||
throw std::invalid_argument( "null functor" );
|
||||
f_ = f;
|
||||
}
|
||||
|
||||
template< typename Exception >
|
||||
void throws( Exception e )
|
||||
{
|
||||
f_ = lambda_type::make_throw( e );
|
||||
}
|
||||
|
||||
const functor_type& functor() const
|
||||
{
|
||||
return f_;
|
||||
}
|
||||
|
||||
private:
|
||||
functor_type f_;
|
||||
};
|
||||
|
||||
template< typename Signature >
|
||||
class action< void, Signature >
|
||||
{
|
||||
typedef BOOST_DEDUCED_TYPENAME
|
||||
boost::function< Signature > functor_type;
|
||||
|
||||
typedef lambda< void, Signature > lambda_type;
|
||||
|
||||
public:
|
||||
action()
|
||||
: f_( lambda_type::make_nothing() )
|
||||
{}
|
||||
|
||||
void calls( const functor_type& f )
|
||||
{
|
||||
if( !f )
|
||||
throw std::invalid_argument( "null functor" );
|
||||
f_ = f;
|
||||
}
|
||||
|
||||
template< typename Exception >
|
||||
void throws( Exception e )
|
||||
{
|
||||
f_ = lambda_type::make_throw( e );
|
||||
}
|
||||
|
||||
const functor_type& functor() const
|
||||
{
|
||||
return f_;
|
||||
}
|
||||
|
||||
private:
|
||||
functor_type f_;
|
||||
};
|
||||
|
||||
template< typename Result, typename Signature >
|
||||
class action< std::auto_ptr< Result >, Signature >
|
||||
{
|
||||
typedef BOOST_DEDUCED_TYPENAME
|
||||
boost::function< Signature > functor_type;
|
||||
|
||||
typedef lambda< std::auto_ptr< Result >, Signature > lambda_type;
|
||||
|
||||
public:
|
||||
action()
|
||||
{}
|
||||
action( const action& rhs )
|
||||
: r_( const_cast< action& >( rhs ).r_.release() )
|
||||
, f_( r_.get()
|
||||
? lambda_type::make_val( boost::ref( r_ ) )
|
||||
: rhs.f_ )
|
||||
{}
|
||||
|
||||
template< typename Value >
|
||||
void returns( Value v )
|
||||
{
|
||||
set( v );
|
||||
}
|
||||
|
||||
void calls( const functor_type& f )
|
||||
{
|
||||
if( !f )
|
||||
throw std::invalid_argument( "null functor" );
|
||||
f_ = f;
|
||||
}
|
||||
|
||||
template< typename Exception >
|
||||
void throws( Exception e )
|
||||
{
|
||||
f_ = lambda_type::make_throw( e );
|
||||
r_.reset();
|
||||
}
|
||||
|
||||
const functor_type& functor() const
|
||||
{
|
||||
return f_;
|
||||
}
|
||||
|
||||
private:
|
||||
template< typename Y >
|
||||
void set( std::auto_ptr< Y > r )
|
||||
{
|
||||
r_ = r;
|
||||
f_ = lambda_type::make_val( boost::ref( r_ ) );
|
||||
}
|
||||
template< typename Y >
|
||||
void set( boost::reference_wrapper< Y > r )
|
||||
{
|
||||
f_ = lambda_type::make_val( r );
|
||||
r_.reset();
|
||||
}
|
||||
template< typename Y >
|
||||
void set( Y* r )
|
||||
{
|
||||
r_.reset( r );
|
||||
f_ = lambda_type::make_val( boost::ref( r_ ) );
|
||||
}
|
||||
|
||||
std::auto_ptr< Result > r_;
|
||||
functor_type f_;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
#endif // MOCK_ACTION_HPP_INCLUDED
|
||||
70
turtle/args.hpp
Normal file
70
turtle/args.hpp
Normal file
|
|
@ -0,0 +1,70 @@
|
|||
//
|
||||
// Copyright Mathieu Champlon 2010
|
||||
//
|
||||
// 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)
|
||||
//
|
||||
// See http://turtle.sf.net for documentation.
|
||||
|
||||
#ifndef MOCK_ARGS_HPP_INCLUDED
|
||||
#define MOCK_ARGS_HPP_INCLUDED
|
||||
|
||||
#include <boost/function_types/parameter_types.hpp>
|
||||
#include <boost/function_types/function_arity.hpp>
|
||||
#include <boost/preprocessor/arithmetic/inc.hpp>
|
||||
#include <boost/mpl/at.hpp>
|
||||
|
||||
namespace mock
|
||||
{
|
||||
namespace detail
|
||||
{
|
||||
struct invalid_type
|
||||
{
|
||||
private:
|
||||
invalid_type();
|
||||
};
|
||||
|
||||
template< typename S, int n, bool B >
|
||||
struct arg_imp
|
||||
{
|
||||
typedef invalid_type type;
|
||||
};
|
||||
template< typename S, int n >
|
||||
struct arg_imp< S, n, true >
|
||||
{
|
||||
typedef BOOST_DEDUCED_TYPENAME
|
||||
boost::mpl::at_c<
|
||||
BOOST_DEDUCED_TYPENAME
|
||||
boost::function_types::parameter_types< S >,
|
||||
n - 1
|
||||
>::type type;
|
||||
};
|
||||
template< typename S, int n, int N >
|
||||
struct arg :
|
||||
arg_imp< S, n, boost::function_types::function_arity< S >::value == N >
|
||||
{
|
||||
BOOST_MPL_ASSERT_RELATION( n, >, 0 );
|
||||
BOOST_MPL_ASSERT_RELATION( n, <=, N );
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
#define MOCK_ARG(N, n, S, tpn) \
|
||||
BOOST_PP_COMMA_IF(n) tpn \
|
||||
mock::detail::arg< S, BOOST_PP_INC(n), N >::type p##n
|
||||
#define MOCK_ARG_PROXY(z, n, d) \
|
||||
MOCK_ARG( \
|
||||
BOOST_PP_ARRAY_ELEM(0, d), \
|
||||
n, \
|
||||
BOOST_PP_ARRAY_ELEM(1, d), \
|
||||
BOOST_PP_ARRAY_ELEM(2, d) )
|
||||
|
||||
#define MOCK_ARGS(n, S, tpn) \
|
||||
BOOST_PP_REPEAT(n, MOCK_ARG_PROXY, (3, (n, S, tpn)))
|
||||
|
||||
#define MOCK_DECL(M, n, S, c, tpn) \
|
||||
tpn boost::function_types::result_type< S >::type M( \
|
||||
MOCK_ARGS(n, S, tpn) ) c
|
||||
|
||||
#endif // MOCK_ARGS_HPP_INCLUDED
|
||||
99
turtle/boost_test_error.hpp
Normal file
99
turtle/boost_test_error.hpp
Normal file
|
|
@ -0,0 +1,99 @@
|
|||
//
|
||||
// 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)
|
||||
//
|
||||
// See http://turtle.sf.net for documentation.
|
||||
|
||||
#ifndef MOCK_BOOST_TEST_ERROR_POLICY_HPP_INCLUDED
|
||||
#define MOCK_BOOST_TEST_ERROR_POLICY_HPP_INCLUDED
|
||||
|
||||
#include <boost/test/framework.hpp>
|
||||
#include <boost/test/test_tools.hpp>
|
||||
#include <boost/test/unit_test_suite.hpp>
|
||||
#include <boost/test/execution_monitor.hpp>
|
||||
#include <boost/exception/enable_current_exception.hpp>
|
||||
|
||||
namespace mock
|
||||
{
|
||||
struct exception : public boost::execution_aborted
|
||||
{};
|
||||
|
||||
template< typename Result >
|
||||
struct boost_test_error_policy
|
||||
{
|
||||
static Result abort()
|
||||
{
|
||||
boost::unit_test::framework::test_unit_aborted(
|
||||
boost::unit_test::framework::current_test_case() );
|
||||
throw boost::enable_current_exception( exception() );
|
||||
}
|
||||
|
||||
static void checkpoint( const char* file, int line )
|
||||
{
|
||||
boost::unit_test::unit_test_log.set_checkpoint( file,
|
||||
static_cast< std::size_t >( line ) );
|
||||
}
|
||||
|
||||
template< typename Context >
|
||||
static void fail(
|
||||
const char* message, const Context& context,
|
||||
const char* 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,
|
||||
static_cast< std::size_t >( line ) )
|
||||
<< boost::unit_test::log_all_errors
|
||||
<< message << ": " << context
|
||||
<< boost::unit_test::log::end();
|
||||
}
|
||||
|
||||
template< typename Context >
|
||||
static void expected_call( const Context& context,
|
||||
const char* file, int line )
|
||||
{
|
||||
boost::unit_test::framework::assertion_result( true );
|
||||
boost::unit_test::unit_test_log
|
||||
<< boost::unit_test::log::begin( file,
|
||||
static_cast< std::size_t >( line ) )
|
||||
<< boost::unit_test::log_successful_tests
|
||||
<< "mock expectation fulfilled: " << context
|
||||
<< boost::unit_test::log::end();
|
||||
}
|
||||
|
||||
template< typename Context >
|
||||
static void missing_action( const Context& context,
|
||||
const char* file, int line )
|
||||
{
|
||||
fail( "missing action", context, file, line );
|
||||
}
|
||||
template< typename Context >
|
||||
static void unexpected_call( const Context& context )
|
||||
{
|
||||
fail( "unexpected call", context );
|
||||
}
|
||||
template< typename Context >
|
||||
static void sequence_failed( const Context& context,
|
||||
const char* file, int line )
|
||||
{
|
||||
fail( "sequence failed", context, file, line );
|
||||
}
|
||||
template< typename Context >
|
||||
static void verification_failed( const Context& context,
|
||||
const char* file, int line )
|
||||
{
|
||||
fail( "verification failed", context, file, line );
|
||||
}
|
||||
template< typename Context >
|
||||
static void untriggered_expectation( const Context& context,
|
||||
const char* file, int line )
|
||||
{
|
||||
fail( "untriggered expectation", context, file, line );
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#endif // MOCK_BOOST_TEST_ERROR_POLICY_HPP_INCLUDED
|
||||
108
turtle/check.hpp
Normal file
108
turtle/check.hpp
Normal file
|
|
@ -0,0 +1,108 @@
|
|||
//
|
||||
// Copyright Mathieu Champlon 2008
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
// See http://turtle.sf.net for documentation.
|
||||
|
||||
#ifndef MOCK_CHECK_HPP_INCLUDED
|
||||
#define MOCK_CHECK_HPP_INCLUDED
|
||||
|
||||
#include "is_functor.hpp"
|
||||
#include "operators.hpp"
|
||||
#include "log.hpp"
|
||||
#include <boost/utility/enable_if.hpp>
|
||||
#include <boost/noncopyable.hpp>
|
||||
#include <boost/ref.hpp>
|
||||
|
||||
namespace mock
|
||||
{
|
||||
namespace detail
|
||||
{
|
||||
template< typename Actual >
|
||||
class check_base : boost::noncopyable
|
||||
{
|
||||
public:
|
||||
virtual ~check_base() {}
|
||||
|
||||
virtual bool operator()( Actual ) = 0;
|
||||
|
||||
friend std::ostream& operator<<( std::ostream& s, const check_base& c )
|
||||
{
|
||||
c.serialize( s );
|
||||
return s;
|
||||
}
|
||||
private:
|
||||
virtual void serialize( 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 )
|
||||
{}
|
||||
private:
|
||||
virtual bool operator()( Actual actual )
|
||||
{
|
||||
return actual == boost::unwrap_ref( expected_ );
|
||||
}
|
||||
virtual void serialize( 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_ )
|
||||
{}
|
||||
private:
|
||||
virtual bool operator()( Actual actual )
|
||||
{
|
||||
return c_( actual );
|
||||
}
|
||||
virtual void serialize( 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<
|
||||
detail::is_functor< Functor >
|
||||
>::type
|
||||
> : public check_base< Actual >
|
||||
{
|
||||
public:
|
||||
explicit check( const Functor& f )
|
||||
: f_( f )
|
||||
{}
|
||||
private:
|
||||
virtual bool operator()( Actual actual )
|
||||
{
|
||||
return f_( actual );
|
||||
}
|
||||
virtual void serialize( std::ostream& s ) const
|
||||
{
|
||||
s << mock::format( f_ );
|
||||
}
|
||||
private:
|
||||
Functor f_;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
#endif // MOCK_CHECK_HPP_INCLUDED
|
||||
52
turtle/child.hpp
Normal file
52
turtle/child.hpp
Normal file
|
|
@ -0,0 +1,52 @@
|
|||
//
|
||||
// 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)
|
||||
//
|
||||
// See http://turtle.sf.net for documentation.
|
||||
|
||||
#ifndef MOCK_CHILD_HPP_INCLUDED
|
||||
#define MOCK_CHILD_HPP_INCLUDED
|
||||
|
||||
#include "parent.hpp"
|
||||
#include "type_name.hpp"
|
||||
#include <boost/test/utils/basic_cstring/basic_cstring.hpp>
|
||||
#include <boost/optional.hpp>
|
||||
#include <ostream>
|
||||
|
||||
namespace mock
|
||||
{
|
||||
namespace detail
|
||||
{
|
||||
class child
|
||||
{
|
||||
public:
|
||||
child()
|
||||
: parent_( 0 )
|
||||
{}
|
||||
void update( parent& p,
|
||||
boost::unit_test::const_string instance,
|
||||
const boost::optional< type_name >& type,
|
||||
boost::unit_test::const_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_;
|
||||
boost::unit_test::const_string name_;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
#endif // MOCK_CHILD_HPP_INCLUDED
|
||||
40
turtle/cleanup.hpp
Normal file
40
turtle/cleanup.hpp
Normal file
|
|
@ -0,0 +1,40 @@
|
|||
//
|
||||
// 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)
|
||||
//
|
||||
// See http://turtle.sf.net for documentation.
|
||||
|
||||
#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()
|
||||
{
|
||||
// $$$$ MAT : because of a bug in Boost.Test
|
||||
// this will crash if anything needs to be logged
|
||||
//mock::verify();
|
||||
mock::reset();
|
||||
}
|
||||
};
|
||||
BOOST_GLOBAL_FIXTURE( cleanup );
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#endif // MOCK_CLEANUP_HPP_INCLUDED
|
||||
48
turtle/config.hpp
Normal file
48
turtle/config.hpp
Normal file
|
|
@ -0,0 +1,48 @@
|
|||
//
|
||||
// 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)
|
||||
//
|
||||
// See http://turtle.sf.net for documentation.
|
||||
|
||||
#ifndef MOCK_CONFIG_HPP_INCLUDED
|
||||
#define MOCK_CONFIG_HPP_INCLUDED
|
||||
|
||||
#include <boost/preprocessor/arithmetic/inc.hpp>
|
||||
#include <boost/preprocessor/comparison/less.hpp>
|
||||
|
||||
#ifndef MOCK_MAX_ARGS
|
||||
# define MOCK_MAX_ARGS 9
|
||||
#elif BOOST_PP_LESS(9, MOCK_MAX_ARGS)
|
||||
# define MOCK_USE_BOOST_PHOENIX
|
||||
#endif
|
||||
|
||||
#ifndef BOOST_FUNCTION_MAX_ARGS
|
||||
# define BOOST_FUNCTION_MAX_ARGS MOCK_MAX_ARGS
|
||||
#elif BOOST_PP_LESS(BOOST_FUNCTION_MAX_ARGS, MOCK_MAX_ARGS)
|
||||
# error BOOST_FUNCTION_MAX_ARGS must be set to MOCK_MAX_ARGS or higher
|
||||
#endif
|
||||
|
||||
#ifndef BOOST_FT_MAX_ARITY
|
||||
# define BOOST_FT_MAX_ARITY BOOST_PP_INC(MOCK_MAX_ARGS)
|
||||
#elif BOOST_PP_LESS_EQUAL(BOOST_FT_MAX_ARITY, MOCK_MAX_ARGS)
|
||||
# error BOOST_FT_MAX_ARITY must be set to MOCK_MAX_ARGS + 1 or higher
|
||||
#endif
|
||||
|
||||
#ifdef MOCK_USE_BOOST_PHOENIX
|
||||
# ifndef PHOENIX_LIMIT
|
||||
# define PHOENIX_LIMIT MOCK_MAX_ARGS
|
||||
# elif BOOST_PP_LESS(PHOENIX_LIMIT, MOCK_MAX_ARGS)
|
||||
# error PHOENIX_LIMIT must be set to MOCK_MAX_ARGS or higher
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifndef MOCK_USE_BOOST_TEST
|
||||
# ifdef BOOST_TEST_DECL
|
||||
# define MOCK_USE_BOOST_TEST
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#endif // MOCK_CONFIG_HPP_INCLUDED
|
||||
25
turtle/constraint.hpp
Normal file
25
turtle/constraint.hpp
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
//
|
||||
// Copyright Mathieu Champlon 2008
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
// See http://turtle.sf.net for documentation.
|
||||
|
||||
#ifndef MOCK_CONSTRAINT_HPP_INCLUDED
|
||||
#define MOCK_CONSTRAINT_HPP_INCLUDED
|
||||
|
||||
namespace mock
|
||||
{
|
||||
template< typename Constraint >
|
||||
struct constraint
|
||||
{
|
||||
constraint( const Constraint& c )
|
||||
: f_( c )
|
||||
{}
|
||||
Constraint f_;
|
||||
};
|
||||
}
|
||||
|
||||
#endif // MOCK_CONSTRAINT_HPP_INCLUDED
|
||||
230
turtle/constraints.hpp
Normal file
230
turtle/constraints.hpp
Normal file
|
|
@ -0,0 +1,230 @@
|
|||
//
|
||||
// Copyright Mathieu Champlon 2008
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
// See http://turtle.sf.net for documentation.
|
||||
|
||||
#ifndef MOCK_CONSTRAINTS_HPP_INCLUDED
|
||||
#define MOCK_CONSTRAINTS_HPP_INCLUDED
|
||||
|
||||
#include "constraint.hpp"
|
||||
#include "log.hpp"
|
||||
#include <boost/ref.hpp>
|
||||
#include <boost/utility/enable_if.hpp>
|
||||
#include <boost/utility/addressof.hpp>
|
||||
#include <boost/type_traits/is_convertible.hpp>
|
||||
#include <boost/preprocessor/stringize.hpp>
|
||||
|
||||
namespace mock
|
||||
{
|
||||
#define MOCK_CONSTRAINT(N,Expr) \
|
||||
namespace detail \
|
||||
{ \
|
||||
struct N \
|
||||
{ \
|
||||
template< typename Actual > \
|
||||
bool operator()( const Actual& actual ) const \
|
||||
{ \
|
||||
return Expr; \
|
||||
} \
|
||||
friend std::ostream& operator<<( std::ostream& s, const N& ) \
|
||||
{ \
|
||||
return s << BOOST_STRINGIZE(N); \
|
||||
} \
|
||||
}; \
|
||||
} \
|
||||
template<> \
|
||||
struct constraint< detail::N > \
|
||||
{ \
|
||||
constraint() \
|
||||
{} \
|
||||
detail::N f_; \
|
||||
}; \
|
||||
const constraint< detail::N > N;
|
||||
|
||||
MOCK_CONSTRAINT(any, true && &actual)
|
||||
MOCK_CONSTRAINT(affirm, !! actual)
|
||||
MOCK_CONSTRAINT(negate, ! actual)
|
||||
MOCK_CONSTRAINT(evaluate, actual())
|
||||
|
||||
#undef MOCK_CONSTRAINT
|
||||
|
||||
#define MOCK_CONSTRAINT(N,Expr) \
|
||||
namespace detail \
|
||||
{ \
|
||||
template< typename Expected > \
|
||||
struct N \
|
||||
{ \
|
||||
explicit N( const Expected& expected ) \
|
||||
: expected_( expected ) \
|
||||
{} \
|
||||
template< typename Actual > \
|
||||
bool operator()( const Actual& actual ) const \
|
||||
{ \
|
||||
return Expr; \
|
||||
} \
|
||||
friend std::ostream& operator<<( std::ostream& s, const N& n ) \
|
||||
{ \
|
||||
return s << BOOST_STRINGIZE(N) \
|
||||
<< "( " << mock::format( n.expected_ ) << " )"; \
|
||||
} \
|
||||
Expected expected_; \
|
||||
}; \
|
||||
} \
|
||||
template< typename T > \
|
||||
constraint< detail::N< T > > N( T t ) \
|
||||
{ \
|
||||
return detail::N< T >( t ); \
|
||||
}
|
||||
|
||||
MOCK_CONSTRAINT(equal, actual == boost::unwrap_ref( expected_ ))
|
||||
MOCK_CONSTRAINT(less, actual < boost::unwrap_ref( expected_ ))
|
||||
MOCK_CONSTRAINT(greater, actual > boost::unwrap_ref( expected_ ))
|
||||
MOCK_CONSTRAINT(less_equal, actual <= boost::unwrap_ref( expected_ ))
|
||||
MOCK_CONSTRAINT(greater_equal, actual >= boost::unwrap_ref( expected_ ))
|
||||
|
||||
#undef MOCK_CONSTRAINT
|
||||
|
||||
namespace detail
|
||||
{
|
||||
template< typename Expected >
|
||||
struct same
|
||||
{
|
||||
explicit same( const Expected& expected )
|
||||
: expected_( boost::addressof( boost::unwrap_ref( expected ) ) )
|
||||
{}
|
||||
template< typename Actual >
|
||||
bool operator()( const Actual& actual ) const
|
||||
{
|
||||
return boost::addressof( actual ) == expected_;
|
||||
}
|
||||
friend std::ostream& operator<<( std::ostream& os, const same& s )
|
||||
{
|
||||
return os << "same( " << mock::format( *s.expected_ ) << " )";
|
||||
}
|
||||
const BOOST_DEDUCED_TYPENAME
|
||||
boost::unwrap_reference< Expected >::type* expected_;
|
||||
};
|
||||
|
||||
template< typename Expected >
|
||||
struct retrieve
|
||||
{
|
||||
explicit retrieve( Expected& expected )
|
||||
: expected_( boost::addressof( boost::unwrap_ref( expected ) ) )
|
||||
{}
|
||||
template< typename Actual >
|
||||
bool operator()( const Actual& actual,
|
||||
BOOST_DEDUCED_TYPENAME boost::disable_if<
|
||||
boost::is_convertible<
|
||||
const Actual*,
|
||||
BOOST_DEDUCED_TYPENAME
|
||||
boost::unwrap_reference< Expected >::type
|
||||
>
|
||||
>::type* = 0 ) const
|
||||
{
|
||||
*expected_ = actual;
|
||||
return true;
|
||||
}
|
||||
template< typename Actual >
|
||||
bool operator()( Actual& actual,
|
||||
BOOST_DEDUCED_TYPENAME boost::enable_if<
|
||||
boost::is_convertible< Actual*,
|
||||
BOOST_DEDUCED_TYPENAME
|
||||
boost::unwrap_reference< Expected >::type
|
||||
>
|
||||
>::type* = 0 ) const
|
||||
{
|
||||
*expected_ = boost::addressof( actual );
|
||||
return true;
|
||||
}
|
||||
friend std::ostream& operator<<( std::ostream& s, const retrieve& r )
|
||||
{
|
||||
return s << "retrieve( " << mock::format( *r.expected_ ) << " )";
|
||||
}
|
||||
BOOST_DEDUCED_TYPENAME
|
||||
boost::unwrap_reference< Expected >::type* expected_;
|
||||
};
|
||||
|
||||
template< typename Expected >
|
||||
struct assign
|
||||
{
|
||||
explicit assign( const Expected& expected )
|
||||
: expected_( expected )
|
||||
{}
|
||||
template< typename Actual >
|
||||
bool operator()( Actual& actual ) const
|
||||
{
|
||||
actual = boost::unwrap_ref( expected_ );
|
||||
return true;
|
||||
}
|
||||
template< typename Actual >
|
||||
bool operator()( Actual* actual,
|
||||
BOOST_DEDUCED_TYPENAME boost::enable_if<
|
||||
boost::is_convertible<
|
||||
BOOST_DEDUCED_TYPENAME
|
||||
boost::unwrap_reference< Expected >::type,
|
||||
Actual
|
||||
>
|
||||
>::type* = 0 ) const
|
||||
{
|
||||
*actual = boost::unwrap_ref( expected_ );
|
||||
return true;
|
||||
}
|
||||
friend std::ostream& operator<<( std::ostream& s, const assign& a )
|
||||
{
|
||||
return s << "assign( " << mock::format( a.expected_ ) << " )";
|
||||
}
|
||||
Expected expected_;
|
||||
};
|
||||
|
||||
template< typename Expected >
|
||||
struct contain
|
||||
{
|
||||
explicit contain( const Expected& expected )
|
||||
: expected_( expected )
|
||||
{}
|
||||
bool operator()( const std::string& actual ) const
|
||||
{
|
||||
return actual.find( boost::unwrap_ref( expected_ ) )
|
||||
!= std::string::npos;
|
||||
}
|
||||
friend std::ostream& operator<<( std::ostream& s, const contain& n )
|
||||
{
|
||||
return s << "contain( " << mock::format( n.expected_ ) << " )";
|
||||
}
|
||||
Expected expected_;
|
||||
};
|
||||
}
|
||||
|
||||
template< typename T >
|
||||
constraint< detail::same< T > > same( T& t )
|
||||
{
|
||||
return detail::same< T >( t );
|
||||
}
|
||||
template< typename T >
|
||||
constraint< detail::retrieve< T > > retrieve( T& t )
|
||||
{
|
||||
return detail::retrieve< T >( t );
|
||||
}
|
||||
template< typename T >
|
||||
constraint< detail::assign< T > > assign( T t )
|
||||
{
|
||||
return detail::assign< T >( t );
|
||||
}
|
||||
template< typename T >
|
||||
constraint< detail::contain< T > > contain( T t )
|
||||
{
|
||||
return detail::contain< T >( t );
|
||||
}
|
||||
|
||||
template< typename T >
|
||||
constraint< T > call( T t )
|
||||
{
|
||||
return t;
|
||||
}
|
||||
}
|
||||
|
||||
#endif // MOCK_CONSTRAINTS_HPP_INCLUDED
|
||||
44
turtle/context.hpp
Normal file
44
turtle/context.hpp
Normal file
|
|
@ -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)
|
||||
//
|
||||
// See http://turtle.sf.net for documentation.
|
||||
|
||||
#ifndef MOCK_CONTEXT_HPP_INCLUDED
|
||||
#define MOCK_CONTEXT_HPP_INCLUDED
|
||||
|
||||
#include "type_name.hpp"
|
||||
#include <boost/noncopyable.hpp>
|
||||
#include <boost/optional.hpp>
|
||||
#include <boost/test/utils/basic_cstring/basic_cstring.hpp>
|
||||
#include <ostream>
|
||||
|
||||
namespace mock
|
||||
{
|
||||
namespace detail
|
||||
{
|
||||
class verifiable;
|
||||
|
||||
class context : boost::noncopyable
|
||||
{
|
||||
public:
|
||||
context() {}
|
||||
virtual ~context() {}
|
||||
|
||||
virtual void add( const void* p, verifiable& v,
|
||||
boost::unit_test::const_string instance,
|
||||
const boost::optional< type_name >& type,
|
||||
boost::unit_test::const_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
|
||||
77
turtle/default_error.hpp
Normal file
77
turtle/default_error.hpp
Normal file
|
|
@ -0,0 +1,77 @@
|
|||
//
|
||||
// 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)
|
||||
//
|
||||
// See http://turtle.sf.net for documentation.
|
||||
|
||||
#ifndef MOCK_DEFAULT_ERROR_POLICY_HPP_INCLUDED
|
||||
#define MOCK_DEFAULT_ERROR_POLICY_HPP_INCLUDED
|
||||
|
||||
#include <iostream>
|
||||
|
||||
namespace mock
|
||||
{
|
||||
struct exception
|
||||
{};
|
||||
|
||||
template< typename Result >
|
||||
struct default_error_policy
|
||||
{
|
||||
static Result abort()
|
||||
{
|
||||
throw exception();
|
||||
}
|
||||
|
||||
static void checkpoint( const char* /*file*/, int /*line*/ )
|
||||
{}
|
||||
|
||||
template< typename Context >
|
||||
static void fail(
|
||||
const char* message, const Context& context,
|
||||
const char* file = "unknown location", int line = 0 )
|
||||
{
|
||||
std::cerr << file << '(' << line << "): "
|
||||
<< message << ": " << context << std::endl;
|
||||
}
|
||||
|
||||
template< typename Context >
|
||||
static void expected_call( const Context& /*context*/,
|
||||
const char* /*file*/, int /*line*/ )
|
||||
{}
|
||||
|
||||
template< typename Context >
|
||||
static void missing_action( const Context& context,
|
||||
const char* file, int line )
|
||||
{
|
||||
fail( "missing action", context, file, line );
|
||||
}
|
||||
template< typename Context >
|
||||
static void unexpected_call( const Context& context )
|
||||
{
|
||||
fail( "unexpected call", context );
|
||||
}
|
||||
template< typename Context >
|
||||
static void sequence_failed( const Context& context,
|
||||
const char* file, int line )
|
||||
{
|
||||
fail( "sequence failed", context, file, line );
|
||||
}
|
||||
template< typename Context >
|
||||
static void verification_failed( const Context& context,
|
||||
const char* file, int line )
|
||||
{
|
||||
fail( "verification failed", context, file, line );
|
||||
}
|
||||
template< typename Context >
|
||||
static void untriggered_expectation( const Context& context,
|
||||
const char* file, int line )
|
||||
{
|
||||
fail( "untriggered expectation", context, file, line );
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#endif // MOCK_DEFAULT_ERROR_POLICY_HPP_INCLUDED
|
||||
25
turtle/error.hpp
Normal file
25
turtle/error.hpp
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
//
|
||||
// Copyright Mathieu Champlon 2008
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
// See http://turtle.sf.net for documentation.
|
||||
|
||||
#ifndef MOCK_ERROR_HPP_INCLUDED
|
||||
#define MOCK_ERROR_HPP_INCLUDED
|
||||
|
||||
#include "config.hpp"
|
||||
|
||||
#ifndef MOCK_ERROR_POLICY
|
||||
# ifdef MOCK_USE_BOOST_TEST
|
||||
# define MOCK_ERROR_POLICY boost_test_error_policy
|
||||
# include "boost_test_error.hpp"
|
||||
# else
|
||||
# define MOCK_ERROR_POLICY default_error_policy
|
||||
# include "default_error.hpp"
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#endif // MOCK_ERROR_HPP_INCLUDED
|
||||
262
turtle/expectation.hpp
Normal file
262
turtle/expectation.hpp
Normal file
|
|
@ -0,0 +1,262 @@
|
|||
//
|
||||
// Copyright Mathieu Champlon 2008
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
// See http://turtle.sf.net for documentation.
|
||||
|
||||
#ifndef MOCK_EXPECTATION_HPP_INCLUDED
|
||||
#define MOCK_EXPECTATION_HPP_INCLUDED
|
||||
|
||||
#include "config.hpp"
|
||||
#include "invocation.hpp"
|
||||
#include "action.hpp"
|
||||
#include "sequence.hpp"
|
||||
#include "check.hpp"
|
||||
#include "constraints.hpp"
|
||||
#include <boost/shared_ptr.hpp>
|
||||
#include <boost/preprocessor/repetition/repeat_from_to.hpp>
|
||||
#include <boost/preprocessor/repetition/enum_params.hpp>
|
||||
#include <boost/preprocessor/repetition/enum_binary_params.hpp>
|
||||
#include <boost/function_types/parameter_types.hpp>
|
||||
#include <boost/function_types/result_type.hpp>
|
||||
#include <boost/mpl/at.hpp>
|
||||
#include <ostream>
|
||||
#include <vector>
|
||||
|
||||
namespace mock
|
||||
{
|
||||
namespace detail
|
||||
{
|
||||
class expectation_base
|
||||
{
|
||||
public:
|
||||
expectation_base()
|
||||
: i_( new detail::unlimited() )
|
||||
, file_( "unknown location" )
|
||||
, line_( 0 )
|
||||
{}
|
||||
void set_location( const char* file, int line )
|
||||
{
|
||||
file_ = file;
|
||||
line_ = line;
|
||||
}
|
||||
|
||||
bool verify() const
|
||||
{
|
||||
return i_->verify();
|
||||
}
|
||||
|
||||
bool invoke() const
|
||||
{
|
||||
for( sequences_cit it = sequences_.begin();
|
||||
it != sequences_.end(); ++it )
|
||||
if( ! (*it)->is_valid( this ) )
|
||||
return false;
|
||||
bool result = i_->invoke();
|
||||
for( sequences_cit it = sequences_.begin();
|
||||
it != sequences_.end(); ++it )
|
||||
(*it)->invalidate( this );
|
||||
return result;
|
||||
}
|
||||
|
||||
bool invoked() const
|
||||
{
|
||||
return i_->invoked();
|
||||
}
|
||||
|
||||
const char* file() const
|
||||
{
|
||||
return file_;
|
||||
}
|
||||
int line() const
|
||||
{
|
||||
return line_;
|
||||
}
|
||||
|
||||
protected:
|
||||
~expectation_base()
|
||||
{
|
||||
for( sequences_cit it = sequences_.begin();
|
||||
it != sequences_.end(); ++it )
|
||||
(*it)->remove( this );
|
||||
}
|
||||
|
||||
void expect( detail::invocation* i )
|
||||
{
|
||||
i_.reset( i );
|
||||
}
|
||||
|
||||
void add( boost::shared_ptr< detail::sequence_impl > s )
|
||||
{
|
||||
s->add( this );
|
||||
sequences_.push_back( s );
|
||||
}
|
||||
|
||||
boost::shared_ptr< detail::invocation > i_;
|
||||
|
||||
private:
|
||||
typedef std::vector<
|
||||
boost::shared_ptr< detail::sequence_impl >
|
||||
> sequences_type;
|
||||
typedef sequences_type::const_iterator sequences_cit;
|
||||
|
||||
sequences_type sequences_;
|
||||
const char* file_;
|
||||
int line_;
|
||||
};
|
||||
|
||||
template< typename Signature, int Arity >
|
||||
class expectation
|
||||
{
|
||||
};
|
||||
|
||||
#define MOCK_EXPECTATION_METHODS \
|
||||
expectation& in( sequence& s ) \
|
||||
{ \
|
||||
add( s.impl_ ); \
|
||||
return *this; \
|
||||
} \
|
||||
expectation& once() \
|
||||
{ \
|
||||
expect( new detail::once() ); \
|
||||
return *this; \
|
||||
} \
|
||||
expectation& never() \
|
||||
{ \
|
||||
expect( new detail::never() ); \
|
||||
return *this; \
|
||||
} \
|
||||
expectation& exactly( std::size_t count ) \
|
||||
{ \
|
||||
expect( new detail::exactly( count ) ); \
|
||||
return *this; \
|
||||
} \
|
||||
expectation& at_least( std::size_t min ) \
|
||||
{ \
|
||||
expect( new detail::at_least( min ) ); \
|
||||
return *this; \
|
||||
} \
|
||||
expectation& at_most( std::size_t max ) \
|
||||
{ \
|
||||
expect( new detail::at_most( max ) ); \
|
||||
return *this; \
|
||||
} \
|
||||
expectation& between( std::size_t min, std::size_t max ) \
|
||||
{ \
|
||||
expect( new detail::between( min, max ) ); \
|
||||
return *this; \
|
||||
}
|
||||
|
||||
template< typename Signature >
|
||||
class expectation< Signature, 0 >
|
||||
: public expectation_base
|
||||
, public action< BOOST_DEDUCED_TYPENAME
|
||||
boost::function_types::result_type< Signature >::type, Signature >
|
||||
{
|
||||
public:
|
||||
bool is_valid() const
|
||||
{
|
||||
return ! i_->exhausted();
|
||||
}
|
||||
|
||||
MOCK_EXPECTATION_METHODS
|
||||
|
||||
friend std::ostream& operator<<( std::ostream& s,
|
||||
const expectation& m )
|
||||
{
|
||||
return s << (m.i_->exhausted() ? 'v' : '.') << ' ' << *m.i_;
|
||||
}
|
||||
};
|
||||
|
||||
#define MOCK_EXPECTATION_TYPEDEF(z, n, d) \
|
||||
typedef BOOST_DEDUCED_TYPENAME \
|
||||
boost::mpl::at_c< \
|
||||
BOOST_DEDUCED_TYPENAME \
|
||||
boost::function_types::parameter_types< Signature >, \
|
||||
n \
|
||||
>::type arg##n##_type;
|
||||
#define MOCK_EXPECTATION_INITIALIZE(z, n, d) \
|
||||
BOOST_PP_COMMA_IF(n) c##n##_( \
|
||||
new detail::check< \
|
||||
arg##n##_type, \
|
||||
constraint< detail::any > \
|
||||
>( mock::any ) )
|
||||
#define MOCK_EXPECTATION_WITH(z, n, d) \
|
||||
c##n##_.reset( \
|
||||
new detail::check< \
|
||||
arg##n##_type, \
|
||||
Constraint_##n \
|
||||
>( c##n ) );
|
||||
#define MOCK_EXPECTATION_MEMBER(z, n, d) \
|
||||
boost::shared_ptr< detail::check_base< arg##n##_type > > c##n##_;
|
||||
#define MOCK_EXPECTATION_ARGS(z, n, d) \
|
||||
BOOST_PP_COMMA_IF(n) arg##n##_type a##n
|
||||
#define MOCK_EXPECTATION_IS_VALID(z, n, d) \
|
||||
&& (*c##n##_)( a##n )
|
||||
#define MOCK_EXPECTATION_SERIALIZE(z, n, d) \
|
||||
BOOST_PP_IF(n, << ", " <<,) *m.c##n##_
|
||||
#define MOCK_EXPECTATION(z, n, d) \
|
||||
template< typename Signature > \
|
||||
class expectation< Signature, n > \
|
||||
: public expectation_base \
|
||||
, public action< \
|
||||
BOOST_DEDUCED_TYPENAME \
|
||||
boost::function_types::result_type< Signature >::type, \
|
||||
Signature \
|
||||
> \
|
||||
{ \
|
||||
BOOST_PP_REPEAT(n, MOCK_EXPECTATION_TYPEDEF, BOOST_PP_EMPTY) \
|
||||
public: \
|
||||
expectation() \
|
||||
: BOOST_PP_REPEAT(n, MOCK_EXPECTATION_INITIALIZE, BOOST_PP_EMPTY) \
|
||||
{} \
|
||||
template< BOOST_PP_ENUM_PARAMS(n, typename Constraint_) > \
|
||||
expectation& with( BOOST_PP_ENUM_BINARY_PARAMS(n, Constraint_, c) ) \
|
||||
{ \
|
||||
BOOST_PP_REPEAT(n, MOCK_EXPECTATION_WITH, BOOST_PP_EMPTY) \
|
||||
return *this; \
|
||||
} \
|
||||
bool is_valid( \
|
||||
BOOST_PP_REPEAT(n, MOCK_EXPECTATION_ARGS, BOOST_PP_EMPTY) ) const \
|
||||
{ \
|
||||
return ! i_->exhausted() \
|
||||
BOOST_PP_REPEAT(n, \
|
||||
MOCK_EXPECTATION_IS_VALID, BOOST_PP_EMPTY); \
|
||||
} \
|
||||
MOCK_EXPECTATION_METHODS \
|
||||
friend std::ostream& operator<<( \
|
||||
std::ostream& s, const expectation& m ) \
|
||||
{ \
|
||||
return s << (m.i_->exhausted() ? 'v' : '.') \
|
||||
<< ' ' << *m.i_ << ".with( " \
|
||||
<< BOOST_PP_REPEAT(n, \
|
||||
MOCK_EXPECTATION_SERIALIZE, BOOST_PP_EMPTY) \
|
||||
<< " )"; \
|
||||
} \
|
||||
private: \
|
||||
BOOST_PP_REPEAT(n, MOCK_EXPECTATION_MEMBER, BOOST_PP_EMPTY) \
|
||||
};
|
||||
|
||||
BOOST_PP_REPEAT_FROM_TO(
|
||||
1,
|
||||
BOOST_PP_INC(MOCK_MAX_ARGS),
|
||||
MOCK_EXPECTATION,
|
||||
BOOST_PP_EMPTY)
|
||||
|
||||
#undef MOCK_EXPECTATION_METHODS
|
||||
#undef MOCK_EXPECTATION_TYPEDEF
|
||||
#undef MOCK_EXPECTATION_INITIALIZE
|
||||
#undef MOCK_EXPECTATION_WITH
|
||||
#undef MOCK_EXPECTATION_MEMBER
|
||||
#undef MOCK_EXPECTATION_ARGS
|
||||
#undef MOCK_EXPECTATION_IS_VALID
|
||||
#undef MOCK_EXPECTATION_SERIALIZE
|
||||
#undef MOCK_EXPECTATION
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#endif // MOCK_EXPECTATION_HPP_INCLUDED
|
||||
330
turtle/function.hpp
Normal file
330
turtle/function.hpp
Normal file
|
|
@ -0,0 +1,330 @@
|
|||
//
|
||||
// Copyright Mathieu Champlon 2008
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
// See http://turtle.sf.net for documentation.
|
||||
|
||||
#ifndef MOCK_FUNCTION_HPP_INCLUDED
|
||||
#define MOCK_FUNCTION_HPP_INCLUDED
|
||||
|
||||
#include "config.hpp"
|
||||
#include "error.hpp"
|
||||
#include "context.hpp"
|
||||
#include "expectation.hpp"
|
||||
#include "verifiable.hpp"
|
||||
#include "log.hpp"
|
||||
#include "args.hpp"
|
||||
#include "type_name.hpp"
|
||||
#include <boost/function_types/result_type.hpp>
|
||||
#include <boost/function_types/function_arity.hpp>
|
||||
#include <boost/function_types/parameter_types.hpp>
|
||||
#include <boost/preprocessor/repetition/repeat_from_to.hpp>
|
||||
#include <boost/preprocessor/repetition/enum_params.hpp>
|
||||
#include <boost/preprocessor/repetition/enum_binary_params.hpp>
|
||||
#include <boost/preprocessor/comparison/equal.hpp>
|
||||
#include <boost/test/utils/basic_cstring/basic_cstring.hpp>
|
||||
#include <boost/test/utils/lazy_ostream.hpp>
|
||||
#include <boost/enable_shared_from_this.hpp>
|
||||
#include <boost/shared_ptr.hpp>
|
||||
#include <boost/optional.hpp>
|
||||
#include <ostream>
|
||||
#include <list>
|
||||
|
||||
namespace mock
|
||||
{
|
||||
template< typename Signature >
|
||||
class function
|
||||
{
|
||||
public:
|
||||
typedef BOOST_DEDUCED_TYPENAME
|
||||
boost::function_types::result_type< Signature >::type result_type;
|
||||
|
||||
template< typename Args >
|
||||
struct sig
|
||||
{
|
||||
typedef result_type type;
|
||||
};
|
||||
|
||||
private:
|
||||
typedef BOOST_DEDUCED_TYPENAME
|
||||
boost::function_types::function_arity< Signature > arity;
|
||||
typedef BOOST_DEDUCED_TYPENAME
|
||||
detail::expectation< Signature, arity::value > expectation_type;
|
||||
|
||||
public:
|
||||
function()
|
||||
: impl_( new function_impl() )
|
||||
{}
|
||||
|
||||
bool verify() const
|
||||
{
|
||||
return impl_->verify();
|
||||
}
|
||||
bool verify( const char* file, int line ) const
|
||||
{
|
||||
function_impl::error_type::checkpoint( file, line );
|
||||
return impl_->verify();
|
||||
}
|
||||
void reset()
|
||||
{
|
||||
impl_->reset();
|
||||
}
|
||||
void reset( const char* file, int line )
|
||||
{
|
||||
function_impl::error_type::checkpoint( file, line );
|
||||
return impl_->reset();
|
||||
}
|
||||
|
||||
expectation_type& expect( const char* file, int line )
|
||||
{
|
||||
function_impl::error_type::checkpoint( file, line );
|
||||
return impl_->expect();
|
||||
}
|
||||
expectation_type& expect()
|
||||
{
|
||||
return impl_->expect();
|
||||
}
|
||||
|
||||
void test() const
|
||||
{
|
||||
impl_->test();
|
||||
}
|
||||
|
||||
result_type operator()() const
|
||||
{
|
||||
return (*impl_)();
|
||||
}
|
||||
|
||||
#define MOCK_FUNCTION_OPERATOR(z, n, d) \
|
||||
MOCK_DECL(operator(), n, Signature, const, BOOST_DEDUCED_TYPENAME) \
|
||||
{ \
|
||||
return (*impl_)( BOOST_PP_ENUM_PARAMS(n, p) ); \
|
||||
}
|
||||
|
||||
BOOST_PP_REPEAT_FROM_TO(
|
||||
1,
|
||||
BOOST_PP_INC(MOCK_MAX_ARGS),
|
||||
MOCK_FUNCTION_OPERATOR,
|
||||
BOOST_PP_EMPTY)
|
||||
|
||||
#undef MOCK_FUNCTION_OPERATOR
|
||||
|
||||
friend std::ostream& operator<<( std::ostream& s, const function& e )
|
||||
{
|
||||
return s << *e.impl_;
|
||||
}
|
||||
|
||||
function& operator()( detail::context& c,
|
||||
boost::unit_test::const_string instance )
|
||||
{
|
||||
if( ! impl_->context_ )
|
||||
c.add( *impl_ );
|
||||
c.add( impl_.get(), *impl_, instance,
|
||||
boost::optional< detail::type_name >(), "" );
|
||||
impl_->context_ = &c;
|
||||
return *this;
|
||||
}
|
||||
|
||||
void configure( detail::context& c, const void* p,
|
||||
boost::unit_test::const_string instance,
|
||||
const boost::optional< detail::type_name >& type,
|
||||
boost::unit_test::const_string name ) const
|
||||
{
|
||||
if( ! impl_->context_ )
|
||||
c.add( *impl_ );
|
||||
c.add( p, *impl_, instance, type, name );
|
||||
impl_->context_ = &c;
|
||||
}
|
||||
|
||||
private:
|
||||
class function_impl : public detail::verifiable,
|
||||
public boost::enable_shared_from_this< function_impl >
|
||||
{
|
||||
public:
|
||||
typedef MOCK_ERROR_POLICY< result_type > error_type;
|
||||
|
||||
public:
|
||||
function_impl()
|
||||
: context_( 0 )
|
||||
, valid_( true )
|
||||
{}
|
||||
virtual ~function_impl()
|
||||
{
|
||||
if( valid_ && ! std::uncaught_exception() )
|
||||
for( expectations_cit it = expectations_.begin();
|
||||
it != expectations_.end(); ++it )
|
||||
{
|
||||
if( ! it->verify() )
|
||||
error_type::untriggered_expectation(
|
||||
boost::unit_test::lazy_ostream::instance()
|
||||
<< lazy_context( this )
|
||||
<< lazy_expectations( this ),
|
||||
it->file(), it->line() );
|
||||
else if( ! it->invoked() )
|
||||
error_type::expected_call(
|
||||
boost::unit_test::lazy_ostream::instance()
|
||||
<< lazy_context( this )
|
||||
<< lazy_expectations( this ),
|
||||
it->file(), it->line() );
|
||||
}
|
||||
if( context_ )
|
||||
context_->remove( *this );
|
||||
}
|
||||
|
||||
virtual bool verify() const
|
||||
{
|
||||
for( expectations_cit it = expectations_.begin();
|
||||
it != expectations_.end(); ++it )
|
||||
if( !it->verify() )
|
||||
{
|
||||
valid_ = false;
|
||||
error_type::verification_failed(
|
||||
boost::unit_test::lazy_ostream::instance()
|
||||
<< lazy_context( this )
|
||||
<< lazy_expectations( this ),
|
||||
it->file(), it->line() );
|
||||
}
|
||||
return valid_;
|
||||
}
|
||||
|
||||
virtual void reset()
|
||||
{
|
||||
valid_ = true;
|
||||
boost::shared_ptr< function_impl > guard =
|
||||
this->shared_from_this();
|
||||
expectations_.clear();
|
||||
}
|
||||
|
||||
expectation_type& expect( const char* file, int line )
|
||||
{
|
||||
expectation_type& e = expect();
|
||||
e.set_location( file, line );
|
||||
return e;
|
||||
}
|
||||
expectation_type& expect()
|
||||
{
|
||||
expectations_.push_back( expectation_type() );
|
||||
valid_ = true;
|
||||
return expectations_.back();
|
||||
}
|
||||
|
||||
#define MOCK_FUNCTION_FORMAT(z, n, N) \
|
||||
<< " " << mock::format( p##n ) \
|
||||
<< BOOST_PP_IF(BOOST_PP_EQUAL(N,n), " ", ",")
|
||||
#define MOCK_FUNCTION_CONTEXT(n) \
|
||||
boost::unit_test::lazy_ostream::instance() \
|
||||
<< lazy_context( this ) \
|
||||
<< "(" BOOST_PP_REPEAT(n, MOCK_FUNCTION_FORMAT, BOOST_PP_DEC(n)) \
|
||||
<< ")" \
|
||||
<< lazy_expectations( this )
|
||||
#define MOCK_FUNCTION_INVOKE(z, n, A) \
|
||||
{ \
|
||||
valid_ = false; \
|
||||
for( expectations_cit it = expectations_.begin(); \
|
||||
it != expectations_.end(); ++it ) \
|
||||
if( it->is_valid( BOOST_PP_ENUM_PARAMS(n, p) ) ) \
|
||||
{ \
|
||||
if( ! it->invoke() ) \
|
||||
{ \
|
||||
error_type::sequence_failed( \
|
||||
MOCK_FUNCTION_CONTEXT(n), it->file(), it->line() ); \
|
||||
return A; \
|
||||
} \
|
||||
if( ! it->functor() ) \
|
||||
{ \
|
||||
error_type::missing_action( \
|
||||
MOCK_FUNCTION_CONTEXT(n), it->file(), it->line() ); \
|
||||
return A; \
|
||||
} \
|
||||
valid_ = true; \
|
||||
error_type::expected_call( \
|
||||
MOCK_FUNCTION_CONTEXT(n), it->file(), it->line() ); \
|
||||
return it->functor()( BOOST_PP_ENUM_PARAMS(n, p) ); \
|
||||
} \
|
||||
error_type::unexpected_call( MOCK_FUNCTION_CONTEXT(n) ); \
|
||||
return A; \
|
||||
}
|
||||
#define MOCK_FUNCTION_OPERATOR(z, n, P) \
|
||||
MOCK_DECL(operator(), n, Signature, const, BOOST_DEDUCED_TYPENAME) \
|
||||
MOCK_FUNCTION_INVOKE(z, n, P)
|
||||
|
||||
BOOST_PP_REPEAT(
|
||||
BOOST_PP_INC(MOCK_MAX_ARGS),
|
||||
MOCK_FUNCTION_OPERATOR,
|
||||
error_type::abort())
|
||||
|
||||
void test() const
|
||||
MOCK_FUNCTION_INVOKE(, 0,)
|
||||
|
||||
#undef MOCK_FUNCTION_FORMAT
|
||||
#undef MOCK_FUNCTION_OPERATOR
|
||||
#undef MOCK_FUNCTION_INVOKE
|
||||
#undef MOCK_FUNCTION_CONTEXT
|
||||
|
||||
friend std::ostream& operator<<(
|
||||
std::ostream& s, const function_impl& e )
|
||||
{
|
||||
return s << lazy_context( &e ) << lazy_expectations( &e );
|
||||
}
|
||||
|
||||
struct lazy_context
|
||||
{
|
||||
lazy_context( const function_impl* impl )
|
||||
: impl_( impl )
|
||||
{}
|
||||
friend std::ostream& operator<<(
|
||||
std::ostream& s, const lazy_context& c )
|
||||
{
|
||||
if( c.impl_->context_ )
|
||||
c.impl_->context_->serialize( s, *c.impl_ );
|
||||
else
|
||||
s << "?";
|
||||
return s;
|
||||
}
|
||||
const function_impl* impl_;
|
||||
};
|
||||
|
||||
struct lazy_expectations
|
||||
{
|
||||
lazy_expectations( const function_impl* impl )
|
||||
: impl_( impl )
|
||||
{}
|
||||
friend std::ostream& operator<<(
|
||||
std::ostream& s, const lazy_expectations& e )
|
||||
{
|
||||
for( expectations_cit it = e.impl_->expectations_.begin();
|
||||
it != e.impl_->expectations_.end(); ++it )
|
||||
s << std::endl << *it;
|
||||
return s;
|
||||
}
|
||||
const function_impl* impl_;
|
||||
};
|
||||
|
||||
typedef std::list< expectation_type > expectations_type;
|
||||
typedef BOOST_DEDUCED_TYPENAME
|
||||
expectations_type::const_iterator expectations_cit;
|
||||
|
||||
expectations_type expectations_;
|
||||
detail::context* context_;
|
||||
mutable bool valid_;
|
||||
};
|
||||
|
||||
boost::shared_ptr< function_impl > impl_;
|
||||
};
|
||||
|
||||
template< typename Signature >
|
||||
bool verify( const function< Signature >& f )
|
||||
{
|
||||
return f.verify();
|
||||
}
|
||||
template< typename Signature >
|
||||
void reset( function< Signature >& f )
|
||||
{
|
||||
f.reset();
|
||||
}
|
||||
}
|
||||
|
||||
#endif // MOCK_FUNCTION_HPP_INCLUDED
|
||||
65
turtle/group.hpp
Normal file
65
turtle/group.hpp
Normal file
|
|
@ -0,0 +1,65 @@
|
|||
//
|
||||
// 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)
|
||||
//
|
||||
// See http://turtle.sf.net for documentation.
|
||||
|
||||
#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 verifiables_t verifiables = verifiables_;
|
||||
for( verifiables_cit it = verifiables.begin();
|
||||
it != verifiables.end(); ++it )
|
||||
if( std::find( verifiables_.begin(), verifiables_.end(), *it )
|
||||
!= verifiables_.end() )
|
||||
(*it)->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
|
||||
177
turtle/invocation.hpp
Normal file
177
turtle/invocation.hpp
Normal file
|
|
@ -0,0 +1,177 @@
|
|||
//
|
||||
// Copyright Mathieu Champlon 2008
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
// See http://turtle.sf.net for documentation.
|
||||
|
||||
#ifndef MOCK_INVOCATION_HPP_INCLUDED
|
||||
#define MOCK_INVOCATION_HPP_INCLUDED
|
||||
|
||||
#include <boost/noncopyable.hpp>
|
||||
#include <stdexcept>
|
||||
#include <ostream>
|
||||
#include <limits>
|
||||
|
||||
namespace mock
|
||||
{
|
||||
namespace detail
|
||||
{
|
||||
class invocation : private boost::noncopyable
|
||||
{
|
||||
public:
|
||||
invocation() {}
|
||||
virtual ~invocation() {}
|
||||
|
||||
virtual bool invoke() = 0;
|
||||
virtual bool verify() const = 0;
|
||||
|
||||
virtual bool invoked() const = 0;
|
||||
virtual bool exhausted() const = 0;
|
||||
|
||||
friend inline std::ostream& operator<<(
|
||||
std::ostream& s, const invocation& i )
|
||||
{
|
||||
return i.serialize( s );
|
||||
}
|
||||
|
||||
private:
|
||||
virtual std::ostream& serialize( std::ostream& s ) const = 0;
|
||||
};
|
||||
|
||||
class between : public invocation
|
||||
{
|
||||
public:
|
||||
between( std::size_t min, std::size_t max )
|
||||
: min_( min )
|
||||
, max_( max )
|
||||
, count_( 0 )
|
||||
{
|
||||
if( min > max )
|
||||
throw std::invalid_argument( "'min' > 'max'" );
|
||||
}
|
||||
|
||||
virtual bool invoke()
|
||||
{
|
||||
if( count_ == max_ )
|
||||
return false;
|
||||
++count_;
|
||||
return true;
|
||||
}
|
||||
|
||||
virtual bool invoked() const
|
||||
{
|
||||
return count_ > 0;
|
||||
}
|
||||
|
||||
virtual bool exhausted() const
|
||||
{
|
||||
return count_ >= max_;
|
||||
}
|
||||
|
||||
virtual bool verify() const
|
||||
{
|
||||
return min_ <= count_ && count_ <= max_;
|
||||
}
|
||||
|
||||
protected:
|
||||
const std::size_t min_, max_;
|
||||
std::size_t count_;
|
||||
|
||||
private:
|
||||
virtual std::ostream& serialize( std::ostream& s ) const
|
||||
{
|
||||
return s << "between( " << count_
|
||||
<< "/[" << min_ << ',' << max_ << "] )";
|
||||
}
|
||||
};
|
||||
|
||||
class exactly : public between
|
||||
{
|
||||
public:
|
||||
explicit exactly( std::size_t count )
|
||||
: between( count, count )
|
||||
{}
|
||||
|
||||
private:
|
||||
virtual std::ostream& serialize( std::ostream& s ) const
|
||||
{
|
||||
return s << "exactly( " << count_ << '/' << max_ << " )";
|
||||
}
|
||||
};
|
||||
|
||||
class never : public exactly
|
||||
{
|
||||
public:
|
||||
never()
|
||||
: exactly( 0 )
|
||||
{}
|
||||
|
||||
private:
|
||||
virtual std::ostream& serialize( std::ostream& s ) const
|
||||
{
|
||||
return s << "never()";
|
||||
}
|
||||
};
|
||||
|
||||
class once : public exactly
|
||||
{
|
||||
public:
|
||||
once()
|
||||
: exactly( 1 )
|
||||
{}
|
||||
|
||||
private:
|
||||
virtual std::ostream& serialize( std::ostream& s ) const
|
||||
{
|
||||
return s << "once()";
|
||||
}
|
||||
};
|
||||
|
||||
class at_least : public between
|
||||
{
|
||||
public:
|
||||
explicit at_least( std::size_t min )
|
||||
: between( min, std::numeric_limits< std::size_t >::max() )
|
||||
{}
|
||||
|
||||
private:
|
||||
virtual std::ostream& serialize( std::ostream& s ) const
|
||||
{
|
||||
return s << "at_least( " << count_ << '/' << min_ << " )";
|
||||
}
|
||||
};
|
||||
|
||||
class at_most : public between
|
||||
{
|
||||
public:
|
||||
explicit at_most( std::size_t max )
|
||||
: between( 0, max )
|
||||
{}
|
||||
|
||||
private:
|
||||
virtual std::ostream& serialize( std::ostream& s ) const
|
||||
{
|
||||
return s << "at_most( " << count_ << '/' << max_ << " )";
|
||||
}
|
||||
};
|
||||
|
||||
class unlimited : public at_least
|
||||
{
|
||||
public:
|
||||
unlimited()
|
||||
: at_least( 0 )
|
||||
{}
|
||||
|
||||
private:
|
||||
virtual std::ostream& serialize( std::ostream& s ) const
|
||||
{
|
||||
return s << "unlimited()";
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
#endif // MOCK_INVOCATION_HPP_INCLUDED
|
||||
50
turtle/is_functor.hpp
Normal file
50
turtle/is_functor.hpp
Normal file
|
|
@ -0,0 +1,50 @@
|
|||
//
|
||||
// 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)
|
||||
//
|
||||
// See http://turtle.sf.net for documentation.
|
||||
|
||||
#ifndef MOCK_IS_FUNCTOR_HPP_INCLUDED
|
||||
#define MOCK_IS_FUNCTOR_HPP_INCLUDED
|
||||
|
||||
#include "yes_no_type.hpp"
|
||||
#include <boost/function_types/is_callable_builtin.hpp>
|
||||
#include <boost/mpl/bool.hpp>
|
||||
#include <boost/mpl/or.hpp>
|
||||
|
||||
namespace mock
|
||||
{
|
||||
namespace detail
|
||||
{
|
||||
#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( ... ); \
|
||||
template< typename T > struct N \
|
||||
: boost::mpl::bool_< \
|
||||
sizeof( N##_helper< T >( 0 ) ) == sizeof( yes_type ) \
|
||||
> \
|
||||
{};
|
||||
|
||||
MOCK_IS_FUNCTION_HELPER( has_result_type, result_type )
|
||||
MOCK_IS_FUNCTION_HELPER( has_sig, BOOST_NESTED_TEMPLATE sig< void > )
|
||||
MOCK_IS_FUNCTION_HELPER( has_result, BOOST_NESTED_TEMPLATE result< void > )
|
||||
|
||||
#undef MOCK_IS_FUNCTION_HELPER
|
||||
|
||||
template< typename T >
|
||||
struct is_functor
|
||||
: boost::mpl::or_<
|
||||
boost::function_types::is_callable_builtin< T >,
|
||||
has_result_type< T >,
|
||||
has_result< T >,
|
||||
has_sig< T >
|
||||
>
|
||||
{};
|
||||
}
|
||||
}
|
||||
|
||||
#endif // MOCK_IS_FUNCTOR_HPP_INCLUDED
|
||||
79
turtle/lambda.hpp
Normal file
79
turtle/lambda.hpp
Normal file
|
|
@ -0,0 +1,79 @@
|
|||
//
|
||||
// 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)
|
||||
//
|
||||
// See http://turtle.sf.net for documentation.
|
||||
|
||||
#ifndef MOCK_LAMBDA_HPP_INCLUDED
|
||||
#define MOCK_LAMBDA_HPP_INCLUDED
|
||||
|
||||
#include "config.hpp"
|
||||
#ifdef MOCK_USE_BOOST_PHOENIX
|
||||
#include <boost/spirit/home/phoenix/bind.hpp>
|
||||
#else
|
||||
#include <boost/bind.hpp>
|
||||
#endif
|
||||
#include <boost/function.hpp>
|
||||
|
||||
namespace mock
|
||||
{
|
||||
namespace detail
|
||||
{
|
||||
#ifdef MOCK_USE_BOOST_PHOENIX
|
||||
using boost::phoenix::bind;
|
||||
#else
|
||||
using boost::bind;
|
||||
#endif
|
||||
|
||||
template< typename Result, typename Signature >
|
||||
struct lambda
|
||||
{
|
||||
typedef BOOST_DEDUCED_TYPENAME
|
||||
boost::function< Signature > functor_type;
|
||||
|
||||
template< typename T >
|
||||
static functor_type make_val( T t )
|
||||
{
|
||||
return mock::detail::bind( &do_identity< T >, t );
|
||||
}
|
||||
template< typename T >
|
||||
static functor_type make_val( boost::reference_wrapper< T > t )
|
||||
{
|
||||
return mock::detail::bind(
|
||||
&do_ref_identity< T >, t.get_pointer() );
|
||||
}
|
||||
template< typename T >
|
||||
static functor_type make_throw( T t )
|
||||
{
|
||||
return mock::detail::bind( &do_throw< T >, t );
|
||||
}
|
||||
static functor_type make_nothing()
|
||||
{
|
||||
return mock::detail::bind( &do_nothing );
|
||||
}
|
||||
|
||||
template< typename T >
|
||||
static T do_identity( T t )
|
||||
{
|
||||
return t;
|
||||
}
|
||||
template< typename T >
|
||||
static T& do_ref_identity( T* t )
|
||||
{
|
||||
return *t;
|
||||
}
|
||||
template< typename T >
|
||||
static Result do_throw( T t )
|
||||
{
|
||||
throw t;
|
||||
}
|
||||
static void do_nothing()
|
||||
{}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
#endif // MOCK_LAMBDA_HPP_INCLUDED
|
||||
312
turtle/log.hpp
Normal file
312
turtle/log.hpp
Normal file
|
|
@ -0,0 +1,312 @@
|
|||
//
|
||||
// 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)
|
||||
//
|
||||
// See http://turtle.sf.net for documentation.
|
||||
|
||||
#ifndef MOCK_LOG_HPP_INCLUDED
|
||||
#define MOCK_LOG_HPP_INCLUDED
|
||||
|
||||
#include <boost/utility/enable_if.hpp>
|
||||
#include <boost/detail/container_fwd.hpp>
|
||||
#include <boost/function_types/is_callable_builtin.hpp>
|
||||
#include <boost/utility/addressof.hpp>
|
||||
#include <ostream>
|
||||
#include <memory>
|
||||
|
||||
namespace boost
|
||||
{
|
||||
template< typename T > class shared_ptr;
|
||||
template< typename T > class weak_ptr;
|
||||
|
||||
namespace phoenix
|
||||
{
|
||||
template< typename T > struct actor;
|
||||
}
|
||||
namespace lambda
|
||||
{
|
||||
template< typename T > struct lambda_functor;
|
||||
}
|
||||
namespace assign_detail
|
||||
{
|
||||
template< typename T > class generic_list;
|
||||
}
|
||||
template< typename T > class reference_wrapper;
|
||||
}
|
||||
|
||||
namespace mock
|
||||
{
|
||||
struct stream
|
||||
{
|
||||
explicit stream( std::ostream& s )
|
||||
: s_( &s )
|
||||
{}
|
||||
std::ostream* s_;
|
||||
};
|
||||
|
||||
#ifdef MOCK_USE_CONVERSIONS
|
||||
|
||||
namespace detail3
|
||||
{
|
||||
struct sink
|
||||
{
|
||||
template< typename T >
|
||||
sink( const T& )
|
||||
{}
|
||||
};
|
||||
|
||||
inline std::ostream& operator<<( std::ostream& s, const sink& )
|
||||
{
|
||||
return s << '?';
|
||||
}
|
||||
|
||||
struct holder
|
||||
{
|
||||
virtual ~holder()
|
||||
{}
|
||||
virtual void serialize( std::ostream& s ) const = 0;
|
||||
};
|
||||
|
||||
template< typename T >
|
||||
struct holder_imp : holder
|
||||
{
|
||||
explicit holder_imp( const T& t )
|
||||
: t_( boost::addressof( t ) )
|
||||
{}
|
||||
virtual void serialize( std::ostream& s ) const
|
||||
{
|
||||
// if an error about an ambiguous conversion is generated by the
|
||||
// line below the solution is to add a serialization operator to a
|
||||
// mock::stream for T
|
||||
s << *t_;
|
||||
}
|
||||
const T* t_;
|
||||
};
|
||||
|
||||
struct data
|
||||
{
|
||||
template< typename T >
|
||||
data( const T& t )
|
||||
: h_( new holder_imp< T >( t ) )
|
||||
{}
|
||||
~data()
|
||||
{
|
||||
delete h_;
|
||||
}
|
||||
holder* h_;
|
||||
};
|
||||
}
|
||||
|
||||
inline stream& operator<<( stream& s, const detail3::data& d )
|
||||
{
|
||||
d.h_->serialize( *s.s_ );
|
||||
return s;
|
||||
}
|
||||
|
||||
#else // MOCK_USE_CONVERSIONS
|
||||
|
||||
namespace detail3
|
||||
{
|
||||
template< typename S, typename T >
|
||||
S& operator<<( S &s, const T& )
|
||||
{
|
||||
return s << '?';
|
||||
}
|
||||
}
|
||||
|
||||
template< typename T >
|
||||
stream& operator<<( stream& s, const T& t )
|
||||
{
|
||||
using namespace detail3;
|
||||
*s.s_ << t;
|
||||
return s;
|
||||
}
|
||||
|
||||
#endif // MOCK_USE_CONVERSIONS
|
||||
|
||||
namespace detail2
|
||||
{
|
||||
template< typename T >
|
||||
void serialize( stream& s, const T& t )
|
||||
{
|
||||
// if an error about an ambiguous conversion is generated by the
|
||||
// line below the solution is to add a serialization operator to a
|
||||
// mock::stream for T
|
||||
s << t;
|
||||
}
|
||||
inline void serialize( stream& s, bool b )
|
||||
{
|
||||
s << (b ? "true" : "false");
|
||||
}
|
||||
template< typename C, typename T, typename A >
|
||||
void serialize( stream& s, const std::basic_string< C, T, A >& str )
|
||||
{
|
||||
s << '"' << str << '"';
|
||||
}
|
||||
inline void serialize( stream& s, const char* const str )
|
||||
{
|
||||
s << '"' << str << '"';
|
||||
}
|
||||
inline void serialize( stream& s, unsigned char c )
|
||||
{
|
||||
s << static_cast< int >( c );
|
||||
}
|
||||
|
||||
template< typename T >
|
||||
struct formatter
|
||||
{
|
||||
explicit formatter( const T& t )
|
||||
: t_( boost::addressof( t ) )
|
||||
{}
|
||||
void serialize( stream& s ) const
|
||||
{
|
||||
mock::detail2::serialize( s, *t_ );
|
||||
}
|
||||
const T* t_;
|
||||
};
|
||||
|
||||
template< typename T >
|
||||
stream& operator<<( stream& s, const formatter< T >& ser )
|
||||
{
|
||||
ser.serialize( s );
|
||||
return s;
|
||||
}
|
||||
|
||||
template< typename T >
|
||||
std::ostream& operator<<( std::ostream& s, const formatter< T >& ser )
|
||||
{
|
||||
stream ss( s );
|
||||
ser.serialize( ss );
|
||||
return s;
|
||||
}
|
||||
}
|
||||
|
||||
template< typename T >
|
||||
detail2::formatter< T > format( const T& t )
|
||||
{
|
||||
return detail2::formatter< T >( t );
|
||||
}
|
||||
|
||||
template< typename T >
|
||||
stream& operator<<( stream& s, const std::auto_ptr< T >& t )
|
||||
{
|
||||
return s << mock::format( t.get() );
|
||||
}
|
||||
template< typename T1, typename T2 >
|
||||
stream& operator<<( stream& s, const std::pair< T1, T2 >& p )
|
||||
{
|
||||
return s << '(' << mock::format( p.first )
|
||||
<< ',' << mock::format( p.second ) << ')';
|
||||
}
|
||||
|
||||
namespace detail
|
||||
{
|
||||
template< typename T >
|
||||
void serialize( stream& s, const T& begin, const T& end )
|
||||
{
|
||||
s << '(';
|
||||
for( T it = begin; it != end; ++it )
|
||||
s << (it == begin ? "" : ",") << mock::format( *it );
|
||||
s << ')';
|
||||
}
|
||||
}
|
||||
|
||||
template< typename T, typename A >
|
||||
stream& operator<<( stream& s, const std::deque< T, A >& t )
|
||||
{
|
||||
mock::detail::serialize( s, t.begin(), t.end() );
|
||||
return s;
|
||||
}
|
||||
template< typename T, typename A >
|
||||
stream& operator<<( stream& s, const std::list< T, A >& t )
|
||||
{
|
||||
mock::detail::serialize( s, t.begin(), t.end() );
|
||||
return s;
|
||||
}
|
||||
template< typename T, typename A >
|
||||
stream& operator<<( stream& s, const std::vector< T, A >& t )
|
||||
{
|
||||
mock::detail::serialize( s, t.begin(), t.end() );
|
||||
return s;
|
||||
}
|
||||
template< typename K, typename T, typename C, typename A >
|
||||
stream& operator<<( stream& s, const std::map< K, T, C, A >& t )
|
||||
{
|
||||
mock::detail::serialize( s, t.begin(), t.end() );
|
||||
return s;
|
||||
}
|
||||
template< typename K, typename T, typename C, typename A >
|
||||
stream& operator<<( stream& s, const std::multimap< K, T, C, A >& t )
|
||||
{
|
||||
mock::detail::serialize( s, t.begin(), t.end() );
|
||||
return s;
|
||||
}
|
||||
template< typename T, typename C, typename A >
|
||||
stream& operator<<( stream& s, const std::set< T, C, A >& t )
|
||||
{
|
||||
mock::detail::serialize( s, t.begin(), t.end() );
|
||||
return s;
|
||||
}
|
||||
template< typename T, typename C, typename A >
|
||||
stream& operator<<( stream& s, const std::multiset< T, C, A >& t )
|
||||
{
|
||||
mock::detail::serialize( s, t.begin(), t.end() );
|
||||
return s;
|
||||
}
|
||||
template< typename T >
|
||||
stream& operator<<( stream& s,
|
||||
const boost::assign_detail::generic_list< T >& t )
|
||||
{
|
||||
mock::detail::serialize( s, t.begin(), t.end() );
|
||||
return s;
|
||||
}
|
||||
template< typename T >
|
||||
stream& operator<<( stream& s, boost::reference_wrapper< T > t )
|
||||
{
|
||||
return s << mock::format( t.get() );
|
||||
}
|
||||
template< typename T >
|
||||
stream& operator<<( stream& s, boost::shared_ptr< T > t )
|
||||
{
|
||||
return s << mock::format( t.get() );
|
||||
}
|
||||
template< typename T >
|
||||
stream& operator<<( stream& s, boost::weak_ptr< T > t )
|
||||
{
|
||||
return s << mock::format( t.lock() );
|
||||
}
|
||||
template< typename T >
|
||||
stream& operator<<( stream& s, boost::lambda::lambda_functor< T > )
|
||||
{
|
||||
return s << '?';
|
||||
}
|
||||
template< typename T >
|
||||
stream& operator<<( stream& s, boost::phoenix::actor< T > )
|
||||
{
|
||||
return s << '?';
|
||||
}
|
||||
template< typename T >
|
||||
BOOST_DEDUCED_TYPENAME boost::enable_if<
|
||||
boost::function_types::is_callable_builtin< T >,
|
||||
stream&
|
||||
>::type
|
||||
operator<<( stream& s, T* )
|
||||
{
|
||||
return s << '?';
|
||||
}
|
||||
template< typename T >
|
||||
BOOST_DEDUCED_TYPENAME boost::disable_if<
|
||||
boost::function_types::is_callable_builtin< T >,
|
||||
stream&
|
||||
>::type
|
||||
operator<<( stream& s, T* t )
|
||||
{
|
||||
*s.s_ << t;
|
||||
return s;
|
||||
}
|
||||
}
|
||||
|
||||
#endif // MOCK_LOG_HPP_INCLUDED
|
||||
196
turtle/mock.hpp
Normal file
196
turtle/mock.hpp
Normal file
|
|
@ -0,0 +1,196 @@
|
|||
//
|
||||
// Copyright Mathieu Champlon 2008
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
// See http://turtle.sf.net for documentation.
|
||||
|
||||
#ifndef MOCK_MOCK_HPP_INCLUDED
|
||||
#define MOCK_MOCK_HPP_INCLUDED
|
||||
|
||||
#include "config.hpp"
|
||||
#include "cleanup.hpp"
|
||||
#include "object.hpp"
|
||||
#include "function.hpp"
|
||||
#include "args.hpp"
|
||||
#include "type_name.hpp"
|
||||
#include <boost/preprocessor/repetition/repeat.hpp>
|
||||
#include <boost/preprocessor/stringize.hpp>
|
||||
#include <boost/function_types/parameter_types.hpp>
|
||||
#include <boost/function_types/function_type.hpp>
|
||||
#include <boost/function_types/result_type.hpp>
|
||||
#include <boost/mpl/joint_view.hpp>
|
||||
#include <boost/mpl/single_view.hpp>
|
||||
#include <boost/mpl/pop_front.hpp>
|
||||
#define BOOST_TYPEOF_SILENT
|
||||
#include <boost/typeof/typeof.hpp>
|
||||
#include <boost/type_traits.hpp>
|
||||
|
||||
namespace mock
|
||||
{
|
||||
namespace detail
|
||||
{
|
||||
template< typename M >
|
||||
struct signature :
|
||||
boost::function_types::function_type<
|
||||
boost::mpl::joint_view<
|
||||
boost::mpl::single_view<
|
||||
BOOST_DEDUCED_TYPENAME
|
||||
boost::function_types::result_type< M >::type
|
||||
>,
|
||||
BOOST_DEDUCED_TYPENAME boost::mpl::pop_front<
|
||||
BOOST_DEDUCED_TYPENAME
|
||||
boost::function_types::parameter_types< M >
|
||||
>::type
|
||||
>
|
||||
>
|
||||
{};
|
||||
|
||||
template< typename T >
|
||||
struct base
|
||||
{
|
||||
typedef T base_type;
|
||||
};
|
||||
|
||||
template< typename S >
|
||||
struct functor : mock::function< S >
|
||||
{
|
||||
functor()
|
||||
{
|
||||
static functor* f = 0;
|
||||
if( f )
|
||||
{
|
||||
*this = *f;
|
||||
f = 0;
|
||||
}
|
||||
else
|
||||
f = this;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
// if an error is generated by the line below it means
|
||||
// the method is ambiguous : use MOCK_METHOD_EXT instead
|
||||
template< typename T >
|
||||
T& ambiguous_method_name_use_MOCK_METHOD_EXT_instead( const T& );
|
||||
}
|
||||
|
||||
#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(f, S) \
|
||||
mock::detail::functor< S > f, f##_mock
|
||||
|
||||
#define MOCK_HELPER(t) \
|
||||
t##_mock( mock::detail::root, BOOST_PP_STRINGIZE(t) )
|
||||
#define MOCK_ANONYMOUS_HELPER(t) \
|
||||
t##_mock( mock::detail::root, "?." )
|
||||
|
||||
#define MOCK_METHOD_HELPER(S, t) \
|
||||
mutable mock::function< S > t##_mock_; \
|
||||
mock::function< S >& t##_mock( \
|
||||
const mock::detail::context&, \
|
||||
boost::unit_test::const_string instance ) const \
|
||||
{ \
|
||||
mock::detail::configure( *this, t##_mock_, \
|
||||
instance.substr( 0, instance.rfind( BOOST_PP_STRINGIZE(t) ) ), \
|
||||
mock::detail::type_name( typeid( *this ) ), \
|
||||
BOOST_PP_STRINGIZE(t) ); \
|
||||
return t##_mock_; \
|
||||
}
|
||||
|
||||
#define MOCK_SIGNATURE(M) \
|
||||
mock::detail::signature< \
|
||||
BOOST_TYPEOF( \
|
||||
mock::ambiguous_method_name_use_MOCK_METHOD_EXT_instead( \
|
||||
&base_type::M ) ) \
|
||||
>::type
|
||||
|
||||
#define MOCK_METHOD_AUX(M, n, S, t, c, tpn) \
|
||||
MOCK_DECL(M, n, S, c, tpn) \
|
||||
{ \
|
||||
return MOCK_ANONYMOUS_HELPER(t)( \
|
||||
BOOST_PP_ENUM_PARAMS(n, p) ); \
|
||||
}
|
||||
|
||||
#define MOCK_METHOD_EXT(M, n, S, t) \
|
||||
MOCK_METHOD_AUX(M, n, S, t,,) \
|
||||
MOCK_METHOD_AUX(M, n, S, t, const,) \
|
||||
MOCK_METHOD_HELPER(S, t)
|
||||
#define MOCK_CONST_METHOD_EXT(M, n, S, t) \
|
||||
MOCK_METHOD_AUX(M, n, S, t, const,) \
|
||||
MOCK_METHOD_HELPER(S, t)
|
||||
#define MOCK_NON_CONST_METHOD_EXT(M, n, S, t) \
|
||||
MOCK_METHOD_AUX(M, n, S, t,,) \
|
||||
MOCK_METHOD_HELPER(S, t)
|
||||
#define MOCK_METHOD(M, n) \
|
||||
MOCK_METHOD_EXT(M, n, MOCK_SIGNATURE(M), M)
|
||||
|
||||
#define MOCK_METHOD_EXT_TPL(M, n, S, t) \
|
||||
MOCK_METHOD_AUX(M, n, S, t,, BOOST_DEDUCED_TYPENAME) \
|
||||
MOCK_METHOD_AUX(M, n, S, t, const, BOOST_DEDUCED_TYPENAME) \
|
||||
MOCK_METHOD_HELPER(S, t)
|
||||
#define MOCK_CONST_METHOD_EXT_TPL(M, n, S, t) \
|
||||
MOCK_METHOD_AUX(M, n, S, t, const, BOOST_DEDUCED_TYPENAME) \
|
||||
MOCK_METHOD_HELPER(S, t)
|
||||
#define MOCK_NON_CONST_METHOD_EXT_TPL(M, n, S, t) \
|
||||
MOCK_METHOD_AUX(M, n, S, t,, BOOST_DEDUCED_TYPENAME) \
|
||||
MOCK_METHOD_HELPER(S, t)
|
||||
|
||||
#define MOCK_CONST_CONVERSION_OPERATOR(T, t) \
|
||||
operator T() const { return MOCK_ANONYMOUS_HELPER(t)(); } \
|
||||
MOCK_METHOD_HELPER(T(), t)
|
||||
#define MOCK_NON_CONST_CONVERSION_OPERATOR(T, t) \
|
||||
operator T() { return MOCK_ANONYMOUS_HELPER(t)(); } \
|
||||
MOCK_METHOD_HELPER(T(), t)
|
||||
#define MOCK_CONVERSION_OPERATOR(T, t) \
|
||||
operator T() const { return MOCK_ANONYMOUS_HELPER(t)(); } \
|
||||
operator T() { return MOCK_ANONYMOUS_HELPER(t)(); } \
|
||||
MOCK_METHOD_HELPER(T(), t)
|
||||
|
||||
#define MOCK_FUNCTION_HELPER(S, t, s) \
|
||||
s mock::function< S >& t##_mock( \
|
||||
mock::detail::context& context, \
|
||||
boost::unit_test::const_string instance ) \
|
||||
{ \
|
||||
static mock::function< S > f; \
|
||||
return f( context, instance ); \
|
||||
}
|
||||
|
||||
#define MOCK_CONSTRUCTOR_AUX(T, n, A, t, tpn) \
|
||||
MOCK_FUNCTION_HELPER(void A, t, static) \
|
||||
T( MOCK_ARGS(n, void A, tpn) ) \
|
||||
{ \
|
||||
MOCK_HELPER(t)( BOOST_PP_ENUM_PARAMS(n, p) ); \
|
||||
}
|
||||
|
||||
#define MOCK_CONSTRUCTOR(T, n, A, t) \
|
||||
MOCK_CONSTRUCTOR_AUX(T, n, A, t,)
|
||||
#define MOCK_CONSTRUCTOR_TPL(T, n, A, t) \
|
||||
MOCK_CONSTRUCTOR_AUX(T, n, A, t, BOOST_DEDUCED_TYPENAME)
|
||||
|
||||
#define MOCK_DESTRUCTOR(T, t) \
|
||||
~T() { MOCK_ANONYMOUS_HELPER(t).test(); } \
|
||||
MOCK_METHOD_HELPER(void(), t)
|
||||
|
||||
#define MOCK_FUNCTION_AUX(F, n, S, t, s, tpn) \
|
||||
MOCK_FUNCTION_HELPER(S, t, s) \
|
||||
s MOCK_DECL(F, n, S,,tpn) \
|
||||
{ \
|
||||
return MOCK_HELPER(t)( BOOST_PP_ENUM_PARAMS(n, p) ); \
|
||||
}
|
||||
#define MOCK_FUNCTION(F, n, S, t) \
|
||||
MOCK_FUNCTION_AUX(F, n, S, t,,)
|
||||
#define MOCK_STATIC_METHOD(F, n, S, t) \
|
||||
MOCK_FUNCTION_AUX(F, n, S, t, static,)
|
||||
#define MOCK_STATIC_METHOD_TPL(F, n, S, t) \
|
||||
MOCK_FUNCTION_AUX(F, n, S, t, static, BOOST_DEDUCED_TYPENAME)
|
||||
|
||||
#define MOCK_EXPECT(t) MOCK_HELPER(t).expect( __FILE__, __LINE__ )
|
||||
#define MOCK_RESET(t) MOCK_HELPER(t).reset( __FILE__, __LINE__ )
|
||||
#define MOCK_VERIFY(t) MOCK_HELPER(t).verify( __FILE__, __LINE__ )
|
||||
|
||||
#endif // MOCK_MOCK_HPP_INCLUDED
|
||||
134
turtle/object.hpp
Normal file
134
turtle/object.hpp
Normal file
|
|
@ -0,0 +1,134 @@
|
|||
//
|
||||
// Copyright Mathieu Champlon 2008
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
// See http://turtle.sf.net for documentation.
|
||||
|
||||
#ifndef MOCK_OBJECT_HPP_INCLUDED
|
||||
#define MOCK_OBJECT_HPP_INCLUDED
|
||||
|
||||
#include "root.hpp"
|
||||
#include "context.hpp"
|
||||
#include "parent.hpp"
|
||||
#include "child.hpp"
|
||||
#include "type_name.hpp"
|
||||
#include <boost/enable_shared_from_this.hpp>
|
||||
#include <boost/type_traits/is_base_of.hpp>
|
||||
#include <boost/utility/enable_if.hpp>
|
||||
#include <boost/shared_ptr.hpp>
|
||||
|
||||
namespace mock
|
||||
{
|
||||
class object
|
||||
{
|
||||
public:
|
||||
object()
|
||||
: impl_( new object_impl() )
|
||||
{}
|
||||
|
||||
protected:
|
||||
~object()
|
||||
{}
|
||||
|
||||
private:
|
||||
class object_impl : public detail::context, public detail::verifiable,
|
||||
public boost::enable_shared_from_this< object_impl >
|
||||
{
|
||||
public:
|
||||
virtual void add( const void* /*p*/, detail::verifiable& v,
|
||||
boost::unit_test::const_string instance,
|
||||
const boost::optional< detail::type_name >& type,
|
||||
boost::unit_test::const_string name )
|
||||
{
|
||||
if( children_.empty() )
|
||||
mock::detail::root.add( *this );
|
||||
children_[ &v ].update( parent_, instance, type, name );
|
||||
}
|
||||
virtual void add( detail::verifiable& v )
|
||||
{
|
||||
group_.add( v );
|
||||
}
|
||||
virtual void remove( detail::verifiable& v )
|
||||
{
|
||||
group_.remove( v );
|
||||
children_.erase( &v );
|
||||
if( children_.empty() )
|
||||
mock::detail::root.remove( *this );
|
||||
}
|
||||
|
||||
virtual void serialize( std::ostream& s,
|
||||
const detail::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()
|
||||
{
|
||||
boost::shared_ptr< object_impl > guard = shared_from_this();
|
||||
group_.reset();
|
||||
}
|
||||
|
||||
private:
|
||||
typedef std::map<
|
||||
const detail::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,
|
||||
boost::unit_test::const_string instance,
|
||||
const boost::optional< type_name >& type,
|
||||
boost::unit_test::const_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,
|
||||
boost::unit_test::const_string instance,
|
||||
const boost::optional< type_name >& type,
|
||||
boost::unit_test::const_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
|
||||
111
turtle/operators.hpp
Normal file
111
turtle/operators.hpp
Normal file
|
|
@ -0,0 +1,111 @@
|
|||
//
|
||||
// Copyright Mathieu Champlon 2010
|
||||
//
|
||||
// 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)
|
||||
//
|
||||
// See http://turtle.sf.net for documentation.
|
||||
|
||||
#ifndef MOCK_OPERATORS_HPP_INCLUDED
|
||||
#define MOCK_OPERATORS_HPP_INCLUDED
|
||||
|
||||
#include "constraint.hpp"
|
||||
#include "log.hpp"
|
||||
|
||||
namespace mock
|
||||
{
|
||||
namespace detail
|
||||
{
|
||||
template< typename Constraint1, typename Constraint2 >
|
||||
class and_
|
||||
{
|
||||
public:
|
||||
and_( const Constraint1& c1, const Constraint2& c2 )
|
||||
: c1_( c1 )
|
||||
, c2_( c2 )
|
||||
{}
|
||||
template< typename Actual >
|
||||
bool operator()( const Actual& actual ) const
|
||||
{
|
||||
return c1_( actual ) && c2_( actual );
|
||||
}
|
||||
friend std::ostream& operator<<( std::ostream& s, const and_& a )
|
||||
{
|
||||
return s << "( " << mock::format( a.c1_ )
|
||||
<< " && " << mock::format( a.c2_ ) << " )";
|
||||
}
|
||||
private:
|
||||
Constraint1 c1_;
|
||||
Constraint2 c2_;
|
||||
};
|
||||
|
||||
template< typename Constraint1, typename Constraint2 >
|
||||
class or_
|
||||
{
|
||||
public:
|
||||
or_( const Constraint1& c1, const Constraint2& c2 )
|
||||
: c1_( c1 )
|
||||
, c2_( c2 )
|
||||
{}
|
||||
template< typename Actual >
|
||||
bool operator()( const Actual& actual ) const
|
||||
{
|
||||
return c1_( actual ) || c2_( actual );
|
||||
}
|
||||
friend std::ostream& operator<<( std::ostream& s, const or_& o )
|
||||
{
|
||||
return s << "( " << mock::format( o.c1_ )
|
||||
<< " || " << mock::format( o.c2_ )<< " )";
|
||||
}
|
||||
private:
|
||||
Constraint1 c1_;
|
||||
Constraint2 c2_;
|
||||
};
|
||||
|
||||
template< typename Constraint >
|
||||
class not_
|
||||
{
|
||||
public:
|
||||
explicit not_( const Constraint& f )
|
||||
: f_( f )
|
||||
{}
|
||||
template< typename Actual >
|
||||
bool operator()( const Actual& actual ) const
|
||||
{
|
||||
return ! f_( actual );
|
||||
}
|
||||
friend std::ostream& operator<<( std::ostream& s, const not_& n )
|
||||
{
|
||||
return s << "! " << mock::format( n.f_ );
|
||||
}
|
||||
private:
|
||||
Constraint f_;
|
||||
};
|
||||
}
|
||||
|
||||
template< typename Constraint1, typename Constraint2 >
|
||||
const constraint< detail::or_< Constraint1, Constraint2 > >
|
||||
operator||( const constraint< Constraint1 >& lhs,
|
||||
const constraint< Constraint2 >& rhs )
|
||||
{
|
||||
return detail::or_< Constraint1, Constraint2 >( lhs.f_, rhs.f_ );
|
||||
}
|
||||
|
||||
template< typename Constraint1, typename Constraint2 >
|
||||
const constraint< detail::and_< Constraint1, Constraint2 > >
|
||||
operator&&( const constraint< Constraint1 >& lhs,
|
||||
const constraint< Constraint2 >& rhs )
|
||||
{
|
||||
return detail::and_< Constraint1, Constraint2 >( lhs.f_, rhs.f_ );
|
||||
}
|
||||
|
||||
template< typename Constraint >
|
||||
const constraint< detail::not_< Constraint > >
|
||||
operator!( const constraint< Constraint >& c )
|
||||
{
|
||||
return detail::not_< Constraint >( c.f_ );
|
||||
}
|
||||
}
|
||||
|
||||
#endif // MOCK_OPERATORS_HPP_INCLUDED
|
||||
46
turtle/parent.hpp
Normal file
46
turtle/parent.hpp
Normal file
|
|
@ -0,0 +1,46 @@
|
|||
//
|
||||
// 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)
|
||||
//
|
||||
// See http://turtle.sf.net for documentation.
|
||||
|
||||
#ifndef MOCK_PARENT_HPP_INCLUDED
|
||||
#define MOCK_PARENT_HPP_INCLUDED
|
||||
|
||||
#include "type_name.hpp"
|
||||
#include <boost/optional.hpp>
|
||||
#include <boost/test/utils/basic_cstring/io.hpp>
|
||||
#include <ostream>
|
||||
|
||||
namespace mock
|
||||
{
|
||||
namespace detail
|
||||
{
|
||||
class parent
|
||||
{
|
||||
public:
|
||||
parent()
|
||||
{}
|
||||
parent( boost::unit_test::const_string instance,
|
||||
const boost::optional< type_name >& type )
|
||||
: instance_( instance )
|
||||
, type_( type )
|
||||
{}
|
||||
friend std::ostream& operator<<( std::ostream& s, const parent& p )
|
||||
{
|
||||
s << p.instance_;
|
||||
if( p.type_ )
|
||||
s << *p.type_ << "::";
|
||||
return s;
|
||||
}
|
||||
private:
|
||||
boost::unit_test::const_string instance_;
|
||||
boost::optional< type_name > type_;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
#endif // MOCK_PARENT_HPP_INCLUDED
|
||||
142
turtle/root.hpp
Normal file
142
turtle/root.hpp
Normal file
|
|
@ -0,0 +1,142 @@
|
|||
//
|
||||
// Copyright Mathieu Champlon 2008
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
// See http://turtle.sf.net for documentation.
|
||||
|
||||
#ifndef MOCK_ROOT_HPP_INCLUDED
|
||||
#define MOCK_ROOT_HPP_INCLUDED
|
||||
|
||||
#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 <map>
|
||||
|
||||
namespace mock
|
||||
{
|
||||
namespace detail
|
||||
{
|
||||
class root_t : public boost::unit_test::singleton< root_t >,
|
||||
public detail::context
|
||||
{
|
||||
public:
|
||||
virtual void add( const void* p, verifiable& v,
|
||||
boost::unit_test::const_string instance,
|
||||
const boost::optional< type_name >& type,
|
||||
boost::unit_test::const_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()
|
||||
{
|
||||
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:
|
||||
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( boost::unit_test::const_string instance,
|
||||
const boost::optional< type_name >& type,
|
||||
boost::unit_test::const_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 );
|
||||
};
|
||||
BOOST_TEST_SINGLETON_INST( root )
|
||||
}
|
||||
|
||||
inline bool verify()
|
||||
{
|
||||
return mock::detail::root.verify();
|
||||
}
|
||||
inline void reset()
|
||||
{
|
||||
mock::detail::root.reset();
|
||||
}
|
||||
}
|
||||
|
||||
#endif // MOCK_ROOT_HPP_INCLUDED
|
||||
68
turtle/sequence.hpp
Normal file
68
turtle/sequence.hpp
Normal file
|
|
@ -0,0 +1,68 @@
|
|||
//
|
||||
// Copyright Mathieu Champlon 2008
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
// See http://turtle.sf.net for documentation.
|
||||
|
||||
#ifndef MOCK_SEQUENCE_HPP_INCLUDED
|
||||
#define MOCK_SEQUENCE_HPP_INCLUDED
|
||||
|
||||
#include <boost/noncopyable.hpp>
|
||||
#include <boost/shared_ptr.hpp>
|
||||
#include <algorithm>
|
||||
#include <vector>
|
||||
|
||||
namespace mock
|
||||
{
|
||||
namespace detail
|
||||
{
|
||||
class sequence_impl : private boost::noncopyable
|
||||
{
|
||||
public:
|
||||
void add( void* e )
|
||||
{
|
||||
elements_.push_back( e );
|
||||
}
|
||||
void remove( void* e )
|
||||
{
|
||||
elements_.erase( std::remove( elements_.begin(),
|
||||
elements_.end(), e ), elements_.end() );
|
||||
}
|
||||
|
||||
bool is_valid( const void* e ) const
|
||||
{
|
||||
return std::find( elements_.begin(), elements_.end(), e )
|
||||
!= elements_.end();
|
||||
}
|
||||
|
||||
void invalidate( const void* e )
|
||||
{
|
||||
elements_it it =
|
||||
std::find( elements_.begin(), elements_.end(), e );
|
||||
if( it != elements_.end() )
|
||||
elements_.erase( elements_.begin(), it );
|
||||
}
|
||||
|
||||
private:
|
||||
typedef std::vector< void* > elements_type;
|
||||
typedef elements_type::iterator elements_it;
|
||||
|
||||
elements_type elements_;
|
||||
};
|
||||
}
|
||||
|
||||
class sequence
|
||||
{
|
||||
public:
|
||||
sequence()
|
||||
: impl_( new detail::sequence_impl() )
|
||||
{}
|
||||
|
||||
boost::shared_ptr< detail::sequence_impl > impl_;
|
||||
};
|
||||
}
|
||||
|
||||
#endif // MOCK_SEQUENCE_HPP_INCLUDED
|
||||
86
turtle/type_name.hpp
Normal file
86
turtle/type_name.hpp
Normal file
|
|
@ -0,0 +1,86 @@
|
|||
//
|
||||
// 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)
|
||||
//
|
||||
// See http://turtle.sf.net for documentation.
|
||||
|
||||
#ifndef MOCK_TYPE_NAME_HPP_INCLUDED
|
||||
#define MOCK_TYPE_NAME_HPP_INCLUDED
|
||||
|
||||
#include <boost/test/utils/basic_cstring/io.hpp>
|
||||
#include <stdexcept>
|
||||
#include <typeinfo>
|
||||
#include <ostream>
|
||||
#ifdef __GNUC__
|
||||
#include <cxxabi.h>
|
||||
#include <cstdlib>
|
||||
#endif
|
||||
|
||||
namespace mock
|
||||
{
|
||||
namespace detail
|
||||
{
|
||||
class type_name
|
||||
{
|
||||
public:
|
||||
explicit type_name( const std::type_info& info )
|
||||
: info_( &info )
|
||||
{}
|
||||
friend std::ostream& operator<<( std::ostream& s, const type_name& t )
|
||||
{
|
||||
t.serialize( s, *t.info_ );
|
||||
return s;
|
||||
}
|
||||
private:
|
||||
void serialize( std::ostream& s, const std::type_info& info ) const
|
||||
{
|
||||
const char* name = info.name();
|
||||
#ifdef __GNUC__
|
||||
size_t size = 0;
|
||||
int status = 0;
|
||||
char* result = abi::__cxa_demangle( name, NULL, &size, &status );
|
||||
struct guard
|
||||
{
|
||||
explicit guard( char* p )
|
||||
: p_( p )
|
||||
{}
|
||||
~guard()
|
||||
{
|
||||
free( p_ );
|
||||
}
|
||||
private:
|
||||
char* p_;
|
||||
} g( result );
|
||||
if( result )
|
||||
serialize( s, result );
|
||||
else
|
||||
#endif
|
||||
serialize( s, name );
|
||||
}
|
||||
void serialize( std::ostream& s,
|
||||
boost::unit_test::const_string name ) const
|
||||
{
|
||||
boost::unit_test::const_string::size_type p = name.rfind( "::" );
|
||||
if( p != boost::unit_test::const_string::npos )
|
||||
{
|
||||
s << name.substr( p + 2 );
|
||||
return;
|
||||
}
|
||||
p = name.rfind( " " );
|
||||
if( p != boost::unit_test::const_string::npos )
|
||||
{
|
||||
s << name.substr( p + 1 );
|
||||
return;
|
||||
}
|
||||
s << name;
|
||||
}
|
||||
|
||||
const std::type_info* info_;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
#endif // MOCK_TYPE_NAME_HPP_INCLUDED
|
||||
32
turtle/verifiable.hpp
Normal file
32
turtle/verifiable.hpp
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
//
|
||||
// Copyright Mathieu Champlon 2008
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
// See http://turtle.sf.net for documentation.
|
||||
|
||||
#ifndef MOCK_VERIFIABLE_HPP_INCLUDED
|
||||
#define MOCK_VERIFIABLE_HPP_INCLUDED
|
||||
|
||||
#include <boost/noncopyable.hpp>
|
||||
|
||||
namespace mock
|
||||
{
|
||||
namespace detail
|
||||
{
|
||||
class verifiable : private boost::noncopyable
|
||||
{
|
||||
public:
|
||||
verifiable() {}
|
||||
virtual ~verifiable() {}
|
||||
|
||||
virtual bool verify() const = 0;
|
||||
|
||||
virtual void reset() = 0;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
#endif // MOCK_VERIFIABLE_HPP_INCLUDED
|
||||
32
turtle/yes_no_type.hpp
Normal file
32
turtle/yes_no_type.hpp
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
//
|
||||
// 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)
|
||||
//
|
||||
// See http://turtle.sf.net for documentation.
|
||||
|
||||
#ifndef MOCK_YES_NO_TYPE_HPP_INCLUDED
|
||||
#define MOCK_YES_NO_TYPE_HPP_INCLUDED
|
||||
|
||||
#include <boost/static_assert.hpp>
|
||||
|
||||
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 // MOCK_YES_NO_TYPE_HPP_INCLUDED
|
||||
Loading…
Add table
Add a link
Reference in a new issue