aboutsummaryrefslogtreecommitdiffstats
path: root/include/gmock/gmock-matchers.h
diff options
context:
space:
mode:
Diffstat (limited to 'include/gmock/gmock-matchers.h')
-rw-r--r--include/gmock/gmock-matchers.h704
1 files changed, 382 insertions, 322 deletions
diff --git a/include/gmock/gmock-matchers.h b/include/gmock/gmock-matchers.h
index 5f5a29fd..b1689d6e 100644
--- a/include/gmock/gmock-matchers.h
+++ b/include/gmock/gmock-matchers.h
@@ -64,14 +64,74 @@ namespace testing {
// ownership management as Matcher objects can now be copied like
// plain values.
+// MatchResultListener is an abstract class. Its << operator can be
+// used by a matcher to explain why a value matches or doesn't match.
+//
+// TODO(wan@google.com): add method
+// bool InterestedInWhy(bool result) const;
+// to indicate whether the listener is interested in why the match
+// result is 'result'.
+class MatchResultListener {
+ public:
+ // Creates a listener object with the given underlying ostream. The
+ // listener does not own the ostream.
+ explicit MatchResultListener(::std::ostream* os) : stream_(os) {}
+ virtual ~MatchResultListener() = 0; // Makes this class abstract.
+
+ // Streams x to the underlying ostream; does nothing if the ostream
+ // is NULL.
+ template <typename T>
+ MatchResultListener& operator<<(const T& x) {
+ if (stream_ != NULL)
+ *stream_ << x;
+ return *this;
+ }
+
+ // Returns the underlying ostream.
+ ::std::ostream* stream() { return stream_; }
+
+ private:
+ ::std::ostream* const stream_;
+
+ GTEST_DISALLOW_COPY_AND_ASSIGN_(MatchResultListener);
+};
+
+inline MatchResultListener::~MatchResultListener() {
+}
+
// The implementation of a matcher.
template <typename T>
class MatcherInterface {
public:
virtual ~MatcherInterface() {}
+ // Returns true iff the matcher matches x; also explains the match
+ // result to 'listener'.
+ //
+ // You should override this method when defining a new matcher. For
+ // backward compatibility, we provide a default implementation that
+ // just forwards to the old, deprecated matcher API (Matches() and
+ // ExplainMatchResultTo()).
+ //
+ // It's the responsibility of the caller (Google Mock) to guarantee
+ // that 'listener' is not NULL. This helps to simplify a matcher's
+ // implementation when it doesn't care about the performance, as it
+ // can talk to 'listener' without checking its validity first.
+ // However, in order to implement dummy listeners efficiently,
+ // listener->stream() may be NULL.
+ virtual bool MatchAndExplain(T x, MatchResultListener* listener) const {
+ const bool match = Matches(x);
+ if (listener->stream() != NULL) {
+ ExplainMatchResultTo(x, listener->stream());
+ }
+ return match;
+ }
+
+ // DEPRECATED. This method will be removed. Override
+ // MatchAndExplain() instead.
+ //
// Returns true iff the matcher matches x.
- virtual bool Matches(T x) const = 0;
+ virtual bool Matches(T /* x */) const { return false; }
// Describes this matcher to an ostream.
virtual void DescribeTo(::std::ostream* os) const = 0;
@@ -88,6 +148,9 @@ class MatcherInterface {
*os << ")";
}
+ // DEPRECATED. This method will be removed. Override
+ // MatchAndExplain() instead.
+ //
// Explains why x matches, or doesn't match, the matcher. Override
// this to provide any additional information that helps a user
// understand the match result.
@@ -100,14 +163,58 @@ class MatcherInterface {
namespace internal {
+// A match result listener that ignores the explanation.
+class DummyMatchResultListener : public MatchResultListener {
+ public:
+ DummyMatchResultListener() : MatchResultListener(NULL) {}
+
+ private:
+ GTEST_DISALLOW_COPY_AND_ASSIGN_(DummyMatchResultListener);
+};
+
+// A match result listener that forwards the explanation to a given
+// ostream. The difference between this and MatchResultListener is
+// that the former is concrete.
+class StreamMatchResultListener : public MatchResultListener {
+ public:
+ explicit StreamMatchResultListener(::std::ostream* os)
+ : MatchResultListener(os) {}
+
+ private:
+ GTEST_DISALLOW_COPY_AND_ASSIGN_(StreamMatchResultListener);
+};
+
+// A match result listener that stores the explanation in a string.
+class StringMatchResultListener : public MatchResultListener {
+ public:
+ StringMatchResultListener() : MatchResultListener(&ss_) {}
+
+ // Returns the explanation heard so far.
+ internal::string str() const { return ss_.str(); }
+
+ private:
+ ::std::stringstream ss_;
+
+ GTEST_DISALLOW_COPY_AND_ASSIGN_(StringMatchResultListener);
+};
+
// An internal class for implementing Matcher<T>, which will derive
// from it. We put functionalities common to all Matcher<T>
// specializations here to avoid code duplication.
template <typename T>
class MatcherBase {
public:
+ // Returns true iff the matcher matches x; also explains the match
+ // result to 'listener'.
+ bool MatchAndExplain(T x, MatchResultListener* listener) const {
+ return impl_->MatchAndExplain(x, listener);
+ }
+
// Returns true iff this matcher matches x.
- bool Matches(T x) const { return impl_->Matches(x); }
+ bool Matches(T x) const {
+ DummyMatchResultListener dummy;
+ return MatchAndExplain(x, &dummy);
+ }
// Describes this matcher to an ostream.
void DescribeTo(::std::ostream* os) const { impl_->DescribeTo(os); }
@@ -119,7 +226,8 @@ class MatcherBase {
// Explains why x matches, or doesn't match, the matcher.
void ExplainMatchResultTo(T x, ::std::ostream* os) const {
- impl_->ExplainMatchResultTo(x, os);
+ StreamMatchResultListener listener(os);
+ MatchAndExplain(x, &listener);
}
protected:
@@ -156,6 +264,27 @@ inline void ExplainMatchResultTo(const PolymorphicMatcherImpl& /* impl */,
// prints the value of x elsewhere.
}
+// The default implementation of MatchAndExplain() for polymorphic
+// matchers.
+template <typename PolymorphicMatcherImpl, typename T>
+inline bool MatchAndExplain(const PolymorphicMatcherImpl& impl,
+ const T& x,
+ MatchResultListener* listener) {
+ const bool match = impl.Matches(x);
+
+ ::std::ostream* const os = listener->stream();
+ if (os != NULL) {
+ using ::testing::internal::ExplainMatchResultTo;
+ // When resolving the following call, both
+ // ::testing::internal::ExplainMatchResultTo() and
+ // foo::ExplainMatchResultTo() are considered, where foo is the
+ // namespace where class PolymorphicMatcherImpl is defined.
+ ExplainMatchResultTo(impl, x, os);
+ }
+
+ return match;
+}
+
} // namespace internal
// A Matcher<T> is a copyable and IMMUTABLE (except by assignment)
@@ -220,19 +349,31 @@ class Matcher<internal::string>
// polymorphic matcher (i.e. a matcher that can match values of more
// than one type, e.g. Eq(n) and NotNull()).
//
-// To define a polymorphic matcher, a user first provides a Impl class
-// that has a Matches() method, a DescribeTo() method, and a
-// DescribeNegationTo() method. The Matches() method is usually a
-// method template (such that it works with multiple types). Then the
-// user creates the polymorphic matcher using
-// MakePolymorphicMatcher(). To provide additional explanation to the
-// match result, define a FREE function (or function template)
+// To define a polymorphic matcher in the old, deprecated way, a user
+// first provides an Impl class that has a Matches() method, a
+// DescribeTo() method, and a DescribeNegationTo() method. The
+// Matches() method is usually a method template (such that it works
+// with multiple types). Then the user creates the polymorphic
+// matcher using MakePolymorphicMatcher(). To provide additional
+// explanation to the match result, define a FREE function (or
+// function template)
//
// void ExplainMatchResultTo(const Impl& matcher, const Value& value,
// ::std::ostream* os);
//
-// in the SAME NAME SPACE where Impl is defined. See the definition
-// of NotNull() for a complete example.
+// in the SAME NAME SPACE where Impl is defined.
+//
+// The new, recommended way to define a polymorphic matcher is to
+// provide an Impl class that has a DescribeTo() method and a
+// DescribeNegationTo() method, and define a FREE function (or
+// function template)
+//
+// bool MatchAndExplain(const Impl& matcher, const Value& value,
+// MatchResultListener* listener);
+//
+// in the SAME NAME SPACE where Impl is defined.
+//
+// See the definition of NotNull() for a complete example.
template <class Impl>
class PolymorphicMatcher {
public:
@@ -257,8 +398,6 @@ class PolymorphicMatcher {
public:
explicit MonomorphicImpl(const Impl& impl) : impl_(impl) {}
- virtual bool Matches(T x) const { return impl_.Matches(x); }
-
virtual void DescribeTo(::std::ostream* os) const {
impl_.DescribeTo(os);
}
@@ -267,22 +406,15 @@ class PolymorphicMatcher {
impl_.DescribeNegationTo(os);
}
- virtual void ExplainMatchResultTo(T x, ::std::ostream* os) const {
- using ::testing::internal::ExplainMatchResultTo;
-
+ virtual bool MatchAndExplain(T x, MatchResultListener* listener) const {
// C++ uses Argument-Dependent Look-up (aka Koenig Look-up) to
- // resolve the call to ExplainMatchResultTo() here. This
- // means that if there's a ExplainMatchResultTo() function
- // defined in the name space where class Impl is defined, it
- // will be picked by the compiler as the better match.
- // Otherwise the default implementation of it in
- // ::testing::internal will be picked.
- //
- // This look-up rule lets a writer of a polymorphic matcher
- // customize the behavior of ExplainMatchResultTo() when he
- // cares to. Nothing needs to be done by the writer if he
- // doesn't need to customize it.
- ExplainMatchResultTo(impl_, x, os);
+ // resolve the call to MatchAndExplain() here. This means that
+ // if there's a MatchAndExplain() function defined in the name
+ // space where class Impl is defined, it will be picked by the
+ // compiler as the better match. Otherwise the default
+ // implementation of it in ::testing::internal will be picked.
+ using ::testing::internal::MatchAndExplain;
+ return MatchAndExplain(impl_, x, listener);
}
private:
@@ -390,16 +522,12 @@ Matcher<T> A();
// and MUST NOT BE USED IN USER CODE!!!
namespace internal {
-// Appends the explanation on the result of matcher.Matches(value) to
-// os iff the explanation is not empty.
-template <typename T>
-void ExplainMatchResultAsNeededTo(const Matcher<T>& matcher, T value,
- ::std::ostream* os) {
- ::std::stringstream reason;
- matcher.ExplainMatchResultTo(value, &reason);
- const internal::string s = reason.str();
- if (s != "") {
- *os << " (" << s << ")";
+// If the given string is not empty and os is not NULL, wraps the
+// string inside a pair of parentheses and streams the result to os.
+inline void StreamInParensAsNeeded(const internal::string& str,
+ ::std::ostream* os) {
+ if (!str.empty() && os != NULL) {
+ *os << " (" << str << ")";
}
}
@@ -439,7 +567,8 @@ class TuplePrefix {
get<N - 1>(matchers);
typedef typename tuple_element<N - 1, ValueTuple>::type Value;
Value value = get<N - 1>(values);
- if (!matcher.Matches(value)) {
+ StringMatchResultListener listener;
+ if (!matcher.MatchAndExplain(value, &listener)) {
// TODO(wan): include in the message the name of the parameter
// as used in MOCK_METHOD*() when possible.
*os << " Expected arg #" << N - 1 << ": ";
@@ -452,7 +581,8 @@ class TuplePrefix {
// the address is interesting.
internal::UniversalPrinter<GMOCK_REMOVE_REFERENCE_(Value)>::
Print(value, os);
- ExplainMatchResultAsNeededTo<Value>(matcher, value, os);
+
+ StreamInParensAsNeeded(listener.str(), os);
*os << "\n";
}
}
@@ -537,8 +667,8 @@ class MatcherCastImpl<T, Matcher<U> > {
: source_matcher_(source_matcher) {}
// We delegate the matching logic to the source matcher.
- virtual bool Matches(T x) const {
- return source_matcher_.Matches(static_cast<U>(x));
+ virtual bool MatchAndExplain(T x, MatchResultListener* listener) const {
+ return source_matcher_.MatchAndExplain(static_cast<U>(x), listener);
}
virtual void DescribeTo(::std::ostream* os) const {
@@ -549,10 +679,6 @@ class MatcherCastImpl<T, Matcher<U> > {
source_matcher_.DescribeNegationTo(os);
}
- virtual void ExplainMatchResultTo(T x, ::std::ostream* os) const {
- source_matcher_.ExplainMatchResultTo(static_cast<U>(x), os);
- }
-
private:
const Matcher<U> source_matcher_;
@@ -572,7 +698,8 @@ class MatcherCastImpl<T, Matcher<T> > {
template <typename T>
class AnyMatcherImpl : public MatcherInterface<T> {
public:
- virtual bool Matches(T /* x */) const { return true; }
+ virtual bool MatchAndExplain(
+ T /* x */, MatchResultListener* /* listener */) const { return true; }
virtual void DescribeTo(::std::ostream* os) const { *os << "is anything"; }
virtual void DescribeNegationTo(::std::ostream* os) const {
// This is mostly for completeness' safe, as it's not very useful
@@ -618,7 +745,10 @@ class AnythingMatcher {
class Impl : public MatcherInterface<Lhs> { \
public: \
explicit Impl(const Rhs& rhs) : rhs_(rhs) {} \
- virtual bool Matches(Lhs lhs) const { return lhs op rhs_; } \
+ virtual bool MatchAndExplain(\
+ Lhs lhs, MatchResultListener* /* listener */) const { \
+ return lhs op rhs_; \
+ } \
virtual void DescribeTo(::std::ostream* os) const { \
*os << "is " relation " "; \
UniversalPrinter<Rhs>::Print(rhs_, os); \
@@ -719,7 +849,11 @@ class RefMatcher<T&> {
// Matches() takes a Super& (as opposed to const Super&) in
// order to match the interface MatcherInterface<Super&>.
- virtual bool Matches(Super& x) const { return &x == &object_; } // NOLINT
+ virtual bool MatchAndExplain(
+ Super& x, MatchResultListener* listener) const {
+ *listener << "is located @" << static_cast<const void*>(&x);
+ return &x == &object_;
+ }
virtual void DescribeTo(::std::ostream* os) const {
*os << "references the variable ";
@@ -731,11 +865,6 @@ class RefMatcher<T&> {
UniversalPrinter<Super&>::Print(object_, os);
}
- virtual void ExplainMatchResultTo(Super& x, // NOLINT
- ::std::ostream* os) const {
- *os << "is located @" << static_cast<const void*>(&x);
- }
-
private:
const Super& object_;
@@ -1017,7 +1146,9 @@ class MatchesRegexMatcher {
template <typename T1, typename T2> \
class Impl : public MatcherInterface<const ::std::tr1::tuple<T1, T2>&> { \
public: \
- virtual bool Matches(const ::std::tr1::tuple<T1, T2>& args) const { \
+ virtual bool MatchAndExplain( \
+ const ::std::tr1::tuple<T1, T2>& args, \
+ MatchResultListener* /* listener */) const { \
return ::std::tr1::get<0>(args) op ::std::tr1::get<1>(args); \
} \
virtual void DescribeTo(::std::ostream* os) const { \
@@ -1049,8 +1180,8 @@ class NotMatcherImpl : public MatcherInterface<T> {
explicit NotMatcherImpl(const Matcher<T>& matcher)
: matcher_(matcher) {}
- virtual bool Matches(T x) const {
- return !matcher_.Matches(x);
+ virtual bool MatchAndExplain(T x, MatchResultListener* listener) const {
+ return !matcher_.MatchAndExplain(x, listener);
}
virtual void DescribeTo(::std::ostream* os) const {
@@ -1061,10 +1192,6 @@ class NotMatcherImpl : public MatcherInterface<T> {
matcher_.DescribeTo(os);
}
- virtual void ExplainMatchResultTo(T x, ::std::ostream* os) const {
- matcher_.ExplainMatchResultTo(x, os);
- }
-
private:
const Matcher<T> matcher_;
@@ -1101,10 +1228,6 @@ class BothOfMatcherImpl : public MatcherInterface<T> {
BothOfMatcherImpl(const Matcher<T>& matcher1, const Matcher<T>& matcher2)
: matcher1_(matcher1), matcher2_(matcher2) {}
- virtual bool Matches(T x) const {
- return matcher1_.Matches(x) && matcher2_.Matches(x);
- }
-
virtual void DescribeTo(::std::ostream* os) const {
*os << "(";
matcher1_.DescribeTo(os);
@@ -1118,35 +1241,34 @@ class BothOfMatcherImpl : public MatcherInterface<T> {
DescribeTo(os);
}
- virtual void ExplainMatchResultTo(T x, ::std::ostream* os) const {
- if (Matches(x)) {
- // When both matcher1_ and matcher2_ match x, we need to
- // explain why *both* of them match.
- ::std::stringstream ss1;
- matcher1_.ExplainMatchResultTo(x, &ss1);
- const internal::string s1 = ss1.str();
+ virtual bool MatchAndExplain(T x, MatchResultListener* listener) const {
+ // If either matcher1_ or matcher2_ doesn't match x, we only need
+ // to explain why one of them fails.
+ StringMatchResultListener listener1;
+ if (!matcher1_.MatchAndExplain(x, &listener1)) {
+ *listener << listener1.str();
+ return false;
+ }
+
+ StringMatchResultListener listener2;
+ if (!matcher2_.MatchAndExplain(x, &listener2)) {
+ *listener << listener2.str();
+ return false;
+ }
- ::std::stringstream ss2;
- matcher2_.ExplainMatchResultTo(x, &ss2);
- const internal::string s2 = ss2.str();
+ // Otherwise we need to explain why *both* of them match.
+ const internal::string s1 = listener1.str();
+ const internal::string s2 = listener2.str();
- if (s1 == "") {
- *os << s2;
- } else {
- *os << s1;
- if (s2 != "") {
- *os << "; " << s2;
- }
- }
+ if (s1 == "") {
+ *listener << s2;
} else {
- // Otherwise we only need to explain why *one* of them fails
- // to match.
- if (!matcher1_.Matches(x)) {
- matcher1_.ExplainMatchResultTo(x, os);
- } else {
- matcher2_.ExplainMatchResultTo(x, os);
+ *listener << s1;
+ if (s2 != "") {
+ *listener << "; " << s2;
}
}
+ return true;
}
private:
@@ -1190,10 +1312,6 @@ class EitherOfMatcherImpl : public MatcherInterface<T> {
EitherOfMatcherImpl(const Matcher<T>& matcher1, const Matcher<T>& matcher2)
: matcher1_(matcher1), matcher2_(matcher2) {}
- virtual bool Matches(T x) const {
- return matcher1_.Matches(x) || matcher2_.Matches(x);
- }
-
virtual void DescribeTo(::std::ostream* os) const {
*os << "(";
matcher1_.DescribeTo(os);
@@ -1207,34 +1325,34 @@ class EitherOfMatcherImpl : public MatcherInterface<T> {
DescribeTo(os);
}
- virtual void ExplainMatchResultTo(T x, ::std::ostream* os) const {
- if (Matches(x)) {
- // If either matcher1_ or matcher2_ matches x, we just need
- // to explain why *one* of them matches.
- if (matcher1_.Matches(x)) {
- matcher1_.ExplainMatchResultTo(x, os);
- } else {
- matcher2_.ExplainMatchResultTo(x, os);
- }
- } else {
- // Otherwise we need to explain why *neither* matches.
- ::std::stringstream ss1;
- matcher1_.ExplainMatchResultTo(x, &ss1);
- const internal::string s1 = ss1.str();
+ virtual bool MatchAndExplain(T x, MatchResultListener* listener) const {
+ // If either matcher1_ or matcher2_ matches x, we just need to
+ // explain why *one* of them matches.
+ StringMatchResultListener listener1;
+ if (matcher1_.MatchAndExplain(x, &listener1)) {
+ *listener << listener1.str();
+ return true;
+ }
- ::std::stringstream ss2;
- matcher2_.ExplainMatchResultTo(x, &ss2);
- const internal::string s2 = ss2.str();
+ StringMatchResultListener listener2;
+ if (matcher2_.MatchAndExplain(x, &listener2)) {
+ *listener << listener2.str();
+ return true;
+ }
- if (s1 == "") {
- *os << s2;
- } else {
- *os << s1;
- if (s2 != "") {
- *os << "; " << s2;
- }
+ // Otherwise we need to explain why *both* of them fail.
+ const internal::string s1 = listener1.str();
+ const internal::string s2 = listener2.str();
+
+ if (s1 == "") {
+ *listener << s2;
+ } else {
+ *listener << s1;
+ if (s2 != "") {
+ *listener << "; " << s2;
}
}
+ return false;
}
private:
@@ -1367,7 +1485,8 @@ class PredicateFormatterFromMatcher {
// Matcher<const T&>(matcher_), as the latter won't compile when
// matcher_ has type Matcher<T> (e.g. An<int>()).
const Matcher<const T&> matcher = MatcherCast<const T&>(matcher_);
- if (matcher.Matches(x)) {
+ StringMatchResultListener listener;
+ if (matcher.MatchAndExplain(x, &listener)) {
return AssertionSuccess();
} else {
::std::stringstream ss;
@@ -1376,7 +1495,7 @@ class PredicateFormatterFromMatcher {
matcher.DescribeTo(&ss);
ss << "\n Actual: ";
UniversalPrinter<T>::Print(x, &ss);
- ExplainMatchResultAsNeededTo<const T&>(matcher, x, &ss);
+ StreamInParensAsNeeded(listener.str(), &ss);
return AssertionFailure(Message() << ss.str());
}
}
@@ -1417,7 +1536,8 @@ class FloatingEqMatcher {
Impl(FloatType rhs, bool nan_eq_nan) :
rhs_(rhs), nan_eq_nan_(nan_eq_nan) {}
- virtual bool Matches(T value) const {
+ virtual bool MatchAndExplain(T value,
+ MatchResultListener* /* listener */) const {
const FloatingPoint<FloatType> lhs(value), rhs(rhs_);
// Compares NaNs first, if nan_eq_nan_ is true.
@@ -1525,10 +1645,6 @@ class PointeeMatcher {
explicit Impl(const InnerMatcher& matcher)
: matcher_(MatcherCast<const Pointee&>(matcher)) {}
- virtual bool Matches(Pointer p) const {
- return GetRawPointer(p) != NULL && matcher_.Matches(*p);
- }
-
virtual void DescribeTo(::std::ostream* os) const {
*os << "points to a value that ";
matcher_.DescribeTo(os);
@@ -1539,17 +1655,18 @@ class PointeeMatcher {
matcher_.DescribeTo(os);
}
- virtual void ExplainMatchResultTo(Pointer pointer,
- ::std::ostream* os) const {
+ virtual bool MatchAndExplain(Pointer pointer,
+ MatchResultListener* listener) const {
if (GetRawPointer(pointer) == NULL)
- return;
+ return false;
- ::std::stringstream ss;
- matcher_.ExplainMatchResultTo(*pointer, &ss);
- const internal::string s = ss.str();
+ StringMatchResultListener inner_listener;
+ const bool match = matcher_.MatchAndExplain(*pointer, &inner_listener);
+ const internal::string s = inner_listener.str();
if (s != "") {
- *os << "points to a value that " << s;
+ *listener << "points to a value that " << s;
}
+ return match;
}
private:
@@ -1572,16 +1689,6 @@ class FieldMatcher {
const Matcher<const FieldType&>& matcher)
: field_(field), matcher_(matcher) {}
- // Returns true iff the inner matcher matches obj.field.
- bool Matches(const Class& obj) const {
- return matcher_.Matches(obj.*field_);
- }
-
- // Returns true iff the inner matcher matches obj->field.
- bool Matches(const Class* p) const {
- return (p != NULL) && matcher_.Matches(p->*field_);
- }
-
void DescribeTo(::std::ostream* os) const {
*os << "the given field ";
matcher_.DescribeTo(os);
@@ -1592,27 +1699,29 @@ class FieldMatcher {
matcher_.DescribeNegationTo(os);
}
- // The first argument of ExplainMatchResultTo() is needed to help
+ // The first argument of MatchAndExplain() is needed to help
// Symbian's C++ compiler choose which overload to use. Its type is
// true_type iff the Field() matcher is used to match a pointer.
- void ExplainMatchResultTo(false_type /* is_not_pointer */, const Class& obj,
- ::std::ostream* os) const {
- ::std::stringstream ss;
- matcher_.ExplainMatchResultTo(obj.*field_, &ss);
- const internal::string s = ss.str();
+ bool MatchAndExplain(false_type /* is_not_pointer */, const Class& obj,
+ MatchResultListener* listener) const {
+ StringMatchResultListener inner_listener;
+ const bool match = matcher_.MatchAndExplain(obj.*field_, &inner_listener);
+ const internal::string s = inner_listener.str();
if (s != "") {
- *os << "the given field " << s;
+ *listener << "the given field " << s;
}
+ return match;
}
- void ExplainMatchResultTo(true_type /* is_pointer */, const Class* p,
- ::std::ostream* os) const {
- if (p != NULL) {
- // Since *p has a field, it must be a class/struct/union type
- // and thus cannot be a pointer. Therefore we pass false_type()
- // as the first argument.
- ExplainMatchResultTo(false_type(), *p, os);
- }
+ bool MatchAndExplain(true_type /* is_pointer */, const Class* p,
+ MatchResultListener* listener) const {
+ if (p == NULL)
+ return false;
+
+ // Since *p has a field, it must be a class/struct/union type and
+ // thus cannot be a pointer. Therefore we pass false_type() as
+ // the first argument.
+ return MatchAndExplain(false_type(), *p, listener);
}
private:
@@ -1622,12 +1731,11 @@ class FieldMatcher {
GTEST_DISALLOW_ASSIGN_(FieldMatcher);
};
-// Explains the result of matching an object or pointer against a field matcher.
template <typename Class, typename FieldType, typename T>
-void ExplainMatchResultTo(const FieldMatcher<Class, FieldType>& matcher,
- const T& value, ::std::ostream* os) {
- matcher.ExplainMatchResultTo(
- typename ::testing::internal::is_pointer<T>::type(), value, os);
+bool MatchAndExplain(const FieldMatcher<Class, FieldType>& matcher,
+ const T& value, MatchResultListener* listener) {
+ return matcher.MatchAndExplain(
+ typename ::testing::internal::is_pointer<T>::type(), value, listener);
}
// Implements the Property() matcher for matching a property
@@ -1645,16 +1753,6 @@ class PropertyMatcher {
const Matcher<RefToConstProperty>& matcher)
: property_(property), matcher_(matcher) {}
- // Returns true iff obj.property() matches the inner matcher.
- bool Matches(const Class& obj) const {
- return matcher_.Matches((obj.*property_)());
- }
-
- // Returns true iff p->property() matches the inner matcher.
- bool Matches(const Class* p) const {
- return (p != NULL) && matcher_.Matches((p->*property_)());
- }
-
void DescribeTo(::std::ostream* os) const {
*os << "the given property ";
matcher_.DescribeTo(os);
@@ -1665,27 +1763,30 @@ class PropertyMatcher {
matcher_.DescribeNegationTo(os);
}
- // The first argument of ExplainMatchResultTo() is needed to help
+ // The first argument of MatchAndExplain() is needed to help
// Symbian's C++ compiler choose which overload to use. Its type is
// true_type iff the Property() matcher is used to match a pointer.
- void ExplainMatchResultTo(false_type /* is_not_pointer */, const Class& obj,
- ::std::ostream* os) const {
- ::std::stringstream ss;
- matcher_.ExplainMatchResultTo((obj.*property_)(), &ss);
- const internal::string s = ss.str();
+ bool MatchAndExplain(false_type /* is_not_pointer */, const Class& obj,
+ MatchResultListener* listener) const {
+ StringMatchResultListener inner_listener;
+ const bool match = matcher_.MatchAndExplain((obj.*property_)(),
+ &inner_listener);
+ const internal::string s = inner_listener.str();
if (s != "") {
- *os << "the given property " << s;
+ *listener << "the given property " << s;
}
+ return match;
}
- void ExplainMatchResultTo(true_type /* is_pointer */, const Class* p,
- ::std::ostream* os) const {
- if (p != NULL) {
- // Since *p has a property method, it must be a
- // class/struct/union type and thus cannot be a pointer.
- // Therefore we pass false_type() as the first argument.
- ExplainMatchResultTo(false_type(), *p, os);
- }
+ bool MatchAndExplain(true_type /* is_pointer */, const Class* p,
+ MatchResultListener* listener) const {
+ if (p == NULL)
+ return false;
+
+ // Since *p has a property method, it must be a class/struct/union
+ // type and thus cannot be a pointer. Therefore we pass
+ // false_type() as the first argument.
+ return MatchAndExplain(false_type(), *p, listener);
}
private:
@@ -1695,13 +1796,11 @@ class PropertyMatcher {
GTEST_DISALLOW_ASSIGN_(PropertyMatcher);
};
-// Explains the result of matching an object or pointer against a
-// property matcher.
-template <typename Class, typename PropertyType, typename T>
-void ExplainMatchResultTo(const PropertyMatcher<Class, PropertyType>& matcher,
- const T& value, ::std::ostream* os) {
- matcher.ExplainMatchResultTo(
- typename ::testing::internal::is_pointer<T>::type(), value, os);
+template <typename Class, typename PropertyType, typename T>
+bool MatchAndExplain(const PropertyMatcher<Class, PropertyType>& matcher,
+ const T& value, MatchResultListener* listener) {
+ return matcher.MatchAndExplain(
+ typename ::testing::internal::is_pointer<T>::type(), value, listener);
}
// Type traits specifying various features of different functors for ResultOf.
@@ -1759,13 +1858,6 @@ class ResultOfMatcher {
public:
Impl(CallableStorageType callable, const Matcher<ResultType>& matcher)
: callable_(callable), matcher_(matcher) {}
- // Returns true iff callable_(obj) matches the inner matcher.
- // The calling syntax is different for different types of callables
- // so we abstract it in CallableTraits<Callable>::Invoke().
- virtual bool Matches(T obj) const {
- return matcher_.Matches(
- CallableTraits<Callable>::template Invoke<T>(callable_, obj));
- }
virtual void DescribeTo(::std::ostream* os) const {
*os << "result of the given callable ";
@@ -1777,14 +1869,17 @@ class ResultOfMatcher {
matcher_.DescribeNegationTo(os);
}
- virtual void ExplainMatchResultTo(T obj, ::std::ostream* os) const {
- ::std::stringstream ss;
- matcher_.ExplainMatchResultTo(
+ virtual bool MatchAndExplain(T obj, MatchResultListener* listener) const {
+ StringMatchResultListener inner_listener;
+ const bool match = matcher_.MatchAndExplain(
CallableTraits<Callable>::template Invoke<T>(callable_, obj),
- &ss);
- const internal::string s = ss.str();
+ &inner_listener);
+
+ const internal::string s = inner_listener.str();
if (s != "")
- *os << "result of the given callable " << s;
+ *listener << "result of the given callable " << s;
+
+ return match;
}
private:
@@ -1929,17 +2024,6 @@ class ContainsMatcherImpl : public MatcherInterface<Container> {
: inner_matcher_(
testing::SafeMatcherCast<const Element&>(inner_matcher)) {}
- // Returns true iff 'container' matches.
- virtual bool Matches(Container container) const {
- StlContainerReference stl_container = View::ConstReference(container);
- for (typename StlContainer::const_iterator it = stl_container.begin();
- it != stl_container.end(); ++it) {
- if (inner_matcher_.Matches(*it))
- return true;
- }
- return false;
- }
-
// Describes what this matcher does.
virtual void DescribeTo(::std::ostream* os) const {
*os << "contains at least one element that ";
@@ -1952,19 +2036,18 @@ class ContainsMatcherImpl : public MatcherInterface<Container> {
inner_matcher_.DescribeTo(os);
}
- // Explains why 'container' matches, or doesn't match, this matcher.
- virtual void ExplainMatchResultTo(Container container,
- ::std::ostream* os) const {
+ virtual bool MatchAndExplain(Container container,
+ MatchResultListener* listener) const {
StlContainerReference stl_container = View::ConstReference(container);
-
- // We need to explain which (if any) element matches inner_matcher_.
- typename StlContainer::const_iterator it = stl_container.begin();
- for (size_t i = 0; it != stl_container.end(); ++it, ++i) {
+ size_t i = 0;
+ for (typename StlContainer::const_iterator it = stl_container.begin();
+ it != stl_container.end(); ++it, ++i) {
if (inner_matcher_.Matches(*it)) {
- *os << "element " << i << " matches";
- return;
+ *listener << "element " << i << " matches";
+ return true;
}
}
+ return false;
}
private:
@@ -2007,8 +2090,9 @@ class KeyMatcherImpl : public MatcherInterface<PairType> {
}
// Returns true iff 'key_value.first' (the key) matches the inner matcher.
- virtual bool Matches(PairType key_value) const {
- return inner_matcher_.Matches(key_value.first);
+ virtual bool MatchAndExplain(PairType key_value,
+ MatchResultListener* listener) const {
+ return inner_matcher_.MatchAndExplain(key_value.first, listener);
}
// Describes what this matcher does.
@@ -2023,12 +2107,6 @@ class KeyMatcherImpl : public MatcherInterface<PairType> {
inner_matcher_.DescribeTo(os);
}
- // Explains why 'key_value' matches, or doesn't match, this matcher.
- virtual void ExplainMatchResultTo(PairType key_value,
- ::std::ostream* os) const {
- inner_matcher_.ExplainMatchResultTo(key_value.first, os);
- }
-
private:
const Matcher<const KeyType&> inner_matcher_;
@@ -2069,13 +2147,6 @@ class PairMatcherImpl : public MatcherInterface<PairType> {
testing::SafeMatcherCast<const SecondType&>(second_matcher)) {
}
- // Returns true iff 'a_pair.first' matches first_matcher and 'a_pair.second'
- // matches second_matcher.
- virtual bool Matches(PairType a_pair) const {
- return first_matcher_.Matches(a_pair.first) &&
- second_matcher_.Matches(a_pair.second);
- }
-
// Describes what this matcher does.
virtual void DescribeTo(::std::ostream* os) const {
*os << "has a first field that ";
@@ -2092,28 +2163,40 @@ class PairMatcherImpl : public MatcherInterface<PairType> {
second_matcher_.DescribeNegationTo(os);
}
- // Explains why 'a_pair' matches, or doesn't match, this matcher.
- virtual void ExplainMatchResultTo(PairType a_pair,
- ::std::ostream* os) const {
- ::std::stringstream ss1;
- first_matcher_.ExplainMatchResultTo(a_pair.first, &ss1);
- internal::string s1 = ss1.str();
+ // Returns true iff 'a_pair.first' matches first_matcher and 'a_pair.second'
+ // matches second_matcher.
+ virtual bool MatchAndExplain(PairType a_pair,
+ MatchResultListener* listener) const {
+ StringMatchResultListener listener1;
+ const bool match1 = first_matcher_.MatchAndExplain(a_pair.first,
+ &listener1);
+ internal::string s1 = listener1.str();
if (s1 != "") {
- s1 = "the first field " + s1;
+ s1 = "the first field " + s1;
+ }
+ if (!match1) {
+ *listener << s1;
+ return false;
}
- ::std::stringstream ss2;
- second_matcher_.ExplainMatchResultTo(a_pair.second, &ss2);
- internal::string s2 = ss2.str();
+ StringMatchResultListener listener2;
+ const bool match2 = second_matcher_.MatchAndExplain(a_pair.second,
+ &listener2);
+ internal::string s2 = listener2.str();
if (s2 != "") {
- s2 = "the second field " + s2;
+ s2 = "the second field " + s2;
+ }
+ if (!match2) {
+ *listener << s2;
+ return false;
}
- *os << s1;
+ *listener << s1;
if (s1 != "" && s2 != "") {
- *os << ", and ";
+ *listener << ", and ";
}
- *os << s2;
+ *listener << s2;
+ return true;
}
private:
@@ -2165,21 +2248,6 @@ class ElementsAreMatcherImpl : public MatcherInterface<Container> {
}
}
- // Returns true iff 'container' matches.
- virtual bool Matches(Container container) const {
- StlContainerReference stl_container = View::ConstReference(container);
- if (stl_container.size() != count())
- return false;
-
- typename StlContainer::const_iterator it = stl_container.begin();
- for (size_t i = 0; i != count(); ++it, ++i) {
- if (!matchers_[i].Matches(*it))
- return false;
- }
-
- return true;
- }
-
// Describes what this matcher does.
virtual void DescribeTo(::std::ostream* os) const {
if (count() == 0) {
@@ -2216,63 +2284,54 @@ class ElementsAreMatcherImpl : public MatcherInterface<Container> {
}
}
- // Explains why 'container' matches, or doesn't match, this matcher.
- virtual void ExplainMatchResultTo(Container container,
- ::std::ostream* os) const {
+ virtual bool MatchAndExplain(Container container,
+ MatchResultListener* listener) const {
StlContainerReference stl_container = View::ConstReference(container);
- if (Matches(container)) {
- // We need to explain why *each* element matches (the obvious
- // ones can be skipped).
-
- bool reason_printed = false;
- typename StlContainer::const_iterator it = stl_container.begin();
- for (size_t i = 0; i != count(); ++it, ++i) {
- ::std::stringstream ss;
- matchers_[i].ExplainMatchResultTo(*it, &ss);
-
- const string s = ss.str();
- if (!s.empty()) {
- if (reason_printed) {
- *os << ",\n";
- }
- *os << "element " << i << " " << s;
- reason_printed = true;
- }
- }
- } else {
- // We need to explain why the container doesn't match.
- const size_t actual_count = stl_container.size();
- if (actual_count != count()) {
- // The element count doesn't match. If the container is
- // empty, there's no need to explain anything as Google Mock
- // already prints the empty container. Otherwise we just need
- // to show how many elements there actually are.
- if (actual_count != 0) {
- *os << "has " << Elements(actual_count);
- }
- return;
+ const size_t actual_count = stl_container.size();
+ if (actual_count != count()) {
+ // The element count doesn't match. If the container is empty,
+ // there's no need to explain anything as Google Mock already
+ // prints the empty container. Otherwise we just need to show
+ // how many elements there actually are.
+ if (actual_count != 0) {
+ *listener << "has " << Elements(actual_count);
}
+ return false;
+ }
- // The container has the right size but at least one element
- // doesn't match expectation. We need to find this element and
- // explain why it doesn't match.
- typename StlContainer::const_iterator it = stl_container.begin();
- for (size_t i = 0; i != count(); ++it, ++i) {
- if (matchers_[i].Matches(*it)) {
- continue;
- }
+ typename StlContainer::const_iterator it = stl_container.begin();
+ // explanations[i] is the explanation of the element at index i.
+ std::vector<internal::string> explanations(count());
+ for (size_t i = 0; i != count(); ++it, ++i) {
+ StringMatchResultListener s;
+ if (matchers_[i].MatchAndExplain(*it, &s)) {
+ explanations[i] = s.str();
+ } else {
+ // The container has the right size but the i-th element
+ // doesn't match its expectation.
+ *listener << "element " << i << " doesn't match";
+
+ StreamInParensAsNeeded(s.str(), listener->stream());
+ return false;
+ }
+ }
- *os << "element " << i << " doesn't match";
+ // Every element matches its expectation. We need to explain why
+ // (the obvious ones can be skipped).
- ::std::stringstream ss;
- matchers_[i].ExplainMatchResultTo(*it, &ss);
- const string s = ss.str();
- if (!s.empty()) {
- *os << " (" << s << ")";
+ bool reason_printed = false;
+ for (size_t i = 0; i != count(); ++i) {
+ const internal::string& s = explanations[i];
+ if (!s.empty()) {
+ if (reason_printed) {
+ *listener << ",\n";
}
- return;
+ *listener << "element " << i << " " << s;
+ reason_printed = true;
}
}
+
+ return true;
}
private:
@@ -2811,13 +2870,14 @@ Truly(Predicate pred) {
// values that are included in one container but not the other. (Duplicate
// values and order differences are not explained.)
template <typename Container>
-inline PolymorphicMatcher<internal::ContainerEqMatcher<
+inline PolymorphicMatcher<internal::ContainerEqMatcher< // NOLINT
GMOCK_REMOVE_CONST_(Container)> >
ContainerEq(const Container& rhs) {
// This following line is for working around a bug in MSVC 8.0,
// which causes Container to be a const type sometimes.
typedef GMOCK_REMOVE_CONST_(Container) RawContainer;
- return MakePolymorphicMatcher(internal::ContainerEqMatcher<RawContainer>(rhs));
+ return MakePolymorphicMatcher(
+ internal::ContainerEqMatcher<RawContainer>(rhs));
}
// Matches an STL-style container or a native array that contains at