Aleph-w 3.0
A C++ Library for Data Structures and Algorithms
Loading...
Searching...
No Matches
container_edge_cases_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
47#include <gtest/gtest.h>
48#include <limits>
49#include <random>
50#include <vector>
51#include <string>
52#include <set>
53#include <deque>
54
55// Container headers
56#include <tpl_array.H>
57#include <tpl_dynArray.H>
58#include <tpl_arrayQueue.H>
59#include <tpl_arrayStack.H>
60#include <tpl_dynDlist.H>
61#include <htlist.H>
62#include <tpl_odhash.H>
63#include <tpl_olhash.H>
64#include <tpl_dynSetTree.H>
65#include <bitArray.H>
66
67using namespace std;
68using namespace Aleph;
69
70// ============================================================================
71// DynArray Edge Cases
72// ============================================================================
73
74class DynArrayEdgeCases : public ::testing::Test
75{
76protected:
78};
79
81{
82 EXPECT_EQ(arr.size(), 0);
83 EXPECT_TRUE(arr.is_empty());
84}
85
87{
88 // Empty array - no valid indices
89 EXPECT_FALSE(arr.exist(0));
90 EXPECT_FALSE(arr.exist(100));
91}
92
94{
95 arr.touch(0) = 42; // Use touch() which allocates
96 EXPECT_EQ(arr.size(), 1);
97 EXPECT_EQ(arr(0), 42); // Use () for fast read
98 EXPECT_FALSE(arr.is_empty());
99}
100
102{
103 arr.touch(100) = 999; // Use touch() for allocation
104 EXPECT_EQ(arr.size(), 101);
105 EXPECT_EQ(arr(100), 999);
106 // Note: sparse arrays may not initialize intermediate elements
107 EXPECT_TRUE(arr.exist(100));
108}
109
110// Note: DynArray allocates blocks, so exist() can return true for indices
111// in allocated blocks even if not explicitly written
113{
114 arr.touch(50) = 42;
115 EXPECT_TRUE(arr.exist(50));
116 // exist() checks if the block is allocated, not just if i < size
117 EXPECT_EQ(arr.size(), 51);
118}
119
121{
122 arr.touch(10000) = 1;
123 EXPECT_GE(arr.size(), 10001);
124 EXPECT_EQ(arr(10000), 1);
125}
126
128{
129 for (int i = 0; i < 100; ++i)
130 arr.touch(i) = i;
131
132 arr.cut(50);
133 EXPECT_EQ(arr.size(), 50);
134 EXPECT_EQ(arr(49), 49);
135 // Note: cut() may not deallocate memory, so exist() might still return true
136 // for previously allocated indices. The key invariant is size() == 50
137}
138
140{
141 arr.touch(10) = 42;
142 arr.cut(0);
143 EXPECT_EQ(arr.size(), 0);
144 EXPECT_TRUE(arr.is_empty());
145}
146
147// ============================================================================
148// ArrayQueue Edge Cases
149// ============================================================================
150
151class ArrayQueueEdgeCases : public ::testing::Test
152{
153protected:
155};
156
158{
159 EXPECT_TRUE(queue.is_empty());
160 EXPECT_EQ(queue.size(), 0);
161}
162
164{
165 EXPECT_THROW(queue.get(), std::underflow_error);
166}
167
169{
170 // Empty queue should have size 0
171 EXPECT_EQ(queue.size(), 0);
172 // After put/get cycle, should return to empty
173 queue.put(1);
174 (void)queue.get();
175 EXPECT_EQ(queue.size(), 0);
176}
177
179{
180 queue.put(42);
181 EXPECT_FALSE(queue.is_empty());
182 EXPECT_EQ(queue.size(), 1);
183 EXPECT_EQ(queue.front(), 42);
184 EXPECT_EQ(queue.rear(), 42);
185 EXPECT_EQ(queue.get(), 42);
186 EXPECT_TRUE(queue.is_empty());
187}
188
190{
191 for (int i = 0; i < 10; ++i)
192 queue.put(i);
193
194 EXPECT_EQ(queue.size(), 10);
195 EXPECT_EQ(queue.front(), 0);
196 EXPECT_EQ(queue.rear(), 9);
197}
198
200{
201 // ArrayQueue may auto-resize, so just verify it handles many elements
202 for (int i = 0; i < 20; ++i)
203 queue.put(i);
204
205 EXPECT_EQ(queue.size(), 20);
206 // Elements should be in FIFO order
207 for (int i = 0; i < 20; ++i)
208 EXPECT_EQ(queue.get(), i);
209}
210
212{
213 // Fill and partially empty
214 for (int i = 0; i < 8; ++i)
215 queue.put(i);
216
217 for (int i = 0; i < 5; ++i)
218 (void)queue.get();
219
220 // Add more to wrap around
221 for (int i = 0; i < 5; ++i)
222 queue.put(100 + i);
223
224 EXPECT_EQ(queue.size(), 8);
225 EXPECT_EQ(queue.front(), 5); // First remaining element
226}
227
228// ============================================================================
229// ArrayStack Edge Cases
230// ============================================================================
231
232class ArrayStackEdgeCases : public ::testing::Test
233{
234protected:
236};
237
239{
240 EXPECT_TRUE(stack.is_empty());
241 EXPECT_EQ(stack.size(), 0);
242}
243
245{
246 EXPECT_THROW(stack.pop(), std::underflow_error);
247}
248
250{
251 EXPECT_THROW(stack.top(), std::underflow_error);
252}
253
255{
256 stack.push(42);
257 EXPECT_FALSE(stack.is_empty());
258 EXPECT_EQ(stack.size(), 1);
259 EXPECT_EQ(stack.top(), 42);
260 EXPECT_EQ(stack.pop(), 42);
261 EXPECT_TRUE(stack.is_empty());
262}
263
265{
266 for (int i = 0; i < 10; ++i)
267 stack.push(i);
268
269 EXPECT_EQ(stack.size(), 10);
270 EXPECT_EQ(stack.top(), 9);
271}
272
274{
275 // ArrayStack may auto-resize, so just verify it handles many elements
276 for (int i = 0; i < 20; ++i)
277 stack.push(i);
278
279 EXPECT_EQ(stack.size(), 20);
280 // Elements should be in LIFO order
281 for (int i = 19; i >= 0; --i)
282 EXPECT_EQ(stack.pop(), i);
283}
284
286{
287 stack.push(1);
288 stack.push(2);
289 EXPECT_EQ(stack.pop(), 2);
290 stack.push(3);
291 EXPECT_EQ(stack.pop(), 3);
292 EXPECT_EQ(stack.pop(), 1);
293 EXPECT_TRUE(stack.is_empty());
294}
295
296// ============================================================================
297// DynDlist Edge Cases
298// ============================================================================
299
300class DynDlistEdgeCases : public ::testing::Test
301{
302protected:
304};
305
307{
308 EXPECT_TRUE(dlist.is_empty());
309 EXPECT_EQ(dlist.size(), 0);
310}
311
313{
314 EXPECT_THROW(dlist.remove_first(), std::underflow_error);
315 EXPECT_THROW(dlist.remove_last(), std::underflow_error);
316}
317
319{
320 EXPECT_THROW(dlist.get_first(), std::underflow_error);
321 EXPECT_THROW(dlist.get_last(), std::underflow_error);
322}
323
325{
326 dlist.append(42);
327 EXPECT_EQ(dlist.size(), 1);
328 EXPECT_EQ(dlist.get_first(), 42);
329 EXPECT_EQ(dlist.get_last(), 42);
330}
331
333{
334 dlist.append(42);
335 EXPECT_EQ(dlist.remove_first(), 42);
336 EXPECT_TRUE(dlist.is_empty());
337}
338
340{
341 dlist.append(42);
342 EXPECT_EQ(dlist.remove_last(), 42);
343 EXPECT_TRUE(dlist.is_empty());
344}
345
347{
348 dlist.insert(1); // Insert at front
349 dlist.append(3); // Append at back
350 dlist.insert(0); // Insert at front again
351
352 EXPECT_EQ(dlist.get_first(), 0);
353 EXPECT_EQ(dlist.get_last(), 3);
354}
355
357{
358 auto it = dlist.begin();
359 EXPECT_EQ(it, dlist.end());
360}
361
363{
364 dlist.reverse(); // Should not crash
365 EXPECT_TRUE(dlist.is_empty());
366}
367
369{
370 dlist.append(42);
371 dlist.reverse();
372 EXPECT_EQ(dlist.size(), 1);
373 EXPECT_EQ(dlist.get_first(), 42);
374}
375
377{
378 for (int i = 1; i <= 5; ++i)
379 dlist.append(i);
380
381 dlist.reverse();
382
383 EXPECT_EQ(dlist.get_first(), 5);
384 EXPECT_EQ(dlist.get_last(), 1);
385}
386
388{
390 dlist.append(std::move(other));
391 EXPECT_TRUE(dlist.is_empty());
392}
393
395{
397 other.append(1);
398 other.append(2);
399
400 dlist.append(std::move(other));
401
402 EXPECT_EQ(dlist.size(), 2);
404}
405
406// ============================================================================
407// DynList (htlist) Edge Cases
408// ============================================================================
409
410class DynListEdgeCases : public ::testing::Test
411{
412protected:
414};
415
417{
418 EXPECT_TRUE(slist.is_empty());
419 EXPECT_EQ(slist.size(), 0);
420}
421
423{
424 EXPECT_THROW(slist.remove_first(), std::underflow_error);
425}
426
428{
429 slist.insert(42);
430 EXPECT_EQ(slist.size(), 1);
431 EXPECT_EQ(slist.get_first(), 42);
432 EXPECT_EQ(slist.remove_first(), 42);
433 EXPECT_TRUE(slist.is_empty());
434}
435
437{
438 slist.append(1);
439 slist.append(2);
440 slist.append(3);
441
442 EXPECT_EQ(slist.remove_first(), 1);
443 EXPECT_EQ(slist.remove_first(), 2);
444 EXPECT_EQ(slist.remove_first(), 3);
445}
446
448{
449 slist.insert(1);
450 slist.insert(2);
451 slist.insert(3);
452
453 EXPECT_EQ(slist.remove_first(), 3);
454 EXPECT_EQ(slist.remove_first(), 2);
455 EXPECT_EQ(slist.remove_first(), 1);
456}
457
458// ============================================================================
459// ODhashTable Edge Cases
460// ============================================================================
461
462class ODhashTableEdgeCases : public ::testing::Test
463{
464protected:
465 ODhashTable<int> table; // Uses default hash and comparison
466};
467
469{
470 EXPECT_EQ(table.size(), 0);
471 EXPECT_TRUE(table.is_empty());
472}
473
475{
476 EXPECT_EQ(table.search(42), nullptr);
477 EXPECT_EQ(table.search(0), nullptr);
478 EXPECT_EQ(table.search(-1), nullptr);
479}
480
482{
483 EXPECT_THROW(table.remove(42), std::domain_error);
484}
485
487{
488 int * p = table.insert(42);
489 EXPECT_NE(p, nullptr);
490 EXPECT_EQ(*p, 42);
491 EXPECT_EQ(table.size(), 1);
492
493 int * found = table.search(42);
494 EXPECT_EQ(found, p);
495
496 EXPECT_NO_THROW(table.remove(42));
497 EXPECT_TRUE(table.is_empty());
498}
499
501{
502 EXPECT_NE(table.insert(42), nullptr);
503 int * dup = table.insert(42);
504 EXPECT_EQ(dup, nullptr);
505 EXPECT_EQ(table.size(), 1);
506}
507
509{
510 // Insert values that will likely collide
511 for (int i = 0; i < 100; ++i)
512 {
513 int * p = table.insert(i);
514 EXPECT_NE(p, nullptr) << "Failed to insert " << i;
515 }
516
517 EXPECT_EQ(table.size(), 100);
518
519 // Verify all can be found
520 for (int i = 0; i < 100; ++i)
521 EXPECT_NE(table.search(i), nullptr) << "Failed to find " << i;
522}
523
525{
526 EXPECT_NE(table.insert(1), nullptr);
527 EXPECT_NE(table.insert(2), nullptr);
528
529 EXPECT_THROW(table.remove(99), std::domain_error);
530 EXPECT_EQ(table.size(), 2);
531}
532
534{
535 EXPECT_NE(table.insert(0), nullptr);
536 EXPECT_NE(table.insert(-1), nullptr);
537 EXPECT_NE(table.insert(-100), nullptr);
538
539 EXPECT_NE(table.search(0), nullptr);
540 EXPECT_NE(table.search(-1), nullptr);
541 EXPECT_NE(table.search(-100), nullptr);
542}
543
544// ============================================================================
545// OLhashTable Edge Cases
546// ============================================================================
547
548class OLhashTableEdgeCases : public ::testing::Test
549{
550protected:
551 OLhashTable<int> table; // Uses default hash and comparison
552};
553
555{
556 EXPECT_EQ(table.size(), 0);
557 EXPECT_TRUE(table.is_empty());
558}
559
561{
562 EXPECT_EQ(table.search(42), nullptr);
563}
564
566{
567 int * p = table.insert(42);
568 EXPECT_NE(p, nullptr);
569 EXPECT_EQ(table.size(), 1);
570
571 EXPECT_NE(table.search(42), nullptr);
572 table.remove(42); // OLhashTable::remove returns void
573 EXPECT_TRUE(table.is_empty());
574}
575
577{
578 // Insert many elements to test linear probing
579 for (int i = 0; i < 50; ++i)
580 EXPECT_NE(table.insert(i), nullptr);
581
582 EXPECT_EQ(table.size(), 50);
583
584 // Verify all can be found
585 for (int i = 0; i < 50; ++i)
586 EXPECT_NE(table.search(i), nullptr);
587}
588
589// ============================================================================
590// DynSetTree Edge Cases
591// ============================================================================
592
593class DynSetTreeEdgeCases : public ::testing::Test
594{
595protected:
597};
598
600{
601 EXPECT_EQ(tree.size(), 0);
602 EXPECT_TRUE(tree.is_empty());
603}
604
606{
607 EXPECT_EQ(tree.search(42), nullptr);
608 EXPECT_FALSE(tree.has(42));
609 EXPECT_FALSE(tree.contains(42));
610}
611
616
618{
619 int * p = tree.insert(42);
620 EXPECT_NE(p, nullptr);
621 EXPECT_EQ(*p, 42);
622 EXPECT_EQ(tree.size(), 1);
623 EXPECT_TRUE(tree.has(42));
624}
625
627{
628 tree.insert(42);
629 EXPECT_EQ(tree.min(), 42);
630 EXPECT_EQ(tree.max(), 42);
631}
632
634{
635 tree.insert(42);
636 int * dup = tree.insert(42);
637 EXPECT_EQ(dup, nullptr);
638 EXPECT_EQ(tree.size(), 1);
639}
640
642{
643 for (int i = 1; i <= 100; ++i)
644 tree.insert(i);
645
646 EXPECT_EQ(tree.size(), 100);
647 EXPECT_EQ(tree.min(), 1);
648 EXPECT_EQ(tree.max(), 100);
649}
650
652{
653 for (int i = 100; i >= 1; --i)
654 tree.insert(i);
655
656 EXPECT_EQ(tree.size(), 100);
657 EXPECT_EQ(tree.min(), 1);
658 EXPECT_EQ(tree.max(), 100);
659}
660
662{
663 for (int i = 1; i <= 10; ++i)
664 tree.insert(i);
665
666 tree.remove(1);
667 EXPECT_EQ(tree.min(), 2);
668 EXPECT_EQ(tree.size(), 9);
669}
670
672{
673 for (int i = 1; i <= 10; ++i)
674 tree.insert(i);
675
676 tree.remove(10);
677 EXPECT_EQ(tree.max(), 9);
678 EXPECT_EQ(tree.size(), 9);
679}
680
682{
683 for (int i = 1; i <= 10; ++i)
684 tree.insert(i);
685
686 tree.remove(5);
687 EXPECT_FALSE(tree.has(5));
688 EXPECT_EQ(tree.size(), 9);
689}
690
692{
693 vector<int> values = {5, 3, 7, 1, 4, 6, 8};
694 for (int v : values)
695 tree.insert(v);
696
697 vector<int> result;
698 tree.for_each([&](int x) { result.push_back(x); });
699
700 EXPECT_TRUE(std::is_sorted(result.begin(), result.end()));
701}
702
704{
705 tree.insert(std::numeric_limits<int>::max());
706 tree.insert(std::numeric_limits<int>::min());
707 tree.insert(0);
708
709 EXPECT_EQ(tree.min(), std::numeric_limits<int>::min());
710 EXPECT_EQ(tree.max(), std::numeric_limits<int>::max());
711}
712
713// ============================================================================
714// BitArray Edge Cases
715// ============================================================================
716
718{
719 // BitArray requires at least 1 bit
720 BitArray bits(1);
721 EXPECT_EQ(bits.size(), 1);
722}
723
725{
726 BitArray bits(1);
727
728 EXPECT_EQ(bits.read_bit(0), 0);
729 bits.write_bit(0, 1);
730 EXPECT_EQ(bits.read_bit(0), 1);
731 bits.write_bit(0, 0);
732 EXPECT_EQ(bits.read_bit(0), 0);
733}
734
736{
737 BitArray bits(64);
738
739 for (size_t i = 0; i < 64; ++i)
740 bits.write_bit(i, 1);
741
742 for (size_t i = 0; i < 64; ++i)
743 EXPECT_EQ(bits.read_bit(i), 1);
744}
745
747{
748 BitArray bits(64);
749
750 // Should start all zeros
751 for (size_t i = 0; i < 64; ++i)
752 EXPECT_EQ(bits.read_bit(i), 0);
753}
754
756{
757 BitArray bits(100);
758
759 for (size_t i = 0; i < 100; ++i)
760 bits.write_bit(i, i % 2);
761
762 for (size_t i = 0; i < 100; ++i)
763 EXPECT_EQ(bits.read_bit(i), i % 2);
764}
765
767{
768 BitArray bits(128);
769
770 // Test at byte boundaries
771 bits.write_bit(7, 1); // End of first byte
772 bits.write_bit(8, 1); // Start of second byte
773 bits.write_bit(63, 1); // End of first long
774 bits.write_bit(64, 1); // Start of second long
775 bits.write_bit(127, 1); // Last bit
776
777 EXPECT_EQ(bits.read_bit(7), 1);
778 EXPECT_EQ(bits.read_bit(8), 1);
779 EXPECT_EQ(bits.read_bit(63), 1);
780 EXPECT_EQ(bits.read_bit(64), 1);
781 EXPECT_EQ(bits.read_bit(127), 1);
782}
783
784// ============================================================================
785// Array (fixed) Edge Cases
786// ============================================================================
787
789{
790 Array<int> arr(1);
791 arr(0) = 42;
792 EXPECT_EQ(arr(0), 42);
793 EXPECT_EQ(arr.size(), 1);
794}
795
797{
798 Array<int> arr(10);
799 arr(0) = 1;
800 arr(9) = 10;
801
802 EXPECT_EQ(arr(0), 1);
803 EXPECT_EQ(arr(9), 10);
804}
805
806// Array uses noexcept, so out of bounds is undefined behavior, not exception
807
808// ============================================================================
809// Stress Test - Mixed Operations
810// ============================================================================
811
813{
814 DynSetTree<int> tree;
815 std::mt19937 gen(12345);
816 std::uniform_int_distribution<int> val_dist(0, 10000);
817 std::uniform_int_distribution<int> op_dist(0, 2);
818
819 std::set<int> reference;
820
821 for (int i = 0; i < 10000; ++i)
822 {
823 int op = op_dist(gen);
824 int val = val_dist(gen);
825
826 if (op == 0 || op == 1) // Insert
827 {
828 auto ref_result = reference.insert(val);
829 int * tree_result = tree.insert(val);
830
831 if (ref_result.second)
832 EXPECT_NE(tree_result, nullptr);
833 else
834 EXPECT_EQ(tree_result, nullptr);
835 }
836 else if (!reference.empty()) // Remove
837 {
838 auto it = reference.begin();
839 std::advance(it, gen() % reference.size());
840 int to_remove = *it;
841
842 reference.erase(to_remove);
843 tree.remove(to_remove);
844
846 }
847 }
848
849 // Verify consistency
850 EXPECT_EQ(tree.size(), reference.size());
851 for (int val : reference)
852 EXPECT_TRUE(tree.has(val));
853}
854
856{
857 ODhashTable<int> table;
858 std::mt19937 gen(54321);
859 std::uniform_int_distribution<int> val_dist(0, 5000);
860 std::uniform_int_distribution<int> op_dist(0, 2);
861
862 std::set<int> reference;
863
864 for (int i = 0; i < 5000; ++i)
865 {
866 int op = op_dist(gen);
867 int val = val_dist(gen);
868
869 if (op == 0 || op == 1) // Insert
870 {
871 auto ref_result = reference.insert(val);
872 int * table_result = table.insert(val);
873
874 if (ref_result.second)
875 EXPECT_NE(table_result, nullptr);
876 else
877 EXPECT_EQ(table_result, nullptr);
878 }
879 else if (!reference.empty()) // Remove
880 {
881 auto it = reference.begin();
882 std::advance(it, gen() % reference.size());
883 int to_remove = *it;
884
885 reference.erase(to_remove);
886 table.remove(to_remove); // Will throw if not found, but we know it exists
887
888 EXPECT_EQ(table.search(to_remove), nullptr);
889 }
890 }
891
892 // Verify consistency
893 EXPECT_EQ(table.size(), reference.size());
894 for (int val : reference)
895 EXPECT_NE(table.search(val), nullptr);
896}
897
899{
900 DynDlist<int> dlist;
901 std::deque<int> reference;
902 std::mt19937 gen(99999);
903 std::uniform_int_distribution<int> val_dist(0, 1000);
904 std::uniform_int_distribution<int> op_dist(0, 3);
905
906 for (int i = 0; i < 5000; ++i)
907 {
908 int op = op_dist(gen);
909 int val = val_dist(gen);
910
911 switch (op)
912 {
913 case 0: // Insert at front
914 dlist.insert(val);
915 reference.push_front(val);
916 break;
917
918 case 1: // Append at back
919 dlist.append(val);
920 reference.push_back(val);
921 break;
922
923 case 2: // Remove from front (if not empty)
924 if (!reference.empty())
925 {
926 int dlist_val = dlist.remove_first();
927 int ref_val = reference.front();
928 reference.pop_front();
930 }
931 break;
932
933 case 3: // Remove from back (if not empty)
934 if (!reference.empty())
935 {
936 int dlist_val = dlist.remove_last();
937 int ref_val = reference.back();
938 reference.pop_back();
940 }
941 break;
942 }
943 }
944
945 // Verify consistency
946 EXPECT_EQ(dlist.size(), reference.size());
947}
948
950{
951 ArrayQueue<int> queue = ArrayQueue<int>(100);
952 std::mt19937 gen(77777);
953 std::uniform_int_distribution<int> val_dist(0, 1000);
954
955 // Do multiple fill/empty cycles
956 for (int cycle = 0; cycle < 100; ++cycle)
957 {
958 // Fill partially
959 int fill_count = gen() % 50 + 1;
960 for (int i = 0; i < fill_count && queue.size() < 100; ++i)
961 queue.put(val_dist(gen));
962
963 // Empty partially
964 int empty_count = gen() % queue.size() + 1;
965 for (int i = 0; i < empty_count && !queue.is_empty(); ++i)
966 (void)queue.get();
967 }
968
969 // Should not crash and queue should be valid
970 EXPECT_LE(queue.size(), 100);
971}
972
973// ============================================================================
974// Main
975// ============================================================================
976
977int main(int argc, char **argv)
978{
979 ::testing::InitGoogleTest(&argc, argv);
980 return RUN_ALL_TESTS();
981}
int main()
Space-efficient bit array implementation.
Queue implemented with a single dynamic array.
T & put(const T &item)
Copy and put an item in the queue.
T get()
Remove the oldest item of the queue and return a copy.
Stack implemented with simple dynamic array and with bounds verification.
Simple dynamic array with automatic resizing and functional operations.
Definition tpl_array.H:138
constexpr size_t size() const noexcept
Return the number of elements stored in the stack.
Definition tpl_array.H:333
Contiguous array of bits.
Definition bitArray.H:189
int read_bit(const size_t i) const
Read bit i.
Definition bitArray.H:377
void write_bit(const size_t i, const unsigned int value)
Write bit i with the value.
Definition bitArray.H:392
constexpr size_t size() const noexcept
Returns the dimension of the bit array.
Definition bitArray.H:334
Dynamic doubly linked list with O(1) size and bidirectional access.
const size_t & size() const noexcept
Return the number of elements (constant time)
T remove_last()
Remove the last item of the list; return a copy of removed item.
T & append(const T &item)
Append a copied item at the end of the list.
T & insert(const T &item)
Insert a copy of item at the beginning of the list.
T remove_first()
Remove the first item of the list; return a copy of removed item.
Dynamic singly linked list with functional programming support.
Definition htlist.H:1423
T & insert(const T &item)
Insert a new item by copy.
Definition htlist.H:1502
T & append(const T &item)
Append a new item by copy.
Definition htlist.H:1562
T & push(const T &item)
Definition htlist.H:1523
T & put(const T &item)
Definition htlist.H:1532
Dynamic set backed by balanced binary search trees with automatic memory management.
const size_t & size() const
Returns the cardinality of the set.
Key * insert(const Key &key)
Inserts a key into the dynamic set.
bool has(const Key &key) const
size_t remove(const Key &key)
Removes a key from the dynamic set.
constexpr bool is_empty() const noexcept
Return true if list is empty.
Definition htlist.H:523
size_t size() const noexcept
Count the number of elements of the list.
Definition htlist.H:1319
size_t size() const noexcept
Return the number of elements.
bool is_empty() const noexcept
Return true is the array is empty.
Open addressing hash table with double hashing collision resolution.
Definition tpl_odhash.H:180
Key * search(const Key &key) const noexcept
searches the table for the key.
Definition tpl_odhash.H:537
void remove(const Key &key)
Remove a key from the hash table.
Definition tpl_odhash.H:897
Open addressing hash table with linear probing collision resolution.
Definition tpl_olhash.H:168
constexpr size_t size() const noexcept
Returns the number of entries in the table.
Definition hashDry.H:612
Key * insert(const Key &key)
Inserts a key into the hash table (copy version).
Definition hashDry.H:203
TEST_F(DynArrayEdgeCases, EmptyArray_SizeIsZero)
#define TEST(name)
Singly linked list implementations with head-tail access.
Main namespace for Aleph-w library functions.
Definition ah-arena.H:89
DynList< T > maps(const C &c, Op op)
Classic map operation.
STL namespace.
Circular queue implementations backed by arrays.
Stack implementations backed by dynamic or fixed arrays.
Dynamic array container with automatic resizing.
Lazy and scalable dynamic array implementation.
Dynamic doubly linked list implementation.
Dynamic set implementations based on balanced binary search trees.
Open addressing hash table with double hashing.
Open addressing hash table with linear probing.