diff options
author | zhanyong.wan <zhanyong.wan@8415998a-534a-0410-bf83-d39667b30386> | 2009-07-16 20:26:41 +0000 |
---|---|---|
committer | zhanyong.wan <zhanyong.wan@8415998a-534a-0410-bf83-d39667b30386> | 2009-07-16 20:26:41 +0000 |
commit | b5937dab6969ca4b1d8304cc8939ce16c1fb62e5 (patch) | |
tree | 7884617457eb65e7fe7e5b20fc1d150e472b11fa | |
parent | 41b9b0b5614588d252d565646ae43e9607d46502 (diff) | |
download | googletest-b5937dab6969ca4b1d8304cc8939ce16c1fb62e5.tar.gz googletest-b5937dab6969ca4b1d8304cc8939ce16c1fb62e5.tar.bz2 googletest-b5937dab6969ca4b1d8304cc8939ce16c1fb62e5.zip |
Adds the Key() matcher, by Marcus Borger.
-rw-r--r-- | include/gmock/gmock-matchers.h | 66 | ||||
-rw-r--r-- | test/gmock-matchers_test.cc | 49 |
2 files changed, 115 insertions, 0 deletions
diff --git a/include/gmock/gmock-matchers.h b/include/gmock/gmock-matchers.h index 4696f704..db23a1bd 100644 --- a/include/gmock/gmock-matchers.h +++ b/include/gmock/gmock-matchers.h @@ -1867,6 +1867,64 @@ class ContainsMatcher { const M inner_matcher_; }; +// Implements Key(inner_matcher) for the given argument pair type. +// Key(inner_matcher) matches an std::pair whose 'first' field matches +// inner_matcher. For example, Contains(Key(Ge(5))) can be used to match an +// std::map that contains at least one element whose key is >= 5. +template <typename PairType> +class KeyMatcherImpl : public MatcherInterface<PairType> { + public: + typedef GMOCK_REMOVE_CONST_(GMOCK_REMOVE_REFERENCE_(PairType)) RawPairType; + typedef typename RawPairType::first_type KeyType; + + template <typename InnerMatcher> + explicit KeyMatcherImpl(InnerMatcher inner_matcher) + : inner_matcher_( + testing::SafeMatcherCast<const KeyType&>(inner_matcher)) { + } + + // 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); + } + + // Describes what this matcher does. + virtual void DescribeTo(::std::ostream* os) const { + *os << "has a key that "; + inner_matcher_.DescribeTo(os); + } + + // Describes what the negation of this matcher does. + virtual void DescribeNegationTo(::std::ostream* os) const { + *os << "doesn't have a key that "; + 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_; +}; + +// Implements polymorphic Key(matcher_for_key). +template <typename M> +class KeyMatcher { + public: + explicit KeyMatcher(M m) : matcher_for_key_(m) {} + + template <typename PairType> + operator Matcher<PairType>() const { + return MakeMatcher(new KeyMatcherImpl<PairType>(matcher_for_key_)); + } + + private: + const M matcher_for_key_; +}; + } // namespace internal // Implements MatcherCast(). @@ -2342,6 +2400,14 @@ inline internal::ContainsMatcher<M> Contains(M matcher) { return internal::ContainsMatcher<M>(matcher); } +// Key(inner_matcher) matches an std::pair whose 'first' field matches +// inner_matcher. For example, Contains(Key(Ge(5))) can be used to match an +// std::map that contains at least one element whose key is >= 5. +template <typename M> +inline internal::KeyMatcher<M> Key(M inner_matcher) { + return internal::KeyMatcher<M>(inner_matcher); +} + // Returns a predicate that is satisfied by anything that matches the // given matcher. template <typename M> diff --git a/test/gmock-matchers_test.cc b/test/gmock-matchers_test.cc index 3541eef7..052202d7 100644 --- a/test/gmock-matchers_test.cc +++ b/test/gmock-matchers_test.cc @@ -59,6 +59,8 @@ bool SkipPrefix(const char* prefix, const char** pstr); namespace gmock_matchers_test { +using std::map; +using std::multimap; using std::stringstream; using std::tr1::make_tuple; using testing::A; @@ -75,6 +77,7 @@ using testing::FloatEq; using testing::Ge; using testing::Gt; using testing::HasSubstr; +using testing::Key; using testing::Le; using testing::Lt; using testing::MakeMatcher; @@ -850,6 +853,52 @@ TEST(HasSubstrTest, CanDescribeSelf) { EXPECT_EQ("has substring \"foo\\n\\\"\"", Describe(m)); } +TEST(KeyTest, CanDescribeSelf) { + Matcher<const std::pair<std::string, int>&> m = Key("foo"); + EXPECT_EQ("has a key that is equal to \"foo\"", Describe(m)); +} + +TEST(KeyTest, MatchesCorrectly) { + std::pair<int, std::string> p(25, "foo"); + EXPECT_THAT(p, Key(25)); + EXPECT_THAT(p, Not(Key(42))); + EXPECT_THAT(p, Key(Ge(20))); + EXPECT_THAT(p, Not(Key(Lt(25)))); +} + +TEST(KeyTest, SafelyCastsInnerMatcher) { + Matcher<int> is_positive = Gt(0); + Matcher<int> is_negative = Lt(0); + std::pair<char, bool> p('a', true); + EXPECT_THAT(p, Key(is_positive)); + EXPECT_THAT(p, Not(Key(is_negative))); +} + +TEST(KeyTest, InsideContainsUsingMap) { + std::map<int, std::string> container; + container.insert(std::make_pair(1, "foo")); + container.insert(std::make_pair(2, "bar")); + container.insert(std::make_pair(4, "baz")); + EXPECT_THAT(container, Contains(Key(1))); + EXPECT_THAT(container, Not(Contains(Key(3)))); +} + +TEST(KeyTest, InsideContainsUsingMultimap) { + std::multimap<int, std::string> container; + container.insert(std::make_pair(1, "foo")); + container.insert(std::make_pair(2, "bar")); + container.insert(std::make_pair(4, "baz")); + + EXPECT_THAT(container, Not(Contains(Key(25)))); + container.insert(std::make_pair(25, "more foo")); + EXPECT_THAT(container, Contains(Key(25))); + container.insert(std::make_pair(25, "more bar")); + EXPECT_THAT(container, Contains(Key(25))); + + EXPECT_THAT(container, Contains(Key(1))); + EXPECT_THAT(container, Not(Contains(Key(3)))); +} + // Tests StartsWith(s). TEST(StartsWithTest, MatchesStringWithGivenPrefix) { |