Makes Google Mock compile much faster and use much less memory; reviewed by Nico Weber. This fixes issue 68.

This commit is contained in:
zhanyong.wan 2011-02-23 19:39:27 +00:00
parent b3e904227f
commit ed6c9277bb
8 changed files with 818 additions and 575 deletions

View File

@ -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

View File

@ -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)

View File

@ -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)

File diff suppressed because it is too large Load Diff

View File

@ -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

View File

@ -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.

View File

@ -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) {

View File

@ -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) {