diff options
author | Abseil Team <absl-team@google.com> | 2018-12-15 13:11:02 (GMT) |
---|---|---|
committer | Mark Barolak <mbar@google.com> | 2018-12-17 18:53:33 (GMT) |
commit | 1ec20f87e390e1d711e69b69345e68a1fa656bbc (patch) | |
tree | e859ddc35cf3d0322e97907b9c6a4b6c0cd5b6a4 | |
parent | 096fb37a1976bbddde136c9db5fa88ac4332b802 (diff) | |
download | googletest-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.h | 30 | ||||
-rw-r--r-- | googlemock/test/gmock-matchers_test.cc | 107 |
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 |