1616
1717using namespace ::testing;
1818
19+ using executorch::aten::DeviceType;
20+ using executorch::aten::Layout;
21+ using executorch::aten::MemoryFormat;
1922using executorch::aten::ScalarType;
2023using executorch::runtime::BoxedEvalueList;
24+ using executorch::runtime::Error;
2125using executorch::runtime::EValue;
2226using executorch::runtime::Tag;
2327using executorch::runtime::testing::TensorFactory;
@@ -239,8 +243,7 @@ TEST_F(EValueTest, BoxedEvalueListTryGetWrongElementTag) {
239243}
240244
241245TEST_F (EValueTest, BoxedEvalueListTryGetNullElement) {
242- // A null wrapped pointer is a malformed program for non-optional lists;
243- // tryGet reports InvalidState rather than aborting inside ET_CHECK.
246+ // A null value is a malformed program for non-optional lists.
244247 EValue a ((int64_t )1 );
245248 EValue c ((int64_t )3 );
246249 EValue* values_p[3 ] = {&a, nullptr , &c};
@@ -251,8 +254,7 @@ TEST_F(EValueTest, BoxedEvalueListTryGetNullElement) {
251254}
252255
253256TEST_F (EValueTest, BoxedEvalueListTryGetOptionalTensorNullIsNone) {
254- // For the optional<Tensor> specialization, a null wrapped pointer is a
255- // valid None encoding (matches parseListOptionalType), not an error.
257+ // For optional<Tensor>, null value is valid.
256258 EValue a;
257259 EValue* values_p[2 ] = {&a, nullptr };
258260 std::optional<executorch::aten::Tensor> storage[2 ];
@@ -469,204 +471,115 @@ TEST_F(EValueTest, toListOptionalTensorNullPointerCheck) {
469471 ET_EXPECT_DEATH ({ e.toListOptionalTensor (); }, " pointer is null" );
470472}
471473
472- TEST_F (EValueTest, TryToTensorSuccess) {
473- TensorFactory<ScalarType::Float> tf;
474- EValue e (tf.ones ({3 , 2 }));
475- auto result = e.tryToTensor ();
476- EXPECT_TRUE (result.ok ());
477- EXPECT_EQ (result->dim (), 2 );
478- EXPECT_EQ (result->numel (), 6 );
479- }
480-
481- TEST_F (EValueTest, TryToTensorTypeMismatch) {
482- EValue e (static_cast <int64_t >(42 ));
483- auto result = e.tryToTensor ();
484- EXPECT_FALSE (result.ok ());
485- EXPECT_EQ (result.error (), executorch::runtime::Error::InvalidType);
486- }
487-
488- TEST_F (EValueTest, TryToOptionalTensorSuccess) {
489- TensorFactory<ScalarType::Float> tf;
490- EValue e (tf.ones ({3 , 2 }));
491- auto result = e.tryToOptional <executorch::aten::Tensor>();
492- EXPECT_TRUE (result.ok ());
493- EXPECT_TRUE (result->has_value ());
494- EXPECT_EQ (result->value ().dim (), 2 );
495- }
496-
497- TEST_F (EValueTest, TryToOptionalTensorNone) {
498- EValue e;
499- auto result = e.tryToOptional <executorch::aten::Tensor>();
500- EXPECT_TRUE (result.ok ());
501- EXPECT_FALSE (result->has_value ());
502- }
503-
504- TEST_F (EValueTest, TryToOptionalTensorTypeMismatch) {
505- EValue e (static_cast <int64_t >(42 ));
506- auto result = e.tryToOptional <executorch::aten::Tensor>();
507- EXPECT_FALSE (result.ok ());
508- EXPECT_EQ (result.error (), executorch::runtime::Error::InvalidType);
509- }
510-
511- // Scalar/primitive tryTo* coverage. The Success+TypeMismatch pair is
512- // identical per-type modulo the method name, so the macro below generates
513- // both tests. `match_value` should satisfy the isX() tag check; `mismatch_ev`
514- // must construct an EValue whose tag differs.
515- #define TRY_TO_PRIMITIVE_TEST (Name, Type, match_value, mismatch_ev ) \
516- TEST_F (EValueTest, TryTo##Name##Success) { \
517- EValue e (static_cast <Type>(match_value)); \
518- auto result = e.tryTo ##Name (); \
519- EXPECT_TRUE (result.ok ()); \
520- EXPECT_EQ (result.get (), static_cast <Type>(match_value)); \
521- } \
522- TEST_F (EValueTest, TryTo##Name##TypeMismatch) { \
523- EValue e (mismatch_ev); \
524- auto result = e.tryTo ##Name (); \
525- EXPECT_EQ (result.error (), executorch::runtime::Error::InvalidType); \
526- }
527-
528- TRY_TO_PRIMITIVE_TEST (Int, int64_t , 42 , 3.14 )
529- TRY_TO_PRIMITIVE_TEST(Double, double , 3.14 , static_cast <int64_t >(42 ))
530- TRY_TO_PRIMITIVE_TEST(Bool, bool , true , static_cast <int64_t >(42 ))
531-
532- #undef TRY_TO_PRIMITIVE_TEST
533-
534- TEST_F (EValueTest, TryToScalarFromInt) {
535- EValue e (static_cast <int64_t >(7 ));
536- auto result = e.tryToScalar ();
537- EXPECT_TRUE (result.ok ());
538- EXPECT_EQ (result->to <int64_t >(), 7 );
539- }
540-
541- TEST_F (EValueTest, TryToScalarFromDouble) {
542- EValue e (2.5 );
543- auto result = e.tryToScalar ();
544- EXPECT_TRUE (result.ok ());
545- EXPECT_DOUBLE_EQ (result->to <double >(), 2.5 );
546- }
547-
548- TEST_F (EValueTest, TryToScalarFromBool) {
549- EValue e (true );
550- auto result = e.tryToScalar ();
551- EXPECT_TRUE (result.ok ());
552- EXPECT_EQ (result->to <bool >(), true );
553- }
554-
555- TEST_F (EValueTest, TryToScalarNoneTag) {
556- // None is neither Int/Double/Bool, so tryToScalar must reject it.
557- EValue e;
558- auto result = e.tryToScalar ();
559- EXPECT_EQ (result.error (), executorch::runtime::Error::InvalidType);
560- }
561-
562- TEST_F (EValueTest, TryToScalarTypeTagReturnsScalarType) {
563- // ScalarType/MemoryFormat/Layout/Device share the Int tag; exercise each.
564- EValue e (static_cast <int64_t >(static_cast <int >(ScalarType::Float)));
565- auto st = e.tryToScalarType ();
566- EXPECT_TRUE (st.ok ());
567- EXPECT_EQ (st.get (), ScalarType::Float);
568- }
474+ // Per-type tryTo* coverage.
475+ // For each type:
476+ // - success and failure for named method tryTo[Int/Double/Bool/Tensor/..]
477+ // - success and failure for templated tryTo<T>() specialization
569478
570- TEST_F (EValueTest, TryToScalarTypeTypeMismatch) {
571- EValue e (3.14 );
572- auto result = e.tryToScalarType ();
573- EXPECT_EQ (result.error (), executorch::runtime::Error::InvalidType);
574- }
575-
576- TEST_F (EValueTest, TryToMemoryFormatTypeMismatch) {
577- EValue e (3.14 );
578- auto result = e.tryToMemoryFormat ();
579- EXPECT_EQ (result.error (), executorch::runtime::Error::InvalidType);
580- }
581-
582- TEST_F (EValueTest, TryToLayoutTypeMismatch) {
583- EValue e (3.14 );
584- auto result = e.tryToLayout ();
585- EXPECT_EQ (result.error (), executorch::runtime::Error::InvalidType);
586- }
587-
588- TEST_F (EValueTest, TryToDeviceTypeMismatch) {
589- EValue e (3.14 );
590- auto result = e.tryToDevice ();
591- EXPECT_EQ (result.error (), executorch::runtime::Error::InvalidType);
592- }
593-
594- // List tryTo* — only cover TensorList and ListOptionalTensor. The other
595- // list/string variants share the same `if (!isX()) return Error::InvalidType`
596- // pattern exercised by the primitive mismatch tests above. Tensor-family
597- // lists are the highest-risk attack surface (pointer-holding), so keep
598- // explicit coverage.
599-
600- TEST_F (EValueTest, TryToTensorListTypeMismatch) {
601- EValue e (static_cast <int64_t >(42 ));
602- auto result = e.tryToTensorList ();
603- EXPECT_EQ (result.error (), executorch::runtime::Error::InvalidType);
604- }
605-
606- TEST_F (EValueTest, TryToListOptionalTensorTypeMismatch) {
607- EValue e (static_cast <int64_t >(42 ));
608- auto result = e.tryToListOptionalTensor ();
609- EXPECT_EQ (result.error (), executorch::runtime::Error::InvalidType);
479+ TEST_F (EValueTest, TryToInt) {
480+ EValue e_int (static_cast <int64_t >(42 ));
481+ EValue e_mismatch (3.14 );
482+ EXPECT_EQ (e_int.tryToInt ().get (), 42 );
483+ EXPECT_EQ (e_mismatch.tryToInt ().error (), Error::InvalidType);
484+ EXPECT_EQ (e_int.tryTo <int64_t >().get (), 42 );
485+ EXPECT_EQ (e_mismatch.tryTo <int64_t >().error (), Error::InvalidType);
610486}
611487
612- // Templated tryTo<T>() dispatcher. Matches and mismatches should behave
613- // identically to the named tryToX methods.
614-
615- TEST_F (EValueTest, TryToTemplateIntSuccess) {
616- EValue e (static_cast <int64_t >(42 ));
617- auto result = e.tryTo <int64_t >();
618- EXPECT_TRUE (result.ok ());
619- EXPECT_EQ (result.get (), 42 );
488+ TEST_F (EValueTest, TryToDouble) {
489+ EValue e_double (3.14 );
490+ EValue e_mismatch (static_cast <int64_t >(42 ));
491+ EXPECT_DOUBLE_EQ (e_double.tryToDouble ().get (), 3.14 );
492+ EXPECT_EQ (e_mismatch.tryToDouble ().error (), Error::InvalidType);
493+ EXPECT_DOUBLE_EQ (e_double.tryTo <double >().get (), 3.14 );
494+ EXPECT_EQ (e_mismatch.tryTo <double >().error (), Error::InvalidType);
620495}
621496
622- TEST_F (EValueTest, TryToTemplateIntMismatch) {
623- EValue e (3.14 );
624- auto result = e.tryTo <int64_t >();
625- EXPECT_EQ (result.error (), executorch::runtime::Error::InvalidType);
497+ TEST_F (EValueTest, TryToBool) {
498+ EValue e_bool (true );
499+ EValue e_mismatch (static_cast <int64_t >(42 ));
500+ EXPECT_EQ (e_bool.tryToBool ().get (), true );
501+ EXPECT_EQ (e_mismatch.tryToBool ().error (), Error::InvalidType);
502+ EXPECT_EQ (e_bool.tryTo <bool >().get (), true );
503+ EXPECT_EQ (e_mismatch.tryTo <bool >().error (), Error::InvalidType);
626504}
627505
628- TEST_F (EValueTest, TryToTemplateTensorSuccess ) {
506+ TEST_F (EValueTest, TryToTensor ) {
629507 TensorFactory<ScalarType::Float> tf;
630- EValue e (tf.ones ({3 , 2 }));
631- auto result = e.tryTo <executorch::aten::Tensor>();
632- EXPECT_TRUE (result.ok ());
633- EXPECT_EQ (result->numel (), 6 );
508+ EValue e_tensor (tf.ones ({3 , 2 }));
509+ EValue e_mismatch (static_cast <int64_t >(42 ));
510+ EXPECT_EQ (e_tensor.tryToTensor ()->numel (), 6 );
511+ EXPECT_EQ (e_mismatch.tryToTensor ().error (), Error::InvalidType);
512+ EXPECT_EQ (e_tensor.tryTo <executorch::aten::Tensor>()->numel (), 6 );
513+ EXPECT_EQ (
514+ e_mismatch.tryTo <executorch::aten::Tensor>().error (), Error::InvalidType);
634515}
635516
636- TEST_F (EValueTest, TryToOptionalIntSuccess) {
517+ TEST_F (EValueTest, TryToOptionalTensor) {
518+ TensorFactory<ScalarType::Float> tf;
519+ EValue e_tensor (tf.ones ({3 , 2 }));
520+ EValue e_none;
521+ EValue e_mismatch (static_cast <int64_t >(42 ));
522+ // Named tryToOptional<Tensor>: value, None, mismatch.
523+ auto r_val = e_tensor.tryToOptional <executorch::aten::Tensor>();
524+ EXPECT_TRUE (r_val->has_value ());
525+ EXPECT_EQ (r_val->value ().numel (), 6 );
526+ EXPECT_FALSE (e_none.tryToOptional <executorch::aten::Tensor>()->has_value ());
527+ EXPECT_EQ (
528+ e_mismatch.tryToOptional <executorch::aten::Tensor>().error (),
529+ Error::InvalidType);
530+ // Templated tryTo<std::optional<Tensor>>: None path.
531+ EXPECT_FALSE (
532+ e_none.tryTo <std::optional<executorch::aten::Tensor>>()->has_value ());
533+ }
534+
535+ TEST_F (EValueTest, TryToScalar) {
536+ EValue e_int (static_cast <int64_t >(7 ));
537+ EValue e_double (2.5 );
538+ EValue e_bool (true );
539+ EValue e_none;
540+ EXPECT_EQ (e_int.tryToScalar ()->to <int64_t >(), 7 );
541+ EXPECT_DOUBLE_EQ (e_double.tryToScalar ()->to <double >(), 2.5 );
542+ EXPECT_EQ (e_bool.tryToScalar ()->to <bool >(), true );
543+ // None is neither Int/Double/Bool.
544+ EXPECT_EQ (e_none.tryToScalar ().error (), Error::InvalidType);
545+ }
546+
547+ TEST_F (EValueTest, TryToScalarType) {
548+ EValue e (static_cast <int64_t >(ScalarType::Float));
549+ EValue e_mismatch (3.14 );
550+ EXPECT_EQ (e.tryToScalarType ().get (), ScalarType::Float);
551+ EXPECT_EQ (e_mismatch.tryToScalarType ().error (), Error::InvalidType);
552+ EXPECT_EQ (e.tryTo <ScalarType>().get (), ScalarType::Float);
553+ EXPECT_EQ (e_mismatch.tryTo <ScalarType>().error (), Error::InvalidType);
554+ }
555+
556+ TEST_F (EValueTest, TryToMemoryFormat) {
557+ EValue e (static_cast <int64_t >(MemoryFormat::Contiguous));
558+ EValue e_mismatch (3.14 );
559+ EXPECT_EQ (e.tryToMemoryFormat ().get (), MemoryFormat::Contiguous);
560+ EXPECT_EQ (e_mismatch.tryToMemoryFormat ().error (), Error::InvalidType);
561+ }
562+
563+ TEST_F (EValueTest, TryToLayout) {
564+ EValue e (static_cast <int64_t >(Layout::Strided));
565+ EValue e_mismatch (3.14 );
566+ EXPECT_EQ (e.tryToLayout ().get (), Layout::Strided);
567+ EXPECT_EQ (e_mismatch.tryToLayout ().error (), Error::InvalidType);
568+ }
569+
570+ TEST_F (EValueTest, TryToDevice) {
571+ EValue e (static_cast <int64_t >(DeviceType::CPU));
572+ EValue e_mismatch (3.14 );
573+ EXPECT_EQ (e.tryToDevice ().get ().type (), DeviceType::CPU);
574+ EXPECT_EQ (e_mismatch.tryToDevice ().error (), Error::InvalidType);
575+ }
576+
577+ TEST_F (EValueTest, TryToTensorList) {
637578 EValue e (static_cast <int64_t >(42 ));
638- auto result = e.tryToOptional <int64_t >();
639- EXPECT_TRUE (result.ok ());
640- EXPECT_TRUE (result->has_value ());
641- EXPECT_EQ (result->value (), 42 );
579+ EXPECT_EQ (e.tryToTensorList ().error (), Error::InvalidType);
642580}
643581
644- TEST_F (EValueTest, TryToOptionalIntNone) {
645- EValue e;
646- auto result = e.tryToOptional <int64_t >();
647- EXPECT_TRUE (result.ok ());
648- EXPECT_FALSE (result->has_value ());
649- }
650-
651- TEST_F (EValueTest, TryToOptionalIntTypeMismatch) {
652- EValue e (3.14 );
653- auto result = e.tryToOptional <int64_t >();
654- EXPECT_EQ (result.error (), executorch::runtime::Error::InvalidType);
655- }
656-
657- // Verify tryTo<std::optional<T>>() specializations match tryToOptional<T>()
658- // semantics, mirroring the to<std::optional<T>>() specializations of to<T>().
659- TEST_F (EValueTest, TryToTemplateOptionalIntSuccess) {
582+ TEST_F (EValueTest, TryToListOptionalTensor) {
660583 EValue e (static_cast <int64_t >(42 ));
661- auto result = e.tryTo <std::optional<int64_t >>();
662- EXPECT_TRUE (result.ok ());
663- EXPECT_TRUE (result->has_value ());
664- EXPECT_EQ (result->value (), 42 );
665- }
666-
667- TEST_F (EValueTest, TryToTemplateOptionalTensorNone) {
668- EValue e;
669- auto result = e.tryTo <std::optional<executorch::aten::Tensor>>();
670- EXPECT_TRUE (result.ok ());
671- EXPECT_FALSE (result->has_value ());
584+ EXPECT_EQ (e.tryToListOptionalTensor ().error (), Error::InvalidType);
672585}
0 commit comments