Skip to content

Commit

Permalink
Merge remote-tracking branch 'otrempe-fakeit/Fix-CollidingMockingCont…
Browse files Browse the repository at this point in the history
…extIds' into otrempe-Fix-CollidingMockingContextIds
  • Loading branch information
FranckRJ committed May 11, 2024
2 parents c1d74ea + 2230a37 commit e91d6b8
Show file tree
Hide file tree
Showing 13 changed files with 109 additions and 31 deletions.
16 changes: 8 additions & 8 deletions include/fakeit/Mock.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -71,63 +71,63 @@ namespace fakeit {
}

// const
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_base_of<T, C>::value>::type>
MockingContext<internal::WithCommonVoid_t<R>, arglist...> stub(R (T::*vMethod)(arglist...) const) {
auto methodWithoutConstVolatile = reinterpret_cast<internal::WithCommonVoid_t<R> (T::*)(arglist...)>(vMethod);
return impl.template stubMethod<id>(methodWithoutConstVolatile);
}

// volatile
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_base_of<T, C>::value>::type>
MockingContext<internal::WithCommonVoid_t<R>, arglist...> stub(R(T::*vMethod)(arglist...) volatile) {
auto methodWithoutConstVolatile = reinterpret_cast<internal::WithCommonVoid_t<R>(T::*)(arglist...)>(vMethod);
return impl.template stubMethod<id>(methodWithoutConstVolatile);
}

// const volatile
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_base_of<T, C>::value>::type>
MockingContext<internal::WithCommonVoid_t<R>, arglist...> stub(R(T::*vMethod)(arglist...) const volatile) {
auto methodWithoutConstVolatile = reinterpret_cast<internal::WithCommonVoid_t<R>(T::*)(arglist...)>(vMethod);
return impl.template stubMethod<id>(methodWithoutConstVolatile);
}

// no qualifier
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_base_of<T, C>::value>::type>
MockingContext<internal::WithCommonVoid_t<R>, arglist...> stub(R(T::*vMethod)(arglist...)) {
auto methodWithoutConstVolatile = reinterpret_cast<internal::WithCommonVoid_t<R>(T::*)(arglist...)>(vMethod);
return impl.template stubMethod<id>(methodWithoutConstVolatile);
}

// ref
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_base_of<T, C>::value>::type>
MockingContext<internal::WithCommonVoid_t<R>, arglist...> stub(R(T::*vMethod)(arglist...) &) {
auto methodWithoutConstVolatile = reinterpret_cast<internal::WithCommonVoid_t<R>(T::*)(arglist...)>(vMethod);
return impl.template stubMethod<id>(methodWithoutConstVolatile);
}

// const ref
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_base_of<T, C>::value>::type>
MockingContext<internal::WithCommonVoid_t<R>, arglist...> stub(R(T::*vMethod)(arglist...) const&) {
auto methodWithoutConstVolatile = reinterpret_cast<internal::WithCommonVoid_t<R>(T::*)(arglist...)>(vMethod);
return impl.template stubMethod<id>(methodWithoutConstVolatile);
}

// rval ref
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_base_of<T, C>::value>::type>
MockingContext<internal::WithCommonVoid_t<R>, arglist...> stub(R(T::*vMethod)(arglist...) &&) {
auto methodWithoutConstVolatile = reinterpret_cast<internal::WithCommonVoid_t<R>(T::*)(arglist...)>(vMethod);
return impl.template stubMethod<id>(methodWithoutConstVolatile);
}

// const rval ref
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_base_of<T, C>::value>::type>
MockingContext<internal::WithCommonVoid_t<R>, arglist...> stub(R(T::*vMethod)(arglist...) const&&) {
auto methodWithoutConstVolatile = reinterpret_cast<internal::WithCommonVoid_t<R>(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 @@ -101,7 +101,7 @@ namespace fakeit {
return DataMemberStubbingRoot<T, DataType>();
}

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 @@ -226,7 +226,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 @@ -323,7 +323,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 @@ -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<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 RefOverloadedMethod(mock, method, prototype) \
(mock).template stub<__COUNTER__>(REF_OVERLOADED_METHOD_PTR( mock , method, prototype )).setMethodDetails(#mock,#method)
Expand Down
12 changes: 6 additions & 6 deletions include/mockutils/DynamicProxy.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,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 @@ -42,11 +42,11 @@ namespace fakeit {
}

public:
InvocationHandlers(std::vector<std::shared_ptr<Destructible>> &methodMocks, std::vector<unsigned int> &offsets)
InvocationHandlers(std::vector<std::shared_ptr<Destructible>> &methodMocks, std::vector<size_t> &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<Destructible> ptr = _methodMocks[offset];
return ptr.get();
Expand Down Expand Up @@ -108,7 +108,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 @@ -217,7 +217,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 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);
Expand All @@ -29,7 +29,7 @@ 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 > ));
}
Expand All @@ -41,7 +41,7 @@ namespace fakeit {

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 @@ -50,7 +50,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 @@ -65,7 +65,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 @@ -178,7 +178,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 @@ -234,7 +234,7 @@ namespace fakeit {
setCookie(dtorCookieIndex, method);
}

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

Expand All @@ -256,7 +256,7 @@ namespace fakeit {
static const unsigned int dtorCookieIndex = numOfCookies - 1; // use the last cookie

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
2 changes: 2 additions & 0 deletions tests/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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
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;

0 comments on commit e91d6b8

Please sign in to comment.