IVGCVSW-3596 Register the dynamic backends in the BackendRegistry

 * Added getter for the factory function in the DynamicBackend class
 * Added new RegisterDynamicBackends method in utils class
 * Added dynamic backend registration process in the Runtime class
 * Added new dummy dynamic backend objects for testing
 * Added unit tests for dynamic backend registration
 * Added convenience methods to BackendId

Change-Id: I01e147d1d6f01bf56747ad946f73f867af5770c4
Signed-off-by: Matteo Martincigh <matteo.martincigh@arm.com>
diff --git a/include/armnn/BackendId.hpp b/include/armnn/BackendId.hpp
index 7dd1460..59d4ac1 100644
--- a/include/armnn/BackendId.hpp
+++ b/include/armnn/BackendId.hpp
@@ -129,6 +129,9 @@
 
     const std::string& Get() const { return m_Id; }
 
+    bool IsEmpty() const { return m_Id.empty(); }
+    bool IsUndefined() const { return m_Id == GetComputeDeviceAsCString(Compute::Undefined); }
+
 private:
     std::string m_Id;
 };
diff --git a/src/armnn/Runtime.cpp b/src/armnn/Runtime.cpp
index 3505030..ddfa6b4 100644
--- a/src/armnn/Runtime.cpp
+++ b/src/armnn/Runtime.cpp
@@ -9,7 +9,6 @@
 #include <backendsCommon/BackendRegistry.hpp>
 #include <backendsCommon/IBackendContext.hpp>
 #include <backendsCommon/DynamicBackendUtils.hpp>
-#include <backendsCommon/DynamicBackend.hpp>
 
 #include <iostream>
 
@@ -253,7 +252,10 @@
     std::vector<std::string> sharedObjects = DynamicBackendUtils::GetSharedObjects(backendPaths);
 
     // Create a list of dynamic backends
-    DynamicBackendUtils::CreateDynamicBackends(sharedObjects);
+    m_DynamicBackends = DynamicBackendUtils::CreateDynamicBackends(sharedObjects);
+
+    // Register the dynamic backends in the backend registry
+    DynamicBackendUtils::RegisterDynamicBackends(m_DynamicBackends);
 }
 
 } // namespace armnn
diff --git a/src/armnn/Runtime.hpp b/src/armnn/Runtime.hpp
index 624304e..35684f1 100644
--- a/src/armnn/Runtime.hpp
+++ b/src/armnn/Runtime.hpp
@@ -6,11 +6,14 @@
 
 #include "LoadedNetwork.hpp"
 #include "DeviceSpec.hpp"
+
 #include <armnn/INetwork.hpp>
 #include <armnn/IRuntime.hpp>
 #include <armnn/Tensor.hpp>
 #include <armnn/BackendId.hpp>
 
+#include <backendsCommon/DynamicBackend.hpp>
+
 #include <mutex>
 #include <unordered_map>
 
@@ -100,6 +103,9 @@
     int m_NetworkIdCounter;
 
     DeviceSpec m_DeviceSpec;
+
+    /// List of dynamic backends loaded in the runtime
+    std::vector<DynamicBackendPtr> m_DynamicBackends;
 };
 
-}
+} // namespace armnn
diff --git a/src/backends/backendsCommon/DynamicBackend.cpp b/src/backends/backendsCommon/DynamicBackend.cpp
index 06d819b..c576199 100644
--- a/src/backends/backendsCommon/DynamicBackend.cpp
+++ b/src/backends/backendsCommon/DynamicBackend.cpp
@@ -70,18 +70,22 @@
 
 IBackendInternalUniquePtr DynamicBackend::GetBackend()
 {
+    // This call throws in case of error
+    return CreateBackend();
+}
+
+BackendRegistry::FactoryFunction DynamicBackend::GetFactoryFunction()
+{
     if (m_BackendFactoryFunction == nullptr)
     {
-        throw RuntimeException("GetBackend error: invalid function pointer");
+        throw RuntimeException("GetFactoryFunction error: invalid function pointer");
     }
 
-    auto backendPointer = reinterpret_cast<IBackendInternal*>(m_BackendFactoryFunction());
-    if (backendPointer == nullptr)
+    return [this]() -> IBackendInternalUniquePtr
     {
-        throw RuntimeException("GetBackend error: backend instance must not be null");
-    }
-
-    return std::unique_ptr<IBackendInternal>(backendPointer);
+        // This call throws in case of error
+        return CreateBackend();
+    };
 }
 
 template<typename BackendFunctionType>
@@ -108,4 +112,20 @@
     return functionPointer;
 }
 
+IBackendInternalUniquePtr DynamicBackend::CreateBackend()
+{
+    if (m_BackendFactoryFunction == nullptr)
+    {
+        throw RuntimeException("CreateBackend error: invalid function pointer");
+    }
+
+    auto backendPointer = reinterpret_cast<IBackendInternal*>(m_BackendFactoryFunction());
+    if (backendPointer == nullptr)
+    {
+        throw RuntimeException("CreateBackend error: backend instance must not be null");
+    }
+
+    return std::unique_ptr<IBackendInternal>(backendPointer);
+}
+
 } // namespace armnn
diff --git a/src/backends/backendsCommon/DynamicBackend.hpp b/src/backends/backendsCommon/DynamicBackend.hpp
index b202309..34c0019 100644
--- a/src/backends/backendsCommon/DynamicBackend.hpp
+++ b/src/backends/backendsCommon/DynamicBackend.hpp
@@ -6,6 +6,7 @@
 #pragma once
 
 #include "IBackendInternal.hpp"
+#include "BackendRegistry.hpp"
 
 #include <functional>
 #include <memory>
