Reduce exposed interface (macros)

Move implementation details to mock_impl.hpp and remove MOCK_*_TPL macros.
Make sure all exposed macros (in mock.hpp) are properly documented.
Closes #105
This commit is contained in:
Alexander Grund 2022-01-24 19:03:15 +01:00
parent 3dda0bf328
commit bd0a4cfc73
No known key found for this signature in database
GPG key ID: AA48A0760367A42B
9 changed files with 191 additions and 217 deletions

View file

@ -134,27 +134,17 @@ StatementMacros:
- MOCK_BASE_CLASS - MOCK_BASE_CLASS
- MOCK_CLASS - MOCK_CLASS
- MOCK_CONSTRUCTOR - MOCK_CONSTRUCTOR
- MOCK_CONSTRUCTOR_TPL
- MOCK_CONST_CONVERSION_OPERATOR - MOCK_CONST_CONVERSION_OPERATOR
- MOCK_CONST_CONVERSION_OPERATOR_TPL
- MOCK_CONST_METHOD - MOCK_CONST_METHOD
- MOCK_CONST_METHOD_EXT - MOCK_CONST_METHOD_EXT
- MOCK_CONST_METHOD_EXT_TPL
- MOCK_CONST_METHOD_TPL
- MOCK_CONVERSION_OPERATOR - MOCK_CONVERSION_OPERATOR
- MOCK_DESTRUCTOR - MOCK_DESTRUCTOR
- MOCK_METHOD - MOCK_METHOD
- MOCK_METHOD_EXT - MOCK_METHOD_EXT
- MOCK_METHOD_EXT_TPL
- MOCK_METHOD_TPL
- MOCK_NON_CONST_CONVERSION_OPERATOR - MOCK_NON_CONST_CONVERSION_OPERATOR
- MOCK_NON_CONST_CONVERSION_OPERATOR_TPL
- MOCK_NON_CONST_METHOD - MOCK_NON_CONST_METHOD
- MOCK_NON_CONST_METHOD_EXT - MOCK_NON_CONST_METHOD_EXT
- MOCK_NON_CONST_METHOD_EXT_TPL
- MOCK_NON_CONST_METHOD_TPL
- MOCK_STATIC_METHOD - MOCK_STATIC_METHOD
- MOCK_STATIC_METHOD_TPL
TabWidth: 4 TabWidth: 4
UseCRLF: false UseCRLF: false
UseTab: Never UseTab: Never

View file

@ -12,7 +12,7 @@ Released -
* Allow auto-deducing signature in `MOCK_METHOD_(NON_)CONST` * Allow auto-deducing signature in `MOCK_METHOD_(NON_)CONST`
* Replaced Boost facilities with std:: equivalents where existing in C++14 * 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 * Added MOCK_PROTECT_FUNCTION_SIG to pass function signatures with commas in the return type
[endsect] [endsect]

View file

