aboutsummaryrefslogtreecommitdiffstats
path: root/googlemock/include/gmock/gmock-spec-builders.h
diff options
context:
space:
mode:
authorBrukerJWD <jonathan.wendeborn@bruker.com>2018-10-16 08:37:56 +0200
committerGitHub <noreply@github.com>2018-10-16 08:37:56 +0200
commit8c82ba48e433005b9e25835b4a342ef4dcc0cfc0 (patch)
treee1ae94f37108a8f506cd4d11eec0e058c2c39980 /googlemock/include/gmock/gmock-spec-builders.h
parent6bbf911a8dc0c42ad05135f26a07f4893eb83916 (diff)
parenta651a4d44e65b749467fa3dddf93819a22f0cc4a (diff)
downloadgoogletest-8c82ba48e433005b9e25835b4a342ef4dcc0cfc0.tar.gz
googletest-8c82ba48e433005b9e25835b4a342ef4dcc0cfc0.tar.bz2
googletest-8c82ba48e433005b9e25835b4a342ef4dcc0cfc0.zip
Merge branch 'master' into isnice
Diffstat (limited to 'googlemock/include/gmock/gmock-spec-builders.h')
-rw-r--r--googlemock/include/gmock/gmock-spec-builders.h302
1 files changed, 187 insertions, 115 deletions
diff --git a/googlemock/include/gmock/gmock-spec-builders.h b/googlemock/include/gmock/gmock-spec-builders.h
index 1e8f732f..d085df34 100644
--- a/googlemock/include/gmock/gmock-spec-builders.h
+++ b/googlemock/include/gmock/gmock-spec-builders.h
@@ -26,8 +26,7 @@
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-//
-// Author: wan@google.com (Zhanyong Wan)
+
// Google Mock - a framework for writing C++ mock classes.
//
@@ -57,6 +56,8 @@
// where all clauses are optional, and .InSequence()/.After()/
// .WillOnce() can appear any number of times.
+// GOOGLETEST_CM0002 DO NOT DELETE
+
#ifndef GMOCK_INCLUDE_GMOCK_GMOCK_SPEC_BUILDERS_H_
#define GMOCK_INCLUDE_GMOCK_GMOCK_SPEC_BUILDERS_H_
@@ -65,11 +66,6 @@
#include <sstream>
#include <string>
#include <vector>
-
-#if GTEST_HAS_EXCEPTIONS
-# include <stdexcept> // NOLINT
-#endif
-
#include "gmock/gmock-actions.h"
#include "gmock/gmock-cardinalities.h"
#include "gmock/gmock-matchers.h"
@@ -77,6 +73,13 @@
#include "gmock/internal/gmock-port.h"
#include "gtest/gtest.h"
+#if GTEST_HAS_EXCEPTIONS
+# include <stdexcept> // NOLINT
+#endif
+
+GTEST_DISABLE_MSC_WARNINGS_PUSH_(4251 \
+/* class A needs to have dll-interface to be used by clients of class B */)
+
namespace testing {
// An abstract handle of an expectation.
@@ -148,15 +151,13 @@ class GTEST_API_ UntypedFunctionMockerBase {
// action fails.
// L = *
virtual UntypedActionResultHolderBase* UntypedPerformDefaultAction(
- const void* untyped_args,
- const string& call_description) const = 0;
+ void* untyped_args, const std::string& call_description) const = 0;
// Performs the given action with the given arguments and returns
// the action's result.
// L = *
virtual UntypedActionResultHolderBase* UntypedPerformAction(
- const void* untyped_action,
- const void* untyped_args) const = 0;
+ const void* untyped_action, void* untyped_args) const = 0;
// Writes a message that the call is uninteresting (i.e. neither
// explicitly expected nor explicitly unexpected) to the given
@@ -186,7 +187,7 @@ class GTEST_API_ UntypedFunctionMockerBase {
// this information in the global mock registry. Will be called
// whenever an EXPECT_CALL() or ON_CALL() is executed on this mock
// method.
- // TODO(wan@google.com): rename to SetAndRegisterOwner().
+ // FIXME: rename to SetAndRegisterOwner().
void RegisterOwner(const void* mock_obj)
GTEST_LOCK_EXCLUDED_(g_gmock_mutex);
@@ -211,9 +212,8 @@ class GTEST_API_ UntypedFunctionMockerBase {
// arguments. This function can be safely called from multiple
// threads concurrently. The caller is responsible for deleting the
// result.
- UntypedActionResultHolderBase* UntypedInvokeWith(
- const void* untyped_args)
- GTEST_LOCK_EXCLUDED_(g_gmock_mutex);
+ UntypedActionResultHolderBase* UntypedInvokeWith(void* untyped_args)
+ GTEST_LOCK_EXCLUDED_(g_gmock_mutex);
protected:
typedef std::vector<const void*> UntypedOnCallSpecs;
@@ -238,6 +238,14 @@ class GTEST_API_ UntypedFunctionMockerBase {
UntypedOnCallSpecs untyped_on_call_specs_;
// All expectations for this function mocker.
+ //
+ // It's undefined behavior to interleave expectations (EXPECT_CALLs
+ // or ON_CALLs) and mock function calls. Also, the order of
+ // expectations is important. Therefore it's a logic race condition
+ // to read/write untyped_expectations_ concurrently. In order for
+ // tools like tsan to catch concurrent read/write accesses to
+ // untyped_expectations, we deliberately leave accesses to it
+ // unprotected.
UntypedExpectations untyped_expectations_;
}; // class UntypedFunctionMockerBase
@@ -263,12 +271,14 @@ class UntypedOnCallSpecBase {
};
// Asserts that the ON_CALL() statement has a certain property.
- void AssertSpecProperty(bool property, const string& failure_message) const {
+ void AssertSpecProperty(bool property,
+ const std::string& failure_message) const {
Assert(property, file_, line_, failure_message);
}
// Expects that the ON_CALL() statement has a certain property.
- void ExpectSpecProperty(bool property, const string& failure_message) const {
+ void ExpectSpecProperty(bool property,
+ const std::string& failure_message) const {
Expect(property, file_, line_, failure_message);
}
@@ -362,7 +372,6 @@ enum CallReaction {
kAllow,
kWarn,
kFail,
- kDefault = kWarn // By default, warn about uninteresting calls.
};
} // namespace internal
@@ -700,7 +709,7 @@ GTEST_API_ extern ThreadLocal<Sequence*> g_gmock_implicit_sequence;
class GTEST_API_ ExpectationBase {
public:
// source_text is the EXPECT_CALL(...) source that created this Expectation.
- ExpectationBase(const char* file, int line, const string& source_text);
+ ExpectationBase(const char* file, int line, const std::string& source_text);
virtual ~ExpectationBase();
@@ -748,12 +757,14 @@ class GTEST_API_ ExpectationBase {
virtual Expectation GetHandle() = 0;
// Asserts that the EXPECT_CALL() statement has the given property.
- void AssertSpecProperty(bool property, const string& failure_message) const {
+ void AssertSpecProperty(bool property,
+ const std::string& failure_message) const {
Assert(property, file_, line_, failure_message);
}
// Expects that the EXPECT_CALL() statement has the given property.
- void ExpectSpecProperty(bool property, const string& failure_message) const {
+ void ExpectSpecProperty(bool property,
+ const std::string& failure_message) const {
Expect(property, file_, line_, failure_message);
}
@@ -855,7 +866,7 @@ class GTEST_API_ ExpectationBase {
// an EXPECT_CALL() statement finishes.
const char* file_; // The file that contains the expectation.
int line_; // The line number of the expectation.
- const string source_text_; // The EXPECT_CALL(...) source text.
+ const std::string source_text_; // The EXPECT_CALL(...) source text.
// True iff the cardinality is specified explicitly.
bool cardinality_specified_;
Cardinality cardinality_; // The cardinality of the expectation.
@@ -890,8 +901,8 @@ class TypedExpectation : public ExpectationBase {
typedef typename Function<F>::ArgumentMatcherTuple ArgumentMatcherTuple;
typedef typename Function<F>::Result Result;
- TypedExpectation(FunctionMockerBase<F>* owner,
- const char* a_file, int a_line, const string& a_source_text,
+ TypedExpectation(FunctionMockerBase<F>* owner, const char* a_file, int a_line,
+ const std::string& a_source_text,
const ArgumentMatcherTuple& m)
: ExpectationBase(a_file, a_line, a_source_text),
owner_(owner),
@@ -1183,9 +1194,10 @@ class TypedExpectation : public ExpectationBase {
Log(kWarning, ss.str(), 1);
}
- return count <= action_count ?
- *static_cast<const Action<F>*>(untyped_actions_[count - 1]) :
- repeated_action();
+ return count <= action_count
+ ? *static_cast<const Action<F>*>(
+ untyped_actions_[static_cast<size_t>(count - 1)])
+ : repeated_action();
}
// Given the arguments of a mock function call, if the call will
@@ -1209,10 +1221,10 @@ class TypedExpectation : public ExpectationBase {
mocker->DescribeDefaultActionTo(args, what);
DescribeCallCountTo(why);
- // TODO(wan@google.com): allow the user to control whether
+ // FIXME: allow the user to control whether
// unexpected calls should fail immediately or continue using a
// flag --gmock_unexpected_calls_are_fatal.
- return NULL;
+ return nullptr;
}
IncrementCallCount();
@@ -1250,7 +1262,7 @@ class TypedExpectation : public ExpectationBase {
// Logs a message including file and line number information.
GTEST_API_ void LogWithLocation(testing::internal::LogSeverity severity,
const char* file, int line,
- const string& message);
+ const std::string& message);
template <typename F>
class MockSpec {
@@ -1261,15 +1273,16 @@ class MockSpec {
// Constructs a MockSpec object, given the function mocker object
// that the spec is associated with.
- explicit MockSpec(internal::FunctionMockerBase<F>* function_mocker)
- : function_mocker_(function_mocker) {}
+ MockSpec(internal::FunctionMockerBase<F>* function_mocker,
+ const ArgumentMatcherTuple& matchers)
+ : function_mocker_(function_mocker), matchers_(matchers) {}
// Adds a new default action spec to the function mocker and returns
// the newly created spec.
internal::OnCallSpec<F>& InternalDefaultActionSetAt(
const char* file, int line, const char* obj, const char* call) {
LogWithLocation(internal::kInfo, file, line,
- string("ON_CALL(") + obj + ", " + call + ") invoked");
+ std::string("ON_CALL(") + obj + ", " + call + ") invoked");
return function_mocker_->AddNewOnCallSpec(file, line, matchers_);
}
@@ -1277,20 +1290,24 @@ class MockSpec {
// the newly created spec.
internal::TypedExpectation<F>& InternalExpectedAt(
const char* file, int line, const char* obj, const char* call) {
- const string source_text(string("EXPECT_CALL(") + obj + ", " + call + ")");
+ const std::string source_text(std::string("EXPECT_CALL(") + obj + ", " +
+ call + ")");
LogWithLocation(internal::kInfo, file, line, source_text + " invoked");
return function_mocker_->AddNewExpectation(
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;
- void SetMatchers(const ArgumentMatcherTuple& matchers) {
- matchers_ = matchers;
- }
-
// The function mocker that owns this spec.
internal::FunctionMockerBase<F>* const function_mocker_;
// The argument matchers specified in the spec.
@@ -1354,11 +1371,7 @@ class ReferenceOrValueWrapper<T&> {
// we need to temporarily disable the warning. We have to do it for
// the entire class to suppress the warning, even though it's about
// the constructor only.
-
-#ifdef _MSC_VER
-# pragma warning(push) // Saves the current warning state.
-# pragma warning(disable:4355) // Temporarily disables warning 4355.
-#endif // _MSV_VER
+GTEST_DISABLE_MSC_WARNINGS_PUSH_(4355)
// C++ treats the void type specially. For example, you cannot define
// a void-typed variable or pass a void value to a function.
@@ -1398,19 +1411,20 @@ class ActionResultHolder : public UntypedActionResultHolderBase {
template <typename F>
static ActionResultHolder* PerformDefaultAction(
const FunctionMockerBase<F>* func_mocker,
- const typename Function<F>::ArgumentTuple& args,
- const string& call_description) {
- return new ActionResultHolder(Wrapper(
- func_mocker->PerformDefaultAction(args, call_description)));
+ typename RvalueRef<typename Function<F>::ArgumentTuple>::type args,
+ const std::string& call_description) {
+ return new ActionResultHolder(Wrapper(func_mocker->PerformDefaultAction(
+ internal::move(args), call_description)));
}
// Performs the given action and returns the result in a new-ed
// ActionResultHolder.
template <typename F>
- static ActionResultHolder*
- PerformAction(const Action<F>& action,
- const typename Function<F>::ArgumentTuple& args) {
- return new ActionResultHolder(Wrapper(action.Perform(args)));
+ static ActionResultHolder* PerformAction(
+ const Action<F>& action,
+ typename RvalueRef<typename Function<F>::ArgumentTuple>::type args) {
+ return new ActionResultHolder(
+ Wrapper(action.Perform(internal::move(args))));
}
private:
@@ -1438,9 +1452,9 @@ class ActionResultHolder<void> : public UntypedActionResultHolderBase {
template <typename F>
static ActionResultHolder* PerformDefaultAction(
const FunctionMockerBase<F>* func_mocker,
- const typename Function<F>::ArgumentTuple& args,
- const string& call_description) {
- func_mocker->PerformDefaultAction(args, call_description);
+ typename RvalueRef<typename Function<F>::ArgumentTuple>::type args,
+ const std::string& call_description) {
+ func_mocker->PerformDefaultAction(internal::move(args), call_description);
return new ActionResultHolder;
}
@@ -1449,8 +1463,8 @@ class ActionResultHolder<void> : public UntypedActionResultHolderBase {
template <typename F>
static ActionResultHolder* PerformAction(
const Action<F>& action,
- const typename Function<F>::ArgumentTuple& args) {
- action.Perform(args);
+ typename RvalueRef<typename Function<F>::ArgumentTuple>::type args) {
+ action.Perform(internal::move(args));
return new ActionResultHolder;
}
@@ -1469,7 +1483,7 @@ class FunctionMockerBase : public UntypedFunctionMockerBase {
typedef typename Function<F>::ArgumentTuple ArgumentTuple;
typedef typename Function<F>::ArgumentMatcherTuple ArgumentMatcherTuple;
- FunctionMockerBase() : current_spec_(this) {}
+ FunctionMockerBase() {}
// The destructor verifies that all expectations on this mock
// function have been satisfied. If not, it will report Google Test
@@ -1495,7 +1509,7 @@ class FunctionMockerBase : public UntypedFunctionMockerBase {
return spec;
}
- return NULL;
+ return nullptr;
}
// Performs the default action of this mock function on the given
@@ -1505,14 +1519,16 @@ class FunctionMockerBase : public UntypedFunctionMockerBase {
// mutable state of this object, and thus can be called concurrently
// without locking.
// L = *
- Result PerformDefaultAction(const ArgumentTuple& args,
- const string& call_description) const {
+ Result PerformDefaultAction(
+ typename RvalueRef<typename Function<F>::ArgumentTuple>::type args,
+ const std::string& call_description) const {
const OnCallSpec<F>* const spec =
this->FindOnCallSpec(args);
- if (spec != NULL) {
- return spec->GetAction().Perform(args);
+ if (spec != nullptr) {
+ return spec->GetAction().Perform(internal::move(args));
}
- const string message = call_description +
+ const std::string message =
+ call_description +
"\n The mock function has no default action "
"set, and its return type has no default value set.";
#if GTEST_HAS_EXCEPTIONS
@@ -1531,11 +1547,11 @@ class FunctionMockerBase : public UntypedFunctionMockerBase {
// action fails. The caller is responsible for deleting the result.
// L = *
virtual UntypedActionResultHolderBase* UntypedPerformDefaultAction(
- const void* untyped_args, // must point to an ArgumentTuple
- const string& call_description) const {
- const ArgumentTuple& args =
- *static_cast<const ArgumentTuple*>(untyped_args);
- return ResultHolder::PerformDefaultAction(this, args, call_description);
+ void* untyped_args, // must point to an ArgumentTuple
+ const std::string& call_description) const {
+ ArgumentTuple* args = static_cast<ArgumentTuple*>(untyped_args);
+ return ResultHolder::PerformDefaultAction(this, internal::move(*args),
+ call_description);
}
// Performs the given action with the given arguments and returns
@@ -1543,13 +1559,12 @@ class FunctionMockerBase : public UntypedFunctionMockerBase {
// result.
// L = *
virtual UntypedActionResultHolderBase* UntypedPerformAction(
- const void* untyped_action, const void* untyped_args) const {
+ const void* untyped_action, void* untyped_args) const {
// Make a copy of the action before performing it, in case the
// action deletes the mock object (and thus deletes itself).
const Action<F> action = *static_cast<const Action<F>*>(untyped_action);
- const ArgumentTuple& args =
- *static_cast<const ArgumentTuple*>(untyped_args);
- return ResultHolder::PerformAction(action, args);
+ ArgumentTuple* args = static_cast<ArgumentTuple*>(untyped_args);
+ return ResultHolder::PerformAction(action, internal::move(*args));
}
// Implements UntypedFunctionMockerBase::ClearDefaultActionsLocked():
@@ -1589,10 +1604,14 @@ class FunctionMockerBase : public UntypedFunctionMockerBase {
// Returns the result of invoking this mock function with the given
// arguments. This function can be safely called from multiple
// threads concurrently.
- Result InvokeWith(const ArgumentTuple& args)
- GTEST_LOCK_EXCLUDED_(g_gmock_mutex) {
+ Result InvokeWith(
+ typename RvalueRef<typename Function<F>::ArgumentTuple>::type args)
+ GTEST_LOCK_EXCLUDED_(g_gmock_mutex) {
+ // const_cast is required since in C++98 we still pass ArgumentTuple around
+ // by const& instead of rvalue reference.
+ void* untyped_args = const_cast<void*>(static_cast<const void*>(&args));
scoped_ptr<ResultHolder> holder(
- DownCast_<ResultHolder*>(this->UntypedInvokeWith(&args)));
+ DownCast_<ResultHolder*>(this->UntypedInvokeWith(untyped_args)));
return holder->Unwrap();
}
@@ -1608,31 +1627,27 @@ class FunctionMockerBase : public UntypedFunctionMockerBase {
}
// Adds and returns an expectation spec for this mock function.
- TypedExpectation<F>& AddNewExpectation(
- const char* file,
- int line,
- const string& source_text,
- const ArgumentMatcherTuple& m)
- GTEST_LOCK_EXCLUDED_(g_gmock_mutex) {
+ TypedExpectation<F>& AddNewExpectation(const char* file, int line,
+ const std::string& source_text,
+ const ArgumentMatcherTuple& m)
+ GTEST_LOCK_EXCLUDED_(g_gmock_mutex) {
Mock::RegisterUseByOnCallOrExpectCall(MockObject(), file, line);
TypedExpectation<F>* const expectation =
new TypedExpectation<F>(this, file, line, source_text, m);
const linked_ptr<ExpectationBase> untyped_expectation(expectation);
+ // See the definition of untyped_expectations_ for why access to
+ // it is unprotected here.
untyped_expectations_.push_back(untyped_expectation);
// Adds this expectation into the implicit sequence if there is one.
Sequence* const implicit_sequence = g_gmock_implicit_sequence.get();
- if (implicit_sequence != NULL) {
+ if (implicit_sequence != nullptr) {
implicit_sequence->AddExpectation(Expectation(untyped_expectation));
}
return *expectation;
}
- // The current spec (either default action spec or expectation spec)
- // being described on this function mocker.
- MockSpec<F>& current_spec() { return current_spec_; }
-
private:
template <typename Func> friend class TypedExpectation;
@@ -1645,7 +1660,7 @@ class FunctionMockerBase : public UntypedFunctionMockerBase {
::std::ostream* os) const {
const OnCallSpec<F>* const spec = FindOnCallSpec(args);
- if (spec == NULL) {
+ if (spec == nullptr) {
*os << (internal::type_equals<Result, void>::value ?
"returning directly.\n" :
"returning default value.\n");
@@ -1695,9 +1710,9 @@ class FunctionMockerBase : public UntypedFunctionMockerBase {
*static_cast<const ArgumentTuple*>(untyped_args);
MutexLock l(&g_gmock_mutex);
TypedExpectation<F>* exp = this->FindMatchingExpectationLocked(args);
- if (exp == NULL) { // A match wasn't found.
+ if (exp == nullptr) { // A match wasn't found.
this->FormatUnexpectedCallMessageLocked(args, what, why);
- return NULL;
+ return nullptr;
}
// This line must be done before calling GetActionForArguments(),
@@ -1705,8 +1720,8 @@ class FunctionMockerBase : public UntypedFunctionMockerBase {
// its saturation status.
*is_excessive = exp->IsSaturated();
const Action<F>* action = exp->GetActionForArguments(this, args, what, why);
- if (action != NULL && action->IsDoDefault())
- action = NULL; // Normalize "do default" to NULL.
+ if (action != nullptr && action->IsDoDefault())
+ action = nullptr; // Normalize "do default" to NULL.
*untyped_action = action;
return exp;
}
@@ -1725,6 +1740,8 @@ class FunctionMockerBase : public UntypedFunctionMockerBase {
const ArgumentTuple& args) const
GTEST_EXCLUSIVE_LOCK_REQUIRED_(g_gmock_mutex) {
g_gmock_mutex.AssertHeld();
+ // See the definition of untyped_expectations_ for why access to
+ // it is unprotected here.
for (typename UntypedExpectations::const_reverse_iterator it =
untyped_expectations_.rbegin();
it != untyped_expectations_.rend(); ++it) {
@@ -1734,7 +1751,7 @@ class FunctionMockerBase : public UntypedFunctionMockerBase {
return exp;
}
}
- return NULL;
+ return nullptr;
}
// Returns a message that the arguments don't match any expectation.
@@ -1756,12 +1773,12 @@ class FunctionMockerBase : public UntypedFunctionMockerBase {
::std::ostream* why) const
GTEST_EXCLUSIVE_LOCK_REQUIRED_(g_gmock_mutex) {
g_gmock_mutex.AssertHeld();
- const int count = static_cast<int>(untyped_expectations_.size());
+ const size_t count = untyped_expectations_.size();
*why << "Google Mock tried the following " << count << " "
<< (count == 1 ? "expectation, but it didn't match" :
"expectations, but none matched")
<< ":\n";
- for (int i = 0; i < count; i++) {
+ for (size_t i = 0; i < count; i++) {
TypedExpectation<F>* const expectation =
static_cast<TypedExpectation<F>*>(untyped_expectations_[i].get());
*why << "\n";
@@ -1775,14 +1792,10 @@ class FunctionMockerBase : public UntypedFunctionMockerBase {
}
}
- // The current spec (either default action spec or expectation spec)
- // being described on this function mocker.
- MockSpec<F> current_spec_;
-
// There is no generally useful and implementable semantics of
// copying a mock object, so copying a mock is usually a user error.
// Thus we disallow copying function mockers. If the user really
- // wants to copy a mock object, he should implement his own copy
+ // wants to copy a mock object, they should implement their own copy
// operation, for example:
//
// class MockFoo : public Foo {
@@ -1794,9 +1807,7 @@ class FunctionMockerBase : public UntypedFunctionMockerBase {
GTEST_DISALLOW_COPY_AND_ASSIGN_(FunctionMockerBase);
}; // class FunctionMockerBase
-#ifdef _MSC_VER
-# pragma warning(pop) // Restores the warning state.
-#endif // _MSV_VER
+GTEST_DISABLE_MSC_WARNINGS_POP_() // 4355
// Implements methods of FunctionMockerBase.
@@ -1806,7 +1817,7 @@ class FunctionMockerBase : public UntypedFunctionMockerBase {
// Reports an uninteresting call (whose description is in msg) in the
// manner specified by 'reaction'.
-void ReportUninterestingCall(CallReaction reaction, const string& msg);
+void ReportUninterestingCall(CallReaction reaction, const std::string& msg);
} // namespace internal
@@ -1841,17 +1852,78 @@ 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)
-
-#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)
+GTEST_DISABLE_MSC_WARNINGS_POP_() // 4251
+
+// 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 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_