xref: /aosp_15_r20/external/executorch/kernels/test/op_detach_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 #include <cmath>
18 
19 using namespace ::testing;
20 using exec_aten::Scalar;
21 using exec_aten::ScalarType;
22 using exec_aten::Tensor;
23 using torch::executor::testing::TensorFactory;
24 
25 class OpDetachCopyOutTest : public OperatorTest {
26  protected:
op_detach_copy_out(const Tensor & self,Tensor & out)27   Tensor& op_detach_copy_out(const Tensor& self, Tensor& out) {
28     return torch::executor::aten::detach_copy_outf(context_, self, out);
29   }
30 
31   // Common testing for eq operator
32   template <ScalarType DTYPE>
test_detach_copy_out()33   void test_detach_copy_out() {
34     TensorFactory<DTYPE> tf;
35     const std::vector<int32_t> sizes = {2, 2};
36 
37     Tensor in = tf.make(sizes, {1, 2, 3, 4});
38     Tensor out = tf.zeros(sizes);
39 
40     // Valid input should give the expected output
41     op_detach_copy_out(in, out);
42     EXPECT_TENSOR_EQ(out, tf.make(sizes, {1, 2, 3, 4}));
43   }
44 
45   template <ScalarType DTYPE>
test_detach_copy_out_invalid_shape()46   void test_detach_copy_out_invalid_shape() {
47     TensorFactory<DTYPE> tf;
48 
49     const std::vector<int32_t> in_sizes = {2, 2};
50     const std::vector<int32_t> out_sizes = {4};
51 
52     Tensor in = tf.ones(in_sizes);
53     Tensor out = tf.zeros(out_sizes);
54 
55     ET_EXPECT_KERNEL_FAILURE(context_, op_detach_copy_out(in, out));
56   }
57 };
58 
59 template <>
test_detach_copy_out()60 void OpDetachCopyOutTest::test_detach_copy_out<ScalarType::Bool>() {
61   TensorFactory<ScalarType::Bool> tf;
62   const std::vector<int32_t> sizes = {2, 2};
63   Tensor out = tf.zeros(sizes);
64 
65   // Valid input should give the expected output
66   op_detach_copy_out(tf.make(sizes, /*data=*/{true, false, true, false}), out);
67   EXPECT_TENSOR_EQ(out, tf.make(sizes, /*data=*/{true, false, true, false}));
68 }
69 
70 template <>
test_detach_copy_out()71 void OpDetachCopyOutTest::test_detach_copy_out<ScalarType::Float>() {
72   TensorFactory<ScalarType::Float> tf;
73   const std::vector<int32_t> sizes = {2, 2};
74   Tensor out = tf.zeros(sizes);
75 
76   // Valid input should give the expected output
77   op_detach_copy_out(
78       tf.make(sizes, /*data=*/{3.14, INFINITY, -INFINITY, NAN}), out);
79   EXPECT_TENSOR_EQ(
80       out, tf.make(sizes, /*data=*/{3.14, INFINITY, -INFINITY, NAN}));
81 }
82 
TEST_F(OpDetachCopyOutTest,AllScalarInputOutputSupport)83 TEST_F(OpDetachCopyOutTest, AllScalarInputOutputSupport) {
84 #define TEST_ENTRY(ctype, dtype) test_detach_copy_out<ScalarType::dtype>();
85   ET_FORALL_REAL_TYPES_AND(Bool, TEST_ENTRY);
86 #undef TEST_ENTRY
87 }
88 
89 // Mismatched shape tests.
TEST_F(OpDetachCopyOutTest,MismatchedShapesDies)90 TEST_F(OpDetachCopyOutTest, MismatchedShapesDies) {
91   if (torch::executor::testing::SupportedFeatures::get()->is_aten) {
92     GTEST_SKIP() << "ATen kernel can handle mismatched shapes";
93   }
94 #define TEST_ENTRY(ctype, dtype) \
95   test_detach_copy_out_invalid_shape<ScalarType::dtype>();
96   ET_FORALL_REAL_TYPES_AND(Bool, TEST_ENTRY);
97 #undef TEST_ENTRY
98 }
99 
TEST_F(OpDetachCopyOutTest,MismatchedInputDtypesDies)100 TEST_F(OpDetachCopyOutTest, MismatchedInputDtypesDies) {
101   TensorFactory<ScalarType::Byte> tf_byte;
102   TensorFactory<ScalarType::Char> tf_char;
103 
104   const std::vector<int32_t> sizes = {2, 2};
105 
106   Tensor in = tf_byte.ones(sizes);
107   Tensor out = tf_char.ones(sizes);
108 
109   ET_EXPECT_KERNEL_FAILURE(context_, op_detach_copy_out(in, out));
110 }
111 
TEST_F(OpDetachCopyOutTest,SimpleGeneratedCase)112 TEST_F(OpDetachCopyOutTest, SimpleGeneratedCase) {
113   TensorFactory<ScalarType::Float> tf;
114 
115   Tensor x = tf.make(
116       {10, 10},
117       {1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0,
118        1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0,
119        1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0,
120        1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0,
121        1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0,
122        1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0,
123        1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0,
124        1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0});
125   Tensor expected_result = tf.make(
126       {10, 10},
127       {1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0,
128        1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0,
129        1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0,
130        1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0,
131        1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0,
132        1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0,
133        1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0,
134        1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0});
135 
136   Tensor out = tf.zeros({10, 10});
137   Tensor ret = op_detach_copy_out(x, out);
138   EXPECT_TENSOR_CLOSE(out, expected_result);
139 }
140 
TEST_F(OpDetachCopyOutTest,DynamicShapeUpperBoundSameAsExpected)141 TEST_F(OpDetachCopyOutTest, DynamicShapeUpperBoundSameAsExpected) {
142   TensorFactory<ScalarType::Float> tf;
143 
144   Tensor x = tf.make(
145       {3, 2},
146       {0.18719732761383057,
147        0.03402292728424072,
148        0.944246232509613,
149        0.8801798820495605,
150        0.0012360215187072754,
151        0.5935860276222229});
152   Tensor expected_result = tf.make(
153       {3, 2},
154       {0.18719732761383057,
155        0.03402292728424072,
156        0.944246232509613,
157        0.8801798820495605,
158        0.0012360215187072754,
159        0.5935860276222229});
160 
161   Tensor out =
162       tf.zeros({3, 2}, torch::executor::TensorShapeDynamism::DYNAMIC_BOUND);
163   Tensor ret = op_detach_copy_out(x, out);
164   EXPECT_TENSOR_CLOSE(out, expected_result);
165 }
166 
TEST_F(OpDetachCopyOutTest,DynamicShapeUpperBoundLargerThanExpected)167 TEST_F(OpDetachCopyOutTest, DynamicShapeUpperBoundLargerThanExpected) {
168   TensorFactory<ScalarType::Float> tf;
169 
170   Tensor x = tf.make(
171       {3, 2},
172       {0.18719732761383057,
173        0.03402292728424072,
174        0.944246232509613,
175        0.8801798820495605,
176        0.0012360215187072754,
177        0.5935860276222229});
178   Tensor expected_result = tf.make(
179       {3, 2},
180       {0.18719732761383057,
181        0.03402292728424072,
182        0.944246232509613,
183        0.8801798820495605,
184        0.0012360215187072754,
185        0.5935860276222229});
186 
187   Tensor out =
188       tf.zeros({10, 10}, torch::executor::TensorShapeDynamism::DYNAMIC_BOUND);
189   Tensor ret = op_detach_copy_out(x, out);
190   EXPECT_TENSOR_CLOSE(out, expected_result);
191 }
192 
TEST_F(OpDetachCopyOutTest,DynamicShapeUnbound)193 TEST_F(OpDetachCopyOutTest, DynamicShapeUnbound) {
194   GTEST_SKIP() << "Dynamic shape unbound not supported";
195   TensorFactory<ScalarType::Float> tf;
196 
197   Tensor x = tf.make(
198       {3, 2},
199       {0.18719732761383057,
200        0.03402292728424072,
201        0.944246232509613,
202        0.8801798820495605,
203        0.0012360215187072754,
204        0.5935860276222229});
205   Tensor expected_result = tf.make(
206       {3, 2},
207       {0.18719732761383057,
208        0.03402292728424072,
209        0.944246232509613,
210        0.8801798820495605,
211        0.0012360215187072754,
212        0.5935860276222229});
213 
214   Tensor out =
215       tf.zeros({1, 1}, torch::executor::TensorShapeDynamism::DYNAMIC_UNBOUND);
216   Tensor ret = op_detach_copy_out(x, out);
217   EXPECT_TENSOR_CLOSE(out, expected_result);
218 }
219