aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJan Eilers <jan.eilers@arm.com>2019-07-25 17:08:37 +0100
committerMatteo Martincigh <matteo.martincigh@arm.com>2019-08-05 16:32:25 +0000
commit4a539fcde5008b5e55d565ab9615eab2970360ae (patch)
tree3bfe3616453246acbafac38e7f7bad54c2a25b6c
parente7d449893b85a00a063836bd01dce4f925a24dd2 (diff)
downloadarmnn-4a539fcde5008b5e55d565ab9615eab2970360ae.tar.gz
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 <matteo.martincigh@arm.com> Change-Id: Ibfc0bad740b72696714d343eb32a593c2ec1f8c6
-rw-r--r--src/backends/backendsCommon/DynamicBackendUtils.cpp86
-rw-r--r--src/backends/backendsCommon/DynamicBackendUtils.hpp1
-rw-r--r--src/backends/backendsCommon/test/DynamicBackendTests.cpp2
-rw-r--r--src/backends/backendsCommon/test/DynamicBackendTests.hpp82
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 <boost/filesystem/operations.hpp>
+#include <boost/filesystem.hpp>
#include <boost/algorithm/string.hpp>
#include <boost/log/trivial.hpp>
+#include <regex>
+
namespace armnn
{
@@ -151,4 +153,86 @@ bool DynamicBackendUtils::IsPathValid(const std::string& path)
return true;
}
+std::vector<std::string> DynamicBackendUtils::GetSharedObjects(const std::vector<std::string>& backendPaths)
+{
+ std::unordered_set<std::string> uniqueSharedObjects;
+ std::vector<std::string> 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: <vendor>_<name>_backend.so[<version>]
+ // 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<std::string> GetBackendPaths(const std::string& overrideBackendPath = "");
static bool IsPathValid(const std::string& path);
+ static std::vector<std::string> GetSharedObjects(const std::vector<std::string>& 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 <string>
#include <memory>
-
#include <string>
#include <boost/test/unit_test.hpp>
@@ -570,3 +569,84 @@ void GetBackendPathsOverrideTestImpl()
std::vector<std::string> 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<std::string> backendPaths
+ {
+ testDynamicBackendsSubDir1,
+ testDynamicBackendsSubDir2,
+ testDynamicBackendsSubDir3,
+ testDynamicBackendsSubDir4
+ };
+ std::vector<std::string> sharedObjects = DynamicBackendUtils::GetSharedObjects(backendPaths);
+ std::unordered_set<std::string> 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()));
+ }
+}