mirror of
https://github.com/google/googletest.git
synced 2025-03-10 09:16:48 +00:00
Implements Expectation, ExpectationSet, and After for specifying expectation orders.
This commit is contained in:
parent
4019819dbb
commit
41b9b0b561
@ -49,13 +49,13 @@
|
|||||||
// .With(multi-argument-matchers)
|
// .With(multi-argument-matchers)
|
||||||
// .Times(cardinality)
|
// .Times(cardinality)
|
||||||
// .InSequence(sequences)
|
// .InSequence(sequences)
|
||||||
|
// .After(expectations)
|
||||||
// .WillOnce(action)
|
// .WillOnce(action)
|
||||||
// .WillRepeatedly(action)
|
// .WillRepeatedly(action)
|
||||||
// .RetiresOnSaturation();
|
// .RetiresOnSaturation();
|
||||||
//
|
//
|
||||||
// where all clauses are optional, .InSequence() and .WillOnce() can
|
// where all clauses are optional, and .InSequence()/.After()/
|
||||||
// appear any number of times, and .Times() can be omitted only if
|
// .WillOnce() can appear any number of times.
|
||||||
// .WillOnce() or .WillRepeatedly() is present.
|
|
||||||
|
|
||||||
#ifndef GMOCK_INCLUDE_GMOCK_GMOCK_SPEC_BUILDERS_H_
|
#ifndef GMOCK_INCLUDE_GMOCK_GMOCK_SPEC_BUILDERS_H_
|
||||||
#define GMOCK_INCLUDE_GMOCK_GMOCK_SPEC_BUILDERS_H_
|
#define GMOCK_INCLUDE_GMOCK_GMOCK_SPEC_BUILDERS_H_
|
||||||
@ -76,22 +76,30 @@
|
|||||||
|
|
||||||
namespace testing {
|
namespace testing {
|
||||||
|
|
||||||
|
// An abstract handle of an expectation.
|
||||||
|
class Expectation;
|
||||||
|
|
||||||
|
// A set of expectation handles.
|
||||||
|
class ExpectationSet;
|
||||||
|
|
||||||
// Anything inside the 'internal' namespace IS INTERNAL IMPLEMENTATION
|
// Anything inside the 'internal' namespace IS INTERNAL IMPLEMENTATION
|
||||||
// and MUST NOT BE USED IN USER CODE!!!
|
// and MUST NOT BE USED IN USER CODE!!!
|
||||||
namespace internal {
|
namespace internal {
|
||||||
|
|
||||||
template <typename F>
|
// Implements a mock function.
|
||||||
class FunctionMocker;
|
template <typename F> class FunctionMocker;
|
||||||
|
|
||||||
// Base class for expectations.
|
// Base class for expectations.
|
||||||
class ExpectationBase;
|
class ExpectationBase;
|
||||||
|
|
||||||
|
// Implements an expectation.
|
||||||
|
template <typename F> class TypedExpectation;
|
||||||
|
|
||||||
// Helper class for testing the Expectation class template.
|
// Helper class for testing the Expectation class template.
|
||||||
class ExpectationTester;
|
class ExpectationTester;
|
||||||
|
|
||||||
// Base class for function mockers.
|
// Base class for function mockers.
|
||||||
template <typename F>
|
template <typename F> class FunctionMockerBase;
|
||||||
class FunctionMockerBase;
|
|
||||||
|
|
||||||
// Protects the mock object registry (in class Mock), all function
|
// Protects the mock object registry (in class Mock), all function
|
||||||
// mockers, and all expectations.
|
// mockers, and all expectations.
|
||||||
@ -232,7 +240,8 @@ class DefaultActionSpec {
|
|||||||
Clause last_clause_;
|
Clause last_clause_;
|
||||||
}; // class DefaultActionSpec
|
}; // class DefaultActionSpec
|
||||||
|
|
||||||
// Possible reactions on uninteresting calls.
|
// Possible reactions on uninteresting calls. TODO(wan@google.com):
|
||||||
|
// rename the enum values to the kFoo style.
|
||||||
enum CallReaction {
|
enum CallReaction {
|
||||||
ALLOW,
|
ALLOW,
|
||||||
WARN,
|
WARN,
|
||||||
@ -327,31 +336,166 @@ class Mock {
|
|||||||
static void UnregisterLocked(internal::UntypedFunctionMockerBase* mocker);
|
static void UnregisterLocked(internal::UntypedFunctionMockerBase* mocker);
|
||||||
}; // class Mock
|
}; // class Mock
|
||||||
|
|
||||||
|
// An abstract handle of an expectation. Useful in the .After()
|
||||||
|
// clause of EXPECT_CALL() for setting the (partial) order of
|
||||||
|
// expectations. The syntax:
|
||||||
|
//
|
||||||
|
// Expectation e1 = EXPECT_CALL(...)...;
|
||||||
|
// EXPECT_CALL(...).After(e1)...;
|
||||||
|
//
|
||||||
|
// sets two expectations where the latter can only be matched after
|
||||||
|
// the former has been satisfied.
|
||||||
|
//
|
||||||
|
// Notes:
|
||||||
|
// - This class is copyable and has value semantics.
|
||||||
|
// - Constness is shallow: a const Expectation object itself cannot
|
||||||
|
// be modified, but the mutable methods of the ExpectationBase
|
||||||
|
// object it references can be called via expectation_base().
|
||||||
|
class Expectation {
|
||||||
|
public:
|
||||||
|
// Constructs a null object that doesn't reference any expectation.
|
||||||
|
Expectation() {}
|
||||||
|
|
||||||
|
// This single-argument ctor must not be explicit, in order to support the
|
||||||
|
// Expectation e = EXPECT_CALL(...);
|
||||||
|
// syntax.
|
||||||
|
//
|
||||||
|
// A TypedExpectation object stores its pre-requisites as
|
||||||
|
// Expectation objects, and needs to call the non-const Retire()
|
||||||
|
// method on the ExpectationBase objects they reference. Therefore
|
||||||
|
// Expectation must receive a *non-const* reference to the
|
||||||
|
// ExpectationBase object.
|
||||||
|
Expectation(internal::ExpectationBase& exp); // NOLINT
|
||||||
|
|
||||||
|
// The compiler-generated copy ctor and operator= work exactly as
|
||||||
|
// intended, so we don't need to define our own.
|
||||||
|
|
||||||
|
// Returns true iff rhs references the same expectation as this object does.
|
||||||
|
bool operator==(const Expectation& rhs) const {
|
||||||
|
return expectation_base_ == rhs.expectation_base_;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator!=(const Expectation& rhs) const { return !(*this == rhs); }
|
||||||
|
|
||||||
|
private:
|
||||||
|
friend class ExpectationSet;
|
||||||
|
friend class Sequence;
|
||||||
|
friend class ::testing::internal::ExpectationBase;
|
||||||
|
|
||||||
|
template <typename F>
|
||||||
|
friend class ::testing::internal::FunctionMockerBase;
|
||||||
|
|
||||||
|
template <typename F>
|
||||||
|
friend class ::testing::internal::TypedExpectation;
|
||||||
|
|
||||||
|
// This comparator is needed for putting Expectation objects into a set.
|
||||||
|
class Less {
|
||||||
|
public:
|
||||||
|
bool operator()(const Expectation& lhs, const Expectation& rhs) const {
|
||||||
|
return lhs.expectation_base_.get() < rhs.expectation_base_.get();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef ::std::set<Expectation, Less> Set;
|
||||||
|
|
||||||
|
Expectation(
|
||||||
|
const internal::linked_ptr<internal::ExpectationBase>& expectation_base) :
|
||||||
|
expectation_base_(expectation_base) {}
|
||||||
|
|
||||||
|
// Returns the expectation this object references.
|
||||||
|
const internal::linked_ptr<internal::ExpectationBase>&
|
||||||
|
expectation_base() const {
|
||||||
|
return expectation_base_;
|
||||||
|
}
|
||||||
|
|
||||||
|
// A linked_ptr that co-owns the expectation this handle references.
|
||||||
|
internal::linked_ptr<internal::ExpectationBase> expectation_base_;
|
||||||
|
};
|
||||||
|
|
||||||
|
// A set of expectation handles. Useful in the .After() clause of
|
||||||
|
// EXPECT_CALL() for setting the (partial) order of expectations. The
|
||||||
|
// syntax:
|
||||||
|
//
|
||||||
|
// ExpectationSet es;
|
||||||
|
// es += EXPECT_CALL(...)...;
|
||||||
|
// es += EXPECT_CALL(...)...;
|
||||||
|
// EXPECT_CALL(...).After(es)...;
|
||||||
|
//
|
||||||
|
// sets three expectations where the last one can only be matched
|
||||||
|
// after the first two have both been satisfied.
|
||||||
|
//
|
||||||
|
// This class is copyable and has value semantics.
|
||||||
|
class ExpectationSet {
|
||||||
|
public:
|
||||||
|
// A bidirectional iterator that can read a const element in the set.
|
||||||
|
typedef Expectation::Set::const_iterator const_iterator;
|
||||||
|
|
||||||
|
// An object stored in the set. This is an alias of Expectation.
|
||||||
|
typedef Expectation::Set::value_type value_type;
|
||||||
|
|
||||||
|
// Constructs an empty set.
|
||||||
|
ExpectationSet() {}
|
||||||
|
|
||||||
|
// This single-argument ctor must not be explicit, in order to support the
|
||||||
|
// ExpectationSet es = EXPECT_CALL(...);
|
||||||
|
// syntax.
|
||||||
|
ExpectationSet(internal::ExpectationBase& exp) { // NOLINT
|
||||||
|
*this += Expectation(exp);
|
||||||
|
}
|
||||||
|
|
||||||
|
// This single-argument ctor implements implicit conversion from
|
||||||
|
// Expectation and thus must not be explicit. This allows either an
|
||||||
|
// Expectation or an ExpectationSet to be used in .After().
|
||||||
|
ExpectationSet(const Expectation& e) { // NOLINT
|
||||||
|
*this += e;
|
||||||
|
}
|
||||||
|
|
||||||
|
// The compiler-generator ctor and operator= works exactly as
|
||||||
|
// intended, so we don't need to define our own.
|
||||||
|
|
||||||
|
// Returns true iff rhs contains the same set of Expectation objects
|
||||||
|
// as this does.
|
||||||
|
bool operator==(const ExpectationSet& rhs) const {
|
||||||
|
return expectations_ == rhs.expectations_;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator!=(const ExpectationSet& rhs) const { return !(*this == rhs); }
|
||||||
|
|
||||||
|
// Implements the syntax
|
||||||
|
// expectation_set += EXPECT_CALL(...);
|
||||||
|
ExpectationSet& operator+=(const Expectation& e) {
|
||||||
|
expectations_.insert(e);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
int size() const { return static_cast<int>(expectations_.size()); }
|
||||||
|
|
||||||
|
const_iterator begin() const { return expectations_.begin(); }
|
||||||
|
const_iterator end() const { return expectations_.end(); }
|
||||||
|
|
||||||
|
private:
|
||||||
|
Expectation::Set expectations_;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
// Sequence objects are used by a user to specify the relative order
|
// Sequence objects are used by a user to specify the relative order
|
||||||
// in which the expectations should match. They are copyable (we rely
|
// in which the expectations should match. They are copyable (we rely
|
||||||
// on the compiler-defined copy constructor and assignment operator).
|
// on the compiler-defined copy constructor and assignment operator).
|
||||||
class Sequence {
|
class Sequence {
|
||||||
public:
|
public:
|
||||||
// Constructs an empty sequence.
|
// Constructs an empty sequence.
|
||||||
Sequence()
|
Sequence() : last_expectation_(new Expectation) {}
|
||||||
: last_expectation_(
|
|
||||||
new internal::linked_ptr<internal::ExpectationBase>(NULL)) {}
|
|
||||||
|
|
||||||
// Adds an expectation to this sequence. The caller must ensure
|
// Adds an expectation to this sequence. The caller must ensure
|
||||||
// that no other thread is accessing this Sequence object.
|
// that no other thread is accessing this Sequence object.
|
||||||
void AddExpectation(
|
void AddExpectation(const Expectation& expectation) const;
|
||||||
const internal::linked_ptr<internal::ExpectationBase>& expectation) const;
|
|
||||||
private:
|
private:
|
||||||
// The last expectation in this sequence. We use a nested
|
// The last expectation in this sequence. We use a linked_ptr here
|
||||||
// linked_ptr here because:
|
// because Sequence objects are copyable and we want the copies to
|
||||||
// - Sequence objects are copyable, and we want the copies to act
|
// be aliases. The linked_ptr allows the copies to co-own and share
|
||||||
// as aliases. The outer linked_ptr allows the copies to co-own
|
// the same Expectation object.
|
||||||
// and share the same state.
|
internal::linked_ptr<Expectation> last_expectation_;
|
||||||
// - An Expectation object is co-owned (via linked_ptr) by its
|
|
||||||
// FunctionMocker and its successors (other Expectation objects).
|
|
||||||
// Hence the inner linked_ptr.
|
|
||||||
internal::linked_ptr<internal::linked_ptr<internal::ExpectationBase> >
|
|
||||||
last_expectation_;
|
|
||||||
}; // class Sequence
|
}; // class Sequence
|
||||||
|
|
||||||
// An object of this type causes all EXPECT_CALL() statements
|
// An object of this type causes all EXPECT_CALL() statements
|
||||||
@ -431,9 +575,7 @@ class ExpectationBase {
|
|||||||
// L >= g_gmock_mutex
|
// L >= g_gmock_mutex
|
||||||
virtual void DescribeCallCountTo(::std::ostream* os) const = 0;
|
virtual void DescribeCallCountTo(::std::ostream* os) const = 0;
|
||||||
protected:
|
protected:
|
||||||
typedef std::set<linked_ptr<ExpectationBase>,
|
friend class ::testing::Expectation;
|
||||||
LinkedPtrLessThan<ExpectationBase> >
|
|
||||||
ExpectationBaseSet;
|
|
||||||
|
|
||||||
enum Clause {
|
enum Clause {
|
||||||
// Don't change the order of the enum members!
|
// Don't change the order of the enum members!
|
||||||
@ -441,11 +583,16 @@ class ExpectationBase {
|
|||||||
kWith,
|
kWith,
|
||||||
kTimes,
|
kTimes,
|
||||||
kInSequence,
|
kInSequence,
|
||||||
|
kAfter,
|
||||||
kWillOnce,
|
kWillOnce,
|
||||||
kWillRepeatedly,
|
kWillRepeatedly,
|
||||||
kRetiresOnSaturation,
|
kRetiresOnSaturation,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Returns an Expectation object that references and co-owns this
|
||||||
|
// expectation.
|
||||||
|
virtual Expectation GetHandle() = 0;
|
||||||
|
|
||||||
// Asserts that the EXPECT_CALL() statement has the given property.
|
// Asserts that the EXPECT_CALL() statement has the given property.
|
||||||
void AssertSpecProperty(bool property, const string& failure_message) const {
|
void AssertSpecProperty(bool property, const string& failure_message) const {
|
||||||
Assert(property, file_, line_, failure_message);
|
Assert(property, file_, line_, failure_message);
|
||||||
@ -518,7 +665,7 @@ class ExpectationBase {
|
|||||||
|
|
||||||
// Adds unsatisfied pre-requisites of this expectation to 'result'.
|
// Adds unsatisfied pre-requisites of this expectation to 'result'.
|
||||||
// L >= g_gmock_mutex
|
// L >= g_gmock_mutex
|
||||||
void FindUnsatisfiedPrerequisites(ExpectationBaseSet* result) const;
|
void FindUnsatisfiedPrerequisites(ExpectationSet* result) const;
|
||||||
|
|
||||||
// Returns the number this expectation has been invoked.
|
// Returns the number this expectation has been invoked.
|
||||||
// L >= g_gmock_mutex
|
// L >= g_gmock_mutex
|
||||||
@ -539,7 +686,7 @@ class ExpectationBase {
|
|||||||
friend class ::testing::internal::ExpectationTester;
|
friend class ::testing::internal::ExpectationTester;
|
||||||
|
|
||||||
template <typename Function>
|
template <typename Function>
|
||||||
friend class Expectation;
|
friend class TypedExpectation;
|
||||||
|
|
||||||
// This group of fields are part of the spec and won't change after
|
// This group of fields are part of the spec and won't change after
|
||||||
// an EXPECT_CALL() statement finishes.
|
// an EXPECT_CALL() statement finishes.
|
||||||
@ -548,11 +695,13 @@ class ExpectationBase {
|
|||||||
// True iff the cardinality is specified explicitly.
|
// True iff the cardinality is specified explicitly.
|
||||||
bool cardinality_specified_;
|
bool cardinality_specified_;
|
||||||
Cardinality cardinality_; // The cardinality of the expectation.
|
Cardinality cardinality_; // The cardinality of the expectation.
|
||||||
// The immediate pre-requisites of this expectation. We use
|
// The immediate pre-requisites (i.e. expectations that must be
|
||||||
// linked_ptr in the set because we want an Expectation object to be
|
// satisfied before this expectation can be matched) of this
|
||||||
// co-owned by its FunctionMocker and its successors. This allows
|
// expectation. We use linked_ptr in the set because we want an
|
||||||
// multiple mock objects to be deleted at different times.
|
// Expectation object to be co-owned by its FunctionMocker and its
|
||||||
ExpectationBaseSet immediate_prerequisites_;
|
// successors. This allows multiple mock objects to be deleted at
|
||||||
|
// different times.
|
||||||
|
ExpectationSet immediate_prerequisites_;
|
||||||
|
|
||||||
// This group of fields are the current state of the expectation,
|
// This group of fields are the current state of the expectation,
|
||||||
// and can change as the mock function is called.
|
// and can change as the mock function is called.
|
||||||
@ -562,13 +711,13 @@ class ExpectationBase {
|
|||||||
|
|
||||||
// Impements an expectation for the given function type.
|
// Impements an expectation for the given function type.
|
||||||
template <typename F>
|
template <typename F>
|
||||||
class Expectation : public ExpectationBase {
|
class TypedExpectation : public ExpectationBase {
|
||||||
public:
|
public:
|
||||||
typedef typename Function<F>::ArgumentTuple ArgumentTuple;
|
typedef typename Function<F>::ArgumentTuple ArgumentTuple;
|
||||||
typedef typename Function<F>::ArgumentMatcherTuple ArgumentMatcherTuple;
|
typedef typename Function<F>::ArgumentMatcherTuple ArgumentMatcherTuple;
|
||||||
typedef typename Function<F>::Result Result;
|
typedef typename Function<F>::Result Result;
|
||||||
|
|
||||||
Expectation(FunctionMockerBase<F>* owner, const char* file, int line,
|
TypedExpectation(FunctionMockerBase<F>* owner, const char* file, int line,
|
||||||
const ArgumentMatcherTuple& m)
|
const ArgumentMatcherTuple& m)
|
||||||
: ExpectationBase(file, line),
|
: ExpectationBase(file, line),
|
||||||
owner_(owner),
|
owner_(owner),
|
||||||
@ -584,14 +733,14 @@ class Expectation : public ExpectationBase {
|
|||||||
last_clause_(kNone),
|
last_clause_(kNone),
|
||||||
action_count_checked_(false) {}
|
action_count_checked_(false) {}
|
||||||
|
|
||||||
virtual ~Expectation() {
|
virtual ~TypedExpectation() {
|
||||||
// Check the validity of the action count if it hasn't been done
|
// Check the validity of the action count if it hasn't been done
|
||||||
// yet (for example, if the expectation was never used).
|
// yet (for example, if the expectation was never used).
|
||||||
CheckActionCountIfNotDone();
|
CheckActionCountIfNotDone();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Implements the .With() clause.
|
// Implements the .With() clause.
|
||||||
Expectation& With(const Matcher<const ArgumentTuple&>& m) {
|
TypedExpectation& With(const Matcher<const ArgumentTuple&>& m) {
|
||||||
if (last_clause_ == kWith) {
|
if (last_clause_ == kWith) {
|
||||||
ExpectSpecProperty(false,
|
ExpectSpecProperty(false,
|
||||||
".With() cannot appear "
|
".With() cannot appear "
|
||||||
@ -608,7 +757,7 @@ class Expectation : public ExpectationBase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Implements the .Times() clause.
|
// Implements the .Times() clause.
|
||||||
Expectation& Times(const Cardinality& cardinality) {
|
TypedExpectation& Times(const Cardinality& cardinality) {
|
||||||
if (last_clause_ ==kTimes) {
|
if (last_clause_ ==kTimes) {
|
||||||
ExpectSpecProperty(false,
|
ExpectSpecProperty(false,
|
||||||
".Times() cannot appear "
|
".Times() cannot appear "
|
||||||
@ -626,40 +775,70 @@ class Expectation : public ExpectationBase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Implements the .Times() clause.
|
// Implements the .Times() clause.
|
||||||
Expectation& Times(int n) {
|
TypedExpectation& Times(int n) {
|
||||||
return Times(Exactly(n));
|
return Times(Exactly(n));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Implements the .InSequence() clause.
|
// Implements the .InSequence() clause.
|
||||||
Expectation& InSequence(const Sequence& s) {
|
TypedExpectation& InSequence(const Sequence& s) {
|
||||||
ExpectSpecProperty(last_clause_ <= kInSequence,
|
ExpectSpecProperty(last_clause_ <= kInSequence,
|
||||||
".InSequence() cannot appear after .WillOnce(),"
|
".InSequence() cannot appear after .After(),"
|
||||||
" .WillRepeatedly(), or "
|
" .WillOnce(), .WillRepeatedly(), or "
|
||||||
".RetiresOnSaturation().");
|
".RetiresOnSaturation().");
|
||||||
last_clause_ = kInSequence;
|
last_clause_ = kInSequence;
|
||||||
|
|
||||||
s.AddExpectation(owner_->GetLinkedExpectationBase(this));
|
s.AddExpectation(GetHandle());
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
Expectation& InSequence(const Sequence& s1, const Sequence& s2) {
|
TypedExpectation& InSequence(const Sequence& s1, const Sequence& s2) {
|
||||||
return InSequence(s1).InSequence(s2);
|
return InSequence(s1).InSequence(s2);
|
||||||
}
|
}
|
||||||
Expectation& InSequence(const Sequence& s1, const Sequence& s2,
|
TypedExpectation& InSequence(const Sequence& s1, const Sequence& s2,
|
||||||
const Sequence& s3) {
|
const Sequence& s3) {
|
||||||
return InSequence(s1, s2).InSequence(s3);
|
return InSequence(s1, s2).InSequence(s3);
|
||||||
}
|
}
|
||||||
Expectation& InSequence(const Sequence& s1, const Sequence& s2,
|
TypedExpectation& InSequence(const Sequence& s1, const Sequence& s2,
|
||||||
const Sequence& s3, const Sequence& s4) {
|
const Sequence& s3, const Sequence& s4) {
|
||||||
return InSequence(s1, s2, s3).InSequence(s4);
|
return InSequence(s1, s2, s3).InSequence(s4);
|
||||||
}
|
}
|
||||||
Expectation& InSequence(const Sequence& s1, const Sequence& s2,
|
TypedExpectation& InSequence(const Sequence& s1, const Sequence& s2,
|
||||||
const Sequence& s3, const Sequence& s4,
|
const Sequence& s3, const Sequence& s4,
|
||||||
const Sequence& s5) {
|
const Sequence& s5) {
|
||||||
return InSequence(s1, s2, s3, s4).InSequence(s5);
|
return InSequence(s1, s2, s3, s4).InSequence(s5);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Implements that .After() clause.
|
||||||
|
TypedExpectation& After(const ExpectationSet& s) {
|
||||||
|
ExpectSpecProperty(last_clause_ <= kAfter,
|
||||||
|
".After() cannot appear after .WillOnce(),"
|
||||||
|
" .WillRepeatedly(), or "
|
||||||
|
".RetiresOnSaturation().");
|
||||||
|
last_clause_ = kAfter;
|
||||||
|
|
||||||
|
for (ExpectationSet::const_iterator it = s.begin(); it != s.end(); ++it) {
|
||||||
|
immediate_prerequisites_ += *it;
|
||||||
|
}
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
TypedExpectation& After(const ExpectationSet& s1, const ExpectationSet& s2) {
|
||||||
|
return After(s1).After(s2);
|
||||||
|
}
|
||||||
|
TypedExpectation& After(const ExpectationSet& s1, const ExpectationSet& s2,
|
||||||
|
const ExpectationSet& s3) {
|
||||||
|
return After(s1, s2).After(s3);
|
||||||
|
}
|
||||||
|
TypedExpectation& After(const ExpectationSet& s1, const ExpectationSet& s2,
|
||||||
|
const ExpectationSet& s3, const ExpectationSet& s4) {
|
||||||
|
return After(s1, s2, s3).After(s4);
|
||||||
|
}
|
||||||
|
TypedExpectation& After(const ExpectationSet& s1, const ExpectationSet& s2,
|
||||||
|
const ExpectationSet& s3, const ExpectationSet& s4,
|
||||||
|
const ExpectationSet& s5) {
|
||||||
|
return After(s1, s2, s3, s4).After(s5);
|
||||||
|
}
|
||||||
|
|
||||||
// Implements the .WillOnce() clause.
|
// Implements the .WillOnce() clause.
|
||||||
Expectation& WillOnce(const Action<F>& action) {
|
TypedExpectation& WillOnce(const Action<F>& action) {
|
||||||
ExpectSpecProperty(last_clause_ <= kWillOnce,
|
ExpectSpecProperty(last_clause_ <= kWillOnce,
|
||||||
".WillOnce() cannot appear after "
|
".WillOnce() cannot appear after "
|
||||||
".WillRepeatedly() or .RetiresOnSaturation().");
|
".WillRepeatedly() or .RetiresOnSaturation().");
|
||||||
@ -673,7 +852,7 @@ class Expectation : public ExpectationBase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Implements the .WillRepeatedly() clause.
|
// Implements the .WillRepeatedly() clause.
|
||||||
Expectation& WillRepeatedly(const Action<F>& action) {
|
TypedExpectation& WillRepeatedly(const Action<F>& action) {
|
||||||
if (last_clause_ == kWillRepeatedly) {
|
if (last_clause_ == kWillRepeatedly) {
|
||||||
ExpectSpecProperty(false,
|
ExpectSpecProperty(false,
|
||||||
".WillRepeatedly() cannot appear "
|
".WillRepeatedly() cannot appear "
|
||||||
@ -698,7 +877,7 @@ class Expectation : public ExpectationBase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Implements the .RetiresOnSaturation() clause.
|
// Implements the .RetiresOnSaturation() clause.
|
||||||
Expectation& RetiresOnSaturation() {
|
TypedExpectation& RetiresOnSaturation() {
|
||||||
ExpectSpecProperty(last_clause_ < kRetiresOnSaturation,
|
ExpectSpecProperty(last_clause_ < kRetiresOnSaturation,
|
||||||
".RetiresOnSaturation() cannot appear "
|
".RetiresOnSaturation() cannot appear "
|
||||||
"more than once.");
|
"more than once.");
|
||||||
@ -756,6 +935,12 @@ class Expectation : public ExpectationBase {
|
|||||||
template <typename Function>
|
template <typename Function>
|
||||||
friend class FunctionMockerBase;
|
friend class FunctionMockerBase;
|
||||||
|
|
||||||
|
// Returns an Expectation object that references and co-owns this
|
||||||
|
// expectation.
|
||||||
|
virtual Expectation GetHandle() {
|
||||||
|
return owner_->GetHandleOf(this);
|
||||||
|
}
|
||||||
|
|
||||||
// The following methods will be called only after the EXPECT_CALL()
|
// The following methods will be called only after the EXPECT_CALL()
|
||||||
// statement finishes and when the current thread holds
|
// statement finishes and when the current thread holds
|
||||||
// g_gmock_mutex.
|
// g_gmock_mutex.
|
||||||
@ -807,12 +992,12 @@ class Expectation : public ExpectationBase {
|
|||||||
*os << " Expected: all pre-requisites are satisfied\n"
|
*os << " Expected: all pre-requisites are satisfied\n"
|
||||||
<< " Actual: the following immediate pre-requisites "
|
<< " Actual: the following immediate pre-requisites "
|
||||||
<< "are not satisfied:\n";
|
<< "are not satisfied:\n";
|
||||||
ExpectationBaseSet unsatisfied_prereqs;
|
ExpectationSet unsatisfied_prereqs;
|
||||||
FindUnsatisfiedPrerequisites(&unsatisfied_prereqs);
|
FindUnsatisfiedPrerequisites(&unsatisfied_prereqs);
|
||||||
int i = 0;
|
int i = 0;
|
||||||
for (ExpectationBaseSet::const_iterator it = unsatisfied_prereqs.begin();
|
for (ExpectationSet::const_iterator it = unsatisfied_prereqs.begin();
|
||||||
it != unsatisfied_prereqs.end(); ++it) {
|
it != unsatisfied_prereqs.end(); ++it) {
|
||||||
(*it)->DescribeLocationTo(os);
|
it->expectation_base()->DescribeLocationTo(os);
|
||||||
*os << "pre-requisite #" << i++ << "\n";
|
*os << "pre-requisite #" << i++ << "\n";
|
||||||
}
|
}
|
||||||
*os << " (end of pre-requisites)\n";
|
*os << " (end of pre-requisites)\n";
|
||||||
@ -957,7 +1142,7 @@ class Expectation : public ExpectationBase {
|
|||||||
Clause last_clause_;
|
Clause last_clause_;
|
||||||
mutable bool action_count_checked_; // Under mutex_.
|
mutable bool action_count_checked_; // Under mutex_.
|
||||||
mutable Mutex mutex_; // Protects action_count_checked_.
|
mutable Mutex mutex_; // Protects action_count_checked_.
|
||||||
}; // class Expectation
|
}; // class TypedExpectation
|
||||||
|
|
||||||
// A MockSpec object is used by ON_CALL() or EXPECT_CALL() for
|
// A MockSpec object is used by ON_CALL() or EXPECT_CALL() for
|
||||||
// specifying the default behavior of, or expectation on, a mock
|
// specifying the default behavior of, or expectation on, a mock
|
||||||
@ -992,7 +1177,7 @@ class MockSpec {
|
|||||||
|
|
||||||
// Adds a new expectation spec to the function mocker and returns
|
// Adds a new expectation spec to the function mocker and returns
|
||||||
// the newly created spec.
|
// the newly created spec.
|
||||||
internal::Expectation<F>& InternalExpectedAt(
|
internal::TypedExpectation<F>& InternalExpectedAt(
|
||||||
const char* file, int line, const char* obj, const char* call) {
|
const char* file, int line, const char* obj, const char* call) {
|
||||||
LogWithLocation(internal::INFO, file, line,
|
LogWithLocation(internal::INFO, file, line,
|
||||||
string("EXPECT_CALL(") + obj + ", " + call + ") invoked");
|
string("EXPECT_CALL(") + obj + ", " + call + ") invoked");
|
||||||
@ -1247,18 +1432,18 @@ class FunctionMockerBase : public UntypedFunctionMockerBase {
|
|||||||
|
|
||||||
// Adds and returns an expectation spec for this mock function.
|
// Adds and returns an expectation spec for this mock function.
|
||||||
// L < g_gmock_mutex
|
// L < g_gmock_mutex
|
||||||
Expectation<F>& AddNewExpectation(
|
TypedExpectation<F>& AddNewExpectation(
|
||||||
const char* file, int line,
|
const char* file, int line,
|
||||||
const ArgumentMatcherTuple& m) {
|
const ArgumentMatcherTuple& m) {
|
||||||
Mock::RegisterUseByOnCallOrExpectCall(MockObject(), file, line);
|
Mock::RegisterUseByOnCallOrExpectCall(MockObject(), file, line);
|
||||||
const linked_ptr<Expectation<F> > expectation(
|
const linked_ptr<TypedExpectation<F> > expectation(
|
||||||
new Expectation<F>(this, file, line, m));
|
new TypedExpectation<F>(this, file, line, m));
|
||||||
expectations_.push_back(expectation);
|
expectations_.push_back(expectation);
|
||||||
|
|
||||||
// Adds this expectation into the implicit sequence if there is one.
|
// Adds this expectation into the implicit sequence if there is one.
|
||||||
Sequence* const implicit_sequence = g_gmock_implicit_sequence.get();
|
Sequence* const implicit_sequence = g_gmock_implicit_sequence.get();
|
||||||
if (implicit_sequence != NULL) {
|
if (implicit_sequence != NULL) {
|
||||||
implicit_sequence->AddExpectation(expectation);
|
implicit_sequence->AddExpectation(Expectation(expectation));
|
||||||
}
|
}
|
||||||
|
|
||||||
return *expectation;
|
return *expectation;
|
||||||
@ -1268,22 +1453,23 @@ class FunctionMockerBase : public UntypedFunctionMockerBase {
|
|||||||
// being described on this function mocker.
|
// being described on this function mocker.
|
||||||
MockSpec<F>& current_spec() { return current_spec_; }
|
MockSpec<F>& current_spec() { return current_spec_; }
|
||||||
private:
|
private:
|
||||||
template <typename Func> friend class Expectation;
|
template <typename Func> friend class TypedExpectation;
|
||||||
|
|
||||||
typedef std::vector<internal::linked_ptr<Expectation<F> > > Expectations;
|
typedef std::vector<internal::linked_ptr<TypedExpectation<F> > >
|
||||||
|
TypedExpectations;
|
||||||
|
|
||||||
// Gets the internal::linked_ptr<ExpectationBase> object that co-owns 'exp'.
|
// Returns an Expectation object that references and co-owns exp,
|
||||||
internal::linked_ptr<ExpectationBase> GetLinkedExpectationBase(
|
// which must be an expectation on this mock function.
|
||||||
Expectation<F>* exp) {
|
Expectation GetHandleOf(TypedExpectation<F>* exp) {
|
||||||
for (typename Expectations::const_iterator it = expectations_.begin();
|
for (typename TypedExpectations::const_iterator it = expectations_.begin();
|
||||||
it != expectations_.end(); ++it) {
|
it != expectations_.end(); ++it) {
|
||||||
if (it->get() == exp) {
|
if (it->get() == exp) {
|
||||||
return *it;
|
return Expectation(*it);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Assert(false, __FILE__, __LINE__, "Cannot find expectation.");
|
Assert(false, __FILE__, __LINE__, "Cannot find expectation.");
|
||||||
return internal::linked_ptr<ExpectationBase>(NULL);
|
return Expectation();
|
||||||
// The above statement is just to make the code compile, and will
|
// The above statement is just to make the code compile, and will
|
||||||
// never be executed.
|
// never be executed.
|
||||||
}
|
}
|
||||||
@ -1330,7 +1516,7 @@ class FunctionMockerBase : public UntypedFunctionMockerBase {
|
|||||||
// mock function) and excessive locking could cause a dead lock.
|
// mock function) and excessive locking could cause a dead lock.
|
||||||
// L < g_gmock_mutex
|
// L < g_gmock_mutex
|
||||||
bool FindMatchingExpectationAndAction(
|
bool FindMatchingExpectationAndAction(
|
||||||
const ArgumentTuple& args, Expectation<F>** exp, Action<F>* action,
|
const ArgumentTuple& args, TypedExpectation<F>** exp, Action<F>* action,
|
||||||
bool* is_excessive, ::std::ostream* what, ::std::ostream* why) {
|
bool* is_excessive, ::std::ostream* what, ::std::ostream* why) {
|
||||||
MutexLock l(&g_gmock_mutex);
|
MutexLock l(&g_gmock_mutex);
|
||||||
*exp = this->FindMatchingExpectationLocked(args);
|
*exp = this->FindMatchingExpectationLocked(args);
|
||||||
@ -1351,13 +1537,13 @@ class FunctionMockerBase : public UntypedFunctionMockerBase {
|
|||||||
// Returns the expectation that matches the arguments, or NULL if no
|
// Returns the expectation that matches the arguments, or NULL if no
|
||||||
// expectation matches them.
|
// expectation matches them.
|
||||||
// L >= g_gmock_mutex
|
// L >= g_gmock_mutex
|
||||||
Expectation<F>* FindMatchingExpectationLocked(
|
TypedExpectation<F>* FindMatchingExpectationLocked(
|
||||||
const ArgumentTuple& args) const {
|
const ArgumentTuple& args) const {
|
||||||
g_gmock_mutex.AssertHeld();
|
g_gmock_mutex.AssertHeld();
|
||||||
for (typename Expectations::const_reverse_iterator it =
|
for (typename TypedExpectations::const_reverse_iterator it =
|
||||||
expectations_.rbegin();
|
expectations_.rbegin();
|
||||||
it != expectations_.rend(); ++it) {
|
it != expectations_.rend(); ++it) {
|
||||||
Expectation<F>* const exp = it->get();
|
TypedExpectation<F>* const exp = it->get();
|
||||||
if (exp->ShouldHandleArguments(args)) {
|
if (exp->ShouldHandleArguments(args)) {
|
||||||
return exp;
|
return exp;
|
||||||
}
|
}
|
||||||
@ -1415,7 +1601,7 @@ class FunctionMockerBase : public UntypedFunctionMockerBase {
|
|||||||
// All default action specs for this function mocker.
|
// All default action specs for this function mocker.
|
||||||
std::vector<DefaultActionSpec<F> > default_actions_;
|
std::vector<DefaultActionSpec<F> > default_actions_;
|
||||||
// All expectations for this function mocker.
|
// All expectations for this function mocker.
|
||||||
Expectations expectations_;
|
TypedExpectations expectations_;
|
||||||
|
|
||||||
// There is no generally useful and implementable semantics of
|
// There is no generally useful and implementable semantics of
|
||||||
// copying a mock object, so copying a mock is usually a user error.
|
// copying a mock object, so copying a mock is usually a user error.
|
||||||
@ -1446,9 +1632,9 @@ template <typename F>
|
|||||||
bool FunctionMockerBase<F>::VerifyAndClearExpectationsLocked() {
|
bool FunctionMockerBase<F>::VerifyAndClearExpectationsLocked() {
|
||||||
g_gmock_mutex.AssertHeld();
|
g_gmock_mutex.AssertHeld();
|
||||||
bool expectations_met = true;
|
bool expectations_met = true;
|
||||||
for (typename Expectations::const_iterator it = expectations_.begin();
|
for (typename TypedExpectations::const_iterator it = expectations_.begin();
|
||||||
it != expectations_.end(); ++it) {
|
it != expectations_.end(); ++it) {
|
||||||
Expectation<F>* const exp = it->get();
|
TypedExpectation<F>* const exp = it->get();
|
||||||
|
|
||||||
if (exp->IsOverSaturated()) {
|
if (exp->IsOverSaturated()) {
|
||||||
// There was an upper-bound violation. Since the error was
|
// There was an upper-bound violation. Since the error was
|
||||||
@ -1532,7 +1718,7 @@ typename Function<F>::Result FunctionMockerBase<F>::InvokeWith(
|
|||||||
::std::stringstream why;
|
::std::stringstream why;
|
||||||
::std::stringstream loc;
|
::std::stringstream loc;
|
||||||
Action<F> action;
|
Action<F> action;
|
||||||
Expectation<F>* exp;
|
TypedExpectation<F>* exp;
|
||||||
|
|
||||||
// The FindMatchingExpectationAndAction() function acquires and
|
// The FindMatchingExpectationAndAction() function acquires and
|
||||||
// releases g_gmock_mutex.
|
// releases g_gmock_mutex.
|
||||||
@ -1605,6 +1791,10 @@ using internal::MockSpec;
|
|||||||
template <typename T>
|
template <typename T>
|
||||||
inline const T& Const(const T& x) { return x; }
|
inline const T& Const(const T& x) { return x; }
|
||||||
|
|
||||||
|
// Constructs an Expectation object that references and co-owns exp.
|
||||||
|
inline Expectation::Expectation(internal::ExpectationBase& exp) // NOLINT
|
||||||
|
: expectation_base_(exp.GetHandle().expectation_base()) {}
|
||||||
|
|
||||||
} // namespace testing
|
} // namespace testing
|
||||||
|
|
||||||
// A separate macro is required to avoid compile errors when the name
|
// A separate macro is required to avoid compile errors when the name
|
||||||
|
@ -82,11 +82,9 @@ void ExpectationBase::RetireAllPreRequisites() {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (ExpectationBaseSet::const_iterator it =
|
for (ExpectationSet::const_iterator it = immediate_prerequisites_.begin();
|
||||||
immediate_prerequisites_.begin();
|
it != immediate_prerequisites_.end(); ++it) {
|
||||||
it != immediate_prerequisites_.end();
|
ExpectationBase* const prerequisite = it->expectation_base().get();
|
||||||
++it) {
|
|
||||||
ExpectationBase* const prerequisite = (*it).get();
|
|
||||||
if (!prerequisite->is_retired()) {
|
if (!prerequisite->is_retired()) {
|
||||||
prerequisite->RetireAllPreRequisites();
|
prerequisite->RetireAllPreRequisites();
|
||||||
prerequisite->Retire();
|
prerequisite->Retire();
|
||||||
@ -99,10 +97,10 @@ void ExpectationBase::RetireAllPreRequisites() {
|
|||||||
// L >= g_gmock_mutex
|
// L >= g_gmock_mutex
|
||||||
bool ExpectationBase::AllPrerequisitesAreSatisfied() const {
|
bool ExpectationBase::AllPrerequisitesAreSatisfied() const {
|
||||||
g_gmock_mutex.AssertHeld();
|
g_gmock_mutex.AssertHeld();
|
||||||
for (ExpectationBaseSet::const_iterator it = immediate_prerequisites_.begin();
|
for (ExpectationSet::const_iterator it = immediate_prerequisites_.begin();
|
||||||
it != immediate_prerequisites_.end(); ++it) {
|
it != immediate_prerequisites_.end(); ++it) {
|
||||||
if (!(*it)->IsSatisfied() ||
|
if (!(it->expectation_base()->IsSatisfied()) ||
|
||||||
!(*it)->AllPrerequisitesAreSatisfied())
|
!(it->expectation_base()->AllPrerequisitesAreSatisfied()))
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
@ -111,21 +109,21 @@ bool ExpectationBase::AllPrerequisitesAreSatisfied() const {
|
|||||||
// Adds unsatisfied pre-requisites of this expectation to 'result'.
|
// Adds unsatisfied pre-requisites of this expectation to 'result'.
|
||||||
// L >= g_gmock_mutex
|
// L >= g_gmock_mutex
|
||||||
void ExpectationBase::FindUnsatisfiedPrerequisites(
|
void ExpectationBase::FindUnsatisfiedPrerequisites(
|
||||||
ExpectationBaseSet* result) const {
|
ExpectationSet* result) const {
|
||||||
g_gmock_mutex.AssertHeld();
|
g_gmock_mutex.AssertHeld();
|
||||||
for (ExpectationBaseSet::const_iterator it = immediate_prerequisites_.begin();
|
for (ExpectationSet::const_iterator it = immediate_prerequisites_.begin();
|
||||||
it != immediate_prerequisites_.end(); ++it) {
|
it != immediate_prerequisites_.end(); ++it) {
|
||||||
if ((*it)->IsSatisfied()) {
|
if (it->expectation_base()->IsSatisfied()) {
|
||||||
// If *it is satisfied and has a call count of 0, some of its
|
// If *it is satisfied and has a call count of 0, some of its
|
||||||
// pre-requisites may not be satisfied yet.
|
// pre-requisites may not be satisfied yet.
|
||||||
if ((*it)->call_count_ == 0) {
|
if (it->expectation_base()->call_count_ == 0) {
|
||||||
(*it)->FindUnsatisfiedPrerequisites(result);
|
it->expectation_base()->FindUnsatisfiedPrerequisites(result);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Now that we know *it is unsatisfied, we are not so interested
|
// Now that we know *it is unsatisfied, we are not so interested
|
||||||
// in whether its pre-requisites are satisfied. Therefore we
|
// in whether its pre-requisites are satisfied. Therefore we
|
||||||
// don't recursively call FindUnsatisfiedPrerequisites() here.
|
// don't recursively call FindUnsatisfiedPrerequisites() here.
|
||||||
result->insert(*it);
|
*result += *it;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -421,11 +419,11 @@ void Mock::ClearDefaultActionsLocked(void* mock_obj) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Adds an expectation to a sequence.
|
// Adds an expectation to a sequence.
|
||||||
void Sequence::AddExpectation(
|
void Sequence::AddExpectation(const Expectation& expectation) const {
|
||||||
const internal::linked_ptr<internal::ExpectationBase>& expectation) const {
|
|
||||||
if (*last_expectation_ != expectation) {
|
if (*last_expectation_ != expectation) {
|
||||||
if (*last_expectation_ != NULL) {
|
if (last_expectation_->expectation_base() != NULL) {
|
||||||
expectation->immediate_prerequisites_.insert(*last_expectation_);
|
expectation.expectation_base()->immediate_prerequisites_
|
||||||
|
+= *last_expectation_;
|
||||||
}
|
}
|
||||||
*last_expectation_ = expectation;
|
*last_expectation_ = expectation;
|
||||||
}
|
}
|
||||||
|
@ -71,6 +71,9 @@ using testing::CardinalityInterface;
|
|||||||
using testing::Const;
|
using testing::Const;
|
||||||
using testing::DoAll;
|
using testing::DoAll;
|
||||||
using testing::DoDefault;
|
using testing::DoDefault;
|
||||||
|
using testing::Eq;
|
||||||
|
using testing::Expectation;
|
||||||
|
using testing::ExpectationSet;
|
||||||
using testing::GMOCK_FLAG(verbose);
|
using testing::GMOCK_FLAG(verbose);
|
||||||
using testing::Gt;
|
using testing::Gt;
|
||||||
using testing::InSequence;
|
using testing::InSequence;
|
||||||
@ -80,13 +83,13 @@ using testing::IsSubstring;
|
|||||||
using testing::Lt;
|
using testing::Lt;
|
||||||
using testing::Message;
|
using testing::Message;
|
||||||
using testing::Mock;
|
using testing::Mock;
|
||||||
|
using testing::Ne;
|
||||||
using testing::Return;
|
using testing::Return;
|
||||||
using testing::Sequence;
|
using testing::Sequence;
|
||||||
using testing::internal::g_gmock_mutex;
|
using testing::internal::g_gmock_mutex;
|
||||||
using testing::internal::kErrorVerbosity;
|
using testing::internal::kErrorVerbosity;
|
||||||
using testing::internal::kInfoVerbosity;
|
using testing::internal::kInfoVerbosity;
|
||||||
using testing::internal::kWarningVerbosity;
|
using testing::internal::kWarningVerbosity;
|
||||||
using testing::internal::Expectation;
|
|
||||||
using testing::internal::ExpectationTester;
|
using testing::internal::ExpectationTester;
|
||||||
using testing::internal::string;
|
using testing::internal::string;
|
||||||
|
|
||||||
@ -345,7 +348,22 @@ TEST(ExpectCallSyntaxTest, InSequenceCanAppearMultipleTimes) {
|
|||||||
a.DoA(1);
|
a.DoA(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(ExpectCallSyntaxTest, InSequenceMustBeBeforeWill) {
|
TEST(ExpectCallSyntaxTest, InSequenceMustBeBeforeAfter) {
|
||||||
|
MockA a;
|
||||||
|
Sequence s;
|
||||||
|
|
||||||
|
Expectation e = EXPECT_CALL(a, DoA(1))
|
||||||
|
.Times(AnyNumber());
|
||||||
|
EXPECT_NONFATAL_FAILURE({ // NOLINT
|
||||||
|
EXPECT_CALL(a, DoA(2))
|
||||||
|
.After(e)
|
||||||
|
.InSequence(s);
|
||||||
|
}, ".InSequence() cannot appear after ");
|
||||||
|
|
||||||
|
a.DoA(2);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(ExpectCallSyntaxTest, InSequenceMustBeBeforeWillOnce) {
|
||||||
MockA a;
|
MockA a;
|
||||||
Sequence s;
|
Sequence s;
|
||||||
|
|
||||||
@ -358,6 +376,20 @@ TEST(ExpectCallSyntaxTest, InSequenceMustBeBeforeWill) {
|
|||||||
a.DoA(1);
|
a.DoA(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST(ExpectCallSyntaxTest, AfterMustBeBeforeWillOnce) {
|
||||||
|
MockA a;
|
||||||
|
|
||||||
|
Expectation e = EXPECT_CALL(a, DoA(1));
|
||||||
|
EXPECT_NONFATAL_FAILURE({
|
||||||
|
EXPECT_CALL(a, DoA(2))
|
||||||
|
.WillOnce(Return())
|
||||||
|
.After(e);
|
||||||
|
}, ".After() cannot appear after ");
|
||||||
|
|
||||||
|
a.DoA(1);
|
||||||
|
a.DoA(2);
|
||||||
|
}
|
||||||
|
|
||||||
TEST(ExpectCallSyntaxTest, WillIsOptional) {
|
TEST(ExpectCallSyntaxTest, WillIsOptional) {
|
||||||
MockA a;
|
MockA a;
|
||||||
|
|
||||||
@ -1248,6 +1280,292 @@ TEST(SequenceTest, Retirement) {
|
|||||||
a.DoA(1);
|
a.DoA(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Tests Expectation.
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
|
EXPECT_THAT(e1, Ne(e2));
|
||||||
|
EXPECT_THAT(e2, Eq(e3));
|
||||||
|
a.DoA(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(ExpectationTest, AssignmentWorks) {
|
||||||
|
MockA a;
|
||||||
|
Expectation e1;
|
||||||
|
Expectation e2 = EXPECT_CALL(a, DoA(1));
|
||||||
|
|
||||||
|
EXPECT_THAT(e1, Ne(e2));
|
||||||
|
|
||||||
|
e1 = e2;
|
||||||
|
EXPECT_THAT(e1, Eq(e2));
|
||||||
|
|
||||||
|
a.DoA(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Tests ExpectationSet.
|
||||||
|
|
||||||
|
TEST(ExpectationSetTest, MemberTypesAreCorrect) {
|
||||||
|
::testing::StaticAssertTypeEq<Expectation, ExpectationSet::value_type>();
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(ExpectationSetTest, ConstructorsWork) {
|
||||||
|
MockA a;
|
||||||
|
|
||||||
|
Expectation e1;
|
||||||
|
const Expectation e2;
|
||||||
|
ExpectationSet es1; // Default ctor.
|
||||||
|
ExpectationSet es2 = EXPECT_CALL(a, DoA(1)); // Ctor from EXPECT_CALL.
|
||||||
|
ExpectationSet es3 = e1; // Ctor from Expectation.
|
||||||
|
ExpectationSet es4(e1); // Ctor from Expectation; alternative syntax.
|
||||||
|
ExpectationSet es5 = e2; // Ctor from const Expectation.
|
||||||
|
ExpectationSet es6(e2); // Ctor from const Expectation; alternative syntax.
|
||||||
|
ExpectationSet es7 = es2; // Copy ctor.
|
||||||
|
|
||||||
|
EXPECT_EQ(0, es1.size());
|
||||||
|
EXPECT_EQ(1, es2.size());
|
||||||
|
EXPECT_EQ(1, es3.size());
|
||||||
|
EXPECT_EQ(1, es4.size());
|
||||||
|
EXPECT_EQ(1, es5.size());
|
||||||
|
EXPECT_EQ(1, es6.size());
|
||||||
|
EXPECT_EQ(1, es7.size());
|
||||||
|
|
||||||
|
EXPECT_THAT(es3, Ne(es2));
|
||||||
|
EXPECT_THAT(es4, Eq(es3));
|
||||||
|
EXPECT_THAT(es5, Eq(es4));
|
||||||
|
EXPECT_THAT(es6, Eq(es5));
|
||||||
|
EXPECT_THAT(es7, Eq(es2));
|
||||||
|
a.DoA(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(ExpectationSetTest, AssignmentWorks) {
|
||||||
|
ExpectationSet es1;
|
||||||
|
ExpectationSet es2 = Expectation();
|
||||||
|
|
||||||
|
es1 = es2;
|
||||||
|
EXPECT_EQ(1, es1.size());
|
||||||
|
EXPECT_THAT(*(es1.begin()), Eq(Expectation()));
|
||||||
|
EXPECT_THAT(es1, Eq(es2));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(ExpectationSetTest, InsertionWorks) {
|
||||||
|
ExpectationSet es1;
|
||||||
|
Expectation e1;
|
||||||
|
es1 += e1;
|
||||||
|
EXPECT_EQ(1, es1.size());
|
||||||
|
EXPECT_THAT(*(es1.begin()), Eq(e1));
|
||||||
|
|
||||||
|
MockA a;
|
||||||
|
Expectation e2 = EXPECT_CALL(a, DoA(1));
|
||||||
|
es1 += e2;
|
||||||
|
EXPECT_EQ(2, es1.size());
|
||||||
|
|
||||||
|
ExpectationSet::const_iterator it1 = es1.begin();
|
||||||
|
ExpectationSet::const_iterator it2 = it1;
|
||||||
|
++it2;
|
||||||
|
EXPECT_TRUE(*it1 == e1 || *it2 == e1); // e1 must be in the set.
|
||||||
|
EXPECT_TRUE(*it1 == e2 || *it2 == e2); // e2 must be in the set too.
|
||||||
|
a.DoA(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(ExpectationSetTest, SizeWorks) {
|
||||||
|
ExpectationSet es;
|
||||||
|
EXPECT_EQ(0, es.size());
|
||||||
|
|
||||||
|
es += Expectation();
|
||||||
|
EXPECT_EQ(1, es.size());
|
||||||
|
|
||||||
|
MockA a;
|
||||||
|
es += EXPECT_CALL(a, DoA(1));
|
||||||
|
EXPECT_EQ(2, es.size());
|
||||||
|
|
||||||
|
a.DoA(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(ExpectationSetTest, IsEnumerable) {
|
||||||
|
ExpectationSet es;
|
||||||
|
EXPECT_THAT(es.begin(), Eq(es.end()));
|
||||||
|
|
||||||
|
es += Expectation();
|
||||||
|
ExpectationSet::const_iterator it = es.begin();
|
||||||
|
EXPECT_THAT(it, Ne(es.end()));
|
||||||
|
EXPECT_THAT(*it, Eq(Expectation()));
|
||||||
|
++it;
|
||||||
|
EXPECT_THAT(it, Eq(es.end()));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Tests the .After() clause.
|
||||||
|
|
||||||
|
TEST(AfterTest, SucceedsWhenPartialOrderIsSatisfied) {
|
||||||
|
MockA a;
|
||||||
|
ExpectationSet es;
|
||||||
|
es += EXPECT_CALL(a, DoA(1));
|
||||||
|
es += EXPECT_CALL(a, DoA(2));
|
||||||
|
EXPECT_CALL(a, DoA(3))
|
||||||
|
.After(es);
|
||||||
|
|
||||||
|
a.DoA(1);
|
||||||
|
a.DoA(2);
|
||||||
|
a.DoA(3);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(AfterTest, SucceedsWhenTotalOrderIsSatisfied) {
|
||||||
|
MockA a;
|
||||||
|
MockB b;
|
||||||
|
// The following also verifies that const Expectation objects work
|
||||||
|
// too. Do not remove the const modifiers.
|
||||||
|
const Expectation e1 = EXPECT_CALL(a, DoA(1));
|
||||||
|
const Expectation e2 = EXPECT_CALL(b, DoB())
|
||||||
|
.Times(2)
|
||||||
|
.After(e1);
|
||||||
|
EXPECT_CALL(a, DoA(2)).After(e2);
|
||||||
|
|
||||||
|
a.DoA(1);
|
||||||
|
b.DoB();
|
||||||
|
b.DoB();
|
||||||
|
a.DoA(2);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Calls must be in strict order when specified so.
|
||||||
|
TEST(AfterTest, CallsMustBeInStrictOrderWhenSpecifiedSo) {
|
||||||
|
MockA a;
|
||||||
|
MockB b;
|
||||||
|
Expectation e1 = EXPECT_CALL(a, DoA(1));
|
||||||
|
Expectation e2 = EXPECT_CALL(b, DoB())
|
||||||
|
.Times(2)
|
||||||
|
.After(e1);
|
||||||
|
EXPECT_CALL(a, ReturnResult(2))
|
||||||
|
.After(e2)
|
||||||
|
.WillOnce(Return(Result()));
|
||||||
|
|
||||||
|
a.DoA(1);
|
||||||
|
// If a call to ReturnResult() violates the specified order, no
|
||||||
|
// matching expectation will be found, and thus the default action
|
||||||
|
// will be done. Since the return type of ReturnResult() is not a
|
||||||
|
// built-in type, gmock won't know what to return and will thus
|
||||||
|
// abort the program. Therefore a death test can tell us whether
|
||||||
|
// gmock catches the order violation correctly.
|
||||||
|
//
|
||||||
|
// gtest and gmock print messages to stdout, which isn't captured by
|
||||||
|
// death tests. Therefore we have to match with an empty regular
|
||||||
|
// expression in all the EXPECT_DEATH()s.
|
||||||
|
EXPECT_DEATH(a.ReturnResult(2), "");
|
||||||
|
|
||||||
|
b.DoB();
|
||||||
|
EXPECT_DEATH(a.ReturnResult(2), "");
|
||||||
|
|
||||||
|
b.DoB();
|
||||||
|
a.ReturnResult(2);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Calls must satisfy the partial order when specified so.
|
||||||
|
TEST(AfterTest, CallsMustSatisfyPartialOrderWhenSpecifiedSo) {
|
||||||
|
MockA a;
|
||||||
|
Expectation e = EXPECT_CALL(a, DoA(1));
|
||||||
|
const ExpectationSet es = EXPECT_CALL(a, DoA(2));
|
||||||
|
EXPECT_CALL(a, ReturnResult(3))
|
||||||
|
.After(e, es)
|
||||||
|
.WillOnce(Return(Result()));
|
||||||
|
|
||||||
|
EXPECT_DEATH(a.ReturnResult(3), "");
|
||||||
|
|
||||||
|
a.DoA(2);
|
||||||
|
EXPECT_DEATH(a.ReturnResult(3), "");
|
||||||
|
|
||||||
|
a.DoA(1);
|
||||||
|
a.ReturnResult(3);
|
||||||
|
}
|
||||||
|
|
||||||
|
// .After() can be combined with .InSequence().
|
||||||
|
TEST(AfterTest, CanBeUsedWithInSequence) {
|
||||||
|
MockA a;
|
||||||
|
Sequence s;
|
||||||
|
Expectation e = EXPECT_CALL(a, DoA(1));
|
||||||
|
EXPECT_CALL(a, DoA(2)).InSequence(s);
|
||||||
|
EXPECT_CALL(a, ReturnResult(3))
|
||||||
|
.InSequence(s).After(e)
|
||||||
|
.WillOnce(Return(Result()));
|
||||||
|
|
||||||
|
a.DoA(1);
|
||||||
|
EXPECT_DEATH(a.ReturnResult(3), "");
|
||||||
|
|
||||||
|
a.DoA(2);
|
||||||
|
a.ReturnResult(3);
|
||||||
|
}
|
||||||
|
|
||||||
|
// .After() can be called multiple times.
|
||||||
|
TEST(AfterTest, CanBeCalledManyTimes) {
|
||||||
|
MockA a;
|
||||||
|
Expectation e1 = EXPECT_CALL(a, DoA(1));
|
||||||
|
Expectation e2 = EXPECT_CALL(a, DoA(2));
|
||||||
|
Expectation e3 = EXPECT_CALL(a, DoA(3));
|
||||||
|
EXPECT_CALL(a, DoA(4))
|
||||||
|
.After(e1)
|
||||||
|
.After(e2)
|
||||||
|
.After(e3);
|
||||||
|
|
||||||
|
a.DoA(3);
|
||||||
|
a.DoA(1);
|
||||||
|
a.DoA(2);
|
||||||
|
a.DoA(4);
|
||||||
|
}
|
||||||
|
|
||||||
|
// .After() accepts up to 5 arguments.
|
||||||
|
TEST(AfterTest, AcceptsUpToFiveArguments) {
|
||||||
|
MockA a;
|
||||||
|
Expectation e1 = EXPECT_CALL(a, DoA(1));
|
||||||
|
Expectation e2 = EXPECT_CALL(a, DoA(2));
|
||||||
|
Expectation e3 = EXPECT_CALL(a, DoA(3));
|
||||||
|
ExpectationSet es1 = EXPECT_CALL(a, DoA(4));
|
||||||
|
ExpectationSet es2 = EXPECT_CALL(a, DoA(5));
|
||||||
|
EXPECT_CALL(a, DoA(6))
|
||||||
|
.After(e1, e2, e3, es1, es2);
|
||||||
|
|
||||||
|
a.DoA(5);
|
||||||
|
a.DoA(2);
|
||||||
|
a.DoA(4);
|
||||||
|
a.DoA(1);
|
||||||
|
a.DoA(3);
|
||||||
|
a.DoA(6);
|
||||||
|
}
|
||||||
|
|
||||||
|
// .After() allows input to contain duplicated Expectations.
|
||||||
|
TEST(AfterTest, AcceptsDuplicatedInput) {
|
||||||
|
MockA a;
|
||||||
|
Expectation e1 = EXPECT_CALL(a, DoA(1));
|
||||||
|
Expectation e2 = EXPECT_CALL(a, DoA(2));
|
||||||
|
ExpectationSet es;
|
||||||
|
es += e1;
|
||||||
|
es += e2;
|
||||||
|
EXPECT_CALL(a, ReturnResult(3))
|
||||||
|
.After(e1, e2, es, e1)
|
||||||
|
.WillOnce(Return(Result()));
|
||||||
|
|
||||||
|
a.DoA(1);
|
||||||
|
EXPECT_DEATH(a.ReturnResult(3), "");
|
||||||
|
|
||||||
|
a.DoA(2);
|
||||||
|
a.ReturnResult(3);
|
||||||
|
}
|
||||||
|
|
||||||
|
// An Expectation added to an ExpectationSet after it has been used in
|
||||||
|
// an .After() has no effect.
|
||||||
|
TEST(AfterTest, ChangesToExpectationSetHaveNoEffectAfterwards) {
|
||||||
|
MockA a;
|
||||||
|
ExpectationSet es1 = EXPECT_CALL(a, DoA(1));
|
||||||
|
Expectation e2 = EXPECT_CALL(a, DoA(2));
|
||||||
|
EXPECT_CALL(a, DoA(3))
|
||||||
|
.After(es1);
|
||||||
|
es1 += e2;
|
||||||
|
|
||||||
|
a.DoA(1);
|
||||||
|
a.DoA(3);
|
||||||
|
a.DoA(2);
|
||||||
|
}
|
||||||
|
|
||||||
// Tests that Google Mock correctly handles calls to mock functions
|
// Tests that Google Mock correctly handles calls to mock functions
|
||||||
// after a mock object owning one of their pre-requisites has died.
|
// after a mock object owning one of their pre-requisites has died.
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user