@@ -13,7 +14,7 @@
 namespace armnn
 {
 
-class DynamicBackend
+class DynamicBackend final
 {
 public:
     using HandleCloser = std::function<void(const void*)>;
@@ -25,10 +26,13 @@
     BackendId GetBackendId();
     BackendVersion GetBackendVersion();
     IBackendInternalUniquePtr GetBackend();
+    BackendRegistry::FactoryFunction GetFactoryFunction();
 
 private:
+    /// Private utility functions
     template<typename BackendFunctionType>
     BackendFunctionType SetFunctionPointer(const std::string& backendFunctionName);
+    IBackendInternalUniquePtr CreateBackend();
 
     /// Backend function pointer types
     using IdFunctionType      = const char*(*)();
diff --git a/src/backends/backendsCommon/DynamicBackendUtils.cpp b/src/backends/backendsCommon/DynamicBackendUtils.cpp
index 57a6056..38ac5ad 100644
--- a/src/backends/backendsCommon/DynamicBackendUtils.cpp
+++ b/src/backends/backendsCommon/DynamicBackendUtils.cpp
@@ -281,7 +281,6 @@
         {
             BOOST_LOG_TRIVIAL(warning) << "Invalid dynamic backend object for the shared object file \""
                                        << sharedObject << "\"";
-
             continue;
         }
 
@@ -292,4 +291,71 @@
     return dynamicBackends;
 }
 
+void DynamicBackendUtils::RegisterDynamicBackends(const std::vector<DynamicBackendPtr>& dynamicBackends)
+{
+    // Get a reference of the backend registry
+    BackendRegistry& backendRegistry = BackendRegistryInstance();
+
+    // Register the dynamic backends in the backend registry
+    RegisterDynamicBackendsImpl(backendRegistry, dynamicBackends);
+}
+
+void DynamicBackendUtils::RegisterDynamicBackendsImpl(BackendRegistry& backendRegistry,
+                                                      const std::vector<DynamicBackendPtr>& dynamicBackends)
+{
+    // Register the dynamic backends in the backend registry
+    for (const DynamicBackendPtr& dynamicBackend : dynamicBackends)
+    {
+        BackendId dynamicBackendId;
+        try
+        {
+            dynamicBackendId = dynamicBackend->GetBackendId();
+        }
+        catch (const RuntimeException& e)
+        {
+            BOOST_LOG_TRIVIAL(warning) << "Cannot register dynamic backend, "
+                                       << "an error has occurred when getting the backend id: " << e.what();
+            continue;
+        }
+        if (dynamicBackendId.IsEmpty() ||
+            dynamicBackendId.IsUndefined())
+        {
+            BOOST_LOG_TRIVIAL(warning) << "Cannot register dynamic backend, invalid backend id: " << dynamicBackendId;
+            continue;
+        }
+
+        // Check whether the dynamic backend is already registered
+        bool backendAlreadyRegistered = backendRegistry.IsBackendRegistered(dynamicBackendId);
+        if (backendAlreadyRegistered)
+        {
+            BOOST_LOG_TRIVIAL(warning) << "Cannot register dynamic backend \"" << dynamicBackendId
+                                       << "\": backend already registered";
+            continue;
+        }
+
+        // Get the dynamic backend factory function
+        BackendRegistry::FactoryFunction dynamicBackendFactoryFunction = nullptr;
+        try
+        {
+            dynamicBackendFactoryFunction = dynamicBackend->GetFactoryFunction();
+        }
+        catch (const RuntimeException& e)
+        {
+            BOOST_LOG_TRIVIAL(warning) << "Cannot register dynamic backend \"" << dynamicBackendId
+                                       << "\": an error has occurred when getting the backend factory function: "
+                                       << e.what();
+            continue;
+        }
+        if (dynamicBackendFactoryFunction == nullptr)
+        {
+            BOOST_LOG_TRIVIAL(warning) << "Cannot register dynamic backend \"" << dynamicBackendId
+                                       << "\": invalid backend factory function";
+            continue;
+        }
+
+        // Register the dynamic backend
+        backendRegistry.Register(dynamicBackendId, dynamicBackendFactoryFunction);
+    }
+}
+
 } // namespace armnn
diff --git a/src/backends/backendsCommon/DynamicBackendUtils.hpp b/src/backends/backendsCommon/DynamicBackendUtils.hpp
index 9c10df7..187b0b1 100644
--- a/src/backends/backendsCommon/DynamicBackendUtils.hpp
+++ b/src/backends/backendsCommon/DynamicBackendUtils.hpp
@@ -39,11 +39,14 @@
     static std::vector<std::string> GetSharedObjects(const std::vector<std::string>& backendPaths);
 
     static std::vector<DynamicBackendPtr> CreateDynamicBackends(const std::vector<std::string>& sharedObjects);
+    static void RegisterDynamicBackends(const std::vector<DynamicBackendPtr>& dynamicBackends);
 
 protected:
     /// Protected methods for testing purposes
     static bool IsBackendCompatibleImpl(const BackendVersion& backendApiVersion, const BackendVersion& backendVersion);
     static std::vector<std::string> GetBackendPathsImpl(const std::string& backendPaths);
+    static void RegisterDynamicBackendsImpl(BackendRegistry& backendRegistry,
+                                            const std::vector<DynamicBackendPtr>& dynamicBackends);
 
 private:
     static std::string GetDlError();
diff --git a/src/backends/backendsCommon/test/CMakeLists.txt b/src/backends/backendsCommon/test/CMakeLists.txt
index 6714a20..f517356 100644
--- a/src/backends/backendsCommon/test/CMakeLists.txt
+++ b/src/backends/backendsCommon/test/CMakeLists.txt
@@ -215,6 +215,14 @@
 set_target_properties(Arm_TestValid4_backend PROPERTIES PREFIX "")
 set_target_properties(Arm_TestValid4_backend PROPERTIES LIBRARY_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/backendsTestPath6)
 
+add_library_ex(Arm_TestValid5_backend MODULE ${testDynamicBackend_sources})
+target_compile_definitions(Arm_TestValid5_backend PRIVATE -DVALID_TEST_DYNAMIC_BACKEND_5)
+target_include_directories(Arm_TestValid5_backend PRIVATE ${PROJECT_SOURCE_DIR}/src/armnn)
+target_include_directories(Arm_TestValid5_backend PRIVATE ${PROJECT_SOURCE_DIR}/src/backends)
+target_link_libraries(Arm_TestValid5_backend armnn)
+set_target_properties(Arm_TestValid5_backend PROPERTIES PREFIX "")
+set_target_properties(Arm_TestValid5_backend PROPERTIES LIBRARY_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/backendsTestPath6)
+
 add_library_ex(Arm_TestInvalid9_backend MODULE ${testDynamicBackend_sources})
 target_compile_definitions(Arm_TestInvalid9_backend PRIVATE -DINVALID_TEST_DYNAMIC_BACKEND_9)
 target_include_directories(Arm_TestInvalid9_backend PRIVATE ${PROJECT_SOURCE_DIR}/src/armnn)
@@ -223,4 +231,20 @@
 set_target_properties(Arm_TestInvalid9_backend PROPERTIES PREFIX "")
 set_target_properties(Arm_TestInvalid9_backend PROPERTIES LIBRARY_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/backendsTestPath6)
 
