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:2287
int32_t i
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:2004
std::shared_ptr< arrow::Table > asArrowTable() const
Return a type erased arrow table backing store for / the type safe table.
Definition ASoA.h:2046
GLint GLenum GLint x
Definition glcorearb.h:403
GLint GLsizei count
Definition glcorearb.h:399
GLuint buffer
Definition glcorearb.h:655
GLdouble f
Definition glcorearb.h:310
GLboolean GLboolean GLboolean b
Definition glcorearb.h:1233
GLint y
Definition glcorearb.h:270
GLboolean * data
Definition glcorearb.h:298
GLfloat GLfloat GLfloat GLfloat v3
Definition glcorearb.h:814
GLboolean GLboolean GLboolean GLboolean a
Definition glcorearb.h:1233
Defining PrimaryVertex explicitly as messageable.
Definition TFIDInfo.h:20
TEST_CASE("test_prepareArguments")
o2::soa::InPlaceTable< 0, test2::X, test2::Y > TestTable
std::vector< int > row