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 <memory>
19 #include <string>
20 #include <vector>
21
22 #include <gtest/gtest.h>
23
24 #include "arrow/compute/kernel.h"
25 #include "arrow/status.h"
26 #include "arrow/testing/gtest_util.h"
27 #include "arrow/type.h"
28 #include "arrow/util/key_value_metadata.h"
29
30 namespace arrow {
31 namespace compute {
32
33 // ----------------------------------------------------------------------
34 // TypeMatcher
35
TEST(TypeMatcher,SameTypeId)36 TEST(TypeMatcher, SameTypeId) {
37 std::shared_ptr<TypeMatcher> matcher = match::SameTypeId(Type::DECIMAL);
38 ASSERT_TRUE(matcher->Matches(*decimal(12, 2)));
39 ASSERT_FALSE(matcher->Matches(*int8()));
40
41 ASSERT_EQ("Type::DECIMAL128", matcher->ToString());
42
43 ASSERT_TRUE(matcher->Equals(*matcher));
44 ASSERT_TRUE(matcher->Equals(*match::SameTypeId(Type::DECIMAL)));
45 ASSERT_FALSE(matcher->Equals(*match::SameTypeId(Type::TIMESTAMP)));
46 }
47
TEST(TypeMatcher,TimestampTypeUnit)48 TEST(TypeMatcher, TimestampTypeUnit) {
49 auto matcher = match::TimestampTypeUnit(TimeUnit::MILLI);
50 auto matcher2 = match::Time32TypeUnit(TimeUnit::MILLI);
51
52 ASSERT_TRUE(matcher->Matches(*timestamp(TimeUnit::MILLI)));
53 ASSERT_TRUE(matcher->Matches(*timestamp(TimeUnit::MILLI, "utc")));
54 ASSERT_FALSE(matcher->Matches(*timestamp(TimeUnit::SECOND)));
55 ASSERT_FALSE(matcher->Matches(*time32(TimeUnit::MILLI)));
56 ASSERT_TRUE(matcher2->Matches(*time32(TimeUnit::MILLI)));
57
58 // Check ToString representation
59 ASSERT_EQ("timestamp(s)", match::TimestampTypeUnit(TimeUnit::SECOND)->ToString());
60 ASSERT_EQ("timestamp(ms)", match::TimestampTypeUnit(TimeUnit::MILLI)->ToString());
61 ASSERT_EQ("timestamp(us)", match::TimestampTypeUnit(TimeUnit::MICRO)->ToString());
62 ASSERT_EQ("timestamp(ns)", match::TimestampTypeUnit(TimeUnit::NANO)->ToString());
63
64 // Equals implementation
65 ASSERT_TRUE(matcher->Equals(*matcher));
66 ASSERT_TRUE(matcher->Equals(*match::TimestampTypeUnit(TimeUnit::MILLI)));
67 ASSERT_FALSE(matcher->Equals(*match::TimestampTypeUnit(TimeUnit::MICRO)));
68 ASSERT_FALSE(matcher->Equals(*match::Time32TypeUnit(TimeUnit::MILLI)));
69 }
70
71 // ----------------------------------------------------------------------
72 // InputType
73
TEST(InputType,AnyTypeConstructor)74 TEST(InputType, AnyTypeConstructor) {
75 // Check the ANY_TYPE ctors
76 InputType ty;
77 ASSERT_EQ(InputType::ANY_TYPE, ty.kind());
78 ASSERT_EQ(ValueDescr::ANY, ty.shape());
79
80 ty = InputType(ValueDescr::SCALAR);
81 ASSERT_EQ(ValueDescr::SCALAR, ty.shape());
82
83 ty = InputType(ValueDescr::ARRAY);
84 ASSERT_EQ(ValueDescr::ARRAY, ty.shape());
85 }
86
TEST(InputType,Constructors)87 TEST(InputType, Constructors) {
88 // Exact type constructor
89 InputType ty1(int8());
90 ASSERT_EQ(InputType::EXACT_TYPE, ty1.kind());
91 ASSERT_EQ(ValueDescr::ANY, ty1.shape());
92 AssertTypeEqual(*int8(), *ty1.type());
93
94 InputType ty1_implicit = int8();
95 ASSERT_TRUE(ty1.Equals(ty1_implicit));
96
97 InputType ty1_array(int8(), ValueDescr::ARRAY);
98 ASSERT_EQ(ValueDescr::ARRAY, ty1_array.shape());
99
100 InputType ty1_scalar(int8(), ValueDescr::SCALAR);
101 ASSERT_EQ(ValueDescr::SCALAR, ty1_scalar.shape());
102
103 // Same type id constructor
104 InputType ty2(Type::DECIMAL);
105 ASSERT_EQ(InputType::USE_TYPE_MATCHER, ty2.kind());
106 ASSERT_EQ("any[Type::DECIMAL128]", ty2.ToString());
107 ASSERT_TRUE(ty2.type_matcher().Matches(*decimal(12, 2)));
108 ASSERT_FALSE(ty2.type_matcher().Matches(*int16()));
109
110 InputType ty2_array(Type::DECIMAL, ValueDescr::ARRAY);
111 ASSERT_EQ(ValueDescr::ARRAY, ty2_array.shape());
112
113 InputType ty2_scalar(Type::DECIMAL, ValueDescr::SCALAR);
114 ASSERT_EQ(ValueDescr::SCALAR, ty2_scalar.shape());
115
116 // Implicit construction in a vector
117 std::vector<InputType> types = {int8(), InputType(Type::DECIMAL)};
118 ASSERT_TRUE(types[0].Equals(ty1));
119 ASSERT_TRUE(types[1].Equals(ty2));
120
121 // Copy constructor
122 InputType ty3 = ty1;
123 InputType ty4 = ty2;
124 ASSERT_TRUE(ty3.Equals(ty1));
125 ASSERT_TRUE(ty4.Equals(ty2));
126
127 // Move constructor
128 InputType ty5 = std::move(ty3);
129 InputType ty6 = std::move(ty4);
130 ASSERT_TRUE(ty5.Equals(ty1));
131 ASSERT_TRUE(ty6.Equals(ty2));
132
133 // ToString
134 ASSERT_EQ("any[int8]", ty1.ToString());
135 ASSERT_EQ("array[int8]", ty1_array.ToString());
136 ASSERT_EQ("scalar[int8]", ty1_scalar.ToString());
137
138 ASSERT_EQ("any[Type::DECIMAL128]", ty2.ToString());
139 ASSERT_EQ("array[Type::DECIMAL128]", ty2_array.ToString());
140 ASSERT_EQ("scalar[Type::DECIMAL128]", ty2_scalar.ToString());
141
142 InputType ty7(match::TimestampTypeUnit(TimeUnit::MICRO));
143 ASSERT_EQ("any[timestamp(us)]", ty7.ToString());
144
145 InputType ty8;
146 InputType ty9(ValueDescr::ANY);
147 InputType ty10(ValueDescr::ARRAY);
148 InputType ty11(ValueDescr::SCALAR);
149 ASSERT_EQ("any[any]", ty8.ToString());
150 ASSERT_EQ("any[any]", ty9.ToString());
151 ASSERT_EQ("array[any]", ty10.ToString());
152 ASSERT_EQ("scalar[any]", ty11.ToString());
153 }
154
TEST(InputType,Equals)155 TEST(InputType, Equals) {
156 InputType t1 = int8();
157 InputType t2 = int8();
158 InputType t3(int8(), ValueDescr::ARRAY);
159 InputType t3_i32(int32(), ValueDescr::ARRAY);
160 InputType t3_scalar(int8(), ValueDescr::SCALAR);
161 InputType t4(int8(), ValueDescr::ARRAY);
162 InputType t4_i32(int32(), ValueDescr::ARRAY);
163
164 InputType t5(Type::DECIMAL);
165 InputType t6(Type::DECIMAL);
166 InputType t7(Type::DECIMAL, ValueDescr::SCALAR);
167 InputType t7_i32(Type::INT32, ValueDescr::SCALAR);
168 InputType t8(Type::DECIMAL, ValueDescr::SCALAR);
169 InputType t8_i32(Type::INT32, ValueDescr::SCALAR);
170
171 ASSERT_TRUE(t1.Equals(t2));
172 ASSERT_EQ(t1, t2);
173
174 // ANY vs SCALAR
175 ASSERT_NE(t1, t3);
176
177 ASSERT_EQ(t3, t4);
178
179 // both ARRAY, but different type
180 ASSERT_NE(t3, t3_i32);
181
182 // ARRAY vs SCALAR
183 ASSERT_NE(t3, t3_scalar);
184
185 ASSERT_EQ(t3_i32, t4_i32);
186
187 ASSERT_FALSE(t1.Equals(t5));
188 ASSERT_NE(t1, t5);
189
190 ASSERT_EQ(t5, t5);
191 ASSERT_EQ(t5, t6);
192 ASSERT_NE(t5, t7);
193 ASSERT_EQ(t7, t8);
194 ASSERT_EQ(t7, t8);
195 ASSERT_NE(t7, t7_i32);
196 ASSERT_EQ(t7_i32, t8_i32);
197
198 // NOTE: For the time being, we treat int32() and Type::INT32 as being
199 // different. This could obviously be fixed later to make these equivalent
200 ASSERT_NE(InputType(int8()), InputType(Type::INT32));
201
202 // Check that field metadata excluded from equality checks
203 InputType t9 = list(
204 field("item", utf8(), /*nullable=*/true, key_value_metadata({"foo"}, {"bar"})));
205 InputType t10 = list(field("item", utf8()));
206 ASSERT_TRUE(t9.Equals(t10));
207 }
208
TEST(InputType,Hash)209 TEST(InputType, Hash) {
210 InputType t0;
211 InputType t0_scalar(ValueDescr::SCALAR);
212 InputType t0_array(ValueDescr::ARRAY);
213
214 InputType t1 = int8();
215 InputType t2(Type::DECIMAL);
216
217 // These checks try to determine first of all whether Hash always returns the
218 // same value, and whether the elements of the type are all incorporated into
219 // the Hash
220 ASSERT_EQ(t0.Hash(), t0.Hash());
221 ASSERT_NE(t0.Hash(), t0_scalar.Hash());
222 ASSERT_NE(t0.Hash(), t0_array.Hash());
223 ASSERT_NE(t0_scalar.Hash(), t0_array.Hash());
224
225 ASSERT_EQ(t1.Hash(), t1.Hash());
226 ASSERT_EQ(t2.Hash(), t2.Hash());
227
228 ASSERT_NE(t0.Hash(), t1.Hash());
229 ASSERT_NE(t0.Hash(), t2.Hash());
230 ASSERT_NE(t1.Hash(), t2.Hash());
231 }
232
TEST(InputType,Matches)233 TEST(InputType, Matches) {
234 InputType ty1 = int8();
235
236 ASSERT_TRUE(ty1.Matches(ValueDescr::Scalar(int8())));
237 ASSERT_TRUE(ty1.Matches(ValueDescr::Array(int8())));
238 ASSERT_TRUE(ty1.Matches(ValueDescr::Any(int8())));
239 ASSERT_FALSE(ty1.Matches(ValueDescr::Any(int16())));
240
241 InputType ty2(Type::DECIMAL);
242 ASSERT_TRUE(ty2.Matches(ValueDescr::Scalar(decimal(12, 2))));
243 ASSERT_TRUE(ty2.Matches(ValueDescr::Array(decimal(12, 2))));
244 ASSERT_FALSE(ty2.Matches(ValueDescr::Any(float64())));
245
246 InputType ty3(int64(), ValueDescr::SCALAR);
247 ASSERT_FALSE(ty3.Matches(ValueDescr::Array(int64())));
248 ASSERT_TRUE(ty3.Matches(ValueDescr::Scalar(int64())));
249 ASSERT_FALSE(ty3.Matches(ValueDescr::Scalar(int32())));
250 ASSERT_FALSE(ty3.Matches(ValueDescr::Any(int64())));
251 }
252
253 // ----------------------------------------------------------------------
254 // OutputType
255
TEST(OutputType,Constructors)256 TEST(OutputType, Constructors) {
257 OutputType ty1 = int8();
258 ASSERT_EQ(OutputType::FIXED, ty1.kind());
259 AssertTypeEqual(*int8(), *ty1.type());
260
261 auto DummyResolver = [](KernelContext*,
262 const std::vector<ValueDescr>& args) -> Result<ValueDescr> {
263 return ValueDescr(int32(), GetBroadcastShape(args));
264 };
265 OutputType ty2(DummyResolver);
266 ASSERT_EQ(OutputType::COMPUTED, ty2.kind());
267
268 ASSERT_OK_AND_ASSIGN(ValueDescr out_descr2, ty2.Resolve(nullptr, {}));
269 ASSERT_EQ(ValueDescr::Scalar(int32()), out_descr2);
270
271 // Copy constructor
272 OutputType ty3 = ty1;
273 ASSERT_EQ(OutputType::FIXED, ty3.kind());
274 AssertTypeEqual(*ty1.type(), *ty3.type());
275
276 OutputType ty4 = ty2;
277 ASSERT_EQ(OutputType::COMPUTED, ty4.kind());
278 ASSERT_OK_AND_ASSIGN(ValueDescr out_descr4, ty4.Resolve(nullptr, {}));
279 ASSERT_EQ(ValueDescr::Scalar(int32()), out_descr4);
280
281 // Move constructor
282 OutputType ty5 = std::move(ty1);
283 ASSERT_EQ(OutputType::FIXED, ty5.kind());
284 AssertTypeEqual(*int8(), *ty5.type());
285
286 OutputType ty6 = std::move(ty4);
287 ASSERT_EQ(OutputType::COMPUTED, ty6.kind());
288 ASSERT_OK_AND_ASSIGN(ValueDescr out_descr6, ty6.Resolve(nullptr, {}));
289 ASSERT_EQ(ValueDescr::Scalar(int32()), out_descr6);
290
291 // ToString
292
293 // ty1 was copied to ty3
294 ASSERT_EQ("int8", ty3.ToString());
295 ASSERT_EQ("computed", ty2.ToString());
296 }
297
TEST(OutputType,Resolve)298 TEST(OutputType, Resolve) {
299 // Check shape promotion rules for FIXED kind
300 OutputType ty1(int32());
301
302 ASSERT_OK_AND_ASSIGN(ValueDescr descr, ty1.Resolve(nullptr, {}));
303 ASSERT_EQ(ValueDescr::Scalar(int32()), descr);
304
305 ASSERT_OK_AND_ASSIGN(descr,
306 ty1.Resolve(nullptr, {ValueDescr(int8(), ValueDescr::SCALAR)}));
307 ASSERT_EQ(ValueDescr::Scalar(int32()), descr);
308
309 ASSERT_OK_AND_ASSIGN(descr,
310 ty1.Resolve(nullptr, {ValueDescr(int8(), ValueDescr::SCALAR),
311 ValueDescr(int8(), ValueDescr::ARRAY)}));
312 ASSERT_EQ(ValueDescr::Array(int32()), descr);
313
314 OutputType ty2([](KernelContext*, const std::vector<ValueDescr>& args) {
315 return ValueDescr(args[0].type, GetBroadcastShape(args));
316 });
317
318 ASSERT_OK_AND_ASSIGN(descr, ty2.Resolve(nullptr, {ValueDescr::Array(utf8())}));
319 ASSERT_EQ(ValueDescr::Array(utf8()), descr);
320
321 // Type resolver that returns an error
322 OutputType ty3(
323 [](KernelContext* ctx, const std::vector<ValueDescr>& args) -> Result<ValueDescr> {
324 // NB: checking the value types versus the function arity should be
325 // validated elsewhere, so this is just for illustration purposes
326 if (args.size() == 0) {
327 return Status::Invalid("Need at least one argument");
328 }
329 return ValueDescr(args[0]);
330 });
331 ASSERT_RAISES(Invalid, ty3.Resolve(nullptr, {}));
332
333 // Type resolver that returns ValueDescr::ANY and needs type promotion
334 OutputType ty4(
335 [](KernelContext* ctx, const std::vector<ValueDescr>& args) -> Result<ValueDescr> {
336 return int32();
337 });
338
339 ASSERT_OK_AND_ASSIGN(descr, ty4.Resolve(nullptr, {ValueDescr::Array(int8())}));
340 ASSERT_EQ(ValueDescr::Array(int32()), descr);
341 ASSERT_OK_AND_ASSIGN(descr, ty4.Resolve(nullptr, {ValueDescr::Scalar(int8())}));
342 ASSERT_EQ(ValueDescr::Scalar(int32()), descr);
343 }
344
TEST(OutputType,ResolveDescr)345 TEST(OutputType, ResolveDescr) {
346 ValueDescr d1 = ValueDescr::Scalar(int32());
347 ValueDescr d2 = ValueDescr::Array(int32());
348
349 OutputType ty1(d1);
350 OutputType ty2(d2);
351
352 ASSERT_EQ(ValueDescr::SCALAR, ty1.shape());
353 ASSERT_EQ(ValueDescr::ARRAY, ty2.shape());
354
355 {
356 ASSERT_OK_AND_ASSIGN(ValueDescr descr, ty1.Resolve(nullptr, {}));
357 ASSERT_EQ(d1, descr);
358 }
359
360 {
361 ASSERT_OK_AND_ASSIGN(ValueDescr descr, ty2.Resolve(nullptr, {}));
362 ASSERT_EQ(d2, descr);
363 }
364 }
365
366 // ----------------------------------------------------------------------
367 // KernelSignature
368
TEST(KernelSignature,Basics)369 TEST(KernelSignature, Basics) {
370 // (any[int8], scalar[decimal]) -> utf8
371 std::vector<InputType> in_types({int8(), InputType(Type::DECIMAL, ValueDescr::SCALAR)});
372 OutputType out_type(utf8());
373
374 KernelSignature sig(in_types, out_type);
375 ASSERT_EQ(2, sig.in_types().size());
376 ASSERT_TRUE(sig.in_types()[0].type()->Equals(*int8()));
377 ASSERT_TRUE(sig.in_types()[0].Matches(ValueDescr::Scalar(int8())));
378 ASSERT_TRUE(sig.in_types()[0].Matches(ValueDescr::Array(int8())));
379
380 ASSERT_TRUE(sig.in_types()[1].Matches(ValueDescr::Scalar(decimal(12, 2))));
381 ASSERT_FALSE(sig.in_types()[1].Matches(ValueDescr::Array(decimal(12, 2))));
382 }
383
TEST(KernelSignature,Equals)384 TEST(KernelSignature, Equals) {
385 KernelSignature sig1({}, utf8());
386 KernelSignature sig1_copy({}, utf8());
387 KernelSignature sig2({int8()}, utf8());
388
389 // Output type doesn't matter (for now)
390 KernelSignature sig3({int8()}, int32());
391
392 KernelSignature sig4({int8(), int16()}, utf8());
393 KernelSignature sig4_copy({int8(), int16()}, utf8());
394 KernelSignature sig5({int8(), int16(), int32()}, utf8());
395
396 // Differ in shape
397 KernelSignature sig6({ValueDescr::Scalar(int8())}, utf8());
398 KernelSignature sig7({ValueDescr::Array(int8())}, utf8());
399
400 ASSERT_EQ(sig1, sig1);
401
402 ASSERT_EQ(sig2, sig3);
403 ASSERT_NE(sig3, sig4);
404
405 // Different sig objects, but same sig
406 ASSERT_EQ(sig1, sig1_copy);
407 ASSERT_EQ(sig4, sig4_copy);
408
409 // Match first 2 args, but not third
410 ASSERT_NE(sig4, sig5);
411
412 ASSERT_NE(sig6, sig7);
413 }
414
TEST(KernelSignature,VarArgsEquals)415 TEST(KernelSignature, VarArgsEquals) {
416 KernelSignature sig1({int8()}, utf8(), /*is_varargs=*/true);
417 KernelSignature sig2({int8()}, utf8(), /*is_varargs=*/true);
418 KernelSignature sig3({int8()}, utf8());
419
420 ASSERT_EQ(sig1, sig2);
421 ASSERT_NE(sig2, sig3);
422 }
423
TEST(KernelSignature,Hash)424 TEST(KernelSignature, Hash) {
425 // Some basic tests to ensure that the hashes are deterministic and that all
426 // input arguments are incorporated
427 KernelSignature sig1({}, utf8());
428 KernelSignature sig2({int8()}, utf8());
429 KernelSignature sig3({int8(), int32()}, utf8());
430
431 ASSERT_EQ(sig1.Hash(), sig1.Hash());
432 ASSERT_EQ(sig2.Hash(), sig2.Hash());
433 ASSERT_NE(sig1.Hash(), sig2.Hash());
434 ASSERT_NE(sig2.Hash(), sig3.Hash());
435 }
436
TEST(KernelSignature,MatchesInputs)437 TEST(KernelSignature, MatchesInputs) {
438 // () -> boolean
439 KernelSignature sig1({}, boolean());
440
441 ASSERT_TRUE(sig1.MatchesInputs({}));
442 ASSERT_FALSE(sig1.MatchesInputs({int8()}));
443
444 // (any[int8], any[decimal]) -> boolean
445 KernelSignature sig2({int8(), InputType(Type::DECIMAL)}, boolean());
446
447 ASSERT_FALSE(sig2.MatchesInputs({}));
448 ASSERT_FALSE(sig2.MatchesInputs({int8()}));
449 ASSERT_TRUE(sig2.MatchesInputs({int8(), decimal(12, 2)}));
450 ASSERT_TRUE(sig2.MatchesInputs(
451 {ValueDescr::Scalar(int8()), ValueDescr::Scalar(decimal(12, 2))}));
452 ASSERT_TRUE(
453 sig2.MatchesInputs({ValueDescr::Array(int8()), ValueDescr::Array(decimal(12, 2))}));
454
455 // (scalar[int8], array[int32]) -> boolean
456 KernelSignature sig3({ValueDescr::Scalar(int8()), ValueDescr::Array(int32())},
457 boolean());
458
459 ASSERT_FALSE(sig3.MatchesInputs({}));
460
461 // Unqualified, these are ANY type and do not match because the kernel
462 // requires a scalar and an array
463 ASSERT_FALSE(sig3.MatchesInputs({int8(), int32()}));
464 ASSERT_TRUE(
465 sig3.MatchesInputs({ValueDescr::Scalar(int8()), ValueDescr::Array(int32())}));
466 ASSERT_FALSE(
467 sig3.MatchesInputs({ValueDescr::Array(int8()), ValueDescr::Array(int32())}));
468 }
469
TEST(KernelSignature,VarArgsMatchesInputs)470 TEST(KernelSignature, VarArgsMatchesInputs) {
471 {
472 KernelSignature sig({int8()}, utf8(), /*is_varargs=*/true);
473
474 std::vector<ValueDescr> args = {int8()};
475 ASSERT_TRUE(sig.MatchesInputs(args));
476 args.push_back(ValueDescr::Scalar(int8()));
477 args.push_back(ValueDescr::Array(int8()));
478 ASSERT_TRUE(sig.MatchesInputs(args));
479 args.push_back(int32());
480 ASSERT_FALSE(sig.MatchesInputs(args));
481 }
482 {
483 KernelSignature sig({int8(), utf8()}, utf8(), /*is_varargs=*/true);
484
485 std::vector<ValueDescr> args = {int8()};
486 ASSERT_TRUE(sig.MatchesInputs(args));
487 args.push_back(ValueDescr::Scalar(utf8()));
488 args.push_back(ValueDescr::Array(utf8()));
489 ASSERT_TRUE(sig.MatchesInputs(args));
490 args.push_back(int32());
491 ASSERT_FALSE(sig.MatchesInputs(args));
492 }
493 }
494
TEST(KernelSignature,ToString)495 TEST(KernelSignature, ToString) {
496 std::vector<InputType> in_types = {InputType(int8(), ValueDescr::SCALAR),
497 InputType(Type::DECIMAL, ValueDescr::ARRAY),
498 InputType(utf8())};
499 KernelSignature sig(in_types, utf8());
500 ASSERT_EQ("(scalar[int8], array[Type::DECIMAL128], any[string]) -> string",
501 sig.ToString());
502
503 OutputType out_type([](KernelContext*, const std::vector<ValueDescr>& args) {
504 return Status::Invalid("NYI");
505 });
506 KernelSignature sig2({int8(), InputType(Type::DECIMAL)}, out_type);
507 ASSERT_EQ("(any[int8], any[Type::DECIMAL128]) -> computed", sig2.ToString());
508 }
509
TEST(KernelSignature,VarArgsToString)510 TEST(KernelSignature, VarArgsToString) {
511 KernelSignature sig({int8()}, utf8(), /*is_varargs=*/true);
512 ASSERT_EQ("varargs[any[int8]] -> string", sig.ToString());
513 }
514
515 } // namespace compute
516 } // namespace arrow
517