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 1 : BOOST_REQUIRE_THROW((*header)[header->get_header().num_requested_components], std::range_error);
79 :
80 1 : void* buff = malloc(header->get_total_size_bytes());
81 1 : std::memcpy(buff, header->get_storage_location(), header->get_total_size_bytes());
82 :
83 : // Constructor should copy header
84 1 : TriggerRecordHeader copy_header(const_cast<void*>(header->get_storage_location()), true);
85 1 : delete header; // NOLINT(build/raw_ownership)
86 :
87 1 : BOOST_REQUIRE_EQUAL(copy_header.get_run_number(), 9);
88 1 : BOOST_REQUIRE_EQUAL(copy_header.get_sequence_number(), 13);
89 1 : BOOST_REQUIRE_EQUAL(copy_header.get_max_sequence_number(), 14);
90 1 : BOOST_REQUIRE_EQUAL(copy_header.get_status_bit(static_cast<TriggerRecordStatusBits>(0)), false);
91 1 : BOOST_REQUIRE_EQUAL(copy_header.get_status_bit(static_cast<TriggerRecordStatusBits>(1)), true);
92 1 : BOOST_REQUIRE_EQUAL(copy_header.get_header().status_bits, 10);
93 1 : BOOST_REQUIRE_EQUAL(copy_header.at(0).window_begin, 3);
94 1 : BOOST_REQUIRE_EQUAL(copy_header[1].window_begin, 7);
95 :
96 1 : {
97 : // Test copy constructor
98 1 : TriggerRecordHeader copy_copy_header(copy_header);
99 1 : BOOST_REQUIRE_EQUAL(copy_copy_header.get_run_number(), 9);
100 1 : BOOST_REQUIRE_EQUAL(copy_copy_header.get_sequence_number(), 13);
101 1 : BOOST_REQUIRE_EQUAL(copy_copy_header.get_max_sequence_number(), 14);
102 1 : BOOST_REQUIRE_EQUAL(copy_copy_header.get_status_bit(static_cast<TriggerRecordStatusBits>(0)), false);
103 1 : BOOST_REQUIRE_EQUAL(copy_copy_header.get_status_bit(static_cast<TriggerRecordStatusBits>(1)), true);
104 1 : BOOST_REQUIRE_EQUAL(copy_copy_header.get_header().status_bits, 10);
105 1 : BOOST_REQUIRE_EQUAL(copy_copy_header.at(0).window_begin, 3);
106 1 : BOOST_REQUIRE_EQUAL(copy_copy_header[1].window_begin, 7);
107 1 : }
108 1 : {
109 : // Test copy assignment
110 1 : TriggerRecordHeader copy_assign_header = copy_header;
111 1 : BOOST_REQUIRE_EQUAL(copy_assign_header.get_run_number(), 9);
112 1 : BOOST_REQUIRE_EQUAL(copy_assign_header.get_sequence_number(), 13);
113 1 : BOOST_REQUIRE_EQUAL(copy_assign_header.get_max_sequence_number(), 14);
114 1 : BOOST_REQUIRE_EQUAL(copy_assign_header.get_status_bit(static_cast<TriggerRecordStatusBits>(0)), false);
115 1 : BOOST_REQUIRE_EQUAL(copy_assign_header.get_status_bit(static_cast<TriggerRecordStatusBits>(1)), true);
116 1 : BOOST_REQUIRE_EQUAL(copy_assign_header.get_header().status_bits, 10);
117 1 : BOOST_REQUIRE_EQUAL(copy_assign_header.at(0).window_begin, 3);
118 1 : BOOST_REQUIRE_EQUAL(copy_assign_header[1].window_begin, 7);
119 1 : }
120 :
121 1 : {
122 : // Test Buffer adoption constructor
123 1 : TriggerRecordHeader buffer_header(buff, false);
124 :
125 1 : BOOST_REQUIRE_EQUAL(buffer_header.get_run_number(), 9);
126 1 : BOOST_REQUIRE_EQUAL(buffer_header.get_sequence_number(), 13);
127 1 : BOOST_REQUIRE_EQUAL(buffer_header.get_max_sequence_number(), 14);
128 1 : BOOST_REQUIRE_EQUAL(buffer_header.get_status_bit(static_cast<TriggerRecordStatusBits>(0)), false);
129 1 : BOOST_REQUIRE_EQUAL(buffer_header.get_status_bit(static_cast<TriggerRecordStatusBits>(1)), true);
130 1 : BOOST_REQUIRE_EQUAL(buffer_header.get_header().status_bits, 10);
131 1 : BOOST_REQUIRE_EQUAL(buffer_header.at(0).window_begin, 3);
132 1 : BOOST_REQUIRE_EQUAL(buffer_header[1].window_begin, 7);
133 1 : }
134 :
135 1 : BOOST_REQUIRE_EQUAL(*reinterpret_cast<uint32_t*>(buff), // NOLINT
136 : TriggerRecordHeaderData::s_trigger_record_header_magic);
137 :
138 1 : free(buff);
139 1 : }
140 :
141 2 : BOOST_AUTO_TEST_CASE(MoveConstructor)
142 : {
143 1 : std::vector<ComponentRequest> components;
144 1 : components.emplace_back();
145 1 : components.back().component = { SourceID::Subsystem::kDetectorReadout, 12 };
146 1 : components.back().window_begin = 3;
147 1 : components.back().window_end = 4;
148 1 : components.emplace_back();
149 1 : components.back().component = { SourceID::Subsystem::kDetectorReadout, 56 };
150 1 : components.back().window_begin = 7;
151 1 : components.back().window_end = 8;
152 :
153 1 : auto header = new TriggerRecordHeader(components);
154 :
155 1 : TriggerRecordHeader another_header(std::move(*header));
156 :
157 1 : delete header; // NOLINT We are specifically testing what happens when the original trh is deleted
158 :
159 1 : BOOST_REQUIRE_EQUAL(another_header.get_num_requested_components(), 2);
160 1 : }
161 :
162 2 : BOOST_AUTO_TEST_CASE(MoveAssignment)
163 : {
164 1 : std::vector<ComponentRequest> components;
165 1 : components.emplace_back();
166 1 : components.back().component = { SourceID::Subsystem::kDetectorReadout, 12 };
167 1 : components.back().window_begin = 3;
168 1 : components.back().window_end = 4;
169 1 : components.emplace_back();
170 1 : components.back().component = { SourceID::Subsystem::kDetectorReadout, 56 };
171 1 : components.back().window_begin = 7;
172 1 : components.back().window_end = 8;
173 :
174 1 : auto header = new TriggerRecordHeader(components);
175 :
176 1 : auto another_header = std::move(*header);
177 :
178 1 : delete header; // NOLINT We are specifically testing what happens when the original trh is deleted
179 :
180 1 : BOOST_REQUIRE_EQUAL(another_header.get_num_requested_components(), 2);
181 1 : }
182 :
183 2 : BOOST_AUTO_TEST_CASE(BadConstructors)
184 : {
185 1 : TriggerRecordHeaderData header_data;
186 1 : header_data.num_requested_components = std::numeric_limits<uint64_t>::max() - 10; // NOLINT(build/unsigned)
187 1 : header_data.run_number = 9;
188 1 : header_data.trigger_number = 10;
189 1 : header_data.trigger_timestamp = 11;
190 1 : header_data.trigger_type = 12;
191 :
192 1 : auto hdr = malloc(sizeof(TriggerRecordHeaderData) + sizeof(ComponentRequest));
193 1 : std::memcpy(hdr, &header_data, sizeof(TriggerRecordHeaderData));
194 :
195 1 : #pragma GCC diagnostic push
196 1 : #pragma GCC diagnostic ignored "-Wrestrict"
197 1 : BOOST_REQUIRE_EXCEPTION(
198 : TriggerRecordHeader oversize_header(hdr, true), std::bad_alloc, [&](std::bad_alloc) { return true; });
199 1 : #pragma GCC diagnostic pop
200 :
201 1 : header_data.num_requested_components = 1;
202 1 : std::memcpy(hdr, &header_data, sizeof(TriggerRecordHeaderData));
203 1 : TriggerRecordHeader bad_header(hdr, false);
204 1 : BOOST_REQUIRE_EQUAL(bad_header.get_num_requested_components(), 1);
205 :
206 1 : reinterpret_cast<TriggerRecordHeaderData*>(hdr)->num_requested_components = // NOLINT
207 : std::numeric_limits<uint64_t>::max() - 10; // NOLINT(build/unsigned)
208 1 : BOOST_REQUIRE_EQUAL(bad_header.get_num_requested_components(),
209 : std::numeric_limits<uint64_t>::max() - 10); // NOLINT(build/unsigned)
210 :
211 1 : BOOST_REQUIRE_EXCEPTION(
212 : TriggerRecordHeader header_inst = bad_header, std::bad_alloc, [&](std::bad_alloc) { return true; });
213 :
214 1 : free(hdr);
215 1 : }
216 :
217 : /**
218 : * @brief Test header field manipulation methods
219 : */
220 2 : BOOST_AUTO_TEST_CASE(HeaderFields)
221 : {
222 1 : std::vector<ComponentRequest> components;
223 1 : components.emplace_back();
224 1 : components.back().component = { SourceID::Subsystem::kDetectorReadout, 12 };
225 1 : components.back().window_begin = 3;
226 1 : components.back().window_end = 4;
227 1 : components.emplace_back();
228 1 : components.back().component = { SourceID::Subsystem::kDetectorReadout, 34 };
229 1 : components.back().window_begin = 5;
230 1 : components.back().window_end = 6;
231 1 : components.emplace_back();
232 1 : components.back().component = { SourceID::Subsystem::kDetectorReadout, 56 };
233 1 : components.back().window_begin = 7;
234 1 : components.back().window_end = 8;
235 1 : components.emplace_back();
236 1 : components.back().component = { SourceID::Subsystem::kDetectorReadout, 78 };
237 1 : components.back().window_begin = 9;
238 1 : components.back().window_end = 10;
239 1 : components.emplace_back();
240 1 : components.back().component = { SourceID::Subsystem::kDetectorReadout, 90 };
241 1 : components.back().window_begin = 11;
242 1 : components.back().window_end = 12;
243 :
244 1 : auto header = new TriggerRecordHeader(components);
245 1 : header->set_run_number(9);
246 1 : header->set_trigger_number(10);
247 1 : header->set_trigger_timestamp(11);
248 1 : header->set_trigger_type(12);
249 1 : header->set_sequence_number(13);
250 1 : header->set_max_sequence_number(14);
251 1 : header->set_status_bit(TriggerRecordStatusBits::kMismatch, true);
252 1 : header->set_status_bit(TriggerRecordStatusBits::kUnassigned31, true);
253 :
254 1 : auto header_data = header->get_header();
255 1 : BOOST_REQUIRE_EQUAL(header->get_run_number(), header_data.run_number);
256 1 : BOOST_REQUIRE_EQUAL(header->get_trigger_number(), header_data.trigger_number);
257 1 : BOOST_REQUIRE_EQUAL(header->get_trigger_timestamp(), header_data.trigger_timestamp);
258 1 : BOOST_REQUIRE_EQUAL(header->get_trigger_type(), header_data.trigger_type);
259 1 : BOOST_REQUIRE_EQUAL(header->get_sequence_number(), header_data.sequence_number);
260 1 : BOOST_REQUIRE_EQUAL(header->get_max_sequence_number(), header_data.max_sequence_number);
261 1 : BOOST_REQUIRE_EQUAL(header->get_num_requested_components(), 5);
262 1 : BOOST_REQUIRE_EQUAL(header->get_num_requested_components(), header_data.num_requested_components);
263 1 : BOOST_REQUIRE_EQUAL(header->get_status_bits().to_ulong(), 0x80000002);
264 :
265 1 : auto comp_ref = header->get_component_for_source_id({ SourceID::Subsystem::kDetectorReadout, 78 });
266 1 : BOOST_REQUIRE_EQUAL(comp_ref.window_begin, 9);
267 1 : BOOST_REQUIRE_EQUAL(comp_ref.window_end, 10);
268 1 : comp_ref = header->get_component_for_source_id({ SourceID::Subsystem::kDetectorReadout, 56 });
269 1 : BOOST_REQUIRE_EQUAL(comp_ref.window_begin, 7);
270 1 : BOOST_REQUIRE_EQUAL(comp_ref.window_end, 8);
271 1 : comp_ref = header->get_component_for_source_id({ SourceID::Subsystem::kDetectorReadout, 12 });
272 1 : BOOST_REQUIRE_EQUAL(comp_ref.window_begin, 3);
273 1 : BOOST_REQUIRE_EQUAL(comp_ref.window_end, 4);
274 1 : comp_ref = header->get_component_for_source_id({ SourceID::Subsystem::kDetectorReadout, 90 });
275 1 : BOOST_REQUIRE_EQUAL(comp_ref.window_begin, 11);
276 1 : BOOST_REQUIRE_EQUAL(comp_ref.window_end, 12);
277 1 : BOOST_REQUIRE_EXCEPTION(header->get_component_for_source_id({ SourceID::Subsystem::kDetectorReadout, 43 }),
278 : std::invalid_argument,
279 : [&](std::invalid_argument) { return true; });
280 :
281 1 : auto header_ptr = static_cast<const TriggerRecordHeaderData*>(header->get_storage_location());
282 1 : BOOST_REQUIRE_EQUAL(header_ptr->run_number, header_data.run_number);
283 1 : header->set_run_number(10);
284 1 : BOOST_REQUIRE(header_ptr->run_number != header_data.run_number);
285 1 : BOOST_REQUIRE_EQUAL(header_ptr->run_number, 10);
286 1 : header->set_status_bits(std::bitset<32>(0x11111111));
287 1 : BOOST_REQUIRE_EQUAL(header_ptr->status_bits, 0x11111111);
288 1 : }
289 :
290 2 : BOOST_AUTO_TEST_CASE(StreamOperator)
291 : {
292 1 : std::vector<ComponentRequest> components;
293 1 : components.emplace_back();
294 1 : components.back().component = { SourceID::Subsystem::kDetectorReadout, 12 };
295 1 : components.back().window_begin = 3;
296 1 : components.back().window_end = 4;
297 1 : components.emplace_back();
298 1 : components.back().component = { SourceID::Subsystem::kDetectorReadout, 56 };
299 1 : components.back().window_begin = 7;
300 1 : components.back().window_end = 8;
301 :
302 1 : auto header = std::make_unique<TriggerRecordHeader>(components);
303 1 : header->set_run_number(9);
304 1 : header->set_trigger_number(10);
305 1 : header->set_trigger_timestamp(11);
306 1 : header->set_trigger_type(12);
307 1 : header->set_sequence_number(13);
308 1 : header->set_max_sequence_number(14);
309 1 : header->set_status_bit(TriggerRecordStatusBits::kMismatch, true);
310 1 : header->set_status_bit(TriggerRecordStatusBits::kUnassigned3, true);
311 :
312 1 : auto header_data = header->get_header();
313 1 : std::ostringstream oss;
314 1 : oss << header_data;
315 1 : std::istringstream iss(oss.str());
316 1 : TriggerRecordHeaderData trhd;
317 1 : iss >> trhd;
318 1 : BOOST_REQUIRE_EQUAL(trhd.run_number, header_data.run_number);
319 1 : BOOST_REQUIRE_EQUAL(trhd.trigger_number, header_data.trigger_number);
320 1 : BOOST_REQUIRE_EQUAL(trhd.trigger_timestamp, header_data.trigger_timestamp);
321 1 : BOOST_REQUIRE_EQUAL(trhd.trigger_type, header_data.trigger_type);
322 1 : BOOST_REQUIRE_EQUAL(trhd.sequence_number, header_data.sequence_number);
323 1 : BOOST_REQUIRE_EQUAL(trhd.max_sequence_number, header_data.max_sequence_number);
324 1 : BOOST_REQUIRE_EQUAL(trhd.num_requested_components, header_data.num_requested_components);
325 1 : }
326 :
327 : BOOST_AUTO_TEST_SUITE_END()
|