Project
Loading...
Searching...
No Matches
test_TableBuilder.cxx
Go to the documentation of this file.
1// Copyright 2019-2025 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>
13
15#include "Framework/Output.h"
16#include <arrow/table.h>
17#include <arrow/ipc/writer.h>
18#include <arrow/io/memory.h>
19#include <arrow/ipc/writer.h>
20#include <arrow/ipc/reader.h>
21
22#include <string_view>
23
24using namespace o2::framework;
25
26// We use a different namespace to avoid clashes with the
27// test_ASoA.cxx test.
28namespace test2
29{
30DECLARE_SOA_COLUMN_FULL(X, x, uint64_t, "x");
31DECLARE_SOA_COLUMN_FULL(Y, y, uint64_t, "y");
32DECLARE_SOA_COLUMN_FULL(Blob, blob, std::span<std::byte>, "blob");
33DECLARE_SOA_COLUMN_FULL(Pos, pos, int[4], "pos");
34} // namespace test2
35
39
40TEST_CASE("TestTableBuilder")
41{
42 using namespace o2::framework;
43 TableBuilder builder;
44 auto rowWriter = builder.persist<uint64_t, uint64_t>({"x", "y"});
45 rowWriter(0, 0, 0);
46 rowWriter(0, 10, 1);
47 rowWriter(0, 20, 2);
48 rowWriter(0, 30, 3);
49 rowWriter(0, 40, 4);
50 rowWriter(0, 50, 5);
51 rowWriter(0, 60, 6);
52 rowWriter(0, 70, 7);
53 auto table = builder.finalize();
54 REQUIRE(table->num_columns() == 2);
55 REQUIRE(table->num_rows() == 8);
56 REQUIRE(table->schema()->field(0)->name() == "x");
57 REQUIRE(table->schema()->field(1)->name() == "y");
58 REQUIRE(table->schema()->field(0)->type()->id() == arrow::uint64()->id());
59 REQUIRE(table->schema()->field(1)->type()->id() == arrow::uint64()->id());
60
61 auto readBack = TestTable{table};
62
63 auto readBackTable = readBack.asArrowTable();
64 REQUIRE(readBackTable->num_columns() == 2);
65 REQUIRE(readBackTable->num_rows() == 8);
66 REQUIRE(readBackTable->schema()->field(0)->name() == "x");
67 REQUIRE(readBackTable->schema()->field(1)->name() == "y");
68 REQUIRE(readBackTable->schema()->field(0)->type()->id() == arrow::uint64()->id());
69 REQUIRE(readBackTable->schema()->field(1)->type()->id() == arrow::uint64()->id());
70 size_t i = 0;
71 SECTION("Check")
72 {
73 for (auto const& row : readBack) {
74 REQUIRE(row.x() == i * 10);
75 REQUIRE(row.y() == i);
76 ++i;
77 }
78 }
79}
80
81TEST_CASE("TestTableBuilderArray")
82{
83 using namespace o2::framework;
84 TableBuilder builder;
85 const int numElem = 4;
86 auto rowWriter = builder.persist<int[numElem]>({"pos"});
87 int a[numElem] = {1, 10, 300, 350};
88 int b[numElem] = {0, 20, 30, 40};
89 rowWriter(0, a);
90 rowWriter(0, b);
91 using v3 = std::array<int, numElem>;
92 rowWriter(0, v3{0, 11, 123, 256}.data());
93 auto table = builder.finalize();
94
95 REQUIRE(table->num_columns() == 1);
96 REQUIRE(table->num_rows() == 3);
97 REQUIRE(table->schema()->field(0)->name() == "pos");
98 REQUIRE(table->schema()->field(0)->type()->id() == arrow::fixed_size_list(arrow::int32(), numElem)->id());
99
100 auto chunkToUse = table->column(0)->chunk(0);
101 chunkToUse = std::static_pointer_cast<arrow::FixedSizeListArray>(chunkToUse)->values();
102 auto data = chunkToUse->data();
103
104 REQUIRE(data->GetValues<int>(1)[0] == 1);
105 REQUIRE(data->GetValues<int>(1)[1] == 10);
106 REQUIRE(data->GetValues<int>(1)[2] == 300);
107 REQUIRE(data->GetValues<int>(1)[3] == 350);
108 REQUIRE(data->GetValues<int>(1)[4] == 0);
109 REQUIRE(data->GetValues<int>(1)[5] == 20);
110 REQUIRE(data->GetValues<int>(1)[6] == 30);
111 REQUIRE(data->GetValues<int>(1)[7] == 40);
112
113 auto readBack = ArrayTable{table};
114 auto row = readBack.begin();
115
116 REQUIRE(row.pos()[0] == 1);
117 REQUIRE(row.pos()[1] == 10);
118 REQUIRE(row.pos()[2] == 300);
119 REQUIRE(row.pos()[3] == 350);
120
121 row++;
122 REQUIRE(row.pos()[0] == 0);
123 REQUIRE(row.pos()[1] == 20);
124 REQUIRE(row.pos()[2] == 30);
125 REQUIRE(row.pos()[3] == 40);
126
127 row++;
128 REQUIRE(row.pos()[0] == 0);
129 REQUIRE(row.pos()[1] == 11);
130 REQUIRE(row.pos()[2] == 123);
131 REQUIRE(row.pos()[3] == 256);
132}
133
134TEST_CASE("TestTableBuilderStruct")
135{
136 using namespace o2::framework;
137 TableBuilder builder;
138 struct Foo {
139 uint64_t x;
140 uint64_t y;
141 };
142 auto rowWriter = builder.persist<Foo>({"x", "y"});
143 rowWriter(0, Foo{0, 0});
144 rowWriter(0, Foo{10, 1});
145 rowWriter(0, Foo{20, 2});
146 rowWriter(0, Foo{30, 3});
147 rowWriter(0, Foo{40, 4});
148 rowWriter(0, Foo{50, 5});
149 rowWriter(0, Foo{60, 6});
150 rowWriter(0, Foo{70, 7});
151 auto table = builder.finalize();
152 REQUIRE(table->num_columns() == 2);
153 REQUIRE(table->num_rows() == 8);
154 REQUIRE(table->schema()->field(0)->name() == "x");
155 REQUIRE(table->schema()->field(1)->name() == "y");
156 REQUIRE(table->schema()->field(0)->type()->id() == arrow::uint64()->id());
157 REQUIRE(table->schema()->field(1)->type()->id() == arrow::uint64()->id());
158
159 auto readBack = TestTable{table};
160
161 size_t i = 0;
162 for (auto& row : readBack) {
163 REQUIRE(row.x() == i * 10);
164 REQUIRE(row.y() == i);
165 ++i;
166 }
167}
168
169TEST_CASE("TestTableBuilderMore")
170{
171 using namespace o2::framework;
172 TableBuilder builder;
173 auto rowWriter = builder.persist<int, float, std::string, bool>({"x", "y", "s", "b"});
175 rowWriter(0, 0, 0., "foo", true);
176 rowWriter(0, 1, 1., "bar", false);
177 rowWriter(0, 2, 2., "fbr", false);
178 rowWriter(0, 3, 3., "bar", false);
179 rowWriter(0, 4, 4., "abr", true);
180 rowWriter(0, 5, 5., "aaa", false);
181 rowWriter(0, 6, 6., "bbb", true);
182 rowWriter(0, 7, 7., "ccc", false);
183 auto table = builder.finalize();
184 REQUIRE(table->num_columns() == 4);
185 REQUIRE(table->num_rows() == 8);
186 REQUIRE(table->schema()->field(0)->name() == "x");
187 REQUIRE(table->schema()->field(1)->name() == "y");
188 REQUIRE(table->schema()->field(2)->name() == "s");
189 REQUIRE(table->schema()->field(3)->name() == "b");
190 REQUIRE(table->schema()->field(0)->type()->id() == arrow::int32()->id());
191 REQUIRE(table->schema()->field(1)->type()->id() == arrow::float32()->id());
192 REQUIRE(table->schema()->field(2)->type()->id() == arrow::utf8()->id());
193 REQUIRE(table->schema()->field(3)->type()->id() == arrow::boolean()->id());
194}
195
196TEST_CASE("TestSpan")
197{
198 TableBuilder builder;
199 std::vector<std::byte> buffer{10, std::byte{'c'}};
200 std::vector<std::byte> buffer1{10, std::byte{'a'}};
201
202 auto rowWriter = builder.persist<std::span<std::byte>>({"blob"});
203 rowWriter(0, std::span(buffer));
204 rowWriter(0, std::span(buffer.data() + 1, 9));
205 rowWriter(0, std::span(buffer1.data(), 3));
206 rowWriter(0, std::span(buffer1.data(), 1));
207 auto table = builder.finalize();
208
209 REQUIRE(table->num_columns() == 1);
210 REQUIRE(table->num_rows() == 4);
211 REQUIRE(table->schema()->field(0)->name() == "blob");
212 REQUIRE(table->schema()->field(0)->type()->id() == arrow::binary_view()->id());
213
214 auto readBack = SpanTable{table};
215 auto row = readBack.begin();
216 REQUIRE(row.blob() == "cccccccccc");
217 ++row;
218 REQUIRE(row.blob() == "ccccccccc");
219 ++row;
220 REQUIRE(row.blob() == "aaa");
221 ++row;
222 REQUIRE(row.blob() == "a");
223}
224
225TEST_CASE("TestSoAIntegration")
226{
227 TableBuilder builder;
228 auto rowWriter = builder.cursor<TestTable>();
229 rowWriter(0, 0, 0);
230 rowWriter(0, 10, 1);
231 rowWriter(0, 20, 2);
232 rowWriter(0, 30, 3);
233 rowWriter(0, 40, 4);
234 rowWriter(0, 50, 5);
235 auto table = builder.finalize();
236 auto readBack = TestTable{table};
237
238 size_t i = 0;
239 for (auto& row : readBack) {
240 REQUIRE(row.x() == i * 10);
241 REQUIRE(row.y() == i);
242 ++i;
243 }
244}
245
246TEST_CASE("TestDataAllocatorReturnType")
247{
248 const Output output{"TST", "DUMMY", 0};
249}
250
251TEST_CASE("TestPodInjestion")
252{
253 struct A {
254 uint64_t x;
255 uint64_t y;
256 };
257 TableBuilder builder;
258 auto rowWriter = builder.cursor<TestTable, A>();
259 rowWriter(0, A{0, 0});
260 rowWriter(0, A{10, 1});
261 rowWriter(0, A{20, 2});
262 rowWriter(0, A{30, 3});
263 rowWriter(0, A{40, 4});
264 rowWriter(0, A{50, 5});
265 auto table = builder.finalize();
266 auto readBack = TestTable{table};
267
268 size_t i = 0;
269 for (auto& row : readBack) {
270 REQUIRE(row.x() == i * 10);
271 REQUIRE(row.y() == i);
272 ++i;
273 }
274}
275
276TEST_CASE("TestColumnCount")
277{
278 struct Foo {
279 int x;
280 int y;
281 };
282 struct Bar {
283 int x;
284 int y;
285 std::string s;
286 };
287 struct FooBar {
288 int x;
289 int y;
290 float f;
291 };
292 REQUIRE(TableBuilder::countColumns<Foo>() == 2);
293 REQUIRE(TableBuilder::countColumns<Bar>() == 3);
294 REQUIRE(TableBuilder::countColumns<FooBar>() == 3);
295 int count = TableBuilder::countColumns<float, int>();
296 REQUIRE(count == 2);
297 int count2 = TableBuilder::countColumns<float, int, char[3]>();
298 REQUIRE(count2 == 3);
299}
#define DECLARE_SOA_COLUMN_FULL(_Name_, _Getter_, _Type_, _Label_)
Definition ASoA.h:2334
int32_t i
Timeframe settings Average distance in cm of events merged into Randomize distance around average distance of merged events Simulate correct bunch interactions instead of placing only the average number of events A value[n] sets TFlen for[n] collisions in Number of bunches per trainsort Number of bunch trains Instantaneous interaction rate Do not simulate border Total number of collisions to be placed in the interior of all time Do not select random but walk over array of events in stride steps h Event generator settings h configStandalone Use CPU for GPU Force usage of the specified GPU device no CPU fallback Continue processing after an error s
Timeframe settings Average distance in cm of events merged into Randomize distance around average distance of merged events Simulate correct bunch interactions instead of placing only the average number of events A value[n] sets TFlen for[n] collisions in Number of bunches per trainsort Number of bunch trains Instantaneous interaction rate Do not simulate border Total number of collisions to be placed in the interior of all time Do not select random but walk over array of events in stride steps h Event generator settings h configStandalone Use CPU for GPU Force usage of the specified GPU device no CPU fallback Continue processing after an error First event to Number of events to Number of iterations to Number of iterations to Number of initial iterations excluded from const char Directory with events to Events directory is and not inside events Show standalone event Run event generator maximum time bin of continuous for triggered for automatic continuous for automatic continuous triggered uint64_t
configStandalone Reconstruction rec_tpc float
void output(const std::map< std::string, ChannelStat > &channels)
Definition rawdump.cxx:197
uint16_t pos
Definition RawData.h:3
Definition A.h:16
auto reserve(o2::framework::pack< ARGS... > &&, int s)
auto persist(std::array< char const *, sizeof...(ARGS)+1 > const &columnNames)
std::shared_ptr< arrow::Table > finalize()
unfiltered_iterator begin()
Definition ASoA.h:2029
std::shared_ptr< arrow::Table > asArrowTable() const
Return a type erased arrow table backing store for / the type safe table.
Definition ASoA.h:2071
GLint GLenum GLint x
Definition glcorearb.h:403
GLint GLsizei count
Definition glcorearb.h:399
GLdouble f
Definition glcorearb.h:310
GLboolean GLboolean GLboolean b
Definition glcorearb.h:1233
GLint y
Definition glcorearb.h:270
GLfloat GLfloat GLfloat GLfloat v3
Definition glcorearb.h:814
GLboolean GLboolean GLboolean GLboolean a
Definition glcorearb.h:1233
Defining ITS Vertex explicitly as messageable.
Definition Cartesian.h:288
TEST_CASE("test_prepareArguments")
o2::soa::InPlaceTable< 0, test2::X, test2::Y > TestTable
std::vector< int > row