1 //===- RangeAdapterTest.cpp - Unit tests for range adapters --------------===// 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_range.h" 11 #include "llvm/ADT/STLExtras.h" 12 #include "gtest/gtest.h" 13 14 #include <iterator> 15 #include <list> 16 #include <vector> 17 18 using namespace llvm; 19 20 namespace { 21 22 // A wrapper around vector which exposes rbegin(), rend(). 23 class ReverseOnlyVector { 24 std::vector<int> Vec; 25 26 public: 27 ReverseOnlyVector(std::initializer_list<int> list) : Vec(list) {} 28 29 typedef std::vector<int>::reverse_iterator reverse_iterator; 30 typedef std::vector<int>::const_reverse_iterator const_reverse_iterator; 31 reverse_iterator rbegin() { return Vec.rbegin(); } 32 reverse_iterator rend() { return Vec.rend(); } 33 const_reverse_iterator rbegin() const { return Vec.rbegin(); } 34 const_reverse_iterator rend() const { return Vec.rend(); } 35 }; 36 37 // A wrapper around vector which exposes begin(), end(), rbegin() and rend(). 38 // begin() and end() don't have implementations as this ensures that we will 39 // get a linker error if reverse() chooses begin()/end() over rbegin(), rend(). 40 class BidirectionalVector { 41 mutable std::vector<int> Vec; 42 43 public: 44 BidirectionalVector(std::initializer_list<int> list) : Vec(list) {} 45 46 typedef std::vector<int>::iterator iterator; 47 iterator begin() const; 48 iterator end() const; 49 50 typedef std::vector<int>::reverse_iterator reverse_iterator; 51 reverse_iterator rbegin() const { return Vec.rbegin(); } 52 reverse_iterator rend() const { return Vec.rend(); } 53 }; 54 55 /// This is the same as BidirectionalVector but with the addition of const 56 /// begin/rbegin methods to ensure that the type traits for has_rbegin works. 57 class BidirectionalVectorConsts { 58 std::vector<int> Vec; 59 60 public: 61 BidirectionalVectorConsts(std::initializer_list<int> list) : Vec(list) {} 62 63 typedef std::vector<int>::iterator iterator; 64 typedef std::vector<int>::const_iterator const_iterator; 65 iterator begin(); 66 iterator end(); 67 const_iterator begin() const; 68 const_iterator end() const; 69 70 typedef std::vector<int>::reverse_iterator reverse_iterator; 71 typedef std::vector<int>::const_reverse_iterator const_reverse_iterator; 72 reverse_iterator rbegin() { return Vec.rbegin(); } 73 reverse_iterator rend() { return Vec.rend(); } 74 const_reverse_iterator rbegin() const { return Vec.rbegin(); } 75 const_reverse_iterator rend() const { return Vec.rend(); } 76 }; 77 78 /// Check that types with custom iterators work. 79 class CustomIteratorVector { 80 mutable std::vector<int> V; 81 82 public: 83 CustomIteratorVector(std::initializer_list<int> list) : V(list) {} 84 85 typedef std::vector<int>::iterator iterator; 86 class reverse_iterator { 87 std::vector<int>::iterator I; 88 89 public: 90 reverse_iterator() = default; 91 reverse_iterator(const reverse_iterator &) = default; 92 reverse_iterator &operator=(const reverse_iterator &) = default; 93 94 explicit reverse_iterator(std::vector<int>::iterator I) : I(I) {} 95 96 reverse_iterator &operator++() { 97 --I; 98 return *this; 99 } 100 reverse_iterator &operator--() { 101 ++I; 102 return *this; 103 } 104 int &operator*() const { return *std::prev(I); } 105 int *operator->() const { return &*std::prev(I); } 106 friend bool operator==(const reverse_iterator &L, 107 const reverse_iterator &R) { 108 return L.I == R.I; 109 } 110 friend bool operator!=(const reverse_iterator &L, 111 const reverse_iterator &R) { 112 return !(L == R); 113 } 114 }; 115 116 iterator begin() const { return V.begin(); } 117 iterator end() const { return V.end(); } 118 reverse_iterator rbegin() const { return reverse_iterator(V.end()); } 119 reverse_iterator rend() const { return reverse_iterator(V.begin()); } 120 }; 121 122 template <typename R> void TestRev(const R &r) { 123 int counter = 3; 124 for (int i : r) 125 EXPECT_EQ(i, counter--); 126 } 127 128 // Test fixture 129 template <typename T> class RangeAdapterLValueTest : public ::testing::Test {}; 130 131 typedef ::testing::Types<std::vector<int>, std::list<int>, int[4]> 132 RangeAdapterLValueTestTypes; 133 TYPED_TEST_CASE(RangeAdapterLValueTest, RangeAdapterLValueTestTypes); 134 135 TYPED_TEST(RangeAdapterLValueTest, TrivialOperation) { 136 TypeParam v = {0, 1, 2, 3}; 137 TestRev(reverse(v)); 138 139 const TypeParam c = {0, 1, 2, 3}; 140 TestRev(reverse(c)); 141 } 142 143 template <typename T> struct RangeAdapterRValueTest : testing::Test {}; 144 145 typedef ::testing::Types<std::vector<int>, std::list<int>, CustomIteratorVector, 146 ReverseOnlyVector, BidirectionalVector, 147 BidirectionalVectorConsts> 148 RangeAdapterRValueTestTypes; 149 TYPED_TEST_CASE(RangeAdapterRValueTest, RangeAdapterRValueTestTypes); 150 151 TYPED_TEST(RangeAdapterRValueTest, TrivialOperation) { 152 TestRev(reverse(TypeParam({0, 1, 2, 3}))); 153 } 154 155 TYPED_TEST(RangeAdapterRValueTest, HasRbegin) { 156 static_assert(has_rbegin<TypeParam>::value, "rbegin() should be defined"); 157 } 158 159 TYPED_TEST(RangeAdapterRValueTest, RangeType) { 160 static_assert( 161 std::is_same< 162 decltype(reverse(*static_cast<TypeParam *>(nullptr)).begin()), 163 decltype(static_cast<TypeParam *>(nullptr)->rbegin())>::value, 164 "reverse().begin() should have the same type as rbegin()"); 165 static_assert( 166 std::is_same< 167 decltype(reverse(*static_cast<const TypeParam *>(nullptr)).begin()), 168 decltype(static_cast<const TypeParam *>(nullptr)->rbegin())>::value, 169 "reverse().begin() should have the same type as rbegin() [const]"); 170 } 171 172 } // anonymous namespace 173