@ -215,10 +215,8 @@ namespace member_function_example_7 {
template<typename T> template<typename T>
MOCK_CLASS(mock_class) MOCK_CLASS(mock_class)
{ {
MOCK_METHOD_TPL( MOCK_METHOD(method, 1,
method, void(const T&)) // includes a template parameter of the class
1,
void(const T&)) // the _TPL variants must be used if the signature includes a template parameter of the class
}; };
//] //]
} // namespace member_function_example_7 } // namespace member_function_example_7
@ -262,7 +260,7 @@ namespace static_member_function_example_2 {
template<typename T> template<typename T>
MOCK_CLASS(mock_class) 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 } // namespace static_member_function_example_2
@ -296,7 +294,7 @@ template<typename T>
MOCK_CLASS(mock_class) MOCK_CLASS(mock_class)
{ {
MOCK_CONSTRUCTOR(mock_class, 2, (int, const std::string&), identifier) 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 } // namespace constructor_example_2
@ -347,8 +345,7 @@ namespace conversion_operator_example_2 {
template<typename T> template<typename T>
MOCK_CLASS(mock_class) MOCK_CLASS(mock_class)
{ {
MOCK_CONVERSION_OPERATOR_TPL(operator, T, conversion_to_T) // the _TPL variants must be used if the signature MOCK_CONVERSION_OPERATOR(operator, T, conversion_to_T) // includes a template parameter of the class
// includes a template parameter of the class
MOCK_CONST_CONVERSION_OPERATOR(operator, const std::string&, const_conversion_to_string) 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) MOCK_NON_CONST_CONVERSION_OPERATOR(operator, const std::string&, non_const_conversion_to_string)
}; };

View file

@ -91,15 +91,11 @@ Synopsis :
MOCK_CONST_METHOD( [calling convention] name, arity[, signature[, identifier]] ) // generates only the const version of the method 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_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 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 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.] [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 : Synopsis :
MOCK_METHOD_EXT( [calling convention] name, arity, signature, identifier ) // generates both const and non-const methods MOCK_METHOD( [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_CONST_METHOD( [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_NON_CONST_METHOD( [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
Example : Example :
@ -159,8 +151,6 @@ Synopsis :
MOCK_STATIC_METHOD( [calling convention] name, arity, signature[, identifier] ) // if 'identifier' is omitted it will default to 'name' 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].] [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].]
[note In case of a calling convention specified, all four parameters must be provided.] [note In case of a calling convention specified, all four parameters must be provided.]
@ -189,8 +179,6 @@ Synopsis :
MOCK_CONSTRUCTOR( [calling convention] name, arity, parameters, identifier ) 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.] [note As constructors do not have a return type, the usual signature gets restricted here to just the parameters.]
Example : Example :
@ -241,10 +229,6 @@ Synopsis :
MOCK_CONST_CONVERSION_OPERATOR( [calling convention] name, type, identifier ) // generates only a const operator 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_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 : Example :
[conversion_operator_example_1] [conversion_operator_example_1]
@ -293,8 +277,6 @@ Synopsis :
MOCK_FUNCTOR( [calling convention] name, signature ); MOCK_FUNCTOR( [calling convention] name, signature );
MOCK_FUNCTOR_TPL( [calling convention] name, signature ); // must be used if the signature uses a template parameter
Example : Example :
[functor_example_1] [functor_example_1]

View file

