@@ -21,6 +21,9 @@ using namespace ::testing;
2121using executorch::runtime::ArrayRef;
2222using executorch::runtime::Error;
2323using executorch::runtime::TensorShapeDynamism;
24+ using executorch::runtime::etensor::Device;
25+ using executorch::runtime::etensor::DeviceIndex;
26+ using executorch::runtime::etensor::DeviceType;
2427using executorch::runtime::etensor::ScalarType;
2528using executorch::runtime::etensor::TensorImpl;
2629using SizesType = TensorImpl::SizesType;
@@ -449,3 +452,155 @@ TEST_F(TensorImplTest, TestResizingTensorToZeroAndBack) {
449452 EXPECT_GT (t.numel (), 0 );
450453 EXPECT_EQ (t.data (), data);
451454}
455+
456+ // ============== Size Tests ==============
457+
458+ TEST_F (TensorImplTest, TestTensorImplSize) {
459+ // Verify TensorImpl size hasn't regressed after adding Device member.
460+ // Device (2 bytes) fits within existing padding after type_ and
461+ // shape_dynamism_, so sizeof(TensorImpl) should remain unchanged.
462+ //
463+ // Memory layout (64-bit):
464+ // sizes_ : 8 bytes (pointer)
465+ // dim_order_ : 8 bytes (pointer)
466+ // strides_ : 8 bytes (pointer)
467+ // data_ : 8 bytes (pointer)
468+ // dim_ : 8 bytes (ssize_t)
469+ // numel_ : 8 bytes (ssize_t)
470+ // numel_bound_ : 8 bytes (size_t)
471+ // type_ : 1 byte (ScalarType : int8_t)
472+ // shape_dynamism_ : 1 byte (TensorShapeDynamism : uint8_t)
473+ // device_ : 2 bytes (Device: DeviceType + DeviceIndex)
474+ // padding : 4 bytes (to align struct to 8 bytes)
475+ // Total : 64 bytes
476+ //
477+ // Memory layout (32-bit):
478+ // sizes_ : 4 bytes (pointer)
479+ // dim_order_ : 4 bytes (pointer)
480+ // strides_ : 4 bytes (pointer)
481+ // data_ : 4 bytes (pointer)
482+ // dim_ : 4 bytes (ssize_t)
483+ // numel_ : 4 bytes (ssize_t)
484+ // numel_bound_ : 4 bytes (size_t)
485+ // type_ : 1 byte (ScalarType : int8_t)
486+ // shape_dynamism_ : 1 byte (TensorShapeDynamism : uint8_t)
487+ // device_ : 2 bytes (Device: DeviceType + DeviceIndex)
488+ // Total : 32 bytes (no additional padding needed)
489+
490+ #if INTPTR_MAX == INT64_MAX
491+ // 64-bit architecture
492+ EXPECT_EQ (sizeof (TensorImpl), 64 );
493+ #else
494+ // 32-bit architecture
495+ EXPECT_EQ (sizeof (TensorImpl), 32 );
496+ #endif
497+ }
498+
499+ // ============== Device Tests ==============
500+
501+ TEST_F (TensorImplTest, TestDefaultDeviceIsCPU) {
502+ // TensorImpl constructed without device parameters should default to CPU
503+ SizesType sizes[2 ] = {3 , 2 };
504+ float data[6 ] = {1.0 , 2.0 , 3.0 , 4.0 , 5.0 , 6.0 };
505+ TensorImpl t (ScalarType::Float, 2 , sizes, data);
506+
507+ EXPECT_EQ (t.device_type (), DeviceType::CPU);
508+ EXPECT_EQ (t.device_index (), 0 );
509+ EXPECT_EQ (t.device (), Device (DeviceType::CPU, 0 ));
510+ }
511+
512+ TEST_F (TensorImplTest, TestExplicitCPUDevice) {
513+ // TensorImpl constructed with explicit CPU device
514+ SizesType sizes[2 ] = {3 , 2 };
515+ DimOrderType dim_order[2 ] = {0 , 1 };
516+ StridesType strides[2 ] = {2 , 1 };
517+ float data[6 ] = {1.0 , 2.0 , 3.0 , 4.0 , 5.0 , 6.0 };
518+ TensorImpl t (
519+ ScalarType::Float,
520+ 2 ,
521+ sizes,
522+ data,
523+ dim_order,
524+ strides,
525+ TensorShapeDynamism::STATIC,
526+ DeviceType::CPU,
527+ 0 );
528+
529+ EXPECT_EQ (t.device_type (), DeviceType::CPU);
530+ EXPECT_EQ (t.device_index (), 0 );
531+ EXPECT_EQ (t.device (), Device (DeviceType::CPU, 0 ));
532+ }
533+
534+ TEST_F (TensorImplTest, TestCUDADevice) {
535+ // TensorImpl constructed with CUDA device
536+ SizesType sizes[2 ] = {3 , 2 };
537+ DimOrderType dim_order[2 ] = {0 , 1 };
538+ StridesType strides[2 ] = {2 , 1 };
539+ float data[6 ] = {1.0 , 2.0 , 3.0 , 4.0 , 5.0 , 6.0 };
540+ TensorImpl t (
541+ ScalarType::Float,
542+ 2 ,
543+ sizes,
544+ data,
545+ dim_order,
546+ strides,
547+ TensorShapeDynamism::STATIC,
548+ DeviceType::CUDA,
549+ 0 );
550+
551+ EXPECT_EQ (t.device_type (), DeviceType::CUDA);
552+ EXPECT_EQ (t.device_index (), 0 );
553+ EXPECT_EQ (t.device (), Device (DeviceType::CUDA, 0 ));
554+ }
555+
556+ TEST_F (TensorImplTest, TestCUDADeviceMultiGPU) {
557+ // TensorImpl with CUDA device index 1 (second GPU)
558+ SizesType sizes[2 ] = {3 , 2 };
559+ DimOrderType dim_order[2 ] = {0 , 1 };
560+ StridesType strides[2 ] = {2 , 1 };
561+ float data[6 ] = {1.0 , 2.0 , 3.0 , 4.0 , 5.0 , 6.0 };
562+ TensorImpl t (
563+ ScalarType::Float,
564+ 2 ,
565+ sizes,
566+ data,
567+ dim_order,
568+ strides,
569+ TensorShapeDynamism::STATIC,
570+ DeviceType::CUDA,
571+ 1 );
572+
573+ EXPECT_EQ (t.device_type (), DeviceType::CUDA);
574+ EXPECT_EQ (t.device_index (), 1 );
575+ EXPECT_EQ (t.device (), Device (DeviceType::CUDA, 1 ));
576+ }
577+
578+ TEST_F (TensorImplTest, TestDeviceWithDynamicTensor) {
579+ // Device info should work correctly with dynamic tensors
580+ SizesType sizes[2 ] = {3 , 2 };
581+ DimOrderType dim_order[2 ] = {0 , 1 };
582+ StridesType strides[2 ] = {2 , 1 };
583+ float data[6 ] = {1.0 , 2.0 , 3.0 , 4.0 , 5.0 , 6.0 };
584+ TensorImpl t (
585+ ScalarType::Float,
586+ 2 ,
587+ sizes,
588+ data,
589+ dim_order,
590+ strides,
591+ TensorShapeDynamism::DYNAMIC_BOUND,
592+ DeviceType::CUDA,
593+ 0 );
594+
595+ EXPECT_EQ (t.device_type (), DeviceType::CUDA);
596+ EXPECT_EQ (t.device_index (), 0 );
597+
598+ // Resize should not affect device
599+ SizesType new_sizes[2 ] = {2 , 2 };
600+ Error err = resize_tensor_impl (&t, {new_sizes, 2 });
601+ EXPECT_EQ (err, Error::Ok);
602+
603+ // Device should remain unchanged after resize
604+ EXPECT_EQ (t.device_type (), DeviceType::CUDA);
605+ EXPECT_EQ (t.device_index (), 0 );
606+ }
0 commit comments