+add_library_ex(Arm_TestInvalid10_backend MODULE ${testDynamicBackend_sources})
+target_compile_definitions(Arm_TestInvalid10_backend PRIVATE -DINVALID_TEST_DYNAMIC_BACKEND_10)
+target_include_directories(Arm_TestInvalid10_backend PRIVATE ${PROJECT_SOURCE_DIR}/src/armnn)
+target_include_directories(Arm_TestInvalid10_backend PRIVATE ${PROJECT_SOURCE_DIR}/src/backends)
+target_link_libraries(Arm_TestInvalid10_backend armnn)
+set_target_properties(Arm_TestInvalid10_backend PROPERTIES PREFIX "")
+set_target_properties(Arm_TestInvalid10_backend PROPERTIES LIBRARY_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/backendsTestPath9)
+
+add_library_ex(Arm_TestInvalid11_backend MODULE ${testDynamicBackend_sources})
+target_compile_definitions(Arm_TestInvalid11_backend PRIVATE -DINVALID_TEST_DYNAMIC_BACKEND_11)
+target_include_directories(Arm_TestInvalid11_backend PRIVATE ${PROJECT_SOURCE_DIR}/src/armnn)
+target_include_directories(Arm_TestInvalid11_backend PRIVATE ${PROJECT_SOURCE_DIR}/src/backends)
+target_link_libraries(Arm_TestInvalid11_backend armnn)
+set_target_properties(Arm_TestInvalid11_backend PROPERTIES PREFIX "")
+set_target_properties(Arm_TestInvalid11_backend PROPERTIES LIBRARY_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/backendsTestPath9)
+
 file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/backendsTestPath7)
diff --git a/src/backends/backendsCommon/test/DynamicBackendTests.cpp b/src/backends/backendsCommon/test/DynamicBackendTests.cpp
index b5d159a..21ce2db 100644
--- a/src/backends/backendsCommon/test/DynamicBackendTests.cpp
+++ b/src/backends/backendsCommon/test/DynamicBackendTests.cpp
@@ -50,4 +50,9 @@
 ARMNN_SIMPLE_TEST_CASE(CreateDynamicBackendsAllInvalid, CreateDynamicBackendsAllInvalidTestImpl);
 ARMNN_SIMPLE_TEST_CASE(CreateDynamicBackendsMixedTypes, CreateDynamicBackendsMixedTypesTestImpl);
 
+ARMNN_SIMPLE_TEST_CASE(RegisterSingleDynamicBackend, RegisterSingleDynamicBackendTestImpl);
+ARMNN_SIMPLE_TEST_CASE(RegisterMultipleDynamicBackends, RegisterMultipleDynamicBackendsTestImpl);
+ARMNN_SIMPLE_TEST_CASE(RegisterMultipleInvalidDynamicBackends, RegisterMultipleInvalidDynamicBackendsTestImpl);
+ARMNN_SIMPLE_TEST_CASE(RegisterMixedDynamicBackends, RegisterMixedDynamicBackendsTestImpl);
+
 BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/backends/backendsCommon/test/DynamicBackendTests.hpp b/src/backends/backendsCommon/test/DynamicBackendTests.hpp
index e3fbe31..ae922bc 100644
--- a/src/backends/backendsCommon/test/DynamicBackendTests.hpp
+++ b/src/backends/backendsCommon/test/DynamicBackendTests.hpp
@@ -36,17 +36,43 @@
 static std::string g_TestValidBackend2FileName              = "Arm_TestValid2_backend.so";
 static std::string g_TestValidBackend3FileName              = "Arm_TestValid3_backend.so";
 static std::string g_TestValidBackend4FileName              = "Arm_TestValid4_backend.so";
+static std::string g_TestValidBackend5FileName              = "Arm_TestValid5_backend.so";
 static std::string g_TestInvalidBackend8FileName            = "Arm_TestInvalid8_backend.so";
 static std::string g_TestInvalidBackend9FileName            = "Arm_TestInvalid9_backend.so";
