Clone of unsubmitted cr/176529515. Introduce parameterless expectations.

This commit is contained in:
David Sunderland
2018-04-18 19:28:56 -04:00
parent 1f605414cc
commit f437f8ca0d
7 changed files with 425 additions and 12 deletions

View File

@@ -1282,6 +1282,13 @@ class MockSpec {
file, line, source_text, matchers_);
}
// This operator overload is used to swallow the superfluous parameter list
// introduced by the ON/EXPECT_CALL macros. See the macro comments for more
// explanation.
MockSpec<F>& operator()(const internal::WithoutMatchers&, void* const) {
return *this;
}
private:
template <typename Function>
friend class internal::FunctionMocker;
@@ -1836,17 +1843,76 @@ inline Expectation::Expectation(internal::ExpectationBase& exp) // NOLINT
} // namespace testing
// A separate macro is required to avoid compile errors when the name
// of the method used in call is a result of macro expansion.
// See CompilesWithMethodNameExpandedFromMacro tests in
// internal/gmock-spec-builders_test.cc for more details.
#define GMOCK_ON_CALL_IMPL_(obj, call) \
((obj).gmock_##call).InternalDefaultActionSetAt(__FILE__, __LINE__, \
#obj, #call)
#define ON_CALL(obj, call) GMOCK_ON_CALL_IMPL_(obj, call)
// Implementation for ON_CALL and EXPECT_CALL macros. A separate macro is
// required to avoid compile errors when the name of the method used in call is
// a result of macro expansion. See CompilesWithMethodNameExpandedFromMacro
// tests in internal/gmock-spec-builders_test.cc for more details.
//
// This macro supports statements both with and without parameter matchers. If
// the parameter list is omitted, gMock will accept any parameters, which allows
// tests to be written that don't need to encode the number of method
// parameter. This technique may only be used for non-overloaded methods.
//
// // These are the same:
// ON_CALL(mock, NoArgsMethod()).WillByDefault(…);
// ON_CALL(mock, NoArgsMethod).WillByDefault(…);
//
// // As are these:
// ON_CALL(mock, TwoArgsMethod(_, _)).WillByDefault(…);
// ON_CALL(mock, TwoArgsMethod).WillByDefault(…);
//
// // Can also specify args if you want, of course:
// ON_CALL(mock, TwoArgsMethod(_, 45)).WillByDefault(…);
//
// // Overloads work as long as you specify parameters:
// ON_CALL(mock, OverloadedMethod(_)).WillByDefault(…);
// ON_CALL(mock, OverloadedMethod(_, _)).WillByDefault(…);
//
// // Oops! Which overload did you want?
// ON_CALL(mock, OverloadedMethod).WillByDefault(…);
// => ERROR: call to member function 'gmock_OverloadedMethod' is ambiguous
//
// How this works: The mock class uses two overloads of the gmock_Method
// expectation setter method plus an operator() overload on the MockSpec object.
// In the matcher list form, the macro expands to:
//
// // This statement:
// ON_CALL(mock, TwoArgsMethod(_, 45))…
//
// // …expands to:
// mock.gmock_TwoArgsMethod(_, 45)(WithoutMatchers(), nullptr)…
// |-------------v---------------||------------v-------------|
// invokes first overload swallowed by operator()
//
// // …which is essentially:
// mock.gmock_TwoArgsMethod(_, 45)…
//
// Whereas the form without a matcher list:
//
// // This statement:
// ON_CALL(mock, TwoArgsMethod)…
//
// // …expands to:
// mock.gmock_TwoArgsMethod(WithoutMatchers(), nullptr)…
// |-----------------------v--------------------------|
// invokes second overload
//
// // …which is essentially:
// mock.gmock_TwoArgsMethod(_, _)…
//
// The WithoutMatchers() argument is used to disambiguate overloads and to
// block the caller from accidentally invoking the second overload directly. The
// second argument is an internal type derived from the method signature. The
// failure to disambiguate two overloads of this method in the ON_CALL statement
// is how we block callers from setting expectations on overloaded methods.
#define GMOCK_ON_CALL_IMPL_(mock_expr, Setter, call) \
((mock_expr).gmock_##call)(::testing::internal::GetWithoutMatchers(), NULL) \
.Setter(__FILE__, __LINE__, #mock_expr, #call)
#define GMOCK_EXPECT_CALL_IMPL_(obj, call) \
((obj).gmock_##call).InternalExpectedAt(__FILE__, __LINE__, #obj, #call)
#define EXPECT_CALL(obj, call) GMOCK_EXPECT_CALL_IMPL_(obj, call)
#define ON_CALL(obj, call) \
GMOCK_ON_CALL_IMPL_(obj, InternalDefaultActionSetAt, call)
#define EXPECT_CALL(obj, call) \
GMOCK_ON_CALL_IMPL_(obj, InternalExpectedAt, call)
#endif // GMOCK_INCLUDE_GMOCK_GMOCK_SPEC_BUILDERS_H_