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.h>
10
11 #include <gtest/gtest.h>
12
13 #include <executorch/runtime/platform/runtime.h>
14 #include <executorch/test/utils/DeathTest.h>
15
16 using namespace ::executorch::extension;
17 using namespace ::executorch::runtime;
18
19 class TensorPtrTest : public ::testing::Test {
20 protected:
SetUpTestSuite()21 static void SetUpTestSuite() {
22 runtime_init();
23 }
24 };
25
TEST_F(TensorPtrTest,ScalarTensorCreation)26 TEST_F(TensorPtrTest, ScalarTensorCreation) {
27 float scalar_data = 3.14f;
28 auto tensor = make_tensor_ptr({}, &scalar_data);
29
30 EXPECT_EQ(tensor->numel(), 1);
31 EXPECT_EQ(tensor->dim(), 0);
32 EXPECT_EQ(tensor->sizes().size(), 0);
33 EXPECT_EQ(tensor->strides().size(), 0);
34 EXPECT_EQ(tensor->const_data_ptr<float>(), &scalar_data);
35 EXPECT_EQ(tensor->const_data_ptr<float>()[0], 3.14f);
36 }
37
TEST_F(TensorPtrTest,ScalarTensorOwningData)38 TEST_F(TensorPtrTest, ScalarTensorOwningData) {
39 auto tensor = make_tensor_ptr({}, {3.14f});
40
41 EXPECT_EQ(tensor->numel(), 1);
42 EXPECT_EQ(tensor->dim(), 0);
43 EXPECT_EQ(tensor->sizes().size(), 0);
44 EXPECT_EQ(tensor->strides().size(), 0);
45 EXPECT_EQ(tensor->const_data_ptr<float>()[0], 3.14f);
46 }
47
TEST_F(TensorPtrTest,ScalarTensorSingleValueCreation)48 TEST_F(TensorPtrTest, ScalarTensorSingleValueCreation) {
49 auto tensor_float = make_tensor_ptr(3.14f);
50 EXPECT_EQ(tensor_float->dim(), 0);
51 EXPECT_EQ(tensor_float->numel(), 1);
52 EXPECT_EQ(tensor_float->sizes().size(), 0);
53 EXPECT_EQ(tensor_float->strides().size(), 0);
54 EXPECT_EQ(tensor_float->const_data_ptr<float>()[0], 3.14f);
55 EXPECT_EQ(tensor_float->scalar_type(), exec_aten::ScalarType::Float);
56
57 auto tensor_int32 = make_tensor_ptr(42);
58 EXPECT_EQ(tensor_int32->dim(), 0);
59 EXPECT_EQ(tensor_int32->numel(), 1);
60 EXPECT_EQ(tensor_int32->sizes().size(), 0);
61 EXPECT_EQ(tensor_int32->strides().size(), 0);
62 EXPECT_EQ(tensor_int32->const_data_ptr<int32_t>()[0], 42);
63 EXPECT_EQ(tensor_int32->scalar_type(), exec_aten::ScalarType::Int);
64
65 auto tensor_double = make_tensor_ptr(2.718);
66 EXPECT_EQ(tensor_double->dim(), 0);
67 EXPECT_EQ(tensor_double->numel(), 1);
68 EXPECT_EQ(tensor_double->sizes().size(), 0);
69 EXPECT_EQ(tensor_double->strides().size(), 0);
70 EXPECT_EQ(tensor_double->const_data_ptr<double>()[0], 2.718);
71 EXPECT_EQ(tensor_double->scalar_type(), exec_aten::ScalarType::Double);
72
73 auto tensor_int64 = make_tensor_ptr(static_cast<int64_t>(10000000000));
74 EXPECT_EQ(tensor_int64->dim(), 0);
75 EXPECT_EQ(tensor_int64->numel(), 1);
76 EXPECT_EQ(tensor_int64->sizes().size(), 0);
77 EXPECT_EQ(tensor_int64->strides().size(), 0);
78 EXPECT_EQ(tensor_int64->const_data_ptr<int64_t>()[0], 10000000000);
79 EXPECT_EQ(tensor_int64->scalar_type(), exec_aten::ScalarType::Long);
80 }
81
TEST_F(TensorPtrTest,CreateTensorWithStridesAndDimOrder)82 TEST_F(TensorPtrTest, CreateTensorWithStridesAndDimOrder) {
83 float data[20] = {2};
84 auto tensor = make_tensor_ptr({4, 5}, data, {0, 1}, {5, 1});
85 EXPECT_EQ(tensor->dim(), 2);
86 EXPECT_EQ(tensor->size(0), 4);
87 EXPECT_EQ(tensor->size(1), 5);
88 EXPECT_EQ(tensor->strides()[0], 5);
89 EXPECT_EQ(tensor->strides()[1], 1);
90 EXPECT_EQ(tensor->const_data_ptr<float>(), data);
91 EXPECT_EQ(tensor->const_data_ptr<float>()[0], 2);
92 }
93
TEST_F(TensorPtrTest,TensorSharingImpl)94 TEST_F(TensorPtrTest, TensorSharingImpl) {
95 float data[20] = {2};
96 auto tensor1 = make_tensor_ptr({4, 5}, data);
97 auto tensor2 = tensor1;
98 EXPECT_EQ(tensor1.get(), tensor2.get());
99 EXPECT_EQ(tensor1->unsafeGetTensorImpl(), tensor2->unsafeGetTensorImpl());
100 }
101
TEST_F(TensorPtrTest,TensorLifetime)102 TEST_F(TensorPtrTest, TensorLifetime) {
103 TensorPtr tensor;
104 EXPECT_EQ(tensor, nullptr);
105 {
106 float data[20] = {2};
107 tensor = make_tensor_ptr({4, 5}, data);
108 }
109 EXPECT_EQ(tensor->dim(), 2);
110 EXPECT_EQ(tensor->size(0), 4);
111 EXPECT_EQ(tensor->size(1), 5);
112 }
113
TEST_F(TensorPtrTest,TensorWithZeroDimensionAndElements)114 TEST_F(TensorPtrTest, TensorWithZeroDimensionAndElements) {
115 float data[20] = {2};
116 auto tensor = make_tensor_ptr({}, data);
117 EXPECT_EQ(tensor->dim(), 0);
118 EXPECT_EQ(tensor->numel(), 1);
119 tensor = make_tensor_ptr({0, 5}, data);
120 EXPECT_EQ(tensor->dim(), 2);
121 EXPECT_EQ(tensor->numel(), 0);
122 }
123
TEST_F(TensorPtrTest,TensorResize)124 TEST_F(TensorPtrTest, TensorResize) {
125 float data[20] = {2};
126 auto tensor = make_tensor_ptr(
127 {4, 5},
128 data,
129 {},
130 {},
131 exec_aten::ScalarType::Float,
132 exec_aten::TensorShapeDynamism::DYNAMIC_UNBOUND);
133 EXPECT_EQ(resize_tensor_ptr(tensor, {5, 4}), Error::Ok);
134 EXPECT_EQ(tensor->size(0), 5);
135 EXPECT_EQ(tensor->size(1), 4);
136 }
137
TEST_F(TensorPtrTest,TensorDataAccess)138 TEST_F(TensorPtrTest, TensorDataAccess) {
139 float data[6] = {1, 2, 3, 4, 5, 6};
140 auto tensor = make_tensor_ptr({2, 3}, data);
141 EXPECT_EQ(tensor->const_data_ptr<float>()[0], 1);
142 EXPECT_EQ(tensor->const_data_ptr<float>()[5], 6);
143 tensor->mutable_data_ptr<float>()[0] = 10;
144 EXPECT_EQ(tensor->const_data_ptr<float>()[0], 10);
145 }
146
TEST_F(TensorPtrTest,TensorWithCustomDataDeleter)147 TEST_F(TensorPtrTest, TensorWithCustomDataDeleter) {
148 auto deleter_called = false;
149 float* data = new float[20]();
150 auto tensor = make_tensor_ptr(
151 {4, 5},
152 data,
153 {},
154 {},
155 exec_aten::ScalarType::Float,
156 exec_aten::TensorShapeDynamism::DYNAMIC_BOUND,
157 [&deleter_called](void* ptr) {
158 deleter_called = true;
159 delete[] static_cast<float*>(ptr);
160 });
161
162 tensor.reset();
163 EXPECT_TRUE(deleter_called);
164 }
165
TEST_F(TensorPtrTest,TensorManagesMovedVector)166 TEST_F(TensorPtrTest, TensorManagesMovedVector) {
167 auto deleter_called = false;
168 std::vector<float> data(20, 3.0f);
169 auto* data_ptr = data.data();
170 auto tensor = make_tensor_ptr(
171 {4, 5},
172 data_ptr,
173 {},
174 {},
175 exec_aten::ScalarType::Float,
176 exec_aten::TensorShapeDynamism::DYNAMIC_BOUND,
177 [moved_data = std::move(data), &deleter_called](void*) mutable {
178 deleter_called = true;
179 });
180
181 EXPECT_TRUE(data.empty()); // NOLINT(bugprone-use-after-move)
182 EXPECT_EQ(tensor->data_ptr<float>(), data_ptr);
183
184 tensor.reset();
185 EXPECT_TRUE(deleter_called);
186 }
187
TEST_F(TensorPtrTest,TensorDeleterReleasesCapturedSharedPtr)188 TEST_F(TensorPtrTest, TensorDeleterReleasesCapturedSharedPtr) {
189 auto deleter_called = false;
190 std::shared_ptr<float[]> data_ptr(
191 new float[10], [](float* ptr) { delete[] ptr; });
192 auto tensor = make_tensor_ptr(
193 {4, 5},
194 data_ptr.get(),
195 {},
196 {},
197 exec_aten::ScalarType::Float,
198 exec_aten::TensorShapeDynamism::DYNAMIC_BOUND,
199 [data_ptr, &deleter_called](void*) mutable { deleter_called = true; });
200
201 EXPECT_EQ(data_ptr.use_count(), 2);
202
203 tensor.reset();
204 EXPECT_TRUE(deleter_called);
205 EXPECT_EQ(data_ptr.use_count(), 1);
206 }
207
TEST_F(TensorPtrTest,TensorOwningData)208 TEST_F(TensorPtrTest, TensorOwningData) {
209 auto tensor = make_tensor_ptr(
210 {2, 5},
211 {1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f, 7.0f, 8.0f, 9.0f, 10.0f},
212 {1, 0},
213 {1, 2});
214
215 EXPECT_EQ(tensor->dim(), 2);
216 EXPECT_EQ(tensor->size(0), 2);
217 EXPECT_EQ(tensor->size(1), 5);
218 EXPECT_EQ(tensor->strides()[0], 1);
219 EXPECT_EQ(tensor->strides()[1], 2);
220 EXPECT_EQ(tensor->const_data_ptr<float>()[0], 1.0f);
221 EXPECT_EQ(tensor->const_data_ptr<float>()[9], 10.0f);
222 }
223
TEST_F(TensorPtrTest,TensorOwningEmptyData)224 TEST_F(TensorPtrTest, TensorOwningEmptyData) {
225 auto tensor = make_tensor_ptr({0, 5}, std::vector<float>());
226
227 EXPECT_EQ(tensor->dim(), 2);
228 EXPECT_EQ(tensor->size(0), 0);
229 EXPECT_EQ(tensor->size(1), 5);
230 EXPECT_EQ(tensor->strides()[0], 5);
231 EXPECT_EQ(tensor->strides()[1], 1);
232 EXPECT_EQ(tensor->data_ptr<float>(), nullptr);
233 EXPECT_EQ(tensor->scalar_type(), exec_aten::ScalarType::Float);
234 }
235
TEST_F(TensorPtrTest,TensorDataOnly)236 TEST_F(TensorPtrTest, TensorDataOnly) {
237 auto tensor = make_tensor_ptr({1.0f, 2.0f, 3.0f, 4.0f});
238
239 EXPECT_EQ(tensor->dim(), 1);
240 EXPECT_EQ(tensor->size(0), 4);
241 EXPECT_EQ(tensor->strides()[0], 1);
242 EXPECT_EQ(tensor->const_data_ptr<float>()[0], 1.0);
243 EXPECT_EQ(tensor->const_data_ptr<float>()[3], 4.0);
244 EXPECT_EQ(tensor->scalar_type(), exec_aten::ScalarType::Float);
245 }
246
TEST_F(TensorPtrTest,TensorDataOnlyDoubleType)247 TEST_F(TensorPtrTest, TensorDataOnlyDoubleType) {
248 std::vector<double> data = {1.0, 2.0, 3.0, 4.0};
249 auto tensor = make_tensor_ptr(std::move(data));
250
251 EXPECT_EQ(tensor->dim(), 1);
252 EXPECT_EQ(tensor->size(0), 4);
253 EXPECT_EQ(tensor->strides()[0], 1);
254 EXPECT_EQ(tensor->const_data_ptr<double>()[0], 1.0);
255 EXPECT_EQ(tensor->const_data_ptr<double>()[3], 4.0);
256 EXPECT_EQ(tensor->scalar_type(), exec_aten::ScalarType::Double);
257 }
258
TEST_F(TensorPtrTest,TensorDataOnlyInt32Type)259 TEST_F(TensorPtrTest, TensorDataOnlyInt32Type) {
260 std::vector<int32_t> data = {10, 20, 30, 40};
261 auto tensor = make_tensor_ptr(std::move(data));
262
263 EXPECT_EQ(tensor->dim(), 1);
264 EXPECT_EQ(tensor->size(0), 4);
265 EXPECT_EQ(tensor->strides()[0], 1);
266 EXPECT_EQ(tensor->const_data_ptr<int32_t>()[0], 10);
267 EXPECT_EQ(tensor->const_data_ptr<int32_t>()[3], 40);
268 EXPECT_EQ(tensor->scalar_type(), exec_aten::ScalarType::Int);
269 }
270
TEST_F(TensorPtrTest,TensorDataOnlyInt64Type)271 TEST_F(TensorPtrTest, TensorDataOnlyInt64Type) {
272 std::vector<int64_t> data = {100, 200, 300, 400};
273 auto tensor = make_tensor_ptr(std::move(data));
274
275 EXPECT_EQ(tensor->dim(), 1);
276 EXPECT_EQ(tensor->size(0), 4);
277 EXPECT_EQ(tensor->strides()[0], 1);
278 EXPECT_EQ(tensor->const_data_ptr<int64_t>()[0], 100);
279 EXPECT_EQ(tensor->const_data_ptr<int64_t>()[3], 400);
280 EXPECT_EQ(tensor->scalar_type(), exec_aten::ScalarType::Long);
281 }
282
TEST_F(TensorPtrTest,TensorDataOnlyUint8Type)283 TEST_F(TensorPtrTest, TensorDataOnlyUint8Type) {
284 std::vector<uint8_t> data = {10, 20, 30, 40};
285 auto tensor = make_tensor_ptr(std::move(data));
286
287 EXPECT_EQ(tensor->dim(), 1);
288 EXPECT_EQ(tensor->size(0), 4);
289 EXPECT_EQ(tensor->strides()[0], 1);
290 EXPECT_EQ(tensor->const_data_ptr<uint8_t>()[0], 10);
291 EXPECT_EQ(tensor->const_data_ptr<uint8_t>()[3], 40);
292 EXPECT_EQ(tensor->scalar_type(), exec_aten::ScalarType::Byte);
293 }
294
TEST_F(TensorPtrTest,TensorAmbiguityWithMixedVectors)295 TEST_F(TensorPtrTest, TensorAmbiguityWithMixedVectors) {
296 std::vector<exec_aten::SizesType> sizes = {2, 2};
297 std::vector<float> data = {1.0f, 2.0f, 3.0f, 4.0f};
298 auto tensor = make_tensor_ptr(std::move(sizes), std::move(data));
299
300 EXPECT_EQ(tensor->dim(), 2);
301 EXPECT_EQ(tensor->size(0), 2);
302 EXPECT_EQ(tensor->size(1), 2);
303 EXPECT_EQ(tensor->strides()[0], 2);
304 EXPECT_EQ(tensor->strides()[1], 1);
305 EXPECT_EQ(tensor->const_data_ptr<float>()[0], 1.0f);
306 EXPECT_EQ(tensor->const_data_ptr<float>()[3], 4.0f);
307
308 auto tensor2 = make_tensor_ptr({2, 2}, {1.0f, 2.0f, 3.0f, 4.0f});
309
310 EXPECT_EQ(tensor2->dim(), 2);
311 EXPECT_EQ(tensor2->size(0), 2);
312 EXPECT_EQ(tensor2->size(1), 2);
313 EXPECT_EQ(tensor2->strides()[0], 2);
314 EXPECT_EQ(tensor2->strides()[1], 1);
315 EXPECT_EQ(tensor2->const_data_ptr<float>()[0], 1.0f);
316 EXPECT_EQ(tensor2->const_data_ptr<float>()[3], 4.0f);
317 }
318
TEST_F(TensorPtrTest,TensorSharingImplModifiesSharedDataVector)319 TEST_F(TensorPtrTest, TensorSharingImplModifiesSharedDataVector) {
320 std::vector<float> data = {1, 2, 3, 4, 5, 6};
321
322 auto tensor1 = make_tensor_ptr({2, 3}, std::move(data));
323 auto tensor2 = tensor1;
324
325 tensor1->mutable_data_ptr<float>()[0] = 10;
326 EXPECT_EQ(tensor2->const_data_ptr<float>()[0], 10);
327
328 tensor2->mutable_data_ptr<float>()[5] = 20;
329 EXPECT_EQ(tensor1->const_data_ptr<float>()[5], 20);
330 }
331
TEST_F(TensorPtrTest,TensorSharingImplResizingAffectsBothVector)332 TEST_F(TensorPtrTest, TensorSharingImplResizingAffectsBothVector) {
333 std::vector<float> data = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12};
334
335 auto tensor1 = make_tensor_ptr({3, 4}, std::move(data));
336 auto tensor2 = tensor1;
337
338 EXPECT_EQ(resize_tensor_ptr(tensor1, {2, 6}), Error::Ok);
339 EXPECT_EQ(tensor2->size(0), 2);
340 EXPECT_EQ(tensor2->size(1), 6);
341
342 EXPECT_EQ(resize_tensor_ptr(tensor2, {4, 3}), Error::Ok);
343 EXPECT_EQ(tensor1->size(0), 4);
344 EXPECT_EQ(tensor1->size(1), 3);
345 }
346
TEST_F(TensorPtrTest,MakeTensorPtrFromExistingTensorInt32)347 TEST_F(TensorPtrTest, MakeTensorPtrFromExistingTensorInt32) {
348 std::vector<int32_t> data = {1, 2, 3, 4};
349 auto tensor = make_tensor_ptr({2, 2}, data);
350 auto new_tensor = make_tensor_ptr(*tensor);
351
352 EXPECT_EQ(new_tensor->dim(), tensor->dim());
353 EXPECT_EQ(new_tensor->size(0), tensor->size(0));
354 EXPECT_EQ(new_tensor->size(1), tensor->size(1));
355 EXPECT_EQ(
356 new_tensor->const_data_ptr<int32_t>(), tensor->const_data_ptr<int32_t>());
357 EXPECT_EQ(new_tensor->scalar_type(), exec_aten::ScalarType::Int);
358 }
359
TEST_F(TensorPtrTest,CloneTensorPtrFromExistingTensorInt32)360 TEST_F(TensorPtrTest, CloneTensorPtrFromExistingTensorInt32) {
361 std::vector<int32_t> data = {1, 2, 3, 4};
362 auto tensor = make_tensor_ptr({2, 2}, std::move(data));
363 auto cloned_tensor = clone_tensor_ptr(*tensor);
364
365 EXPECT_EQ(cloned_tensor->dim(), tensor->dim());
366 EXPECT_EQ(cloned_tensor->size(0), tensor->size(0));
367 EXPECT_EQ(cloned_tensor->size(1), tensor->size(1));
368 EXPECT_NE(
369 cloned_tensor->const_data_ptr<int32_t>(),
370 tensor->const_data_ptr<int32_t>());
371 EXPECT_EQ(cloned_tensor->const_data_ptr<int32_t>()[0], 1);
372 EXPECT_EQ(cloned_tensor->const_data_ptr<int32_t>()[3], 4);
373 EXPECT_EQ(cloned_tensor->scalar_type(), exec_aten::ScalarType::Int);
374 }
375
TEST_F(TensorPtrTest,CloneTensorPtrFromTensorPtrInt32)376 TEST_F(TensorPtrTest, CloneTensorPtrFromTensorPtrInt32) {
377 std::vector<int32_t> data = {1, 2, 3, 4};
378 auto tensor = make_tensor_ptr({2, 2}, std::move(data));
379 auto cloned_tensor = clone_tensor_ptr(tensor);
380
381 EXPECT_EQ(cloned_tensor->dim(), tensor->dim());
382 EXPECT_EQ(cloned_tensor->size(0), tensor->size(0));
383 EXPECT_EQ(cloned_tensor->size(1), tensor->size(1));
384 EXPECT_NE(
385 cloned_tensor->const_data_ptr<int32_t>(),
386 tensor->const_data_ptr<int32_t>());
387 EXPECT_EQ(cloned_tensor->const_data_ptr<int32_t>()[0], 1);
388 EXPECT_EQ(cloned_tensor->const_data_ptr<int32_t>()[3], 4);
389 EXPECT_EQ(cloned_tensor->scalar_type(), exec_aten::ScalarType::Int);
390 }
391
TEST_F(TensorPtrTest,MakeTensorPtrFromExistingTensorDouble)392 TEST_F(TensorPtrTest, MakeTensorPtrFromExistingTensorDouble) {
393 std::vector<double> data = {1.0, 2.0, 3.0, 4.0};
394 auto tensor = make_tensor_ptr({2, 2}, data);
395 auto new_tensor = make_tensor_ptr(*tensor);
396
397 EXPECT_EQ(new_tensor->dim(), tensor->dim());
398 EXPECT_EQ(new_tensor->size(0), tensor->size(0));
399 EXPECT_EQ(new_tensor->size(1), tensor->size(1));
400 EXPECT_EQ(
401 new_tensor->const_data_ptr<double>(), tensor->const_data_ptr<double>());
402 EXPECT_EQ(new_tensor->scalar_type(), exec_aten::ScalarType::Double);
403 }
404
TEST_F(TensorPtrTest,CloneTensorPtrFromExistingTensorDouble)405 TEST_F(TensorPtrTest, CloneTensorPtrFromExistingTensorDouble) {
406 std::vector<double> data = {1.0, 2.0, 3.0, 4.0};
407 auto tensor = make_tensor_ptr({2, 2}, std::move(data));
408 auto cloned_tensor = clone_tensor_ptr(*tensor);
409
410 EXPECT_EQ(cloned_tensor->dim(), tensor->dim());
411 EXPECT_EQ(cloned_tensor->size(0), tensor->size(0));
412 EXPECT_EQ(cloned_tensor->size(1), tensor->size(1));
413 EXPECT_NE(
414 cloned_tensor->const_data_ptr<double>(),
415 tensor->const_data_ptr<double>());
416 EXPECT_EQ(cloned_tensor->const_data_ptr<double>()[0], 1.0);
417 EXPECT_EQ(cloned_tensor->const_data_ptr<double>()[3], 4.0);
418 EXPECT_EQ(cloned_tensor->scalar_type(), exec_aten::ScalarType::Double);
419 }
420
TEST_F(TensorPtrTest,CloneTensorPtrFromTensorPtrDouble)421 TEST_F(TensorPtrTest, CloneTensorPtrFromTensorPtrDouble) {
422 std::vector<double> data = {1.0, 2.0, 3.0, 4.0};
423 auto tensor = make_tensor_ptr({2, 2}, std::move(data));
424 auto cloned_tensor = clone_tensor_ptr(tensor);
425
426 EXPECT_EQ(cloned_tensor->dim(), tensor->dim());
427 EXPECT_EQ(cloned_tensor->size(0), tensor->size(0));
428 EXPECT_EQ(cloned_tensor->size(1), tensor->size(1));
429 EXPECT_NE(
430 cloned_tensor->const_data_ptr<double>(),
431 tensor->const_data_ptr<double>());
432 EXPECT_EQ(cloned_tensor->const_data_ptr<double>()[0], 1.0);
433 EXPECT_EQ(cloned_tensor->const_data_ptr<double>()[3], 4.0);
434 EXPECT_EQ(cloned_tensor->scalar_type(), exec_aten::ScalarType::Double);
435 }
436
TEST_F(TensorPtrTest,MakeTensorPtrFromExistingTensorInt64)437 TEST_F(TensorPtrTest, MakeTensorPtrFromExistingTensorInt64) {
438 std::vector<int64_t> data = {100, 200, 300, 400};
439 auto tensor = make_tensor_ptr({2, 2}, data);
440 auto new_tensor = make_tensor_ptr(*tensor);
441
442 EXPECT_EQ(new_tensor->dim(), tensor->dim());
443 EXPECT_EQ(new_tensor->size(0), tensor->size(0));
444 EXPECT_EQ(new_tensor->size(1), tensor->size(1));
445 EXPECT_EQ(
446 new_tensor->const_data_ptr<int64_t>(), tensor->const_data_ptr<int64_t>());
447 EXPECT_EQ(new_tensor->scalar_type(), exec_aten::ScalarType::Long);
448 }
449
TEST_F(TensorPtrTest,CloneTensorPtrFromExistingTensorInt64)450 TEST_F(TensorPtrTest, CloneTensorPtrFromExistingTensorInt64) {
451 std::vector<int64_t> data = {100, 200, 300, 400};
452 auto tensor = make_tensor_ptr({2, 2}, std::move(data));
453 auto cloned_tensor = clone_tensor_ptr(*tensor);
454
455 EXPECT_EQ(cloned_tensor->dim(), tensor->dim());
456 EXPECT_EQ(cloned_tensor->size(0), tensor->size(0));
457 EXPECT_EQ(cloned_tensor->size(1), tensor->size(1));
458 EXPECT_NE(
459 cloned_tensor->const_data_ptr<int64_t>(),
460 tensor->const_data_ptr<int64_t>());
461 EXPECT_EQ(cloned_tensor->const_data_ptr<int64_t>()[0], 100);
462 EXPECT_EQ(cloned_tensor->const_data_ptr<int64_t>()[3], 400);
463 EXPECT_EQ(cloned_tensor->scalar_type(), exec_aten::ScalarType::Long);
464 }
465
TEST_F(TensorPtrTest,CloneTensorPtrFromTensorPtrInt64)466 TEST_F(TensorPtrTest, CloneTensorPtrFromTensorPtrInt64) {
467 std::vector<int64_t> data = {100, 200, 300, 400};
468 auto tensor = make_tensor_ptr({2, 2}, std::move(data));
469 auto cloned_tensor = clone_tensor_ptr(tensor);
470
471 EXPECT_EQ(cloned_tensor->dim(), tensor->dim());
472 EXPECT_EQ(cloned_tensor->size(0), tensor->size(0));
473 EXPECT_EQ(cloned_tensor->size(1), tensor->size(1));
474 EXPECT_NE(
475 cloned_tensor->const_data_ptr<int64_t>(),
476 tensor->const_data_ptr<int64_t>());
477 EXPECT_EQ(cloned_tensor->const_data_ptr<int64_t>()[0], 100);
478 EXPECT_EQ(cloned_tensor->const_data_ptr<int64_t>()[3], 400);
479 EXPECT_EQ(cloned_tensor->scalar_type(), exec_aten::ScalarType::Long);
480 }
481
TEST_F(TensorPtrTest,CloneTensorPtrFromTensorPtrNull)482 TEST_F(TensorPtrTest, CloneTensorPtrFromTensorPtrNull) {
483 auto tensor = make_tensor_ptr({2, 2}, nullptr);
484 auto cloned_tensor = clone_tensor_ptr(tensor);
485
486 EXPECT_EQ(cloned_tensor->dim(), tensor->dim());
487 EXPECT_EQ(cloned_tensor->size(0), tensor->size(0));
488 EXPECT_EQ(cloned_tensor->size(1), tensor->size(1));
489 EXPECT_EQ(cloned_tensor->const_data_ptr(), tensor->const_data_ptr());
490 EXPECT_EQ(cloned_tensor->const_data_ptr(), nullptr);
491 }
492
TEST_F(TensorPtrTest,TensorDataCastingFromIntToFloat)493 TEST_F(TensorPtrTest, TensorDataCastingFromIntToFloat) {
494 std::vector<int32_t> int_data = {1, 2, 3, 4, 5, 6};
495 auto tensor = make_tensor_ptr(
496 {2, 3}, std::move(int_data), {}, {}, exec_aten::ScalarType::Float);
497
498 EXPECT_EQ(tensor->dim(), 2);
499 EXPECT_EQ(tensor->size(0), 2);
500 EXPECT_EQ(tensor->size(1), 3);
501 EXPECT_EQ(tensor->scalar_type(), exec_aten::ScalarType::Float);
502
503 auto data_ptr = tensor->const_data_ptr<float>();
504 EXPECT_FLOAT_EQ(data_ptr[0], 1.0f);
505 EXPECT_FLOAT_EQ(data_ptr[5], 6.0f);
506 }
507
TEST_F(TensorPtrTest,TensorDataCastingFromIntToDouble)508 TEST_F(TensorPtrTest, TensorDataCastingFromIntToDouble) {
509 std::vector<int32_t> int_data = {1, 2, 3};
510 auto tensor =
511 make_tensor_ptr(std::move(int_data), exec_aten::ScalarType::Double);
512
513 EXPECT_EQ(tensor->dim(), 1);
514 EXPECT_EQ(tensor->size(0), 3);
515 EXPECT_EQ(tensor->scalar_type(), exec_aten::ScalarType::Double);
516
517 auto data_ptr = tensor->const_data_ptr<double>();
518 EXPECT_DOUBLE_EQ(data_ptr[0], 1.0);
519 EXPECT_DOUBLE_EQ(data_ptr[1], 2.0);
520 EXPECT_DOUBLE_EQ(data_ptr[2], 3.0);
521 }
522
TEST_F(TensorPtrTest,TensorDataCastingFromFloatToHalf)523 TEST_F(TensorPtrTest, TensorDataCastingFromFloatToHalf) {
524 std::vector<float> float_data = {1.0f, 2.0f, 3.0f};
525 auto tensor =
526 make_tensor_ptr(std::move(float_data), exec_aten::ScalarType::Half);
527
528 EXPECT_EQ(tensor->dim(), 1);
529 EXPECT_EQ(tensor->size(0), 3);
530 EXPECT_EQ(tensor->scalar_type(), exec_aten::ScalarType::Half);
531
532 auto data_ptr = tensor->const_data_ptr<exec_aten::Half>();
533 EXPECT_EQ(static_cast<float>(data_ptr[0]), 1.0f);
534 EXPECT_EQ(static_cast<float>(data_ptr[1]), 2.0f);
535 EXPECT_EQ(static_cast<float>(data_ptr[2]), 3.0f);
536 }
537
TEST_F(TensorPtrTest,TensorDataCastingFromDoubleToFloat)538 TEST_F(TensorPtrTest, TensorDataCastingFromDoubleToFloat) {
539 std::vector<double> double_data = {1.1, 2.2, 3.3};
540 auto tensor =
541 make_tensor_ptr(std::move(double_data), exec_aten::ScalarType::Float);
542
543 EXPECT_EQ(tensor->dim(), 1);
544 EXPECT_EQ(tensor->size(0), 3);
545 EXPECT_EQ(tensor->scalar_type(), exec_aten::ScalarType::Float);
546
547 auto data_ptr = tensor->const_data_ptr<float>();
548 EXPECT_FLOAT_EQ(data_ptr[0], 1.1f);
549 EXPECT_FLOAT_EQ(data_ptr[1], 2.2f);
550 EXPECT_FLOAT_EQ(data_ptr[2], 3.3f);
551 }
552
TEST_F(TensorPtrTest,TensorDataCastingFromInt64ToInt32)553 TEST_F(TensorPtrTest, TensorDataCastingFromInt64ToInt32) {
554 std::vector<int64_t> int64_data = {10000000000, 20000000000, 30000000000};
555 auto tensor =
556 make_tensor_ptr(std::move(int64_data), exec_aten::ScalarType::Int);
557
558 EXPECT_EQ(tensor->dim(), 1);
559 EXPECT_EQ(tensor->size(0), 3);
560 EXPECT_EQ(tensor->scalar_type(), exec_aten::ScalarType::Int);
561
562 auto data_ptr = tensor->const_data_ptr<int32_t>();
563 EXPECT_NE(data_ptr[0], 10000000000); // Expected overflow
564 }
565
TEST_F(TensorPtrTest,TensorDataCastingFromFloatToBFloat16)566 TEST_F(TensorPtrTest, TensorDataCastingFromFloatToBFloat16) {
567 std::vector<float> float_data = {1.0f, 2.0f, 3.0f};
568 auto tensor =
569 make_tensor_ptr(std::move(float_data), exec_aten::ScalarType::BFloat16);
570
571 EXPECT_EQ(tensor->dim(), 1);
572 EXPECT_EQ(tensor->size(0), 3);
573 EXPECT_EQ(tensor->scalar_type(), exec_aten::ScalarType::BFloat16);
574
575 auto data_ptr = tensor->const_data_ptr<exec_aten::BFloat16>();
576 EXPECT_EQ(static_cast<float>(data_ptr[0]), 1.0f);
577 EXPECT_EQ(static_cast<float>(data_ptr[1]), 2.0f);
578 EXPECT_EQ(static_cast<float>(data_ptr[2]), 3.0f);
579 }
580
TEST_F(TensorPtrTest,InitializerListDoubleToHalf)581 TEST_F(TensorPtrTest, InitializerListDoubleToHalf) {
582 auto tensor =
583 make_tensor_ptr<double>({1.5, 2.7, 3.14}, exec_aten::ScalarType::Half);
584 EXPECT_EQ(tensor->dim(), 1);
585 EXPECT_EQ(tensor->size(0), 3);
586 EXPECT_EQ(tensor->scalar_type(), exec_aten::ScalarType::Half);
587
588 auto data_ptr = tensor->const_data_ptr<exec_aten::Half>();
589 EXPECT_NEAR(static_cast<float>(data_ptr[0]), 1.5f, 0.01);
590 EXPECT_NEAR(static_cast<float>(data_ptr[1]), 2.7f, 0.01);
591 EXPECT_NEAR(static_cast<float>(data_ptr[2]), 3.14f, 0.01);
592 }
593
TEST_F(TensorPtrTest,InitializerListInt8ToInt64)594 TEST_F(TensorPtrTest, InitializerListInt8ToInt64) {
595 auto tensor =
596 make_tensor_ptr<int8_t>({1, -2, 3, -4}, exec_aten::ScalarType::Long);
597 EXPECT_EQ(tensor->dim(), 1);
598 EXPECT_EQ(tensor->size(0), 4);
599 EXPECT_EQ(tensor->scalar_type(), exec_aten::ScalarType::Long);
600
601 auto data_ptr = tensor->const_data_ptr<int64_t>();
602 EXPECT_EQ(data_ptr[0], 1);
603 EXPECT_EQ(data_ptr[1], -2);
604 EXPECT_EQ(data_ptr[2], 3);
605 EXPECT_EQ(data_ptr[3], -4);
606 }
607
TEST_F(TensorPtrTest,TensorInferredDimOrderAndStrides)608 TEST_F(TensorPtrTest, TensorInferredDimOrderAndStrides) {
609 float data[12] = {0};
610 auto tensor = make_tensor_ptr({3, 4}, data, {}, {4, 1});
611
612 EXPECT_EQ(tensor->dim(), 2);
613 EXPECT_EQ(tensor->size(0), 3);
614 EXPECT_EQ(tensor->size(1), 4);
615 EXPECT_EQ(tensor->strides()[0], 4);
616 EXPECT_EQ(tensor->strides()[1], 1);
617 EXPECT_EQ(tensor->const_data_ptr(), data);
618 }
619
TEST_F(TensorPtrTest,TensorInferredDimOrderCustomStrides)620 TEST_F(TensorPtrTest, TensorInferredDimOrderCustomStrides) {
621 float data[12] = {0};
622 auto tensor = make_tensor_ptr({3, 4}, data, {}, {1, 3});
623
624 EXPECT_EQ(tensor->dim(), 2);
625 EXPECT_EQ(tensor->size(0), 3);
626 EXPECT_EQ(tensor->size(1), 4);
627 EXPECT_EQ(tensor->strides()[0], 1);
628 EXPECT_EQ(tensor->strides()[1], 3);
629 }
630
TEST_F(TensorPtrTest,TensorDefaultDimOrderAndStrides)631 TEST_F(TensorPtrTest, TensorDefaultDimOrderAndStrides) {
632 float data[24] = {0};
633 auto tensor = make_tensor_ptr({2, 3, 4}, data);
634
635 EXPECT_EQ(tensor->dim(), 3);
636 EXPECT_EQ(tensor->size(0), 2);
637 EXPECT_EQ(tensor->size(1), 3);
638 EXPECT_EQ(tensor->size(2), 4);
639 EXPECT_EQ(tensor->strides()[0], 12);
640 EXPECT_EQ(tensor->strides()[1], 4);
641 EXPECT_EQ(tensor->strides()[2], 1);
642 }
643
TEST_F(TensorPtrTest,TensorMismatchStridesAndDimOrder)644 TEST_F(TensorPtrTest, TensorMismatchStridesAndDimOrder) {
645 float data[12] = {0};
646 ET_EXPECT_DEATH(
647 { auto _ = make_tensor_ptr({3, 4}, data, {1, 0}, {1, 4}); }, "");
648 }
649
TEST_F(TensorPtrTest,TensorCustomDimOrderAndStrides)650 TEST_F(TensorPtrTest, TensorCustomDimOrderAndStrides) {
651 float data[12] = {0};
652 auto tensor = make_tensor_ptr({3, 4}, data, {1, 0}, {1, 3});
653
654 EXPECT_EQ(tensor->dim(), 2);
655 EXPECT_EQ(tensor->size(0), 3);
656 EXPECT_EQ(tensor->size(1), 4);
657 EXPECT_EQ(tensor->strides()[0], 1);
658 EXPECT_EQ(tensor->strides()[1], 3);
659 }
660
TEST_F(TensorPtrTest,TensorInvalidDimOrder)661 TEST_F(TensorPtrTest, TensorInvalidDimOrder) {
662 ET_EXPECT_DEATH(
663 {
664 float data[20] = {2};
665 auto _ = make_tensor_ptr({4, 5}, data, {2, 1}, {1, 4});
666 },
667 "");
668 }
669
TEST_F(TensorPtrTest,TensorCustomDeleter)670 TEST_F(TensorPtrTest, TensorCustomDeleter) {
671 float data[20] = {4};
672 auto tensor = make_tensor_ptr({4, 5}, data);
673
674 TensorPtr copied_tensor = tensor;
675 EXPECT_EQ(tensor.use_count(), copied_tensor.use_count());
676
677 tensor.reset();
678 EXPECT_EQ(copied_tensor.use_count(), 1);
679 }
680
TEST_F(TensorPtrTest,TensorDataDeleterReleasesCapturedSharedPtr)681 TEST_F(TensorPtrTest, TensorDataDeleterReleasesCapturedSharedPtr) {
682 auto deleter_called = false;
683 std::shared_ptr<float[]> data_ptr(
684 new float[10], [](float* ptr) { delete[] ptr; });
685 auto tensor = make_tensor_ptr(
686 {4, 5},
687 data_ptr.get(),
688 {},
689 {},
690 exec_aten::ScalarType::Float,
691 exec_aten::TensorShapeDynamism::DYNAMIC_BOUND,
692 [data_ptr, &deleter_called](void*) mutable { deleter_called = true; });
693
694 EXPECT_EQ(data_ptr.use_count(), 2);
695
696 tensor.reset();
697 EXPECT_TRUE(deleter_called);
698 EXPECT_EQ(data_ptr.use_count(), 1);
699 }
700
TEST_F(TensorPtrTest,SharedDataManagement)701 TEST_F(TensorPtrTest, SharedDataManagement) {
702 auto data = std::make_shared<std::vector<float>>(100, 1.0f);
703 auto tensor1 = make_tensor_ptr({10, 10}, data->data());
704 auto tensor2 = tensor1;
705
706 EXPECT_EQ(tensor1.get(), tensor2.get());
707 EXPECT_EQ(tensor1.use_count(), 2);
708 EXPECT_EQ(tensor1->const_data_ptr<float>()[0], 1.0f);
709
710 tensor1->mutable_data_ptr<float>()[0] = 2.0f;
711 EXPECT_EQ(tensor1->const_data_ptr<float>()[0], 2.0f);
712
713 tensor1.reset();
714 EXPECT_NE(tensor2.get(), nullptr);
715 EXPECT_EQ(tensor2.use_count(), 1);
716
717 EXPECT_EQ(tensor2->const_data_ptr<float>()[0], 2.0f);
718 }
719
TEST_F(TensorPtrTest,CustomDeleterWithSharedData)720 TEST_F(TensorPtrTest, CustomDeleterWithSharedData) {
721 auto data = std::make_shared<std::vector<float>>(100, 1.0f);
722 bool deleter_called = false;
723 {
724 auto tensor = make_tensor_ptr(
725 {10, 10},
726 data->data(),
727 {},
728 {},
729 exec_aten::ScalarType::Float,
730 exec_aten::TensorShapeDynamism::DYNAMIC_BOUND,
731 [data, &deleter_called](void*) mutable {
732 deleter_called = true;
733 data.reset();
734 });
735
736 EXPECT_EQ(data.use_count(), 2);
737 EXPECT_FALSE(deleter_called);
738 }
739 EXPECT_TRUE(deleter_called);
740 EXPECT_EQ(data.use_count(), 1);
741 }
742
TEST_F(TensorPtrTest,TensorDeducedScalarType)743 TEST_F(TensorPtrTest, TensorDeducedScalarType) {
744 std::vector<double> data = {1.0, 2.0, 3.0, 4.0};
745 auto tensor = make_tensor_ptr({2, 2}, std::move(data));
746
747 EXPECT_EQ(tensor->dim(), 2);
748 EXPECT_EQ(tensor->size(0), 2);
749 EXPECT_EQ(tensor->size(1), 2);
750 EXPECT_EQ(tensor->strides()[0], 2);
751 EXPECT_EQ(tensor->strides()[1], 1);
752 EXPECT_EQ(tensor->const_data_ptr<double>()[0], 1.0);
753 EXPECT_EQ(tensor->const_data_ptr<double>()[3], 4.0);
754 }
755
TEST_F(TensorPtrTest,TensorUint8BufferWithFloatScalarType)756 TEST_F(TensorPtrTest, TensorUint8BufferWithFloatScalarType) {
757 std::vector<uint8_t> data(
758 4 * exec_aten::elementSize(exec_aten::ScalarType::Float));
759
760 float* float_data = reinterpret_cast<float*>(data.data());
761 float_data[0] = 1.0f;
762 float_data[1] = 2.0f;
763 float_data[2] = 3.0f;
764 float_data[3] = 4.0f;
765
766 auto tensor = make_tensor_ptr({2, 2}, std::move(data));
767
768 EXPECT_EQ(tensor->dim(), 2);
769 EXPECT_EQ(tensor->size(0), 2);
770 EXPECT_EQ(tensor->size(1), 2);
771 EXPECT_EQ(tensor->strides()[0], 2);
772 EXPECT_EQ(tensor->strides()[1], 1);
773
774 EXPECT_EQ(tensor->const_data_ptr<float>()[0], 1.0f);
775 EXPECT_EQ(tensor->const_data_ptr<float>()[1], 2.0f);
776 EXPECT_EQ(tensor->const_data_ptr<float>()[2], 3.0f);
777 EXPECT_EQ(tensor->const_data_ptr<float>()[3], 4.0f);
778 }
779
TEST_F(TensorPtrTest,TensorUint8BufferTooSmallExpectDeath)780 TEST_F(TensorPtrTest, TensorUint8BufferTooSmallExpectDeath) {
781 std::vector<uint8_t> data(
782 2 * exec_aten::elementSize(exec_aten::ScalarType::Float));
783 ET_EXPECT_DEATH(
784 { auto tensor = make_tensor_ptr({2, 2}, std::move(data)); }, "");
785 }
786
TEST_F(TensorPtrTest,TensorUint8BufferTooLarge)787 TEST_F(TensorPtrTest, TensorUint8BufferTooLarge) {
788 std::vector<uint8_t> data(
789 4 * exec_aten::elementSize(exec_aten::ScalarType::Float));
790 auto tensor = make_tensor_ptr({2, 2}, std::move(data));
791
792 EXPECT_EQ(tensor->dim(), 2);
793 EXPECT_EQ(tensor->size(0), 2);
794 EXPECT_EQ(tensor->size(1), 2);
795 EXPECT_EQ(tensor->strides()[0], 2);
796 EXPECT_EQ(tensor->strides()[1], 1);
797 }
798
TEST_F(TensorPtrTest,StridesAndDimOrderMustMatchSizes)799 TEST_F(TensorPtrTest, StridesAndDimOrderMustMatchSizes) {
800 float data[12] = {0};
801 ET_EXPECT_DEATH({ auto _ = make_tensor_ptr({3, 4}, data, {}, {1}); }, "");
802 ET_EXPECT_DEATH({ auto _ = make_tensor_ptr({3, 4}, data, {0}, {4, 1}); }, "");
803 }
804
TEST_F(TensorPtrTest,TensorDataCastingInvalidCast)805 TEST_F(TensorPtrTest, TensorDataCastingInvalidCast) {
806 std::vector<float> float_data = {1.0f, 2.0f, 3.0f};
807 ET_EXPECT_DEATH(
808 {
809 auto _ =
810 make_tensor_ptr(std::move(float_data), exec_aten::ScalarType::Int);
811 },
812 "");
813 }
814