aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorzhanyong.wan <zhanyong.wan@8415998a-534a-0410-bf83-d39667b30386>2009-07-16 20:26:41 +0000
committerzhanyong.wan <zhanyong.wan@8415998a-534a-0410-bf83-d39667b30386>2009-07-16 20:26:41 +0000
commitb5937dab6969ca4b1d8304cc8939ce16c1fb62e5 (patch)
tree7884617457eb65e7fe7e5b20fc1d150e472b11fa
parent41b9b0b5614588d252d565646ae43e9607d46502 (diff)
downloadgoogletest-b5937dab6969ca4b1d8304cc8939ce16c1fb62e5.tar.gz
googletest-b5937dab6969ca4b1d8304cc8939ce16c1fb62e5.tar.bz2
googletest-b5937dab6969ca4b1d8304cc8939ce16c1fb62e5.zip
Adds the Key() matcher, by Marcus Borger.
-rw-r--r--include/gmock/gmock-matchers.h66
-rw-r--r--test/gmock-matchers_test.cc49
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) {