David Beck | 32cbb0c | 2018-10-09 15:46:08 +0100 | [diff] [blame] | 1 | // |
| 2 | // Copyright © 2017 Arm Ltd. All rights reserved. |
| 3 | // SPDX-License-Identifier: MIT |
| 4 | // |
David Beck | 32cbb0c | 2018-10-09 15:46:08 +0100 | [diff] [blame] | 5 | |
David Beck | 32cbb0c | 2018-10-09 15:46:08 +0100 | [diff] [blame] | 6 | #include <armnn/Types.hpp> |
Matteo Martincigh | c601aa6 | 2019-10-29 15:03:22 +0000 | [diff] [blame] | 7 | #include <armnn/BackendRegistry.hpp> |
David Beck | 32cbb0c | 2018-10-09 15:46:08 +0100 | [diff] [blame] | 8 | |
Matteo Martincigh | e5b8eb9 | 2019-11-28 15:45:42 +0000 | [diff] [blame] | 9 | #include <armnn/backends/IBackendInternal.hpp> |
Francis Murtagh | 5dc64fe | 2021-01-25 10:18:10 +0000 | [diff] [blame] | 10 | #include <reference/RefBackend.hpp> |
Aron Virginas-Tar | c9cc804 | 2018-11-01 16:15:57 +0000 | [diff] [blame] | 11 | |
Sadik Armagan | 1625efc | 2021-06-10 18:24:34 +0100 | [diff] [blame] | 12 | #include <doctest/doctest.h> |
Aron Virginas-Tar | c9cc804 | 2018-11-01 16:15:57 +0000 | [diff] [blame] | 13 | |
David Beck | 32cbb0c | 2018-10-09 15:46:08 +0100 | [diff] [blame] | 14 | namespace |
| 15 | { |
| 16 | |
| 17 | class SwapRegistryStorage : public armnn::BackendRegistry |
| 18 | { |
| 19 | public: |
| 20 | SwapRegistryStorage() : armnn::BackendRegistry() |
| 21 | { |
David Beck | 3e9e115 | 2018-10-17 14:17:50 +0100 | [diff] [blame] | 22 | Swap(armnn::BackendRegistryInstance(), m_TempStorage); |
David Beck | 32cbb0c | 2018-10-09 15:46:08 +0100 | [diff] [blame] | 23 | } |
| 24 | |
| 25 | ~SwapRegistryStorage() |
| 26 | { |
David Beck | 3e9e115 | 2018-10-17 14:17:50 +0100 | [diff] [blame] | 27 | Swap(armnn::BackendRegistryInstance(),m_TempStorage); |
David Beck | 32cbb0c | 2018-10-09 15:46:08 +0100 | [diff] [blame] | 28 | } |
| 29 | |
| 30 | private: |
David Beck | 3e9e115 | 2018-10-17 14:17:50 +0100 | [diff] [blame] | 31 | FactoryStorage m_TempStorage; |
David Beck | 32cbb0c | 2018-10-09 15:46:08 +0100 | [diff] [blame] | 32 | }; |
| 33 | |
| 34 | } |
| 35 | |
Sadik Armagan | 1625efc | 2021-06-10 18:24:34 +0100 | [diff] [blame] | 36 | TEST_SUITE("BackendRegistryTests") |
| 37 | { |
| 38 | TEST_CASE("SwapRegistry") |
David Beck | 32cbb0c | 2018-10-09 15:46:08 +0100 | [diff] [blame] | 39 | { |
David Beck | 3e9e115 | 2018-10-17 14:17:50 +0100 | [diff] [blame] | 40 | using namespace armnn; |
| 41 | auto nFactories = BackendRegistryInstance().Size(); |
David Beck | 32cbb0c | 2018-10-09 15:46:08 +0100 | [diff] [blame] | 42 | { |
| 43 | SwapRegistryStorage helper; |
Sadik Armagan | 1625efc | 2021-06-10 18:24:34 +0100 | [diff] [blame] | 44 | CHECK(BackendRegistryInstance().Size() == 0); |
David Beck | 32cbb0c | 2018-10-09 15:46:08 +0100 | [diff] [blame] | 45 | } |
Sadik Armagan | 1625efc | 2021-06-10 18:24:34 +0100 | [diff] [blame] | 46 | CHECK(BackendRegistryInstance().Size() == nFactories); |
David Beck | 32cbb0c | 2018-10-09 15:46:08 +0100 | [diff] [blame] | 47 | } |
| 48 | |
Sadik Armagan | 1625efc | 2021-06-10 18:24:34 +0100 | [diff] [blame] | 49 | TEST_CASE("TestRegistryHelper") |
David Beck | 32cbb0c | 2018-10-09 15:46:08 +0100 | [diff] [blame] | 50 | { |
David Beck | 3e9e115 | 2018-10-17 14:17:50 +0100 | [diff] [blame] | 51 | using namespace armnn; |
David Beck | 32cbb0c | 2018-10-09 15:46:08 +0100 | [diff] [blame] | 52 | SwapRegistryStorage helper; |
| 53 | |
| 54 | bool called = false; |
David Beck | 3e9e115 | 2018-10-17 14:17:50 +0100 | [diff] [blame] | 55 | |
David Beck | 111b5d9 | 2018-11-12 14:59:37 +0000 | [diff] [blame] | 56 | BackendRegistry::StaticRegistryInitializer factoryHelper( |
David Beck | 3e9e115 | 2018-10-17 14:17:50 +0100 | [diff] [blame] | 57 | BackendRegistryInstance(), |
| 58 | "HelloWorld", |
David Beck | 9efb57d | 2018-11-05 13:40:33 +0000 | [diff] [blame] | 59 | [&called]() |
David Beck | 3e9e115 | 2018-10-17 14:17:50 +0100 | [diff] [blame] | 60 | { |
| 61 | called = true; |
David Beck | 29c75de | 2018-10-23 13:35:58 +0100 | [diff] [blame] | 62 | return armnn::IBackendInternalUniquePtr(nullptr); |
David Beck | 3e9e115 | 2018-10-17 14:17:50 +0100 | [diff] [blame] | 63 | } |
| 64 | ); |
David Beck | 32cbb0c | 2018-10-09 15:46:08 +0100 | [diff] [blame] | 65 | |
| 66 | // sanity check: the factory has not been called yet |
Sadik Armagan | 1625efc | 2021-06-10 18:24:34 +0100 | [diff] [blame] | 67 | CHECK(called == false); |
David Beck | 32cbb0c | 2018-10-09 15:46:08 +0100 | [diff] [blame] | 68 | |
David Beck | 3e9e115 | 2018-10-17 14:17:50 +0100 | [diff] [blame] | 69 | auto factoryFunction = BackendRegistryInstance().GetFactory("HelloWorld"); |
David Beck | 32cbb0c | 2018-10-09 15:46:08 +0100 | [diff] [blame] | 70 | |
| 71 | // sanity check: the factory still not called |
Sadik Armagan | 1625efc | 2021-06-10 18:24:34 +0100 | [diff] [blame] | 72 | CHECK(called == false); |
David Beck | 32cbb0c | 2018-10-09 15:46:08 +0100 | [diff] [blame] | 73 | |
David Beck | 9efb57d | 2018-11-05 13:40:33 +0000 | [diff] [blame] | 74 | factoryFunction(); |
Sadik Armagan | 1625efc | 2021-06-10 18:24:34 +0100 | [diff] [blame] | 75 | CHECK(called == true); |
David Monahan | c1536d6 | 2020-02-12 15:52:35 +0000 | [diff] [blame] | 76 | BackendRegistryInstance().Deregister("HelloWorld"); |
David Beck | 32cbb0c | 2018-10-09 15:46:08 +0100 | [diff] [blame] | 77 | } |
| 78 | |
Sadik Armagan | 1625efc | 2021-06-10 18:24:34 +0100 | [diff] [blame] | 79 | TEST_CASE("TestDirectCallToRegistry") |
David Beck | 32cbb0c | 2018-10-09 15:46:08 +0100 | [diff] [blame] | 80 | { |
David Beck | 3e9e115 | 2018-10-17 14:17:50 +0100 | [diff] [blame] | 81 | using namespace armnn; |
David Beck | 32cbb0c | 2018-10-09 15:46:08 +0100 | [diff] [blame] | 82 | SwapRegistryStorage helper; |
| 83 | |
| 84 | bool called = false; |
David Beck | 3e9e115 | 2018-10-17 14:17:50 +0100 | [diff] [blame] | 85 | BackendRegistryInstance().Register( |
| 86 | "HelloWorld", |
David Beck | 9efb57d | 2018-11-05 13:40:33 +0000 | [diff] [blame] | 87 | [&called]() |
David Beck | 3e9e115 | 2018-10-17 14:17:50 +0100 | [diff] [blame] | 88 | { |
| 89 | called = true; |
David Beck | 29c75de | 2018-10-23 13:35:58 +0100 | [diff] [blame] | 90 | return armnn::IBackendInternalUniquePtr(nullptr); |
David Beck | 3e9e115 | 2018-10-17 14:17:50 +0100 | [diff] [blame] | 91 | } |
| 92 | ); |
David Beck | 32cbb0c | 2018-10-09 15:46:08 +0100 | [diff] [blame] | 93 | |
| 94 | // sanity check: the factory has not been called yet |
Sadik Armagan | 1625efc | 2021-06-10 18:24:34 +0100 | [diff] [blame] | 95 | CHECK(called == false); |
David Beck | 32cbb0c | 2018-10-09 15:46:08 +0100 | [diff] [blame] | 96 | |
David Beck | 3e9e115 | 2018-10-17 14:17:50 +0100 | [diff] [blame] | 97 | auto factoryFunction = BackendRegistryInstance().GetFactory("HelloWorld"); |
David Beck | 32cbb0c | 2018-10-09 15:46:08 +0100 | [diff] [blame] | 98 | |
| 99 | // sanity check: the factory still not called |
Sadik Armagan | 1625efc | 2021-06-10 18:24:34 +0100 | [diff] [blame] | 100 | CHECK(called == false); |
David Beck | 32cbb0c | 2018-10-09 15:46:08 +0100 | [diff] [blame] | 101 | |
David Beck | 9efb57d | 2018-11-05 13:40:33 +0000 | [diff] [blame] | 102 | factoryFunction(); |
Sadik Armagan | 1625efc | 2021-06-10 18:24:34 +0100 | [diff] [blame] | 103 | CHECK(called == true); |
David Monahan | c1536d6 | 2020-02-12 15:52:35 +0000 | [diff] [blame] | 104 | BackendRegistryInstance().Deregister("HelloWorld"); |
David Beck | 32cbb0c | 2018-10-09 15:46:08 +0100 | [diff] [blame] | 105 | } |
| 106 | |
Francis Murtagh | 5dc64fe | 2021-01-25 10:18:10 +0000 | [diff] [blame] | 107 | // 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 Armagan | 1625efc | 2021-06-10 18:24:34 +0100 | [diff] [blame] | 114 | TEST_CASE("ThrowBackendUnavailableException") |
Francis Murtagh | 5dc64fe | 2021-01-25 10:18:10 +0000 | [diff] [blame] | 115 | { |
| 116 | using namespace armnn; |
| 117 | |
| 118 | const BackendId mockBackendId("MockDynamicBackend"); |
| 119 | |
| 120 | const std::string exceptionMessage("Neon support not found on device, could not register CpuAcc Backend.\n"); |
| 121 | |
| 122 | // Register the mock backend with a factory function lambda equivalent to NeonRegisterInitializer |
| 123 | BackendRegistryInstance().Register(mockBackendId, |
| 124 | [exceptionMessage]() |
| 125 | { |
| 126 | if (false) |
| 127 | { |
| 128 | return IBackendInternalUniquePtr(new RefBackend); |
| 129 | } |
| 130 | ARMNN_LOG(info) << "Neon support not found on device, could not register CpuAcc Backend."; |
| 131 | throw armnn::BackendUnavailableException(exceptionMessage); |
| 132 | }); |
| 133 | |
| 134 | // Get the factory function of the mock backend |
| 135 | auto factoryFunc = BackendRegistryInstance().GetFactory(mockBackendId); |
| 136 | |
| 137 | try |
| 138 | { |
| 139 | // Call the factory function as done during runtime backend registering |
| 140 | auto backend = factoryFunc(); |
| 141 | } |
| 142 | catch (const BackendUnavailableException& e) |
| 143 | { |
| 144 | // Caught |
Sadik Armagan | 1625efc | 2021-06-10 18:24:34 +0100 | [diff] [blame] | 145 | CHECK_EQ(e.what(), exceptionMessage); |
| 146 | MESSAGE("ThrowBackendUnavailableExceptionImpl: BackendUnavailableException caught."); |
Francis Murtagh | 5dc64fe | 2021-01-25 10:18:10 +0000 | [diff] [blame] | 147 | } |
| 148 | } |
| 149 | |
Sadik Armagan | 1625efc | 2021-06-10 18:24:34 +0100 | [diff] [blame] | 150 | } |