summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorzhanyong.wan <zhanyong.wan@8415998a-534a-0410-bf83-d39667b30386>2011-02-23 19:39:27 +0000
committerzhanyong.wan <zhanyong.wan@8415998a-534a-0410-bf83-d39667b30386>2011-02-23 19:39:27 +0000
commit580f3c8adc14ce88999b7e2bd5f92e4231f95b31 (patch)
tree463781d99fd74011cb43829a73bad5023350a22f
parentdee0830e18bfee0e6a88696863004f6db4d3d0b3 (diff)
downloadgooglemock-580f3c8adc14ce88999b7e2bd5f92e4231f95b31.tar.gz
Makes Google Mock compile much faster and use much less memory; reviewed by Nico Weber. This fixes issue 68.
git-svn-id: http://googlemock.googlecode.com/svn/trunk@359 8415998a-534a-0410-bf83-d39667b30386
-rw-r--r--include/gmock/gmock-actions.h63
-rw-r--r--include/gmock/gmock-generated-function-mockers.h63
-rw-r--r--include/gmock/gmock-generated-function-mockers.h.pump3
-rw-r--r--include/gmock/gmock-spec-builders.h852
-rwxr-xr-xscripts/gmock_doctor.py4
-rw-r--r--src/gmock-spec-builders.cc338
-rw-r--r--test/gmock-actions_test.cc3
-rw-r--r--test/gmock-spec-builders_test.cc57
8 files changed, 813 insertions, 570 deletions
diff --git a/include/gmock/gmock-actions.h b/include/gmock/gmock-actions.h
index f88ac80..af3483f 100644
--- a/include/gmock/gmock-actions.h
+++ b/include/gmock/gmock-actions.h
@@ -59,9 +59,6 @@ namespace testing {
namespace internal {
-template <typename F>
-class MonomorphicDoDefaultActionImpl;
-
template <typename F1, typename F2>
class ActionAdaptor;
@@ -255,8 +252,7 @@ class ActionInterface {
typedef typename internal::Function<F>::Result Result;
typedef typename internal::Function<F>::ArgumentTuple ArgumentTuple;
- ActionInterface() : is_do_default_(false) {}
-
+ ActionInterface() {}
virtual ~ActionInterface() {}
// Performs the action. This method is not const, as in general an
@@ -265,21 +261,7 @@ class ActionInterface {
// remember the current element.
virtual Result Perform(const ArgumentTuple& args) = 0;
- // Returns true iff this is the DoDefault() action.
- bool IsDoDefault() const { return is_do_default_; }
-
private:
- template <typename Function>
- friend class internal::MonomorphicDoDefaultActionImpl;
-
- // This private constructor is reserved for implementing
- // DoDefault(), the default action for a given mock function.
- explicit ActionInterface(bool is_do_default)
- : is_do_default_(is_do_default) {}
-
- // True iff this action is DoDefault().
- const bool is_do_default_;
-
GTEST_DISALLOW_COPY_AND_ASSIGN_(ActionInterface);
};
@@ -302,7 +284,8 @@ class Action {
// STL containers.
Action() : impl_(NULL) {}
- // Constructs an Action from its implementation.
+ // Constructs an Action from its implementation. A NULL impl is
+ // used to represent the "do-default" action.
explicit Action(ActionInterface<F>* impl) : impl_(impl) {}
// Copy constructor.
@@ -316,7 +299,7 @@ class Action {
explicit Action(const Action<Func>& action);
// Returns true iff this is the DoDefault() action.
- bool IsDoDefault() const { return impl_->IsDoDefault(); }
+ bool IsDoDefault() const { return impl_.get() == NULL; }
// Performs the action. Note that this method is const even though
// the corresponding method in ActionInterface is not. The reason
@@ -325,6 +308,13 @@ class Action {
// cannot change state. (Think of the difference between a const
// pointer and a pointer to const.)
Result Perform(const ArgumentTuple& args) const {
+ internal::Assert(
+ !IsDoDefault(), __FILE__, __LINE__,
+ "You are using DoDefault() inside a composite action like "
+ "DoAll() or WithArgs(). This is not supported for technical "
+ "reasons. Please instead spell out the default action, or "
+ "assign the default action to an Action variable and use "
+ "the variable in various places.");
return impl_->Perform(args);
}
@@ -633,42 +623,13 @@ class ReturnRefOfCopyAction {
GTEST_DISALLOW_ASSIGN_(ReturnRefOfCopyAction);
};
-// Implements the DoDefault() action for a particular function type F.
-template <typename F>
-class MonomorphicDoDefaultActionImpl : public ActionInterface<F> {
- public:
- typedef typename Function<F>::Result Result;
- typedef typename Function<F>::ArgumentTuple ArgumentTuple;
-
- MonomorphicDoDefaultActionImpl() : ActionInterface<F>(true) {}
-
- // For technical reasons, DoDefault() cannot be used inside a
- // composite action (e.g. DoAll(...)). It can only be used at the
- // top level in an EXPECT_CALL(). If this function is called, the
- // user must be using DoDefault() inside a composite action, and we
- // have to generate a run-time error.
- virtual Result Perform(const ArgumentTuple&) {
- Assert(false, __FILE__, __LINE__,
- "You are using DoDefault() inside a composite action like "
- "DoAll() or WithArgs(). This is not supported for technical "
- "reasons. Please instead spell out the default action, or "
- "assign the default action to an Action variable and use "
- "the variable in various places.");
- return internal::Invalid<Result>();
- // The above statement will never be reached, but is required in
- // order for this function to compile.
- }
-};
-
// Implements the polymorphic DoDefault() action.
class DoDefaultAction {
public:
// This template type conversion operator allows DoDefault() to be
// used in any function.
template <typename F>
- operator Action<F>() const {
- return Action<F>(new MonomorphicDoDefaultActionImpl<F>);
- }
+ operator Action<F>() const { return Action<F>(NULL); }
};
// Implements the Assign action to set a given pointer referent to a
diff --git a/include/gmock/gmock-generated-function-mockers.h b/include/gmock/gmock-generated-function-mockers.h
index 7b334e4..509d46c 100644
--- a/include/gmock/gmock-generated-function-mockers.h
+++ b/include/gmock/gmock-generated-function-mockers.h
@@ -1,4 +1,6 @@
-// This file was GENERATED by a script. DO NOT EDIT BY HAND!!!
+// This file was GENERATED by command:
+// pump.py gmock-generated-function-mockers.h.pump
+// DO NOT EDIT BY HAND!!!
// Copyright 2007, Google Inc.
// All rights reserved.
@@ -352,7 +354,8 @@ using internal::FunctionMocker;
} \
::testing::MockSpec<F>& \
gmock_##Method() constness { \
- return GMOCK_MOCKER_(0, constness, Method).RegisterOwner(this).With(); \
+ GMOCK_MOCKER_(0, constness, Method).RegisterOwner(this); \
+ return GMOCK_MOCKER_(0, constness, Method).With(); \
} \
mutable ::testing::FunctionMocker<F> GMOCK_MOCKER_(0, constness, Method)
@@ -367,8 +370,8 @@ using internal::FunctionMocker;
} \
::testing::MockSpec<F>& \
gmock_##Method(GMOCK_MATCHER_(tn, F, 1) gmock_a1) constness { \
- return GMOCK_MOCKER_(1, constness, \
- Method).RegisterOwner(this).With(gmock_a1); \
+ GMOCK_MOCKER_(1, constness, Method).RegisterOwner(this); \
+ return GMOCK_MOCKER_(1, constness, Method).With(gmock_a1); \
} \
mutable ::testing::FunctionMocker<F> GMOCK_MOCKER_(1, constness, Method)
@@ -385,8 +388,8 @@ using internal::FunctionMocker;
::testing::MockSpec<F>& \
gmock_##Method(GMOCK_MATCHER_(tn, F, 1) gmock_a1, \
GMOCK_MATCHER_(tn, F, 2) gmock_a2) constness { \
- return GMOCK_MOCKER_(2, constness, \
- Method).RegisterOwner(this).With(gmock_a1, gmock_a2); \
+ GMOCK_MOCKER_(2, constness, Method).RegisterOwner(this); \
+ return GMOCK_MOCKER_(2, constness, Method).With(gmock_a1, gmock_a2); \
} \
mutable ::testing::FunctionMocker<F> GMOCK_MOCKER_(2, constness, Method)
@@ -406,8 +409,9 @@ using internal::FunctionMocker;
gmock_##Method(GMOCK_MATCHER_(tn, F, 1) gmock_a1, \
GMOCK_MATCHER_(tn, F, 2) gmock_a2, \
GMOCK_MATCHER_(tn, F, 3) gmock_a3) constness { \
- return GMOCK_MOCKER_(3, constness, \
- Method).RegisterOwner(this).With(gmock_a1, gmock_a2, gmock_a3); \
+ GMOCK_MOCKER_(3, constness, Method).RegisterOwner(this); \
+ return GMOCK_MOCKER_(3, constness, Method).With(gmock_a1, gmock_a2, \
+ gmock_a3); \
} \
mutable ::testing::FunctionMocker<F> GMOCK_MOCKER_(3, constness, Method)
@@ -429,9 +433,9 @@ using internal::FunctionMocker;
GMOCK_MATCHER_(tn, F, 2) gmock_a2, \
GMOCK_MATCHER_(tn, F, 3) gmock_a3, \
GMOCK_MATCHER_(tn, F, 4) gmock_a4) constness { \
- return GMOCK_MOCKER_(4, constness, \
- Method).RegisterOwner(this).With(gmock_a1, gmock_a2, gmock_a3, \
- gmock_a4); \
+ GMOCK_MOCKER_(4, constness, Method).RegisterOwner(this); \
+ return GMOCK_MOCKER_(4, constness, Method).With(gmock_a1, gmock_a2, \
+ gmock_a3, gmock_a4); \
} \
mutable ::testing::FunctionMocker<F> GMOCK_MOCKER_(4, constness, Method)
@@ -455,9 +459,9 @@ using internal::FunctionMocker;
GMOCK_MATCHER_(tn, F, 3) gmock_a3, \
GMOCK_MATCHER_(tn, F, 4) gmock_a4, \
GMOCK_MATCHER_(tn, F, 5) gmock_a5) constness { \
- return GMOCK_MOCKER_(5, constness, \
- Method).RegisterOwner(this).With(gmock_a1, gmock_a2, gmock_a3, \
- gmock_a4, gmock_a5); \
+ GMOCK_MOCKER_(5, constness, Method).RegisterOwner(this); \
+ return GMOCK_MOCKER_(5, constness, Method).With(gmock_a1, gmock_a2, \
+ gmock_a3, gmock_a4, gmock_a5); \
} \
mutable ::testing::FunctionMocker<F> GMOCK_MOCKER_(5, constness, Method)
@@ -483,9 +487,9 @@ using internal::FunctionMocker;
GMOCK_MATCHER_(tn, F, 4) gmock_a4, \
GMOCK_MATCHER_(tn, F, 5) gmock_a5, \
GMOCK_MATCHER_(tn, F, 6) gmock_a6) constness { \
- return GMOCK_MOCKER_(6, constness, \
- Method).RegisterOwner(this).With(gmock_a1, gmock_a2, gmock_a3, \
- gmock_a4, gmock_a5, gmock_a6); \
+ GMOCK_MOCKER_(6, constness, Method).RegisterOwner(this); \
+ return GMOCK_MOCKER_(6, constness, Method).With(gmock_a1, gmock_a2, \
+ gmock_a3, gmock_a4, gmock_a5, gmock_a6); \
} \
mutable ::testing::FunctionMocker<F> GMOCK_MOCKER_(6, constness, Method)
@@ -513,9 +517,9 @@ using internal::FunctionMocker;
GMOCK_MATCHER_(tn, F, 5) gmock_a5, \
GMOCK_MATCHER_(tn, F, 6) gmock_a6, \
GMOCK_MATCHER_(tn, F, 7) gmock_a7) constness { \
- return GMOCK_MOCKER_(7, constness, \
- Method).RegisterOwner(this).With(gmock_a1, gmock_a2, gmock_a3, \
- gmock_a4, gmock_a5, gmock_a6, gmock_a7); \
+ GMOCK_MOCKER_(7, constness, Method).RegisterOwner(this); \
+ return GMOCK_MOCKER_(7, constness, Method).With(gmock_a1, gmock_a2, \
+ gmock_a3, gmock_a4, gmock_a5, gmock_a6, gmock_a7); \
} \
mutable ::testing::FunctionMocker<F> GMOCK_MOCKER_(7, constness, Method)
@@ -545,9 +549,9 @@ using internal::FunctionMocker;
GMOCK_MATCHER_(tn, F, 6) gmock_a6, \
GMOCK_MATCHER_(tn, F, 7) gmock_a7, \
GMOCK_MATCHER_(tn, F, 8) gmock_a8) constness { \
- return GMOCK_MOCKER_(8, constness, \
- Method).RegisterOwner(this).With(gmock_a1, gmock_a2, gmock_a3, \
- gmock_a4, gmock_a5, gmock_a6, gmock_a7, gmock_a8); \
+ GMOCK_MOCKER_(8, constness, Method).RegisterOwner(this); \
+ return GMOCK_MOCKER_(8, constness, Method).With(gmock_a1, gmock_a2, \
+ gmock_a3, gmock_a4, gmock_a5, gmock_a6, gmock_a7, gmock_a8); \
} \
mutable ::testing::FunctionMocker<F> GMOCK_MOCKER_(8, constness, Method)
@@ -580,9 +584,10 @@ using internal::FunctionMocker;
GMOCK_MATCHER_(tn, F, 7) gmock_a7, \
GMOCK_MATCHER_(tn, F, 8) gmock_a8, \
GMOCK_MATCHER_(tn, F, 9) gmock_a9) constness { \
- return GMOCK_MOCKER_(9, constness, \
- Method).RegisterOwner(this).With(gmock_a1, gmock_a2, gmock_a3, \
- gmock_a4, gmock_a5, gmock_a6, gmock_a7, gmock_a8, gmock_a9); \
+ GMOCK_MOCKER_(9, constness, Method).RegisterOwner(this); \
+ return GMOCK_MOCKER_(9, constness, Method).With(gmock_a1, gmock_a2, \
+ gmock_a3, gmock_a4, gmock_a5, gmock_a6, gmock_a7, gmock_a8, \
+ gmock_a9); \
} \
mutable ::testing::FunctionMocker<F> GMOCK_MOCKER_(9, constness, Method)
@@ -617,9 +622,9 @@ using internal::FunctionMocker;
GMOCK_MATCHER_(tn, F, 8) gmock_a8, \
GMOCK_MATCHER_(tn, F, 9) gmock_a9, \
GMOCK_MATCHER_(tn, F, 10) gmock_a10) constness { \
- return GMOCK_MOCKER_(10, constness, \
- Method).RegisterOwner(this).With(gmock_a1, gmock_a2, gmock_a3, \
- gmock_a4, gmock_a5, gmock_a6, gmock_a7, gmock_a8, gmock_a9, \
+ GMOCK_MOCKER_(10, constness, Method).RegisterOwner(this); \
+ return GMOCK_MOCKER_(10, constness, Method).With(gmock_a1, gmock_a2, \
+ gmock_a3, gmock_a4, gmock_a5, gmock_a6, gmock_a7, gmock_a8, gmock_a9, \
gmock_a10); \
} \
mutable ::testing::FunctionMocker<F> GMOCK_MOCKER_(10, constness, Method)
diff --git a/include/gmock/gmock-generated-function-mockers.h.pump b/include/gmock/gmock-generated-function-mockers.h.pump
index 50b369b..4f82d62 100644
--- a/include/gmock/gmock-generated-function-mockers.h.pump
+++ b/include/gmock/gmock-generated-function-mockers.h.pump
@@ -140,7 +140,8 @@ $var matcher_as = [[$for j, \
} \
::testing::MockSpec<F>& \
gmock_##Method($matcher_as) constness { \
- return GMOCK_MOCKER_($i, constness, Method).RegisterOwner(this).With($as); \
+ GMOCK_MOCKER_($i, constness, Method).RegisterOwner(this); \
+ return GMOCK_MOCKER_($i, constness, Method).With($as); \
} \
mutable ::testing::FunctionMocker<F> GMOCK_MOCKER_($i, constness, Method)
diff --git a/include/gmock/gmock-spec-builders.h b/include/gmock/gmock-spec-builders.h
index 4f0b072..9e18508 100644
--- a/include/gmock/gmock-spec-builders.h
+++ b/include/gmock/gmock-spec-builders.h
@@ -113,53 +113,190 @@ template <typename F> class FunctionMockerBase;
// calls to ensure the integrity of the mock objects' states.
GTEST_DECLARE_STATIC_MUTEX_(g_gmock_mutex);
+// Untyped base class for ActionResultHolder<R>.
+class UntypedActionResultHolderBase;
+
// Abstract base class of FunctionMockerBase. This is the
// type-agnostic part of the function mocker interface. Its pure
// virtual methods are implemented by FunctionMockerBase.
class UntypedFunctionMockerBase {
public:
- virtual ~UntypedFunctionMockerBase() {}
+ UntypedFunctionMockerBase();
+ virtual ~UntypedFunctionMockerBase();
// Verifies that all expectations on this mock function have been
// satisfied. Reports one or more Google Test non-fatal failures
// and returns false if not.
// L >= g_gmock_mutex
- virtual bool VerifyAndClearExpectationsLocked() = 0;
+ bool VerifyAndClearExpectationsLocked();
// Clears the ON_CALL()s set on this mock function.
// L >= g_gmock_mutex
virtual void ClearDefaultActionsLocked() = 0;
+
+ // In all of the following Untyped* functions, it's the caller's
+ // responsibility to guarantee the correctness of the arguments'
+ // types.
+
+ // Performs the default action with the given arguments and returns
+ // the action's result. The call description string will be used in
+ // the error message to describe the call in the case the default
+ // action fails.
+ // L = *
+ virtual UntypedActionResultHolderBase* UntypedPerformDefaultAction(
+ const void* untyped_args,
+ const 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;
+
+ // Writes a message that the call is uninteresting (i.e. neither
+ // explicitly expected nor explicitly unexpected) to the given
+ // ostream.
+ // L < g_gmock_mutex
+ virtual void UntypedDescribeUninterestingCall(const void* untyped_args,
+ ::std::ostream* os) const = 0;
+
+ // Returns the expectation that matches the given function arguments
+ // (or NULL is there's no match); when a match is found,
+ // untyped_action is set to point to the action that should be
+ // performed (or NULL if the action is "do default"), and
+ // is_excessive is modified to indicate whether the call exceeds the
+ // expected number.
+ // L < g_gmock_mutex
+ virtual const ExpectationBase* UntypedFindMatchingExpectation(
+ const void* untyped_args,
+ const void** untyped_action, bool* is_excessive,
+ ::std::ostream* what, ::std::ostream* why) = 0;
+
+ // Prints the given function arguments to the ostream.
+ virtual void UntypedPrintArgs(const void* untyped_args,
+ ::std::ostream* os) const = 0;
+
+ // Sets the mock object this mock method belongs to, and registers
+ // 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().
+ // L < g_gmock_mutex
+ void RegisterOwner(const void* mock_obj);
+
+ // Sets the mock object this mock method belongs to, and sets the
+ // name of the mock function. Will be called upon each invocation
+ // of this mock function.
+ // L < g_gmock_mutex
+ void SetOwnerAndName(const void* mock_obj, const char* name);
+
+ // Returns the mock object this mock method belongs to. Must be
+ // called after RegisterOwner() or SetOwnerAndName() has been
+ // called.
+ // L < g_gmock_mutex
+ const void* MockObject() const;
+
+ // Returns the name of this mock method. Must be called after
+ // SetOwnerAndName() has been called.
+ // L < g_gmock_mutex
+ const char* Name() const;
+
+ // Returns the result of invoking this mock function with the given
+ // arguments. This function can be safely called from multiple
+ // threads concurrently. The caller is responsible for deleting the
+ // result.
+ // L < g_gmock_mutex
+ const UntypedActionResultHolderBase* UntypedInvokeWith(
+ const void* untyped_args);
+
+ protected:
+ typedef std::vector<const void*> UntypedOnCallSpecs;
+
+ typedef std::vector<internal::linked_ptr<ExpectationBase> >
+ UntypedExpectations;
+
+ // Returns an Expectation object that references and co-owns exp,
+ // which must be an expectation on this mock function.
+ Expectation GetHandleOf(ExpectationBase* exp);
+
+ // Address of the mock object this mock method belongs to. Only
+ // valid after this mock method has been called or
+ // ON_CALL/EXPECT_CALL has been invoked on it.
+ const void* mock_obj_; // Protected by g_gmock_mutex.
+
+ // Name of the function being mocked. Only valid after this mock
+ // method has been called.
+ const char* name_; // Protected by g_gmock_mutex.
+
+ // All default action specs for this function mocker.
+ UntypedOnCallSpecs untyped_on_call_specs_;
+
+ // All expectations for this function mocker.
+ UntypedExpectations untyped_expectations_;
}; // class UntypedFunctionMockerBase
-// This template class implements a default action spec (i.e. an
-// ON_CALL() statement).
+// Untyped base class for OnCallSpec<F>.
+class UntypedOnCallSpecBase {
+ public:
+ // The arguments are the location of the ON_CALL() statement.
+ UntypedOnCallSpecBase(const char* a_file, int a_line)
+ : file_(a_file), line_(a_line), last_clause_(kNone) {}
+
+ // Where in the source file was the default action spec defined?
+ const char* file() const { return file_; }
+ int line() const { return line_; }
+
+ protected:
+ // Gives each clause in the ON_CALL() statement a name.
+ enum Clause {
+ // Do not change the order of the enum members! The run-time
+ // syntax checking relies on it.
+ kNone,
+ kWith,
+ kWillByDefault,
+ };
+
+ // Asserts that the ON_CALL() statement has a certain property.
+ void AssertSpecProperty(bool property, const 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 {
+ Expect(property, file_, line_, failure_message);
+ }
+
+ const char* file_;
+ int line_;
+
+ // The last clause in the ON_CALL() statement as seen so far.
+ // Initially kNone and changes as the statement is parsed.
+ Clause last_clause_;
+}; // class UntypedOnCallSpecBase
+
+// This template class implements an ON_CALL spec.
template <typename F>
-class DefaultActionSpec {
+class OnCallSpec : public UntypedOnCallSpecBase {
public:
typedef typename Function<F>::ArgumentTuple ArgumentTuple;
typedef typename Function<F>::ArgumentMatcherTuple ArgumentMatcherTuple;
- // Constructs a DefaultActionSpec object from the information inside
+ // Constructs an OnCallSpec object from the information inside
// the parenthesis of an ON_CALL() statement.
- DefaultActionSpec(const char* a_file, int a_line,
- const ArgumentMatcherTuple& matchers)
- : file_(a_file),
- line_(a_line),
+ OnCallSpec(const char* a_file, int a_line,
+ const ArgumentMatcherTuple& matchers)
+ : UntypedOnCallSpecBase(a_file, a_line),
matchers_(matchers),
// By default, extra_matcher_ should match anything. However,
// we cannot initialize it with _ as that triggers a compiler
// bug in Symbian's C++ compiler (cannot decide between two
// overloaded constructors of Matcher<const ArgumentTuple&>).
- extra_matcher_(A<const ArgumentTuple&>()),
- last_clause_(kNone) {
+ extra_matcher_(A<const ArgumentTuple&>()) {
}
- // Where in the source file was the default action spec defined?
- const char* file() const { return file_; }
- int line() const { return line_; }
-
// Implements the .With() clause.
- DefaultActionSpec& With(const Matcher<const ArgumentTuple&>& m) {
+ OnCallSpec& With(const Matcher<const ArgumentTuple&>& m) {
// Makes sure this is called at most once.
ExpectSpecProperty(last_clause_ < kWith,
".With() cannot appear "
@@ -171,7 +308,7 @@ class DefaultActionSpec {
}
// Implements the .WillByDefault() clause.
- DefaultActionSpec& WillByDefault(const Action<F>& action) {
+ OnCallSpec& WillByDefault(const Action<F>& action) {
ExpectSpecProperty(last_clause_ < kWillByDefault,
".WillByDefault() must appear "
"exactly once in an ON_CALL().");
@@ -197,25 +334,6 @@ class DefaultActionSpec {
}
private:
- // Gives each clause in the ON_CALL() statement a name.
- enum Clause {
- // Do not change the order of the enum members! The run-time
- // syntax checking relies on it.
- kNone,
- kWith,
- kWillByDefault,
- };
-
- // Asserts that the ON_CALL() statement has a certain property.
- void AssertSpecProperty(bool property, const 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 {
- Expect(property, file_, line_, failure_message);
- }
-
// The information in statement
//
// ON_CALL(mock_object, Method(matchers))
@@ -229,16 +347,10 @@ class DefaultActionSpec {
// matchers => matchers_
// multi-argument-matcher => extra_matcher_
// action => action_
- const char* file_;
- int line_;
ArgumentMatcherTuple matchers_;
Matcher<const ArgumentTuple&> extra_matcher_;
Action<F> action_;
-
- // The last clause in the ON_CALL() statement as seen so far.
- // Initially kNone and changes as the statement is parsed.
- Clause last_clause_;
-}; // class DefaultActionSpec
+}; // class OnCallSpec
// Possible reactions on uninteresting calls. TODO(wan@google.com):
// rename the enum values to the kFoo style.
@@ -269,6 +381,8 @@ class Mock {
// verification was successful.
static bool VerifyAndClear(void* mock_obj);
private:
+ friend class internal::UntypedFunctionMockerBase;
+
// Needed for a function mocker to register itself (so that we know
// how to clear a mock object).
template <typename F>
@@ -389,6 +503,7 @@ class Expectation {
friend class ExpectationSet;
friend class Sequence;
friend class ::testing::internal::ExpectationBase;
+ friend class ::testing::internal::UntypedFunctionMockerBase;
template <typename F>
friend class ::testing::internal::FunctionMockerBase;
@@ -581,10 +696,15 @@ class ExpectationBase {
// Describes how many times a function call matching this
// expectation has occurred.
// L >= g_gmock_mutex
- virtual void DescribeCallCountTo(::std::ostream* os) const = 0;
+ void DescribeCallCountTo(::std::ostream* os) const;
+
+ // If this mock method has an extra matcher (i.e. .With(matcher)),
+ // describes it to the ostream.
+ virtual void MaybeDescribeExtraMatcherTo(::std::ostream* os) = 0;
protected:
friend class ::testing::Expectation;
+ friend class UntypedFunctionMockerBase;
enum Clause {
// Don't change the order of the enum members!
@@ -598,6 +718,8 @@ class ExpectationBase {
kRetiresOnSaturation,
};
+ typedef std::vector<const void*> UntypedActions;
+
// Returns an Expectation object that references and co-owns this
// expectation.
virtual Expectation GetHandle() = 0;
@@ -690,13 +812,22 @@ class ExpectationBase {
call_count_++;
}
- private:
+ // Checks the action count (i.e. the number of WillOnce() and
+ // WillRepeatedly() clauses) against the cardinality if this hasn't
+ // been done before. Prints a warning if there are too many or too
+ // few actions.
+ // L < mutex_
+ void CheckActionCountIfNotDone() const;
+
friend class ::testing::Sequence;
friend class ::testing::internal::ExpectationTester;
template <typename Function>
friend class TypedExpectation;
+ // Implements the .Times() clause.
+ void UntypedTimes(const Cardinality& a_cardinality);
+
// This group of fields are part of the spec and won't change after
// an EXPECT_CALL() statement finishes.
const char* file_; // The file that contains the expectation.
@@ -717,6 +848,13 @@ class ExpectationBase {
// and can change as the mock function is called.
int call_count_; // How many times this expectation has been invoked.
bool retired_; // True iff this expectation has retired.
+ UntypedActions untyped_actions_;
+ bool extra_matcher_specified_;
+ bool repeated_action_specified_; // True if a WillRepeatedly() was specified.
+ bool retires_on_saturation_;
+ Clause last_clause_;
+ mutable bool action_count_checked_; // Under mutex_.
+ mutable Mutex mutex_; // Protects action_count_checked_.
GTEST_DISALLOW_ASSIGN_(ExpectationBase);
}; // class ExpectationBase
@@ -735,22 +873,21 @@ class TypedExpectation : public ExpectationBase {
: ExpectationBase(a_file, a_line, a_source_text),
owner_(owner),
matchers_(m),
- extra_matcher_specified_(false),
// By default, extra_matcher_ should match anything. However,
// we cannot initialize it with _ as that triggers a compiler
// bug in Symbian's C++ compiler (cannot decide between two
// overloaded constructors of Matcher<const ArgumentTuple&>).
extra_matcher_(A<const ArgumentTuple&>()),
- repeated_action_specified_(false),
- repeated_action_(DoDefault()),
- retires_on_saturation_(false),
- last_clause_(kNone),
- action_count_checked_(false) {}
+ repeated_action_(DoDefault()) {}
virtual ~TypedExpectation() {
// Check the validity of the action count if it hasn't been done
// yet (for example, if the expectation was never used).
CheckActionCountIfNotDone();
+ for (UntypedActions::const_iterator it = untyped_actions_.begin();
+ it != untyped_actions_.end(); ++it) {
+ delete static_cast<const Action<F>*>(*it);
+ }
}
// Implements the .With() clause.
@@ -773,19 +910,7 @@ class TypedExpectation : public ExpectationBase {
// Implements the .Times() clause.
TypedExpectation& Times(const Cardinality& a_cardinality) {
- if (last_clause_ ==kTimes) {
- ExpectSpecProperty(false,
- ".Times() cannot appear "
- "more than once in an EXPECT_CALL().");
- } else {
- ExpectSpecProperty(last_clause_ < kTimes,
- ".Times() cannot appear after "
- ".InSequence(), .WillOnce(), .WillRepeatedly(), "
- "or .RetiresOnSaturation().");
- }
- last_clause_ = kTimes;
-
- ExpectationBase::SpecifyCardinality(a_cardinality);
+ ExpectationBase::UntypedTimes(a_cardinality);
return *this;
}
@@ -859,9 +984,9 @@ class TypedExpectation : public ExpectationBase {
".WillRepeatedly() or .RetiresOnSaturation().");
last_clause_ = kWillOnce;
- actions_.push_back(action);
+ untyped_actions_.push_back(new Action<F>(action));
if (!cardinality_specified()) {
- set_cardinality(Exactly(static_cast<int>(actions_.size())));
+ set_cardinality(Exactly(static_cast<int>(untyped_actions_.size())));
}
return *this;
}
@@ -882,7 +1007,7 @@ class TypedExpectation : public ExpectationBase {
repeated_action_ = action;
if (!cardinality_specified()) {
- set_cardinality(AtLeast(static_cast<int>(actions_.size())));
+ set_cardinality(AtLeast(static_cast<int>(untyped_actions_.size())));
}
// Now that no more action clauses can be specified, we check
@@ -916,38 +1041,12 @@ class TypedExpectation : public ExpectationBase {
return extra_matcher_;
}
- // Returns the sequence of actions specified by the .WillOnce() clause.
- const std::vector<Action<F> >& actions() const { return actions_; }
-
// Returns the action specified by the .WillRepeatedly() clause.
const Action<F>& repeated_action() const { return repeated_action_; }
- // Returns true iff the .RetiresOnSaturation() clause was specified.
- bool retires_on_saturation() const { return retires_on_saturation_; }
-
- // Describes how many times a function call matching this
- // expectation has occurred (implements
- // ExpectationBase::DescribeCallCountTo()).
- // L >= g_gmock_mutex
- virtual void DescribeCallCountTo(::std::ostream* os) const {
- g_gmock_mutex.AssertHeld();
-
- // Describes how many times the function is expected to be called.
- *os << " Expected: to be ";
- cardinality().DescribeTo(os);
- *os << "\n Actual: ";
- Cardinality::DescribeActualCallCountTo(call_count(), os);
-
- // Describes the state of the expectation (e.g. is it satisfied?
- // is it active?).
- *os << " - " << (IsOverSaturated() ? "over-saturated" :
- IsSaturated() ? "saturated" :
- IsSatisfied() ? "satisfied" : "unsatisfied")
- << " and "
- << (is_retired() ? "retired" : "active");
- }
-
- void MaybeDescribeExtraMatcherTo(::std::ostream* os) {
+ // If this mock method has an extra matcher (i.e. .With(matcher)),
+ // describes it to the ostream.
+ virtual void MaybeDescribeExtraMatcherTo(::std::ostream* os) {
if (extra_matcher_specified_) {
*os << " Expected args: ";
extra_matcher_.DescribeTo(os);
@@ -1044,7 +1143,7 @@ class TypedExpectation : public ExpectationBase {
"call_count() is <= 0 when GetCurrentAction() is "
"called - this should never happen.");
- const int action_count = static_cast<int>(actions().size());
+ const int action_count = static_cast<int>(untyped_actions_.size());
if (action_count > 0 && !repeated_action_specified_ &&
count > action_count) {
// If there is at least one WillOnce() and no WillRepeatedly(),
@@ -1059,7 +1158,9 @@ class TypedExpectation : public ExpectationBase {
Log(WARNING, ss.str(), 1);
}
- return count <= action_count ? actions()[count - 1] : repeated_action();
+ return count <= action_count ?
+ *static_cast<const Action<F>*>(untyped_actions_[count - 1]) :
+ repeated_action();
}
// Given the arguments of a mock function call, if the call will
@@ -1067,12 +1168,13 @@ class TypedExpectation : public ExpectationBase {
// otherwise, returns the next action in this expectation. Also
// describes *what* happened to 'what', and explains *why* Google
// Mock does it to 'why'. This method is not const as it calls
- // IncrementCallCount().
+ // IncrementCallCount(). A return value of NULL means the default
+ // action.
// L >= g_gmock_mutex
- Action<F> GetActionForArguments(const FunctionMockerBase<F>* mocker,
- const ArgumentTuple& args,
- ::std::ostream* what,
- ::std::ostream* why) {
+ const Action<F>* GetActionForArguments(const FunctionMockerBase<F>* mocker,
+ const ArgumentTuple& args,
+ ::std::ostream* what,
+ ::std::ostream* why) {
g_gmock_mutex.AssertHeld();
if (IsSaturated()) {
// We have an excessive call.
@@ -1081,92 +1183,30 @@ class TypedExpectation : public ExpectationBase {
mocker->DescribeDefaultActionTo(args, what);
DescribeCallCountTo(why);
- // TODO(wan): allow the user to control whether unexpected calls
- // should fail immediately or continue using a flag
- // --gmock_unexpected_calls_are_fatal.
- return DoDefault();
+ // TODO(wan@google.com): allow the user to control whether
+ // unexpected calls should fail immediately or continue using a
+ // flag --gmock_unexpected_calls_are_fatal.
+ return NULL;
}
IncrementCallCount();
RetireAllPreRequisites();
- if (retires_on_saturation() && IsSaturated()) {
+ if (retires_on_saturation_ && IsSaturated()) {
Retire();
}
// Must be done after IncrementCount()!
*what << "Mock function call matches " << source_text() <<"...\n";
- return GetCurrentAction(mocker, args);
- }
-
- // Checks the action count (i.e. the number of WillOnce() and
- // WillRepeatedly() clauses) against the cardinality if this hasn't
- // been done before. Prints a warning if there are too many or too
- // few actions.
- // L < mutex_
- void CheckActionCountIfNotDone() const {
- bool should_check = false;
- {
- MutexLock l(&mutex_);
- if (!action_count_checked_) {
- action_count_checked_ = true;
- should_check = true;
- }
- }
-
- if (should_check) {
- if (!cardinality_specified_) {
- // The cardinality was inferred - no need to check the action
- // count against it.
- return;
- }
-
- // The cardinality was explicitly specified.
- const int action_count = static_cast<int>(actions_.size());
- const int upper_bound = cardinality().ConservativeUpperBound();
- const int lower_bound = cardinality().ConservativeLowerBound();
- bool too_many; // True if there are too many actions, or false
- // if there are too few.
- if (action_count > upper_bound ||
- (action_count == upper_bound && repeated_action_specified_)) {
- too_many = true;
- } else if (0 < action_count && action_count < lower_bound &&
- !repeated_action_specified_) {
- too_many = false;
- } else {
- return;
- }
-
- ::std::stringstream ss;
- DescribeLocationTo(&ss);
- ss << "Too " << (too_many ? "many" : "few")
- << " actions specified in " << source_text() << "...\n"
- << "Expected to be ";
- cardinality().DescribeTo(&ss);
- ss << ", but has " << (too_many ? "" : "only ")
- << action_count << " WillOnce()"
- << (action_count == 1 ? "" : "s");
- if (repeated_action_specified_) {
- ss << " and a WillRepeatedly()";
- }
- ss << ".";
- Log(WARNING, ss.str(), -1); // -1 means "don't print stack trace".
- }
+ return &(GetCurrentAction(mocker, args));
}
// All the fields below won't change once the EXPECT_CALL()
// statement finishes.
FunctionMockerBase<F>* const owner_;
ArgumentMatcherTuple matchers_;
- bool extra_matcher_specified_;
Matcher<const ArgumentTuple&> extra_matcher_;
- std::vector<Action<F> > actions_;
- bool repeated_action_specified_; // True if a WillRepeatedly() was specified.
Action<F> repeated_action_;
- bool retires_on_saturation_;
- Clause last_clause_;
- mutable bool action_count_checked_; // Under mutex_.
- mutable Mutex mutex_; // Protects action_count_checked_.
GTEST_DISALLOW_COPY_AND_ASSIGN_(TypedExpectation);
}; // class TypedExpectation
@@ -1181,6 +1221,11 @@ class TypedExpectation : public ExpectationBase {
// template. To workaround this compiler bug, we define MockSpec in
// ::testing::internal and import it into ::testing.
+// Logs a message including file and line number information.
+void LogWithLocation(testing::internal::LogSeverity severity,
+ const char* file, int line,
+ const string& message);
+
template <typename F>
class MockSpec {
public:
@@ -1195,11 +1240,11 @@ class MockSpec {
// Adds a new default action spec to the function mocker and returns
// the newly created spec.
- internal::DefaultActionSpec<F>& InternalDefaultActionSetAt(
+ internal::OnCallSpec<F>& InternalDefaultActionSetAt(
const char* file, int line, const char* obj, const char* call) {
LogWithLocation(internal::INFO, file, line,
string("ON_CALL(") + obj + ", " + call + ") invoked");
- return function_mocker_->AddNewDefaultActionSpec(file, line, matchers_);
+ return function_mocker_->AddNewOnCallSpec(file, line, matchers_);
}
// Adds a new expectation spec to the function mocker and returns
@@ -1220,15 +1265,6 @@ class MockSpec {
matchers_ = matchers;
}
- // Logs a message including file and line number information.
- void LogWithLocation(testing::internal::LogSeverity severity,
- const char* file, int line,
- const string& message) {
- ::std::ostringstream s;
- s << file << ":" << line << ": " << message << ::std::endl;
- Log(severity, s.str(), 0);
- }
-
// The function mocker that owns this spec.
internal::FunctionMockerBase<F>* const function_mocker_;
// The argument matchers specified in the spec.
@@ -1253,42 +1289,58 @@ class MockSpec {
// copyable type or void (T doesn't need to be default-constructable).
// It hides the syntactic difference between void and other types, and
// is used to unify the code for invoking both void-returning and
-// non-void-returning mock functions. This generic definition is used
-// when T is not void.
+// non-void-returning mock functions.
+
+// Untyped base class for ActionResultHolder<T>.
+class UntypedActionResultHolderBase {
+ public:
+ virtual ~UntypedActionResultHolderBase() {}
+
+ // Prints the held value as an action's result to os.
+ virtual void PrintAsActionResult(::std::ostream* os) const = 0;
+};
+
+// This generic definition is used when T is not void.
template <typename T>
-class ActionResultHolder {
+class ActionResultHolder : public UntypedActionResultHolderBase {
public:
explicit ActionResultHolder(T a_value) : value_(a_value) {}
// The compiler-generated copy constructor and assignment operator
// are exactly what we need, so we don't need to define them.
- T value() const { return value_; }
+ // Returns the held value and deletes this object.
+ T GetValueAndDelete() const {
+ T retval(value_);
+ delete this;
+ return retval;
+ }
// Prints the held value as an action's result to os.
- void PrintAsActionResult(::std::ostream* os) const {
+ virtual void PrintAsActionResult(::std::ostream* os) const {
*os << "\n Returns: ";
// T may be a reference type, so we don't use UniversalPrint().
UniversalPrinter<T>::Print(value_, os);
}
// Performs the given mock function's default action and returns the
- // result in a ActionResultHolder.
- template <typename Function, typename Arguments>
- static ActionResultHolder PerformDefaultAction(
- const FunctionMockerBase<Function>* func_mocker,
- const Arguments& args,
+ // result in a new-ed ActionResultHolder.
+ template <typename F>
+ static ActionResultHolder* PerformDefaultAction(
+ const FunctionMockerBase<F>* func_mocker,
+ const typename Function<F>::ArgumentTuple& args,
const string& call_description) {
- return ActionResultHolder(
+ return new ActionResultHolder(
func_mocker->PerformDefaultAction(args, call_description));
}
- // Performs the given action and returns the result in a
+ // Performs the given action and returns the result in a new-ed
// ActionResultHolder.
- template <typename Function, typename Arguments>
- static ActionResultHolder PerformAction(const Action<Function>& action,
- const Arguments& args) {
- return ActionResultHolder(action.Perform(args));
+ template <typename F>
+ static ActionResultHolder*
+ PerformAction(const Action<F>& action,
+ const typename Function<F>::ArgumentTuple& args) {
+ return new ActionResultHolder(action.Perform(args));
}
private:
@@ -1300,26 +1352,29 @@ class ActionResultHolder {
// Specialization for T = void.
template <>
-class ActionResultHolder<void> {
+class ActionResultHolder<void> : public UntypedActionResultHolderBase {
public:
- ActionResultHolder() {}
- void value() const {}
- void PrintAsActionResult(::std::ostream* /* os */) const {}
-
- template <typename Function, typename Arguments>
- static ActionResultHolder PerformDefaultAction(
- const FunctionMockerBase<Function>* func_mocker,
- const Arguments& args,
+ void GetValueAndDelete() const { delete this; }
+
+ virtual void PrintAsActionResult(::std::ostream* /* os */) const {}
+
+ // Performs the given mock function's default action and returns NULL;
+ 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);
- return ActionResultHolder();
+ return NULL;
}
- template <typename Function, typename Arguments>
- static ActionResultHolder PerformAction(const Action<Function>& action,
- const Arguments& args) {
+ // Performs the given action and returns NULL.
+ template <typename F>
+ static ActionResultHolder* PerformAction(
+ const Action<F>& action,
+ const typename Function<F>::ArgumentTuple& args) {
action.Perform(args);
- return ActionResultHolder();
+ return NULL;
}
};
@@ -1333,7 +1388,7 @@ class FunctionMockerBase : public UntypedFunctionMockerBase {
typedef typename Function<F>::ArgumentTuple ArgumentTuple;
typedef typename Function<F>::ArgumentMatcherTuple ArgumentMatcherTuple;
- FunctionMockerBase() : mock_obj_(NULL), name_(""), current_spec_(this) {}
+ FunctionMockerBase() : current_spec_(this) {}
// The destructor verifies that all expectations on this mock
// function have been satisfied. If not, it will report Google Test
@@ -1343,19 +1398,20 @@ class FunctionMockerBase : public UntypedFunctionMockerBase {
MutexLock l(&g_gmock_mutex);
VerifyAndClearExpectationsLocked();
Mock::UnregisterLocked(this);
+ ClearDefaultActionsLocked();
}
// Returns the ON_CALL spec that matches this mock function with the
// given arguments; returns NULL if no matching ON_CALL is found.
// L = *
- const DefaultActionSpec<F>* FindDefaultActionSpec(
+ const OnCallSpec<F>* FindOnCallSpec(
const ArgumentTuple& args) const {
- for (typename std::vector<DefaultActionSpec<F> >::const_reverse_iterator it
- = default_actions_.rbegin();
- it != default_actions_.rend(); ++it) {
- const DefaultActionSpec<F>& spec = *it;
- if (spec.Matches(args))
- return &spec;
+ for (UntypedOnCallSpecs::const_reverse_iterator it
+ = untyped_on_call_specs_.rbegin();
+ it != untyped_on_call_specs_.rend(); ++it) {
+ const OnCallSpec<F>* spec = static_cast<const OnCallSpec<F>*>(*it);
+ if (spec->Matches(args))
+ return spec;
}
return NULL;
@@ -1368,7 +1424,8 @@ class FunctionMockerBase : public UntypedFunctionMockerBase {
// L = *
Result PerformDefaultAction(const ArgumentTuple& args,
const string& call_description) const {
- const DefaultActionSpec<F>* const spec = FindDefaultActionSpec(args);
+ const OnCallSpec<F>* const spec =
+ this->FindOnCallSpec(args);
if (spec != NULL) {
return spec->GetAction().Perform(args);
}
@@ -1378,91 +1435,70 @@ class FunctionMockerBase : public UntypedFunctionMockerBase {
return DefaultValue<Result>::Get();
}
- // Registers this function mocker and the mock object owning it;
- // returns a reference to the function mocker object. This is only
- // called by the ON_CALL() and EXPECT_CALL() macros.
- // L < g_gmock_mutex
- FunctionMocker<F>& RegisterOwner(const void* mock_obj) {
- {
- MutexLock l(&g_gmock_mutex);
- mock_obj_ = mock_obj;
- }
- Mock::Register(mock_obj, this);
- return *::testing::internal::DownCast_<FunctionMocker<F>*>(this);
+ // Performs the default action with the given arguments and returns
+ // the action's result. The call description string will be used in
+ // the error message to describe the call in the case the default
+ // 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);
}
- // The following two functions are from UntypedFunctionMockerBase.
-
- // Verifies that all expectations on this mock function have been
- // satisfied. Reports one or more Google Test non-fatal failures
- // and returns false if not.
- // L >= g_gmock_mutex
- virtual bool VerifyAndClearExpectationsLocked();
-
- // Clears the ON_CALL()s set on this mock function.
+ // Performs the given action with the given arguments and returns
+ // the action's result. The caller is responsible for deleting the
+ // result.
+ // L = *
+ virtual UntypedActionResultHolderBase* UntypedPerformAction(
+ const void* untyped_action, const 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);
+ }
+
+ // Implements UntypedFunctionMockerBase::ClearDefaultActionsLocked():
+ // clears the ON_CALL()s set on this mock function.
// L >= g_gmock_mutex
virtual void ClearDefaultActionsLocked() {
g_gmock_mutex.AssertHeld();
- default_actions_.clear();
- }
-
- // Sets the name of the function being mocked. Will be called upon
- // each invocation of this mock function.
- // L < g_gmock_mutex
- void SetOwnerAndName(const void* mock_obj, const char* name) {
- // We protect name_ under g_gmock_mutex in case this mock function
- // is called from two threads concurrently.
- MutexLock l(&g_gmock_mutex);
- mock_obj_ = mock_obj;
- name_ = name;
- }
-
- // Returns the address of the mock object this method belongs to.
- // Must be called after SetOwnerAndName() has been called.
- // L < g_gmock_mutex
- const void* MockObject() const {
- const void* mock_obj;
- {
- // We protect mock_obj_ under g_gmock_mutex in case this mock
- // function is called from two threads concurrently.
- MutexLock l(&g_gmock_mutex);
- mock_obj = mock_obj_;
+ for (UntypedOnCallSpecs::const_iterator it =
+ untyped_on_call_specs_.begin();
+ it != untyped_on_call_specs_.end(); ++it) {
+ delete static_cast<const OnCallSpec<F>*>(*it);
}
- return mock_obj;
- }
-
- // Returns the name of the function being mocked. Must be called
- // after SetOwnerAndName() has been called.
- // L < g_gmock_mutex
- const char* Name() const {
- const char* name;
- {
- // We protect name_ under g_gmock_mutex in case this mock
- // function is called from two threads concurrently.
- MutexLock l(&g_gmock_mutex);
- name = name_;
- }
- return name;
+ untyped_on_call_specs_.clear();
}
protected:
template <typename Function>
friend class MockSpec;
+ typedef ActionResultHolder<Result> ResultHolder;
+
// Returns the result of invoking this mock function with the given
// arguments. This function can be safely called from multiple
// threads concurrently.
// L < g_gmock_mutex
- Result InvokeWith(const ArgumentTuple& args);
+ Result InvokeWith(const ArgumentTuple& args) {
+ return static_cast<const ResultHolder*>(
+ this->UntypedInvokeWith(&args))->GetValueAndDelete();
+ }
// Adds and returns a default action spec for this mock function.
// L < g_gmock_mutex
- DefaultActionSpec<F>& AddNewDefaultActionSpec(
+ OnCallSpec<F>& AddNewOnCallSpec(
const char* file, int line,
const ArgumentMatcherTuple& m) {
Mock::RegisterUseByOnCallOrExpectCall(MockObject(), file, line);
- default_actions_.push_back(DefaultActionSpec<F>(file, line, m));
- return default_actions_.back();
+ OnCallSpec<F>* const on_call_spec = new OnCallSpec<F>(file, line, m);
+ untyped_on_call_specs_.push_back(on_call_spec);
+ return *on_call_spec;
}
// Adds and returns an expectation spec for this mock function.
@@ -1473,14 +1509,15 @@ class FunctionMockerBase : public UntypedFunctionMockerBase {
const string& source_text,
const ArgumentMatcherTuple& m) {
Mock::RegisterUseByOnCallOrExpectCall(MockObject(), file, line);
- const linked_ptr<TypedExpectation<F> > expectation(
- new TypedExpectation<F>(this, file, line, source_text, m));
- expectations_.push_back(expectation);
+ TypedExpectation<F>* const expectation =
+ new TypedExpectation<F>(this, file, line, source_text, m);
+ const linked_ptr<ExpectationBase> untyped_expectation(expectation);
+ 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) {
- implicit_sequence->AddExpectation(Expectation(expectation));
+ implicit_sequence->AddExpectation(Expectation(untyped_expectation));
}
return *expectation;
@@ -1493,33 +1530,14 @@ class FunctionMockerBase : public UntypedFunctionMockerBase {
private:
template <typename Func> friend class TypedExpectation;
- typedef std::vector<internal::linked_ptr<TypedExpectation<F> > >
- TypedExpectations;
-
- // Returns an Expectation object that references and co-owns exp,
- // which must be an expectation on this mock function.
- Expectation GetHandleOf(TypedExpectation<F>* exp) {
- for (typename TypedExpectations::const_iterator it = expectations_.begin();
- it != expectations_.end(); ++it) {
- if (it->get() == exp) {
- return Expectation(*it);
- }
- }
-
- Assert(false, __FILE__, __LINE__, "Cannot find expectation.");
- return Expectation();
- // The above statement is just to make the code compile, and will
- // never be executed.
- }
-
- // Some utilities needed for implementing InvokeWith().
+ // Some utilities needed for implementing UntypedInvokeWith().
// Describes what default action will be performed for the given
// arguments.
// L = *
void DescribeDefaultActionTo(const ArgumentTuple& args,
::std::ostream* os) const {
- const DefaultActionSpec<F>* const spec = FindDefaultActionSpec(args);
+ const OnCallSpec<F>* const spec = FindOnCallSpec(args);
if (spec == NULL) {
*os << (internal::type_equals<Result, void>::value ?
@@ -1535,14 +1553,23 @@ class FunctionMockerBase : public UntypedFunctionMockerBase {
// explicitly expected nor explicitly unexpected) to the given
// ostream.
// L < g_gmock_mutex
- void DescribeUninterestingCall(const ArgumentTuple& args,
- ::std::ostream* os) const {
+ virtual void UntypedDescribeUninterestingCall(const void* untyped_args,
+ ::std::ostream* os) const {
+ const ArgumentTuple& args =
+ *static_cast<const ArgumentTuple*>(untyped_args);
*os << "Uninteresting mock function call - ";
DescribeDefaultActionTo(args, os);
*os << " Function call: " << Name();
UniversalPrint(args, os);
}
+ // Returns the expectation that matches the given function arguments
+ // (or NULL is there's no match); when a match is found,
+ // untyped_action is set to point to the action that should be
+ // performed (or NULL if the action is "do default"), and
+ // is_excessive is modified to indicate whether the call exceeds the
+ // expected number.
+ //
// Critical section: We must find the matching expectation and the
// corresponding action that needs to be taken in an ATOMIC
// transaction. Otherwise another thread may call this mock
@@ -1553,23 +1580,36 @@ class FunctionMockerBase : public UntypedFunctionMockerBase {
// action does (it can invoke an arbitrary user function or even a
// mock function) and excessive locking could cause a dead lock.
// L < g_gmock_mutex
- bool FindMatchingExpectationAndAction(
- const ArgumentTuple& args, TypedExpectation<F>** exp, Action<F>* action,
- bool* is_excessive, ::std::ostream* what, ::std::ostream* why) {
+ virtual const ExpectationBase* UntypedFindMatchingExpectation(
+ const void* untyped_args,
+ const void** untyped_action, bool* is_excessive,
+ ::std::ostream* what, ::std::ostream* why) {
+ const ArgumentTuple& args =
+ *static_cast<const ArgumentTuple*>(untyped_args);
MutexLock l(&g_gmock_mutex);
- *exp = this->FindMatchingExpectationLocked(args);
- if (*exp == NULL) { // A match wasn't found.
- *action = DoDefault();
+ TypedExpectation<F>* exp = this->FindMatchingExpectationLocked(args);
+ if (exp == NULL) { // A match wasn't found.
this->FormatUnexpectedCallMessageLocked(args, what, why);
- return false;
+ return NULL;
}
// This line must be done before calling GetActionForArguments(),
// which will increment the call count for *exp and thus affect
// its saturation status.
- *is_excessive = (*exp)->IsSaturated();
- *action = (*exp)->GetActionForArguments(this, args, what, why);
- return true;
+ *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.
+ *untyped_action = action;
+ return exp;
+ }
+
+ // Prints the given function arguments to the ostream.
+ virtual void UntypedPrintArgs(const void* untyped_args,
+ ::std::ostream* os) const {
+ const ArgumentTuple& args =
+ *static_cast<const ArgumentTuple*>(untyped_args);
+ UniversalPrint(args, os);
}
// Returns the expectation that matches the arguments, or NULL if no
@@ -1578,10 +1618,11 @@ class FunctionMockerBase : public UntypedFunctionMockerBase {
TypedExpectation<F>* FindMatchingExpectationLocked(
const ArgumentTuple& args) const {
g_gmock_mutex.AssertHeld();
- for (typename TypedExpectations::const_reverse_iterator it =
- expectations_.rbegin();
- it != expectations_.rend(); ++it) {
- TypedExpectation<F>* const exp = it->get();
+ for (typename UntypedExpectations::const_reverse_iterator it =
+ untyped_expectations_.rbegin();
+ it != untyped_expectations_.rend(); ++it) {
+ TypedExpectation<F>* const exp =
+ static_cast<TypedExpectation<F>*>(it->get());
if (exp->ShouldHandleArguments(args)) {
return exp;
}
@@ -1606,41 +1647,29 @@ class FunctionMockerBase : public UntypedFunctionMockerBase {
void PrintTriedExpectationsLocked(const ArgumentTuple& args,
::std::ostream* why) const {
g_gmock_mutex.AssertHeld();
- const int count = static_cast<int>(expectations_.size());
+ const int count = static_cast<int>(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++) {
+ TypedExpectation<F>* const expectation =
+ static_cast<TypedExpectation<F>*>(untyped_expectations_[i].get());
*why << "\n";
- expectations_[i]->DescribeLocationTo(why);
+ expectation->DescribeLocationTo(why);
if (count > 1) {
*why << "tried expectation #" << i << ": ";
}
- *why << expectations_[i]->source_text() << "...\n";
- expectations_[i]->ExplainMatchResultTo(args, why);
- expectations_[i]->DescribeCallCountTo(why);
+ *why << expectation->source_text() << "...\n";
+ expectation->ExplainMatchResultTo(args, why);
+ expectation->DescribeCallCountTo(why);
}
}
- // Address of the mock object this mock method belongs to. Only
- // valid after this mock method has been called or
- // ON_CALL/EXPECT_CALL has been invoked on it.
- const void* mock_obj_; // Protected by g_gmock_mutex.
-
- // Name of the function being mocked. Only valid after this mock
- // method has been called.
- const char* name_; // Protected by g_gmock_mutex.
-
// The current spec (either default action spec or expectation spec)
// being described on this function mocker.
MockSpec<F> current_spec_;
- // All default action specs for this function mocker.
- std::vector<DefaultActionSpec<F> > default_actions_;
- // All expectations for this function mocker.
- TypedExpectations expectations_;
-
// 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
@@ -1666,144 +1695,11 @@ class FunctionMockerBase : public UntypedFunctionMockerBase {
// satisfied. Reports one or more Google Test non-fatal failures and
// returns false if not.
// L >= g_gmock_mutex
-template <typename F>
-bool FunctionMockerBase<F>::VerifyAndClearExpectationsLocked() {
- g_gmock_mutex.AssertHeld();
- bool expectations_met = true;
- for (typename TypedExpectations::const_iterator it = expectations_.begin();
- it != expectations_.end(); ++it) {
- TypedExpectation<F>* const exp = it->get();
-
- if (exp->IsOverSaturated()) {
- // There was an upper-bound violation. Since the error was
- // already reported when it occurred, there is no need to do
- // anything here.
- expectations_met = false;
- } else if (!exp->IsSatisfied()) {
- expectations_met = false;
- ::std::stringstream ss;
- ss << "Actual function call count doesn't match "
- << exp->source_text() << "...\n";
- // No need to show the source file location of the expectation
- // in the description, as the Expect() call that follows already
- // takes care of it.
- exp->MaybeDescribeExtraMatcherTo(&ss);
- exp->DescribeCallCountTo(&ss);
- Expect(false, exp->file(), exp->line(), ss.str());
- }
- }
- expectations_.clear();
- return expectations_met;
-}
// Reports an uninteresting call (whose description is in msg) in the
// manner specified by 'reaction'.
void ReportUninterestingCall(CallReaction reaction, const string& msg);
-// Calculates the result of invoking this mock function with the given
-// arguments, prints it, and returns it.
-// L < g_gmock_mutex
-template <typename F>
-typename Function<F>::Result FunctionMockerBase<F>::InvokeWith(
- const typename Function<F>::ArgumentTuple& args) {
- typedef ActionResultHolder<Result> ResultHolder;
-
- if (expectations_.size() == 0) {
- // No expectation is set on this mock method - we have an
- // uninteresting call.
-
- // We must get Google Mock's reaction on uninteresting calls
- // made on this mock object BEFORE performing the action,
- // because the action may DELETE the mock object and make the
- // following expression meaningless.
- const CallReaction reaction =
- Mock::GetReactionOnUninterestingCalls(MockObject());
-
- // True iff we need to print this call's arguments and return
- // value. This definition must be kept in sync with
- // the behavior of ReportUninterestingCall().
- const bool need_to_report_uninteresting_call =
- // If the user allows this uninteresting call, we print it
- // only when he wants informational messages.
- reaction == ALLOW ? LogIsVisible(INFO) :
- // If the user wants this to be a warning, we print it only
- // when he wants to see warnings.
- reaction == WARN ? LogIsVisible(WARNING) :
- // Otherwise, the user wants this to be an error, and we
- // should always print detailed information in the error.
- true;
-
- if (!need_to_report_uninteresting_call) {
- // Perform the action without printing the call information.
- return PerformDefaultAction(args, "");
- }
-
- // Warns about the uninteresting call.
- ::std::stringstream ss;
- DescribeUninterestingCall(args, &ss);
-
- // Calculates the function result.
- const ResultHolder result =
- ResultHolder::PerformDefaultAction(this, args, ss.str());
-
- // Prints the function result.
- result.PrintAsActionResult(&ss);
-
- ReportUninterestingCall(reaction, ss.str());
- return result.value();
- }
-
- bool is_excessive = false;
- ::std::stringstream ss;
- ::std::stringstream why;
- ::std::stringstream loc;
- Action<F> action;
- TypedExpectation<F>* exp;
-
- // The FindMatchingExpectationAndAction() function acquires and
- // releases g_gmock_mutex.
- const bool found = FindMatchingExpectationAndAction(
- args, &exp, &action, &is_excessive, &ss, &why);
-
- // True iff we need to print the call's arguments and return value.
- // This definition must be kept in sync with the uses of Expect()
- // and Log() in this function.
- const bool need_to_report_call = !found || is_excessive || LogIsVisible(INFO);
- if (!need_to_report_call) {
- // Perform the action without printing the call information.
- return action.IsDoDefault() ? PerformDefaultAction(args, "") :
- action.Perform(args);
- }
-
- ss << " Function call: " << Name();
- UniversalPrint(args, &ss);
-
- // In case the action deletes a piece of the expectation, we
- // generate the message beforehand.
- if (found && !is_excessive) {
- exp->DescribeLocationTo(&loc);
- }
-
- const ResultHolder result = action.IsDoDefault() ?
- ResultHolder::PerformDefaultAction(this, args, ss.str()) :
- ResultHolder::PerformAction(action, args);
- result.PrintAsActionResult(&ss);
- ss << "\n" << why.str();
-
- if (!found) {
- // No expectation matches this call - reports a failure.
- Expect(false, NULL, -1, ss.str());
- } else if (is_excessive) {
- // We had an upper-bound violation and the failure message is in ss.
- Expect(false, exp->file(), exp->line(), ss.str());
- } else {
- // We had an expected call and the matching expectation is
- // described in ss.
- Log(INFO, loc.str() + ss.str(), 2);
- }
- return result.value();
-}
-
} // namespace internal
// The style guide prohibits "using" statements in a namespace scope
diff --git a/scripts/gmock_doctor.py b/scripts/gmock_doctor.py
index f7932b5..ab923ef 100755
--- a/scripts/gmock_doctor.py
+++ b/scripts/gmock_doctor.py
@@ -261,8 +261,8 @@ def _IncompleteByReferenceArgumentDiagnoser(msg):
r'(.*\n)*?' +
_CLANG_NON_GMOCK_FILE_LINE_RE +
r'note: in instantiation of member function '
- r'\'testing::internal::FunctionMocker<.*>::Invoke\' '
- r'requested here')
+ r'\'testing::internal2::TypeWithoutFormatter<.*>::'
+ r'PrintValue\' requested here')
diagnosis = """
In order to mock this function, Google Mock needs to see the definition
of type "%(type)s" - declaration alone is not enough. Either #include
diff --git a/src/gmock-spec-builders.cc b/src/gmock-spec-builders.cc
index 0d40d9c..a99caef 100644
--- a/src/gmock-spec-builders.cc
+++ b/src/gmock-spec-builders.cc
@@ -55,6 +55,15 @@ namespace internal {
// mockers, and all expectations.
GTEST_DEFINE_STATIC_MUTEX_(g_gmock_mutex);
+// Logs a message including file and line number information.
+void LogWithLocation(testing::internal::LogSeverity severity,
+ const char* file, int line,
+ const string& message) {
+ ::std::ostringstream s;
+ s << file << ":" << line << ": " << message << ::std::endl;
+ Log(severity, s.str(), 0);
+}
+
// Constructs an ExpectationBase object.
ExpectationBase::ExpectationBase(const char* a_file,
int a_line,
@@ -65,8 +74,12 @@ ExpectationBase::ExpectationBase(const char* a_file,
cardinality_specified_(false),
cardinality_(Exactly(1)),
call_count_(0),
- retired_(false) {
-}
+ retired_(false),
+ extra_matcher_specified_(false),
+ repeated_action_specified_(false),
+ retires_on_saturation_(false),
+ last_clause_(kNone),
+ action_count_checked_(false) {}
// Destructs an ExpectationBase object.
ExpectationBase::~ExpectationBase() {}
@@ -132,6 +145,99 @@ void ExpectationBase::FindUnsatisfiedPrerequisites(
}
}
+// Describes how many times a function call matching this
+// expectation has occurred.
+// L >= g_gmock_mutex
+void ExpectationBase::DescribeCallCountTo(::std::ostream* os) const {
+ g_gmock_mutex.AssertHeld();
+
+ // Describes how many times the function is expected to be called.
+ *os << " Expected: to be ";
+ cardinality().DescribeTo(os);
+ *os << "\n Actual: ";
+ Cardinality::DescribeActualCallCountTo(call_count(), os);
+
+ // Describes the state of the expectation (e.g. is it satisfied?
+ // is it active?).
+ *os << " - " << (IsOverSaturated() ? "over-saturated" :
+ IsSaturated() ? "saturated" :
+ IsSatisfied() ? "satisfied" : "unsatisfied")
+ << " and "
+ << (is_retired() ? "retired" : "active");
+}
+
+// Checks the action count (i.e. the number of WillOnce() and
+// WillRepeatedly() clauses) against the cardinality if this hasn't
+// been done before. Prints a warning if there are too many or too
+// few actions.
+// L < mutex_
+void ExpectationBase::CheckActionCountIfNotDone() const {
+ bool should_check = false;
+ {
+ MutexLock l(&mutex_);
+ if (!action_count_checked_) {
+ action_count_checked_ = true;
+ should_check = true;
+ }
+ }
+
+ if (should_check) {
+ if (!cardinality_specified_) {
+ // The cardinality was inferred - no need to check the action
+ // count against it.
+ return;
+ }
+
+ // The cardinality was explicitly specified.
+ const int action_count = static_cast<int>(untyped_actions_.size());
+ const int upper_bound = cardinality().ConservativeUpperBound();
+ const int lower_bound = cardinality().ConservativeLowerBound();
+ bool too_many; // True if there are too many actions, or false
+ // if there are too few.
+ if (action_count > upper_bound ||
+ (action_count == upper_bound && repeated_action_specified_)) {
+ too_many = true;
+ } else if (0 < action_count && action_count < lower_bound &&
+ !repeated_action_specified_) {
+ too_many = false;
+ } else {
+ return;
+ }
+
+ ::std::stringstream ss;
+ DescribeLocationTo(&ss);
+ ss << "Too " << (too_many ? "many" : "few")
+ << " actions specified in " << source_text() << "...\n"
+ << "Expected to be ";
+ cardinality().DescribeTo(&ss);
+ ss << ", but has " << (too_many ? "" : "only ")
+ << action_count << " WillOnce()"
+ << (action_count == 1 ? "" : "s");
+ if (repeated_action_specified_) {
+ ss << " and a WillRepeatedly()";
+ }
+ ss << ".";
+ Log(WARNING, ss.str(), -1); // -1 means "don't print stack trace".
+ }
+}
+
+// Implements the .Times() clause.
+void ExpectationBase::UntypedTimes(const Cardinality& a_cardinality) {
+ if (last_clause_ == kTimes) {
+ ExpectSpecProperty(false,
+ ".Times() cannot appear "
+ "more than once in an EXPECT_CALL().");
+ } else {
+ ExpectSpecProperty(last_clause_ < kTimes,
+ ".Times() cannot appear after "
+ ".InSequence(), .WillOnce(), .WillRepeatedly(), "
+ "or .RetiresOnSaturation().");
+ }
+ last_clause_ = kTimes;
+
+ SpecifyCardinality(a_cardinality);
+}
+
// Points to the implicit sequence introduced by a living InSequence
// object (if any) in the current thread or NULL.
ThreadLocal<Sequence*> g_gmock_implicit_sequence;
@@ -151,6 +257,233 @@ void ReportUninterestingCall(CallReaction reaction, const string& msg) {
}
}
+UntypedFunctionMockerBase::UntypedFunctionMockerBase()
+ : mock_obj_(NULL), name_("") {}
+
+UntypedFunctionMockerBase::~UntypedFunctionMockerBase() {}
+
+// Sets the mock object this mock method belongs to, and registers
+// this information in the global mock registry. Will be called
+// whenever an EXPECT_CALL() or ON_CALL() is executed on this mock
+// method.
+// L < g_gmock_mutex
+void UntypedFunctionMockerBase::RegisterOwner(const void* mock_obj) {
+ {
+ MutexLock l(&g_gmock_mutex);
+ mock_obj_ = mock_obj;
+ }
+ Mock::Register(mock_obj, this);
+}
+
+// Sets the mock object this mock method belongs to, and sets the name
+// of the mock function. Will be called upon each invocation of this
+// mock function.
+// L < g_gmock_mutex
+void UntypedFunctionMockerBase::SetOwnerAndName(
+ const void* mock_obj, const char* name) {
+ // We protect name_ under g_gmock_mutex in case this mock function
+ // is called from two threads concurrently.
+ MutexLock l(&g_gmock_mutex);
+ mock_obj_ = mock_obj;
+ name_ = name;
+}
+
+// Returns the name of the function being mocked. Must be called
+// after RegisterOwner() or SetOwnerAndName() has been called.
+// L < g_gmock_mutex
+const void* UntypedFunctionMockerBase::MockObject() const {
+ const void* mock_obj;
+ {
+ // We protect mock_obj_ under g_gmock_mutex in case this mock
+ // function is called from two threads concurrently.
+ MutexLock l(&g_gmock_mutex);
+ Assert(mock_obj_ != NULL, __FILE__, __LINE__,
+ "MockObject() must not be called before RegisterOwner() or "
+ "SetOwnerAndName() has been called.");
+ mock_obj = mock_obj_;
+ }
+ return mock_obj;
+}
+
+// Returns the name of this mock method. Must be called after
+// SetOwnerAndName() has been called.
+// L < g_gmock_mutex
+const char* UntypedFunctionMockerBase::Name() const {
+ const char* name;
+ {
+ // We protect name_ under g_gmock_mutex in case this mock
+ // function is called from two threads concurrently.
+ MutexLock l(&g_gmock_mutex);
+ Assert(name_ != NULL, __FILE__, __LINE__,
+ "Name() must not be called before SetOwnerAndName() has "
+ "been called.");
+ name = name_;
+ }
+ return name;
+}
+
+// Calculates the result of invoking this mock function with the given
+// arguments, prints it, and returns it. The caller is responsible
+// for deleting the result.
+// L < g_gmock_mutex
+const UntypedActionResultHolderBase*
+UntypedFunctionMockerBase::UntypedInvokeWith(const void* const untyped_args) {
+ if (untyped_expectations_.size() == 0) {
+ // No expectation is set on this mock method - we have an
+ // uninteresting call.
+
+ // We must get Google Mock's reaction on uninteresting calls
+ // made on this mock object BEFORE performing the action,
+ // because the action may DELETE the mock object and make the
+ // following expression meaningless.
+ const CallReaction reaction =
+ Mock::GetReactionOnUninterestingCalls(MockObject());
+
+ // True iff we need to print this call's arguments and return
+ // value. This definition must be kept in sync with
+ // the behavior of ReportUninterestingCall().
+ const bool need_to_report_uninteresting_call =
+ // If the user allows this uninteresting call, we print it
+ // only when he wants informational messages.
+ reaction == ALLOW ? LogIsVisible(INFO) :
+ // If the user wants this to be a warning, we print it only
+ // when he wants to see warnings.
+ reaction == WARN ? LogIsVisible(WARNING) :
+ // Otherwise, the user wants this to be an error, and we
+ // should always print detailed information in the error.
+ true;
+
+ if (!need_to_report_uninteresting_call) {
+ // Perform the action without printing the call information.
+ return this->UntypedPerformDefaultAction(untyped_args, "");
+ }
+
+ // Warns about the uninteresting call.
+ ::std::stringstream ss;
+ this->UntypedDescribeUninterestingCall(untyped_args, &ss);
+
+ // Calculates the function result.
+ const UntypedActionResultHolderBase* const result =
+ this->UntypedPerformDefaultAction(untyped_args, ss.str());
+
+ // Prints the function result.
+ if (result != NULL)
+ result->PrintAsActionResult(&ss);
+
+ ReportUninterestingCall(reaction, ss.str());
+ return result;
+ }
+
+ bool is_excessive = false;
+ ::std::stringstream ss;
+ ::std::stringstream why;
+ ::std::stringstream loc;
+ const void* untyped_action = NULL;
+
+ // The UntypedFindMatchingExpectation() function acquires and
+ // releases g_gmock_mutex.
+ const ExpectationBase* const untyped_expectation =
+ this->UntypedFindMatchingExpectation(
+ untyped_args, &untyped_action, &is_excessive,
+ &ss, &why);
+ const bool found = untyped_expectation != NULL;
+
+ // True iff we need to print the call's arguments and return value.
+ // This definition must be kept in sync with the uses of Expect()
+ // and Log() in this function.
+ const bool need_to_report_call = !found || is_excessive || LogIsVisible(INFO);
+ if (!need_to_report_call) {
+ // Perform the action without printing the call information.
+ return
+ untyped_action == NULL ?
+ this->UntypedPerformDefaultAction(untyped_args, "") :
+ this->UntypedPerformAction(untyped_action, untyped_args);
+ }
+
+ ss << " Function call: " << Name();
+ this->UntypedPrintArgs(untyped_args, &ss);
+
+ // In case the action deletes a piece of the expectation, we
+ // generate the message beforehand.
+ if (found && !is_excessive) {
+ untyped_expectation->DescribeLocationTo(&loc);
+ }
+
+ const UntypedActionResultHolderBase* const result =
+ untyped_action == NULL ?
+ this->UntypedPerformDefaultAction(untyped_args, ss.str()) :
+ this->UntypedPerformAction(untyped_action, untyped_args);
+ if (result != NULL)
+ result->PrintAsActionResult(&ss);
+ ss << "\n" << why.str();
+
+ if (!found) {
+ // No expectation matches this call - reports a failure.
+ Expect(false, NULL, -1, ss.str());
+ } else if (is_excessive) {
+ // We had an upper-bound violation and the failure message is in ss.
+ Expect(false, untyped_expectation->file(),
+ untyped_expectation->line(), ss.str());
+ } else {
+ // We had an expected call and the matching expectation is
+ // described in ss.
+ Log(INFO, loc.str() + ss.str(), 2);
+ }
+
+ return result;
+}
+
+// Returns an Expectation object that references and co-owns exp,
+// which must be an expectation on this mock function.
+Expectation UntypedFunctionMockerBase::GetHandleOf(ExpectationBase* exp) {
+ for (UntypedExpectations::const_iterator it =
+ untyped_expectations_.begin();
+ it != untyped_expectations_.end(); ++it) {
+ if (it->get() == exp) {
+ return Expectation(*it);
+ }
+ }
+
+ Assert(false, __FILE__, __LINE__, "Cannot find expectation.");
+ return Expectation();
+ // The above statement is just to make the code compile, and will
+ // never be executed.
+}
+
+// Verifies that all expectations on this mock function have been
+// satisfied. Reports one or more Google Test non-fatal failures
+// and returns false if not.
+// L >= g_gmock_mutex
+bool UntypedFunctionMockerBase::VerifyAndClearExpectationsLocked() {
+ g_gmock_mutex.AssertHeld();
+ bool expectations_met = true;
+ for (UntypedExpectations::const_iterator it =
+ untyped_expectations_.begin();
+ it != untyped_expectations_.end(); ++it) {
+ ExpectationBase* const untyped_expectation = it->get();
+ if (untyped_expectation->IsOverSaturated()) {
+ // There was an upper-bound violation. Since the error was
+ // already reported when it occurred, there is no need to do
+ // anything here.
+ expectations_met = false;
+ } else if (!untyped_expectation->IsSatisfied()) {
+ expectations_met = false;
+ ::std::stringstream ss;
+ ss << "Actual function call count doesn't match "
+ << untyped_expectation->source_text() << "...\n";
+ // No need to show the source file location of the expectation
+ // in the description, as the Expect() call that follows already
+ // takes care of it.
+ untyped_expectation->MaybeDescribeExtraMatcherTo(&ss);
+ untyped_expectation->DescribeCallCountTo(&ss);
+ Expect(false, untyped_expectation->file(),
+ untyped_expectation->line(), ss.str());
+ }
+ }
+ untyped_expectations_.clear();
+ return expectations_met;
+}
+
} // namespace internal
// Class Mock.
@@ -190,7 +523,6 @@ class MockObjectRegistry {
// object alive. Therefore we report any living object as test
// failure, unless the user explicitly asked us to ignore it.
~MockObjectRegistry() {
-
// "using ::std::cout;" doesn't work with Symbian's STLport, where cout is
// a macro.
diff --git a/test/gmock-actions_test.cc b/test/gmock-actions_test.cc
index e12402b..b3f8d52 100644
--- a/test/gmock-actions_test.cc
+++ b/test/gmock-actions_test.cc
@@ -334,8 +334,7 @@ class MyActionImpl : public ActionInterface<MyFunction> {
TEST(ActionInterfaceTest, CanBeImplementedByDefiningPerform) {
MyActionImpl my_action_impl;
-
- EXPECT_FALSE(my_action_impl.IsDoDefault());
+ (void)my_action_impl;
}
TEST(ActionInterfaceTest, MakeAction) {
diff --git a/test/gmock-spec-builders_test.cc b/test/gmock-spec-builders_test.cc
index 737bcff..aea5228 100644
--- a/test/gmock-spec-builders_test.cc
+++ b/test/gmock-spec-builders_test.cc
@@ -103,6 +103,34 @@ using testing::internal::CaptureStdout;
using testing::internal::GetCapturedStdout;
#endif
+class Incomplete;
+
+class MockIncomplete {
+ public:
+ // This line verifies that a mock method can take a by-reference
+ // argument of an incomplete type.
+ MOCK_METHOD1(ByRefFunc, void(const Incomplete& x));
+};
+
+// Tells Google Mock how to print a value of type Incomplete.
+void PrintTo(const Incomplete& x, ::std::ostream* os);
+
+TEST(MockMethodTest, CanInstantiateWithIncompleteArgType) {
+ // Even though this mock class contains a mock method that takes
+ // by-reference an argument whose type is incomplete, we can still
+ // use the mock, as long as Google Mock knows how to print the
+ // argument.
+ MockIncomplete incomplete;
+ EXPECT_CALL(incomplete, ByRefFunc(_))
+ .Times(AnyNumber());
+}
+
+// The definition of the printer for the argument type doesn't have to
+// be visible where the mock is used.
+void PrintTo(const Incomplete& /* x */, ::std::ostream* os) {
+ *os << "incomplete";
+}
+
class Result {};
class MockA {
@@ -1327,12 +1355,33 @@ TEST(SequenceTest, Retirement) {
TEST(ExpectationTest, ConstrutorsWork) {
MockA a;
Expectation e1; // Default ctor.
- Expectation e2 = EXPECT_CALL(a, DoA(1)); // Ctor from EXPECT_CALL.
- Expectation e3 = e2; // Copy ctor.
+
+ // Ctor from various forms of EXPECT_CALL.
+ Expectation e2 = EXPECT_CALL(a, DoA(2));
+ Expectation e3 = EXPECT_CALL(a, DoA(3)).With(_);
+ {
+ Sequence s;
+ Expectation e4 = EXPECT_CALL(a, DoA(4)).Times(1);
+ Expectation e5 = EXPECT_CALL(a, DoA(5)).InSequence(s);
+ }
+ Expectation e6 = EXPECT_CALL(a, DoA(6)).After(e2);
+ Expectation e7 = EXPECT_CALL(a, DoA(7)).WillOnce(Return());
+ Expectation e8 = EXPECT_CALL(a, DoA(8)).WillRepeatedly(Return());
+ Expectation e9 = EXPECT_CALL(a, DoA(9)).RetiresOnSaturation();
+
+ Expectation e10 = e2; // Copy ctor.
EXPECT_THAT(e1, Ne(e2));
- EXPECT_THAT(e2, Eq(e3));
- a.DoA(1);
+ EXPECT_THAT(e2, Eq(e10));
+
+ a.DoA(2);
+ a.DoA(3);
+ a.DoA(4);
+ a.DoA(5);
+ a.DoA(6);
+ a.DoA(7);
+ a.DoA(8);
+ a.DoA(9);
}
TEST(ExpectationTest, AssignmentWorks) {