Skip to content

Commit 8e4c979

Browse files
committed
Use function pointers (dependent on the mocked function) as id for Method() instead of a hashed value of a counter.
1 parent e91d6b8 commit 8e4c979

14 files changed

+212
-100
lines changed

include/fakeit/Mock.hpp

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -71,63 +71,63 @@ namespace fakeit {
7171
}
7272

7373
// const
74-
template<size_t id, typename R, typename T, typename ... arglist, class = typename std::enable_if<
74+
template<MethodIdType id, typename R, typename T, typename ... arglist, class = typename std::enable_if<
7575
std::is_base_of<T, C>::value>::type>
7676
MockingContext<internal::WithCommonVoid_t<R>, arglist...> stub(R (T::*vMethod)(arglist...) const) {
7777
auto methodWithoutConstVolatile = reinterpret_cast<internal::WithCommonVoid_t<R> (T::*)(arglist...)>(vMethod);
7878
return impl.template stubMethod<id>(methodWithoutConstVolatile);
7979
}
8080

8181
// volatile
82-
template<size_t id, typename R, typename T, typename... arglist, class = typename std::enable_if<
82+
template<MethodIdType id, typename R, typename T, typename... arglist, class = typename std::enable_if<
8383
std::is_base_of<T, C>::value>::type>
8484
MockingContext<internal::WithCommonVoid_t<R>, arglist...> stub(R(T::*vMethod)(arglist...) volatile) {
8585
auto methodWithoutConstVolatile = reinterpret_cast<internal::WithCommonVoid_t<R>(T::*)(arglist...)>(vMethod);
8686
return impl.template stubMethod<id>(methodWithoutConstVolatile);
8787
}
8888

8989
// const volatile
90-
template<size_t id, typename R, typename T, typename... arglist, class = typename std::enable_if<
90+
template<MethodIdType id, typename R, typename T, typename... arglist, class = typename std::enable_if<
9191
std::is_base_of<T, C>::value>::type>
9292
MockingContext<internal::WithCommonVoid_t<R>, arglist...> stub(R(T::*vMethod)(arglist...) const volatile) {
9393
auto methodWithoutConstVolatile = reinterpret_cast<internal::WithCommonVoid_t<R>(T::*)(arglist...)>(vMethod);
9494
return impl.template stubMethod<id>(methodWithoutConstVolatile);
9595
}
9696

9797
// no qualifier
98-
template<size_t id, typename R, typename T, typename... arglist, class = typename std::enable_if<
98+
template<MethodIdType id, typename R, typename T, typename... arglist, class = typename std::enable_if<
9999
std::is_base_of<T, C>::value>::type>
100100
MockingContext<internal::WithCommonVoid_t<R>, arglist...> stub(R(T::*vMethod)(arglist...)) {
101101
auto methodWithoutConstVolatile = reinterpret_cast<internal::WithCommonVoid_t<R>(T::*)(arglist...)>(vMethod);
102102
return impl.template stubMethod<id>(methodWithoutConstVolatile);
103103
}
104104

105105
// ref
106-
template<size_t id, typename R, typename T, typename... arglist, class = typename std::enable_if<
106+
template<MethodIdType id, typename R, typename T, typename... arglist, class = typename std::enable_if<
107107
std::is_base_of<T, C>::value>::type>
108108
MockingContext<internal::WithCommonVoid_t<R>, arglist...> stub(R(T::*vMethod)(arglist...) &) {
109109
auto methodWithoutConstVolatile = reinterpret_cast<internal::WithCommonVoid_t<R>(T::*)(arglist...)>(vMethod);
110110
return impl.template stubMethod<id>(methodWithoutConstVolatile);
111111
}
112112

113113
// const ref
114-
template<size_t id, typename R, typename T, typename... arglist, class = typename std::enable_if<
114+
template<MethodIdType id, typename R, typename T, typename... arglist, class = typename std::enable_if<
115115
std::is_base_of<T, C>::value>::type>
116116
MockingContext<internal::WithCommonVoid_t<R>, arglist...> stub(R(T::*vMethod)(arglist...) const&) {
117117
auto methodWithoutConstVolatile = reinterpret_cast<internal::WithCommonVoid_t<R>(T::*)(arglist...)>(vMethod);
118118
return impl.template stubMethod<id>(methodWithoutConstVolatile);
119119
}
120120

