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_TestDynamicBackendsFileParsingSubDir1 = "backendsTestPath1/";
37 static std::string g_TestDynamicBackendsFileParsingSubDir2 = "backendsTestPath2/";
38 static std::string g_TestDynamicBackendsFileParsingSubDir3 = "backendsTestPath3/";
39 static std::string g_TestDynamicBackendsFileParsingSubDir4 = "backendsTestPath4/";
41 std::string GetTestDirectoryBasePath()
43 using namespace boost::filesystem;
45 path programLocation = boost::dll::program_location().parent_path();
46 path sharedObjectPath = programLocation.append(g_TestBaseDir);
47 BOOST_CHECK(exists(sharedObjectPath));
49 return sharedObjectPath.string();
52 std::string GetTestSubDirectory(const std::string& subdir)
54 using namespace boost::filesystem;
56 std::string testDynamicBackendsBaseDir = GetTestDirectoryBasePath();
57 path testDynamicBackendsBasePath(testDynamicBackendsBaseDir);
58 path testDynamicBackendsSubDir = testDynamicBackendsBasePath.append(subdir);
59 // Do not check that the sub-directory exists because for testing reasons we may use non-existing paths
61 return testDynamicBackendsSubDir.string();
64 std::string GetTestFilePath(const std::string& directory, const std::string& fileName)
66 using namespace boost::filesystem;
68 path directoryPath(directory);
69 path fileNamePath = directoryPath.append(fileName);
70 BOOST_CHECK(exists(fileNamePath));
72 return fileNamePath.string();
75 void OpenCloseHandleTestImpl()
77 using namespace armnn;
79 std::string testSubDirectory = GetTestSubDirectory(g_TestSharedObjectSubDir);
80 std::string sharedObjectFilePath = GetTestFilePath(testSubDirectory, g_TestSharedObjectFileName);
82 void* sharedObjectHandle = nullptr;
83 BOOST_CHECK_NO_THROW(sharedObjectHandle = DynamicBackendUtils::OpenHandle(sharedObjectFilePath));
84 BOOST_TEST((sharedObjectHandle != nullptr));
86 DynamicBackendUtils::CloseHandle(sharedObjectHandle);
89 void CloseInvalidHandleTestImpl()
91 using namespace armnn;
93 // This calls must silently handle invalid handles and complete successfully (no segfaults, etc.)
94 DynamicBackendUtils::CloseHandle(nullptr);
97 void OpenEmptyFileNameTestImpl()
99 using namespace armnn;
101 void* sharedObjectHandle = nullptr;
102 BOOST_CHECK_THROW(sharedObjectHandle = DynamicBackendUtils::OpenHandle(""), RuntimeException);
103 BOOST_TEST((sharedObjectHandle == nullptr));
106 void OpenNotExistingFileTestImpl()
108 using namespace armnn;
110 void* sharedObjectHandle = nullptr;
111 BOOST_CHECK_THROW(sharedObjectHandle = DynamicBackendUtils::OpenHandle("NotExistingFileName"), RuntimeException);
112 BOOST_TEST((sharedObjectHandle == nullptr));
115 void OpenNotSharedObjectTestImpl()
117 using namespace armnn;
119 std::string testSubDirectory = GetTestSubDirectory(g_TestSharedObjectSubDir);
120 std::string notSharedObjectFilePath = GetTestFilePath(testSubDirectory, g_TestNoSharedObjectFileName);
122 void* sharedObjectHandle = nullptr;
123 BOOST_CHECK_THROW(sharedObjectHandle = DynamicBackendUtils::OpenHandle(notSharedObjectFilePath), RuntimeException);
124 BOOST_TEST((sharedObjectHandle == nullptr));
127 void GetValidEntryPointTestImpl()
129 using namespace armnn;
131 std::string testSubDirectory = GetTestSubDirectory(g_TestSharedObjectSubDir);
132 std::string sharedObjectFilePath = GetTestFilePath(testSubDirectory, g_TestSharedObjectFileName);
134 void* sharedObjectHandle = nullptr;
135 BOOST_CHECK_NO_THROW(sharedObjectHandle = DynamicBackendUtils::OpenHandle(sharedObjectFilePath));
136 BOOST_TEST((sharedObjectHandle != nullptr));
138 using TestFunctionType = int(*)(int);
139 TestFunctionType testFunctionPointer = nullptr;
140 BOOST_CHECK_NO_THROW(testFunctionPointer = DynamicBackendUtils::GetEntryPoint<TestFunctionType>(sharedObjectHandle,
142 BOOST_TEST((testFunctionPointer != nullptr));
143 BOOST_TEST(testFunctionPointer(7) == 7);
145 DynamicBackendUtils::CloseHandle(sharedObjectHandle);
148 void GetNameMangledEntryPointTestImpl()
150 using namespace armnn;
152 std::string testSubDirectory = GetTestSubDirectory(g_TestSharedObjectSubDir);
153 std::string sharedObjectFilePath = GetTestFilePath(testSubDirectory, g_TestSharedObjectFileName);
155 void* sharedObjectHandle = nullptr;
156 BOOST_CHECK_NO_THROW(sharedObjectHandle = DynamicBackendUtils::OpenHandle(sharedObjectFilePath));
157 BOOST_TEST((sharedObjectHandle != nullptr));
159 using TestFunctionType = int(*)(int);
160 TestFunctionType testFunctionPointer = nullptr;
161 BOOST_CHECK_THROW(testFunctionPointer = DynamicBackendUtils::GetEntryPoint<TestFunctionType>(sharedObjectHandle,
164 BOOST_TEST((testFunctionPointer == nullptr));
166 DynamicBackendUtils::CloseHandle(sharedObjectHandle);
169 void GetNoExternEntryPointTestImpl()
171 using namespace armnn;
173 std::string testSubDirectory = GetTestSubDirectory(g_TestSharedObjectSubDir);
174 std::string sharedObjectFilePath = GetTestFilePath(testSubDirectory, g_TestSharedObjectFileName);
176 void* sharedObjectHandle = nullptr;
177 BOOST_CHECK_NO_THROW(sharedObjectHandle = DynamicBackendUtils::OpenHandle(sharedObjectFilePath));
178 BOOST_TEST((sharedObjectHandle != nullptr));
180 using TestFunctionType = int(*)(int);
181 TestFunctionType testFunctionPointer = nullptr;
182 BOOST_CHECK_THROW(testFunctionPointer = DynamicBackendUtils::GetEntryPoint<TestFunctionType>(sharedObjectHandle,
185 BOOST_TEST((testFunctionPointer == nullptr));
187 DynamicBackendUtils::CloseHandle(sharedObjectHandle);
190 void GetNotExistingEntryPointTestImpl()
192 using namespace armnn;
194 std::string testSubDirectory = GetTestSubDirectory(g_TestSharedObjectSubDir);
195 std::string sharedObjectFilePath = GetTestFilePath(testSubDirectory, g_TestSharedObjectFileName);
197 void* sharedObjectHandle = nullptr;
198 BOOST_CHECK_NO_THROW(sharedObjectHandle = DynamicBackendUtils::OpenHandle(sharedObjectFilePath));
199 BOOST_TEST((sharedObjectHandle != nullptr));
201 using TestFunctionType = int(*)(int);
202 TestFunctionType testFunctionPointer = nullptr;
203 BOOST_CHECK_THROW(testFunctionPointer = DynamicBackendUtils::GetEntryPoint<TestFunctionType>(sharedObjectHandle,
206 BOOST_TEST((testFunctionPointer == nullptr));
208 DynamicBackendUtils::CloseHandle(sharedObjectHandle);
211 void BackendVersioningTestImpl()
213 using namespace armnn;
215 class TestDynamicBackendUtils : public DynamicBackendUtils
218 static bool IsBackendCompatibleTest(const BackendVersion& backendApiVersion,
219 const BackendVersion& backendVersion)
221 return IsBackendCompatibleImpl(backendApiVersion, backendVersion);
225 // The backend API version used for the tests
226 BackendVersion backendApiVersion{ 2, 4 };
228 // Same backend and backend API versions are compatible with the backend API
229 BackendVersion sameBackendVersion{ 2, 4 };
230 BOOST_TEST(sameBackendVersion == backendApiVersion);
231 BOOST_TEST(sameBackendVersion <= backendApiVersion);
232 BOOST_TEST(TestDynamicBackendUtils::IsBackendCompatibleTest(backendApiVersion, sameBackendVersion) == true);
234 // Backend versions that differ from the backend API version by major revision are not compatible
235 // with the backend API
236 BackendVersion laterMajorBackendVersion{ 3, 4 };
237 BOOST_TEST(!(laterMajorBackendVersion == backendApiVersion));
238 BOOST_TEST(!(laterMajorBackendVersion <= backendApiVersion));
239 BOOST_TEST(TestDynamicBackendUtils::IsBackendCompatibleTest(backendApiVersion, laterMajorBackendVersion) == false);
241 BackendVersion earlierMajorBackendVersion{ 1, 4 };
242 BOOST_TEST(!(earlierMajorBackendVersion == backendApiVersion));
243 BOOST_TEST(earlierMajorBackendVersion <= backendApiVersion);
244 BOOST_TEST(TestDynamicBackendUtils::IsBackendCompatibleTest(backendApiVersion,
245 earlierMajorBackendVersion) == false);
247 // Backend versions with the same major revision but later minor revision than
248 // the backend API version are not compatible with the backend API
249 BackendVersion laterMinorBackendVersion{ 2, 5 };
250 BOOST_TEST(!(laterMinorBackendVersion == backendApiVersion));
251 BOOST_TEST(!(laterMinorBackendVersion <= backendApiVersion));
252 BOOST_TEST(TestDynamicBackendUtils::IsBackendCompatibleTest(backendApiVersion, laterMinorBackendVersion) == false);
254 // Backend versions with the same major revision but earlier minor revision than
255 // the backend API version are compatible with the backend API
256 BackendVersion earlierMinorBackendVersion{ 2, 3 };
257 BOOST_TEST(!(earlierMinorBackendVersion == backendApiVersion));
258 BOOST_TEST(earlierMinorBackendVersion <= backendApiVersion);
259 BOOST_TEST(TestDynamicBackendUtils::IsBackendCompatibleTest(backendApiVersion, earlierMinorBackendVersion) == true);
262 void CreateValidDynamicBackendObjectTestImpl()
264 // Valid shared object handle
265 // Correct name mangling
267 // Correct backend implementation
269 using namespace armnn;
271 std::string testSubDirectory = GetTestSubDirectory(g_TestDynamicBackendSubDir);
272 std::string sharedObjectFilePath = GetTestFilePath(testSubDirectory, g_TestValidTestDynamicBackendFileName);
274 void* sharedObjectHandle = nullptr;
275 BOOST_CHECK_NO_THROW(sharedObjectHandle = DynamicBackendUtils::OpenHandle(sharedObjectFilePath));
276 BOOST_TEST((sharedObjectHandle != nullptr));
278 std::unique_ptr<DynamicBackend> dynamicBackend;
279 BOOST_CHECK_NO_THROW(dynamicBackend.reset(new DynamicBackend(sharedObjectHandle)));
280 BOOST_TEST((dynamicBackend != nullptr));
282 BackendId dynamicBackendId;
283 BOOST_CHECK_NO_THROW(dynamicBackendId = dynamicBackend->GetBackendId());
284 BOOST_TEST((dynamicBackendId == "ValidTestDynamicBackend"));
286 BackendVersion dynamicBackendVersion;
287 BOOST_CHECK_NO_THROW(dynamicBackendVersion = dynamicBackend->GetBackendVersion());
288 BOOST_TEST((dynamicBackendVersion == BackendVersion({ 1, 0 })));
290 IBackendInternalUniquePtr dynamicBackendInstance;
291 BOOST_CHECK_NO_THROW(dynamicBackendInstance = dynamicBackend->GetBackend());
292 BOOST_TEST((dynamicBackendInstance != nullptr));
294 BOOST_TEST((dynamicBackendInstance->GetId() == "ValidTestDynamicBackend"));
297 void CreateDynamicBackendObjectInvalidHandleTestImpl()
299 // Invalid (null) shared object handle
301 using namespace armnn;
303 void* sharedObjectHandle = nullptr;
304 std::unique_ptr<DynamicBackend> dynamicBackend;
305 BOOST_CHECK_THROW(dynamicBackend.reset(new DynamicBackend(sharedObjectHandle)), InvalidArgumentException);
306 BOOST_TEST((dynamicBackend == nullptr));
309 void CreateDynamicBackendObjectInvalidInterface1TestImpl()
311 // Valid shared object handle
312 // Wrong (not C-style) name mangling
314 using namespace armnn;
316 std::string testSubDirectory = GetTestSubDirectory(g_TestDynamicBackendSubDir);
317 std::string sharedObjectFilePath = GetTestFilePath(testSubDirectory, g_TestInvalidTestDynamicBackend1FileName);
319 void* sharedObjectHandle = nullptr;
320 BOOST_CHECK_NO_THROW(sharedObjectHandle = DynamicBackendUtils::OpenHandle(sharedObjectFilePath));
321 BOOST_TEST((sharedObjectHandle != nullptr));
323 std::unique_ptr<DynamicBackend> dynamicBackend;
324 BOOST_CHECK_THROW(dynamicBackend.reset(new DynamicBackend(sharedObjectHandle)), RuntimeException);
325 BOOST_TEST((dynamicBackend == nullptr));
328 void CreateDynamicBackendObjectInvalidInterface2TestImpl()
330 // Valid shared object handle
331 // Correct name mangling
332 // Wrong interface (missing GetBackendId())
334 using namespace armnn;
336 std::string testSubDirectory = GetTestSubDirectory(g_TestDynamicBackendSubDir);
337 std::string sharedObjectFilePath = GetTestFilePath(testSubDirectory, g_TestInvalidTestDynamicBackend2FileName);
339 void* sharedObjectHandle = nullptr;
340 BOOST_CHECK_NO_THROW(sharedObjectHandle = DynamicBackendUtils::OpenHandle(sharedObjectFilePath));
341 BOOST_TEST((sharedObjectHandle != nullptr));
343 std::unique_ptr<DynamicBackend> dynamicBackend;
344 BOOST_CHECK_THROW(dynamicBackend.reset(new DynamicBackend(sharedObjectHandle)), RuntimeException);
345 BOOST_TEST((dynamicBackend == nullptr));
348 void CreateDynamicBackendObjectInvalidInterface3TestImpl()
350 // Valid shared object handle
351 // Correct name mangling
352 // Wrong interface (missing GetVersion())
354 using namespace armnn;
356 std::string testSubDirectory = GetTestSubDirectory(g_TestDynamicBackendSubDir);
357 std::string sharedObjectFilePath = GetTestFilePath(testSubDirectory, g_TestInvalidTestDynamicBackend3FileName);
359 void* sharedObjectHandle = nullptr;
360 BOOST_CHECK_NO_THROW(sharedObjectHandle = DynamicBackendUtils::OpenHandle(sharedObjectFilePath));
361 BOOST_TEST((sharedObjectHandle != nullptr));
363 std::unique_ptr<DynamicBackend> dynamicBackend;
364 BOOST_CHECK_THROW(dynamicBackend.reset(new DynamicBackend(sharedObjectHandle)), RuntimeException);
365 BOOST_TEST((dynamicBackend == nullptr));
368 void CreateDynamicBackendObjectInvalidInterface4TestImpl()
370 // Valid shared object handle
371 // Correct name mangling
372 // Wrong interface (missing BackendFactory())
374 using namespace armnn;
376 std::string testSubDirectory = GetTestSubDirectory(g_TestDynamicBackendSubDir);
377 std::string sharedObjectFilePath = GetTestFilePath(testSubDirectory, g_TestInvalidTestDynamicBackend4FileName);
379 void* sharedObjectHandle = nullptr;
380 BOOST_CHECK_NO_THROW(sharedObjectHandle = DynamicBackendUtils::OpenHandle(sharedObjectFilePath));
381 BOOST_TEST((sharedObjectHandle != nullptr));
383 std::unique_ptr<DynamicBackend> dynamicBackend;
384 BOOST_CHECK_THROW(dynamicBackend.reset(new DynamicBackend(sharedObjectHandle)), RuntimeException);
385 BOOST_TEST((dynamicBackend == nullptr));
388 void CreateDynamicBackendObjectInvalidInterface5TestImpl()
390 // Valid shared object handle
391 // Correct name mangling
393 // Invalid (null) backend id returned by GetBackendId()
395 using namespace armnn;
397 std::string testSubDirectory = GetTestSubDirectory(g_TestDynamicBackendSubDir);
398 std::string sharedObjectFilePath = GetTestFilePath(testSubDirectory, g_TestInvalidTestDynamicBackend5FileName);
400 void* sharedObjectHandle = nullptr;
401 BOOST_CHECK_NO_THROW(sharedObjectHandle = DynamicBackendUtils::OpenHandle(sharedObjectFilePath));
402 BOOST_TEST((sharedObjectHandle != nullptr));
404 std::unique_ptr<DynamicBackend> dynamicBackend;
405 BOOST_CHECK_THROW(dynamicBackend.reset(new DynamicBackend(sharedObjectHandle)), RuntimeException);
406 BOOST_TEST((dynamicBackend == nullptr));
409 void CreateDynamicBackendObjectInvalidInterface6TestImpl()
411 // Valid shared object handle
412 // Correct name mangling
414 // Invalid (null) backend instance returned by BackendFactory()
416 using namespace armnn;
418 std::string testSubDirectory = GetTestSubDirectory(g_TestDynamicBackendSubDir);
419 std::string sharedObjectFilePath = GetTestFilePath(testSubDirectory, g_TestInvalidTestDynamicBackend6FileName);
421 void* sharedObjectHandle = nullptr;
422 BOOST_CHECK_NO_THROW(sharedObjectHandle = DynamicBackendUtils::OpenHandle(sharedObjectFilePath));
423 BOOST_TEST((sharedObjectHandle != nullptr));
425 std::unique_ptr<DynamicBackend> dynamicBackend;
426 BOOST_CHECK_NO_THROW(dynamicBackend.reset(new DynamicBackend(sharedObjectHandle)));
427 BOOST_TEST((dynamicBackend != nullptr));
429 BackendId dynamicBackendId;
430 BOOST_CHECK_NO_THROW(dynamicBackendId = dynamicBackend->GetBackendId());
431 BOOST_TEST((dynamicBackendId == "InvalidTestDynamicBackend"));
433 BackendVersion dynamicBackendVersion;
434 BOOST_CHECK_NO_THROW(dynamicBackendVersion = dynamicBackend->GetBackendVersion());
435 BOOST_TEST((dynamicBackendVersion == BackendVersion({ 1, 0 })));
437 IBackendInternalUniquePtr dynamicBackendInstance;
438 BOOST_CHECK_THROW(dynamicBackendInstance = dynamicBackend->GetBackend(), RuntimeException);
439 BOOST_TEST((dynamicBackendInstance == nullptr));
442 void CreateDynamicBackendObjectInvalidInterface7TestImpl()
444 // Valid shared object handle
445 // Correct name mangling
447 // Invalid (incompatible backend API version) backend instance returned by BackendFactory()
449 using namespace armnn;
451 std::string testSubDirectory = GetTestSubDirectory(g_TestDynamicBackendSubDir);
452 std::string sharedObjectFilePath = GetTestFilePath(testSubDirectory, g_TestInvalidTestDynamicBackend7FileName);
454 void* sharedObjectHandle = nullptr;
455 BOOST_CHECK_NO_THROW(sharedObjectHandle = DynamicBackendUtils::OpenHandle(sharedObjectFilePath));
456 BOOST_TEST((sharedObjectHandle != nullptr));
458 std::unique_ptr<DynamicBackend> dynamicBackend;
459 BOOST_CHECK_THROW(dynamicBackend.reset(new DynamicBackend(sharedObjectHandle)), RuntimeException);
460 BOOST_TEST((dynamicBackend == nullptr));
463 void GetBackendPathsTestImpl()
465 using namespace armnn;
466 using namespace boost::filesystem;
468 // The test covers four directories:
469 // <unit test path>/src/backends/backendsCommon/test/
470 // ├─ backendsTestPath1/ -> existing, contains files
471 // ├─ backendsTestPath2/ -> existing, contains files
472 // ├─ backendsTestPath3/ -> existing, but empty
473 // └─ backendsTestPath4/ -> not existing
475 std::string subDir1 = GetTestSubDirectory(g_TestDynamicBackendsFileParsingSubDir1);
476 std::string subDir2 = GetTestSubDirectory(g_TestDynamicBackendsFileParsingSubDir2);
477 std::string subDir3 = GetTestSubDirectory(g_TestDynamicBackendsFileParsingSubDir3);
478 std::string subDir4 = GetTestSubDirectory(g_TestDynamicBackendsFileParsingSubDir4);
480 BOOST_CHECK(exists(subDir1));
481 BOOST_CHECK(exists(subDir2));
482 BOOST_CHECK(exists(subDir3));
483 BOOST_CHECK(!exists(subDir4));
485 class TestDynamicBackendUtils : public DynamicBackendUtils
488 static std::vector<std::string> GetBackendPathsImplTest(const std::string& path)
490 return GetBackendPathsImpl(path);
495 BOOST_TEST(TestDynamicBackendUtils::GetBackendPathsImplTest("").empty());
498 std::string malformedDir(subDir1 + "/" + subDir1);
499 BOOST_TEST(TestDynamicBackendUtils::GetBackendPathsImplTest(malformedDir).size()==0);
502 std::vector<std::string> DynamicBackendPaths2 = TestDynamicBackendUtils::GetBackendPathsImplTest(subDir1);
503 BOOST_TEST(DynamicBackendPaths2.size() == 1);
504 BOOST_TEST(DynamicBackendPaths2[0] == subDir1);
506 // Multiple equal and valid paths
507 std::string multipleEqualDirs(subDir1 + ":" + subDir1);
508 std::vector<std::string> DynamicBackendPaths3 = TestDynamicBackendUtils::GetBackendPathsImplTest(multipleEqualDirs);
509 BOOST_TEST(DynamicBackendPaths3.size() == 1);
510 BOOST_TEST(DynamicBackendPaths3[0] == subDir1);
512 // Multiple empty paths
513 BOOST_TEST(TestDynamicBackendUtils::GetBackendPathsImplTest(":::").empty());
515 // Multiple valid paths
516 std::string multipleValidPaths(subDir1 + ":" + subDir2 + ":" + subDir3);
517 std::vector<std::string> DynamicBackendPaths5 =
518 TestDynamicBackendUtils::GetBackendPathsImplTest(multipleValidPaths);
519 BOOST_TEST(DynamicBackendPaths5.size() == 3);
520 BOOST_TEST(DynamicBackendPaths5[0] == subDir1);
521 BOOST_TEST(DynamicBackendPaths5[1] == subDir2);
522 BOOST_TEST(DynamicBackendPaths5[2] == subDir3);
524 // Valid among empty paths
525 std::string validAmongEmptyDirs("::" + subDir1 + ":");
526 std::vector<std::string> DynamicBackendPaths6 =
527 TestDynamicBackendUtils::GetBackendPathsImplTest(validAmongEmptyDirs);
528 BOOST_TEST(DynamicBackendPaths6.size() == 1);
529 BOOST_TEST(DynamicBackendPaths6[0] == subDir1);
531 // Invalid among empty paths
532 std::string invalidAmongEmptyDirs(":" + subDir4 + "::");
533 BOOST_TEST(TestDynamicBackendUtils::GetBackendPathsImplTest(invalidAmongEmptyDirs).empty());
535 // Valid, invalid and empty paths
536 std::string validInvalidEmptyDirs(subDir1 + ":" + subDir4 + ":");
537 std::vector<std::string> DynamicBackendPaths8 =
538 TestDynamicBackendUtils::GetBackendPathsImplTest(validInvalidEmptyDirs);
539 BOOST_TEST(DynamicBackendPaths8.size() == 1);
540 BOOST_TEST(DynamicBackendPaths8[0] == subDir1);
542 // Mix of duplicates of valid, invalid and empty paths
543 std::string duplicateValidInvalidEmptyDirs(validInvalidEmptyDirs + ":" + validInvalidEmptyDirs + ":" +
544 subDir2 + ":" + subDir2);
545 std::vector<std::string> DynamicBackendPaths9 =
546 TestDynamicBackendUtils::GetBackendPathsImplTest(duplicateValidInvalidEmptyDirs);
547 BOOST_TEST(DynamicBackendPaths9.size() == 2);
548 BOOST_TEST(DynamicBackendPaths9[0] == subDir1);
549 BOOST_TEST(DynamicBackendPaths9[1] == subDir2);
552 void GetBackendPathsOverrideTestImpl()
554 using namespace armnn;
555 using namespace boost::filesystem;
557 std::string subDir1 = GetTestSubDirectory(g_TestDynamicBackendsFileParsingSubDir1);
558 std::string subDir4 = GetTestSubDirectory(g_TestDynamicBackendsFileParsingSubDir4);
560 BOOST_CHECK(exists(subDir1));
561 BOOST_CHECK(!exists(subDir4));
563 // Override with valid path
564 std::vector<std::string> validResult = DynamicBackendUtils::GetBackendPaths(subDir1);
565 BOOST_TEST(validResult.size() == 1);
566 BOOST_TEST(validResult[0] == subDir1);
568 // Override with invalid path
569 std::vector<std::string> invalidResult = DynamicBackendUtils::GetBackendPaths(subDir4);
570 BOOST_TEST(invalidResult.empty());
573 void GetSharedObjectsTestImpl()
575 using namespace armnn;
576 using namespace boost::filesystem;
579 // The test sub-directory backendsTestPath1/ contains the following test files:
581 // Arm_GpuAcc_backend.so -> valid (basic backend name)
582 // Arm_GpuAcc_backend.so.1 -> valid (single field version number)
583 // Arm_GpuAcc_backend.so.1.2 -> valid (multiple field version number)
584 // Arm_GpuAcc_backend.so.1.2.3 -> valid (multiple field version number)
585 // Arm_GpuAcc_backend.so.10.1.27 -> valid (Multiple digit version)
586 // Arm_GpuAcc_backend.so.10.1.33. -> not valid (dot not followed by version number)
587 // Arm_GpuAcc_backend.so.3.4..5 -> not valid (dot not followed by version number)
588 // Arm_GpuAcc_backend.so.1,1.1 -> not valid (comma instead of dot in the version)
590 // Arm123_GpuAcc_backend.so -> valid (digits in vendor name are allowed)
591 // Arm_GpuAcc456_backend.so -> valid (digits in backend id are allowed)
592 // Arm%Co_GpuAcc_backend.so -> not valid (invalid character in vendor name)
593 // Arm_Gpu.Acc_backend.so -> not valid (invalid character in backend id)
595 // GpuAcc_backend.so -> not valid (missing vendor name)
596 // _GpuAcc_backend.so -> not valid (missing vendor name)
597 // Arm__backend.so -> not valid (missing backend id)
598 // Arm_GpuAcc.so -> not valid (missing "backend" at the end)
599 // __backend.so -> not valid (missing vendor name and backend id)
600 // __.so -> not valid (missing all fields)
602 // Arm_GpuAcc_backend -> not valid (missing at least ".so" at the end)
603 // Arm_GpuAcc_backend_v1.2.so -> not valid (extra version info at the end)
605 // The test sub-directory backendsTestPath1/ contains the following test files:
607 // Arm_CpuAcc_backend.so -> valid (basic backend name)
608 // Arm_CpuAcc_backend.so.1 -> Arm_CpuAcc_backend.so -> valid (symlink to valid backend file)
609 // Arm_CpuAcc_backend.so.1.2 -> Arm_CpuAcc_backend.so.1 -> valid (symlink to valid symlink)
610 // Arm_CpuAcc_backend.so.1.2.3 -> Arm_CpuAcc_backend.so.1.2 -> valid (symlink to valid symlink)
612 // Arm_no_backend.so -> nothing -> not valid (symlink resolves to non-existent file)
614 // Arm_GpuAcc_backend.so -> valid (but duplicated from backendsTestPath1/)
616 std::string testDynamicBackendsSubDir1 = GetTestSubDirectory(g_TestDynamicBackendsFileParsingSubDir1);
617 std::string testDynamicBackendsSubDir2 = GetTestSubDirectory(g_TestDynamicBackendsFileParsingSubDir2);
618 std::string testDynamicBackendsSubDir3 = GetTestSubDirectory(g_TestDynamicBackendsFileParsingSubDir3);
619 std::string testDynamicBackendsSubDir4 = GetTestSubDirectory(g_TestDynamicBackendsFileParsingSubDir4);
620 BOOST_CHECK(exists(testDynamicBackendsSubDir1));
621 BOOST_CHECK(exists(testDynamicBackendsSubDir2));
622 BOOST_CHECK(exists(testDynamicBackendsSubDir3));
623 BOOST_CHECK(!exists(testDynamicBackendsSubDir4));
625 std::vector<std::string> backendPaths
627 testDynamicBackendsSubDir1,
628 testDynamicBackendsSubDir2,
629 testDynamicBackendsSubDir3,
630 testDynamicBackendsSubDir4
632 std::vector<std::string> sharedObjects = DynamicBackendUtils::GetSharedObjects(backendPaths);
633 std::unordered_set<std::string> expectedSharedObjects
635 testDynamicBackendsSubDir1 + "Arm_GpuAcc_backend.so", // Basic backend name
636 testDynamicBackendsSubDir1 + "Arm_GpuAcc_backend.so.1", // Single field version number
637 testDynamicBackendsSubDir1 + "Arm_GpuAcc_backend.so.1.2", // Multiple field version number
638 testDynamicBackendsSubDir1 + "Arm_GpuAcc_backend.so.1.2.3", // Multiple field version number
639 testDynamicBackendsSubDir1 + "Arm_GpuAcc_backend.so.10.1.27", // Multiple digit version
640 testDynamicBackendsSubDir1 + "Arm123_GpuAcc_backend.so", // Digits in vendor name are allowed
641 testDynamicBackendsSubDir1 + "Arm_GpuAcc456_backend.so", // Digits in backend id are allowed
642 testDynamicBackendsSubDir2 + "Arm_CpuAcc_backend.so", // Duplicate symlinks removed
643 testDynamicBackendsSubDir2 + "Arm_GpuAcc_backend.so" // Duplicates on different paths are allowed
646 BOOST_TEST(sharedObjects.size() == expectedSharedObjects.size());
647 for (const std::string& sharedObject : sharedObjects)
649 auto it = expectedSharedObjects.find(sharedObject);
650 BOOST_TEST((it != expectedSharedObjects.end()));