Aleph-w 3.0
A C++ Library for Data Structures and Algorithms
Loading...
Searching...
No Matches
tpl_random_queue_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
38#include <gtest/gtest.h>
39#include <tpl_random_queue.H>
40#include <tpl_dynDlist.H>
41#include <set>
42#include <map>
43#include <algorithm>
44#include <thread>
45#include <chrono>
46
47using namespace Aleph;
48
49// =============================================================================
50// Basic Functionality Tests
51// =============================================================================
52
53class RandomSetTest : public ::testing::Test
54{
55protected:
57};
58
60{
61 EXPECT_TRUE(rset.is_empty());
62 EXPECT_EQ(rset.size(), 0);
63}
64
66{
67 rset.put(1);
68 EXPECT_EQ(rset.size(), 1);
69 EXPECT_FALSE(rset.is_empty());
70
71 rset.put(2);
72 rset.put(3);
73 EXPECT_EQ(rset.size(), 3);
74}
75
77{
78 rset.put(1);
79 rset.put(2);
80 rset.put(3);
81
82 rset.get();
83 EXPECT_EQ(rset.size(), 2);
84
85 rset.get();
86 rset.get();
87 EXPECT_EQ(rset.size(), 0);
88 EXPECT_TRUE(rset.is_empty());
89}
90
92{
93 std::set<int> inserted = {1, 2, 3, 4, 5};
94 for (int x : inserted)
95 rset.put(x);
96
97 std::set<int> retrieved;
98 while (!rset.is_empty())
99 retrieved.insert(rset.get());
100
102}
103
105{
106 EXPECT_THROW(rset.get(), std::underflow_error);
107}
108
110{
111 rset.put(1);
112 rset.put(2);
113 rset.put(3);
114
115 rset.pick(); // Should not remove
116 EXPECT_EQ(rset.size(), 3);
117
118 rset.pick();
119 EXPECT_EQ(rset.size(), 3);
120}
121
123{
124 EXPECT_THROW(rset.pick(), std::underflow_error);
125}
126
127// =============================================================================
128// Append Tests (Random Insertion)
129// =============================================================================
130
132{
133 rset.append(1);
134 EXPECT_EQ(rset.size(), 1);
135
136 rset.append(2);
137 rset.append(3);
138 EXPECT_EQ(rset.size(), 3);
139}
140
142{
143 int& ref = rset.append(42);
144 // The reference should be valid within the container
145 EXPECT_GE(ref, 0); // Just verify it's accessible
146}
147
148// =============================================================================
149// Copy and Move Semantics
150// =============================================================================
151
153{
154 rset.put(1);
155 rset.put(2);
156 rset.put(3);
157
158 Random_Set<int> copy(rset);
159
160 EXPECT_EQ(copy.size(), 3);
161
162 // Both should have same elements
163 std::set<int> orig_elems, copy_elems;
164 while (!rset.is_empty())
165 orig_elems.insert(rset.get());
166 while (!copy.is_empty())
167 copy_elems.insert(copy.get());
168
170}
171
173{
174 rset.put(1);
175 rset.put(2);
176 rset.put(3);
177
178 Random_Set<int> moved(std::move(rset));
179
180 EXPECT_EQ(moved.size(), 3);
181}
182
184{
185 rset.put(1);
186 rset.put(2);
187
189 other.put(10);
190
191 other = rset;
192
193 EXPECT_EQ(other.size(), 2);
194}
195
197{
198 rset.put(1);
199 rset.put(2);
200
202 other = std::move(rset);
203
204 EXPECT_EQ(other.size(), 2);
205}
206
207// =============================================================================
208// Initializer List and Iterator Constructors
209// =============================================================================
210
212{
213 Random_Set<int> rset = {1, 2, 3, 4, 5};
214
215 EXPECT_EQ(rset.size(), 5);
216
217 std::set<int> retrieved;
218 while (!rset.is_empty())
219 retrieved.insert(rset.get());
220
221 std::set<int> expected = {1, 2, 3, 4, 5};
223}
224
226{
227 DynList<int> list;
228 list.append(1);
229 list.append(2);
230 list.append(3);
231
232 Random_Set<int> rset(list);
233
234 EXPECT_EQ(rset.size(), 3);
235}
236
238{
239 std::vector<int> vec = {1, 2, 3, 4, 5};
240
241 Random_Set<int> rset(vec.begin(), vec.end());
242
243 EXPECT_EQ(rset.size(), 5);
244}
245
246// =============================================================================
247// Randomness Tests
248// =============================================================================
249
251{
252 // Verify that different seeds produce different extraction order
253 const int N = 100;
254
255 // First extraction with seed 1
257 for (int i = 0; i < N; ++i)
258 rset1.put(i);
259 rset1.set_seed(12345);
260 std::vector<int> seq1;
261 while (!rset1.is_empty())
262 seq1.push_back(rset1.get());
263
264 // Second extraction with seed 2
266 for (int i = 0; i < N; ++i)
267 rset2.put(i);
268 rset2.set_seed(67890);
269 std::vector<int> seq2;
270 while (!rset2.is_empty())
271 seq2.push_back(rset2.get());
272
273 // Different seeds should produce different orders
274 EXPECT_NE(seq1, seq2) << "Different seeds should produce different extraction orders";
275}
276
278{
280
281 for (int i = 0; i < 10; ++i)
282 {
283 rset1.put(i);
284 rset2.put(i);
285 }
286
287 rset1.set_seed(12345);
288 rset2.set_seed(12345);
289
290 std::vector<int> seq1, seq2;
291 while (!rset1.is_empty())
292 seq1.push_back(rset1.get());
293 while (!rset2.is_empty())
294 seq2.push_back(rset2.get());
295
297}
298
299// =============================================================================
300// Traverse Tests
301// =============================================================================
302
304{
305 rset.put(1);
306 rset.put(2);
307 rset.put(3);
308
309 std::set<int> visited;
310 rset.traverse([&visited](int x) {
311 visited.insert(x);
312 return true;
313 });
314
315 std::set<int> expected = {1, 2, 3};
317}
318
320{
321 for (int i = 1; i <= 10; ++i)
322 rset.put(i);
323
324 int count = 0;
325 rset.traverse([&count](int) {
326 ++count;
327 return count < 5; // Stop after 5 elements
328 });
329
330 EXPECT_EQ(count, 5);
331}
332
333// =============================================================================
334// Shuffle Function Tests
335// =============================================================================
336
338{
339 DynList<int> list;
340 for (int i = 0; i < 10; ++i)
341 list.append(i);
342
343 auto shuffled = shuffle(list);
344
345 // Same size
346 EXPECT_EQ(shuffled.size(), list.size());
347
348 // Same elements (just reordered)
349 std::set<int> orig_set, shuffled_set;
350 list.for_each([&](int x) { orig_set.insert(x); });
351 shuffled.for_each([&](int x) { shuffled_set.insert(x); });
352
354}
355
357{
358 DynList<int> list;
359 for (int i = 0; i < 100; ++i)
360 list.append(i);
361
362 auto shuffled = shuffle(list);
363
364 // Check it's actually shuffled (not in original order)
365 std::vector<int> orig_vec, shuffled_vec;
366 list.for_each([&](int x) { orig_vec.push_back(x); });
367 shuffled.for_each([&](int x) { shuffled_vec.push_back(x); });
368
369 // With 100 elements, probability of same order is 1/100! ≈ 0
371}
372
373// =============================================================================
374// Move Semantics for Elements
375// =============================================================================
376
378{
380
381 std::string s = "hello";
382 rset.put(std::move(s));
383
384 EXPECT_EQ(rset.size(), 1);
385 // s may be empty after move
386}
387
389{
391
392 std::string s = "world";
393 rset.append(std::move(s));
394
395 EXPECT_EQ(rset.size(), 1);
396}
397
398// =============================================================================
399// Stress Tests
400// =============================================================================
401
403{
404 Random_Set<int> rset;
405
406 const int N = 10000;
407 for (int i = 0; i < N; ++i)
408 rset.put(i);
409
410 EXPECT_EQ(rset.size(), N);
411
412 std::set<int> retrieved;
413 while (!rset.is_empty())
414 retrieved.insert(rset.get());
415
417 for (int i = 0; i < N; ++i)
418 EXPECT_TRUE(retrieved.count(i));
419}
420
422{
423 Random_Set<int> rset;
424
425 for (int cycle = 0; cycle < 100; ++cycle)
426 {
427 // Add some elements
428 for (int i = 0; i < 100; ++i)
429 rset.put(cycle * 100 + i);
430
431 // Remove some
432 for (int i = 0; i < 50; ++i)
433 rset.get();
434 }
435
436 // Should have 50 * 100 = 5000 elements remaining
437 EXPECT_EQ(rset.size(), 5000);
438}
439
440// =============================================================================
441// Edge Cases
442// =============================================================================
443
445{
446 rset.put(42);
447
448 EXPECT_EQ(rset.get(), 42);
449 EXPECT_TRUE(rset.is_empty());
450}
451
453{
454 rset.put(1);
455 rset.put(1);
456 rset.put(1);
457
458 EXPECT_EQ(rset.size(), 3);
459
460 int sum = 0;
461 while (!rset.is_empty())
462 sum += rset.get();
463
464 EXPECT_EQ(sum, 3); // Three 1's
465}
466
467// =============================================================================
468// Main
469// =============================================================================
470
471int main(int argc, char **argv)
472{
473 ::testing::InitGoogleTest(&argc, argv);
474 return RUN_ALL_TESTS();
475}
int main()
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 & put(const T &item)
Definition htlist.H:1532
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
void put(const T &item)
Insert an item by copy.
bool is_empty() const
Return true if the queue is empty.
T get()
Extract randomly an item.
T & append(const T &item)
Insert randomly an item by copy.
size_t size() const
Return the number of items in the queue.
void for_each(Operation &operation)
Traverse all the container and performs an operation on each element.
Definition ah-dry.H:685
Random_Set< int > rset
iterator end() noexcept
Return an STL-compatible end iterator.
iterator begin() noexcept
Return an STL-compatible iterator to the first element.
#define TEST(name)
#define N
Definition fib.C:294
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
auto shuffle(const C< T > &c)
Randomly shuffle a sequence.
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.
bool traverse(Operation &operation) noexcept(traverse_is_noexcept< Operation >())
Traverse the container via its iterator and performs a conditioned operation on each item.
Definition ah-dry.H:95
Dynamic doubly linked list implementation.
Random access queue (bag) with O(1) random pop.
TEST_F(RandomSetTest, InitiallyEmpty)