Project
Loading...
Searching...
No Matches
unittest_DataSpecUtils.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 <catch_amalgamated.hpp>
15
16#include <string>
17
18using namespace o2;
19using namespace o2::framework;
20
21TEST_CASE("ConcreteData")
22{
24 OutputSpec spec{
25 "TEST",
26 "FOOO",
27 1,
28 Lifetime::Timeframe};
29
30 InputSpec inputSpec{
31 "binding",
32 "TEST",
33 "FOOO",
34 1,
35 Lifetime::Timeframe};
36
37 REQUIRE(DataSpecUtils::validate(inputSpec));
38
39 {
41 CHECK(std::string(concrete.origin.as<std::string>()) == "TEST");
42 CHECK(std::string(concrete.description.as<std::string>()) == "FOOO");
43 CHECK(concrete.subSpec == 1);
44 CHECK(DataSpecUtils::describe(spec) == "TEST/FOOO/1");
46
48 CHECK(std::string(dataType.origin.as<std::string>()) == "TEST");
49 CHECK(std::string(dataType.description.as<std::string>()) == "FOOO");
50
51 CHECK(DataSpecUtils::match(spec, ConcreteDataMatcher{"TEST", "FOOO", 1}));
52 CHECK(DataSpecUtils::match(spec, ConcreteDataMatcher{"TEST", "FOOO", 0}) == false);
54 CHECK(DataSpecUtils::match(spec, ConcreteDataMatcher{"TEST", "FOOO", 0}) == true);
55 CHECK(DataSpecUtils::match(inputSpec, ConcreteDataMatcher{"TEST", "FOOO", 1}));
56 CHECK(DataSpecUtils::match(inputSpec, ConcreteDataMatcher{"TEST", "FOOO", 0}) == false);
58 CHECK(DataSpecUtils::match(inputSpec, ConcreteDataMatcher{"TEST", "FOOO", 0}) == true);
59 }
60}
61
62TEST_CASE("WithWildCards")
63{
64 OutputSpec spec{
65 {"TEST", "FOOO"},
66 Lifetime::Timeframe};
67
68 CHECK_THROWS_AS(DataSpecUtils::asConcreteDataMatcher(spec), std::bad_variant_access);
69 auto dataType = DataSpecUtils::asConcreteDataTypeMatcher(spec);
70
71 CHECK(std::string(dataType.origin.as<std::string>()) == "TEST");
72 CHECK(std::string(dataType.description.as<std::string>()) == "FOOO");
73
74 CHECK(DataSpecUtils::match(spec, ConcreteDataMatcher{"TEST", "FOOO", 1}));
75 CHECK(DataSpecUtils::match(spec, ConcreteDataMatcher{"TEST", "FOOO", 0}));
76 CHECK(DataSpecUtils::describe(spec) == "TEST/FOOO");
77
78 CHECK(DataSpecUtils::getOptionalSubSpec(spec) == std::nullopt);
79}
80
81TEST_CASE("MatchingInputs")
82{
83 OutputSpec fullySpecified{
84 "TEST",
85 "FOOO",
86 1,
87 Lifetime::Timeframe};
88
89 OutputSpec partialMatching{
90 {"TEST", "FOOO"},
91 Lifetime::Timeframe};
92
93 auto matchingInput1 = DataSpecUtils::matchingInput(fullySpecified);
95
96 CHECK(std::string(concrete.origin.as<std::string>()) == "TEST");
97 CHECK(std::string(concrete.description.as<std::string>()) == "FOOO");
98 CHECK(concrete.subSpec == 1);
99
100 auto matchingInput2 = DataSpecUtils::matchingInput(partialMatching);
101 // CHECK_THROW(DataSpecUtils::asConcreteDataMatcher(matchingInput), std::bad_variant_access);
102 // We need a ConcreteDataMatcher to check if the generated input is
103 // correct, because a ConcreteDataTypeMatcher has one extra degree of
104 // freedom.
105 ConcreteDataMatcher concreteExample1{
106 "TEST",
107 "FOOO",
108 0};
109 ConcreteDataMatcher concreteExample2{
110 "TEST",
111 "FOOO",
112 1};
113 ConcreteDataMatcher concreteExample3{
114 "BAR",
115 "FOOO",
116 0};
117 ConcreteDataMatcher concreteExample4{
118 "TEST",
119 "BAR",
120 0};
121 CHECK(DataSpecUtils::match(matchingInput2, concreteExample1) == true);
122 CHECK(DataSpecUtils::match(matchingInput2, concreteExample2) == true);
123 CHECK(DataSpecUtils::match(matchingInput2, concreteExample3) == false);
124 CHECK(DataSpecUtils::match(matchingInput2, concreteExample4) == false);
125
126 CHECK_THROWS_AS(DataSpecUtils::asConcreteDataMatcher(matchingInput2), std::runtime_error);
127 CHECK(concrete.origin.as<std::string>() == "TEST");
128 CHECK(concrete.description.as<std::string>() == "FOOO");
129 CHECK(concrete.subSpec == 1);
130}
131
132TEST_CASE("MatchingOutputs")
133{
134 OutputSpec output1{
135 "TST", "A1", 0, Lifetime::Timeframe};
136
137 OutputSpec output2{
138 "TST", "B1", 0, Lifetime::Timeframe};
139
140 OutputSpec output3{
141 {"TST", "A1"}, Lifetime::Timeframe};
142
143 InputSpec input1{
144 "binding", "TST", "A1", 0, Lifetime::Timeframe};
145
146 InputSpec input2{
147 "binding", "TST", "A1", 1, Lifetime::Timeframe};
148
149 InputSpec input3{
150 "binding", "TST", "B1", 0, Lifetime::Timeframe};
151
152 InputSpec input4{
153 "binding", {"TST", "A1"}, Lifetime::Timeframe};
154
155 // matching inputs to outputs
156 CHECK(DataSpecUtils::match(input1, output1) == true);
157 CHECK(DataSpecUtils::match(input1, output2) == false);
158 CHECK(DataSpecUtils::match(input1, output3) == false); // Wildcard on output!
159 CHECK(DataSpecUtils::match(input2, output1) == false);
160 CHECK(DataSpecUtils::match(input2, output2) == false);
161 CHECK(DataSpecUtils::match(input2, output3) == false); // Wildcard on output!
162 CHECK(DataSpecUtils::match(input3, output1) == false);
163 CHECK(DataSpecUtils::match(input3, output2) == true);
164 CHECK(DataSpecUtils::match(input3, output3) == false); // Wildcard on output!
165 CHECK(DataSpecUtils::match(input4, output1) == true); // Wildcard in input!
166 CHECK(DataSpecUtils::match(input4, output2) == false);
167 CHECK(DataSpecUtils::match(input4, output3) == true); // Wildcard on both!
168
169 // matching outputs to output definitions
170 // ConcreteDataMatcher on both sides
171 CHECK(DataSpecUtils::match(output1, OutputSpec{"TST", "A1", 0}) == true);
172 CHECK(DataSpecUtils::match(output1, OutputSpec{"TST", "A1", 1}) == false);
173
174 // ConcreteDataMatcher left, ConcreteDataTypeMatcher right (subspec ignored)
175 CHECK(DataSpecUtils::match(output1, OutputSpec{"TST", "A1"}) == true);
176
177 // ConcreteDataTypeMatcher left (subspec ignored), ConcreteDataMatcher right
178 CHECK(DataSpecUtils::match(output3, OutputSpec{"TST", "A1", 0}) == true);
179 CHECK(DataSpecUtils::match(output3, OutputSpec{"TST", "A1", 1}) == true);
180
181 // ConcreteDataTypeMatcher on both sides
182 CHECK(DataSpecUtils::match(output3, OutputSpec{"TST", "A1"}) == true);
183}
184
185TEST_CASE("PartialMatching")
186{
187 OutputSpec fullySpecifiedOutput{
188 "TEST",
189 "FOOO",
190 1,
191 Lifetime::Timeframe};
192
193 InputSpec fullySpecifiedInput{
194 "binding",
195 "TSET",
196 "FOOO",
197 1,
198 Lifetime::Timeframe};
199
200 CHECK(DataSpecUtils::partialMatch(fullySpecifiedOutput, header::DataOrigin("TEST")));
201 CHECK(DataSpecUtils::partialMatch(fullySpecifiedInput, header::DataOrigin("TSET")));
202
203 CHECK(DataSpecUtils::partialMatch(fullySpecifiedOutput, header::DataOrigin("FOO")) == false);
204 CHECK(DataSpecUtils::partialMatch(fullySpecifiedInput, header::DataOrigin("FOO")) == false);
205
206 CHECK(DataSpecUtils::partialMatch(fullySpecifiedOutput, header::DataDescription("TEST")) == false);
207 CHECK(DataSpecUtils::partialMatch(fullySpecifiedInput, header::DataDescription("TSET")) == false);
208
209 CHECK(DataSpecUtils::partialMatch(fullySpecifiedOutput, header::DataDescription("FOOO")) == true);
210 CHECK(DataSpecUtils::partialMatch(fullySpecifiedInput, header::DataDescription("FOOO")) == true);
211}
212
213TEST_CASE("GetOptionalSubSpecWithMatcher")
214{
215 InputSpec fullInputSpec{
216 "binding",
217 "TSET", "FOOO", 1,
218 Lifetime::Timeframe};
219
220 InputSpec wildcardInputSpec{
221 "binding",
222 {"TSET", "FOOO"},
223 Lifetime::Timeframe};
224
225 auto fromQueryInputSpec = DataDescriptorQueryBuilder::parse("x:TST/A1/77;y:STS/A2;z:FOO/A3");
226
227 CHECK(*DataSpecUtils::getOptionalSubSpec(fullInputSpec) == 1);
228 CHECK(DataSpecUtils::getOptionalSubSpec(wildcardInputSpec) == std::nullopt);
229 REQUIRE(fromQueryInputSpec.size() == 3);
230 CHECK(DataSpecUtils::getOptionalSubSpec(fromQueryInputSpec[0]) != std::nullopt);
231 CHECK(DataSpecUtils::getOptionalSubSpec(fromQueryInputSpec[0]) == 77);
232 CHECK(DataSpecUtils::getOptionalSubSpec(fromQueryInputSpec[1]) == std::nullopt);
233 CHECK(DataSpecUtils::getOptionalSubSpec(fromQueryInputSpec[2]) == std::nullopt);
234 DataSpecUtils::updateMatchingSubspec(fromQueryInputSpec[2], 10);
235 CHECK(DataSpecUtils::getOptionalSubSpec(fromQueryInputSpec[2]) == 10);
236
237 auto dataType1 = DataSpecUtils::asConcreteDataTypeMatcher(fullInputSpec);
238 CHECK(std::string(dataType1.origin.as<std::string>()) == "TSET");
239 CHECK(std::string(dataType1.description.as<std::string>()) == "FOOO");
240
241 auto dataType2 = DataSpecUtils::asConcreteDataTypeMatcher(wildcardInputSpec);
242 CHECK(std::string(dataType2.origin.as<std::string>()) == "TSET");
243 CHECK(std::string(dataType2.description.as<std::string>()) == "FOOO");
244}
245
246TEST_CASE("TestMatcherFromDescription")
247{
248 auto fromQueryInputSpec = DataSpecUtils::dataDescriptorMatcherFrom(header::DataDescription{"TSET"});
249 InputSpec ddSpec{
250 "binding",
251 std::move(fromQueryInputSpec)};
252
253 CHECK(DataSpecUtils::asConcreteDataDescription(ddSpec).as<std::string>() == "TSET");
254}
255
256TEST_CASE("TestMatcherFromConcrete")
257{
258 auto fromQueryInputSpec = DataSpecUtils::dataDescriptorMatcherFrom(ConcreteDataMatcher{"TSET", "FOO", 1});
259 InputSpec ddSpec{
260 "binding",
261 std::move(fromQueryInputSpec)};
262
263 auto concrete = DataSpecUtils::asConcreteDataMatcher(ddSpec);
264
265 CHECK(concrete.origin.as<std::string>() == "TSET");
266 CHECK(concrete.description.as<std::string>() == "FOO");
267 CHECK(concrete.subSpec == 1);
268}
269
270TEST_CASE("FindOutputSpec")
271{
272 std::vector<OutputSpec> specs = {
273 {"TST", "DATA1", 0},
274 {"TST", "DATA2", 0}};
275
276 auto spec = DataSpecUtils::find(specs, {"TST"}, {"DATA1"}, 0);
277 CHECK(spec == specs[0]);
278 CHECK(DataSpecUtils::find(specs, {"TST"}, {"DATA3"}, 0) == std::nullopt);
279}
280
281TEST_CASE("FindInputSpec")
282{
283 std::vector<InputSpec> specs = {
284 {"x", "TST", "DATA1", 0},
285 {"y", "TST", "DATA2", 0}};
286
287 auto spec = DataSpecUtils::find(specs, {"TST"}, {"DATA1"}, 0);
288 CHECK(spec == specs[0]);
289 CHECK(DataSpecUtils::find(specs, {"TST"}, {"DATA3"}, 0) == std::nullopt);
290}
291
292TEST_CASE("GettingConcreteMembers")
293{
294 InputSpec fullySpecifiedInput{
295 "binding",
296 "TSET",
297 "FOOO",
298 1,
299 Lifetime::Timeframe};
300
301 InputSpec wildcardInputSpec{
302 "binding",
303 {"TSET", "FOOO"},
304 Lifetime::Timeframe};
305
306 auto justOriginInputSpec = DataDescriptorQueryBuilder::parse("x:TST");
307
308 CHECK(DataSpecUtils::asConcreteOrigin(fullySpecifiedInput).as<std::string>() == "TSET");
309 CHECK(DataSpecUtils::asConcreteDataDescription(fullySpecifiedInput).as<std::string>() == "FOOO");
310
311 CHECK(DataSpecUtils::asConcreteOrigin(wildcardInputSpec).as<std::string>() == "TSET");
312 CHECK(DataSpecUtils::asConcreteDataDescription(wildcardInputSpec).as<std::string>() == "FOOO");
313
314 REQUIRE(justOriginInputSpec.size() == 1);
315 CHECK(DataSpecUtils::asConcreteOrigin(justOriginInputSpec.at(0)).as<std::string>() == "TST");
316 CHECK_THROWS_AS(DataSpecUtils::asConcreteDataDescription(justOriginInputSpec.at(0)).as<std::string>(), RuntimeErrorRef);
317}
318
319TEST_CASE("Includes")
320{
321 InputSpec concreteInput1{"binding", "TSET", "FOOO", 1, Lifetime::Timeframe};
322 InputSpec concreteInput2{"binding", "TSET", "BAAAR", 1, Lifetime::Timeframe};
323 InputSpec wildcardInput1{"binding", {"TSET", "FOOO"}, Lifetime::Timeframe};
324 InputSpec wildcardInput2{"binding", {"TSET", "BAAAR"}, Lifetime::Timeframe};
325
326 // wildcard and concrete
327 CHECK(DataSpecUtils::includes(wildcardInput1, concreteInput1));
328 CHECK(!DataSpecUtils::includes(wildcardInput1, concreteInput2));
329 CHECK(!DataSpecUtils::includes(concreteInput1, wildcardInput1));
330 CHECK(!DataSpecUtils::includes(concreteInput2, wildcardInput1));
331
332 // concrete and concrete
333 CHECK(DataSpecUtils::includes(concreteInput1, concreteInput1));
334 CHECK(!DataSpecUtils::includes(concreteInput1, concreteInput2));
335 CHECK(!DataSpecUtils::includes(concreteInput2, concreteInput1));
336
337 // wildcard and wildcard
338 CHECK(DataSpecUtils::includes(wildcardInput1, wildcardInput1));
339 CHECK(!DataSpecUtils::includes(wildcardInput1, wildcardInput2));
340 CHECK(!DataSpecUtils::includes(wildcardInput2, wildcardInput1));
341
342 auto inputsFromQuery = DataDescriptorQueryBuilder::parse("b0:TST/FOO/0;b1:TST/FOO/1");
343 CHECK(!DataSpecUtils::includes(inputsFromQuery[0], inputsFromQuery[1]));
344 CHECK(!DataSpecUtils::includes(inputsFromQuery[1], inputsFromQuery[0]));
345}
346
347TEST_CASE("optionalConcreteDataMatcherFrom")
348{
349 using namespace data_matcher;
350
351 // the standard structure of fully qualified data descriptor
352 DataDescriptorMatcher matcher1{
353 DataDescriptorMatcher::Op::And,
354 OriginValueMatcher{"TPC"},
355 std::make_unique<DataDescriptorMatcher>(
356 DataDescriptorMatcher::Op::And,
357 DescriptionValueMatcher{"CLUSTERS"},
358 std::make_unique<DataDescriptorMatcher>(
359 DataDescriptorMatcher::Op::And,
361 std::make_unique<DataDescriptorMatcher>(
362 DataDescriptorMatcher::Op::Just,
363 StartTimeValueMatcher(ContextRef{ContextPos::STARTTIME_POS}))))};
364
365 // also fully qualified, but interchanged components
366 DataDescriptorMatcher matcher2{
367 DataDescriptorMatcher::Op::And,
368 DescriptionValueMatcher{"CLUSTERS"},
369 std::make_unique<DataDescriptorMatcher>(
370 DataDescriptorMatcher::Op::And,
371 OriginValueMatcher{"TPC"},
372 std::make_unique<DataDescriptorMatcher>(
373 DataDescriptorMatcher::Op::And,
375 std::make_unique<DataDescriptorMatcher>(
376 DataDescriptorMatcher::Op::Just,
377 StartTimeValueMatcher(ContextRef{ContextPos::STARTTIME_POS}))))};
378
379 // matcher with no unique subSpec
380 DataDescriptorMatcher matcher3{
381 DataDescriptorMatcher::Op::And,
382 OriginValueMatcher{"TPC"},
383 std::make_unique<DataDescriptorMatcher>(
384 DataDescriptorMatcher::Op::And,
385 DescriptionValueMatcher{"CLUSTERS"},
386 std::make_unique<DataDescriptorMatcher>(
387 DataDescriptorMatcher::Op::And,
388 std::make_unique<DataDescriptorMatcher>(
389 DataDescriptorMatcher::Op::Not,
391 std::make_unique<DataDescriptorMatcher>(
392 DataDescriptorMatcher::Op::Just,
393 StartTimeValueMatcher(ContextRef{ContextPos::STARTTIME_POS}))))};
394
395 // another matcher with no unique subSpec
396 DataDescriptorMatcher matcher4{
397 DataDescriptorMatcher::Op::And,
398 OriginValueMatcher{"TPC"},
399 std::make_unique<DataDescriptorMatcher>(
400 DataDescriptorMatcher::Op::And,
401 DescriptionValueMatcher{"CLUSTERS"},
402 std::make_unique<DataDescriptorMatcher>(
403 DataDescriptorMatcher::Op::And,
404 std::make_unique<DataDescriptorMatcher>(
405 DataDescriptorMatcher::Op::Or,
408 std::make_unique<DataDescriptorMatcher>(
409 DataDescriptorMatcher::Op::Just,
410 StartTimeValueMatcher(ContextRef{ContextPos::STARTTIME_POS}))))};
411
412 // unique origin and description only
413 DataDescriptorMatcher matcher5{
414 DataDescriptorMatcher::Op::And,
415 OriginValueMatcher{"TPC"},
416 std::make_unique<DataDescriptorMatcher>(
417 DataDescriptorMatcher::Op::And,
418 DescriptionValueMatcher{"CLUSTERS"},
419 std::make_unique<DataDescriptorMatcher>(
420 DataDescriptorMatcher::Op::And,
422 std::make_unique<DataDescriptorMatcher>(
423 DataDescriptorMatcher::Op::Just,
424 StartTimeValueMatcher(ContextRef{ContextPos::STARTTIME_POS}))))};
425
426 // no subspec in the matcher
427 DataDescriptorMatcher matcher6{
428 DataDescriptorMatcher::Op::And,
429 OriginValueMatcher{"TPC"},
430 std::make_unique<DataDescriptorMatcher>(
431 DataDescriptorMatcher::Op::And,
432 DescriptionValueMatcher{"CLUSTERS"},
433 std::make_unique<DataDescriptorMatcher>(
434 DataDescriptorMatcher::Op::And,
436 std::make_unique<DataDescriptorMatcher>(
437 DataDescriptorMatcher::Op::Just,
438 StartTimeValueMatcher(ContextRef{ContextPos::STARTTIME_POS}))))};
439
442
443 auto check = [](DataDescriptorMatcher const& matcher, bool expectConcreteDataMatcher, ConcreteDataMatcher compare = {"", "", 0}) {
444 auto concrete = DataSpecUtils::optionalConcreteDataMatcherFrom(matcher);
445 CHECK(concrete.has_value() == expectConcreteDataMatcher);
446 if (concrete.has_value()) {
447 CHECK(*concrete == compare);
448 }
449 };
450
451 check(matcher1, true, ConcreteDataMatcher{"TPC", "CLUSTERS", 1});
452 check(matcher2, true, ConcreteDataMatcher{"TPC", "CLUSTERS", 1});
453 check(matcher3, false);
454 check(matcher4, false);
455 check(matcher5, false);
456 check(matcher6, false);
457 check(matcher7, true, ConcreteDataMatcher{"ITS", "RAWDATA", 0});
458 check(matcher8, false);
459
460 REQUIRE(DataSpecUtils::asOptionalConcreteDataMatcher(ConcreteDataMatcher{"ITS", "RAWDATA", 0}) == ConcreteDataMatcher{"ITS", "RAWDATA", 0});
461 REQUIRE(DataSpecUtils::asOptionalConcreteDataMatcher(ConcreteDataTypeMatcher{"ITS", "RAWDATA"}) == std::nullopt);
462}
463
464// Testcase for DataSpecUtils::updateOutputList
465TEST_CASE("UpdateOutputList")
466{
467 // Empty vector of output specs should simply add the new spec
468 std::vector<OutputSpec> outputSpecs;
469 DataSpecUtils::updateOutputList(outputSpecs, {"TST", "DATA1", 0});
470 CHECK(outputSpecs.size() == 1);
471
472 // Adding the same spec again should not change the size
473 DataSpecUtils::updateOutputList(outputSpecs, {"TST", "DATA1", 0});
474 CHECK(outputSpecs.size() == 1);
475
476 // Adding a different spec should increase the size
477 DataSpecUtils::updateOutputList(outputSpecs, {"TST", "DATA2", 0});
478 CHECK(outputSpecs.size() == 2);
479
480 // Adding again the same spec again should not change the size
481 DataSpecUtils::updateOutputList(outputSpecs, {"TST", "DATA1", 0});
482 CHECK(outputSpecs.size() == 2);
483 // Check with something real..
484 ConcreteDataMatcher dstf{"FLP", "DISTSUBTIMEFRAME", 0xccdb};
485 DataSpecUtils::updateOutputList(outputSpecs, OutputSpec{{"ccdb-diststf"}, dstf, Lifetime::Timeframe});
486 CHECK(outputSpecs.size() == 3);
487 DataSpecUtils::updateOutputList(outputSpecs, OutputSpec{{"ccdb-diststf"}, dstf, Lifetime::Timeframe});
488 CHECK(outputSpecs.size() == 3);
489 // Label does not matter
490 DataSpecUtils::updateOutputList(outputSpecs, OutputSpec{{"ccdb2-diststf"}, dstf, Lifetime::Timeframe});
491 CHECK(outputSpecs.size() == 3);
492}
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.
#define CHECK
Defining PrimaryVertex explicitly as messageable.
Definition TFIDInfo.h:20
void check(const std::vector< std::string > &arguments, const std::vector< ConfigParamSpec > &workflowOptions, const std::vector< DeviceSpec > &deviceSpecs, CheckMatrix &matrix)
TEST_CASE("test_prepareArguments")
void clean_all_runtime_errors()
a couple of static helper functions to create timestamp values for CCDB queries or override obsolete ...
header::DataHeader::SubSpecificationType subSpec
static std::vector< InputSpec > parse(const char *s="")
static std::optional< ConcreteDataMatcher > asOptionalConcreteDataMatcher(OutputSpec const &spec)
static bool partialMatch(InputSpec const &spec, o2::header::DataOrigin const &origin)
static std::string describe(InputSpec const &spec)
static void updateOutputList(std::vector< OutputSpec > &list, OutputSpec &&input)
Updates list of OutputSpecs by merging metadata (or adding output).
static ConcreteDataTypeMatcher asConcreteDataTypeMatcher(OutputSpec const &spec)
static bool validate(InputSpec const &input)
static std::optional< typename ContainerT::value_type > find(ContainerT const &container, const o2::header::DataOrigin &origin, const o2::header::DataDescription &description, const o2::header::DataHeader::SubSpecificationType &subSpec)
static ConcreteDataMatcher asConcreteDataMatcher(InputSpec const &input)
static std::optional< header::DataHeader::SubSpecificationType > getOptionalSubSpec(OutputSpec const &spec)
Get the subspec, if available.
static InputSpec matchingInput(OutputSpec const &spec)
static data_matcher::DataDescriptorMatcher dataDescriptorMatcherFrom(ConcreteDataMatcher const &concrete)
Build a DataDescriptMatcher which does not care about the subSpec.
static std::optional< framework::ConcreteDataMatcher > optionalConcreteDataMatcherFrom(data_matcher::DataDescriptorMatcher const &matcher)
static void updateMatchingSubspec(InputSpec &in, header::DataHeader::SubSpecificationType subSpec)
static bool includes(const InputSpec &left, const InputSpec &right)
Checks if left includes right (or is equal to)
static header::DataOrigin asConcreteOrigin(InputSpec const &spec)
static header::DataDescription asConcreteDataDescription(InputSpec const &spec)
static bool match(InputSpec const &spec, ConcreteDataMatcher const &target)
A typesafe reference to an element of the context.
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 compare(std::string_view s1, std::string_view s2)