121121
// rval ref
122-
template<size_t id, typename R, typename T, typename... arglist, class = typename std::enable_if<
122+
template<MethodIdType id, typename R, typename T, typename... arglist, class = typename std::enable_if<
123123
std::is_base_of<T, C>::value>::type>
124124
MockingContext<internal::WithCommonVoid_t<R>, arglist...> stub(R(T::*vMethod)(arglist...) &&) {
125125
auto methodWithoutConstVolatile = reinterpret_cast<internal::WithCommonVoid_t<R>(T::*)(arglist...)>(vMethod);
126126
return impl.template stubMethod<id>(methodWithoutConstVolatile);
127127
}
128128

129129
// const rval ref
130-
template<size_t id, typename R, typename T, typename... arglist, class = typename std::enable_if<
130+
template<MethodIdType id, typename R, typename T, typename... arglist, class = typename std::enable_if<
131131
std::is_base_of<T, C>::value>::type>
132132
MockingContext<internal::WithCommonVoid_t<R>, arglist...> stub(R(T::*vMethod)(arglist...) const&&) {
133133
auto methodWithoutConstVolatile = reinterpret_cast<internal::WithCommonVoid_t<R>(T::*)(arglist...)>(vMethod);

include/fakeit/MockImpl.hpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,7 @@ namespace fakeit {
101101
return DataMemberStubbingRoot<T, DataType>();
102102
}
103103

104-
template<size_t id, typename R, typename T, typename ... arglist, class = typename std::enable_if<std::is_base_of<T, C>::value>::type>
104+
template<MethodIdType id, typename R, typename T, typename ... arglist, class = typename std::enable_if<std::is_base_of<T, C>::value>::type>
105105
MockingContext<R, arglist...> stubMethod(R(T::*vMethod)(arglist...)) {
106106
return MockingContext<R, arglist...>(new UniqueMethodMockingContextImpl < id, R, arglist... >
107107
(*this, vMethod));
@@ -226,7 +226,7 @@ namespace fakeit {
226226
};
227227

228228

229-
template<size_t id, typename R, typename ... arglist>
229+
template<MethodIdType id, typename R, typename ... arglist>
230230
class UniqueMethodMockingContextImpl : public MethodMockingContextImpl<R, arglist...> {
231231
protected:
232232

@@ -323,7 +323,7 @@ namespace fakeit {
323323
return origMethodPtr;
324324
}
325325

326-
template<size_t id, typename R, typename ... arglist>
326+
template<MethodIdType id, typename R, typename ... arglist>
327327
RecordedMethodBody<R, arglist...> &stubMethodIfNotStubbed(DynamicProxy<C, baseclasses...> &proxy,
328328
R (C::*vMethod)(arglist...)) {
329329
if (!proxy.isMethodStubbed(vMethod)) {

include/fakeit/Prototype.hpp

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -18,27 +18,27 @@ namespace fakeit {
1818
using RValRefType = R (C::*)(Args...) &&;
1919
using ConstRValRefType = R (C::*)(Args...) const&&;
2020

21-
static Type get(Type t) {
21+
static constexpr Type get(Type t) {
2222
return t;
2323
}
2424

25-
static ConstType getConst(ConstType t) {
25+
static constexpr ConstType getConst(ConstType t) {
2626
return t;
2727
}
2828

29-
static RefType getRef(RefType t) {
29+
static constexpr RefType getRef(RefType t) {
3030
return t;
3131
}
3232

33-
static ConstRefType getConstRef(ConstRefType t) {
33+
static constexpr ConstRefType getConstRef(ConstRefType t) {
3434
return t;
3535
}
3636

37-
static RValRefType getRValRef(RValRefType t) {
37+
static constexpr RValRefType getRValRef(RValRefType t) {
3838
return t;
3939
}
4040

41-
static ConstRValRefType getConstRValRef(ConstRValRefType t) {
41+
static constexpr ConstRValRefType getConstRValRef(ConstRValRefType t) {
4242
return t;
4343
}
4444

include/fakeit/api_macros.hpp

Lines changed: 8 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,11 @@
11
#pragma once
22

3-
#include "mockutils/constexpr_hash.hpp"
3+
#include "mockutils/MethodProxy.hpp"
44

55
#ifdef _MSC_VER
66
#define __func__ __FUNCTION__
77
#endif
88

9-
#define COUNTER_STRINGIFY( counter ) #counter
10-
11-
#define STUB_ID_STR( counter ) \
12-
__FILE__ COUNTER_STRINGIFY(counter)
13-
14-
#define STUB_ID(counter) \
15-
fakeit::constExprHash(STUB_ID_STR(counter))
16-
179
#define MOCK_TYPE(mock) \
1810
std::remove_reference<decltype((mock).get())>::type
1911

@@ -39,25 +31,25 @@
3931
(mock).dtor().setMethodDetails(#mock,"destructor")
4032

4133
#define Method(mock, method) \
42-
(mock).template stub<STUB_ID(__COUNTER__)>(&MOCK_TYPE(mock)::method).setMethodDetails(#mock,#method)
34+
(mock).template stub<&fakeit::funcIdMethod<decltype(&MOCK_TYPE(mock)::method), &MOCK_TYPE(mock)::method>>(&MOCK_TYPE(mock)::method).setMethodDetails(#mock,#method)
4335

4436
#define OverloadedMethod(mock, method, prototype) \
45-
(mock).template stub<STUB_ID(__COUNTER__)>(OVERLOADED_METHOD_PTR( mock , method, prototype )).setMethodDetails(#mock,#method)
37+
(mock).template stub<&fakeit::funcIdMethod<decltype(OVERLOADED_METHOD_PTR( mock , method, prototype )), &MOCK_TYPE(mock)::method>>(OVERLOADED_METHOD_PTR( mock , method, prototype )).setMethodDetails(#mock,#method)
4638

4739
#define ConstOverloadedMethod(mock, method, prototype) \
48-
(mock).template stub<STUB_ID(__COUNTER__)>(CONST_OVERLOADED_METHOD_PTR( mock , method, prototype )).setMethodDetails(#mock,#method)
40+
(mock).template stub<&fakeit::funcIdMethod<decltype(CONST_OVERLOADED_METHOD_PTR( mock , method, prototype )), &MOCK_TYPE(mock)::method>>(CONST_OVERLOADED_METHOD_PTR( mock , method, prototype )).setMethodDetails(#mock,#method)
4941

5042
#define RefOverloadedMethod(mock, method, prototype) \
51-
(mock).template stub<__COUNTER__>(REF_OVERLOADED_METHOD_PTR( mock , method, prototype )).setMethodDetails(#mock,#method)
43+
(mock).template stub<&fakeit::funcIdMethod<decltype(REF_OVERLOADED_METHOD_PTR( mock , method, prototype )), &MOCK_TYPE(mock)::method>>(REF_OVERLOADED_METHOD_PTR( mock , method, prototype )).setMethodDetails(#mock,#method)
5244

5345
#define ConstRefOverloadedMethod(mock, method, prototype) \
54-
(mock).template stub<__COUNTER__>(CONST_REF_OVERLOADED_METHOD_PTR( mock , method, prototype )).setMethodDetails(#mock,#method)
46+
(mock).template stub<&fakeit::funcIdMethod<decltype(CONST_REF_OVERLOADED_METHOD_PTR( mock , method, prototype )), &MOCK_TYPE(mock)::method>>(CONST_REF_OVERLOADED_METHOD_PTR( mock , method, prototype )).setMethodDetails(#mock,#method)
5547

5648
#define RValRefOverloadedMethod(mock, method, prototype) \
57-
(mock).template stub<__COUNTER__>(R_VAL_REF_OVERLOADED_METHOD_PTR( mock , method, prototype )).setMethodDetails(#mock,#method)
49+
(mock).template stub<&fakeit::funcIdMethod<decltype(R_VAL_REF_OVERLOADED_METHOD_PTR( mock , method, prototype )), &MOCK_TYPE(mock)::method>>(R_VAL_REF_OVERLOADED_METHOD_PTR( mock , method, prototype )).setMethodDetails(#mock,#method)
5850

5951
#define ConstRValRefOverloadedMethod(mock, method, prototype) \
60-
(mock).template stub<__COUNTER__>(CONST_R_VAL_REF_OVERLOADED_METHOD_PTR( mock , method, prototype )).setMethodDetails(#mock,#method)
52+
(mock).template stub<&fakeit::funcIdMethod<decltype(CONST_R_VAL_REF_OVERLOADED_METHOD_PTR( mock , method, prototype )), &MOCK_TYPE(mock)::method>>(CONST_R_VAL_REF_OVERLOADED_METHOD_PTR( mock , method, prototype )).setMethodDetails(#mock,#method)
6153

6254
#define Verify(...) \
6355
Verify( __VA_ARGS__ ).setFileInfo(__FILE__, __LINE__, __func__)

include/mockutils/DynamicProxy.hpp

Lines changed: 10 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -13,10 +13,8 @@
1313
#include <vector>
1414
#include <array>
1515
#include <new>
16-
#include <limits>
1716

1817
#include "mockutils/VirtualTable.hpp"
19-
#include "mockutils/union_cast.hpp"
2018
#include "mockutils/MethodInvocationHandler.hpp"
2119
#include "mockutils/VTUtils.hpp"
2220
#include "mockutils/FakeObject.hpp"
@@ -28,9 +26,9 @@ namespace fakeit {
2826

2927
class InvocationHandlers : public InvocationHandlerCollection {
3028
std::vector<std::shared_ptr<Destructible>> &_methodMocks;
31-
std::vector<size_t> &_offsets;
29+
std::vector<MethodIdType> &_offsets;
3230

33-
unsigned int getOffset(size_t id) const
31+
unsigned int getOffset(MethodIdType id) const
3432
{
3533
unsigned int offset = 0;
3634
for (; offset < _offsets.size(); offset++) {
@@ -42,11 +40,11 @@ namespace fakeit {
4240
}
4341

4442
public:
45-
InvocationHandlers(std::vector<std::shared_ptr<Destructible>> &methodMocks, std::vector<size_t> &offsets)
43+
InvocationHandlers(std::vector<std::shared_ptr<Destructible>> &methodMocks, std::vector<MethodIdType> &offsets)
4644
: _methodMocks(methodMocks), _offsets(offsets) {
4745
}
4846

49-
Destructible *getInvocatoinHandlerPtrById(size_t id) override {
47+
Destructible *getInvocatoinHandlerPtrById(MethodIdType id) override {
5048
unsigned int offset = getOffset(id);
5149
std::shared_ptr<Destructible> ptr = _methodMocks[offset];
5250
return ptr.get();
@@ -62,7 +60,7 @@ namespace fakeit {
6260
DynamicProxy(C &inst) :
6361
_instancePtr(&inst),
6462
_methodMocks(VTUtils::getVTSize<C>()),
65-
_offsets(VTUtils::getVTSize<C>(), std::numeric_limits<int>::max()),
63+
_offsets(VTUtils::getVTSize<C>(), &funcIdNotStubbed),
6664
_invocationHandlers(_methodMocks, _offsets) {
6765
_originalVt.copyFrom(VirtualTable<C, baseclasses...>::getVTable(*_instancePtr));
6866
_originalVt.setCookie(InvocationHandlerCollection::VtCookieIndex, &_invocationHandlers);
@@ -108,11 +106,11 @@ namespace fakeit {
108106
{
109107
}
110108

111-
template<size_t id, typename R, typename ... arglist>
109+
template<MethodIdType id, typename R, typename ... arglist>
112110
void stubMethod(R(C::*vMethod)(arglist...), MethodInvocationHandler<R, arglist...> *methodInvocationHandler) {
113111
auto offset = VTUtils::getOffset(vMethod);
114112
MethodProxyCreator<R, arglist...> creator;
115-
bind(creator.template createMethodProxy<id + 1>(offset), methodInvocationHandler);
113+
bind(creator.template createMethodProxy<id>(offset), methodInvocationHandler);
116114
}
117115

118116
void stubDtor(MethodInvocationHandler<void> *methodInvocationHandler) {
@@ -125,9 +123,9 @@ namespace fakeit {
125123
// For GCC / Clang, the destructor is directly called, like normal methods, so we use the member-function
126124
// version.
127125
#ifdef _MSC_VER
128-
bindDtor(creator.createMethodProxyStatic<0>(offset), methodInvocationHandler);
126+
bindDtor(creator.createMethodProxyStatic<&funcIdDestructor>(offset), methodInvocationHandler);
129127
#else
130-
bindDtor(creator.createMethodProxy<0>(offset), methodInvocationHandler);
128+
bindDtor(creator.createMethodProxy<&funcIdDestructor>(offset), methodInvocationHandler);
131129
#endif
132130
}
133131

@@ -217,7 +215,7 @@ namespace fakeit {
217215
//
218216
std::vector<std::shared_ptr<Destructible>> _methodMocks;
219217
std::vector<std::shared_ptr<Destructible>> _members;
220-
std::vector<size_t> _offsets;
218+
std::vector<MethodIdType> _offsets;
221219
InvocationHandlers _invocationHandlers;
222220

223221
FakeObject<C, baseclasses...> &getFake() {

include/mockutils/MethodProxy.hpp

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,23 @@
44

55
namespace fakeit {
66

7+
// A bunch of functions used by the method id mechanism. We use a pointer to them to represent the ID of a unique
8+
// mockable method.
9+
// Those methods are never called, we only use their address, this is why they are excluded from code coverage analysis.
10+
/* LCOV_EXCL_START */
11+
template<typename MethodPtrType, MethodPtrType MethodPtr>
12+
void funcIdMethod() {}
13+
14+
inline void funcIdDestructor() {}
15+
16+
inline void funcIdNotStubbed() {}
17+
/* LCOV_EXCL_STOP */
18+
19+
using MethodIdType = void(*)();
20+
721
struct MethodProxy {
822

9-
MethodProxy(size_t id, unsigned int offset, void *vMethod) :
23+
MethodProxy(MethodIdType id, unsigned int offset, void *vMethod) :
1024
_id(id),
1125
_offset(offset),
1226
_vMethod(vMethod) {
@@ -16,7 +30,7 @@ namespace fakeit {
1630
return _offset;
1731
}
1832

19-
size_t getId() const {
33+
MethodIdType getId() const {
2034
return _id;
2135
}
2236

@@ -25,8 +39,8 @@ namespace fakeit {
2539
}
2640

2741
private:
28-
size_t _id;
42+
MethodIdType _id;
2943
unsigned int _offset;
3044
void *_vMethod;
3145
};
32-
}
46+
}

include/mockutils/MethodProxyCreator.hpp

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ namespace fakeit {
1111
struct InvocationHandlerCollection {
1212
static const unsigned int VtCookieIndex = 0;
1313

14-
virtual Destructible *getInvocatoinHandlerPtrById(size_t index) = 0;
14+
virtual Destructible *getInvocatoinHandlerPtrById(MethodIdType id) = 0;
1515

1616
static InvocationHandlerCollection *getInvocationHandlerCollection(void *instance) {
1717
VirtualTableBase &vt = VirtualTableBase::getVTable(instance);
@@ -29,19 +29,19 @@ namespace fakeit {
2929

3030
public:
3131

32-
template<size_t id>
32+
template<MethodIdType id>
3333
MethodProxy createMethodProxy(unsigned int offset) {
3434
return MethodProxy(id, offset, union_cast<void *>(&MethodProxyCreator::methodProxyX < id > ));
3535
}
3636

37-
template<unsigned int id>
37+
template<MethodIdType id>
3838
MethodProxy createMethodProxyStatic(unsigned int offset) {
3939
return MethodProxy(id, offset, union_cast<void *>(&MethodProxyCreator::methodProxyXStatic < id > ));
4040
}
4141

4242
protected:
4343

44-
R methodProxy(size_t id, const typename fakeit::production_arg<arglist>::type... args) {
44+
R methodProxy(MethodIdType id, const typename fakeit::production_arg<arglist>::type... args) {
4545
InvocationHandlerCollection *invocationHandlerCollection = InvocationHandlerCollection::getInvocationHandlerCollection(
4646
this);
4747
MethodInvocationHandler<R, arglist...> *invocationHandler =
@@ -50,12 +50,12 @@ namespace fakeit {
5050
return invocationHandler->handleMethodInvocation(std::forward<const typename fakeit::production_arg<arglist>::type>(args)...);
5151
}
5252

53-
template<size_t id>
53+
template<MethodIdType id>
5454
R methodProxyX(arglist ... args) {
5555
return methodProxy(id, std::forward<const typename fakeit::production_arg<arglist>::type>(args)...);
5656
}
5757

58-
static R methodProxyStatic(void* instance, unsigned int id, const typename fakeit::production_arg<arglist>::type... args) {
58+
static R methodProxyStatic(void* instance, MethodIdType id, const typename fakeit::production_arg<arglist>::type... args) {
5959
InvocationHandlerCollection *invocationHandlerCollection = InvocationHandlerCollection::getInvocationHandlerCollection(
6060
instance);
6161
MethodInvocationHandler<R, arglist...> *invocationHandler =
@@ -64,7 +64,7 @@ namespace fakeit {
6464
return invocationHandler->handleMethodInvocation(std::forward<const typename fakeit::production_arg<arglist>::type>(args)...);
6565
}
6666

67-
template<int id>
67+
template<MethodIdType id>
6868
static R methodProxyXStatic(void* instance, arglist ... args) {
6969
return methodProxyStatic(instance, id, std::forward<const typename fakeit::production_arg<arglist>::type>(args)...);
7070
}

include/mockutils/VTUtils.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ namespace fakeit {
6565
}
6666

6767
template<typename C>
68-
static size_t getVTSize() {
68+
static unsigned int getVTSize() {
6969
struct Derrived : public C {
7070
virtual void endOfVt() {
7171
}

include/mockutils/constexpr_hash.hpp

Lines changed: 0 additions & 17 deletions
This file was deleted.

0 commit comments

Comments
 (0)