diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index ee1ce1f..08be1a6 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -904,6 +904,7 @@ jobs: cxx_standard: 20, cxx_asan: true, libcxx: false, + cxx_flags: "-Wno-gnu-zero-variadic-macro-arguments" } - { name: "Linux Clang 10 C++11 / libc++", @@ -940,6 +941,7 @@ jobs: cxx_standard: 20, cxx_asan: true, libcxx: true, + cxx_flags: "-Wno-gnu-zero-variadic-macro-arguments" } # Clang-11 @@ -978,6 +980,7 @@ jobs: cxx_standard: 20, cxx_asan: true, libcxx: false, + cxx_flags: "-Wno-gnu-zero-variadic-macro-arguments" } - { name: "Linux Clang 11 C++11 / libc++", @@ -1014,6 +1017,7 @@ jobs: cxx_standard: 20, cxx_asan: true, libcxx: true, + cxx_flags: "-Wno-gnu-zero-variadic-macro-arguments" } # Clang-12 @@ -1052,6 +1056,7 @@ jobs: cxx_standard: 20, cxx_asan: true, libcxx: false, + cxx_flags: "-Wno-gnu-zero-variadic-macro-arguments" } - { name: "Linux Clang 12 C++11 / libc++", @@ -1088,6 +1093,7 @@ jobs: cxx_standard: 20, cxx_asan: true, libcxx: true, + cxx_flags: "-Wno-gnu-zero-variadic-macro-arguments" } # Clang-13 @@ -1126,6 +1132,7 @@ jobs: cxx_standard: 20, cxx_asan: true, libcxx: false, + cxx_flags: "-Wno-gnu-zero-variadic-macro-arguments" } - { name: "Linux Clang 13 C++11 / libc++", @@ -1162,6 +1169,7 @@ jobs: cxx_standard: 20, cxx_asan: true, libcxx: true, + cxx_flags: "-Wno-gnu-zero-variadic-macro-arguments" } # Clang-14 @@ -1628,24 +1636,52 @@ jobs: cc: "cl", cxx: "cl", cxx_standard: 11, } + - { + name: "Windows MSVC 2022 C++11 preprocessor", + os: windows-2022, + cc: "cl", cxx: "cl", + cxx_standard: 11, + cxx_flags: "/Zc:preprocessor" + } - { name: "Windows MSVC 2022 C++14", os: windows-2022, cc: "cl", cxx: "cl", cxx_standard: 14, } + - { + name: "Windows MSVC 2022 C++14 preprocessor", + os: windows-2022, + cc: "cl", cxx: "cl", + cxx_standard: 14, + cxx_flags: "/Zc:preprocessor" + } - { name: "Windows MSVC 2022 C++17", os: windows-2022, cc: "cl", cxx: "cl", cxx_standard: 17, } + - { + name: "Windows MSVC 2022 C++17 preprocessor", + os: windows-2022, + cc: "cl", cxx: "cl", + cxx_standard: 17, + cxx_flags: "/Zc:preprocessor" + } - { name: "Windows MSVC 2022 C++20", os: windows-2022, cc: "cl", cxx: "cl", cxx_standard: 20, } + - { + name: "Windows MSVC 2022 C++20 preprocessor", + os: windows-2022, + cc: "cl", cxx: "cl", + cxx_standard: 20, + cxx_flags: "/Zc:preprocessor" + } # MSVC 2019 - { @@ -1654,24 +1690,52 @@ jobs: cc: "cl", cxx: "cl", cxx_standard: 11, } + - { + name: "Windows MSVC 2019 C++11 preprocessor", + os: windows-2019, + cc: "cl", cxx: "cl", + cxx_standard: 11, + cxx_flags: "/Zc:preprocessor" + } - { name: "Windows MSVC 2019 C++14", os: windows-2019, cc: "cl", cxx: "cl", cxx_standard: 14, } + - { + name: "Windows MSVC 2019 C++14 preprocessor", + os: windows-2019, + cc: "cl", cxx: "cl", + cxx_standard: 14, + cxx_flags: "/Zc:preprocessor" + } - { name: "Windows MSVC 2019 C++17", os: windows-2019, cc: "cl", cxx: "cl", cxx_standard: 17, } + - { + name: "Windows MSVC 2019 C++17 preprocessor", + os: windows-2019, + cc: "cl", cxx: "cl", + cxx_standard: 17, + cxx_flags: "/Zc:preprocessor" + } - { name: "Windows MSVC 2019 C++20", os: windows-2019, cc: "cl", cxx: "cl", cxx_standard: 20, } + - { + name: "Windows MSVC 2019 C++20 preprocessor", + os: windows-2019, + cc: "cl", cxx: "cl", + cxx_standard: 20, + cxx_flags: "/Zc:preprocessor" + } steps: - uses: actions/checkout@v4 @@ -1698,6 +1762,10 @@ jobs: shell: bash run: | STD=${{ matrix.config.cxx_standard }} + if [ -n "${{ matrix.config.cxx_flags }}" ] + then + cxx_flags="${{matrix.config.cxx_flags }}" + fi if [ "x${{ matrix.config.libcxx }}" == "xtrue" ] then cxx_flags="${cxx_flags} -stdlib=libc++ -Wno-unused-command-line-argument" diff --git a/ChangeLog b/ChangeLog index 311c45f..7193e68 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,25 @@ + * Added mocking macros that infers function arity from a trailing return + type syntax signature. + + MAKE_MOCK(name, signature {, specifiers}) + MAKE_CONST_MOCK(name, signature {, specifiers}) + MAKE_STDMETHOD_MOCK(name, signature {, specifiers}) + + Note that these only work with trailing return type syntax. Examples + of specifiers are 'override', 'final' and 'noexcept' + + The preprocessor is limited and can only handle nullary functions, + i.e. functions that do not accept any arguments, in some cases. + + MSVC handles nullary functions when compiling with /Zc:preprocessor + with MSVC 19.40 (VS 17.10) or later. + + Gcc and Clang always handles nullary functions when compiling with + C++20 or later, and when enabling a gcc extension by compiling with + -std=gnu++11/14/17 and defining the macro TROMPELOEIL_HAS_GCC_PP before + #include:ing the trompeloeil headers. + + * Added .RT_TIMES() to exceptations, which works like .TIMES() but where the limits are only known at runtime. Thank you Dominic Koepke for submitting the implementation. diff --git a/README.md b/README.md index 6c58e9f..0c81114 100644 --- a/README.md +++ b/README.md @@ -59,9 +59,9 @@ void interface_func(Interface*); // function to test class Mock : public Interface { public: - MAKE_MOCK2(foo, bool(int, std::string&),override); - MAKE_MOCK1(bar, bool(int),override); - MAKE_MOCK1(bar, bool(std::string),override); + MAKE_MOCK(foo, auto (int, std::string&) -> bool, override); + MAKE_MOCK(bar, auto (int) -> bool, override); + MAKE_MOCK(bar, auto (std::string) -> bool, override); MAKE_MOCK0(baz, void()); // not from Interface }; diff --git a/docs/CookBook.md b/docs/CookBook.md index a55cef6..af59507 100644 --- a/docs/CookBook.md +++ b/docs/CookBook.md @@ -652,11 +652,28 @@ only work when implementing to an interface, do not handle multiple inheritance and do not handle overloads. A more generic technique is to implement free mocks as members of any -`struct` or `class` using the macros [**`MAKE_MOCKn`**]( +`struct` or `class` using the macros [**`MAKE_MOCK`**]( +reference.md/#MAKE_MOCK +) and [**`MAKE_CONST_MOCK`**]( +reference.md/#MAKE_CONST_MOCK +) and also [**`MAKE_MOCKn`**]( reference.md/#MAKE_MOCKn -) and [**`MAKE_CONST_MOCKn`**]( +) and [**`MAKE_CONST_MOCKn`**]( reference.md/#MAKE_CONST_MOCKn -), where `n` is the number of parameters in the function. +). + +The macros [**`MAKE_MOCKn`**]( +reference.md/#MAKE_MOCKn +) and [**`MAKE_CONST_MOCKn`**]( +reference.md/#MAKE_CONST_MOCKn +) requires that you explicitly state the number of parameters to the function +(the `n`), while macros [**`MAKE_MOCK`**]( +reference.md/#MAKE_MOCK +) and [**`MAKE_CONST_MOCK`**]( +reference.md/#MAKE_CONST_MOCK +) infers the number of parameters, but require that you write the function +signatures with the trailing return type syntax. + Example: @@ -677,7 +694,7 @@ class MockDictionary : public trompeloeil::mock_interface struct Logger { - MAKE_MOCK2(log, void(int severity, const std::string& msg)); + MAKE_MOCK(log, auto (int severity, const std::string& msg) -> void); }; ``` @@ -689,9 +706,11 @@ The line `IMPLEMENT_CONST_MOCK1(lookup);` implements the function `std::string& lookup(int) const` and the line `IMPLEMENT_MOCK2(add);` implements the function `void add(int, std::string&&)`. -The line `MAKE_MOCK2(log, void(int severity, const std::string& msg))` +The line `MAKE_MOCK(log, auto (int severity, const std::string& msg) -> void)` creates a mock function `void Logger::log(int, const std::string&)`. If -[**`MAKE_MOCKn(...)`**](reference.md/#MAKE_MOCKn) or +[**`MAKE_MOCK(...)`**](reference.md/#MAKE_MOCK), +[**`MAKE_MOCKn(...)`**](reference.md/#MAKE_MOCKn), +[**`MAKE_CONST_MOCK(...)`**](reference.md/#MAKE_CONST_MOCK)or [**`MAKE_CONST_MOCKn(...)`**](reference.md/#MAKE_CONST_MOCKn) are used to implement a virtual function from a base class, it is always recommended to add a third macro parameter `override` since it gives the compiler an ability to @@ -700,11 +719,10 @@ complain about mistakes. ### Mocking private or protected member functions Mocking private or protected member functions using -[**`MAKE_MOCKn(...)`**](reference.md/#MAKE_MOCKn) or +[**`MAKE_MOCK(...)`**](reference.md/#MAKE_MOCK), [**`MAKE_MOCKn(...)`**](reference.md/#MAKE_MOCKn), +[**`MAKE_CONST_MOCK(...)`**](reference.md/#MAKE_CONST_MOCK) or [**`MAKE_CONST_MOCKn(...)`**](reference.md/#MAKE_CONST_MOCKn) is no different -from mocking - -public member functions. Just make them public in the mock class. It may seem +from mocking public member functions. Just make them public in the mock class. It may seem strange that you can change access rights of a member function through inheritance, but C\+\+ allows it. @@ -720,7 +738,7 @@ private: class Mock : public Base { public: - MAKE_MOCK1(secret, void(int), override); // not so secret now + MAKE_MOCK(secret, auto (int) -> void, override); // not so secret now }; ``` @@ -746,9 +764,9 @@ Example: class Mock { public: - MAKE_MOCK1(overload, void(int)); - MAKE_MOCK1(overload, int(const std::string&)); - MAKE_MOCK2(overload, int(const char*, size_t)); + MAKE_MOCK(overload, auto (int) -> void); + MAKE_MOCK(overload, auto (const std::string&) -> int); + MAKE_MOCK(overload, auto (const char*, size_t) -> int); }; ``` @@ -775,7 +793,7 @@ class Mock { public: int operator()(int x) const { return function_call(x); } - MAKE_CONST_MOCK1(function_call, int(int)); + MAKE_CONST_MOCK(function_call, auto (int) -> int); }; ``` @@ -791,8 +809,8 @@ template class Mock { public: - MAKE_MOCK1(func, void(int)); - MAKE_MOCK2(tfunc, int(const T&, size_t)); + MAKE_MOCK(func, auto (int) -> void); + MAKE_MOCK(tfunc, auto(const T&, size_t) -> int); }; ``` @@ -812,7 +830,7 @@ Example: class ConcreteMock { public: - MAKE_MOCK2(func, bool(size_t, const char*)); + MAKE_MOCK(func, auto(size_t, const char*) -> bool); }; ``` @@ -922,8 +940,18 @@ void a_test() ### Mocking functions which return a template -To use template as return type you have to put the signature into parentheses -like this: +To use template as return type, you need to introduce an alias for the return type instead: + +```Cpp +using pair_ints = std::pair; + +struct M +{ + MAKE_MOCK(make, auto (int, int)->pair_ints); +}; +``` +If you use the [**`MAKE_MOCKn()`**](reference.md/#MAKE_MOCKn) macros, you can get away +with enclosing the return type in parentheses, like this: ```Cpp struct M @@ -938,7 +966,9 @@ Windows API functions and COM Interfaces are declared with the [__stdcall](https://learn.microsoft.com/en-us/cpp/cpp/stdcall?view=msvc-170) calling convention when targeting a 32-bit build, which becomes part of the signature of a method. If you have the need to mock this type of functions the -[**`MAKE_STDMETHOD_MOCKn(...)`**](reference.md/#MAKE_STDMETHOD_MOCKn) and +[**`MAKE_STDMETHOD_MOCK(...)`**](reference.md/#MAKE_STDMETHOD_MOCK), +[**`MAKE_STDMETHOD_MOCKn(...)`**](reference.md/#MAKE_STDMETHOD_MOCKn), +[**`IMPLEMENT_STDMETHOD_MOCKn(...)`**](reference.md/#IMPLEMENT_STDMETHOD_MOCKn) and [**`IMPLEMENT_STDMETHOD_MOCKn(...)`**](reference.md/#IMPLEMENT_STDMETHOD_MOCKn) macros are provided. @@ -947,7 +977,7 @@ struct Mock_stdcall : public trompeloeil::mock_interface { IMPLEMENT_STDMETHOD_MOCK0(AddRef); IMPLEMENT_STDMETHOD_MOCK0(Release); - MAKE_STDMETHOD_MOCK2(QueryInterface, HRESULT(REFIID, void **), override); + MAKE_STDMETHOD_MOCK(QueryInterface, auto (REFIID, void **) -> HRESULT, override); } ``` @@ -1006,8 +1036,8 @@ Example: class Mock { public: - MAKE_MOCK1(func, void(int)); - MAKE_MOCK2(func, void(const char*)); + MAKE_MOCK(func, auto (int) -> void); + MAKE_MOCK2(func, auto (const char*) -> void); }; void test() @@ -1043,9 +1073,9 @@ Example: class Mock { public: - MAKE_MOCK1(func, void(int)); - MAKE_MOCK1(func, void(const char*)); - MAKE_MOCK1(func, void(const std::string&)) + MAKE_MOCK(func, auto (int) -> void); + MAKE_MOCK(func, auto (const char*) -> void); + MAKE_MOCK(func, auto (const std::string&) -> void) }; void test() @@ -1138,7 +1168,7 @@ Example: class Mock { public: - MAKE_MOCK1(func, void(const char*)); + MAKE_MOCK(func, auto (const char*) -> void); }; void test() @@ -1166,8 +1196,8 @@ Example: class Mock { public: - MAKE_MOCK1(func, void(int*)); - MAKE_MOCK2(func, void(std::unique_ptr*)); + MAKE_MOCK(func, auto (int*) -> void); + MAKE_MOCK(func, auto (std::unique_ptr) -> void); }; using trompeloeil::eq; @@ -1193,7 +1223,7 @@ Example: ```Cpp struct Mock { - MAKE_MOCK1(func, void(const std::string&)); + MAKE_MOCK(func, auto (const std::string&) -> void); }; using trompeloeil::re; // matching regular expressions @@ -1219,7 +1249,7 @@ Example: class Mock { public: - MAKE_MOCK2(func, void(const char*, size_t len)); + MAKE_MOCK(func, auto (const char*, size_t len) -> void); }; using trompeloeil::ne; @@ -1274,7 +1304,7 @@ Example: class Mock { public: - MAKE_MOCK1(func, void(std::unique_ptr)); + MAKE_MOCK(func, auto (std::unique_ptr) -> void); }; using trompeloeil::ne; @@ -1300,7 +1330,7 @@ bind a reference in the expectation. class Mock { public: - MAKE_MOCK1(func, void(std::unique_ptr&)); + MAKE_MOCK(func, auto (std::unique_ptr&) -> void); }; void func_to_test(Mock& m, std::unique_ptr& ptr); @@ -1338,8 +1368,8 @@ Example: class Mock { public: - MAKE_MOCK1(func, void(int*)); - MAKE_MOCK1(func, void(char*)); + MAKE_MOCK(func, auto (int*) -> void); + MAKE_MOCK(func, auto (char*) -> void); }; using namespace trompeloeil; @@ -1367,8 +1397,8 @@ Example: class Mock { public: - MAKE_MOCK1(func, void(int)); - MAKE_CONST_MOCK1(func, void(int)); + MAKE_MOCK(func, auto (int) -> void); + MAKE_CONST_MOCK(func, auto (int) -> void); }; void test() @@ -1403,7 +1433,7 @@ Example: class Dispatcher { public: - MAKE_MOCK1(subscribe, void(std::function)); + MAKE_MOCK(subscribe, auto (std::function) -> void); }; using trompeloeil::_; @@ -1451,7 +1481,7 @@ class Dictionary { public: using id_t = size_t; - MAKE_MOCK1(lookup, std::string(id_t)); + MAKE_MOCK(lookup, auto (id_t) -> std::string); }; using trompeloeil::ge; // greater than or equal @@ -1496,7 +1526,7 @@ class Dictionary { public: using id_t = size_t; - MAKE_MOCK1(lookup, const std::string&(id_t)); + MAKE_MOCK(lookup, auto (id_t) -> const std::string&); }; using trompeloeil::gt; // greater than or equal @@ -1548,7 +1578,7 @@ class Dictionary { public: using id_t = size_t; - MAKE_CONST_MOCK1(lookup, const std::string&(id_t)); + MAKE_CONST_MOCK(lookup, auto (id_t) -> const std::string&); }; using trompeloeil::_; // matches anything @@ -1595,8 +1625,8 @@ template class Allocator { public: - MAKE_MOCK1(allocate, T*(size_t)); - MAKE_MOCK1(deallocate, void(T*)); + MAKE_MOCK(allocate, auto (size_t) -> T*); + MAKE_MOCK(deallocate, auto (T*) -> void); }; using trompeloeil::_; @@ -1632,8 +1662,8 @@ template class Allocator { public: - MAKE_MOCK1(allocate, T*(size_t)); - MAKE_MOCK1(deallocate, void(T*)); + MAKE_MOCK(allocate, auto (size_t) -> T*); + MAKE_MOCK(deallocate, auto (T*) -> void); }; using trompeloeil::_; @@ -1705,9 +1735,9 @@ class FileOps { public: using handle = int; - MAKE_MOCK1(open, handle(const std::string&)); - MAKE_MOCK3(write, size_t(handle, const char*, size_t)); - MAKE_MOCK1(close, void(handle)); + MAKE_MOCK(open, auto (const std::string&) -> handle); + MAKE_MOCK(write, auto (handle, const char*, size_t) -> size_t); + MAKE_MOCK(close, auto (handle) -> void); }; using trompeloeil::ne; @@ -1751,9 +1781,9 @@ class FileOps { public: using handle = int; - MAKE_MOCK1(open, handle(const std::string&)); - MAKE_MOCK3(write, size_t(handle, const char*, size_t)); - MAKE_MOCK1(close, void(handle)); + MAKE_MOCK(open, auto (const std::string&) -> handle); + MAKE_MOCK(write, auto (handle, const char*, size_t) -> size_t); + MAKE_MOCK(close, auto (handle) -> void); }; using trompeloeil::ne; @@ -1814,7 +1844,7 @@ Example: class Mock { public: - MAKE_MOCK1(func, void(int)); + MAKE_MOCK(func, auto (int) -> void); }; void some_test() @@ -1857,7 +1887,7 @@ class Mock { public: virtual ~Mock() {} // virtual destructor required for deathwatched<> - MAKE_MOCK1(func, void(int)); + MAKE_MOCK(func, auto (int) -> void); } template @@ -2049,8 +2079,8 @@ Example: class Mock { public: - MAKE_MOCK1(create, int(const std::string&)); - MAKE_MOCK1(func, std::string(int)); + MAKE_MOCK(create, auto (const std::string&) -> int); + MAKE_MOCK(func, auto (int) -> std::string); }; using trompeloeil::_; @@ -2193,7 +2223,7 @@ Example usage: class Mock { public: - MAKE_MOCK1(func, void(int)); + MAKE_MOCK(func, auto (int) -> void); }; void test() @@ -2307,9 +2337,9 @@ Here's an example of the usage. ```Cpp struct C { - MAKE_MOCK1(func, void(int)); - MAKE_MOCK1(func, void(std::string&&)); - MAKE_MOCK1(func2, void(std::vector const&); + MAKE_MOCK(func, auto (int) -> void); + MAKE_MOCK(func, auto (std::string&&) -> void); + MAKE_MOCK(func2, auto (std::vector const&) -> void); }; void test() @@ -2542,7 +2572,7 @@ Example usage: class Mock { public: - MAKE_MOCK1(func, void(int)); + MAKE_MOCK(func, auto (int) -> void); }; void test() diff --git a/docs/FAQ.md b/docs/FAQ.md index 06f071b..00b089c 100644 --- a/docs/FAQ.md +++ b/docs/FAQ.md @@ -22,6 +22,8 @@ - Q. [How do I use *Trompeloeil* in a CMake project?](#cmake) - Q. [Why are mock objects not move constructible?](#move_constructible) - Q. [Why can't I mock a function that returns a template?](#return_template) +- Q. [Why doesn't **`MAKE_MOCK(...)`** work with templated parameter types?](#template_args) +- Q. [Why doesn't **`MAKE_MOCK(...)`** work with nullary functions?](#nullary_functions) - Q. [Can I mock a `noexcept` function?](#mock_noexcept) - Q. [What does it mean that an expectation is "saturated"?](#saturated_expectation) - Q. [Can I mock a coroutine functionp?](#coroutines) @@ -312,10 +314,11 @@ idea. If you can provide a pull request, so much the better. ## Q. Why the need to provide the number of parameters in [**`MAKE_MOCKn()`**](reference.md/#MAKE_MOCKn) when all information is in the signature? -**A.** If you can figure out a way to infer the information necessary to -generate a mocked implementation without an explicit parameter count, -please [open an issue](https://github.com/rollbear/trompeloeil/issues) -discussing the idea. If you can provide a pull request, so much the better. +**A.** When using the trailing return type syntax for the function signatures, you can +use the macros [**`MAKE_MOCK(...)`**](reference.md#MAKE_MOCK), +[**`MAKE_CONST_MOCK(...)`**](reference.md#MAKE_CONST_MOCK) and +[**`MAKE_STDMETHODCALL_MOCK(...)`**](reference.md#MAKE_STDMETHOD_MOCK) and let the +preprocessor infer the number of parameters for you. ## Q. Why *`C++14`* and not *`C++11`* or *`C++03`* that is more widely spread? @@ -693,32 +696,77 @@ work poorly with templates. It sees the parameters to the macro above as `make`, `std::pair(int,int)`, which of course is nonsense and causes compilation errors. -One easy way around this is to put the signature into parentheses: +One easy way around this is to create an alias: ```Cpp +using pair_int_int = std::pair; + struct M { - MAKE_MOCK2(make, (std::pair(int,int))); + MAKE_MOCK2(make, pair_int_int(int,int)); + MAKE_MOCK(make_trail, auto (int, int)->pair_int_int); }; ``` -Or if you prefer the legacy way, create an alias: +These work around the preprocessor parameter problem. + +Another way, if you're mocking an interface, is to use +[**`trompeloeil::mock_interface`**](reference.md/#mock_interface) +and [**`IMPLEMENT_MOCKn`**](reference.md/#IMPLEMENT_MOCKn). See +[CookBook](CookBook.md/#creating_mock_classes) for an intro. + +### Q. Why doesn't **`MAKE_MOCK(...)`** work with templated parameter types? + +Like this: + +```Cpp +struct M +{ + MAKE_MOCK(make, auto (std::pair)->int); +}; +``` + +**A.** You can, but there is a limitation in the preprocessor, that makes it +work poorly with templates. The expansion of the +[**`MAKE_MOCK()`**](reference.md/#MAKE_MOCK) macro sees the parameters to the +function as `std::pair`, which of course is nonsense +and causes compilation errors. The same problem applies to the return type. + +A way around this is to create an alias: ```Cpp using pair_int_int = std::pair; struct M { - MAKE_MOCK2(make, pair_int_int(int,int)); + MAKE_MOCK(make, auto (pair_int_int) -> int); }; ``` -These work around the preprocessor parameter problem. +Another way is to resort to [**`MAKE_MOCKn(...)`**](reference.md/#MAKE_MOCKn) +and be explicit about the function arity. + +### Q. Why doesn't **`MAKE_MOCK(...)`** work with nullary functions? + +Like this: + +```Cpp +struct M +{ + MAKE_MOCK(make, auto () -> int); +}; +``` + +**A.** It does, but compilers disgagree a bit on it. + +* MSVC handles nullary functions when compiling with `/Zc:preprocessor` + with MSVC 19.40 (VS 17.10) or later. + +* Gcc and Clang always handles nullary functions when compiling with + C++20 or later, and when enabling a gcc extension by defining the macro + `TROMPELOEIL_HAS_GCC_PP` before `#include`:ing the trompeloeil headers, and + compiling with `-std=gnu++11`, `-std=gnu++14` or `-std=gnu++17`. -Another way, if you're mocking an interface, is to use -[**`trompeloeil::mock_interface`**](reference.md/#mock_interface) -and [**`IMPLEMENT_MOCKn`**](reference.md/#IMPLEMENT_MOCKn). See -[CookBook](CookBook.md/#creating_mock_classes) for an intro. ### Q. Can I mock a `noexcept` function? diff --git a/docs/reference.md b/docs/reference.md index 0e7340d..96ae055 100644 --- a/docs/reference.md +++ b/docs/reference.md @@ -49,8 +49,11 @@ - [**`LR_SIDE_EFFECT(`** *expr* **`)`**](#LR_SIDE_EFFECT) - [**`LR_THROW(`** *expr* **`)`**](#LR_THROW) - [**`LR_WITH(`** *expr* **`)`**](#LR_WITH) + - [**`MAKE_CONST_MOCK(`** *func_name*, *signature* **`)`**](#MAKE_CONST_MOCK) - [**`MAKE_CONST_MOCKn(`** *func_name*, *signature* **`)`**](#MAKE_CONST_MOCKn) + - [**`MAKE_MOCK(`** *name*, *signature* **`)`**](#MAKE_MOCK) - [**`MAKE_MOCKn(`** *name*, *signature* **`)`**](#MAKE_MOCKn) + - [**`MAKE_STDMETHOD_MOCK(`** *name*, *signature* **`)`**](#MAKE_STDMETHOD_MOCK) - [**`MAKE_STDMETHOD_MOCKn(`** *name*, *signature* **`)`**](#MAKE_STDMETHOD_MOCKn) - [**`NAMED_ALLOW_CALL(`** *mock_object*, *func_name*(*parameter_list*)**`)`**](#NAMED_ALLOW_CALL) - [**`NAMED_FORBID_CALL(`** *mock_object*, *func_name*(*parameter_list*)**`)`**](#NAMED_FORBID_CALL) @@ -96,7 +99,9 @@ ### Mock function A *mock function* is a member function that is mocked with -[**`MAKE_MOCKn(name, signature)`**](#MAKE_MOCKn) or +[**`MAKE_MOCK(name, signature)`**](#MAKE_MOCK), +[**`MAKE_MOCKn(name, signature)`**](#MAKE_MOCKn), +[**`MAKE_CONST_MOCK(name, signature)`**](#MAKE_CONST_MOCK) or [**`MAKE_CONST_MOCKn(name, signature)`**](#MAKE_CONST_MOCKn). Example: @@ -106,12 +111,12 @@ class C { public: MAKE_MOCK1(func, void(int)); - MAKE_CONST_MOCK2(cfunc, int(std::string, int)); + MAKE_CONST_MOCK(cfunc, auto (std::string, int) -> int); }; ``` Above `C` is a type that has two mock functions `void func(int)` and -`int cfunc(std::string, int) const`. With a [mock object](#mock_object) +`auto cfunc(std::string, int) const -> int`. With a [mock object](#mock_object) of type `C` it is possible to place [expectations](#expectation) on the functions `func(...)` and `cfunc(...)`. @@ -1649,7 +1654,9 @@ you can call [mock functions](#mock_function) from those. See also [**`IMPLEMENT_MOCKn(...)`**](#IMPLEMENT_MOCKn) for non-`const` member functions. -See also [**`MAKE_MOCKn(...)`**](#MAKE_MOCKn) and +See also [**`MAKE_MOCK(...)`**](#MAKE_MOCK), +[**`MAKE_MOCKn(...)`**](#MAKE_MOCKn), +[**`MAKE_CONST_MOCK(...)`**](#MAKE_CONST_MOCK) and [**`MAKE_CONST_MOCKn(...)`**](#MAKE_CONST_MOCKn) for making mock implementations of any member functions. @@ -2136,6 +2143,74 @@ global/static objects will be modified also by those See also [**`WITH(...)`**](#WITH) which accesses copies of local objects. + + +### **`MAKE_CONST_MOCK(`** *func_name*, *signature* {, *specifiers* } **`)`** + +Make a `const` [mock function](#mock_function) named *func_name*. It is a good +idea for this to implement a pure virtual function from an interface, but +it is not a requirement. `n` is the number of parameters in *signature*. +*specifiers* is an optional list which may include attributes or specifiers like +[`override`](http://en.cppreference.com/w/cpp/language/override) or +[`noexcept`](https://en.cppreference.com/w/cpp/language/noexcept_spec). + +Because of limitations in how the preprocessor works, *signature* **must** be written with +[trailing return type syntax](https://arne-mertz.de/2016/11/trailing-return-types-everywhere/). + +`#include ` + +Example: + +```Cpp +class I +{ +public: + virtual ~I() = default; + virtual auto func1(int, const std::vector&)) const -> int = 0; +}; + +class C +{ +public: + MAKE_CONST_MOCK(func1, auto (int, const std::vector&) -> int, override); + MAKE_CONST_MOCK(func2, auto (std::string) -> int); +}; +``` + +Above, class `C` will effectively become: + +```Cpp +class C : public I +{ +public: + auto func1(int, const std::vector&) const -> int override; + auto func2(std::string) const -> int; +}; +``` + +It is not possible to mock operators, constructors or the destructor, but +you can call [mock functions](#mock_function) from those. + +**Note!** The preprocessor is limited and can only handle nullary functions, +i.e. functions that do not accept any arguments, in some cases. + +* MSVC handles nullary functions when compiling with `/Zc:preprocessor` + with MSVC 19.40 (VS 17.10) or later. + +* Gcc and Clang always handles nullary functions when compiling with + C++20 or later, and when enabling a gcc extension by defining the macro + `TROMPELOEIL_HAS_GCC_PP` before `#include`:ing the trompeloeil headers, and + compiling with `-std=gnu++11`, `-std=gnu++14` or `-std=gnu++17`. + +Otherwise, use [**`MAKE_CONST_MOCK0(...)`**](#MAKE_CONST_MOCKn) to explicitly +define a nullary mock function. + + +See also [**`MAKE_MOCK(...)`**](#MAKE_MOCK) for non-`const` +member functions, and [**`MAKE_CONST_MOCKn(...)`**](#MAKE_CONST_MOCKn) for +explicit function arity. + + ### **`MAKE_CONST_MOCKn(`** *func_name*, *signature* {, *specifiers* } **`)`** @@ -2182,7 +2257,78 @@ It is not possible to mock operators, constructors or the destructor, but you can call [mock functions](#mock_function) from those. See also [**`MAKE_MOCKn(...)`**](#MAKE_MOCKn) for non-`const` -member functions. +member functions and [**`MAKE_CONST_MOCK(...)`**`](#MAKE_CONST_MOCK) for +implicit function arity deduction. + + + + +### **`MAKE_MOCK(`** *func_name*, *signature* {, *specifiers* } **`)`** + +Make a non-const [mock function](#mock_function) named *func_name*. It is a +good idea for this to implement a pure virtual function from an interface, but +it is not a requirement. `n` is the number of parameters in *signature*. +*specifiers* is an optional list which may include attributes or specifiers like +[`override`](http://en.cppreference.com/w/cpp/language/override) or +[`noexcept`](https://en.cppreference.com/w/cpp/language/noexcept_spec). + +Because of limitations in how the preprocessor works, *signature* **must** be written with +[trailing return type syntax](https://arne-mertz.de/2016/11/trailing-return-types-everywhere/). + + +`#include ` + +Example: + +```Cpp +class I +{ +public: + virtual ~I() = default; + virtual auto func1(int, const std::vector&)) -> int = 0; +}; + +class C : public I +{ +public: + MAKE_MOCK(func1, auto (int, const std::vector&) -> int, override); + MAKE_MOCK(func2, auto (std::string) -> int); +}; +``` + +Above, class `C` will effectively become: + +```Cpp +class C : public I +{ +public: + auto func1(int, const std::vector&) -> int override; + auto func2(std::string) -> int; +}; +``` + +It is not possible to mock operators, constructors or the destructor, but +you can call [mock functions](#mock_function) from those. + +**Note!** The preprocessor is limited and can only handle nullary functions, +i.e. functions that do not accept any arguments, in some cases. + +* MSVC handles nullary functions when compiling with `/Zc:preprocessor` + with MSVC 19.40 (VS 17.10) or later. + +* Gcc and Clang always handles nullary functions when compiling with + C++20 or later, and when enabling a gcc extension by defining the macro + `TROMPELOEIL_HAS_GCC_PP` before `#include`:ing the trompeloeil headers, and + compiling with `-std=gnu++11`, `-std=gnu++14` or `-std=gnu++17`. + +Otherwise, use [**`MAKE_MOCK0(...)`**](#MAKE_MOCKn) to explicitly +define a nullary mock function. + + +See also [**`MAKE_CONST_MOCK(...)`**](#MAKE_CONST_MOCK) for `const` +member functions and [**`MAKE_MOCKn(...)`**](#MAKE_MOCKn) for explicit +function arity. + @@ -2230,7 +2376,77 @@ It is not possible to mock operators, constructors or the destructor, but you can call [mock functions](#mock_function) from those. See also [**`MAKE_CONST_MOCKn(...)`**](#MAKE_CONST_MOCKn) for `const` -member functions. +member functions and [**`MAKE_MOCK(...)`**`](#MAKE_MOCK) for implicit function +arity deduction. + + + + +### **`MAKE_STDMETHOD_MOCK(`** *func_name*, *signature* {, *specifiers* } **`)`** + +Make a STDMETHODCALLTYPE [mock function](#mock_function) named *func_name*. It is a +good idea for this to implement a pure virtual function from an interface, but +it is not a requirement. `n` is the number of parameters in *signature*. +*specifiers* is an optional list which may include attributes or specifiers like +[`override`](http://en.cppreference.com/w/cpp/language/override) or +[`noexcept`](https://en.cppreference.com/w/cpp/language/noexcept_spec). + +Because of limitations in how the preprocessor works, *signature* **must** be written with +[trailing return type syntax](https://arne-mertz.de/2016/11/trailing-return-types-everywhere/). + +`#include ` + +Example: + +```Cpp +class I +{ +public: + virtual ~I() = default; + virtual auto STDMETHODCALLTYPE func1(int, const std::vector&)) -> int = 0; +}; + +class C : public I +{ +public: + MAKE_STDMETHOD_MOCK(func1, auto (int, const std::vector&) -> int, override); + MAKE_STDMETHOD_MOCK(func2, auto (std::string) -> int); +}; +``` + +Above, class `C` will effectively become: + +```Cpp +class C : public I +{ +public: + auto STDMETHODCALLTYPE func1(int, const std::vector&) -> int override; + auto STDMETHODCALLTYPE func2(std::string) -> int; +}; +``` + +It is not possible to mock operators, constructors or the destructor, but +you can call [mock functions](#mock_function) from those. + +**NOTE!** **`MAKE_STDMETHOD_MOCK(...)`** only works on Windows. + +**NOTE!** The preprocessor is limited and can only handle nullary functions, +i.e. functions that do not accept any arguments, in some cases. + +* MSVC handles nullary functions when compiling with `/Zc:preprocessor` + with MSVC 19.40 (VS 17.10) or later. + +* Gcc and Clang always handles nullary functions when compiling with + C++20 or later, and when enabling a gcc extension by defining the macro + `TROMPELOEIL_HAS_GCC_PP` before `#include`:ing the trompeloeil headers, and + compiling with `-std=gnu++11`, `-std=gnu++14` or `-std=gnu++17`. + +Otherwise, use [**`MAKE_STDMETHOD_MOCK0(...)`**](#MAKE_STDMETHOD_MOCKn) to +explicitly define a nullary mock function. + +See also [**`MAKE_STDTMETHOD_MOCKn(...)`**](#MAKE_STDMETHOD_MOCKn) for explicit +function arity. + @@ -2258,8 +2474,8 @@ public: class C : public I { public: - MAKE_STDMETHO_MOCK2(func1, int(int, const std::vector&), override); - MAKE_STDMETHO_MOCK1(func2, int(std::string)); + MAKE_STDMETHOD_MOCK2(func1, int(int, const std::vector&), override); + MAKE_STDMETHOD_MOCK1(func2, int(std::string)); }; ``` @@ -2279,6 +2495,10 @@ you can call [mock functions](#mock_function) from those. **NOTE!** **`MAKE_STDMETHOD_MOCKn(...)`** only works on Windows. +See also [**`MAKE_STDMETHOD_MOCK(...)`**`](#MAKE_STDMETHOD_MOCK) for implicit +function arity deduction. + + ### **`NAMED_ALLOW_CALL(`** *mock_object*, *func_name*(*parameter_list*)**`)`** @@ -3036,7 +3256,8 @@ you want to mock). It enables use of the [**`IMPLEMENT_MOCKn(...)`**](#IMPLEMENT_MOCKn) and [**`IMPLEMENT_CONST_MOCKn(...)`**](#IMPLEMENT_CONST_MOCKn) macros. -The [**`MAKE_MOCKn(...)`**](#MAKE_MOCKn) and +The [**`MAKE_MOCK(...)`**](#MAKE_MOCK), [**`MAKE_MOCKn(...)`**](#MAKE_MOCKn), +[**`MAKE_CONST_MOCK(...)`**](#MAKE_CONST_MOCK) and [**`MAKE_CONST_MOCKn(...)`**](#MAKE_CONST_MOCKn) macros can also be used. The interface type `T` must not be final. diff --git a/include/trompeloeil/mock.hpp b/include/trompeloeil/mock.hpp index f7189b5..21da87d 100644 --- a/include/trompeloeil/mock.hpp +++ b/include/trompeloeil/mock.hpp @@ -122,6 +122,43 @@ #define TROMPELOEIL_NOT_IMPLEMENTED(...) __VA_ARGS__ #endif +#if defined(_MSVC_TRADITIONAL) && _MSVC_TRADITIONAL==0 +# if _MSC_VER >= 1940 +# define TROMPELOEIL_HAS_VA_OPT 1 +# else +# define TROMPELOEIL_HAS_VA_OPT 0 +# endif +# define TROMPELOEIL_MSVC_PREPROCESSOR 0 +#elif __cplusplus >= 202002L +# define TROMPELOEIL_HAS_VA_OPT 1 +#else +# define TROMPELOEIL_HAS_VA_OPT 0 +#endif + +#if TROMPELOEIL_MSVC +# if !defined(TROMPELOEIL_MSVC_PREPROCESSOR) +# define TROMPELOEIL_MSVC_PREPROCESSOR 1 +# endif +#else +# define TROMPELOEIL_MSVC_PREPROCESSOR 0 +#endif + +#define TROMPELOEIL_IDENTITY(...) __VA_ARGS__ +#define TROMPELOEIL_APPLY(f, ...) TROMPELOEIL_SEQUENCE(f, (__VA_ARGS__)) +#define TROMPELOEIL_SEQUENCE(a,b) a b +#if TROMPELOEIL_HAS_VA_OPT +# define TROMPELOEIL_COUNT(...) TROMPELOEIL_COUNT_(__VA_OPT__(__VA_ARGS__,) 15,14,13,12,11,10,9,8,7,6,5,4,3,2,1,0) +# define TROMPELOEIL_COUNT_(_0,_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12,_13,_14,_15,...) _15 +#else +# if defined (TROMPELOEIL_HAS_GCC_PP) +# define TROMPELOEIL_COUNT(...) TROMPELOEIL_APPLY(TROMPELOEIL_COUNT_,TROMPELOEIL_IDENTITY(,## __VA_ARGS__,15,14,13,12,11,10,9,8,7,6,5,4,3,2,1,0)) +# else +# define TROMPELOEIL_COUNT(...) TROMPELOEIL_APPLY(TROMPELOEIL_COUNT_,TROMPELOEIL_IDENTITY(__VA_ARGS__,16,15,14,13,12,11,10,9,8,7,6,5,4,3,2,1,0)) +# endif +# define TROMPELOEIL_COUNT_(_0,_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12,_13,_14,_15,_16,...) _16 +#endif + + #include #include #include @@ -173,25 +210,20 @@ namespace trompeloeil { using std::unique_lock; } #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 TROMPELOEIL_MSVC +#if TROMPELOEIL_MSVC_PREPROCESSOR #define TROMPELOEIL_CONCAT_(x, y, ...) x ## y __VA_ARGS__ #define TROMPELOEIL_CONCAT(x, ...) TROMPELOEIL_CONCAT_(x, __VA_ARGS__) -#else /* TROMPELOEIL_MSVC */ +#else /* TROMPELOEIL_MSVC_PREPROCESSOR */ #define TROMPELOEIL_CONCAT_(x, ...) x ## __VA_ARGS__ #define TROMPELOEIL_CONCAT(x, ...) TROMPELOEIL_CONCAT_(x, __VA_ARGS__) -#endif /* !TROMPELOEIL_MSVC */ +#endif /* !TROMPELOEIL_MSVC_PREPROCESSOR */ #define TROMPELOEIL_SEPARATE1(p1) p1 #define TROMPELOEIL_SEPARATE2(p1,p2) p1 p2 @@ -203,8 +235,9 @@ namespace trompeloeil { using std::unique_lock; } #define TROMPELOEIL_SEPARATE8(p1,...) p1 TROMPELOEIL_SEPARATE7(__VA_ARGS__) #define TROMPELOEIL_SEPARATE9(p1,...) p1 TROMPELOEIL_SEPARATE8(__VA_ARGS__) #define TROMPELOEIL_SEPARATE(...) \ - TROMPELOEIL_CONCAT(TROMPELOEIL_SEPARATE,\ - TROMPELOEIL_COUNT(__VA_ARGS__))(__VA_ARGS__) + TROMPELOEIL_APPLY(TROMPELOEIL_CONCAT, \ + TROMPELOEIL_SEPARATE, \ + TROMPELOEIL_COUNT(__VA_ARGS__))(__VA_ARGS__) #define TROMPELOEIL_REMOVE_PAREN(...) TROMPELOEIL_CONCAT(TROMPELOEIL_CLEAR_, \ @@ -263,8 +296,9 @@ namespace trompeloeil { using std::unique_lock; } #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__) + TROMPELOEIL_APPLY(TROMPELOEIL_CONCAT, \ + TROMPELOEIL_INIT_WITH_STR, \ + TROMPELOEIL_COUNT(__VA_ARGS__))(base, __VA_ARGS__) #define TROMPELOEIL_PARAM_LIST15(...) \ TROMPELOEIL_PARAM_LIST14(__VA_ARGS__), \ @@ -3332,14 +3366,10 @@ template call_matcher_list saturated{}; }; - template - return_of_t mock_func(std::false_type, P&& ...); - template return_of_t - mock_func(std::true_type, - expectations& e, + mock_func(expectations& e, char const *func_name, char const *sig_name, P&& ... p) @@ -3404,210 +3434,210 @@ template #define TROMPELOEIL_COUNT_ID(name) \ TROMPELOEIL_CONCAT(trompeloeil_c_ ## name ## _, __COUNTER__) -#if TROMPELOEIL_MSVC +#if TROMPELOEIL_MSVC_PREPROCESSOR #define TROMPELOEIL_MAKE_MOCK0(name, sig, ...) \ - TROMPELOEIL_MAKE_MOCK_(name,,,0, sig, __VA_ARGS__,,) + TROMPELOEIL_MAKE_MOCK_CHECKED(name,,,0, sig, __VA_ARGS__,,) #define TROMPELOEIL_MAKE_MOCK1(name, sig, ...) \ - TROMPELOEIL_MAKE_MOCK_(name,,,1, sig, __VA_ARGS__,,) + TROMPELOEIL_MAKE_MOCK_CHECKED(name,,,1, sig, __VA_ARGS__,,) #define TROMPELOEIL_MAKE_MOCK2(name, sig, ...) \ - TROMPELOEIL_MAKE_MOCK_(name,,,2, sig, __VA_ARGS__,,) + TROMPELOEIL_MAKE_MOCK_CHECKED(name,,,2, sig, __VA_ARGS__,,) #define TROMPELOEIL_MAKE_MOCK3(name, sig, ...) \ - TROMPELOEIL_MAKE_MOCK_(name,,,3, sig, __VA_ARGS__,,) + TROMPELOEIL_MAKE_MOCK_CHECKED(name,,,3, sig, __VA_ARGS__,,) #define TROMPELOEIL_MAKE_MOCK4(name, sig, ...) \ - TROMPELOEIL_MAKE_MOCK_(name,,,4, sig, __VA_ARGS__,,) + TROMPELOEIL_MAKE_MOCK_CHECKED(name,,,4, sig, __VA_ARGS__,,) #define TROMPELOEIL_MAKE_MOCK5(name, sig, ...) \ - TROMPELOEIL_MAKE_MOCK_(name,,,5, sig, __VA_ARGS__,,) + TROMPELOEIL_MAKE_MOCK_CHECKED(name,,,5, sig, __VA_ARGS__,,) #define TROMPELOEIL_MAKE_MOCK6(name, sig, ...) \ - TROMPELOEIL_MAKE_MOCK_(name,,,6, sig, __VA_ARGS__,,) + TROMPELOEIL_MAKE_MOCK_CHECKED(name,,,6, sig, __VA_ARGS__,,) #define TROMPELOEIL_MAKE_MOCK7(name, sig, ...) \ - TROMPELOEIL_MAKE_MOCK_(name,,,7, sig, __VA_ARGS__,,) + TROMPELOEIL_MAKE_MOCK_CHECKED(name,,,7, sig, __VA_ARGS__,,) #define TROMPELOEIL_MAKE_MOCK8(name, sig, ...) \ - TROMPELOEIL_MAKE_MOCK_(name,,,8, sig, __VA_ARGS__,,) + TROMPELOEIL_MAKE_MOCK_CHECKED(name,,,8, sig, __VA_ARGS__,,) #define TROMPELOEIL_MAKE_MOCK9(name, sig, ...) \ - TROMPELOEIL_MAKE_MOCK_(name,,,9, sig, __VA_ARGS__,,) + TROMPELOEIL_MAKE_MOCK_CHECKED(name,,,9, sig, __VA_ARGS__,,) #define TROMPELOEIL_MAKE_MOCK10(name, sig, ...) \ - TROMPELOEIL_MAKE_MOCK_(name,,,10, sig, __VA_ARGS__,,) + TROMPELOEIL_MAKE_MOCK_CHECKED(name,,,10, sig, __VA_ARGS__,,) #define TROMPELOEIL_MAKE_MOCK11(name, sig, ...) \ - TROMPELOEIL_MAKE_MOCK_(name,,,11, sig, __VA_ARGS__,,) + TROMPELOEIL_MAKE_MOCK_CHECKED(name,,,11, sig, __VA_ARGS__,,) #define TROMPELOEIL_MAKE_MOCK12(name, sig, ...) \ - TROMPELOEIL_MAKE_MOCK_(name,,,12, sig, __VA_ARGS__,,) + TROMPELOEIL_MAKE_MOCK_CHECKED(name,,,12, sig, __VA_ARGS__,,) #define TROMPELOEIL_MAKE_MOCK13(name, sig, ...) \ - TROMPELOEIL_MAKE_MOCK_(name,,,13, sig, __VA_ARGS__,,) + TROMPELOEIL_MAKE_MOCK_CHECKED(name,,,13, sig, __VA_ARGS__,,) #define TROMPELOEIL_MAKE_MOCK14(name, sig, ...) \ - TROMPELOEIL_MAKE_MOCK_(name,,,14, sig, __VA_ARGS__,,) + TROMPELOEIL_MAKE_MOCK_CHECKED(name,,,14, sig, __VA_ARGS__,,) #define TROMPELOEIL_MAKE_MOCK15(name, sig, ...) \ - TROMPELOEIL_MAKE_MOCK_(name,,,15, sig, __VA_ARGS__,,) + TROMPELOEIL_MAKE_MOCK_CHECKED(name,,,15, sig, __VA_ARGS__,,) #define TROMPELOEIL_MAKE_CONST_MOCK0(name, sig, ...) \ - TROMPELOEIL_MAKE_MOCK_(name,const,,0, sig, __VA_ARGS__,,) + TROMPELOEIL_MAKE_MOCK_CHECKED(name,const,,0, sig, __VA_ARGS__,,) #define TROMPELOEIL_MAKE_CONST_MOCK1(name, sig, ...) \ - TROMPELOEIL_MAKE_MOCK_(name,const,,1, sig, __VA_ARGS__,,) + TROMPELOEIL_MAKE_MOCK_CHECKED(name,const,,1, sig, __VA_ARGS__,,) #define TROMPELOEIL_MAKE_CONST_MOCK2(name, sig, ...) \ - TROMPELOEIL_MAKE_MOCK_(name,const,,2, sig, __VA_ARGS__,,) + TROMPELOEIL_MAKE_MOCK_CHECKED(name,const,,2, sig, __VA_ARGS__,,) #define TROMPELOEIL_MAKE_CONST_MOCK3(name, sig, ...) \ - TROMPELOEIL_MAKE_MOCK_(name,const,,3, sig, __VA_ARGS__,,) + TROMPELOEIL_MAKE_MOCK_CHECKED(name,const,,3, sig, __VA_ARGS__,,) #define TROMPELOEIL_MAKE_CONST_MOCK4(name, sig, ...) \ - TROMPELOEIL_MAKE_MOCK_(name,const,,4, sig, __VA_ARGS__,,) + TROMPELOEIL_MAKE_MOCK_CHECKED(name,const,,4, sig, __VA_ARGS__,,) #define TROMPELOEIL_MAKE_CONST_MOCK5(name, sig, ...) \ - TROMPELOEIL_MAKE_MOCK_(name,const,,5, sig, __VA_ARGS__,,) + TROMPELOEIL_MAKE_MOCK_CHECKED(name,const,,5, sig, __VA_ARGS__,,) #define TROMPELOEIL_MAKE_CONST_MOCK6(name, sig, ...) \ - TROMPELOEIL_MAKE_MOCK_(name,const,,6, sig, __VA_ARGS__,,) + TROMPELOEIL_MAKE_MOCK_CHECKED(name,const,,6, sig, __VA_ARGS__,,) #define TROMPELOEIL_MAKE_CONST_MOCK7(name, sig, ...) \ - TROMPELOEIL_MAKE_MOCK_(name,const,,7, sig, __VA_ARGS__,,) + TROMPELOEIL_MAKE_MOCK_CHECKED(name,const,,7, sig, __VA_ARGS__,,) #define TROMPELOEIL_MAKE_CONST_MOCK8(name, sig, ...) \ - TROMPELOEIL_MAKE_MOCK_(name,const,,8, sig, __VA_ARGS__,,) + TROMPELOEIL_MAKE_MOCK_CHECKED(name,const,,8, sig, __VA_ARGS__,,) #define TROMPELOEIL_MAKE_CONST_MOCK9(name, sig, ...) \ - TROMPELOEIL_MAKE_MOCK_(name,const,,9, sig, __VA_ARGS__,,) + TROMPELOEIL_MAKE_MOCK_CHECKED(name,const,,9, sig, __VA_ARGS__,,) #define TROMPELOEIL_MAKE_CONST_MOCK10(name, sig, ...) \ - TROMPELOEIL_MAKE_MOCK_(name,const,,10, sig, __VA_ARGS__,,) + TROMPELOEIL_MAKE_MOCK_CHECKED(name,const,,10, sig, __VA_ARGS__,,) #define TROMPELOEIL_MAKE_CONST_MOCK11(name, sig, ...) \ - TROMPELOEIL_MAKE_MOCK_(name,const,,11, sig, __VA_ARGS__,,) + TROMPELOEIL_MAKE_MOCK_CHECKED(name,const,,11, sig, __VA_ARGS__,,) #define TROMPELOEIL_MAKE_CONST_MOCK12(name, sig, ...) \ - TROMPELOEIL_MAKE_MOCK_(name,const,,12, sig, __VA_ARGS__,,) + TROMPELOEIL_MAKE_MOCK_CHECKED(name,const,,12, sig, __VA_ARGS__,,) #define TROMPELOEIL_MAKE_CONST_MOCK13(name, sig, ...) \ - TROMPELOEIL_MAKE_MOCK_(name,const,,13, sig, __VA_ARGS__,,) + TROMPELOEIL_MAKE_MOCK_CHECKED(name,const,,13, sig, __VA_ARGS__,,) #define TROMPELOEIL_MAKE_CONST_MOCK14(name, sig, ...) \ - TROMPELOEIL_MAKE_MOCK_(name,const,,14, sig, __VA_ARGS__,,) + TROMPELOEIL_MAKE_MOCK_CHECKED(name,const,,14, sig, __VA_ARGS__,,) #define TROMPELOEIL_MAKE_CONST_MOCK15(name, sig, ...) \ - TROMPELOEIL_MAKE_MOCK_(name,const,,15, sig, __VA_ARGS__,,) + TROMPELOEIL_MAKE_MOCK_CHECKED(name,const,,15, sig, __VA_ARGS__,,) #ifdef STDMETHODCALLTYPE #define TROMPELOEIL_MAKE_STDMETHOD_MOCK0(name, sig, ...) \ - TROMPELOEIL_MAKE_MOCK_(name,,STDMETHODCALLTYPE,0, sig, __VA_ARGS__,,) + TROMPELOEIL_MAKE_MOCK_CHECKED(name,,STDMETHODCALLTYPE,0, sig, __VA_ARGS__,,) #define TROMPELOEIL_MAKE_STDMETHOD_MOCK1(name, sig, ...) \ - TROMPELOEIL_MAKE_MOCK_(name,,STDMETHODCALLTYPE,1, sig, __VA_ARGS__,,) + TROMPELOEIL_MAKE_MOCK_CHECKED(name,,STDMETHODCALLTYPE,1, sig, __VA_ARGS__,,) #define TROMPELOEIL_MAKE_STDMETHOD_MOCK2(name, sig, ...) \ - TROMPELOEIL_MAKE_MOCK_(name,,STDMETHODCALLTYPE,2, sig, __VA_ARGS__,,) + TROMPELOEIL_MAKE_MOCK_CHECKED(name,,STDMETHODCALLTYPE,2, sig, __VA_ARGS__,,) #define TROMPELOEIL_MAKE_STDMETHOD_MOCK3(name, sig, ...) \ - TROMPELOEIL_MAKE_MOCK_(name,,STDMETHODCALLTYPE,3, sig, __VA_ARGS__,,) + TROMPELOEIL_MAKE_MOCK_CHECKED(name,,STDMETHODCALLTYPE,3, sig, __VA_ARGS__,,) #define TROMPELOEIL_MAKE_STDMETHOD_MOCK4(name, sig, ...) \ - TROMPELOEIL_MAKE_MOCK_(name,,STDMETHODCALLTYPE,4, sig, __VA_ARGS__,,) + TROMPELOEIL_MAKE_MOCK_CHECKED(name,,STDMETHODCALLTYPE,4, sig, __VA_ARGS__,,) #define TROMPELOEIL_MAKE_STDMETHOD_MOCK5(name, sig, ...) \ - TROMPELOEIL_MAKE_MOCK_(name,,STDMETHODCALLTYPE,5, sig, __VA_ARGS__,,) + TROMPELOEIL_MAKE_MOCK_CHECKED(name,,STDMETHODCALLTYPE,5, sig, __VA_ARGS__,,) #define TROMPELOEIL_MAKE_STDMETHOD_MOCK6(name, sig, ...) \ - TROMPELOEIL_MAKE_MOCK_(name,,STDMETHODCALLTYPE,6, sig, __VA_ARGS__,,) + TROMPELOEIL_MAKE_MOCK_CHECKED(name,,STDMETHODCALLTYPE,6, sig, __VA_ARGS__,,) #define TROMPELOEIL_MAKE_STDMETHOD_MOCK7(name, sig, ...) \ - TROMPELOEIL_MAKE_MOCK_(name,,STDMETHODCALLTYPE,7, sig, __VA_ARGS__,,) + TROMPELOEIL_MAKE_MOCK_CHECKED(name,,STDMETHODCALLTYPE,7, sig, __VA_ARGS__,,) #define TROMPELOEIL_MAKE_STDMETHOD_MOCK8(name, sig, ...) \ - TROMPELOEIL_MAKE_MOCK_(name,,STDMETHODCALLTYPE,8, sig, __VA_ARGS__,,) + TROMPELOEIL_MAKE_MOCK_CHECKED(name,,STDMETHODCALLTYPE,8, sig, __VA_ARGS__,,) #define TROMPELOEIL_MAKE_STDMETHOD_MOCK9(name, sig, ...) \ - TROMPELOEIL_MAKE_MOCK_(name,,STDMETHODCALLTYPE,9, sig, __VA_ARGS__,,) + TROMPELOEIL_MAKE_MOCK_CHECKED(name,,STDMETHODCALLTYPE,9, sig, __VA_ARGS__,,) #define TROMPELOEIL_MAKE_STDMETHOD_MOCK10(name, sig, ...) \ - TROMPELOEIL_MAKE_MOCK_(name,,STDMETHODCALLTYPE,10, sig, __VA_ARGS__,,) + TROMPELOEIL_MAKE_MOCK_CHECKED(name,,STDMETHODCALLTYPE,10, sig, __VA_ARGS__,,) #define TROMPELOEIL_MAKE_STDMETHOD_MOCK11(name, sig, ...) \ - TROMPELOEIL_MAKE_MOCK_(name,,STDMETHODCALLTYPE,11, sig, __VA_ARGS__,,) + TROMPELOEIL_MAKE_MOCK_CHECKED(name,,STDMETHODCALLTYPE,11, sig, __VA_ARGS__,,) #define TROMPELOEIL_MAKE_STDMETHOD_MOCK12(name, sig, ...) \ - TROMPELOEIL_MAKE_MOCK_(name,,STDMETHODCALLTYPE,12, sig, __VA_ARGS__,,) + TROMPELOEIL_MAKE_MOCK_CHECKED(name,,STDMETHODCALLTYPE,12, sig, __VA_ARGS__,,) #define TROMPELOEIL_MAKE_STDMETHOD_MOCK13(name, sig, ...) \ - TROMPELOEIL_MAKE_MOCK_(name,,STDMETHODCALLTYPE,13, sig, __VA_ARGS__,,) + TROMPELOEIL_MAKE_MOCK_CHECKED(name,,STDMETHODCALLTYPE,13, sig, __VA_ARGS__,,) #define TROMPELOEIL_MAKE_STDMETHOD_MOCK14(name, sig, ...) \ - TROMPELOEIL_MAKE_MOCK_(name,,STDMETHODCALLTYPE,14, sig, __VA_ARGS__,,) + TROMPELOEIL_MAKE_MOCK_CHECKED(name,,STDMETHODCALLTYPE,14, sig, __VA_ARGS__,,) #define TROMPELOEIL_MAKE_STDMETHOD_MOCK15(name, sig, ...) \ - TROMPELOEIL_MAKE_MOCK_(name,,STDMETHODCALLTYPE,15, sig, __VA_ARGS__,,) + TROMPELOEIL_MAKE_MOCK_CHECKED(name,,STDMETHODCALLTYPE,15, sig, __VA_ARGS__,,) #endif #else // sane standards compliant preprocessor #define TROMPELOEIL_MAKE_MOCK0(name, ...) \ - TROMPELOEIL_MAKE_MOCK_(name,,,0, __VA_ARGS__,,) + TROMPELOEIL_MAKE_MOCK_CHECKED(name,,,0, __VA_ARGS__,,) #define TROMPELOEIL_MAKE_MOCK1(name, ...) \ - TROMPELOEIL_MAKE_MOCK_(name,,,1, __VA_ARGS__,,) + TROMPELOEIL_MAKE_MOCK_CHECKED(name,,,1, __VA_ARGS__,,) #define TROMPELOEIL_MAKE_MOCK2(name, ...) \ - TROMPELOEIL_MAKE_MOCK_(name,,,2, __VA_ARGS__,,) + TROMPELOEIL_MAKE_MOCK_CHECKED(name,,,2, __VA_ARGS__,,) #define TROMPELOEIL_MAKE_MOCK3(name, ...) \ - TROMPELOEIL_MAKE_MOCK_(name,,,3, __VA_ARGS__,,) + TROMPELOEIL_MAKE_MOCK_CHECKED(name,,,3, __VA_ARGS__,,) #define TROMPELOEIL_MAKE_MOCK4(name, ...) \ - TROMPELOEIL_MAKE_MOCK_(name,,,4, __VA_ARGS__,,) + TROMPELOEIL_MAKE_MOCK_CHECKED(name,,,4, __VA_ARGS__,,) #define TROMPELOEIL_MAKE_MOCK5(name, ...) \ - TROMPELOEIL_MAKE_MOCK_(name,,,5, __VA_ARGS__,,) + TROMPELOEIL_MAKE_MOCK_CHECKED(name,,,5, __VA_ARGS__,,) #define TROMPELOEIL_MAKE_MOCK6(name, ...) \ - TROMPELOEIL_MAKE_MOCK_(name,,,6, __VA_ARGS__,,) + TROMPELOEIL_MAKE_MOCK_CHECKED(name,,,6, __VA_ARGS__,,) #define TROMPELOEIL_MAKE_MOCK7(name, ...) \ - TROMPELOEIL_MAKE_MOCK_(name,,,7, __VA_ARGS__,,) + TROMPELOEIL_MAKE_MOCK_CHECKED(name,,,7, __VA_ARGS__,,) #define TROMPELOEIL_MAKE_MOCK8(name, ...) \ - TROMPELOEIL_MAKE_MOCK_(name,,,8, __VA_ARGS__,,) + TROMPELOEIL_MAKE_MOCK_CHECKED(name,,,8, __VA_ARGS__,,) #define TROMPELOEIL_MAKE_MOCK9(name, ...) \ - TROMPELOEIL_MAKE_MOCK_(name,,,9, __VA_ARGS__,,) + TROMPELOEIL_MAKE_MOCK_CHECKED(name,,,9, __VA_ARGS__,,) #define TROMPELOEIL_MAKE_MOCK10(name, ...) \ - TROMPELOEIL_MAKE_MOCK_(name,,,10, __VA_ARGS__,,) + TROMPELOEIL_MAKE_MOCK_CHECKED(name,,,10, __VA_ARGS__,,) #define TROMPELOEIL_MAKE_MOCK11(name, ...) \ - TROMPELOEIL_MAKE_MOCK_(name,,,11, __VA_ARGS__,,) + TROMPELOEIL_MAKE_MOCK_CHECKED(name,,,11, __VA_ARGS__,,) #define TROMPELOEIL_MAKE_MOCK12(name, ...) \ - TROMPELOEIL_MAKE_MOCK_(name,,,12, __VA_ARGS__,,) + TROMPELOEIL_MAKE_MOCK_CHECKED(name,,,12, __VA_ARGS__,,) #define TROMPELOEIL_MAKE_MOCK13(name, ...) \ - TROMPELOEIL_MAKE_MOCK_(name,,,13, __VA_ARGS__,,) + TROMPELOEIL_MAKE_MOCK_CHECKED(name,,,13, __VA_ARGS__,,) #define TROMPELOEIL_MAKE_MOCK14(name, ...) \ - TROMPELOEIL_MAKE_MOCK_(name,,,14,__VA_ARGS__,,) + TROMPELOEIL_MAKE_MOCK_CHECKED(name,,,14,__VA_ARGS__,,) #define TROMPELOEIL_MAKE_MOCK15(name, ...) \ - TROMPELOEIL_MAKE_MOCK_(name,,,15, __VA_ARGS__,,) + TROMPELOEIL_MAKE_MOCK_CHECKED(name,,,15, __VA_ARGS__,,) #define TROMPELOEIL_MAKE_CONST_MOCK0(name, ...) \ - TROMPELOEIL_MAKE_MOCK_(name,const,,0, __VA_ARGS__,,) + TROMPELOEIL_MAKE_MOCK_CHECKED(name,const,,0, __VA_ARGS__,,) #define TROMPELOEIL_MAKE_CONST_MOCK1(name, ...) \ - TROMPELOEIL_MAKE_MOCK_(name,const,,1, __VA_ARGS__,,) + TROMPELOEIL_MAKE_MOCK_CHECKED(name,const,,1, __VA_ARGS__,,) #define TROMPELOEIL_MAKE_CONST_MOCK2(name, ...) \ - TROMPELOEIL_MAKE_MOCK_(name,const,,2, __VA_ARGS__,,) + TROMPELOEIL_MAKE_MOCK_CHECKED(name,const,,2, __VA_ARGS__,,) #define TROMPELOEIL_MAKE_CONST_MOCK3(name, ...) \ - TROMPELOEIL_MAKE_MOCK_(name,const,,3, __VA_ARGS__,,) + TROMPELOEIL_MAKE_MOCK_CHECKED(name,const,,3, __VA_ARGS__,,) #define TROMPELOEIL_MAKE_CONST_MOCK4(name, ...) \ - TROMPELOEIL_MAKE_MOCK_(name,const,,4, __VA_ARGS__,,) + TROMPELOEIL_MAKE_MOCK_CHECKED(name,const,,4, __VA_ARGS__,,) #define TROMPELOEIL_MAKE_CONST_MOCK5(name, ...) \ - TROMPELOEIL_MAKE_MOCK_(name,const,,5, __VA_ARGS__,,) + TROMPELOEIL_MAKE_MOCK_CHECKED(name,const,,5, __VA_ARGS__,,) #define TROMPELOEIL_MAKE_CONST_MOCK6(name, ...) \ - TROMPELOEIL_MAKE_MOCK_(name,const,,6, __VA_ARGS__,,) + TROMPELOEIL_MAKE_MOCK_CHECKED(name,const,,6, __VA_ARGS__,,) #define TROMPELOEIL_MAKE_CONST_MOCK7(name, ...) \ - TROMPELOEIL_MAKE_MOCK_(name,const,,7, __VA_ARGS__,,) + TROMPELOEIL_MAKE_MOCK_CHECKED(name,const,,7, __VA_ARGS__,,) #define TROMPELOEIL_MAKE_CONST_MOCK8(name, ...) \ - TROMPELOEIL_MAKE_MOCK_(name,const,,8, __VA_ARGS__,,) + TROMPELOEIL_MAKE_MOCK_CHECKED(name,const,,8, __VA_ARGS__,,) #define TROMPELOEIL_MAKE_CONST_MOCK9(name, ...) \ - TROMPELOEIL_MAKE_MOCK_(name,const,,9, __VA_ARGS__,,) + TROMPELOEIL_MAKE_MOCK_CHECKED(name,const,,9, __VA_ARGS__,,) #define TROMPELOEIL_MAKE_CONST_MOCK10(name, ...) \ - TROMPELOEIL_MAKE_MOCK_(name,const,,10, __VA_ARGS__,,) + TROMPELOEIL_MAKE_MOCK_CHECKED(name,const,,10, __VA_ARGS__,,) #define TROMPELOEIL_MAKE_CONST_MOCK11(name, ...) \ - TROMPELOEIL_MAKE_MOCK_(name,const,,11, __VA_ARGS__,,) + TROMPELOEIL_MAKE_MOCK_CHECKED(name,const,,11, __VA_ARGS__,,) #define TROMPELOEIL_MAKE_CONST_MOCK12(name, ...) \ - TROMPELOEIL_MAKE_MOCK_(name,const,,12, __VA_ARGS__,,) + TROMPELOEIL_MAKE_MOCK_CHECKED(name,const,,12, __VA_ARGS__,,) #define TROMPELOEIL_MAKE_CONST_MOCK13(name, ...) \ - TROMPELOEIL_MAKE_MOCK_(name,const,,13, __VA_ARGS__,,) + TROMPELOEIL_MAKE_MOCK_CHECKED(name,const,,13, __VA_ARGS__,,) #define TROMPELOEIL_MAKE_CONST_MOCK14(name, ...) \ - TROMPELOEIL_MAKE_MOCK_(name,const,,14, __VA_ARGS__,,) + TROMPELOEIL_MAKE_MOCK_CHECKED(name,const,,14, __VA_ARGS__,,) #define TROMPELOEIL_MAKE_CONST_MOCK15(name, ...) \ - TROMPELOEIL_MAKE_MOCK_(name,const,,15, __VA_ARGS__,,) + TROMPELOEIL_MAKE_MOCK_CHECKED(name,const,,15, __VA_ARGS__,,) #ifdef STDMETHODCALLTYPE #define TROMPELOEIL_MAKE_STDMETHOD_MOCK0(name, ...) \ - TROMPELOEIL_MAKE_MOCK_(name,,STDMETHODCALLTYPE,0, __VA_ARGS__,,) + TROMPELOEIL_MAKE_MOCK_CHECKED(name,,STDMETHODCALLTYPE,0, __VA_ARGS__,,) #define TROMPELOEIL_MAKE_STDMETHOD_MOCK1(name, ...) \ - TROMPELOEIL_MAKE_MOCK_(name,,STDMETHODCALLTYPE,1, __VA_ARGS__,,) + TROMPELOEIL_MAKE_MOCK_CHECKED(name,,STDMETHODCALLTYPE,1, __VA_ARGS__,,) #define TROMPELOEIL_MAKE_STDMETHOD_MOCK2(name, ...) \ - TROMPELOEIL_MAKE_MOCK_(name,,STDMETHODCALLTYPE,2, __VA_ARGS__,,) + TROMPELOEIL_MAKE_MOCK_CHECKED(name,,STDMETHODCALLTYPE,2, __VA_ARGS__,,) #define TROMPELOEIL_MAKE_STDMETHOD_MOCK3(name, ...) \ - TROMPELOEIL_MAKE_MOCK_(name,,STDMETHODCALLTYPE,3, __VA_ARGS__,,) + TROMPELOEIL_MAKE_MOCK_CHECKED(name,,STDMETHODCALLTYPE,3, __VA_ARGS__,,) #define TROMPELOEIL_MAKE_STDMETHOD_MOCK4(name, ...) \ - TROMPELOEIL_MAKE_MOCK_(name,,STDMETHODCALLTYPE,4, __VA_ARGS__,,) + TROMPELOEIL_MAKE_MOCK_CHECKED(name,,STDMETHODCALLTYPE,4, __VA_ARGS__,,) #define TROMPELOEIL_MAKE_STDMETHOD_MOCK5(name, ...) \ - TROMPELOEIL_MAKE_MOCK_(name,,STDMETHODCALLTYPE,5, __VA_ARGS__,,) + TROMPELOEIL_MAKE_MOCK_CHECKED(name,,STDMETHODCALLTYPE,5, __VA_ARGS__,,) #define TROMPELOEIL_MAKE_STDMETHOD_MOCK6(name, ...) \ - TROMPELOEIL_MAKE_MOCK_(name,,STDMETHODCALLTYPE,6, __VA_ARGS__,,) + TROMPELOEIL_MAKE_MOCK_CHECKED(name,,STDMETHODCALLTYPE,6, __VA_ARGS__,,) #define TROMPELOEIL_MAKE_STDMETHOD_MOCK7(name, ...) \ - TROMPELOEIL_MAKE_MOCK_(name,,STDMETHODCALLTYPE,7, __VA_ARGS__,,) + TROMPELOEIL_MAKE_MOCK_CHECKED(name,,STDMETHODCALLTYPE,7, __VA_ARGS__,,) #define TROMPELOEIL_MAKE_STDMETHOD_MOCK8(name, ...) \ - TROMPELOEIL_MAKE_MOCK_(name,,STDMETHODCALLTYPE,8, __VA_ARGS__,,) + TROMPELOEIL_MAKE_MOCK_CHECKED(name,,STDMETHODCALLTYPE,8, __VA_ARGS__,,) #define TROMPELOEIL_MAKE_STDMETHOD_MOCK9(name, ...) \ - TROMPELOEIL_MAKE_MOCK_(name,,STDMETHODCALLTYPE,9, __VA_ARGS__,,) + TROMPELOEIL_MAKE_MOCK_CHECKED(name,,STDMETHODCALLTYPE,9, __VA_ARGS__,,) #define TROMPELOEIL_MAKE_STDMETHOD_MOCK10(name, ...) \ - TROMPELOEIL_MAKE_MOCK_(name,,STDMETHODCALLTYPE,10, __VA_ARGS__,,) + TROMPELOEIL_MAKE_MOCK_CHECKED(name,,STDMETHODCALLTYPE,10, __VA_ARGS__,,) #define TROMPELOEIL_MAKE_STDMETHOD_MOCK11(name, ...) \ - TROMPELOEIL_MAKE_MOCK_(name,,STDMETHODCALLTYPE,11, __VA_ARGS__,,) + TROMPELOEIL_MAKE_MOCK_CHECKED(name,,STDMETHODCALLTYPE,11, __VA_ARGS__,,) #define TROMPELOEIL_MAKE_STDMETHOD_MOCK12(name, ...) \ - TROMPELOEIL_MAKE_MOCK_(name,,STDMETHODCALLTYPE,12, __VA_ARGS__,,) + TROMPELOEIL_MAKE_MOCK_CHECKED(name,,STDMETHODCALLTYPE,12, __VA_ARGS__,,) #define TROMPELOEIL_MAKE_STDMETHOD_MOCK13(name, ...) \ - TROMPELOEIL_MAKE_MOCK_(name,,STDMETHODCALLTYPE,13, __VA_ARGS__,,) + TROMPELOEIL_MAKE_MOCK_CHECKED(name,,STDMETHODCALLTYPE,13, __VA_ARGS__,,) #define TROMPELOEIL_MAKE_STDMETHOD_MOCK14(name, ...) \ - TROMPELOEIL_MAKE_MOCK_(name,,STDMETHODCALLTYPE,14, __VA_ARGS__,,) + TROMPELOEIL_MAKE_MOCK_CHECKED(name,,STDMETHODCALLTYPE,14, __VA_ARGS__,,) #define TROMPELOEIL_MAKE_STDMETHOD_MOCK15(name, ...) \ - TROMPELOEIL_MAKE_MOCK_(name,,STDMETHODCALLTYPE,15, __VA_ARGS__,,) + TROMPELOEIL_MAKE_MOCK_CHECKED(name,,STDMETHODCALLTYPE,15, __VA_ARGS__,,) #endif #endif @@ -3728,7 +3758,7 @@ template TROMPELOEIL_IDENTITY(TROMPELOEIL_IMPLEMENT_STDMETHOD_MOCK_(15, __VA_ARGS__,override)) #define TROMPELOEIL_IMPLEMENT_STDMETHOD_MOCK_(num, name, ...) \ - TROMPELOEIL_MAKE_MOCK_(name,\ + TROMPELOEIL_MAKE_MOCK_CHECKED(name,\ ,\ STDMETHODCALLTYPE,\ num,\ @@ -3736,13 +3766,28 @@ template TROMPELOEIL_SEPARATE(__VA_ARGS__),) #endif +#define TROMPELOEIL_FIRST(a,...) a +#define TROMPELOEIL_COUNT_COMMA(sig) TROMPELOEIL_IDENTITY(TROMPELOEIL_COUNT_COMMA_ ## sig) +#define TROMPELOEIL_COUNT_COMMA_auto(...) TROMPELOEIL_COUNT(__VA_ARGS__), + +#define TROMPELOEIL_CARDINALITY(sig) TROMPELOEIL_APPLY(TROMPELOEIL_FIRST, TROMPELOEIL_COUNT_COMMA(sig)) + +#define TROMPELOEIL_MAKE_MOCK(name, ...) \ + TROMPELOEIL_APPLY(TROMPELOEIL_MAKE_MOCK_, name,,,TROMPELOEIL_CARDINALITY(TROMPELOEIL_FIRST(__VA_ARGS__,)), __VA_ARGS__,,) +#define TROMPELOEIL_MAKE_CONST_MOCK(name, ...) \ + TROMPELOEIL_APPLY(TROMPELOEIL_MAKE_MOCK_, name,const,,TROMPELOEIL_CARDINALITY(TROMPELOEIL_FIRST(__VA_ARGS__,)), __VA_ARGS__,,) +#ifdef STDMETHODCALLTYPE +# define TROMPELOEIL_MAKE_STDMETHOD_MOCK(name, ...) \ + TROMPELOEIL_APPLY(TROMPELOEIL_MAKE_MOCK_, name,,STDMETHODCALLTYPE,TROMPELOEIL_CARDINALITY(TROMPELOEIL_FIRST(__VA_ARGS__,)), __VA_ARGS__,,) +#endif + +#define TROMPELOEIL_MAKE_MOCK_CHECKED(name, constness, callconv, num, sig, spec, ...) \ + static_assert(num == ::trompeloeil::param_list::size, \ + "Function signature does not have " #num " parameters"); \ + TROMPELOEIL_MAKE_MOCK_(name, constness, callconv, num, sig, spec, __VA_ARGS__) + #define TROMPELOEIL_MAKE_MOCK_(name, constness, callconv, num, sig, spec, ...) \ private: \ - using TROMPELOEIL_LINE_ID(cardinality_match) = \ - std::integral_constant::size>; \ - static_assert(TROMPELOEIL_LINE_ID(cardinality_match)::value, \ - "Function signature does not have " #num " parameters"); \ using TROMPELOEIL_LINE_ID(matcher_list_t) = \ ::trompeloeil::call_matcher_list; \ using TROMPELOEIL_LINE_ID(expectation_list_t) = \ @@ -3805,10 +3850,9 @@ template spec \ { \ return ::trompeloeil::mock_func( \ - TROMPELOEIL_LINE_ID(cardinality_match){}, \ TROMPELOEIL_LINE_ID(expectations), \ -#name, \ -#sig \ + #name, \ + #sig \ TROMPELOEIL_PARAMS(num)); \ } \ \ @@ -4174,6 +4218,7 @@ template #ifndef TROMPELOEIL_LONG_MACROS +#define MAKE_MOCK TROMPELOEIL_MAKE_MOCK #define MAKE_MOCK0 TROMPELOEIL_MAKE_MOCK0 #define MAKE_MOCK1 TROMPELOEIL_MAKE_MOCK1 #define MAKE_MOCK2 TROMPELOEIL_MAKE_MOCK2 @@ -4191,6 +4236,7 @@ template #define MAKE_MOCK14 TROMPELOEIL_MAKE_MOCK14 #define MAKE_MOCK15 TROMPELOEIL_MAKE_MOCK15 +#define MAKE_CONST_MOCK TROMPELOEIL_MAKE_CONST_MOCK #define MAKE_CONST_MOCK0 TROMPELOEIL_MAKE_CONST_MOCK0 #define MAKE_CONST_MOCK1 TROMPELOEIL_MAKE_CONST_MOCK1 #define MAKE_CONST_MOCK2 TROMPELOEIL_MAKE_CONST_MOCK2 @@ -4208,6 +4254,7 @@ template #define MAKE_CONST_MOCK14 TROMPELOEIL_MAKE_CONST_MOCK14 #define MAKE_CONST_MOCK15 TROMPELOEIL_MAKE_CONST_MOCK15 +#define MAKE_STDMETHOD_MOCK TROMPELOEIL_MAKE_STDMETHOD_MOCK #define MAKE_STDMETHOD_MOCK0 TROMPELOEIL_MAKE_STDMETHOD_MOCK0 #define MAKE_STDMETHOD_MOCK1 TROMPELOEIL_MAKE_STDMETHOD_MOCK1 #define MAKE_STDMETHOD_MOCK2 TROMPELOEIL_MAKE_STDMETHOD_MOCK2 diff --git a/test/compiling_tests.hpp b/test/compiling_tests.hpp index 3b349a5..dd77456 100644 --- a/test/compiling_tests.hpp +++ b/test/compiling_tests.hpp @@ -674,12 +674,52 @@ struct all_mock MAKE_CONST_MOCK1(cf1t, (std::pair(I<1>))); }; +struct trailing_mock +{ +#if TROMPELOEIL_HAS_VA_OPT + MAKE_MOCK(f, auto ()->int); +#endif + MAKE_MOCK(f, auto(I<1>)->int); + MAKE_MOCK(f, auto (I<1>, I<2>)->int, noexcept); + MAKE_MOCK(f, auto (I<1>, I<2>,I<3>)->int); + MAKE_MOCK(f, auto (I<1>, I<2>,I<3>,I<5>)->int); + MAKE_MOCK(f, auto (I<1>, I<2>,I<3>,I<5>,I<6>)->int); + MAKE_MOCK(f, auto (I<1>, I<2>,I<3>,I<5>,I<6>,I<7>)->int); + MAKE_MOCK(f, auto (I<1>, I<2>,I<3>,I<5>,I<6>,I<7>,I<8>)->int); + MAKE_MOCK(f, auto (I<1>, I<2>,I<3>,I<5>,I<6>,I<7>,I<8>,I<9>)->int); + MAKE_MOCK(f, auto (I<1>, I<2>,I<3>,I<5>,I<6>,I<7>,I<8>,I<9>,I<10>)->int); + MAKE_MOCK(f, auto (I<1>, I<2>,I<3>,I<5>,I<6>,I<7>,I<8>,I<9>,I<10>,I<11>)->int); + MAKE_MOCK(f, auto (I<1>, I<2>,I<3>,I<5>,I<6>,I<7>,I<8>,I<9>,I<10>,I<11>,I<12>)->int); + MAKE_MOCK(f, auto (I<1>, I<2>,I<3>,I<5>,I<6>,I<7>,I<8>,I<9>,I<10>,I<11>,I<12>,I<13>)->int); + MAKE_MOCK(f, auto (I<1>, I<2>,I<3>,I<5>,I<6>,I<7>,I<8>,I<9>,I<10>,I<11>,I<12>,I<13>,I<14>)->int); + MAKE_MOCK(f, auto (I<1>, I<2>,I<3>,I<5>,I<6>,I<7>,I<8>,I<9>,I<10>,I<11>,I<12>,I<13>,I<14>,I<15>)->int); + MAKE_MOCK(f, auto (I<1>, I<2>,I<3>,I<5>,I<6>,I<7>,I<8>,I<9>,I<10>,I<11>,I<12>,I<13>,I<14>,I<15>,I<16>)->int); +#if TROMPELOEIL_HAS_VA_OPT + MAKE_CONST_MOCK(f, auto ()->int); +#endif + MAKE_CONST_MOCK(f, auto(I<1>)->int); + MAKE_CONST_MOCK(f, auto (I<1>, I<2>)->int, noexcept); + MAKE_CONST_MOCK(f, auto (I<1>, I<2>,I<3>)->int); + MAKE_CONST_MOCK(f, auto (I<1>, I<2>,I<3>,I<5>)->int); + MAKE_CONST_MOCK(f, auto (I<1>, I<2>,I<3>,I<5>,I<6>)->int); + MAKE_CONST_MOCK(f, auto (I<1>, I<2>,I<3>,I<5>,I<6>,I<7>)->int); + MAKE_CONST_MOCK(f, auto (I<1>, I<2>,I<3>,I<5>,I<6>,I<7>,I<8>)->int); + MAKE_CONST_MOCK(f, auto (I<1>, I<2>,I<3>,I<5>,I<6>,I<7>,I<8>,I<9>)->int); + MAKE_CONST_MOCK(f, auto (I<1>, I<2>,I<3>,I<5>,I<6>,I<7>,I<8>,I<9>,I<10>)->int); + MAKE_CONST_MOCK(f, auto (I<1>, I<2>,I<3>,I<5>,I<6>,I<7>,I<8>,I<9>,I<10>,I<11>)->int); + MAKE_CONST_MOCK(f, auto (I<1>, I<2>,I<3>,I<5>,I<6>,I<7>,I<8>,I<9>,I<10>,I<11>,I<12>)->int); + MAKE_CONST_MOCK(f, auto (I<1>, I<2>,I<3>,I<5>,I<6>,I<7>,I<8>,I<9>,I<10>,I<11>,I<12>,I<13>)->int); + MAKE_CONST_MOCK(f, auto (I<1>, I<2>,I<3>,I<5>,I<6>,I<7>,I<8>,I<9>,I<10>,I<11>,I<12>,I<13>,I<14>)->int); + MAKE_CONST_MOCK(f, auto (I<1>, I<2>,I<3>,I<5>,I<6>,I<7>,I<8>,I<9>,I<10>,I<11>,I<12>,I<13>,I<14>,I<15>)->int); + MAKE_CONST_MOCK(f, auto (I<1>, I<2>,I<3>,I<5>,I<6>,I<7>,I<8>,I<9>,I<10>,I<11>,I<12>,I<13>,I<14>,I<15>,I<16>)->int); +}; + #if defined(_WIN32) struct idispatch_mock : public trompeloeil::mock_interface { IMPLEMENT_STDMETHOD_MOCK0(AddRef); IMPLEMENT_STDMETHOD_MOCK0(Release); MAKE_STDMETHOD_MOCK2(QueryInterface, HRESULT(REFIID, void **), override); - IMPLEMENT_STDMETHOD_MOCK1(GetTypeInfoCount); + MAKE_STDMETHOD_MOCK(GetTypeInfoCount, auto (UINT*)->HRESULT, override); IMPLEMENT_STDMETHOD_MOCK3(GetTypeInfo); IMPLEMENT_STDMETHOD_MOCK5(GetIDsOfNames); IMPLEMENT_STDMETHOD_MOCK8(Invoke); diff --git a/test/compiling_tests_11.cpp b/test/compiling_tests_11.cpp index 99db3d2..013bdad 100644 --- a/test/compiling_tests_11.cpp +++ b/test/compiling_tests_11.cpp @@ -6037,6 +6037,119 @@ TEST_CASE( mock.cf15(0,1,2,3,4,5,6,7,8,9,10,11,12,13,14); } +TEST_CASE_METHOD( + Fixture, + "C++11: all trailing return overloads can be mocked and called", + "[C++11][C++14][C++20]" + ) +{ + trailing_mock m; + const trailing_mock& cm = m; +#if TROMPELOEIL_HAS_VA_OPT + { + REQUIRE_CALL_V(m, f(), .RETURN(1)); + REQUIRE_CALL_V(cm, f(), .RETURN(-1)); + REQUIRE(m.f() == 1); + REQUIRE(cm.f() == -1); + } +#endif + { + REQUIRE_CALL_V(m, f(0), .RETURN(1)); + REQUIRE_CALL_V(cm, f(0), .RETURN(-1)); + REQUIRE(m.f(0) == 1); + REQUIRE(cm.f(0) == -1); + } + { + REQUIRE_CALL_V(m, f(0,1), .RETURN(1)); + REQUIRE_CALL_V(cm, f(0,1), .RETURN(-1)); + REQUIRE(m.f(0,1) == 1); + REQUIRE(cm.f(0,1) == -1); + } + { + REQUIRE_CALL_V(m, f(0,1,2), .RETURN(1)); + REQUIRE_CALL_V(cm, f(0,1,2), .RETURN(-1)); + REQUIRE(m.f(0,1,2) == 1); + REQUIRE(cm.f(0,1,2) == -1); + } + { + REQUIRE_CALL_V(m, f(0,1,2,3), .RETURN(1)); + REQUIRE_CALL_V(cm, f(0,1,2,3), .RETURN(-1)); + REQUIRE(m.f(0,1,2,3) == 1); + REQUIRE(cm.f(0,1,2,3) == -1); + } + { + REQUIRE_CALL_V(m, f(0,1,2,3,4), .RETURN(1)); + REQUIRE_CALL_V(cm, f(0,1,2,3,4), .RETURN(-1)); + REQUIRE(m.f(0,1,2,3,4) == 1); + REQUIRE(cm.f(0,1,2,3,4) == -1); + } + { + REQUIRE_CALL_V(m, f(0,1,2,3,4,5), .RETURN(1)); + REQUIRE_CALL_V(cm, f(0,1,2,3,4,5), .RETURN(-1)); + REQUIRE(m.f(0,1,2,3,4,5) == 1); + REQUIRE(cm.f(0,1,2,3,4,5) == -1); + } + { + REQUIRE_CALL_V(m, f(0,1,2,3,4,5,6), .RETURN(1)); + REQUIRE_CALL_V(cm, f(0,1,2,3,4,5,6), .RETURN(-1)); + REQUIRE(m.f(0,1,2,3,4,5,6) == 1); + REQUIRE(cm.f(0,1,2,3,4,5,6) == -1); + } + { + REQUIRE_CALL_V(m, f(0,1,2,3,4,5,6,7), .RETURN(1)); + REQUIRE_CALL_V(cm, f(0,1,2,3,4,5,6,7), .RETURN(-1)); + REQUIRE(m.f(0,1,2,3,4,5,6,7) == 1); + REQUIRE(cm.f(0,1,2,3,4,5,6,7) == -1); + } + { + REQUIRE_CALL_V(m, f(0,1,2,3,4,5,6,7,8), .RETURN(1)); + REQUIRE_CALL_V(cm, f(0,1,2,3,4,5,6,7,8), .RETURN(-1)); + REQUIRE(m.f(0,1,2,3,4,5,6,7,8) == 1); + REQUIRE(cm.f(0,1,2,3,4,5,6,7,8) == -1); + } + { + REQUIRE_CALL_V(m, f(0,1,2,3,4,5,6,7,8,9), .RETURN(1)); + REQUIRE_CALL_V(cm, f(0,1,2,3,4,5,6,7,8,9), .RETURN(-1)); + REQUIRE(m.f(0,1,2,3,4,5,6,7,8,9) == 1); + REQUIRE(cm.f(0,1,2,3,4,5,6,7,8,9) == -1); + } + { + REQUIRE_CALL_V(m, f(0,1,2,3,4,5,6,7,8,9,10), .RETURN(1)); + REQUIRE_CALL_V(cm, f(0,1,2,3,4,5,6,7,8,9,10), .RETURN(-1)); + REQUIRE(m.f(0,1,2,3,4,5,6,7,8,9,10) == 1); + REQUIRE(cm.f(0,1,2,3,4,5,6,7,8,9,10) == -1); + } + { + REQUIRE_CALL_V(m, f(0,1,2,3,4,5,6,7,8,9,10,11), .RETURN(1)); + REQUIRE_CALL_V(cm, f(0,1,2,3,4,5,6,7,8,9,10,11), .RETURN(-1)); + REQUIRE(m.f(0,1,2,3,4,5,6,7,8,9,10,11) == 1); + REQUIRE(cm.f(0,1,2,3,4,5,6,7,8,9,10,11) == -1); + } + { + REQUIRE_CALL_V(m, f(0,1,2,3,4,5,6,7,8,9,10,11,12), .RETURN(1)); + REQUIRE_CALL_V(cm, f(0,1,2,3,4,5,6,7,8,9,10,11,12), .RETURN(-1)); + REQUIRE(m.f(0,1,2,3,4,5,6,7,8,9,10,11,12) == 1); + REQUIRE(cm.f(0,1,2,3,4,5,6,7,8,9,10,11,12) == -1); + } + { + REQUIRE_CALL_V(m, f(0,1,2,3,4,5,6,7,8,9,10,11,12,13), .RETURN(1)); + REQUIRE_CALL_V(cm, f(0,1,2,3,4,5,6,7,8,9,10,11,12,13), .RETURN(-1)); + REQUIRE(m.f(0,1,2,3,4,5,6,7,8,9,10,11,12,13) == 1); + REQUIRE(cm.f(0,1,2,3,4,5,6,7,8,9,10,11,12,13) == -1); + } + { + REQUIRE_CALL_V(m, f(0,1,2,3,4,5,6,7,8,9,10,11,12,14), .RETURN(1)); + REQUIRE_CALL_V(cm, f(0,1,2,3,4,5,6,7,8,9,10,11,12,14), .RETURN(-1)); + REQUIRE(m.f(0,1,2,3,4,5,6,7,8,9,10,11,12,14) == 1); + REQUIRE(cm.f(0,1,2,3,4,5,6,7,8,9,10,11,12,14) == -1); + } + { + REQUIRE_CALL_V(m, f(0,1,2,3,4,5,6,7,8,9,10,11,12,14,15), .RETURN(1)); + REQUIRE_CALL_V(cm, f(0,1,2,3,4,5,6,7,8,9,10,11,12,14,15), .RETURN(-1)); + REQUIRE(m.f(0,1,2,3,4,5,6,7,8,9,10,11,12,14,15) == 1); + REQUIRE(cm.f(0,1,2,3,4,5,6,7,8,9,10,11,12,14,15) == -1); + } +} TEST_CASE_METHOD( Fixture, "C++11: a member function of a mock object can call a mocked function",