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