Skip to content

Commit

Permalink
Fixed spying on MSVC.
Browse files Browse the repository at this point in the history
  • Loading branch information
FranckRJ committed Apr 2, 2023
1 parent 0cb7a75 commit 7994353
Show file tree
Hide file tree
Showing 3 changed files with 31 additions and 14 deletions.
31 changes: 20 additions & 11 deletions include/fakeit/MockImpl.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@

namespace fakeit {


template<typename C, typename ... baseclasses>
class MockImpl : private MockObject<C>, public virtual ActualInvocationsSource {
public:
Expand Down Expand Up @@ -107,7 +107,7 @@ namespace fakeit {

private:
// Keep members in this order! _proxy should be deleted before _inatanceOwner.
// Not that the dtor of MockImpl calls _proxy.detach(), hence the detach happens
// Not that the dtor of MockImpl calls _proxy.detach(), hence the detach happens
// before the destructor of the _proxy is invoked. As a result the dtor method in the virtual
// table of the fakedObject is reverted to unmockedDtor() before the proxy is deleted.
// This way, any recorded arguments in the proxy that capture the fakeObject itself will
Expand Down Expand Up @@ -172,7 +172,7 @@ namespace fakeit {
protected:

R (C::*_vMethod)(arglist...);

public:
virtual ~MethodMockingContextImpl() = default;

Expand All @@ -182,11 +182,14 @@ namespace fakeit {

template<typename ... T, typename std::enable_if<all_true<smart_is_copy_constructible<T>::value...>::value, int>::type = 0>
std::function<R(arglist&...)> getOriginalMethodCopyArgsInternal(int) {
void *mPtr = MethodMockingContextBase<R, arglist...>::_mock.getOriginalMethod(_vMethod);
auto mPtr = _vMethod;
auto& mock = MethodMockingContextBase<R, arglist...>::_mock;
C * instance = &(MethodMockingContextBase<R, arglist...>::_mock.get());
return [=](arglist&... args) -> R {
auto m = union_cast<typename VTableMethodType<R,arglist...>::type>(mPtr);
return m(instance, args...);
return [=, &mock](arglist&... args) -> R {
// TODO: try to only swap function called and not whole vtable
// TODO: test what happen when spying an object through base class instead of real class
auto vTableSwapper = mock.createRaiiVTableSwapper();
return (instance->*mPtr)(args...);
};
}

Expand All @@ -202,11 +205,12 @@ namespace fakeit {
}

std::function<R(arglist&...)> getOriginalMethodForwardArgs() override {
void *mPtr = MethodMockingContextBase<R, arglist...>::_mock.getOriginalMethod(_vMethod);
auto mPtr = _vMethod;
auto& mock = MethodMockingContextBase<R, arglist...>::_mock;
C * instance = &(MethodMockingContextBase<R, arglist...>::_mock.get());
return [=](arglist&... args) -> R {
auto m = union_cast<typename VTableMethodType<R,arglist...>::type>(mPtr);
return m(instance, std::forward<arglist>(args)...);
return [=, &mock](arglist&... args) -> R {
auto vTableSwapper = mock.createRaiiVTableSwapper();
return (instance->*mPtr)(std::forward<arglist>(args)...);
};
}
};
Expand Down Expand Up @@ -289,6 +293,11 @@ namespace fakeit {
return reinterpret_cast<C *>(fake);
}

Finally createRaiiVTableSwapper() {
_proxy.detach();
return Finally{[&](){_proxy.attach();}};
}

template<typename R, typename ... arglist>
void *getOriginalMethod(R (C::*vMethod)(arglist...)) {
auto vt = _proxy.getOriginalVT();
Expand Down
4 changes: 4 additions & 0 deletions include/mockutils/DynamicProxy.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,10 @@ namespace fakeit {
_invocationHandlers(_methodMocks, _offsets) {
_cloneVt.copyFrom(originalVtHandle.restore());
_cloneVt.setCookie(InvocationHandlerCollection::VtCookieIndex, &_invocationHandlers);
attach();
}

void attach() {
getFake().setVirtualTable(_cloneVt);
}

Expand Down
10 changes: 7 additions & 3 deletions include/mockutils/Finally.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
* Copyright (c) 2014 Eran Pe'er.
*
* This program is made available under the terms of the MIT License.
*
*
* Created on Aug 30, 2014
*/
#pragma once
Expand All @@ -16,15 +16,19 @@ namespace fakeit {
private:
std::function<void()> _finallyClause;

Finally(const Finally &);
Finally(const Finally &) = delete;

Finally &operator=(const Finally &);
Finally &operator=(const Finally &) = delete;

public:
explicit Finally(std::function<void()> f) :
_finallyClause(f) {
}

Finally(Finally&& other) {
_finallyClause.swap(other._finallyClause);
}

~Finally() {
_finallyClause();
}
Expand Down

0 comments on commit 7994353

Please sign in to comment.