1 // Licensed to the Apache Software Foundation (ASF) under one
2 // or more contributor license agreements. See the NOTICE file
3 // distributed with this work for additional information
4 // regarding copyright ownership. The ASF licenses this file
5 // to you under the Apache License, Version 2.0 (the
6 // "License"); you may not use this file except in compliance
7 // with the License. You may obtain a copy of the License at
8 //
9 // http://www.apache.org/licenses/LICENSE-2.0
10 //
11 // Unless required by applicable law or agreed to in writing,
12 // software distributed under the License is distributed on an
13 // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14 // KIND, either express or implied. See the License for the
15 // specific language governing permissions and limitations
16 // under the License.
17
18 #include <algorithm>
19 #include <cstdint>
20 #include <limits>
21 #include <memory>
22 #include <new>
23 #include <string>
24 #include <vector>
25
26 #include <gtest/gtest.h>
27
28 #include "arrow/memory_pool.h"
29 #include "arrow/stl.h"
30 #include "arrow/stl_allocator.h"
31 #include "arrow/table.h"
32 #include "arrow/testing/gtest_util.h"
33 #include "arrow/type.h"
34 #include "arrow/type_fwd.h"
35 #include "arrow/util/optional.h"
36
37 using primitive_types_tuple = std::tuple<int8_t, int16_t, int32_t, int64_t, uint8_t,
38 uint16_t, uint32_t, uint64_t, bool, std::string>;
39
40 using raw_pointer_optional_types_tuple =
41 std::tuple<int8_t*, int16_t*, int32_t*, int64_t*, uint8_t*, uint16_t*, uint32_t*,
42 uint64_t*, bool*, std::string*>;
43
44 struct CustomType {
45 int8_t i8;
46 int16_t i16;
47 int32_t i32;
48 int64_t i64;
49 uint8_t u8;
50 uint16_t u16;
51 uint32_t u32;
52 uint64_t u64;
53 bool b;
54 std::string s;
55
56 #define ARROW_CUSTOM_TYPE_TIED std::tie(i8, i16, i32, i64, u8, u16, u32, u64, b, s)
tieCustomType57 auto tie() const -> decltype(ARROW_CUSTOM_TYPE_TIED) { return ARROW_CUSTOM_TYPE_TIED; }
58 #undef ARROW_CUSTOM_TYPE_TIED
59 };
60
61 // Mock optional object returning null, "yes", "no", null, "yes", "no", ...
62 // Note: This mock optional object will advance its state every time it's casted
63 // to bool. Successive castings to bool may give inconsistent results. It
64 // doesn't mock entire optional logic. It is used only for ensuring user
65 // specialization isn't broken with templated Optionals.
66 struct CustomOptionalTypeMock {
67 static int counter;
68 mutable bool was_casted_once_ = false;
69
70 CustomOptionalTypeMock() = default;
operator boolCustomOptionalTypeMock71 explicit operator bool() const {
72 if (!was_casted_once_) {
73 was_casted_once_ = true;
74 counter++;
75 return counter % 3 != 0;
76 }
77 ADD_FAILURE() << "A CustomOptionalTypeMock should be casted to bool only once.";
78 return false;
79 }
operator *CustomOptionalTypeMock80 std::string operator*() const {
81 switch (counter % 3) {
82 case 0:
83 ADD_FAILURE() << "Optional dereferenced in null value";
84 break;
85 case 1:
86 return "yes";
87 case 2:
88 return "no";
89 }
90 return "error";
91 }
92 };
93
94 int CustomOptionalTypeMock::counter = -1;
95
96 // This is for testing appending list values with custom types
97 struct TestInt32Type {
98 int32_t value;
99 };
100
101 namespace arrow {
102
103 using optional_types_tuple =
104 std::tuple<util::optional<int8_t>, util::optional<int16_t>, util::optional<int32_t>,
105 util::optional<int64_t>, util::optional<uint8_t>, util::optional<uint16_t>,
106 util::optional<uint32_t>, util::optional<uint64_t>, util::optional<bool>,
107 util::optional<std::string>>;
108
109 template <>
110 struct CTypeTraits<CustomOptionalTypeMock> {
111 using ArrowType = ::arrow::StringType;
112
type_singletonarrow::CTypeTraits113 static std::shared_ptr<::arrow::DataType> type_singleton() { return ::arrow::utf8(); }
114 };
115
116 template <>
117 struct CTypeTraits<TestInt32Type> {
118 using ArrowType = ::arrow::Int32Type;
119
type_singletonarrow::CTypeTraits120 static std::shared_ptr<::arrow::DataType> type_singleton() { return ::arrow::int32(); }
121 };
122
123 namespace stl {
124
125 template <>
126 struct ConversionTraits<CustomOptionalTypeMock>
127 : public CTypeTraits<CustomOptionalTypeMock> {
AppendRowarrow::stl::ConversionTraits128 static Status AppendRow(typename TypeTraits<ArrowType>::BuilderType& builder,
129 const CustomOptionalTypeMock& cell) {
130 if (cell) {
131 return builder.Append("mock " + *cell);
132 } else {
133 return builder.AppendNull();
134 }
135 }
136 };
137
138 template <>
139 struct ConversionTraits<TestInt32Type> : public CTypeTraits<TestInt32Type> {
140 // AppendRow is not needed, explicitly elide an implementation
141 };
142
143 template <>
AppendListValues(Int32Builder & value_builder,const std::vector<TestInt32Type> & cell_range)144 Status AppendListValues<TestInt32Type, const std::vector<TestInt32Type>&>(
145 Int32Builder& value_builder, const std::vector<TestInt32Type>& cell_range) {
146 return value_builder.AppendValues(reinterpret_cast<const int32_t*>(cell_range.data()),
147 cell_range.size());
148 }
149
TEST(TestSchemaFromTuple,PrimitiveTypesVector)150 TEST(TestSchemaFromTuple, PrimitiveTypesVector) {
151 Schema expected_schema(
152 {field("column1", int8(), false), field("column2", int16(), false),
153 field("column3", int32(), false), field("column4", int64(), false),
154 field("column5", uint8(), false), field("column6", uint16(), false),
155 field("column7", uint32(), false), field("column8", uint64(), false),
156 field("column9", boolean(), false), field("column10", utf8(), false)});
157
158 std::shared_ptr<Schema> schema = SchemaFromTuple<primitive_types_tuple>::MakeSchema(
159 std::vector<std::string>({"column1", "column2", "column3", "column4", "column5",
160 "column6", "column7", "column8", "column9", "column10"}));
161 ASSERT_TRUE(expected_schema.Equals(*schema));
162 }
163
TEST(TestSchemaFromTuple,PrimitiveTypesTuple)164 TEST(TestSchemaFromTuple, PrimitiveTypesTuple) {
165 Schema expected_schema(
166 {field("column1", int8(), false), field("column2", int16(), false),
167 field("column3", int32(), false), field("column4", int64(), false),
168 field("column5", uint8(), false), field("column6", uint16(), false),
169 field("column7", uint32(), false), field("column8", uint64(), false),
170 field("column9", boolean(), false), field("column10", utf8(), false)});
171
172 std::shared_ptr<Schema> schema = SchemaFromTuple<primitive_types_tuple>::MakeSchema(
173 std::make_tuple("column1", "column2", "column3", "column4", "column5", "column6",
174 "column7", "column8", "column9", "column10"));
175 ASSERT_TRUE(expected_schema.Equals(*schema));
176 }
177
TEST(TestSchemaFromTuple,SimpleList)178 TEST(TestSchemaFromTuple, SimpleList) {
179 Schema expected_schema({field("column1", list(utf8()), false)});
180 std::shared_ptr<Schema> schema =
181 SchemaFromTuple<std::tuple<std::vector<std::string>>>::MakeSchema({"column1"});
182
183 ASSERT_TRUE(expected_schema.Equals(*schema));
184 }
185
TEST(TestSchemaFromTuple,NestedList)186 TEST(TestSchemaFromTuple, NestedList) {
187 Schema expected_schema({field("column1", list(list(boolean())), false)});
188 std::shared_ptr<Schema> schema =
189 SchemaFromTuple<std::tuple<std::vector<std::vector<bool>>>>::MakeSchema(
190 {"column1"});
191
192 ASSERT_TRUE(expected_schema.Equals(*schema));
193 }
194
TEST(TestTableFromTupleVector,PrimitiveTypes)195 TEST(TestTableFromTupleVector, PrimitiveTypes) {
196 std::vector<std::string> names{"column1", "column2", "column3", "column4", "column5",
197 "column6", "column7", "column8", "column9", "column10"};
198 std::vector<primitive_types_tuple> rows{
199 primitive_types_tuple(-1, -2, -3, -4, 1, 2, 3, 4, true, "Tests"),
200 primitive_types_tuple(-10, -20, -30, -40, 10, 20, 30, 40, false, "Other")};
201 std::shared_ptr<Table> table;
202 ASSERT_OK(TableFromTupleRange(default_memory_pool(), rows, names, &table));
203
204 std::shared_ptr<Schema> expected_schema =
205 schema({field("column1", int8(), false), field("column2", int16(), false),
206 field("column3", int32(), false), field("column4", int64(), false),
207 field("column5", uint8(), false), field("column6", uint16(), false),
208 field("column7", uint32(), false), field("column8", uint64(), false),
209 field("column9", boolean(), false), field("column10", utf8(), false)});
210
211 // Construct expected arrays
212 std::shared_ptr<Array> int8_array = ArrayFromJSON(int8(), "[-1, -10]");
213 std::shared_ptr<Array> int16_array = ArrayFromJSON(int16(), "[-2, -20]");
214 std::shared_ptr<Array> int32_array = ArrayFromJSON(int32(), "[-3, -30]");
215 std::shared_ptr<Array> int64_array = ArrayFromJSON(int64(), "[-4, -40]");
216 std::shared_ptr<Array> uint8_array = ArrayFromJSON(uint8(), "[1, 10]");
217 std::shared_ptr<Array> uint16_array = ArrayFromJSON(uint16(), "[2, 20]");
218 std::shared_ptr<Array> uint32_array = ArrayFromJSON(uint32(), "[3, 30]");
219 std::shared_ptr<Array> uint64_array = ArrayFromJSON(uint64(), "[4, 40]");
220 std::shared_ptr<Array> bool_array = ArrayFromJSON(boolean(), "[true, false]");
221 std::shared_ptr<Array> string_array = ArrayFromJSON(utf8(), R"(["Tests", "Other"])");
222 auto expected_table =
223 Table::Make(expected_schema,
224 {int8_array, int16_array, int32_array, int64_array, uint8_array,
225 uint16_array, uint32_array, uint64_array, bool_array, string_array});
226
227 ASSERT_TRUE(expected_table->Equals(*table));
228 }
229
TEST(TestTableFromTupleVector,ListType)230 TEST(TestTableFromTupleVector, ListType) {
231 using tuple_type = std::tuple<std::vector<int64_t>>;
232
233 auto expected_schema =
234 std::shared_ptr<Schema>(new Schema({field("column1", list(int64()), false)}));
235 std::shared_ptr<Array> expected_array =
236 ArrayFromJSON(list(int64()), "[[1, 1, 2, 34], [2, -4]]");
237 std::shared_ptr<Table> expected_table = Table::Make(expected_schema, {expected_array});
238
239 std::vector<tuple_type> rows{tuple_type(std::vector<int64_t>{1, 1, 2, 34}),
240 tuple_type(std::vector<int64_t>{2, -4})};
241 std::vector<std::string> names{"column1"};
242
243 std::shared_ptr<Table> table;
244 ASSERT_OK(TableFromTupleRange(default_memory_pool(), rows, names, &table));
245 ASSERT_TRUE(expected_table->Equals(*table));
246 }
247
TEST(TestTableFromTupleVector,ReferenceTuple)248 TEST(TestTableFromTupleVector, ReferenceTuple) {
249 std::vector<std::string> names{"column1", "column2", "column3", "column4", "column5",
250 "column6", "column7", "column8", "column9", "column10"};
251 std::vector<CustomType> rows{
252 {-1, -2, -3, -4, 1, 2, 3, 4, true, std::string("Tests")},
253 {-10, -20, -30, -40, 10, 20, 30, 40, false, std::string("Other")}};
254 std::vector<decltype(rows[0].tie())> rng_rows{
255 rows[0].tie(),
256 rows[1].tie(),
257 };
258 std::shared_ptr<Table> table;
259 ASSERT_OK(TableFromTupleRange(default_memory_pool(), rng_rows, names, &table));
260
261 std::shared_ptr<Schema> expected_schema =
262 schema({field("column1", int8(), false), field("column2", int16(), false),
263 field("column3", int32(), false), field("column4", int64(), false),
264 field("column5", uint8(), false), field("column6", uint16(), false),
265 field("column7", uint32(), false), field("column8", uint64(), false),
266 field("column9", boolean(), false), field("column10", utf8(), false)});
267
268 // Construct expected arrays
269 std::shared_ptr<Array> int8_array = ArrayFromJSON(int8(), "[-1, -10]");
270 std::shared_ptr<Array> int16_array = ArrayFromJSON(int16(), "[-2, -20]");
271 std::shared_ptr<Array> int32_array = ArrayFromJSON(int32(), "[-3, -30]");
272 std::shared_ptr<Array> int64_array = ArrayFromJSON(int64(), "[-4, -40]");
273 std::shared_ptr<Array> uint8_array = ArrayFromJSON(uint8(), "[1, 10]");
274 std::shared_ptr<Array> uint16_array = ArrayFromJSON(uint16(), "[2, 20]");
275 std::shared_ptr<Array> uint32_array = ArrayFromJSON(uint32(), "[3, 30]");
276 std::shared_ptr<Array> uint64_array = ArrayFromJSON(uint64(), "[4, 40]");
277 std::shared_ptr<Array> bool_array = ArrayFromJSON(boolean(), "[true, false]");
278 std::shared_ptr<Array> string_array = ArrayFromJSON(utf8(), R"(["Tests", "Other"])");
279 auto expected_table =
280 Table::Make(expected_schema,
281 {int8_array, int16_array, int32_array, int64_array, uint8_array,
282 uint16_array, uint32_array, uint64_array, bool_array, string_array});
283
284 ASSERT_TRUE(expected_table->Equals(*table));
285 }
286
TEST(TestTableFromTupleVector,NullableTypesWithBoostOptional)287 TEST(TestTableFromTupleVector, NullableTypesWithBoostOptional) {
288 std::vector<std::string> names{"column1", "column2", "column3", "column4", "column5",
289 "column6", "column7", "column8", "column9", "column10"};
290 using types_tuple = optional_types_tuple;
291 std::vector<types_tuple> rows{
292 types_tuple(-1, -2, -3, -4, 1, 2, 3, 4, true, std::string("Tests")),
293 types_tuple(-10, -20, -30, -40, 10, 20, 30, 40, false, std::string("Other")),
294 types_tuple(util::nullopt, util::nullopt, util::nullopt, util::nullopt,
295 util::nullopt, util::nullopt, util::nullopt, util::nullopt,
296 util::nullopt, util::nullopt),
297 };
298 std::shared_ptr<Table> table;
299 ASSERT_OK(TableFromTupleRange(default_memory_pool(), rows, names, &table));
300
301 std::shared_ptr<Schema> expected_schema =
302 schema({field("column1", int8(), true), field("column2", int16(), true),
303 field("column3", int32(), true), field("column4", int64(), true),
304 field("column5", uint8(), true), field("column6", uint16(), true),
305 field("column7", uint32(), true), field("column8", uint64(), true),
306 field("column9", boolean(), true), field("column10", utf8(), true)});
307
308 // Construct expected arrays
309 std::shared_ptr<Array> int8_array = ArrayFromJSON(int8(), "[-1, -10, null]");
310 std::shared_ptr<Array> int16_array = ArrayFromJSON(int16(), "[-2, -20, null]");
311 std::shared_ptr<Array> int32_array = ArrayFromJSON(int32(), "[-3, -30, null]");
312 std::shared_ptr<Array> int64_array = ArrayFromJSON(int64(), "[-4, -40, null]");
313 std::shared_ptr<Array> uint8_array = ArrayFromJSON(uint8(), "[1, 10, null]");
314 std::shared_ptr<Array> uint16_array = ArrayFromJSON(uint16(), "[2, 20, null]");
315 std::shared_ptr<Array> uint32_array = ArrayFromJSON(uint32(), "[3, 30, null]");
316 std::shared_ptr<Array> uint64_array = ArrayFromJSON(uint64(), "[4, 40, null]");
317 std::shared_ptr<Array> bool_array = ArrayFromJSON(boolean(), "[true, false, null]");
318 std::shared_ptr<Array> string_array =
319 ArrayFromJSON(utf8(), R"(["Tests", "Other", null])");
320 auto expected_table =
321 Table::Make(expected_schema,
322 {int8_array, int16_array, int32_array, int64_array, uint8_array,
323 uint16_array, uint32_array, uint64_array, bool_array, string_array});
324
325 ASSERT_TRUE(expected_table->Equals(*table));
326 }
327
TEST(TestTableFromTupleVector,NullableTypesWithRawPointer)328 TEST(TestTableFromTupleVector, NullableTypesWithRawPointer) {
329 std::vector<std::string> names{"column1", "column2", "column3", "column4", "column5",
330 "column6", "column7", "column8", "column9", "column10"};
331 std::vector<primitive_types_tuple> data_rows{
332 primitive_types_tuple(-1, -2, -3, -4, 1, 2, 3, 4, true, std::string("Tests")),
333 primitive_types_tuple(-10, -20, -30, -40, 10, 20, 30, 40, false,
334 std::string("Other")),
335 };
336 std::vector<raw_pointer_optional_types_tuple> pointer_rows;
337 for (auto& row : data_rows) {
338 pointer_rows.emplace_back(
339 std::addressof(std::get<0>(row)), std::addressof(std::get<1>(row)),
340 std::addressof(std::get<2>(row)), std::addressof(std::get<3>(row)),
341 std::addressof(std::get<4>(row)), std::addressof(std::get<5>(row)),
342 std::addressof(std::get<6>(row)), std::addressof(std::get<7>(row)),
343 std::addressof(std::get<8>(row)), std::addressof(std::get<9>(row)));
344 }
345 pointer_rows.emplace_back(nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
346 nullptr, nullptr, nullptr);
347 std::shared_ptr<Table> table;
348 ASSERT_OK(TableFromTupleRange(default_memory_pool(), pointer_rows, names, &table));
349
350 std::shared_ptr<Schema> expected_schema =
351 schema({field("column1", int8(), true), field("column2", int16(), true),
352 field("column3", int32(), true), field("column4", int64(), true),
353 field("column5", uint8(), true), field("column6", uint16(), true),
354 field("column7", uint32(), true), field("column8", uint64(), true),
355 field("column9", boolean(), true), field("column10", utf8(), true)});
356
357 // Construct expected arrays
358 std::shared_ptr<Array> int8_array = ArrayFromJSON(int8(), "[-1, -10, null]");
359 std::shared_ptr<Array> int16_array = ArrayFromJSON(int16(), "[-2, -20, null]");
360 std::shared_ptr<Array> int32_array = ArrayFromJSON(int32(), "[-3, -30, null]");
361 std::shared_ptr<Array> int64_array = ArrayFromJSON(int64(), "[-4, -40, null]");
362 std::shared_ptr<Array> uint8_array = ArrayFromJSON(uint8(), "[1, 10, null]");
363 std::shared_ptr<Array> uint16_array = ArrayFromJSON(uint16(), "[2, 20, null]");
364 std::shared_ptr<Array> uint32_array = ArrayFromJSON(uint32(), "[3, 30, null]");
365 std::shared_ptr<Array> uint64_array = ArrayFromJSON(uint64(), "[4, 40, null]");
366 std::shared_ptr<Array> bool_array = ArrayFromJSON(boolean(), "[true, false, null]");
367 std::shared_ptr<Array> string_array =
368 ArrayFromJSON(utf8(), R"(["Tests", "Other", null])");
369 auto expected_table =
370 Table::Make(expected_schema,
371 {int8_array, int16_array, int32_array, int64_array, uint8_array,
372 uint16_array, uint32_array, uint64_array, bool_array, string_array});
373
374 ASSERT_TRUE(expected_table->Equals(*table));
375 }
376
TEST(TestTableFromTupleVector,NullableTypesDoNotBreakUserSpecialization)377 TEST(TestTableFromTupleVector, NullableTypesDoNotBreakUserSpecialization) {
378 std::vector<std::string> names{"column1"};
379 std::vector<std::tuple<CustomOptionalTypeMock>> rows(3);
380 std::shared_ptr<Table> table;
381 ASSERT_OK(TableFromTupleRange(default_memory_pool(), rows, names, &table));
382
383 std::shared_ptr<Schema> expected_schema = schema({field("column1", utf8(), true)});
384 std::shared_ptr<Array> string_array =
385 ArrayFromJSON(utf8(), R"([null, "mock yes", "mock no"])");
386 auto expected_table = Table::Make(expected_schema, {string_array});
387
388 ASSERT_TRUE(expected_table->Equals(*table));
389 }
390
TEST(TestTableFromTupleVector,AppendingMultipleRows)391 TEST(TestTableFromTupleVector, AppendingMultipleRows) {
392 using row_type = std::tuple<std::vector<TestInt32Type>>;
393 std::vector<std::string> names{"column1"};
394 std::vector<row_type> rows = {
395 row_type{{{1}, {2}, {3}}}, //
396 row_type{{{10}, {20}, {30}}} //
397 };
398 std::shared_ptr<Table> table;
399 ASSERT_OK(TableFromTupleRange(default_memory_pool(), rows, names, &table));
400
401 std::shared_ptr<Schema> expected_schema =
402 schema({field("column1", list(int32()), false)});
403 std::shared_ptr<Array> int_array =
404 ArrayFromJSON(list(int32()), "[[1, 2, 3], [10, 20, 30]]");
405 auto expected_table = Table::Make(expected_schema, {int_array});
406
407 ASSERT_TRUE(expected_table->Equals(*table));
408 }
409
TEST(TestTupleVectorFromTable,PrimitiveTypes)410 TEST(TestTupleVectorFromTable, PrimitiveTypes) {
411 compute::ExecContext ctx;
412 compute::CastOptions cast_options;
413
414 std::vector<primitive_types_tuple> expected_rows{
415 primitive_types_tuple(-1, -2, -3, -4, 1, 2, 3, 4, true, "Tests"),
416 primitive_types_tuple(-10, -20, -30, -40, 10, 20, 30, 40, false, "Other")};
417
418 std::shared_ptr<Schema> schema = std::shared_ptr<Schema>(
419 new Schema({field("column1", int8(), false), field("column2", int16(), false),
420 field("column3", int32(), false), field("column4", int64(), false),
421 field("column5", uint8(), false), field("column6", uint16(), false),
422 field("column7", uint32(), false), field("column8", uint64(), false),
423 field("column9", boolean(), false), field("column10", utf8(), false)}));
424
425 // Construct expected arrays
426 std::shared_ptr<Array> int8_array;
427 ArrayFromVector<Int8Type, int8_t>({-1, -10}, &int8_array);
428 std::shared_ptr<Array> int16_array;
429 ArrayFromVector<Int16Type, int16_t>({-2, -20}, &int16_array);
430 std::shared_ptr<Array> int32_array;
431 ArrayFromVector<Int32Type, int32_t>({-3, -30}, &int32_array);
432 std::shared_ptr<Array> int64_array;
433 ArrayFromVector<Int64Type, int64_t>({-4, -40}, &int64_array);
434 std::shared_ptr<Array> uint8_array;
435 ArrayFromVector<UInt8Type, uint8_t>({1, 10}, &uint8_array);
436 std::shared_ptr<Array> uint16_array;
437 ArrayFromVector<UInt16Type, uint16_t>({2, 20}, &uint16_array);
438 std::shared_ptr<Array> uint32_array;
439 ArrayFromVector<UInt32Type, uint32_t>({3, 30}, &uint32_array);
440 std::shared_ptr<Array> uint64_array;
441 ArrayFromVector<UInt64Type, uint64_t>({4, 40}, &uint64_array);
442 std::shared_ptr<Array> bool_array;
443 ArrayFromVector<BooleanType, bool>({true, false}, &bool_array);
444 std::shared_ptr<Array> string_array;
445 ArrayFromVector<StringType, std::string>({"Tests", "Other"}, &string_array);
446 auto table = Table::Make(
447 schema, {int8_array, int16_array, int32_array, int64_array, uint8_array,
448 uint16_array, uint32_array, uint64_array, bool_array, string_array});
449
450 std::vector<primitive_types_tuple> rows(2);
451 ASSERT_OK(TupleRangeFromTable(*table, cast_options, &ctx, &rows));
452 ASSERT_EQ(rows, expected_rows);
453
454 // The number of rows must match
455 std::vector<primitive_types_tuple> too_few_rows(1);
456 ASSERT_RAISES(Invalid, TupleRangeFromTable(*table, cast_options, &ctx, &too_few_rows));
457
458 // The number of columns must match
459 ASSERT_OK_AND_ASSIGN(auto corrupt_table, table->RemoveColumn(0));
460 ASSERT_RAISES(Invalid, TupleRangeFromTable(*corrupt_table, cast_options, &ctx, &rows));
461 }
462
TEST(TestTupleVectorFromTable,ListType)463 TEST(TestTupleVectorFromTable, ListType) {
464 using tuple_type = std::tuple<std::vector<int64_t>>;
465
466 compute::ExecContext ctx;
467 compute::CastOptions cast_options;
468 auto expected_schema =
469 std::shared_ptr<Schema>(new Schema({field("column1", list(int64()), false)}));
470 std::shared_ptr<Array> expected_array =
471 ArrayFromJSON(list(int64()), "[[1, 1, 2, 34], [2, -4]]");
472 std::shared_ptr<Table> table = Table::Make(expected_schema, {expected_array});
473
474 std::vector<tuple_type> expected_rows{tuple_type(std::vector<int64_t>{1, 1, 2, 34}),
475 tuple_type(std::vector<int64_t>{2, -4})};
476
477 std::vector<tuple_type> rows(2);
478 ASSERT_OK(TupleRangeFromTable(*table, cast_options, &ctx, &rows));
479 ASSERT_EQ(rows, expected_rows);
480 }
481
TEST(TestTupleVectorFromTable,CastingNeeded)482 TEST(TestTupleVectorFromTable, CastingNeeded) {
483 using tuple_type = std::tuple<std::vector<int64_t>>;
484
485 compute::ExecContext ctx;
486 compute::CastOptions cast_options;
487 auto expected_schema =
488 std::shared_ptr<Schema>(new Schema({field("column1", list(int16()), false)}));
489 std::shared_ptr<Array> expected_array =
490 ArrayFromJSON(list(int16()), "[[1, 1, 2, 34], [2, -4]]");
491 std::shared_ptr<Table> table = Table::Make(expected_schema, {expected_array});
492
493 std::vector<tuple_type> expected_rows{tuple_type(std::vector<int64_t>{1, 1, 2, 34}),
494 tuple_type(std::vector<int64_t>{2, -4})};
495
496 std::vector<tuple_type> rows(2);
497 ASSERT_OK(TupleRangeFromTable(*table, cast_options, &ctx, &rows));
498 ASSERT_EQ(rows, expected_rows);
499 }
500
TEST(STLMemoryPool,Base)501 TEST(STLMemoryPool, Base) {
502 std::allocator<uint8_t> allocator;
503 STLMemoryPool<std::allocator<uint8_t>> pool(allocator);
504
505 uint8_t* data = nullptr;
506 ASSERT_OK(pool.Allocate(100, &data));
507 ASSERT_EQ(pool.max_memory(), 100);
508 ASSERT_EQ(pool.bytes_allocated(), 100);
509 ASSERT_NE(data, nullptr);
510
511 ASSERT_OK(pool.Reallocate(100, 150, &data));
512 ASSERT_EQ(pool.max_memory(), 150);
513 ASSERT_EQ(pool.bytes_allocated(), 150);
514
515 pool.Free(data, 150);
516
517 ASSERT_EQ(pool.max_memory(), 150);
518 ASSERT_EQ(pool.bytes_allocated(), 0);
519 }
520
TEST(allocator,MemoryTracking)521 TEST(allocator, MemoryTracking) {
522 auto pool = default_memory_pool();
523 allocator<uint64_t> alloc;
524 uint64_t* data = alloc.allocate(100);
525
526 ASSERT_EQ(100 * sizeof(uint64_t), pool->bytes_allocated());
527
528 alloc.deallocate(data, 100);
529 ASSERT_EQ(0, pool->bytes_allocated());
530 }
531
532 #if !(defined(ARROW_VALGRIND) || defined(ADDRESS_SANITIZER) || defined(ARROW_JEMALLOC))
533
TEST(allocator,TestOOM)534 TEST(allocator, TestOOM) {
535 allocator<uint64_t> alloc;
536 uint64_t to_alloc = std::numeric_limits<uint64_t>::max() / 2;
537 ASSERT_THROW(alloc.allocate(to_alloc), std::bad_alloc);
538 }
539
TEST(stl_allocator,MaxMemory)540 TEST(stl_allocator, MaxMemory) {
541 auto pool = MemoryPool::CreateDefault();
542
543 allocator<uint8_t> alloc(pool.get());
544 uint8_t* data = alloc.allocate(1000);
545 uint8_t* data2 = alloc.allocate(1000);
546
547 alloc.deallocate(data, 1000);
548 alloc.deallocate(data2, 1000);
549
550 ASSERT_EQ(2000, pool->max_memory());
551 }
552
553 #endif // !(defined(ARROW_VALGRIND) || defined(ADDRESS_SANITIZER)
554 // || defined(ARROW_JEMALLOC))
555
556 } // namespace stl
557
558 } // namespace arrow
559