LCOV - code coverage report
Current view: top level - tpglibs/unittest - ProcessorInternalStateBufferManager_test.cxx (source / functions) Coverage Total Hit
Test: code.result Lines: 100.0 % 374 374
Test Date: 2025-12-21 13:07:08 Functions: 100.0 % 48 48

            Line data    Source code
       1              : /**
       2              :  * @file ProcessorInternalStateBufferManager_test.cxx
       3              :  *
       4              :  * @copyright This is part of the DUNE DAQ Software Suite, copyright 2020.
       5              :  * Licensing/copyright details are in the COPYING file that you should have
       6              :  * received with this code.
       7              :  */
       8              : 
       9              : #define BOOST_TEST_MODULE ProcessorInternalStateBufferManager_tests
      10              : #define FMT_HEADER_ONLY
      11              : 
      12              : #include "tpglibs/ProcessorInternalStateBufferManager.hpp"
      13              : #include "tpglibs/ProcessorInternalStateNameRegistry.hpp"
      14              : 
      15              : #include <boost/test/unit_test.hpp>
      16              : #include <immintrin.h>
      17              : #include <thread>
      18              : #include <atomic>
      19              : #include <vector>
      20              : #include <chrono>
      21              : 
      22              : namespace tpglibs {
      23              : 
      24              : // =============================================================================
      25              : // LIFECYCLE TESTS
      26              : // =============================================================================
      27              : 
      28              : BOOST_AUTO_TEST_SUITE(lifecycle_tests)
      29              : 
      30            2 : BOOST_AUTO_TEST_CASE(test_construction_and_destruction)
      31              : {
      32              :   // Test that we can construct and destroy without crashing
      33            1 :   ProcessorInternalStateBufferManager<__m256i> manager;
      34            1 :   BOOST_TEST(true); // If we reach here, construction succeeded
      35            1 : }
      36              : 
      37            2 : BOOST_AUTO_TEST_CASE(test_configure_single_item)
      38              : {
      39            1 :   ProcessorInternalStateNameRegistry<__m256i> registry;
      40            1 :   __m256i a = _mm256_set1_epi16(42);
      41            1 :   auto a_ptr = std::make_shared<__m256i>(a);
      42              :   
      43            1 :   registry.register_internal_state("state_a", a_ptr);
      44            1 :   registry.parse_requested_internal_state_items("state_a");
      45              :   
      46            1 :   ProcessorInternalStateBufferManager<__m256i> manager;
      47            1 :   manager.configure_from_registry(&registry);
      48              :   
      49              :   // Configuration should succeed without crash
      50            1 :   BOOST_TEST(true);
      51            1 : }
      52              : 
      53            2 : BOOST_AUTO_TEST_CASE(test_configure_multiple_items)
      54              : {
      55            1 :   ProcessorInternalStateNameRegistry<__m256i> registry;
      56              :   
      57            1 :   __m256i a = _mm256_set1_epi16(1);
      58            1 :   __m256i b = _mm256_set1_epi16(2);
      59            1 :   __m256i c = _mm256_set1_epi16(3);
      60              :   
      61            1 :   auto a_ptr = std::make_shared<__m256i>(a);
      62            1 :   auto b_ptr = std::make_shared<__m256i>(b);
      63            1 :   auto c_ptr = std::make_shared<__m256i>(c);
      64              :   
      65            1 :   registry.register_internal_state("a", a_ptr);
      66            1 :   registry.register_internal_state("b", b_ptr);
      67            1 :   registry.register_internal_state("c", c_ptr);
      68            1 :   registry.parse_requested_internal_state_items("a,b,c");
      69              :   
      70            1 :   ProcessorInternalStateBufferManager<__m256i> manager;
      71            1 :   manager.configure_from_registry(&registry);
      72              :   
      73            1 :   BOOST_TEST(true);
      74            1 : }
      75              : 
      76            2 : BOOST_AUTO_TEST_CASE(test_configure_empty_registry)
      77              : {
      78            1 :   ProcessorInternalStateNameRegistry<__m256i> registry;
      79              :   // Don't register or request any items
      80            1 :   registry.parse_requested_internal_state_items("");
      81              :   
      82            1 :   ProcessorInternalStateBufferManager<__m256i> manager;
      83            1 :   manager.configure_from_registry(&registry);
      84              :   
      85              :   // Should handle empty configuration gracefully
      86            1 :   BOOST_TEST(true);
      87            1 : }
      88              : 
      89              : BOOST_AUTO_TEST_SUITE_END()
      90              : 
      91              : // =============================================================================
      92              : // READ AND WRITE BEHAVIOR TESTS
      93              : // =============================================================================
      94              : 
      95              : BOOST_AUTO_TEST_SUITE(read_write_behavior_tests)
      96              : 
      97            2 : BOOST_AUTO_TEST_CASE(test_basic_write_and_read)
      98              : {
      99            1 :   ProcessorInternalStateNameRegistry<__m256i> registry;
     100            1 :   __m256i a = _mm256_set1_epi16(100);
     101            1 :   auto a_ptr = std::make_shared<__m256i>(a);
     102              :   
     103            1 :   registry.register_internal_state("a", a_ptr);
     104            1 :   registry.parse_requested_internal_state_items("a");
     105              :   
     106            1 :   ProcessorInternalStateBufferManager<__m256i> manager;
     107            1 :   manager.configure_from_registry(&registry);
     108            1 :   manager.write_to_active_buffer();
     109              :   
     110            1 :   auto result = manager.switch_buffer_and_read();
     111              :   
     112            1 :   BOOST_TEST(result.m_size == 1);
     113            1 :   BOOST_REQUIRE(result.m_data != nullptr);
     114              :   
     115            1 :   int16_t out[16];
     116            1 :   _mm256_storeu_si256(reinterpret_cast<__m256i*>(&out), result.m_data[0]);
     117              :   
     118           17 :   for (int i = 0; i < 16; i++) {
     119           16 :     BOOST_TEST(out[i] == 100);
     120              :   }
     121            1 : }
     122              : 
     123            2 : BOOST_AUTO_TEST_CASE(test_multiple_items_write_and_read)
     124              : {
     125            1 :   ProcessorInternalStateNameRegistry<__m256i> registry;
     126              :   
     127            1 :   __m256i a = _mm256_set1_epi16(10);
     128            1 :   __m256i b = _mm256_set1_epi16(20);
     129            1 :   __m256i c = _mm256_set1_epi16(30);
     130              :   
     131            1 :   auto a_ptr = std::make_shared<__m256i>(a);
     132            1 :   auto b_ptr = std::make_shared<__m256i>(b);
     133            1 :   auto c_ptr = std::make_shared<__m256i>(c);
     134              :   
     135            1 :   registry.register_internal_state("a", a_ptr);
     136            1 :   registry.register_internal_state("b", b_ptr);
     137            1 :   registry.register_internal_state("c", c_ptr);
     138            1 :   registry.parse_requested_internal_state_items("a,b,c");
     139              :   
     140            1 :   ProcessorInternalStateBufferManager<__m256i> manager;
     141            1 :   manager.configure_from_registry(&registry);
     142            1 :   manager.write_to_active_buffer();
     143              :   
     144            1 :   auto result = manager.switch_buffer_and_read();
     145              :   
     146            1 :   BOOST_TEST(result.m_size == 3);
     147            1 :   BOOST_REQUIRE(result.m_data != nullptr);
     148              :   
     149              :   // Check each item
     150            1 :   int16_t expected_values[3] = {10, 20, 30};
     151            4 :   for (size_t item = 0; item < 3; ++item) {
     152            3 :     int16_t out[16];
     153            3 :     _mm256_storeu_si256(reinterpret_cast<__m256i*>(&out), result.m_data[item]);
     154              :     
     155           51 :     for (int i = 0; i < 16; i++) {
     156           48 :       BOOST_TEST(out[i] == expected_values[item]);
     157              :     }
     158              :   }
     159            1 : }
     160              : 
     161            2 : BOOST_AUTO_TEST_CASE(test_data_update_between_writes)
     162              : {
     163            1 :   ProcessorInternalStateNameRegistry<__m256i> registry;
     164            1 :   __m256i state = _mm256_set1_epi16(100);
     165            1 :   auto state_ptr = std::make_shared<__m256i>(state);
     166              :   
     167            1 :   registry.register_internal_state("state", state_ptr);
     168            1 :   registry.parse_requested_internal_state_items("state");
     169              :   
     170            1 :   ProcessorInternalStateBufferManager<__m256i> manager;
     171            1 :   manager.configure_from_registry(&registry);
     172              :   
     173              :   // First write
     174            1 :   manager.write_to_active_buffer();
     175            1 :   auto result1 = manager.switch_buffer_and_read();
     176              :   
     177            1 :   int16_t out1[16];
     178            1 :   _mm256_storeu_si256(reinterpret_cast<__m256i*>(&out1), result1.m_data[0]);
     179            1 :   BOOST_TEST(out1[0] == 100);
     180              :   
     181              :   // Modify the state
     182            1 :   *state_ptr = _mm256_set1_epi16(200);
     183              :   
     184              :   // Second write
     185            1 :   manager.write_to_active_buffer();
     186            1 :   auto result2 = manager.switch_buffer_and_read();
     187              :   
     188            1 :   int16_t out2[16];
     189            1 :   _mm256_storeu_si256(reinterpret_cast<__m256i*>(&out2), result2.m_data[0]);
     190            1 :   BOOST_TEST(out2[0] == 200);
     191            1 : }
     192              : 
     193            2 : BOOST_AUTO_TEST_CASE(test_multiple_consecutive_writes)
     194              : {
     195            1 :   ProcessorInternalStateNameRegistry<__m256i> registry;
     196            1 :   __m256i state = _mm256_set1_epi16(1);
     197            1 :   auto state_ptr = std::make_shared<__m256i>(state);
     198              :   
     199            1 :   registry.register_internal_state("state", state_ptr);
     200            1 :   registry.parse_requested_internal_state_items("state");
     201              :   
     202            1 :   ProcessorInternalStateBufferManager<__m256i> manager;
     203            1 :   manager.configure_from_registry(&registry);
     204              :   
     205              :   // Multiple writes without reads
     206            6 :   for (int i = 1; i <= 5; ++i) {
     207            5 :     *state_ptr = _mm256_set1_epi16(i * 10);
     208            5 :     manager.write_to_active_buffer();
     209              :   }
     210              :   
     211              :   // Read should get the last written value
     212            1 :   auto result = manager.switch_buffer_and_read();
     213              :   
     214            1 :   int16_t out[16];
     215            1 :   _mm256_storeu_si256(reinterpret_cast<__m256i*>(&out), result.m_data[0]);
     216            1 :   BOOST_TEST(out[0] == 50); // Last value (5 * 10)
     217            1 : }
     218              : 
     219            2 : BOOST_AUTO_TEST_CASE(test_casted_read)
     220              : {
     221            1 :   ProcessorInternalStateNameRegistry<__m256i> registry;
     222            1 :   __m256i a = _mm256_set1_epi16(123);
     223            1 :   auto a_ptr = std::make_shared<__m256i>(a);
     224              :   
     225            1 :   registry.register_internal_state("a", a_ptr);
     226            1 :   registry.parse_requested_internal_state_items("a");
     227              :   
     228            1 :   ProcessorInternalStateBufferManager<__m256i> manager;
     229            1 :   manager.configure_from_registry(&registry);
     230            1 :   manager.write_to_active_buffer();
     231              :   
     232            1 :   auto result = manager.switch_buffer_and_read_casted();
     233              :   
     234            1 :   BOOST_TEST(result.m_size == 1);
     235            1 :   BOOST_REQUIRE(result.m_data != nullptr);
     236              :   
     237              :   // Check all 16 values in the array
     238           17 :   for (int i = 0; i < 16; i++) {
     239           16 :     BOOST_TEST(result.m_data[0][i] == 123);
     240              :   }
     241            1 : }
     242              : 
     243            2 : BOOST_AUTO_TEST_CASE(test_multiple_reads_without_write)
     244              : {
     245            1 :   ProcessorInternalStateNameRegistry<__m256i> registry;
     246            1 :   __m256i state = _mm256_set1_epi16(777);
     247            1 :   auto state_ptr = std::make_shared<__m256i>(state);
     248              :   
     249            1 :   registry.register_internal_state("state", state_ptr);
     250            1 :   registry.parse_requested_internal_state_items("state");
     251              :   
     252            1 :   ProcessorInternalStateBufferManager<__m256i> manager;
     253            1 :   manager.configure_from_registry(&registry);
     254            1 :   manager.write_to_active_buffer();
     255              :   
     256              :   // Multiple reads
     257            4 :   for (int i = 0; i < 3; ++i) {
     258            3 :     auto result = manager.switch_buffer_and_read();
     259            3 :     int16_t out[16];
     260            3 :     _mm256_storeu_si256(reinterpret_cast<__m256i*>(&out), result.m_data[0]);
     261            3 :     BOOST_TEST(out[0] == 777);
     262              :   }
     263            1 : }
     264              : 
     265              : BOOST_AUTO_TEST_SUITE_END()
     266              : 
     267              : // =============================================================================
     268              : // THREAD SAFETY TESTS
     269              : // =============================================================================
     270              : 
     271              : BOOST_AUTO_TEST_SUITE(thread_safety_tests)
     272              : 
     273            2 : BOOST_AUTO_TEST_CASE(test_concurrent_single_writer_single_reader)
     274              : {
     275            1 :   ProcessorInternalStateNameRegistry<__m256i> registry;
     276            1 :   __m256i state = _mm256_set1_epi16(0);
     277            1 :   auto state_ptr = std::make_shared<__m256i>(state);
     278              :   
     279            1 :   registry.register_internal_state("state", state_ptr);
     280            1 :   registry.parse_requested_internal_state_items("state");
     281              :   
     282            1 :   ProcessorInternalStateBufferManager<__m256i> manager;
     283            1 :   manager.configure_from_registry(&registry);
     284              :   
     285            1 :   std::atomic<bool> done{false};
     286            1 :   std::atomic<int> write_count{0};
     287            1 :   std::atomic<int> read_count{0};
     288              :   
     289              :   // Writer thread
     290            3 :   std::thread writer([&]() {
     291         1001 :     for (int i = 0; i < 1000; ++i) {
     292         1000 :       *state_ptr = _mm256_set1_epi16(i);
     293         1000 :       manager.write_to_active_buffer();
     294         1000 :       write_count++;
     295         1000 :       std::this_thread::sleep_for(std::chrono::microseconds(10));
     296              :     }
     297            1 :     done.store(true, std::memory_order_release);
     298            2 :   });
     299              :   
     300              :   // Reader thread
     301            3 :   std::thread reader([&]() {
     302          935 :     while (!done.load(std::memory_order_acquire)) {
     303          934 :       auto result = manager.switch_buffer_and_read();
     304          934 :       if (result.m_data != nullptr) {
     305          934 :         read_count++;
     306              :       }
     307          934 :       std::this_thread::sleep_for(std::chrono::microseconds(15));
     308              :     }
     309            2 :   });
     310              :   
     311            1 :   writer.join();
     312            1 :   reader.join();
     313              :   
     314            1 :   BOOST_TEST(write_count == 1000);
     315            1 :   BOOST_TEST(read_count > 0);
     316            1 : }
     317              : 
     318            2 : BOOST_AUTO_TEST_CASE(test_concurrent_single_writer_multiple_readers)
     319              : {
     320            1 :   ProcessorInternalStateNameRegistry<__m256i> registry;
     321            1 :   __m256i state = _mm256_set1_epi16(0);
     322            1 :   auto state_ptr = std::make_shared<__m256i>(state);
     323              :   
     324            1 :   registry.register_internal_state("state", state_ptr);
     325            1 :   registry.parse_requested_internal_state_items("state");
     326              :   
     327            1 :   ProcessorInternalStateBufferManager<__m256i> manager;
     328            1 :   manager.configure_from_registry(&registry);
     329              :   
     330            1 :   std::atomic<bool> done{false};
     331            1 :   std::atomic<int> total_reads{0};
     332            1 :   const int num_readers = 3;
     333              :   
     334              :   // Writer thread
     335            3 :   std::thread writer([&]() {
     336          501 :     for (int i = 0; i < 500; ++i) {
     337          500 :       *state_ptr = _mm256_set1_epi16(i);
     338          500 :       manager.write_to_active_buffer();
     339          500 :       std::this_thread::sleep_for(std::chrono::microseconds(20));
     340              :     }
     341            1 :     done.store(true, std::memory_order_release);
     342            2 :   });
     343              :   
     344              :   // Multiple reader threads
     345            1 :   std::vector<std::thread> readers;
     346            4 :   for (int r = 0; r < num_readers; ++r) {
     347            6 :     readers.emplace_back([&]() {
     348            3 :       int local_reads = 0;
     349         1381 :       while (!done.load(std::memory_order_acquire)) {
     350         1375 :         auto result = manager.switch_buffer_and_read();
     351         1373 :         if (result.m_data != nullptr) {
     352         1373 :           local_reads++;
     353              :         }
     354         1373 :         std::this_thread::sleep_for(std::chrono::microseconds(30));
     355              :       }
     356            3 :       total_reads.fetch_add(local_reads);
     357            3 :     });
     358              :   }
     359              :   
     360            1 :   writer.join();
     361            4 :   for (auto& reader : readers) {
     362            3 :     reader.join();
     363              :   }
     364              :   
     365            1 :   BOOST_TEST(total_reads > 0);
     366            1 : }
     367              : 
     368            2 : BOOST_AUTO_TEST_CASE(test_stress_many_operations)
     369              : {
     370            1 :   ProcessorInternalStateNameRegistry<__m256i> registry;
     371            1 :   __m256i a = _mm256_set1_epi16(0);
     372            1 :   __m256i b = _mm256_set1_epi16(0);
     373              :   
     374            1 :   auto a_ptr = std::make_shared<__m256i>(a);
     375            1 :   auto b_ptr = std::make_shared<__m256i>(b);
     376              :   
     377            1 :   registry.register_internal_state("a", a_ptr);
     378            1 :   registry.register_internal_state("b", b_ptr);
     379            1 :   registry.parse_requested_internal_state_items("a,b");
     380              :   
     381            1 :   ProcessorInternalStateBufferManager<__m256i> manager;
     382            1 :   manager.configure_from_registry(&registry);
     383              :   
     384            1 :   std::atomic<bool> done{false};
     385              :   
     386              :   // High-frequency writer
     387            3 :   std::thread writer([&]() {
     388        10001 :     for (int i = 0; i < 10000; ++i) {
     389        10000 :       *a_ptr = _mm256_set1_epi16(i % 1000);
     390        10000 :       *b_ptr = _mm256_set1_epi16((i * 2) % 1000);
     391        10000 :       manager.write_to_active_buffer();
     392              :     }
     393            1 :     done.store(true, std::memory_order_release);
     394            2 :   });
     395              :   
     396              :   // High-frequency reader
     397            3 :   std::thread reader([&]() {
     398            1 :     int successful_reads = 0;
     399         3215 :     while (!done.load(std::memory_order_acquire)) {
     400         3214 :       auto result = manager.switch_buffer_and_read();
     401         3214 :       if (result.m_data != nullptr && result.m_size == 2) {
     402         3214 :         successful_reads++;
     403              :       }
     404              :     }
     405            1 :     BOOST_TEST(successful_reads > 0);
     406            2 :   });
     407              :   
     408            1 :   writer.join();
     409            1 :   reader.join();
     410              :   
     411            1 :   BOOST_TEST(true); // Test passes if no crashes
     412            1 : }
     413              : 
     414            2 : BOOST_AUTO_TEST_CASE(test_casted_read_thread_safety)
     415              : {
     416            1 :   ProcessorInternalStateNameRegistry<__m256i> registry;
     417            1 :   __m256i state = _mm256_set1_epi16(0);
     418            1 :   auto state_ptr = std::make_shared<__m256i>(state);
     419              :   
     420            1 :   registry.register_internal_state("state", state_ptr);
     421            1 :   registry.parse_requested_internal_state_items("state");
     422              :   
     423            1 :   ProcessorInternalStateBufferManager<__m256i> manager;
     424            1 :   manager.configure_from_registry(&registry);
     425              :   
     426            1 :   std::atomic<bool> done{false};
     427              :   
     428              :   // Writer thread
     429            3 :   std::thread writer([&]() {
     430         1001 :     for (int i = 0; i < 1000; ++i) {
     431         1000 :       *state_ptr = _mm256_set1_epi16(i);
     432         1000 :       manager.write_to_active_buffer();
     433         1000 :       std::this_thread::sleep_for(std::chrono::microseconds(10));
     434              :     }
     435            1 :     done.store(true, std::memory_order_release);
     436            2 :   });
     437              :   
     438              :   // Reader using casted read
     439            3 :   std::thread reader([&]() {
     440            1 :     int successful_reads = 0;
     441          928 :     while (!done.load(std::memory_order_acquire)) {
     442          927 :       auto result = manager.switch_buffer_and_read_casted();
     443          927 :       if (result.m_data != nullptr) {
     444          927 :         successful_reads++;
     445              :       }
     446          927 :       std::this_thread::sleep_for(std::chrono::microseconds(15));
     447              :     }
     448            1 :     BOOST_TEST(successful_reads > 0);
     449            2 :   });
     450              :   
     451            1 :   writer.join();
     452            1 :   reader.join();
     453              :   
     454            1 :   BOOST_TEST(true);
     455            1 : }
     456              : 
     457              : BOOST_AUTO_TEST_SUITE_END()
     458              : 
     459              : // =============================================================================
     460              : // EDGE CASE TESTS
     461              : // =============================================================================
     462              : 
     463              : BOOST_AUTO_TEST_SUITE(edge_case_tests)
     464              : 
     465            2 : BOOST_AUTO_TEST_CASE(test_read_before_any_write)
     466              : {
     467            1 :   ProcessorInternalStateNameRegistry<__m256i> registry;
     468            1 :   __m256i state = _mm256_set1_epi16(555);
     469            1 :   auto state_ptr = std::make_shared<__m256i>(state);
     470              :   
     471            1 :   registry.register_internal_state("state", state_ptr);
     472            1 :   registry.parse_requested_internal_state_items("state");
     473              :   
     474            1 :   ProcessorInternalStateBufferManager<__m256i> manager;
     475            1 :   manager.configure_from_registry(&registry);
     476              :   
     477              :   // Read without writing first - should not crash
     478            1 :   auto result = manager.switch_buffer_and_read();
     479            1 :   BOOST_TEST(result.m_data != nullptr);
     480            1 : }
     481              : 
     482            2 : BOOST_AUTO_TEST_CASE(test_alternating_write_read_pattern)
     483              : {
     484            1 :   ProcessorInternalStateNameRegistry<__m256i> registry;
     485            1 :   __m256i state = _mm256_set1_epi16(0);
     486            1 :   auto state_ptr = std::make_shared<__m256i>(state);
     487              :   
     488            1 :   registry.register_internal_state("state", state_ptr);
     489            1 :   registry.parse_requested_internal_state_items("state");
     490              :   
     491            1 :   ProcessorInternalStateBufferManager<__m256i> manager;
     492            1 :   manager.configure_from_registry(&registry);
     493              :   
     494              :   // Alternating write-read pattern
     495           11 :   for (int i = 0; i < 10; ++i) {
     496           10 :     *state_ptr = _mm256_set1_epi16(i * 10);
     497           10 :     manager.write_to_active_buffer();
     498              :     
     499           10 :     auto result = manager.switch_buffer_and_read();
     500           10 :     int16_t out[16];
     501           10 :     _mm256_storeu_si256(reinterpret_cast<__m256i*>(&out), result.m_data[0]);
     502           10 :     BOOST_TEST(out[0] == i * 10);
     503              :   }
     504            1 : }
     505              : 
     506            2 : BOOST_AUTO_TEST_CASE(test_rapid_buffer_switching)
     507              : {
     508            1 :   ProcessorInternalStateNameRegistry<__m256i> registry;
     509            1 :   __m256i state = _mm256_set1_epi16(999);
     510            1 :   auto state_ptr = std::make_shared<__m256i>(state);
     511              :   
     512            1 :   registry.register_internal_state("state", state_ptr);
     513            1 :   registry.parse_requested_internal_state_items("state");
     514              :   
     515            1 :   ProcessorInternalStateBufferManager<__m256i> manager;
     516            1 :   manager.configure_from_registry(&registry);
     517            1 :   manager.write_to_active_buffer();
     518              :   
     519              :   // Rapid consecutive reads (buffer switches)
     520          101 :   for (int i = 0; i < 100; ++i) {
     521          100 :     auto result = manager.switch_buffer_and_read();
     522          100 :     BOOST_TEST(result.m_data != nullptr);
     523          100 :     BOOST_TEST(result.m_size == 1);
     524              :   }
     525            1 : }
     526              : 
     527            2 : BOOST_AUTO_TEST_CASE(test_partial_item_selection)
     528              : {
     529            1 :   ProcessorInternalStateNameRegistry<__m256i> registry;
     530              :   
     531            1 :   __m256i a = _mm256_set1_epi16(10);
     532            1 :   __m256i b = _mm256_set1_epi16(20);
     533            1 :   __m256i c = _mm256_set1_epi16(30);
     534              :   
     535            1 :   auto a_ptr = std::make_shared<__m256i>(a);
     536            1 :   auto b_ptr = std::make_shared<__m256i>(b);
     537            1 :   auto c_ptr = std::make_shared<__m256i>(c);
     538              :   
     539            1 :   registry.register_internal_state("a", a_ptr);
     540            1 :   registry.register_internal_state("b", b_ptr);
     541            1 :   registry.register_internal_state("c", c_ptr);
     542              :   
     543              :   // Only request a subset of registered items
     544            1 :   registry.parse_requested_internal_state_items("a,c");
     545              :   
     546            1 :   ProcessorInternalStateBufferManager<__m256i> manager;
     547            1 :   manager.configure_from_registry(&registry);
     548            1 :   manager.write_to_active_buffer();
     549              :   
     550            1 :   auto result = manager.switch_buffer_and_read();
     551              :   
     552              :   // Should only have 2 items (a and c)
     553            1 :   BOOST_TEST(result.m_size == 2);
     554              :   
     555            1 :   int16_t out0[16], out1[16];
     556            1 :   _mm256_storeu_si256(reinterpret_cast<__m256i*>(&out0), result.m_data[0]);
     557            1 :   _mm256_storeu_si256(reinterpret_cast<__m256i*>(&out1), result.m_data[1]);
     558              :   
     559            1 :   BOOST_TEST(out0[0] == 10); // a
     560            1 :   BOOST_TEST(out1[0] == 30); // c
     561            1 : }
     562              : 
     563            2 : BOOST_AUTO_TEST_CASE(test_large_number_of_items)
     564              : {
     565            1 :   ProcessorInternalStateNameRegistry<__m256i> registry;
     566              :   
     567            1 :   const int num_items = 20;
     568            1 :   std::vector<std::shared_ptr<__m256i>> ptrs;
     569            1 :   std::string request_string;
     570              :   
     571           21 :   for (int i = 0; i < num_items; ++i) {
     572           20 :     __m256i val = _mm256_set1_epi16(i * 100);
     573           20 :     auto ptr = std::make_shared<__m256i>(val);
     574           20 :     ptrs.push_back(ptr);
     575              :     
     576           20 :     std::string name = "state_" + std::to_string(i);
     577           20 :     registry.register_internal_state(name, ptr);
     578              :     
     579           20 :     if (i > 0) request_string += ",";
     580           20 :     request_string += name;
     581           20 :   }
     582              :   
     583            1 :   registry.parse_requested_internal_state_items(request_string);
     584              :   
     585            1 :   ProcessorInternalStateBufferManager<__m256i> manager;
     586            1 :   manager.configure_from_registry(&registry);
     587            1 :   manager.write_to_active_buffer();
     588              :   
     589            1 :   auto result = manager.switch_buffer_and_read();
     590              :   
     591            1 :   BOOST_TEST(result.m_size == num_items);
     592              :   
     593              :   // Verify each item
     594           21 :   for (int i = 0; i < num_items; ++i) {
     595           20 :     int16_t out[16];
     596           20 :     _mm256_storeu_si256(reinterpret_cast<__m256i*>(&out), result.m_data[i]);
     597           20 :     BOOST_TEST(out[0] == i * 100);
     598              :   }
     599            1 : }
     600              : 
     601            2 : BOOST_AUTO_TEST_CASE(test_data_consistency_after_multiple_switches)
     602              : {
     603            1 :   ProcessorInternalStateNameRegistry<__m256i> registry;
     604            1 :   __m256i state = _mm256_set1_epi16(12345);
     605            1 :   auto state_ptr = std::make_shared<__m256i>(state);
     606              :   
     607            1 :   registry.register_internal_state("state", state_ptr);
     608            1 :   registry.parse_requested_internal_state_items("state");
     609              :   
     610            1 :   ProcessorInternalStateBufferManager<__m256i> manager;
     611            1 :   manager.configure_from_registry(&registry);
     612              :   
     613              :   // Write once
     614            1 :   manager.write_to_active_buffer();
     615              :   
     616              :   // Multiple reads - data should remain consistent
     617            6 :   for (int i = 0; i < 5; ++i) {
     618            5 :     auto result = manager.switch_buffer_and_read();
     619            5 :     int16_t out[16];
     620            5 :     _mm256_storeu_si256(reinterpret_cast<__m256i*>(&out), result.m_data[0]);
     621            5 :     BOOST_TEST(out[0] == 12345);
     622              :   }
     623            1 : }
     624              : 
     625              : BOOST_AUTO_TEST_SUITE_END()
     626              : 
     627              : } // namespace tpglibs
     628              :  
        

Generated by: LCOV version 2.0-1