Skip to content

Commit 4c4924c

Browse files
authored
Merge pull request #336 from eranpeer/otrempe-Fix-CollidingMockingContextIds
Fix colliding mocking context ids (rebased)
2 parents 54b2af5 + 7116221 commit 4c4924c

21 files changed

+424
-56
lines changed

.github/workflows/ci_linux_clang.yml

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,14 @@ jobs:
1616
fail-fast: false
1717
matrix:
1818
config:
19+
- {
20+
name: "Ubuntu 22.04 Clang 13 C++11 with cross-translation units mocks",
21+
os: ubuntu-22.04,
22+
build_type: Debug,
23+
cc: "clang-13", cxx: "clang++-13",
24+
cxx_standard: 11,
25+
additional_parameters: "-DENABLE_FAKEIT_CROSS_TRANSLATION_UNITS_MOCKS_IN_TESTS=ON"
26+
}
1927
- {
2028
name: "Ubuntu 22.04 Clang 13",
2129
os: ubuntu-22.04,
@@ -88,6 +96,14 @@ jobs:
8896
cc: "clang-18", cxx: "clang++-18",
8997
cxx_standard: 26
9098
}
99+
- {
100+
name: "Ubuntu 24.04 Clang 18 C++26 with cross-translation units mocks",
101+
os: ubuntu-24.04,
102+
build_type: Debug,
103+
cc: "clang-18", cxx: "clang++-18",
104+
cxx_standard: 26,
105+
additional_parameters: "-DENABLE_FAKEIT_CROSS_TRANSLATION_UNITS_MOCKS_IN_TESTS=ON"
106+
}
91107
- {
92108
name: "Ubuntu 24.04 Clang with sanitizers",
93109
os: ubuntu-24.04,
@@ -107,7 +123,8 @@ jobs:
107123
-DENABLE_TESTING=ON \
108124
-DWARNINGS_AS_ERRORS_FOR_TESTS=ON \
109125
-DOVERRIDE_CXX_STANDARD_FOR_TESTS=${{ matrix.config.cxx_standard }} \
110-
-DENABLE_SANITIZERS_IN_TESTS=${{ matrix.config.enable_sanitizers_in_tests }}
126+
-DENABLE_SANITIZERS_IN_TESTS=${{ matrix.config.enable_sanitizers_in_tests }} \
127+
${{ matrix.config.additional_parameters }}
111128
cmake --build build -j
112129
- name: Run tests
113130
run: |

.github/workflows/ci_linux_gcc.yml

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,14 @@ jobs:
1616
fail-fast: false
1717
matrix:
1818
config:
19+
- {
20+
name: "Ubuntu 22.04 GCC 10 C++11 with cross-translation units mocks",
21+
os: ubuntu-22.04,
22+
build_type: Debug,
23+
cc: "gcc-10", cxx: "g++-10",
24+
cxx_standard: 11,
25+
additional_parameters: "-DENABLE_FAKEIT_CROSS_TRANSLATION_UNITS_MOCKS_IN_TESTS=ON"
26+
}
1927
- {
2028
name: "Ubuntu 22.04 GCC 10",
2129
os: ubuntu-22.04,
@@ -82,6 +90,14 @@ jobs:
8290
cc: "gcc-14", cxx: "g++-14",
8391
cxx_standard: 26
8492
}
93+
- {
94+
name: "Ubuntu 24.04 GCC 14 C++26 with cross-translation units mocks",
95+
os: ubuntu-24.04,
96+
build_type: Debug,
97+
cc: "gcc-14", cxx: "g++-14",
98+
cxx_standard: 26,
99+
additional_parameters: "-DENABLE_FAKEIT_CROSS_TRANSLATION_UNITS_MOCKS_IN_TESTS=ON"
100+
}
85101
- {
86102
name: "Ubuntu 24.04 GCC with sanitizers",
87103
os: ubuntu-24.04,
@@ -101,7 +117,8 @@ jobs:
101117
-DENABLE_TESTING=ON \
102118
-DWARNINGS_AS_ERRORS_FOR_TESTS=ON \
103119
-DOVERRIDE_CXX_STANDARD_FOR_TESTS=${{ matrix.config.cxx_standard }} \
104-
-DENABLE_SANITIZERS_IN_TESTS=${{ matrix.config.enable_sanitizers_in_tests }}
120+
-DENABLE_SANITIZERS_IN_TESTS=${{ matrix.config.enable_sanitizers_in_tests }} \
121+
${{ matrix.config.additional_parameters }}
105122
cmake --build build -j
106123
- name: Run tests
107124
run: |

.github/workflows/ci_macos_appleclang.yml

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,13 @@ jobs:
1616
fail-fast: false
1717
matrix:
1818
config:
19+
- {
20+
name: "macOS 14 AppleClang 15 C++11 with cross-translation units mocks",
21+
os: macos-14,
22+
build_type: Debug,
23+
cxx_standard: 11,
24+
additional_parameters: "-DENABLE_FAKEIT_CROSS_TRANSLATION_UNITS_MOCKS_IN_TESTS=ON"
25+
}
1926
- {
2027
name: "macOS 14 AppleClang 15 C++11",
2128
os: macos-14,
@@ -64,6 +71,13 @@ jobs:
6471
build_type: Debug,
6572
cxx_standard: 26
6673
}
74+
- {
75+
name: "macOS 15 AppleClang 17 C++26 with cross-translation units mocks",
76+
os: macos-15,
77+
build_type: Debug,
78+
cxx_standard: 26,
79+
additional_parameters: "-DENABLE_FAKEIT_CROSS_TRANSLATION_UNITS_MOCKS_IN_TESTS=ON"
80+
}
6781
- {
6882
name: "macOS 15 AppleClang with sanitizers",
6983
os: macos-15,
@@ -80,7 +94,8 @@ jobs:
8094
-DENABLE_TESTING=ON \
8195
-DWARNINGS_AS_ERRORS_FOR_TESTS=ON \
8296
-DOVERRIDE_CXX_STANDARD_FOR_TESTS=${{ matrix.config.cxx_standard }} \
83-
-DENABLE_SANITIZERS_IN_TESTS=${{ matrix.config.enable_sanitizers_in_tests }}
97+
-DENABLE_SANITIZERS_IN_TESTS=${{ matrix.config.enable_sanitizers_in_tests }} \
98+
${{ matrix.config.additional_parameters }}
8499
cmake --build build -j
85100
- name: Run tests
86101
run: |

.github/workflows/ci_windows_msvc.yml

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,15 @@ jobs:
1616
fail-fast: false
1717
matrix:
1818
config:
19+
- {
20+
name: "Windows 2022 MSVC 2022 Win32 C++11 with cross-translation units mocks",
21+
os: windows-2022,
22+
build_type: Debug,
23+
generator: "Visual Studio 17 2022",
24+
architecture: "Win32",
25+
cxx_standard: 11,
26+
additional_parameters: "-DENABLE_FAKEIT_CROSS_TRANSLATION_UNITS_MOCKS_IN_TESTS=ON"
27+
}
1928
- {
2029
name: "Windows 2022 MSVC 2022 Win32",
2130
os: windows-2022,
@@ -126,6 +135,15 @@ jobs:
126135
architecture: "x64",
127136
cxx_standard: 26
128137
}
138+
- {
139+
name: "Windows 2025 MSVC 2022 x64 C++26 with cross-translation units mocks",
140+
os: windows-2025,
141+
build_type: Debug,
142+
generator: "Visual Studio 17 2022",
143+
architecture: "x64",
144+
cxx_standard: 26,
145+
additional_parameters: "-DENABLE_FAKEIT_CROSS_TRANSLATION_UNITS_MOCKS_IN_TESTS=ON"
146+
}
129147
steps:
130148
- uses: actions/checkout@v3
131149
- name: Build project
@@ -135,7 +153,8 @@ jobs:
135153
-A ${{ matrix.config.architecture }} \
136154
-DENABLE_TESTING=ON \
137155
-DWARNINGS_AS_ERRORS_FOR_TESTS=ON \
138-
-DOVERRIDE_CXX_STANDARD_FOR_TESTS=${{ matrix.config.cxx_standard }}
156+
-DOVERRIDE_CXX_STANDARD_FOR_TESTS=${{ matrix.config.cxx_standard }} \
157+
${{ matrix.config.additional_parameters }}
139158
cmake --build build --config ${{ matrix.config.build_type }} -j
140159
- name: Run tests
141160
run: |

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,3 +70,6 @@ Testing/
7070

7171
# Benchmark
7272
/benchmark/bench*/
73+
74+
# Cache
75+
/.cache

CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ set(OVERRIDE_CXX_STANDARD_FOR_TESTS "" CACHE STRING "Override the C++ standard u
88
option(WARNINGS_AS_ERRORS_FOR_TESTS "Treat warnings as errors when building tests." OFF)
99
option(ENABLE_SANITIZERS_IN_TESTS "Enable address / undefined sanitizers in tests." OFF)
1010
option(ENABLE_COVERAGE "Enable coverage reporting for gcc/clang." OFF)
11+
option(ENABLE_FAKEIT_CROSS_TRANSLATION_UNITS_MOCKS_IN_TESTS "Enable cross-translation units mocks in tests." OFF)
1112

1213
# Directory containing main targets of FakeIt.
1314
add_subdirectory(include)

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<int id, typename R, typename T, typename ... arglist, class = typename std::enable_if<
74+
template<size_t 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<int id, typename R, typename T, typename... arglist, class = typename std::enable_if<
82+
template<size_t 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<int id, typename R, typename T, typename... arglist, class = typename std::enable_if<
90+
template<size_t 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<int id, typename R, typename T, typename... arglist, class = typename std::enable_if<
98+
template<size_t 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<int id, typename R, typename T, typename... arglist, class = typename std::enable_if<
106+
template<size_t 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<int id, typename R, typename T, typename... arglist, class = typename std::enable_if<
114+
template<size_t 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<int id, typename R, typename T, typename... arglist, class = typename std::enable_if<
122+
template<size_t 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<int id, typename R, typename T, typename... arglist, class = typename std::enable_if<
130+
template<size_t 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<int id, typename R, typename T, typename ... arglist, class = typename std::enable_if<std::is_base_of<T, C>::value>::type>
104+
template<size_t 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<int id, typename R, typename ... arglist>
229+
template<size_t 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<unsigned int id, typename R, typename ... arglist>
326+
template<size_t 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/api_macros.hpp

Lines changed: 22 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,24 @@
11
#pragma once
22

3+
#include "mockutils/constexpr_hash.hpp"
4+
35
#ifdef _MSC_VER
46
#define __func__ __FUNCTION__
57
#endif
68

9+
#define COUNTER_STRINGIFY( counter ) #counter
10+
11+
#define STUB_ID_STR( counter ) \
12+
__FILE__ COUNTER_STRINGIFY(counter)
13+
14+
#ifdef FAKEIT_CROSS_TRANSLATION_UNITS_MOCKS
15+
#define STUB_ID(counter) \
16+
fakeit::constExprHash(STUB_ID_STR(counter))
17+
#else
18+
#define STUB_ID(counter) \
19+
counter
20+
#endif
21+
722
#define MOCK_TYPE(mock) \
823
std::remove_reference<decltype((mock).get())>::type
924

@@ -29,25 +44,25 @@
2944
(mock).dtor().setMethodDetails(#mock,"destructor")
3045

3146
#define Method(mock, method) \
32-
(mock).template stub<__COUNTER__>(&MOCK_TYPE(mock)::method).setMethodDetails(#mock,#method)
47+
(mock).template stub<STUB_ID(__COUNTER__)>(&MOCK_TYPE(mock)::method).setMethodDetails(#mock,#method)
3348

3449
#define OverloadedMethod(mock, method, prototype) \
35-
(mock).template stub<__COUNTER__>(OVERLOADED_METHOD_PTR( mock , method, prototype )).setMethodDetails(#mock,#method)
50+
(mock).template stub<STUB_ID(__COUNTER__)>(OVERLOADED_METHOD_PTR( mock , method, prototype )).setMethodDetails(#mock,#method)
3651

3752
#define ConstOverloadedMethod(mock, method, prototype) \
38-
(mock).template stub<__COUNTER__>(CONST_OVERLOADED_METHOD_PTR( mock , method, prototype )).setMethodDetails(#mock,#method)
53+
(mock).template stub<STUB_ID(__COUNTER__)>(CONST_OVERLOADED_METHOD_PTR( mock , method, prototype )).setMethodDetails(#mock,#method)
3954

4055
#define RefOverloadedMethod(mock, method, prototype) \
41-
(mock).template stub<__COUNTER__>(REF_OVERLOADED_METHOD_PTR( mock , method, prototype )).setMethodDetails(#mock,#method)
56+
(mock).template stub<STUB_ID(__COUNTER__)>(REF_OVERLOADED_METHOD_PTR( mock , method, prototype )).setMethodDetails(#mock,#method)
4257

4358
#define ConstRefOverloadedMethod(mock, method, prototype) \
44-
(mock).template stub<__COUNTER__>(CONST_REF_OVERLOADED_METHOD_PTR( mock , method, prototype )).setMethodDetails(#mock,#method)
59+
(mock).template stub<STUB_ID(__COUNTER__)>(CONST_REF_OVERLOADED_METHOD_PTR( mock , method, prototype )).setMethodDetails(#mock,#method)
4560

4661
#define RValRefOverloadedMethod(mock, method, prototype) \
47-
(mock).template stub<__COUNTER__>(R_VAL_REF_OVERLOADED_METHOD_PTR( mock , method, prototype )).setMethodDetails(#mock,#method)
62+
(mock).template stub<STUB_ID(__COUNTER__)>(R_VAL_REF_OVERLOADED_METHOD_PTR( mock , method, prototype )).setMethodDetails(#mock,#method)
4863

4964
#define ConstRValRefOverloadedMethod(mock, method, prototype) \
50-
(mock).template stub<__COUNTER__>(CONST_R_VAL_REF_OVERLOADED_METHOD_PTR( mock , method, prototype )).setMethodDetails(#mock,#method)
65+
(mock).template stub<STUB_ID(__COUNTER__)>(CONST_R_VAL_REF_OVERLOADED_METHOD_PTR( mock , method, prototype )).setMethodDetails(#mock,#method)
5166

5267
#define Verify(...) \
5368
Verify( __VA_ARGS__ ).setFileInfo(__FILE__, __LINE__, __func__)

0 commit comments

Comments
 (0)