+static std::string g_TestInvalidBackend10FileName           = "Arm_TestInvalid10_backend.so";
+static std::string g_TestInvalidBackend11FileName           = "Arm_TestInvalid11_backend.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/";
-static std::string g_TestDynamicBackendsFileParsingSubDir5  = "backendsTestPath5/";
-static std::string g_TestDynamicBackendsFileParsingSubDir6  = "backendsTestPath6/";
-static std::string g_TestDynamicBackendsFileParsingSubDir7  = "backendsTestPath7/";
-static std::string g_TestDynamicBackendsFileParsingSubDir8  = "backendsTestPath8/";
+static std::string g_TestDynamicBackendsSubDir1  = "backendsTestPath1/";
+static std::string g_TestDynamicBackendsSubDir2  = "backendsTestPath2/";
+static std::string g_TestDynamicBackendsSubDir3  = "backendsTestPath3/";
+static std::string g_TestDynamicBackendsSubDir4  = "backendsTestPath4/";
+static std::string g_TestDynamicBackendsSubDir5  = "backendsTestPath5/";
+static std::string g_TestDynamicBackendsSubDir6  = "backendsTestPath6/";
+static std::string g_TestDynamicBackendsSubDir7  = "backendsTestPath7/";
+static std::string g_TestDynamicBackendsSubDir8  = "backendsTestPath8/";
+static std::string g_TestDynamicBackendsSubDir9  = "backendsTestPath9/";
+
+// Wrapper class used for testing
+class TestDynamicBackendUtils : public armnn::DynamicBackendUtils
+{
+public:
+    static bool IsBackendCompatibleTest(const armnn::BackendVersion& backendApiVersion,
+                                        const armnn::BackendVersion& backendVersion)
+    {
+        return IsBackendCompatibleImpl(backendApiVersion, backendVersion);
+    }
+
+    static std::vector<std::string> GetBackendPathsImplTest(const std::string& path)
+    {
+        return GetBackendPathsImpl(path);
+    }
+
+    static void RegisterDynamicBackendsImplTest(armnn::BackendRegistry& backendRegistry,
+                                                const std::vector<armnn::DynamicBackendPtr>& dynamicBackends)
+    {
+        RegisterDynamicBackendsImpl(backendRegistry, dynamicBackends);
+    }
+};
 
 std::string GetTestDirectoryBasePath()
 {
@@ -222,16 +248,6 @@
 {
     using namespace armnn;
 
-    class TestDynamicBackendUtils : public DynamicBackendUtils
-    {
-    public:
-        static bool IsBackendCompatibleTest(const BackendVersion& backendApiVersion,
-                                            const BackendVersion& backendVersion)
-        {
-            return IsBackendCompatibleImpl(backendApiVersion, backendVersion);
-        }
-    };
-
     // The backend API version used for the tests
     BackendVersion backendApiVersion{ 2, 4 };
 
@@ -297,11 +313,20 @@
     BOOST_CHECK_NO_THROW(dynamicBackendVersion = dynamicBackend->GetBackendVersion());
     BOOST_TEST((dynamicBackendVersion == IBackendInternal::GetApiVersion()));
 
-    IBackendInternalUniquePtr dynamicBackendInstance;
-    BOOST_CHECK_NO_THROW(dynamicBackendInstance = dynamicBackend->GetBackend());
-    BOOST_TEST((dynamicBackendInstance != nullptr));
+    IBackendInternalUniquePtr dynamicBackendInstance1;
+    BOOST_CHECK_NO_THROW(dynamicBackendInstance1 = dynamicBackend->GetBackend());
+    BOOST_TEST((dynamicBackendInstance1 != nullptr));
 
-    BOOST_TEST((dynamicBackendInstance->GetId() == "ValidTestDynamicBackend"));
+    BackendRegistry::FactoryFunction dynamicBackendFactoryFunction = nullptr;
+    BOOST_CHECK_NO_THROW(dynamicBackendFactoryFunction = dynamicBackend->GetFactoryFunction());
+    BOOST_TEST((dynamicBackendFactoryFunction != nullptr));
+
+    IBackendInternalUniquePtr dynamicBackendInstance2;
+    BOOST_CHECK_NO_THROW(dynamicBackendInstance2 = dynamicBackendFactoryFunction());
+    BOOST_TEST((dynamicBackendInstance2 != nullptr));
+
+    BOOST_TEST((dynamicBackendInstance1->GetId() == "ValidTestDynamicBackend"));
+    BOOST_TEST((dynamicBackendInstance2->GetId() == "ValidTestDynamicBackend"));
 }
 
 void CreateDynamicBackendObjectInvalidHandleTestImpl()
@@ -444,9 +469,17 @@
     BOOST_CHECK_NO_THROW(dynamicBackendVersion = dynamicBackend->GetBackendVersion());
     BOOST_TEST((dynamicBackendVersion == BackendVersion({ 1, 0 })));
 
-    IBackendInternalUniquePtr dynamicBackendInstance;
-    BOOST_CHECK_THROW(dynamicBackendInstance = dynamicBackend->GetBackend(), RuntimeException);
-    BOOST_TEST((dynamicBackendInstance == nullptr));
+    IBackendInternalUniquePtr dynamicBackendInstance1;
+    BOOST_CHECK_THROW(dynamicBackendInstance1 = dynamicBackend->GetBackend(), RuntimeException);
+    BOOST_TEST((dynamicBackendInstance1 == nullptr));
+
+    BackendRegistry::FactoryFunction dynamicBackendFactoryFunction = nullptr;
+    BOOST_CHECK_NO_THROW(dynamicBackendFactoryFunction = dynamicBackend->GetFactoryFunction());
+    BOOST_TEST((dynamicBackendFactoryFunction != nullptr));
+
+    IBackendInternalUniquePtr dynamicBackendInstance2;
+    BOOST_CHECK_THROW(dynamicBackendInstance2 = dynamicBackendFactoryFunction(), RuntimeException);
+    BOOST_TEST((dynamicBackendInstance2 == nullptr));
 }
 
 void CreateDynamicBackendObjectInvalidInterface7TestImpl()
@@ -482,25 +515,16 @@
     //                                                ├─ backendsTestPath3/   -> exists, but empty
     //                                                └─ backendsTestPath4/   -> does not exist
 
-    std::string subDir1 = GetTestSubDirectory(g_TestDynamicBackendsFileParsingSubDir1);
-    std::string subDir2 = GetTestSubDirectory(g_TestDynamicBackendsFileParsingSubDir2);
-    std::string subDir3 = GetTestSubDirectory(g_TestDynamicBackendsFileParsingSubDir3);
-    std::string subDir4 = GetTestSubDirectory(g_TestDynamicBackendsFileParsingSubDir4);
+    std::string subDir1 = GetTestSubDirectory(g_TestDynamicBackendsSubDir1);
+    std::string subDir2 = GetTestSubDirectory(g_TestDynamicBackendsSubDir2);
+    std::string subDir3 = GetTestSubDirectory(g_TestDynamicBackendsSubDir3);
+    std::string subDir4 = GetTestSubDirectory(g_TestDynamicBackendsSubDir4);
 
     BOOST_CHECK(exists(subDir1));
     BOOST_CHECK(exists(subDir2));
     BOOST_CHECK(exists(subDir3));
     BOOST_CHECK(!exists(subDir4));
 
-    class TestDynamicBackendUtils : public DynamicBackendUtils
-    {
-    public:
-        static std::vector<std::string> GetBackendPathsImplTest(const std::string& path)
-        {
-            return GetBackendPathsImpl(path);
-        }
-    };
-
     // No path
     BOOST_TEST(TestDynamicBackendUtils::GetBackendPathsImplTest("").empty());
 
@@ -564,8 +588,8 @@
     using namespace armnn;
     using namespace boost::filesystem;
 
-    std::string subDir1 = GetTestSubDirectory(g_TestDynamicBackendsFileParsingSubDir1);
-    std::string subDir4 = GetTestSubDirectory(g_TestDynamicBackendsFileParsingSubDir4);
+    std::string subDir1 = GetTestSubDirectory(g_TestDynamicBackendsSubDir1);
+    std::string subDir4 = GetTestSubDirectory(g_TestDynamicBackendsSubDir4);
 
     BOOST_CHECK(exists(subDir1));
     BOOST_CHECK(!exists(subDir4));
@@ -629,10 +653,10 @@
     //
     // 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);
+    std::string testDynamicBackendsSubDir1 = GetTestSubDirectory(g_TestDynamicBackendsSubDir1);
+    std::string testDynamicBackendsSubDir2 = GetTestSubDirectory(g_TestDynamicBackendsSubDir2);
+    std::string testDynamicBackendsSubDir3 = GetTestSubDirectory(g_TestDynamicBackendsSubDir3);
+    std::string testDynamicBackendsSubDir4 = GetTestSubDirectory(g_TestDynamicBackendsSubDir4);
     BOOST_CHECK(exists(testDynamicBackendsSubDir1));
     BOOST_CHECK(exists(testDynamicBackendsSubDir2));
     BOOST_CHECK(exists(testDynamicBackendsSubDir3));
@@ -676,7 +700,7 @@
     using namespace armnn;
     using namespace boost::filesystem;
 
