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