aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorzhanyong.wan <zhanyong.wan@8415998a-534a-0410-bf83-d39667b30386>2010-04-22 23:37:47 +0000
committerzhanyong.wan <zhanyong.wan@8415998a-534a-0410-bf83-d39667b30386>2010-04-22 23:37:47 +0000
commit33605ba45417979cff7254c1196dfee65a7275b3 (patch)
tree605e5164cedef35af498c6bab63c750951d35216
parent090c4830ddf39c0468f607f0d6b629ac6b4b0e4e (diff)
downloadgoogletest-33605ba45417979cff7254c1196dfee65a7275b3.tar.gz
googletest-33605ba45417979cff7254c1196dfee65a7275b3.tar.bz2
googletest-33605ba45417979cff7254c1196dfee65a7275b3.zip
Adds Each(m) (by Wojtek Moczydlowski); removes scripts/test/Makefile (by Zhanyong Wan); pulls in gtest r424.
-rw-r--r--Makefile.am4
-rw-r--r--include/gmock/gmock-matchers.h144
-rw-r--r--scripts/test/Makefile57
-rw-r--r--test/gmock-matchers_test.cc102
4 files changed, 219 insertions, 88 deletions
diff --git a/Makefile.am b/Makefile.am
index 8e9b61c3..f0aa5c5c 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -137,9 +137,7 @@ EXTRA_DIST += include/gmock/gmock-generated-actions.h.pump \
include/gmock/internal/gmock-generated-internal-utils.h.pump
# Script for fusing Google Mock and Google Test source files.
-EXTRA_DIST += \
- scripts/fuse_gmock_files.py \
- scripts/test/Makefile
+EXTRA_DIST += scripts/fuse_gmock_files.py
# The Google Mock Generator tool from the cppclean project.
EXTRA_DIST += \
diff --git a/include/gmock/gmock-matchers.h b/include/gmock/gmock-matchers.h
index 66efecd4..7ca2f007 100644
--- a/include/gmock/gmock-matchers.h
+++ b/include/gmock/gmock-matchers.h
@@ -1947,9 +1947,9 @@ class ContainerEqMatcher {
GTEST_DISALLOW_ASSIGN_(ContainerEqMatcher);
};
-// Implements Contains(element_matcher) for the given argument type Container.
+// Holds the logic common to ContainsMatcherImpl and EachMatcherImpl.
template <typename Container>
-class ContainsMatcherImpl : public MatcherInterface<Container> {
+class QuantifierMatcherImpl : public MatcherInterface<Container> {
public:
typedef GMOCK_REMOVE_CONST_(GMOCK_REMOVE_REFERENCE_(Container)) RawContainer;
typedef StlContainerView<RawContainer> View;
@@ -1958,44 +1958,97 @@ class ContainsMatcherImpl : public MatcherInterface<Container> {
typedef typename StlContainer::value_type Element;
template <typename InnerMatcher>
- explicit ContainsMatcherImpl(InnerMatcher inner_matcher)
+ explicit QuantifierMatcherImpl(InnerMatcher inner_matcher)
: inner_matcher_(
- testing::SafeMatcherCast<const Element&>(inner_matcher)) {}
+ testing::SafeMatcherCast<const Element&>(inner_matcher)) {}
+
+ // Checks whether:
+ // * All elements in the container match, if all_elements_should_match.
+ // * Any element in the container matches, if !all_elements_should_match.
+ bool MatchAndExplainImpl(bool all_elements_should_match,
+ Container container,
+ MatchResultListener* listener) const {
+ StlContainerReference stl_container = View::ConstReference(container);
+ size_t i = 0;
+ for (typename StlContainer::const_iterator it = stl_container.begin();
+ it != stl_container.end(); ++it, ++i) {
+ StringMatchResultListener inner_listener;
+ const bool matches = inner_matcher_.MatchAndExplain(*it, &inner_listener);
+
+ if (matches != all_elements_should_match) {
+ *listener << "whose element #" << i
+ << (matches ? " matches" : " doesn't match");
+ PrintIfNotEmpty(inner_listener.str(), listener->stream());
+ return !all_elements_should_match;
+ }
+ }
+ return all_elements_should_match;
+ }
+
+ protected:
+ const Matcher<const Element&> inner_matcher_;
+
+ GTEST_DISALLOW_ASSIGN_(QuantifierMatcherImpl);
+};
+
+// Implements Contains(element_matcher) for the given argument type Container.
+// Symmetric to EachMatcherImpl.
+template <typename Container>
+class ContainsMatcherImpl : public QuantifierMatcherImpl<Container> {
+ public:
+ template <typename InnerMatcher>
+ explicit ContainsMatcherImpl(InnerMatcher inner_matcher)
+ : QuantifierMatcherImpl<Container>(inner_matcher) {}
// Describes what this matcher does.
virtual void DescribeTo(::std::ostream* os) const {
*os << "contains at least one element that ";
- inner_matcher_.DescribeTo(os);
+ this->inner_matcher_.DescribeTo(os);
}
- // Describes what the negation of this matcher does.
virtual void DescribeNegationTo(::std::ostream* os) const {
*os << "doesn't contain any element that ";
- inner_matcher_.DescribeTo(os);
+ this->inner_matcher_.DescribeTo(os);
}
virtual bool MatchAndExplain(Container container,
MatchResultListener* listener) const {
- StlContainerReference stl_container = View::ConstReference(container);
- size_t i = 0;
- for (typename StlContainer::const_iterator it = stl_container.begin();
- it != stl_container.end(); ++it, ++i) {
- StringMatchResultListener inner_listener;
- if (inner_matcher_.MatchAndExplain(*it, &inner_listener)) {
- *listener << "whose element #" << i << " matches";
- PrintIfNotEmpty(inner_listener.str(), listener->stream());
- return true;
- }
- }
- return false;
+ return this->MatchAndExplainImpl(false, container, listener);
}
private:
- const Matcher<const Element&> inner_matcher_;
-
GTEST_DISALLOW_ASSIGN_(ContainsMatcherImpl);
};
+// Implements Each(element_matcher) for the given argument type Container.
+// Symmetric to ContainsMatcherImpl.
+template <typename Container>
+class EachMatcherImpl : public QuantifierMatcherImpl<Container> {
+ public:
+ template <typename InnerMatcher>
+ explicit EachMatcherImpl(InnerMatcher inner_matcher)
+ : QuantifierMatcherImpl<Container>(inner_matcher) {}
+
+ // Describes what this matcher does.
+ virtual void DescribeTo(::std::ostream* os) const {
+ *os << "only contains elements that ";
+ this->inner_matcher_.DescribeTo(os);
+ }
+
+ virtual void DescribeNegationTo(::std::ostream* os) const {
+ *os << "contains some element that ";
+ this->inner_matcher_.DescribeNegationTo(os);
+ }
+
+ virtual bool MatchAndExplain(Container container,
+ MatchResultListener* listener) const {
+ return this->MatchAndExplainImpl(true, container, listener);
+ }
+
+ private:
+ GTEST_DISALLOW_ASSIGN_(EachMatcherImpl);
+};
+
// Implements polymorphic Contains(element_matcher).
template <typename M>
class ContainsMatcher {
@@ -2013,6 +2066,23 @@ class ContainsMatcher {
GTEST_DISALLOW_ASSIGN_(ContainsMatcher);
};
+// Implements polymorphic Each(element_matcher).
+template <typename M>
+class EachMatcher {
+ public:
+ explicit EachMatcher(M m) : inner_matcher_(m) {}
+
+ template <typename Container>
+ operator Matcher<Container>() const {
+ return MakeMatcher(new EachMatcherImpl<Container>(inner_matcher_));
+ }
+
+ private:
+ const M inner_matcher_;
+
+ GTEST_DISALLOW_ASSIGN_(EachMatcher);
+};
+
// 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
@@ -2855,6 +2925,38 @@ inline internal::ContainsMatcher<M> Contains(M matcher) {
return internal::ContainsMatcher<M>(matcher);
}
+// Matches an STL-style container or a native array that contains only
+// elements matching the given value or matcher.
+//
+// Each(m) is semantically equivalent to Not(Contains(Not(m))). Only
+// the messages are different.
+//
+// Examples:
+// ::std::set<int> page_ids;
+// // Each(m) matches an empty container, regardless of what m is.
+// EXPECT_THAT(page_ids, Each(Eq(1)));
+// EXPECT_THAT(page_ids, Each(Eq(77)));
+//
+// page_ids.insert(3);
+// EXPECT_THAT(page_ids, Each(Gt(0)));
+// EXPECT_THAT(page_ids, Not(Each(Gt(4))));
+// page_ids.insert(1);
+// EXPECT_THAT(page_ids, Not(Each(Lt(2))));
+//
+// ::std::map<int, size_t> page_lengths;
+// page_lengths[1] = 100;
+// page_lengths[2] = 200;
+// page_lengths[3] = 300;
+// EXPECT_THAT(page_lengths, Not(Each(Pair(1, 100))));
+// EXPECT_THAT(page_lengths, Each(Key(Le(3))));
+//
+// const char* user_ids[] = { "joe", "mike", "tom" };
+// EXPECT_THAT(user_ids, Not(Each(Eq(::std::string("tom")))));
+template <typename M>
+inline internal::EachMatcher<M> Each(M matcher) {
+ return internal::EachMatcher<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.
diff --git a/scripts/test/Makefile b/scripts/test/Makefile
deleted file mode 100644
index 8edaea06..00000000
--- a/scripts/test/Makefile
+++ /dev/null
@@ -1,57 +0,0 @@
-# A Makefile for fusing Google Mock and building a sample test against it.
-#
-# SYNOPSIS:
-#
-# make [all] - makes everything.
-# make TARGET - makes the given target.
-# make check - makes everything and runs the built sample test.
-# make clean - removes all files generated by make.
-
-# Points to the root of fused Google Mock, relative to where this file is.
-FUSED_GMOCK_DIR = output
-
-# Paths to the fused gmock files.
-FUSED_GTEST_H = $(FUSED_GMOCK_DIR)/gtest/gtest.h
-FUSED_GMOCK_H = $(FUSED_GMOCK_DIR)/gmock/gmock.h
-FUSED_GMOCK_GTEST_ALL_CC = $(FUSED_GMOCK_DIR)/gmock-gtest-all.cc
-
-# Where to find the gmock_test.cc.
-GMOCK_TEST_CC = ../../test/gmock_test.cc
-
-# Where to find gmock_main.cc.
-GMOCK_MAIN_CC = ../../src/gmock_main.cc
-
-# Flags passed to the preprocessor.
-CPPFLAGS += -I$(FUSED_GMOCK_DIR)
-
-# Flags passed to the C++ compiler.
-CXXFLAGS += -g
-
-all : gmock_test
-
-check : all
- ./gmock_test
-
-clean :
- rm -rf $(FUSED_GMOCK_DIR) gmock_test *.o
-
-$(FUSED_GTEST_H) :
- ../fuse_gmock_files.py $(FUSED_GMOCK_DIR)
-
-$(FUSED_GMOCK_H) :
- ../fuse_gmock_files.py $(FUSED_GMOCK_DIR)
-
-$(FUSED_GMOCK_GTEST_ALL_CC) :
- ../fuse_gmock_files.py $(FUSED_GMOCK_DIR)
-
-gmock-gtest-all.o : $(FUSED_GTEST_H) $(FUSED_GMOCK_H) $(FUSED_GMOCK_GTEST_ALL_CC)
- $(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(FUSED_GMOCK_GTEST_ALL_CC)
-
-gmock_main.o : $(FUSED_GTEST_H) $(FUSED_GMOCK_H) $(GMOCK_MAIN_CC)
- $(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(GMOCK_MAIN_CC)
-
-gmock_test.o : $(FUSED_GTEST_H) $(FUSED_GMOCK_H) $(GMOCK_TEST_CC)
- $(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(GMOCK_TEST_CC)
-
-gmock_test : gmock_test.o gmock-gtest-all.o gmock_main.o
- $(CXX) $(CPPFLAGS) $(CXXFLAGS) $^ -o $@
diff --git a/test/gmock-matchers_test.cc b/test/gmock-matchers_test.cc
index 6d784f16..a7c217d4 100644
--- a/test/gmock-matchers_test.cc
+++ b/test/gmock-matchers_test.cc
@@ -65,8 +65,10 @@ using std::make_pair;
using std::map;
using std::multimap;
using std::pair;
+using std::set;
using std::stringstream;
using std::tr1::make_tuple;
+using std::vector;
using testing::A;
using testing::AllArgs;
using testing::AllOf;
@@ -363,20 +365,20 @@ TEST(MakeMatcherTest, ConstructsMatcherFromMatcherInterface) {
// Tests that MakePolymorphicMatcher() can construct a polymorphic
// matcher from its implementation using the old API.
-const int bar = 1;
+const int g_bar = 1;
class ReferencesBarOrIsZeroImpl {
public:
template <typename T>
bool MatchAndExplain(const T& x,
MatchResultListener* /* listener */) const {
const void* p = &x;
- return p == &bar || x == 0;
+ return p == &g_bar || x == 0;
}
- void DescribeTo(::std::ostream* os) const { *os << "bar or zero"; }
+ void DescribeTo(::std::ostream* os) const { *os << "g_bar or zero"; }
void DescribeNegationTo(::std::ostream* os) const {
- *os << "doesn't reference bar and is not zero";
+ *os << "doesn't reference g_bar and is not zero";
}
};
@@ -391,15 +393,15 @@ TEST(MakePolymorphicMatcherTest, ConstructsMatcherUsingOldAPI) {
Matcher<const int&> m1 = ReferencesBarOrIsZero();
EXPECT_TRUE(m1.Matches(0));
// Verifies that the identity of a by-reference argument is preserved.
- EXPECT_TRUE(m1.Matches(bar));
+ EXPECT_TRUE(m1.Matches(g_bar));
EXPECT_FALSE(m1.Matches(1));
- EXPECT_EQ("bar or zero", Describe(m1));
+ EXPECT_EQ("g_bar or zero", Describe(m1));
// Using a polymorphic matcher to match a value type.
Matcher<double> m2 = ReferencesBarOrIsZero();
EXPECT_TRUE(m2.Matches(0.0));
EXPECT_FALSE(m2.Matches(0.1));
- EXPECT_EQ("bar or zero", Describe(m2));
+ EXPECT_EQ("g_bar or zero", Describe(m2));
}
// Tests implementing a polymorphic matcher using MatchAndExplain().
@@ -3984,5 +3986,91 @@ TEST(MatcherTupleTest, ExplainsMatchFailure) {
// explanation.
}
+// Tests Each().
+
+TEST(EachTest, ExplainsMatchResultCorrectly) {
+ set<int> a; // empty
+
+ Matcher<set<int> > m = Each(2);
+ EXPECT_EQ("", Explain(m, a));
+
+ Matcher<const int(&)[1]> n = Each(1);
+
+ const int b[1] = { 1 };
+ EXPECT_EQ("", Explain(n, b));
+
+ n = Each(3);
+ EXPECT_EQ("whose element #0 doesn't match", Explain(n, b));
+
+ a.insert(1);
+ a.insert(2);
+ a.insert(3);
+ m = Each(GreaterThan(0));
+ EXPECT_EQ("", Explain(m, a));
+
+ m = Each(GreaterThan(10));
+ EXPECT_EQ("whose element #0 doesn't match, which is 9 less than 10",
+ Explain(m, a));
+}
+
+TEST(EachTest, DescribesItselfCorrectly) {
+ Matcher<vector<int> > m = Each(1);
+ EXPECT_EQ("only contains elements that is equal to 1", Describe(m));
+
+ Matcher<vector<int> > m2 = Not(m);
+ EXPECT_EQ("contains some element that isn't equal to 1", Describe(m2));
+}
+
+TEST(EachTest, MatchesVectorWhenAllElementsMatch) {
+ vector<int> some_vector;
+ EXPECT_THAT(some_vector, Each(1));
+ some_vector.push_back(3);
+ EXPECT_THAT(some_vector, Not(Each(1)));
+ EXPECT_THAT(some_vector, Each(3));
+ some_vector.push_back(1);
+ some_vector.push_back(2);
+ EXPECT_THAT(some_vector, Not(Each(3)));
+ EXPECT_THAT(some_vector, Each(Lt(3.5)));
+
+ vector<string> another_vector;
+ another_vector.push_back("fee");
+ EXPECT_THAT(another_vector, Each(string("fee")));
+ another_vector.push_back("fie");
+ another_vector.push_back("foe");
+ another_vector.push_back("fum");
+ EXPECT_THAT(another_vector, Not(Each(string("fee"))));
+}
+
+TEST(EachTest, MatchesMapWhenAllElementsMatch) {
+ map<const char*, int> my_map;
+ const char* bar = "a string";
+ my_map[bar] = 2;
+ EXPECT_THAT(my_map, Each(make_pair(bar, 2)));
+
+ map<string, int> another_map;
+ EXPECT_THAT(another_map, Each(make_pair(string("fee"), 1)));
+ another_map["fee"] = 1;
+ EXPECT_THAT(another_map, Each(make_pair(string("fee"), 1)));
+ another_map["fie"] = 2;
+ another_map["foe"] = 3;
+ another_map["fum"] = 4;
+ EXPECT_THAT(another_map, Not(Each(make_pair(string("fee"), 1))));
+ EXPECT_THAT(another_map, Not(Each(make_pair(string("fum"), 1))));
+ EXPECT_THAT(another_map, Each(Pair(_, Gt(0))));
+}
+
+TEST(EachTest, AcceptsMatcher) {
+ const int a[] = { 1, 2, 3 };
+ EXPECT_THAT(a, Each(Gt(0)));
+ EXPECT_THAT(a, Not(Each(Gt(1))));
+}
+
+TEST(EachTest, WorksForNativeArrayAsTuple) {
+ const int a[] = { 1, 2 };
+ const int* const pointer = a;
+ EXPECT_THAT(make_tuple(pointer, 2), Each(Gt(0)));
+ EXPECT_THAT(make_tuple(pointer, 2), Not(Each(Gt(1))));
+}
+
} // namespace gmock_matchers_test
} // namespace testing