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/CMakeLists.txt b/CMakeLists.txt index 957f3d7..5ddc100 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -21,7 +21,8 @@ endif() find_package(Boost 1.58 REQUIRED) set(MOCK_VERSION "\"${PROJECT_VERSION}\"") -configure_file(version.hpp.cmake ${CMAKE_CURRENT_BINARY_DIR}/include/turtle/version.hpp @ONLY) +set(_turtleVersionFile ${CMAKE_CURRENT_BINARY_DIR}/include/turtle/version.hpp) +configure_file(version.hpp.cmake ${_turtleVersionFile} @ONLY) add_library(turtle INTERFACE) add_library(turtle::turtle ALIAS turtle) @@ -30,6 +31,14 @@ target_compile_features(turtle INTERFACE cxx_std_14) target_link_libraries(turtle INTERFACE Boost::boost Boost::disable_autolinking) +if(NOT CMAKE_VERSION VERSION_LESS 3.19) + file(GLOB _turtleHeaders include/turtle/*.hpp) + file(GLOB _turtleHeadersDetail include/turtle/detail/*.hpp) + source_group(turtle FILES ${_turtleHeaders} ${_turtleVersionFile}) + source_group(turtle/detail FILES ${_turtleHeadersDetail}) + target_sources(turtle PRIVATE ${_turtleHeaders} ${_turtleVersionFile} ${_turtleHeadersDetail}) +endif() + if(BUILD_TESTING) add_subdirectory(test) endif() diff --git a/doc/changelog.qbk b/doc/changelog.qbk index 20c3d4c..c608e81 100644 --- a/doc/changelog.qbk +++ b/doc/changelog.qbk @@ -12,8 +12,9 @@ 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 -* Added MOCK_PROTECT_FUNCTION_SIG to pass function signatures with commas in the return type +* Removed MOCK_*_TPL as they are no longer required, use the non _TPL variant even for templates +* Added MOCK_PROTECT_SIGNATURE to pass function signatures with commas in the return type +* Remove support for protecting function signatures via BOOST_IDENTITY_TYPE, use MOCK_PROTECT_SIGNATURE instead [endsect] diff --git a/doc/example/reference.cpp b/doc/example/reference.cpp index adec0b3..2b19a4e 100644 --- a/doc/example/reference.cpp +++ b/doc/example/reference.cpp @@ -88,8 +88,8 @@ class base struct name : base, mock::object // equivalent to using MOCK_BASE_CLASS { - typedef base - base_type; // this is required for the shortest form of MOCK_METHOD to work when not using MOCK_BASE_CLASS + // this is required for the shortest form of MOCK_METHOD to work when not using MOCK_BASE_CLASS + using base_type = base; }; //] } // namespace class_example_7 @@ -103,7 +103,7 @@ struct base template struct name : base, mock::object { - typedef base base_type; + using base_type = base; }; //] } // namespace class_example_8 @@ -134,15 +134,10 @@ struct base_class MOCK_BASE_CLASS(mock_class, base_class) { - MOCK_METHOD( - method, - 2, - void(int, const std::string&), - identifier_1) // both the signature and identifier must be specified because of ambiguity due to overloading - MOCK_METHOD(method, - 1, - void(float), - identifier_2) // the identifier must differ from the previous one in order to fully disambiguate methods + // both the signature and identifier must be specified because of ambiguity due to overloading + MOCK_METHOD(method, 2, void(int, const std::string&), identifier_1) + // the identifier must differ from the previous one in order to fully disambiguate methods + MOCK_METHOD(method, 1, void(float), identifier_2) }; //] } // namespace member_function_example_2 @@ -174,9 +169,10 @@ struct base_class MOCK_BASE_CLASS(mock_class, base_class) { - MOCK_CONST_METHOD(method, 1, void(float), identifier_1) // this generates only the const version - MOCK_NON_CONST_METHOD( - method, 1, void(float), identifier_2) // this generates only the non-const version, with a different identifier + // this generates only the const version + MOCK_CONST_METHOD(method, 1, void(float), identifier_1) + // this generates only the non-const version, with a different identifier + MOCK_NON_CONST_METHOD(method, 1, void(float), identifier_2) }; //] } // namespace member_function_example_4 @@ -191,7 +187,7 @@ struct base_class struct mock_class : base_class { - typedef base_class base_type; // this is required for MOCK_METHOD to work when not using MOCK_BASE_CLASS + using base_type = base_class; // this is required for MOCK_METHOD to work when not using MOCK_BASE_CLASS MOCK_METHOD(method, 1) }; @@ -215,10 +211,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 + // includes a template parameter of the class + MOCK_METHOD(method, 1, void(const T&)) }; //] } // namespace member_function_example_7 @@ -227,11 +221,14 @@ namespace member_function_example_8 { //[ member_function_example_8 MOCK_CLASS(mock_class) { - MOCK_METHOD( - method, 0, BOOST_IDENTITY_TYPE((std::map()))) // the signature must be wrapped in BOOST_IDENTITY_TYPE if - // the return type contains a comma + // the signature must be wrapped in MOCK_PROTECT_SIGNATURE if the return type contains a comma + MOCK_METHOD(method, 0, MOCK_PROTECT_SIGNATURE(std::map())) }; //] + +static_assert(std::is_same().method()), std::map>::value, + "Wrong return value"); + } // namespace member_function_example_8 #ifdef BOOST_MSVC @@ -239,10 +236,8 @@ namespace member_function_example_9 { //[ member_function_example_9 MOCK_CLASS(mock_class) { - MOCK_METHOD(__stdcall method, - 0, - void(), - method) // all parameters must be provided when specifying a different calling convention + // all parameters must be provided when specifying a different calling convention + MOCK_METHOD(__stdcall method, 0, void(), method) }; //] } // namespace member_function_example_9 @@ -262,7 +257,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 @@ -272,10 +267,8 @@ namespace static_member_function_example_3 { //[ static_member_function_example_3 MOCK_CLASS(mock_class) { - MOCK_STATIC_METHOD(__stdcall method, - 0, - void(), - method) // all parameters must be provided when specifying a different calling convention + // all parameters must be provided when specifying a different calling convention + MOCK_STATIC_METHOD(__stdcall method, 0, void(), method) }; //] } // namespace static_member_function_example_3 @@ -296,7 +289,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 +340,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) }; @@ -381,10 +373,8 @@ BOOST_AUTO_TEST_CASE(demonstrates_instantiating_a_mock_function) #ifdef BOOST_MSVC namespace function_example_2 { //[ function_example_2 -MOCK_FUNCTION(__stdcall f, - 0, - void(), - f) // all parameters must be provided when specifying a different calling convention +// all parameters must be provided when specifying a different calling convention +MOCK_FUNCTION(__stdcall f, 0, void(), f) //] } // namespace function_example_2 #endif @@ -898,11 +888,10 @@ BOOST_AUTO_TEST_CASE(mock_constraint_0_arity) namespace helpers_example_2 { //[ helpers_example_2 -MOCK_CONSTRAINT(equal, expected, actual == expected) // this is how mock::equal could be defined -MOCK_CONSTRAINT(near, - expected, - std::abs(actual - expected) < - 0.01) // this defines a 'near' constraint which can be used as 'near( 42 )' +// this is how mock::equal could be defined +MOCK_CONSTRAINT(equal, expected, actual == expected) +// this defines a 'near' constraint which can be used as 'near( 42 )' +MOCK_CONSTRAINT(near, expected, std::abs(actual - expected) < 0.01) BOOST_AUTO_TEST_CASE(mock_constraint_1_arity) { @@ -915,10 +904,8 @@ BOOST_AUTO_TEST_CASE(mock_constraint_1_arity) namespace helpers_example_3 { //[ helpers_example_3 -MOCK_CONSTRAINT(near, - expected, - tolerance, - std::abs(actual - expected) < tolerance) // this is how mock::near could be defined +// this is how mock::near could be defined +MOCK_CONSTRAINT(near, expected, tolerance, std::abs(actual - expected) <= tolerance) BOOST_AUTO_TEST_CASE(mock_constraint_2_arity) { 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..211e81c --- /dev/null +++ b/include/turtle/detail/mock_impl.hpp @@ -0,0 +1,113 @@ +// 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 "signature.hpp" +#include "signature_traits.hpp" +#include "type_name.hpp" +#include +#include +#include + +namespace mock { namespace detail { + /// Simplified trait to extract the argument type of a function signature with 1 argument + template + struct arg_type; + template + struct arg_type + { + using type = U; + }; + /// Used in MOCK_PROTECT_SIGNATURE to unwrap the passed function signature + /// T is something like `void(std::map)` + template + using unwrap_signature_t = std::remove_pointer_t::type>; +}} // namespace mock::detail + +#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 < 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) \ + static_assert(n == mock::detail::function_arity_t::value, "Arity mismatch"); \ + MOCK_DECL(M, n, S, c) { 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) \ + static_assert(n == mock::detail::function_arity_t::value, "Arity mismatch"); \ + s MOCK_DECL(F, n, S, ) { 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 + +#define MOCK_REPLACED_MACRO_ERROR(oldName, newName) static_assert(false, #oldName " has been replaced by " #newName) +// Replaced macros +#define MOCK_CONST_CONVERSION_OPERATOR_TPL(...) \ + MOCK_REPLACED_MACRO_ERROR(MOCK_CONST_CONVERSION_OPERATOR_TPL, MOCK_CONST_CONVERSION_OPERATOR) +#define MOCK_CONST_METHOD_EXT_TPL(...) MOCK_REPLACED_MACRO_ERROR(MOCK_CONST_METHOD_EXT_TPL, MOCK_CONST_METHOD) +#define MOCK_CONST_METHOD_TPL(...) MOCK_REPLACED_MACRO_ERROR(MOCK_CONST_METHOD_TPL, MOCK_CONST_METHOD) +#define MOCK_CONVERSION_OPERATOR_TPL(...) \ + MOCK_REPLACED_MACRO_ERROR(MOCK_CONVERSION_OPERATOR_TPL, MOCK_CONVERSION_OPERATOR) +#define MOCK_FUNCTOR_TPL(...) MOCK_REPLACED_MACRO_ERROR(MOCK_FUNCTOR_TPL, MOCK_FUNCTOR) +#define MOCK_METHOD_EXT_TPL(...) MOCK_REPLACED_MACRO_ERROR(MOCK_METHOD_EXT_TPL, MOCK_METHOD) +#define MOCK_METHOD_TPL(...) MOCK_REPLACED_MACRO_ERROR(MOCK_METHOD_TPL, MOCK_METHOD) +#define MOCK_NON_CONST_CONVERSION_OPERATOR_TPL(...) \ + MOCK_REPLACED_MACRO_ERROR(MOCK_NON_CONST_CONVERSION_OPERATOR_TPL, MOCK_NON_CONST_CONVERSION_OPERATOR) +#define MOCK_NON_CONST_METHOD_EXT_TPL(...) \ + MOCK_REPLACED_MACRO_ERROR(MOCK_NON_CONST_METHOD_EXT_TPL, MOCK_NON_CONST_METHOD) +#define MOCK_NON_CONST_METHOD_TPL(...) MOCK_REPLACED_MACRO_ERROR(MOCK_NON_CONST_METHOD_TPL, MOCK_NON_CONST_METHOD) +#define MOCK_STATIC_METHOD_TPL(...) MOCK_REPLACED_MACRO_ERROR(MOCK_STATIC_METHOD_TPL, MOCK_STATIC_METHOD) +#define MOCK_CONSTRUCTOR_TPL(...) MOCK_REPLACED_MACRO_ERROR(MOCK_CONSTRUCTOR_TPL, MOCK_CONSTRUCTOR) + +#endif // MOCK_MOCK_IMPL_HPP_INCLUDED diff --git a/include/turtle/detail/parameter.hpp b/include/turtle/detail/parameter.hpp deleted file mode 100644 index 34679b4..0000000 --- a/include/turtle/detail/parameter.hpp +++ /dev/null @@ -1,76 +0,0 @@ -// http://turtle.sourceforge.net -// -// Copyright Mathieu Champlon 2012 -// -// 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_PARAMETER_HPP_INCLUDED -#define MOCK_PARAMETER_HPP_INCLUDED - -#include "../config.hpp" - -namespace mock { namespace detail { - template - struct tuple; - - template - struct tuple_element; - - template - struct tuple_element> : tuple_element> - {}; - - template - struct tuple_element<0, tuple> - { - using type = H; - }; - - template - struct result_type; - - template - struct result_type - { - using type = R; - }; - - template - struct function_arity; - - template - struct function_arity - { - static constexpr size_t value = sizeof...(Args); - }; - - template - struct parameter_types; - - template - struct parameter_types - { - using type = tuple; - }; - - template - struct parameter - { - static_assert(n < function_arity::value, "Function signature has not that many parameters"); - using type = typename tuple_element::type>::type; - }; - - template - struct parameter_type; - template - struct parameter_type - { - using type = U; - }; - template - using parameter_type_t = typename parameter_type::type; -}} // namespace mock::detail - -#endif // MOCK_PARAMETER_HPP_INCLUDED diff --git a/include/turtle/detail/signature.hpp b/include/turtle/detail/signature.hpp index f76c7b0..cb4b3eb 100644 --- a/include/turtle/detail/signature.hpp +++ b/include/turtle/detail/signature.hpp @@ -54,21 +54,24 @@ namespace mock { namespace detail { struct signature : signature::type> {}; + /// Return the (non-member) function signature out of (any) signature + template + using signature_t = typename signature::type; + + /// CRTP class to define the base_type typedef template struct base { - typedef T base_type; + using base_type = T; }; - // if an error is generated by the line below it means - // the method is ambiguous : specify its signature to - // disambiguate + // If an error is generated by the line below it means the method is ambiguous. + // Specify its signature to disambiguate template - T& ambiguous_method_requires_to_specify_signature(const T&); + T ambiguous_method_requires_to_specify_signature(const T&); }} // namespace mock::detail -#define MOCK_SIGNATURE(M) \ - mock::detail::signature>>::type +#define MOCK_SIGNATURE(M) \ + mock::detail::signature_t #endif // MOCK_SIGNATURE_HPP_INCLUDED diff --git a/include/turtle/detail/signature_traits.hpp b/include/turtle/detail/signature_traits.hpp new file mode 100644 index 0000000..e6948f6 --- /dev/null +++ b/include/turtle/detail/signature_traits.hpp @@ -0,0 +1,62 @@ +// http://turtle.sourceforge.net +// +// Copyright Mathieu Champlon 2012 +// +// 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_PARAMETER_HPP_INCLUDED +#define MOCK_PARAMETER_HPP_INCLUDED + +#include "../config.hpp" +#include + +namespace mock { namespace detail { + /// Helper class to store a tuple/list of types + template + struct tuple; + + /// Get the type at the given index in the tuple + template + struct tuple_element; + + template + struct tuple_element> : tuple_element> + {}; + + template + struct tuple_element<0, tuple> + { + using type = H; + }; + + /// Provides information about a given function signature + /// Member types: return_type, args + /// Member constant: arity + template + struct signature_traits; + + template + struct signature_traits + { + using return_type = R; + static constexpr std::size_t arity = sizeof...(Args); + using args = tuple; + }; + + /// Return the result type of the function signature + template + using result_type_t = typename signature_traits::return_type; + + /// Return the arity of the function signature + template + using function_arity_t = std::integral_constant::arity>; + + /// Return the type at the given index of the function signature + template + using parameter_t = typename tuple_element::args>::type; + +}} // namespace mock::detail + +#endif // MOCK_PARAMETER_HPP_INCLUDED diff --git a/include/turtle/mock.hpp b/include/turtle/mock.hpp index 4d25f8d..9e78a4f 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 - -/// 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__> +#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(T, ...) struct T : __VA_ARGS__, mock::object, mock::detail::base<__VA_ARGS__> +#define MOCK_BASE_CLASS(name, ...) struct name : __VA_ARGS__, mock::object, mock::detail::base<__VA_ARGS__> + +/// MOCK_PROTECT_SIGNATURE( signature ) +/// Use this with MOCK_FUNCTION/MOCK_*_METHOD if the return type contains commas +#define MOCK_PROTECT_SIGNATURE(...) mock::detail::unwrap_signature_t /// 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<__VA_ARGS__> 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,32 @@ 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__) #endif // MOCK_MOCK_HPP_INCLUDED diff --git a/test/detail/test_signature.cpp b/test/detail/test_signature.cpp index ad8228d..fd4e3ef 100644 --- a/test/detail/test_signature.cpp +++ b/test/detail/test_signature.cpp @@ -6,21 +6,87 @@ // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) -#include +#include #include +#include #include namespace { struct base { void method_1(); - float method_2(int) const; + float method_2(int); + // Using templates in result and argument types + std::map method_3(std::map, short); + + // Qualified methods + float qual_1(int) &; + float qual_2(int) &&; + float qual_3(int) const; + float qual_4(int) const&; + float qual_5(int) const&&; + float qual_6(int) volatile; + float qual_7(int) volatile&; + float qual_8(int) volatile&&; + float qual_9(int) const volatile; + float qual_10(int) const volatile&; + float qual_11(int) const volatile&&; }; -typedef base base_type; } // namespace -BOOST_AUTO_TEST_CASE(mock_signature_generates_signature) +BOOST_AUTO_TEST_CASE(signature_traits_return_correct_values) { + using function1 = void(); + static_assert(std::is_same, void>::value, "!"); + static_assert(mock::detail::function_arity_t::value == 0, "!"); + + using function2 = float(int); + static_assert(std::is_same, float>::value, "!"); + static_assert(mock::detail::function_arity_t::value == 1, "!"); + static_assert(std::is_same, int>::value, "!"); + + using function3 = unsigned(short&, int, const char*, float, double, char, unsigned char, std::map); + static_assert(std::is_same, unsigned>::value, "!"); + static_assert(mock::detail::function_arity_t::value == 8, "!"); + static_assert(std::is_same, short&>::value, "!"); + static_assert(std::is_same, int>::value, "!"); + static_assert(std::is_same, const char*>::value, "!"); + static_assert(std::is_same, float>::value, "!"); + static_assert(std::is_same, double>::value, "!"); + static_assert(std::is_same, char>::value, "!"); + static_assert(std::is_same, unsigned char>::value, "!"); + static_assert(std::is_same, std::map>::value, "!"); +} + +BOOST_AUTO_TEST_CASE(MOCK_SIGNATURE_generates_signature) +{ + using base_type = base; // MOCK_SIGNATURE requires a visible base_type typedef in the current scope static_assert(std::is_same::value, "!"); static_assert(std::is_same::value, "!"); + static_assert(std::is_same(std::map, short), MOCK_SIGNATURE(method_3)>::value, "!"); + static_assert(std::is_same::value, "!"); + static_assert(std::is_same::value, "!"); + static_assert(std::is_same::value, "!"); + static_assert(std::is_same::value, "!"); + static_assert(std::is_same::value, "!"); + static_assert(std::is_same::value, "!"); + static_assert(std::is_same::value, "!"); + static_assert(std::is_same::value, "!"); + static_assert(std::is_same::value, "!"); + static_assert(std::is_same::value, "!"); + static_assert(std::is_same::value, "!"); +} + +BOOST_AUTO_TEST_CASE(MOCK_PROTECT_SIGNATURE_keeps_signature) +{ + // MOCK_PROTECT_SIGNATURE is basically a no-op regarding its argument + // and only required to get it through a VAR_ARGS macro + // clang-format off + static_assert(std::is_same::value, "!"); + static_assert(std::is_same::value, "!"); + static_assert(std::is_same(std::map, short), MOCK_PROTECT_SIGNATURE( + std::map(std::map, short))>::value, "!"); + // clang-format on } diff --git a/test/fail_constraint_functor_not_compatible.cpp b/test/fail_constraint_functor_not_compatible.cpp index 0fc5d83..d5534f8 100644 --- a/test/fail_constraint_functor_not_compatible.cpp +++ b/test/fail_constraint_functor_not_compatible.cpp @@ -10,7 +10,7 @@ MOCK_CLASS(my_class) { - MOCK_METHOD_EXT(my_method, 1, void(int), my_method) + MOCK_METHOD(my_method, 1, void(int), my_method) }; bool constraint(int, int) { diff --git a/test/fail_constraint_value_not_comparable.cpp b/test/fail_constraint_value_not_comparable.cpp index ee8b81d..1e97da6 100644 --- a/test/fail_constraint_value_not_comparable.cpp +++ b/test/fail_constraint_value_not_comparable.cpp @@ -10,7 +10,7 @@ MOCK_CLASS(my_class) { - MOCK_METHOD_EXT(my_method, 1, void(int), my_method) + MOCK_METHOD(my_method, 1, void(int), my_method) }; void test_case() { diff --git a/test/fail_constraint_value_of_wrong_type_in_builtin_constraint.cpp b/test/fail_constraint_value_of_wrong_type_in_builtin_constraint.cpp index 4deaea0..67c97ab 100644 --- a/test/fail_constraint_value_of_wrong_type_in_builtin_constraint.cpp +++ b/test/fail_constraint_value_of_wrong_type_in_builtin_constraint.cpp @@ -10,7 +10,7 @@ MOCK_CLASS(my_class) { - MOCK_METHOD_EXT(my_method, 1, void(int), my_method) + MOCK_METHOD(my_method, 1, void(int), my_method) }; void test_case() { diff --git a/test/fail_mismatch_type_in_returns_int_action.cpp b/test/fail_mismatch_type_in_returns_int_action.cpp index 8b5df96..79386f3 100644 --- a/test/fail_mismatch_type_in_returns_int_action.cpp +++ b/test/fail_mismatch_type_in_returns_int_action.cpp @@ -10,7 +10,7 @@ MOCK_CLASS(my_class) { - MOCK_METHOD_EXT(my_method, 0, int(), my_method) + MOCK_METHOD(my_method, 0, int(), my_method) }; void test_case() { diff --git a/test/fail_mismatch_type_in_returns_string_action.cpp b/test/fail_mismatch_type_in_returns_string_action.cpp index dadcc33..b3cea88 100644 --- a/test/fail_mismatch_type_in_returns_string_action.cpp +++ b/test/fail_mismatch_type_in_returns_string_action.cpp @@ -10,7 +10,7 @@ MOCK_CLASS(my_class) { - MOCK_METHOD_EXT(my_method, 0, std::string(), my_method) + MOCK_METHOD(my_method, 0, std::string(), my_method) }; void test_case() { diff --git a/test/fail_mismatch_type_in_returns_void_action.cpp b/test/fail_mismatch_type_in_returns_void_action.cpp index ea7afd3..7a09043 100644 --- a/test/fail_mismatch_type_in_returns_void_action.cpp +++ b/test/fail_mismatch_type_in_returns_void_action.cpp @@ -10,7 +10,7 @@ MOCK_CLASS(my_class) { - MOCK_METHOD_EXT(my_method, 0, void(), my_method) + MOCK_METHOD(my_method, 0, void(), my_method) }; void test_case() { diff --git a/test/fail_wrong_number_of_arguments_in_with.cpp b/test/fail_wrong_number_of_arguments_in_with.cpp index d653265..f527e68 100644 --- a/test/fail_wrong_number_of_arguments_in_with.cpp +++ b/test/fail_wrong_number_of_arguments_in_with.cpp @@ -10,7 +10,7 @@ MOCK_CLASS(my_class) { - MOCK_METHOD_EXT(my_method, 1, void(int), my_method) + MOCK_METHOD(my_method, 1, void(int), my_method) }; void test_case() { diff --git a/test/mock_error.hpp b/test/mock_error.hpp index 5ac02f6..3f4224d 100644 --- a/test/mock_error.hpp +++ b/test/mock_error.hpp @@ -15,6 +15,7 @@ #include #include +/// Container to hold data about mocked function calls (and expectation errors) struct mock_error_data_t : mock::detail::singleton { void reset() @@ -41,16 +42,15 @@ struct mock_error_data_t : mock::detail::singleton ++error_count; } - int error_count; - int call_count; - std::string last_message; - std::string last_context; - std::string last_file; - int last_line; + int call_count = 0; + int error_count = 0; + std::string last_message, last_context, last_file; + int last_line = 0; MOCK_SINGLETON_CONS(mock_error_data_t); }; MOCK_SINGLETON_INST(mock_error_data) +/// Error handler that populates the mock_error_data singleton instead of failing template struct mock_error { @@ -73,6 +73,8 @@ struct mock_error } }; +/// Fixture to use CHECK_CALLS & CHECK_ERROR: Initializes the mock_error_data singleton +/// Verifies there are no pending verifications on end of the test struct mock_error_fixture { mock_error_fixture() { mock_error_data.reset(); } @@ -83,9 +85,15 @@ struct mock_error_fixture } }; +/// Check that the number of calls to mocked function equals the given amount +/// and resets them (for the next check and cleanup) #define CHECK_CALLS(calls) \ BOOST_CHECK_EQUAL(calls, mock_error_data.call_count); \ mock_error_data.call_count = 0; +/// Similar to BOOST_CHECK_THROW: +/// Checks that running `expr` leads to an error of the set expectations, +/// that the error message equals `error`, with the given `context` +/// and `calls` mocked functions were called. #define CHECK_ERROR(expr, error, calls, context) \ BOOST_CHECK(mock_error_data.verify()); \ try \ diff --git a/test/test_integration.cpp b/test/test_integration.cpp index aceccd5..2442b8f 100644 --- a/test/test_integration.cpp +++ b/test/test_integration.cpp @@ -17,7 +17,7 @@ namespace { struct my_custom_mock { - MOCK_METHOD_EXT(my_method, 0, void(), my_tag) + MOCK_METHOD(my_method, 0, void(), my_tag) }; } // namespace @@ -32,7 +32,7 @@ BOOST_FIXTURE_TEST_CASE(custom_mock_object_without_macros_and_without_inheriting namespace { struct my_custom_mock_object { - MOCK_METHOD_EXT(my_method, 0, void(), my_tag) + MOCK_METHOD(my_method, 0, void(), my_tag) }; } // namespace @@ -47,7 +47,7 @@ BOOST_FIXTURE_TEST_CASE(custom_mock_object_without_macros, mock_error_fixture) namespace { MOCK_CLASS(my_mock) { - MOCK_METHOD_EXT(my_method, 1, int(int), my_tag) + MOCK_METHOD(my_method, 1, int(int), my_tag) }; } // namespace @@ -89,8 +89,8 @@ public: MOCK_BASE_CLASS(my_ambiguited_mock, my_ambiguited_interface) { - MOCK_METHOD_EXT(my_method, 0, void(), my_tag1) - MOCK_METHOD_EXT(my_method, 1, void(int), my_tag_2) + MOCK_METHOD(my_method, 0, void(), my_tag1) + MOCK_METHOD(my_method, 1, void(int), my_tag_2) }; } // namespace @@ -116,8 +116,8 @@ public: MOCK_BASE_CLASS(my_const_ambiguited_mock, my_const_ambiguited_interface) { - MOCK_NON_CONST_METHOD_EXT(my_method, 0, void(), tag1) - MOCK_CONST_METHOD_EXT(my_method, 0, void(), tag_2) + MOCK_NON_CONST_METHOD(my_method, 0, void(), tag1) + MOCK_CONST_METHOD(my_method, 0, void(), tag_2) }; } // namespace @@ -133,7 +133,7 @@ BOOST_FIXTURE_TEST_CASE(mock_object_method_const_disambiguation, mock_error_fixt namespace { MOCK_CLASS(my_undefined_mock) { - MOCK_METHOD_EXT(m, 1, void(undefined&), t) + MOCK_METHOD(m, 1, void(undefined&), t) }; } // namespace @@ -186,9 +186,9 @@ namespace { 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(my_method, 0, void(), my_tag) + MOCK_METHOD(my_method, 2, void(T, std::string), my_tpl_tag) + MOCK_METHOD(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(my_method, 1, void(T), my_method) + MOCK_METHOD(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 @@ -366,7 +366,7 @@ BOOST_FIXTURE_TEST_CASE(failed_sequence_in_mocked_destructor_does_not_throw, moc namespace { MOCK_CLASS(boost_optional) { - MOCK_METHOD_EXT(method, 0, boost::optional(), tag) + MOCK_METHOD(method, 0, boost::optional(), tag) }; } // namespace @@ -451,7 +451,7 @@ void nothing(T) struct member_pointer_mock_class { - MOCK_CONST_METHOD_EXT(my_method, 0, void(), my_method) + MOCK_CONST_METHOD(my_method, 0, void(), my_method) }; } // 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 @@ -532,7 +532,7 @@ BOOST_FIXTURE_TEST_CASE(a_static_method_in_a_template_class_can_be_mocked, mock_ namespace { MOCK_CLASS(mock_class) { - MOCK_METHOD_EXT(m, 0, void(), t); + MOCK_METHOD(m, 0, void(), t); }; } // namespace @@ -550,7 +550,7 @@ BOOST_FIXTURE_TEST_CASE(resetting_referenced_mock_class_does_not_crash, mock_err namespace { MOCK_CLASS(mock_class2) { - MOCK_METHOD_EXT(m, 0, mock_class2(), t); + MOCK_METHOD(m, 0, mock_class2(), t); }; } // namespace @@ -646,8 +646,8 @@ BOOST_FIXTURE_TEST_CASE(mock_class_is_thread_safe, mock_error_fixture) namespace { MOCK_CLASS(my_multi_mock) { - MOCK_METHOD_EXT(m1, 1, void(int), m1); - MOCK_METHOD_EXT(m2, 2, void(int, int), m2); + MOCK_METHOD(m1, 1, void(int), m1); + MOCK_METHOD(m2, 2, void(int, int), m2); }; } // namespace @@ -742,6 +742,6 @@ BOOST_FIXTURE_TEST_CASE(std_unique_ptr_argument_is_supported_in_retrieve_constra struct my_unique_ptr_class { MOCK_CONSTRUCTOR(my_unique_ptr_class, 1, (std::unique_ptr), constructor) - MOCK_METHOD_EXT(m, 1, void(std::unique_ptr), m) + MOCK_METHOD(m, 1, void(std::unique_ptr), m) MOCK_STATIC_METHOD(ms, 1, void(std::unique_ptr), ms) }; diff --git a/test/test_max_args.cpp b/test/test_max_args.cpp index 14ac35e..147089c 100644 --- a/test/test_max_args.cpp +++ b/test/test_max_args.cpp @@ -16,8 +16,8 @@ namespace { struct my_custom_mock { - MOCK_METHOD_EXT(method, MOCK_MAX_ARGS, void(BOOST_PP_ENUM(MOCK_MAX_ARGS, IDENTITY, int)), tag) - MOCK_METHOD_EXT(method2, MOCK_MAX_ARGS, int(BOOST_PP_ENUM(MOCK_MAX_ARGS, IDENTITY, int)), tag_2) + MOCK_METHOD(method, MOCK_MAX_ARGS, void(BOOST_PP_ENUM(MOCK_MAX_ARGS, IDENTITY, int)), tag) + MOCK_METHOD(method2, MOCK_MAX_ARGS, int(BOOST_PP_ENUM(MOCK_MAX_ARGS, IDENTITY, int)), tag_2) }; } // namespace diff --git a/test/test_mock.cpp b/test/test_mock.cpp index edcea98..a61c305 100644 --- a/test/test_mock.cpp +++ b/test/test_mock.cpp @@ -19,7 +19,7 @@ void my_function(T& t) } MOCK_CLASS(mock_class) { - MOCK_METHOD_EXT(my_method, 1, void(const std::string&), my_tag) + MOCK_METHOD(my_method, 1, void(const std::string&), my_tag) }; } // namespace @@ -34,7 +34,7 @@ BOOST_FIXTURE_TEST_CASE(mock_object_for_static_polymorphism, mock_error_fixture) namespace { MOCK_CLASS(mock_class_with_operator) { - MOCK_CONST_METHOD_EXT(operator+=, 1, mock_class_with_operator &(int), addition) + MOCK_CONST_METHOD(operator+=, 1, mock_class_with_operator &(int), addition) }; } // namespace @@ -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 @@ -142,12 +144,12 @@ BOOST_FIXTURE_TEST_CASE(mock_template_non_const_conversion_operator, mock_error_ namespace { MOCK_CLASS(my_mock) { - MOCK_CONST_METHOD_EXT(my_method, 1, void(int), my_method) - MOCK_CONST_METHOD_EXT(my_method_2, 1, void(int), my_method_2) + MOCK_CONST_METHOD(my_method, 1, void(int), my_method) + MOCK_CONST_METHOD(my_method_2, 1, void(int), my_method_2) }; } // namespace -BOOST_FIXTURE_TEST_CASE(MOCK_CONST_METHOD_EXT_macro_defines_a_bindable_method, mock_error_fixture) +BOOST_FIXTURE_TEST_CASE(MOCK_CONST_METHOD_macro_defines_a_bindable_method, mock_error_fixture) { my_mock m; const auto f = std::bind(&my_mock::my_method, &m, 42); @@ -216,8 +218,8 @@ BOOST_FIXTURE_TEST_CASE(mock_object_const_shared_pointer_is_named, mock_error_fi namespace { struct my_custom_mock { - MOCK_METHOD_EXT(my_method, 0, void(), my_tag) - MOCK_METHOD_EXT(my_method_2, 0, void(), my_tag_2) + MOCK_METHOD(my_method, 0, void(), my_tag) + MOCK_METHOD(my_method_2, 0, void(), my_tag_2) }; } // namespace @@ -236,8 +238,8 @@ BOOST_FIXTURE_TEST_CASE(custom_mock_object_without_macros_and_without_inheriting namespace { struct my_custom_mock_object : mock::object { - MOCK_METHOD_EXT(my_method, 0, void(), my_tag) - MOCK_METHOD_EXT(my_method_2, 0, void(), my_tag_2) + MOCK_METHOD(my_method, 0, void(), my_tag) + MOCK_METHOD(my_method_2, 0, void(), my_tag_2) }; } // namespace @@ -310,11 +312,11 @@ BOOST_FIXTURE_TEST_CASE(mock_static_function_is_named, mock_error_fixture) namespace { MOCK_CLASS(round_parenthesized_signature) { - MOCK_METHOD_EXT(m0, 0, MOCK_PROTECT_FUNCTION_SIG(std::map()), m0) - MOCK_STATIC_METHOD(m1, 0, MOCK_PROTECT_FUNCTION_SIG(std::map()), m1) - MOCK_FUNCTOR(f0, MOCK_PROTECT_FUNCTION_SIG(std::map())); + MOCK_METHOD(m0, 0, MOCK_PROTECT_SIGNATURE(std::map()), m0) + MOCK_STATIC_METHOD(m1, 0, MOCK_PROTECT_SIGNATURE(std::map()), m1) + MOCK_FUNCTOR(f0, MOCK_PROTECT_SIGNATURE(std::map())); }; -MOCK_FUNCTION(fun0, 0, MOCK_PROTECT_FUNCTION_SIG(std::map()), fun0) +MOCK_FUNCTION(fun0, 0, MOCK_PROTECT_SIGNATURE(std::map()), fun0) } // namespace 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) @@ -361,7 +363,7 @@ MOCK_BASE_CLASS(comma_base, std::map) MOCK_FUNCTION(fun1, 0, void()) MOCK_FUNCTION(fun2, 0, void(), fun2) -MOCK_FUNCTION(fun3, 0, MOCK_PROTECT_FUNCTION_SIG(std::map())) +MOCK_FUNCTION(fun3, 0, MOCK_PROTECT_SIGNATURE(std::map())) MOCK_FUNCTOR(f_variadic, std::map()); } // namespace @@ -385,8 +387,8 @@ MOCK_BASE_CLASS(derived, base) MOCK_CONSTRUCTOR(MOCK_STDCALL derived, 0, (), derived) MOCK_DESTRUCTOR(MOCK_STDCALL ~derived, derived) MOCK_CONVERSION_OPERATOR(MOCK_STDCALL operator, int, to_int) - MOCK_METHOD_EXT(MOCK_STDCALL m1, 0, void(), m1) - MOCK_METHOD_EXT(MOCK_STDCALL m2, 0, void(), m2) + MOCK_METHOD(MOCK_STDCALL m1, 0, void(), m1) + MOCK_METHOD(MOCK_STDCALL m2, 0, void(), m2) MOCK_METHOD(MOCK_STDCALL m3, 0, void(), m3) MOCK_STATIC_METHOD(MOCK_STDCALL m4, 0, void(), m4) };