From 36ba75f0ad5383a9759f17f3f72fd4661c72cb6d Mon Sep 17 00:00:00 2001 From: Abseil Team Date: Thu, 27 Aug 2026 04:13:04 -0700 Subject: [PATCH] `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 --- googlemock/include/gmock/gmock-matchers.h | 4 +- .../test/gmock-matchers-containers_test.cc | 60 +++++++++++++++++++ 2 files changed, 62 insertions(+), 2 deletions(-) diff --git a/googlemock/include/gmock/gmock-matchers.h b/googlemock/include/gmock/gmock-matchers.h index 9caee1d6..800b7676 100644 --- a/googlemock/include/gmock/gmock-matchers.h +++ b/googlemock/include/gmock/gmock-matchers.h @@ -3971,8 +3971,8 @@ class [[nodiscard]] UnorderedElementsAreMatcherImpl } private: - template - MatchMatrix AnalyzeElements(ElementIter elem_first, ElementIter elem_last, + template + MatchMatrix AnalyzeElements(ElementIter elem_first, ElementIterEnd elem_last, ::std::vector* 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 697509f7..e7969a0c 100644 --- a/googlemock/test/gmock-matchers-containers_test.cc +++ b/googlemock/test/gmock-matchers-containers_test.cc @@ -78,6 +78,52 @@ TEST(ContainsTest, WorksWithMoveOnly) { 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 test_vector{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12}; @@ -87,6 +133,13 @@ TEST(ElementsAreTest, HugeMatcher) { 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 test_vector{ @@ -105,6 +158,13 @@ TEST(ElementsAreTest, HugeMatcherUnordered) { 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) {