Line data Source code
1 : /**
2 : * @file DAQHeader_test.cxx DAQHeader 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/DAQHeader.hpp"
10 :
11 : #define BOOST_TEST_MODULE DAQHeader_test // NOLINT
12 :
13 : #include "boost/test/unit_test.hpp"
14 :
15 : #include <cstring>
16 : #include <limits>
17 : #include <sstream>
18 : #include <string>
19 : #include <tuple>
20 : #include <utility>
21 : #include <vector>
22 :
23 : #pragma GCC diagnostic ignored "-Woverflow" // intentional overflows are performed as part of testing
24 :
25 : using namespace dunedaq::detdataformats;
26 :
27 : // Unit tests for a data formats library can expect to work with a lot of unsigned integers
28 : // NOLINTBEGIN(build/unsigned)
29 :
30 : namespace {
31 : using word_t = DAQHeader::word_t;
32 :
33 : DAQHeader
34 11 : make_header(word_t version,
35 : word_t det_id,
36 : word_t crate_id,
37 : word_t slot_id,
38 : word_t link_id,
39 : word_t timestamp_1,
40 : word_t timestamp_2)
41 : {
42 11 : DAQHeader header;
43 11 : header.version = version;
44 11 : header.det_id = det_id;
45 11 : header.crate_id = crate_id;
46 11 : header.slot_id = slot_id;
47 11 : header.link_id = link_id;
48 11 : header.timestamp_1 = timestamp_1;
49 11 : header.timestamp_2 = timestamp_2;
50 11 : return header;
51 : }
52 :
53 : std::pair<word_t, word_t>
54 6 : split_timestamp(uint64_t timestamp)
55 : {
56 6 : return { static_cast<word_t>(timestamp), static_cast<word_t>(timestamp >> 32) };
57 : }
58 :
59 : DAQHeader
60 1 : header_from_stream_output(const std::string& output)
61 : {
62 1 : std::istringstream iss(output);
63 :
64 1 : std::string version_token;
65 1 : std::string det_id_token;
66 1 : std::string crate_id_token;
67 1 : std::string slot_id_token;
68 1 : std::string link_id_token;
69 1 : std::string timestamp_label;
70 1 : uint64_t timestamp_value{};
71 :
72 1 : iss >> version_token >> det_id_token >> crate_id_token >> slot_id_token >> link_id_token >> timestamp_label >>
73 1 : timestamp_value;
74 :
75 1 : const auto [timestamp_1, timestamp_2] = split_timestamp(timestamp_value);
76 :
77 5 : return make_header(static_cast<word_t>(std::stoul(version_token.substr(std::string("Version:").size()))),
78 2 : static_cast<word_t>(std::stoul(det_id_token.substr(std::string("DetID:").size()))),
79 2 : static_cast<word_t>(std::stoul(crate_id_token.substr(std::string("CrateID:").size()))),
80 2 : static_cast<word_t>(std::stoul(slot_id_token.substr(std::string("SlotID:").size()))),
81 2 : static_cast<word_t>(std::stoul(link_id_token.substr(std::string("LinkID:").size()))),
82 : timestamp_1,
83 1 : timestamp_2);
84 1 : }
85 : } // namespace ""
86 :
87 : BOOST_AUTO_TEST_SUITE(DAQHeader_test)
88 :
89 2 : BOOST_AUTO_TEST_CASE(DefaultConstruction)
90 : {
91 1 : DAQHeader header;
92 :
93 1 : BOOST_REQUIRE_EQUAL(header.timestamp_1, std::numeric_limits<word_t>::max());
94 1 : BOOST_REQUIRE_EQUAL(header.timestamp_2, std::numeric_limits<word_t>::max());
95 1 : BOOST_REQUIRE_EQUAL(header.get_timestamp(), std::numeric_limits<uint64_t>::max());
96 1 : }
97 :
98 2 : BOOST_AUTO_TEST_CASE(TimestampAssembly)
99 : {
100 1 : DAQHeader header = make_header(0, 0, 0, 0, 0, 0x89ABCDEF, 0x01234567);
101 :
102 1 : BOOST_REQUIRE_EQUAL(header.get_timestamp(), 0x0123456789ABCDEFULL);
103 1 : }
104 :
105 2 : BOOST_AUTO_TEST_CASE(TimestampRoundTripFromGetTimestamp)
106 : {
107 1 : const std::vector<std::pair<word_t, word_t>> values = { { 0x00000000u, 0x00000000u },
108 : { 0xFFFFFFFFu, 0x00000000u },
109 : { 0x00000000u, 0xFFFFFFFFu },
110 : { 0x01234567u, 0x89ABCDEFu },
111 1 : { 0xFFFFFFFFu, 0xFFFFFFFFu } };
112 :
113 6 : for (const auto& value : values) {
114 5 : const DAQHeader original = make_header(0, 0, 0, 0, 0, value.first, value.second);
115 5 : const uint64_t timestamp = original.get_timestamp();
116 5 : const auto [timestamp_1, timestamp_2] = split_timestamp(timestamp);
117 :
118 5 : BOOST_REQUIRE_EQUAL(timestamp_1, original.timestamp_1);
119 5 : BOOST_REQUIRE_EQUAL(timestamp_2, original.timestamp_2);
120 : }
121 1 : }
122 :
123 2 : BOOST_AUTO_TEST_CASE(BitfieldUpperBounds)
124 : {
125 1 : DAQHeader header = make_header(63, 63, 1023, 15, 63, 0, 0);
126 :
127 1 : BOOST_REQUIRE_EQUAL(header.version, 63);
128 1 : BOOST_REQUIRE_EQUAL(header.det_id, 63);
129 1 : BOOST_REQUIRE_EQUAL(header.crate_id, 1023);
130 1 : BOOST_REQUIRE_EQUAL(header.slot_id, 15);
131 1 : BOOST_REQUIRE_EQUAL(header.link_id, 63);
132 1 : }
133 :
134 2 : BOOST_AUTO_TEST_CASE(BitfieldMasking)
135 : {
136 1 : DAQHeader header = make_header(0, 0, 0, 0, 0, 0, 0);
137 :
138 1 : header.version = 99; // NOLINT 99 & 0x3F = 35
139 1 : header.det_id = 127; // NOLINT 127 & 0x3F = 63
140 1 : header.crate_id = 2048; // NOLINT 2048 & 0x3FF = 0
141 1 : header.slot_id = 31; // NOLINT 31 & 0x0F = 15
142 1 : header.link_id = 65; // NOLINT 65 & 0x3F = 1
143 :
144 1 : BOOST_REQUIRE_EQUAL(header.version, 35);
145 1 : BOOST_REQUIRE_EQUAL(header.det_id, 63);
146 1 : BOOST_REQUIRE_EQUAL(header.crate_id, 0);
147 1 : BOOST_REQUIRE_EQUAL(header.slot_id, 15);
148 1 : BOOST_REQUIRE_EQUAL(header.link_id, 1);
149 1 : }
150 :
151 2 : BOOST_AUTO_TEST_CASE(StreamOperatorRoundTrip)
152 : {
153 1 : const DAQHeader original = make_header(7, 3, 22, 4, 9, 0x01234567, 0x89ABCDEF);
154 :
155 1 : std::ostringstream oss;
156 1 : oss << original;
157 1 : const std::string output = oss.str();
158 1 : const DAQHeader recovered = header_from_stream_output(output);
159 :
160 1 : BOOST_REQUIRE(!output.empty());
161 1 : BOOST_REQUIRE(output.back() == '\n');
162 :
163 1 : BOOST_REQUIRE_EQUAL(recovered.version, original.version);
164 1 : BOOST_REQUIRE_EQUAL(recovered.det_id, original.det_id);
165 1 : BOOST_REQUIRE_EQUAL(recovered.crate_id, original.crate_id);
166 1 : BOOST_REQUIRE_EQUAL(recovered.slot_id, original.slot_id);
167 1 : BOOST_REQUIRE_EQUAL(recovered.link_id, original.link_id);
168 1 : BOOST_REQUIRE_EQUAL(recovered.timestamp_1, original.timestamp_1);
169 1 : BOOST_REQUIRE_EQUAL(recovered.timestamp_2, original.timestamp_2);
170 1 : }
171 :
172 2 : BOOST_AUTO_TEST_CASE(ByteRoundTrip)
173 : {
174 1 : const DAQHeader original = make_header(13, 21, 777, 10, 55, 0x11111111, 0x22222222);
175 :
176 1 : uint8_t buffer[sizeof(DAQHeader)]; // NOLINT(modernize-avoid-c-arrays)
177 1 : std::memcpy(buffer, &original, sizeof(DAQHeader));
178 :
179 1 : DAQHeader recovered;
180 1 : std::memcpy(&recovered, buffer, sizeof(DAQHeader));
181 :
182 1 : BOOST_REQUIRE_EQUAL(recovered.version, original.version);
183 1 : BOOST_REQUIRE_EQUAL(recovered.det_id, original.det_id);
184 1 : BOOST_REQUIRE_EQUAL(recovered.crate_id, original.crate_id);
185 1 : BOOST_REQUIRE_EQUAL(recovered.slot_id, original.slot_id);
186 1 : BOOST_REQUIRE_EQUAL(recovered.link_id, original.link_id);
187 1 : BOOST_REQUIRE_EQUAL(recovered.timestamp_1, original.timestamp_1);
188 1 : BOOST_REQUIRE_EQUAL(recovered.timestamp_2, original.timestamp_2);
189 1 : BOOST_REQUIRE_EQUAL(recovered.get_timestamp(), original.get_timestamp());
190 1 : }
191 :
192 : BOOST_AUTO_TEST_SUITE_END()
193 :
194 : // NOLINTEND(build/unsigned)
|