diff --git a/include/fakeit/Mock.hpp b/include/fakeit/Mock.hpp index fffde197..4cae42e3 100644 --- a/include/fakeit/Mock.hpp +++ b/include/fakeit/Mock.hpp @@ -71,7 +71,7 @@ namespace fakeit { } // const - template::value>::type> MockingContext, arglist...> stub(R (T::*vMethod)(arglist...) const) { auto methodWithoutConstVolatile = reinterpret_cast (T::*)(arglist...)>(vMethod); @@ -79,7 +79,7 @@ namespace fakeit { } // volatile - template::value>::type> MockingContext, arglist...> stub(R(T::*vMethod)(arglist...) volatile) { auto methodWithoutConstVolatile = reinterpret_cast(T::*)(arglist...)>(vMethod); @@ -87,7 +87,7 @@ namespace fakeit { } // const volatile - template::value>::type> MockingContext, arglist...> stub(R(T::*vMethod)(arglist...) const volatile) { auto methodWithoutConstVolatile = reinterpret_cast(T::*)(arglist...)>(vMethod); @@ -95,7 +95,7 @@ namespace fakeit { } // no qualifier - template::value>::type> MockingContext, arglist...> stub(R(T::*vMethod)(arglist...)) { auto methodWithoutConstVolatile = reinterpret_cast(T::*)(arglist...)>(vMethod); @@ -103,7 +103,7 @@ namespace fakeit { } // ref - template::value>::type> MockingContext, arglist...> stub(R(T::*vMethod)(arglist...) &) { auto methodWithoutConstVolatile = reinterpret_cast(T::*)(arglist...)>(vMethod); @@ -111,7 +111,7 @@ namespace fakeit { } // const ref - template::value>::type> MockingContext, arglist...> stub(R(T::*vMethod)(arglist...) const&) { auto methodWithoutConstVolatile = reinterpret_cast(T::*)(arglist...)>(vMethod); @@ -119,7 +119,7 @@ namespace fakeit { } // rval ref - template::value>::type> MockingContext, arglist...> stub(R(T::*vMethod)(arglist...) &&) { auto methodWithoutConstVolatile = reinterpret_cast(T::*)(arglist...)>(vMethod); @@ -127,7 +127,7 @@ namespace fakeit { } // const rval ref - template::value>::type> MockingContext, arglist...> stub(R(T::*vMethod)(arglist...) const&&) { auto methodWithoutConstVolatile = reinterpret_cast(T::*)(arglist...)>(vMethod); diff --git a/include/fakeit/MockImpl.hpp b/include/fakeit/MockImpl.hpp index 96eaa12f..891c337f 100644 --- a/include/fakeit/MockImpl.hpp +++ b/include/fakeit/MockImpl.hpp @@ -101,7 +101,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)); @@ -226,7 +226,7 @@ namespace fakeit { }; - template + template class UniqueMethodMockingContextImpl : public MethodMockingContextImpl { protected: @@ -323,7 +323,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 4f099a98..ae89b756 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 @@ -29,13 +39,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 RefOverloadedMethod(mock, method, prototype) \ (mock).template stub<__COUNTER__>(REF_OVERLOADED_METHOD_PTR( mock , method, prototype )).setMethodDetails(#mock,#method) diff --git a/include/mockutils/DynamicProxy.hpp b/include/mockutils/DynamicProxy.hpp index 2d562f23..e1dcde6c 100644 --- a/include/mockutils/DynamicProxy.hpp +++ b/include/mockutils/DynamicProxy.hpp @@ -28,9 +28,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++) { @@ -42,11 +42,11 @@ namespace fakeit { } public: - InvocationHandlers(std::vector> &methodMocks, std::vector &offsets) + InvocationHandlers(std::vector> &methodMocks, std::vector &offsets) : _methodMocks(methodMocks), _offsets(offsets) { } - 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(); @@ -108,7 +108,7 @@ namespace fakeit { { } - template + template void stubMethod(R(C::*vMethod)(arglist...), MethodInvocationHandler *methodInvocationHandler) { auto offset = VTUtils::getOffset(vMethod); MethodProxyCreator creator; @@ -217,7 +217,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 3d80b21f..23f64953 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(unsigned int index) = 0; + virtual Destructible *getInvocatoinHandlerPtrById(size_t index) = 0; static InvocationHandlerCollection *getInvocationHandlerCollection(void *instance) { VirtualTableBase &vt = VirtualTableBase::getVTable(instance); @@ -29,7 +29,7 @@ namespace fakeit { public: - template + template MethodProxy createMethodProxy(unsigned int offset) { return MethodProxy(id, offset, union_cast(&MethodProxyCreator::methodProxyX < id > )); } @@ -41,7 +41,7 @@ namespace fakeit { 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 = @@ -50,7 +50,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 3256b711..cc0268e1 100644 --- a/include/mockutils/VTUtils.hpp +++ b/include/mockutils/VTUtils.hpp @@ -65,7 +65,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..0a3822c6 --- /dev/null +++ b/include/mockutils/constexpr_hash.hpp @@ -0,0 +1,17 @@ +#pragma once + +namespace fakeit { + + constexpr size_t _FNV_prime = sizeof(size_t) == 4 ? 16777619ULL : 1099511628211ULL; + constexpr size_t _FNV_offset_basis = sizeof(size_t) == 4 ? 2166136261ULL : 14695981039346656037ULL; + + 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 diff --git a/include/mockutils/mscpp/VirtualTable.hpp b/include/mockutils/mscpp/VirtualTable.hpp index 0d57d241..449f6577 100644 --- a/include/mockutils/mscpp/VirtualTable.hpp +++ b/include/mockutils/mscpp/VirtualTable.hpp @@ -178,7 +178,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); } @@ -234,7 +234,7 @@ namespace fakeit { setCookie(dtorCookieIndex, method); } - unsigned int getSize() { + size_t getSize() { return VTUtils::getVTSize(); } @@ -256,7 +256,7 @@ namespace fakeit { static const unsigned int dtorCookieIndex = numOfCookies - 1; // use the last cookie 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/CMakeLists.txt b/tests/CMakeLists.txt index 02af1c4b..ae861015 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -15,6 +15,8 @@ add_executable(FakeIt_tests moving_mocks_around.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 remove_const_volatile_tests.cpp 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;