mirror of
https://github.com/mat007/turtle.git
synced 2026-06-22 12:13:43 +00:00
Merge 21567894a5 into 2a9438ea7e
This commit is contained in:
commit
6e28c5e137
6 changed files with 169 additions and 46 deletions
|
|
@ -12,11 +12,13 @@
|
|||
|
||||
#include "function.hpp"
|
||||
#include "functor.hpp"
|
||||
#include "pp_foreach.hpp"
|
||||
#include "signature.hpp"
|
||||
#include "signature_traits.hpp"
|
||||
#include "type_name.hpp"
|
||||
#include <boost/preprocessor/repetition/enum.hpp>
|
||||
#include <boost/preprocessor/stringize.hpp>
|
||||
#include <boost/preprocessor/tuple/elem.hpp>
|
||||
#include <type_traits>
|
||||
|
||||
namespace mock { namespace detail {
|
||||
|
|
@ -65,15 +67,17 @@ namespace mock { namespace detail {
|
|||
return MOCK_ANONYMOUS_HELPER(identifier)(MOCK_FORWARD_PARAMS(arity, signature)); \
|
||||
}
|
||||
|
||||
#define MOCK_METHOD_EXT(name, arity, signature, identifier) \
|
||||
MOCK_METHOD_AUX(name, arity, signature, identifier, ) \
|
||||
MOCK_METHOD_AUX(name, arity, signature, identifier, const) \
|
||||
MOCK_METHOD_HELPER(signature, identifier)
|
||||
#define MOCK_CONST_METHOD_EXT(name, arity, signature, identifier) \
|
||||
MOCK_METHOD_AUX(name, arity, signature, identifier, const) \
|
||||
MOCK_METHOD_HELPER(signature, identifier)
|
||||
#define MOCK_NON_CONST_METHOD_EXT(name, arity, signature, identifier) \
|
||||
MOCK_METHOD_AUX(name, arity, signature, identifier, ) \
|
||||
/// MOCK_METHOD_ITER((name, arity, signature, identifier), qualifier)
|
||||
#define MOCK_METHOD_ITER(M_n_S_t, qualifier) \
|
||||
MOCK_METHOD_AUX(BOOST_PP_TUPLE_ELEM(0, M_n_S_t), \
|
||||
BOOST_PP_TUPLE_ELEM(1, M_n_S_t), \
|
||||
BOOST_PP_TUPLE_ELEM(2, M_n_S_t), \
|
||||
BOOST_PP_TUPLE_ELEM(3, M_n_S_t), \
|
||||
qualifier)
|
||||
|
||||
#define MOCK_METHOD_EXT_I(name, arity, signature, identifier, qualifiers) \
|
||||
static_assert(arity == mock::detail::function_arity_t<signature>::value, "Arity mismatch"); \
|
||||
MOCK_PP_TUPLE_FOR_EACH(MOCK_METHOD_ITER, (name, arity, signature, identifier), qualifiers) \
|
||||
MOCK_METHOD_HELPER(signature, identifier)
|
||||
|
||||
#define MOCK_FUNCTION_HELPER(signature, identifier, prefix) \
|
||||
|
|
|
|||
66
include/turtle/detail/pp_foreach.hpp
Normal file
66
include/turtle/detail/pp_foreach.hpp
Normal file
|
|
@ -0,0 +1,66 @@
|
|||
// http://turtle.sourceforge.net
|
||||
//
|
||||
// Copyright 2025 Alexander Grund
|
||||
//
|
||||
// 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_PP_FOREACH_HPP_INCLUDED
|
||||
#define MOCK_PP_FOREACH_HPP_INCLUDED
|
||||
|
||||
#include <boost/preprocessor/cat.hpp>
|
||||
#include <boost/preprocessor/empty.hpp>
|
||||
#include <boost/preprocessor/facilities/overload.hpp>
|
||||
#include <boost/preprocessor/tuple/rem.hpp>
|
||||
|
||||
/// Expand to `macro(data, elem)` for each element in the tuple.
|
||||
/// Same as BOOST_PP_TUPLE_FOR_EACH but supports empty elements,
|
||||
/// without causing a C4003 "not enough arguments for function-like macro invocation" warning on MSVC
|
||||
#define MOCK_PP_TUPLE_FOR_EACH(macro, data, tuple) MOCK_PP_FOR_EACH(macro, data, BOOST_PP_REM tuple)
|
||||
|
||||
/// Expand to `macro(data, elem)` for each variadic element passed
|
||||
#if BOOST_PP_VARIADICS_MSVC
|
||||
# define MOCK_PP_FOR_EACH(macro, data, ...) \
|
||||
BOOST_PP_CAT(BOOST_PP_OVERLOAD(MOCK_PP_INVOKE_, __VA_ARGS__)(macro, data, __VA_ARGS__), BOOST_PP_EMPTY())
|
||||
#else
|
||||
# define MOCK_PP_FOR_EACH(macro, data, ...) BOOST_PP_OVERLOAD(MOCK_PP_INVOKE_, __VA_ARGS__)(macro, data, __VA_ARGS__)
|
||||
#endif
|
||||
|
||||
// When the compiler supports detection of empty variadic element (e.g. Clang & GCC) Boost.PP returns a size of zero.
|
||||
// However an empty variadic is a valid case: A single invocation with an empty element.
|
||||
#define MOCK_PP_INVOKE_0(macro, data, x) macro(data, x)
|
||||
#define MOCK_PP_INVOKE_1(macro, data, x) macro(data, x)
|
||||
#define MOCK_PP_INVOKE_2(macro, data, x, ...) macro(data, x) MOCK_PP_INVOKE_1(macro, data, __VA_ARGS__)
|
||||
#define MOCK_PP_INVOKE_3(macro, data, x, ...) macro(data, x) MOCK_PP_INVOKE_2(macro, data, __VA_ARGS__)
|
||||
#define MOCK_PP_INVOKE_4(macro, data, x, ...) macro(data, x) MOCK_PP_INVOKE_3(macro, data, __VA_ARGS__)
|
||||
#define MOCK_PP_INVOKE_5(macro, data, x, ...) macro(data, x) MOCK_PP_INVOKE_4(macro, data, __VA_ARGS__)
|
||||
#define MOCK_PP_INVOKE_6(macro, data, x, ...) macro(data, x) MOCK_PP_INVOKE_5(macro, data, __VA_ARGS__)
|
||||
#define MOCK_PP_INVOKE_7(macro, data, x, ...) macro(data, x) MOCK_PP_INVOKE_6(macro, data, __VA_ARGS__)
|
||||
#define MOCK_PP_INVOKE_8(macro, data, x, ...) macro(data, x) MOCK_PP_INVOKE_7(macro, data, __VA_ARGS__)
|
||||
#define MOCK_PP_INVOKE_9(macro, data, x, ...) macro(data, x) MOCK_PP_INVOKE_8(macro, data, __VA_ARGS__)
|
||||
#define MOCK_PP_INVOKE_10(macro, data, x, ...) macro(data, x) MOCK_PP_INVOKE_9(macro, data, __VA_ARGS__)
|
||||
#define MOCK_PP_INVOKE_11(macro, data, x, ...) macro(data, x) MOCK_PP_INVOKE_10(macro, data, __VA_ARGS__)
|
||||
#define MOCK_PP_INVOKE_12(macro, data, x, ...) macro(data, x) MOCK_PP_INVOKE_11(macro, data, __VA_ARGS__)
|
||||
#define MOCK_PP_INVOKE_13(macro, data, x, ...) macro(data, x) MOCK_PP_INVOKE_12(macro, data, __VA_ARGS__)
|
||||
#define MOCK_PP_INVOKE_14(macro, data, x, ...) macro(data, x) MOCK_PP_INVOKE_13(macro, data, __VA_ARGS__)
|
||||
#define MOCK_PP_INVOKE_15(macro, data, x, ...) macro(data, x) MOCK_PP_INVOKE_14(macro, data, __VA_ARGS__)
|
||||
#define MOCK_PP_INVOKE_16(macro, data, x, ...) macro(data, x) MOCK_PP_INVOKE_15(macro, data, __VA_ARGS__)
|
||||
#define MOCK_PP_INVOKE_17(macro, data, x, ...) macro(data, x) MOCK_PP_INVOKE_16(macro, data, __VA_ARGS__)
|
||||
#define MOCK_PP_INVOKE_18(macro, data, x, ...) macro(data, x) MOCK_PP_INVOKE_17(macro, data, __VA_ARGS__)
|
||||
#define MOCK_PP_INVOKE_19(macro, data, x, ...) macro(data, x) MOCK_PP_INVOKE_18(macro, data, __VA_ARGS__)
|
||||
#define MOCK_PP_INVOKE_20(macro, data, x, ...) macro(data, x) MOCK_PP_INVOKE_19(macro, data, __VA_ARGS__)
|
||||
#define MOCK_PP_INVOKE_21(macro, data, x, ...) macro(data, x) MOCK_PP_INVOKE_20(macro, data, __VA_ARGS__)
|
||||
#define MOCK_PP_INVOKE_22(macro, data, x, ...) macro(data, x) MOCK_PP_INVOKE_21(macro, data, __VA_ARGS__)
|
||||
#define MOCK_PP_INVOKE_23(macro, data, x, ...) macro(data, x) MOCK_PP_INVOKE_22(macro, data, __VA_ARGS__)
|
||||
#define MOCK_PP_INVOKE_24(macro, data, x, ...) macro(data, x) MOCK_PP_INVOKE_23(macro, data, __VA_ARGS__)
|
||||
#define MOCK_PP_INVOKE_25(macro, data, x, ...) macro(data, x) MOCK_PP_INVOKE_24(macro, data, __VA_ARGS__)
|
||||
#define MOCK_PP_INVOKE_26(macro, data, x, ...) macro(data, x) MOCK_PP_INVOKE_25(macro, data, __VA_ARGS__)
|
||||
#define MOCK_PP_INVOKE_27(macro, data, x, ...) macro(data, x) MOCK_PP_INVOKE_26(macro, data, __VA_ARGS__)
|
||||
#define MOCK_PP_INVOKE_28(macro, data, x, ...) macro(data, x) MOCK_PP_INVOKE_27(macro, data, __VA_ARGS__)
|
||||
#define MOCK_PP_INVOKE_29(macro, data, x, ...) macro(data, x) MOCK_PP_INVOKE_28(macro, data, __VA_ARGS__)
|
||||
#define MOCK_PP_INVOKE_30(macro, data, x, ...) macro(data, x) MOCK_PP_INVOKE_29(macro, data, __VA_ARGS__)
|
||||
#define MOCK_PP_INVOKE_31(macro, data, x, ...) macro(data, x) MOCK_PP_INVOKE_30(macro, data, __VA_ARGS__)
|
||||
#define MOCK_PP_INVOKE_32(macro, data, x, ...) macro(data, x) MOCK_PP_INVOKE_31(macro, data, __VA_ARGS__)
|
||||
|
||||
#endif // MOCK_PP_FOREACH_HPP_INCLUDED
|
||||
|
|
@ -1,6 +1,7 @@
|
|||
// http://turtle.sourceforge.net
|
||||
//
|
||||
// Copyright Mathieu Champlon 2012
|
||||
// Copyright 2020-2025 Alexander Grund
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// (See accompanying file LICENSE_1_0.txt or copy at
|
||||
|
|
@ -10,36 +11,44 @@
|
|||
#define MOCK_SIGNATURE_HPP_INCLUDED
|
||||
|
||||
#include "../config.hpp"
|
||||
#include <boost/preprocessor/empty.hpp>
|
||||
#include <type_traits>
|
||||
|
||||
namespace mock { namespace detail {
|
||||
#define MOCK_NOARG
|
||||
#define MOCK_STRIP_FUNCTION_QUALIFIERS(cv, ref) \
|
||||
template<typename R, typename... Args> \
|
||||
struct strip_function_qualifiers<R(Args...) cv ref> \
|
||||
{ \
|
||||
using type = R(Args...); \
|
||||
}; \
|
||||
template<typename R, typename... Args> \
|
||||
struct strip_function_qualifiers<R(Args..., ...) cv ref> \
|
||||
{ \
|
||||
using type = R(Args..., ...); \
|
||||
#define MOCK_STRIP_FUNCTION_QUALIFIERS(ne, cv, ref) \
|
||||
template<typename R, typename... Args> \
|
||||
struct strip_function_qualifiers<R(Args...) cv ref ne> \
|
||||
{ \
|
||||
using type = R(Args...); \
|
||||
}; \
|
||||
template<typename R, typename... Args> \
|
||||
struct strip_function_qualifiers<R(Args..., ...) cv ref ne> \
|
||||
{ \
|
||||
using type = R(Args..., ...); \
|
||||
};
|
||||
|
||||
#define MOCK_STRIP_FUNCTION_QUALIFIERS_REF(cv) \
|
||||
MOCK_STRIP_FUNCTION_QUALIFIERS(cv, ) \
|
||||
MOCK_STRIP_FUNCTION_QUALIFIERS(cv, &) \
|
||||
MOCK_STRIP_FUNCTION_QUALIFIERS(cv, &&)
|
||||
#define MOCK_STRIP_FUNCTION_QUALIFIERS_REF(ne, cv) \
|
||||
MOCK_STRIP_FUNCTION_QUALIFIERS(ne, cv, ) \
|
||||
MOCK_STRIP_FUNCTION_QUALIFIERS(ne, cv, &) \
|
||||
MOCK_STRIP_FUNCTION_QUALIFIERS(ne, cv, &&)
|
||||
#define MOCK_STRIP_FUNCTION_QUALIFIERS_CV_REF(except_spec) \
|
||||
MOCK_STRIP_FUNCTION_QUALIFIERS_REF(except_spec, BOOST_PP_EMPTY()) \
|
||||
MOCK_STRIP_FUNCTION_QUALIFIERS_REF(except_spec, const) \
|
||||
MOCK_STRIP_FUNCTION_QUALIFIERS_REF(except_spec, volatile) \
|
||||
MOCK_STRIP_FUNCTION_QUALIFIERS_REF(except_spec, const volatile)
|
||||
|
||||
template<typename>
|
||||
struct strip_function_qualifiers;
|
||||
MOCK_STRIP_FUNCTION_QUALIFIERS_REF(MOCK_NOARG)
|
||||
MOCK_STRIP_FUNCTION_QUALIFIERS_REF(const)
|
||||
MOCK_STRIP_FUNCTION_QUALIFIERS_REF(volatile)
|
||||
MOCK_STRIP_FUNCTION_QUALIFIERS_REF(const volatile)
|
||||
#undef MOCK_NOARG
|
||||
MOCK_STRIP_FUNCTION_QUALIFIERS_CV_REF(BOOST_PP_EMPTY())
|
||||
|
||||
// C++17 includes noexcept in the function type
|
||||
#if MOCK_CXX_VERSION >= 201703L
|
||||
MOCK_STRIP_FUNCTION_QUALIFIERS_CV_REF(noexcept)
|
||||
#endif
|
||||
|
||||
#undef MOCK_STRIP_FUNCTION_QUALIFIERS
|
||||
#undef MOCK_STRIP_FUNCTION_QUALIFIERS_REF
|
||||
#undef MOCK_STRIP_FUNCTION_QUALIFIERS_CV_REF
|
||||
|
||||
template<typename M>
|
||||
struct signature;
|
||||
|
|
|
|||
|
|
@ -72,33 +72,45 @@
|
|||
} \
|
||||
MOCK_METHOD_HELPER(void(), identifier)
|
||||
|
||||
/// MOCK_METHOD( [calling convention] name, arity[, signature[, identifier]] )
|
||||
/// generates both const and non-const methods
|
||||
/// MOCK_METHOD( [calling convention] name, arity[, signature[, identifier, [, specifiers]]] )
|
||||
/// generates both const and non-const methods by default, but can be changed by passing a specifier tuple.
|
||||
/// 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, \
|
||||
BOOST_PP_VARIADIC_ELEM(0, __VA_ARGS__, ), \
|
||||
BOOST_PP_VARIADIC_ELEM(1, __VA_ARGS__, MOCK_SIGNATURE(M), ), \
|
||||
BOOST_PP_VARIADIC_ELEM(2, __VA_ARGS__, M, M, ))
|
||||
/// 'specifiers' is a potentially empty, tuple of method specifiers, e.g. (&, &&) or (const override)
|
||||
#define MOCK_METHOD(M, ...) \
|
||||
MOCK_METHOD_EXT_I(M, \
|
||||
BOOST_PP_VARIADIC_ELEM(0, __VA_ARGS__, ), \
|
||||
BOOST_PP_VARIADIC_ELEM(1, __VA_ARGS__, MOCK_SIGNATURE(M), ), \
|
||||
BOOST_PP_VARIADIC_ELEM(2, __VA_ARGS__, M, M, ), \
|
||||
BOOST_PP_VARIADIC_ELEM(3, __VA_ARGS__, (const, ), (const, ), (const, ), ))
|
||||
/// 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, \
|
||||
BOOST_PP_VARIADIC_ELEM(0, __VA_ARGS__, ), \
|
||||
BOOST_PP_VARIADIC_ELEM(1, __VA_ARGS__, MOCK_SIGNATURE(M), ), \
|
||||
BOOST_PP_VARIADIC_ELEM(2, __VA_ARGS__, M, M, ))
|
||||
#define MOCK_CONST_METHOD(M, ...) \
|
||||
MOCK_METHOD_EXT_I(M, \
|
||||
BOOST_PP_VARIADIC_ELEM(0, __VA_ARGS__, ), \
|
||||
BOOST_PP_VARIADIC_ELEM(1, __VA_ARGS__, MOCK_SIGNATURE(M), ), \
|
||||
BOOST_PP_VARIADIC_ELEM(2, __VA_ARGS__, M, M, ), \
|
||||
(const))
|
||||
/// 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, \
|
||||
BOOST_PP_VARIADIC_ELEM(0, __VA_ARGS__, ), \
|
||||
BOOST_PP_VARIADIC_ELEM(1, __VA_ARGS__, MOCK_SIGNATURE(M), ), \
|
||||
BOOST_PP_VARIADIC_ELEM(2, __VA_ARGS__, M, M, ))
|
||||
#define MOCK_NON_CONST_METHOD(M, ...) \
|
||||
MOCK_METHOD_EXT_I(M, \
|
||||
BOOST_PP_VARIADIC_ELEM(0, __VA_ARGS__, ), \
|
||||
BOOST_PP_VARIADIC_ELEM(1, __VA_ARGS__, MOCK_SIGNATURE(M), ), \
|
||||
BOOST_PP_VARIADIC_ELEM(2, __VA_ARGS__, M, M, ), \
|
||||
())
|
||||
|
||||
/// MOCK_METHOD_EXT( [calling convention] name, arity, qualifiers [, signature, [identifier]] )
|
||||
#define MOCK_METHOD_EXT(M, arity, ...) \
|
||||
MOCK_METHOD_EXT_I(M, \
|
||||
arity, \
|
||||
BOOST_PP_VARIADIC_ELEM(1, __VA_ARGS__, MOCK_SIGNATURE(M), ), \
|
||||
BOOST_PP_VARIADIC_ELEM(2, __VA_ARGS__, M, M, ), \
|
||||
BOOST_PP_VARIADIC_ELEM(0, __VA_ARGS__, ))
|
||||
|
||||
/// MOCK_FUNCTION( [calling convention] name, arity, signature[, identifier] )
|
||||
/// if 'identifier' is omitted it will default to 'name'
|
||||
|
|
|
|||
|
|
@ -20,6 +20,9 @@ if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU" OR CMAKE_CXX_COMPILER_ID MATCHES "Clang"
|
|||
if(TURTLE_CXX_UNUSED_FUNCTION)
|
||||
target_compile_options(TurtleTestMain INTERFACE -Wno-unused-function)
|
||||
endif()
|
||||
if(CMAKE_CXX_COMPILER_ID MATCHES "Clang")
|
||||
target_compile_options(TurtleTestMain INTERFACE -Wno-inconsistent-missing-override)
|
||||
endif()
|
||||
if(TURTLE_WERROR)
|
||||
check_cxx_compiler_flag(-Wdeprecated-declarations TURTLE_CXX_DEPRECATED_DECLARATIONS)
|
||||
if(TURTLE_CXX_DEPRECATED_DECLARATIONS)
|
||||
|
|
|
|||
|
|
@ -327,6 +327,15 @@ struct base
|
|||
virtual void m1() = 0;
|
||||
virtual void m10() const = 0;
|
||||
virtual void m11() = 0;
|
||||
virtual void m12() noexcept = 0;
|
||||
virtual void m13() && = 0;
|
||||
virtual void m14() = 0;
|
||||
virtual void m14(int, float) = 0;
|
||||
virtual void m14(int, int) = 0;
|
||||
virtual void m14(int) = 0;
|
||||
virtual void m14(int) const noexcept = 0;
|
||||
virtual void m15() & = 0;
|
||||
virtual void m15() && = 0;
|
||||
};
|
||||
|
||||
MOCK_BASE_CLASS(variadic, base)
|
||||
|
|
@ -340,9 +349,29 @@ MOCK_BASE_CLASS(variadic, base)
|
|||
MOCK_NON_CONST_METHOD(m11, 0)
|
||||
MOCK_NON_CONST_METHOD(m6, 0, void())
|
||||
MOCK_NON_CONST_METHOD(m7, 0, void(), m7)
|
||||
|
||||
MOCK_METHOD_EXT(m12, 0, (noexcept override))
|
||||
MOCK_METHOD_EXT(m13, 0, (&&override))
|
||||
// Overloaded method
|
||||
MOCK_METHOD(m14, 0, void(), m14_empty)
|
||||
MOCK_METHOD(m14, 2, void(int, float), m14_int_float, ())
|
||||
MOCK_METHOD(m14, 2, void(int, int), m14_int_int, (override))
|
||||
MOCK_METHOD(m14, 1, void(int), m14_int, (override, const noexcept override))
|
||||
MOCK_METHOD_EXT(m15, 0, (&override, &&override), void())
|
||||
MOCK_STATIC_METHOD(m8, 0, void())
|
||||
MOCK_STATIC_METHOD(m9, 0, void(), m9)
|
||||
};
|
||||
void instantiate_class()
|
||||
{
|
||||
variadic inst; // If this compiles all pure virtual methods were mocked
|
||||
const variadic& cinst = inst;
|
||||
(void)cinst; // Avoid unused variable warning
|
||||
static_assert(noexcept(inst.m12()), "noexcept should be kept");
|
||||
static_assert(!noexcept(inst.m14()), "noexcept should not be set");
|
||||
static_assert(noexcept(cinst.m14(1)), "noexcept should be kept");
|
||||
static_assert(!noexcept(inst.m14(1)), "noexcept should not be set");
|
||||
static_assert(noexcept(std::declval<const variadic>().m14(1)), "noexcept should be kept");
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
MOCK_BASE_CLASS(variadic_tpl, base)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue