// // Copyright © 2020 Arm Ltd. All rights reserved. // SPDX-License-Identifier: MIT // #define ARMNN_POLYMORPHIC_CAST_TESTABLE #define ARMNN_NUMERIC_CAST_TESTABLE #include #include #include #include #include #include #include // Tests of include/Utility files TEST_SUITE("UtilityTests") { TEST_CASE("PolymorphicDowncast") { using namespace armnn; class Base { public: virtual ~Base(){} float v; }; class Child1 : public Base { public: int j; }; class Child2 : public Base { public: char b; }; Child1 child1; Base* base1 = &child1; auto ptr1 = dynamic_cast(base1); CHECK(ptr1 != nullptr); CHECK_NOTHROW(armnn::PolymorphicDowncast(base1)); CHECK(armnn::PolymorphicDowncast(base1) == ptr1); auto ptr2 = dynamic_cast(base1); CHECK(ptr2 == nullptr); CHECK_THROWS_AS(armnn::PolymorphicDowncast(base1), std::bad_cast); armnn::IgnoreUnused(ptr1, ptr2); } TEST_CASE("PolymorphicPointerDowncast_SharedPointer") { using namespace armnn; class Base { public: virtual ~Base(){} float v; }; class Child1 : public Base { public: int j; }; class Child2 : public Base { public: char b; }; std::shared_ptr base1 = std::make_shared(); std::shared_ptr ptr1 = std::static_pointer_cast(base1); CHECK(ptr1); CHECK_NOTHROW(armnn::PolymorphicPointerDowncast(base1)); CHECK(armnn::PolymorphicPointerDowncast(base1) == ptr1); auto ptr2 = std::dynamic_pointer_cast(base1); CHECK(!ptr2); CHECK_THROWS_AS(armnn::PolymorphicPointerDowncast(base1), std::bad_cast); armnn::IgnoreUnused(ptr1, ptr2); } TEST_CASE("PolymorphicPointerDowncast_BuildInPointer") { using namespace armnn; class Base { public: virtual ~Base(){} float v; }; class Child1 : public Base { public: int j; }; class Child2 : public Base { public: char b; }; Child1 child1; Base* base1 = &child1; auto ptr1 = dynamic_cast(base1); CHECK(ptr1 != nullptr); CHECK_NOTHROW(armnn::PolymorphicPointerDowncast(base1)); CHECK(armnn::PolymorphicPointerDowncast(base1) == ptr1); auto ptr2 = dynamic_cast(base1); CHECK(ptr2 == nullptr); CHECK_THROWS_AS(armnn::PolymorphicPointerDowncast(base1), std::bad_cast); armnn::IgnoreUnused(ptr1, ptr2); } TEST_CASE("NumericCast") { using namespace armnn; // To 8 bit CHECK_THROWS_AS(numeric_cast(-1), std::bad_cast); CHECK_THROWS_AS(numeric_cast(1 << 8), std::bad_cast); CHECK_THROWS_AS(numeric_cast(1L << 16), std::bad_cast); CHECK_THROWS_AS(numeric_cast(1LL << 32), std::bad_cast); CHECK_THROWS_AS(numeric_cast((1L << 8)*-1), std::bad_cast); CHECK_THROWS_AS(numeric_cast((1L << 15)*-1), std::bad_cast); CHECK_THROWS_AS(numeric_cast((1LL << 31)*-1), std::bad_cast); CHECK_NOTHROW(numeric_cast(1U)); CHECK_NOTHROW(numeric_cast(1L)); CHECK_NOTHROW(numeric_cast(-1)); CHECK_NOTHROW(numeric_cast(-1L)); CHECK_NOTHROW(numeric_cast((1 << 7)*-1)); // To 16 bit CHECK_THROWS_AS(numeric_cast(-1), std::bad_cast); CHECK_THROWS_AS(numeric_cast(1L << 16), std::bad_cast); CHECK_THROWS_AS(numeric_cast(1LL << 32), std::bad_cast); CHECK_THROWS_AS(numeric_cast(1L << 15), std::bad_cast); CHECK_THROWS_AS(numeric_cast(1LL << 31), std::bad_cast); CHECK_NOTHROW(numeric_cast(1L << 8)); CHECK_NOTHROW(numeric_cast(1L << 7)); CHECK_NOTHROW(numeric_cast((1L << 15)*-1)); CHECK_NOTHROW(numeric_cast(1U << 8)); CHECK_NOTHROW(numeric_cast(1U << 14)); // To 32 bit CHECK_NOTHROW(numeric_cast(1)); CHECK_NOTHROW(numeric_cast(1 << 8)); CHECK_NOTHROW(numeric_cast(1L << 16)); CHECK_NOTHROW(numeric_cast(1LL << 31)); CHECK_NOTHROW(numeric_cast(-1)); CHECK_NOTHROW(numeric_cast((1L << 8)*-1)); CHECK_NOTHROW(numeric_cast((1L << 16)*-1)); CHECK_NOTHROW(numeric_cast((1LL << 31)*-1)); CHECK_NOTHROW(numeric_cast(1U)); CHECK_NOTHROW(numeric_cast(1U << 8)); CHECK_NOTHROW(numeric_cast(1U << 16)); CHECK_NOTHROW(numeric_cast(1U << 30)); float float_max = std::numeric_limits::max(); float float_min = std::numeric_limits::lowest(); auto int8_max = std::numeric_limits::max(); auto int16_max = std::numeric_limits::max(); auto int32_max = std::numeric_limits::max(); auto int8_min = std::numeric_limits::lowest(); auto int16_min = std::numeric_limits::lowest(); auto int32_min = std::numeric_limits::lowest(); auto uint8_max = std::numeric_limits::max(); auto uint16_max = std::numeric_limits::max(); auto uint32_max = std::numeric_limits::max(); auto double_max = std::numeric_limits::max(); // Float to signed integer CHECK_NOTHROW(numeric_cast(1.324f)); CHECK(1 == numeric_cast(1.324f)); CHECK_NOTHROW(numeric_cast(-1.0f)); CHECK(-1 == numeric_cast(-1.0f)); CHECK_NOTHROW(numeric_cast(static_cast(int8_max))); CHECK_NOTHROW(numeric_cast(static_cast(int16_max))); CHECK_NOTHROW(numeric_cast(static_cast(int32_max))); CHECK_THROWS_AS(numeric_cast(float_max), std::bad_cast); CHECK_THROWS_AS(numeric_cast(float_max), std::bad_cast); CHECK_THROWS_AS(numeric_cast(float_max), std::bad_cast); CHECK_THROWS_AS(numeric_cast(float_min), std::bad_cast); CHECK_THROWS_AS(numeric_cast(float_min), std::bad_cast); CHECK_THROWS_AS(numeric_cast(float_min), std::bad_cast); // Signed integer to float CHECK_NOTHROW(numeric_cast(1)); CHECK(1.0 == numeric_cast(1)); CHECK_NOTHROW(numeric_cast(-1)); CHECK(-1.0 == numeric_cast(-1)); CHECK_NOTHROW(numeric_cast(int8_max)); CHECK_NOTHROW(numeric_cast(int16_max)); CHECK_NOTHROW(numeric_cast(int32_max)); CHECK_NOTHROW(numeric_cast(int8_min)); CHECK_NOTHROW(numeric_cast(int16_min)); CHECK_NOTHROW(numeric_cast(int32_min)); // Unsigned integer to float CHECK_NOTHROW(numeric_cast(1U)); CHECK(1.0 == numeric_cast(1U)); CHECK_NOTHROW(numeric_cast(uint8_max)); CHECK_NOTHROW(numeric_cast(uint16_max)); CHECK_NOTHROW(numeric_cast(uint32_max)); // Float to unsigned integer CHECK_NOTHROW(numeric_cast(1.43243f)); CHECK(1 == numeric_cast(1.43243f)); CHECK_THROWS_AS(numeric_cast(-1.1f), std::bad_cast); CHECK_THROWS_AS(numeric_cast(float_max), std::bad_cast); // Double checks CHECK_THROWS_AS(numeric_cast(double_max), std::bad_cast); CHECK_THROWS_AS(numeric_cast(double_max), std::bad_cast); CHECK_THROWS_AS(numeric_cast(double_max), std::bad_cast); CHECK_NOTHROW(numeric_cast(int32_max)); CHECK_NOTHROW(numeric_cast(int32_max)); } TEST_CASE("StringToBool") { CHECK(true == armnn::stringUtils::StringToBool("1")); CHECK(false == armnn::stringUtils::StringToBool("0")); // Any number larger than 1 will be a failure. CHECK_THROWS_AS(armnn::stringUtils::StringToBool("2"), armnn::InvalidArgumentException); CHECK_THROWS_AS(armnn::stringUtils::StringToBool("23456567"), armnn::InvalidArgumentException); CHECK_THROWS_AS(armnn::stringUtils::StringToBool("-23456567"), armnn::InvalidArgumentException); CHECK_THROWS_AS(armnn::stringUtils::StringToBool("Not a number"), armnn::InvalidArgumentException); // Empty string should be a failure. CHECK_THROWS_AS(armnn::stringUtils::StringToBool(""), armnn::InvalidArgumentException); CHECK(true == armnn::stringUtils::StringToBool("true")); CHECK(false == armnn::stringUtils::StringToBool("false")); // Should be case agnostic. CHECK(true == armnn::stringUtils::StringToBool("TrUe")); CHECK(false == armnn::stringUtils::StringToBool("fAlSe")); // Same negative test cases with throw_on_error set to false. CHECK(false == armnn::stringUtils::StringToBool("2", false)); CHECK(false == armnn::stringUtils::StringToBool("23456567", false)); CHECK(false == armnn::stringUtils::StringToBool("-23456567", false)); CHECK(false == armnn::stringUtils::StringToBool("Not a number", false)); CHECK(false == armnn::stringUtils::StringToBool("", false)); } }