@ -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 <boost/preprocessor/repetition/repeat.hpp>
#include <boost/preprocessor/stringize.hpp>
// 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<MOCK_FUNCTION_TYPE(S)> t##_mock_; \
mock::detail::function<MOCK_FUNCTION_TYPE(S)>& 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<MOCK_FUNCTION_TYPE(S)> 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<MOCK_FUNCTION_TYPE(S)>::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<MOCK_FUNCTION_TYPE(S)>& t##_mock(mock::detail::context& context, \
boost::unit_test::const_string instance) \
{ \
static mock::detail::function<MOCK_FUNCTION_TYPE(S)> 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<MOCK_FUNCTION_TYPE(S)>::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

View file

@ -36,6 +36,8 @@ namespace mock { namespace detail {
{ {
using type = R; using type = R;
}; };
template<typename Signature>
using result_type_t = typename result_type<Signature>::type;
template<typename Signature> template<typename Signature>
struct function_arity; struct function_arity;
@ -55,12 +57,14 @@ namespace mock { namespace detail {
using type = tuple<Args...>; using type = tuple<Args...>;
}; };
template<typename Signature, int n> template<typename Signature, std::size_t n>
struct parameter struct parameter
{ {
static_assert(n < function_arity<Signature>::value, "Function signature has not that many parameters"); static_assert(n < function_arity<Signature>::value, "Function signature has not that many parameters");
using type = typename tuple_element<n, typename parameter_types<Signature>::type>::type; using type = typename tuple_element<n, typename parameter_types<Signature>::type>::type;
}; };
template<typename T, std::size_t n>
using parameter_t = typename parameter<T, n>::type;
template<typename T> template<typename T>
struct parameter_type; struct parameter_type;

View file

@ -11,159 +11,64 @@
#include "cleanup.hpp" #include "cleanup.hpp"
#include "config.hpp" #include "config.hpp"
#include "detail/function.hpp" #include "detail/mock_impl.hpp"
#include "detail/functor.hpp"
#include "detail/parameter.hpp"
#include "detail/signature.hpp"
#include "detail/type_name.hpp"
#include "object.hpp" #include "object.hpp"
#include "reset.hpp" #include "reset.hpp"
#include "verify.hpp" #include "verify.hpp"
#include <boost/preprocessor/repetition/repeat.hpp>
#include <boost/preprocessor/stringize.hpp>
/// MOCK_CLASS( name ) /// MOCK_CLASS( name )
/// Define a class /// 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 ) /// MOCK_PROTECT_FUNCTION_SIG( signature )
/// Use this with MOCK_FUNCTION/MOCK_*_METHOD if the return type contains commas /// Use this with MOCK_FUNCTION/MOCK_*_METHOD if the return type contains commas
#define MOCK_PROTECT_FUNCTION_SIG(...) mock::detail::parameter_type_t<void(__VA_ARGS__)> #define MOCK_PROTECT_FUNCTION_SIG(...) mock::detail::parameter_type_t<void(__VA_ARGS__)>
/// 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 ) /// MOCK_FUNCTOR( name, signature )
/// Define a callable variable/member /// Define a callable variable/member
#define MOCK_FUNCTOR(f, ...) mock::detail::functor<MOCK_FUNCTION_TYPE(__VA_ARGS__)> f, f##_mock #define MOCK_FUNCTOR(name, ...) mock::detail::functor<MOCK_FUNCTION_TYPE(__VA_ARGS__)> name, name##_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<MOCK_FUNCTION_TYPE(S)> t##_mock_; \
mock::detail::function<MOCK_FUNCTION_TYPE(S)>& 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<MOCK_FUNCTION_TYPE(S)>::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<MOCK_FUNCTION_TYPE(S)>::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)
/// MOCK_CONVERSION_OPERATOR( [calling convention] name, type, identifier ) /// MOCK_CONVERSION_OPERATOR( [calling convention] name, type, identifier )
/// generates both const and non-const operators /// generates both const and non-const conversion operators
#define MOCK_CONVERSION_OPERATOR(M, T, t) \ #define MOCK_CONVERSION_OPERATOR(M, T, identifier) \
M T() const { return MOCK_ANONYMOUS_HELPER(t)(); } \ M T() const { return MOCK_ANONYMOUS_HELPER(identifier)(); } \
M T() { return MOCK_ANONYMOUS_HELPER(t)(); } \ M T() { return MOCK_ANONYMOUS_HELPER(identifier)(); } \
MOCK_METHOD_HELPER(T(), t) MOCK_METHOD_HELPER(T(), identifier)
/// MOCK_CONST_CONVERSION_OPERATOR( [calling convention] name, type, identifier ) /// MOCK_CONST_CONVERSION_OPERATOR( [calling convention] name, type, identifier )
/// generates only a const operator /// generates only a const conversion operator
#define MOCK_CONST_CONVERSION_OPERATOR(M, T, t) \ #define MOCK_CONST_CONVERSION_OPERATOR(M, T, identifier) \
M T() const { return MOCK_ANONYMOUS_HELPER(t)(); } \ M T() const { return MOCK_ANONYMOUS_HELPER(identifier)(); } \
MOCK_METHOD_HELPER(T(), t) MOCK_METHOD_HELPER(T(), identifier)
/// MOCK_NON_CONST_CONVERSION_OPERATOR( [calling convention] name, type, identifier ) /// MOCK_NON_CONST_CONVERSION_OPERATOR( [calling convention] name, type, identifier )
/// generates only a non-const operator /// generates only a non-const conversion operator
#define MOCK_NON_CONST_CONVERSION_OPERATOR(M, T, t) \ #define MOCK_NON_CONST_CONVERSION_OPERATOR(M, T, identifier) \
M T() { return MOCK_ANONYMOUS_HELPER(t)(); } \ M T() { return MOCK_ANONYMOUS_HELPER(identifier)(); } \
MOCK_METHOD_HELPER(T(), t) MOCK_METHOD_HELPER(T(), identifier)
#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<MOCK_FUNCTION_TYPE(S)>& t##_mock(mock::detail::context& context, \
boost::unit_test::const_string instance) \
{ \
static mock::detail::function<MOCK_FUNCTION_TYPE(S)> 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)
/// MOCK_CONSTRUCTOR( [calling convention] name, arity, parameters, 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. /// 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, ) #define MOCK_CONSTRUCTOR(T, arity, parameters, identifier) MOCK_CONSTRUCTOR_AUX(T, arity, parameters, identifier)
/// 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)
/// MOCK_DESTRUCTOR( [calling convention] ~name, identifier ) /// MOCK_DESTRUCTOR( [calling convention] ~name, identifier )
#define MOCK_DESTRUCTOR(T, t) \ #define MOCK_DESTRUCTOR(T, identifier) \
T() \ T() \
{ \ { \
try \ try \
{ \ { \
MOCK_ANONYMOUS_HELPER(t)(); \ MOCK_ANONYMOUS_HELPER(identifier)(); \
} catch(...) \ } catch(...) \
{} \ {} \
} \ } \
MOCK_METHOD_HELPER(void(), t) MOCK_METHOD_HELPER(void(), identifier)
#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<MOCK_FUNCTION_TYPE(S)>::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
/// MOCK_METHOD( [calling convention] name, arity[, signature[, identifier]] ) /// MOCK_METHOD( [calling convention] name, arity[, signature[, identifier]] )
/// generates both const and non-const methods /// 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, ...) \ #define MOCK_METHOD(M, ...) \
MOCK_METHOD_EXT(M, \ MOCK_METHOD_EXT(M, \
MOCK_VARIADIC_ELEM_0(__VA_ARGS__, ), \ MOCK_VARIADIC_ELEM_0(__VA_ARGS__, ), \
@ -171,6 +76,8 @@
MOCK_VARIADIC_ELEM_2(__VA_ARGS__, M, M, )) MOCK_VARIADIC_ELEM_2(__VA_ARGS__, M, M, ))
/// MOCK_CONST_METHOD( [calling convention] name, arity[, signature[, identifier]] ) /// MOCK_CONST_METHOD( [calling convention] name, arity[, signature[, identifier]] )
/// generates only the const version of the method /// 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, ...) \ #define MOCK_CONST_METHOD(M, ...) \
MOCK_CONST_METHOD_EXT(M, \ MOCK_CONST_METHOD_EXT(M, \
MOCK_VARIADIC_ELEM_0(__VA_ARGS__, ), \ MOCK_VARIADIC_ELEM_0(__VA_ARGS__, ), \
@ -178,50 +85,53 @@
MOCK_VARIADIC_ELEM_2(__VA_ARGS__, M, M, )) MOCK_VARIADIC_ELEM_2(__VA_ARGS__, M, M, ))
/// MOCK_NON_CONST_METHOD( [calling convention] name, arity[, signature[, identifier]] ) /// MOCK_NON_CONST_METHOD( [calling convention] name, arity[, signature[, identifier]] )
/// generates only the non-const version of the method /// 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, ...) \ #define MOCK_NON_CONST_METHOD(M, ...) \
MOCK_NON_CONST_METHOD_EXT(M, \ MOCK_NON_CONST_METHOD_EXT(M, \
MOCK_VARIADIC_ELEM_0(__VA_ARGS__, ), \ MOCK_VARIADIC_ELEM_0(__VA_ARGS__, ), \
MOCK_VARIADIC_ELEM_1(__VA_ARGS__, MOCK_SIGNATURE(M), ), \ MOCK_VARIADIC_ELEM_1(__VA_ARGS__, MOCK_SIGNATURE(M), ), \
MOCK_VARIADIC_ELEM_2(__VA_ARGS__, M, 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] ) /// MOCK_FUNCTION( [calling convention] name, arity, signature[, identifier] )
/// if 'identifier' is omitted it will default to 'name' /// if 'identifier' is omitted it will default to 'name'
#define MOCK_FUNCTION(F, n, ...) \ #define MOCK_FUNCTION(F, arity, ...) \
MOCK_FUNCTION_AUX(F, n, MOCK_VARIADIC_ELEM_0(__VA_ARGS__, ), MOCK_VARIADIC_ELEM_1(__VA_ARGS__, F, ), inline, ) 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] ) /// MOCK_STATIC_METHOD( [calling convention] name, arity, signature[, identifier] )
/// if 'identifier' is omitted it will default to 'name' /// if 'identifier' is omitted it will default to 'name'
#define MOCK_STATIC_METHOD(F, n, ...) \ #define MOCK_STATIC_METHOD(F, arity, ...) \
MOCK_FUNCTION_AUX(F, n, MOCK_VARIADIC_ELEM_0(__VA_ARGS__, ), MOCK_VARIADIC_ELEM_1(__VA_ARGS__, F, ), static, ) MOCK_FUNCTION_AUX(F, arity, 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)
/// MOCK_EXPECT( identifier ) /// 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 ) /// 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 ) /// 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 #endif // MOCK_MOCK_HPP_INCLUDED

