blob: 2f1f6202b63f625094a5218466726f3845420f1f [file] [log] [blame]
Matteo Martincighac60d282019-07-25 15:25:44 +01001//
2// Copyright © 2017 Arm Ltd. All rights reserved.
3// 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>
Jan Eilersbb446e52020-04-02 13:56:54 +010010#include <armnn/ILayerSupport.hpp>
11#include <armnn/utility/PolymorphicDowncast.hpp>
Matteo Martincigh4e73b422019-08-08 13:46:32 +010012#include <backendsCommon/CpuTensorHandle.hpp>
Jan Eilersbb446e52020-04-02 13:56:54 +010013#include <backendsCommon/DynamicBackendUtils.hpp>
Francis Murtagh532a29d2020-06-29 11:50:01 +010014#include <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
Matteo Martincighac60d282019-07-25 15:25:44 +010021#include <boost/test/unit_test.hpp>
Matteo Martincigh986c1862019-07-26 15:12:47 +010022
Colm Donelanaa93d982020-06-28 08:16:46 +010023#if !defined(DYNAMIC_BACKEND_BUILD_DIR)
24#define DYNAMIC_BACKEND_BUILD_DIR fs::path("./")
25#endif
26
27static std::string g_TestDirCLI = "--dynamic-backend-build-dir";
Matteo Martincighd0dc7702019-08-01 17:09:03 +010028static std::string g_TestBaseDir = "src/backends/backendsCommon/test/";
Matteo Martincigh986c1862019-07-26 15:12:47 +010029
Matteo Martincighd0dc7702019-08-01 17:09:03 +010030static std::string g_TestSharedObjectSubDir = "testSharedObject/";
31static std::string g_TestDynamicBackendSubDir = "testDynamicBackend/";
32
33static std::string g_TestSharedObjectFileName = "libTestSharedObject.so";
34static std::string g_TestNoSharedObjectFileName = "libNoSharedObject.txt";
35
36static std::string g_TestValidTestDynamicBackendFileName = "libValidTestDynamicBackend.so";
37static std::string g_TestInvalidTestDynamicBackend1FileName = "libInvalidTestDynamicBackend1.so";
38static std::string g_TestInvalidTestDynamicBackend2FileName = "libInvalidTestDynamicBackend2.so";
39static std::string g_TestInvalidTestDynamicBackend3FileName = "libInvalidTestDynamicBackend3.so";
40static std::string g_TestInvalidTestDynamicBackend4FileName = "libInvalidTestDynamicBackend4.so";
41static std::string g_TestInvalidTestDynamicBackend5FileName = "libInvalidTestDynamicBackend5.so";
42static std::string g_TestInvalidTestDynamicBackend6FileName = "libInvalidTestDynamicBackend6.so";
43static std::string g_TestInvalidTestDynamicBackend7FileName = "libInvalidTestDynamicBackend7.so";
44
Matteo Martincighe54aa062019-08-05 14:12:11 +010045static std::string g_TestValidBackend2FileName = "Arm_TestValid2_backend.so";
46static std::string g_TestValidBackend3FileName = "Arm_TestValid3_backend.so";
47static std::string g_TestValidBackend4FileName = "Arm_TestValid4_backend.so";
Matteo Martincigh0c2b2892019-08-05 14:12:11 +010048static std::string g_TestValidBackend5FileName = "Arm_TestValid5_backend.so";
Matteo Martincighe54aa062019-08-05 14:12:11 +010049static std::string g_TestInvalidBackend8FileName = "Arm_TestInvalid8_backend.so";
50static std::string g_TestInvalidBackend9FileName = "Arm_TestInvalid9_backend.so";
Matteo Martincigh0c2b2892019-08-05 14:12:11 +010051static std::string g_TestInvalidBackend10FileName = "Arm_TestInvalid10_backend.so";
52static std::string g_TestInvalidBackend11FileName = "Arm_TestInvalid11_backend.so";
Matteo Martincighe54aa062019-08-05 14:12:11 +010053
Matteo Martincigh0c2b2892019-08-05 14:12:11 +010054static std::string g_TestDynamicBackendsSubDir1 = "backendsTestPath1/";
55static std::string g_TestDynamicBackendsSubDir2 = "backendsTestPath2/";
56static std::string g_TestDynamicBackendsSubDir3 = "backendsTestPath3/";
57static std::string g_TestDynamicBackendsSubDir4 = "backendsTestPath4/";
58static std::string g_TestDynamicBackendsSubDir5 = "backendsTestPath5/";
59static std::string g_TestDynamicBackendsSubDir6 = "backendsTestPath6/";
60static std::string g_TestDynamicBackendsSubDir7 = "backendsTestPath7/";
61static std::string g_TestDynamicBackendsSubDir8 = "backendsTestPath8/";
62static std::string g_TestDynamicBackendsSubDir9 = "backendsTestPath9/";
63
Matteo Martincigh4e73b422019-08-08 13:46:32 +010064static std::string g_DynamicBackendsBaseDir = "src/backends/dynamic";
65static std::string g_ReferenceDynamicBackendSubDir = "reference/";
66static std::string g_ReferenceBackendFileName = "Arm_CpuRef_backend.so";
67
Matteo Martincigh3d8a9ed2019-08-08 10:49:03 +010068// DynamicBackendUtils wrapper class used for testing (allows to directly invoke the protected methods)
Matteo Martincigh0c2b2892019-08-05 14:12:11 +010069class TestDynamicBackendUtils : public armnn::DynamicBackendUtils
70{
71public:
72 static bool IsBackendCompatibleTest(const armnn::BackendVersion& backendApiVersion,
73 const armnn::BackendVersion& backendVersion)
74 {
75 return IsBackendCompatibleImpl(backendApiVersion, backendVersion);
76 }
77
78 static std::vector<std::string> GetBackendPathsImplTest(const std::string& path)
79 {
80 return GetBackendPathsImpl(path);
81 }
82
Matteo Martincigh89533902019-08-15 12:08:06 +010083 static armnn::BackendIdSet RegisterDynamicBackendsImplTest(
84 armnn::BackendRegistry& backendRegistry,
85 const std::vector<armnn::DynamicBackendPtr>& dynamicBackends)
Matteo Martincigh0c2b2892019-08-05 14:12:11 +010086 {
Matteo Martincigh89533902019-08-15 12:08:06 +010087 return RegisterDynamicBackendsImpl(backendRegistry, dynamicBackends);
Matteo Martincigh0c2b2892019-08-05 14:12:11 +010088 }
89};
Matteo Martincighe7d44982019-08-05 12:16:47 +010090
Matteo Martincigh3d8a9ed2019-08-08 10:49:03 +010091// BackendRegistry wrapper class used for testing (swaps the underlying factory storage)
92class TestBackendRegistry : public armnn::BackendRegistry
93{
94public:
95 TestBackendRegistry() : armnn::BackendRegistry()
96 {
97 Swap(armnn::BackendRegistryInstance(), m_TempStorage);
98 }
99
100 ~TestBackendRegistry()
101 {
102 Swap(armnn::BackendRegistryInstance(), m_TempStorage);
103 }
104
105private:
106 FactoryStorage m_TempStorage;
107};
108
Matteo Martincigh4e73b422019-08-08 13:46:32 +0100109std::string GetBasePath(const std::string& basePath)
Matteo Martincigh986c1862019-07-26 15:12:47 +0100110{
Francis Murtagh532a29d2020-06-29 11:50:01 +0100111 using namespace fs;
Colm Donelanaa93d982020-06-28 08:16:46 +0100112 // What we're looking for here is the location of the UnitTests executable.
113 // In the normal build environment there are a series of files and
114 // directories created by cmake. If the executable has been relocated they
115 // may not be there. The search hierarchy is:
116 // * User specified --dynamic-backend-build-dir
117 // * Compile time value of DYNAMIC_BACKEND_BUILD_DIR.
118 // * Arg0 location.
119 // * Fall back value of current directory.
120 path programLocation = DYNAMIC_BACKEND_BUILD_DIR;
121 // Look for the specific argument --dynamic-backend-build-dir?
122 if (boost::unit_test::framework::master_test_suite().argc == 3)
123 {
124 // Boost custom arguments begin after a '--' on the command line.
125 if (g_TestDirCLI.compare(boost::unit_test::framework::master_test_suite().argv[1]) == 0)
126 {
127 // Then the next argument is the path.
128 programLocation = boost::unit_test::framework::master_test_suite().argv[2];
129 }
130 }
131 else
132 {
133 // Start by checking if DYNAMIC_BACKEND_BUILD_DIR value exist.
134 if (!exists(programLocation))
135 {
136 // That doesn't exist try looking at arg[0].
137 path arg0Path(boost::unit_test::framework::master_test_suite().argv[0]);
138 arg0Path.remove_filename();
139 path arg0SharedObjectPath(arg0Path);
140 arg0SharedObjectPath.append(basePath);
141 if (exists(arg0SharedObjectPath))
142 {
143 // Yeah arg0 worked.
144 programLocation = arg0Path;
145 }
146 }
147 }
148 // This is the base path from the build where the test libraries were built.
Matteo Martincigh4e73b422019-08-08 13:46:32 +0100149 path sharedObjectPath = programLocation.append(basePath);
Colm Donelanaa93d982020-06-28 08:16:46 +0100150 BOOST_REQUIRE_MESSAGE(exists(sharedObjectPath), "Base path for shared objects does not exist: " +
151 sharedObjectPath.string() + "\nTo specify the root of this base path on the " +
152 "command line add: \'-- --dynamic-backend-build-dir <path>\'");
Matteo Martincighd0dc7702019-08-01 17:09:03 +0100153 return sharedObjectPath.string();
154}
155
Matteo Martincigh4e73b422019-08-08 13:46:32 +0100156std::string GetTestDirectoryBasePath()
157{
158 return GetBasePath(g_TestBaseDir);
159}
160
161std::string GetDynamicBackendsBasePath()
162{
163 return GetBasePath(g_DynamicBackendsBaseDir);
164}
165
Matteo Martincighd0dc7702019-08-01 17:09:03 +0100166std::string GetTestSubDirectory(const std::string& subdir)
167{
Francis Murtagh532a29d2020-06-29 11:50:01 +0100168 using namespace fs;
Matteo Martincighd0dc7702019-08-01 17:09:03 +0100169
170 std::string testDynamicBackendsBaseDir = GetTestDirectoryBasePath();
171 path testDynamicBackendsBasePath(testDynamicBackendsBaseDir);
172 path testDynamicBackendsSubDir = testDynamicBackendsBasePath.append(subdir);
173 // Do not check that the sub-directory exists because for testing reasons we may use non-existing paths
174
175 return testDynamicBackendsSubDir.string();
176}
177
Matteo Martincigh4e73b422019-08-08 13:46:32 +0100178std::string GetTestSubDirectory(const std::string& basePath, const std::string& subdir)
179{
Francis Murtagh532a29d2020-06-29 11:50:01 +0100180 using namespace fs;
Matteo Martincigh4e73b422019-08-08 13:46:32 +0100181
182 path testDynamicBackendsBasePath(basePath);
183 path testDynamicBackendsSubDir = testDynamicBackendsBasePath.append(subdir);
184 // Do not check that the sub-directory exists because for testing reasons we may use non-existing paths
185
186 return testDynamicBackendsSubDir.string();
187}
188
Matteo Martincighd0dc7702019-08-01 17:09:03 +0100189std::string GetTestFilePath(const std::string& directory, const std::string& fileName)
190{
Francis Murtagh532a29d2020-06-29 11:50:01 +0100191 using namespace fs;
Matteo Martincighd0dc7702019-08-01 17:09:03 +0100192
193 path directoryPath(directory);
194 path fileNamePath = directoryPath.append(fileName);
195 BOOST_CHECK(exists(fileNamePath));
196
197 return fileNamePath.string();
Matteo Martincigh986c1862019-07-26 15:12:47 +0100198}
199
200void OpenCloseHandleTestImpl()
201{
202 using namespace armnn;
203
Matteo Martincighd0dc7702019-08-01 17:09:03 +0100204 std::string testSubDirectory = GetTestSubDirectory(g_TestSharedObjectSubDir);
205 std::string sharedObjectFilePath = GetTestFilePath(testSubDirectory, g_TestSharedObjectFileName);
Matteo Martincigh986c1862019-07-26 15:12:47 +0100206
207 void* sharedObjectHandle = nullptr;
208 BOOST_CHECK_NO_THROW(sharedObjectHandle = DynamicBackendUtils::OpenHandle(sharedObjectFilePath));
209 BOOST_TEST((sharedObjectHandle != nullptr));
210
211 DynamicBackendUtils::CloseHandle(sharedObjectHandle);
212}
213
214void CloseInvalidHandleTestImpl()
215{
216 using namespace armnn;
217
218 // This calls must silently handle invalid handles and complete successfully (no segfaults, etc.)
219 DynamicBackendUtils::CloseHandle(nullptr);
220}
221
222void OpenEmptyFileNameTestImpl()
223{
224 using namespace armnn;
225
226 void* sharedObjectHandle = nullptr;
227 BOOST_CHECK_THROW(sharedObjectHandle = DynamicBackendUtils::OpenHandle(""), RuntimeException);
228 BOOST_TEST((sharedObjectHandle == nullptr));
229}
230
231void OpenNotExistingFileTestImpl()
232{
233 using namespace armnn;
234
235 void* sharedObjectHandle = nullptr;
236 BOOST_CHECK_THROW(sharedObjectHandle = DynamicBackendUtils::OpenHandle("NotExistingFileName"), RuntimeException);
237 BOOST_TEST((sharedObjectHandle == nullptr));
238}
239
240void OpenNotSharedObjectTestImpl()
241{
242 using namespace armnn;
243
Matteo Martincighd0dc7702019-08-01 17:09:03 +0100244 std::string testSubDirectory = GetTestSubDirectory(g_TestSharedObjectSubDir);
245 std::string notSharedObjectFilePath = GetTestFilePath(testSubDirectory, g_TestNoSharedObjectFileName);
Matteo Martincigh986c1862019-07-26 15:12:47 +0100246
247 void* sharedObjectHandle = nullptr;
248 BOOST_CHECK_THROW(sharedObjectHandle = DynamicBackendUtils::OpenHandle(notSharedObjectFilePath), RuntimeException);
249 BOOST_TEST((sharedObjectHandle == nullptr));
250}
251
252void GetValidEntryPointTestImpl()
253{
254 using namespace armnn;
255
Matteo Martincighd0dc7702019-08-01 17:09:03 +0100256 std::string testSubDirectory = GetTestSubDirectory(g_TestSharedObjectSubDir);
257 std::string sharedObjectFilePath = GetTestFilePath(testSubDirectory, g_TestSharedObjectFileName);
Matteo Martincigh986c1862019-07-26 15:12:47 +0100258
259 void* sharedObjectHandle = nullptr;
260 BOOST_CHECK_NO_THROW(sharedObjectHandle = DynamicBackendUtils::OpenHandle(sharedObjectFilePath));
261 BOOST_TEST((sharedObjectHandle != nullptr));
262
263 using TestFunctionType = int(*)(int);
264 TestFunctionType testFunctionPointer = nullptr;
265 BOOST_CHECK_NO_THROW(testFunctionPointer = DynamicBackendUtils::GetEntryPoint<TestFunctionType>(sharedObjectHandle,
266 "TestFunction1"));
267 BOOST_TEST((testFunctionPointer != nullptr));
268 BOOST_TEST(testFunctionPointer(7) == 7);
269
270 DynamicBackendUtils::CloseHandle(sharedObjectHandle);
271}
272
273void GetNameMangledEntryPointTestImpl()
274{
275 using namespace armnn;
276
Matteo Martincighd0dc7702019-08-01 17:09:03 +0100277 std::string testSubDirectory = GetTestSubDirectory(g_TestSharedObjectSubDir);
278 std::string sharedObjectFilePath = GetTestFilePath(testSubDirectory, g_TestSharedObjectFileName);
Matteo Martincigh986c1862019-07-26 15:12:47 +0100279
280 void* sharedObjectHandle = nullptr;
281 BOOST_CHECK_NO_THROW(sharedObjectHandle = DynamicBackendUtils::OpenHandle(sharedObjectFilePath));
282 BOOST_TEST((sharedObjectHandle != nullptr));
283
284 using TestFunctionType = int(*)(int);
285 TestFunctionType testFunctionPointer = nullptr;
286 BOOST_CHECK_THROW(testFunctionPointer = DynamicBackendUtils::GetEntryPoint<TestFunctionType>(sharedObjectHandle,
287 "TestFunction2"),
288 RuntimeException);
289 BOOST_TEST((testFunctionPointer == nullptr));
290
291 DynamicBackendUtils::CloseHandle(sharedObjectHandle);
292}
293
294void GetNoExternEntryPointTestImpl()
295{
296 using namespace armnn;
297
Matteo Martincighd0dc7702019-08-01 17:09:03 +0100298 std::string testSubDirectory = GetTestSubDirectory(g_TestSharedObjectSubDir);
299 std::string sharedObjectFilePath = GetTestFilePath(testSubDirectory, g_TestSharedObjectFileName);
Matteo Martincigh986c1862019-07-26 15:12:47 +0100300
301 void* sharedObjectHandle = nullptr;
302 BOOST_CHECK_NO_THROW(sharedObjectHandle = DynamicBackendUtils::OpenHandle(sharedObjectFilePath));
303 BOOST_TEST((sharedObjectHandle != nullptr));
304
305 using TestFunctionType = int(*)(int);
306 TestFunctionType testFunctionPointer = nullptr;
307 BOOST_CHECK_THROW(testFunctionPointer = DynamicBackendUtils::GetEntryPoint<TestFunctionType>(sharedObjectHandle,
308 "TestFunction3"),
309 RuntimeException);
310 BOOST_TEST((testFunctionPointer == nullptr));
311
312 DynamicBackendUtils::CloseHandle(sharedObjectHandle);
313}
314
315void GetNotExistingEntryPointTestImpl()
316{
317 using namespace armnn;
318
Matteo Martincighd0dc7702019-08-01 17:09:03 +0100319 std::string testSubDirectory = GetTestSubDirectory(g_TestSharedObjectSubDir);
320 std::string sharedObjectFilePath = GetTestFilePath(testSubDirectory, g_TestSharedObjectFileName);
Matteo Martincigh986c1862019-07-26 15:12:47 +0100321
322 void* sharedObjectHandle = nullptr;
323 BOOST_CHECK_NO_THROW(sharedObjectHandle = DynamicBackendUtils::OpenHandle(sharedObjectFilePath));
324 BOOST_TEST((sharedObjectHandle != nullptr));
325
326 using TestFunctionType = int(*)(int);
327 TestFunctionType testFunctionPointer = nullptr;
328 BOOST_CHECK_THROW(testFunctionPointer = DynamicBackendUtils::GetEntryPoint<TestFunctionType>(sharedObjectHandle,
329 "TestFunction4"),
330 RuntimeException);
331 BOOST_TEST((testFunctionPointer == nullptr));
332
333 DynamicBackendUtils::CloseHandle(sharedObjectHandle);
334}
Matteo Martincighac60d282019-07-25 15:25:44 +0100335
336void BackendVersioningTestImpl()
337{
Matteo Martincigh986c1862019-07-26 15:12:47 +0100338 using namespace armnn;
339
Matteo Martincighac60d282019-07-25 15:25:44 +0100340 // The backend API version used for the tests
Matteo Martincigh986c1862019-07-26 15:12:47 +0100341 BackendVersion backendApiVersion{ 2, 4 };
Matteo Martincighac60d282019-07-25 15:25:44 +0100342
343 // Same backend and backend API versions are compatible with the backend API
Matteo Martincigh986c1862019-07-26 15:12:47 +0100344 BackendVersion sameBackendVersion{ 2, 4 };
Matteo Martincighac60d282019-07-25 15:25:44 +0100345 BOOST_TEST(sameBackendVersion == backendApiVersion);
346 BOOST_TEST(sameBackendVersion <= backendApiVersion);
347 BOOST_TEST(TestDynamicBackendUtils::IsBackendCompatibleTest(backendApiVersion, sameBackendVersion) == true);
348
349 // Backend versions that differ from the backend API version by major revision are not compatible
350 // with the backend API
Matteo Martincigh986c1862019-07-26 15:12:47 +0100351 BackendVersion laterMajorBackendVersion{ 3, 4 };
Matteo Martincighac60d282019-07-25 15:25:44 +0100352 BOOST_TEST(!(laterMajorBackendVersion == backendApiVersion));
353 BOOST_TEST(!(laterMajorBackendVersion <= backendApiVersion));
354 BOOST_TEST(TestDynamicBackendUtils::IsBackendCompatibleTest(backendApiVersion, laterMajorBackendVersion) == false);
355
Matteo Martincigh986c1862019-07-26 15:12:47 +0100356 BackendVersion earlierMajorBackendVersion{ 1, 4 };
Matteo Martincighac60d282019-07-25 15:25:44 +0100357 BOOST_TEST(!(earlierMajorBackendVersion == backendApiVersion));
358 BOOST_TEST(earlierMajorBackendVersion <= backendApiVersion);
359 BOOST_TEST(TestDynamicBackendUtils::IsBackendCompatibleTest(backendApiVersion,
360 earlierMajorBackendVersion) == false);
361
362 // Backend versions with the same major revision but later minor revision than
363 // the backend API version are not compatible with the backend API
Matteo Martincigh986c1862019-07-26 15:12:47 +0100364 BackendVersion laterMinorBackendVersion{ 2, 5 };
Matteo Martincighac60d282019-07-25 15:25:44 +0100365 BOOST_TEST(!(laterMinorBackendVersion == backendApiVersion));
366 BOOST_TEST(!(laterMinorBackendVersion <= backendApiVersion));
367 BOOST_TEST(TestDynamicBackendUtils::IsBackendCompatibleTest(backendApiVersion, laterMinorBackendVersion) == false);
368
369 // Backend versions with the same major revision but earlier minor revision than
370 // the backend API version are compatible with the backend API
Matteo Martincigh986c1862019-07-26 15:12:47 +0100371 BackendVersion earlierMinorBackendVersion{ 2, 3 };
Matteo Martincighac60d282019-07-25 15:25:44 +0100372 BOOST_TEST(!(earlierMinorBackendVersion == backendApiVersion));
373 BOOST_TEST(earlierMinorBackendVersion <= backendApiVersion);
374 BOOST_TEST(TestDynamicBackendUtils::IsBackendCompatibleTest(backendApiVersion, earlierMinorBackendVersion) == true);
375}
Matteo Martincighbc2e2102019-07-24 14:56:13 +0100376
377void CreateValidDynamicBackendObjectTestImpl()
378{
379 // Valid shared object handle
380 // Correct name mangling
381 // Correct interface
382 // Correct backend implementation
383
384 using namespace armnn;
385
Matteo Martincighd0dc7702019-08-01 17:09:03 +0100386 std::string testSubDirectory = GetTestSubDirectory(g_TestDynamicBackendSubDir);
Colm Donelanf060b2e2020-06-16 17:14:51 +0100387
388 // We expect this path to exists so we can load a valid dynamic backend.
Francis Murtagh532a29d2020-06-29 11:50:01 +0100389 BOOST_CHECK_MESSAGE(fs::exists(testSubDirectory),
Colm Donelanf060b2e2020-06-16 17:14:51 +0100390 "Base path for shared objects does not exist: " + testSubDirectory);
391
Matteo Martincighd0dc7702019-08-01 17:09:03 +0100392 std::string sharedObjectFilePath = GetTestFilePath(testSubDirectory, g_TestValidTestDynamicBackendFileName);
Matteo Martincighbc2e2102019-07-24 14:56:13 +0100393
394 void* sharedObjectHandle = nullptr;
395 BOOST_CHECK_NO_THROW(sharedObjectHandle = DynamicBackendUtils::OpenHandle(sharedObjectFilePath));
396 BOOST_TEST((sharedObjectHandle != nullptr));
397
Matteo Martincighe54aa062019-08-05 14:12:11 +0100398 DynamicBackendPtr dynamicBackend;
Matteo Martincighbc2e2102019-07-24 14:56:13 +0100399 BOOST_CHECK_NO_THROW(dynamicBackend.reset(new DynamicBackend(sharedObjectHandle)));
400 BOOST_TEST((dynamicBackend != nullptr));
401
402 BackendId dynamicBackendId;
403 BOOST_CHECK_NO_THROW(dynamicBackendId = dynamicBackend->GetBackendId());
404 BOOST_TEST((dynamicBackendId == "ValidTestDynamicBackend"));
405
406 BackendVersion dynamicBackendVersion;
407 BOOST_CHECK_NO_THROW(dynamicBackendVersion = dynamicBackend->GetBackendVersion());
Matteo Martincighe54aa062019-08-05 14:12:11 +0100408 BOOST_TEST((dynamicBackendVersion == IBackendInternal::GetApiVersion()));
Matteo Martincighbc2e2102019-07-24 14:56:13 +0100409
Matteo Martincigh0c2b2892019-08-05 14:12:11 +0100410 IBackendInternalUniquePtr dynamicBackendInstance1;
411 BOOST_CHECK_NO_THROW(dynamicBackendInstance1 = dynamicBackend->GetBackend());
412 BOOST_TEST((dynamicBackendInstance1 != nullptr));
Matteo Martincighbc2e2102019-07-24 14:56:13 +0100413
Matteo Martincigh0c2b2892019-08-05 14:12:11 +0100414 BackendRegistry::FactoryFunction dynamicBackendFactoryFunction = nullptr;
415 BOOST_CHECK_NO_THROW(dynamicBackendFactoryFunction = dynamicBackend->GetFactoryFunction());
416 BOOST_TEST((dynamicBackendFactoryFunction != nullptr));
417
418 IBackendInternalUniquePtr dynamicBackendInstance2;
419 BOOST_CHECK_NO_THROW(dynamicBackendInstance2 = dynamicBackendFactoryFunction());
420 BOOST_TEST((dynamicBackendInstance2 != nullptr));
421
422 BOOST_TEST((dynamicBackendInstance1->GetId() == "ValidTestDynamicBackend"));
423 BOOST_TEST((dynamicBackendInstance2->GetId() == "ValidTestDynamicBackend"));
Matteo Martincighbc2e2102019-07-24 14:56:13 +0100424}
425
426void CreateDynamicBackendObjectInvalidHandleTestImpl()
427{
428 // Invalid (null) shared object handle
429
430 using namespace armnn;
431
432 void* sharedObjectHandle = nullptr;
Matteo Martincighe54aa062019-08-05 14:12:11 +0100433 DynamicBackendPtr dynamicBackend;
Matteo Martincighbc2e2102019-07-24 14:56:13 +0100434 BOOST_CHECK_THROW(dynamicBackend.reset(new DynamicBackend(sharedObjectHandle)), InvalidArgumentException);
435 BOOST_TEST((dynamicBackend == nullptr));
436}
437
438void CreateDynamicBackendObjectInvalidInterface1TestImpl()
439{
440 // Valid shared object handle
441 // Wrong (not C-style) name mangling
442
443 using namespace armnn;
444
Matteo Martincighd0dc7702019-08-01 17:09:03 +0100445 std::string testSubDirectory = GetTestSubDirectory(g_TestDynamicBackendSubDir);
446 std::string sharedObjectFilePath = GetTestFilePath(testSubDirectory, g_TestInvalidTestDynamicBackend1FileName);
Matteo Martincighbc2e2102019-07-24 14:56:13 +0100447
448 void* sharedObjectHandle = nullptr;
449 BOOST_CHECK_NO_THROW(sharedObjectHandle = DynamicBackendUtils::OpenHandle(sharedObjectFilePath));
450 BOOST_TEST((sharedObjectHandle != nullptr));
451
Matteo Martincighe54aa062019-08-05 14:12:11 +0100452 DynamicBackendPtr dynamicBackend;
Matteo Martincighbc2e2102019-07-24 14:56:13 +0100453 BOOST_CHECK_THROW(dynamicBackend.reset(new DynamicBackend(sharedObjectHandle)), RuntimeException);
454 BOOST_TEST((dynamicBackend == nullptr));
455}
456
457void CreateDynamicBackendObjectInvalidInterface2TestImpl()
458{
459 // Valid shared object handle
460 // Correct name mangling
461 // Wrong interface (missing GetBackendId())
462
463 using namespace armnn;
464
Matteo Martincighd0dc7702019-08-01 17:09:03 +0100465 std::string testSubDirectory = GetTestSubDirectory(g_TestDynamicBackendSubDir);
466 std::string sharedObjectFilePath = GetTestFilePath(testSubDirectory, g_TestInvalidTestDynamicBackend2FileName);
Matteo Martincighbc2e2102019-07-24 14:56:13 +0100467
468 void* sharedObjectHandle = nullptr;
469 BOOST_CHECK_NO_THROW(sharedObjectHandle = DynamicBackendUtils::OpenHandle(sharedObjectFilePath));
470 BOOST_TEST((sharedObjectHandle != nullptr));
471
Matteo Martincighe54aa062019-08-05 14:12:11 +0100472 DynamicBackendPtr dynamicBackend;
Matteo Martincighbc2e2102019-07-24 14:56:13 +0100473 BOOST_CHECK_THROW(dynamicBackend.reset(new DynamicBackend(sharedObjectHandle)), RuntimeException);
474 BOOST_TEST((dynamicBackend == nullptr));
475}
476
477void CreateDynamicBackendObjectInvalidInterface3TestImpl()
478{
479 // Valid shared object handle
480 // Correct name mangling
481 // Wrong interface (missing GetVersion())
482
483 using namespace armnn;
484
Matteo Martincighd0dc7702019-08-01 17:09:03 +0100485 std::string testSubDirectory = GetTestSubDirectory(g_TestDynamicBackendSubDir);
486 std::string sharedObjectFilePath = GetTestFilePath(testSubDirectory, g_TestInvalidTestDynamicBackend3FileName);
Matteo Martincighbc2e2102019-07-24 14:56:13 +0100487
488 void* sharedObjectHandle = nullptr;
489 BOOST_CHECK_NO_THROW(sharedObjectHandle = DynamicBackendUtils::OpenHandle(sharedObjectFilePath));
490 BOOST_TEST((sharedObjectHandle != nullptr));
491
Matteo Martincighe54aa062019-08-05 14:12:11 +0100492 DynamicBackendPtr dynamicBackend;
Matteo Martincighbc2e2102019-07-24 14:56:13 +0100493 BOOST_CHECK_THROW(dynamicBackend.reset(new DynamicBackend(sharedObjectHandle)), RuntimeException);
494 BOOST_TEST((dynamicBackend == nullptr));
495}
496
497void CreateDynamicBackendObjectInvalidInterface4TestImpl()
498{
499 // Valid shared object handle
500 // Correct name mangling
501 // Wrong interface (missing BackendFactory())
502
503 using namespace armnn;
504
Matteo Martincighd0dc7702019-08-01 17:09:03 +0100505 std::string testSubDirectory = GetTestSubDirectory(g_TestDynamicBackendSubDir);
506 std::string sharedObjectFilePath = GetTestFilePath(testSubDirectory, g_TestInvalidTestDynamicBackend4FileName);
Matteo Martincighbc2e2102019-07-24 14:56:13 +0100507
508 void* sharedObjectHandle = nullptr;
509 BOOST_CHECK_NO_THROW(sharedObjectHandle = DynamicBackendUtils::OpenHandle(sharedObjectFilePath));
510 BOOST_TEST((sharedObjectHandle != nullptr));
511
Matteo Martincighe54aa062019-08-05 14:12:11 +0100512 DynamicBackendPtr dynamicBackend;
Matteo Martincighbc2e2102019-07-24 14:56:13 +0100513 BOOST_CHECK_THROW(dynamicBackend.reset(new DynamicBackend(sharedObjectHandle)), RuntimeException);
514 BOOST_TEST((dynamicBackend == nullptr));
515}
516
517void CreateDynamicBackendObjectInvalidInterface5TestImpl()
518{
519 // Valid shared object handle
520 // Correct name mangling
521 // Correct interface
522 // Invalid (null) backend id returned by GetBackendId()
523
524 using namespace armnn;
525
Matteo Martincighd0dc7702019-08-01 17:09:03 +0100526 std::string testSubDirectory = GetTestSubDirectory(g_TestDynamicBackendSubDir);
527 std::string sharedObjectFilePath = GetTestFilePath(testSubDirectory, g_TestInvalidTestDynamicBackend5FileName);
Matteo Martincighbc2e2102019-07-24 14:56:13 +0100528
529 void* sharedObjectHandle = nullptr;
530 BOOST_CHECK_NO_THROW(sharedObjectHandle = DynamicBackendUtils::OpenHandle(sharedObjectFilePath));
531 BOOST_TEST((sharedObjectHandle != nullptr));
532
Matteo Martincighe54aa062019-08-05 14:12:11 +0100533 DynamicBackendPtr dynamicBackend;
Matteo Martincighbc2e2102019-07-24 14:56:13 +0100534 BOOST_CHECK_THROW(dynamicBackend.reset(new DynamicBackend(sharedObjectHandle)), RuntimeException);
535 BOOST_TEST((dynamicBackend == nullptr));
536}
537
538void CreateDynamicBackendObjectInvalidInterface6TestImpl()
539{
540 // Valid shared object handle
541 // Correct name mangling
542 // Correct interface
543 // Invalid (null) backend instance returned by BackendFactory()
544
545 using namespace armnn;
546
Matteo Martincighd0dc7702019-08-01 17:09:03 +0100547 std::string testSubDirectory = GetTestSubDirectory(g_TestDynamicBackendSubDir);
548 std::string sharedObjectFilePath = GetTestFilePath(testSubDirectory, g_TestInvalidTestDynamicBackend6FileName);
Matteo Martincighbc2e2102019-07-24 14:56:13 +0100549
550 void* sharedObjectHandle = nullptr;
551 BOOST_CHECK_NO_THROW(sharedObjectHandle = DynamicBackendUtils::OpenHandle(sharedObjectFilePath));
552 BOOST_TEST((sharedObjectHandle != nullptr));
553
Matteo Martincighe54aa062019-08-05 14:12:11 +0100554 DynamicBackendPtr dynamicBackend;
Matteo Martincighbc2e2102019-07-24 14:56:13 +0100555 BOOST_CHECK_NO_THROW(dynamicBackend.reset(new DynamicBackend(sharedObjectHandle)));
556 BOOST_TEST((dynamicBackend != nullptr));
557
558 BackendId dynamicBackendId;
559 BOOST_CHECK_NO_THROW(dynamicBackendId = dynamicBackend->GetBackendId());
560 BOOST_TEST((dynamicBackendId == "InvalidTestDynamicBackend"));
561
562 BackendVersion dynamicBackendVersion;
563 BOOST_CHECK_NO_THROW(dynamicBackendVersion = dynamicBackend->GetBackendVersion());
564 BOOST_TEST((dynamicBackendVersion == BackendVersion({ 1, 0 })));
565
Matteo Martincigh0c2b2892019-08-05 14:12:11 +0100566 IBackendInternalUniquePtr dynamicBackendInstance1;
567 BOOST_CHECK_THROW(dynamicBackendInstance1 = dynamicBackend->GetBackend(), RuntimeException);
568 BOOST_TEST((dynamicBackendInstance1 == nullptr));
569
570 BackendRegistry::FactoryFunction dynamicBackendFactoryFunction = nullptr;
571 BOOST_CHECK_NO_THROW(dynamicBackendFactoryFunction = dynamicBackend->GetFactoryFunction());
572 BOOST_TEST((dynamicBackendFactoryFunction != nullptr));
573
574 IBackendInternalUniquePtr dynamicBackendInstance2;
575 BOOST_CHECK_THROW(dynamicBackendInstance2 = dynamicBackendFactoryFunction(), RuntimeException);
576 BOOST_TEST((dynamicBackendInstance2 == nullptr));
Matteo Martincighbc2e2102019-07-24 14:56:13 +0100577}
578
579void CreateDynamicBackendObjectInvalidInterface7TestImpl()
580{
581 // Valid shared object handle
582 // Correct name mangling
583 // Correct interface
584 // Invalid (incompatible backend API version) backend instance returned by BackendFactory()
585
586 using namespace armnn;
587
Matteo Martincighd0dc7702019-08-01 17:09:03 +0100588 std::string testSubDirectory = GetTestSubDirectory(g_TestDynamicBackendSubDir);
589 std::string sharedObjectFilePath = GetTestFilePath(testSubDirectory, g_TestInvalidTestDynamicBackend7FileName);
Matteo Martincighbc2e2102019-07-24 14:56:13 +0100590
591 void* sharedObjectHandle = nullptr;
592 BOOST_CHECK_NO_THROW(sharedObjectHandle = DynamicBackendUtils::OpenHandle(sharedObjectFilePath));
593 BOOST_TEST((sharedObjectHandle != nullptr));
594
Matteo Martincighe54aa062019-08-05 14:12:11 +0100595 DynamicBackendPtr dynamicBackend;
Matteo Martincighbc2e2102019-07-24 14:56:13 +0100596 BOOST_CHECK_THROW(dynamicBackend.reset(new DynamicBackend(sharedObjectHandle)), RuntimeException);
597 BOOST_TEST((dynamicBackend == nullptr));
598}
Matteo Martincighe7d44982019-08-05 12:16:47 +0100599
600void GetBackendPathsTestImpl()
601{
602 using namespace armnn;
Francis Murtagh532a29d2020-06-29 11:50:01 +0100603 using namespace fs;
Matteo Martincighe7d44982019-08-05 12:16:47 +0100604
605 // The test covers four directories:
606 // <unit test path>/src/backends/backendsCommon/test/
Matteo Martincighe54aa062019-08-05 14:12:11 +0100607 // ├─ backendsTestPath1/ -> exists, contains files
608 // ├─ backendsTestPath2/ -> exists, contains files
609 // ├─ backendsTestPath3/ -> exists, but empty
610 // └─ backendsTestPath4/ -> does not exist
Matteo Martincighe7d44982019-08-05 12:16:47 +0100611
Matteo Martincigh0c2b2892019-08-05 14:12:11 +0100612 std::string subDir1 = GetTestSubDirectory(g_TestDynamicBackendsSubDir1);
613 std::string subDir2 = GetTestSubDirectory(g_TestDynamicBackendsSubDir2);
614 std::string subDir3 = GetTestSubDirectory(g_TestDynamicBackendsSubDir3);
615 std::string subDir4 = GetTestSubDirectory(g_TestDynamicBackendsSubDir4);
Matteo Martincighe7d44982019-08-05 12:16:47 +0100616
617 BOOST_CHECK(exists(subDir1));
618 BOOST_CHECK(exists(subDir2));
619 BOOST_CHECK(exists(subDir3));
620 BOOST_CHECK(!exists(subDir4));
621
Matteo Martincighe7d44982019-08-05 12:16:47 +0100622 // No path
623 BOOST_TEST(TestDynamicBackendUtils::GetBackendPathsImplTest("").empty());
624
625 // Malformed path
626 std::string malformedDir(subDir1 + "/" + subDir1);
627 BOOST_TEST(TestDynamicBackendUtils::GetBackendPathsImplTest(malformedDir).size()==0);
628
629 // Single valid path
630 std::vector<std::string> DynamicBackendPaths2 = TestDynamicBackendUtils::GetBackendPathsImplTest(subDir1);
631 BOOST_TEST(DynamicBackendPaths2.size() == 1);
632 BOOST_TEST(DynamicBackendPaths2[0] == subDir1);
633
634 // Multiple equal and valid paths
635 std::string multipleEqualDirs(subDir1 + ":" + subDir1);
636 std::vector<std::string> DynamicBackendPaths3 = TestDynamicBackendUtils::GetBackendPathsImplTest(multipleEqualDirs);
637 BOOST_TEST(DynamicBackendPaths3.size() == 1);
638 BOOST_TEST(DynamicBackendPaths3[0] == subDir1);
639
640 // Multiple empty paths
641 BOOST_TEST(TestDynamicBackendUtils::GetBackendPathsImplTest(":::").empty());
642
643 // Multiple valid paths
644 std::string multipleValidPaths(subDir1 + ":" + subDir2 + ":" + subDir3);
645 std::vector<std::string> DynamicBackendPaths5 =
646 TestDynamicBackendUtils::GetBackendPathsImplTest(multipleValidPaths);
647 BOOST_TEST(DynamicBackendPaths5.size() == 3);
648 BOOST_TEST(DynamicBackendPaths5[0] == subDir1);
649 BOOST_TEST(DynamicBackendPaths5[1] == subDir2);
650 BOOST_TEST(DynamicBackendPaths5[2] == subDir3);
651
652 // Valid among empty paths
653 std::string validAmongEmptyDirs("::" + subDir1 + ":");
654 std::vector<std::string> DynamicBackendPaths6 =
655 TestDynamicBackendUtils::GetBackendPathsImplTest(validAmongEmptyDirs);
656 BOOST_TEST(DynamicBackendPaths6.size() == 1);
657 BOOST_TEST(DynamicBackendPaths6[0] == subDir1);
658
659 // Invalid among empty paths
660 std::string invalidAmongEmptyDirs(":" + subDir4 + "::");
661 BOOST_TEST(TestDynamicBackendUtils::GetBackendPathsImplTest(invalidAmongEmptyDirs).empty());
662
663 // Valid, invalid and empty paths
664 std::string validInvalidEmptyDirs(subDir1 + ":" + subDir4 + ":");
665 std::vector<std::string> DynamicBackendPaths8 =
666 TestDynamicBackendUtils::GetBackendPathsImplTest(validInvalidEmptyDirs);
667 BOOST_TEST(DynamicBackendPaths8.size() == 1);
668 BOOST_TEST(DynamicBackendPaths8[0] == subDir1);
669
670 // Mix of duplicates of valid, invalid and empty paths
671 std::string duplicateValidInvalidEmptyDirs(validInvalidEmptyDirs + ":" + validInvalidEmptyDirs + ":" +
672 subDir2 + ":" + subDir2);
673 std::vector<std::string> DynamicBackendPaths9 =
674 TestDynamicBackendUtils::GetBackendPathsImplTest(duplicateValidInvalidEmptyDirs);
675 BOOST_TEST(DynamicBackendPaths9.size() == 2);
676 BOOST_TEST(DynamicBackendPaths9[0] == subDir1);
677 BOOST_TEST(DynamicBackendPaths9[1] == subDir2);
678}
679
680void GetBackendPathsOverrideTestImpl()
681{
682 using namespace armnn;
Francis Murtagh532a29d2020-06-29 11:50:01 +0100683 using namespace fs;
Matteo Martincighe7d44982019-08-05 12:16:47 +0100684
Matteo Martincigh0c2b2892019-08-05 14:12:11 +0100685 std::string subDir1 = GetTestSubDirectory(g_TestDynamicBackendsSubDir1);
686 std::string subDir4 = GetTestSubDirectory(g_TestDynamicBackendsSubDir4);
Matteo Martincighe7d44982019-08-05 12:16:47 +0100687
688 BOOST_CHECK(exists(subDir1));
689 BOOST_CHECK(!exists(subDir4));
690
691 // Override with valid path
692 std::vector<std::string> validResult = DynamicBackendUtils::GetBackendPaths(subDir1);
693 BOOST_TEST(validResult.size() == 1);
694 BOOST_TEST(validResult[0] == subDir1);
695
696 // Override with invalid path
697 std::vector<std::string> invalidResult = DynamicBackendUtils::GetBackendPaths(subDir4);
698 BOOST_TEST(invalidResult.empty());
699}
Jan Eilers4a539fc2019-07-25 17:08:37 +0100700
701void GetSharedObjectsTestImpl()
702{
703 using namespace armnn;
Francis Murtagh532a29d2020-06-29 11:50:01 +0100704 using namespace fs;
Jan Eilers4a539fc2019-07-25 17:08:37 +0100705
Matteo Martincighe54aa062019-08-05 14:12:11 +0100706 // The test covers four directories:
707 // <unit test path>/src/backends/backendsCommon/test/
708 // ├─ backendsTestPath1/ -> exists, contains files
709 // ├─ backendsTestPath2/ -> exists, contains files
710 // ├─ backendsTestPath3/ -> exists, but empty
711 // └─ backendsTestPath4/ -> does not exist
Jan Eilers4a539fc2019-07-25 17:08:37 +0100712 //
713 // The test sub-directory backendsTestPath1/ contains the following test files:
714 //
715 // Arm_GpuAcc_backend.so -> valid (basic backend name)
716 // Arm_GpuAcc_backend.so.1 -> valid (single field version number)
717 // Arm_GpuAcc_backend.so.1.2 -> valid (multiple field version number)
718 // Arm_GpuAcc_backend.so.1.2.3 -> valid (multiple field version number)
719 // Arm_GpuAcc_backend.so.10.1.27 -> valid (Multiple digit version)
720 // Arm_GpuAcc_backend.so.10.1.33. -> not valid (dot not followed by version number)
721 // Arm_GpuAcc_backend.so.3.4..5 -> not valid (dot not followed by version number)
722 // Arm_GpuAcc_backend.so.1,1.1 -> not valid (comma instead of dot in the version)
723 //
724 // Arm123_GpuAcc_backend.so -> valid (digits in vendor name are allowed)
725 // Arm_GpuAcc456_backend.so -> valid (digits in backend id are allowed)
726 // Arm%Co_GpuAcc_backend.so -> not valid (invalid character in vendor name)
727 // Arm_Gpu.Acc_backend.so -> not valid (invalid character in backend id)
728 //
729 // GpuAcc_backend.so -> not valid (missing vendor name)
730 // _GpuAcc_backend.so -> not valid (missing vendor name)
731 // Arm__backend.so -> not valid (missing backend id)
732 // Arm_GpuAcc.so -> not valid (missing "backend" at the end)
733 // __backend.so -> not valid (missing vendor name and backend id)
734 // __.so -> not valid (missing all fields)
735 //
736 // Arm_GpuAcc_backend -> not valid (missing at least ".so" at the end)
737 // Arm_GpuAcc_backend_v1.2.so -> not valid (extra version info at the end)
738 //
739 // The test sub-directory backendsTestPath1/ contains the following test files:
740 //
741 // Arm_CpuAcc_backend.so -> valid (basic backend name)
742 // Arm_CpuAcc_backend.so.1 -> Arm_CpuAcc_backend.so -> valid (symlink to valid backend file)
743 // Arm_CpuAcc_backend.so.1.2 -> Arm_CpuAcc_backend.so.1 -> valid (symlink to valid symlink)
744 // Arm_CpuAcc_backend.so.1.2.3 -> Arm_CpuAcc_backend.so.1.2 -> valid (symlink to valid symlink)
745 //
746 // Arm_no_backend.so -> nothing -> not valid (symlink resolves to non-existent file)
747 //
748 // Arm_GpuAcc_backend.so -> valid (but duplicated from backendsTestPath1/)
749
Matteo Martincigh0c2b2892019-08-05 14:12:11 +0100750 std::string testDynamicBackendsSubDir1 = GetTestSubDirectory(g_TestDynamicBackendsSubDir1);
751 std::string testDynamicBackendsSubDir2 = GetTestSubDirectory(g_TestDynamicBackendsSubDir2);
752 std::string testDynamicBackendsSubDir3 = GetTestSubDirectory(g_TestDynamicBackendsSubDir3);
753 std::string testDynamicBackendsSubDir4 = GetTestSubDirectory(g_TestDynamicBackendsSubDir4);
Jan Eilers4a539fc2019-07-25 17:08:37 +0100754 BOOST_CHECK(exists(testDynamicBackendsSubDir1));
755 BOOST_CHECK(exists(testDynamicBackendsSubDir2));
756 BOOST_CHECK(exists(testDynamicBackendsSubDir3));
757 BOOST_CHECK(!exists(testDynamicBackendsSubDir4));
758
759 std::vector<std::string> backendPaths
760 {
761 testDynamicBackendsSubDir1,
762 testDynamicBackendsSubDir2,
763 testDynamicBackendsSubDir3,
764 testDynamicBackendsSubDir4
765 };
766 std::vector<std::string> sharedObjects = DynamicBackendUtils::GetSharedObjects(backendPaths);
Colm Donelanaa93d982020-06-28 08:16:46 +0100767 std::vector<fs::path> expectedSharedObjects
Jan Eilers4a539fc2019-07-25 17:08:37 +0100768 {
Colm Donelanaa93d982020-06-28 08:16:46 +0100769 path(testDynamicBackendsSubDir1 + "Arm123_GpuAcc_backend.so"), // Digits in vendor name are allowed
770 path(testDynamicBackendsSubDir1 + "Arm_GpuAcc456_backend.so"), // Digits in backend id are allowed
771 path(testDynamicBackendsSubDir1 + "Arm_GpuAcc_backend.so"), // Basic backend name
772 path(testDynamicBackendsSubDir1 + "Arm_GpuAcc_backend.so.1"), // Single field version number
773 path(testDynamicBackendsSubDir1 + "Arm_GpuAcc_backend.so.1.2"), // Multiple field version number
774 path(testDynamicBackendsSubDir1 + "Arm_GpuAcc_backend.so.1.2.3"), // Multiple field version number
775 path(testDynamicBackendsSubDir1 + "Arm_GpuAcc_backend.so.10.1.27"), // Multiple digit version
776 path(testDynamicBackendsSubDir2 + "Arm_CpuAcc_backend.so"), // Duplicate symlinks removed
777 path(testDynamicBackendsSubDir2 + "Arm_GpuAcc_backend.so") // Duplicates on different paths are allowed
Jan Eilers4a539fc2019-07-25 17:08:37 +0100778 };
779
780 BOOST_TEST(sharedObjects.size() == expectedSharedObjects.size());
Colm Donelanaa93d982020-06-28 08:16:46 +0100781 BOOST_TEST(fs::equivalent(path(sharedObjects[0]), expectedSharedObjects[0]));
782 BOOST_TEST(fs::equivalent(path(sharedObjects[1]), expectedSharedObjects[1]));
783 BOOST_TEST(fs::equivalent(path(sharedObjects[2]), expectedSharedObjects[2]));
784 BOOST_TEST(fs::equivalent(path(sharedObjects[3]), expectedSharedObjects[3]));
785 BOOST_TEST(fs::equivalent(path(sharedObjects[4]), expectedSharedObjects[4]));
786 BOOST_TEST(fs::equivalent(path(sharedObjects[5]), expectedSharedObjects[5]));
787 BOOST_TEST(fs::equivalent(path(sharedObjects[6]), expectedSharedObjects[6]));
788 BOOST_TEST(fs::equivalent(path(sharedObjects[7]), expectedSharedObjects[7]));
789 BOOST_TEST(fs::equivalent(path(sharedObjects[8]), expectedSharedObjects[8]));
Matteo Martincighe54aa062019-08-05 14:12:11 +0100790}
791
792void CreateDynamicBackendsTestImpl()
793{
794 using namespace armnn;
Francis Murtagh532a29d2020-06-29 11:50:01 +0100795 using namespace fs;
Matteo Martincighe54aa062019-08-05 14:12:11 +0100796
Matteo Martincigh0c2b2892019-08-05 14:12:11 +0100797 // The test covers four directories:
Matteo Martincighe54aa062019-08-05 14:12:11 +0100798 // <unit test path>/src/backends/backendsCommon/test/
799 // ├─ backendsTestPath5/ -> exists, contains files
800 // ├─ backendsTestPath6/ -> exists, contains files
801 // ├─ backendsTestPath7/ -> exists, but empty
802 // └─ backendsTestPath8/ -> does not exist
803 //
804 // The test sub-directory backendsTestPath5/ contains the following test files:
805 //
806 // Arm_TestValid2_backend.so -> valid (basic backend name)
807 // Arm_TestValid3_backend.so -> valid (basic backend name)
808 // Arm_TestInvalid8_backend.so -> not valid (invalid backend id)
809 //
810 // The test sub-directory backendsTestPath6/ contains the following test files:
811 //
812 // Arm_TestValid2_backend.so -> valid (but duplicated from backendsTestPath5/)
813 // Arm_TestValid4_backend.so -> valid (it has a different filename,
814 // but it has the same backend id of Arm_TestValid2_backend.so
815 // and the same version)
Matteo Martincigh0c2b2892019-08-05 14:12:11 +0100816 // Arm_TestValid5_backend.so -> valid (basic backend name)
Matteo Martincighe54aa062019-08-05 14:12:11 +0100817 // Arm_TestInvalid9_backend.so -> not valid (it has a different filename,
818 // but it has the same backend id of Arm_TestValid2_backend.so
819 // and a version incompatible with the Backend API)
820
Matteo Martincigh0c2b2892019-08-05 14:12:11 +0100821 std::string testDynamicBackendsSubDir5 = GetTestSubDirectory(g_TestDynamicBackendsSubDir5);
822 std::string testDynamicBackendsSubDir6 = GetTestSubDirectory(g_TestDynamicBackendsSubDir6);
823 std::string testDynamicBackendsSubDir7 = GetTestSubDirectory(g_TestDynamicBackendsSubDir7);
824 std::string testDynamicBackendsSubDir8 = GetTestSubDirectory(g_TestDynamicBackendsSubDir8);
Matteo Martincighe54aa062019-08-05 14:12:11 +0100825 BOOST_CHECK(exists(testDynamicBackendsSubDir5));
826 BOOST_CHECK(exists(testDynamicBackendsSubDir6));
827 BOOST_CHECK(exists(testDynamicBackendsSubDir7));
828 BOOST_CHECK(!exists(testDynamicBackendsSubDir8));
829
830 std::vector<std::string> backendPaths
Jan Eilers4a539fc2019-07-25 17:08:37 +0100831 {
Matteo Martincighe54aa062019-08-05 14:12:11 +0100832 testDynamicBackendsSubDir5,
833 testDynamicBackendsSubDir6,
834 testDynamicBackendsSubDir7,
835 testDynamicBackendsSubDir8
836 };
837 std::vector<std::string> sharedObjects = DynamicBackendUtils::GetSharedObjects(backendPaths);
838 std::vector<DynamicBackendPtr> dynamicBackends = DynamicBackendUtils::CreateDynamicBackends(sharedObjects);
839
Matteo Martincigh0c2b2892019-08-05 14:12:11 +0100840 BOOST_TEST(dynamicBackends.size() == 5);
Matteo Martincighe54aa062019-08-05 14:12:11 +0100841 BOOST_TEST((dynamicBackends[0] != nullptr));
842 BOOST_TEST((dynamicBackends[1] != nullptr));
843 BOOST_TEST((dynamicBackends[2] != nullptr));
844 BOOST_TEST((dynamicBackends[3] != nullptr));
Matteo Martincigh0c2b2892019-08-05 14:12:11 +0100845 BOOST_TEST((dynamicBackends[4] != nullptr));
Matteo Martincighe54aa062019-08-05 14:12:11 +0100846
847 // Duplicates are allowed here, they will be skipped later during the backend registration
848 BOOST_TEST((dynamicBackends[0]->GetBackendId() == "TestValid2"));
849 BOOST_TEST((dynamicBackends[1]->GetBackendId() == "TestValid3"));
850 BOOST_TEST((dynamicBackends[2]->GetBackendId() == "TestValid2")); // From duplicate Arm_TestValid2_backend.so
851 BOOST_TEST((dynamicBackends[3]->GetBackendId() == "TestValid2")); // From Arm_TestValid4_backend.so
Matteo Martincigh0c2b2892019-08-05 14:12:11 +0100852 BOOST_TEST((dynamicBackends[4]->GetBackendId() == "TestValid5"));
Matteo Martincighe54aa062019-08-05 14:12:11 +0100853}
854
855void CreateDynamicBackendsNoPathsTestImpl()
856{
857 using namespace armnn;
858
859 std::vector<DynamicBackendPtr> dynamicBackends = DynamicBackendUtils::CreateDynamicBackends({});
860
861 BOOST_TEST(dynamicBackends.empty());
862}
863
864void CreateDynamicBackendsAllInvalidTestImpl()
865{
866 using namespace armnn;
867
868 std::vector<std::string> sharedObjects
869 {
870 "InvalidSharedObject1",
871 "InvalidSharedObject2",
872 "InvalidSharedObject3",
873 };
874 std::vector<DynamicBackendPtr> dynamicBackends = DynamicBackendUtils::CreateDynamicBackends(sharedObjects);
875
876 BOOST_TEST(dynamicBackends.empty());
877}
878
879void CreateDynamicBackendsMixedTypesTestImpl()
880{
881 using namespace armnn;
Francis Murtagh532a29d2020-06-29 11:50:01 +0100882 using namespace fs;
Matteo Martincighe54aa062019-08-05 14:12:11 +0100883
Matteo Martincigh0c2b2892019-08-05 14:12:11 +0100884 std::string testDynamicBackendsSubDir5 = GetTestSubDirectory(g_TestDynamicBackendsSubDir5);
885 std::string testDynamicBackendsSubDir6 = GetTestSubDirectory(g_TestDynamicBackendsSubDir6);
Matteo Martincighe54aa062019-08-05 14:12:11 +0100886 BOOST_CHECK(exists(testDynamicBackendsSubDir5));
887 BOOST_CHECK(exists(testDynamicBackendsSubDir6));
888
889 std::string testValidBackend2FilePath = GetTestFilePath(testDynamicBackendsSubDir5,
890 g_TestValidBackend2FileName);
891 std::string testInvalidBackend8FilePath = GetTestFilePath(testDynamicBackendsSubDir5,
892 g_TestInvalidBackend8FileName);
893 std::string testInvalidBackend9FilePath = GetTestFilePath(testDynamicBackendsSubDir6,
894 g_TestInvalidBackend9FileName);
895 BOOST_CHECK(exists(testValidBackend2FilePath));
896 BOOST_CHECK(exists(testInvalidBackend8FilePath));
897 BOOST_CHECK(exists(testInvalidBackend9FilePath));
898
899 std::vector<std::string> sharedObjects
900 {
901 testValidBackend2FilePath, // Arm_TestValid2_backend.so -> valid (basic backend name)
902 testInvalidBackend8FilePath, // Arm_TestInvalid8_backend.so -> not valid (invalid backend id)
903 testInvalidBackend9FilePath, // Arm_TestInvalid9_backend.so -> not valid (incompatible version)
904 "InvalidSharedObject", // The file does not exist
905 };
906 std::vector<DynamicBackendPtr> dynamicBackends = DynamicBackendUtils::CreateDynamicBackends(sharedObjects);
907
908 BOOST_TEST(dynamicBackends.size() == 1);
909 BOOST_TEST((dynamicBackends[0] != nullptr));
910 BOOST_TEST((dynamicBackends[0]->GetBackendId() == "TestValid2"));
Jan Eilers4a539fc2019-07-25 17:08:37 +0100911}
Matteo Martincigh0c2b2892019-08-05 14:12:11 +0100912
913void 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;
922 BOOST_TEST(backendRegistry.Size() == 0);
923
924 std::string testDynamicBackendsSubDir5 = GetTestSubDirectory(g_TestDynamicBackendsSubDir5);
925 BOOST_CHECK(exists(testDynamicBackendsSubDir5));
926
927 std::string testValidBackend2FilePath = GetTestFilePath(testDynamicBackendsSubDir5, g_TestValidBackend2FileName);
928 BOOST_CHECK(exists(testValidBackend2FilePath));
929
930 std::vector<std::string> sharedObjects{ testValidBackend2FilePath };
931 std::vector<DynamicBackendPtr> dynamicBackends = TestDynamicBackendUtils::CreateDynamicBackends(sharedObjects);
932
933 BOOST_TEST(dynamicBackends.size() == 1);
934 BOOST_TEST((dynamicBackends[0] != nullptr));
935
936 BackendId dynamicBackendId = dynamicBackends[0]->GetBackendId();
937 BOOST_TEST((dynamicBackendId == "TestValid2"));
938
939 BackendVersion dynamicBackendVersion = dynamicBackends[0]->GetBackendVersion();
940 BOOST_TEST(TestDynamicBackendUtils::IsBackendCompatible(dynamicBackendVersion));
941
Matteo Martincigh89533902019-08-15 12:08:06 +0100942 BackendIdSet registeredBackendIds = TestDynamicBackendUtils::RegisterDynamicBackendsImplTest(backendRegistry,
943 dynamicBackends);
Matteo Martincigh0c2b2892019-08-05 14:12:11 +0100944 BOOST_TEST(backendRegistry.Size() == 1);
Matteo Martincigh89533902019-08-15 12:08:06 +0100945 BOOST_TEST(registeredBackendIds.size() == 1);
Matteo Martincigh0c2b2892019-08-05 14:12:11 +0100946
947 BackendIdSet backendIds = backendRegistry.GetBackendIds();
948 BOOST_TEST(backendIds.size() == 1);
949 BOOST_TEST((backendIds.find(dynamicBackendId) != backendIds.end()));
Matteo Martincigh89533902019-08-15 12:08:06 +0100950 BOOST_TEST((registeredBackendIds.find(dynamicBackendId) != registeredBackendIds.end()));
Matteo Martincigh0c2b2892019-08-05 14:12:11 +0100951
952 auto dynamicBackendFactoryFunction = backendRegistry.GetFactory(dynamicBackendId);
953 BOOST_TEST((dynamicBackendFactoryFunction != nullptr));
954
955 IBackendInternalUniquePtr dynamicBackend = dynamicBackendFactoryFunction();
956 BOOST_TEST((dynamicBackend != nullptr));
957 BOOST_TEST((dynamicBackend->GetId() == dynamicBackendId));
958}
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);
969 BOOST_CHECK(exists(testDynamicBackendsSubDir5));
970 BOOST_CHECK(exists(testDynamicBackendsSubDir6));
971
972 std::string testValidBackend2FilePath = GetTestFilePath(testDynamicBackendsSubDir5, g_TestValidBackend2FileName);
973 std::string testValidBackend3FilePath = GetTestFilePath(testDynamicBackendsSubDir5, g_TestValidBackend3FileName);
974 std::string testValidBackend5FilePath = GetTestFilePath(testDynamicBackendsSubDir6, g_TestValidBackend5FileName);
975 BOOST_CHECK(exists(testValidBackend2FilePath));
976 BOOST_CHECK(exists(testValidBackend3FilePath));
977 BOOST_CHECK(exists(testValidBackend5FilePath));
978
979 std::vector<std::string> sharedObjects
980 {
981 testValidBackend2FilePath,
982 testValidBackend3FilePath,
983 testValidBackend5FilePath
984 };
985 std::vector<DynamicBackendPtr> dynamicBackends = TestDynamicBackendUtils::CreateDynamicBackends(sharedObjects);
986
987 BOOST_TEST(dynamicBackends.size() == 3);
988 BOOST_TEST((dynamicBackends[0] != nullptr));
989 BOOST_TEST((dynamicBackends[1] != nullptr));
990 BOOST_TEST((dynamicBackends[2] != nullptr));
991
992 BackendId dynamicBackendId1 = dynamicBackends[0]->GetBackendId();
993 BackendId dynamicBackendId2 = dynamicBackends[1]->GetBackendId();
994 BackendId dynamicBackendId3 = dynamicBackends[2]->GetBackendId();
995 BOOST_TEST((dynamicBackendId1 == "TestValid2"));
996 BOOST_TEST((dynamicBackendId2 == "TestValid3"));
997 BOOST_TEST((dynamicBackendId3 == "TestValid5"));
998
999 for (size_t i = 0; i < dynamicBackends.size(); i++)
1000 {
1001 BackendVersion dynamicBackendVersion = dynamicBackends[i]->GetBackendVersion();
1002 BOOST_TEST(TestDynamicBackendUtils::IsBackendCompatible(dynamicBackendVersion));
1003 }
1004
1005 // Dummy registry used for testing
1006 BackendRegistry backendRegistry;
1007 BOOST_TEST(backendRegistry.Size() == 0);
1008
Matteo Martincigh89533902019-08-15 12:08:06 +01001009 BackendIdSet registeredBackendIds = TestDynamicBackendUtils::RegisterDynamicBackendsImplTest(backendRegistry,
1010 dynamicBackends);
Matteo Martincigh0c2b2892019-08-05 14:12:11 +01001011 BOOST_TEST(backendRegistry.Size() == 3);
Matteo Martincigh89533902019-08-15 12:08:06 +01001012 BOOST_TEST(registeredBackendIds.size() == 3);
Matteo Martincigh0c2b2892019-08-05 14:12:11 +01001013
1014 BackendIdSet backendIds = backendRegistry.GetBackendIds();
1015 BOOST_TEST(backendIds.size() == 3);
1016 BOOST_TEST((backendIds.find(dynamicBackendId1) != backendIds.end()));
1017 BOOST_TEST((backendIds.find(dynamicBackendId2) != backendIds.end()));
1018 BOOST_TEST((backendIds.find(dynamicBackendId3) != backendIds.end()));
Matteo Martincigh89533902019-08-15 12:08:06 +01001019 BOOST_TEST((registeredBackendIds.find(dynamicBackendId1) != registeredBackendIds.end()));
1020 BOOST_TEST((registeredBackendIds.find(dynamicBackendId2) != registeredBackendIds.end()));
1021 BOOST_TEST((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);
1028 BOOST_TEST((dynamicBackendFactoryFunction != nullptr));
1029
1030 IBackendInternalUniquePtr dynamicBackend = dynamicBackendFactoryFunction();
1031 BOOST_TEST((dynamicBackend != nullptr));
1032 BOOST_TEST((dynamicBackend->GetId() == dynamicBackendId));
1033 }
1034}
1035
1036void RegisterMultipleInvalidDynamicBackendsTestImpl()
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 // Try to register many invalid dynamic backends
1042
1043 // The test covers one directory:
1044 // <unit test path>/src/backends/backendsCommon/test/
1045 // └─ backendsTestPath9/ -> exists, contains files
1046 //
1047 // The test sub-directory backendsTestPath9/ contains the following test files:
1048 //
1049 // Arm_TestInvalid10_backend.so -> not valid (invalid backend id)
1050 // Arm_TestInvalid11_backend.so -> not valid (invalid backend id)
1051
1052 std::string testDynamicBackendsSubDir9 = GetTestSubDirectory(g_TestDynamicBackendsSubDir9);
1053 BOOST_CHECK(exists(testDynamicBackendsSubDir9));
1054
1055 std::string testInvalidBackend10FilePath = GetTestFilePath(testDynamicBackendsSubDir9,
1056 g_TestInvalidBackend10FileName);
1057 std::string testInvalidBackend11FilePath = GetTestFilePath(testDynamicBackendsSubDir9,
1058 g_TestInvalidBackend11FileName);
1059 BOOST_CHECK(exists(testInvalidBackend10FilePath));
1060 BOOST_CHECK(exists(testInvalidBackend11FilePath));
1061
1062 std::vector<std::string> sharedObjects
1063 {
1064 testInvalidBackend10FilePath,
1065 testInvalidBackend11FilePath,
1066 "InvalidSharedObject"
1067 };
1068 std::vector<DynamicBackendPtr> dynamicBackends = TestDynamicBackendUtils::CreateDynamicBackends(sharedObjects);
1069
1070 BOOST_TEST(dynamicBackends.size() == 2);
1071 BOOST_TEST((dynamicBackends[0] != nullptr));
1072 BOOST_TEST((dynamicBackends[1] != nullptr));
1073
1074 BackendId dynamicBackendId1 = dynamicBackends[0]->GetBackendId();
1075 BackendId dynamicBackendId2 = dynamicBackends[1]->GetBackendId();
1076 BOOST_TEST((dynamicBackendId1 == ""));
1077 BOOST_TEST((dynamicBackendId2 == "Unknown"));
1078
1079 for (size_t i = 0; i < dynamicBackends.size(); i++)
1080 {
1081 BackendVersion dynamicBackendVersion = dynamicBackends[i]->GetBackendVersion();
1082 BOOST_TEST(TestDynamicBackendUtils::IsBackendCompatible(dynamicBackendVersion));
1083 }
1084
1085 // Dummy registry used for testing
1086 BackendRegistry backendRegistry;
1087 BOOST_TEST(backendRegistry.Size() == 0);
1088
1089 // Check that no dynamic backend got registered
Matteo Martincigh89533902019-08-15 12:08:06 +01001090 BackendIdSet registeredBackendIds = TestDynamicBackendUtils::RegisterDynamicBackendsImplTest(backendRegistry,
1091 dynamicBackends);
Matteo Martincigh0c2b2892019-08-05 14:12:11 +01001092 BOOST_TEST(backendRegistry.Size() == 0);
Matteo Martincigh89533902019-08-15 12:08:06 +01001093 BOOST_TEST(registeredBackendIds.empty());
Matteo Martincigh0c2b2892019-08-05 14:12:11 +01001094}
1095
1096void RegisterMixedDynamicBackendsTestImpl()
1097{
1098 using namespace armnn;
Francis Murtagh532a29d2020-06-29 11:50:01 +01001099 using namespace fs;
Matteo Martincigh0c2b2892019-08-05 14:12:11 +01001100
1101 // The test covers five directories:
1102 // <unit test path>/src/backends/backendsCommon/test/
1103 // ├─ backendsTestPath5/ -> exists, contains files
1104 // ├─ backendsTestPath6/ -> exists, contains files
1105 // ├─ backendsTestPath7/ -> exists, but empty
1106 // ├─ backendsTestPath8/ -> does not exist
1107 // └─ backendsTestPath9/ -> exists, contains files
1108 //
1109 // The test sub-directory backendsTestPath5/ contains the following test files:
1110 //
1111 // Arm_TestValid2_backend.so -> valid (basic backend name)
1112 // Arm_TestValid3_backend.so -> valid (basic backend name)
1113 // Arm_TestInvalid8_backend.so -> not valid (invalid backend id)
1114 //
1115 // The test sub-directory backendsTestPath6/ contains the following test files:
1116 //
1117 // Arm_TestValid2_backend.so -> valid (but duplicated from backendsTestPath5/)
1118 // Arm_TestValid4_backend.so -> valid (it has a different filename,
1119 // but it has the same backend id of Arm_TestValid2_backend.so
1120 // and the same version)
1121 // Arm_TestValid5_backend.so -> valid (basic backend name)
1122 // Arm_TestInvalid9_backend.so -> not valid (it has a different filename,
1123 // but it has the same backend id of Arm_TestValid2_backend.so
1124 // and a version incompatible with the Backend API)
1125 //
1126 // The test sub-directory backendsTestPath9/ contains the following test files:
1127 //
1128 // Arm_TestInvalid10_backend.so -> not valid (empty backend id)
1129 // Arm_TestInvalid11_backend.so -> not valid ("Unknown" backend id)
1130
1131 std::string testDynamicBackendsSubDir5 = GetTestSubDirectory(g_TestDynamicBackendsSubDir5);
1132 std::string testDynamicBackendsSubDir6 = GetTestSubDirectory(g_TestDynamicBackendsSubDir6);
1133 std::string testDynamicBackendsSubDir7 = GetTestSubDirectory(g_TestDynamicBackendsSubDir7);
1134 std::string testDynamicBackendsSubDir8 = GetTestSubDirectory(g_TestDynamicBackendsSubDir8);
1135 std::string testDynamicBackendsSubDir9 = GetTestSubDirectory(g_TestDynamicBackendsSubDir9);
1136 BOOST_CHECK(exists(testDynamicBackendsSubDir5));
1137 BOOST_CHECK(exists(testDynamicBackendsSubDir6));
1138 BOOST_CHECK(exists(testDynamicBackendsSubDir7));
1139 BOOST_CHECK(!exists(testDynamicBackendsSubDir8));
1140 BOOST_CHECK(exists(testDynamicBackendsSubDir9));
1141
1142 std::string testValidBackend2FilePath = GetTestFilePath(testDynamicBackendsSubDir5, g_TestValidBackend2FileName);
1143 std::string testValidBackend3FilePath = GetTestFilePath(testDynamicBackendsSubDir5, g_TestValidBackend3FileName);
1144 std::string testValidBackend2DupFilePath = GetTestFilePath(testDynamicBackendsSubDir6, g_TestValidBackend2FileName);
1145 std::string testValidBackend4FilePath = GetTestFilePath(testDynamicBackendsSubDir6, g_TestValidBackend4FileName);
1146 std::string testValidBackend5FilePath = GetTestFilePath(testDynamicBackendsSubDir6, g_TestValidBackend5FileName);
1147 std::string testInvalidBackend8FilePath = GetTestFilePath(testDynamicBackendsSubDir5,
1148 g_TestInvalidBackend8FileName);
1149 std::string testInvalidBackend9FilePath = GetTestFilePath(testDynamicBackendsSubDir6,
1150 g_TestInvalidBackend9FileName);
1151 std::string testInvalidBackend10FilePath = GetTestFilePath(testDynamicBackendsSubDir9,
1152 g_TestInvalidBackend10FileName);
1153 std::string testInvalidBackend11FilePath = GetTestFilePath(testDynamicBackendsSubDir9,
1154 g_TestInvalidBackend11FileName);
1155 BOOST_CHECK(exists(testValidBackend2FilePath));
1156 BOOST_CHECK(exists(testValidBackend3FilePath));
1157 BOOST_CHECK(exists(testValidBackend2DupFilePath));
1158 BOOST_CHECK(exists(testValidBackend4FilePath));
1159 BOOST_CHECK(exists(testValidBackend5FilePath));
1160 BOOST_CHECK(exists(testInvalidBackend8FilePath));
1161 BOOST_CHECK(exists(testInvalidBackend9FilePath));
1162 BOOST_CHECK(exists(testInvalidBackend10FilePath));
1163 BOOST_CHECK(exists(testInvalidBackend11FilePath));
1164
1165 std::vector<std::string> sharedObjects
1166 {
1167 testValidBackend2FilePath,
1168 testValidBackend3FilePath,
1169 testValidBackend2DupFilePath,
1170 testValidBackend4FilePath,
1171 testValidBackend5FilePath,
1172 testInvalidBackend8FilePath,
1173 testInvalidBackend9FilePath,
1174 testInvalidBackend10FilePath,
1175 testInvalidBackend11FilePath,
1176 "InvalidSharedObject"
1177 };
1178 std::vector<DynamicBackendPtr> dynamicBackends = TestDynamicBackendUtils::CreateDynamicBackends(sharedObjects);
1179
1180 BOOST_TEST(dynamicBackends.size() == 7);
1181 BOOST_TEST((dynamicBackends[0] != nullptr));
1182 BOOST_TEST((dynamicBackends[1] != nullptr));
1183 BOOST_TEST((dynamicBackends[2] != nullptr));
1184 BOOST_TEST((dynamicBackends[3] != nullptr));
1185 BOOST_TEST((dynamicBackends[4] != nullptr));
1186 BOOST_TEST((dynamicBackends[5] != nullptr));
1187 BOOST_TEST((dynamicBackends[6] != nullptr));
1188
1189 BackendId dynamicBackendId1 = dynamicBackends[0]->GetBackendId();
1190 BackendId dynamicBackendId2 = dynamicBackends[1]->GetBackendId();
1191 BackendId dynamicBackendId3 = dynamicBackends[2]->GetBackendId();
1192 BackendId dynamicBackendId4 = dynamicBackends[3]->GetBackendId();
1193 BackendId dynamicBackendId5 = dynamicBackends[4]->GetBackendId();
1194 BackendId dynamicBackendId6 = dynamicBackends[5]->GetBackendId();
1195 BackendId dynamicBackendId7 = dynamicBackends[6]->GetBackendId();
1196 BOOST_TEST((dynamicBackendId1 == "TestValid2"));
1197 BOOST_TEST((dynamicBackendId2 == "TestValid3"));
1198 BOOST_TEST((dynamicBackendId3 == "TestValid2")); // From duplicate Arm_TestValid2_backend.so
1199 BOOST_TEST((dynamicBackendId4 == "TestValid2")); // From Arm_TestValid4_backend.so
1200 BOOST_TEST((dynamicBackendId5 == "TestValid5"));
1201 BOOST_TEST((dynamicBackendId6 == ""));
1202 BOOST_TEST((dynamicBackendId7 == "Unknown"));
1203
1204 for (size_t i = 0; i < dynamicBackends.size(); i++)
1205 {
1206 BackendVersion dynamicBackendVersion = dynamicBackends[i]->GetBackendVersion();
1207 BOOST_TEST(TestDynamicBackendUtils::IsBackendCompatible(dynamicBackendVersion));
1208 }
1209
1210 // Dummy registry used for testing
1211 BackendRegistry backendRegistry;
1212 BOOST_TEST(backendRegistry.Size() == 0);
1213
1214 std::vector<BackendId> expectedRegisteredbackendIds
1215 {
1216 "TestValid2",
1217 "TestValid3",
1218 "TestValid5"
1219 };
1220
Matteo Martincigh89533902019-08-15 12:08:06 +01001221 BackendIdSet registeredBackendIds = TestDynamicBackendUtils::RegisterDynamicBackendsImplTest(backendRegistry,
1222 dynamicBackends);
Matteo Martincigh0c2b2892019-08-05 14:12:11 +01001223 BOOST_TEST(backendRegistry.Size() == expectedRegisteredbackendIds.size());
Matteo Martincigh89533902019-08-15 12:08:06 +01001224 BOOST_TEST(registeredBackendIds.size() == expectedRegisteredbackendIds.size());
Matteo Martincigh0c2b2892019-08-05 14:12:11 +01001225
1226 BackendIdSet backendIds = backendRegistry.GetBackendIds();
1227 BOOST_TEST(backendIds.size() == expectedRegisteredbackendIds.size());
1228 for (const BackendId& expectedRegisteredbackendId : expectedRegisteredbackendIds)
1229 {
1230 BOOST_TEST((backendIds.find(expectedRegisteredbackendId) != backendIds.end()));
Matteo Martincigh89533902019-08-15 12:08:06 +01001231 BOOST_TEST((registeredBackendIds.find(expectedRegisteredbackendId) != registeredBackendIds.end()));
Matteo Martincigh0c2b2892019-08-05 14:12:11 +01001232
1233 auto dynamicBackendFactoryFunction = backendRegistry.GetFactory(expectedRegisteredbackendId);
1234 BOOST_TEST((dynamicBackendFactoryFunction != nullptr));
1235
1236 IBackendInternalUniquePtr dynamicBackend = dynamicBackendFactoryFunction();
1237 BOOST_TEST((dynamicBackend != nullptr));
1238 BOOST_TEST((dynamicBackend->GetId() == expectedRegisteredbackendId));
1239 }
1240}
Matteo Martincigh3d8a9ed2019-08-08 10:49:03 +01001241
Narumol Prangnawarat60a20fb2019-12-09 17:24:41 +00001242#if !defined(ARMNN_DYNAMIC_BACKEND_ENABLED)
1243
Matteo Martincigh3d8a9ed2019-08-08 10:49:03 +01001244void RuntimeEmptyTestImpl()
1245{
1246 using namespace armnn;
1247
1248 // Swapping the backend registry storage for testing
1249 TestBackendRegistry testBackendRegistry;
1250
Matteo Martincigh89533902019-08-15 12:08:06 +01001251 const BackendRegistry& backendRegistry = BackendRegistryInstance();
1252 BOOST_TEST(backendRegistry.Size() == 0);
1253
Matteo Martincigh3d8a9ed2019-08-08 10:49:03 +01001254 IRuntime::CreationOptions creationOptions;
1255 IRuntimePtr runtime = IRuntime::Create(creationOptions);
1256
Jan Eilersbb446e52020-04-02 13:56:54 +01001257 const DeviceSpec& deviceSpec = *PolymorphicDowncast<const DeviceSpec*>(&runtime->GetDeviceSpec());
Matteo Martincigh89533902019-08-15 12:08:06 +01001258 BackendIdSet supportedBackendIds = deviceSpec.GetSupportedBackends();
1259 BOOST_TEST(supportedBackendIds.empty());
1260
Matteo Martincigh3d8a9ed2019-08-08 10:49:03 +01001261 BOOST_TEST(backendRegistry.Size() == 0);
1262}
1263
Narumol Prangnawarat60a20fb2019-12-09 17:24:41 +00001264#endif
1265
Matteo Martincigh3d8a9ed2019-08-08 10:49:03 +01001266void RuntimeDynamicBackendsTestImpl()
1267{
1268 using namespace armnn;
Francis Murtagh532a29d2020-06-29 11:50:01 +01001269 using namespace fs;
Matteo Martincigh3d8a9ed2019-08-08 10:49:03 +01001270
1271 // Swapping the backend registry storage for testing
1272 TestBackendRegistry testBackendRegistry;
1273
1274 // This directory contains valid and invalid backends
1275 std::string testDynamicBackendsSubDir5 = GetTestSubDirectory(g_TestDynamicBackendsSubDir5);
1276 BOOST_CHECK(exists(testDynamicBackendsSubDir5));
1277
1278 // Using the path override in CreationOptions to load some test dynamic backends
1279 IRuntime::CreationOptions creationOptions;
1280 creationOptions.m_DynamicBackendsPath = testDynamicBackendsSubDir5;
1281 IRuntimePtr runtime = IRuntime::Create(creationOptions);
1282
1283 std::vector<BackendId> expectedRegisteredbackendIds
1284 {
1285 "TestValid2",
1286 "TestValid3"
1287 };
1288
1289 const BackendRegistry& backendRegistry = BackendRegistryInstance();
1290 BOOST_TEST(backendRegistry.Size() == expectedRegisteredbackendIds.size());
1291
1292 BackendIdSet backendIds = backendRegistry.GetBackendIds();
1293 for (const BackendId& expectedRegisteredbackendId : expectedRegisteredbackendIds)
1294 {
1295 BOOST_TEST((backendIds.find(expectedRegisteredbackendId) != backendIds.end()));
1296 }
Matteo Martincigh89533902019-08-15 12:08:06 +01001297
Jan Eilersbb446e52020-04-02 13:56:54 +01001298 const DeviceSpec& deviceSpec = *PolymorphicDowncast<const DeviceSpec*>(&runtime->GetDeviceSpec());
Matteo Martincigh89533902019-08-15 12:08:06 +01001299 BackendIdSet supportedBackendIds = deviceSpec.GetSupportedBackends();
1300 BOOST_TEST(supportedBackendIds.size() == expectedRegisteredbackendIds.size());
1301 for (const BackendId& expectedRegisteredbackendId : expectedRegisteredbackendIds)
1302 {
1303 BOOST_TEST((supportedBackendIds.find(expectedRegisteredbackendId) != supportedBackendIds.end()));
1304 }
Matteo Martincigh3d8a9ed2019-08-08 10:49:03 +01001305}
1306
1307void RuntimeDuplicateDynamicBackendsTestImpl()
1308{
1309 using namespace armnn;
Francis Murtagh532a29d2020-06-29 11:50:01 +01001310 using namespace fs;
Matteo Martincigh3d8a9ed2019-08-08 10:49:03 +01001311
1312 // Swapping the backend registry storage for testing
1313 TestBackendRegistry testBackendRegistry;
1314
1315 // This directory contains valid, invalid and duplicate backends
1316 std::string testDynamicBackendsSubDir6 = GetTestSubDirectory(g_TestDynamicBackendsSubDir6);
1317 BOOST_CHECK(exists(testDynamicBackendsSubDir6));
1318
1319 // Using the path override in CreationOptions to load some test dynamic backends
1320 IRuntime::CreationOptions creationOptions;
1321 creationOptions.m_DynamicBackendsPath = testDynamicBackendsSubDir6;
1322 IRuntimePtr runtime = IRuntime::Create(creationOptions);
1323
1324 std::vector<BackendId> expectedRegisteredbackendIds
1325 {
1326 "TestValid2",
1327 "TestValid5"
1328 };
1329
1330 const BackendRegistry& backendRegistry = BackendRegistryInstance();
1331 BOOST_TEST(backendRegistry.Size() == expectedRegisteredbackendIds.size());
1332
1333 BackendIdSet backendIds = backendRegistry.GetBackendIds();
1334 for (const BackendId& expectedRegisteredbackendId : expectedRegisteredbackendIds)
1335 {
1336 BOOST_TEST((backendIds.find(expectedRegisteredbackendId) != backendIds.end()));
1337 }
Matteo Martincigh89533902019-08-15 12:08:06 +01001338
Jan Eilersbb446e52020-04-02 13:56:54 +01001339 const DeviceSpec& deviceSpec = *PolymorphicDowncast<const DeviceSpec*>(&runtime->GetDeviceSpec());
Matteo Martincigh89533902019-08-15 12:08:06 +01001340 BackendIdSet supportedBackendIds = deviceSpec.GetSupportedBackends();
1341 BOOST_TEST(supportedBackendIds.size() == expectedRegisteredbackendIds.size());
1342 for (const BackendId& expectedRegisteredbackendId : expectedRegisteredbackendIds)
1343 {
1344 BOOST_TEST((supportedBackendIds.find(expectedRegisteredbackendId) != supportedBackendIds.end()));
1345 }
Matteo Martincigh3d8a9ed2019-08-08 10:49:03 +01001346}
1347
1348void RuntimeInvalidDynamicBackendsTestImpl()
1349{
1350 using namespace armnn;
Francis Murtagh532a29d2020-06-29 11:50:01 +01001351 using namespace fs;
Matteo Martincigh3d8a9ed2019-08-08 10:49:03 +01001352
1353 // Swapping the backend registry storage for testing
1354 TestBackendRegistry testBackendRegistry;
1355
1356 // This directory contains only invalid backends
1357 std::string testDynamicBackendsSubDir9 = GetTestSubDirectory(g_TestDynamicBackendsSubDir9);
1358 BOOST_CHECK(exists(testDynamicBackendsSubDir9));
1359
1360 // Using the path override in CreationOptions to load some test dynamic backends
1361 IRuntime::CreationOptions creationOptions;
1362 creationOptions.m_DynamicBackendsPath = testDynamicBackendsSubDir9;
1363 IRuntimePtr runtime = IRuntime::Create(creationOptions);
1364
1365 const BackendRegistry& backendRegistry = BackendRegistryInstance();
1366 BOOST_TEST(backendRegistry.Size() == 0);
Matteo Martincigh89533902019-08-15 12:08:06 +01001367
Jan Eilersbb446e52020-04-02 13:56:54 +01001368 const DeviceSpec& deviceSpec = *PolymorphicDowncast<const DeviceSpec*>(&runtime->GetDeviceSpec());
Matteo Martincigh89533902019-08-15 12:08:06 +01001369 BackendIdSet supportedBackendIds = deviceSpec.GetSupportedBackends();
1370 BOOST_TEST(supportedBackendIds.empty());
Matteo Martincigh3d8a9ed2019-08-08 10:49:03 +01001371}
1372
1373void RuntimeInvalidOverridePathTestImpl()
1374{
1375 using namespace armnn;
1376
1377 // Swapping the backend registry storage for testing
1378 TestBackendRegistry testBackendRegistry;
1379
1380 // Using the path override in CreationOptions to load some test dynamic backends
1381 IRuntime::CreationOptions creationOptions;
1382 creationOptions.m_DynamicBackendsPath = "InvalidPath";
1383 IRuntimePtr runtime = IRuntime::Create(creationOptions);
1384
1385 const BackendRegistry& backendRegistry = BackendRegistryInstance();
1386 BOOST_TEST(backendRegistry.Size() == 0);
Matteo Martincigh89533902019-08-15 12:08:06 +01001387
Jan Eilersbb446e52020-04-02 13:56:54 +01001388 const DeviceSpec& deviceSpec = *PolymorphicDowncast<const DeviceSpec*>(&runtime->GetDeviceSpec());
Matteo Martincigh89533902019-08-15 12:08:06 +01001389 BackendIdSet supportedBackendIds = deviceSpec.GetSupportedBackends();
1390 BOOST_TEST(supportedBackendIds.empty());
Matteo Martincigh3d8a9ed2019-08-08 10:49:03 +01001391}
Matteo Martincigh4e73b422019-08-08 13:46:32 +01001392
Matteo Martincighdb16dd32019-08-27 16:41:11 +01001393#if defined(ARMNNREF_ENABLED)
Matteo Martincighe67edb22019-08-14 14:05:46 +01001394
1395// This test unit needs the reference backend, it's not available if the reference backend is not built
1396
Matteo Martincigh4e73b422019-08-08 13:46:32 +01001397void CreateReferenceDynamicBackendTestImpl()
1398{
1399 using namespace armnn;
Francis Murtagh532a29d2020-06-29 11:50:01 +01001400 using namespace fs;
Matteo Martincigh4e73b422019-08-08 13:46:32 +01001401
1402 // Swapping the backend registry storage for testing
1403 TestBackendRegistry testBackendRegistry;
1404
1405 // This directory contains the reference dynamic backend
1406 std::string dynamicBackendsBaseDir = GetDynamicBackendsBasePath();
1407 std::string referenceDynamicBackendSubDir = GetTestSubDirectory(dynamicBackendsBaseDir,
1408 g_ReferenceDynamicBackendSubDir);
1409 BOOST_CHECK(exists(referenceDynamicBackendSubDir));
1410
1411 // Check that the reference dynamic backend file exists
1412 std::string referenceBackendFilePath = GetTestFilePath(referenceDynamicBackendSubDir,
1413 g_ReferenceBackendFileName);
1414 BOOST_CHECK(exists(referenceBackendFilePath));
1415
1416 // Using the path override in CreationOptions to load the reference dynamic backend
1417 IRuntime::CreationOptions creationOptions;
1418 creationOptions.m_DynamicBackendsPath = referenceDynamicBackendSubDir;
1419 IRuntimePtr runtime = IRuntime::Create(creationOptions);
1420
1421 const BackendRegistry& backendRegistry = BackendRegistryInstance();
1422 BOOST_TEST(backendRegistry.Size() == 1);
1423
1424 BackendIdSet backendIds = backendRegistry.GetBackendIds();
1425 BOOST_TEST((backendIds.find("CpuRef") != backendIds.end()));
1426
Jan Eilersbb446e52020-04-02 13:56:54 +01001427 const DeviceSpec& deviceSpec = *PolymorphicDowncast<const DeviceSpec*>(&runtime->GetDeviceSpec());
Matteo Martincigh89533902019-08-15 12:08:06 +01001428 BackendIdSet supportedBackendIds = deviceSpec.GetSupportedBackends();
1429 BOOST_TEST(supportedBackendIds.size() == 1);
1430 BOOST_TEST((supportedBackendIds.find("CpuRef") != supportedBackendIds.end()));
1431
Matteo Martincigh4e73b422019-08-08 13:46:32 +01001432 // Get the factory function
1433 auto referenceDynamicBackendFactoryFunction = backendRegistry.GetFactory("CpuRef");
1434 BOOST_TEST((referenceDynamicBackendFactoryFunction != nullptr));
1435
1436 // Use the factory function to create an instance of the reference backend
1437 IBackendInternalUniquePtr referenceDynamicBackend = referenceDynamicBackendFactoryFunction();
1438 BOOST_TEST((referenceDynamicBackend != nullptr));
1439 BOOST_TEST((referenceDynamicBackend->GetId() == "CpuRef"));
1440
1441 // Test the backend instance by querying the layer support
1442 IBackendInternal::ILayerSupportSharedPtr referenceLayerSupport = referenceDynamicBackend->GetLayerSupport();
1443 BOOST_TEST((referenceLayerSupport != nullptr));
1444
1445 TensorShape inputShape { 1, 16, 16, 16 };
1446 TensorShape outputShape{ 1, 16, 16, 16 };
1447 TensorShape weightShape{ 16, 1, 1, 16 };
1448 TensorInfo inputInfo (inputShape, DataType::Float32);
1449 TensorInfo outputInfo(outputShape, DataType::Float32);
1450 TensorInfo weightInfo(weightShape, DataType::Float32);
1451 Convolution2dDescriptor convolution2dDescriptor;
1452 bool referenceConvolution2dSupported =
1453 referenceLayerSupport->IsConvolution2dSupported(inputInfo,
1454 outputInfo,
1455 convolution2dDescriptor,
1456 weightInfo,
1457 EmptyOptional());
1458 BOOST_TEST(referenceConvolution2dSupported);
1459
1460 // Test the backend instance by creating a workload
1461 IBackendInternal::IWorkloadFactoryPtr referenceWorkloadFactory = referenceDynamicBackend->CreateWorkloadFactory();
1462 BOOST_TEST((referenceWorkloadFactory != nullptr));
1463
1464 // Create dummy settings for the workload
1465 Convolution2dQueueDescriptor convolution2dQueueDescriptor;
1466 WorkloadInfo workloadInfo
1467 {
1468 { inputInfo },
1469 { outputInfo }
1470 };
1471 convolution2dQueueDescriptor.m_Inputs.push_back(nullptr);
1472 auto weights = std::make_unique<ScopedCpuTensorHandle>(weightInfo);
1473 convolution2dQueueDescriptor.m_Weight = weights.get();
1474
1475 // Create a convolution workload with the dummy settings
1476 auto workload = referenceWorkloadFactory->CreateConvolution2d(convolution2dQueueDescriptor, workloadInfo);
1477 BOOST_TEST((workload != nullptr));
Jan Eilersbb446e52020-04-02 13:56:54 +01001478 BOOST_TEST(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";
1497 BOOST_FAIL(message);
1498 }
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();
1508 BOOST_TEST(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();
1512 BOOST_TEST(supportedBackendIds.size()>= 1);
1513 BOOST_TEST((supportedBackendIds.find("SampleDynamic") != supportedBackendIds.end()));
1514
1515 // Get the factory function
1516 auto sampleDynamicBackendFactoryFunction = backendRegistry.GetFactory("SampleDynamic");
1517 BOOST_TEST((sampleDynamicBackendFactoryFunction != nullptr));
1518
1519 // Use the factory function to create an instance of the dynamic backend
1520 IBackendInternalUniquePtr sampleDynamicBackend = sampleDynamicBackendFactoryFunction();
1521 BOOST_TEST((sampleDynamicBackend != nullptr));
1522 BOOST_TEST((sampleDynamicBackend->GetId() == "SampleDynamic"));
1523
1524 // Test the backend instance by querying the layer support
1525 IBackendInternal::ILayerSupportSharedPtr sampleLayerSupport = sampleDynamicBackend->GetLayerSupport();
1526 BOOST_TEST((sampleLayerSupport != nullptr));
1527
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;
1535 bool sampleConvolution2dSupported =
1536 sampleLayerSupport->IsConvolution2dSupported(inputInfo,
1537 outputInfo,
1538 convolution2dDescriptor,
1539 weightInfo,
1540 EmptyOptional());
1541 BOOST_TEST(!sampleConvolution2dSupported);
1542
1543 // Test the backend instance by creating a workload
1544 IBackendInternal::IWorkloadFactoryPtr sampleWorkloadFactory = sampleDynamicBackend->CreateWorkloadFactory();
1545 BOOST_TEST((sampleWorkloadFactory != nullptr));
1546
1547 // Create dummy settings for the workload
1548 AdditionQueueDescriptor additionQueueDescriptor;
1549 WorkloadInfo workloadInfo
1550 {
1551 { inputInfo, inputInfo },
1552 { outputInfo }
1553 };
1554
1555 // Create a addition workload
1556 auto workload = sampleWorkloadFactory->CreateAddition(additionQueueDescriptor, workloadInfo);
1557 BOOST_TEST((workload != nullptr));
1558}
1559
1560void SampleDynamicBackendEndToEndTestImpl()
1561{
1562 using namespace armnn;
Narumol Prangnawarat867eba52020-02-03 12:29:56 +00001563 // Create runtime in which test will run
1564 IRuntime::CreationOptions options;
1565 IRuntimePtr runtime(IRuntime::Create(options));
Colm Donelanfa0d8382020-06-04 12:30:16 +01001566 CheckSampleDynamicBackendLoaded();
Narumol Prangnawarat867eba52020-02-03 12:29:56 +00001567 // Builds up the structure of the network.
1568 INetworkPtr net(INetwork::Create());
1569
1570 IConnectableLayer* input0 = net->AddInputLayer(0);
1571 IConnectableLayer* input1 = net->AddInputLayer(1);
1572 IConnectableLayer* add = net->AddAdditionLayer();
1573 IConnectableLayer* output = net->AddOutputLayer(0);
1574
1575 input0->GetOutputSlot(0).Connect(add->GetInputSlot(0));
1576 input1->GetOutputSlot(0).Connect(add->GetInputSlot(1));
1577 add->GetOutputSlot(0).Connect(output->GetInputSlot(0));
1578
1579 TensorInfo tensorInfo(TensorShape({2, 1}), DataType::Float32);
1580 input0->GetOutputSlot(0).SetTensorInfo(tensorInfo);
1581 input1->GetOutputSlot(0).SetTensorInfo(tensorInfo);
1582 add->GetOutputSlot(0).SetTensorInfo(tensorInfo);
1583
1584 // optimize the network
1585 IOptimizedNetworkPtr optNet = Optimize(*net, {"SampleDynamic"}, runtime->GetDeviceSpec());
1586
1587 // Loads it into the runtime.
1588 NetworkId netId;
1589 runtime->LoadNetwork(netId, std::move(optNet));
1590
1591 std::vector<float> input0Data{ 5.0f, 3.0f };
1592 std::vector<float> input1Data{ 10.0f, 8.0f };
1593 std::vector<float> expectedOutputData{ 15.0f, 11.0f };
1594 std::vector<float> outputData(2);
1595
1596 InputTensors inputTensors
1597 {
1598 {0,armnn::ConstTensor(runtime->GetInputTensorInfo(netId, 0), input0Data.data())},
1599 {1,armnn::ConstTensor(runtime->GetInputTensorInfo(netId, 0), input1Data.data())}
1600 };
1601 OutputTensors outputTensors
1602 {
1603 {0,armnn::Tensor(runtime->GetOutputTensorInfo(netId, 0), outputData.data())}
1604 };
1605
1606 // Does the inference.
1607 runtime->EnqueueWorkload(netId, inputTensors, outputTensors);
1608
1609 // Checks the results.
1610 BOOST_TEST(outputData == expectedOutputData);
1611}
1612#endif