1 // Copyright 2007, Google Inc. 2 // All rights reserved. 3 // 4 // Redistribution and use in source and binary forms, with or without 5 // modification, are permitted provided that the following conditions are 6 // met: 7 // 8 // * Redistributions of source code must retain the above copyright 9 // notice, this list of conditions and the following disclaimer. 10 // * Redistributions in binary form must reproduce the above 11 // copyright notice, this list of conditions and the following disclaimer 12 // in the documentation and/or other materials provided with the 13 // distribution. 14 // * Neither the name of Google Inc. nor the names of its 15 // contributors may be used to endorse or promote products derived from 16 // this software without specific prior written permission. 17 // 18 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 21 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 22 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 24 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 30 // Google Mock - a framework for writing C++ mock classes. 31 // 32 // This file implements MOCK_METHOD. 33 34 // GOOGLETEST_CM0002 DO NOT DELETE 35 36 #ifndef THIRD_PARTY_GOOGLETEST_GOOGLEMOCK_INCLUDE_GMOCK_INTERNAL_GMOCK_FUNCTION_MOCKER_H_ // NOLINT 37 #define THIRD_PARTY_GOOGLETEST_GOOGLEMOCK_INCLUDE_GMOCK_INTERNAL_GMOCK_FUNCTION_MOCKER_H_ // NOLINT 38 39 #include "gmock/gmock-generated-function-mockers.h" // NOLINT 40 #include "gmock/internal/gmock-pp.h" 41 42 #define MOCK_METHOD(...) \ 43 GMOCK_PP_VARIADIC_CALL(GMOCK_INTERNAL_MOCK_METHOD_ARG_, __VA_ARGS__) 44 45 #define GMOCK_INTERNAL_MOCK_METHOD_ARG_1(...) \ 46 GMOCK_INTERNAL_WRONG_ARITY(__VA_ARGS__) 47 48 #define GMOCK_INTERNAL_MOCK_METHOD_ARG_2(...) \ 49 GMOCK_INTERNAL_WRONG_ARITY(__VA_ARGS__) 50 51 #define GMOCK_INTERNAL_MOCK_METHOD_ARG_3(_Ret, _MethodName, _Args) \ 52 GMOCK_INTERNAL_MOCK_METHOD_ARG_4(_Ret, _MethodName, _Args, ()) 53 54 #define GMOCK_INTERNAL_MOCK_METHOD_ARG_4(_Ret, _MethodName, _Args, _Spec) \ 55 GMOCK_INTERNAL_ASSERT_PARENTHESIS(_Args); \ 56 GMOCK_INTERNAL_ASSERT_PARENTHESIS(_Spec); \ 57 GMOCK_INTERNAL_ASSERT_VALID_SIGNATURE( \ 58 GMOCK_PP_NARG0 _Args, GMOCK_INTERNAL_SIGNATURE(_Ret, _Args)); \ 59 GMOCK_INTERNAL_ASSERT_VALID_SPEC(_Spec) \ 60 GMOCK_INTERNAL_MOCK_METHOD_IMPL( \ 61 GMOCK_PP_NARG0 _Args, _MethodName, GMOCK_INTERNAL_HAS_CONST(_Spec), \ 62 GMOCK_INTERNAL_HAS_OVERRIDE(_Spec), GMOCK_INTERNAL_HAS_FINAL(_Spec), \ 63 GMOCK_INTERNAL_HAS_NOEXCEPT(_Spec), GMOCK_INTERNAL_GET_CALLTYPE(_Spec), \ 64 (GMOCK_INTERNAL_SIGNATURE(_Ret, _Args))) 65 66 #define GMOCK_INTERNAL_MOCK_METHOD_ARG_5(...) \ 67 GMOCK_INTERNAL_WRONG_ARITY(__VA_ARGS__) 68 69 #define GMOCK_INTERNAL_MOCK_METHOD_ARG_6(...) \ 70 GMOCK_INTERNAL_WRONG_ARITY(__VA_ARGS__) 71 72 #define GMOCK_INTERNAL_MOCK_METHOD_ARG_7(...) \ 73 GMOCK_INTERNAL_WRONG_ARITY(__VA_ARGS__) 74 75 #define GMOCK_INTERNAL_WRONG_ARITY(...) \ 76 static_assert( \ 77 false, \ 78 "MOCK_METHOD must be called with 3 or 4 arguments. _Ret, " \ 79 "_MethodName, _Args and optionally _Spec. _Args and _Spec must be " \ 80 "enclosed in parentheses. If _Ret is a type with unprotected commas, " \ 81 "it must also be enclosed in parentheses.") 82 83 #define GMOCK_INTERNAL_ASSERT_PARENTHESIS(_Tuple) \ 84 static_assert( \ 85 GMOCK_PP_IS_ENCLOSED_PARENS(_Tuple), \ 86 GMOCK_PP_STRINGIZE(_Tuple) " should be enclosed in parentheses.") 87 88 #define GMOCK_INTERNAL_ASSERT_VALID_SIGNATURE(_N, ...) \ 89 static_assert( \ 90 std::is_function<__VA_ARGS__>::value, \ 91 "Signature must be a function type, maybe return type contains " \ 92 "unprotected comma."); \ 93 static_assert( \ 94 ::testing::tuple_size<typename ::testing::internal::Function< \ 95 __VA_ARGS__>::ArgumentTuple>::value == _N, \ 96 "This method does not take " GMOCK_PP_STRINGIZE( \ 97 _N) " arguments. Parenthesize all types with unproctected commas.") 98 99 #define GMOCK_INTERNAL_ASSERT_VALID_SPEC(_Spec) \ 100 GMOCK_PP_FOR_EACH(GMOCK_INTERNAL_ASSERT_VALID_SPEC_ELEMENT, ~, _Spec) 101 102 #define GMOCK_INTERNAL_MOCK_METHOD_IMPL(_N, _MethodName, _Constness, \ 103 _Override, _Final, _Noexcept, \ 104 _CallType, _Signature) \ 105 typename ::testing::internal::Function<GMOCK_PP_REMOVE_PARENS( \ 106 _Signature)>::Result \ 107 GMOCK_INTERNAL_EXPAND(_CallType) \ 108 _MethodName(GMOCK_PP_REPEAT(GMOCK_INTERNAL_PARAMETER, _Signature, _N)) \ 109 GMOCK_PP_IF(_Constness, const, ) GMOCK_PP_IF(_Noexcept, noexcept, ) \ 110 GMOCK_PP_IF(_Override, override, ) \ 111 GMOCK_PP_IF(_Final, final, ) { \ 112 GMOCK_MOCKER_(_N, _Constness, _MethodName) \ 113 .SetOwnerAndName(this, #_MethodName); \ 114 return GMOCK_MOCKER_(_N, _Constness, _MethodName) \ 115 .Invoke(GMOCK_PP_REPEAT(GMOCK_INTERNAL_FORWARD_ARG, _Signature, _N)); \ 116 } \ 117 ::testing::MockSpec<GMOCK_PP_REMOVE_PARENS(_Signature)> gmock_##_MethodName( \ 118 GMOCK_PP_REPEAT(GMOCK_INTERNAL_MATCHER_PARAMETER, _Signature, _N)) \ 119 GMOCK_PP_IF(_Constness, const, ) { \ 120 GMOCK_MOCKER_(_N, _Constness, _MethodName).RegisterOwner(this); \ 121 return GMOCK_MOCKER_(_N, _Constness, _MethodName) \ 122 .With(GMOCK_PP_REPEAT(GMOCK_INTERNAL_MATCHER_ARGUMENT, , _N)); \ 123 } \ 124 ::testing::MockSpec<GMOCK_PP_REMOVE_PARENS(_Signature)> gmock_##_MethodName( \ 125 const ::testing::internal::WithoutMatchers&, \ 126 GMOCK_PP_IF(_Constness, const, )::testing::internal::Function< \ 127 GMOCK_PP_REMOVE_PARENS(_Signature)>*) \ 128 const GMOCK_PP_IF(_Noexcept, noexcept, ) { \ 129 return GMOCK_PP_CAT(::testing::internal::AdjustConstness_, \ 130 GMOCK_PP_IF(_Constness, const, ))(this) \ 131 ->gmock_##_MethodName(GMOCK_PP_REPEAT( \ 132 GMOCK_INTERNAL_A_MATCHER_ARGUMENT, _Signature, _N)); \ 133 } \ 134 mutable ::testing::FunctionMocker<GMOCK_PP_REMOVE_PARENS(_Signature)> \ 135 GMOCK_MOCKER_(_N, _Constness, _MethodName) 136 137 #define GMOCK_INTERNAL_EXPAND(...) __VA_ARGS__ 138 139 // Five Valid modifiers. 140 #define GMOCK_INTERNAL_HAS_CONST(_Tuple) \ 141 GMOCK_PP_HAS_COMMA(GMOCK_PP_FOR_EACH(GMOCK_INTERNAL_DETECT_CONST, ~, _Tuple)) 142 143 #define GMOCK_INTERNAL_HAS_OVERRIDE(_Tuple) \ 144 GMOCK_PP_HAS_COMMA( \ 145 GMOCK_PP_FOR_EACH(GMOCK_INTERNAL_DETECT_OVERRIDE, ~, _Tuple)) 146 147 #define GMOCK_INTERNAL_HAS_FINAL(_Tuple) \ 148 GMOCK_PP_HAS_COMMA(GMOCK_PP_FOR_EACH(GMOCK_INTERNAL_DETECT_FINAL, ~, _Tuple)) 149 150 #define GMOCK_INTERNAL_HAS_NOEXCEPT(_Tuple) \ 151 GMOCK_PP_HAS_COMMA( \ 152 GMOCK_PP_FOR_EACH(GMOCK_INTERNAL_DETECT_NOEXCEPT, ~, _Tuple)) 153 154 #define GMOCK_INTERNAL_GET_CALLTYPE(_Tuple) \ 155 GMOCK_PP_FOR_EACH(GMOCK_INTERNAL_GET_CALLTYPE_IMPL, ~, _Tuple) 156 157 #define GMOCK_INTERNAL_ASSERT_VALID_SPEC_ELEMENT(_i, _, _elem) \ 158 static_assert( \ 159 (GMOCK_PP_HAS_COMMA(GMOCK_INTERNAL_DETECT_CONST(_i, _, _elem)) + \ 160 GMOCK_PP_HAS_COMMA(GMOCK_INTERNAL_DETECT_OVERRIDE(_i, _, _elem)) + \ 161 GMOCK_PP_HAS_COMMA(GMOCK_INTERNAL_DETECT_FINAL(_i, _, _elem)) + \ 162 GMOCK_PP_HAS_COMMA(GMOCK_INTERNAL_DETECT_NOEXCEPT(_i, _, _elem)) + \ 163 GMOCK_INTERNAL_IS_CALLTYPE(_elem)) == 1, \ 164 GMOCK_PP_STRINGIZE( \ 165 _elem) " cannot be recognized as a valid specification modifier."); 166 167 // Modifiers implementation. 168 #define GMOCK_INTERNAL_DETECT_CONST(_i, _, _elem) \ 169 GMOCK_PP_CAT(GMOCK_INTERNAL_DETECT_CONST_I_, _elem) 170 171 #define GMOCK_INTERNAL_DETECT_CONST_I_const , 172 173 #define GMOCK_INTERNAL_DETECT_OVERRIDE(_i, _, _elem) \ 174 GMOCK_PP_CAT(GMOCK_INTERNAL_DETECT_OVERRIDE_I_, _elem) 175 176 #define GMOCK_INTERNAL_DETECT_OVERRIDE_I_override , 177 178 #define GMOCK_INTERNAL_DETECT_FINAL(_i, _, _elem) \ 179 GMOCK_PP_CAT(GMOCK_INTERNAL_DETECT_FINAL_I_, _elem) 180 181 #define GMOCK_INTERNAL_DETECT_FINAL_I_final , 182 183 // TODO(iserna): Maybe noexcept should accept an argument here as well. 184 #define GMOCK_INTERNAL_DETECT_NOEXCEPT(_i, _, _elem) \ 185 GMOCK_PP_CAT(GMOCK_INTERNAL_DETECT_NOEXCEPT_I_, _elem) 186 187 #define GMOCK_INTERNAL_DETECT_NOEXCEPT_I_noexcept , 188 189 #define GMOCK_INTERNAL_GET_CALLTYPE_IMPL(_i, _, _elem) \ 190 GMOCK_PP_IF(GMOCK_INTERNAL_IS_CALLTYPE(_elem), \ 191 GMOCK_INTERNAL_GET_VALUE_CALLTYPE, GMOCK_PP_EMPTY) \ 192 (_elem) 193 194 // TODO(iserna): GMOCK_INTERNAL_IS_CALLTYPE and 195 // GMOCK_INTERNAL_GET_VALUE_CALLTYPE needed more expansions to work on windows 196 // maybe they can be simplified somehow. 197 #define GMOCK_INTERNAL_IS_CALLTYPE(_arg) \ 198 GMOCK_INTERNAL_IS_CALLTYPE_I( \ 199 GMOCK_PP_CAT(GMOCK_INTERNAL_IS_CALLTYPE_HELPER_, _arg)) 200 #define GMOCK_INTERNAL_IS_CALLTYPE_I(_arg) GMOCK_PP_IS_ENCLOSED_PARENS(_arg) 201 202 #define GMOCK_INTERNAL_GET_VALUE_CALLTYPE(_arg) \ 203 GMOCK_INTERNAL_GET_VALUE_CALLTYPE_I( \ 204 GMOCK_PP_CAT(GMOCK_INTERNAL_IS_CALLTYPE_HELPER_, _arg)) 205 #define GMOCK_INTERNAL_GET_VALUE_CALLTYPE_I(_arg) \ 206 GMOCK_PP_CAT(GMOCK_PP_IDENTITY, _arg) 207 208 #define GMOCK_INTERNAL_IS_CALLTYPE_HELPER_Calltype 209 210 #define GMOCK_INTERNAL_SIGNATURE(_Ret, _Args) \ 211 GMOCK_PP_IF(GMOCK_PP_IS_BEGIN_PARENS(_Ret), GMOCK_PP_REMOVE_PARENS, \ 212 GMOCK_PP_IDENTITY) \ 213 (_Ret)(GMOCK_PP_FOR_EACH(GMOCK_INTERNAL_GET_TYPE, _, _Args)) 214 215 #define GMOCK_INTERNAL_GET_TYPE(_i, _, _elem) \ 216 GMOCK_PP_COMMA_IF(_i) \ 217 GMOCK_PP_IF(GMOCK_PP_IS_BEGIN_PARENS(_elem), GMOCK_PP_REMOVE_PARENS, \ 218 GMOCK_PP_IDENTITY) \ 219 (_elem) 220 221 #define GMOCK_INTERNAL_PARAMETER(_i, _Signature, _) \ 222 GMOCK_PP_COMMA_IF(_i) \ 223 GMOCK_INTERNAL_ARG_O(typename, GMOCK_PP_INC(_i), \ 224 GMOCK_PP_REMOVE_PARENS(_Signature)) \ 225 gmock_a##_i 226 227 #define GMOCK_INTERNAL_FORWARD_ARG(_i, _Signature, _) \ 228 GMOCK_PP_COMMA_IF(_i) \ 229 ::std::forward<GMOCK_INTERNAL_ARG_O(typename, GMOCK_PP_INC(_i), \ 230 GMOCK_PP_REMOVE_PARENS(_Signature))>( \ 231 gmock_a##_i) 232 233 #define GMOCK_INTERNAL_MATCHER_PARAMETER(_i, _Signature, _) \ 234 GMOCK_PP_COMMA_IF(_i) \ 235 GMOCK_INTERNAL_MATCHER_O(typename, GMOCK_PP_INC(_i), \ 236 GMOCK_PP_REMOVE_PARENS(_Signature)) \ 237 gmock_a##_i 238 239 #define GMOCK_INTERNAL_MATCHER_ARGUMENT(_i, _1, _2) \ 240 GMOCK_PP_COMMA_IF(_i) \ 241 gmock_a##_i 242 243 #define GMOCK_INTERNAL_A_MATCHER_ARGUMENT(_i, _Signature, _) \ 244 GMOCK_PP_COMMA_IF(_i) \ 245 ::testing::A<GMOCK_INTERNAL_ARG_O(typename, GMOCK_PP_INC(_i), \ 246 GMOCK_PP_REMOVE_PARENS(_Signature))>() 247 248 #define GMOCK_INTERNAL_ARG_O(_tn, _i, ...) GMOCK_ARG_(_tn, _i, __VA_ARGS__) 249 250 #define GMOCK_INTERNAL_MATCHER_O(_tn, _i, ...) \ 251 GMOCK_MATCHER_(_tn, _i, __VA_ARGS__) 252 253 #endif // THIRD_PARTY_GOOGLETEST_GOOGLEMOCK_INCLUDE_GMOCK_INTERNAL_GMOCK_FUNCTION_MOCKER_H_ 254