Project
Loading...
Searching...
No Matches
test_DataDescriptorMatcher.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
14#include "Framework/InputSpec.h"
16#include "Headers/Stack.h"
17
18#include <catch_amalgamated.hpp>
19#include <variant>
20
21using namespace o2::framework;
22using namespace o2::header;
23using namespace o2::framework::data_matcher;
24
25TEST_CASE("TestMatcherInvariants")
26{
27 DataHeader header0;
28 header0.dataOrigin = "TPC";
29 header0.dataDescription = "CLUSTERS";
30 header0.subSpecification = 1;
31 VariableContext context;
32
33 DataHeader header1;
34 header1.dataOrigin = "ITS";
35 header1.dataDescription = "TRACKLET";
36 header1.subSpecification = 2;
37
38 DataHeader header2;
39 header2.dataOrigin = "TPC";
40 header2.dataDescription = "TRACKLET";
41 header2.subSpecification = 1;
42
43 DataHeader header3;
44 header3.dataOrigin = "TPC";
45 header3.dataDescription = "CLUSTERS";
46 header3.subSpecification = 0;
47
48 DataHeader header4;
49 header4.dataOrigin = "TRD";
50 header4.dataDescription = "TRACKLET";
51 header4.subSpecification = 0;
52
54 DataDescriptorMatcher::Op::And,
55 OriginValueMatcher{"TPC"},
56 std::make_unique<DataDescriptorMatcher>(
57 DataDescriptorMatcher::Op::And,
58 DescriptionValueMatcher{"CLUSTERS"},
59 std::make_unique<DataDescriptorMatcher>(
60 DataDescriptorMatcher::Op::And,
62 ConstantValueMatcher{true}))};
63 DataDescriptorMatcher matcher2 = matcher;
64 REQUIRE(matcher.match(header0, context) == true);
65 REQUIRE(matcher.match(header1, context) == false);
66 REQUIRE(matcher.match(header2, context) == false);
67 REQUIRE(matcher.match(header3, context) == false);
68 REQUIRE(matcher.match(header4, context) == false);
69 REQUIRE(matcher2.match(header0, context) == true);
70 REQUIRE(matcher2.match(header1, context) == false);
71 REQUIRE(matcher2.match(header2, context) == false);
72 REQUIRE(matcher2.match(header3, context) == false);
73 REQUIRE(matcher2.match(header4, context) == false);
74
75 REQUIRE(matcher2 == matcher);
76
77 {
78 DataDescriptorMatcher matcherA{
79 DataDescriptorMatcher::Op::Just,
80 OriginValueMatcher{"TPC"}};
81 DataDescriptorMatcher matcherB{
82 DataDescriptorMatcher::Op::Just,
83 OriginValueMatcher{"TPC"}};
84 REQUIRE(matcherA == matcherB);
85 }
86
87 {
88 DataDescriptorMatcher matcherA{
89 DataDescriptorMatcher::Op::Just,
90 DescriptionValueMatcher{"TRACKS"}};
91 DataDescriptorMatcher matcherB{
92 DataDescriptorMatcher::Op::Just,
93 DescriptionValueMatcher{"TRACKS"}};
94 REQUIRE(matcherA == matcherB);
95 }
96
97 {
98 DataDescriptorMatcher matcherA{
99 DataDescriptorMatcher::Op::Just,
101 DataDescriptorMatcher matcherB{
102 DataDescriptorMatcher::Op::Just,
104 REQUIRE(matcherA == matcherB);
105 }
106
107 {
108 DataDescriptorMatcher matcherA{
109 DataDescriptorMatcher::Op::Just,
111 DataDescriptorMatcher matcherB{
112 DataDescriptorMatcher::Op::Just,
114 REQUIRE(matcherA == matcherB);
115 }
116
117 {
118 DataDescriptorMatcher matcherA{
119 DataDescriptorMatcher::Op::And,
122 DataDescriptorMatcher matcherB{
123 DataDescriptorMatcher::Op::Just,
126 REQUIRE(!(matcherA == matcherB));
127 }
128
129 {
130 DataDescriptorMatcher matcherA{
131 DataDescriptorMatcher::Op::And,
132 OriginValueMatcher{"TPC"},
133 std::make_unique<DataDescriptorMatcher>(
134 DataDescriptorMatcher::Op::And,
135 DescriptionValueMatcher{"CLUSTERS"},
136 std::make_unique<DataDescriptorMatcher>(
137 DataDescriptorMatcher::Op::And,
139 ConstantValueMatcher{true}))};
140
141 DataDescriptorMatcher matcherB{
142 DataDescriptorMatcher::Op::And,
143 OriginValueMatcher{"TPC"},
144 std::make_unique<DataDescriptorMatcher>(
145 DataDescriptorMatcher::Op::And,
146 DescriptionValueMatcher{"CLUSTERS"},
147 std::make_unique<DataDescriptorMatcher>(
148 DataDescriptorMatcher::Op::And,
150 ConstantValueMatcher{true}))};
151 REQUIRE(matcherA == matcherB);
152 }
153
154 {
155 DataDescriptorMatcher matcherA{
156 DataDescriptorMatcher::Op::Not,
157 OriginValueMatcher{"TPC"}};
158 DataDescriptorMatcher matcherB{
159 DataDescriptorMatcher::Op::Not,
160 DescriptionValueMatcher{"TRACKLET"}};
161 DataDescriptorMatcher matcherC{
162 DataDescriptorMatcher::Op::Not,
164
165 REQUIRE(matcherA.match(header0, context) == false);
166 REQUIRE(matcherA.match(header1, context) == true);
167 REQUIRE(matcherA.match(header4, context) == true);
168 REQUIRE(matcherB.match(header0, context) == true);
169 REQUIRE(matcherB.match(header1, context) == false);
170 REQUIRE(matcherB.match(header4, context) == false);
171 REQUIRE(matcherC.match(header0, context) == false);
172 REQUIRE(matcherC.match(header1, context) == true);
173 REQUIRE(matcherC.match(header4, context) == true);
174 }
175}
176
177TEST_CASE("TestSimpleMatching")
178{
179 DataHeader header0;
180 header0.dataOrigin = "TPC";
181 header0.dataDescription = "CLUSTERS";
182 header0.subSpecification = 1;
183
184 DataHeader header1;
185 header1.dataOrigin = "ITS";
186 header1.dataDescription = "TRACKLET";
187 header1.subSpecification = 2;
188
189 DataHeader header2;
190 header2.dataOrigin = "TPC";
191 header2.dataDescription = "TRACKLET";
192 header2.subSpecification = 1;
193
194 DataHeader header3;
195 header3.dataOrigin = "TPC";
196 header3.dataDescription = "CLUSTERS";
197 header3.subSpecification = 0;
198
199 DataHeader header4;
200 header4.dataOrigin = "TRD";
201 header4.dataDescription = "TRACKLET";
202 header4.subSpecification = 0;
203
204 DataDescriptorMatcher matcher{
205 DataDescriptorMatcher::Op::And,
206 OriginValueMatcher{"TPC"},
207 std::make_unique<DataDescriptorMatcher>(
208 DataDescriptorMatcher::Op::And,
209 DescriptionValueMatcher{"CLUSTERS"},
210 std::make_unique<DataDescriptorMatcher>(
211 DataDescriptorMatcher::Op::And,
213 ConstantValueMatcher{true}))};
214
215 VariableContext context;
216 REQUIRE(matcher.match(header0, context) == true);
217 REQUIRE(matcher.match(header1, context) == false);
218 REQUIRE(matcher.match(header2, context) == false);
219 REQUIRE(matcher.match(header3, context) == false);
220 REQUIRE(matcher.match(header4, context) == false);
221
222 DataDescriptorMatcher matcher1{
223 DataDescriptorMatcher::Op::Or,
224 OriginValueMatcher{"TPC"},
225 OriginValueMatcher{"ITS"}};
226
227 REQUIRE(matcher1.match(header0, context) == true);
228 REQUIRE(matcher1.match(header1, context) == true);
229 REQUIRE(matcher1.match(header2, context) == true);
230 REQUIRE(matcher1.match(header3, context) == true);
231 REQUIRE(matcher1.match(header4, context) == false);
232
233 DataDescriptorMatcher matcher2{
234 DataDescriptorMatcher::Op::Just,
235 DescriptionValueMatcher{"TRACKLET"}};
236
237 REQUIRE(matcher2.match(header0, context) == false);
238 REQUIRE(matcher2.match(header1, context) == true);
239 REQUIRE(matcher2.match(header2, context) == true);
240 REQUIRE(matcher2.match(header3, context) == false);
241 REQUIRE(matcher2.match(header4, context) == true);
242}
243
244TEST_CASE("TestDataDescriptorQueryBuilder")
245{
246 DataHeader header0;
247 header0.dataOrigin = "TPC";
248 header0.dataDescription = "CLUSTERS";
249 header0.subSpecification = 1;
250
251 DataHeader header1;
252 header1.dataOrigin = "ITS";
253 header1.dataDescription = "TRACKLET";
254 header1.subSpecification = 2;
255
256 DataHeader header2;
257 header2.dataOrigin = "TPC";
258 header2.dataDescription = "TRACKLET";
259 header2.subSpecification = 1;
260
261 DataHeader header3;
262 header3.dataOrigin = "TPC";
263 header3.dataDescription = "CLUSTERS";
264 header3.subSpecification = 0;
265
266 DataHeader header4;
267 header4.dataOrigin = "TRD";
268 header4.dataDescription = "TRACKLET";
269 header4.subSpecification = 0;
270
272 VariableContext context;
273
274 auto matcher1 = DataDescriptorQueryBuilder::buildFromKeepConfig("TPC/CLUSTERS/1");
275 REQUIRE(matcher1.matcher->match(header0, context) == true);
276 REQUIRE(matcher1.matcher->match(header1, context) == false);
277 REQUIRE(matcher1.matcher->match(header2, context) == false);
278 REQUIRE(matcher1.matcher->match(header3, context) == false);
279 REQUIRE(matcher1.matcher->match(header4, context) == false);
280
281 auto matcher2 = DataDescriptorQueryBuilder::buildFromKeepConfig("ITS/TRACKLET/2");
282 REQUIRE(matcher2.matcher->match(header0, context) == false);
283 REQUIRE(matcher2.matcher->match(header1, context) == true);
284 REQUIRE(matcher2.matcher->match(header2, context) == false);
285 REQUIRE(matcher2.matcher->match(header3, context) == false);
286 REQUIRE(matcher2.matcher->match(header4, context) == false);
287
288 auto matcher3 = DataDescriptorQueryBuilder::buildFromKeepConfig("TPC/CLUSTERS/1,ITS/TRACKLET/2");
289 REQUIRE(matcher3.matcher->match(header0, context) == true);
290 REQUIRE(matcher3.matcher->match(header1, context) == true);
291 REQUIRE(matcher3.matcher->match(header2, context) == false);
292 REQUIRE(matcher3.matcher->match(header3, context) == false);
293 REQUIRE(matcher3.matcher->match(header4, context) == false);
294
296 REQUIRE(matcher4.matcher->match(header0, context) == false);
297 REQUIRE(matcher4.matcher->match(header1, context) == false);
298 REQUIRE(matcher4.matcher->match(header2, context) == false);
299 REQUIRE(matcher4.matcher->match(header3, context) == false);
300 REQUIRE(matcher4.matcher->match(header4, context) == false);
301}
302
303// This checks matching using variables
304TEST_CASE("TestMatchingVariables")
305{
306 VariableContext context;
307
308 DataDescriptorMatcher matcher{
309 DataDescriptorMatcher::Op::And,
311 std::make_unique<DataDescriptorMatcher>(
312 DataDescriptorMatcher::Op::And,
313 DescriptionValueMatcher{"CLUSTERS"},
314 std::make_unique<DataDescriptorMatcher>(
315 DataDescriptorMatcher::Op::And,
317 ConstantValueMatcher{true}))};
318
319 DataHeader header0;
320 header0.dataOrigin = "TPC";
321 header0.dataDescription = "CLUSTERS";
322 header0.subSpecification = 1;
323
324 REQUIRE(matcher.match(header0, context) == true);
325 auto s = std::get_if<std::string>(&context.get(0));
326 REQUIRE(s != nullptr);
327 REQUIRE(*s == "TPC");
328 auto v = std::get_if<o2::header::DataHeader::SubSpecificationType>(&context.get(1));
329 REQUIRE(v != nullptr);
330 REQUIRE(*v == 1);
331
332 // This will not match, because ContextRef{0} is bound
333 // to TPC already.
334 DataHeader header1;
335 header1.dataOrigin = "ITS";
336 header1.dataDescription = "CLUSTERS";
337 header1.subSpecification = 1;
338
339 REQUIRE(matcher.match(header1, context) == false);
340 auto s1 = std::get_if<std::string>(&context.get(0));
341 REQUIRE(s1 != nullptr);
342 REQUIRE(*s1 == "TPC");
343}
344
345TEST_CASE("TestInputSpecMatching")
346{
347 ConcreteDataMatcher spec0{"TPC", "CLUSTERS", 1};
348 ConcreteDataMatcher spec1{"ITS", "TRACKLET", 2};
349 ConcreteDataMatcher spec2{"ITS", "TRACKLET", 1};
350 ConcreteDataMatcher spec3{"TPC", "CLUSTERS", 0};
351 ConcreteDataMatcher spec4{"TRD", "TRACKLET", 0};
352
353 DataDescriptorMatcher matcher{
354 DataDescriptorMatcher::Op::And,
355 OriginValueMatcher{"TPC"},
356 std::make_unique<DataDescriptorMatcher>(
357 DataDescriptorMatcher::Op::And,
358 DescriptionValueMatcher{"CLUSTERS"},
359 std::make_unique<DataDescriptorMatcher>(
360 DataDescriptorMatcher::Op::And,
362 ConstantValueMatcher{true}))};
363
364 VariableContext context;
365
366 REQUIRE(matcher.match(spec0, context) == true);
367 REQUIRE(matcher.match(spec1, context) == false);
368 REQUIRE(matcher.match(spec2, context) == false);
369 REQUIRE(matcher.match(spec3, context) == false);
370 REQUIRE(matcher.match(spec4, context) == false);
371
372 DataDescriptorMatcher matcher1{
373 DataDescriptorMatcher::Op::Or,
374 OriginValueMatcher{"TPC"},
375 OriginValueMatcher{"ITS"}};
376
377 REQUIRE(matcher1.match(spec0, context) == true);
378 REQUIRE(matcher1.match(spec1, context) == true);
379 REQUIRE(matcher1.match(spec2, context) == true);
380 REQUIRE(matcher1.match(spec3, context) == true);
381 REQUIRE(matcher1.match(spec4, context) == false);
382
383 DataDescriptorMatcher matcher2{
384 DataDescriptorMatcher::Op::Just,
385 DescriptionValueMatcher{"TRACKLET"}};
386
387 REQUIRE(matcher2.match(spec0, context) == false);
388 REQUIRE(matcher2.match(spec1, context) == true);
389 REQUIRE(matcher2.match(spec2, context) == true);
390 REQUIRE(matcher2.match(spec3, context) == false);
391 REQUIRE(matcher2.match(spec4, context) == true);
392}
393
394TEST_CASE("TestStartTimeMatching")
395{
396 VariableContext context;
397
398 DataDescriptorMatcher matcher{
399 DataDescriptorMatcher::Op::Just,
401
402 DataHeader dh;
403 dh.dataOrigin = "TPC";
404 dh.dataDescription = "CLUSTERS";
405 dh.subSpecification = 1;
406
408 dph.startTime = 123;
409
410 Stack s{dh, dph};
411 auto s2dph = o2::header::get<DataProcessingHeader*>(s.data());
412 REQUIRE(s2dph != nullptr);
413 REQUIRE(s2dph->startTime == 123);
414 REQUIRE(matcher.match(s, context) == true);
415 auto vPtr = std::get_if<uint64_t>(&context.get(0));
416 REQUIRE(vPtr != nullptr);
417 REQUIRE(*vPtr == 123);
418}
419
422TEST_CASE("TestAtomicUpdatesOfContext")
423{
424 VariableContext context;
425
426 DataDescriptorMatcher matcher{
427 DataDescriptorMatcher::Op::And,
429 std::make_unique<DataDescriptorMatcher>(
430 DataDescriptorMatcher::Op::And,
431 DescriptionValueMatcher{"CLUSTERS"},
432 std::make_unique<DataDescriptorMatcher>(
433 DataDescriptorMatcher::Op::Just,
435
438 DataHeader dh;
439 dh.dataOrigin = "TPC";
440 dh.dataDescription = "TRACKS";
441 dh.subSpecification = 1;
442
443 auto vPtr0 = std::get_if<None>(&context.get(0));
444 auto vPtr1 = std::get_if<None>(&context.get(1));
445 REQUIRE(vPtr0 != nullptr);
446 REQUIRE(vPtr1 != nullptr);
447 REQUIRE(matcher.match(dh, context) == false);
448 // We discard the updates, because there was no match
449 context.discard();
450 vPtr0 = std::get_if<None>(&context.get(0));
451 vPtr1 = std::get_if<None>(&context.get(1));
452 REQUIRE(vPtr0 != nullptr);
453 REQUIRE(vPtr1 != nullptr);
454}
455
456TEST_CASE("TestVariableContext")
457{
458 VariableContext context;
459 // Put some updates, but do not commit them
460 // we should still be able to retrieve them
461 // (just slower).
462 context.put(ContextUpdate{0, "A TEST"});
463 context.put(ContextUpdate{10, uint32_t{77}});
464 auto v1 = std::get_if<std::string>(&context.get(0));
465 REQUIRE(v1 != nullptr);
466 REQUIRE(*v1 == "A TEST");
467 auto v2 = std::get_if<std::string>(&context.get(1));
468 REQUIRE(v2 == nullptr);
469 auto v3 = std::get_if<uint32_t>(&context.get(10));
470 REQUIRE(v3 != nullptr);
471 REQUIRE(*v3 == 77);
472 context.commit();
473 // After commits everything is the same
474 v1 = std::get_if<std::string>(&context.get(0));
475 REQUIRE(v1 != nullptr);
476 REQUIRE(*v1 == "A TEST");
477 v2 = std::get_if<std::string>(&context.get(1));
478 REQUIRE(v2 == nullptr);
479 v3 = std::get_if<uint32_t>(&context.get(10));
480 REQUIRE(v3 != nullptr);
481 REQUIRE(*v3 == 77);
482
483 // Let's update again. New values should win.
484 context.put(ContextUpdate{0, "SOME MORE"});
485 context.put(ContextUpdate{10, uint32_t{16}});
486 v1 = std::get_if<std::string>(&context.get(0));
487 REQUIRE(v1 != nullptr);
488 REQUIRE(*v1 == "SOME MORE");
489 v2 = std::get_if<std::string>(&context.get(1));
490 REQUIRE(v2 == nullptr);
491 v3 = std::get_if<uint32_t>(&context.get(10));
492 REQUIRE(v3 != nullptr);
493 REQUIRE(*v3 == 16);
494
495 // Until we discard
496 context.discard();
497 v1 = std::get_if<std::string>(&context.get(0));
498 REQUIRE(v1 != nullptr);
499 REQUIRE(*v1 == "A TEST");
500 auto n = std::get_if<None>(&context.get(1));
501 REQUIRE(n != nullptr);
502 v3 = std::get_if<uint32_t>(&context.get(10));
503 REQUIRE(v3 != nullptr);
504 REQUIRE(*v3 == 77);
505
506 // Let's update again. New values should win.
507 context.put(ContextUpdate{0, "SOME MORE"});
508 context.put(ContextUpdate{10, uint32_t{16}});
509 v1 = std::get_if<std::string>(&context.get(0));
510 REQUIRE(v1 != nullptr);
511 REQUIRE(*v1 == "SOME MORE");
512 v2 = std::get_if<std::string>(&context.get(1));
513 REQUIRE(v2 == nullptr);
514 v3 = std::get_if<uint32_t>(&context.get(10));
515 REQUIRE(v3 != nullptr);
516 REQUIRE(*v3 == 16);
517
518 // Until we discard again, using reset
519 context.reset();
520 auto n1 = std::get_if<None>(&context.get(0));
521 REQUIRE(n1 != nullptr);
522 auto n2 = std::get_if<None>(&context.get(1));
523 REQUIRE(n2 != nullptr);
524 auto n3 = std::get_if<None>(&context.get(10));
525 REQUIRE(n3 != nullptr);
526
527 // auto d3 = std::get_if<uint64_t>(&context.get(0));
528 // REQUIRE(d1 == nullptr);;
529 // REQUIRE(d2 == nullptr);;
530 // REQUIRE(d3 == nullptr);;
531}
532
533TEST_CASE("DataQuery")
534{
535 auto empty_bindings = [](std::runtime_error const& ex) -> bool {
536 REQUIRE(std::string(ex.what()) == "Parse error: empty binding string");
537 return true;
538 };
539 auto missing_origin = [](std::runtime_error const& ex) -> bool {
540 REQUIRE(std::string(ex.what()) == "Parse error: origin needs to be between 1 and 4 char long");
541 return true;
542 };
543 auto missing_description = [](std::runtime_error const& ex) -> bool {
544 REQUIRE(std::string(ex.what()) == "Parse error: description needs to be between 1 and 16 char long");
545 return true;
546 };
547 auto missing_subspec = [](std::runtime_error const& ex) -> bool {
548 REQUIRE(std::string(ex.what()) == "Parse error: Expected a number");
549 return true;
550 };
551 auto missing_timemodulo = [](std::runtime_error const& ex) -> bool {
552 REQUIRE(std::string(ex.what()) == "Parse error: Expected a number");
553 return true;
554 };
555 auto trailing_semicolon = [](std::runtime_error const& ex) -> bool {
556 REQUIRE(std::string(ex.what()) == "Parse error: Remove trailing ;");
557 return true;
558 };
559
560 auto missing_value = [](std::runtime_error const& ex) -> bool {
561 REQUIRE(std::string(ex.what()) == "Parse error: value needs to be between 1 and 1000 char long");
562 return true;
563 };
564 auto missing_key = [](std::runtime_error const& ex) -> bool {
565 REQUIRE(std::string(ex.what()) == "Parse error: missing value for attribute key");
566 return true;
567 };
568 // Empty query.
569 REQUIRE(DataDescriptorQueryBuilder::parse().empty() == true);
570 // Empty bindings.
571 REQUIRE_THROWS_AS(DataDescriptorQueryBuilder::parse(":"), std::runtime_error);
572 // Missing origin
573 REQUIRE_THROWS_AS(DataDescriptorQueryBuilder::parse("x:"), std::runtime_error);
574 // Origin too long
575 REQUIRE_THROWS_AS(DataDescriptorQueryBuilder::parse("x:bacjasbjkca"), std::runtime_error);
576 // This is a valid expression, short for x:TST/*/* or x:TST/$1/$2
577 REQUIRE_NOTHROW(DataDescriptorQueryBuilder::parse("x:TST"));
578 // This one is not, as we expect a description after a /
579 REQUIRE_THROWS_AS(DataDescriptorQueryBuilder::parse("x:TST/"), std::runtime_error);
580 // This one is not, as the description is too long
581 REQUIRE_THROWS_AS(DataDescriptorQueryBuilder::parse("x:TST/cdjancajncjancjkancjkadncancnacaklmcak"), std::runtime_error);
582 // This one is ok, short for "x:TST/A1/*"
583 REQUIRE_NOTHROW(DataDescriptorQueryBuilder::parse("x:TST/A1"));
584 // This one is not, as subspec needs to be a value or a range.
585 REQUIRE_THROWS_AS(DataDescriptorQueryBuilder::parse("x:TST/A1/"), std::runtime_error);
586 // Not valid as subspec should be a number.
587 REQUIRE_THROWS_AS(DataDescriptorQueryBuilder::parse("x:TST/A1/a0"), std::runtime_error);
588
589 // Let's verify that the contents are correct.
590 auto result0 = DataDescriptorQueryBuilder::parse("x:TST/A1/77");
591 REQUIRE(result0.size() == 1);
592 DataDescriptorMatcher expectedMatcher00{
593 DataDescriptorMatcher::Op::And,
594 OriginValueMatcher{"TST"},
595 std::make_unique<DataDescriptorMatcher>(
596 DataDescriptorMatcher::Op::And,
598 std::make_unique<DataDescriptorMatcher>(
599 DataDescriptorMatcher::Op::And,
601 std::make_unique<DataDescriptorMatcher>(DataDescriptorMatcher::Op::Just,
603 auto matcher = std::get_if<DataDescriptorMatcher>(&result0[0].matcher);
604 REQUIRE(matcher != nullptr);
605 REQUIRE(expectedMatcher00 == *matcher);
606 std::ostringstream ss0;
607 ss0 << *matcher;
608 std::ostringstream expectedSS00;
609 expectedSS00 << expectedMatcher00;
610 REQUIRE(ss0.str() == "(and origin:TST (and description:A1 (and subSpec:77 (just startTime:$0 ))))");
611 REQUIRE(expectedSS00.str() == "(and origin:TST (and description:A1 (and subSpec:77 (just startTime:$0 ))))");
612 REQUIRE(ss0.str() == expectedSS00.str());
613
614 // This is valid. TimeModulo is 1.
615 REQUIRE_NOTHROW(DataDescriptorQueryBuilder::parse("x:TST/A1/0"));
616 // Not valid as timemodulo should be a number.
617 REQUIRE_THROWS_AS(DataDescriptorQueryBuilder::parse("x:TST/A1/0%"), std::runtime_error);
618 REQUIRE_THROWS_AS(DataDescriptorQueryBuilder::parse("x:TST/A1/0\%oabdian"), std::runtime_error);
619 // This is valid.
620 REQUIRE_NOTHROW(DataDescriptorQueryBuilder::parse("x:TST/A1/0%1"));
621 // This is not valid.
622 REQUIRE_THROWS_AS(DataDescriptorQueryBuilder::parse("x:TST/A1/0%1;:"), std::runtime_error);
623 // This is not valid.
624 REQUIRE_THROWS_AS(DataDescriptorQueryBuilder::parse("x:TST/A1/0%1;"), std::runtime_error);
625 // This is valid.
626 REQUIRE_NOTHROW(DataDescriptorQueryBuilder::parse("x:TST/A1/0%1;x:TST/A2"));
627 // Let's verify that the contents are correct.
628 auto result1 = DataDescriptorQueryBuilder::parse("x:TST/A1/0%1;y:TST/A2");
629 REQUIRE(result1.size() == 2);
630
631 std::ostringstream ops;
632 ops << DataDescriptorMatcher::Op::And
633 << DataDescriptorMatcher::Op::Or
634 << DataDescriptorMatcher::Op::Xor
635 << DataDescriptorMatcher::Op::Just;
636 REQUIRE(ops.str() == "andorxorjust");
637
638 // Let's check the metadata associated to a query
639 auto result2 = DataDescriptorQueryBuilder::parse("x:TST/A1/0?lifetime=condition");
640 REQUIRE(result2[0].lifetime == Lifetime::Condition);
641
642 REQUIRE_THROWS_AS(DataDescriptorQueryBuilder::parse("x:TST/A1/0?lifetime="), std::runtime_error);
643 REQUIRE_THROWS_AS(DataDescriptorQueryBuilder::parse("x:TST/A1/0?"), std::runtime_error);
644
645 auto result3 = DataDescriptorQueryBuilder::parse("x:TST/A1/0?key=value&key2=value2");
646 REQUIRE(result3[0].metadata.size() == 2);
647
648 auto result4 = DataDescriptorQueryBuilder::parse("x:TST/A1/0?lifetime=condition&ccdb-path=GLO/Config/GRPECS&key3=value3");
649 REQUIRE(result4.size() == 1);
650 result4[0].lifetime = Lifetime::Condition;
651 REQUIRE(result4[0].metadata.size() == 3);
652 REQUIRE(result4[0].metadata[0].name == "lifetime");
653 REQUIRE(result4[0].metadata[0].defaultValue.get<std::string>() == "condition");
654 REQUIRE(result4[0].metadata[1].name == "ccdb-path");
655 REQUIRE(result4[0].metadata[1].defaultValue.get<std::string>() == "GLO/Config/GRPECS");
656 REQUIRE(result4[0].metadata[2].name == "key3");
657 REQUIRE(result4[0].metadata[2].defaultValue.get<std::string>() == "value3");
658
659 // This is valid.
660 REQUIRE_NOTHROW(DataDescriptorQueryBuilder::parse("x:TST/A1/0xccdb"));
661
662 auto result5 = DataDescriptorQueryBuilder::parse("x:TST/A1/0?lifetime=sporadic&ccdb-path=GLO/Config/GRPECS&key3=value3");
663 REQUIRE(result5.size() == 1);
664 REQUIRE(result5[0].lifetime == Lifetime::Sporadic);
665 REQUIRE(result5[0].metadata.size() == 3);
666 REQUIRE(result5[0].metadata[0].name == "lifetime");
667 REQUIRE(result5[0].metadata[0].defaultValue.get<std::string>() == "sporadic");
668 REQUIRE(result5[0].metadata[1].name == "ccdb-path");
669 REQUIRE(result5[0].metadata[1].defaultValue.get<std::string>() == "GLO/Config/GRPECS");
670 REQUIRE(result5[0].metadata[2].name == "key3");
671 REQUIRE(result5[0].metadata[2].defaultValue.get<std::string>() == "value3");
672}
673
674TEST_CASE("DataQueryLifetime")
675{
676 auto result0 = DataDescriptorQueryBuilder::parse("x:TST/A1?lifetime=timeframe");
677 REQUIRE(result0.size() == 1);
678 REQUIRE(result0[0].lifetime == Lifetime::Timeframe);
679 auto result1 = DataDescriptorQueryBuilder::parse("x:TST/A1?lifetime=sporadic");
680 REQUIRE(result1.size() == 1);
681 REQUIRE(result1[0].lifetime == Lifetime::Sporadic);
682 auto result2 = DataDescriptorQueryBuilder::parse("x:TST/A1?lifetime=condition");
683 REQUIRE(result2.size() == 1);
684 REQUIRE(result2[0].lifetime == Lifetime::Condition);
685
686 auto result3 = DataDescriptorQueryBuilder::parse("x:TST/A1/1?lifetime=timeframe");
687 REQUIRE(result3.size() == 1);
688 REQUIRE(result3[0].lifetime == Lifetime::Timeframe);
689 auto result4 = DataDescriptorQueryBuilder::parse("x:TST/A1/2?lifetime=sporadic");
690 REQUIRE(result4.size() == 1);
691 REQUIRE(result4[0].lifetime == Lifetime::Sporadic);
692 auto result5 = DataDescriptorQueryBuilder::parse("noiseMap:TRD/NOISEMAP?lifetime=condition&ccdb-path=TRD/Calib/NoiseMapMCM");
693 REQUIRE(result5.size() == 1);
694 auto concrete = DataSpecUtils::asConcreteDataTypeMatcher(result5[0]);
695 REQUIRE(concrete.origin.as<std::string>() == "TRD");
696 REQUIRE(concrete.description.as<std::string>() == "NOISEMAP");
697 REQUIRE(result5[0].lifetime == Lifetime::Condition);
698}
699
700// Make sure that 10 and 1 subspect are matched differently
701
702TEST_CASE("MatchSubspec")
703{
704 DataHeader header0;
705 header0.dataOrigin = "EMC";
706 header0.dataDescription = "CELLSTRGR";
707 header0.subSpecification = 10;
708 VariableContext context;
709
710 DataDescriptorMatcher matcher{
711 DataDescriptorMatcher::Op::And,
712 OriginValueMatcher{"EMC"},
713 std::make_unique<DataDescriptorMatcher>(
714 DataDescriptorMatcher::Op::And,
715 DescriptionValueMatcher{"CELLSTRGR"},
716 std::make_unique<DataDescriptorMatcher>(
717 DataDescriptorMatcher::Op::And,
719 ConstantValueMatcher{true}))};
720
721 REQUIRE(matcher.match(header0, context) == false);
722}
bool match(ConcreteDataMatcher const &matcher, VariableContext &context) const
Something which can be matched against a header::DataDescription.
Something which can be matched against a header::DataOrigin.
Matcher on actual time, as reported in the DataProcessingHeader.
Something which can be matched against a header::SubSpecificationType.
ContextElement::Value const & get(size_t pos) const
GLdouble n
Definition glcorearb.h:1982
const GLdouble * v
Definition glcorearb.h:832
GLuint GLfloat GLfloat GLfloat GLfloat GLfloat GLfloat GLfloat GLfloat s1
Definition glcorearb.h:5034
GLuint const GLchar * name
Definition glcorearb.h:781
GLfloat GLfloat v1
Definition glcorearb.h:812
GLfloat GLfloat GLfloat GLfloat v3
Definition glcorearb.h:814
GLfloat GLfloat GLfloat v2
Definition glcorearb.h:813
Defining PrimaryVertex explicitly as messageable.
Definition TFIDInfo.h:20
O2 data header classes and API, v0.1.
Definition DetID.h:49
void empty(int)
static std::vector< InputSpec > parse(const char *s="")
static DataDescriptorQuery buildFromKeepConfig(std::string const &config)
static ConcreteDataTypeMatcher asConcreteDataTypeMatcher(OutputSpec const &spec)
A typesafe reference to an element of the context.
the main header struct
Definition DataHeader.h:618
DataDescription dataDescription
Definition DataHeader.h:636
SubSpecificationType subSpecification
Definition DataHeader.h:656
a move-only header stack with serialized headers This is the flat buffer where all the headers in a m...
Definition Stack.h:36
TEST_CASE("TestMatcherInvariants")