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()
|