ArmNN
 20.05
DynamicBackendTests.hpp
Go to the documentation of this file.
1 //
2 // Copyright © 2017 Arm Ltd. All rights reserved.
3 // SPDX-License-Identifier: MIT
4 //
5 
6 #pragma once
7 
10 #include <armnn/ILayerSupport.hpp>
15 #include <Runtime.hpp>
16 
17 #include <string>
18 #include <memory>
19 
20 #include <boost/test/unit_test.hpp>
21 #include <boost/filesystem.hpp>
22 #include <boost/dll.hpp>
23 
24 static std::string g_TestBaseDir = "src/backends/backendsCommon/test/";
25 
26 static std::string g_TestSharedObjectSubDir = "testSharedObject/";
27 static std::string g_TestDynamicBackendSubDir = "testDynamicBackend/";
28 
29 static std::string g_TestSharedObjectFileName = "libTestSharedObject.so";
30 static std::string g_TestNoSharedObjectFileName = "libNoSharedObject.txt";
31 
32 static std::string g_TestValidTestDynamicBackendFileName = "libValidTestDynamicBackend.so";
33 static std::string g_TestInvalidTestDynamicBackend1FileName = "libInvalidTestDynamicBackend1.so";
34 static std::string g_TestInvalidTestDynamicBackend2FileName = "libInvalidTestDynamicBackend2.so";
35 static std::string g_TestInvalidTestDynamicBackend3FileName = "libInvalidTestDynamicBackend3.so";
36 static std::string g_TestInvalidTestDynamicBackend4FileName = "libInvalidTestDynamicBackend4.so";
37 static std::string g_TestInvalidTestDynamicBackend5FileName = "libInvalidTestDynamicBackend5.so";
38 static std::string g_TestInvalidTestDynamicBackend6FileName = "libInvalidTestDynamicBackend6.so";
39 static std::string g_TestInvalidTestDynamicBackend7FileName = "libInvalidTestDynamicBackend7.so";
40 
41 static std::string g_TestValidBackend2FileName = "Arm_TestValid2_backend.so";
42 static std::string g_TestValidBackend3FileName = "Arm_TestValid3_backend.so";
43 static std::string g_TestValidBackend4FileName = "Arm_TestValid4_backend.so";
44 static std::string g_TestValidBackend5FileName = "Arm_TestValid5_backend.so";
45 static std::string g_TestInvalidBackend8FileName = "Arm_TestInvalid8_backend.so";
46 static std::string g_TestInvalidBackend9FileName = "Arm_TestInvalid9_backend.so";
47 static std::string g_TestInvalidBackend10FileName = "Arm_TestInvalid10_backend.so";
48 static std::string g_TestInvalidBackend11FileName = "Arm_TestInvalid11_backend.so";
49 
50 static std::string g_TestDynamicBackendsSubDir1 = "backendsTestPath1/";
51 static std::string g_TestDynamicBackendsSubDir2 = "backendsTestPath2/";
52 static std::string g_TestDynamicBackendsSubDir3 = "backendsTestPath3/";
53 static std::string g_TestDynamicBackendsSubDir4 = "backendsTestPath4/";
54 static std::string g_TestDynamicBackendsSubDir5 = "backendsTestPath5/";
55 static std::string g_TestDynamicBackendsSubDir6 = "backendsTestPath6/";
56 static std::string g_TestDynamicBackendsSubDir7 = "backendsTestPath7/";
57 static std::string g_TestDynamicBackendsSubDir8 = "backendsTestPath8/";
58 static std::string g_TestDynamicBackendsSubDir9 = "backendsTestPath9/";
59 
60 static std::string g_DynamicBackendsBaseDir = "src/backends/dynamic";
61 static std::string g_ReferenceDynamicBackendSubDir = "reference/";
62 static std::string g_ReferenceBackendFileName = "Arm_CpuRef_backend.so";
63 
64 // DynamicBackendUtils wrapper class used for testing (allows to directly invoke the protected methods)
66 {
67 public:
68  static bool IsBackendCompatibleTest(const armnn::BackendVersion& backendApiVersion,
69  const armnn::BackendVersion& backendVersion)
70  {
71  return IsBackendCompatibleImpl(backendApiVersion, backendVersion);
72  }
73 
74  static std::vector<std::string> GetBackendPathsImplTest(const std::string& path)
75  {
76  return GetBackendPathsImpl(path);
77  }
78 
80  armnn::BackendRegistry& backendRegistry,
81  const std::vector<armnn::DynamicBackendPtr>& dynamicBackends)
82  {
83  return RegisterDynamicBackendsImpl(backendRegistry, dynamicBackends);
84  }
85 };
86 
87 // BackendRegistry wrapper class used for testing (swaps the underlying factory storage)
89 {
90 public:
91  TestBackendRegistry() : armnn::BackendRegistry()
92  {
93  Swap(armnn::BackendRegistryInstance(), m_TempStorage);
94  }
95 
97  {
98  Swap(armnn::BackendRegistryInstance(), m_TempStorage);
99  }
100 
101 private:
102  FactoryStorage m_TempStorage;
103 };
104 
105 std::string GetBasePath(const std::string& basePath)
106 {
107  using namespace boost::filesystem;
108 
109  path programLocation = boost::dll::program_location().parent_path();
110  path sharedObjectPath = programLocation.append(basePath);
111  BOOST_CHECK(exists(sharedObjectPath));
112 
113  return sharedObjectPath.string();
114 }
115 
117 {
118  return GetBasePath(g_TestBaseDir);
119 }
120 
122 {
123  return GetBasePath(g_DynamicBackendsBaseDir);
124 }
125 
126 std::string GetTestSubDirectory(const std::string& subdir)
127 {
128  using namespace boost::filesystem;
129 
130  std::string testDynamicBackendsBaseDir = GetTestDirectoryBasePath();
131  path testDynamicBackendsBasePath(testDynamicBackendsBaseDir);
132  path testDynamicBackendsSubDir = testDynamicBackendsBasePath.append(subdir);
133  // Do not check that the sub-directory exists because for testing reasons we may use non-existing paths
134 
135  return testDynamicBackendsSubDir.string();
136 }
137 
138 std::string GetTestSubDirectory(const std::string& basePath, const std::string& subdir)
139 {
140  using namespace boost::filesystem;
141 
142  path testDynamicBackendsBasePath(basePath);
143  path testDynamicBackendsSubDir = testDynamicBackendsBasePath.append(subdir);
144  // Do not check that the sub-directory exists because for testing reasons we may use non-existing paths
145 
146  return testDynamicBackendsSubDir.string();
147 }
148 
149 std::string GetTestFilePath(const std::string& directory, const std::string& fileName)
150 {
151  using namespace boost::filesystem;
152 
153  path directoryPath(directory);
154  path fileNamePath = directoryPath.append(fileName);
155  BOOST_CHECK(exists(fileNamePath));
156 
157  return fileNamePath.string();
158 }
159 
161 {
162  using namespace armnn;
163 
164  std::string testSubDirectory = GetTestSubDirectory(g_TestSharedObjectSubDir);
165  std::string sharedObjectFilePath = GetTestFilePath(testSubDirectory, g_TestSharedObjectFileName);
166 
167  void* sharedObjectHandle = nullptr;
168  BOOST_CHECK_NO_THROW(sharedObjectHandle = DynamicBackendUtils::OpenHandle(sharedObjectFilePath));
169  BOOST_TEST((sharedObjectHandle != nullptr));
170 
171  DynamicBackendUtils::CloseHandle(sharedObjectHandle);
172 }
173 
175 {
176  using namespace armnn;
177 
178  // This calls must silently handle invalid handles and complete successfully (no segfaults, etc.)
179  DynamicBackendUtils::CloseHandle(nullptr);
180 }
181 
183 {
184  using namespace armnn;
185 
186  void* sharedObjectHandle = nullptr;
187  BOOST_CHECK_THROW(sharedObjectHandle = DynamicBackendUtils::OpenHandle(""), RuntimeException);
188  BOOST_TEST((sharedObjectHandle == nullptr));
189 }
190 
192 {
193  using namespace armnn;
194 
195  void* sharedObjectHandle = nullptr;
196  BOOST_CHECK_THROW(sharedObjectHandle = DynamicBackendUtils::OpenHandle("NotExistingFileName"), RuntimeException);
197  BOOST_TEST((sharedObjectHandle == nullptr));
198 }
199 
201 {
202  using namespace armnn;
203 
204  std::string testSubDirectory = GetTestSubDirectory(g_TestSharedObjectSubDir);
205  std::string notSharedObjectFilePath = GetTestFilePath(testSubDirectory, g_TestNoSharedObjectFileName);
206 
207  void* sharedObjectHandle = nullptr;
208  BOOST_CHECK_THROW(sharedObjectHandle = DynamicBackendUtils::OpenHandle(notSharedObjectFilePath), RuntimeException);
209  BOOST_TEST((sharedObjectHandle == nullptr));
210 }
211 
213 {
214  using namespace armnn;
215 
216  std::string testSubDirectory = GetTestSubDirectory(g_TestSharedObjectSubDir);
217  std::string sharedObjectFilePath = GetTestFilePath(testSubDirectory, g_TestSharedObjectFileName);
218 
219  void* sharedObjectHandle = nullptr;
220  BOOST_CHECK_NO_THROW(sharedObjectHandle = DynamicBackendUtils::OpenHandle(sharedObjectFilePath));
221  BOOST_TEST((sharedObjectHandle != nullptr));
222 
223  using TestFunctionType = int(*)(int);
224  TestFunctionType testFunctionPointer = nullptr;
225  BOOST_CHECK_NO_THROW(testFunctionPointer = DynamicBackendUtils::GetEntryPoint<TestFunctionType>(sharedObjectHandle,
226  "TestFunction1"));
227  BOOST_TEST((testFunctionPointer != nullptr));
228  BOOST_TEST(testFunctionPointer(7) == 7);
229 
230  DynamicBackendUtils::CloseHandle(sharedObjectHandle);
231 }
232 
234 {
235  using namespace armnn;
236 
237  std::string testSubDirectory = GetTestSubDirectory(g_TestSharedObjectSubDir);
238  std::string sharedObjectFilePath = GetTestFilePath(testSubDirectory, g_TestSharedObjectFileName);
239 
240  void* sharedObjectHandle = nullptr;
241  BOOST_CHECK_NO_THROW(sharedObjectHandle = DynamicBackendUtils::OpenHandle(sharedObjectFilePath));
242  BOOST_TEST((sharedObjectHandle != nullptr));
243 
244  using TestFunctionType = int(*)(int);
245  TestFunctionType testFunctionPointer = nullptr;
246  BOOST_CHECK_THROW(testFunctionPointer = DynamicBackendUtils::GetEntryPoint<TestFunctionType>(sharedObjectHandle,
247  "TestFunction2"),
249  BOOST_TEST((testFunctionPointer == nullptr));
250 
251  DynamicBackendUtils::CloseHandle(sharedObjectHandle);
252 }
253 
255 {
256  using namespace armnn;
257 
258  std::string testSubDirectory = GetTestSubDirectory(g_TestSharedObjectSubDir);
259  std::string sharedObjectFilePath = GetTestFilePath(testSubDirectory, g_TestSharedObjectFileName);
260 
261  void* sharedObjectHandle = nullptr;
262  BOOST_CHECK_NO_THROW(sharedObjectHandle = DynamicBackendUtils::OpenHandle(sharedObjectFilePath));
263  BOOST_TEST((sharedObjectHandle != nullptr));
264 
265  using TestFunctionType = int(*)(int);
266  TestFunctionType testFunctionPointer = nullptr;
267  BOOST_CHECK_THROW(testFunctionPointer = DynamicBackendUtils::GetEntryPoint<TestFunctionType>(sharedObjectHandle,
268  "TestFunction3"),
270  BOOST_TEST((testFunctionPointer == nullptr));
271 
272  DynamicBackendUtils::CloseHandle(sharedObjectHandle);
273 }
274 
276 {
277  using namespace armnn;
278 
279  std::string testSubDirectory = GetTestSubDirectory(g_TestSharedObjectSubDir);
280  std::string sharedObjectFilePath = GetTestFilePath(testSubDirectory, g_TestSharedObjectFileName);
281 
282  void* sharedObjectHandle = nullptr;
283  BOOST_CHECK_NO_THROW(sharedObjectHandle = DynamicBackendUtils::OpenHandle(sharedObjectFilePath));
284  BOOST_TEST((sharedObjectHandle != nullptr));
285 
286  using TestFunctionType = int(*)(int);
287  TestFunctionType testFunctionPointer = nullptr;
288  BOOST_CHECK_THROW(testFunctionPointer = DynamicBackendUtils::GetEntryPoint<TestFunctionType>(sharedObjectHandle,
289  "TestFunction4"),
291  BOOST_TEST((testFunctionPointer == nullptr));
292 
293  DynamicBackendUtils::CloseHandle(sharedObjectHandle);
294 }
295 
297 {
298  using namespace armnn;
299 
300  // The backend API version used for the tests
301  BackendVersion backendApiVersion{ 2, 4 };
302 
303  // Same backend and backend API versions are compatible with the backend API
304  BackendVersion sameBackendVersion{ 2, 4 };
305  BOOST_TEST(sameBackendVersion == backendApiVersion);
306  BOOST_TEST(sameBackendVersion <= backendApiVersion);
307  BOOST_TEST(TestDynamicBackendUtils::IsBackendCompatibleTest(backendApiVersion, sameBackendVersion) == true);
308 
309  // Backend versions that differ from the backend API version by major revision are not compatible
310  // with the backend API
311  BackendVersion laterMajorBackendVersion{ 3, 4 };
312  BOOST_TEST(!(laterMajorBackendVersion == backendApiVersion));
313  BOOST_TEST(!(laterMajorBackendVersion <= backendApiVersion));
314  BOOST_TEST(TestDynamicBackendUtils::IsBackendCompatibleTest(backendApiVersion, laterMajorBackendVersion) == false);
315 
316  BackendVersion earlierMajorBackendVersion{ 1, 4 };
317  BOOST_TEST(!(earlierMajorBackendVersion == backendApiVersion));
318  BOOST_TEST(earlierMajorBackendVersion <= backendApiVersion);
319  BOOST_TEST(TestDynamicBackendUtils::IsBackendCompatibleTest(backendApiVersion,
320  earlierMajorBackendVersion) == false);
321 
322  // Backend versions with the same major revision but later minor revision than
323  // the backend API version are not compatible with the backend API
324  BackendVersion laterMinorBackendVersion{ 2, 5 };
325  BOOST_TEST(!(laterMinorBackendVersion == backendApiVersion));
326  BOOST_TEST(!(laterMinorBackendVersion <= backendApiVersion));
327  BOOST_TEST(TestDynamicBackendUtils::IsBackendCompatibleTest(backendApiVersion, laterMinorBackendVersion) == false);
328 
329  // Backend versions with the same major revision but earlier minor revision than
330  // the backend API version are compatible with the backend API
331  BackendVersion earlierMinorBackendVersion{ 2, 3 };
332  BOOST_TEST(!(earlierMinorBackendVersion == backendApiVersion));
333  BOOST_TEST(earlierMinorBackendVersion <= backendApiVersion);
334  BOOST_TEST(TestDynamicBackendUtils::IsBackendCompatibleTest(backendApiVersion, earlierMinorBackendVersion) == true);
335 }
336 
338 {
339  // Valid shared object handle
340  // Correct name mangling
341  // Correct interface
342  // Correct backend implementation
343 
344  using namespace armnn;
345 
346  std::string testSubDirectory = GetTestSubDirectory(g_TestDynamicBackendSubDir);
347  std::string sharedObjectFilePath = GetTestFilePath(testSubDirectory, g_TestValidTestDynamicBackendFileName);
348 
349  void* sharedObjectHandle = nullptr;
350  BOOST_CHECK_NO_THROW(sharedObjectHandle = DynamicBackendUtils::OpenHandle(sharedObjectFilePath));
351  BOOST_TEST((sharedObjectHandle != nullptr));
352 
353  DynamicBackendPtr dynamicBackend;
354  BOOST_CHECK_NO_THROW(dynamicBackend.reset(new DynamicBackend(sharedObjectHandle)));
355  BOOST_TEST((dynamicBackend != nullptr));
356 
357  BackendId dynamicBackendId;
358  BOOST_CHECK_NO_THROW(dynamicBackendId = dynamicBackend->GetBackendId());
359  BOOST_TEST((dynamicBackendId == "ValidTestDynamicBackend"));
360 
361  BackendVersion dynamicBackendVersion;
362  BOOST_CHECK_NO_THROW(dynamicBackendVersion = dynamicBackend->GetBackendVersion());
363  BOOST_TEST((dynamicBackendVersion == IBackendInternal::GetApiVersion()));
364 
365  IBackendInternalUniquePtr dynamicBackendInstance1;
366  BOOST_CHECK_NO_THROW(dynamicBackendInstance1 = dynamicBackend->GetBackend());
367  BOOST_TEST((dynamicBackendInstance1 != nullptr));
368 
369  BackendRegistry::FactoryFunction dynamicBackendFactoryFunction = nullptr;
370  BOOST_CHECK_NO_THROW(dynamicBackendFactoryFunction = dynamicBackend->GetFactoryFunction());
371  BOOST_TEST((dynamicBackendFactoryFunction != nullptr));
372 
373  IBackendInternalUniquePtr dynamicBackendInstance2;
374  BOOST_CHECK_NO_THROW(dynamicBackendInstance2 = dynamicBackendFactoryFunction());
375  BOOST_TEST((dynamicBackendInstance2 != nullptr));
376 
377  BOOST_TEST((dynamicBackendInstance1->GetId() == "ValidTestDynamicBackend"));
378  BOOST_TEST((dynamicBackendInstance2->GetId() == "ValidTestDynamicBackend"));
379 }
380 
382 {
383  // Invalid (null) shared object handle
384 
385  using namespace armnn;
386 
387  void* sharedObjectHandle = nullptr;
388  DynamicBackendPtr dynamicBackend;
389  BOOST_CHECK_THROW(dynamicBackend.reset(new DynamicBackend(sharedObjectHandle)), InvalidArgumentException);
390  BOOST_TEST((dynamicBackend == nullptr));
391 }
392 
394 {
395  // Valid shared object handle
396  // Wrong (not C-style) name mangling
397 
398  using namespace armnn;
399 
400  std::string testSubDirectory = GetTestSubDirectory(g_TestDynamicBackendSubDir);
401  std::string sharedObjectFilePath = GetTestFilePath(testSubDirectory, g_TestInvalidTestDynamicBackend1FileName);
402 
403  void* sharedObjectHandle = nullptr;
404  BOOST_CHECK_NO_THROW(sharedObjectHandle = DynamicBackendUtils::OpenHandle(sharedObjectFilePath));
405  BOOST_TEST((sharedObjectHandle != nullptr));
406 
407  DynamicBackendPtr dynamicBackend;
408  BOOST_CHECK_THROW(dynamicBackend.reset(new DynamicBackend(sharedObjectHandle)), RuntimeException);
409  BOOST_TEST((dynamicBackend == nullptr));
410 }
411 
413 {
414  // Valid shared object handle
415  // Correct name mangling
416  // Wrong interface (missing GetBackendId())
417 
418  using namespace armnn;
419 
420  std::string testSubDirectory = GetTestSubDirectory(g_TestDynamicBackendSubDir);
421  std::string sharedObjectFilePath = GetTestFilePath(testSubDirectory, g_TestInvalidTestDynamicBackend2FileName);
422 
423  void* sharedObjectHandle = nullptr;
424  BOOST_CHECK_NO_THROW(sharedObjectHandle = DynamicBackendUtils::OpenHandle(sharedObjectFilePath));
425  BOOST_TEST((sharedObjectHandle != nullptr));
426 
427  DynamicBackendPtr dynamicBackend;
428  BOOST_CHECK_THROW(dynamicBackend.reset(new DynamicBackend(sharedObjectHandle)), RuntimeException);
429  BOOST_TEST((dynamicBackend == nullptr));
430 }
431 
433 {
434  // Valid shared object handle
435  // Correct name mangling
436  // Wrong interface (missing GetVersion())
437 
438  using namespace armnn;
439 
440  std::string testSubDirectory = GetTestSubDirectory(g_TestDynamicBackendSubDir);
441  std::string sharedObjectFilePath = GetTestFilePath(testSubDirectory, g_TestInvalidTestDynamicBackend3FileName);
442 
443  void* sharedObjectHandle = nullptr;
444  BOOST_CHECK_NO_THROW(sharedObjectHandle = DynamicBackendUtils::OpenHandle(sharedObjectFilePath));
445  BOOST_TEST((sharedObjectHandle != nullptr));
446 
447  DynamicBackendPtr dynamicBackend;
448  BOOST_CHECK_THROW(dynamicBackend.reset(new DynamicBackend(sharedObjectHandle)), RuntimeException);
449  BOOST_TEST((dynamicBackend == nullptr));
450 }
451 
453 {
454  // Valid shared object handle
455  // Correct name mangling
456  // Wrong interface (missing BackendFactory())
457 
458  using namespace armnn;
459 
460  std::string testSubDirectory = GetTestSubDirectory(g_TestDynamicBackendSubDir);
461  std::string sharedObjectFilePath = GetTestFilePath(testSubDirectory, g_TestInvalidTestDynamicBackend4FileName);
462 
463  void* sharedObjectHandle = nullptr;
464  BOOST_CHECK_NO_THROW(sharedObjectHandle = DynamicBackendUtils::OpenHandle(sharedObjectFilePath));
465  BOOST_TEST((sharedObjectHandle != nullptr));
466 
467  DynamicBackendPtr dynamicBackend;
468  BOOST_CHECK_THROW(dynamicBackend.reset(new DynamicBackend(sharedObjectHandle)), RuntimeException);
469  BOOST_TEST((dynamicBackend == nullptr));
470 }
471 
473 {
474  // Valid shared object handle
475  // Correct name mangling
476  // Correct interface
477  // Invalid (null) backend id returned by GetBackendId()
478 
479  using namespace armnn;
480 
481  std::string testSubDirectory = GetTestSubDirectory(g_TestDynamicBackendSubDir);
482  std::string sharedObjectFilePath = GetTestFilePath(testSubDirectory, g_TestInvalidTestDynamicBackend5FileName);
483 
484  void* sharedObjectHandle = nullptr;
485  BOOST_CHECK_NO_THROW(sharedObjectHandle = DynamicBackendUtils::OpenHandle(sharedObjectFilePath));
486  BOOST_TEST((sharedObjectHandle != nullptr));
487 
488  DynamicBackendPtr dynamicBackend;
489  BOOST_CHECK_THROW(dynamicBackend.reset(new DynamicBackend(sharedObjectHandle)), RuntimeException);
490  BOOST_TEST((dynamicBackend == nullptr));
491 }
492 
494 {
495  // Valid shared object handle
496  // Correct name mangling
497  // Correct interface
498  // Invalid (null) backend instance returned by BackendFactory()
499 
500  using namespace armnn;
501 
502  std::string testSubDirectory = GetTestSubDirectory(g_TestDynamicBackendSubDir);
503  std::string sharedObjectFilePath = GetTestFilePath(testSubDirectory, g_TestInvalidTestDynamicBackend6FileName);
504 
505  void* sharedObjectHandle = nullptr;
506  BOOST_CHECK_NO_THROW(sharedObjectHandle = DynamicBackendUtils::OpenHandle(sharedObjectFilePath));
507  BOOST_TEST((sharedObjectHandle != nullptr));
508 
509  DynamicBackendPtr dynamicBackend;
510  BOOST_CHECK_NO_THROW(dynamicBackend.reset(new DynamicBackend(sharedObjectHandle)));
511  BOOST_TEST((dynamicBackend != nullptr));
512 
513  BackendId dynamicBackendId;
514  BOOST_CHECK_NO_THROW(dynamicBackendId = dynamicBackend->GetBackendId());
515  BOOST_TEST((dynamicBackendId == "InvalidTestDynamicBackend"));
516 
517  BackendVersion dynamicBackendVersion;
518  BOOST_CHECK_NO_THROW(dynamicBackendVersion = dynamicBackend->GetBackendVersion());
519  BOOST_TEST((dynamicBackendVersion == BackendVersion({ 1, 0 })));
520 
521  IBackendInternalUniquePtr dynamicBackendInstance1;
522  BOOST_CHECK_THROW(dynamicBackendInstance1 = dynamicBackend->GetBackend(), RuntimeException);
523  BOOST_TEST((dynamicBackendInstance1 == nullptr));
524 
525  BackendRegistry::FactoryFunction dynamicBackendFactoryFunction = nullptr;
526  BOOST_CHECK_NO_THROW(dynamicBackendFactoryFunction = dynamicBackend->GetFactoryFunction());
527  BOOST_TEST((dynamicBackendFactoryFunction != nullptr));
528 
529  IBackendInternalUniquePtr dynamicBackendInstance2;
530  BOOST_CHECK_THROW(dynamicBackendInstance2 = dynamicBackendFactoryFunction(), RuntimeException);
531  BOOST_TEST((dynamicBackendInstance2 == nullptr));
532 }
533 
535 {
536  // Valid shared object handle
537  // Correct name mangling
538  // Correct interface
539  // Invalid (incompatible backend API version) backend instance returned by BackendFactory()
540 
541  using namespace armnn;
542 
543  std::string testSubDirectory = GetTestSubDirectory(g_TestDynamicBackendSubDir);
544  std::string sharedObjectFilePath = GetTestFilePath(testSubDirectory, g_TestInvalidTestDynamicBackend7FileName);
545 
546  void* sharedObjectHandle = nullptr;
547  BOOST_CHECK_NO_THROW(sharedObjectHandle = DynamicBackendUtils::OpenHandle(sharedObjectFilePath));
548  BOOST_TEST((sharedObjectHandle != nullptr));
549 
550  DynamicBackendPtr dynamicBackend;
551  BOOST_CHECK_THROW(dynamicBackend.reset(new DynamicBackend(sharedObjectHandle)), RuntimeException);
552  BOOST_TEST((dynamicBackend == nullptr));
553 }
554 
556 {
557  using namespace armnn;
558  using namespace boost::filesystem;
559 
560  // The test covers four directories:
561  // <unit test path>/src/backends/backendsCommon/test/
562  // ├─ backendsTestPath1/ -> exists, contains files
563  // ├─ backendsTestPath2/ -> exists, contains files
564  // ├─ backendsTestPath3/ -> exists, but empty
565  // └─ backendsTestPath4/ -> does not exist
566 
567  std::string subDir1 = GetTestSubDirectory(g_TestDynamicBackendsSubDir1);
568  std::string subDir2 = GetTestSubDirectory(g_TestDynamicBackendsSubDir2);
569  std::string subDir3 = GetTestSubDirectory(g_TestDynamicBackendsSubDir3);
570  std::string subDir4 = GetTestSubDirectory(g_TestDynamicBackendsSubDir4);
571 
572  BOOST_CHECK(exists(subDir1));
573  BOOST_CHECK(exists(subDir2));
574  BOOST_CHECK(exists(subDir3));
575  BOOST_CHECK(!exists(subDir4));
576 
577  // No path
578  BOOST_TEST(TestDynamicBackendUtils::GetBackendPathsImplTest("").empty());
579 
580  // Malformed path
581  std::string malformedDir(subDir1 + "/" + subDir1);
582  BOOST_TEST(TestDynamicBackendUtils::GetBackendPathsImplTest(malformedDir).size()==0);
583 
584  // Single valid path
585  std::vector<std::string> DynamicBackendPaths2 = TestDynamicBackendUtils::GetBackendPathsImplTest(subDir1);
586  BOOST_TEST(DynamicBackendPaths2.size() == 1);
587  BOOST_TEST(DynamicBackendPaths2[0] == subDir1);
588 
589  // Multiple equal and valid paths
590  std::string multipleEqualDirs(subDir1 + ":" + subDir1);
591  std::vector<std::string> DynamicBackendPaths3 = TestDynamicBackendUtils::GetBackendPathsImplTest(multipleEqualDirs);
592  BOOST_TEST(DynamicBackendPaths3.size() == 1);
593  BOOST_TEST(DynamicBackendPaths3[0] == subDir1);
594 
595  // Multiple empty paths
596  BOOST_TEST(TestDynamicBackendUtils::GetBackendPathsImplTest(":::").empty());
597 
598  // Multiple valid paths
599  std::string multipleValidPaths(subDir1 + ":" + subDir2 + ":" + subDir3);
600  std::vector<std::string> DynamicBackendPaths5 =
602  BOOST_TEST(DynamicBackendPaths5.size() == 3);
603  BOOST_TEST(DynamicBackendPaths5[0] == subDir1);
604  BOOST_TEST(DynamicBackendPaths5[1] == subDir2);
605  BOOST_TEST(DynamicBackendPaths5[2] == subDir3);
606 
607  // Valid among empty paths
608  std::string validAmongEmptyDirs("::" + subDir1 + ":");
609  std::vector<std::string> DynamicBackendPaths6 =
611  BOOST_TEST(DynamicBackendPaths6.size() == 1);
612  BOOST_TEST(DynamicBackendPaths6[0] == subDir1);
613 
614  // Invalid among empty paths
615  std::string invalidAmongEmptyDirs(":" + subDir4 + "::");
616  BOOST_TEST(TestDynamicBackendUtils::GetBackendPathsImplTest(invalidAmongEmptyDirs).empty());
617 
618  // Valid, invalid and empty paths
619  std::string validInvalidEmptyDirs(subDir1 + ":" + subDir4 + ":");
620  std::vector<std::string> DynamicBackendPaths8 =
622  BOOST_TEST(DynamicBackendPaths8.size() == 1);
623  BOOST_TEST(DynamicBackendPaths8[0] == subDir1);
624 
625  // Mix of duplicates of valid, invalid and empty paths
626  std::string duplicateValidInvalidEmptyDirs(validInvalidEmptyDirs + ":" + validInvalidEmptyDirs + ":" +
627  subDir2 + ":" + subDir2);
628  std::vector<std::string> DynamicBackendPaths9 =
629  TestDynamicBackendUtils::GetBackendPathsImplTest(duplicateValidInvalidEmptyDirs);
630  BOOST_TEST(DynamicBackendPaths9.size() == 2);
631  BOOST_TEST(DynamicBackendPaths9[0] == subDir1);
632  BOOST_TEST(DynamicBackendPaths9[1] == subDir2);
633 }
634 
636 {
637  using namespace armnn;
638  using namespace boost::filesystem;
639 
640  std::string subDir1 = GetTestSubDirectory(g_TestDynamicBackendsSubDir1);
641  std::string subDir4 = GetTestSubDirectory(g_TestDynamicBackendsSubDir4);
642 
643  BOOST_CHECK(exists(subDir1));
644  BOOST_CHECK(!exists(subDir4));
645 
646  // Override with valid path
647  std::vector<std::string> validResult = DynamicBackendUtils::GetBackendPaths(subDir1);
648  BOOST_TEST(validResult.size() == 1);
649  BOOST_TEST(validResult[0] == subDir1);
650 
651  // Override with invalid path
652  std::vector<std::string> invalidResult = DynamicBackendUtils::GetBackendPaths(subDir4);
653  BOOST_TEST(invalidResult.empty());
654 }
655 
657 {
658  using namespace armnn;
659  using namespace boost::filesystem;
660 
661  // The test covers four directories:
662  // <unit test path>/src/backends/backendsCommon/test/
663  // ├─ backendsTestPath1/ -> exists, contains files
664  // ├─ backendsTestPath2/ -> exists, contains files
665  // ├─ backendsTestPath3/ -> exists, but empty
666  // └─ backendsTestPath4/ -> does not exist
667  //
668  // The test sub-directory backendsTestPath1/ contains the following test files:
669  //
670  // Arm_GpuAcc_backend.so -> valid (basic backend name)
671  // Arm_GpuAcc_backend.so.1 -> valid (single field version number)
672  // Arm_GpuAcc_backend.so.1.2 -> valid (multiple field version number)
673  // Arm_GpuAcc_backend.so.1.2.3 -> valid (multiple field version number)
674  // Arm_GpuAcc_backend.so.10.1.27 -> valid (Multiple digit version)
675  // Arm_GpuAcc_backend.so.10.1.33. -> not valid (dot not followed by version number)
676  // Arm_GpuAcc_backend.so.3.4..5 -> not valid (dot not followed by version number)
677  // Arm_GpuAcc_backend.so.1,1.1 -> not valid (comma instead of dot in the version)
678  //
679  // Arm123_GpuAcc_backend.so -> valid (digits in vendor name are allowed)
680  // Arm_GpuAcc456_backend.so -> valid (digits in backend id are allowed)
681  // Arm%Co_GpuAcc_backend.so -> not valid (invalid character in vendor name)
682  // Arm_Gpu.Acc_backend.so -> not valid (invalid character in backend id)
683  //
684  // GpuAcc_backend.so -> not valid (missing vendor name)
685  // _GpuAcc_backend.so -> not valid (missing vendor name)
686  // Arm__backend.so -> not valid (missing backend id)
687  // Arm_GpuAcc.so -> not valid (missing "backend" at the end)
688  // __backend.so -> not valid (missing vendor name and backend id)
689  // __.so -> not valid (missing all fields)
690  //
691  // Arm_GpuAcc_backend -> not valid (missing at least ".so" at the end)
692  // Arm_GpuAcc_backend_v1.2.so -> not valid (extra version info at the end)
693  //
694  // The test sub-directory backendsTestPath1/ contains the following test files:
695  //
696  // Arm_CpuAcc_backend.so -> valid (basic backend name)
697  // Arm_CpuAcc_backend.so.1 -> Arm_CpuAcc_backend.so -> valid (symlink to valid backend file)
698  // Arm_CpuAcc_backend.so.1.2 -> Arm_CpuAcc_backend.so.1 -> valid (symlink to valid symlink)
699  // Arm_CpuAcc_backend.so.1.2.3 -> Arm_CpuAcc_backend.so.1.2 -> valid (symlink to valid symlink)
700  //
701  // Arm_no_backend.so -> nothing -> not valid (symlink resolves to non-existent file)
702  //
703  // Arm_GpuAcc_backend.so -> valid (but duplicated from backendsTestPath1/)
704 
705  std::string testDynamicBackendsSubDir1 = GetTestSubDirectory(g_TestDynamicBackendsSubDir1);
706  std::string testDynamicBackendsSubDir2 = GetTestSubDirectory(g_TestDynamicBackendsSubDir2);
707  std::string testDynamicBackendsSubDir3 = GetTestSubDirectory(g_TestDynamicBackendsSubDir3);
708  std::string testDynamicBackendsSubDir4 = GetTestSubDirectory(g_TestDynamicBackendsSubDir4);
709  BOOST_CHECK(exists(testDynamicBackendsSubDir1));
710  BOOST_CHECK(exists(testDynamicBackendsSubDir2));
711  BOOST_CHECK(exists(testDynamicBackendsSubDir3));
712  BOOST_CHECK(!exists(testDynamicBackendsSubDir4));
713 
714  std::vector<std::string> backendPaths
715  {
716  testDynamicBackendsSubDir1,
717  testDynamicBackendsSubDir2,
718  testDynamicBackendsSubDir3,
719  testDynamicBackendsSubDir4
720  };
721  std::vector<std::string> sharedObjects = DynamicBackendUtils::GetSharedObjects(backendPaths);
722  std::vector<std::string> expectedSharedObjects
723  {
724  testDynamicBackendsSubDir1 + "Arm123_GpuAcc_backend.so", // Digits in vendor name are allowed
725  testDynamicBackendsSubDir1 + "Arm_GpuAcc456_backend.so", // Digits in backend id are allowed
726  testDynamicBackendsSubDir1 + "Arm_GpuAcc_backend.so", // Basic backend name
727  testDynamicBackendsSubDir1 + "Arm_GpuAcc_backend.so.1", // Single field version number
728  testDynamicBackendsSubDir1 + "Arm_GpuAcc_backend.so.1.2", // Multiple field version number
729  testDynamicBackendsSubDir1 + "Arm_GpuAcc_backend.so.1.2.3", // Multiple field version number
730  testDynamicBackendsSubDir1 + "Arm_GpuAcc_backend.so.10.1.27", // Multiple digit version
731  testDynamicBackendsSubDir2 + "Arm_CpuAcc_backend.so", // Duplicate symlinks removed
732  testDynamicBackendsSubDir2 + "Arm_GpuAcc_backend.so" // Duplicates on different paths are allowed
733  };
734 
735  BOOST_TEST(sharedObjects.size() == expectedSharedObjects.size());
736  BOOST_TEST(sharedObjects[0] == expectedSharedObjects[0]);
737  BOOST_TEST(sharedObjects[1] == expectedSharedObjects[1]);
738  BOOST_TEST(sharedObjects[2] == expectedSharedObjects[2]);
739  BOOST_TEST(sharedObjects[3] == expectedSharedObjects[3]);
740  BOOST_TEST(sharedObjects[4] == expectedSharedObjects[4]);
741  BOOST_TEST(sharedObjects[5] == expectedSharedObjects[5]);
742  BOOST_TEST(sharedObjects[6] == expectedSharedObjects[6]);
743  BOOST_TEST(sharedObjects[7] == expectedSharedObjects[7]);
744  BOOST_TEST(sharedObjects[8] == expectedSharedObjects[8]);
745 }
746 
748 {
749  using namespace armnn;
750  using namespace boost::filesystem;
751 
752  // The test covers four directories:
753  // <unit test path>/src/backends/backendsCommon/test/
754  // ├─ backendsTestPath5/ -> exists, contains files
755  // ├─ backendsTestPath6/ -> exists, contains files
756  // ├─ backendsTestPath7/ -> exists, but empty
757  // └─ backendsTestPath8/ -> does not exist
758  //
759  // The test sub-directory backendsTestPath5/ contains the following test files:
760  //
761  // Arm_TestValid2_backend.so -> valid (basic backend name)
762  // Arm_TestValid3_backend.so -> valid (basic backend name)
763  // Arm_TestInvalid8_backend.so -> not valid (invalid backend id)
764  //
765  // The test sub-directory backendsTestPath6/ contains the following test files:
766  //
767  // Arm_TestValid2_backend.so -> valid (but duplicated from backendsTestPath5/)
768  // Arm_TestValid4_backend.so -> valid (it has a different filename,
769  // but it has the same backend id of Arm_TestValid2_backend.so
770  // and the same version)
771  // Arm_TestValid5_backend.so -> valid (basic backend name)
772  // Arm_TestInvalid9_backend.so -> not valid (it has a different filename,
773  // but it has the same backend id of Arm_TestValid2_backend.so
774  // and a version incompatible with the Backend API)
775 
776  std::string testDynamicBackendsSubDir5 = GetTestSubDirectory(g_TestDynamicBackendsSubDir5);
777  std::string testDynamicBackendsSubDir6 = GetTestSubDirectory(g_TestDynamicBackendsSubDir6);
778  std::string testDynamicBackendsSubDir7 = GetTestSubDirectory(g_TestDynamicBackendsSubDir7);
779  std::string testDynamicBackendsSubDir8 = GetTestSubDirectory(g_TestDynamicBackendsSubDir8);
780  BOOST_CHECK(exists(testDynamicBackendsSubDir5));
781  BOOST_CHECK(exists(testDynamicBackendsSubDir6));
782  BOOST_CHECK(exists(testDynamicBackendsSubDir7));
783  BOOST_CHECK(!exists(testDynamicBackendsSubDir8));
784 
785  std::vector<std::string> backendPaths
786  {
787  testDynamicBackendsSubDir5,
788  testDynamicBackendsSubDir6,
789  testDynamicBackendsSubDir7,
790  testDynamicBackendsSubDir8
791  };
792  std::vector<std::string> sharedObjects = DynamicBackendUtils::GetSharedObjects(backendPaths);
793  std::vector<DynamicBackendPtr> dynamicBackends = DynamicBackendUtils::CreateDynamicBackends(sharedObjects);
794 
795  BOOST_TEST(dynamicBackends.size() == 5);
796  BOOST_TEST((dynamicBackends[0] != nullptr));
797  BOOST_TEST((dynamicBackends[1] != nullptr));
798  BOOST_TEST((dynamicBackends[2] != nullptr));
799  BOOST_TEST((dynamicBackends[3] != nullptr));
800  BOOST_TEST((dynamicBackends[4] != nullptr));
801 
802  // Duplicates are allowed here, they will be skipped later during the backend registration
803  BOOST_TEST((dynamicBackends[0]->GetBackendId() == "TestValid2"));
804  BOOST_TEST((dynamicBackends[1]->GetBackendId() == "TestValid3"));
805  BOOST_TEST((dynamicBackends[2]->GetBackendId() == "TestValid2")); // From duplicate Arm_TestValid2_backend.so
806  BOOST_TEST((dynamicBackends[3]->GetBackendId() == "TestValid2")); // From Arm_TestValid4_backend.so
807  BOOST_TEST((dynamicBackends[4]->GetBackendId() == "TestValid5"));
808 }
809 
811 {
812  using namespace armnn;
813 
814  std::vector<DynamicBackendPtr> dynamicBackends = DynamicBackendUtils::CreateDynamicBackends({});
815 
816  BOOST_TEST(dynamicBackends.empty());
817 }
818 
820 {
821  using namespace armnn;
822 
823  std::vector<std::string> sharedObjects
824  {
825  "InvalidSharedObject1",
826  "InvalidSharedObject2",
827  "InvalidSharedObject3",
828  };
829  std::vector<DynamicBackendPtr> dynamicBackends = DynamicBackendUtils::CreateDynamicBackends(sharedObjects);
830 
831  BOOST_TEST(dynamicBackends.empty());
832 }
833 
835 {
836  using namespace armnn;
837  using namespace boost::filesystem;
838 
839  std::string testDynamicBackendsSubDir5 = GetTestSubDirectory(g_TestDynamicBackendsSubDir5);
840  std::string testDynamicBackendsSubDir6 = GetTestSubDirectory(g_TestDynamicBackendsSubDir6);
841  BOOST_CHECK(exists(testDynamicBackendsSubDir5));
842  BOOST_CHECK(exists(testDynamicBackendsSubDir6));
843 
844  std::string testValidBackend2FilePath = GetTestFilePath(testDynamicBackendsSubDir5,
845  g_TestValidBackend2FileName);
846  std::string testInvalidBackend8FilePath = GetTestFilePath(testDynamicBackendsSubDir5,
847  g_TestInvalidBackend8FileName);
848  std::string testInvalidBackend9FilePath = GetTestFilePath(testDynamicBackendsSubDir6,
849  g_TestInvalidBackend9FileName);
850  BOOST_CHECK(exists(testValidBackend2FilePath));
851  BOOST_CHECK(exists(testInvalidBackend8FilePath));
852  BOOST_CHECK(exists(testInvalidBackend9FilePath));
853 
854  std::vector<std::string> sharedObjects
855  {
856  testValidBackend2FilePath, // Arm_TestValid2_backend.so -> valid (basic backend name)
857  testInvalidBackend8FilePath, // Arm_TestInvalid8_backend.so -> not valid (invalid backend id)
858  testInvalidBackend9FilePath, // Arm_TestInvalid9_backend.so -> not valid (incompatible version)
859  "InvalidSharedObject", // The file does not exist
860  };
861  std::vector<DynamicBackendPtr> dynamicBackends = DynamicBackendUtils::CreateDynamicBackends(sharedObjects);
862 
863  BOOST_TEST(dynamicBackends.size() == 1);
864  BOOST_TEST((dynamicBackends[0] != nullptr));
865  BOOST_TEST((dynamicBackends[0]->GetBackendId() == "TestValid2"));
866 }
867 
869 {
870  using namespace armnn;
871  using namespace boost::filesystem;
872 
873  // Register one valid dynamic backend
874 
875  // Dummy registry used for testing
876  BackendRegistry backendRegistry;
877  BOOST_TEST(backendRegistry.Size() == 0);
878 
879  std::string testDynamicBackendsSubDir5 = GetTestSubDirectory(g_TestDynamicBackendsSubDir5);
880  BOOST_CHECK(exists(testDynamicBackendsSubDir5));
881 
882  std::string testValidBackend2FilePath = GetTestFilePath(testDynamicBackendsSubDir5, g_TestValidBackend2FileName);
883  BOOST_CHECK(exists(testValidBackend2FilePath));
884 
885  std::vector<std::string> sharedObjects{ testValidBackend2FilePath };
886  std::vector<DynamicBackendPtr> dynamicBackends = TestDynamicBackendUtils::CreateDynamicBackends(sharedObjects);
887 
888  BOOST_TEST(dynamicBackends.size() == 1);
889  BOOST_TEST((dynamicBackends[0] != nullptr));
890 
891  BackendId dynamicBackendId = dynamicBackends[0]->GetBackendId();
892  BOOST_TEST((dynamicBackendId == "TestValid2"));
893 
894  BackendVersion dynamicBackendVersion = dynamicBackends[0]->GetBackendVersion();
895  BOOST_TEST(TestDynamicBackendUtils::IsBackendCompatible(dynamicBackendVersion));
896 
897  BackendIdSet registeredBackendIds = TestDynamicBackendUtils::RegisterDynamicBackendsImplTest(backendRegistry,
898  dynamicBackends);
899  BOOST_TEST(backendRegistry.Size() == 1);
900  BOOST_TEST(registeredBackendIds.size() == 1);
901 
902  BackendIdSet backendIds = backendRegistry.GetBackendIds();
903  BOOST_TEST(backendIds.size() == 1);
904  BOOST_TEST((backendIds.find(dynamicBackendId) != backendIds.end()));
905  BOOST_TEST((registeredBackendIds.find(dynamicBackendId) != registeredBackendIds.end()));
906 
907  auto dynamicBackendFactoryFunction = backendRegistry.GetFactory(dynamicBackendId);
908  BOOST_TEST((dynamicBackendFactoryFunction != nullptr));
909 
910  IBackendInternalUniquePtr dynamicBackend = dynamicBackendFactoryFunction();
911  BOOST_TEST((dynamicBackend != nullptr));
912  BOOST_TEST((dynamicBackend->GetId() == dynamicBackendId));
913 }
914 
916 {
917  using namespace armnn;
918  using namespace boost::filesystem;
919 
920  // Register many valid dynamic backends
921 
922  std::string testDynamicBackendsSubDir5 = GetTestSubDirectory(g_TestDynamicBackendsSubDir5);
923  std::string testDynamicBackendsSubDir6 = GetTestSubDirectory(g_TestDynamicBackendsSubDir6);
924  BOOST_CHECK(exists(testDynamicBackendsSubDir5));
925  BOOST_CHECK(exists(testDynamicBackendsSubDir6));
926 
927  std::string testValidBackend2FilePath = GetTestFilePath(testDynamicBackendsSubDir5, g_TestValidBackend2FileName);
928  std::string testValidBackend3FilePath = GetTestFilePath(testDynamicBackendsSubDir5, g_TestValidBackend3FileName);
929  std::string testValidBackend5FilePath = GetTestFilePath(testDynamicBackendsSubDir6, g_TestValidBackend5FileName);
930  BOOST_CHECK(exists(testValidBackend2FilePath));
931  BOOST_CHECK(exists(testValidBackend3FilePath));
932  BOOST_CHECK(exists(testValidBackend5FilePath));
933 
934  std::vector<std::string> sharedObjects
935  {
936  testValidBackend2FilePath,
937  testValidBackend3FilePath,
938  testValidBackend5FilePath
939  };
940  std::vector<DynamicBackendPtr> dynamicBackends = TestDynamicBackendUtils::CreateDynamicBackends(sharedObjects);
941 
942  BOOST_TEST(dynamicBackends.size() == 3);
943  BOOST_TEST((dynamicBackends[0] != nullptr));
944  BOOST_TEST((dynamicBackends[1] != nullptr));
945  BOOST_TEST((dynamicBackends[2] != nullptr));
946 
947  BackendId dynamicBackendId1 = dynamicBackends[0]->GetBackendId();
948  BackendId dynamicBackendId2 = dynamicBackends[1]->GetBackendId();
949  BackendId dynamicBackendId3 = dynamicBackends[2]->GetBackendId();
950  BOOST_TEST((dynamicBackendId1 == "TestValid2"));
951  BOOST_TEST((dynamicBackendId2 == "TestValid3"));
952  BOOST_TEST((dynamicBackendId3 == "TestValid5"));
953 
954  for (size_t i = 0; i < dynamicBackends.size(); i++)
955  {
956  BackendVersion dynamicBackendVersion = dynamicBackends[i]->GetBackendVersion();
957  BOOST_TEST(TestDynamicBackendUtils::IsBackendCompatible(dynamicBackendVersion));
958  }
959 
960  // Dummy registry used for testing
961  BackendRegistry backendRegistry;
962  BOOST_TEST(backendRegistry.Size() == 0);
963 
964  BackendIdSet registeredBackendIds = TestDynamicBackendUtils::RegisterDynamicBackendsImplTest(backendRegistry,
965  dynamicBackends);
966  BOOST_TEST(backendRegistry.Size() == 3);
967  BOOST_TEST(registeredBackendIds.size() == 3);
968 
969  BackendIdSet backendIds = backendRegistry.GetBackendIds();
970  BOOST_TEST(backendIds.size() == 3);
971  BOOST_TEST((backendIds.find(dynamicBackendId1) != backendIds.end()));
972  BOOST_TEST((backendIds.find(dynamicBackendId2) != backendIds.end()));
973  BOOST_TEST((backendIds.find(dynamicBackendId3) != backendIds.end()));
974  BOOST_TEST((registeredBackendIds.find(dynamicBackendId1) != registeredBackendIds.end()));
975  BOOST_TEST((registeredBackendIds.find(dynamicBackendId2) != registeredBackendIds.end()));
976  BOOST_TEST((registeredBackendIds.find(dynamicBackendId3) != registeredBackendIds.end()));
977 
978  for (size_t i = 0; i < dynamicBackends.size(); i++)
979  {
980  BackendId dynamicBackendId = dynamicBackends[i]->GetBackendId();
981 
982  auto dynamicBackendFactoryFunction = backendRegistry.GetFactory(dynamicBackendId);
983  BOOST_TEST((dynamicBackendFactoryFunction != nullptr));
984 
985  IBackendInternalUniquePtr dynamicBackend = dynamicBackendFactoryFunction();
986  BOOST_TEST((dynamicBackend != nullptr));
987  BOOST_TEST((dynamicBackend->GetId() == dynamicBackendId));
988  }
989 }
990 
992 {
993  using namespace armnn;
994  using namespace boost::filesystem;
995 
996  // Try to register many invalid dynamic backends
997 
998  // The test covers one directory:
999  // <unit test path>/src/backends/backendsCommon/test/
1000  // └─ backendsTestPath9/ -> exists, contains files
1001  //
1002  // The test sub-directory backendsTestPath9/ contains the following test files:
1003  //
1004  // Arm_TestInvalid10_backend.so -> not valid (invalid backend id)
1005  // Arm_TestInvalid11_backend.so -> not valid (invalid backend id)
1006 
1007  std::string testDynamicBackendsSubDir9 = GetTestSubDirectory(g_TestDynamicBackendsSubDir9);
1008  BOOST_CHECK(exists(testDynamicBackendsSubDir9));
1009 
1010  std::string testInvalidBackend10FilePath = GetTestFilePath(testDynamicBackendsSubDir9,
1011  g_TestInvalidBackend10FileName);
1012  std::string testInvalidBackend11FilePath = GetTestFilePath(testDynamicBackendsSubDir9,
1013  g_TestInvalidBackend11FileName);
1014  BOOST_CHECK(exists(testInvalidBackend10FilePath));
1015  BOOST_CHECK(exists(testInvalidBackend11FilePath));
1016 
1017  std::vector<std::string> sharedObjects
1018  {
1019  testInvalidBackend10FilePath,
1020  testInvalidBackend11FilePath,
1021  "InvalidSharedObject"
1022  };
1023  std::vector<DynamicBackendPtr> dynamicBackends = TestDynamicBackendUtils::CreateDynamicBackends(sharedObjects);
1024 
1025  BOOST_TEST(dynamicBackends.size() == 2);
1026  BOOST_TEST((dynamicBackends[0] != nullptr));
1027  BOOST_TEST((dynamicBackends[1] != nullptr));
1028 
1029  BackendId dynamicBackendId1 = dynamicBackends[0]->GetBackendId();
1030  BackendId dynamicBackendId2 = dynamicBackends[1]->GetBackendId();
1031  BOOST_TEST((dynamicBackendId1 == ""));
1032  BOOST_TEST((dynamicBackendId2 == "Unknown"));
1033 
1034  for (size_t i = 0; i < dynamicBackends.size(); i++)
1035  {
1036  BackendVersion dynamicBackendVersion = dynamicBackends[i]->GetBackendVersion();
1037  BOOST_TEST(TestDynamicBackendUtils::IsBackendCompatible(dynamicBackendVersion));
1038  }
1039 
1040  // Dummy registry used for testing
1041  BackendRegistry backendRegistry;
1042  BOOST_TEST(backendRegistry.Size() == 0);
1043 
1044  // Check that no dynamic backend got registered
1045  BackendIdSet registeredBackendIds = TestDynamicBackendUtils::RegisterDynamicBackendsImplTest(backendRegistry,
1046  dynamicBackends);
1047  BOOST_TEST(backendRegistry.Size() == 0);
1048  BOOST_TEST(registeredBackendIds.empty());
1049 }
1050 
1052 {
1053  using namespace armnn;
1054  using namespace boost::filesystem;
1055 
1056  // The test covers five directories:
1057  // <unit test path>/src/backends/backendsCommon/test/
1058  // ├─ backendsTestPath5/ -> exists, contains files
1059  // ├─ backendsTestPath6/ -> exists, contains files
1060  // ├─ backendsTestPath7/ -> exists, but empty
1061  // ├─ backendsTestPath8/ -> does not exist
1062  // └─ backendsTestPath9/ -> exists, contains files
1063  //
1064  // The test sub-directory backendsTestPath5/ contains the following test files:
1065  //
1066  // Arm_TestValid2_backend.so -> valid (basic backend name)
1067  // Arm_TestValid3_backend.so -> valid (basic backend name)
1068  // Arm_TestInvalid8_backend.so -> not valid (invalid backend id)
1069  //
1070  // The test sub-directory backendsTestPath6/ contains the following test files:
1071  //
1072  // Arm_TestValid2_backend.so -> valid (but duplicated from backendsTestPath5/)
1073  // Arm_TestValid4_backend.so -> valid (it has a different filename,
1074  // but it has the same backend id of Arm_TestValid2_backend.so
1075  // and the same version)
1076  // Arm_TestValid5_backend.so -> valid (basic backend name)
1077  // Arm_TestInvalid9_backend.so -> not valid (it has a different filename,
1078  // but it has the same backend id of Arm_TestValid2_backend.so
1079  // and a version incompatible with the Backend API)
1080  //
1081  // The test sub-directory backendsTestPath9/ contains the following test files:
1082  //
1083  // Arm_TestInvalid10_backend.so -> not valid (empty backend id)
1084  // Arm_TestInvalid11_backend.so -> not valid ("Unknown" backend id)
1085 
1086  std::string testDynamicBackendsSubDir5 = GetTestSubDirectory(g_TestDynamicBackendsSubDir5);
1087  std::string testDynamicBackendsSubDir6 = GetTestSubDirectory(g_TestDynamicBackendsSubDir6);
1088  std::string testDynamicBackendsSubDir7 = GetTestSubDirectory(g_TestDynamicBackendsSubDir7);
1089  std::string testDynamicBackendsSubDir8 = GetTestSubDirectory(g_TestDynamicBackendsSubDir8);
1090  std::string testDynamicBackendsSubDir9 = GetTestSubDirectory(g_TestDynamicBackendsSubDir9);
1091  BOOST_CHECK(exists(testDynamicBackendsSubDir5));
1092  BOOST_CHECK(exists(testDynamicBackendsSubDir6));
1093  BOOST_CHECK(exists(testDynamicBackendsSubDir7));
1094  BOOST_CHECK(!exists(testDynamicBackendsSubDir8));
1095  BOOST_CHECK(exists(testDynamicBackendsSubDir9));
1096 
1097  std::string testValidBackend2FilePath = GetTestFilePath(testDynamicBackendsSubDir5, g_TestValidBackend2FileName);
1098  std::string testValidBackend3FilePath = GetTestFilePath(testDynamicBackendsSubDir5, g_TestValidBackend3FileName);
1099  std::string testValidBackend2DupFilePath = GetTestFilePath(testDynamicBackendsSubDir6, g_TestValidBackend2FileName);
1100  std::string testValidBackend4FilePath = GetTestFilePath(testDynamicBackendsSubDir6, g_TestValidBackend4FileName);
1101  std::string testValidBackend5FilePath = GetTestFilePath(testDynamicBackendsSubDir6, g_TestValidBackend5FileName);
1102  std::string testInvalidBackend8FilePath = GetTestFilePath(testDynamicBackendsSubDir5,
1103  g_TestInvalidBackend8FileName);
1104  std::string testInvalidBackend9FilePath = GetTestFilePath(testDynamicBackendsSubDir6,
1105  g_TestInvalidBackend9FileName);
1106  std::string testInvalidBackend10FilePath = GetTestFilePath(testDynamicBackendsSubDir9,
1107  g_TestInvalidBackend10FileName);
1108  std::string testInvalidBackend11FilePath = GetTestFilePath(testDynamicBackendsSubDir9,
1109  g_TestInvalidBackend11FileName);
1110  BOOST_CHECK(exists(testValidBackend2FilePath));
1111  BOOST_CHECK(exists(testValidBackend3FilePath));
1112  BOOST_CHECK(exists(testValidBackend2DupFilePath));
1113  BOOST_CHECK(exists(testValidBackend4FilePath));
1114  BOOST_CHECK(exists(testValidBackend5FilePath));
1115  BOOST_CHECK(exists(testInvalidBackend8FilePath));
1116  BOOST_CHECK(exists(testInvalidBackend9FilePath));
1117  BOOST_CHECK(exists(testInvalidBackend10FilePath));
1118  BOOST_CHECK(exists(testInvalidBackend11FilePath));
1119 
1120  std::vector<std::string> sharedObjects
1121  {
1122  testValidBackend2FilePath,
1123  testValidBackend3FilePath,
1124  testValidBackend2DupFilePath,
1125  testValidBackend4FilePath,
1126  testValidBackend5FilePath,
1127  testInvalidBackend8FilePath,
1128  testInvalidBackend9FilePath,
1129  testInvalidBackend10FilePath,
1130  testInvalidBackend11FilePath,
1131  "InvalidSharedObject"
1132  };
1133  std::vector<DynamicBackendPtr> dynamicBackends = TestDynamicBackendUtils::CreateDynamicBackends(sharedObjects);
1134 
1135  BOOST_TEST(dynamicBackends.size() == 7);
1136  BOOST_TEST((dynamicBackends[0] != nullptr));
1137  BOOST_TEST((dynamicBackends[1] != nullptr));
1138  BOOST_TEST((dynamicBackends[2] != nullptr));
1139  BOOST_TEST((dynamicBackends[3] != nullptr));
1140  BOOST_TEST((dynamicBackends[4] != nullptr));
1141  BOOST_TEST((dynamicBackends[5] != nullptr));
1142  BOOST_TEST((dynamicBackends[6] != nullptr));
1143 
1144  BackendId dynamicBackendId1 = dynamicBackends[0]->GetBackendId();
1145  BackendId dynamicBackendId2 = dynamicBackends[1]->GetBackendId();
1146  BackendId dynamicBackendId3 = dynamicBackends[2]->GetBackendId();
1147  BackendId dynamicBackendId4 = dynamicBackends[3]->GetBackendId();
1148  BackendId dynamicBackendId5 = dynamicBackends[4]->GetBackendId();
1149  BackendId dynamicBackendId6 = dynamicBackends[5]->GetBackendId();
1150  BackendId dynamicBackendId7 = dynamicBackends[6]->GetBackendId();
1151  BOOST_TEST((dynamicBackendId1 == "TestValid2"));
1152  BOOST_TEST((dynamicBackendId2 == "TestValid3"));
1153  BOOST_TEST((dynamicBackendId3 == "TestValid2")); // From duplicate Arm_TestValid2_backend.so
1154  BOOST_TEST((dynamicBackendId4 == "TestValid2")); // From Arm_TestValid4_backend.so
1155  BOOST_TEST((dynamicBackendId5 == "TestValid5"));
1156  BOOST_TEST((dynamicBackendId6 == ""));
1157  BOOST_TEST((dynamicBackendId7 == "Unknown"));
1158 
1159  for (size_t i = 0; i < dynamicBackends.size(); i++)
1160  {
1161  BackendVersion dynamicBackendVersion = dynamicBackends[i]->GetBackendVersion();
1162  BOOST_TEST(TestDynamicBackendUtils::IsBackendCompatible(dynamicBackendVersion));
1163  }
1164 
1165  // Dummy registry used for testing
1166  BackendRegistry backendRegistry;
1167  BOOST_TEST(backendRegistry.Size() == 0);
1168 
1169  std::vector<BackendId> expectedRegisteredbackendIds
1170  {
1171  "TestValid2",
1172  "TestValid3",
1173  "TestValid5"
1174  };
1175 
1176  BackendIdSet registeredBackendIds = TestDynamicBackendUtils::RegisterDynamicBackendsImplTest(backendRegistry,
1177  dynamicBackends);
1178  BOOST_TEST(backendRegistry.Size() == expectedRegisteredbackendIds.size());
1179  BOOST_TEST(registeredBackendIds.size() == expectedRegisteredbackendIds.size());
1180 
1181  BackendIdSet backendIds = backendRegistry.GetBackendIds();
1182  BOOST_TEST(backendIds.size() == expectedRegisteredbackendIds.size());
1183  for (const BackendId& expectedRegisteredbackendId : expectedRegisteredbackendIds)
1184  {
1185  BOOST_TEST((backendIds.find(expectedRegisteredbackendId) != backendIds.end()));
1186  BOOST_TEST((registeredBackendIds.find(expectedRegisteredbackendId) != registeredBackendIds.end()));
1187 
1188  auto dynamicBackendFactoryFunction = backendRegistry.GetFactory(expectedRegisteredbackendId);
1189  BOOST_TEST((dynamicBackendFactoryFunction != nullptr));
1190 
1191  IBackendInternalUniquePtr dynamicBackend = dynamicBackendFactoryFunction();
1192  BOOST_TEST((dynamicBackend != nullptr));
1193  BOOST_TEST((dynamicBackend->GetId() == expectedRegisteredbackendId));
1194  }
1195 }
1196 
1197 #if !defined(ARMNN_DYNAMIC_BACKEND_ENABLED)
1198 
1200 {
1201  using namespace armnn;
1202 
1203  // Swapping the backend registry storage for testing
1204  TestBackendRegistry testBackendRegistry;
1205 
1206  const BackendRegistry& backendRegistry = BackendRegistryInstance();
1207  BOOST_TEST(backendRegistry.Size() == 0);
1208 
1209  IRuntime::CreationOptions creationOptions;
1210  IRuntimePtr runtime = IRuntime::Create(creationOptions);
1211 
1212  const DeviceSpec& deviceSpec = *PolymorphicDowncast<const DeviceSpec*>(&runtime->GetDeviceSpec());
1213  BackendIdSet supportedBackendIds = deviceSpec.GetSupportedBackends();
1214  BOOST_TEST(supportedBackendIds.empty());
1215 
1216  BOOST_TEST(backendRegistry.Size() == 0);
1217 }
1218 
1219 #endif
1220 
1222 {
1223  using namespace armnn;
1224  using namespace boost::filesystem;
1225 
1226  // Swapping the backend registry storage for testing
1227  TestBackendRegistry testBackendRegistry;
1228 
1229  // This directory contains valid and invalid backends
1230  std::string testDynamicBackendsSubDir5 = GetTestSubDirectory(g_TestDynamicBackendsSubDir5);
1231  BOOST_CHECK(exists(testDynamicBackendsSubDir5));
1232 
1233  // Using the path override in CreationOptions to load some test dynamic backends
1234  IRuntime::CreationOptions creationOptions;
1235  creationOptions.m_DynamicBackendsPath = testDynamicBackendsSubDir5;
1236  IRuntimePtr runtime = IRuntime::Create(creationOptions);
1237 
1238  std::vector<BackendId> expectedRegisteredbackendIds
1239  {
1240  "TestValid2",
1241  "TestValid3"
1242  };
1243 
1244  const BackendRegistry& backendRegistry = BackendRegistryInstance();
1245  BOOST_TEST(backendRegistry.Size() == expectedRegisteredbackendIds.size());
1246 
1247  BackendIdSet backendIds = backendRegistry.GetBackendIds();
1248  for (const BackendId& expectedRegisteredbackendId : expectedRegisteredbackendIds)
1249  {
1250  BOOST_TEST((backendIds.find(expectedRegisteredbackendId) != backendIds.end()));
1251  }
1252 
1253  const DeviceSpec& deviceSpec = *PolymorphicDowncast<const DeviceSpec*>(&runtime->GetDeviceSpec());
1254  BackendIdSet supportedBackendIds = deviceSpec.GetSupportedBackends();
1255  BOOST_TEST(supportedBackendIds.size() == expectedRegisteredbackendIds.size());
1256  for (const BackendId& expectedRegisteredbackendId : expectedRegisteredbackendIds)
1257  {
1258  BOOST_TEST((supportedBackendIds.find(expectedRegisteredbackendId) != supportedBackendIds.end()));
1259  }
1260 }
1261 
1263 {
1264  using namespace armnn;
1265  using namespace boost::filesystem;
1266 
1267  // Swapping the backend registry storage for testing
1268  TestBackendRegistry testBackendRegistry;
1269 
1270  // This directory contains valid, invalid and duplicate backends
1271  std::string testDynamicBackendsSubDir6 = GetTestSubDirectory(g_TestDynamicBackendsSubDir6);
1272  BOOST_CHECK(exists(testDynamicBackendsSubDir6));
1273 
1274  // Using the path override in CreationOptions to load some test dynamic backends
1275  IRuntime::CreationOptions creationOptions;
1276  creationOptions.m_DynamicBackendsPath = testDynamicBackendsSubDir6;
1277  IRuntimePtr runtime = IRuntime::Create(creationOptions);
1278 
1279  std::vector<BackendId> expectedRegisteredbackendIds
1280  {
1281  "TestValid2",
1282  "TestValid5"
1283  };
1284 
1285  const BackendRegistry& backendRegistry = BackendRegistryInstance();
1286  BOOST_TEST(backendRegistry.Size() == expectedRegisteredbackendIds.size());
1287 
1288  BackendIdSet backendIds = backendRegistry.GetBackendIds();
1289  for (const BackendId& expectedRegisteredbackendId : expectedRegisteredbackendIds)
1290  {
1291  BOOST_TEST((backendIds.find(expectedRegisteredbackendId) != backendIds.end()));
1292  }
1293 
1294  const DeviceSpec& deviceSpec = *PolymorphicDowncast<const DeviceSpec*>(&runtime->GetDeviceSpec());
1295  BackendIdSet supportedBackendIds = deviceSpec.GetSupportedBackends();
1296  BOOST_TEST(supportedBackendIds.size() == expectedRegisteredbackendIds.size());
1297  for (const BackendId& expectedRegisteredbackendId : expectedRegisteredbackendIds)
1298  {
1299  BOOST_TEST((supportedBackendIds.find(expectedRegisteredbackendId) != supportedBackendIds.end()));
1300  }
1301 }
1302 
1304 {
1305  using namespace armnn;
1306  using namespace boost::filesystem;
1307 
1308  // Swapping the backend registry storage for testing
1309  TestBackendRegistry testBackendRegistry;
1310 
1311  // This directory contains only invalid backends
1312  std::string testDynamicBackendsSubDir9 = GetTestSubDirectory(g_TestDynamicBackendsSubDir9);
1313  BOOST_CHECK(exists(testDynamicBackendsSubDir9));
1314 
1315  // Using the path override in CreationOptions to load some test dynamic backends
1316  IRuntime::CreationOptions creationOptions;
1317  creationOptions.m_DynamicBackendsPath = testDynamicBackendsSubDir9;
1318  IRuntimePtr runtime = IRuntime::Create(creationOptions);
1319 
1320  const BackendRegistry& backendRegistry = BackendRegistryInstance();
1321  BOOST_TEST(backendRegistry.Size() == 0);
1322 
1323  const DeviceSpec& deviceSpec = *PolymorphicDowncast<const DeviceSpec*>(&runtime->GetDeviceSpec());
1324  BackendIdSet supportedBackendIds = deviceSpec.GetSupportedBackends();
1325  BOOST_TEST(supportedBackendIds.empty());
1326 }
1327 
1329 {
1330  using namespace armnn;
1331 
1332  // Swapping the backend registry storage for testing
1333  TestBackendRegistry testBackendRegistry;
1334 
1335  // Using the path override in CreationOptions to load some test dynamic backends
1336  IRuntime::CreationOptions creationOptions;
1337  creationOptions.m_DynamicBackendsPath = "InvalidPath";
1338  IRuntimePtr runtime = IRuntime::Create(creationOptions);
1339 
1340  const BackendRegistry& backendRegistry = BackendRegistryInstance();
1341  BOOST_TEST(backendRegistry.Size() == 0);
1342 
1343  const DeviceSpec& deviceSpec = *PolymorphicDowncast<const DeviceSpec*>(&runtime->GetDeviceSpec());
1344  BackendIdSet supportedBackendIds = deviceSpec.GetSupportedBackends();
1345  BOOST_TEST(supportedBackendIds.empty());
1346 }
1347 
1348 #if defined(ARMNNREF_ENABLED)
1349 
1350 // This test unit needs the reference backend, it's not available if the reference backend is not built
1351 
1352 void CreateReferenceDynamicBackendTestImpl()
1353 {
1354  using namespace armnn;
1355  using namespace boost::filesystem;
1356 
1357  // Swapping the backend registry storage for testing
1358  TestBackendRegistry testBackendRegistry;
1359 
1360  // This directory contains the reference dynamic backend
1361  std::string dynamicBackendsBaseDir = GetDynamicBackendsBasePath();
1362  std::string referenceDynamicBackendSubDir = GetTestSubDirectory(dynamicBackendsBaseDir,
1363  g_ReferenceDynamicBackendSubDir);
1364  BOOST_CHECK(exists(referenceDynamicBackendSubDir));
1365 
1366  // Check that the reference dynamic backend file exists
1367  std::string referenceBackendFilePath = GetTestFilePath(referenceDynamicBackendSubDir,
1368  g_ReferenceBackendFileName);
1369  BOOST_CHECK(exists(referenceBackendFilePath));
1370 
1371  // Using the path override in CreationOptions to load the reference dynamic backend
1372  IRuntime::CreationOptions creationOptions;
1373  creationOptions.m_DynamicBackendsPath = referenceDynamicBackendSubDir;
1374  IRuntimePtr runtime = IRuntime::Create(creationOptions);
1375 
1376  const BackendRegistry& backendRegistry = BackendRegistryInstance();
1377  BOOST_TEST(backendRegistry.Size() == 1);
1378 
1379  BackendIdSet backendIds = backendRegistry.GetBackendIds();
1380  BOOST_TEST((backendIds.find("CpuRef") != backendIds.end()));
1381 
1382  const DeviceSpec& deviceSpec = *PolymorphicDowncast<const DeviceSpec*>(&runtime->GetDeviceSpec());
1383  BackendIdSet supportedBackendIds = deviceSpec.GetSupportedBackends();
1384  BOOST_TEST(supportedBackendIds.size() == 1);
1385  BOOST_TEST((supportedBackendIds.find("CpuRef") != supportedBackendIds.end()));
1386 
1387  // Get the factory function
1388  auto referenceDynamicBackendFactoryFunction = backendRegistry.GetFactory("CpuRef");
1389  BOOST_TEST((referenceDynamicBackendFactoryFunction != nullptr));
1390 
1391  // Use the factory function to create an instance of the reference backend
1392  IBackendInternalUniquePtr referenceDynamicBackend = referenceDynamicBackendFactoryFunction();
1393  BOOST_TEST((referenceDynamicBackend != nullptr));
1394  BOOST_TEST((referenceDynamicBackend->GetId() == "CpuRef"));
1395 
1396  // Test the backend instance by querying the layer support
1397  IBackendInternal::ILayerSupportSharedPtr referenceLayerSupport = referenceDynamicBackend->GetLayerSupport();
1398  BOOST_TEST((referenceLayerSupport != nullptr));
1399 
1400  TensorShape inputShape { 1, 16, 16, 16 };
1401  TensorShape outputShape{ 1, 16, 16, 16 };
1402  TensorShape weightShape{ 16, 1, 1, 16 };
1403  TensorInfo inputInfo (inputShape, DataType::Float32);
1404  TensorInfo outputInfo(outputShape, DataType::Float32);
1405  TensorInfo weightInfo(weightShape, DataType::Float32);
1406  Convolution2dDescriptor convolution2dDescriptor;
1407  bool referenceConvolution2dSupported =
1408  referenceLayerSupport->IsConvolution2dSupported(inputInfo,
1409  outputInfo,
1410  convolution2dDescriptor,
1411  weightInfo,
1412  EmptyOptional());
1413  BOOST_TEST(referenceConvolution2dSupported);
1414 
1415  // Test the backend instance by creating a workload
1416  IBackendInternal::IWorkloadFactoryPtr referenceWorkloadFactory = referenceDynamicBackend->CreateWorkloadFactory();
1417  BOOST_TEST((referenceWorkloadFactory != nullptr));
1418 
1419  // Create dummy settings for the workload
1420  Convolution2dQueueDescriptor convolution2dQueueDescriptor;
1421  WorkloadInfo workloadInfo
1422  {
1423  { inputInfo },
1424  { outputInfo }
1425  };
1426  convolution2dQueueDescriptor.m_Inputs.push_back(nullptr);
1427  auto weights = std::make_unique<ScopedCpuTensorHandle>(weightInfo);
1428  convolution2dQueueDescriptor.m_Weight = weights.get();
1429 
1430  // Create a convolution workload with the dummy settings
1431  auto workload = referenceWorkloadFactory->CreateConvolution2d(convolution2dQueueDescriptor, workloadInfo);
1432  BOOST_TEST((workload != nullptr));
1433  BOOST_TEST(workload.get() == PolymorphicDowncast<RefConvolution2dWorkload*>(workload.get()));
1434 }
1435 
1436 #endif
1437 
1438 #if defined(SAMPLE_DYNAMIC_BACKEND_ENABLED)
1439 void CreateSampleDynamicBackendTestImpl()
1440 {
1441  using namespace armnn;
1442 
1443  // Using the path override in CreationOptions to load the reference dynamic backend
1444  IRuntime::CreationOptions creationOptions;
1445  IRuntimePtr runtime = IRuntime::Create(creationOptions);
1446 
1447  const BackendRegistry& backendRegistry = BackendRegistryInstance();
1448  BOOST_TEST(backendRegistry.Size() >= 1);
1449 
1450  BackendIdSet backendIds = backendRegistry.GetBackendIds();
1451  BOOST_TEST((backendIds.find("SampleDynamic") != backendIds.end()));
1452 
1453  const DeviceSpec& deviceSpec = *PolymorphicDowncast<const DeviceSpec*>(&runtime->GetDeviceSpec());
1454  BackendIdSet supportedBackendIds = deviceSpec.GetSupportedBackends();
1455  BOOST_TEST(supportedBackendIds.size()>= 1);
1456  BOOST_TEST((supportedBackendIds.find("SampleDynamic") != supportedBackendIds.end()));
1457 
1458  // Get the factory function
1459  auto sampleDynamicBackendFactoryFunction = backendRegistry.GetFactory("SampleDynamic");
1460  BOOST_TEST((sampleDynamicBackendFactoryFunction != nullptr));
1461 
1462  // Use the factory function to create an instance of the dynamic backend
1463  IBackendInternalUniquePtr sampleDynamicBackend = sampleDynamicBackendFactoryFunction();
1464  BOOST_TEST((sampleDynamicBackend != nullptr));
1465  BOOST_TEST((sampleDynamicBackend->GetId() == "SampleDynamic"));
1466 
1467  // Test the backend instance by querying the layer support
1468  IBackendInternal::ILayerSupportSharedPtr sampleLayerSupport = sampleDynamicBackend->GetLayerSupport();
1469  BOOST_TEST((sampleLayerSupport != nullptr));
1470 
1471  TensorShape inputShape { 1, 16, 16, 16 };
1472  TensorShape outputShape{ 1, 16, 16, 16 };
1473  TensorShape weightShape{ 16, 1, 1, 16 };
1474  TensorInfo inputInfo (inputShape, DataType::Float32);
1475  TensorInfo outputInfo(outputShape, DataType::Float32);
1476  TensorInfo weightInfo(weightShape, DataType::Float32);
1477  Convolution2dDescriptor convolution2dDescriptor;
1478  bool sampleConvolution2dSupported =
1479  sampleLayerSupport->IsConvolution2dSupported(inputInfo,
1480  outputInfo,
1481  convolution2dDescriptor,
1482  weightInfo,
1483  EmptyOptional());
1484  BOOST_TEST(!sampleConvolution2dSupported);
1485 
1486  // Test the backend instance by creating a workload
1487  IBackendInternal::IWorkloadFactoryPtr sampleWorkloadFactory = sampleDynamicBackend->CreateWorkloadFactory();
1488  BOOST_TEST((sampleWorkloadFactory != nullptr));
1489 
1490  // Create dummy settings for the workload
1491  AdditionQueueDescriptor additionQueueDescriptor;
1492  WorkloadInfo workloadInfo
1493  {
1494  { inputInfo, inputInfo },
1495  { outputInfo }
1496  };
1497 
1498  // Create a addition workload
1499  auto workload = sampleWorkloadFactory->CreateAddition(additionQueueDescriptor, workloadInfo);
1500  BOOST_TEST((workload != nullptr));
1501 }
1502 
1503 void SampleDynamicBackendEndToEndTestImpl()
1504 {
1505  using namespace armnn;
1506  using namespace boost::filesystem;
1507  // Create runtime in which test will run
1509  IRuntimePtr runtime(IRuntime::Create(options));
1510 
1511  // Builds up the structure of the network.
1512  INetworkPtr net(INetwork::Create());
1513 
1514  IConnectableLayer* input0 = net->AddInputLayer(0);
1515  IConnectableLayer* input1 = net->AddInputLayer(1);
1516  IConnectableLayer* add = net->AddAdditionLayer();
1517  IConnectableLayer* output = net->AddOutputLayer(0);
1518 
1519  input0->GetOutputSlot(0).Connect(add->GetInputSlot(0));
1520  input1->GetOutputSlot(0).Connect(add->GetInputSlot(1));
1521  add->GetOutputSlot(0).Connect(output->GetInputSlot(0));
1522 
1523  TensorInfo tensorInfo(TensorShape({2, 1}), DataType::Float32);
1524  input0->GetOutputSlot(0).SetTensorInfo(tensorInfo);
1525  input1->GetOutputSlot(0).SetTensorInfo(tensorInfo);
1526  add->GetOutputSlot(0).SetTensorInfo(tensorInfo);
1527 
1528  // optimize the network
1529  IOptimizedNetworkPtr optNet = Optimize(*net, {"SampleDynamic"}, runtime->GetDeviceSpec());
1530 
1531  // Loads it into the runtime.
1532  NetworkId netId;
1533  runtime->LoadNetwork(netId, std::move(optNet));
1534 
1535  std::vector<float> input0Data{ 5.0f, 3.0f };
1536  std::vector<float> input1Data{ 10.0f, 8.0f };
1537  std::vector<float> expectedOutputData{ 15.0f, 11.0f };
1538  std::vector<float> outputData(2);
1539 
1540  InputTensors inputTensors
1541  {
1542  {0,armnn::ConstTensor(runtime->GetInputTensorInfo(netId, 0), input0Data.data())},
1543  {1,armnn::ConstTensor(runtime->GetInputTensorInfo(netId, 0), input1Data.data())}
1544  };
1545  OutputTensors outputTensors
1546  {
1547  {0,armnn::Tensor(runtime->GetOutputTensorInfo(netId, 0), outputData.data())}
1548  };
1549 
1550  // Does the inference.
1551  runtime->EnqueueWorkload(netId, inputTensors, outputTensors);
1552 
1553  // Checks the results.
1554  BOOST_TEST(outputData == expectedOutputData);
1555 }
1556 #endif
void GetNameMangledEntryPointTestImpl()
void GetNoExternEntryPointTestImpl()
void GetSharedObjectsTestImpl()
void CreateDynamicBackendsNoPathsTestImpl()
static armnn::BackendIdSet RegisterDynamicBackendsImplTest(armnn::BackendRegistry &backendRegistry, const std::vector< armnn::DynamicBackendPtr > &dynamicBackends)
FactoryFunction GetFactory(const BackendId &id) const
std::unique_ptr< IWorkloadFactory > IWorkloadFactoryPtr
Interface for a layer that is connectable to other layers via InputSlots and OutputSlots.
Definition: INetwork.hpp:61
BackendIdSet GetBackendIds() const
void CreateDynamicBackendObjectInvalidInterface3TestImpl()
std::function< PointerType()> FactoryFunction
std::string GetTestSubDirectory(const std::string &subdir)
std::unordered_set< BackendId > BackendIdSet
Definition: BackendId.hpp:191
void CreateDynamicBackendsAllInvalidTestImpl()
static bool IsBackendCompatible(const BackendVersion &backendVersion)
void OpenNotSharedObjectTestImpl()
A Convolution2dDescriptor for the Convolution2dLayer.
std::string GetTestDirectoryBasePath()
std::unique_ptr< IRuntime, void(*)(IRuntime *runtime)> IRuntimePtr
Definition: IRuntime.hpp:25
std::unordered_map< BackendId, FactoryFunction > FactoryStorage
BackendRegistry & BackendRegistryInstance()
std::vector< std::pair< LayerBindingId, class ConstTensor > > InputTensors
Definition: Tensor.hpp:225
void BackendVersioningTestImpl()
static std::vector< DynamicBackendPtr > CreateDynamicBackends(const std::vector< std::string > &sharedObjects)
void CreateDynamicBackendObjectInvalidHandleTestImpl()
int NetworkId
Definition: IRuntime.hpp:20
std::string GetTestFilePath(const std::string &directory, const std::string &fileName)
Copyright (c) 2020 ARM Limited.
BOOST_CHECK(profilingService.GetCurrentState()==ProfilingState::WaitingForAck)
std::unique_ptr< DynamicBackend > DynamicBackendPtr
void CreateDynamicBackendObjectInvalidInterface6TestImpl()
static std::vector< std::string > GetBackendPathsImplTest(const std::string &path)
virtual void SetTensorInfo(const TensorInfo &tensorInfo)=0
void RegisterMixedDynamicBackendsTestImpl()
A tensor defined by a TensorInfo (shape and data type) and a mutable backing store.
Definition: Tensor.hpp:191
void GetValidEntryPointTestImpl()
void RuntimeDynamicBackendsTestImpl()
void GetBackendPathsOverrideTestImpl()
const char * GetBackendId()
IOptimizedNetworkPtr Optimize(const INetwork &network, const std::vector< BackendId > &backendPreferences, const IDeviceSpec &deviceSpec, const OptimizerOptions &options=OptimizerOptions(), Optional< std::vector< std::string > &> messages=EmptyOptional())
Create an optimized version of the network.
Definition: Network.cpp:1003
void CreateDynamicBackendObjectInvalidInterface5TestImpl()
const ConstCpuTensorHandle * m_Weight
A tensor defined by a TensorInfo (shape and data type) and an immutable backing store.
Definition: Tensor.hpp:199
void RegisterMultipleInvalidDynamicBackendsTestImpl()
std::vector< std::pair< LayerBindingId, class Tensor > > OutputTensors
Definition: Tensor.hpp:226
void GetNotExistingEntryPointTestImpl()
void CreateDynamicBackendObjectInvalidInterface1TestImpl()
std::unique_ptr< IOptimizedNetwork, void(*)(IOptimizedNetwork *network)> IOptimizedNetworkPtr
Definition: INetwork.hpp:573
void RuntimeInvalidOverridePathTestImpl()
void CreateDynamicBackendsTestImpl()
void CreateDynamicBackendObjectInvalidInterface2TestImpl()
void RegisterMultipleDynamicBackendsTestImpl()
void CloseInvalidHandleTestImpl()
std::shared_ptr< ILayerSupport > ILayerSupportSharedPtr
void CreateDynamicBackendsMixedTypesTestImpl()
void OpenEmptyFileNameTestImpl()
std::string m_DynamicBackendsPath
Setting this value will override the paths set by the DYNAMIC_BACKEND_PATHS compiler directive Only a...
Definition: IRuntime.hpp:59
static BackendIdSet RegisterDynamicBackendsImpl(BackendRegistry &backendRegistry, const std::vector< DynamicBackendPtr > &dynamicBackends)
EmptyOptional is used to initialize the Optional class in case we want to have default value for an O...
Definition: Optional.hpp:32
static bool IsBackendCompatibleTest(const armnn::BackendVersion &backendApiVersion, const armnn::BackendVersion &backendVersion)
virtual const BackendIdSet & GetSupportedBackends() const override
Definition: DeviceSpec.hpp:25
void OpenCloseHandleTestImpl()
std::string GetDynamicBackendsBasePath()
virtual const IInputSlot & GetInputSlot(unsigned int index) const =0
Get a const input slot handle by slot index.
static bool IsBackendCompatibleImpl(const BackendVersion &backendApiVersion, const BackendVersion &backendVersion)
Protected methods for testing purposes.
void CreateDynamicBackendObjectInvalidInterface4TestImpl()
static std::vector< std::string > GetBackendPathsImpl(const std::string &backendPaths)
virtual const IOutputSlot & GetOutputSlot(unsigned int index) const =0
Get the const output slot handle by slot index.
Contains information about inputs and outputs to a layer.
void RegisterSingleDynamicBackendTestImpl()
void RuntimeEmptyTestImpl()
void RuntimeDuplicateDynamicBackendsTestImpl()
std::vector< ITensorHandle * > m_Inputs
std::unique_ptr< INetwork, void(*)(INetwork *network)> INetworkPtr
Definition: INetwork.hpp:101
std::unique_ptr< IBackendInternal > IBackendInternalUniquePtr
std::string GetBasePath(const std::string &basePath)
virtual int Connect(IInputSlot &destination)=0
armnn::Runtime::CreationOptions::ExternalProfilingOptions options
void RuntimeInvalidDynamicBackendsTestImpl()
void CreateValidDynamicBackendObjectTestImpl()
void OpenNotExistingFileTestImpl()
void CreateDynamicBackendObjectInvalidInterface7TestImpl()
void GetBackendPathsTestImpl()