Commit 2336e9c1 authored by kosak's avatar kosak
Browse files

Defines the UnorderedPointwise(m, container) matcher, which is like...

Defines the UnorderedPointwise(m, container) matcher, which is like Pointwise(m, container) but ignores the order of the elements.
parent 06678924
......@@ -3430,6 +3430,81 @@ class ElementsAreArrayMatcher {
GTEST_DISALLOW_ASSIGN_(ElementsAreArrayMatcher);
};
// Given a 2-tuple matcher tm of type Tuple2Matcher and a value second
// of type Second, BoundSecondMatcher<Tuple2Matcher, Second>(tm,
// second) is a polymorphic matcher that matches a value x iff tm
// matches tuple (x, second). Useful for implementing
// UnorderedPointwise() in terms of UnorderedElementsAreArray().
//
// BoundSecondMatcher is copyable and assignable, as we need to put
// instances of this class in a vector when implementing
// UnorderedPointwise().
template <typename Tuple2Matcher, typename Second>
class BoundSecondMatcher {
public:
BoundSecondMatcher(const Tuple2Matcher& tm, const Second& second)
: tuple2_matcher_(tm), second_value_(second) {}
template <typename T>
operator Matcher<T>() const {
return MakeMatcher(new Impl<T>(tuple2_matcher_, second_value_));
}
// We have to define this for UnorderedPointwise() to compile in
// C++98 mode, as it puts BoundSecondMatcher instances in a vector,
// which requires the elements to be assignable in C++98. The
// compiler cannot generate the operator= for us, as Tuple2Matcher
// and Second may not be assignable.
//
// However, this should never be called, so the implementation just
// need to assert.
void operator=(const BoundSecondMatcher& /*rhs*/) {
GTEST_LOG_(FATAL) << "BoundSecondMatcher should never be assigned.";
}
private:
template <typename T>
class Impl : public MatcherInterface<T> {
public:
typedef ::testing::tuple<T, Second> ArgTuple;
Impl(const Tuple2Matcher& tm, const Second& second)
: mono_tuple2_matcher_(SafeMatcherCast<const ArgTuple&>(tm)),
second_value_(second) {}
virtual void DescribeTo(::std::ostream* os) const {
*os << "and ";
UniversalPrint(second_value_, os);
*os << " ";
mono_tuple2_matcher_.DescribeTo(os);
}
virtual bool MatchAndExplain(T x, MatchResultListener* listener) const {
return mono_tuple2_matcher_.MatchAndExplain(ArgTuple(x, second_value_),
listener);
}
private:
const Matcher<const ArgTuple&> mono_tuple2_matcher_;
const Second second_value_;
GTEST_DISALLOW_ASSIGN_(Impl);
};
const Tuple2Matcher tuple2_matcher_;
const Second second_value_;
};
// Given a 2-tuple matcher tm and a value second,
// MatcherBindSecond(tm, second) returns a matcher that matches a
// value x iff tm matches tuple (x, second). Useful for implementing
// UnorderedPointwise() in terms of UnorderedElementsAreArray().
template <typename Tuple2Matcher, typename Second>
BoundSecondMatcher<Tuple2Matcher, Second> MatcherBindSecond(
const Tuple2Matcher& tm, const Second& second) {
return BoundSecondMatcher<Tuple2Matcher, Second>(tm, second);
}
// Returns the description for a matcher defined using the MATCHER*()
// macro where the user-supplied description string is "", if
// 'negation' is false; otherwise returns the description of the
......@@ -4002,12 +4077,80 @@ inline internal::PointwiseMatcher<TupleMatcher,
GTEST_REMOVE_CONST_(Container)>
Pointwise(const TupleMatcher& tuple_matcher, const Container& rhs) {
// This following line is for working around a bug in MSVC 8.0,
// which causes Container to be a const type sometimes.
// which causes Container to be a const type sometimes (e.g. when
// rhs is a const int[])..
typedef GTEST_REMOVE_CONST_(Container) RawContainer;
return internal::PointwiseMatcher<TupleMatcher, RawContainer>(
tuple_matcher, rhs);
}
#if GTEST_HAS_STD_INITIALIZER_LIST_
// Supports the Pointwise(m, {a, b, c}) syntax.
template <typename TupleMatcher, typename T>
inline internal::PointwiseMatcher<TupleMatcher, std::vector<T> > Pointwise(
const TupleMatcher& tuple_matcher, std::initializer_list<T> rhs) {
return Pointwise(tuple_matcher, std::vector<T>(rhs));
}
#endif // GTEST_HAS_STD_INITIALIZER_LIST_
// UnorderedPointwise(pair_matcher, rhs) matches an STL-style
// container or a native array that contains the same number of
// elements as in rhs, where in some permutation of the container, its
// i-th element and rhs's i-th element (as a pair) satisfy the given
// pair matcher, for all i. Tuple2Matcher 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 container and the RHS container
// respectively.
//
// This is like Pointwise(pair_matcher, rhs), except that the element
// order doesn't matter.
template <typename Tuple2Matcher, typename RhsContainer>
inline internal::UnorderedElementsAreArrayMatcher<
typename internal::BoundSecondMatcher<
Tuple2Matcher, typename internal::StlContainerView<GTEST_REMOVE_CONST_(
RhsContainer)>::type::value_type> >
UnorderedPointwise(const Tuple2Matcher& tuple2_matcher,
const RhsContainer& rhs_container) {
// This following line is for working around a bug in MSVC 8.0,
// which causes RhsContainer to be a const type sometimes (e.g. when
// rhs_container is a const int[]).
typedef GTEST_REMOVE_CONST_(RhsContainer) RawRhsContainer;
// RhsView allows the same code to handle RhsContainer being a
// STL-style container and it being a native C-style array.
typedef typename internal::StlContainerView<RawRhsContainer> RhsView;
typedef typename RhsView::type RhsStlContainer;
typedef typename RhsStlContainer::value_type Second;
const RhsStlContainer& rhs_stl_container =
RhsView::ConstReference(rhs_container);
// Create a matcher for each element in rhs_container.
::std::vector<internal::BoundSecondMatcher<Tuple2Matcher, Second> > matchers;
for (typename RhsStlContainer::const_iterator it = rhs_stl_container.begin();
it != rhs_stl_container.end(); ++it) {
matchers.push_back(
internal::MatcherBindSecond(tuple2_matcher, *it));
}
// Delegate the work to UnorderedElementsAreArray().
return UnorderedElementsAreArray(matchers);
}
#if GTEST_HAS_STD_INITIALIZER_LIST_
// Supports the UnorderedPointwise(m, {a, b, c}) syntax.
template <typename Tuple2Matcher, typename T>
inline internal::UnorderedElementsAreArrayMatcher<
typename internal::BoundSecondMatcher<Tuple2Matcher, T> >
UnorderedPointwise(const Tuple2Matcher& tuple2_matcher,
std::initializer_list<T> rhs) {
return UnorderedPointwise(tuple2_matcher, std::vector<T>(rhs));
}
#endif // GTEST_HAS_STD_INITIALIZER_LIST_
// Matches an STL-style container or a native array that contains at
// least one element matching the given value or matcher.
//
......
......@@ -77,9 +77,6 @@ using std::ostream;
using std::pair;
using std::set;
using std::stringstream;
using testing::get;
using testing::make_tuple;
using testing::tuple;
using std::vector;
using testing::A;
using testing::AllArgs;
......@@ -128,17 +125,19 @@ using testing::Ref;
using testing::ResultOf;
using testing::SizeIs;
using testing::StartsWith;
using testing::StringMatchResultListener;
using testing::StrCaseEq;
using testing::StrCaseNe;
using testing::StrEq;
using testing::StrNe;
using testing::StringMatchResultListener;
using testing::Truly;
using testing::TypedEq;
using testing::UnorderedPointwise;
using testing::Value;
using testing::WhenSorted;
using testing::WhenSortedBy;
using testing::_;
using testing::get;
using testing::internal::DummyMatchResultListener;
using testing::internal::ElementMatcherPair;
using testing::internal::ElementMatcherPairs;
......@@ -154,6 +153,8 @@ using testing::internal::Strings;
using testing::internal::linked_ptr;
using testing::internal::scoped_ptr;
using testing::internal::string;
using testing::make_tuple;
using testing::tuple;
// For testing ExplainMatchResultTo().
class GreaterThanMatcher : public MatcherInterface<int> {
......@@ -4272,18 +4273,18 @@ TEST(ContainerEqExtraTest, WorksForMaps) {
}
TEST(ContainerEqExtraTest, WorksForNativeArray) {
int a1[] = { 1, 2, 3 };
int a2[] = { 1, 2, 3 };
int b[] = { 1, 2, 4 };
int a1[] = {1, 2, 3};
int a2[] = {1, 2, 3};
int b[] = {1, 2, 4};
EXPECT_THAT(a1, ContainerEq(a2));
EXPECT_THAT(a1, Not(ContainerEq(b)));
}
TEST(ContainerEqExtraTest, WorksForTwoDimensionalNativeArray) {
const char a1[][3] = { "hi", "lo" };
const char a2[][3] = { "hi", "lo" };
const char b[][3] = { "lo", "hi" };
const char a1[][3] = {"hi", "lo"};
const char a2[][3] = {"hi", "lo"};
const char b[][3] = {"lo", "hi"};
// Tests using ContainerEq() in the first dimension.
EXPECT_THAT(a1, ContainerEq(a2));
......@@ -4295,27 +4296,27 @@ TEST(ContainerEqExtraTest, WorksForTwoDimensionalNativeArray) {
}
TEST(ContainerEqExtraTest, WorksForNativeArrayAsTuple) {
const int a1[] = { 1, 2, 3 };
const int a2[] = { 1, 2, 3 };
const int b[] = { 1, 2, 3, 4 };
const int a1[] = {1, 2, 3};
const int a2[] = {1, 2, 3};
const int b[] = {1, 2, 3, 4};
const int* const p1 = a1;
EXPECT_THAT(make_tuple(p1, 3), ContainerEq(a2));
EXPECT_THAT(make_tuple(p1, 3), Not(ContainerEq(b)));
const int c[] = { 1, 3, 2 };
const int c[] = {1, 3, 2};
EXPECT_THAT(make_tuple(p1, 3), Not(ContainerEq(c)));
}
TEST(ContainerEqExtraTest, CopiesNativeArrayParameter) {
std::string a1[][3] = {
{ "hi", "hello", "ciao" },
{ "bye", "see you", "ciao" }
{"hi", "hello", "ciao"},
{"bye", "see you", "ciao"}
};
std::string a2[][3] = {
{ "hi", "hello", "ciao" },
{ "bye", "see you", "ciao" }
{"hi", "hello", "ciao"},
{"bye", "see you", "ciao"}
};
const Matcher<const std::string(&)[2][3]> m = ContainerEq(a2);
......@@ -4355,8 +4356,8 @@ TEST(WhenSortedByTest, WorksForNonVectorContainer) {
}
TEST(WhenSortedByTest, WorksForNativeArray) {
const int numbers[] = { 1, 3, 2, 4 };
const int sorted_numbers[] = { 1, 2, 3, 4 };
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)));
......@@ -4376,7 +4377,7 @@ TEST(WhenSortedByTest, CanDescribeSelf) {
}
TEST(WhenSortedByTest, ExplainsMatchResult) {
const int a[] = { 2, 1 };
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",
......@@ -4534,7 +4535,7 @@ class Streamlike {
};
TEST(StreamlikeTest, Iteration) {
const int a[5] = { 2, 1, 4, 5, 3 };
const int a[5] = {2, 1, 4, 5, 3};
Streamlike<int> s(a, a + 5);
Streamlike<int>::const_iterator it = s.begin();
const int* ip = a;
......@@ -4559,7 +4560,7 @@ TEST(BeginEndDistanceIsTest, WorksWithForwardList) {
#endif // GTEST_LANG_CXX11
TEST(BeginEndDistanceIsTest, WorksWithNonStdList) {
const int a[5] = { 1, 2, 3, 4, 5 };
const int a[5] = {1, 2, 3, 4, 5};
Streamlike<int> s(a, a + 5);
EXPECT_THAT(s, BeginEndDistanceIs(5));
}
......@@ -4604,14 +4605,14 @@ TEST(BeginEndDistanceIsTest, ExplainsResult) {
TEST(WhenSortedTest, WorksForStreamlike) {
// Streamlike 'container' provides only minimal iterator support.
// Its iterators are tagged with input_iterator_tag.
const int a[5] = { 2, 1, 4, 5, 3 };
const int a[5] = {2, 1, 4, 5, 3};
Streamlike<int> s(a, a + GTEST_ARRAY_SIZE_(a));
EXPECT_THAT(s, WhenSorted(ElementsAre(1, 2, 3, 4, 5)));
EXPECT_THAT(s, Not(WhenSorted(ElementsAre(2, 1, 4, 5, 3))));
}
TEST(WhenSortedTest, WorksForVectorConstRefMatcherOnStreamlike) {
const int a[] = { 2, 1, 4, 5, 3 };
const int a[] = {2, 1, 4, 5, 3};
Streamlike<int> s(a, a + GTEST_ARRAY_SIZE_(a));
Matcher<const std::vector<int>&> vector_match = ElementsAre(1, 2, 3, 4, 5);
EXPECT_THAT(s, WhenSorted(vector_match));
......@@ -4622,14 +4623,14 @@ TEST(WhenSortedTest, WorksForVectorConstRefMatcherOnStreamlike) {
// "containers".
TEST(ElemensAreStreamTest, WorksForStreamlike) {
const int a[5] = { 1, 2, 3, 4, 5 };
const int a[5] = {1, 2, 3, 4, 5};
Streamlike<int> s(a, a + GTEST_ARRAY_SIZE_(a));
EXPECT_THAT(s, ElementsAre(1, 2, 3, 4, 5));
EXPECT_THAT(s, Not(ElementsAre(2, 1, 4, 5, 3)));
}
TEST(ElemensAreArrayStreamTest, WorksForStreamlike) {
const int a[5] = { 1, 2, 3, 4, 5 };
const int a[5] = {1, 2, 3, 4, 5};
Streamlike<int> s(a, a + GTEST_ARRAY_SIZE_(a));
vector<int> expected;
......@@ -4667,7 +4668,7 @@ TEST(ElementsAreTest, TakesStlContainer) {
// Tests for UnorderedElementsAreArray()
TEST(UnorderedElementsAreArrayTest, SucceedsWhenExpected) {
const int a[] = { 0, 1, 2, 3, 4 };
const int a[] = {0, 1, 2, 3, 4};
std::vector<int> s(a, a + GTEST_ARRAY_SIZE_(a));
do {
StringMatchResultListener listener;
......@@ -4677,8 +4678,8 @@ TEST(UnorderedElementsAreArrayTest, SucceedsWhenExpected) {
}
TEST(UnorderedElementsAreArrayTest, VectorBool) {
const bool a[] = { 0, 1, 0, 1, 1 };
const bool b[] = { 1, 0, 1, 1, 0 };
const bool a[] = {0, 1, 0, 1, 1};
const bool b[] = {1, 0, 1, 1, 0};
std::vector<bool> expected(a, a + GTEST_ARRAY_SIZE_(a));
std::vector<bool> actual(b, b + GTEST_ARRAY_SIZE_(b));
StringMatchResultListener listener;
......@@ -4690,7 +4691,7 @@ TEST(UnorderedElementsAreArrayTest, WorksForStreamlike) {
// Streamlike 'container' provides only minimal iterator support.
// Its iterators are tagged with input_iterator_tag, and it has no
// size() or empty() methods.
const int a[5] = { 2, 1, 4, 5, 3 };
const int a[5] = {2, 1, 4, 5, 3};
Streamlike<int> s(a, a + GTEST_ARRAY_SIZE_(a));
::std::vector<int> expected;
......@@ -4721,35 +4722,35 @@ TEST(UnorderedElementsAreArrayTest, TakesStlContainer) {
#if GTEST_HAS_STD_INITIALIZER_LIST_
TEST(UnorderedElementsAreArrayTest, TakesInitializerList) {
const int a[5] = { 2, 1, 4, 5, 3 };
EXPECT_THAT(a, UnorderedElementsAreArray({ 1, 2, 3, 4, 5 }));
EXPECT_THAT(a, Not(UnorderedElementsAreArray({ 1, 2, 3, 4, 6 })));
const int a[5] = {2, 1, 4, 5, 3};
EXPECT_THAT(a, UnorderedElementsAreArray({1, 2, 3, 4, 5}));
EXPECT_THAT(a, Not(UnorderedElementsAreArray({1, 2, 3, 4, 6})));
}
TEST(UnorderedElementsAreArrayTest, TakesInitializerListOfCStrings) {
const string a[5] = { "a", "b", "c", "d", "e" };
EXPECT_THAT(a, UnorderedElementsAreArray({ "a", "b", "c", "d", "e" }));
EXPECT_THAT(a, Not(UnorderedElementsAreArray({ "a", "b", "c", "d", "ef" })));
const string a[5] = {"a", "b", "c", "d", "e"};
EXPECT_THAT(a, UnorderedElementsAreArray({"a", "b", "c", "d", "e"}));
EXPECT_THAT(a, Not(UnorderedElementsAreArray({"a", "b", "c", "d", "ef"})));
}
TEST(UnorderedElementsAreArrayTest, TakesInitializerListOfSameTypedMatchers) {
const int a[5] = { 2, 1, 4, 5, 3 };
const int a[5] = {2, 1, 4, 5, 3};
EXPECT_THAT(a, UnorderedElementsAreArray(
{ Eq(1), Eq(2), Eq(3), Eq(4), Eq(5) }));
{Eq(1), Eq(2), Eq(3), Eq(4), Eq(5)}));
EXPECT_THAT(a, Not(UnorderedElementsAreArray(
{ Eq(1), Eq(2), Eq(3), Eq(4), Eq(6) })));
{Eq(1), Eq(2), Eq(3), Eq(4), Eq(6)})));
}
TEST(UnorderedElementsAreArrayTest,
TakesInitializerListOfDifferentTypedMatchers) {
const int a[5] = { 2, 1, 4, 5, 3 };
const int a[5] = {2, 1, 4, 5, 3};
// The compiler cannot infer the type of the initializer list if its
// elements have different types. We must explicitly specify the
// unified element type in this case.
EXPECT_THAT(a, UnorderedElementsAreArray<Matcher<int> >(
{ Eq(1), Ne(-2), Ge(3), Le(4), Eq(5) }));
{Eq(1), Ne(-2), Ge(3), Le(4), Eq(5)}));
EXPECT_THAT(a, Not(UnorderedElementsAreArray<Matcher<int> >(
{ Eq(1), Ne(-2), Ge(3), Le(4), Eq(6) })));
{Eq(1), Ne(-2), Ge(3), Le(4), Eq(6)})));
}
#endif // GTEST_HAS_STD_INITIALIZER_LIST_
......@@ -4768,7 +4769,7 @@ TEST_F(UnorderedElementsAreTest, WorksWithUncopyable) {
}
TEST_F(UnorderedElementsAreTest, SucceedsWhenExpected) {
const int a[] = { 1, 2, 3 };
const int a[] = {1, 2, 3};
std::vector<int> s(a, a + GTEST_ARRAY_SIZE_(a));
do {
StringMatchResultListener listener;
......@@ -4778,7 +4779,7 @@ TEST_F(UnorderedElementsAreTest, SucceedsWhenExpected) {
}
TEST_F(UnorderedElementsAreTest, FailsWhenAnElementMatchesNoMatcher) {
const int a[] = { 1, 2, 3 };
const int a[] = {1, 2, 3};
std::vector<int> s(a, a + GTEST_ARRAY_SIZE_(a));
std::vector<Matcher<int> > mv;
mv.push_back(1);
......@@ -4794,7 +4795,7 @@ TEST_F(UnorderedElementsAreTest, WorksForStreamlike) {
// Streamlike 'container' provides only minimal iterator support.
// Its iterators are tagged with input_iterator_tag, and it has no
// size() or empty() methods.
const int a[5] = { 2, 1, 4, 5, 3 };
const int a[5] = {2, 1, 4, 5, 3};
Streamlike<int> s(a, a + GTEST_ARRAY_SIZE_(a));
EXPECT_THAT(s, UnorderedElementsAre(1, 2, 3, 4, 5));
......@@ -5105,7 +5106,7 @@ TEST_F(BipartiteNonSquareTest, SimpleBacktracking) {
// :.......:
// 0 1 2
MatchMatrix g(4, 3);
static const int kEdges[][2] = { {0, 2}, {1, 1}, {2, 1}, {3, 0} };
static const int kEdges[][2] = {{0, 2}, {1, 1}, {2, 1}, {3, 0}};
for (size_t i = 0; i < GTEST_ARRAY_SIZE_(kEdges); ++i) {
g.SetEdge(kEdges[i][0], kEdges[i][1], true);
}
......@@ -5209,17 +5210,17 @@ TEST(JoinAsTupleTest, JoinsEmptyTuple) {
}
TEST(JoinAsTupleTest, JoinsOneTuple) {
const char* fields[] = { "1" };
const char* fields[] = {"1"};
EXPECT_EQ("1", JoinAsTuple(Strings(fields, fields + 1)));
}
TEST(JoinAsTupleTest, JoinsTwoTuple) {
const char* fields[] = { "1", "a" };
const char* fields[] = {"1", "a"};
EXPECT_EQ("(1, a)", JoinAsTuple(Strings(fields, fields + 2)));
}
TEST(JoinAsTupleTest, JoinsTenTuple) {
const char* fields[] = { "1", "2", "3", "4", "5", "6", "7", "8", "9", "10" };
const char* fields[] = {"1", "2", "3", "4", "5", "6", "7", "8", "9", "10"};
EXPECT_EQ("(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)",
JoinAsTuple(Strings(fields, fields + 10)));
}
......@@ -5232,12 +5233,12 @@ TEST(FormatMatcherDescriptionTest, WorksForEmptyDescription) {
EXPECT_EQ("not (is even)",
FormatMatcherDescription(true, "IsEven", Strings()));
const char* params[] = { "5" };
const char* params[] = {"5"};
EXPECT_EQ("equals 5",
FormatMatcherDescription(false, "Equals",
Strings(params, params + 1)));
const char* params2[] = { "5", "8" };
const char* params2[] = {"5", "8"};
EXPECT_EQ("is in range (5, 8)",
FormatMatcherDescription(false, "IsInRange",
Strings(params2, params2 + 2)));
......@@ -5294,7 +5295,7 @@ TEST(EachTest, ExplainsMatchResultCorrectly) {
Matcher<const int(&)[1]> n = Each(1); // NOLINT
const int b[1] = { 1 };
const int b[1] = {1};
EXPECT_EQ("", Explain(n, b));
n = Each(3);
......@@ -5358,13 +5359,13 @@ TEST(EachTest, MatchesMapWhenAllElementsMatch) {
}
TEST(EachTest, AcceptsMatcher) {
const int a[] = { 1, 2, 3 };
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 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))));
......@@ -5418,7 +5419,7 @@ TEST(PointwiseTest, MakesCopyOfRhs) {
rhs.push_back(2);
rhs.push_back(4);
int lhs[] = { 1, 2 };
int lhs[] = {1, 2};
const Matcher<const int (&)[2]> m = Pointwise(IsHalfOf(), rhs);
EXPECT_THAT(lhs, m);
......@@ -5428,7 +5429,7 @@ TEST(PointwiseTest, MakesCopyOfRhs) {
}
TEST(PointwiseTest, WorksForLhsNativeArray) {
const int lhs[] = { 1, 2, 3 };
const int lhs[] = {1, 2, 3};
vector<int> rhs;
rhs.push_back(2);
rhs.push_back(4);
......@@ -5438,7 +5439,7 @@ TEST(PointwiseTest, WorksForLhsNativeArray) {
}
TEST(PointwiseTest, WorksForRhsNativeArray) {
const int rhs[] = { 1, 2, 3 };
const int rhs[] = {1, 2, 3};
vector<int> lhs;
lhs.push_back(2);
lhs.push_back(4);
......@@ -5447,20 +5448,30 @@ TEST(PointwiseTest, WorksForRhsNativeArray) {
EXPECT_THAT(lhs, Not(Pointwise(Lt(), rhs)));
}
#if GTEST_HAS_STD_INITIALIZER_LIST_
TEST(PointwiseTest, WorksForRhsInitializerList) {
const vector<int> lhs{2, 4, 6};
EXPECT_THAT(lhs, Pointwise(Gt(), {1, 2, 3}));
EXPECT_THAT(lhs, Not(Pointwise(Lt(), {3, 3, 7})));
}
#endif // GTEST_HAS_STD_INITIALIZER_LIST_
TEST(PointwiseTest, RejectsWrongSize) {
const double lhs[2] = { 1, 2 };
const int rhs[1] = { 0 };
const double lhs[2] = {1, 2};
const int rhs[1] = {0};
EXPECT_THAT(lhs, Not(Pointwise(Gt(), rhs)));
EXPECT_EQ("which contains 2 values",
Explain(Pointwise(Gt(), rhs), lhs));
const int rhs2[3] = { 0, 1, 2 };
const int rhs2[3] = {0, 1, 2};
EXPECT_THAT(lhs, Not(Pointwise(Gt(), rhs2)));
}
TEST(PointwiseTest, RejectsWrongContent) {
const double lhs[3] = { 1, 2, 3 };
const int rhs[3] = { 2, 6, 4 };
const double lhs[3] = {1, 2, 3};
const int rhs[3] = {2, 6, 4};
EXPECT_THAT(lhs, Not(Pointwise(IsHalfOf(), rhs)));
EXPECT_EQ("where the value pair (2, 6) at index #1 don't match, "
"where the second/2 is 3",
......@@ -5468,15 +5479,15 @@ TEST(PointwiseTest, RejectsWrongContent) {
}
TEST(PointwiseTest, AcceptsCorrectContent) {
const double lhs[3] = { 1, 2, 3 };
const int rhs[3] = { 2, 4, 6 };
const double lhs[3] = {1, 2, 3};
const int rhs[3] = {2, 4, 6};
EXPECT_THAT(lhs, Pointwise(IsHalfOf(), rhs));
EXPECT_EQ("", Explain(Pointwise(IsHalfOf(), rhs), lhs));
}
TEST(PointwiseTest, AllowsMonomorphicInnerMatcher) {
const double lhs[3] = { 1, 2, 3 };
const int rhs[3] = { 2, 4, 6 };
const double lhs[3] = {1, 2, 3};
const int rhs[3] = {2, 4, 6};
const Matcher<tuple<const double&, const int&> > m1 = IsHalfOf();
EXPECT_THAT(lhs, Pointwise(m1, rhs));
EXPECT_EQ("", Explain(Pointwise(m1, rhs), lhs));
......@@ -5488,5 +5499,119 @@ TEST(PointwiseTest, AllowsMonomorphicInnerMatcher) {
EXPECT_EQ("", Explain(Pointwise(m2, rhs), lhs));
}
TEST(UnorderedPointwiseTest, DescribesSelf) {
vector<int> rhs;
rhs.push_back(1);
rhs.push_back(2);
rhs.push_back(3);
const Matcher<const vector<int>&> m = UnorderedPointwise(IsHalfOf(), rhs);
EXPECT_EQ(
"has 3 elements and there exists some permutation of elements such "
"that:\n"
" - element #0 and 1 are a pair where the first is half of the second, "
"and\n"
" - element #1 and 2 are a pair where the first is half of the second, "
"and\n"
" - element #2 and 3 are a pair where the first is half of the second",
Describe(m));
EXPECT_EQ(
"doesn't have 3 elements, or there exists no permutation of elements "
"such that:\n"
" - element #0 and 1 are a pair where the first is half of the second, "
"and\n"
" - element #1 and 2 are a pair where the first is half of the second, "
"and\n"
" - element #2 and 3 are a pair where the first is half of the second",
DescribeNegation(m));
}
TEST(UnorderedPointwiseTest, MakesCopyOfRhs) {
list<signed char> rhs;
rhs.push_back(2);
rhs.push_back(4);
int lhs[] = {2, 1};
const Matcher<const int (&)[2]> m = UnorderedPointwise(IsHalfOf(), rhs);
EXPECT_THAT(lhs, m);
// Changing rhs now shouldn't affect m, which made a copy of rhs.
rhs.push_back(6);
EXPECT_THAT(lhs, m);
}
TEST(UnorderedPointwiseTest, WorksForLhsNativeArray) {
const int lhs[] = {1, 2, 3};
vector<int> rhs;
rhs.push_back(4);
rhs.push_back(6);
rhs.push_back(2);
EXPECT_THAT(lhs, UnorderedPointwise(Lt(), rhs));
EXPECT_THAT(lhs, Not(UnorderedPointwise(Gt(), rhs)));
}
TEST(UnorderedPointwiseTest, WorksForRhsNativeArray) {
const int rhs[] = {1, 2, 3};
vector<int> lhs;
lhs.push_back(4);
lhs.push_back(2);
lhs.push_back(6);
EXPECT_THAT(lhs, UnorderedPointwise(Gt(), rhs));
EXPECT_THAT(lhs, Not(UnorderedPointwise(Lt(), rhs)));
}
#if GTEST_HAS_STD_INITIALIZER_LIST_
TEST(UnorderedPointwiseTest, WorksForRhsInitializerList) {
const vector<int> lhs{2, 4, 6};
EXPECT_THAT(lhs, UnorderedPointwise(Gt(), {5, 1, 3}));
EXPECT_THAT(lhs, Not(UnorderedPointwise(Lt(), {1, 1, 7})));
}
#endif // GTEST_HAS_STD_INITIALIZER_LIST_
TEST(UnorderedPointwiseTest, RejectsWrongSize) {
const double lhs[2] = {1, 2};
const int rhs[1] = {0};
EXPECT_THAT(lhs, Not(UnorderedPointwise(Gt(), rhs)));
EXPECT_EQ("which has 2 elements",
Explain(UnorderedPointwise(Gt(), rhs), lhs));
const int rhs2[3] = {0, 1, 2};
EXPECT_THAT(lhs, Not(UnorderedPointwise(Gt(), rhs2)));
}
TEST(UnorderedPointwiseTest, RejectsWrongContent) {
const double lhs[3] = {1, 2, 3};
const int rhs[3] = {2, 6, 6};
EXPECT_THAT(lhs, Not(UnorderedPointwise(IsHalfOf(), rhs)));
EXPECT_EQ("where the following elements don't match any matchers:\n"
"element #1: 2",
Explain(UnorderedPointwise(IsHalfOf(), rhs), lhs));
}
TEST(UnorderedPointwiseTest, AcceptsCorrectContentInSameOrder) {
const double lhs[3] = {1, 2, 3};
const int rhs[3] = {2, 4, 6};
EXPECT_THAT(lhs, UnorderedPointwise(IsHalfOf(), rhs));
}
TEST(UnorderedPointwiseTest, AcceptsCorrectContentInDifferentOrder) {
const double lhs[3] = {1, 2, 3};
const int rhs[3] = {6, 4, 2};
EXPECT_THAT(lhs, UnorderedPointwise(IsHalfOf(), rhs));
}
TEST(UnorderedPointwiseTest, AllowsMonomorphicInnerMatcher) {
const double lhs[3] = {1, 2, 3};
const int rhs[3] = {4, 6, 2};
const Matcher<tuple<const double&, const int&> > m1 = IsHalfOf();
EXPECT_THAT(lhs, UnorderedPointwise(m1, rhs));
// This type works as a tuple<const double&, const int&> can be
// implicitly cast to tuple<double, int>.
const Matcher<tuple<double, int> > m2 = IsHalfOf();
EXPECT_THAT(lhs, UnorderedPointwise(m2, rhs));
}
} // namespace gmock_matchers_test
} // namespace testing
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment