blob: a55146e704a8c5e9a58d07ad5321228f96e43413 [file] [log] [blame]
Matteo Martincighac60d282019-07-25 15:25:44 +01001//
Mike Kelly1ec5f852023-04-05 12:51:10 +01002// Copyright © 2019-2023 Arm Ltd and Contributors. All rights reserved.
Matteo Martincighac60d282019-07-25 15:25:44 +01003// SPDX-License-Identifier: MIT
4//
5
6#pragma once
7
Matteo Martincighe5b8eb92019-11-28 15:45:42 +00008#include <armnn/BackendRegistry.hpp>
Matteo Martincighe5b8eb92019-11-28 15:45:42 +00009#include <armnn/backends/DynamicBackend.hpp>
Francis Murtaghcae45682021-04-26 10:07:49 +010010#include <armnn/backends/ILayerSupport.hpp>
Jan Eilersbb446e52020-04-02 13:56:54 +010011#include <armnn/utility/PolymorphicDowncast.hpp>
Jan Eilersbb446e52020-04-02 13:56:54 +010012#include <backendsCommon/DynamicBackendUtils.hpp>
Colm Donelan0c479742021-12-10 12:43:54 +000013#include <armnn/backends/TensorHandle.hpp>
Rob Hughes9542f902021-07-14 09:48:54 +010014#include <armnnUtils/Filesystem.hpp>
Matteo Martincigh4e73b422019-08-08 13:46:32 +010015#include <reference/workloads/RefConvolution2dWorkload.hpp>
Matteo Martincigh3d8a9ed2019-08-08 10:49:03 +010016#include <Runtime.hpp>
17
Matteo Martincighbc2e2102019-07-24 14:56:13 +010018#include <string>
19#include <memory>
Matteo Martincigh986c1862019-07-26 15:12:47 +010020
Sadik Armagan1625efc2021-06-10 18:24:34 +010021#include <doctest/doctest.h>
22
23#if defined(_MSC_VER)
24#include <Windows.h>
25#endif
Matteo Martincigh986c1862019-07-26 15:12:47 +010026
Colm Donelanaa93d982020-06-28 08:16:46 +010027#if !defined(DYNAMIC_BACKEND_BUILD_DIR)
28#define DYNAMIC_BACKEND_BUILD_DIR fs::path("./")
29#endif
30
31static std::string g_TestDirCLI = "--dynamic-backend-build-dir";
Matteo Martincighd0dc7702019-08-01 17:09:03 +010032static std::string g_TestBaseDir = "src/backends/backendsCommon/test/";
Matteo Martincigh986c1862019-07-26 15:12:47 +010033
Matteo Martincighd0dc7702019-08-01 17:09:03 +010034static std::string g_TestSharedObjectSubDir = "testSharedObject/";
35static std::string g_TestDynamicBackendSubDir = "testDynamicBackend/";
36
37static std::string g_TestSharedObjectFileName = "libTestSharedObject.so";
38static std::string g_TestNoSharedObjectFileName = "libNoSharedObject.txt";
39
40static std::string g_TestValidTestDynamicBackendFileName = "libValidTestDynamicBackend.so";
41static std::string g_TestInvalidTestDynamicBackend1FileName = "libInvalidTestDynamicBackend1.so";
42static std::string g_TestInvalidTestDynamicBackend2FileName = "libInvalidTestDynamicBackend2.so";
43static std::string g_TestInvalidTestDynamicBackend3FileName = "libInvalidTestDynamicBackend3.so";
44static std::string g_TestInvalidTestDynamicBackend4FileName = "libInvalidTestDynamicBackend4.so";
45static std::string g_TestInvalidTestDynamicBackend5FileName = "libInvalidTestDynamicBackend5.so";
46static std::string g_TestInvalidTestDynamicBackend6FileName = "libInvalidTestDynamicBackend6.so";
47static std::string g_TestInvalidTestDynamicBackend7FileName = "libInvalidTestDynamicBackend7.so";
48
Matteo Martincighe54aa062019-08-05 14:12:11 +010049static std::string g_TestValidBackend2FileName = "Arm_TestValid2_backend.so";
50static std::string g_TestValidBackend3FileName = "Arm_TestValid3_backend.so";
51static std::string g_TestValidBackend4FileName = "Arm_TestValid4_backend.so";
Matteo Martincigh0c2b2892019-08-05 14:12:11 +010052static std::string g_TestValidBackend5FileName = "Arm_TestValid5_backend.so";
Matteo Martincighe54aa062019-08-05 14:12:11 +010053static std::string g_TestInvalidBackend8FileName = "Arm_TestInvalid8_backend.so";
54static std::string g_TestInvalidBackend9FileName = "Arm_TestInvalid9_backend.so";
Matteo Martincigh0c2b2892019-08-05 14:12:11 +010055static std::string g_TestInvalidBackend10FileName = "Arm_TestInvalid10_backend.so";
56static std::string g_TestInvalidBackend11FileName = "Arm_TestInvalid11_backend.so";
Matteo Martincighe54aa062019-08-05 14:12:11 +010057
Matteo Martincigh0c2b2892019-08-05 14:12:11 +010058static std::string g_TestDynamicBackendsSubDir1 = "backendsTestPath1/";
59static std::string g_TestDynamicBackendsSubDir2 = "backendsTestPath2/";
60static std::string g_TestDynamicBackendsSubDir3 = "backendsTestPath3/";
61static std::string g_TestDynamicBackendsSubDir4 = "backendsTestPath4/";
62static std::string g_TestDynamicBackendsSubDir5 = "backendsTestPath5/";
63static std::string g_TestDynamicBackendsSubDir6 = "backendsTestPath6/";
64static std::string g_TestDynamicBackendsSubDir7 = "backendsTestPath7/";
65static std::string g_TestDynamicBackendsSubDir8 = "backendsTestPath8/";
66static std::string g_TestDynamicBackendsSubDir9 = "backendsTestPath9/";
67
Matteo Martincigh4e73b422019-08-08 13:46:32 +010068static std::string g_DynamicBackendsBaseDir = "src/backends/dynamic";
69static std::string g_ReferenceDynamicBackendSubDir = "reference/";
70static std::string g_ReferenceBackendFileName = "Arm_CpuRef_backend.so";
71
Matteo Martincigh3d8a9ed2019-08-08 10:49:03 +010072// DynamicBackendUtils wrapper class used for testing (allows to directly invoke the protected methods)
Matteo Martincigh0c2b2892019-08-05 14:12:11 +010073class TestDynamicBackendUtils : public armnn::DynamicBackendUtils
74{
75public:
76 static bool IsBackendCompatibleTest(const armnn::BackendVersion& backendApiVersion,
77 const armnn::BackendVersion& backendVersion)
78 {
79 return IsBackendCompatibleImpl(backendApiVersion, backendVersion);
80 }
81
82 static std::vector<std::string> GetBackendPathsImplTest(const std::string& path)
83 {
84 return GetBackendPathsImpl(path);
85 }
86
Matteo Martincigh89533902019-08-15 12:08:06 +010087 static armnn::BackendIdSet RegisterDynamicBackendsImplTest(
88 armnn::BackendRegistry& backendRegistry,
89 const std::vector<armnn::DynamicBackendPtr>& dynamicBackends)
Matteo Martincigh0c2b2892019-08-05 14:12:11 +010090 {
Matteo Martincigh89533902019-08-15 12:08:06 +010091 return RegisterDynamicBackendsImpl(backendRegistry, dynamicBackends);
Matteo Martincigh0c2b2892019-08-05 14:12:11 +010092 }
93};
Matteo Martincighe7d44982019-08-05 12:16:47 +010094
Matteo Martincigh3d8a9ed2019-08-08 10:49:03 +010095// BackendRegistry wrapper class used for testing (swaps the underlying factory storage)
96class TestBackendRegistry : public armnn::BackendRegistry
97{
98public:
99 TestBackendRegistry() : armnn::BackendRegistry()
100 {
101 Swap(armnn::BackendRegistryInstance(), m_TempStorage);
102 }
103
104 ~TestBackendRegistry()
105 {
106 Swap(armnn::BackendRegistryInstance(), m_TempStorage);
107 }
108
109private:
110 FactoryStorage m_TempStorage;
111};
112
Sadik Armagan1625efc2021-06-10 18:24:34 +0100113#if defined(_MSC_VER)
114std::string GetUnitTestExecutablePath()
115{
116 char buffer[MAX_PATH] = "";
117 GetModuleFileNameA(NULL, buffer, MAX_PATH);
118 fs::path executablePath(buffer);
119 return executablePath.parent_path();
120}
121
122#else
123std::string GetUnitTestExecutablePath()
124{
125 char buffer[PATH_MAX] = "";
126 if (readlink("/proc/self/exe", buffer, PATH_MAX) != -1)
127 {
128 fs::path executablePath(buffer);
129 return executablePath.parent_path();
130 }
131 return "";
132}
133#endif
134
Matteo Martincigh4e73b422019-08-08 13:46:32 +0100135std::string GetBasePath(const std::string& basePath)
Matteo Martincigh986c1862019-07-26 15:12:47 +0100136{
Francis Murtagh532a29d2020-06-29 11:50:01 +0100137 using namespace fs;
Colm Donelanaa93d982020-06-28 08:16:46 +0100138 // What we're looking for here is the location of the UnitTests executable.
Sadik Armagan1625efc2021-06-10 18:24:34 +0100139 // Fall back value of current directory.
140 path programLocation = GetUnitTestExecutablePath();
141 if (!exists(programLocation))
Colm Donelanaa93d982020-06-28 08:16:46 +0100142 {
Sadik Armagan1625efc2021-06-10 18:24:34 +0100143 programLocation = DYNAMIC_BACKEND_BUILD_DIR;
Colm Donelanaa93d982020-06-28 08:16:46 +0100144 }
Sadik Armagan1625efc2021-06-10 18:24:34 +0100145
Colm Donelanaa93d982020-06-28 08:16:46 +0100146 // This is the base path from the build where the test libraries were built.
Matteo Martincigh4e73b422019-08-08 13:46:32 +0100147 path sharedObjectPath = programLocation.append(basePath);
Sadik Armagan1625efc2021-06-10 18:24:34 +0100148 REQUIRE_MESSAGE(exists(sharedObjectPath),
Jan Eilers13d2e0d2021-09-28 15:11:28 +0100149 ("Base path for shared objects does not exist: " + sharedObjectPath.string()));
Matteo Martincighd0dc7702019-08-01 17:09:03 +0100150 return sharedObjectPath.string();
151}
152
Matteo Martincigh4e73b422019-08-08 13:46:32 +0100153std::string GetTestDirectoryBasePath()
154{
155 return GetBasePath(g_TestBaseDir);
156}
157
158std::string GetDynamicBackendsBasePath()
159{
160 return GetBasePath(g_DynamicBackendsBaseDir);
161}
162
Matteo Martincighd0dc7702019-08-01 17:09:03 +0100163std::string GetTestSubDirectory(const std::string& subdir)
164{
Francis Murtagh532a29d2020-06-29 11:50:01 +0100165 using namespace fs;
Matteo Martincighd0dc7702019-08-01 17:09:03 +0100166
167 std::string testDynamicBackendsBaseDir = GetTestDirectoryBasePath();
168 path testDynamicBackendsBasePath(testDynamicBackendsBaseDir);
169 path testDynamicBackendsSubDir = testDynamicBackendsBasePath.append(subdir);
170 // Do not check that the sub-directory exists because for testing reasons we may use non-existing paths
171
172 return testDynamicBackendsSubDir.string();
173}
174
Matteo Martincigh4e73b422019-08-08 13:46:32 +0100175std::string GetTestSubDirectory(const std::string& basePath, const std::string& subdir)
176{
Francis Murtagh532a29d2020-06-29 11:50:01 +0100177 using namespace fs;
Matteo Martincigh4e73b422019-08-08 13:46:32 +0100178
179 path testDynamicBackendsBasePath(basePath);
180 path testDynamicBackendsSubDir = testDynamicBackendsBasePath.append(subdir);
181 // Do not check that the sub-directory exists because for testing reasons we may use non-existing paths
182
183 return testDynamicBackendsSubDir.string();
184}
185
Matteo Martincighd0dc7702019-08-01 17:09:03 +0100186std::string GetTestFilePath(const std::string& directory, const std::string& fileName)
187{
Francis Murtagh532a29d2020-06-29 11:50:01 +0100188 using namespace fs;
Matteo Martincighd0dc7702019-08-01 17:09:03 +0100189
190 path directoryPath(directory);
191 path fileNamePath = directoryPath.append(fileName);
Sadik Armagan1625efc2021-06-10 18:24:34 +0100192 CHECK(exists(fileNamePath));
Matteo Martincighd0dc7702019-08-01 17:09:03 +0100193
194 return fileNamePath.string();
Matteo Martincigh986c1862019-07-26 15:12:47 +0100195}
196
197void OpenCloseHandleTestImpl()
198{
199 using namespace armnn;
200
Matteo Martincighd0dc7702019-08-01 17:09:03 +0100201 std::string testSubDirectory = GetTestSubDirectory(g_TestSharedObjectSubDir);
202 std::string sharedObjectFilePath = GetTestFilePath(testSubDirectory, g_TestSharedObjectFileName);
Matteo Martincigh986c1862019-07-26 15:12:47 +0100203
204 void* sharedObjectHandle = nullptr;
Sadik Armagan1625efc2021-06-10 18:24:34 +0100205 CHECK_NOTHROW(sharedObjectHandle = DynamicBackendUtils::OpenHandle(sharedObjectFilePath));
206 CHECK((sharedObjectHandle != nullptr));
Matteo Martincigh986c1862019-07-26 15:12:47 +0100207
208 DynamicBackendUtils::CloseHandle(sharedObjectHandle);
209}
210
211void CloseInvalidHandleTestImpl()
212{
213 using namespace armnn;
214
215 // This calls must silently handle invalid handles and complete successfully (no segfaults, etc.)
216 DynamicBackendUtils::CloseHandle(nullptr);
217}
218
219void OpenEmptyFileNameTestImpl()
220{
221 using namespace armnn;
222
223 void* sharedObjectHandle = nullptr;
Sadik Armagan1625efc2021-06-10 18:24:34 +0100224 CHECK_THROWS_AS(sharedObjectHandle = DynamicBackendUtils::OpenHandle(""), RuntimeException);
225 CHECK((sharedObjectHandle == nullptr));
Matteo Martincigh986c1862019-07-26 15:12:47 +0100226}
227
228void OpenNotExistingFileTestImpl()
229{
230 using namespace armnn;
231
232 void* sharedObjectHandle = nullptr;
Sadik Armagan1625efc2021-06-10 18:24:34 +0100233 CHECK_THROWS_AS(sharedObjectHandle = DynamicBackendUtils::OpenHandle("NotExistingFileName"), RuntimeException);
234 CHECK((sharedObjectHandle == nullptr));
Matteo Martincigh986c1862019-07-26 15:12:47 +0100235}
236
237void OpenNotSharedObjectTestImpl()
238{
239 using namespace armnn;
240
Matteo Martincighd0dc7702019-08-01 17:09:03 +0100241 std::string testSubDirectory = GetTestSubDirectory(g_TestSharedObjectSubDir);
242 std::string notSharedObjectFilePath = GetTestFilePath(testSubDirectory, g_TestNoSharedObjectFileName);
Matteo Martincigh986c1862019-07-26 15:12:47 +0100243
244 void* sharedObjectHandle = nullptr;
Sadik Armagan1625efc2021-06-10 18:24:34 +0100245 CHECK_THROWS_AS(sharedObjectHandle = DynamicBackendUtils::OpenHandle(notSharedObjectFilePath), RuntimeException);
246 CHECK((sharedObjectHandle == nullptr));
Matteo Martincigh986c1862019-07-26 15:12:47 +0100247}
248
249void GetValidEntryPointTestImpl()
250{
251 using namespace armnn;
252
Matteo Martincighd0dc7702019-08-01 17:09:03 +0100253 std::string testSubDirectory = GetTestSubDirectory(g_TestSharedObjectSubDir);
254 std::string sharedObjectFilePath = GetTestFilePath(testSubDirectory, g_TestSharedObjectFileName);
Matteo Martincigh986c1862019-07-26 15:12:47 +0100255
256 void* sharedObjectHandle = nullptr;
Sadik Armagan1625efc2021-06-10 18:24:34 +0100257 CHECK_NOTHROW(sharedObjectHandle = DynamicBackendUtils::OpenHandle(sharedObjectFilePath));
258 CHECK((sharedObjectHandle != nullptr));
Matteo Martincigh986c1862019-07-26 15:12:47 +0100259
260 using TestFunctionType = int(*)(int);
261 TestFunctionType testFunctionPointer = nullptr;
Sadik Armagan1625efc2021-06-10 18:24:34 +0100262 CHECK_NOTHROW(testFunctionPointer = DynamicBackendUtils::GetEntryPoint<TestFunctionType>(sharedObjectHandle,
Matteo Martincigh986c1862019-07-26 15:12:47 +0100263 "TestFunction1"));
Sadik Armagan1625efc2021-06-10 18:24:34 +0100264 CHECK((testFunctionPointer != nullptr));
265 CHECK(testFunctionPointer(7) == 7);
Matteo Martincigh986c1862019-07-26 15:12:47 +0100266
267 DynamicBackendUtils::CloseHandle(sharedObjectHandle);
268}
269
270void GetNameMangledEntryPointTestImpl()
271{
272 using namespace armnn;
273
Matteo Martincighd0dc7702019-08-01 17:09:03 +0100274 std::string testSubDirectory = GetTestSubDirectory(g_TestSharedObjectSubDir);
275 std::string sharedObjectFilePath = GetTestFilePath(testSubDirectory, g_TestSharedObjectFileName);
Matteo Martincigh986c1862019-07-26 15:12:47 +0100276
277 void* sharedObjectHandle = nullptr;
Sadik Armagan1625efc2021-06-10 18:24:34 +0100278 CHECK_NOTHROW(sharedObjectHandle = DynamicBackendUtils::OpenHandle(sharedObjectFilePath));
279 CHECK((sharedObjectHandle != nullptr));
Matteo Martincigh986c1862019-07-26 15:12:47 +0100280
281 using TestFunctionType = int(*)(int);
282 TestFunctionType testFunctionPointer = nullptr;
Sadik Armagan1625efc2021-06-10 18:24:34 +0100283 CHECK_THROWS_AS(testFunctionPointer = DynamicBackendUtils::GetEntryPoint<TestFunctionType>(sharedObjectHandle,
Matteo Martincigh986c1862019-07-26 15:12:47 +0100284 "TestFunction2"),
285 RuntimeException);
Sadik Armagan1625efc2021-06-10 18:24:34 +0100286 CHECK((testFunctionPointer == nullptr));
Matteo Martincigh986c1862019-07-26 15:12:47 +0100287
288 DynamicBackendUtils::CloseHandle(sharedObjectHandle);
289}
290
291void GetNoExternEntryPointTestImpl()
292{
293 using namespace armnn;
294
Matteo Martincighd0dc7702019-08-01 17:09:03 +0100295 std::string testSubDirectory = GetTestSubDirectory(g_TestSharedObjectSubDir);
296 std::string sharedObjectFilePath = GetTestFilePath(testSubDirectory, g_TestSharedObjectFileName);
Matteo Martincigh986c1862019-07-26 15:12:47 +0100297
298 void* sharedObjectHandle = nullptr;
Sadik Armagan1625efc2021-06-10 18:24:34 +0100299 CHECK_NOTHROW(sharedObjectHandle = DynamicBackendUtils::OpenHandle(sharedObjectFilePath));
300 CHECK((sharedObjectHandle != nullptr));
Matteo Martincigh986c1862019-07-26 15:12:47 +0100301
302 using TestFunctionType = int(*)(int);
303 TestFunctionType testFunctionPointer = nullptr;
Sadik Armagan1625efc2021-06-10 18:24:34 +0100304 CHECK_THROWS_AS(testFunctionPointer = DynamicBackendUtils::GetEntryPoint<TestFunctionType>(sharedObjectHandle,
Matteo Martincigh986c1862019-07-26 15:12:47 +0100305 "TestFunction3"),
306 RuntimeException);
Sadik Armagan1625efc2021-06-10 18:24:34 +0100307 CHECK((testFunctionPointer == nullptr));
Matteo Martincigh986c1862019-07-26 15:12:47 +0100308
309 DynamicBackendUtils::CloseHandle(sharedObjectHandle);
310}
311
312void GetNotExistingEntryPointTestImpl()
313{
314 using namespace armnn;
315
Matteo Martincighd0dc7702019-08-01 17:09:03 +0100316 std::string testSubDirectory = GetTestSubDirectory(g_TestSharedObjectSubDir);
317 std::string sharedObjectFilePath = GetTestFilePath(testSubDirectory, g_TestSharedObjectFileName);
Matteo Martincigh986c1862019-07-26 15:12:47 +0100318
319 void* sharedObjectHandle = nullptr;
Sadik Armagan1625efc2021-06-10 18:24:34 +0100320 CHECK_NOTHROW(sharedObjectHandle = DynamicBackendUtils::OpenHandle(sharedObjectFilePath));
321 CHECK((sharedObjectHandle != nullptr));
Matteo Martincigh986c1862019-07-26 15:12:47 +0100322
323 using TestFunctionType = int(*)(int);
324 TestFunctionType testFunctionPointer = nullptr;
Sadik Armagan1625efc2021-06-10 18:24:34 +0100325 CHECK_THROWS_AS(testFunctionPointer = DynamicBackendUtils::GetEntryPoint<TestFunctionType>(sharedObjectHandle,
Matteo Martincigh986c1862019-07-26 15:12:47 +0100326 "TestFunction4"),
327 RuntimeException);
Sadik Armagan1625efc2021-06-10 18:24:34 +0100328 CHECK((testFunctionPointer == nullptr));
Matteo Martincigh986c1862019-07-26 15:12:47 +0100329
330 DynamicBackendUtils::CloseHandle(sharedObjectHandle);
331}
Matteo Martincighac60d282019-07-25 15:25:44 +0100332
333void BackendVersioningTestImpl()
334{
Matteo Martincigh986c1862019-07-26 15:12:47 +0100335 using namespace armnn;
336
Matteo Martincighac60d282019-07-25 15:25:44 +0100337 // The backend API version used for the tests
Matteo Martincigh986c1862019-07-26 15:12:47 +0100338 BackendVersion backendApiVersion{ 2, 4 };
Matteo Martincighac60d282019-07-25 15:25:44 +0100339
340 // Same backend and backend API versions are compatible with the backend API
Matteo Martincigh986c1862019-07-26 15:12:47 +0100341 BackendVersion sameBackendVersion{ 2, 4 };
Sadik Armagan1625efc2021-06-10 18:24:34 +0100342 CHECK(sameBackendVersion == backendApiVersion);
343 CHECK(sameBackendVersion <= backendApiVersion);
344 CHECK(TestDynamicBackendUtils::IsBackendCompatibleTest(backendApiVersion, sameBackendVersion) == true);
Matteo Martincighac60d282019-07-25 15:25:44 +0100345
346 // Backend versions that differ from the backend API version by major revision are not compatible
347 // with the backend API
Matteo Martincigh986c1862019-07-26 15:12:47 +0100348 BackendVersion laterMajorBackendVersion{ 3, 4 };
Sadik Armagan1625efc2021-06-10 18:24:34 +0100349 CHECK(!(laterMajorBackendVersion == backendApiVersion));
350 CHECK(!(laterMajorBackendVersion <= backendApiVersion));
351 CHECK(TestDynamicBackendUtils::IsBackendCompatibleTest(backendApiVersion, laterMajorBackendVersion) == false);
Matteo Martincighac60d282019-07-25 15:25:44 +0100352
Matteo Martincigh986c1862019-07-26 15:12:47 +0100353 BackendVersion earlierMajorBackendVersion{ 1, 4 };
Sadik Armagan1625efc2021-06-10 18:24:34 +0100354 CHECK(!(earlierMajorBackendVersion == backendApiVersion));
355 CHECK(earlierMajorBackendVersion <= backendApiVersion);
356 CHECK(TestDynamicBackendUtils::IsBackendCompatibleTest(backendApiVersion,
Matteo Martincighac60d282019-07-25 15:25:44 +0100357 earlierMajorBackendVersion) == false);
358
359 // Backend versions with the same major revision but later minor revision than
360 // the backend API version are not compatible with the backend API
Matteo Martincigh986c1862019-07-26 15:12:47 +0100361 BackendVersion laterMinorBackendVersion{ 2, 5 };
Sadik Armagan1625efc2021-06-10 18:24:34 +0100362 CHECK(!(laterMinorBackendVersion == backendApiVersion));
363 CHECK(!(laterMinorBackendVersion <= backendApiVersion));
364 CHECK(TestDynamicBackendUtils::IsBackendCompatibleTest(backendApiVersion, laterMinorBackendVersion) == false);
Matteo Martincighac60d282019-07-25 15:25:44 +0100365
366 // Backend versions with the same major revision but earlier minor revision than
367 // the backend API version are compatible with the backend API
Matteo Martincigh986c1862019-07-26 15:12:47 +0100368 BackendVersion earlierMinorBackendVersion{ 2, 3 };
Sadik Armagan1625efc2021-06-10 18:24:34 +0100369 CHECK(!(earlierMinorBackendVersion == backendApiVersion));
370 CHECK(earlierMinorBackendVersion <= backendApiVersion);
371 CHECK(TestDynamicBackendUtils::IsBackendCompatibleTest(backendApiVersion, earlierMinorBackendVersion) == true);
Matteo Martincighac60d282019-07-25 15:25:44 +0100372}
Matteo Martincighbc2e2102019-07-24 14:56:13 +0100373
David Monahan9e9c7f52020-09-03 09:02:52 +0100374#if defined(ARMNNREF_ENABLED)
Matteo Martincighbc2e2102019-07-24 14:56:13 +0100375void CreateValidDynamicBackendObjectTestImpl()
376{
377 // Valid shared object handle
378 // Correct name mangling
379 // Correct interface
380 // Correct backend implementation
381
382 using namespace armnn;
383
Matteo Martincighd0dc7702019-08-01 17:09:03 +0100384 std::string testSubDirectory = GetTestSubDirectory(g_TestDynamicBackendSubDir);
Colm Donelanf060b2e2020-06-16 17:14:51 +0100385
386 // We expect this path to exists so we can load a valid dynamic backend.
Sadik Armagan1625efc2021-06-10 18:24:34 +0100387 CHECK_MESSAGE(fs::exists(testSubDirectory),
Jan Eilers13d2e0d2021-09-28 15:11:28 +0100388 ("Base path for shared objects does not exist: " + testSubDirectory));
Colm Donelanf060b2e2020-06-16 17:14:51 +0100389
Matteo Martincighd0dc7702019-08-01 17:09:03 +0100390 std::string sharedObjectFilePath = GetTestFilePath(testSubDirectory, g_TestValidTestDynamicBackendFileName);
Matteo Martincighbc2e2102019-07-24 14:56:13 +0100391
392 void* sharedObjectHandle = nullptr;
Sadik Armagan1625efc2021-06-10 18:24:34 +0100393 CHECK_NOTHROW(sharedObjectHandle = DynamicBackendUtils::OpenHandle(sharedObjectFilePath));
394 CHECK((sharedObjectHandle != nullptr));
Matteo Martincighbc2e2102019-07-24 14:56:13 +0100395
Matteo Martincighe54aa062019-08-05 14:12:11 +0100396 DynamicBackendPtr dynamicBackend;
Sadik Armagan1625efc2021-06-10 18:24:34 +0100397 CHECK_NOTHROW(dynamicBackend.reset(new DynamicBackend(sharedObjectHandle)));
398 CHECK((dynamicBackend != nullptr));
Matteo Martincighbc2e2102019-07-24 14:56:13 +0100399
400 BackendId dynamicBackendId;
Sadik Armagan1625efc2021-06-10 18:24:34 +0100401 CHECK_NOTHROW(dynamicBackendId = dynamicBackend->GetBackendId());
402 CHECK((dynamicBackendId == "ValidTestDynamicBackend"));
Matteo Martincighbc2e2102019-07-24 14:56:13 +0100403
404 BackendVersion dynamicBackendVersion;
Sadik Armagan1625efc2021-06-10 18:24:34 +0100405 CHECK_NOTHROW(dynamicBackendVersion = dynamicBackend->GetBackendVersion());
406 CHECK((dynamicBackendVersion == IBackendInternal::GetApiVersion()));
Matteo Martincighbc2e2102019-07-24 14:56:13 +0100407
Matteo Martincigh0c2b2892019-08-05 14:12:11 +0100408 IBackendInternalUniquePtr dynamicBackendInstance1;
Sadik Armagan1625efc2021-06-10 18:24:34 +0100409 CHECK_NOTHROW(dynamicBackendInstance1 = dynamicBackend->GetBackend());
410 CHECK((dynamicBackendInstance1 != nullptr));
Matteo Martincighbc2e2102019-07-24 14:56:13 +0100411
Matteo Martincigh0c2b2892019-08-05 14:12:11 +0100412 BackendRegistry::FactoryFunction dynamicBackendFactoryFunction = nullptr;
Sadik Armagan1625efc2021-06-10 18:24:34 +0100413 CHECK_NOTHROW(dynamicBackendFactoryFunction = dynamicBackend->GetFactoryFunction());
414 CHECK((dynamicBackendFactoryFunction != nullptr));
Matteo Martincigh0c2b2892019-08-05 14:12:11 +0100415
416 IBackendInternalUniquePtr dynamicBackendInstance2;
Sadik Armagan1625efc2021-06-10 18:24:34 +0100417 CHECK_NOTHROW(dynamicBackendInstance2 = dynamicBackendFactoryFunction());
418 CHECK((dynamicBackendInstance2 != nullptr));
Matteo Martincigh0c2b2892019-08-05 14:12:11 +0100419
Sadik Armagan1625efc2021-06-10 18:24:34 +0100420 CHECK((dynamicBackendInstance1->GetId() == "ValidTestDynamicBackend"));
421 CHECK((dynamicBackendInstance2->GetId() == "ValidTestDynamicBackend"));
Matteo Martincighbc2e2102019-07-24 14:56:13 +0100422}
David Monahan9e9c7f52020-09-03 09:02:52 +0100423#endif
Matteo Martincighbc2e2102019-07-24 14:56:13 +0100424
425void CreateDynamicBackendObjectInvalidHandleTestImpl()
426{
427 // Invalid (null) shared object handle
428
429 using namespace armnn;
430
431 void* sharedObjectHandle = nullptr;
Matteo Martincighe54aa062019-08-05 14:12:11 +0100432 DynamicBackendPtr dynamicBackend;
Sadik Armagan1625efc2021-06-10 18:24:34 +0100433 CHECK_THROWS_AS(dynamicBackend.reset(new DynamicBackend(sharedObjectHandle)), InvalidArgumentException);
434 CHECK((dynamicBackend == nullptr));
Matteo Martincighbc2e2102019-07-24 14:56:13 +0100435}
436
437void CreateDynamicBackendObjectInvalidInterface1TestImpl()
438{
439 // Valid shared object handle
440 // Wrong (not C-style) name mangling
441
442 using namespace armnn;
443
Matteo Martincighd0dc7702019-08-01 17:09:03 +0100444 std::string testSubDirectory = GetTestSubDirectory(g_TestDynamicBackendSubDir);
445 std::string sharedObjectFilePath = GetTestFilePath(testSubDirectory, g_TestInvalidTestDynamicBackend1FileName);
Matteo Martincighbc2e2102019-07-24 14:56:13 +0100446
447 void* sharedObjectHandle = nullptr;
Sadik Armagan1625efc2021-06-10 18:24:34 +0100448 CHECK_NOTHROW(sharedObjectHandle = DynamicBackendUtils::OpenHandle(sharedObjectFilePath));
449 CHECK((sharedObjectHandle != nullptr));
Matteo Martincighbc2e2102019-07-24 14:56:13 +0100450
Matteo Martincighe54aa062019-08-05 14:12:11 +0100451 DynamicBackendPtr dynamicBackend;
Sadik Armagan1625efc2021-06-10 18:24:34 +0100452 CHECK_THROWS_AS(dynamicBackend.reset(new DynamicBackend(sharedObjectHandle)), RuntimeException);
453 CHECK((dynamicBackend == nullptr));
Matteo Martincighbc2e2102019-07-24 14:56:13 +0100454}
455
456void CreateDynamicBackendObjectInvalidInterface2TestImpl()
457{
458 // Valid shared object handle
459 // Correct name mangling
460 // Wrong interface (missing GetBackendId())
461
462 using namespace armnn;
463
Matteo Martincighd0dc7702019-08-01 17:09:03 +0100464 std::string testSubDirectory = GetTestSubDirectory(g_TestDynamicBackendSubDir);
465 std::string sharedObjectFilePath = GetTestFilePath(testSubDirectory, g_TestInvalidTestDynamicBackend2FileName);
Matteo Martincighbc2e2102019-07-24 14:56:13 +0100466
467 void* sharedObjectHandle = nullptr;
Sadik Armagan1625efc2021-06-10 18:24:34 +0100468 CHECK_NOTHROW(sharedObjectHandle = DynamicBackendUtils::OpenHandle(sharedObjectFilePath));
469 CHECK((sharedObjectHandle != nullptr));
Matteo Martincighbc2e2102019-07-24 14:56:13 +0100470
Matteo Martincighe54aa062019-08-05 14:12:11 +0100471 DynamicBackendPtr dynamicBackend;
Sadik Armagan1625efc2021-06-10 18:24:34 +0100472 CHECK_THROWS_AS(dynamicBackend.reset(new DynamicBackend(sharedObjectHandle)), RuntimeException);
473 CHECK((dynamicBackend == nullptr));
Matteo Martincighbc2e2102019-07-24 14:56:13 +0100474}
475
476void CreateDynamicBackendObjectInvalidInterface3TestImpl()
477{
478 // Valid shared object handle
479 // Correct name mangling
480 // Wrong interface (missing GetVersion())
481
482 using namespace armnn;
483
Matteo Martincighd0dc7702019-08-01 17:09:03 +0100484 std::string testSubDirectory = GetTestSubDirectory(g_TestDynamicBackendSubDir);
485 std::string sharedObjectFilePath = GetTestFilePath(testSubDirectory, g_TestInvalidTestDynamicBackend3FileName);
Matteo Martincighbc2e2102019-07-24 14:56:13 +0100486
487 void* sharedObjectHandle = nullptr;
Sadik Armagan1625efc2021-06-10 18:24:34 +0100488 CHECK_NOTHROW(sharedObjectHandle = DynamicBackendUtils::OpenHandle(sharedObjectFilePath));
489 CHECK((sharedObjectHandle != nullptr));
Matteo Martincighbc2e2102019-07-24 14:56:13 +0100490
Matteo Martincighe54aa062019-08-05 14:12:11 +0100491 DynamicBackendPtr dynamicBackend;
Sadik Armagan1625efc2021-06-10 18:24:34 +0100492 CHECK_THROWS_AS(dynamicBackend.reset(new DynamicBackend(sharedObjectHandle)), RuntimeException);
493 CHECK((dynamicBackend == nullptr));
Matteo Martincighbc2e2102019-07-24 14:56:13 +0100494}
495
496void CreateDynamicBackendObjectInvalidInterface4TestImpl()
497{
498 // Valid shared object handle
499 // Correct name mangling
500 // Wrong interface (missing BackendFactory())
501
502 using namespace armnn;
503
Matteo Martincighd0dc7702019-08-01 17:09:03 +0100504 std::string testSubDirectory = GetTestSubDirectory(g_TestDynamicBackendSubDir);
505 std::string sharedObjectFilePath = GetTestFilePath(testSubDirectory, g_TestInvalidTestDynamicBackend4FileName);
Matteo Martincighbc2e2102019-07-24 14:56:13 +0100506
507 void* sharedObjectHandle = nullptr;
Sadik Armagan1625efc2021-06-10 18:24:34 +0100508 CHECK_NOTHROW(sharedObjectHandle = DynamicBackendUtils::OpenHandle(sharedObjectFilePath));
509 CHECK((sharedObjectHandle != nullptr));
Matteo Martincighbc2e2102019-07-24 14:56:13 +0100510
Matteo Martincighe54aa062019-08-05 14:12:11 +0100511 DynamicBackendPtr dynamicBackend;
Sadik Armagan1625efc2021-06-10 18:24:34 +0100512 CHECK_THROWS_AS(dynamicBackend.reset(new DynamicBackend(sharedObjectHandle)), RuntimeException);
513 CHECK((dynamicBackend == nullptr));
Matteo Martincighbc2e2102019-07-24 14:56:13 +0100514}
515
516void CreateDynamicBackendObjectInvalidInterface5TestImpl()
517{
518 // Valid shared object handle
519 // Correct name mangling
520 // Correct interface
521 // Invalid (null) backend id returned by GetBackendId()
522
523 using namespace armnn;
524
Matteo Martincighd0dc7702019-08-01 17:09:03 +0100525 std::string testSubDirectory = GetTestSubDirectory(g_TestDynamicBackendSubDir);
526 std::string sharedObjectFilePath = GetTestFilePath(testSubDirectory, g_TestInvalidTestDynamicBackend5FileName);
Matteo Martincighbc2e2102019-07-24 14:56:13 +0100527
528 void* sharedObjectHandle = nullptr;
Sadik Armagan1625efc2021-06-10 18:24:34 +0100529 CHECK_NOTHROW(sharedObjectHandle = DynamicBackendUtils::OpenHandle(sharedObjectFilePath));
530 CHECK((sharedObjectHandle != nullptr));
Matteo Martincighbc2e2102019-07-24 14:56:13 +0100531
Matteo Martincighe54aa062019-08-05 14:12:11 +0100532 DynamicBackendPtr dynamicBackend;
Sadik Armagan1625efc2021-06-10 18:24:34 +0100533 CHECK_THROWS_AS(dynamicBackend.reset(new DynamicBackend(sharedObjectHandle)), RuntimeException);
534 CHECK((dynamicBackend == nullptr));
Matteo Martincighbc2e2102019-07-24 14:56:13 +0100535}
536
537void CreateDynamicBackendObjectInvalidInterface6TestImpl()
538{
539 // Valid shared object handle
540 // Correct name mangling
541 // Correct interface
542 // Invalid (null) backend instance returned by BackendFactory()
543
544 using namespace armnn;
545
Matteo Martincighd0dc7702019-08-01 17:09:03 +0100546 std::string testSubDirectory = GetTestSubDirectory(g_TestDynamicBackendSubDir);
547 std::string sharedObjectFilePath = GetTestFilePath(testSubDirectory, g_TestInvalidTestDynamicBackend6FileName);
Matteo Martincighbc2e2102019-07-24 14:56:13 +0100548
549 void* sharedObjectHandle = nullptr;
Sadik Armagan1625efc2021-06-10 18:24:34 +0100550 CHECK_NOTHROW(sharedObjectHandle = DynamicBackendUtils::OpenHandle(sharedObjectFilePath));
551 CHECK((sharedObjectHandle != nullptr));
Matteo Martincighbc2e2102019-07-24 14:56:13 +0100552
Matteo Martincighe54aa062019-08-05 14:12:11 +0100553 DynamicBackendPtr dynamicBackend;
Sadik Armagan1625efc2021-06-10 18:24:34 +0100554 CHECK_NOTHROW(dynamicBackend.reset(new DynamicBackend(sharedObjectHandle)));
555 CHECK((dynamicBackend != nullptr));
Matteo Martincighbc2e2102019-07-24 14:56:13 +0100556
557 BackendId dynamicBackendId;
Sadik Armagan1625efc2021-06-10 18:24:34 +0100558 CHECK_NOTHROW(dynamicBackendId = dynamicBackend->GetBackendId());
559 CHECK((dynamicBackendId == "InvalidTestDynamicBackend"));
Matteo Martincighbc2e2102019-07-24 14:56:13 +0100560
561 BackendVersion dynamicBackendVersion;
Sadik Armagan1625efc2021-06-10 18:24:34 +0100562 CHECK_NOTHROW(dynamicBackendVersion = dynamicBackend->GetBackendVersion());
Jan Eilers15fcc7e2021-07-14 13:50:15 +0100563 CHECK((dynamicBackendVersion >= BackendVersion({ 1, 0 })));
Matteo Martincighbc2e2102019-07-24 14:56:13 +0100564
Matteo Martincigh0c2b2892019-08-05 14:12:11 +0100565 IBackendInternalUniquePtr dynamicBackendInstance1;
Sadik Armagan1625efc2021-06-10 18:24:34 +0100566 CHECK_THROWS_AS(dynamicBackendInstance1 = dynamicBackend->GetBackend(), RuntimeException);
567 CHECK((dynamicBackendInstance1 == nullptr));
Matteo Martincigh0c2b2892019-08-05 14:12:11 +0100568
569 BackendRegistry::FactoryFunction dynamicBackendFactoryFunction = nullptr;
Sadik Armagan1625efc2021-06-10 18:24:34 +0100570 CHECK_NOTHROW(dynamicBackendFactoryFunction = dynamicBackend->GetFactoryFunction());
571 CHECK((dynamicBackendFactoryFunction != nullptr));
Matteo Martincigh0c2b2892019-08-05 14:12:11 +0100572
573 IBackendInternalUniquePtr dynamicBackendInstance2;
Sadik Armagan1625efc2021-06-10 18:24:34 +0100574 CHECK_THROWS_AS(dynamicBackendInstance2 = dynamicBackendFactoryFunction(), RuntimeException);
575 CHECK((dynamicBackendInstance2 == nullptr));
Matteo Martincighbc2e2102019-07-24 14:56:13 +0100576}
577
578void CreateDynamicBackendObjectInvalidInterface7TestImpl()
579{
580 // Valid shared object handle
581 // Correct name mangling
582 // Correct interface
583 // Invalid (incompatible backend API version) backend instance returned by BackendFactory()
584
585 using namespace armnn;
586
Matteo Martincighd0dc7702019-08-01 17:09:03 +0100587 std::string testSubDirectory = GetTestSubDirectory(g_TestDynamicBackendSubDir);
588 std::string sharedObjectFilePath = GetTestFilePath(testSubDirectory, g_TestInvalidTestDynamicBackend7FileName);
Matteo Martincighbc2e2102019-07-24 14:56:13 +0100589
590 void* sharedObjectHandle = nullptr;
Sadik Armagan1625efc2021-06-10 18:24:34 +0100591 CHECK_NOTHROW(sharedObjectHandle = DynamicBackendUtils::OpenHandle(sharedObjectFilePath));
592 CHECK((sharedObjectHandle != nullptr));
Matteo Martincighbc2e2102019-07-24 14:56:13 +0100593
Matteo Martincighe54aa062019-08-05 14:12:11 +0100594 DynamicBackendPtr dynamicBackend;
Sadik Armagan1625efc2021-06-10 18:24:34 +0100595 CHECK_THROWS_AS(dynamicBackend.reset(new DynamicBackend(sharedObjectHandle)), RuntimeException);
596 CHECK((dynamicBackend == nullptr));
Matteo Martincighbc2e2102019-07-24 14:56:13 +0100597}
Matteo Martincighe7d44982019-08-05 12:16:47 +0100598
599void GetBackendPathsTestImpl()
600{
601 using namespace armnn;
Francis Murtagh532a29d2020-06-29 11:50:01 +0100602 using namespace fs;
Matteo Martincighe7d44982019-08-05 12:16:47 +0100603
604 // The test covers four directories:
605 // <unit test path>/src/backends/backendsCommon/test/
Matteo Martincighe54aa062019-08-05 14:12:11 +0100606 // ├─ backendsTestPath1/ -> exists, contains files
607 // ├─ backendsTestPath2/ -> exists, contains files
608 // ├─ backendsTestPath3/ -> exists, but empty
609 // └─ backendsTestPath4/ -> does not exist
Matteo Martincighe7d44982019-08-05 12:16:47 +0100610
Matteo Martincigh0c2b2892019-08-05 14:12:11 +0100611 std::string subDir1 = GetTestSubDirectory(g_TestDynamicBackendsSubDir1);
612 std::string subDir2 = GetTestSubDirectory(g_TestDynamicBackendsSubDir2);
613 std::string subDir3 = GetTestSubDirectory(g_TestDynamicBackendsSubDir3);
614 std::string subDir4 = GetTestSubDirectory(g_TestDynamicBackendsSubDir4);
Matteo Martincighe7d44982019-08-05 12:16:47 +0100615
Sadik Armagan1625efc2021-06-10 18:24:34 +0100616 CHECK(exists(subDir1));
617 CHECK(exists(subDir2));
618 CHECK(exists(subDir3));
619 CHECK(!exists(subDir4));
Matteo Martincighe7d44982019-08-05 12:16:47 +0100620
Matteo Martincighe7d44982019-08-05 12:16:47 +0100621 // No path
Sadik Armagan1625efc2021-06-10 18:24:34 +0100622 CHECK(TestDynamicBackendUtils::GetBackendPathsImplTest("").empty());
Matteo Martincighe7d44982019-08-05 12:16:47 +0100623
624 // Malformed path
625 std::string malformedDir(subDir1 + "/" + subDir1);
Sadik Armagan1625efc2021-06-10 18:24:34 +0100626 CHECK(TestDynamicBackendUtils::GetBackendPathsImplTest(malformedDir).size()==0);
Matteo Martincighe7d44982019-08-05 12:16:47 +0100627
628 // Single valid path
629 std::vector<std::string> DynamicBackendPaths2 = TestDynamicBackendUtils::GetBackendPathsImplTest(subDir1);
Sadik Armagan1625efc2021-06-10 18:24:34 +0100630 CHECK(DynamicBackendPaths2.size() == 1);
631 CHECK(DynamicBackendPaths2[0] == subDir1);
Matteo Martincighe7d44982019-08-05 12:16:47 +0100632
633 // Multiple equal and valid paths
634 std::string multipleEqualDirs(subDir1 + ":" + subDir1);
635 std::vector<std::string> DynamicBackendPaths3 = TestDynamicBackendUtils::GetBackendPathsImplTest(multipleEqualDirs);
Sadik Armagan1625efc2021-06-10 18:24:34 +0100636 CHECK(DynamicBackendPaths3.size() == 1);
637 CHECK(DynamicBackendPaths3[0] == subDir1);
Matteo Martincighe7d44982019-08-05 12:16:47 +0100638
639 // Multiple empty paths
Sadik Armagan1625efc2021-06-10 18:24:34 +0100640 CHECK(TestDynamicBackendUtils::GetBackendPathsImplTest(":::").empty());
Matteo Martincighe7d44982019-08-05 12:16:47 +0100641
642 // Multiple valid paths
643 std::string multipleValidPaths(subDir1 + ":" + subDir2 + ":" + subDir3);
644 std::vector<std::string> DynamicBackendPaths5 =
645 TestDynamicBackendUtils::GetBackendPathsImplTest(multipleValidPaths);
Sadik Armagan1625efc2021-06-10 18:24:34 +0100646 CHECK(DynamicBackendPaths5.size() == 3);
647 CHECK(DynamicBackendPaths5[0] == subDir1);
648 CHECK(DynamicBackendPaths5[1] == subDir2);
649 CHECK(DynamicBackendPaths5[2] == subDir3);
Matteo Martincighe7d44982019-08-05 12:16:47 +0100650
651 // Valid among empty paths
652 std::string validAmongEmptyDirs("::" + subDir1 + ":");
653 std::vector<std::string> DynamicBackendPaths6 =
654 TestDynamicBackendUtils::GetBackendPathsImplTest(validAmongEmptyDirs);
Sadik Armagan1625efc2021-06-10 18:24:34 +0100655 CHECK(DynamicBackendPaths6.size() == 1);
656 CHECK(DynamicBackendPaths6[0] == subDir1);
Matteo Martincighe7d44982019-08-05 12:16:47 +0100657
658 // Invalid among empty paths
659 std::string invalidAmongEmptyDirs(":" + subDir4 + "::");
Sadik Armagan1625efc2021-06-10 18:24:34 +0100660 CHECK(TestDynamicBackendUtils::GetBackendPathsImplTest(invalidAmongEmptyDirs).empty());
Matteo Martincighe7d44982019-08-05 12:16:47 +0100661
662 // Valid, invalid and empty paths
663 std::string validInvalidEmptyDirs(subDir1 + ":" + subDir4 + ":");
664 std::vector<std::string> DynamicBackendPaths8 =
665 TestDynamicBackendUtils::GetBackendPathsImplTest(validInvalidEmptyDirs);
Sadik Armagan1625efc2021-06-10 18:24:34 +0100666 CHECK(DynamicBackendPaths8.size() == 1);
667 CHECK(DynamicBackendPaths8[0] == subDir1);
Matteo Martincighe7d44982019-08-05 12:16:47 +0100668
669 // Mix of duplicates of valid, invalid and empty paths
670 std::string duplicateValidInvalidEmptyDirs(validInvalidEmptyDirs + ":" + validInvalidEmptyDirs + ":" +
671 subDir2 + ":" + subDir2);
672 std::vector<std::string> DynamicBackendPaths9 =
673 TestDynamicBackendUtils::GetBackendPathsImplTest(duplicateValidInvalidEmptyDirs);
Sadik Armagan1625efc2021-06-10 18:24:34 +0100674 CHECK(DynamicBackendPaths9.size() == 2);
675 CHECK(DynamicBackendPaths9[0] == subDir1);
676 CHECK(DynamicBackendPaths9[1] == subDir2);
Matteo Martincighe7d44982019-08-05 12:16:47 +0100677}
678
679void GetBackendPathsOverrideTestImpl()
680{
681 using namespace armnn;
Francis Murtagh532a29d2020-06-29 11:50:01 +0100682 using namespace fs;
Matteo Martincighe7d44982019-08-05 12:16:47 +0100683
Matteo Martincigh0c2b2892019-08-05 14:12:11 +0100684 std::string subDir1 = GetTestSubDirectory(g_TestDynamicBackendsSubDir1);
685 std::string subDir4 = GetTestSubDirectory(g_TestDynamicBackendsSubDir4);
Matteo Martincighe7d44982019-08-05 12:16:47 +0100686
Sadik Armagan1625efc2021-06-10 18:24:34 +0100687 CHECK(exists(subDir1));
688 CHECK(!exists(subDir4));
Matteo Martincighe7d44982019-08-05 12:16:47 +0100689
690 // Override with valid path
691 std::vector<std::string> validResult = DynamicBackendUtils::GetBackendPaths(subDir1);
Sadik Armagan1625efc2021-06-10 18:24:34 +0100692 CHECK(validResult.size() == 1);
693 CHECK(validResult[0] == subDir1);
Matteo Martincighe7d44982019-08-05 12:16:47 +0100694
695 // Override with invalid path
696 std::vector<std::string> invalidResult = DynamicBackendUtils::GetBackendPaths(subDir4);
Sadik Armagan1625efc2021-06-10 18:24:34 +0100697 CHECK(invalidResult.empty());
Matteo Martincighe7d44982019-08-05 12:16:47 +0100698}
Jan Eilers4a539fc2019-07-25 17:08:37 +0100699
700void GetSharedObjectsTestImpl()
701{
702 using namespace armnn;
Francis Murtagh532a29d2020-06-29 11:50:01 +0100703 using namespace fs;
Jan Eilers4a539fc2019-07-25 17:08:37 +0100704
Matteo Martincighe54aa062019-08-05 14:12:11 +0100705 // The test covers four directories:
706 // <unit test path>/src/backends/backendsCommon/test/
707 // ├─ backendsTestPath1/ -> exists, contains files
708 // ├─ backendsTestPath2/ -> exists, contains files
709 // ├─ backendsTestPath3/ -> exists, but empty
710 // └─ backendsTestPath4/ -> does not exist
Jan Eilers4a539fc2019-07-25 17:08:37 +0100711 //
712 // The test sub-directory backendsTestPath1/ contains the following test files:
713 //
714 // Arm_GpuAcc_backend.so -> valid (basic backend name)
715 // Arm_GpuAcc_backend.so.1 -> valid (single field version number)
716 // Arm_GpuAcc_backend.so.1.2 -> valid (multiple field version number)
717 // Arm_GpuAcc_backend.so.1.2.3 -> valid (multiple field version number)
718 // Arm_GpuAcc_backend.so.10.1.27 -> valid (Multiple digit version)
719 // Arm_GpuAcc_backend.so.10.1.33. -> not valid (dot not followed by version number)
720 // Arm_GpuAcc_backend.so.3.4..5 -> not valid (dot not followed by version number)
721 // Arm_GpuAcc_backend.so.1,1.1 -> not valid (comma instead of dot in the version)
722 //
723 // Arm123_GpuAcc_backend.so -> valid (digits in vendor name are allowed)
724 // Arm_GpuAcc456_backend.so -> valid (digits in backend id are allowed)
725 // Arm%Co_GpuAcc_backend.so -> not valid (invalid character in vendor name)
726 // Arm_Gpu.Acc_backend.so -> not valid (invalid character in backend id)
727 //
728 // GpuAcc_backend.so -> not valid (missing vendor name)
729 // _GpuAcc_backend.so -> not valid (missing vendor name)
730 // Arm__backend.so -> not valid (missing backend id)
731 // Arm_GpuAcc.so -> not valid (missing "backend" at the end)
732 // __backend.so -> not valid (missing vendor name and backend id)
733 // __.so -> not valid (missing all fields)
734 //
735 // Arm_GpuAcc_backend -> not valid (missing at least ".so" at the end)
736 // Arm_GpuAcc_backend_v1.2.so -> not valid (extra version info at the end)
737 //
738 // The test sub-directory backendsTestPath1/ contains the following test files:
739 //
740 // Arm_CpuAcc_backend.so -> valid (basic backend name)
741 // Arm_CpuAcc_backend.so.1 -> Arm_CpuAcc_backend.so -> valid (symlink to valid backend file)
742 // Arm_CpuAcc_backend.so.1.2 -> Arm_CpuAcc_backend.so.1 -> valid (symlink to valid symlink)
743 // Arm_CpuAcc_backend.so.1.2.3 -> Arm_CpuAcc_backend.so.1.2 -> valid (symlink to valid symlink)
744 //
745 // Arm_no_backend.so -> nothing -> not valid (symlink resolves to non-existent file)
746 //
747 // Arm_GpuAcc_backend.so -> valid (but duplicated from backendsTestPath1/)
748
Matteo Martincigh0c2b2892019-08-05 14:12:11 +0100749 std::string testDynamicBackendsSubDir1 = GetTestSubDirectory(g_TestDynamicBackendsSubDir1);
750 std::string testDynamicBackendsSubDir2 = GetTestSubDirectory(g_TestDynamicBackendsSubDir2);
751 std::string testDynamicBackendsSubDir3 = GetTestSubDirectory(g_TestDynamicBackendsSubDir3);
752 std::string testDynamicBackendsSubDir4 = GetTestSubDirectory(g_TestDynamicBackendsSubDir4);
Sadik Armagan1625efc2021-06-10 18:24:34 +0100753 CHECK(exists(testDynamicBackendsSubDir1));
754 CHECK(exists(testDynamicBackendsSubDir2));
755 CHECK(exists(testDynamicBackendsSubDir3));
756 CHECK(!exists(testDynamicBackendsSubDir4));
Jan Eilers4a539fc2019-07-25 17:08:37 +0100757
758 std::vector<std::string> backendPaths
759 {
760 testDynamicBackendsSubDir1,
761 testDynamicBackendsSubDir2,
762 testDynamicBackendsSubDir3,
763 testDynamicBackendsSubDir4
764 };
765 std::vector<std::string> sharedObjects = DynamicBackendUtils::GetSharedObjects(backendPaths);
Colm Donelanaa93d982020-06-28 08:16:46 +0100766 std::vector<fs::path> expectedSharedObjects
Jan Eilers4a539fc2019-07-25 17:08:37 +0100767 {
Colm Donelanaa93d982020-06-28 08:16:46 +0100768 path(testDynamicBackendsSubDir1 + "Arm123_GpuAcc_backend.so"), // Digits in vendor name are allowed
769 path(testDynamicBackendsSubDir1 + "Arm_GpuAcc456_backend.so"), // Digits in backend id are allowed
770 path(testDynamicBackendsSubDir1 + "Arm_GpuAcc_backend.so"), // Basic backend name
771 path(testDynamicBackendsSubDir1 + "Arm_GpuAcc_backend.so.1"), // Single field version number
772 path(testDynamicBackendsSubDir1 + "Arm_GpuAcc_backend.so.1.2"), // Multiple field version number
773 path(testDynamicBackendsSubDir1 + "Arm_GpuAcc_backend.so.1.2.3"), // Multiple field version number
774 path(testDynamicBackendsSubDir1 + "Arm_GpuAcc_backend.so.10.1.27"), // Multiple digit version
775 path(testDynamicBackendsSubDir2 + "Arm_CpuAcc_backend.so"), // Duplicate symlinks removed
776 path(testDynamicBackendsSubDir2 + "Arm_GpuAcc_backend.so") // Duplicates on different paths are allowed
Jan Eilers4a539fc2019-07-25 17:08:37 +0100777 };
778
Sadik Armagan1625efc2021-06-10 18:24:34 +0100779 CHECK(sharedObjects.size() == expectedSharedObjects.size());
780 CHECK(fs::equivalent(path(sharedObjects[0]), expectedSharedObjects[0]));
781 CHECK(fs::equivalent(path(sharedObjects[1]), expectedSharedObjects[1]));
782 CHECK(fs::equivalent(path(sharedObjects[2]), expectedSharedObjects[2]));
783 CHECK(fs::equivalent(path(sharedObjects[3]), expectedSharedObjects[3]));
784 CHECK(fs::equivalent(path(sharedObjects[4]), expectedSharedObjects[4]));
785 CHECK(fs::equivalent(path(sharedObjects[5]), expectedSharedObjects[5]));
786 CHECK(fs::equivalent(path(sharedObjects[6]), expectedSharedObjects[6]));
787 CHECK(fs::equivalent(path(sharedObjects[7]), expectedSharedObjects[7]));
788 CHECK(fs::equivalent(path(sharedObjects[8]), expectedSharedObjects[8]));
Matteo Martincighe54aa062019-08-05 14:12:11 +0100789}
790
791void CreateDynamicBackendsTestImpl()
792{
793 using namespace armnn;
Francis Murtagh532a29d2020-06-29 11:50:01 +0100794 using namespace fs;
Matteo Martincighe54aa062019-08-05 14:12:11 +0100795
Matteo Martincigh0c2b2892019-08-05 14:12:11 +0100796 // The test covers four directories:
Matteo Martincighe54aa062019-08-05 14:12:11 +0100797 // <unit test path>/src/backends/backendsCommon/test/
798 // ├─ backendsTestPath5/ -> exists, contains files
799 // ├─ backendsTestPath6/ -> exists, contains files
800 // ├─ backendsTestPath7/ -> exists, but empty
801 // └─ backendsTestPath8/ -> does not exist
802 //
803 // The test sub-directory backendsTestPath5/ contains the following test files:
804 //
805 // Arm_TestValid2_backend.so -> valid (basic backend name)
806 // Arm_TestValid3_backend.so -> valid (basic backend name)
807 // Arm_TestInvalid8_backend.so -> not valid (invalid backend id)
808 //
809 // The test sub-directory backendsTestPath6/ contains the following test files:
810 //
811 // Arm_TestValid2_backend.so -> valid (but duplicated from backendsTestPath5/)
812 // Arm_TestValid4_backend.so -> valid (it has a different filename,
813 // but it has the same backend id of Arm_TestValid2_backend.so
814 // and the same version)
Matteo Martincigh0c2b2892019-08-05 14:12:11 +0100815 // Arm_TestValid5_backend.so -> valid (basic backend name)
Matteo Martincighe54aa062019-08-05 14:12:11 +0100816 // Arm_TestInvalid9_backend.so -> not valid (it has a different filename,
817 // but it has the same backend id of Arm_TestValid2_backend.so
818 // and a version incompatible with the Backend API)
819
Matteo Martincigh0c2b2892019-08-05 14:12:11 +0100820 std::string testDynamicBackendsSubDir5 = GetTestSubDirectory(g_TestDynamicBackendsSubDir5);
821 std::string testDynamicBackendsSubDir6 = GetTestSubDirectory(g_TestDynamicBackendsSubDir6);
822 std::string testDynamicBackendsSubDir7 = GetTestSubDirectory(g_TestDynamicBackendsSubDir7);
823 std::string testDynamicBackendsSubDir8 = GetTestSubDirectory(g_TestDynamicBackendsSubDir8);
Sadik Armagan1625efc2021-06-10 18:24:34 +0100824 CHECK(exists(testDynamicBackendsSubDir5));
825 CHECK(exists(testDynamicBackendsSubDir6));
826 CHECK(exists(testDynamicBackendsSubDir7));
827 CHECK(!exists(testDynamicBackendsSubDir8));
Matteo Martincighe54aa062019-08-05 14:12:11 +0100828
829 std::vector<std::string> backendPaths
Jan Eilers4a539fc2019-07-25 17:08:37 +0100830 {
Matteo Martincighe54aa062019-08-05 14:12:11 +0100831 testDynamicBackendsSubDir5,
832 testDynamicBackendsSubDir6,
833 testDynamicBackendsSubDir7,
834 testDynamicBackendsSubDir8
835 };
836 std::vector<std::string> sharedObjects = DynamicBackendUtils::GetSharedObjects(backendPaths);
837 std::vector<DynamicBackendPtr> dynamicBackends = DynamicBackendUtils::CreateDynamicBackends(sharedObjects);
838
Sadik Armagan1625efc2021-06-10 18:24:34 +0100839 CHECK(dynamicBackends.size() == 5);
840 CHECK((dynamicBackends[0] != nullptr));
841 CHECK((dynamicBackends[1] != nullptr));
842 CHECK((dynamicBackends[2] != nullptr));
843 CHECK((dynamicBackends[3] != nullptr));
844 CHECK((dynamicBackends[4] != nullptr));
Matteo Martincighe54aa062019-08-05 14:12:11 +0100845
846 // Duplicates are allowed here, they will be skipped later during the backend registration
Sadik Armagan1625efc2021-06-10 18:24:34 +0100847 CHECK((dynamicBackends[0]->GetBackendId() == "TestValid2"));
848 CHECK((dynamicBackends[1]->GetBackendId() == "TestValid3"));
849 CHECK((dynamicBackends[2]->GetBackendId() == "TestValid2")); // From duplicate Arm_TestValid2_backend.so
850 CHECK((dynamicBackends[3]->GetBackendId() == "TestValid2")); // From Arm_TestValid4_backend.so
851 CHECK((dynamicBackends[4]->GetBackendId() == "TestValid5"));
Matteo Martincighe54aa062019-08-05 14:12:11 +0100852}
853
854void CreateDynamicBackendsNoPathsTestImpl()
855{
856 using namespace armnn;
857
858 std::vector<DynamicBackendPtr> dynamicBackends = DynamicBackendUtils::CreateDynamicBackends({});
859
Sadik Armagan1625efc2021-06-10 18:24:34 +0100860 CHECK(dynamicBackends.empty());
Matteo Martincighe54aa062019-08-05 14:12:11 +0100861}
862
863void CreateDynamicBackendsAllInvalidTestImpl()
864{
865 using namespace armnn;
866
867 std::vector<std::string> sharedObjects
868 {
869 "InvalidSharedObject1",
870 "InvalidSharedObject2",
871 "InvalidSharedObject3",
872 };
873 std::vector<DynamicBackendPtr> dynamicBackends = DynamicBackendUtils::CreateDynamicBackends(sharedObjects);
874
Sadik Armagan1625efc2021-06-10 18:24:34 +0100875 CHECK(dynamicBackends.empty());
Matteo Martincighe54aa062019-08-05 14:12:11 +0100876}
877
878void CreateDynamicBackendsMixedTypesTestImpl()
879{
880 using namespace armnn;
Francis Murtagh532a29d2020-06-29 11:50:01 +0100881 using namespace fs;
Matteo Martincighe54aa062019-08-05 14:12:11 +0100882
Matteo Martincigh0c2b2892019-08-05 14:12:11 +0100883 std::string testDynamicBackendsSubDir5 = GetTestSubDirectory(g_TestDynamicBackendsSubDir5);
884 std::string testDynamicBackendsSubDir6 = GetTestSubDirectory(g_TestDynamicBackendsSubDir6);
Sadik Armagan1625efc2021-06-10 18:24:34 +0100885 CHECK(exists(testDynamicBackendsSubDir5));
886 CHECK(exists(testDynamicBackendsSubDir6));
Matteo Martincighe54aa062019-08-05 14:12:11 +0100887
888 std::string testValidBackend2FilePath = GetTestFilePath(testDynamicBackendsSubDir5,
889 g_TestValidBackend2FileName);
890 std::string testInvalidBackend8FilePath = GetTestFilePath(testDynamicBackendsSubDir5,
891 g_TestInvalidBackend8FileName);
892 std::string testInvalidBackend9FilePath = GetTestFilePath(testDynamicBackendsSubDir6,
893 g_TestInvalidBackend9FileName);
Sadik Armagan1625efc2021-06-10 18:24:34 +0100894 CHECK(exists(testValidBackend2FilePath));
895 CHECK(exists(testInvalidBackend8FilePath));
896 CHECK(exists(testInvalidBackend9FilePath));
Matteo Martincighe54aa062019-08-05 14:12:11 +0100897
898 std::vector<std::string> sharedObjects
899 {
900 testValidBackend2FilePath, // Arm_TestValid2_backend.so -> valid (basic backend name)
901 testInvalidBackend8FilePath, // Arm_TestInvalid8_backend.so -> not valid (invalid backend id)
902 testInvalidBackend9FilePath, // Arm_TestInvalid9_backend.so -> not valid (incompatible version)
903 "InvalidSharedObject", // The file does not exist
904 };
905 std::vector<DynamicBackendPtr> dynamicBackends = DynamicBackendUtils::CreateDynamicBackends(sharedObjects);
906
Sadik Armagan1625efc2021-06-10 18:24:34 +0100907 CHECK(dynamicBackends.size() == 1);
908 CHECK((dynamicBackends[0] != nullptr));
909 CHECK((dynamicBackends[0]->GetBackendId() == "TestValid2"));
Jan Eilers4a539fc2019-07-25 17:08:37 +0100910}
Matteo Martincigh0c2b2892019-08-05 14:12:11 +0100911
David Monahan9e9c7f52020-09-03 09:02:52 +0100912#if defined(ARMNNREF_ENABLED)
Matteo Martincigh0c2b2892019-08-05 14:12:11 +0100913void RegisterSingleDynamicBackendTestImpl()
914{
915 using namespace armnn;
Francis Murtagh532a29d2020-06-29 11:50:01 +0100916 using namespace fs;
Matteo Martincigh0c2b2892019-08-05 14:12:11 +0100917
918 // Register one valid dynamic backend
919
920 // Dummy registry used for testing
921 BackendRegistry backendRegistry;
Sadik Armagan1625efc2021-06-10 18:24:34 +0100922 CHECK(backendRegistry.Size() == 0);
Matteo Martincigh0c2b2892019-08-05 14:12:11 +0100923
924 std::string testDynamicBackendsSubDir5 = GetTestSubDirectory(g_TestDynamicBackendsSubDir5);
Sadik Armagan1625efc2021-06-10 18:24:34 +0100925 CHECK(exists(testDynamicBackendsSubDir5));
Matteo Martincigh0c2b2892019-08-05 14:12:11 +0100926
927 std::string testValidBackend2FilePath = GetTestFilePath(testDynamicBackendsSubDir5, g_TestValidBackend2FileName);
Sadik Armagan1625efc2021-06-10 18:24:34 +0100928 CHECK(exists(testValidBackend2FilePath));
Matteo Martincigh0c2b2892019-08-05 14:12:11 +0100929
930 std::vector<std::string> sharedObjects{ testValidBackend2FilePath };
931 std::vector<DynamicBackendPtr> dynamicBackends = TestDynamicBackendUtils::CreateDynamicBackends(sharedObjects);
932
Sadik Armagan1625efc2021-06-10 18:24:34 +0100933 CHECK(dynamicBackends.size() == 1);
934 CHECK((dynamicBackends[0] != nullptr));
Matteo Martincigh0c2b2892019-08-05 14:12:11 +0100935
936 BackendId dynamicBackendId = dynamicBackends[0]->GetBackendId();
Sadik Armagan1625efc2021-06-10 18:24:34 +0100937 CHECK((dynamicBackendId == "TestValid2"));
Matteo Martincigh0c2b2892019-08-05 14:12:11 +0100938
939 BackendVersion dynamicBackendVersion = dynamicBackends[0]->GetBackendVersion();
Sadik Armagan1625efc2021-06-10 18:24:34 +0100940 CHECK(TestDynamicBackendUtils::IsBackendCompatible(dynamicBackendVersion));
Matteo Martincigh0c2b2892019-08-05 14:12:11 +0100941
Matteo Martincigh89533902019-08-15 12:08:06 +0100942 BackendIdSet registeredBackendIds = TestDynamicBackendUtils::RegisterDynamicBackendsImplTest(backendRegistry,
943 dynamicBackends);
Sadik Armagan1625efc2021-06-10 18:24:34 +0100944 CHECK(backendRegistry.Size() == 1);
945 CHECK(registeredBackendIds.size() == 1);
Matteo Martincigh0c2b2892019-08-05 14:12:11 +0100946
947 BackendIdSet backendIds = backendRegistry.GetBackendIds();
Sadik Armagan1625efc2021-06-10 18:24:34 +0100948 CHECK(backendIds.size() == 1);
949 CHECK((backendIds.find(dynamicBackendId) != backendIds.end()));
950 CHECK((registeredBackendIds.find(dynamicBackendId) != registeredBackendIds.end()));
Matteo Martincigh0c2b2892019-08-05 14:12:11 +0100951
952 auto dynamicBackendFactoryFunction = backendRegistry.GetFactory(dynamicBackendId);
Sadik Armagan1625efc2021-06-10 18:24:34 +0100953 CHECK((dynamicBackendFactoryFunction != nullptr));
Matteo Martincigh0c2b2892019-08-05 14:12:11 +0100954
955 IBackendInternalUniquePtr dynamicBackend = dynamicBackendFactoryFunction();
Sadik Armagan1625efc2021-06-10 18:24:34 +0100956 CHECK((dynamicBackend != nullptr));
957 CHECK((dynamicBackend->GetId() == dynamicBackendId));
Matteo Martincigh0c2b2892019-08-05 14:12:11 +0100958}
959
960void RegisterMultipleDynamicBackendsTestImpl()
961{
962 using namespace armnn;
Francis Murtagh532a29d2020-06-29 11:50:01 +0100963 using namespace fs;
Matteo Martincigh0c2b2892019-08-05 14:12:11 +0100964
965 // Register many valid dynamic backends
966
967 std::string testDynamicBackendsSubDir5 = GetTestSubDirectory(g_TestDynamicBackendsSubDir5);
968 std::string testDynamicBackendsSubDir6 = GetTestSubDirectory(g_TestDynamicBackendsSubDir6);
Sadik Armagan1625efc2021-06-10 18:24:34 +0100969 CHECK(exists(testDynamicBackendsSubDir5));
970 CHECK(exists(testDynamicBackendsSubDir6));
Matteo Martincigh0c2b2892019-08-05 14:12:11 +0100971
972 std::string testValidBackend2FilePath = GetTestFilePath(testDynamicBackendsSubDir5, g_TestValidBackend2FileName);
973 std::string testValidBackend3FilePath = GetTestFilePath(testDynamicBackendsSubDir5, g_TestValidBackend3FileName);
974 std::string testValidBackend5FilePath = GetTestFilePath(testDynamicBackendsSubDir6, g_TestValidBackend5FileName);
Sadik Armagan1625efc2021-06-10 18:24:34 +0100975 CHECK(exists(testValidBackend2FilePath));
976 CHECK(exists(testValidBackend3FilePath));
977 CHECK(exists(testValidBackend5FilePath));
Matteo Martincigh0c2b2892019-08-05 14:12:11 +0100978
979 std::vector<std::string> sharedObjects
980 {
981 testValidBackend2FilePath,
982 testValidBackend3FilePath,
983 testValidBackend5FilePath
984 };
985 std::vector<DynamicBackendPtr> dynamicBackends = TestDynamicBackendUtils::CreateDynamicBackends(sharedObjects);
986
Sadik Armagan1625efc2021-06-10 18:24:34 +0100987 CHECK(dynamicBackends.size() == 3);
988 CHECK((dynamicBackends[0] != nullptr));
989 CHECK((dynamicBackends[1] != nullptr));
990 CHECK((dynamicBackends[2] != nullptr));
Matteo Martincigh0c2b2892019-08-05 14:12:11 +0100991
992 BackendId dynamicBackendId1 = dynamicBackends[0]->GetBackendId();
993 BackendId dynamicBackendId2 = dynamicBackends[1]->GetBackendId();
994 BackendId dynamicBackendId3 = dynamicBackends[2]->GetBackendId();
Sadik Armagan1625efc2021-06-10 18:24:34 +0100995 CHECK((dynamicBackendId1 == "TestValid2"));
996 CHECK((dynamicBackendId2 == "TestValid3"));
997 CHECK((dynamicBackendId3 == "TestValid5"));
Matteo Martincigh0c2b2892019-08-05 14:12:11 +0100998
999 for (size_t i = 0; i < dynamicBackends.size(); i++)
1000 {
1001 BackendVersion dynamicBackendVersion = dynamicBackends[i]->GetBackendVersion();
Sadik Armagan1625efc2021-06-10 18:24:34 +01001002 CHECK(TestDynamicBackendUtils::IsBackendCompatible(dynamicBackendVersion));
Matteo Martincigh0c2b2892019-08-05 14:12:11 +01001003 }
1004
1005 // Dummy registry used for testing
1006 BackendRegistry backendRegistry;
Sadik Armagan1625efc2021-06-10 18:24:34 +01001007 CHECK(backendRegistry.Size() == 0);
Matteo Martincigh0c2b2892019-08-05 14:12:11 +01001008
Matteo Martincigh89533902019-08-15 12:08:06 +01001009 BackendIdSet registeredBackendIds = TestDynamicBackendUtils::RegisterDynamicBackendsImplTest(backendRegistry,
1010 dynamicBackends);
Sadik Armagan1625efc2021-06-10 18:24:34 +01001011 CHECK(backendRegistry.Size() == 3);
1012 CHECK(registeredBackendIds.size() == 3);
Matteo Martincigh0c2b2892019-08-05 14:12:11 +01001013
1014 BackendIdSet backendIds = backendRegistry.GetBackendIds();
Sadik Armagan1625efc2021-06-10 18:24:34 +01001015 CHECK(backendIds.size() == 3);
1016 CHECK((backendIds.find(dynamicBackendId1) != backendIds.end()));
1017 CHECK((backendIds.find(dynamicBackendId2) != backendIds.end()));
1018 CHECK((backendIds.find(dynamicBackendId3) != backendIds.end()));
1019 CHECK((registeredBackendIds.find(dynamicBackendId1) != registeredBackendIds.end()));
1020 CHECK((registeredBackendIds.find(dynamicBackendId2) != registeredBackendIds.end()));
1021 CHECK((registeredBackendIds.find(dynamicBackendId3) != registeredBackendIds.end()));
Matteo Martincigh0c2b2892019-08-05 14:12:11 +01001022
1023 for (size_t i = 0; i < dynamicBackends.size(); i++)
1024 {
1025 BackendId dynamicBackendId = dynamicBackends[i]->GetBackendId();
1026
1027 auto dynamicBackendFactoryFunction = backendRegistry.GetFactory(dynamicBackendId);
Sadik Armagan1625efc2021-06-10 18:24:34 +01001028 CHECK((dynamicBackendFactoryFunction != nullptr));
Matteo Martincigh0c2b2892019-08-05 14:12:11 +01001029
1030 IBackendInternalUniquePtr dynamicBackend = dynamicBackendFactoryFunction();
Sadik Armagan1625efc2021-06-10 18:24:34 +01001031 CHECK((dynamicBackend != nullptr));
1032 CHECK((dynamicBackend->GetId() == dynamicBackendId));
Matteo Martincigh0c2b2892019-08-05 14:12:11 +01001033 }
1034}
1035
Matteo Martincigh0c2b2892019-08-05 14:12:11 +01001036void RegisterMixedDynamicBackendsTestImpl()
1037{
1038 using namespace armnn;
Francis Murtagh532a29d2020-06-29 11:50:01 +01001039 using namespace fs;
Matteo Martincigh0c2b2892019-08-05 14:12:11 +01001040
1041 // The test covers five directories:
1042 // <unit test path>/src/backends/backendsCommon/test/
1043 // ├─ backendsTestPath5/ -> exists, contains files
1044 // ├─ backendsTestPath6/ -> exists, contains files
1045 // ├─ backendsTestPath7/ -> exists, but empty
1046 // ├─ backendsTestPath8/ -> does not exist
1047 // └─ backendsTestPath9/ -> exists, contains files
1048 //
1049 // The test sub-directory backendsTestPath5/ contains the following test files:
1050 //
1051 // Arm_TestValid2_backend.so -> valid (basic backend name)
1052 // Arm_TestValid3_backend.so -> valid (basic backend name)
1053 // Arm_TestInvalid8_backend.so -> not valid (invalid backend id)
1054 //
1055 // The test sub-directory backendsTestPath6/ contains the following test files:
1056 //
1057 // Arm_TestValid2_backend.so -> valid (but duplicated from backendsTestPath5/)
1058 // Arm_TestValid4_backend.so -> valid (it has a different filename,
1059 // but it has the same backend id of Arm_TestValid2_backend.so
1060 // and the same version)
1061 // Arm_TestValid5_backend.so -> valid (basic backend name)
1062 // Arm_TestInvalid9_backend.so -> not valid (it has a different filename,
1063 // but it has the same backend id of Arm_TestValid2_backend.so
1064 // and a version incompatible with the Backend API)
1065 //
1066 // The test sub-directory backendsTestPath9/ contains the following test files:
1067 //
1068 // Arm_TestInvalid10_backend.so -> not valid (empty backend id)
1069 // Arm_TestInvalid11_backend.so -> not valid ("Unknown" backend id)
1070
1071 std::string testDynamicBackendsSubDir5 = GetTestSubDirectory(g_TestDynamicBackendsSubDir5);
1072 std::string testDynamicBackendsSubDir6 = GetTestSubDirectory(g_TestDynamicBackendsSubDir6);
1073 std::string testDynamicBackendsSubDir7 = GetTestSubDirectory(g_TestDynamicBackendsSubDir7);
1074 std::string testDynamicBackendsSubDir8 = GetTestSubDirectory(g_TestDynamicBackendsSubDir8);
1075 std::string testDynamicBackendsSubDir9 = GetTestSubDirectory(g_TestDynamicBackendsSubDir9);
Sadik Armagan1625efc2021-06-10 18:24:34 +01001076 CHECK(exists(testDynamicBackendsSubDir5));
1077 CHECK(exists(testDynamicBackendsSubDir6));
1078 CHECK(exists(testDynamicBackendsSubDir7));
1079 CHECK(!exists(testDynamicBackendsSubDir8));
1080 CHECK(exists(testDynamicBackendsSubDir9));
Matteo Martincigh0c2b2892019-08-05 14:12:11 +01001081
1082 std::string testValidBackend2FilePath = GetTestFilePath(testDynamicBackendsSubDir5, g_TestValidBackend2FileName);
1083 std::string testValidBackend3FilePath = GetTestFilePath(testDynamicBackendsSubDir5, g_TestValidBackend3FileName);
1084 std::string testValidBackend2DupFilePath = GetTestFilePath(testDynamicBackendsSubDir6, g_TestValidBackend2FileName);
1085 std::string testValidBackend4FilePath = GetTestFilePath(testDynamicBackendsSubDir6, g_TestValidBackend4FileName);
1086 std::string testValidBackend5FilePath = GetTestFilePath(testDynamicBackendsSubDir6, g_TestValidBackend5FileName);
1087 std::string testInvalidBackend8FilePath = GetTestFilePath(testDynamicBackendsSubDir5,
1088 g_TestInvalidBackend8FileName);
1089 std::string testInvalidBackend9FilePath = GetTestFilePath(testDynamicBackendsSubDir6,
1090 g_TestInvalidBackend9FileName);
1091 std::string testInvalidBackend10FilePath = GetTestFilePath(testDynamicBackendsSubDir9,
1092 g_TestInvalidBackend10FileName);
1093 std::string testInvalidBackend11FilePath = GetTestFilePath(testDynamicBackendsSubDir9,
1094 g_TestInvalidBackend11FileName);
Sadik Armagan1625efc2021-06-10 18:24:34 +01001095 CHECK(exists(testValidBackend2FilePath));
1096 CHECK(exists(testValidBackend3FilePath));
1097 CHECK(exists(testValidBackend2DupFilePath));
1098 CHECK(exists(testValidBackend4FilePath));
1099 CHECK(exists(testValidBackend5FilePath));
1100 CHECK(exists(testInvalidBackend8FilePath));
1101 CHECK(exists(testInvalidBackend9FilePath));
1102 CHECK(exists(testInvalidBackend10FilePath));
1103 CHECK(exists(testInvalidBackend11FilePath));
Matteo Martincigh0c2b2892019-08-05 14:12:11 +01001104
1105 std::vector<std::string> sharedObjects
1106 {
1107 testValidBackend2FilePath,
1108 testValidBackend3FilePath,
1109 testValidBackend2DupFilePath,
1110 testValidBackend4FilePath,
1111 testValidBackend5FilePath,
1112 testInvalidBackend8FilePath,
1113 testInvalidBackend9FilePath,
1114 testInvalidBackend10FilePath,
1115 testInvalidBackend11FilePath,
1116 "InvalidSharedObject"
1117 };
1118 std::vector<DynamicBackendPtr> dynamicBackends = TestDynamicBackendUtils::CreateDynamicBackends(sharedObjects);
1119
Sadik Armagan1625efc2021-06-10 18:24:34 +01001120 CHECK(dynamicBackends.size() == 7);
1121 CHECK((dynamicBackends[0] != nullptr));
1122 CHECK((dynamicBackends[1] != nullptr));
1123 CHECK((dynamicBackends[2] != nullptr));
1124 CHECK((dynamicBackends[3] != nullptr));
1125 CHECK((dynamicBackends[4] != nullptr));
1126 CHECK((dynamicBackends[5] != nullptr));
1127 CHECK((dynamicBackends[6] != nullptr));
Matteo Martincigh0c2b2892019-08-05 14:12:11 +01001128
1129 BackendId dynamicBackendId1 = dynamicBackends[0]->GetBackendId();
1130 BackendId dynamicBackendId2 = dynamicBackends[1]->GetBackendId();
1131 BackendId dynamicBackendId3 = dynamicBackends[2]->GetBackendId();
1132 BackendId dynamicBackendId4 = dynamicBackends[3]->GetBackendId();
1133 BackendId dynamicBackendId5 = dynamicBackends[4]->GetBackendId();
1134 BackendId dynamicBackendId6 = dynamicBackends[5]->GetBackendId();
1135 BackendId dynamicBackendId7 = dynamicBackends[6]->GetBackendId();
Sadik Armagan1625efc2021-06-10 18:24:34 +01001136 CHECK((dynamicBackendId1 == "TestValid2"));
1137 CHECK((dynamicBackendId2 == "TestValid3"));
1138 CHECK((dynamicBackendId3 == "TestValid2")); // From duplicate Arm_TestValid2_backend.so
1139 CHECK((dynamicBackendId4 == "TestValid2")); // From Arm_TestValid4_backend.so
1140 CHECK((dynamicBackendId5 == "TestValid5"));
1141 CHECK((dynamicBackendId6 == ""));
1142 CHECK((dynamicBackendId7 == "Unknown"));
Matteo Martincigh0c2b2892019-08-05 14:12:11 +01001143
1144 for (size_t i = 0; i < dynamicBackends.size(); i++)
1145 {
1146 BackendVersion dynamicBackendVersion = dynamicBackends[i]->GetBackendVersion();
Sadik Armagan1625efc2021-06-10 18:24:34 +01001147 CHECK(TestDynamicBackendUtils::IsBackendCompatible(dynamicBackendVersion));
Matteo Martincigh0c2b2892019-08-05 14:12:11 +01001148 }
1149
1150 // Dummy registry used for testing
1151 BackendRegistry backendRegistry;
Sadik Armagan1625efc2021-06-10 18:24:34 +01001152 CHECK(backendRegistry.Size() == 0);
Matteo Martincigh0c2b2892019-08-05 14:12:11 +01001153
1154 std::vector<BackendId> expectedRegisteredbackendIds
1155 {
1156 "TestValid2",
1157 "TestValid3",
1158 "TestValid5"
1159 };
1160
Matteo Martincigh89533902019-08-15 12:08:06 +01001161 BackendIdSet registeredBackendIds = TestDynamicBackendUtils::RegisterDynamicBackendsImplTest(backendRegistry,
1162 dynamicBackends);
Sadik Armagan1625efc2021-06-10 18:24:34 +01001163 CHECK(backendRegistry.Size() == expectedRegisteredbackendIds.size());
1164 CHECK(registeredBackendIds.size() == expectedRegisteredbackendIds.size());
Matteo Martincigh0c2b2892019-08-05 14:12:11 +01001165
1166 BackendIdSet backendIds = backendRegistry.GetBackendIds();
Sadik Armagan1625efc2021-06-10 18:24:34 +01001167 CHECK(backendIds.size() == expectedRegisteredbackendIds.size());
Matteo Martincigh0c2b2892019-08-05 14:12:11 +01001168 for (const BackendId& expectedRegisteredbackendId : expectedRegisteredbackendIds)
1169 {
Sadik Armagan1625efc2021-06-10 18:24:34 +01001170 CHECK((backendIds.find(expectedRegisteredbackendId) != backendIds.end()));
1171 CHECK((registeredBackendIds.find(expectedRegisteredbackendId) != registeredBackendIds.end()));
Matteo Martincigh0c2b2892019-08-05 14:12:11 +01001172
1173 auto dynamicBackendFactoryFunction = backendRegistry.GetFactory(expectedRegisteredbackendId);
Sadik Armagan1625efc2021-06-10 18:24:34 +01001174 CHECK((dynamicBackendFactoryFunction != nullptr));
Matteo Martincigh0c2b2892019-08-05 14:12:11 +01001175
1176 IBackendInternalUniquePtr dynamicBackend = dynamicBackendFactoryFunction();
Sadik Armagan1625efc2021-06-10 18:24:34 +01001177 CHECK((dynamicBackend != nullptr));
1178 CHECK((dynamicBackend->GetId() == expectedRegisteredbackendId));
Matteo Martincigh0c2b2892019-08-05 14:12:11 +01001179 }
1180}
David Monahan9e9c7f52020-09-03 09:02:52 +01001181#endif
1182
1183void RegisterMultipleInvalidDynamicBackendsTestImpl()
1184{
1185 using namespace armnn;
1186 using namespace fs;
1187
1188 // Try to register many invalid dynamic backends
1189
1190 // The test covers one directory:
1191 // <unit test path>/src/backends/backendsCommon/test/
1192 // └─ backendsTestPath9/ -> exists, contains files
1193 //
1194 // The test sub-directory backendsTestPath9/ contains the following test files:
1195 //
1196 // Arm_TestInvalid10_backend.so -> not valid (invalid backend id)
1197 // Arm_TestInvalid11_backend.so -> not valid (invalid backend id)
1198
1199 std::string testDynamicBackendsSubDir9 = GetTestSubDirectory(g_TestDynamicBackendsSubDir9);
Sadik Armagan1625efc2021-06-10 18:24:34 +01001200 CHECK(exists(testDynamicBackendsSubDir9));
David Monahan9e9c7f52020-09-03 09:02:52 +01001201
1202 std::string testInvalidBackend10FilePath = GetTestFilePath(testDynamicBackendsSubDir9,
1203 g_TestInvalidBackend10FileName);
1204 std::string testInvalidBackend11FilePath = GetTestFilePath(testDynamicBackendsSubDir9,
1205 g_TestInvalidBackend11FileName);
Sadik Armagan1625efc2021-06-10 18:24:34 +01001206 CHECK(exists(testInvalidBackend10FilePath));
1207 CHECK(exists(testInvalidBackend11FilePath));
David Monahan9e9c7f52020-09-03 09:02:52 +01001208
1209 std::vector<std::string> sharedObjects
1210 {
1211 testInvalidBackend10FilePath,
1212 testInvalidBackend11FilePath,
1213 "InvalidSharedObject"
1214 };
1215 std::vector<DynamicBackendPtr> dynamicBackends = TestDynamicBackendUtils::CreateDynamicBackends(sharedObjects);
1216
Sadik Armagan1625efc2021-06-10 18:24:34 +01001217 CHECK(dynamicBackends.size() == 2);
1218 CHECK((dynamicBackends[0] != nullptr));
1219 CHECK((dynamicBackends[1] != nullptr));
David Monahan9e9c7f52020-09-03 09:02:52 +01001220
1221 BackendId dynamicBackendId1 = dynamicBackends[0]->GetBackendId();
1222 BackendId dynamicBackendId2 = dynamicBackends[1]->GetBackendId();
Sadik Armagan1625efc2021-06-10 18:24:34 +01001223 CHECK((dynamicBackendId1 == ""));
1224 CHECK((dynamicBackendId2 == "Unknown"));
David Monahan9e9c7f52020-09-03 09:02:52 +01001225
1226 for (size_t i = 0; i < dynamicBackends.size(); i++)
1227 {
1228 BackendVersion dynamicBackendVersion = dynamicBackends[i]->GetBackendVersion();
Sadik Armagan1625efc2021-06-10 18:24:34 +01001229 CHECK(TestDynamicBackendUtils::IsBackendCompatible(dynamicBackendVersion));
David Monahan9e9c7f52020-09-03 09:02:52 +01001230 }
1231
1232 // Dummy registry used for testing
1233 BackendRegistry backendRegistry;
Sadik Armagan1625efc2021-06-10 18:24:34 +01001234 CHECK(backendRegistry.Size() == 0);
David Monahan9e9c7f52020-09-03 09:02:52 +01001235
1236 // Check that no dynamic backend got registered
1237 BackendIdSet registeredBackendIds = TestDynamicBackendUtils::RegisterDynamicBackendsImplTest(backendRegistry,
1238 dynamicBackends);
Sadik Armagan1625efc2021-06-10 18:24:34 +01001239 CHECK(backendRegistry.Size() == 0);
1240 CHECK(registeredBackendIds.empty());
David Monahan9e9c7f52020-09-03 09:02:52 +01001241}
Matteo Martincigh3d8a9ed2019-08-08 10:49:03 +01001242
Narumol Prangnawarat60a20fb2019-12-09 17:24:41 +00001243#if !defined(ARMNN_DYNAMIC_BACKEND_ENABLED)
1244
Matteo Martincigh3d8a9ed2019-08-08 10:49:03 +01001245void RuntimeEmptyTestImpl()
1246{
1247 using namespace armnn;
1248
1249 // Swapping the backend registry storage for testing
1250 TestBackendRegistry testBackendRegistry;
1251
Matteo Martincigh89533902019-08-15 12:08:06 +01001252 const BackendRegistry& backendRegistry = BackendRegistryInstance();
Sadik Armagan1625efc2021-06-10 18:24:34 +01001253 CHECK(backendRegistry.Size() == 0);
Matteo Martincigh89533902019-08-15 12:08:06 +01001254
Matteo Martincigh3d8a9ed2019-08-08 10:49:03 +01001255 IRuntime::CreationOptions creationOptions;
1256 IRuntimePtr runtime = IRuntime::Create(creationOptions);
1257
Jan Eilersbb446e52020-04-02 13:56:54 +01001258 const DeviceSpec& deviceSpec = *PolymorphicDowncast<const DeviceSpec*>(&runtime->GetDeviceSpec());
Matteo Martincigh89533902019-08-15 12:08:06 +01001259 BackendIdSet supportedBackendIds = deviceSpec.GetSupportedBackends();
Sadik Armagan1625efc2021-06-10 18:24:34 +01001260 CHECK(supportedBackendIds.empty());
Matteo Martincigh89533902019-08-15 12:08:06 +01001261
Sadik Armagan1625efc2021-06-10 18:24:34 +01001262 CHECK(backendRegistry.Size() == 0);
Matteo Martincigh3d8a9ed2019-08-08 10:49:03 +01001263}
1264
Narumol Prangnawarat60a20fb2019-12-09 17:24:41 +00001265#endif
1266
Matteo Martincigh3d8a9ed2019-08-08 10:49:03 +01001267void RuntimeDynamicBackendsTestImpl()
1268{
1269 using namespace armnn;
Francis Murtagh532a29d2020-06-29 11:50:01 +01001270 using namespace fs;
Matteo Martincigh3d8a9ed2019-08-08 10:49:03 +01001271
1272 // Swapping the backend registry storage for testing
1273 TestBackendRegistry testBackendRegistry;
1274
1275 // This directory contains valid and invalid backends
1276 std::string testDynamicBackendsSubDir5 = GetTestSubDirectory(g_TestDynamicBackendsSubDir5);
Sadik Armagan1625efc2021-06-10 18:24:34 +01001277 CHECK(exists(testDynamicBackendsSubDir5));
Matteo Martincigh3d8a9ed2019-08-08 10:49:03 +01001278
1279 // Using the path override in CreationOptions to load some test dynamic backends
1280 IRuntime::CreationOptions creationOptions;
1281 creationOptions.m_DynamicBackendsPath = testDynamicBackendsSubDir5;
1282 IRuntimePtr runtime = IRuntime::Create(creationOptions);
1283
1284 std::vector<BackendId> expectedRegisteredbackendIds
1285 {
1286 "TestValid2",
1287 "TestValid3"
1288 };
1289
1290 const BackendRegistry& backendRegistry = BackendRegistryInstance();
Sadik Armagan1625efc2021-06-10 18:24:34 +01001291 CHECK(backendRegistry.Size() == expectedRegisteredbackendIds.size());
Matteo Martincigh3d8a9ed2019-08-08 10:49:03 +01001292
1293 BackendIdSet backendIds = backendRegistry.GetBackendIds();
1294 for (const BackendId& expectedRegisteredbackendId : expectedRegisteredbackendIds)
1295 {
Sadik Armagan1625efc2021-06-10 18:24:34 +01001296 CHECK((backendIds.find(expectedRegisteredbackendId) != backendIds.end()));
Matteo Martincigh3d8a9ed2019-08-08 10:49:03 +01001297 }
Matteo Martincigh89533902019-08-15 12:08:06 +01001298
Jan Eilersbb446e52020-04-02 13:56:54 +01001299 const DeviceSpec& deviceSpec = *PolymorphicDowncast<const DeviceSpec*>(&runtime->GetDeviceSpec());
Matteo Martincigh89533902019-08-15 12:08:06 +01001300 BackendIdSet supportedBackendIds = deviceSpec.GetSupportedBackends();
Sadik Armagan1625efc2021-06-10 18:24:34 +01001301 CHECK(supportedBackendIds.size() == expectedRegisteredbackendIds.size());
Matteo Martincigh89533902019-08-15 12:08:06 +01001302 for (const BackendId& expectedRegisteredbackendId : expectedRegisteredbackendIds)
1303 {
Sadik Armagan1625efc2021-06-10 18:24:34 +01001304 CHECK((supportedBackendIds.find(expectedRegisteredbackendId) != supportedBackendIds.end()));
Matteo Martincigh89533902019-08-15 12:08:06 +01001305 }
Matteo Martincigh3d8a9ed2019-08-08 10:49:03 +01001306}
1307
1308void RuntimeDuplicateDynamicBackendsTestImpl()
1309{
1310 using namespace armnn;
Francis Murtagh532a29d2020-06-29 11:50:01 +01001311 using namespace fs;
Matteo Martincigh3d8a9ed2019-08-08 10:49:03 +01001312
1313 // Swapping the backend registry storage for testing
1314 TestBackendRegistry testBackendRegistry;
1315
1316 // This directory contains valid, invalid and duplicate backends
1317 std::string testDynamicBackendsSubDir6 = GetTestSubDirectory(g_TestDynamicBackendsSubDir6);
Sadik Armagan1625efc2021-06-10 18:24:34 +01001318 CHECK(exists(testDynamicBackendsSubDir6));
Matteo Martincigh3d8a9ed2019-08-08 10:49:03 +01001319
1320 // Using the path override in CreationOptions to load some test dynamic backends
1321 IRuntime::CreationOptions creationOptions;
1322 creationOptions.m_DynamicBackendsPath = testDynamicBackendsSubDir6;
1323 IRuntimePtr runtime = IRuntime::Create(creationOptions);
1324
1325 std::vector<BackendId> expectedRegisteredbackendIds
1326 {
1327 "TestValid2",
1328 "TestValid5"
1329 };
1330
1331 const BackendRegistry& backendRegistry = BackendRegistryInstance();
Sadik Armagan1625efc2021-06-10 18:24:34 +01001332 CHECK(backendRegistry.Size() == expectedRegisteredbackendIds.size());
Matteo Martincigh3d8a9ed2019-08-08 10:49:03 +01001333
1334 BackendIdSet backendIds = backendRegistry.GetBackendIds();
1335 for (const BackendId& expectedRegisteredbackendId : expectedRegisteredbackendIds)
1336 {
Sadik Armagan1625efc2021-06-10 18:24:34 +01001337 CHECK((backendIds.find(expectedRegisteredbackendId) != backendIds.end()));
Matteo Martincigh3d8a9ed2019-08-08 10:49:03 +01001338 }
Matteo Martincigh89533902019-08-15 12:08:06 +01001339
Jan Eilersbb446e52020-04-02 13:56:54 +01001340 const DeviceSpec& deviceSpec = *PolymorphicDowncast<const DeviceSpec*>(&runtime->GetDeviceSpec());
Matteo Martincigh89533902019-08-15 12:08:06 +01001341 BackendIdSet supportedBackendIds = deviceSpec.GetSupportedBackends();
Sadik Armagan1625efc2021-06-10 18:24:34 +01001342 CHECK(supportedBackendIds.size() == expectedRegisteredbackendIds.size());
Matteo Martincigh89533902019-08-15 12:08:06 +01001343 for (const BackendId& expectedRegisteredbackendId : expectedRegisteredbackendIds)
1344 {
Sadik Armagan1625efc2021-06-10 18:24:34 +01001345 CHECK((supportedBackendIds.find(expectedRegisteredbackendId) != supportedBackendIds.end()));
Matteo Martincigh89533902019-08-15 12:08:06 +01001346 }
Matteo Martincigh3d8a9ed2019-08-08 10:49:03 +01001347}
1348
1349void RuntimeInvalidDynamicBackendsTestImpl()
1350{
1351 using namespace armnn;
Francis Murtagh532a29d2020-06-29 11:50:01 +01001352 using namespace fs;
Matteo Martincigh3d8a9ed2019-08-08 10:49:03 +01001353
1354 // Swapping the backend registry storage for testing
1355 TestBackendRegistry testBackendRegistry;
1356
1357 // This directory contains only invalid backends
1358 std::string testDynamicBackendsSubDir9 = GetTestSubDirectory(g_TestDynamicBackendsSubDir9);
Sadik Armagan1625efc2021-06-10 18:24:34 +01001359 CHECK(exists(testDynamicBackendsSubDir9));
Matteo Martincigh3d8a9ed2019-08-08 10:49:03 +01001360
1361 // Using the path override in CreationOptions to load some test dynamic backends
1362 IRuntime::CreationOptions creationOptions;
1363 creationOptions.m_DynamicBackendsPath = testDynamicBackendsSubDir9;
1364 IRuntimePtr runtime = IRuntime::Create(creationOptions);
1365
1366 const BackendRegistry& backendRegistry = BackendRegistryInstance();
Sadik Armagan1625efc2021-06-10 18:24:34 +01001367 CHECK(backendRegistry.Size() == 0);
Matteo Martincigh89533902019-08-15 12:08:06 +01001368
Jan Eilersbb446e52020-04-02 13:56:54 +01001369 const DeviceSpec& deviceSpec = *PolymorphicDowncast<const DeviceSpec*>(&runtime->GetDeviceSpec());
Matteo Martincigh89533902019-08-15 12:08:06 +01001370 BackendIdSet supportedBackendIds = deviceSpec.GetSupportedBackends();
Sadik Armagan1625efc2021-06-10 18:24:34 +01001371 CHECK(supportedBackendIds.empty());
Matteo Martincigh3d8a9ed2019-08-08 10:49:03 +01001372}
1373
1374void RuntimeInvalidOverridePathTestImpl()
1375{
1376 using namespace armnn;
1377
1378 // Swapping the backend registry storage for testing
1379 TestBackendRegistry testBackendRegistry;
1380
1381 // Using the path override in CreationOptions to load some test dynamic backends
1382 IRuntime::CreationOptions creationOptions;
1383 creationOptions.m_DynamicBackendsPath = "InvalidPath";
1384 IRuntimePtr runtime = IRuntime::Create(creationOptions);
1385
1386 const BackendRegistry& backendRegistry = BackendRegistryInstance();
Sadik Armagan1625efc2021-06-10 18:24:34 +01001387 CHECK(backendRegistry.Size() == 0);
Matteo Martincigh89533902019-08-15 12:08:06 +01001388
Jan Eilersbb446e52020-04-02 13:56:54 +01001389 const DeviceSpec& deviceSpec = *PolymorphicDowncast<const DeviceSpec*>(&runtime->GetDeviceSpec());
Matteo Martincigh89533902019-08-15 12:08:06 +01001390 BackendIdSet supportedBackendIds = deviceSpec.GetSupportedBackends();
Sadik Armagan1625efc2021-06-10 18:24:34 +01001391 CHECK(supportedBackendIds.empty());
Matteo Martincigh3d8a9ed2019-08-08 10:49:03 +01001392}
Matteo Martincigh4e73b422019-08-08 13:46:32 +01001393
Matteo Martincighdb16dd32019-08-27 16:41:11 +01001394#if defined(ARMNNREF_ENABLED)
Matteo Martincighe67edb22019-08-14 14:05:46 +01001395
1396// This test unit needs the reference backend, it's not available if the reference backend is not built
1397
Matteo Martincigh4e73b422019-08-08 13:46:32 +01001398void CreateReferenceDynamicBackendTestImpl()
1399{
1400 using namespace armnn;
Francis Murtagh532a29d2020-06-29 11:50:01 +01001401 using namespace fs;
Matteo Martincigh4e73b422019-08-08 13:46:32 +01001402
1403 // Swapping the backend registry storage for testing
1404 TestBackendRegistry testBackendRegistry;
1405
1406 // This directory contains the reference dynamic backend
1407 std::string dynamicBackendsBaseDir = GetDynamicBackendsBasePath();
1408 std::string referenceDynamicBackendSubDir = GetTestSubDirectory(dynamicBackendsBaseDir,
1409 g_ReferenceDynamicBackendSubDir);
Sadik Armagan1625efc2021-06-10 18:24:34 +01001410 CHECK(exists(referenceDynamicBackendSubDir));
Matteo Martincigh4e73b422019-08-08 13:46:32 +01001411
1412 // Check that the reference dynamic backend file exists
1413 std::string referenceBackendFilePath = GetTestFilePath(referenceDynamicBackendSubDir,
1414 g_ReferenceBackendFileName);
Sadik Armagan1625efc2021-06-10 18:24:34 +01001415 CHECK(exists(referenceBackendFilePath));
Matteo Martincigh4e73b422019-08-08 13:46:32 +01001416
1417 // Using the path override in CreationOptions to load the reference dynamic backend
1418 IRuntime::CreationOptions creationOptions;
1419 creationOptions.m_DynamicBackendsPath = referenceDynamicBackendSubDir;
1420 IRuntimePtr runtime = IRuntime::Create(creationOptions);
1421
1422 const BackendRegistry& backendRegistry = BackendRegistryInstance();
Sadik Armagan1625efc2021-06-10 18:24:34 +01001423 CHECK(backendRegistry.Size() == 1);
Matteo Martincigh4e73b422019-08-08 13:46:32 +01001424
1425 BackendIdSet backendIds = backendRegistry.GetBackendIds();
Sadik Armagan1625efc2021-06-10 18:24:34 +01001426 CHECK((backendIds.find("CpuRef") != backendIds.end()));
Matteo Martincigh4e73b422019-08-08 13:46:32 +01001427
Jan Eilersbb446e52020-04-02 13:56:54 +01001428 const DeviceSpec& deviceSpec = *PolymorphicDowncast<const DeviceSpec*>(&runtime->GetDeviceSpec());
Matteo Martincigh89533902019-08-15 12:08:06 +01001429 BackendIdSet supportedBackendIds = deviceSpec.GetSupportedBackends();
Sadik Armagan1625efc2021-06-10 18:24:34 +01001430 CHECK(supportedBackendIds.size() == 1);
1431 CHECK((supportedBackendIds.find("CpuRef") != supportedBackendIds.end()));
Matteo Martincigh89533902019-08-15 12:08:06 +01001432
Matteo Martincigh4e73b422019-08-08 13:46:32 +01001433 // Get the factory function
1434 auto referenceDynamicBackendFactoryFunction = backendRegistry.GetFactory("CpuRef");
Sadik Armagan1625efc2021-06-10 18:24:34 +01001435 CHECK((referenceDynamicBackendFactoryFunction != nullptr));
Matteo Martincigh4e73b422019-08-08 13:46:32 +01001436
1437 // Use the factory function to create an instance of the reference backend
1438 IBackendInternalUniquePtr referenceDynamicBackend = referenceDynamicBackendFactoryFunction();
Sadik Armagan1625efc2021-06-10 18:24:34 +01001439 CHECK((referenceDynamicBackend != nullptr));
1440 CHECK((referenceDynamicBackend->GetId() == "CpuRef"));
Matteo Martincigh4e73b422019-08-08 13:46:32 +01001441
1442 // Test the backend instance by querying the layer support
1443 IBackendInternal::ILayerSupportSharedPtr referenceLayerSupport = referenceDynamicBackend->GetLayerSupport();
Sadik Armagan1625efc2021-06-10 18:24:34 +01001444 CHECK((referenceLayerSupport != nullptr));
Matteo Martincigh4e73b422019-08-08 13:46:32 +01001445
1446 TensorShape inputShape { 1, 16, 16, 16 };
1447 TensorShape outputShape{ 1, 16, 16, 16 };
1448 TensorShape weightShape{ 16, 1, 1, 16 };
1449 TensorInfo inputInfo (inputShape, DataType::Float32);
1450 TensorInfo outputInfo(outputShape, DataType::Float32);
1451 TensorInfo weightInfo(weightShape, DataType::Float32);
1452 Convolution2dDescriptor convolution2dDescriptor;
Cathal Corbett34b429c2021-12-24 12:24:40 +00001453 std::vector<TensorInfo> infos = {inputInfo, outputInfo, weightInfo, TensorInfo()};
Matteo Martincigh4e73b422019-08-08 13:46:32 +01001454 bool referenceConvolution2dSupported =
Cathal Corbett34b429c2021-12-24 12:24:40 +00001455 referenceLayerSupport->IsLayerSupported(LayerType::Convolution2d,
1456 infos,
1457 convolution2dDescriptor);
Sadik Armagan1625efc2021-06-10 18:24:34 +01001458 CHECK(referenceConvolution2dSupported);
Matteo Martincigh4e73b422019-08-08 13:46:32 +01001459
1460 // Test the backend instance by creating a workload
1461 IBackendInternal::IWorkloadFactoryPtr referenceWorkloadFactory = referenceDynamicBackend->CreateWorkloadFactory();
Sadik Armagan1625efc2021-06-10 18:24:34 +01001462 CHECK((referenceWorkloadFactory != nullptr));
Matteo Martincigh4e73b422019-08-08 13:46:32 +01001463
1464 // Create dummy settings for the workload
1465 Convolution2dQueueDescriptor convolution2dQueueDescriptor;
1466 WorkloadInfo workloadInfo
1467 {
Keith Davisb4dd5cc2022-04-07 11:32:00 +01001468 { inputInfo, weightInfo },
Matteo Martincigh4e73b422019-08-08 13:46:32 +01001469 { outputInfo }
1470 };
1471 convolution2dQueueDescriptor.m_Inputs.push_back(nullptr);
Matteo Martincigh4e73b422019-08-08 13:46:32 +01001472
1473 // Create a convolution workload with the dummy settings
Teresa Charlin611c7fb2022-01-07 09:47:29 +00001474 auto workload = referenceWorkloadFactory->CreateWorkload(LayerType::Convolution2d,
1475 convolution2dQueueDescriptor,
1476 workloadInfo);
Sadik Armagan1625efc2021-06-10 18:24:34 +01001477 CHECK((workload != nullptr));
1478 CHECK(workload.get() == PolymorphicDowncast<RefConvolution2dWorkload*>(workload.get()));
Matteo Martincigh4e73b422019-08-08 13:46:32 +01001479}
Matteo Martincighe67edb22019-08-14 14:05:46 +01001480
1481#endif
Narumol Prangnawarat867eba52020-02-03 12:29:56 +00001482
1483#if defined(SAMPLE_DYNAMIC_BACKEND_ENABLED)
Colm Donelanfa0d8382020-06-04 12:30:16 +01001484
1485void CheckSampleDynamicBackendLoaded()
1486{
1487 using namespace armnn;
1488 // At this point we expect DYNAMIC_BACKEND_PATHS to include a path to where libArm_SampleDynamic_backend.so is.
1489 // If it hasn't been loaded there's no point continuing with the rest of the tests.
1490 BackendIdSet backendIds = BackendRegistryInstance().GetBackendIds();
1491 if (backendIds.find("SampleDynamic") == backendIds.end())
1492 {
1493 std::string message = "The SampleDynamic backend has not been loaded. This may be a build configuration error. "
1494 "Ensure a DYNAMIC_BACKEND_PATHS was set at compile time to the location of "
1495 "libArm_SampleDynamic_backend.so. "
1496 "To disable this test recompile with: -DSAMPLE_DYNAMIC_BACKEND_ENABLED=0";
Sadik Armagan1625efc2021-06-10 18:24:34 +01001497 FAIL(message);
Colm Donelanfa0d8382020-06-04 12:30:16 +01001498 }
1499}
1500
Narumol Prangnawarat867eba52020-02-03 12:29:56 +00001501void CreateSampleDynamicBackendTestImpl()
1502{
1503 using namespace armnn;
Narumol Prangnawarat867eba52020-02-03 12:29:56 +00001504 // Using the path override in CreationOptions to load the reference dynamic backend
1505 IRuntime::CreationOptions creationOptions;
Colm Donelan0dbe00a2020-06-03 08:00:28 +01001506 IRuntimePtr runtime = IRuntime::Create(creationOptions);
Narumol Prangnawarat867eba52020-02-03 12:29:56 +00001507 const BackendRegistry& backendRegistry = BackendRegistryInstance();
Sadik Armagan1625efc2021-06-10 18:24:34 +01001508 CHECK(backendRegistry.Size() >= 1);
Colm Donelanfa0d8382020-06-04 12:30:16 +01001509 CheckSampleDynamicBackendLoaded();
Jan Eilersbb446e52020-04-02 13:56:54 +01001510 const DeviceSpec& deviceSpec = *PolymorphicDowncast<const DeviceSpec*>(&runtime->GetDeviceSpec());
Narumol Prangnawarat867eba52020-02-03 12:29:56 +00001511 BackendIdSet supportedBackendIds = deviceSpec.GetSupportedBackends();
Sadik Armagan1625efc2021-06-10 18:24:34 +01001512 CHECK(supportedBackendIds.size()>= 1);
1513 CHECK((supportedBackendIds.find("SampleDynamic") != supportedBackendIds.end()));
Narumol Prangnawarat867eba52020-02-03 12:29:56 +00001514
1515 // Get the factory function
1516 auto sampleDynamicBackendFactoryFunction = backendRegistry.GetFactory("SampleDynamic");
Sadik Armagan1625efc2021-06-10 18:24:34 +01001517 CHECK((sampleDynamicBackendFactoryFunction != nullptr));
Narumol Prangnawarat867eba52020-02-03 12:29:56 +00001518
1519 // Use the factory function to create an instance of the dynamic backend
1520 IBackendInternalUniquePtr sampleDynamicBackend = sampleDynamicBackendFactoryFunction();
Sadik Armagan1625efc2021-06-10 18:24:34 +01001521 CHECK((sampleDynamicBackend != nullptr));
1522 CHECK((sampleDynamicBackend->GetId() == "SampleDynamic"));
Narumol Prangnawarat867eba52020-02-03 12:29:56 +00001523
1524 // Test the backend instance by querying the layer support
1525 IBackendInternal::ILayerSupportSharedPtr sampleLayerSupport = sampleDynamicBackend->GetLayerSupport();
Sadik Armagan1625efc2021-06-10 18:24:34 +01001526 CHECK((sampleLayerSupport != nullptr));
Narumol Prangnawarat867eba52020-02-03 12:29:56 +00001527
1528 TensorShape inputShape { 1, 16, 16, 16 };
1529 TensorShape outputShape{ 1, 16, 16, 16 };
1530 TensorShape weightShape{ 16, 1, 1, 16 };
1531 TensorInfo inputInfo (inputShape, DataType::Float32);
1532 TensorInfo outputInfo(outputShape, DataType::Float32);
1533 TensorInfo weightInfo(weightShape, DataType::Float32);
1534 Convolution2dDescriptor convolution2dDescriptor;
Cathal Corbett34b429c2021-12-24 12:24:40 +00001535 std::vector<TensorInfo> infos = {inputInfo, outputInfo, weightInfo, TensorInfo()};
Cathal Corbett5ed0f862022-01-20 08:54:45 +00001536 bool sampleConvolution2dSupported =
1537 sampleLayerSupport->IsLayerSupported(LayerType::Convolution2d,
1538 infos,
1539 convolution2dDescriptor);
Sadik Armagan1625efc2021-06-10 18:24:34 +01001540 CHECK(!sampleConvolution2dSupported);
Narumol Prangnawarat867eba52020-02-03 12:29:56 +00001541
1542 // Test the backend instance by creating a workload
1543 IBackendInternal::IWorkloadFactoryPtr sampleWorkloadFactory = sampleDynamicBackend->CreateWorkloadFactory();
Sadik Armagan1625efc2021-06-10 18:24:34 +01001544 CHECK((sampleWorkloadFactory != nullptr));
Narumol Prangnawarat867eba52020-02-03 12:29:56 +00001545
1546 // Create dummy settings for the workload
1547 AdditionQueueDescriptor additionQueueDescriptor;
1548 WorkloadInfo workloadInfo
1549 {
1550 { inputInfo, inputInfo },
1551 { outputInfo }
1552 };
1553
1554 // Create a addition workload
Teresa Charlin479e2302022-01-19 10:19:31 +00001555 auto workload = sampleWorkloadFactory->CreateWorkload(LayerType::Addition, additionQueueDescriptor, workloadInfo);
Sadik Armagan1625efc2021-06-10 18:24:34 +01001556 CHECK((workload != nullptr));
Narumol Prangnawarat867eba52020-02-03 12:29:56 +00001557}
1558
1559void SampleDynamicBackendEndToEndTestImpl()
1560{
1561 using namespace armnn;
Narumol Prangnawarat867eba52020-02-03 12:29:56 +00001562 // Create runtime in which test will run
1563 IRuntime::CreationOptions options;
1564 IRuntimePtr runtime(IRuntime::Create(options));
Colm Donelanfa0d8382020-06-04 12:30:16 +01001565 CheckSampleDynamicBackendLoaded();
Narumol Prangnawarat867eba52020-02-03 12:29:56 +00001566 // Builds up the structure of the network.
1567 INetworkPtr net(INetwork::Create());
1568
1569 IConnectableLayer* input0 = net->AddInputLayer(0);
1570 IConnectableLayer* input1 = net->AddInputLayer(1);
Mike Kelly1ec5f852023-04-05 12:51:10 +01001571 ARMNN_NO_DEPRECATE_WARN_BEGIN
Narumol Prangnawarat867eba52020-02-03 12:29:56 +00001572 IConnectableLayer* add = net->AddAdditionLayer();
Mike Kelly1ec5f852023-04-05 12:51:10 +01001573 ARMNN_NO_DEPRECATE_WARN_END
Narumol Prangnawarat867eba52020-02-03 12:29:56 +00001574 IConnectableLayer* output = net->AddOutputLayer(0);
1575
1576 input0->GetOutputSlot(0).Connect(add->GetInputSlot(0));
1577 input1->GetOutputSlot(0).Connect(add->GetInputSlot(1));
1578 add->GetOutputSlot(0).Connect(output->GetInputSlot(0));
1579
1580 TensorInfo tensorInfo(TensorShape({2, 1}), DataType::Float32);
1581 input0->GetOutputSlot(0).SetTensorInfo(tensorInfo);
1582 input1->GetOutputSlot(0).SetTensorInfo(tensorInfo);
1583 add->GetOutputSlot(0).SetTensorInfo(tensorInfo);
1584
1585 // optimize the network
1586 IOptimizedNetworkPtr optNet = Optimize(*net, {"SampleDynamic"}, runtime->GetDeviceSpec());
1587
1588 // Loads it into the runtime.
1589 NetworkId netId;
1590 runtime->LoadNetwork(netId, std::move(optNet));
1591
1592 std::vector<float> input0Data{ 5.0f, 3.0f };
1593 std::vector<float> input1Data{ 10.0f, 8.0f };
1594 std::vector<float> expectedOutputData{ 15.0f, 11.0f };
1595 std::vector<float> outputData(2);
1596
Cathal Corbett5b8093c2021-10-22 11:12:07 +01001597 TensorInfo inputTensorInfo = runtime->GetInputTensorInfo(netId, 0);
1598 inputTensorInfo.SetConstant(true);
Narumol Prangnawarat867eba52020-02-03 12:29:56 +00001599 InputTensors inputTensors
1600 {
Cathal Corbett5b8093c2021-10-22 11:12:07 +01001601 {0,armnn::ConstTensor(inputTensorInfo, input0Data.data())},
1602 {1,armnn::ConstTensor(inputTensorInfo, input1Data.data())}
Narumol Prangnawarat867eba52020-02-03 12:29:56 +00001603 };
1604 OutputTensors outputTensors
1605 {
1606 {0,armnn::Tensor(runtime->GetOutputTensorInfo(netId, 0), outputData.data())}
1607 };
1608
1609 // Does the inference.
1610 runtime->EnqueueWorkload(netId, inputTensors, outputTensors);
1611
1612 // Checks the results.
Sadik Armagan1625efc2021-06-10 18:24:34 +01001613 CHECK(outputData == expectedOutputData);
Narumol Prangnawarat867eba52020-02-03 12:29:56 +00001614}
1615#endif