blob: ba407d29082a69125654691e3d080b54c370c454 [file] [log] [blame]
David Beck32cbb0c2018-10-09 15:46:08 +01001//
2// Copyright © 2017 Arm Ltd. All rights reserved.
3// SPDX-License-Identifier: MIT
4//
David Beck32cbb0c2018-10-09 15:46:08 +01005
David Beck32cbb0c2018-10-09 15:46:08 +01006#include <armnn/Types.hpp>
Matteo Martincighc601aa62019-10-29 15:03:22 +00007#include <armnn/BackendRegistry.hpp>
David Beck32cbb0c2018-10-09 15:46:08 +01008
Matteo Martincighe5b8eb92019-11-28 15:45:42 +00009#include <armnn/backends/IBackendInternal.hpp>
Francis Murtagh5dc64fe2021-01-25 10:18:10 +000010#include <reference/RefBackend.hpp>
Aron Virginas-Tarc9cc8042018-11-01 16:15:57 +000011
Sadik Armagan1625efc2021-06-10 18:24:34 +010012#include <doctest/doctest.h>
Aron Virginas-Tarc9cc8042018-11-01 16:15:57 +000013
David Beck32cbb0c2018-10-09 15:46:08 +010014namespace
15{
16
17class SwapRegistryStorage : public armnn::BackendRegistry
18{
19public:
20 SwapRegistryStorage() : armnn::BackendRegistry()
21 {
David Beck3e9e1152018-10-17 14:17:50 +010022 Swap(armnn::BackendRegistryInstance(), m_TempStorage);
David Beck32cbb0c2018-10-09 15:46:08 +010023 }
24
25 ~SwapRegistryStorage()
26 {
David Beck3e9e1152018-10-17 14:17:50 +010027 Swap(armnn::BackendRegistryInstance(),m_TempStorage);
David Beck32cbb0c2018-10-09 15:46:08 +010028 }
29
30private:
David Beck3e9e1152018-10-17 14:17:50 +010031 FactoryStorage m_TempStorage;
David Beck32cbb0c2018-10-09 15:46:08 +010032};
33
34}
35
Sadik Armagan1625efc2021-06-10 18:24:34 +010036TEST_SUITE("BackendRegistryTests")
37{
38TEST_CASE("SwapRegistry")
David Beck32cbb0c2018-10-09 15:46:08 +010039{
David Beck3e9e1152018-10-17 14:17:50 +010040 using namespace armnn;
41 auto nFactories = BackendRegistryInstance().Size();
David Beck32cbb0c2018-10-09 15:46:08 +010042 {
43 SwapRegistryStorage helper;
Sadik Armagan1625efc2021-06-10 18:24:34 +010044 CHECK(BackendRegistryInstance().Size() == 0);
David Beck32cbb0c2018-10-09 15:46:08 +010045 }
Sadik Armagan1625efc2021-06-10 18:24:34 +010046 CHECK(BackendRegistryInstance().Size() == nFactories);
David Beck32cbb0c2018-10-09 15:46:08 +010047}
48
Sadik Armagan1625efc2021-06-10 18:24:34 +010049TEST_CASE("TestRegistryHelper")
David Beck32cbb0c2018-10-09 15:46:08 +010050{
David Beck3e9e1152018-10-17 14:17:50 +010051 using namespace armnn;
David Beck32cbb0c2018-10-09 15:46:08 +010052 SwapRegistryStorage helper;
53
54 bool called = false;
David Beck3e9e1152018-10-17 14:17:50 +010055
David Beck111b5d92018-11-12 14:59:37 +000056 BackendRegistry::StaticRegistryInitializer factoryHelper(
David Beck3e9e1152018-10-17 14:17:50 +010057 BackendRegistryInstance(),
58 "HelloWorld",
David Beck9efb57d2018-11-05 13:40:33 +000059 [&called]()
David Beck3e9e1152018-10-17 14:17:50 +010060 {
61 called = true;
David Beck29c75de2018-10-23 13:35:58 +010062 return armnn::IBackendInternalUniquePtr(nullptr);
David Beck3e9e1152018-10-17 14:17:50 +010063 }
64 );
David Beck32cbb0c2018-10-09 15:46:08 +010065
66 // sanity check: the factory has not been called yet
Sadik Armagan1625efc2021-06-10 18:24:34 +010067 CHECK(called == false);
David Beck32cbb0c2018-10-09 15:46:08 +010068
David Beck3e9e1152018-10-17 14:17:50 +010069 auto factoryFunction = BackendRegistryInstance().GetFactory("HelloWorld");
David Beck32cbb0c2018-10-09 15:46:08 +010070
71 // sanity check: the factory still not called
Sadik Armagan1625efc2021-06-10 18:24:34 +010072 CHECK(called == false);
David Beck32cbb0c2018-10-09 15:46:08 +010073
David Beck9efb57d2018-11-05 13:40:33 +000074 factoryFunction();
Sadik Armagan1625efc2021-06-10 18:24:34 +010075 CHECK(called == true);
David Monahanc1536d62020-02-12 15:52:35 +000076 BackendRegistryInstance().Deregister("HelloWorld");
David Beck32cbb0c2018-10-09 15:46:08 +010077}
78
Sadik Armagan1625efc2021-06-10 18:24:34 +010079TEST_CASE("TestDirectCallToRegistry")
David Beck32cbb0c2018-10-09 15:46:08 +010080{
David Beck3e9e1152018-10-17 14:17:50 +010081 using namespace armnn;
David Beck32cbb0c2018-10-09 15:46:08 +010082 SwapRegistryStorage helper;
83
84 bool called = false;
David Beck3e9e1152018-10-17 14:17:50 +010085 BackendRegistryInstance().Register(
86 "HelloWorld",
David Beck9efb57d2018-11-05 13:40:33 +000087 [&called]()
David Beck3e9e1152018-10-17 14:17:50 +010088 {
89 called = true;
David Beck29c75de2018-10-23 13:35:58 +010090 return armnn::IBackendInternalUniquePtr(nullptr);
David Beck3e9e1152018-10-17 14:17:50 +010091 }
92 );
David Beck32cbb0c2018-10-09 15:46:08 +010093
94 // sanity check: the factory has not been called yet
Sadik Armagan1625efc2021-06-10 18:24:34 +010095 CHECK(called == false);
David Beck32cbb0c2018-10-09 15:46:08 +010096
David Beck3e9e1152018-10-17 14:17:50 +010097 auto factoryFunction = BackendRegistryInstance().GetFactory("HelloWorld");
David Beck32cbb0c2018-10-09 15:46:08 +010098
99 // sanity check: the factory still not called
Sadik Armagan1625efc2021-06-10 18:24:34 +0100100 CHECK(called == false);
David Beck32cbb0c2018-10-09 15:46:08 +0100101
David Beck9efb57d2018-11-05 13:40:33 +0000102 factoryFunction();
Sadik Armagan1625efc2021-06-10 18:24:34 +0100103 CHECK(called == true);
David Monahanc1536d62020-02-12 15:52:35 +0000104 BackendRegistryInstance().Deregister("HelloWorld");
David Beck32cbb0c2018-10-09 15:46:08 +0100105}
106
Francis Murtagh5dc64fe2021-01-25 10:18:10 +0000107// Test that backends can throw exceptions during their factory function to prevent loading in an unsuitable
108// environment. For example Neon Backend loading on armhf device without neon support.
109// In reality the dynamic backend is loaded in during the LoadDynamicBackends(options.m_DynamicBackendsPath)
110// step of runtime constructor, then the factory function is called to check if supported, in case
111// of Neon not being detected the exception is raised and so the backend is not added to the supportedBackends
112// list
113
Sadik Armagan1625efc2021-06-10 18:24:34 +0100114TEST_CASE("ThrowBackendUnavailableException")
Francis Murtagh5dc64fe2021-01-25 10:18:10 +0000115{
116 using namespace armnn;
117
118 const BackendId mockBackendId("MockDynamicBackend");
119
Matthew Benthama369b892021-07-05 09:20:23 +0100120 const std::string exceptionMessage("Mock error message to test unavailable backend");
Francis Murtagh5dc64fe2021-01-25 10:18:10 +0000121
Matthew Benthama369b892021-07-05 09:20:23 +0100122 // Register the mock backend with a factory function lambda that always throws
Francis Murtagh5dc64fe2021-01-25 10:18:10 +0000123 BackendRegistryInstance().Register(mockBackendId,
124 [exceptionMessage]()
125 {
Francis Murtagh5dc64fe2021-01-25 10:18:10 +0000126 throw armnn::BackendUnavailableException(exceptionMessage);
Matthew Benthama369b892021-07-05 09:20:23 +0100127 return IBackendInternalUniquePtr(); // Satisfy return type
Francis Murtagh5dc64fe2021-01-25 10:18:10 +0000128 });
129
130 // Get the factory function of the mock backend
131 auto factoryFunc = BackendRegistryInstance().GetFactory(mockBackendId);
132
133 try
134 {
135 // Call the factory function as done during runtime backend registering
136 auto backend = factoryFunc();
Matthew Benthama369b892021-07-05 09:20:23 +0100137 FAIL("Expected exception to have been thrown");
Francis Murtagh5dc64fe2021-01-25 10:18:10 +0000138 }
139 catch (const BackendUnavailableException& e)
140 {
141 // Caught
Sadik Armagan1625efc2021-06-10 18:24:34 +0100142 CHECK_EQ(e.what(), exceptionMessage);
Francis Murtagh5dc64fe2021-01-25 10:18:10 +0000143 }
144}
145
Sadik Armagan1625efc2021-06-10 18:24:34 +0100146}