xref: /aosp_15_r20/external/pigweed/pw_containers/intrusive_list_test.cc (revision 61c4878ac05f98d0ceed94b57d316916de578985)
1 // Copyright 2020 The Pigweed Authors
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License"); you may not
4 // use this file except in compliance with the License. You may obtain a copy of
5 // the License at
6 //
7 //     https://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, WITHOUT
11 // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12 // License for the specific language governing permissions and limitations under
13 // the License.
14 
15 #include "pw_containers/intrusive_list.h"
16 
17 #include <array>
18 #include <cstddef>
19 #include <cstdint>
20 
21 #include "pw_compilation_testing/negative_compilation.h"
22 #include "pw_containers/vector.h"
23 #include "pw_preprocessor/util.h"
24 #include "pw_unit_test/framework.h"
25 
26 namespace {
27 
28 // Test fixtures
29 
30 using ::pw::containers::future::IntrusiveList;
31 
32 class Item : public IntrusiveList<Item>::Item {
33  public:
34   constexpr Item() = default;
Item(int number)35   constexpr Item(int number) : number_(number) {}
36 
Item(Item && other)37   Item(Item&& other) { *this = std::move(other); }
operator =(Item && other)38   Item& operator=(Item&& other) {
39     number_ = other.number_;
40     return *this;
41   }
42 
GetNumber() const43   int GetNumber() const { return number_; }
SetNumber(int num)44   void SetNumber(int num) { number_ = num; }
45 
46   // This operator ensures comparisons are done by identity rather than equality
47   // for `remove`, and allows using the zero-parameter overload of `unique`.
operator ==(const Item & other) const48   bool operator==(const Item& other) const { return number_ == other.number_; }
49 
50   // This operator allows using the zero-parameter overloads of `merge` and
51   // `sort`.
operator <(const Item & other) const52   bool operator<(const Item& other) const { return number_ < other.number_; }
53 
54  private:
55   int number_ = 0;
56 };
57 
58 using List = IntrusiveList<Item>;
59 
60 // Test that a list of items derived from a different Item class can be created.
61 class DerivedItem : public Item {};
62 
63 // TODO: b/235289499 - Tests guarded by this definition should trigger CHECK
64 // failures. These require using a testing version of pw_assert.
65 #ifndef TESTING_CHECK_FAILURES_IS_SUPPORTED
66 #define TESTING_CHECK_FAILURES_IS_SUPPORTED 0
67 #endif  // TESTING_CHECK_FAILURES_IS_SUPPORTED
68 
69 // Unit tests.
70 
TEST(IntrusiveListTest,Construct_InitializerList_Empty)71 TEST(IntrusiveListTest, Construct_InitializerList_Empty) {
72   List list({});
73   EXPECT_TRUE(list.empty());
74 }
75 
TEST(IntrusiveListTest,Construct_InitializerList_One)76 TEST(IntrusiveListTest, Construct_InitializerList_One) {
77   Item one(1);
78   List list({&one});
79 
80   EXPECT_EQ(&one, &list.front());
81   list.clear();
82 }
83 
TEST(IntrusiveListTest,Construct_InitializerList_Multiple)84 TEST(IntrusiveListTest, Construct_InitializerList_Multiple) {
85   Item one(1);
86   Item two(2);
87   Item thr(3);
88 
89   List list({&one, &two, &thr});
90   auto it = list.begin();
91   EXPECT_EQ(&one, &(*it++));
92   EXPECT_EQ(&two, &(*it++));
93   EXPECT_EQ(&thr, &(*it++));
94   EXPECT_EQ(list.end(), it);
95   list.clear();
96 }
97 
TEST(IntrusiveListTest,Construct_ObjectIterator_Empty)98 TEST(IntrusiveListTest, Construct_ObjectIterator_Empty) {
99   std::array<Item, 0> array;
100   List list(array.begin(), array.end());
101 
102   EXPECT_TRUE(list.empty());
103 }
104 
TEST(IntrusiveListTest,Construct_ObjectIterator_One)105 TEST(IntrusiveListTest, Construct_ObjectIterator_One) {
106   std::array<Item, 1> array{{{1}}};
107   List list(array.begin(), array.end());
108 
109   EXPECT_EQ(&array.front(), &list.front());
110   list.clear();
111 }
112 
TEST(IntrusiveListTest,Construct_ObjectIterator_Multiple)113 TEST(IntrusiveListTest, Construct_ObjectIterator_Multiple) {
114   std::array<Item, 3> array{{{1}, {2}, {3}}};
115 
116   List list(array.begin(), array.end());
117   auto it = list.begin();
118   EXPECT_EQ(&array[0], &(*it++));
119   EXPECT_EQ(&array[1], &(*it++));
120   EXPECT_EQ(&array[2], &(*it++));
121   EXPECT_EQ(list.end(), it);
122   list.clear();
123 }
124 
TEST(IntrusiveListTest,Construct_PointerIterator_Empty)125 TEST(IntrusiveListTest, Construct_PointerIterator_Empty) {
126   std::array<Item*, 0> array;
127   List list(array.begin(), array.end());
128 
129   EXPECT_TRUE(list.empty());
130   list.clear();
131 }
132 
TEST(IntrusiveListTest,Construct_PointerIterator_One)133 TEST(IntrusiveListTest, Construct_PointerIterator_One) {
134   std::array<Item, 1> array{{{1}}};
135   std::array<Item*, 1> ptrs{{&array[0]}};
136 
137   List list(ptrs.begin(), ptrs.end());
138 
139   EXPECT_EQ(ptrs[0], &list.front());
140   list.clear();
141 }
142 
TEST(IntrusiveListTest,Construct_PointerIterator_Multiple)143 TEST(IntrusiveListTest, Construct_PointerIterator_Multiple) {
144   std::array<Item, 3> array{{{1}, {2}, {3}}};
145   std::array<Item*, 3> ptrs{{&array[0], &array[1], &array[2]}};
146 
147   List list(ptrs.begin(), ptrs.end());
148   auto it = list.begin();
149   EXPECT_EQ(ptrs[0], &(*it++));
150   EXPECT_EQ(ptrs[1], &(*it++));
151   EXPECT_EQ(ptrs[2], &(*it++));
152   EXPECT_EQ(list.end(), it);
153   list.clear();
154 }
155 
156 #if TESTING_CHECK_FAILURES_IS_SUPPORTED
TEST(IntrusiveListTest,Construct_DuplicateItems)157 TEST(IntrusiveListTest, Construct_DuplicateItems) {
158   Item item(1);
159   List list({&item, &item});
160 }
161 #endif  // TESTING_CHECK_FAILURES_IS_SUPPORTED
162 
TEST(IntrusiveListTest,Assign_ReplacesPriorContents)163 TEST(IntrusiveListTest, Assign_ReplacesPriorContents) {
164   std::array<Item, 3> array{{{0}, {100}, {200}}};
165   List list(array.begin(), array.end());
166 
167   list.assign(array.begin() + 1, array.begin() + 2);
168 
169   auto it = list.begin();
170   EXPECT_EQ(&array[1], &(*it++));
171   EXPECT_EQ(list.end(), it);
172   list.clear();
173 }
174 
TEST(IntrusiveListTest,Assign_EmptyRange)175 TEST(IntrusiveListTest, Assign_EmptyRange) {
176   std::array<Item, 3> array{{{0}, {100}, {200}}};
177   List list(array.begin(), array.end());
178 
179   list.assign(array.begin() + 1, array.begin() + 1);
180 
181   EXPECT_TRUE(list.empty());
182 }
183 
184 // Element access unit tests
185 
TEST(IntrusiveListTest,ListFront)186 TEST(IntrusiveListTest, ListFront) {
187   Item item1(1);
188   Item item2(0);
189   Item item3(0xffff);
190 
191   List list;
192   list.push_back(item1);
193   list.push_back(item2);
194   list.push_back(item3);
195 
196   EXPECT_EQ(&item1, &list.front());
197   EXPECT_EQ(&item1, &(*list.begin()));
198   list.clear();
199 }
200 
TEST(IntrusiveListTest,ListBack)201 TEST(IntrusiveListTest, ListBack) {
202   Item item1(1);
203   Item item2(0);
204   Item item3(0xffff);
205 
206   List list;
207   list.push_back(item1);
208   list.push_back(item2);
209   list.push_back(item3);
210 
211   EXPECT_EQ(&item3, &list.back());
212   auto it = list.end();
213   --it;
214   EXPECT_EQ(&item3, &(*it));
215   list.clear();
216 }
217 
218 // Iterator unit tests
219 
TEST(IntrusiveListTest,IteratorIncrement)220 TEST(IntrusiveListTest, IteratorIncrement) {
221   Item item_array[20];
222   List list;
223   for (size_t i = 0; i < PW_ARRAY_SIZE(item_array); ++i) {
224     item_array[i].SetNumber(static_cast<int>(i));
225     list.push_back(item_array[i]);
226   }
227 
228   auto it = list.begin();
229   int i = 0;
230   while (it != list.end()) {
231     if (i == 0) {
232       // Test pre-incrementing on the first element.
233       EXPECT_EQ((++it)->GetNumber(), item_array[++i].GetNumber());
234     } else {
235       EXPECT_EQ((it++)->GetNumber(), item_array[i++].GetNumber());
236     }
237   }
238   list.clear();
239 }
240 
TEST(IntrusiveListTest,IteratorDecrement)241 TEST(IntrusiveListTest, IteratorDecrement) {
242   Item item_array[20];
243   List list;
244   for (size_t i = 0; i < PW_ARRAY_SIZE(item_array); ++i) {
245     item_array[i].SetNumber(static_cast<int>(i));
246     list.push_back(item_array[i]);
247   }
248 
249   auto it = list.end();
250   int i = PW_ARRAY_SIZE(item_array);
251   do {
252     if (i == PW_ARRAY_SIZE(item_array)) {
253       // Test pre-incrementing on the last element.
254       EXPECT_EQ((--it)->GetNumber(), item_array[--i].GetNumber());
255     } else {
256       EXPECT_EQ((it--)->GetNumber(), item_array[i--].GetNumber());
257     }
258   } while (it != list.begin());
259   list.clear();
260 }
261 
TEST(IntrusiveListTest,ConstIteratorRead)262 TEST(IntrusiveListTest, ConstIteratorRead) {
263   // For this test, items are checked to be non-zero.
264   Item item1(1);
265   Item item2(99);
266   List list;
267 
268   const List* const_list = &list;
269 
270   list.push_back(item1);
271   list.push_back(item2);
272 
273   auto it = const_list->begin();
274   while (it != const_list->end()) {
275     EXPECT_NE(it->GetNumber(), 0);
276     it++;
277   }
278   list.clear();
279 }
280 
TEST(IntrusiveListTest,CompareConstAndNonConstIterator)281 TEST(IntrusiveListTest, CompareConstAndNonConstIterator) {
282   List list;
283   EXPECT_EQ(list.end(), list.cend());
284 }
285 
286 class OtherListItem : public IntrusiveList<OtherListItem>::Item {};
287 
288 using OtherList = IntrusiveList<OtherListItem>;
289 
TEST(IntrusiveListTest,CompareConstAndNonConstIterator_CompilationFails)290 TEST(IntrusiveListTest, CompareConstAndNonConstIterator_CompilationFails) {
291   List list;
292   OtherList list2;
293 #if PW_NC_TEST(CannotCompareIncompatibleIteratorsEqual)
294   PW_NC_EXPECT("list\.end\(\) == list2\.end\(\)");
295   static_cast<void>(list.end() == list2.end());
296 #elif PW_NC_TEST(CannotCompareIncompatibleIteratorsInequal)
297   PW_NC_EXPECT("list\.end\(\) != list2\.end\(\)");
298   static_cast<void>(list.end() != list2.end());
299 #endif  // PW_NC_TEST
300 }
301 
302 #if PW_NC_TEST(CannotModifyThroughConstIterator)
303 PW_NC_EXPECT("function is not marked const|discards qualifiers");
304 
TEST(IntrusiveListTest,ConstIteratorModify)305 TEST(IntrusiveListTest, ConstIteratorModify) {
306   Item item1(1);
307   Item item2(99);
308   List list;
309 
310   const List* const_list = &list;
311 
312   list.push_back(item1);
313   list.push_back(item2);
314 
315   auto it = const_list->begin();
316   while (it != const_list->end()) {
317     it->SetNumber(0);
318     it++;
319   }
320 }
321 
322 #endif  // PW_NC_TEST
323 
324 // Capacity unit tests
325 
TEST(IntrusiveListTest,IsEmpty)326 TEST(IntrusiveListTest, IsEmpty) {
327   Item item1(1);
328 
329   List list;
330   EXPECT_TRUE(list.empty());
331 
332   list.push_back(item1);
333   EXPECT_FALSE(list.empty());
334   list.clear();
335 }
336 
TEST(IntrusiveListTest,SizeBasic)337 TEST(IntrusiveListTest, SizeBasic) {
338   List list;
339   EXPECT_EQ(list.size(), 0u);
340 
341   Item one(55);
342   list.push_front(one);
343   EXPECT_EQ(list.size(), static_cast<size_t>(1));
344 
345   Item two(66);
346   list.push_back(two);
347   EXPECT_EQ(list.size(), static_cast<size_t>(2));
348 
349   Item thr(77);
350   list.push_back(thr);
351   EXPECT_EQ(list.size(), static_cast<size_t>(3));
352   list.clear();
353 }
354 
TEST(IntrusiveListTest,MaxSize)355 TEST(IntrusiveListTest, MaxSize) {
356   List list;
357   EXPECT_EQ(list.max_size(), size_t(std::numeric_limits<ptrdiff_t>::max()));
358 }
359 
360 // Modifier unit tests
361 
TEST(IntrusiveListTest,Clear_Empty)362 TEST(IntrusiveListTest, Clear_Empty) {
363   List list;
364   EXPECT_TRUE(list.empty());
365   list.clear();
366   EXPECT_TRUE(list.empty());
367 }
368 
TEST(IntrusiveListTest,Clear_OneItem)369 TEST(IntrusiveListTest, Clear_OneItem) {
370   Item item(42);
371   List list;
372   list.push_back(item);
373   EXPECT_FALSE(list.empty());
374   list.clear();
375   EXPECT_TRUE(list.empty());
376 }
377 
TEST(IntrusiveListTest,Clear_TwoItems)378 TEST(IntrusiveListTest, Clear_TwoItems) {
379   Item item1(42);
380   Item item2(42);
381   List list;
382   list.push_back(item1);
383   list.push_back(item2);
384   EXPECT_FALSE(list.empty());
385   list.clear();
386   EXPECT_TRUE(list.empty());
387 }
388 
TEST(IntrusiveListTest,Clear_ReinsertClearedItems)389 TEST(IntrusiveListTest, Clear_ReinsertClearedItems) {
390   std::array<Item, 20> item_array;
391   List list;
392   EXPECT_TRUE(list.empty());
393   list.clear();
394   EXPECT_TRUE(list.empty());
395 
396   // Fill the list with Item objects.
397   for (size_t i = 0; i < item_array.size(); ++i) {
398     item_array[i].SetNumber(0);
399     list.push_back(item_array[i]);
400   }
401 
402   // Remove everything.
403   list.clear();
404   EXPECT_TRUE(list.empty());
405 
406   // Ensure all the removed elements can still be added back to a list.
407   for (size_t i = 0; i < item_array.size(); ++i) {
408     item_array[i].SetNumber(0);
409     list.push_back(item_array[i]);
410   }
411   list.clear();
412 }
413 
TEST(IntrusiveListTest,Insert)414 TEST(IntrusiveListTest, Insert) {
415   // Create a test item to insert midway through the list.
416   constexpr int kMagicValue = 42;
417   Item inserted_item(kMagicValue);
418 
419   // Create initial values to fill in the start/end.
420   Item item_array[20];
421 
422   List list;
423   // Fill the list with Item objects that have a value of zero.
424   for (size_t i = 0; i < PW_ARRAY_SIZE(item_array); ++i) {
425     item_array[i].SetNumber(0);
426     list.push_back(item_array[i]);
427   }
428 
429   // Move an iterator to the middle of the list, and then insert the magic item.
430   auto it = list.begin();
431   size_t expected_index = 0;  // Expected index is iterator index.
432   for (size_t i = 0; i < PW_ARRAY_SIZE(item_array) / 2; ++i) {
433     it++;
434     expected_index++;
435   }
436   it = list.insert(it, inserted_item);
437 
438   // Ensure the returned iterator from insert is the newly inserted
439   // element.
440   EXPECT_EQ(it->GetNumber(), kMagicValue);
441 
442   // Ensure the value is in the expected location (index of the iterator + 1).
443   size_t i = 0;
444   for (Item& item : list) {
445     if (item.GetNumber() == kMagicValue) {
446       EXPECT_EQ(i, expected_index);
447     } else {
448       EXPECT_EQ(item.GetNumber(), 0);
449     }
450     i++;
451   }
452 
453   // Ensure the list didn't break and change sizes.
454   EXPECT_EQ(i, PW_ARRAY_SIZE(item_array) + 1);
455   list.clear();
456 }
457 
TEST(IntrusiveListTest,Insert_Range)458 TEST(IntrusiveListTest, Insert_Range) {
459   // Create an array of test items to insert into the middle of the list.
460   constexpr int kMagicValue = 42;
461   constexpr int kNumItems = 3;
462   std::array<Item, kNumItems> inserted_items;
463   int n = kMagicValue;
464   for (auto& item : inserted_items) {
465     item.SetNumber(n++);
466   }
467 
468   // Create initial values to fill in the start/end.
469   Item item_array[20];
470 
471   List list;
472   // Fill the list with Item objects that have a value of zero.
473   for (size_t i = 0; i < PW_ARRAY_SIZE(item_array); ++i) {
474     item_array[i].SetNumber(0);
475     list.push_back(item_array[i]);
476   }
477 
478   // Move an iterator to the middle of the list, and then insert the magic item.
479   auto it = list.begin();
480   size_t expected_index = 0;  // Expected index is iterator index.
481   for (size_t i = 0; i < PW_ARRAY_SIZE(item_array) / 2; ++i) {
482     it++;
483     expected_index++;
484   }
485   it = list.insert(it, inserted_items.begin(), inserted_items.end());
486 
487   // Ensure the returned iterator from insert is the last newly inserted
488   // element.
489   EXPECT_EQ(it->GetNumber(), kMagicValue + kNumItems - 1);
490 
491   // Ensure the value is in the expected location (index of the iterator + 1).
492   size_t i = 0;
493   for (Item& item : list) {
494     if (i < expected_index) {
495       EXPECT_EQ(item.GetNumber(), 0);
496     } else if (i < expected_index + inserted_items.size()) {
497       EXPECT_EQ(item.GetNumber(),
498                 kMagicValue + static_cast<int>(i - expected_index));
499     } else {
500       EXPECT_EQ(item.GetNumber(), 0);
501     }
502     i++;
503   }
504 
505   // Ensure the list didn't break and change sizes.
506   EXPECT_EQ(i, PW_ARRAY_SIZE(item_array) + inserted_items.size());
507   list.clear();
508 }
509 
TEST(IntrusiveListTest,Insert_InitializerList)510 TEST(IntrusiveListTest, Insert_InitializerList) {
511   // Create an array of test items to insert into the middle of the list.
512   constexpr int kMagicValue = 42;
513   constexpr int kNumItems = 3;
514   std::array<Item, kNumItems> inserted_items;
515   int n = kMagicValue;
516   for (auto& item : inserted_items) {
517     item.SetNumber(n++);
518   }
519 
520   // Create initial values to fill in the start/end.
521   Item item_array[20];
522 
523   List list;
524   // Fill the list with Item objects that have a value of zero.
525   for (size_t i = 0; i < PW_ARRAY_SIZE(item_array); ++i) {
526     item_array[i].SetNumber(0);
527     list.push_back(item_array[i]);
528   }
529 
530   // Move an iterator to the middle of the list, and then insert the magic item.
531   auto it = list.begin();
532   size_t expected_index = 0;  // Expected index is iterator index.
533   for (size_t i = 0; i < PW_ARRAY_SIZE(item_array) / 2; ++i) {
534     it++;
535     expected_index++;
536   }
537   it = list.insert(it,
538                    {
539                        &inserted_items[0],
540                        &inserted_items[1],
541                        &inserted_items[2],
542                    });
543 
544   // Ensure the returned iterator from insert is the last newly inserted
545   // element.
546   EXPECT_EQ(it->GetNumber(), kMagicValue + kNumItems - 1);
547 
548   // Ensure the value is in the expected location (index of the iterator + 1).
549   size_t i = 0;
550   for (Item& item : list) {
551     if (i < expected_index) {
552       EXPECT_EQ(item.GetNumber(), 0);
553     } else if (i < expected_index + inserted_items.size()) {
554       EXPECT_EQ(item.GetNumber(),
555                 kMagicValue + static_cast<int>(i - expected_index));
556     } else {
557       EXPECT_EQ(item.GetNumber(), 0);
558     }
559     i++;
560   }
561 
562   // Ensure the list didn't break and change sizes.
563   EXPECT_EQ(i, PW_ARRAY_SIZE(item_array) + inserted_items.size());
564   list.clear();
565 }
566 
TEST(IntrusiveListTest,Insert_BeforeBegin)567 TEST(IntrusiveListTest, Insert_BeforeBegin) {
568   // Create a test item to insert at the beginning of the list.
569   constexpr int kMagicValue = 42;
570   Item inserted_item(kMagicValue);
571 
572   // Create initial values to fill in the start/end.
573   Item item_array[20];
574 
575   List list;
576   // Fill the list with Item objects that have a value of zero.
577   for (size_t i = 0; i < PW_ARRAY_SIZE(item_array); ++i) {
578     item_array[i].SetNumber(0);
579     list.push_back(item_array[i]);
580   }
581 
582   auto it = list.insert(list.begin(), inserted_item);
583 
584   // Ensure the returned iterator from insert is the newly inserted
585   // element.
586   EXPECT_EQ(it->GetNumber(), kMagicValue);
587 
588   // Ensure the value is at the beginning of the list.
589   size_t i = 0;
590   for (Item& item : list) {
591     if (item.GetNumber() == kMagicValue) {
592       EXPECT_EQ(i, static_cast<size_t>(0));
593     } else {
594       EXPECT_EQ(item.GetNumber(), 0);
595     }
596     i++;
597   }
598   list.clear();
599 }
600 
TEST(IntrusiveListTest,Insert_BeforeBegin_Range)601 TEST(IntrusiveListTest, Insert_BeforeBegin_Range) {
602   // Create an array of test items to insert into the middle of the list.
603   constexpr int kMagicValue = 42;
604   constexpr int kNumItems = 3;
605   std::array<Item, kNumItems> inserted_items;
606   int n = kMagicValue;
607   for (auto& item : inserted_items) {
608     item.SetNumber(n++);
609   }
610 
611   // Create initial values to fill in the start/end.
612   Item item_array[20];
613 
614   List list;
615   // Fill the list with Item objects that have a value of zero.
616   for (size_t i = 0; i < PW_ARRAY_SIZE(item_array); ++i) {
617     item_array[i].SetNumber(0);
618     list.push_back(item_array[i]);
619   }
620 
621   auto it =
622       list.insert(list.begin(), inserted_items.begin(), inserted_items.end());
623 
624   // Ensure the returned iterator from insert is the last newly inserted
625   // element.
626   EXPECT_EQ(it->GetNumber(), kMagicValue + kNumItems - 1);
627 
628   // Ensure the values are at the beginning of the list.
629   size_t i = 0;
630   for (Item& item : list) {
631     if (i < inserted_items.size()) {
632       EXPECT_EQ(item.GetNumber(), kMagicValue + static_cast<int>(i));
633     } else {
634       EXPECT_EQ(item.GetNumber(), 0);
635     }
636     i++;
637   }
638   list.clear();
639 }
640 
TEST(IntrusiveListTest,Insert_BeforeBegin_InitializerList)641 TEST(IntrusiveListTest, Insert_BeforeBegin_InitializerList) {
642   // Create an array of test items to insert into the middle of the list.
643   constexpr int kMagicValue = 42;
644   constexpr int kNumItems = 3;
645   std::array<Item, kNumItems> inserted_items;
646   int n = kMagicValue;
647   for (auto& item : inserted_items) {
648     item.SetNumber(n++);
649   }
650 
651   // Create initial values to fill in the start/end.
652   Item item_array[20];
653 
654   List list;
655   // Fill the list with Item objects that have a value of zero.
656   for (size_t i = 0; i < PW_ARRAY_SIZE(item_array); ++i) {
657     item_array[i].SetNumber(0);
658     list.push_back(item_array[i]);
659   }
660 
661   auto it = list.insert(list.begin(),
662                         {
663                             &inserted_items[0],
664                             &inserted_items[1],
665                             &inserted_items[2],
666                         });
667 
668   // Ensure the returned iterator from insert is the last newly inserted
669   // element.
670   EXPECT_EQ(it->GetNumber(), kMagicValue + kNumItems - 1);
671 
672   // Ensure the values are at the beginning of the list.
673   size_t i = 0;
674   for (Item& item : list) {
675     if (i < inserted_items.size()) {
676       EXPECT_EQ(item.GetNumber(), kMagicValue + static_cast<int>(i));
677     } else {
678       EXPECT_EQ(item.GetNumber(), 0);
679     }
680     i++;
681   }
682   list.clear();
683 }
684 
685 #if TESTING_CHECK_FAILURES_IS_SUPPORTED
TEST(IntrusiveListTest,Insert_SameItem)686 TEST(IntrusiveListTest, Insert_SameItem) {
687   Item item(1);
688   List list({&item});
689 
690   list.insert(list.begin(), item);
691 }
692 
TEST(IntrusiveListTest,Insert_SameItemAfterEnd)693 TEST(IntrusiveListTest, Insert_SameItemAfterEnd) {
694   Item item(1);
695   List list({&item});
696 
697   list.insert(list.end(), item);
698 }
699 #endif  // TESTING_CHECK_FAILURES_IS_SUPPORTED
700 
TEST(IntrusiveListTest,Erase_First_ByIterator)701 TEST(IntrusiveListTest, Erase_First_ByIterator) {
702   std::array<Item, 3> items{{{0}, {1}, {2}}};
703   List list(items.begin(), items.end());
704 
705   auto it = list.erase(list.begin());
706   EXPECT_EQ(list.begin(), it);
707   EXPECT_EQ(&items[1], &list.front());
708   list.clear();
709 }
710 
TEST(IntrusiveListTest,Erase_First_ByItem)711 TEST(IntrusiveListTest, Erase_First_ByItem) {
712   std::array<Item, 3> items{{{0}, {1}, {2}}};
713   List list(items.begin(), items.end());
714 
715   auto erased = list.erase(items[0]);
716   auto iter = list.begin();
717   EXPECT_EQ(erased, iter);
718   EXPECT_EQ(&items[1], &(*iter++));
719   EXPECT_EQ(&items[2], &(*iter++));
720   EXPECT_EQ(list.end(), iter);
721   list.clear();
722 }
723 
TEST(IntrusiveListTest,Erase_Middle_ByItem)724 TEST(IntrusiveListTest, Erase_Middle_ByItem) {
725   std::array<Item, 3> items{{{0}, {1}, {2}}};
726   List list(items.begin(), items.end());
727 
728   auto erased = list.erase(items[1]);
729   auto iter = list.begin();
730   EXPECT_EQ(&items[0], &(*iter++));
731   EXPECT_EQ(erased, iter);
732   EXPECT_EQ(&items[2], &(*iter++));
733   EXPECT_EQ(list.end(), iter);
734   list.clear();
735 }
736 
TEST(IntrusiveListTest,Erase_Last_ByIterator)737 TEST(IntrusiveListTest, Erase_Last_ByIterator) {
738   std::array<Item, 3> items{{{0}, {1}, {2}}};
739   List list(items.begin(), items.end());
740 
741   auto it = list.end();
742   --it;
743 
744   it = list.erase(it);
745   EXPECT_EQ(list.end(), it);
746 
747   it = list.begin();
748   ++it;
749 
750   EXPECT_EQ(&items[1], &(*it));
751   list.clear();
752 }
753 
TEST(IntrusiveListTest,Erase_Last_ByItem)754 TEST(IntrusiveListTest, Erase_Last_ByItem) {
755   std::array<Item, 3> items{{{0}, {1}, {2}}};
756   List list(items.begin(), items.end());
757 
758   auto erased = list.erase(items[2]);
759   auto iter = list.begin();
760   EXPECT_EQ(&items[0], &(*iter++));
761   EXPECT_EQ(&items[1], &(*iter++));
762   EXPECT_EQ(erased, iter);
763   EXPECT_EQ(list.end(), iter);
764   list.clear();
765 }
766 
TEST(IntrusiveListTest,Erase_AllItems)767 TEST(IntrusiveListTest, Erase_AllItems) {
768   std::array<Item, 3> items{{{0}, {1}, {2}}};
769   List list(items.begin(), items.end());
770 
771   list.erase(list.begin());
772   list.erase(list.begin());
773   auto it = list.erase(list.begin());
774 
775   EXPECT_EQ(list.end(), it);
776   EXPECT_TRUE(list.empty());
777 }
778 
TEST(IntrusiveListTest,Erase_LeadingRange)779 TEST(IntrusiveListTest, Erase_LeadingRange) {
780   std::array<Item, 4> items{{{0}, {1}, {2}, {3}}};
781   List list(items.begin(), items.end());
782 
783   auto it = list.begin();
784   it = list.erase(it, std::next(std::next(it)));
785   EXPECT_EQ(list.begin(), it);
786   EXPECT_EQ(&items[2], &(*it++));
787   EXPECT_EQ(&items[3], &(*it++));
788   EXPECT_EQ(list.end(), it);
789   list.clear();
790 }
791 
TEST(IntrusiveListTest,Erase_TrailingRange)792 TEST(IntrusiveListTest, Erase_TrailingRange) {
793   std::array<Item, 4> items{{{0}, {1}, {2}, {3}}};
794   List list(items.begin(), items.end());
795 
796   auto it = list.end();
797   it = list.erase(std::prev(std::prev(it)), it);
798   EXPECT_EQ(list.end(), it);
799 
800   it = list.begin();
801   EXPECT_EQ(&items[0], &(*it++));
802   EXPECT_EQ(&items[1], &(*it++));
803   EXPECT_EQ(list.end(), it);
804   list.clear();
805 }
806 
TEST(IntrusiveListTest,Erase_FullRange)807 TEST(IntrusiveListTest, Erase_FullRange) {
808   std::array<Item, 4> items{{{0}, {1}, {2}, {3}}};
809   List list(items.begin(), items.end());
810 
811   auto it = list.erase(list.begin(), list.end());
812   EXPECT_EQ(list.end(), it);
813   EXPECT_TRUE(list.empty());
814 }
815 
TEST(IntrusiveListTest,Erase_EmptyRange)816 TEST(IntrusiveListTest, Erase_EmptyRange) {
817   std::array<Item, 4> items{{{0}, {1}, {2}, {3}}};
818   List list(items.begin(), items.end());
819 
820   auto it = list.erase(list.begin(), list.begin());
821   EXPECT_EQ(list.begin(), it);
822   EXPECT_EQ(&items[0], &list.front());
823   list.clear();
824 }
825 
TEST(IntrusiveListTest,PushBackOne)826 TEST(IntrusiveListTest, PushBackOne) {
827   constexpr int kMagicValue = 31;
828   Item item1(kMagicValue);
829   List list;
830   list.push_back(item1);
831   EXPECT_FALSE(list.empty());
832   EXPECT_EQ(list.front().GetNumber(), kMagicValue);
833   list.clear();
834 }
835 
TEST(IntrusiveListTest,PushBackThree)836 TEST(IntrusiveListTest, PushBackThree) {
837   Item item1(1);
838   Item item2(2);
839   Item item3(3);
840 
841   List list;
842   list.push_back(item1);
843   list.push_back(item2);
844   list.push_back(item3);
845 
846   int loop_count = 0;
847   for (auto& test_item : list) {
848     loop_count++;
849     EXPECT_EQ(loop_count, test_item.GetNumber());
850   }
851   EXPECT_EQ(loop_count, 3);
852   list.clear();
853 }
854 
855 #if TESTING_CHECK_FAILURES_IS_SUPPORTED
TEST(IntrusiveListTest,PushBack_SameItem)856 TEST(IntrusiveListTest, PushBack_SameItem) {
857   Item item(1);
858   List list({&item});
859 
860   list.push_back(item);
861 }
862 #endif  // TESTING_CHECK_FAILURES_IS_SUPPORTED
863 
TEST(IntrusiveListTest,PopBack)864 TEST(IntrusiveListTest, PopBack) {
865   constexpr int kValue1 = 32;
866   constexpr int kValue2 = 4083;
867 
868   Item item1(kValue1);
869   Item item2(kValue2);
870 
871   List list;
872   EXPECT_TRUE(list.empty());
873 
874   list.push_back(item1);
875   list.push_back(item2);
876   list.pop_back();
877   EXPECT_EQ(list.back().GetNumber(), kValue1);
878   EXPECT_FALSE(list.empty());
879   list.pop_back();
880   EXPECT_TRUE(list.empty());
881 }
882 
TEST(IntrusiveListTest,PopBackAndReinsert)883 TEST(IntrusiveListTest, PopBackAndReinsert) {
884   constexpr int kValue1 = 32;
885   constexpr int kValue2 = 4083;
886 
887   Item item1(kValue1);
888   Item item2(kValue2);
889 
890   List list;
891   EXPECT_TRUE(list.empty());
892 
893   list.push_back(item1);
894   list.push_back(item2);
895   list.pop_back();
896   list.push_back(item2);
897   EXPECT_EQ(list.back().GetNumber(), kValue2);
898   list.clear();
899 }
900 
TEST(IntrusiveListTest,PushFront)901 TEST(IntrusiveListTest, PushFront) {
902   constexpr int kMagicValue = 42;
903   Item pushed_item(kMagicValue);
904 
905   Item item_array[20];
906   List list;
907   // Fill the list with Item objects that have a value of zero.
908   for (size_t i = 0; i < PW_ARRAY_SIZE(item_array); ++i) {
909     item_array[i].SetNumber(0);
910     list.push_back(item_array[i]);
911   }
912 
913   // Create a test item to push to the front of the list.
914   list.push_front(pushed_item);
915   EXPECT_EQ(list.front().GetNumber(), kMagicValue);
916   list.clear();
917 }
918 
TEST(IntrusiveListTest,PushFrontOne)919 TEST(IntrusiveListTest, PushFrontOne) {
920   constexpr int kMagicValue = 31;
921   Item item1(kMagicValue);
922   List list;
923   list.push_front(item1);
924   EXPECT_FALSE(list.empty());
925   EXPECT_EQ(list.front().GetNumber(), kMagicValue);
926   list.clear();
927 }
928 
TEST(IntrusiveListTest,PushFrontThree)929 TEST(IntrusiveListTest, PushFrontThree) {
930   Item item1(1);
931   Item item2(2);
932   Item item3(3);
933 
934   List list;
935   list.push_front(item3);
936   list.push_front(item2);
937   list.push_front(item1);
938 
939   int loop_count = 0;
940   for (auto& test_item : list) {
941     loop_count++;
942     EXPECT_EQ(loop_count, test_item.GetNumber());
943   }
944   EXPECT_EQ(loop_count, 3);
945   list.clear();
946 }
947 
948 #if TESTING_CHECK_FAILURES_IS_SUPPORTED
TEST(IntrusiveListTest,PushFront_SameItem)949 TEST(IntrusiveListTest, PushFront_SameItem) {
950   Item item(1);
951   List list({&item});
952 
953   list.push_front(item);
954 }
955 #endif  // TESTING_CHECK_FAILURES_IS_SUPPORTED
956 
TEST(IntrusiveListTest,PopFront)957 TEST(IntrusiveListTest, PopFront) {
958   constexpr int kValue1 = 32;
959   constexpr int kValue2 = 4083;
960 
961   Item item1(kValue1);
962   Item item2(kValue2);
963 
964   List list;
965   EXPECT_TRUE(list.empty());
966 
967   list.push_front(item2);
968   list.push_front(item1);
969   list.pop_front();
970   EXPECT_EQ(list.front().GetNumber(), kValue2);
971   EXPECT_FALSE(list.empty());
972   list.pop_front();
973   EXPECT_TRUE(list.empty());
974 }
975 
TEST(IntrusiveListTest,PopFrontAndReinsert)976 TEST(IntrusiveListTest, PopFrontAndReinsert) {
977   constexpr int kValue1 = 32;
978   constexpr int kValue2 = 4083;
979 
980   Item item1(kValue1);
981   Item item2(kValue2);
982 
983   List list;
984   EXPECT_TRUE(list.empty());
985 
986   list.push_front(item2);
987   list.push_front(item1);
988   list.pop_front();
989   list.push_front(item1);
990   EXPECT_EQ(list.front().GetNumber(), kValue1);
991   list.clear();
992 }
993 
TEST(IntrusiveListTest,Swap)994 TEST(IntrusiveListTest, Swap) {
995   std::array<Item, 4> items1{{{0}, {1}, {2}, {3}}};
996   std::array<Item, 2> items2{{{4}, {5}}};
997   List list1(items1.begin(), items1.end());
998   List list2(items2.begin(), items2.end());
999 
1000   list1.swap(list2);
1001 
1002   auto it = list1.begin();
1003   EXPECT_EQ(&items2[0], &(*it++));
1004   EXPECT_EQ(&items2[1], &(*it++));
1005   EXPECT_EQ(it, list1.end());
1006 
1007   it = list2.begin();
1008   EXPECT_EQ(&items1[0], &(*it++));
1009   EXPECT_EQ(&items1[1], &(*it++));
1010   EXPECT_EQ(&items1[2], &(*it++));
1011   EXPECT_EQ(&items1[3], &(*it++));
1012   EXPECT_EQ(it, list2.end());
1013 
1014   list1.clear();
1015   list2.clear();
1016 }
1017 
TEST(IntrusiveListTest,Swap_Empty)1018 TEST(IntrusiveListTest, Swap_Empty) {
1019   std::array<Item, 3> items1{{{0}, {1}, {2}}};
1020   List list1(items1.begin(), items1.end());
1021   List list2;
1022 
1023   list1.swap(list2);
1024   EXPECT_TRUE(list1.empty());
1025 
1026   auto it = list2.begin();
1027   EXPECT_EQ(&items1[0], &(*it++));
1028   EXPECT_EQ(&items1[1], &(*it++));
1029   EXPECT_EQ(&items1[2], &(*it++));
1030   EXPECT_EQ(it, list2.end());
1031 
1032   list1.swap(list2);
1033   EXPECT_TRUE(list2.empty());
1034 
1035   it = list1.begin();
1036   EXPECT_EQ(&items1[0], &(*it++));
1037   EXPECT_EQ(&items1[1], &(*it++));
1038   EXPECT_EQ(&items1[2], &(*it++));
1039   EXPECT_EQ(it, list1.end());
1040 
1041   list1.clear();
1042 }
1043 
1044 // Operation unit tests
1045 
TEST(IntrusiveListTest,Merge)1046 TEST(IntrusiveListTest, Merge) {
1047   std::array<Item, 3> evens{{{0}, {2}, {4}}};
1048   std::array<Item, 3> odds{{{1}, {3}, {5}}};
1049 
1050   List list(evens.begin(), evens.end());
1051   List other(odds.begin(), odds.end());
1052   list.merge(other);
1053   EXPECT_TRUE(other.empty());
1054 
1055   int i = 0;
1056   for (const Item& item : list) {
1057     EXPECT_EQ(item.GetNumber(), i++);
1058   }
1059   EXPECT_EQ(i, 6);
1060   list.clear();
1061 }
1062 
TEST(IntrusiveListTest,Merge_Compare)1063 TEST(IntrusiveListTest, Merge_Compare) {
1064   std::array<Item, 3> evens{{{4}, {2}, {0}}};
1065   std::array<Item, 3> odds{{{5}, {3}, {1}}};
1066   auto greater_than = [](const Item& a, const Item& b) {
1067     return a.GetNumber() > b.GetNumber();
1068   };
1069 
1070   List list(evens.begin(), evens.end());
1071   List other(odds.begin(), odds.end());
1072   list.merge(other, greater_than);
1073   EXPECT_TRUE(other.empty());
1074 
1075   int i = 6;
1076   for (const Item& item : list) {
1077     EXPECT_EQ(item.GetNumber(), --i);
1078   }
1079   EXPECT_EQ(i, 0);
1080   list.clear();
1081 }
1082 
TEST(IntrusiveListTest,Merge_Empty)1083 TEST(IntrusiveListTest, Merge_Empty) {
1084   std::array<Item, 3> items{{{1}, {2}, {3}}};
1085 
1086   List list;
1087   List other(items.begin(), items.end());
1088   list.merge(other);
1089 
1090   EXPECT_TRUE(other.empty());
1091   list.merge(other);
1092 
1093   int i = 1;
1094   for (const Item& item : list) {
1095     EXPECT_EQ(item.GetNumber(), i++);
1096   }
1097   EXPECT_EQ(i, 4);
1098   list.clear();
1099 }
1100 
TEST(IntrusiveListTest,Merge_IsStable)1101 TEST(IntrusiveListTest, Merge_IsStable) {
1102   std::array<Item, 2> ends{{{0}, {2}}};
1103   std::array<Item, 3> mids{{{1}, {1}, {1}}};
1104 
1105   List list(ends.begin(), ends.end());
1106   List other(mids.begin(), mids.end());
1107   list.merge(other);
1108   EXPECT_TRUE(other.empty());
1109 
1110   auto it = list.begin();
1111   EXPECT_EQ(&ends[0], &(*it++));
1112   EXPECT_EQ(&mids[0], &(*it++));
1113   EXPECT_EQ(&mids[1], &(*it++));
1114   EXPECT_EQ(&mids[2], &(*it++));
1115   EXPECT_EQ(&ends[1], &(*it++));
1116   EXPECT_EQ(list.end(), it);
1117   list.clear();
1118 }
1119 
TEST(IntrusiveListTest,Splice)1120 TEST(IntrusiveListTest, Splice) {
1121   std::array<Item, 2> items{{{1}, {5}}};
1122   std::array<Item, 3> other_items{{{2}, {3}, {4}}};
1123 
1124   List list(items.begin(), items.end());
1125   List other(other_items.begin(), other_items.end());
1126   list.splice(std::next(list.begin()), other);
1127   EXPECT_TRUE(other.empty());
1128 
1129   int i = 1;
1130   for (const Item& item : list) {
1131     EXPECT_EQ(item.GetNumber(), i++);
1132   }
1133   EXPECT_EQ(i, 6);
1134   list.clear();
1135 }
1136 
TEST(IntrusiveListTest,Splice_BeforeBegin)1137 TEST(IntrusiveListTest, Splice_BeforeBegin) {
1138   std::array<Item, 2> items{{{4}, {5}}};
1139   std::array<Item, 3> other_items{{{1}, {2}, {3}}};
1140 
1141   List list(items.begin(), items.end());
1142   List other(other_items.begin(), other_items.end());
1143   list.splice(list.begin(), other);
1144   EXPECT_TRUE(other.empty());
1145 
1146   int i = 1;
1147   for (const Item& item : list) {
1148     EXPECT_EQ(item.GetNumber(), i++);
1149   }
1150   EXPECT_EQ(i, 6);
1151   list.clear();
1152 }
1153 
TEST(IntrusiveListTest,Splice_BeforeEnd)1154 TEST(IntrusiveListTest, Splice_BeforeEnd) {
1155   std::array<Item, 2> items{{{1}, {2}}};
1156   std::array<Item, 3> other_items{{{3}, {4}, {5}}};
1157 
1158   List list(items.begin(), items.end());
1159   List other(other_items.begin(), other_items.end());
1160   list.splice(list.end(), other);
1161   EXPECT_TRUE(other.empty());
1162 
1163   int i = 1;
1164   for (const Item& item : list) {
1165     EXPECT_EQ(item.GetNumber(), i++);
1166   }
1167   EXPECT_EQ(i, 6);
1168   list.clear();
1169 }
1170 
TEST(IntrusiveListTest,Splice_OneItem)1171 TEST(IntrusiveListTest, Splice_OneItem) {
1172   std::array<Item, 2> items{{{1}, {3}}};
1173   std::array<Item, 3> other_items{{{1}, {2}, {3}}};
1174 
1175   List list(items.begin(), items.end());
1176   List other(other_items.begin(), other_items.end());
1177   list.splice(std::next(list.begin()), other, std::next(other.begin()));
1178   EXPECT_FALSE(other.empty());
1179 
1180   int i = 1;
1181   for (const Item& item : list) {
1182     EXPECT_EQ(item.GetNumber(), i++);
1183   }
1184   EXPECT_EQ(i, 4);
1185   other.clear();
1186   list.clear();
1187 }
1188 
TEST(IntrusiveListTest,Splice_Range)1189 TEST(IntrusiveListTest, Splice_Range) {
1190   std::array<Item, 2> items{{{1}, {5}}};
1191   std::array<Item, 5> other_items{{{1}, {2}, {3}, {4}, {5}}};
1192 
1193   List list(items.begin(), items.end());
1194   List other(other_items.begin(), other_items.end());
1195   list.splice(std::next(list.begin()),
1196               other,
1197               std::next(other.begin()),
1198               std::prev(other.end()));
1199   EXPECT_FALSE(other.empty());
1200 
1201   int i = 1;
1202   for (const Item& item : list) {
1203     EXPECT_EQ(item.GetNumber(), i++);
1204   }
1205   EXPECT_EQ(i, 6);
1206   other.clear();
1207   list.clear();
1208 }
1209 
TEST(IntrusiveListTest,Splice_EmptyRange)1210 TEST(IntrusiveListTest, Splice_EmptyRange) {
1211   std::array<Item, 3> items{{{1}, {2}, {3}}};
1212   std::array<Item, 3> other_items{{{4}, {4}, {4}}};
1213 
1214   List list(items.begin(), items.end());
1215   List other(other_items.begin(), other_items.end());
1216   list.splice(list.begin(), other, other.begin(), other.begin());
1217   EXPECT_FALSE(other.empty());
1218 
1219   int i = 1;
1220   for (const Item& item : list) {
1221     EXPECT_EQ(item.GetNumber(), i++);
1222   }
1223   EXPECT_EQ(i, 4);
1224   other.clear();
1225   list.clear();
1226 }
1227 
TEST(IntrusiveListTest,Remove_EmptyList)1228 TEST(IntrusiveListTest, Remove_EmptyList) {
1229   std::array<Item, 1> items{{{3}}};
1230   List list(items.begin(), items.begin());  // Add nothing!
1231 
1232   EXPECT_TRUE(list.empty());
1233   EXPECT_FALSE(list.remove(items[0]));
1234 }
1235 
TEST(IntrusiveListTest,Remove_SingleItem_NotPresent)1236 TEST(IntrusiveListTest, Remove_SingleItem_NotPresent) {
1237   std::array<Item, 1> items{{{1}}};
1238   List list(items.begin(), items.end());
1239 
1240   EXPECT_FALSE(list.remove(Item(1)));
1241   EXPECT_EQ(&items.front(), &list.front());
1242   list.clear();
1243 }
1244 
TEST(IntrusiveListTest,Remove_SingleItem_Removed)1245 TEST(IntrusiveListTest, Remove_SingleItem_Removed) {
1246   std::array<Item, 1> items{{{1}}};
1247   List list(items.begin(), items.end());
1248 
1249   EXPECT_TRUE(list.remove(items[0]));
1250   EXPECT_TRUE(list.empty());
1251 }
1252 
TEST(IntrusiveListTest,Remove_MultipleItems_NotPresent)1253 TEST(IntrusiveListTest, Remove_MultipleItems_NotPresent) {
1254   std::array<Item, 5> items{{{1}, {1}, {2}, {3}, {4}}};
1255   List list(items.begin(), items.end());
1256 
1257   EXPECT_FALSE(list.remove(Item(1)));
1258   list.clear();
1259 }
1260 
TEST(IntrusiveListTest,Remove_MultipleItems_RemoveAndPushBack)1261 TEST(IntrusiveListTest, Remove_MultipleItems_RemoveAndPushBack) {
1262   std::array<Item, 5> items{{{1}, {1}, {2}, {3}, {4}}};
1263   List list(items.begin(), items.end());
1264 
1265   EXPECT_TRUE(list.remove(items[0]));
1266   EXPECT_TRUE(list.remove(items[3]));
1267   list.push_back(items[0]);  // Make sure can add the item after removing it.
1268 
1269   auto it = list.begin();
1270   EXPECT_EQ(&items[1], &(*it++));
1271   EXPECT_EQ(&items[2], &(*it++));
1272   EXPECT_EQ(&items[4], &(*it++));
1273   EXPECT_EQ(&items[0], &(*it++));
1274   EXPECT_EQ(list.end(), it);
1275   list.clear();
1276 }
1277 
TEST(IntrusiveListTest,RemoveIf_MatchNone)1278 TEST(IntrusiveListTest, RemoveIf_MatchNone) {
1279   std::array<Item, 5> items{{{1}, {3}, {5}, {7}, {9}}};
1280   List list(items.begin(), items.end());
1281   auto equal_two = [](const Item& a) { return a.GetNumber() == 2; };
1282 
1283   EXPECT_EQ(list.remove_if(equal_two), 0U);
1284 
1285   auto it = list.begin();
1286   EXPECT_EQ(&items[0], &(*it++));
1287   EXPECT_EQ(&items[1], &(*it++));
1288   EXPECT_EQ(&items[2], &(*it++));
1289   EXPECT_EQ(&items[3], &(*it++));
1290   EXPECT_EQ(&items[4], &(*it++));
1291   EXPECT_EQ(list.end(), it);
1292   list.clear();
1293 }
1294 
TEST(IntrusiveListTest,RemoveIf_MatchSome)1295 TEST(IntrusiveListTest, RemoveIf_MatchSome) {
1296   std::array<Item, 5> items{{{1}, {2}, {2}, {2}, {3}}};
1297   List list(items.begin(), items.end());
1298   auto equal_two = [](const Item& a) { return a.GetNumber() == 2; };
1299 
1300   EXPECT_EQ(list.remove_if(equal_two), 3U);
1301 
1302   auto it = list.begin();
1303   EXPECT_EQ(&items[0], &(*it++));
1304   EXPECT_EQ(&items[4], &(*it++));
1305   EXPECT_EQ(list.end(), it);
1306   list.clear();
1307 }
1308 
TEST(IntrusiveListTest,RemoveIf_MatchAll)1309 TEST(IntrusiveListTest, RemoveIf_MatchAll) {
1310   std::array<Item, 5> items{{{2}, {2}, {2}, {2}, {2}}};
1311   List list(items.begin(), items.end());
1312   auto equal_two = [](const Item& a) { return a.GetNumber() == 2; };
1313 
1314   EXPECT_EQ(list.remove_if(equal_two), 5U);
1315   EXPECT_TRUE(list.empty());
1316 }
1317 
TEST(IntrusiveListTest,RemoveIf_Empty)1318 TEST(IntrusiveListTest, RemoveIf_Empty) {
1319   List list;
1320   auto equal_two = [](const Item& a) { return a.GetNumber() == 2; };
1321 
1322   EXPECT_EQ(list.remove_if(equal_two), 0U);
1323   EXPECT_TRUE(list.empty());
1324 }
1325 
TEST(IntrusiveListTest,Reverse)1326 TEST(IntrusiveListTest, Reverse) {
1327   std::array<Item, 5> items{{{0}, {1}, {2}, {3}, {4}}};
1328   List list(items.begin(), items.end());
1329 
1330   list.reverse();
1331 
1332   int i = 4;
1333   for (const Item& item : list) {
1334     EXPECT_EQ(item.GetNumber(), i--);
1335   }
1336   EXPECT_EQ(i, -1);
1337   list.clear();
1338 }
1339 
TEST(IntrusiveListTest,Reverse_Empty)1340 TEST(IntrusiveListTest, Reverse_Empty) {
1341   List list;
1342   list.reverse();
1343   EXPECT_TRUE(list.empty());
1344 }
1345 
TEST(IntrusiveListTest,Unique)1346 TEST(IntrusiveListTest, Unique) {
1347   std::array<Item, 10> items{
1348       {{0}, {0}, {0}, {1}, {2}, {2}, {3}, {3}, {3}, {3}}};
1349   List list(items.begin(), items.end());
1350 
1351   EXPECT_EQ(list.unique(), 6U);
1352 
1353   int i = 0;
1354   for (const Item& item : list) {
1355     EXPECT_EQ(item.GetNumber(), i++);
1356   }
1357   EXPECT_EQ(i, 4);
1358   list.clear();
1359 }
1360 
TEST(IntrusiveListTest,Unique_Compare)1361 TEST(IntrusiveListTest, Unique_Compare) {
1362   std::array<Item, 10> items{
1363       {{0}, {2}, {1}, {3}, {1}, {0}, {1}, {0}, {2}, {4}}};
1364   List list(items.begin(), items.end());
1365   auto parity = [](const Item& a, const Item& b) {
1366     return (a.GetNumber() % 2) == (b.GetNumber() % 2);
1367   };
1368 
1369   EXPECT_EQ(list.unique(parity), 5U);
1370 
1371   int i = 0;
1372   for (const Item& item : list) {
1373     EXPECT_EQ(item.GetNumber(), i);
1374     i = (i + 1) % 2;
1375   }
1376   list.clear();
1377 }
1378 
TEST(IntrusiveListTest,Unique_Empty)1379 TEST(IntrusiveListTest, Unique_Empty) {
1380   List list;
1381 
1382   EXPECT_EQ(list.unique(), 0U);
1383 
1384   EXPECT_TRUE(list.empty());
1385 }
1386 
TEST(IntrusiveListTest,Unique_NoDuplicates)1387 TEST(IntrusiveListTest, Unique_NoDuplicates) {
1388   std::array<Item, 5> items{{{0}, {1}, {2}, {3}, {4}}};
1389   List list(items.begin(), items.end());
1390 
1391   EXPECT_EQ(list.unique(), 0U);
1392 
1393   int i = 0;
1394   for (const Item& item : list) {
1395     EXPECT_EQ(item.GetNumber(), i++);
1396   }
1397   EXPECT_EQ(i, 5);
1398   list.clear();
1399 }
1400 
TEST(IntrusiveListTest,Sort)1401 TEST(IntrusiveListTest, Sort) {
1402   std::array<Item, 5> items{{{5}, {1}, {3}, {2}, {4}}};
1403   List list(items.begin(), items.end());
1404   list.sort();
1405 
1406   int i = 1;
1407   for (const Item& item : list) {
1408     EXPECT_EQ(item.GetNumber(), i++);
1409   }
1410   EXPECT_EQ(i, 6);
1411   list.clear();
1412 }
1413 
TEST(IntrusiveListTest,Sort_Compare)1414 TEST(IntrusiveListTest, Sort_Compare) {
1415   std::array<Item, 5> items{{{5}, {1}, {3}, {2}, {4}}};
1416   List list(items.begin(), items.end());
1417   auto greater_than = [](const Item& a, const Item& b) {
1418     return a.GetNumber() > b.GetNumber();
1419   };
1420   list.sort(greater_than);
1421 
1422   int i = 5;
1423   for (const Item& item : list) {
1424     EXPECT_EQ(item.GetNumber(), i--);
1425   }
1426   EXPECT_EQ(i, 0);
1427   list.clear();
1428 }
1429 
TEST(IntrusiveListTest,Sort_Empty)1430 TEST(IntrusiveListTest, Sort_Empty) {
1431   List list;
1432   list.sort();
1433   EXPECT_TRUE(list.empty());
1434 }
1435 
TEST(IntrusiveListTest,Sort_Stable)1436 TEST(IntrusiveListTest, Sort_Stable) {
1437   std::array<Item, 5> items{{{0}, {1}, {1}, {1}, {2}}};
1438   List list(items.begin(), items.end());
1439   list.sort();
1440 
1441   auto it = list.begin();
1442   EXPECT_EQ(&items[0], &(*it++));
1443   EXPECT_EQ(&items[1], &(*it++));
1444   EXPECT_EQ(&items[2], &(*it++));
1445   EXPECT_EQ(&items[3], &(*it++));
1446   EXPECT_EQ(&items[4], &(*it++));
1447   EXPECT_EQ(list.end(), it);
1448   list.clear();
1449 }
1450 
1451 // Other type-related unit tests
1452 
TEST(IntrusiveListTest,AddItemsOfDerivedClassToList)1453 TEST(IntrusiveListTest, AddItemsOfDerivedClassToList) {
1454   List list;
1455 
1456   DerivedItem item1;
1457   list.push_front(item1);
1458 
1459   Item item2;
1460   list.push_front(item2);
1461 
1462   EXPECT_EQ(2u, list.size());
1463   list.clear();
1464 }
1465 
TEST(IntrusiveListTest,ListOfDerivedClassItems)1466 TEST(IntrusiveListTest, ListOfDerivedClassItems) {
1467   IntrusiveList<DerivedItem> derived_from_compatible_item_type;
1468 
1469   DerivedItem item1;
1470   derived_from_compatible_item_type.push_front(item1);
1471 
1472   EXPECT_EQ(1u, derived_from_compatible_item_type.size());
1473 
1474 #if PW_NC_TEST(CannotAddBaseClassToDerivedClassList)
1475   PW_NC_EXPECT_CLANG("cannot bind to a value of unrelated type");
1476   PW_NC_EXPECT_GCC("cannot convert");
1477 
1478   Item item2;
1479   derived_from_compatible_item_type.push_front(item2);
1480 #endif
1481   derived_from_compatible_item_type.clear();
1482 }
1483 
1484 #if PW_NC_TEST(IncompatibleItem)
1485 PW_NC_EXPECT("IntrusiveList items must be derived from IntrusiveList<T>::Item");
1486 
1487 struct Foo {};
1488 
1489 class BadItem : public IntrusiveList<Foo>::Item {};
1490 
1491 [[maybe_unused]] IntrusiveList<BadItem> derived_from_incompatible_item_type;
1492 
1493 #elif PW_NC_TEST(DoesNotInheritFromItem)
1494 PW_NC_EXPECT("IntrusiveList items must be derived from IntrusiveList<T>::Item");
1495 
1496 struct NotAnItem {};
1497 
1498 [[maybe_unused]] IntrusiveList<NotAnItem> list;
1499 
1500 #endif  // PW_NC_TEST
1501 
TEST(IntrusiveListTest,MoveUnlistedItems)1502 TEST(IntrusiveListTest, MoveUnlistedItems) {
1503   Item item1(3);
1504   EXPECT_EQ(item1.GetNumber(), 3);
1505 
1506   Item item2(std::move(item1));
1507   EXPECT_EQ(item2.GetNumber(), 3);
1508 
1509   Item item3;
1510   item3 = std::move(item2);
1511   EXPECT_EQ(item3.GetNumber(), 3);
1512 }
1513 
TEST(IntrusiveListTest,MoveItemsToVector)1514 TEST(IntrusiveListTest, MoveItemsToVector) {
1515   pw::Vector<Item, 3> vec;
1516   vec.emplace_back(Item(1));
1517   vec.emplace_back(Item(2));
1518   vec.emplace_back(Item(3));
1519   List list;
1520   list.assign(vec.begin(), vec.end());
1521 
1522   auto iter = list.begin();
1523   for (const auto& item : vec) {
1524     EXPECT_NE(iter, list.end());
1525     if (iter == list.end()) {
1526       break;
1527     }
1528     EXPECT_EQ(item.GetNumber(), iter->GetNumber());
1529     ++iter;
1530   }
1531   list.clear();
1532 
1533   // TODO(b/313899658): Vector has an MSAN bug in its destructor when clearing
1534   // items that reference themselves. Workaround it by manually clearing.
1535   vec.clear();
1536 }
1537 
1538 }  // namespace
1539