From bccd3ff3036bfd5e6f7f3df3d1a5ddccc3538094 Mon Sep 17 00:00:00 2001 From: Mathieu Champlon Date: Mon, 12 Mar 2018 08:26:18 +0100 Subject: [PATCH] Added support for move only types to constraints Therefore mock::retrieve now supports std::unique_ptr. --- doc/changelog.qbk | 1 + include/turtle/constraints.hpp | 13 ++++++++++++ .../turtle/detail/expectation_template.hpp | 19 ++++++++--------- .../turtle/detail/function_impl_template.hpp | 2 +- .../turtle/detail/matcher_base_template.hpp | 5 +---- include/turtle/matcher.hpp | 8 +++---- test/test_constraints.cpp | 10 +++++++++ test/test_integration.cpp | 21 +++++++++++++++++++ 8 files changed, 60 insertions(+), 19 deletions(-) diff --git a/doc/changelog.qbk b/doc/changelog.qbk index 4b52eb2..303f163 100644 --- a/doc/changelog.qbk +++ b/doc/changelog.qbk @@ -16,6 +16,7 @@ Not yet released * 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/include/turtle/constraints.hpp b/include/turtle/constraints.hpp index 7541990..780f37f 100644 --- a/include/turtle/constraints.hpp +++ b/include/turtle/constraints.hpp @@ -183,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*, diff --git a/include/turtle/detail/expectation_template.hpp b/include/turtle/detail/expectation_template.hpp index 4dd0c7c..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,8 +23,8 @@ #define MOCK_EXPECTATION_SERIALIZE_ANY(z, n, d) \ BOOST_PP_IF(n, << ", " <<,) "any" -#define MOCK_CALL_PARAM_TYPE(z, n, d) \ - typename boost::call_traits< T##n >::param_type +#define MOCK_EXPECTATION_PARAM(z, n, Args) \ + boost::forward< T##n >( a##n ) namespace mock { @@ -39,7 +39,7 @@ namespace detail { private: virtual bool operator()( - BOOST_PP_ENUM(MOCK_NUM_ARGS, MOCK_CALL_PARAM_TYPE, _) ) + BOOST_PP_ENUM_PARAMS(MOCK_NUM_ARGS, T) ) { return true; } @@ -73,7 +73,7 @@ namespace detail private: virtual bool operator()( - BOOST_PP_ENUM(MOCK_NUM_ARGS, MOCK_CALL_PARAM, _) ) + BOOST_PP_ENUM_BINARY_PARAMS(MOCK_NUM_ARGS, T, a) ) { return BOOST_PP_REPEAT(MOCK_NUM_ARGS, MOCK_EXPECTATION_IS_VALID, _); @@ -103,9 +103,9 @@ namespace detail private: virtual bool operator()( - BOOST_PP_ENUM(MOCK_NUM_ARGS, MOCK_CALL_PARAM, _) ) + 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,10 +201,10 @@ namespace detail } bool is_valid( - BOOST_PP_ENUM(MOCK_NUM_ARGS, MOCK_CALL_PARAM, _) ) const + 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 @@ -259,7 +259,6 @@ namespace detail } } // mock -#undef MOCK_CALL_PARAM_TYPE #undef MOCK_EXPECTATION_INITIALIZE #undef MOCK_EXPECTATION_MEMBER #undef MOCK_EXPECTATION_IS_VALID diff --git a/include/turtle/detail/function_impl_template.hpp b/include/turtle/detail/function_impl_template.hpp index c60ce6f..044195f 100644 --- a/include/turtle/detail/function_impl_template.hpp +++ b/include/turtle/detail/function_impl_template.hpp @@ -216,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() ) { diff --git a/include/turtle/detail/matcher_base_template.hpp b/include/turtle/detail/matcher_base_template.hpp index 79bc17b..c1f1fa7 100644 --- a/include/turtle/detail/matcher_base_template.hpp +++ b/include/turtle/detail/matcher_base_template.hpp @@ -6,9 +6,6 @@ // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) -#define MOCK_CALL_PARAM(z, n, d) \ - typename boost::call_traits< T##n >::param_type a##n - namespace mock { namespace detail @@ -24,7 +21,7 @@ namespace detail virtual ~matcher_base() {} virtual bool operator()( - BOOST_PP_ENUM(MOCK_NUM_ARGS, MOCK_CALL_PARAM, _) ) = 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 659ff67..91f1f23 100644 --- a/include/turtle/matcher.hpp +++ b/include/turtle/matcher.hpp @@ -67,9 +67,9 @@ namespace mock explicit matcher( const constraint< Constraint >& c ) : c_( c.c_ ) {} - bool operator()( const 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 ) @@ -91,9 +91,9 @@ namespace mock explicit matcher( const Functor& f ) : c_( f ) {} - bool operator()( const 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 d54a54e..27d1782 100644 --- a/test/test_constraints.cpp +++ b/test/test_constraints.cpp @@ -252,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 diff --git a/test/test_integration.cpp b/test/test_integration.cpp index 3626400..4b17cc4 100644 --- a/test/test_integration.cpp +++ b/test/test_integration.cpp @@ -721,4 +721,25 @@ BOOST_FIXTURE_TEST_CASE( std_unique_ptr_argument_is_supported_in_equal_constrain } } +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