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