summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAbseil Team <absl-team@google.com>2018-12-15 13:11:02 (GMT)
committerMark Barolak <mbar@google.com>2018-12-17 18:53:33 (GMT)
commit1ec20f87e390e1d711e69b69345e68a1fa656bbc (patch)
treee859ddc35cf3d0322e97907b9c6a4b6c0cd5b6a4
parent096fb37a1976bbddde136c9db5fa88ac4332b802 (diff)
downloadgoogletest-1ec20f87e390e1d711e69b69345e68a1fa656bbc.zip
googletest-1ec20f87e390e1d711e69b69345e68a1fa656bbc.tar.gz
googletest-1ec20f87e390e1d711e69b69345e68a1fa656bbc.tar.bz2
Googletest export
Allow container matchers to accept move-only containers. PiperOrigin-RevId: 225667441
-rw-r--r--googlemock/include/gmock/gmock-matchers.h30
-rw-r--r--googlemock/test/gmock-matchers_test.cc107
2 files changed, 121 insertions, 16 deletions
diff --git a/googlemock/include/gmock/gmock-matchers.h b/googlemock/include/gmock/gmock-matchers.h
index 68278be..fa89bd6 100644
--- a/googlemock/include/gmock/gmock-matchers.h
+++ b/googlemock/include/gmock/gmock-matchers.h
@@ -1959,7 +1959,7 @@ class SizeIsMatcher {
template <typename Container>
operator Matcher<Container>() const {
- return MakeMatcher(new Impl<Container>(size_matcher_));
+ return Matcher<Container>(new Impl<const Container&>(size_matcher_));
}
template <typename Container>
@@ -2009,7 +2009,7 @@ class BeginEndDistanceIsMatcher {
template <typename Container>
operator Matcher<Container>() const {
- return MakeMatcher(new Impl<Container>(distance_matcher_));
+ return Matcher<Container>(new Impl<const Container&>(distance_matcher_));
}
template <typename Container>
@@ -2269,7 +2269,8 @@ class PointwiseMatcher {
!IsHashTable<GTEST_REMOVE_REFERENCE_AND_CONST_(LhsContainer)>::value,
use_UnorderedPointwise_with_hash_tables);
- return MakeMatcher(new Impl<LhsContainer>(tuple_matcher_, rhs_));
+ return Matcher<LhsContainer>(
+ new Impl<const LhsContainer&>(tuple_matcher_, rhs_));
}
template <typename LhsContainer>
@@ -2471,7 +2472,8 @@ class ContainsMatcher {
template <typename Container>
operator Matcher<Container>() const {
- return MakeMatcher(new ContainsMatcherImpl<Container>(inner_matcher_));
+ return Matcher<Container>(
+ new ContainsMatcherImpl<const Container&>(inner_matcher_));
}
private:
@@ -2488,7 +2490,8 @@ class EachMatcher {
template <typename Container>
operator Matcher<Container>() const {
- return MakeMatcher(new EachMatcherImpl<Container>(inner_matcher_));
+ return Matcher<Container>(
+ new EachMatcherImpl<const Container&>(inner_matcher_));
}
private:
@@ -3086,8 +3089,10 @@ class UnorderedElementsAreMatcher {
matchers.reserve(::std::tuple_size<MatcherTuple>::value);
TransformTupleValues(CastAndAppendTransform<const Element&>(), matchers_,
::std::back_inserter(matchers));
- return MakeMatcher(new UnorderedElementsAreMatcherImpl<Container>(
- UnorderedMatcherRequire::ExactMatch, matchers.begin(), matchers.end()));
+ return Matcher<Container>(
+ new UnorderedElementsAreMatcherImpl<const Container&>(
+ UnorderedMatcherRequire::ExactMatch, matchers.begin(),
+ matchers.end()));
}
private:
@@ -3116,8 +3121,8 @@ class ElementsAreMatcher {
matchers.reserve(::std::tuple_size<MatcherTuple>::value);
TransformTupleValues(CastAndAppendTransform<const Element&>(), matchers_,
::std::back_inserter(matchers));
- return MakeMatcher(new ElementsAreMatcherImpl<Container>(
- matchers.begin(), matchers.end()));
+ return Matcher<Container>(new ElementsAreMatcherImpl<const Container&>(
+ matchers.begin(), matchers.end()));
}
private:
@@ -3136,8 +3141,9 @@ class UnorderedElementsAreArrayMatcher {
template <typename Container>
operator Matcher<Container>() const {
- return MakeMatcher(new UnorderedElementsAreMatcherImpl<Container>(
- match_flags_, matchers_.begin(), matchers_.end()));
+ return Matcher<Container>(
+ new UnorderedElementsAreMatcherImpl<const Container&>(
+ match_flags_, matchers_.begin(), matchers_.end()));
}
private:
@@ -3160,7 +3166,7 @@ class ElementsAreArrayMatcher {
!IsHashTable<GTEST_REMOVE_REFERENCE_AND_CONST_(Container)>::value,
use_UnorderedElementsAreArray_with_hash_tables);
- return MakeMatcher(new ElementsAreMatcherImpl<Container>(
+ return Matcher<Container>(new ElementsAreMatcherImpl<const Container&>(
matchers_.begin(), matchers_.end()));
}
diff --git a/googlemock/test/gmock-matchers_test.cc b/googlemock/test/gmock-matchers_test.cc
index c1589a4..a722187 100644
--- a/googlemock/test/gmock-matchers_test.cc
+++ b/googlemock/test/gmock-matchers_test.cc
@@ -72,6 +72,7 @@
namespace testing {
namespace gmock_matchers_test {
+namespace {
using std::greater;
using std::less;
@@ -158,6 +159,19 @@ using testing::internal::StreamMatchResultListener;
using testing::internal::string;
using testing::internal::Strings;
+// Helper for testing container-valued matchers in mock method context. It is
+// important to test matchers in this context, since it requires additional type
+// deduction beyond what EXPECT_THAT does, thus making it more restrictive.
+struct ContainerHelper {
+ MOCK_METHOD1(Call, void(std::vector<std::unique_ptr<int>>));
+};
+
+std::vector<std::unique_ptr<int>> MakeUniquePtrs(const std::vector<int>& ints) {
+ std::vector<std::unique_ptr<int>> pointers;
+ for (int i : ints) pointers.emplace_back(new int(i));
+ return pointers;
+}
+
// For testing ExplainMatchResultTo().
class GreaterThanMatcher : public MatcherInterface<int> {
public:
@@ -1679,6 +1693,12 @@ TEST(PairTest, InsideContainsUsingMap) {
EXPECT_THAT(container, Not(Contains(Pair(3, _))));
}
+TEST(ContainsTest, WorksWithMoveOnly) {
+ ContainerHelper helper;
+ EXPECT_CALL(helper, Call(Contains(Pointee(2))));
+ helper.Call(MakeUniquePtrs({1, 2}));
+}
+
#if GTEST_LANG_CXX11
TEST(PairTest, UseGetInsteadOfMembers) {
PairWithGet pair{7, "ABC"};
@@ -4752,6 +4772,12 @@ TEST(IsEmptyTest, ExplainsResult) {
EXPECT_EQ("whose size is 1", Explain(m, container));
}
+TEST(IsEmptyTest, WorksWithMoveOnly) {
+ ContainerHelper helper;
+ EXPECT_CALL(helper, Call(IsEmpty()));
+ helper.Call({});
+}
+
TEST(IsTrueTest, IsTrueIsFalse) {
EXPECT_THAT(true, IsTrue());
EXPECT_THAT(false, IsFalse());
@@ -4822,6 +4848,12 @@ TEST(SizeIsTest, WorksWithReferences) {
EXPECT_THAT(container, m);
}
+TEST(SizeIsTest, WorksWithMoveOnly) {
+ ContainerHelper helper;
+ EXPECT_CALL(helper, Call(SizeIs(3)));
+ helper.Call(MakeUniquePtrs({1, 2, 3}));
+}
+
// SizeIs should work for any type that provides a size() member function.
// For example, a size_type member type should not need to be provided.
struct MinimalistCustomType {
@@ -5308,6 +5340,12 @@ TEST(BeginEndDistanceIsTest, CanDescribeSelf) {
DescribeNegation(m));
}
+TEST(BeginEndDistanceIsTest, WorksWithMoveOnly) {
+ ContainerHelper helper;
+ EXPECT_CALL(helper, Call(BeginEndDistanceIs(2)));
+ helper.Call(MakeUniquePtrs({1, 2}));
+}
+
TEST(BeginEndDistanceIsTest, ExplainsResult) {
Matcher<vector<int> > m1 = BeginEndDistanceIs(2);
Matcher<vector<int> > m2 = BeginEndDistanceIs(Lt(2));
@@ -5477,6 +5515,14 @@ TEST(IsSupersetOfTest, WorksForRhsInitializerList) {
}
#endif
+TEST(IsSupersetOfTest, WorksWithMoveOnly) {
+ ContainerHelper helper;
+ EXPECT_CALL(helper, Call(IsSupersetOf({Pointee(1)})));
+ helper.Call(MakeUniquePtrs({1, 2}));
+ EXPECT_CALL(helper, Call(Not(IsSupersetOf({Pointee(1), Pointee(2)}))));
+ helper.Call(MakeUniquePtrs({2}));
+}
+
TEST(IsSubsetOfTest, WorksForNativeArray) {
const int subset[] = {1, 4};
const int superset[] = {1, 2, 4};
@@ -5599,6 +5645,14 @@ TEST(IsSubsetOfTest, WorksForRhsInitializerList) {
}
#endif
+TEST(IsSubsetOfTest, WorksWithMoveOnly) {
+ ContainerHelper helper;
+ EXPECT_CALL(helper, Call(IsSubsetOf({Pointee(1), Pointee(2)})));
+ helper.Call(MakeUniquePtrs({1}));
+ EXPECT_CALL(helper, Call(Not(IsSubsetOf({Pointee(1)}))));
+ helper.Call(MakeUniquePtrs({2}));
+}
+
// Tests using ElementsAre() and ElementsAreArray() with stream-like
// "containers".
@@ -5632,6 +5686,15 @@ TEST(ElementsAreTest, WorksWithUncopyable) {
EXPECT_THAT(objs, ElementsAre(UncopyableIs(-3), Truly(ValueIsPositive)));
}
+TEST(ElementsAreTest, WorksWithMoveOnly) {
+ ContainerHelper helper;
+ EXPECT_CALL(helper, Call(ElementsAre(Pointee(1), Pointee(2))));
+ helper.Call(MakeUniquePtrs({1, 2}));
+
+ EXPECT_CALL(helper, Call(ElementsAreArray({Pointee(3), Pointee(4)})));
+ helper.Call(MakeUniquePtrs({3, 4}));
+}
+
TEST(ElementsAreTest, TakesStlContainer) {
const int actual[] = {3, 1, 2};
@@ -5735,6 +5798,13 @@ TEST(UnorderedElementsAreArrayTest,
#endif // GTEST_HAS_STD_INITIALIZER_LIST_
+TEST(UnorderedElementsAreArrayTest, WorksWithMoveOnly) {
+ ContainerHelper helper;
+ EXPECT_CALL(helper,
+ Call(UnorderedElementsAreArray({Pointee(1), Pointee(2)})));
+ helper.Call(MakeUniquePtrs({2, 1}));
+}
+
class UnorderedElementsAreTest : public testing::Test {
protected:
typedef std::vector<int> IntVec;
@@ -5782,6 +5852,12 @@ TEST_F(UnorderedElementsAreTest, WorksForStreamlike) {
EXPECT_THAT(s, Not(UnorderedElementsAre(2, 2, 3, 4, 5)));
}
+TEST_F(UnorderedElementsAreTest, WorksWithMoveOnly) {
+ ContainerHelper helper;
+ EXPECT_CALL(helper, Call(UnorderedElementsAre(Pointee(1), Pointee(2))));
+ helper.Call(MakeUniquePtrs({2, 1}));
+}
+
// One naive implementation of the matcher runs in O(N!) time, which is too
// slow for many real-world inputs. This test shows that our matcher can match
// 100 inputs very quickly (a few milliseconds). An O(100!) is 10^158
@@ -6332,6 +6408,12 @@ TEST(EachTest, WorksForNativeArrayAsTuple) {
EXPECT_THAT(std::make_tuple(pointer, 2), Not(Each(Gt(1))));
}
+TEST(EachTest, WorksWithMoveOnly) {
+ ContainerHelper helper;
+ EXPECT_CALL(helper, Call(Each(Pointee(Gt(0)))));
+ helper.Call(MakeUniquePtrs({1, 2}));
+}
+
// For testing Pointwise().
class IsHalfOfMatcher {
public:
@@ -6470,6 +6552,17 @@ TEST(PointwiseTest, AllowsMonomorphicInnerMatcher) {
EXPECT_EQ("", Explain(Pointwise(m2, rhs), lhs));
}
+MATCHER(PointeeEquals, "Points to an equal value") {
+ return ExplainMatchResult(::testing::Pointee(::testing::get<1>(arg)),
+ ::testing::get<0>(arg), result_listener);
+}
+
+TEST(PointwiseTest, WorksWithMoveOnly) {
+ ContainerHelper helper;
+ EXPECT_CALL(helper, Call(Pointwise(PointeeEquals(), std::vector<int>{1, 2})));
+ helper.Call(MakeUniquePtrs({1, 2}));
+}
+
TEST(UnorderedPointwiseTest, DescribesSelf) {
vector<int> rhs;
rhs.push_back(1);
@@ -6584,6 +6677,13 @@ TEST(UnorderedPointwiseTest, AllowsMonomorphicInnerMatcher) {
EXPECT_THAT(lhs, UnorderedPointwise(m2, rhs));
}
+TEST(UnorderedPointwiseTest, WorksWithMoveOnly) {
+ ContainerHelper helper;
+ EXPECT_CALL(helper, Call(UnorderedPointwise(PointeeEquals(),
+ std::vector<int>{1, 2})));
+ helper.Call(MakeUniquePtrs({2, 1}));
+}
+
// Sample optional type implementation with minimal requirements for use with
// Optional matcher.
class SampleOptionalInt {
@@ -6976,8 +7076,7 @@ TEST_F(PredicateFormatterFromMatcherTest, NoShortCircuitOnFailure) {
EXPECT_FALSE(result); // Implicit cast to bool.
std::string expect =
"Value of: dummy-name\nExpected: [DescribeTo]\n"
- " Actual: 1" +
- OfType(kMatcherType) + ", [MatchAndExplain]";
+ " Actual: 1, [MatchAndExplain]";
EXPECT_EQ(expect, result.message());
}
@@ -6988,11 +7087,11 @@ TEST_F(PredicateFormatterFromMatcherTest, DetectsFlakyShortCircuit) {
"Value of: dummy-name\nExpected: [DescribeTo]\n"
" The matcher failed on the initial attempt; but passed when rerun to "
"generate the explanation.\n"
- " Actual: 2" +
- OfType(kMatcherType) + ", [MatchAndExplain]";
+ " Actual: 2, [MatchAndExplain]";
EXPECT_EQ(expect, result.message());
}
+} // namespace
} // namespace gmock_matchers_test
} // namespace testing