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/STLExtras.h" 11 #include "llvm/ADT/SmallVector.h" 12 #include "llvm/ADT/iterator.h" 13 #include "gtest/gtest.h" 14 15 using namespace llvm; 16 17 namespace { 18 19 template <int> struct Shadow; 20 21 struct WeirdIter : std::iterator<std::input_iterator_tag, Shadow<0>, Shadow<1>, 22 Shadow<2>, Shadow<3>> {}; 23 24 struct AdaptedIter : iterator_adaptor_base<AdaptedIter, WeirdIter> {}; 25 26 // Test that iterator_adaptor_base forwards typedefs, if value_type is 27 // unchanged. 28 static_assert(std::is_same<typename AdaptedIter::value_type, Shadow<0>>::value, 29 ""); 30 static_assert( 31 std::is_same<typename AdaptedIter::difference_type, Shadow<1>>::value, ""); 32 static_assert(std::is_same<typename AdaptedIter::pointer, Shadow<2>>::value, 33 ""); 34 static_assert(std::is_same<typename AdaptedIter::reference, Shadow<3>>::value, 35 ""); 36 37 TEST(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 45 typedef pointee_iterator<SmallVectorImpl<int *>::const_iterator> 46 test_iterator; 47 48 test_iterator Begin, End; 49 Begin = V.begin(); 50 End = test_iterator(V.end()); 51 52 test_iterator I = Begin; 53 for (int i = 0; i < 4; ++i) { 54 EXPECT_EQ(*V[i], *I); 55 56 EXPECT_EQ(I, Begin + i); 57 EXPECT_EQ(I, std::next(Begin, i)); 58 test_iterator J = Begin; 59 J += i; 60 EXPECT_EQ(I, J); 61 EXPECT_EQ(*V[i], Begin[i]); 62 63 EXPECT_NE(I, End); 64 EXPECT_GT(End, I); 65 EXPECT_LT(I, End); 66 EXPECT_GE(I, Begin); 67 EXPECT_LE(Begin, I); 68 69 EXPECT_EQ(i, I - Begin); 70 EXPECT_EQ(i, std::distance(Begin, I)); 71 EXPECT_EQ(Begin, I - i); 72 73 test_iterator K = I++; 74 EXPECT_EQ(K, std::prev(I)); 75 } 76 EXPECT_EQ(End, I); 77 } 78 79 TEST(PointeeIteratorTest, SmartPointer) { 80 SmallVector<std::unique_ptr<int>, 4> V; 81 V.push_back(make_unique<int>(1)); 82 V.push_back(make_unique<int>(2)); 83 V.push_back(make_unique<int>(3)); 84 V.push_back(make_unique<int>(4)); 85 86 typedef pointee_iterator< 87 SmallVectorImpl<std::unique_ptr<int>>::const_iterator> 88 test_iterator; 89 90 test_iterator Begin, End; 91 Begin = V.begin(); 92 End = test_iterator(V.end()); 93 94 test_iterator I = Begin; 95 for (int i = 0; i < 4; ++i) { 96 EXPECT_EQ(*V[i], *I); 97 98 EXPECT_EQ(I, Begin + i); 99 EXPECT_EQ(I, std::next(Begin, i)); 100 test_iterator J = Begin; 101 J += i; 102 EXPECT_EQ(I, J); 103 EXPECT_EQ(*V[i], Begin[i]); 104 105 EXPECT_NE(I, End); 106 EXPECT_GT(End, I); 107 EXPECT_LT(I, End); 108 EXPECT_GE(I, Begin); 109 EXPECT_LE(Begin, I); 110 111 EXPECT_EQ(i, I - Begin); 112 EXPECT_EQ(i, std::distance(Begin, I)); 113 EXPECT_EQ(Begin, I - i); 114 115 test_iterator K = I++; 116 EXPECT_EQ(K, std::prev(I)); 117 } 118 EXPECT_EQ(End, I); 119 } 120 121 TEST(FilterIteratorTest, Lambda) { 122 auto IsOdd = [](int N) { return N % 2 == 1; }; 123 int A[] = {0, 1, 2, 3, 4, 5, 6}; 124 auto Range = make_filter_range(A, IsOdd); 125 SmallVector<int, 3> Actual(Range.begin(), Range.end()); 126 EXPECT_EQ((SmallVector<int, 3>{1, 3, 5}), Actual); 127 } 128 129 TEST(FilterIteratorTest, CallableObject) { 130 int Counter = 0; 131 struct Callable { 132 int &Counter; 133 134 Callable(int &Counter) : Counter(Counter) {} 135 136 bool operator()(int N) { 137 Counter++; 138 return N % 2 == 1; 139 } 140 }; 141 Callable IsOdd(Counter); 142 int A[] = {0, 1, 2, 3, 4, 5, 6}; 143 auto Range = make_filter_range(A, IsOdd); 144 EXPECT_EQ(2, Counter); 145 SmallVector<int, 3> Actual(Range.begin(), Range.end()); 146 EXPECT_GE(Counter, 7); 147 EXPECT_EQ((SmallVector<int, 3>{1, 3, 5}), Actual); 148 } 149 150 TEST(FilterIteratorTest, FunctionPointer) { 151 bool (*IsOdd)(int) = [](int N) { return N % 2 == 1; }; 152 int A[] = {0, 1, 2, 3, 4, 5, 6}; 153 auto Range = make_filter_range(A, IsOdd); 154 SmallVector<int, 3> Actual(Range.begin(), Range.end()); 155 EXPECT_EQ((SmallVector<int, 3>{1, 3, 5}), Actual); 156 } 157 158 TEST(FilterIteratorTest, Composition) { 159 auto IsOdd = [](int N) { return N % 2 == 1; }; 160 std::unique_ptr<int> A[] = {make_unique<int>(0), make_unique<int>(1), 161 make_unique<int>(2), make_unique<int>(3), 162 make_unique<int>(4), make_unique<int>(5), 163 make_unique<int>(6)}; 164 using PointeeIterator = pointee_iterator<std::unique_ptr<int> *>; 165 auto Range = make_filter_range( 166 make_range(PointeeIterator(std::begin(A)), PointeeIterator(std::end(A))), 167 IsOdd); 168 SmallVector<int, 3> Actual(Range.begin(), Range.end()); 169 EXPECT_EQ((SmallVector<int, 3>{1, 3, 5}), Actual); 170 } 171 172 TEST(FilterIteratorTest, InputIterator) { 173 struct InputIterator 174 : iterator_adaptor_base<InputIterator, int *, std::input_iterator_tag> { 175 using BaseT = 176 iterator_adaptor_base<InputIterator, int *, std::input_iterator_tag>; 177 178 InputIterator(int *It) : BaseT(It) {} 179 }; 180 181 auto IsOdd = [](int N) { return N % 2 == 1; }; 182 int A[] = {0, 1, 2, 3, 4, 5, 6}; 183 auto Range = make_filter_range( 184 make_range(InputIterator(std::begin(A)), InputIterator(std::end(A))), 185 IsOdd); 186 SmallVector<int, 3> Actual(Range.begin(), Range.end()); 187 EXPECT_EQ((SmallVector<int, 3>{1, 3, 5}), Actual); 188 } 189 190 TEST(PointerIterator, Basic) { 191 int A[] = {1, 2, 3, 4}; 192 pointer_iterator<int *> Begin(std::begin(A)), End(std::end(A)); 193 EXPECT_EQ(A, *Begin); 194 ++Begin; 195 EXPECT_EQ(A + 1, *Begin); 196 ++Begin; 197 EXPECT_EQ(A + 2, *Begin); 198 ++Begin; 199 EXPECT_EQ(A + 3, *Begin); 200 ++Begin; 201 EXPECT_EQ(Begin, End); 202 } 203 204 TEST(PointerIterator, Const) { 205 int A[] = {1, 2, 3, 4}; 206 const pointer_iterator<int *> Begin(std::begin(A)); 207 EXPECT_EQ(A, *Begin); 208 EXPECT_EQ(A + 1, std::next(*Begin, 1)); 209 EXPECT_EQ(A + 2, std::next(*Begin, 2)); 210 EXPECT_EQ(A + 3, std::next(*Begin, 3)); 211 EXPECT_EQ(A + 4, std::next(*Begin, 4)); 212 } 213 214 TEST(ZipIteratorTest, Basic) { 215 using namespace std; 216 const SmallVector<unsigned, 6> pi{3, 1, 4, 1, 5, 9}; 217 SmallVector<bool, 6> odd{1, 1, 0, 1, 1, 1}; 218 const char message[] = "yynyyy\0"; 219 220 for (auto tup : zip(pi, odd, message)) { 221 EXPECT_EQ(get<0>(tup) & 0x01, get<1>(tup)); 222 EXPECT_EQ(get<0>(tup) & 0x01 ? 'y' : 'n', get<2>(tup)); 223 } 224 225 // note the rvalue 226 for (auto tup : zip(pi, SmallVector<bool, 0>{1, 1, 0, 1, 1})) { 227 EXPECT_EQ(get<0>(tup) & 0x01, get<1>(tup)); 228 } 229 } 230 231 TEST(ZipIteratorTest, ZipFirstBasic) { 232 using namespace std; 233 const SmallVector<unsigned, 6> pi{3, 1, 4, 1, 5, 9}; 234 unsigned iters = 0; 235 236 for (auto tup : zip_first(SmallVector<bool, 0>{1, 1, 0, 1}, pi)) { 237 EXPECT_EQ(get<0>(tup), get<1>(tup) & 0x01); 238 iters += 1; 239 } 240 241 EXPECT_EQ(iters, 4u); 242 } 243 244 TEST(ZipIteratorTest, Mutability) { 245 using namespace std; 246 const SmallVector<unsigned, 4> pi{3, 1, 4, 1, 5, 9}; 247 char message[] = "hello zip\0"; 248 249 for (auto tup : zip(pi, message, message)) { 250 EXPECT_EQ(get<1>(tup), get<2>(tup)); 251 get<2>(tup) = get<0>(tup) & 0x01 ? 'y' : 'n'; 252 } 253 254 // note the rvalue 255 for (auto tup : zip(message, "yynyyyzip\0")) { 256 EXPECT_EQ(get<0>(tup), get<1>(tup)); 257 } 258 } 259 260 TEST(ZipIteratorTest, ZipFirstMutability) { 261 using namespace std; 262 vector<unsigned> pi{3, 1, 4, 1, 5, 9}; 263 unsigned iters = 0; 264 265 for (auto tup : zip_first(SmallVector<bool, 0>{1, 1, 0, 1}, pi)) { 266 get<1>(tup) = get<0>(tup); 267 iters += 1; 268 } 269 270 EXPECT_EQ(iters, 4u); 271 272 for (auto tup : zip_first(SmallVector<bool, 0>{1, 1, 0, 1}, pi)) { 273 EXPECT_EQ(get<0>(tup), get<1>(tup)); 274 } 275 } 276 277 TEST(ZipIteratorTest, Filter) { 278 using namespace std; 279 vector<unsigned> pi{3, 1, 4, 1, 5, 9}; 280 281 unsigned iters = 0; 282 // pi is length 6, but the zip RHS is length 7. 283 auto zipped = zip_first(pi, vector<bool>{1, 1, 0, 1, 1, 1, 0}); 284 for (auto tup : make_filter_range( 285 zipped, [](decltype(zipped)::value_type t) { return get<1>(t); })) { 286 EXPECT_EQ(get<0>(tup) & 0x01, get<1>(tup)); 287 get<0>(tup) += 1; 288 iters += 1; 289 } 290 291 // Should have skipped pi[2]. 292 EXPECT_EQ(iters, 5u); 293 294 // Ensure that in-place mutation works. 295 EXPECT_TRUE(all_of(pi, [](unsigned n) { return (n & 0x01) == 0; })); 296 } 297 298 TEST(ZipIteratorTest, Reverse) { 299 using namespace std; 300 vector<unsigned> ascending{0, 1, 2, 3, 4, 5}; 301 302 auto zipped = zip_first(ascending, vector<bool>{0, 1, 0, 1, 0, 1}); 303 unsigned last = 6; 304 for (auto tup : reverse(zipped)) { 305 // Check that this is in reverse. 306 EXPECT_LT(get<0>(tup), last); 307 last = get<0>(tup); 308 EXPECT_EQ(get<0>(tup) & 0x01, get<1>(tup)); 309 } 310 311 auto odds = [](decltype(zipped)::value_type tup) { return get<1>(tup); }; 312 last = 6; 313 for (auto tup : make_filter_range(reverse(zipped), odds)) { 314 EXPECT_LT(get<0>(tup), last); 315 last = get<0>(tup); 316 EXPECT_TRUE(get<0>(tup) & 0x01); 317 get<0>(tup) += 1; 318 } 319 320 // Ensure that in-place mutation works. 321 EXPECT_TRUE(all_of(ascending, [](unsigned n) { return (n & 0x01) == 0; })); 322 } 323 324 } // anonymous namespace 325