Project
Loading...
Searching...
No Matches
test_InputRecord.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#include <catch_amalgamated.hpp>
14#include "Framework/InputSpan.h"
16#include "Headers/DataHeader.h"
17#include "Headers/Stack.h"
18
19using namespace o2::framework;
22
23bool any_exception(RuntimeErrorRef const&) { return true; }
24
25TEST_CASE("TestInputRecord")
26{
27 // Create the routes we want for the InputRecord
28 InputSpec spec1{"x", "TPC", "CLUSTERS", 0, Lifetime::Timeframe};
29 InputSpec spec2{"y", "ITS", "CLUSTERS", 0, Lifetime::Timeframe};
30 InputSpec spec3{"z", "TST", "EMPTY", 0, Lifetime::Timeframe};
31
32 size_t i = 0;
33 auto createRoute = [&i](const char* source, InputSpec& spec) {
34 return InputRoute{
35 spec,
36 i++,
37 source,
38 0,
39 std::nullopt};
40 };
41
43 std::vector<InputRoute> schema = {
44 createRoute("x_source", spec1),
45 createRoute("y_source", spec2),
46 createRoute("z_source", spec3)};
47 // First of all we test if an empty registry behaves as expected, raising a
48 // bunch of exceptions.
49 InputSpan span{
50 [](size_t) { return DataRef{nullptr, nullptr, nullptr}; },
51 0};
52 ServiceRegistry registry;
53 InputRecord emptyRecord(schema, span, registry);
54
55 REQUIRE_THROWS_AS(emptyRecord.get("x"), RuntimeErrorRef);
56 REQUIRE_THROWS_AS(emptyRecord.get("y"), RuntimeErrorRef);
57 REQUIRE_THROWS_AS(emptyRecord.get("z"), RuntimeErrorRef);
58 REQUIRE_THROWS_AS((void)emptyRecord.getByPos(0), RuntimeErrorRef);
59 REQUIRE_THROWS_AS((void)emptyRecord.getByPos(1), RuntimeErrorRef);
60 REQUIRE_THROWS_AS((void)emptyRecord.getByPos(2), RuntimeErrorRef);
61 // Then we actually check with a real set of inputs.
62
63 std::vector<void*> inputs;
64
65 auto createMessage = [&inputs](DataHeader& dh, int value) {
66 DataProcessingHeader dph{0, 1};
67 Stack stack{dh, dph};
68 void* header = malloc(stack.size());
69 void* payload = malloc(sizeof(int));
70 memcpy(header, stack.data(), stack.size());
71 memcpy(payload, &value, sizeof(int));
72 inputs.emplace_back(header);
73 inputs.emplace_back(payload);
74 };
75
76 auto createEmpty = [&inputs]() {
77 inputs.emplace_back(nullptr);
78 inputs.emplace_back(nullptr);
79 };
80
81 DataHeader dh1;
82 dh1.dataDescription = "CLUSTERS";
83 dh1.dataOrigin = "TPC";
84 dh1.subSpecification = 0;
86 DataHeader dh2;
87 dh2.dataDescription = "CLUSTERS";
88 dh2.dataOrigin = "ITS";
89 dh2.subSpecification = 0;
91 createMessage(dh1, 1);
92 createMessage(dh2, 2);
93 createEmpty();
94 InputSpan span2{[&inputs](size_t i) { return DataRef{nullptr, static_cast<char const*>(inputs[2 * i]), static_cast<char const*>(inputs[2 * i + 1])}; }, inputs.size() / 2};
95 InputRecord record{schema, span2, registry};
96
97 // Checking we can get the whole ref by name
98 REQUIRE_NOTHROW(record.get("x"));
99 REQUIRE_NOTHROW(record.get("y"));
100 REQUIRE_NOTHROW(record.get("z"));
101 auto ref00 = record.get("x");
102 auto ref10 = record.get("y");
103 REQUIRE_THROWS_AS(record.get("err"), RuntimeErrorRef);
104
105 // Or we can get it positionally
106 REQUIRE_NOTHROW(record.get("x"));
107 auto ref01 = record.getByPos(0);
108 auto ref11 = record.getByPos(1);
109 REQUIRE_THROWS_AS((void)record.getByPos(10), RuntimeErrorRef);
110
111 // This should be exactly the same pointers
112 REQUIRE(ref00.header == ref01.header);
113 REQUIRE(ref00.payload == ref01.payload);
114 REQUIRE(ref10.header == ref11.header);
115 REQUIRE(ref10.payload == ref11.payload);
116
117 REQUIRE(record.isValid("x") == true);
118 REQUIRE(record.isValid("y") == true);
119 REQUIRE(record.isValid("z") == false);
120 REQUIRE(record.size() == 3);
121 REQUIRE(record.countValidInputs() == 2);
122
123 REQUIRE(record.isValid(0) == true);
124 REQUIRE(record.isValid(1) == true);
125 REQUIRE(record.isValid(2) == false);
126 // This by default is a shortcut for
127 //
128 // *static_cast<int const *>(record.get("x").payload);
129 //
130 REQUIRE(record.get<int>("x") == 1);
131 REQUIRE(record.get<int>("y") == 2);
132 // A few more time just to make sure we are not stateful..
133 REQUIRE(record.get<int>("x") == 1);
134 REQUIRE(record.get<int>("x") == 1);
135
136 // test the iterator
137 int position = 0;
138 for (auto input = record.begin(), end = record.end(); input != end; input++, position++) {
139 if (position == 0) {
140 REQUIRE(input.matches("TPC") == true);
141 REQUIRE(input.matches("TPC", "CLUSTERS") == true);
142 REQUIRE(input.matches("ITS", "CLUSTERS") == false);
143 }
144 if (position == 1) {
145 REQUIRE(input.matches("ITS") == true);
146 REQUIRE(input.matches("ITS", "CLUSTERS") == true);
147 REQUIRE(input.matches("TPC", "CLUSTERS") == false);
148 }
149 // check if invalid slots are filtered out by the iterator
150 REQUIRE(position != 2);
151 }
152
153 // the 2-level iterator to access inputs and their parts
154 // all inputs have 1 part, we check the first input
155 REQUIRE(record.begin().size() == 1);
156 // the end-instance of the inputs has no parts
157 REQUIRE(record.end().size() == 0);
158 // thus there is no element and begin == end
159 REQUIRE(record.end().begin() == record.end().end());
160}
161
162// TODO:
163// - test all `get` implementations
164// - create a list of supported types and check that the API compiles
165// - test return value optimization for vectors, unique_ptr
166// - check objects which work directly on the payload for zero-copy
int32_t i
uint32_t stack
Definition RawData.h:1
The input API of the Data Processing Layer This class holds the inputs which are valid for processing...
decltype(auto) get(R binding, int part=0) const
static DataRef getByPos(std::vector< InputRoute > const &routes, InputSpan const &span, int pos, int part=0)
GLuint GLuint end
Definition glcorearb.h:469
GLsizei GLsizei GLchar * source
Definition glcorearb.h:798
GLsizei const GLfloat * value
Definition glcorearb.h:819
Defining PrimaryVertex explicitly as messageable.
Definition TFIDInfo.h:20
TEST_CASE("test_prepareArguments")
constexpr o2::header::SerializationMethod gSerializationMethodNone
Definition DataHeader.h:327
the main header struct
Definition DataHeader.h:618
SerializationMethod payloadSerializationMethod
Definition DataHeader.h:651
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
bool any_exception(RuntimeErrorRef const &)