diff --git a/.clang-format b/.clang-format index 3e0460e..69c1f29 100644 --- a/.clang-format +++ b/.clang-format @@ -134,27 +134,17 @@ StatementMacros: - MOCK_BASE_CLASS - MOCK_CLASS - MOCK_CONSTRUCTOR - - MOCK_CONSTRUCTOR_TPL - MOCK_CONST_CONVERSION_OPERATOR - - MOCK_CONST_CONVERSION_OPERATOR_TPL - MOCK_CONST_METHOD - MOCK_CONST_METHOD_EXT - - MOCK_CONST_METHOD_EXT_TPL - - MOCK_CONST_METHOD_TPL - MOCK_CONVERSION_OPERATOR - MOCK_DESTRUCTOR - MOCK_METHOD - MOCK_METHOD_EXT - - MOCK_METHOD_EXT_TPL - - MOCK_METHOD_TPL - MOCK_NON_CONST_CONVERSION_OPERATOR - - MOCK_NON_CONST_CONVERSION_OPERATOR_TPL - MOCK_NON_CONST_METHOD - MOCK_NON_CONST_METHOD_EXT - - MOCK_NON_CONST_METHOD_EXT_TPL - - MOCK_NON_CONST_METHOD_TPL - MOCK_STATIC_METHOD - - MOCK_STATIC_METHOD_TPL TabWidth: 4 UseCRLF: false UseTab: Never diff --git a/doc/changelog.qbk b/doc/changelog.qbk index 20c3d4c..3ae5506 100644 --- a/doc/changelog.qbk +++ b/doc/changelog.qbk @@ -12,7 +12,7 @@ Released - * Allow auto-deducing signature in `MOCK_METHOD_(NON_)CONST` * Replaced Boost facilities with std:: equivalents where existing in C++14 -* Deprecated MOCK_FUNCTOR_TPL as no longer required, use the non _TPL variant even for templates +* Deprecated MOCK_*_TPL as no longer required, use the non _TPL variant even for templates * Added MOCK_PROTECT_FUNCTION_SIG to pass function signatures with commas in the return type [endsect] diff --git a/doc/example/reference.cpp b/doc/example/reference.cpp index adec0b3..f322b7c 100644 --- a/doc/example/reference.cpp +++ b/doc/example/reference.cpp @@ -215,10 +215,8 @@ namespace member_function_example_7 { template MOCK_CLASS(mock_class) { - MOCK_METHOD_TPL( - method, - 1, - void(const T&)) // the _TPL variants must be used if the signature includes a template parameter of the class + MOCK_METHOD(method, 1, + void(const T&)) // includes a template parameter of the class }; //] } // namespace member_function_example_7 @@ -262,7 +260,7 @@ namespace static_member_function_example_2 { template MOCK_CLASS(mock_class) { - MOCK_STATIC_METHOD_TPL(method, 1, void(T)) + MOCK_STATIC_METHOD(method, 1, void(T)) // includes a template parameter of the class }; //] } // namespace static_member_function_example_2 @@ -296,7 +294,7 @@ template MOCK_CLASS(mock_class) { MOCK_CONSTRUCTOR(mock_class, 2, (int, const std::string&), identifier) - MOCK_CONSTRUCTOR_TPL(mock_class, 2, (T, const std::string&), identifier_2) + MOCK_CONSTRUCTOR(mock_class, 2, (T, const std::string&), identifier_2) // includes a template parameter of the class }; //] } // namespace constructor_example_2 @@ -347,8 +345,7 @@ namespace conversion_operator_example_2 { template MOCK_CLASS(mock_class) { - MOCK_CONVERSION_OPERATOR_TPL(operator, T, conversion_to_T) // the _TPL variants must be used if the signature - // includes a template parameter of the class + MOCK_CONVERSION_OPERATOR(operator, T, conversion_to_T) // includes a template parameter of the class MOCK_CONST_CONVERSION_OPERATOR(operator, const std::string&, const_conversion_to_string) MOCK_NON_CONST_CONVERSION_OPERATOR(operator, const std::string&, non_const_conversion_to_string) }; diff --git a/doc/reference.qbk b/doc/reference.qbk index dacce89..72dd7a9 100644 --- a/doc/reference.qbk +++ b/doc/reference.qbk @@ -90,16 +90,12 @@ Synopsis : MOCK_METHOD( [calling convention] name, arity[, signature[, identifier]] ) // generates both const and non-const methods MOCK_CONST_METHOD( [calling convention] name, arity[, signature[, identifier]] ) // generates only the const version of the method MOCK_NON_CONST_METHOD( [calling convention] name, arity[, signature[, identifier]] ) // generates only the non-const version of the method - - MOCK_METHOD_TPL( [calling convention] name, arity, signature[, identifier] ) // must be used if the signature uses a template parameter of the class, generates both const and non-const methods - MOCK_CONST_METHOD_TPL( [calling convention] name, arity, signature[, identifier] ) // must be used if the signature uses a template parameter of the class, generates only the const version of the method - MOCK_NON_CONST_METHOD_TPL( [calling convention] name, arity, signature[, identifier] ) // must be used if the signature uses a template parameter of the class, generates only the non-const version of the method [note If the identifier is omitted it will default to the method name.] [note If the method name is not ambiguous both the signature and the identifier can be omitted in the context of a derived MOCK_BASE_CLASS or base_type typedef.] -[note The signature cannot be omitted for the _TPL familly of macros, see the related [link turtle.limitations.template_base_class_methods_cannot_be_mocked_without_specifying_the_signature limitation section].] +[note The signature cannot be omitted if it uses a template parameter of the class, see the related [link turtle.limitations.template_base_class_methods_cannot_be_mocked_without_specifying_the_signature limitation section].] [note [link turtle.reference.creation.constructor Constructors], [link turtle.reference.creation.destructor destructors] and [link turtle.reference.creation.conversion_operator conversion operators] require special care.] @@ -107,13 +103,9 @@ Synopsis : Synopsis : - MOCK_METHOD_EXT( [calling convention] name, arity, signature, identifier ) // generates both const and non-const methods - MOCK_CONST_METHOD_EXT( [calling convention] name, arity, signature, identifier ) // generates only the const version of the method - MOCK_NON_CONST_METHOD_EXT( [calling convention] name, arity, signature, identifier ) // generates only the non-const version of the method - - MOCK_METHOD_EXT_TPL( [calling convention] name, arity, signature, identifier ) // must be used if the signature uses a template parameter of the class, generates both const and non-const methods - MOCK_CONST_METHOD_EXT_TPL( [calling convention] name, arity, signature, identifier ) // must be used if the signature uses a template parameter of the class, generates only the const version of the method - MOCK_NON_CONST_METHOD_EXT_TPL( [calling convention] name, arity, signature, identifier ) // must be used if the signature uses a template parameter of the class, generates only the non-const version of the method + MOCK_METHOD( [calling convention] name, arity, signature, identifier ) // generates both const and non-const methods + MOCK_CONST_METHOD( [calling convention] name, arity, signature, identifier ) // generates only the const version of the method + MOCK_NON_CONST_METHOD( [calling convention] name, arity, signature, identifier ) // generates only the non-const version of the method Example : @@ -158,8 +150,6 @@ Example for gcc : Synopsis : MOCK_STATIC_METHOD( [calling convention] name, arity, signature[, identifier] ) // if 'identifier' is omitted it will default to 'name' - - MOCK_STATIC_METHOD_TPL( [calling convention] name, arity, signature[, identifier] ) // must be used if the signature uses a template parameter of the class, if 'identifier' is omitted it will default to 'name' [note A static object is used behind the scene in order to keep track of the expectations of a mock static method, therefore to ensure all tests run in isolation it is strongly suggested to manually [link turtle.reference.verification verify] and [link turtle.reference.reset reset] the static method at the end of each test, see the related [link turtle.patterns.managing_static_mock_objects pattern section].] @@ -189,8 +179,6 @@ Synopsis : MOCK_CONSTRUCTOR( [calling convention] name, arity, parameters, identifier ) - MOCK_CONSTRUCTOR_TPL( [calling convention] name, arity, parameters, identifier ) // must be used if the signature uses a template parameter of the class - [note As constructors do not have a return type, the usual signature gets restricted here to just the parameters.] Example : @@ -241,10 +229,6 @@ Synopsis : MOCK_CONST_CONVERSION_OPERATOR( [calling convention] name, type, identifier ) // generates only a const operator MOCK_NON_CONST_CONVERSION_OPERATOR( [calling convention] name, type, identifier ) // generates only a non-const operator - MOCK_CONVERSION_OPERATOR_TPL( [calling convention] name, type, identifier ) // must be used if the signature uses a template parameter of the class - MOCK_CONST_CONVERSION_OPERATOR_TPL( [calling convention] name, type, identifier ) // must be used if the signature uses a template parameter of the class - MOCK_NON_CONST_CONVERSION_OPERATOR_TPL( [calling convention] name, type, identifier ) // must be used if the signature uses a template parameter of the class - Example : [conversion_operator_example_1] @@ -293,8 +277,6 @@ Synopsis : MOCK_FUNCTOR( [calling convention] name, signature ); - MOCK_FUNCTOR_TPL( [calling convention] name, signature ); // must be used if the signature uses a template parameter - Example : [functor_example_1] diff --git a/include/turtle/detail/mock_impl.hpp b/include/turtle/detail/mock_impl.hpp new file mode 100644 index 0000000..822f7a7 --- /dev/null +++ b/include/turtle/detail/mock_impl.hpp @@ -0,0 +1,89 @@ +// http://turtle.sourceforge.net +// +// Copyright Mathieu Champlon 2008 +// +// 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_MOCK_IMPL_HPP_INCLUDED +#define MOCK_MOCK_IMPL_HPP_INCLUDED + +#include "function.hpp" +#include "functor.hpp" +#include "parameter.hpp" +#include "signature.hpp" +#include "type_name.hpp" +#include +#include + +// Internal compatibility macro if function signature is passed via BOOST_IDENTITY_TYPE +// TODO: Remove support for doing that and move remove_pointer_t to MOCK_PROTECT_FUNCTION_SIG +#define MOCK_FUNCTION_TYPE(...) std::remove_pointer_t<__VA_ARGS__> + +#define MOCK_HELPER(t) t##_mock(mock::detail::root, BOOST_PP_STRINGIZE(t)) +#define MOCK_ANONYMOUS_HELPER(t) t##_mock(mock::detail::root, "?.") + +#define MOCK_METHOD_HELPER(S, t) \ + mutable mock::detail::function t##_mock_; \ + mock::detail::function& t##_mock(const mock::detail::context&, \ + const boost::unit_test::const_string& instance) const \ + { \ + mock::detail::configure(*this, \ + t##_mock_, \ + instance.substr(0, instance.rfind(BOOST_PP_STRINGIZE(t))), \ + mock::detail::make_type_name(*this), \ + BOOST_PP_STRINGIZE(t)); \ + return t##_mock_; \ + } + +#define MOCK_PARAM(S) mock::detail::parameter_t < MOCK_FUNCTION_TYPE(S) +#define MOCK_DECL_PARAM(z, n, d) BOOST_PP_COMMA_IF(n) d, n > p##n +#define MOCK_DECL_PARAMS(n, S) BOOST_PP_REPEAT(n, MOCK_DECL_PARAM, MOCK_PARAM(S)) +#define MOCK_DECL(M, n, S, c) mock::detail::result_type_t M(MOCK_DECL_PARAMS(n, S)) c + +#define MOCK_FORWARD_PARAM(z, n, d) BOOST_PP_COMMA_IF(n) d, n >> (p##n) +#define MOCK_FORWARD_PARAMS(n, S) BOOST_PP_REPEAT(n, MOCK_FORWARD_PARAM, std::forward < MOCK_PARAM(S)) +#define MOCK_METHOD_AUX(M, n, S, t, c) \ + MOCK_DECL(M, n, S, c) \ + { \ + static_assert(n == mock::detail::function_arity::value, "Arity mismatch"); \ + return MOCK_ANONYMOUS_HELPER(t)(MOCK_FORWARD_PARAMS(n, S)); \ + } + +#define MOCK_METHOD_EXT(M, n, S, t) \ + MOCK_METHOD_AUX(M, n, S, t, ) \ + MOCK_METHOD_AUX(M, n, S, t, const) \ + MOCK_METHOD_HELPER(S, t) +#define MOCK_CONST_METHOD_EXT(M, n, S, t) \ + MOCK_METHOD_AUX(M, n, S, t, const) \ + MOCK_METHOD_HELPER(S, t) +#define MOCK_NON_CONST_METHOD_EXT(M, n, S, t) \ + MOCK_METHOD_AUX(M, n, S, t, ) \ + MOCK_METHOD_HELPER(S, t) + +#define MOCK_FUNCTION_HELPER(S, t, s) \ + s mock::detail::function& t##_mock(mock::detail::context& context, \ + boost::unit_test::const_string instance) \ + { \ + static mock::detail::function f; \ + return f(context, instance); \ + } + +#define MOCK_CONSTRUCTOR_AUX(T, n, A, t) \ + T(MOCK_DECL_PARAMS(n, void A)) { MOCK_HELPER(t)(MOCK_FORWARD_PARAMS(n, void A)); } \ + MOCK_FUNCTION_HELPER(void A, t, static) + +#define MOCK_FUNCTION_AUX(F, n, S, t, s) \ + MOCK_FUNCTION_HELPER(S, t, s) \ + s MOCK_DECL(F, n, S, ) \ + { \ + static_assert(n == mock::detail::function_arity::value, "Arity mismatch"); \ + return MOCK_HELPER(t)(MOCK_FORWARD_PARAMS(n, S)); \ + } + +#define MOCK_VARIADIC_ELEM_0(e0, ...) e0 +#define MOCK_VARIADIC_ELEM_1(e0, e1, ...) e1 +#define MOCK_VARIADIC_ELEM_2(e0, e1, e2, ...) e2 + +#endif // MOCK_MOCK_IMPL_HPP_INCLUDED diff --git a/include/turtle/detail/parameter.hpp b/include/turtle/detail/parameter.hpp index 34679b4..1db8228 100644 --- a/include/turtle/detail/parameter.hpp +++ b/include/turtle/detail/parameter.hpp @@ -36,6 +36,8 @@ namespace mock { namespace detail { { using type = R; }; + template + using result_type_t = typename result_type::type; template struct function_arity; @@ -55,12 +57,14 @@ namespace mock { namespace detail { using type = tuple; }; - template + template struct parameter { static_assert(n < function_arity::value, "Function signature has not that many parameters"); using type = typename tuple_element::type>::type; }; + template + using parameter_t = typename parameter::type; template struct parameter_type; diff --git a/include/turtle/mock.hpp b/include/turtle/mock.hpp index 4d25f8d..991691b 100644 --- a/include/turtle/mock.hpp +++ b/include/turtle/mock.hpp @@ -11,159 +11,64 @@ #include "cleanup.hpp" #include "config.hpp" -#include "detail/function.hpp" -#include "detail/functor.hpp" -#include "detail/parameter.hpp" -#include "detail/signature.hpp" -#include "detail/type_name.hpp" +#include "detail/mock_impl.hpp" #include "object.hpp" #include "reset.hpp" #include "verify.hpp" -#include -#include /// MOCK_CLASS( name ) /// Define a class -#define MOCK_CLASS(T) struct T : mock::object +#define MOCK_CLASS(name) struct name : mock::object + +/// MOCK_BASE_CLASS( name, base ) +/// Define a class deriving from a base class +#define MOCK_BASE_CLASS(name, ...) struct name : __VA_ARGS__, mock::object, mock::detail::base<__VA_ARGS__> /// MOCK_PROTECT_FUNCTION_SIG( signature ) /// Use this with MOCK_FUNCTION/MOCK_*_METHOD if the return type contains commas #define MOCK_PROTECT_FUNCTION_SIG(...) mock::detail::parameter_type_t -/// Internal compatibility macro if function signature is passed via BOOST_IDENTITY_TYPE -/// TODO: Remove support for doing that and move remove_pointer_t to MOCK_PROTECT_FUNCTION_SIG -#define MOCK_FUNCTION_TYPE(...) std::remove_pointer_t<__VA_ARGS__> - -/// MOCK_BASE_CLASS( name, base ) -/// Define a class deriving from a base class -#define MOCK_BASE_CLASS(T, ...) struct T : __VA_ARGS__, mock::object, mock::detail::base<__VA_ARGS__> - /// MOCK_FUNCTOR( name, signature ) /// Define a callable variable/member -#define MOCK_FUNCTOR(f, ...) mock::detail::functor f, f##_mock -/// MOCK_FUNCTOR_TPL( name, signature ) -#define MOCK_FUNCTOR_TPL(f, ...) static_assert(false, "MOCK_FUNCTOR_TPL has been replaced by MOCK_FUNCTOR") - -#define MOCK_HELPER(t) t##_mock(mock::detail::root, BOOST_PP_STRINGIZE(t)) -#define MOCK_ANONYMOUS_HELPER(t) t##_mock(mock::detail::root, "?.") - -#define MOCK_METHOD_HELPER(S, t) \ - mutable mock::detail::function t##_mock_; \ - mock::detail::function& t##_mock(const mock::detail::context&, \ - const boost::unit_test::const_string& instance) const \ - { \ - mock::detail::configure(*this, \ - t##_mock_, \ - instance.substr(0, instance.rfind(BOOST_PP_STRINGIZE(t))), \ - mock::detail::make_type_name(*this), \ - BOOST_PP_STRINGIZE(t)); \ - return t##_mock_; \ - } - -#define MOCK_PARAM(S, tpn) tpn mock::detail::parameter < MOCK_FUNCTION_TYPE(S) -#define MOCK_DECL_PARAM(z, n, d) BOOST_PP_COMMA_IF(n) d, n > ::type p##n -#define MOCK_DECL_PARAMS(n, S, tpn) BOOST_PP_REPEAT(n, MOCK_DECL_PARAM, MOCK_PARAM(S, tpn)) -#define MOCK_DECL(M, n, S, c, tpn) \ - tpn mock::detail::result_type::type M(MOCK_DECL_PARAMS(n, S, tpn)) c - -#define MOCK_FORWARD_PARAM(z, n, d) BOOST_PP_COMMA_IF(n) d, n > ::type > (p##n) -#define MOCK_FORWARD_PARAMS(n, S, tpn) BOOST_PP_REPEAT(n, MOCK_FORWARD_PARAM, std::forward < MOCK_PARAM(S, tpn)) -#define MOCK_METHOD_AUX(M, n, S, t, c, tpn) \ - MOCK_DECL(M, n, S, c, tpn) \ - { \ - static_assert(n == mock::detail::function_arity::value, "Arity mismatch"); \ - return MOCK_ANONYMOUS_HELPER(t)(MOCK_FORWARD_PARAMS(n, S, tpn)); \ - } - -#define MOCK_METHOD_EXT(M, n, S, t) \ - MOCK_METHOD_AUX(M, n, S, t, , ) \ - MOCK_METHOD_AUX(M, n, S, t, const, ) \ - MOCK_METHOD_HELPER(S, t) -#define MOCK_CONST_METHOD_EXT(M, n, S, t) \ - MOCK_METHOD_AUX(M, n, S, t, const, ) \ - MOCK_METHOD_HELPER(S, t) -#define MOCK_NON_CONST_METHOD_EXT(M, n, S, t) \ - MOCK_METHOD_AUX(M, n, S, t, , ) \ - MOCK_METHOD_HELPER(S, t) - -#define MOCK_METHOD_EXT_TPL(M, n, S, t) \ - MOCK_METHOD_AUX(M, n, S, t, , typename) \ - MOCK_METHOD_AUX(M, n, S, t, const, typename) \ - MOCK_METHOD_HELPER(S, t) -#define MOCK_CONST_METHOD_EXT_TPL(M, n, S, t) \ - MOCK_METHOD_AUX(M, n, S, t, const, typename) \ - MOCK_METHOD_HELPER(S, t) -#define MOCK_NON_CONST_METHOD_EXT_TPL(M, n, S, t) \ - MOCK_METHOD_AUX(M, n, S, t, , typename) \ - MOCK_METHOD_HELPER(S, t) +#define MOCK_FUNCTOR(name, ...) mock::detail::functor name, name##_mock /// MOCK_CONVERSION_OPERATOR( [calling convention] name, type, identifier ) -/// generates both const and non-const operators -#define MOCK_CONVERSION_OPERATOR(M, T, t) \ - M T() const { return MOCK_ANONYMOUS_HELPER(t)(); } \ - M T() { return MOCK_ANONYMOUS_HELPER(t)(); } \ - MOCK_METHOD_HELPER(T(), t) +/// generates both const and non-const conversion operators +#define MOCK_CONVERSION_OPERATOR(M, T, identifier) \ + M T() const { return MOCK_ANONYMOUS_HELPER(identifier)(); } \ + M T() { return MOCK_ANONYMOUS_HELPER(identifier)(); } \ + MOCK_METHOD_HELPER(T(), identifier) /// MOCK_CONST_CONVERSION_OPERATOR( [calling convention] name, type, identifier ) -/// generates only a const operator -#define MOCK_CONST_CONVERSION_OPERATOR(M, T, t) \ - M T() const { return MOCK_ANONYMOUS_HELPER(t)(); } \ - MOCK_METHOD_HELPER(T(), t) +/// generates only a const conversion operator +#define MOCK_CONST_CONVERSION_OPERATOR(M, T, identifier) \ + M T() const { return MOCK_ANONYMOUS_HELPER(identifier)(); } \ + MOCK_METHOD_HELPER(T(), identifier) /// MOCK_NON_CONST_CONVERSION_OPERATOR( [calling convention] name, type, identifier ) -/// generates only a non-const operator -#define MOCK_NON_CONST_CONVERSION_OPERATOR(M, T, t) \ - M T() { return MOCK_ANONYMOUS_HELPER(t)(); } \ - MOCK_METHOD_HELPER(T(), t) - -#define MOCK_CONVERSION_OPERATOR_TPL(M, T, t) MOCK_CONVERSION_OPERATOR(M, T, t) -#define MOCK_CONST_CONVERSION_OPERATOR_TPL(M, T, t) MOCK_CONST_CONVERSION_OPERATOR(M, T, t) -#define MOCK_NON_CONST_CONVERSION_OPERATOR_TPL(M, T, t) MOCK_NON_CONST_CONVERSION_OPERATOR(M, T, t) - -#define MOCK_FUNCTION_HELPER(S, t, s, tpn) \ - s mock::detail::function& t##_mock(mock::detail::context& context, \ - boost::unit_test::const_string instance) \ - { \ - static mock::detail::function f; \ - return f(context, instance); \ - } - -#define MOCK_CONSTRUCTOR_AUX(T, n, A, t, tpn) \ - T(MOCK_DECL_PARAMS(n, void A, tpn)) { MOCK_HELPER(t)(MOCK_FORWARD_PARAMS(n, void A, tpn)); } \ - MOCK_FUNCTION_HELPER(void A, t, static, tpn) +/// generates only a non-const conversion operator +#define MOCK_NON_CONST_CONVERSION_OPERATOR(M, T, identifier) \ + M T() { return MOCK_ANONYMOUS_HELPER(identifier)(); } \ + MOCK_METHOD_HELPER(T(), identifier) /// MOCK_CONSTRUCTOR( [calling convention] name, arity, parameters, identifier ) /// As constructors do not have a return type, the usual signature gets restricted here to just the parameters. -#define MOCK_CONSTRUCTOR(T, n, A, t) MOCK_CONSTRUCTOR_AUX(T, n, A, t, ) -/// MOCK_CONSTRUCTOR( [calling convention] name, arity, parameters, identifier ) -/// must be used if the signature uses a template parameter of the class -/// As constructors do not have a return type, the usual signature gets restricted here to just the parameters. -#define MOCK_CONSTRUCTOR_TPL(T, n, A, t) MOCK_CONSTRUCTOR_AUX(T, n, A, t, typename) +#define MOCK_CONSTRUCTOR(T, arity, parameters, identifier) MOCK_CONSTRUCTOR_AUX(T, arity, parameters, identifier) /// MOCK_DESTRUCTOR( [calling convention] ~name, identifier ) -#define MOCK_DESTRUCTOR(T, t) \ - T() \ - { \ - try \ - { \ - MOCK_ANONYMOUS_HELPER(t)(); \ - } catch(...) \ - {} \ - } \ - MOCK_METHOD_HELPER(void(), t) - -#define MOCK_FUNCTION_AUX(F, n, S, t, s, tpn) \ - MOCK_FUNCTION_HELPER(S, t, s, tpn) \ - s MOCK_DECL(F, n, S, , tpn) \ - { \ - static_assert(n == mock::detail::function_arity::value, "Arity mismatch"); \ - return MOCK_HELPER(t)(MOCK_FORWARD_PARAMS(n, S, tpn)); \ - } - -#define MOCK_VARIADIC_ELEM_0(e0, ...) e0 -#define MOCK_VARIADIC_ELEM_1(e0, e1, ...) e1 -#define MOCK_VARIADIC_ELEM_2(e0, e1, e2, ...) e2 +#define MOCK_DESTRUCTOR(T, identifier) \ + T() \ + { \ + try \ + { \ + MOCK_ANONYMOUS_HELPER(identifier)(); \ + } catch(...) \ + {} \ + } \ + MOCK_METHOD_HELPER(void(), identifier) /// MOCK_METHOD( [calling convention] name, arity[, signature[, identifier]] ) /// generates both const and non-const methods +/// The 'signature' can be omitted if it can be uniquely identified from the base class +/// if 'identifier' is omitted it will default to 'name' #define MOCK_METHOD(M, ...) \ MOCK_METHOD_EXT(M, \ MOCK_VARIADIC_ELEM_0(__VA_ARGS__, ), \ @@ -171,6 +76,8 @@ MOCK_VARIADIC_ELEM_2(__VA_ARGS__, M, M, )) /// MOCK_CONST_METHOD( [calling convention] name, arity[, signature[, identifier]] ) /// generates only the const version of the method +/// The 'signature' can be omitted if it can be uniquely identified from the base class +/// if 'identifier' is omitted it will default to 'name' #define MOCK_CONST_METHOD(M, ...) \ MOCK_CONST_METHOD_EXT(M, \ MOCK_VARIADIC_ELEM_0(__VA_ARGS__, ), \ @@ -178,50 +85,53 @@ MOCK_VARIADIC_ELEM_2(__VA_ARGS__, M, M, )) /// MOCK_NON_CONST_METHOD( [calling convention] name, arity[, signature[, identifier]] ) /// generates only the non-const version of the method +/// The 'signature' can be omitted if it can be uniquely identified from the base class +/// if 'identifier' is omitted it will default to 'name' #define MOCK_NON_CONST_METHOD(M, ...) \ MOCK_NON_CONST_METHOD_EXT(M, \ MOCK_VARIADIC_ELEM_0(__VA_ARGS__, ), \ MOCK_VARIADIC_ELEM_1(__VA_ARGS__, MOCK_SIGNATURE(M), ), \ MOCK_VARIADIC_ELEM_2(__VA_ARGS__, M, M, )) -/// MOCK_METHOD_TPL( [calling convention] name, arity, signature[, identifier] ) -/// must be used if the signature uses a template parameter of the class -/// generates both const and non-const methods -#define MOCK_METHOD_TPL(M, n, ...) \ - MOCK_METHOD_EXT_TPL(M, n, MOCK_VARIADIC_ELEM_0(__VA_ARGS__, ), MOCK_VARIADIC_ELEM_1(__VA_ARGS__, M, )) -/// MOCK_CONST_METHOD_TPL( [calling convention] name, arity, signature[, identifier] ) -/// must be used if the signature uses a template parameter of the class -/// generates only the const version of the method -#define MOCK_CONST_METHOD_TPL(M, n, ...) \ - MOCK_CONST_METHOD_EXT_TPL(M, n, MOCK_VARIADIC_ELEM_0(__VA_ARGS__, ), MOCK_VARIADIC_ELEM_1(__VA_ARGS__, M, )) -/// MOCK_NON_CONST_METHOD_TPL( [calling convention] name, arity, signature[, identifier] ) -/// must be used if the signature uses a template parameter of the class -/// generates only the non-const version of the method -#define MOCK_NON_CONST_METHOD_TPL(M, n, ...) \ - MOCK_NON_CONST_METHOD_EXT_TPL(M, n, MOCK_VARIADIC_ELEM_0(__VA_ARGS__, ), MOCK_VARIADIC_ELEM_1(__VA_ARGS__, M, )) - /// MOCK_FUNCTION( [calling convention] name, arity, signature[, identifier] ) /// if 'identifier' is omitted it will default to 'name' -#define MOCK_FUNCTION(F, n, ...) \ - MOCK_FUNCTION_AUX(F, n, MOCK_VARIADIC_ELEM_0(__VA_ARGS__, ), MOCK_VARIADIC_ELEM_1(__VA_ARGS__, F, ), inline, ) +#define MOCK_FUNCTION(F, arity, ...) \ + MOCK_FUNCTION_AUX(F, arity, MOCK_VARIADIC_ELEM_0(__VA_ARGS__, ), MOCK_VARIADIC_ELEM_1(__VA_ARGS__, F, ), inline) /// MOCK_STATIC_METHOD( [calling convention] name, arity, signature[, identifier] ) /// if 'identifier' is omitted it will default to 'name' -#define MOCK_STATIC_METHOD(F, n, ...) \ - MOCK_FUNCTION_AUX(F, n, MOCK_VARIADIC_ELEM_0(__VA_ARGS__, ), MOCK_VARIADIC_ELEM_1(__VA_ARGS__, F, ), static, ) - -/// MOCK_STATIC_METHOD_TPL( [calling convention] name, arity, signature[, identifier] ) -/// must be used if the signature uses a template parameter of the class -/// if 'identifier' is omitted it will default to 'name' -#define MOCK_STATIC_METHOD_TPL(F, n, ...) \ - MOCK_FUNCTION_AUX( \ - F, n, MOCK_VARIADIC_ELEM_0(__VA_ARGS__, ), MOCK_VARIADIC_ELEM_1(__VA_ARGS__, F, ), static, typename) +#define MOCK_STATIC_METHOD(F, arity, ...) \ + MOCK_FUNCTION_AUX(F, arity, MOCK_VARIADIC_ELEM_0(__VA_ARGS__, ), MOCK_VARIADIC_ELEM_1(__VA_ARGS__, F, ), static) /// MOCK_EXPECT( identifier ) -#define MOCK_EXPECT(t) MOCK_HELPER(t).expect(__FILE__, __LINE__) +/// Begin setting up expectation for the identifier +#define MOCK_EXPECT(identifier) MOCK_HELPER(identifier).expect(__FILE__, __LINE__) /// MOCK_RESET( identifier ) -#define MOCK_RESET(t) MOCK_HELPER(t).reset(__FILE__, __LINE__) +/// Reset all pending expectations for the identifier +#define MOCK_RESET(identifier) MOCK_HELPER(identifier).reset(__FILE__, __LINE__) /// MOCK_VERIFY( identifier ) -#define MOCK_VERIFY(t) MOCK_HELPER(t).verify(__FILE__, __LINE__) +/// Verify all expectations for the identifier have been met +#define MOCK_VERIFY(identifier) MOCK_HELPER(identifier).verify(__FILE__, __LINE__) + +// Replaced macros +#define MOCK_DETAIL_REPLACED_MACRO_ERROR(oldName, newName) \ + static_assert(false, #oldName " has been replaced by " #newName) +#define MOCK_CONST_CONVERSION_OPERATOR_TPL(...) \ + MOCK_DETAIL_REPLACED_MACRO_ERROR(MOCK_CONST_CONVERSION_OPERATOR_TPL, MOCK_CONST_CONVERSION_OPERATOR) +#define MOCK_CONST_METHOD_EXT_TPL(...) MOCK_DETAIL_REPLACED_MACRO_ERROR(MOCK_CONST_METHOD_EXT_TPL, MOCK_CONST_METHOD) +#define MOCK_CONST_METHOD_TPL(...) MOCK_DETAIL_REPLACED_MACRO_ERROR(MOCK_CONST_METHOD_TPL, MOCK_CONST_METHOD) +#define MOCK_CONVERSION_OPERATOR_TPL(...) \ + MOCK_DETAIL_REPLACED_MACRO_ERROR(MOCK_CONVERSION_OPERATOR_TPL, MOCK_CONVERSION_OPERATOR) +#define MOCK_FUNCTOR_TPL(...) MOCK_DETAIL_REPLACED_MACRO_ERROR(MOCK_FUNCTOR_TPL, MOCK_FUNCTOR) +#define MOCK_METHOD_EXT_TPL(...) MOCK_DETAIL_REPLACED_MACRO_ERROR(MOCK_METHOD_EXT_TPL, MOCK_METHOD) +#define MOCK_METHOD_TPL(...) MOCK_DETAIL_REPLACED_MACRO_ERROR(MOCK_METHOD_TPL, MOCK_METHOD) +#define MOCK_NON_CONST_CONVERSION_OPERATOR_TPL(...) \ + MOCK_DETAIL_REPLACED_MACRO_ERROR(MOCK_NON_CONST_CONVERSION_OPERATOR_TPL, MOCK_NON_CONST_CONVERSION_OPERATOR) +#define MOCK_NON_CONST_METHOD_EXT_TPL(...) \ + MOCK_DETAIL_REPLACED_MACRO_ERROR(MOCK_NON_CONST_METHOD_EXT_TPL, MOCK_NON_CONST_METHOD) +#define MOCK_NON_CONST_METHOD_TPL(...) \ + MOCK_DETAIL_REPLACED_MACRO_ERROR(MOCK_NON_CONST_METHOD_TPL, MOCK_NON_CONST_METHOD) +#define MOCK_STATIC_METHOD_TPL(...) MOCK_DETAIL_REPLACED_MACRO_ERROR(MOCK_STATIC_METHOD_TPL, MOCK_STATIC_METHOD) +#define MOCK_CONSTRUCTOR_TPL(...) MOCK_DETAIL_REPLACED_MACRO_ERROR(MOCK_CONSTRUCTOR_TPL, MOCK_CONSTRUCTOR) #endif // MOCK_MOCK_HPP_INCLUDED diff --git a/test/test_integration.cpp b/test/test_integration.cpp index aceccd5..11aea83 100644 --- a/test/test_integration.cpp +++ b/test/test_integration.cpp @@ -187,8 +187,8 @@ template struct my_template_mock { MOCK_METHOD_EXT(my_method, 0, void(), my_tag) - MOCK_METHOD_EXT_TPL(my_method, 2, void(T, std::string), my_tpl_tag) - MOCK_METHOD_EXT_TPL(my_other_method, 0, void(), my_other_tag) + MOCK_METHOD_EXT(my_method, 2, void(T, std::string), my_tpl_tag) + MOCK_METHOD_EXT(my_other_method, 0, void(), my_other_tag) }; } // namespace @@ -212,8 +212,8 @@ struct my_template_base_class template MOCK_BASE_CLASS(my_template_base_class_mock, my_template_base_class) { - MOCK_METHOD_EXT_TPL(my_method, 1, void(T), my_method) - MOCK_METHOD_EXT_TPL(my_other_method, 0, void(), my_other_method) + MOCK_METHOD_EXT(my_method, 1, void(T), my_method) + MOCK_METHOD_EXT(my_other_method, 0, void(), my_other_method) }; } // namespace @@ -307,7 +307,7 @@ namespace { template MOCK_CLASS(my_constructed_template_class) { - MOCK_CONSTRUCTOR_TPL(my_constructed_template_class, 2, (T, const std::string&), constructor) + MOCK_CONSTRUCTOR(my_constructed_template_class, 2, (T, const std::string&), constructor) }; } // namespace @@ -511,7 +511,7 @@ namespace { template struct some_template_class { - MOCK_STATIC_METHOD_TPL(some_static_method, 1, void(T), some_static_method) + MOCK_STATIC_METHOD(some_static_method, 1, void(T), some_static_method) }; } // namespace diff --git a/test/test_mock.cpp b/test/test_mock.cpp index edcea98..5460838 100644 --- a/test/test_mock.cpp +++ b/test/test_mock.cpp @@ -64,7 +64,9 @@ BOOST_FIXTURE_TEST_CASE(mock_conversion_operator, mock_error_fixture) namespace { template MOCK_CLASS(mock_template_class_with_conversion_operator) -{ MOCK_CONVERSION_OPERATOR_TPL(operator, T, conversion) }; +{ + MOCK_CONVERSION_OPERATOR(operator, T, conversion) +}; } // namespace BOOST_FIXTURE_TEST_CASE(mock_template_conversion_operator, mock_error_fixture) @@ -111,7 +113,7 @@ namespace { template MOCK_CLASS(mock_template_class_with_const_conversion_operator) { - MOCK_CONST_CONVERSION_OPERATOR_TPL(operator, T, conversion) + MOCK_CONST_CONVERSION_OPERATOR(operator, T, conversion) }; } // namespace @@ -127,7 +129,7 @@ namespace { template MOCK_CLASS(mock_template_class_with_non_const_conversion_operator) { - MOCK_NON_CONST_CONVERSION_OPERATOR_TPL(operator, T, conversion) + MOCK_NON_CONST_CONVERSION_OPERATOR(operator, T, conversion) }; } // namespace @@ -346,14 +348,14 @@ template MOCK_BASE_CLASS(variadic_tpl, base) { MOCK_METHOD(m1, 0, void()) - MOCK_METHOD_TPL(m2, 0, T()) - MOCK_METHOD_TPL(m3, 0, T(), m3) - MOCK_CONST_METHOD_TPL(m4, 0, T()) - MOCK_CONST_METHOD_TPL(m5, 0, T(), m5) - MOCK_NON_CONST_METHOD_TPL(m6, 0, T()) - MOCK_NON_CONST_METHOD_TPL(m7, 0, T(), m7) - MOCK_STATIC_METHOD_TPL(m8, 0, T()) - MOCK_STATIC_METHOD_TPL(m9, 0, T(), m9) + MOCK_METHOD(m2, 0, T()) + MOCK_METHOD(m3, 0, T(), m3) + MOCK_CONST_METHOD(m4, 0, T()) + MOCK_CONST_METHOD(m5, 0, T(), m5) + MOCK_NON_CONST_METHOD(m6, 0, T()) + MOCK_NON_CONST_METHOD(m7, 0, T(), m7) + MOCK_STATIC_METHOD(m8, 0, T()) + MOCK_STATIC_METHOD(m9, 0, T(), m9) }; MOCK_BASE_CLASS(comma_base, std::map)