blob: 0c24ec6f448731fe3b72f869fff86b52f4dd6df6 [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 Martincighe5b8eb92019-11-28 15:45:42 +00008#include <armnn/BackendRegistry.hpp>
Matteo Martincighe5b8eb92019-11-28 15:45:42 +00009#include <armnn/backends/DynamicBackend.hpp>
Jan Eilersbb446e52020-04-02 13:56:54 +010010#include <armnn/ILayerSupport.hpp>
11#include <armnn/utility/PolymorphicDowncast.hpp>
Matteo Martincigh4e73b422019-08-08 13:46:32 +010012#include <backendsCommon/CpuTensorHandle.hpp>
Jan Eilersbb446e52020-04-02 13:56:54 +010013#include <backendsCommon/DynamicBackendUtils.hpp>
Matteo Martincigh4e73b422019-08-08 13:46:32 +010014#include <reference/workloads/RefConvolution2dWorkload.hpp>
Matteo Martincigh3d8a9ed2019-08-08 10:49:03 +010015#include <Runtime.hpp>
16
Matteo Martincighbc2e2102019-07-24 14:56:13 +010017#include <string>
18#include <memory>
Matteo Martincigh986c1862019-07-26 15:12:47 +010019
Matteo Martincighac60d282019-07-25 15:25:44 +010020#include <boost/test/unit_test.hpp>
Matteo Martincigh986c1862019-07-26 15:12:47 +010021#include <boost/filesystem.hpp>
Matteo Martincigha77d80e2019-07-31 11:05:16 +010022#include <boost/dll.hpp>
Matteo Martincigh986c1862019-07-26 15:12:47 +010023
Matteo Martincighd0dc7702019-08-01 17:09:03 +010024static std::string g_TestBaseDir = "src/backends/backendsCommon/test/";
Matteo Martincigh986c1862019-07-26 15:12:47 +010025
Matteo Martincighd0dc7702019-08-01 17:09:03 +010026static std::string g_TestSharedObjectSubDir = "testSharedObject/";
27static std::string g_TestDynamicBackendSubDir = "testDynamicBackend/";
28
29static std::string g_TestSharedObjectFileName = "libTestSharedObject.so";
30static std::string g_TestNoSharedObjectFileName = "libNoSharedObject.txt";
31
32static std::string g_TestValidTestDynamicBackendFileName = "libValidTestDynamicBackend.so";
33static std::string g_TestInvalidTestDynamicBackend1FileName = "libInvalidTestDynamicBackend1.so";
34static std::string g_TestInvalidTestDynamicBackend2FileName = "libInvalidTestDynamicBackend2.so";
35static std::string g_TestInvalidTestDynamicBackend3FileName = "libInvalidTestDynamicBackend3.so";
36static std::string g_TestInvalidTestDynamicBackend4FileName = "libInvalidTestDynamicBackend4.so";
37static std::string g_TestInvalidTestDynamicBackend5FileName = "libInvalidTestDynamicBackend5.so";
38static std::string g_TestInvalidTestDynamicBackend6FileName = "libInvalidTestDynamicBackend6.so";
39static std::string g_TestInvalidTestDynamicBackend7FileName = "libInvalidTestDynamicBackend7.so";
40
Matteo Martincighe54aa062019-08-05 14:12:11 +010041static std::string g_TestValidBackend2FileName = "Arm_TestValid2_backend.so";
42static std::string g_TestValidBackend3FileName = "Arm_TestValid3_backend.so";
43static std::string g_TestValidBackend4FileName = "Arm_TestValid4_backend.so";
Matteo Martincigh0c2b2892019-08-05 14:12:11 +010044static std::string g_TestValidBackend5FileName = "Arm_TestValid5_backend.so";
Matteo Martincighe54aa062019-08-05 14:12:11 +010045static std::string g_TestInvalidBackend8FileName = "Arm_TestInvalid8_backend.so";
46static std::string g_TestInvalidBackend9FileName = "Arm_TestInvalid9_backend.so";
Matteo Martincigh0c2b2892019-08-05 14:12:11 +010047static std::string g_TestInvalidBackend10FileName = "Arm_TestInvalid10_backend.so";
48static std::string g_TestInvalidBackend11FileName = "Arm_TestInvalid11_backend.so";
Matteo Martincighe54aa062019-08-05 14:12:11 +010049
Matteo Martincigh0c2b2892019-08-05 14:12:11 +010050static std::string g_TestDynamicBackendsSubDir1 = "backendsTestPath1/";
51static std::string g_TestDynamicBackendsSubDir2 = "backendsTestPath2/";
52static std::string g_TestDynamicBackendsSubDir3 = "backendsTestPath3/";
53static std::string g_TestDynamicBackendsSubDir4 = "backendsTestPath4/";
54static std::string g_TestDynamicBackendsSubDir5 = "backendsTestPath5/";
55static std::string g_TestDynamicBackendsSubDir6 = "backendsTestPath6/";
56static std::string g_TestDynamicBackendsSubDir7 = "backendsTestPath7/";
57static std::string g_TestDynamicBackendsSubDir8 = "backendsTestPath8/";
58static std::string g_TestDynamicBackendsSubDir9 = "backendsTestPath9/";
59
Matteo Martincigh4e73b422019-08-08 13:46:32 +010060static std::string g_DynamicBackendsBaseDir = "src/backends/dynamic";
61static std::string g_ReferenceDynamicBackendSubDir = "reference/";
62static std::string g_ReferenceBackendFileName = "Arm_CpuRef_backend.so";
63
Matteo Martincigh3d8a9ed2019-08-08 10:49:03 +010064// DynamicBackendUtils wrapper class used for testing (allows to directly invoke the protected methods)
Matteo Martincigh0c2b2892019-08-05 14:12:11 +010065class TestDynamicBackendUtils : public armnn::DynamicBackendUtils
66{
67public:
68 static bool IsBackendCompatibleTest(const armnn::BackendVersion& backendApiVersion,
69 const armnn::BackendVersion& backendVersion)
70 {
71 return IsBackendCompatibleImpl(backendApiVersion, backendVersion);
72 }
73
74 static std::vector<std::string> GetBackendPathsImplTest(const std::string& path)
75 {
76 return GetBackendPathsImpl(path);
77 }
78
Matteo Martincigh89533902019-08-15 12:08:06 +010079 static armnn::BackendIdSet RegisterDynamicBackendsImplTest(
80 armnn::BackendRegistry& backendRegistry,
81 const std::vector<armnn::DynamicBackendPtr>& dynamicBackends)
Matteo Martincigh0c2b2892019-08-05 14:12:11 +010082 {
Matteo Martincigh89533902019-08-15 12:08:06 +010083 return RegisterDynamicBackendsImpl(backendRegistry, dynamicBackends);
Matteo Martincigh0c2b2892019-08-05 14:12:11 +010084 }
85};
Matteo Martincighe7d44982019-08-05 12:16:47 +010086
Matteo Martincigh3d8a9ed2019-08-08 10:49:03 +010087// BackendRegistry wrapper class used for testing (swaps the underlying factory storage)
88class TestBackendRegistry : public armnn::BackendRegistry
89{
90public:
91 TestBackendRegistry() : armnn::BackendRegistry()
92 {
93 Swap(armnn::BackendRegistryInstance(), m_TempStorage);
94 }
95
96 ~TestBackendRegistry()
97 {
98 Swap(armnn::BackendRegistryInstance(), m_TempStorage);
99 }
100
101private:
102 FactoryStorage m_TempStorage;
103};
104
Matteo Martincigh4e73b422019-08-08 13:46:32 +0100105std::string GetBasePath(const std::string& basePath)
Matteo Martincigh986c1862019-07-26 15:12:47 +0100106{
107 using namespace boost::filesystem;
108
Matteo Martincigha77d80e2019-07-31 11:05:16 +0100109 path programLocation = boost::dll::program_location().parent_path();
Matteo Martincigh4e73b422019-08-08 13:46:32 +0100110 path sharedObjectPath = programLocation.append(basePath);
Matteo Martincighd0dc7702019-08-01 17:09:03 +0100111 BOOST_CHECK(exists(sharedObjectPath));
Matteo Martincigh986c1862019-07-26 15:12:47 +0100112
Matteo Martincighd0dc7702019-08-01 17:09:03 +0100113 return sharedObjectPath.string();
114}
115
Matteo Martincigh4e73b422019-08-08 13:46:32 +0100116std::string GetTestDirectoryBasePath()
117{
118 return GetBasePath(g_TestBaseDir);
119}
120
121std::string GetDynamicBackendsBasePath()
122{
123 return GetBasePath(g_DynamicBackendsBaseDir);
124}
125
Matteo Martincighd0dc7702019-08-01 17:09:03 +0100126std::string GetTestSubDirectory(const std::string& subdir)
127{
128 using namespace boost::filesystem;
129
130 std::string testDynamicBackendsBaseDir = GetTestDirectoryBasePath();
131 path testDynamicBackendsBasePath(testDynamicBackendsBaseDir);
132 path testDynamicBackendsSubDir = testDynamicBackendsBasePath.append(subdir);
133 // Do not check that the sub-directory exists because for testing reasons we may use non-existing paths
134
135 return testDynamicBackendsSubDir.string();
136}
137
Matteo Martincigh4e73b422019-08-08 13:46:32 +0100138std::string GetTestSubDirectory(const std::string& basePath, const std::string& subdir)
139{
140 using namespace boost::filesystem;
141
142 path testDynamicBackendsBasePath(basePath);
143 path testDynamicBackendsSubDir = testDynamicBackendsBasePath.append(subdir);
144 // Do not check that the sub-directory exists because for testing reasons we may use non-existing paths
145
146 return testDynamicBackendsSubDir.string();
147}
148
Matteo Martincighd0dc7702019-08-01 17:09:03 +0100149std::string GetTestFilePath(const std::string& directory, const std::string& fileName)
150{
151 using namespace boost::filesystem;
152
153 path directoryPath(directory);
154 path fileNamePath = directoryPath.append(fileName);
155 BOOST_CHECK(exists(fileNamePath));
156
157 return fileNamePath.string();
Matteo Martincigh986c1862019-07-26 15:12:47 +0100158}
159
160void OpenCloseHandleTestImpl()
161{
162 using namespace armnn;
163
Matteo Martincighd0dc7702019-08-01 17:09:03 +0100164 std::string testSubDirectory = GetTestSubDirectory(g_TestSharedObjectSubDir);
165 std::string sharedObjectFilePath = GetTestFilePath(testSubDirectory, g_TestSharedObjectFileName);
Matteo Martincigh986c1862019-07-26 15:12:47 +0100166
167 void* sharedObjectHandle = nullptr;
168 BOOST_CHECK_NO_THROW(sharedObjectHandle = DynamicBackendUtils::OpenHandle(sharedObjectFilePath));
169 BOOST_TEST((sharedObjectHandle != nullptr));
170
171 DynamicBackendUtils::CloseHandle(sharedObjectHandle);
172}
173
174void CloseInvalidHandleTestImpl()
175{
176 using namespace armnn;
177
178 // This calls must silently handle invalid handles and complete successfully (no segfaults, etc.)
179 DynamicBackendUtils::CloseHandle(nullptr);
180}
181
182void OpenEmptyFileNameTestImpl()
183{
184 using namespace armnn;
185
186 void* sharedObjectHandle = nullptr;
187 BOOST_CHECK_THROW(sharedObjectHandle = DynamicBackendUtils::OpenHandle(""), RuntimeException);
188 BOOST_TEST((sharedObjectHandle == nullptr));
189}
190
191void OpenNotExistingFileTestImpl()
192{
193 using namespace armnn;
194
195 void* sharedObjectHandle = nullptr;
196 BOOST_CHECK_THROW(sharedObjectHandle = DynamicBackendUtils::OpenHandle("NotExistingFileName"), RuntimeException);
197 BOOST_TEST((sharedObjectHandle == nullptr));
198}
199
200void OpenNotSharedObjectTestImpl()
201{
202 using namespace armnn;
203
Matteo Martincighd0dc7702019-08-01 17:09:03 +0100204 std::string testSubDirectory = GetTestSubDirectory(g_TestSharedObjectSubDir);
205 std::string notSharedObjectFilePath = GetTestFilePath(testSubDirectory, g_TestNoSharedObjectFileName);
Matteo Martincigh986c1862019-07-26 15:12:47 +0100206
207 void* sharedObjectHandle = nullptr;
208 BOOST_CHECK_THROW(sharedObjectHandle = DynamicBackendUtils::OpenHandle(notSharedObjectFilePath), RuntimeException);
209 BOOST_TEST((sharedObjectHandle == nullptr));
210}
211
212void GetValidEntryPointTestImpl()
213{
214 using namespace armnn;
215
Matteo Martincighd0dc7702019-08-01 17:09:03 +0100216 std::string testSubDirectory = GetTestSubDirectory(g_TestSharedObjectSubDir);
217 std::string sharedObjectFilePath = GetTestFilePath(testSubDirectory, g_TestSharedObjectFileName);
Matteo Martincigh986c1862019-07-26 15:12:47 +0100218
219 void* sharedObjectHandle = nullptr;
220 BOOST_CHECK_NO_THROW(sharedObjectHandle = DynamicBackendUtils::OpenHandle(sharedObjectFilePath));
221 BOOST_TEST((sharedObjectHandle != nullptr));
222
223 using TestFunctionType = int(*)(int);
224 TestFunctionType testFunctionPointer = nullptr;
225 BOOST_CHECK_NO_THROW(testFunctionPointer = DynamicBackendUtils::GetEntryPoint<TestFunctionType>(sharedObjectHandle,
226 "TestFunction1"));
227 BOOST_TEST((testFunctionPointer != nullptr));
228 BOOST_TEST(testFunctionPointer(7) == 7);
229
230 DynamicBackendUtils::CloseHandle(sharedObjectHandle);
231}
232
233void GetNameMangledEntryPointTestImpl()
234{
235 using namespace armnn;
236
Matteo Martincighd0dc7702019-08-01 17:09:03 +0100237 std::string testSubDirectory = GetTestSubDirectory(g_TestSharedObjectSubDir);
238 std::string sharedObjectFilePath = GetTestFilePath(testSubDirectory, g_TestSharedObjectFileName);
Matteo Martincigh986c1862019-07-26 15:12:47 +0100239
240 void* sharedObjectHandle = nullptr;
241 BOOST_CHECK_NO_THROW(sharedObjectHandle = DynamicBackendUtils::OpenHandle(sharedObjectFilePath));
242 BOOST_TEST((sharedObjectHandle != nullptr));
243
244 using TestFunctionType = int(*)(int);
245 TestFunctionType testFunctionPointer = nullptr;
246 BOOST_CHECK_THROW(testFunctionPointer = DynamicBackendUtils::GetEntryPoint<TestFunctionType>(sharedObjectHandle,
247 "TestFunction2"),
248 RuntimeException);
249 BOOST_TEST((testFunctionPointer == nullptr));
250
251 DynamicBackendUtils::CloseHandle(sharedObjectHandle);
252}
253
254void GetNoExternEntryPointTestImpl()
255{
256 using namespace armnn;
257
Matteo Martincighd0dc7702019-08-01 17:09:03 +0100258 std::string testSubDirectory = GetTestSubDirectory(g_TestSharedObjectSubDir);
259 std::string sharedObjectFilePath = GetTestFilePath(testSubDirectory, g_TestSharedObjectFileName);
Matteo Martincigh986c1862019-07-26 15:12:47 +0100260
261 void* sharedObjectHandle = nullptr;
262 BOOST_CHECK_NO_THROW(sharedObjectHandle = DynamicBackendUtils::OpenHandle(sharedObjectFilePath));
263 BOOST_TEST((sharedObjectHandle != nullptr));
264
265 using TestFunctionType = int(*)(int);
266 TestFunctionType testFunctionPointer = nullptr;
267 BOOST_CHECK_THROW(testFunctionPointer = DynamicBackendUtils::GetEntryPoint<TestFunctionType>(sharedObjectHandle,
268 "TestFunction3"),
269 RuntimeException);
270 BOOST_TEST((testFunctionPointer == nullptr));
271
272 DynamicBackendUtils::CloseHandle(sharedObjectHandle);
273}
274
275void GetNotExistingEntryPointTestImpl()
276{
277 using namespace armnn;
278
Matteo Martincighd0dc7702019-08-01 17:09:03 +0100279 std::string testSubDirectory = GetTestSubDirectory(g_TestSharedObjectSubDir);
280 std::string sharedObjectFilePath = GetTestFilePath(testSubDirectory, g_TestSharedObjectFileName);
Matteo Martincigh986c1862019-07-26 15:12:47 +0100281
282 void* sharedObjectHandle = nullptr;
283 BOOST_CHECK_NO_THROW(sharedObjectHandle = DynamicBackendUtils::OpenHandle(sharedObjectFilePath));
284 BOOST_TEST((sharedObjectHandle != nullptr));
285
286 using TestFunctionType = int(*)(int);
287 TestFunctionType testFunctionPointer = nullptr;
288 BOOST_CHECK_THROW(testFunctionPointer = DynamicBackendUtils::GetEntryPoint<TestFunctionType>(sharedObjectHandle,
289 "TestFunction4"),
290 RuntimeException);
291 BOOST_TEST((testFunctionPointer == nullptr));
292
293 DynamicBackendUtils::CloseHandle(sharedObjectHandle);
294}
Matteo Martincighac60d282019-07-25 15:25:44 +0100295
296void BackendVersioningTestImpl()
297{
Matteo Martincigh986c1862019-07-26 15:12:47 +0100298 using namespace armnn;
299
Matteo Martincighac60d282019-07-25 15:25:44 +0100300 // The backend API version used for the tests
Matteo Martincigh986c1862019-07-26 15:12:47 +0100301 BackendVersion backendApiVersion{ 2, 4 };
Matteo Martincighac60d282019-07-25 15:25:44 +0100302
303 // Same backend and backend API versions are compatible with the backend API
Matteo Martincigh986c1862019-07-26 15:12:47 +0100304 BackendVersion sameBackendVersion{ 2, 4 };
Matteo Martincighac60d282019-07-25 15:25:44 +0100305 BOOST_TEST(sameBackendVersion == backendApiVersion);
306 BOOST_TEST(sameBackendVersion <= backendApiVersion);
307 BOOST_TEST(TestDynamicBackendUtils::IsBackendCompatibleTest(backendApiVersion, sameBackendVersion) == true);
308
309 // Backend versions that differ from the backend API version by major revision are not compatible
310 // with the backend API
Matteo Martincigh986c1862019-07-26 15:12:47 +0100311 BackendVersion laterMajorBackendVersion{ 3, 4 };
Matteo Martincighac60d282019-07-25 15:25:44 +0100312 BOOST_TEST(!(laterMajorBackendVersion == backendApiVersion));
313 BOOST_TEST(!(laterMajorBackendVersion <= backendApiVersion));
314 BOOST_TEST(TestDynamicBackendUtils::IsBackendCompatibleTest(backendApiVersion, laterMajorBackendVersion) == false);
315
Matteo Martincigh986c1862019-07-26 15:12:47 +0100316 BackendVersion earlierMajorBackendVersion{ 1, 4 };
Matteo Martincighac60d282019-07-25 15:25:44 +0100317 BOOST_TEST(!(earlierMajorBackendVersion == backendApiVersion));
318 BOOST_TEST(earlierMajorBackendVersion <= backendApiVersion);
319 BOOST_TEST(TestDynamicBackendUtils::IsBackendCompatibleTest(backendApiVersion,
320 earlierMajorBackendVersion) == false);
321
322 // Backend versions with the same major revision but later minor revision than
323 // the backend API version are not compatible with the backend API
Matteo Martincigh986c1862019-07-26 15:12:47 +0100324 BackendVersion laterMinorBackendVersion{ 2, 5 };
Matteo Martincighac60d282019-07-25 15:25:44 +0100325 BOOST_TEST(!(laterMinorBackendVersion == backendApiVersion));
326 BOOST_TEST(!(laterMinorBackendVersion <= backendApiVersion));
327 BOOST_TEST(TestDynamicBackendUtils::IsBackendCompatibleTest(backendApiVersion, laterMinorBackendVersion) == false);
328
329 // Backend versions with the same major revision but earlier minor revision than
330 // the backend API version are compatible with the backend API
Matteo Martincigh986c1862019-07-26 15:12:47 +0100331 BackendVersion earlierMinorBackendVersion{ 2, 3 };
Matteo Martincighac60d282019-07-25 15:25:44 +0100332 BOOST_TEST(!(earlierMinorBackendVersion == backendApiVersion));
333 BOOST_TEST(earlierMinorBackendVersion <= backendApiVersion);
334 BOOST_TEST(TestDynamicBackendUtils::IsBackendCompatibleTest(backendApiVersion, earlierMinorBackendVersion) == true);
335}
Matteo Martincighbc2e2102019-07-24 14:56:13 +0100336
337void CreateValidDynamicBackendObjectTestImpl()
338{
339 // Valid shared object handle
340 // Correct name mangling
341 // Correct interface
342 // Correct backend implementation
343
344 using namespace armnn;
345
Matteo Martincighd0dc7702019-08-01 17:09:03 +0100346 std::string testSubDirectory = GetTestSubDirectory(g_TestDynamicBackendSubDir);
347 std::string sharedObjectFilePath = GetTestFilePath(testSubDirectory, g_TestValidTestDynamicBackendFileName);
Matteo Martincighbc2e2102019-07-24 14:56:13 +0100348
349 void* sharedObjectHandle = nullptr;
350 BOOST_CHECK_NO_THROW(sharedObjectHandle = DynamicBackendUtils::OpenHandle(sharedObjectFilePath));
351 BOOST_TEST((sharedObjectHandle != nullptr));
352
Matteo Martincighe54aa062019-08-05 14:12:11 +0100353 DynamicBackendPtr dynamicBackend;
Matteo Martincighbc2e2102019-07-24 14:56:13 +0100354 BOOST_CHECK_NO_THROW(dynamicBackend.reset(new DynamicBackend(sharedObjectHandle)));
355 BOOST_TEST((dynamicBackend != nullptr));
356
357 BackendId dynamicBackendId;
358 BOOST_CHECK_NO_THROW(dynamicBackendId = dynamicBackend->GetBackendId());
359 BOOST_TEST((dynamicBackendId == "ValidTestDynamicBackend"));
360
361 BackendVersion dynamicBackendVersion;
362 BOOST_CHECK_NO_THROW(dynamicBackendVersion = dynamicBackend->GetBackendVersion());
Matteo Martincighe54aa062019-08-05 14:12:11 +0100363 BOOST_TEST((dynamicBackendVersion == IBackendInternal::GetApiVersion()));
Matteo Martincighbc2e2102019-07-24 14:56:13 +0100364
Matteo Martincigh0c2b2892019-08-05 14:12:11 +0100365 IBackendInternalUniquePtr dynamicBackendInstance1;
366 BOOST_CHECK_NO_THROW(dynamicBackendInstance1 = dynamicBackend->GetBackend());
367 BOOST_TEST((dynamicBackendInstance1 != nullptr));
Matteo Martincighbc2e2102019-07-24 14:56:13 +0100368
Matteo Martincigh0c2b2892019-08-05 14:12:11 +0100369 BackendRegistry::FactoryFunction dynamicBackendFactoryFunction = nullptr;
370 BOOST_CHECK_NO_THROW(dynamicBackendFactoryFunction = dynamicBackend->GetFactoryFunction());
371 BOOST_TEST((dynamicBackendFactoryFunction != nullptr));
372
373 IBackendInternalUniquePtr dynamicBackendInstance2;
374 BOOST_CHECK_NO_THROW(dynamicBackendInstance2 = dynamicBackendFactoryFunction());
375 BOOST_TEST((dynamicBackendInstance2 != nullptr));
376
377 BOOST_TEST((dynamicBackendInstance1->GetId() == "ValidTestDynamicBackend"));
378 BOOST_TEST((dynamicBackendInstance2->GetId() == "ValidTestDynamicBackend"));
Matteo Martincighbc2e2102019-07-24 14:56:13 +0100379}
380
381void CreateDynamicBackendObjectInvalidHandleTestImpl()
382{
383 // Invalid (null) shared object handle
384
385 using namespace armnn;
386
387 void* sharedObjectHandle = nullptr;
Matteo Martincighe54aa062019-08-05 14:12:11 +0100388 DynamicBackendPtr dynamicBackend;
Matteo Martincighbc2e2102019-07-24 14:56:13 +0100389 BOOST_CHECK_THROW(dynamicBackend.reset(new DynamicBackend(sharedObjectHandle)), InvalidArgumentException);
390 BOOST_TEST((dynamicBackend == nullptr));
391}
392
393void CreateDynamicBackendObjectInvalidInterface1TestImpl()
394{
395 // Valid shared object handle
396 // Wrong (not C-style) name mangling
397
398 using namespace armnn;
399
Matteo Martincighd0dc7702019-08-01 17:09:03 +0100400 std::string testSubDirectory = GetTestSubDirectory(g_TestDynamicBackendSubDir);
401 std::string sharedObjectFilePath = GetTestFilePath(testSubDirectory, g_TestInvalidTestDynamicBackend1FileName);
Matteo Martincighbc2e2102019-07-24 14:56:13 +0100402
403 void* sharedObjectHandle = nullptr;
404 BOOST_CHECK_NO_THROW(sharedObjectHandle = DynamicBackendUtils::OpenHandle(sharedObjectFilePath));
405 BOOST_TEST((sharedObjectHandle != nullptr));
406
Matteo Martincighe54aa062019-08-05 14:12:11 +0100407 DynamicBackendPtr dynamicBackend;
Matteo Martincighbc2e2102019-07-24 14:56:13 +0100408 BOOST_CHECK_THROW(dynamicBackend.reset(new DynamicBackend(sharedObjectHandle)), RuntimeException);
409 BOOST_TEST((dynamicBackend == nullptr));
410}
411
412void CreateDynamicBackendObjectInvalidInterface2TestImpl()
413{
414 // Valid shared object handle
415 // Correct name mangling
416 // Wrong interface (missing GetBackendId())
417
418 using namespace armnn;
419
Matteo Martincighd0dc7702019-08-01 17:09:03 +0100420 std::string testSubDirectory = GetTestSubDirectory(g_TestDynamicBackendSubDir);
421 std::string sharedObjectFilePath = GetTestFilePath(testSubDirectory, g_TestInvalidTestDynamicBackend2FileName);
Matteo Martincighbc2e2102019-07-24 14:56:13 +0100422
423 void* sharedObjectHandle = nullptr;
424 BOOST_CHECK_NO_THROW(sharedObjectHandle = DynamicBackendUtils::OpenHandle(sharedObjectFilePath));
425 BOOST_TEST((sharedObjectHandle != nullptr));
426
Matteo Martincighe54aa062019-08-05 14:12:11 +0100427 DynamicBackendPtr dynamicBackend;
Matteo Martincighbc2e2102019-07-24 14:56:13 +0100428 BOOST_CHECK_THROW(dynamicBackend.reset(new DynamicBackend(sharedObjectHandle)), RuntimeException);
429 BOOST_TEST((dynamicBackend == nullptr));
430}
431
432void CreateDynamicBackendObjectInvalidInterface3TestImpl()
433{
434 // Valid shared object handle
435 // Correct name mangling
436 // Wrong interface (missing GetVersion())
437
438 using namespace armnn;
439
Matteo Martincighd0dc7702019-08-01 17:09:03 +0100440 std::string testSubDirectory = GetTestSubDirectory(g_TestDynamicBackendSubDir);
441 std::string sharedObjectFilePath = GetTestFilePath(testSubDirectory, g_TestInvalidTestDynamicBackend3FileName);
Matteo Martincighbc2e2102019-07-24 14:56:13 +0100442
443 void* sharedObjectHandle = nullptr;
444 BOOST_CHECK_NO_THROW(sharedObjectHandle = DynamicBackendUtils::OpenHandle(sharedObjectFilePath));
445 BOOST_TEST((sharedObjectHandle != nullptr));
446
Matteo Martincighe54aa062019-08-05 14:12:11 +0100447 DynamicBackendPtr dynamicBackend;
Matteo Martincighbc2e2102019-07-24 14:56:13 +0100448 BOOST_CHECK_THROW(dynamicBackend.reset(new DynamicBackend(sharedObjectHandle)), RuntimeException);
449 BOOST_TEST((dynamicBackend == nullptr));
450}
451
452void CreateDynamicBackendObjectInvalidInterface4TestImpl()
453{
454 // Valid shared object handle
455 // Correct name mangling
456 // Wrong interface (missing BackendFactory())
457
458 using namespace armnn;
459
Matteo Martincighd0dc7702019-08-01 17:09:03 +0100460 std::string testSubDirectory = GetTestSubDirectory(g_TestDynamicBackendSubDir);
461 std::string sharedObjectFilePath = GetTestFilePath(testSubDirectory, g_TestInvalidTestDynamicBackend4FileName);
Matteo Martincighbc2e2102019-07-24 14:56:13 +0100462
463 void* sharedObjectHandle = nullptr;
464 BOOST_CHECK_NO_THROW(sharedObjectHandle = DynamicBackendUtils::OpenHandle(sharedObjectFilePath));
465 BOOST_TEST((sharedObjectHandle != nullptr));
466
Matteo Martincighe54aa062019-08-05 14:12:11 +0100467 DynamicBackendPtr dynamicBackend;
Matteo Martincighbc2e2102019-07-24 14:56:13 +0100468 BOOST_CHECK_THROW(dynamicBackend.reset(new DynamicBackend(sharedObjectHandle)), RuntimeException);
469 BOOST_TEST((dynamicBackend == nullptr));
470}
471
472void CreateDynamicBackendObjectInvalidInterface5TestImpl()
473{
474 // Valid shared object handle
475 // Correct name mangling
476 // Correct interface
477 // Invalid (null) backend id returned by GetBackendId()
478
479 using namespace armnn;
480
Matteo Martincighd0dc7702019-08-01 17:09:03 +0100481 std::string testSubDirectory = GetTestSubDirectory(g_TestDynamicBackendSubDir);
482 std::string sharedObjectFilePath = GetTestFilePath(testSubDirectory, g_TestInvalidTestDynamicBackend5FileName);
Matteo Martincighbc2e2102019-07-24 14:56:13 +0100483
484 void* sharedObjectHandle = nullptr;
485 BOOST_CHECK_NO_THROW(sharedObjectHandle = DynamicBackendUtils::OpenHandle(sharedObjectFilePath));
486 BOOST_TEST((sharedObjectHandle != nullptr));
487
Matteo Martincighe54aa062019-08-05 14:12:11 +0100488 DynamicBackendPtr dynamicBackend;
Matteo Martincighbc2e2102019-07-24 14:56:13 +0100489 BOOST_CHECK_THROW(dynamicBackend.reset(new DynamicBackend(sharedObjectHandle)), RuntimeException);
490 BOOST_TEST((dynamicBackend == nullptr));
491}
492
493void CreateDynamicBackendObjectInvalidInterface6TestImpl()
494{
495 // Valid shared object handle
496 // Correct name mangling
497 // Correct interface
498 // Invalid (null) backend instance returned by BackendFactory()
499
500 using namespace armnn;
501
Matteo Martincighd0dc7702019-08-01 17:09:03 +0100502 std::string testSubDirectory = GetTestSubDirectory(g_TestDynamicBackendSubDir);
503 std::string sharedObjectFilePath = GetTestFilePath(testSubDirectory, g_TestInvalidTestDynamicBackend6FileName);
Matteo Martincighbc2e2102019-07-24 14:56:13 +0100504
505 void* sharedObjectHandle = nullptr;
506 BOOST_CHECK_NO_THROW(sharedObjectHandle = DynamicBackendUtils::OpenHandle(sharedObjectFilePath));
507 BOOST_TEST((sharedObjectHandle != nullptr));
508
Matteo Martincighe54aa062019-08-05 14:12:11 +0100509 DynamicBackendPtr dynamicBackend;
Matteo Martincighbc2e2102019-07-24 14:56:13 +0100510 BOOST_CHECK_NO_THROW(dynamicBackend.reset(new DynamicBackend(sharedObjectHandle)));
511 BOOST_TEST((dynamicBackend != nullptr));
512
513 BackendId dynamicBackendId;
514 BOOST_CHECK_NO_THROW(dynamicBackendId = dynamicBackend->GetBackendId());
515 BOOST_TEST((dynamicBackendId == "InvalidTestDynamicBackend"));
516
517 BackendVersion dynamicBackendVersion;
518 BOOST_CHECK_NO_THROW(dynamicBackendVersion = dynamicBackend->GetBackendVersion());
519 BOOST_TEST((dynamicBackendVersion == BackendVersion({ 1, 0 })));
520
Matteo Martincigh0c2b2892019-08-05 14:12:11 +0100521 IBackendInternalUniquePtr dynamicBackendInstance1;
522 BOOST_CHECK_THROW(dynamicBackendInstance1 = dynamicBackend->GetBackend(), RuntimeException);
523 BOOST_TEST((dynamicBackendInstance1 == nullptr));
524
525 BackendRegistry::FactoryFunction dynamicBackendFactoryFunction = nullptr;
526 BOOST_CHECK_NO_THROW(dynamicBackendFactoryFunction = dynamicBackend->GetFactoryFunction());
527 BOOST_TEST((dynamicBackendFactoryFunction != nullptr));
528
529 IBackendInternalUniquePtr dynamicBackendInstance2;
530 BOOST_CHECK_THROW(dynamicBackendInstance2 = dynamicBackendFactoryFunction(), RuntimeException);
531 BOOST_TEST((dynamicBackendInstance2 == nullptr));
Matteo Martincighbc2e2102019-07-24 14:56:13 +0100532}
533
534void CreateDynamicBackendObjectInvalidInterface7TestImpl()
535{
536 // Valid shared object handle
537 // Correct name mangling
538 // Correct interface
539 // Invalid (incompatible backend API version) backend instance returned by BackendFactory()
540
541 using namespace armnn;
542
Matteo Martincighd0dc7702019-08-01 17:09:03 +0100543 std::string testSubDirectory = GetTestSubDirectory(g_TestDynamicBackendSubDir);
544 std::string sharedObjectFilePath = GetTestFilePath(testSubDirectory, g_TestInvalidTestDynamicBackend7FileName);
Matteo Martincighbc2e2102019-07-24 14:56:13 +0100545
546 void* sharedObjectHandle = nullptr;
547 BOOST_CHECK_NO_THROW(sharedObjectHandle = DynamicBackendUtils::OpenHandle(sharedObjectFilePath));
548 BOOST_TEST((sharedObjectHandle != nullptr));
549
Matteo Martincighe54aa062019-08-05 14:12:11 +0100550 DynamicBackendPtr dynamicBackend;
Matteo Martincighbc2e2102019-07-24 14:56:13 +0100551 BOOST_CHECK_THROW(dynamicBackend.reset(new DynamicBackend(sharedObjectHandle)), RuntimeException);
552 BOOST_TEST((dynamicBackend == nullptr));
553}
Matteo Martincighe7d44982019-08-05 12:16:47 +0100554
555void GetBackendPathsTestImpl()
556{
557 using namespace armnn;
558 using namespace boost::filesystem;
559
560 // The test covers four directories:
561 // <unit test path>/src/backends/backendsCommon/test/
Matteo Martincighe54aa062019-08-05 14:12:11 +0100562 // ├─ backendsTestPath1/ -> exists, contains files
563 // ├─ backendsTestPath2/ -> exists, contains files
564 // ├─ backendsTestPath3/ -> exists, but empty
565 // └─ backendsTestPath4/ -> does not exist
Matteo Martincighe7d44982019-08-05 12:16:47 +0100566
Matteo Martincigh0c2b2892019-08-05 14:12:11 +0100567 std::string subDir1 = GetTestSubDirectory(g_TestDynamicBackendsSubDir1);
568 std::string subDir2 = GetTestSubDirectory(g_TestDynamicBackendsSubDir2);
569 std::string subDir3 = GetTestSubDirectory(g_TestDynamicBackendsSubDir3);
570 std::string subDir4 = GetTestSubDirectory(g_TestDynamicBackendsSubDir4);
Matteo Martincighe7d44982019-08-05 12:16:47 +0100571
572 BOOST_CHECK(exists(subDir1));
573 BOOST_CHECK(exists(subDir2));
574 BOOST_CHECK(exists(subDir3));
575 BOOST_CHECK(!exists(subDir4));
576
Matteo Martincighe7d44982019-08-05 12:16:47 +0100577 // No path
578 BOOST_TEST(TestDynamicBackendUtils::GetBackendPathsImplTest("").empty());
579
580 // Malformed path
581 std::string malformedDir(subDir1 + "/" + subDir1);
582 BOOST_TEST(TestDynamicBackendUtils::GetBackendPathsImplTest(malformedDir).size()==0);
583
584 // Single valid path
585 std::vector<std::string> DynamicBackendPaths2 = TestDynamicBackendUtils::GetBackendPathsImplTest(subDir1);
586 BOOST_TEST(DynamicBackendPaths2.size() == 1);
587 BOOST_TEST(DynamicBackendPaths2[0] == subDir1);
588
589 // Multiple equal and valid paths
590 std::string multipleEqualDirs(subDir1 + ":" + subDir1);
591 std::vector<std::string> DynamicBackendPaths3 = TestDynamicBackendUtils::GetBackendPathsImplTest(multipleEqualDirs);
592 BOOST_TEST(DynamicBackendPaths3.size() == 1);
593 BOOST_TEST(DynamicBackendPaths3[0] == subDir1);
594
595 // Multiple empty paths
596 BOOST_TEST(TestDynamicBackendUtils::GetBackendPathsImplTest(":::").empty());
597
598 // Multiple valid paths
599 std::string multipleValidPaths(subDir1 + ":" + subDir2 + ":" + subDir3);
600 std::vector<std::string> DynamicBackendPaths5 =
601 TestDynamicBackendUtils::GetBackendPathsImplTest(multipleValidPaths);
602 BOOST_TEST(DynamicBackendPaths5.size() == 3);
603 BOOST_TEST(DynamicBackendPaths5[0] == subDir1);
604 BOOST_TEST(DynamicBackendPaths5[1] == subDir2);
605 BOOST_TEST(DynamicBackendPaths5[2] == subDir3);
606
607 // Valid among empty paths
608 std::string validAmongEmptyDirs("::" + subDir1 + ":");
609 std::vector<std::string> DynamicBackendPaths6 =
610 TestDynamicBackendUtils::GetBackendPathsImplTest(validAmongEmptyDirs);
611 BOOST_TEST(DynamicBackendPaths6.size() == 1);
612 BOOST_TEST(DynamicBackendPaths6[0] == subDir1);
613
614 // Invalid among empty paths
615 std::string invalidAmongEmptyDirs(":" + subDir4 + "::");
616 BOOST_TEST(TestDynamicBackendUtils::GetBackendPathsImplTest(invalidAmongEmptyDirs).empty());
617
618 // Valid, invalid and empty paths
619 std::string validInvalidEmptyDirs(subDir1 + ":" + subDir4 + ":");
620 std::vector<std::string> DynamicBackendPaths8 =
621 TestDynamicBackendUtils::GetBackendPathsImplTest(validInvalidEmptyDirs);
622 BOOST_TEST(DynamicBackendPaths8.size() == 1);
623 BOOST_TEST(DynamicBackendPaths8[0] == subDir1);
624
625 // Mix of duplicates of valid, invalid and empty paths
626 std::string duplicateValidInvalidEmptyDirs(validInvalidEmptyDirs + ":" + validInvalidEmptyDirs + ":" +
627 subDir2 + ":" + subDir2);
628 std::vector<std::string> DynamicBackendPaths9 =
629 TestDynamicBackendUtils::GetBackendPathsImplTest(duplicateValidInvalidEmptyDirs);
630 BOOST_TEST(DynamicBackendPaths9.size() == 2);
631 BOOST_TEST(DynamicBackendPaths9[0] == subDir1);
632 BOOST_TEST(DynamicBackendPaths9[1] == subDir2);
633}
634
635void GetBackendPathsOverrideTestImpl()
636{
637 using namespace armnn;
638 using namespace boost::filesystem;
639
Matteo Martincigh0c2b2892019-08-05 14:12:11 +0100640 std::string subDir1 = GetTestSubDirectory(g_TestDynamicBackendsSubDir1);
641 std::string subDir4 = GetTestSubDirectory(g_TestDynamicBackendsSubDir4);
Matteo Martincighe7d44982019-08-05 12:16:47 +0100642
643 BOOST_CHECK(exists(subDir1));
644 BOOST_CHECK(!exists(subDir4));
645
646 // Override with valid path
647 std::vector<std::string> validResult = DynamicBackendUtils::GetBackendPaths(subDir1);
648 BOOST_TEST(validResult.size() == 1);
649 BOOST_TEST(validResult[0] == subDir1);
650
651 // Override with invalid path
652 std::vector<std::string> invalidResult = DynamicBackendUtils::GetBackendPaths(subDir4);
653 BOOST_TEST(invalidResult.empty());
654}
Jan Eilers4a539fc2019-07-25 17:08:37 +0100655
656void GetSharedObjectsTestImpl()
657{
658 using namespace armnn;
659 using namespace boost::filesystem;
660
Matteo Martincighe54aa062019-08-05 14:12:11 +0100661 // The test covers four directories:
662 // <unit test path>/src/backends/backendsCommon/test/
663 // ├─ backendsTestPath1/ -> exists, contains files
664 // ├─ backendsTestPath2/ -> exists, contains files
665 // ├─ backendsTestPath3/ -> exists, but empty
666 // └─ backendsTestPath4/ -> does not exist
Jan Eilers4a539fc2019-07-25 17:08:37 +0100667 //
668 // The test sub-directory backendsTestPath1/ contains the following test files:
669 //
670 // Arm_GpuAcc_backend.so -> valid (basic backend name)
671 // Arm_GpuAcc_backend.so.1 -> valid (single field version number)
672 // Arm_GpuAcc_backend.so.1.2 -> valid (multiple field version number)
673 // Arm_GpuAcc_backend.so.1.2.3 -> valid (multiple field version number)
674 // Arm_GpuAcc_backend.so.10.1.27 -> valid (Multiple digit version)
675 // Arm_GpuAcc_backend.so.10.1.33. -> not valid (dot not followed by version number)
676 // Arm_GpuAcc_backend.so.3.4..5 -> not valid (dot not followed by version number)
677 // Arm_GpuAcc_backend.so.1,1.1 -> not valid (comma instead of dot in the version)
678 //
679 // Arm123_GpuAcc_backend.so -> valid (digits in vendor name are allowed)
680 // Arm_GpuAcc456_backend.so -> valid (digits in backend id are allowed)
681 // Arm%Co_GpuAcc_backend.so -> not valid (invalid character in vendor name)
682 // Arm_Gpu.Acc_backend.so -> not valid (invalid character in backend id)
683 //
684 // GpuAcc_backend.so -> not valid (missing vendor name)
685 // _GpuAcc_backend.so -> not valid (missing vendor name)
686 // Arm__backend.so -> not valid (missing backend id)
687 // Arm_GpuAcc.so -> not valid (missing "backend" at the end)
688 // __backend.so -> not valid (missing vendor name and backend id)
689 // __.so -> not valid (missing all fields)
690 //
691 // Arm_GpuAcc_backend -> not valid (missing at least ".so" at the end)
692 // Arm_GpuAcc_backend_v1.2.so -> not valid (extra version info at the end)
693 //
694 // The test sub-directory backendsTestPath1/ contains the following test files:
695 //
696 // Arm_CpuAcc_backend.so -> valid (basic backend name)
697 // Arm_CpuAcc_backend.so.1 -> Arm_CpuAcc_backend.so -> valid (symlink to valid backend file)
698 // Arm_CpuAcc_backend.so.1.2 -> Arm_CpuAcc_backend.so.1 -> valid (symlink to valid symlink)
699 // Arm_CpuAcc_backend.so.1.2.3 -> Arm_CpuAcc_backend.so.1.2 -> valid (symlink to valid symlink)
700 //
701 // Arm_no_backend.so -> nothing -> not valid (symlink resolves to non-existent file)
702 //
703 // Arm_GpuAcc_backend.so -> valid (but duplicated from backendsTestPath1/)
704
Matteo Martincigh0c2b2892019-08-05 14:12:11 +0100705 std::string testDynamicBackendsSubDir1 = GetTestSubDirectory(g_TestDynamicBackendsSubDir1);
706 std::string testDynamicBackendsSubDir2 = GetTestSubDirectory(g_TestDynamicBackendsSubDir2);
707 std::string testDynamicBackendsSubDir3 = GetTestSubDirectory(g_TestDynamicBackendsSubDir3);
708 std::string testDynamicBackendsSubDir4 = GetTestSubDirectory(g_TestDynamicBackendsSubDir4);
Jan Eilers4a539fc2019-07-25 17:08:37 +0100709 BOOST_CHECK(exists(testDynamicBackendsSubDir1));
710 BOOST_CHECK(exists(testDynamicBackendsSubDir2));
711 BOOST_CHECK(exists(testDynamicBackendsSubDir3));
712 BOOST_CHECK(!exists(testDynamicBackendsSubDir4));
713
714 std::vector<std::string> backendPaths
715 {
716 testDynamicBackendsSubDir1,
717 testDynamicBackendsSubDir2,
718 testDynamicBackendsSubDir3,
719 testDynamicBackendsSubDir4
720 };
721 std::vector<std::string> sharedObjects = DynamicBackendUtils::GetSharedObjects(backendPaths);
Matteo Martincighe54aa062019-08-05 14:12:11 +0100722 std::vector<std::string> expectedSharedObjects
Jan Eilers4a539fc2019-07-25 17:08:37 +0100723 {
Matteo Martincighe54aa062019-08-05 14:12:11 +0100724 testDynamicBackendsSubDir1 + "Arm123_GpuAcc_backend.so", // Digits in vendor name are allowed
725 testDynamicBackendsSubDir1 + "Arm_GpuAcc456_backend.so", // Digits in backend id are allowed
Jan Eilers4a539fc2019-07-25 17:08:37 +0100726 testDynamicBackendsSubDir1 + "Arm_GpuAcc_backend.so", // Basic backend name
727 testDynamicBackendsSubDir1 + "Arm_GpuAcc_backend.so.1", // Single field version number
728 testDynamicBackendsSubDir1 + "Arm_GpuAcc_backend.so.1.2", // Multiple field version number
729 testDynamicBackendsSubDir1 + "Arm_GpuAcc_backend.so.1.2.3", // Multiple field version number
730 testDynamicBackendsSubDir1 + "Arm_GpuAcc_backend.so.10.1.27", // Multiple digit version
Jan Eilers4a539fc2019-07-25 17:08:37 +0100731 testDynamicBackendsSubDir2 + "Arm_CpuAcc_backend.so", // Duplicate symlinks removed
732 testDynamicBackendsSubDir2 + "Arm_GpuAcc_backend.so" // Duplicates on different paths are allowed
733 };
734
735 BOOST_TEST(sharedObjects.size() == expectedSharedObjects.size());
Matteo Martincighe54aa062019-08-05 14:12:11 +0100736 BOOST_TEST(sharedObjects[0] == expectedSharedObjects[0]);
737 BOOST_TEST(sharedObjects[1] == expectedSharedObjects[1]);
738 BOOST_TEST(sharedObjects[2] == expectedSharedObjects[2]);
739 BOOST_TEST(sharedObjects[3] == expectedSharedObjects[3]);
740 BOOST_TEST(sharedObjects[4] == expectedSharedObjects[4]);
741 BOOST_TEST(sharedObjects[5] == expectedSharedObjects[5]);
742 BOOST_TEST(sharedObjects[6] == expectedSharedObjects[6]);
743 BOOST_TEST(sharedObjects[7] == expectedSharedObjects[7]);
744 BOOST_TEST(sharedObjects[8] == expectedSharedObjects[8]);
745}
746
747void CreateDynamicBackendsTestImpl()
748{
749 using namespace armnn;
750 using namespace boost::filesystem;
751
Matteo Martincigh0c2b2892019-08-05 14:12:11 +0100752 // The test covers four directories:
Matteo Martincighe54aa062019-08-05 14:12:11 +0100753 // <unit test path>/src/backends/backendsCommon/test/
754 // ├─ backendsTestPath5/ -> exists, contains files
755 // ├─ backendsTestPath6/ -> exists, contains files
756 // ├─ backendsTestPath7/ -> exists, but empty
757 // └─ backendsTestPath8/ -> does not exist
758 //
759 // The test sub-directory backendsTestPath5/ contains the following test files:
760 //
761 // Arm_TestValid2_backend.so -> valid (basic backend name)
762 // Arm_TestValid3_backend.so -> valid (basic backend name)
763 // Arm_TestInvalid8_backend.so -> not valid (invalid backend id)
764 //
765 // The test sub-directory backendsTestPath6/ contains the following test files:
766 //
767 // Arm_TestValid2_backend.so -> valid (but duplicated from backendsTestPath5/)
768 // Arm_TestValid4_backend.so -> valid (it has a different filename,
769 // but it has the same backend id of Arm_TestValid2_backend.so
770 // and the same version)
Matteo Martincigh0c2b2892019-08-05 14:12:11 +0100771 // Arm_TestValid5_backend.so -> valid (basic backend name)
Matteo Martincighe54aa062019-08-05 14:12:11 +0100772 // Arm_TestInvalid9_backend.so -> not valid (it has a different filename,
773 // but it has the same backend id of Arm_TestValid2_backend.so
774 // and a version incompatible with the Backend API)
775
Matteo Martincigh0c2b2892019-08-05 14:12:11 +0100776 std::string testDynamicBackendsSubDir5 = GetTestSubDirectory(g_TestDynamicBackendsSubDir5);
777 std::string testDynamicBackendsSubDir6 = GetTestSubDirectory(g_TestDynamicBackendsSubDir6);
778 std::string testDynamicBackendsSubDir7 = GetTestSubDirectory(g_TestDynamicBackendsSubDir7);
779 std::string testDynamicBackendsSubDir8 = GetTestSubDirectory(g_TestDynamicBackendsSubDir8);
Matteo Martincighe54aa062019-08-05 14:12:11 +0100780 BOOST_CHECK(exists(testDynamicBackendsSubDir5));
781 BOOST_CHECK(exists(testDynamicBackendsSubDir6));
782 BOOST_CHECK(exists(testDynamicBackendsSubDir7));
783 BOOST_CHECK(!exists(testDynamicBackendsSubDir8));
784
785 std::vector<std::string> backendPaths
Jan Eilers4a539fc2019-07-25 17:08:37 +0100786 {
Matteo Martincighe54aa062019-08-05 14:12:11 +0100787 testDynamicBackendsSubDir5,
788 testDynamicBackendsSubDir6,
789 testDynamicBackendsSubDir7,
790 testDynamicBackendsSubDir8
791 };
792 std::vector<std::string> sharedObjects = DynamicBackendUtils::GetSharedObjects(backendPaths);
793 std::vector<DynamicBackendPtr> dynamicBackends = DynamicBackendUtils::CreateDynamicBackends(sharedObjects);
794
Matteo Martincigh0c2b2892019-08-05 14:12:11 +0100795 BOOST_TEST(dynamicBackends.size() == 5);
Matteo Martincighe54aa062019-08-05 14:12:11 +0100796 BOOST_TEST((dynamicBackends[0] != nullptr));
797 BOOST_TEST((dynamicBackends[1] != nullptr));
798 BOOST_TEST((dynamicBackends[2] != nullptr));
799 BOOST_TEST((dynamicBackends[3] != nullptr));
Matteo Martincigh0c2b2892019-08-05 14:12:11 +0100800 BOOST_TEST((dynamicBackends[4] != nullptr));
Matteo Martincighe54aa062019-08-05 14:12:11 +0100801
802 // Duplicates are allowed here, they will be skipped later during the backend registration
803 BOOST_TEST((dynamicBackends[0]->GetBackendId() == "TestValid2"));
804 BOOST_TEST((dynamicBackends[1]->GetBackendId() == "TestValid3"));
805 BOOST_TEST((dynamicBackends[2]->GetBackendId() == "TestValid2")); // From duplicate Arm_TestValid2_backend.so
806 BOOST_TEST((dynamicBackends[3]->GetBackendId() == "TestValid2")); // From Arm_TestValid4_backend.so
Matteo Martincigh0c2b2892019-08-05 14:12:11 +0100807 BOOST_TEST((dynamicBackends[4]->GetBackendId() == "TestValid5"));
Matteo Martincighe54aa062019-08-05 14:12:11 +0100808}
809
810void CreateDynamicBackendsNoPathsTestImpl()
811{
812 using namespace armnn;
813
814 std::vector<DynamicBackendPtr> dynamicBackends = DynamicBackendUtils::CreateDynamicBackends({});
815
816 BOOST_TEST(dynamicBackends.empty());
817}
818
819void CreateDynamicBackendsAllInvalidTestImpl()
820{
821 using namespace armnn;
822
823 std::vector<std::string> sharedObjects
824 {
825 "InvalidSharedObject1",
826 "InvalidSharedObject2",
827 "InvalidSharedObject3",
828 };
829 std::vector<DynamicBackendPtr> dynamicBackends = DynamicBackendUtils::CreateDynamicBackends(sharedObjects);
830
831 BOOST_TEST(dynamicBackends.empty());
832}
833
834void CreateDynamicBackendsMixedTypesTestImpl()
835{
836 using namespace armnn;
837 using namespace boost::filesystem;
838
Matteo Martincigh0c2b2892019-08-05 14:12:11 +0100839 std::string testDynamicBackendsSubDir5 = GetTestSubDirectory(g_TestDynamicBackendsSubDir5);
840 std::string testDynamicBackendsSubDir6 = GetTestSubDirectory(g_TestDynamicBackendsSubDir6);
Matteo Martincighe54aa062019-08-05 14:12:11 +0100841 BOOST_CHECK(exists(testDynamicBackendsSubDir5));
842 BOOST_CHECK(exists(testDynamicBackendsSubDir6));
843
844 std::string testValidBackend2FilePath = GetTestFilePath(testDynamicBackendsSubDir5,
845 g_TestValidBackend2FileName);
846 std::string testInvalidBackend8FilePath = GetTestFilePath(testDynamicBackendsSubDir5,
847 g_TestInvalidBackend8FileName);
848 std::string testInvalidBackend9FilePath = GetTestFilePath(testDynamicBackendsSubDir6,
849 g_TestInvalidBackend9FileName);
850 BOOST_CHECK(exists(testValidBackend2FilePath));
851 BOOST_CHECK(exists(testInvalidBackend8FilePath));
852 BOOST_CHECK(exists(testInvalidBackend9FilePath));
853
854 std::vector<std::string> sharedObjects
855 {
856 testValidBackend2FilePath, // Arm_TestValid2_backend.so -> valid (basic backend name)
857 testInvalidBackend8FilePath, // Arm_TestInvalid8_backend.so -> not valid (invalid backend id)
858 testInvalidBackend9FilePath, // Arm_TestInvalid9_backend.so -> not valid (incompatible version)
859 "InvalidSharedObject", // The file does not exist
860 };
861 std::vector<DynamicBackendPtr> dynamicBackends = DynamicBackendUtils::CreateDynamicBackends(sharedObjects);
862
863 BOOST_TEST(dynamicBackends.size() == 1);
864 BOOST_TEST((dynamicBackends[0] != nullptr));
865 BOOST_TEST((dynamicBackends[0]->GetBackendId() == "TestValid2"));
Jan Eilers4a539fc2019-07-25 17:08:37 +0100866}
Matteo Martincigh0c2b2892019-08-05 14:12:11 +0100867
868void RegisterSingleDynamicBackendTestImpl()
869{
870 using namespace armnn;
871 using namespace boost::filesystem;
872
873 // Register one valid dynamic backend
874
875 // Dummy registry used for testing
876 BackendRegistry backendRegistry;
877 BOOST_TEST(backendRegistry.Size() == 0);
878
879 std::string testDynamicBackendsSubDir5 = GetTestSubDirectory(g_TestDynamicBackendsSubDir5);
880 BOOST_CHECK(exists(testDynamicBackendsSubDir5));
881
882 std::string testValidBackend2FilePath = GetTestFilePath(testDynamicBackendsSubDir5, g_TestValidBackend2FileName);
883 BOOST_CHECK(exists(testValidBackend2FilePath));
884
885 std::vector<std::string> sharedObjects{ testValidBackend2FilePath };
886 std::vector<DynamicBackendPtr> dynamicBackends = TestDynamicBackendUtils::CreateDynamicBackends(sharedObjects);
887
888 BOOST_TEST(dynamicBackends.size() == 1);
889 BOOST_TEST((dynamicBackends[0] != nullptr));
890
891 BackendId dynamicBackendId = dynamicBackends[0]->GetBackendId();
892 BOOST_TEST((dynamicBackendId == "TestValid2"));
893
894 BackendVersion dynamicBackendVersion = dynamicBackends[0]->GetBackendVersion();
895 BOOST_TEST(TestDynamicBackendUtils::IsBackendCompatible(dynamicBackendVersion));
896
Matteo Martincigh89533902019-08-15 12:08:06 +0100897 BackendIdSet registeredBackendIds = TestDynamicBackendUtils::RegisterDynamicBackendsImplTest(backendRegistry,
898 dynamicBackends);
Matteo Martincigh0c2b2892019-08-05 14:12:11 +0100899 BOOST_TEST(backendRegistry.Size() == 1);
Matteo Martincigh89533902019-08-15 12:08:06 +0100900 BOOST_TEST(registeredBackendIds.size() == 1);
Matteo Martincigh0c2b2892019-08-05 14:12:11 +0100901
902 BackendIdSet backendIds = backendRegistry.GetBackendIds();
903 BOOST_TEST(backendIds.size() == 1);
904 BOOST_TEST((backendIds.find(dynamicBackendId) != backendIds.end()));
Matteo Martincigh89533902019-08-15 12:08:06 +0100905 BOOST_TEST((registeredBackendIds.find(dynamicBackendId) != registeredBackendIds.end()));
Matteo Martincigh0c2b2892019-08-05 14:12:11 +0100906
907 auto dynamicBackendFactoryFunction = backendRegistry.GetFactory(dynamicBackendId);
908 BOOST_TEST((dynamicBackendFactoryFunction != nullptr));
909
910 IBackendInternalUniquePtr dynamicBackend = dynamicBackendFactoryFunction();
911 BOOST_TEST((dynamicBackend != nullptr));
912 BOOST_TEST((dynamicBackend->GetId() == dynamicBackendId));
913}
914
915void RegisterMultipleDynamicBackendsTestImpl()
916{
917 using namespace armnn;
918 using namespace boost::filesystem;
919
920 // Register many valid dynamic backends
921
922 std::string testDynamicBackendsSubDir5 = GetTestSubDirectory(g_TestDynamicBackendsSubDir5);
923 std::string testDynamicBackendsSubDir6 = GetTestSubDirectory(g_TestDynamicBackendsSubDir6);
924 BOOST_CHECK(exists(testDynamicBackendsSubDir5));
925 BOOST_CHECK(exists(testDynamicBackendsSubDir6));
926
927 std::string testValidBackend2FilePath = GetTestFilePath(testDynamicBackendsSubDir5, g_TestValidBackend2FileName);
928 std::string testValidBackend3FilePath = GetTestFilePath(testDynamicBackendsSubDir5, g_TestValidBackend3FileName);
929 std::string testValidBackend5FilePath = GetTestFilePath(testDynamicBackendsSubDir6, g_TestValidBackend5FileName);
930 BOOST_CHECK(exists(testValidBackend2FilePath));
931 BOOST_CHECK(exists(testValidBackend3FilePath));
932 BOOST_CHECK(exists(testValidBackend5FilePath));
933
934 std::vector<std::string> sharedObjects
935 {
936 testValidBackend2FilePath,
937 testValidBackend3FilePath,
938 testValidBackend5FilePath
939 };
940 std::vector<DynamicBackendPtr> dynamicBackends = TestDynamicBackendUtils::CreateDynamicBackends(sharedObjects);
941
942 BOOST_TEST(dynamicBackends.size() == 3);
943 BOOST_TEST((dynamicBackends[0] != nullptr));
944 BOOST_TEST((dynamicBackends[1] != nullptr));
945 BOOST_TEST((dynamicBackends[2] != nullptr));
946
947 BackendId dynamicBackendId1 = dynamicBackends[0]->GetBackendId();
948 BackendId dynamicBackendId2 = dynamicBackends[1]->GetBackendId();
949 BackendId dynamicBackendId3 = dynamicBackends[2]->GetBackendId();
950 BOOST_TEST((dynamicBackendId1 == "TestValid2"));
951 BOOST_TEST((dynamicBackendId2 == "TestValid3"));
952 BOOST_TEST((dynamicBackendId3 == "TestValid5"));
953
954 for (size_t i = 0; i < dynamicBackends.size(); i++)
955 {
956 BackendVersion dynamicBackendVersion = dynamicBackends[i]->GetBackendVersion();
957 BOOST_TEST(TestDynamicBackendUtils::IsBackendCompatible(dynamicBackendVersion));
958 }
959
960 // Dummy registry used for testing
961 BackendRegistry backendRegistry;
962 BOOST_TEST(backendRegistry.Size() == 0);
963
Matteo Martincigh89533902019-08-15 12:08:06 +0100964 BackendIdSet registeredBackendIds = TestDynamicBackendUtils::RegisterDynamicBackendsImplTest(backendRegistry,
965 dynamicBackends);
Matteo Martincigh0c2b2892019-08-05 14:12:11 +0100966 BOOST_TEST(backendRegistry.Size() == 3);
Matteo Martincigh89533902019-08-15 12:08:06 +0100967 BOOST_TEST(registeredBackendIds.size() == 3);
Matteo Martincigh0c2b2892019-08-05 14:12:11 +0100968
969 BackendIdSet backendIds = backendRegistry.GetBackendIds();
970 BOOST_TEST(backendIds.size() == 3);
971 BOOST_TEST((backendIds.find(dynamicBackendId1) != backendIds.end()));
972 BOOST_TEST((backendIds.find(dynamicBackendId2) != backendIds.end()));
973 BOOST_TEST((backendIds.find(dynamicBackendId3) != backendIds.end()));
Matteo Martincigh89533902019-08-15 12:08:06 +0100974 BOOST_TEST((registeredBackendIds.find(dynamicBackendId1) != registeredBackendIds.end()));
975 BOOST_TEST((registeredBackendIds.find(dynamicBackendId2) != registeredBackendIds.end()));
976 BOOST_TEST((registeredBackendIds.find(dynamicBackendId3) != registeredBackendIds.end()));
Matteo Martincigh0c2b2892019-08-05 14:12:11 +0100977
978 for (size_t i = 0; i < dynamicBackends.size(); i++)
979 {
980 BackendId dynamicBackendId = dynamicBackends[i]->GetBackendId();
981
982 auto dynamicBackendFactoryFunction = backendRegistry.GetFactory(dynamicBackendId);
983 BOOST_TEST((dynamicBackendFactoryFunction != nullptr));
984
985 IBackendInternalUniquePtr dynamicBackend = dynamicBackendFactoryFunction();
986 BOOST_TEST((dynamicBackend != nullptr));
987 BOOST_TEST((dynamicBackend->GetId() == dynamicBackendId));
988 }
989}
990
991void RegisterMultipleInvalidDynamicBackendsTestImpl()
992{
993 using namespace armnn;
994 using namespace boost::filesystem;
995
996 // Try to register many invalid dynamic backends
997
998 // The test covers one directory:
999 // <unit test path>/src/backends/backendsCommon/test/
1000 // └─ backendsTestPath9/ -> exists, contains files
1001 //
1002 // The test sub-directory backendsTestPath9/ contains the following test files:
1003 //
1004 // Arm_TestInvalid10_backend.so -> not valid (invalid backend id)
1005 // Arm_TestInvalid11_backend.so -> not valid (invalid backend id)
1006
1007 std::string testDynamicBackendsSubDir9 = GetTestSubDirectory(g_TestDynamicBackendsSubDir9);
1008 BOOST_CHECK(exists(testDynamicBackendsSubDir9));
1009
1010 std::string testInvalidBackend10FilePath = GetTestFilePath(testDynamicBackendsSubDir9,
1011 g_TestInvalidBackend10FileName);
1012 std::string testInvalidBackend11FilePath = GetTestFilePath(testDynamicBackendsSubDir9,
1013 g_TestInvalidBackend11FileName);
1014 BOOST_CHECK(exists(testInvalidBackend10FilePath));
1015 BOOST_CHECK(exists(testInvalidBackend11FilePath));
1016
1017 std::vector<std::string> sharedObjects
1018 {
1019 testInvalidBackend10FilePath,
1020 testInvalidBackend11FilePath,
1021 "InvalidSharedObject"
1022 };
1023 std::vector<DynamicBackendPtr> dynamicBackends = TestDynamicBackendUtils::CreateDynamicBackends(sharedObjects);
1024
1025 BOOST_TEST(dynamicBackends.size() == 2);
1026 BOOST_TEST((dynamicBackends[0] != nullptr));
1027 BOOST_TEST((dynamicBackends[1] != nullptr));
1028
1029 BackendId dynamicBackendId1 = dynamicBackends[0]->GetBackendId();
1030 BackendId dynamicBackendId2 = dynamicBackends[1]->GetBackendId();
1031 BOOST_TEST((dynamicBackendId1 == ""));
1032 BOOST_TEST((dynamicBackendId2 == "Unknown"));
1033
1034 for (size_t i = 0; i < dynamicBackends.size(); i++)
1035 {
1036 BackendVersion dynamicBackendVersion = dynamicBackends[i]->GetBackendVersion();
1037 BOOST_TEST(TestDynamicBackendUtils::IsBackendCompatible(dynamicBackendVersion));
1038 }
1039
1040 // Dummy registry used for testing
1041 BackendRegistry backendRegistry;
1042 BOOST_TEST(backendRegistry.Size() == 0);
1043
1044 // Check that no dynamic backend got registered
Matteo Martincigh89533902019-08-15 12:08:06 +01001045 BackendIdSet registeredBackendIds = TestDynamicBackendUtils::RegisterDynamicBackendsImplTest(backendRegistry,
1046 dynamicBackends);
Matteo Martincigh0c2b2892019-08-05 14:12:11 +01001047 BOOST_TEST(backendRegistry.Size() == 0);
Matteo Martincigh89533902019-08-15 12:08:06 +01001048 BOOST_TEST(registeredBackendIds.empty());
Matteo Martincigh0c2b2892019-08-05 14:12:11 +01001049}
1050
1051void RegisterMixedDynamicBackendsTestImpl()
1052{
1053 using namespace armnn;
1054 using namespace boost::filesystem;
1055
1056 // The test covers five directories:
1057 // <unit test path>/src/backends/backendsCommon/test/
1058 // ├─ backendsTestPath5/ -> exists, contains files
1059 // ├─ backendsTestPath6/ -> exists, contains files
1060 // ├─ backendsTestPath7/ -> exists, but empty
1061 // ├─ backendsTestPath8/ -> does not exist
1062 // └─ backendsTestPath9/ -> exists, contains files
1063 //
1064 // The test sub-directory backendsTestPath5/ contains the following test files:
1065 //
1066 // Arm_TestValid2_backend.so -> valid (basic backend name)
1067 // Arm_TestValid3_backend.so -> valid (basic backend name)
1068 // Arm_TestInvalid8_backend.so -> not valid (invalid backend id)
1069 //
1070 // The test sub-directory backendsTestPath6/ contains the following test files:
1071 //
1072 // Arm_TestValid2_backend.so -> valid (but duplicated from backendsTestPath5/)
1073 // Arm_TestValid4_backend.so -> valid (it has a different filename,
1074 // but it has the same backend id of Arm_TestValid2_backend.so
1075 // and the same version)
1076 // Arm_TestValid5_backend.so -> valid (basic backend name)
1077 // Arm_TestInvalid9_backend.so -> not valid (it has a different filename,
1078 // but it has the same backend id of Arm_TestValid2_backend.so
1079 // and a version incompatible with the Backend API)
1080 //
1081 // The test sub-directory backendsTestPath9/ contains the following test files:
1082 //
1083 // Arm_TestInvalid10_backend.so -> not valid (empty backend id)
1084 // Arm_TestInvalid11_backend.so -> not valid ("Unknown" backend id)
1085
1086 std::string testDynamicBackendsSubDir5 = GetTestSubDirectory(g_TestDynamicBackendsSubDir5);
1087 std::string testDynamicBackendsSubDir6 = GetTestSubDirectory(g_TestDynamicBackendsSubDir6);
1088 std::string testDynamicBackendsSubDir7 = GetTestSubDirectory(g_TestDynamicBackendsSubDir7);
1089 std::string testDynamicBackendsSubDir8 = GetTestSubDirectory(g_TestDynamicBackendsSubDir8);
1090 std::string testDynamicBackendsSubDir9 = GetTestSubDirectory(g_TestDynamicBackendsSubDir9);
1091 BOOST_CHECK(exists(testDynamicBackendsSubDir5));
1092 BOOST_CHECK(exists(testDynamicBackendsSubDir6));
1093 BOOST_CHECK(exists(testDynamicBackendsSubDir7));
1094 BOOST_CHECK(!exists(testDynamicBackendsSubDir8));
1095 BOOST_CHECK(exists(testDynamicBackendsSubDir9));
1096
1097 std::string testValidBackend2FilePath = GetTestFilePath(testDynamicBackendsSubDir5, g_TestValidBackend2FileName);
1098 std::string testValidBackend3FilePath = GetTestFilePath(testDynamicBackendsSubDir5, g_TestValidBackend3FileName);
1099 std::string testValidBackend2DupFilePath = GetTestFilePath(testDynamicBackendsSubDir6, g_TestValidBackend2FileName);
1100 std::string testValidBackend4FilePath = GetTestFilePath(testDynamicBackendsSubDir6, g_TestValidBackend4FileName);
1101 std::string testValidBackend5FilePath = GetTestFilePath(testDynamicBackendsSubDir6, g_TestValidBackend5FileName);
1102 std::string testInvalidBackend8FilePath = GetTestFilePath(testDynamicBackendsSubDir5,
1103 g_TestInvalidBackend8FileName);
1104 std::string testInvalidBackend9FilePath = GetTestFilePath(testDynamicBackendsSubDir6,
1105 g_TestInvalidBackend9FileName);
1106 std::string testInvalidBackend10FilePath = GetTestFilePath(testDynamicBackendsSubDir9,
1107 g_TestInvalidBackend10FileName);
1108 std::string testInvalidBackend11FilePath = GetTestFilePath(testDynamicBackendsSubDir9,
1109 g_TestInvalidBackend11FileName);
1110 BOOST_CHECK(exists(testValidBackend2FilePath));
1111 BOOST_CHECK(exists(testValidBackend3FilePath));
1112 BOOST_CHECK(exists(testValidBackend2DupFilePath));
1113 BOOST_CHECK(exists(testValidBackend4FilePath));
1114 BOOST_CHECK(exists(testValidBackend5FilePath));
1115 BOOST_CHECK(exists(testInvalidBackend8FilePath));
1116 BOOST_CHECK(exists(testInvalidBackend9FilePath));
1117 BOOST_CHECK(exists(testInvalidBackend10FilePath));
1118 BOOST_CHECK(exists(testInvalidBackend11FilePath));
1119
1120 std::vector<std::string> sharedObjects
1121 {
1122 testValidBackend2FilePath,
1123 testValidBackend3FilePath,
1124 testValidBackend2DupFilePath,
1125 testValidBackend4FilePath,
1126 testValidBackend5FilePath,
1127 testInvalidBackend8FilePath,
1128 testInvalidBackend9FilePath,
1129 testInvalidBackend10FilePath,
1130 testInvalidBackend11FilePath,
1131 "InvalidSharedObject"
1132 };
1133 std::vector<DynamicBackendPtr> dynamicBackends = TestDynamicBackendUtils::CreateDynamicBackends(sharedObjects);
1134
1135 BOOST_TEST(dynamicBackends.size() == 7);
1136 BOOST_TEST((dynamicBackends[0] != nullptr));
1137 BOOST_TEST((dynamicBackends[1] != nullptr));
1138 BOOST_TEST((dynamicBackends[2] != nullptr));
1139 BOOST_TEST((dynamicBackends[3] != nullptr));
1140 BOOST_TEST((dynamicBackends[4] != nullptr));
1141 BOOST_TEST((dynamicBackends[5] != nullptr));
1142 BOOST_TEST((dynamicBackends[6] != nullptr));
1143
1144 BackendId dynamicBackendId1 = dynamicBackends[0]->GetBackendId();
1145 BackendId dynamicBackendId2 = dynamicBackends[1]->GetBackendId();
1146 BackendId dynamicBackendId3 = dynamicBackends[2]->GetBackendId();
1147 BackendId dynamicBackendId4 = dynamicBackends[3]->GetBackendId();
1148 BackendId dynamicBackendId5 = dynamicBackends[4]->GetBackendId();
1149 BackendId dynamicBackendId6 = dynamicBackends[5]->GetBackendId();
1150 BackendId dynamicBackendId7 = dynamicBackends[6]->GetBackendId();
1151 BOOST_TEST((dynamicBackendId1 == "TestValid2"));
1152 BOOST_TEST((dynamicBackendId2 == "TestValid3"));
1153 BOOST_TEST((dynamicBackendId3 == "TestValid2")); // From duplicate Arm_TestValid2_backend.so
1154 BOOST_TEST((dynamicBackendId4 == "TestValid2")); // From Arm_TestValid4_backend.so
1155 BOOST_TEST((dynamicBackendId5 == "TestValid5"));
1156 BOOST_TEST((dynamicBackendId6 == ""));
1157 BOOST_TEST((dynamicBackendId7 == "Unknown"));
1158
1159 for (size_t i = 0; i < dynamicBackends.size(); i++)
1160 {
1161 BackendVersion dynamicBackendVersion = dynamicBackends[i]->GetBackendVersion();
1162 BOOST_TEST(TestDynamicBackendUtils::IsBackendCompatible(dynamicBackendVersion));
1163 }
1164
1165 // Dummy registry used for testing
1166 BackendRegistry backendRegistry;
1167 BOOST_TEST(backendRegistry.Size() == 0);
1168
1169 std::vector<BackendId> expectedRegisteredbackendIds
1170 {
1171 "TestValid2",
1172 "TestValid3",
1173 "TestValid5"
1174 };
1175
Matteo Martincigh89533902019-08-15 12:08:06 +01001176 BackendIdSet registeredBackendIds = TestDynamicBackendUtils::RegisterDynamicBackendsImplTest(backendRegistry,
1177 dynamicBackends);
Matteo Martincigh0c2b2892019-08-05 14:12:11 +01001178 BOOST_TEST(backendRegistry.Size() == expectedRegisteredbackendIds.size());
Matteo Martincigh89533902019-08-15 12:08:06 +01001179 BOOST_TEST(registeredBackendIds.size() == expectedRegisteredbackendIds.size());
Matteo Martincigh0c2b2892019-08-05 14:12:11 +01001180
1181 BackendIdSet backendIds = backendRegistry.GetBackendIds();
1182 BOOST_TEST(backendIds.size() == expectedRegisteredbackendIds.size());
1183 for (const BackendId& expectedRegisteredbackendId : expectedRegisteredbackendIds)
1184 {
1185 BOOST_TEST((backendIds.find(expectedRegisteredbackendId) != backendIds.end()));
Matteo Martincigh89533902019-08-15 12:08:06 +01001186 BOOST_TEST((registeredBackendIds.find(expectedRegisteredbackendId) != registeredBackendIds.end()));
Matteo Martincigh0c2b2892019-08-05 14:12:11 +01001187
1188 auto dynamicBackendFactoryFunction = backendRegistry.GetFactory(expectedRegisteredbackendId);
1189 BOOST_TEST((dynamicBackendFactoryFunction != nullptr));
1190
1191 IBackendInternalUniquePtr dynamicBackend = dynamicBackendFactoryFunction();
1192 BOOST_TEST((dynamicBackend != nullptr));
1193 BOOST_TEST((dynamicBackend->GetId() == expectedRegisteredbackendId));
1194 }
1195}
Matteo Martincigh3d8a9ed2019-08-08 10:49:03 +01001196
Narumol Prangnawarat60a20fb2019-12-09 17:24:41 +00001197#if !defined(ARMNN_DYNAMIC_BACKEND_ENABLED)
1198
Matteo Martincigh3d8a9ed2019-08-08 10:49:03 +01001199void RuntimeEmptyTestImpl()
1200{
1201 using namespace armnn;
1202
1203 // Swapping the backend registry storage for testing
1204 TestBackendRegistry testBackendRegistry;
1205
Matteo Martincigh89533902019-08-15 12:08:06 +01001206 const BackendRegistry& backendRegistry = BackendRegistryInstance();
1207 BOOST_TEST(backendRegistry.Size() == 0);
1208
Matteo Martincigh3d8a9ed2019-08-08 10:49:03 +01001209 IRuntime::CreationOptions creationOptions;
1210 IRuntimePtr runtime = IRuntime::Create(creationOptions);
1211
Jan Eilersbb446e52020-04-02 13:56:54 +01001212 const DeviceSpec& deviceSpec = *PolymorphicDowncast<const DeviceSpec*>(&runtime->GetDeviceSpec());
Matteo Martincigh89533902019-08-15 12:08:06 +01001213 BackendIdSet supportedBackendIds = deviceSpec.GetSupportedBackends();
1214 BOOST_TEST(supportedBackendIds.empty());
1215
Matteo Martincigh3d8a9ed2019-08-08 10:49:03 +01001216 BOOST_TEST(backendRegistry.Size() == 0);
1217}
1218
Narumol Prangnawarat60a20fb2019-12-09 17:24:41 +00001219#endif
1220
Matteo Martincigh3d8a9ed2019-08-08 10:49:03 +01001221void RuntimeDynamicBackendsTestImpl()
1222{
1223 using namespace armnn;
1224 using namespace boost::filesystem;
1225
1226 // Swapping the backend registry storage for testing
1227 TestBackendRegistry testBackendRegistry;
1228
1229 // This directory contains valid and invalid backends
1230 std::string testDynamicBackendsSubDir5 = GetTestSubDirectory(g_TestDynamicBackendsSubDir5);
1231 BOOST_CHECK(exists(testDynamicBackendsSubDir5));
1232
1233 // Using the path override in CreationOptions to load some test dynamic backends
1234 IRuntime::CreationOptions creationOptions;
1235 creationOptions.m_DynamicBackendsPath = testDynamicBackendsSubDir5;
1236 IRuntimePtr runtime = IRuntime::Create(creationOptions);
1237
1238 std::vector<BackendId> expectedRegisteredbackendIds
1239 {
1240 "TestValid2",
1241 "TestValid3"
1242 };
1243
1244 const BackendRegistry& backendRegistry = BackendRegistryInstance();
1245 BOOST_TEST(backendRegistry.Size() == expectedRegisteredbackendIds.size());
1246
1247 BackendIdSet backendIds = backendRegistry.GetBackendIds();
1248 for (const BackendId& expectedRegisteredbackendId : expectedRegisteredbackendIds)
1249 {
1250 BOOST_TEST((backendIds.find(expectedRegisteredbackendId) != backendIds.end()));
1251 }
Matteo Martincigh89533902019-08-15 12:08:06 +01001252
Jan Eilersbb446e52020-04-02 13:56:54 +01001253 const DeviceSpec& deviceSpec = *PolymorphicDowncast<const DeviceSpec*>(&runtime->GetDeviceSpec());
Matteo Martincigh89533902019-08-15 12:08:06 +01001254 BackendIdSet supportedBackendIds = deviceSpec.GetSupportedBackends();
1255 BOOST_TEST(supportedBackendIds.size() == expectedRegisteredbackendIds.size());
1256 for (const BackendId& expectedRegisteredbackendId : expectedRegisteredbackendIds)
1257 {
1258 BOOST_TEST((supportedBackendIds.find(expectedRegisteredbackendId) != supportedBackendIds.end()));
1259 }
Matteo Martincigh3d8a9ed2019-08-08 10:49:03 +01001260}
1261
1262void RuntimeDuplicateDynamicBackendsTestImpl()
1263{
1264 using namespace armnn;
1265 using namespace boost::filesystem;
1266
1267 // Swapping the backend registry storage for testing
1268 TestBackendRegistry testBackendRegistry;
1269
1270 // This directory contains valid, invalid and duplicate backends
1271 std::string testDynamicBackendsSubDir6 = GetTestSubDirectory(g_TestDynamicBackendsSubDir6);
1272 BOOST_CHECK(exists(testDynamicBackendsSubDir6));
1273
1274 // Using the path override in CreationOptions to load some test dynamic backends
1275 IRuntime::CreationOptions creationOptions;
1276 creationOptions.m_DynamicBackendsPath = testDynamicBackendsSubDir6;
1277 IRuntimePtr runtime = IRuntime::Create(creationOptions);
1278
1279 std::vector<BackendId> expectedRegisteredbackendIds
1280 {
1281 "TestValid2",
1282 "TestValid5"
1283 };
1284
1285 const BackendRegistry& backendRegistry = BackendRegistryInstance();
1286 BOOST_TEST(backendRegistry.Size() == expectedRegisteredbackendIds.size());
1287
1288 BackendIdSet backendIds = backendRegistry.GetBackendIds();
1289 for (const BackendId& expectedRegisteredbackendId : expectedRegisteredbackendIds)
1290 {
1291 BOOST_TEST((backendIds.find(expectedRegisteredbackendId) != backendIds.end()));
1292 }
Matteo Martincigh89533902019-08-15 12:08:06 +01001293
Jan Eilersbb446e52020-04-02 13:56:54 +01001294 const DeviceSpec& deviceSpec = *PolymorphicDowncast<const DeviceSpec*>(&runtime->GetDeviceSpec());
Matteo Martincigh89533902019-08-15 12:08:06 +01001295 BackendIdSet supportedBackendIds = deviceSpec.GetSupportedBackends();
1296 BOOST_TEST(supportedBackendIds.size() == expectedRegisteredbackendIds.size());
1297 for (const BackendId& expectedRegisteredbackendId : expectedRegisteredbackendIds)
1298 {
1299 BOOST_TEST((supportedBackendIds.find(expectedRegisteredbackendId) != supportedBackendIds.end()));
1300 }
Matteo Martincigh3d8a9ed2019-08-08 10:49:03 +01001301}
1302
1303void RuntimeInvalidDynamicBackendsTestImpl()
1304{
1305 using namespace armnn;
1306 using namespace boost::filesystem;
1307
1308 // Swapping the backend registry storage for testing
1309 TestBackendRegistry testBackendRegistry;
1310
1311 // This directory contains only invalid backends
1312 std::string testDynamicBackendsSubDir9 = GetTestSubDirectory(g_TestDynamicBackendsSubDir9);
1313 BOOST_CHECK(exists(testDynamicBackendsSubDir9));
1314
1315 // Using the path override in CreationOptions to load some test dynamic backends
1316 IRuntime::CreationOptions creationOptions;
1317 creationOptions.m_DynamicBackendsPath = testDynamicBackendsSubDir9;
1318 IRuntimePtr runtime = IRuntime::Create(creationOptions);
1319
1320 const BackendRegistry& backendRegistry = BackendRegistryInstance();
1321 BOOST_TEST(backendRegistry.Size() == 0);
Matteo Martincigh89533902019-08-15 12:08:06 +01001322
Jan Eilersbb446e52020-04-02 13:56:54 +01001323 const DeviceSpec& deviceSpec = *PolymorphicDowncast<const DeviceSpec*>(&runtime->GetDeviceSpec());
Matteo Martincigh89533902019-08-15 12:08:06 +01001324 BackendIdSet supportedBackendIds = deviceSpec.GetSupportedBackends();
1325 BOOST_TEST(supportedBackendIds.empty());
Matteo Martincigh3d8a9ed2019-08-08 10:49:03 +01001326}
1327
1328void RuntimeInvalidOverridePathTestImpl()
1329{
1330 using namespace armnn;
1331
1332 // Swapping the backend registry storage for testing
1333 TestBackendRegistry testBackendRegistry;
1334
1335 // Using the path override in CreationOptions to load some test dynamic backends
1336 IRuntime::CreationOptions creationOptions;
1337 creationOptions.m_DynamicBackendsPath = "InvalidPath";
1338 IRuntimePtr runtime = IRuntime::Create(creationOptions);
1339
1340 const BackendRegistry& backendRegistry = BackendRegistryInstance();
1341 BOOST_TEST(backendRegistry.Size() == 0);
Matteo Martincigh89533902019-08-15 12:08:06 +01001342
Jan Eilersbb446e52020-04-02 13:56:54 +01001343 const DeviceSpec& deviceSpec = *PolymorphicDowncast<const DeviceSpec*>(&runtime->GetDeviceSpec());
Matteo Martincigh89533902019-08-15 12:08:06 +01001344 BackendIdSet supportedBackendIds = deviceSpec.GetSupportedBackends();
1345 BOOST_TEST(supportedBackendIds.empty());
Matteo Martincigh3d8a9ed2019-08-08 10:49:03 +01001346}
Matteo Martincigh4e73b422019-08-08 13:46:32 +01001347
Matteo Martincighdb16dd32019-08-27 16:41:11 +01001348#if defined(ARMNNREF_ENABLED)
Matteo Martincighe67edb22019-08-14 14:05:46 +01001349
1350// This test unit needs the reference backend, it's not available if the reference backend is not built
1351
Matteo Martincigh4e73b422019-08-08 13:46:32 +01001352void CreateReferenceDynamicBackendTestImpl()
1353{
1354 using namespace armnn;
1355 using namespace boost::filesystem;
1356
1357 // Swapping the backend registry storage for testing
1358 TestBackendRegistry testBackendRegistry;
1359
1360 // This directory contains the reference dynamic backend
1361 std::string dynamicBackendsBaseDir = GetDynamicBackendsBasePath();
1362 std::string referenceDynamicBackendSubDir = GetTestSubDirectory(dynamicBackendsBaseDir,
1363 g_ReferenceDynamicBackendSubDir);
1364 BOOST_CHECK(exists(referenceDynamicBackendSubDir));
1365
1366 // Check that the reference dynamic backend file exists
1367 std::string referenceBackendFilePath = GetTestFilePath(referenceDynamicBackendSubDir,
1368 g_ReferenceBackendFileName);
1369 BOOST_CHECK(exists(referenceBackendFilePath));
1370
1371 // Using the path override in CreationOptions to load the reference dynamic backend
1372 IRuntime::CreationOptions creationOptions;
1373 creationOptions.m_DynamicBackendsPath = referenceDynamicBackendSubDir;
1374 IRuntimePtr runtime = IRuntime::Create(creationOptions);
1375
1376 const BackendRegistry& backendRegistry = BackendRegistryInstance();
1377 BOOST_TEST(backendRegistry.Size() == 1);
1378
1379 BackendIdSet backendIds = backendRegistry.GetBackendIds();
1380 BOOST_TEST((backendIds.find("CpuRef") != backendIds.end()));
1381
Jan Eilersbb446e52020-04-02 13:56:54 +01001382 const DeviceSpec& deviceSpec = *PolymorphicDowncast<const DeviceSpec*>(&runtime->GetDeviceSpec());
Matteo Martincigh89533902019-08-15 12:08:06 +01001383 BackendIdSet supportedBackendIds = deviceSpec.GetSupportedBackends();
1384 BOOST_TEST(supportedBackendIds.size() == 1);
1385 BOOST_TEST((supportedBackendIds.find("CpuRef") != supportedBackendIds.end()));
1386
Matteo Martincigh4e73b422019-08-08 13:46:32 +01001387 // Get the factory function
1388 auto referenceDynamicBackendFactoryFunction = backendRegistry.GetFactory("CpuRef");
1389 BOOST_TEST((referenceDynamicBackendFactoryFunction != nullptr));
1390
1391 // Use the factory function to create an instance of the reference backend
1392 IBackendInternalUniquePtr referenceDynamicBackend = referenceDynamicBackendFactoryFunction();
1393 BOOST_TEST((referenceDynamicBackend != nullptr));
1394 BOOST_TEST((referenceDynamicBackend->GetId() == "CpuRef"));
1395
1396 // Test the backend instance by querying the layer support
1397 IBackendInternal::ILayerSupportSharedPtr referenceLayerSupport = referenceDynamicBackend->GetLayerSupport();
1398 BOOST_TEST((referenceLayerSupport != nullptr));
1399
1400 TensorShape inputShape { 1, 16, 16, 16 };
1401 TensorShape outputShape{ 1, 16, 16, 16 };
1402 TensorShape weightShape{ 16, 1, 1, 16 };
1403 TensorInfo inputInfo (inputShape, DataType::Float32);
1404 TensorInfo outputInfo(outputShape, DataType::Float32);
1405 TensorInfo weightInfo(weightShape, DataType::Float32);
1406 Convolution2dDescriptor convolution2dDescriptor;
1407 bool referenceConvolution2dSupported =
1408 referenceLayerSupport->IsConvolution2dSupported(inputInfo,
1409 outputInfo,
1410 convolution2dDescriptor,
1411 weightInfo,
1412 EmptyOptional());
1413 BOOST_TEST(referenceConvolution2dSupported);
1414
1415 // Test the backend instance by creating a workload
1416 IBackendInternal::IWorkloadFactoryPtr referenceWorkloadFactory = referenceDynamicBackend->CreateWorkloadFactory();
1417 BOOST_TEST((referenceWorkloadFactory != nullptr));
1418
1419 // Create dummy settings for the workload
1420 Convolution2dQueueDescriptor convolution2dQueueDescriptor;
1421 WorkloadInfo workloadInfo
1422 {
1423 { inputInfo },
1424 { outputInfo }
1425 };
1426 convolution2dQueueDescriptor.m_Inputs.push_back(nullptr);
1427 auto weights = std::make_unique<ScopedCpuTensorHandle>(weightInfo);
1428 convolution2dQueueDescriptor.m_Weight = weights.get();
1429
1430 // Create a convolution workload with the dummy settings
1431 auto workload = referenceWorkloadFactory->CreateConvolution2d(convolution2dQueueDescriptor, workloadInfo);
1432 BOOST_TEST((workload != nullptr));
Jan Eilersbb446e52020-04-02 13:56:54 +01001433 BOOST_TEST(workload.get() == PolymorphicDowncast<RefConvolution2dWorkload*>(workload.get()));
Matteo Martincigh4e73b422019-08-08 13:46:32 +01001434}
Matteo Martincighe67edb22019-08-14 14:05:46 +01001435
1436#endif
Narumol Prangnawarat867eba52020-02-03 12:29:56 +00001437
1438#if defined(SAMPLE_DYNAMIC_BACKEND_ENABLED)
Colm Donelanfa0d8382020-06-04 12:30:16 +01001439
1440void CheckSampleDynamicBackendLoaded()
1441{
1442 using namespace armnn;
1443 // At this point we expect DYNAMIC_BACKEND_PATHS to include a path to where libArm_SampleDynamic_backend.so is.
1444 // If it hasn't been loaded there's no point continuing with the rest of the tests.
1445 BackendIdSet backendIds = BackendRegistryInstance().GetBackendIds();
1446 if (backendIds.find("SampleDynamic") == backendIds.end())
1447 {
1448 std::string message = "The SampleDynamic backend has not been loaded. This may be a build configuration error. "
1449 "Ensure a DYNAMIC_BACKEND_PATHS was set at compile time to the location of "
1450 "libArm_SampleDynamic_backend.so. "
1451 "To disable this test recompile with: -DSAMPLE_DYNAMIC_BACKEND_ENABLED=0";
1452 BOOST_FAIL(message);
1453 }
1454}
1455
Narumol Prangnawarat867eba52020-02-03 12:29:56 +00001456void CreateSampleDynamicBackendTestImpl()
1457{
1458 using namespace armnn;
Narumol Prangnawarat867eba52020-02-03 12:29:56 +00001459 // Using the path override in CreationOptions to load the reference dynamic backend
1460 IRuntime::CreationOptions creationOptions;
Colm Donelan0dbe00a2020-06-03 08:00:28 +01001461 IRuntimePtr runtime = IRuntime::Create(creationOptions);
Narumol Prangnawarat867eba52020-02-03 12:29:56 +00001462 const BackendRegistry& backendRegistry = BackendRegistryInstance();
1463 BOOST_TEST(backendRegistry.Size() >= 1);
Colm Donelanfa0d8382020-06-04 12:30:16 +01001464 CheckSampleDynamicBackendLoaded();
Jan Eilersbb446e52020-04-02 13:56:54 +01001465 const DeviceSpec& deviceSpec = *PolymorphicDowncast<const DeviceSpec*>(&runtime->GetDeviceSpec());
Narumol Prangnawarat867eba52020-02-03 12:29:56 +00001466 BackendIdSet supportedBackendIds = deviceSpec.GetSupportedBackends();
1467 BOOST_TEST(supportedBackendIds.size()>= 1);
1468 BOOST_TEST((supportedBackendIds.find("SampleDynamic") != supportedBackendIds.end()));
1469
1470 // Get the factory function
1471 auto sampleDynamicBackendFactoryFunction = backendRegistry.GetFactory("SampleDynamic");
1472 BOOST_TEST((sampleDynamicBackendFactoryFunction != nullptr));
1473
1474 // Use the factory function to create an instance of the dynamic backend
1475 IBackendInternalUniquePtr sampleDynamicBackend = sampleDynamicBackendFactoryFunction();
1476 BOOST_TEST((sampleDynamicBackend != nullptr));
1477 BOOST_TEST((sampleDynamicBackend->GetId() == "SampleDynamic"));
1478
1479 // Test the backend instance by querying the layer support
1480 IBackendInternal::ILayerSupportSharedPtr sampleLayerSupport = sampleDynamicBackend->GetLayerSupport();
1481 BOOST_TEST((sampleLayerSupport != nullptr));
1482
1483 TensorShape inputShape { 1, 16, 16, 16 };
1484 TensorShape outputShape{ 1, 16, 16, 16 };
1485 TensorShape weightShape{ 16, 1, 1, 16 };
1486 TensorInfo inputInfo (inputShape, DataType::Float32);
1487 TensorInfo outputInfo(outputShape, DataType::Float32);
1488 TensorInfo weightInfo(weightShape, DataType::Float32);
1489 Convolution2dDescriptor convolution2dDescriptor;
1490 bool sampleConvolution2dSupported =
1491 sampleLayerSupport->IsConvolution2dSupported(inputInfo,
1492 outputInfo,
1493 convolution2dDescriptor,
1494 weightInfo,
1495 EmptyOptional());
1496 BOOST_TEST(!sampleConvolution2dSupported);
1497
1498 // Test the backend instance by creating a workload
1499 IBackendInternal::IWorkloadFactoryPtr sampleWorkloadFactory = sampleDynamicBackend->CreateWorkloadFactory();
1500 BOOST_TEST((sampleWorkloadFactory != nullptr));
1501
1502 // Create dummy settings for the workload
1503 AdditionQueueDescriptor additionQueueDescriptor;
1504 WorkloadInfo workloadInfo
1505 {
1506 { inputInfo, inputInfo },
1507 { outputInfo }
1508 };
1509
1510 // Create a addition workload
1511 auto workload = sampleWorkloadFactory->CreateAddition(additionQueueDescriptor, workloadInfo);
1512 BOOST_TEST((workload != nullptr));
1513}
1514
1515void SampleDynamicBackendEndToEndTestImpl()
1516{
1517 using namespace armnn;
1518 using namespace boost::filesystem;
1519 // Create runtime in which test will run
1520 IRuntime::CreationOptions options;
1521 IRuntimePtr runtime(IRuntime::Create(options));
Colm Donelanfa0d8382020-06-04 12:30:16 +01001522 CheckSampleDynamicBackendLoaded();
Narumol Prangnawarat867eba52020-02-03 12:29:56 +00001523 // Builds up the structure of the network.
1524 INetworkPtr net(INetwork::Create());
1525
1526 IConnectableLayer* input0 = net->AddInputLayer(0);
1527 IConnectableLayer* input1 = net->AddInputLayer(1);
1528 IConnectableLayer* add = net->AddAdditionLayer();
1529 IConnectableLayer* output = net->AddOutputLayer(0);
1530
1531 input0->GetOutputSlot(0).Connect(add->GetInputSlot(0));
1532 input1->GetOutputSlot(0).Connect(add->GetInputSlot(1));
1533 add->GetOutputSlot(0).Connect(output->GetInputSlot(0));
1534
1535 TensorInfo tensorInfo(TensorShape({2, 1}), DataType::Float32);
1536 input0->GetOutputSlot(0).SetTensorInfo(tensorInfo);
1537 input1->GetOutputSlot(0).SetTensorInfo(tensorInfo);
1538 add->GetOutputSlot(0).SetTensorInfo(tensorInfo);
1539
1540 // optimize the network
1541 IOptimizedNetworkPtr optNet = Optimize(*net, {"SampleDynamic"}, runtime->GetDeviceSpec());
1542
1543 // Loads it into the runtime.
1544 NetworkId netId;
1545 runtime->LoadNetwork(netId, std::move(optNet));
1546
1547 std::vector<float> input0Data{ 5.0f, 3.0f };
1548 std::vector<float> input1Data{ 10.0f, 8.0f };
1549 std::vector<float> expectedOutputData{ 15.0f, 11.0f };
1550 std::vector<float> outputData(2);
1551
1552 InputTensors inputTensors
1553 {
1554 {0,armnn::ConstTensor(runtime->GetInputTensorInfo(netId, 0), input0Data.data())},
1555 {1,armnn::ConstTensor(runtime->GetInputTensorInfo(netId, 0), input1Data.data())}
1556 };
1557 OutputTensors outputTensors
1558 {
1559 {0,armnn::Tensor(runtime->GetOutputTensorInfo(netId, 0), outputData.data())}
1560 };
1561
1562 // Does the inference.
1563 runtime->EnqueueWorkload(netId, inputTensors, outputTensors);
1564
1565 // Checks the results.
1566 BOOST_TEST(outputData == expectedOutputData);
1567}
1568#endif