From e7d449893b85a00a063836bd01dce4f925a24dd2 Mon Sep 17 00:00:00 2001 From: Matteo Martincigh Date: Mon, 5 Aug 2019 12:16:47 +0100 Subject: IVGCVSW-3541 Get the paths where to load the dynamic backends from * Adds GetBackendPaths and IsPathValid to DynamicBackendUtils * Adds related unit tests Change-Id: I94e377d92a88a4b5d48026f6ad5b4d5387d20c21 Signed-off-by: Jan Eilers Signed-off-by: Matteo Martincigh --- .../backendsCommon/DynamicBackendUtils.cpp | 92 +++++++++++++++++ .../backendsCommon/DynamicBackendUtils.hpp | 11 +- .../backendsCommon/test/DynamicBackendTests.cpp | 3 + .../backendsCommon/test/DynamicBackendTests.hpp | 115 +++++++++++++++++++++ 4 files changed, 220 insertions(+), 1 deletion(-) (limited to 'src/backends/backendsCommon') diff --git a/src/backends/backendsCommon/DynamicBackendUtils.cpp b/src/backends/backendsCommon/DynamicBackendUtils.cpp index 0ab02d7c98..ae36a24b30 100644 --- a/src/backends/backendsCommon/DynamicBackendUtils.cpp +++ b/src/backends/backendsCommon/DynamicBackendUtils.cpp @@ -5,6 +5,10 @@ #include "DynamicBackendUtils.hpp" +#include +#include +#include + namespace armnn { @@ -59,4 +63,92 @@ std::string DynamicBackendUtils::GetDlError() return std::string(errorMessage); } +std::vector DynamicBackendUtils::GetBackendPaths(const std::string& overrideBackendPath) +{ + // Check if a path where to dynamically load the backends from is given + if (!overrideBackendPath.empty()) + { + if (!IsPathValid(overrideBackendPath)) + { + BOOST_LOG_TRIVIAL(warning) << "WARNING: The given override path for dynamic backends \"" + << overrideBackendPath << "\" is not valid"; + + return {}; + } + + return std::vector{ overrideBackendPath }; + } + + // Expects a colon-separated list: DYNAMIC_BACKEND_PATHS="PATH_1:PATH_2:...:PATH_N" + const std::string backendPaths = DYNAMIC_BACKEND_PATHS; + + return GetBackendPathsImpl(backendPaths); +} + +std::vector DynamicBackendUtils::GetBackendPathsImpl(const std::string& backendPaths) +{ + std::unordered_set uniqueBackendPaths; + std::vector tempBackendPaths; + std::vector validBackendPaths; + + // Split the given list of paths + boost::split(tempBackendPaths, backendPaths, boost::is_any_of(":")); + + for (const std::string& path : tempBackendPaths) + { + // Check whether the path is valid + if (!IsPathValid(path)) + { + continue; + } + + // Check whether the path is a duplicate + auto it = uniqueBackendPaths.find(path); + if (it != uniqueBackendPaths.end()) + { + // The path is a duplicate + continue; + } + + // Add the path to the set of unique paths + uniqueBackendPaths.insert(path); + + // Add the path to the list of valid paths + validBackendPaths.push_back(path); + } + + return validBackendPaths; +} + +bool DynamicBackendUtils::IsPathValid(const std::string& path) +{ + if (path.empty()) + { + BOOST_LOG_TRIVIAL(warning) << "WARNING: The given backend path is empty"; + return false; + } + + boost::filesystem::path boostPath(path); + + if (!boost::filesystem::exists(boostPath)) + { + BOOST_LOG_TRIVIAL(warning) << "WARNING: The given backend path \"" << path << "\" does not exist"; + return false; + } + + if (!boost::filesystem::is_directory(boostPath)) + { + BOOST_LOG_TRIVIAL(warning) << "WARNING: The given backend path \"" << path << "\" is not a directory"; + return false; + } + + if (!boostPath.is_absolute()) + { + BOOST_LOG_TRIVIAL(warning) << "WARNING: The given backend path \"" << path << "\" is not absolute"; + return false; + } + + return true; +} + } // namespace armnn diff --git a/src/backends/backendsCommon/DynamicBackendUtils.hpp b/src/backends/backendsCommon/DynamicBackendUtils.hpp index 0a2d428fd3..f0bfd3b220 100644 --- a/src/backends/backendsCommon/DynamicBackendUtils.hpp +++ b/src/backends/backendsCommon/DynamicBackendUtils.hpp @@ -11,9 +11,14 @@ #include #include +#include #include +#if !defined(DYNAMIC_BACKEND_PATHS) +#define DYNAMIC_BACKEND_PATHS "" +#endif + namespace armnn { @@ -28,9 +33,13 @@ public: static bool IsBackendCompatible(const BackendVersion& backendVersion); + static std::vector GetBackendPaths(const std::string& overrideBackendPath = ""); + static bool IsPathValid(const std::string& path); + protected: - /// Protected for testing purposes + /// Protected methods for testing purposes static bool IsBackendCompatibleImpl(const BackendVersion& backendApiVersion, const BackendVersion& backendVersion); + static std::vector GetBackendPathsImpl(const std::string& backendPaths); private: static std::string GetDlError(); diff --git a/src/backends/backendsCommon/test/DynamicBackendTests.cpp b/src/backends/backendsCommon/test/DynamicBackendTests.cpp index 10a650af7e..16d07c1a47 100644 --- a/src/backends/backendsCommon/test/DynamicBackendTests.cpp +++ b/src/backends/backendsCommon/test/DynamicBackendTests.cpp @@ -40,4 +40,7 @@ ARMNN_SIMPLE_TEST_CASE(CreateDynamicBackendObjectInvalidInterface6, ARMNN_SIMPLE_TEST_CASE(CreateDynamicBackendObjectInvalidInterface7, CreateDynamicBackendObjectInvalidInterface7TestImpl); +ARMNN_SIMPLE_TEST_CASE(GetBackendPaths, GetBackendPathsTestImpl) +ARMNN_SIMPLE_TEST_CASE(GetBackendPathsOverride, GetBackendPathsOverrideTestImpl) + BOOST_AUTO_TEST_SUITE_END() diff --git a/src/backends/backendsCommon/test/DynamicBackendTests.hpp b/src/backends/backendsCommon/test/DynamicBackendTests.hpp index 55f90d48eb..32778118c3 100644 --- a/src/backends/backendsCommon/test/DynamicBackendTests.hpp +++ b/src/backends/backendsCommon/test/DynamicBackendTests.hpp @@ -34,6 +34,11 @@ static std::string g_TestInvalidTestDynamicBackend5FileName = "libInvalidTestDyn static std::string g_TestInvalidTestDynamicBackend6FileName = "libInvalidTestDynamicBackend6.so"; static std::string g_TestInvalidTestDynamicBackend7FileName = "libInvalidTestDynamicBackend7.so"; +static std::string g_TestDynamicBackendsFileParsingSubDir1 = "backendsTestPath1/"; +static std::string g_TestDynamicBackendsFileParsingSubDir2 = "backendsTestPath2/"; +static std::string g_TestDynamicBackendsFileParsingSubDir3 = "backendsTestPath3/"; +static std::string g_TestDynamicBackendsFileParsingSubDir4 = "backendsTestPath4/"; + std::string GetTestDirectoryBasePath() { using namespace boost::filesystem; @@ -455,3 +460,113 @@ void CreateDynamicBackendObjectInvalidInterface7TestImpl() BOOST_CHECK_THROW(dynamicBackend.reset(new DynamicBackend(sharedObjectHandle)), RuntimeException); BOOST_TEST((dynamicBackend == nullptr)); } + +void GetBackendPathsTestImpl() +{ + using namespace armnn; + using namespace boost::filesystem; + + // The test covers four directories: + // /src/backends/backendsCommon/test/ + // ├─ backendsTestPath1/ -> existing, contains files + // ├─ backendsTestPath2/ -> existing, contains files + // ├─ backendsTestPath3/ -> existing, but empty + // └─ backendsTestPath4/ -> not existing + + std::string subDir1 = GetTestSubDirectory(g_TestDynamicBackendsFileParsingSubDir1); + std::string subDir2 = GetTestSubDirectory(g_TestDynamicBackendsFileParsingSubDir2); + std::string subDir3 = GetTestSubDirectory(g_TestDynamicBackendsFileParsingSubDir3); + std::string subDir4 = GetTestSubDirectory(g_TestDynamicBackendsFileParsingSubDir4); + + BOOST_CHECK(exists(subDir1)); + BOOST_CHECK(exists(subDir2)); + BOOST_CHECK(exists(subDir3)); + BOOST_CHECK(!exists(subDir4)); + + class TestDynamicBackendUtils : public DynamicBackendUtils + { + public: + static std::vector GetBackendPathsImplTest(const std::string& path) + { + return GetBackendPathsImpl(path); + } + }; + + // No path + BOOST_TEST(TestDynamicBackendUtils::GetBackendPathsImplTest("").empty()); + + // Malformed path + std::string malformedDir(subDir1 + "/" + subDir1); + BOOST_TEST(TestDynamicBackendUtils::GetBackendPathsImplTest(malformedDir).size()==0); + + // Single valid path + std::vector DynamicBackendPaths2 = TestDynamicBackendUtils::GetBackendPathsImplTest(subDir1); + BOOST_TEST(DynamicBackendPaths2.size() == 1); + BOOST_TEST(DynamicBackendPaths2[0] == subDir1); + + // Multiple equal and valid paths + std::string multipleEqualDirs(subDir1 + ":" + subDir1); + std::vector DynamicBackendPaths3 = TestDynamicBackendUtils::GetBackendPathsImplTest(multipleEqualDirs); + BOOST_TEST(DynamicBackendPaths3.size() == 1); + BOOST_TEST(DynamicBackendPaths3[0] == subDir1); + + // Multiple empty paths + BOOST_TEST(TestDynamicBackendUtils::GetBackendPathsImplTest(":::").empty()); + + // Multiple valid paths + std::string multipleValidPaths(subDir1 + ":" + subDir2 + ":" + subDir3); + std::vector DynamicBackendPaths5 = + TestDynamicBackendUtils::GetBackendPathsImplTest(multipleValidPaths); + BOOST_TEST(DynamicBackendPaths5.size() == 3); + BOOST_TEST(DynamicBackendPaths5[0] == subDir1); + BOOST_TEST(DynamicBackendPaths5[1] == subDir2); + BOOST_TEST(DynamicBackendPaths5[2] == subDir3); + + // Valid among empty paths + std::string validAmongEmptyDirs("::" + subDir1 + ":"); + std::vector DynamicBackendPaths6 = + TestDynamicBackendUtils::GetBackendPathsImplTest(validAmongEmptyDirs); + BOOST_TEST(DynamicBackendPaths6.size() == 1); + BOOST_TEST(DynamicBackendPaths6[0] == subDir1); + + // Invalid among empty paths + std::string invalidAmongEmptyDirs(":" + subDir4 + "::"); + BOOST_TEST(TestDynamicBackendUtils::GetBackendPathsImplTest(invalidAmongEmptyDirs).empty()); + + // Valid, invalid and empty paths + std::string validInvalidEmptyDirs(subDir1 + ":" + subDir4 + ":"); + std::vector DynamicBackendPaths8 = + TestDynamicBackendUtils::GetBackendPathsImplTest(validInvalidEmptyDirs); + BOOST_TEST(DynamicBackendPaths8.size() == 1); + BOOST_TEST(DynamicBackendPaths8[0] == subDir1); + + // Mix of duplicates of valid, invalid and empty paths + std::string duplicateValidInvalidEmptyDirs(validInvalidEmptyDirs + ":" + validInvalidEmptyDirs + ":" + + subDir2 + ":" + subDir2); + std::vector DynamicBackendPaths9 = + TestDynamicBackendUtils::GetBackendPathsImplTest(duplicateValidInvalidEmptyDirs); + BOOST_TEST(DynamicBackendPaths9.size() == 2); + BOOST_TEST(DynamicBackendPaths9[0] == subDir1); + BOOST_TEST(DynamicBackendPaths9[1] == subDir2); +} + +void GetBackendPathsOverrideTestImpl() +{ + using namespace armnn; + using namespace boost::filesystem; + + std::string subDir1 = GetTestSubDirectory(g_TestDynamicBackendsFileParsingSubDir1); + std::string subDir4 = GetTestSubDirectory(g_TestDynamicBackendsFileParsingSubDir4); + + BOOST_CHECK(exists(subDir1)); + BOOST_CHECK(!exists(subDir4)); + + // Override with valid path + std::vector validResult = DynamicBackendUtils::GetBackendPaths(subDir1); + BOOST_TEST(validResult.size() == 1); + BOOST_TEST(validResult[0] == subDir1); + + // Override with invalid path + std::vector invalidResult = DynamicBackendUtils::GetBackendPaths(subDir4); + BOOST_TEST(invalidResult.empty()); +} -- cgit v1.2.1