xref: /aosp_15_r20/external/executorch/kernels/test/op_t_copy_test.cpp (revision 523fa7a60841cd1ecfb9cc4201f1ca8b03ed023a)
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 
16 #include <gtest/gtest.h>
17 
18 using namespace ::testing;
19 using exec_aten::ArrayRef;
20 using exec_aten::ScalarType;
21 using exec_aten::Tensor;
22 using torch::executor::testing::TensorFactory;
23 
24 class OpTCopyTest : public OperatorTest {
25  protected:
op_t_copy_out(const Tensor & self,Tensor & out)26   Tensor& op_t_copy_out(const Tensor& self, Tensor& out) {
27     return torch::executor::aten::t_copy_outf(context_, self, out);
28   }
29 };
30 
31 TEST_F(OpTCopyTest, 1DTranspose) {
32   TensorFactory<ScalarType::Int> tf;
33 
34   Tensor t_in = tf.make({4}, {1, 2, 3, 4});
35   Tensor t_out = tf.make({4}, {0, 0, 0, 0});
36 
37   op_t_copy_out(t_in, t_out);
38   EXPECT_TENSOR_EQ(t_in, t_out);
39 }
40 
41 TEST_F(OpTCopyTest, 1DTransposeMismatchShapeDie) {
42   if (torch::executor::testing::SupportedFeatures::get()->is_aten) {
43     GTEST_SKIP() << "ATen kernel can handle mismatched shapes";
44   }
45   TensorFactory<ScalarType::Int> tf;
46 
47   Tensor t_in = tf.make({4}, {1, 2, 3, 4});
48   Tensor t_out = tf.make({2}, {0, 0});
49 
50   ET_EXPECT_KERNEL_FAILURE(context_, op_t_copy_out(t_in, t_out));
51 }
52 
53 TEST_F(OpTCopyTest, 2DTranspose) {
54   TensorFactory<ScalarType::Int> tf;
55 
56   Tensor t_in = tf.make({2, 3}, {1, 2, 3, 4, 5, 6});
57   Tensor t_out = tf.make({3, 2}, {0, 0, 0, 0, 0, 0});
58   Tensor t_expected = tf.make({3, 2}, {1, 4, 2, 5, 3, 6});
59 
60   op_t_copy_out(t_in, t_out);
61   EXPECT_TENSOR_EQ(t_out, t_expected);
62 }
63 
64 TEST_F(OpTCopyTest, 2DTransposeMismatchShapeDie) {
65   if (torch::executor::testing::SupportedFeatures::get()->is_aten) {
66     GTEST_SKIP() << "ATen kernel can handle mismatched shapes";
67   }
68   TensorFactory<ScalarType::Int> tf;
69 
70   Tensor t_in = tf.make({2, 3}, {1, 2, 3, 4, 5, 6});
71   Tensor t_out = tf.make({2, 2}, {0, 0, 0, 0});
72 
73   ET_EXPECT_KERNEL_FAILURE(context_, op_t_copy_out(t_in, t_out));
74 }
75 
76 TEST_F(OpTCopyTest, 3DTransposeDie) {
77   TensorFactory<ScalarType::Int> tf;
78 
79   Tensor t_in = tf.make({2, 3, 1}, {1, 2, 3, 4, 5, 6});
80   Tensor t_out = tf.make({3, 2, 1}, {0, 0, 0, 0, 0, 0});
81 
82   ET_EXPECT_KERNEL_FAILURE(context_, op_t_copy_out(t_in, t_out));
83 }
84 
85 /* %python
86 import torch
87 torch.manual_seed(0)
88 x = torch.rand(3, 2)
89 res = torch.t(x)
90 op = "op_t_copy_out"
91 dtype = "ScalarType::Float"
92 check = "EXPECT_TENSOR_EQ" */
93 
TEST_F(OpTCopyTest,DynamicShapeUpperBoundSameAsExpected)94 TEST_F(OpTCopyTest, DynamicShapeUpperBoundSameAsExpected) {
95   /* %python
96   out_args = "{2, 3}, torch::executor::TensorShapeDynamism::DYNAMIC_BOUND"
97   %rewrite(unary_op) */
98 
99   TensorFactory<ScalarType::Float> tf;
100 
101   Tensor x = tf.make(
102       {3, 2},
103       {0.49625658988952637,
104        0.7682217955589294,
105        0.08847743272781372,
106        0.13203048706054688,
107        0.30742281675338745,
108        0.6340786814689636});
109   Tensor expected = tf.make(
110       {2, 3},
111       {0.49625658988952637,
112        0.08847743272781372,
113        0.30742281675338745,
114        0.7682217955589294,
115        0.13203048706054688,
116        0.6340786814689636});
117 
118   Tensor out =
119       tf.zeros({2, 3}, torch::executor::TensorShapeDynamism::DYNAMIC_BOUND);
120   op_t_copy_out(x, out);
121   EXPECT_TENSOR_EQ(out, expected);
122 }
123 
TEST_F(OpTCopyTest,DynamicShapeUpperBoundLargerThanExpected)124 TEST_F(OpTCopyTest, DynamicShapeUpperBoundLargerThanExpected) {
125   if (!torch::executor::testing::SupportedFeatures::get()->output_resize) {
126     GTEST_SKIP() << "Dynamic shape not supported";
127   }
128   /* %python
129   out_args = "{10, 10}, torch::executor::TensorShapeDynamism::DYNAMIC_BOUND"
130   %rewrite(unary_op) */
131 
132   TensorFactory<ScalarType::Float> tf;
133 
134   Tensor x = tf.make(
135       {3, 2},
136       {0.49625658988952637,
137        0.7682217955589294,
138        0.08847743272781372,
139        0.13203048706054688,
140        0.30742281675338745,
141        0.6340786814689636});
142   Tensor expected = tf.make(
143       {2, 3},
144       {0.49625658988952637,
145        0.08847743272781372,
146        0.30742281675338745,
147        0.7682217955589294,
148        0.13203048706054688,
149        0.6340786814689636});
150 
151   Tensor out =
152       tf.zeros({10, 10}, torch::executor::TensorShapeDynamism::DYNAMIC_BOUND);
153   op_t_copy_out(x, out);
154   EXPECT_TENSOR_EQ(out, expected);
155 }
156 
TEST_F(OpTCopyTest,DynamicShapeUnbound)157 TEST_F(OpTCopyTest, DynamicShapeUnbound) {
158   if (!torch::executor::testing::SupportedFeatures::get()->output_resize) {
159     GTEST_SKIP() << "Dynamic shape not supported";
160   }
161   /* %python
162   out_args = "{1, 1}, torch::executor::TensorShapeDynamism::DYNAMIC_UNBOUND"
163   %rewrite(unary_op) */
164 
165   TensorFactory<ScalarType::Float> tf;
166 
167   Tensor x = tf.make(
168       {3, 2},
169       {0.49625658988952637,
170        0.7682217955589294,
171        0.08847743272781372,
172        0.13203048706054688,
173        0.30742281675338745,
174        0.6340786814689636});
175   Tensor expected = tf.make(
176       {2, 3},
177       {0.49625658988952637,
178        0.08847743272781372,
179        0.30742281675338745,
180        0.7682217955589294,
181        0.13203048706054688,
182        0.6340786814689636});
183 
184   Tensor out =
185       tf.zeros({1, 1}, torch::executor::TensorShapeDynamism::DYNAMIC_UNBOUND);
186   op_t_copy_out(x, out);
187   EXPECT_TENSOR_EQ(out, expected);
188 }
189