mirror of
https://github.com/google/googletest.git
synced 2025-12-07 17:26:53 +08:00
gmock updates applied and compiling
This commit is contained in:
parent
3423814d5a
commit
cd9b4de20e
@ -80,6 +80,8 @@
|
||||
#include "gmock/internal/gmock-port.h"
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
#include "../../../coroutines/include/cotest/internal/cotest-util-types.h"
|
||||
|
||||
#if GTEST_HAS_EXCEPTIONS
|
||||
#include <stdexcept> // NOLINT
|
||||
#endif
|
||||
@ -169,9 +171,9 @@ class GTEST_API_ UntypedFunctionMockerBase {
|
||||
// performed (or NULL if the action is "do default"), and
|
||||
// is_excessive is modified to indicate whether the call exceeds the
|
||||
// expected number.
|
||||
virtual const ExpectationBase* UntypedFindMatchingExpectation(
|
||||
virtual ExpectationBase* UntypedFindMatchingExpectation(
|
||||
const void* untyped_args, const void** untyped_action, bool* is_excessive,
|
||||
::std::ostream* what, ::std::ostream* why)
|
||||
::std::ostream* what, ::std::ostream* why, bool *use_exp_for_action)
|
||||
GTEST_LOCK_EXCLUDED_(g_gmock_mutex) = 0;
|
||||
|
||||
// Prints the given function arguments to the ostream.
|
||||
@ -182,7 +184,7 @@ class GTEST_API_ UntypedFunctionMockerBase {
|
||||
// this information in the global mock registry. Will be called
|
||||
// whenever an EXPECT_CALL() or ON_CALL() is executed on this mock
|
||||
// method.
|
||||
void RegisterOwner(const void* mock_obj) GTEST_LOCK_EXCLUDED_(g_gmock_mutex);
|
||||
void RegisterOwner(const void* mock_obj, bool to_reg = true);
|
||||
|
||||
// Sets the mock object this mock method belongs to, and sets the
|
||||
// name of the mock function. Will be called upon each invocation
|
||||
@ -194,16 +196,23 @@ class GTEST_API_ UntypedFunctionMockerBase {
|
||||
// called after RegisterOwner() or SetOwnerAndName() has been
|
||||
// called.
|
||||
const void* MockObject() const GTEST_LOCK_EXCLUDED_(g_gmock_mutex);
|
||||
|
||||
const void* MockObjectLocked() const GTEST_EXCLUSIVE_LOCK_REQUIRED_(g_gmock_mutex);
|
||||
|
||||
// Returns the name of this mock method. Must be called after
|
||||
// SetOwnerAndName() has been called.
|
||||
const char* Name() const GTEST_LOCK_EXCLUDED_(g_gmock_mutex);
|
||||
|
||||
const char* NameLocked() const GTEST_EXCLUSIVE_LOCK_REQUIRED_(g_gmock_mutex);
|
||||
|
||||
// Get a pointer to the vector of expectations for this mocker
|
||||
using UntypedExpectations = std::vector<std::shared_ptr<ExpectationBase>>;
|
||||
const UntypedExpectations *GetMockHandlerScheme() const
|
||||
{
|
||||
return &untyped_expectations_;
|
||||
}
|
||||
|
||||
protected:
|
||||
typedef std::vector<const void*> UntypedOnCallSpecs;
|
||||
|
||||
using UntypedExpectations = std::vector<std::shared_ptr<ExpectationBase>>;
|
||||
|
||||
struct UninterestingCallCleanupHandler;
|
||||
struct FailureCleanupHandler;
|
||||
|
||||
@ -233,8 +242,39 @@ class GTEST_API_ UntypedFunctionMockerBase {
|
||||
// untyped_expectations, we deliberately leave accesses to it
|
||||
// unprotected.
|
||||
UntypedExpectations untyped_expectations_;
|
||||
|
||||
// Provide support for mock object that we create only to identify
|
||||
// which method overload was called - these are not registered, and
|
||||
// do not acquire the mutex.
|
||||
bool registered = false;
|
||||
}; // class UntypedFunctionMockerBase
|
||||
|
||||
// Extension to allow wild-carded expectations. If global mocker instance
|
||||
// is overwritten with an object instance, this will be used to find
|
||||
// expectations instead of the function mocker's algorithm.
|
||||
// Additionally, a global generation number is set in every
|
||||
// expectation, as a way of efficiently respecting expectation
|
||||
// priority order.
|
||||
class AlternateMockCallManager {
|
||||
protected:
|
||||
using UntypedExpectations = std::vector<std::shared_ptr<ExpectationBase>>;
|
||||
|
||||
public:
|
||||
typedef uint64_t Priority;
|
||||
|
||||
virtual ~AlternateMockCallManager() {}
|
||||
|
||||
static Priority GetNextPriority();
|
||||
static AlternateMockCallManager *TryGetInstance();
|
||||
virtual void PreMockUnlocked(const UntypedFunctionMockerBase *mocker, const void* mock_obj, const char *name ) = 0;
|
||||
virtual bool IsUninteresting(const UntypedFunctionMockerBase* mocker, const void* untyped_args) const = 0;
|
||||
virtual ExpectationBase *FindMatchingExpectationLocked(const UntypedFunctionMockerBase* mocker, const void* untyped_args, bool *is_mocker_exp) const = 0;
|
||||
|
||||
protected:
|
||||
static Priority next_global_priority;
|
||||
static AlternateMockCallManager *instance;
|
||||
};
|
||||
|
||||
// Untyped base class for OnCallSpec<F>.
|
||||
class UntypedOnCallSpecBase {
|
||||
public:
|
||||
@ -716,6 +756,10 @@ class GTEST_API_ ExpectationBase {
|
||||
description_ = std::move(description);
|
||||
}
|
||||
|
||||
// Permit non-templated code to try out an expectation
|
||||
virtual bool ShouldHandleCall(const UntypedFunctionMockerBase *mocker,
|
||||
const void* untyped_args) = 0;
|
||||
|
||||
protected:
|
||||
friend class ::testing::Expectation;
|
||||
friend class UntypedFunctionMockerBase;
|
||||
@ -758,11 +802,13 @@ class GTEST_API_ ExpectationBase {
|
||||
// explicitly using a .Times().
|
||||
bool cardinality_specified() const { return cardinality_specified_; }
|
||||
|
||||
public:
|
||||
// Sets the cardinality of this expectation spec.
|
||||
void set_cardinality(const Cardinality& a_cardinality) {
|
||||
cardinality_ = a_cardinality;
|
||||
}
|
||||
|
||||
protected:
|
||||
// The following group of methods should only be called after the
|
||||
// EXPECT_CALL() statement, and only when g_gmock_mutex is held by
|
||||
// the current thread.
|
||||
@ -776,12 +822,32 @@ class GTEST_API_ ExpectationBase {
|
||||
return retired_;
|
||||
}
|
||||
|
||||
public:
|
||||
// Retires this expectation.
|
||||
void Retire() GTEST_EXCLUSIVE_LOCK_REQUIRED_(g_gmock_mutex) {
|
||||
g_gmock_mutex.AssertHeld();
|
||||
retired_ = true;
|
||||
}
|
||||
|
||||
virtual void DetachCoroutine() {};
|
||||
|
||||
AlternateMockCallManager::Priority GetPriority() const {
|
||||
return priority_;
|
||||
}
|
||||
|
||||
// Update cardinality and return true if an action is still required
|
||||
virtual bool UpdateCardinality( const ::testing::internal::UntypedFunctionMockerBase *mocker,
|
||||
const void *untyped_args,
|
||||
::std::ostream* what,
|
||||
::std::ostream* why) { return false; }
|
||||
|
||||
// Allow the expectation to provide an action directly via a vcall; return true if action was performed
|
||||
virtual bool TryPerformAction( const ::testing::internal::UntypedFunctionMockerBase *mocker,
|
||||
const void *untyped_args,
|
||||
const void **untyped_return_value) { return false; };
|
||||
|
||||
protected:
|
||||
|
||||
// Returns a human-readable description of this expectation.
|
||||
// Do not rely on this for correctness. It is only for human readability.
|
||||
const std::string& GetDescription() const { return description_; }
|
||||
@ -792,12 +858,14 @@ class GTEST_API_ ExpectationBase {
|
||||
return cardinality().IsSatisfiedByCallCount(call_count_);
|
||||
}
|
||||
|
||||
public:
|
||||
// Returns true if and only if this expectation is saturated.
|
||||
bool IsSaturated() const GTEST_EXCLUSIVE_LOCK_REQUIRED_(g_gmock_mutex) {
|
||||
g_gmock_mutex.AssertHeld();
|
||||
return cardinality().IsSaturatedByCallCount(call_count_);
|
||||
}
|
||||
|
||||
protected:
|
||||
// Returns true if and only if this expectation is over-saturated.
|
||||
bool IsOverSaturated() const GTEST_EXCLUSIVE_LOCK_REQUIRED_(g_gmock_mutex) {
|
||||
g_gmock_mutex.AssertHeld();
|
||||
@ -840,6 +908,11 @@ class GTEST_API_ ExpectationBase {
|
||||
// Implements the .Times() clause.
|
||||
void UntypedTimes(const Cardinality& a_cardinality);
|
||||
|
||||
// Verifies that this expectation has been satisfied and returns
|
||||
// false if not. Could report one Google Test non-fatal failure.
|
||||
bool VerifyExpectationLocked()
|
||||
GTEST_EXCLUSIVE_LOCK_REQUIRED_(g_gmock_mutex);
|
||||
|
||||
// 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.
|
||||
@ -868,6 +941,7 @@ class GTEST_API_ ExpectationBase {
|
||||
Clause last_clause_;
|
||||
mutable bool action_count_checked_; // Under mutex_.
|
||||
mutable Mutex mutex_; // Protects action_count_checked_.
|
||||
const AlternateMockCallManager::Priority priority_;
|
||||
}; // class ExpectationBase
|
||||
|
||||
template <typename F>
|
||||
@ -1041,9 +1115,9 @@ class TypedExpectation<R(Args...)> : public ExpectationBase {
|
||||
"after .RetiresOnSaturation().");
|
||||
}
|
||||
last_clause_ = kWillRepeatedly;
|
||||
repeated_action_specified_ = true;
|
||||
|
||||
repeated_action_ = action;
|
||||
|
||||
set_repeated_action(action);
|
||||
|
||||
if (!cardinality_specified()) {
|
||||
set_cardinality(AtLeast(static_cast<int>(untyped_actions_.size())));
|
||||
}
|
||||
@ -1053,7 +1127,12 @@ class TypedExpectation<R(Args...)> : public ExpectationBase {
|
||||
CheckActionCountIfNotDone();
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
void set_repeated_action(const Action<F>& action) {
|
||||
repeated_action_specified_ = true;
|
||||
repeated_action_ = action;
|
||||
}
|
||||
|
||||
// Implements the .RetiresOnSaturation() clause.
|
||||
TypedExpectation& RetiresOnSaturation() {
|
||||
ExpectSpecProperty(last_clause_ < kRetiresOnSaturation,
|
||||
@ -1112,6 +1191,7 @@ class TypedExpectation<R(Args...)> : public ExpectationBase {
|
||||
// statement finishes and when the current thread holds
|
||||
// g_gmock_mutex.
|
||||
|
||||
protected:
|
||||
// Returns true if and only if this expectation matches the given arguments.
|
||||
bool Matches(const ArgumentTuple& args) const
|
||||
GTEST_EXCLUSIVE_LOCK_REQUIRED_(g_gmock_mutex) {
|
||||
@ -1119,6 +1199,7 @@ class TypedExpectation<R(Args...)> : public ExpectationBase {
|
||||
return TupleMatches(matchers_, args) && extra_matcher_.Matches(args);
|
||||
}
|
||||
|
||||
private:
|
||||
// Returns true if and only if this expectation should handle the given
|
||||
// arguments.
|
||||
bool ShouldHandleArguments(const ArgumentTuple& args) const
|
||||
@ -1133,9 +1214,19 @@ class TypedExpectation<R(Args...)> : public ExpectationBase {
|
||||
return !is_retired() && AllPrerequisitesAreSatisfied() && Matches(args);
|
||||
}
|
||||
|
||||
// Returns true if and only if this expectation should handle a call to
|
||||
// the given mocker with the given arguments.
|
||||
bool ShouldHandleCall( const UntypedFunctionMockerBase *mocker,
|
||||
const void* untyped_args) override {
|
||||
const ArgumentTuple& args =
|
||||
*static_cast<const ArgumentTuple*>(untyped_args);
|
||||
(void)mocker;
|
||||
return ShouldHandleArguments(args);
|
||||
}
|
||||
|
||||
// Describes the result of matching the arguments against this
|
||||
// expectation to the given ostream.
|
||||
void ExplainMatchResultTo(const ArgumentTuple& args, ::std::ostream* os) const
|
||||
virtual void ExplainMatchResultTo(const ArgumentTuple& args, ::std::ostream* os) const
|
||||
GTEST_EXCLUSIVE_LOCK_REQUIRED_(g_gmock_mutex) {
|
||||
g_gmock_mutex.AssertHeld();
|
||||
|
||||
@ -1263,6 +1354,55 @@ class TypedExpectation<R(Args...)> : public ExpectationBase {
|
||||
TypedExpectation& operator=(const TypedExpectation&) = delete;
|
||||
}; // class TypedExpectation
|
||||
|
||||
template <typename F>
|
||||
class SpecFactory;
|
||||
|
||||
// Implements an expectation for the given function type.
|
||||
template <typename R, typename... Args>
|
||||
class SpecFactory<R(Args...)> {
|
||||
private:
|
||||
using F = R(Args...);
|
||||
|
||||
public:
|
||||
typedef typename Function<F>::ArgumentTuple ArgumentTuple;
|
||||
typedef typename Function<F>::ArgumentMatcherTuple ArgumentMatcherTuple;
|
||||
typedef typename Function<F>::Result Result;
|
||||
|
||||
// Note: could route AddNewOnCallSpec() through here too
|
||||
|
||||
virtual OnCallSpec<F> *CreateOnCall(
|
||||
const char* a_file, int a_line, const ArgumentMatcherTuple& m ) = 0;
|
||||
|
||||
virtual std::shared_ptr<TypedExpectation<F>> CreateExpectation(
|
||||
FunctionMocker<F>* owner, const char* a_file, int a_line,
|
||||
const std::string& a_source_text, const ArgumentMatcherTuple& m ) = 0;
|
||||
};
|
||||
|
||||
|
||||
template <typename F>
|
||||
class DefaultSpecFactory;
|
||||
|
||||
// Implements an expectation for the given function type.
|
||||
template <typename R, typename... Args>
|
||||
class DefaultSpecFactory<R(Args...)> : public SpecFactory<R(Args...)> {
|
||||
private:
|
||||
using F = R(Args...);
|
||||
|
||||
public:
|
||||
typedef typename Function<F>::ArgumentMatcherTuple ArgumentMatcherTuple;
|
||||
|
||||
OnCallSpec<F> *CreateOnCall(
|
||||
const char* a_file, int a_line, const ArgumentMatcherTuple& m ) final {
|
||||
return new OnCallSpec<F>(a_file, a_line, m);
|
||||
}
|
||||
|
||||
std::shared_ptr<TypedExpectation<F>> CreateExpectation(
|
||||
FunctionMocker<F>* owner, const char* a_file, int a_line,
|
||||
const std::string& a_source_text, const ArgumentMatcherTuple& m ) final {
|
||||
return std::make_shared<TypedExpectation<F>>(owner, a_file, a_line, a_source_text, m);
|
||||
}
|
||||
};
|
||||
|
||||
// A MockSpec object is used by ON_CALL() or EXPECT_CALL() for
|
||||
// specifying the default behavior of, or expectation on, a mock
|
||||
// function.
|
||||
@ -1293,26 +1433,36 @@ class MockSpec {
|
||||
|
||||
// Adds a new default action spec to the function mocker and returns
|
||||
// the newly created spec.
|
||||
internal::OnCallSpec<F>& InternalDefaultActionSetAt(const char* file,
|
||||
internal::OnCallSpec<F>& InternalDefaultActionSetAt(SpecFactory<F> *factory,
|
||||
const char* file,
|
||||
int line, const char* obj,
|
||||
const char* call) {
|
||||
LogWithLocation(internal::kInfo, file, line,
|
||||
std::string("ON_CALL(") + obj + ", " + call + ") invoked");
|
||||
return function_mocker_->AddNewOnCallSpec(file, line, matchers_);
|
||||
return function_mocker_->AddNewOnCallSpec(factory, file, line, matchers_);
|
||||
}
|
||||
|
||||
// Adds a new expectation spec to the function mocker and returns
|
||||
// the newly created spec.
|
||||
internal::TypedExpectation<F>& InternalExpectedAt(const char* file, int line,
|
||||
internal::TypedExpectation<F>& InternalExpectedAt(SpecFactory<F> *factory,
|
||||
const char* file, int line,
|
||||
const char* obj,
|
||||
const char* call) {
|
||||
const std::string source_text(std::string("EXPECT_CALL(") + obj + ", " +
|
||||
call + ")");
|
||||
LogWithLocation(internal::kInfo, file, line, source_text + " invoked");
|
||||
return function_mocker_->AddNewExpectation(file, line, source_text,
|
||||
return function_mocker_->AddNewExpectation(factory, file, line, source_text,
|
||||
matchers_);
|
||||
}
|
||||
|
||||
const ArgumentMatcherTuple& InternalGetMatchers() const {
|
||||
return matchers_;
|
||||
}
|
||||
|
||||
internal::FunctionMocker<F>* InternalGetMocker() const {
|
||||
return function_mocker_;
|
||||
}
|
||||
|
||||
// This operator overload is used to swallow the superfluous parameter list
|
||||
// introduced by the ON/EXPECT_CALL macros. See the macro comments for more
|
||||
// explanation.
|
||||
@ -1467,6 +1617,8 @@ class FunctionMocker<R(Args...)> final : public UntypedFunctionMockerBase {
|
||||
// function have been satisfied. If not, it will report Google Test
|
||||
// non-fatal failures for the violations.
|
||||
~FunctionMocker() override GTEST_LOCK_EXCLUDED_(g_gmock_mutex) {
|
||||
if( !registered )
|
||||
return;
|
||||
MutexLock l(&g_gmock_mutex);
|
||||
VerifyAndClearExpectationsLocked();
|
||||
Mock::UnregisterLocked(this);
|
||||
@ -1552,29 +1704,9 @@ class FunctionMocker<R(Args...)> final : public UntypedFunctionMockerBase {
|
||||
return MockSpec<F>(this, ::std::make_tuple(std::move(m)...));
|
||||
}
|
||||
|
||||
protected:
|
||||
template <typename Function>
|
||||
friend class MockSpec;
|
||||
|
||||
// Adds and returns a default action spec for this mock function.
|
||||
OnCallSpec<F>& AddNewOnCallSpec(const char* file, int line,
|
||||
const ArgumentMatcherTuple& m)
|
||||
GTEST_LOCK_EXCLUDED_(g_gmock_mutex) {
|
||||
Mock::RegisterUseByOnCallOrExpectCall(MockObject(), file, line);
|
||||
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.
|
||||
TypedExpectation<F>& AddNewExpectation(const char* file, int line,
|
||||
const std::string& source_text,
|
||||
const ArgumentMatcherTuple& m)
|
||||
void AddExpectationInstance(const std::shared_ptr<ExpectationBase> untyped_expectation)
|
||||
GTEST_LOCK_EXCLUDED_(g_gmock_mutex) {
|
||||
Mock::RegisterUseByOnCallOrExpectCall(MockObject(), file, line);
|
||||
TypedExpectation<F>* const expectation =
|
||||
new TypedExpectation<F>(this, file, line, source_text, m);
|
||||
const std::shared_ptr<ExpectationBase> untyped_expectation(expectation);
|
||||
// See the definition of untyped_expectations_ for why access to
|
||||
// it is unprotected here.
|
||||
untyped_expectations_.push_back(untyped_expectation);
|
||||
@ -1584,7 +1716,32 @@ class FunctionMocker<R(Args...)> final : public UntypedFunctionMockerBase {
|
||||
if (implicit_sequence != nullptr) {
|
||||
implicit_sequence->AddExpectation(Expectation(untyped_expectation));
|
||||
}
|
||||
}
|
||||
|
||||
protected:
|
||||
template <typename Function>
|
||||
friend class MockSpec;
|
||||
|
||||
// Adds and returns a default action spec for this mock function.
|
||||
OnCallSpec<F>& AddNewOnCallSpec(SpecFactory<R(Args...)> *factory,
|
||||
const char* file, int line,
|
||||
const ArgumentMatcherTuple& m)
|
||||
GTEST_LOCK_EXCLUDED_(g_gmock_mutex) {
|
||||
Mock::RegisterUseByOnCallOrExpectCall(MockObject(), file, line);
|
||||
OnCallSpec<F>* const on_call_spec = factory->CreateOnCall(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.
|
||||
TypedExpectation<F>& AddNewExpectation(SpecFactory<R(Args...)> *factory,
|
||||
const char* file, int line,
|
||||
const std::string& source_text,
|
||||
const ArgumentMatcherTuple& m)
|
||||
GTEST_LOCK_EXCLUDED_(g_gmock_mutex) {
|
||||
Mock::RegisterUseByOnCallOrExpectCall(MockObject(), file, line);
|
||||
auto expectation = factory->CreateExpectation(this, file, line, source_text, m);
|
||||
AddExpectationInstance(expectation);
|
||||
return *expectation;
|
||||
}
|
||||
|
||||
@ -1640,15 +1797,26 @@ class FunctionMocker<R(Args...)> final : public UntypedFunctionMockerBase {
|
||||
// section. The reason is that we have no control on what the
|
||||
// action does (it can invoke an arbitrary user function or even a
|
||||
// mock function) and excessive locking could cause a dead lock.
|
||||
const ExpectationBase* UntypedFindMatchingExpectation(
|
||||
ExpectationBase* UntypedFindMatchingExpectation(
|
||||
const void* untyped_args, const void** untyped_action, bool* is_excessive,
|
||||
::std::ostream* what, ::std::ostream* why) override
|
||||
::std::ostream* what, ::std::ostream* why, bool *use_exp_for_action) override
|
||||
GTEST_LOCK_EXCLUDED_(g_gmock_mutex) {
|
||||
const ArgumentTuple& args =
|
||||
*static_cast<const ArgumentTuple*>(untyped_args);
|
||||
MutexLock l(&g_gmock_mutex);
|
||||
TypedExpectation<F>* exp = this->FindMatchingExpectationLocked(args);
|
||||
if (exp == nullptr) { // A match wasn't found.
|
||||
ExpectationBase *exp;
|
||||
TypedExpectation<F> *typed_exp = nullptr;
|
||||
if( auto aem = AlternateMockCallManager::TryGetInstance() ) {
|
||||
bool is_mocker_exp;
|
||||
exp = aem->FindMatchingExpectationLocked(this, untyped_args, &is_mocker_exp);
|
||||
if( is_mocker_exp )
|
||||
typed_exp = static_cast<TypedExpectation<F>*>(exp);
|
||||
}
|
||||
else {
|
||||
exp = typed_exp = this->FindMatchingExpectationLocked(untyped_args);
|
||||
}
|
||||
|
||||
if (exp == nullptr) { // A match wasn't found.
|
||||
this->FormatUnexpectedCallMessageLocked(args, what, why);
|
||||
return nullptr;
|
||||
}
|
||||
@ -1657,11 +1825,18 @@ class FunctionMocker<R(Args...)> final : public UntypedFunctionMockerBase {
|
||||
// which will increment the call count for *exp and thus affect
|
||||
// its saturation status.
|
||||
*is_excessive = exp->IsSaturated();
|
||||
const Action<F>* action = exp->GetActionForArguments(this, args, what, why);
|
||||
if (action != nullptr && action->IsDoDefault())
|
||||
action = nullptr; // Normalize "do default" to NULL.
|
||||
*untyped_action = action;
|
||||
return exp;
|
||||
if( typed_exp ) {
|
||||
const Action<F>* action = typed_exp->GetActionForArguments(this, args, what, why);
|
||||
*use_exp_for_action = (action != nullptr); // even if the action is default
|
||||
if (action != nullptr && action->IsDoDefault())
|
||||
action = nullptr; // Normalize "do default" to NULL.
|
||||
*untyped_action = action;
|
||||
}
|
||||
else {
|
||||
*untyped_action = nullptr;
|
||||
*use_exp_for_action = exp->UpdateCardinality(this, untyped_args, what, why);
|
||||
}
|
||||
return exp;
|
||||
}
|
||||
|
||||
// Prints the given function arguments to the ostream.
|
||||
@ -1674,7 +1849,7 @@ class FunctionMocker<R(Args...)> final : public UntypedFunctionMockerBase {
|
||||
|
||||
// Returns the expectation that matches the arguments, or NULL if no
|
||||
// expectation matches them.
|
||||
TypedExpectation<F>* FindMatchingExpectationLocked(const ArgumentTuple& args)
|
||||
TypedExpectation<F>* FindMatchingExpectationLocked(const void* untyped_args)
|
||||
const GTEST_EXCLUSIVE_LOCK_REQUIRED_(g_gmock_mutex) {
|
||||
g_gmock_mutex.AssertHeld();
|
||||
// See the definition of untyped_expectations_ for why access to
|
||||
@ -1684,7 +1859,7 @@ class FunctionMocker<R(Args...)> final : public UntypedFunctionMockerBase {
|
||||
it != untyped_expectations_.rend(); ++it) {
|
||||
TypedExpectation<F>* const exp =
|
||||
static_cast<TypedExpectation<F>*>(it->get());
|
||||
if (exp->ShouldHandleArguments(args)) {
|
||||
if (exp->ShouldHandleCall(this, untyped_args)) {
|
||||
return exp;
|
||||
}
|
||||
}
|
||||
@ -1788,9 +1963,14 @@ class FunctionMocker<R(Args...)> final : public UntypedFunctionMockerBase {
|
||||
template <typename R, typename... Args>
|
||||
R FunctionMocker<R(Args...)>::InvokeWith(ArgumentTuple&& args)
|
||||
GTEST_LOCK_EXCLUDED_(g_gmock_mutex) {
|
||||
bool uninteresting;
|
||||
if( auto aem = AlternateMockCallManager::TryGetInstance() )
|
||||
uninteresting = aem->IsUninteresting(this, &args);
|
||||
else
|
||||
uninteresting = untyped_expectations_.empty();
|
||||
// See the definition of untyped_expectations_ for why access to it
|
||||
// is unprotected here.
|
||||
if (untyped_expectations_.size() == 0) {
|
||||
if (uninteresting) {
|
||||
// No expectation is set on this mock method - we have an
|
||||
// uninteresting call.
|
||||
|
||||
@ -1850,13 +2030,15 @@ R FunctionMocker<R(Args...)>::InvokeWith(ArgumentTuple&& args)
|
||||
::std::stringstream why;
|
||||
::std::stringstream loc;
|
||||
const void* untyped_action = nullptr;
|
||||
|
||||
bool use_exp_for_action = false;
|
||||
|
||||
// The UntypedFindMatchingExpectation() function acquires and
|
||||
// releases g_gmock_mutex.
|
||||
|
||||
const ExpectationBase* const untyped_expectation =
|
||||
ExpectationBase* const untyped_expectation =
|
||||
this->UntypedFindMatchingExpectation(&args, &untyped_action,
|
||||
&is_excessive, &ss, &why);
|
||||
&is_excessive, &ss, &why,
|
||||
&use_exp_for_action);
|
||||
const bool found = untyped_expectation != nullptr;
|
||||
|
||||
// True if and only if we need to print the call's arguments
|
||||
@ -1867,7 +2049,14 @@ R FunctionMocker<R(Args...)>::InvokeWith(ArgumentTuple&& args)
|
||||
!found || is_excessive || LogIsVisible(kInfo);
|
||||
if (!need_to_report_call) {
|
||||
// Perform the action without printing the call information.
|
||||
return PerformAction(untyped_action, std::move(args), "");
|
||||
const void *untyped_return_value;
|
||||
bool handled = false;
|
||||
if( use_exp_for_action )
|
||||
handled = untyped_expectation->TryPerformAction(this, &args, &untyped_return_value);
|
||||
if( handled )
|
||||
return CotestTypeUtils<R>::Specialise( untyped_return_value );
|
||||
else
|
||||
return PerformAction(untyped_action, std::move(args), "");
|
||||
}
|
||||
|
||||
ss << " Function call: " << Name();
|
||||
@ -1893,8 +2082,15 @@ R FunctionMocker<R(Args...)>::InvokeWith(ArgumentTuple&& args)
|
||||
ss, why, loc, untyped_expectation, found, is_excessive
|
||||
};
|
||||
|
||||
return PerformActionAndPrintResult(untyped_action, std::move(args), ss.str(),
|
||||
ss);
|
||||
const void *untyped_return_value;
|
||||
bool handled = false;
|
||||
if( use_exp_for_action )
|
||||
handled = untyped_expectation->TryPerformAction(this, &args, &untyped_return_value);
|
||||
if( handled )
|
||||
return CotestTypeUtils<R>::Specialise( untyped_return_value );
|
||||
else
|
||||
return PerformActionAndPrintResult(untyped_action, std::move(args), ss.str(),
|
||||
ss);
|
||||
}
|
||||
|
||||
} // namespace internal
|
||||
@ -1931,6 +2127,15 @@ class MockFunction<R(Args...)> {
|
||||
return this->gmock_Call(::testing::A<Args>()...);
|
||||
}
|
||||
|
||||
MockSpec<R(Args...)> gmockq_Call(Matcher<Args>... m) {
|
||||
mock_.RegisterOwner(this, false);
|
||||
return mock_.With(std::move(m)...);
|
||||
}
|
||||
|
||||
MockSpec<R(Args...)> gmockq_Call(const WithoutMatchers&, R (*)(Args...)) {
|
||||
return this->gmockq_Call(::testing::A<Args>()...);
|
||||
}
|
||||
|
||||
protected:
|
||||
MockFunction() = default;
|
||||
~MockFunction() = default;
|
||||
@ -2134,15 +2339,30 @@ GTEST_DISABLE_MSC_WARNINGS_POP_() // 4251
|
||||
// second argument is an internal type derived from the method signature. The
|
||||
// failure to disambiguate two overloads of this method in the ON_CALL statement
|
||||
// is how we block callers from setting expectations on overloaded methods.
|
||||
#define GMOCK_ON_CALL_IMPL_(mock_expr, Setter, call) \
|
||||
((mock_expr).gmock_##call)(::testing::internal::GetWithoutMatchers(), \
|
||||
template <typename R, typename... Args>
|
||||
::testing::internal::OnCallSpec<R(Args...)>& GMockOnCallImpl_(
|
||||
::testing::MockSpec<R(Args...)> &&mock_spec,
|
||||
const char* file, int line, const char* obj, const char* call ) {
|
||||
static ::testing::internal::DefaultSpecFactory<R(Args...)> factory;
|
||||
return mock_spec.InternalDefaultActionSetAt(&factory, file, line, obj, call);
|
||||
}
|
||||
|
||||
template <typename R, typename... Args>
|
||||
::testing::internal::TypedExpectation<R(Args...)>& GMockExpectCallImpl_(
|
||||
::testing::MockSpec<R(Args...)> &&mock_spec,
|
||||
const char* file, int line, const char* obj, const char* call ) {
|
||||
static ::testing::internal::DefaultSpecFactory<R(Args...)> factory;
|
||||
return mock_spec.InternalExpectedAt(&factory, file, line, obj, call);
|
||||
}
|
||||
|
||||
#define GMOCK_GET_MOCKSPEC(mock_expr, call, prefix) \
|
||||
((mock_expr).prefix##_##call)(::testing::internal::GetWithoutMatchers(), \
|
||||
nullptr) \
|
||||
.Setter(__FILE__, __LINE__, #mock_expr, #call)
|
||||
|
||||
#define ON_CALL(obj, call) \
|
||||
GMOCK_ON_CALL_IMPL_(obj, InternalDefaultActionSetAt, call)
|
||||
GMockOnCallImpl_(std::move(GMOCK_GET_MOCKSPEC(obj, call, gmock)), __FILE__, __LINE__, #obj, #call)
|
||||
|
||||
#define EXPECT_CALL(obj, call) \
|
||||
GMOCK_ON_CALL_IMPL_(obj, InternalExpectedAt, call)
|
||||
GMockExpectCallImpl_(std::move(GMOCK_GET_MOCKSPEC(obj, call, gmock)), __FILE__, __LINE__, #obj, #call)
|
||||
|
||||
#endif // GOOGLEMOCK_INCLUDE_GMOCK_GMOCK_SPEC_BUILDERS_H_
|
||||
|
||||
@ -93,7 +93,8 @@ ExpectationBase::ExpectationBase(const char* a_file, int a_line,
|
||||
repeated_action_specified_(false),
|
||||
retires_on_saturation_(false),
|
||||
last_clause_(kNone),
|
||||
action_count_checked_(false) {}
|
||||
action_count_checked_(false),
|
||||
priority_(AlternateMockCallManager::GetNextPriority()) {}
|
||||
|
||||
// Destructs an ExpectationBase object.
|
||||
ExpectationBase::~ExpectationBase() = default;
|
||||
@ -275,6 +276,37 @@ void ExpectationBase::UntypedTimes(const Cardinality& a_cardinality) {
|
||||
SpecifyCardinality(a_cardinality);
|
||||
}
|
||||
|
||||
bool ExpectationBase::VerifyExpectationLocked()
|
||||
GTEST_EXCLUSIVE_LOCK_REQUIRED_(g_gmock_mutex) {
|
||||
bool expectation_met = true;
|
||||
if (IsOverSaturated()) {
|
||||
// There was an upper-bound violation. Since the error was
|
||||
// already reported when it occurred, there is no need to do
|
||||
// anything here.
|
||||
expectation_met = false;
|
||||
} else if (!IsSatisfied()) {
|
||||
expectation_met = false;
|
||||
::std::stringstream ss;
|
||||
|
||||
const ::std::string& expectation_name =
|
||||
GetDescription();
|
||||
ss << "Actual function ";
|
||||
if (!expectation_name.empty()) {
|
||||
ss << "\"" << expectation_name << "\" ";
|
||||
}
|
||||
ss << "call count doesn't match " << 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.
|
||||
MaybeDescribeExtraMatcherTo(&ss);
|
||||
DescribeCallCountTo(&ss);
|
||||
Expect(false, file(), line(),
|
||||
ss.str());
|
||||
}
|
||||
return expectation_met;
|
||||
}
|
||||
|
||||
// Points to the implicit sequence introduced by a living InSequence
|
||||
// object (if any) in the current thread or NULL.
|
||||
GTEST_API_ ThreadLocal<Sequence*> g_gmock_implicit_sequence;
|
||||
@ -315,13 +347,25 @@ UntypedFunctionMockerBase::~UntypedFunctionMockerBase() = default;
|
||||
// this information in the global mock registry. Will be called
|
||||
// whenever an EXPECT_CALL() or ON_CALL() is executed on this mock
|
||||
// method.
|
||||
void UntypedFunctionMockerBase::RegisterOwner(const void* mock_obj)
|
||||
GTEST_LOCK_EXCLUDED_(g_gmock_mutex) {
|
||||
void UntypedFunctionMockerBase::RegisterOwner(const void* mock_obj,
|
||||
bool to_reg) {
|
||||
// If mock_obj_ is NULL then "this" is probably corrupt (offset from NULL) but
|
||||
// the constructor defaults mock_obj_ to NULL, so we can check for that later.
|
||||
if( !mock_obj )
|
||||
return;
|
||||
|
||||
// If not registering, we still want to store the mock object pointer
|
||||
if( !to_reg ) {
|
||||
mock_obj_ = mock_obj;
|
||||
return;
|
||||
}
|
||||
|
||||
{
|
||||
MutexLock l(&g_gmock_mutex);
|
||||
mock_obj_ = mock_obj;
|
||||
}
|
||||
Mock::Register(mock_obj, this);
|
||||
registered = true; // Ensure we un-register
|
||||
}
|
||||
|
||||
// Sets the mock object this mock method belongs to, and sets the name
|
||||
@ -330,6 +374,12 @@ void UntypedFunctionMockerBase::RegisterOwner(const void* mock_obj)
|
||||
void UntypedFunctionMockerBase::SetOwnerAndName(const void* mock_obj,
|
||||
const char* name)
|
||||
GTEST_LOCK_EXCLUDED_(g_gmock_mutex) {
|
||||
|
||||
// This is our hook for pre-mocks. We must invoke cotest before
|
||||
// locking the gmock mutex.
|
||||
if( auto aem = AlternateMockCallManager::TryGetInstance() )
|
||||
aem->PreMockUnlocked(this, mock_obj, name);
|
||||
|
||||
// We protect name_ under g_gmock_mutex in case this mock function
|
||||
// is called from two threads concurrently.
|
||||
MutexLock l(&g_gmock_mutex);
|
||||
@ -349,11 +399,16 @@ const void* UntypedFunctionMockerBase::MockObject() const
|
||||
Assert(mock_obj_ != nullptr, __FILE__, __LINE__,
|
||||
"MockObject() must not be called before RegisterOwner() or "
|
||||
"SetOwnerAndName() has been called.");
|
||||
mock_obj = mock_obj_;
|
||||
mock_obj = MockObjectLocked();
|
||||
}
|
||||
return mock_obj;
|
||||
}
|
||||
|
||||
const void* UntypedFunctionMockerBase::MockObjectLocked() const
|
||||
GTEST_LOCK_EXCLUDED_(g_gmock_mutex) {
|
||||
return mock_obj_;
|
||||
}
|
||||
|
||||
// Returns the name of this mock method. Must be called after
|
||||
// SetOwnerAndName() has been called.
|
||||
const char* UntypedFunctionMockerBase::Name() const
|
||||
@ -366,11 +421,19 @@ const char* UntypedFunctionMockerBase::Name() const
|
||||
Assert(name_ != nullptr, __FILE__, __LINE__,
|
||||
"Name() must not be called before SetOwnerAndName() has "
|
||||
"been called.");
|
||||
name = name_;
|
||||
name = NameLocked();
|
||||
}
|
||||
return name;
|
||||
}
|
||||
|
||||
const char* UntypedFunctionMockerBase::NameLocked() const
|
||||
GTEST_EXCLUSIVE_LOCK_REQUIRED_(g_gmock_mutex) {
|
||||
Assert(name_ != nullptr, __FILE__, __LINE__,
|
||||
"Name() must not be called before SetOwnerAndName() has "
|
||||
"been called.");
|
||||
return name_;
|
||||
}
|
||||
|
||||
// Returns an Expectation object that references and co-owns exp,
|
||||
// which must be an expectation on this mock function.
|
||||
Expectation UntypedFunctionMockerBase::GetHandleOf(ExpectationBase* exp) {
|
||||
@ -443,6 +506,20 @@ bool UntypedFunctionMockerBase::VerifyAndClearExpectationsLocked()
|
||||
return expectations_met;
|
||||
}
|
||||
|
||||
AlternateMockCallManager::Priority AlternateMockCallManager::GetNextPriority()
|
||||
{
|
||||
return next_global_priority;
|
||||
}
|
||||
|
||||
AlternateMockCallManager *AlternateMockCallManager::TryGetInstance()
|
||||
{
|
||||
return instance;
|
||||
}
|
||||
|
||||
AlternateMockCallManager::Priority AlternateMockCallManager::next_global_priority = 0;
|
||||
|
||||
AlternateMockCallManager *AlternateMockCallManager::instance = nullptr;
|
||||
|
||||
static CallReaction intToCallReaction(int mock_behavior) {
|
||||
if (mock_behavior >= kAllow && mock_behavior <= kFail) {
|
||||
return static_cast<internal::CallReaction>(mock_behavior);
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user