From 6794f312a31bd36d59f76b77825eecefc70adfa6 Mon Sep 17 00:00:00 2001 From: "zhanyong.wan" Date: Mon, 15 Mar 2010 21:23:04 +0000 Subject: 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. git-svn-id: http://googlemock.googlecode.com/svn/trunk@276 8415998a-534a-0410-bf83-d39667b30386 --- include/gmock/gmock-matchers.h | 19 ++++++++++++--- test/gmock-matchers_test.cc | 53 +++++++++++++++++++++++++++++++++++------- 2 files changed, 61 insertions(+), 11 deletions(-) diff --git a/include/gmock/gmock-matchers.h b/include/gmock/gmock-matchers.h index 50c0d7b..8dba440 100644 --- a/include/gmock/gmock-matchers.h +++ b/include/gmock/gmock-matchers.h @@ -90,6 +90,12 @@ class MatchResultListener { // Returns the underlying ostream. ::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: ::std::ostream* const stream_; @@ -106,7 +112,10 @@ class MatcherInterface { virtual ~MatcherInterface() {} // 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. // @@ -118,7 +127,11 @@ class MatcherInterface { // listener->stream() may be NULL. 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; // 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 // result to listener. template -inline bool MatchAndExplain( +inline bool ExplainMatchResult( M matcher, const T& value, MatchResultListener* listener) { return SafeMatcherCast(matcher).MatchAndExplain(value, listener); } diff --git a/test/gmock-matchers_test.cc b/test/gmock-matchers_test.cc index 1eaecf9..1ba4c8d 100644 --- a/test/gmock-matchers_test.cc +++ b/test/gmock-matchers_test.cc @@ -37,6 +37,7 @@ #include #include +#include #include #include #include @@ -88,7 +89,7 @@ using testing::Matcher; using testing::MatcherCast; using testing::MatcherInterface; using testing::Matches; -using testing::MatchAndExplain; +using testing::ExplainMatchResult; using testing::MatchResultListener; using testing::NanSensitiveDoubleEq; using testing::NanSensitiveFloatEq; @@ -110,6 +111,7 @@ using testing::Truly; using testing::TypedEq; using testing::Value; using testing::_; +using testing::internal::DummyMatchResultListener; using testing::internal::FloatingEqMatcher; using testing::internal::FormatMatcherDescriptionSyntaxError; using testing::internal::GetParamIndex; @@ -117,6 +119,7 @@ using testing::internal::Interpolation; using testing::internal::Interpolations; using testing::internal::JoinAsTuple; using testing::internal::SkipPrefix; +using testing::internal::StreamMatchResultListener; using testing::internal::String; using testing::internal::Strings; using testing::internal::StringMatchResultListener; @@ -187,6 +190,31 @@ string Explain(const MatcherType& m, const Value& x) { 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 interface doesn't // change. class EvenMatcherImpl : public MatcherInterface { @@ -205,7 +233,8 @@ class EvenMatcherImpl : public MatcherInterface { // two methods is optional. }; -TEST(MatcherInterfaceTest, CanBeImplementedUsingDeprecatedAPI) { +// Makes sure that the MatcherInterface API doesn't change. +TEST(MatcherInterfaceTest, CanBeImplementedUsingPublishedAPI) { EvenMatcherImpl m; } @@ -2049,28 +2078,36 @@ TEST(ValueTest, WorksWithMonomorphicMatcher) { EXPECT_FALSE(Value(1, ref_n)); } -TEST(MatchAndExplainTest, WorksWithPolymorphicMatcher) { +TEST(ExplainMatchResultTest, WorksWithPolymorphicMatcher) { StringMatchResultListener listener1; - EXPECT_TRUE(MatchAndExplain(PolymorphicIsEven(), 42, &listener1)); + EXPECT_TRUE(ExplainMatchResult(PolymorphicIsEven(), 42, &listener1)); EXPECT_EQ("% 2 == 0", listener1.str()); StringMatchResultListener listener2; - EXPECT_FALSE(MatchAndExplain(Ge(42), 1.5, &listener2)); + EXPECT_FALSE(ExplainMatchResult(Ge(42), 1.5, &listener2)); EXPECT_EQ("", listener2.str()); } -TEST(MatchAndExplainTest, WorksWithMonomorphicMatcher) { +TEST(ExplainMatchResultTest, WorksWithMonomorphicMatcher) { const Matcher is_even = PolymorphicIsEven(); StringMatchResultListener listener1; - EXPECT_TRUE(MatchAndExplain(is_even, 42, &listener1)); + EXPECT_TRUE(ExplainMatchResult(is_even, 42, &listener1)); EXPECT_EQ("% 2 == 0", listener1.str()); const Matcher is_zero = Eq(0); StringMatchResultListener listener2; - EXPECT_FALSE(MatchAndExplain(is_zero, 1.5, &listener2)); + EXPECT_FALSE(ExplainMatchResult(is_zero, 1.5, &listener2)); 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) { EXPECT_THAT(make_tuple(1, 2L), AllArgs(Lt())); EXPECT_THAT(make_tuple(2L, 1), Not(AllArgs(Lt()))); -- cgit v1.2.1