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::IntArrayRef;
21 using exec_aten::MemoryFormat;
22 using exec_aten::optional;
23 using exec_aten::Scalar;
24 using exec_aten::ScalarType;
25 using exec_aten::Tensor;
26 using torch::executor::testing::TensorFactory;
27
28 class OpFullOutTest : public OperatorTest {
29 protected:
30 Tensor&
op_full_out(const IntArrayRef sizes,const Scalar & fill_value,Tensor & out)31 op_full_out(const IntArrayRef sizes, const Scalar& fill_value, Tensor& out) {
32 return torch::executor::aten::full_outf(context_, sizes, fill_value, out);
33 }
34
35 template <ScalarType DTYPE>
test_ones_out(std::vector<int32_t> && size_int32_t)36 void test_ones_out(std::vector<int32_t>&& size_int32_t) {
37 TensorFactory<DTYPE> tf;
38 std::vector<int64_t> size_int64_t(size_int32_t.begin(), size_int32_t.end());
39 auto aref = IntArrayRef(size_int64_t.data(), size_int64_t.size());
40
41 // Boolean Scalar
42 // Before: `out` consists of 0s.
43 Tensor out = tf.zeros(size_int32_t);
44 // After: `out` consists of 1s.
45 op_full_out(aref, true, out);
46 EXPECT_TENSOR_EQ(out, tf.ones(size_int32_t));
47
48 // Integral Scalar
49 // Before: `out` consists of 0s.
50 out = tf.zeros(size_int32_t);
51 // After: `out` consists of 1s.
52 op_full_out(aref, 1, out);
53 EXPECT_TENSOR_EQ(out, tf.ones(size_int32_t));
54
55 // Floating Point Scalar
56 // Before: `out` consists of 0s.
57 out = tf.zeros(size_int32_t);
58 // After: `out` consists of 1s.
59 op_full_out(aref, 1.0, out);
60 EXPECT_TENSOR_EQ(out, tf.ones(size_int32_t));
61 }
62 };
63
64 #define GENERATE_TEST(_, DTYPE) \
65 TEST_F(OpFullOutTest, DTYPE##Tensors) { \
66 test_ones_out<ScalarType::DTYPE>({}); \
67 test_ones_out<ScalarType::DTYPE>({1}); \
68 test_ones_out<ScalarType::DTYPE>({1, 1, 1}); \
69 test_ones_out<ScalarType::DTYPE>({2, 0, 4}); \
70 test_ones_out<ScalarType::DTYPE>({2, 3, 4}); \
71 }
72
73 ET_FORALL_REALH_TYPES(GENERATE_TEST)
74
TEST_F(OpFullOutTest,ValueOverflow)75 TEST_F(OpFullOutTest, ValueOverflow) {
76 if (torch::executor::testing::SupportedFeatures::get()->is_aten) {
77 GTEST_SKIP() << "ATen kernel doesn't handle overflow";
78 }
79 TensorFactory<ScalarType::Byte> tf;
80
81 std::vector<int64_t> sizes_int64_t_vec = {2, 3};
82 std::vector<int32_t> sizes_in32_t_vec = {2, 3};
83 auto sizes = IntArrayRef(sizes_int64_t_vec.data(), sizes_int64_t_vec.size());
84
85 Tensor out = tf.zeros(sizes_in32_t_vec);
86
87 op_full_out(sizes, 1000, out);
88 }
89
TEST_F(OpFullOutTest,HalfSupport)90 TEST_F(OpFullOutTest, HalfSupport) {
91 TensorFactory<ScalarType::Half> tf;
92
93 std::vector<int64_t> sizes_int64_t_vec = {2, 3};
94 std::vector<int32_t> sizes_in32_t_vec = {2, 3};
95 auto sizes = IntArrayRef(sizes_int64_t_vec.data(), sizes_int64_t_vec.size());
96
97 // Boolean Scalar
98 Tensor out = tf.zeros(sizes_in32_t_vec);
99 op_full_out(sizes, true, out);
100 EXPECT_TENSOR_EQ(out, tf.ones(sizes_in32_t_vec));
101
102 // Integral Scalar
103 out = tf.zeros(sizes_in32_t_vec);
104 op_full_out(sizes, 1, out);
105 EXPECT_TENSOR_EQ(out, tf.ones(sizes_in32_t_vec));
106
107 // Floating Point Scalar
108 out = tf.zeros(sizes_in32_t_vec);
109 op_full_out(sizes, 3.1415926535, out);
110 EXPECT_TENSOR_EQ(out, tf.full(sizes_in32_t_vec, 3.1415926535));
111 }
112
TEST_F(OpFullOutTest,ZeroDim)113 TEST_F(OpFullOutTest, ZeroDim) {
114 TensorFactory<ScalarType::Half> tf;
115
116 std::vector<int64_t> sizes_int64_t_vec = {};
117 std::vector<int32_t> sizes_in32_t_vec = {};
118 auto sizes = IntArrayRef(sizes_int64_t_vec.data(), sizes_int64_t_vec.size());
119
120 // Boolean Scalar
121 Tensor out = tf.zeros(sizes_in32_t_vec);
122 op_full_out(sizes, true, out);
123 EXPECT_TENSOR_EQ(out, tf.ones(sizes_in32_t_vec));
124 }
125