Project
Loading...
Searching...
No Matches
testDataHeader.cxx
Go to the documentation of this file.
1// Copyright 2019-2020 CERN and copyright holders of ALICE O2.
2// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders.
3// All rights not expressly granted are reserved.
4//
5// This software is distributed under the terms of the GNU General Public
6// License v3 (GPL Version 3), copied verbatim in the file "COPYING".
7//
8// In applying this license CERN does not waive the privileges and immunities
9// granted to it by virtue of its status as an Intergovernmental Organization
10// or submit itself to any jurisdiction.
11
12#define BOOST_TEST_MODULE Test Headers DataHeaderTest
13#define BOOST_TEST_MAIN
14#define BOOST_TEST_DYN_LINK
15#include <boost/test/unit_test.hpp>
16#include <iostream>
17#include <iomanip>
18#include "Headers/DataHeader.h"
20#include "Headers/NameHeader.h"
21#include "Headers/Stack.h"
22
23#include <chrono>
24
25using system_clock = std::chrono::system_clock;
26using TimeScale = std::chrono::nanoseconds;
27
28namespace o2
29{
30namespace header
31{
32namespace test
33{
34struct MetaHeader : public BaseHeader {
35 // Required to do the lookup
37 static const uint32_t sVersion = 1;
38
39 MetaHeader(uint32_t v)
41 {
42 }
43
44 uint64_t secret;
45};
47} // namespace test
48} // namespace header
49} // namespace o2
50
51namespace o2
52{
53namespace header
54{
55
56BOOST_AUTO_TEST_CASE(Descriptor_test)
57{
58 // test for the templated Descriptor struct
59 constexpr int descriptorSize = 8;
60 using TestDescriptorT = Descriptor<descriptorSize>;
61 BOOST_CHECK(TestDescriptorT::size == descriptorSize);
62 BOOST_CHECK(TestDescriptorT::bitcount == descriptorSize * 8);
63 BOOST_CHECK(sizeof(TestDescriptorT::ItgType) * TestDescriptorT::arraySize == descriptorSize);
64 static_assert(TestDescriptorT::size == sizeof(TestDescriptorT),
65 "Descriptor must have size of the underlying data member");
66
67 // the Descriptor allows to define an integral value from
68 // a char sequence so that the in-memory representation shows
69 // a readable pattern
70 constexpr char readable[] = "DESCRPTR";
71 // the inverse sequence as integer value: R T P R C S E D
72 constexpr TestDescriptorT::ItgType itgvalue = 0x5254505243534544;
73
74 TestDescriptorT testDescriptor(readable);
75 TestDescriptorT anotherDescriptor("ANOTHER");
76 BOOST_CHECK(TestDescriptorT::size == sizeof(testDescriptor));
77
78 // copy constructor and comparison operator
79 BOOST_CHECK(testDescriptor == TestDescriptorT(testDescriptor));
80
81 // comparison operator
82 BOOST_CHECK(testDescriptor != anotherDescriptor);
83
84 // type cast operator
85 BOOST_CHECK(itgvalue == testDescriptor);
86
87 // assignment operator
88 anotherDescriptor = testDescriptor;
89 BOOST_CHECK(testDescriptor == anotherDescriptor);
90 anotherDescriptor = TestDescriptorT("SOMEMORE");
91 BOOST_CHECK(itgvalue != anotherDescriptor);
92
93 // assignment using implicit conversion with constructor
94 anotherDescriptor = itgvalue;
95 BOOST_CHECK(testDescriptor == anotherDescriptor);
96
97 // check with runtime string
98 std::string runtimeString = "RUNTIMES";
99 TestDescriptorT runtimeDescriptor;
100 runtimeDescriptor.runtimeInit(runtimeString.c_str());
101 BOOST_CHECK(runtimeDescriptor == TestDescriptorT("RUNTIMES"));
102
103 BOOST_CHECK(testDescriptor.as<std::string>().length() == 8);
104}
105
106BOOST_AUTO_TEST_CASE(DataDescription_test)
107{
108 char test[16] = "ITSRAW*********";
109 test[6] = 0;
110
111 DataDescription desc("ITSRAW");
112 BOOST_CHECK(strcmp(desc.str, "ITSRAW") == 0);
113
114 // checking the corresponding integer value
115 // the upper part must be 0 since the string has only up tp 8 chars
116 // lower part corresponds to reverse ITSRAW
117 // W A R S T I
118 uint64_t itgDesc = 0x0000574152535449;
119 BOOST_CHECK(desc.itg[0] == itgDesc);
120 BOOST_CHECK(desc.itg[1] == 0);
121
122 BOOST_CHECK(desc == DataDescription("ITSRAW"));
123
124 DataDescription desc2(test);
125 BOOST_CHECK(strcmp(desc2.str, "ITSRAW") == 0);
126 // the upper part must be 0 since the string has only up tp 8 chars
127 BOOST_CHECK(desc2.itg[1] == 0);
128
129 BOOST_CHECK(desc2 == DataDescription("ITSRAW"));
130
131 std::string runtimeString = "DATA_DESCRIPTION";
132 DataDescription runtimeDesc;
133 runtimeDesc.runtimeInit(runtimeString.c_str());
134 BOOST_CHECK(runtimeDesc == DataDescription("DATA_DESCRIPTION"));
135
136 BOOST_CHECK(desc.as<std::string>().length() == 6);
137 BOOST_CHECK(runtimeDesc.as<std::string>().length() == 16);
138 BOOST_CHECK(DataDescription("INVALIDDATA").as<std::string>().length() == 11);
139
144}
145
146BOOST_AUTO_TEST_CASE(DataOrigin_test)
147{
148 // test for the templated Descriptor struct
149 constexpr int descriptorSize = 4;
150 using TestDescriptorT = Descriptor<descriptorSize>;
151 BOOST_CHECK(TestDescriptorT::size == descriptorSize);
152 BOOST_CHECK(TestDescriptorT::bitcount == descriptorSize * 8);
153 BOOST_CHECK(sizeof(TestDescriptorT::ItgType) * TestDescriptorT::arraySize == descriptorSize);
154 BOOST_CHECK(TestDescriptorT::size == sizeof(DataOrigin));
155
156 // we want to explicitely have the size of DataOrigin to be 4
157 static_assert(sizeof(DataOrigin) == 4,
158 "DataOrigin struct must be of size 4");
159
160 // Check that ordering works.
161 BOOST_CHECK(DataOrigin("A") < DataOrigin("B"));
162 BOOST_CHECK(DataOrigin("AA") < DataOrigin("AB"));
163 BOOST_CHECK(DataOrigin("AAA") < DataOrigin("AAB"));
164 BOOST_CHECK(DataOrigin("AAA") < DataOrigin("ABA"));
165 std::vector<DataOrigin> v1 = {DataOrigin("B"), DataOrigin("C"), DataOrigin("A")};
166 std::sort(v1.begin(), v1.end());
170 std::vector<DataOrigin> v2 = {DataOrigin("A"), DataOrigin("B")};
171 std::sort(v2.begin(), v2.end());
174
175 using CustomHeader = std::tuple<DataOrigin, DataDescription>;
176 std::vector<CustomHeader> v3{CustomHeader{"TST", "B"}, CustomHeader{"TST", "A"}};
177 std::sort(v3.begin(), v3.end());
178 auto h0 = CustomHeader{"TST", "A"};
179 auto h1 = CustomHeader{"TST", "B"};
180 BOOST_CHECK(v3[0] == h0);
181 BOOST_CHECK(v3[1] == h1);
182
183 using CustomHeader2 = std::tuple<DataOrigin, DataDescription, int>;
184 std::vector<CustomHeader2> v4{CustomHeader2{"TST", "A", 1}, CustomHeader2{"TST", "A", 0}};
185 std::sort(v4.begin(), v4.end());
186 auto hh0 = CustomHeader2{"TST", "A", 0};
187 auto hh1 = CustomHeader2{"TST", "A", 1};
188 BOOST_CHECK(v4[0] == hh0);
189 BOOST_CHECK(v4[1] == hh1);
190
191 struct CustomHeader3 {
192 DataOrigin origin;
193 DataDescription desc;
194 uint64_t subSpec;
195 int isOut;
196 };
197 std::vector<CustomHeader3> v5{CustomHeader3{"TST", "A", 0, 1}, CustomHeader3{"TST", "A", 0, 0}};
198 std::sort(v5.begin(), v5.end(), [](CustomHeader3 const& lhs, CustomHeader3 const& rhs) {
199 return std::tie(lhs.origin, lhs.desc, rhs.subSpec, lhs.isOut) < std::tie(rhs.origin, rhs.desc, rhs.subSpec, rhs.isOut);
200 });
201 BOOST_CHECK(v5[0].isOut == 0);
202 BOOST_CHECK(v5[1].isOut == 1);
203}
204
205BOOST_AUTO_TEST_CASE(BaseHeader_test)
206{
207 static_assert(sizeof(HeaderType) == 8,
208 "HeaderType struct must be of size 8");
209 static_assert(sizeof(SerializationMethod) == 8,
210 "SerializationMethod struct must be of size 8");
211 static_assert(sizeof(BaseHeader) == 32,
212 "BaseHeader struct must be of size 32");
213}
214
215BOOST_AUTO_TEST_CASE(DataHeader_test)
216{
217 DataHeader dh;
218 bool verbose = false;
219 if (verbose) {
220 std::cout << "size of BaseHeader: " << sizeof(BaseHeader) << std::endl;
221 std::cout << "size of DataHeader: " << sizeof(DataHeader) << std::endl;
222
223 std::cout << "dataDescription: "
224 << "size " << std::setw(2) << sizeof(dh.dataDescription) << " at " << (char*)(&dh.dataDescription) - (char*)(&dh) << std::endl;
225 std::cout << "dataOrigin: "
226 << "size " << std::setw(2) << sizeof(dh.dataOrigin) << " at " << (char*)(&dh.dataOrigin) - (char*)(&dh) << std::endl;
227 std::cout << "splitPayloadParts: "
228 << "size " << std::setw(2) << sizeof(dh.splitPayloadParts) << " at "
229 << (char*)(&dh.splitPayloadParts) - (char*)(&dh) << std::endl;
230 std::cout << "payloadSerializationMethod: "
231 << "size " << std::setw(2) << sizeof(dh.payloadSerializationMethod) << " at " << (char*)(&dh.payloadSerializationMethod) - (char*)(&dh) << std::endl;
232 std::cout << "subSpecification: "
233 << "size " << std::setw(2) << sizeof(dh.subSpecification) << " at " << (char*)(&dh.subSpecification) - (char*)(&dh) << std::endl;
234 std::cout << "splitPayloadIndex: "
235 << "size " << std::setw(2) << sizeof(dh.splitPayloadIndex) << " at "
236 << (char*)(&dh.splitPayloadIndex) - (char*)(&dh) << std::endl;
237 std::cout << "payloadSize "
238 << "size " << std::setw(2) << sizeof(dh.payloadSize) << " at " << (char*)(&dh.payloadSize) - (char*)(&dh) << std::endl;
239 }
240
241 // DataHeader must have size 96
242 static_assert(sizeof(DataHeader) == 96,
243 "DataHeader struct must be of size 96");
244 DataHeader dh2;
245 BOOST_CHECK(dh == dh2);
247 BOOST_CHECK(dh == dh3);
249 BOOST_CHECK(!(dh4 == dh));
250 dh4 = dh;
251 BOOST_CHECK(dh4 == dh);
253 BOOST_REQUIRE_EQUAL(fmt::format("{}", gDataOriginAny), "***");
254 BOOST_REQUIRE_EQUAL(fmt::format("{}", gDataDescriptionAny), "***************");
255 BOOST_REQUIRE_EQUAL(fmt::format("{}", DataHeader::SubSpecificationType{1}), "1");
256}
257
258BOOST_AUTO_TEST_CASE(headerStack_test)
259{
260
262
264 NameHeader<9>{"somename"}};
265
266 const DataHeader* h1 = get<DataHeader*>(s1.data());
267 BOOST_CHECK(h1 != nullptr);
268 BOOST_CHECK(*h1 == dh1);
270 const NameHeader<0>* h2 = get<NameHeader<0>*>(s1.data());
271 BOOST_CHECK(h2 != nullptr);
272 BOOST_CHECK(0 == std::strcmp(h2->getName(), "somename"));
275 BOOST_CHECK(h2->size() == sizeof(NameHeader<9>));
276 BOOST_CHECK(h2->getNameLength() == 9);
277
278 // create new stack from stack and additional header
279 auto meta = test::MetaHeader{42};
280 Stack s2{s1, meta};
281 BOOST_CHECK(s2.size() == s1.size() + sizeof(decltype(meta)));
282
283 //check dynamic construction - where we don't have the type information and need to
284 //work with BaseHeader pointers
285 const test::MetaHeader thead{2};
286 o2::header::BaseHeader const* bname = reinterpret_cast<BaseHeader const*>(&thead);
287 Stack ds2(s1, *bname);
288 BOOST_CHECK(ds2.size() == s1.size() + sizeof(thead));
289 BOOST_CHECK(std::memcmp(get<test::MetaHeader*>(ds2.data()), &thead, sizeof(thead)) == 0);
290
291 auto* h3 = get<test::MetaHeader*>(s1.data());
292 BOOST_CHECK(h3 == nullptr);
293 h3 = get<test::MetaHeader*>(s2.data());
294 BOOST_REQUIRE(h3 != nullptr);
295 BOOST_CHECK(h3->flagsNextHeader == false);
296 h1 = get<DataHeader*>(s2.data());
297 BOOST_REQUIRE(h1 != nullptr);
298 BOOST_CHECK(h1->flagsNextHeader == true);
299
300 // create stack from header and empty stack
301 Stack s3{meta, Stack{}};
302 BOOST_CHECK(s3.size() == sizeof(meta));
303 h3 = get<test::MetaHeader*>(s3.data());
304 BOOST_REQUIRE(h3 != nullptr);
305 // no next header to be flagged as the stack was empty
306 BOOST_CHECK(h3->flagsNextHeader == false);
307
308 // create new stack from stack, empty stack, and header
309 Stack s4{s1, Stack{}, meta};
310 BOOST_CHECK(s4.size() == s1.size() + sizeof(meta));
311 // check if we can find the header even though there was an empty stack in the middle
312 h3 = get<test::MetaHeader*>(s4.data());
313 BOOST_REQUIRE(h3 != nullptr);
314 BOOST_CHECK(h3->secret == 42);
315
316 //test constructing from a buffer and an additional header
317 using namespace boost::container::pmr;
318 Stack s5(new_delete_resource(), s1.data(), Stack{}, meta);
319 BOOST_CHECK(s5.size() == s1.size() + sizeof(meta));
320 // check if we can find the header even though there was an empty stack in the middle
321 h3 = get<test::MetaHeader*>(s5.data());
322 BOOST_REQUIRE(h3 != nullptr);
323 BOOST_CHECK(h3->secret == 42);
324 auto* h4 = Stack::lastHeader(s5.data());
325 auto* h5 = Stack::firstHeader(s5.data());
326 auto* h6 = get<DataHeader*>(s5.data());
327 BOOST_REQUIRE(h5 == h6);
328 BOOST_REQUIRE(h5 != nullptr);
329 BOOST_CHECK(h4 == h3);
330
331 // let's assume we have some stack that is missing the required DataHeader at the beginning:
332 Stack s6{new_delete_resource(), DataHeader{}, s1.data()};
333 BOOST_CHECK(s6.size() == sizeof(DataHeader) + s1.size());
334}
335
336BOOST_AUTO_TEST_CASE(Descriptor_benchmark)
337{
338 using TestDescriptor = Descriptor<8>;
339 TestDescriptor a("TESTDESC");
340 TestDescriptor b(a);
341
342 auto refTime = system_clock::now();
343 const int nrolls = 1000000;
344 for (auto count = 0; count < nrolls; ++count) {
345 if (a == b) {
346 ++a.itg[0];
347 ++b.itg[0];
348 }
349 }
350 auto duration = std::chrono::duration_cast<TimeScale>(std::chrono::system_clock::now() - refTime);
351 std::cout << nrolls << " operation(s): " << duration.count() << " ns" << std::endl;
352 // there is not really a check at the moment
353}
354
355BOOST_AUTO_TEST_CASE(Descriptor_formatting)
356{
357 using TestDescriptor = Descriptor<8>;
358 TestDescriptor a("TESTDESC");
359 TestDescriptor b(a);
360
361 auto refTime = system_clock::now();
362 const int nrolls = 1000000;
363 for (auto count = 0; count < nrolls; ++count) {
364 if (a == b) {
365 ++a.itg[0];
366 ++b.itg[0];
367 }
368 }
369 auto duration = std::chrono::duration_cast<TimeScale>(std::chrono::system_clock::now() - refTime);
370 std::cout << nrolls << " operation(s): " << duration.count() << " ns" << std::endl;
371 // there is not really a check at the moment
372}
373} // namespace header
374} // namespace o2
GLint GLsizei count
Definition glcorearb.h:399
const GLdouble * v
Definition glcorearb.h:832
GLuint GLfloat GLfloat GLfloat GLfloat GLfloat GLfloat GLfloat GLfloat s1
Definition glcorearb.h:5034
GLboolean GLboolean GLboolean b
Definition glcorearb.h:1233
GLuint GLsizei GLsizei * length
Definition glcorearb.h:790
GLfloat GLfloat v1
Definition glcorearb.h:812
GLfloat GLfloat GLfloat GLfloat v3
Definition glcorearb.h:814
GLboolean GLboolean GLboolean GLboolean a
Definition glcorearb.h:1233
GLfloat GLfloat GLfloat v2
Definition glcorearb.h:813
constexpr o2::header::DataDescription gDataDescriptionInvalid
Definition DataHeader.h:596
constexpr o2::header::DataOrigin gDataOriginInvalid
Definition DataHeader.h:561
constexpr o2::header::DataOrigin gDataOriginAny
Definition DataHeader.h:560
constexpr o2::header::DataDescription gDataDescriptionAny
Definition DataHeader.h:595
Descriptor< gSizeHeaderDescriptionString > HeaderType
Definition DataHeader.h:321
Descriptor< gSizeDataDescriptionString > DataDescription
Definition DataHeader.h:551
BOOST_AUTO_TEST_CASE(Descriptor_test)
constexpr o2::header::SerializationMethod gSerializationMethodNone
Definition DataHeader.h:327
Descriptor< gSizeDataOriginString > DataOrigin
Definition DataHeader.h:550
Descriptor< gSizeSerializationMethodString > SerializationMethod
Definition DataHeader.h:322
a couple of static helper functions to create timestamp values for CCDB queries or override obsolete ...
FIXME: do not use data model tables.
the base header struct Every header type must begin (i.e. derive) with this. Don't use this struct di...
Definition DataHeader.h:351
const std::byte * data() const noexcept
Definition DataHeader.h:422
o2::header::HeaderType description
header type description, set by derived header
Definition DataHeader.h:385
constexpr uint32_t size() const noexcept
Definition DataHeader.h:421
o2::header::SerializationMethod serialization
header serialization method, set by derived header
Definition DataHeader.h:388
the main header struct
Definition DataHeader.h:618
SplitPayloadPartsType splitPayloadParts
Definition DataHeader.h:646
SerializationMethod payloadSerializationMethod
Definition DataHeader.h:651
DataDescription dataDescription
Definition DataHeader.h:636
SubSpecificationType subSpecification
Definition DataHeader.h:656
PayloadSizeType payloadSize
Definition DataHeader.h:666
uint32_t SubSpecificationType
Definition DataHeader.h:620
SplitPayloadIndexType splitPayloadIndex
Definition DataHeader.h:661
std::enable_if_t< std::is_same< T, std::string >::value==true, T > as() const
get the descriptor as std::string
Definition DataHeader.h:301
void runtimeInit(const char *string, short length=-1)
Definition DataHeader.h:261
ItgType itg[arraySize]
Definition DataHeader.h:218
an example data header containing a name of an object as a null terminated char arr....
Definition NameHeader.h:39
const char * getName() const
Definition NameHeader.h:68
size_t getNameLength() const
Definition NameHeader.h:69
a move-only header stack with serialized headers This is the flat buffer where all the headers in a m...
Definition Stack.h:36
size_t size() const
Definition Stack.h:59
static const BaseHeader * firstHeader(std::byte const *buf)
Definition Stack.h:62
static const BaseHeader * lastHeader(std::byte const *buf)
Definition Stack.h:63
value_type * data() const
Definition Stack.h:58
static const uint32_t sVersion
static const o2::header::HeaderType sHeaderType
std::chrono::system_clock system_clock
std::chrono::nanoseconds TimeScale
BOOST_CHECK(tree)
BOOST_CHECK_EQUAL(triggersD.size(), triggers.size())