Line data Source code
1 : /**
2 : * @file ProcessorInternalStateNameRegistry_test.cxx
3 : *
4 : * @brief Comprehensive unit tests for ProcessorInternalStateNameRegistry
5 : *
6 : * @copyright This is part of the DUNE DAQ Software Suite, copyright 2020.
7 : * Licensing/copyright details are in the COPYING file that you should have
8 : * received with this code.
9 : */
10 :
11 : #define BOOST_TEST_MODULE ProcessorInternalStateNameRegistry_test
12 : #define FMT_HEADER_ONLY
13 : #define TPGLIBS_ENABLE_TEST_INTERFACES
14 :
15 : #include "tpglibs/ProcessorInternalStateNameRegistry.hpp"
16 :
17 : #include <boost/test/unit_test.hpp>
18 : #include <immintrin.h>
19 : #include <array>
20 : #include <memory>
21 : #include <string>
22 : #include <algorithm>
23 :
24 : namespace tpglibs {
25 :
26 : // =============================================================================
27 : // SECTION 1: Object Lifetime Tests
28 : // =============================================================================
29 :
30 : BOOST_AUTO_TEST_SUITE(ObjectLifetime)
31 :
32 2 : BOOST_AUTO_TEST_CASE(test_default_construction)
33 : {
34 1 : ProcessorInternalStateNameRegistry<__m256i> registry;
35 1 : BOOST_TEST(registry.get_number_of_requested_internal_states() == 0);
36 1 : BOOST_TEST(registry.get_names_of_requested_internal_states().empty());
37 1 : BOOST_TEST(registry.test_get_map_size() == 0);
38 1 : }
39 :
40 2 : BOOST_AUTO_TEST_CASE(test_destruction_with_empty_registry)
41 : {
42 1 : {
43 1 : ProcessorInternalStateNameRegistry<__m256i> registry;
44 1 : } // Should not crash on destruction
45 1 : BOOST_TEST(true); // If we reach here, destruction succeeded
46 1 : }
47 :
48 2 : BOOST_AUTO_TEST_CASE(test_destruction_with_registered_states)
49 : {
50 1 : {
51 1 : ProcessorInternalStateNameRegistry<__m256i> registry;
52 1 : auto state1 = std::make_shared<__m256i>();
53 1 : auto state2 = std::make_shared<__m256i>();
54 1 : registry.register_internal_state("state1", state1);
55 1 : registry.register_internal_state("state2", state2);
56 1 : } // Should properly clean up all registered states
57 1 : BOOST_TEST(true);
58 1 : }
59 :
60 2 : BOOST_AUTO_TEST_CASE(test_destruction_clears_shared_ptrs)
61 : {
62 1 : std::weak_ptr<__m256i> weak_state;
63 1 : {
64 1 : ProcessorInternalStateNameRegistry<__m256i> registry;
65 1 : auto state = std::make_shared<__m256i>();
66 1 : weak_state = state;
67 1 : registry.register_internal_state("state", state);
68 1 : BOOST_TEST(!weak_state.expired());
69 1 : }
70 : // After registry is destroyed, if no other references exist, weak_ptr should expire
71 : // Note: state variable above still holds reference, so this is more about testing cleanup
72 1 : }
73 :
74 2 : BOOST_AUTO_TEST_CASE(test_move_construction)
75 : {
76 1 : ProcessorInternalStateNameRegistry<__m256i> registry1;
77 1 : registry1.parse_requested_internal_state_items("a,b,c");
78 1 : auto state = std::make_shared<__m256i>();
79 1 : registry1.register_internal_state("a", state);
80 :
81 1 : ProcessorInternalStateNameRegistry<__m256i> registry2(std::move(registry1));
82 :
83 1 : BOOST_TEST(registry2.get_number_of_requested_internal_states() == 3);
84 1 : BOOST_TEST(registry2.is_registered("a"));
85 1 : BOOST_TEST(registry2.get_internal_state_item_ptr("a") == state);
86 1 : }
87 :
88 2 : BOOST_AUTO_TEST_CASE(test_move_assignment)
89 : {
90 1 : ProcessorInternalStateNameRegistry<__m256i> registry1;
91 1 : registry1.parse_requested_internal_state_items("x,y");
92 1 : auto state = std::make_shared<__m256i>();
93 1 : registry1.register_internal_state("x", state);
94 :
95 1 : ProcessorInternalStateNameRegistry<__m256i> registry2;
96 1 : registry2 = std::move(registry1);
97 :
98 1 : BOOST_TEST(registry2.get_number_of_requested_internal_states() == 2);
99 1 : BOOST_TEST(registry2.is_registered("x"));
100 1 : BOOST_TEST(registry2.get_internal_state_item_ptr("x") == state);
101 1 : }
102 :
103 2 : BOOST_AUTO_TEST_CASE(test_multiple_instances_independence)
104 : {
105 1 : ProcessorInternalStateNameRegistry<__m256i> registry1;
106 1 : ProcessorInternalStateNameRegistry<__m256i> registry2;
107 :
108 1 : registry1.parse_requested_internal_state_items("a,b");
109 1 : registry2.parse_requested_internal_state_items("c,d");
110 :
111 1 : auto state1 = std::make_shared<__m256i>();
112 1 : auto state2 = std::make_shared<__m256i>();
113 :
114 1 : registry1.register_internal_state("a", state1);
115 1 : registry2.register_internal_state("c", state2);
116 :
117 : // Verify independence
118 1 : BOOST_TEST(registry1.get_number_of_requested_internal_states() == 2);
119 1 : BOOST_TEST(registry2.get_number_of_requested_internal_states() == 2);
120 1 : BOOST_TEST(registry1.is_registered("a"));
121 1 : BOOST_TEST(!registry1.is_registered("c"));
122 1 : BOOST_TEST(registry2.is_registered("c"));
123 1 : BOOST_TEST(!registry2.is_registered("a"));
124 1 : }
125 :
126 2 : BOOST_AUTO_TEST_CASE(test_different_template_types)
127 : {
128 : // Test with __m256i
129 1 : ProcessorInternalStateNameRegistry<__m256i> registry_avx;
130 1 : auto state_avx = std::make_shared<__m256i>();
131 1 : registry_avx.register_internal_state("avx_state", state_avx);
132 1 : BOOST_TEST(registry_avx.is_registered("avx_state"));
133 :
134 : // Test with array type
135 1 : ProcessorInternalStateNameRegistry<std::array<int16_t, 16>> registry_array;
136 1 : auto state_array = std::make_shared<std::array<int16_t, 16>>();
137 1 : registry_array.register_internal_state("array_state", state_array);
138 1 : BOOST_TEST(registry_array.is_registered("array_state"));
139 :
140 : // Test with simple int
141 1 : ProcessorInternalStateNameRegistry<int> registry_int;
142 1 : auto state_int = std::make_shared<int>(42);
143 1 : registry_int.register_internal_state("int_state", state_int);
144 1 : BOOST_TEST(registry_int.is_registered("int_state"));
145 1 : BOOST_TEST(*registry_int.get_internal_state_item_ptr("int_state") == 42);
146 1 : }
147 :
148 : BOOST_AUTO_TEST_SUITE_END()
149 :
150 : // =============================================================================
151 : // SECTION 2: Parse Operation Tests
152 : // =============================================================================
153 :
154 : BOOST_AUTO_TEST_SUITE(ParseOperations)
155 :
156 2 : BOOST_AUTO_TEST_CASE(test_parse_empty_string)
157 : {
158 1 : ProcessorInternalStateNameRegistry<__m256i> registry;
159 1 : registry.parse_requested_internal_state_items("");
160 1 : BOOST_TEST(registry.get_number_of_requested_internal_states() == 0);
161 1 : BOOST_TEST(registry.get_names_of_requested_internal_states().empty());
162 1 : }
163 :
164 2 : BOOST_AUTO_TEST_CASE(test_parse_single_item)
165 : {
166 1 : ProcessorInternalStateNameRegistry<__m256i> registry;
167 1 : registry.parse_requested_internal_state_items("state1");
168 1 : BOOST_TEST(registry.get_number_of_requested_internal_states() == 1);
169 1 : BOOST_TEST(registry.get_names_of_requested_internal_states()[0] == "state1");
170 1 : BOOST_TEST(registry.is_requested("state1"));
171 1 : }
172 :
173 2 : BOOST_AUTO_TEST_CASE(test_parse_multiple_items)
174 : {
175 1 : ProcessorInternalStateNameRegistry<__m256i> registry;
176 1 : registry.parse_requested_internal_state_items("a,b,c,d,e");
177 :
178 1 : BOOST_TEST(registry.get_number_of_requested_internal_states() == 5);
179 1 : auto names = registry.get_names_of_requested_internal_states();
180 1 : BOOST_TEST(names[0] == "a");
181 1 : BOOST_TEST(names[1] == "b");
182 1 : BOOST_TEST(names[2] == "c");
183 1 : BOOST_TEST(names[3] == "d");
184 1 : BOOST_TEST(names[4] == "e");
185 1 : }
186 :
187 2 : BOOST_AUTO_TEST_CASE(test_parse_with_spaces)
188 : {
189 1 : ProcessorInternalStateNameRegistry<__m256i> registry;
190 1 : registry.parse_requested_internal_state_items(" a , b , c ");
191 :
192 1 : BOOST_TEST(registry.get_number_of_requested_internal_states() == 3);
193 1 : auto names = registry.get_names_of_requested_internal_states();
194 1 : BOOST_TEST(names[0] == "a");
195 1 : BOOST_TEST(names[1] == "b");
196 1 : BOOST_TEST(names[2] == "c");
197 1 : }
198 :
199 2 : BOOST_AUTO_TEST_CASE(test_parse_with_tabs_and_newlines)
200 : {
201 1 : ProcessorInternalStateNameRegistry<__m256i> registry;
202 1 : registry.parse_requested_internal_state_items("\ta\t,\nb\n,\r\nc\r\n");
203 :
204 1 : BOOST_TEST(registry.get_number_of_requested_internal_states() == 3);
205 1 : auto names = registry.get_names_of_requested_internal_states();
206 1 : BOOST_TEST(names[0] == "a");
207 1 : BOOST_TEST(names[1] == "b");
208 1 : BOOST_TEST(names[2] == "c");
209 1 : }
210 :
211 2 : BOOST_AUTO_TEST_CASE(test_parse_with_empty_items)
212 : {
213 1 : ProcessorInternalStateNameRegistry<__m256i> registry;
214 1 : registry.parse_requested_internal_state_items("a,,b,,,c");
215 :
216 : // Empty items should be filtered out
217 1 : BOOST_TEST(registry.get_number_of_requested_internal_states() == 3);
218 1 : auto names = registry.get_names_of_requested_internal_states();
219 1 : BOOST_TEST(names[0] == "a");
220 1 : BOOST_TEST(names[1] == "b");
221 1 : BOOST_TEST(names[2] == "c");
222 1 : }
223 :
224 2 : BOOST_AUTO_TEST_CASE(test_parse_with_only_commas)
225 : {
226 1 : ProcessorInternalStateNameRegistry<__m256i> registry;
227 1 : registry.parse_requested_internal_state_items(",,,");
228 1 : BOOST_TEST(registry.get_number_of_requested_internal_states() == 0);
229 1 : }
230 :
231 2 : BOOST_AUTO_TEST_CASE(test_parse_with_only_whitespace)
232 : {
233 1 : ProcessorInternalStateNameRegistry<__m256i> registry;
234 1 : registry.parse_requested_internal_state_items(" \t\n ");
235 1 : BOOST_TEST(registry.get_number_of_requested_internal_states() == 0);
236 1 : }
237 :
238 2 : BOOST_AUTO_TEST_CASE(test_parse_trailing_comma)
239 : {
240 1 : ProcessorInternalStateNameRegistry<__m256i> registry;
241 1 : registry.parse_requested_internal_state_items("a,b,c,");
242 :
243 1 : BOOST_TEST(registry.get_number_of_requested_internal_states() == 3);
244 1 : auto names = registry.get_names_of_requested_internal_states();
245 1 : BOOST_TEST(names[0] == "a");
246 1 : BOOST_TEST(names[1] == "b");
247 1 : BOOST_TEST(names[2] == "c");
248 1 : }
249 :
250 2 : BOOST_AUTO_TEST_CASE(test_parse_leading_comma)
251 : {
252 1 : ProcessorInternalStateNameRegistry<__m256i> registry;
253 1 : registry.parse_requested_internal_state_items(",a,b,c");
254 :
255 1 : BOOST_TEST(registry.get_number_of_requested_internal_states() == 3);
256 1 : auto names = registry.get_names_of_requested_internal_states();
257 1 : BOOST_TEST(names[0] == "a");
258 1 : BOOST_TEST(names[1] == "b");
259 1 : BOOST_TEST(names[2] == "c");
260 1 : }
261 :
262 2 : BOOST_AUTO_TEST_CASE(test_parse_duplicate_names)
263 : {
264 1 : ProcessorInternalStateNameRegistry<__m256i> registry;
265 1 : registry.parse_requested_internal_state_items("a,b,a,c,b");
266 :
267 : // Current implementation doesn't deduplicate
268 1 : BOOST_TEST(registry.get_number_of_requested_internal_states() == 5);
269 1 : auto names = registry.get_names_of_requested_internal_states();
270 1 : BOOST_TEST(names[0] == "a");
271 1 : BOOST_TEST(names[1] == "b");
272 1 : BOOST_TEST(names[2] == "a");
273 1 : BOOST_TEST(names[3] == "c");
274 1 : BOOST_TEST(names[4] == "b");
275 1 : }
276 :
277 2 : BOOST_AUTO_TEST_CASE(test_parse_overwrite_previous)
278 : {
279 1 : ProcessorInternalStateNameRegistry<__m256i> registry;
280 1 : registry.parse_requested_internal_state_items("a,b,c");
281 1 : BOOST_TEST(registry.get_number_of_requested_internal_states() == 3);
282 :
283 : // Parse again - should clear previous
284 1 : registry.parse_requested_internal_state_items("x,y");
285 1 : BOOST_TEST(registry.get_number_of_requested_internal_states() == 2);
286 1 : auto names = registry.get_names_of_requested_internal_states();
287 1 : BOOST_TEST(names[0] == "x");
288 1 : BOOST_TEST(names[1] == "y");
289 1 : }
290 :
291 2 : BOOST_AUTO_TEST_CASE(test_parse_long_names)
292 : {
293 1 : ProcessorInternalStateNameRegistry<__m256i> registry;
294 1 : std::string long_name(1000, 'x');
295 1 : registry.parse_requested_internal_state_items(long_name);
296 :
297 1 : BOOST_TEST(registry.get_number_of_requested_internal_states() == 1);
298 1 : BOOST_TEST(registry.get_names_of_requested_internal_states()[0] == long_name);
299 1 : }
300 :
301 2 : BOOST_AUTO_TEST_CASE(test_parse_special_characters)
302 : {
303 1 : ProcessorInternalStateNameRegistry<__m256i> registry;
304 1 : registry.parse_requested_internal_state_items("state_1,state-2,state.3,state:4");
305 :
306 1 : BOOST_TEST(registry.get_number_of_requested_internal_states() == 4);
307 1 : auto names = registry.get_names_of_requested_internal_states();
308 1 : BOOST_TEST(names[0] == "state_1");
309 1 : BOOST_TEST(names[1] == "state-2");
310 1 : BOOST_TEST(names[2] == "state.3");
311 1 : BOOST_TEST(names[3] == "state:4");
312 1 : }
313 :
314 2 : BOOST_AUTO_TEST_CASE(test_parse_very_many_items)
315 : {
316 1 : ProcessorInternalStateNameRegistry<__m256i> registry;
317 1 : std::string config;
318 1001 : for (int i = 0; i < 1000; ++i) {
319 1000 : if (i > 0) config += ",";
320 1000 : config += "state" + std::to_string(i);
321 : }
322 :
323 1 : registry.parse_requested_internal_state_items(config);
324 1 : BOOST_TEST(registry.get_number_of_requested_internal_states() == 1000);
325 1 : }
326 :
327 : BOOST_AUTO_TEST_SUITE_END()
328 :
329 : // =============================================================================
330 : // SECTION 3: Register Operation Tests
331 : // =============================================================================
332 :
333 : BOOST_AUTO_TEST_SUITE(RegisterOperations)
334 :
335 2 : BOOST_AUTO_TEST_CASE(test_register_single_state)
336 : {
337 1 : ProcessorInternalStateNameRegistry<__m256i> registry;
338 1 : auto state = std::make_shared<__m256i>();
339 :
340 1 : registry.register_internal_state("test_state", state);
341 :
342 1 : BOOST_TEST(registry.is_registered("test_state"));
343 1 : BOOST_TEST(registry.get_internal_state_item_ptr("test_state") == state);
344 1 : }
345 :
346 2 : BOOST_AUTO_TEST_CASE(test_register_multiple_states)
347 : {
348 1 : ProcessorInternalStateNameRegistry<__m256i> registry;
349 1 : auto state1 = std::make_shared<__m256i>();
350 1 : auto state2 = std::make_shared<__m256i>();
351 1 : auto state3 = std::make_shared<__m256i>();
352 :
353 1 : registry.register_internal_state("s1", state1);
354 1 : registry.register_internal_state("s2", state2);
355 1 : registry.register_internal_state("s3", state3);
356 :
357 1 : BOOST_TEST(registry.test_get_map_size() == 3);
358 1 : BOOST_TEST(registry.get_internal_state_item_ptr("s1") == state1);
359 1 : BOOST_TEST(registry.get_internal_state_item_ptr("s2") == state2);
360 1 : BOOST_TEST(registry.get_internal_state_item_ptr("s3") == state3);
361 1 : }
362 :
363 2 : BOOST_AUTO_TEST_CASE(test_register_overwrites_existing)
364 : {
365 1 : ProcessorInternalStateNameRegistry<__m256i> registry;
366 1 : auto state1 = std::make_shared<__m256i>();
367 1 : auto state2 = std::make_shared<__m256i>();
368 :
369 1 : registry.register_internal_state("test", state1);
370 1 : BOOST_TEST(registry.get_internal_state_item_ptr("test") == state1);
371 :
372 : // Register again with different pointer
373 1 : registry.register_internal_state("test", state2);
374 1 : BOOST_TEST(registry.get_internal_state_item_ptr("test") == state2);
375 1 : BOOST_TEST(registry.test_get_map_size() == 1); // Should not create duplicate
376 1 : }
377 :
378 2 : BOOST_AUTO_TEST_CASE(test_register_nullptr)
379 : {
380 1 : ProcessorInternalStateNameRegistry<__m256i> registry;
381 :
382 : // Registering nullptr should be allowed (user might do this)
383 1 : registry.register_internal_state("null_state", nullptr);
384 1 : BOOST_TEST(registry.is_registered("null_state"));
385 1 : BOOST_TEST(registry.get_internal_state_item_ptr("null_state") == nullptr);
386 1 : }
387 :
388 2 : BOOST_AUTO_TEST_CASE(test_register_empty_name)
389 : {
390 1 : ProcessorInternalStateNameRegistry<__m256i> registry;
391 1 : auto state = std::make_shared<__m256i>();
392 :
393 : // Empty string as name should work (though not recommended)
394 1 : registry.register_internal_state("", state);
395 1 : BOOST_TEST(registry.is_registered(""));
396 1 : BOOST_TEST(registry.get_internal_state_item_ptr("") == state);
397 1 : }
398 :
399 2 : BOOST_AUTO_TEST_CASE(test_register_names_with_whitespace)
400 : {
401 1 : ProcessorInternalStateNameRegistry<__m256i> registry;
402 1 : auto state1 = std::make_shared<__m256i>();
403 1 : auto state2 = std::make_shared<__m256i>();
404 :
405 1 : registry.register_internal_state(" a ", state1);
406 1 : registry.register_internal_state("a", state2);
407 :
408 : // These are different names (with and without spaces)
409 1 : BOOST_TEST(registry.test_get_map_size() == 2);
410 1 : BOOST_TEST(registry.get_internal_state_item_ptr(" a ") == state1);
411 1 : BOOST_TEST(registry.get_internal_state_item_ptr("a") == state2);
412 1 : }
413 :
414 2 : BOOST_AUTO_TEST_CASE(test_register_shared_ownership)
415 : {
416 1 : ProcessorInternalStateNameRegistry<__m256i> registry;
417 1 : auto state = std::make_shared<__m256i>();
418 1 : std::weak_ptr<__m256i> weak_state = state;
419 :
420 1 : registry.register_internal_state("shared", state);
421 :
422 : // Registry should hold a reference
423 1 : BOOST_TEST(state.use_count() == 2); // Original + registry
424 :
425 : // Release original reference
426 1 : state.reset();
427 1 : BOOST_TEST(!weak_state.expired()); // Registry still holds it
428 :
429 : // Get pointer from registry
430 1 : auto retrieved = registry.get_internal_state_item_ptr("shared");
431 1 : BOOST_TEST(retrieved != nullptr);
432 1 : BOOST_TEST(retrieved.use_count() == 2); // Registry + retrieved
433 1 : }
434 :
435 : BOOST_AUTO_TEST_SUITE_END()
436 :
437 : // =============================================================================
438 : // SECTION 4: Retrieval Operation Tests
439 : // =============================================================================
440 :
441 : BOOST_AUTO_TEST_SUITE(RetrievalOperations)
442 :
443 2 : BOOST_AUTO_TEST_CASE(test_get_unregistered_name)
444 : {
445 1 : ProcessorInternalStateNameRegistry<__m256i> registry;
446 :
447 : // Getting non-existent key returns nullptr (default-constructed shared_ptr)
448 1 : auto ptr = registry.get_internal_state_item_ptr("nonexistent");
449 1 : BOOST_TEST(ptr == nullptr);
450 1 : }
451 :
452 2 : BOOST_AUTO_TEST_CASE(test_is_registered)
453 : {
454 1 : ProcessorInternalStateNameRegistry<__m256i> registry;
455 1 : auto state = std::make_shared<__m256i>();
456 :
457 1 : BOOST_TEST(!registry.is_registered("test"));
458 1 : registry.register_internal_state("test", state);
459 1 : BOOST_TEST(registry.is_registered("test"));
460 1 : }
461 :
462 2 : BOOST_AUTO_TEST_CASE(test_is_requested)
463 : {
464 1 : ProcessorInternalStateNameRegistry<__m256i> registry;
465 :
466 1 : registry.parse_requested_internal_state_items("a,b,c");
467 :
468 1 : BOOST_TEST(registry.is_requested("a"));
469 1 : BOOST_TEST(registry.is_requested("b"));
470 1 : BOOST_TEST(registry.is_requested("c"));
471 1 : BOOST_TEST(!registry.is_requested("d"));
472 1 : }
473 :
474 2 : BOOST_AUTO_TEST_CASE(test_get_all_registered_names)
475 : {
476 1 : ProcessorInternalStateNameRegistry<__m256i> registry;
477 1 : auto state1 = std::make_shared<__m256i>();
478 1 : auto state2 = std::make_shared<__m256i>();
479 1 : auto state3 = std::make_shared<__m256i>();
480 :
481 1 : registry.register_internal_state("x", state1);
482 1 : registry.register_internal_state("y", state2);
483 1 : registry.register_internal_state("z", state3);
484 :
485 1 : auto names = registry.test_get_all_registered_internal_state_names();
486 1 : BOOST_TEST(names.size() == 3);
487 :
488 : // Order not guaranteed in unordered_map, so check presence
489 1 : bool has_x = (std::find(names.begin(), names.end(), "x") != names.end());
490 1 : bool has_y = (std::find(names.begin(), names.end(), "y") != names.end());
491 1 : bool has_z = (std::find(names.begin(), names.end(), "z") != names.end());
492 1 : BOOST_TEST(has_x);
493 1 : BOOST_TEST(has_y);
494 1 : BOOST_TEST(has_z);
495 1 : }
496 :
497 2 : BOOST_AUTO_TEST_CASE(test_get_all_requested_item_ptrs_empty)
498 : {
499 1 : ProcessorInternalStateNameRegistry<__m256i> registry;
500 :
501 1 : auto ptrs = registry.get_all_requested_internal_state_item_ptrs();
502 1 : BOOST_TEST(ptrs.empty());
503 1 : }
504 :
505 2 : BOOST_AUTO_TEST_CASE(test_get_all_requested_item_ptrs_all_registered)
506 : {
507 1 : ProcessorInternalStateNameRegistry<__m256i> registry;
508 :
509 1 : registry.parse_requested_internal_state_items("a,b,c");
510 :
511 1 : auto state_a = std::make_shared<__m256i>();
512 1 : auto state_b = std::make_shared<__m256i>();
513 1 : auto state_c = std::make_shared<__m256i>();
514 :
515 1 : registry.register_internal_state("a", state_a);
516 1 : registry.register_internal_state("b", state_b);
517 1 : registry.register_internal_state("c", state_c);
518 :
519 1 : auto ptrs = registry.get_all_requested_internal_state_item_ptrs();
520 1 : BOOST_TEST(ptrs.size() == 3);
521 1 : BOOST_TEST(ptrs[0] == state_a);
522 1 : BOOST_TEST(ptrs[1] == state_b);
523 1 : BOOST_TEST(ptrs[2] == state_c);
524 1 : }
525 :
526 2 : BOOST_AUTO_TEST_CASE(test_get_all_requested_item_ptrs_partial_registered)
527 : {
528 1 : ProcessorInternalStateNameRegistry<__m256i> registry;
529 :
530 1 : registry.parse_requested_internal_state_items("a,b,c");
531 :
532 1 : auto state_a = std::make_shared<__m256i>();
533 1 : registry.register_internal_state("a", state_a);
534 : // b and c not registered
535 :
536 1 : auto ptrs = registry.get_all_requested_internal_state_item_ptrs();
537 1 : BOOST_TEST(ptrs.size() == 3);
538 1 : BOOST_TEST(ptrs[0] == state_a);
539 1 : BOOST_TEST(ptrs[1] == nullptr); // Not registered
540 1 : BOOST_TEST(ptrs[2] == nullptr); // Not registered
541 1 : }
542 :
543 2 : BOOST_AUTO_TEST_CASE(test_get_all_requested_item_ptrs_order_preserved)
544 : {
545 1 : ProcessorInternalStateNameRegistry<__m256i> registry;
546 :
547 : // Parse in specific order
548 1 : registry.parse_requested_internal_state_items("z,a,m,b");
549 :
550 1 : auto state_z = std::make_shared<__m256i>();
551 1 : auto state_a = std::make_shared<__m256i>();
552 1 : auto state_m = std::make_shared<__m256i>();
553 1 : auto state_b = std::make_shared<__m256i>();
554 :
555 : // Register in different order
556 1 : registry.register_internal_state("a", state_a);
557 1 : registry.register_internal_state("z", state_z);
558 1 : registry.register_internal_state("b", state_b);
559 1 : registry.register_internal_state("m", state_m);
560 :
561 1 : auto ptrs = registry.get_all_requested_internal_state_item_ptrs();
562 :
563 : // Should follow requested order, not registration order
564 1 : BOOST_TEST(ptrs[0] == state_z);
565 1 : BOOST_TEST(ptrs[1] == state_a);
566 1 : BOOST_TEST(ptrs[2] == state_m);
567 1 : BOOST_TEST(ptrs[3] == state_b);
568 1 : }
569 :
570 : BOOST_AUTO_TEST_SUITE_END()
571 :
572 : // =============================================================================
573 : // SECTION 5: Clear Operation Tests
574 : // =============================================================================
575 :
576 : BOOST_AUTO_TEST_SUITE(ClearOperations)
577 :
578 2 : BOOST_AUTO_TEST_CASE(test_clear_empty_registry)
579 : {
580 1 : ProcessorInternalStateNameRegistry<__m256i> registry;
581 1 : registry.test_clear();
582 :
583 1 : BOOST_TEST(registry.get_number_of_requested_internal_states() == 0);
584 1 : BOOST_TEST(registry.test_get_map_size() == 0);
585 1 : }
586 :
587 2 : BOOST_AUTO_TEST_CASE(test_clear_removes_all_data)
588 : {
589 1 : ProcessorInternalStateNameRegistry<__m256i> registry;
590 :
591 1 : registry.parse_requested_internal_state_items("a,b,c");
592 1 : auto state1 = std::make_shared<__m256i>();
593 1 : auto state2 = std::make_shared<__m256i>();
594 1 : registry.register_internal_state("a", state1);
595 1 : registry.register_internal_state("b", state2);
596 :
597 1 : BOOST_TEST(registry.get_number_of_requested_internal_states() == 3);
598 1 : BOOST_TEST(registry.test_get_map_size() == 2);
599 :
600 1 : registry.test_clear();
601 :
602 1 : BOOST_TEST(registry.get_number_of_requested_internal_states() == 0);
603 1 : BOOST_TEST(registry.test_get_map_size() == 0);
604 1 : BOOST_TEST(!registry.is_registered("a"));
605 1 : BOOST_TEST(!registry.is_registered("b"));
606 1 : }
607 :
608 2 : BOOST_AUTO_TEST_CASE(test_clear_releases_shared_ptrs)
609 : {
610 1 : ProcessorInternalStateNameRegistry<__m256i> registry;
611 :
612 1 : auto state = std::make_shared<__m256i>();
613 1 : std::weak_ptr<__m256i> weak_state = state;
614 :
615 1 : registry.register_internal_state("test", state);
616 1 : BOOST_TEST(state.use_count() == 2);
617 :
618 1 : state.reset(); // Release original
619 1 : BOOST_TEST(!weak_state.expired()); // Registry still holds it
620 :
621 1 : registry.test_clear();
622 1 : BOOST_TEST(weak_state.expired()); // Now it should be gone
623 1 : }
624 :
625 2 : BOOST_AUTO_TEST_CASE(test_use_after_clear)
626 : {
627 1 : ProcessorInternalStateNameRegistry<__m256i> registry;
628 :
629 1 : registry.parse_requested_internal_state_items("a,b");
630 1 : registry.test_clear();
631 :
632 : // Should be usable after clear
633 1 : registry.parse_requested_internal_state_items("x,y,z");
634 1 : BOOST_TEST(registry.get_number_of_requested_internal_states() == 3);
635 :
636 1 : auto state = std::make_shared<__m256i>();
637 1 : registry.register_internal_state("x", state);
638 1 : BOOST_TEST(registry.is_registered("x"));
639 1 : }
640 :
641 : BOOST_AUTO_TEST_SUITE_END()
642 :
643 : // =============================================================================
644 : // SECTION 6: Edge Cases and Integration Tests
645 : // =============================================================================
646 :
647 : BOOST_AUTO_TEST_SUITE(EdgeCasesAndIntegration)
648 :
649 2 : BOOST_AUTO_TEST_CASE(test_parse_then_register_workflow)
650 : {
651 1 : ProcessorInternalStateNameRegistry<__m256i> registry;
652 :
653 : // Typical workflow: parse config, then register states
654 1 : registry.parse_requested_internal_state_items("input,output,temp");
655 :
656 1 : auto input_state = std::make_shared<__m256i>();
657 1 : auto output_state = std::make_shared<__m256i>();
658 1 : auto temp_state = std::make_shared<__m256i>();
659 :
660 1 : registry.register_internal_state("input", input_state);
661 1 : registry.register_internal_state("output", output_state);
662 1 : registry.register_internal_state("temp", temp_state);
663 :
664 1 : auto ptrs = registry.get_all_requested_internal_state_item_ptrs();
665 1 : BOOST_TEST(ptrs.size() == 3);
666 1 : BOOST_TEST(ptrs[0] == input_state);
667 1 : BOOST_TEST(ptrs[1] == output_state);
668 1 : BOOST_TEST(ptrs[2] == temp_state);
669 1 : }
670 :
671 2 : BOOST_AUTO_TEST_CASE(test_register_then_parse_workflow)
672 : {
673 1 : ProcessorInternalStateNameRegistry<__m256i> registry;
674 :
675 : // Register states first
676 1 : auto state1 = std::make_shared<__m256i>();
677 1 : auto state2 = std::make_shared<__m256i>();
678 1 : registry.register_internal_state("s1", state1);
679 1 : registry.register_internal_state("s2", state2);
680 :
681 : // Then parse which ones to request
682 1 : registry.parse_requested_internal_state_items("s1");
683 :
684 1 : auto ptrs = registry.get_all_requested_internal_state_item_ptrs();
685 1 : BOOST_TEST(ptrs.size() == 1);
686 1 : BOOST_TEST(ptrs[0] == state1);
687 1 : }
688 :
689 2 : BOOST_AUTO_TEST_CASE(test_requesting_unregistered_states)
690 : {
691 1 : ProcessorInternalStateNameRegistry<__m256i> registry;
692 :
693 1 : registry.parse_requested_internal_state_items("a,b,c");
694 : // Don't register anything
695 :
696 1 : auto ptrs = registry.get_all_requested_internal_state_item_ptrs();
697 1 : BOOST_TEST(ptrs.size() == 3);
698 1 : BOOST_TEST(ptrs[0] == nullptr);
699 1 : BOOST_TEST(ptrs[1] == nullptr);
700 1 : BOOST_TEST(ptrs[2] == nullptr);
701 1 : }
702 :
703 2 : BOOST_AUTO_TEST_CASE(test_registering_unrequested_states)
704 : {
705 1 : ProcessorInternalStateNameRegistry<__m256i> registry;
706 :
707 1 : registry.parse_requested_internal_state_items("a");
708 :
709 1 : auto state_a = std::make_shared<__m256i>();
710 1 : auto state_b = std::make_shared<__m256i>();
711 1 : auto state_c = std::make_shared<__m256i>();
712 :
713 1 : registry.register_internal_state("a", state_a);
714 1 : registry.register_internal_state("b", state_b);
715 1 : registry.register_internal_state("c", state_c);
716 :
717 : // All are registered
718 1 : BOOST_TEST(registry.test_get_map_size() == 3);
719 :
720 : // But only 'a' is requested
721 1 : auto ptrs = registry.get_all_requested_internal_state_item_ptrs();
722 1 : BOOST_TEST(ptrs.size() == 1);
723 1 : BOOST_TEST(ptrs[0] == state_a);
724 1 : }
725 :
726 2 : BOOST_AUTO_TEST_CASE(test_case_sensitive_names)
727 : {
728 1 : ProcessorInternalStateNameRegistry<__m256i> registry;
729 :
730 1 : auto state_lower = std::make_shared<__m256i>();
731 1 : auto state_upper = std::make_shared<__m256i>();
732 :
733 1 : registry.register_internal_state("test", state_lower);
734 1 : registry.register_internal_state("TEST", state_upper);
735 :
736 : // Case-sensitive, should be different
737 1 : BOOST_TEST(registry.test_get_map_size() == 2);
738 1 : BOOST_TEST(registry.get_internal_state_item_ptr("test") == state_lower);
739 1 : BOOST_TEST(registry.get_internal_state_item_ptr("TEST") == state_upper);
740 1 : }
741 :
742 2 : BOOST_AUTO_TEST_CASE(test_unicode_names)
743 : {
744 1 : ProcessorInternalStateNameRegistry<__m256i> registry;
745 :
746 1 : auto state = std::make_shared<__m256i>();
747 1 : registry.register_internal_state("状態", state);
748 :
749 1 : BOOST_TEST(registry.is_registered("状態"));
750 1 : BOOST_TEST(registry.get_internal_state_item_ptr("状態") == state);
751 1 : }
752 :
753 2 : BOOST_AUTO_TEST_CASE(test_very_long_name)
754 : {
755 1 : ProcessorInternalStateNameRegistry<__m256i> registry;
756 :
757 1 : std::string very_long_name(10000, 'x');
758 1 : auto state = std::make_shared<__m256i>();
759 :
760 1 : registry.register_internal_state(very_long_name, state);
761 1 : BOOST_TEST(registry.is_registered(very_long_name));
762 1 : BOOST_TEST(registry.get_internal_state_item_ptr(very_long_name) == state);
763 1 : }
764 :
765 2 : BOOST_AUTO_TEST_CASE(test_repeated_parse_calls)
766 : {
767 1 : ProcessorInternalStateNameRegistry<__m256i> registry;
768 :
769 1 : registry.parse_requested_internal_state_items("a,b");
770 1 : BOOST_TEST(registry.get_number_of_requested_internal_states() == 2);
771 :
772 1 : registry.parse_requested_internal_state_items("c,d,e");
773 1 : BOOST_TEST(registry.get_number_of_requested_internal_states() == 3);
774 1 : BOOST_TEST(!registry.is_requested("a")); // Previous should be cleared
775 1 : BOOST_TEST(registry.is_requested("c"));
776 :
777 1 : registry.parse_requested_internal_state_items("");
778 1 : BOOST_TEST(registry.get_number_of_requested_internal_states() == 0);
779 1 : }
780 :
781 2 : BOOST_AUTO_TEST_CASE(test_stress_many_operations)
782 : {
783 1 : ProcessorInternalStateNameRegistry<__m256i> registry;
784 :
785 : // Register many states
786 1 : std::vector<std::shared_ptr<__m256i>> states;
787 101 : for (int i = 0; i < 100; ++i) {
788 100 : auto state = std::make_shared<__m256i>();
789 100 : states.push_back(state);
790 100 : registry.register_internal_state("state" + std::to_string(i), state);
791 100 : }
792 :
793 1 : BOOST_TEST(registry.test_get_map_size() == 100);
794 :
795 : // Request subset
796 1 : std::string config;
797 51 : for (int i = 0; i < 50; ++i) {
798 50 : if (i > 0) config += ",";
799 50 : config += "state" + std::to_string(i * 2); // Even indices
800 : }
801 1 : registry.parse_requested_internal_state_items(config);
802 :
803 1 : auto ptrs = registry.get_all_requested_internal_state_item_ptrs();
804 1 : BOOST_TEST(ptrs.size() == 50);
805 :
806 : // Verify correctness
807 51 : for (int i = 0; i < 50; ++i) {
808 50 : BOOST_TEST(ptrs[i] == states[i * 2]);
809 : }
810 1 : }
811 :
812 2 : BOOST_AUTO_TEST_CASE(test_interleaved_parse_register)
813 : {
814 1 : ProcessorInternalStateNameRegistry<__m256i> registry;
815 :
816 1 : registry.parse_requested_internal_state_items("a,b");
817 :
818 1 : auto state_a = std::make_shared<__m256i>();
819 1 : registry.register_internal_state("a", state_a);
820 :
821 1 : registry.parse_requested_internal_state_items("a,b,c");
822 :
823 1 : auto state_b = std::make_shared<__m256i>();
824 1 : auto state_c = std::make_shared<__m256i>();
825 1 : registry.register_internal_state("b", state_b);
826 1 : registry.register_internal_state("c", state_c);
827 :
828 1 : auto ptrs = registry.get_all_requested_internal_state_item_ptrs();
829 1 : BOOST_TEST(ptrs.size() == 3);
830 1 : BOOST_TEST(ptrs[0] == state_a);
831 1 : BOOST_TEST(ptrs[1] == state_b);
832 1 : BOOST_TEST(ptrs[2] == state_c);
833 1 : }
834 :
835 2 : BOOST_AUTO_TEST_CASE(test_memory_leak_scenario)
836 : {
837 : // Test that circular references don't prevent cleanup
838 1 : ProcessorInternalStateNameRegistry<__m256i> registry;
839 :
840 1 : std::weak_ptr<__m256i> weak_state;
841 :
842 1 : {
843 1 : auto state = std::make_shared<__m256i>();
844 1 : weak_state = state;
845 1 : registry.register_internal_state("test", state);
846 1 : BOOST_TEST(state.use_count() == 2);
847 : // state goes out of scope
848 1 : }
849 :
850 1 : BOOST_TEST(!weak_state.expired()); // Registry still holds it
851 :
852 1 : registry.test_clear();
853 1 : BOOST_TEST(weak_state.expired()); // Should be cleaned up
854 1 : }
855 :
856 : BOOST_AUTO_TEST_SUITE_END()
857 :
858 : } // namespace tpglibs
|