Aleph-w 3.0
A C++ Library for Data Structures and Algorithms
Loading...
Searching...
No Matches
driven_table_test.cc
Go to the documentation of this file.
1
10#include <gtest/gtest.h>
11#include <driven_table.H>
12#include <string>
13
14// The legacy (void*) aliases are deprecated but still part of the
15// supported surface until 5.0.0; these tests are their coverage.
16#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
17
18using namespace std;
19
20// =============================================================================
21// Helper Functions for Legacy Events (void* interface)
22// =============================================================================
23
24// Simple event that returns a string
25void* event_hello(void* data) {
26 (void)data;
27 static string msg = "Hello";
28 return &msg;
29}
30
31// Event that increments a counter passed as data
32void* event_increment(void* data) {
33 int* counter = static_cast<int*>(data);
34 if (counter) {
35 (*counter)++;
36 }
37 return counter;
38}
39
40// Event that returns the input data directly
41void* event_echo(void* data) {
42 return data;
43}
44
45// =============================================================================
46// Legacy Static_Event_Table Tests (void* interface)
47// =============================================================================
48
53
56
57 // Register at specific index
59
60 // Execute
61 void* result = table.execute_event(0);
62 string* msg = static_cast<string*>(result);
63 EXPECT_EQ(*msg, "Hello");
64}
65
68
69 // Note: register_event(fct) appends to the END of the table.
70 // For Static_Event_Table, this means writing to index size().
71 // But Static_Event_Table has fixed size, so writing to size() is out of bounds!
72 //
73 // Wait, let's check the implementation of append_event_to_table:
74 // void append_event_to_table(Event_Fct fct) { write_table(size(), fct); }
75 //
76 // And Static_Event_Table::write_table checks: if (i >= size_table) error.
77 //
78 // So register_event(fct) on a Static_Event_Table will ALWAYS fail
79 // because it tries to append beyond the fixed size.
80 // This seems to be a design limitation or intended behavior for dynamic tables only.
81 // Let's verify this behavior.
82
83 EXPECT_THROW(table.register_event(event_hello), std::range_error);
84}
85
97
100 table.register_event(1, event_hello);
101
102 EXPECT_TRUE(table.check(1, event_hello));
103
104 table.unregister_event(1);
105
106 // Should be nullptr now
107 EXPECT_FALSE(table.check(1, event_hello));
108
109 // Executing unregistered event should throw
110 EXPECT_THROW(table.execute_event(1), std::range_error);
111}
112
115
116 EXPECT_THROW(table.register_event(5, event_hello), std::range_error);
117 EXPECT_THROW(table.execute_event(5), std::range_error); // read_table checks range first
118}
119
126
131
134 table1.register_event(0, event_hello);
135
136 // Move constructor
138 EXPECT_EQ(table2.size(), 5u);
139 EXPECT_EQ(table1.size(), 0u); // Moved from
140
141 void* result = table2.execute_event(0);
142 EXPECT_EQ(*static_cast<string*>(result), "Hello");
143
144 // Move assignment
146 table3 = std::move(table2);
147 EXPECT_EQ(table3.size(), 5u);
148 EXPECT_EQ(table2.size(), 0u);
149
150 result = table3.execute_event(0);
151 EXPECT_EQ(*static_cast<string*>(result), "Hello");
152}
153
154// =============================================================================
155// Dynamic_Event_Table Tests
156// =============================================================================
157
162
164 Legacy_Dynamic_Event_Table table; // Empty
165
166 // Auto-append
167 size_t id1 = table.register_event(event_hello);
168 EXPECT_EQ(id1, 0u);
169 EXPECT_EQ(table.size(), 1u);
170
171 size_t id2 = table.register_event(event_echo);
172 EXPECT_EQ(id2, 1u);
173 EXPECT_EQ(table.size(), 2u);
174
175 // Execute
176 void* result = table.execute_event(id1);
177 EXPECT_EQ(*static_cast<string*>(result), "Hello");
178
179 int data = 42;
180 result = table.execute_event(id2, &data);
181 EXPECT_EQ(*static_cast<int*>(result), 42);
182}
183
185 Legacy_Dynamic_Event_Table table(10); // Pre-allocate
186
187 table.register_event(5, event_hello);
188 EXPECT_TRUE(table.check(5, event_hello));
189
190 // Should grow if we write beyond the current size?
191 // The base class register_event(index, fct) checks: index >= size() -> range_error
192 // So we cannot register at arbitrary index beyond size using register_event(index, fct).
193 // We must use register_event(fct) to append.
194
195 EXPECT_THROW(table.register_event(20, event_hello), std::range_error);
196}
197
201 size_t id1 = table.register_event(event_echo);
202
203 EXPECT_EQ(table.size(), 2u);
204
205 // Unregister last event: slot is cleared but table does not shrink
206 // (size stays the same because the base class only shrinks when
207 // index == size(), which is unreachable after the range check).
208 table.unregister_event(id1);
209 EXPECT_EQ(table.size(), 2u);
211
212 // Verify event at id0 was not corrupted by unregistering id1
213 EXPECT_TRUE(table.check(0, event_hello));
214 void* result = table.execute_event(0);
215 EXPECT_EQ(*static_cast<string*>(result), "Hello");
216
217 // The cleared slot can be reused via register_event(index, fct)
220}
221
224 table.register_event(0, event_hello);
225 table.unregister_event(0);
226
227 // Now slot 0 is free
228 table.register_event(0, event_echo);
229 EXPECT_TRUE(table.check(0, event_echo));
230}
231
232// =============================================================================
233// Modern Type-Safe Event Table Tests (with lambdas and templates)
234// =============================================================================
235
236// Test void(int) signature
238 Static_Event_Table<void(int)> table(5);
239 EXPECT_EQ(table.size(), 5u);
240
241 int counter = 0;
242 table.register_event(0, [&counter](int x) { counter += x; });
243
244 table.execute_event(0, 10);
245 EXPECT_EQ(counter, 10);
246
247 table.execute_event(0, 5);
248 EXPECT_EQ(counter, 15);
249}
250
251// Test int(int, int) signature with return value
253 Static_Event_Table<int(int, int)> table(3);
254
255 // Lambda that adds two numbers
256 table.register_event(0, [](int a, int b) { return a + b; });
257
258 // Lambda that multiplies
259 table.register_event(1, [](int a, int b) { return a * b; });
260
261 EXPECT_EQ(table.execute_event(0, 3, 4), 7);
262 EXPECT_EQ(table.execute_event(1, 3, 4), 12);
263}
264
265// Test string(string) with complex objects
267 Static_Event_Table<string(const string&)> table(2);
268
269 table.register_event(0, [](const string& s) { return "Hello, " + s; });
270 table.register_event(1, [](const string& s) {
271 string upper = s;
272 for (auto& c : upper) c = toupper(c);
273 return upper;
274 });
275
276 EXPECT_EQ(table.execute_event(0, "World"), "Hello, World");
277 EXPECT_EQ(table.execute_event(1, "test"), "TEST");
278}
279
280// Test Dynamic_Event_Table with lambdas
282 Dynamic_Event_Table<int(int)> table;
283
284 auto id1 = table.register_event([](int x) { return x * 2; });
285 auto id2 = table.register_event([](int x) { return x * 3; });
286 auto id3 = table.register_event([](int x) { return x * 5; });
287
288 EXPECT_EQ(table.size(), 3u);
289
290 EXPECT_EQ(table.execute_event(id1, 10), 20);
291 EXPECT_EQ(table.execute_event(id2, 10), 30);
292 EXPECT_EQ(table.execute_event(id3, 10), 50);
293}
294
295// Test with stateful lambdas (captures)
297 Dynamic_Event_Table<void(int)> table;
298
299 int total = 0;
300 int count = 0;
301
302 // Lambda capturing by reference
303 auto avg_id = table.register_event([&](int value) {
304 total += value;
305 count++;
306 });
307
308 table.execute_event(avg_id, 10);
309 table.execute_event(avg_id, 20);
310 table.execute_event(avg_id, 30);
311
312 EXPECT_EQ(total, 60);
313 EXPECT_EQ(count, 3);
314}
315
316// Test std::function directly
318 Dynamic_Event_Table<double(double)> table;
319
320 std::function<double(double)> square = [](double x) { return x * x; };
321 std::function<double(double)> cube = [](double x) { return x * x * x; };
322
323 auto square_id = table.register_event(square);
324 auto cube_id = table.register_event(cube);
325
326 EXPECT_DOUBLE_EQ(table.execute_event(square_id, 5.0), 25.0);
327 EXPECT_DOUBLE_EQ(table.execute_event(cube_id, 3.0), 27.0);
328}
329
330// Test is_registered
332 Dynamic_Event_Table<void()> table;
333
334 auto id1 = table.register_event([]() {});
335 auto id2 = table.register_event([]() {});
336
339 EXPECT_FALSE(table.is_registered(999));
340
341 table.unregister_event(id1);
344}
345
346// Test move semantics
349 table1.register_event(0, [](int x) { return x * 10; });
350
351 // Move constructor
352 Static_Event_Table<int(int)> table2(std::move(table1));
353 EXPECT_EQ(table2.size(), 3u);
354 EXPECT_EQ(table1.size(), 0u);
355
356 EXPECT_EQ(table2.execute_event(0, 5), 50);
357
358 // Move assignment
360 table3 = std::move(table2);
361 EXPECT_EQ(table3.size(), 3u);
362 EXPECT_EQ(table2.size(), 0u);
363
364 EXPECT_EQ(table3.execute_event(0, 5), 50);
365}
366
367// =============================================================================
368// Main
369// =============================================================================
size_t size_t int32_t value
Definition ca-c-api.h:116
Dynamic (growable) event table implementation.
size_t size() const override
Get the current table size (implements Event_Table virtual method)
bool is_registered(const size_t index) const
Check if an event is registered at the given index.
void register_event(const size_t index, Callable &&fct)
Register an event at a specific index.
void unregister_event(const size_t index)
Unregister an event at the given index.
bool check(const size_t, F) const
Legacy check method (for backward compatibility).
auto execute_event(const size_t index, Args &&... args) const
Execute the event at the given index with type-safe arguments.
Fixed-size event table implementation.
size_t size() const override
Get table size (implements Event_Table virtual method)
#define TEST(name)
Event-driven table abstraction for event-driven simulations.
void * event_echo(void *data)
void * event_hello(void *data)
void * event_increment(void *data)
size_t blossom_maximum_cardinality_matching(const GT &g, DynDlist< typename GT::Arc * > &matching, SA sa=SA())
Alias of compute_maximum_cardinality_general_matching().
Definition Blossom.H:466
std::string toupper(const char *str)
Convert a C std::string to upper-case.
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.
static long counter
Definition test-splice.C:40