/* * Trompeloeil C++ mocking framework * * Copyright Björn Fahller 2014-2019 * Copyright (C) 2017, 2018 Andrew Paxie * Copyright Tore Martin Hagen 2019 * * Use, modification and distribution is subject to 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) * * Project home: https://github.com/rollbear/trompeloeil */ #ifndef TROMPELOEIL_HPP_ #define TROMPELOEIL_HPP_ // trompe l'oeil noun (Concise Encyclopedia) // Style of representation in which a painted object is intended // to deceive the viewer into believing it is the object itself... // project home: https://github.com/rollbear/trompeloeil // Deficiencies and missing features // * Mocking function templates is not supported // * If a macro kills a kitten, this threatens extinction of all felines! #if defined(_MSC_VER) # define TROMPELOEIL_NORETURN __declspec(noreturn) # if (!defined(__cplusplus) || _MSC_VER < 1900) # error requires C++ in Visual Studio 2015 RC or later # endif #else # define TROMPELOEIL_NORETURN [[noreturn]] # if (!defined(__cplusplus) || __cplusplus < 201103L) # error requires C++11 or higher # endif #endif #if defined(__clang__) # define TROMPELOEIL_CLANG 1 # define TROMPELOEIL_GCC 0 # define TROMPELOEIL_MSVC 0 # define TROMPELOEIL_CLANG_VERSION \ (__clang_major__ * 10000 + __clang_minor__ * 100 + __clang_patchlevel__) # define TROMPELOEIL_GCC_VERSION 0 # define TROMPELOEIL_CPLUSPLUS __cplusplus # define TROMPELOEIL_NOT_IMPLEMENTED(...) \ _Pragma("clang diagnostic push") \ _Pragma("clang diagnostic ignored \"-Wunneeded-member-function\"") \ __VA_ARGS__ \ _Pragma("clang diagnostic pop") #elif defined(__GNUC__) # define TROMPELOEIL_CLANG 0 # define TROMPELOEIL_GCC 1 # define TROMPELOEIL_MSVC 0 # define TROMPELOEIL_CLANG_VERSION 0 # define TROMPELOEIL_GCC_VERSION \ (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) # define TROMPELOEIL_CPLUSPLUS __cplusplus #elif defined(_MSC_VER) # define TROMPELOEIL_CLANG 0 # define TROMPELOEIL_GCC 0 # define TROMPELOEIL_MSVC 1 # define TROMPELOEIL_CLANG_VERSION 0 # define TROMPELOEIL_GCC_VERSION 0 # if defined(_MSVC_LANG) // Compiler is at least Microsoft Visual Studio 2015 Update 3. # define TROMPELOEIL_CPLUSPLUS _MSVC_LANG # else /* defined(_MSVC_LANG) */ /* * This version of Microsoft Visual C++ is released * in a version of Microsoft Visual Studio between * 2015 RC and less than 2015 Update 3. * * It is an amalgam of C++ versions, with no provision * to specify C++11 mode. * * It also has a __cplusplus macro stuck at 199711L with * no way to change it, such as /Zc:__cplusplus. * * Assume the C++14 code path, but don't promise that it is a * fully conforming implementation of C++14 either. * Hence a value of 201401L, which less than 201402L, * the standards conforming value of __cplusplus. */ # define TROMPELOEIL_CPLUSPLUS 201401L # endif /* !defined(_MSVC_LANG) */ #endif #ifndef TROMPELOEIL_NOT_IMPLEMENTED #define TROMPELOEIL_NOT_IMPLEMENTED(...) __VA_ARGS__ #endif #include #include #include #include #include #include #include #include #include #include #include #include #include #ifdef TROMPELOEIL_SANITY_CHECKS #include #define TROMPELOEIL_ASSERT(x) assert(x) #else #define TROMPELOEIL_ASSERT(x) do {} while (false) #endif #define TROMPELOEIL_IDENTITY(...) __VA_ARGS__ // work around stupid MS VS2015 RC bug #define TROMPELOEIL_ARG16(_0,_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12,_13,_14,_15, ...) _15 #define TROMPELOEIL_COUNT(...) \ TROMPELOEIL_IDENTITY(TROMPELOEIL_ARG16(__VA_ARGS__, \ 15,14,13,12,11,10,9,8,7,6,5,4,3,2,1,0)) #if defined(_MSC_VER) #define TROMPELOEIL_CONCAT_(x, y, ...) x ## y __VA_ARGS__ #define TROMPELOEIL_CONCAT(x, ...) TROMPELOEIL_CONCAT_(x, __VA_ARGS__) #else /* defined(_MSC_VER) */ #define TROMPELOEIL_CONCAT_(x, ...) x ## __VA_ARGS__ #define TROMPELOEIL_CONCAT(x, ...) TROMPELOEIL_CONCAT_(x, __VA_ARGS__) #endif /* !defined(_MSC_VER) */ #define TROMPELOEIL_REMOVE_PAREN(...) TROMPELOEIL_CONCAT(TROMPELOEIL_CLEAR_, \ TROMPELOEIL_REMOVE_PAREN_INTERNAL __VA_ARGS__) #define TROMPELOEIL_REMOVE_PAREN_INTERNAL(...) \ TROMPELOEIL_REMOVE_PAREN_INTERNAL __VA_ARGS__ #define TROMPELOEIL_CLEAR_TROMPELOEIL_REMOVE_PAREN_INTERNAL #define TROMPELOEIL_INIT_WITH_STR15(base, x, ...) \ base{#x, x}, TROMPELOEIL_INIT_WITH_STR14(base, __VA_ARGS__) #define TROMPELOEIL_INIT_WITH_STR14(base, x, ...) \ base{#x, x}, TROMPELOEIL_INIT_WITH_STR13(base, __VA_ARGS__) #define TROMPELOEIL_INIT_WITH_STR13(base, x, ...) \ base{#x, x}, TROMPELOEIL_INIT_WITH_STR12(base, __VA_ARGS__) #define TROMPELOEIL_INIT_WITH_STR12(base, x, ...) \ base{#x, x}, TROMPELOEIL_INIT_WITH_STR11(base, __VA_ARGS__) #define TROMPELOEIL_INIT_WITH_STR11(base, x, ...) \ base{#x, x}, TROMPELOEIL_INIT_WITH_STR10(base, __VA_ARGS__) #define TROMPELOEIL_INIT_WITH_STR10(base, x, ...) \ base{#x, x}, TROMPELOEIL_INIT_WITH_STR9(base, __VA_ARGS__) #define TROMPELOEIL_INIT_WITH_STR9(base, x, ...) \ base{#x, x}, TROMPELOEIL_INIT_WITH_STR8(base, __VA_ARGS__) #define TROMPELOEIL_INIT_WITH_STR8(base, x, ...) \ base{#x, x}, TROMPELOEIL_INIT_WITH_STR7(base, __VA_ARGS__) #define TROMPELOEIL_INIT_WITH_STR7(base, x, ...) \ base{#x, x}, TROMPELOEIL_INIT_WITH_STR6(base, __VA_ARGS__) #define TROMPELOEIL_INIT_WITH_STR6(base, x, ...) \ base{#x, x}, TROMPELOEIL_INIT_WITH_STR5(base, __VA_ARGS__) #define TROMPELOEIL_INIT_WITH_STR5(base, x, ...) \ base{#x, x}, TROMPELOEIL_INIT_WITH_STR4(base, __VA_ARGS__) #define TROMPELOEIL_INIT_WITH_STR4(base, x, ...) \ base{#x, x}, TROMPELOEIL_INIT_WITH_STR3(base, __VA_ARGS__) #define TROMPELOEIL_INIT_WITH_STR3(base, x, ...) \ base{#x, x}, TROMPELOEIL_INIT_WITH_STR2(base, __VA_ARGS__) #define TROMPELOEIL_INIT_WITH_STR2(base, x, ...) \ base{#x, x}, TROMPELOEIL_INIT_WITH_STR1(base, __VA_ARGS__) #define TROMPELOEIL_INIT_WITH_STR1(base, x) \ base{#x, x} #define TROMPELOEIL_INIT_WITH_STR0(base) #define TROMPELOEIL_INIT_WITH_STR(base, ...) \ TROMPELOEIL_CONCAT(TROMPELOEIL_INIT_WITH_STR, \ TROMPELOEIL_COUNT(__VA_ARGS__))(base, __VA_ARGS__) #define TROMPELOEIL_PARAM_LIST15(...) \ TROMPELOEIL_PARAM_LIST14(__VA_ARGS__), \ ::trompeloeil::param_list_t<__VA_ARGS__, 14> p15 #define TROMPELOEIL_PARAM_LIST14(...) \ TROMPELOEIL_PARAM_LIST13(__VA_ARGS__), \ ::trompeloeil::param_list_t<__VA_ARGS__, 13> p14 #define TROMPELOEIL_PARAM_LIST13(...) \ TROMPELOEIL_PARAM_LIST12(__VA_ARGS__), \ ::trompeloeil::param_list_t<__VA_ARGS__, 12> p13 #define TROMPELOEIL_PARAM_LIST12(...) \ TROMPELOEIL_PARAM_LIST11(__VA_ARGS__), \ ::trompeloeil::param_list_t<__VA_ARGS__, 11> p12 #define TROMPELOEIL_PARAM_LIST11(...) \ TROMPELOEIL_PARAM_LIST10(__VA_ARGS__), \ ::trompeloeil::param_list_t<__VA_ARGS__, 10> p11 #define TROMPELOEIL_PARAM_LIST10(...) \ TROMPELOEIL_PARAM_LIST9(__VA_ARGS__), \ ::trompeloeil::param_list_t<__VA_ARGS__, 9> p10 #define TROMPELOEIL_PARAM_LIST9(...) \ TROMPELOEIL_PARAM_LIST8(__VA_ARGS__), \ ::trompeloeil::param_list_t<__VA_ARGS__, 8> p9 #define TROMPELOEIL_PARAM_LIST8(...) \ TROMPELOEIL_PARAM_LIST7(__VA_ARGS__), \ ::trompeloeil::param_list_t<__VA_ARGS__, 7> p8 #define TROMPELOEIL_PARAM_LIST7(...) \ TROMPELOEIL_PARAM_LIST6(__VA_ARGS__), \ ::trompeloeil::param_list_t<__VA_ARGS__, 6> p7 #define TROMPELOEIL_PARAM_LIST6(...) \ TROMPELOEIL_PARAM_LIST5(__VA_ARGS__), \ ::trompeloeil::param_list_t<__VA_ARGS__, 5> p6 #define TROMPELOEIL_PARAM_LIST5(...) \ TROMPELOEIL_PARAM_LIST4(__VA_ARGS__), \ ::trompeloeil::param_list_t<__VA_ARGS__, 4> p5 #define TROMPELOEIL_PARAM_LIST4(...) \ TROMPELOEIL_PARAM_LIST3(__VA_ARGS__), \ ::trompeloeil::param_list_t<__VA_ARGS__, 3> p4 #define TROMPELOEIL_PARAM_LIST3(...) \ TROMPELOEIL_PARAM_LIST2(__VA_ARGS__), \ ::trompeloeil::param_list_t<__VA_ARGS__, 2> p3 #define TROMPELOEIL_PARAM_LIST2(...) \ TROMPELOEIL_PARAM_LIST1(__VA_ARGS__), \ ::trompeloeil::param_list_t<__VA_ARGS__, 1> p2 #define TROMPELOEIL_PARAM_LIST1(...) \ ::trompeloeil::param_list_t<__VA_ARGS__, 0> p1 #define TROMPELOEIL_PARAM_LIST0(func_type) #define TROMPELOEIL_PARAM_LIST(num, func_type) \ TROMPELOEIL_CONCAT(TROMPELOEIL_PARAM_LIST, num) \ (TROMPELOEIL_REMOVE_PAREN(func_type)) #define TROMPELOEIL_PARAMS15 TROMPELOEIL_PARAMS14, p15 #define TROMPELOEIL_PARAMS14 TROMPELOEIL_PARAMS13, p14 #define TROMPELOEIL_PARAMS13 TROMPELOEIL_PARAMS12, p13 #define TROMPELOEIL_PARAMS12 TROMPELOEIL_PARAMS11, p12 #define TROMPELOEIL_PARAMS11 TROMPELOEIL_PARAMS10, p11 #define TROMPELOEIL_PARAMS10 TROMPELOEIL_PARAMS9, p10 #define TROMPELOEIL_PARAMS9 TROMPELOEIL_PARAMS8, p9 #define TROMPELOEIL_PARAMS8 TROMPELOEIL_PARAMS7, p8 #define TROMPELOEIL_PARAMS7 TROMPELOEIL_PARAMS6, p7 #define TROMPELOEIL_PARAMS6 TROMPELOEIL_PARAMS5, p6 #define TROMPELOEIL_PARAMS5 TROMPELOEIL_PARAMS4, p5 #define TROMPELOEIL_PARAMS4 TROMPELOEIL_PARAMS3, p4 #define TROMPELOEIL_PARAMS3 TROMPELOEIL_PARAMS2, p3 #define TROMPELOEIL_PARAMS2 TROMPELOEIL_PARAMS1, p2 #define TROMPELOEIL_PARAMS1 , p1 #define TROMPELOEIL_PARAMS0 #define TROMPELOEIL_PARAMS(num) TROMPELOEIL_CONCAT(TROMPELOEIL_PARAMS, num) #if defined(__cxx_rtti) || defined(__GXX_RTTI) || defined(_CPPRTTI) # define TROMPELOEIL_TYPE_ID_NAME(x) typeid(x).name() #else # define TROMPELOEIL_TYPE_ID_NAME(x) "object" #endif #if (TROMPELOEIL_CPLUSPLUS == 201103L) #define TROMPELOEIL_DECLTYPE_AUTO \ auto #define TROMPELOEIL_TRAILING_RETURN_TYPE(return_type) \ -> return_type #else /* (TROMPELOEIL_CPLUSPLUS == 201103L) */ #define TROMPELOEIL_DECLTYPE_AUTO \ decltype(auto) #define TROMPELOEIL_TRAILING_RETURN_TYPE(return_type) \ /**/ #endif /* !(TROMPELOEIL_CPLUSPLUS == 201103L) */ static constexpr bool trompeloeil_movable_mock = false; namespace trompeloeil { template struct identity_type { using type = T; }; template identity_type nonconst_member_signature(R (C::*)(Args...)) { return {}; } template identity_type const_member_signature(R (C::*)(Args...) const) { return {}; } template struct void_t_ { using type = void; }; template using void_t = typename void_t_::type; template