From 176611c735a31af6421302cd5096d7ecf695bb27 Mon Sep 17 00:00:00 2001 From: mat007 Date: Mon, 10 Jan 2011 14:22:32 +0000 Subject: [PATCH] Enhanced custom constraints support git-svn-id: https://svn.code.sf.net/p/turtle/code/trunk@178 860be788-9bd5-4423-9f1e-828f051e677b --- build/vc100/turtle.vcxproj | 2 +- build/vc100/turtle.vcxproj.filters | 6 +-- build/vc100/turtle_test.vcxproj | 1 + build/vc100/turtle_test.vcxproj.filters | 3 ++ build/vc80/turtle.vcproj | 4 ++ build/vc80/turtle_test.vcproj | 4 ++ src/libraries/turtle/check.hpp | 13 ++++-- src/libraries/turtle/has_operator.hpp | 34 ++++++++++++++ src/tests/turtle_test/has_operator_test.cpp | 35 +++++++++++++++ src/tests/turtle_test/integration_test.cpp | 49 +++++++++++++++++++++ 10 files changed, 144 insertions(+), 7 deletions(-) create mode 100644 src/libraries/turtle/has_operator.hpp create mode 100644 src/tests/turtle_test/has_operator_test.cpp diff --git a/build/vc100/turtle.vcxproj b/build/vc100/turtle.vcxproj index 19ce6a4..da3c4dd 100644 --- a/build/vc100/turtle.vcxproj +++ b/build/vc100/turtle.vcxproj @@ -148,7 +148,7 @@ - + diff --git a/build/vc100/turtle.vcxproj.filters b/build/vc100/turtle.vcxproj.filters index 1ad3f82..bbfd10d 100644 --- a/build/vc100/turtle.vcxproj.filters +++ b/build/vc100/turtle.vcxproj.filters @@ -37,9 +37,6 @@ Source Files - - Source Files - Source Files @@ -73,5 +70,8 @@ Source Files + + Source Files + \ No newline at end of file diff --git a/build/vc100/turtle_test.vcxproj b/build/vc100/turtle_test.vcxproj index e8343dc..ca7de70 100644 --- a/build/vc100/turtle_test.vcxproj +++ b/build/vc100/turtle_test.vcxproj @@ -199,6 +199,7 @@ + diff --git a/build/vc100/turtle_test.vcxproj.filters b/build/vc100/turtle_test.vcxproj.filters index 7ab6ed9..f489b3d 100644 --- a/build/vc100/turtle_test.vcxproj.filters +++ b/build/vc100/turtle_test.vcxproj.filters @@ -40,6 +40,9 @@ Source Files + + Source Files + diff --git a/build/vc80/turtle.vcproj b/build/vc80/turtle.vcproj index 12d874f..5856283 100644 --- a/build/vc80/turtle.vcproj +++ b/build/vc80/turtle.vcproj @@ -192,6 +192,10 @@ RelativePath="..\..\src\libraries\turtle\functional.hpp" > + + diff --git a/build/vc80/turtle_test.vcproj b/build/vc80/turtle_test.vcproj index 492812c..902d25a 100644 --- a/build/vc80/turtle_test.vcproj +++ b/build/vc80/turtle_test.vcproj @@ -206,6 +206,10 @@ RelativePath="..\..\src\tests\turtle_test\function_test.cpp" > + + diff --git a/src/libraries/turtle/check.hpp b/src/libraries/turtle/check.hpp index d6fb2ac..15a2a33 100644 --- a/src/libraries/turtle/check.hpp +++ b/src/libraries/turtle/check.hpp @@ -11,6 +11,7 @@ #include "placeholder.hpp" #include "is_functor.hpp" +#include "has_operator.hpp" #include "constraints.hpp" #include "format.hpp" #include @@ -67,9 +68,12 @@ namespace detail template< typename Functor > explicit check( const Functor& f, BOOST_DEDUCED_TYPENAME boost::enable_if< - BOOST_DEDUCED_TYPENAME detail::is_functor< Functor > + BOOST_DEDUCED_TYPENAME boost::mpl::or_< + BOOST_DEDUCED_TYPENAME detail::is_functor< Functor >, + BOOST_DEDUCED_TYPENAME detail::has_operator< Functor, Actual > // $$$$ MAT : add a has_const_operator too ? + > >::type* = 0 ) - : desc_( "?" ) + : desc_( mock::format( f ) ) { BOOST_CONCEPT_ASSERT(( FunctorCompatible< Functor, Actual > )); f_ = f; @@ -79,7 +83,10 @@ namespace detail template< typename Expected > explicit check( const Expected& expected, BOOST_DEDUCED_TYPENAME boost::disable_if< - BOOST_DEDUCED_TYPENAME detail::is_functor< Expected > + BOOST_DEDUCED_TYPENAME boost::mpl::or_< + BOOST_DEDUCED_TYPENAME detail::is_functor< Expected >, + BOOST_DEDUCED_TYPENAME detail::has_operator< Expected, Actual > + > >::type* = 0 ) : desc_( mock::format( expected ) ) { diff --git a/src/libraries/turtle/has_operator.hpp b/src/libraries/turtle/has_operator.hpp new file mode 100644 index 0000000..11184ee --- /dev/null +++ b/src/libraries/turtle/has_operator.hpp @@ -0,0 +1,34 @@ +// +// Copyright Mathieu Champlon 2011 +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef MOCK_HAS_OPERATOR_HPP_INCLUDED +#define MOCK_HAS_OPERATOR_HPP_INCLUDED + +#include +#include +#include + +namespace mock +{ +namespace detail +{ + typedef boost::type_traits::yes_type yes_type; + typedef boost::type_traits::no_type no_type; + + template< typename T, typename Actual, bool(T::*)( Actual ) const > struct has_operator_helper_class {}; + + template< typename T, typename Actual > yes_type& has_operator_helper( has_operator_helper_class< T, Actual, &T::operator() >* ); + template< typename T, typename Actual > no_type& has_operator_helper( ... ); + + template< typename T, typename Actual > struct has_operator + : boost::mpl::bool_< sizeof( has_operator_helper< T, Actual >( 0 ) ) == sizeof( yes_type ) > + {}; +} +} + +#endif // #ifndef MOCK_HAS_OPERATOR_HPP_INCLUDED diff --git a/src/tests/turtle_test/has_operator_test.cpp b/src/tests/turtle_test/has_operator_test.cpp new file mode 100644 index 0000000..0cc6c5b --- /dev/null +++ b/src/tests/turtle_test/has_operator_test.cpp @@ -0,0 +1,35 @@ +// +// Copyright Mathieu Champlon 2009 +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// + +#include + +#include +#define BOOST_LIB_NAME boost_unit_test_framework +#include + +namespace +{ + struct functor_with_valid_operator + { + bool operator()( float ) const + { + return true; + } + }; + BOOST_STATIC_ASSERT(( mock::detail::has_operator< functor_with_valid_operator, float >::type::value )); + + struct functor_with_valid_template_operator + { + template< typename T > + bool operator()( T ) const + { + return true; + } + }; + BOOST_STATIC_ASSERT(( mock::detail::has_operator< functor_with_valid_template_operator, float >::type::value )); +} diff --git a/src/tests/turtle_test/integration_test.cpp b/src/tests/turtle_test/integration_test.cpp index 714338b..820f0fe 100644 --- a/src/tests/turtle_test/integration_test.cpp +++ b/src/tests/turtle_test/integration_test.cpp @@ -310,3 +310,52 @@ BOOST_AUTO_TEST_CASE( boost_optional_on_base_class_reference_as_return_type ) MOCK_EXPECT( b, method ).once().returns( boost::ref( o ) ); b.method(); } + +namespace +{ + template< typename Expected > + struct near_constraint + { + near_constraint( Expected expected, Expected threshold ) + : expected_( expected ) + , threshold_( threshold ) + {} + + template< typename Actual > + bool operator()( Actual actual ) const + { + return std::abs( actual - expected_ ) < threshold_; + } + + friend std::ostream& operator<<( std::ostream& os, const near_constraint& c ) + { + return os << "std::abs( _ - " << c.expected_ << " ) < " << c.threshold_; + } + + //template< typename Actual > + //void explain( std::ostream& os, Actual actual ) const + //{ + // os << std::abs( actual - expected_ ) << " >= " << threshold_; + //} + + Expected expected_; + Expected threshold_; + }; + template< typename Expected > + near_constraint< Expected > near( Expected expected, Expected threshold ) + { + return near_constraint< Expected >( expected, threshold ); + } + + MOCK_CLASS( custom_constraint_mock ) + { + MOCK_METHOD_EXT( method, 1, void( float ), method ) + }; +} + +BOOST_AUTO_TEST_CASE( writing_custom_constraint ) +{ + custom_constraint_mock m; + MOCK_EXPECT( m, method ).with( near( 3.f, 0.01f ) ); + m.method( 3.f ); +}