Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix colliding mocking context ids #296

Closed
wants to merge 5 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions build/sources.mk
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ 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 \
remove_const_volatile_tests.cpp \
Expand Down
16 changes: 8 additions & 8 deletions include/fakeit/Mock.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -57,55 +57,55 @@ namespace fakeit {
return impl.stubDataMember(member, ctorargs...);
}

template<int id, typename R, typename T, typename ... arglist, class = typename std::enable_if<
template<size_t id, typename R, typename T, typename ... arglist, class = typename std::enable_if<
!std::is_void<R>::value && std::is_base_of<T, C>::value>::type>
MockingContext<R, arglist...> stub(R (T::*vMethod)(arglist...) const) {
auto methodWithoutConstVolatile = reinterpret_cast<R (T::*)(arglist...)>(vMethod);
return impl.template stubMethod<id>(methodWithoutConstVolatile);
}

template<int id, typename R, typename T, typename... arglist, class = typename std::enable_if<
template<size_t id, typename R, typename T, typename... arglist, class = typename std::enable_if<
!std::is_void<R>::value && std::is_base_of<T, C>::value>::type>
MockingContext<R, arglist...> stub(R(T::*vMethod)(arglist...) volatile) {
auto methodWithoutConstVolatile = reinterpret_cast<R(T::*)(arglist...)>(vMethod);
return impl.template stubMethod<id>(methodWithoutConstVolatile);
}

template<int id, typename R, typename T, typename... arglist, class = typename std::enable_if<
template<size_t id, typename R, typename T, typename... arglist, class = typename std::enable_if<
!std::is_void<R>::value && std::is_base_of<T, C>::value>::type>
MockingContext<R, arglist...> stub(R(T::*vMethod)(arglist...) const volatile) {
auto methodWithoutConstVolatile = reinterpret_cast<R(T::*)(arglist...)>(vMethod);
return impl.template stubMethod<id>(methodWithoutConstVolatile);
}

template<int id, typename R, typename T, typename... arglist, class = typename std::enable_if<
template<size_t id, typename R, typename T, typename... arglist, class = typename std::enable_if<
!std::is_void<R>::value && std::is_base_of<T, C>::value>::type>
MockingContext<R, arglist...> stub(R(T::*vMethod)(arglist...)) {
return impl.template stubMethod<id>(vMethod);
}

template<int id, typename R, typename T, typename... arglist, class = typename std::enable_if<
template<size_t id, typename R, typename T, typename... arglist, class = typename std::enable_if<
std::is_void<R>::value && std::is_base_of<T, C>::value>::type>
MockingContext<void, arglist...> stub(R(T::*vMethod)(arglist...) const) {
auto methodWithoutConstVolatile = reinterpret_cast<void (T::*)(arglist...)>(vMethod);
return impl.template stubMethod<id>(methodWithoutConstVolatile);
}

template<int id, typename R, typename T, typename... arglist, class = typename std::enable_if<
template<size_t id, typename R, typename T, typename... arglist, class = typename std::enable_if<
std::is_void<R>::value && std::is_base_of<T, C>::value>::type>
MockingContext<void, arglist...> stub(R(T::*vMethod)(arglist...) volatile) {
auto methodWithoutConstVolatile = reinterpret_cast<void (T::*)(arglist...)>(vMethod);
return impl.template stubMethod<id>(methodWithoutConstVolatile);
}

template<int id, typename R, typename T, typename... arglist, class = typename std::enable_if<
template<size_t id, typename R, typename T, typename... arglist, class = typename std::enable_if<
std::is_void<R>::value && std::is_base_of<T, C>::value>::type>
MockingContext<void, arglist...> stub(R(T::*vMethod)(arglist...) const volatile) {
auto methodWithoutConstVolatile = reinterpret_cast<void (T::*)(arglist...)>(vMethod);
return impl.template stubMethod<id>(methodWithoutConstVolatile);
}

