diff --git a/.gitignore b/.gitignore index 17f91c4..02e5fb3 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ +.vscode bin out build/xsl diff --git a/doc/changelog.qbk b/doc/changelog.qbk index 64aba81..303f163 100644 --- a/doc/changelog.qbk +++ b/doc/changelog.qbk @@ -13,6 +13,10 @@ Not yet released * Fixed mocking of a function returning a reference for gcc 4.1 * Added MOCK_NO_AUTO_PTR to deactivate std::auto_ptr support * 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] diff --git a/doc/example/patterns_quick_constraint.cpp b/doc/example/patterns_quick_constraint.cpp index f3bc053..a331bdc 100644 --- a/doc/example/patterns_quick_constraint.cpp +++ b/doc/example/patterns_quick_constraint.cpp @@ -18,10 +18,11 @@ namespace { public: explicit my_class( int data ) - : data_( data ) + : data_( data ) {} int data_; }; + std::ostream& operator<<( std::ostream& os, const my_class& c ) // my_class is serializable to an std::ostream { return os << "my_class( " << c.data_ << " )"; @@ -37,7 +38,7 @@ namespace //[ quick_constraint_solution #include -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 { diff --git a/doc/reference.qbk b/doc/reference.qbk index eeb4d48..434a630 100644 --- a/doc/reference.qbk +++ b/doc/reference.qbk @@ -384,17 +384,21 @@ Constraints : calls ['expected] as a functor returning a ['bool], throws std::invalid_argument if ! ['expected] 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::greater( ['expected] )] [['actual] > ['expected]] [compares ['actual] to ['expected] using operator >]] [[mock::less_equal( ['expected] )] [['actual] <= ['expected]] [compares ['actual] to ['expected] using operator <=]] [[mock::greater_equal( ['expected] )] [['actual] >= ['expected]] [compares ['actual] to ['expected] using operator >=]] - [[mock::near( ['expected], ['tolerance] )] [std::abs( ['actual] - ['expected] ) < ['tolerance]] [checks whether ['actual] is near ['expected] within ['tolerance]]] - [[mock::close( ['expected], ['tolerance] )] [boost::test_tools::check_is_close( ['actual], ['expected], boost::test_tools::percent_tolerance( ['arg] ) )] [checks whether ['actual] is close to ['expected], see [@http://www.boost.org/libs/test/doc/html/boost_test/testing_tools/extended_comparison/floating_point.html Floating-point comparison algorithms] ]] - [[mock::close_fraction( ['expected], ['tolerance] )] [boost::test_tools::check_is_close( ['actual], ['expected], boost::test_tools::fraction_tolerance( ['arg] ) )] [checks whether ['actual] is close to ['expected], see [@http://www.boost.org/libs/test/doc/html/boost_test/testing_tools/extended_comparison/floating_point.html Floating-point comparison algorithms] ]] - [[mock::small( ['tolerance] )] [boost::test_tools::check_is_small( ['actual], ['expected] ) )] [checks whether ['actual] is small within ['tolerance], see [@http://www.boost.org/libs/test/doc/html/boost_test/testing_tools/extended_comparison/floating_point.html Floating-point comparison algorithms] ]] - [[mock::call( ['expected] )] [['expected]( ['actual] )] [calls ['expected] as a functor returning a ['bool] and accepting ['actual] as parameter]] - [[mock::same( ['expected] )] [&['actual] == &['expected]] [compares ['actual] to ['expected] by comparing their pointers]] + [[mock::near( ['expected], ['tolerance] )] [std::abs( ['actual] - ['expected] ) < ['tolerance]] [checks whether ['actual] is near ['expected] within ['tolerance]]] + [[mock::close( ['expected], ['tolerance] )] [boost::test_tools::check_is_close( ['actual], ['expected], boost::test_tools::percent_tolerance( ['arg] ) )] [checks whether ['actual] is close to ['expected], see [@http://www.boost.org/libs/test/doc/html/boost_test/testing_tools/extended_comparison/floating_point.html Floating-point comparison algorithms] ]] + [[mock::close_fraction( ['expected], ['tolerance] )] [boost::test_tools::check_is_close( ['actual], ['expected], boost::test_tools::fraction_tolerance( ['arg] ) )] [checks whether ['actual] is close to ['expected], see [@http://www.boost.org/libs/test/doc/html/boost_test/testing_tools/extended_comparison/floating_point.html Floating-point comparison algorithms] ]] + [[mock::small( ['tolerance] )] [boost::test_tools::check_is_small( ['actual], ['expected] ) )] [checks whether ['actual] is small within ['tolerance], see [@http://www.boost.org/libs/test/doc/html/boost_test/testing_tools/extended_comparison/floating_point.html Floating-point comparison algorithms] ]] + [[mock::call( ['expected] )] [['expected]( ['actual] )] [calls ['expected] as a functor returning a ['bool] and accepting ['actual] as parameter]] + [[mock::same( ['expected] )] [&['actual] == &['expected]] [compares ['actual] to ['expected] by comparing their pointers]] [[mock::assign( ['expected] )] [['actual] = ['expected], true *['actual] = ['expected], true] [assigns ['expected] to ['actual] using operator = @@ -406,9 +410,9 @@ Constraints : 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::affirm] [['actual]] [uses ['actual] as a boolean]] - [[mock::negate] [! ['actual]] [negates ['actual] using operator !]] - [[mock::evaluate] [['actual]()] [evaluates ['actual] as a functor returning a bool and taking no argument]] + [[mock::affirm] [['actual]] [uses ['actual] as a ['bool]]] + [[mock::negate] [! ['actual]] [negates ['actual] using operator !]] + [[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.] diff --git a/include/turtle/config.hpp b/include/turtle/config.hpp index 1bd4a6b..5d2f78e 100644 --- a/include/turtle/config.hpp +++ b/include/turtle/config.hpp @@ -70,6 +70,12 @@ # 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) # ifndef MOCK_NO_HDR_MUTEX # define MOCK_HDR_MUTEX diff --git a/include/turtle/constraint.hpp b/include/turtle/constraint.hpp index 32329c2..081c04d 100644 --- a/include/turtle/constraint.hpp +++ b/include/turtle/constraint.hpp @@ -19,6 +19,7 @@ #include #include #include +#include namespace mock { @@ -157,12 +158,14 @@ namespace detail Expected_##n expected##n; #define MOCK_CONSTRAINT_CREF_PARAM(z, n, Args) \ - typename \ - boost::unwrap_reference< Expected_##n >::type \ - BOOST_PP_ARRAY_ELEM(n, Args) + const typename boost::unwrap_reference< Expected_##n >::type& \ + 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) \ - 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) \ namespace detail \ @@ -171,7 +174,7 @@ namespace detail struct 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, _) \ {} \ template< typename Actual > \ @@ -199,9 +202,10 @@ namespace detail template< BOOST_PP_ENUM_PARAMS(n, typename T) > \ mock::constraint< \ 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) \ diff --git a/include/turtle/constraints.hpp b/include/turtle/constraints.hpp index 77a142f..780f37f 100644 --- a/include/turtle/constraints.hpp +++ b/include/turtle/constraints.hpp @@ -17,6 +17,7 @@ #include #include #include +#include #include namespace mock @@ -26,7 +27,6 @@ namespace mock MOCK_UNARY_CONSTRAINT( negate, 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( greater, 1, ( expected ), actual > expected ) MOCK_NARY_CONSTRAINT( less_equal, 1, ( expected ), actual <= expected ) @@ -107,6 +107,43 @@ 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 > struct same { @@ -146,6 +183,19 @@ namespace detail return true; } 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, typename boost::enable_if< boost::is_convertible< Actual*, @@ -187,6 +237,8 @@ namespace detail > >::type* = 0 ) const { + if( ! actual ) + return false; *actual = boost::unwrap_ref( expected_ ); 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 > constraint< detail::same< T > > same( T& t ) { diff --git a/include/turtle/detail/action.hpp b/include/turtle/detail/action.hpp index 53f830f..8c49633 100644 --- a/include/turtle/detail/action.hpp +++ b/include/turtle/detail/action.hpp @@ -27,8 +27,13 @@ namespace detail class action_base { 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< Result() > action_type; +#endif public: const functor_type& functor() const @@ -100,11 +105,11 @@ namespace detail } template< typename Value > - void moves( BOOST_RV_REF( Value ) v ) + void moves( BOOST_RV_REF(Value) v ) { this->set( boost::bind( - &boost::move< BOOST_RV_REF( Value ) >, + &boost::move< BOOST_RV_REF(Value) >, boost::ref( store( boost::move( v ) ) ) ) ); } @@ -124,7 +129,7 @@ namespace detail >::type >::type value_type; - value_imp( BOOST_RV_REF( value_type ) t ) + value_imp( BOOST_RV_REF(value_type) t ) : t_( boost::move( t ) ) {} value_imp( const T& t ) @@ -138,7 +143,7 @@ namespace detail }; template< typename T > - T& store( BOOST_RV_REF( T ) t ) + T& store( BOOST_RV_REF(T) t ) { v_.reset( new value_imp< T >( boost::move( t ) ) ); return static_cast< value_imp< T >& >( *v_ ).t_; diff --git a/include/turtle/detail/expectation_template.hpp b/include/turtle/detail/expectation_template.hpp index a4f14a0..e404460 100644 --- a/include/turtle/detail/expectation_template.hpp +++ b/include/turtle/detail/expectation_template.hpp @@ -15,7 +15,7 @@ matcher< T##n, Constraint_##n > c##n##_; #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) \ BOOST_PP_IF(n, << ", " <<,) c##n##_ @@ -23,6 +23,9 @@ #define MOCK_EXPECTATION_SERIALIZE_ANY(z, n, d) \ BOOST_PP_IF(n, << ", " <<,) "any" +#define MOCK_EXPECTATION_PARAM(z, n, Args) \ + boost::forward< T##n >( a##n ) + namespace mock { namespace detail @@ -91,7 +94,7 @@ namespace detail template< typename F, BOOST_PP_ENUM_PARAMS(MOCK_NUM_ARGS, typename T) > class multi_matcher< F, void( BOOST_PP_ENUM_PARAMS(MOCK_NUM_ARGS, T) ) > - : public matcher_base< void( BOOST_PP_ENUM_PARAMS(MOCK_NUM_ARGS,T) ) > + : public matcher_base< void( BOOST_PP_ENUM_PARAMS(MOCK_NUM_ARGS, T) ) > { public: multi_matcher( const F& f ) @@ -100,9 +103,9 @@ namespace detail private: 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 { @@ -201,7 +204,7 @@ namespace detail BOOST_PP_ENUM_BINARY_PARAMS(MOCK_NUM_ARGS, T, a) ) const { 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 diff --git a/include/turtle/detail/function.hpp b/include/turtle/detail/function.hpp index 4a48220..837b169 100644 --- a/include/turtle/detail/function.hpp +++ b/include/turtle/detail/function.hpp @@ -33,6 +33,7 @@ #include #include #include +#include #include #include #include diff --git a/include/turtle/detail/function_impl_template.hpp b/include/turtle/detail/function_impl_template.hpp index 32f04b3..044195f 100644 --- a/include/turtle/detail/function_impl_template.hpp +++ b/include/turtle/detail/function_impl_template.hpp @@ -144,6 +144,7 @@ namespace detail BOOST_PP_ENUM_PARAMS(MOCK_NUM_ARGS, c) ); return *this; } + #if MOCK_NUM_ARGS > 1 template< typename Constraint > wrapper with( const Constraint& c ) @@ -215,7 +216,7 @@ namespace detail for( expectations_cit it = expectations_.begin(); it != expectations_.end(); ++it ) if( it->is_valid( - BOOST_PP_ENUM_PARAMS(MOCK_NUM_ARGS, t) ) ) + BOOST_PP_ENUM(MOCK_NUM_ARGS, MOCK_FORWARD, _) ) ) { if( ! it->invoke() ) { @@ -234,7 +235,7 @@ namespace detail MOCK_FUNCTION_CONTEXT, it->file(), it->line() ); if( it->functor() ) return it->functor()( - BOOST_PP_ENUM_PARAMS(MOCK_NUM_ARGS, t) ); + BOOST_PP_ENUM(MOCK_NUM_ARGS, MOCK_FORWARD, _) ); return it->trigger(); } error_type::fail( "unexpected call", MOCK_FUNCTION_CONTEXT ); diff --git a/include/turtle/detail/function_template.hpp b/include/turtle/detail/function_template.hpp index f356eca..04a0ad2 100644 --- a/include/turtle/detail/function_template.hpp +++ b/include/turtle/detail/function_template.hpp @@ -8,12 +8,8 @@ #include "function_impl_template.hpp" -#define MOCK_FUNCTION_CALL(z, n, d ) \ - BOOST_PP_COMMA_IF(n) typename \ - boost::call_traits< T##n >::param_type - -#define MOCK_FUNCTION_PARAM(z, n, d) \ - MOCK_FUNCTION_CALL(z, n, d) t##n +#define MOCK_FORWARD(z, n, d) \ + boost::forward< T##n >( t##n ) namespace mock { @@ -36,7 +32,7 @@ namespace detail private: typedef function_impl< - R ( BOOST_PP_REPEAT(MOCK_NUM_ARGS, MOCK_FUNCTION_CALL, _) ) + R ( BOOST_PP_ENUM_PARAMS(MOCK_NUM_ARGS, T) ) > impl_type; typedef typename impl_type::wrapper_type expectation_type; typedef typename impl_type::error_type error_type; @@ -76,9 +72,9 @@ namespace detail } 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 ) @@ -106,6 +102,3 @@ namespace detail }; } } // mock - -#undef MOCK_FUNCTION_CALL -#undef MOCK_FUNCTION_PARAM diff --git a/include/turtle/detail/matcher_base_template.hpp b/include/turtle/detail/matcher_base_template.hpp index d3d0993..c1f1fa7 100644 --- a/include/turtle/detail/matcher_base_template.hpp +++ b/include/turtle/detail/matcher_base_template.hpp @@ -13,15 +13,15 @@ namespace detail template< typename Signature > class matcher_base; template< - BOOST_PP_ENUM_PARAMS(MOCK_NUM_ARGS, typename Actual_) > - class matcher_base< void( BOOST_PP_ENUM_PARAMS(MOCK_NUM_ARGS, Actual_) ) > + BOOST_PP_ENUM_PARAMS(MOCK_NUM_ARGS, typename T) > + class matcher_base< void( BOOST_PP_ENUM_PARAMS(MOCK_NUM_ARGS, T) ) > : boost::noncopyable { public: virtual ~matcher_base() {} 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<<( std::ostream& s, const matcher_base& m ) diff --git a/include/turtle/matcher.hpp b/include/turtle/matcher.hpp index 162301b..91f1f23 100644 --- a/include/turtle/matcher.hpp +++ b/include/turtle/matcher.hpp @@ -11,7 +11,7 @@ #include "config.hpp" #include "log.hpp" -#include "constraint.hpp" +#include "constraints.hpp" #include "detail/is_functor.hpp" #include #include @@ -26,9 +26,10 @@ namespace mock explicit matcher( 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<<( std::ostream& s, const matcher& m ) @@ -66,9 +67,9 @@ namespace mock explicit matcher( const constraint< Constraint >& 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<<( std::ostream& s, const matcher& m ) @@ -90,9 +91,9 @@ namespace mock explicit matcher( const Functor& 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<<( std::ostream& s, const matcher& m ) diff --git a/test/test_constraints.cpp b/test/test_constraints.cpp index 60e3128..27d1782 100644 --- a/test/test_constraints.cpp +++ b/test/test_constraints.cpp @@ -47,14 +47,41 @@ BOOST_AUTO_TEST_CASE( equal_constraint ) BOOST_CHECK( ! mock::equal( std::string( "string" ) ).c_( "not string" ) ); { std::string s; - mock::constraint< - mock::detail::equal< - boost::reference_wrapper< const std::string > - > - > c = mock::equal( boost::cref( s ) ); + auto c = mock::equal( boost::cref( s ) ); s = "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 ) @@ -104,6 +131,12 @@ BOOST_AUTO_TEST_CASE( assign_constraint ) BOOST_CHECK( mock::assign( &j ).c_( 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 j = 1; @@ -219,6 +252,16 @@ BOOST_AUTO_TEST_CASE( retrieve_constraint ) BOOST_CHECK_EQUAL( i, &j ); } #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 @@ -244,10 +287,20 @@ BOOST_AUTO_TEST_CASE( retrieve_constraint_uses_assignment_operator ) BOOST_AUTO_TEST_CASE( affirm_constraint ) { - int* i = 0; - int j; - BOOST_CHECK( ! mock::affirm.c_( i ) ); - BOOST_CHECK( mock::affirm.c_( &j ) ); + { + int* i = 0; + int j; + BOOST_CHECK( ! mock::affirm.c_( i ) ); + 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 ) diff --git a/test/test_integration.cpp b/test/test_integration.cpp index d212b8c..e3bef9e 100644 --- a/test/test_integration.cpp +++ b/test/test_integration.cpp @@ -704,3 +704,56 @@ BOOST_FIXTURE_TEST_CASE( mock_method_accepts_polymorphic_multi_constraint, mock_ m.m2( 1, 2 ); 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