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