1 | #ifndef THIRD_PARTY_GOOGLETEST_GOOGLEMOCK_INCLUDE_GMOCK_INTERNAL_GMOCK_FUNCTION_MOCKER_H_ // NOLINT |
2 | #define THIRD_PARTY_GOOGLETEST_GOOGLEMOCK_INCLUDE_GMOCK_INTERNAL_GMOCK_FUNCTION_MOCKER_H_ // NOLINT |
3 | |
4 | #include "gmock/gmock-generated-function-mockers.h" // NOLINT |
5 | #include "gmock/internal/gmock-pp.h" |
6 | |
7 | #define MOCK_METHOD(...) \ |
8 | GMOCK_PP_VARIADIC_CALL(GMOCK_INTERNAL_MOCK_METHOD_ARG_, __VA_ARGS__) |
9 | |
10 | #define GMOCK_INTERNAL_MOCK_METHOD_ARG_1(...) \ |
11 | GMOCK_INTERNAL_WRONG_ARITY(__VA_ARGS__) |
12 | |
13 | #define GMOCK_INTERNAL_MOCK_METHOD_ARG_2(...) \ |
14 | GMOCK_INTERNAL_WRONG_ARITY(__VA_ARGS__) |
15 | |
16 | #define GMOCK_INTERNAL_MOCK_METHOD_ARG_3(_Ret, _MethodName, _Args) \ |
17 | GMOCK_INTERNAL_MOCK_METHOD_ARG_4(_Ret, _MethodName, _Args, ()) |
18 | |
19 | #define GMOCK_INTERNAL_MOCK_METHOD_ARG_4(_Ret, _MethodName, _Args, _Spec) \ |
20 | GMOCK_INTERNAL_ASSERT_PARENTHESIS(_Args); \ |
21 | GMOCK_INTERNAL_ASSERT_PARENTHESIS(_Spec); \ |
22 | GMOCK_INTERNAL_ASSERT_VALID_SIGNATURE( \ |
23 | GMOCK_PP_NARG0 _Args, GMOCK_INTERNAL_SIGNATURE(_Ret, _Args)); \ |
24 | GMOCK_INTERNAL_ASSERT_VALID_SPEC(_Spec) \ |
25 | GMOCK_INTERNAL_MOCK_METHOD_IMPL( \ |
26 | GMOCK_PP_NARG0 _Args, _MethodName, GMOCK_INTERNAL_HAS_CONST(_Spec), \ |
27 | GMOCK_INTERNAL_HAS_OVERRIDE(_Spec), GMOCK_INTERNAL_HAS_FINAL(_Spec), \ |
28 | GMOCK_INTERNAL_HAS_NOEXCEPT(_Spec), GMOCK_INTERNAL_GET_CALLTYPE(_Spec), \ |
29 | (GMOCK_INTERNAL_SIGNATURE(_Ret, _Args))) |
30 | |
31 | #define GMOCK_INTERNAL_MOCK_METHOD_ARG_5(...) \ |
32 | GMOCK_INTERNAL_WRONG_ARITY(__VA_ARGS__) |
33 | |
34 | #define GMOCK_INTERNAL_MOCK_METHOD_ARG_6(...) \ |
35 | GMOCK_INTERNAL_WRONG_ARITY(__VA_ARGS__) |
36 | |
37 | #define GMOCK_INTERNAL_MOCK_METHOD_ARG_7(...) \ |
38 | GMOCK_INTERNAL_WRONG_ARITY(__VA_ARGS__) |
39 | |
40 | #define GMOCK_INTERNAL_WRONG_ARITY(...) \ |
41 | static_assert( \ |
42 | false, \ |
43 | "MOCK_METHOD must be called with 3 or 4 arguments. _Ret, " \ |
44 | "_MethodName, _Args and optionally _Spec. _Args and _Spec must be " \ |
45 | "enclosed in parentheses. If _Ret is a type with unprotected commas, " \ |
46 | "it must also be enclosed in parentheses.") |
47 | |
48 | #define GMOCK_INTERNAL_ASSERT_PARENTHESIS(_Tuple) \ |
49 | static_assert( \ |
50 | GMOCK_PP_IS_ENCLOSED_PARENS(_Tuple), \ |
51 | GMOCK_PP_STRINGIZE(_Tuple) " should be enclosed in parentheses.") |
52 | |
53 | #define GMOCK_INTERNAL_ASSERT_VALID_SIGNATURE(_N, ...) \ |
54 | static_assert( \ |
55 | std::is_function<__VA_ARGS__>::value, \ |
56 | "Signature must be a function type, maybe return type contains " \ |
57 | "unprotected comma."); \ |
58 | static_assert( \ |
59 | ::testing::tuple_size<typename ::testing::internal::Function< \ |
60 | __VA_ARGS__>::ArgumentTuple>::value == _N, \ |
61 | "This method does not take " GMOCK_PP_STRINGIZE( \ |
62 | _N) " arguments. Parenthesize all types with unproctected commas.") |
63 | |
64 | #define GMOCK_INTERNAL_ASSERT_VALID_SPEC(_Spec) \ |
65 | GMOCK_PP_FOR_EACH(GMOCK_INTERNAL_ASSERT_VALID_SPEC_ELEMENT, ~, _Spec) |
66 | |
67 | #define GMOCK_INTERNAL_MOCK_METHOD_IMPL(_N, _MethodName, _Constness, \ |
68 | _Override, _Final, _Noexcept, \ |
69 | _CallType, _Signature) \ |
70 | typename ::testing::internal::Function<GMOCK_PP_REMOVE_PARENS( \ |
71 | _Signature)>::Result \ |
72 | GMOCK_INTERNAL_EXPAND(_CallType) \ |
73 | _MethodName(GMOCK_PP_REPEAT(GMOCK_INTERNAL_PARAMETER, _Signature, _N)) \ |
74 | GMOCK_PP_IF(_Constness, const, ) GMOCK_PP_IF(_Noexcept, noexcept, ) \ |
75 | GMOCK_PP_IF(_Override, override, ) \ |
76 | GMOCK_PP_IF(_Final, final, ) { \ |
77 | GMOCK_MOCKER_(_N, _Constness, _MethodName) \ |
78 | .SetOwnerAndName(this, #_MethodName); \ |
79 | return GMOCK_MOCKER_(_N, _Constness, _MethodName) \ |
80 | .Invoke(GMOCK_PP_REPEAT(GMOCK_INTERNAL_FORWARD_ARG, _Signature, _N)); \ |
81 | } \ |
82 | ::testing::MockSpec<GMOCK_PP_REMOVE_PARENS(_Signature)> gmock_##_MethodName( \ |
83 | GMOCK_PP_REPEAT(GMOCK_INTERNAL_MATCHER_PARAMETER, _Signature, _N)) \ |
84 | GMOCK_PP_IF(_Constness, const, ) { \ |
85 | GMOCK_MOCKER_(_N, _Constness, _MethodName).RegisterOwner(this); \ |
86 | return GMOCK_MOCKER_(_N, _Constness, _MethodName) \ |
87 | .With(GMOCK_PP_REPEAT(GMOCK_INTERNAL_MATCHER_ARGUMENT, , _N)); \ |
88 | } \ |
89 | ::testing::MockSpec<GMOCK_PP_REMOVE_PARENS(_Signature)> gmock_##_MethodName( \ |
90 | const ::testing::internal::WithoutMatchers&, \ |
91 | GMOCK_PP_IF(_Constness, const, )::testing::internal::Function< \ |
92 | GMOCK_PP_REMOVE_PARENS(_Signature)>*) \ |
93 | const GMOCK_PP_IF(_Noexcept, noexcept, ) { \ |
94 | return GMOCK_PP_CAT(::testing::internal::AdjustConstness_, \ |
95 | GMOCK_PP_IF(_Constness, const, ))(this) \ |
96 | ->gmock_##_MethodName(GMOCK_PP_REPEAT( \ |
97 | GMOCK_INTERNAL_A_MATCHER_ARGUMENT, _Signature, _N)); \ |
98 | } \ |
99 | mutable ::testing::FunctionMocker<GMOCK_PP_REMOVE_PARENS(_Signature)> \ |
100 | GMOCK_MOCKER_(_N, _Constness, _MethodName) |
101 | |
102 | #define GMOCK_INTERNAL_EXPAND(...) __VA_ARGS__ |
103 | |
104 | // Five Valid modifiers. |
105 | #define GMOCK_INTERNAL_HAS_CONST(_Tuple) \ |
106 | GMOCK_PP_HAS_COMMA(GMOCK_PP_FOR_EACH(GMOCK_INTERNAL_DETECT_CONST, ~, _Tuple)) |
107 | |
108 | #define GMOCK_INTERNAL_HAS_OVERRIDE(_Tuple) \ |
109 | GMOCK_PP_HAS_COMMA( \ |
110 | GMOCK_PP_FOR_EACH(GMOCK_INTERNAL_DETECT_OVERRIDE, ~, _Tuple)) |
111 | |
112 | #define GMOCK_INTERNAL_HAS_FINAL(_Tuple) \ |
113 | GMOCK_PP_HAS_COMMA(GMOCK_PP_FOR_EACH(GMOCK_INTERNAL_DETECT_FINAL, ~, _Tuple)) |
114 | |
115 | #define GMOCK_INTERNAL_HAS_NOEXCEPT(_Tuple) \ |
116 | GMOCK_PP_HAS_COMMA( \ |
117 | GMOCK_PP_FOR_EACH(GMOCK_INTERNAL_DETECT_NOEXCEPT, ~, _Tuple)) |
118 | |
119 | #define GMOCK_INTERNAL_GET_CALLTYPE(_Tuple) \ |
120 | GMOCK_PP_FOR_EACH(GMOCK_INTERNAL_GET_CALLTYPE_IMPL, ~, _Tuple) |
121 | |
122 | #define GMOCK_INTERNAL_ASSERT_VALID_SPEC_ELEMENT(_i, _, _elem) \ |
123 | static_assert( \ |
124 | (GMOCK_PP_HAS_COMMA(GMOCK_INTERNAL_DETECT_CONST(_i, _, _elem)) + \ |
125 | GMOCK_PP_HAS_COMMA(GMOCK_INTERNAL_DETECT_OVERRIDE(_i, _, _elem)) + \ |
126 | GMOCK_PP_HAS_COMMA(GMOCK_INTERNAL_DETECT_FINAL(_i, _, _elem)) + \ |
127 | GMOCK_PP_HAS_COMMA(GMOCK_INTERNAL_DETECT_NOEXCEPT(_i, _, _elem)) + \ |
128 | GMOCK_INTERNAL_IS_CALLTYPE(_elem)) == 1, \ |
129 | GMOCK_PP_STRINGIZE( \ |
130 | _elem) " cannot be recognized as a valid specification modifier."); |
131 | |
132 | // Modifiers implementation. |
133 | #define GMOCK_INTERNAL_DETECT_CONST(_i, _, _elem) \ |
134 | GMOCK_PP_CAT(GMOCK_INTERNAL_DETECT_CONST_I_, _elem) |
135 | |
136 | #define GMOCK_INTERNAL_DETECT_CONST_I_const , |
137 | |
138 | #define GMOCK_INTERNAL_DETECT_OVERRIDE(_i, _, _elem) \ |
139 | GMOCK_PP_CAT(GMOCK_INTERNAL_DETECT_OVERRIDE_I_, _elem) |
140 | |
141 | #define GMOCK_INTERNAL_DETECT_OVERRIDE_I_override , |
142 | |
143 | #define GMOCK_INTERNAL_DETECT_FINAL(_i, _, _elem) \ |
144 | GMOCK_PP_CAT(GMOCK_INTERNAL_DETECT_FINAL_I_, _elem) |
145 | |
146 | #define GMOCK_INTERNAL_DETECT_FINAL_I_final , |
147 | |
148 | // TODO(iserna): Maybe noexcept should accept an argument here as well. |
149 | #define GMOCK_INTERNAL_DETECT_NOEXCEPT(_i, _, _elem) \ |
150 | GMOCK_PP_CAT(GMOCK_INTERNAL_DETECT_NOEXCEPT_I_, _elem) |
151 | |
152 | #define GMOCK_INTERNAL_DETECT_NOEXCEPT_I_noexcept , |
153 | |
154 | #define GMOCK_INTERNAL_GET_CALLTYPE_IMPL(_i, _, _elem) \ |
155 | GMOCK_PP_IF(GMOCK_INTERNAL_IS_CALLTYPE(_elem), \ |
156 | GMOCK_INTERNAL_GET_VALUE_CALLTYPE, GMOCK_PP_EMPTY) \ |
157 | (_elem) |
158 | |
159 | // TODO(iserna): GMOCK_INTERNAL_IS_CALLTYPE and |
160 | // GMOCK_INTERNAL_GET_VALUE_CALLTYPE needed more expansions to work on windows |
161 | // maybe they can be simplified somehow. |
162 | #define GMOCK_INTERNAL_IS_CALLTYPE(_arg) \ |
163 | GMOCK_INTERNAL_IS_CALLTYPE_I( \ |
164 | GMOCK_PP_CAT(GMOCK_INTERNAL_IS_CALLTYPE_HELPER_, _arg)) |
165 | #define GMOCK_INTERNAL_IS_CALLTYPE_I(_arg) GMOCK_PP_IS_ENCLOSED_PARENS(_arg) |
166 | |
167 | #define GMOCK_INTERNAL_GET_VALUE_CALLTYPE(_arg) \ |
168 | GMOCK_INTERNAL_GET_VALUE_CALLTYPE_I( \ |
169 | GMOCK_PP_CAT(GMOCK_INTERNAL_IS_CALLTYPE_HELPER_, _arg)) |
170 | #define GMOCK_INTERNAL_GET_VALUE_CALLTYPE_I(_arg) \ |
171 | GMOCK_PP_CAT(GMOCK_PP_IDENTITY, _arg) |
172 | |
173 | #define GMOCK_INTERNAL_IS_CALLTYPE_HELPER_Calltype |
174 | |
175 | #define GMOCK_INTERNAL_SIGNATURE(_Ret, _Args) \ |
176 | GMOCK_PP_IF(GMOCK_PP_IS_BEGIN_PARENS(_Ret), GMOCK_PP_REMOVE_PARENS, \ |
177 | GMOCK_PP_IDENTITY) \ |
178 | (_Ret)(GMOCK_PP_FOR_EACH(GMOCK_INTERNAL_GET_TYPE, _, _Args)) |
179 | |
180 | #define GMOCK_INTERNAL_GET_TYPE(_i, _, _elem) \ |
181 | GMOCK_PP_COMMA_IF(_i) \ |
182 | GMOCK_PP_IF(GMOCK_PP_IS_BEGIN_PARENS(_elem), GMOCK_PP_REMOVE_PARENS, \ |
183 | GMOCK_PP_IDENTITY) \ |
184 | (_elem) |
185 | |
186 | #define GMOCK_INTERNAL_PARAMETER(_i, _Signature, _) \ |
187 | GMOCK_PP_COMMA_IF(_i) \ |
188 | GMOCK_INTERNAL_ARG_O(typename, GMOCK_PP_INC(_i), \ |
189 | GMOCK_PP_REMOVE_PARENS(_Signature)) \ |
190 | gmock_a##_i |
191 | |
192 | #define GMOCK_INTERNAL_FORWARD_ARG(_i, _Signature, _) \ |
193 | GMOCK_PP_COMMA_IF(_i) \ |
194 | ::std::forward<GMOCK_INTERNAL_ARG_O(typename, GMOCK_PP_INC(_i), \ |
195 | GMOCK_PP_REMOVE_PARENS(_Signature))>( \ |
196 | gmock_a##_i) |
197 | |
198 | #define GMOCK_INTERNAL_MATCHER_PARAMETER(_i, _Signature, _) \ |
199 | GMOCK_PP_COMMA_IF(_i) \ |
200 | GMOCK_INTERNAL_MATCHER_O(typename, GMOCK_PP_INC(_i), \ |
201 | GMOCK_PP_REMOVE_PARENS(_Signature)) \ |
202 | gmock_a##_i |
203 | |
204 | #define GMOCK_INTERNAL_MATCHER_ARGUMENT(_i, _1, _2) \ |
205 | GMOCK_PP_COMMA_IF(_i) \ |
206 | gmock_a##_i |
207 | |
208 | #define GMOCK_INTERNAL_A_MATCHER_ARGUMENT(_i, _Signature, _) \ |
209 | GMOCK_PP_COMMA_IF(_i) \ |
210 | ::testing::A<GMOCK_INTERNAL_ARG_O(typename, GMOCK_PP_INC(_i), \ |
211 | GMOCK_PP_REMOVE_PARENS(_Signature))>() |
212 | |
213 | #define GMOCK_INTERNAL_ARG_O(_tn, _i, ...) GMOCK_ARG_(_tn, _i, __VA_ARGS__) |
214 | |
215 | #define GMOCK_INTERNAL_MATCHER_O(_tn, _i, ...) \ |
216 | GMOCK_MATCHER_(_tn, _i, __VA_ARGS__) |
217 | |
218 | #endif // THIRD_PARTY_GOOGLETEST_GOOGLEMOCK_INCLUDE_GMOCK_INTERNAL_GMOCK_FUNCTION_MOCKER_H_ |
219 | |