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