/* * Trompeloeil C++ mocking framework * * Copyright Björn Fahller 2014-2019 * Copyright (C) 2017, 2018 Andrew Paxie * * 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 #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 #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)) #define TROMPELOEIL_CONCAT_(x, y) x ## y #define TROMPELOEIL_CONCAT(x, y) TROMPELOEIL_CONCAT_(x, y) #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(func_type) \ TROMPELOEIL_PARAM_LIST14(func_type), \ ::trompeloeil::param_list_t p15 #define TROMPELOEIL_PARAM_LIST14(func_type) \ TROMPELOEIL_PARAM_LIST13(func_type), \ ::trompeloeil::param_list_t p14 #define TROMPELOEIL_PARAM_LIST13(func_type) \ TROMPELOEIL_PARAM_LIST12(func_type), \ ::trompeloeil::param_list_t p13 #define TROMPELOEIL_PARAM_LIST12(func_type) \ TROMPELOEIL_PARAM_LIST11(func_type), \ ::trompeloeil::param_list_t p12 #define TROMPELOEIL_PARAM_LIST11(func_type) \ TROMPELOEIL_PARAM_LIST10(func_type), \ ::trompeloeil::param_list_t p11 #define TROMPELOEIL_PARAM_LIST10(func_type) \ TROMPELOEIL_PARAM_LIST9(func_type), \ ::trompeloeil::param_list_t p10 #define TROMPELOEIL_PARAM_LIST9(func_type) \ TROMPELOEIL_PARAM_LIST8(func_type), \ ::trompeloeil::param_list_t p9 #define TROMPELOEIL_PARAM_LIST8(func_type) \ TROMPELOEIL_PARAM_LIST7(func_type), \ ::trompeloeil::param_list_t p8 #define TROMPELOEIL_PARAM_LIST7(func_type) \ TROMPELOEIL_PARAM_LIST6(func_type), \ ::trompeloeil::param_list_t p7 #define TROMPELOEIL_PARAM_LIST6(func_type) \ TROMPELOEIL_PARAM_LIST5(func_type), \ ::trompeloeil::param_list_t p6 #define TROMPELOEIL_PARAM_LIST5(func_type) \ TROMPELOEIL_PARAM_LIST4(func_type), \ ::trompeloeil::param_list_t p5 #define TROMPELOEIL_PARAM_LIST4(func_type) \ TROMPELOEIL_PARAM_LIST3(func_type), \ ::trompeloeil::param_list_t p4 #define TROMPELOEIL_PARAM_LIST3(func_type) \ TROMPELOEIL_PARAM_LIST2(func_type), \ ::trompeloeil::param_list_t p3 #define TROMPELOEIL_PARAM_LIST2(func_type) \ TROMPELOEIL_PARAM_LIST1(func_type), \ ::trompeloeil::param_list_t p2 #define TROMPELOEIL_PARAM_LIST1(func_type) \ ::trompeloeil::param_list_t p1 #define TROMPELOEIL_PARAM_LIST0(func_type) #define TROMPELOEIL_PARAM_LIST(num, func_type) \ TROMPELOEIL_CONCAT(TROMPELOEIL_PARAM_LIST, num)(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 (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