xref: /aosp_15_r20/external/executorch/extension/tensor/test/tensor_ptr_maker_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/extension/tensor/tensor_ptr_maker.h>
10 
11 #include <gtest/gtest.h>
12 
13 #include <executorch/runtime/platform/runtime.h>
14 
15 using namespace ::executorch::extension;
16 using namespace ::executorch::runtime;
17 
18 class TensorPtrMakerTest : public ::testing::Test {
19  protected:
SetUpTestSuite()20   static void SetUpTestSuite() {
21     runtime_init();
22   }
23 };
24 
TEST_F(TensorPtrMakerTest,CreateTensorUsingTensorMaker)25 TEST_F(TensorPtrMakerTest, CreateTensorUsingTensorMaker) {
26   float data[20] = {2};
27   auto tensor = for_blob(data, {4, 5})
28                     .dim_order({0, 1})
29                     .strides({5, 1})
30                     .dynamism(exec_aten::TensorShapeDynamism::DYNAMIC_BOUND)
31                     .make_tensor_ptr();
32 
33   EXPECT_EQ(tensor->dim(), 2);
34   EXPECT_EQ(tensor->size(0), 4);
35   EXPECT_EQ(tensor->size(1), 5);
36   EXPECT_EQ(tensor->strides()[0], 5);
37   EXPECT_EQ(tensor->strides()[1], 1);
38   EXPECT_EQ(tensor->const_data_ptr<float>(), data);
39   EXPECT_EQ(tensor->const_data_ptr<float>()[0], 2);
40 }
41 
TEST_F(TensorPtrMakerTest,PerfectForwardingLValue)42 TEST_F(TensorPtrMakerTest, PerfectForwardingLValue) {
43   float data[20] = {2};
44   std::vector<exec_aten::SizesType> sizes = {4, 5};
45   std::vector<exec_aten::DimOrderType> dim_order = {0, 1};
46   std::vector<exec_aten::StridesType> strides = {5, 1};
47 
48   auto tensor = for_blob(data, sizes)
49                     .dim_order(dim_order)
50                     .strides(strides)
51                     .make_tensor_ptr();
52 
53   EXPECT_EQ(tensor->dim(), 2);
54   EXPECT_EQ(tensor->size(0), 4);
55   EXPECT_EQ(tensor->size(1), 5);
56   EXPECT_EQ(tensor->strides()[0], 5);
57   EXPECT_EQ(tensor->strides()[1], 1);
58 
59   EXPECT_EQ(sizes.size(), 2);
60   EXPECT_EQ(dim_order.size(), 2);
61   EXPECT_EQ(strides.size(), 2);
62 }
63 
TEST_F(TensorPtrMakerTest,PerfectForwardingRValue)64 TEST_F(TensorPtrMakerTest, PerfectForwardingRValue) {
65   float data[20] = {2};
66   std::vector<exec_aten::SizesType> sizes = {4, 5};
67   std::vector<exec_aten::DimOrderType> dim_order = {0, 1};
68   std::vector<exec_aten::StridesType> strides = {5, 1};
69 
70   auto tensor = for_blob(data, std::move(sizes))
71                     .dim_order(std::move(dim_order))
72                     .strides(std::move(strides))
73                     .make_tensor_ptr();
74 
75   EXPECT_EQ(tensor->dim(), 2);
76   EXPECT_EQ(tensor->size(0), 4);
77   EXPECT_EQ(tensor->size(1), 5);
78   EXPECT_EQ(tensor->strides()[0], 5);
79   EXPECT_EQ(tensor->strides()[1], 1);
80   // for_blob() moved the contents of the vectors, leaving these empty.
81   EXPECT_EQ(sizes.size(), 0); // NOLINT(bugprone-use-after-move)
82   EXPECT_EQ(dim_order.size(), 0); // NOLINT(bugprone-use-after-move)
83   EXPECT_EQ(strides.size(), 0); // NOLINT(bugprone-use-after-move)
84 }
85 
TEST_F(TensorPtrMakerTest,CreateTensorFromBlob)86 TEST_F(TensorPtrMakerTest, CreateTensorFromBlob) {
87   float data[20] = {2};
88   auto tensor = from_blob(data, {4, 5});
89 
90   EXPECT_EQ(tensor->dim(), 2);
91   EXPECT_EQ(tensor->size(0), 4);
92   EXPECT_EQ(tensor->size(1), 5);
93   EXPECT_EQ(tensor->strides()[0], 5);
94   EXPECT_EQ(tensor->strides()[1], 1);
95   EXPECT_EQ(tensor->const_data_ptr<float>(), data);
96   EXPECT_EQ(tensor->const_data_ptr<float>()[0], 2);
97   EXPECT_EQ(tensor->const_data_ptr<float>()[19], 0);
98 }
99 
TEST_F(TensorPtrMakerTest,CreateTensorUsingFromBlobWithStrides)100 TEST_F(TensorPtrMakerTest, CreateTensorUsingFromBlobWithStrides) {
101   float data[20] = {3};
102   auto tensor = from_blob(data, {2, 2, 2}, {4, 2, 1});
103 
104   EXPECT_EQ(tensor->dim(), 3);
105   EXPECT_EQ(tensor->size(0), 2);
106   EXPECT_EQ(tensor->size(1), 2);
107   EXPECT_EQ(tensor->size(2), 2);
108   EXPECT_EQ(tensor->strides()[0], 4);
109   EXPECT_EQ(tensor->strides()[1], 2);
110   EXPECT_EQ(tensor->strides()[2], 1);
111   EXPECT_EQ(tensor->const_data_ptr<float>(), data);
112   EXPECT_EQ(tensor->const_data_ptr<float>()[0], 3);
113 }
114 
TEST_F(TensorPtrMakerTest,TensorMakerConversionOperator)115 TEST_F(TensorPtrMakerTest, TensorMakerConversionOperator) {
116   float data[20] = {2};
117   TensorPtr tensor =
118       for_blob(data, {4, 5})
119           .dynamism(exec_aten::TensorShapeDynamism::DYNAMIC_BOUND);
120 
121   EXPECT_EQ(tensor->dim(), 2);
122   EXPECT_EQ(tensor->size(0), 4);
123   EXPECT_EQ(tensor->size(1), 5);
124 }
125 
TEST_F(TensorPtrMakerTest,CreateTensorWithZeroDimensions)126 TEST_F(TensorPtrMakerTest, CreateTensorWithZeroDimensions) {
127   float data[1] = {2};
128   auto tensor = from_blob(data, {});
129 
130   EXPECT_EQ(tensor->dim(), 0);
131   EXPECT_EQ(tensor->numel(), 1);
132   EXPECT_EQ(tensor->const_data_ptr<float>()[0], 2);
133 }
134 
TEST_F(TensorPtrMakerTest,TensorWithCustomDataDeleter)135 TEST_F(TensorPtrMakerTest, TensorWithCustomDataDeleter) {
136   auto deleter_called = false;
137   float* data = new float[20]();
138   auto tensor = for_blob(data, {4, 5})
139                     .deleter([&deleter_called](void* ptr) {
140                       deleter_called = true;
141                       delete[] static_cast<float*>(ptr);
142                     })
143                     .make_tensor_ptr();
144 
145   tensor.reset();
146   EXPECT_TRUE(deleter_called);
147 }
148 
TEST_F(TensorPtrMakerTest,TensorManagesMovedVector)149 TEST_F(TensorPtrMakerTest, TensorManagesMovedVector) {
150   auto deleter_called = false;
151   std::vector<float> data(20, 3.0f);
152   auto* data_ptr = data.data();
153   auto tensor = for_blob(data_ptr, {4, 5})
154                     .deleter([moved_data = std::move(data), &deleter_called](
155                                  void*) mutable { deleter_called = true; })
156                     .make_tensor_ptr();
157 
158   EXPECT_TRUE(data.empty()); // NOLINT(bugprone-use-after-move)
159   EXPECT_EQ(tensor->data_ptr<float>(), data_ptr);
160 
161   tensor.reset();
162   EXPECT_TRUE(deleter_called);
163 }
164 
TEST_F(TensorPtrMakerTest,TensorDeleterReleasesCapturedSharedPtr)165 TEST_F(TensorPtrMakerTest, TensorDeleterReleasesCapturedSharedPtr) {
166   auto deleter_called = false;
167   std::shared_ptr<float[]> data_ptr(
168       new float[10], [](float* ptr) { delete[] ptr; });
169   auto tensor = from_blob(
170       data_ptr.get(),
171       {4, 5},
172       exec_aten::ScalarType::Float,
173       [data_ptr, &deleter_called](void*) mutable { deleter_called = true; });
174 
175   EXPECT_EQ(data_ptr.use_count(), 2);
176 
177   tensor.reset();
178   EXPECT_TRUE(deleter_called);
179   EXPECT_EQ(data_ptr.use_count(), 1);
180 }
181 
TEST_F(TensorPtrMakerTest,CreateEmpty)182 TEST_F(TensorPtrMakerTest, CreateEmpty) {
183   auto tensor = empty({4, 5});
184   EXPECT_EQ(tensor->dim(), 2);
185   EXPECT_EQ(tensor->size(0), 4);
186   EXPECT_EQ(tensor->size(1), 5);
187   EXPECT_EQ(tensor->scalar_type(), exec_aten::ScalarType::Float);
188 
189   auto tensor2 = empty({4, 5}, exec_aten::ScalarType::Int);
190   EXPECT_EQ(tensor2->dim(), 2);
191   EXPECT_EQ(tensor2->size(0), 4);
192   EXPECT_EQ(tensor2->size(1), 5);
193   EXPECT_EQ(tensor2->scalar_type(), exec_aten::ScalarType::Int);
194 
195   auto tensor3 = empty({4, 5}, exec_aten::ScalarType::Long);
196   EXPECT_EQ(tensor3->dim(), 2);
197   EXPECT_EQ(tensor3->size(0), 4);
198   EXPECT_EQ(tensor3->size(1), 5);
199   EXPECT_EQ(tensor3->scalar_type(), exec_aten::ScalarType::Long);
200 
201   auto tensor4 = empty({4, 5}, exec_aten::ScalarType::Double);
202   EXPECT_EQ(tensor4->dim(), 2);
203   EXPECT_EQ(tensor4->size(0), 4);
204   EXPECT_EQ(tensor4->size(1), 5);
205   EXPECT_EQ(tensor4->scalar_type(), exec_aten::ScalarType::Double);
206 }
207 
TEST_F(TensorPtrMakerTest,CreateFull)208 TEST_F(TensorPtrMakerTest, CreateFull) {
209   auto tensor = full({4, 5}, 7);
210   EXPECT_EQ(tensor->dim(), 2);
211   EXPECT_EQ(tensor->size(0), 4);
212   EXPECT_EQ(tensor->size(1), 5);
213   EXPECT_EQ(tensor->scalar_type(), exec_aten::ScalarType::Float);
214   EXPECT_EQ(tensor->const_data_ptr<float>()[0], 7);
215 
216   auto tensor2 = full({4, 5}, 3, exec_aten::ScalarType::Int);
217   EXPECT_EQ(tensor2->dim(), 2);
218   EXPECT_EQ(tensor2->size(0), 4);
219   EXPECT_EQ(tensor2->size(1), 5);
220   EXPECT_EQ(tensor2->scalar_type(), exec_aten::ScalarType::Int);
221   EXPECT_EQ(tensor2->const_data_ptr<int32_t>()[0], 3);
222 
223   auto tensor3 = full({4, 5}, 9, exec_aten::ScalarType::Long);
224   EXPECT_EQ(tensor3->dim(), 2);
225   EXPECT_EQ(tensor3->size(0), 4);
226   EXPECT_EQ(tensor3->size(1), 5);
227   EXPECT_EQ(tensor3->scalar_type(), exec_aten::ScalarType::Long);
228   EXPECT_EQ(tensor3->const_data_ptr<int64_t>()[0], 9);
229 
230   auto tensor4 = full({4, 5}, 11, exec_aten::ScalarType::Double);
231   EXPECT_EQ(tensor4->dim(), 2);
232   EXPECT_EQ(tensor4->size(0), 4);
233   EXPECT_EQ(tensor4->size(1), 5);
234   EXPECT_EQ(tensor4->scalar_type(), exec_aten::ScalarType::Double);
235   EXPECT_EQ(tensor4->const_data_ptr<double>()[0], 11);
236 }
237 
TEST_F(TensorPtrMakerTest,CreateScalar)238 TEST_F(TensorPtrMakerTest, CreateScalar) {
239   auto tensor = scalar_tensor(3.14f);
240 
241   EXPECT_EQ(tensor->dim(), 0);
242   EXPECT_EQ(tensor->numel(), 1);
243   EXPECT_EQ(tensor->scalar_type(), exec_aten::ScalarType::Float);
244   EXPECT_EQ(tensor->const_data_ptr<float>()[0], 3.14f);
245 
246   auto tensor2 = scalar_tensor(5, exec_aten::ScalarType::Int);
247 
248   EXPECT_EQ(tensor2->dim(), 0);
249   EXPECT_EQ(tensor2->numel(), 1);
250   EXPECT_EQ(tensor2->scalar_type(), exec_aten::ScalarType::Int);
251   EXPECT_EQ(tensor2->const_data_ptr<int32_t>()[0], 5);
252 
253   auto tensor3 = scalar_tensor(7.0, exec_aten::ScalarType::Double);
254 
255   EXPECT_EQ(tensor3->dim(), 0);
256   EXPECT_EQ(tensor3->numel(), 1);
257   EXPECT_EQ(tensor3->scalar_type(), exec_aten::ScalarType::Double);
258   EXPECT_EQ(tensor3->const_data_ptr<double>()[0], 7.0);
259 }
260 
TEST_F(TensorPtrMakerTest,CreateOnes)261 TEST_F(TensorPtrMakerTest, CreateOnes) {
262   auto tensor = ones({4, 5});
263   EXPECT_EQ(tensor->dim(), 2);
264   EXPECT_EQ(tensor->size(0), 4);
265   EXPECT_EQ(tensor->size(1), 5);
266   EXPECT_EQ(tensor->scalar_type(), exec_aten::ScalarType::Float);
267   EXPECT_EQ(tensor->const_data_ptr<float>()[0], 1);
268 
269   auto tensor2 = ones({4, 5}, exec_aten::ScalarType::Int);
270   EXPECT_EQ(tensor2->dim(), 2);
271   EXPECT_EQ(tensor2->size(0), 4);
272   EXPECT_EQ(tensor2->size(1), 5);
273   EXPECT_EQ(tensor2->scalar_type(), exec_aten::ScalarType::Int);
274   EXPECT_EQ(tensor2->const_data_ptr<int32_t>()[0], 1);
275 
276   auto tensor3 = ones({4, 5}, exec_aten::ScalarType::Long);
277   EXPECT_EQ(tensor3->dim(), 2);
278   EXPECT_EQ(tensor3->size(0), 4);
279   EXPECT_EQ(tensor3->size(1), 5);
280   EXPECT_EQ(tensor3->scalar_type(), exec_aten::ScalarType::Long);
281   EXPECT_EQ(tensor3->const_data_ptr<int64_t>()[0], 1);
282 
283   auto tensor4 = ones({4, 5}, exec_aten::ScalarType::Double);
284   EXPECT_EQ(tensor4->dim(), 2);
285   EXPECT_EQ(tensor4->size(0), 4);
286   EXPECT_EQ(tensor4->size(1), 5);
287   EXPECT_EQ(tensor4->scalar_type(), exec_aten::ScalarType::Double);
288   EXPECT_EQ(tensor4->const_data_ptr<double>()[0], 1);
289 }
290 
TEST_F(TensorPtrMakerTest,CreateZeros)291 TEST_F(TensorPtrMakerTest, CreateZeros) {
292   auto tensor = zeros({4, 5});
293   EXPECT_EQ(tensor->dim(), 2);
294   EXPECT_EQ(tensor->size(0), 4);
295   EXPECT_EQ(tensor->size(1), 5);
296   EXPECT_EQ(tensor->scalar_type(), exec_aten::ScalarType::Float);
297   EXPECT_EQ(tensor->const_data_ptr<float>()[0], 0);
298 
299   auto tensor2 = zeros({4, 5}, exec_aten::ScalarType::Int);
300   EXPECT_EQ(tensor2->dim(), 2);
301   EXPECT_EQ(tensor2->size(0), 4);
302   EXPECT_EQ(tensor2->size(1), 5);
303   EXPECT_EQ(tensor2->scalar_type(), exec_aten::ScalarType::Int);
304   EXPECT_EQ(tensor2->const_data_ptr<int32_t>()[0], 0);
305 
306   auto tensor3 = zeros({4, 5}, exec_aten::ScalarType::Long);
307   EXPECT_EQ(tensor3->dim(), 2);
308   EXPECT_EQ(tensor3->size(0), 4);
309   EXPECT_EQ(tensor3->size(1), 5);
310   EXPECT_EQ(tensor3->scalar_type(), exec_aten::ScalarType::Long);
311   EXPECT_EQ(tensor3->const_data_ptr<int64_t>()[0], 0);
312 
313   auto tensor4 = zeros({4, 5}, exec_aten::ScalarType::Double);
314   EXPECT_EQ(tensor4->dim(), 2);
315   EXPECT_EQ(tensor4->size(0), 4);
316   EXPECT_EQ(tensor4->size(1), 5);
317   EXPECT_EQ(tensor4->scalar_type(), exec_aten::ScalarType::Double);
318   EXPECT_EQ(tensor4->const_data_ptr<double>()[0], 0);
319 }
320 
TEST_F(TensorPtrMakerTest,CreateRandTensor)321 TEST_F(TensorPtrMakerTest, CreateRandTensor) {
322   auto tensor = rand({4, 5});
323 
324   EXPECT_EQ(tensor->dim(), 2);
325   EXPECT_EQ(tensor->size(0), 4);
326   EXPECT_EQ(tensor->size(1), 5);
327   EXPECT_EQ(tensor->scalar_type(), exec_aten::ScalarType::Float);
328 
329   for (auto i = 0; i < tensor->numel(); ++i) {
330     auto val = tensor->const_data_ptr<float>()[i];
331     EXPECT_GE(val, 0.0f);
332     EXPECT_LT(val, 1.0f);
333   }
334 }
335 
TEST_F(TensorPtrMakerTest,CreateRandTensorWithIntType)336 TEST_F(TensorPtrMakerTest, CreateRandTensorWithIntType) {
337   auto tensor = rand({4, 5}, exec_aten::ScalarType::Int);
338 
339   EXPECT_EQ(tensor->dim(), 2);
340   EXPECT_EQ(tensor->size(0), 4);
341   EXPECT_EQ(tensor->size(1), 5);
342   EXPECT_EQ(tensor->scalar_type(), exec_aten::ScalarType::Int);
343 
344   for (auto i = 0; i < tensor->numel(); ++i) {
345     auto val = tensor->const_data_ptr<int32_t>()[i];
346     EXPECT_EQ(val, 0);
347   }
348 }
349 
TEST_F(TensorPtrMakerTest,CreateRandTensorWithDoubleType)350 TEST_F(TensorPtrMakerTest, CreateRandTensorWithDoubleType) {
351   auto tensor = rand({4, 5}, exec_aten::ScalarType::Double);
352 
353   EXPECT_EQ(tensor->dim(), 2);
354   EXPECT_EQ(tensor->size(0), 4);
355   EXPECT_EQ(tensor->size(1), 5);
356   EXPECT_EQ(tensor->scalar_type(), exec_aten::ScalarType::Double);
357 
358   for (auto i = 0; i < tensor->numel(); ++i) {
359     auto val = tensor->const_data_ptr<double>()[i];
360     EXPECT_GE(val, 0.0);
361     EXPECT_LT(val, 1.0);
362   }
363 }
364 
TEST_F(TensorPtrMakerTest,CreateRandnTensor)365 TEST_F(TensorPtrMakerTest, CreateRandnTensor) {
366   auto tensor = randn({100, 100});
367 
368   EXPECT_EQ(tensor->dim(), 2);
369   EXPECT_EQ(tensor->size(0), 100);
370   EXPECT_EQ(tensor->size(1), 100);
371   EXPECT_EQ(tensor->scalar_type(), exec_aten::ScalarType::Float);
372 
373   auto sum = 0.0f;
374   for (auto i = 0; i < tensor->numel(); ++i) {
375     sum += tensor->const_data_ptr<float>()[i];
376   }
377   const auto average = sum / tensor->numel();
378   EXPECT_NEAR(average, 0.0f, 1.0f);
379 }
380 
TEST_F(TensorPtrMakerTest,CreateRandnTensorWithDoubleType)381 TEST_F(TensorPtrMakerTest, CreateRandnTensorWithDoubleType) {
382   auto tensor = randn({100, 100}, exec_aten::ScalarType::Double);
383 
384   EXPECT_EQ(tensor->dim(), 2);
385   EXPECT_EQ(tensor->size(0), 100);
386   EXPECT_EQ(tensor->size(1), 100);
387   EXPECT_EQ(tensor->scalar_type(), exec_aten::ScalarType::Double);
388 
389   auto sum = 0.0;
390   for (auto i = 0; i < tensor->numel(); ++i) {
391     sum += tensor->const_data_ptr<double>()[i];
392   }
393   const auto average = sum / tensor->numel();
394   EXPECT_NEAR(average, 0.0, 1.0);
395 }
396 
TEST_F(TensorPtrMakerTest,CreateRandIntTensorWithIntType)397 TEST_F(TensorPtrMakerTest, CreateRandIntTensorWithIntType) {
398   auto tensor = randint(10, 20, {4, 5}, exec_aten::ScalarType::Int);
399 
400   EXPECT_EQ(tensor->dim(), 2);
401   EXPECT_EQ(tensor->size(0), 4);
402   EXPECT_EQ(tensor->size(1), 5);
403   EXPECT_EQ(tensor->scalar_type(), exec_aten::ScalarType::Int);
404 
405   for (auto i = 0; i < tensor->numel(); ++i) {
406     auto val = tensor->const_data_ptr<int32_t>()[i];
407     EXPECT_GE(val, 10);
408     EXPECT_LT(val, 20);
409   }
410 }
411 
TEST_F(TensorPtrMakerTest,CreateRandIntTensorWithLongType)412 TEST_F(TensorPtrMakerTest, CreateRandIntTensorWithLongType) {
413   auto tensor = randint(10, 20, {4, 5}, exec_aten::ScalarType::Long);
414 
415   EXPECT_EQ(tensor->dim(), 2);
416   EXPECT_EQ(tensor->size(0), 4);
417   EXPECT_EQ(tensor->size(1), 5);
418   EXPECT_EQ(tensor->scalar_type(), exec_aten::ScalarType::Long);
419 
420   for (auto i = 0; i < tensor->numel(); ++i) {
421     auto val = tensor->const_data_ptr<int64_t>()[i];
422     EXPECT_GE(val, 10);
423     EXPECT_LT(val, 20);
424   }
425 }
426 
TEST_F(TensorPtrMakerTest,CreateRandnTensorWithIntType)427 TEST_F(TensorPtrMakerTest, CreateRandnTensorWithIntType) {
428   auto tensor = rand({4, 5}, exec_aten::ScalarType::Int);
429 
430   EXPECT_EQ(tensor->dim(), 2);
431   EXPECT_EQ(tensor->size(0), 4);
432   EXPECT_EQ(tensor->size(1), 5);
433   EXPECT_EQ(tensor->scalar_type(), exec_aten::ScalarType::Int);
434 
435   for (auto i = 0; i < tensor->numel(); ++i) {
436     auto val = tensor->const_data_ptr<int32_t>()[i];
437     EXPECT_EQ(val, 0);
438   }
439 }
440