Line data Source code
1 : #include "artdaq-core/Data/Fragment.hh"
2 : #include "artdaq-core/Data/detail/RawFragmentHeader.hh"
3 :
4 : #define BOOST_TEST_MODULE(Fragment_t)
5 : #include <cetlib/quiet_unit_test.hpp>
6 :
7 : /**
8 : * \brief Test Metadata with three fields in two long words
9 : */
10 : struct MetadataTypeOne
11 : {
12 : uint64_t field1{0}; ///< 1. A 64-bit field
13 : uint32_t field2{0}; ///< 2. A 32-bit field
14 : uint32_t field3{0}; ///< 3. A 32-bit field
15 : };
16 :
17 : /**
18 : * \brief Test Metadata with five fields, mixing field sizes
19 : */
20 : struct MetadataTypeTwo
21 : {
22 : uint64_t field1{0}; ///< 1. A 64-bit field
23 : uint32_t field2{0}; ///< 2. A 32-bit field
24 : uint32_t field3{0}; ///< 3. A 32-bit field
25 : uint64_t field4{0}; ///< 4. A 64-bit field
26 : uint16_t field5{0}; ///< 5. A 16-bit field
27 : };
28 :
29 : /**
30 : * \brief Test Metadata that is very large
31 : */
32 : struct MetadataTypeHuge
33 : {
34 : uint64_t fields[300]; ///< 300 long words
35 : };
36 :
37 : BOOST_AUTO_TEST_SUITE(Fragment_test)
38 :
39 2 : BOOST_AUTO_TEST_CASE(Construct)
40 : {
41 : // 01-Mar-2013, KAB - I'm constructing these tests based on the
42 : // constructors that I already see in the class, but I have to
43 : // wonder if these truly correspond to the behavior that we want.
44 1 : artdaq::Fragment f1;
45 1 : BOOST_REQUIRE_EQUAL(f1.dataSize(), (size_t)0);
46 1 : BOOST_REQUIRE_EQUAL(f1.size(), (size_t)artdaq::detail::RawFragmentHeader::num_words());
47 1 : BOOST_REQUIRE_EQUAL(f1.version(), (artdaq::Fragment::version_t)artdaq::detail::RawFragmentHeader::CurrentVersion);
48 1 : BOOST_REQUIRE_EQUAL(f1.type(), (artdaq::Fragment::type_t)artdaq::Fragment::InvalidFragmentType);
49 1 : BOOST_REQUIRE_EQUAL(f1.sequenceID(), (artdaq::Fragment::sequence_id_t)artdaq::Fragment::InvalidSequenceID);
50 1 : BOOST_REQUIRE_EQUAL(f1.fragmentID(), (artdaq::Fragment::fragment_id_t)artdaq::Fragment::InvalidFragmentID);
51 1 : BOOST_REQUIRE_EQUAL(f1.hasMetadata(), false);
52 :
53 1 : artdaq::Fragment f2(7);
54 1 : BOOST_REQUIRE_EQUAL(f2.dataSize(), (size_t)7);
55 1 : BOOST_REQUIRE_EQUAL(f2.size(), (size_t)artdaq::detail::RawFragmentHeader::num_words() + 7);
56 1 : BOOST_REQUIRE_EQUAL(f2.version(), (artdaq::Fragment::version_t)artdaq::detail::RawFragmentHeader::CurrentVersion);
57 1 : BOOST_REQUIRE(f2.type() == artdaq::Fragment::InvalidFragmentType);
58 1 : BOOST_REQUIRE(f2.sequenceID() == artdaq::Fragment::InvalidSequenceID);
59 1 : BOOST_REQUIRE(f2.fragmentID() == artdaq::Fragment::InvalidFragmentID);
60 1 : BOOST_REQUIRE_EQUAL(f2.hasMetadata(), false);
61 :
62 1 : artdaq::Fragment f3(101, 202, artdaq ::Fragment::DataFragmentType);
63 1 : BOOST_REQUIRE_EQUAL(f3.dataSize(), (size_t)0);
64 1 : BOOST_REQUIRE_EQUAL(f3.size(), (size_t)artdaq::detail::RawFragmentHeader::num_words());
65 1 : BOOST_REQUIRE_EQUAL(f3.version(), (artdaq::Fragment::version_t)artdaq::detail::RawFragmentHeader::CurrentVersion);
66 1 : BOOST_REQUIRE(f3.type() == artdaq::Fragment::DataFragmentType);
67 1 : BOOST_REQUIRE_EQUAL(f3.sequenceID(), (artdaq::Fragment::sequence_id_t)101);
68 1 : BOOST_REQUIRE_EQUAL(f3.fragmentID(), (artdaq::Fragment::fragment_id_t)202);
69 1 : BOOST_REQUIRE_EQUAL(f3.hasMetadata(), false);
70 :
71 2 : std::vector<artdaq::RawDataType> d{1, 2, 3};
72 1 : auto f4 = artdaq::Fragment::dataFrag(101, 202, artdaq::Fragment::DataFragmentType, &d[0], 3);
73 1 : BOOST_REQUIRE_EQUAL(f4->dataSize(), (size_t)3);
74 1 : BOOST_REQUIRE_EQUAL(f4->size(), (size_t)artdaq::detail::RawFragmentHeader::num_words() + 3);
75 1 : BOOST_REQUIRE_EQUAL(f4->version(), (artdaq::Fragment::version_t)artdaq::detail::RawFragmentHeader::CurrentVersion);
76 1 : BOOST_REQUIRE(f4->type() == artdaq::Fragment::DataFragmentType);
77 1 : BOOST_REQUIRE_EQUAL(f4->sequenceID(), (artdaq::Fragment::sequence_id_t)101);
78 1 : BOOST_REQUIRE_EQUAL(f4->fragmentID(), (artdaq::Fragment::fragment_id_t)202);
79 1 : BOOST_REQUIRE_EQUAL(f4->hasMetadata(), false);
80 :
81 : // Verify that any type may be specified in the constructor
82 : // Some system types
83 1 : artdaq::Fragment frag1(101, 202, 0);
84 1 : artdaq::Fragment frag2(101, 202, 225);
85 1 : artdaq::Fragment frag3(101, 202, 255);
86 1 : artdaq::Fragment frag4(101, 202, artdaq::Fragment::InvalidFragmentType);
87 1 : artdaq::Fragment frag5(101, 202, artdaq::detail::RawFragmentHeader::FIRST_SYSTEM_TYPE);
88 1 : artdaq::Fragment frag6(101, 202, artdaq::detail::RawFragmentHeader::LAST_SYSTEM_TYPE);
89 :
90 : // Some user types
91 : artdaq::Fragment
92 1 : fragA(101, 202, artdaq::detail::RawFragmentHeader::FIRST_USER_TYPE);
93 : artdaq::Fragment
94 1 : fragB(101, 202, artdaq::detail::RawFragmentHeader::LAST_USER_TYPE);
95 1 : artdaq::Fragment fragC(101, 202, 1);
96 1 : artdaq::Fragment fragD(101, 202, 2);
97 1 : artdaq::Fragment fragE(101, 202, 3);
98 1 : artdaq::Fragment fragF(101, 202, 100);
99 1 : artdaq::Fragment fragG(101, 202, 200);
100 1 : artdaq::Fragment fragH(101, 202, 224);
101 :
102 3 : TLOG(TLVL_INFO) << "Example Fragment: " << f1;
103 1 : BOOST_REQUIRE_EQUAL(f1.typeString(), "0");
104 1 : }
105 :
106 2 : BOOST_AUTO_TEST_CASE(FragmentType)
107 : {
108 1 : artdaq::Fragment frag(15);
109 :
110 : // test "user" fragment types
111 1 : BOOST_REQUIRE_THROW(frag.setUserType(0), cet::exception);
112 1 : BOOST_REQUIRE_THROW(frag.setUserType(225), cet::exception);
113 1 : BOOST_REQUIRE_THROW(frag.setUserType(255), cet::exception);
114 1 : BOOST_REQUIRE_THROW(frag.setUserType(artdaq::Fragment::InvalidFragmentType), cet::exception);
115 1 : BOOST_REQUIRE_THROW(frag.setUserType(artdaq::detail::RawFragmentHeader::FIRST_SYSTEM_TYPE), cet::exception);
116 1 : BOOST_REQUIRE_THROW(frag.setUserType(artdaq::detail::RawFragmentHeader::LAST_SYSTEM_TYPE), cet::exception);
117 :
118 1 : frag.setUserType(artdaq::detail::RawFragmentHeader::FIRST_USER_TYPE);
119 1 : frag.setUserType(artdaq::detail::RawFragmentHeader::LAST_USER_TYPE);
120 1 : frag.setUserType(1);
121 1 : frag.setUserType(2);
122 1 : frag.setUserType(3);
123 1 : frag.setUserType(100);
124 1 : frag.setUserType(200);
125 1 : frag.setUserType(224);
126 :
127 : // test "system" fragment types
128 1 : BOOST_REQUIRE_THROW(frag.setSystemType(0), cet::exception);
129 1 : BOOST_REQUIRE_THROW(frag.setSystemType(1), cet::exception);
130 1 : BOOST_REQUIRE_THROW(frag.setSystemType(224), cet::exception);
131 1 : BOOST_REQUIRE_THROW(frag.setSystemType(artdaq::Fragment::InvalidFragmentType), cet::exception);
132 1 : BOOST_REQUIRE_THROW(frag.setSystemType(artdaq::detail::RawFragmentHeader::FIRST_USER_TYPE), cet::exception);
133 1 : BOOST_REQUIRE_THROW(frag.setSystemType(artdaq::detail::RawFragmentHeader::LAST_USER_TYPE), cet::exception);
134 :
135 1 : frag.setSystemType(artdaq::detail::RawFragmentHeader::FIRST_SYSTEM_TYPE);
136 1 : frag.setSystemType(artdaq::detail::RawFragmentHeader::LAST_SYSTEM_TYPE);
137 1 : frag.setSystemType(225);
138 1 : frag.setSystemType(230);
139 1 : frag.setSystemType(240);
140 1 : frag.setSystemType(250);
141 1 : frag.setSystemType(255);
142 :
143 1 : auto map = artdaq::detail::RawFragmentHeader::MakeVerboseSystemTypeMap();
144 1 : BOOST_REQUIRE(map.size() > 0);
145 1 : map = artdaq::detail::RawFragmentHeader::MakeSystemTypeMap();
146 1 : BOOST_REQUIRE(map.size() > 0);
147 1 : }
148 :
149 2 : BOOST_AUTO_TEST_CASE(SequenceID)
150 : {
151 1 : artdaq::Fragment f1;
152 1 : f1.setSequenceID(0);
153 1 : BOOST_REQUIRE_EQUAL(f1.sequenceID(), (uint64_t)0);
154 1 : f1.setSequenceID(1);
155 1 : BOOST_REQUIRE_EQUAL(f1.sequenceID(), (uint64_t)1);
156 1 : f1.setSequenceID(0xffff);
157 1 : BOOST_REQUIRE_EQUAL(f1.sequenceID(), (uint64_t)0xffff);
158 1 : f1.setSequenceID(0x0000ffffffffffff);
159 1 : BOOST_REQUIRE_EQUAL(f1.sequenceID(), (uint64_t)0x0000ffffffffffff);
160 :
161 1 : artdaq::Fragment f2(0x12345, 0xab, artdaq::Fragment::DataFragmentType);
162 1 : BOOST_REQUIRE_EQUAL(f2.sequenceID(), (uint64_t)0x12345);
163 :
164 1 : artdaq::Fragment f3(0x0000567812345678, 0xab, artdaq::Fragment::DataFragmentType);
165 1 : BOOST_REQUIRE_EQUAL(f3.sequenceID(), (uint64_t)0x0000567812345678);
166 1 : }
167 :
168 2 : BOOST_AUTO_TEST_CASE(FragmentID)
169 : {
170 1 : artdaq::Fragment f1;
171 1 : f1.setFragmentID(0);
172 1 : BOOST_REQUIRE_EQUAL(f1.fragmentID(), (uint16_t)0);
173 1 : f1.setFragmentID(1);
174 1 : BOOST_REQUIRE_EQUAL(f1.fragmentID(), (uint16_t)1);
175 1 : f1.setFragmentID(0xffff);
176 1 : BOOST_REQUIRE_EQUAL(f1.fragmentID(), (uint16_t)0xffff);
177 :
178 1 : artdaq::Fragment f2(0x12345, 0xab, artdaq::Fragment::DataFragmentType);
179 1 : BOOST_REQUIRE_EQUAL(f2.fragmentID(), (uint16_t)0xab);
180 :
181 1 : artdaq::Fragment f3(0x0000567812345678, 0xffff, artdaq::Fragment::DataFragmentType);
182 1 : BOOST_REQUIRE_EQUAL(f3.fragmentID(), (uint16_t)0xffff);
183 1 : }
184 :
185 2 : BOOST_AUTO_TEST_CASE(Resize)
186 : {
187 : // basic fragment
188 1 : artdaq::Fragment f1;
189 1 : f1.resize(1234);
190 1 : BOOST_REQUIRE_EQUAL(f1.dataSize(), (size_t)1234);
191 1 : BOOST_REQUIRE_EQUAL(f1.size(), (size_t)1234 +
192 : artdaq::detail::RawFragmentHeader::num_words());
193 :
194 : // fragment with metadata
195 1 : MetadataTypeOne mdOneA{};
196 1 : artdaq::Fragment f2(1, 123, 3, 5, mdOneA);
197 1 : f2.resize(129);
198 1 : BOOST_REQUIRE_EQUAL(f2.dataSize(), (size_t)129);
199 1 : BOOST_REQUIRE_EQUAL(f2.size(), (size_t)129 + 2 +
200 : artdaq::detail::RawFragmentHeader::num_words());
201 1 : }
202 :
203 2 : BOOST_AUTO_TEST_CASE(Empty)
204 : {
205 1 : artdaq::Fragment f1;
206 1 : BOOST_REQUIRE_EQUAL(f1.empty(), true);
207 1 : f1.resize(1234);
208 1 : BOOST_REQUIRE_EQUAL(f1.empty(), false);
209 :
210 1 : MetadataTypeOne mdOneA{};
211 1 : artdaq::Fragment f2(1, 123, 3, 5, mdOneA);
212 1 : BOOST_REQUIRE_EQUAL(f2.empty(), false);
213 1 : f2.resize(129);
214 1 : BOOST_REQUIRE_EQUAL(f2.empty(), false);
215 1 : f2.resize(0);
216 1 : BOOST_REQUIRE_EQUAL(f2.empty(), true);
217 1 : BOOST_REQUIRE_EQUAL(f2.dataSize(), (size_t)0);
218 1 : BOOST_REQUIRE_EQUAL(f2.size(), (size_t)2 +
219 : artdaq::detail::RawFragmentHeader::num_words());
220 :
221 1 : artdaq::Fragment f3;
222 1 : BOOST_REQUIRE_EQUAL(f3.empty(), true);
223 1 : f3.setMetadata(mdOneA);
224 1 : BOOST_REQUIRE_EQUAL(f3.empty(), true);
225 :
226 1 : artdaq::Fragment f4(14);
227 1 : BOOST_REQUIRE_EQUAL(f4.empty(), false);
228 1 : f4.setMetadata(mdOneA);
229 1 : BOOST_REQUIRE_EQUAL(f4.empty(), false);
230 1 : }
231 :
232 2 : BOOST_AUTO_TEST_CASE(Clear)
233 : {
234 1 : artdaq::Fragment f1;
235 1 : BOOST_REQUIRE_EQUAL(f1.empty(), true);
236 1 : f1.resize(1234);
237 1 : BOOST_REQUIRE_EQUAL(f1.empty(), false);
238 1 : f1.clear();
239 1 : BOOST_REQUIRE_EQUAL(f1.empty(), true);
240 :
241 1 : MetadataTypeOne mdOneA;
242 1 : artdaq::Fragment f2(1, 123, 3, 5, mdOneA);
243 1 : BOOST_REQUIRE_EQUAL(f2.empty(), false);
244 1 : f2.resize(129);
245 1 : BOOST_REQUIRE_EQUAL(f2.empty(), false);
246 1 : f2.clear();
247 1 : BOOST_REQUIRE_EQUAL(f2.empty(), true);
248 1 : BOOST_REQUIRE_EQUAL(f2.dataSize(), (size_t)0);
249 1 : BOOST_REQUIRE_EQUAL(f2.size(), (size_t)2 +
250 : artdaq::detail::RawFragmentHeader::num_words());
251 :
252 1 : artdaq::Fragment f3;
253 1 : BOOST_REQUIRE_EQUAL(f3.empty(), true);
254 1 : BOOST_REQUIRE_EQUAL(f3.hasMetadata(), false);
255 1 : f3.setMetadata(mdOneA);
256 1 : BOOST_REQUIRE_EQUAL(f3.empty(), true);
257 1 : BOOST_REQUIRE_EQUAL(f3.hasMetadata(), true);
258 1 : f3.clear();
259 1 : BOOST_REQUIRE_EQUAL(f3.empty(), true);
260 1 : BOOST_REQUIRE_EQUAL(f3.hasMetadata(), true);
261 :
262 1 : artdaq::Fragment f4(14);
263 1 : BOOST_REQUIRE_EQUAL(f4.empty(), false);
264 1 : BOOST_REQUIRE_EQUAL(f4.hasMetadata(), false);
265 1 : f4.setMetadata(mdOneA);
266 1 : BOOST_REQUIRE_EQUAL(f4.empty(), false);
267 1 : BOOST_REQUIRE_EQUAL(f4.hasMetadata(), true);
268 1 : f4.clear();
269 1 : BOOST_REQUIRE_EQUAL(f4.empty(), true);
270 1 : BOOST_REQUIRE_EQUAL(f4.hasMetadata(), true);
271 1 : }
272 :
273 2 : BOOST_AUTO_TEST_CASE(Addresses)
274 : {
275 : // no metadata
276 1 : artdaq::Fragment f1(200);
277 1 : BOOST_REQUIRE_EQUAL(f1.dataSize(), (size_t)200);
278 1 : BOOST_REQUIRE_EQUAL(f1.size(), (size_t)200 +
279 : artdaq::detail::RawFragmentHeader::num_words());
280 1 : artdaq::RawDataType* haddr = f1.headerAddress();
281 1 : artdaq::RawDataType* daddr = f1.dataAddress();
282 1 : BOOST_REQUIRE_EQUAL(daddr,
283 : (haddr + artdaq::detail::RawFragmentHeader::num_words())); // NOLINT(cppcoreguidelines-pro-bounds-pointer-arithmetic)
284 :
285 1 : BOOST_REQUIRE_THROW(f1.metadataAddress(), cet::exception);
286 :
287 1 : BOOST_REQUIRE_EQUAL(haddr, &(*(f1.headerBegin())));
288 1 : BOOST_REQUIRE_EQUAL(daddr, &(*(f1.dataBegin())));
289 1 : BOOST_REQUIRE_EQUAL(daddr + 200, &(*(f1.dataEnd()))); // NOLINT(cppcoreguidelines-pro-bounds-pointer-arithmetic)
290 :
291 : // Const versions
292 1 : const artdaq::Fragment cf1(f1);
293 1 : BOOST_REQUIRE_EQUAL(cf1.dataSize(), (size_t)200);
294 1 : BOOST_REQUIRE_EQUAL(cf1.size(), (size_t)200 +
295 : artdaq::detail::RawFragmentHeader::num_words());
296 1 : const artdaq::RawDataType* chaddr = cf1.headerBegin();
297 1 : const artdaq::RawDataType* cdaddr = cf1.dataBegin();
298 1 : BOOST_REQUIRE_EQUAL(cdaddr,
299 : (chaddr + artdaq::detail::RawFragmentHeader::num_words())); // NOLINT(cppcoreguidelines-pro-bounds-pointer-arithmetic)
300 :
301 1 : BOOST_REQUIRE_EQUAL(cdaddr + 200, &(*(cf1.dataEnd()))); // NOLINT(cppcoreguidelines-pro-bounds-pointer-arithmetic)
302 :
303 : // metadata with integer number of longwords
304 1 : MetadataTypeOne mdOneA{};
305 1 : artdaq::Fragment f2(135, 101, 0, 3, mdOneA);
306 1 : BOOST_REQUIRE_EQUAL(f2.dataSize(), (size_t)135);
307 1 : BOOST_REQUIRE_EQUAL(f2.size(), (size_t)135 + 2 +
308 : artdaq::detail::RawFragmentHeader::num_words());
309 1 : haddr = f2.headerAddress();
310 1 : daddr = f2.dataAddress();
311 1 : artdaq::RawDataType* maddr = f2.metadataAddress();
312 1 : BOOST_REQUIRE_EQUAL(maddr, haddr + // NOLINT(cppcoreguidelines-pro-bounds-pointer-arithmetic)
313 : artdaq::detail::RawFragmentHeader::num_words());
314 1 : BOOST_REQUIRE_EQUAL(daddr, maddr + 2); // NOLINT(cppcoreguidelines-pro-bounds-pointer-arithmetic)
315 1 : BOOST_REQUIRE_EQUAL(haddr, &(*(f2.headerBegin())));
316 1 : BOOST_REQUIRE_EQUAL(daddr, &(*(f2.dataBegin())));
317 1 : BOOST_REQUIRE_EQUAL(daddr + 135, &(*(f2.dataEnd()))); // NOLINT(cppcoreguidelines-pro-bounds-pointer-arithmetic)
318 :
319 : // metadata with fractional number of longwords
320 1 : MetadataTypeTwo mdTwoA;
321 1 : artdaq::Fragment f3(77, 101, 0, 3, mdTwoA);
322 1 : BOOST_REQUIRE_EQUAL(f3.dataSize(), (size_t)77);
323 1 : BOOST_REQUIRE_EQUAL(f3.size(), (size_t)77 + 4 + // NOLINT(cppcoreguidelines-pro-bounds-pointer-arithmetic)
324 : artdaq::detail::RawFragmentHeader::num_words());
325 1 : haddr = f3.headerAddress();
326 1 : daddr = f3.dataAddress();
327 1 : maddr = f3.metadataAddress();
328 1 : BOOST_REQUIRE_EQUAL(maddr, haddr + // NOLINT(cppcoreguidelines-pro-bounds-pointer-arithmetic)
329 : artdaq::detail::RawFragmentHeader::num_words());
330 1 : BOOST_REQUIRE_EQUAL(daddr, maddr + 4); // NOLINT(cppcoreguidelines-pro-bounds-pointer-arithmetic)
331 1 : BOOST_REQUIRE_EQUAL(haddr, &(*(f3.headerBegin())));
332 1 : BOOST_REQUIRE_EQUAL(daddr, &(*(f3.dataBegin())));
333 1 : BOOST_REQUIRE_EQUAL(daddr + 77, &(*(f3.dataEnd()))); // NOLINT(cppcoreguidelines-pro-bounds-pointer-arithmetic)
334 1 : }
335 :
336 2 : BOOST_AUTO_TEST_CASE(Metadata)
337 : {
338 1 : artdaq::Fragment f1(42);
339 1 : BOOST_REQUIRE_EQUAL(f1.hasMetadata(), false);
340 :
341 1 : BOOST_REQUIRE_THROW(f1.metadata<MetadataTypeOne>(), cet::exception);
342 :
343 1 : MetadataTypeOne mdOneA;
344 1 : mdOneA.field1 = 5;
345 1 : mdOneA.field2 = 10;
346 1 : mdOneA.field3 = 15;
347 :
348 1 : BOOST_REQUIRE_THROW(f1.updateMetadata(mdOneA), cet::exception);
349 :
350 1 : f1.setMetadata(mdOneA);
351 1 : auto* mdOnePtr = f1.metadata<MetadataTypeOne>();
352 1 : BOOST_REQUIRE_EQUAL(mdOnePtr->field1, (uint64_t)5);
353 1 : BOOST_REQUIRE_EQUAL(mdOnePtr->field2, (uint32_t)10);
354 1 : BOOST_REQUIRE_EQUAL(mdOnePtr->field3, (uint32_t)15);
355 :
356 1 : MetadataTypeOne mdOneB{};
357 1 : BOOST_REQUIRE_THROW(f1.setMetadata(mdOneB), cet::exception);
358 :
359 1 : f1.updateMetadata(*mdOnePtr);
360 :
361 1 : MetadataTypeTwo mdTwoA;
362 1 : mdTwoA.field1 = 10;
363 1 : mdTwoA.field2 = 20;
364 1 : mdTwoA.field3 = 30;
365 1 : mdTwoA.field4 = 40;
366 1 : mdTwoA.field5 = 50;
367 :
368 1 : BOOST_REQUIRE_THROW(f1.updateMetadata(mdTwoA), cet::exception);
369 :
370 1 : artdaq::Fragment f2(10, 1, 2, 3, mdTwoA);
371 1 : auto* mdTwoPtr = f2.metadata<MetadataTypeTwo>();
372 1 : BOOST_REQUIRE_EQUAL(mdTwoPtr->field1, (uint64_t)10);
373 1 : BOOST_REQUIRE_EQUAL(mdTwoPtr->field2, (uint32_t)20);
374 1 : BOOST_REQUIRE_EQUAL(mdTwoPtr->field3, (uint32_t)30);
375 1 : BOOST_REQUIRE_EQUAL(mdTwoPtr->field4, (uint32_t)40);
376 1 : BOOST_REQUIRE_EQUAL(mdTwoPtr->field5, (uint32_t)50);
377 :
378 1 : artdaq::Fragment f3(0xabcdef, 0xc3a5, 123);
379 1 : BOOST_REQUIRE_EQUAL(f3.sequenceID(), (uint32_t)0xabcdef);
380 1 : BOOST_REQUIRE_EQUAL(f3.fragmentID(), (uint16_t)0xc3a5);
381 1 : BOOST_REQUIRE_EQUAL(f3.type(), (uint16_t)123);
382 1 : f3.resize(5);
383 1 : BOOST_REQUIRE_EQUAL(f3.sequenceID(), (uint32_t)0xabcdef);
384 1 : BOOST_REQUIRE_EQUAL(f3.fragmentID(), (uint16_t)0xc3a5);
385 1 : BOOST_REQUIRE_EQUAL(f3.type(), (uint8_t)123);
386 1 : artdaq::RawDataType* dataPtr = f3.dataAddress();
387 1 : dataPtr[0] = 0x12345678; // NOLINT(cppcoreguidelines-pro-bounds-pointer-arithmetic)
388 1 : dataPtr[1] = 0xabcd; // NOLINT(cppcoreguidelines-pro-bounds-pointer-arithmetic)
389 1 : dataPtr[2] = 0x456789ab; // NOLINT(cppcoreguidelines-pro-bounds-pointer-arithmetic)
390 1 : dataPtr[3] = 0x3c3c3c3c; // NOLINT(cppcoreguidelines-pro-bounds-pointer-arithmetic)
391 1 : dataPtr[4] = 0x5a5a5a5a; // NOLINT(cppcoreguidelines-pro-bounds-pointer-arithmetic)
392 1 : BOOST_REQUIRE_EQUAL(dataPtr[0], (uint64_t)0x12345678); // NOLINT(cppcoreguidelines-pro-bounds-pointer-arithmetic)
393 1 : BOOST_REQUIRE_EQUAL(dataPtr[1], (uint64_t)0xabcd); // NOLINT(cppcoreguidelines-pro-bounds-pointer-arithmetic)
394 1 : BOOST_REQUIRE_EQUAL(dataPtr[2], (uint64_t)0x456789ab); // NOLINT(cppcoreguidelines-pro-bounds-pointer-arithmetic)
395 1 : BOOST_REQUIRE_EQUAL(dataPtr[3], (uint64_t)0x3c3c3c3c); // NOLINT(cppcoreguidelines-pro-bounds-pointer-arithmetic)
396 1 : BOOST_REQUIRE_EQUAL(dataPtr[4], (uint64_t)0x5a5a5a5a); // NOLINT(cppcoreguidelines-pro-bounds-pointer-arithmetic)
397 1 : BOOST_REQUIRE_EQUAL(f3.sequenceID(), (uint32_t)0xabcdef);
398 1 : BOOST_REQUIRE_EQUAL(f3.fragmentID(), (uint16_t)0xc3a5);
399 1 : BOOST_REQUIRE_EQUAL(f3.type(), (uint8_t)123);
400 1 : MetadataTypeOne mdOneC;
401 1 : mdOneC.field1 = 505;
402 1 : mdOneC.field2 = 510;
403 1 : mdOneC.field3 = 515;
404 1 : f3.setMetadata(mdOneC);
405 1 : mdOnePtr = f3.metadata<MetadataTypeOne>();
406 1 : BOOST_REQUIRE_EQUAL(mdOnePtr->field1, (uint64_t)505);
407 1 : BOOST_REQUIRE_EQUAL(mdOnePtr->field2, (uint32_t)510);
408 1 : BOOST_REQUIRE_EQUAL(mdOnePtr->field3, (uint32_t)515);
409 1 : BOOST_REQUIRE_EQUAL(f3.sequenceID(), (uint32_t)0xabcdef);
410 1 : BOOST_REQUIRE_EQUAL(f3.fragmentID(), (uint16_t)0xc3a5);
411 1 : BOOST_REQUIRE_EQUAL(f3.type(), (uint8_t)123);
412 1 : dataPtr = f3.dataAddress();
413 1 : dataPtr[0] = 0x12345678; // NOLINT(cppcoreguidelines-pro-bounds-pointer-arithmetic)
414 1 : dataPtr[1] = 0xabcd; // NOLINT(cppcoreguidelines-pro-bounds-pointer-arithmetic)
415 1 : dataPtr[2] = 0x456789ab; // NOLINT(cppcoreguidelines-pro-bounds-pointer-arithmetic)
416 1 : dataPtr[3] = 0x3c3c3c3c; // NOLINT(cppcoreguidelines-pro-bounds-pointer-arithmetic)
417 1 : dataPtr[4] = 0x5a5a5a5a; // NOLINT(cppcoreguidelines-pro-bounds-pointer-arithmetic)
418 1 : BOOST_REQUIRE_EQUAL(dataPtr[0], (uint64_t)0x12345678); // NOLINT(cppcoreguidelines-pro-bounds-pointer-arithmetic)
419 1 : BOOST_REQUIRE_EQUAL(dataPtr[1], (uint64_t)0xabcd); // NOLINT(cppcoreguidelines-pro-bounds-pointer-arithmetic)
420 1 : BOOST_REQUIRE_EQUAL(dataPtr[2], (uint64_t)0x456789ab); // NOLINT(cppcoreguidelines-pro-bounds-pointer-arithmetic)
421 1 : BOOST_REQUIRE_EQUAL(dataPtr[3], (uint64_t)0x3c3c3c3c); // NOLINT(cppcoreguidelines-pro-bounds-pointer-arithmetic)
422 1 : BOOST_REQUIRE_EQUAL(dataPtr[4], (uint64_t)0x5a5a5a5a); // NOLINT(cppcoreguidelines-pro-bounds-pointer-arithmetic)
423 :
424 : MetadataTypeHuge mdHuge;
425 1 : artdaq::Fragment f4(19);
426 1 : BOOST_REQUIRE_EQUAL(f4.hasMetadata(), false);
427 :
428 1 : BOOST_REQUIRE_THROW(f4.setMetadata(mdHuge), cet::exception);
429 :
430 2 : BOOST_REQUIRE_THROW(artdaq::Fragment f5(127, 1, 2, 3, mdHuge), cet::exception);
431 1 : }
432 :
433 : // JCF, 4/15/14 -- perform a set of tests concerning the new
434 : // byte-by-byte interface functions added to artdaq::Fragment
435 :
436 2 : BOOST_AUTO_TEST_CASE(Bytes)
437 : {
438 1 : std::size_t payload_size = 5;
439 :
440 : // seqID, fragID, type are all random
441 1 : artdaq::Fragment::sequence_id_t seqID = 1;
442 1 : artdaq::Fragment::fragment_id_t fragID = 1;
443 1 : artdaq::Fragment::type_t type = 3;
444 :
445 : // No explicit constructor necessary for Metadata -- all we care
446 : // about is its size in the artdaq::Fragment, not its values
447 :
448 : struct Metadata
449 : {
450 : uint8_t byteOne;
451 : uint8_t byteTwo;
452 : uint8_t byteThree;
453 : };
454 :
455 : Metadata theMetadata;
456 :
457 1 : BOOST_REQUIRE(sizeof(artdaq::Fragment::byte_t) == 1);
458 :
459 : // Assumption in some of the arithmetic below is that RawDataType is 8 bytes
460 1 : BOOST_REQUIRE(sizeof(artdaq::RawDataType) == 8);
461 :
462 : // Check that the factory function and the explicit constructor
463 : // methods of creating a fragment yield identical results IF the
464 : // number of bytes passed to FragmentBytes() is a multiple of the
465 : // size of the RawDataType
466 :
467 1 : std::unique_ptr<artdaq::Fragment> f1(new artdaq::Fragment(payload_size));
468 : std::unique_ptr<artdaq::Fragment> f1_factory(artdaq::Fragment::FragmentBytes(
469 1 : payload_size * sizeof(artdaq::RawDataType)));
470 :
471 1 : BOOST_REQUIRE(f1->size() == f1_factory->size());
472 1 : BOOST_REQUIRE(f1->sizeBytes() == f1_factory->sizeBytes());
473 :
474 1 : std::unique_ptr<artdaq::Fragment> f2(new artdaq::Fragment(payload_size, seqID, fragID, type, theMetadata));
475 : std::unique_ptr<artdaq::Fragment> f2_factory(artdaq::Fragment::FragmentBytes(
476 : payload_size * sizeof(artdaq::RawDataType),
477 : seqID, fragID,
478 1 : type, theMetadata));
479 :
480 1 : BOOST_REQUIRE(f2->size() == f2_factory->size());
481 1 : BOOST_REQUIRE(f2->sizeBytes() == f2_factory->sizeBytes());
482 :
483 : // Now let's make sure that data gets aligned as expected (i.e.,
484 : // along boundaries separated by sizeof(RawDataType) bytes)
485 :
486 1 : std::size_t offset = 3;
487 : std::unique_ptr<artdaq::Fragment> f3_factory(artdaq::Fragment::FragmentBytes(
488 1 : payload_size * sizeof(artdaq::RawDataType) - offset,
489 : seqID, fragID,
490 1 : type, theMetadata));
491 :
492 1 : BOOST_REQUIRE(f3_factory->size() == f2->size());
493 1 : BOOST_REQUIRE(f3_factory->sizeBytes() == f2->sizeBytes());
494 :
495 : // Make certain dataBegin(), dataBeginBytes() and the
496 : // (now-deprecated, but still in legacy code) dataAddress() point to
497 : // the same region in memory, i.e., the start of the payload
498 :
499 : auto* hdrptr = reinterpret_cast<artdaq::Fragment::byte_t*>( // NOLINT(cppcoreguidelines-pro-type-reinterpret-cast)
500 1 : &*f3_factory->headerBegin());
501 1 : BOOST_REQUIRE_EQUAL(&*f3_factory->headerBeginBytes(), hdrptr);
502 :
503 : auto* ptr1 = reinterpret_cast<artdaq::Fragment::byte_t*>( // NOLINT(cppcoreguidelines-pro-type-reinterpret-cast)
504 1 : &*f3_factory->dataBegin());
505 :
506 1 : artdaq::Fragment::byte_t* ptr2 = f3_factory->dataBeginBytes();
507 :
508 1 : auto* ptr3 = reinterpret_cast<artdaq::Fragment::byte_t*>(f3_factory->dataAddress()); // NOLINT(cppcoreguidelines-pro-type-reinterpret-cast)
509 :
510 1 : BOOST_REQUIRE_EQUAL(ptr1, ptr2);
511 1 : BOOST_REQUIRE_EQUAL(ptr2, ptr3);
512 :
513 : auto* dataEndPtr = reinterpret_cast<artdaq::Fragment::byte_t*>( // NOLINT(cppcoreguidelines-pro-type-reinterpret-cast)
514 1 : &*f3_factory->dataEnd());
515 1 : BOOST_REQUIRE_EQUAL(&*f3_factory->dataEndBytes(), dataEndPtr);
516 :
517 : // Check const versions, too
518 1 : const artdaq::Fragment f3_copy(*f3_factory);
519 1 : auto chdrptr = reinterpret_cast<const artdaq::Fragment::byte_t*>(f3_copy.headerBegin()); // NOLINT(cppcoreguidelines-pro-type-reinterpret-cast)
520 1 : BOOST_REQUIRE_EQUAL(&*f3_copy.headerBeginBytes(), chdrptr);
521 : auto* cptr1 = reinterpret_cast<const artdaq::Fragment::byte_t*>( // NOLINT(cppcoreguidelines-pro-type-reinterpret-cast)
522 1 : &*f3_copy.dataBegin());
523 :
524 1 : const artdaq::Fragment::byte_t* cptr2 = f3_copy.dataBeginBytes();
525 :
526 1 : BOOST_REQUIRE_EQUAL(cptr1, cptr2);
527 :
528 : auto* cdataEndPtr = reinterpret_cast<const artdaq::Fragment::byte_t*>( // NOLINT(cppcoreguidelines-pro-type-reinterpret-cast)
529 1 : &*f3_copy.dataEnd());
530 1 : BOOST_REQUIRE_EQUAL(&*f3_copy.dataEndBytes(), cdataEndPtr);
531 :
532 : // Make sure metadata struct gets aligned
533 : // header == 3 RawDataTypes, metadata is 3 bytes (rounds up to 1 RawDataType)
534 : std::size_t const metadata_size =
535 1 : f3_factory->dataBeginBytes() - reinterpret_cast<artdaq::Fragment::byte_t*>(&*f3_factory->headerBegin()); // NOLINT(cppcoreguidelines-pro-type-reinterpret-cast)
536 1 : BOOST_REQUIRE(metadata_size ==
537 : (1 + artdaq::detail::RawFragmentHeader::num_words()) * sizeof(artdaq::RawDataType));
538 :
539 : // Sanity check for the payload size
540 1 : BOOST_REQUIRE(static_cast<std::size_t>(f3_factory->dataEndBytes() - f3_factory->dataBeginBytes()) == f3_factory->dataSizeBytes()); // NOLINT(cppcoreguidelines-pro-bounds-pointer-arithmetic)
541 :
542 : // Check resizing
543 1 : artdaq::Fragment f4(payload_size);
544 1 : BOOST_REQUIRE_EQUAL(f4.dataSize(), payload_size);
545 1 : BOOST_REQUIRE_EQUAL(f4.dataSizeBytes(), (payload_size * sizeof(artdaq::RawDataType)));
546 1 : f4.resize(payload_size + 1);
547 1 : BOOST_REQUIRE_EQUAL(f4.dataSize(), (payload_size + 1));
548 1 : BOOST_REQUIRE_EQUAL(f4.dataSizeBytes(), ((payload_size + 1) * sizeof(artdaq::RawDataType)));
549 1 : f4.resizeBytes(f4.dataSizeBytes() + 2);
550 1 : BOOST_REQUIRE_EQUAL(f4.dataSize(), (payload_size + 2));
551 1 : BOOST_REQUIRE_EQUAL(f4.dataSizeBytes(), ((payload_size + 2) * sizeof(artdaq::RawDataType)));
552 1 : f4.resizeBytes(f4.dataSizeBytes() + 1);
553 1 : BOOST_REQUIRE_EQUAL(f4.dataSize(), (payload_size + 3));
554 1 : BOOST_REQUIRE_EQUAL(f4.dataSizeBytes(), ((payload_size + 3) * sizeof(artdaq::RawDataType)));
555 1 : f4.resizeBytes(f4.dataSizeBytes() + 1);
556 1 : BOOST_REQUIRE_EQUAL(f4.dataSize(), (payload_size + 4));
557 1 : BOOST_REQUIRE_EQUAL(f4.dataSizeBytes(), ((payload_size + 4) * sizeof(artdaq::RawDataType)));
558 :
559 1 : size_t targetSize = (payload_size + 4) * sizeof(artdaq::RawDataType);
560 1 : ++targetSize;
561 1 : f4.resizeBytes(targetSize);
562 1 : BOOST_REQUIRE_EQUAL(f4.dataSize(), (payload_size + 5));
563 1 : BOOST_REQUIRE_EQUAL(f4.dataSizeBytes(), ((payload_size + 5) * sizeof(artdaq::RawDataType)));
564 1 : ++targetSize;
565 1 : f4.resizeBytes(targetSize);
566 1 : BOOST_REQUIRE_EQUAL(f4.dataSize(), (payload_size + 5));
567 1 : BOOST_REQUIRE_EQUAL(f4.dataSizeBytes(), ((payload_size + 5) * sizeof(artdaq::RawDataType)));
568 1 : ++targetSize;
569 1 : f4.resizeBytes(targetSize);
570 1 : BOOST_REQUIRE_EQUAL(f4.dataSize(), (payload_size + 5));
571 1 : BOOST_REQUIRE_EQUAL(f4.dataSizeBytes(), ((payload_size + 5) * sizeof(artdaq::RawDataType)));
572 1 : ++targetSize;
573 1 : f4.resizeBytes(targetSize);
574 1 : BOOST_REQUIRE_EQUAL(f4.dataSize(), (payload_size + 5));
575 1 : BOOST_REQUIRE_EQUAL(f4.dataSizeBytes(), ((payload_size + 5) * sizeof(artdaq::RawDataType)));
576 1 : ++targetSize;
577 1 : f4.resizeBytes(targetSize);
578 1 : BOOST_REQUIRE_EQUAL(f4.dataSize(), (payload_size + 5));
579 1 : BOOST_REQUIRE_EQUAL(f4.dataSizeBytes(), ((payload_size + 5) * sizeof(artdaq::RawDataType)));
580 1 : ++targetSize;
581 1 : f4.resizeBytes(targetSize);
582 1 : BOOST_REQUIRE_EQUAL(f4.dataSize(), (payload_size + 5));
583 1 : BOOST_REQUIRE_EQUAL(f4.dataSizeBytes(), ((payload_size + 5) * sizeof(artdaq::RawDataType)));
584 1 : ++targetSize;
585 1 : f4.resizeBytes(targetSize);
586 1 : BOOST_REQUIRE_EQUAL(f4.dataSize(), (payload_size + 5));
587 1 : BOOST_REQUIRE_EQUAL(f4.dataSizeBytes(), ((payload_size + 5) * sizeof(artdaq::RawDataType)));
588 1 : ++targetSize;
589 1 : f4.resizeBytes(targetSize);
590 1 : BOOST_REQUIRE_EQUAL(f4.dataSize(), (payload_size + 5));
591 1 : BOOST_REQUIRE_EQUAL(f4.dataSizeBytes(), ((payload_size + 5) * sizeof(artdaq::RawDataType)));
592 1 : ++targetSize;
593 1 : f4.resizeBytes(targetSize);
594 1 : BOOST_REQUIRE_EQUAL(f4.dataSize(), (payload_size + 6));
595 1 : BOOST_REQUIRE_EQUAL(f4.dataSizeBytes(), ((payload_size + 6) * sizeof(artdaq::RawDataType)));
596 :
597 : // Check adding metadata after construction
598 1 : artdaq::Fragment f5(payload_size);
599 1 : BOOST_REQUIRE_EQUAL(f5.size(), (payload_size + artdaq::detail::RawFragmentHeader::num_words()));
600 1 : BOOST_REQUIRE_EQUAL(f5.sizeBytes(), ((payload_size + artdaq::detail::RawFragmentHeader::num_words()) * sizeof(artdaq::RawDataType)));
601 1 : f5.setMetadata(theMetadata);
602 1 : BOOST_REQUIRE_EQUAL(f5.dataSize(), payload_size);
603 1 : BOOST_REQUIRE_EQUAL(f5.dataSizeBytes(), (payload_size * sizeof(artdaq::RawDataType)));
604 1 : BOOST_REQUIRE_EQUAL(f5.size(), (payload_size + 1 + artdaq::detail::RawFragmentHeader::num_words()));
605 1 : BOOST_REQUIRE_EQUAL(f5.sizeBytes(), ((payload_size + 1 + artdaq::detail::RawFragmentHeader::num_words()) * sizeof(artdaq::RawDataType)));
606 1 : }
607 :
608 2 : BOOST_AUTO_TEST_CASE(Upgrade_V0)
609 : {
610 1 : artdaq::Fragment f(7);
611 : artdaq::detail::RawFragmentHeaderV0 hdr0;
612 :
613 1 : hdr0.word_count = artdaq::detail::RawFragmentHeader::num_words() + 7;
614 1 : hdr0.version = 0;
615 1 : hdr0.type = 0xFE;
616 1 : hdr0.metadata_word_count = 0;
617 :
618 1 : hdr0.sequence_id = 0xFEEDDEADBEEF;
619 1 : hdr0.fragment_id = 0xBEE7;
620 1 : hdr0.timestamp = 0xCAFEFECA;
621 :
622 1 : hdr0.unused1 = 0xF0F0;
623 1 : hdr0.unused2 = 0xC5C5;
624 :
625 1 : memcpy(f.headerBeginBytes(), &hdr0, sizeof(hdr0));
626 1 : f.invalidateHeader();
627 :
628 1 : artdaq::detail::RawFragmentHeader::RawDataType counter = 0;
629 9 : for (size_t ii = artdaq::detail::RawFragmentHeaderV0::num_words(); ii < artdaq::detail::RawFragmentHeader::num_words() + 7; ++ii)
630 : {
631 8 : memcpy(f.headerBegin() + ii, &(++counter), sizeof(counter));
632 : }
633 :
634 1 : BOOST_REQUIRE_EQUAL(f.version(), 0);
635 1 : BOOST_REQUIRE_EQUAL(f.type(), 0xFE);
636 1 : BOOST_REQUIRE_EQUAL(f.hasMetadata(), false);
637 :
638 1 : BOOST_REQUIRE_EQUAL(f.sequenceID(), 0xFEEDDEADBEEF);
639 1 : BOOST_REQUIRE_EQUAL(f.fragmentID(), 0xBEE7);
640 1 : BOOST_REQUIRE_EQUAL(f.timestamp(), 0xCAFEFECA);
641 :
642 9 : for (size_t jj = 0; jj < f.dataSize(); ++jj)
643 : {
644 8 : BOOST_REQUIRE_EQUAL(*(f.dataBegin() + jj), jj + 1);
645 : }
646 1 : }
647 :
648 2 : BOOST_AUTO_TEST_CASE(Upgrade_V1)
649 : {
650 1 : artdaq::Fragment f(7);
651 : artdaq::detail::RawFragmentHeaderV1 hdr1;
652 :
653 1 : hdr1.word_count = artdaq::detail::RawFragmentHeader::num_words() + 7;
654 1 : hdr1.version = 1;
655 1 : hdr1.type = 0xFE;
656 1 : hdr1.metadata_word_count = 0;
657 :
658 1 : hdr1.sequence_id = 0xFEEDDEADBEEF;
659 1 : hdr1.fragment_id = 0xBEE7;
660 1 : hdr1.timestamp = 0xCAFEFECAAAAABBBB;
661 :
662 1 : memcpy(f.headerBeginBytes(), &hdr1, sizeof(hdr1));
663 1 : f.invalidateHeader();
664 :
665 1 : artdaq::detail::RawFragmentHeader::RawDataType counter = 0;
666 9 : for (size_t ii = artdaq::detail::RawFragmentHeaderV1::num_words(); ii < artdaq::detail::RawFragmentHeader::num_words() + 7; ++ii)
667 : {
668 8 : memcpy(f.headerBegin() + ii, &(++counter), sizeof(counter));
669 : }
670 :
671 1 : BOOST_REQUIRE_EQUAL(f.version(), 1);
672 1 : BOOST_REQUIRE_EQUAL(f.type(), 0xFE);
673 1 : BOOST_REQUIRE_EQUAL(f.hasMetadata(), false);
674 :
675 1 : BOOST_REQUIRE_EQUAL(f.sequenceID(), 0xFEEDDEADBEEF);
676 1 : BOOST_REQUIRE_EQUAL(f.fragmentID(), 0xBEE7);
677 1 : BOOST_REQUIRE_EQUAL(f.timestamp(), 0xCAFEFECAAAAABBBB);
678 :
679 9 : for (size_t jj = 0; jj < f.dataSize(); ++jj)
680 : {
681 8 : BOOST_REQUIRE_EQUAL(*(f.dataBegin() + jj), jj + 1); // NOLINT(cppcoreguidelines-pro-bounds-pointer-arithmetic)
682 : }
683 1 : }
684 :
685 : BOOST_AUTO_TEST_SUITE_END()
|