-    // The test covers three directories:
+    // The test covers four directories:
     // <unit test path>/src/backends/backendsCommon/test/
     //                                                ├─ backendsTestPath5/   -> exists, contains files
     //                                                ├─ backendsTestPath6/   -> exists, contains files
@@ -695,14 +719,15 @@
     // Arm_TestValid4_backend.so   -> valid (it has a different filename,
     //                                       but it has the same backend id of Arm_TestValid2_backend.so
     //                                       and the same version)
+    // Arm_TestValid5_backend.so   -> valid (basic backend name)
     // Arm_TestInvalid9_backend.so -> not valid (it has a different filename,
     //                                           but it has the same backend id of Arm_TestValid2_backend.so
     //                                           and a version incompatible with the Backend API)
 
-    std::string testDynamicBackendsSubDir5 = GetTestSubDirectory(g_TestDynamicBackendsFileParsingSubDir5);
-    std::string testDynamicBackendsSubDir6 = GetTestSubDirectory(g_TestDynamicBackendsFileParsingSubDir6);
-    std::string testDynamicBackendsSubDir7 = GetTestSubDirectory(g_TestDynamicBackendsFileParsingSubDir7);
-    std::string testDynamicBackendsSubDir8 = GetTestSubDirectory(g_TestDynamicBackendsFileParsingSubDir8);
+    std::string testDynamicBackendsSubDir5 = GetTestSubDirectory(g_TestDynamicBackendsSubDir5);
+    std::string testDynamicBackendsSubDir6 = GetTestSubDirectory(g_TestDynamicBackendsSubDir6);
+    std::string testDynamicBackendsSubDir7 = GetTestSubDirectory(g_TestDynamicBackendsSubDir7);
+    std::string testDynamicBackendsSubDir8 = GetTestSubDirectory(g_TestDynamicBackendsSubDir8);
     BOOST_CHECK(exists(testDynamicBackendsSubDir5));
     BOOST_CHECK(exists(testDynamicBackendsSubDir6));
     BOOST_CHECK(exists(testDynamicBackendsSubDir7));
@@ -718,17 +743,19 @@
     std::vector<std::string> sharedObjects = DynamicBackendUtils::GetSharedObjects(backendPaths);
     std::vector<DynamicBackendPtr> dynamicBackends = DynamicBackendUtils::CreateDynamicBackends(sharedObjects);
 
-    BOOST_TEST(dynamicBackends.size() == 4);
+    BOOST_TEST(dynamicBackends.size() == 5);
     BOOST_TEST((dynamicBackends[0] != nullptr));
     BOOST_TEST((dynamicBackends[1] != nullptr));
     BOOST_TEST((dynamicBackends[2] != nullptr));
     BOOST_TEST((dynamicBackends[3] != nullptr));
+    BOOST_TEST((dynamicBackends[4] != nullptr));
 
     // Duplicates are allowed here, they will be skipped later during the backend registration
     BOOST_TEST((dynamicBackends[0]->GetBackendId() == "TestValid2"));
     BOOST_TEST((dynamicBackends[1]->GetBackendId() == "TestValid3"));
     BOOST_TEST((dynamicBackends[2]->GetBackendId() == "TestValid2")); // From duplicate Arm_TestValid2_backend.so
     BOOST_TEST((dynamicBackends[3]->GetBackendId() == "TestValid2")); // From Arm_TestValid4_backend.so
+    BOOST_TEST((dynamicBackends[4]->GetBackendId() == "TestValid5"));
 }
 
 void CreateDynamicBackendsNoPathsTestImpl()
@@ -760,8 +787,8 @@
     using namespace armnn;
     using namespace boost::filesystem;
 
-    std::string testDynamicBackendsSubDir5 = GetTestSubDirectory(g_TestDynamicBackendsFileParsingSubDir5);
-    std::string testDynamicBackendsSubDir6 = GetTestSubDirectory(g_TestDynamicBackendsFileParsingSubDir6);
+    std::string testDynamicBackendsSubDir5 = GetTestSubDirectory(g_TestDynamicBackendsSubDir5);
+    std::string testDynamicBackendsSubDir6 = GetTestSubDirectory(g_TestDynamicBackendsSubDir6);
     BOOST_CHECK(exists(testDynamicBackendsSubDir5));
     BOOST_CHECK(exists(testDynamicBackendsSubDir6));
 
@@ -788,3 +815,319 @@
     BOOST_TEST((dynamicBackends[0] != nullptr));
     BOOST_TEST((dynamicBackends[0]->GetBackendId() == "TestValid2"));
 }
