From e9fbf9779495f4428f2853f0260e1092a78f0162 Mon Sep 17 00:00:00 2001 From: Gregor Jasny Date: Mon, 24 Jan 2022 12:21:57 +0100 Subject: [PATCH 01/20] Disarm UBSAN for VirtualOffsetSelector cast Otherswise Clang will report the following: ``` .../include/standalone/fakeit.hpp:5337:47: runtime error: member call on address 0x7ffc27172e08 which does not point to an object of type 'rtc::test::tpsclient::ITestCaseHandler' 0x7ffc27172e08: note: object is of type 'fakeit::VirtualOffsetSelector' 00 00 00 00 38 b1 5e 00 00 00 00 00 10 c0 91 01 00 00 00 00 10 c0 91 01 00 00 00 00 f8 1d 05 01 ^~~~~~~~~~~~~~~~~~~~~~~ vptr for 'fakeit::VirtualOffsetSelector' SUMMARY: UndefinedBehaviorSanitizer: undefined-behavior .../include/standalone/fakeit.hpp:5337:47 in ``` --- include/mockutils/VTUtils.hpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/include/mockutils/VTUtils.hpp b/include/mockutils/VTUtils.hpp index 109fcdac..1a0c3458 100644 --- a/include/mockutils/VTUtils.hpp +++ b/include/mockutils/VTUtils.hpp @@ -38,6 +38,9 @@ namespace fakeit { template static typename std::enable_if::value, unsigned int>::type +#if defined(__clang__) +__attribute__((no_sanitize("undefined"))) +#endif getDestructorOffset() { VirtualOffsetSelector offsetSelctor; union_cast(&offsetSelctor)->~C(); From b2829a9db7cf7ee8e80b19bff5b95bda38f869ae Mon Sep 17 00:00:00 2001 From: Jonliu1993 <13720414433@163.com> Date: Thu, 1 Sep 2022 14:17:12 +0800 Subject: [PATCH 02/20] Add vcpkg installation instructions --- README.md | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/README.md b/README.md index 0df2c4b2..723165a3 100644 --- a/README.md +++ b/README.md @@ -161,6 +161,18 @@ run the tests by typing ./fakeit_tests.exe ``` +### Building fakeit - Using vcpkg + +You can download and install fakeit using the [vcpkg](https://github.com/Microsoft/vcpkg) dependency manager: + + git clone https://github.com/Microsoft/vcpkg.git + cd vcpkg + ./bootstrap-vcpkg.sh + ./vcpkg integrate install + ./vcpkg install fakeit + +The fakeit port in vcpkg is kept up to date by Microsoft team members and community contributors. If the version is out of date, please [create an issue or pull request](https://github.com/Microsoft/vcpkg) on the vcpkg repository. + #### Building and Running the Unit Tests with Visual Studio Open the tests/all_tests.vcxproj project file with Visual Studio. Build and run the project and check the test results. From f5276430461e279e2064d3f65bdbe1ee43c1ceac Mon Sep 17 00:00:00 2001 From: Malcolm Davey Date: Tue, 25 Oct 2022 20:43:59 +1100 Subject: [PATCH 03/20] Handle stubbing modern C++ ref overloades - partial --- include/fakeit/Mock.hpp | 36 ++++++++++++++++++++++ include/fakeit/Prototype.hpp | 33 ++++++++++++++++++-- include/fakeit/api_macros.hpp | 25 +++++++++++++++ tests/overloadded_methods_tests.cpp | 48 ++++++++++++++++++++++++++++- 4 files changed, 138 insertions(+), 4 deletions(-) diff --git a/include/fakeit/Mock.hpp b/include/fakeit/Mock.hpp index 30821951..b86166fa 100644 --- a/include/fakeit/Mock.hpp +++ b/include/fakeit/Mock.hpp @@ -57,6 +57,7 @@ namespace fakeit { return impl.stubDataMember(member, ctorargs...); } + // const non void template::value && std::is_base_of::value>::type> MockingContext stub(R (T::*vMethod)(arglist...) const) { @@ -64,6 +65,7 @@ namespace fakeit { return impl.template stubMethod(methodWithoutConstVolatile); } + // volatile non void template::value && std::is_base_of::value>::type> MockingContext stub(R(T::*vMethod)(arglist...) volatile) { @@ -71,6 +73,7 @@ namespace fakeit { return impl.template stubMethod(methodWithoutConstVolatile); } + // const volatile non void template::value && std::is_base_of::value>::type> MockingContext stub(R(T::*vMethod)(arglist...) const volatile) { @@ -78,12 +81,45 @@ namespace fakeit { return impl.template stubMethod(methodWithoutConstVolatile); } + // non void template::value && std::is_base_of::value>::type> MockingContext stub(R(T::*vMethod)(arglist...)) { return impl.template stubMethod(vMethod); } + // ref non void + template::value&& std::is_base_of::value>::type> + MockingContext stub(R(T::* vMethod)(arglist...) &) { + auto methodWithoutConstVolatile = reinterpret_cast(vMethod); + return impl.template stubMethod(methodWithoutConstVolatile); + } + + // const ref non void + template::value&& std::is_base_of::value>::type> + MockingContext stub(R(T::* vMethod)(arglist...) const&) { + auto methodWithoutConstVolatile = reinterpret_cast(vMethod); + return impl.template stubMethod(methodWithoutConstVolatile); + } + + // rref non void + template::value&& std::is_base_of::value>::type> + MockingContext stub(R(T::* vMethod)(arglist...) &&) { + auto methodWithoutConstVolatile = reinterpret_cast(vMethod); + return impl.template stubMethod(methodWithoutConstVolatile); + } + + // const rref non void + template::value&& std::is_base_of::value>::type> + MockingContext stub(R(T::* vMethod)(arglist...) const&&) { + auto methodWithoutConstVolatile = reinterpret_cast(vMethod); + return impl.template stubMethod(methodWithoutConstVolatile); + } + template::value && std::is_base_of::value>::type> MockingContext stub(R(T::*vMethod)(arglist...) const) { diff --git a/include/fakeit/Prototype.hpp b/include/fakeit/Prototype.hpp index 1170554c..82582ba4 100644 --- a/include/fakeit/Prototype.hpp +++ b/include/fakeit/Prototype.hpp @@ -12,20 +12,47 @@ namespace fakeit { typedef R ConstType(Args...) const; - template + typedef R RefType(Args...) &; + + typedef R ConstRefType(Args...) const&; + + typedef R RRefType(Args...) &&; + + typedef R ConstRRefType(Args...) const&&; + + template struct MemberType { typedef Type(C::*type); - typedef ConstType(C::*cosntType); + typedef ConstType(C::* constType); + typedef RefType(C::* refType); + typedef ConstRefType(C::* constRefType); + typedef RRefType(C::* rRefType); + typedef ConstRRefType(C::* constRRefType); static type get(type t) { return t; } - static cosntType getconst(cosntType t) { + static constType getconst(constType t) { return t; } + static refType getRef(refType t) { + return t; + } + + static constRefType getConstRef(constRefType t) { + return t; + } + + static rRefType getRRef(rRefType t) { + return t; + } + + static constRRefType getConstRRef(constRRefType t) { + return t; + } }; }; diff --git a/include/fakeit/api_macros.hpp b/include/fakeit/api_macros.hpp index 966b47af..11b140ea 100644 --- a/include/fakeit/api_macros.hpp +++ b/include/fakeit/api_macros.hpp @@ -13,6 +13,18 @@ #define CONST_OVERLOADED_METHOD_PTR(mock, method, prototype) \ fakeit::Prototype::MemberType::getconst(&MOCK_TYPE(mock)::method) +#define REF_OVERLOADED_METHOD_PTR(mock, method, prototype) \ + fakeit::Prototype::MemberType::getRef(&MOCK_TYPE(mock)::method) + +#define CONST_REF_OVERLOADED_METHOD_PTR(mock, method, prototype) \ + fakeit::Prototype::MemberType::getConstRef(&MOCK_TYPE(mock)::method) + +#define RREF_OVERLOADED_METHOD_PTR(mock, method, prototype) \ + fakeit::Prototype::MemberType::getRRef(&MOCK_TYPE(mock)::method) + +#define CONST_RREF_OVERLOADED_METHOD_PTR(mock, method, prototype) \ + fakeit::Prototype::MemberType::getConstRRef(&MOCK_TYPE(mock)::method) + #define Dtor(mock) \ (mock).dtor().setMethodDetails(#mock,"destructor") @@ -25,6 +37,19 @@ #define ConstOverloadedMethod(mock, method, prototype) \ (mock).template stub<__COUNTER__>(CONST_OVERLOADED_METHOD_PTR( mock , method, prototype )).setMethodDetails(#mock,#method) +#define RefOverloadedMethod(mock, method, prototype) \ + (mock).template stub<__COUNTER__>(REF_OVERLOADED_METHOD_PTR( mock , method, prototype )).setMethodDetails(#mock,#method) + +#define ConstRefOverloadedMethod(mock, method, prototype) \ + (mock).template stub<__COUNTER__>(CONST_REF_OVERLOADED_METHOD_PTR( mock , method, prototype )).setMethodDetails(#mock,#method) + +#define RRefOverloadedMethod(mock, method, prototype) \ + (mock).template stub<__COUNTER__>(RREF_OVERLOADED_METHOD_PTR( mock , method, prototype )).setMethodDetails(#mock,#method) + +#define ConstRRefOverloadedMethod(mock, method, prototype) \ + (mock).template stub<__COUNTER__>(CONST_RREF_OVERLOADED_METHOD_PTR( mock , method, prototype )).setMethodDetails(#mock,#method) + + #define Verify(...) \ Verify( __VA_ARGS__ ).setFileInfo(__FILE__, __LINE__, __func__) diff --git a/tests/overloadded_methods_tests.cpp b/tests/overloadded_methods_tests.cpp index 414d4580..543e7dbb 100644 --- a/tests/overloadded_methods_tests.cpp +++ b/tests/overloadded_methods_tests.cpp @@ -40,7 +40,11 @@ struct OverloadedMethods : tpunit::TestFixture { tpunit::TestFixture( TEST(OverloadedMethods::stub_overloaded_methods), TEST(OverloadedMethods::stub_const_overloaded_methods), - TEST(OverloadedMethods::stub_overloaded_methods_with_templates)) { + TEST(OverloadedMethods::stub_overloaded_methods_with_templates), + TEST(OverloadedMethods::stub_modern_overloaded_methods), + TEST(OverloadedMethods::stub_modern_rref_overloaded_method), + TEST(OverloadedMethods::stub_modern_constrref_overloaded_method) + ) { } void stub_overloaded_methods() { @@ -94,4 +98,46 @@ struct OverloadedMethods : tpunit::TestFixture { ASSERT_EQUAL(45, i.func(1)); } + struct SomeModernCppInterface { + + virtual int func() & = 0; + + virtual int func(int) & = 0; + virtual int func(int) const& = 0; + virtual int func(int) && = 0; + virtual int func(int) const&& = 0; + }; + + void stub_modern_overloaded_methods() { + + Mock mock; + When(RefOverloadedMethod(mock, func, int(int))).Return(1); + When(ConstRefOverloadedMethod(mock, func, int(int))).Return(2); + + SomeModernCppInterface& refObj = mock.get(); + const SomeModernCppInterface& refConstObj = mock.get(); + + ASSERT_EQUAL(1, refObj.func(1)); + ASSERT_EQUAL(2, refConstObj.func(1)); + } + + void stub_modern_rref_overloaded_method() { + + Mock mock; + When(RRefOverloadedMethod(mock, func, int(int))).Return(3); + + SomeModernCppInterface& refObj = mock.get(); + + ASSERT_EQUAL(3, std::move(refObj).func(1)); + } + + void stub_modern_constrref_overloaded_method() { + + Mock mock; + When(ConstRRefOverloadedMethod(mock, func, int(int))).Return(4); + + const SomeModernCppInterface& refConstObj = mock.get(); + ASSERT_EQUAL(4, std::move(refConstObj).func(1)); + } + } __OverloadedMethods; From 75e2cf4543ae7d227eee797b637dcde7574044db Mon Sep 17 00:00:00 2001 From: Franck W Date: Sun, 2 Apr 2023 14:31:46 +0200 Subject: [PATCH 04/20] Fixed spying on MSVC. --- include/fakeit/MockImpl.hpp | 29 ++++++++++++++-------- include/mockutils/DynamicProxy.hpp | 13 ++++++++++ include/mockutils/Finally.hpp | 10 +++++--- tests/spying_tests.cpp | 40 +++++++++++++++++++++++++++--- 4 files changed, 74 insertions(+), 18 deletions(-) diff --git a/include/fakeit/MockImpl.hpp b/include/fakeit/MockImpl.hpp index 7fca2b2f..c8d6e355 100644 --- a/include/fakeit/MockImpl.hpp +++ b/include/fakeit/MockImpl.hpp @@ -22,7 +22,7 @@ namespace fakeit { - + template class MockImpl : private MockObject, public virtual ActualInvocationsSource { public: @@ -107,7 +107,7 @@ namespace fakeit { private: // Keep members in this order! _proxy should be deleted before _inatanceOwner. - // Not that the dtor of MockImpl calls _proxy.detach(), hence the detach happens + // Not that the dtor of MockImpl calls _proxy.detach(), hence the detach happens // before the destructor of the _proxy is invoked. As a result the dtor method in the virtual // table of the fakedObject is reverted to unmockedDtor() before the proxy is deleted. // This way, any recorded arguments in the proxy that capture the fakeObject itself will @@ -172,7 +172,7 @@ namespace fakeit { protected: R (C::*_vMethod)(arglist...); - + public: virtual ~MethodMockingContextImpl() = default; @@ -182,11 +182,12 @@ namespace fakeit { template::value...>::value, int>::type = 0> std::function getOriginalMethodCopyArgsInternal(int) { - void *mPtr = MethodMockingContextBase::_mock.getOriginalMethod(_vMethod); + auto mPtr = _vMethod; + auto& mock = MethodMockingContextBase::_mock; C * instance = &(MethodMockingContextBase::_mock.get()); - return [=](arglist&... args) -> R { - auto m = union_cast::type>(mPtr); - return m(instance, args...); + return [=, &mock](arglist&... args) -> R { + auto methodSwapper = mock.createRaiiMethodSwapper(mPtr); + return (instance->*mPtr)(args...); }; } @@ -202,11 +203,12 @@ namespace fakeit { } std::function getOriginalMethodForwardArgs() override { - void *mPtr = MethodMockingContextBase::_mock.getOriginalMethod(_vMethod); + auto mPtr = _vMethod; + auto& mock = MethodMockingContextBase::_mock; C * instance = &(MethodMockingContextBase::_mock.get()); - return [=](arglist&... args) -> R { - auto m = union_cast::type>(mPtr); - return m(instance, std::forward(args)...); + return [=, &mock](arglist&... args) -> R { + auto methodSwapper = mock.createRaiiMethodSwapper(mPtr); + return (instance->*mPtr)(std::forward(args)...); }; } }; @@ -289,6 +291,11 @@ namespace fakeit { return reinterpret_cast(fake); } + template + Finally createRaiiMethodSwapper(R(C::*vMethod)(arglist...)) { + return _proxy.createRaiiMethodSwapper(vMethod); + } + template void *getOriginalMethod(R (C::*vMethod)(arglist...)) { auto vt = _proxy.getOriginalVT(); diff --git a/include/mockutils/DynamicProxy.hpp b/include/mockutils/DynamicProxy.hpp index b3a735fb..424b42ac 100644 --- a/include/mockutils/DynamicProxy.hpp +++ b/include/mockutils/DynamicProxy.hpp @@ -20,6 +20,7 @@ #include "mockutils/MethodInvocationHandler.hpp" #include "mockutils/VTUtils.hpp" #include "mockutils/FakeObject.hpp" +#include "mockutils/Finally.hpp" #include "mockutils/MethodProxy.hpp" #include "mockutils/MethodProxyCreator.hpp" @@ -163,6 +164,18 @@ namespace fakeit { return vt; } + template + Finally createRaiiMethodSwapper(R(C::*vMethod)(arglist...)) { + auto offset = VTUtils::getOffset(vMethod); + auto fakeMethod = getFake().getVirtualTable().getMethod(offset); + auto originalMethod = getOriginalVT().getMethod(offset); + + getFake().setMethod(offset, originalMethod); + return Finally{[&, offset, fakeMethod](){ + getFake().setMethod(offset, fakeMethod); + }}; + } + private: template diff --git a/include/mockutils/Finally.hpp b/include/mockutils/Finally.hpp index 57e7c6db..cf227fb1 100644 --- a/include/mockutils/Finally.hpp +++ b/include/mockutils/Finally.hpp @@ -3,7 +3,7 @@ * Copyright (c) 2014 Eran Pe'er. * * This program is made available under the terms of the MIT License. - * + * * Created on Aug 30, 2014 */ #pragma once @@ -16,15 +16,19 @@ namespace fakeit { private: std::function _finallyClause; - Finally(const Finally &); + Finally(const Finally &) = delete; - Finally &operator=(const Finally &); + Finally &operator=(const Finally &) = delete; public: explicit Finally(std::function f) : _finallyClause(f) { } + Finally(Finally&& other) { + _finallyClause.swap(other._finallyClause); + } + ~Finally() { _finallyClause(); } diff --git a/tests/spying_tests.cpp b/tests/spying_tests.cpp index 45f54f54..2d691704 100644 --- a/tests/spying_tests.cpp +++ b/tests/spying_tests.cpp @@ -30,7 +30,8 @@ struct SpyingTests: tpunit::TestFixture { TEST(SpyingTests::spyThenVerifyValueArg), TEST(SpyingTests::spyMoveOnlyPassedByRef), TEST(SpyingTests::spyMoveOnlyWithoutVerify), - TEST(SpyingTests::spyVectorOfMoveOnly) + TEST(SpyingTests::spyVectorOfMoveOnly), + TEST(SpyingTests::spyWorksWithDerivedClasses) // ) // { @@ -50,9 +51,12 @@ struct SpyingTests: tpunit::TestFixture { virtual int func1(int arg) { return arg; } - virtual int func2(int arg) { - return arg; - } + virtual int func2(int arg) { + return arg; + } + virtual int func3(int arg) { + return arg; + } virtual void proc(){ } virtual std::string funcTakeByValue(std::string arg) { @@ -73,6 +77,19 @@ struct SpyingTests: tpunit::TestFixture { } }; + class DerivedClass : public SomeClass { + public: + int func1(int arg) override { + return arg * 2; + } + int func2(int arg) override { + return arg * 2; + } + int func3(int arg) override { + return arg * 2; + } + }; + void useOriginalClassMethodIfNotFaked() { SomeClass obj; Mock spy(obj); @@ -262,4 +279,19 @@ struct SpyingTests: tpunit::TestFixture { ASSERT_EQUAL(15, i.funcVectorOfMoveOnly(testutils::multi_emplace(std::vector{}, MoveOnlyType{5}, MoveOnlyType{10}))); } + void spyWorksWithDerivedClasses() { + DerivedClass derived; + SomeClass& objRef = derived; + Mock spy(objRef); + Spy(Method(spy,func1)); + Fake(Method(spy,func2)); + ASSERT_EQUAL(2, objRef.func1(1)); // spied, should call original + ASSERT_EQUAL(0, objRef.func2(1)); // mocked, should call default impl + ASSERT_EQUAL(2, objRef.func3(1)); // not spied nor mocked, should call original + + Verify(Method(spy,func1).Using(1)).Once(); + Verify(Method(spy,func2).Using(1)).Once(); + VerifyNoOtherInvocations(spy); + } + } __SpyingTests; From f26afcccde3c93db1cf352a23b7683bceef72c3d Mon Sep 17 00:00:00 2001 From: Franck W Date: Sun, 2 Apr 2023 10:52:57 +0200 Subject: [PATCH 05/20] Fixed dtor mocking on MSVC. --- include/mockutils/DynamicProxy.hpp | 10 ++++++++++ include/mockutils/MethodProxyCreator.hpp | 19 +++++++++++++++++++ 2 files changed, 29 insertions(+) diff --git a/include/mockutils/DynamicProxy.hpp b/include/mockutils/DynamicProxy.hpp index 424b42ac..0d06a715 100644 --- a/include/mockutils/DynamicProxy.hpp +++ b/include/mockutils/DynamicProxy.hpp @@ -111,7 +111,17 @@ namespace fakeit { void stubDtor(MethodInvocationHandler *methodInvocationHandler) { auto offset = VTUtils::getDestructorOffset(); MethodProxyCreator creator; + // MSVC use an indirection for destructors, the "initial" destructor (VirtualTable::dtor, an helper) will be + // called through a member-function call, but the "final" destructor (the method proxy) will be called through + // a free-function call (inside the initial destructor). Therefor we use the free-function version + // (static method, but it's the same) of MethodProxy. + // For GCC / Clang, the destructor is directly called, like normal methods, so we use the member-function + // version. +#ifdef _MSC_VER + bindDtor(creator.createMethodProxyStatic<0>(offset), methodInvocationHandler); +#else bindDtor(creator.createMethodProxy<0>(offset), methodInvocationHandler); +#endif } template diff --git a/include/mockutils/MethodProxyCreator.hpp b/include/mockutils/MethodProxyCreator.hpp index b37c645e..3d80b21f 100644 --- a/include/mockutils/MethodProxyCreator.hpp +++ b/include/mockutils/MethodProxyCreator.hpp @@ -34,6 +34,11 @@ namespace fakeit { return MethodProxy(id, offset, union_cast(&MethodProxyCreator::methodProxyX < id > )); } + template + MethodProxy createMethodProxyStatic(unsigned int offset) { + return MethodProxy(id, offset, union_cast(&MethodProxyCreator::methodProxyXStatic < id > )); + } + protected: R methodProxy(unsigned int id, const typename fakeit::production_arg::type... args) { @@ -49,5 +54,19 @@ namespace fakeit { R methodProxyX(arglist ... args) { return methodProxy(id, std::forward::type>(args)...); } + + static R methodProxyStatic(void* instance, unsigned int id, const typename fakeit::production_arg::type... args) { + InvocationHandlerCollection *invocationHandlerCollection = InvocationHandlerCollection::getInvocationHandlerCollection( + instance); + MethodInvocationHandler *invocationHandler = + (MethodInvocationHandler *) invocationHandlerCollection->getInvocatoinHandlerPtrById( + id); + return invocationHandler->handleMethodInvocation(std::forward::type>(args)...); + } + + template + static R methodProxyXStatic(void* instance, arglist ... args) { + return methodProxyStatic(instance, id, std::forward::type>(args)...); + } }; } From bdd884e2b9dc2b6dc9d6d8def8e09f5a39a10d1a Mon Sep 17 00:00:00 2001 From: Franck W Date: Sun, 2 Apr 2023 19:52:41 +0200 Subject: [PATCH 06/20] Added a lot more configurations in the CI, and fixed some stuff. - Added more versions of GCC and Clang. - Tests now run for MSVC. - Test several C++ standard instead of only the default one of the compiler. - Test are not ran by default, their building need to be enabled manually. - Disabled appveyor. --- .github/workflows/ci_linux_clang.yml | 77 ++++++++++++++++++---- .github/workflows/ci_linux_gcc.yml | 95 ++++++++++++++++----------- .github/workflows/ci_windows_msvc.yml | 65 +++++++++++++----- .github/workflows/coverage.yml | 38 +++++++++++ CMakeLists.txt | 8 ++- README.md | 6 +- appveyor.yml | 1 + tests/CMakeLists.txt | 5 ++ 8 files changed, 222 insertions(+), 73 deletions(-) create mode 100644 .github/workflows/coverage.yml create mode 100644 appveyor.yml diff --git a/.github/workflows/ci_linux_clang.yml b/.github/workflows/ci_linux_clang.yml index 1e6ec203..2f13d7db 100644 --- a/.github/workflows/ci_linux_clang.yml +++ b/.github/workflows/ci_linux_clang.yml @@ -9,24 +9,73 @@ defaults: shell: bash jobs: - clang-ubuntu-20-04: - runs-on: ubuntu-20.04 + build: + name: ${{ matrix.config.name }} + runs-on: ${{ matrix.config.os }} + strategy: + fail-fast: false + matrix: + config: + - { + name: "Ubuntu 20.04 Clang 10", + os: ubuntu-20.04, + build_type: Debug, + cc: "clang-10", cxx: "clang++-10" + } + - { + name: "Ubuntu 20.04 Clang 11", + os: ubuntu-20.04, + build_type: Debug, + cc: "clang-11", cxx: "clang++-11" + } + - { + name: "Ubuntu 20.04 Clang 12", + os: ubuntu-20.04, + build_type: Debug, + cc: "clang-12", cxx: "clang++-12" + } + - { + name: "Ubuntu 22.04 Clang 13", + os: ubuntu-22.04, + build_type: Debug, + cc: "clang-13", cxx: "clang++-13" + } + - { + name: "Ubuntu 22.04 Clang 14 C++11", + os: ubuntu-22.04, + build_type: Debug, + cc: "clang-14", cxx: "clang++-14", + cxx_standard: 11 + } + - { + name: "Ubuntu 22.04 Clang 14 C++14", + os: ubuntu-22.04, + build_type: Debug, + cc: "clang-14", cxx: "clang++-14", + cxx_standard: 14 + } + - { + name: "Ubuntu 22.04 Clang 14 C++17", + os: ubuntu-22.04, + build_type: Debug, + cc: "clang-14", cxx: "clang++-14", + cxx_standard: 17 + } + - { + name: "Ubuntu 22.04 Clang 14 C++20", + os: ubuntu-22.04, + build_type: Debug, + cc: "clang-14", cxx: "clang++-14", + cxx_standard: 20 + } steps: - uses: actions/checkout@v2 - name: Build project + env: + CC: ${{ matrix.config.cc }} + CXX: ${{ matrix.config.cxx }} run: | - CC=clang CXX=clang++ cmake -S . -B build -DCMAKE_BUILD_TYPE=Debug - cmake --build build -j - - name: Run tests - run: | - build/tests/FakeIt_tests - clang-ubuntu-18-04: - runs-on: ubuntu-18.04 - steps: - - uses: actions/checkout@v2 - - name: Build project - run: | - CC=clang CXX=clang++ cmake -S . -B build -DCMAKE_BUILD_TYPE=Debug + cmake -S . -B build -DCMAKE_BUILD_TYPE=${{ matrix.config.build_type }} -DENABLE_TESTING=ON -DOVERRIDE_CXX_STANDARD_FOR_TESTS=${{ matrix.config.cxx_standard }} cmake --build build -j - name: Run tests run: | diff --git a/.github/workflows/ci_linux_gcc.yml b/.github/workflows/ci_linux_gcc.yml index 3196117b..b2ba4e02 100644 --- a/.github/workflows/ci_linux_gcc.yml +++ b/.github/workflows/ci_linux_gcc.yml @@ -9,48 +9,67 @@ defaults: shell: bash jobs: - coverage: - runs-on: ubuntu-20.04 + build: + name: ${{ matrix.config.name }} + runs-on: ${{ matrix.config.os }} + strategy: + fail-fast: false + matrix: + config: + - { + name: "Ubuntu 20.04 GCC 9", + os: ubuntu-20.04, + build_type: Debug, + cc: "gcc-9", cxx: "g++-9" + } + - { + name: "Ubuntu 20.04 GCC 10", + os: ubuntu-20.04, + build_type: Debug, + cc: "gcc-10", cxx: "g++-10" + } + - { + name: "Ubuntu 22.04 GCC 11", + os: ubuntu-22.04, + build_type: Debug, + cc: "gcc-11", cxx: "g++-11" + } + - { + name: "Ubuntu 22.04 GCC 12 C++11", + os: ubuntu-22.04, + build_type: Debug, + cc: "gcc-12", cxx: "g++-12", + cxx_standard: 11 + } + - { + name: "Ubuntu 22.04 GCC 12 C++14", + os: ubuntu-22.04, + build_type: Debug, + cc: "gcc-12", cxx: "g++-12", + cxx_standard: 14 + } + - { + name: "Ubuntu 22.04 GCC 12 C++17", + os: ubuntu-22.04, + build_type: Debug, + cc: "gcc-12", cxx: "g++-12", + cxx_standard: 17 + } + - { + name: "Ubuntu 22.04 GCC 12 C++20", + os: ubuntu-22.04, + build_type: Debug, + cc: "gcc-12", cxx: "g++-12", + cxx_standard: 20 + } steps: - - name: Install LCOV - run: sudo apt install -y lcov - uses: actions/checkout@v2 - name: Build project + env: + CC: ${{ matrix.config.cc }} + CXX: ${{ matrix.config.cxx }} run: | - CC=gcc CXX=g++ cmake -S . -B build -DCMAKE_BUILD_TYPE=Debug -DENABLE_COVERAGE=ON - cmake --build build -j - - name: Run tests - run: | - build/tests/FakeIt_tests - - name: Generate report - run: | - cd build/tests/CMakeFiles/FakeIt_tests.dir - gcov *.o - lcov --directory . -c -o report.info - lcov --remove report.info '/usr/*' '*/tests/*' -o report_filtered.info - - name: Upload report - uses: coverallsapp/github-action@master - with: - github-token: ${{ secrets.GITHUB_TOKEN }} - path-to-lcov: ./build/tests/CMakeFiles/FakeIt_tests.dir/report_filtered.info - gcc-ubuntu-20-04: - runs-on: ubuntu-20.04 - steps: - - uses: actions/checkout@v2 - - name: Build project - run: | - CC=gcc CXX=g++ cmake -S . -B build -DCMAKE_BUILD_TYPE=Debug - cmake --build build -j - - name: Run tests - run: | - build/tests/FakeIt_tests - gcc-ubuntu-18-04: - runs-on: ubuntu-18.04 - steps: - - uses: actions/checkout@v2 - - name: Build project - run: | - CC=gcc CXX=g++ cmake -S . -B build -DCMAKE_BUILD_TYPE=Debug + cmake -S . -B build -DCMAKE_BUILD_TYPE=${{ matrix.config.build_type }} -DENABLE_TESTING=ON -DOVERRIDE_CXX_STANDARD_FOR_TESTS=${{ matrix.config.cxx_standard }} cmake --build build -j - name: Run tests run: | diff --git a/.github/workflows/ci_windows_msvc.yml b/.github/workflows/ci_windows_msvc.yml index abc34090..65e5a865 100644 --- a/.github/workflows/ci_windows_msvc.yml +++ b/.github/workflows/ci_windows_msvc.yml @@ -9,25 +9,58 @@ defaults: shell: bash jobs: - msvc-windows-2022: - runs-on: windows-2022 + build: + name: ${{ matrix.config.name }} + runs-on: ${{ matrix.config.os }} + strategy: + fail-fast: false + matrix: + config: + - { + name: "Windows 2019 MSVC 2019 Win32", + os: windows-2019, + build_type: Debug, + generator: "Visual Studio 16 2019", + architecture: "Win32" + } + - { + name: "Windows 2022 MSVC 2022 Win32 C++11", + os: windows-2022, + build_type: Debug, + generator: "Visual Studio 17 2022", + architecture: "Win32", + cxx_standard: 11 + } + - { + name: "Windows 2022 MSVC 2022 Win32 C++14", + os: windows-2022, + build_type: Debug, + generator: "Visual Studio 17 2022", + architecture: "Win32", + cxx_standard: 14 + } + - { + name: "Windows 2022 MSVC 2022 Win32 C++17", + os: windows-2022, + build_type: Debug, + generator: "Visual Studio 17 2022", + architecture: "Win32", + cxx_standard: 17 + } + - { + name: "Windows 2022 MSVC 2022 Win32 C++20", + os: windows-2022, + build_type: Debug, + generator: "Visual Studio 17 2022", + architecture: "Win32", + cxx_standard: 20 + } steps: - uses: actions/checkout@v2 - name: Build project run: | - cmake -S . -B build -G "Visual Studio 17 2022" - cmake --build build --config Debug -j + cmake -S . -B build -G "${{ matrix.config.generator }}" -A ${{ matrix.config.architecture }} -DENABLE_TESTING=ON -DOVERRIDE_CXX_STANDARD_FOR_TESTS=${{ matrix.config.cxx_standard }} + cmake --build build --config ${{ matrix.config.build_type }} -j - name: Run tests run: | - echo "Not yet because bugged but it needs to be fixed." - msvc-windows-2019: - runs-on: windows-2019 - steps: - - uses: actions/checkout@v2 - - name: Build project - run: | - cmake -S . -B build -G "Visual Studio 16 2019" - cmake --build build --config Debug -j - - name: Run tests - run: | - echo "Not yet because bugged but it needs to be fixed." + build/tests/Debug/FakeIt_tests.exe diff --git a/.github/workflows/coverage.yml b/.github/workflows/coverage.yml new file mode 100644 index 00000000..c18103a7 --- /dev/null +++ b/.github/workflows/coverage.yml @@ -0,0 +1,38 @@ +name: Coverage + +on: + push: + pull_request: + +defaults: + run: + shell: bash + +jobs: + coverage: + runs-on: ubuntu-20.04 + steps: + - name: Install LCOV + run: sudo apt install -y lcov + - uses: actions/checkout@v2 + - name: Build project + env: + CC: gcc-9 + CXX: g++-9 + run: | + cmake -S . -B build -DCMAKE_BUILD_TYPE=Debug -DENABLE_TESTING=ON -DENABLE_COVERAGE=ON + cmake --build build -j + - name: Run tests + run: | + build/tests/FakeIt_tests + - name: Generate report + run: | + cd build/tests/CMakeFiles/FakeIt_tests.dir + gcov-9 *.o + lcov --gcov-tool gcov-9 --directory . -c -o report.info + lcov --gcov-tool gcov-9 --remove report.info '/usr/*' '*/tests/*' -o report_filtered.info + - name: Upload report + uses: coverallsapp/github-action@master + with: + github-token: ${{ secrets.GITHUB_TOKEN }} + path-to-lcov: ./build/tests/CMakeFiles/FakeIt_tests.dir/report_filtered.info diff --git a/CMakeLists.txt b/CMakeLists.txt index 1bb39311..f94a3f85 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -4,6 +4,8 @@ cmake_minimum_required(VERSION 3.14) project(FakeIt VERSION 2.3.2 LANGUAGES CXX) option(ENABLE_COVERAGE "Enable coverage reporting for gcc/clang." OFF) +option(ENABLE_TESTING "Enable build of tests." OFF) +option(OVERRIDE_CXX_STANDARD_FOR_TESTS "Override the C++ standard used for building tests." "") # Directory containing main targets of FakeIt. add_subdirectory(include) @@ -11,8 +13,10 @@ add_subdirectory(include) # Directory containing config targets of FakeIt. add_subdirectory(config) -# Directory containing test targets of FakeIt. -add_subdirectory(tests) +if(ENABLE_TESTING) + # Directory containing test targets of FakeIt. + add_subdirectory(tests) +endif() # Directory containing single header targets of FakeIt. add_subdirectory(single_header) diff --git a/README.md b/README.md index 326c8118..5a817372 100644 --- a/README.md +++ b/README.md @@ -124,7 +124,7 @@ For GCC, it is recommended to build the test project with -O1 or -O0 flags. Some #### Building and Running the Unit Tests with GCC ``` -CC=gcc CXX=g++ cmake -S . -B build -DCMAKE_BUILD_TYPE=Debug +CC=gcc CXX=g++ cmake -S . -B build -DCMAKE_BUILD_TYPE=Debug -DENABLE_TESTING=ON cmake --build build -j ``` Run the tests by typing: @@ -134,7 +134,7 @@ Run the tests by typing: #### Building and Running the Unit Tests with Clang ``` -CC=clang CXX=clang++ cmake -S . -B build -DCMAKE_BUILD_TYPE=Debug +CC=clang CXX=clang++ cmake -S . -B build -DCMAKE_BUILD_TYPE=Debug -DENABLE_TESTING=ON cmake --build build -j ``` Run the tests by typing: @@ -144,7 +144,7 @@ Run the tests by typing: #### Building and Running the Unit Tests with Visual Studio ``` -cmake -S . -B build -G "Visual Studio 17 2022" +cmake -S . -B build -G "Visual Studio 17 2022" -DENABLE_TESTING=ON cmake --build build --config Debug -j ``` Run the tests by typing: diff --git a/appveyor.yml b/appveyor.yml new file mode 100644 index 00000000..4dd7b0a3 --- /dev/null +++ b/appveyor.yml @@ -0,0 +1 @@ +build: off diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 5a0fc555..fb77acc1 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -40,6 +40,11 @@ elseif(MSVC) target_compile_options(FakeIt_tests PRIVATE /W3 /sdl /Od) endif() +if(OVERRIDE_CXX_STANDARD_FOR_TESTS) + set_target_properties(FakeIt_tests PROPERTIES CXX_STANDARD ${OVERRIDE_CXX_STANDARD_FOR_TESTS}) + message(STATUS "Building tests in C++${OVERRIDE_CXX_STANDARD_FOR_TESTS}.") +endif() + if(ENABLE_COVERAGE) if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU" OR CMAKE_CXX_COMPILER_ID MATCHES "^(Apple)?Clang$") target_compile_options(FakeIt_tests PRIVATE --coverage) From e849ea47f614bb18c9afa0533d39896fd27f130e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20Sch=C3=A4rf?= Date: Thu, 6 Apr 2023 15:29:24 +0200 Subject: [PATCH 07/20] Provide CMake option to disable building tests This is useful when FakeIt is imported via FetchContent. In this case, building FakeIt tests along with your project is probably not desired. --- CMakeLists.txt | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 1bb39311..4d70ea16 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -4,6 +4,7 @@ cmake_minimum_required(VERSION 3.14) project(FakeIt VERSION 2.3.2 LANGUAGES CXX) option(ENABLE_COVERAGE "Enable coverage reporting for gcc/clang." OFF) +option(ENABLE_TESTING "Enable building unit tests" ON) # Directory containing main targets of FakeIt. add_subdirectory(include) @@ -12,7 +13,9 @@ add_subdirectory(include) add_subdirectory(config) # Directory containing test targets of FakeIt. -add_subdirectory(tests) +if(${ENABLE_TESTING}) + add_subdirectory(tests) +endif() # Directory containing single header targets of FakeIt. add_subdirectory(single_header) From 5153735c1886e720a889ed096d001fb00096ff62 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20Sch=C3=A4rf?= Date: Thu, 6 Apr 2023 15:29:58 +0200 Subject: [PATCH 08/20] Set single headers as system includes This causes compiler warnings originating from FakeIt includes to be suppressed when using target_link_libraries() --- single_header/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/single_header/CMakeLists.txt b/single_header/CMakeLists.txt index e9a81ad9..4dbf753c 100644 --- a/single_header/CMakeLists.txt +++ b/single_header/CMakeLists.txt @@ -8,7 +8,7 @@ function(add_configuration config_name) # Add include directories to the interface library. # If we use FakeIt from build-tree then we use BUILD_INTERFACE wrapper. # If we use FakeIt from install-tree then we use INSTALL_INTERFACE wrapper. - target_include_directories(FakeIt-${config_name} INTERFACE + target_include_directories(FakeIt-${config_name} SYSTEM INTERFACE $ $ ) From 7f62f6fc27b954dd54c4938d677788041a899b8d Mon Sep 17 00:00:00 2001 From: Franck W Date: Thu, 6 Apr 2023 20:23:29 +0200 Subject: [PATCH 09/20] Added more installation instructions in README and updated CONTRIBUTING.md. --- CONTRIBUTING.md | 7 ++-- README.md | 94 +++++++++++++++++++++++++++++++++++-------------- 2 files changed, 72 insertions(+), 29 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index e1247685..7d33a465 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,3 +1,4 @@ -Don't generate single header files in your pull request, only modify the original files (the ones inside the `include` folder). - -Add unit tests for your development or at least provide examples on how to test your changes in your pull request. +When submitting a pull request, you should follow these rules: +* Base your developments on the `dev` branch. +* Don't generate single header files in your pull request, only modify the original files (the ones inside the `include` folder). +* Add unit tests for your development or at least provide examples on how to test your changes in your pull request. diff --git a/README.md b/README.md index fca2284f..d57a46ad 100644 --- a/README.md +++ b/README.md @@ -75,6 +75,22 @@ FakeIt is pre-configured to work with some of the major unit testing frameworks. If you don't find your unit testing framework on the list, simply use the *standalone* configuration. + +### Configurations' name + +Here's the list of each unit testing framework FakeIt is pre-configured with and the name of the respective configuration to use if you want FakeIt to integrate with them (if your favorite unit testing framework is not on the list, simply use the `standalone` configuration): +* GoogleTest: `gtest` +* MSTest: `mstest` +* Boost.Test: `boost` +* Catch2: `catch` +* tpunit++: `tpunit` +* mettle: `mettle` +* Qt Test: `qtest` +* NUnit: `nunit` +* CUTE: `cute` +* doctest: `doctest` +* Without a unit test framework: `standalone` + ### Using a pre-packaged single header file Pre-packaged single header versions of FakeIt are located under the *single_header* folder. Depending on the unit testing framework you use, simply add one of the pre-packaged versions to the include path of your test project: @@ -104,45 +120,49 @@ For example: ``` -I"/include" -I"/config/gtest" ``` -* For every other unit test framework (or for using FakeIt without a unit test framework), just replace `gtest` by the name of the configuration: - * GoogleTest: `gtest` - * MSTest: `mstest` - * Boost.Test: `boost` - * Catch2: `catch` - * tpunit++: `tpunit` - * mettle: `mettle` - * Qt Test: `qtest` - * NUnit: `nunit` - * CUTE: `cute` - * doctest: `doctest` - * Without a unit test framework: `standalone` +* For every other unit test framework (or for using FakeIt without a unit test framework), just replace `gtest` by the name of the configuration (see `Configurations' name` section for details). * If you use FakeIt with **NUnit** in a managed Visual Studio C++/CLI project, note that it is useful to define your mocks in `#pragma unmanaged` sections so that you can use lambda expressions. It is recommended to build and run the unit tests to make sure FakeIt fits your environment. For GCC, it is recommended to build the test project with -O1 or -O0 flags. Some features of FakeIt may not work with stronger optimizations!! -#### Building and Running the Unit Tests with GCC -``` -CC=gcc CXX=g++ cmake -S . -B build -DCMAKE_BUILD_TYPE=Debug -DENABLE_TESTING=ON -cmake --build build -j +### Installing FakeIt with CMake + +Clone the repository, `cd` into it then execute the following commands: ``` -Run the tests by typing: -``` -./build/tests/FakeIt_tests +cmake -S . -B build -DCMAKE_INSTALL_PREFIX= +cmake --build build +cmake --install build ``` -#### Building and Running the Unit Tests with Clang +Replace `` by the path of the directory where you want to install FakeIt. + +Then in your project's `CMakeLists.txt`: ``` -CC=clang CXX=clang++ cmake -S . -B build -DCMAKE_BUILD_TYPE=Debug -DENABLE_TESTING=ON -cmake --build build -j +find_package(FakeIt REQUIRED) +[...] +target_link_libraries( PRIVATE FakeIt::FakeIt-) ``` -Run the tests by typing: + +Where `` is the name of the target you want to link FakeIt with, and `` is the name of the specific configuration you want to use (see `Configurations' name` section for details). + +Then, when you'll invoke CMake's configure command, pass the argument `-DFakeIt_ROOT=`, with `` being the directory where you installed FakeIt. + +### Installing FakeIt through Conan + +To use FakeIt with Conan, you'll need a `conanfile.txt` like this: ``` -./build/tests/FakeIt_tests +[requires] +fakeit/ + +[options] +fakeit:integration= ``` -### Building fakeit - Using vcpkg +Replace `` by the version of FakeIt you want to use, and `` with the name of the configuration you want to use (see `Configurations' name` section for details). + +### Installing FakeIt through vcpkg You can download and install fakeit using the [vcpkg](https://github.com/Microsoft/vcpkg) dependency manager: @@ -154,7 +174,29 @@ You can download and install fakeit using the [vcpkg](https://github.com/Microso The fakeit port in vcpkg is kept up to date by Microsoft team members and community contributors. If the version is out of date, please [create an issue or pull request](https://github.com/Microsoft/vcpkg) on the vcpkg repository. -#### Building and Running the Unit Tests with Visual Studio +## Running the tests + +### Building and Running the Unit Tests with GCC +``` +CC=gcc CXX=g++ cmake -S . -B build -DCMAKE_BUILD_TYPE=Debug -DENABLE_TESTING=ON +cmake --build build -j +``` +Run the tests by typing: +``` +./build/tests/FakeIt_tests +``` + +### Building and Running the Unit Tests with Clang +``` +CC=clang CXX=clang++ cmake -S . -B build -DCMAKE_BUILD_TYPE=Debug -DENABLE_TESTING=ON +cmake --build build -j +``` +Run the tests by typing: +``` +./build/tests/FakeIt_tests +``` + +### Building and Running the Unit Tests with Visual Studio ``` cmake -S . -B build -G "Visual Studio 17 2022" -DENABLE_TESTING=ON cmake --build build --config Debug -j From 059cf8b28a8506884e21e3973feac649b4d8d5db Mon Sep 17 00:00:00 2001 From: Franck W Date: Sun, 16 Apr 2023 14:27:21 +0200 Subject: [PATCH 10/20] Fixed ref-qualified overload for GCC. --- include/fakeit/Prototype.hpp | 40 ++++++++++------------------- include/fakeit/api_macros.hpp | 3 +-- tests/overloadded_methods_tests.cpp | 24 ++++++++++++----- 3 files changed, 33 insertions(+), 34 deletions(-) diff --git a/include/fakeit/Prototype.hpp b/include/fakeit/Prototype.hpp index 82582ba4..5aecf9c0 100644 --- a/include/fakeit/Prototype.hpp +++ b/include/fakeit/Prototype.hpp @@ -8,51 +8,40 @@ namespace fakeit { template struct Prototype { - typedef R Type(Args...); - - typedef R ConstType(Args...) const; - - typedef R RefType(Args...) &; - - typedef R ConstRefType(Args...) const&; - - typedef R RRefType(Args...) &&; - - typedef R ConstRRefType(Args...) const&&; - - template + template struct MemberType { - typedef Type(C::*type); - typedef ConstType(C::* constType); - typedef RefType(C::* refType); - typedef ConstRefType(C::* constRefType); - typedef RRefType(C::* rRefType); - typedef ConstRRefType(C::* constRRefType); + using Type = R (C::*)(Args...); + using ConstType = R (C::*)(Args...) const; + using RefType = R (C::*)(Args...) &; + using ConstRefType = R (C::*)(Args...) const&; + using RRefType = R (C::*)(Args...) &&; + using ConstRRefType = R (C::*)(Args...) const&&; - static type get(type t) { + static Type get(Type t) { return t; } - static constType getconst(constType t) { + static ConstType getConst(ConstType t) { return t; } - static refType getRef(refType t) { + static RefType getRef(RefType t) { return t; } - static constRefType getConstRef(constRefType t) { + static ConstRefType getConstRef(ConstRefType t) { return t; } - static rRefType getRRef(rRefType t) { + static RRefType getRRef(RRefType t) { return t; } - static constRRefType getConstRRef(constRRefType t) { + static ConstRRefType getConstRRef(ConstRRefType t) { return t; } + }; }; @@ -73,4 +62,3 @@ namespace fakeit { }; } - diff --git a/include/fakeit/api_macros.hpp b/include/fakeit/api_macros.hpp index c72e4bad..4c12448a 100644 --- a/include/fakeit/api_macros.hpp +++ b/include/fakeit/api_macros.hpp @@ -11,7 +11,7 @@ fakeit::Prototype::template MemberType::get(&MOCK_TYPE(mock)::method) #define CONST_OVERLOADED_METHOD_PTR(mock, method, prototype) \ - fakeit::Prototype::template MemberType::getconst(&MOCK_TYPE(mock)::method) + fakeit::Prototype::template MemberType::getConst(&MOCK_TYPE(mock)::method) #define REF_OVERLOADED_METHOD_PTR(mock, method, prototype) \ fakeit::Prototype::MemberType::getRef(&MOCK_TYPE(mock)::method) @@ -64,4 +64,3 @@ #define When(call) \ When(call) - diff --git a/tests/overloadded_methods_tests.cpp b/tests/overloadded_methods_tests.cpp index 543e7dbb..c7819f9b 100644 --- a/tests/overloadded_methods_tests.cpp +++ b/tests/overloadded_methods_tests.cpp @@ -99,7 +99,6 @@ struct OverloadedMethods : tpunit::TestFixture { } struct SomeModernCppInterface { - virtual int func() & = 0; virtual int func(int) & = 0; @@ -109,7 +108,6 @@ struct OverloadedMethods : tpunit::TestFixture { }; void stub_modern_overloaded_methods() { - Mock mock; When(RefOverloadedMethod(mock, func, int(int))).Return(1); When(ConstRefOverloadedMethod(mock, func, int(int))).Return(2); @@ -117,27 +115,41 @@ struct OverloadedMethods : tpunit::TestFixture { SomeModernCppInterface& refObj = mock.get(); const SomeModernCppInterface& refConstObj = mock.get(); - ASSERT_EQUAL(1, refObj.func(1)); - ASSERT_EQUAL(2, refConstObj.func(1)); + ASSERT_EQUAL(1, refObj.func(10)); + ASSERT_EQUAL(2, refConstObj.func(20)); + + Verify(RefOverloadedMethod(mock, func, int(int)).Using(10)).Exactly(1); + Verify(ConstRefOverloadedMethod(mock, func, int(int)).Using(20)).Exactly(1); + + VerifyNoOtherInvocations(mock); } void stub_modern_rref_overloaded_method() { - Mock mock; + When(RefOverloadedMethod(mock, func, int(int))).Return(1); When(RRefOverloadedMethod(mock, func, int(int))).Return(3); SomeModernCppInterface& refObj = mock.get(); + ASSERT_EQUAL(1, refObj.func(1)); ASSERT_EQUAL(3, std::move(refObj).func(1)); + + Verify(RefOverloadedMethod(mock, func, int(int))).Exactly(1); + Verify(RRefOverloadedMethod(mock, func, int(int))).Exactly(1); + + VerifyNoOtherInvocations(mock); } void stub_modern_constrref_overloaded_method() { - Mock mock; When(ConstRRefOverloadedMethod(mock, func, int(int))).Return(4); const SomeModernCppInterface& refConstObj = mock.get(); ASSERT_EQUAL(4, std::move(refConstObj).func(1)); + + Verify(ConstRRefOverloadedMethod(mock, func, int(int)).Using(1)).Exactly(1); + + VerifyNoOtherInvocations(mock); } } __OverloadedMethods; From 966b0071d2d9d98f617cc5af90cf2d66f9879f01 Mon Sep 17 00:00:00 2001 From: Franck W Date: Sun, 16 Apr 2023 17:42:47 +0200 Subject: [PATCH 11/20] De-duplicated some code related to stubbing void / non-void methods. --- include/fakeit/Mock.hpp | 112 +++++++++++++--------------- include/fakeit/api_macros.hpp | 1 - tests/overloadded_methods_tests.cpp | 37 ++++++++- 3 files changed, 86 insertions(+), 64 deletions(-) diff --git a/include/fakeit/Mock.hpp b/include/fakeit/Mock.hpp index 0fc1a009..51484d84 100644 --- a/include/fakeit/Mock.hpp +++ b/include/fakeit/Mock.hpp @@ -14,8 +14,23 @@ namespace fakeit { namespace internal { + template + struct WithCommonVoid { + using type = T; + }; + + // The goal of this specialization is to replace all kinds of void (e.g. "const void") by a common type, "void". + // This is because some other parts of the code have specialization for "void", but these specializations only + // handle "void", and not "const void", so instead of modifying all these specialization to handle both types, + // we replace "const void" by "void" here. + template + struct WithCommonVoid::value, void>::type> { + using type = void; + }; + + template + using WithCommonVoid_t = typename WithCommonVoid::type; } - using namespace fakeit::internal; template class Mock : public ActualInvocationsSource { @@ -38,7 +53,7 @@ namespace fakeit { // std::shared_ptr getShared() { // return impl.getShared(); // } - + C &operator()() { return get(); } @@ -57,94 +72,67 @@ namespace fakeit { return impl.stubDataMember(member, ctorargs...); } - // const non void + // const template::value && std::is_base_of::value>::type> - MockingContext stub(R (T::*vMethod)(arglist...) const) { - auto methodWithoutConstVolatile = reinterpret_cast(vMethod); - return impl.template stubMethod(methodWithoutConstVolatile); - } - - // volatile non void - template::value && std::is_base_of::value>::type> - MockingContext stub(R(T::*vMethod)(arglist...) volatile) { - auto methodWithoutConstVolatile = reinterpret_cast(vMethod); - return impl.template stubMethod(methodWithoutConstVolatile); - } - - // const volatile non void - template::value && std::is_base_of::value>::type> - MockingContext stub(R(T::*vMethod)(arglist...) const volatile) { - auto methodWithoutConstVolatile = reinterpret_cast(vMethod); - return impl.template stubMethod(methodWithoutConstVolatile); - } - - // non void - template::value && std::is_base_of::value>::type> - MockingContext stub(R(T::*vMethod)(arglist...)) { - return impl.template stubMethod(vMethod); - } - - // ref non void - template::value&& std::is_base_of::value>::type> - MockingContext stub(R(T::* vMethod)(arglist...) &) { - auto methodWithoutConstVolatile = reinterpret_cast(vMethod); + std::is_base_of::value>::type> + MockingContext, arglist...> stub(R (T::*vMethod)(arglist...) const) { + auto methodWithoutConstVolatile = reinterpret_cast (T::*)(arglist...)>(vMethod); return impl.template stubMethod(methodWithoutConstVolatile); } - // const ref non void + // volatile template::value&& std::is_base_of::value>::type> - MockingContext stub(R(T::* vMethod)(arglist...) const&) { - auto methodWithoutConstVolatile = reinterpret_cast(vMethod); + std::is_base_of::value>::type> + MockingContext, arglist...> stub(R(T::*vMethod)(arglist...) volatile) { + auto methodWithoutConstVolatile = reinterpret_cast(T::*)(arglist...)>(vMethod); return impl.template stubMethod(methodWithoutConstVolatile); } - // rref non void + // const volatile template::value&& std::is_base_of::value>::type> - MockingContext stub(R(T::* vMethod)(arglist...) &&) { - auto methodWithoutConstVolatile = reinterpret_cast(vMethod); + std::is_base_of::value>::type> + MockingContext, arglist...> stub(R(T::*vMethod)(arglist...) const volatile) { + auto methodWithoutConstVolatile = reinterpret_cast(T::*)(arglist...)>(vMethod); return impl.template stubMethod(methodWithoutConstVolatile); } - // const rref non void + // no qualifier template::value&& std::is_base_of::value>::type> - MockingContext stub(R(T::* vMethod)(arglist...) const&&) { - auto methodWithoutConstVolatile = reinterpret_cast(vMethod); + std::is_base_of::value>::type> + MockingContext, arglist...> stub(R(T::*vMethod)(arglist...)) { + auto methodWithoutConstVolatile = reinterpret_cast(T::*)(arglist...)>(vMethod); return impl.template stubMethod(methodWithoutConstVolatile); } + // ref template::value && std::is_base_of::value>::type> - MockingContext stub(R(T::*vMethod)(arglist...) const) { - auto methodWithoutConstVolatile = reinterpret_cast(vMethod); + std::is_base_of::value>::type> + MockingContext, arglist...> stub(R(T::*vMethod)(arglist...) &) { + auto methodWithoutConstVolatile = reinterpret_cast(T::*)(arglist...)>(vMethod); return impl.template stubMethod(methodWithoutConstVolatile); } + // const ref template::value && std::is_base_of::value>::type> - MockingContext stub(R(T::*vMethod)(arglist...) volatile) { - auto methodWithoutConstVolatile = reinterpret_cast(vMethod); + std::is_base_of::value>::type> + MockingContext, arglist...> stub(R(T::*vMethod)(arglist...) const&) { + auto methodWithoutConstVolatile = reinterpret_cast(T::*)(arglist...)>(vMethod); return impl.template stubMethod(methodWithoutConstVolatile); } + // rref template::value && std::is_base_of::value>::type> - MockingContext stub(R(T::*vMethod)(arglist...) const volatile) { - auto methodWithoutConstVolatile = reinterpret_cast(vMethod); + std::is_base_of::value>::type> + MockingContext, arglist...> stub(R(T::*vMethod)(arglist...) &&) { + auto methodWithoutConstVolatile = reinterpret_cast(T::*)(arglist...)>(vMethod); return impl.template stubMethod(methodWithoutConstVolatile); } + // const rref template::value && std::is_base_of::value>::type> - MockingContext stub(R(T::*vMethod)(arglist...)) { - auto methodWithoutConstVolatile = reinterpret_cast(vMethod); + std::is_base_of::value>::type> + MockingContext, arglist...> stub(R(T::*vMethod)(arglist...) const&&) { + auto methodWithoutConstVolatile = reinterpret_cast(T::*)(arglist...)>(vMethod); return impl.template stubMethod(methodWithoutConstVolatile); } @@ -158,4 +146,4 @@ namespace fakeit { }; -} \ No newline at end of file +} diff --git a/include/fakeit/api_macros.hpp b/include/fakeit/api_macros.hpp index 4c12448a..7771c260 100644 --- a/include/fakeit/api_macros.hpp +++ b/include/fakeit/api_macros.hpp @@ -49,7 +49,6 @@ #define ConstRRefOverloadedMethod(mock, method, prototype) \ (mock).template stub<__COUNTER__>(CONST_RREF_OVERLOADED_METHOD_PTR( mock , method, prototype )).setMethodDetails(#mock,#method) - #define Verify(...) \ Verify( __VA_ARGS__ ).setFileInfo(__FILE__, __LINE__, __func__) diff --git a/tests/overloadded_methods_tests.cpp b/tests/overloadded_methods_tests.cpp index c7819f9b..d95ff627 100644 --- a/tests/overloadded_methods_tests.cpp +++ b/tests/overloadded_methods_tests.cpp @@ -43,7 +43,8 @@ struct OverloadedMethods : tpunit::TestFixture { TEST(OverloadedMethods::stub_overloaded_methods_with_templates), TEST(OverloadedMethods::stub_modern_overloaded_methods), TEST(OverloadedMethods::stub_modern_rref_overloaded_method), - TEST(OverloadedMethods::stub_modern_constrref_overloaded_method) + TEST(OverloadedMethods::stub_modern_constrref_overloaded_method), + TEST(OverloadedMethods::stub_modern_overloaded_proc) ) { } @@ -105,6 +106,11 @@ struct OverloadedMethods : tpunit::TestFixture { virtual int func(int) const& = 0; virtual int func(int) && = 0; virtual int func(int) const&& = 0; + + virtual void proc(int) & = 0; + virtual void proc(int) const& = 0; + virtual void proc(int) && = 0; + virtual void proc(int) const&& = 0; }; void stub_modern_overloaded_methods() { @@ -152,4 +158,33 @@ struct OverloadedMethods : tpunit::TestFixture { VerifyNoOtherInvocations(mock); } + void stub_modern_overloaded_proc() { + Mock mock; + int ret = 0; + + When(ConstRRefOverloadedMethod(mock, proc, void(int))).Do([&](int){ret = 4;}); + When(ConstRefOverloadedMethod(mock, proc, void(int))).Do([&](int){ret = 3;}); + When(RRefOverloadedMethod(mock, proc, void(int))).Do([&](int){ret = 2;}); + When(RefOverloadedMethod(mock, proc, void(int))).Do([&](int){ret = 1;}); + + SomeModernCppInterface& refObj = mock.get(); + const SomeModernCppInterface& refConstObj = mock.get(); + + refObj.proc(0); + ASSERT_EQUAL(1, ret); + std::move(refObj).proc(0); + ASSERT_EQUAL(2, ret); + refConstObj.proc(0); + ASSERT_EQUAL(3, ret); + std::move(refConstObj).proc(0); + ASSERT_EQUAL(4, ret); + + Verify(RefOverloadedMethod(mock, proc, void(int))).Exactly(1); + Verify(RRefOverloadedMethod(mock, proc, void(int))).Exactly(1); + Verify(ConstRefOverloadedMethod(mock, proc, void(int))).Exactly(1); + Verify(ConstRRefOverloadedMethod(mock, proc, void(int))).Exactly(1); + + VerifyNoOtherInvocations(mock); + } + } __OverloadedMethods; From 57e8521ec2298663f82df2e2afc8ba4598751d7f Mon Sep 17 00:00:00 2001 From: Franck W Date: Sun, 16 Apr 2023 19:22:18 +0200 Subject: [PATCH 12/20] Fixed C++ standard detection on MSVC. --- include/fakeit/FakeitExceptions.hpp | 8 +++++--- include/fakeit/StubbingProgress.hpp | 14 +++++++------- include/mockutils/Macros.hpp | 14 ++++++++++---- tests/cpp14_tests.cpp | 4 +++- tests/stubbing_tests.cpp | 5 +++-- 5 files changed, 28 insertions(+), 17 deletions(-) diff --git a/include/fakeit/FakeitExceptions.hpp b/include/fakeit/FakeitExceptions.hpp index 8c894890..fdf662ee 100644 --- a/include/fakeit/FakeitExceptions.hpp +++ b/include/fakeit/FakeitExceptions.hpp @@ -7,12 +7,14 @@ */ #pragma once -#include "fakeit/FakeitEvents.hpp" #include +#include "mockutils/Macros.hpp" + +#include "fakeit/FakeitEvents.hpp" namespace fakeit { -#if __cplusplus >= 201703L || defined(__cpp_lib_uncaught_exceptions) +#if FAKEIT_CPLUSPLUS >= 201703L || defined(__cpp_lib_uncaught_exceptions) inline bool UncaughtException () { return std::uncaught_exceptions() >= 1; } @@ -36,7 +38,7 @@ namespace fakeit { }; - // Unlike verification exceptions (that are thrown from the test level), this exception + // Unlike verification exceptions (that are thrown from the test level), this exception // should not inherit from std::exception so that production code will not catch it. struct UnexpectedMethodCallException : public FakeitException { diff --git a/include/fakeit/StubbingProgress.hpp b/include/fakeit/StubbingProgress.hpp index 0ca8439d..a93252e1 100644 --- a/include/fakeit/StubbingProgress.hpp +++ b/include/fakeit/StubbingProgress.hpp @@ -172,7 +172,7 @@ namespace fakeit { MethodStubbingProgress &operator=(const MethodStubbingProgress &other) = delete; template -#if __cplusplus >= 201402L +#if FAKEIT_CPLUSPLUS >= 201402L auto #else std::function::type...)> @@ -197,7 +197,7 @@ namespace fakeit { } template -#if __cplusplus >= 201402L +#if FAKEIT_CPLUSPLUS >= 201402L auto #else std::function::type...)> @@ -316,7 +316,7 @@ namespace fakeit { MethodStubbingProgress &operator=(const MethodStubbingProgress &other) = delete; template -#if __cplusplus >= 201402L +#if FAKEIT_CPLUSPLUS >= 201402L auto #else std::function::type...)> @@ -340,7 +340,7 @@ namespace fakeit { } template -#if __cplusplus >= 201402L +#if FAKEIT_CPLUSPLUS >= 201402L auto #else std::function::type...)> @@ -382,7 +382,7 @@ namespace fakeit { template static void CheckPositions(const std::tuple...> arg_vals) { -#if __cplusplus >= 201402L && !defined(_WIN32) +#if FAKEIT_CPLUSPLUS >= 201402L && !defined(_WIN32) static_assert(std::get(arg_vals).pos <= max_index, "Argument index out of range"); ArgValidator::CheckPositions(arg_vals); @@ -434,7 +434,7 @@ namespace fakeit { struct ArgLocator { template static void AssignArg(current_arg &&p, std::tuple...> arg_vals) { -#if __cplusplus >= 201703L && !defined (_WIN32) +#if FAKEIT_CPLUSPLUS >= 201703L && !defined (_WIN32) if constexpr (std::get(arg_vals).pos == arg_index) GetArg(std::forward(p)) = std::get(arg_vals).value; #else @@ -445,7 +445,7 @@ namespace fakeit { ArgLocator::AssignArg(std::forward(p), arg_vals); } -#if __cplusplus < 201703L || defined (_WIN32) +#if FAKEIT_CPLUSPLUS < 201703L || defined (_WIN32) private: template static diff --git a/include/mockutils/Macros.hpp b/include/mockutils/Macros.hpp index 1ad56868..d5819113 100644 --- a/include/mockutils/Macros.hpp +++ b/include/mockutils/Macros.hpp @@ -8,9 +8,15 @@ #pragma once #if defined (__GNUG__) || _MSC_VER >= 1900 -#define FAKEIT_THROWS noexcept(false) -#define FAKEIT_NO_THROWS noexcept(true) +# define FAKEIT_THROWS noexcept(false) +# define FAKEIT_NO_THROWS noexcept(true) #elif defined (_MSC_VER) -#define FAKEIT_THROWS throw(...) -#define FAKEIT_NO_THROWS +# define FAKEIT_THROWS throw(...) +# define FAKEIT_NO_THROWS +#endif + +#ifdef _MSVC_LANG +# define FAKEIT_CPLUSPLUS _MSVC_LANG +#else +# define FAKEIT_CPLUSPLUS __cplusplus #endif diff --git a/tests/cpp14_tests.cpp b/tests/cpp14_tests.cpp index 0a6344f3..4b6a2821 100644 --- a/tests/cpp14_tests.cpp +++ b/tests/cpp14_tests.cpp @@ -6,7 +6,9 @@ * Created on Mar 10, 2014 */ -#if __cplusplus > 201103L +#include "mockutils/Macros.hpp" + +#if FAKEIT_CPLUSPLUS > 201103L #include #include "tpunit++.hpp" diff --git a/tests/stubbing_tests.cpp b/tests/stubbing_tests.cpp index 89bbbc5e..e3e35995 100644 --- a/tests/stubbing_tests.cpp +++ b/tests/stubbing_tests.cpp @@ -9,6 +9,8 @@ #include #include +#include "mockutils/Macros.hpp" + #include "tpunit++.hpp" #include "fakeit.hpp" @@ -236,7 +238,7 @@ struct BasicStubbing : tpunit::TestFixture { i.procIncompatArgs(s, chk_v); ASSERT_EQUAL(chk_v, v); -#if __cplusplus < 201703L +#if FAKEIT_CPLUSPLUS < 201703L || defined (_WIN32) When(Method(mock, procIncompatArgs)).ReturnAndSet(_1 <= v); try { i.procIncompatArgs(s, chk_v); @@ -884,4 +886,3 @@ struct BasicStubbing : tpunit::TestFixture { } } __BasicStubbing; - From 04d96385decf648a8b6d2b9838f022ad7511d15b Mon Sep 17 00:00:00 2001 From: Franck W Date: Sun, 16 Apr 2023 22:40:14 +0200 Subject: [PATCH 13/20] Improved UBSAN support for gcc too + added a macro to disable tests that have to trigger UBSAN. --- include/mockutils/Macros.hpp | 6 ++++++ include/mockutils/VTUtils.hpp | 5 ++--- tests/default_behaviore_tests.cpp | 4 ++++ tests/referece_types_tests.cpp | 30 +++++++++++++++++++++++------- tests/stubbing_tests.cpp | 2 -- 5 files changed, 35 insertions(+), 12 deletions(-) diff --git a/include/mockutils/Macros.hpp b/include/mockutils/Macros.hpp index d5819113..48a70bcd 100644 --- a/include/mockutils/Macros.hpp +++ b/include/mockutils/Macros.hpp @@ -20,3 +20,9 @@ #else # define FAKEIT_CPLUSPLUS __cplusplus #endif + +#ifdef __GNUG__ +# define FAKEIT_DISARM_UBSAN __attribute__((no_sanitize("undefined"))) +#else +# define FAKEIT_DISARM_UBSAN +#endif diff --git a/include/mockutils/VTUtils.hpp b/include/mockutils/VTUtils.hpp index 1a0c3458..3256b711 100644 --- a/include/mockutils/VTUtils.hpp +++ b/include/mockutils/VTUtils.hpp @@ -10,6 +10,7 @@ #include #include +#include "mockutils/Macros.hpp" #include "mockutils/VirtualOffestSelector.hpp" #include "mockutils/union_cast.hpp" @@ -37,10 +38,8 @@ namespace fakeit { #endif template + FAKEIT_DISARM_UBSAN static typename std::enable_if::value, unsigned int>::type -#if defined(__clang__) -__attribute__((no_sanitize("undefined"))) -#endif getDestructorOffset() { VirtualOffsetSelector offsetSelctor; union_cast(&offsetSelctor)->~C(); diff --git a/tests/default_behaviore_tests.cpp b/tests/default_behaviore_tests.cpp index cfa2a098..6d1d7cf1 100644 --- a/tests/default_behaviore_tests.cpp +++ b/tests/default_behaviore_tests.cpp @@ -22,9 +22,13 @@ struct DefaultBehavioreTests : tpunit::TestFixture { TEST(DefaultBehavioreTests::DefaultBeaviorOfVoidFunctionsIsToDoNothing), // TEST(DefaultBehavioreTests::ReturnByValue_ReturnDefaultConstructedObject), // TEST(DefaultBehavioreTests::ReturnByValue_ThrowExceptionIfNotDefaultConstructible), // +#ifndef FAKEIT_DISABLE_UBSAN_TRIGGERING_TESTS TEST(DefaultBehavioreTests::ReturnByReference_ReturnReferenceToNullIfAbstract), // +#endif TEST(DefaultBehavioreTests::ReturnByReference_ReturnReferenceToDefaultConstructedObject), // +#ifndef FAKEIT_DISABLE_UBSAN_TRIGGERING_TESTS TEST(DefaultBehavioreTests::ReturnByReference_ReturnReferenceToNullIfNotDefaultConstructible), // +#endif TEST(DefaultBehavioreTests::ReturnPtr_NullPtrIfPtrToAbstract), TEST(DefaultBehavioreTests::production_shared_ptr_mock_used_in_invocation) //TEST(DefaultBehavioreTests::should_survive_delete_of_mock_instance_by_user) diff --git a/tests/referece_types_tests.cpp b/tests/referece_types_tests.cpp index 31e6852e..6c5df9cf 100644 --- a/tests/referece_types_tests.cpp +++ b/tests/referece_types_tests.cpp @@ -57,11 +57,18 @@ struct ReferenceTypesTests: tpunit::TestFixture { void implicitStubbingDefaultReturnValues() { Mock mock; +#ifndef FAKEIT_DISABLE_UBSAN_TRIGGERING_TESTS Fake( // Method(mock,returnIntByRef), // Method(mock,returnAbstractTypeByRef), // Method(mock,returnConcreteTypeByRef) // ); +#else + Fake( // + Method(mock,returnIntByRef), // + Method(mock,returnConcreteTypeByRef) // + ); +#endif ReferenceInterface & i = mock.get(); @@ -69,18 +76,22 @@ struct ReferenceTypesTests: tpunit::TestFixture { // Return a reference to the default value. ASSERT_EQUAL(0, i.returnIntByRef()); - // Concrete types types are initiated by default ctor. + // Concrete types are initiated by default ctor. // Return a reference to the default value. ASSERT_EQUAL(ConcreteType(), i.returnConcreteTypeByRef()); +#ifndef FAKEIT_DISABLE_UBSAN_TRIGGERING_TESTS // For abstract types return a reference to nullptr. ASSERT_EQUAL(nullptr, &i.returnAbstractTypeByRef()); +#endif } void explicitStubbingDefualtReturnValues() { Mock mock; // When(Method(mock,returnIntByRef)).Return(); // +#ifndef FAKEIT_DISABLE_UBSAN_TRIGGERING_TESTS When(Method(mock,returnAbstractTypeByRef)).Return(); // +#endif When(Method(mock,returnConcreteTypeByRef)).Return(); // ReferenceInterface & i = mock.get(); @@ -89,12 +100,14 @@ struct ReferenceTypesTests: tpunit::TestFixture { // Return a reference to the default value. ASSERT_EQUAL(0, i.returnIntByRef()); - // Concrete types types are initiated by default ctor. + // Concrete types are initiated by default ctor. // Return a reference to the default value. ASSERT_EQUAL(ConcreteType(), i.returnConcreteTypeByRef()); +#ifndef FAKEIT_DISABLE_UBSAN_TRIGGERING_TESTS // For abstract types return a reference to nullptr. ASSERT_EQUAL(nullptr, &i.returnAbstractTypeByRef()); +#endif } void explicitStubbingReturnValues() { @@ -113,7 +126,7 @@ struct ReferenceTypesTests: tpunit::TestFixture { // Return a reference to the default value. ASSERT_EQUAL(1, i.returnIntByRef()); - // Concrete types types are initiated by default ctor. + // Concrete types are initiated by default ctor. // Return a reference to the default value. ASSERT_EQUAL(&c, &i.returnConcreteTypeByRef()); @@ -137,7 +150,7 @@ struct ReferenceTypesTests: tpunit::TestFixture { // Return a reference to the default value. ASSERT_EQUAL(1, i.returnIntByRef()); - // Concrete types types are initiated by default ctor. + // Concrete types are initiated by default ctor. // Return a reference to the default value. ASSERT_EQUAL(&c, &i.returnConcreteTypeByRef()); @@ -161,7 +174,7 @@ struct ReferenceTypesTests: tpunit::TestFixture { // Return a reference to the default value. ASSERT_EQUAL(1, i.returnIntByRef()); - // Concrete types types are initiated by default ctor. + // Concrete types are initiated by default ctor. // Return a reference to the default value. ASSERT_EQUAL(&c, &i.returnConcreteTypeByRef()); @@ -172,7 +185,9 @@ struct ReferenceTypesTests: tpunit::TestFixture { void explicitStubbingDefualtReturnValues_with_AlwaysReturn() { Mock mock; When(Method(mock,returnIntByRef)).AlwaysReturn(); +#ifndef FAKEIT_DISABLE_UBSAN_TRIGGERING_TESTS When(Method(mock,returnAbstractTypeByRef)).AlwaysReturn(); // +#endif When(Method(mock,returnConcreteTypeByRef)).AlwaysReturn(); // ReferenceInterface & i = mock.get(); @@ -181,13 +196,14 @@ struct ReferenceTypesTests: tpunit::TestFixture { // Return a reference to the default value. ASSERT_EQUAL(0, i.returnIntByRef()); - // Concrete types types are initiated by default ctor. + // Concrete types are initiated by default ctor. // Return a reference to the default value. ASSERT_EQUAL(ConcreteType(), i.returnConcreteTypeByRef()); +#ifndef FAKEIT_DISABLE_UBSAN_TRIGGERING_TESTS // For abstract types return a reference to nullptr. ASSERT_EQUAL(nullptr, &i.returnAbstractTypeByRef()); +#endif } } __ReferenceTypesTests; - diff --git a/tests/stubbing_tests.cpp b/tests/stubbing_tests.cpp index e3e35995..bff76c72 100644 --- a/tests/stubbing_tests.cpp +++ b/tests/stubbing_tests.cpp @@ -9,8 +9,6 @@ #include #include -#include "mockutils/Macros.hpp" - #include "tpunit++.hpp" #include "fakeit.hpp" From 5d6c9905019709d49e4ac3dd2116305906c828c5 Mon Sep 17 00:00:00 2001 From: Franck W Date: Sun, 16 Apr 2023 22:31:42 +0200 Subject: [PATCH 14/20] Added an action with sanitizers enabled for GCC / Clang in GitHub CI. --- .github/workflows/ci_linux_clang.yml | 13 ++++++++++++- .github/workflows/ci_linux_gcc.yml | 13 ++++++++++++- .github/workflows/ci_windows_msvc.yml | 6 +++++- CMakeLists.txt | 3 ++- tests/CMakeLists.txt | 11 +++++++++++ 5 files changed, 42 insertions(+), 4 deletions(-) diff --git a/.github/workflows/ci_linux_clang.yml b/.github/workflows/ci_linux_clang.yml index 2f13d7db..414220e8 100644 --- a/.github/workflows/ci_linux_clang.yml +++ b/.github/workflows/ci_linux_clang.yml @@ -68,6 +68,13 @@ jobs: cc: "clang-14", cxx: "clang++-14", cxx_standard: 20 } + - { + name: "Ubuntu 22.04 Clang with sanitizers", + os: ubuntu-22.04, + build_type: Debug, + cc: "clang", cxx: "clang++", + enable_sanitizers_in_tests: ON + } steps: - uses: actions/checkout@v2 - name: Build project @@ -75,7 +82,11 @@ jobs: CC: ${{ matrix.config.cc }} CXX: ${{ matrix.config.cxx }} run: | - cmake -S . -B build -DCMAKE_BUILD_TYPE=${{ matrix.config.build_type }} -DENABLE_TESTING=ON -DOVERRIDE_CXX_STANDARD_FOR_TESTS=${{ matrix.config.cxx_standard }} + cmake -S . -B build \ + -DCMAKE_BUILD_TYPE=${{ matrix.config.build_type }} \ + -DENABLE_TESTING=ON \ + -DOVERRIDE_CXX_STANDARD_FOR_TESTS=${{ matrix.config.cxx_standard }} \ + -DENABLE_SANITIZERS_IN_TESTS=${{ matrix.config.enable_sanitizers_in_tests }} cmake --build build -j - name: Run tests run: | diff --git a/.github/workflows/ci_linux_gcc.yml b/.github/workflows/ci_linux_gcc.yml index b2ba4e02..1445cbad 100644 --- a/.github/workflows/ci_linux_gcc.yml +++ b/.github/workflows/ci_linux_gcc.yml @@ -62,6 +62,13 @@ jobs: cc: "gcc-12", cxx: "g++-12", cxx_standard: 20 } + - { + name: "Ubuntu 22.04 GCC with sanitizers", + os: ubuntu-22.04, + build_type: Debug, + cc: "gcc", cxx: "g++", + enable_sanitizers_in_tests: ON + } steps: - uses: actions/checkout@v2 - name: Build project @@ -69,7 +76,11 @@ jobs: CC: ${{ matrix.config.cc }} CXX: ${{ matrix.config.cxx }} run: | - cmake -S . -B build -DCMAKE_BUILD_TYPE=${{ matrix.config.build_type }} -DENABLE_TESTING=ON -DOVERRIDE_CXX_STANDARD_FOR_TESTS=${{ matrix.config.cxx_standard }} + cmake -S . -B build \ + -DCMAKE_BUILD_TYPE=${{ matrix.config.build_type }} \ + -DENABLE_TESTING=ON \ + -DOVERRIDE_CXX_STANDARD_FOR_TESTS=${{ matrix.config.cxx_standard }} \ + -DENABLE_SANITIZERS_IN_TESTS=${{ matrix.config.enable_sanitizers_in_tests }} cmake --build build -j - name: Run tests run: | diff --git a/.github/workflows/ci_windows_msvc.yml b/.github/workflows/ci_windows_msvc.yml index 65e5a865..bdc1d56b 100644 --- a/.github/workflows/ci_windows_msvc.yml +++ b/.github/workflows/ci_windows_msvc.yml @@ -59,7 +59,11 @@ jobs: - uses: actions/checkout@v2 - name: Build project run: | - cmake -S . -B build -G "${{ matrix.config.generator }}" -A ${{ matrix.config.architecture }} -DENABLE_TESTING=ON -DOVERRIDE_CXX_STANDARD_FOR_TESTS=${{ matrix.config.cxx_standard }} + cmake -S . -B build \ + -G "${{ matrix.config.generator }}" \ + -A ${{ matrix.config.architecture }} \ + -DENABLE_TESTING=ON \ + -DOVERRIDE_CXX_STANDARD_FOR_TESTS=${{ matrix.config.cxx_standard }} cmake --build build --config ${{ matrix.config.build_type }} -j - name: Run tests run: | diff --git a/CMakeLists.txt b/CMakeLists.txt index f94a3f85..8c4adb62 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -3,9 +3,10 @@ cmake_minimum_required(VERSION 3.14) project(FakeIt VERSION 2.3.2 LANGUAGES CXX) -option(ENABLE_COVERAGE "Enable coverage reporting for gcc/clang." OFF) option(ENABLE_TESTING "Enable build of tests." OFF) option(OVERRIDE_CXX_STANDARD_FOR_TESTS "Override the C++ standard used for building tests." "") +option(ENABLE_SANITIZERS_IN_TESTS "Enable address / undefined sanitizers in tests." OFF) +option(ENABLE_COVERAGE "Enable coverage reporting for gcc/clang." OFF) # Directory containing main targets of FakeIt. add_subdirectory(include) diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index fb77acc1..51883ddd 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -45,6 +45,17 @@ if(OVERRIDE_CXX_STANDARD_FOR_TESTS) message(STATUS "Building tests in C++${OVERRIDE_CXX_STANDARD_FOR_TESTS}.") endif() +if(ENABLE_SANITIZERS_IN_TESTS) + if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU" OR CMAKE_CXX_COMPILER_ID MATCHES "^(Apple)?Clang$") + target_compile_options(FakeIt_tests PRIVATE -fsanitize=address,undefined -fno-sanitize-recover=address,undefined) + target_link_options(FakeIt_tests PRIVATE -fsanitize=address,undefined -fno-sanitize-recover=address,undefined) + target_compile_definitions(FakeIt_tests PRIVATE FAKEIT_DISABLE_UBSAN_TRIGGERING_TESTS) + message(STATUS "Sanitizers enabled: address, undefined.") + else() + message(SEND_ERROR "Sanitizers requested but compiler is not compatible.") + endif() +endif() + if(ENABLE_COVERAGE) if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU" OR CMAKE_CXX_COMPILER_ID MATCHES "^(Apple)?Clang$") target_compile_options(FakeIt_tests PRIVATE --coverage) From d15b1163f67c60a552134320a7118ecfb371d75d Mon Sep 17 00:00:00 2001 From: Franck W Date: Mon, 17 Apr 2023 19:54:12 +0200 Subject: [PATCH 15/20] Updated README to show proper badges. --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index d57a46ad..1d7b00bf 100644 --- a/README.md +++ b/README.md @@ -3,12 +3,12 @@ FakeIt [![Join the chat at https://gitter.im/eranpeer/FakeIt](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/eranpeer/FakeIt?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) -Linux / GCC: [![Build status Linux/GCC](https://github.com/eranpeer/FakeIt/actions/workflows/ci_linux_gcc.yml/badge.svg)](https://github.com/eranpeer/FakeIt/actions/workflows/ci_linux_gcc.yml) +Linux / GCC: [![CI Linux/GCC](https://github.com/eranpeer/FakeIt/actions/workflows/ci_linux_gcc.yml/badge.svg?branch=master&event=push)](https://github.com/eranpeer/FakeIt/actions/workflows/ci_linux_gcc.yml?query=branch%3Amaster+event%3Apush) [![Coverage Status](https://coveralls.io/repos/github/eranpeer/FakeIt/badge.svg?branch=master)](https://coveralls.io/github/eranpeer/FakeIt?branch=master) -Linux / Clang: [![Build status Linux/Clang](https://github.com/eranpeer/FakeIt/actions/workflows/ci_linux_clang.yml/badge.svg)](https://github.com/eranpeer/FakeIt/actions/workflows/ci_linux_clang.yml) +Linux / Clang: [![CI Linux/Clang](https://github.com/eranpeer/FakeIt/actions/workflows/ci_linux_clang.yml/badge.svg?branch=master&event=push)](https://github.com/eranpeer/FakeIt/actions/workflows/ci_linux_clang.yml?query=branch%3Amaster+event%3Apush) -MSVC: [![Build status Windows/MSVC](https://github.com/eranpeer/FakeIt/actions/workflows/ci_windows_msvc.yml/badge.svg)](https://github.com/eranpeer/FakeIt/actions/workflows/ci_windows_msvc.yml) +MSVC: [![CI Windows/MSVC](https://github.com/eranpeer/FakeIt/actions/workflows/ci_windows_msvc.yml/badge.svg?branch=master&event=push)](https://github.com/eranpeer/FakeIt/actions/workflows/ci_windows_msvc.yml?query=branch%3Amaster+event%3Apush) FakeIt is a simple mocking framework for C++. It supports GCC, Clang and MS Visual C++. From 23ede0f75d014f3854f527db5f9a31c8ff1e8ade Mon Sep 17 00:00:00 2001 From: Franck W Date: Mon, 17 Apr 2023 21:26:49 +0200 Subject: [PATCH 16/20] Renamed RRef to RValRef for *OverloadedMethod. --- include/fakeit/Mock.hpp | 4 ++-- include/fakeit/Prototype.hpp | 8 ++++---- include/fakeit/api_macros.hpp | 16 ++++++++-------- tests/overloadded_methods_tests.cpp | 24 ++++++++++++------------ 4 files changed, 26 insertions(+), 26 deletions(-) diff --git a/include/fakeit/Mock.hpp b/include/fakeit/Mock.hpp index 51484d84..c13a4b49 100644 --- a/include/fakeit/Mock.hpp +++ b/include/fakeit/Mock.hpp @@ -120,7 +120,7 @@ namespace fakeit { return impl.template stubMethod(methodWithoutConstVolatile); } - // rref + // rval ref template::value>::type> MockingContext, arglist...> stub(R(T::*vMethod)(arglist...) &&) { @@ -128,7 +128,7 @@ namespace fakeit { return impl.template stubMethod(methodWithoutConstVolatile); } - // const rref + // const rval ref template::value>::type> MockingContext, arglist...> stub(R(T::*vMethod)(arglist...) const&&) { diff --git a/include/fakeit/Prototype.hpp b/include/fakeit/Prototype.hpp index 5aecf9c0..8b86f08b 100644 --- a/include/fakeit/Prototype.hpp +++ b/include/fakeit/Prototype.hpp @@ -15,8 +15,8 @@ namespace fakeit { using ConstType = R (C::*)(Args...) const; using RefType = R (C::*)(Args...) &; using ConstRefType = R (C::*)(Args...) const&; - using RRefType = R (C::*)(Args...) &&; - using ConstRRefType = R (C::*)(Args...) const&&; + using RValRefType = R (C::*)(Args...) &&; + using ConstRValRefType = R (C::*)(Args...) const&&; static Type get(Type t) { return t; @@ -34,11 +34,11 @@ namespace fakeit { return t; } - static RRefType getRRef(RRefType t) { + static RValRefType getRValRef(RValRefType t) { return t; } - static ConstRRefType getConstRRef(ConstRRefType t) { + static ConstRValRefType getConstRValRef(ConstRValRefType t) { return t; } diff --git a/include/fakeit/api_macros.hpp b/include/fakeit/api_macros.hpp index 7771c260..4f099a98 100644 --- a/include/fakeit/api_macros.hpp +++ b/include/fakeit/api_macros.hpp @@ -19,11 +19,11 @@ #define CONST_REF_OVERLOADED_METHOD_PTR(mock, method, prototype) \ fakeit::Prototype::MemberType::getConstRef(&MOCK_TYPE(mock)::method) -#define RREF_OVERLOADED_METHOD_PTR(mock, method, prototype) \ - fakeit::Prototype::MemberType::getRRef(&MOCK_TYPE(mock)::method) +#define R_VAL_REF_OVERLOADED_METHOD_PTR(mock, method, prototype) \ + fakeit::Prototype::MemberType::getRValRef(&MOCK_TYPE(mock)::method) -#define CONST_RREF_OVERLOADED_METHOD_PTR(mock, method, prototype) \ - fakeit::Prototype::MemberType::getConstRRef(&MOCK_TYPE(mock)::method) +#define CONST_R_VAL_REF_OVERLOADED_METHOD_PTR(mock, method, prototype) \ + fakeit::Prototype::MemberType::getConstRValRef(&MOCK_TYPE(mock)::method) #define Dtor(mock) \ (mock).dtor().setMethodDetails(#mock,"destructor") @@ -43,11 +43,11 @@ #define ConstRefOverloadedMethod(mock, method, prototype) \ (mock).template stub<__COUNTER__>(CONST_REF_OVERLOADED_METHOD_PTR( mock , method, prototype )).setMethodDetails(#mock,#method) -#define RRefOverloadedMethod(mock, method, prototype) \ - (mock).template stub<__COUNTER__>(RREF_OVERLOADED_METHOD_PTR( mock , method, prototype )).setMethodDetails(#mock,#method) +#define RValRefOverloadedMethod(mock, method, prototype) \ + (mock).template stub<__COUNTER__>(R_VAL_REF_OVERLOADED_METHOD_PTR( mock , method, prototype )).setMethodDetails(#mock,#method) -#define ConstRRefOverloadedMethod(mock, method, prototype) \ - (mock).template stub<__COUNTER__>(CONST_RREF_OVERLOADED_METHOD_PTR( mock , method, prototype )).setMethodDetails(#mock,#method) +#define ConstRValRefOverloadedMethod(mock, method, prototype) \ + (mock).template stub<__COUNTER__>(CONST_R_VAL_REF_OVERLOADED_METHOD_PTR( mock , method, prototype )).setMethodDetails(#mock,#method) #define Verify(...) \ Verify( __VA_ARGS__ ).setFileInfo(__FILE__, __LINE__, __func__) diff --git a/tests/overloadded_methods_tests.cpp b/tests/overloadded_methods_tests.cpp index d95ff627..bce97eb7 100644 --- a/tests/overloadded_methods_tests.cpp +++ b/tests/overloadded_methods_tests.cpp @@ -42,8 +42,8 @@ struct OverloadedMethods : tpunit::TestFixture { TEST(OverloadedMethods::stub_const_overloaded_methods), TEST(OverloadedMethods::stub_overloaded_methods_with_templates), TEST(OverloadedMethods::stub_modern_overloaded_methods), - TEST(OverloadedMethods::stub_modern_rref_overloaded_method), - TEST(OverloadedMethods::stub_modern_constrref_overloaded_method), + TEST(OverloadedMethods::stub_modern_rvalref_overloaded_method), + TEST(OverloadedMethods::stub_modern_constrvalref_overloaded_method), TEST(OverloadedMethods::stub_modern_overloaded_proc) ) { } @@ -130,10 +130,10 @@ struct OverloadedMethods : tpunit::TestFixture { VerifyNoOtherInvocations(mock); } - void stub_modern_rref_overloaded_method() { + void stub_modern_rvalref_overloaded_method() { Mock mock; When(RefOverloadedMethod(mock, func, int(int))).Return(1); - When(RRefOverloadedMethod(mock, func, int(int))).Return(3); + When(RValRefOverloadedMethod(mock, func, int(int))).Return(3); SomeModernCppInterface& refObj = mock.get(); @@ -141,19 +141,19 @@ struct OverloadedMethods : tpunit::TestFixture { ASSERT_EQUAL(3, std::move(refObj).func(1)); Verify(RefOverloadedMethod(mock, func, int(int))).Exactly(1); - Verify(RRefOverloadedMethod(mock, func, int(int))).Exactly(1); + Verify(RValRefOverloadedMethod(mock, func, int(int))).Exactly(1); VerifyNoOtherInvocations(mock); } - void stub_modern_constrref_overloaded_method() { + void stub_modern_constrvalref_overloaded_method() { Mock mock; - When(ConstRRefOverloadedMethod(mock, func, int(int))).Return(4); + When(ConstRValRefOverloadedMethod(mock, func, int(int))).Return(4); const SomeModernCppInterface& refConstObj = mock.get(); ASSERT_EQUAL(4, std::move(refConstObj).func(1)); - Verify(ConstRRefOverloadedMethod(mock, func, int(int)).Using(1)).Exactly(1); + Verify(ConstRValRefOverloadedMethod(mock, func, int(int)).Using(1)).Exactly(1); VerifyNoOtherInvocations(mock); } @@ -162,9 +162,9 @@ struct OverloadedMethods : tpunit::TestFixture { Mock mock; int ret = 0; - When(ConstRRefOverloadedMethod(mock, proc, void(int))).Do([&](int){ret = 4;}); + When(ConstRValRefOverloadedMethod(mock, proc, void(int))).Do([&](int){ ret = 4;}); When(ConstRefOverloadedMethod(mock, proc, void(int))).Do([&](int){ret = 3;}); - When(RRefOverloadedMethod(mock, proc, void(int))).Do([&](int){ret = 2;}); + When(RValRefOverloadedMethod(mock, proc, void(int))).Do([&](int){ ret = 2;}); When(RefOverloadedMethod(mock, proc, void(int))).Do([&](int){ret = 1;}); SomeModernCppInterface& refObj = mock.get(); @@ -180,9 +180,9 @@ struct OverloadedMethods : tpunit::TestFixture { ASSERT_EQUAL(4, ret); Verify(RefOverloadedMethod(mock, proc, void(int))).Exactly(1); - Verify(RRefOverloadedMethod(mock, proc, void(int))).Exactly(1); + Verify(RValRefOverloadedMethod(mock, proc, void(int))).Exactly(1); Verify(ConstRefOverloadedMethod(mock, proc, void(int))).Exactly(1); - Verify(ConstRRefOverloadedMethod(mock, proc, void(int))).Exactly(1); + Verify(ConstRValRefOverloadedMethod(mock, proc, void(int))).Exactly(1); VerifyNoOtherInvocations(mock); } From e881bf09dbaa749f4101501e80b30eb527cf5074 Mon Sep 17 00:00:00 2001 From: Franck W Date: Mon, 17 Apr 2023 21:27:09 +0200 Subject: [PATCH 17/20] Fixed single header generation script. --- generate_fakeit_single_header.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/generate_fakeit_single_header.py b/generate_fakeit_single_header.py index 942d152a..b47dca8a 100755 --- a/generate_fakeit_single_header.py +++ b/generate_fakeit_single_header.py @@ -113,7 +113,12 @@ def create_fakeit_file_for_config(config): def get_all_configs(): - return os.listdir(os.path.join(fakeit_path, 'config')) + configs = [] + with os.scandir(os.path.join(fakeit_path, 'config')) as entries: + for entry in entries: + if entry.is_dir(): + configs.append(entry.name) + return configs def get_parser(): From fb021b15fe29b2e1c004b64ee2f6eae62978d20e Mon Sep 17 00:00:00 2001 From: Franck W Date: Mon, 17 Apr 2023 21:27:32 +0200 Subject: [PATCH 18/20] Minor fixes (indent, etc). --- single_header/CMakeLists.txt | 2 +- tests/CMakeLists.txt | 2 +- tests/spying_tests.cpp | 38 ++++++++++++++++++------------------ 3 files changed, 21 insertions(+), 21 deletions(-) diff --git a/single_header/CMakeLists.txt b/single_header/CMakeLists.txt index 4dbf753c..1d2e280a 100644 --- a/single_header/CMakeLists.txt +++ b/single_header/CMakeLists.txt @@ -50,7 +50,7 @@ write_basic_package_version_file("${PROJECT_BINARY_DIR}/FakeItConfigVersion.cmak VERSION ${PROJECT_VERSION} COMPATIBILITY - AnyNewerVersion + SameMajorVersion ARCH_INDEPENDENT ) install(FILES "${PROJECT_BINARY_DIR}/FakeItConfigVersion.cmake" DESTINATION ${FakeIt_CONFIG_DIR}) diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 51883ddd..dc63ea74 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -59,7 +59,7 @@ endif() if(ENABLE_COVERAGE) if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU" OR CMAKE_CXX_COMPILER_ID MATCHES "^(Apple)?Clang$") target_compile_options(FakeIt_tests PRIVATE --coverage) - target_link_libraries(FakeIt_tests PRIVATE --coverage) + target_link_options(FakeIt_tests PRIVATE --coverage) message(STATUS "Code coverage enabled.") else() message(SEND_ERROR "Code coverage requested but compiler is not compatible.") diff --git a/tests/spying_tests.cpp b/tests/spying_tests.cpp index 2d691704..79498ef1 100644 --- a/tests/spying_tests.cpp +++ b/tests/spying_tests.cpp @@ -24,7 +24,7 @@ struct SpyingTests: tpunit::TestFixture { TEST(SpyingTests::mockDestructorDoesNotDeleteObject), // TEST(SpyingTests::canVerifyMethodAfterSpying),// TEST(SpyingTests::canVerifyProcedureAfterSpying), - TEST(SpyingTests::restoreObjectOnMockDelete), + TEST(SpyingTests::restoreObjectOnMockDelete), TEST(SpyingTests::spyMultipleMethods), TEST(SpyingTests::callMemberMethodFromSpiedMethod), TEST(SpyingTests::spyThenVerifyValueArg), @@ -51,12 +51,12 @@ struct SpyingTests: tpunit::TestFixture { virtual int func1(int arg) { return arg; } - virtual int func2(int arg) { - return arg; - } - virtual int func3(int arg) { - return arg; - } + virtual int func2(int arg) { + return arg; + } + virtual int func3(int arg) { + return arg; + } virtual void proc(){ } virtual std::string funcTakeByValue(std::string arg) { @@ -77,18 +77,18 @@ struct SpyingTests: tpunit::TestFixture { } }; - class DerivedClass : public SomeClass { - public: - int func1(int arg) override { - return arg * 2; - } - int func2(int arg) override { - return arg * 2; - } - int func3(int arg) override { - return arg * 2; - } - }; + class DerivedClass : public SomeClass { + public: + int func1(int arg) override { + return arg * 2; + } + int func2(int arg) override { + return arg * 2; + } + int func3(int arg) override { + return arg * 2; + } + }; void useOriginalClassMethodIfNotFaked() { SomeClass obj; From 69100ec81aeb1b775e8c081a98b0eabe9ac4d0bd Mon Sep 17 00:00:00 2001 From: Franck W Date: Mon, 17 Apr 2023 21:30:48 +0200 Subject: [PATCH 19/20] Bumped version to 2.4.0 + generated single header files. --- CMakeLists.txt | 2 +- single_header/boost/fakeit.hpp | 284 +++++++++++++++++++------- single_header/catch/fakeit.hpp | 284 +++++++++++++++++++------- single_header/cute/fakeit.hpp | 284 +++++++++++++++++++------- single_header/doctest/fakeit.hpp | 284 +++++++++++++++++++------- single_header/gtest/fakeit.hpp | 284 +++++++++++++++++++------- single_header/mettle/fakeit.hpp | 284 +++++++++++++++++++------- single_header/mstest/fakeit.hpp | 284 +++++++++++++++++++------- single_header/nunit/fakeit.hpp | 284 +++++++++++++++++++------- single_header/qtest/fakeit.hpp | 284 +++++++++++++++++++------- single_header/standalone/fakeit.hpp | 284 +++++++++++++++++++------- single_header/tpunit/fakeit.hpp | 304 ++++++++++++++++++++-------- 12 files changed, 2294 insertions(+), 852 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 8c4adb62..47537058 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,7 +1,7 @@ # ARCH_INDEPENDENT option at write_basic_package_version_file requires 3.14 version of CMake. cmake_minimum_required(VERSION 3.14) -project(FakeIt VERSION 2.3.2 LANGUAGES CXX) +project(FakeIt VERSION 2.4.0 LANGUAGES CXX) option(ENABLE_TESTING "Enable build of tests." OFF) option(OVERRIDE_CXX_STANDARD_FOR_TESTS "Override the C++ standard used for building tests." "") diff --git a/single_header/boost/fakeit.hpp b/single_header/boost/fakeit.hpp index f7180460..121e963a 100644 --- a/single_header/boost/fakeit.hpp +++ b/single_header/boost/fakeit.hpp @@ -2,7 +2,7 @@ /* * FakeIt - A Simplified C++ Mocking Framework * Copyright (c) Eran Pe'er 2013 - * Generated: 2022-12-16 13:26:48.801805 + * Generated: 2023-04-17 21:28:49.928208 * Distributed under the MIT License. Please refer to the LICENSE file at: * https://github.com/eranpeer/FakeIt */ @@ -18,11 +18,23 @@ #include #include #if defined (__GNUG__) || _MSC_VER >= 1900 -#define FAKEIT_THROWS noexcept(false) -#define FAKEIT_NO_THROWS noexcept(true) +# define FAKEIT_THROWS noexcept(false) +# define FAKEIT_NO_THROWS noexcept(true) #elif defined (_MSC_VER) -#define FAKEIT_THROWS throw(...) -#define FAKEIT_NO_THROWS +# define FAKEIT_THROWS throw(...) +# define FAKEIT_NO_THROWS +#endif + +#ifdef _MSVC_LANG +# define FAKEIT_CPLUSPLUS _MSVC_LANG +#else +# define FAKEIT_CPLUSPLUS __cplusplus +#endif + +#ifdef __GNUG__ +# define FAKEIT_DISARM_UBSAN __attribute__((no_sanitize("undefined"))) +#else +# define FAKEIT_DISARM_UBSAN #endif #include #include @@ -1003,8 +1015,9 @@ namespace fakeit { #include + namespace fakeit { -#if __cplusplus >= 201703L || defined(__cpp_lib_uncaught_exceptions) +#if FAKEIT_CPLUSPLUS >= 201703L || defined(__cpp_lib_uncaught_exceptions) inline bool UncaughtException () { return std::uncaught_exceptions() >= 1; } @@ -5307,6 +5320,7 @@ namespace fakeit { #endif template + FAKEIT_DISARM_UBSAN static typename std::enable_if::value, unsigned int>::type getDestructorOffset() { VirtualOffsetSelector offsetSelctor; @@ -5869,6 +5883,32 @@ namespace fakeit } }; } +#include + +namespace fakeit { + + class Finally { + private: + std::function _finallyClause; + + Finally(const Finally &) = delete; + + Finally &operator=(const Finally &) = delete; + + public: + explicit Finally(std::function f) : + _finallyClause(f) { + } + + Finally(Finally&& other) { + _finallyClause.swap(other._finallyClause); + } + + ~Finally() { + _finallyClause(); + } + }; +} namespace fakeit { struct MethodProxy { @@ -5928,6 +5968,11 @@ namespace fakeit { return MethodProxy(id, offset, union_cast(&MethodProxyCreator::methodProxyX < id > )); } + template + MethodProxy createMethodProxyStatic(unsigned int offset) { + return MethodProxy(id, offset, union_cast(&MethodProxyCreator::methodProxyXStatic < id > )); + } + protected: R methodProxy(unsigned int id, const typename fakeit::production_arg::type... args) { @@ -5943,6 +5988,20 @@ namespace fakeit { R methodProxyX(arglist ... args) { return methodProxy(id, std::forward::type>(args)...); } + + static R methodProxyStatic(void* instance, unsigned int id, const typename fakeit::production_arg::type... args) { + InvocationHandlerCollection *invocationHandlerCollection = InvocationHandlerCollection::getInvocationHandlerCollection( + instance); + MethodInvocationHandler *invocationHandler = + (MethodInvocationHandler *) invocationHandlerCollection->getInvocatoinHandlerPtrById( + id); + return invocationHandler->handleMethodInvocation(std::forward::type>(args)...); + } + + template + static R methodProxyXStatic(void* instance, arglist ... args) { + return methodProxyStatic(instance, id, std::forward::type>(args)...); + } }; } @@ -6033,7 +6092,17 @@ namespace fakeit { void stubDtor(MethodInvocationHandler *methodInvocationHandler) { auto offset = VTUtils::getDestructorOffset(); MethodProxyCreator creator; + + + + + + +#ifdef _MSC_VER + bindDtor(creator.createMethodProxyStatic<0>(offset), methodInvocationHandler); +#else bindDtor(creator.createMethodProxy<0>(offset), methodInvocationHandler); +#endif } template @@ -6086,6 +6155,18 @@ namespace fakeit { return vt; } + template + Finally createRaiiMethodSwapper(R(C::*vMethod)(arglist...)) { + auto offset = VTUtils::getOffset(vMethod); + auto fakeMethod = getFake().getVirtualTable().getMethod(offset); + auto originalMethod = getOriginalVT().getMethod(offset); + + getFake().setMethod(offset, originalMethod); + return Finally{[&, offset, fakeMethod](){ + getFake().setMethod(offset, fakeMethod); + }}; + } + private: template @@ -7600,7 +7681,7 @@ namespace fakeit { MethodStubbingProgress &operator=(const MethodStubbingProgress &other) = delete; template -#if __cplusplus >= 201402L +#if FAKEIT_CPLUSPLUS >= 201402L auto #else std::function::type...)> @@ -7625,7 +7706,7 @@ namespace fakeit { } template -#if __cplusplus >= 201402L +#if FAKEIT_CPLUSPLUS >= 201402L auto #else std::function::type...)> @@ -7744,7 +7825,7 @@ namespace fakeit { MethodStubbingProgress &operator=(const MethodStubbingProgress &other) = delete; template -#if __cplusplus >= 201402L +#if FAKEIT_CPLUSPLUS >= 201402L auto #else std::function::type...)> @@ -7768,7 +7849,7 @@ namespace fakeit { } template -#if __cplusplus >= 201402L +#if FAKEIT_CPLUSPLUS >= 201402L auto #else std::function::type...)> @@ -7810,7 +7891,7 @@ namespace fakeit { template static void CheckPositions(const std::tuple...> arg_vals) { -#if __cplusplus >= 201402L && !defined(_WIN32) +#if FAKEIT_CPLUSPLUS >= 201402L && !defined(_WIN32) static_assert(std::get(arg_vals).pos <= max_index, "Argument index out of range"); ArgValidator::CheckPositions(arg_vals); @@ -7862,7 +7943,7 @@ namespace fakeit { struct ArgLocator { template static void AssignArg(current_arg &&p, std::tuple...> arg_vals) { -#if __cplusplus >= 201703L && !defined (_WIN32) +#if FAKEIT_CPLUSPLUS >= 201703L && !defined (_WIN32) if constexpr (std::get(arg_vals).pos == arg_index) GetArg(std::forward(p)) = std::get(arg_vals).value; #else @@ -7873,7 +7954,7 @@ namespace fakeit { ArgLocator::AssignArg(std::forward(p), arg_vals); } -#if __cplusplus < 201703L || defined (_WIN32) +#if FAKEIT_CPLUSPLUS < 201703L || defined (_WIN32) private: template static @@ -7931,28 +8012,8 @@ namespace fakeit { using placeholders::operator <=; } #include -#include - -namespace fakeit { - - class Finally { - private: - std::function _finallyClause; - - Finally(const Finally &); - Finally &operator=(const Finally &); - public: - explicit Finally(std::function f) : - _finallyClause(f) { - } - - ~Finally() { - _finallyClause(); - } - }; -} namespace fakeit { @@ -8669,11 +8730,12 @@ namespace fakeit { template::value...>::value, int>::type = 0> std::function getOriginalMethodCopyArgsInternal(int) { - void *mPtr = MethodMockingContextBase::_mock.getOriginalMethod(_vMethod); + auto mPtr = _vMethod; + auto& mock = MethodMockingContextBase::_mock; C * instance = &(MethodMockingContextBase::_mock.get()); - return [=](arglist&... args) -> R { - auto m = union_cast::type>(mPtr); - return m(instance, args...); + return [=, &mock](arglist&... args) -> R { + auto methodSwapper = mock.createRaiiMethodSwapper(mPtr); + return (instance->*mPtr)(args...); }; } @@ -8689,11 +8751,12 @@ namespace fakeit { } std::function getOriginalMethodForwardArgs() override { - void *mPtr = MethodMockingContextBase::_mock.getOriginalMethod(_vMethod); + auto mPtr = _vMethod; + auto& mock = MethodMockingContextBase::_mock; C * instance = &(MethodMockingContextBase::_mock.get()); - return [=](arglist&... args) -> R { - auto m = union_cast::type>(mPtr); - return m(instance, std::forward(args)...); + return [=, &mock](arglist&... args) -> R { + auto methodSwapper = mock.createRaiiMethodSwapper(mPtr); + return (instance->*mPtr)(std::forward(args)...); }; } }; @@ -8776,6 +8839,11 @@ namespace fakeit { return reinterpret_cast(fake); } + template + Finally createRaiiMethodSwapper(R(C::*vMethod)(arglist...)) { + return _proxy.createRaiiMethodSwapper(vMethod); + } + template void *getOriginalMethod(R (C::*vMethod)(arglist...)) { auto vt = _proxy.getOriginalVT(); @@ -8830,21 +8898,37 @@ namespace fakeit { template struct Prototype { - typedef R Type(Args...); - - typedef R ConstType(Args...) const; - template struct MemberType { - typedef Type(C::*type); - typedef ConstType(C::*cosntType); + using Type = R (C::*)(Args...); + using ConstType = R (C::*)(Args...) const; + using RefType = R (C::*)(Args...) &; + using ConstRefType = R (C::*)(Args...) const&; + using RValRefType = R (C::*)(Args...) &&; + using ConstRValRefType = R (C::*)(Args...) const&&; + + static Type get(Type t) { + return t; + } + + static ConstType getConst(ConstType t) { + return t; + } + + static RefType getRef(RefType t) { + return t; + } + + static ConstRefType getConstRef(ConstRefType t) { + return t; + } - static type get(type t) { + static RValRefType getRValRef(RValRefType t) { return t; } - static cosntType getconst(cosntType t) { + static ConstRValRefType getConstRValRef(ConstRValRefType t) { return t; } @@ -8869,11 +8953,25 @@ namespace fakeit { } - namespace fakeit { namespace internal { + template + struct WithCommonVoid { + using type = T; + }; + + + + + + template + struct WithCommonVoid::value, void>::type> { + using type = void; + }; + + template + using WithCommonVoid_t = typename WithCommonVoid::type; } - using namespace fakeit::internal; template class Mock : public ActualInvocationsSource { @@ -8915,58 +9013,67 @@ namespace fakeit { return impl.stubDataMember(member, ctorargs...); } + template::value && std::is_base_of::value>::type> - MockingContext stub(R (T::*vMethod)(arglist...) const) { - auto methodWithoutConstVolatile = reinterpret_cast(vMethod); + std::is_base_of::value>::type> + MockingContext, arglist...> stub(R (T::*vMethod)(arglist...) const) { + auto methodWithoutConstVolatile = reinterpret_cast (T::*)(arglist...)>(vMethod); return impl.template stubMethod(methodWithoutConstVolatile); } + template::value && std::is_base_of::value>::type> - MockingContext stub(R(T::*vMethod)(arglist...) volatile) { - auto methodWithoutConstVolatile = reinterpret_cast(vMethod); + std::is_base_of::value>::type> + MockingContext, arglist...> stub(R(T::*vMethod)(arglist...) volatile) { + auto methodWithoutConstVolatile = reinterpret_cast(T::*)(arglist...)>(vMethod); return impl.template stubMethod(methodWithoutConstVolatile); } + template::value && std::is_base_of::value>::type> - MockingContext stub(R(T::*vMethod)(arglist...) const volatile) { - auto methodWithoutConstVolatile = reinterpret_cast(vMethod); + std::is_base_of::value>::type> + MockingContext, arglist...> stub(R(T::*vMethod)(arglist...) const volatile) { + auto methodWithoutConstVolatile = reinterpret_cast(T::*)(arglist...)>(vMethod); return impl.template stubMethod(methodWithoutConstVolatile); } + template::value && std::is_base_of::value>::type> - MockingContext stub(R(T::*vMethod)(arglist...)) { - return impl.template stubMethod(vMethod); + std::is_base_of::value>::type> + MockingContext, arglist...> stub(R(T::*vMethod)(arglist...)) { + auto methodWithoutConstVolatile = reinterpret_cast(T::*)(arglist...)>(vMethod); + return impl.template stubMethod(methodWithoutConstVolatile); } + template::value && std::is_base_of::value>::type> - MockingContext stub(R(T::*vMethod)(arglist...) const) { - auto methodWithoutConstVolatile = reinterpret_cast(vMethod); + std::is_base_of::value>::type> + MockingContext, arglist...> stub(R(T::*vMethod)(arglist...) &) { + auto methodWithoutConstVolatile = reinterpret_cast(T::*)(arglist...)>(vMethod); return impl.template stubMethod(methodWithoutConstVolatile); } + template::value && std::is_base_of::value>::type> - MockingContext stub(R(T::*vMethod)(arglist...) volatile) { - auto methodWithoutConstVolatile = reinterpret_cast(vMethod); + std::is_base_of::value>::type> + MockingContext, arglist...> stub(R(T::*vMethod)(arglist...) const&) { + auto methodWithoutConstVolatile = reinterpret_cast(T::*)(arglist...)>(vMethod); return impl.template stubMethod(methodWithoutConstVolatile); } + template::value && std::is_base_of::value>::type> - MockingContext stub(R(T::*vMethod)(arglist...) const volatile) { - auto methodWithoutConstVolatile = reinterpret_cast(vMethod); + std::is_base_of::value>::type> + MockingContext, arglist...> stub(R(T::*vMethod)(arglist...) &&) { + auto methodWithoutConstVolatile = reinterpret_cast(T::*)(arglist...)>(vMethod); return impl.template stubMethod(methodWithoutConstVolatile); } + template::value && std::is_base_of::value>::type> - MockingContext stub(R(T::*vMethod)(arglist...)) { - auto methodWithoutConstVolatile = reinterpret_cast(vMethod); + std::is_base_of::value>::type> + MockingContext, arglist...> stub(R(T::*vMethod)(arglist...) const&&) { + auto methodWithoutConstVolatile = reinterpret_cast(T::*)(arglist...)>(vMethod); return impl.template stubMethod(methodWithoutConstVolatile); } @@ -10002,7 +10109,19 @@ namespace fakeit { fakeit::Prototype::template MemberType::get(&MOCK_TYPE(mock)::method) #define CONST_OVERLOADED_METHOD_PTR(mock, method, prototype) \ - fakeit::Prototype::template MemberType::getconst(&MOCK_TYPE(mock)::method) + fakeit::Prototype::template MemberType::getConst(&MOCK_TYPE(mock)::method) + +#define REF_OVERLOADED_METHOD_PTR(mock, method, prototype) \ + fakeit::Prototype::MemberType::getRef(&MOCK_TYPE(mock)::method) + +#define CONST_REF_OVERLOADED_METHOD_PTR(mock, method, prototype) \ + fakeit::Prototype::MemberType::getConstRef(&MOCK_TYPE(mock)::method) + +#define R_VAL_REF_OVERLOADED_METHOD_PTR(mock, method, prototype) \ + fakeit::Prototype::MemberType::getRValRef(&MOCK_TYPE(mock)::method) + +#define CONST_R_VAL_REF_OVERLOADED_METHOD_PTR(mock, method, prototype) \ + fakeit::Prototype::MemberType::getConstRValRef(&MOCK_TYPE(mock)::method) #define Dtor(mock) \ (mock).dtor().setMethodDetails(#mock,"destructor") @@ -10016,6 +10135,18 @@ namespace fakeit { #define ConstOverloadedMethod(mock, method, prototype) \ (mock).template stub<__COUNTER__>(CONST_OVERLOADED_METHOD_PTR( mock , method, prototype )).setMethodDetails(#mock,#method) +#define RefOverloadedMethod(mock, method, prototype) \ + (mock).template stub<__COUNTER__>(REF_OVERLOADED_METHOD_PTR( mock , method, prototype )).setMethodDetails(#mock,#method) + +#define ConstRefOverloadedMethod(mock, method, prototype) \ + (mock).template stub<__COUNTER__>(CONST_REF_OVERLOADED_METHOD_PTR( mock , method, prototype )).setMethodDetails(#mock,#method) + +#define RValRefOverloadedMethod(mock, method, prototype) \ + (mock).template stub<__COUNTER__>(R_VAL_REF_OVERLOADED_METHOD_PTR( mock , method, prototype )).setMethodDetails(#mock,#method) + +#define ConstRValRefOverloadedMethod(mock, method, prototype) \ + (mock).template stub<__COUNTER__>(CONST_R_VAL_REF_OVERLOADED_METHOD_PTR( mock , method, prototype )).setMethodDetails(#mock,#method) + #define Verify(...) \ Verify( __VA_ARGS__ ).setFileInfo(__FILE__, __LINE__, __func__) @@ -10031,5 +10162,4 @@ namespace fakeit { #define When(call) \ When(call) - #endif diff --git a/single_header/catch/fakeit.hpp b/single_header/catch/fakeit.hpp index 080bae35..90468539 100644 --- a/single_header/catch/fakeit.hpp +++ b/single_header/catch/fakeit.hpp @@ -2,7 +2,7 @@ /* * FakeIt - A Simplified C++ Mocking Framework * Copyright (c) Eran Pe'er 2013 - * Generated: 2022-12-16 13:26:49.112179 + * Generated: 2023-04-17 21:28:50.210014 * Distributed under the MIT License. Please refer to the LICENSE file at: * https://github.com/eranpeer/FakeIt */ @@ -18,11 +18,23 @@ #include #include #if defined (__GNUG__) || _MSC_VER >= 1900 -#define FAKEIT_THROWS noexcept(false) -#define FAKEIT_NO_THROWS noexcept(true) +# define FAKEIT_THROWS noexcept(false) +# define FAKEIT_NO_THROWS noexcept(true) #elif defined (_MSC_VER) -#define FAKEIT_THROWS throw(...) -#define FAKEIT_NO_THROWS +# define FAKEIT_THROWS throw(...) +# define FAKEIT_NO_THROWS +#endif + +#ifdef _MSVC_LANG +# define FAKEIT_CPLUSPLUS _MSVC_LANG +#else +# define FAKEIT_CPLUSPLUS __cplusplus +#endif + +#ifdef __GNUG__ +# define FAKEIT_DISARM_UBSAN __attribute__((no_sanitize("undefined"))) +#else +# define FAKEIT_DISARM_UBSAN #endif #include #include @@ -1003,8 +1015,9 @@ namespace fakeit { #include + namespace fakeit { -#if __cplusplus >= 201703L || defined(__cpp_lib_uncaught_exceptions) +#if FAKEIT_CPLUSPLUS >= 201703L || defined(__cpp_lib_uncaught_exceptions) inline bool UncaughtException () { return std::uncaught_exceptions() >= 1; } @@ -5345,6 +5358,7 @@ namespace fakeit { #endif template + FAKEIT_DISARM_UBSAN static typename std::enable_if::value, unsigned int>::type getDestructorOffset() { VirtualOffsetSelector offsetSelctor; @@ -5907,6 +5921,32 @@ namespace fakeit } }; } +#include + +namespace fakeit { + + class Finally { + private: + std::function _finallyClause; + + Finally(const Finally &) = delete; + + Finally &operator=(const Finally &) = delete; + + public: + explicit Finally(std::function f) : + _finallyClause(f) { + } + + Finally(Finally&& other) { + _finallyClause.swap(other._finallyClause); + } + + ~Finally() { + _finallyClause(); + } + }; +} namespace fakeit { struct MethodProxy { @@ -5966,6 +6006,11 @@ namespace fakeit { return MethodProxy(id, offset, union_cast(&MethodProxyCreator::methodProxyX < id > )); } + template + MethodProxy createMethodProxyStatic(unsigned int offset) { + return MethodProxy(id, offset, union_cast(&MethodProxyCreator::methodProxyXStatic < id > )); + } + protected: R methodProxy(unsigned int id, const typename fakeit::production_arg::type... args) { @@ -5981,6 +6026,20 @@ namespace fakeit { R methodProxyX(arglist ... args) { return methodProxy(id, std::forward::type>(args)...); } + + static R methodProxyStatic(void* instance, unsigned int id, const typename fakeit::production_arg::type... args) { + InvocationHandlerCollection *invocationHandlerCollection = InvocationHandlerCollection::getInvocationHandlerCollection( + instance); + MethodInvocationHandler *invocationHandler = + (MethodInvocationHandler *) invocationHandlerCollection->getInvocatoinHandlerPtrById( + id); + return invocationHandler->handleMethodInvocation(std::forward::type>(args)...); + } + + template + static R methodProxyXStatic(void* instance, arglist ... args) { + return methodProxyStatic(instance, id, std::forward::type>(args)...); + } }; } @@ -6071,7 +6130,17 @@ namespace fakeit { void stubDtor(MethodInvocationHandler *methodInvocationHandler) { auto offset = VTUtils::getDestructorOffset(); MethodProxyCreator creator; + + + + + + +#ifdef _MSC_VER + bindDtor(creator.createMethodProxyStatic<0>(offset), methodInvocationHandler); +#else bindDtor(creator.createMethodProxy<0>(offset), methodInvocationHandler); +#endif } template @@ -6124,6 +6193,18 @@ namespace fakeit { return vt; } + template + Finally createRaiiMethodSwapper(R(C::*vMethod)(arglist...)) { + auto offset = VTUtils::getOffset(vMethod); + auto fakeMethod = getFake().getVirtualTable().getMethod(offset); + auto originalMethod = getOriginalVT().getMethod(offset); + + getFake().setMethod(offset, originalMethod); + return Finally{[&, offset, fakeMethod](){ + getFake().setMethod(offset, fakeMethod); + }}; + } + private: template @@ -7638,7 +7719,7 @@ namespace fakeit { MethodStubbingProgress &operator=(const MethodStubbingProgress &other) = delete; template -#if __cplusplus >= 201402L +#if FAKEIT_CPLUSPLUS >= 201402L auto #else std::function::type...)> @@ -7663,7 +7744,7 @@ namespace fakeit { } template -#if __cplusplus >= 201402L +#if FAKEIT_CPLUSPLUS >= 201402L auto #else std::function::type...)> @@ -7782,7 +7863,7 @@ namespace fakeit { MethodStubbingProgress &operator=(const MethodStubbingProgress &other) = delete; template -#if __cplusplus >= 201402L +#if FAKEIT_CPLUSPLUS >= 201402L auto #else std::function::type...)> @@ -7806,7 +7887,7 @@ namespace fakeit { } template -#if __cplusplus >= 201402L +#if FAKEIT_CPLUSPLUS >= 201402L auto #else std::function::type...)> @@ -7848,7 +7929,7 @@ namespace fakeit { template static void CheckPositions(const std::tuple...> arg_vals) { -#if __cplusplus >= 201402L && !defined(_WIN32) +#if FAKEIT_CPLUSPLUS >= 201402L && !defined(_WIN32) static_assert(std::get(arg_vals).pos <= max_index, "Argument index out of range"); ArgValidator::CheckPositions(arg_vals); @@ -7900,7 +7981,7 @@ namespace fakeit { struct ArgLocator { template static void AssignArg(current_arg &&p, std::tuple...> arg_vals) { -#if __cplusplus >= 201703L && !defined (_WIN32) +#if FAKEIT_CPLUSPLUS >= 201703L && !defined (_WIN32) if constexpr (std::get(arg_vals).pos == arg_index) GetArg(std::forward(p)) = std::get(arg_vals).value; #else @@ -7911,7 +7992,7 @@ namespace fakeit { ArgLocator::AssignArg(std::forward(p), arg_vals); } -#if __cplusplus < 201703L || defined (_WIN32) +#if FAKEIT_CPLUSPLUS < 201703L || defined (_WIN32) private: template static @@ -7969,28 +8050,8 @@ namespace fakeit { using placeholders::operator <=; } #include -#include - -namespace fakeit { - - class Finally { - private: - std::function _finallyClause; - - Finally(const Finally &); - Finally &operator=(const Finally &); - public: - explicit Finally(std::function f) : - _finallyClause(f) { - } - - ~Finally() { - _finallyClause(); - } - }; -} namespace fakeit { @@ -8707,11 +8768,12 @@ namespace fakeit { template::value...>::value, int>::type = 0> std::function getOriginalMethodCopyArgsInternal(int) { - void *mPtr = MethodMockingContextBase::_mock.getOriginalMethod(_vMethod); + auto mPtr = _vMethod; + auto& mock = MethodMockingContextBase::_mock; C * instance = &(MethodMockingContextBase::_mock.get()); - return [=](arglist&... args) -> R { - auto m = union_cast::type>(mPtr); - return m(instance, args...); + return [=, &mock](arglist&... args) -> R { + auto methodSwapper = mock.createRaiiMethodSwapper(mPtr); + return (instance->*mPtr)(args...); }; } @@ -8727,11 +8789,12 @@ namespace fakeit { } std::function getOriginalMethodForwardArgs() override { - void *mPtr = MethodMockingContextBase::_mock.getOriginalMethod(_vMethod); + auto mPtr = _vMethod; + auto& mock = MethodMockingContextBase::_mock; C * instance = &(MethodMockingContextBase::_mock.get()); - return [=](arglist&... args) -> R { - auto m = union_cast::type>(mPtr); - return m(instance, std::forward(args)...); + return [=, &mock](arglist&... args) -> R { + auto methodSwapper = mock.createRaiiMethodSwapper(mPtr); + return (instance->*mPtr)(std::forward(args)...); }; } }; @@ -8814,6 +8877,11 @@ namespace fakeit { return reinterpret_cast(fake); } + template + Finally createRaiiMethodSwapper(R(C::*vMethod)(arglist...)) { + return _proxy.createRaiiMethodSwapper(vMethod); + } + template void *getOriginalMethod(R (C::*vMethod)(arglist...)) { auto vt = _proxy.getOriginalVT(); @@ -8868,21 +8936,37 @@ namespace fakeit { template struct Prototype { - typedef R Type(Args...); - - typedef R ConstType(Args...) const; - template struct MemberType { - typedef Type(C::*type); - typedef ConstType(C::*cosntType); + using Type = R (C::*)(Args...); + using ConstType = R (C::*)(Args...) const; + using RefType = R (C::*)(Args...) &; + using ConstRefType = R (C::*)(Args...) const&; + using RValRefType = R (C::*)(Args...) &&; + using ConstRValRefType = R (C::*)(Args...) const&&; + + static Type get(Type t) { + return t; + } + + static ConstType getConst(ConstType t) { + return t; + } + + static RefType getRef(RefType t) { + return t; + } + + static ConstRefType getConstRef(ConstRefType t) { + return t; + } - static type get(type t) { + static RValRefType getRValRef(RValRefType t) { return t; } - static cosntType getconst(cosntType t) { + static ConstRValRefType getConstRValRef(ConstRValRefType t) { return t; } @@ -8907,11 +8991,25 @@ namespace fakeit { } - namespace fakeit { namespace internal { + template + struct WithCommonVoid { + using type = T; + }; + + + + + + template + struct WithCommonVoid::value, void>::type> { + using type = void; + }; + + template + using WithCommonVoid_t = typename WithCommonVoid::type; } - using namespace fakeit::internal; template class Mock : public ActualInvocationsSource { @@ -8953,58 +9051,67 @@ namespace fakeit { return impl.stubDataMember(member, ctorargs...); } + template::value && std::is_base_of::value>::type> - MockingContext stub(R (T::*vMethod)(arglist...) const) { - auto methodWithoutConstVolatile = reinterpret_cast(vMethod); + std::is_base_of::value>::type> + MockingContext, arglist...> stub(R (T::*vMethod)(arglist...) const) { + auto methodWithoutConstVolatile = reinterpret_cast (T::*)(arglist...)>(vMethod); return impl.template stubMethod(methodWithoutConstVolatile); } + template::value && std::is_base_of::value>::type> - MockingContext stub(R(T::*vMethod)(arglist...) volatile) { - auto methodWithoutConstVolatile = reinterpret_cast(vMethod); + std::is_base_of::value>::type> + MockingContext, arglist...> stub(R(T::*vMethod)(arglist...) volatile) { + auto methodWithoutConstVolatile = reinterpret_cast(T::*)(arglist...)>(vMethod); return impl.template stubMethod(methodWithoutConstVolatile); } + template::value && std::is_base_of::value>::type> - MockingContext stub(R(T::*vMethod)(arglist...) const volatile) { - auto methodWithoutConstVolatile = reinterpret_cast(vMethod); + std::is_base_of::value>::type> + MockingContext, arglist...> stub(R(T::*vMethod)(arglist...) const volatile) { + auto methodWithoutConstVolatile = reinterpret_cast(T::*)(arglist...)>(vMethod); return impl.template stubMethod(methodWithoutConstVolatile); } + template::value && std::is_base_of::value>::type> - MockingContext stub(R(T::*vMethod)(arglist...)) { - return impl.template stubMethod(vMethod); + std::is_base_of::value>::type> + MockingContext, arglist...> stub(R(T::*vMethod)(arglist...)) { + auto methodWithoutConstVolatile = reinterpret_cast(T::*)(arglist...)>(vMethod); + return impl.template stubMethod(methodWithoutConstVolatile); } + template::value && std::is_base_of::value>::type> - MockingContext stub(R(T::*vMethod)(arglist...) const) { - auto methodWithoutConstVolatile = reinterpret_cast(vMethod); + std::is_base_of::value>::type> + MockingContext, arglist...> stub(R(T::*vMethod)(arglist...) &) { + auto methodWithoutConstVolatile = reinterpret_cast(T::*)(arglist...)>(vMethod); return impl.template stubMethod(methodWithoutConstVolatile); } + template::value && std::is_base_of::value>::type> - MockingContext stub(R(T::*vMethod)(arglist...) volatile) { - auto methodWithoutConstVolatile = reinterpret_cast(vMethod); + std::is_base_of::value>::type> + MockingContext, arglist...> stub(R(T::*vMethod)(arglist...) const&) { + auto methodWithoutConstVolatile = reinterpret_cast(T::*)(arglist...)>(vMethod); return impl.template stubMethod(methodWithoutConstVolatile); } + template::value && std::is_base_of::value>::type> - MockingContext stub(R(T::*vMethod)(arglist...) const volatile) { - auto methodWithoutConstVolatile = reinterpret_cast(vMethod); + std::is_base_of::value>::type> + MockingContext, arglist...> stub(R(T::*vMethod)(arglist...) &&) { + auto methodWithoutConstVolatile = reinterpret_cast(T::*)(arglist...)>(vMethod); return impl.template stubMethod(methodWithoutConstVolatile); } + template::value && std::is_base_of::value>::type> - MockingContext stub(R(T::*vMethod)(arglist...)) { - auto methodWithoutConstVolatile = reinterpret_cast(vMethod); + std::is_base_of::value>::type> + MockingContext, arglist...> stub(R(T::*vMethod)(arglist...) const&&) { + auto methodWithoutConstVolatile = reinterpret_cast(T::*)(arglist...)>(vMethod); return impl.template stubMethod(methodWithoutConstVolatile); } @@ -10026,7 +10133,19 @@ namespace fakeit { fakeit::Prototype::template MemberType::get(&MOCK_TYPE(mock)::method) #define CONST_OVERLOADED_METHOD_PTR(mock, method, prototype) \ - fakeit::Prototype::template MemberType::getconst(&MOCK_TYPE(mock)::method) + fakeit::Prototype::template MemberType::getConst(&MOCK_TYPE(mock)::method) + +#define REF_OVERLOADED_METHOD_PTR(mock, method, prototype) \ + fakeit::Prototype::MemberType::getRef(&MOCK_TYPE(mock)::method) + +#define CONST_REF_OVERLOADED_METHOD_PTR(mock, method, prototype) \ + fakeit::Prototype::MemberType::getConstRef(&MOCK_TYPE(mock)::method) + +#define R_VAL_REF_OVERLOADED_METHOD_PTR(mock, method, prototype) \ + fakeit::Prototype::MemberType::getRValRef(&MOCK_TYPE(mock)::method) + +#define CONST_R_VAL_REF_OVERLOADED_METHOD_PTR(mock, method, prototype) \ + fakeit::Prototype::MemberType::getConstRValRef(&MOCK_TYPE(mock)::method) #define Dtor(mock) \ (mock).dtor().setMethodDetails(#mock,"destructor") @@ -10040,6 +10159,18 @@ namespace fakeit { #define ConstOverloadedMethod(mock, method, prototype) \ (mock).template stub<__COUNTER__>(CONST_OVERLOADED_METHOD_PTR( mock , method, prototype )).setMethodDetails(#mock,#method) +#define RefOverloadedMethod(mock, method, prototype) \ + (mock).template stub<__COUNTER__>(REF_OVERLOADED_METHOD_PTR( mock , method, prototype )).setMethodDetails(#mock,#method) + +#define ConstRefOverloadedMethod(mock, method, prototype) \ + (mock).template stub<__COUNTER__>(CONST_REF_OVERLOADED_METHOD_PTR( mock , method, prototype )).setMethodDetails(#mock,#method) + +#define RValRefOverloadedMethod(mock, method, prototype) \ + (mock).template stub<__COUNTER__>(R_VAL_REF_OVERLOADED_METHOD_PTR( mock , method, prototype )).setMethodDetails(#mock,#method) + +#define ConstRValRefOverloadedMethod(mock, method, prototype) \ + (mock).template stub<__COUNTER__>(CONST_R_VAL_REF_OVERLOADED_METHOD_PTR( mock , method, prototype )).setMethodDetails(#mock,#method) + #define Verify(...) \ Verify( __VA_ARGS__ ).setFileInfo(__FILE__, __LINE__, __func__) @@ -10055,5 +10186,4 @@ namespace fakeit { #define When(call) \ When(call) - #endif diff --git a/single_header/cute/fakeit.hpp b/single_header/cute/fakeit.hpp index 59bae8c8..538fae80 100644 --- a/single_header/cute/fakeit.hpp +++ b/single_header/cute/fakeit.hpp @@ -2,7 +2,7 @@ /* * FakeIt - A Simplified C++ Mocking Framework * Copyright (c) Eran Pe'er 2013 - * Generated: 2022-12-16 13:26:49.412618 + * Generated: 2023-04-17 21:28:50.478194 * Distributed under the MIT License. Please refer to the LICENSE file at: * https://github.com/eranpeer/FakeIt */ @@ -18,11 +18,23 @@ #include #include #if defined (__GNUG__) || _MSC_VER >= 1900 -#define FAKEIT_THROWS noexcept(false) -#define FAKEIT_NO_THROWS noexcept(true) +# define FAKEIT_THROWS noexcept(false) +# define FAKEIT_NO_THROWS noexcept(true) #elif defined (_MSC_VER) -#define FAKEIT_THROWS throw(...) -#define FAKEIT_NO_THROWS +# define FAKEIT_THROWS throw(...) +# define FAKEIT_NO_THROWS +#endif + +#ifdef _MSVC_LANG +# define FAKEIT_CPLUSPLUS _MSVC_LANG +#else +# define FAKEIT_CPLUSPLUS __cplusplus +#endif + +#ifdef __GNUG__ +# define FAKEIT_DISARM_UBSAN __attribute__((no_sanitize("undefined"))) +#else +# define FAKEIT_DISARM_UBSAN #endif #include #include @@ -1003,8 +1015,9 @@ namespace fakeit { #include + namespace fakeit { -#if __cplusplus >= 201703L || defined(__cpp_lib_uncaught_exceptions) +#if FAKEIT_CPLUSPLUS >= 201703L || defined(__cpp_lib_uncaught_exceptions) inline bool UncaughtException () { return std::uncaught_exceptions() >= 1; } @@ -5272,6 +5285,7 @@ namespace fakeit { #endif template + FAKEIT_DISARM_UBSAN static typename std::enable_if::value, unsigned int>::type getDestructorOffset() { VirtualOffsetSelector offsetSelctor; @@ -5834,6 +5848,32 @@ namespace fakeit } }; } +#include + +namespace fakeit { + + class Finally { + private: + std::function _finallyClause; + + Finally(const Finally &) = delete; + + Finally &operator=(const Finally &) = delete; + + public: + explicit Finally(std::function f) : + _finallyClause(f) { + } + + Finally(Finally&& other) { + _finallyClause.swap(other._finallyClause); + } + + ~Finally() { + _finallyClause(); + } + }; +} namespace fakeit { struct MethodProxy { @@ -5893,6 +5933,11 @@ namespace fakeit { return MethodProxy(id, offset, union_cast(&MethodProxyCreator::methodProxyX < id > )); } + template + MethodProxy createMethodProxyStatic(unsigned int offset) { + return MethodProxy(id, offset, union_cast(&MethodProxyCreator::methodProxyXStatic < id > )); + } + protected: R methodProxy(unsigned int id, const typename fakeit::production_arg::type... args) { @@ -5908,6 +5953,20 @@ namespace fakeit { R methodProxyX(arglist ... args) { return methodProxy(id, std::forward::type>(args)...); } + + static R methodProxyStatic(void* instance, unsigned int id, const typename fakeit::production_arg::type... args) { + InvocationHandlerCollection *invocationHandlerCollection = InvocationHandlerCollection::getInvocationHandlerCollection( + instance); + MethodInvocationHandler *invocationHandler = + (MethodInvocationHandler *) invocationHandlerCollection->getInvocatoinHandlerPtrById( + id); + return invocationHandler->handleMethodInvocation(std::forward::type>(args)...); + } + + template + static R methodProxyXStatic(void* instance, arglist ... args) { + return methodProxyStatic(instance, id, std::forward::type>(args)...); + } }; } @@ -5998,7 +6057,17 @@ namespace fakeit { void stubDtor(MethodInvocationHandler *methodInvocationHandler) { auto offset = VTUtils::getDestructorOffset(); MethodProxyCreator creator; + + + + + + +#ifdef _MSC_VER + bindDtor(creator.createMethodProxyStatic<0>(offset), methodInvocationHandler); +#else bindDtor(creator.createMethodProxy<0>(offset), methodInvocationHandler); +#endif } template @@ -6051,6 +6120,18 @@ namespace fakeit { return vt; } + template + Finally createRaiiMethodSwapper(R(C::*vMethod)(arglist...)) { + auto offset = VTUtils::getOffset(vMethod); + auto fakeMethod = getFake().getVirtualTable().getMethod(offset); + auto originalMethod = getOriginalVT().getMethod(offset); + + getFake().setMethod(offset, originalMethod); + return Finally{[&, offset, fakeMethod](){ + getFake().setMethod(offset, fakeMethod); + }}; + } + private: template @@ -7565,7 +7646,7 @@ namespace fakeit { MethodStubbingProgress &operator=(const MethodStubbingProgress &other) = delete; template -#if __cplusplus >= 201402L +#if FAKEIT_CPLUSPLUS >= 201402L auto #else std::function::type...)> @@ -7590,7 +7671,7 @@ namespace fakeit { } template -#if __cplusplus >= 201402L +#if FAKEIT_CPLUSPLUS >= 201402L auto #else std::function::type...)> @@ -7709,7 +7790,7 @@ namespace fakeit { MethodStubbingProgress &operator=(const MethodStubbingProgress &other) = delete; template -#if __cplusplus >= 201402L +#if FAKEIT_CPLUSPLUS >= 201402L auto #else std::function::type...)> @@ -7733,7 +7814,7 @@ namespace fakeit { } template -#if __cplusplus >= 201402L +#if FAKEIT_CPLUSPLUS >= 201402L auto #else std::function::type...)> @@ -7775,7 +7856,7 @@ namespace fakeit { template static void CheckPositions(const std::tuple...> arg_vals) { -#if __cplusplus >= 201402L && !defined(_WIN32) +#if FAKEIT_CPLUSPLUS >= 201402L && !defined(_WIN32) static_assert(std::get(arg_vals).pos <= max_index, "Argument index out of range"); ArgValidator::CheckPositions(arg_vals); @@ -7827,7 +7908,7 @@ namespace fakeit { struct ArgLocator { template static void AssignArg(current_arg &&p, std::tuple...> arg_vals) { -#if __cplusplus >= 201703L && !defined (_WIN32) +#if FAKEIT_CPLUSPLUS >= 201703L && !defined (_WIN32) if constexpr (std::get(arg_vals).pos == arg_index) GetArg(std::forward(p)) = std::get(arg_vals).value; #else @@ -7838,7 +7919,7 @@ namespace fakeit { ArgLocator::AssignArg(std::forward(p), arg_vals); } -#if __cplusplus < 201703L || defined (_WIN32) +#if FAKEIT_CPLUSPLUS < 201703L || defined (_WIN32) private: template static @@ -7896,28 +7977,8 @@ namespace fakeit { using placeholders::operator <=; } #include -#include - -namespace fakeit { - - class Finally { - private: - std::function _finallyClause; - - Finally(const Finally &); - Finally &operator=(const Finally &); - public: - explicit Finally(std::function f) : - _finallyClause(f) { - } - - ~Finally() { - _finallyClause(); - } - }; -} namespace fakeit { @@ -8634,11 +8695,12 @@ namespace fakeit { template::value...>::value, int>::type = 0> std::function getOriginalMethodCopyArgsInternal(int) { - void *mPtr = MethodMockingContextBase::_mock.getOriginalMethod(_vMethod); + auto mPtr = _vMethod; + auto& mock = MethodMockingContextBase::_mock; C * instance = &(MethodMockingContextBase::_mock.get()); - return [=](arglist&... args) -> R { - auto m = union_cast::type>(mPtr); - return m(instance, args...); + return [=, &mock](arglist&... args) -> R { + auto methodSwapper = mock.createRaiiMethodSwapper(mPtr); + return (instance->*mPtr)(args...); }; } @@ -8654,11 +8716,12 @@ namespace fakeit { } std::function getOriginalMethodForwardArgs() override { - void *mPtr = MethodMockingContextBase::_mock.getOriginalMethod(_vMethod); + auto mPtr = _vMethod; + auto& mock = MethodMockingContextBase::_mock; C * instance = &(MethodMockingContextBase::_mock.get()); - return [=](arglist&... args) -> R { - auto m = union_cast::type>(mPtr); - return m(instance, std::forward(args)...); + return [=, &mock](arglist&... args) -> R { + auto methodSwapper = mock.createRaiiMethodSwapper(mPtr); + return (instance->*mPtr)(std::forward(args)...); }; } }; @@ -8741,6 +8804,11 @@ namespace fakeit { return reinterpret_cast(fake); } + template + Finally createRaiiMethodSwapper(R(C::*vMethod)(arglist...)) { + return _proxy.createRaiiMethodSwapper(vMethod); + } + template void *getOriginalMethod(R (C::*vMethod)(arglist...)) { auto vt = _proxy.getOriginalVT(); @@ -8795,21 +8863,37 @@ namespace fakeit { template struct Prototype { - typedef R Type(Args...); - - typedef R ConstType(Args...) const; - template struct MemberType { - typedef Type(C::*type); - typedef ConstType(C::*cosntType); + using Type = R (C::*)(Args...); + using ConstType = R (C::*)(Args...) const; + using RefType = R (C::*)(Args...) &; + using ConstRefType = R (C::*)(Args...) const&; + using RValRefType = R (C::*)(Args...) &&; + using ConstRValRefType = R (C::*)(Args...) const&&; + + static Type get(Type t) { + return t; + } + + static ConstType getConst(ConstType t) { + return t; + } + + static RefType getRef(RefType t) { + return t; + } + + static ConstRefType getConstRef(ConstRefType t) { + return t; + } - static type get(type t) { + static RValRefType getRValRef(RValRefType t) { return t; } - static cosntType getconst(cosntType t) { + static ConstRValRefType getConstRValRef(ConstRValRefType t) { return t; } @@ -8834,11 +8918,25 @@ namespace fakeit { } - namespace fakeit { namespace internal { + template + struct WithCommonVoid { + using type = T; + }; + + + + + + template + struct WithCommonVoid::value, void>::type> { + using type = void; + }; + + template + using WithCommonVoid_t = typename WithCommonVoid::type; } - using namespace fakeit::internal; template class Mock : public ActualInvocationsSource { @@ -8880,58 +8978,67 @@ namespace fakeit { return impl.stubDataMember(member, ctorargs...); } + template::value && std::is_base_of::value>::type> - MockingContext stub(R (T::*vMethod)(arglist...) const) { - auto methodWithoutConstVolatile = reinterpret_cast(vMethod); + std::is_base_of::value>::type> + MockingContext, arglist...> stub(R (T::*vMethod)(arglist...) const) { + auto methodWithoutConstVolatile = reinterpret_cast (T::*)(arglist...)>(vMethod); return impl.template stubMethod(methodWithoutConstVolatile); } + template::value && std::is_base_of::value>::type> - MockingContext stub(R(T::*vMethod)(arglist...) volatile) { - auto methodWithoutConstVolatile = reinterpret_cast(vMethod); + std::is_base_of::value>::type> + MockingContext, arglist...> stub(R(T::*vMethod)(arglist...) volatile) { + auto methodWithoutConstVolatile = reinterpret_cast(T::*)(arglist...)>(vMethod); return impl.template stubMethod(methodWithoutConstVolatile); } + template::value && std::is_base_of::value>::type> - MockingContext stub(R(T::*vMethod)(arglist...) const volatile) { - auto methodWithoutConstVolatile = reinterpret_cast(vMethod); + std::is_base_of::value>::type> + MockingContext, arglist...> stub(R(T::*vMethod)(arglist...) const volatile) { + auto methodWithoutConstVolatile = reinterpret_cast(T::*)(arglist...)>(vMethod); return impl.template stubMethod(methodWithoutConstVolatile); } + template::value && std::is_base_of::value>::type> - MockingContext stub(R(T::*vMethod)(arglist...)) { - return impl.template stubMethod(vMethod); + std::is_base_of::value>::type> + MockingContext, arglist...> stub(R(T::*vMethod)(arglist...)) { + auto methodWithoutConstVolatile = reinterpret_cast(T::*)(arglist...)>(vMethod); + return impl.template stubMethod(methodWithoutConstVolatile); } + template::value && std::is_base_of::value>::type> - MockingContext stub(R(T::*vMethod)(arglist...) const) { - auto methodWithoutConstVolatile = reinterpret_cast(vMethod); + std::is_base_of::value>::type> + MockingContext, arglist...> stub(R(T::*vMethod)(arglist...) &) { + auto methodWithoutConstVolatile = reinterpret_cast(T::*)(arglist...)>(vMethod); return impl.template stubMethod(methodWithoutConstVolatile); } + template::value && std::is_base_of::value>::type> - MockingContext stub(R(T::*vMethod)(arglist...) volatile) { - auto methodWithoutConstVolatile = reinterpret_cast(vMethod); + std::is_base_of::value>::type> + MockingContext, arglist...> stub(R(T::*vMethod)(arglist...) const&) { + auto methodWithoutConstVolatile = reinterpret_cast(T::*)(arglist...)>(vMethod); return impl.template stubMethod(methodWithoutConstVolatile); } + template::value && std::is_base_of::value>::type> - MockingContext stub(R(T::*vMethod)(arglist...) const volatile) { - auto methodWithoutConstVolatile = reinterpret_cast(vMethod); + std::is_base_of::value>::type> + MockingContext, arglist...> stub(R(T::*vMethod)(arglist...) &&) { + auto methodWithoutConstVolatile = reinterpret_cast(T::*)(arglist...)>(vMethod); return impl.template stubMethod(methodWithoutConstVolatile); } + template::value && std::is_base_of::value>::type> - MockingContext stub(R(T::*vMethod)(arglist...)) { - auto methodWithoutConstVolatile = reinterpret_cast(vMethod); + std::is_base_of::value>::type> + MockingContext, arglist...> stub(R(T::*vMethod)(arglist...) const&&) { + auto methodWithoutConstVolatile = reinterpret_cast(T::*)(arglist...)>(vMethod); return impl.template stubMethod(methodWithoutConstVolatile); } @@ -9967,7 +10074,19 @@ namespace fakeit { fakeit::Prototype::template MemberType::get(&MOCK_TYPE(mock)::method) #define CONST_OVERLOADED_METHOD_PTR(mock, method, prototype) \ - fakeit::Prototype::template MemberType::getconst(&MOCK_TYPE(mock)::method) + fakeit::Prototype::template MemberType::getConst(&MOCK_TYPE(mock)::method) + +#define REF_OVERLOADED_METHOD_PTR(mock, method, prototype) \ + fakeit::Prototype::MemberType::getRef(&MOCK_TYPE(mock)::method) + +#define CONST_REF_OVERLOADED_METHOD_PTR(mock, method, prototype) \ + fakeit::Prototype::MemberType::getConstRef(&MOCK_TYPE(mock)::method) + +#define R_VAL_REF_OVERLOADED_METHOD_PTR(mock, method, prototype) \ + fakeit::Prototype::MemberType::getRValRef(&MOCK_TYPE(mock)::method) + +#define CONST_R_VAL_REF_OVERLOADED_METHOD_PTR(mock, method, prototype) \ + fakeit::Prototype::MemberType::getConstRValRef(&MOCK_TYPE(mock)::method) #define Dtor(mock) \ (mock).dtor().setMethodDetails(#mock,"destructor") @@ -9981,6 +10100,18 @@ namespace fakeit { #define ConstOverloadedMethod(mock, method, prototype) \ (mock).template stub<__COUNTER__>(CONST_OVERLOADED_METHOD_PTR( mock , method, prototype )).setMethodDetails(#mock,#method) +#define RefOverloadedMethod(mock, method, prototype) \ + (mock).template stub<__COUNTER__>(REF_OVERLOADED_METHOD_PTR( mock , method, prototype )).setMethodDetails(#mock,#method) + +#define ConstRefOverloadedMethod(mock, method, prototype) \ + (mock).template stub<__COUNTER__>(CONST_REF_OVERLOADED_METHOD_PTR( mock , method, prototype )).setMethodDetails(#mock,#method) + +#define RValRefOverloadedMethod(mock, method, prototype) \ + (mock).template stub<__COUNTER__>(R_VAL_REF_OVERLOADED_METHOD_PTR( mock , method, prototype )).setMethodDetails(#mock,#method) + +#define ConstRValRefOverloadedMethod(mock, method, prototype) \ + (mock).template stub<__COUNTER__>(CONST_R_VAL_REF_OVERLOADED_METHOD_PTR( mock , method, prototype )).setMethodDetails(#mock,#method) + #define Verify(...) \ Verify( __VA_ARGS__ ).setFileInfo(__FILE__, __LINE__, __func__) @@ -9996,5 +10127,4 @@ namespace fakeit { #define When(call) \ When(call) - #endif diff --git a/single_header/doctest/fakeit.hpp b/single_header/doctest/fakeit.hpp index 5403b5f4..e2918b17 100644 --- a/single_header/doctest/fakeit.hpp +++ b/single_header/doctest/fakeit.hpp @@ -2,7 +2,7 @@ /* * FakeIt - A Simplified C++ Mocking Framework * Copyright (c) Eran Pe'er 2013 - * Generated: 2022-12-16 13:26:49.738659 + * Generated: 2023-04-17 21:28:50.758101 * Distributed under the MIT License. Please refer to the LICENSE file at: * https://github.com/eranpeer/FakeIt */ @@ -18,11 +18,23 @@ #include #include #if defined (__GNUG__) || _MSC_VER >= 1900 -#define FAKEIT_THROWS noexcept(false) -#define FAKEIT_NO_THROWS noexcept(true) +# define FAKEIT_THROWS noexcept(false) +# define FAKEIT_NO_THROWS noexcept(true) #elif defined (_MSC_VER) -#define FAKEIT_THROWS throw(...) -#define FAKEIT_NO_THROWS +# define FAKEIT_THROWS throw(...) +# define FAKEIT_NO_THROWS +#endif + +#ifdef _MSVC_LANG +# define FAKEIT_CPLUSPLUS _MSVC_LANG +#else +# define FAKEIT_CPLUSPLUS __cplusplus +#endif + +#ifdef __GNUG__ +# define FAKEIT_DISARM_UBSAN __attribute__((no_sanitize("undefined"))) +#else +# define FAKEIT_DISARM_UBSAN #endif #include #include @@ -1003,8 +1015,9 @@ namespace fakeit { #include + namespace fakeit { -#if __cplusplus >= 201703L || defined(__cpp_lib_uncaught_exceptions) +#if FAKEIT_CPLUSPLUS >= 201703L || defined(__cpp_lib_uncaught_exceptions) inline bool UncaughtException () { return std::uncaught_exceptions() >= 1; } @@ -5300,6 +5313,7 @@ namespace fakeit { #endif template + FAKEIT_DISARM_UBSAN static typename std::enable_if::value, unsigned int>::type getDestructorOffset() { VirtualOffsetSelector offsetSelctor; @@ -5862,6 +5876,32 @@ namespace fakeit } }; } +#include + +namespace fakeit { + + class Finally { + private: + std::function _finallyClause; + + Finally(const Finally &) = delete; + + Finally &operator=(const Finally &) = delete; + + public: + explicit Finally(std::function f) : + _finallyClause(f) { + } + + Finally(Finally&& other) { + _finallyClause.swap(other._finallyClause); + } + + ~Finally() { + _finallyClause(); + } + }; +} namespace fakeit { struct MethodProxy { @@ -5921,6 +5961,11 @@ namespace fakeit { return MethodProxy(id, offset, union_cast(&MethodProxyCreator::methodProxyX < id > )); } + template + MethodProxy createMethodProxyStatic(unsigned int offset) { + return MethodProxy(id, offset, union_cast(&MethodProxyCreator::methodProxyXStatic < id > )); + } + protected: R methodProxy(unsigned int id, const typename fakeit::production_arg::type... args) { @@ -5936,6 +5981,20 @@ namespace fakeit { R methodProxyX(arglist ... args) { return methodProxy(id, std::forward::type>(args)...); } + + static R methodProxyStatic(void* instance, unsigned int id, const typename fakeit::production_arg::type... args) { + InvocationHandlerCollection *invocationHandlerCollection = InvocationHandlerCollection::getInvocationHandlerCollection( + instance); + MethodInvocationHandler *invocationHandler = + (MethodInvocationHandler *) invocationHandlerCollection->getInvocatoinHandlerPtrById( + id); + return invocationHandler->handleMethodInvocation(std::forward::type>(args)...); + } + + template + static R methodProxyXStatic(void* instance, arglist ... args) { + return methodProxyStatic(instance, id, std::forward::type>(args)...); + } }; } @@ -6026,7 +6085,17 @@ namespace fakeit { void stubDtor(MethodInvocationHandler *methodInvocationHandler) { auto offset = VTUtils::getDestructorOffset(); MethodProxyCreator creator; + + + + + + +#ifdef _MSC_VER + bindDtor(creator.createMethodProxyStatic<0>(offset), methodInvocationHandler); +#else bindDtor(creator.createMethodProxy<0>(offset), methodInvocationHandler); +#endif } template @@ -6079,6 +6148,18 @@ namespace fakeit { return vt; } + template + Finally createRaiiMethodSwapper(R(C::*vMethod)(arglist...)) { + auto offset = VTUtils::getOffset(vMethod); + auto fakeMethod = getFake().getVirtualTable().getMethod(offset); + auto originalMethod = getOriginalVT().getMethod(offset); + + getFake().setMethod(offset, originalMethod); + return Finally{[&, offset, fakeMethod](){ + getFake().setMethod(offset, fakeMethod); + }}; + } + private: template @@ -7593,7 +7674,7 @@ namespace fakeit { MethodStubbingProgress &operator=(const MethodStubbingProgress &other) = delete; template -#if __cplusplus >= 201402L +#if FAKEIT_CPLUSPLUS >= 201402L auto #else std::function::type...)> @@ -7618,7 +7699,7 @@ namespace fakeit { } template -#if __cplusplus >= 201402L +#if FAKEIT_CPLUSPLUS >= 201402L auto #else std::function::type...)> @@ -7737,7 +7818,7 @@ namespace fakeit { MethodStubbingProgress &operator=(const MethodStubbingProgress &other) = delete; template -#if __cplusplus >= 201402L +#if FAKEIT_CPLUSPLUS >= 201402L auto #else std::function::type...)> @@ -7761,7 +7842,7 @@ namespace fakeit { } template -#if __cplusplus >= 201402L +#if FAKEIT_CPLUSPLUS >= 201402L auto #else std::function::type...)> @@ -7803,7 +7884,7 @@ namespace fakeit { template static void CheckPositions(const std::tuple...> arg_vals) { -#if __cplusplus >= 201402L && !defined(_WIN32) +#if FAKEIT_CPLUSPLUS >= 201402L && !defined(_WIN32) static_assert(std::get(arg_vals).pos <= max_index, "Argument index out of range"); ArgValidator::CheckPositions(arg_vals); @@ -7855,7 +7936,7 @@ namespace fakeit { struct ArgLocator { template static void AssignArg(current_arg &&p, std::tuple...> arg_vals) { -#if __cplusplus >= 201703L && !defined (_WIN32) +#if FAKEIT_CPLUSPLUS >= 201703L && !defined (_WIN32) if constexpr (std::get(arg_vals).pos == arg_index) GetArg(std::forward(p)) = std::get(arg_vals).value; #else @@ -7866,7 +7947,7 @@ namespace fakeit { ArgLocator::AssignArg(std::forward(p), arg_vals); } -#if __cplusplus < 201703L || defined (_WIN32) +#if FAKEIT_CPLUSPLUS < 201703L || defined (_WIN32) private: template static @@ -7924,28 +8005,8 @@ namespace fakeit { using placeholders::operator <=; } #include -#include - -namespace fakeit { - - class Finally { - private: - std::function _finallyClause; - - Finally(const Finally &); - Finally &operator=(const Finally &); - public: - explicit Finally(std::function f) : - _finallyClause(f) { - } - - ~Finally() { - _finallyClause(); - } - }; -} namespace fakeit { @@ -8662,11 +8723,12 @@ namespace fakeit { template::value...>::value, int>::type = 0> std::function getOriginalMethodCopyArgsInternal(int) { - void *mPtr = MethodMockingContextBase::_mock.getOriginalMethod(_vMethod); + auto mPtr = _vMethod; + auto& mock = MethodMockingContextBase::_mock; C * instance = &(MethodMockingContextBase::_mock.get()); - return [=](arglist&... args) -> R { - auto m = union_cast::type>(mPtr); - return m(instance, args...); + return [=, &mock](arglist&... args) -> R { + auto methodSwapper = mock.createRaiiMethodSwapper(mPtr); + return (instance->*mPtr)(args...); }; } @@ -8682,11 +8744,12 @@ namespace fakeit { } std::function getOriginalMethodForwardArgs() override { - void *mPtr = MethodMockingContextBase::_mock.getOriginalMethod(_vMethod); + auto mPtr = _vMethod; + auto& mock = MethodMockingContextBase::_mock; C * instance = &(MethodMockingContextBase::_mock.get()); - return [=](arglist&... args) -> R { - auto m = union_cast::type>(mPtr); - return m(instance, std::forward(args)...); + return [=, &mock](arglist&... args) -> R { + auto methodSwapper = mock.createRaiiMethodSwapper(mPtr); + return (instance->*mPtr)(std::forward(args)...); }; } }; @@ -8769,6 +8832,11 @@ namespace fakeit { return reinterpret_cast(fake); } + template + Finally createRaiiMethodSwapper(R(C::*vMethod)(arglist...)) { + return _proxy.createRaiiMethodSwapper(vMethod); + } + template void *getOriginalMethod(R (C::*vMethod)(arglist...)) { auto vt = _proxy.getOriginalVT(); @@ -8823,21 +8891,37 @@ namespace fakeit { template struct Prototype { - typedef R Type(Args...); - - typedef R ConstType(Args...) const; - template struct MemberType { - typedef Type(C::*type); - typedef ConstType(C::*cosntType); + using Type = R (C::*)(Args...); + using ConstType = R (C::*)(Args...) const; + using RefType = R (C::*)(Args...) &; + using ConstRefType = R (C::*)(Args...) const&; + using RValRefType = R (C::*)(Args...) &&; + using ConstRValRefType = R (C::*)(Args...) const&&; + + static Type get(Type t) { + return t; + } + + static ConstType getConst(ConstType t) { + return t; + } + + static RefType getRef(RefType t) { + return t; + } + + static ConstRefType getConstRef(ConstRefType t) { + return t; + } - static type get(type t) { + static RValRefType getRValRef(RValRefType t) { return t; } - static cosntType getconst(cosntType t) { + static ConstRValRefType getConstRValRef(ConstRValRefType t) { return t; } @@ -8862,11 +8946,25 @@ namespace fakeit { } - namespace fakeit { namespace internal { + template + struct WithCommonVoid { + using type = T; + }; + + + + + + template + struct WithCommonVoid::value, void>::type> { + using type = void; + }; + + template + using WithCommonVoid_t = typename WithCommonVoid::type; } - using namespace fakeit::internal; template class Mock : public ActualInvocationsSource { @@ -8908,58 +9006,67 @@ namespace fakeit { return impl.stubDataMember(member, ctorargs...); } + template::value && std::is_base_of::value>::type> - MockingContext stub(R (T::*vMethod)(arglist...) const) { - auto methodWithoutConstVolatile = reinterpret_cast(vMethod); + std::is_base_of::value>::type> + MockingContext, arglist...> stub(R (T::*vMethod)(arglist...) const) { + auto methodWithoutConstVolatile = reinterpret_cast (T::*)(arglist...)>(vMethod); return impl.template stubMethod(methodWithoutConstVolatile); } + template::value && std::is_base_of::value>::type> - MockingContext stub(R(T::*vMethod)(arglist...) volatile) { - auto methodWithoutConstVolatile = reinterpret_cast(vMethod); + std::is_base_of::value>::type> + MockingContext, arglist...> stub(R(T::*vMethod)(arglist...) volatile) { + auto methodWithoutConstVolatile = reinterpret_cast(T::*)(arglist...)>(vMethod); return impl.template stubMethod(methodWithoutConstVolatile); } + template::value && std::is_base_of::value>::type> - MockingContext stub(R(T::*vMethod)(arglist...) const volatile) { - auto methodWithoutConstVolatile = reinterpret_cast(vMethod); + std::is_base_of::value>::type> + MockingContext, arglist...> stub(R(T::*vMethod)(arglist...) const volatile) { + auto methodWithoutConstVolatile = reinterpret_cast(T::*)(arglist...)>(vMethod); return impl.template stubMethod(methodWithoutConstVolatile); } + template::value && std::is_base_of::value>::type> - MockingContext stub(R(T::*vMethod)(arglist...)) { - return impl.template stubMethod(vMethod); + std::is_base_of::value>::type> + MockingContext, arglist...> stub(R(T::*vMethod)(arglist...)) { + auto methodWithoutConstVolatile = reinterpret_cast(T::*)(arglist...)>(vMethod); + return impl.template stubMethod(methodWithoutConstVolatile); } + template::value && std::is_base_of::value>::type> - MockingContext stub(R(T::*vMethod)(arglist...) const) { - auto methodWithoutConstVolatile = reinterpret_cast(vMethod); + std::is_base_of::value>::type> + MockingContext, arglist...> stub(R(T::*vMethod)(arglist...) &) { + auto methodWithoutConstVolatile = reinterpret_cast(T::*)(arglist...)>(vMethod); return impl.template stubMethod(methodWithoutConstVolatile); } + template::value && std::is_base_of::value>::type> - MockingContext stub(R(T::*vMethod)(arglist...) volatile) { - auto methodWithoutConstVolatile = reinterpret_cast(vMethod); + std::is_base_of::value>::type> + MockingContext, arglist...> stub(R(T::*vMethod)(arglist...) const&) { + auto methodWithoutConstVolatile = reinterpret_cast(T::*)(arglist...)>(vMethod); return impl.template stubMethod(methodWithoutConstVolatile); } + template::value && std::is_base_of::value>::type> - MockingContext stub(R(T::*vMethod)(arglist...) const volatile) { - auto methodWithoutConstVolatile = reinterpret_cast(vMethod); + std::is_base_of::value>::type> + MockingContext, arglist...> stub(R(T::*vMethod)(arglist...) &&) { + auto methodWithoutConstVolatile = reinterpret_cast(T::*)(arglist...)>(vMethod); return impl.template stubMethod(methodWithoutConstVolatile); } + template::value && std::is_base_of::value>::type> - MockingContext stub(R(T::*vMethod)(arglist...)) { - auto methodWithoutConstVolatile = reinterpret_cast(vMethod); + std::is_base_of::value>::type> + MockingContext, arglist...> stub(R(T::*vMethod)(arglist...) const&&) { + auto methodWithoutConstVolatile = reinterpret_cast(T::*)(arglist...)>(vMethod); return impl.template stubMethod(methodWithoutConstVolatile); } @@ -9981,7 +10088,19 @@ namespace fakeit { fakeit::Prototype::template MemberType::get(&MOCK_TYPE(mock)::method) #define CONST_OVERLOADED_METHOD_PTR(mock, method, prototype) \ - fakeit::Prototype::template MemberType::getconst(&MOCK_TYPE(mock)::method) + fakeit::Prototype::template MemberType::getConst(&MOCK_TYPE(mock)::method) + +#define REF_OVERLOADED_METHOD_PTR(mock, method, prototype) \ + fakeit::Prototype::MemberType::getRef(&MOCK_TYPE(mock)::method) + +#define CONST_REF_OVERLOADED_METHOD_PTR(mock, method, prototype) \ + fakeit::Prototype::MemberType::getConstRef(&MOCK_TYPE(mock)::method) + +#define R_VAL_REF_OVERLOADED_METHOD_PTR(mock, method, prototype) \ + fakeit::Prototype::MemberType::getRValRef(&MOCK_TYPE(mock)::method) + +#define CONST_R_VAL_REF_OVERLOADED_METHOD_PTR(mock, method, prototype) \ + fakeit::Prototype::MemberType::getConstRValRef(&MOCK_TYPE(mock)::method) #define Dtor(mock) \ (mock).dtor().setMethodDetails(#mock,"destructor") @@ -9995,6 +10114,18 @@ namespace fakeit { #define ConstOverloadedMethod(mock, method, prototype) \ (mock).template stub<__COUNTER__>(CONST_OVERLOADED_METHOD_PTR( mock , method, prototype )).setMethodDetails(#mock,#method) +#define RefOverloadedMethod(mock, method, prototype) \ + (mock).template stub<__COUNTER__>(REF_OVERLOADED_METHOD_PTR( mock , method, prototype )).setMethodDetails(#mock,#method) + +#define ConstRefOverloadedMethod(mock, method, prototype) \ + (mock).template stub<__COUNTER__>(CONST_REF_OVERLOADED_METHOD_PTR( mock , method, prototype )).setMethodDetails(#mock,#method) + +#define RValRefOverloadedMethod(mock, method, prototype) \ + (mock).template stub<__COUNTER__>(R_VAL_REF_OVERLOADED_METHOD_PTR( mock , method, prototype )).setMethodDetails(#mock,#method) + +#define ConstRValRefOverloadedMethod(mock, method, prototype) \ + (mock).template stub<__COUNTER__>(CONST_R_VAL_REF_OVERLOADED_METHOD_PTR( mock , method, prototype )).setMethodDetails(#mock,#method) + #define Verify(...) \ Verify( __VA_ARGS__ ).setFileInfo(__FILE__, __LINE__, __func__) @@ -10010,5 +10141,4 @@ namespace fakeit { #define When(call) \ When(call) - #endif diff --git a/single_header/gtest/fakeit.hpp b/single_header/gtest/fakeit.hpp index efea87ab..28a41b00 100644 --- a/single_header/gtest/fakeit.hpp +++ b/single_header/gtest/fakeit.hpp @@ -2,7 +2,7 @@ /* * FakeIt - A Simplified C++ Mocking Framework * Copyright (c) Eran Pe'er 2013 - * Generated: 2022-12-16 13:26:50.045623 + * Generated: 2023-04-17 21:28:51.025153 * Distributed under the MIT License. Please refer to the LICENSE file at: * https://github.com/eranpeer/FakeIt */ @@ -18,11 +18,23 @@ #include #include #if defined (__GNUG__) || _MSC_VER >= 1900 -#define FAKEIT_THROWS noexcept(false) -#define FAKEIT_NO_THROWS noexcept(true) +# define FAKEIT_THROWS noexcept(false) +# define FAKEIT_NO_THROWS noexcept(true) #elif defined (_MSC_VER) -#define FAKEIT_THROWS throw(...) -#define FAKEIT_NO_THROWS +# define FAKEIT_THROWS throw(...) +# define FAKEIT_NO_THROWS +#endif + +#ifdef _MSVC_LANG +# define FAKEIT_CPLUSPLUS _MSVC_LANG +#else +# define FAKEIT_CPLUSPLUS __cplusplus +#endif + +#ifdef __GNUG__ +# define FAKEIT_DISARM_UBSAN __attribute__((no_sanitize("undefined"))) +#else +# define FAKEIT_DISARM_UBSAN #endif #include #include @@ -1003,8 +1015,9 @@ namespace fakeit { #include + namespace fakeit { -#if __cplusplus >= 201703L || defined(__cpp_lib_uncaught_exceptions) +#if FAKEIT_CPLUSPLUS >= 201703L || defined(__cpp_lib_uncaught_exceptions) inline bool UncaughtException () { return std::uncaught_exceptions() >= 1; } @@ -5272,6 +5285,7 @@ namespace fakeit { #endif template + FAKEIT_DISARM_UBSAN static typename std::enable_if::value, unsigned int>::type getDestructorOffset() { VirtualOffsetSelector offsetSelctor; @@ -5834,6 +5848,32 @@ namespace fakeit } }; } +#include + +namespace fakeit { + + class Finally { + private: + std::function _finallyClause; + + Finally(const Finally &) = delete; + + Finally &operator=(const Finally &) = delete; + + public: + explicit Finally(std::function f) : + _finallyClause(f) { + } + + Finally(Finally&& other) { + _finallyClause.swap(other._finallyClause); + } + + ~Finally() { + _finallyClause(); + } + }; +} namespace fakeit { struct MethodProxy { @@ -5893,6 +5933,11 @@ namespace fakeit { return MethodProxy(id, offset, union_cast(&MethodProxyCreator::methodProxyX < id > )); } + template + MethodProxy createMethodProxyStatic(unsigned int offset) { + return MethodProxy(id, offset, union_cast(&MethodProxyCreator::methodProxyXStatic < id > )); + } + protected: R methodProxy(unsigned int id, const typename fakeit::production_arg::type... args) { @@ -5908,6 +5953,20 @@ namespace fakeit { R methodProxyX(arglist ... args) { return methodProxy(id, std::forward::type>(args)...); } + + static R methodProxyStatic(void* instance, unsigned int id, const typename fakeit::production_arg::type... args) { + InvocationHandlerCollection *invocationHandlerCollection = InvocationHandlerCollection::getInvocationHandlerCollection( + instance); + MethodInvocationHandler *invocationHandler = + (MethodInvocationHandler *) invocationHandlerCollection->getInvocatoinHandlerPtrById( + id); + return invocationHandler->handleMethodInvocation(std::forward::type>(args)...); + } + + template + static R methodProxyXStatic(void* instance, arglist ... args) { + return methodProxyStatic(instance, id, std::forward::type>(args)...); + } }; } @@ -5998,7 +6057,17 @@ namespace fakeit { void stubDtor(MethodInvocationHandler *methodInvocationHandler) { auto offset = VTUtils::getDestructorOffset(); MethodProxyCreator creator; + + + + + + +#ifdef _MSC_VER + bindDtor(creator.createMethodProxyStatic<0>(offset), methodInvocationHandler); +#else bindDtor(creator.createMethodProxy<0>(offset), methodInvocationHandler); +#endif } template @@ -6051,6 +6120,18 @@ namespace fakeit { return vt; } + template + Finally createRaiiMethodSwapper(R(C::*vMethod)(arglist...)) { + auto offset = VTUtils::getOffset(vMethod); + auto fakeMethod = getFake().getVirtualTable().getMethod(offset); + auto originalMethod = getOriginalVT().getMethod(offset); + + getFake().setMethod(offset, originalMethod); + return Finally{[&, offset, fakeMethod](){ + getFake().setMethod(offset, fakeMethod); + }}; + } + private: template @@ -7565,7 +7646,7 @@ namespace fakeit { MethodStubbingProgress &operator=(const MethodStubbingProgress &other) = delete; template -#if __cplusplus >= 201402L +#if FAKEIT_CPLUSPLUS >= 201402L auto #else std::function::type...)> @@ -7590,7 +7671,7 @@ namespace fakeit { } template -#if __cplusplus >= 201402L +#if FAKEIT_CPLUSPLUS >= 201402L auto #else std::function::type...)> @@ -7709,7 +7790,7 @@ namespace fakeit { MethodStubbingProgress &operator=(const MethodStubbingProgress &other) = delete; template -#if __cplusplus >= 201402L +#if FAKEIT_CPLUSPLUS >= 201402L auto #else std::function::type...)> @@ -7733,7 +7814,7 @@ namespace fakeit { } template -#if __cplusplus >= 201402L +#if FAKEIT_CPLUSPLUS >= 201402L auto #else std::function::type...)> @@ -7775,7 +7856,7 @@ namespace fakeit { template static void CheckPositions(const std::tuple...> arg_vals) { -#if __cplusplus >= 201402L && !defined(_WIN32) +#if FAKEIT_CPLUSPLUS >= 201402L && !defined(_WIN32) static_assert(std::get(arg_vals).pos <= max_index, "Argument index out of range"); ArgValidator::CheckPositions(arg_vals); @@ -7827,7 +7908,7 @@ namespace fakeit { struct ArgLocator { template static void AssignArg(current_arg &&p, std::tuple...> arg_vals) { -#if __cplusplus >= 201703L && !defined (_WIN32) +#if FAKEIT_CPLUSPLUS >= 201703L && !defined (_WIN32) if constexpr (std::get(arg_vals).pos == arg_index) GetArg(std::forward(p)) = std::get(arg_vals).value; #else @@ -7838,7 +7919,7 @@ namespace fakeit { ArgLocator::AssignArg(std::forward(p), arg_vals); } -#if __cplusplus < 201703L || defined (_WIN32) +#if FAKEIT_CPLUSPLUS < 201703L || defined (_WIN32) private: template static @@ -7896,28 +7977,8 @@ namespace fakeit { using placeholders::operator <=; } #include -#include - -namespace fakeit { - - class Finally { - private: - std::function _finallyClause; - - Finally(const Finally &); - Finally &operator=(const Finally &); - public: - explicit Finally(std::function f) : - _finallyClause(f) { - } - - ~Finally() { - _finallyClause(); - } - }; -} namespace fakeit { @@ -8634,11 +8695,12 @@ namespace fakeit { template::value...>::value, int>::type = 0> std::function getOriginalMethodCopyArgsInternal(int) { - void *mPtr = MethodMockingContextBase::_mock.getOriginalMethod(_vMethod); + auto mPtr = _vMethod; + auto& mock = MethodMockingContextBase::_mock; C * instance = &(MethodMockingContextBase::_mock.get()); - return [=](arglist&... args) -> R { - auto m = union_cast::type>(mPtr); - return m(instance, args...); + return [=, &mock](arglist&... args) -> R { + auto methodSwapper = mock.createRaiiMethodSwapper(mPtr); + return (instance->*mPtr)(args...); }; } @@ -8654,11 +8716,12 @@ namespace fakeit { } std::function getOriginalMethodForwardArgs() override { - void *mPtr = MethodMockingContextBase::_mock.getOriginalMethod(_vMethod); + auto mPtr = _vMethod; + auto& mock = MethodMockingContextBase::_mock; C * instance = &(MethodMockingContextBase::_mock.get()); - return [=](arglist&... args) -> R { - auto m = union_cast::type>(mPtr); - return m(instance, std::forward(args)...); + return [=, &mock](arglist&... args) -> R { + auto methodSwapper = mock.createRaiiMethodSwapper(mPtr); + return (instance->*mPtr)(std::forward(args)...); }; } }; @@ -8741,6 +8804,11 @@ namespace fakeit { return reinterpret_cast(fake); } + template + Finally createRaiiMethodSwapper(R(C::*vMethod)(arglist...)) { + return _proxy.createRaiiMethodSwapper(vMethod); + } + template void *getOriginalMethod(R (C::*vMethod)(arglist...)) { auto vt = _proxy.getOriginalVT(); @@ -8795,21 +8863,37 @@ namespace fakeit { template struct Prototype { - typedef R Type(Args...); - - typedef R ConstType(Args...) const; - template struct MemberType { - typedef Type(C::*type); - typedef ConstType(C::*cosntType); + using Type = R (C::*)(Args...); + using ConstType = R (C::*)(Args...) const; + using RefType = R (C::*)(Args...) &; + using ConstRefType = R (C::*)(Args...) const&; + using RValRefType = R (C::*)(Args...) &&; + using ConstRValRefType = R (C::*)(Args...) const&&; + + static Type get(Type t) { + return t; + } + + static ConstType getConst(ConstType t) { + return t; + } + + static RefType getRef(RefType t) { + return t; + } + + static ConstRefType getConstRef(ConstRefType t) { + return t; + } - static type get(type t) { + static RValRefType getRValRef(RValRefType t) { return t; } - static cosntType getconst(cosntType t) { + static ConstRValRefType getConstRValRef(ConstRValRefType t) { return t; } @@ -8834,11 +8918,25 @@ namespace fakeit { } - namespace fakeit { namespace internal { + template + struct WithCommonVoid { + using type = T; + }; + + + + + + template + struct WithCommonVoid::value, void>::type> { + using type = void; + }; + + template + using WithCommonVoid_t = typename WithCommonVoid::type; } - using namespace fakeit::internal; template class Mock : public ActualInvocationsSource { @@ -8880,58 +8978,67 @@ namespace fakeit { return impl.stubDataMember(member, ctorargs...); } + template::value && std::is_base_of::value>::type> - MockingContext stub(R (T::*vMethod)(arglist...) const) { - auto methodWithoutConstVolatile = reinterpret_cast(vMethod); + std::is_base_of::value>::type> + MockingContext, arglist...> stub(R (T::*vMethod)(arglist...) const) { + auto methodWithoutConstVolatile = reinterpret_cast (T::*)(arglist...)>(vMethod); return impl.template stubMethod(methodWithoutConstVolatile); } + template::value && std::is_base_of::value>::type> - MockingContext stub(R(T::*vMethod)(arglist...) volatile) { - auto methodWithoutConstVolatile = reinterpret_cast(vMethod); + std::is_base_of::value>::type> + MockingContext, arglist...> stub(R(T::*vMethod)(arglist...) volatile) { + auto methodWithoutConstVolatile = reinterpret_cast(T::*)(arglist...)>(vMethod); return impl.template stubMethod(methodWithoutConstVolatile); } + template::value && std::is_base_of::value>::type> - MockingContext stub(R(T::*vMethod)(arglist...) const volatile) { - auto methodWithoutConstVolatile = reinterpret_cast(vMethod); + std::is_base_of::value>::type> + MockingContext, arglist...> stub(R(T::*vMethod)(arglist...) const volatile) { + auto methodWithoutConstVolatile = reinterpret_cast(T::*)(arglist...)>(vMethod); return impl.template stubMethod(methodWithoutConstVolatile); } + template::value && std::is_base_of::value>::type> - MockingContext stub(R(T::*vMethod)(arglist...)) { - return impl.template stubMethod(vMethod); + std::is_base_of::value>::type> + MockingContext, arglist...> stub(R(T::*vMethod)(arglist...)) { + auto methodWithoutConstVolatile = reinterpret_cast(T::*)(arglist...)>(vMethod); + return impl.template stubMethod(methodWithoutConstVolatile); } + template::value && std::is_base_of::value>::type> - MockingContext stub(R(T::*vMethod)(arglist...) const) { - auto methodWithoutConstVolatile = reinterpret_cast(vMethod); + std::is_base_of::value>::type> + MockingContext, arglist...> stub(R(T::*vMethod)(arglist...) &) { + auto methodWithoutConstVolatile = reinterpret_cast(T::*)(arglist...)>(vMethod); return impl.template stubMethod(methodWithoutConstVolatile); } + template::value && std::is_base_of::value>::type> - MockingContext stub(R(T::*vMethod)(arglist...) volatile) { - auto methodWithoutConstVolatile = reinterpret_cast(vMethod); + std::is_base_of::value>::type> + MockingContext, arglist...> stub(R(T::*vMethod)(arglist...) const&) { + auto methodWithoutConstVolatile = reinterpret_cast(T::*)(arglist...)>(vMethod); return impl.template stubMethod(methodWithoutConstVolatile); } + template::value && std::is_base_of::value>::type> - MockingContext stub(R(T::*vMethod)(arglist...) const volatile) { - auto methodWithoutConstVolatile = reinterpret_cast(vMethod); + std::is_base_of::value>::type> + MockingContext, arglist...> stub(R(T::*vMethod)(arglist...) &&) { + auto methodWithoutConstVolatile = reinterpret_cast(T::*)(arglist...)>(vMethod); return impl.template stubMethod(methodWithoutConstVolatile); } + template::value && std::is_base_of::value>::type> - MockingContext stub(R(T::*vMethod)(arglist...)) { - auto methodWithoutConstVolatile = reinterpret_cast(vMethod); + std::is_base_of::value>::type> + MockingContext, arglist...> stub(R(T::*vMethod)(arglist...) const&&) { + auto methodWithoutConstVolatile = reinterpret_cast(T::*)(arglist...)>(vMethod); return impl.template stubMethod(methodWithoutConstVolatile); } @@ -9967,7 +10074,19 @@ namespace fakeit { fakeit::Prototype::template MemberType::get(&MOCK_TYPE(mock)::method) #define CONST_OVERLOADED_METHOD_PTR(mock, method, prototype) \ - fakeit::Prototype::template MemberType::getconst(&MOCK_TYPE(mock)::method) + fakeit::Prototype::template MemberType::getConst(&MOCK_TYPE(mock)::method) + +#define REF_OVERLOADED_METHOD_PTR(mock, method, prototype) \ + fakeit::Prototype::MemberType::getRef(&MOCK_TYPE(mock)::method) + +#define CONST_REF_OVERLOADED_METHOD_PTR(mock, method, prototype) \ + fakeit::Prototype::MemberType::getConstRef(&MOCK_TYPE(mock)::method) + +#define R_VAL_REF_OVERLOADED_METHOD_PTR(mock, method, prototype) \ + fakeit::Prototype::MemberType::getRValRef(&MOCK_TYPE(mock)::method) + +#define CONST_R_VAL_REF_OVERLOADED_METHOD_PTR(mock, method, prototype) \ + fakeit::Prototype::MemberType::getConstRValRef(&MOCK_TYPE(mock)::method) #define Dtor(mock) \ (mock).dtor().setMethodDetails(#mock,"destructor") @@ -9981,6 +10100,18 @@ namespace fakeit { #define ConstOverloadedMethod(mock, method, prototype) \ (mock).template stub<__COUNTER__>(CONST_OVERLOADED_METHOD_PTR( mock , method, prototype )).setMethodDetails(#mock,#method) +#define RefOverloadedMethod(mock, method, prototype) \ + (mock).template stub<__COUNTER__>(REF_OVERLOADED_METHOD_PTR( mock , method, prototype )).setMethodDetails(#mock,#method) + +#define ConstRefOverloadedMethod(mock, method, prototype) \ + (mock).template stub<__COUNTER__>(CONST_REF_OVERLOADED_METHOD_PTR( mock , method, prototype )).setMethodDetails(#mock,#method) + +#define RValRefOverloadedMethod(mock, method, prototype) \ + (mock).template stub<__COUNTER__>(R_VAL_REF_OVERLOADED_METHOD_PTR( mock , method, prototype )).setMethodDetails(#mock,#method) + +#define ConstRValRefOverloadedMethod(mock, method, prototype) \ + (mock).template stub<__COUNTER__>(CONST_R_VAL_REF_OVERLOADED_METHOD_PTR( mock , method, prototype )).setMethodDetails(#mock,#method) + #define Verify(...) \ Verify( __VA_ARGS__ ).setFileInfo(__FILE__, __LINE__, __func__) @@ -9996,5 +10127,4 @@ namespace fakeit { #define When(call) \ When(call) - #endif diff --git a/single_header/mettle/fakeit.hpp b/single_header/mettle/fakeit.hpp index be6f7b89..0e9f96fd 100644 --- a/single_header/mettle/fakeit.hpp +++ b/single_header/mettle/fakeit.hpp @@ -2,7 +2,7 @@ /* * FakeIt - A Simplified C++ Mocking Framework * Copyright (c) Eran Pe'er 2013 - * Generated: 2022-12-16 13:26:50.312744 + * Generated: 2023-04-17 21:28:51.293789 * Distributed under the MIT License. Please refer to the LICENSE file at: * https://github.com/eranpeer/FakeIt */ @@ -17,11 +17,23 @@ #include #include #if defined (__GNUG__) || _MSC_VER >= 1900 -#define FAKEIT_THROWS noexcept(false) -#define FAKEIT_NO_THROWS noexcept(true) +# define FAKEIT_THROWS noexcept(false) +# define FAKEIT_NO_THROWS noexcept(true) #elif defined (_MSC_VER) -#define FAKEIT_THROWS throw(...) -#define FAKEIT_NO_THROWS +# define FAKEIT_THROWS throw(...) +# define FAKEIT_NO_THROWS +#endif + +#ifdef _MSVC_LANG +# define FAKEIT_CPLUSPLUS _MSVC_LANG +#else +# define FAKEIT_CPLUSPLUS __cplusplus +#endif + +#ifdef __GNUG__ +# define FAKEIT_DISARM_UBSAN __attribute__((no_sanitize("undefined"))) +#else +# define FAKEIT_DISARM_UBSAN #endif #include #include @@ -1002,8 +1014,9 @@ namespace fakeit { #include + namespace fakeit { -#if __cplusplus >= 201703L || defined(__cpp_lib_uncaught_exceptions) +#if FAKEIT_CPLUSPLUS >= 201703L || defined(__cpp_lib_uncaught_exceptions) inline bool UncaughtException () { return std::uncaught_exceptions() >= 1; } @@ -5294,6 +5307,7 @@ namespace fakeit { #endif template + FAKEIT_DISARM_UBSAN static typename std::enable_if::value, unsigned int>::type getDestructorOffset() { VirtualOffsetSelector offsetSelctor; @@ -5856,6 +5870,32 @@ namespace fakeit } }; } +#include + +namespace fakeit { + + class Finally { + private: + std::function _finallyClause; + + Finally(const Finally &) = delete; + + Finally &operator=(const Finally &) = delete; + + public: + explicit Finally(std::function f) : + _finallyClause(f) { + } + + Finally(Finally&& other) { + _finallyClause.swap(other._finallyClause); + } + + ~Finally() { + _finallyClause(); + } + }; +} namespace fakeit { struct MethodProxy { @@ -5915,6 +5955,11 @@ namespace fakeit { return MethodProxy(id, offset, union_cast(&MethodProxyCreator::methodProxyX < id > )); } + template + MethodProxy createMethodProxyStatic(unsigned int offset) { + return MethodProxy(id, offset, union_cast(&MethodProxyCreator::methodProxyXStatic < id > )); + } + protected: R methodProxy(unsigned int id, const typename fakeit::production_arg::type... args) { @@ -5930,6 +5975,20 @@ namespace fakeit { R methodProxyX(arglist ... args) { return methodProxy(id, std::forward::type>(args)...); } + + static R methodProxyStatic(void* instance, unsigned int id, const typename fakeit::production_arg::type... args) { + InvocationHandlerCollection *invocationHandlerCollection = InvocationHandlerCollection::getInvocationHandlerCollection( + instance); + MethodInvocationHandler *invocationHandler = + (MethodInvocationHandler *) invocationHandlerCollection->getInvocatoinHandlerPtrById( + id); + return invocationHandler->handleMethodInvocation(std::forward::type>(args)...); + } + + template + static R methodProxyXStatic(void* instance, arglist ... args) { + return methodProxyStatic(instance, id, std::forward::type>(args)...); + } }; } @@ -6020,7 +6079,17 @@ namespace fakeit { void stubDtor(MethodInvocationHandler *methodInvocationHandler) { auto offset = VTUtils::getDestructorOffset(); MethodProxyCreator creator; + + + + + + +#ifdef _MSC_VER + bindDtor(creator.createMethodProxyStatic<0>(offset), methodInvocationHandler); +#else bindDtor(creator.createMethodProxy<0>(offset), methodInvocationHandler); +#endif } template @@ -6073,6 +6142,18 @@ namespace fakeit { return vt; } + template + Finally createRaiiMethodSwapper(R(C::*vMethod)(arglist...)) { + auto offset = VTUtils::getOffset(vMethod); + auto fakeMethod = getFake().getVirtualTable().getMethod(offset); + auto originalMethod = getOriginalVT().getMethod(offset); + + getFake().setMethod(offset, originalMethod); + return Finally{[&, offset, fakeMethod](){ + getFake().setMethod(offset, fakeMethod); + }}; + } + private: template @@ -7587,7 +7668,7 @@ namespace fakeit { MethodStubbingProgress &operator=(const MethodStubbingProgress &other) = delete; template -#if __cplusplus >= 201402L +#if FAKEIT_CPLUSPLUS >= 201402L auto #else std::function::type...)> @@ -7612,7 +7693,7 @@ namespace fakeit { } template -#if __cplusplus >= 201402L +#if FAKEIT_CPLUSPLUS >= 201402L auto #else std::function::type...)> @@ -7731,7 +7812,7 @@ namespace fakeit { MethodStubbingProgress &operator=(const MethodStubbingProgress &other) = delete; template -#if __cplusplus >= 201402L +#if FAKEIT_CPLUSPLUS >= 201402L auto #else std::function::type...)> @@ -7755,7 +7836,7 @@ namespace fakeit { } template -#if __cplusplus >= 201402L +#if FAKEIT_CPLUSPLUS >= 201402L auto #else std::function::type...)> @@ -7797,7 +7878,7 @@ namespace fakeit { template static void CheckPositions(const std::tuple...> arg_vals) { -#if __cplusplus >= 201402L && !defined(_WIN32) +#if FAKEIT_CPLUSPLUS >= 201402L && !defined(_WIN32) static_assert(std::get(arg_vals).pos <= max_index, "Argument index out of range"); ArgValidator::CheckPositions(arg_vals); @@ -7849,7 +7930,7 @@ namespace fakeit { struct ArgLocator { template static void AssignArg(current_arg &&p, std::tuple...> arg_vals) { -#if __cplusplus >= 201703L && !defined (_WIN32) +#if FAKEIT_CPLUSPLUS >= 201703L && !defined (_WIN32) if constexpr (std::get(arg_vals).pos == arg_index) GetArg(std::forward(p)) = std::get(arg_vals).value; #else @@ -7860,7 +7941,7 @@ namespace fakeit { ArgLocator::AssignArg(std::forward(p), arg_vals); } -#if __cplusplus < 201703L || defined (_WIN32) +#if FAKEIT_CPLUSPLUS < 201703L || defined (_WIN32) private: template static @@ -7918,28 +7999,8 @@ namespace fakeit { using placeholders::operator <=; } #include -#include - -namespace fakeit { - - class Finally { - private: - std::function _finallyClause; - - Finally(const Finally &); - Finally &operator=(const Finally &); - public: - explicit Finally(std::function f) : - _finallyClause(f) { - } - - ~Finally() { - _finallyClause(); - } - }; -} namespace fakeit { @@ -8656,11 +8717,12 @@ namespace fakeit { template::value...>::value, int>::type = 0> std::function getOriginalMethodCopyArgsInternal(int) { - void *mPtr = MethodMockingContextBase::_mock.getOriginalMethod(_vMethod); + auto mPtr = _vMethod; + auto& mock = MethodMockingContextBase::_mock; C * instance = &(MethodMockingContextBase::_mock.get()); - return [=](arglist&... args) -> R { - auto m = union_cast::type>(mPtr); - return m(instance, args...); + return [=, &mock](arglist&... args) -> R { + auto methodSwapper = mock.createRaiiMethodSwapper(mPtr); + return (instance->*mPtr)(args...); }; } @@ -8676,11 +8738,12 @@ namespace fakeit { } std::function getOriginalMethodForwardArgs() override { - void *mPtr = MethodMockingContextBase::_mock.getOriginalMethod(_vMethod); + auto mPtr = _vMethod; + auto& mock = MethodMockingContextBase::_mock; C * instance = &(MethodMockingContextBase::_mock.get()); - return [=](arglist&... args) -> R { - auto m = union_cast::type>(mPtr); - return m(instance, std::forward(args)...); + return [=, &mock](arglist&... args) -> R { + auto methodSwapper = mock.createRaiiMethodSwapper(mPtr); + return (instance->*mPtr)(std::forward(args)...); }; } }; @@ -8763,6 +8826,11 @@ namespace fakeit { return reinterpret_cast(fake); } + template + Finally createRaiiMethodSwapper(R(C::*vMethod)(arglist...)) { + return _proxy.createRaiiMethodSwapper(vMethod); + } + template void *getOriginalMethod(R (C::*vMethod)(arglist...)) { auto vt = _proxy.getOriginalVT(); @@ -8817,21 +8885,37 @@ namespace fakeit { template struct Prototype { - typedef R Type(Args...); - - typedef R ConstType(Args...) const; - template struct MemberType { - typedef Type(C::*type); - typedef ConstType(C::*cosntType); + using Type = R (C::*)(Args...); + using ConstType = R (C::*)(Args...) const; + using RefType = R (C::*)(Args...) &; + using ConstRefType = R (C::*)(Args...) const&; + using RValRefType = R (C::*)(Args...) &&; + using ConstRValRefType = R (C::*)(Args...) const&&; + + static Type get(Type t) { + return t; + } + + static ConstType getConst(ConstType t) { + return t; + } + + static RefType getRef(RefType t) { + return t; + } + + static ConstRefType getConstRef(ConstRefType t) { + return t; + } - static type get(type t) { + static RValRefType getRValRef(RValRefType t) { return t; } - static cosntType getconst(cosntType t) { + static ConstRValRefType getConstRValRef(ConstRValRefType t) { return t; } @@ -8856,11 +8940,25 @@ namespace fakeit { } - namespace fakeit { namespace internal { + template + struct WithCommonVoid { + using type = T; + }; + + + + + + template + struct WithCommonVoid::value, void>::type> { + using type = void; + }; + + template + using WithCommonVoid_t = typename WithCommonVoid::type; } - using namespace fakeit::internal; template class Mock : public ActualInvocationsSource { @@ -8902,58 +9000,67 @@ namespace fakeit { return impl.stubDataMember(member, ctorargs...); } + template::value && std::is_base_of::value>::type> - MockingContext stub(R (T::*vMethod)(arglist...) const) { - auto methodWithoutConstVolatile = reinterpret_cast(vMethod); + std::is_base_of::value>::type> + MockingContext, arglist...> stub(R (T::*vMethod)(arglist...) const) { + auto methodWithoutConstVolatile = reinterpret_cast (T::*)(arglist...)>(vMethod); return impl.template stubMethod(methodWithoutConstVolatile); } + template::value && std::is_base_of::value>::type> - MockingContext stub(R(T::*vMethod)(arglist...) volatile) { - auto methodWithoutConstVolatile = reinterpret_cast(vMethod); + std::is_base_of::value>::type> + MockingContext, arglist...> stub(R(T::*vMethod)(arglist...) volatile) { + auto methodWithoutConstVolatile = reinterpret_cast(T::*)(arglist...)>(vMethod); return impl.template stubMethod(methodWithoutConstVolatile); } + template::value && std::is_base_of::value>::type> - MockingContext stub(R(T::*vMethod)(arglist...) const volatile) { - auto methodWithoutConstVolatile = reinterpret_cast(vMethod); + std::is_base_of::value>::type> + MockingContext, arglist...> stub(R(T::*vMethod)(arglist...) const volatile) { + auto methodWithoutConstVolatile = reinterpret_cast(T::*)(arglist...)>(vMethod); return impl.template stubMethod(methodWithoutConstVolatile); } + template::value && std::is_base_of::value>::type> - MockingContext stub(R(T::*vMethod)(arglist...)) { - return impl.template stubMethod(vMethod); + std::is_base_of::value>::type> + MockingContext, arglist...> stub(R(T::*vMethod)(arglist...)) { + auto methodWithoutConstVolatile = reinterpret_cast(T::*)(arglist...)>(vMethod); + return impl.template stubMethod(methodWithoutConstVolatile); } + template::value && std::is_base_of::value>::type> - MockingContext stub(R(T::*vMethod)(arglist...) const) { - auto methodWithoutConstVolatile = reinterpret_cast(vMethod); + std::is_base_of::value>::type> + MockingContext, arglist...> stub(R(T::*vMethod)(arglist...) &) { + auto methodWithoutConstVolatile = reinterpret_cast(T::*)(arglist...)>(vMethod); return impl.template stubMethod(methodWithoutConstVolatile); } + template::value && std::is_base_of::value>::type> - MockingContext stub(R(T::*vMethod)(arglist...) volatile) { - auto methodWithoutConstVolatile = reinterpret_cast(vMethod); + std::is_base_of::value>::type> + MockingContext, arglist...> stub(R(T::*vMethod)(arglist...) const&) { + auto methodWithoutConstVolatile = reinterpret_cast(T::*)(arglist...)>(vMethod); return impl.template stubMethod(methodWithoutConstVolatile); } + template::value && std::is_base_of::value>::type> - MockingContext stub(R(T::*vMethod)(arglist...) const volatile) { - auto methodWithoutConstVolatile = reinterpret_cast(vMethod); + std::is_base_of::value>::type> + MockingContext, arglist...> stub(R(T::*vMethod)(arglist...) &&) { + auto methodWithoutConstVolatile = reinterpret_cast(T::*)(arglist...)>(vMethod); return impl.template stubMethod(methodWithoutConstVolatile); } + template::value && std::is_base_of::value>::type> - MockingContext stub(R(T::*vMethod)(arglist...)) { - auto methodWithoutConstVolatile = reinterpret_cast(vMethod); + std::is_base_of::value>::type> + MockingContext, arglist...> stub(R(T::*vMethod)(arglist...) const&&) { + auto methodWithoutConstVolatile = reinterpret_cast(T::*)(arglist...)>(vMethod); return impl.template stubMethod(methodWithoutConstVolatile); } @@ -9975,7 +10082,19 @@ namespace fakeit { fakeit::Prototype::template MemberType::get(&MOCK_TYPE(mock)::method) #define CONST_OVERLOADED_METHOD_PTR(mock, method, prototype) \ - fakeit::Prototype::template MemberType::getconst(&MOCK_TYPE(mock)::method) + fakeit::Prototype::template MemberType::getConst(&MOCK_TYPE(mock)::method) + +#define REF_OVERLOADED_METHOD_PTR(mock, method, prototype) \ + fakeit::Prototype::MemberType::getRef(&MOCK_TYPE(mock)::method) + +#define CONST_REF_OVERLOADED_METHOD_PTR(mock, method, prototype) \ + fakeit::Prototype::MemberType::getConstRef(&MOCK_TYPE(mock)::method) + +#define R_VAL_REF_OVERLOADED_METHOD_PTR(mock, method, prototype) \ + fakeit::Prototype::MemberType::getRValRef(&MOCK_TYPE(mock)::method) + +#define CONST_R_VAL_REF_OVERLOADED_METHOD_PTR(mock, method, prototype) \ + fakeit::Prototype::MemberType::getConstRValRef(&MOCK_TYPE(mock)::method) #define Dtor(mock) \ (mock).dtor().setMethodDetails(#mock,"destructor") @@ -9989,6 +10108,18 @@ namespace fakeit { #define ConstOverloadedMethod(mock, method, prototype) \ (mock).template stub<__COUNTER__>(CONST_OVERLOADED_METHOD_PTR( mock , method, prototype )).setMethodDetails(#mock,#method) +#define RefOverloadedMethod(mock, method, prototype) \ + (mock).template stub<__COUNTER__>(REF_OVERLOADED_METHOD_PTR( mock , method, prototype )).setMethodDetails(#mock,#method) + +#define ConstRefOverloadedMethod(mock, method, prototype) \ + (mock).template stub<__COUNTER__>(CONST_REF_OVERLOADED_METHOD_PTR( mock , method, prototype )).setMethodDetails(#mock,#method) + +#define RValRefOverloadedMethod(mock, method, prototype) \ + (mock).template stub<__COUNTER__>(R_VAL_REF_OVERLOADED_METHOD_PTR( mock , method, prototype )).setMethodDetails(#mock,#method) + +#define ConstRValRefOverloadedMethod(mock, method, prototype) \ + (mock).template stub<__COUNTER__>(CONST_R_VAL_REF_OVERLOADED_METHOD_PTR( mock , method, prototype )).setMethodDetails(#mock,#method) + #define Verify(...) \ Verify( __VA_ARGS__ ).setFileInfo(__FILE__, __LINE__, __func__) @@ -10003,4 +10134,3 @@ namespace fakeit { #define When(call) \ When(call) - diff --git a/single_header/mstest/fakeit.hpp b/single_header/mstest/fakeit.hpp index 5ea285bb..aaf91925 100644 --- a/single_header/mstest/fakeit.hpp +++ b/single_header/mstest/fakeit.hpp @@ -2,7 +2,7 @@ /* * FakeIt - A Simplified C++ Mocking Framework * Copyright (c) Eran Pe'er 2013 - * Generated: 2022-12-16 13:26:50.590953 + * Generated: 2023-04-17 21:28:51.558480 * Distributed under the MIT License. Please refer to the LICENSE file at: * https://github.com/eranpeer/FakeIt */ @@ -18,11 +18,23 @@ #include #include #if defined (__GNUG__) || _MSC_VER >= 1900 -#define FAKEIT_THROWS noexcept(false) -#define FAKEIT_NO_THROWS noexcept(true) +# define FAKEIT_THROWS noexcept(false) +# define FAKEIT_NO_THROWS noexcept(true) #elif defined (_MSC_VER) -#define FAKEIT_THROWS throw(...) -#define FAKEIT_NO_THROWS +# define FAKEIT_THROWS throw(...) +# define FAKEIT_NO_THROWS +#endif + +#ifdef _MSVC_LANG +# define FAKEIT_CPLUSPLUS _MSVC_LANG +#else +# define FAKEIT_CPLUSPLUS __cplusplus +#endif + +#ifdef __GNUG__ +# define FAKEIT_DISARM_UBSAN __attribute__((no_sanitize("undefined"))) +#else +# define FAKEIT_DISARM_UBSAN #endif #include #include @@ -1003,8 +1015,9 @@ namespace fakeit { #include + namespace fakeit { -#if __cplusplus >= 201703L || defined(__cpp_lib_uncaught_exceptions) +#if FAKEIT_CPLUSPLUS >= 201703L || defined(__cpp_lib_uncaught_exceptions) inline bool UncaughtException () { return std::uncaught_exceptions() >= 1; } @@ -5296,6 +5309,7 @@ namespace fakeit { #endif template + FAKEIT_DISARM_UBSAN static typename std::enable_if::value, unsigned int>::type getDestructorOffset() { VirtualOffsetSelector offsetSelctor; @@ -5858,6 +5872,32 @@ namespace fakeit } }; } +#include + +namespace fakeit { + + class Finally { + private: + std::function _finallyClause; + + Finally(const Finally &) = delete; + + Finally &operator=(const Finally &) = delete; + + public: + explicit Finally(std::function f) : + _finallyClause(f) { + } + + Finally(Finally&& other) { + _finallyClause.swap(other._finallyClause); + } + + ~Finally() { + _finallyClause(); + } + }; +} namespace fakeit { struct MethodProxy { @@ -5917,6 +5957,11 @@ namespace fakeit { return MethodProxy(id, offset, union_cast(&MethodProxyCreator::methodProxyX < id > )); } + template + MethodProxy createMethodProxyStatic(unsigned int offset) { + return MethodProxy(id, offset, union_cast(&MethodProxyCreator::methodProxyXStatic < id > )); + } + protected: R methodProxy(unsigned int id, const typename fakeit::production_arg::type... args) { @@ -5932,6 +5977,20 @@ namespace fakeit { R methodProxyX(arglist ... args) { return methodProxy(id, std::forward::type>(args)...); } + + static R methodProxyStatic(void* instance, unsigned int id, const typename fakeit::production_arg::type... args) { + InvocationHandlerCollection *invocationHandlerCollection = InvocationHandlerCollection::getInvocationHandlerCollection( + instance); + MethodInvocationHandler *invocationHandler = + (MethodInvocationHandler *) invocationHandlerCollection->getInvocatoinHandlerPtrById( + id); + return invocationHandler->handleMethodInvocation(std::forward::type>(args)...); + } + + template + static R methodProxyXStatic(void* instance, arglist ... args) { + return methodProxyStatic(instance, id, std::forward::type>(args)...); + } }; } @@ -6022,7 +6081,17 @@ namespace fakeit { void stubDtor(MethodInvocationHandler *methodInvocationHandler) { auto offset = VTUtils::getDestructorOffset(); MethodProxyCreator creator; + + + + + + +#ifdef _MSC_VER + bindDtor(creator.createMethodProxyStatic<0>(offset), methodInvocationHandler); +#else bindDtor(creator.createMethodProxy<0>(offset), methodInvocationHandler); +#endif } template @@ -6075,6 +6144,18 @@ namespace fakeit { return vt; } + template + Finally createRaiiMethodSwapper(R(C::*vMethod)(arglist...)) { + auto offset = VTUtils::getOffset(vMethod); + auto fakeMethod = getFake().getVirtualTable().getMethod(offset); + auto originalMethod = getOriginalVT().getMethod(offset); + + getFake().setMethod(offset, originalMethod); + return Finally{[&, offset, fakeMethod](){ + getFake().setMethod(offset, fakeMethod); + }}; + } + private: template @@ -7589,7 +7670,7 @@ namespace fakeit { MethodStubbingProgress &operator=(const MethodStubbingProgress &other) = delete; template -#if __cplusplus >= 201402L +#if FAKEIT_CPLUSPLUS >= 201402L auto #else std::function::type...)> @@ -7614,7 +7695,7 @@ namespace fakeit { } template -#if __cplusplus >= 201402L +#if FAKEIT_CPLUSPLUS >= 201402L auto #else std::function::type...)> @@ -7733,7 +7814,7 @@ namespace fakeit { MethodStubbingProgress &operator=(const MethodStubbingProgress &other) = delete; template -#if __cplusplus >= 201402L +#if FAKEIT_CPLUSPLUS >= 201402L auto #else std::function::type...)> @@ -7757,7 +7838,7 @@ namespace fakeit { } template -#if __cplusplus >= 201402L +#if FAKEIT_CPLUSPLUS >= 201402L auto #else std::function::type...)> @@ -7799,7 +7880,7 @@ namespace fakeit { template static void CheckPositions(const std::tuple...> arg_vals) { -#if __cplusplus >= 201402L && !defined(_WIN32) +#if FAKEIT_CPLUSPLUS >= 201402L && !defined(_WIN32) static_assert(std::get(arg_vals).pos <= max_index, "Argument index out of range"); ArgValidator::CheckPositions(arg_vals); @@ -7851,7 +7932,7 @@ namespace fakeit { struct ArgLocator { template static void AssignArg(current_arg &&p, std::tuple...> arg_vals) { -#if __cplusplus >= 201703L && !defined (_WIN32) +#if FAKEIT_CPLUSPLUS >= 201703L && !defined (_WIN32) if constexpr (std::get(arg_vals).pos == arg_index) GetArg(std::forward(p)) = std::get(arg_vals).value; #else @@ -7862,7 +7943,7 @@ namespace fakeit { ArgLocator::AssignArg(std::forward(p), arg_vals); } -#if __cplusplus < 201703L || defined (_WIN32) +#if FAKEIT_CPLUSPLUS < 201703L || defined (_WIN32) private: template static @@ -7920,28 +8001,8 @@ namespace fakeit { using placeholders::operator <=; } #include -#include - -namespace fakeit { - - class Finally { - private: - std::function _finallyClause; - - Finally(const Finally &); - Finally &operator=(const Finally &); - public: - explicit Finally(std::function f) : - _finallyClause(f) { - } - - ~Finally() { - _finallyClause(); - } - }; -} namespace fakeit { @@ -8658,11 +8719,12 @@ namespace fakeit { template::value...>::value, int>::type = 0> std::function getOriginalMethodCopyArgsInternal(int) { - void *mPtr = MethodMockingContextBase::_mock.getOriginalMethod(_vMethod); + auto mPtr = _vMethod; + auto& mock = MethodMockingContextBase::_mock; C * instance = &(MethodMockingContextBase::_mock.get()); - return [=](arglist&... args) -> R { - auto m = union_cast::type>(mPtr); - return m(instance, args...); + return [=, &mock](arglist&... args) -> R { + auto methodSwapper = mock.createRaiiMethodSwapper(mPtr); + return (instance->*mPtr)(args...); }; } @@ -8678,11 +8740,12 @@ namespace fakeit { } std::function getOriginalMethodForwardArgs() override { - void *mPtr = MethodMockingContextBase::_mock.getOriginalMethod(_vMethod); + auto mPtr = _vMethod; + auto& mock = MethodMockingContextBase::_mock; C * instance = &(MethodMockingContextBase::_mock.get()); - return [=](arglist&... args) -> R { - auto m = union_cast::type>(mPtr); - return m(instance, std::forward(args)...); + return [=, &mock](arglist&... args) -> R { + auto methodSwapper = mock.createRaiiMethodSwapper(mPtr); + return (instance->*mPtr)(std::forward(args)...); }; } }; @@ -8765,6 +8828,11 @@ namespace fakeit { return reinterpret_cast(fake); } + template + Finally createRaiiMethodSwapper(R(C::*vMethod)(arglist...)) { + return _proxy.createRaiiMethodSwapper(vMethod); + } + template void *getOriginalMethod(R (C::*vMethod)(arglist...)) { auto vt = _proxy.getOriginalVT(); @@ -8819,21 +8887,37 @@ namespace fakeit { template struct Prototype { - typedef R Type(Args...); - - typedef R ConstType(Args...) const; - template struct MemberType { - typedef Type(C::*type); - typedef ConstType(C::*cosntType); + using Type = R (C::*)(Args...); + using ConstType = R (C::*)(Args...) const; + using RefType = R (C::*)(Args...) &; + using ConstRefType = R (C::*)(Args...) const&; + using RValRefType = R (C::*)(Args...) &&; + using ConstRValRefType = R (C::*)(Args...) const&&; + + static Type get(Type t) { + return t; + } + + static ConstType getConst(ConstType t) { + return t; + } + + static RefType getRef(RefType t) { + return t; + } + + static ConstRefType getConstRef(ConstRefType t) { + return t; + } - static type get(type t) { + static RValRefType getRValRef(RValRefType t) { return t; } - static cosntType getconst(cosntType t) { + static ConstRValRefType getConstRValRef(ConstRValRefType t) { return t; } @@ -8858,11 +8942,25 @@ namespace fakeit { } - namespace fakeit { namespace internal { + template + struct WithCommonVoid { + using type = T; + }; + + + + + + template + struct WithCommonVoid::value, void>::type> { + using type = void; + }; + + template + using WithCommonVoid_t = typename WithCommonVoid::type; } - using namespace fakeit::internal; template class Mock : public ActualInvocationsSource { @@ -8904,58 +9002,67 @@ namespace fakeit { return impl.stubDataMember(member, ctorargs...); } + template::value && std::is_base_of::value>::type> - MockingContext stub(R (T::*vMethod)(arglist...) const) { - auto methodWithoutConstVolatile = reinterpret_cast(vMethod); + std::is_base_of::value>::type> + MockingContext, arglist...> stub(R (T::*vMethod)(arglist...) const) { + auto methodWithoutConstVolatile = reinterpret_cast (T::*)(arglist...)>(vMethod); return impl.template stubMethod(methodWithoutConstVolatile); } + template::value && std::is_base_of::value>::type> - MockingContext stub(R(T::*vMethod)(arglist...) volatile) { - auto methodWithoutConstVolatile = reinterpret_cast(vMethod); + std::is_base_of::value>::type> + MockingContext, arglist...> stub(R(T::*vMethod)(arglist...) volatile) { + auto methodWithoutConstVolatile = reinterpret_cast(T::*)(arglist...)>(vMethod); return impl.template stubMethod(methodWithoutConstVolatile); } + template::value && std::is_base_of::value>::type> - MockingContext stub(R(T::*vMethod)(arglist...) const volatile) { - auto methodWithoutConstVolatile = reinterpret_cast(vMethod); + std::is_base_of::value>::type> + MockingContext, arglist...> stub(R(T::*vMethod)(arglist...) const volatile) { + auto methodWithoutConstVolatile = reinterpret_cast(T::*)(arglist...)>(vMethod); return impl.template stubMethod(methodWithoutConstVolatile); } + template::value && std::is_base_of::value>::type> - MockingContext stub(R(T::*vMethod)(arglist...)) { - return impl.template stubMethod(vMethod); + std::is_base_of::value>::type> + MockingContext, arglist...> stub(R(T::*vMethod)(arglist...)) { + auto methodWithoutConstVolatile = reinterpret_cast(T::*)(arglist...)>(vMethod); + return impl.template stubMethod(methodWithoutConstVolatile); } + template::value && std::is_base_of::value>::type> - MockingContext stub(R(T::*vMethod)(arglist...) const) { - auto methodWithoutConstVolatile = reinterpret_cast(vMethod); + std::is_base_of::value>::type> + MockingContext, arglist...> stub(R(T::*vMethod)(arglist...) &) { + auto methodWithoutConstVolatile = reinterpret_cast(T::*)(arglist...)>(vMethod); return impl.template stubMethod(methodWithoutConstVolatile); } + template::value && std::is_base_of::value>::type> - MockingContext stub(R(T::*vMethod)(arglist...) volatile) { - auto methodWithoutConstVolatile = reinterpret_cast(vMethod); + std::is_base_of::value>::type> + MockingContext, arglist...> stub(R(T::*vMethod)(arglist...) const&) { + auto methodWithoutConstVolatile = reinterpret_cast(T::*)(arglist...)>(vMethod); return impl.template stubMethod(methodWithoutConstVolatile); } + template::value && std::is_base_of::value>::type> - MockingContext stub(R(T::*vMethod)(arglist...) const volatile) { - auto methodWithoutConstVolatile = reinterpret_cast(vMethod); + std::is_base_of::value>::type> + MockingContext, arglist...> stub(R(T::*vMethod)(arglist...) &&) { + auto methodWithoutConstVolatile = reinterpret_cast(T::*)(arglist...)>(vMethod); return impl.template stubMethod(methodWithoutConstVolatile); } + template::value && std::is_base_of::value>::type> - MockingContext stub(R(T::*vMethod)(arglist...)) { - auto methodWithoutConstVolatile = reinterpret_cast(vMethod); + std::is_base_of::value>::type> + MockingContext, arglist...> stub(R(T::*vMethod)(arglist...) const&&) { + auto methodWithoutConstVolatile = reinterpret_cast(T::*)(arglist...)>(vMethod); return impl.template stubMethod(methodWithoutConstVolatile); } @@ -9991,7 +10098,19 @@ namespace fakeit { fakeit::Prototype::template MemberType::get(&MOCK_TYPE(mock)::method) #define CONST_OVERLOADED_METHOD_PTR(mock, method, prototype) \ - fakeit::Prototype::template MemberType::getconst(&MOCK_TYPE(mock)::method) + fakeit::Prototype::template MemberType::getConst(&MOCK_TYPE(mock)::method) + +#define REF_OVERLOADED_METHOD_PTR(mock, method, prototype) \ + fakeit::Prototype::MemberType::getRef(&MOCK_TYPE(mock)::method) + +#define CONST_REF_OVERLOADED_METHOD_PTR(mock, method, prototype) \ + fakeit::Prototype::MemberType::getConstRef(&MOCK_TYPE(mock)::method) + +#define R_VAL_REF_OVERLOADED_METHOD_PTR(mock, method, prototype) \ + fakeit::Prototype::MemberType::getRValRef(&MOCK_TYPE(mock)::method) + +#define CONST_R_VAL_REF_OVERLOADED_METHOD_PTR(mock, method, prototype) \ + fakeit::Prototype::MemberType::getConstRValRef(&MOCK_TYPE(mock)::method) #define Dtor(mock) \ (mock).dtor().setMethodDetails(#mock,"destructor") @@ -10005,6 +10124,18 @@ namespace fakeit { #define ConstOverloadedMethod(mock, method, prototype) \ (mock).template stub<__COUNTER__>(CONST_OVERLOADED_METHOD_PTR( mock , method, prototype )).setMethodDetails(#mock,#method) +#define RefOverloadedMethod(mock, method, prototype) \ + (mock).template stub<__COUNTER__>(REF_OVERLOADED_METHOD_PTR( mock , method, prototype )).setMethodDetails(#mock,#method) + +#define ConstRefOverloadedMethod(mock, method, prototype) \ + (mock).template stub<__COUNTER__>(CONST_REF_OVERLOADED_METHOD_PTR( mock , method, prototype )).setMethodDetails(#mock,#method) + +#define RValRefOverloadedMethod(mock, method, prototype) \ + (mock).template stub<__COUNTER__>(R_VAL_REF_OVERLOADED_METHOD_PTR( mock , method, prototype )).setMethodDetails(#mock,#method) + +#define ConstRValRefOverloadedMethod(mock, method, prototype) \ + (mock).template stub<__COUNTER__>(CONST_R_VAL_REF_OVERLOADED_METHOD_PTR( mock , method, prototype )).setMethodDetails(#mock,#method) + #define Verify(...) \ Verify( __VA_ARGS__ ).setFileInfo(__FILE__, __LINE__, __func__) @@ -10020,5 +10151,4 @@ namespace fakeit { #define When(call) \ When(call) - #endif diff --git a/single_header/nunit/fakeit.hpp b/single_header/nunit/fakeit.hpp index ab0cfcc4..8ae5af1a 100644 --- a/single_header/nunit/fakeit.hpp +++ b/single_header/nunit/fakeit.hpp @@ -2,7 +2,7 @@ /* * FakeIt - A Simplified C++ Mocking Framework * Copyright (c) Eran Pe'er 2013 - * Generated: 2022-12-16 13:26:50.853101 + * Generated: 2023-04-17 21:28:51.825688 * Distributed under the MIT License. Please refer to the LICENSE file at: * https://github.com/eranpeer/FakeIt */ @@ -18,11 +18,23 @@ #include #include #if defined (__GNUG__) || _MSC_VER >= 1900 -#define FAKEIT_THROWS noexcept(false) -#define FAKEIT_NO_THROWS noexcept(true) +# define FAKEIT_THROWS noexcept(false) +# define FAKEIT_NO_THROWS noexcept(true) #elif defined (_MSC_VER) -#define FAKEIT_THROWS throw(...) -#define FAKEIT_NO_THROWS +# define FAKEIT_THROWS throw(...) +# define FAKEIT_NO_THROWS +#endif + +#ifdef _MSVC_LANG +# define FAKEIT_CPLUSPLUS _MSVC_LANG +#else +# define FAKEIT_CPLUSPLUS __cplusplus +#endif + +#ifdef __GNUG__ +# define FAKEIT_DISARM_UBSAN __attribute__((no_sanitize("undefined"))) +#else +# define FAKEIT_DISARM_UBSAN #endif #include #include @@ -1003,8 +1015,9 @@ namespace fakeit { #include + namespace fakeit { -#if __cplusplus >= 201703L || defined(__cpp_lib_uncaught_exceptions) +#if FAKEIT_CPLUSPLUS >= 201703L || defined(__cpp_lib_uncaught_exceptions) inline bool UncaughtException () { return std::uncaught_exceptions() >= 1; } @@ -5279,6 +5292,7 @@ namespace fakeit { #endif template + FAKEIT_DISARM_UBSAN static typename std::enable_if::value, unsigned int>::type getDestructorOffset() { VirtualOffsetSelector offsetSelctor; @@ -5841,6 +5855,32 @@ namespace fakeit } }; } +#include + +namespace fakeit { + + class Finally { + private: + std::function _finallyClause; + + Finally(const Finally &) = delete; + + Finally &operator=(const Finally &) = delete; + + public: + explicit Finally(std::function f) : + _finallyClause(f) { + } + + Finally(Finally&& other) { + _finallyClause.swap(other._finallyClause); + } + + ~Finally() { + _finallyClause(); + } + }; +} namespace fakeit { struct MethodProxy { @@ -5900,6 +5940,11 @@ namespace fakeit { return MethodProxy(id, offset, union_cast(&MethodProxyCreator::methodProxyX < id > )); } + template + MethodProxy createMethodProxyStatic(unsigned int offset) { + return MethodProxy(id, offset, union_cast(&MethodProxyCreator::methodProxyXStatic < id > )); + } + protected: R methodProxy(unsigned int id, const typename fakeit::production_arg::type... args) { @@ -5915,6 +5960,20 @@ namespace fakeit { R methodProxyX(arglist ... args) { return methodProxy(id, std::forward::type>(args)...); } + + static R methodProxyStatic(void* instance, unsigned int id, const typename fakeit::production_arg::type... args) { + InvocationHandlerCollection *invocationHandlerCollection = InvocationHandlerCollection::getInvocationHandlerCollection( + instance); + MethodInvocationHandler *invocationHandler = + (MethodInvocationHandler *) invocationHandlerCollection->getInvocatoinHandlerPtrById( + id); + return invocationHandler->handleMethodInvocation(std::forward::type>(args)...); + } + + template + static R methodProxyXStatic(void* instance, arglist ... args) { + return methodProxyStatic(instance, id, std::forward::type>(args)...); + } }; } @@ -6005,7 +6064,17 @@ namespace fakeit { void stubDtor(MethodInvocationHandler *methodInvocationHandler) { auto offset = VTUtils::getDestructorOffset(); MethodProxyCreator creator; + + + + + + +#ifdef _MSC_VER + bindDtor(creator.createMethodProxyStatic<0>(offset), methodInvocationHandler); +#else bindDtor(creator.createMethodProxy<0>(offset), methodInvocationHandler); +#endif } template @@ -6058,6 +6127,18 @@ namespace fakeit { return vt; } + template + Finally createRaiiMethodSwapper(R(C::*vMethod)(arglist...)) { + auto offset = VTUtils::getOffset(vMethod); + auto fakeMethod = getFake().getVirtualTable().getMethod(offset); + auto originalMethod = getOriginalVT().getMethod(offset); + + getFake().setMethod(offset, originalMethod); + return Finally{[&, offset, fakeMethod](){ + getFake().setMethod(offset, fakeMethod); + }}; + } + private: template @@ -7572,7 +7653,7 @@ namespace fakeit { MethodStubbingProgress &operator=(const MethodStubbingProgress &other) = delete; template -#if __cplusplus >= 201402L +#if FAKEIT_CPLUSPLUS >= 201402L auto #else std::function::type...)> @@ -7597,7 +7678,7 @@ namespace fakeit { } template -#if __cplusplus >= 201402L +#if FAKEIT_CPLUSPLUS >= 201402L auto #else std::function::type...)> @@ -7716,7 +7797,7 @@ namespace fakeit { MethodStubbingProgress &operator=(const MethodStubbingProgress &other) = delete; template -#if __cplusplus >= 201402L +#if FAKEIT_CPLUSPLUS >= 201402L auto #else std::function::type...)> @@ -7740,7 +7821,7 @@ namespace fakeit { } template -#if __cplusplus >= 201402L +#if FAKEIT_CPLUSPLUS >= 201402L auto #else std::function::type...)> @@ -7782,7 +7863,7 @@ namespace fakeit { template static void CheckPositions(const std::tuple...> arg_vals) { -#if __cplusplus >= 201402L && !defined(_WIN32) +#if FAKEIT_CPLUSPLUS >= 201402L && !defined(_WIN32) static_assert(std::get(arg_vals).pos <= max_index, "Argument index out of range"); ArgValidator::CheckPositions(arg_vals); @@ -7834,7 +7915,7 @@ namespace fakeit { struct ArgLocator { template static void AssignArg(current_arg &&p, std::tuple...> arg_vals) { -#if __cplusplus >= 201703L && !defined (_WIN32) +#if FAKEIT_CPLUSPLUS >= 201703L && !defined (_WIN32) if constexpr (std::get(arg_vals).pos == arg_index) GetArg(std::forward(p)) = std::get(arg_vals).value; #else @@ -7845,7 +7926,7 @@ namespace fakeit { ArgLocator::AssignArg(std::forward(p), arg_vals); } -#if __cplusplus < 201703L || defined (_WIN32) +#if FAKEIT_CPLUSPLUS < 201703L || defined (_WIN32) private: template static @@ -7903,28 +7984,8 @@ namespace fakeit { using placeholders::operator <=; } #include -#include - -namespace fakeit { - - class Finally { - private: - std::function _finallyClause; - - Finally(const Finally &); - Finally &operator=(const Finally &); - public: - explicit Finally(std::function f) : - _finallyClause(f) { - } - - ~Finally() { - _finallyClause(); - } - }; -} namespace fakeit { @@ -8641,11 +8702,12 @@ namespace fakeit { template::value...>::value, int>::type = 0> std::function getOriginalMethodCopyArgsInternal(int) { - void *mPtr = MethodMockingContextBase::_mock.getOriginalMethod(_vMethod); + auto mPtr = _vMethod; + auto& mock = MethodMockingContextBase::_mock; C * instance = &(MethodMockingContextBase::_mock.get()); - return [=](arglist&... args) -> R { - auto m = union_cast::type>(mPtr); - return m(instance, args...); + return [=, &mock](arglist&... args) -> R { + auto methodSwapper = mock.createRaiiMethodSwapper(mPtr); + return (instance->*mPtr)(args...); }; } @@ -8661,11 +8723,12 @@ namespace fakeit { } std::function getOriginalMethodForwardArgs() override { - void *mPtr = MethodMockingContextBase::_mock.getOriginalMethod(_vMethod); + auto mPtr = _vMethod; + auto& mock = MethodMockingContextBase::_mock; C * instance = &(MethodMockingContextBase::_mock.get()); - return [=](arglist&... args) -> R { - auto m = union_cast::type>(mPtr); - return m(instance, std::forward(args)...); + return [=, &mock](arglist&... args) -> R { + auto methodSwapper = mock.createRaiiMethodSwapper(mPtr); + return (instance->*mPtr)(std::forward(args)...); }; } }; @@ -8748,6 +8811,11 @@ namespace fakeit { return reinterpret_cast(fake); } + template + Finally createRaiiMethodSwapper(R(C::*vMethod)(arglist...)) { + return _proxy.createRaiiMethodSwapper(vMethod); + } + template void *getOriginalMethod(R (C::*vMethod)(arglist...)) { auto vt = _proxy.getOriginalVT(); @@ -8802,21 +8870,37 @@ namespace fakeit { template struct Prototype { - typedef R Type(Args...); - - typedef R ConstType(Args...) const; - template struct MemberType { - typedef Type(C::*type); - typedef ConstType(C::*cosntType); + using Type = R (C::*)(Args...); + using ConstType = R (C::*)(Args...) const; + using RefType = R (C::*)(Args...) &; + using ConstRefType = R (C::*)(Args...) const&; + using RValRefType = R (C::*)(Args...) &&; + using ConstRValRefType = R (C::*)(Args...) const&&; + + static Type get(Type t) { + return t; + } + + static ConstType getConst(ConstType t) { + return t; + } + + static RefType getRef(RefType t) { + return t; + } + + static ConstRefType getConstRef(ConstRefType t) { + return t; + } - static type get(type t) { + static RValRefType getRValRef(RValRefType t) { return t; } - static cosntType getconst(cosntType t) { + static ConstRValRefType getConstRValRef(ConstRValRefType t) { return t; } @@ -8841,11 +8925,25 @@ namespace fakeit { } - namespace fakeit { namespace internal { + template + struct WithCommonVoid { + using type = T; + }; + + + + + + template + struct WithCommonVoid::value, void>::type> { + using type = void; + }; + + template + using WithCommonVoid_t = typename WithCommonVoid::type; } - using namespace fakeit::internal; template class Mock : public ActualInvocationsSource { @@ -8887,58 +8985,67 @@ namespace fakeit { return impl.stubDataMember(member, ctorargs...); } + template::value && std::is_base_of::value>::type> - MockingContext stub(R (T::*vMethod)(arglist...) const) { - auto methodWithoutConstVolatile = reinterpret_cast(vMethod); + std::is_base_of::value>::type> + MockingContext, arglist...> stub(R (T::*vMethod)(arglist...) const) { + auto methodWithoutConstVolatile = reinterpret_cast (T::*)(arglist...)>(vMethod); return impl.template stubMethod(methodWithoutConstVolatile); } + template::value && std::is_base_of::value>::type> - MockingContext stub(R(T::*vMethod)(arglist...) volatile) { - auto methodWithoutConstVolatile = reinterpret_cast(vMethod); + std::is_base_of::value>::type> + MockingContext, arglist...> stub(R(T::*vMethod)(arglist...) volatile) { + auto methodWithoutConstVolatile = reinterpret_cast(T::*)(arglist...)>(vMethod); return impl.template stubMethod(methodWithoutConstVolatile); } + template::value && std::is_base_of::value>::type> - MockingContext stub(R(T::*vMethod)(arglist...) const volatile) { - auto methodWithoutConstVolatile = reinterpret_cast(vMethod); + std::is_base_of::value>::type> + MockingContext, arglist...> stub(R(T::*vMethod)(arglist...) const volatile) { + auto methodWithoutConstVolatile = reinterpret_cast(T::*)(arglist...)>(vMethod); return impl.template stubMethod(methodWithoutConstVolatile); } + template::value && std::is_base_of::value>::type> - MockingContext stub(R(T::*vMethod)(arglist...)) { - return impl.template stubMethod(vMethod); + std::is_base_of::value>::type> + MockingContext, arglist...> stub(R(T::*vMethod)(arglist...)) { + auto methodWithoutConstVolatile = reinterpret_cast(T::*)(arglist...)>(vMethod); + return impl.template stubMethod(methodWithoutConstVolatile); } + template::value && std::is_base_of::value>::type> - MockingContext stub(R(T::*vMethod)(arglist...) const) { - auto methodWithoutConstVolatile = reinterpret_cast(vMethod); + std::is_base_of::value>::type> + MockingContext, arglist...> stub(R(T::*vMethod)(arglist...) &) { + auto methodWithoutConstVolatile = reinterpret_cast(T::*)(arglist...)>(vMethod); return impl.template stubMethod(methodWithoutConstVolatile); } + template::value && std::is_base_of::value>::type> - MockingContext stub(R(T::*vMethod)(arglist...) volatile) { - auto methodWithoutConstVolatile = reinterpret_cast(vMethod); + std::is_base_of::value>::type> + MockingContext, arglist...> stub(R(T::*vMethod)(arglist...) const&) { + auto methodWithoutConstVolatile = reinterpret_cast(T::*)(arglist...)>(vMethod); return impl.template stubMethod(methodWithoutConstVolatile); } + template::value && std::is_base_of::value>::type> - MockingContext stub(R(T::*vMethod)(arglist...) const volatile) { - auto methodWithoutConstVolatile = reinterpret_cast(vMethod); + std::is_base_of::value>::type> + MockingContext, arglist...> stub(R(T::*vMethod)(arglist...) &&) { + auto methodWithoutConstVolatile = reinterpret_cast(T::*)(arglist...)>(vMethod); return impl.template stubMethod(methodWithoutConstVolatile); } + template::value && std::is_base_of::value>::type> - MockingContext stub(R(T::*vMethod)(arglist...)) { - auto methodWithoutConstVolatile = reinterpret_cast(vMethod); + std::is_base_of::value>::type> + MockingContext, arglist...> stub(R(T::*vMethod)(arglist...) const&&) { + auto methodWithoutConstVolatile = reinterpret_cast(T::*)(arglist...)>(vMethod); return impl.template stubMethod(methodWithoutConstVolatile); } @@ -9974,7 +10081,19 @@ namespace fakeit { fakeit::Prototype::template MemberType::get(&MOCK_TYPE(mock)::method) #define CONST_OVERLOADED_METHOD_PTR(mock, method, prototype) \ - fakeit::Prototype::template MemberType::getconst(&MOCK_TYPE(mock)::method) + fakeit::Prototype::template MemberType::getConst(&MOCK_TYPE(mock)::method) + +#define REF_OVERLOADED_METHOD_PTR(mock, method, prototype) \ + fakeit::Prototype::MemberType::getRef(&MOCK_TYPE(mock)::method) + +#define CONST_REF_OVERLOADED_METHOD_PTR(mock, method, prototype) \ + fakeit::Prototype::MemberType::getConstRef(&MOCK_TYPE(mock)::method) + +#define R_VAL_REF_OVERLOADED_METHOD_PTR(mock, method, prototype) \ + fakeit::Prototype::MemberType::getRValRef(&MOCK_TYPE(mock)::method) + +#define CONST_R_VAL_REF_OVERLOADED_METHOD_PTR(mock, method, prototype) \ + fakeit::Prototype::MemberType::getConstRValRef(&MOCK_TYPE(mock)::method) #define Dtor(mock) \ (mock).dtor().setMethodDetails(#mock,"destructor") @@ -9988,6 +10107,18 @@ namespace fakeit { #define ConstOverloadedMethod(mock, method, prototype) \ (mock).template stub<__COUNTER__>(CONST_OVERLOADED_METHOD_PTR( mock , method, prototype )).setMethodDetails(#mock,#method) +#define RefOverloadedMethod(mock, method, prototype) \ + (mock).template stub<__COUNTER__>(REF_OVERLOADED_METHOD_PTR( mock , method, prototype )).setMethodDetails(#mock,#method) + +#define ConstRefOverloadedMethod(mock, method, prototype) \ + (mock).template stub<__COUNTER__>(CONST_REF_OVERLOADED_METHOD_PTR( mock , method, prototype )).setMethodDetails(#mock,#method) + +#define RValRefOverloadedMethod(mock, method, prototype) \ + (mock).template stub<__COUNTER__>(R_VAL_REF_OVERLOADED_METHOD_PTR( mock , method, prototype )).setMethodDetails(#mock,#method) + +#define ConstRValRefOverloadedMethod(mock, method, prototype) \ + (mock).template stub<__COUNTER__>(CONST_R_VAL_REF_OVERLOADED_METHOD_PTR( mock , method, prototype )).setMethodDetails(#mock,#method) + #define Verify(...) \ Verify( __VA_ARGS__ ).setFileInfo(__FILE__, __LINE__, __func__) @@ -10003,5 +10134,4 @@ namespace fakeit { #define When(call) \ When(call) - #endif diff --git a/single_header/qtest/fakeit.hpp b/single_header/qtest/fakeit.hpp index 098df610..744a50dd 100644 --- a/single_header/qtest/fakeit.hpp +++ b/single_header/qtest/fakeit.hpp @@ -2,7 +2,7 @@ /* * FakeIt - A Simplified C++ Mocking Framework * Copyright (c) Eran Pe'er 2013 - * Generated: 2022-12-16 13:26:51.124635 + * Generated: 2023-04-17 21:28:52.091640 * Distributed under the MIT License. Please refer to the LICENSE file at: * https://github.com/eranpeer/FakeIt */ @@ -18,11 +18,23 @@ #include #include #if defined (__GNUG__) || _MSC_VER >= 1900 -#define FAKEIT_THROWS noexcept(false) -#define FAKEIT_NO_THROWS noexcept(true) +# define FAKEIT_THROWS noexcept(false) +# define FAKEIT_NO_THROWS noexcept(true) #elif defined (_MSC_VER) -#define FAKEIT_THROWS throw(...) -#define FAKEIT_NO_THROWS +# define FAKEIT_THROWS throw(...) +# define FAKEIT_NO_THROWS +#endif + +#ifdef _MSVC_LANG +# define FAKEIT_CPLUSPLUS _MSVC_LANG +#else +# define FAKEIT_CPLUSPLUS __cplusplus +#endif + +#ifdef __GNUG__ +# define FAKEIT_DISARM_UBSAN __attribute__((no_sanitize("undefined"))) +#else +# define FAKEIT_DISARM_UBSAN #endif #include #include @@ -1003,8 +1015,9 @@ namespace fakeit { #include + namespace fakeit { -#if __cplusplus >= 201703L || defined(__cpp_lib_uncaught_exceptions) +#if FAKEIT_CPLUSPLUS >= 201703L || defined(__cpp_lib_uncaught_exceptions) inline bool UncaughtException () { return std::uncaught_exceptions() >= 1; } @@ -5280,6 +5293,7 @@ namespace fakeit { #endif template + FAKEIT_DISARM_UBSAN static typename std::enable_if::value, unsigned int>::type getDestructorOffset() { VirtualOffsetSelector offsetSelctor; @@ -5842,6 +5856,32 @@ namespace fakeit } }; } +#include + +namespace fakeit { + + class Finally { + private: + std::function _finallyClause; + + Finally(const Finally &) = delete; + + Finally &operator=(const Finally &) = delete; + + public: + explicit Finally(std::function f) : + _finallyClause(f) { + } + + Finally(Finally&& other) { + _finallyClause.swap(other._finallyClause); + } + + ~Finally() { + _finallyClause(); + } + }; +} namespace fakeit { struct MethodProxy { @@ -5901,6 +5941,11 @@ namespace fakeit { return MethodProxy(id, offset, union_cast(&MethodProxyCreator::methodProxyX < id > )); } + template + MethodProxy createMethodProxyStatic(unsigned int offset) { + return MethodProxy(id, offset, union_cast(&MethodProxyCreator::methodProxyXStatic < id > )); + } + protected: R methodProxy(unsigned int id, const typename fakeit::production_arg::type... args) { @@ -5916,6 +5961,20 @@ namespace fakeit { R methodProxyX(arglist ... args) { return methodProxy(id, std::forward::type>(args)...); } + + static R methodProxyStatic(void* instance, unsigned int id, const typename fakeit::production_arg::type... args) { + InvocationHandlerCollection *invocationHandlerCollection = InvocationHandlerCollection::getInvocationHandlerCollection( + instance); + MethodInvocationHandler *invocationHandler = + (MethodInvocationHandler *) invocationHandlerCollection->getInvocatoinHandlerPtrById( + id); + return invocationHandler->handleMethodInvocation(std::forward::type>(args)...); + } + + template + static R methodProxyXStatic(void* instance, arglist ... args) { + return methodProxyStatic(instance, id, std::forward::type>(args)...); + } }; } @@ -6006,7 +6065,17 @@ namespace fakeit { void stubDtor(MethodInvocationHandler *methodInvocationHandler) { auto offset = VTUtils::getDestructorOffset(); MethodProxyCreator creator; + + + + + + +#ifdef _MSC_VER + bindDtor(creator.createMethodProxyStatic<0>(offset), methodInvocationHandler); +#else bindDtor(creator.createMethodProxy<0>(offset), methodInvocationHandler); +#endif } template @@ -6059,6 +6128,18 @@ namespace fakeit { return vt; } + template + Finally createRaiiMethodSwapper(R(C::*vMethod)(arglist...)) { + auto offset = VTUtils::getOffset(vMethod); + auto fakeMethod = getFake().getVirtualTable().getMethod(offset); + auto originalMethod = getOriginalVT().getMethod(offset); + + getFake().setMethod(offset, originalMethod); + return Finally{[&, offset, fakeMethod](){ + getFake().setMethod(offset, fakeMethod); + }}; + } + private: template @@ -7573,7 +7654,7 @@ namespace fakeit { MethodStubbingProgress &operator=(const MethodStubbingProgress &other) = delete; template -#if __cplusplus >= 201402L +#if FAKEIT_CPLUSPLUS >= 201402L auto #else std::function::type...)> @@ -7598,7 +7679,7 @@ namespace fakeit { } template -#if __cplusplus >= 201402L +#if FAKEIT_CPLUSPLUS >= 201402L auto #else std::function::type...)> @@ -7717,7 +7798,7 @@ namespace fakeit { MethodStubbingProgress &operator=(const MethodStubbingProgress &other) = delete; template -#if __cplusplus >= 201402L +#if FAKEIT_CPLUSPLUS >= 201402L auto #else std::function::type...)> @@ -7741,7 +7822,7 @@ namespace fakeit { } template -#if __cplusplus >= 201402L +#if FAKEIT_CPLUSPLUS >= 201402L auto #else std::function::type...)> @@ -7783,7 +7864,7 @@ namespace fakeit { template static void CheckPositions(const std::tuple...> arg_vals) { -#if __cplusplus >= 201402L && !defined(_WIN32) +#if FAKEIT_CPLUSPLUS >= 201402L && !defined(_WIN32) static_assert(std::get(arg_vals).pos <= max_index, "Argument index out of range"); ArgValidator::CheckPositions(arg_vals); @@ -7835,7 +7916,7 @@ namespace fakeit { struct ArgLocator { template static void AssignArg(current_arg &&p, std::tuple...> arg_vals) { -#if __cplusplus >= 201703L && !defined (_WIN32) +#if FAKEIT_CPLUSPLUS >= 201703L && !defined (_WIN32) if constexpr (std::get(arg_vals).pos == arg_index) GetArg(std::forward(p)) = std::get(arg_vals).value; #else @@ -7846,7 +7927,7 @@ namespace fakeit { ArgLocator::AssignArg(std::forward(p), arg_vals); } -#if __cplusplus < 201703L || defined (_WIN32) +#if FAKEIT_CPLUSPLUS < 201703L || defined (_WIN32) private: template static @@ -7904,28 +7985,8 @@ namespace fakeit { using placeholders::operator <=; } #include -#include - -namespace fakeit { - - class Finally { - private: - std::function _finallyClause; - - Finally(const Finally &); - Finally &operator=(const Finally &); - public: - explicit Finally(std::function f) : - _finallyClause(f) { - } - - ~Finally() { - _finallyClause(); - } - }; -} namespace fakeit { @@ -8642,11 +8703,12 @@ namespace fakeit { template::value...>::value, int>::type = 0> std::function getOriginalMethodCopyArgsInternal(int) { - void *mPtr = MethodMockingContextBase::_mock.getOriginalMethod(_vMethod); + auto mPtr = _vMethod; + auto& mock = MethodMockingContextBase::_mock; C * instance = &(MethodMockingContextBase::_mock.get()); - return [=](arglist&... args) -> R { - auto m = union_cast::type>(mPtr); - return m(instance, args...); + return [=, &mock](arglist&... args) -> R { + auto methodSwapper = mock.createRaiiMethodSwapper(mPtr); + return (instance->*mPtr)(args...); }; } @@ -8662,11 +8724,12 @@ namespace fakeit { } std::function getOriginalMethodForwardArgs() override { - void *mPtr = MethodMockingContextBase::_mock.getOriginalMethod(_vMethod); + auto mPtr = _vMethod; + auto& mock = MethodMockingContextBase::_mock; C * instance = &(MethodMockingContextBase::_mock.get()); - return [=](arglist&... args) -> R { - auto m = union_cast::type>(mPtr); - return m(instance, std::forward(args)...); + return [=, &mock](arglist&... args) -> R { + auto methodSwapper = mock.createRaiiMethodSwapper(mPtr); + return (instance->*mPtr)(std::forward(args)...); }; } }; @@ -8749,6 +8812,11 @@ namespace fakeit { return reinterpret_cast(fake); } + template + Finally createRaiiMethodSwapper(R(C::*vMethod)(arglist...)) { + return _proxy.createRaiiMethodSwapper(vMethod); + } + template void *getOriginalMethod(R (C::*vMethod)(arglist...)) { auto vt = _proxy.getOriginalVT(); @@ -8803,21 +8871,37 @@ namespace fakeit { template struct Prototype { - typedef R Type(Args...); - - typedef R ConstType(Args...) const; - template struct MemberType { - typedef Type(C::*type); - typedef ConstType(C::*cosntType); + using Type = R (C::*)(Args...); + using ConstType = R (C::*)(Args...) const; + using RefType = R (C::*)(Args...) &; + using ConstRefType = R (C::*)(Args...) const&; + using RValRefType = R (C::*)(Args...) &&; + using ConstRValRefType = R (C::*)(Args...) const&&; + + static Type get(Type t) { + return t; + } + + static ConstType getConst(ConstType t) { + return t; + } + + static RefType getRef(RefType t) { + return t; + } + + static ConstRefType getConstRef(ConstRefType t) { + return t; + } - static type get(type t) { + static RValRefType getRValRef(RValRefType t) { return t; } - static cosntType getconst(cosntType t) { + static ConstRValRefType getConstRValRef(ConstRValRefType t) { return t; } @@ -8842,11 +8926,25 @@ namespace fakeit { } - namespace fakeit { namespace internal { + template + struct WithCommonVoid { + using type = T; + }; + + + + + + template + struct WithCommonVoid::value, void>::type> { + using type = void; + }; + + template + using WithCommonVoid_t = typename WithCommonVoid::type; } - using namespace fakeit::internal; template class Mock : public ActualInvocationsSource { @@ -8888,58 +8986,67 @@ namespace fakeit { return impl.stubDataMember(member, ctorargs...); } + template::value && std::is_base_of::value>::type> - MockingContext stub(R (T::*vMethod)(arglist...) const) { - auto methodWithoutConstVolatile = reinterpret_cast(vMethod); + std::is_base_of::value>::type> + MockingContext, arglist...> stub(R (T::*vMethod)(arglist...) const) { + auto methodWithoutConstVolatile = reinterpret_cast (T::*)(arglist...)>(vMethod); return impl.template stubMethod(methodWithoutConstVolatile); } + template::value && std::is_base_of::value>::type> - MockingContext stub(R(T::*vMethod)(arglist...) volatile) { - auto methodWithoutConstVolatile = reinterpret_cast(vMethod); + std::is_base_of::value>::type> + MockingContext, arglist...> stub(R(T::*vMethod)(arglist...) volatile) { + auto methodWithoutConstVolatile = reinterpret_cast(T::*)(arglist...)>(vMethod); return impl.template stubMethod(methodWithoutConstVolatile); } + template::value && std::is_base_of::value>::type> - MockingContext stub(R(T::*vMethod)(arglist...) const volatile) { - auto methodWithoutConstVolatile = reinterpret_cast(vMethod); + std::is_base_of::value>::type> + MockingContext, arglist...> stub(R(T::*vMethod)(arglist...) const volatile) { + auto methodWithoutConstVolatile = reinterpret_cast(T::*)(arglist...)>(vMethod); return impl.template stubMethod(methodWithoutConstVolatile); } + template::value && std::is_base_of::value>::type> - MockingContext stub(R(T::*vMethod)(arglist...)) { - return impl.template stubMethod(vMethod); + std::is_base_of::value>::type> + MockingContext, arglist...> stub(R(T::*vMethod)(arglist...)) { + auto methodWithoutConstVolatile = reinterpret_cast(T::*)(arglist...)>(vMethod); + return impl.template stubMethod(methodWithoutConstVolatile); } + template::value && std::is_base_of::value>::type> - MockingContext stub(R(T::*vMethod)(arglist...) const) { - auto methodWithoutConstVolatile = reinterpret_cast(vMethod); + std::is_base_of::value>::type> + MockingContext, arglist...> stub(R(T::*vMethod)(arglist...) &) { + auto methodWithoutConstVolatile = reinterpret_cast(T::*)(arglist...)>(vMethod); return impl.template stubMethod(methodWithoutConstVolatile); } + template::value && std::is_base_of::value>::type> - MockingContext stub(R(T::*vMethod)(arglist...) volatile) { - auto methodWithoutConstVolatile = reinterpret_cast(vMethod); + std::is_base_of::value>::type> + MockingContext, arglist...> stub(R(T::*vMethod)(arglist...) const&) { + auto methodWithoutConstVolatile = reinterpret_cast(T::*)(arglist...)>(vMethod); return impl.template stubMethod(methodWithoutConstVolatile); } + template::value && std::is_base_of::value>::type> - MockingContext stub(R(T::*vMethod)(arglist...) const volatile) { - auto methodWithoutConstVolatile = reinterpret_cast(vMethod); + std::is_base_of::value>::type> + MockingContext, arglist...> stub(R(T::*vMethod)(arglist...) &&) { + auto methodWithoutConstVolatile = reinterpret_cast(T::*)(arglist...)>(vMethod); return impl.template stubMethod(methodWithoutConstVolatile); } + template::value && std::is_base_of::value>::type> - MockingContext stub(R(T::*vMethod)(arglist...)) { - auto methodWithoutConstVolatile = reinterpret_cast(vMethod); + std::is_base_of::value>::type> + MockingContext, arglist...> stub(R(T::*vMethod)(arglist...) const&&) { + auto methodWithoutConstVolatile = reinterpret_cast(T::*)(arglist...)>(vMethod); return impl.template stubMethod(methodWithoutConstVolatile); } @@ -9975,7 +10082,19 @@ namespace fakeit { fakeit::Prototype::template MemberType::get(&MOCK_TYPE(mock)::method) #define CONST_OVERLOADED_METHOD_PTR(mock, method, prototype) \ - fakeit::Prototype::template MemberType::getconst(&MOCK_TYPE(mock)::method) + fakeit::Prototype::template MemberType::getConst(&MOCK_TYPE(mock)::method) + +#define REF_OVERLOADED_METHOD_PTR(mock, method, prototype) \ + fakeit::Prototype::MemberType::getRef(&MOCK_TYPE(mock)::method) + +#define CONST_REF_OVERLOADED_METHOD_PTR(mock, method, prototype) \ + fakeit::Prototype::MemberType::getConstRef(&MOCK_TYPE(mock)::method) + +#define R_VAL_REF_OVERLOADED_METHOD_PTR(mock, method, prototype) \ + fakeit::Prototype::MemberType::getRValRef(&MOCK_TYPE(mock)::method) + +#define CONST_R_VAL_REF_OVERLOADED_METHOD_PTR(mock, method, prototype) \ + fakeit::Prototype::MemberType::getConstRValRef(&MOCK_TYPE(mock)::method) #define Dtor(mock) \ (mock).dtor().setMethodDetails(#mock,"destructor") @@ -9989,6 +10108,18 @@ namespace fakeit { #define ConstOverloadedMethod(mock, method, prototype) \ (mock).template stub<__COUNTER__>(CONST_OVERLOADED_METHOD_PTR( mock , method, prototype )).setMethodDetails(#mock,#method) +#define RefOverloadedMethod(mock, method, prototype) \ + (mock).template stub<__COUNTER__>(REF_OVERLOADED_METHOD_PTR( mock , method, prototype )).setMethodDetails(#mock,#method) + +#define ConstRefOverloadedMethod(mock, method, prototype) \ + (mock).template stub<__COUNTER__>(CONST_REF_OVERLOADED_METHOD_PTR( mock , method, prototype )).setMethodDetails(#mock,#method) + +#define RValRefOverloadedMethod(mock, method, prototype) \ + (mock).template stub<__COUNTER__>(R_VAL_REF_OVERLOADED_METHOD_PTR( mock , method, prototype )).setMethodDetails(#mock,#method) + +#define ConstRValRefOverloadedMethod(mock, method, prototype) \ + (mock).template stub<__COUNTER__>(CONST_R_VAL_REF_OVERLOADED_METHOD_PTR( mock , method, prototype )).setMethodDetails(#mock,#method) + #define Verify(...) \ Verify( __VA_ARGS__ ).setFileInfo(__FILE__, __LINE__, __func__) @@ -10004,5 +10135,4 @@ namespace fakeit { #define When(call) \ When(call) - #endif diff --git a/single_header/standalone/fakeit.hpp b/single_header/standalone/fakeit.hpp index fad8a01e..3fbd299c 100644 --- a/single_header/standalone/fakeit.hpp +++ b/single_header/standalone/fakeit.hpp @@ -2,7 +2,7 @@ /* * FakeIt - A Simplified C++ Mocking Framework * Copyright (c) Eran Pe'er 2013 - * Generated: 2022-12-16 13:26:51.420648 + * Generated: 2023-04-17 21:28:52.363853 * Distributed under the MIT License. Please refer to the LICENSE file at: * https://github.com/eranpeer/FakeIt */ @@ -17,11 +17,23 @@ #include #include #if defined (__GNUG__) || _MSC_VER >= 1900 -#define FAKEIT_THROWS noexcept(false) -#define FAKEIT_NO_THROWS noexcept(true) +# define FAKEIT_THROWS noexcept(false) +# define FAKEIT_NO_THROWS noexcept(true) #elif defined (_MSC_VER) -#define FAKEIT_THROWS throw(...) -#define FAKEIT_NO_THROWS +# define FAKEIT_THROWS throw(...) +# define FAKEIT_NO_THROWS +#endif + +#ifdef _MSVC_LANG +# define FAKEIT_CPLUSPLUS _MSVC_LANG +#else +# define FAKEIT_CPLUSPLUS __cplusplus +#endif + +#ifdef __GNUG__ +# define FAKEIT_DISARM_UBSAN __attribute__((no_sanitize("undefined"))) +#else +# define FAKEIT_DISARM_UBSAN #endif #include #include @@ -1002,8 +1014,9 @@ namespace fakeit { #include + namespace fakeit { -#if __cplusplus >= 201703L || defined(__cpp_lib_uncaught_exceptions) +#if FAKEIT_CPLUSPLUS >= 201703L || defined(__cpp_lib_uncaught_exceptions) inline bool UncaughtException () { return std::uncaught_exceptions() >= 1; } @@ -5348,6 +5361,7 @@ namespace fakeit { #endif template + FAKEIT_DISARM_UBSAN static typename std::enable_if::value, unsigned int>::type getDestructorOffset() { VirtualOffsetSelector offsetSelctor; @@ -5910,6 +5924,32 @@ namespace fakeit } }; } +#include + +namespace fakeit { + + class Finally { + private: + std::function _finallyClause; + + Finally(const Finally &) = delete; + + Finally &operator=(const Finally &) = delete; + + public: + explicit Finally(std::function f) : + _finallyClause(f) { + } + + Finally(Finally&& other) { + _finallyClause.swap(other._finallyClause); + } + + ~Finally() { + _finallyClause(); + } + }; +} namespace fakeit { struct MethodProxy { @@ -5969,6 +6009,11 @@ namespace fakeit { return MethodProxy(id, offset, union_cast(&MethodProxyCreator::methodProxyX < id > )); } + template + MethodProxy createMethodProxyStatic(unsigned int offset) { + return MethodProxy(id, offset, union_cast(&MethodProxyCreator::methodProxyXStatic < id > )); + } + protected: R methodProxy(unsigned int id, const typename fakeit::production_arg::type... args) { @@ -5984,6 +6029,20 @@ namespace fakeit { R methodProxyX(arglist ... args) { return methodProxy(id, std::forward::type>(args)...); } + + static R methodProxyStatic(void* instance, unsigned int id, const typename fakeit::production_arg::type... args) { + InvocationHandlerCollection *invocationHandlerCollection = InvocationHandlerCollection::getInvocationHandlerCollection( + instance); + MethodInvocationHandler *invocationHandler = + (MethodInvocationHandler *) invocationHandlerCollection->getInvocatoinHandlerPtrById( + id); + return invocationHandler->handleMethodInvocation(std::forward::type>(args)...); + } + + template + static R methodProxyXStatic(void* instance, arglist ... args) { + return methodProxyStatic(instance, id, std::forward::type>(args)...); + } }; } @@ -6074,7 +6133,17 @@ namespace fakeit { void stubDtor(MethodInvocationHandler *methodInvocationHandler) { auto offset = VTUtils::getDestructorOffset(); MethodProxyCreator creator; + + + + + + +#ifdef _MSC_VER + bindDtor(creator.createMethodProxyStatic<0>(offset), methodInvocationHandler); +#else bindDtor(creator.createMethodProxy<0>(offset), methodInvocationHandler); +#endif } template @@ -6127,6 +6196,18 @@ namespace fakeit { return vt; } + template + Finally createRaiiMethodSwapper(R(C::*vMethod)(arglist...)) { + auto offset = VTUtils::getOffset(vMethod); + auto fakeMethod = getFake().getVirtualTable().getMethod(offset); + auto originalMethod = getOriginalVT().getMethod(offset); + + getFake().setMethod(offset, originalMethod); + return Finally{[&, offset, fakeMethod](){ + getFake().setMethod(offset, fakeMethod); + }}; + } + private: template @@ -7641,7 +7722,7 @@ namespace fakeit { MethodStubbingProgress &operator=(const MethodStubbingProgress &other) = delete; template -#if __cplusplus >= 201402L +#if FAKEIT_CPLUSPLUS >= 201402L auto #else std::function::type...)> @@ -7666,7 +7747,7 @@ namespace fakeit { } template -#if __cplusplus >= 201402L +#if FAKEIT_CPLUSPLUS >= 201402L auto #else std::function::type...)> @@ -7785,7 +7866,7 @@ namespace fakeit { MethodStubbingProgress &operator=(const MethodStubbingProgress &other) = delete; template -#if __cplusplus >= 201402L +#if FAKEIT_CPLUSPLUS >= 201402L auto #else std::function::type...)> @@ -7809,7 +7890,7 @@ namespace fakeit { } template -#if __cplusplus >= 201402L +#if FAKEIT_CPLUSPLUS >= 201402L auto #else std::function::type...)> @@ -7851,7 +7932,7 @@ namespace fakeit { template static void CheckPositions(const std::tuple...> arg_vals) { -#if __cplusplus >= 201402L && !defined(_WIN32) +#if FAKEIT_CPLUSPLUS >= 201402L && !defined(_WIN32) static_assert(std::get(arg_vals).pos <= max_index, "Argument index out of range"); ArgValidator::CheckPositions(arg_vals); @@ -7903,7 +7984,7 @@ namespace fakeit { struct ArgLocator { template static void AssignArg(current_arg &&p, std::tuple...> arg_vals) { -#if __cplusplus >= 201703L && !defined (_WIN32) +#if FAKEIT_CPLUSPLUS >= 201703L && !defined (_WIN32) if constexpr (std::get(arg_vals).pos == arg_index) GetArg(std::forward(p)) = std::get(arg_vals).value; #else @@ -7914,7 +7995,7 @@ namespace fakeit { ArgLocator::AssignArg(std::forward(p), arg_vals); } -#if __cplusplus < 201703L || defined (_WIN32) +#if FAKEIT_CPLUSPLUS < 201703L || defined (_WIN32) private: template static @@ -7972,28 +8053,8 @@ namespace fakeit { using placeholders::operator <=; } #include -#include - -namespace fakeit { - - class Finally { - private: - std::function _finallyClause; - - Finally(const Finally &); - Finally &operator=(const Finally &); - public: - explicit Finally(std::function f) : - _finallyClause(f) { - } - - ~Finally() { - _finallyClause(); - } - }; -} namespace fakeit { @@ -8710,11 +8771,12 @@ namespace fakeit { template::value...>::value, int>::type = 0> std::function getOriginalMethodCopyArgsInternal(int) { - void *mPtr = MethodMockingContextBase::_mock.getOriginalMethod(_vMethod); + auto mPtr = _vMethod; + auto& mock = MethodMockingContextBase::_mock; C * instance = &(MethodMockingContextBase::_mock.get()); - return [=](arglist&... args) -> R { - auto m = union_cast::type>(mPtr); - return m(instance, args...); + return [=, &mock](arglist&... args) -> R { + auto methodSwapper = mock.createRaiiMethodSwapper(mPtr); + return (instance->*mPtr)(args...); }; } @@ -8730,11 +8792,12 @@ namespace fakeit { } std::function getOriginalMethodForwardArgs() override { - void *mPtr = MethodMockingContextBase::_mock.getOriginalMethod(_vMethod); + auto mPtr = _vMethod; + auto& mock = MethodMockingContextBase::_mock; C * instance = &(MethodMockingContextBase::_mock.get()); - return [=](arglist&... args) -> R { - auto m = union_cast::type>(mPtr); - return m(instance, std::forward(args)...); + return [=, &mock](arglist&... args) -> R { + auto methodSwapper = mock.createRaiiMethodSwapper(mPtr); + return (instance->*mPtr)(std::forward(args)...); }; } }; @@ -8817,6 +8880,11 @@ namespace fakeit { return reinterpret_cast(fake); } + template + Finally createRaiiMethodSwapper(R(C::*vMethod)(arglist...)) { + return _proxy.createRaiiMethodSwapper(vMethod); + } + template void *getOriginalMethod(R (C::*vMethod)(arglist...)) { auto vt = _proxy.getOriginalVT(); @@ -8871,21 +8939,37 @@ namespace fakeit { template struct Prototype { - typedef R Type(Args...); - - typedef R ConstType(Args...) const; - template struct MemberType { - typedef Type(C::*type); - typedef ConstType(C::*cosntType); + using Type = R (C::*)(Args...); + using ConstType = R (C::*)(Args...) const; + using RefType = R (C::*)(Args...) &; + using ConstRefType = R (C::*)(Args...) const&; + using RValRefType = R (C::*)(Args...) &&; + using ConstRValRefType = R (C::*)(Args...) const&&; + + static Type get(Type t) { + return t; + } + + static ConstType getConst(ConstType t) { + return t; + } + + static RefType getRef(RefType t) { + return t; + } + + static ConstRefType getConstRef(ConstRefType t) { + return t; + } - static type get(type t) { + static RValRefType getRValRef(RValRefType t) { return t; } - static cosntType getconst(cosntType t) { + static ConstRValRefType getConstRValRef(ConstRValRefType t) { return t; } @@ -8910,11 +8994,25 @@ namespace fakeit { } - namespace fakeit { namespace internal { + template + struct WithCommonVoid { + using type = T; + }; + + + + + + template + struct WithCommonVoid::value, void>::type> { + using type = void; + }; + + template + using WithCommonVoid_t = typename WithCommonVoid::type; } - using namespace fakeit::internal; template class Mock : public ActualInvocationsSource { @@ -8956,58 +9054,67 @@ namespace fakeit { return impl.stubDataMember(member, ctorargs...); } + template::value && std::is_base_of::value>::type> - MockingContext stub(R (T::*vMethod)(arglist...) const) { - auto methodWithoutConstVolatile = reinterpret_cast(vMethod); + std::is_base_of::value>::type> + MockingContext, arglist...> stub(R (T::*vMethod)(arglist...) const) { + auto methodWithoutConstVolatile = reinterpret_cast (T::*)(arglist...)>(vMethod); return impl.template stubMethod(methodWithoutConstVolatile); } + template::value && std::is_base_of::value>::type> - MockingContext stub(R(T::*vMethod)(arglist...) volatile) { - auto methodWithoutConstVolatile = reinterpret_cast(vMethod); + std::is_base_of::value>::type> + MockingContext, arglist...> stub(R(T::*vMethod)(arglist...) volatile) { + auto methodWithoutConstVolatile = reinterpret_cast(T::*)(arglist...)>(vMethod); return impl.template stubMethod(methodWithoutConstVolatile); } + template::value && std::is_base_of::value>::type> - MockingContext stub(R(T::*vMethod)(arglist...) const volatile) { - auto methodWithoutConstVolatile = reinterpret_cast(vMethod); + std::is_base_of::value>::type> + MockingContext, arglist...> stub(R(T::*vMethod)(arglist...) const volatile) { + auto methodWithoutConstVolatile = reinterpret_cast(T::*)(arglist...)>(vMethod); return impl.template stubMethod(methodWithoutConstVolatile); } + template::value && std::is_base_of::value>::type> - MockingContext stub(R(T::*vMethod)(arglist...)) { - return impl.template stubMethod(vMethod); + std::is_base_of::value>::type> + MockingContext, arglist...> stub(R(T::*vMethod)(arglist...)) { + auto methodWithoutConstVolatile = reinterpret_cast(T::*)(arglist...)>(vMethod); + return impl.template stubMethod(methodWithoutConstVolatile); } + template::value && std::is_base_of::value>::type> - MockingContext stub(R(T::*vMethod)(arglist...) const) { - auto methodWithoutConstVolatile = reinterpret_cast(vMethod); + std::is_base_of::value>::type> + MockingContext, arglist...> stub(R(T::*vMethod)(arglist...) &) { + auto methodWithoutConstVolatile = reinterpret_cast(T::*)(arglist...)>(vMethod); return impl.template stubMethod(methodWithoutConstVolatile); } + template::value && std::is_base_of::value>::type> - MockingContext stub(R(T::*vMethod)(arglist...) volatile) { - auto methodWithoutConstVolatile = reinterpret_cast(vMethod); + std::is_base_of::value>::type> + MockingContext, arglist...> stub(R(T::*vMethod)(arglist...) const&) { + auto methodWithoutConstVolatile = reinterpret_cast(T::*)(arglist...)>(vMethod); return impl.template stubMethod(methodWithoutConstVolatile); } + template::value && std::is_base_of::value>::type> - MockingContext stub(R(T::*vMethod)(arglist...) const volatile) { - auto methodWithoutConstVolatile = reinterpret_cast(vMethod); + std::is_base_of::value>::type> + MockingContext, arglist...> stub(R(T::*vMethod)(arglist...) &&) { + auto methodWithoutConstVolatile = reinterpret_cast(T::*)(arglist...)>(vMethod); return impl.template stubMethod(methodWithoutConstVolatile); } + template::value && std::is_base_of::value>::type> - MockingContext stub(R(T::*vMethod)(arglist...)) { - auto methodWithoutConstVolatile = reinterpret_cast(vMethod); + std::is_base_of::value>::type> + MockingContext, arglist...> stub(R(T::*vMethod)(arglist...) const&&) { + auto methodWithoutConstVolatile = reinterpret_cast(T::*)(arglist...)>(vMethod); return impl.template stubMethod(methodWithoutConstVolatile); } @@ -10029,7 +10136,19 @@ namespace fakeit { fakeit::Prototype::template MemberType::get(&MOCK_TYPE(mock)::method) #define CONST_OVERLOADED_METHOD_PTR(mock, method, prototype) \ - fakeit::Prototype::template MemberType::getconst(&MOCK_TYPE(mock)::method) + fakeit::Prototype::template MemberType::getConst(&MOCK_TYPE(mock)::method) + +#define REF_OVERLOADED_METHOD_PTR(mock, method, prototype) \ + fakeit::Prototype::MemberType::getRef(&MOCK_TYPE(mock)::method) + +#define CONST_REF_OVERLOADED_METHOD_PTR(mock, method, prototype) \ + fakeit::Prototype::MemberType::getConstRef(&MOCK_TYPE(mock)::method) + +#define R_VAL_REF_OVERLOADED_METHOD_PTR(mock, method, prototype) \ + fakeit::Prototype::MemberType::getRValRef(&MOCK_TYPE(mock)::method) + +#define CONST_R_VAL_REF_OVERLOADED_METHOD_PTR(mock, method, prototype) \ + fakeit::Prototype::MemberType::getConstRValRef(&MOCK_TYPE(mock)::method) #define Dtor(mock) \ (mock).dtor().setMethodDetails(#mock,"destructor") @@ -10043,6 +10162,18 @@ namespace fakeit { #define ConstOverloadedMethod(mock, method, prototype) \ (mock).template stub<__COUNTER__>(CONST_OVERLOADED_METHOD_PTR( mock , method, prototype )).setMethodDetails(#mock,#method) +#define RefOverloadedMethod(mock, method, prototype) \ + (mock).template stub<__COUNTER__>(REF_OVERLOADED_METHOD_PTR( mock , method, prototype )).setMethodDetails(#mock,#method) + +#define ConstRefOverloadedMethod(mock, method, prototype) \ + (mock).template stub<__COUNTER__>(CONST_REF_OVERLOADED_METHOD_PTR( mock , method, prototype )).setMethodDetails(#mock,#method) + +#define RValRefOverloadedMethod(mock, method, prototype) \ + (mock).template stub<__COUNTER__>(R_VAL_REF_OVERLOADED_METHOD_PTR( mock , method, prototype )).setMethodDetails(#mock,#method) + +#define ConstRValRefOverloadedMethod(mock, method, prototype) \ + (mock).template stub<__COUNTER__>(CONST_R_VAL_REF_OVERLOADED_METHOD_PTR( mock , method, prototype )).setMethodDetails(#mock,#method) + #define Verify(...) \ Verify( __VA_ARGS__ ).setFileInfo(__FILE__, __LINE__, __func__) @@ -10057,4 +10188,3 @@ namespace fakeit { #define When(call) \ When(call) - diff --git a/single_header/tpunit/fakeit.hpp b/single_header/tpunit/fakeit.hpp index 0a2c19b0..efdc1792 100644 --- a/single_header/tpunit/fakeit.hpp +++ b/single_header/tpunit/fakeit.hpp @@ -2,7 +2,7 @@ /* * FakeIt - A Simplified C++ Mocking Framework * Copyright (c) Eran Pe'er 2013 - * Generated: 2022-12-16 13:26:51.715139 + * Generated: 2023-04-17 21:28:52.630973 * Distributed under the MIT License. Please refer to the LICENSE file at: * https://github.com/eranpeer/FakeIt */ @@ -18,11 +18,23 @@ #include #include #if defined (__GNUG__) || _MSC_VER >= 1900 -#define FAKEIT_THROWS noexcept(false) -#define FAKEIT_NO_THROWS noexcept(true) +# define FAKEIT_THROWS noexcept(false) +# define FAKEIT_NO_THROWS noexcept(true) #elif defined (_MSC_VER) -#define FAKEIT_THROWS throw(...) -#define FAKEIT_NO_THROWS +# define FAKEIT_THROWS throw(...) +# define FAKEIT_NO_THROWS +#endif + +#ifdef _MSVC_LANG +# define FAKEIT_CPLUSPLUS _MSVC_LANG +#else +# define FAKEIT_CPLUSPLUS __cplusplus +#endif + +#ifdef __GNUG__ +# define FAKEIT_DISARM_UBSAN __attribute__((no_sanitize("undefined"))) +#else +# define FAKEIT_DISARM_UBSAN #endif #include #include @@ -1003,8 +1015,9 @@ namespace fakeit { #include + namespace fakeit { -#if __cplusplus >= 201703L || defined(__cpp_lib_uncaught_exceptions) +#if FAKEIT_CPLUSPLUS >= 201703L || defined(__cpp_lib_uncaught_exceptions) inline bool UncaughtException () { return std::uncaught_exceptions() >= 1; } @@ -1135,11 +1148,23 @@ namespace fakeit { }; } #if defined (__GNUG__) || _MSC_VER >= 1900 -#define FAKEIT_THROWS noexcept(false) -#define FAKEIT_NO_THROWS noexcept(true) +# define FAKEIT_THROWS noexcept(false) +# define FAKEIT_NO_THROWS noexcept(true) #elif defined (_MSC_VER) -#define FAKEIT_THROWS throw(...) -#define FAKEIT_NO_THROWS +# define FAKEIT_THROWS throw(...) +# define FAKEIT_NO_THROWS +#endif + +#ifdef _MSVC_LANG +# define FAKEIT_CPLUSPLUS _MSVC_LANG +#else +# define FAKEIT_CPLUSPLUS __cplusplus +#endif + +#ifdef __GNUG__ +# define FAKEIT_DISARM_UBSAN __attribute__((no_sanitize("undefined"))) +#else +# define FAKEIT_DISARM_UBSAN #endif #include #include @@ -5319,6 +5344,7 @@ namespace fakeit { #endif template + FAKEIT_DISARM_UBSAN static typename std::enable_if::value, unsigned int>::type getDestructorOffset() { VirtualOffsetSelector offsetSelctor; @@ -5881,6 +5907,32 @@ namespace fakeit } }; } +#include + +namespace fakeit { + + class Finally { + private: + std::function _finallyClause; + + Finally(const Finally &) = delete; + + Finally &operator=(const Finally &) = delete; + + public: + explicit Finally(std::function f) : + _finallyClause(f) { + } + + Finally(Finally&& other) { + _finallyClause.swap(other._finallyClause); + } + + ~Finally() { + _finallyClause(); + } + }; +} namespace fakeit { struct MethodProxy { @@ -5940,6 +5992,11 @@ namespace fakeit { return MethodProxy(id, offset, union_cast(&MethodProxyCreator::methodProxyX < id > )); } + template + MethodProxy createMethodProxyStatic(unsigned int offset) { + return MethodProxy(id, offset, union_cast(&MethodProxyCreator::methodProxyXStatic < id > )); + } + protected: R methodProxy(unsigned int id, const typename fakeit::production_arg::type... args) { @@ -5955,6 +6012,20 @@ namespace fakeit { R methodProxyX(arglist ... args) { return methodProxy(id, std::forward::type>(args)...); } + + static R methodProxyStatic(void* instance, unsigned int id, const typename fakeit::production_arg::type... args) { + InvocationHandlerCollection *invocationHandlerCollection = InvocationHandlerCollection::getInvocationHandlerCollection( + instance); + MethodInvocationHandler *invocationHandler = + (MethodInvocationHandler *) invocationHandlerCollection->getInvocatoinHandlerPtrById( + id); + return invocationHandler->handleMethodInvocation(std::forward::type>(args)...); + } + + template + static R methodProxyXStatic(void* instance, arglist ... args) { + return methodProxyStatic(instance, id, std::forward::type>(args)...); + } }; } @@ -6045,7 +6116,17 @@ namespace fakeit { void stubDtor(MethodInvocationHandler *methodInvocationHandler) { auto offset = VTUtils::getDestructorOffset(); MethodProxyCreator creator; + + + + + + +#ifdef _MSC_VER + bindDtor(creator.createMethodProxyStatic<0>(offset), methodInvocationHandler); +#else bindDtor(creator.createMethodProxy<0>(offset), methodInvocationHandler); +#endif } template @@ -6098,6 +6179,18 @@ namespace fakeit { return vt; } + template + Finally createRaiiMethodSwapper(R(C::*vMethod)(arglist...)) { + auto offset = VTUtils::getOffset(vMethod); + auto fakeMethod = getFake().getVirtualTable().getMethod(offset); + auto originalMethod = getOriginalVT().getMethod(offset); + + getFake().setMethod(offset, originalMethod); + return Finally{[&, offset, fakeMethod](){ + getFake().setMethod(offset, fakeMethod); + }}; + } + private: template @@ -7612,7 +7705,7 @@ namespace fakeit { MethodStubbingProgress &operator=(const MethodStubbingProgress &other) = delete; template -#if __cplusplus >= 201402L +#if FAKEIT_CPLUSPLUS >= 201402L auto #else std::function::type...)> @@ -7637,7 +7730,7 @@ namespace fakeit { } template -#if __cplusplus >= 201402L +#if FAKEIT_CPLUSPLUS >= 201402L auto #else std::function::type...)> @@ -7756,7 +7849,7 @@ namespace fakeit { MethodStubbingProgress &operator=(const MethodStubbingProgress &other) = delete; template -#if __cplusplus >= 201402L +#if FAKEIT_CPLUSPLUS >= 201402L auto #else std::function::type...)> @@ -7780,7 +7873,7 @@ namespace fakeit { } template -#if __cplusplus >= 201402L +#if FAKEIT_CPLUSPLUS >= 201402L auto #else std::function::type...)> @@ -7822,7 +7915,7 @@ namespace fakeit { template static void CheckPositions(const std::tuple...> arg_vals) { -#if __cplusplus >= 201402L && !defined(_WIN32) +#if FAKEIT_CPLUSPLUS >= 201402L && !defined(_WIN32) static_assert(std::get(arg_vals).pos <= max_index, "Argument index out of range"); ArgValidator::CheckPositions(arg_vals); @@ -7874,7 +7967,7 @@ namespace fakeit { struct ArgLocator { template static void AssignArg(current_arg &&p, std::tuple...> arg_vals) { -#if __cplusplus >= 201703L && !defined (_WIN32) +#if FAKEIT_CPLUSPLUS >= 201703L && !defined (_WIN32) if constexpr (std::get(arg_vals).pos == arg_index) GetArg(std::forward(p)) = std::get(arg_vals).value; #else @@ -7885,7 +7978,7 @@ namespace fakeit { ArgLocator::AssignArg(std::forward(p), arg_vals); } -#if __cplusplus < 201703L || defined (_WIN32) +#if FAKEIT_CPLUSPLUS < 201703L || defined (_WIN32) private: template static @@ -7943,28 +8036,8 @@ namespace fakeit { using placeholders::operator <=; } #include -#include -namespace fakeit { - - class Finally { - private: - std::function _finallyClause; - - Finally(const Finally &); - Finally &operator=(const Finally &); - - public: - explicit Finally(std::function f) : - _finallyClause(f) { - } - - ~Finally() { - _finallyClause(); - } - }; -} namespace fakeit { @@ -8681,11 +8754,12 @@ namespace fakeit { template::value...>::value, int>::type = 0> std::function getOriginalMethodCopyArgsInternal(int) { - void *mPtr = MethodMockingContextBase::_mock.getOriginalMethod(_vMethod); + auto mPtr = _vMethod; + auto& mock = MethodMockingContextBase::_mock; C * instance = &(MethodMockingContextBase::_mock.get()); - return [=](arglist&... args) -> R { - auto m = union_cast::type>(mPtr); - return m(instance, args...); + return [=, &mock](arglist&... args) -> R { + auto methodSwapper = mock.createRaiiMethodSwapper(mPtr); + return (instance->*mPtr)(args...); }; } @@ -8701,11 +8775,12 @@ namespace fakeit { } std::function getOriginalMethodForwardArgs() override { - void *mPtr = MethodMockingContextBase::_mock.getOriginalMethod(_vMethod); + auto mPtr = _vMethod; + auto& mock = MethodMockingContextBase::_mock; C * instance = &(MethodMockingContextBase::_mock.get()); - return [=](arglist&... args) -> R { - auto m = union_cast::type>(mPtr); - return m(instance, std::forward(args)...); + return [=, &mock](arglist&... args) -> R { + auto methodSwapper = mock.createRaiiMethodSwapper(mPtr); + return (instance->*mPtr)(std::forward(args)...); }; } }; @@ -8788,6 +8863,11 @@ namespace fakeit { return reinterpret_cast(fake); } + template + Finally createRaiiMethodSwapper(R(C::*vMethod)(arglist...)) { + return _proxy.createRaiiMethodSwapper(vMethod); + } + template void *getOriginalMethod(R (C::*vMethod)(arglist...)) { auto vt = _proxy.getOriginalVT(); @@ -8842,21 +8922,37 @@ namespace fakeit { template struct Prototype { - typedef R Type(Args...); - - typedef R ConstType(Args...) const; - template struct MemberType { - typedef Type(C::*type); - typedef ConstType(C::*cosntType); + using Type = R (C::*)(Args...); + using ConstType = R (C::*)(Args...) const; + using RefType = R (C::*)(Args...) &; + using ConstRefType = R (C::*)(Args...) const&; + using RValRefType = R (C::*)(Args...) &&; + using ConstRValRefType = R (C::*)(Args...) const&&; + + static Type get(Type t) { + return t; + } + + static ConstType getConst(ConstType t) { + return t; + } + + static RefType getRef(RefType t) { + return t; + } - static type get(type t) { + static ConstRefType getConstRef(ConstRefType t) { return t; } - static cosntType getconst(cosntType t) { + static RValRefType getRValRef(RValRefType t) { + return t; + } + + static ConstRValRefType getConstRValRef(ConstRValRefType t) { return t; } @@ -8881,11 +8977,25 @@ namespace fakeit { } - namespace fakeit { namespace internal { + template + struct WithCommonVoid { + using type = T; + }; + + + + + + template + struct WithCommonVoid::value, void>::type> { + using type = void; + }; + + template + using WithCommonVoid_t = typename WithCommonVoid::type; } - using namespace fakeit::internal; template class Mock : public ActualInvocationsSource { @@ -8927,58 +9037,67 @@ namespace fakeit { return impl.stubDataMember(member, ctorargs...); } + template::value && std::is_base_of::value>::type> - MockingContext stub(R (T::*vMethod)(arglist...) const) { - auto methodWithoutConstVolatile = reinterpret_cast(vMethod); + std::is_base_of::value>::type> + MockingContext, arglist...> stub(R (T::*vMethod)(arglist...) const) { + auto methodWithoutConstVolatile = reinterpret_cast (T::*)(arglist...)>(vMethod); return impl.template stubMethod(methodWithoutConstVolatile); } + template::value && std::is_base_of::value>::type> - MockingContext stub(R(T::*vMethod)(arglist...) volatile) { - auto methodWithoutConstVolatile = reinterpret_cast(vMethod); + std::is_base_of::value>::type> + MockingContext, arglist...> stub(R(T::*vMethod)(arglist...) volatile) { + auto methodWithoutConstVolatile = reinterpret_cast(T::*)(arglist...)>(vMethod); return impl.template stubMethod(methodWithoutConstVolatile); } + template::value && std::is_base_of::value>::type> - MockingContext stub(R(T::*vMethod)(arglist...) const volatile) { - auto methodWithoutConstVolatile = reinterpret_cast(vMethod); + std::is_base_of::value>::type> + MockingContext, arglist...> stub(R(T::*vMethod)(arglist...) const volatile) { + auto methodWithoutConstVolatile = reinterpret_cast(T::*)(arglist...)>(vMethod); return impl.template stubMethod(methodWithoutConstVolatile); } + template::value && std::is_base_of::value>::type> - MockingContext stub(R(T::*vMethod)(arglist...)) { - return impl.template stubMethod(vMethod); + std::is_base_of::value>::type> + MockingContext, arglist...> stub(R(T::*vMethod)(arglist...)) { + auto methodWithoutConstVolatile = reinterpret_cast(T::*)(arglist...)>(vMethod); + return impl.template stubMethod(methodWithoutConstVolatile); } + template::value && std::is_base_of::value>::type> - MockingContext stub(R(T::*vMethod)(arglist...) const) { - auto methodWithoutConstVolatile = reinterpret_cast(vMethod); + std::is_base_of::value>::type> + MockingContext, arglist...> stub(R(T::*vMethod)(arglist...) &) { + auto methodWithoutConstVolatile = reinterpret_cast(T::*)(arglist...)>(vMethod); return impl.template stubMethod(methodWithoutConstVolatile); } + template::value && std::is_base_of::value>::type> - MockingContext stub(R(T::*vMethod)(arglist...) volatile) { - auto methodWithoutConstVolatile = reinterpret_cast(vMethod); + std::is_base_of::value>::type> + MockingContext, arglist...> stub(R(T::*vMethod)(arglist...) const&) { + auto methodWithoutConstVolatile = reinterpret_cast(T::*)(arglist...)>(vMethod); return impl.template stubMethod(methodWithoutConstVolatile); } + template::value && std::is_base_of::value>::type> - MockingContext stub(R(T::*vMethod)(arglist...) const volatile) { - auto methodWithoutConstVolatile = reinterpret_cast(vMethod); + std::is_base_of::value>::type> + MockingContext, arglist...> stub(R(T::*vMethod)(arglist...) &&) { + auto methodWithoutConstVolatile = reinterpret_cast(T::*)(arglist...)>(vMethod); return impl.template stubMethod(methodWithoutConstVolatile); } + template::value && std::is_base_of::value>::type> - MockingContext stub(R(T::*vMethod)(arglist...)) { - auto methodWithoutConstVolatile = reinterpret_cast(vMethod); + std::is_base_of::value>::type> + MockingContext, arglist...> stub(R(T::*vMethod)(arglist...) const&&) { + auto methodWithoutConstVolatile = reinterpret_cast(T::*)(arglist...)>(vMethod); return impl.template stubMethod(methodWithoutConstVolatile); } @@ -10000,7 +10119,19 @@ namespace fakeit { fakeit::Prototype::template MemberType::get(&MOCK_TYPE(mock)::method) #define CONST_OVERLOADED_METHOD_PTR(mock, method, prototype) \ - fakeit::Prototype::template MemberType::getconst(&MOCK_TYPE(mock)::method) + fakeit::Prototype::template MemberType::getConst(&MOCK_TYPE(mock)::method) + +#define REF_OVERLOADED_METHOD_PTR(mock, method, prototype) \ + fakeit::Prototype::MemberType::getRef(&MOCK_TYPE(mock)::method) + +#define CONST_REF_OVERLOADED_METHOD_PTR(mock, method, prototype) \ + fakeit::Prototype::MemberType::getConstRef(&MOCK_TYPE(mock)::method) + +#define R_VAL_REF_OVERLOADED_METHOD_PTR(mock, method, prototype) \ + fakeit::Prototype::MemberType::getRValRef(&MOCK_TYPE(mock)::method) + +#define CONST_R_VAL_REF_OVERLOADED_METHOD_PTR(mock, method, prototype) \ + fakeit::Prototype::MemberType::getConstRValRef(&MOCK_TYPE(mock)::method) #define Dtor(mock) \ (mock).dtor().setMethodDetails(#mock,"destructor") @@ -10014,6 +10145,18 @@ namespace fakeit { #define ConstOverloadedMethod(mock, method, prototype) \ (mock).template stub<__COUNTER__>(CONST_OVERLOADED_METHOD_PTR( mock , method, prototype )).setMethodDetails(#mock,#method) +#define RefOverloadedMethod(mock, method, prototype) \ + (mock).template stub<__COUNTER__>(REF_OVERLOADED_METHOD_PTR( mock , method, prototype )).setMethodDetails(#mock,#method) + +#define ConstRefOverloadedMethod(mock, method, prototype) \ + (mock).template stub<__COUNTER__>(CONST_REF_OVERLOADED_METHOD_PTR( mock , method, prototype )).setMethodDetails(#mock,#method) + +#define RValRefOverloadedMethod(mock, method, prototype) \ + (mock).template stub<__COUNTER__>(R_VAL_REF_OVERLOADED_METHOD_PTR( mock , method, prototype )).setMethodDetails(#mock,#method) + +#define ConstRValRefOverloadedMethod(mock, method, prototype) \ + (mock).template stub<__COUNTER__>(CONST_R_VAL_REF_OVERLOADED_METHOD_PTR( mock , method, prototype )).setMethodDetails(#mock,#method) + #define Verify(...) \ Verify( __VA_ARGS__ ).setFileInfo(__FILE__, __LINE__, __func__) @@ -10029,5 +10172,4 @@ namespace fakeit { #define When(call) \ When(call) - #endif From 6226383c62712a9c1fef103a1d4cd98315bea09a Mon Sep 17 00:00:00 2001 From: Franck W Date: Mon, 17 Apr 2023 21:39:19 +0200 Subject: [PATCH 20/20] Updated actions/checkout in CI to v3. --- .github/workflows/ci_linux_clang.yml | 2 +- .github/workflows/ci_linux_gcc.yml | 2 +- .github/workflows/ci_windows_msvc.yml | 2 +- .github/workflows/coverage.yml | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/ci_linux_clang.yml b/.github/workflows/ci_linux_clang.yml index 414220e8..2f9298ec 100644 --- a/.github/workflows/ci_linux_clang.yml +++ b/.github/workflows/ci_linux_clang.yml @@ -76,7 +76,7 @@ jobs: enable_sanitizers_in_tests: ON } steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - name: Build project env: CC: ${{ matrix.config.cc }} diff --git a/.github/workflows/ci_linux_gcc.yml b/.github/workflows/ci_linux_gcc.yml index 1445cbad..d772e7d5 100644 --- a/.github/workflows/ci_linux_gcc.yml +++ b/.github/workflows/ci_linux_gcc.yml @@ -70,7 +70,7 @@ jobs: enable_sanitizers_in_tests: ON } steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - name: Build project env: CC: ${{ matrix.config.cc }} diff --git a/.github/workflows/ci_windows_msvc.yml b/.github/workflows/ci_windows_msvc.yml index bdc1d56b..4cfcf8cd 100644 --- a/.github/workflows/ci_windows_msvc.yml +++ b/.github/workflows/ci_windows_msvc.yml @@ -56,7 +56,7 @@ jobs: cxx_standard: 20 } steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - name: Build project run: | cmake -S . -B build \ diff --git a/.github/workflows/coverage.yml b/.github/workflows/coverage.yml index c18103a7..f6767ebe 100644 --- a/.github/workflows/coverage.yml +++ b/.github/workflows/coverage.yml @@ -14,7 +14,7 @@ jobs: steps: - name: Install LCOV run: sudo apt install -y lcov - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - name: Build project env: CC: gcc-9