From fe860088cd5e1ff929b79f685a001b41c08dc8b9 Mon Sep 17 00:00:00 2001 From: FranckRJ Date: Sun, 12 May 2024 13:01:15 +0200 Subject: [PATCH] Test commit of new method id system to see if it works on other compilers. --- include/fakeit/Mock.hpp | 32 ++++----- include/fakeit/MockImpl.hpp | 12 ++-- include/fakeit/Prototype.hpp | 12 ++-- include/fakeit/api_macros.hpp | 14 ++-- include/mockutils/DynamicProxy.hpp | 71 ++++++++++--------- include/mockutils/MethodProxy.hpp | 10 +-- include/mockutils/MethodProxyCreator.hpp | 14 ++-- tests/multiple_translation_units_stub.h | 2 + .../multiple_translation_units_stub_test.cpp | 1 + 9 files changed, 90 insertions(+), 78 deletions(-) diff --git a/include/fakeit/Mock.hpp b/include/fakeit/Mock.hpp index 4cae42e3..dc6f7ec4 100644 --- a/include/fakeit/Mock.hpp +++ b/include/fakeit/Mock.hpp @@ -71,67 +71,67 @@ namespace fakeit { } // const - template::value>::type> MockingContext, arglist...> stub(R (T::*vMethod)(arglist...) const) { auto methodWithoutConstVolatile = reinterpret_cast (T::*)(arglist...)>(vMethod); - return impl.template stubMethod(methodWithoutConstVolatile); + return impl.template stubMethod(methodWithoutConstVolatile); } // volatile - template::value>::type> MockingContext, arglist...> stub(R(T::*vMethod)(arglist...) volatile) { auto methodWithoutConstVolatile = reinterpret_cast(T::*)(arglist...)>(vMethod); - return impl.template stubMethod(methodWithoutConstVolatile); + return impl.template stubMethod(methodWithoutConstVolatile); } // const volatile - template::value>::type> MockingContext, arglist...> stub(R(T::*vMethod)(arglist...) const volatile) { auto methodWithoutConstVolatile = reinterpret_cast(T::*)(arglist...)>(vMethod); - return impl.template stubMethod(methodWithoutConstVolatile); + return impl.template stubMethod(methodWithoutConstVolatile); } // no qualifier - template::value>::type> MockingContext, arglist...> stub(R(T::*vMethod)(arglist...)) { auto methodWithoutConstVolatile = reinterpret_cast(T::*)(arglist...)>(vMethod); - return impl.template stubMethod(methodWithoutConstVolatile); + return impl.template stubMethod(methodWithoutConstVolatile); } // ref - template::value>::type> MockingContext, arglist...> stub(R(T::*vMethod)(arglist...) &) { auto methodWithoutConstVolatile = reinterpret_cast(T::*)(arglist...)>(vMethod); - return impl.template stubMethod(methodWithoutConstVolatile); + return impl.template stubMethod(methodWithoutConstVolatile); } // const ref - template::value>::type> MockingContext, arglist...> stub(R(T::*vMethod)(arglist...) const&) { auto methodWithoutConstVolatile = reinterpret_cast(T::*)(arglist...)>(vMethod); - return impl.template stubMethod(methodWithoutConstVolatile); + return impl.template stubMethod(methodWithoutConstVolatile); } // rval ref - template::value>::type> MockingContext, arglist...> stub(R(T::*vMethod)(arglist...) &&) { auto methodWithoutConstVolatile = reinterpret_cast(T::*)(arglist...)>(vMethod); - return impl.template stubMethod(methodWithoutConstVolatile); + return impl.template stubMethod(methodWithoutConstVolatile); } // const rval ref - template::value>::type> MockingContext, arglist...> stub(R(T::*vMethod)(arglist...) const&&) { auto methodWithoutConstVolatile = reinterpret_cast(T::*)(arglist...)>(vMethod); - return impl.template stubMethod(methodWithoutConstVolatile); + return impl.template stubMethod(methodWithoutConstVolatile); } DtorMockingContext dtor() { diff --git a/include/fakeit/MockImpl.hpp b/include/fakeit/MockImpl.hpp index 891c337f..289b7062 100644 --- a/include/fakeit/MockImpl.hpp +++ b/include/fakeit/MockImpl.hpp @@ -101,9 +101,9 @@ namespace fakeit { return DataMemberStubbingRoot(); } - template::value>::type> + template::value>::type> MockingContext stubMethod(R(T::*vMethod)(arglist...)) { - return MockingContext(new UniqueMethodMockingContextImpl < id, R, arglist... > + return MockingContext(new UniqueMethodMockingContextImpl < MethodType, Method, R, arglist... > (*this, vMethod)); } @@ -226,12 +226,12 @@ namespace fakeit { }; - template + template class UniqueMethodMockingContextImpl : public MethodMockingContextImpl { protected: RecordedMethodBody &getRecordedMethodBody() override { - return MethodMockingContextBase::_mock.template stubMethodIfNotStubbed( + return MethodMockingContextBase::_mock.template stubMethodIfNotStubbed( MethodMockingContextBase::_mock._proxy, MethodMockingContextImpl::_vMethod); } @@ -323,11 +323,11 @@ namespace fakeit { return origMethodPtr; } - template + template RecordedMethodBody &stubMethodIfNotStubbed(DynamicProxy &proxy, R (C::*vMethod)(arglist...)) { if (!proxy.isMethodStubbed(vMethod)) { - proxy.template stubMethod(vMethod, createRecordedMethodBody < R, arglist... > (*this, vMethod)); + proxy.template stubMethod(vMethod, createRecordedMethodBody < R, arglist... > (*this, vMethod)); } Destructible *d = proxy.getMethodMock(vMethod); RecordedMethodBody *methodMock = dynamic_cast *>(d); diff --git a/include/fakeit/Prototype.hpp b/include/fakeit/Prototype.hpp index 8b86f08b..4367aca1 100644 --- a/include/fakeit/Prototype.hpp +++ b/include/fakeit/Prototype.hpp @@ -18,27 +18,27 @@ namespace fakeit { using RValRefType = R (C::*)(Args...) &&; using ConstRValRefType = R (C::*)(Args...) const&&; - static Type get(Type t) { + static constexpr Type get(Type t) { return t; } - static ConstType getConst(ConstType t) { + static constexpr ConstType getConst(ConstType t) { return t; } - static RefType getRef(RefType t) { + static constexpr RefType getRef(RefType t) { return t; } - static ConstRefType getConstRef(ConstRefType t) { + static constexpr ConstRefType getConstRef(ConstRefType t) { return t; } - static RValRefType getRValRef(RValRefType t) { + static constexpr RValRefType getRValRef(RValRefType t) { return t; } - static ConstRValRefType getConstRValRef(ConstRValRefType t) { + static constexpr ConstRValRefType getConstRValRef(ConstRValRefType t) { return t; } diff --git a/include/fakeit/api_macros.hpp b/include/fakeit/api_macros.hpp index dcf2fb56..a81ad315 100644 --- a/include/fakeit/api_macros.hpp +++ b/include/fakeit/api_macros.hpp @@ -39,25 +39,25 @@ (mock).dtor().setMethodDetails(#mock,"destructor") #define Method(mock, method) \ - (mock).template stub(&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(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(CONST_OVERLOADED_METHOD_PTR( mock , method, prototype )).setMethodDetails(#mock,#method) + (mock).template stub(CONST_OVERLOADED_METHOD_PTR( mock , method, prototype )).setMethodDetails(#mock,#method) #define RefOverloadedMethod(mock, method, prototype) \ - (mock).template stub(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(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(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(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 62d28857..0fa607f1 100644 --- a/include/mockutils/DynamicProxy.hpp +++ b/include/mockutils/DynamicProxy.hpp @@ -26,45 +26,52 @@ namespace fakeit { - class InvocationHandlers : public InvocationHandlerCollection { - std::vector> &_methodMocks; - std::vector &_offsets; + namespace details { + template + void funcId() {} - unsigned int getOffset(size_t id) const - { - unsigned int offset = 0; - for (; offset < _offsets.size(); offset++) { - // "_methodMocks[offset] != nullptr" checked to guarantee that "_offsets[offset]" was really set and - // doesn't just contain the default id. - if (_offsets[offset] == id && _methodMocks[offset] != nullptr) { - break; + inline void funcIdDestructor() {} + + inline void funcIdNotStubbed() {} + } + + template + struct DynamicProxy { + + class InvocationHandlers : public InvocationHandlerCollection { + std::vector> &_methodMocks; + std::vector &_offsets; + + unsigned int getOffset(MethodIdType id) const + { + unsigned int offset = 0; + for (; offset < _offsets.size(); offset++) { + if (_offsets[offset] == id) { + break; + } } + return offset; } - return offset; - } - - public: - InvocationHandlers(std::vector> &methodMocks, std::vector &offsets) - : _methodMocks(methodMocks), _offsets(offsets) { - } - Destructible *getInvocatoinHandlerPtrById(size_t id) override { - unsigned int offset = getOffset(id); - std::shared_ptr ptr = _methodMocks[offset]; - return ptr.get(); - } + public: + InvocationHandlers(std::vector> &methodMocks, std::vector &offsets) + : _methodMocks(methodMocks), _offsets(offsets) { + } - }; + Destructible *getInvocatoinHandlerPtrById(MethodIdType id) override { + unsigned int offset = getOffset(id); + std::shared_ptr ptr = _methodMocks[offset]; + return ptr.get(); + } - template - struct DynamicProxy { + }; static_assert(std::is_polymorphic::value, "DynamicProxy requires a polymorphic type"); DynamicProxy(C &inst) : _instancePtr(&inst), _methodMocks(VTUtils::getVTSize()), - _offsets(VTUtils::getVTSize(), std::numeric_limits::max()), + _offsets(VTUtils::getVTSize(), &details::funcIdNotStubbed), _invocationHandlers(_methodMocks, _offsets) { _originalVt.copyFrom(VirtualTable::getVTable(*_instancePtr)); _originalVt.setCookie(InvocationHandlerCollection::VtCookieIndex, &_invocationHandlers); @@ -110,11 +117,11 @@ namespace fakeit { { } - template + template void stubMethod(R(C::*vMethod)(arglist...), MethodInvocationHandler *methodInvocationHandler) { auto offset = VTUtils::getOffset(vMethod); MethodProxyCreator creator; - bind(creator.template createMethodProxy(offset), methodInvocationHandler); + bind(creator.template createMethodProxy<&details::funcId>(offset), methodInvocationHandler); } void stubDtor(MethodInvocationHandler *methodInvocationHandler) { @@ -127,9 +134,9 @@ namespace fakeit { // 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); + bindDtor(creator.createMethodProxyStatic<&details::funcIdDestructor>(offset), methodInvocationHandler); #else - bindDtor(creator.createMethodProxy<0>(offset), methodInvocationHandler); + bindDtor(creator.createMethodProxy<&details::funcIdDestructor>(offset), methodInvocationHandler); #endif } @@ -219,7 +226,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 66ee39d6..15294256 100644 --- a/include/mockutils/MethodProxy.hpp +++ b/include/mockutils/MethodProxy.hpp @@ -4,9 +4,11 @@ namespace fakeit { + using MethodIdType = void(*)(); + struct MethodProxy { - MethodProxy(size_t id, unsigned int offset, void *vMethod) : + MethodProxy(MethodIdType id, unsigned int offset, void *vMethod) : _id(id), _offset(offset), _vMethod(vMethod) { @@ -16,7 +18,7 @@ namespace fakeit { return _offset; } - size_t getId() const { + MethodIdType getId() const { return _id; } @@ -25,8 +27,8 @@ namespace fakeit { } private: - size_t _id; + MethodIdType _id; unsigned int _offset; void *_vMethod; }; -} \ No newline at end of file +} diff --git a/include/mockutils/MethodProxyCreator.hpp b/include/mockutils/MethodProxyCreator.hpp index 23f64953..464bfa4c 100644 --- a/include/mockutils/MethodProxyCreator.hpp +++ b/include/mockutils/MethodProxyCreator.hpp @@ -11,7 +11,7 @@ namespace fakeit { struct InvocationHandlerCollection { static const unsigned int VtCookieIndex = 0; - virtual Destructible *getInvocatoinHandlerPtrById(size_t index) = 0; + virtual Destructible *getInvocatoinHandlerPtrById(MethodIdType id) = 0; static InvocationHandlerCollection *getInvocationHandlerCollection(void *instance) { VirtualTableBase &vt = VirtualTableBase::getVTable(instance); @@ -29,19 +29,19 @@ namespace fakeit { public: - template + template MethodProxy createMethodProxy(unsigned int offset) { 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 > )); } protected: - R methodProxy(size_t id, const typename fakeit::production_arg::type... args) { + R methodProxy(MethodIdType id, const typename fakeit::production_arg::type... args) { InvocationHandlerCollection *invocationHandlerCollection = InvocationHandlerCollection::getInvocationHandlerCollection( this); MethodInvocationHandler *invocationHandler = @@ -50,12 +50,12 @@ namespace fakeit { return invocationHandler->handleMethodInvocation(std::forward::type>(args)...); } - template + template 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) { + static R methodProxyStatic(void* instance, MethodIdType 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/tests/multiple_translation_units_stub.h b/tests/multiple_translation_units_stub.h index 747a4f41..bb75bbc5 100644 --- a/tests/multiple_translation_units_stub.h +++ b/tests/multiple_translation_units_stub.h @@ -9,6 +9,8 @@ namespace multiple_tu { struct SomeInterface { virtual int func() = 0; virtual std::string func2() = 0; + virtual int funcOverloaded(int) = 0; + virtual int funcOverloaded(double) = 0; }; void stubFunc(fakeit::Mock& mock); diff --git a/tests/multiple_translation_units_stub_test.cpp b/tests/multiple_translation_units_stub_test.cpp index 4435816d..2e4b2297 100644 --- a/tests/multiple_translation_units_stub_test.cpp +++ b/tests/multiple_translation_units_stub_test.cpp @@ -22,6 +22,7 @@ struct MultipleTranslationUnitsStub : tpunit::TestFixture { stubFunc(mock); When(Method(mock, func2)).Return("Something"); + When(OverloadedMethod(mock, funcOverloaded, int(int))).Return(5); SomeInterface &i = mock.get();