1 //===- 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
10 #include "llvm/ADT/iterator.h"
11 #include "llvm/ADT/ArrayRef.h"
12 #include "llvm/ADT/STLExtras.h"
13 #include "llvm/ADT/SmallVector.h"
14 #include "gtest/gtest.h"
15
16 using namespace llvm;
17
18 namespace {
19
20 template <int> struct Shadow;
21
22 struct WeirdIter : std::iterator<std::input_iterator_tag, Shadow<0>, Shadow<1>,
23 Shadow<2>, Shadow<3>> {};
24
25 struct AdaptedIter : iterator_adaptor_base<AdaptedIter, WeirdIter> {};
26
27 // Test that iterator_adaptor_base forwards typedefs, if value_type is
28 // unchanged.
29 static_assert(std::is_same<typename AdaptedIter::value_type, Shadow<0>>::value,
30 "");
31 static_assert(
32 std::is_same<typename AdaptedIter::difference_type, Shadow<1>>::value, "");
33 static_assert(std::is_same<typename AdaptedIter::pointer, Shadow<2>>::value,
34 "");
35 static_assert(std::is_same<typename AdaptedIter::reference, Shadow<3>>::value,
36 "");
37
TEST(PointeeIteratorTest,Basic)38 TEST(PointeeIteratorTest, Basic) {
39 int arr[4] = {1, 2, 3, 4};
40 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
46 typedef pointee_iterator<SmallVectorImpl<int *>::const_iterator>
47 test_iterator;
48
49 test_iterator Begin, End;
50 Begin = V.begin();
51 End = test_iterator(V.end());
52
53 test_iterator I = Begin;
54 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));
59 test_iterator J = Begin;
60 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
74 test_iterator K = I++;
75 EXPECT_EQ(K, std::prev(I));
76 }
77 EXPECT_EQ(End, I);
78 }
79
TEST(PointeeIteratorTest,SmartPointer)80 TEST(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
87 typedef pointee_iterator<
88 SmallVectorImpl<std::unique_ptr<int>>::const_iterator>
89 test_iterator;
90
91 test_iterator Begin, End;
92 Begin = V.begin();
93 End = test_iterator(V.end());
94
95 test_iterator I = Begin;
96 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));
101 test_iterator J = Begin;
102 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
116 test_iterator K = I++;
117 EXPECT_EQ(K, std::prev(I));
118 }
119 EXPECT_EQ(End, I);
120 }
121
TEST(PointeeIteratorTest,Range)122 TEST(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
TEST(PointeeIteratorTest,PointeeType)131 TEST(PointeeIteratorTest, PointeeType) {
132 struct S {
133 int X;
134 bool operator==(const S &RHS) const { return X == RHS.X; };
135 };
136 S A[] = {S{0}, S{1}};
137 SmallVector<S *, 2> V{&A[0], &A[1]};
138
139 pointee_iterator<SmallVectorImpl<S *>::const_iterator, const S> I = V.begin();
140 for (int j = 0; j < 2; ++j, ++I) {
141 EXPECT_EQ(*V[j], *I);
142 }
143 }
144
TEST(FilterIteratorTest,Lambda)145 TEST(FilterIteratorTest, Lambda) {
146 auto IsOdd = [](int N) { return N % 2 == 1; };
147 int A[] = {0, 1, 2, 3, 4, 5, 6};
148 auto Range = make_filter_range(A, IsOdd);
149 SmallVector<int, 3> Actual(Range.begin(), Range.end());
150 EXPECT_EQ((SmallVector<int, 3>{1, 3, 5}), Actual);
151 }
152
TEST(FilterIteratorTest,CallableObject)153 TEST(FilterIteratorTest, CallableObject) {
154 int Counter = 0;
155 struct Callable {
156 int &Counter;
157
158 Callable(int &Counter) : Counter(Counter) {}
159
160 bool operator()(int N) {
161 Counter++;
162 return N % 2 == 1;
163 }
164 };
165 Callable IsOdd(Counter);
166 int A[] = {0, 1, 2, 3, 4, 5, 6};
167 auto Range = make_filter_range(A, IsOdd);
168 EXPECT_EQ(2, Counter);
169 SmallVector<int, 3> Actual(Range.begin(), Range.end());
170 EXPECT_GE(Counter, 7);
171 EXPECT_EQ((SmallVector<int, 3>{1, 3, 5}), Actual);
172 }
173
TEST(FilterIteratorTest,FunctionPointer)174 TEST(FilterIteratorTest, FunctionPointer) {
175 bool (*IsOdd)(int) = [](int N) { return N % 2 == 1; };
176 int A[] = {0, 1, 2, 3, 4, 5, 6};
177 auto Range = make_filter_range(A, IsOdd);
178 SmallVector<int, 3> Actual(Range.begin(), Range.end());
179 EXPECT_EQ((SmallVector<int, 3>{1, 3, 5}), Actual);
180 }
181
TEST(FilterIteratorTest,Composition)182 TEST(FilterIteratorTest, Composition) {
183 auto IsOdd = [](int N) { return N % 2 == 1; };
184 std::unique_ptr<int> A[] = {make_unique<int>(0), make_unique<int>(1),
185 make_unique<int>(2), make_unique<int>(3),
186 make_unique<int>(4), make_unique<int>(5),
187 make_unique<int>(6)};
188 using PointeeIterator = pointee_iterator<std::unique_ptr<int> *>;
189 auto Range = make_filter_range(
190 make_range(PointeeIterator(std::begin(A)), PointeeIterator(std::end(A))),
191 IsOdd);
192 SmallVector<int, 3> Actual(Range.begin(), Range.end());
193 EXPECT_EQ((SmallVector<int, 3>{1, 3, 5}), Actual);
194 }
195
TEST(FilterIteratorTest,InputIterator)196 TEST(FilterIteratorTest, InputIterator) {
197 struct InputIterator
198 : iterator_adaptor_base<InputIterator, int *, std::input_iterator_tag> {
199 using BaseT =
200 iterator_adaptor_base<InputIterator, int *, std::input_iterator_tag>;
201
202 InputIterator(int *It) : BaseT(It) {}
203 };
204
205 auto IsOdd = [](int N) { return N % 2 == 1; };
206 int A[] = {0, 1, 2, 3, 4, 5, 6};
207 auto Range = make_filter_range(
208 make_range(InputIterator(std::begin(A)), InputIterator(std::end(A))),
209 IsOdd);
210 SmallVector<int, 3> Actual(Range.begin(), Range.end());
211 EXPECT_EQ((SmallVector<int, 3>{1, 3, 5}), Actual);
212 }
213
TEST(FilterIteratorTest,ReverseFilterRange)214 TEST(FilterIteratorTest, ReverseFilterRange) {
215 auto IsOdd = [](int N) { return N % 2 == 1; };
216 int A[] = {0, 1, 2, 3, 4, 5, 6};
217
218 // Check basic reversal.
219 auto Range = reverse(make_filter_range(A, IsOdd));
220 SmallVector<int, 3> Actual(Range.begin(), Range.end());
221 EXPECT_EQ((SmallVector<int, 3>{5, 3, 1}), Actual);
222
223 // Check that the reverse of the reverse is the original.
224 auto Range2 = reverse(reverse(make_filter_range(A, IsOdd)));
225 SmallVector<int, 3> Actual2(Range2.begin(), Range2.end());
226 EXPECT_EQ((SmallVector<int, 3>{1, 3, 5}), Actual2);
227
228 // Check empty ranges.
229 auto Range3 = reverse(make_filter_range(ArrayRef<int>(), IsOdd));
230 SmallVector<int, 0> Actual3(Range3.begin(), Range3.end());
231 EXPECT_EQ((SmallVector<int, 0>{}), Actual3);
232
233 // Check that we don't skip the first element, provided it isn't filtered
234 // away.
235 auto IsEven = [](int N) { return N % 2 == 0; };
236 auto Range4 = reverse(make_filter_range(A, IsEven));
237 SmallVector<int, 4> Actual4(Range4.begin(), Range4.end());
238 EXPECT_EQ((SmallVector<int, 4>{6, 4, 2, 0}), Actual4);
239 }
240
TEST(PointerIterator,Basic)241 TEST(PointerIterator, Basic) {
242 int A[] = {1, 2, 3, 4};
243 pointer_iterator<int *> Begin(std::begin(A)), End(std::end(A));
244 EXPECT_EQ(A, *Begin);
245 ++Begin;
246 EXPECT_EQ(A + 1, *Begin);
247 ++Begin;
248 EXPECT_EQ(A + 2, *Begin);
249 ++Begin;
250 EXPECT_EQ(A + 3, *Begin);
251 ++Begin;
252 EXPECT_EQ(Begin, End);
253 }
254
TEST(PointerIterator,Const)255 TEST(PointerIterator, Const) {
256 int A[] = {1, 2, 3, 4};
257 const pointer_iterator<int *> Begin(std::begin(A));
258 EXPECT_EQ(A, *Begin);
259 EXPECT_EQ(A + 1, std::next(*Begin, 1));
260 EXPECT_EQ(A + 2, std::next(*Begin, 2));
261 EXPECT_EQ(A + 3, std::next(*Begin, 3));
262 EXPECT_EQ(A + 4, std::next(*Begin, 4));
263 }
264
TEST(PointerIterator,Range)265 TEST(PointerIterator, Range) {
266 int A[] = {1, 2, 3, 4};
267 int I = 0;
268 for (int *P : make_pointer_range(A))
269 EXPECT_EQ(A + I++, P);
270 }
271
TEST(ZipIteratorTest,Basic)272 TEST(ZipIteratorTest, Basic) {
273 using namespace std;
274 const SmallVector<unsigned, 6> pi{3, 1, 4, 1, 5, 9};
275 SmallVector<bool, 6> odd{1, 1, 0, 1, 1, 1};
276 const char message[] = "yynyyy\0";
277
278 for (auto tup : zip(pi, odd, message)) {
279 EXPECT_EQ(get<0>(tup) & 0x01, get<1>(tup));
280 EXPECT_EQ(get<0>(tup) & 0x01 ? 'y' : 'n', get<2>(tup));
281 }
282
283 // note the rvalue
284 for (auto tup : zip(pi, SmallVector<bool, 0>{1, 1, 0, 1, 1})) {
285 EXPECT_EQ(get<0>(tup) & 0x01, get<1>(tup));
286 }
287 }
288
TEST(ZipIteratorTest,ZipFirstBasic)289 TEST(ZipIteratorTest, ZipFirstBasic) {
290 using namespace std;
291 const SmallVector<unsigned, 6> pi{3, 1, 4, 1, 5, 9};
292 unsigned iters = 0;
293
294 for (auto tup : zip_first(SmallVector<bool, 0>{1, 1, 0, 1}, pi)) {
295 EXPECT_EQ(get<0>(tup), get<1>(tup) & 0x01);
296 iters += 1;
297 }
298
299 EXPECT_EQ(iters, 4u);
300 }
301
TEST(ZipIteratorTest,Mutability)302 TEST(ZipIteratorTest, Mutability) {
303 using namespace std;
304 const SmallVector<unsigned, 4> pi{3, 1, 4, 1, 5, 9};
305 char message[] = "hello zip\0";
306
307 for (auto tup : zip(pi, message, message)) {
308 EXPECT_EQ(get<1>(tup), get<2>(tup));
309 get<2>(tup) = get<0>(tup) & 0x01 ? 'y' : 'n';
310 }
311
312 // note the rvalue
313 for (auto tup : zip(message, "yynyyyzip\0")) {
314 EXPECT_EQ(get<0>(tup), get<1>(tup));
315 }
316 }
317
TEST(ZipIteratorTest,ZipFirstMutability)318 TEST(ZipIteratorTest, ZipFirstMutability) {
319 using namespace std;
320 vector<unsigned> pi{3, 1, 4, 1, 5, 9};
321 unsigned iters = 0;
322
323 for (auto tup : zip_first(SmallVector<bool, 0>{1, 1, 0, 1}, pi)) {
324 get<1>(tup) = get<0>(tup);
325 iters += 1;
326 }
327
328 EXPECT_EQ(iters, 4u);
329
330 for (auto tup : zip_first(SmallVector<bool, 0>{1, 1, 0, 1}, pi)) {
331 EXPECT_EQ(get<0>(tup), get<1>(tup));
332 }
333 }
334
TEST(ZipIteratorTest,Filter)335 TEST(ZipIteratorTest, Filter) {
336 using namespace std;
337 vector<unsigned> pi{3, 1, 4, 1, 5, 9};
338
339 unsigned iters = 0;
340 // pi is length 6, but the zip RHS is length 7.
341 auto zipped = zip_first(pi, vector<bool>{1, 1, 0, 1, 1, 1, 0});
342 for (auto tup : make_filter_range(
343 zipped, [](decltype(zipped)::value_type t) { return get<1>(t); })) {
344 EXPECT_EQ(get<0>(tup) & 0x01, get<1>(tup));
345 get<0>(tup) += 1;
346 iters += 1;
347 }
348
349 // Should have skipped pi[2].
350 EXPECT_EQ(iters, 5u);
351
352 // Ensure that in-place mutation works.
353 EXPECT_TRUE(all_of(pi, [](unsigned n) { return (n & 0x01) == 0; }));
354 }
355
TEST(ZipIteratorTest,Reverse)356 TEST(ZipIteratorTest, Reverse) {
357 using namespace std;
358 vector<unsigned> ascending{0, 1, 2, 3, 4, 5};
359
360 auto zipped = zip_first(ascending, vector<bool>{0, 1, 0, 1, 0, 1});
361 unsigned last = 6;
362 for (auto tup : reverse(zipped)) {
363 // Check that this is in reverse.
364 EXPECT_LT(get<0>(tup), last);
365 last = get<0>(tup);
366 EXPECT_EQ(get<0>(tup) & 0x01, get<1>(tup));
367 }
368
369 auto odds = [](decltype(zipped)::value_type tup) { return get<1>(tup); };
370 last = 6;
371 for (auto tup : make_filter_range(reverse(zipped), odds)) {
372 EXPECT_LT(get<0>(tup), last);
373 last = get<0>(tup);
374 EXPECT_TRUE(get<0>(tup) & 0x01);
375 get<0>(tup) += 1;
376 }
377
378 // Ensure that in-place mutation works.
379 EXPECT_TRUE(all_of(ascending, [](unsigned n) { return (n & 0x01) == 0; }));
380 }
381
TEST(RangeTest,Distance)382 TEST(RangeTest, Distance) {
383 std::vector<int> v1;
384 std::vector<int> v2{1, 2, 3};
385
386 EXPECT_EQ(std::distance(v1.begin(), v1.end()), size(v1));
387 EXPECT_EQ(std::distance(v2.begin(), v2.end()), size(v2));
388 }
389
TEST(IteratorRangeTest,DropBegin)390 TEST(IteratorRangeTest, DropBegin) {
391 SmallVector<int, 5> vec{0, 1, 2, 3, 4};
392
393 for (int n = 0; n < 5; ++n) {
394 int i = n;
395 for (auto &v : drop_begin(vec, n)) {
396 EXPECT_EQ(v, i);
397 i += 1;
398 }
399 EXPECT_EQ(i, 5);
400 }
401 }
402
403 } // anonymous namespace
404