2 // Copyright © 2017 Arm Ltd. All rights reserved.
3 // SPDX-License-Identifier: MIT
8 #include <backendsCommon/DynamicBackend.hpp>
9 #include <backendsCommon/DynamicBackendUtils.hpp>
15 #include <boost/test/unit_test.hpp>
16 #include <boost/filesystem.hpp>
17 #include <boost/dll.hpp>
19 static std::string g_TestBaseDir = "src/backends/backendsCommon/test/";
21 static std::string g_TestSharedObjectSubDir = "testSharedObject/";
22 static std::string g_TestDynamicBackendSubDir = "testDynamicBackend/";
24 static std::string g_TestSharedObjectFileName = "libTestSharedObject.so";
25 static std::string g_TestNoSharedObjectFileName = "libNoSharedObject.txt";
27 static std::string g_TestValidTestDynamicBackendFileName = "libValidTestDynamicBackend.so";
28 static std::string g_TestInvalidTestDynamicBackend1FileName = "libInvalidTestDynamicBackend1.so";
29 static std::string g_TestInvalidTestDynamicBackend2FileName = "libInvalidTestDynamicBackend2.so";
30 static std::string g_TestInvalidTestDynamicBackend3FileName = "libInvalidTestDynamicBackend3.so";
31 static std::string g_TestInvalidTestDynamicBackend4FileName = "libInvalidTestDynamicBackend4.so";
32 static std::string g_TestInvalidTestDynamicBackend5FileName = "libInvalidTestDynamicBackend5.so";
33 static std::string g_TestInvalidTestDynamicBackend6FileName = "libInvalidTestDynamicBackend6.so";
34 static std::string g_TestInvalidTestDynamicBackend7FileName = "libInvalidTestDynamicBackend7.so";
36 static std::string g_TestValidBackend2FileName = "Arm_TestValid2_backend.so";
37 static std::string g_TestValidBackend3FileName = "Arm_TestValid3_backend.so";
38 static std::string g_TestValidBackend4FileName = "Arm_TestValid4_backend.so";
39 static std::string g_TestInvalidBackend8FileName = "Arm_TestInvalid8_backend.so";
40 static std::string g_TestInvalidBackend9FileName = "Arm_TestInvalid9_backend.so";
42 static std::string g_TestDynamicBackendsFileParsingSubDir1 = "backendsTestPath1/";
43 static std::string g_TestDynamicBackendsFileParsingSubDir2 = "backendsTestPath2/";
44 static std::string g_TestDynamicBackendsFileParsingSubDir3 = "backendsTestPath3/";
45 static std::string g_TestDynamicBackendsFileParsingSubDir4 = "backendsTestPath4/";
46 static std::string g_TestDynamicBackendsFileParsingSubDir5 = "backendsTestPath5/";
47 static std::string g_TestDynamicBackendsFileParsingSubDir6 = "backendsTestPath6/";
48 static std::string g_TestDynamicBackendsFileParsingSubDir7 = "backendsTestPath7/";
49 static std::string g_TestDynamicBackendsFileParsingSubDir8 = "backendsTestPath8/";
51 std::string GetTestDirectoryBasePath()
53 using namespace boost::filesystem;
55 path programLocation = boost::dll::program_location().parent_path();
56 path sharedObjectPath = programLocation.append(g_TestBaseDir);
57 BOOST_CHECK(exists(sharedObjectPath));
59 return sharedObjectPath.string();
62 std::string GetTestSubDirectory(const std::string& subdir)
64 using namespace boost::filesystem;
66 std::string testDynamicBackendsBaseDir = GetTestDirectoryBasePath();
67 path testDynamicBackendsBasePath(testDynamicBackendsBaseDir);
68 path testDynamicBackendsSubDir = testDynamicBackendsBasePath.append(subdir);
69 // Do not check that the sub-directory exists because for testing reasons we may use non-existing paths
71 return testDynamicBackendsSubDir.string();
74 std::string GetTestFilePath(const std::string& directory, const std::string& fileName)
76 using namespace boost::filesystem;
78 path directoryPath(directory);
79 path fileNamePath = directoryPath.append(fileName);
80 BOOST_CHECK(exists(fileNamePath));
82 return fileNamePath.string();
85 void OpenCloseHandleTestImpl()
87 using namespace armnn;
89 std::string testSubDirectory = GetTestSubDirectory(g_TestSharedObjectSubDir);
90 std::string sharedObjectFilePath = GetTestFilePath(testSubDirectory, g_TestSharedObjectFileName);
92 void* sharedObjectHandle = nullptr;
93 BOOST_CHECK_NO_THROW(sharedObjectHandle = DynamicBackendUtils::OpenHandle(sharedObjectFilePath));
94 BOOST_TEST((sharedObjectHandle != nullptr));
96 DynamicBackendUtils::CloseHandle(sharedObjectHandle);
99 void CloseInvalidHandleTestImpl()
101 using namespace armnn;
103 // This calls must silently handle invalid handles and complete successfully (no segfaults, etc.)
104 DynamicBackendUtils::CloseHandle(nullptr);
107 void OpenEmptyFileNameTestImpl()
109 using namespace armnn;
111 void* sharedObjectHandle = nullptr;
112 BOOST_CHECK_THROW(sharedObjectHandle = DynamicBackendUtils::OpenHandle(""), RuntimeException);
113 BOOST_TEST((sharedObjectHandle == nullptr));
116 void OpenNotExistingFileTestImpl()
118 using namespace armnn;
120 void* sharedObjectHandle = nullptr;
121 BOOST_CHECK_THROW(sharedObjectHandle = DynamicBackendUtils::OpenHandle("NotExistingFileName"), RuntimeException);
122 BOOST_TEST((sharedObjectHandle == nullptr));
125 void OpenNotSharedObjectTestImpl()
127 using namespace armnn;
129 std::string testSubDirectory = GetTestSubDirectory(g_TestSharedObjectSubDir);
130 std::string notSharedObjectFilePath = GetTestFilePath(testSubDirectory, g_TestNoSharedObjectFileName);
132 void* sharedObjectHandle = nullptr;
133 BOOST_CHECK_THROW(sharedObjectHandle = DynamicBackendUtils::OpenHandle(notSharedObjectFilePath), RuntimeException);
134 BOOST_TEST((sharedObjectHandle == nullptr));
137 void GetValidEntryPointTestImpl()
139 using namespace armnn;
141 std::string testSubDirectory = GetTestSubDirectory(g_TestSharedObjectSubDir);
142 std::string sharedObjectFilePath = GetTestFilePath(testSubDirectory, g_TestSharedObjectFileName);
144 void* sharedObjectHandle = nullptr;
145 BOOST_CHECK_NO_THROW(sharedObjectHandle = DynamicBackendUtils::OpenHandle(sharedObjectFilePath));
146 BOOST_TEST((sharedObjectHandle != nullptr));
148 using TestFunctionType = int(*)(int);
149 TestFunctionType testFunctionPointer = nullptr;
150 BOOST_CHECK_NO_THROW(testFunctionPointer = DynamicBackendUtils::GetEntryPoint<TestFunctionType>(sharedObjectHandle,
152 BOOST_TEST((testFunctionPointer != nullptr));
153 BOOST_TEST(testFunctionPointer(7) == 7);
155 DynamicBackendUtils::CloseHandle(sharedObjectHandle);
158 void GetNameMangledEntryPointTestImpl()
160 using namespace armnn;
162 std::string testSubDirectory = GetTestSubDirectory(g_TestSharedObjectSubDir);
163 std::string sharedObjectFilePath = GetTestFilePath(testSubDirectory, g_TestSharedObjectFileName);
165 void* sharedObjectHandle = nullptr;
166 BOOST_CHECK_NO_THROW(sharedObjectHandle = DynamicBackendUtils::OpenHandle(sharedObjectFilePath));
167 BOOST_TEST((sharedObjectHandle != nullptr));
169 using TestFunctionType = int(*)(int);
170 TestFunctionType testFunctionPointer = nullptr;
171 BOOST_CHECK_THROW(testFunctionPointer = DynamicBackendUtils::GetEntryPoint<TestFunctionType>(sharedObjectHandle,
174 BOOST_TEST((testFunctionPointer == nullptr));
176 DynamicBackendUtils::CloseHandle(sharedObjectHandle);
179 void GetNoExternEntryPointTestImpl()
181 using namespace armnn;
183 std::string testSubDirectory = GetTestSubDirectory(g_TestSharedObjectSubDir);
184 std::string sharedObjectFilePath = GetTestFilePath(testSubDirectory, g_TestSharedObjectFileName);
186 void* sharedObjectHandle = nullptr;
187 BOOST_CHECK_NO_THROW(sharedObjectHandle = DynamicBackendUtils::OpenHandle(sharedObjectFilePath));
188 BOOST_TEST((sharedObjectHandle != nullptr));
190 using TestFunctionType = int(*)(int);
191 TestFunctionType testFunctionPointer = nullptr;
192 BOOST_CHECK_THROW(testFunctionPointer = DynamicBackendUtils::GetEntryPoint<TestFunctionType>(sharedObjectHandle,
195 BOOST_TEST((testFunctionPointer == nullptr));
197 DynamicBackendUtils::CloseHandle(sharedObjectHandle);
200 void GetNotExistingEntryPointTestImpl()
202 using namespace armnn;
204 std::string testSubDirectory = GetTestSubDirectory(g_TestSharedObjectSubDir);
205 std::string sharedObjectFilePath = GetTestFilePath(testSubDirectory, g_TestSharedObjectFileName);
207 void* sharedObjectHandle = nullptr;
208 BOOST_CHECK_NO_THROW(sharedObjectHandle = DynamicBackendUtils::OpenHandle(sharedObjectFilePath));
209 BOOST_TEST((sharedObjectHandle != nullptr));
211 using TestFunctionType = int(*)(int);
212 TestFunctionType testFunctionPointer = nullptr;
213 BOOST_CHECK_THROW(testFunctionPointer = DynamicBackendUtils::GetEntryPoint<TestFunctionType>(sharedObjectHandle,
216 BOOST_TEST((testFunctionPointer == nullptr));
218 DynamicBackendUtils::CloseHandle(sharedObjectHandle);
221 void BackendVersioningTestImpl()
223 using namespace armnn;
225 class TestDynamicBackendUtils : public DynamicBackendUtils
228 static bool IsBackendCompatibleTest(const BackendVersion& backendApiVersion,
229 const BackendVersion& backendVersion)
231 return IsBackendCompatibleImpl(backendApiVersion, backendVersion);
235 // The backend API version used for the tests
236 BackendVersion backendApiVersion{ 2, 4 };
238 // Same backend and backend API versions are compatible with the backend API
239 BackendVersion sameBackendVersion{ 2, 4 };
240 BOOST_TEST(sameBackendVersion == backendApiVersion);
241 BOOST_TEST(sameBackendVersion <= backendApiVersion);
242 BOOST_TEST(TestDynamicBackendUtils::IsBackendCompatibleTest(backendApiVersion, sameBackendVersion) == true);
244 // Backend versions that differ from the backend API version by major revision are not compatible
245 // with the backend API
246 BackendVersion laterMajorBackendVersion{ 3, 4 };
247 BOOST_TEST(!(laterMajorBackendVersion == backendApiVersion));
248 BOOST_TEST(!(laterMajorBackendVersion <= backendApiVersion));
249 BOOST_TEST(TestDynamicBackendUtils::IsBackendCompatibleTest(backendApiVersion, laterMajorBackendVersion) == false);
251 BackendVersion earlierMajorBackendVersion{ 1, 4 };
252 BOOST_TEST(!(earlierMajorBackendVersion == backendApiVersion));
253 BOOST_TEST(earlierMajorBackendVersion <= backendApiVersion);
254 BOOST_TEST(TestDynamicBackendUtils::IsBackendCompatibleTest(backendApiVersion,
255 earlierMajorBackendVersion) == false);
257 // Backend versions with the same major revision but later minor revision than
258 // the backend API version are not compatible with the backend API
259 BackendVersion laterMinorBackendVersion{ 2, 5 };
260 BOOST_TEST(!(laterMinorBackendVersion == backendApiVersion));
261 BOOST_TEST(!(laterMinorBackendVersion <= backendApiVersion));
262 BOOST_TEST(TestDynamicBackendUtils::IsBackendCompatibleTest(backendApiVersion, laterMinorBackendVersion) == false);
264 // Backend versions with the same major revision but earlier minor revision than
265 // the backend API version are compatible with the backend API
266 BackendVersion earlierMinorBackendVersion{ 2, 3 };
267 BOOST_TEST(!(earlierMinorBackendVersion == backendApiVersion));
268 BOOST_TEST(earlierMinorBackendVersion <= backendApiVersion);
269 BOOST_TEST(TestDynamicBackendUtils::IsBackendCompatibleTest(backendApiVersion, earlierMinorBackendVersion) == true);
272 void CreateValidDynamicBackendObjectTestImpl()
274 // Valid shared object handle
275 // Correct name mangling
277 // Correct backend implementation
279 using namespace armnn;
281 std::string testSubDirectory = GetTestSubDirectory(g_TestDynamicBackendSubDir);
282 std::string sharedObjectFilePath = GetTestFilePath(testSubDirectory, g_TestValidTestDynamicBackendFileName);
284 void* sharedObjectHandle = nullptr;
285 BOOST_CHECK_NO_THROW(sharedObjectHandle = DynamicBackendUtils::OpenHandle(sharedObjectFilePath));
286 BOOST_TEST((sharedObjectHandle != nullptr));
288 DynamicBackendPtr dynamicBackend;
289 BOOST_CHECK_NO_THROW(dynamicBackend.reset(new DynamicBackend(sharedObjectHandle)));
290 BOOST_TEST((dynamicBackend != nullptr));
292 BackendId dynamicBackendId;
293 BOOST_CHECK_NO_THROW(dynamicBackendId = dynamicBackend->GetBackendId());
294 BOOST_TEST((dynamicBackendId == "ValidTestDynamicBackend"));
296 BackendVersion dynamicBackendVersion;
297 BOOST_CHECK_NO_THROW(dynamicBackendVersion = dynamicBackend->GetBackendVersion());
298 BOOST_TEST((dynamicBackendVersion == IBackendInternal::GetApiVersion()));
300 IBackendInternalUniquePtr dynamicBackendInstance;
301 BOOST_CHECK_NO_THROW(dynamicBackendInstance = dynamicBackend->GetBackend());
302 BOOST_TEST((dynamicBackendInstance != nullptr));
304 BOOST_TEST((dynamicBackendInstance->GetId() == "ValidTestDynamicBackend"));
307 void CreateDynamicBackendObjectInvalidHandleTestImpl()
309 // Invalid (null) shared object handle
311 using namespace armnn;
313 void* sharedObjectHandle = nullptr;
314 DynamicBackendPtr dynamicBackend;
315 BOOST_CHECK_THROW(dynamicBackend.reset(new DynamicBackend(sharedObjectHandle)), InvalidArgumentException);
316 BOOST_TEST((dynamicBackend == nullptr));
319 void CreateDynamicBackendObjectInvalidInterface1TestImpl()
321 // Valid shared object handle
322 // Wrong (not C-style) name mangling
324 using namespace armnn;
326 std::string testSubDirectory = GetTestSubDirectory(g_TestDynamicBackendSubDir);
327 std::string sharedObjectFilePath = GetTestFilePath(testSubDirectory, g_TestInvalidTestDynamicBackend1FileName);
329 void* sharedObjectHandle = nullptr;
330 BOOST_CHECK_NO_THROW(sharedObjectHandle = DynamicBackendUtils::OpenHandle(sharedObjectFilePath));
331 BOOST_TEST((sharedObjectHandle != nullptr));
333 DynamicBackendPtr dynamicBackend;
334 BOOST_CHECK_THROW(dynamicBackend.reset(new DynamicBackend(sharedObjectHandle)), RuntimeException);
335 BOOST_TEST((dynamicBackend == nullptr));
338 void CreateDynamicBackendObjectInvalidInterface2TestImpl()
340 // Valid shared object handle
341 // Correct name mangling
342 // Wrong interface (missing GetBackendId())
344 using namespace armnn;
346 std::string testSubDirectory = GetTestSubDirectory(g_TestDynamicBackendSubDir);
347 std::string sharedObjectFilePath = GetTestFilePath(testSubDirectory, g_TestInvalidTestDynamicBackend2FileName);
349 void* sharedObjectHandle = nullptr;
350 BOOST_CHECK_NO_THROW(sharedObjectHandle = DynamicBackendUtils::OpenHandle(sharedObjectFilePath));
351 BOOST_TEST((sharedObjectHandle != nullptr));
353 DynamicBackendPtr dynamicBackend;
354 BOOST_CHECK_THROW(dynamicBackend.reset(new DynamicBackend(sharedObjectHandle)), RuntimeException);
355 BOOST_TEST((dynamicBackend == nullptr));
358 void CreateDynamicBackendObjectInvalidInterface3TestImpl()
360 // Valid shared object handle
361 // Correct name mangling
362 // Wrong interface (missing GetVersion())
364 using namespace armnn;
366 std::string testSubDirectory = GetTestSubDirectory(g_TestDynamicBackendSubDir);
367 std::string sharedObjectFilePath = GetTestFilePath(testSubDirectory, g_TestInvalidTestDynamicBackend3FileName);
369 void* sharedObjectHandle = nullptr;
370 BOOST_CHECK_NO_THROW(sharedObjectHandle = DynamicBackendUtils::OpenHandle(sharedObjectFilePath));
371 BOOST_TEST((sharedObjectHandle != nullptr));
373 DynamicBackendPtr dynamicBackend;
374 BOOST_CHECK_THROW(dynamicBackend.reset(new DynamicBackend(sharedObjectHandle)), RuntimeException);
375 BOOST_TEST((dynamicBackend == nullptr));
378 void CreateDynamicBackendObjectInvalidInterface4TestImpl()
380 // Valid shared object handle
381 // Correct name mangling
382 // Wrong interface (missing BackendFactory())
384 using namespace armnn;
386 std::string testSubDirectory = GetTestSubDirectory(g_TestDynamicBackendSubDir);
387 std::string sharedObjectFilePath = GetTestFilePath(testSubDirectory, g_TestInvalidTestDynamicBackend4FileName);
389 void* sharedObjectHandle = nullptr;
390 BOOST_CHECK_NO_THROW(sharedObjectHandle = DynamicBackendUtils::OpenHandle(sharedObjectFilePath));
391 BOOST_TEST((sharedObjectHandle != nullptr));
393 DynamicBackendPtr dynamicBackend;
394 BOOST_CHECK_THROW(dynamicBackend.reset(new DynamicBackend(sharedObjectHandle)), RuntimeException);
395 BOOST_TEST((dynamicBackend == nullptr));
398 void CreateDynamicBackendObjectInvalidInterface5TestImpl()
400 // Valid shared object handle
401 // Correct name mangling
403 // Invalid (null) backend id returned by GetBackendId()
405 using namespace armnn;
407 std::string testSubDirectory = GetTestSubDirectory(g_TestDynamicBackendSubDir);
408 std::string sharedObjectFilePath = GetTestFilePath(testSubDirectory, g_TestInvalidTestDynamicBackend5FileName);
410 void* sharedObjectHandle = nullptr;
411 BOOST_CHECK_NO_THROW(sharedObjectHandle = DynamicBackendUtils::OpenHandle(sharedObjectFilePath));
412 BOOST_TEST((sharedObjectHandle != nullptr));
414 DynamicBackendPtr dynamicBackend;
415 BOOST_CHECK_THROW(dynamicBackend.reset(new DynamicBackend(sharedObjectHandle)), RuntimeException);
416 BOOST_TEST((dynamicBackend == nullptr));
419 void CreateDynamicBackendObjectInvalidInterface6TestImpl()
421 // Valid shared object handle
422 // Correct name mangling
424 // Invalid (null) backend instance returned by BackendFactory()
426 using namespace armnn;
428 std::string testSubDirectory = GetTestSubDirectory(g_TestDynamicBackendSubDir);
429 std::string sharedObjectFilePath = GetTestFilePath(testSubDirectory, g_TestInvalidTestDynamicBackend6FileName);
431 void* sharedObjectHandle = nullptr;
432 BOOST_CHECK_NO_THROW(sharedObjectHandle = DynamicBackendUtils::OpenHandle(sharedObjectFilePath));
433 BOOST_TEST((sharedObjectHandle != nullptr));
435 DynamicBackendPtr dynamicBackend;
436 BOOST_CHECK_NO_THROW(dynamicBackend.reset(new DynamicBackend(sharedObjectHandle)));
437 BOOST_TEST((dynamicBackend != nullptr));
439 BackendId dynamicBackendId;
440 BOOST_CHECK_NO_THROW(dynamicBackendId = dynamicBackend->GetBackendId());
441 BOOST_TEST((dynamicBackendId == "InvalidTestDynamicBackend"));
443 BackendVersion dynamicBackendVersion;
444 BOOST_CHECK_NO_THROW(dynamicBackendVersion = dynamicBackend->GetBackendVersion());
445 BOOST_TEST((dynamicBackendVersion == BackendVersion({ 1, 0 })));
447 IBackendInternalUniquePtr dynamicBackendInstance;
448 BOOST_CHECK_THROW(dynamicBackendInstance = dynamicBackend->GetBackend(), RuntimeException);
449 BOOST_TEST((dynamicBackendInstance == nullptr));
452 void CreateDynamicBackendObjectInvalidInterface7TestImpl()
454 // Valid shared object handle
455 // Correct name mangling
457 // Invalid (incompatible backend API version) backend instance returned by BackendFactory()
459 using namespace armnn;
461 std::string testSubDirectory = GetTestSubDirectory(g_TestDynamicBackendSubDir);
462 std::string sharedObjectFilePath = GetTestFilePath(testSubDirectory, g_TestInvalidTestDynamicBackend7FileName);
464 void* sharedObjectHandle = nullptr;
465 BOOST_CHECK_NO_THROW(sharedObjectHandle = DynamicBackendUtils::OpenHandle(sharedObjectFilePath));
466 BOOST_TEST((sharedObjectHandle != nullptr));
468 DynamicBackendPtr dynamicBackend;
469 BOOST_CHECK_THROW(dynamicBackend.reset(new DynamicBackend(sharedObjectHandle)), RuntimeException);
470 BOOST_TEST((dynamicBackend == nullptr));
473 void GetBackendPathsTestImpl()
475 using namespace armnn;
476 using namespace boost::filesystem;
478 // The test covers four directories:
479 // <unit test path>/src/backends/backendsCommon/test/
480 // ├─ backendsTestPath1/ -> exists, contains files
481 // ├─ backendsTestPath2/ -> exists, contains files
482 // ├─ backendsTestPath3/ -> exists, but empty
483 // └─ backendsTestPath4/ -> does not exist
485 std::string subDir1 = GetTestSubDirectory(g_TestDynamicBackendsFileParsingSubDir1);
486 std::string subDir2 = GetTestSubDirectory(g_TestDynamicBackendsFileParsingSubDir2);
487 std::string subDir3 = GetTestSubDirectory(g_TestDynamicBackendsFileParsingSubDir3);
488 std::string subDir4 = GetTestSubDirectory(g_TestDynamicBackendsFileParsingSubDir4);
490 BOOST_CHECK(exists(subDir1));
491 BOOST_CHECK(exists(subDir2));
492 BOOST_CHECK(exists(subDir3));
493 BOOST_CHECK(!exists(subDir4));
495 class TestDynamicBackendUtils : public DynamicBackendUtils
498 static std::vector<std::string> GetBackendPathsImplTest(const std::string& path)
500 return GetBackendPathsImpl(path);
505 BOOST_TEST(TestDynamicBackendUtils::GetBackendPathsImplTest("").empty());
508 std::string malformedDir(subDir1 + "/" + subDir1);
509 BOOST_TEST(TestDynamicBackendUtils::GetBackendPathsImplTest(malformedDir).size()==0);
512 std::vector<std::string> DynamicBackendPaths2 = TestDynamicBackendUtils::GetBackendPathsImplTest(subDir1);
513 BOOST_TEST(DynamicBackendPaths2.size() == 1);
514 BOOST_TEST(DynamicBackendPaths2[0] == subDir1);
516 // Multiple equal and valid paths
517 std::string multipleEqualDirs(subDir1 + ":" + subDir1);
518 std::vector<std::string> DynamicBackendPaths3 = TestDynamicBackendUtils::GetBackendPathsImplTest(multipleEqualDirs);
519 BOOST_TEST(DynamicBackendPaths3.size() == 1);
520 BOOST_TEST(DynamicBackendPaths3[0] == subDir1);
522 // Multiple empty paths
523 BOOST_TEST(TestDynamicBackendUtils::GetBackendPathsImplTest(":::").empty());
525 // Multiple valid paths
526 std::string multipleValidPaths(subDir1 + ":" + subDir2 + ":" + subDir3);
527 std::vector<std::string> DynamicBackendPaths5 =
528 TestDynamicBackendUtils::GetBackendPathsImplTest(multipleValidPaths);
529 BOOST_TEST(DynamicBackendPaths5.size() == 3);
530 BOOST_TEST(DynamicBackendPaths5[0] == subDir1);
531 BOOST_TEST(DynamicBackendPaths5[1] == subDir2);
532 BOOST_TEST(DynamicBackendPaths5[2] == subDir3);
534 // Valid among empty paths
535 std::string validAmongEmptyDirs("::" + subDir1 + ":");
536 std::vector<std::string> DynamicBackendPaths6 =
537 TestDynamicBackendUtils::GetBackendPathsImplTest(validAmongEmptyDirs);
538 BOOST_TEST(DynamicBackendPaths6.size() == 1);
539 BOOST_TEST(DynamicBackendPaths6[0] == subDir1);
541 // Invalid among empty paths
542 std::string invalidAmongEmptyDirs(":" + subDir4 + "::");
543 BOOST_TEST(TestDynamicBackendUtils::GetBackendPathsImplTest(invalidAmongEmptyDirs).empty());
545 // Valid, invalid and empty paths
546 std::string validInvalidEmptyDirs(subDir1 + ":" + subDir4 + ":");
547 std::vector<std::string> DynamicBackendPaths8 =
548 TestDynamicBackendUtils::GetBackendPathsImplTest(validInvalidEmptyDirs);
549 BOOST_TEST(DynamicBackendPaths8.size() == 1);
550 BOOST_TEST(DynamicBackendPaths8[0] == subDir1);
552 // Mix of duplicates of valid, invalid and empty paths
553 std::string duplicateValidInvalidEmptyDirs(validInvalidEmptyDirs + ":" + validInvalidEmptyDirs + ":" +
554 subDir2 + ":" + subDir2);
555 std::vector<std::string> DynamicBackendPaths9 =
556 TestDynamicBackendUtils::GetBackendPathsImplTest(duplicateValidInvalidEmptyDirs);
557 BOOST_TEST(DynamicBackendPaths9.size() == 2);
558 BOOST_TEST(DynamicBackendPaths9[0] == subDir1);
559 BOOST_TEST(DynamicBackendPaths9[1] == subDir2);
562 void GetBackendPathsOverrideTestImpl()
564 using namespace armnn;
565 using namespace boost::filesystem;
567 std::string subDir1 = GetTestSubDirectory(g_TestDynamicBackendsFileParsingSubDir1);
568 std::string subDir4 = GetTestSubDirectory(g_TestDynamicBackendsFileParsingSubDir4);
570 BOOST_CHECK(exists(subDir1));
571 BOOST_CHECK(!exists(subDir4));
573 // Override with valid path
574 std::vector<std::string> validResult = DynamicBackendUtils::GetBackendPaths(subDir1);
575 BOOST_TEST(validResult.size() == 1);
576 BOOST_TEST(validResult[0] == subDir1);
578 // Override with invalid path
579 std::vector<std::string> invalidResult = DynamicBackendUtils::GetBackendPaths(subDir4);
580 BOOST_TEST(invalidResult.empty());
583 void GetSharedObjectsTestImpl()
585 using namespace armnn;
586 using namespace boost::filesystem;
588 // The test covers four directories:
589 // <unit test path>/src/backends/backendsCommon/test/
590 // ├─ backendsTestPath1/ -> exists, contains files
591 // ├─ backendsTestPath2/ -> exists, contains files
592 // ├─ backendsTestPath3/ -> exists, but empty
593 // └─ backendsTestPath4/ -> does not exist
595 // The test sub-directory backendsTestPath1/ contains the following test files:
597 // Arm_GpuAcc_backend.so -> valid (basic backend name)
598 // Arm_GpuAcc_backend.so.1 -> valid (single field version number)
599 // Arm_GpuAcc_backend.so.1.2 -> valid (multiple field version number)
600 // Arm_GpuAcc_backend.so.1.2.3 -> valid (multiple field version number)
601 // Arm_GpuAcc_backend.so.10.1.27 -> valid (Multiple digit version)
602 // Arm_GpuAcc_backend.so.10.1.33. -> not valid (dot not followed by version number)
603 // Arm_GpuAcc_backend.so.3.4..5 -> not valid (dot not followed by version number)
604 // Arm_GpuAcc_backend.so.1,1.1 -> not valid (comma instead of dot in the version)
606 // Arm123_GpuAcc_backend.so -> valid (digits in vendor name are allowed)
607 // Arm_GpuAcc456_backend.so -> valid (digits in backend id are allowed)
608 // Arm%Co_GpuAcc_backend.so -> not valid (invalid character in vendor name)
609 // Arm_Gpu.Acc_backend.so -> not valid (invalid character in backend id)
611 // GpuAcc_backend.so -> not valid (missing vendor name)
612 // _GpuAcc_backend.so -> not valid (missing vendor name)
613 // Arm__backend.so -> not valid (missing backend id)
614 // Arm_GpuAcc.so -> not valid (missing "backend" at the end)
615 // __backend.so -> not valid (missing vendor name and backend id)
616 // __.so -> not valid (missing all fields)
618 // Arm_GpuAcc_backend -> not valid (missing at least ".so" at the end)
619 // Arm_GpuAcc_backend_v1.2.so -> not valid (extra version info at the end)
621 // The test sub-directory backendsTestPath1/ contains the following test files:
623 // Arm_CpuAcc_backend.so -> valid (basic backend name)
624 // Arm_CpuAcc_backend.so.1 -> Arm_CpuAcc_backend.so -> valid (symlink to valid backend file)
625 // Arm_CpuAcc_backend.so.1.2 -> Arm_CpuAcc_backend.so.1 -> valid (symlink to valid symlink)
626 // Arm_CpuAcc_backend.so.1.2.3 -> Arm_CpuAcc_backend.so.1.2 -> valid (symlink to valid symlink)
628 // Arm_no_backend.so -> nothing -> not valid (symlink resolves to non-existent file)
630 // Arm_GpuAcc_backend.so -> valid (but duplicated from backendsTestPath1/)
632 std::string testDynamicBackendsSubDir1 = GetTestSubDirectory(g_TestDynamicBackendsFileParsingSubDir1);
633 std::string testDynamicBackendsSubDir2 = GetTestSubDirectory(g_TestDynamicBackendsFileParsingSubDir2);
634 std::string testDynamicBackendsSubDir3 = GetTestSubDirectory(g_TestDynamicBackendsFileParsingSubDir3);
635 std::string testDynamicBackendsSubDir4 = GetTestSubDirectory(g_TestDynamicBackendsFileParsingSubDir4);
636 BOOST_CHECK(exists(testDynamicBackendsSubDir1));
637 BOOST_CHECK(exists(testDynamicBackendsSubDir2));
638 BOOST_CHECK(exists(testDynamicBackendsSubDir3));
639 BOOST_CHECK(!exists(testDynamicBackendsSubDir4));
641 std::vector<std::string> backendPaths
643 testDynamicBackendsSubDir1,
644 testDynamicBackendsSubDir2,
645 testDynamicBackendsSubDir3,
646 testDynamicBackendsSubDir4
648 std::vector<std::string> sharedObjects = DynamicBackendUtils::GetSharedObjects(backendPaths);
649 std::vector<std::string> expectedSharedObjects
651 testDynamicBackendsSubDir1 + "Arm123_GpuAcc_backend.so", // Digits in vendor name are allowed
652 testDynamicBackendsSubDir1 + "Arm_GpuAcc456_backend.so", // Digits in backend id are allowed
653 testDynamicBackendsSubDir1 + "Arm_GpuAcc_backend.so", // Basic backend name
654 testDynamicBackendsSubDir1 + "Arm_GpuAcc_backend.so.1", // Single field version number
655 testDynamicBackendsSubDir1 + "Arm_GpuAcc_backend.so.1.2", // Multiple field version number
656 testDynamicBackendsSubDir1 + "Arm_GpuAcc_backend.so.1.2.3", // Multiple field version number
657 testDynamicBackendsSubDir1 + "Arm_GpuAcc_backend.so.10.1.27", // Multiple digit version
658 testDynamicBackendsSubDir2 + "Arm_CpuAcc_backend.so", // Duplicate symlinks removed
659 testDynamicBackendsSubDir2 + "Arm_GpuAcc_backend.so" // Duplicates on different paths are allowed
662 BOOST_TEST(sharedObjects.size() == expectedSharedObjects.size());
663 BOOST_TEST(sharedObjects[0] == expectedSharedObjects[0]);
664 BOOST_TEST(sharedObjects[1] == expectedSharedObjects[1]);
665 BOOST_TEST(sharedObjects[2] == expectedSharedObjects[2]);
666 BOOST_TEST(sharedObjects[3] == expectedSharedObjects[3]);
667 BOOST_TEST(sharedObjects[4] == expectedSharedObjects[4]);
668 BOOST_TEST(sharedObjects[5] == expectedSharedObjects[5]);
669 BOOST_TEST(sharedObjects[6] == expectedSharedObjects[6]);
670 BOOST_TEST(sharedObjects[7] == expectedSharedObjects[7]);
671 BOOST_TEST(sharedObjects[8] == expectedSharedObjects[8]);
674 void CreateDynamicBackendsTestImpl()
676 using namespace armnn;
677 using namespace boost::filesystem;
679 // The test covers three directories:
680 // <unit test path>/src/backends/backendsCommon/test/
681 // ├─ backendsTestPath5/ -> exists, contains files
682 // ├─ backendsTestPath6/ -> exists, contains files
683 // ├─ backendsTestPath7/ -> exists, but empty
684 // └─ backendsTestPath8/ -> does not exist
686 // The test sub-directory backendsTestPath5/ contains the following test files:
688 // Arm_TestValid2_backend.so -> valid (basic backend name)
689 // Arm_TestValid3_backend.so -> valid (basic backend name)
690 // Arm_TestInvalid8_backend.so -> not valid (invalid backend id)
692 // The test sub-directory backendsTestPath6/ contains the following test files:
694 // Arm_TestValid2_backend.so -> valid (but duplicated from backendsTestPath5/)
695 // Arm_TestValid4_backend.so -> valid (it has a different filename,
696 // but it has the same backend id of Arm_TestValid2_backend.so
697 // and the same version)
698 // Arm_TestInvalid9_backend.so -> not valid (it has a different filename,
699 // but it has the same backend id of Arm_TestValid2_backend.so
700 // and a version incompatible with the Backend API)
702 std::string testDynamicBackendsSubDir5 = GetTestSubDirectory(g_TestDynamicBackendsFileParsingSubDir5);
703 std::string testDynamicBackendsSubDir6 = GetTestSubDirectory(g_TestDynamicBackendsFileParsingSubDir6);
704 std::string testDynamicBackendsSubDir7 = GetTestSubDirectory(g_TestDynamicBackendsFileParsingSubDir7);
705 std::string testDynamicBackendsSubDir8 = GetTestSubDirectory(g_TestDynamicBackendsFileParsingSubDir8);
706 BOOST_CHECK(exists(testDynamicBackendsSubDir5));
707 BOOST_CHECK(exists(testDynamicBackendsSubDir6));
708 BOOST_CHECK(exists(testDynamicBackendsSubDir7));
709 BOOST_CHECK(!exists(testDynamicBackendsSubDir8));
711 std::vector<std::string> backendPaths
713 testDynamicBackendsSubDir5,
714 testDynamicBackendsSubDir6,
715 testDynamicBackendsSubDir7,
716 testDynamicBackendsSubDir8
718 std::vector<std::string> sharedObjects = DynamicBackendUtils::GetSharedObjects(backendPaths);
719 std::vector<DynamicBackendPtr> dynamicBackends = DynamicBackendUtils::CreateDynamicBackends(sharedObjects);
721 BOOST_TEST(dynamicBackends.size() == 4);
722 BOOST_TEST((dynamicBackends[0] != nullptr));
723 BOOST_TEST((dynamicBackends[1] != nullptr));
724 BOOST_TEST((dynamicBackends[2] != nullptr));
725 BOOST_TEST((dynamicBackends[3] != nullptr));
727 // Duplicates are allowed here, they will be skipped later during the backend registration
728 BOOST_TEST((dynamicBackends[0]->GetBackendId() == "TestValid2"));
729 BOOST_TEST((dynamicBackends[1]->GetBackendId() == "TestValid3"));
730 BOOST_TEST((dynamicBackends[2]->GetBackendId() == "TestValid2")); // From duplicate Arm_TestValid2_backend.so
731 BOOST_TEST((dynamicBackends[3]->GetBackendId() == "TestValid2")); // From Arm_TestValid4_backend.so
734 void CreateDynamicBackendsNoPathsTestImpl()
736 using namespace armnn;
738 std::vector<DynamicBackendPtr> dynamicBackends = DynamicBackendUtils::CreateDynamicBackends({});
740 BOOST_TEST(dynamicBackends.empty());
743 void CreateDynamicBackendsAllInvalidTestImpl()
745 using namespace armnn;
747 std::vector<std::string> sharedObjects
749 "InvalidSharedObject1",
750 "InvalidSharedObject2",
751 "InvalidSharedObject3",
753 std::vector<DynamicBackendPtr> dynamicBackends = DynamicBackendUtils::CreateDynamicBackends(sharedObjects);
755 BOOST_TEST(dynamicBackends.empty());
758 void CreateDynamicBackendsMixedTypesTestImpl()
760 using namespace armnn;
761 using namespace boost::filesystem;
763 std::string testDynamicBackendsSubDir5 = GetTestSubDirectory(g_TestDynamicBackendsFileParsingSubDir5);
764 std::string testDynamicBackendsSubDir6 = GetTestSubDirectory(g_TestDynamicBackendsFileParsingSubDir6);
765 BOOST_CHECK(exists(testDynamicBackendsSubDir5));
766 BOOST_CHECK(exists(testDynamicBackendsSubDir6));
768 std::string testValidBackend2FilePath = GetTestFilePath(testDynamicBackendsSubDir5,
769 g_TestValidBackend2FileName);
770 std::string testInvalidBackend8FilePath = GetTestFilePath(testDynamicBackendsSubDir5,
771 g_TestInvalidBackend8FileName);
772 std::string testInvalidBackend9FilePath = GetTestFilePath(testDynamicBackendsSubDir6,
773 g_TestInvalidBackend9FileName);
774 BOOST_CHECK(exists(testValidBackend2FilePath));
775 BOOST_CHECK(exists(testInvalidBackend8FilePath));
776 BOOST_CHECK(exists(testInvalidBackend9FilePath));
778 std::vector<std::string> sharedObjects
780 testValidBackend2FilePath, // Arm_TestValid2_backend.so -> valid (basic backend name)
781 testInvalidBackend8FilePath, // Arm_TestInvalid8_backend.so -> not valid (invalid backend id)
782 testInvalidBackend9FilePath, // Arm_TestInvalid9_backend.so -> not valid (incompatible version)
783 "InvalidSharedObject", // The file does not exist
785 std::vector<DynamicBackendPtr> dynamicBackends = DynamicBackendUtils::CreateDynamicBackends(sharedObjects);
787 BOOST_TEST(dynamicBackends.size() == 1);
788 BOOST_TEST((dynamicBackends[0] != nullptr));
789 BOOST_TEST((dynamicBackends[0]->GetBackendId() == "TestValid2"));