Adds IsInterested() to MatchResultListener; clarifies the format of matcher description and match result explanation; renames the free function MatchAndExplain() to ExplainMatchResult() to avoid it being hidden inside a MATCHER* definition.
This commit is contained in:
parent
34b034c21e
commit
a862f1de30
@ -90,6 +90,12 @@ class MatchResultListener {
|
|||||||
// Returns the underlying ostream.
|
// Returns the underlying ostream.
|
||||||
::std::ostream* stream() { return stream_; }
|
::std::ostream* stream() { return stream_; }
|
||||||
|
|
||||||
|
// Returns true iff the listener is interested in an explanation of
|
||||||
|
// the match result. A matcher's MatchAndExplain() method can use
|
||||||
|
// this information to avoid generating the explanation when no one
|
||||||
|
// intends to hear it.
|
||||||
|
bool IsInterested() const { return stream_ != NULL; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
::std::ostream* const stream_;
|
::std::ostream* const stream_;
|
||||||
|
|
||||||
@ -106,7 +112,10 @@ class MatcherInterface {
|
|||||||
virtual ~MatcherInterface() {}
|
virtual ~MatcherInterface() {}
|
||||||
|
|
||||||
// Returns true iff the matcher matches x; also explains the match
|
// Returns true iff the matcher matches x; also explains the match
|
||||||
// result to 'listener'.
|
// result to 'listener', in the form of a non-restrictive relative
|
||||||
|
// clause ("which ...", "whose ...", etc) that describes x. For
|
||||||
|
// example, the MatchAndExplain() method of the Pointee(...) matcher
|
||||||
|
// should generate an explanation like "which points to ...".
|
||||||
//
|
//
|
||||||
// You should override this method when defining a new matcher.
|
// You should override this method when defining a new matcher.
|
||||||
//
|
//
|
||||||
@ -118,7 +127,11 @@ class MatcherInterface {
|
|||||||
// listener->stream() may be NULL.
|
// listener->stream() may be NULL.
|
||||||
virtual bool MatchAndExplain(T x, MatchResultListener* listener) const = 0;
|
virtual bool MatchAndExplain(T x, MatchResultListener* listener) const = 0;
|
||||||
|
|
||||||
// Describes this matcher to an ostream.
|
// Describes this matcher to an ostream. The function should print
|
||||||
|
// a verb phrase that describes the property a value matching this
|
||||||
|
// matcher should have. The subject of the verb phrase is the value
|
||||||
|
// being matched. For example, the DescribeTo() method of the Gt(7)
|
||||||
|
// matcher prints "is greater than 7".
|
||||||
virtual void DescribeTo(::std::ostream* os) const = 0;
|
virtual void DescribeTo(::std::ostream* os) const = 0;
|
||||||
|
|
||||||
// Describes the negation of this matcher to an ostream. For
|
// Describes the negation of this matcher to an ostream. For
|
||||||
@ -2853,7 +2866,7 @@ inline bool Value(const T& value, M matcher) {
|
|||||||
// Matches the value against the given matcher and explains the match
|
// Matches the value against the given matcher and explains the match
|
||||||
// result to listener.
|
// result to listener.
|
||||||
template <typename T, typename M>
|
template <typename T, typename M>
|
||||||
inline bool MatchAndExplain(
|
inline bool ExplainMatchResult(
|
||||||
M matcher, const T& value, MatchResultListener* listener) {
|
M matcher, const T& value, MatchResultListener* listener) {
|
||||||
return SafeMatcherCast<const T&>(matcher).MatchAndExplain(value, listener);
|
return SafeMatcherCast<const T&>(matcher).MatchAndExplain(value, listener);
|
||||||
}
|
}
|
||||||
|
@ -37,6 +37,7 @@
|
|||||||
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <functional>
|
#include <functional>
|
||||||
|
#include <iostream>
|
||||||
#include <list>
|
#include <list>
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <set>
|
#include <set>
|
||||||
@ -88,7 +89,7 @@ using testing::Matcher;
|
|||||||
using testing::MatcherCast;
|
using testing::MatcherCast;
|
||||||
using testing::MatcherInterface;
|
using testing::MatcherInterface;
|
||||||
using testing::Matches;
|
using testing::Matches;
|
||||||
using testing::MatchAndExplain;
|
using testing::ExplainMatchResult;
|
||||||
using testing::MatchResultListener;
|
using testing::MatchResultListener;
|
||||||
using testing::NanSensitiveDoubleEq;
|
using testing::NanSensitiveDoubleEq;
|
||||||
using testing::NanSensitiveFloatEq;
|
using testing::NanSensitiveFloatEq;
|
||||||
@ -110,6 +111,7 @@ using testing::Truly;
|
|||||||
using testing::TypedEq;
|
using testing::TypedEq;
|
||||||
using testing::Value;
|
using testing::Value;
|
||||||
using testing::_;
|
using testing::_;
|
||||||
|
using testing::internal::DummyMatchResultListener;
|
||||||
using testing::internal::FloatingEqMatcher;
|
using testing::internal::FloatingEqMatcher;
|
||||||
using testing::internal::FormatMatcherDescriptionSyntaxError;
|
using testing::internal::FormatMatcherDescriptionSyntaxError;
|
||||||
using testing::internal::GetParamIndex;
|
using testing::internal::GetParamIndex;
|
||||||
@ -117,6 +119,7 @@ using testing::internal::Interpolation;
|
|||||||
using testing::internal::Interpolations;
|
using testing::internal::Interpolations;
|
||||||
using testing::internal::JoinAsTuple;
|
using testing::internal::JoinAsTuple;
|
||||||
using testing::internal::SkipPrefix;
|
using testing::internal::SkipPrefix;
|
||||||
|
using testing::internal::StreamMatchResultListener;
|
||||||
using testing::internal::String;
|
using testing::internal::String;
|
||||||
using testing::internal::Strings;
|
using testing::internal::Strings;
|
||||||
using testing::internal::StringMatchResultListener;
|
using testing::internal::StringMatchResultListener;
|
||||||
@ -187,6 +190,31 @@ string Explain(const MatcherType& m, const Value& x) {
|
|||||||
return ss.str();
|
return ss.str();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST(MatchResultListenerTest, StreamingWorks) {
|
||||||
|
StringMatchResultListener listener;
|
||||||
|
listener << "hi" << 5;
|
||||||
|
EXPECT_EQ("hi5", listener.str());
|
||||||
|
|
||||||
|
// Streaming shouldn't crash when the underlying ostream is NULL.
|
||||||
|
DummyMatchResultListener dummy;
|
||||||
|
dummy << "hi" << 5;
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(MatchResultListenerTest, CanAccessUnderlyingStream) {
|
||||||
|
EXPECT_TRUE(DummyMatchResultListener().stream() == NULL);
|
||||||
|
EXPECT_TRUE(StreamMatchResultListener(NULL).stream() == NULL);
|
||||||
|
|
||||||
|
EXPECT_EQ(&std::cout, StreamMatchResultListener(&std::cout).stream());
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(MatchResultListenerTest, IsInterestedWorks) {
|
||||||
|
EXPECT_TRUE(StringMatchResultListener().IsInterested());
|
||||||
|
EXPECT_TRUE(StreamMatchResultListener(&std::cout).IsInterested());
|
||||||
|
|
||||||
|
EXPECT_FALSE(DummyMatchResultListener().IsInterested());
|
||||||
|
EXPECT_FALSE(StreamMatchResultListener(NULL).IsInterested());
|
||||||
|
}
|
||||||
|
|
||||||
// Makes sure that the MatcherInterface<T> interface doesn't
|
// Makes sure that the MatcherInterface<T> interface doesn't
|
||||||
// change.
|
// change.
|
||||||
class EvenMatcherImpl : public MatcherInterface<int> {
|
class EvenMatcherImpl : public MatcherInterface<int> {
|
||||||
@ -205,7 +233,8 @@ class EvenMatcherImpl : public MatcherInterface<int> {
|
|||||||
// two methods is optional.
|
// two methods is optional.
|
||||||
};
|
};
|
||||||
|
|
||||||
TEST(MatcherInterfaceTest, CanBeImplementedUsingDeprecatedAPI) {
|
// Makes sure that the MatcherInterface API doesn't change.
|
||||||
|
TEST(MatcherInterfaceTest, CanBeImplementedUsingPublishedAPI) {
|
||||||
EvenMatcherImpl m;
|
EvenMatcherImpl m;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2049,28 +2078,36 @@ TEST(ValueTest, WorksWithMonomorphicMatcher) {
|
|||||||
EXPECT_FALSE(Value(1, ref_n));
|
EXPECT_FALSE(Value(1, ref_n));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(MatchAndExplainTest, WorksWithPolymorphicMatcher) {
|
TEST(ExplainMatchResultTest, WorksWithPolymorphicMatcher) {
|
||||||
StringMatchResultListener listener1;
|
StringMatchResultListener listener1;
|
||||||
EXPECT_TRUE(MatchAndExplain(PolymorphicIsEven(), 42, &listener1));
|
EXPECT_TRUE(ExplainMatchResult(PolymorphicIsEven(), 42, &listener1));
|
||||||
EXPECT_EQ("% 2 == 0", listener1.str());
|
EXPECT_EQ("% 2 == 0", listener1.str());
|
||||||
|
|
||||||
StringMatchResultListener listener2;
|
StringMatchResultListener listener2;
|
||||||
EXPECT_FALSE(MatchAndExplain(Ge(42), 1.5, &listener2));
|
EXPECT_FALSE(ExplainMatchResult(Ge(42), 1.5, &listener2));
|
||||||
EXPECT_EQ("", listener2.str());
|
EXPECT_EQ("", listener2.str());
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(MatchAndExplainTest, WorksWithMonomorphicMatcher) {
|
TEST(ExplainMatchResultTest, WorksWithMonomorphicMatcher) {
|
||||||
const Matcher<int> is_even = PolymorphicIsEven();
|
const Matcher<int> is_even = PolymorphicIsEven();
|
||||||
StringMatchResultListener listener1;
|
StringMatchResultListener listener1;
|
||||||
EXPECT_TRUE(MatchAndExplain(is_even, 42, &listener1));
|
EXPECT_TRUE(ExplainMatchResult(is_even, 42, &listener1));
|
||||||
EXPECT_EQ("% 2 == 0", listener1.str());
|
EXPECT_EQ("% 2 == 0", listener1.str());
|
||||||
|
|
||||||
const Matcher<const double&> is_zero = Eq(0);
|
const Matcher<const double&> is_zero = Eq(0);
|
||||||
StringMatchResultListener listener2;
|
StringMatchResultListener listener2;
|
||||||
EXPECT_FALSE(MatchAndExplain(is_zero, 1.5, &listener2));
|
EXPECT_FALSE(ExplainMatchResult(is_zero, 1.5, &listener2));
|
||||||
EXPECT_EQ("", listener2.str());
|
EXPECT_EQ("", listener2.str());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
MATCHER_P(Really, inner_matcher, "") {
|
||||||
|
return ExplainMatchResult(inner_matcher, arg, result_listener);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(ExplainMatchResultTest, WorksInsideMATCHER) {
|
||||||
|
EXPECT_THAT(0, Really(Eq(0)));
|
||||||
|
}
|
||||||
|
|
||||||
TEST(AllArgsTest, WorksForTuple) {
|
TEST(AllArgsTest, WorksForTuple) {
|
||||||
EXPECT_THAT(make_tuple(1, 2L), AllArgs(Lt()));
|
EXPECT_THAT(make_tuple(1, 2L), AllArgs(Lt()));
|
||||||
EXPECT_THAT(make_tuple(2L, 1), Not(AllArgs(Lt())));
|
EXPECT_THAT(make_tuple(2L, 1), Not(AllArgs(Lt())));
|
||||||
|
Loading…
Reference in New Issue
Block a user