Googletest export
Allow container matchers to accept move-only containers. PiperOrigin-RevId: 225667441
This commit is contained in:
		
				
					committed by
					
						
						Mark Barolak
					
				
			
			
				
	
			
			
			
						parent
						
							096fb37a19
						
					
				
				
					commit
					1ec20f87e3
				
			@@ -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()));
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -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
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user