+
+void RegisterSingleDynamicBackendTestImpl()
+{
+    using namespace armnn;
+    using namespace boost::filesystem;
+
+    // Register one valid dynamic backend
+
+    // Dummy registry used for testing
+    BackendRegistry backendRegistry;
+    BOOST_TEST(backendRegistry.Size() == 0);
+
+    std::string testDynamicBackendsSubDir5 = GetTestSubDirectory(g_TestDynamicBackendsSubDir5);
+    BOOST_CHECK(exists(testDynamicBackendsSubDir5));
+
+    std::string testValidBackend2FilePath = GetTestFilePath(testDynamicBackendsSubDir5, g_TestValidBackend2FileName);
+    BOOST_CHECK(exists(testValidBackend2FilePath));
+
+    std::vector<std::string> sharedObjects{ testValidBackend2FilePath };
+    std::vector<DynamicBackendPtr> dynamicBackends = TestDynamicBackendUtils::CreateDynamicBackends(sharedObjects);
+
+    BOOST_TEST(dynamicBackends.size() == 1);
+    BOOST_TEST((dynamicBackends[0] != nullptr));
+
+    BackendId dynamicBackendId = dynamicBackends[0]->GetBackendId();
+    BOOST_TEST((dynamicBackendId == "TestValid2"));
+
+    BackendVersion dynamicBackendVersion = dynamicBackends[0]->GetBackendVersion();
+    BOOST_TEST(TestDynamicBackendUtils::IsBackendCompatible(dynamicBackendVersion));
+
+    TestDynamicBackendUtils::RegisterDynamicBackendsImplTest(backendRegistry, dynamicBackends);
+    BOOST_TEST(backendRegistry.Size() == 1);
+
+    BackendIdSet backendIds = backendRegistry.GetBackendIds();
+    BOOST_TEST(backendIds.size() == 1);
+    BOOST_TEST((backendIds.find(dynamicBackendId) != backendIds.end()));
+
+    auto dynamicBackendFactoryFunction = backendRegistry.GetFactory(dynamicBackendId);
+    BOOST_TEST((dynamicBackendFactoryFunction != nullptr));
+
+    IBackendInternalUniquePtr dynamicBackend = dynamicBackendFactoryFunction();
+    BOOST_TEST((dynamicBackend != nullptr));
+    BOOST_TEST((dynamicBackend->GetId() == dynamicBackendId));
+}
+
+void RegisterMultipleDynamicBackendsTestImpl()
+{
+    using namespace armnn;
+    using namespace boost::filesystem;
+
+    // Register many valid dynamic backends
+
+    std::string testDynamicBackendsSubDir5 = GetTestSubDirectory(g_TestDynamicBackendsSubDir5);
+    std::string testDynamicBackendsSubDir6 = GetTestSubDirectory(g_TestDynamicBackendsSubDir6);
+    BOOST_CHECK(exists(testDynamicBackendsSubDir5));
+    BOOST_CHECK(exists(testDynamicBackendsSubDir6));
+
+    std::string testValidBackend2FilePath = GetTestFilePath(testDynamicBackendsSubDir5, g_TestValidBackend2FileName);
+    std::string testValidBackend3FilePath = GetTestFilePath(testDynamicBackendsSubDir5, g_TestValidBackend3FileName);
+    std::string testValidBackend5FilePath = GetTestFilePath(testDynamicBackendsSubDir6, g_TestValidBackend5FileName);
+    BOOST_CHECK(exists(testValidBackend2FilePath));
+    BOOST_CHECK(exists(testValidBackend3FilePath));
+    BOOST_CHECK(exists(testValidBackend5FilePath));
+
+    std::vector<std::string> sharedObjects
+    {
+        testValidBackend2FilePath,
+        testValidBackend3FilePath,
+        testValidBackend5FilePath
+    };
+    std::vector<DynamicBackendPtr> dynamicBackends = TestDynamicBackendUtils::CreateDynamicBackends(sharedObjects);
+
+    BOOST_TEST(dynamicBackends.size() == 3);
+    BOOST_TEST((dynamicBackends[0] != nullptr));
+    BOOST_TEST((dynamicBackends[1] != nullptr));
+    BOOST_TEST((dynamicBackends[2] != nullptr));
+
+    BackendId dynamicBackendId1 = dynamicBackends[0]->GetBackendId();
+    BackendId dynamicBackendId2 = dynamicBackends[1]->GetBackendId();
+    BackendId dynamicBackendId3 = dynamicBackends[2]->GetBackendId();
+    BOOST_TEST((dynamicBackendId1 == "TestValid2"));
+    BOOST_TEST((dynamicBackendId2 == "TestValid3"));
+    BOOST_TEST((dynamicBackendId3 == "TestValid5"));
+
+    for (size_t i = 0; i < dynamicBackends.size(); i++)
+    {
+        BackendVersion dynamicBackendVersion = dynamicBackends[i]->GetBackendVersion();
+        BOOST_TEST(TestDynamicBackendUtils::IsBackendCompatible(dynamicBackendVersion));
+    }
+
+    // Dummy registry used for testing
+    BackendRegistry backendRegistry;
+    BOOST_TEST(backendRegistry.Size() == 0);
+
+    TestDynamicBackendUtils::RegisterDynamicBackendsImplTest(backendRegistry, dynamicBackends);
+    BOOST_TEST(backendRegistry.Size() == 3);
+
+    BackendIdSet backendIds = backendRegistry.GetBackendIds();
+    BOOST_TEST(backendIds.size() == 3);
+    BOOST_TEST((backendIds.find(dynamicBackendId1) != backendIds.end()));
+    BOOST_TEST((backendIds.find(dynamicBackendId2) != backendIds.end()));
+    BOOST_TEST((backendIds.find(dynamicBackendId3) != backendIds.end()));
+
+    for (size_t i = 0; i < dynamicBackends.size(); i++)
+    {
+        BackendId dynamicBackendId = dynamicBackends[i]->GetBackendId();
+
+        auto dynamicBackendFactoryFunction = backendRegistry.GetFactory(dynamicBackendId);
+        BOOST_TEST((dynamicBackendFactoryFunction != nullptr));
+
+        IBackendInternalUniquePtr dynamicBackend = dynamicBackendFactoryFunction();
+        BOOST_TEST((dynamicBackend != nullptr));
+        BOOST_TEST((dynamicBackend->GetId() == dynamicBackendId));
+    }
+}
+
+void RegisterMultipleInvalidDynamicBackendsTestImpl()
+{
+    using namespace armnn;
+    using namespace boost::filesystem;
+
+    // Try to register many invalid dynamic backends
+
+    // The test covers one directory:
+    // <unit test path>/src/backends/backendsCommon/test/
+    //                                                └─ backendsTestPath9/   -> exists, contains files
+    //
+    // The test sub-directory backendsTestPath9/ contains the following test files:
+    //
+    // Arm_TestInvalid10_backend.so -> not valid (invalid backend id)
+    // Arm_TestInvalid11_backend.so -> not valid (invalid backend id)
+
+    std::string testDynamicBackendsSubDir9 = GetTestSubDirectory(g_TestDynamicBackendsSubDir9);
+    BOOST_CHECK(exists(testDynamicBackendsSubDir9));
+
+    std::string testInvalidBackend10FilePath = GetTestFilePath(testDynamicBackendsSubDir9,
+                                                               g_TestInvalidBackend10FileName);
+    std::string testInvalidBackend11FilePath = GetTestFilePath(testDynamicBackendsSubDir9,
+                                                               g_TestInvalidBackend11FileName);
+    BOOST_CHECK(exists(testInvalidBackend10FilePath));
+    BOOST_CHECK(exists(testInvalidBackend11FilePath));
+
+    std::vector<std::string> sharedObjects
+    {
+        testInvalidBackend10FilePath,
+        testInvalidBackend11FilePath,
+        "InvalidSharedObject"
+    };
+    std::vector<DynamicBackendPtr> dynamicBackends = TestDynamicBackendUtils::CreateDynamicBackends(sharedObjects);
+
+    BOOST_TEST(dynamicBackends.size() == 2);
+    BOOST_TEST((dynamicBackends[0] != nullptr));
+    BOOST_TEST((dynamicBackends[1] != nullptr));
+
+    BackendId dynamicBackendId1 = dynamicBackends[0]->GetBackendId();
+    BackendId dynamicBackendId2 = dynamicBackends[1]->GetBackendId();
+    BOOST_TEST((dynamicBackendId1 == ""));
+    BOOST_TEST((dynamicBackendId2 == "Unknown"));
+
+    for (size_t i = 0; i < dynamicBackends.size(); i++)
+    {
+        BackendVersion dynamicBackendVersion = dynamicBackends[i]->GetBackendVersion();
+        BOOST_TEST(TestDynamicBackendUtils::IsBackendCompatible(dynamicBackendVersion));
+    }
+
+    // Dummy registry used for testing
+    BackendRegistry backendRegistry;
+    BOOST_TEST(backendRegistry.Size() == 0);
+
+    // Check that no dynamic backend got registered
+    TestDynamicBackendUtils::RegisterDynamicBackendsImplTest(backendRegistry, dynamicBackends);
+    BOOST_TEST(backendRegistry.Size() == 0);
+}
+
+void RegisterMixedDynamicBackendsTestImpl()
+{
+    using namespace armnn;
+    using namespace boost::filesystem;
+
+    // The test covers five directories:
+    // <unit test path>/src/backends/backendsCommon/test/
+    //                                                ├─ backendsTestPath5/   -> exists, contains files
+    //                                                ├─ backendsTestPath6/   -> exists, contains files
+    //                                                ├─ backendsTestPath7/   -> exists, but empty
+    //                                                ├─ backendsTestPath8/   -> does not exist
+    //                                                └─ backendsTestPath9/   -> exists, contains files
+    //
+    // The test sub-directory backendsTestPath5/ contains the following test files:
+    //
+    // Arm_TestValid2_backend.so   -> valid (basic backend name)
+    // Arm_TestValid3_backend.so   -> valid (basic backend name)
+    // Arm_TestInvalid8_backend.so -> not valid (invalid backend id)
+    //
+    // The test sub-directory backendsTestPath6/ contains the following test files:
+    //
+    // Arm_TestValid2_backend.so   -> valid (but duplicated from backendsTestPath5/)
+    // Arm_TestValid4_backend.so   -> valid (it has a different filename,
+    //                                       but it has the same backend id of Arm_TestValid2_backend.so
+    //                                       and the same version)
+    // Arm_TestValid5_backend.so   -> valid (basic backend name)
+    // Arm_TestInvalid9_backend.so -> not valid (it has a different filename,
+    //                                           but it has the same backend id of Arm_TestValid2_backend.so
+    //                                           and a version incompatible with the Backend API)
+    //
+    // The test sub-directory backendsTestPath9/ contains the following test files:
+    //
+    // Arm_TestInvalid10_backend.so -> not valid (empty backend id)
+    // Arm_TestInvalid11_backend.so -> not valid ("Unknown" backend id)
+
+    std::string testDynamicBackendsSubDir5 = GetTestSubDirectory(g_TestDynamicBackendsSubDir5);
+    std::string testDynamicBackendsSubDir6 = GetTestSubDirectory(g_TestDynamicBackendsSubDir6);
+    std::string testDynamicBackendsSubDir7 = GetTestSubDirectory(g_TestDynamicBackendsSubDir7);
+    std::string testDynamicBackendsSubDir8 = GetTestSubDirectory(g_TestDynamicBackendsSubDir8);
+    std::string testDynamicBackendsSubDir9 = GetTestSubDirectory(g_TestDynamicBackendsSubDir9);
+    BOOST_CHECK(exists(testDynamicBackendsSubDir5));
+    BOOST_CHECK(exists(testDynamicBackendsSubDir6));
+    BOOST_CHECK(exists(testDynamicBackendsSubDir7));
+    BOOST_CHECK(!exists(testDynamicBackendsSubDir8));
+    BOOST_CHECK(exists(testDynamicBackendsSubDir9));
+
+    std::string testValidBackend2FilePath    = GetTestFilePath(testDynamicBackendsSubDir5, g_TestValidBackend2FileName);
+    std::string testValidBackend3FilePath    = GetTestFilePath(testDynamicBackendsSubDir5, g_TestValidBackend3FileName);
+    std::string testValidBackend2DupFilePath = GetTestFilePath(testDynamicBackendsSubDir6, g_TestValidBackend2FileName);
+    std::string testValidBackend4FilePath    = GetTestFilePath(testDynamicBackendsSubDir6, g_TestValidBackend4FileName);
+    std::string testValidBackend5FilePath    = GetTestFilePath(testDynamicBackendsSubDir6, g_TestValidBackend5FileName);
+    std::string testInvalidBackend8FilePath  = GetTestFilePath(testDynamicBackendsSubDir5,
+                                                               g_TestInvalidBackend8FileName);
+    std::string testInvalidBackend9FilePath  = GetTestFilePath(testDynamicBackendsSubDir6,
+                                                               g_TestInvalidBackend9FileName);
+    std::string testInvalidBackend10FilePath = GetTestFilePath(testDynamicBackendsSubDir9,
+                                                               g_TestInvalidBackend10FileName);
+    std::string testInvalidBackend11FilePath = GetTestFilePath(testDynamicBackendsSubDir9,
+                                                               g_TestInvalidBackend11FileName);
+    BOOST_CHECK(exists(testValidBackend2FilePath));
+    BOOST_CHECK(exists(testValidBackend3FilePath));
+    BOOST_CHECK(exists(testValidBackend2DupFilePath));
+    BOOST_CHECK(exists(testValidBackend4FilePath));
+    BOOST_CHECK(exists(testValidBackend5FilePath));
+    BOOST_CHECK(exists(testInvalidBackend8FilePath));
+    BOOST_CHECK(exists(testInvalidBackend9FilePath));
+    BOOST_CHECK(exists(testInvalidBackend10FilePath));
+    BOOST_CHECK(exists(testInvalidBackend11FilePath));
+
+    std::vector<std::string> sharedObjects
+    {
+        testValidBackend2FilePath,
+        testValidBackend3FilePath,
+        testValidBackend2DupFilePath,
+        testValidBackend4FilePath,
+        testValidBackend5FilePath,
+        testInvalidBackend8FilePath,
+        testInvalidBackend9FilePath,
+        testInvalidBackend10FilePath,
+        testInvalidBackend11FilePath,
+        "InvalidSharedObject"
+    };
+    std::vector<DynamicBackendPtr> dynamicBackends = TestDynamicBackendUtils::CreateDynamicBackends(sharedObjects);
+
+    BOOST_TEST(dynamicBackends.size() == 7);
+    BOOST_TEST((dynamicBackends[0] != nullptr));
+    BOOST_TEST((dynamicBackends[1] != nullptr));
+    BOOST_TEST((dynamicBackends[2] != nullptr));
+    BOOST_TEST((dynamicBackends[3] != nullptr));
+    BOOST_TEST((dynamicBackends[4] != nullptr));
+    BOOST_TEST((dynamicBackends[5] != nullptr));
+    BOOST_TEST((dynamicBackends[6] != nullptr));
+
+    BackendId dynamicBackendId1 = dynamicBackends[0]->GetBackendId();
+    BackendId dynamicBackendId2 = dynamicBackends[1]->GetBackendId();
+    BackendId dynamicBackendId3 = dynamicBackends[2]->GetBackendId();
+    BackendId dynamicBackendId4 = dynamicBackends[3]->GetBackendId();
+    BackendId dynamicBackendId5 = dynamicBackends[4]->GetBackendId();
+    BackendId dynamicBackendId6 = dynamicBackends[5]->GetBackendId();
+    BackendId dynamicBackendId7 = dynamicBackends[6]->GetBackendId();
+    BOOST_TEST((dynamicBackendId1 == "TestValid2"));
+    BOOST_TEST((dynamicBackendId2 == "TestValid3"));
+    BOOST_TEST((dynamicBackendId3 == "TestValid2")); // From duplicate Arm_TestValid2_backend.so
+    BOOST_TEST((dynamicBackendId4 == "TestValid2")); // From Arm_TestValid4_backend.so
+    BOOST_TEST((dynamicBackendId5 == "TestValid5"));
+    BOOST_TEST((dynamicBackendId6 == ""));
+    BOOST_TEST((dynamicBackendId7 == "Unknown"));
+
+    for (size_t i = 0; i < dynamicBackends.size(); i++)
+    {
+        BackendVersion dynamicBackendVersion = dynamicBackends[i]->GetBackendVersion();
+        BOOST_TEST(TestDynamicBackendUtils::IsBackendCompatible(dynamicBackendVersion));
+    }
+
+    // Dummy registry used for testing
+    BackendRegistry backendRegistry;
+    BOOST_TEST(backendRegistry.Size() == 0);
+
+    std::vector<BackendId> expectedRegisteredbackendIds
+    {
+        "TestValid2",
+        "TestValid3",
+        "TestValid5"
+    };
+
+    TestDynamicBackendUtils::RegisterDynamicBackendsImplTest(backendRegistry, dynamicBackends);
+    BOOST_TEST(backendRegistry.Size() == expectedRegisteredbackendIds.size());
+
+    BackendIdSet backendIds = backendRegistry.GetBackendIds();
+    BOOST_TEST(backendIds.size() == expectedRegisteredbackendIds.size());
+    for (const BackendId& expectedRegisteredbackendId : expectedRegisteredbackendIds)
+    {
+        BOOST_TEST((backendIds.find(expectedRegisteredbackendId) != backendIds.end()));
+
+        auto dynamicBackendFactoryFunction = backendRegistry.GetFactory(expectedRegisteredbackendId);
+        BOOST_TEST((dynamicBackendFactoryFunction != nullptr));
+
+        IBackendInternalUniquePtr dynamicBackend = dynamicBackendFactoryFunction();
+        BOOST_TEST((dynamicBackend != nullptr));
+        BOOST_TEST((dynamicBackend->GetId() == expectedRegisteredbackendId));
+    }
+}
diff --git a/src/backends/backendsCommon/test/TestDynamicBackend.cpp b/src/backends/backendsCommon/test/TestDynamicBackend.cpp
index bdbc174..7230702 100644
--- a/src/backends/backendsCommon/test/TestDynamicBackend.cpp
+++ b/src/backends/backendsCommon/test/TestDynamicBackend.cpp
@@ -28,6 +28,21 @@
     // The test dynamic backend 3 is a different backend than the test dynamic backend 2
     return "TestValid3";
 
