blob: a8d5b33a0b4975f3567ffd81d5db1ebfd1f074ab [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
10#include "llvm/ADT/iterator.h"
Chandler Carruthd5835ee2014-04-24 21:10:35 +000011#include "llvm/ADT/STLExtras.h"
Chandler Carruth9a6be8b2014-04-24 03:31:23 +000012#include "llvm/ADT/SmallVector.h"
13#include "gtest/gtest.h"
14
15using namespace llvm;
16
17namespace {
18
Tim Shen75c16562016-08-09 20:23:13 +000019template <int> struct Shadow;
20
21struct WeirdIter : std::iterator<std::input_iterator_tag, Shadow<0>, Shadow<1>,
22 Shadow<2>, Shadow<3>> {};
23
24struct AdaptedIter : iterator_adaptor_base<AdaptedIter, WeirdIter> {};
25
26// Test that iterator_adaptor_base forwards typedefs, if value_type is
27// unchanged.
28static_assert(std::is_same<typename AdaptedIter::value_type, Shadow<0>>::value,
29 "");
30static_assert(
31 std::is_same<typename AdaptedIter::difference_type, Shadow<1>>::value, "");
32static_assert(std::is_same<typename AdaptedIter::pointer, Shadow<2>>::value,
33 "");
34static_assert(std::is_same<typename AdaptedIter::reference, Shadow<3>>::value,
35 "");
36
Chandler Carruth9a6be8b2014-04-24 03:31:23 +000037TEST(PointeeIteratorTest, Basic) {
38 int arr[4] = { 1, 2, 3, 4 };
39 SmallVector<int *, 4> V;
40 V.push_back(&arr[0]);
41 V.push_back(&arr[1]);
42 V.push_back(&arr[2]);
43 V.push_back(&arr[3]);
44
Justin Lebar4765c012016-10-10 19:56:52 +000045 typedef pointee_iterator<SmallVectorImpl<int *>::const_iterator> test_iterator;
Chandler Carruth9a6be8b2014-04-24 03:31:23 +000046
Justin Lebar4765c012016-10-10 19:56:52 +000047 test_iterator Begin, End;
48 Begin = V.begin();
49 End = test_iterator(V.end());
50
51 test_iterator I = Begin;
Chandler Carruth9a6be8b2014-04-24 03:31:23 +000052 for (int i = 0; i < 4; ++i) {
53 EXPECT_EQ(*V[i], *I);
54
55 EXPECT_EQ(I, Begin + i);
56 EXPECT_EQ(I, std::next(Begin, i));
Justin Lebar4765c012016-10-10 19:56:52 +000057 test_iterator J = Begin;
Chandler Carruth9a6be8b2014-04-24 03:31:23 +000058 J += i;
59 EXPECT_EQ(I, J);
60 EXPECT_EQ(*V[i], Begin[i]);
61
62 EXPECT_NE(I, End);
63 EXPECT_GT(End, I);
64 EXPECT_LT(I, End);
65 EXPECT_GE(I, Begin);
66 EXPECT_LE(Begin, I);
67
68 EXPECT_EQ(i, I - Begin);
69 EXPECT_EQ(i, std::distance(Begin, I));
70 EXPECT_EQ(Begin, I - i);
71
Justin Lebar4765c012016-10-10 19:56:52 +000072 test_iterator K = I++;
Chandler Carruth9a6be8b2014-04-24 03:31:23 +000073 EXPECT_EQ(K, std::prev(I));
74 }
75 EXPECT_EQ(End, I);
76}
77
Chandler Carruthd5835ee2014-04-24 21:10:35 +000078TEST(PointeeIteratorTest, SmartPointer) {
79 SmallVector<std::unique_ptr<int>, 4> V;
80 V.push_back(make_unique<int>(1));
81 V.push_back(make_unique<int>(2));
82 V.push_back(make_unique<int>(3));
83 V.push_back(make_unique<int>(4));
84
Justin Lebar4765c012016-10-10 19:56:52 +000085 typedef pointee_iterator<
86 SmallVectorImpl<std::unique_ptr<int>>::const_iterator> test_iterator;
Chandler Carruthd5835ee2014-04-24 21:10:35 +000087
Justin Lebar4765c012016-10-10 19:56:52 +000088 test_iterator Begin, End;
89 Begin = V.begin();
90 End = test_iterator(V.end());
91
92 test_iterator I = Begin;
Chandler Carruthd5835ee2014-04-24 21:10:35 +000093 for (int i = 0; i < 4; ++i) {
94 EXPECT_EQ(*V[i], *I);
95
96 EXPECT_EQ(I, Begin + i);
97 EXPECT_EQ(I, std::next(Begin, i));
Justin Lebar4765c012016-10-10 19:56:52 +000098 test_iterator J = Begin;
Chandler Carruthd5835ee2014-04-24 21:10:35 +000099 J += i;
100 EXPECT_EQ(I, J);
101 EXPECT_EQ(*V[i], Begin[i]);
102
103 EXPECT_NE(I, End);
104 EXPECT_GT(End, I);
105 EXPECT_LT(I, End);
106 EXPECT_GE(I, Begin);
107 EXPECT_LE(Begin, I);
108
109 EXPECT_EQ(i, I - Begin);
110 EXPECT_EQ(i, std::distance(Begin, I));
111 EXPECT_EQ(Begin, I - i);
112
Justin Lebar4765c012016-10-10 19:56:52 +0000113 test_iterator K = I++;
Chandler Carruthd5835ee2014-04-24 21:10:35 +0000114 EXPECT_EQ(K, std::prev(I));
115 }
116 EXPECT_EQ(End, I);
117}
118
Tim Shene78e32a2016-08-12 22:03:28 +0000119TEST(FilterIteratorTest, Lambda) {
120 auto IsOdd = [](int N) { return N % 2 == 1; };
121 int A[] = {0, 1, 2, 3, 4, 5, 6};
122 auto Range = make_filter_range(A, IsOdd);
123 SmallVector<int, 3> Actual(Range.begin(), Range.end());
124 EXPECT_EQ((SmallVector<int, 3>{1, 3, 5}), Actual);
125}
126
127TEST(FilterIteratorTest, CallableObject) {
128 int Counter = 0;
129 struct Callable {
130 int &Counter;
131
132 Callable(int &Counter) : Counter(Counter) {}
133
134 bool operator()(int N) {
135 Counter++;
136 return N % 2 == 1;
137 }
138 };
139 Callable IsOdd(Counter);
140 int A[] = {0, 1, 2, 3, 4, 5, 6};
141 auto Range = make_filter_range(A, IsOdd);
142 EXPECT_EQ(2, Counter);
143 SmallVector<int, 3> Actual(Range.begin(), Range.end());
144 EXPECT_GE(Counter, 7);
145 EXPECT_EQ((SmallVector<int, 3>{1, 3, 5}), Actual);
146}
147
148TEST(FilterIteratorTest, FunctionPointer) {
149 bool (*IsOdd)(int) = [](int N) { return N % 2 == 1; };
150 int A[] = {0, 1, 2, 3, 4, 5, 6};
151 auto Range = make_filter_range(A, IsOdd);
152 SmallVector<int, 3> Actual(Range.begin(), Range.end());
153 EXPECT_EQ((SmallVector<int, 3>{1, 3, 5}), Actual);
154}
155
156TEST(FilterIteratorTest, Composition) {
157 auto IsOdd = [](int N) { return N % 2 == 1; };
158 std::unique_ptr<int> A[] = {make_unique<int>(0), make_unique<int>(1),
159 make_unique<int>(2), make_unique<int>(3),
160 make_unique<int>(4), make_unique<int>(5),
161 make_unique<int>(6)};
162 using PointeeIterator = pointee_iterator<std::unique_ptr<int> *>;
163 auto Range = make_filter_range(
164 make_range(PointeeIterator(std::begin(A)), PointeeIterator(std::end(A))),
165 IsOdd);
166 SmallVector<int, 3> Actual(Range.begin(), Range.end());
167 EXPECT_EQ((SmallVector<int, 3>{1, 3, 5}), Actual);
168}
169
170TEST(FilterIteratorTest, InputIterator) {
171 struct InputIterator
172 : iterator_adaptor_base<InputIterator, int *, std::input_iterator_tag> {
173 using BaseT =
174 iterator_adaptor_base<InputIterator, int *, std::input_iterator_tag>;
175
176 InputIterator(int *It) : BaseT(It) {}
177 };
178
179 auto IsOdd = [](int N) { return N % 2 == 1; };
180 int A[] = {0, 1, 2, 3, 4, 5, 6};
181 auto Range = make_filter_range(
182 make_range(InputIterator(std::begin(A)), InputIterator(std::end(A))),
183 IsOdd);
184 SmallVector<int, 3> Actual(Range.begin(), Range.end());
185 EXPECT_EQ((SmallVector<int, 3>{1, 3, 5}), Actual);
186}
187
Tim Shencf03add2016-08-19 21:04:45 +0000188TEST(PointerIterator, Basic) {
189 int A[] = {1, 2, 3, 4};
Justin Lebar4765c012016-10-10 19:56:52 +0000190 pointer_iterator<int *> Begin(std::begin(A)), End(std::end(A));
Tim Shencf03add2016-08-19 21:04:45 +0000191 EXPECT_EQ(A, *Begin);
192 ++Begin;
193 EXPECT_EQ(A + 1, *Begin);
194 ++Begin;
195 EXPECT_EQ(A + 2, *Begin);
196 ++Begin;
197 EXPECT_EQ(A + 3, *Begin);
198 ++Begin;
199 EXPECT_EQ(Begin, End);
200}
201
202TEST(PointerIterator, Const) {
203 int A[] = {1, 2, 3, 4};
Justin Lebar4765c012016-10-10 19:56:52 +0000204 const pointer_iterator<int *> Begin(std::begin(A));
Tim Shencf03add2016-08-19 21:04:45 +0000205 EXPECT_EQ(A, *Begin);
206 EXPECT_EQ(A + 1, std::next(*Begin, 1));
207 EXPECT_EQ(A + 2, std::next(*Begin, 2));
208 EXPECT_EQ(A + 3, std::next(*Begin, 3));
209 EXPECT_EQ(A + 4, std::next(*Begin, 4));
210}
211
Mehdi Aminia8515452016-10-19 18:02:21 +0000212TEST(ZipIteratorTest, Basic) {
213 using namespace std;
214 const SmallVector<unsigned, 6> pi{3, 1, 4, 1, 5, 9};
215 SmallVector<bool, 6> odd{1, 1, 0, 1, 1, 1};
216 const char message[] = "yynyyy\0";
217
218 for (auto tup : zip(pi, odd, message)) {
219 EXPECT_EQ(get<0>(tup) & 0x01, get<1>(tup));
220 EXPECT_EQ(get<0>(tup) & 0x01 ? 'y' : 'n', get<2>(tup));
221 }
222
223 // note the rvalue
224 for (auto tup : zip(pi, SmallVector<bool, 0>{1, 1, 0, 1, 1})) {
225 EXPECT_EQ(get<0>(tup) & 0x01, get<1>(tup));
226 }
227}
228
229TEST(ZipIteratorTest, ZipFirstBasic) {
230 using namespace std;
231 const SmallVector<unsigned, 6> pi{3, 1, 4, 1, 5, 9};
232 unsigned iters = 0;
233
234 for (auto tup : zip_first(SmallVector<bool, 0>{1, 1, 0, 1}, pi)) {
235 EXPECT_EQ(get<0>(tup), get<1>(tup) & 0x01);
236 iters += 1;
237 }
238
239 EXPECT_EQ(iters, 4u);
240}
241
242TEST(ZipIteratorTest, Mutability) {
243 using namespace std;
244 const SmallVector<unsigned, 4> pi{3, 1, 4, 1, 5, 9};
245 char message[] = "hello zip\0";
246
247 for (auto tup : zip(pi, message, message)) {
248 EXPECT_EQ(get<1>(tup), get<2>(tup));
249 get<2>(tup) = get<0>(tup) & 0x01 ? 'y' : 'n';
250 }
251
252 // note the rvalue
253 for (auto tup : zip(message, "yynyyyzip\0")) {
254 EXPECT_EQ(get<0>(tup), get<1>(tup));
255 }
256}
257
258TEST(ZipIteratorTest, ZipFirstMutability) {
259 using namespace std;
260 vector<unsigned> pi{3, 1, 4, 1, 5, 9};
261 unsigned iters = 0;
262
263 for (auto tup : zip_first(SmallVector<bool, 0>{1, 1, 0, 1}, pi)) {
264 get<1>(tup) = get<0>(tup);
265 iters += 1;
266 }
267
268 EXPECT_EQ(iters, 4u);
269
270 for (auto tup : zip_first(SmallVector<bool, 0>{1, 1, 0, 1}, pi)) {
271 EXPECT_EQ(get<0>(tup), get<1>(tup));
272 }
273}
274
Chandler Carruth9a6be8b2014-04-24 03:31:23 +0000275} // anonymous namespace