Update copyright year range in header of all files managed by GDB
[binutils-gdb.git] / gdb / unittests / intrusive_list-selftests.c
blobfe47177d51f1b5e565a2387d6eb70a48c6c0ee9d
1 /* Tests fpr intrusive double linked list for GDB, the GNU debugger.
2 Copyright (C) 2021-2023 Free Software Foundation, Inc.
4 This file is part of GDB.
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 3 of the License, or
9 (at your option) any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program. If not, see <http://www.gnu.org/licenses/>. */
19 #include "defs.h"
21 #include "gdbsupport/intrusive_list.h"
22 #include "gdbsupport/selftest.h"
23 #include <unordered_set>
25 /* An item type using intrusive_list_node by inheriting from it and its
26 corresponding list type. Put another base before intrusive_list_node
27 so that a pointer to the node != a pointer to the item. */
29 struct other_base
31 int n = 1;
34 struct item_with_base : public other_base,
35 public intrusive_list_node<item_with_base>
37 explicit item_with_base (const char *name)
38 : name (name)
41 const char *const name;
44 using item_with_base_list = intrusive_list<item_with_base>;
46 /* An item type using intrusive_list_node as a field and its corresponding
47 list type. Put the other field before the node, so that a pointer to the
48 node != a pointer to the item. */
50 struct item_with_member
52 explicit item_with_member (const char *name)
53 : name (name)
56 const char *const name;
57 intrusive_list_node<item_with_member> node;
60 using item_with_member_node
61 = intrusive_member_node<item_with_member, &item_with_member::node>;
62 using item_with_member_list
63 = intrusive_list<item_with_member, item_with_member_node>;
65 /* To run all tests using both the base and member methods, all tests are
66 declared in this templated class, which is instantiated once for each
67 list type. */
69 template <typename ListType>
70 struct intrusive_list_test
72 using item_type = typename ListType::value_type;
74 /* Verify that LIST contains exactly the items in EXPECTED.
76 Traverse the list forward and backwards to exercise all links. */
78 static void
79 verify_items (const ListType &list,
80 gdb::array_view<const typename ListType::value_type *> expected)
82 int i = 0;
84 for (typename ListType::iterator it = list.begin ();
85 it != list.end ();
86 ++it)
88 const item_type &item = *it;
90 gdb_assert (i < expected.size ());
91 gdb_assert (&item == expected[i]);
93 ++i;
96 gdb_assert (i == expected.size ());
98 for (typename ListType::reverse_iterator it = list.rbegin ();
99 it != list.rend ();
100 ++it)
102 const item_type &item = *it;
104 --i;
106 gdb_assert (i >= 0);
107 gdb_assert (&item == expected[i]);
110 gdb_assert (i == 0);
113 static void
114 test_move_constructor ()
117 /* Other list is not empty. */
118 item_type a ("a"), b ("b"), c ("c");
119 ListType list1;
120 std::vector<const item_type *> expected;
122 list1.push_back (a);
123 list1.push_back (b);
124 list1.push_back (c);
126 ListType list2 (std::move (list1));
128 expected = {};
129 verify_items (list1, expected);
131 expected = {&a, &b, &c};
132 verify_items (list2, expected);
136 /* Other list contains 1 element. */
137 item_type a ("a");
138 ListType list1;
139 std::vector<const item_type *> expected;
141 list1.push_back (a);
143 ListType list2 (std::move (list1));
145 expected = {};
146 verify_items (list1, expected);
148 expected = {&a};
149 verify_items (list2, expected);
153 /* Other list is empty. */
154 ListType list1;
155 std::vector<const item_type *> expected;
157 ListType list2 (std::move (list1));
159 expected = {};
160 verify_items (list1, expected);
162 expected = {};
163 verify_items (list2, expected);
167 static void
168 test_move_assignment ()
171 /* Both lists are not empty. */
172 item_type a ("a"), b ("b"), c ("c"), d ("d"), e ("e");
173 ListType list1;
174 ListType list2;
175 std::vector<const item_type *> expected;
177 list1.push_back (a);
178 list1.push_back (b);
179 list1.push_back (c);
181 list2.push_back (d);
182 list2.push_back (e);
184 list2 = std::move (list1);
186 expected = {};
187 verify_items (list1, expected);
189 expected = {&a, &b, &c};
190 verify_items (list2, expected);
194 /* rhs list is empty. */
195 item_type a ("a"), b ("b"), c ("c");
196 ListType list1;
197 ListType list2;
198 std::vector<const item_type *> expected;
200 list2.push_back (a);
201 list2.push_back (b);
202 list2.push_back (c);
204 list2 = std::move (list1);
206 expected = {};
207 verify_items (list1, expected);
209 expected = {};
210 verify_items (list2, expected);
214 /* lhs list is empty. */
215 item_type a ("a"), b ("b"), c ("c");
216 ListType list1;
217 ListType list2;
218 std::vector<const item_type *> expected;
220 list1.push_back (a);
221 list1.push_back (b);
222 list1.push_back (c);
224 list2 = std::move (list1);
226 expected = {};
227 verify_items (list1, expected);
229 expected = {&a, &b, &c};
230 verify_items (list2, expected);
234 /* Both lists contain 1 item. */
235 item_type a ("a"), b ("b");
236 ListType list1;
237 ListType list2;
238 std::vector<const item_type *> expected;
240 list1.push_back (a);
241 list2.push_back (b);
243 list2 = std::move (list1);
245 expected = {};
246 verify_items (list1, expected);
248 expected = {&a};
249 verify_items (list2, expected);
253 /* Both lists are empty. */
254 ListType list1;
255 ListType list2;
256 std::vector<const item_type *> expected;
258 list2 = std::move (list1);
260 expected = {};
261 verify_items (list1, expected);
263 expected = {};
264 verify_items (list2, expected);
268 static void
269 test_swap ()
272 /* Two non-empty lists. */
273 item_type a ("a"), b ("b"), c ("c"), d ("d"), e ("e");
274 ListType list1;
275 ListType list2;
276 std::vector<const item_type *> expected;
278 list1.push_back (a);
279 list1.push_back (b);
280 list1.push_back (c);
282 list2.push_back (d);
283 list2.push_back (e);
285 std::swap (list1, list2);
287 expected = {&d, &e};
288 verify_items (list1, expected);
290 expected = {&a, &b, &c};
291 verify_items (list2, expected);
295 /* Other is empty. */
296 item_type a ("a"), b ("b"), c ("c");
297 ListType list1;
298 ListType list2;
299 std::vector<const item_type *> expected;
301 list1.push_back (a);
302 list1.push_back (b);
303 list1.push_back (c);
305 std::swap (list1, list2);
307 expected = {};
308 verify_items (list1, expected);
310 expected = {&a, &b, &c};
311 verify_items (list2, expected);
315 /* *this is empty. */
316 item_type a ("a"), b ("b"), c ("c");
317 ListType list1;
318 ListType list2;
319 std::vector<const item_type *> expected;
321 list2.push_back (a);
322 list2.push_back (b);
323 list2.push_back (c);
325 std::swap (list1, list2);
327 expected = {&a, &b, &c};
328 verify_items (list1, expected);
330 expected = {};
331 verify_items (list2, expected);
335 /* Both lists empty. */
336 ListType list1;
337 ListType list2;
338 std::vector<const item_type *> expected;
340 std::swap (list1, list2);
342 expected = {};
343 verify_items (list1, expected);
345 expected = {};
346 verify_items (list2, expected);
350 /* Swap one element twice. */
351 item_type a ("a");
352 ListType list1;
353 ListType list2;
354 std::vector<const item_type *> expected;
356 list1.push_back (a);
358 std::swap (list1, list2);
360 expected = {};
361 verify_items (list1, expected);
363 expected = {&a};
364 verify_items (list2, expected);
366 std::swap (list1, list2);
368 expected = {&a};
369 verify_items (list1, expected);
371 expected = {};
372 verify_items (list2, expected);
376 static void
377 test_front_back ()
379 item_type a ("a"), b ("b"), c ("c");
380 ListType list;
381 const ListType &clist = list;
383 list.push_back (a);
384 list.push_back (b);
385 list.push_back (c);
387 gdb_assert (&list.front () == &a);
388 gdb_assert (&clist.front () == &a);
389 gdb_assert (&list.back () == &c);
390 gdb_assert (&clist.back () == &c);
393 static void
394 test_push_front ()
396 item_type a ("a"), b ("b"), c ("c");
397 ListType list;
398 std::vector<const item_type *> expected;
400 expected = {};
401 verify_items (list, expected);
403 list.push_front (a);
404 expected = {&a};
405 verify_items (list, expected);
407 list.push_front (b);
408 expected = {&b, &a};
409 verify_items (list, expected);
411 list.push_front (c);
412 expected = {&c, &b, &a};
413 verify_items (list, expected);
416 static void
417 test_push_back ()
419 item_type a ("a"), b ("b"), c ("c");
420 ListType list;
421 std::vector<const item_type *> expected;
423 expected = {};
424 verify_items (list, expected);
426 list.push_back (a);
427 expected = {&a};
428 verify_items (list, expected);
430 list.push_back (b);
431 expected = {&a, &b};
432 verify_items (list, expected);
434 list.push_back (c);
435 expected = {&a, &b, &c};
436 verify_items (list, expected);
439 static void
440 test_insert ()
442 std::vector<const item_type *> expected;
445 /* Insert at beginning. */
446 item_type a ("a"), b ("b"), c ("c");
447 ListType list;
450 list.insert (list.begin (), a);
451 expected = {&a};
452 verify_items (list, expected);
454 list.insert (list.begin (), b);
455 expected = {&b, &a};
456 verify_items (list, expected);
458 list.insert (list.begin (), c);
459 expected = {&c, &b, &a};
460 verify_items (list, expected);
464 /* Insert at end. */
465 item_type a ("a"), b ("b"), c ("c");
466 ListType list;
469 list.insert (list.end (), a);
470 expected = {&a};
471 verify_items (list, expected);
473 list.insert (list.end (), b);
474 expected = {&a, &b};
475 verify_items (list, expected);
477 list.insert (list.end (), c);
478 expected = {&a, &b, &c};
479 verify_items (list, expected);
483 /* Insert in the middle. */
484 item_type a ("a"), b ("b"), c ("c");
485 ListType list;
487 list.push_back (a);
488 list.push_back (b);
490 list.insert (list.iterator_to (b), c);
491 expected = {&a, &c, &b};
492 verify_items (list, expected);
496 /* Insert in empty list. */
497 item_type a ("a");
498 ListType list;
500 list.insert (list.end (), a);
501 expected = {&a};
502 verify_items (list, expected);
506 static void
507 test_splice ()
510 /* Two non-empty lists. */
511 item_type a ("a"), b ("b"), c ("c"), d ("d"), e ("e");
512 ListType list1;
513 ListType list2;
514 std::vector<const item_type *> expected;
516 list1.push_back (a);
517 list1.push_back (b);
518 list1.push_back (c);
520 list2.push_back (d);
521 list2.push_back (e);
523 list1.splice (std::move (list2));
525 expected = {&a, &b, &c, &d, &e};
526 verify_items (list1, expected);
528 expected = {};
529 verify_items (list2, expected);
533 /* Receiving list empty. */
534 item_type a ("a"), b ("b"), c ("c");
535 ListType list1;
536 ListType list2;
537 std::vector<const item_type *> expected;
539 list2.push_back (a);
540 list2.push_back (b);
541 list2.push_back (c);
543 list1.splice (std::move (list2));
545 expected = {&a, &b, &c};
546 verify_items (list1, expected);
548 expected = {};
549 verify_items (list2, expected);
553 /* Giving list empty. */
554 item_type a ("a"), b ("b"), c ("c");
555 ListType list1;
556 ListType list2;
557 std::vector<const item_type *> expected;
559 list1.push_back (a);
560 list1.push_back (b);
561 list1.push_back (c);
563 list1.splice (std::move (list2));
565 expected = {&a, &b, &c};
566 verify_items (list1, expected);
568 expected = {};
569 verify_items (list2, expected);
573 /* Both lists empty. */
574 item_type a ("a"), b ("b"), c ("c");
575 ListType list1;
576 ListType list2;
577 std::vector<const item_type *> expected;
579 list1.splice (std::move (list2));
581 expected = {};
582 verify_items (list1, expected);
584 expected = {};
585 verify_items (list2, expected);
589 static void
590 test_pop_front ()
592 item_type a ("a"), b ("b"), c ("c");
593 ListType list;
594 std::vector<const item_type *> expected;
596 list.push_back (a);
597 list.push_back (b);
598 list.push_back (c);
600 list.pop_front ();
601 expected = {&b, &c};
602 verify_items (list, expected);
604 list.pop_front ();
605 expected = {&c};
606 verify_items (list, expected);
608 list.pop_front ();
609 expected = {};
610 verify_items (list, expected);
613 static void
614 test_pop_back ()
616 item_type a ("a"), b ("b"), c ("c");
617 ListType list;
618 std::vector<const item_type *> expected;
620 list.push_back (a);
621 list.push_back (b);
622 list.push_back (c);
624 list.pop_back();
625 expected = {&a, &b};
626 verify_items (list, expected);
628 list.pop_back ();
629 expected = {&a};
630 verify_items (list, expected);
632 list.pop_back ();
633 expected = {};
634 verify_items (list, expected);
637 static void
638 test_erase ()
640 item_type a ("a"), b ("b"), c ("c");
641 ListType list;
642 std::vector<const item_type *> expected;
644 list.push_back (a);
645 list.push_back (b);
646 list.push_back (c);
648 list.erase (list.iterator_to (b));
649 expected = {&a, &c};
650 verify_items (list, expected);
652 list.erase (list.iterator_to (c));
653 expected = {&a};
654 verify_items (list, expected);
656 list.erase (list.iterator_to (a));
657 expected = {};
658 verify_items (list, expected);
661 static void
662 test_clear ()
664 item_type a ("a"), b ("b"), c ("c");
665 ListType list;
666 std::vector<const item_type *> expected;
668 list.push_back (a);
669 list.push_back (b);
670 list.push_back (c);
672 list.clear ();
673 expected = {};
674 verify_items (list, expected);
676 /* Verify idempotency. */
677 list.clear ();
678 expected = {};
679 verify_items (list, expected);
682 static void
683 test_clear_and_dispose ()
685 item_type a ("a"), b ("b"), c ("c");
686 ListType list;
687 std::vector<const item_type *> expected;
688 std::unordered_set<const item_type *> disposer_seen;
689 int disposer_calls = 0;
691 list.push_back (a);
692 list.push_back (b);
693 list.push_back (c);
695 auto disposer = [&] (const item_type *item)
697 disposer_seen.insert (item);
698 disposer_calls++;
700 list.clear_and_dispose (disposer);
702 expected = {};
703 verify_items (list, expected);
704 gdb_assert (disposer_calls == 3);
705 gdb_assert (disposer_seen.find (&a) != disposer_seen.end ());
706 gdb_assert (disposer_seen.find (&b) != disposer_seen.end ());
707 gdb_assert (disposer_seen.find (&c) != disposer_seen.end ());
709 /* Verify idempotency. */
710 list.clear_and_dispose (disposer);
711 gdb_assert (disposer_calls == 3);
714 static void
715 test_empty ()
717 item_type a ("a");
718 ListType list;
720 gdb_assert (list.empty ());
721 list.push_back (a);
722 gdb_assert (!list.empty ());
723 list.erase (list.iterator_to (a));
724 gdb_assert (list.empty ());
727 static void
728 test_begin_end ()
730 item_type a ("a"), b ("b"), c ("c");
731 ListType list;
732 const ListType &clist = list;
734 list.push_back (a);
735 list.push_back (b);
736 list.push_back (c);
738 gdb_assert (&*list.begin () == &a);
739 gdb_assert (&*list.cbegin () == &a);
740 gdb_assert (&*clist.begin () == &a);
741 gdb_assert (&*list.rbegin () == &c);
742 gdb_assert (&*list.crbegin () == &c);
743 gdb_assert (&*clist.rbegin () == &c);
745 /* At least check that they compile. */
746 list.end ();
747 list.cend ();
748 clist.end ();
749 list.rend ();
750 list.crend ();
751 clist.end ();
755 template <typename ListType>
756 static void
757 test_intrusive_list_1 ()
759 intrusive_list_test<ListType> tests;
761 tests.test_move_constructor ();
762 tests.test_move_assignment ();
763 tests.test_swap ();
764 tests.test_front_back ();
765 tests.test_push_front ();
766 tests.test_push_back ();
767 tests.test_insert ();
768 tests.test_splice ();
769 tests.test_pop_front ();
770 tests.test_pop_back ();
771 tests.test_erase ();
772 tests.test_clear ();
773 tests.test_clear_and_dispose ();
774 tests.test_empty ();
775 tests.test_begin_end ();
778 static void
779 test_node_is_linked ()
782 item_with_base a ("a");
783 item_with_base_list list;
785 gdb_assert (!a.is_linked ());
786 list.push_back (a);
787 gdb_assert (a.is_linked ());
788 list.pop_back ();
789 gdb_assert (!a.is_linked ());
793 item_with_member a ("a");
794 item_with_member_list list;
796 gdb_assert (!a.node.is_linked ());
797 list.push_back (a);
798 gdb_assert (a.node.is_linked ());
799 list.pop_back ();
800 gdb_assert (!a.node.is_linked ());
804 static void
805 test_intrusive_list ()
807 test_intrusive_list_1<item_with_base_list> ();
808 test_intrusive_list_1<item_with_member_list> ();
809 test_node_is_linked ();
812 void _initialize_intrusive_list_selftests ();
813 void
814 _initialize_intrusive_list_selftests ()
816 selftests::register_test
817 ("intrusive_list", test_intrusive_list);