diff options
-rw-r--r-- | include/gmock/gmock-generated-matchers.h | 32 | ||||
-rw-r--r-- | include/gmock/gmock-generated-matchers.h.pump | 5 | ||||
-rw-r--r-- | include/gmock/gmock-matchers.h | 184 | ||||
-rw-r--r-- | test/gmock-generated-matchers_test.cc | 9 | ||||
-rw-r--r-- | test/gmock-matchers_test.cc | 204 | ||||
-rw-r--r-- | test/gmock_output_test_golden.txt | 6 |
6 files changed, 344 insertions, 96 deletions
diff --git a/include/gmock/gmock-generated-matchers.h b/include/gmock/gmock-generated-matchers.h index 90f3750e..2790e06c 100644 --- a/include/gmock/gmock-generated-matchers.h +++ b/include/gmock/gmock-generated-matchers.h @@ -221,7 +221,7 @@ template <class ArgsTuple, int k0 = -1, int k1 = -1, int k2 = -1, int k3 = -1, class ArgsMatcherImpl : public MatcherInterface<ArgsTuple> { public: // ArgsTuple may have top-level const or reference modifiers. - typedef GTEST_REMOVE_CONST_(GTEST_REMOVE_REFERENCE_(ArgsTuple)) RawArgsTuple; + typedef GTEST_REMOVE_REFERENCE_AND_CONST_(ArgsTuple) RawArgsTuple; typedef typename internal::TupleFields<RawArgsTuple, k0, k1, k2, k3, k4, k5, k6, k7, k8, k9>::type SelectedArgs; typedef Matcher<const SelectedArgs&> MonomorphicInnerMatcher; @@ -314,8 +314,7 @@ class ElementsAreMatcher1 { template <typename Container> operator Matcher<Container>() const { - typedef GTEST_REMOVE_CONST_(GTEST_REMOVE_REFERENCE_(Container)) - RawContainer; + typedef GTEST_REMOVE_REFERENCE_AND_CONST_(Container) RawContainer; typedef typename internal::StlContainerView<RawContainer>::type::value_type Element; @@ -343,8 +342,7 @@ class ElementsAreMatcher2 { template <typename Container> operator Matcher<Container>() const { - typedef GTEST_REMOVE_CONST_(GTEST_REMOVE_REFERENCE_(Container)) - RawContainer; + typedef GTEST_REMOVE_REFERENCE_AND_CONST_(Container) RawContainer; typedef typename internal::StlContainerView<RawContainer>::type::value_type Element; @@ -371,8 +369,7 @@ class ElementsAreMatcher3 { template <typename Container> operator Matcher<Container>() const { - typedef GTEST_REMOVE_CONST_(GTEST_REMOVE_REFERENCE_(Container)) - RawContainer; + typedef GTEST_REMOVE_REFERENCE_AND_CONST_(Container) RawContainer; typedef typename internal::StlContainerView<RawContainer>::type::value_type Element; @@ -401,8 +398,7 @@ class ElementsAreMatcher4 { template <typename Container> operator Matcher<Container>() const { - typedef GTEST_REMOVE_CONST_(GTEST_REMOVE_REFERENCE_(Container)) - RawContainer; + typedef GTEST_REMOVE_REFERENCE_AND_CONST_(Container) RawContainer; typedef typename internal::StlContainerView<RawContainer>::type::value_type Element; @@ -433,8 +429,7 @@ class ElementsAreMatcher5 { template <typename Container> operator Matcher<Container>() const { - typedef GTEST_REMOVE_CONST_(GTEST_REMOVE_REFERENCE_(Container)) - RawContainer; + typedef GTEST_REMOVE_REFERENCE_AND_CONST_(Container) RawContainer; typedef typename internal::StlContainerView<RawContainer>::type::value_type Element; @@ -469,8 +464,7 @@ class ElementsAreMatcher6 { template <typename Container> operator Matcher<Container>() const { - typedef GTEST_REMOVE_CONST_(GTEST_REMOVE_REFERENCE_(Container)) - RawContainer; + typedef GTEST_REMOVE_REFERENCE_AND_CONST_(Container) RawContainer; typedef typename internal::StlContainerView<RawContainer>::type::value_type Element; @@ -507,8 +501,7 @@ class ElementsAreMatcher7 { template <typename Container> operator Matcher<Container>() const { - typedef GTEST_REMOVE_CONST_(GTEST_REMOVE_REFERENCE_(Container)) - RawContainer; + typedef GTEST_REMOVE_REFERENCE_AND_CONST_(Container) RawContainer; typedef typename internal::StlContainerView<RawContainer>::type::value_type Element; @@ -547,8 +540,7 @@ class ElementsAreMatcher8 { template <typename Container> operator Matcher<Container>() const { - typedef GTEST_REMOVE_CONST_(GTEST_REMOVE_REFERENCE_(Container)) - RawContainer; + typedef GTEST_REMOVE_REFERENCE_AND_CONST_(Container) RawContainer; typedef typename internal::StlContainerView<RawContainer>::type::value_type Element; @@ -590,8 +582,7 @@ class ElementsAreMatcher9 { template <typename Container> operator Matcher<Container>() const { - typedef GTEST_REMOVE_CONST_(GTEST_REMOVE_REFERENCE_(Container)) - RawContainer; + typedef GTEST_REMOVE_REFERENCE_AND_CONST_(Container) RawContainer; typedef typename internal::StlContainerView<RawContainer>::type::value_type Element; @@ -635,8 +626,7 @@ class ElementsAreMatcher10 { template <typename Container> operator Matcher<Container>() const { - typedef GTEST_REMOVE_CONST_(GTEST_REMOVE_REFERENCE_(Container)) - RawContainer; + typedef GTEST_REMOVE_REFERENCE_AND_CONST_(Container) RawContainer; typedef typename internal::StlContainerView<RawContainer>::type::value_type Element; diff --git a/include/gmock/gmock-generated-matchers.h.pump b/include/gmock/gmock-generated-matchers.h.pump index 2f325b04..db498ec0 100644 --- a/include/gmock/gmock-generated-matchers.h.pump +++ b/include/gmock/gmock-generated-matchers.h.pump @@ -107,7 +107,7 @@ template <class ArgsTuple$for i [[, int k$i = -1]]> class ArgsMatcherImpl : public MatcherInterface<ArgsTuple> { public: // ArgsTuple may have top-level const or reference modifiers. - typedef GTEST_REMOVE_CONST_(GTEST_REMOVE_REFERENCE_(ArgsTuple)) RawArgsTuple; + typedef GTEST_REMOVE_REFERENCE_AND_CONST_(ArgsTuple) RawArgsTuple; typedef typename internal::TupleFields<RawArgsTuple, $ks>::type SelectedArgs; typedef Matcher<const SelectedArgs&> MonomorphicInnerMatcher; @@ -200,8 +200,7 @@ class ElementsAreMatcher$i { template <typename Container> operator Matcher<Container>() const { - typedef GTEST_REMOVE_CONST_(GTEST_REMOVE_REFERENCE_(Container)) - RawContainer; + typedef GTEST_REMOVE_REFERENCE_AND_CONST_(Container) RawContainer; typedef typename internal::StlContainerView<RawContainer>::type::value_type Element; diff --git a/include/gmock/gmock-matchers.h b/include/gmock/gmock-matchers.h index 7f84761e..2a42bf94 100644 --- a/include/gmock/gmock-matchers.h +++ b/include/gmock/gmock-matchers.h @@ -43,6 +43,7 @@ #include <ostream> // NOLINT #include <sstream> #include <string> +#include <utility> #include <vector> #include <gmock/internal/gmock-internal-utils.h> @@ -427,8 +428,8 @@ class SafeMatcherCastImpl { cannot_convert_non_referentce_arg_to_reference); // In case both T and U are arithmetic types, enforce that the // conversion is not lossy. - typedef GTEST_REMOVE_CONST_(GTEST_REMOVE_REFERENCE_(T)) RawT; - typedef GTEST_REMOVE_CONST_(GTEST_REMOVE_REFERENCE_(U)) RawU; + typedef GTEST_REMOVE_REFERENCE_AND_CONST_(T) RawT; + typedef GTEST_REMOVE_REFERENCE_AND_CONST_(U) RawU; const bool kTIsOther = GMOCK_KIND_OF_(RawT) == internal::kOther; const bool kUIsOther = GMOCK_KIND_OF_(RawU) == internal::kOther; GTEST_COMPILE_ASSERT_( @@ -1095,38 +1096,46 @@ class MatchesRegexMatcher { // // We define this as a macro in order to eliminate duplicated source // code. -#define GMOCK_IMPLEMENT_COMPARISON2_MATCHER_(name, op) \ +#define GMOCK_IMPLEMENT_COMPARISON2_MATCHER_(name, op, relation) \ class name##2Matcher { \ public: \ template <typename T1, typename T2> \ + operator Matcher< ::std::tr1::tuple<T1, T2> >() const { \ + return MakeMatcher(new Impl< ::std::tr1::tuple<T1, T2> >); \ + } \ + template <typename T1, typename T2> \ operator Matcher<const ::std::tr1::tuple<T1, T2>&>() const { \ - return MakeMatcher(new Impl<T1, T2>); \ + return MakeMatcher(new Impl<const ::std::tr1::tuple<T1, T2>&>); \ } \ private: \ - template <typename T1, typename T2> \ - class Impl : public MatcherInterface<const ::std::tr1::tuple<T1, T2>&> { \ + template <typename Tuple> \ + class Impl : public MatcherInterface<Tuple> { \ public: \ virtual bool MatchAndExplain( \ - const ::std::tr1::tuple<T1, T2>& args, \ + Tuple args, \ MatchResultListener* /* listener */) const { \ return ::std::tr1::get<0>(args) op ::std::tr1::get<1>(args); \ } \ virtual void DescribeTo(::std::ostream* os) const { \ - *os << "are a pair (x, y) where x " #op " y"; \ + *os << "are " relation; \ } \ virtual void DescribeNegationTo(::std::ostream* os) const { \ - *os << "are a pair (x, y) where x " #op " y is false"; \ + *os << "aren't " relation; \ } \ }; \ } // Implements Eq(), Ge(), Gt(), Le(), Lt(), and Ne() respectively. -GMOCK_IMPLEMENT_COMPARISON2_MATCHER_(Eq, ==); -GMOCK_IMPLEMENT_COMPARISON2_MATCHER_(Ge, >=); -GMOCK_IMPLEMENT_COMPARISON2_MATCHER_(Gt, >); -GMOCK_IMPLEMENT_COMPARISON2_MATCHER_(Le, <=); -GMOCK_IMPLEMENT_COMPARISON2_MATCHER_(Lt, <); -GMOCK_IMPLEMENT_COMPARISON2_MATCHER_(Ne, !=); +GMOCK_IMPLEMENT_COMPARISON2_MATCHER_(Eq, ==, "an equal pair"); +GMOCK_IMPLEMENT_COMPARISON2_MATCHER_( + Ge, >=, "a pair where the first >= the second"); +GMOCK_IMPLEMENT_COMPARISON2_MATCHER_( + Gt, >, "a pair where the first > the second"); +GMOCK_IMPLEMENT_COMPARISON2_MATCHER_( + Le, <=, "a pair where the first <= the second"); +GMOCK_IMPLEMENT_COMPARISON2_MATCHER_( + Lt, <, "a pair where the first < the second"); +GMOCK_IMPLEMENT_COMPARISON2_MATCHER_(Ne, !=, "an unequal pair"); #undef GMOCK_IMPLEMENT_COMPARISON2_MATCHER_ @@ -1873,8 +1882,8 @@ class ContainerEqMatcher { explicit ContainerEqMatcher(const Container& rhs) : rhs_(View::Copy(rhs)) { // Makes sure the user doesn't instantiate this class template // with a const or reference type. - testing::StaticAssertTypeEq<Container, - GTEST_REMOVE_CONST_(GTEST_REMOVE_REFERENCE_(Container))>(); + (void)testing::StaticAssertTypeEq<Container, + GTEST_REMOVE_REFERENCE_AND_CONST_(Container)>(); } void DescribeTo(::std::ostream* os) const { @@ -1945,11 +1954,121 @@ class ContainerEqMatcher { GTEST_DISALLOW_ASSIGN_(ContainerEqMatcher); }; +// Implements Pointwise(tuple_matcher, rhs_container). tuple_matcher +// must be able to be safely cast to Matcher<tuple<const T1&, const +// T2&> >, where T1 and T2 are the types of elements in the LHS +// container and the RHS container respectively. +template <typename TupleMatcher, typename RhsContainer> +class PointwiseMatcher { + public: + typedef internal::StlContainerView<RhsContainer> RhsView; + typedef typename RhsView::type RhsStlContainer; + typedef typename RhsStlContainer::value_type RhsValue; + + // Like ContainerEq, we make a copy of rhs in case the elements in + // it are modified after this matcher is created. + PointwiseMatcher(const TupleMatcher& tuple_matcher, const RhsContainer& rhs) + : tuple_matcher_(tuple_matcher), rhs_(RhsView::Copy(rhs)) { + // Makes sure the user doesn't instantiate this class template + // with a const or reference type. + (void)testing::StaticAssertTypeEq<RhsContainer, + GTEST_REMOVE_REFERENCE_AND_CONST_(RhsContainer)>(); + } + + template <typename LhsContainer> + operator Matcher<LhsContainer>() const { + return MakeMatcher(new Impl<LhsContainer>(tuple_matcher_, rhs_)); + } + + template <typename LhsContainer> + class Impl : public MatcherInterface<LhsContainer> { + public: + typedef internal::StlContainerView< + GTEST_REMOVE_REFERENCE_AND_CONST_(LhsContainer)> LhsView; + typedef typename LhsView::type LhsStlContainer; + typedef typename LhsView::const_reference LhsStlContainerReference; + typedef typename LhsStlContainer::value_type LhsValue; + // We pass the LHS value and the RHS value to the inner matcher by + // reference, as they may be expensive to copy. We must use tuple + // instead of pair here, as a pair cannot hold references (C++ 98, + // 20.2.2 [lib.pairs]). + typedef std::tr1::tuple<const LhsValue&, const RhsValue&> InnerMatcherArg; + + Impl(const TupleMatcher& tuple_matcher, const RhsStlContainer& rhs) + // mono_tuple_matcher_ holds a monomorphic version of the tuple matcher. + : mono_tuple_matcher_(SafeMatcherCast<InnerMatcherArg>(tuple_matcher)), + rhs_(rhs) {} + + virtual void DescribeTo(::std::ostream* os) const { + *os << "contains " << rhs_.size() + << " values, where each value and its corresponding value in "; + UniversalPrinter<RhsStlContainer>::Print(rhs_, os); + *os << " "; + mono_tuple_matcher_.DescribeTo(os); + } + virtual void DescribeNegationTo(::std::ostream* os) const { + *os << "doesn't contain exactly " << rhs_.size() + << " values, or contains a value x at some index i" + << " where x and the i-th value of "; + UniversalPrint(rhs_, os); + *os << " "; + mono_tuple_matcher_.DescribeNegationTo(os); + } + + virtual bool MatchAndExplain(LhsContainer lhs, + MatchResultListener* listener) const { + LhsStlContainerReference lhs_stl_container = LhsView::ConstReference(lhs); + const size_t actual_size = lhs_stl_container.size(); + if (actual_size != rhs_.size()) { + *listener << "which contains " << actual_size << " values"; + return false; + } + + typename LhsStlContainer::const_iterator left = lhs_stl_container.begin(); + typename RhsStlContainer::const_iterator right = rhs_.begin(); + for (size_t i = 0; i != actual_size; ++i, ++left, ++right) { + const InnerMatcherArg value_pair(*left, *right); + + if (listener->IsInterested()) { + StringMatchResultListener inner_listener; + if (!mono_tuple_matcher_.MatchAndExplain( + value_pair, &inner_listener)) { + *listener << "where the value pair ("; + UniversalPrint(*left, listener->stream()); + *listener << ", "; + UniversalPrint(*right, listener->stream()); + *listener << ") at index #" << i << " don't match"; + PrintIfNotEmpty(inner_listener.str(), listener->stream()); + return false; + } + } else { + if (!mono_tuple_matcher_.Matches(value_pair)) + return false; + } + } + + return true; + } + + private: + const Matcher<InnerMatcherArg> mono_tuple_matcher_; + const RhsStlContainer rhs_; + + GTEST_DISALLOW_ASSIGN_(Impl); + }; + + private: + const TupleMatcher tuple_matcher_; + const RhsStlContainer rhs_; + + GTEST_DISALLOW_ASSIGN_(PointwiseMatcher); +}; + // Holds the logic common to ContainsMatcherImpl and EachMatcherImpl. template <typename Container> class QuantifierMatcherImpl : public MatcherInterface<Container> { public: - typedef GTEST_REMOVE_CONST_(GTEST_REMOVE_REFERENCE_(Container)) RawContainer; + typedef GTEST_REMOVE_REFERENCE_AND_CONST_(Container) RawContainer; typedef StlContainerView<RawContainer> View; typedef typename View::type StlContainer; typedef typename View::const_reference StlContainerReference; @@ -2088,7 +2207,7 @@ class EachMatcher { template <typename PairType> class KeyMatcherImpl : public MatcherInterface<PairType> { public: - typedef GTEST_REMOVE_CONST_(GTEST_REMOVE_REFERENCE_(PairType)) RawPairType; + typedef GTEST_REMOVE_REFERENCE_AND_CONST_(PairType) RawPairType; typedef typename RawPairType::first_type KeyType; template <typename InnerMatcher> @@ -2150,7 +2269,7 @@ class KeyMatcher { template <typename PairType> class PairMatcherImpl : public MatcherInterface<PairType> { public: - typedef GTEST_REMOVE_CONST_(GTEST_REMOVE_REFERENCE_(PairType)) RawPairType; + typedef GTEST_REMOVE_REFERENCE_AND_CONST_(PairType) RawPairType; typedef typename RawPairType::first_type FirstType; typedef typename RawPairType::second_type SecondType; @@ -2257,7 +2376,7 @@ class PairMatcher { template <typename Container> class ElementsAreMatcherImpl : public MatcherInterface<Container> { public: - typedef GTEST_REMOVE_CONST_(GTEST_REMOVE_REFERENCE_(Container)) RawContainer; + typedef GTEST_REMOVE_REFERENCE_AND_CONST_(Container) RawContainer; typedef internal::StlContainerView<RawContainer> View; typedef typename View::type StlContainer; typedef typename View::const_reference StlContainerReference; @@ -2376,8 +2495,7 @@ class ElementsAreMatcher0 { template <typename Container> operator Matcher<Container>() const { - typedef GTEST_REMOVE_CONST_(GTEST_REMOVE_REFERENCE_(Container)) - RawContainer; + typedef GTEST_REMOVE_REFERENCE_AND_CONST_(Container) RawContainer; typedef typename internal::StlContainerView<RawContainer>::type::value_type Element; @@ -2395,8 +2513,7 @@ class ElementsAreArrayMatcher { template <typename Container> operator Matcher<Container>() const { - typedef GTEST_REMOVE_CONST_(GTEST_REMOVE_REFERENCE_(Container)) - RawContainer; + typedef GTEST_REMOVE_REFERENCE_AND_CONST_(Container) RawContainer; typedef typename internal::StlContainerView<RawContainer>::type::value_type Element; @@ -2900,6 +3017,23 @@ inline PolymorphicMatcher<internal::ContainerEqMatcher< // NOLINT internal::ContainerEqMatcher<RawContainer>(rhs)); } +// Matches an STL-style container or a native array that contains the +// same number of elements as in rhs, where its i-th element and rhs's +// i-th element (as a pair) satisfy the given pair matcher, for all i. +// TupleMatcher must be able to be safely cast to Matcher<tuple<const +// T1&, const T2&> >, where T1 and T2 are the types of elements in the +// LHS container and the RHS container respectively. +template <typename TupleMatcher, typename Container> +inline internal::PointwiseMatcher<TupleMatcher, + GTEST_REMOVE_CONST_(Container)> +Pointwise(const TupleMatcher& tuple_matcher, 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 GTEST_REMOVE_CONST_(Container) RawContainer; + return internal::PointwiseMatcher<TupleMatcher, RawContainer>( + tuple_matcher, rhs); +} + // Matches an STL-style container or a native array that contains at // least one element matching the given value or matcher. // diff --git a/test/gmock-generated-matchers_test.cc b/test/gmock-generated-matchers_test.cc index 12479af4..eebca8a0 100644 --- a/test/gmock-generated-matchers_test.cc +++ b/test/gmock-generated-matchers_test.cc @@ -192,7 +192,8 @@ TEST(ArgsTest, AcceptsTenTemplateArgs) { TEST(ArgsTest, DescirbesSelfCorrectly) { const Matcher<tuple<int, bool, char> > m = Args<2, 0>(Lt()); - EXPECT_EQ("are a tuple whose fields (#2, #0) are a pair (x, y) where x < y", + EXPECT_EQ("are a tuple whose fields (#2, #0) are a pair where " + "the first < the second", Describe(m)); } @@ -200,14 +201,14 @@ TEST(ArgsTest, DescirbesNestedArgsCorrectly) { const Matcher<const tuple<int, bool, char, int>&> m = Args<0, 2, 3>(Args<2, 0>(Lt())); EXPECT_EQ("are a tuple whose fields (#0, #2, #3) are a tuple " - "whose fields (#2, #0) are a pair (x, y) where x < y", + "whose fields (#2, #0) are a pair where the first < the second", Describe(m)); } TEST(ArgsTest, DescribesNegationCorrectly) { const Matcher<tuple<int, char> > m = Args<1, 0>(Gt()); - EXPECT_EQ("are a tuple whose fields (#1, #0) are a pair (x, y) " - "where x > y is false", + EXPECT_EQ("are a tuple whose fields (#1, #0) aren't a pair " + "where the first > the second", DescribeNegation(m)); } diff --git a/test/gmock-matchers_test.cc b/test/gmock-matchers_test.cc index a7c217d4..3b151dbd 100644 --- a/test/gmock-matchers_test.cc +++ b/test/gmock-matchers_test.cc @@ -61,13 +61,18 @@ bool SkipPrefix(const char* prefix, const char** pstr); namespace gmock_matchers_test { +using std::list; using std::make_pair; using std::map; using std::multimap; +using std::multiset; +using std::ostream; using std::pair; using std::set; using std::stringstream; +using std::tr1::get; using std::tr1::make_tuple; +using std::tr1::tuple; using std::vector; using testing::A; using testing::AllArgs; @@ -104,6 +109,7 @@ using testing::Not; using testing::NotNull; using testing::Pair; using testing::Pointee; +using testing::Pointwise; using testing::PolymorphicMatcher; using testing::Property; using testing::Ref; @@ -144,7 +150,7 @@ class GreaterThanMatcher : public MatcherInterface<int> { public: explicit GreaterThanMatcher(int rhs) : rhs_(rhs) {} - virtual void DescribeTo(::std::ostream* os) const { + virtual void DescribeTo(ostream* os) const { *os << "is > " << rhs_; } @@ -189,9 +195,9 @@ string DescribeNegation(const Matcher<T>& m) { // Returns the reason why x matches, or doesn't match, m. template <typename MatcherType, typename Value> string Explain(const MatcherType& m, const Value& x) { - stringstream ss; - m.ExplainMatchResultTo(x, &ss); - return ss.str(); + StringMatchResultListener listener; + ExplainMatchResult(m, x, &listener); + return listener.str(); } TEST(MatchResultListenerTest, StreamingWorks) { @@ -228,7 +234,7 @@ class EvenMatcherImpl : public MatcherInterface<int> { return x % 2 == 0; } - virtual void DescribeTo(::std::ostream* os) const { + virtual void DescribeTo(ostream* os) const { *os << "is an even number"; } @@ -258,7 +264,7 @@ class NewEvenMatcherImpl : public MatcherInterface<int> { return match; } - virtual void DescribeTo(::std::ostream* os) const { + virtual void DescribeTo(ostream* os) const { *os << "is an even number"; } }; @@ -375,9 +381,9 @@ class ReferencesBarOrIsZeroImpl { return p == &g_bar || x == 0; } - void DescribeTo(::std::ostream* os) const { *os << "g_bar or zero"; } + void DescribeTo(ostream* os) const { *os << "g_bar or zero"; } - void DescribeNegationTo(::std::ostream* os) const { + void DescribeNegationTo(ostream* os) const { *os << "doesn't reference g_bar and is not zero"; } }; @@ -408,9 +414,9 @@ TEST(MakePolymorphicMatcherTest, ConstructsMatcherUsingOldAPI) { class PolymorphicIsEvenImpl { public: - void DescribeTo(::std::ostream* os) const { *os << "is even"; } + void DescribeTo(ostream* os) const { *os << "is even"; } - void DescribeNegationTo(::std::ostream* os) const { + void DescribeNegationTo(ostream* os) const { *os << "is odd"; } @@ -1150,7 +1156,7 @@ TEST(KeyTest, SafelyCastsInnerMatcher) { } TEST(KeyTest, InsideContainsUsingMap) { - std::map<int, char> container; + map<int, char> container; container.insert(make_pair(1, 'a')); container.insert(make_pair(2, 'b')); container.insert(make_pair(4, 'c')); @@ -1159,7 +1165,7 @@ TEST(KeyTest, InsideContainsUsingMap) { } TEST(KeyTest, InsideContainsUsingMultimap) { - std::multimap<int, char> container; + multimap<int, char> container; container.insert(make_pair(1, 'a')); container.insert(make_pair(2, 'b')); container.insert(make_pair(4, 'c')); @@ -1268,7 +1274,7 @@ TEST(PairTest, SafelyCastsInnerMatchers) { } TEST(PairTest, InsideContainsUsingMap) { - std::map<int, char> container; + map<int, char> container; container.insert(make_pair(1, 'a')); container.insert(make_pair(2, 'b')); container.insert(make_pair(4, 'c')); @@ -1761,7 +1767,7 @@ TEST(Eq2Test, MatchesEqualArguments) { // Tests that Eq() describes itself properly. TEST(Eq2Test, CanDescribeSelf) { Matcher<const Tuple2&> m = Eq(); - EXPECT_EQ("are a pair (x, y) where x == y", Describe(m)); + EXPECT_EQ("are an equal pair", Describe(m)); } // Tests that Ge() matches a 2-tuple where the first field >= the @@ -1776,7 +1782,7 @@ TEST(Ge2Test, MatchesGreaterThanOrEqualArguments) { // Tests that Ge() describes itself properly. TEST(Ge2Test, CanDescribeSelf) { Matcher<const Tuple2&> m = Ge(); - EXPECT_EQ("are a pair (x, y) where x >= y", Describe(m)); + EXPECT_EQ("are a pair where the first >= the second", Describe(m)); } // Tests that Gt() matches a 2-tuple where the first field > the @@ -1791,7 +1797,7 @@ TEST(Gt2Test, MatchesGreaterThanArguments) { // Tests that Gt() describes itself properly. TEST(Gt2Test, CanDescribeSelf) { Matcher<const Tuple2&> m = Gt(); - EXPECT_EQ("are a pair (x, y) where x > y", Describe(m)); + EXPECT_EQ("are a pair where the first > the second", Describe(m)); } // Tests that Le() matches a 2-tuple where the first field <= the @@ -1806,7 +1812,7 @@ TEST(Le2Test, MatchesLessThanOrEqualArguments) { // Tests that Le() describes itself properly. TEST(Le2Test, CanDescribeSelf) { Matcher<const Tuple2&> m = Le(); - EXPECT_EQ("are a pair (x, y) where x <= y", Describe(m)); + EXPECT_EQ("are a pair where the first <= the second", Describe(m)); } // Tests that Lt() matches a 2-tuple where the first field < the @@ -1821,7 +1827,7 @@ TEST(Lt2Test, MatchesLessThanArguments) { // Tests that Lt() describes itself properly. TEST(Lt2Test, CanDescribeSelf) { Matcher<const Tuple2&> m = Lt(); - EXPECT_EQ("are a pair (x, y) where x < y", Describe(m)); + EXPECT_EQ("are a pair where the first < the second", Describe(m)); } // Tests that Ne() matches a 2-tuple where the first field != the @@ -1836,7 +1842,7 @@ TEST(Ne2Test, MatchesUnequalArguments) { // Tests that Ne() describes itself properly. TEST(Ne2Test, CanDescribeSelf) { Matcher<const Tuple2&> m = Ne(); - EXPECT_EQ("are a pair (x, y) where x != y", Describe(m)); + EXPECT_EQ("are an unequal pair", Describe(m)); } // Tests that Not(m) matches any value that doesn't match m. @@ -3338,11 +3344,11 @@ class DivisibleByImpl { return (n % divider_) == 0; } - void DescribeTo(::std::ostream* os) const { + void DescribeTo(ostream* os) const { *os << "is divisible by " << divider_; } - void DescribeNegationTo(::std::ostream* os) const { + void DescribeNegationTo(ostream* os) const { *os << "is not divisible by " << divider_; } @@ -3444,10 +3450,10 @@ template <typename T> class ContainerEqTest : public testing::Test {}; typedef testing::Types< - std::set<int>, - std::vector<size_t>, - std::multiset<size_t>, - std::list<int> > + set<int>, + vector<size_t>, + multiset<size_t>, + list<int> > ContainerEqTestTypes; TYPED_TEST_CASE(ContainerEqTest, ContainerEqTestTypes); @@ -3515,9 +3521,9 @@ TYPED_TEST(ContainerEqTest, DuplicateDifference) { TEST(ContainerEqExtraTest, MultipleValuesMissing) { static const int vals[] = {1, 1, 2, 3, 5, 8}; static const int test_vals[] = {2, 1, 5}; - std::vector<int> my_set(vals, vals + 6); - std::vector<int> test_set(test_vals, test_vals + 3); - const Matcher<std::vector<int> > m = ContainerEq(my_set); + vector<int> my_set(vals, vals + 6); + vector<int> test_set(test_vals, test_vals + 3); + const Matcher<vector<int> > m = ContainerEq(my_set); EXPECT_FALSE(m.Matches(test_set)); EXPECT_EQ("which doesn't have these expected elements: 3, 8", Explain(m, test_set)); @@ -3528,9 +3534,9 @@ TEST(ContainerEqExtraTest, MultipleValuesMissing) { TEST(ContainerEqExtraTest, MultipleValuesAdded) { static const int vals[] = {1, 1, 2, 3, 5, 8}; static const int test_vals[] = {1, 2, 92, 3, 5, 8, 46}; - std::list<size_t> my_set(vals, vals + 6); - std::list<size_t> test_set(test_vals, test_vals + 7); - const Matcher<const std::list<size_t>&> m = ContainerEq(my_set); + list<size_t> my_set(vals, vals + 6); + list<size_t> test_set(test_vals, test_vals + 7); + const Matcher<const list<size_t>&> m = ContainerEq(my_set); EXPECT_FALSE(m.Matches(test_set)); EXPECT_EQ("which has these unexpected elements: 92, 46", Explain(m, test_set)); @@ -3540,9 +3546,9 @@ TEST(ContainerEqExtraTest, MultipleValuesAdded) { TEST(ContainerEqExtraTest, MultipleValuesAddedAndRemoved) { static const int vals[] = {1, 1, 2, 3, 5, 8}; static const int test_vals[] = {1, 2, 3, 92, 46}; - std::list<size_t> my_set(vals, vals + 6); - std::list<size_t> test_set(test_vals, test_vals + 5); - const Matcher<const std::list<size_t> > m = ContainerEq(my_set); + list<size_t> my_set(vals, vals + 6); + list<size_t> test_set(test_vals, test_vals + 5); + const Matcher<const list<size_t> > m = ContainerEq(my_set); EXPECT_FALSE(m.Matches(test_set)); EXPECT_EQ("which has these unexpected elements: 92, 46,\n" "and doesn't have these expected elements: 5, 8", @@ -3554,9 +3560,9 @@ TEST(ContainerEqExtraTest, MultipleValuesAddedAndRemoved) { TEST(ContainerEqExtraTest, MultiSetOfIntDuplicateDifference) { static const int vals[] = {1, 1, 2, 3, 5, 8}; static const int test_vals[] = {1, 2, 3, 5, 8}; - std::vector<int> my_set(vals, vals + 6); - std::vector<int> test_set(test_vals, test_vals + 5); - const Matcher<std::vector<int> > m = ContainerEq(my_set); + vector<int> my_set(vals, vals + 6); + vector<int> test_set(test_vals, test_vals + 5); + const Matcher<vector<int> > m = ContainerEq(my_set); EXPECT_TRUE(m.Matches(my_set)); EXPECT_FALSE(m.Matches(test_set)); // There is nothing to report when both sets contain all the same values. @@ -3566,15 +3572,15 @@ TEST(ContainerEqExtraTest, MultiSetOfIntDuplicateDifference) { // Tests that ContainerEq works for non-trivial associative containers, // like maps. TEST(ContainerEqExtraTest, WorksForMaps) { - std::map<int, std::string> my_map; + map<int, std::string> my_map; my_map[0] = "a"; my_map[1] = "b"; - std::map<int, std::string> test_map; + map<int, std::string> test_map; test_map[0] = "aa"; test_map[1] = "b"; - const Matcher<const std::map<int, std::string>&> m = ContainerEq(my_map); + const Matcher<const map<int, std::string>&> m = ContainerEq(my_map); EXPECT_TRUE(m.Matches(my_map)); EXPECT_FALSE(m.Matches(test_map)); @@ -4072,5 +4078,123 @@ TEST(EachTest, WorksForNativeArrayAsTuple) { EXPECT_THAT(make_tuple(pointer, 2), Not(Each(Gt(1)))); } +// For testing Pointwise(). +class IsHalfOfMatcher { + public: + template <typename T1, typename T2> + bool MatchAndExplain(const tuple<T1, T2>& a_pair, + MatchResultListener* listener) const { + if (get<0>(a_pair) == get<1>(a_pair)/2) { + *listener << "where the second is " << get<1>(a_pair); + return true; + } else { + *listener << "where the second/2 is " << get<1>(a_pair)/2; + return false; + } + } + + void DescribeTo(ostream* os) const { + *os << "are a pair where the first is half of the second"; + } + + void DescribeNegationTo(ostream* os) const { + *os << "are a pair where the first isn't half of the second"; + } +}; + +PolymorphicMatcher<IsHalfOfMatcher> IsHalfOf() { + return MakePolymorphicMatcher(IsHalfOfMatcher()); +} + +TEST(PointwiseTest, DescribesSelf) { + vector<int> rhs; + rhs.push_back(1); + rhs.push_back(2); + rhs.push_back(3); + const Matcher<const vector<int>&> m = Pointwise(IsHalfOf(), rhs); + EXPECT_EQ("contains 3 values, where each value and its corresponding value " + "in { 1, 2, 3 } are a pair where the first is half of the second", + Describe(m)); + EXPECT_EQ("doesn't contain exactly 3 values, or contains a value x at some " + "index i where x and the i-th value of { 1, 2, 3 } are a pair " + "where the first isn't half of the second", + DescribeNegation(m)); +} + +TEST(PointwiseTest, MakesCopyOfRhs) { + list<signed char> rhs; + rhs.push_back(2); + rhs.push_back(4); + + int lhs[] = { 1, 2 }; + const Matcher<const int (&)[2]> m = Pointwise(IsHalfOf(), rhs); + EXPECT_THAT(lhs, m); + + // Changing rhs now shouldn't affect m, which made a copy of rhs. + rhs.push_back(6); + EXPECT_THAT(lhs, m); +} + +TEST(PointwiseTest, WorksForLhsNativeArray) { + const int lhs[] = { 1, 2, 3 }; + vector<int> rhs; + rhs.push_back(2); + rhs.push_back(4); + rhs.push_back(6); + EXPECT_THAT(lhs, Pointwise(Lt(), rhs)); + EXPECT_THAT(lhs, Not(Pointwise(Gt(), rhs))); +} + +TEST(PointwiseTest, WorksForRhsNativeArray) { + const int rhs[] = { 1, 2, 3 }; + vector<int> lhs; + lhs.push_back(2); + lhs.push_back(4); + lhs.push_back(6); + EXPECT_THAT(lhs, Pointwise(Gt(), rhs)); + EXPECT_THAT(lhs, Not(Pointwise(Lt(), rhs))); +} + +TEST(PointwiseTest, RejectsWrongSize) { + const double lhs[2] = { 1, 2 }; + const int rhs[1] = { 0 }; + EXPECT_THAT(lhs, Not(Pointwise(Gt(), rhs))); + EXPECT_EQ("which contains 2 values", + Explain(Pointwise(Gt(), rhs), lhs)); + + const int rhs2[3] = { 0, 1, 2 }; + EXPECT_THAT(lhs, Not(Pointwise(Gt(), rhs2))); +} + +TEST(PointwiseTest, RejectsWrongContent) { + const double lhs[3] = { 1, 2, 3 }; + const int rhs[3] = { 2, 6, 4 }; + EXPECT_THAT(lhs, Not(Pointwise(IsHalfOf(), rhs))); + EXPECT_EQ("where the value pair (2, 6) at index #1 don't match, " + "where the second/2 is 3", + Explain(Pointwise(IsHalfOf(), rhs), lhs)); +} + +TEST(PointwiseTest, AcceptsCorrectContent) { + const double lhs[3] = { 1, 2, 3 }; + const int rhs[3] = { 2, 4, 6 }; + EXPECT_THAT(lhs, Pointwise(IsHalfOf(), rhs)); + EXPECT_EQ("", Explain(Pointwise(IsHalfOf(), rhs), lhs)); +} + +TEST(PointwiseTest, AllowsMonomorphicInnerMatcher) { + const double lhs[3] = { 1, 2, 3 }; + const int rhs[3] = { 2, 4, 6 }; + const Matcher<tuple<const double&, const int&> > m1 = IsHalfOf(); + EXPECT_THAT(lhs, Pointwise(m1, rhs)); + EXPECT_EQ("", Explain(Pointwise(m1, rhs), lhs)); + + // This type works as a tuple<const double&, const int&> can be + // implicitly cast to tuple<double, int>. + const Matcher<tuple<double, int> > m2 = IsHalfOf(); + EXPECT_THAT(lhs, Pointwise(m2, rhs)); + EXPECT_EQ("", Explain(Pointwise(m2, rhs), lhs)); +} + } // namespace gmock_matchers_test } // namespace testing diff --git a/test/gmock_output_test_golden.txt b/test/gmock_output_test_golden.txt index 382dc8cc..a7ff5630 100644 --- a/test/gmock_output_test_golden.txt +++ b/test/gmock_output_test_golden.txt @@ -151,7 +151,7 @@ FILE:#: pre-requisite #1 [ RUN ] GMockOutputTest.UnsatisfiedWith FILE:#: Failure Actual function call count doesn't match EXPECT_CALL(foo_, Bar2(_, _))... - Expected args: are a pair (x, y) where x >= y + Expected args: are a pair where the first >= the second Expected: to be called once Actual: never called - unsatisfied and active [ FAILED ] GMockOutputTest.UnsatisfiedWith @@ -190,7 +190,7 @@ Unexpected mock function call - returning default value. Google Mock tried the following 1 expectation, but it didn't match: FILE:#: EXPECT_CALL(foo_, Bar2(Ge(2), Ge(1)))... - Expected args: are a pair (x, y) where x >= y + Expected args: are a pair where the first >= the second Actual: don't match Expected: to be called once Actual: never called - unsatisfied and active @@ -206,7 +206,7 @@ Google Mock tried the following 1 expectation, but it didn't match: FILE:#: EXPECT_CALL(foo_, Bar2(Ge(2), Ge(1)))... Expected arg #0: is >= 2 Actual: 1 - Expected args: are a pair (x, y) where x >= y + Expected args: are a pair where the first >= the second Actual: don't match Expected: to be called once Actual: never called - unsatisfied and active |