• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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::IntArrayRef;
20 using exec_aten::Scalar;
21 using exec_aten::ScalarType;
22 using exec_aten::Tensor;
23 using torch::executor::testing::SupportedFeatures;
24 using torch::executor::testing::TensorFactory;
25 
26 class OpConstantPadNDOutTest : public OperatorTest {
27  protected:
op_constant_pad_nd_out(const Tensor & self,const IntArrayRef padding,const Scalar & value,Tensor & out)28   Tensor& op_constant_pad_nd_out(
29       const Tensor& self,
30       const IntArrayRef padding,
31       const Scalar& value,
32       Tensor& out) {
33     return torch::executor::aten::constant_pad_nd_outf(
34         context_, self, padding, value, out);
35   }
36 
37   template <ScalarType DTYPE>
test_constant_pad_nd_out_dim2()38   void test_constant_pad_nd_out_dim2() {
39     TensorFactory<DTYPE> tf;
40 
41     const std::vector<int32_t> sizes = {2, 4, 4};
42     const std::vector<int32_t> sizes_out = {2, 4, 6};
43     const std::vector<int64_t> padding = {1, 1};
44 
45     // clang-format off
46     Tensor self = tf.make(
47         sizes,
48         {
49            1,  2,  3,  4,
50            5,  6,  7,  8,
51            1,  2,  3,  4,
52            5,  6,  7,  8,
53 
54            1,  2,  3,  4,
55            5,  6,  7,  8,
56            1,  2,  3,  4,
57            5,  6,  7,  8,
58         });
59     // clang-format on
60 
61     // clang-format off
62     Tensor expected = tf.make(
63         sizes_out,
64         {
65            7,  1,  2,  3,  4,  7,
66            7,  5,  6,  7,  8,  7,
67            7,  1,  2,  3,  4,  7,
68            7,  5,  6,  7,  8,  7,
69 
70            7,  1,  2,  3,  4,  7,
71            7,  5,  6,  7,  8,  7,
72            7,  1,  2,  3,  4,  7,
73            7,  5,  6,  7,  8,  7,
74         });
75     // clang-format on
76 
77     IntArrayRef padding_ref = IntArrayRef(padding.data(), padding.size());
78     Tensor out = tf.zeros(sizes_out);
79 
80     // Valid input should give the expected output
81     op_constant_pad_nd_out(self, padding_ref, 7, out);
82     EXPECT_TENSOR_CLOSE(out, expected);
83   }
84 
85   template <ScalarType DTYPE>
test_constant_pad_nd_out_dim1()86   void test_constant_pad_nd_out_dim1() {
87     TensorFactory<DTYPE> tf;
88 
89     const std::vector<int32_t> sizes = {2, 4, 4};
90     const std::vector<int32_t> sizes_out = {2, 6, 4};
91     const std::vector<int64_t> padding = {0, 0, 2, 0};
92 
93     // clang-format off
94     Tensor self = tf.make(
95         sizes,
96         {
97            1,  2,  3,  4,
98            5,  6,  7,  8,
99            1,  2,  3,  4,
100            5,  6,  7,  8,
101 
102            1,  2,  3,  4,
103            5,  6,  7,  8,
104            1,  2,  3,  4,
105            5,  6,  7,  8,
106         });
107     // clang-format on
108 
109     // clang-format off
110     Tensor expected = tf.make(
111         sizes_out,
112         {
113            7,  7,  7,  7,
114            7,  7,  7,  7,
115            1,  2,  3,  4,
116            5,  6,  7,  8,
117            1,  2,  3,  4,
118            5,  6,  7,  8,
119 
120            7,  7,  7,  7,
121            7,  7,  7,  7,
122            1,  2,  3,  4,
123            5,  6,  7,  8,
124            1,  2,  3,  4,
125            5,  6,  7,  8,
126         });
127     // clang-format on
128 
129     IntArrayRef padding_ref = IntArrayRef(padding.data(), padding.size());
130     Tensor out = tf.zeros(sizes_out);
131 
132     // Valid input should give the expected output
133     op_constant_pad_nd_out(self, padding_ref, 7, out);
134     EXPECT_TENSOR_CLOSE(out, expected);
135   }
136 
137   template <ScalarType DTYPE>
test_constant_pad_nd_out_dim0()138   void test_constant_pad_nd_out_dim0() {
139     TensorFactory<DTYPE> tf;
140 
141     const std::vector<int32_t> sizes = {2, 4, 4};
142     const std::vector<int32_t> sizes_out = {3, 4, 4};
143     const std::vector<int64_t> padding = {0, 0, 0, 0, 1, 0};
144 
145     // clang-format off
146     Tensor self = tf.make(
147         sizes,
148         {
149            1,  2,  3,  4,
150            5,  6,  7,  8,
151            1,  2,  3,  4,
152            5,  6,  7,  8,
153 
154            1,  2,  3,  4,
155            5,  6,  7,  8,
156            1,  2,  3,  4,
157            5,  6,  7,  8,
158         });
159     // clang-format on
160 
161     // clang-format off
162     Tensor expected = tf.make(
163         sizes_out,
164         {
165            7,  7,  7,  7,
166            7,  7,  7,  7,
167            7,  7,  7,  7,
168            7,  7,  7,  7,
169 
170            1,  2,  3,  4,
171            5,  6,  7,  8,
172            1,  2,  3,  4,
173            5,  6,  7,  8,
174 
175            1,  2,  3,  4,
176            5,  6,  7,  8,
177            1,  2,  3,  4,
178            5,  6,  7,  8,
179         });
180     // clang-format on
181 
182     IntArrayRef padding_ref = IntArrayRef(padding.data(), padding.size());
183     Tensor out = tf.zeros(sizes_out);
184 
185     // Valid input should give the expected output
186     op_constant_pad_nd_out(self, padding_ref, 7, out);
187     EXPECT_TENSOR_CLOSE(out, expected);
188   }
189 
190   template <ScalarType DTYPE>
test_constant_pad_nd_out_dim12()191   void test_constant_pad_nd_out_dim12() {
192     TensorFactory<DTYPE> tf;
193 
194     const std::vector<int32_t> sizes = {2, 4, 4};
195     const std::vector<int32_t> sizes_out = {2, 6, 7};
196     const std::vector<int64_t> padding = {2, 1, 0, 2};
197 
198     // clang-format off
199     Tensor self = tf.make(
200         sizes,
201         {
202            1,  2,  3,  4,
203            5,  6,  7,  8,
204            1,  2,  3,  4,
205            5,  6,  7,  8,
206 
207            1,  2,  3,  4,
208            5,  6,  7,  8,
209            1,  2,  3,  4,
210            5,  6,  7,  8,
211         });
212     // clang-format on
213 
214     // clang-format off
215     Tensor expected = tf.make(
216         sizes_out,
217         {
218            7,  7,  1,  2,  3,  4,  7,
219            7,  7,  5,  6,  7,  8,  7,
220            7,  7,  1,  2,  3,  4,  7,
221            7,  7,  5,  6,  7,  8,  7,
222            7,  7,  7,  7,  7,  7,  7,
223            7,  7,  7,  7,  7,  7,  7,
224 
225            7,  7,  1,  2,  3,  4,  7,
226            7,  7,  5,  6,  7,  8,  7,
227            7,  7,  1,  2,  3,  4,  7,
228            7,  7,  5,  6,  7,  8,  7,
229            7,  7,  7,  7,  7,  7,  7,
230            7,  7,  7,  7,  7,  7,  7,
231         });
232     // clang-format on
233 
234     IntArrayRef padding_ref = IntArrayRef(padding.data(), padding.size());
235     Tensor out = tf.zeros(sizes_out);
236 
237     // Valid input should give the expected output
238     op_constant_pad_nd_out(self, padding_ref, 7, out);
239     EXPECT_TENSOR_CLOSE(out, expected);
240   }
241 
242   template <ScalarType DTYPE>
test_constant_pad_nd_out_dim02()243   void test_constant_pad_nd_out_dim02() {
244     TensorFactory<DTYPE> tf;
245 
246     const std::vector<int32_t> sizes = {2, 4, 4};
247     const std::vector<int32_t> sizes_out = {3, 4, 7};
248     const std::vector<int64_t> padding = {2, 1, 0, 0, 0, 1};
249 
250     // clang-format off
251     Tensor self = tf.make(
252         sizes,
253         {
254            1,  2,  3,  4,
255            5,  6,  7,  8,
256            1,  2,  3,  4,
257            5,  6,  7,  8,
258 
259            1,  2,  3,  4,
260            5,  6,  7,  8,
261            1,  2,  3,  4,
262            5,  6,  7,  8,
263         });
264     // clang-format on
265 
266     // clang-format off
267     Tensor expected = tf.make(
268         sizes_out,
269         {
270            7,  7,  1,  2,  3,  4,  7,
271            7,  7,  5,  6,  7,  8,  7,
272            7,  7,  1,  2,  3,  4,  7,
273            7,  7,  5,  6,  7,  8,  7,
274 
275            7,  7,  1,  2,  3,  4,  7,
276            7,  7,  5,  6,  7,  8,  7,
277            7,  7,  1,  2,  3,  4,  7,
278            7,  7,  5,  6,  7,  8,  7,
279 
280            7,  7,  7,  7,  7,  7,  7,
281            7,  7,  7,  7,  7,  7,  7,
282            7,  7,  7,  7,  7,  7,  7,
283            7,  7,  7,  7,  7,  7,  7,
284         });
285     // clang-format on
286 
287     IntArrayRef padding_ref = IntArrayRef(padding.data(), padding.size());
288     Tensor out = tf.zeros(sizes_out);
289 
290     // Valid input should give the expected output
291     op_constant_pad_nd_out(self, padding_ref, 7, out);
292     EXPECT_TENSOR_CLOSE(out, expected);
293   }
294 
295   template <ScalarType DTYPE>
test_constant_pad_nd_out_dim012()296   void test_constant_pad_nd_out_dim012() {
297     TensorFactory<DTYPE> tf;
298 
299     const std::vector<int32_t> sizes = {2, 4, 4};
300     const std::vector<int32_t> sizes_out = {3, 5, 7};
301     const std::vector<int64_t> padding = {2, 1, 1, 0, 0, 1};
302 
303     // clang-format off
304     Tensor self = tf.make(
305         sizes,
306         {
307            1,  2,  3,  4,
308            5,  6,  7,  8,
309            1,  2,  3,  4,
310            5,  6,  7,  8,
311 
312            1,  2,  3,  4,
313            5,  6,  7,  8,
314            1,  2,  3,  4,
315            5,  6,  7,  8,
316         });
317     // clang-format on
318 
319     // clang-format off
320     Tensor expected = tf.make(
321         sizes_out,
322         {
323            7,  7,  7,  7,  7,  7,  7,
324            7,  7,  1,  2,  3,  4,  7,
325            7,  7,  5,  6,  7,  8,  7,
326            7,  7,  1,  2,  3,  4,  7,
327            7,  7,  5,  6,  7,  8,  7,
328 
329            7,  7,  7,  7,  7,  7,  7,
330            7,  7,  1,  2,  3,  4,  7,
331            7,  7,  5,  6,  7,  8,  7,
332            7,  7,  1,  2,  3,  4,  7,
333            7,  7,  5,  6,  7,  8,  7,
334 
335            7,  7,  7,  7,  7,  7,  7,
336            7,  7,  7,  7,  7,  7,  7,
337            7,  7,  7,  7,  7,  7,  7,
338            7,  7,  7,  7,  7,  7,  7,
339            7,  7,  7,  7,  7,  7,  7,
340         });
341     // clang-format on
342 
343     IntArrayRef padding_ref = IntArrayRef(padding.data(), padding.size());
344     Tensor out = tf.zeros(sizes_out);
345 
346     // Valid input should give the expected output
347     op_constant_pad_nd_out(self, padding_ref, 7, out);
348     EXPECT_TENSOR_CLOSE(out, expected);
349   }
350 };
351 
TEST_F(OpConstantPadNDOutTest,TestPadDim2)352 TEST_F(OpConstantPadNDOutTest, TestPadDim2) {
353 #define TEST_ENTRY(ctype, dtype) \
354   test_constant_pad_nd_out_dim2<ScalarType::dtype>();
355 
356   ET_FORALL_REAL_TYPES(TEST_ENTRY);
357 #undef TEST_ENTRY
358 }
359 
TEST_F(OpConstantPadNDOutTest,TestPadDim1)360 TEST_F(OpConstantPadNDOutTest, TestPadDim1) {
361 #define TEST_ENTRY(ctype, dtype) \
362   test_constant_pad_nd_out_dim1<ScalarType::dtype>();
363 
364   ET_FORALL_REAL_TYPES(TEST_ENTRY);
365 #undef TEST_ENTRY
366 }
367 
TEST_F(OpConstantPadNDOutTest,TestPadDim0)368 TEST_F(OpConstantPadNDOutTest, TestPadDim0) {
369 #define TEST_ENTRY(ctype, dtype) \
370   test_constant_pad_nd_out_dim0<ScalarType::dtype>();
371 
372   ET_FORALL_REAL_TYPES(TEST_ENTRY);
373 #undef TEST_ENTRY
374 }
375 
TEST_F(OpConstantPadNDOutTest,TestPadDim1And2)376 TEST_F(OpConstantPadNDOutTest, TestPadDim1And2) {
377 #define TEST_ENTRY(ctype, dtype) \
378   test_constant_pad_nd_out_dim12<ScalarType::dtype>();
379 
380   ET_FORALL_REAL_TYPES(TEST_ENTRY);
381 #undef TEST_ENTRY
382 }
383 
TEST_F(OpConstantPadNDOutTest,TestPadDim0And2)384 TEST_F(OpConstantPadNDOutTest, TestPadDim0And2) {
385 #define TEST_ENTRY(ctype, dtype) \
386   test_constant_pad_nd_out_dim02<ScalarType::dtype>();
387 
388   ET_FORALL_REAL_TYPES(TEST_ENTRY);
389 #undef TEST_ENTRY
390 }
391 
TEST_F(OpConstantPadNDOutTest,TestPadDim0And1And2)392 TEST_F(OpConstantPadNDOutTest, TestPadDim0And1And2) {
393 #define TEST_ENTRY(ctype, dtype) \
394   test_constant_pad_nd_out_dim012<ScalarType::dtype>();
395 
396   ET_FORALL_REAL_TYPES(TEST_ENTRY);
397 #undef TEST_ENTRY
398 }
399 
TEST_F(OpConstantPadNDOutTest,DifferentInputOutputTypesFail)400 TEST_F(OpConstantPadNDOutTest, DifferentInputOutputTypesFail) {
401   TensorFactory<ScalarType::Float> tf;
402   TensorFactory<ScalarType::Double> tf_out;
403 
404   const std::vector<int32_t> sizes = {1, 4, 4};
405   const std::vector<int32_t> sizes_out = {1, 4, 6};
406   const std::vector<int64_t> padding = {1, 1};
407 
408   IntArrayRef padding_ref = IntArrayRef(padding.data(), padding.size());
409 
410   Tensor self = tf.ones(sizes);
411   Tensor out = tf_out.zeros(sizes_out);
412 
413   ET_EXPECT_KERNEL_FAILURE(
414       context_, op_constant_pad_nd_out(self, padding_ref, 0, out));
415 }
416 
TEST_F(OpConstantPadNDOutTest,OddNumberOfPaddingElementsFail)417 TEST_F(OpConstantPadNDOutTest, OddNumberOfPaddingElementsFail) {
418   TensorFactory<ScalarType::Float> tf;
419 
420   const std::vector<int32_t> sizes = {1, 4, 4};
421   const std::vector<int32_t> sizes_out = {1, 4, 4};
422   const std::vector<int64_t> padding = {1, 1, 0};
423 
424   IntArrayRef padding_ref = IntArrayRef(padding.data(), padding.size());
425 
426   Tensor self = tf.ones(sizes);
427   Tensor out = tf.zeros(sizes_out);
428 
429   ET_EXPECT_KERNEL_FAILURE(
430       context_, op_constant_pad_nd_out(self, padding_ref, 0, out));
431 }
432 
TEST_F(OpConstantPadNDOutTest,TooManyPaddingElementsFail)433 TEST_F(OpConstantPadNDOutTest, TooManyPaddingElementsFail) {
434   TensorFactory<ScalarType::Float> tf;
435 
436   const std::vector<int32_t> sizes = {1, 4, 4};
437   const std::vector<int32_t> sizes_out = {1, 4, 4};
438   const std::vector<int64_t> padding = {3, 2, 1, 1, 2, 1, 1, 0};
439 
440   IntArrayRef padding_ref = IntArrayRef(padding.data(), padding.size());
441 
442   Tensor self = tf.ones(sizes);
443   Tensor out = tf.zeros(sizes_out);
444 
445   ET_EXPECT_KERNEL_FAILURE(
446       context_, op_constant_pad_nd_out(self, padding_ref, 0, out));
447 }
448 
TEST_F(OpConstantPadNDOutTest,IncorrectOutputShapeFail)449 TEST_F(OpConstantPadNDOutTest, IncorrectOutputShapeFail) {
450   if (SupportedFeatures::get()->is_aten) {
451     GTEST_SKIP() << "ATen kernel can handle reshape output";
452   }
453 
454   TensorFactory<ScalarType::Float> tf;
455 
456   const std::vector<int32_t> sizes = {1, 4, 4};
457   const std::vector<int32_t> sizes_out = {1, 4, 4};
458   const std::vector<int64_t> padding = {1, 1};
459 
460   IntArrayRef padding_ref = IntArrayRef(padding.data(), padding.size());
461 
462   Tensor self = tf.ones(sizes);
463   Tensor out = tf.zeros(sizes_out);
464 
465   ET_EXPECT_KERNEL_FAILURE(
466       context_, op_constant_pad_nd_out(self, padding_ref, 0, out));
467 }
468