`UnorderedElementsAre()`: Allow matching containers where `end` is a [sentinel](https://en.cppreference.com/cpp/iterator/sentinel_for). `ElementsAre` already supports that. PiperOrigin-RevId: 971869110 Change-Id: I1316463fbd0b532bdf5d636d47165aace84b3801
diff --git a/googlemock/include/gmock/gmock-matchers.h b/googlemock/include/gmock/gmock-matchers.h index 9caee1d..800b767 100644 --- a/googlemock/include/gmock/gmock-matchers.h +++ b/googlemock/include/gmock/gmock-matchers.h
@@ -3971,8 +3971,8 @@ } private: - template <typename ElementIter> - MatchMatrix AnalyzeElements(ElementIter elem_first, ElementIter elem_last, + template <typename ElementIter, typename ElementIterEnd> + MatchMatrix AnalyzeElements(ElementIter elem_first, ElementIterEnd elem_last, ::std::vector<std::string>* element_printouts, MatchResultListener* listener) const { element_printouts->clear();
diff --git a/googlemock/test/gmock-matchers-containers_test.cc b/googlemock/test/gmock-matchers-containers_test.cc index 697509f..e7969a0 100644 --- a/googlemock/test/gmock-matchers-containers_test.cc +++ b/googlemock/test/gmock-matchers-containers_test.cc
@@ -78,6 +78,52 @@ INSTANTIATE_GTEST_MATCHER_TEST_P(ElementsAreTest); +// A range of decreasing, positive integers. +class DecreasingIntRange { + public: + explicit DecreasingIntRange(int start) : v_(start) {} + + struct Sentinel {}; + + class Iterator { + public: + using difference_type = std::ptrdiff_t; + using value_type = int; + using iterator_category = std::input_iterator_tag; + using pointer = void; + using reference = int; + + explicit Iterator(int v) : v_(v) {} + + int operator*() const { return v_; } + + Iterator& operator++() { + --v_; + return *this; + } + Iterator operator++(int) { + auto tmp = *this; + ++*this; + return tmp; + } + + bool operator==(const Iterator& other) const { return v_ == other.v_; } + bool operator!=(const Iterator& other) const { return v_ != other.v_; } + + bool operator==(const Sentinel&) const { return v_ < 0; } + bool operator!=(const Sentinel&) const { return v_ >= 0; } + + private: + int v_; + }; + + Iterator begin() const { return Iterator(v_); } + Sentinel end() const { return Sentinel{}; } + + private: + int v_; +}; + // Tests the variadic version of the ElementsAreMatcher TEST(ElementsAreTest, HugeMatcher) { vector<int> test_vector{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12}; @@ -87,6 +133,13 @@ Eq(8), Eq(9), Eq(10), Gt(1), Eq(12))); } +// Tests ElementsAreMatcher with a range that uses a sentinel. +TEST(ElementsAreTest, HugeMatcherSentinel) { + DecreasingIntRange range(3); + + EXPECT_THAT(range, ElementsAre(Eq(3), Eq(2), Eq(1), Eq(0))); +} + // Tests the variadic version of the UnorderedElementsAreMatcher TEST(ElementsAreTest, HugeMatcherStr) { vector<std::string> test_vector{ @@ -105,6 +158,13 @@ Eq(3), Eq(9), Eq(12), Eq(11), Ne(122))); } +// Tests the UnorderedElementsAreMatcher with a range that uses a sentinel. +TEST(ElementsAreTest, HugeMatcherUnorderedSentinel) { + DecreasingIntRange range(3); + + EXPECT_THAT(range, UnorderedElementsAre(Eq(2), Eq(1), Eq(3), Eq(0))); +} + // Tests that ASSERT_THAT() and EXPECT_THAT() work when the value // matches the matcher. TEST(MatcherAssertionTest, WorksWhenMatcherIsSatisfied) {