From 4a539fcde5008b5e55d565ab9615eab2970360ae Mon Sep 17 00:00:00 2001 From: Jan Eilers Date: Thu, 25 Jul 2019 17:08:37 +0100 Subject: IVGCVSW-3599 Create the GetSharedObjects method in DynamicBackendUtils * Added GetSharedObjects to DynamicBackendUtils * Goes through the given paths and returns a list of files that match the naming scheme for dynamic backends * Added unit test * Update the cmake file to generate the test files/symlinks Signed-off-by: Matteo Martincigh Change-Id: Ibfc0bad740b72696714d343eb32a593c2ec1f8c6 --- .../backendsCommon/DynamicBackendUtils.cpp | 86 +++++++++++++++++++++- .../backendsCommon/DynamicBackendUtils.hpp | 1 + .../backendsCommon/test/DynamicBackendTests.cpp | 2 + .../backendsCommon/test/DynamicBackendTests.hpp | 82 ++++++++++++++++++++- 4 files changed, 169 insertions(+), 2 deletions(-) diff --git a/src/backends/backendsCommon/DynamicBackendUtils.cpp b/src/backends/backendsCommon/DynamicBackendUtils.cpp index ae36a24b30..1dea802016 100644 --- a/src/backends/backendsCommon/DynamicBackendUtils.cpp +++ b/src/backends/backendsCommon/DynamicBackendUtils.cpp @@ -5,10 +5,12 @@ #include "DynamicBackendUtils.hpp" -#include +#include #include #include +#include + namespace armnn { @@ -151,4 +153,86 @@ bool DynamicBackendUtils::IsPathValid(const std::string& path) return true; } +std::vector DynamicBackendUtils::GetSharedObjects(const std::vector& backendPaths) +{ + std::unordered_set uniqueSharedObjects; + std::vector sharedObjects; + + for (const std::string& backendPath : backendPaths) + { + using namespace boost::filesystem; + + // Check if the path is valid. In case of error, IsValidPath will log an error message + if (!IsPathValid(backendPath)) + { + continue; + } + + // Go through all the files in the current backend path + for (directory_iterator fileIterator(backendPath); fileIterator != directory_iterator(); fileIterator++) + { + path filePath = *fileIterator; + std::string filename = filePath.filename().string(); + + if (filename.empty()) + { + // Empty filename + continue; + } + + path canonicalPath; + try + { + // Get the canonical path for the current file, it will throw if for example the file is a + // symlink that cannot be resolved + canonicalPath = canonical(filePath); + } + catch (const filesystem_error& e) + { + BOOST_LOG_TRIVIAL(warning) << "GetSharedObjects warning: " << e.what(); + } + if (canonicalPath.empty()) + { + // No such file or perhaps a symlink that couldn't be resolved + continue; + } + + // Check if the current filename matches the expected naming convention + // The expected format is: __backend.so[] + // e.g. "Arm_GpuAcc_backend.so" or "Arm_GpuAcc_backend.so.1.2" + const std::regex dynamicBackendRegex("^[a-zA-Z0-9]+_[a-zA-Z0-9]+_backend.so(\\.[0-9]+)*$"); + + bool filenameMatch = false; + try + { + // Match the filename to the expected naming scheme + filenameMatch = std::regex_match(filename, dynamicBackendRegex); + } + catch (const std::exception& e) + { + BOOST_LOG_TRIVIAL(warning) << "GetSharedObjects warning: " << e.what(); + } + if (!filenameMatch) + { + // Filename does not match the expected naming scheme (or an error has occurred) + continue; + } + + // Append the valid canonical path to the output list only if it's not a duplicate + std::string validCanonicalPath = canonicalPath.string(); + auto it = uniqueSharedObjects.find(validCanonicalPath); + if (it == uniqueSharedObjects.end()) + { + // Not a duplicate, append the canonical path to the output list + sharedObjects.push_back(validCanonicalPath); + + // Add the canonical path to the collection of unique shared objects + uniqueSharedObjects.insert(validCanonicalPath); + } + } + } + + return sharedObjects; +} + } // namespace armnn diff --git a/src/backends/backendsCommon/DynamicBackendUtils.hpp b/src/backends/backendsCommon/DynamicBackendUtils.hpp index f0bfd3b220..b327a9ea60 100644 --- a/src/backends/backendsCommon/DynamicBackendUtils.hpp +++ b/src/backends/backendsCommon/DynamicBackendUtils.hpp @@ -35,6 +35,7 @@ public: static std::vector GetBackendPaths(const std::string& overrideBackendPath = ""); static bool IsPathValid(const std::string& path); + static std::vector GetSharedObjects(const std::vector& backendPaths); protected: /// Protected methods for testing purposes diff --git a/src/backends/backendsCommon/test/DynamicBackendTests.cpp b/src/backends/backendsCommon/test/DynamicBackendTests.cpp index 16d07c1a47..a467b0e645 100644 --- a/src/backends/backendsCommon/test/DynamicBackendTests.cpp +++ b/src/backends/backendsCommon/test/DynamicBackendTests.cpp @@ -43,4 +43,6 @@ ARMNN_SIMPLE_TEST_CASE(CreateDynamicBackendObjectInvalidInterface7, ARMNN_SIMPLE_TEST_CASE(GetBackendPaths, GetBackendPathsTestImpl) ARMNN_SIMPLE_TEST_CASE(GetBackendPathsOverride, GetBackendPathsOverrideTestImpl) +ARMNN_SIMPLE_TEST_CASE(GetSharedObjects, GetSharedObjectsTestImpl); + BOOST_AUTO_TEST_SUITE_END() diff --git a/src/backends/backendsCommon/test/DynamicBackendTests.hpp b/src/backends/backendsCommon/test/DynamicBackendTests.hpp index 32778118c3..b4af705fcd 100644 --- a/src/backends/backendsCommon/test/DynamicBackendTests.hpp +++ b/src/backends/backendsCommon/test/DynamicBackendTests.hpp @@ -10,7 +10,6 @@ #include #include - #include #include @@ -570,3 +569,84 @@ void GetBackendPathsOverrideTestImpl() std::vector invalidResult = DynamicBackendUtils::GetBackendPaths(subDir4); BOOST_TEST(invalidResult.empty()); } + +void GetSharedObjectsTestImpl() +{ + using namespace armnn; + using namespace boost::filesystem; + + // + // The test sub-directory backendsTestPath1/ contains the following test files: + // + // Arm_GpuAcc_backend.so -> valid (basic backend name) + // Arm_GpuAcc_backend.so.1 -> valid (single field version number) + // Arm_GpuAcc_backend.so.1.2 -> valid (multiple field version number) + // Arm_GpuAcc_backend.so.1.2.3 -> valid (multiple field version number) + // Arm_GpuAcc_backend.so.10.1.27 -> valid (Multiple digit version) + // Arm_GpuAcc_backend.so.10.1.33. -> not valid (dot not followed by version number) + // Arm_GpuAcc_backend.so.3.4..5 -> not valid (dot not followed by version number) + // Arm_GpuAcc_backend.so.1,1.1 -> not valid (comma instead of dot in the version) + // + // Arm123_GpuAcc_backend.so -> valid (digits in vendor name are allowed) + // Arm_GpuAcc456_backend.so -> valid (digits in backend id are allowed) + // Arm%Co_GpuAcc_backend.so -> not valid (invalid character in vendor name) + // Arm_Gpu.Acc_backend.so -> not valid (invalid character in backend id) + // + // GpuAcc_backend.so -> not valid (missing vendor name) + // _GpuAcc_backend.so -> not valid (missing vendor name) + // Arm__backend.so -> not valid (missing backend id) + // Arm_GpuAcc.so -> not valid (missing "backend" at the end) + // __backend.so -> not valid (missing vendor name and backend id) + // __.so -> not valid (missing all fields) + // + // Arm_GpuAcc_backend -> not valid (missing at least ".so" at the end) + // Arm_GpuAcc_backend_v1.2.so -> not valid (extra version info at the end) + // + // The test sub-directory backendsTestPath1/ contains the following test files: + // + // Arm_CpuAcc_backend.so -> valid (basic backend name) + // Arm_CpuAcc_backend.so.1 -> Arm_CpuAcc_backend.so -> valid (symlink to valid backend file) + // Arm_CpuAcc_backend.so.1.2 -> Arm_CpuAcc_backend.so.1 -> valid (symlink to valid symlink) + // Arm_CpuAcc_backend.so.1.2.3 -> Arm_CpuAcc_backend.so.1.2 -> valid (symlink to valid symlink) + // + // Arm_no_backend.so -> nothing -> not valid (symlink resolves to non-existent file) + // + // Arm_GpuAcc_backend.so -> valid (but duplicated from backendsTestPath1/) + + std::string testDynamicBackendsSubDir1 = GetTestSubDirectory(g_TestDynamicBackendsFileParsingSubDir1); + std::string testDynamicBackendsSubDir2 = GetTestSubDirectory(g_TestDynamicBackendsFileParsingSubDir2); + std::string testDynamicBackendsSubDir3 = GetTestSubDirectory(g_TestDynamicBackendsFileParsingSubDir3); + std::string testDynamicBackendsSubDir4 = GetTestSubDirectory(g_TestDynamicBackendsFileParsingSubDir4); + BOOST_CHECK(exists(testDynamicBackendsSubDir1)); + BOOST_CHECK(exists(testDynamicBackendsSubDir2)); + BOOST_CHECK(exists(testDynamicBackendsSubDir3)); + BOOST_CHECK(!exists(testDynamicBackendsSubDir4)); + + std::vector backendPaths + { + testDynamicBackendsSubDir1, + testDynamicBackendsSubDir2, + testDynamicBackendsSubDir3, + testDynamicBackendsSubDir4 + }; + std::vector sharedObjects = DynamicBackendUtils::GetSharedObjects(backendPaths); + std::unordered_set expectedSharedObjects + { + testDynamicBackendsSubDir1 + "Arm_GpuAcc_backend.so", // Basic backend name + testDynamicBackendsSubDir1 + "Arm_GpuAcc_backend.so.1", // Single field version number + testDynamicBackendsSubDir1 + "Arm_GpuAcc_backend.so.1.2", // Multiple field version number + testDynamicBackendsSubDir1 + "Arm_GpuAcc_backend.so.1.2.3", // Multiple field version number + testDynamicBackendsSubDir1 + "Arm_GpuAcc_backend.so.10.1.27", // Multiple digit version + testDynamicBackendsSubDir1 + "Arm123_GpuAcc_backend.so", // Digits in vendor name are allowed + testDynamicBackendsSubDir1 + "Arm_GpuAcc456_backend.so", // Digits in backend id are allowed + testDynamicBackendsSubDir2 + "Arm_CpuAcc_backend.so", // Duplicate symlinks removed + testDynamicBackendsSubDir2 + "Arm_GpuAcc_backend.so" // Duplicates on different paths are allowed + }; + + BOOST_TEST(sharedObjects.size() == expectedSharedObjects.size()); + for (const std::string& sharedObject : sharedObjects) + { + auto it = expectedSharedObjects.find(sharedObject); + BOOST_TEST((it != expectedSharedObjects.end())); + } +} -- cgit v1.2.1