xref: /aosp_15_r20/external/cronet/base/containers/checked_iterators_unittest.cc (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
1 // Copyright 2020 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "base/containers/checked_iterators.h"
6 
7 #include <algorithm>
8 #include <iterator>
9 
10 #include "base/check_op.h"
11 #include "base/ranges/algorithm.h"
12 #include "build/build_config.h"
13 #include "testing/gtest/include/gtest/gtest.h"
14 
15 namespace base {
16 
TEST(CheckedContiguousIterator,SatisfiesContiguousIteratorConcept)17 TEST(CheckedContiguousIterator, SatisfiesContiguousIteratorConcept) {
18   static_assert(std::contiguous_iterator<CheckedContiguousIterator<int>>);
19 }
20 
21 // Checks that constexpr CheckedContiguousConstIterators can be compared at
22 // compile time.
TEST(CheckedContiguousIterator,StaticComparisonOperators)23 TEST(CheckedContiguousIterator, StaticComparisonOperators) {
24   static constexpr int arr[] = {0};
25 
26   constexpr CheckedContiguousConstIterator<int> begin(arr, arr, arr + 1);
27   constexpr CheckedContiguousConstIterator<int> end(arr, arr + 1, arr + 1);
28 
29   static_assert(begin == begin, "");
30   static_assert(end == end, "");
31 
32   static_assert(begin != end, "");
33   static_assert(end != begin, "");
34 
35   static_assert(begin < end, "");
36 
37   static_assert(begin <= begin, "");
38   static_assert(begin <= end, "");
39   static_assert(end <= end, "");
40 
41   static_assert(end > begin, "");
42 
43   static_assert(end >= end, "");
44   static_assert(end >= begin, "");
45   static_assert(begin >= begin, "");
46 }
47 
48 // Checks that comparison between iterators and const iterators works in both
49 // directions.
TEST(CheckedContiguousIterator,ConvertingComparisonOperators)50 TEST(CheckedContiguousIterator, ConvertingComparisonOperators) {
51   static int arr[] = {0};
52 
53   CheckedContiguousIterator<int> begin(arr, arr, arr + 1);
54   CheckedContiguousConstIterator<int> cbegin(arr, arr, arr + 1);
55 
56   CheckedContiguousIterator<int> end(arr, arr + 1, arr + 1);
57   CheckedContiguousConstIterator<int> cend(arr, arr + 1, arr + 1);
58 
59   EXPECT_EQ(begin, cbegin);
60   EXPECT_EQ(cbegin, begin);
61   EXPECT_EQ(end, cend);
62   EXPECT_EQ(cend, end);
63 
64   EXPECT_NE(begin, cend);
65   EXPECT_NE(cbegin, end);
66   EXPECT_NE(end, cbegin);
67   EXPECT_NE(cend, begin);
68 
69   EXPECT_LT(begin, cend);
70   EXPECT_LT(cbegin, end);
71 
72   EXPECT_LE(begin, cbegin);
73   EXPECT_LE(cbegin, begin);
74   EXPECT_LE(begin, cend);
75   EXPECT_LE(cbegin, end);
76   EXPECT_LE(end, cend);
77   EXPECT_LE(cend, end);
78 
79   EXPECT_GT(end, cbegin);
80   EXPECT_GT(cend, begin);
81 
82   EXPECT_GE(end, cend);
83   EXPECT_GE(cend, end);
84   EXPECT_GE(end, cbegin);
85   EXPECT_GE(cend, begin);
86   EXPECT_GE(begin, cbegin);
87   EXPECT_GE(cbegin, begin);
88 }
89 
90 }  // namespace base
91 
92 namespace {
93 
94 // Helper template that wraps an iterator and disables its dereference and
95 // increment operations.
96 template <typename Iterator>
97 struct DisableDerefAndIncr : Iterator {
98   using Iterator::Iterator;
99 
100   // NOLINTNEXTLINE(google-explicit-constructor)
DisableDerefAndIncr__anon4e2118660111::DisableDerefAndIncr101   constexpr DisableDerefAndIncr(const Iterator& iter) : Iterator(iter) {}
102 
103   void operator*() = delete;
104   void operator++() = delete;
105   void operator++(int) = delete;
106 };
107 
108 }  // namespace
109 
110 // Inherit `pointer_traits` specialization from the base class.
111 template <typename Iter>
112 struct std::pointer_traits<DisableDerefAndIncr<Iter>>
113     : ::std::pointer_traits<Iter> {};
114 
115 namespace base {
116 
117 // Tests that using std::copy with CheckedContiguousIterator<int> results in an
118 // optimized code-path that does not invoke the iterator's dereference and
119 // increment operations, as expected in libc++. This fails to compile if
120 // std::copy is not optimized.
121 // NOTE: This test relies on implementation details of the STL and thus might
122 // break in the future during a libc++ roll. If this does happen, please reach
123 // out to [email protected] to reevaluate whether this test will
124 // still be needed.
125 #if defined(_LIBCPP_VERSION)
TEST(CheckedContiguousIterator,OptimizedCopy)126 TEST(CheckedContiguousIterator, OptimizedCopy) {
127   using Iter = DisableDerefAndIncr<CheckedContiguousIterator<int>>;
128 
129   int arr_in[5] = {1, 2, 3, 4, 5};
130   int arr_out[5];
131 
132   Iter in_begin(std::begin(arr_in), std::end(arr_in));
133   Iter in_end(std::begin(arr_in), std::end(arr_in), std::end(arr_in));
134   Iter out_begin(std::begin(arr_out), std::end(arr_out));
135   Iter out_end = std::copy(in_begin, in_end, out_begin);
136   EXPECT_EQ(out_end, out_begin + (in_end - in_begin));
137 
138   EXPECT_TRUE(ranges::equal(arr_in, arr_out));
139 }
140 #endif  // defined(_LIBCPP_VERSION)
141 
142 }  // namespace base
143