Aleph-w 3.0
A C++ Library for Data Structures and Algorithms
Loading...
Searching...
No Matches
dynskiplist_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
33
38#include <gtest/gtest.h>
39#include <gsl/gsl_rng.h>
40#include <string>
41#include <vector>
42#include <algorithm>
43#include <tpl_dynSkipList.H>
44
45using namespace Aleph;
46
47namespace {
48
49class DynSkipListTest : public ::testing::Test
50{
51protected:
53};
54
55// ============================================================================
56// Construction Tests
57// ============================================================================
58
59TEST_F(DynSkipListTest, DefaultConstruction)
60{
61 EXPECT_TRUE(sl.is_empty());
62 EXPECT_EQ(sl.size(), 0);
63}
64
65TEST_F(DynSkipListTest, InitializerListConstruction)
66{
67 DynSkipList<int> sl2({5, 2, 8, 1, 9});
68
69 EXPECT_EQ(sl2.size(), 5);
70 EXPECT_TRUE(sl2.has(1));
71 EXPECT_TRUE(sl2.has(2));
72 EXPECT_TRUE(sl2.has(5));
73 EXPECT_TRUE(sl2.has(8));
74 EXPECT_TRUE(sl2.has(9));
75}
76
77TEST_F(DynSkipListTest, ConstructorWithSeed)
78{
79 DynSkipList<int> sl2(42, 0.5);
80 sl2.insert(1);
81 sl2.insert(2);
82 EXPECT_EQ(sl2.size(), 2);
83}
84
85TEST_F(DynSkipListTest, SetSeed)
86{
87 sl.set_seed(123);
88 EXPECT_NE(sl.gsl_rng_object(), nullptr);
89}
90
91TEST_F(DynSkipListTest, GslRngObject)
92{
93 gsl_rng* rng = sl.gsl_rng_object();
94 EXPECT_NE(rng, nullptr);
95}
96
97TEST_F(DynSkipListTest, CopyConstruction)
98{
99 sl.insert(1);
100 sl.insert(2);
101 sl.insert(3);
102
104
105 EXPECT_EQ(sl2.size(), 3);
106 EXPECT_TRUE(sl2.has(1));
107 EXPECT_TRUE(sl2.has(2));
108 EXPECT_TRUE(sl2.has(3));
109
110 // Modify original, copy should be independent
111 sl.insert(4);
112 EXPECT_FALSE(sl2.has(4));
113}
114
115TEST_F(DynSkipListTest, MoveConstruction)
116{
117 sl.insert(1);
118 sl.insert(2);
119 sl.insert(3);
120
121 DynSkipList<int> sl2(std::move(sl));
122
123 EXPECT_EQ(sl2.size(), 3);
124 EXPECT_TRUE(sl2.has(1));
125 EXPECT_TRUE(sl2.has(2));
126 EXPECT_TRUE(sl2.has(3));
127
128 // Original should be empty
129 EXPECT_TRUE(sl.is_empty());
130}
131
132// ============================================================================
133// Insert Tests
134// ============================================================================
135
136TEST_F(DynSkipListTest, InsertSingle)
137{
138 int * result = sl.insert(42);
139
140 ASSERT_NE(result, nullptr);
141 EXPECT_EQ(*result, 42);
142 EXPECT_EQ(sl.size(), 1);
143 EXPECT_TRUE(sl.has(42));
144}
145
146TEST_F(DynSkipListTest, InsertDuplicate)
147{
148 sl.insert(42);
149 int * result = sl.insert(42);
150
151 EXPECT_EQ(result, nullptr); // Duplicate not inserted
152 EXPECT_EQ(sl.size(), 1);
153}
154
155TEST_F(DynSkipListTest, InsertMultiple)
156{
157 for (int i = 1; i <= 10; ++i)
158 sl.insert(i);
159
160 EXPECT_EQ(sl.size(), 10);
161
162 for (int i = 1; i <= 10; ++i)
163 EXPECT_TRUE(sl.has(i));
164}
165
166TEST_F(DynSkipListTest, InsertDescending)
167{
168 for (int i = 10; i >= 1; --i)
169 sl.insert(i);
170
171 EXPECT_EQ(sl.size(), 10);
172 EXPECT_EQ(sl.min(), 1);
173 EXPECT_EQ(sl.max(), 10);
174}
175
176TEST_F(DynSkipListTest, InsertRvalue)
177{
178 std::string str = "hello";
180
181 sl_str.insert(std::move(str));
182
183 EXPECT_EQ(sl_str.size(), 1);
184 EXPECT_TRUE(sl_str.has("hello"));
185}
186
187// ============================================================================
188// Search Tests
189// ============================================================================
190
191TEST_F(DynSkipListTest, SearchEmpty)
192{
193 EXPECT_EQ(sl.search(42), nullptr);
194}
195
196TEST_F(DynSkipListTest, SearchExisting)
197{
198 sl.insert(42);
199
200 int * result = sl.search(42);
201 ASSERT_NE(result, nullptr);
202 EXPECT_EQ(*result, 42);
203}
204
205TEST_F(DynSkipListTest, SearchNonExisting)
206{
207 sl.insert(42);
208
209 EXPECT_EQ(sl.search(41), nullptr);
210 EXPECT_EQ(sl.search(43), nullptr);
211}
212
213TEST_F(DynSkipListTest, HasContainsExist)
214{
215 sl.insert(42);
216
217 EXPECT_TRUE(sl.has(42));
218 EXPECT_TRUE(sl.contains(42));
219 EXPECT_TRUE(sl.exist(42));
220
221 EXPECT_FALSE(sl.has(43));
222 EXPECT_FALSE(sl.contains(43));
223 EXPECT_FALSE(sl.exist(43));
224}
225
226TEST_F(DynSkipListTest, Find)
227{
228 sl.insert(42);
229
230 EXPECT_EQ(sl.find(42), 42);
231
232 EXPECT_THROW((void)sl.find(43), std::domain_error);
233}
234
235// ============================================================================
236// Remove Tests
237// ============================================================================
238
239TEST_F(DynSkipListTest, RemoveExisting)
240{
241 sl.insert(1);
242 sl.insert(2);
243 sl.insert(3);
244
245 size_t removed = sl.remove(2);
246
247 EXPECT_EQ(removed, 1); // 1 element was removed
248 EXPECT_EQ(sl.size(), 2);
249 EXPECT_FALSE(sl.has(2));
250 EXPECT_TRUE(sl.has(1));
251 EXPECT_TRUE(sl.has(3));
252}
253
254TEST_F(DynSkipListTest, RemoveNonExisting)
255{
256 sl.insert(1);
257 sl.insert(2);
258
259 size_t removed = sl.remove(99);
260
261 EXPECT_EQ(removed, 0); // Nothing was removed
262 EXPECT_EQ(sl.size(), 2);
263}
264
265TEST_F(DynSkipListTest, RemoveFirst)
266{
267 sl.insert(1);
268 sl.insert(2);
269 sl.insert(3);
270
271 sl.remove(1);
272
273 EXPECT_EQ(sl.min(), 2);
274}
275
276TEST_F(DynSkipListTest, RemoveLast)
277{
278 sl.insert(1);
279 sl.insert(2);
280 sl.insert(3);
281
282 sl.remove(3);
283
284 EXPECT_EQ(sl.max(), 2);
285}
286
287TEST_F(DynSkipListTest, RemoveAll)
288{
289 for (int i = 1; i <= 5; ++i)
290 sl.insert(i);
291
292 for (int i = 1; i <= 5; ++i)
293 sl.remove(i);
294
295 EXPECT_TRUE(sl.is_empty());
296}
297
298TEST_F(DynSkipListTest, Del)
299{
300 sl.insert(42);
301
302 int deleted = sl.del(42);
303
304 EXPECT_EQ(deleted, 42);
305 EXPECT_FALSE(sl.has(42));
306
307 EXPECT_THROW(sl.del(42), std::domain_error);
308}
309
310// ============================================================================
311// Min/Max Tests
312// ============================================================================
313
314TEST_F(DynSkipListTest, MinMax)
315{
316 sl.insert(5);
317 sl.insert(2);
318 sl.insert(8);
319 sl.insert(1);
320 sl.insert(9);
321
322 EXPECT_EQ(sl.min(), 1);
323 EXPECT_EQ(sl.get_first(), 1);
324 EXPECT_EQ(sl.max(), 9);
325 EXPECT_EQ(sl.get_last(), 9);
326}
327
328TEST_F(DynSkipListTest, MinMaxEmpty)
329{
330 EXPECT_THROW((void)sl.min(), std::domain_error);
331 EXPECT_THROW((void)sl.max(), std::domain_error);
332}
333
334// ============================================================================
335// Iterator Tests
336// ============================================================================
337
338TEST_F(DynSkipListTest, IteratorEmpty)
339{
341 EXPECT_FALSE(it.has_curr());
342}
343
344TEST_F(DynSkipListTest, IteratorTraverse)
345{
346 for (int i = 1; i <= 5; ++i)
347 sl.insert(i);
348
349 int expected = 1;
350 for (DynSkipList<int>::Iterator it(sl); it.has_curr(); it.next())
351 {
352 EXPECT_EQ(it.get_curr(), expected);
353 ++expected;
354 }
356}
357
358TEST_F(DynSkipListTest, IteratorRangeBased)
359{
360 sl.insert(3);
361 sl.insert(1);
362 sl.insert(2);
363
364 std::vector<int> result;
365 for (const auto & key : sl)
366 result.push_back(key);
367
368 EXPECT_EQ(result.size(), 3);
369 EXPECT_EQ(result[0], 1);
370 EXPECT_EQ(result[1], 2);
371 EXPECT_EQ(result[2], 3);
372}
373
374TEST_F(DynSkipListTest, IteratorOperators)
375{
376 sl.insert(1);
377 sl.insert(2);
378 sl.insert(3);
379
380 auto it = sl.begin();
381 EXPECT_EQ(*it, 1);
382
383 ++it;
384 EXPECT_EQ(*it, 2);
385
386 it++;
387 EXPECT_EQ(*it, 3);
388
389 ++it;
390 EXPECT_EQ(it, sl.end());
391}
392
393// ============================================================================
394// Assignment Tests
395// ============================================================================
396
397TEST_F(DynSkipListTest, CopyAssignment)
398{
399 sl.insert(1);
400 sl.insert(2);
401
403 sl2.insert(99);
404
405 sl2 = sl;
406
407 EXPECT_EQ(sl2.size(), 2);
408 EXPECT_TRUE(sl2.has(1));
409 EXPECT_TRUE(sl2.has(2));
410 EXPECT_FALSE(sl2.has(99));
411}
412
413TEST_F(DynSkipListTest, MoveAssignment)
414{
415 sl.insert(1);
416 sl.insert(2);
417
419 sl2.insert(99);
420
421 sl2 = std::move(sl);
422
423 EXPECT_EQ(sl2.size(), 2);
424 EXPECT_TRUE(sl2.has(1));
425 EXPECT_TRUE(sl.is_empty());
426}
427
428TEST_F(DynSkipListTest, SelfAssignment)
429{
430 sl.insert(1);
431 sl.insert(2);
432
433 sl = sl;
434
435 EXPECT_EQ(sl.size(), 2);
436}
437
438// ============================================================================
439// Empty/Swap Tests
440// ============================================================================
441
442TEST_F(DynSkipListTest, Empty)
443{
444 sl.insert(1);
445 sl.insert(2);
446 sl.insert(3);
447
448 sl.empty();
449
450 EXPECT_TRUE(sl.is_empty());
451 EXPECT_EQ(sl.size(), 0);
452}
453
454TEST_F(DynSkipListTest, Swap)
455{
456 sl.insert(1);
457 sl.insert(2);
458
460 sl2.insert(10);
461 sl2.insert(20);
462 sl2.insert(30);
463
464 sl.swap(sl2);
465
466 EXPECT_EQ(sl.size(), 3);
467 EXPECT_TRUE(sl.has(10));
468
469 EXPECT_EQ(sl2.size(), 2);
470 EXPECT_TRUE(sl2.has(1));
471}
472
473// ============================================================================
474// Functional Tests
475// ============================================================================
476
477TEST_F(DynSkipListTest, ForEach)
478{
479 sl.insert(1);
480 sl.insert(2);
481 sl.insert(3);
482
483 int sum = 0;
484 sl.for_each([&sum](int x) { sum += x; });
485
486 EXPECT_EQ(sum, 6);
487}
488
489TEST_F(DynSkipListTest, All)
490{
491 sl.insert(2);
492 sl.insert(4);
493 sl.insert(6);
494
495 EXPECT_TRUE(sl.all([](int x) { return x % 2 == 0; }));
496
497 sl.insert(3);
498 EXPECT_FALSE(sl.all([](int x) { return x % 2 == 0; }));
499}
500
501TEST_F(DynSkipListTest, Exists)
502{
503 sl.insert(1);
504 sl.insert(2);
505 sl.insert(3);
506
507 EXPECT_TRUE(sl.exists([](int x) { return x > 2; }));
508 EXPECT_FALSE(sl.exists([](int x) { return x > 10; }));
509}
510
511TEST_F(DynSkipListTest, Traverse)
512{
513 sl.insert(1);
514 sl.insert(2);
515 sl.insert(3);
516 sl.insert(4);
517 sl.insert(5);
518
519 // Traverse until we find 3
520 int count = 0;
521 bool completed = sl.traverse([&count](int x) {
522 ++count;
523 return x != 3; // Stop when we find 3
524 });
525
527 EXPECT_EQ(count, 3);
528}
529
530// ============================================================================
531// Large Scale Tests
532// ============================================================================
533
534TEST_F(DynSkipListTest, LargeScale)
535{
536 const int N = 1000;
537
538 for (int i = 0; i < N; ++i)
539 sl.insert(i);
540
541 EXPECT_EQ(sl.size(), N);
542
543 for (int i = 0; i < N; ++i)
544 EXPECT_TRUE(sl.has(i));
545
546 for (int i = 0; i < N; i += 2)
547 sl.remove(i);
548
549 EXPECT_EQ(sl.size(), N / 2);
550
551 for (int i = 0; i < N; ++i)
552 {
553 if (i % 2 == 0)
554 EXPECT_FALSE(sl.has(i));
555 else
556 EXPECT_TRUE(sl.has(i));
557 }
558}
559
560// ============================================================================
561// String Key Tests
562// ============================================================================
563
565{
567
568 sl.insert("banana");
569 sl.insert("apple");
570 sl.insert("cherry");
571
572 EXPECT_EQ(sl.size(), 3);
573 EXPECT_EQ(sl.min(), "apple");
574 EXPECT_EQ(sl.max(), "cherry");
575
576 EXPECT_TRUE(sl.has("banana"));
577 EXPECT_FALSE(sl.has("date"));
578}
579
580// ============================================================================
581// SearchOrInsert Tests
582// ============================================================================
583
584TEST_F(DynSkipListTest, SearchOrInsertNew)
585{
586 int * result = sl.search_or_insert(42);
587
588 ASSERT_NE(result, nullptr);
589 EXPECT_EQ(*result, 42);
590 EXPECT_EQ(sl.size(), 1);
591}
592
593TEST_F(DynSkipListTest, SearchOrInsertExisting)
594{
595 sl.insert(42);
596
597 int * result = sl.search_or_insert(42);
598
599 ASSERT_NE(result, nullptr);
600 EXPECT_EQ(*result, 42);
601 EXPECT_EQ(sl.size(), 1); // No new insertion
602}
603
604} // anonymous namespace
605
606int main(int argc, char** argv)
607{
608 ::testing::InitGoogleTest(&argc, argv);
609 return RUN_ALL_TESTS();
610}
TEST_F(StaticArenaFixture, simple_fail)
Definition ah-arena.cc:59
int main()
T & insert(const T &item)
Insert a new item by copy.
Definition htlist.H:1502
T remove()
Remove the first item of the list.
Definition htlist.H:1611
Forward iterator for DynSkipList.
bool has_curr() const noexcept
Dynamic ordered set implemented with a Skip List.
Key * search_or_insert(const Key &key)
Search and insert if not found.
const Key & min() const
Return the minimum element (first in sorted order)
Key * insert(const Key &key)
Insert an element into the set.
size_t size() const noexcept
Return the number of elements in the set.
bool has(const Key &key) const noexcept
Return true if the key exists in the set.
const Key & max() const
Return the maximum element (last in sorted order)
size_t size() const noexcept
Count the number of elements of the list.
Definition htlist.H:1319
#define TEST(name)
static mt19937 rng
#define N
Definition fib.C:294
Main namespace for Aleph-w library functions.
Definition ah-arena.H:89
bool completed() const noexcept
Return true if all underlying iterators are finished.
Definition ah-zip.H:140
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
T sum(const Container &container, const T &init=T{})
Compute sum of all elements.
Dynamic ordered set implemented with a Skip List.