Introduce a BeginEndDistanceIs matcher for containers such as std::forward_list
which lack a size() member. Also pull in gtest 678.
This commit is contained in:
parent
fc4aa1d718
commit
b6a348862b
@ -2267,6 +2267,67 @@ class SizeIsMatcher {
|
|||||||
GTEST_DISALLOW_ASSIGN_(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
|
// Implements an equality matcher for any STL-style container whose elements
|
||||||
// support ==. This matcher is like Eq(), but its failure explanations provide
|
// 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.
|
// 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);
|
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.
|
// Returns a matcher that matches an equal container.
|
||||||
// This matcher behaves like Eq(), but in the event of mismatch lists the
|
// 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
|
// values that are included in one container but not the other. (Duplicate
|
||||||
|
@ -54,6 +54,10 @@
|
|||||||
#include "gtest/gtest.h"
|
#include "gtest/gtest.h"
|
||||||
#include "gtest/gtest-spi.h"
|
#include "gtest/gtest-spi.h"
|
||||||
|
|
||||||
|
#if GTEST_LANG_CXX11
|
||||||
|
# include <forward_list> // NOLINT
|
||||||
|
#endif
|
||||||
|
|
||||||
namespace testing {
|
namespace testing {
|
||||||
|
|
||||||
namespace internal {
|
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) {
|
TEST(WhenSortedTest, WorksForStreamlike) {
|
||||||
// Streamlike 'container' provides only minimal iterator support.
|
// Streamlike 'container' provides only minimal iterator support.
|
||||||
// Its iterators are tagged with input_iterator_tag.
|
// Its iterators are tagged with input_iterator_tag.
|
||||||
|
Loading…
Reference in New Issue
Block a user