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
|