View file

@ -187,8 +187,8 @@ template<typename T>
struct my_template_mock struct my_template_mock
{ {
MOCK_METHOD_EXT(my_method, 0, void(), my_tag) 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(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_other_method, 0, void(), my_other_tag)
}; };
} // namespace } // namespace
@ -212,8 +212,8 @@ struct my_template_base_class
template<typename T> template<typename T>
MOCK_BASE_CLASS(my_template_base_class_mock, my_template_base_class<T>) MOCK_BASE_CLASS(my_template_base_class_mock, my_template_base_class<T>)
{ {
MOCK_METHOD_EXT_TPL(my_method, 1, void(T), my_method) MOCK_METHOD_EXT(my_method, 1, void(T), my_method)
MOCK_METHOD_EXT_TPL(my_other_method, 0, void(), my_other_method) MOCK_METHOD_EXT(my_other_method, 0, void(), my_other_method)
}; };
} // namespace } // namespace
@ -307,7 +307,7 @@ namespace {
template<typename T> template<typename T>
MOCK_CLASS(my_constructed_template_class) 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 } // namespace
@ -511,7 +511,7 @@ namespace {
template<typename T> template<typename T>
struct some_template_class 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 } // namespace

View file

@ -64,7 +64,9 @@ BOOST_FIXTURE_TEST_CASE(mock_conversion_operator, mock_error_fixture)
namespace { namespace {
template<typename T> template<typename T>
MOCK_CLASS(mock_template_class_with_conversion_operator) MOCK_CLASS(mock_template_class_with_conversion_operator)
{ MOCK_CONVERSION_OPERATOR_TPL(operator, T, conversion) }; {
MOCK_CONVERSION_OPERATOR(operator, T, conversion)
};
} // namespace } // namespace
BOOST_FIXTURE_TEST_CASE(mock_template_conversion_operator, mock_error_fixture) BOOST_FIXTURE_TEST_CASE(mock_template_conversion_operator, mock_error_fixture)
@ -111,7 +113,7 @@ namespace {
template<typename T> template<typename T>
MOCK_CLASS(mock_template_class_with_const_conversion_operator) 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 } // namespace
@ -127,7 +129,7 @@ namespace {
template<typename T> template<typename T>
MOCK_CLASS(mock_template_class_with_non_const_conversion_operator) 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 } // namespace
@ -346,14 +348,14 @@ template<typename T>
MOCK_BASE_CLASS(variadic_tpl, base) MOCK_BASE_CLASS(variadic_tpl, base)
{ {
MOCK_METHOD(m1, 0, void()) MOCK_METHOD(m1, 0, void())
MOCK_METHOD_TPL(m2, 0, T()) MOCK_METHOD(m2, 0, T())
MOCK_METHOD_TPL(m3, 0, T(), m3) MOCK_METHOD(m3, 0, T(), m3)
MOCK_CONST_METHOD_TPL(m4, 0, T()) MOCK_CONST_METHOD(m4, 0, T())
MOCK_CONST_METHOD_TPL(m5, 0, T(), m5) MOCK_CONST_METHOD(m5, 0, T(), m5)
MOCK_NON_CONST_METHOD_TPL(m6, 0, T()) MOCK_NON_CONST_METHOD(m6, 0, T())
MOCK_NON_CONST_METHOD_TPL(m7, 0, T(), m7) MOCK_NON_CONST_METHOD(m7, 0, T(), m7)
MOCK_STATIC_METHOD_TPL(m8, 0, T()) MOCK_STATIC_METHOD(m8, 0, T())
MOCK_STATIC_METHOD_TPL(m9, 0, T(), m9) MOCK_STATIC_METHOD(m9, 0, T(), m9)
}; };
MOCK_BASE_CLASS(comma_base, std::map<int, int>) MOCK_BASE_CLASS(comma_base, std::map<int, int>)