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