+#elif defined(VALID_TEST_DYNAMIC_BACKEND_5)
+
+    // The test dynamic backend 5 is a different backend than the test dynamic backend 2
+    return "TestValid5";
+
+#elif defined(INVALID_TEST_DYNAMIC_BACKEND_10)
+
+    // Empty backend id
+    return "";
+
+#elif defined(INVALID_TEST_DYNAMIC_BACKEND_11)
+
+    // "Unknown" backend id, "Unknown" is a reserved id in ArmNN
+    return "Unknown";
+
 #else
 
     return "InvalidTestDynamicBackend";
diff --git a/src/backends/backendsCommon/test/TestDynamicBackend.hpp b/src/backends/backendsCommon/test/TestDynamicBackend.hpp
index 74ab91b..61a6eaf 100644
--- a/src/backends/backendsCommon/test/TestDynamicBackend.hpp
+++ b/src/backends/backendsCommon/test/TestDynamicBackend.hpp
@@ -10,7 +10,8 @@
 #if defined(VALID_TEST_DYNAMIC_BACKEND_1) || \
     defined(VALID_TEST_DYNAMIC_BACKEND_2) || \
     defined(VALID_TEST_DYNAMIC_BACKEND_3) || \
-    defined(VALID_TEST_DYNAMIC_BACKEND_4)
+    defined(VALID_TEST_DYNAMIC_BACKEND_4) || \
+    defined(VALID_TEST_DYNAMIC_BACKEND_5)
 
 // Correct dynamic backend interface
 extern "C"
