Aleph-w 3.0
A C++ Library for Data Structures and Algorithms
Loading...
Searching...
No Matches
dlink_test.cc
Go to the documentation of this file.
1
2/*
3 Aleph_w
4
5 Data structures & Algorithms
6 version 2.0.0b
7 https://github.com/lrleon/Aleph-w
8
9 This file is part of Aleph-w library
10
11 Copyright (c) 2002-2026 Leandro Rabindranath Leon
12
13 Permission is hereby granted, free of charge, to any person obtaining a copy
14 of this software and associated documentation files (the "Software"), to deal
15 in the Software without restriction, including without limitation the rights
16 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
17 copies of the Software, and to permit persons to whom the Software is
18 furnished to do so, subject to the following conditions:
19
20 The above copyright notice and this permission notice shall be included in all
21 copies or substantial portions of the Software.
22
23 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
24 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
25 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
26 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
27 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
28 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
29 SOFTWARE.
30*/
31
32
41#include <gtest/gtest.h>
42#include <vector>
43#include <algorithm>
44#include <random>
45#include <dlink.H>
46
47using namespace std;
48using namespace testing;
49using namespace Aleph;
50
51// =============================================================================
52// Basic Construction and Initialization Tests
53// =============================================================================
54
55class DlinkBasicTest : public Test
56{
57protected:
59};
60
62{
63 EXPECT_TRUE(list.is_empty());
64 EXPECT_EQ(list.get_next(), &list);
65 EXPECT_EQ(list.get_prev(), &list);
66 EXPECT_TRUE(list.is_unitarian_or_empty());
67 EXPECT_FALSE(list.is_unitarian());
68}
69
71{
72 Dlink copy(list);
73 EXPECT_TRUE(copy.is_empty());
74 EXPECT_EQ(copy.get_next(), &copy);
75 EXPECT_EQ(copy.get_prev(), &copy);
76}
77
79{
80 Dlink moved(std::move(list));
82 EXPECT_TRUE(list.is_empty());
83}
84
86{
87 Dlink node;
88 node.reset();
89 EXPECT_TRUE(node.is_empty());
90 EXPECT_EQ(node.get_next(), &node);
91 EXPECT_EQ(node.get_prev(), &node);
92}
93
95{
96 Dlink node;
97 node.init();
98 EXPECT_TRUE(node.is_empty());
99 EXPECT_EQ(node.get_next(), &node);
100 EXPECT_EQ(node.get_prev(), &node);
101}
102
103// =============================================================================
104// Stack Operations Tests (including bug fix verification)
105// =============================================================================
106
107class DlinkStackTest : public Test
108{
109protected:
112};
113
115{
116 // This tests the bug fix: message should say "is empty" not "is not empty"
117 EXPECT_TRUE(stack.is_empty());
118 try
119 {
120 stack.top();
121 FAIL() << "Expected underflow_error";
122 }
123 catch (const std::underflow_error &e)
124 {
125 std::string msg = e.what();
126 EXPECT_NE(msg.find("empty"), std::string::npos)
127 << "Error message should mention 'empty': " << msg;
128 EXPECT_EQ(msg.find("not empty"), std::string::npos)
129 << "Error message should NOT say 'not empty': " << msg;
130 }
131}
132
134{
135 // This tests the bug fix: message should say "is empty" not "is not empty"
136 EXPECT_TRUE(stack.is_empty());
137 try
138 {
139 stack.pop();
140 FAIL() << "Expected underflow_error";
141 }
142 catch (const std::underflow_error &e)
143 {
144 std::string msg = e.what();
145 EXPECT_NE(msg.find("empty"), std::string::npos)
146 << "Error message should mention 'empty': " << msg;
147 EXPECT_EQ(msg.find("not empty"), std::string::npos)
148 << "Error message should NOT say 'not empty': " << msg;
149 }
150}
151
153{
154 stack.push(&n1);
155 EXPECT_EQ(stack.top(), &n1);
156 EXPECT_FALSE(stack.is_empty());
157 EXPECT_TRUE(stack.is_unitarian());
158
159 stack.push(&n2);
160 EXPECT_EQ(stack.top(), &n2);
161 EXPECT_FALSE(stack.is_unitarian());
162
163 stack.push(&n3);
164 EXPECT_EQ(stack.top(), &n3);
165
166 EXPECT_EQ(stack.pop(), &n3);
167 EXPECT_EQ(stack.top(), &n2);
168
169 EXPECT_EQ(stack.pop(), &n2);
170 EXPECT_EQ(stack.top(), &n1);
171
172 EXPECT_EQ(stack.pop(), &n1);
173 EXPECT_TRUE(stack.is_empty());
174}
175
177{
178 stack.push(&n1);
179 EXPECT_EQ(stack.pop(), &n1);
180 EXPECT_TRUE(stack.is_empty());
181
182 stack.push(&n2);
183 stack.push(&n3);
184 EXPECT_EQ(stack.pop(), &n3);
185
186 stack.push(&n4);
187 EXPECT_EQ(stack.pop(), &n4);
188 EXPECT_EQ(stack.pop(), &n2);
189 EXPECT_TRUE(stack.is_empty());
190}
191
192// =============================================================================
193// Insert and Append Operations Tests
194// =============================================================================
195
196class DlinkInsertAppendTest : public Test
197{
198protected:
201
202 void SetUp() override
203 {
204 nodes.resize(10);
205 }
206};
207
209{
210 list.insert(&nodes[0]);
211 EXPECT_FALSE(list.is_empty());
212 EXPECT_TRUE(list.is_unitarian());
213 EXPECT_EQ(list.get_first(), &nodes[0]);
214 EXPECT_EQ(list.get_last(), &nodes[0]);
215}
216
218{
219 list.append(&nodes[0]);
220 EXPECT_FALSE(list.is_empty());
221 EXPECT_TRUE(list.is_unitarian());
222 EXPECT_EQ(list.get_first(), &nodes[0]);
223 EXPECT_EQ(list.get_last(), &nodes[0]);
224}
225
227{
228 // Insert in reverse order: 0, 1, 2, 3, 4
229 // Result should be: 4, 3, 2, 1, 0
230 for (size_t i = 0; i < 5; ++i)
231 list.insert(&nodes[i]);
232
233 Dlink::Iterator it(list);
234 for (int i = 4; i >= 0; --i, it.next())
235 EXPECT_EQ(it.get_curr(), &nodes[i]);
236}
237
239{
240 // Append in order: 0, 1, 2, 3, 4
241 // Result should be: 0, 1, 2, 3, 4
242 for (size_t i = 0; i < 5; ++i)
243 list.append(&nodes[i]);
244
245 Dlink::Iterator it(list);
246 for (size_t i = 0; i < 5; ++i, it.next())
247 EXPECT_EQ(it.get_curr(), &nodes[i]);
248}
249
251{
252 list.append(&nodes[2]); // list: 2
253 list.insert(&nodes[1]); // list: 1, 2
254 list.append(&nodes[3]); // list: 1, 2, 3
255 list.insert(&nodes[0]); // list: 0, 1, 2, 3
256
257 Dlink::Iterator it(list);
258 EXPECT_EQ(it.get_curr(), &nodes[0]);
259 it.next();
260 EXPECT_EQ(it.get_curr(), &nodes[1]);
261 it.next();
262 EXPECT_EQ(it.get_curr(), &nodes[2]);
263 it.next();
264 EXPECT_EQ(it.get_curr(), &nodes[3]);
265}
266
267// =============================================================================
268// Swap Operations Tests
269// =============================================================================
270
271class DlinkSwapTest : public Test
272{
273protected:
276};
277
279{
280 list1.swap(&list2);
281 EXPECT_TRUE(list1.is_empty());
282 EXPECT_TRUE(list2.is_empty());
283}
284
286{
287 list1.append(&n1);
288 list1.append(&n2);
289 list1.append(&n3);
290
291 list1.swap(&list2);
292
293 EXPECT_TRUE(list1.is_empty());
294 EXPECT_FALSE(list2.is_empty());
295 EXPECT_EQ(list2.get_first(), &n1);
296 EXPECT_EQ(list2.get_last(), &n3);
297}
298
300{
301 list2.append(&n1);
302 list2.append(&n2);
303
304 list1.swap(&list2);
305
306 EXPECT_FALSE(list1.is_empty());
307 EXPECT_TRUE(list2.is_empty());
308 EXPECT_EQ(list1.get_first(), &n1);
309 EXPECT_EQ(list1.get_last(), &n2);
310}
311
313{
314 list1.append(&n1);
315 list1.append(&n2);
316 list1.append(&n3);
317
318 list2.append(&n4);
319 list2.append(&n5);
320 list2.append(&n6);
321
322 list1.swap(&list2);
323
324 EXPECT_EQ(list1.get_first(), &n4);
325 EXPECT_EQ(list1.get_last(), &n6);
326 EXPECT_EQ(list2.get_first(), &n1);
327 EXPECT_EQ(list2.get_last(), &n3);
328}
329
331{
332 list1.append(&n1);
333 list2.append(&n2);
334
335 list1.swap(list2);
336
337 EXPECT_EQ(list1.get_first(), &n2);
338 EXPECT_EQ(list2.get_first(), &n1);
339}
340
341// =============================================================================
342// List Operations Tests (concat, split, cut, insert_list, append_list)
343// =============================================================================
344
345class DlinkListOperationsTest : public Test
346{
347protected:
350
351 void SetUp() override
352 {
353 nodes.resize(20);
354 }
355
356 void populateList(Dlink &l, size_t start, size_t count)
357 {
358 for (size_t i = start; i < start + count; ++i)
359 l.append(&nodes[i]);
360 }
361};
362
364{
365 list.concat_list(&aux);
366 EXPECT_TRUE(list.is_empty());
367 EXPECT_TRUE(aux.is_empty());
368}
369
371{
372 populateList(aux, 0, 3);
373
374 list.concat_list(&aux);
375
376 EXPECT_FALSE(list.is_empty());
377 EXPECT_TRUE(aux.is_empty());
378 EXPECT_EQ(list.get_first(), &nodes[0]);
379 EXPECT_EQ(list.get_last(), &nodes[2]);
380}
381
383{
384 populateList(list, 0, 3);
385
386 list.concat_list(&aux);
387
388 EXPECT_FALSE(list.is_empty());
389 EXPECT_TRUE(aux.is_empty());
390 EXPECT_EQ(list.get_first(), &nodes[0]);
391 EXPECT_EQ(list.get_last(), &nodes[2]);
392}
393
395{
396 populateList(list, 0, 3); // list: 0, 1, 2
397 populateList(aux, 3, 3); // aux: 3, 4, 5
398
399 list.concat_list(&aux);
400
401 EXPECT_TRUE(aux.is_empty());
402 EXPECT_EQ(list.get_first(), &nodes[0]);
403 EXPECT_EQ(list.get_last(), &nodes[5]);
404
405 // Verify order
406 Dlink::Iterator it(list);
407 for (size_t i = 0; i < 6; ++i, it.next())
408 EXPECT_EQ(it.get_curr(), &nodes[i]);
409}
410
412{
413 populateList(list, 0, 3);
414
415 nodes[1].insert_list(&aux); // Insert empty list after nodes[1]
416
417 // List should be unchanged
418 EXPECT_EQ(list.get_first(), &nodes[0]);
419 EXPECT_EQ(list.get_last(), &nodes[2]);
420}
421
423{
424 populateList(list, 0, 3); // list: 0, 1, 2
425 populateList(aux, 10, 2); // aux: 10, 11
426
427 nodes[0].insert_list(&aux); // Insert after nodes[0]
428 // Expected: 0, 10, 11, 1, 2
429
430 EXPECT_TRUE(aux.is_empty());
431 EXPECT_EQ(list.get_first(), &nodes[0]);
432 EXPECT_EQ(list.get_last(), &nodes[2]);
433
434 Dlink::Iterator it(list);
435 EXPECT_EQ(it.get_curr(), &nodes[0]);
436 it.next();
437 EXPECT_EQ(it.get_curr(), &nodes[10]);
438 it.next();
439 EXPECT_EQ(it.get_curr(), &nodes[11]);
440 it.next();
441 EXPECT_EQ(it.get_curr(), &nodes[1]);
442 it.next();
443 EXPECT_EQ(it.get_curr(), &nodes[2]);
444}
445
447{
448 populateList(list, 0, 3);
449
450 nodes[1].append_list(&aux); // Append empty list before nodes[1]
451
452 // List should be unchanged
453 EXPECT_EQ(list.get_first(), &nodes[0]);
454 EXPECT_EQ(list.get_last(), &nodes[2]);
455}
456
458{
459 Dlink l, r;
460 size_t count = list.split_list(l, r);
461
462 EXPECT_EQ(count, 0);
465}
466
468{
469 list.append(&nodes[0]);
470
471 Dlink l, r;
472 size_t count = list.split_list(l, r);
473
474 EXPECT_EQ(count, 1);
475 EXPECT_TRUE(list.is_empty());
476 // One element goes to l or r
477 EXPECT_TRUE(!l.is_empty() || !r.is_empty());
478}
479
481{
482 populateList(list, 0, 6); // list: 0, 1, 2, 3, 4, 5
483
484 Dlink l, r;
485 size_t count = list.split_list(l, r);
486
487 EXPECT_EQ(count, 6);
488 EXPECT_TRUE(list.is_empty());
491}
492
494{
495 populateList(list, 0, 5); // list: 0, 1, 2, 3, 4
496
497 Dlink l, r;
498 size_t count = list.split_list(l, r);
499
500 EXPECT_EQ(count, 5);
501 EXPECT_TRUE(list.is_empty());
502}
503
505{
506 populateList(list, 0, 5); // list: 0, 1, 2, 3, 4
507
508 Dlink cut = list.cut_list(&nodes[0]);
509
510 EXPECT_TRUE(list.is_empty());
511 EXPECT_EQ(cut.get_first(), &nodes[0]);
512 EXPECT_EQ(cut.get_last(), &nodes[4]);
513}
514
516{
517 populateList(list, 0, 5); // list: 0, 1, 2, 3, 4
518
519 Dlink cut = list.cut_list(&nodes[4]);
520
521 EXPECT_FALSE(list.is_empty());
522 EXPECT_EQ(list.get_first(), &nodes[0]);
523 EXPECT_EQ(list.get_last(), &nodes[3]);
525 EXPECT_EQ(cut.get_first(), &nodes[4]);
526}
527
529{
530 populateList(list, 0, 5); // list: 0, 1, 2, 3, 4
531
532 Dlink cut = list.cut_list(&nodes[2]);
533
534 EXPECT_EQ(list.get_first(), &nodes[0]);
535 EXPECT_EQ(list.get_last(), &nodes[1]);
536 EXPECT_EQ(cut.get_first(), &nodes[2]);
537 EXPECT_EQ(cut.get_last(), &nodes[4]);
538}
539
540// =============================================================================
541// Reverse Operations Tests
542// =============================================================================
543
544class DlinkReverseTest : public Test
545{
546protected:
549
550 void SetUp() override
551 {
552 nodes.resize(10);
553 }
554};
555
557{
558 size_t count = list.reverse_list();
559 EXPECT_EQ(count, 0);
560 EXPECT_TRUE(list.is_empty());
561}
562
564{
565 list.append(&nodes[0]);
566 size_t count = list.reverse_list();
567 EXPECT_EQ(count, 1);
568 EXPECT_EQ(list.get_first(), &nodes[0]);
569}
570
572{
573 list.append(&nodes[0]);
574 list.append(&nodes[1]);
575
576 list.reverse_list();
577
578 EXPECT_EQ(list.get_first(), &nodes[1]);
579 EXPECT_EQ(list.get_last(), &nodes[0]);
580}
581
583{
584 for (size_t i = 0; i < 5; ++i)
585 list.append(&nodes[i]); // list: 0, 1, 2, 3, 4
586
587 size_t count = list.reverse_list();
588
589 EXPECT_EQ(count, 5);
590 EXPECT_EQ(list.get_first(), &nodes[4]);
591 EXPECT_EQ(list.get_last(), &nodes[0]);
592
593 // Verify order: 4, 3, 2, 1, 0
594 Dlink::Iterator it(list);
595 for (int i = 4; i >= 0; --i, it.next())
596 EXPECT_EQ(it.get_curr(), &nodes[i]);
597}
598
600{
601 for (size_t i = 0; i < 5; ++i)
602 list.append(&nodes[i]);
603
604 list.reverse_list();
605 list.reverse_list();
606
607 Dlink::Iterator it(list);
608 for (size_t i = 0; i < 5; ++i, it.next())
609 EXPECT_EQ(it.get_curr(), &nodes[i]);
610}
611
612// =============================================================================
613// Rotation Tests
614// =============================================================================
615
616class DlinkRotationTest : public Test
617{
618protected:
621
622 void SetUp() override
623 {
624 nodes.resize(10);
625 for (size_t i = 0; i < 5; ++i)
626 list.append(&nodes[i]); // list: 0, 1, 2, 3, 4
627 }
628};
629
631{
632 list.rotate_left(0);
633
634 Dlink::Iterator it(list);
635 for (size_t i = 0; i < 5; ++i, it.next())
636 EXPECT_EQ(it.get_curr(), &nodes[i]);
637}
638
640{
641 list.rotate_left(1); // Expected: 1, 2, 3, 4, 0
642
643 Dlink::Iterator it(list);
644 EXPECT_EQ(it.get_curr(), &nodes[1]);
645 it.next();
646 EXPECT_EQ(it.get_curr(), &nodes[2]);
647 it.next();
648 EXPECT_EQ(it.get_curr(), &nodes[3]);
649 it.next();
650 EXPECT_EQ(it.get_curr(), &nodes[4]);
651 it.next();
652 EXPECT_EQ(it.get_curr(), &nodes[0]);
653}
654
656{
657 list.rotate_left(5); // Full rotation should restore original order
658
659 Dlink::Iterator it(list);
660 for (size_t i = 0; i < 5; ++i, it.next())
661 EXPECT_EQ(it.get_curr(), &nodes[i]);
662}
663
665{
666 list.rotate_right(1); // Expected: 4, 0, 1, 2, 3
667
668 Dlink::Iterator it(list);
669 EXPECT_EQ(it.get_curr(), &nodes[4]);
670 it.next();
671 EXPECT_EQ(it.get_curr(), &nodes[0]);
672}
673
675{
676 Dlink empty;
677 EXPECT_THROW(empty.rotate_left(1), std::domain_error);
678 EXPECT_THROW(empty.rotate_right(1), std::domain_error);
681}
682
683// =============================================================================
684// Iterator Tests
685// =============================================================================
686
687class DlinkIteratorTest : public Test
688{
689protected:
692
693 void SetUp() override
694 {
695 nodes.resize(10);
696 }
697};
698
700{
701 Dlink::Iterator it(list);
703 EXPECT_THROW(it.get_curr(), std::overflow_error);
704 EXPECT_THROW(it.next(), std::overflow_error);
705 EXPECT_THROW(it.prev(), std::underflow_error);
706}
707
709{
710 for (size_t i = 0; i < 5; ++i)
711 list.append(&nodes[i]);
712
713 size_t count = 0;
714 for (Dlink::Iterator it(list); it.has_curr(); it.next(), ++count)
715 EXPECT_EQ(it.get_curr(), &nodes[count]);
716
717 EXPECT_EQ(count, 5);
718}
719
721{
722 for (size_t i = 0; i < 5; ++i)
723 list.append(&nodes[i]);
724
725 Dlink::Iterator it(list);
726 it.reset_last();
727
728 int count = 4;
729 while (it.has_curr())
730 {
731 EXPECT_EQ(it.get_curr(), &nodes[count]);
732 it.prev();
733 --count;
734 }
735 EXPECT_EQ(count, -1);
736}
737
739{
740 for (size_t i = 0; i < 5; ++i)
741 list.append(&nodes[i]);
742
743 Dlink::Iterator it(list);
744 while (it.has_curr())
745 it.del();
746
747 EXPECT_TRUE(list.is_empty());
748}
749
751{
752 for (size_t i = 0; i < 5; ++i)
753 list.append(&nodes[i]); // list: 0, 1, 2, 3, 4
754
755 Dlink::Iterator it(list);
756 it.next();
757 it.next(); // Now at nodes[2]
758
759 Dlink *deleted = it.del();
760 EXPECT_EQ(deleted, &nodes[2]);
761
762 // Iterator should now be at nodes[3]
763 EXPECT_TRUE(it.has_curr());
764 EXPECT_EQ(it.get_curr(), &nodes[3]);
765}
766
768{
769 for (size_t i = 0; i < 3; ++i)
770 list.append(&nodes[i]);
771
772 Dlink::Iterator it(list);
774 EXPECT_FALSE(it.is_last());
775
776 it.next();
778 EXPECT_FALSE(it.is_last());
779
780 it.next();
782 EXPECT_TRUE(it.is_last());
783}
784
786{
787 for (size_t i = 0; i < 3; ++i)
788 list.append(&nodes[i]);
789
790 Dlink::Iterator it1(list);
791 Dlink::Iterator it2(list);
792
793 EXPECT_TRUE(it1 == it2);
794 EXPECT_FALSE(it1 != it2);
795
796 it1.next();
797 EXPECT_FALSE(it1 == it2);
798 EXPECT_TRUE(it1 != it2);
799}
800
801// =============================================================================
802// Check Consistency Tests
803// =============================================================================
804
806{
807 Dlink list;
808 EXPECT_TRUE(list.check());
809}
810
812{
813 Dlink list;
815
816 for (size_t i = 0; i < 10; ++i)
817 list.append(&nodes[i]);
818
819 EXPECT_TRUE(list.check());
820
821 list.reverse_list();
822 EXPECT_TRUE(list.check());
823
824 list.rotate_left(3);
825 EXPECT_TRUE(list.check());
826
827 Dlink l, r;
828 list.split_list(l, r);
829 EXPECT_TRUE(l.check());
830 EXPECT_TRUE(r.check());
831}
832
833// =============================================================================
834// Stress Tests
835// =============================================================================
836
838{
839 constexpr size_t N = 10000;
840 Dlink list;
842
843 // Build large list
844 for (size_t i = 0; i < N; ++i)
845 list.append(&nodes[i]);
846
847 EXPECT_TRUE(list.check());
848
849 // Reverse
850 size_t count = list.reverse_list();
851 EXPECT_EQ(count, N);
852 EXPECT_TRUE(list.check());
853
854 // Split
855 Dlink l, r;
856 list.split_list(l, r);
857 EXPECT_TRUE(list.is_empty());
858 EXPECT_TRUE(l.check());
859 EXPECT_TRUE(r.check());
860
861 // Concat back
862 l.concat_list(&r);
863 EXPECT_TRUE(l.check());
864}
865
867{
868 constexpr size_t N = 1000;
869 constexpr size_t OPS = 5000;
870
871 Dlink list;
873 vector<bool> inList(N, false);
874
875 std::mt19937 rng(42);
876 std::uniform_int_distribution<size_t> nodeDist(0, N - 1);
877 std::uniform_int_distribution<int> opDist(0, 3);
878
879 for (size_t op = 0; op < OPS; ++op)
880 {
881 int operation = opDist(rng);
882 size_t nodeIdx = nodeDist(rng);
883
884 switch (operation)
885 {
886 case 0: // Insert
887 if (!inList[nodeIdx])
888 {
889 list.insert(&nodes[nodeIdx]);
890 inList[nodeIdx] = true;
891 }
892 break;
893 case 1: // Append
894 if (!inList[nodeIdx])
895 {
896 list.append(&nodes[nodeIdx]);
897 inList[nodeIdx] = true;
898 }
899 break;
900 case 2: // Remove first
901 if (!list.is_empty())
902 {
903 Dlink *removed = list.remove_first();
904 for (size_t i = 0; i < N; ++i)
905 {
906 if (&nodes[i] == removed)
907 {
908 inList[i] = false;
909 break;
910 }
911 }
912 }
913 break;
914 case 3: // Remove last
915 if (!list.is_empty())
916 {
917 Dlink *removed = list.remove_last();
918 for (size_t i = 0; i < N; ++i)
919 {
920 if (&nodes[i] == removed)
921 {
922 inList[i] = false;
923 break;
924 }
925 }
926 }
927 break;
928 }
929 }
930
931 EXPECT_TRUE(list.check());
932}
933
934// =============================================================================
935// Move Semantics Tests
936// =============================================================================
937
939{
940 Dlink list;
941 Dlink n1, n2, n3;
942 list.append(&n1);
943 list.append(&n2);
944 list.append(&n3);
945
946 Dlink moved(std::move(list));
947
948 EXPECT_TRUE(list.is_empty());
950 EXPECT_EQ(moved.get_first(), &n1);
951 EXPECT_EQ(moved.get_last(), &n3);
952}
953
955{
956 Dlink list1, list2;
957 Dlink n1, n2, n3;
958 list1.append(&n1);
959 list1.append(&n2);
960 list1.append(&n3);
961
962 list2 = std::move(list1);
963
964 EXPECT_TRUE(list1.is_empty());
965 EXPECT_FALSE(list2.is_empty());
966 EXPECT_EQ(list2.get_first(), &n1);
967 EXPECT_EQ(list2.get_last(), &n3);
968}
969
970// =============================================================================
971// Edge Cases
972// =============================================================================
973
975{
976 Dlink list;
977 Dlink n1, n2;
978 list.append(&n1);
979 list.append(&n2);
980
981 // Self swap should work without issues
982 list.swap(&list);
983
984 EXPECT_FALSE(list.is_empty());
985 EXPECT_EQ(list.get_first(), &n1);
986 EXPECT_EQ(list.get_last(), &n2);
987}
988
990{
991 Dlink list;
992 Dlink n1;
993 list.append(&n1);
994
996
997 Dlink *removed = list.remove_first();
998 EXPECT_EQ(removed, &n1);
999 EXPECT_TRUE(list.is_empty());
1000}
1001
1003{
1004 Dlink list;
1005 Dlink n1;
1006 list.append(&n1);
1007
1008 Dlink::Iterator it(list);
1009 EXPECT_TRUE(it.has_curr());
1011 EXPECT_TRUE(it.is_last());
1012 EXPECT_EQ(it.get_curr(), &n1);
1013
1014 it.next();
1015 EXPECT_FALSE(it.has_curr());
1016}
1017
1018// =============================================================================
1019// Additional Stress and Fuzz Tests
1020// =============================================================================
1021
1023{
1024 constexpr size_t N = 50000;
1025 Dlink list;
1027
1028 // Build massive list
1029 for (size_t i = 0; i < N; ++i)
1030 list.append(&nodes[i]);
1031
1032 EXPECT_TRUE(list.check());
1033 EXPECT_EQ(list.get_first(), &nodes[0]);
1034 EXPECT_EQ(list.get_last(), &nodes[N - 1]);
1035
1036 // Verify traversal
1037 size_t count = 0;
1038 for (Dlink::Iterator it(list); it.has_curr(); it.next(), ++count)
1039 ;
1040 EXPECT_EQ(count, N);
1041
1042 // Multiple reverses
1043 for (int i = 0; i < 5; ++i)
1044 {
1045 list.reverse_list();
1046 EXPECT_TRUE(list.check());
1047 }
1048
1049 // Remove all from front
1050 while (!list.is_empty())
1051 list.remove_first();
1052
1053 EXPECT_TRUE(list.is_empty());
1054}
1055
1057{
1058 constexpr size_t N = 1000;
1059 constexpr size_t ITERATIONS = 100;
1060
1061 Dlink list;
1063
1064 for (size_t i = 0; i < N; ++i)
1065 list.append(&nodes[i]);
1066
1067 std::mt19937 rng(54321);
1068
1069 for (size_t iter = 0; iter < ITERATIONS; ++iter)
1070 {
1071 Dlink l, r;
1072 list.split_list(l, r);
1073
1074 EXPECT_TRUE(list.is_empty());
1075 EXPECT_TRUE(l.check());
1076 EXPECT_TRUE(r.check());
1077
1078 // Concat back in random order
1079 if (rng() % 2 == 0)
1080 {
1081 l.concat_list(&r);
1082 list.swap(&l);
1083 }
1084 else
1085 {
1086 r.concat_list(&l);
1087 list.swap(&r);
1088 }
1089
1090 EXPECT_TRUE(list.check());
1091 }
1092}
1093
1095{
1096 constexpr size_t N = 2000;
1097 constexpr size_t OPS = 10000;
1098
1099 Dlink list;
1101 vector<bool> inList(N, false);
1102 size_t listSize = 0;
1103
1104 std::mt19937 rng(12345);
1105 std::uniform_int_distribution<size_t> nodeDist(0, N - 1);
1106 std::uniform_int_distribution<int> opDist(0, 4);
1107
1108 for (size_t op = 0; op < OPS; ++op)
1109 {
1110 int operation = opDist(rng);
1111 size_t nodeIdx = nodeDist(rng);
1112
1113 switch (operation)
1114 {
1115 case 0: // Insert at front
1116 if (!inList[nodeIdx])
1117 {
1118 list.insert(&nodes[nodeIdx]);
1119 inList[nodeIdx] = true;
1120 ++listSize;
1121 }
1122 break;
1123 case 1: // Append at back
1124 if (!inList[nodeIdx])
1125 {
1126 list.append(&nodes[nodeIdx]);
1127 inList[nodeIdx] = true;
1128 ++listSize;
1129 }
1130 break;
1131 case 2: // Remove first
1132 if (!list.is_empty())
1133 {
1134 Dlink *removed = list.remove_first();
1135 for (size_t i = 0; i < N; ++i)
1136 {
1137 if (&nodes[i] == removed)
1138 {
1139 inList[i] = false;
1140 --listSize;
1141 break;
1142 }
1143 }
1144 }
1145 break;
1146 case 3: // Remove last
1147 if (!list.is_empty())
1148 {
1149 Dlink *removed = list.remove_last();
1150 for (size_t i = 0; i < N; ++i)
1151 {
1152 if (&nodes[i] == removed)
1153 {
1154 inList[i] = false;
1155 --listSize;
1156 break;
1157 }
1158 }
1159 }
1160 break;
1161 case 4: // Reverse
1162 if (!list.is_empty())
1163 list.reverse_list();
1164 break;
1165 }
1166
1167 // Periodic consistency check
1168 if (op % 1000 == 0)
1169 EXPECT_TRUE(list.check());
1170 }
1171
1172 EXPECT_TRUE(list.check());
1173
1174 // Verify size
1175 size_t actualSize = 0;
1176 for (Dlink::Iterator it(list); it.has_curr(); it.next())
1177 ++actualSize;
1179}
1180
1182{
1183 constexpr size_t N = 1000;
1184
1185 Dlink list;
1187
1188 for (size_t i = 0; i < N; ++i)
1189 list.append(&nodes[i]);
1190
1191 // Many rotations
1192 for (size_t i = 0; i < 100; ++i)
1193 {
1194 list.rotate_left(i % N);
1195 EXPECT_TRUE(list.check());
1196
1197 list.rotate_right((i * 7) % N);
1198 EXPECT_TRUE(list.check());
1199 }
1200
1201 // Full rotation should maintain order
1202 list.rotate_left(N);
1203 EXPECT_TRUE(list.check());
1204}
1205
1207{
1208 constexpr size_t N = 500;
1209
1210 Dlink list;
1212
1213 for (size_t i = 0; i < N; ++i)
1214 list.append(&nodes[i]);
1215
1216 // Delete every other element using iterator
1217 Dlink::Iterator it(list);
1218 size_t count = 0;
1219 while (it.has_curr())
1220 {
1221 if (count % 2 == 0)
1222 it.del();
1223 else
1224 it.next();
1225 ++count;
1226 }
1227
1228 EXPECT_TRUE(list.check());
1229
1230 // Verify remaining elements
1231 size_t remaining = 0;
1232 for (Dlink::Iterator it2(list); it2.has_curr(); it2.next())
1233 ++remaining;
1234 EXPECT_EQ(remaining, N / 2);
1235}
1236
T & append(const T &item)
Append a new item by copy.
Definition htlist.H:1562
T & get_last() const
Return the last item of the list.
Definition htlist.H:1663
T & get_first() const
Return the first item of the list.
Definition htlist.H:1675
T & push(const T &item)
Definition htlist.H:1523
constexpr bool is_empty() const noexcept
Return true if list is empty.
Definition htlist.H:523
void concat_list(HTList &l) noexcept
Definition htlist.H:663
size_t split_list(HTList &l, HTList &r) noexcept
It divides 'this' into two equal lists without modifying elements order.
Definition htlist.H:930
vector< Dlink > nodes
void SetUp() override
vector< Dlink > nodes
void SetUp() override
void populateList(Dlink &l, size_t start, size_t count)
vector< Dlink > nodes
void SetUp() override
vector< Dlink > nodes
void SetUp() override
void SetUp() override
vector< Dlink > nodes
#define FAIL(msg)
#define TEST(name)
static mt19937 rng
#define N
Definition fib.C:294
DynArray< Graph::Node * > nodes
Definition graphpic.C:406
Main namespace for Aleph-w library functions.
Definition ah-arena.H:89
Itor2 copy(Itor1 sourceBeg, const Itor1 &sourceEnd, Itor2 destBeg)
Copy elements from one range to another.
Definition ahAlgo.H:584
DynList< T > maps(const C &c, Op op)
Classic map operation.
Itor::difference_type count(const Itor &beg, const Itor &end, const T &value)
Count elements equal to a value.
Definition ahAlgo.H:127
STL namespace.
DynList< int > l