LCOV - code coverage report
Current view: top level - tpglibs/unittest - processor_state_registrate_collect_test.cxx (source / functions) Coverage Total Hit
Test: code.result Lines: 99.4 % 697 693
Test Date: 2025-12-21 13:07:08 Functions: 97.9 % 48 47

            Line data    Source code
       1              : /**
       2              :  * @file processor_state_registrate_collect_test.cxx
       3              :  *
       4              :  * @brief Comprehensive unit tests for internal state registration and collection
       5              :  *        across all processors that support internal state monitoring
       6              :  *
       7              :  * @copyright This is part of the DUNE DAQ Software Suite, copyright 2020.
       8              :  * Licensing/copyright details are in the COPYING file that you should have
       9              :  * received with this code.
      10              :  */
      11              : 
      12              : #define BOOST_TEST_MODULE ProcessorStateRegistrationCollectionTest
      13              : #define FMT_HEADER_ONLY
      14              : 
      15              : #include "tpglibs/AVXRunSumProcessor.hpp"
      16              : #include "tpglibs/AVXAbsRunSumProcessor.hpp"
      17              : #include "tpglibs/AVXFrugalPedestalSubtractProcessor.hpp"
      18              : #include "tpglibs/NaiveRunSumProcessor.hpp"
      19              : #include "tpglibs/NaiveAbsRunSumProcessor.hpp"
      20              : #include "tpglibs/NaiveFrugalPedestalSubtractProcessor.hpp"
      21              : 
      22              : #include <boost/test/unit_test.hpp>
      23              : #include <immintrin.h>
      24              : #include <array>
      25              : #include <vector>
      26              : #include <memory>
      27              : 
      28              : namespace tpglibs {
      29              : 
      30              : // =============================================================================
      31              : // Helper Functions
      32              : // =============================================================================
      33              : 
      34              : // Helper function to create test signal for AVX processors
      35            4 : __m256i create_avx_test_signal(const int16_t values[16]) {
      36            4 :   return _mm256_set_epi16(
      37            4 :     values[15], values[14], values[13], values[12],
      38            4 :     values[11], values[10], values[9], values[8],
      39            4 :     values[7], values[6], values[5], values[4],
      40            4 :     values[3], values[2], values[1], values[0]
      41            4 :   );
      42              : }
      43              : 
      44              : // Helper function to create test signal for Naive processors
      45            3 : std::array<int16_t, 16> create_naive_test_signal(const int16_t values[16]) {
      46            3 :   std::array<int16_t, 16> signal;
      47           51 :   for (int i = 0; i < 16; ++i) {
      48           48 :     signal[i] = values[i];
      49              :   }
      50            3 :   return signal;
      51              : }
      52              : 
      53              : // Helper function to extract values from __m256i
      54            0 : void extract_avx_values(__m256i vec, int16_t output[16]) {
      55            0 :   _mm256_storeu_si256(reinterpret_cast<__m256i*>(output), vec);
      56            0 : }
      57              : 
      58              : // Helper function to create standard test configuration
      59           21 : nlohmann::json create_test_config(const std::string& requested_states = "") {
      60           21 :   nlohmann::json config = {
      61              :     {"metric_collect_toggle_state", true},
      62           42 :     {"metric_collect_time_sample_period", 1}  // Collect every sample
      63          147 :   };
      64              :   
      65           21 :   if (!requested_states.empty()) {
      66            0 :     config["requested_internal_states"] = requested_states;
      67              :   }
      68              :   
      69           21 :   return config;
      70          126 : }
      71              : 
      72              : // =============================================================================
      73              : // SECTION 1: AVXRunSumProcessor Tests
      74              : // =============================================================================
      75              : 
      76              : BOOST_AUTO_TEST_SUITE(AVXRunSumProcessorTests)
      77              : 
      78            2 : BOOST_AUTO_TEST_CASE(test_avx_runsum_configuration_and_registration) {
      79            1 :   auto processor = std::make_shared<AVXRunSumProcessor>();
      80            1 :   int16_t plane_numbers[16] = {0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2};
      81              : 
      82            1 :   auto config = create_test_config();
      83            1 :   config["requested_internal_states"] = "r,s,rs";
      84            1 :   config["memory_factor_plane0"] = 100;
      85            1 :   config["memory_factor_plane1"] = 200;
      86            1 :   config["memory_factor_plane2"] = 300;
      87            1 :   config["scale_factor_plane0"] = 10;
      88            1 :   config["scale_factor_plane1"] = 20;
      89            1 :   config["scale_factor_plane2"] = 30;
      90            1 :   config["memory_divisor_plane0"] = 10;
      91            1 :   config["memory_divisor_plane1"] = 10;
      92            1 :   config["memory_divisor_plane2"] = 10;
      93            1 :   config["scale_divisor_plane0"] = 10;
      94            1 :   config["scale_divisor_plane1"] = 10;
      95            1 :   config["scale_divisor_plane2"] = 10;
      96              : 
      97            1 :   processor->configure(config, plane_numbers);
      98              : 
      99              :   // Test that internal states are registered
     100            1 :   auto requested_states = processor->get_requested_internal_state_names();
     101            1 :   BOOST_TEST(requested_states.size() == 3);
     102            1 :   BOOST_TEST(requested_states[0] == "r");
     103            1 :   BOOST_TEST(requested_states[1] == "s");
     104            1 :   BOOST_TEST(requested_states[2] == "rs");
     105            1 : }
     106              : 
     107            2 : BOOST_AUTO_TEST_CASE(test_avx_runsum_initial_state_collection) {
     108            1 :   auto processor = std::make_shared<AVXRunSumProcessor>();
     109            1 :   int16_t plane_numbers[16] = {0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2};
     110              : 
     111            1 :   auto config = create_test_config();
     112            1 :   config["requested_internal_states"] = "r,s,rs";
     113            1 :   config["memory_factor_plane0"] = 100;
     114            1 :   config["memory_factor_plane1"] = 200;
     115            1 :   config["memory_factor_plane2"] = 300;
     116            1 :   config["scale_factor_plane0"] = 10;
     117            1 :   config["scale_factor_plane1"] = 20;
     118            1 :   config["scale_factor_plane2"] = 30;
     119            1 :   config["memory_divisor_plane0"] = 10;
     120            1 :   config["memory_divisor_plane1"] = 10;
     121            1 :   config["memory_divisor_plane2"] = 10;
     122            1 :   config["scale_divisor_plane0"] = 10;
     123            1 :   config["scale_divisor_plane1"] = 10;
     124            1 :   config["scale_divisor_plane2"] = 10;
     125              : 
     126            1 :   processor->configure(config, plane_numbers);
     127              : 
     128              :   // Collect initial state
     129            1 :   auto buffer_manager = processor->_get_internal_state_buffer_manager();
     130            1 :   buffer_manager->write_to_active_buffer();
     131            1 :   auto state_value = buffer_manager->switch_buffer_and_read_casted();
     132              : 
     133            1 :   BOOST_TEST(state_value.m_size == 3);
     134            1 :   BOOST_TEST(state_value.m_data != nullptr);
     135              : 
     136              :   // Check initial values
     137              :   // r (memory_factor) should be configured values
     138            1 :   int16_t expected_r[16] = {100, 100, 100, 100, 100, 200, 200, 200, 200, 200, 300, 300, 300, 300, 300, 300};
     139           17 :   for (int i = 0; i < 16; ++i) {
     140           16 :     BOOST_TEST(state_value.m_data[0][i] == expected_r[i]);
     141              :   }
     142              : 
     143              :   // s (scale_factor) should be configured values
     144            1 :   int16_t expected_s[16] = {10, 10, 10, 10, 10, 20, 20, 20, 20, 20, 30, 30, 30, 30, 30, 30};
     145           17 :   for (int i = 0; i < 16; ++i) {
     146           16 :     BOOST_TEST(state_value.m_data[1][i] == expected_s[i]);
     147              :   }
     148              : 
     149              :   // rs (running_sum) should be initialized to 0
     150           17 :   for (int i = 0; i < 16; ++i) {
     151           16 :     BOOST_TEST(state_value.m_data[2][i] == 0);
     152              :   }
     153            1 : }
     154              : 
     155            2 : BOOST_AUTO_TEST_CASE(test_avx_runsum_processing_and_state_update) {
     156            1 :   auto processor = std::make_shared<AVXRunSumProcessor>();
     157            1 :   int16_t plane_numbers[16] = {0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2};
     158              : 
     159            1 :   auto config = create_test_config();
     160            1 :   config["requested_internal_states"] = "rs";  // Only collect running sum
     161            1 :   config["memory_factor_plane0"] = 100;
     162            1 :   config["memory_factor_plane1"] = 200;
     163            1 :   config["memory_factor_plane2"] = 300;
     164            1 :   config["scale_factor_plane0"] = 10;
     165            1 :   config["scale_factor_plane1"] = 20;
     166            1 :   config["scale_factor_plane2"] = 30;
     167            1 :   config["memory_divisor_plane0"] = 10;
     168            1 :   config["memory_divisor_plane1"] = 10;
     169            1 :   config["memory_divisor_plane2"] = 10;
     170            1 :   config["scale_divisor_plane0"] = 10;
     171            1 :   config["scale_divisor_plane1"] = 10;
     172            1 :   config["scale_divisor_plane2"] = 10;
     173              : 
     174            1 :   processor->configure(config, plane_numbers);
     175              : 
     176              :   // Create test signal
     177              :   int16_t signal_values[16];
     178           17 :   for (int i = 0; i < 16; ++i) {
     179           16 :     signal_values[i] = 1000;  // Constant signal
     180              :   }
     181            1 :   __m256i signal = create_avx_test_signal(signal_values);
     182              : 
     183              :   // Process the signal twice - first call writes old state to buffer, second call updates state
     184            1 :   processor->process(signal);
     185            1 :   processor->process(signal);
     186              : 
     187              :   // Collect state after processing
     188            1 :   auto buffer_manager = processor->_get_internal_state_buffer_manager();
     189            1 :   auto state_value = buffer_manager->switch_buffer_and_read_casted();
     190              : 
     191            1 :   BOOST_TEST(state_value.m_size == 1);
     192            1 :   BOOST_TEST(state_value.m_data != nullptr);
     193              : 
     194              :   // Running sum should have been updated (non-zero)
     195            1 :   bool running_sum_updated = false;
     196            1 :   for (int i = 0; i < 16; ++i) {
     197            1 :     if (state_value.m_data[0][i] != 0) {
     198            1 :       running_sum_updated = true;
     199            1 :       break;
     200              :     }
     201              :   }
     202            1 :   BOOST_TEST(running_sum_updated);
     203            1 : }
     204              : 
     205              : BOOST_AUTO_TEST_SUITE_END()
     206              : 
     207              : // =============================================================================
     208              : // SECTION 2: AVXAbsRunSumProcessor Tests
     209              : // =============================================================================
     210              : 
     211              : BOOST_AUTO_TEST_SUITE(AVXAbsRunSumProcessorTests)
     212              : 
     213            2 : BOOST_AUTO_TEST_CASE(test_avx_abs_runsum_inherits_registration) {
     214            1 :   auto processor = std::make_shared<AVXAbsRunSumProcessor>();
     215            1 :   int16_t plane_numbers[16] = {0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2};
     216              : 
     217            1 :   auto config = create_test_config();
     218            1 :   config["requested_internal_states"] = "r,s,rs";
     219            1 :   config["memory_factor_plane0"] = 100;
     220            1 :   config["memory_factor_plane1"] = 200;
     221            1 :   config["memory_factor_plane2"] = 300;
     222            1 :   config["scale_factor_plane0"] = 10;
     223            1 :   config["scale_factor_plane1"] = 20;
     224            1 :   config["scale_factor_plane2"] = 30;
     225            1 :   config["memory_divisor_plane0"] = 10;
     226            1 :   config["memory_divisor_plane1"] = 10;
     227            1 :   config["memory_divisor_plane2"] = 10;
     228            1 :   config["scale_divisor_plane0"] = 10;
     229            1 :   config["scale_divisor_plane1"] = 10;
     230            1 :   config["scale_divisor_plane2"] = 10;
     231              : 
     232            1 :   processor->configure(config, plane_numbers);
     233              : 
     234              :   // Should inherit the same internal state registration as parent
     235            1 :   auto requested_states = processor->get_requested_internal_state_names();
     236            1 :   BOOST_TEST(requested_states.size() == 3);
     237            1 :   BOOST_TEST(requested_states[0] == "r");
     238            1 :   BOOST_TEST(requested_states[1] == "s");
     239            1 :   BOOST_TEST(requested_states[2] == "rs");
     240            1 : }
     241              : 
     242            2 : BOOST_AUTO_TEST_CASE(test_avx_abs_runsum_processing_with_absolute_values) {
     243            1 :   auto processor = std::make_shared<AVXAbsRunSumProcessor>();
     244            1 :   int16_t plane_numbers[16] = {0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2};
     245              : 
     246            1 :   auto config = create_test_config();
     247            1 :   config["requested_internal_states"] = "rs";
     248            1 :   config["memory_factor_plane0"] = 100;
     249            1 :   config["memory_factor_plane1"] = 200;
     250            1 :   config["memory_factor_plane2"] = 300;
     251            1 :   config["scale_factor_plane0"] = 10;
     252            1 :   config["scale_factor_plane1"] = 20;
     253            1 :   config["scale_factor_plane2"] = 30;
     254            1 :   config["memory_divisor_plane0"] = 10;
     255            1 :   config["memory_divisor_plane1"] = 10;
     256            1 :   config["memory_divisor_plane2"] = 10;
     257            1 :   config["scale_divisor_plane0"] = 10;
     258            1 :   config["scale_divisor_plane1"] = 10;
     259            1 :   config["scale_divisor_plane2"] = 10;
     260              : 
     261            1 :   processor->configure(config, plane_numbers);
     262              : 
     263              :   // Create test signal with negative values
     264              :   int16_t signal_values[16];
     265           17 :   for (int i = 0; i < 16; ++i) {
     266           16 :     signal_values[i] = -1000;  // Negative signal
     267              :   }
     268            1 :   __m256i signal = create_avx_test_signal(signal_values);
     269              : 
     270              :   // Process the signal twice - first call writes old state to buffer, second call updates state
     271            1 :   processor->process(signal);
     272            1 :   processor->process(signal);
     273              : 
     274              :   // Collect state after processing
     275            1 :   auto buffer_manager = processor->_get_internal_state_buffer_manager();
     276            1 :   auto state_value = buffer_manager->switch_buffer_and_read_casted();
     277              : 
     278            1 :   BOOST_TEST(state_value.m_size == 1);
     279            1 :   BOOST_TEST(state_value.m_data != nullptr);
     280              : 
     281              :   // Running sum should have been updated (non-zero)
     282            1 :   bool running_sum_updated = false;
     283            1 :   for (int i = 0; i < 16; ++i) {
     284            1 :     if (state_value.m_data[0][i] != 0) {
     285            1 :       running_sum_updated = true;
     286            1 :       break;
     287              :     }
     288              :   }
     289            1 :   BOOST_TEST(running_sum_updated);
     290            1 : }
     291              : 
     292              : BOOST_AUTO_TEST_SUITE_END()
     293              : 
     294              : // =============================================================================
     295              : // SECTION 3: NaiveRunSumProcessor Tests
     296              : // =============================================================================
     297              : 
     298              : BOOST_AUTO_TEST_SUITE(NaiveRunSumProcessorTests)
     299              : 
     300            2 : BOOST_AUTO_TEST_CASE(test_naive_runsum_configuration_and_registration) {
     301            1 :   auto processor = std::make_shared<NaiveRunSumProcessor>();
     302            1 :   int16_t plane_numbers[16] = {0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2};
     303              : 
     304            1 :   auto config = create_test_config();
     305            1 :   config["requested_internal_states"] = "r,s,rs";
     306            1 :   config["memory_factor_plane0"] = 100;
     307            1 :   config["memory_factor_plane1"] = 200;
     308            1 :   config["memory_factor_plane2"] = 300;
     309            1 :   config["scale_factor_plane0"] = 10;
     310            1 :   config["scale_factor_plane1"] = 20;
     311            1 :   config["scale_factor_plane2"] = 30;
     312            1 :   config["memory_divisor_plane0"] = 10;
     313            1 :   config["memory_divisor_plane1"] = 10;
     314            1 :   config["memory_divisor_plane2"] = 10;
     315            1 :   config["scale_divisor_plane0"] = 10;
     316            1 :   config["scale_divisor_plane1"] = 10;
     317            1 :   config["scale_divisor_plane2"] = 10;
     318              : 
     319            1 :   processor->configure(config, plane_numbers);
     320              : 
     321              :   // Test that internal states are registered
     322            1 :   auto requested_states = processor->get_requested_internal_state_names();
     323            1 :   BOOST_TEST(requested_states.size() == 3);
     324            1 :   BOOST_TEST(requested_states[0] == "r");
     325            1 :   BOOST_TEST(requested_states[1] == "s");
     326            1 :   BOOST_TEST(requested_states[2] == "rs");
     327            1 : }
     328              : 
     329            2 : BOOST_AUTO_TEST_CASE(test_naive_runsum_initial_state_collection) {
     330            1 :   auto processor = std::make_shared<NaiveRunSumProcessor>();
     331            1 :   int16_t plane_numbers[16] = {0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2};
     332              : 
     333            1 :   auto config = create_test_config();
     334            1 :   config["requested_internal_states"] = "r,s,rs";
     335            1 :   config["memory_factor_plane0"] = 100;
     336            1 :   config["memory_factor_plane1"] = 200;
     337            1 :   config["memory_factor_plane2"] = 300;
     338            1 :   config["scale_factor_plane0"] = 10;
     339            1 :   config["scale_factor_plane1"] = 20;
     340            1 :   config["scale_factor_plane2"] = 30;
     341            1 :   config["memory_divisor_plane0"] = 10;
     342            1 :   config["memory_divisor_plane1"] = 10;
     343            1 :   config["memory_divisor_plane2"] = 10;
     344            1 :   config["scale_divisor_plane0"] = 10;
     345            1 :   config["scale_divisor_plane1"] = 10;
     346            1 :   config["scale_divisor_plane2"] = 10;
     347              : 
     348            1 :   processor->configure(config, plane_numbers);
     349              : 
     350              :   // Collect initial state
     351            1 :   auto buffer_manager = processor->_get_internal_state_buffer_manager();
     352            1 :   buffer_manager->write_to_active_buffer();
     353            1 :   auto state_value = buffer_manager->switch_buffer_and_read_casted();
     354              : 
     355            1 :   BOOST_TEST(state_value.m_size == 3);
     356            1 :   BOOST_TEST(state_value.m_data != nullptr);
     357              : 
     358              :   // Check initial values
     359              :   // r (memory_factor) should be configured values
     360            1 :   int16_t expected_r[16] = {100, 100, 100, 100, 100, 200, 200, 200, 200, 200, 300, 300, 300, 300, 300, 300};
     361           17 :   for (int i = 0; i < 16; ++i) {
     362           16 :     BOOST_TEST(state_value.m_data[0][i] == expected_r[i]);
     363              :   }
     364              : 
     365              :   // s (scale_factor) should be configured values
     366            1 :   int16_t expected_s[16] = {10, 10, 10, 10, 10, 20, 20, 20, 20, 20, 30, 30, 30, 30, 30, 30};
     367           17 :   for (int i = 0; i < 16; ++i) {
     368           16 :     BOOST_TEST(state_value.m_data[1][i] == expected_s[i]);
     369              :   }
     370              : 
     371              :   // rs (running_sum) should be initialized to 0
     372           17 :   for (int i = 0; i < 16; ++i) {
     373           16 :     BOOST_TEST(state_value.m_data[2][i] == 0);
     374              :   }
     375            1 : }
     376              : 
     377            2 : BOOST_AUTO_TEST_CASE(test_naive_runsum_processing_and_state_update) {
     378            1 :   auto processor = std::make_shared<NaiveRunSumProcessor>();
     379            1 :   int16_t plane_numbers[16] = {0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2};
     380              : 
     381            1 :   auto config = create_test_config();
     382            1 :   config["requested_internal_states"] = "rs";  // Only collect running sum
     383            1 :   config["memory_factor_plane0"] = 100;
     384            1 :   config["memory_factor_plane1"] = 200;
     385            1 :   config["memory_factor_plane2"] = 300;
     386            1 :   config["scale_factor_plane0"] = 10;
     387            1 :   config["scale_factor_plane1"] = 20;
     388            1 :   config["scale_factor_plane2"] = 30;
     389            1 :   config["memory_divisor_plane0"] = 10;
     390            1 :   config["memory_divisor_plane1"] = 10;
     391            1 :   config["memory_divisor_plane2"] = 10;
     392            1 :   config["scale_divisor_plane0"] = 10;
     393            1 :   config["scale_divisor_plane1"] = 10;
     394            1 :   config["scale_divisor_plane2"] = 10;
     395              : 
     396            1 :   processor->configure(config, plane_numbers);
     397              : 
     398              :   // Create test signal
     399              :   int16_t signal_values[16];
     400           17 :   for (int i = 0; i < 16; ++i) {
     401           16 :     signal_values[i] = 1000;  // Constant signal
     402              :   }
     403            1 :   auto signal = create_naive_test_signal(signal_values);
     404              : 
     405              :   // Process the signal twice - first call writes old state to buffer, second call updates state
     406            1 :   processor->process(signal);
     407            1 :   processor->process(signal);
     408              : 
     409              :   // Collect state after processing
     410            1 :   auto buffer_manager = processor->_get_internal_state_buffer_manager();
     411            1 :   auto state_value = buffer_manager->switch_buffer_and_read_casted();
     412              : 
     413            1 :   BOOST_TEST(state_value.m_size == 1);
     414            1 :   BOOST_TEST(state_value.m_data != nullptr);
     415              : 
     416              :   // Running sum should have been updated (non-zero)
     417            1 :   bool running_sum_updated = false;
     418            1 :   for (int i = 0; i < 16; ++i) {
     419            1 :     if (state_value.m_data[0][i] != 0) {
     420            1 :       running_sum_updated = true;
     421            1 :       break;
     422              :     }
     423              :   }
     424            1 :   BOOST_TEST(running_sum_updated);
     425            1 : }
     426              : 
     427              : BOOST_AUTO_TEST_SUITE_END()
     428              : 
     429              : // =============================================================================
     430              : // SECTION 4: AVXFrugalPedestalSubtractProcessor Tests
     431              : // =============================================================================
     432              : 
     433              : BOOST_AUTO_TEST_SUITE(AVXFrugalPedestalSubtractProcessorTests)
     434              : 
     435            2 : BOOST_AUTO_TEST_CASE(test_avx_frugal_configuration_and_registration) {
     436            1 :   auto processor = std::make_shared<AVXFrugalPedestalSubtractProcessor>();
     437            1 :   int16_t plane_numbers[16] = {0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2};
     438              : 
     439            1 :   auto config = create_test_config();
     440            1 :   config["requested_internal_states"] = "pedestal,accum";
     441            1 :   config["accum_limit"] = 10;
     442              : 
     443            1 :   processor->configure(config, plane_numbers);
     444              : 
     445              :   // Test that internal states are registered
     446            1 :   auto requested_states = processor->get_requested_internal_state_names();
     447            1 :   BOOST_TEST(requested_states.size() == 2);
     448            1 :   BOOST_TEST(requested_states[0] == "pedestal");
     449            1 :   BOOST_TEST(requested_states[1] == "accum");
     450            1 : }
     451              : 
     452            2 : BOOST_AUTO_TEST_CASE(test_avx_frugal_initial_state_collection) {
     453            1 :   auto processor = std::make_shared<AVXFrugalPedestalSubtractProcessor>();
     454            1 :   int16_t plane_numbers[16] = {0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2};
     455              : 
     456            1 :   auto config = create_test_config();
     457            1 :   config["requested_internal_states"] = "pedestal,accum";
     458            1 :   config["accum_limit"] = 10;
     459              : 
     460            1 :   processor->configure(config, plane_numbers);
     461              : 
     462              :   // Collect initial state
     463            1 :   auto buffer_manager = processor->_get_internal_state_buffer_manager();
     464            1 :   buffer_manager->write_to_active_buffer();
     465            1 :   auto state_value = buffer_manager->switch_buffer_and_read_casted();
     466              : 
     467            1 :   BOOST_TEST(state_value.m_size == 2);
     468            1 :   BOOST_TEST(state_value.m_data != nullptr);
     469              : 
     470              :   // Check initial values
     471              :   // pedestal should be initialized to 0x4000 (16384) - 14-bit max
     472           17 :   for (int i = 0; i < 16; ++i) {
     473           16 :     BOOST_TEST(state_value.m_data[0][i] == 0x4000);
     474              :   }
     475              : 
     476              :   // accum should be initialized to 0
     477           17 :   for (int i = 0; i < 16; ++i) {
     478           16 :     BOOST_TEST(state_value.m_data[1][i] == 0);
     479              :   }
     480            1 : }
     481              : 
     482            2 : BOOST_AUTO_TEST_CASE(test_avx_frugal_processing_and_state_update) {
     483            1 :   auto processor = std::make_shared<AVXFrugalPedestalSubtractProcessor>();
     484            1 :   int16_t plane_numbers[16] = {0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2};
     485              : 
     486            1 :   auto config = create_test_config();
     487            1 :   config["requested_internal_states"] = "pedestal,accum";
     488            1 :   config["accum_limit"] = 3;  // Small limit for faster adaptation
     489              : 
     490            1 :   processor->configure(config, plane_numbers);
     491              : 
     492              :   // Create test signal consistently above initial pedestal
     493              :   int16_t signal_values[16];
     494           17 :   for (int i = 0; i < 16; ++i) {
     495           16 :     signal_values[i] = 0x5000;  // Above initial pedestal (0x4000)
     496              :   }
     497            1 :   __m256i signal = create_avx_test_signal(signal_values);
     498              : 
     499              :   // Process multiple times to trigger adaptation
     500           21 :   for (int i = 0; i < 20; ++i) {
     501           20 :     processor->process(signal);
     502              :   }
     503              : 
     504              :   // Collect state after processing
     505            1 :   auto buffer_manager = processor->_get_internal_state_buffer_manager();
     506            1 :   auto state_value = buffer_manager->switch_buffer_and_read_casted();
     507              : 
     508            1 :   BOOST_TEST(state_value.m_size == 2);
     509            1 :   BOOST_TEST(state_value.m_data != nullptr);
     510              : 
     511              :   // With signal consistently above pedestal and small accum_limit,
     512              :   // pedestal should have increased
     513            1 :   bool pedestal_increased = false;
     514            1 :   for (int i = 0; i < 16; ++i) {
     515            1 :     if (state_value.m_data[0][i] > 0x4000) {
     516            1 :       pedestal_increased = true;
     517            1 :       break;
     518              :     }
     519              :   }
     520            1 :   BOOST_TEST(pedestal_increased);
     521            1 : }
     522              : 
     523              : BOOST_AUTO_TEST_SUITE_END()
     524              : 
     525              : // =============================================================================
     526              : // SECTION 5: NaiveAbsRunSumProcessor Tests
     527              : // =============================================================================
     528              : 
     529              : BOOST_AUTO_TEST_SUITE(NaiveAbsRunSumProcessorTests)
     530              : 
     531            2 : BOOST_AUTO_TEST_CASE(test_naive_abs_runsum_inherits_registration) {
     532            1 :   auto processor = std::make_shared<NaiveAbsRunSumProcessor>();
     533            1 :   int16_t plane_numbers[16] = {0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2};
     534              : 
     535            1 :   auto config = create_test_config();
     536            1 :   config["requested_internal_states"] = "r,s,rs";
     537            1 :   config["memory_factor_plane0"] = 100;
     538            1 :   config["memory_factor_plane1"] = 200;
     539            1 :   config["memory_factor_plane2"] = 300;
     540            1 :   config["scale_factor_plane0"] = 10;
     541            1 :   config["scale_factor_plane1"] = 20;
     542            1 :   config["scale_factor_plane2"] = 30;
     543            1 :   config["memory_divisor_plane0"] = 10;
     544            1 :   config["memory_divisor_plane1"] = 10;
     545            1 :   config["memory_divisor_plane2"] = 10;
     546            1 :   config["scale_divisor_plane0"] = 10;
     547            1 :   config["scale_divisor_plane1"] = 10;
     548            1 :   config["scale_divisor_plane2"] = 10;
     549              : 
     550            1 :   processor->configure(config, plane_numbers);
     551              : 
     552              :   // Should inherit the same internal state registration as parent
     553            1 :   auto requested_states = processor->get_requested_internal_state_names();
     554            1 :   BOOST_TEST(requested_states.size() == 3);
     555            1 :   BOOST_TEST(requested_states[0] == "r");
     556            1 :   BOOST_TEST(requested_states[1] == "s");
     557            1 :   BOOST_TEST(requested_states[2] == "rs");
     558            1 : }
     559              : 
     560            2 : BOOST_AUTO_TEST_CASE(test_naive_abs_runsum_processing_with_absolute_values) {
     561            1 :   auto processor = std::make_shared<NaiveAbsRunSumProcessor>();
     562            1 :   int16_t plane_numbers[16] = {0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2};
     563              : 
     564            1 :   auto config = create_test_config();
     565            1 :   config["requested_internal_states"] = "rs";
     566            1 :   config["memory_factor_plane0"] = 100;
     567            1 :   config["memory_factor_plane1"] = 200;
     568            1 :   config["memory_factor_plane2"] = 300;
     569            1 :   config["scale_factor_plane0"] = 10;
     570            1 :   config["scale_factor_plane1"] = 20;
     571            1 :   config["scale_factor_plane2"] = 30;
     572            1 :   config["memory_divisor_plane0"] = 10;
     573            1 :   config["memory_divisor_plane1"] = 10;
     574            1 :   config["memory_divisor_plane2"] = 10;
     575            1 :   config["scale_divisor_plane0"] = 10;
     576            1 :   config["scale_divisor_plane1"] = 10;
     577            1 :   config["scale_divisor_plane2"] = 10;
     578              : 
     579            1 :   processor->configure(config, plane_numbers);
     580              : 
     581              :   // Create test signal with negative values
     582              :   int16_t signal_values[16];
     583           17 :   for (int i = 0; i < 16; ++i) {
     584           16 :     signal_values[i] = -1000;  // Negative signal
     585              :   }
     586            1 :   auto signal = create_naive_test_signal(signal_values);
     587              : 
     588              :   // Process the signal twice - first call writes old state to buffer, second call updates state
     589            1 :   processor->process(signal);
     590            1 :   processor->process(signal);
     591              : 
     592              :   // Collect state after processing
     593            1 :   auto buffer_manager = processor->_get_internal_state_buffer_manager();
     594            1 :   auto state_value = buffer_manager->switch_buffer_and_read_casted();
     595              : 
     596            1 :   BOOST_TEST(state_value.m_size == 1);
     597            1 :   BOOST_TEST(state_value.m_data != nullptr);
     598              : 
     599              :   // Running sum should have been updated (non-zero)
     600            1 :   bool running_sum_updated = false;
     601            1 :   for (int i = 0; i < 16; ++i) {
     602            1 :     if (state_value.m_data[0][i] != 0) {
     603            1 :       running_sum_updated = true;
     604            1 :       break;
     605              :     }
     606              :   }
     607            1 :   BOOST_TEST(running_sum_updated);
     608            1 : }
     609              : 
     610              : BOOST_AUTO_TEST_SUITE_END()
     611              : 
     612              : // =============================================================================
     613              : // SECTION 6: NaiveFrugalPedestalSubtractProcessor Tests
     614              : // =============================================================================
     615              : 
     616              : BOOST_AUTO_TEST_SUITE(NaiveFrugalPedestalSubtractProcessorTests)
     617              : 
     618            2 : BOOST_AUTO_TEST_CASE(test_naive_frugal_configuration_and_registration) {
     619            1 :   auto processor = std::make_shared<NaiveFrugalPedestalSubtractProcessor>();
     620            1 :   int16_t plane_numbers[16] = {0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2};
     621              : 
     622            1 :   auto config = create_test_config();
     623            1 :   config["requested_internal_states"] = "pedestal,accum";
     624            1 :   config["accum_limit"] = 10;
     625              : 
     626            1 :   processor->configure(config, plane_numbers);
     627              : 
     628              :   // Test that internal states are registered
     629            1 :   auto requested_states = processor->get_requested_internal_state_names();
     630            1 :   BOOST_TEST(requested_states.size() == 2);
     631            1 :   BOOST_TEST(requested_states[0] == "pedestal");
     632            1 :   BOOST_TEST(requested_states[1] == "accum");
     633            1 : }
     634              : 
     635            2 : BOOST_AUTO_TEST_CASE(test_naive_frugal_initial_state_collection) {
     636            1 :   auto processor = std::make_shared<NaiveFrugalPedestalSubtractProcessor>();
     637            1 :   int16_t plane_numbers[16] = {0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2};
     638              : 
     639            1 :   auto config = create_test_config();
     640            1 :   config["requested_internal_states"] = "pedestal,accum";
     641            1 :   config["accum_limit"] = 10;
     642              : 
     643            1 :   processor->configure(config, plane_numbers);
     644              : 
     645              :   // Collect initial state
     646            1 :   auto buffer_manager = processor->_get_internal_state_buffer_manager();
     647            1 :   buffer_manager->write_to_active_buffer();
     648            1 :   auto state_value = buffer_manager->switch_buffer_and_read_casted();
     649              : 
     650            1 :   BOOST_TEST(state_value.m_size == 2);
     651            1 :   BOOST_TEST(state_value.m_data != nullptr);
     652              : 
     653              :   // Check initial values
     654              :   // pedestal should be initialized to 0
     655           17 :   for (int i = 0; i < 16; ++i) {
     656           16 :     BOOST_TEST(state_value.m_data[0][i] == 0);
     657              :   }
     658              : 
     659              :   // accum should be initialized to 0
     660           17 :   for (int i = 0; i < 16; ++i) {
     661           16 :     BOOST_TEST(state_value.m_data[1][i] == 0);
     662              :   }
     663            1 : }
     664              : 
     665            2 : BOOST_AUTO_TEST_CASE(test_naive_frugal_processing_and_state_update) {
     666            1 :   auto processor = std::make_shared<NaiveFrugalPedestalSubtractProcessor>();
     667            1 :   int16_t plane_numbers[16] = {0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2};
     668              : 
     669            1 :   auto config = create_test_config();
     670            1 :   config["requested_internal_states"] = "pedestal,accum";
     671            1 :   config["accum_limit"] = 3;  // Small limit for faster adaptation
     672              : 
     673            1 :   processor->configure(config, plane_numbers);
     674              : 
     675              :   // Create test signal consistently above initial pedestal
     676              :   int16_t signal_values[16];
     677           17 :   for (int i = 0; i < 16; ++i) {
     678           16 :     signal_values[i] = 1000;  // Above initial pedestal (0)
     679              :   }
     680            1 :   auto signal = create_naive_test_signal(signal_values);
     681              : 
     682              :   // Process multiple times to trigger adaptation
     683           11 :   for (int i = 0; i < 10; ++i) {
     684           10 :     processor->process(signal);
     685              :   }
     686              : 
     687              :   // Collect state after processing
     688            1 :   auto buffer_manager = processor->_get_internal_state_buffer_manager();
     689            1 :   auto state_value = buffer_manager->switch_buffer_and_read_casted();
     690              : 
     691            1 :   BOOST_TEST(state_value.m_size == 2);
     692            1 :   BOOST_TEST(state_value.m_data != nullptr);
     693              : 
     694              :   // With signal consistently above pedestal and small accum_limit,
     695              :   // pedestal should have increased
     696            1 :   bool pedestal_increased = false;
     697            1 :   for (int i = 0; i < 16; ++i) {
     698            1 :     if (state_value.m_data[0][i] > 0) {
     699            1 :       pedestal_increased = true;
     700            1 :       break;
     701              :     }
     702              :   }
     703            1 :   BOOST_TEST(pedestal_increased);
     704            1 : }
     705              : 
     706              : BOOST_AUTO_TEST_SUITE_END()
     707              : 
     708              : // =============================================================================
     709              : // SECTION 7: Cross-Processor Integration Tests
     710              : // =============================================================================
     711              : 
     712              : BOOST_AUTO_TEST_SUITE(CrossProcessorIntegrationTests)
     713              : 
     714            2 : BOOST_AUTO_TEST_CASE(test_all_processors_independence) {
     715              :   // Create all processor types
     716            1 :   auto avx_runsum = std::make_shared<AVXRunSumProcessor>();
     717            1 :   auto avx_abs_runsum = std::make_shared<AVXAbsRunSumProcessor>();
     718            1 :   auto avx_frugal = std::make_shared<AVXFrugalPedestalSubtractProcessor>();
     719            1 :   auto naive_runsum = std::make_shared<NaiveRunSumProcessor>();
     720            1 :   auto naive_abs_runsum = std::make_shared<NaiveAbsRunSumProcessor>();
     721            1 :   auto naive_frugal = std::make_shared<NaiveFrugalPedestalSubtractProcessor>();
     722              : 
     723            1 :   int16_t plane_numbers[16] = {0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2};
     724              : 
     725              :   // Configure all processors
     726            1 :   auto config = create_test_config();
     727            1 :   config["memory_factor_plane0"] = 100;
     728            1 :   config["memory_factor_plane1"] = 200;
     729            1 :   config["memory_factor_plane2"] = 300;
     730            1 :   config["scale_factor_plane0"] = 10;
     731            1 :   config["scale_factor_plane1"] = 20;
     732            1 :   config["scale_factor_plane2"] = 30;
     733            1 :   config["memory_divisor_plane0"] = 10;
     734            1 :   config["memory_divisor_plane1"] = 10;
     735            1 :   config["memory_divisor_plane2"] = 10;
     736            1 :   config["scale_divisor_plane0"] = 10;
     737            1 :   config["scale_divisor_plane1"] = 10;
     738            1 :   config["scale_divisor_plane2"] = 10;
     739            1 :   config["accum_limit"] = 10;
     740              : 
     741              :   // Configure each processor with its specific states
     742            1 :   auto avx_runsum_config = config;
     743            1 :   avx_runsum_config["requested_internal_states"] = "r,s,rs";
     744            1 :   avx_runsum->configure(avx_runsum_config, plane_numbers);
     745              :   
     746            1 :   auto avx_abs_runsum_config = config;
     747            1 :   avx_abs_runsum_config["requested_internal_states"] = "r,s,rs";
     748            1 :   avx_abs_runsum->configure(avx_abs_runsum_config, plane_numbers);
     749              :   
     750            1 :   auto avx_frugal_config = config;
     751            1 :   avx_frugal_config["requested_internal_states"] = "pedestal,accum";
     752            1 :   avx_frugal->configure(avx_frugal_config, plane_numbers);
     753              :   
     754            1 :   auto naive_runsum_config = config;
     755            1 :   naive_runsum_config["requested_internal_states"] = "r,s,rs";
     756            1 :   naive_runsum->configure(naive_runsum_config, plane_numbers);
     757              :   
     758            1 :   auto naive_abs_runsum_config = config;
     759            1 :   naive_abs_runsum_config["requested_internal_states"] = "r,s,rs";
     760            1 :   naive_abs_runsum->configure(naive_abs_runsum_config, plane_numbers);
     761              :   
     762            1 :   auto naive_frugal_config = config;
     763            1 :   naive_frugal_config["requested_internal_states"] = "pedestal,accum";
     764            1 :   naive_frugal->configure(naive_frugal_config, plane_numbers);
     765              : 
     766              :   // Test that all processors have their expected internal states
     767            1 :   auto avx_runsum_states = avx_runsum->get_requested_internal_state_names();
     768            1 :   auto avx_abs_runsum_states = avx_abs_runsum->get_requested_internal_state_names();
     769            1 :   auto avx_frugal_states = avx_frugal->get_requested_internal_state_names();
     770            1 :   auto naive_runsum_states = naive_runsum->get_requested_internal_state_names();
     771            1 :   auto naive_abs_runsum_states = naive_abs_runsum->get_requested_internal_state_names();
     772            1 :   auto naive_frugal_states = naive_frugal->get_requested_internal_state_names();
     773              : 
     774            1 :   BOOST_TEST(avx_runsum_states.size() == 3);
     775            1 :   BOOST_TEST(avx_abs_runsum_states.size() == 3);
     776            1 :   BOOST_TEST(avx_frugal_states.size() == 2);
     777            1 :   BOOST_TEST(naive_runsum_states.size() == 3);
     778            1 :   BOOST_TEST(naive_abs_runsum_states.size() == 3);
     779            1 :   BOOST_TEST(naive_frugal_states.size() == 2);
     780              : 
     781              :   // Test that they are independent
     782            1 :   auto bm1 = avx_runsum->_get_internal_state_buffer_manager();
     783            1 :   auto bm2 = avx_frugal->_get_internal_state_buffer_manager();
     784            1 :   auto bm3 = naive_runsum->_get_internal_state_buffer_manager();
     785            1 :   auto bm4 = naive_frugal->_get_internal_state_buffer_manager();
     786              : 
     787            1 :   bm1->write_to_active_buffer();
     788            1 :   bm2->write_to_active_buffer();
     789            1 :   bm3->write_to_active_buffer();
     790            1 :   bm4->write_to_active_buffer();
     791              : 
     792            1 :   auto state1 = bm1->switch_buffer_and_read_casted();
     793            1 :   auto state2 = bm2->switch_buffer_and_read_casted();
     794            1 :   auto state3 = bm3->switch_buffer_and_read_casted();
     795            1 :   auto state4 = bm4->switch_buffer_and_read_casted();
     796              : 
     797            1 :   BOOST_TEST(state1.m_size == 3);
     798            1 :   BOOST_TEST(state2.m_size == 2);
     799            1 :   BOOST_TEST(state3.m_size == 3);
     800            1 :   BOOST_TEST(state4.m_size == 2);
     801              : 
     802              :   // They should have different buffer managers (compare within same type)
     803            1 :   BOOST_TEST(bm1 != bm2);
     804            1 :   BOOST_TEST(bm3 != bm4);
     805              :   // Note: Can't compare AVX and Naive buffer managers directly due to different types
     806            1 : }
     807              : 
     808            2 : BOOST_AUTO_TEST_CASE(test_processor_chain_with_internal_states) {
     809              :   // Create a chain of processors (same type to avoid template issues)
     810            1 :   auto avx_runsum1 = std::make_shared<AVXRunSumProcessor>();
     811            1 :   auto avx_runsum2 = std::make_shared<AVXRunSumProcessor>();
     812              : 
     813            1 :   int16_t plane_numbers[16] = {0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2};
     814              : 
     815            1 :   auto config = create_test_config();
     816            1 :   config["requested_internal_states"] = "r,s,rs";
     817            1 :   config["memory_factor_plane0"] = 100;
     818            1 :   config["memory_factor_plane1"] = 200;
     819            1 :   config["memory_factor_plane2"] = 300;
     820            1 :   config["scale_factor_plane0"] = 10;
     821            1 :   config["scale_factor_plane1"] = 20;
     822            1 :   config["scale_factor_plane2"] = 30;
     823            1 :   config["memory_divisor_plane0"] = 10;
     824            1 :   config["memory_divisor_plane1"] = 10;
     825            1 :   config["memory_divisor_plane2"] = 10;
     826            1 :   config["scale_divisor_plane0"] = 10;
     827            1 :   config["scale_divisor_plane1"] = 10;
     828            1 :   config["scale_divisor_plane2"] = 10;
     829              : 
     830            1 :   avx_runsum1->configure(config, plane_numbers);
     831            1 :   avx_runsum2->configure(config, plane_numbers);
     832              : 
     833              :   // Chain them together
     834            1 :   avx_runsum1->set_next_processor(avx_runsum2);
     835              : 
     836              :   // Test that both processors maintain their internal state registration
     837            1 :   auto avx_states1 = avx_runsum1->get_requested_internal_state_names();
     838            1 :   auto avx_states2 = avx_runsum2->get_requested_internal_state_names();
     839              : 
     840            1 :   BOOST_TEST(avx_states1.size() == 3);
     841            1 :   BOOST_TEST(avx_states2.size() == 3);
     842              : 
     843              :   // Process through the chain
     844              :   int16_t signal_values[16];
     845           17 :   for (int i = 0; i < 16; ++i) {
     846           16 :     signal_values[i] = 1000;
     847              :   }
     848            1 :   __m256i signal = create_avx_test_signal(signal_values);
     849              : 
     850            1 :   avx_runsum1->process(signal);
     851              : 
     852              :   // Both processors should have updated their internal states
     853            1 :   auto bm1 = avx_runsum1->_get_internal_state_buffer_manager();
     854            1 :   auto bm2 = avx_runsum2->_get_internal_state_buffer_manager();
     855              : 
     856            1 :   auto state1 = bm1->switch_buffer_and_read_casted();
     857            1 :   auto state2 = bm2->switch_buffer_and_read_casted();
     858              : 
     859            1 :   BOOST_TEST(state1.m_size == 3);
     860            1 :   BOOST_TEST(state2.m_size == 3);
     861            1 : }
     862              : 
     863              : BOOST_AUTO_TEST_SUITE_END()
     864              : 
     865              : // =============================================================================
     866              : // SECTION 8: Basic Edge Cases (Minimal Coverage)
     867              : // =============================================================================
     868              : 
     869              : BOOST_AUTO_TEST_SUITE(BasicEdgeCases)
     870              : 
     871            2 : BOOST_AUTO_TEST_CASE(test_collection_disabled) {
     872            1 :   auto processor = std::make_shared<AVXRunSumProcessor>();
     873            1 :   int16_t plane_numbers[16] = {0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2};
     874              : 
     875            1 :   nlohmann::json config = {
     876            2 :     {"memory_factor_plane0", 100},
     877            2 :     {"memory_factor_plane1", 200},
     878            2 :     {"memory_factor_plane2", 300},
     879            2 :     {"scale_factor_plane0", 10},
     880            2 :     {"scale_factor_plane1", 20},
     881            2 :     {"scale_factor_plane2", 30},
     882            2 :     {"memory_divisor_plane0", 10},
     883            2 :     {"memory_divisor_plane1", 10},
     884            2 :     {"memory_divisor_plane2", 10},
     885            2 :     {"scale_divisor_plane0", 10},
     886            2 :     {"scale_divisor_plane1", 10},
     887            2 :     {"scale_divisor_plane2", 10},
     888              :     {"metric_collect_toggle_state", false}
     889           40 :   };
     890              : 
     891            1 :   processor->configure(config, plane_numbers);
     892              : 
     893            1 :   auto requested_states = processor->get_requested_internal_state_names();
     894            1 :   BOOST_TEST(requested_states.size() == 0);
     895              : 
     896            1 :   auto buffer_manager = processor->_get_internal_state_buffer_manager();
     897            1 :   buffer_manager->write_to_active_buffer();
     898            1 :   auto state_value = buffer_manager->switch_buffer_and_read_casted();
     899              : 
     900            1 :   BOOST_TEST(state_value.m_size == 0);
     901           29 : }
     902              : 
     903            2 : BOOST_AUTO_TEST_CASE(test_empty_internal_state_request) {
     904            1 :   auto processor = std::make_shared<NaiveFrugalPedestalSubtractProcessor>();
     905            1 :   int16_t plane_numbers[16] = {0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2};
     906              : 
     907            1 :   auto config = create_test_config();
     908            1 :   config["requested_internal_states"] = "";
     909            1 :   config["accum_limit"] = 10;
     910              : 
     911            1 :   processor->configure(config, plane_numbers);
     912              : 
     913            1 :   auto requested_states = processor->get_requested_internal_state_names();
     914            1 :   BOOST_TEST(requested_states.size() == 0);
     915              : 
     916            1 :   auto buffer_manager = processor->_get_internal_state_buffer_manager();
     917            1 :   buffer_manager->write_to_active_buffer();
     918            1 :   auto state_value = buffer_manager->switch_buffer_and_read_casted();
     919              : 
     920            1 :   BOOST_TEST(state_value.m_size == 0);
     921            1 : }
     922              : 
     923              : BOOST_AUTO_TEST_SUITE_END()
     924              : 
     925              : // =============================================================================
     926              : // SECTION 9: Core Registration and Collection Verification
     927              : // =============================================================================
     928              : 
     929              : BOOST_AUTO_TEST_SUITE(CoreRegistrationAndCollectionVerification)
     930              : 
     931            2 : BOOST_AUTO_TEST_CASE(test_all_processors_core_functionality) {
     932              :   // Test that all processors properly register and collect their internal states
     933              :   
     934              :   // AVX Processors
     935            1 :   auto avx_runsum = std::make_shared<AVXRunSumProcessor>();
     936            1 :   auto avx_abs_runsum = std::make_shared<AVXAbsRunSumProcessor>();
     937            1 :   auto avx_frugal = std::make_shared<AVXFrugalPedestalSubtractProcessor>();
     938              :   
     939              :   // Naive Processors  
     940            1 :   auto naive_runsum = std::make_shared<NaiveRunSumProcessor>();
     941            1 :   auto naive_abs_runsum = std::make_shared<NaiveAbsRunSumProcessor>();
     942            1 :   auto naive_frugal = std::make_shared<NaiveFrugalPedestalSubtractProcessor>();
     943              : 
     944            1 :   int16_t plane_numbers[16] = {0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2};
     945              : 
     946              :   // Configure all processors with collection enabled
     947            1 :   auto config = create_test_config();
     948            1 :   config["memory_factor_plane0"] = 100;
     949            1 :   config["memory_factor_plane1"] = 200;
     950            1 :   config["memory_factor_plane2"] = 300;
     951            1 :   config["scale_factor_plane0"] = 10;
     952            1 :   config["scale_factor_plane1"] = 20;
     953            1 :   config["scale_factor_plane2"] = 30;
     954            1 :   config["memory_divisor_plane0"] = 10;
     955            1 :   config["memory_divisor_plane1"] = 10;
     956            1 :   config["memory_divisor_plane2"] = 10;
     957            1 :   config["scale_divisor_plane0"] = 10;
     958            1 :   config["scale_divisor_plane1"] = 10;
     959            1 :   config["scale_divisor_plane2"] = 10;
     960            1 :   config["accum_limit"] = 10;
     961              : 
     962              :   // Configure each processor with its specific states
     963            1 :   auto avx_runsum_config = config;
     964            1 :   avx_runsum_config["requested_internal_states"] = "r,s,rs";
     965            1 :   avx_runsum->configure(avx_runsum_config, plane_numbers);
     966              :   
     967            1 :   auto avx_abs_runsum_config = config;
     968            1 :   avx_abs_runsum_config["requested_internal_states"] = "r,s,rs";
     969            1 :   avx_abs_runsum->configure(avx_abs_runsum_config, plane_numbers);
     970              :   
     971            1 :   auto avx_frugal_config = config;
     972            1 :   avx_frugal_config["requested_internal_states"] = "pedestal,accum";
     973            1 :   avx_frugal->configure(avx_frugal_config, plane_numbers);
     974              :   
     975            1 :   auto naive_runsum_config = config;
     976            1 :   naive_runsum_config["requested_internal_states"] = "r,s,rs";
     977            1 :   naive_runsum->configure(naive_runsum_config, plane_numbers);
     978              :   
     979            1 :   auto naive_abs_runsum_config = config;
     980            1 :   naive_abs_runsum_config["requested_internal_states"] = "r,s,rs";
     981            1 :   naive_abs_runsum->configure(naive_abs_runsum_config, plane_numbers);
     982              :   
     983            1 :   auto naive_frugal_config = config;
     984            1 :   naive_frugal_config["requested_internal_states"] = "pedestal,accum";
     985            1 :   naive_frugal->configure(naive_frugal_config, plane_numbers);
     986              : 
     987              :   // Verify registration worked for all processors
     988            1 :   BOOST_TEST(avx_runsum->get_requested_internal_state_names().size() == 3);
     989            1 :   BOOST_TEST(avx_abs_runsum->get_requested_internal_state_names().size() == 3);
     990            1 :   BOOST_TEST(avx_frugal->get_requested_internal_state_names().size() == 2);
     991            1 :   BOOST_TEST(naive_runsum->get_requested_internal_state_names().size() == 3);
     992            1 :   BOOST_TEST(naive_abs_runsum->get_requested_internal_state_names().size() == 3);
     993            1 :   BOOST_TEST(naive_frugal->get_requested_internal_state_names().size() == 2);
     994              : 
     995              :   // Test collection works for all processors
     996              :   // Test AVX processors individually
     997            1 :   auto avx_runsum_bm = avx_runsum->_get_internal_state_buffer_manager();
     998            1 :   avx_runsum_bm->write_to_active_buffer();
     999            1 :   auto avx_runsum_state = avx_runsum_bm->switch_buffer_and_read_casted();
    1000            1 :   BOOST_TEST(avx_runsum_state.m_data != nullptr);
    1001            1 :   BOOST_TEST(avx_runsum_state.m_size > 0);
    1002              : 
    1003            1 :   auto avx_abs_runsum_bm = avx_abs_runsum->_get_internal_state_buffer_manager();
    1004            1 :   avx_abs_runsum_bm->write_to_active_buffer();
    1005            1 :   auto avx_abs_runsum_state = avx_abs_runsum_bm->switch_buffer_and_read_casted();
    1006            1 :   BOOST_TEST(avx_abs_runsum_state.m_data != nullptr);
    1007            1 :   BOOST_TEST(avx_abs_runsum_state.m_size > 0);
    1008              : 
    1009            1 :   auto avx_frugal_bm = avx_frugal->_get_internal_state_buffer_manager();
    1010            1 :   avx_frugal_bm->write_to_active_buffer();
    1011            1 :   auto avx_frugal_state = avx_frugal_bm->switch_buffer_and_read_casted();
    1012            1 :   BOOST_TEST(avx_frugal_state.m_data != nullptr);
    1013            1 :   BOOST_TEST(avx_frugal_state.m_size > 0);
    1014              : 
    1015              :   // Test Naive processors individually
    1016            1 :   auto naive_runsum_bm = naive_runsum->_get_internal_state_buffer_manager();
    1017            1 :   naive_runsum_bm->write_to_active_buffer();
    1018            1 :   auto naive_runsum_state = naive_runsum_bm->switch_buffer_and_read_casted();
    1019            1 :   BOOST_TEST(naive_runsum_state.m_data != nullptr);
    1020            1 :   BOOST_TEST(naive_runsum_state.m_size > 0);
    1021              : 
    1022            1 :   auto naive_abs_runsum_bm = naive_abs_runsum->_get_internal_state_buffer_manager();
    1023            1 :   naive_abs_runsum_bm->write_to_active_buffer();
    1024            1 :   auto naive_abs_runsum_state = naive_abs_runsum_bm->switch_buffer_and_read_casted();
    1025            1 :   BOOST_TEST(naive_abs_runsum_state.m_data != nullptr);
    1026            1 :   BOOST_TEST(naive_abs_runsum_state.m_size > 0);
    1027              : 
    1028            1 :   auto naive_frugal_bm = naive_frugal->_get_internal_state_buffer_manager();
    1029            1 :   naive_frugal_bm->write_to_active_buffer();
    1030            1 :   auto naive_frugal_state = naive_frugal_bm->switch_buffer_and_read_casted();
    1031            1 :   BOOST_TEST(naive_frugal_state.m_data != nullptr);
    1032            1 :   BOOST_TEST(naive_frugal_state.m_size > 0);
    1033            1 : }
    1034              : 
    1035            2 : BOOST_AUTO_TEST_CASE(test_processor_specific_internal_states) {
    1036              :   // Verify each processor registers the correct internal state names
    1037              :   
    1038            1 :   auto avx_runsum = std::make_shared<AVXRunSumProcessor>();
    1039            1 :   auto avx_frugal = std::make_shared<AVXFrugalPedestalSubtractProcessor>();
    1040            1 :   auto naive_runsum = std::make_shared<NaiveRunSumProcessor>();
    1041            1 :   auto naive_frugal = std::make_shared<NaiveFrugalPedestalSubtractProcessor>();
    1042              : 
    1043            1 :   int16_t plane_numbers[16] = {0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2};
    1044              : 
    1045            1 :   auto config = create_test_config();
    1046            1 :   config["memory_factor_plane0"] = 100;
    1047            1 :   config["memory_factor_plane1"] = 200;
    1048            1 :   config["memory_factor_plane2"] = 300;
    1049            1 :   config["scale_factor_plane0"] = 10;
    1050            1 :   config["scale_factor_plane1"] = 20;
    1051            1 :   config["scale_factor_plane2"] = 30;
    1052            1 :   config["memory_divisor_plane0"] = 10;
    1053            1 :   config["memory_divisor_plane1"] = 10;
    1054            1 :   config["memory_divisor_plane2"] = 10;
    1055            1 :   config["scale_divisor_plane0"] = 10;
    1056            1 :   config["scale_divisor_plane1"] = 10;
    1057            1 :   config["scale_divisor_plane2"] = 10;
    1058            1 :   config["accum_limit"] = 10;
    1059              : 
    1060              :   // Configure each processor with its specific states
    1061            1 :   auto avx_runsum_config = config;
    1062            1 :   avx_runsum_config["requested_internal_states"] = "r,s,rs";
    1063            1 :   avx_runsum->configure(avx_runsum_config, plane_numbers);
    1064              :   
    1065            1 :   auto avx_frugal_config = config;
    1066            1 :   avx_frugal_config["requested_internal_states"] = "pedestal,accum";
    1067            1 :   avx_frugal->configure(avx_frugal_config, plane_numbers);
    1068              :   
    1069            1 :   auto naive_runsum_config = config;
    1070            1 :   naive_runsum_config["requested_internal_states"] = "r,s,rs";
    1071            1 :   naive_runsum->configure(naive_runsum_config, plane_numbers);
    1072              :   
    1073            1 :   auto naive_frugal_config = config;
    1074            1 :   naive_frugal_config["requested_internal_states"] = "pedestal,accum";
    1075            1 :   naive_frugal->configure(naive_frugal_config, plane_numbers);
    1076              : 
    1077              :   // Check AVXRunSumProcessor states
    1078            1 :   auto avx_runsum_states = avx_runsum->get_requested_internal_state_names();
    1079            1 :   BOOST_TEST(avx_runsum_states.size() == 3);
    1080            1 :   BOOST_TEST((std::find(avx_runsum_states.begin(), avx_runsum_states.end(), "r") != avx_runsum_states.end()));
    1081            1 :   BOOST_TEST((std::find(avx_runsum_states.begin(), avx_runsum_states.end(), "s") != avx_runsum_states.end()));
    1082            1 :   BOOST_TEST((std::find(avx_runsum_states.begin(), avx_runsum_states.end(), "rs") != avx_runsum_states.end()));
    1083              : 
    1084              :   // Check AVXFrugalPedestalSubtractProcessor states
    1085            1 :   auto avx_frugal_states = avx_frugal->get_requested_internal_state_names();
    1086            1 :   BOOST_TEST(avx_frugal_states.size() == 2);
    1087            1 :   BOOST_TEST((std::find(avx_frugal_states.begin(), avx_frugal_states.end(), "pedestal") != avx_frugal_states.end()));
    1088            1 :   BOOST_TEST((std::find(avx_frugal_states.begin(), avx_frugal_states.end(), "accum") != avx_frugal_states.end()));
    1089              : 
    1090              :   // Check NaiveRunSumProcessor states
    1091            1 :   auto naive_runsum_states = naive_runsum->get_requested_internal_state_names();
    1092            1 :   BOOST_TEST(naive_runsum_states.size() == 3);
    1093            1 :   BOOST_TEST((std::find(naive_runsum_states.begin(), naive_runsum_states.end(), "r") != naive_runsum_states.end()));
    1094            1 :   BOOST_TEST((std::find(naive_runsum_states.begin(), naive_runsum_states.end(), "s") != naive_runsum_states.end()));
    1095            1 :   BOOST_TEST((std::find(naive_runsum_states.begin(), naive_runsum_states.end(), "rs") != naive_runsum_states.end()));
    1096              : 
    1097              :   // Check NaiveFrugalPedestalSubtractProcessor states
    1098            1 :   auto naive_frugal_states = naive_frugal->get_requested_internal_state_names();
    1099            1 :   BOOST_TEST(naive_frugal_states.size() == 2);
    1100            1 :   BOOST_TEST((std::find(naive_frugal_states.begin(), naive_frugal_states.end(), "pedestal") != naive_frugal_states.end()));
    1101            1 :   BOOST_TEST((std::find(naive_frugal_states.begin(), naive_frugal_states.end(), "accum") != naive_frugal_states.end()));
    1102            1 : }
    1103              : 
    1104              : BOOST_AUTO_TEST_SUITE_END()
    1105              : 
    1106              : } // namespace tpglibs
        

Generated by: LCOV version 2.0-1