@@ -50,11 +51,13 @@
 const char* GetBackendId();
 void GetVersion(uint32_t* outMajor, uint32_t* outMinor);
 
-#elif defined(INVALID_TEST_DYNAMIC_BACKEND_5) || \
-      defined(INVALID_TEST_DYNAMIC_BACKEND_6) || \
-      defined(INVALID_TEST_DYNAMIC_BACKEND_7) || \
-      defined(INVALID_TEST_DYNAMIC_BACKEND_8) || \
-      defined(INVALID_TEST_DYNAMIC_BACKEND_9)
+#elif defined(INVALID_TEST_DYNAMIC_BACKEND_5)  || \
+      defined(INVALID_TEST_DYNAMIC_BACKEND_6)  || \
+      defined(INVALID_TEST_DYNAMIC_BACKEND_7)  || \
+      defined(INVALID_TEST_DYNAMIC_BACKEND_8)  || \
+      defined(INVALID_TEST_DYNAMIC_BACKEND_9)  || \
+      defined(INVALID_TEST_DYNAMIC_BACKEND_10) || \
+      defined(INVALID_TEST_DYNAMIC_BACKEND_11)
 
 // The interface is correct, the corresponding invalid changes are in the TestDynamicBackend.cpp file
 const char* GetBackendId();