Implements matchers WhenSorted() and WhenSortedBy(); pulls in gtest r595.
This commit is contained in:
parent
5aa8dd99e2
commit
898725cf47
@ -1970,6 +1970,85 @@ class ContainerEqMatcher {
|
|||||||
GTEST_DISALLOW_ASSIGN_(ContainerEqMatcher);
|
GTEST_DISALLOW_ASSIGN_(ContainerEqMatcher);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// A comparator functor that uses the < operator to compare two values.
|
||||||
|
struct LessComparator {
|
||||||
|
template <typename T, typename U>
|
||||||
|
bool operator()(const T& lhs, const U& rhs) const { return lhs < rhs; }
|
||||||
|
};
|
||||||
|
|
||||||
|
// Implements WhenSortedBy(comparator, container_matcher).
|
||||||
|
template <typename Comparator, typename ContainerMatcher>
|
||||||
|
class WhenSortedByMatcher {
|
||||||
|
public:
|
||||||
|
WhenSortedByMatcher(const Comparator& comparator,
|
||||||
|
const ContainerMatcher& matcher)
|
||||||
|
: comparator_(comparator), matcher_(matcher) {}
|
||||||
|
|
||||||
|
template <typename LhsContainer>
|
||||||
|
operator Matcher<LhsContainer>() const {
|
||||||
|
return MakeMatcher(new Impl<LhsContainer>(comparator_, matcher_));
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename LhsContainer>
|
||||||
|
class Impl : public MatcherInterface<LhsContainer> {
|
||||||
|
public:
|
||||||
|
typedef internal::StlContainerView<
|
||||||
|
GTEST_REMOVE_REFERENCE_AND_CONST_(LhsContainer)> LhsView;
|
||||||
|
typedef typename LhsView::type LhsStlContainer;
|
||||||
|
typedef typename LhsView::const_reference LhsStlContainerReference;
|
||||||
|
typedef typename LhsStlContainer::value_type LhsValue;
|
||||||
|
|
||||||
|
Impl(const Comparator& comparator, const ContainerMatcher& matcher)
|
||||||
|
: comparator_(comparator), matcher_(matcher) {}
|
||||||
|
|
||||||
|
virtual void DescribeTo(::std::ostream* os) const {
|
||||||
|
*os << "(when sorted) ";
|
||||||
|
matcher_.DescribeTo(os);
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void DescribeNegationTo(::std::ostream* os) const {
|
||||||
|
*os << "(when sorted) ";
|
||||||
|
matcher_.DescribeNegationTo(os);
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual bool MatchAndExplain(LhsContainer lhs,
|
||||||
|
MatchResultListener* listener) const {
|
||||||
|
LhsStlContainerReference lhs_stl_container = LhsView::ConstReference(lhs);
|
||||||
|
std::vector<LhsValue> sorted_container(lhs_stl_container.begin(),
|
||||||
|
lhs_stl_container.end());
|
||||||
|
std::sort(sorted_container.begin(), sorted_container.end(), comparator_);
|
||||||
|
|
||||||
|
if (!listener->IsInterested()) {
|
||||||
|
// If the listener is not interested, we do not need to
|
||||||
|
// construct the inner explanation.
|
||||||
|
return matcher_.Matches(sorted_container);
|
||||||
|
}
|
||||||
|
|
||||||
|
*listener << "which is ";
|
||||||
|
UniversalPrint(sorted_container, listener->stream());
|
||||||
|
*listener << " when sorted";
|
||||||
|
|
||||||
|
StringMatchResultListener inner_listener;
|
||||||
|
const bool match = matcher_.MatchAndExplain(sorted_container,
|
||||||
|
&inner_listener);
|
||||||
|
PrintIfNotEmpty(inner_listener.str(), listener->stream());
|
||||||
|
return match;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
const Comparator comparator_;
|
||||||
|
const Matcher<const std::vector<LhsValue>&> matcher_;
|
||||||
|
|
||||||
|
GTEST_DISALLOW_COPY_AND_ASSIGN_(Impl);
|
||||||
|
};
|
||||||
|
|
||||||
|
private:
|
||||||
|
const Comparator comparator_;
|
||||||
|
const ContainerMatcher matcher_;
|
||||||
|
|
||||||
|
GTEST_DISALLOW_ASSIGN_(WhenSortedByMatcher);
|
||||||
|
};
|
||||||
|
|
||||||
// Implements Pointwise(tuple_matcher, rhs_container). tuple_matcher
|
// Implements Pointwise(tuple_matcher, rhs_container). tuple_matcher
|
||||||
// must be able to be safely cast to Matcher<tuple<const T1&, const
|
// must be able to be safely cast to Matcher<tuple<const T1&, const
|
||||||
// T2&> >, where T1 and T2 are the types of elements in the LHS
|
// T2&> >, where T1 and T2 are the types of elements in the LHS
|
||||||
@ -2930,6 +3009,26 @@ inline PolymorphicMatcher<internal::ContainerEqMatcher< // NOLINT
|
|||||||
internal::ContainerEqMatcher<RawContainer>(rhs));
|
internal::ContainerEqMatcher<RawContainer>(rhs));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Returns a matcher that matches a container that, when sorted using
|
||||||
|
// the given comparator, matches container_matcher.
|
||||||
|
template <typename Comparator, typename ContainerMatcher>
|
||||||
|
inline internal::WhenSortedByMatcher<Comparator, ContainerMatcher>
|
||||||
|
WhenSortedBy(const Comparator& comparator,
|
||||||
|
const ContainerMatcher& container_matcher) {
|
||||||
|
return internal::WhenSortedByMatcher<Comparator, ContainerMatcher>(
|
||||||
|
comparator, container_matcher);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Returns a matcher that matches a container that, when sorted using
|
||||||
|
// the < operator, matches container_matcher.
|
||||||
|
template <typename ContainerMatcher>
|
||||||
|
inline internal::WhenSortedByMatcher<internal::LessComparator, ContainerMatcher>
|
||||||
|
WhenSorted(const ContainerMatcher& container_matcher) {
|
||||||
|
return
|
||||||
|
internal::WhenSortedByMatcher<internal::LessComparator, ContainerMatcher>(
|
||||||
|
internal::LessComparator(), container_matcher);
|
||||||
|
}
|
||||||
|
|
||||||
// Matches an STL-style container or a native array that contains the
|
// Matches an STL-style container or a native array that contains the
|
||||||
// same number of elements as in rhs, where its i-th element and rhs's
|
// same number of elements as in rhs, where its i-th element and rhs's
|
||||||
// i-th element (as a pair) satisfy the given pair matcher, for all i.
|
// i-th element (as a pair) satisfy the given pair matcher, for all i.
|
||||||
|
@ -57,6 +57,8 @@ GTEST_API_ string JoinAsTuple(const Strings& fields);
|
|||||||
|
|
||||||
namespace gmock_matchers_test {
|
namespace gmock_matchers_test {
|
||||||
|
|
||||||
|
using std::greater;
|
||||||
|
using std::less;
|
||||||
using std::list;
|
using std::list;
|
||||||
using std::make_pair;
|
using std::make_pair;
|
||||||
using std::map;
|
using std::map;
|
||||||
@ -118,6 +120,8 @@ using testing::StrNe;
|
|||||||
using testing::Truly;
|
using testing::Truly;
|
||||||
using testing::TypedEq;
|
using testing::TypedEq;
|
||||||
using testing::Value;
|
using testing::Value;
|
||||||
|
using testing::WhenSorted;
|
||||||
|
using testing::WhenSortedBy;
|
||||||
using testing::_;
|
using testing::_;
|
||||||
using testing::internal::DummyMatchResultListener;
|
using testing::internal::DummyMatchResultListener;
|
||||||
using testing::internal::ExplainMatchFailureTupleTo;
|
using testing::internal::ExplainMatchFailureTupleTo;
|
||||||
@ -3725,6 +3729,83 @@ TEST(ContainerEqExtraTest, CopiesNativeArrayParameter) {
|
|||||||
EXPECT_THAT(a1, m);
|
EXPECT_THAT(a1, m);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST(WhenSortedByTest, WorksForEmptyContainer) {
|
||||||
|
const vector<int> numbers;
|
||||||
|
EXPECT_THAT(numbers, WhenSortedBy(less<int>(), ElementsAre()));
|
||||||
|
EXPECT_THAT(numbers, Not(WhenSortedBy(less<int>(), ElementsAre(1))));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(WhenSortedByTest, WorksForNonEmptyContainer) {
|
||||||
|
vector<unsigned> numbers;
|
||||||
|
numbers.push_back(3);
|
||||||
|
numbers.push_back(1);
|
||||||
|
numbers.push_back(2);
|
||||||
|
numbers.push_back(2);
|
||||||
|
EXPECT_THAT(numbers, WhenSortedBy(greater<unsigned>(),
|
||||||
|
ElementsAre(3, 2, 2, 1)));
|
||||||
|
EXPECT_THAT(numbers, Not(WhenSortedBy(greater<unsigned>(),
|
||||||
|
ElementsAre(1, 2, 2, 3))));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(WhenSortedByTest, WorksForNonVectorContainer) {
|
||||||
|
list<string> words;
|
||||||
|
words.push_back("say");
|
||||||
|
words.push_back("hello");
|
||||||
|
words.push_back("world");
|
||||||
|
EXPECT_THAT(words, WhenSortedBy(less<string>(),
|
||||||
|
ElementsAre("hello", "say", "world")));
|
||||||
|
EXPECT_THAT(words, Not(WhenSortedBy(less<string>(),
|
||||||
|
ElementsAre("say", "hello", "world"))));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(WhenSortedByTest, WorksForNativeArray) {
|
||||||
|
const int numbers[] = { 1, 3, 2, 4 };
|
||||||
|
const int sorted_numbers[] = { 1, 2, 3, 4 };
|
||||||
|
EXPECT_THAT(numbers, WhenSortedBy(less<int>(), ElementsAre(1, 2, 3, 4)));
|
||||||
|
EXPECT_THAT(numbers, WhenSortedBy(less<int>(),
|
||||||
|
ElementsAreArray(sorted_numbers)));
|
||||||
|
EXPECT_THAT(numbers, Not(WhenSortedBy(less<int>(), ElementsAre(1, 3, 2, 4))));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(WhenSortedByTest, CanDescribeSelf) {
|
||||||
|
const Matcher<vector<int> > m = WhenSortedBy(less<int>(), ElementsAre(1, 2));
|
||||||
|
EXPECT_EQ("(when sorted) has 2 elements where\n"
|
||||||
|
"element #0 is equal to 1,\n"
|
||||||
|
"element #1 is equal to 2",
|
||||||
|
Describe(m));
|
||||||
|
EXPECT_EQ("(when sorted) doesn't have 2 elements, or\n"
|
||||||
|
"element #0 isn't equal to 1, or\n"
|
||||||
|
"element #1 isn't equal to 2",
|
||||||
|
DescribeNegation(m));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(WhenSortedByTest, ExplainsMatchResult) {
|
||||||
|
const int a[] = { 2, 1 };
|
||||||
|
EXPECT_EQ("which is { 1, 2 } when sorted, whose element #0 doesn't match",
|
||||||
|
Explain(WhenSortedBy(less<int>(), ElementsAre(2, 3)), a));
|
||||||
|
EXPECT_EQ("which is { 1, 2 } when sorted",
|
||||||
|
Explain(WhenSortedBy(less<int>(), ElementsAre(1, 2)), a));
|
||||||
|
}
|
||||||
|
|
||||||
|
// WhenSorted() is a simple wrapper on WhenSortedBy(). Hence we don't
|
||||||
|
// need to test it as exhaustively as we test the latter.
|
||||||
|
|
||||||
|
TEST(WhenSortedTest, WorksForEmptyContainer) {
|
||||||
|
const vector<int> numbers;
|
||||||
|
EXPECT_THAT(numbers, WhenSorted(ElementsAre()));
|
||||||
|
EXPECT_THAT(numbers, Not(WhenSorted(ElementsAre(1))));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(WhenSortedTest, WorksForNonEmptyContainer) {
|
||||||
|
list<string> words;
|
||||||
|
words.push_back("3");
|
||||||
|
words.push_back("1");
|
||||||
|
words.push_back("2");
|
||||||
|
words.push_back("2");
|
||||||
|
EXPECT_THAT(words, WhenSorted(ElementsAre("1", "2", "2", "3")));
|
||||||
|
EXPECT_THAT(words, Not(WhenSorted(ElementsAre("3", "1", "2", "2"))));
|
||||||
|
}
|
||||||
|
|
||||||
// Tests IsReadableTypeName().
|
// Tests IsReadableTypeName().
|
||||||
|
|
||||||
TEST(IsReadableTypeNameTest, ReturnsTrueForShortNames) {
|
TEST(IsReadableTypeNameTest, ReturnsTrueForShortNames) {
|
||||||
|
Loading…
Reference in New Issue
Block a user