aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorkosak <kosak@google.com>2014-03-12 21:06:46 +0000
committerkosak <kosak@google.com>2014-03-12 21:06:46 +0000
commitb6a348862b3ef745ae4c43117b67c7c6f877cd7e (patch)
treeaa975d6abafd31007eec8e2b0b6947ae9d86fbf7
parentfc4aa1d7188322dc0ad28f2b43b9002d67e86a24 (diff)
downloadgoogletest-b6a348862b3ef745ae4c43117b67c7c6f877cd7e.tar.gz
googletest-b6a348862b3ef745ae4c43117b67c7c6f877cd7e.tar.bz2
googletest-b6a348862b3ef745ae4c43117b67c7c6f877cd7e.zip
Introduce a BeginEndDistanceIs matcher for containers such as std::forward_list
which lack a size() member. Also pull in gtest 678.
-rw-r--r--include/gmock/gmock-matchers.h72
-rw-r--r--test/gmock-matchers_test.cc61
2 files changed, 133 insertions, 0 deletions
diff --git a/include/gmock/gmock-matchers.h b/include/gmock/gmock-matchers.h
index 5e2a8d5c..de966a7a 100644
--- a/include/gmock/gmock-matchers.h
+++ b/include/gmock/gmock-matchers.h
@@ -2267,6 +2267,67 @@ class SizeIsMatcher {
GTEST_DISALLOW_ASSIGN_(SizeIsMatcher);
};
+// Implements a matcher that checks the begin()..end() distance of an STL-style
+// container.
+template <typename DistanceMatcher>
+class BeginEndDistanceIsMatcher {
+ public:
+ explicit BeginEndDistanceIsMatcher(const DistanceMatcher& distance_matcher)
+ : distance_matcher_(distance_matcher) {}
+
+ template <typename Container>
+ operator Matcher<Container>() const {
+ return MakeMatcher(new Impl<Container>(distance_matcher_));
+ }
+
+ template <typename Container>
+ class Impl : public MatcherInterface<Container> {
+ public:
+ typedef internal::StlContainerView<
+ GTEST_REMOVE_REFERENCE_AND_CONST_(Container)> ContainerView;
+ typedef typename std::iterator_traits<
+ typename ContainerView::type::const_iterator>::difference_type
+ DistanceType;
+ explicit Impl(const DistanceMatcher& distance_matcher)
+ : distance_matcher_(MatcherCast<DistanceType>(distance_matcher)) {}
+
+ virtual void DescribeTo(::std::ostream* os) const {
+ *os << "distance between begin() and end() ";
+ distance_matcher_.DescribeTo(os);
+ }
+ virtual void DescribeNegationTo(::std::ostream* os) const {
+ *os << "distance between begin() and end() ";
+ distance_matcher_.DescribeNegationTo(os);
+ }
+
+ virtual bool MatchAndExplain(Container container,
+ MatchResultListener* listener) const {
+#if GTEST_LANG_CXX11
+ using std::begin;
+ using std::end;
+ DistanceType distance = std::distance(begin(container), end(container));
+#else
+ DistanceType distance = std::distance(container.begin(), container.end());
+#endif
+ StringMatchResultListener distance_listener;
+ const bool result =
+ distance_matcher_.MatchAndExplain(distance, &distance_listener);
+ *listener << "whose distance between begin() and end() " << distance
+ << (result ? " matches" : " doesn't match");
+ PrintIfNotEmpty(distance_listener.str(), listener->stream());
+ return result;
+ }
+
+ private:
+ const Matcher<DistanceType> distance_matcher_;
+ GTEST_DISALLOW_ASSIGN_(Impl);
+ };
+
+ private:
+ const DistanceMatcher distance_matcher_;
+ GTEST_DISALLOW_ASSIGN_(BeginEndDistanceIsMatcher);
+};
+
// Implements an equality matcher for any STL-style container whose elements
// support ==. This matcher is like Eq(), but its failure explanations provide
// more detailed information that is useful when the container is used as a set.
@@ -3799,6 +3860,17 @@ SizeIs(const SizeMatcher& size_matcher) {
return internal::SizeIsMatcher<SizeMatcher>(size_matcher);
}
+// Returns a matcher that matches the distance between the container's begin()
+// iterator and its end() iterator, i.e. the size of the container. This matcher
+// can be used instead of SizeIs with containers such as std::forward_list which
+// do not implement size(). The container must provide const_iterator (with
+// valid iterator_traits), begin() and end().
+template <typename DistanceMatcher>
+inline internal::BeginEndDistanceIsMatcher<DistanceMatcher>
+BeginEndDistanceIs(const DistanceMatcher& distance_matcher) {
+ return internal::BeginEndDistanceIsMatcher<DistanceMatcher>(distance_matcher);
+}
+
// Returns a matcher that matches an equal container.
// This matcher behaves like Eq(), but in the event of mismatch lists the
// values that are included in one container but not the other. (Duplicate
diff --git a/test/gmock-matchers_test.cc b/test/gmock-matchers_test.cc
index 2a5cf908..bd20add2 100644
--- a/test/gmock-matchers_test.cc
+++ b/test/gmock-matchers_test.cc
@@ -54,6 +54,10 @@
#include "gtest/gtest.h"
#include "gtest/gtest-spi.h"
+#if GTEST_LANG_CXX11
+# include <forward_list> // NOLINT
+#endif
+
namespace testing {
namespace internal {
@@ -4419,6 +4423,63 @@ TEST(StreamlikeTest, Iteration) {
}
}
+#if GTEST_LANG_CXX11
+TEST(BeginEndDistanceIsTest, WorksWithForwardList) {
+ std::forward_list<int> container;
+ EXPECT_THAT(container, BeginEndDistanceIs(0));
+ EXPECT_THAT(container, Not(BeginEndDistanceIs(1)));
+ container.push_front(0);
+ EXPECT_THAT(container, Not(BeginEndDistanceIs(0)));
+ EXPECT_THAT(container, BeginEndDistanceIs(1));
+ container.push_front(0);
+ EXPECT_THAT(container, Not(BeginEndDistanceIs(0)));
+ EXPECT_THAT(container, BeginEndDistanceIs(2));
+}
+#endif // GTEST_LANG_CXX11
+
+TEST(BeginEndDistanceIsTest, WorksWithNonStdList) {
+ const int a[5] = { 1, 2, 3, 4, 5 };
+ Streamlike<int> s(a, a + 5);
+ EXPECT_THAT(s, BeginEndDistanceIs(5));
+}
+
+TEST(BeginEndDistanceIsTest, CanDescribeSelf) {
+ Matcher<vector<int> > m = BeginEndDistanceIs(2);
+ EXPECT_EQ("distance between begin() and end() is equal to 2", Describe(m));
+ EXPECT_EQ("distance between begin() and end() isn't equal to 2",
+ DescribeNegation(m));
+}
+
+TEST(BeginEndDistanceIsTest, ExplainsResult) {
+ Matcher<vector<int> > m1 = BeginEndDistanceIs(2);
+ Matcher<vector<int> > m2 = BeginEndDistanceIs(Lt(2));
+ Matcher<vector<int> > m3 = BeginEndDistanceIs(AnyOf(0, 3));
+ Matcher<vector<int> > m4 = BeginEndDistanceIs(GreaterThan(1));
+ vector<int> container;
+ EXPECT_EQ("whose distance between begin() and end() 0 doesn't match",
+ Explain(m1, container));
+ EXPECT_EQ("whose distance between begin() and end() 0 matches",
+ Explain(m2, container));
+ EXPECT_EQ("whose distance between begin() and end() 0 matches",
+ Explain(m3, container));
+ EXPECT_EQ(
+ "whose distance between begin() and end() 0 doesn't match, which is 1 "
+ "less than 1",
+ Explain(m4, container));
+ container.push_back(0);
+ container.push_back(0);
+ EXPECT_EQ("whose distance between begin() and end() 2 matches",
+ Explain(m1, container));
+ EXPECT_EQ("whose distance between begin() and end() 2 doesn't match",
+ Explain(m2, container));
+ EXPECT_EQ("whose distance between begin() and end() 2 doesn't match",
+ Explain(m3, container));
+ EXPECT_EQ(
+ "whose distance between begin() and end() 2 matches, which is 1 more "
+ "than 1",
+ Explain(m4, container));
+}
+
TEST(WhenSortedTest, WorksForStreamlike) {
// Streamlike 'container' provides only minimal iterator support.
// Its iterators are tagged with input_iterator_tag.