blob: 69033bbf593d9051dd9fac3e32ecff6773269492 [file] [log] [blame]
Chandler Carruth9a6be8b2014-04-24 03:31:23 +00001//===- IteratorTest.cpp - Unit tests for iterator utilities ---------------===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
Chandler Carruth9a67b072017-06-06 11:06:56 +000010#include "llvm/ADT/iterator.h"
Vedant Kumar75fda2e2018-04-25 21:50:09 +000011#include "llvm/ADT/ArrayRef.h"
Chandler Carruthd5835ee2014-04-24 21:10:35 +000012#include "llvm/ADT/STLExtras.h"
Chandler Carruth9a6be8b2014-04-24 03:31:23 +000013#include "llvm/ADT/SmallVector.h"
14#include "gtest/gtest.h"
15
16using namespace llvm;
17
18namespace {
19
Tim Shen75c16562016-08-09 20:23:13 +000020template <int> struct Shadow;
21
22struct WeirdIter : std::iterator<std::input_iterator_tag, Shadow<0>, Shadow<1>,
23 Shadow<2>, Shadow<3>> {};
24
25struct AdaptedIter : iterator_adaptor_base<AdaptedIter, WeirdIter> {};
26
27// Test that iterator_adaptor_base forwards typedefs, if value_type is
28// unchanged.
29static_assert(std::is_same<typename AdaptedIter::value_type, Shadow<0>>::value,
30 "");
31static_assert(
32 std::is_same<typename AdaptedIter::difference_type, Shadow<1>>::value, "");
33static_assert(std::is_same<typename AdaptedIter::pointer, Shadow<2>>::value,
34 "");
35static_assert(std::is_same<typename AdaptedIter::reference, Shadow<3>>::value,
36 "");
37
Chandler Carruth9a6be8b2014-04-24 03:31:23 +000038TEST(PointeeIteratorTest, Basic) {
Bryant Wong332e6e52017-02-23 23:00:46 +000039 int arr[4] = {1, 2, 3, 4};
Chandler Carruth9a6be8b2014-04-24 03:31:23 +000040 SmallVector<int *, 4> V;
41 V.push_back(&arr[0]);
42 V.push_back(&arr[1]);
43 V.push_back(&arr[2]);
44 V.push_back(&arr[3]);
45
Bryant Wong332e6e52017-02-23 23:00:46 +000046 typedef pointee_iterator<SmallVectorImpl<int *>::const_iterator>
47 test_iterator;
Chandler Carruth9a6be8b2014-04-24 03:31:23 +000048
Justin Lebar4765c012016-10-10 19:56:52 +000049 test_iterator Begin, End;
50 Begin = V.begin();
51 End = test_iterator(V.end());
52
53 test_iterator I = Begin;
Chandler Carruth9a6be8b2014-04-24 03:31:23 +000054 for (int i = 0; i < 4; ++i) {
55 EXPECT_EQ(*V[i], *I);
56
57 EXPECT_EQ(I, Begin + i);
58 EXPECT_EQ(I, std::next(Begin, i));
Justin Lebar4765c012016-10-10 19:56:52 +000059 test_iterator J = Begin;
Chandler Carruth9a6be8b2014-04-24 03:31:23 +000060 J += i;
61 EXPECT_EQ(I, J);
62 EXPECT_EQ(*V[i], Begin[i]);
63
64 EXPECT_NE(I, End);
65 EXPECT_GT(End, I);
66 EXPECT_LT(I, End);
67 EXPECT_GE(I, Begin);
68 EXPECT_LE(Begin, I);
69
70 EXPECT_EQ(i, I - Begin);
71 EXPECT_EQ(i, std::distance(Begin, I));
72 EXPECT_EQ(Begin, I - i);
73
Justin Lebar4765c012016-10-10 19:56:52 +000074 test_iterator K = I++;
Chandler Carruth9a6be8b2014-04-24 03:31:23 +000075 EXPECT_EQ(K, std::prev(I));
76 }
77 EXPECT_EQ(End, I);
78}
79
Chandler Carruthd5835ee2014-04-24 21:10:35 +000080TEST(PointeeIteratorTest, SmartPointer) {
81 SmallVector<std::unique_ptr<int>, 4> V;
82 V.push_back(make_unique<int>(1));
83 V.push_back(make_unique<int>(2));
84 V.push_back(make_unique<int>(3));
85 V.push_back(make_unique<int>(4));
86
Justin Lebar4765c012016-10-10 19:56:52 +000087 typedef pointee_iterator<
Bryant Wong332e6e52017-02-23 23:00:46 +000088 SmallVectorImpl<std::unique_ptr<int>>::const_iterator>
89 test_iterator;
Chandler Carruthd5835ee2014-04-24 21:10:35 +000090
Justin Lebar4765c012016-10-10 19:56:52 +000091 test_iterator Begin, End;
92 Begin = V.begin();
93 End = test_iterator(V.end());
94
95 test_iterator I = Begin;
Chandler Carruthd5835ee2014-04-24 21:10:35 +000096 for (int i = 0; i < 4; ++i) {
97 EXPECT_EQ(*V[i], *I);
98
99 EXPECT_EQ(I, Begin + i);
100 EXPECT_EQ(I, std::next(Begin, i));
Justin Lebar4765c012016-10-10 19:56:52 +0000101 test_iterator J = Begin;
Chandler Carruthd5835ee2014-04-24 21:10:35 +0000102 J += i;
103 EXPECT_EQ(I, J);
104 EXPECT_EQ(*V[i], Begin[i]);
105
106 EXPECT_NE(I, End);
107 EXPECT_GT(End, I);
108 EXPECT_LT(I, End);
109 EXPECT_GE(I, Begin);
110 EXPECT_LE(Begin, I);
111
112 EXPECT_EQ(i, I - Begin);
113 EXPECT_EQ(i, std::distance(Begin, I));
114 EXPECT_EQ(Begin, I - i);
115
Justin Lebar4765c012016-10-10 19:56:52 +0000116 test_iterator K = I++;
Chandler Carruthd5835ee2014-04-24 21:10:35 +0000117 EXPECT_EQ(K, std::prev(I));
118 }
119 EXPECT_EQ(End, I);
120}
121
Justin Bogner8444d102017-03-27 12:56:12 +0000122TEST(PointeeIteratorTest, Range) {
123 int A[] = {1, 2, 3, 4};
124 SmallVector<int *, 4> V{&A[0], &A[1], &A[2], &A[3]};
125
126 int I = 0;
127 for (int II : make_pointee_range(V))
128 EXPECT_EQ(A[I++], II);
129}
130
Tim Shene78e32a2016-08-12 22:03:28 +0000131TEST(FilterIteratorTest, Lambda) {
132 auto IsOdd = [](int N) { return N % 2 == 1; };
133 int A[] = {0, 1, 2, 3, 4, 5, 6};
134 auto Range = make_filter_range(A, IsOdd);
135 SmallVector<int, 3> Actual(Range.begin(), Range.end());
136 EXPECT_EQ((SmallVector<int, 3>{1, 3, 5}), Actual);
137}
138
139TEST(FilterIteratorTest, CallableObject) {
140 int Counter = 0;
141 struct Callable {
142 int &Counter;
143
144 Callable(int &Counter) : Counter(Counter) {}
145
146 bool operator()(int N) {
147 Counter++;
148 return N % 2 == 1;
149 }
150 };
151 Callable IsOdd(Counter);
152 int A[] = {0, 1, 2, 3, 4, 5, 6};
153 auto Range = make_filter_range(A, IsOdd);
154 EXPECT_EQ(2, Counter);
155 SmallVector<int, 3> Actual(Range.begin(), Range.end());
156 EXPECT_GE(Counter, 7);
157 EXPECT_EQ((SmallVector<int, 3>{1, 3, 5}), Actual);
158}
159
160TEST(FilterIteratorTest, FunctionPointer) {
161 bool (*IsOdd)(int) = [](int N) { return N % 2 == 1; };
162 int A[] = {0, 1, 2, 3, 4, 5, 6};
163 auto Range = make_filter_range(A, IsOdd);
164 SmallVector<int, 3> Actual(Range.begin(), Range.end());
165 EXPECT_EQ((SmallVector<int, 3>{1, 3, 5}), Actual);
166}
167
168TEST(FilterIteratorTest, Composition) {
169 auto IsOdd = [](int N) { return N % 2 == 1; };
170 std::unique_ptr<int> A[] = {make_unique<int>(0), make_unique<int>(1),
171 make_unique<int>(2), make_unique<int>(3),
172 make_unique<int>(4), make_unique<int>(5),
173 make_unique<int>(6)};
174 using PointeeIterator = pointee_iterator<std::unique_ptr<int> *>;
175 auto Range = make_filter_range(
176 make_range(PointeeIterator(std::begin(A)), PointeeIterator(std::end(A))),
177 IsOdd);
178 SmallVector<int, 3> Actual(Range.begin(), Range.end());
179 EXPECT_EQ((SmallVector<int, 3>{1, 3, 5}), Actual);
180}
181
182TEST(FilterIteratorTest, InputIterator) {
183 struct InputIterator
184 : iterator_adaptor_base<InputIterator, int *, std::input_iterator_tag> {
185 using BaseT =
186 iterator_adaptor_base<InputIterator, int *, std::input_iterator_tag>;
187
188 InputIterator(int *It) : BaseT(It) {}
189 };
190
191 auto IsOdd = [](int N) { return N % 2 == 1; };
192 int A[] = {0, 1, 2, 3, 4, 5, 6};
193 auto Range = make_filter_range(
194 make_range(InputIterator(std::begin(A)), InputIterator(std::end(A))),
195 IsOdd);
196 SmallVector<int, 3> Actual(Range.begin(), Range.end());
197 EXPECT_EQ((SmallVector<int, 3>{1, 3, 5}), Actual);
198}
199
Vedant Kumar75fda2e2018-04-25 21:50:09 +0000200TEST(FilterIteratorTest, ReverseFilterRange) {
201 auto IsOdd = [](int N) { return N % 2 == 1; };
202 int A[] = {0, 1, 2, 3, 4, 5, 6};
203
204 // Check basic reversal.
205 auto Range = reverse(make_filter_range(A, IsOdd));
206 SmallVector<int, 3> Actual(Range.begin(), Range.end());
207 EXPECT_EQ((SmallVector<int, 3>{5, 3, 1}), Actual);
208
209 // Check that the reverse of the reverse is the original.
210 auto Range2 = reverse(reverse(make_filter_range(A, IsOdd)));
211 SmallVector<int, 3> Actual2(Range2.begin(), Range2.end());
212 EXPECT_EQ((SmallVector<int, 3>{1, 3, 5}), Actual2);
213
214 // Check empty ranges.
215 auto Range3 = reverse(make_filter_range(ArrayRef<int>(), IsOdd));
216 SmallVector<int, 0> Actual3(Range3.begin(), Range3.end());
217 EXPECT_EQ((SmallVector<int, 0>{}), Actual3);
218
219 // Check that we don't skip the first element, provided it isn't filtered
220 // away.
221 auto IsEven = [](int N) { return N % 2 == 0; };
222 auto Range4 = reverse(make_filter_range(A, IsEven));
223 SmallVector<int, 4> Actual4(Range4.begin(), Range4.end());
224 EXPECT_EQ((SmallVector<int, 4>{6, 4, 2, 0}), Actual4);
225}
226
Tim Shencf03add2016-08-19 21:04:45 +0000227TEST(PointerIterator, Basic) {
228 int A[] = {1, 2, 3, 4};
Justin Lebar4765c012016-10-10 19:56:52 +0000229 pointer_iterator<int *> Begin(std::begin(A)), End(std::end(A));
Tim Shencf03add2016-08-19 21:04:45 +0000230 EXPECT_EQ(A, *Begin);
231 ++Begin;
232 EXPECT_EQ(A + 1, *Begin);
233 ++Begin;
234 EXPECT_EQ(A + 2, *Begin);
235 ++Begin;
236 EXPECT_EQ(A + 3, *Begin);
237 ++Begin;
238 EXPECT_EQ(Begin, End);
239}
240
241TEST(PointerIterator, Const) {
242 int A[] = {1, 2, 3, 4};
Justin Lebar4765c012016-10-10 19:56:52 +0000243 const pointer_iterator<int *> Begin(std::begin(A));
Tim Shencf03add2016-08-19 21:04:45 +0000244 EXPECT_EQ(A, *Begin);
245 EXPECT_EQ(A + 1, std::next(*Begin, 1));
246 EXPECT_EQ(A + 2, std::next(*Begin, 2));
247 EXPECT_EQ(A + 3, std::next(*Begin, 3));
248 EXPECT_EQ(A + 4, std::next(*Begin, 4));
249}
250
Justin Bogner8444d102017-03-27 12:56:12 +0000251TEST(PointerIterator, Range) {
252 int A[] = {1, 2, 3, 4};
253 int I = 0;
254 for (int *P : make_pointer_range(A))
255 EXPECT_EQ(A + I++, P);
256}
257
Mehdi Aminia8515452016-10-19 18:02:21 +0000258TEST(ZipIteratorTest, Basic) {
259 using namespace std;
260 const SmallVector<unsigned, 6> pi{3, 1, 4, 1, 5, 9};
261 SmallVector<bool, 6> odd{1, 1, 0, 1, 1, 1};
262 const char message[] = "yynyyy\0";
263
264 for (auto tup : zip(pi, odd, message)) {
265 EXPECT_EQ(get<0>(tup) & 0x01, get<1>(tup));
266 EXPECT_EQ(get<0>(tup) & 0x01 ? 'y' : 'n', get<2>(tup));
267 }
268
269 // note the rvalue
270 for (auto tup : zip(pi, SmallVector<bool, 0>{1, 1, 0, 1, 1})) {
271 EXPECT_EQ(get<0>(tup) & 0x01, get<1>(tup));
272 }
273}
274
275TEST(ZipIteratorTest, ZipFirstBasic) {
276 using namespace std;
277 const SmallVector<unsigned, 6> pi{3, 1, 4, 1, 5, 9};
278 unsigned iters = 0;
279
280 for (auto tup : zip_first(SmallVector<bool, 0>{1, 1, 0, 1}, pi)) {
281 EXPECT_EQ(get<0>(tup), get<1>(tup) & 0x01);
282 iters += 1;
283 }
284
285 EXPECT_EQ(iters, 4u);
286}
287
288TEST(ZipIteratorTest, Mutability) {
289 using namespace std;
290 const SmallVector<unsigned, 4> pi{3, 1, 4, 1, 5, 9};
291 char message[] = "hello zip\0";
292
293 for (auto tup : zip(pi, message, message)) {
294 EXPECT_EQ(get<1>(tup), get<2>(tup));
295 get<2>(tup) = get<0>(tup) & 0x01 ? 'y' : 'n';
296 }
297
298 // note the rvalue
299 for (auto tup : zip(message, "yynyyyzip\0")) {
300 EXPECT_EQ(get<0>(tup), get<1>(tup));
301 }
302}
303
304TEST(ZipIteratorTest, ZipFirstMutability) {
305 using namespace std;
306 vector<unsigned> pi{3, 1, 4, 1, 5, 9};
307 unsigned iters = 0;
308
309 for (auto tup : zip_first(SmallVector<bool, 0>{1, 1, 0, 1}, pi)) {
310 get<1>(tup) = get<0>(tup);
311 iters += 1;
312 }
313
314 EXPECT_EQ(iters, 4u);
315
316 for (auto tup : zip_first(SmallVector<bool, 0>{1, 1, 0, 1}, pi)) {
317 EXPECT_EQ(get<0>(tup), get<1>(tup));
318 }
319}
320
Bryant Wong332e6e52017-02-23 23:00:46 +0000321TEST(ZipIteratorTest, Filter) {
322 using namespace std;
323 vector<unsigned> pi{3, 1, 4, 1, 5, 9};
324
325 unsigned iters = 0;
326 // pi is length 6, but the zip RHS is length 7.
327 auto zipped = zip_first(pi, vector<bool>{1, 1, 0, 1, 1, 1, 0});
328 for (auto tup : make_filter_range(
329 zipped, [](decltype(zipped)::value_type t) { return get<1>(t); })) {
330 EXPECT_EQ(get<0>(tup) & 0x01, get<1>(tup));
331 get<0>(tup) += 1;
332 iters += 1;
333 }
334
335 // Should have skipped pi[2].
336 EXPECT_EQ(iters, 5u);
337
338 // Ensure that in-place mutation works.
339 EXPECT_TRUE(all_of(pi, [](unsigned n) { return (n & 0x01) == 0; }));
340}
341
342TEST(ZipIteratorTest, Reverse) {
343 using namespace std;
344 vector<unsigned> ascending{0, 1, 2, 3, 4, 5};
345
346 auto zipped = zip_first(ascending, vector<bool>{0, 1, 0, 1, 0, 1});
347 unsigned last = 6;
348 for (auto tup : reverse(zipped)) {
349 // Check that this is in reverse.
350 EXPECT_LT(get<0>(tup), last);
351 last = get<0>(tup);
352 EXPECT_EQ(get<0>(tup) & 0x01, get<1>(tup));
353 }
354
355 auto odds = [](decltype(zipped)::value_type tup) { return get<1>(tup); };
356 last = 6;
357 for (auto tup : make_filter_range(reverse(zipped), odds)) {
358 EXPECT_LT(get<0>(tup), last);
359 last = get<0>(tup);
360 EXPECT_TRUE(get<0>(tup) & 0x01);
361 get<0>(tup) += 1;
362 }
363
364 // Ensure that in-place mutation works.
365 EXPECT_TRUE(all_of(ascending, [](unsigned n) { return (n & 0x01) == 0; }));
366}
367
Vedant Kumare0b5f862018-05-10 23:01:54 +0000368TEST(RangeTest, Distance) {
369 std::vector<int> v1;
370 std::vector<int> v2{1, 2, 3};
371
372 EXPECT_EQ(std::distance(v1.begin(), v1.end()), distance(v1));
373 EXPECT_EQ(std::distance(v2.begin(), v2.end()), distance(v2));
374}
375
Chandler Carruth9a6be8b2014-04-24 03:31:23 +0000376} // anonymous namespace