template<int id, typename R, typename T, typename... arglist, class = typename std::enable_if<
template<size_t id, typename R, typename T, typename... arglist, class = typename std::enable_if<
std::is_void<R>::value && std::is_base_of<T, C>::value>::type>
MockingContext<void, arglist...> stub(R(T::*vMethod)(arglist...)) {
auto methodWithoutConstVolatile = reinterpret_cast<void (T::*)(arglist...)>(vMethod);
Expand Down
6 changes: 3 additions & 3 deletions include/fakeit/MockImpl.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ namespace fakeit {
return DataMemberStubbingRoot<T, DATA_TYPE>();
}

template<int id, typename R, typename T, typename ... arglist, class = typename std::enable_if<std::is_base_of<T, C>::value>::type>
template<size_t id, typename R, typename T, typename ... arglist, class = typename std::enable_if<std::is_base_of<T, C>::value>::type>
MockingContext<R, arglist...> stubMethod(R(T::*vMethod)(arglist...)) {
return MockingContext<R, arglist...>(new UniqueMethodMockingContextImpl < id, R, arglist... >
(*this, vMethod));
Expand Down Expand Up @@ -212,7 +212,7 @@ namespace fakeit {
};


template<int id, typename R, typename ... arglist>
template<size_t id, typename R, typename ... arglist>
class UniqueMethodMockingContextImpl : public MethodMockingContextImpl<R, arglist...> {
protected:

Expand Down Expand Up @@ -304,7 +304,7 @@ namespace fakeit {
return origMethodPtr;
}

template<unsigned int id, typename R, typename ... arglist>
template<size_t id, typename R, typename ... arglist>
RecordedMethodBody<R, arglist...> &stubMethodIfNotStubbed(DynamicProxy<C, baseclasses...> &proxy,
R (C::*vMethod)(arglist...)) {
if (!proxy.isMethodStubbed(vMethod)) {
Expand Down
16 changes: 13 additions & 3 deletions include/fakeit/api_macros.hpp
Original file line number Diff line number Diff line change
@@ -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<decltype((mock).get())>::type

Expand All @@ -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<STUB_ID(__COUNTER__)>(&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<STUB_ID(__COUNTER__)>(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<STUB_ID(__COUNTER__)>(CONST_OVERLOADED_METHOD_PTR( mock , method, prototype )).setMethodDetails(#mock,#method)

#define Verify(...) \
Verify( __VA_ARGS__ ).setFileInfo(__FILE__, __LINE__, __func__)
Expand Down
14 changes: 7 additions & 7 deletions include/mockutils/DynamicProxy.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,9 @@ namespace fakeit {

class InvocationHandlers : public InvocationHandlerCollection {
std::vector<std::shared_ptr<Destructible>> &_methodMocks;
std::vector<unsigned int> &_offsets;
std::vector<size_t> &_offsets;

unsigned int getOffset(unsigned int id) const
unsigned int getOffset(size_t id) const
{
unsigned int offset = 0;
for (; offset < _offsets.size(); offset++) {
Expand All @@ -43,15 +43,15 @@ namespace fakeit {
public:
InvocationHandlers(
std::vector<std::shared_ptr<Destructible>> &methodMocks,
std::vector<unsigned int> &offsets) :
std::vector<size_t> &offsets) :
_methodMocks(methodMocks), _offsets(offsets) {
for (std::vector<unsigned int>::iterator it = _offsets.begin(); it != _offsets.end(); ++it)
for (auto it = _offsets.begin(); it != _offsets.end(); ++it)
{
*it = std::numeric_limits<int>::max();
}
}

Destructible *getInvocatoinHandlerPtrById(unsigned int id) override {
Destructible *getInvocatoinHandlerPtrById(size_t id) override {
unsigned int offset = getOffset(id);
std::shared_ptr<Destructible> ptr = _methodMocks[offset];
return ptr.get();
Expand Down Expand Up @@ -100,7 +100,7 @@ namespace fakeit {
{
}

template<int id, typename R, typename ... arglist>
template<size_t id, typename R, typename ... arglist>
void stubMethod(R(C::*vMethod)(arglist...), MethodInvocationHandler<R, arglist...> *methodInvocationHandler) {
auto offset = VTUtils::getOffset(vMethod);
MethodProxyCreator<R, arglist...> creator;
Expand Down Expand Up @@ -189,7 +189,7 @@ namespace fakeit {
//
std::vector<std::shared_ptr<Destructible>> _methodMocks;
std::vector<std::shared_ptr<Destructible>> _members;
std::vector<unsigned int> _offsets;
std::vector<size_t> _offsets;
InvocationHandlers _invocationHandlers;

FakeObject<C, baseclasses...> &getFake() {
Expand Down
6 changes: 3 additions & 3 deletions include/mockutils/MethodProxy.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand All @@ -16,7 +16,7 @@ namespace fakeit {
return _offset;
}

unsigned int getId() const {
size_t getId() const {
return _id;
}

Expand All @@ -25,7 +25,7 @@ namespace fakeit {
}

private:
unsigned int _id;
size_t _id;
unsigned int _offset;
void *_vMethod;
};
Expand Down
8 changes: 4 additions & 4 deletions include/mockutils/MethodProxyCreator.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand All @@ -29,14 +29,14 @@ namespace fakeit {

public:

template<unsigned int id>
template<size_t id>
MethodProxy createMethodProxy(unsigned int offset) {
return MethodProxy(id, offset, union_cast<void *>(&MethodProxyCreator::methodProxyX < id > ));
}

protected:

R methodProxy(unsigned int id, const typename fakeit::production_arg<arglist>::type... args) {
R methodProxy(size_t id, const typename fakeit::production_arg<arglist>::type... args) {
InvocationHandlerCollection *invocationHandlerCollection = InvocationHandlerCollection::getInvocationHandlerCollection(
this);
MethodInvocationHandler<R, arglist...> *invocationHandler =
Expand All @@ -45,7 +45,7 @@ namespace fakeit {
return invocationHandler->handleMethodInvocation(std::forward<const typename fakeit::production_arg<arglist>::type>(args)...);
}

template<int id>
template<size_t id>
R methodProxyX(arglist ... args) {
return methodProxy(id, std::forward<const typename fakeit::production_arg<arglist>::type>(args)...);
}
Expand Down
2 changes: 1 addition & 1 deletion include/mockutils/VTUtils.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ namespace fakeit {
}

template<typename C>
static unsigned int getVTSize() {
static size_t getVTSize() {
struct Derrived : public C {
virtual void endOfVt() {
}
Expand Down
17 changes: 17 additions & 0 deletions include/mockutils/constexpr_hash.hpp
Original file line number Diff line number Diff line change
@@ -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<size_t N>
constexpr size_t constExprHash(const char(&str)[N]) {
return _constExprHashImpl(str, N);
}

}
6 changes: 3 additions & 3 deletions include/mockutils/mscpp/VirtualTable.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -189,7 +189,7 @@ namespace fakeit {
}

void copyFrom(VirtualTable<C, baseclasses...> &from) {
unsigned int size = VTUtils::getVTSize<C>();
auto size = VTUtils::getVTSize<C>();
for (unsigned int i = 0; i < size; i++) {
_firstMethod[i] = from.getMethod(i);
}
Expand Down Expand Up @@ -233,7 +233,7 @@ namespace fakeit {
setCookie(numOfCookies - 1, method); // use the last cookie
}

unsigned int getSize() {
size_t getSize() {
return VTUtils::getVTSize<C>();
}

Expand All @@ -259,7 +259,7 @@ namespace fakeit {
static const unsigned int numOfCookies = 3;

static void **buildVTArray() {
int vtSize = VTUtils::getVTSize<C>();
auto vtSize = VTUtils::getVTSize<C>();
auto array = new void *[vtSize + numOfCookies + 1]{};
RTTICompleteObjectLocator<C, baseclasses...> *objectLocator = new RTTICompleteObjectLocator<C, baseclasses...>(
typeid(C));
Expand Down
1 change: 1 addition & 0 deletions tests/FakeIt.vcxproj
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@
<ClInclude Include="..\include\mockutils\TupleDispatcher.hpp" />
<ClInclude Include="..\include\mockutils\TuplePrinter.hpp" />
<ClInclude Include="..\include\mockutils\type_utils.hpp" />
<ClInclude Include="..\include\mockutils\constexpr_hash.hpp" />
<ClInclude Include="..\include\mockutils\union_cast.hpp" />
<ClInclude Include="..\include\mockutils\VirtualOffestSelector.hpp" />
<ClInclude Include="..\include\mockutils\VirtualTable.hpp" />
Expand Down
3 changes: 3 additions & 0 deletions tests/all_tests.vcxproj
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,8 @@
<ClCompile Include="miscellaneous_tests.cpp" />
<ClCompile Include="msc_stubbing_multiple_values_tests.cpp" />
<ClCompile Include="msc_type_info_tests.cpp" />
<ClCompile Include="multiple_translation_units_stub_test.cpp" />
<ClCompile Include="multiple_translation_units_stub.cpp" />
<ClCompile Include="overloadded_methods_tests.cpp" />
<ClCompile Include="referece_types_tests.cpp" />
<ClCompile Include="remove_const_volatile_tests.cpp" />
Expand All @@ -151,6 +153,7 @@
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\include\fakeit\ActualInvocationHandler.hpp" />
<ClInclude Include="multiple_translation_units_stub.h" />
<ClInclude Include="tpunit++.hpp" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
Expand Down
12 changes: 12 additions & 0 deletions tests/multiple_translation_units_stub.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
#include "multiple_translation_units_stub.h"


void stubFunc2(fakeit::Mock<SomeInterface>& mock)
{
fakeit::When(Method(mock, func2)).AlwaysReturn<std::string>("String");
}

void stubFunc(fakeit::Mock<SomeInterface>& mock)
{
fakeit::When(Method(mock, func)).AlwaysReturn<int>(3);
}
13 changes: 13 additions & 0 deletions tests/multiple_translation_units_stub.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
#pragma once

#include <string>

#include "fakeit.hpp"

struct SomeInterface {
virtual int func() = 0;
virtual std::string func2() = 0;
};

void stubFunc2(fakeit::Mock<SomeInterface>& mock);
void stubFunc(fakeit::Mock<SomeInterface>& mock);
24 changes: 24 additions & 0 deletions tests/multiple_translation_units_stub_test.cpp
Original file line number Diff line number Diff line change
@@ -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<SomeInterface> mock;
SomeInterface &i = mock.get();

stubFunc2(mock);
When(Method(mock, func)).Return<int>(1);

mock.get().func2(); // Uncatchable write access violation if ids collide
}

} __MultipleTranslationUnitsStub;