From 15285a22ec725c96c35ce9a94d542e24ed258285 Mon Sep 17 00:00:00 2001 From: Mathieu Champlon Date: Mon, 15 Jan 2018 05:23:15 +0100 Subject: [PATCH 1/7] Cleaned code --- include/turtle/detail/action.hpp | 8 ++++---- include/turtle/detail/expectation_template.hpp | 4 ++-- include/turtle/detail/function_impl_template.hpp | 1 + 3 files changed, 7 insertions(+), 6 deletions(-) diff --git a/include/turtle/detail/action.hpp b/include/turtle/detail/action.hpp index 53f830f..f261d57 100644 --- a/include/turtle/detail/action.hpp +++ b/include/turtle/detail/action.hpp @@ -100,11 +100,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 +124,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 +138,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..0c2ac58 100644 --- a/include/turtle/detail/expectation_template.hpp +++ b/include/turtle/detail/expectation_template.hpp @@ -91,7 +91,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 ) @@ -102,7 +102,7 @@ namespace detail virtual bool operator()( 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_PARAMS(MOCK_NUM_ARGS, a) ); } virtual void serialize( std::ostream& s ) const { diff --git a/include/turtle/detail/function_impl_template.hpp b/include/turtle/detail/function_impl_template.hpp index 32f04b3..19cd6ff 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 ) From 58b5e55bb5564cd4b859b83a7a29ab09b262a116 Mon Sep 17 00:00:00 2001 From: Mathieu Champlon Date: Sun, 21 Jan 2018 11:22:50 +0100 Subject: [PATCH 2/7] Fixed alignement --- doc/reference.qbk | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/doc/reference.qbk b/doc/reference.qbk index eeb4d48..827b3d3 100644 --- a/doc/reference.qbk +++ b/doc/reference.qbk @@ -389,12 +389,12 @@ Constraints : [[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 +406,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.] From d3a5d3010c0181eb8deacdc7aedf2cb250e391b2 Mon Sep 17 00:00:00 2001 From: Mathieu Champlon Date: Mon, 15 Jan 2018 06:23:25 +0100 Subject: [PATCH 3/7] Fixed move-only type argument in actions Because boost::function does not move the parameters it receives we need to use std::function instead. --- doc/changelog.qbk | 1 + include/turtle/detail/action.hpp | 4 ++-- include/turtle/detail/expectation_template.hpp | 12 ++++++++---- include/turtle/detail/function.hpp | 1 + .../turtle/detail/function_impl_template.hpp | 2 +- include/turtle/detail/function_template.hpp | 17 +++++------------ include/turtle/detail/matcher_base_template.hpp | 9 ++++++--- test/test_integration.cpp | 16 ++++++++++++++++ 8 files changed, 40 insertions(+), 22 deletions(-) diff --git a/doc/changelog.qbk b/doc/changelog.qbk index 64aba81..e76e4ab 100644 --- a/doc/changelog.qbk +++ b/doc/changelog.qbk @@ -13,6 +13,7 @@ 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 [endsect] diff --git a/include/turtle/detail/action.hpp b/include/turtle/detail/action.hpp index f261d57..7e1fdb2 100644 --- a/include/turtle/detail/action.hpp +++ b/include/turtle/detail/action.hpp @@ -27,8 +27,8 @@ namespace detail class action_base { private: - typedef boost::function< Signature > functor_type; - typedef boost::function< Result() > action_type; + typedef std::function< Signature > functor_type; + typedef std::function< Result() > action_type; public: const functor_type& functor() const diff --git a/include/turtle/detail/expectation_template.hpp b/include/turtle/detail/expectation_template.hpp index 0c2ac58..4dd0c7c 100644 --- a/include/turtle/detail/expectation_template.hpp +++ b/include/turtle/detail/expectation_template.hpp @@ -23,6 +23,9 @@ #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 + namespace mock { namespace detail @@ -36,7 +39,7 @@ namespace detail { private: virtual bool operator()( - BOOST_PP_ENUM_PARAMS(MOCK_NUM_ARGS, T) ) + BOOST_PP_ENUM(MOCK_NUM_ARGS, MOCK_CALL_PARAM_TYPE, _) ) { return true; } @@ -70,7 +73,7 @@ namespace detail private: virtual bool operator()( - BOOST_PP_ENUM_BINARY_PARAMS(MOCK_NUM_ARGS, T, a) ) + BOOST_PP_ENUM(MOCK_NUM_ARGS, MOCK_CALL_PARAM, _) ) { return BOOST_PP_REPEAT(MOCK_NUM_ARGS, MOCK_EXPECTATION_IS_VALID, _); @@ -100,7 +103,7 @@ namespace detail private: virtual bool operator()( - BOOST_PP_ENUM_BINARY_PARAMS( MOCK_NUM_ARGS, T, a ) ) + BOOST_PP_ENUM(MOCK_NUM_ARGS, MOCK_CALL_PARAM, _) ) { return f_( BOOST_PP_ENUM_PARAMS(MOCK_NUM_ARGS, a) ); } @@ -198,7 +201,7 @@ namespace detail } bool is_valid( - BOOST_PP_ENUM_BINARY_PARAMS(MOCK_NUM_ARGS, T, a) ) const + BOOST_PP_ENUM(MOCK_NUM_ARGS, MOCK_CALL_PARAM, _) ) const { return !invocation_->exhausted() && (*matcher_)( BOOST_PP_ENUM_PARAMS(MOCK_NUM_ARGS, a) ); @@ -256,6 +259,7 @@ 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.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 19cd6ff..c60ce6f 100644 --- a/include/turtle/detail/function_impl_template.hpp +++ b/include/turtle/detail/function_impl_template.hpp @@ -235,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..79bc17b 100644 --- a/include/turtle/detail/matcher_base_template.hpp +++ b/include/turtle/detail/matcher_base_template.hpp @@ -6,6 +6,9 @@ // (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 @@ -13,15 +16,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(MOCK_NUM_ARGS, MOCK_CALL_PARAM, _) ) = 0; friend std::ostream& operator<<( std::ostream& s, const matcher_base& m ) diff --git a/test/test_integration.cpp b/test/test_integration.cpp index 71ed0c6..a93d979 100644 --- a/test/test_integration.cpp +++ b/test/test_integration.cpp @@ -690,3 +690,19 @@ 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 ); +} + +#endif From a2d36e961a2f77adf70cc8f4bb3cae067417aafe Mon Sep 17 00:00:00 2001 From: Mathieu Champlon Date: Tue, 16 Jan 2018 19:29:31 +0100 Subject: [PATCH 4/7] Fixed move-only type support in constraints --- doc/changelog.qbk | 1 + include/turtle/constraint.hpp | 15 ++++++++++----- test/test_constraints.cpp | 34 +++++++++++++++++++++++++--------- 3 files changed, 36 insertions(+), 14 deletions(-) diff --git a/doc/changelog.qbk b/doc/changelog.qbk index e76e4ab..36a82f6 100644 --- a/doc/changelog.qbk +++ b/doc/changelog.qbk @@ -14,6 +14,7 @@ Not yet released * 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 [endsect] diff --git a/include/turtle/constraint.hpp b/include/turtle/constraint.hpp index 32329c2..6654b71 100644 --- a/include/turtle/constraint.hpp +++ b/include/turtle/constraint.hpp @@ -19,6 +19,7 @@ #include #include #include +#include namespace mock { @@ -158,11 +159,14 @@ namespace detail #define MOCK_CONSTRAINT_CREF_PARAM(z, n, Args) \ typename \ - boost::unwrap_reference< Expected_##n >::type \ + const 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 +175,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 +203,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/test/test_constraints.cpp b/test/test_constraints.cpp index 60e3128..7fea74f 100644 --- a/test/test_constraints.cpp +++ b/test/test_constraints.cpp @@ -47,14 +47,20 @@ 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( same_constraint ) @@ -244,10 +250,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 ) From 5d11db0f52fd13ae3f8487d2a3ffecb8dfeca6f1 Mon Sep 17 00:00:00 2001 From: Mathieu Champlon Date: Wed, 17 Jan 2018 10:31:53 +0100 Subject: [PATCH 5/7] Added support for dereferencing in mock::equal --- doc/changelog.qbk | 1 + doc/example/patterns_quick_constraint.cpp | 5 ++- doc/reference.qbk | 6 ++- include/turtle/config.hpp | 6 +++ include/turtle/constraint.hpp | 5 +-- include/turtle/constraints.hpp | 47 ++++++++++++++++++++++- include/turtle/detail/action.hpp | 5 +++ include/turtle/matcher.hpp | 11 +++--- test/test_constraints.cpp | 27 +++++++++++++ test/test_integration.cpp | 16 ++++++++ 10 files changed, 117 insertions(+), 12 deletions(-) diff --git a/doc/changelog.qbk b/doc/changelog.qbk index 36a82f6..4b52eb2 100644 --- a/doc/changelog.qbk +++ b/doc/changelog.qbk @@ -15,6 +15,7 @@ Not yet released * 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 [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 827b3d3..434a630 100644 --- a/doc/reference.qbk +++ b/doc/reference.qbk @@ -384,7 +384,11 @@ 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 <=]] 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 6654b71..081c04d 100644 --- a/include/turtle/constraint.hpp +++ b/include/turtle/constraint.hpp @@ -158,9 +158,8 @@ namespace detail Expected_##n expected##n; #define MOCK_CONSTRAINT_CREF_PARAM(z, n, Args) \ - typename \ - const 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) diff --git a/include/turtle/constraints.hpp b/include/turtle/constraints.hpp index 77a142f..7541990 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 { @@ -187,6 +224,8 @@ namespace detail > >::type* = 0 ) const { + if( ! actual ) + return false; *actual = boost::unwrap_ref( expected_ ); return true; } @@ -216,6 +255,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 7e1fdb2..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 diff --git a/include/turtle/matcher.hpp b/include/turtle/matcher.hpp index 162301b..659ff67 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,7 +67,7 @@ namespace mock explicit matcher( const constraint< Constraint >& c ) : c_( c.c_ ) {} - bool operator()( Actual actual ) + bool operator()( const Actual& actual ) { return c_( actual ); } @@ -90,7 +91,7 @@ namespace mock explicit matcher( const Functor& f ) : c_( f ) {} - bool operator()( Actual actual ) + bool operator()( const Actual& actual ) { return c_( actual ); } diff --git a/test/test_constraints.cpp b/test/test_constraints.cpp index 7fea74f..d54a54e 100644 --- a/test/test_constraints.cpp +++ b/test/test_constraints.cpp @@ -63,6 +63,27 @@ BOOST_AUTO_TEST_CASE( equal_constraint ) #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 ) { { @@ -110,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; diff --git a/test/test_integration.cpp b/test/test_integration.cpp index a93d979..3626400 100644 --- a/test/test_integration.cpp +++ b/test/test_integration.cpp @@ -705,4 +705,20 @@ BOOST_FIXTURE_TEST_CASE( std_unique_ptr_argument_is_supported_in_action, mock_er 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 ); + } +} + #endif From 5795f4be709c3d0a16408abcd707c608671198d2 Mon Sep 17 00:00:00 2001 From: Mathieu Champlon Date: Mon, 12 Mar 2018 08:24:20 +0100 Subject: [PATCH 6/7] Added Visual Studio Code configuration folder to gitignore --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 17f91c4..02e5fb3 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ +.vscode bin out build/xsl From bccd3ff3036bfd5e6f7f3df3d1a5ddccc3538094 Mon Sep 17 00:00:00 2001 From: Mathieu Champlon Date: Mon, 12 Mar 2018 08:26:18 +0100 Subject: [PATCH 7/7] 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