blob: edc1ced72ba9f3377846b8cd15da92b2338984cf [file] [log] [blame]
Pete Cooper639ec3d2015-07-29 22:19:09 +00001//===- 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
Pete Cooper639ec3d2015-07-29 22:19:09 +000010#include "llvm/ADT/STLExtras.h"
Chandler Carruth3c0d6072017-06-06 11:06:56 +000011#include "llvm/ADT/iterator_range.h"
Pete Cooper639ec3d2015-07-29 22:19:09 +000012#include "gtest/gtest.h"
13
14#include <iterator>
15#include <list>
16#include <vector>
17
18using namespace llvm;
19
20namespace {
21
22// A wrapper around vector which exposes rbegin(), rend().
23class ReverseOnlyVector {
24 std::vector<int> Vec;
25
26public:
27 ReverseOnlyVector(std::initializer_list<int> list) : Vec(list) {}
28
29 typedef std::vector<int>::reverse_iterator reverse_iterator;
Pete Coopercebbb5e2016-08-17 22:06:59 +000030 typedef std::vector<int>::const_reverse_iterator const_reverse_iterator;
Pete Cooper639ec3d2015-07-29 22:19:09 +000031 reverse_iterator rbegin() { return Vec.rbegin(); }
32 reverse_iterator rend() { return Vec.rend(); }
Pete Coopercebbb5e2016-08-17 22:06:59 +000033 const_reverse_iterator rbegin() const { return Vec.rbegin(); }
34 const_reverse_iterator rend() const { return Vec.rend(); }
Pete Cooper639ec3d2015-07-29 22:19:09 +000035};
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().
40class BidirectionalVector {
Duncan P. N. Exon Smithcd8d0342016-08-18 17:15:25 +000041 mutable std::vector<int> Vec;
Pete Cooper639ec3d2015-07-29 22:19:09 +000042
43public:
44 BidirectionalVector(std::initializer_list<int> list) : Vec(list) {}
45
46 typedef std::vector<int>::iterator iterator;
Duncan P. N. Exon Smithcd8d0342016-08-18 17:15:25 +000047 iterator begin() const;
48 iterator end() const;
Pete Cooper639ec3d2015-07-29 22:19:09 +000049
50 typedef std::vector<int>::reverse_iterator reverse_iterator;
Duncan P. N. Exon Smithcd8d0342016-08-18 17:15:25 +000051 reverse_iterator rbegin() const { return Vec.rbegin(); }
52 reverse_iterator rend() const { return Vec.rend(); }
Pete Cooper639ec3d2015-07-29 22:19:09 +000053};
54
Pete Coopercebbb5e2016-08-17 22:06:59 +000055/// 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.
57class BidirectionalVectorConsts {
58 std::vector<int> Vec;
59
60public:
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
Duncan P. N. Exon Smithcd8d0342016-08-18 17:15:25 +000078/// Check that types with custom iterators work.
79class CustomIteratorVector {
80 mutable std::vector<int> V;
81
82public:
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
Pete Cooper639ec3d2015-07-29 22:19:09 +0000122template <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
129template <typename T> class RangeAdapterLValueTest : public ::testing::Test {};
130
131typedef ::testing::Types<std::vector<int>, std::list<int>, int[4]>
132 RangeAdapterLValueTestTypes;
133TYPED_TEST_CASE(RangeAdapterLValueTest, RangeAdapterLValueTestTypes);
134
135TYPED_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
143template <typename T> struct RangeAdapterRValueTest : testing::Test {};
144
Duncan P. N. Exon Smithcd8d0342016-08-18 17:15:25 +0000145typedef ::testing::Types<std::vector<int>, std::list<int>, CustomIteratorVector,
146 ReverseOnlyVector, BidirectionalVector,
147 BidirectionalVectorConsts>
148 RangeAdapterRValueTestTypes;
Pete Cooper639ec3d2015-07-29 22:19:09 +0000149TYPED_TEST_CASE(RangeAdapterRValueTest, RangeAdapterRValueTestTypes);
150
151TYPED_TEST(RangeAdapterRValueTest, TrivialOperation) {
152 TestRev(reverse(TypeParam({0, 1, 2, 3})));
153}
154
Pete Coopercebbb5e2016-08-17 22:06:59 +0000155TYPED_TEST(RangeAdapterRValueTest, HasRbegin) {
Duncan P. N. Exon Smithcd8d0342016-08-18 17:15:25 +0000156 static_assert(has_rbegin<TypeParam>::value, "rbegin() should be defined");
157}
158
159TYPED_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]");
Pete Coopercebbb5e2016-08-17 22:06:59 +0000170}
171
Pete Cooper639ec3d2015-07-29 22:19:09 +0000172} // anonymous namespace