• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //
2 // Copyright © 2020 Arm Ltd. All rights reserved.
3 // SPDX-License-Identifier: MIT
4 //
5 
6 
7 #define ARMNN_POLYMORPHIC_CAST_TESTABLE
8 #define ARMNN_NUMERIC_CAST_TESTABLE
9 
10 #include <armnn/Exceptions.hpp>
11 #include <armnn/utility/IgnoreUnused.hpp>
12 #include <armnn/utility/PolymorphicDowncast.hpp>
13 #include <armnn/utility/NumericCast.hpp>
14 #include <armnn/utility/StringUtils.hpp>
15 
16 #include <doctest/doctest.h>
17 
18 #include <limits>
19 
20 // Tests of include/Utility files
21 TEST_SUITE("UtilityTests")
22 {
23 TEST_CASE("PolymorphicDowncast")
24 {
25     using namespace armnn;
26     class Base
27     {
28     public:
~Base()29         virtual ~Base(){}
30         float v;
31     };
32 
33     class Child1 : public Base
34     {
35     public:
36         int j;
37     };
38 
39     class Child2 : public Base
40     {
41     public:
42         char b;
43     };
44 
45     Child1 child1;
46     Base* base1 = &child1;
47     auto ptr1 = dynamic_cast<Child1*>(base1);
48     CHECK(ptr1 != nullptr);
49     CHECK_NOTHROW(armnn::PolymorphicDowncast<Child1*>(base1));
50     CHECK(armnn::PolymorphicDowncast<Child1*>(base1) == ptr1);
51 
52     auto ptr2 = dynamic_cast<Child2*>(base1);
53     CHECK(ptr2 == nullptr);
54     CHECK_THROWS_AS(armnn::PolymorphicDowncast<Child2*>(base1), std::bad_cast);
55 
56     armnn::IgnoreUnused(ptr1, ptr2);
57 }
58 
59 
60 TEST_CASE("PolymorphicPointerDowncast_SharedPointer")
61 {
62     using namespace armnn;
63     class Base
64     {
65     public:
~Base()66         virtual ~Base(){}
67         float v;
68     };
69 
70     class Child1 : public Base
71     {
72     public:
73         int j;
74     };
75 
76     class Child2 : public Base
77     {
78     public:
79         char b;
80     };
81 
82     std::shared_ptr<Base> base1 = std::make_shared<Child1>();
83 
84     std::shared_ptr<Child1> ptr1 = std::static_pointer_cast<Child1>(base1);
85     CHECK(ptr1);
86     CHECK_NOTHROW(armnn::PolymorphicPointerDowncast<Child1>(base1));
87     CHECK(armnn::PolymorphicPointerDowncast<Child1>(base1) == ptr1);
88 
89     auto ptr2 = std::dynamic_pointer_cast<Child2>(base1);
90     CHECK(!ptr2);
91     CHECK_THROWS_AS(armnn::PolymorphicPointerDowncast<Child2>(base1), std::bad_cast);
92 
93     armnn::IgnoreUnused(ptr1, ptr2);
94 }
95 
96 
97 TEST_CASE("PolymorphicPointerDowncast_BuildInPointer")
98 {
99     using namespace armnn;
100     class Base
101     {
102     public:
~Base()103         virtual ~Base(){}
104         float v;
105     };
106 
107     class Child1 : public Base
108     {
109     public:
110         int j;
111     };
112 
113     class Child2 : public Base
114     {
115     public:
116         char b;
117     };
118 
119     Child1 child1;
120     Base* base1 = &child1;
121     auto ptr1 = dynamic_cast<Child1*>(base1);
122     CHECK(ptr1 != nullptr);
123     CHECK_NOTHROW(armnn::PolymorphicPointerDowncast<Child1>(base1));
124     CHECK(armnn::PolymorphicPointerDowncast<Child1>(base1) == ptr1);
125 
126     auto ptr2 = dynamic_cast<Child2*>(base1);
127     CHECK(ptr2 == nullptr);
128     CHECK_THROWS_AS(armnn::PolymorphicPointerDowncast<Child2>(base1), std::bad_cast);
129 
130     armnn::IgnoreUnused(ptr1, ptr2);
131 }
132 
133 
134 TEST_CASE("NumericCast")
135 {
136     using namespace armnn;
137 
138     // To 8 bit
139     CHECK_THROWS_AS(numeric_cast<unsigned char>(-1), std::bad_cast);
140     CHECK_THROWS_AS(numeric_cast<unsigned char>(1 << 8), std::bad_cast);
141     CHECK_THROWS_AS(numeric_cast<unsigned char>(1L << 16), std::bad_cast);
142     CHECK_THROWS_AS(numeric_cast<unsigned char>(1LL << 32), std::bad_cast);
143 
144     CHECK_THROWS_AS(numeric_cast<signed char>((1L << 8)*-1), std::bad_cast);
145     CHECK_THROWS_AS(numeric_cast<signed char>((1L << 15)*-1), std::bad_cast);
146     CHECK_THROWS_AS(numeric_cast<signed char>((1LL << 31)*-1), std::bad_cast);
147 
148     CHECK_NOTHROW(numeric_cast<unsigned char>(1U));
149     CHECK_NOTHROW(numeric_cast<unsigned char>(1L));
150     CHECK_NOTHROW(numeric_cast<signed char>(-1));
151     CHECK_NOTHROW(numeric_cast<signed char>(-1L));
152     CHECK_NOTHROW(numeric_cast<signed char>((1 << 7)*-1));
153 
154     // To 16 bit
155     CHECK_THROWS_AS(numeric_cast<uint16_t>(-1), std::bad_cast);
156     CHECK_THROWS_AS(numeric_cast<uint16_t>(1L << 16), std::bad_cast);
157     CHECK_THROWS_AS(numeric_cast<uint16_t>(1LL << 32), std::bad_cast);
158 
159     CHECK_THROWS_AS(numeric_cast<int16_t>(1L << 15), std::bad_cast);
160     CHECK_THROWS_AS(numeric_cast<int16_t>(1LL << 31), std::bad_cast);
161 
162     CHECK_NOTHROW(numeric_cast<uint16_t>(1L << 8));
163     CHECK_NOTHROW(numeric_cast<int16_t>(1L << 7));
164     CHECK_NOTHROW(numeric_cast<int16_t>((1L << 15)*-1));
165 
166     CHECK_NOTHROW(numeric_cast<int16_t>(1U << 8));
167     CHECK_NOTHROW(numeric_cast<int16_t>(1U << 14));
168 
169     // To 32 bit
170     CHECK_NOTHROW(numeric_cast<uint32_t>(1));
171     CHECK_NOTHROW(numeric_cast<uint32_t>(1 << 8));
172     CHECK_NOTHROW(numeric_cast<uint32_t>(1L << 16));
173     CHECK_NOTHROW(numeric_cast<uint32_t>(1LL << 31));
174 
175     CHECK_NOTHROW(numeric_cast<int32_t>(-1));
176     CHECK_NOTHROW(numeric_cast<int32_t>((1L << 8)*-1));
177     CHECK_NOTHROW(numeric_cast<int32_t>((1L << 16)*-1));
178     CHECK_NOTHROW(numeric_cast<int32_t>((1LL << 31)*-1));
179 
180     CHECK_NOTHROW(numeric_cast<int32_t>(1U));
181     CHECK_NOTHROW(numeric_cast<int32_t>(1U << 8));
182     CHECK_NOTHROW(numeric_cast<int32_t>(1U << 16));
183     CHECK_NOTHROW(numeric_cast<int32_t>(1U << 30));
184 
185     float float_max = std::numeric_limits<float>::max();
186     float float_min = std::numeric_limits<float>::lowest();
187     auto int8_max = std::numeric_limits<int8_t>::max();
188     auto int16_max = std::numeric_limits<int16_t>::max();
189     auto int32_max = std::numeric_limits<int32_t>::max();
190     auto int8_min = std::numeric_limits<int8_t>::lowest();
191     auto int16_min = std::numeric_limits<int16_t>::lowest();
192     auto int32_min = std::numeric_limits<int32_t>::lowest();
193     auto uint8_max = std::numeric_limits<uint8_t>::max();
194     auto uint16_max = std::numeric_limits<uint16_t>::max();
195     auto uint32_max = std::numeric_limits<uint32_t>::max();
196     auto double_max = std::numeric_limits<double>::max();
197 
198     // Float to signed integer
199     CHECK_NOTHROW(numeric_cast<int32_t>(1.324f));
200     CHECK(1 == numeric_cast<int32_t>(1.324f));
201     CHECK_NOTHROW(numeric_cast<int32_t>(-1.0f));
202     CHECK(-1 == numeric_cast<int32_t>(-1.0f));
203 
204     CHECK_NOTHROW(numeric_cast<int8_t>(static_cast<float>(int8_max)));
205     CHECK_NOTHROW(numeric_cast<int16_t>(static_cast<float>(int16_max)));
206     CHECK_NOTHROW(numeric_cast<int32_t>(static_cast<double>(int32_max)));
207 
208     CHECK_THROWS_AS(numeric_cast<int8_t>(float_max), std::bad_cast);
209     CHECK_THROWS_AS(numeric_cast<int16_t>(float_max), std::bad_cast);
210     CHECK_THROWS_AS(numeric_cast<int32_t>(float_max), std::bad_cast);
211 
212     CHECK_THROWS_AS(numeric_cast<int8_t>(float_min), std::bad_cast);
213     CHECK_THROWS_AS(numeric_cast<int16_t>(float_min), std::bad_cast);
214     CHECK_THROWS_AS(numeric_cast<int32_t>(float_min), std::bad_cast);
215 
216     // Signed integer to float
217     CHECK_NOTHROW(numeric_cast<float>(1));
218     CHECK(1.0 == numeric_cast<float>(1));
219     CHECK_NOTHROW(numeric_cast<float>(-1));
220     CHECK(-1.0 == numeric_cast<float>(-1));
221 
222     CHECK_NOTHROW(numeric_cast<float>(int8_max));
223     CHECK_NOTHROW(numeric_cast<float>(int16_max));
224     CHECK_NOTHROW(numeric_cast<float>(int32_max));
225 
226     CHECK_NOTHROW(numeric_cast<float>(int8_min));
227     CHECK_NOTHROW(numeric_cast<float>(int16_min));
228     CHECK_NOTHROW(numeric_cast<float>(int32_min));
229 
230     // Unsigned integer to float
231     CHECK_NOTHROW(numeric_cast<float>(1U));
232     CHECK(1.0 == numeric_cast<float>(1U));
233 
234     CHECK_NOTHROW(numeric_cast<float>(uint8_max));
235     CHECK_NOTHROW(numeric_cast<float>(uint16_max));
236     CHECK_NOTHROW(numeric_cast<float>(uint32_max));
237 
238     // Float to unsigned integer
239     CHECK_NOTHROW(numeric_cast<uint32_t>(1.43243f));
240     CHECK(1 == numeric_cast<uint32_t>(1.43243f));
241 
242     CHECK_THROWS_AS(numeric_cast<uint32_t>(-1.1f), std::bad_cast);
243     CHECK_THROWS_AS(numeric_cast<uint32_t>(float_max), std::bad_cast);
244 
245     // Double checks
246     CHECK_THROWS_AS(numeric_cast<int32_t>(double_max), std::bad_cast);
247     CHECK_THROWS_AS(numeric_cast<int32_t>(double_max), std::bad_cast);
248     CHECK_THROWS_AS(numeric_cast<float>(double_max), std::bad_cast);
249     CHECK_NOTHROW(numeric_cast<double>(int32_max));
250     CHECK_NOTHROW(numeric_cast<long double>(int32_max));
251 
252     }
253 
254 TEST_CASE("StringToBool")
255     {
256         CHECK(true == armnn::stringUtils::StringToBool("1"));
257         CHECK(false == armnn::stringUtils::StringToBool("0"));
258         // Any number larger than 1 will be a failure.
259         CHECK_THROWS_AS(armnn::stringUtils::StringToBool("2"), armnn::InvalidArgumentException);
260         CHECK_THROWS_AS(armnn::stringUtils::StringToBool("23456567"), armnn::InvalidArgumentException);
261         CHECK_THROWS_AS(armnn::stringUtils::StringToBool("-23456567"), armnn::InvalidArgumentException);
262         CHECK_THROWS_AS(armnn::stringUtils::StringToBool("Not a number"), armnn::InvalidArgumentException);
263         // Empty string should be a failure.
264         CHECK_THROWS_AS(armnn::stringUtils::StringToBool(""), armnn::InvalidArgumentException);
265         CHECK(true == armnn::stringUtils::StringToBool("true"));
266         CHECK(false == armnn::stringUtils::StringToBool("false"));
267         // Should be case agnostic.
268         CHECK(true == armnn::stringUtils::StringToBool("TrUe"));
269         CHECK(false == armnn::stringUtils::StringToBool("fAlSe"));
270 
271         // Same negative test cases with throw_on_error set to false.
272         CHECK(false == armnn::stringUtils::StringToBool("2", false));
273         CHECK(false == armnn::stringUtils::StringToBool("23456567", false));
274         CHECK(false == armnn::stringUtils::StringToBool("-23456567", false));
275         CHECK(false == armnn::stringUtils::StringToBool("Not a number", false));
276         CHECK(false == armnn::stringUtils::StringToBool("", false));
277     }
278 }
279