Merge pull request #35 from mat007/support-move-only-types-as-arguments

Support move only types as arguments
This commit is contained in:
Mathieu Champlon 2018-03-12 19:21:54 +01:00 committed by GitHub
commit 176b9bdc01
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
16 changed files with 250 additions and 62 deletions

1
.gitignore vendored
View file

@ -1,3 +1,4 @@
.vscode
bin bin
out out
build/xsl build/xsl

View file

@ -13,6 +13,10 @@ Not yet released
* Fixed mocking of a function returning a reference for gcc 4.1 * Fixed mocking of a function returning a reference for gcc 4.1
* Added MOCK_NO_AUTO_PTR to deactivate std::auto_ptr support * Added MOCK_NO_AUTO_PTR to deactivate std::auto_ptr support
* Added [@https://github.com/philsquared/Catch Catch] integration * Added [@https://github.com/philsquared/Catch Catch] integration
* Fixed move-only type argument in actions
* Fixed move-only type support in constraints
* Added support for dereferencing in mock::equal
* Added support for movable objects in mock::retrieve
[endsect] [endsect]

View file

@ -22,6 +22,7 @@ namespace
{} {}
int data_; int data_;
}; };
std::ostream& operator<<( std::ostream& os, const my_class& c ) // my_class is serializable to an std::ostream std::ostream& operator<<( std::ostream& os, const my_class& c ) // my_class is serializable to an std::ostream
{ {
return os << "my_class( " << c.data_ << " )"; return os << "my_class( " << c.data_ << " )";
@ -37,7 +38,7 @@ namespace
//[ quick_constraint_solution //[ quick_constraint_solution
#include <boost/lexical_cast.hpp> #include <boost/lexical_cast.hpp>
namespace mock // it could also be in the namespace of 'my_class' namespace // in the same namespace as 'my_class'
{ {
bool operator==( const my_class& actual, const std::string& expected ) // the first part of the trick is to compare to a string bool operator==( const my_class& actual, const std::string& expected ) // the first part of the trick is to compare to a string
{ {

View file

@ -384,7 +384,11 @@ Constraints :
calls ['expected] as a functor returning a ['bool], throws std::invalid_argument if ! ['expected] calls ['expected] as a functor returning a ['bool], throws std::invalid_argument if ! ['expected]
compares ['actual] to ['expected] using operator ==]] compares ['actual] to ['expected] using operator ==]]
[[mock::equal( ['expected] )] [['actual] == ['expected]] [compares ['actual] to ['expected] using operator ==]] [[mock::equal( ['expected] )] [['actual] == ['expected]
['actual] && *['actual] == ['expected]] [compares ['actual] to ['expected] using operator ==
compares ['actual] content to ['expected] using operator ==]]
[[mock::less( ['expected] )] [['actual] < ['expected]] [compares ['actual] to ['expected] using operator <]] [[mock::less( ['expected] )] [['actual] < ['expected]] [compares ['actual] to ['expected] using operator <]]
[[mock::greater( ['expected] )] [['actual] > ['expected]] [compares ['actual] to ['expected] using operator >]] [[mock::greater( ['expected] )] [['actual] > ['expected]] [compares ['actual] to ['expected] using operator >]]
[[mock::less_equal( ['expected] )] [['actual] <= ['expected]] [compares ['actual] to ['expected] using operator <=]] [[mock::less_equal( ['expected] )] [['actual] <= ['expected]] [compares ['actual] to ['expected] using operator <=]]
@ -406,9 +410,9 @@ Constraints :
retrieves ['actual] address into ['expected] using operator =]] retrieves ['actual] address into ['expected] using operator =]]
[[mock::contain( ['expected] )] [['actual].find( ['expected] ) != std::string::npos] [checks whether ['expected] is contained in the std::string ['actual]]] [[mock::contain( ['expected] )] [['actual].find( ['expected] ) != std::string::npos] [checks whether ['expected] is contained in the std::string ['actual]]]
[[mock::affirm] [['actual]] [uses ['actual] as a boolean]] [[mock::affirm] [['actual]] [uses ['actual] as a ['bool]]]
[[mock::negate] [! ['actual]] [negates ['actual] using operator !]] [[mock::negate] [! ['actual]] [negates ['actual] using operator !]]
[[mock::evaluate] [['actual]()] [evaluates ['actual] as a functor returning a bool and taking no argument]] [[mock::evaluate] [['actual]()] [evaluates ['actual] as a functor returning a ['bool] and taking no argument]]
] ]
[important When passing ['expected] directly as a shortcut mock::call is implied for a function, a function pointer, an instance of a type with a result_type member typedef (support for standard library, [@http://www.boost.org/libs/bind/bind.html Boost.Bind], [@http://www.boost.org/libs/function Boost.Function] functors), an instance of a type with a sig member (support for [@http://www.boost.org/libs/lambda Boost.Lambda] functors), an instance of a type with a result member (support for [@http://www.boost.org/libs/phoenix Boost.Phoenix] functors); mock::equal is implied for anything else.] [important When passing ['expected] directly as a shortcut mock::call is implied for a function, a function pointer, an instance of a type with a result_type member typedef (support for standard library, [@http://www.boost.org/libs/bind/bind.html Boost.Bind], [@http://www.boost.org/libs/function Boost.Function] functors), an instance of a type with a sig member (support for [@http://www.boost.org/libs/lambda Boost.Lambda] functors), an instance of a type with a result member (support for [@http://www.boost.org/libs/phoenix Boost.Phoenix] functors); mock::equal is implied for anything else.]

View file

@ -70,6 +70,12 @@
# endif # endif
#endif #endif
#if !defined(BOOST_NO_CXX11_HDR_FUNCTIONAL)
# ifndef MOCK_NO_HDR_FUNCTIONAL
# define MOCK_HDR_FUNCTIONAL
# endif
#endif
#if !defined(BOOST_NO_CXX11_HDR_MUTEX) && !defined(BOOST_NO_0X_HDR_MUTEX) #if !defined(BOOST_NO_CXX11_HDR_MUTEX) && !defined(BOOST_NO_0X_HDR_MUTEX)
# ifndef MOCK_NO_HDR_MUTEX # ifndef MOCK_NO_HDR_MUTEX
# define MOCK_HDR_MUTEX # define MOCK_HDR_MUTEX

View file

@ -19,6 +19,7 @@
#include <boost/preprocessor/repetition/enum_params.hpp> #include <boost/preprocessor/repetition/enum_params.hpp>
#include <boost/preprocessor/repetition/enum.hpp> #include <boost/preprocessor/repetition/enum.hpp>
#include <boost/preprocessor/array.hpp> #include <boost/preprocessor/array.hpp>
#include <boost/move/move.hpp>
namespace mock namespace mock
{ {
@ -157,12 +158,14 @@ namespace detail
Expected_##n expected##n; Expected_##n expected##n;
#define MOCK_CONSTRAINT_CREF_PARAM(z, n, Args) \ #define MOCK_CONSTRAINT_CREF_PARAM(z, n, Args) \
typename \ const typename boost::unwrap_reference< Expected_##n >::type& \
boost::unwrap_reference< Expected_##n >::type \
BOOST_PP_ARRAY_ELEM(n, Args) BOOST_PP_ARRAY_ELEM(n, Args)
#define MOCK_CONSTRAINT_ARG(z, n, Args) \
BOOST_FWD_REF(T##n) BOOST_PP_ARRAY_ELEM(n, Args)
#define MOCK_CONSTRAINT_PARAM(z, n, Args) \ #define MOCK_CONSTRAINT_PARAM(z, n, Args) \
T##n BOOST_PP_ARRAY_ELEM(n, Args) boost::forward< T##n >( BOOST_PP_ARRAY_ELEM(n, Args) )
#define MOCK_NARY_CONSTRAINT(Name, n, Args, Expr) \ #define MOCK_NARY_CONSTRAINT(Name, n, Args, Expr) \
namespace detail \ namespace detail \
@ -171,7 +174,7 @@ namespace detail
struct Name \ struct Name \
{ \ { \
explicit Name( \ explicit Name( \
BOOST_PP_ENUM_BINARY_PARAMS(n, const Expected_, & e) ) \ BOOST_PP_ENUM_BINARY_PARAMS(n, Expected_, e) ) \
: BOOST_PP_ENUM(n, MOCK_CONSTRAINT_ASSIGN, _) \ : BOOST_PP_ENUM(n, MOCK_CONSTRAINT_ASSIGN, _) \
{} \ {} \
template< typename Actual > \ template< typename Actual > \
@ -199,9 +202,10 @@ namespace detail
template< BOOST_PP_ENUM_PARAMS(n, typename T) > \ template< BOOST_PP_ENUM_PARAMS(n, typename T) > \
mock::constraint< \ mock::constraint< \
detail::Name< BOOST_PP_ENUM_PARAMS(n, T) > \ detail::Name< BOOST_PP_ENUM_PARAMS(n, T) > \
> Name( BOOST_PP_ENUM(n, MOCK_CONSTRAINT_PARAM, (n, Args)) ) \ > Name( BOOST_PP_ENUM(n, MOCK_CONSTRAINT_ARG, (n, Args)) ) \
{ \ { \
return detail::Name< BOOST_PP_ENUM_PARAMS(n, T) > Args; \ return detail::Name< BOOST_PP_ENUM_PARAMS(n, T) >( \
BOOST_PP_ENUM(n, MOCK_CONSTRAINT_PARAM, (n, Args)) ); \
} }
#define MOCK_CONSTRAINT_EXT(Name, n, Args, Expr) \ #define MOCK_CONSTRAINT_EXT(Name, n, Args, Expr) \

View file

@ -17,6 +17,7 @@
#include <boost/utility/enable_if.hpp> #include <boost/utility/enable_if.hpp>
#include <boost/type_traits/common_type.hpp> #include <boost/type_traits/common_type.hpp>
#include <boost/type_traits/is_convertible.hpp> #include <boost/type_traits/is_convertible.hpp>
#include <boost/type_traits/has_equal_to.hpp>
#include <boost/test/floating_point_comparison.hpp> #include <boost/test/floating_point_comparison.hpp>
namespace mock namespace mock
@ -26,7 +27,6 @@ namespace mock
MOCK_UNARY_CONSTRAINT( negate, 0,, ! actual ) MOCK_UNARY_CONSTRAINT( negate, 0,, ! actual )
MOCK_UNARY_CONSTRAINT( evaluate, 0,, actual() ) MOCK_UNARY_CONSTRAINT( evaluate, 0,, actual() )
MOCK_NARY_CONSTRAINT( equal, 1, ( expected ), actual == expected )
MOCK_NARY_CONSTRAINT( less, 1, ( expected ), actual < expected ) MOCK_NARY_CONSTRAINT( less, 1, ( expected ), actual < expected )
MOCK_NARY_CONSTRAINT( greater, 1, ( expected ), actual > expected ) MOCK_NARY_CONSTRAINT( greater, 1, ( expected ), actual > expected )
MOCK_NARY_CONSTRAINT( less_equal, 1, ( expected ), actual <= expected ) MOCK_NARY_CONSTRAINT( less_equal, 1, ( expected ), actual <= expected )
@ -107,6 +107,43 @@ namespace detail
namespace detail namespace detail
{ {
template< typename Expected >
struct equal
{
explicit equal( Expected expected )
: expected_( expected )
{}
template< typename Actual >
bool operator()( const Actual& actual,
typename boost::enable_if<
boost::has_equal_to<
Actual,
typename
boost::unwrap_reference< Expected >::type
>
>::type* = 0 ) const
{
return actual == boost::unwrap_ref( expected_ );
}
template< typename Actual >
bool operator()( const Actual& actual,
typename boost::disable_if<
boost::has_equal_to<
Actual,
typename
boost::unwrap_reference< Expected >::type
>
>::type* = 0 ) const
{
return actual && *actual == boost::unwrap_ref( expected_ );
}
friend std::ostream& operator<<( std::ostream& s, const equal& e )
{
return s << "equal( " << mock::format( e.expected_ ) << " )";
}
Expected expected_;
};
template< typename Expected > template< typename Expected >
struct same struct same
{ {
@ -146,6 +183,19 @@ namespace detail
return true; return true;
} }
template< typename Actual > template< typename Actual >
bool operator()( BOOST_RV_REF(Actual) actual,
typename boost::disable_if<
boost::is_convertible<
const Actual*,
typename
boost::unwrap_reference< Expected >::type
>
>::type* = 0 ) const
{
*expected_ = boost::move( actual );
return true;
}
template< typename Actual >
bool operator()( Actual& actual, bool operator()( Actual& actual,
typename boost::enable_if< typename boost::enable_if<
boost::is_convertible< Actual*, boost::is_convertible< Actual*,
@ -187,6 +237,8 @@ namespace detail
> >
>::type* = 0 ) const >::type* = 0 ) const
{ {
if( ! actual )
return false;
*actual = boost::unwrap_ref( expected_ ); *actual = boost::unwrap_ref( expected_ );
return true; return true;
} }
@ -216,6 +268,12 @@ namespace detail
}; };
} }
template< typename T >
constraint< detail::equal< T > > equal( BOOST_FWD_REF(T) t )
{
return detail::equal< T >( boost::forward< T >( t ) );
}
template< typename T > template< typename T >
constraint< detail::same< T > > same( T& t ) constraint< detail::same< T > > same( T& t )
{ {

View file

@ -27,8 +27,13 @@ namespace detail
class action_base class action_base
{ {
private: private:
#ifdef MOCK_HDR_FUNCTIONAL
typedef std::function< Signature > functor_type;
typedef std::function< Result() > action_type;
#else
typedef boost::function< Signature > functor_type; typedef boost::function< Signature > functor_type;
typedef boost::function< Result() > action_type; typedef boost::function< Result() > action_type;
#endif
public: public:
const functor_type& functor() const const functor_type& functor() const

View file

@ -15,7 +15,7 @@
matcher< T##n, Constraint_##n > c##n##_; matcher< T##n, Constraint_##n > c##n##_;
#define MOCK_EXPECTATION_IS_VALID(z, n, d) \ #define MOCK_EXPECTATION_IS_VALID(z, n, d) \
BOOST_PP_IF(n, &&,) c##n##_( a##n ) BOOST_PP_IF(n, &&,) c##n##_( boost::forward< T##n >( a##n ) )
#define MOCK_EXPECTATION_SERIALIZE(z, n, d) \ #define MOCK_EXPECTATION_SERIALIZE(z, n, d) \
BOOST_PP_IF(n, << ", " <<,) c##n##_ BOOST_PP_IF(n, << ", " <<,) c##n##_
@ -23,6 +23,9 @@
#define MOCK_EXPECTATION_SERIALIZE_ANY(z, n, d) \ #define MOCK_EXPECTATION_SERIALIZE_ANY(z, n, d) \
BOOST_PP_IF(n, << ", " <<,) "any" BOOST_PP_IF(n, << ", " <<,) "any"
#define MOCK_EXPECTATION_PARAM(z, n, Args) \
boost::forward< T##n >( a##n )
namespace mock namespace mock
{ {
namespace detail namespace detail
@ -102,7 +105,7 @@ namespace detail
virtual bool operator()( virtual bool operator()(
BOOST_PP_ENUM_BINARY_PARAMS(MOCK_NUM_ARGS, T, a) ) BOOST_PP_ENUM_BINARY_PARAMS(MOCK_NUM_ARGS, T, a) )
{ {
return f_( BOOST_PP_ENUM_PARAMS(MOCK_NUM_ARGS, a ) ); return f_( BOOST_PP_ENUM(MOCK_NUM_ARGS, MOCK_EXPECTATION_PARAM, _) );
} }
virtual void serialize( std::ostream& s ) const virtual void serialize( std::ostream& s ) const
{ {
@ -201,7 +204,7 @@ namespace detail
BOOST_PP_ENUM_BINARY_PARAMS(MOCK_NUM_ARGS, T, a) ) const BOOST_PP_ENUM_BINARY_PARAMS(MOCK_NUM_ARGS, T, a) ) const
{ {
return !invocation_->exhausted() return !invocation_->exhausted()
&& (*matcher_)( BOOST_PP_ENUM_PARAMS(MOCK_NUM_ARGS, a) ); && (*matcher_)( BOOST_PP_ENUM(MOCK_NUM_ARGS, MOCK_EXPECTATION_PARAM, _) );
} }
bool invoke() const bool invoke() const

View file

@ -33,6 +33,7 @@
#include <boost/call_traits.hpp> #include <boost/call_traits.hpp>
#include <boost/make_shared.hpp> #include <boost/make_shared.hpp>
#include <boost/noncopyable.hpp> #include <boost/noncopyable.hpp>
#include <boost/move/move.hpp>
#include <boost/optional.hpp> #include <boost/optional.hpp>
#include <ostream> #include <ostream>
#include <vector> #include <vector>

View file

@ -144,6 +144,7 @@ namespace detail
BOOST_PP_ENUM_PARAMS(MOCK_NUM_ARGS, c) ); BOOST_PP_ENUM_PARAMS(MOCK_NUM_ARGS, c) );
return *this; return *this;
} }
#if MOCK_NUM_ARGS > 1 #if MOCK_NUM_ARGS > 1
template< typename Constraint > template< typename Constraint >
wrapper with( const Constraint& c ) wrapper with( const Constraint& c )
@ -215,7 +216,7 @@ namespace detail
for( expectations_cit it = expectations_.begin(); for( expectations_cit it = expectations_.begin();
it != expectations_.end(); ++it ) it != expectations_.end(); ++it )
if( it->is_valid( if( it->is_valid(
BOOST_PP_ENUM_PARAMS(MOCK_NUM_ARGS, t) ) ) BOOST_PP_ENUM(MOCK_NUM_ARGS, MOCK_FORWARD, _) ) )
{ {
if( ! it->invoke() ) if( ! it->invoke() )
{ {
@ -234,7 +235,7 @@ namespace detail
MOCK_FUNCTION_CONTEXT, it->file(), it->line() ); MOCK_FUNCTION_CONTEXT, it->file(), it->line() );
if( it->functor() ) if( it->functor() )
return it->functor()( return it->functor()(
BOOST_PP_ENUM_PARAMS(MOCK_NUM_ARGS, t) ); BOOST_PP_ENUM(MOCK_NUM_ARGS, MOCK_FORWARD, _) );
return it->trigger(); return it->trigger();
} }
error_type::fail( "unexpected call", MOCK_FUNCTION_CONTEXT ); error_type::fail( "unexpected call", MOCK_FUNCTION_CONTEXT );

View file

@ -8,12 +8,8 @@
#include "function_impl_template.hpp" #include "function_impl_template.hpp"
#define MOCK_FUNCTION_CALL(z, n, d ) \ #define MOCK_FORWARD(z, n, d) \
BOOST_PP_COMMA_IF(n) typename \ boost::forward< T##n >( t##n )
boost::call_traits< T##n >::param_type
#define MOCK_FUNCTION_PARAM(z, n, d) \
MOCK_FUNCTION_CALL(z, n, d) t##n
namespace mock namespace mock
{ {
@ -36,7 +32,7 @@ namespace detail
private: private:
typedef function_impl< typedef function_impl<
R ( BOOST_PP_REPEAT(MOCK_NUM_ARGS, MOCK_FUNCTION_CALL, _) ) R ( BOOST_PP_ENUM_PARAMS(MOCK_NUM_ARGS, T) )
> impl_type; > impl_type;
typedef typename impl_type::wrapper_type expectation_type; typedef typename impl_type::wrapper_type expectation_type;
typedef typename impl_type::error_type error_type; typedef typename impl_type::error_type error_type;
@ -76,9 +72,9 @@ namespace detail
} }
R operator()( R operator()(
BOOST_PP_REPEAT(MOCK_NUM_ARGS, MOCK_FUNCTION_PARAM, _) ) const BOOST_PP_ENUM_BINARY_PARAMS(MOCK_NUM_ARGS, T, t) ) const
{ {
return (*impl_)( BOOST_PP_ENUM_PARAMS(MOCK_NUM_ARGS, t) ); return (*impl_)( BOOST_PP_ENUM(MOCK_NUM_ARGS, MOCK_FORWARD, _) );
} }
friend std::ostream& operator<<( std::ostream& s, const function& f ) friend std::ostream& operator<<( std::ostream& s, const function& f )
@ -106,6 +102,3 @@ namespace detail
}; };
} }
} // mock } // mock
#undef MOCK_FUNCTION_CALL
#undef MOCK_FUNCTION_PARAM

View file

@ -13,15 +13,15 @@ namespace detail
template< typename Signature > class matcher_base; template< typename Signature > class matcher_base;
template< template<
BOOST_PP_ENUM_PARAMS(MOCK_NUM_ARGS, typename Actual_) > BOOST_PP_ENUM_PARAMS(MOCK_NUM_ARGS, typename T) >
class matcher_base< void( BOOST_PP_ENUM_PARAMS(MOCK_NUM_ARGS, Actual_) ) > class matcher_base< void( BOOST_PP_ENUM_PARAMS(MOCK_NUM_ARGS, T) ) >
: boost::noncopyable : boost::noncopyable
{ {
public: public:
virtual ~matcher_base() {} virtual ~matcher_base() {}
virtual bool operator()( virtual bool operator()(
BOOST_PP_ENUM_BINARY_PARAMS(MOCK_NUM_ARGS, Actual_, actual_) ) = 0; BOOST_PP_ENUM_BINARY_PARAMS(MOCK_NUM_ARGS, T, a) ) = 0;
friend std::ostream& operator<<( friend std::ostream& operator<<(
std::ostream& s, const matcher_base& m ) std::ostream& s, const matcher_base& m )

View file

@ -11,7 +11,7 @@
#include "config.hpp" #include "config.hpp"
#include "log.hpp" #include "log.hpp"
#include "constraint.hpp" #include "constraints.hpp"
#include "detail/is_functor.hpp" #include "detail/is_functor.hpp"
#include <boost/utility/enable_if.hpp> #include <boost/utility/enable_if.hpp>
#include <boost/ref.hpp> #include <boost/ref.hpp>
@ -26,9 +26,10 @@ namespace mock
explicit matcher( Expected expected ) explicit matcher( Expected expected )
: expected_( expected ) : expected_( expected )
{} {}
bool operator()( Actual actual ) bool operator()( const Actual& actual )
{ {
return actual == boost::unwrap_ref( expected_ ); return mock::equal(
boost::unwrap_ref( expected_ ) ).c_( actual );
} }
friend std::ostream& operator<<( friend std::ostream& operator<<(
std::ostream& s, const matcher& m ) std::ostream& s, const matcher& m )
@ -66,9 +67,9 @@ namespace mock
explicit matcher( const constraint< Constraint >& c ) explicit matcher( const constraint< Constraint >& c )
: c_( c.c_ ) : c_( c.c_ )
{} {}
bool operator()( Actual actual ) bool operator()( BOOST_RV_REF(Actual) actual )
{ {
return c_( actual ); return c_( boost::forward< Actual >( actual ) );
} }
friend std::ostream& operator<<( friend std::ostream& operator<<(
std::ostream& s, const matcher& m ) std::ostream& s, const matcher& m )
@ -90,9 +91,9 @@ namespace mock
explicit matcher( const Functor& f ) explicit matcher( const Functor& f )
: c_( f ) : c_( f )
{} {}
bool operator()( Actual actual ) bool operator()( BOOST_RV_REF(Actual) actual )
{ {
return c_( actual ); return c_( boost::forward< Actual >( actual ) );
} }
friend std::ostream& operator<<( friend std::ostream& operator<<(
std::ostream& s, const matcher& m ) std::ostream& s, const matcher& m )

View file

@ -47,14 +47,41 @@ BOOST_AUTO_TEST_CASE( equal_constraint )
BOOST_CHECK( ! mock::equal( std::string( "string" ) ).c_( "not string" ) ); BOOST_CHECK( ! mock::equal( std::string( "string" ) ).c_( "not string" ) );
{ {
std::string s; std::string s;
mock::constraint< auto c = mock::equal( boost::cref( s ) );
mock::detail::equal<
boost::reference_wrapper< const std::string >
>
> c = mock::equal( boost::cref( s ) );
s = "string"; s = "string";
BOOST_CHECK( c.c_( "string" ) ); BOOST_CHECK( c.c_( "string" ) );
} }
#ifdef MOCK_SMART_PTR
{
std::unique_ptr< int > i;
std::unique_ptr< int > j( new int( 3 ) );
BOOST_CHECK( ! mock::equal( i ).c_( j ) );
BOOST_CHECK( ! mock::equal( j ).c_( i ) );
BOOST_CHECK( mock::equal( i ).c_( i ) );
BOOST_CHECK( mock::equal( j ).c_( j ) );
}
#endif
}
BOOST_AUTO_TEST_CASE( equal_constraint_deref )
{
{
int i = 3;
BOOST_CHECK( mock::equal( 3 ).c_( &i ) );
BOOST_CHECK( ! mock::equal( 7 ).c_( &i ) );
}
{
int* i = 0;
BOOST_CHECK( ! mock::equal( 3 ).c_( i ) );
}
#ifdef MOCK_SMART_PTR
{
std::unique_ptr< int > j( new int( 3 ) );
BOOST_CHECK( mock::equal( 3 ).c_( j ) );
std::unique_ptr< int > i;
BOOST_CHECK( ! mock::equal( 3 ).c_( i ) );
}
#endif // MOCK_SMART_PTR
} }
BOOST_AUTO_TEST_CASE( same_constraint ) BOOST_AUTO_TEST_CASE( same_constraint )
@ -104,6 +131,12 @@ BOOST_AUTO_TEST_CASE( assign_constraint )
BOOST_CHECK( mock::assign( &j ).c_( i ) ); BOOST_CHECK( mock::assign( &j ).c_( i ) );
BOOST_CHECK_EQUAL( &j, i ); BOOST_CHECK_EQUAL( &j, i );
} }
{
int* i = 0;
const int j = 1;
BOOST_CHECK( ! mock::assign( j ).c_( i ) );
BOOST_CHECK( ! i );
}
{ {
int i = 0; int i = 0;
int j = 1; int j = 1;
@ -219,6 +252,16 @@ BOOST_AUTO_TEST_CASE( retrieve_constraint )
BOOST_CHECK_EQUAL( i, &j ); BOOST_CHECK_EQUAL( i, &j );
} }
#endif #endif
#ifdef MOCK_SMART_PTR
{
std::unique_ptr< int > i;
std::unique_ptr< int > j( new int( 3 ) );
BOOST_CHECK( mock::retrieve( i ).c_( boost::move( j ) ) );
BOOST_REQUIRE( i );
BOOST_CHECK_EQUAL( 3, *i );
BOOST_CHECK( !j );
}
#endif
} }
namespace namespace
@ -243,12 +286,22 @@ BOOST_AUTO_TEST_CASE( retrieve_constraint_uses_assignment_operator )
} }
BOOST_AUTO_TEST_CASE( affirm_constraint ) BOOST_AUTO_TEST_CASE( affirm_constraint )
{
{ {
int* i = 0; int* i = 0;
int j; int j;
BOOST_CHECK( ! mock::affirm.c_( i ) ); BOOST_CHECK( ! mock::affirm.c_( i ) );
BOOST_CHECK( mock::affirm.c_( &j ) ); BOOST_CHECK( mock::affirm.c_( &j ) );
} }
{
#ifdef MOCK_SMART_PTR
std::unique_ptr< int > i;
std::unique_ptr< int > j( new int( 3 ) );
BOOST_CHECK( ! mock::affirm.c_( i ) );
BOOST_CHECK( mock::affirm.c_( j ) );
#endif
}
}
BOOST_AUTO_TEST_CASE( negate_constraint ) BOOST_AUTO_TEST_CASE( negate_constraint )
{ {

View file

@ -704,3 +704,56 @@ BOOST_FIXTURE_TEST_CASE( mock_method_accepts_polymorphic_multi_constraint, mock_
m.m2( 1, 2 ); m.m2( 1, 2 );
CHECK_CALLS( 1 ); CHECK_CALLS( 1 );
} }
#ifdef MOCK_SMART_PTR
BOOST_FIXTURE_TEST_CASE( std_unique_ptr_argument_is_supported_in_action, mock_error_fixture )
{
MOCK_FUNCTOR( f, void( std::unique_ptr< int > ) );
std::unique_ptr< int > p;
MOCK_EXPECT( f ).once().calls(
[]( std::unique_ptr< int > )
{
} );
f( std::unique_ptr< int >( new int( 7 ) ) );
CHECK_CALLS( 1 );
}
BOOST_FIXTURE_TEST_CASE( std_unique_ptr_argument_is_supported_in_equal_constraint, mock_error_fixture )
{
{
MOCK_FUNCTOR( f, void( std::unique_ptr< int > ) );
MOCK_EXPECT( f ).once().with( mock::equal( 7 ) );
f( std::unique_ptr< int >( new int( 7 ) ) );
CHECK_CALLS( 1 );
}
{
MOCK_FUNCTOR( f, void( std::unique_ptr< int > ) );
MOCK_EXPECT( f ).once().with( 7 );
f( std::unique_ptr< int >( new int( 7 ) ) );
CHECK_CALLS( 1 );
}
}
BOOST_FIXTURE_TEST_CASE( std_unique_ptr_argument_is_supported_in_retrieve_constraint, mock_error_fixture )
{
{
MOCK_FUNCTOR( f, void( std::unique_ptr< int > ) );
MOCK_EXPECT( f ).once().with( nullptr );
f( 0 );
CHECK_CALLS( 1 );
}
{
std::unique_ptr< int > i;
MOCK_FUNCTOR( f, void( std::unique_ptr< int > ) );
MOCK_EXPECT( f ).once().with( mock::retrieve( i ) );
std::unique_ptr< int > j( new int( 7 ) );
f( std::move( j ) );
BOOST_CHECK( !j );
BOOST_REQUIRE( i );
BOOST_CHECK_EQUAL( 7, *i );
CHECK_CALLS( 1 );
}
}
#endif