1 /*
2  * Copyright (C) 2016 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include <algorithm>
18 #include <forward_list>
19 #include <vector>
20 
21 #include "gtest/gtest.h"
22 #include "intrusive_forward_list.h"
23 
24 namespace art {
25 
26 struct IFLTestValue : public IntrusiveForwardListNode<IFLTestValue> {
27   // Deliberately not explicit.
IFLTestValueart::IFLTestValue28   IFLTestValue(int v) : value(v) { }  // NOLINT(runtime/explicit)
29 
30   int value;
31 };
32 using IFLTestValueList = IntrusiveForwardList<IFLTestValue>;
33 using ConstIFLTestValueList = IntrusiveForwardList<const IFLTestValue>;
34 
operator ==(const IFLTestValue & lhs,const IFLTestValue & rhs)35 bool operator==(const IFLTestValue& lhs, const IFLTestValue& rhs) {
36   return lhs.value == rhs.value;
37 }
38 
operator <(const IFLTestValue & lhs,const IFLTestValue & rhs)39 bool operator<(const IFLTestValue& lhs, const IFLTestValue& rhs) {
40   return lhs.value < rhs.value;
41 }
42 
43 struct IFLTestValue2 {
44   // Deliberately not explicit.
IFLTestValue2art::IFLTestValue245   IFLTestValue2(int v) : hook(), value(v) { }  // NOLINT(runtime/explicit)
46 
47   IntrusiveForwardListHook hook;
48   int value;
49 };
50 using IFLTestValue2List =
51     IntrusiveForwardList<IFLTestValue2, IntrusiveForwardListMemberHookTraits<IFLTestValue2>>;
52 
operator ==(const IFLTestValue2 & lhs,const IFLTestValue2 & rhs)53 bool operator==(const IFLTestValue2& lhs, const IFLTestValue2& rhs) {
54   return lhs.value == rhs.value;
55 }
56 
operator <(const IFLTestValue2 & lhs,const IFLTestValue2 & rhs)57 bool operator<(const IFLTestValue2& lhs, const IFLTestValue2& rhs) {
58   return lhs.value < rhs.value;
59 }
60 
61 #define ASSERT_LISTS_EQUAL(expected, value)                                         \
62   do {                                                                              \
63     ASSERT_EQ((expected).empty(), (value).empty());                                 \
64     ASSERT_EQ(std::distance((expected).begin(), (expected).end()),                  \
65               std::distance((value).begin(), (value).end()));                       \
66     ASSERT_TRUE(std::equal((expected).begin(), (expected).end(), (value).begin())); \
67   } while (false)
68 
69 class IntrusiveForwardListTest : public testing::Test {
70  public:
71   template <typename ListType>
72   void IteratorToConstIterator();
73 
74   template <typename ListType>
75   void IteratorOperators();
76 
77   template <typename ListType>
78   void ConstructRange();
79 
80   template <typename ListType>
81   void Assign();
82 
83   template <typename ListType>
84   void PushPop();
85 
86   template <typename ListType>
87   void InsertAfter1();
88 
89   template <typename ListType>
90   void InsertAfter2();
91 
92   template <typename ListType>
93   void EraseAfter1();
94 
95   template <typename ListType>
96   void EraseAfter2();
97 
98   template <typename ListType>
99   void SwapClear();
100 
101   template <typename ListType>
102   void SpliceAfter();
103 
104   template <typename ListType>
105   void Remove();
106 
107   template <typename ListType>
108   void Unique();
109 
110   template <typename ListType>
111   void Merge();
112 
113   template <typename ListType>
114   void Sort1();
115 
116   template <typename ListType>
117   void Sort2();
118 
119   template <typename ListType>
120   void Reverse();
121 
122   template <typename ListType>
123   void ModifyValue();
124 };
125 
126 template <typename ListType>
IteratorToConstIterator()127 void IntrusiveForwardListTest::IteratorToConstIterator() {
128   ListType ifl;
129   typename ListType::iterator begin = ifl.begin();
130   typename ListType::const_iterator cbegin = ifl.cbegin();
131   typename ListType::const_iterator converted_begin = begin;
132   ASSERT_TRUE(converted_begin == cbegin);
133 }
134 
TEST_F(IntrusiveForwardListTest,IteratorToConstIterator)135 TEST_F(IntrusiveForwardListTest, IteratorToConstIterator) {
136   IteratorToConstIterator<IFLTestValueList>();
137   IteratorToConstIterator<ConstIFLTestValueList>();
138   IteratorToConstIterator<IFLTestValue2List>();
139 }
140 
141 template <typename ListType>
IteratorOperators()142 void IntrusiveForwardListTest::IteratorOperators() {
143   using ValueType = typename ListType::value_type;
144   ListType ifl;
145   ASSERT_TRUE(ifl.begin() == ifl.cbegin());
146   ASSERT_FALSE(ifl.begin() != ifl.cbegin());
147   ASSERT_TRUE(ifl.end() == ifl.cend());
148   ASSERT_FALSE(ifl.end() != ifl.cend());
149 
150   ASSERT_TRUE(ifl.begin() == ifl.end());  // Empty.
151   ASSERT_FALSE(ifl.begin() != ifl.end());  // Empty.
152 
153   ValueType value(1);
154   ifl.insert_after(ifl.cbefore_begin(), value);
155 
156   ASSERT_FALSE(ifl.begin() == ifl.end());  // Not empty.
157   ASSERT_TRUE(ifl.begin() != ifl.end());  // Not empty.
158 }
159 
TEST_F(IntrusiveForwardListTest,IteratorOperators)160 TEST_F(IntrusiveForwardListTest, IteratorOperators) {
161   IteratorOperators<IFLTestValueList>();
162   IteratorOperators<ConstIFLTestValueList>();
163   IteratorOperators<IFLTestValue2List>();
164 }
165 
166 template <typename ListType>
ConstructRange()167 void IntrusiveForwardListTest::ConstructRange() {
168   using ValueType = typename ListType::value_type;
169   std::forward_list<int> ref({ 1, 2, 7 });
170   std::vector<ValueType> storage(ref.begin(), ref.end());
171   ListType ifl(storage.begin(), storage.end());
172   ASSERT_LISTS_EQUAL(ref, ifl);
173 }
174 
TEST_F(IntrusiveForwardListTest,ConstructRange)175 TEST_F(IntrusiveForwardListTest, ConstructRange) {
176   ConstructRange<IFLTestValueList>();
177   ConstructRange<ConstIFLTestValueList>();
178   ConstructRange<IFLTestValue2List>();
179 }
180 
181 template <typename ListType>
Assign()182 void IntrusiveForwardListTest::Assign() {
183   using ValueType = typename ListType::value_type;
184   std::forward_list<int> ref1({ 2, 8, 5 });
185   std::vector<ValueType> storage1(ref1.begin(), ref1.end());
186   ListType ifl;
187   ifl.assign(storage1.begin(), storage1.end());
188   ASSERT_LISTS_EQUAL(ref1, ifl);
189   std::forward_list<int> ref2({ 7, 1, 3 });
190   std::vector<ValueType> storage2(ref2.begin(), ref2.end());
191   ifl.assign(storage2.begin(), storage2.end());
192   ASSERT_LISTS_EQUAL(ref2, ifl);
193 }
194 
TEST_F(IntrusiveForwardListTest,Assign)195 TEST_F(IntrusiveForwardListTest, Assign) {
196   Assign<IFLTestValueList>();
197   Assign<ConstIFLTestValueList>();
198   Assign<IFLTestValue2List>();
199 }
200 
201 template <typename ListType>
PushPop()202 void IntrusiveForwardListTest::PushPop() {
203   using ValueType = typename ListType::value_type;
204   ValueType value3(3);
205   ValueType value7(7);
206   std::forward_list<int> ref;
207   ListType ifl;
208   ASSERT_LISTS_EQUAL(ref, ifl);
209   ref.push_front(3);
210   ifl.push_front(value3);
211   ASSERT_LISTS_EQUAL(ref, ifl);
212   ASSERT_EQ(3, ifl.front());
213   ref.push_front(7);
214   ifl.push_front(value7);
215   ASSERT_LISTS_EQUAL(ref, ifl);
216   ASSERT_EQ(7, ifl.front());
217   ref.pop_front();
218   ifl.pop_front();
219   ASSERT_LISTS_EQUAL(ref, ifl);
220   ASSERT_EQ(3, ifl.front());
221   ref.pop_front();
222   ifl.pop_front();
223   ASSERT_LISTS_EQUAL(ref, ifl);
224 }
225 
TEST_F(IntrusiveForwardListTest,PushPop)226 TEST_F(IntrusiveForwardListTest, PushPop) {
227   PushPop<IFLTestValueList>();
228   PushPop<ConstIFLTestValueList>();
229   PushPop<IFLTestValue2List>();
230 }
231 
232 template <typename ListType>
InsertAfter1()233 void IntrusiveForwardListTest::InsertAfter1() {
234   using ValueType = typename ListType::value_type;
235   ValueType value4(4);
236   ValueType value8(8);
237   ValueType value5(5);
238   ValueType value3(3);
239   std::forward_list<int> ref;
240   ListType ifl;
241 
242   auto ref_it = ref.insert_after(ref.before_begin(), 4);
243   auto ifl_it = ifl.insert_after(ifl.before_begin(), value4);
244   ASSERT_LISTS_EQUAL(ref, ifl);
245   ASSERT_EQ(*ref_it, *ifl_it);
246   CHECK(ref_it == ref.begin());
247   ASSERT_TRUE(ifl_it == ifl.begin());
248 
249   ref_it = ref.insert_after(ref.begin(), 8);
250   ifl_it = ifl.insert_after(ifl.begin(), value8);
251   ASSERT_LISTS_EQUAL(ref, ifl);
252   ASSERT_EQ(*ref_it, *ifl_it);
253   CHECK(ref_it != ref.end());
254   ASSERT_TRUE(ifl_it != ifl.end());
255   CHECK(++ref_it == ref.end());
256   ASSERT_TRUE(++ifl_it == ifl.end());
257 
258   ref_it = ref.insert_after(ref.begin(), 5);
259   ifl_it = ifl.insert_after(ifl.begin(), value5);
260   ASSERT_LISTS_EQUAL(ref, ifl);
261   ASSERT_EQ(*ref_it, *ifl_it);
262 
263   ref_it = ref.insert_after(ref_it, 3);
264   ifl_it = ifl.insert_after(ifl_it, value3);
265   ASSERT_LISTS_EQUAL(ref, ifl);
266   ASSERT_EQ(*ref_it, *ifl_it);
267 }
268 
TEST_F(IntrusiveForwardListTest,InsertAfter1)269 TEST_F(IntrusiveForwardListTest, InsertAfter1) {
270   InsertAfter1<IFLTestValueList>();
271   InsertAfter1<ConstIFLTestValueList>();
272   InsertAfter1<IFLTestValue2List>();
273 }
274 
275 template <typename ListType>
InsertAfter2()276 void IntrusiveForwardListTest::InsertAfter2() {
277   using ValueType = typename ListType::value_type;
278   std::forward_list<int> ref;
279   ListType ifl;
280 
281   auto ref_it = ref.insert_after(ref.before_begin(), { 2, 8, 5 });
282   std::vector<ValueType> storage1({ { 2 }, { 8 }, { 5 } });
283   auto ifl_it = ifl.insert_after(ifl.before_begin(), storage1.begin(), storage1.end());
284   ASSERT_LISTS_EQUAL(ref, ifl);
285   ASSERT_EQ(*ref_it, *ifl_it);
286 
287   std::vector<ValueType> storage2({ { 7 }, { 2 } });
288   ref_it = ref.insert_after(ref.begin(), { 7, 2 });
289   ifl_it = ifl.insert_after(ifl.begin(), storage2.begin(), storage2.end());
290   ASSERT_LISTS_EQUAL(ref, ifl);
291   ASSERT_EQ(*ref_it, *ifl_it);
292 
293   std::vector<ValueType> storage3({ { 1 }, { 3 }, { 4 }, { 9 } });
294   ref_it = ref.begin();
295   ifl_it = ifl.begin();
296   std::advance(ref_it, std::distance(ref.begin(), ref.end()) - 1);
297   std::advance(ifl_it, std::distance(ifl.begin(), ifl.end()) - 1);
298   ref_it = ref.insert_after(ref_it, { 1, 3, 4, 9 });
299   ifl_it = ifl.insert_after(ifl_it, storage3.begin(), storage3.end());
300   ASSERT_LISTS_EQUAL(ref, ifl);
301 }
302 
TEST_F(IntrusiveForwardListTest,InsertAfter2)303 TEST_F(IntrusiveForwardListTest, InsertAfter2) {
304   InsertAfter2<IFLTestValueList>();
305   InsertAfter2<ConstIFLTestValueList>();
306   InsertAfter2<IFLTestValue2List>();
307 }
308 
309 template <typename ListType>
EraseAfter1()310 void IntrusiveForwardListTest::EraseAfter1() {
311   using ValueType = typename ListType::value_type;
312   std::forward_list<int> ref({ 1, 2, 7, 4, 5 });
313   std::vector<ValueType> storage(ref.begin(), ref.end());
314   ListType ifl(storage.begin(), storage.end());
315   ASSERT_LISTS_EQUAL(ref, ifl);
316   CHECK_EQ(std::distance(ref.begin(), ref.end()), 5);
317 
318   auto ref_it = ref.begin();
319   auto ifl_it = ifl.begin();
320   std::advance(ref_it, 2);
321   std::advance(ifl_it, 2);
322   ref_it = ref.erase_after(ref_it);
323   ifl_it = ifl.erase_after(ifl_it);
324   ASSERT_LISTS_EQUAL(ref, ifl);
325   CHECK_EQ(std::distance(ref.begin(), ref.end()), 4);
326   CHECK(ref_it != ref.end());
327   ASSERT_TRUE(ifl_it != ifl.end());
328   CHECK(++ref_it == ref.end());
329   ASSERT_TRUE(++ifl_it == ifl.end());
330 
331   ref_it = ref.begin();
332   ifl_it = ifl.begin();
333   std::advance(ref_it, 2);
334   std::advance(ifl_it, 2);
335   ref_it = ref.erase_after(ref_it);
336   ifl_it = ifl.erase_after(ifl_it);
337   ASSERT_LISTS_EQUAL(ref, ifl);
338   CHECK_EQ(std::distance(ref.begin(), ref.end()), 3);
339   CHECK(ref_it == ref.end());
340   ASSERT_TRUE(ifl_it == ifl.end());
341 
342   ref_it = ref.erase_after(ref.begin());
343   ifl_it = ifl.erase_after(ifl.begin());
344   ASSERT_LISTS_EQUAL(ref, ifl);
345   CHECK_EQ(std::distance(ref.begin(), ref.end()), 2);
346   CHECK(ref_it != ref.end());
347   ASSERT_TRUE(ifl_it != ifl.end());
348   CHECK(++ref_it == ref.end());
349   ASSERT_TRUE(++ifl_it == ifl.end());
350 
351   ref_it = ref.erase_after(ref.before_begin());
352   ifl_it = ifl.erase_after(ifl.before_begin());
353   ASSERT_LISTS_EQUAL(ref, ifl);
354   CHECK_EQ(std::distance(ref.begin(), ref.end()), 1);
355   CHECK(ref_it == ref.begin());
356   ASSERT_TRUE(ifl_it == ifl.begin());
357 
358   ref_it = ref.erase_after(ref.before_begin());
359   ifl_it = ifl.erase_after(ifl.before_begin());
360   ASSERT_LISTS_EQUAL(ref, ifl);
361   CHECK_EQ(std::distance(ref.begin(), ref.end()), 0);
362   CHECK(ref_it == ref.begin());
363   ASSERT_TRUE(ifl_it == ifl.begin());
364 }
365 
TEST_F(IntrusiveForwardListTest,EraseAfter1)366 TEST_F(IntrusiveForwardListTest, EraseAfter1) {
367   EraseAfter1<IFLTestValueList>();
368   EraseAfter1<ConstIFLTestValueList>();
369   EraseAfter1<IFLTestValue2List>();
370 }
371 
372 template <typename ListType>
EraseAfter2()373 void IntrusiveForwardListTest::EraseAfter2() {
374   using ValueType = typename ListType::value_type;
375   std::forward_list<int> ref({ 1, 2, 7, 4, 5, 3, 2, 8, 9 });
376   std::vector<ValueType> storage(ref.begin(), ref.end());
377   ListType ifl(storage.begin(), storage.end());
378   ASSERT_LISTS_EQUAL(ref, ifl);
379   CHECK_EQ(std::distance(ref.begin(), ref.end()), 9);
380 
381   auto ref_it = ref.begin();
382   auto ifl_it = ifl.begin();
383   std::advance(ref_it, 3);
384   std::advance(ifl_it, 3);
385   ref_it = ref.erase_after(ref.begin(), ref_it);
386   ifl_it = ifl.erase_after(ifl.begin(), ifl_it);
387   ASSERT_LISTS_EQUAL(ref, ifl);
388   ASSERT_EQ(std::distance(ref.begin(), ref_it), std::distance(ifl.begin(), ifl_it));
389   CHECK_EQ(std::distance(ref.begin(), ref.end()), 7);
390 
391   ref_it = ref.erase_after(ref_it, ref.end());
392   ifl_it = ifl.erase_after(ifl_it, ifl.end());
393   ASSERT_LISTS_EQUAL(ref, ifl);
394   CHECK(ref_it == ref.end());
395   ASSERT_TRUE(ifl_it == ifl.end());
396   CHECK_EQ(std::distance(ref.begin(), ref.end()), 2);
397 
398   ref_it = ref.erase_after(ref.before_begin(), ref.end());
399   ifl_it = ifl.erase_after(ifl.before_begin(), ifl.end());
400   ASSERT_LISTS_EQUAL(ref, ifl);
401   CHECK(ref_it == ref.end());
402   ASSERT_TRUE(ifl_it == ifl.end());
403   CHECK_EQ(std::distance(ref.begin(), ref.end()), 0);
404 }
405 
TEST_F(IntrusiveForwardListTest,EraseAfter2)406 TEST_F(IntrusiveForwardListTest, EraseAfter2) {
407   EraseAfter2<IFLTestValueList>();
408   EraseAfter2<ConstIFLTestValueList>();
409   EraseAfter2<IFLTestValue2List>();
410 }
411 
412 template <typename ListType>
SwapClear()413 void IntrusiveForwardListTest::SwapClear() {
414   using ValueType = typename ListType::value_type;
415   std::forward_list<int> ref1({ 1, 2, 7 });
416   std::vector<ValueType> storage1(ref1.begin(), ref1.end());
417   ListType ifl1(storage1.begin(), storage1.end());
418   std::forward_list<int> ref2({ 3, 8, 6 });
419   std::vector<ValueType> storage2(ref2.begin(), ref2.end());
420   ListType ifl2(storage2.begin(), storage2.end());
421   ASSERT_LISTS_EQUAL(ref1, ifl1);
422   ASSERT_LISTS_EQUAL(ref2, ifl2);
423   ref1.swap(ref2);
424   ifl1.swap(ifl2);
425   ASSERT_LISTS_EQUAL(ref1, ifl1);
426   ASSERT_LISTS_EQUAL(ref2, ifl2);
427   ref1.clear();
428   ifl1.clear();
429   ASSERT_LISTS_EQUAL(ref1, ifl1);
430   ASSERT_LISTS_EQUAL(ref2, ifl2);
431   swap(ref1, ref2);
432   swap(ifl1, ifl2);
433   ASSERT_LISTS_EQUAL(ref1, ifl1);
434   ASSERT_LISTS_EQUAL(ref2, ifl2);
435   ref1.clear();
436   ifl1.clear();
437   ASSERT_LISTS_EQUAL(ref1, ifl1);
438   ASSERT_LISTS_EQUAL(ref2, ifl2);
439 }
440 
TEST_F(IntrusiveForwardListTest,SwapClear)441 TEST_F(IntrusiveForwardListTest, SwapClear) {
442   SwapClear<IFLTestValueList>();
443   SwapClear<ConstIFLTestValueList>();
444   SwapClear<IFLTestValue2List>();
445 }
446 
447 template <typename ListType>
SpliceAfter()448 void IntrusiveForwardListTest::SpliceAfter() {
449   using ValueType = typename ListType::value_type;
450   std::forward_list<int> ref1({ 3, 1, 2, 7, 4, 5, 4, 8, 7 });
451   std::forward_list<int> ref2;
452   std::vector<ValueType> storage(ref1.begin(), ref1.end());
453   ListType ifl1(storage.begin(), storage.end());
454   ListType ifl2;
455   ASSERT_LISTS_EQUAL(ref1, ifl1);
456   ASSERT_LISTS_EQUAL(ref2, ifl2);
457 
458   // Move everything to ref2/ifl2.
459   ref2.splice_after(ref2.before_begin(), ref1);
460   ifl2.splice_after(ifl2.before_begin(), ifl1);
461   ASSERT_LISTS_EQUAL(ref1, ifl1);
462   ASSERT_LISTS_EQUAL(ref2, ifl2);
463 
464   // Move first element (3) to ref1/ifl1.
465   ref1.splice_after(ref1.before_begin(), ref2, ref2.before_begin());
466   ifl1.splice_after(ifl1.before_begin(), ifl2, ifl2.before_begin());
467   ASSERT_LISTS_EQUAL(ref1, ifl1);
468   ASSERT_LISTS_EQUAL(ref2, ifl2);
469 
470   // Move second element (2) to ref1/ifl1 after the first element (3).
471   ref1.splice_after(ref1.begin(), ref2, ref2.begin());
472   ifl1.splice_after(ifl1.begin(), ifl2, ifl2.begin());
473   ASSERT_LISTS_EQUAL(ref1, ifl1);
474   ASSERT_LISTS_EQUAL(ref2, ifl2);
475 
476   // Move everything from ref2/ifl2 between the 2 elements now in ref1/ifl1.
477   ref1.splice_after(ref1.begin(), ref2);
478   ifl1.splice_after(ifl1.begin(), ifl2);
479   ASSERT_LISTS_EQUAL(ref1, ifl1);
480   ASSERT_LISTS_EQUAL(ref2, ifl2);
481 
482   std::forward_list<int> check({ 3, 1, 7, 4, 5, 4, 8, 7, 2 });
483   ASSERT_LISTS_EQUAL(check, ifl1);
484   ASSERT_TRUE(ifl2.empty());
485 
486   // Empty splice_after().
487   ref2.splice_after(
488       ref2.before_begin(), ref1, ref1.before_begin(), ref1.begin());
489   ifl2.splice_after(ifl2.before_begin(), ifl1, ifl1.before_begin(), ifl1.begin());
490   ASSERT_LISTS_EQUAL(ref1, ifl1);
491   ASSERT_LISTS_EQUAL(ref2, ifl2);
492 
493   // Move { 1, 7 } to ref2/ifl2.
494   auto ref_it = ref1.begin();
495   auto ifl_it = ifl1.begin();
496   std::advance(ref_it, 3);
497   std::advance(ifl_it, 3);
498   ref2.splice_after(ref2.before_begin(), ref1, ref1.begin(), ref_it);
499   ifl2.splice_after(ifl2.before_begin(), ifl1, ifl1.begin(), ifl_it);
500   ASSERT_LISTS_EQUAL(ref1, ifl1);
501   ASSERT_LISTS_EQUAL(ref2, ifl2);
502 
503   // Move { 8, 7, 2 } to the beginning of ref1/ifl1.
504   ref_it = ref1.begin();
505   ifl_it = ifl1.begin();
506   std::advance(ref_it, 3);
507   std::advance(ifl_it, 3);
508   ref1.splice_after(ref1.before_begin(), ref1, ref_it, ref1.end());
509   ifl1.splice_after(ifl1.before_begin(), ifl1, ifl_it, ifl1.end());
510   ASSERT_LISTS_EQUAL(ref1, ifl1);
511 
512   check.assign({ 8, 7, 2, 3, 4, 5, 4 });
513   ASSERT_LISTS_EQUAL(check, ifl1);
514   check.assign({ 1, 7 });
515   ASSERT_LISTS_EQUAL(check, ifl2);
516 
517   // Move all but the first element to ref2/ifl2.
518   ref_it = ref2.begin();
519   ifl_it = ifl2.begin();
520   std::advance(ref_it, 1);
521   std::advance(ifl_it, 1);
522   ref2.splice_after(ref_it, ref1, ref1.begin(), ref1.end());
523   ifl2.splice_after(ifl_it, ifl1, ifl1.begin(), ifl1.end());
524   ASSERT_LISTS_EQUAL(ref1, ifl1);
525   ASSERT_LISTS_EQUAL(ref2, ifl2);
526 
527   check.assign({8});
528   ASSERT_LISTS_EQUAL(check, ifl1);
529 
530   // Move the first element of ref1/ifl1 to the beginning of ref1/ifl1 (do nothing).
531   ref1.splice_after(ref1.before_begin(), ref1, ref1.before_begin());
532   ifl1.splice_after(ifl1.before_begin(), ifl1, ifl1.before_begin());
533   ASSERT_LISTS_EQUAL(ref1, ifl1);
534   ASSERT_LISTS_EQUAL(check, ifl1);
535 
536   // Move the first element of ref2/ifl2 after itself (do nothing).
537   ref1.splice_after(ref1.begin(), ref1, ref1.before_begin());
538   ifl1.splice_after(ifl1.begin(), ifl1, ifl1.before_begin());
539   ASSERT_LISTS_EQUAL(ref1, ifl1);
540   ASSERT_LISTS_EQUAL(check, ifl1);
541 
542   check.assign({ 1, 7, 7, 2, 3, 4, 5, 4 });
543   ASSERT_LISTS_EQUAL(check, ifl2);
544 
545   // Move the first element of ref2/ifl2 to the beginning of ref2/ifl2 (do nothing).
546   ref2.splice_after(ref2.before_begin(), ref2, ref2.before_begin());
547   ifl2.splice_after(ifl2.before_begin(), ifl2, ifl2.before_begin());
548   ASSERT_LISTS_EQUAL(ref2, ifl2);
549   ASSERT_LISTS_EQUAL(check, ifl2);
550 
551   // Move the first element of ref2/ifl2 after itself (do nothing).
552   ref2.splice_after(ref2.begin(), ref2, ref2.before_begin());
553   ifl2.splice_after(ifl2.begin(), ifl2, ifl2.before_begin());
554   ASSERT_LISTS_EQUAL(ref2, ifl2);
555   ASSERT_LISTS_EQUAL(check, ifl2);
556 }
557 
TEST_F(IntrusiveForwardListTest,SpliceAfter)558 TEST_F(IntrusiveForwardListTest, SpliceAfter) {
559   SpliceAfter<IFLTestValueList>();
560   SpliceAfter<ConstIFLTestValueList>();
561   SpliceAfter<IFLTestValue2List>();
562 }
563 
564 template <typename ListType>
Remove()565 void IntrusiveForwardListTest::Remove() {
566   using ValueType = typename ListType::value_type;
567   std::forward_list<int> ref({ 3, 1, 2, 7, 4, 5, 4, 8, 7 });
568   std::vector<ValueType> storage(ref.begin(), ref.end());
569   ListType ifl(storage.begin(), storage.end());
570   ASSERT_LISTS_EQUAL(ref, ifl);
571   ref.remove(1);
572   ifl.remove(1);
573   ASSERT_LISTS_EQUAL(ref, ifl);
574   ref.remove(4);
575   ifl.remove(4);
576   ASSERT_LISTS_EQUAL(ref, ifl);
577   auto odd = [](ValueType value) { return (value.value & 1) != 0; };
578   ref.remove_if(odd);
579   ifl.remove_if(odd);
580   ASSERT_LISTS_EQUAL(ref, ifl);
581   auto all = [](ValueType value ATTRIBUTE_UNUSED) { return true; };
582   ref.remove_if(all);
583   ifl.remove_if(all);
584   ASSERT_LISTS_EQUAL(ref, ifl);
585 }
586 
TEST_F(IntrusiveForwardListTest,Remove)587 TEST_F(IntrusiveForwardListTest, Remove) {
588   Remove<IFLTestValueList>();
589   Remove<ConstIFLTestValueList>();
590   Remove<IFLTestValue2List>();
591 }
592 
593 template <typename ListType>
Unique()594 void IntrusiveForwardListTest::Unique() {
595   using ValueType = typename ListType::value_type;
596   std::forward_list<int> ref({ 3, 1, 1, 2, 3, 3, 7, 7, 4, 4, 5, 7 });
597   std::vector<ValueType> storage(ref.begin(), ref.end());
598   ListType ifl(storage.begin(), storage.end());
599   ASSERT_LISTS_EQUAL(ref, ifl);
600   ref.unique();
601   ifl.unique();
602   ASSERT_LISTS_EQUAL(ref, ifl);
603   std::forward_list<int> check({ 3, 1, 2, 3, 7, 4, 5, 7 });
604   ASSERT_LISTS_EQUAL(check, ifl);
605 
606   auto bin_pred = [](const ValueType& lhs, const ValueType& rhs) {
607     return (lhs.value & ~1) == (rhs.value & ~1);
608   };
609   ref.unique(bin_pred);
610   ifl.unique(bin_pred);
611   ASSERT_LISTS_EQUAL(ref, ifl);
612   check.assign({ 3, 1, 2, 7, 4, 7 });
613   ASSERT_LISTS_EQUAL(check, ifl);
614 }
615 
TEST_F(IntrusiveForwardListTest,Unique)616 TEST_F(IntrusiveForwardListTest, Unique) {
617   Unique<IFLTestValueList>();
618   Unique<ConstIFLTestValueList>();
619   Unique<IFLTestValue2List>();
620 }
621 
622 template <typename ListType>
Merge()623 void IntrusiveForwardListTest::Merge() {
624   using ValueType = typename ListType::value_type;
625   std::forward_list<int> ref1({ 1, 4, 8, 8, 12 });
626   std::vector<ValueType> storage1(ref1.begin(), ref1.end());
627   ListType ifl1(storage1.begin(), storage1.end());
628   std::forward_list<int> ref2({ 3, 5, 6, 7, 9 });
629   std::vector<ValueType> storage2(ref2.begin(), ref2.end());
630   ListType ifl2(storage2.begin(), storage2.end());
631   ASSERT_LISTS_EQUAL(ref1, ifl1);
632   ASSERT_LISTS_EQUAL(ref2, ifl2);
633   CHECK(std::is_sorted(ref1.begin(), ref1.end()));
634   CHECK(std::is_sorted(ref2.begin(), ref2.end()));
635   ref1.merge(ref2);
636   ifl1.merge(ifl2);
637   ASSERT_LISTS_EQUAL(ref1, ifl1);
638   ASSERT_LISTS_EQUAL(ref2, ifl2);
639   CHECK(ref2.empty());
640   std::forward_list<int> check({ 1, 3, 4, 5, 6, 7, 8, 8, 9, 12 });
641   ASSERT_LISTS_EQUAL(check, ifl1);
642 }
643 
TEST_F(IntrusiveForwardListTest,Merge)644 TEST_F(IntrusiveForwardListTest, Merge) {
645   Merge<IFLTestValueList>();
646   Merge<ConstIFLTestValueList>();
647   Merge<IFLTestValue2List>();
648 }
649 
650 template <typename ListType>
Sort1()651 void IntrusiveForwardListTest::Sort1() {
652   using ValueType = typename ListType::value_type;
653   std::forward_list<int> ref({ 2, 9, 8, 3, 7, 4, 1, 5, 3, 0 });
654   std::vector<ValueType> storage(ref.begin(), ref.end());
655   ListType ifl(storage.begin(), storage.end());
656   ASSERT_LISTS_EQUAL(ref, ifl);
657   CHECK(!std::is_sorted(ref.begin(), ref.end()));
658   ref.sort();
659   ifl.sort();
660   ASSERT_LISTS_EQUAL(ref, ifl);
661   std::forward_list<int> check({ 0, 1, 2, 3, 3, 4, 5, 7, 8, 9 });
662   ASSERT_LISTS_EQUAL(check, ifl);
663 }
664 
TEST_F(IntrusiveForwardListTest,Sort1)665 TEST_F(IntrusiveForwardListTest, Sort1) {
666   Sort1<IFLTestValueList>();
667   Sort1<ConstIFLTestValueList>();
668   Sort1<IFLTestValue2List>();
669 }
670 
671 template <typename ListType>
Sort2()672 void IntrusiveForwardListTest::Sort2() {
673   using ValueType = typename ListType::value_type;
674   std::forward_list<int> ref({ 2, 9, 8, 3, 7, 4, 1, 5, 3, 0 });
675   std::vector<ValueType> storage(ref.begin(), ref.end());
676   ListType ifl(storage.begin(), storage.end());
677   ASSERT_LISTS_EQUAL(ref, ifl);
678   auto cmp = [](const ValueType& lhs, const ValueType& rhs) {
679     return (lhs.value & ~1) < (rhs.value & ~1);
680   };
681   CHECK(!std::is_sorted(ref.begin(), ref.end(), cmp));
682   ref.sort(cmp);
683   ifl.sort(cmp);
684   ASSERT_LISTS_EQUAL(ref, ifl);
685   std::forward_list<int> check({ 1, 0, 2, 3, 3, 4, 5, 7, 9, 8 });
686   ASSERT_LISTS_EQUAL(check, ifl);
687 }
688 
TEST_F(IntrusiveForwardListTest,Sort2)689 TEST_F(IntrusiveForwardListTest, Sort2) {
690   Sort2<IFLTestValueList>();
691   Sort2<ConstIFLTestValueList>();
692   Sort2<IFLTestValue2List>();
693 }
694 
695 template <typename ListType>
Reverse()696 void IntrusiveForwardListTest::Reverse() {
697   using ValueType = typename ListType::value_type;
698   std::forward_list<int> ref({ 8, 3, 5, 4, 1, 3 });
699   std::vector<ValueType> storage(ref.begin(), ref.end());
700   ListType ifl(storage.begin(), storage.end());
701   ASSERT_LISTS_EQUAL(ref, ifl);
702   CHECK(!std::is_sorted(ref.begin(), ref.end()));
703   ref.reverse();
704   ifl.reverse();
705   ASSERT_LISTS_EQUAL(ref, ifl);
706   std::forward_list<int> check({ 3, 1, 4, 5, 3, 8 });
707   ASSERT_LISTS_EQUAL(check, ifl);
708 }
709 
TEST_F(IntrusiveForwardListTest,Reverse)710 TEST_F(IntrusiveForwardListTest, Reverse) {
711   Reverse<IFLTestValueList>();
712   Reverse<ConstIFLTestValueList>();
713   Reverse<IFLTestValue2List>();
714 }
715 
716 template <typename ListType>
ModifyValue()717 void IntrusiveForwardListTest::ModifyValue() {
718   using ValueType = typename ListType::value_type;
719   std::forward_list<int> ref({ 3, 7, 42 });
720   std::vector<ValueType> storage(ref.begin(), ref.end());
721   ListType ifl(storage.begin(), storage.end());
722   ASSERT_LISTS_EQUAL(ref, ifl);
723 
724   auto add1 = [](const ValueType& value) { return value.value + 1; };
725   std::transform(ref.begin(), ref.end(), ref.begin(), add1);
726   std::transform(ifl.begin(), ifl.end(), ifl.begin(), add1);
727   ASSERT_LISTS_EQUAL(ref, ifl);
728 }
729 
TEST_F(IntrusiveForwardListTest,ModifyValue)730 TEST_F(IntrusiveForwardListTest, ModifyValue) {
731   ModifyValue<IFLTestValueList>();
732   // Does not compile with ConstIFLTestValueList because LHS of the assignment is const.
733   // ModifyValue<ConstIFLTestValueList>();
734   static_assert(std::is_const<ConstIFLTestValueList::iterator::value_type>::value, "Const check.");
735   ModifyValue<IFLTestValue2List>();
736 }
737 
738 struct Tag1;
739 struct Tag2;
740 struct TwoListsValue : public IntrusiveForwardListNode<TwoListsValue, Tag1>,
741                        public IntrusiveForwardListNode<TwoListsValue, Tag2> {
742   // Deliberately not explicit.
TwoListsValueart::TwoListsValue743   TwoListsValue(int v) : value(v) { }  // NOLINT(runtime/explicit)
744 
745   int value;
746 };
747 using FirstList =
748     IntrusiveForwardList<TwoListsValue, IntrusiveForwardListBaseHookTraits<TwoListsValue, Tag1>>;
749 using SecondList =
750     IntrusiveForwardList<TwoListsValue, IntrusiveForwardListBaseHookTraits<TwoListsValue, Tag2>>;
751 
operator ==(const TwoListsValue & lhs,const TwoListsValue & rhs)752 bool operator==(const TwoListsValue& lhs, const TwoListsValue& rhs) {
753   return lhs.value == rhs.value;
754 }
755 
TEST_F(IntrusiveForwardListTest,TwoLists)756 TEST_F(IntrusiveForwardListTest, TwoLists) {
757   // Test that a value can be in two lists at the same time and the hooks do not interfere.
758   std::vector<TwoListsValue> storage({ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 });  // storage[i] = i
759 
760   std::vector<int> order1({ 3, 1, 7, 2, 8, 9, 4, 0, 6, 5 });
761   FirstList list1;
762   auto pos1 = list1.before_begin();
763   for (size_t idx : order1) {
764     pos1 = list1.insert_after(pos1, storage[idx]);
765   }
766 
767   std::vector<int> order2({ 8, 5, 1, 6, 7, 2, 9, 3, 0, 4 });
768   SecondList list2;
769   auto pos2 = list2.before_begin();
770   for (size_t idx : order2) {
771     pos2 = list2.insert_after(pos2, storage[idx]);
772   }
773 
774   // Using `storage[i] = i`, we can easily compare that nodes of each list are in the right order.
775   ASSERT_LISTS_EQUAL(order1, list1);
776   ASSERT_LISTS_EQUAL(order2, list2);
777 }
778 
779 }  // namespace art
780