blob: 1b3edc5e22b0ed2e7e2dfc62d33554728a455916 [file] [log] [blame]
Matteo Martincighac60d282019-07-25 15:25:44 +01001//
2// Copyright © 2017 Arm Ltd. All rights reserved.
3// SPDX-License-Identifier: MIT
4//
5
6#pragma once
7
Matteo Martincighbc2e2102019-07-24 14:56:13 +01008#include <backendsCommon/DynamicBackend.hpp>
Matteo Martincighac60d282019-07-25 15:25:44 +01009#include <backendsCommon/DynamicBackendUtils.hpp>
10
Matteo Martincighbc2e2102019-07-24 14:56:13 +010011#include <string>
12#include <memory>
Matteo Martincighac60d282019-07-25 15:25:44 +010013
Matteo Martincigh986c1862019-07-26 15:12:47 +010014#include <string>
15
Matteo Martincighac60d282019-07-25 15:25:44 +010016#include <boost/test/unit_test.hpp>
Matteo Martincigh986c1862019-07-26 15:12:47 +010017#include <boost/filesystem.hpp>
18
Matteo Martincighbc2e2102019-07-24 14:56:13 +010019static std::string g_TestSharedObjectSubDir = "src/backends/backendsCommon/test/";
20static std::string g_TestSharedObjectFileName = "libarmnnTestSharedObject.so";
21static std::string g_TestValidTestDynamicBackendFileName = "libarmnnValidTestDynamicBackend.so";
22static std::string g_TestInvalidTestDynamicBackend1FileName = "libarmnnInvalidTestDynamicBackend1.so";
23static std::string g_TestInvalidTestDynamicBackend2FileName = "libarmnnInvalidTestDynamicBackend2.so";
24static std::string g_TestInvalidTestDynamicBackend3FileName = "libarmnnInvalidTestDynamicBackend3.so";
25static std::string g_TestInvalidTestDynamicBackend4FileName = "libarmnnInvalidTestDynamicBackend4.so";
26static std::string g_TestInvalidTestDynamicBackend5FileName = "libarmnnInvalidTestDynamicBackend5.so";
27static std::string g_TestInvalidTestDynamicBackend6FileName = "libarmnnInvalidTestDynamicBackend6.so";
28static std::string g_TestInvalidTestDynamicBackend7FileName = "libarmnnInvalidTestDynamicBackend7.so";
Matteo Martincigh986c1862019-07-26 15:12:47 +010029
30std::string GetTestFilePath(const std::string& fileName)
31{
32 using namespace boost::filesystem;
33
34 path currentPath(current_path());
35 path sharedObjectPath = currentPath.append(g_TestSharedObjectSubDir);
36 path sharedObjectFile = sharedObjectPath.append(fileName);
37 BOOST_TEST(exists(sharedObjectFile));
38
39 return sharedObjectFile.string();
40}
41
42void OpenCloseHandleTestImpl()
43{
44 using namespace armnn;
45
46 std::string sharedObjectFilePath = GetTestFilePath(g_TestSharedObjectFileName);
47
48 void* sharedObjectHandle = nullptr;
49 BOOST_CHECK_NO_THROW(sharedObjectHandle = DynamicBackendUtils::OpenHandle(sharedObjectFilePath));
50 BOOST_TEST((sharedObjectHandle != nullptr));
51
52 DynamicBackendUtils::CloseHandle(sharedObjectHandle);
53}
54
55void CloseInvalidHandleTestImpl()
56{
57 using namespace armnn;
58
59 // This calls must silently handle invalid handles and complete successfully (no segfaults, etc.)
60 DynamicBackendUtils::CloseHandle(nullptr);
61}
62
63void OpenEmptyFileNameTestImpl()
64{
65 using namespace armnn;
66
67 void* sharedObjectHandle = nullptr;
68 BOOST_CHECK_THROW(sharedObjectHandle = DynamicBackendUtils::OpenHandle(""), RuntimeException);
69 BOOST_TEST((sharedObjectHandle == nullptr));
70}
71
72void OpenNotExistingFileTestImpl()
73{
74 using namespace armnn;
75
76 void* sharedObjectHandle = nullptr;
77 BOOST_CHECK_THROW(sharedObjectHandle = DynamicBackendUtils::OpenHandle("NotExistingFileName"), RuntimeException);
78 BOOST_TEST((sharedObjectHandle == nullptr));
79}
80
81void OpenNotSharedObjectTestImpl()
82{
83 using namespace armnn;
84
85 std::string notSharedObjectFilePath = GetTestFilePath("libarmnnNoSharedObject.txt");
86
87 void* sharedObjectHandle = nullptr;
88 BOOST_CHECK_THROW(sharedObjectHandle = DynamicBackendUtils::OpenHandle(notSharedObjectFilePath), RuntimeException);
89 BOOST_TEST((sharedObjectHandle == nullptr));
90}
91
92void GetValidEntryPointTestImpl()
93{
94 using namespace armnn;
95
96 std::string sharedObjectFilePath = GetTestFilePath(g_TestSharedObjectFileName);
97
98 void* sharedObjectHandle = nullptr;
99 BOOST_CHECK_NO_THROW(sharedObjectHandle = DynamicBackendUtils::OpenHandle(sharedObjectFilePath));
100 BOOST_TEST((sharedObjectHandle != nullptr));
101
102 using TestFunctionType = int(*)(int);
103 TestFunctionType testFunctionPointer = nullptr;
104 BOOST_CHECK_NO_THROW(testFunctionPointer = DynamicBackendUtils::GetEntryPoint<TestFunctionType>(sharedObjectHandle,
105 "TestFunction1"));
106 BOOST_TEST((testFunctionPointer != nullptr));
107 BOOST_TEST(testFunctionPointer(7) == 7);
108
109 DynamicBackendUtils::CloseHandle(sharedObjectHandle);
110}
111
112void GetNameMangledEntryPointTestImpl()
113{
114 using namespace armnn;
115
116 std::string sharedObjectFilePath = GetTestFilePath(g_TestSharedObjectFileName);
117
118 void* sharedObjectHandle = nullptr;
119 BOOST_CHECK_NO_THROW(sharedObjectHandle = DynamicBackendUtils::OpenHandle(sharedObjectFilePath));
120 BOOST_TEST((sharedObjectHandle != nullptr));
121
122 using TestFunctionType = int(*)(int);
123 TestFunctionType testFunctionPointer = nullptr;
124 BOOST_CHECK_THROW(testFunctionPointer = DynamicBackendUtils::GetEntryPoint<TestFunctionType>(sharedObjectHandle,
125 "TestFunction2"),
126 RuntimeException);
127 BOOST_TEST((testFunctionPointer == nullptr));
128
129 DynamicBackendUtils::CloseHandle(sharedObjectHandle);
130}
131
132void GetNoExternEntryPointTestImpl()
133{
134 using namespace armnn;
135
136 std::string sharedObjectFilePath = GetTestFilePath(g_TestSharedObjectFileName);
137
138 void* sharedObjectHandle = nullptr;
139 BOOST_CHECK_NO_THROW(sharedObjectHandle = DynamicBackendUtils::OpenHandle(sharedObjectFilePath));
140 BOOST_TEST((sharedObjectHandle != nullptr));
141
142 using TestFunctionType = int(*)(int);
143 TestFunctionType testFunctionPointer = nullptr;
144 BOOST_CHECK_THROW(testFunctionPointer = DynamicBackendUtils::GetEntryPoint<TestFunctionType>(sharedObjectHandle,
145 "TestFunction3"),
146 RuntimeException);
147 BOOST_TEST((testFunctionPointer == nullptr));
148
149 DynamicBackendUtils::CloseHandle(sharedObjectHandle);
150}
151
152void GetNotExistingEntryPointTestImpl()
153{
154 using namespace armnn;
155
156 std::string sharedObjectFilePath = GetTestFilePath(g_TestSharedObjectFileName);
157
158 void* sharedObjectHandle = nullptr;
159 BOOST_CHECK_NO_THROW(sharedObjectHandle = DynamicBackendUtils::OpenHandle(sharedObjectFilePath));
160 BOOST_TEST((sharedObjectHandle != nullptr));
161
162 using TestFunctionType = int(*)(int);
163 TestFunctionType testFunctionPointer = nullptr;
164 BOOST_CHECK_THROW(testFunctionPointer = DynamicBackendUtils::GetEntryPoint<TestFunctionType>(sharedObjectHandle,
165 "TestFunction4"),
166 RuntimeException);
167 BOOST_TEST((testFunctionPointer == nullptr));
168
169 DynamicBackendUtils::CloseHandle(sharedObjectHandle);
170}
Matteo Martincighac60d282019-07-25 15:25:44 +0100171
172void BackendVersioningTestImpl()
173{
Matteo Martincigh986c1862019-07-26 15:12:47 +0100174 using namespace armnn;
175
176 class TestDynamicBackendUtils : public DynamicBackendUtils
Matteo Martincighac60d282019-07-25 15:25:44 +0100177 {
178 public:
Matteo Martincigh986c1862019-07-26 15:12:47 +0100179 static bool IsBackendCompatibleTest(const BackendVersion& backendApiVersion,
180 const BackendVersion& backendVersion)
Matteo Martincighac60d282019-07-25 15:25:44 +0100181 {
182 return IsBackendCompatibleImpl(backendApiVersion, backendVersion);
183 }
184 };
185
186 // The backend API version used for the tests
Matteo Martincigh986c1862019-07-26 15:12:47 +0100187 BackendVersion backendApiVersion{ 2, 4 };
Matteo Martincighac60d282019-07-25 15:25:44 +0100188
189 // Same backend and backend API versions are compatible with the backend API
Matteo Martincigh986c1862019-07-26 15:12:47 +0100190 BackendVersion sameBackendVersion{ 2, 4 };
Matteo Martincighac60d282019-07-25 15:25:44 +0100191 BOOST_TEST(sameBackendVersion == backendApiVersion);
192 BOOST_TEST(sameBackendVersion <= backendApiVersion);
193 BOOST_TEST(TestDynamicBackendUtils::IsBackendCompatibleTest(backendApiVersion, sameBackendVersion) == true);
194
195 // Backend versions that differ from the backend API version by major revision are not compatible
196 // with the backend API
Matteo Martincigh986c1862019-07-26 15:12:47 +0100197 BackendVersion laterMajorBackendVersion{ 3, 4 };
Matteo Martincighac60d282019-07-25 15:25:44 +0100198 BOOST_TEST(!(laterMajorBackendVersion == backendApiVersion));
199 BOOST_TEST(!(laterMajorBackendVersion <= backendApiVersion));
200 BOOST_TEST(TestDynamicBackendUtils::IsBackendCompatibleTest(backendApiVersion, laterMajorBackendVersion) == false);
201
Matteo Martincigh986c1862019-07-26 15:12:47 +0100202 BackendVersion earlierMajorBackendVersion{ 1, 4 };
Matteo Martincighac60d282019-07-25 15:25:44 +0100203 BOOST_TEST(!(earlierMajorBackendVersion == backendApiVersion));
204 BOOST_TEST(earlierMajorBackendVersion <= backendApiVersion);
205 BOOST_TEST(TestDynamicBackendUtils::IsBackendCompatibleTest(backendApiVersion,
206 earlierMajorBackendVersion) == false);
207
208 // Backend versions with the same major revision but later minor revision than
209 // the backend API version are not compatible with the backend API
Matteo Martincigh986c1862019-07-26 15:12:47 +0100210 BackendVersion laterMinorBackendVersion{ 2, 5 };
Matteo Martincighac60d282019-07-25 15:25:44 +0100211 BOOST_TEST(!(laterMinorBackendVersion == backendApiVersion));
212 BOOST_TEST(!(laterMinorBackendVersion <= backendApiVersion));
213 BOOST_TEST(TestDynamicBackendUtils::IsBackendCompatibleTest(backendApiVersion, laterMinorBackendVersion) == false);
214
215 // Backend versions with the same major revision but earlier minor revision than
216 // the backend API version are compatible with the backend API
Matteo Martincigh986c1862019-07-26 15:12:47 +0100217 BackendVersion earlierMinorBackendVersion{ 2, 3 };
Matteo Martincighac60d282019-07-25 15:25:44 +0100218 BOOST_TEST(!(earlierMinorBackendVersion == backendApiVersion));
219 BOOST_TEST(earlierMinorBackendVersion <= backendApiVersion);
220 BOOST_TEST(TestDynamicBackendUtils::IsBackendCompatibleTest(backendApiVersion, earlierMinorBackendVersion) == true);
221}
Matteo Martincighbc2e2102019-07-24 14:56:13 +0100222
223void CreateValidDynamicBackendObjectTestImpl()
224{
225 // Valid shared object handle
226 // Correct name mangling
227 // Correct interface
228 // Correct backend implementation
229
230 using namespace armnn;
231
232 std::string sharedObjectFilePath = GetTestFilePath(g_TestValidTestDynamicBackendFileName);
233
234 void* sharedObjectHandle = nullptr;
235 BOOST_CHECK_NO_THROW(sharedObjectHandle = DynamicBackendUtils::OpenHandle(sharedObjectFilePath));
236 BOOST_TEST((sharedObjectHandle != nullptr));
237
238 std::unique_ptr<DynamicBackend> dynamicBackend;
239 BOOST_CHECK_NO_THROW(dynamicBackend.reset(new DynamicBackend(sharedObjectHandle)));
240 BOOST_TEST((dynamicBackend != nullptr));
241
242 BackendId dynamicBackendId;
243 BOOST_CHECK_NO_THROW(dynamicBackendId = dynamicBackend->GetBackendId());
244 BOOST_TEST((dynamicBackendId == "ValidTestDynamicBackend"));
245
246 BackendVersion dynamicBackendVersion;
247 BOOST_CHECK_NO_THROW(dynamicBackendVersion = dynamicBackend->GetBackendVersion());
248 BOOST_TEST((dynamicBackendVersion == BackendVersion({ 1, 0 })));
249
250 IBackendInternalUniquePtr dynamicBackendInstance;
251 BOOST_CHECK_NO_THROW(dynamicBackendInstance = dynamicBackend->GetBackend());
252 BOOST_TEST((dynamicBackendInstance != nullptr));
253
254 BOOST_TEST((dynamicBackendInstance->GetId() == "ValidTestDynamicBackend"));
255}
256
257void CreateDynamicBackendObjectInvalidHandleTestImpl()
258{
259 // Invalid (null) shared object handle
260
261 using namespace armnn;
262
263 void* sharedObjectHandle = nullptr;
264 std::unique_ptr<DynamicBackend> dynamicBackend;
265 BOOST_CHECK_THROW(dynamicBackend.reset(new DynamicBackend(sharedObjectHandle)), InvalidArgumentException);
266 BOOST_TEST((dynamicBackend == nullptr));
267}
268
269void CreateDynamicBackendObjectInvalidInterface1TestImpl()
270{
271 // Valid shared object handle
272 // Wrong (not C-style) name mangling
273
274 using namespace armnn;
275
276 std::string sharedObjectFilePath = GetTestFilePath(g_TestInvalidTestDynamicBackend1FileName);
277
278 void* sharedObjectHandle = nullptr;
279 BOOST_CHECK_NO_THROW(sharedObjectHandle = DynamicBackendUtils::OpenHandle(sharedObjectFilePath));
280 BOOST_TEST((sharedObjectHandle != nullptr));
281
282 std::unique_ptr<DynamicBackend> dynamicBackend;
283 BOOST_CHECK_THROW(dynamicBackend.reset(new DynamicBackend(sharedObjectHandle)), RuntimeException);
284 BOOST_TEST((dynamicBackend == nullptr));
285}
286
287void CreateDynamicBackendObjectInvalidInterface2TestImpl()
288{
289 // Valid shared object handle
290 // Correct name mangling
291 // Wrong interface (missing GetBackendId())
292
293 using namespace armnn;
294
295 std::string sharedObjectFilePath = GetTestFilePath(g_TestInvalidTestDynamicBackend2FileName);
296
297 void* sharedObjectHandle = nullptr;
298 BOOST_CHECK_NO_THROW(sharedObjectHandle = DynamicBackendUtils::OpenHandle(sharedObjectFilePath));
299 BOOST_TEST((sharedObjectHandle != nullptr));
300
301 std::unique_ptr<DynamicBackend> dynamicBackend;
302 BOOST_CHECK_THROW(dynamicBackend.reset(new DynamicBackend(sharedObjectHandle)), RuntimeException);
303 BOOST_TEST((dynamicBackend == nullptr));
304}
305
306void CreateDynamicBackendObjectInvalidInterface3TestImpl()
307{
308 // Valid shared object handle
309 // Correct name mangling
310 // Wrong interface (missing GetVersion())
311
312 using namespace armnn;
313
314 std::string sharedObjectFilePath = GetTestFilePath(g_TestInvalidTestDynamicBackend3FileName);
315
316 void* sharedObjectHandle = nullptr;
317 BOOST_CHECK_NO_THROW(sharedObjectHandle = DynamicBackendUtils::OpenHandle(sharedObjectFilePath));
318 BOOST_TEST((sharedObjectHandle != nullptr));
319
320 std::unique_ptr<DynamicBackend> dynamicBackend;
321 BOOST_CHECK_THROW(dynamicBackend.reset(new DynamicBackend(sharedObjectHandle)), RuntimeException);
322 BOOST_TEST((dynamicBackend == nullptr));
323}
324
325void CreateDynamicBackendObjectInvalidInterface4TestImpl()
326{
327 // Valid shared object handle
328 // Correct name mangling
329 // Wrong interface (missing BackendFactory())
330
331 using namespace armnn;
332
333 std::string sharedObjectFilePath = GetTestFilePath(g_TestInvalidTestDynamicBackend4FileName);
334
335 void* sharedObjectHandle = nullptr;
336 BOOST_CHECK_NO_THROW(sharedObjectHandle = DynamicBackendUtils::OpenHandle(sharedObjectFilePath));
337 BOOST_TEST((sharedObjectHandle != nullptr));
338
339 std::unique_ptr<DynamicBackend> dynamicBackend;
340 BOOST_CHECK_THROW(dynamicBackend.reset(new DynamicBackend(sharedObjectHandle)), RuntimeException);
341 BOOST_TEST((dynamicBackend == nullptr));
342}
343
344void CreateDynamicBackendObjectInvalidInterface5TestImpl()
345{
346 // Valid shared object handle
347 // Correct name mangling
348 // Correct interface
349 // Invalid (null) backend id returned by GetBackendId()
350
351 using namespace armnn;
352
353 std::string sharedObjectFilePath = GetTestFilePath(g_TestInvalidTestDynamicBackend5FileName);
354
355 void* sharedObjectHandle = nullptr;
356 BOOST_CHECK_NO_THROW(sharedObjectHandle = DynamicBackendUtils::OpenHandle(sharedObjectFilePath));
357 BOOST_TEST((sharedObjectHandle != nullptr));
358
359 std::unique_ptr<DynamicBackend> dynamicBackend;
360 BOOST_CHECK_THROW(dynamicBackend.reset(new DynamicBackend(sharedObjectHandle)), RuntimeException);
361 BOOST_TEST((dynamicBackend == nullptr));
362}
363
364void CreateDynamicBackendObjectInvalidInterface6TestImpl()
365{
366 // Valid shared object handle
367 // Correct name mangling
368 // Correct interface
369 // Invalid (null) backend instance returned by BackendFactory()
370
371 using namespace armnn;
372
373 std::string sharedObjectFilePath = GetTestFilePath(g_TestInvalidTestDynamicBackend6FileName);
374
375 void* sharedObjectHandle = nullptr;
376 BOOST_CHECK_NO_THROW(sharedObjectHandle = DynamicBackendUtils::OpenHandle(sharedObjectFilePath));
377 BOOST_TEST((sharedObjectHandle != nullptr));
378
379 std::unique_ptr<DynamicBackend> dynamicBackend;
380 BOOST_CHECK_NO_THROW(dynamicBackend.reset(new DynamicBackend(sharedObjectHandle)));
381 BOOST_TEST((dynamicBackend != nullptr));
382
383 BackendId dynamicBackendId;
384 BOOST_CHECK_NO_THROW(dynamicBackendId = dynamicBackend->GetBackendId());
385 BOOST_TEST((dynamicBackendId == "InvalidTestDynamicBackend"));
386
387 BackendVersion dynamicBackendVersion;
388 BOOST_CHECK_NO_THROW(dynamicBackendVersion = dynamicBackend->GetBackendVersion());
389 BOOST_TEST((dynamicBackendVersion == BackendVersion({ 1, 0 })));
390
391 IBackendInternalUniquePtr dynamicBackendInstance;
392 BOOST_CHECK_THROW(dynamicBackendInstance = dynamicBackend->GetBackend(), RuntimeException);
393 BOOST_TEST((dynamicBackendInstance == nullptr));
394}
395
396void CreateDynamicBackendObjectInvalidInterface7TestImpl()
397{
398 // Valid shared object handle
399 // Correct name mangling
400 // Correct interface
401 // Invalid (incompatible backend API version) backend instance returned by BackendFactory()
402
403 using namespace armnn;
404
405 std::string sharedObjectFilePath = GetTestFilePath(g_TestInvalidTestDynamicBackend7FileName);
406
407 void* sharedObjectHandle = nullptr;
408 BOOST_CHECK_NO_THROW(sharedObjectHandle = DynamicBackendUtils::OpenHandle(sharedObjectFilePath));
409 BOOST_TEST((sharedObjectHandle != nullptr));
410
411 std::unique_ptr<DynamicBackend> dynamicBackend;
412 BOOST_CHECK_THROW(dynamicBackend.reset(new DynamicBackend(sharedObjectHandle)), RuntimeException);
413 BOOST_TEST((dynamicBackend == nullptr));
414}