From e122e457a6e890faac399c1f86d87cc8d3177ac2 Mon Sep 17 00:00:00 2001 From: "zhanyong.wan" Date: Tue, 12 Jan 2010 09:03:52 +0000 Subject: [PATCH] Converts more matchers to the new API; fixes MatchAndExplain() for polymorphic matchers to allow non-const reference arguments. --- include/gmock/gmock-matchers.h | 143 ++++++++++++++++++++++----------- 1 file changed, 95 insertions(+), 48 deletions(-) diff --git a/include/gmock/gmock-matchers.h b/include/gmock/gmock-matchers.h index b1689d6e..09e469e5 100644 --- a/include/gmock/gmock-matchers.h +++ b/include/gmock/gmock-matchers.h @@ -265,10 +265,11 @@ inline void ExplainMatchResultTo(const PolymorphicMatcherImpl& /* impl */, } // The default implementation of MatchAndExplain() for polymorphic -// matchers. +// matchers. The type of argument x cannot be const T&, in case +// impl.Matches() takes a non-const reference. template inline bool MatchAndExplain(const PolymorphicMatcherImpl& impl, - const T& x, + T& x, MatchResultListener* listener) { const bool match = impl.Matches(x); @@ -789,6 +790,12 @@ class IsNullMatcher { } }; +template +bool MatchAndExplain(const IsNullMatcher& impl, Pointer& p, + MatchResultListener* /* listener */) { + return impl.Matches(p); +} + // Implements the polymorphic NotNull() matcher, which matches any raw or smart // pointer that is not NULL. class NotNullMatcher { @@ -802,6 +809,12 @@ class NotNullMatcher { } }; +template +bool MatchAndExplain(const NotNullMatcher& impl, Pointer& p, + MatchResultListener* /* listener */) { + return impl.Matches(p); +} + // Ref(variable) matches any argument that is a reference to // 'variable'. This matcher is polymorphic as it can match any // super type of the type of 'variable'. @@ -964,6 +977,12 @@ class StrEqualityMatcher { GTEST_DISALLOW_ASSIGN_(StrEqualityMatcher); }; +template +bool MatchAndExplain(const StrEqualityMatcher& impl, T& s, + MatchResultListener* /* listener */) { + return impl.Matches(s); +} + // Implements the polymorphic HasSubstr(substring) matcher, which // can be used as a Matcher as long as T can be converted to a // string. @@ -1003,6 +1022,12 @@ class HasSubstrMatcher { GTEST_DISALLOW_ASSIGN_(HasSubstrMatcher); }; +template +bool MatchAndExplain(const HasSubstrMatcher& impl, T& s, + MatchResultListener* /* listener */) { + return impl.Matches(s); +} + // Implements the polymorphic StartsWith(substring) matcher, which // can be used as a Matcher as long as T can be converted to a // string. @@ -1042,6 +1067,12 @@ class StartsWithMatcher { GTEST_DISALLOW_ASSIGN_(StartsWithMatcher); }; +template +bool MatchAndExplain(const StartsWithMatcher& impl, T& s, + MatchResultListener* /* listener */) { + return impl.Matches(s); +} + // Implements the polymorphic EndsWith(substring) matcher, which // can be used as a Matcher as long as T can be converted to a // string. @@ -1080,6 +1111,12 @@ class EndsWithMatcher { GTEST_DISALLOW_ASSIGN_(EndsWithMatcher); }; +template +bool MatchAndExplain(const EndsWithMatcher& impl, T& s, + MatchResultListener* /* listener */) { + return impl.Matches(s); +} + #if GMOCK_HAS_REGEX // Implements polymorphic matchers MatchesRegex(regex) and @@ -1122,6 +1159,12 @@ class MatchesRegexMatcher { GTEST_DISALLOW_ASSIGN_(MatchesRegexMatcher); }; +template +bool MatchAndExplain(const MatchesRegexMatcher& impl, T& s, + MatchResultListener* /* listener */) { + return impl.Matches(s); +} + #endif // GMOCK_HAS_REGEX // Implements a matcher that compares the two fields of a 2-tuple @@ -1425,6 +1468,12 @@ class TrulyMatcher { GTEST_DISALLOW_ASSIGN_(TrulyMatcher); }; +template +bool MatchAndExplain(const TrulyMatcher& impl, T& x, + MatchResultListener* /* listener */) { + return impl.Matches(x); +} + // Used for implementing Matches(matcher), which turns a matcher into // a predicate. template @@ -1733,7 +1782,7 @@ class FieldMatcher { template bool MatchAndExplain(const FieldMatcher& matcher, - const T& value, MatchResultListener* listener) { + T& value, MatchResultListener* listener) { return matcher.MatchAndExplain( typename ::testing::internal::is_pointer::type(), value, listener); } @@ -1798,7 +1847,7 @@ class PropertyMatcher { template bool MatchAndExplain(const PropertyMatcher& matcher, - const T& value, MatchResultListener* listener) { + T& value, MatchResultListener* listener) { return matcher.MatchAndExplain( typename ::testing::internal::is_pointer::type(), value, listener); } @@ -1933,15 +1982,6 @@ class ContainerEqMatcher { GMOCK_REMOVE_CONST_(GMOCK_REMOVE_REFERENCE_(Container))>(); } - template - bool Matches(const LhsContainer& lhs) const { - // GMOCK_REMOVE_CONST_() is needed to work around an MSVC 8.0 bug - // that causes LhsContainer to be a const type sometimes. - typedef internal::StlContainerView - LhsView; - StlContainerReference lhs_stl_container = LhsView::ConstReference(lhs); - return lhs_stl_container == rhs_; - } void DescribeTo(::std::ostream* os) const { *os << "equals "; UniversalPrinter::Print(rhs_, os); @@ -1952,48 +1992,55 @@ class ContainerEqMatcher { } template - void ExplainMatchResultTo(const LhsContainer& lhs, - ::std::ostream* os) const { + bool MatchAndExplain(const LhsContainer& lhs, + MatchResultListener* listener) const { // GMOCK_REMOVE_CONST_() is needed to work around an MSVC 8.0 bug // that causes LhsContainer to be a const type sometimes. typedef internal::StlContainerView LhsView; typedef typename LhsView::type LhsStlContainer; StlContainerReference lhs_stl_container = LhsView::ConstReference(lhs); + if (lhs_stl_container == rhs_) + return true; - // Something is different. Check for missing values first. - bool printed_header = false; - for (typename LhsStlContainer::const_iterator it = - lhs_stl_container.begin(); - it != lhs_stl_container.end(); ++it) { - if (internal::ArrayAwareFind(rhs_.begin(), rhs_.end(), *it) == - rhs_.end()) { - if (printed_header) { - *os << ", "; - } else { - *os << "Only in actual: "; - printed_header = true; + ::std::ostream* const os = listener->stream(); + if (os != NULL) { + // Something is different. Check for missing values first. + bool printed_header = false; + for (typename LhsStlContainer::const_iterator it = + lhs_stl_container.begin(); + it != lhs_stl_container.end(); ++it) { + if (internal::ArrayAwareFind(rhs_.begin(), rhs_.end(), *it) == + rhs_.end()) { + if (printed_header) { + *os << ", "; + } else { + *os << "Only in actual: "; + printed_header = true; + } + UniversalPrinter::Print(*it, os); + } + } + + // Now check for extra values. + bool printed_header2 = false; + for (typename StlContainer::const_iterator it = rhs_.begin(); + it != rhs_.end(); ++it) { + if (internal::ArrayAwareFind( + lhs_stl_container.begin(), lhs_stl_container.end(), *it) == + lhs_stl_container.end()) { + if (printed_header2) { + *os << ", "; + } else { + *os << (printed_header ? "; not" : "Not") << " in actual: "; + printed_header2 = true; + } + UniversalPrinter::Print(*it, os); } - UniversalPrinter::Print(*it, os); } } - // Now check for extra values. - bool printed_header2 = false; - for (typename StlContainer::const_iterator it = rhs_.begin(); - it != rhs_.end(); ++it) { - if (internal::ArrayAwareFind( - lhs_stl_container.begin(), lhs_stl_container.end(), *it) == - lhs_stl_container.end()) { - if (printed_header2) { - *os << ", "; - } else { - *os << (printed_header ? "; not" : "Not") << " in actual: "; - printed_header2 = true; - } - UniversalPrinter::Print(*it, os); - } - } + return false; } private: @@ -2003,10 +2050,10 @@ class ContainerEqMatcher { }; template -void ExplainMatchResultTo(const ContainerEqMatcher& matcher, - const LhsContainer& lhs, - ::std::ostream* os) { - matcher.ExplainMatchResultTo(lhs, os); +bool MatchAndExplain(const ContainerEqMatcher& matcher, + LhsContainer& lhs, + MatchResultListener* listener) { + return matcher.MatchAndExplain(lhs, listener); } // Implements Contains(element_matcher) for the given argument type Container.