• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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