diff --git a/build/vc80/turtle.vcproj b/build/vc80/turtle.vcproj index 8f6b0de..ca55127 100644 --- a/build/vc80/turtle.vcproj +++ b/build/vc80/turtle.vcproj @@ -156,6 +156,10 @@ RelativePath="..\..\src\libraries\turtle\action.hpp" > + + diff --git a/src/libraries/turtle/args.hpp b/src/libraries/turtle/args.hpp new file mode 100644 index 0000000..eb9be5b --- /dev/null +++ b/src/libraries/turtle/args.hpp @@ -0,0 +1,67 @@ +// +// Copyright Mathieu Champlon 2010 +// +// 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_ARGS_HPP_INCLUDED +#define MOCK_ARGS_HPP_INCLUDED + +#include +#include +#include + +namespace mock +{ +namespace detail +{ + struct invalid_type + { + private: + invalid_type(); + }; + + template< typename S, int n, bool B > + struct arg_imp + { + typedef invalid_type type; + }; + template< typename S, int n > + struct arg_imp< S, n, true > + { + typedef BOOST_DEDUCED_TYPENAME + boost::mpl::at_c< + BOOST_DEDUCED_TYPENAME + boost::function_types::parameter_types< S >, + n - 1 + >::type type; + }; + template< typename S, int n, int N > + struct arg : + arg_imp< S, n, boost::function_types::function_arity< S >::value == N > + { + BOOST_MPL_ASSERT_RELATION( n, >, 0 ); + BOOST_MPL_ASSERT_RELATION( n, <=, N ); + }; +} +} + +#define MOCK_ARG(N, n, S, tpn) \ + BOOST_PP_COMMA_IF(n) tpn mock::detail::arg< S, BOOST_PP_INC(n), N >::type p##n +#define MOCK_ARG_PROXY(z, n, d) \ + MOCK_ARG( \ + BOOST_PP_ARRAY_ELEM(0, d), \ + n, \ + BOOST_PP_ARRAY_ELEM(1, d), \ + BOOST_PP_ARRAY_ELEM(2, d) ) + +#define MOCK_ARGS(n, S, tpn) \ + BOOST_PP_REPEAT_FROM_TO(0, n, MOCK_ARG_PROXY, (3, (n, S, tpn))) + +#define MOCK_DECL(M, n, S, c, tpn) \ + tpn boost::function_types::result_type< S >::type M( \ + MOCK_ARGS(n, S, tpn) ) c + +#endif // #ifndef MOCK_ARGS_HPP_INCLUDED diff --git a/src/libraries/turtle/expectation.hpp b/src/libraries/turtle/expectation.hpp index 46d5637..e8cc1bb 100644 --- a/src/libraries/turtle/expectation.hpp +++ b/src/libraries/turtle/expectation.hpp @@ -17,6 +17,7 @@ #include "root.hpp" #include "format.hpp" #include "invocation.hpp" +#include "args.hpp" #include #include #include @@ -39,10 +40,9 @@ namespace mock public: typedef BOOST_DEDUCED_TYPENAME boost::function_types::result_type< Signature >::type result_type; + typedef Signature signature_type; typedef BOOST_DEDUCED_TYPENAME boost::function_types::function_arity< Signature > arity; - typedef BOOST_DEDUCED_TYPENAME - boost::function_types::parameter_types< Signature >::type parameter_types; template< typename Args > struct sig @@ -104,10 +104,9 @@ namespace mock } #define MOCK_EXPECTATION_OPERATOR(z, n, d) \ - template< BOOST_PP_ENUM_PARAMS(n, typename A) > \ - result_type operator()( BOOST_PP_ENUM_BINARY_PARAMS(n, const A, & a) ) const \ + MOCK_DECL(operator(), n, Signature, const, BOOST_DEDUCED_TYPENAME) \ { \ - return (*impl_)( BOOST_PP_ENUM_PARAMS(n, a) ); \ + return (*impl_)( BOOST_PP_ENUM_PARAMS(n, p) ); \ } BOOST_PP_REPEAT_FROM_TO(1, MOCK_NUM_ARGS, MOCK_EXPECTATION_OPERATOR, BOOST_PP_EMPTY) #undef MOCK_EXPECTATION_OPERATOR @@ -200,38 +199,35 @@ namespace mock return invoke< ErrorPolicy >(); } -#define MOCK_EXPECTATION_PARAMETER(z, n, d) BOOST_PP_COMMA_IF(n) const_cast< A##n & >( a##n ) -#define MOCK_EXPECTATION_DETAIL(z, n, d) + ", " + format( a##n ) -#define MOCK_EXPECTATION_PARAMETERS(n) \ - format( a0 ) BOOST_PP_REPEAT_FROM_TO(1, n, MOCK_EXPECTATION_DETAIL, BOOST_PP_EMPTY) +#define MOCK_EXPECTATION_FORMAT(z, n, d) BOOST_PP_IF(n, + ", " +,) format( p##n ) +#define MOCK_EXPECTATION_CONTEXT(n) \ + context( BOOST_PP_REPEAT_FROM_TO(0, n, MOCK_EXPECTATION_FORMAT, BOOST_PP_EMPTY) ) #define MOCK_EXPECTATION_OPERATOR(z, n, d) \ - template< BOOST_PP_ENUM_PARAMS(n, typename A) > \ - result_type operator()( BOOST_PP_ENUM_BINARY_PARAMS(n, const A, & a) ) const \ - { \ - for( matchers_cit it = matchers_.begin(); it != matchers_.end(); ++it ) \ - if( it->is_valid( BOOST_PP_REPEAT_FROM_TO(0, n, MOCK_EXPECTATION_PARAMETER, BOOST_PP_EMPTY) ) ) \ + MOCK_DECL(operator(), n, Signature, const, BOOST_DEDUCED_TYPENAME) \ + { \ + for( matchers_cit it = matchers_.begin(); it != matchers_.end(); ++it ) \ + if( it->is_valid( BOOST_PP_ENUM_PARAMS(n, p) ) ) \ + { \ + if( ! it->invoke() ) \ { \ - if( ! it->invoke() ) \ - { \ - valid_ = false; \ - ErrorPolicy::sequence_failed( context( MOCK_EXPECTATION_PARAMETERS(n) ), it->file(), it->line() ); \ - return ErrorPolicy::abort(); \ - } \ - if( ! it->functor() ) \ - { \ - ErrorPolicy::missing_action( context( MOCK_EXPECTATION_PARAMETERS(n) ), it->file(), it->line() ); \ - return ErrorPolicy::abort(); \ - } \ - return it->functor()( BOOST_PP_REPEAT_FROM_TO(0, n, MOCK_EXPECTATION_PARAMETER, BOOST_PP_EMPTY) ); \ + valid_ = false; \ + ErrorPolicy::sequence_failed( MOCK_EXPECTATION_CONTEXT(n), it->file(), it->line() ); \ + return ErrorPolicy::abort(); \ } \ - valid_ = false; \ - ErrorPolicy::no_match( context( MOCK_EXPECTATION_PARAMETERS(n) ) ); \ - return ErrorPolicy::abort(); \ - } - BOOST_PP_REPEAT_FROM_TO(1, MOCK_NUM_ARGS, MOCK_EXPECTATION_OPERATOR, BOOST_PP_EMPTY) -#undef MOCK_EXPECTATION_PARAMETER -#undef MOCK_EXPECTATION_PARAMETERS -#undef MOCK_EXPECTATION_DETAIL + if( ! it->functor() ) \ + { \ + ErrorPolicy::missing_action( MOCK_EXPECTATION_CONTEXT(n), it->file(), it->line() ); \ + return ErrorPolicy::abort(); \ + } \ + return it->functor()( BOOST_PP_ENUM_PARAMS(n, p) ); \ + } \ + valid_ = false; \ + ErrorPolicy::no_match( MOCK_EXPECTATION_CONTEXT(n) ); \ + return ErrorPolicy::abort(); \ + } + BOOST_PP_REPEAT_FROM_TO(1, MOCK_NUM_ARGS, MOCK_EXPECTATION_OPERATOR, BOOST_PP_EMPTY) +#undef MOCK_EXPECTATION_CONTEXT +#undef MOCK_EXPECTATION_FORMAT #undef MOCK_EXPECTATION_OPERATOR friend std::ostream& operator<<( std::ostream& s, const expectation_impl& e ) diff --git a/src/libraries/turtle/matcher.hpp b/src/libraries/turtle/matcher.hpp index be8f40a..b862c3c 100644 --- a/src/libraries/turtle/matcher.hpp +++ b/src/libraries/turtle/matcher.hpp @@ -176,9 +176,9 @@ namespace detail #define MOCK_MATCHER_CONSTRUCTOR(z, n, d) BOOST_PP_COMMA_IF(n) c##n##_ ( any ) #define MOCK_MATCHER_WITH(z, n, d) c##n##_ = constraint##n##_type( c##n ); #define MOCK_MATCHER_MEMBER(z, n, d) constraint##n##_type c##n##_; -#define MOCK_MATCHER_IS_VALID_PARAMS(z, n, d) BOOST_PP_COMMA_IF(n) arg##n##_type a##n +#define MOCK_MATCHER_ARGS(z, n, d) BOOST_PP_COMMA_IF(n) arg##n##_type a##n #define MOCK_MATCHER_IS_VALID(z, n, d) && c##n##_( a##n ) -#define MOCK_MATCHER_SERIALIZE(z, n, d) << ", " << m.c##n##_ +#define MOCK_MATCHER_SERIALIZE(z, n, d) BOOST_PP_IF(n, << ", " <<,) m.c##n##_ #define MOCK_MATCHER(z, n, d) \ template< typename Result, typename Signature > \ class matcher< Result, Signature, n > \ @@ -195,7 +195,7 @@ namespace detail BOOST_PP_REPEAT_FROM_TO(0, n, MOCK_MATCHER_WITH, BOOST_PP_EMPTY) \ return *this; \ } \ - bool is_valid( BOOST_PP_REPEAT_FROM_TO(0, n, MOCK_MATCHER_IS_VALID_PARAMS, BOOST_PP_EMPTY) ) const \ + bool is_valid( BOOST_PP_REPEAT_FROM_TO(0, n, MOCK_MATCHER_ARGS, BOOST_PP_EMPTY) ) const \ { \ return i_->is_valid() \ BOOST_PP_REPEAT_FROM_TO(0, n, MOCK_MATCHER_IS_VALID, BOOST_PP_EMPTY); \ @@ -204,8 +204,8 @@ namespace detail friend std::ostream& operator<<( std::ostream& s, const matcher& m ) \ { \ return s << (m.i_->is_valid() ? '.' : 'v') << ' ' << *m.i_ << ".with( " \ - << m.c0_ \ - BOOST_PP_REPEAT_FROM_TO(1, n, MOCK_MATCHER_SERIALIZE, BOOST_PP_EMPTY) \ + << \ + BOOST_PP_REPEAT_FROM_TO(0, n, MOCK_MATCHER_SERIALIZE, BOOST_PP_EMPTY) \ << " )"; \ } \ private: \ @@ -218,7 +218,7 @@ namespace detail #undef MOCK_MATCHER_CONSTRUCTOR #undef MOCK_MATCHER_WITH #undef MOCK_MATCHER_MEMBER -#undef MOCK_MATCHER_IS_VALID_PARAMS +#undef MOCK_MATCHER_ARGS #undef MOCK_MATCHER_IS_VALID #undef MOCK_MATCHER_SERIALIZE #undef MOCK_MATCHER diff --git a/src/libraries/turtle/mock.hpp b/src/libraries/turtle/mock.hpp index ddedc63..9f8f2eb 100644 --- a/src/libraries/turtle/mock.hpp +++ b/src/libraries/turtle/mock.hpp @@ -13,19 +13,21 @@ #include "object.hpp" #include "expectation.hpp" #include "type_name.hpp" +#include "args.hpp" #include #include #include #include #include #include -#include #include #include +#include +#include +#include #include #include #include -#include #include #define BOOST_TYPEOF_SILENT #include @@ -150,78 +152,22 @@ namespace detail typedef T base_type; }; - struct invalid_type - { - private: - invalid_type(); - }; - - template< typename S, int n, bool B > - struct arg_imp - { - typedef invalid_type type; - }; - template< typename S, int n > - struct arg_imp< S, n, true > - { - typedef BOOST_DEDUCED_TYPENAME - boost::mpl::at_c< - BOOST_DEDUCED_TYPENAME - boost::function_types::parameter_types< S >, - n - 1 - >::type type; - }; - template< typename S, int n, int N > - struct arg - { - BOOST_MPL_ASSERT_RELATION( n, >, 0 ); - BOOST_MPL_ASSERT_RELATION( n, <=, N ); - typedef BOOST_DEDUCED_TYPENAME - arg_imp< S, n, - boost::function_types::function_arity< S >::value == N - >::type type; - }; - template< typename E, int N > - struct has_arity - { - typedef BOOST_DEDUCED_TYPENAME - boost::mpl::equal_to< - BOOST_DEDUCED_TYPENAME E::arity, - boost::mpl::size_t< N > - >::type type; - }; + struct has_arity : boost::mpl::equal_to< BOOST_DEDUCED_TYPENAME E::arity, boost::mpl::size_t< N > > + {}; -#define MOCK_CALL_PARAM(z, n, d) \ - BOOST_DEDUCED_TYPENAME \ - boost::mpl::at_c< \ - BOOST_DEDUCED_TYPENAME E::parameter_types, \ - n \ - >::type t##n -#define MOCK_CALL_INVALID_TYPE(z, n, d) invalid_type #define MOCK_CALL(z, n, d) \ template< typename E > \ BOOST_DEDUCED_TYPENAME boost::enable_if< \ BOOST_DEDUCED_TYPENAME has_arity< E, n >::type, \ BOOST_DEDUCED_TYPENAME E::result_type \ >::type \ - call( E e BOOST_PP_COMMA_IF(n) BOOST_PP_ENUM(n, MOCK_CALL_PARAM, BOOST_PP_EMPTY) ) \ + call( E e BOOST_PP_COMMA_IF(n) MOCK_ARGS(n, BOOST_DEDUCED_TYPENAME E::signature_type, BOOST_DEDUCED_TYPENAME ) ) \ { \ - return e( BOOST_PP_ENUM_PARAMS(n, t) ); \ - } \ - template< typename E > \ - BOOST_DEDUCED_TYPENAME boost::disable_if< \ - BOOST_DEDUCED_TYPENAME has_arity< E, n >::type, \ - BOOST_DEDUCED_TYPENAME E::result_type \ - >::type \ - call( E BOOST_PP_COMMA_IF(n) BOOST_PP_ENUM(n, MOCK_CALL_INVALID_TYPE, BOOST_PP_EMPTY) ) \ - { \ - throw std::logic_error( "should never be called" ); \ + return e( BOOST_PP_ENUM_PARAMS(n, p) ); \ } BOOST_PP_REPEAT_FROM_TO(0, MOCK_NUM_ARGS, MOCK_CALL, BOOST_PP_EMPTY) #undef MOCK_CALL -#undef MOCK_CALL_INVALID_TYPE -#undef MOCK_CALL_PARAM } } @@ -249,29 +195,12 @@ namespace detail #define MOCK_SIGNATURE_TPL(M) \ BOOST_DEDUCED_TYPENAME mock::detail::signature< BOOST_TYPEOF_TPL(&base_type::M) >::type -#define MOCK_METHOD_ARG(N, n, S, tpn) \ - BOOST_PP_COMMA_IF(n) tpn mock::detail::arg< S, BOOST_PP_INC(n), N >::type BOOST_PP_CAT(p, n) -#define MOCK_METHOD_ARG_PROXY(z, n, d) \ - MOCK_METHOD_ARG( \ - BOOST_PP_ARRAY_ELEM(0, d), \ - n, \ - BOOST_PP_ARRAY_ELEM(1, d), \ - BOOST_PP_ARRAY_ELEM(2, d) ) #define MOCK_METHOD_STUB(M, n, S, t, c, tpn) \ - tpn boost::function_types::result_type< S >::type M( \ - BOOST_PP_REPEAT_FROM_TO(0, n, MOCK_METHOD_ARG_PROXY, (3, (n, S, tpn))) ) c \ + MOCK_DECL(M, n, S, c, tpn) \ { \ return mock::detail::call( MOCK_ANONYMOUS_MOCKER(this, t) \ BOOST_PP_COMMA_IF(n) BOOST_PP_ENUM_PARAMS(n, p) ); \ } -#define MOCK_METHOD_STUB_PROXY(z, n, d) \ - MOCK_METHOD_STUB( \ - BOOST_PP_ARRAY_ELEM(0, d), \ - n, \ - BOOST_PP_ARRAY_ELEM(1, d), \ - BOOST_PP_ARRAY_ELEM(2, d), \ - BOOST_PP_ARRAY_ELEM(3, d), \ - BOOST_PP_ARRAY_ELEM(4, d)) #define MOCK_METHOD_EXT(M, n, S, t) \ MOCK_METHOD_STUB(M, n, S, t,,) \ @@ -309,6 +238,34 @@ namespace detail // alternate experimental macros below, way too slow to compile to be really usable +namespace mock +{ +namespace detail +{ +#define MOCK_CALL_INVALID_TYPE(z, n, d) invalid_type +#define MOCK_CALL(z, n, d) \ + template< typename E > \ + BOOST_DEDUCED_TYPENAME boost::disable_if< \ + BOOST_DEDUCED_TYPENAME has_arity< E, n >::type, \ + BOOST_DEDUCED_TYPENAME E::result_type \ + >::type \ + call( E BOOST_PP_COMMA_IF(n) BOOST_PP_ENUM(n, MOCK_CALL_INVALID_TYPE, BOOST_PP_EMPTY) ) \ + {} + BOOST_PP_REPEAT_FROM_TO(0, MOCK_NUM_ARGS, MOCK_CALL, BOOST_PP_EMPTY) +#undef MOCK_CALL +#undef MOCK_CALL_INVALID_TYPE +} +} + +#define MOCK_METHOD_STUB_PROXY(z, n, d) \ + MOCK_METHOD_STUB( \ + BOOST_PP_ARRAY_ELEM(0, d), \ + n, \ + BOOST_PP_ARRAY_ELEM(1, d), \ + BOOST_PP_ARRAY_ELEM(2, d), \ + BOOST_PP_ARRAY_ELEM(3, d), \ + BOOST_PP_ARRAY_ELEM(4, d)) + #define MOCK_METHOD_STUB_ALT(M, S, t, c, tpn) \ BOOST_PP_REPEAT_FROM_TO(0, MOCK_NUM_ARGS, MOCK_METHOD_STUB_PROXY, (5,(M, S, t, c, tpn))) diff --git a/src/tests/turtle_test/expectation_test.cpp b/src/tests/turtle_test/expectation_test.cpp index 396e8c2..c56b3bf 100644 --- a/src/tests/turtle_test/expectation_test.cpp +++ b/src/tests/turtle_test/expectation_test.cpp @@ -127,13 +127,12 @@ BOOST_FIXTURE_TEST_CASE( triggering_a_once_expectation_calls_no_match_error_afte } } -/* BOOST_FIXTURE_TEST_CASE( literal_zero_can_be_used_in_expectation_operator_call_as_pointers, error_fixture ) { mock::expectation< void( int* ) > e; + e.expect().once(); e( 0 ); } -*/ // verify