From 5693a7452f6ef8172266afe9a5d54d2e8ee1dcb1 Mon Sep 17 00:00:00 2001 From: otrempe Date: Wed, 9 Nov 2022 13:00:40 -0500 Subject: [PATCH 1/7] Added a test showing up the problem --- tests/all_tests.vcxproj | 3 +++ tests/multiple_translation_units_stub.cpp | 12 ++++++++++ tests/multiple_translation_units_stub.h | 13 ++++++++++ .../multiple_translation_units_stub_test.cpp | 24 +++++++++++++++++++ 4 files changed, 52 insertions(+) create mode 100644 tests/multiple_translation_units_stub.cpp create mode 100644 tests/multiple_translation_units_stub.h create mode 100644 tests/multiple_translation_units_stub_test.cpp diff --git a/tests/all_tests.vcxproj b/tests/all_tests.vcxproj index 52a71b7b..3e0e0df4 100644 --- a/tests/all_tests.vcxproj +++ b/tests/all_tests.vcxproj @@ -135,6 +135,8 @@ + + @@ -151,6 +153,7 @@ + diff --git a/tests/multiple_translation_units_stub.cpp b/tests/multiple_translation_units_stub.cpp new file mode 100644 index 00000000..6f2dc0bb --- /dev/null +++ b/tests/multiple_translation_units_stub.cpp @@ -0,0 +1,12 @@ +#include "multiple_translation_units_stub.h" + + +void stubFunc2(fakeit::Mock& mock) +{ + fakeit::When(Method(mock, func2)).AlwaysReturn("String"); +} + +void stubFunc(fakeit::Mock& mock) +{ + fakeit::When(Method(mock, func)).AlwaysReturn(3); +} diff --git a/tests/multiple_translation_units_stub.h b/tests/multiple_translation_units_stub.h new file mode 100644 index 00000000..084cf17b --- /dev/null +++ b/tests/multiple_translation_units_stub.h @@ -0,0 +1,13 @@ +#pragma once + +#include + +#include "fakeit.hpp" + +struct SomeInterface { + virtual int func() = 0; + virtual std::string func2() = 0; +}; + +void stubFunc2(fakeit::Mock& mock); +void stubFunc(fakeit::Mock& mock); diff --git a/tests/multiple_translation_units_stub_test.cpp b/tests/multiple_translation_units_stub_test.cpp new file mode 100644 index 00000000..75cf43f4 --- /dev/null +++ b/tests/multiple_translation_units_stub_test.cpp @@ -0,0 +1,24 @@ +#include "tpunit++.hpp" +#include "fakeit.hpp" +#include "multiple_translation_units_stub.h" + +using namespace fakeit; + +struct MultipleTranslationUnitsStub : tpunit::TestFixture { + MultipleTranslationUnitsStub() + : tpunit::TestFixture( + TEST(MultipleTranslationUnitsStub::NoCollidingIds) + ) + {} + + void NoCollidingIds() { + Mock mock; + SomeInterface &i = mock.get(); + + stubFunc2(mock); + When(Method(mock, func)).Return(1); + + mock.get().func2(); // Uncatchable write access violation if ids collide + } + +} __MultipleTranslationUnitsStub; From e34f820cbad8084f1079f84925193dc56b7d9b6c Mon Sep 17 00:00:00 2001 From: otrempe Date: Wed, 9 Nov 2022 09:05:15 -0500 Subject: [PATCH 2/7] Unique MockingContext ids across translation units --- include/fakeit/Mock.hpp | 16 ++++++++-------- include/fakeit/MockImpl.hpp | 6 +++--- include/fakeit/api_macros.hpp | 16 +++++++++++++--- include/mockutils/DynamicProxy.hpp | 14 +++++++------- include/mockutils/MethodProxy.hpp | 6 +++--- include/mockutils/MethodProxyCreator.hpp | 8 ++++---- include/mockutils/VTUtils.hpp | 2 +- include/mockutils/constexpr_hash.hpp | 21 +++++++++++++++++++++ include/mockutils/mscpp/VirtualTable.hpp | 6 +++--- tests/FakeIt.vcxproj | 1 + 10 files changed, 64 insertions(+), 32 deletions(-) create mode 100644 include/mockutils/constexpr_hash.hpp diff --git a/include/fakeit/Mock.hpp b/include/fakeit/Mock.hpp index 30821951..9d94308c 100644 --- a/include/fakeit/Mock.hpp +++ b/include/fakeit/Mock.hpp @@ -57,55 +57,55 @@ 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); 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); 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); return impl.template stubMethod(methodWithoutConstVolatile); } - template::value && std::is_base_of::value>::type> MockingContext stub(R(T::*vMethod)(arglist...)) { return impl.template stubMethod(vMethod); } - 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...) volatile) { 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 volatile) { auto methodWithoutConstVolatile = reinterpret_cast(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); diff --git a/include/fakeit/MockImpl.hpp b/include/fakeit/MockImpl.hpp index 2b8b63a2..bca8c53b 100644 --- a/include/fakeit/MockImpl.hpp +++ b/include/fakeit/MockImpl.hpp @@ -89,7 +89,7 @@ namespace fakeit { return DataMemberStubbingRoot(); } - template::value>::type> + template::value>::type> MockingContext stubMethod(R(T::*vMethod)(arglist...)) { return MockingContext(new UniqueMethodMockingContextImpl < id, R, arglist... > (*this, vMethod)); @@ -212,7 +212,7 @@ namespace fakeit { }; - template + template class UniqueMethodMockingContextImpl : public MethodMockingContextImpl { protected: @@ -304,7 +304,7 @@ namespace fakeit { return origMethodPtr; } - template + template RecordedMethodBody &stubMethodIfNotStubbed(DynamicProxy &proxy, R (C::*vMethod)(arglist...)) { if (!proxy.isMethodStubbed(vMethod)) { diff --git a/include/fakeit/api_macros.hpp b/include/fakeit/api_macros.hpp index 966b47af..e28d6c76 100644 --- a/include/fakeit/api_macros.hpp +++ b/include/fakeit/api_macros.hpp @@ -1,9 +1,19 @@ #pragma once +#include "mockutils/constexpr_hash.hpp" + #ifdef _MSC_VER #define __func__ __FUNCTION__ #endif +#define COUNTER_STRINGIFY( counter ) #counter + +#define STUB_ID_STR( counter ) \ + __FILE__ COUNTER_STRINGIFY(counter) + +#define STUB_ID(counter) \ + fakeit::constExprHash(STUB_ID_STR(counter)) + #define MOCK_TYPE(mock) \ std::remove_reference::type @@ -17,13 +27,13 @@ (mock).dtor().setMethodDetails(#mock,"destructor") #define Method(mock, method) \ - (mock).template stub<__COUNTER__>(&MOCK_TYPE(mock)::method).setMethodDetails(#mock,#method) + (mock).template stub(&MOCK_TYPE(mock)::method).setMethodDetails(#mock,#method) #define OverloadedMethod(mock, method, prototype) \ - (mock).template stub<__COUNTER__>(OVERLOADED_METHOD_PTR( mock , method, prototype )).setMethodDetails(#mock,#method) + (mock).template stub(OVERLOADED_METHOD_PTR( mock , method, prototype )).setMethodDetails(#mock,#method) #define ConstOverloadedMethod(mock, method, prototype) \ - (mock).template stub<__COUNTER__>(CONST_OVERLOADED_METHOD_PTR( mock , method, prototype )).setMethodDetails(#mock,#method) + (mock).template stub(CONST_OVERLOADED_METHOD_PTR( mock , method, prototype )).setMethodDetails(#mock,#method) #define Verify(...) \ Verify( __VA_ARGS__ ).setFileInfo(__FILE__, __LINE__, __func__) diff --git a/include/mockutils/DynamicProxy.hpp b/include/mockutils/DynamicProxy.hpp index f1f62844..d0e71a26 100644 --- a/include/mockutils/DynamicProxy.hpp +++ b/include/mockutils/DynamicProxy.hpp @@ -27,9 +27,9 @@ namespace fakeit { class InvocationHandlers : public InvocationHandlerCollection { std::vector> &_methodMocks; - std::vector &_offsets; + std::vector &_offsets; - unsigned int getOffset(unsigned int id) const + unsigned int getOffset(size_t id) const { unsigned int offset = 0; for (; offset < _offsets.size(); offset++) { @@ -43,15 +43,15 @@ namespace fakeit { public: InvocationHandlers( std::vector> &methodMocks, - std::vector &offsets) : + std::vector &offsets) : _methodMocks(methodMocks), _offsets(offsets) { - for (std::vector::iterator it = _offsets.begin(); it != _offsets.end(); ++it) + for (auto it = _offsets.begin(); it != _offsets.end(); ++it) { *it = std::numeric_limits::max(); } } - Destructible *getInvocatoinHandlerPtrById(unsigned int id) override { + Destructible *getInvocatoinHandlerPtrById(size_t id) override { unsigned int offset = getOffset(id); std::shared_ptr ptr = _methodMocks[offset]; return ptr.get(); @@ -100,7 +100,7 @@ namespace fakeit { { } - template + template void stubMethod(R(C::*vMethod)(arglist...), MethodInvocationHandler *methodInvocationHandler) { auto offset = VTUtils::getOffset(vMethod); MethodProxyCreator creator; @@ -189,7 +189,7 @@ namespace fakeit { // std::vector> _methodMocks; std::vector> _members; - std::vector _offsets; + std::vector _offsets; InvocationHandlers _invocationHandlers; FakeObject &getFake() { diff --git a/include/mockutils/MethodProxy.hpp b/include/mockutils/MethodProxy.hpp index b9945c65..66ee39d6 100644 --- a/include/mockutils/MethodProxy.hpp +++ b/include/mockutils/MethodProxy.hpp @@ -6,7 +6,7 @@ namespace fakeit { struct MethodProxy { - MethodProxy(unsigned int id, unsigned int offset, void *vMethod) : + MethodProxy(size_t id, unsigned int offset, void *vMethod) : _id(id), _offset(offset), _vMethod(vMethod) { @@ -16,7 +16,7 @@ namespace fakeit { return _offset; } - unsigned int getId() const { + size_t getId() const { return _id; } @@ -25,7 +25,7 @@ namespace fakeit { } private: - unsigned int _id; + size_t _id; unsigned int _offset; void *_vMethod; }; diff --git a/include/mockutils/MethodProxyCreator.hpp b/include/mockutils/MethodProxyCreator.hpp index 4ae0dfe5..739d9865 100644 --- a/include/mockutils/MethodProxyCreator.hpp +++ b/include/mockutils/MethodProxyCreator.hpp @@ -11,7 +11,7 @@ namespace fakeit { struct InvocationHandlerCollection { static const unsigned int VT_COOKIE_INDEX = 0; - virtual Destructible *getInvocatoinHandlerPtrById(unsigned int index) = 0; + virtual Destructible *getInvocatoinHandlerPtrById(size_t index) = 0; static InvocationHandlerCollection *getInvocationHandlerCollection(void *instance) { VirtualTableBase &vt = VirtualTableBase::getVTable(instance); @@ -29,14 +29,14 @@ namespace fakeit { public: - template + template MethodProxy createMethodProxy(unsigned int offset) { return MethodProxy(id, offset, union_cast(&MethodProxyCreator::methodProxyX < id > )); } protected: - R methodProxy(unsigned int id, const typename fakeit::production_arg::type... args) { + R methodProxy(size_t id, const typename fakeit::production_arg::type... args) { InvocationHandlerCollection *invocationHandlerCollection = InvocationHandlerCollection::getInvocationHandlerCollection( this); MethodInvocationHandler *invocationHandler = @@ -45,7 +45,7 @@ namespace fakeit { return invocationHandler->handleMethodInvocation(std::forward::type>(args)...); } - template + template R methodProxyX(arglist ... args) { return methodProxy(id, std::forward::type>(args)...); } diff --git a/include/mockutils/VTUtils.hpp b/include/mockutils/VTUtils.hpp index 109fcdac..d85ba07f 100644 --- a/include/mockutils/VTUtils.hpp +++ b/include/mockutils/VTUtils.hpp @@ -63,7 +63,7 @@ namespace fakeit { } template - static unsigned int getVTSize() { + static size_t getVTSize() { struct Derrived : public C { virtual void endOfVt() { } diff --git a/include/mockutils/constexpr_hash.hpp b/include/mockutils/constexpr_hash.hpp new file mode 100644 index 00000000..c504afe0 --- /dev/null +++ b/include/mockutils/constexpr_hash.hpp @@ -0,0 +1,21 @@ +#pragma once + +namespace fakeit { + + template + constexpr size_t constExprHash( const char (&str)[N] ) { + size_t _Val = 14695981039346656037ULL; // _FNV_offset_basis + constexpr size_t _FNV_prime = 1099511628211ULL; + + const char* pStr(str); + auto last = pStr + N - 1; + for (; pStr != last; ++pStr) + { + _Val ^= static_cast(*pStr); + _Val *= _FNV_prime; + } + + return _Val; + } + +} \ No newline at end of file diff --git a/include/mockutils/mscpp/VirtualTable.hpp b/include/mockutils/mscpp/VirtualTable.hpp index 029b5834..693a79c0 100644 --- a/include/mockutils/mscpp/VirtualTable.hpp +++ b/include/mockutils/mscpp/VirtualTable.hpp @@ -189,7 +189,7 @@ namespace fakeit { } void copyFrom(VirtualTable &from) { - unsigned int size = VTUtils::getVTSize(); + auto size = VTUtils::getVTSize(); for (unsigned int i = 0; i < size; i++) { _firstMethod[i] = from.getMethod(i); } @@ -233,7 +233,7 @@ namespace fakeit { setCookie(numOfCookies - 1, method); // use the last cookie } - unsigned int getSize() { + size_t getSize() { return VTUtils::getVTSize(); } @@ -259,7 +259,7 @@ namespace fakeit { static const unsigned int numOfCookies = 3; static void **buildVTArray() { - int vtSize = VTUtils::getVTSize(); + auto vtSize = VTUtils::getVTSize(); auto array = new void *[vtSize + numOfCookies + 1]{}; RTTICompleteObjectLocator *objectLocator = new RTTICompleteObjectLocator( typeid(C)); diff --git a/tests/FakeIt.vcxproj b/tests/FakeIt.vcxproj index 449a0568..b7c14392 100644 --- a/tests/FakeIt.vcxproj +++ b/tests/FakeIt.vcxproj @@ -78,6 +78,7 @@ + From 7f40ec6989ba3ae71069dfd792101176da457016 Mon Sep 17 00:00:00 2001 From: otrempe Date: Wed, 9 Nov 2022 14:42:16 -0500 Subject: [PATCH 3/7] C++11 compliant constExprHash --- include/mockutils/constexpr_hash.hpp | 22 +++++++++------------- 1 file changed, 9 insertions(+), 13 deletions(-) diff --git a/include/mockutils/constexpr_hash.hpp b/include/mockutils/constexpr_hash.hpp index c504afe0..0a3822c6 100644 --- a/include/mockutils/constexpr_hash.hpp +++ b/include/mockutils/constexpr_hash.hpp @@ -2,20 +2,16 @@ namespace fakeit { - template - constexpr size_t constExprHash( const char (&str)[N] ) { - size_t _Val = 14695981039346656037ULL; // _FNV_offset_basis - constexpr size_t _FNV_prime = 1099511628211ULL; - - const char* pStr(str); - auto last = pStr + N - 1; - for (; pStr != last; ++pStr) - { - _Val ^= static_cast(*pStr); - _Val *= _FNV_prime; - } + constexpr size_t _FNV_prime = sizeof(size_t) == 4 ? 16777619ULL : 1099511628211ULL; + constexpr size_t _FNV_offset_basis = sizeof(size_t) == 4 ? 2166136261ULL : 14695981039346656037ULL; - return _Val; + constexpr size_t _constExprHashImpl(const char* str, size_t count) { + return count ? (_constExprHashImpl(str, count - 1) ^ str[count - 1]) * _FNV_prime : _FNV_offset_basis; + } + + template + constexpr size_t constExprHash(const char(&str)[N]) { + return _constExprHashImpl(str, N); } } \ No newline at end of file From 9811eb73f00ee686d9d65f7be14953a1da6a4778 Mon Sep 17 00:00:00 2001 From: otrempe Date: Wed, 9 Nov 2022 15:49:36 -0500 Subject: [PATCH 4/7] Added new source test file to build/sources.mk --- build/sources.mk | 1 + 1 file changed, 1 insertion(+) diff --git a/build/sources.mk b/build/sources.mk index 45ac736f..9c0f94e0 100644 --- a/build/sources.mk +++ b/build/sources.mk @@ -13,6 +13,7 @@ CPP_SRCS += \ miscellaneous_tests.cpp \ msc_stubbing_multiple_values_tests.cpp \ msc_type_info_tests.cpp \ + multiple_translation_units_stub_test.cpp \ overloadded_methods_tests.cpp \ referece_types_tests.cpp \ remove_const_volatile_tests.cpp \ From 2230a37a81a065cb2c0caf73cfb84ce1d5dc8ff6 Mon Sep 17 00:00:00 2001 From: otrempe Date: Wed, 9 Nov 2022 15:58:22 -0500 Subject: [PATCH 5/7] Helper file needed as well in build/sources.mk --- build/sources.mk | 1 + 1 file changed, 1 insertion(+) diff --git a/build/sources.mk b/build/sources.mk index 9c0f94e0..21add538 100644 --- a/build/sources.mk +++ b/build/sources.mk @@ -13,6 +13,7 @@ CPP_SRCS += \ miscellaneous_tests.cpp \ msc_stubbing_multiple_values_tests.cpp \ msc_type_info_tests.cpp \ + multiple_translation_units_stub.cpp \ multiple_translation_units_stub_test.cpp \ overloadded_methods_tests.cpp \ referece_types_tests.cpp \ From 2b51c7c111dd7ac8f1c93583101489f3a35a37d7 Mon Sep 17 00:00:00 2001 From: FranckRJ Date: Sun, 26 May 2024 22:30:58 +0200 Subject: [PATCH 6/7] Add back tests from previous implementation. --- tests/CMakeLists.txt | 3 +- tests/inherited_funcs_tests.cpp | 81 ++++++++++++ ...ound.cpp => moving_mocks_around_tests.cpp} | 14 +- tests/multiple_translation_units_stub.cpp | 29 ++++- tests/multiple_translation_units_stub.h | 18 ++- .../multiple_translation_units_stub_test.cpp | 122 ++++++++++++++++-- 6 files changed, 237 insertions(+), 30 deletions(-) create mode 100644 tests/inherited_funcs_tests.cpp rename tests/{moving_mocks_around.cpp => moving_mocks_around_tests.cpp} (89%) diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index ae861015..a532a78b 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -10,9 +10,10 @@ add_executable(FakeIt_tests functional.cpp gcc_stubbing_multiple_values_tests.cpp gcc_type_info_tests.cpp + inherited_funcs_tests.cpp miscellaneous_tests.cpp move_only_return_tests.cpp - moving_mocks_around.cpp + moving_mocks_around_tests.cpp msc_stubbing_multiple_values_tests.cpp msc_type_info_tests.cpp multiple_translation_units_stub.cpp diff --git a/tests/inherited_funcs_tests.cpp b/tests/inherited_funcs_tests.cpp new file mode 100644 index 00000000..185b2dd0 --- /dev/null +++ b/tests/inherited_funcs_tests.cpp @@ -0,0 +1,81 @@ +/* + * Copyright (c) 2014 Eran Pe'er. + * + * This program is made available under the terms of the MIT License. + * + * Created on Mar 10, 2014 + */ + +#include "tpunit++.hpp" +#include "fakeit.hpp" + +using namespace fakeit; + +struct InheritedFuncsTests : tpunit::TestFixture +{ + + InheritedFuncsTests() : + TestFixture( + TEST(InheritedFuncsTests::mock_base_overloaded_functions), + TEST(InheritedFuncsTests::mock_base_and_child_overloaded_functions) + ) + { + } + + class BaseInterface + { + public: + virtual ~BaseInterface() = default; + + virtual double nonOverloadedMethod() = 0; + virtual double overloadedMethod() = 0; + virtual double overloadedMethod() const = 0; + virtual double overloadedInChildMethod() = 0; + }; + + class Interface : public BaseInterface + { + public: + ~Interface() override = default; + using BaseInterface::overloadedInChildMethod; + virtual double overloadedInChildMethod() const = 0; + }; + + void mock_base_overloaded_functions() + { + Mock mock; + + When(Method(mock, nonOverloadedMethod)).Return(1.5); + When(OverloadedMethod(mock, overloadedMethod, double())).Return(2.5); + When(ConstOverloadedMethod(mock, overloadedMethod, double())).Return(3.5); + + Interface& interface = mock.get(); + const Interface& constInterface = mock.get(); + + EXPECT_EQUAL(interface.nonOverloadedMethod(), 1.5); + EXPECT_EQUAL(interface.overloadedMethod(), 2.5); + EXPECT_EQUAL(constInterface.overloadedMethod(), 3.5); + + Verify(Method(mock, nonOverloadedMethod)).Exactly(1); + Verify(OverloadedMethod(mock, overloadedMethod, double())).Exactly(1); + Verify(ConstOverloadedMethod(mock, overloadedMethod, double())).Exactly(1); + } + + void mock_base_and_child_overloaded_functions() + { + Mock mock; + + When(OverloadedMethod(mock, overloadedInChildMethod, double())).Return(4.5); + When(ConstOverloadedMethod(mock, overloadedInChildMethod, double())).Return(5.5); + + Interface& interface = mock.get(); + const Interface& constInterface = mock.get(); + + EXPECT_EQUAL(interface.overloadedInChildMethod(), 4.5); + EXPECT_EQUAL(constInterface.overloadedInChildMethod(), 5.5); + + Verify(OverloadedMethod(mock, overloadedInChildMethod, double())).Exactly(1); + Verify(ConstOverloadedMethod(mock, overloadedInChildMethod, double())).Exactly(1); + } + +} __InheritedFuncsTests; diff --git a/tests/moving_mocks_around.cpp b/tests/moving_mocks_around_tests.cpp similarity index 89% rename from tests/moving_mocks_around.cpp rename to tests/moving_mocks_around_tests.cpp index 4a0a778c..669bc925 100644 --- a/tests/moving_mocks_around.cpp +++ b/tests/moving_mocks_around_tests.cpp @@ -11,15 +11,15 @@ using namespace fakeit; -struct MovingMocksAround : tpunit::TestFixture +struct MovingMocksAroundTests : tpunit::TestFixture { - MovingMocksAround() : + MovingMocksAroundTests() : TestFixture( - TEST(MovingMocksAround::move_mock), - TEST(MovingMocksAround::move_mock_then_delete), - TEST(MovingMocksAround::create_mock_from_function), - TEST(MovingMocksAround::create_multiple_mocks_from_function) + TEST(MovingMocksAroundTests::move_mock), + TEST(MovingMocksAroundTests::move_mock_then_delete), + TEST(MovingMocksAroundTests::create_mock_from_function), + TEST(MovingMocksAroundTests::create_multiple_mocks_from_function) ) { } @@ -98,4 +98,4 @@ struct MovingMocksAround : tpunit::TestFixture Verify(Method(mock2, function).Using(paramString2)).Exactly(1); } -} __MovingMocksAround; +} __MovingMocksAroundTests; diff --git a/tests/multiple_translation_units_stub.cpp b/tests/multiple_translation_units_stub.cpp index 6f2dc0bb..2fa25bfe 100644 --- a/tests/multiple_translation_units_stub.cpp +++ b/tests/multiple_translation_units_stub.cpp @@ -1,12 +1,27 @@ #include "multiple_translation_units_stub.h" +namespace multiple_tu { -void stubFunc2(fakeit::Mock& mock) -{ - fakeit::When(Method(mock, func2)).AlwaysReturn("String"); -} + void stubFunc(fakeit::Mock& mock) + { + fakeit::When(Method(mock, func)).Return(5); + } + + void stubFunc2(fakeit::Mock& mock) + { + fakeit::When(Method(mock, func2)).Return("String"); + } + + void stubMoreFunc(fakeit::Mock& mock) + { + fakeit::When(Method(mock, func).Using(1)).Return(10); + fakeit::When(Method(mock, func).Using(2)).Return(20); + } + + void stubMoreFunc2(fakeit::Mock& mock) + { + fakeit::When(Method(mock, func2).Using(1)).Return("String1"); + fakeit::When(Method(mock, func2).Using(2)).Return("String2"); + } -void stubFunc(fakeit::Mock& mock) -{ - fakeit::When(Method(mock, func)).AlwaysReturn(3); } diff --git a/tests/multiple_translation_units_stub.h b/tests/multiple_translation_units_stub.h index 084cf17b..28293d63 100644 --- a/tests/multiple_translation_units_stub.h +++ b/tests/multiple_translation_units_stub.h @@ -4,10 +4,16 @@ #include "fakeit.hpp" -struct SomeInterface { - virtual int func() = 0; - virtual std::string func2() = 0; -}; +namespace multiple_tu { -void stubFunc2(fakeit::Mock& mock); -void stubFunc(fakeit::Mock& mock); + struct SomeInterface { + virtual int func(int) = 0; + virtual std::string func2(int) = 0; + }; + + void stubFunc(fakeit::Mock& mock); + void stubFunc2(fakeit::Mock& mock); + void stubMoreFunc(fakeit::Mock& mock); + void stubMoreFunc2(fakeit::Mock& mock); + +} diff --git a/tests/multiple_translation_units_stub_test.cpp b/tests/multiple_translation_units_stub_test.cpp index 75cf43f4..8f954850 100644 --- a/tests/multiple_translation_units_stub_test.cpp +++ b/tests/multiple_translation_units_stub_test.cpp @@ -3,22 +3,126 @@ #include "multiple_translation_units_stub.h" using namespace fakeit; +using namespace multiple_tu; struct MultipleTranslationUnitsStub : tpunit::TestFixture { - MultipleTranslationUnitsStub() - : tpunit::TestFixture( - TEST(MultipleTranslationUnitsStub::NoCollidingIds) - ) - {} - void NoCollidingIds() { + MultipleTranslationUnitsStub() : + tpunit::TestFixture( + TEST(MultipleTranslationUnitsStub::NoCollidingIdsBasics), + TEST(MultipleTranslationUnitsStub::NoCollidingIdsAlternateBasics), + TEST(MultipleTranslationUnitsStub::NoCollidingIdsMoreFunctionsMocked), + TEST(MultipleTranslationUnitsStub::NoCollidingIdsWhenOverridingMocks) + ) + { + } + + void NoCollidingIdsBasics() + { + Mock mock; + + stubFunc(mock); + When(Method(mock, func2)).Return("Something"); + + SomeInterface &i = mock.get(); + + // Uncatchable write access violation if ids collide. + EXPECT_EQUAL(i.func(5), 5); + EXPECT_EQUAL(i.func2(5), "Something"); + + Verify(Method(mock, func).Using(5)).Exactly(1); + Verify(Method(mock, func2).Using(5)).Exactly(1); + } + + void NoCollidingIdsAlternateBasics() + { + Mock mock; + + When(Method(mock, func)).Return(100); + stubFunc2(mock); + + SomeInterface &i = mock.get(); + + // Uncatchable write access violation if ids collide. + EXPECT_EQUAL(i.func(5), 100); + EXPECT_EQUAL(i.func2(5), "String"); + + Verify(Method(mock, func).Using(5)).Exactly(1); + Verify(Method(mock, func2).Using(5)).Exactly(1); + } + + void NoCollidingIdsMoreFunctionsMocked() + { Mock mock; + + stubFunc(mock); + stubFunc2(mock); + + When(Method(mock, func).Using(20)).Return(20); + When(Method(mock, func).Using(50)).Return(50); + + When(Method(mock, func2).Using(20)).Return("Something-20"); + When(Method(mock, func2).Using(50)).Return("Something-50"); + + stubMoreFunc(mock); + stubMoreFunc2(mock); + SomeInterface &i = mock.get(); - + + // Uncatchable write access violation if ids collide. + EXPECT_EQUAL(i.func(1), 10); + EXPECT_EQUAL(i.func(2), 20); + EXPECT_EQUAL(i.func(5), 5); + EXPECT_EQUAL(i.func(20), 20); + EXPECT_EQUAL(i.func(50), 50); + EXPECT_EQUAL(i.func2(1), "String1"); + EXPECT_EQUAL(i.func2(2), "String2"); + EXPECT_EQUAL(i.func2(5), "String"); + EXPECT_EQUAL(i.func2(20), "Something-20"); + EXPECT_EQUAL(i.func2(50), "Something-50"); + + Verify(Method(mock, func).Using(1)).Exactly(1); + Verify(Method(mock, func).Using(2)).Exactly(1); + Verify(Method(mock, func).Using(5)).Exactly(1); + Verify(Method(mock, func).Using(20)).Exactly(1); + Verify(Method(mock, func).Using(50)).Exactly(1); + Verify(Method(mock, func2).Using(1)).Exactly(1); + Verify(Method(mock, func2).Using(2)).Exactly(1); + Verify(Method(mock, func2).Using(5)).Exactly(1); + Verify(Method(mock, func2).Using(20)).Exactly(1); + Verify(Method(mock, func2).Using(50)).Exactly(1); + } + + void NoCollidingIdsWhenOverridingMocks() + { + Mock mock; + + stubFunc(mock); + When(Method(mock, func)).Return(123); + When(Method(mock, func2)).Return("Something"); stubFunc2(mock); - When(Method(mock, func)).Return(1); - mock.get().func2(); // Uncatchable write access violation if ids collide + SomeInterface &i = mock.get(); + + EXPECT_EQUAL(i.func(0), 123); + EXPECT_EQUAL(i.func2(0), "String"); + + try { + i.func(0); + FAIL(); + } catch (const UnexpectedMethodCallException&) { + // There was only one action in the mock for this function. + } + + try { + i.func2(0); + FAIL(); + } catch (const UnexpectedMethodCallException&) { + // There was only one action in the mock for this function. + } + + Verify(Method(mock, func)).Exactly(2); + Verify(Method(mock, func)).Exactly(2); } } __MultipleTranslationUnitsStub; From 9769ebb441b693bad6013a9f01190b3a6ade92e9 Mon Sep 17 00:00:00 2001 From: FranckRJ Date: Sun, 26 May 2024 22:55:05 +0200 Subject: [PATCH 7/7] Fixes to be compatible with the new versions of FakeIt. --- include/fakeit/api_macros.hpp | 8 ++++---- include/mockutils/DynamicProxy.hpp | 13 ++++++------- include/mockutils/MethodProxyCreator.hpp | 6 +++--- include/mockutils/VTUtils.hpp | 2 +- include/mockutils/gcc/VirtualTable.hpp | 2 +- include/mockutils/mscpp/VirtualTable.hpp | 8 ++++---- 6 files changed, 19 insertions(+), 20 deletions(-) diff --git a/include/fakeit/api_macros.hpp b/include/fakeit/api_macros.hpp index ae89b756..dcf2fb56 100644 --- a/include/fakeit/api_macros.hpp +++ b/include/fakeit/api_macros.hpp @@ -48,16 +48,16 @@ (mock).template stub(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) + (mock).template stub(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) + (mock).template stub(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) + (mock).template stub(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) + (mock).template stub(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/include/mockutils/DynamicProxy.hpp b/include/mockutils/DynamicProxy.hpp index e1dcde6c..2130a062 100644 --- a/include/mockutils/DynamicProxy.hpp +++ b/include/mockutils/DynamicProxy.hpp @@ -13,10 +13,8 @@ #include #include #include -#include #include "mockutils/VirtualTable.hpp" -#include "mockutils/union_cast.hpp" #include "mockutils/MethodInvocationHandler.hpp" #include "mockutils/VTUtils.hpp" #include "mockutils/FakeObject.hpp" @@ -34,7 +32,8 @@ namespace fakeit { { unsigned int offset = 0; for (; offset < _offsets.size(); offset++) { - if (_offsets[offset] == id) { + // Only check _offsets for methods that were mocked. + if (_methodMocks[offset] != nullptr && _offsets[offset] == id) { break; } } @@ -61,8 +60,8 @@ namespace fakeit { DynamicProxy(C &inst) : _instancePtr(&inst), - _methodMocks(VTUtils::getVTSize()), - _offsets(VTUtils::getVTSize(), std::numeric_limits::max()), + _methodMocks(VTUtils::getVTSize(), nullptr), + _offsets(VTUtils::getVTSize(), 0), _invocationHandlers(_methodMocks, _offsets) { _originalVt.copyFrom(VirtualTable::getVTable(*_instancePtr)); _originalVt.setCookie(InvocationHandlerCollection::VtCookieIndex, &_invocationHandlers); @@ -97,10 +96,10 @@ namespace fakeit { void Reset() { _methodMocks = {}; - _methodMocks.resize(VTUtils::getVTSize()); + _methodMocks.resize(VTUtils::getVTSize(), nullptr); _members = {}; _offsets = {}; - _offsets.resize(VTUtils::getVTSize()); + _offsets.resize(VTUtils::getVTSize(), 0); VirtualTable::getVTable(*_instancePtr).copyFrom(_originalVt); } diff --git a/include/mockutils/MethodProxyCreator.hpp b/include/mockutils/MethodProxyCreator.hpp index 23f64953..c6a53a35 100644 --- a/include/mockutils/MethodProxyCreator.hpp +++ b/include/mockutils/MethodProxyCreator.hpp @@ -34,7 +34,7 @@ namespace fakeit { return MethodProxy(id, offset, union_cast(&MethodProxyCreator::methodProxyX < id > )); } - template + template MethodProxy createMethodProxyStatic(unsigned int offset) { return MethodProxy(id, offset, union_cast(&MethodProxyCreator::methodProxyXStatic < id > )); } @@ -55,7 +55,7 @@ namespace fakeit { return methodProxy(id, std::forward::type>(args)...); } - static R methodProxyStatic(void* instance, unsigned int id, const typename fakeit::production_arg::type... args) { + static R methodProxyStatic(void* instance, size_t id, const typename fakeit::production_arg::type... args) { InvocationHandlerCollection *invocationHandlerCollection = InvocationHandlerCollection::getInvocationHandlerCollection( instance); MethodInvocationHandler *invocationHandler = @@ -64,7 +64,7 @@ namespace fakeit { return invocationHandler->handleMethodInvocation(std::forward::type>(args)...); } - template + template static R methodProxyXStatic(void* instance, arglist ... args) { return methodProxyStatic(instance, id, std::forward::type>(args)...); } diff --git a/include/mockutils/VTUtils.hpp b/include/mockutils/VTUtils.hpp index cc0268e1..3256b711 100644 --- a/include/mockutils/VTUtils.hpp +++ b/include/mockutils/VTUtils.hpp @@ -65,7 +65,7 @@ namespace fakeit { } template - static size_t getVTSize() { + static unsigned int getVTSize() { struct Derrived : public C { virtual void endOfVt() { } diff --git a/include/mockutils/gcc/VirtualTable.hpp b/include/mockutils/gcc/VirtualTable.hpp index 03891818..1ed85f7d 100644 --- a/include/mockutils/gcc/VirtualTable.hpp +++ b/include/mockutils/gcc/VirtualTable.hpp @@ -131,7 +131,7 @@ namespace fakeit { private: static void **buildVTArray() { - int size = VTUtils::getVTSize(); + unsigned int size = VTUtils::getVTSize(); auto array = new void *[size + 2 + numOfCookies]{}; array += numOfCookies; // skip cookies array++; // skip top_offset diff --git a/include/mockutils/mscpp/VirtualTable.hpp b/include/mockutils/mscpp/VirtualTable.hpp index 449f6577..04e31146 100644 --- a/include/mockutils/mscpp/VirtualTable.hpp +++ b/include/mockutils/mscpp/VirtualTable.hpp @@ -178,7 +178,7 @@ namespace fakeit { } void copyFrom(VirtualTable &from) { - auto size = VTUtils::getVTSize(); + unsigned int size = VTUtils::getVTSize(); for (unsigned int i = 0; i < size; i++) { _firstMethod[i] = from.getMethod(i); } @@ -234,12 +234,12 @@ namespace fakeit { setCookie(dtorCookieIndex, method); } - size_t getSize() { + unsigned int getSize() { return VTUtils::getVTSize(); } void initAll(void *value) { - auto size = getSize(); + unsigned int size = getSize(); for (unsigned int i = 0; i < size; i++) { setMethod(i, value); } @@ -256,7 +256,7 @@ namespace fakeit { static const unsigned int dtorCookieIndex = numOfCookies - 1; // use the last cookie static void **buildVTArray() { - auto vtSize = VTUtils::getVTSize(); + unsigned int vtSize = VTUtils::getVTSize(); auto array = new void *[vtSize + numOfCookies + 1]{}; RTTICompleteObjectLocator *objectLocator = new RTTICompleteObjectLocator( typeid(C));