1 /*
2 * Copyright (c) Meta Platforms, Inc. and affiliates.
3 * All rights reserved.
4 *
5 * This source code is licensed under the BSD-style license found in the
6 * LICENSE file in the root directory of this source tree.
7 */
8
9 #include <executorch/kernels/test/FunctionHeaderWrapper.h> // Declares the operator
10 #include <executorch/kernels/test/TestUtil.h>
11 #include <executorch/kernels/test/supported_features.h>
12 #include <executorch/runtime/core/exec_aten/exec_aten.h>
13 #include <executorch/runtime/core/exec_aten/testing_util/tensor_factory.h>
14 #include <executorch/runtime/core/exec_aten/testing_util/tensor_util.h>
15 #include <executorch/runtime/core/exec_aten/util/scalar_type_util.h>
16
17 #include <gtest/gtest.h>
18
19 using namespace ::testing;
20 using exec_aten::ArrayRef;
21 using exec_aten::ScalarType;
22 using exec_aten::Tensor;
23 using exec_aten::TensorList;
24 using torch::executor::testing::TensorFactory;
25 using torch::executor::testing::TensorListFactory;
26
27 class OpSplitCopyTensorOutTest : public OperatorTest {
28 protected:
op_split_copy_tensor_out(const Tensor & self,int64_t split_size,int64_t dim,TensorList out)29 void op_split_copy_tensor_out(
30 const Tensor& self,
31 int64_t split_size,
32 int64_t dim,
33 TensorList out) {
34 return torch::executor::aten::split_copy_outf(
35 context_, self, split_size, dim, out);
36 }
37
38 template <ScalarType DTYPE>
make3x3x3(TensorFactory<DTYPE> & tf)39 Tensor make3x3x3(TensorFactory<DTYPE>& tf) {
40 // clang-format off
41 return tf.make(
42 /*sizes=*/{3, 3, 3},
43 /*data=*/
44 {
45 0, 1, 2, // tensor([[[ 0, 1, 2],
46 3, 4, 5, // [ 3, 4, 5],
47 6, 7, 8, // [ 6, 7, 8]],
48
49 9, 10, 11, // [[ 9, 10, 11],
50 12, 13, 14, // [12, 13, 14],
51 15, 16, 17, // [15, 16, 17]],
52
53 18, 19, 20, // [[18, 19, 20],
54 21, 22, 23, // [21, 22, 23],
55 24, 25, 26, // [24, 25, 26]]])
56 });
57 // clang-format on
58 }
59
60 // A simple successful test case that will work for any real dtype and bool.
61 template <ScalarType DTYPE>
test_dtype()62 void test_dtype() {
63 TensorFactory<DTYPE> tf;
64 TensorListFactory<DTYPE> tlf;
65
66 Tensor input = tf.make(/*sizes=*/{2, 2}, /*data=*/{1, 0, 0, 1});
67
68 std::vector<Tensor> expected_out = {
69 tf.make(/*sizes=*/{1, 2}, /*data=*/{1, 0}),
70 tf.make(/*sizes=*/{1, 2}, /*data=*/{0, 1}),
71 };
72 TensorList out = tlf.zeros_like(expected_out);
73
74 op_split_copy_tensor_out(input, /*split_size=*/1, /*dim=*/0, out);
75
76 EXPECT_TENSOR_LISTS_EQ(out, expected_out);
77 }
78
79 /* %python
80 import torch
81 torch.manual_seed(0)
82 x = torch.randint(10, (2, 9))
83 res = torch.split(x, 3, 1)
84 op = "op_split_copy_tensor_out"
85 opt_extra_params = "3, 1,"
86 out_args = [
87 "out_shape, dynamism",
88 "out_shape, dynamism",
89 "out_shape, dynamism"
90 ]
91 dtype = "ScalarType::Int"
92 check = "EXPECT_TENSOR_LISTS_EQ" */
93
test_dynamic_shape(const std::vector<int32_t> & out_shape,enum torch::executor::TensorShapeDynamism dynamism)94 void test_dynamic_shape(
95 const std::vector<int32_t>& out_shape,
96 enum torch::executor::TensorShapeDynamism dynamism) {
97 /* %python
98 %rewrite(unary_op_tensor_list_out) */
99
100 TensorFactory<ScalarType::Int> tf;
101
102 Tensor x =
103 tf.make({2, 9}, {4, 9, 3, 0, 3, 9, 7, 3, 7, 3, 1, 6, 6, 9, 8, 6, 6, 8});
104 std::vector<Tensor> expectedv = {
105 tf.make({2, 3}, {4, 9, 3, 3, 1, 6}),
106 tf.make({2, 3}, {0, 3, 9, 6, 9, 8}),
107 tf.make({2, 3}, {7, 3, 7, 6, 6, 8})};
108 TensorList expected(expectedv.data(), expectedv.size());
109
110 std::vector<Tensor> outv = {
111 tf.zeros(out_shape, dynamism),
112 tf.zeros(out_shape, dynamism),
113 tf.zeros(out_shape, dynamism)};
114 TensorList out(outv.data(), outv.size());
115 op_split_copy_tensor_out(x, 3, 1, out);
116 EXPECT_TENSOR_LISTS_EQ(out, expected);
117 }
118 };
119
120 /**
121 * Returns a 3x3x3 contiguous tensor where the underlying data counts from 0 to
122 * 26.
123 */
TEST_F(OpSplitCopyTensorOutTest,Split3x3x3OnDim0)124 TEST_F(OpSplitCopyTensorOutTest, Split3x3x3OnDim0) {
125 TensorFactory<ScalarType::Int> tf;
126 TensorListFactory<ScalarType::Int> tlf;
127
128 // Splitting on dim=N with split_size=2 will produce a list of tensors where
129 // the max dim[N] is 2, and the other dims are the same as the input.
130
131 // clang-format off
132 std::vector<Tensor> expected_out = {
133 tf.make(
134 /*sizes=*/{2, 3, 3},
135 /*data=*/
136 {
137 0, 1, 2, // tensor([[[ 0, 1, 2],
138 3, 4, 5, // [ 3, 4, 5],
139 6, 7, 8, // [ 6, 7, 8]],
140
141 9, 10, 11, // [[ 9, 10, 11],
142 12, 13, 14, // [12, 13, 14],
143 15, 16, 17, // [15, 16, 17]]])
144 }),
145 tf.make(
146 /*sizes=*/{1, 3, 3},
147 /*data=*/
148 {
149 18, 19, 20, // tensor([[[18, 19, 20],
150 21, 22, 23, // [21, 22, 23],
151 24, 25, 26, // [24, 25, 26]]])
152 }),
153 };
154 // clang-format on
155
156 Tensor input = make3x3x3(tf);
157
158 // Output list with the same shapes/dtypes as the expected outputs.
159 TensorList out = tlf.zeros_like(expected_out);
160
161 op_split_copy_tensor_out(input, /*split_size=*/2, /*dim=*/0, out);
162
163 EXPECT_TENSOR_LISTS_EQ(expected_out, out);
164
165 // Also show that python negative indexing works for this case.
166 TensorList out2 = tlf.zeros_like(expected_out);
167 op_split_copy_tensor_out(input, /*split_size=*/2, /*dim=*/-3, out2);
168 EXPECT_TENSOR_LISTS_EQ(expected_out, out2);
169 }
170
TEST_F(OpSplitCopyTensorOutTest,Split3x3x3OnDim1)171 TEST_F(OpSplitCopyTensorOutTest, Split3x3x3OnDim1) {
172 TensorFactory<ScalarType::Int> tf;
173 TensorListFactory<ScalarType::Int> tlf;
174
175 // Splitting on dim=N with split_size=2 will produce a list of tensors where
176 // the max dim[N] is 2, and the other dims are the same as the input.
177
178 // clang-format off
179 std::vector<Tensor> expected_out = {
180 tf.make(
181 /*sizes=*/{3, 2, 3},
182 /*data=*/
183 {
184 0, 1, 2, // tensor([[[ 0, 1, 2],
185 3, 4, 5, // [ 3, 4, 5]],
186
187 9, 10, 11, // [[ 9, 10, 11],
188 12, 13, 14, // [12, 13, 14]],
189
190 18, 19, 20, // [[18, 19, 20],
191 21, 22, 23, // [21, 22, 23]]]),
192 }),
193 tf.make(
194 /*sizes=*/{3, 1, 3},
195 /*data=*/
196 {
197 6, 7, 8, // tensor([[[ 6, 7, 8]],
198
199 15, 16, 17, // [[15, 16, 17]],
200
201 24, 25, 26, // [[24, 25, 26]]])
202 }),
203 };
204 // clang-format on
205
206 Tensor input = make3x3x3(tf);
207
208 // Output list with the same shapes/dtypes as the expected outputs.
209 TensorList out = tlf.zeros_like(expected_out);
210
211 op_split_copy_tensor_out(input, /*split_size=*/2, /*dim=*/1, out);
212
213 EXPECT_TENSOR_LISTS_EQ(expected_out, out);
214
215 // Also show that python negative indexing works for this case.
216 TensorList out2 = tlf.zeros_like(expected_out);
217 op_split_copy_tensor_out(input, /*split_size=*/2, /*dim=*/-2, out2);
218 EXPECT_TENSOR_LISTS_EQ(expected_out, out2);
219 }
220
TEST_F(OpSplitCopyTensorOutTest,Split3x3x3OnDim2)221 TEST_F(OpSplitCopyTensorOutTest, Split3x3x3OnDim2) {
222 TensorFactory<ScalarType::Int> tf;
223 TensorListFactory<ScalarType::Int> tlf;
224
225 // Splitting on dim=N with split_size=2 will produce a list of tensors where
226 // the max dim[N] is 2, and the other dims are the same as the input.
227
228 // clang-format off
229 std::vector<Tensor> expected_out = {
230 tf.make(
231 /*sizes=*/{3, 3, 2},
232 /*data=*/
233 {
234 0, 1, // tensor([[[ 0, 1],
235 3, 4, // [ 3, 4],
236 6, 7, // [ 6, 7]],
237
238 9, 10, // [[ 9, 10],
239 12, 13, // [12, 13],
240 15, 16, // [15, 16]],
241
242 18, 19, // [[18, 19],
243 21, 22, // [21, 22],
244 24, 25, // [24, 25]]])
245 }),
246 tf.make(
247 /*sizes=*/{3, 3, 1},
248 /*data=*/
249 {
250 2, // tensor([[[ 2],
251 5, // [ 5],
252 8, // [ 8]],
253
254 11, // [[11],
255 14, // [14],
256 17, // [17]],
257
258 20, // [[20],
259 23, // [23],
260 26, // [26]]])
261 }),
262 };
263 // clang-format on
264
265 Tensor input = make3x3x3(tf);
266
267 // Output list with the same shapes/dtypes as the expected outputs.
268 TensorList out = tlf.zeros_like(expected_out);
269
270 op_split_copy_tensor_out(input, /*split_size=*/2, /*dim=*/2, out);
271
272 EXPECT_TENSOR_LISTS_EQ(expected_out, out);
273
274 // Also show that python negative indexing works for this case.
275 TensorList out2 = tlf.zeros_like(expected_out);
276 op_split_copy_tensor_out(input, /*split_size=*/2, /*dim=*/-1, out2);
277 EXPECT_TENSOR_LISTS_EQ(expected_out, out2);
278 }
279
TEST_F(OpSplitCopyTensorOutTest,LargerSplitSizeDoesNothing)280 TEST_F(OpSplitCopyTensorOutTest, LargerSplitSizeDoesNothing) {
281 TensorFactory<ScalarType::Int> tf;
282 TensorListFactory<ScalarType::Int> tlf;
283
284 Tensor input = make3x3x3(tf);
285
286 // Since split_size will be >= the largest dimension, slicing along any
287 // dimension should return the unmodified input as the only output entry.
288 std::vector<Tensor> expected_out = {input};
289
290 for (int64_t split_size = 3; split_size < 6; ++split_size) {
291 for (size_t dim = 0; dim < input.dim(); ++dim) {
292 TensorList out = tlf.zeros_like({input});
293 op_split_copy_tensor_out(input, split_size, dim, out);
294 EXPECT_TENSOR_LISTS_EQ(out, expected_out);
295 }
296 }
297 }
298
TEST_F(OpSplitCopyTensorOutTest,AllDtypesSupported)299 TEST_F(OpSplitCopyTensorOutTest, AllDtypesSupported) {
300 #define TEST_ENTRY(ctype, dtype) test_dtype<ScalarType::dtype>();
301 ET_FORALL_REAL_TYPES_AND(Bool, TEST_ENTRY);
302 #undef TEST_ENTRY
303 // TODO: Also add tests for half, complex, quantized, and other types. Easiest
304 // way to do that would be to make TensorFactory support zeros() and ones()
305 // for those types.
306 }
307
TEST_F(OpSplitCopyTensorOutTest,EmptyInputTensor)308 TEST_F(OpSplitCopyTensorOutTest, EmptyInputTensor) {
309 TensorFactory<ScalarType::Int> tf;
310 TensorListFactory<ScalarType::Int> tlf;
311
312 Tensor input = tf.ones(/*sizes=*/{0});
313 EXPECT_EQ(input.numel(), 0);
314
315 std::vector<Tensor> expected_out = {input};
316
317 // Splitting a zero-size tensor succeeds, even for split_size zero.
318 TensorList out = tlf.zeros_like({input});
319 for (int64_t split_size = 0; split_size < 3; ++split_size) {
320 op_split_copy_tensor_out(input, split_size, /*dim=*/0, out);
321 EXPECT_TENSOR_LISTS_EQ(out, expected_out);
322 }
323 }
324
TEST_F(OpSplitCopyTensorOutTest,ZeroDimensionalInputTensorDies)325 TEST_F(OpSplitCopyTensorOutTest, ZeroDimensionalInputTensorDies) {
326 TensorFactory<ScalarType::Int> tf;
327 TensorListFactory<ScalarType::Int> tlf;
328
329 Tensor input = tf.ones(/*sizes=*/{});
330 // Arbitrary output shape since this input can't be split.
331 TensorList out = tlf.zeros_like({input});
332
333 ET_EXPECT_KERNEL_FAILURE(
334 context_,
335 op_split_copy_tensor_out(input, /*split_size=*/1, /*dim=*/0, out));
336 }
337
TEST_F(OpSplitCopyTensorOutTest,ZeroSplitSizeOnlyWorksForZeroSizeDims)338 TEST_F(OpSplitCopyTensorOutTest, ZeroSplitSizeOnlyWorksForZeroSizeDims) {
339 TensorFactory<ScalarType::Int> tf;
340 TensorListFactory<ScalarType::Int> tlf;
341
342 Tensor input = tf.ones(/*sizes=*/{1, 0, 2});
343 EXPECT_EQ(input.numel(), 0);
344
345 std::vector<Tensor> expected_out = {input};
346
347 TensorList out = tlf.zeros_like({input});
348
349 // Fails when trying to split with size zero on a dim with size > 0.
350 ET_EXPECT_KERNEL_FAILURE(
351 context_,
352 op_split_copy_tensor_out(input, /*split_size=*/0, /*dim=*/0, out));
353
354 // Successfully splits with size zero on a dim with size == 0.
355 op_split_copy_tensor_out(input, /*split_size=*/0, /*dim=*/1, out);
356 EXPECT_TENSOR_LISTS_EQ(out, expected_out);
357
358 // Fails again when trying to split with size zero on a dim with size > 0.
359 ET_EXPECT_KERNEL_FAILURE(
360 context_,
361 op_split_copy_tensor_out(input, /*split_size=*/0, /*dim=*/2, out));
362 }
363
TEST_F(OpSplitCopyTensorOutTest,NegativeSplitSizeFails)364 TEST_F(OpSplitCopyTensorOutTest, NegativeSplitSizeFails) {
365 TensorFactory<ScalarType::Int> tf;
366 TensorListFactory<ScalarType::Int> tlf;
367
368 Tensor input = tf.ones(/*sizes=*/{2, 2});
369 // Arbitrary output shape since there's no actual valid size.
370 TensorList out = tlf.zeros_like({input});
371
372 ET_EXPECT_KERNEL_FAILURE(
373 context_,
374 op_split_copy_tensor_out(input, /*split_size=*/-1, /*dim=*/0, out));
375 }
376
TEST_F(OpSplitCopyTensorOutTest,OutOfRangeDimsDie)377 TEST_F(OpSplitCopyTensorOutTest, OutOfRangeDimsDie) {
378 TensorFactory<ScalarType::Int> tf;
379 TensorListFactory<ScalarType::Int> tlf;
380
381 Tensor input = tf.ones(/*sizes=*/{2, 2});
382
383 std::vector<int64_t> good_dims = {-2, -1, 0, 1};
384 std::vector<int64_t> bad_dims = {-4, -3, 2, 3};
385
386 // Since split_size is >= the largest dimension, slicing along any
387 // dimension should return the unmodified input as the only output entry.
388 constexpr int64_t split_size = 2;
389 std::vector<Tensor> expected_out = {input};
390
391 for (auto dim : good_dims) {
392 TensorList out = tlf.zeros_like({input});
393 op_split_copy_tensor_out(input, split_size, dim, out);
394 EXPECT_TENSOR_LISTS_EQ(out, expected_out);
395 }
396
397 for (auto dim : bad_dims) {
398 TensorList out = tlf.zeros_like({input});
399 ET_EXPECT_KERNEL_FAILURE(
400 context_, op_split_copy_tensor_out(input, split_size, dim, out));
401 }
402 }
403
TEST_F(OpSplitCopyTensorOutTest,DtypeMismatchDies)404 TEST_F(OpSplitCopyTensorOutTest, DtypeMismatchDies) {
405 GTEST_SKIP() << "ATen kernel can handle dtype mismatch";
406 TensorFactory<ScalarType::Int> tf_int;
407 TensorListFactory<ScalarType::Int> tlf_int;
408 TensorListFactory<ScalarType::Float> tlf_float;
409
410 Tensor input = tf_int.ones(/*sizes=*/{2, 2});
411
412 // Use a split_size that produces a single output entry on success.
413 constexpr int64_t split_size = 2;
414 constexpr int64_t dim = 0;
415
416 // Demonstrate that this setup works when the dtypes are the same.
417 {
418 TensorList out = tlf_int.zeros_like({input});
419 op_split_copy_tensor_out(input, split_size, dim, out);
420 EXPECT_TENSOR_LISTS_EQ(out, std::vector<Tensor>({input}));
421 }
422
423 // Dies with the same setup but the output dtype is different.
424 {
425 TensorList out = tlf_float.zeros_like({input});
426 ET_EXPECT_KERNEL_FAILURE(
427 context_, op_split_copy_tensor_out(input, split_size, dim, out));
428 }
429 }
430
TEST_F(OpSplitCopyTensorOutTest,WrongNumOutputEntriesDies)431 TEST_F(OpSplitCopyTensorOutTest, WrongNumOutputEntriesDies) {
432 TensorFactory<ScalarType::Int> tf;
433 TensorListFactory<ScalarType::Int> tlf;
434
435 Tensor input = tf.ones(/*sizes=*/{3});
436
437 // Use a split_size that produces two output entries on success.
438 constexpr int64_t split_size = 2;
439 constexpr int64_t dim = 0;
440
441 // Demonstrate that splitting the input should produce two output entries.
442 {
443 std::vector<Tensor> expected_out = {
444 tf.ones(/*sizes=*/{2}),
445 tf.ones(/*sizes=*/{1}),
446 };
447 TensorList out = tlf.zeros_like(expected_out);
448 op_split_copy_tensor_out(input, split_size, dim, out);
449 EXPECT_TENSOR_LISTS_EQ(out, expected_out);
450 }
451
452 // Dies with the same setup but the output has one fewer entry than it should.
453 {
454 std::vector<Tensor> incorrect_out = {
455 tf.ones(/*sizes=*/{2}),
456 // Missing second entry.
457 };
458 TensorList out = tlf.zeros_like(incorrect_out);
459 ET_EXPECT_KERNEL_FAILURE(
460 context_, op_split_copy_tensor_out(input, split_size, dim, out));
461 }
462
463 // Dies with the same setup but the output has one more entry than it should.
464 {
465 std::vector<Tensor> incorrect_out = {
466 tf.ones(/*sizes=*/{2}),
467 tf.ones(/*sizes=*/{1}),
468 tf.ones(/*sizes=*/{1}), // Extra entry.
469 };
470 TensorList out = tlf.zeros_like(incorrect_out);
471 ET_EXPECT_KERNEL_FAILURE(
472 context_, op_split_copy_tensor_out(input, split_size, dim, out));
473 }
474 }
475
TEST_F(OpSplitCopyTensorOutTest,WrongOutputShapeDies)476 TEST_F(OpSplitCopyTensorOutTest, WrongOutputShapeDies) {
477 if (torch::executor::testing::SupportedFeatures::get()->is_aten) {
478 GTEST_SKIP() << "ATen kernel can handle wrong out shape";
479 }
480 TensorFactory<ScalarType::Int> tf;
481 TensorListFactory<ScalarType::Int> tlf;
482
483 Tensor input = tf.ones(/*sizes=*/{5, 3, 4});
484
485 // Use a split_size that produces two output entries on success.
486 constexpr int64_t split_size = 2;
487 constexpr int64_t dim = 1;
488
489 // Demonstrate the shapes that this split should produce.
490 {
491 std::vector<Tensor> expected_out = {
492 tf.ones(/*sizes=*/{5, 2, 4}),
493 tf.ones(/*sizes=*/{5, 1, 4}),
494 };
495 TensorList out = tlf.zeros_like(expected_out);
496 op_split_copy_tensor_out(input, split_size, dim, out);
497 EXPECT_TENSOR_LISTS_EQ(out, expected_out);
498 }
499
500 // Make each of the dimensions of the final element incorrect.
501 {
502 std::vector<Tensor> incorrect_out = {
503 tf.ones(/*sizes=*/{5, 2, 4}),
504 tf.ones(/*sizes=*/{5 + 1, 1, 4}), // Wrong size for dim 0.
505 };
506 TensorList out = tlf.zeros_like(incorrect_out);
507 ET_EXPECT_KERNEL_FAILURE(
508 context_, op_split_copy_tensor_out(input, split_size, dim, out));
509 }
510 {
511 std::vector<Tensor> incorrect_out = {
512 tf.ones(/*sizes=*/{5, 2, 4}),
513 tf.ones(/*sizes=*/{5, 1 + 1, 4}), // Wrong size for dim 1 (split dim).
514 };
515 TensorList out = tlf.zeros_like(incorrect_out);
516 ET_EXPECT_KERNEL_FAILURE(
517 context_, op_split_copy_tensor_out(input, split_size, dim, out));
518 }
519 {
520 std::vector<Tensor> incorrect_out = {
521 tf.ones(/*sizes=*/{5, 2, 4}),
522 tf.ones(/*sizes=*/{5, 1, 4 + 1}), // Wrong size for dim 2.
523 };
524 TensorList out = tlf.zeros_like(incorrect_out);
525 ET_EXPECT_KERNEL_FAILURE(
526 context_, op_split_copy_tensor_out(input, split_size, dim, out));
527 }
528
529 // Wrong size of the split dimension for the non-last output element.
530 {
531 std::vector<Tensor> incorrect_out = {
532 tf.ones(/*sizes=*/{5, 2 + 1, 4}), // Wrong size for dim 1 (split dim).
533 tf.ones(/*sizes=*/{5, 1, 4}),
534 };
535 TensorList out = tlf.zeros_like(incorrect_out);
536 ET_EXPECT_KERNEL_FAILURE(
537 context_, op_split_copy_tensor_out(input, split_size, dim, out));
538 }
539
540 // Wrong number of output dimensions.
541 {
542 std::vector<Tensor> incorrect_out = {
543 tf.ones(/*sizes=*/{5, 2, 4}),
544 tf.ones(/*sizes=*/{5, 1, 4, 2}), // Extra dimension
545 };
546 TensorList out = tlf.zeros_like(incorrect_out);
547 ET_EXPECT_KERNEL_FAILURE(
548 context_, op_split_copy_tensor_out(input, split_size, dim, out));
549 }
550 {
551 std::vector<Tensor> incorrect_out = {
552 tf.ones(/*sizes=*/{5, 2, 4}),
553 tf.ones(/*sizes=*/{5, 1}), // Missing dimension
554 };
555 TensorList out = tlf.zeros_like(incorrect_out);
556 ET_EXPECT_KERNEL_FAILURE(
557 context_, op_split_copy_tensor_out(input, split_size, dim, out));
558 }
559 }
560
TEST_F(OpSplitCopyTensorOutTest,DynamicShapeUpperBoundSameAsExpected)561 TEST_F(OpSplitCopyTensorOutTest, DynamicShapeUpperBoundSameAsExpected) {
562 test_dynamic_shape(
563 {2, 3}, torch::executor::TensorShapeDynamism::DYNAMIC_BOUND);
564 }
565
TEST_F(OpSplitCopyTensorOutTest,DynamicShapeUpperBoundLargerThanExpected)566 TEST_F(OpSplitCopyTensorOutTest, DynamicShapeUpperBoundLargerThanExpected) {
567 GTEST_SKIP() << "Dynamic shape not supported";
568 test_dynamic_shape(
569 {10, 10}, torch::executor::TensorShapeDynamism::DYNAMIC_BOUND);
570 }
571
TEST_F(OpSplitCopyTensorOutTest,DynamicShapeUnbound)572 TEST_F(OpSplitCopyTensorOutTest, DynamicShapeUnbound) {
573 GTEST_SKIP() << "Dynamic shape not supported";
574 test_dynamic_shape(
575 {1, 1}, torch::executor::TensorShapeDynamism::DYNAMIC_UNBOUND);
576 }
577