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/ilist.h"
11 #include "llvm/ADT/iterator.h"
12 #include "llvm/ADT/ArrayRef.h"
13 #include "llvm/ADT/STLExtras.h"
14 #include "llvm/ADT/SmallVector.h"
15 #include "gtest/gtest.h"
16 
17 using namespace llvm;
18 
19 namespace {
20 
21 template <int> struct Shadow;
22 
23 struct WeirdIter : std::iterator<std::input_iterator_tag, Shadow<0>, Shadow<1>,
24                                  Shadow<2>, Shadow<3>> {};
25 
26 struct AdaptedIter : iterator_adaptor_base<AdaptedIter, WeirdIter> {};
27 
28 // Test that iterator_adaptor_base forwards typedefs, if value_type is
29 // unchanged.
30 static_assert(std::is_same<typename AdaptedIter::value_type, Shadow<0>>::value,
31               "");
32 static_assert(
33     std::is_same<typename AdaptedIter::difference_type, Shadow<1>>::value, "");
34 static_assert(std::is_same<typename AdaptedIter::pointer, Shadow<2>>::value,
35               "");
36 static_assert(std::is_same<typename AdaptedIter::reference, Shadow<3>>::value,
37               "");
38 
39 // Ensure that pointe{e,r}_iterator adaptors correctly forward the category of
40 // the underlying iterator.
41 
42 using RandomAccessIter = SmallVectorImpl<int*>::iterator;
43 using BidiIter = ilist<int*>::iterator;
44 
45 template<class T>
46 using pointee_iterator_defaulted = pointee_iterator<T>;
47 template<class T>
48 using pointer_iterator_defaulted = pointer_iterator<T>;
49 
50 // Ensures that an iterator and its adaptation have the same iterator_category.
51 template<template<typename> class A, typename It>
52 using IsAdaptedIterCategorySame =
53   std::is_same<typename std::iterator_traits<It>::iterator_category,
54                typename std::iterator_traits<A<It>>::iterator_category>;
55 
56 // pointeE_iterator
57 static_assert(IsAdaptedIterCategorySame<pointee_iterator_defaulted,
58                                         RandomAccessIter>::value, "");
59 static_assert(IsAdaptedIterCategorySame<pointee_iterator_defaulted,
60                                         BidiIter>::value, "");
61 // pointeR_iterator
62 static_assert(IsAdaptedIterCategorySame<pointer_iterator_defaulted,
63                                         RandomAccessIter>::value, "");
64 static_assert(IsAdaptedIterCategorySame<pointer_iterator_defaulted,
65                                         BidiIter>::value, "");
66 
67 TEST(PointeeIteratorTest, Basic) {
68   int arr[4] = {1, 2, 3, 4};
69   SmallVector<int *, 4> V;
70   V.push_back(&arr[0]);
71   V.push_back(&arr[1]);
72   V.push_back(&arr[2]);
73   V.push_back(&arr[3]);
74 
75   typedef pointee_iterator<SmallVectorImpl<int *>::const_iterator>
76       test_iterator;
77 
78   test_iterator Begin, End;
79   Begin = V.begin();
80   End = test_iterator(V.end());
81 
82   test_iterator I = Begin;
83   for (int i = 0; i < 4; ++i) {
84     EXPECT_EQ(*V[i], *I);
85 
86     EXPECT_EQ(I, Begin + i);
87     EXPECT_EQ(I, std::next(Begin, i));
88     test_iterator J = Begin;
89     J += i;
90     EXPECT_EQ(I, J);
91     EXPECT_EQ(*V[i], Begin[i]);
92 
93     EXPECT_NE(I, End);
94     EXPECT_GT(End, I);
95     EXPECT_LT(I, End);
96     EXPECT_GE(I, Begin);
97     EXPECT_LE(Begin, I);
98 
99     EXPECT_EQ(i, I - Begin);
100     EXPECT_EQ(i, std::distance(Begin, I));
101     EXPECT_EQ(Begin, I - i);
102 
103     test_iterator K = I++;
104     EXPECT_EQ(K, std::prev(I));
105   }
106   EXPECT_EQ(End, I);
107 }
108 
109 TEST(PointeeIteratorTest, SmartPointer) {
110   SmallVector<std::unique_ptr<int>, 4> V;
111   V.push_back(make_unique<int>(1));
112   V.push_back(make_unique<int>(2));
113   V.push_back(make_unique<int>(3));
114   V.push_back(make_unique<int>(4));
115 
116   typedef pointee_iterator<
117       SmallVectorImpl<std::unique_ptr<int>>::const_iterator>
118       test_iterator;
119 
120   test_iterator Begin, End;
121   Begin = V.begin();
122   End = test_iterator(V.end());
123 
124   test_iterator I = Begin;
125   for (int i = 0; i < 4; ++i) {
126     EXPECT_EQ(*V[i], *I);
127 
128     EXPECT_EQ(I, Begin + i);
129     EXPECT_EQ(I, std::next(Begin, i));
130     test_iterator J = Begin;
131     J += i;
132     EXPECT_EQ(I, J);
133     EXPECT_EQ(*V[i], Begin[i]);
134 
135     EXPECT_NE(I, End);
136     EXPECT_GT(End, I);
137     EXPECT_LT(I, End);
138     EXPECT_GE(I, Begin);
139     EXPECT_LE(Begin, I);
140 
141     EXPECT_EQ(i, I - Begin);
142     EXPECT_EQ(i, std::distance(Begin, I));
143     EXPECT_EQ(Begin, I - i);
144 
145     test_iterator K = I++;
146     EXPECT_EQ(K, std::prev(I));
147   }
148   EXPECT_EQ(End, I);
149 }
150 
151 TEST(PointeeIteratorTest, Range) {
152   int A[] = {1, 2, 3, 4};
153   SmallVector<int *, 4> V{&A[0], &A[1], &A[2], &A[3]};
154 
155   int I = 0;
156   for (int II : make_pointee_range(V))
157     EXPECT_EQ(A[I++], II);
158 }
159 
160 TEST(PointeeIteratorTest, PointeeType) {
161   struct S {
162     int X;
163     bool operator==(const S &RHS) const { return X == RHS.X; };
164   };
165   S A[] = {S{0}, S{1}};
166   SmallVector<S *, 2> V{&A[0], &A[1]};
167 
168   pointee_iterator<SmallVectorImpl<S *>::const_iterator, const S> I = V.begin();
169   for (int j = 0; j < 2; ++j, ++I) {
170     EXPECT_EQ(*V[j], *I);
171   }
172 }
173 
174 TEST(FilterIteratorTest, Lambda) {
175   auto IsOdd = [](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 
182 TEST(FilterIteratorTest, CallableObject) {
183   int Counter = 0;
184   struct Callable {
185     int &Counter;
186 
187     Callable(int &Counter) : Counter(Counter) {}
188 
189     bool operator()(int N) {
190       Counter++;
191       return N % 2 == 1;
192     }
193   };
194   Callable IsOdd(Counter);
195   int A[] = {0, 1, 2, 3, 4, 5, 6};
196   auto Range = make_filter_range(A, IsOdd);
197   EXPECT_EQ(2, Counter);
198   SmallVector<int, 3> Actual(Range.begin(), Range.end());
199   EXPECT_GE(Counter, 7);
200   EXPECT_EQ((SmallVector<int, 3>{1, 3, 5}), Actual);
201 }
202 
203 TEST(FilterIteratorTest, FunctionPointer) {
204   bool (*IsOdd)(int) = [](int N) { return N % 2 == 1; };
205   int A[] = {0, 1, 2, 3, 4, 5, 6};
206   auto Range = make_filter_range(A, IsOdd);
207   SmallVector<int, 3> Actual(Range.begin(), Range.end());
208   EXPECT_EQ((SmallVector<int, 3>{1, 3, 5}), Actual);
209 }
210 
211 TEST(FilterIteratorTest, Composition) {
212   auto IsOdd = [](int N) { return N % 2 == 1; };
213   std::unique_ptr<int> A[] = {make_unique<int>(0), make_unique<int>(1),
214                               make_unique<int>(2), make_unique<int>(3),
215                               make_unique<int>(4), make_unique<int>(5),
216                               make_unique<int>(6)};
217   using PointeeIterator = pointee_iterator<std::unique_ptr<int> *>;
218   auto Range = make_filter_range(
219       make_range(PointeeIterator(std::begin(A)), PointeeIterator(std::end(A))),
220       IsOdd);
221   SmallVector<int, 3> Actual(Range.begin(), Range.end());
222   EXPECT_EQ((SmallVector<int, 3>{1, 3, 5}), Actual);
223 }
224 
225 TEST(FilterIteratorTest, InputIterator) {
226   struct InputIterator
227       : iterator_adaptor_base<InputIterator, int *, std::input_iterator_tag> {
228     using BaseT =
229         iterator_adaptor_base<InputIterator, int *, std::input_iterator_tag>;
230 
231     InputIterator(int *It) : BaseT(It) {}
232   };
233 
234   auto IsOdd = [](int N) { return N % 2 == 1; };
235   int A[] = {0, 1, 2, 3, 4, 5, 6};
236   auto Range = make_filter_range(
237       make_range(InputIterator(std::begin(A)), InputIterator(std::end(A))),
238       IsOdd);
239   SmallVector<int, 3> Actual(Range.begin(), Range.end());
240   EXPECT_EQ((SmallVector<int, 3>{1, 3, 5}), Actual);
241 }
242 
243 TEST(FilterIteratorTest, ReverseFilterRange) {
244   auto IsOdd = [](int N) { return N % 2 == 1; };
245   int A[] = {0, 1, 2, 3, 4, 5, 6};
246 
247   // Check basic reversal.
248   auto Range = reverse(make_filter_range(A, IsOdd));
249   SmallVector<int, 3> Actual(Range.begin(), Range.end());
250   EXPECT_EQ((SmallVector<int, 3>{5, 3, 1}), Actual);
251 
252   // Check that the reverse of the reverse is the original.
253   auto Range2 = reverse(reverse(make_filter_range(A, IsOdd)));
254   SmallVector<int, 3> Actual2(Range2.begin(), Range2.end());
255   EXPECT_EQ((SmallVector<int, 3>{1, 3, 5}), Actual2);
256 
257   // Check empty ranges.
258   auto Range3 = reverse(make_filter_range(ArrayRef<int>(), IsOdd));
259   SmallVector<int, 0> Actual3(Range3.begin(), Range3.end());
260   EXPECT_EQ((SmallVector<int, 0>{}), Actual3);
261 
262   // Check that we don't skip the first element, provided it isn't filtered
263   // away.
264   auto IsEven = [](int N) { return N % 2 == 0; };
265   auto Range4 = reverse(make_filter_range(A, IsEven));
266   SmallVector<int, 4> Actual4(Range4.begin(), Range4.end());
267   EXPECT_EQ((SmallVector<int, 4>{6, 4, 2, 0}), Actual4);
268 }
269 
270 TEST(PointerIterator, Basic) {
271   int A[] = {1, 2, 3, 4};
272   pointer_iterator<int *> Begin(std::begin(A)), End(std::end(A));
273   EXPECT_EQ(A, *Begin);
274   ++Begin;
275   EXPECT_EQ(A + 1, *Begin);
276   ++Begin;
277   EXPECT_EQ(A + 2, *Begin);
278   ++Begin;
279   EXPECT_EQ(A + 3, *Begin);
280   ++Begin;
281   EXPECT_EQ(Begin, End);
282 }
283 
284 TEST(PointerIterator, Const) {
285   int A[] = {1, 2, 3, 4};
286   const pointer_iterator<int *> Begin(std::begin(A));
287   EXPECT_EQ(A, *Begin);
288   EXPECT_EQ(A + 1, std::next(*Begin, 1));
289   EXPECT_EQ(A + 2, std::next(*Begin, 2));
290   EXPECT_EQ(A + 3, std::next(*Begin, 3));
291   EXPECT_EQ(A + 4, std::next(*Begin, 4));
292 }
293 
294 TEST(PointerIterator, Range) {
295   int A[] = {1, 2, 3, 4};
296   int I = 0;
297   for (int *P : make_pointer_range(A))
298     EXPECT_EQ(A + I++, P);
299 }
300 
301 TEST(ZipIteratorTest, Basic) {
302   using namespace std;
303   const SmallVector<unsigned, 6> pi{3, 1, 4, 1, 5, 9};
304   SmallVector<bool, 6> odd{1, 1, 0, 1, 1, 1};
305   const char message[] = "yynyyy\0";
306 
307   for (auto tup : zip(pi, odd, message)) {
308     EXPECT_EQ(get<0>(tup) & 0x01, get<1>(tup));
309     EXPECT_EQ(get<0>(tup) & 0x01 ? 'y' : 'n', get<2>(tup));
310   }
311 
312   // note the rvalue
313   for (auto tup : zip(pi, SmallVector<bool, 0>{1, 1, 0, 1, 1})) {
314     EXPECT_EQ(get<0>(tup) & 0x01, get<1>(tup));
315   }
316 }
317 
318 TEST(ZipIteratorTest, ZipFirstBasic) {
319   using namespace std;
320   const SmallVector<unsigned, 6> 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     EXPECT_EQ(get<0>(tup), get<1>(tup) & 0x01);
325     iters += 1;
326   }
327 
328   EXPECT_EQ(iters, 4u);
329 }
330 
331 TEST(ZipIteratorTest, ZipLongestBasic) {
332   using namespace std;
333   const vector<unsigned> pi{3, 1, 4, 1, 5, 9};
334   const vector<StringRef> e{"2", "7", "1", "8"};
335 
336   {
337     // Check left range longer than right.
338     const vector<tuple<Optional<unsigned>, Optional<StringRef>>> expected{
339         make_tuple(3, StringRef("2")), make_tuple(1, StringRef("7")),
340         make_tuple(4, StringRef("1")), make_tuple(1, StringRef("8")),
341         make_tuple(5, None),           make_tuple(9, None)};
342     size_t iters = 0;
343     for (auto tup : zip_longest(pi, e)) {
344       EXPECT_EQ(tup, expected[iters]);
345       iters += 1;
346     }
347     EXPECT_EQ(iters, expected.size());
348   }
349 
350   {
351     // Check right range longer than left.
352     const vector<tuple<Optional<StringRef>, Optional<unsigned>>> expected{
353         make_tuple(StringRef("2"), 3), make_tuple(StringRef("7"), 1),
354         make_tuple(StringRef("1"), 4), make_tuple(StringRef("8"), 1),
355         make_tuple(None, 5),           make_tuple(None, 9)};
356     size_t iters = 0;
357     for (auto tup : zip_longest(e, pi)) {
358       EXPECT_EQ(tup, expected[iters]);
359       iters += 1;
360     }
361     EXPECT_EQ(iters, expected.size());
362   }
363 }
364 
365 TEST(ZipIteratorTest, Mutability) {
366   using namespace std;
367   const SmallVector<unsigned, 4> pi{3, 1, 4, 1, 5, 9};
368   char message[] = "hello zip\0";
369 
370   for (auto tup : zip(pi, message, message)) {
371     EXPECT_EQ(get<1>(tup), get<2>(tup));
372     get<2>(tup) = get<0>(tup) & 0x01 ? 'y' : 'n';
373   }
374 
375   // note the rvalue
376   for (auto tup : zip(message, "yynyyyzip\0")) {
377     EXPECT_EQ(get<0>(tup), get<1>(tup));
378   }
379 }
380 
381 TEST(ZipIteratorTest, ZipFirstMutability) {
382   using namespace std;
383   vector<unsigned> pi{3, 1, 4, 1, 5, 9};
384   unsigned iters = 0;
385 
386   for (auto tup : zip_first(SmallVector<bool, 0>{1, 1, 0, 1}, pi)) {
387     get<1>(tup) = get<0>(tup);
388     iters += 1;
389   }
390 
391   EXPECT_EQ(iters, 4u);
392 
393   for (auto tup : zip_first(SmallVector<bool, 0>{1, 1, 0, 1}, pi)) {
394     EXPECT_EQ(get<0>(tup), get<1>(tup));
395   }
396 }
397 
398 TEST(ZipIteratorTest, Filter) {
399   using namespace std;
400   vector<unsigned> pi{3, 1, 4, 1, 5, 9};
401 
402   unsigned iters = 0;
403   // pi is length 6, but the zip RHS is length 7.
404   auto zipped = zip_first(pi, vector<bool>{1, 1, 0, 1, 1, 1, 0});
405   for (auto tup : make_filter_range(
406            zipped, [](decltype(zipped)::value_type t) { return get<1>(t); })) {
407     EXPECT_EQ(get<0>(tup) & 0x01, get<1>(tup));
408     get<0>(tup) += 1;
409     iters += 1;
410   }
411 
412   // Should have skipped pi[2].
413   EXPECT_EQ(iters, 5u);
414 
415   // Ensure that in-place mutation works.
416   EXPECT_TRUE(all_of(pi, [](unsigned n) { return (n & 0x01) == 0; }));
417 }
418 
419 TEST(ZipIteratorTest, Reverse) {
420   using namespace std;
421   vector<unsigned> ascending{0, 1, 2, 3, 4, 5};
422 
423   auto zipped = zip_first(ascending, vector<bool>{0, 1, 0, 1, 0, 1});
424   unsigned last = 6;
425   for (auto tup : reverse(zipped)) {
426     // Check that this is in reverse.
427     EXPECT_LT(get<0>(tup), last);
428     last = get<0>(tup);
429     EXPECT_EQ(get<0>(tup) & 0x01, get<1>(tup));
430   }
431 
432   auto odds = [](decltype(zipped)::value_type tup) { return get<1>(tup); };
433   last = 6;
434   for (auto tup : make_filter_range(reverse(zipped), odds)) {
435     EXPECT_LT(get<0>(tup), last);
436     last = get<0>(tup);
437     EXPECT_TRUE(get<0>(tup) & 0x01);
438     get<0>(tup) += 1;
439   }
440 
441   // Ensure that in-place mutation works.
442   EXPECT_TRUE(all_of(ascending, [](unsigned n) { return (n & 0x01) == 0; }));
443 }
444 
445 TEST(RangeTest, Distance) {
446   std::vector<int> v1;
447   std::vector<int> v2{1, 2, 3};
448 
449   EXPECT_EQ(std::distance(v1.begin(), v1.end()), size(v1));
450   EXPECT_EQ(std::distance(v2.begin(), v2.end()), size(v2));
451 }
452 
453 TEST(IteratorRangeTest, DropBegin) {
454   SmallVector<int, 5> vec{0, 1, 2, 3, 4};
455 
456   for (int n = 0; n < 5; ++n) {
457     int i = n;
458     for (auto &v : drop_begin(vec, n)) {
459       EXPECT_EQ(v, i);
460       i += 1;
461     }
462     EXPECT_EQ(i, 5);
463   }
464 }
465 
466 } // anonymous namespace
467