LCOV - code coverage report
Current view: top level - daqdataformats/unittest - TriggerRecordHeader_test.cxx (source / functions) Coverage Total Hit
Test: code.result Lines: 100.0 % 210 210
Test Date: 2026-05-24 15:29:04 Functions: 100.0 % 14 14

            Line data    Source code
       1              : /**
       2              :  * @file TriggerRecordHeader_test.cxx TriggerRecordHeader class Unit Tests
       3              :  *
       4              :  * This is part of the DUNE DAQ Application Framework, copyright 2020.
       5              :  * Licensing/copyright details are in the COPYING file that you should have
       6              :  * received with this code.
       7              :  */
       8              : 
       9              : // Disable warnings in light of the use of intentially bad constructors during testing
      10              : 
      11              : #pragma GCC diagnostic ignored "-Walloc-size-larger-than="
      12              : #pragma GCC diagnostic ignored "-Warray-bounds"
      13              : #pragma GCC diagnostic ignored "-Wstringop-overflow="
      14              : 
      15              : #include "daqdataformats/TriggerRecordHeader.hpp"
      16              : #include "daqdataformats/TriggerRecordHeaderData.hpp"
      17              : 
      18              : #pragma GCC diagnostic pop
      19              : #pragma GCC diagnostic pop
      20              : #pragma GCC diagnostic pop
      21              : 
      22              : /**
      23              :  * @brief Name of this test module
      24              :  */
      25              : #define BOOST_TEST_MODULE TriggerRecordHeader_test // NOLINT
      26              : 
      27              : #include "boost/test/unit_test.hpp"
      28              : 
      29              : #include <cstring>
      30              : #include <limits>
      31              : #include <memory>
      32              : #include <sstream>
      33              : #include <string>
      34              : #include <utility>
      35              : #include <vector>
      36              : 
      37              : using namespace dunedaq::daqdataformats;
      38              : 
      39              : BOOST_AUTO_TEST_SUITE(TriggerRecordHeader_test)
      40              : 
      41              : /**
      42              :  * @brief Check that TriggerRecords have appropriate Copy/Move semantics
      43              :  */
      44            2 : BOOST_AUTO_TEST_CASE(CopyAndMoveSemantics)
      45              : {
      46            1 :   BOOST_REQUIRE(std::is_copy_constructible_v<TriggerRecordHeader>);
      47            1 :   BOOST_REQUIRE(std::is_copy_assignable_v<TriggerRecordHeader>);
      48            1 :   BOOST_REQUIRE(std::is_move_constructible_v<TriggerRecordHeader>);
      49            1 :   BOOST_REQUIRE(std::is_move_assignable_v<TriggerRecordHeader>);
      50            1 : }
      51              : 
      52              : /**
      53              :  * @brief Check that TriggerRecordHeader constructors function correctly
      54              :  */
      55            2 : BOOST_AUTO_TEST_CASE(ExistingHeader)
      56              : {
      57            1 :   std::vector<ComponentRequest> components;
      58            1 :   components.emplace_back();
      59            1 :   components.back().component = { SourceID::Subsystem::kDetectorReadout, 12 };
      60            1 :   components.back().window_begin = 3;
      61            1 :   components.back().window_end = 4;
      62            1 :   components.emplace_back();
      63            1 :   components.back().component = { SourceID::Subsystem::kDetectorReadout, 56 };
      64            1 :   components.back().window_begin = 7;
      65            1 :   components.back().window_end = 8;
      66              : 
      67            1 :   auto header = new TriggerRecordHeader(components);
      68            1 :   header->set_run_number(9);
      69            1 :   header->set_trigger_number(10);
      70            1 :   header->set_trigger_timestamp(11);
      71            1 :   header->set_trigger_type(12);
      72            1 :   header->set_sequence_number(13);
      73            1 :   header->set_max_sequence_number(14);
      74            1 :   header->set_status_bit(TriggerRecordStatusBits::kMismatch, true);
      75            1 :   header->set_status_bit(TriggerRecordStatusBits::kUnassigned3, true);
      76              : 
      77            1 :   BOOST_REQUIRE_THROW(header->at(header->get_header().num_requested_components), std::range_error);
      78              : 
      79            1 :   void* buff = malloc(header->get_total_size_bytes()); // NOLINT
      80            1 :   std::memcpy(buff, header->get_storage_location(), header->get_total_size_bytes());
      81              : 
      82              :   // Constructor should copy header
      83            1 :   TriggerRecordHeader copy_header(const_cast<void*>(header->get_storage_location()), true); // NOLINT
      84            1 :   delete header; // NOLINT(build/raw_ownership)
      85              : 
      86            1 :   BOOST_REQUIRE_EQUAL(copy_header.get_run_number(), 9);
      87            1 :   BOOST_REQUIRE_EQUAL(copy_header.get_sequence_number(), 13);
      88            1 :   BOOST_REQUIRE_EQUAL(copy_header.get_max_sequence_number(), 14);
      89            1 :   BOOST_REQUIRE_EQUAL(copy_header.get_status_bit(static_cast<TriggerRecordStatusBits>(0)), false);
      90            1 :   BOOST_REQUIRE_EQUAL(copy_header.get_status_bit(static_cast<TriggerRecordStatusBits>(1)), true);
      91            1 :   BOOST_REQUIRE_EQUAL(copy_header.get_header().status_bits, 10);
      92            1 :   BOOST_REQUIRE_EQUAL(copy_header.at(0).window_begin, 3);
      93              : 
      94            1 :   {
      95              :     // Test copy constructor
      96            1 :     TriggerRecordHeader copy_copy_header(copy_header); // NOLINT
      97            1 :     BOOST_REQUIRE_EQUAL(copy_copy_header.get_run_number(), 9);
      98            1 :     BOOST_REQUIRE_EQUAL(copy_copy_header.get_sequence_number(), 13);
      99            1 :     BOOST_REQUIRE_EQUAL(copy_copy_header.get_max_sequence_number(), 14);
     100            1 :     BOOST_REQUIRE_EQUAL(copy_copy_header.get_status_bit(static_cast<TriggerRecordStatusBits>(0)), false);
     101            1 :     BOOST_REQUIRE_EQUAL(copy_copy_header.get_status_bit(static_cast<TriggerRecordStatusBits>(1)), true);
     102            1 :     BOOST_REQUIRE_EQUAL(copy_copy_header.get_header().status_bits, 10);
     103            1 :     BOOST_REQUIRE_EQUAL(copy_copy_header.at(0).window_begin, 3);
     104            1 :   }
     105            1 :   {
     106              :     // Test copy assignment
     107            1 :     TriggerRecordHeader copy_assign_header = copy_header; // NOLINT
     108            1 :     BOOST_REQUIRE_EQUAL(copy_assign_header.get_run_number(), 9);
     109            1 :     BOOST_REQUIRE_EQUAL(copy_assign_header.get_sequence_number(), 13);
     110            1 :     BOOST_REQUIRE_EQUAL(copy_assign_header.get_max_sequence_number(), 14);
     111            1 :     BOOST_REQUIRE_EQUAL(copy_assign_header.get_status_bit(static_cast<TriggerRecordStatusBits>(0)), false);
     112            1 :     BOOST_REQUIRE_EQUAL(copy_assign_header.get_status_bit(static_cast<TriggerRecordStatusBits>(1)), true);
     113            1 :     BOOST_REQUIRE_EQUAL(copy_assign_header.get_header().status_bits, 10);
     114            1 :     BOOST_REQUIRE_EQUAL(copy_assign_header.at(0).window_begin, 3);
     115            1 :   }
     116              : 
     117            1 :   {
     118              :     // Test Buffer adoption constructor
     119            1 :     TriggerRecordHeader buffer_header(buff, false);
     120              : 
     121            1 :     BOOST_REQUIRE_EQUAL(buffer_header.get_run_number(), 9);
     122            1 :     BOOST_REQUIRE_EQUAL(buffer_header.get_sequence_number(), 13);
     123            1 :     BOOST_REQUIRE_EQUAL(buffer_header.get_max_sequence_number(), 14);
     124            1 :     BOOST_REQUIRE_EQUAL(buffer_header.get_status_bit(static_cast<TriggerRecordStatusBits>(0)), false);
     125            1 :     BOOST_REQUIRE_EQUAL(buffer_header.get_status_bit(static_cast<TriggerRecordStatusBits>(1)), true);
     126            1 :     BOOST_REQUIRE_EQUAL(buffer_header.get_header().status_bits, 10);
     127            1 :     BOOST_REQUIRE_EQUAL(buffer_header.at(0).window_begin, 3);
     128            1 :   }
     129              : 
     130            1 :   BOOST_REQUIRE_EQUAL(*reinterpret_cast<uint32_t*>(buff), // NOLINT
     131              :                       TriggerRecordHeaderData::s_trigger_record_header_magic);
     132              : 
     133            1 :   free(buff); // NOLINT
     134            1 : }
     135              : 
     136            2 : BOOST_AUTO_TEST_CASE(MoveConstructor)
     137              : {
     138            1 :   std::vector<ComponentRequest> components;
     139            1 :   components.emplace_back();
     140            1 :   components.back().component = { SourceID::Subsystem::kDetectorReadout, 12 };
     141            1 :   components.back().window_begin = 3;
     142            1 :   components.back().window_end = 4;
     143            1 :   components.emplace_back();
     144            1 :   components.back().component = { SourceID::Subsystem::kDetectorReadout, 56 };
     145            1 :   components.back().window_begin = 7;
     146            1 :   components.back().window_end = 8;
     147              : 
     148            1 :   auto header = new TriggerRecordHeader(components);
     149              : 
     150            1 :   TriggerRecordHeader another_header(std::move(*header));
     151              : 
     152            1 :   delete header; // NOLINT We are specifically testing what happens when the original trh is deleted
     153              : 
     154            1 :   BOOST_REQUIRE_EQUAL(another_header.get_num_requested_components(), 2);
     155            1 : }
     156              : 
     157            2 : BOOST_AUTO_TEST_CASE(MoveAssignment)
     158              : {
     159            1 :   std::vector<ComponentRequest> components;
     160            1 :   components.emplace_back();
     161            1 :   components.back().component = { SourceID::Subsystem::kDetectorReadout, 12 };
     162            1 :   components.back().window_begin = 3;
     163            1 :   components.back().window_end = 4;
     164            1 :   components.emplace_back();
     165            1 :   components.back().component = { SourceID::Subsystem::kDetectorReadout, 56 };
     166            1 :   components.back().window_begin = 7;
     167            1 :   components.back().window_end = 8;
     168              : 
     169            1 :   auto header = new TriggerRecordHeader(components);
     170              : 
     171            1 :   auto another_header = std::move(*header);
     172              : 
     173            1 :   delete header; // NOLINT We are specifically testing what happens when the original trh is deleted
     174              : 
     175            1 :   BOOST_REQUIRE_EQUAL(another_header.get_num_requested_components(), 2);
     176            1 : }
     177              : 
     178            2 : BOOST_AUTO_TEST_CASE(BadConstructors)
     179              : {
     180            1 :   TriggerRecordHeaderData header_data;
     181            1 :   header_data.num_requested_components = std::numeric_limits<uint64_t>::max() - 10; // NOLINT(build/unsigned)
     182            1 :   header_data.run_number = 9;
     183            1 :   header_data.trigger_number = 10;
     184            1 :   header_data.trigger_timestamp = 11;
     185            1 :   header_data.trigger_type = 12;
     186              : 
     187            1 :   auto hdr = malloc(sizeof(TriggerRecordHeaderData) + sizeof(ComponentRequest)); // NOLINT
     188            1 :   std::memcpy(hdr, &header_data, sizeof(TriggerRecordHeaderData));
     189              : 
     190            1 : #pragma GCC diagnostic push
     191            1 : #pragma GCC diagnostic ignored "-Wrestrict"
     192            1 :   BOOST_REQUIRE_EXCEPTION(
     193              :     TriggerRecordHeader oversize_header(hdr, true), std::bad_alloc, [&](std::bad_alloc) { return true; });
     194            1 : #pragma GCC diagnostic pop
     195              : 
     196            1 :   header_data.num_requested_components = 1;
     197            1 :   std::memcpy(hdr, &header_data, sizeof(TriggerRecordHeaderData));
     198            1 :   TriggerRecordHeader bad_header(hdr, false);
     199            1 :   BOOST_REQUIRE_EQUAL(bad_header.get_num_requested_components(), 1);
     200              : 
     201            1 :   reinterpret_cast<TriggerRecordHeaderData*>(hdr)->num_requested_components = // NOLINT
     202              :     std::numeric_limits<uint64_t>::max() - 10;                                // NOLINT(build/unsigned)
     203            1 :   BOOST_REQUIRE_EQUAL(bad_header.get_num_requested_components(),
     204              :                       std::numeric_limits<uint64_t>::max() - 10); // NOLINT(build/unsigned)
     205              : 
     206            1 : #pragma GCC diagnostic push
     207            1 : #pragma GCC diagnostic ignored "-Wrestrict"
     208            1 :   BOOST_REQUIRE_EXCEPTION(
     209              :     TriggerRecordHeader header_inst = bad_header, std::bad_alloc, [&](std::bad_alloc) { return true; }); // NOLINT
     210            1 : #pragma GCC diagnostic pop
     211              : 
     212            1 :   free(hdr); // NOLINT
     213            1 : }
     214              : 
     215              : /**
     216              :  * @brief Test header field manipulation methods
     217              :  */
     218            2 : BOOST_AUTO_TEST_CASE(HeaderFields)
     219              : {
     220            1 :   std::vector<ComponentRequest> components;
     221            1 :   components.emplace_back();
     222            1 :   components.back().component = { SourceID::Subsystem::kDetectorReadout, 12 };
     223            1 :   components.back().window_begin = 3;
     224            1 :   components.back().window_end = 4;
     225            1 :   components.emplace_back();
     226            1 :   components.back().component = { SourceID::Subsystem::kDetectorReadout, 34 };
     227            1 :   components.back().window_begin = 5;
     228            1 :   components.back().window_end = 6;
     229            1 :   components.emplace_back();
     230            1 :   components.back().component = { SourceID::Subsystem::kDetectorReadout, 56 };
     231            1 :   components.back().window_begin = 7;
     232            1 :   components.back().window_end = 8;
     233            1 :   components.emplace_back();
     234            1 :   components.back().component = { SourceID::Subsystem::kDetectorReadout, 78 };
     235            1 :   components.back().window_begin = 9;
     236            1 :   components.back().window_end = 10;
     237            1 :   components.emplace_back();
     238            1 :   components.back().component = { SourceID::Subsystem::kDetectorReadout, 90 };
     239            1 :   components.back().window_begin = 11;
     240            1 :   components.back().window_end = 12;
     241              : 
     242            1 :   auto header = new TriggerRecordHeader(components); // NOLINT
     243            1 :   header->set_run_number(9);
     244            1 :   header->set_trigger_number(10);
     245            1 :   header->set_trigger_timestamp(11);
     246            1 :   header->set_trigger_type(12);
     247            1 :   header->set_sequence_number(13);
     248            1 :   header->set_max_sequence_number(14);
     249            1 :   header->set_status_bit(TriggerRecordStatusBits::kMismatch, true);
     250            1 :   header->set_status_bit(TriggerRecordStatusBits::kUnassigned31, true);
     251              : 
     252            1 :   auto header_data = header->get_header();
     253            1 :   BOOST_REQUIRE_EQUAL(header->get_run_number(), header_data.run_number);
     254            1 :   BOOST_REQUIRE_EQUAL(header->get_trigger_number(), header_data.trigger_number);
     255            1 :   BOOST_REQUIRE_EQUAL(header->get_trigger_timestamp(), header_data.trigger_timestamp);
     256            1 :   BOOST_REQUIRE_EQUAL(header->get_trigger_type(), header_data.trigger_type);
     257            1 :   BOOST_REQUIRE_EQUAL(header->get_sequence_number(), header_data.sequence_number);
     258            1 :   BOOST_REQUIRE_EQUAL(header->get_max_sequence_number(), header_data.max_sequence_number);
     259            1 :   BOOST_REQUIRE_EQUAL(header->get_num_requested_components(), 5);
     260            1 :   BOOST_REQUIRE_EQUAL(header->get_num_requested_components(), header_data.num_requested_components);
     261            1 :   BOOST_REQUIRE_EQUAL(header->get_status_bits().to_ulong(), 0x80000002);
     262              : 
     263            1 :   auto comp_ref = header->get_component_for_source_id({ SourceID::Subsystem::kDetectorReadout, 78 });
     264            1 :   BOOST_REQUIRE_EQUAL(comp_ref.window_begin, 9);
     265            1 :   BOOST_REQUIRE_EQUAL(comp_ref.window_end, 10);
     266            1 :   comp_ref = header->get_component_for_source_id({ SourceID::Subsystem::kDetectorReadout, 56 });
     267            1 :   BOOST_REQUIRE_EQUAL(comp_ref.window_begin, 7);
     268            1 :   BOOST_REQUIRE_EQUAL(comp_ref.window_end, 8);
     269            1 :   comp_ref = header->get_component_for_source_id({ SourceID::Subsystem::kDetectorReadout, 12 });
     270            1 :   BOOST_REQUIRE_EQUAL(comp_ref.window_begin, 3);
     271            1 :   BOOST_REQUIRE_EQUAL(comp_ref.window_end, 4);
     272            1 :   comp_ref = header->get_component_for_source_id({ SourceID::Subsystem::kDetectorReadout, 90 });
     273            1 :   BOOST_REQUIRE_EQUAL(comp_ref.window_begin, 11);
     274            1 :   BOOST_REQUIRE_EQUAL(comp_ref.window_end, 12);
     275            1 :   BOOST_REQUIRE_EXCEPTION(header->get_component_for_source_id({ SourceID::Subsystem::kDetectorReadout, 43 }),
     276              :                           std::invalid_argument,
     277              :                           [&](std::invalid_argument) { return true; });
     278              : 
     279            1 :   auto header_ptr = static_cast<const TriggerRecordHeaderData*>(header->get_storage_location());
     280            1 :   BOOST_REQUIRE_EQUAL(header_ptr->run_number, header_data.run_number);
     281            1 :   header->set_run_number(10);
     282            1 :   BOOST_REQUIRE(header_ptr->run_number != header_data.run_number);
     283            1 :   BOOST_REQUIRE_EQUAL(header_ptr->run_number, 10);
     284            1 :   header->set_status_bits(std::bitset<32>(0x11111111));
     285            1 :   BOOST_REQUIRE_EQUAL(header_ptr->status_bits, 0x11111111);
     286            1 : }
     287              : 
     288            2 : BOOST_AUTO_TEST_CASE(StreamOperator)
     289              : {
     290            1 :   std::vector<ComponentRequest> components;
     291            1 :   components.emplace_back();
     292            1 :   components.back().component = { SourceID::Subsystem::kDetectorReadout, 12 };
     293            1 :   components.back().window_begin = 3;
     294            1 :   components.back().window_end = 4;
     295            1 :   components.emplace_back();
     296            1 :   components.back().component = { SourceID::Subsystem::kDetectorReadout, 56 };
     297            1 :   components.back().window_begin = 7;
     298            1 :   components.back().window_end = 8;
     299              : 
     300            1 :   auto header = std::make_unique<TriggerRecordHeader>(components);
     301            1 :   header->set_run_number(9);
     302            1 :   header->set_trigger_number(10);
     303            1 :   header->set_trigger_timestamp(11);
     304            1 :   header->set_trigger_type(12);
     305            1 :   header->set_sequence_number(13);
     306            1 :   header->set_max_sequence_number(14);
     307            1 :   header->set_status_bit(TriggerRecordStatusBits::kMismatch, true);
     308            1 :   header->set_status_bit(TriggerRecordStatusBits::kUnassigned3, true);
     309              : 
     310            1 :   auto header_data = header->get_header();
     311            1 :   std::ostringstream oss;
     312            1 :   oss << header_data;
     313              :   // std::istringstream iss(oss.str());
     314              :   // TriggerRecordHeaderData trhd;
     315              :   // iss >> trhd;
     316              :   // BOOST_REQUIRE_EQUAL(trhd.run_number, header_data.run_number);
     317              :   // BOOST_REQUIRE_EQUAL(trhd.trigger_number, header_data.trigger_number);
     318              :   // BOOST_REQUIRE_EQUAL(trhd.trigger_timestamp, header_data.trigger_timestamp);
     319              :   // BOOST_REQUIRE_EQUAL(trhd.trigger_type, header_data.trigger_type);
     320              :   // BOOST_REQUIRE_EQUAL(trhd.sequence_number, header_data.sequence_number);
     321              :   // BOOST_REQUIRE_EQUAL(trhd.max_sequence_number, header_data.max_sequence_number);
     322              :   // BOOST_REQUIRE_EQUAL(trhd.num_requested_components, header_data.num_requested_components);
     323            1 : }
     324              : 
     325              : BOOST_AUTO_TEST_SUITE_END()
        

Generated by: LCOV version 2.0-1