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