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

            Line data    Source code
       1              : /**
       2              :  * @file HSIFrame_test.cxx HSIFrame class Unit Tests
       3              :  *
       4              :  * This is part of the DUNE DAQ Application Framework, copyright 2022.
       5              :  * Licensing/copyright details are in the COPYING file that you should have
       6              :  * received with this code.
       7              :  */
       8              : 
       9              : #include "detdataformats/HSIFrame.hpp"
      10              : 
      11              : #define BOOST_TEST_MODULE HSIFrame_test // NOLINT
      12              : 
      13              : #include "boost/test/unit_test.hpp"
      14              : 
      15              : #include <cstring>
      16              : #include <limits>
      17              : #include <vector>
      18              : 
      19              : using namespace dunedaq::detdataformats;
      20              : 
      21              : // Unit tests for a data formats library can expect to work with a lot of unsigned integers
      22              : // NOLINTBEGIN(build/unsigned)
      23              : 
      24              : namespace {
      25              : // Helper to create HSIFrame from individual components
      26              : HSIFrame
      27            4 : make_frame(uint32_t version,
      28              :            uint32_t detector_id,
      29              :            uint32_t crate,
      30              :            uint32_t slot,
      31              :            uint32_t link,
      32              :            uint64_t timestamp,
      33              :            uint32_t input_low,
      34              :            uint32_t input_high,
      35              :            uint32_t trigger,
      36              :            uint32_t sequence)
      37              : {
      38            4 :   HSIFrame frame;
      39            4 :   frame.version = version;
      40            4 :   frame.detector_id = detector_id;
      41            4 :   frame.crate = crate;
      42            4 :   frame.slot = slot;
      43            4 :   frame.link = link;
      44            4 :   frame.set_timestamp(timestamp);
      45            4 :   frame.input_low = input_low;
      46            4 :   frame.input_high = input_high;
      47            4 :   frame.trigger = trigger;
      48            4 :   frame.sequence = sequence;
      49            4 :   return frame;
      50              : }
      51              : } // namespace ""
      52              : 
      53              : BOOST_AUTO_TEST_SUITE(HSIFrame_test)
      54              : 
      55            2 : BOOST_AUTO_TEST_CASE(DefaultConstruction)
      56              : {
      57            1 :   HSIFrame frame;
      58              : 
      59              :   // Note: bitfield members are uninitialized by default, so we don't test them here
      60            1 :   BOOST_REQUIRE_EQUAL(frame.get_timestamp(), std::numeric_limits<uint64_t>::max());
      61            1 :   BOOST_REQUIRE_EQUAL(frame.input_low, std::numeric_limits<uint32_t>::max());
      62            1 :   BOOST_REQUIRE_EQUAL(frame.input_high, std::numeric_limits<uint32_t>::max());
      63            1 :   BOOST_REQUIRE_EQUAL(frame.trigger, std::numeric_limits<uint32_t>::max());
      64            1 :   BOOST_REQUIRE_EQUAL(frame.sequence, std::numeric_limits<uint32_t>::max());
      65            1 : }
      66              : 
      67            2 : BOOST_AUTO_TEST_CASE(GetTimestamp)
      68              : {
      69            1 :   HSIFrame frame;
      70              : 
      71            1 :   uint64_t ts = frame.get_timestamp();
      72            1 :   BOOST_REQUIRE_EQUAL(ts, std::numeric_limits<uint64_t>::max());
      73            1 : }
      74              : 
      75            2 : BOOST_AUTO_TEST_CASE(SetTimestampMax)
      76              : {
      77            1 :   HSIFrame frame;
      78              : 
      79            1 :   uint64_t max_ts = std::numeric_limits<uint64_t>::max();
      80            1 :   frame.set_timestamp(max_ts);
      81            1 :   BOOST_REQUIRE_EQUAL(frame.get_timestamp(), max_ts);
      82            1 :   BOOST_REQUIRE_EQUAL(frame.timestamp_low, std::numeric_limits<uint32_t>::max());
      83            1 :   BOOST_REQUIRE_EQUAL(frame.timestamp_high, std::numeric_limits<uint32_t>::max());
      84            1 : }
      85              : 
      86            2 : BOOST_AUTO_TEST_CASE(SetTimestampSplit)
      87              : {
      88            1 :   HSIFrame frame;
      89              : 
      90              :   // Test a 64-bit value that crosses the 32-bit boundary
      91            1 :   uint64_t ts = 0x0123456789ABCDEF;
      92            1 :   frame.set_timestamp(ts);
      93              : 
      94            1 :   BOOST_REQUIRE_EQUAL(frame.get_timestamp(), ts);
      95            1 :   BOOST_REQUIRE_EQUAL(frame.timestamp_low, 0x89ABCDEF);  // lower 32 bits
      96            1 :   BOOST_REQUIRE_EQUAL(frame.timestamp_high, 0x01234567); // upper 32 bits
      97            1 : }
      98              : 
      99            2 : BOOST_AUTO_TEST_CASE(TimestampRoundTrip)
     100              : {
     101              :   // Test a range of timestamp values
     102            1 :   const std::vector<uint64_t> test_timestamps = { 0,
     103              :                                                   1,
     104              :                                                   0xFF,
     105              :                                                   0xFFFFFFFF,  // max 32-bit
     106              :                                                   0x100000000, // just above 32-bit
     107              :                                                   0x123456789ABCDEF0,
     108            1 :                                                   std::numeric_limits<uint64_t>::max() };
     109              : 
     110            8 :   for (const auto& ts : test_timestamps) {
     111            7 :     HSIFrame frame;
     112            7 :     frame.set_timestamp(ts);
     113            7 :     BOOST_REQUIRE_EQUAL(frame.get_timestamp(), ts);
     114              :   }
     115            1 : }
     116              : 
     117            2 : BOOST_AUTO_TEST_CASE(BitfieldMembers)
     118              : {
     119            1 :   HSIFrame frame;
     120              : 
     121            1 :   frame.version = 5;
     122            1 :   frame.detector_id = 3;
     123            1 :   frame.crate = 7;
     124            1 :   frame.slot = 2;
     125            1 :   frame.link = 42;
     126              : 
     127            1 :   BOOST_REQUIRE_EQUAL(frame.version, 5);
     128            1 :   BOOST_REQUIRE_EQUAL(frame.detector_id, 3);
     129            1 :   BOOST_REQUIRE_EQUAL(frame.crate, 7);
     130            1 :   BOOST_REQUIRE_EQUAL(frame.slot, 2);
     131            1 :   BOOST_REQUIRE_EQUAL(frame.link, 42);
     132            1 : }
     133              : 
     134            2 : BOOST_AUTO_TEST_CASE(BitfieldMask)
     135              : {
     136            1 :   HSIFrame frame;
     137              : 
     138              :   // version is 6 bits: max value 63
     139            1 :   frame.version = 63;
     140            1 :   BOOST_REQUIRE_EQUAL(frame.version, 63);
     141              : 
     142              :   // detector_id is 6 bits: max value 63
     143            1 :   frame.detector_id = 63;
     144            1 :   BOOST_REQUIRE_EQUAL(frame.detector_id, 63);
     145              : 
     146              :   // crate is 10 bits: max value 1023
     147            1 :   frame.crate = 1023;
     148            1 :   BOOST_REQUIRE_EQUAL(frame.crate, 1023);
     149              : 
     150              :   // slot is 4 bits: max value 15
     151            1 :   frame.slot = 15;
     152            1 :   BOOST_REQUIRE_EQUAL(frame.slot, 15);
     153              : 
     154              :   // link is 6 bits: max value 63
     155            1 :   frame.link = 63;
     156            1 :   BOOST_REQUIRE_EQUAL(frame.link, 63);
     157            1 : }
     158              : 
     159            2 : BOOST_AUTO_TEST_CASE(RegularMembers)
     160              : {
     161            1 :   HSIFrame frame;
     162              : 
     163            1 :   frame.input_low = 0x11223344;
     164            1 :   frame.input_high = 0x55667788;
     165            1 :   frame.trigger = 0xDEADBEEF;
     166            1 :   frame.sequence = 0xCAFEBABE;
     167              : 
     168            1 :   BOOST_REQUIRE_EQUAL(frame.input_low, 0x11223344);
     169            1 :   BOOST_REQUIRE_EQUAL(frame.input_high, 0x55667788);
     170            1 :   BOOST_REQUIRE_EQUAL(frame.trigger, 0xDEADBEEF);
     171            1 :   BOOST_REQUIRE_EQUAL(frame.sequence, 0xCAFEBABE);
     172            1 : }
     173              : 
     174            2 : BOOST_AUTO_TEST_CASE(CompleteFrameSetup)
     175              : {
     176            1 :   HSIFrame frame = make_frame(5,                  // version
     177              :                               3,                  // detector_id
     178              :                               7,                  // crate
     179              :                               2,                  // slot
     180              :                               42,                 // link
     181              :                               0x0123456789ABCDEF, // timestamp
     182              :                               0x11111111,         // input_low
     183              :                               0x22222222,         // input_high
     184              :                               0x33333333,         // trigger
     185              :                               0x44444444          // sequence
     186              :   );
     187              : 
     188            1 :   BOOST_REQUIRE_EQUAL(frame.version, 5);
     189            1 :   BOOST_REQUIRE_EQUAL(frame.detector_id, 3);
     190            1 :   BOOST_REQUIRE_EQUAL(frame.crate, 7);
     191            1 :   BOOST_REQUIRE_EQUAL(frame.slot, 2);
     192            1 :   BOOST_REQUIRE_EQUAL(frame.link, 42);
     193            1 :   BOOST_REQUIRE_EQUAL(frame.get_timestamp(), 0x0123456789ABCDEF);
     194            1 :   BOOST_REQUIRE_EQUAL(frame.input_low, 0x11111111);
     195            1 :   BOOST_REQUIRE_EQUAL(frame.input_high, 0x22222222);
     196            1 :   BOOST_REQUIRE_EQUAL(frame.trigger, 0x33333333);
     197            1 :   BOOST_REQUIRE_EQUAL(frame.sequence, 0x44444444);
     198            1 : }
     199              : 
     200            2 : BOOST_AUTO_TEST_CASE(ByteRoundTrip)
     201              : {
     202              :   // Create a frame with specific values
     203            1 :   HSIFrame original = make_frame(5, 3, 7, 2, 42, 0x0123456789ABCDEF, 0x11111111, 0x22222222, 0x33333333, 0x44444444);
     204              : 
     205              :   // Serialize to bytes
     206            1 :   uint8_t buffer[sizeof(HSIFrame)]; // NOLINT(modernize-avoid-c-arrays)
     207            1 :   std::memcpy(buffer, &original, sizeof(HSIFrame));
     208              : 
     209              :   // Deserialize from bytes
     210            1 :   HSIFrame recovered;
     211            1 :   std::memcpy(&recovered, buffer, sizeof(HSIFrame));
     212              : 
     213              :   // Verify all fields match
     214            1 :   BOOST_REQUIRE_EQUAL(recovered.version, original.version);
     215            1 :   BOOST_REQUIRE_EQUAL(recovered.detector_id, original.detector_id);
     216            1 :   BOOST_REQUIRE_EQUAL(recovered.crate, original.crate);
     217            1 :   BOOST_REQUIRE_EQUAL(recovered.slot, original.slot);
     218            1 :   BOOST_REQUIRE_EQUAL(recovered.link, original.link);
     219            1 :   BOOST_REQUIRE_EQUAL(recovered.get_timestamp(), original.get_timestamp());
     220            1 :   BOOST_REQUIRE_EQUAL(recovered.input_low, original.input_low);
     221            1 :   BOOST_REQUIRE_EQUAL(recovered.input_high, original.input_high);
     222            1 :   BOOST_REQUIRE_EQUAL(recovered.trigger, original.trigger);
     223            1 :   BOOST_REQUIRE_EQUAL(recovered.sequence, original.sequence);
     224            1 : }
     225              : 
     226            2 : BOOST_AUTO_TEST_CASE(TimestampEndianness)
     227              : {
     228            1 :   HSIFrame frame;
     229              : 
     230              :   // Set timestamp to a value where endianness matters
     231            1 :   uint64_t ts = 0x0102030405060708;
     232            1 :   frame.set_timestamp(ts);
     233              : 
     234              :   // On little-endian: low 32 bits should be 0x05060708, high 32 bits should be 0x01020304
     235            1 :   BOOST_REQUIRE_EQUAL(frame.timestamp_low, 0x05060708);
     236            1 :   BOOST_REQUIRE_EQUAL(frame.timestamp_high, 0x01020304);
     237              : 
     238              :   // Verify get_timestamp reconstructs it correctly
     239            1 :   BOOST_REQUIRE_EQUAL(frame.get_timestamp(), ts);
     240            1 : }
     241              : 
     242            2 : BOOST_AUTO_TEST_CASE(MultipleFramesIndependent)
     243              : {
     244            1 :   HSIFrame frame1 = make_frame(1, 1, 1, 1, 1, 0x1111111111111111, 0x11, 0x11, 0x11, 0x11);
     245            1 :   HSIFrame frame2 = make_frame(2, 2, 2, 2, 2, 0x2222222222222222, 0x22, 0x22, 0x22, 0x22);
     246              : 
     247              :   // Verify they're independent
     248            1 :   BOOST_REQUIRE_EQUAL(frame1.version, 1);
     249            1 :   BOOST_REQUIRE_EQUAL(frame2.version, 2);
     250              : 
     251            1 :   BOOST_REQUIRE_EQUAL(frame1.get_timestamp(), 0x1111111111111111);
     252            1 :   BOOST_REQUIRE_EQUAL(frame2.get_timestamp(), 0x2222222222222222);
     253              : 
     254              :   // Modify frame1, verify frame2 unchanged
     255            1 :   frame1.version = 5; // Use a value that fits in 6 bits
     256            1 :   BOOST_REQUIRE_EQUAL(frame1.version, 5);
     257            1 :   BOOST_REQUIRE_EQUAL(frame1.version, 5);
     258            1 :   BOOST_REQUIRE_EQUAL(frame2.version, 2);
     259            1 : }
     260              : 
     261            2 : BOOST_AUTO_TEST_CASE(EdgeCaseHighBitfieldValues)
     262              : {
     263            1 :   HSIFrame frame;
     264              : 
     265              :   // Set all bitfields to maximum valid values for their bit widths
     266            1 :   frame.version = (1u << 6) - 1;     // 6 bits: 0x3F = 63
     267            1 :   frame.detector_id = (1u << 6) - 1; // 6 bits: 0x3F = 63
     268            1 :   frame.crate = (1u << 10) - 1;      // 10 bits: 0x3FF = 1023
     269            1 :   frame.slot = (1u << 4) - 1;        // 4 bits: 0xF = 15
     270            1 :   frame.link = (1u << 6) - 1;        // 6 bits: 0x3F = 63
     271              : 
     272              :   // Verify all are at max
     273            1 :   BOOST_REQUIRE_EQUAL(frame.version, 63);
     274            1 :   BOOST_REQUIRE_EQUAL(frame.detector_id, 63);
     275            1 :   BOOST_REQUIRE_EQUAL(frame.crate, 1023);
     276            1 :   BOOST_REQUIRE_EQUAL(frame.slot, 15);
     277            1 :   BOOST_REQUIRE_EQUAL(frame.link, 63);
     278            1 : }
     279              : 
     280              : BOOST_AUTO_TEST_SUITE_END()
     281              : 
     282              : // NOLINTEND(build/unsigned)
        

Generated by: LCOV version 2.0-1