blob: 55f90d48ebfea66a9c495c7266941466b4cd5ac0 [file] [log] [blame]
//
// Copyright © 2017 Arm Ltd. All rights reserved.
// SPDX-License-Identifier: MIT
//
#pragma once
#include <backendsCommon/DynamicBackend.hpp>
#include <backendsCommon/DynamicBackendUtils.hpp>
#include <string>
#include <memory>
#include <string>
#include <boost/test/unit_test.hpp>
#include <boost/filesystem.hpp>
#include <boost/dll.hpp>
static std::string g_TestBaseDir = "src/backends/backendsCommon/test/";
static std::string g_TestSharedObjectSubDir = "testSharedObject/";
static std::string g_TestDynamicBackendSubDir = "testDynamicBackend/";
static std::string g_TestSharedObjectFileName = "libTestSharedObject.so";
static std::string g_TestNoSharedObjectFileName = "libNoSharedObject.txt";
static std::string g_TestValidTestDynamicBackendFileName = "libValidTestDynamicBackend.so";
static std::string g_TestInvalidTestDynamicBackend1FileName = "libInvalidTestDynamicBackend1.so";
static std::string g_TestInvalidTestDynamicBackend2FileName = "libInvalidTestDynamicBackend2.so";
static std::string g_TestInvalidTestDynamicBackend3FileName = "libInvalidTestDynamicBackend3.so";
static std::string g_TestInvalidTestDynamicBackend4FileName = "libInvalidTestDynamicBackend4.so";
static std::string g_TestInvalidTestDynamicBackend5FileName = "libInvalidTestDynamicBackend5.so";
static std::string g_TestInvalidTestDynamicBackend6FileName = "libInvalidTestDynamicBackend6.so";
static std::string g_TestInvalidTestDynamicBackend7FileName = "libInvalidTestDynamicBackend7.so";
std::string GetTestDirectoryBasePath()
{
using namespace boost::filesystem;
path programLocation = boost::dll::program_location().parent_path();
path sharedObjectPath = programLocation.append(g_TestBaseDir);
BOOST_CHECK(exists(sharedObjectPath));
return sharedObjectPath.string();
}
std::string GetTestSubDirectory(const std::string& subdir)
{
using namespace boost::filesystem;
std::string testDynamicBackendsBaseDir = GetTestDirectoryBasePath();
path testDynamicBackendsBasePath(testDynamicBackendsBaseDir);
path testDynamicBackendsSubDir = testDynamicBackendsBasePath.append(subdir);
// Do not check that the sub-directory exists because for testing reasons we may use non-existing paths
return testDynamicBackendsSubDir.string();
}
std::string GetTestFilePath(const std::string& directory, const std::string& fileName)
{
using namespace boost::filesystem;
path directoryPath(directory);
path fileNamePath = directoryPath.append(fileName);
BOOST_CHECK(exists(fileNamePath));
return fileNamePath.string();
}
void OpenCloseHandleTestImpl()
{
using namespace armnn;
std::string testSubDirectory = GetTestSubDirectory(g_TestSharedObjectSubDir);
std::string sharedObjectFilePath = GetTestFilePath(testSubDirectory, g_TestSharedObjectFileName);
void* sharedObjectHandle = nullptr;
BOOST_CHECK_NO_THROW(sharedObjectHandle = DynamicBackendUtils::OpenHandle(sharedObjectFilePath));
BOOST_TEST((sharedObjectHandle != nullptr));
DynamicBackendUtils::CloseHandle(sharedObjectHandle);
}
void CloseInvalidHandleTestImpl()
{
using namespace armnn;
// This calls must silently handle invalid handles and complete successfully (no segfaults, etc.)
DynamicBackendUtils::CloseHandle(nullptr);
}
void OpenEmptyFileNameTestImpl()
{
using namespace armnn;
void* sharedObjectHandle = nullptr;
BOOST_CHECK_THROW(sharedObjectHandle = DynamicBackendUtils::OpenHandle(""), RuntimeException);
BOOST_TEST((sharedObjectHandle == nullptr));
}
void OpenNotExistingFileTestImpl()
{
using namespace armnn;
void* sharedObjectHandle = nullptr;
BOOST_CHECK_THROW(sharedObjectHandle = DynamicBackendUtils::OpenHandle("NotExistingFileName"), RuntimeException);
BOOST_TEST((sharedObjectHandle == nullptr));
}
void OpenNotSharedObjectTestImpl()
{
using namespace armnn;
std::string testSubDirectory = GetTestSubDirectory(g_TestSharedObjectSubDir);
std::string notSharedObjectFilePath = GetTestFilePath(testSubDirectory, g_TestNoSharedObjectFileName);
void* sharedObjectHandle = nullptr;
BOOST_CHECK_THROW(sharedObjectHandle = DynamicBackendUtils::OpenHandle(notSharedObjectFilePath), RuntimeException);
BOOST_TEST((sharedObjectHandle == nullptr));
}
void GetValidEntryPointTestImpl()
{
using namespace armnn;
std::string testSubDirectory = GetTestSubDirectory(g_TestSharedObjectSubDir);
std::string sharedObjectFilePath = GetTestFilePath(testSubDirectory, g_TestSharedObjectFileName);
void* sharedObjectHandle = nullptr;
BOOST_CHECK_NO_THROW(sharedObjectHandle = DynamicBackendUtils::OpenHandle(sharedObjectFilePath));
BOOST_TEST((sharedObjectHandle != nullptr));
using TestFunctionType = int(*)(int);
TestFunctionType testFunctionPointer = nullptr;
BOOST_CHECK_NO_THROW(testFunctionPointer = DynamicBackendUtils::GetEntryPoint<TestFunctionType>(sharedObjectHandle,
"TestFunction1"));
BOOST_TEST((testFunctionPointer != nullptr));
BOOST_TEST(testFunctionPointer(7) == 7);
DynamicBackendUtils::CloseHandle(sharedObjectHandle);
}
void GetNameMangledEntryPointTestImpl()
{
using namespace armnn;
std::string testSubDirectory = GetTestSubDirectory(g_TestSharedObjectSubDir);
std::string sharedObjectFilePath = GetTestFilePath(testSubDirectory, g_TestSharedObjectFileName);
void* sharedObjectHandle = nullptr;
BOOST_CHECK_NO_THROW(sharedObjectHandle = DynamicBackendUtils::OpenHandle(sharedObjectFilePath));
BOOST_TEST((sharedObjectHandle != nullptr));
using TestFunctionType = int(*)(int);
TestFunctionType testFunctionPointer = nullptr;
BOOST_CHECK_THROW(testFunctionPointer = DynamicBackendUtils::GetEntryPoint<TestFunctionType>(sharedObjectHandle,
"TestFunction2"),
RuntimeException);
BOOST_TEST((testFunctionPointer == nullptr));
DynamicBackendUtils::CloseHandle(sharedObjectHandle);
}
void GetNoExternEntryPointTestImpl()
{
using namespace armnn;
std::string testSubDirectory = GetTestSubDirectory(g_TestSharedObjectSubDir);
std::string sharedObjectFilePath = GetTestFilePath(testSubDirectory, g_TestSharedObjectFileName);
void* sharedObjectHandle = nullptr;
BOOST_CHECK_NO_THROW(sharedObjectHandle = DynamicBackendUtils::OpenHandle(sharedObjectFilePath));
BOOST_TEST((sharedObjectHandle != nullptr));
using TestFunctionType = int(*)(int);
TestFunctionType testFunctionPointer = nullptr;
BOOST_CHECK_THROW(testFunctionPointer = DynamicBackendUtils::GetEntryPoint<TestFunctionType>(sharedObjectHandle,
"TestFunction3"),
RuntimeException);
BOOST_TEST((testFunctionPointer == nullptr));
DynamicBackendUtils::CloseHandle(sharedObjectHandle);
}
void GetNotExistingEntryPointTestImpl()
{
using namespace armnn;
std::string testSubDirectory = GetTestSubDirectory(g_TestSharedObjectSubDir);
std::string sharedObjectFilePath = GetTestFilePath(testSubDirectory, g_TestSharedObjectFileName);
void* sharedObjectHandle = nullptr;
BOOST_CHECK_NO_THROW(sharedObjectHandle = DynamicBackendUtils::OpenHandle(sharedObjectFilePath));
BOOST_TEST((sharedObjectHandle != nullptr));
using TestFunctionType = int(*)(int);
TestFunctionType testFunctionPointer = nullptr;
BOOST_CHECK_THROW(testFunctionPointer = DynamicBackendUtils::GetEntryPoint<TestFunctionType>(sharedObjectHandle,
"TestFunction4"),
RuntimeException);
BOOST_TEST((testFunctionPointer == nullptr));
DynamicBackendUtils::CloseHandle(sharedObjectHandle);
}
void BackendVersioningTestImpl()
{
using namespace armnn;
class TestDynamicBackendUtils : public DynamicBackendUtils
{
public:
static bool IsBackendCompatibleTest(const BackendVersion& backendApiVersion,
const BackendVersion& backendVersion)
{
return IsBackendCompatibleImpl(backendApiVersion, backendVersion);
}
};
// The backend API version used for the tests
BackendVersion backendApiVersion{ 2, 4 };
// Same backend and backend API versions are compatible with the backend API
BackendVersion sameBackendVersion{ 2, 4 };
BOOST_TEST(sameBackendVersion == backendApiVersion);
BOOST_TEST(sameBackendVersion <= backendApiVersion);
BOOST_TEST(TestDynamicBackendUtils::IsBackendCompatibleTest(backendApiVersion, sameBackendVersion) == true);
// Backend versions that differ from the backend API version by major revision are not compatible
// with the backend API
BackendVersion laterMajorBackendVersion{ 3, 4 };
BOOST_TEST(!(laterMajorBackendVersion == backendApiVersion));
BOOST_TEST(!(laterMajorBackendVersion <= backendApiVersion));
BOOST_TEST(TestDynamicBackendUtils::IsBackendCompatibleTest(backendApiVersion, laterMajorBackendVersion) == false);
BackendVersion earlierMajorBackendVersion{ 1, 4 };
BOOST_TEST(!(earlierMajorBackendVersion == backendApiVersion));
BOOST_TEST(earlierMajorBackendVersion <= backendApiVersion);
BOOST_TEST(TestDynamicBackendUtils::IsBackendCompatibleTest(backendApiVersion,
earlierMajorBackendVersion) == false);
// Backend versions with the same major revision but later minor revision than
// the backend API version are not compatible with the backend API
BackendVersion laterMinorBackendVersion{ 2, 5 };
BOOST_TEST(!(laterMinorBackendVersion == backendApiVersion));
BOOST_TEST(!(laterMinorBackendVersion <= backendApiVersion));
BOOST_TEST(TestDynamicBackendUtils::IsBackendCompatibleTest(backendApiVersion, laterMinorBackendVersion) == false);
// Backend versions with the same major revision but earlier minor revision than
// the backend API version are compatible with the backend API
BackendVersion earlierMinorBackendVersion{ 2, 3 };
BOOST_TEST(!(earlierMinorBackendVersion == backendApiVersion));
BOOST_TEST(earlierMinorBackendVersion <= backendApiVersion);
BOOST_TEST(TestDynamicBackendUtils::IsBackendCompatibleTest(backendApiVersion, earlierMinorBackendVersion) == true);
}
void CreateValidDynamicBackendObjectTestImpl()
{
// Valid shared object handle
// Correct name mangling
// Correct interface
// Correct backend implementation
using namespace armnn;
std::string testSubDirectory = GetTestSubDirectory(g_TestDynamicBackendSubDir);
std::string sharedObjectFilePath = GetTestFilePath(testSubDirectory, g_TestValidTestDynamicBackendFileName);
void* sharedObjectHandle = nullptr;
BOOST_CHECK_NO_THROW(sharedObjectHandle = DynamicBackendUtils::OpenHandle(sharedObjectFilePath));
BOOST_TEST((sharedObjectHandle != nullptr));
std::unique_ptr<DynamicBackend> dynamicBackend;
BOOST_CHECK_NO_THROW(dynamicBackend.reset(new DynamicBackend(sharedObjectHandle)));
BOOST_TEST((dynamicBackend != nullptr));
BackendId dynamicBackendId;
BOOST_CHECK_NO_THROW(dynamicBackendId = dynamicBackend->GetBackendId());
BOOST_TEST((dynamicBackendId == "ValidTestDynamicBackend"));
BackendVersion dynamicBackendVersion;
BOOST_CHECK_NO_THROW(dynamicBackendVersion = dynamicBackend->GetBackendVersion());
BOOST_TEST((dynamicBackendVersion == BackendVersion({ 1, 0 })));
IBackendInternalUniquePtr dynamicBackendInstance;
BOOST_CHECK_NO_THROW(dynamicBackendInstance = dynamicBackend->GetBackend());
BOOST_TEST((dynamicBackendInstance != nullptr));
BOOST_TEST((dynamicBackendInstance->GetId() == "ValidTestDynamicBackend"));
}
void CreateDynamicBackendObjectInvalidHandleTestImpl()
{
// Invalid (null) shared object handle
using namespace armnn;
void* sharedObjectHandle = nullptr;
std::unique_ptr<DynamicBackend> dynamicBackend;
BOOST_CHECK_THROW(dynamicBackend.reset(new DynamicBackend(sharedObjectHandle)), InvalidArgumentException);
BOOST_TEST((dynamicBackend == nullptr));
}
void CreateDynamicBackendObjectInvalidInterface1TestImpl()
{
// Valid shared object handle
// Wrong (not C-style) name mangling
using namespace armnn;
std::string testSubDirectory = GetTestSubDirectory(g_TestDynamicBackendSubDir);
std::string sharedObjectFilePath = GetTestFilePath(testSubDirectory, g_TestInvalidTestDynamicBackend1FileName);
void* sharedObjectHandle = nullptr;
BOOST_CHECK_NO_THROW(sharedObjectHandle = DynamicBackendUtils::OpenHandle(sharedObjectFilePath));
BOOST_TEST((sharedObjectHandle != nullptr));
std::unique_ptr<DynamicBackend> dynamicBackend;
BOOST_CHECK_THROW(dynamicBackend.reset(new DynamicBackend(sharedObjectHandle)), RuntimeException);
BOOST_TEST((dynamicBackend == nullptr));
}
void CreateDynamicBackendObjectInvalidInterface2TestImpl()
{
// Valid shared object handle
// Correct name mangling
// Wrong interface (missing GetBackendId())
using namespace armnn;
std::string testSubDirectory = GetTestSubDirectory(g_TestDynamicBackendSubDir);
std::string sharedObjectFilePath = GetTestFilePath(testSubDirectory, g_TestInvalidTestDynamicBackend2FileName);
void* sharedObjectHandle = nullptr;
BOOST_CHECK_NO_THROW(sharedObjectHandle = DynamicBackendUtils::OpenHandle(sharedObjectFilePath));
BOOST_TEST((sharedObjectHandle != nullptr));
std::unique_ptr<DynamicBackend> dynamicBackend;
BOOST_CHECK_THROW(dynamicBackend.reset(new DynamicBackend(sharedObjectHandle)), RuntimeException);
BOOST_TEST((dynamicBackend == nullptr));
}
void CreateDynamicBackendObjectInvalidInterface3TestImpl()
{
// Valid shared object handle
// Correct name mangling
// Wrong interface (missing GetVersion())
using namespace armnn;
std::string testSubDirectory = GetTestSubDirectory(g_TestDynamicBackendSubDir);
std::string sharedObjectFilePath = GetTestFilePath(testSubDirectory, g_TestInvalidTestDynamicBackend3FileName);
void* sharedObjectHandle = nullptr;
BOOST_CHECK_NO_THROW(sharedObjectHandle = DynamicBackendUtils::OpenHandle(sharedObjectFilePath));
BOOST_TEST((sharedObjectHandle != nullptr));
std::unique_ptr<DynamicBackend> dynamicBackend;
BOOST_CHECK_THROW(dynamicBackend.reset(new DynamicBackend(sharedObjectHandle)), RuntimeException);
BOOST_TEST((dynamicBackend == nullptr));
}
void CreateDynamicBackendObjectInvalidInterface4TestImpl()
{
// Valid shared object handle
// Correct name mangling
// Wrong interface (missing BackendFactory())
using namespace armnn;
std::string testSubDirectory = GetTestSubDirectory(g_TestDynamicBackendSubDir);
std::string sharedObjectFilePath = GetTestFilePath(testSubDirectory, g_TestInvalidTestDynamicBackend4FileName);
void* sharedObjectHandle = nullptr;
BOOST_CHECK_NO_THROW(sharedObjectHandle = DynamicBackendUtils::OpenHandle(sharedObjectFilePath));
BOOST_TEST((sharedObjectHandle != nullptr));
std::unique_ptr<DynamicBackend> dynamicBackend;
BOOST_CHECK_THROW(dynamicBackend.reset(new DynamicBackend(sharedObjectHandle)), RuntimeException);
BOOST_TEST((dynamicBackend == nullptr));
}
void CreateDynamicBackendObjectInvalidInterface5TestImpl()
{
// Valid shared object handle
// Correct name mangling
// Correct interface
// Invalid (null) backend id returned by GetBackendId()
using namespace armnn;
std::string testSubDirectory = GetTestSubDirectory(g_TestDynamicBackendSubDir);
std::string sharedObjectFilePath = GetTestFilePath(testSubDirectory, g_TestInvalidTestDynamicBackend5FileName);
void* sharedObjectHandle = nullptr;
BOOST_CHECK_NO_THROW(sharedObjectHandle = DynamicBackendUtils::OpenHandle(sharedObjectFilePath));
BOOST_TEST((sharedObjectHandle != nullptr));
std::unique_ptr<DynamicBackend> dynamicBackend;
BOOST_CHECK_THROW(dynamicBackend.reset(new DynamicBackend(sharedObjectHandle)), RuntimeException);
BOOST_TEST((dynamicBackend == nullptr));
}
void CreateDynamicBackendObjectInvalidInterface6TestImpl()
{
// Valid shared object handle
// Correct name mangling
// Correct interface
// Invalid (null) backend instance returned by BackendFactory()
using namespace armnn;
std::string testSubDirectory = GetTestSubDirectory(g_TestDynamicBackendSubDir);
std::string sharedObjectFilePath = GetTestFilePath(testSubDirectory, g_TestInvalidTestDynamicBackend6FileName);
void* sharedObjectHandle = nullptr;
BOOST_CHECK_NO_THROW(sharedObjectHandle = DynamicBackendUtils::OpenHandle(sharedObjectFilePath));
BOOST_TEST((sharedObjectHandle != nullptr));
std::unique_ptr<DynamicBackend> dynamicBackend;
BOOST_CHECK_NO_THROW(dynamicBackend.reset(new DynamicBackend(sharedObjectHandle)));
BOOST_TEST((dynamicBackend != nullptr));
BackendId dynamicBackendId;
BOOST_CHECK_NO_THROW(dynamicBackendId = dynamicBackend->GetBackendId());
BOOST_TEST((dynamicBackendId == "InvalidTestDynamicBackend"));
BackendVersion dynamicBackendVersion;
BOOST_CHECK_NO_THROW(dynamicBackendVersion = dynamicBackend->GetBackendVersion());
BOOST_TEST((dynamicBackendVersion == BackendVersion({ 1, 0 })));
IBackendInternalUniquePtr dynamicBackendInstance;
BOOST_CHECK_THROW(dynamicBackendInstance = dynamicBackend->GetBackend(), RuntimeException);
BOOST_TEST((dynamicBackendInstance == nullptr));
}
void CreateDynamicBackendObjectInvalidInterface7TestImpl()
{
// Valid shared object handle
// Correct name mangling
// Correct interface
// Invalid (incompatible backend API version) backend instance returned by BackendFactory()
using namespace armnn;
std::string testSubDirectory = GetTestSubDirectory(g_TestDynamicBackendSubDir);
std::string sharedObjectFilePath = GetTestFilePath(testSubDirectory, g_TestInvalidTestDynamicBackend7FileName);
void* sharedObjectHandle = nullptr;
BOOST_CHECK_NO_THROW(sharedObjectHandle = DynamicBackendUtils::OpenHandle(sharedObjectFilePath));
BOOST_TEST((sharedObjectHandle != nullptr));
std::unique_ptr<DynamicBackend> dynamicBackend;
BOOST_CHECK_THROW(dynamicBackend.reset(new DynamicBackend(sharedObjectHandle)), RuntimeException);
BOOST_TEST((dynamicBackend == nullptr));
}