• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright (c) 2017 Google Inc.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 //     http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 #include <utility>
16 #include <vector>
17 
18 #include "gmock/gmock.h"
19 #include "source/util/ilist.h"
20 
21 namespace spvtools {
22 namespace utils {
23 namespace {
24 
25 using ::testing::ElementsAre;
26 using IListTest = ::testing::Test;
27 
28 class TestNode : public IntrusiveNodeBase<TestNode> {
29  public:
TestNode()30   TestNode() : IntrusiveNodeBase<TestNode>() {}
31   int data_;
32 };
33 
34 class TestList : public IntrusiveList<TestNode> {
35  public:
36   TestList() = default;
TestList(TestList && that)37   TestList(TestList&& that) : IntrusiveList<TestNode>(std::move(that)) {}
operator =(TestList && that)38   TestList& operator=(TestList&& that) {
39     static_cast<IntrusiveList<TestNode>&>(*this) =
40         static_cast<IntrusiveList<TestNode>&&>(that);
41     return *this;
42   }
43 };
44 
45 // This test checks the push_back method, as well as using an iterator to
46 // traverse the list from begin() to end().  This implicitly test the
47 // PreviousNode and NextNode functions.
TEST(IListTest,PushBack)48 TEST(IListTest, PushBack) {
49   TestNode nodes[10];
50   TestList list;
51   for (int i = 0; i < 10; i++) {
52     nodes[i].data_ = i;
53     list.push_back(&nodes[i]);
54   }
55 
56   std::vector<int> output;
57   for (auto& i : list) output.push_back(i.data_);
58 
59   EXPECT_THAT(output, ElementsAre(0, 1, 2, 3, 4, 5, 6, 7, 8, 9));
60 }
61 
62 // Returns a list containing the values 0 to n-1 using the first n elements of
63 // nodes to build the list.
BuildList(TestNode nodes[],int n)64 TestList BuildList(TestNode nodes[], int n) {
65   TestList list;
66   for (int i = 0; i < n; i++) {
67     nodes[i].data_ = i;
68     list.push_back(&nodes[i]);
69   }
70   return list;
71 }
72 
73 // Test decrementing begin()
TEST(IListTest,DecrementingBegin)74 TEST(IListTest, DecrementingBegin) {
75   TestNode nodes[10];
76   TestList list = BuildList(nodes, 10);
77   EXPECT_EQ(--list.begin(), list.end());
78 }
79 
80 // Test incrementing end()
TEST(IListTest,IncrementingEnd1)81 TEST(IListTest, IncrementingEnd1) {
82   TestNode nodes[10];
83   TestList list = BuildList(nodes, 10);
84   EXPECT_EQ((++list.end())->data_, 0);
85 }
86 
87 // Test incrementing end() should equal begin()
TEST(IListTest,IncrementingEnd2)88 TEST(IListTest, IncrementingEnd2) {
89   TestNode nodes[10];
90   TestList list = BuildList(nodes, 10);
91   EXPECT_EQ(++list.end(), list.begin());
92 }
93 
94 // Test decrementing end()
TEST(IListTest,DecrementingEnd)95 TEST(IListTest, DecrementingEnd) {
96   TestNode nodes[10];
97   TestList list = BuildList(nodes, 10);
98   EXPECT_EQ((--list.end())->data_, 9);
99 }
100 
101 // Test the move constructor for the list class.
TEST(IListTest,MoveConstructor)102 TEST(IListTest, MoveConstructor) {
103   TestNode nodes[10];
104   TestList list = BuildList(nodes, 10);
105   std::vector<int> output;
106   for (auto& i : list) output.push_back(i.data_);
107 
108   EXPECT_THAT(output, ElementsAre(0, 1, 2, 3, 4, 5, 6, 7, 8, 9));
109 }
110 
111 // Using a const list so we can test the const_iterator.
TEST(IListTest,ConstIterator)112 TEST(IListTest, ConstIterator) {
113   TestNode nodes[10];
114   const TestList list = BuildList(nodes, 10);
115   std::vector<int> output;
116   for (auto& i : list) output.push_back(i.data_);
117 
118   EXPECT_THAT(output, ElementsAre(0, 1, 2, 3, 4, 5, 6, 7, 8, 9));
119 }
120 
121 // Uses the move assignement instead of the move constructor.
TEST(IListTest,MoveAssignment)122 TEST(IListTest, MoveAssignment) {
123   TestNode nodes[10];
124   TestList list;
125   list = BuildList(nodes, 10);
126   std::vector<int> output;
127   for (auto& i : list) output.push_back(i.data_);
128 
129   EXPECT_THAT(output, ElementsAre(0, 1, 2, 3, 4, 5, 6, 7, 8, 9));
130 }
131 
132 // Test inserting a new element at the end of a list using the IntrusiveNodeBase
133 // "InsertAfter" function.
TEST(IListTest,InsertAfter1)134 TEST(IListTest, InsertAfter1) {
135   TestNode nodes[10];
136   TestList list = BuildList(nodes, 5);
137 
138   nodes[5].data_ = 5;
139   nodes[5].InsertAfter(&nodes[4]);
140 
141   std::vector<int> output;
142   for (auto& i : list) output.push_back(i.data_);
143 
144   EXPECT_THAT(output, ElementsAre(0, 1, 2, 3, 4, 5));
145 }
146 
147 // Test inserting a new element in the middle of a list using the
148 // IntrusiveNodeBase "InsertAfter" function.
TEST(IListTest,InsertAfter2)149 TEST(IListTest, InsertAfter2) {
150   TestNode nodes[10];
151   TestList list = BuildList(nodes, 5);
152 
153   nodes[5].data_ = 5;
154   nodes[5].InsertAfter(&nodes[2]);
155 
156   std::vector<int> output;
157   for (auto& i : list) output.push_back(i.data_);
158 
159   EXPECT_THAT(output, ElementsAre(0, 1, 2, 5, 3, 4));
160 }
161 
162 // Test moving an element already in the list in the middle of a list using the
163 // IntrusiveNodeBase "InsertAfter" function.
TEST(IListTest,MoveUsingInsertAfter1)164 TEST(IListTest, MoveUsingInsertAfter1) {
165   TestNode nodes[10];
166   TestList list = BuildList(nodes, 6);
167 
168   nodes[5].InsertAfter(&nodes[2]);
169 
170   std::vector<int> output;
171   for (auto& i : list) output.push_back(i.data_);
172 
173   EXPECT_THAT(output, ElementsAre(0, 1, 2, 5, 3, 4));
174 }
175 
176 // Move the element at the start of the list into the middle.
TEST(IListTest,MoveUsingInsertAfter2)177 TEST(IListTest, MoveUsingInsertAfter2) {
178   TestNode nodes[10];
179   TestList list = BuildList(nodes, 6);
180 
181   nodes[0].InsertAfter(&nodes[2]);
182 
183   std::vector<int> output;
184   for (auto& i : list) output.push_back(i.data_);
185 
186   EXPECT_THAT(output, ElementsAre(1, 2, 0, 3, 4, 5));
187 }
188 
189 // Move an element in the middle of the list to the end.
TEST(IListTest,MoveUsingInsertAfter3)190 TEST(IListTest, MoveUsingInsertAfter3) {
191   TestNode nodes[10];
192   TestList list = BuildList(nodes, 6);
193 
194   nodes[2].InsertAfter(&nodes[5]);
195 
196   std::vector<int> output;
197   for (auto& i : list) output.push_back(i.data_);
198 
199   EXPECT_THAT(output, ElementsAre(0, 1, 3, 4, 5, 2));
200 }
201 
202 // Removing an element from the middle of a list.
TEST(IListTest,Remove1)203 TEST(IListTest, Remove1) {
204   TestNode nodes[10];
205   TestList list = BuildList(nodes, 6);
206 
207   nodes[2].RemoveFromList();
208 
209   std::vector<int> output;
210   for (auto& i : list) output.push_back(i.data_);
211 
212   EXPECT_THAT(output, ElementsAre(0, 1, 3, 4, 5));
213 }
214 
215 // Removing an element from the beginning of the list.
TEST(IListTest,Remove2)216 TEST(IListTest, Remove2) {
217   TestNode nodes[10];
218   TestList list = BuildList(nodes, 6);
219 
220   nodes[0].RemoveFromList();
221 
222   std::vector<int> output;
223   for (auto& i : list) output.push_back(i.data_);
224 
225   EXPECT_THAT(output, ElementsAre(1, 2, 3, 4, 5));
226 }
227 
228 // Removing the last element of a list.
TEST(IListTest,Remove3)229 TEST(IListTest, Remove3) {
230   TestNode nodes[10];
231   TestList list = BuildList(nodes, 6);
232 
233   nodes[5].RemoveFromList();
234 
235   std::vector<int> output;
236   for (auto& i : list) output.push_back(i.data_);
237 
238   EXPECT_THAT(output, ElementsAre(0, 1, 2, 3, 4));
239 }
240 
241 // Test that operator== and operator!= work properly for the iterator class.
TEST(IListTest,IteratorEqual)242 TEST(IListTest, IteratorEqual) {
243   TestNode nodes[10];
244   TestList list = BuildList(nodes, 6);
245 
246   std::vector<int> output;
247   for (auto i = list.begin(); i != list.end(); ++i)
248     for (auto j = list.begin(); j != list.end(); ++j)
249       if (i == j) output.push_back(i->data_);
250 
251   EXPECT_THAT(output, ElementsAre(0, 1, 2, 3, 4, 5));
252 }
253 
254 // Test MoveBefore.  Moving into middle of a list.
TEST(IListTest,MoveBefore1)255 TEST(IListTest, MoveBefore1) {
256   TestNode nodes[10];
257   TestList list1 = BuildList(nodes, 6);
258   TestList list2 = BuildList(nodes + 6, 3);
259 
260   TestList::iterator insertion_point = list1.begin();
261   ++insertion_point;
262   insertion_point.MoveBefore(&list2);
263 
264   std::vector<int> output;
265   for (auto i = list1.begin(); i != list1.end(); ++i) {
266     output.push_back(i->data_);
267   }
268 
269   EXPECT_THAT(output, ElementsAre(0, 0, 1, 2, 1, 2, 3, 4, 5));
270 }
271 
272 // Test MoveBefore.  Moving to the start of a list.
TEST(IListTest,MoveBefore2)273 TEST(IListTest, MoveBefore2) {
274   TestNode nodes[10];
275   TestList list1 = BuildList(nodes, 6);
276   TestList list2 = BuildList(nodes + 6, 3);
277 
278   TestList::iterator insertion_point = list1.begin();
279   insertion_point.MoveBefore(&list2);
280 
281   std::vector<int> output;
282   for (auto i = list1.begin(); i != list1.end(); ++i) {
283     output.push_back(i->data_);
284   }
285 
286   EXPECT_THAT(output, ElementsAre(0, 1, 2, 0, 1, 2, 3, 4, 5));
287 }
288 
289 // Test MoveBefore.  Moving to the end of a list.
TEST(IListTest,MoveBefore3)290 TEST(IListTest, MoveBefore3) {
291   TestNode nodes[10];
292   TestList list1 = BuildList(nodes, 6);
293   TestList list2 = BuildList(nodes + 6, 3);
294 
295   TestList::iterator insertion_point = list1.end();
296   insertion_point.MoveBefore(&list2);
297 
298   std::vector<int> output;
299   for (auto i = list1.begin(); i != list1.end(); ++i) {
300     output.push_back(i->data_);
301   }
302 
303   EXPECT_THAT(output, ElementsAre(0, 1, 2, 3, 4, 5, 0, 1, 2));
304 }
305 
306 // Test MoveBefore.  Moving an empty list.
TEST(IListTest,MoveBefore4)307 TEST(IListTest, MoveBefore4) {
308   TestNode nodes[10];
309   TestList list1 = BuildList(nodes, 6);
310   TestList list2;
311 
312   TestList::iterator insertion_point = list1.end();
313   insertion_point.MoveBefore(&list2);
314 
315   std::vector<int> output;
316   for (auto i = list1.begin(); i != list1.end(); ++i) {
317     output.push_back(i->data_);
318   }
319 
320   EXPECT_THAT(output, ElementsAre(0, 1, 2, 3, 4, 5));
321 }
322 
323 }  // namespace
324 }  // namespace utils
325 }  // namespace spvtools
326