Line data Source code
1 : /**
2 : * @file DAQEthHeader_test.cxx DAQEthHeader 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/DAQEthHeader.hpp"
10 :
11 : #define BOOST_TEST_MODULE DAQEthHeader_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 <vector>
20 :
21 : #pragma GCC diagnostic ignored "-Woverflow" // intentional overflows are performed as part of testing
22 :
23 : using namespace dunedaq::detdataformats;
24 :
25 : // Unit tests for a data formats library can expect to work with a lot of unsigned integers
26 : // NOLINTBEGIN(build/unsigned)
27 :
28 : namespace {
29 : using word_t = DAQEthHeader::word_t;
30 :
31 : DAQEthHeader
32 11 : make_header(word_t version,
33 : word_t det_id,
34 : word_t crate_id,
35 : word_t slot_id,
36 : word_t stream_id,
37 : word_t reserved,
38 : word_t seq_id,
39 : word_t block_length,
40 : word_t timestamp)
41 : {
42 11 : DAQEthHeader 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.stream_id = stream_id;
48 11 : header.reserved = reserved;
49 11 : header.seq_id = seq_id;
50 11 : header.block_length = block_length;
51 11 : header.timestamp = timestamp;
52 11 : return header;
53 : }
54 :
55 : DAQEthHeader
56 1 : header_from_stream_output(const std::string& output)
57 : {
58 1 : std::istringstream iss(output);
59 :
60 1 : std::string version_token;
61 1 : std::string det_id_token;
62 1 : std::string crate_id_token;
63 1 : std::string slot_id_token;
64 1 : std::string stream_id_token;
65 1 : std::string sequence_label;
66 1 : unsigned int sequence_value{};
67 1 : std::string block_label;
68 1 : std::string block_length_label;
69 1 : unsigned int block_length_value{};
70 1 : std::string timestamp_label;
71 1 : uint64_t timestamp_value{};
72 :
73 1 : iss >> version_token >> det_id_token >> crate_id_token >> slot_id_token >> stream_id_token >> sequence_label >>
74 1 : sequence_value >> block_label >> block_length_label >> block_length_value >> timestamp_label >> timestamp_value;
75 :
76 1 : BOOST_REQUIRE_EQUAL(sequence_label, "SequenceID:");
77 1 : BOOST_REQUIRE_EQUAL(block_label, "Block");
78 1 : BOOST_REQUIRE_EQUAL(block_length_label, "length:");
79 1 : BOOST_REQUIRE_EQUAL(timestamp_label, "Timestamp:");
80 :
81 2 : return make_header(static_cast<word_t>(std::stoull(version_token.substr(std::string("Version:").size()))),
82 2 : static_cast<word_t>(std::stoull(det_id_token.substr(std::string("DetID:").size()))),
83 2 : static_cast<word_t>(std::stoull(crate_id_token.substr(std::string("CrateID:").size()))),
84 2 : static_cast<word_t>(std::stoull(slot_id_token.substr(std::string("SlotID:").size()))),
85 2 : static_cast<word_t>(std::stoull(stream_id_token.substr(std::string("StreamID:").size()))),
86 : 0,
87 : static_cast<word_t>(sequence_value),
88 : static_cast<word_t>(block_length_value),
89 1 : static_cast<word_t>(timestamp_value));
90 1 : }
91 : } // namespace ""
92 :
93 : BOOST_AUTO_TEST_SUITE(DAQEthHeader_test)
94 :
95 2 : BOOST_AUTO_TEST_CASE(DefaultConstruction)
96 : {
97 1 : DAQEthHeader header;
98 :
99 1 : BOOST_REQUIRE_EQUAL(header.timestamp, std::numeric_limits<word_t>::max());
100 1 : BOOST_REQUIRE_EQUAL(header.get_timestamp(), std::numeric_limits<uint64_t>::max());
101 1 : }
102 :
103 2 : BOOST_AUTO_TEST_CASE(TimestampAccess)
104 : {
105 1 : const DAQEthHeader header = make_header(0, 0, 0, 0, 0, 0, 0, 0, 0x0123456789ABCDEFULL);
106 :
107 1 : BOOST_REQUIRE_EQUAL(header.get_timestamp(), 0x0123456789ABCDEFULL);
108 1 : }
109 :
110 2 : BOOST_AUTO_TEST_CASE(TimestampRoundTripFromGetTimestamp)
111 : {
112 1 : const std::vector<word_t> values = {
113 : 0x0000000000000000ULL, 0x0000000000000001ULL, 0x0123456789ABCDEFULL, 0xFEDCBA9876543210ULL, 0xFFFFFFFFFFFFFFFFULL
114 1 : };
115 :
116 6 : for (const auto& value : values) {
117 5 : const DAQEthHeader original = make_header(0, 0, 0, 0, 0, 0, 0, 0, value);
118 5 : const uint64_t timestamp = original.get_timestamp();
119 :
120 5 : BOOST_REQUIRE_EQUAL(static_cast<word_t>(timestamp), original.timestamp);
121 : }
122 1 : }
123 :
124 2 : BOOST_AUTO_TEST_CASE(BitfieldUpperBounds)
125 : {
126 1 : const DAQEthHeader header = make_header(63, 63, 1023, 15, 255, 63, 4095, 4095, 0);
127 :
128 1 : BOOST_REQUIRE_EQUAL(header.version, 63);
129 1 : BOOST_REQUIRE_EQUAL(header.det_id, 63);
130 1 : BOOST_REQUIRE_EQUAL(header.crate_id, 1023);
131 1 : BOOST_REQUIRE_EQUAL(header.slot_id, 15);
132 1 : BOOST_REQUIRE_EQUAL(header.stream_id, 255);
133 1 : BOOST_REQUIRE_EQUAL(header.reserved, 63);
134 1 : BOOST_REQUIRE_EQUAL(header.seq_id, 4095);
135 1 : BOOST_REQUIRE_EQUAL(header.block_length, 4095);
136 1 : }
137 :
138 2 : BOOST_AUTO_TEST_CASE(BitfieldMasking)
139 : {
140 1 : DAQEthHeader header = make_header(0, 0, 0, 0, 0, 0, 0, 0, 0);
141 :
142 1 : header.version = 99; // NOLINT 99 & 0x3F = 35
143 1 : header.det_id = 127; // NOLINT 127 & 0x3F = 63
144 1 : header.crate_id = 2048; // NOLINT 2048 & 0x3FF = 0
145 1 : header.slot_id = 31; // NOLINT 31 & 0x0F = 15
146 1 : header.stream_id = 511; // NOLINT 511 & 0xFF = 255
147 1 : header.reserved = 127; // NOLINT 127 & 0x3F = 63
148 1 : header.seq_id = 5000; // NOLINT 5000 & 0xFFF = 904
149 1 : header.block_length = 5000; // NOLINT 5000 & 0xFFF = 904
150 :
151 1 : BOOST_REQUIRE_EQUAL(header.version, 35);
152 1 : BOOST_REQUIRE_EQUAL(header.det_id, 63);
153 1 : BOOST_REQUIRE_EQUAL(header.crate_id, 0);
154 1 : BOOST_REQUIRE_EQUAL(header.slot_id, 15);
155 1 : BOOST_REQUIRE_EQUAL(header.stream_id, 255);
156 1 : BOOST_REQUIRE_EQUAL(header.reserved, 63);
157 1 : BOOST_REQUIRE_EQUAL(header.seq_id, 904);
158 1 : BOOST_REQUIRE_EQUAL(header.block_length, 904);
159 1 : }
160 :
161 2 : BOOST_AUTO_TEST_CASE(StreamOperatorRoundTrip)
162 : {
163 1 : const DAQEthHeader original = make_header(7, 3, 22, 4, 9, 0, 1234, 88, 0x0123456789ABCDEFULL);
164 :
165 1 : std::ostringstream oss;
166 1 : oss << original;
167 1 : const std::string output = oss.str();
168 1 : const DAQEthHeader recovered = header_from_stream_output(output);
169 :
170 1 : BOOST_REQUIRE(!output.empty());
171 1 : BOOST_REQUIRE(output.back() == '\n');
172 :
173 1 : BOOST_REQUIRE_EQUAL(recovered.version, original.version);
174 1 : BOOST_REQUIRE_EQUAL(recovered.det_id, original.det_id);
175 1 : BOOST_REQUIRE_EQUAL(recovered.crate_id, original.crate_id);
176 1 : BOOST_REQUIRE_EQUAL(recovered.slot_id, original.slot_id);
177 1 : BOOST_REQUIRE_EQUAL(recovered.stream_id, original.stream_id);
178 1 : BOOST_REQUIRE_EQUAL(recovered.reserved, original.reserved);
179 1 : BOOST_REQUIRE_EQUAL(recovered.seq_id, original.seq_id);
180 1 : BOOST_REQUIRE_EQUAL(recovered.block_length, original.block_length);
181 1 : BOOST_REQUIRE_EQUAL(recovered.timestamp, original.timestamp);
182 1 : }
183 :
184 2 : BOOST_AUTO_TEST_CASE(ByteRoundTrip)
185 : {
186 1 : const DAQEthHeader original = make_header(13, 21, 777, 10, 55, 6, 2048, 1024, 0x1122334455667788ULL);
187 :
188 1 : uint8_t buffer[sizeof(DAQEthHeader)]; // NOLINT(modernize-avoid-c-arrays)
189 1 : std::memcpy(buffer, &original, sizeof(DAQEthHeader));
190 :
191 1 : DAQEthHeader recovered;
192 1 : std::memcpy(&recovered, buffer, sizeof(DAQEthHeader));
193 :
194 1 : BOOST_REQUIRE_EQUAL(recovered.version, original.version);
195 1 : BOOST_REQUIRE_EQUAL(recovered.det_id, original.det_id);
196 1 : BOOST_REQUIRE_EQUAL(recovered.crate_id, original.crate_id);
197 1 : BOOST_REQUIRE_EQUAL(recovered.slot_id, original.slot_id);
198 1 : BOOST_REQUIRE_EQUAL(recovered.stream_id, original.stream_id);
199 1 : BOOST_REQUIRE_EQUAL(recovered.reserved, original.reserved);
200 1 : BOOST_REQUIRE_EQUAL(recovered.seq_id, original.seq_id);
201 1 : BOOST_REQUIRE_EQUAL(recovered.block_length, original.block_length);
202 1 : BOOST_REQUIRE_EQUAL(recovered.timestamp, original.timestamp);
203 1 : BOOST_REQUIRE_EQUAL(recovered.get_timestamp(), original.get_timestamp());
204 1 : }
205 :
206 : BOOST_AUTO_TEST_SUITE_END()
207 :
208 : // NOLINTEND(build/unsigned)
|