Refactor and test initialization of FCL in ocloc

This change:
- extracts FCL to a separate class called OclocFclFacade
- tests the new class
- tests its usage in offline compiler

Related-To: NEO-6834
Signed-off-by: Patryk Wrobel <patryk.wrobel@intel.com>
This commit is contained in:
Patryk Wrobel
2022-04-21 16:06:40 +00:00
committed by Compute-Runtime-Automation
parent c637903132
commit 35a04e5915
11 changed files with 550 additions and 59 deletions

View File

@ -20,6 +20,7 @@ set(IGDRCL_SRCS_offline_compiler_mock
${CMAKE_CURRENT_SOURCE_DIR}/decoder/mock/mock_iga_wrapper.h
${CMAKE_CURRENT_SOURCE_DIR}/mock/mock_argument_helper.h
${CMAKE_CURRENT_SOURCE_DIR}/mock/mock_multi_command.h
${CMAKE_CURRENT_SOURCE_DIR}/mock/mock_ocloc_fcl_facade.h
${CMAKE_CURRENT_SOURCE_DIR}/mock/mock_ocloc_igc_facade.h
${CMAKE_CURRENT_SOURCE_DIR}/mock/mock_offline_compiler.h
${CMAKE_CURRENT_SOURCE_DIR}/mock/mock_offline_linker.h
@ -62,6 +63,8 @@ set(IGDRCL_SRCS_offline_compiler_tests
${CMAKE_CURRENT_SOURCE_DIR}/ocloc_api_tests.cpp
${CMAKE_CURRENT_SOURCE_DIR}/ocloc_fatbinary_tests.cpp
${CMAKE_CURRENT_SOURCE_DIR}/ocloc_fatbinary_tests.h
${CMAKE_CURRENT_SOURCE_DIR}/ocloc_fcl_facade_tests.cpp
${CMAKE_CURRENT_SOURCE_DIR}/ocloc_fcl_facade_tests.h
${CMAKE_CURRENT_SOURCE_DIR}/ocloc_igc_facade_tests.cpp
${CMAKE_CURRENT_SOURCE_DIR}/ocloc_igc_facade_tests.h
${CMAKE_CURRENT_SOURCE_DIR}/ocloc_product_config_tests.cpp

View File

@ -0,0 +1,104 @@
/*
* Copyright (C) 2022 Intel Corporation
*
* SPDX-License-Identifier: MIT
*
*/
#pragma once
#include "shared/offline_compiler/source/ocloc_fcl_facade.h"
#include <optional>
#include <string>
namespace NEO {
class MockOclocFclFacade : public OclocFclFacade {
public:
using OclocFclFacade::fclDeviceCtx;
bool shouldFailLoadingOfFclLib{false};
bool shouldFailLoadingOfFclCreateMainFunction{false};
bool shouldFailCreationOfFclMain{false};
bool shouldFailCreationOfFclDeviceContext{false};
bool shouldReturnInvalidFclPlatformHandle{false};
std::optional<bool> isFclInterfaceCompatibleReturnValue{};
std::optional<std::string> getIncompatibleInterfaceReturnValue{};
std::optional<bool> shouldPopulateFclInterfaceReturnValue{};
int populateFclInterfaceCalledCount{0};
MockOclocFclFacade(OclocArgHelper *argHelper) : OclocFclFacade{argHelper} {}
~MockOclocFclFacade() override = default;
std::unique_ptr<OsLibrary> loadFclLibrary() const override {
if (shouldFailLoadingOfFclLib) {
return nullptr;
} else {
return OclocFclFacade::loadFclLibrary();
}
}
CIF::CreateCIFMainFunc_t loadCreateFclMainFunction() const override {
if (shouldFailLoadingOfFclCreateMainFunction) {
return nullptr;
} else {
return OclocFclFacade::loadCreateFclMainFunction();
}
}
CIF::RAII::UPtr_t<CIF::CIFMain> createFclMain(CIF::CreateCIFMainFunc_t createMainFunction) const override {
if (shouldFailCreationOfFclMain) {
return nullptr;
} else {
return OclocFclFacade::createFclMain(createMainFunction);
}
}
bool isFclInterfaceCompatible() const override {
if (isFclInterfaceCompatibleReturnValue.has_value()) {
return *isFclInterfaceCompatibleReturnValue;
} else {
return OclocFclFacade::isFclInterfaceCompatible();
}
}
std::string getIncompatibleInterface() const override {
if (getIncompatibleInterfaceReturnValue.has_value()) {
return *getIncompatibleInterfaceReturnValue;
} else {
return OclocFclFacade::getIncompatibleInterface();
}
}
CIF::RAII::UPtr_t<IGC::FclOclDeviceCtxTagOCL> createFclDeviceContext() const override {
if (shouldFailCreationOfFclDeviceContext) {
return nullptr;
} else {
return OclocFclFacade::createFclDeviceContext();
}
}
bool shouldPopulateFclInterface() const override {
if (shouldPopulateFclInterfaceReturnValue.has_value()) {
return *shouldPopulateFclInterfaceReturnValue;
} else {
return OclocFclFacade::shouldPopulateFclInterface();
}
}
CIF::RAII::UPtr_t<IGC::PlatformTagOCL> getPlatformHandle() const override {
if (shouldReturnInvalidFclPlatformHandle) {
return nullptr;
} else {
return OclocFclFacade::getPlatformHandle();
}
}
void populateFclInterface(IGC::PlatformTagOCL &handle, const PLATFORM &platform) override {
++populateFclInterfaceCalledCount;
OclocFclFacade::populateFclInterface(handle, platform);
}
};
} // namespace NEO

View File

@ -10,6 +10,7 @@
#include "shared/offline_compiler/source/offline_compiler.h"
#include "opencl/test/unit_test/offline_compiler/mock/mock_argument_helper.h"
#include "opencl/test/unit_test/offline_compiler/mock/mock_ocloc_fcl_facade.h"
#include "opencl/test/unit_test/offline_compiler/mock/mock_ocloc_igc_facade.h"
#include <optional>
@ -25,7 +26,7 @@ class MockOfflineCompiler : public OfflineCompiler {
using OfflineCompiler::deviceName;
using OfflineCompiler::elfBinary;
using OfflineCompiler::excludeIr;
using OfflineCompiler::fclDeviceCtx;
using OfflineCompiler::fclFacade;
using OfflineCompiler::forceStatelessToStatefulOptimization;
using OfflineCompiler::genBinary;
using OfflineCompiler::genBinarySize;
@ -62,6 +63,10 @@ class MockOfflineCompiler : public OfflineCompiler {
uniqueHelper->setAllCallBase(true);
argHelper = uniqueHelper.get();
auto uniqueFclFacadeMock = std::make_unique<MockOclocFclFacade>(argHelper);
mockFclFacade = uniqueFclFacadeMock.get();
fclFacade = std::move(uniqueFclFacadeMock);
auto uniqueIgcFacadeMock = std::make_unique<MockOclocIgcFacade>(argHelper);
mockIgcFacade = uniqueIgcFacadeMock.get();
igcFacade = std::move(uniqueIgcFacadeMock);
@ -125,6 +130,7 @@ class MockOfflineCompiler : public OfflineCompiler {
uint32_t writeOutAllFilesCalled = 0u;
std::unique_ptr<MockOclocArgHelper> uniqueHelper;
MockOclocIgcFacade *mockIgcFacade = nullptr;
MockOclocFclFacade *mockFclFacade = nullptr;
int buildCalledCount{0};
std::optional<int> buildReturnValue{};
bool interceptCreatedDirs{false};

View File

@ -0,0 +1,177 @@
/*
* Copyright (C) 2022 Intel Corporation
*
* SPDX-License-Identifier: MIT
*
*/
#include "ocloc_fcl_facade_tests.h"
#include "shared/offline_compiler/source/ocloc_error_code.h"
#include "shared/source/debug_settings/debug_settings_manager.h"
#include "shared/source/os_interface/os_inc_base.h"
#include "shared/test/common/helpers/debug_manager_state_restore.h"
#include "mock/mock_ocloc_fcl_facade.h"
#include <string>
namespace NEO {
TEST_F(OclocFclFacadeTest, GivenMissingFclLibraryWhenPreparingFclThenFailureIsReported) {
MockOclocFclFacade mockFclFacade{&mockArgHelper};
mockFclFacade.shouldFailLoadingOfFclLib = true;
::testing::internal::CaptureStdout();
const auto fclPreparationResult{mockFclFacade.initialize(hwInfo)};
const auto output{::testing::internal::GetCapturedStdout()};
EXPECT_EQ(OclocErrorCode::OUT_OF_HOST_MEMORY, fclPreparationResult);
EXPECT_FALSE(mockFclFacade.isInitialized());
std::stringstream expectedErrorMessage;
expectedErrorMessage << "Error! Loading of FCL library has failed! Filename: " << Os::frontEndDllName << "\n";
EXPECT_EQ(expectedErrorMessage.str(), output);
}
TEST_F(OclocFclFacadeTest, GivenFailingLoadingOfFclSymbolsWhenPreparingFclThenFailureIsReported) {
MockOclocFclFacade mockFclFacade{&mockArgHelper};
mockFclFacade.shouldFailLoadingOfFclCreateMainFunction = true;
::testing::internal::CaptureStdout();
const auto fclPreparationResult{mockFclFacade.initialize(hwInfo)};
const auto output{::testing::internal::GetCapturedStdout()};
EXPECT_EQ(OclocErrorCode::OUT_OF_HOST_MEMORY, fclPreparationResult);
EXPECT_FALSE(mockFclFacade.isInitialized());
const std::string expectedErrorMessage{"Error! Cannot load required functions from FCL library.\n"};
EXPECT_EQ(expectedErrorMessage, output);
}
TEST_F(OclocFclFacadeTest, GivenFailingCreationOfFclMainWhenPreparingFclThenFailureIsReported) {
MockOclocFclFacade mockFclFacade{&mockArgHelper};
mockFclFacade.shouldFailCreationOfFclMain = true;
::testing::internal::CaptureStdout();
const auto fclPreparationResult{mockFclFacade.initialize(hwInfo)};
const auto output{::testing::internal::GetCapturedStdout()};
EXPECT_EQ(OclocErrorCode::OUT_OF_HOST_MEMORY, fclPreparationResult);
EXPECT_FALSE(mockFclFacade.isInitialized());
const std::string expectedErrorMessage{"Error! Cannot create FCL main component!\n"};
EXPECT_EQ(expectedErrorMessage, output);
}
TEST_F(OclocFclFacadeTest, GivenIncompatibleFclInterfacesWhenPreparingFclThenFailureIsReported) {
DebugManagerStateRestore stateRestore;
DebugManager.flags.EnableDebugBreak.set(false);
MockOclocFclFacade mockFclFacade{&mockArgHelper};
mockFclFacade.isFclInterfaceCompatibleReturnValue = false;
mockFclFacade.getIncompatibleInterfaceReturnValue = "SomeImportantInterface";
::testing::internal::CaptureStdout();
const auto fclPreparationResult{mockFclFacade.initialize(hwInfo)};
const auto output{::testing::internal::GetCapturedStdout()};
EXPECT_EQ(OclocErrorCode::OUT_OF_HOST_MEMORY, fclPreparationResult);
EXPECT_FALSE(mockFclFacade.isInitialized());
const std::string expectedErrorMessage{"Error! Incompatible interface in FCL: SomeImportantInterface\n"};
EXPECT_EQ(expectedErrorMessage, output);
}
TEST_F(OclocFclFacadeTest, GivenFailingCreationOfFclDeviceContextWhenPreparingFclThenFailureIsReported) {
MockOclocFclFacade mockFclFacade{&mockArgHelper};
mockFclFacade.shouldFailCreationOfFclDeviceContext = true;
::testing::internal::CaptureStdout();
const auto fclPreparationResult{mockFclFacade.initialize(hwInfo)};
const auto output{::testing::internal::GetCapturedStdout()};
EXPECT_EQ(OclocErrorCode::OUT_OF_HOST_MEMORY, fclPreparationResult);
EXPECT_FALSE(mockFclFacade.isInitialized());
const std::string expectedErrorMessage{"Error! Cannot create FCL device context!\n"};
EXPECT_EQ(expectedErrorMessage, output);
}
TEST_F(OclocFclFacadeTest, GivenNoneErrorsSetAndNotPopulateFclInterfaceWhenPreparingFclThenSuccessIsReported) {
MockOclocFclFacade mockFclFacade{&mockArgHelper};
mockFclFacade.shouldPopulateFclInterfaceReturnValue = false;
::testing::internal::CaptureStdout();
const auto fclPreparationResult{mockFclFacade.initialize(hwInfo)};
const auto output{::testing::internal::GetCapturedStdout()};
EXPECT_EQ(OclocErrorCode::SUCCESS, fclPreparationResult);
EXPECT_TRUE(output.empty()) << output;
EXPECT_TRUE(mockFclFacade.isInitialized());
EXPECT_EQ(0, mockFclFacade.populateFclInterfaceCalledCount);
}
TEST_F(OclocFclFacadeTest, GivenPopulateFclInterfaceAndInvalidFclDeviceContextWhenPreparingFclThenFailureIsReported) {
MockOclocFclFacade mockFclFacade{&mockArgHelper};
mockFclFacade.shouldPopulateFclInterfaceReturnValue = true;
mockFclFacade.shouldReturnInvalidFclPlatformHandle = true;
::testing::internal::CaptureStdout();
const auto fclPreparationResult{mockFclFacade.initialize(hwInfo)};
const auto output{::testing::internal::GetCapturedStdout()};
EXPECT_EQ(OclocErrorCode::OUT_OF_HOST_MEMORY, fclPreparationResult);
EXPECT_FALSE(mockFclFacade.isInitialized());
const std::string expectedErrorMessage{"Error! FCL device context has not been properly created!\n"};
EXPECT_EQ(expectedErrorMessage, output);
EXPECT_EQ(0, mockFclFacade.populateFclInterfaceCalledCount);
}
TEST_F(OclocFclFacadeTest, GivenPopulateFclInterfaceWhenPreparingFclThenSuccessIsReported) {
MockOclocFclFacade mockFclFacade{&mockArgHelper};
mockFclFacade.shouldPopulateFclInterfaceReturnValue = true;
::testing::internal::CaptureStdout();
const auto fclPreparationResult{mockFclFacade.initialize(hwInfo)};
const auto output{::testing::internal::GetCapturedStdout()};
EXPECT_EQ(OclocErrorCode::SUCCESS, fclPreparationResult);
EXPECT_TRUE(output.empty()) << output;
EXPECT_TRUE(mockFclFacade.isInitialized());
EXPECT_EQ(1, mockFclFacade.populateFclInterfaceCalledCount);
}
TEST_F(OclocFclFacadeTest, GivenNoneErrorsSetWhenPreparingFclThenSuccessIsReported) {
MockOclocFclFacade mockFclFacade{&mockArgHelper};
::testing::internal::CaptureStdout();
const auto fclPreparationResult{mockFclFacade.initialize(hwInfo)};
const auto output{::testing::internal::GetCapturedStdout()};
EXPECT_EQ(OclocErrorCode::SUCCESS, fclPreparationResult);
EXPECT_TRUE(output.empty()) << output;
EXPECT_TRUE(mockFclFacade.isInitialized());
const auto expectedPopulateCalledCount = mockFclFacade.shouldPopulateFclInterface() ? 1 : 0;
EXPECT_EQ(expectedPopulateCalledCount, mockFclFacade.populateFclInterfaceCalledCount);
}
TEST_F(OclocFclFacadeTest, GivenInitializedFclWhenGettingIncompatibleInterfaceThenEmptyStringIsReturned) {
MockOclocFclFacade mockFclFacade{&mockArgHelper};
::testing::internal::CaptureStdout();
const auto fclPreparationResult{mockFclFacade.initialize(hwInfo)};
const auto output{::testing::internal::GetCapturedStdout()};
ASSERT_EQ(OclocErrorCode::SUCCESS, fclPreparationResult);
const auto incompatibleInterface = mockFclFacade.getIncompatibleInterface();
EXPECT_TRUE(incompatibleInterface.empty()) << incompatibleInterface;
}
} // namespace NEO

View File

@ -0,0 +1,24 @@
/*
* Copyright (C) 2022 Intel Corporation
*
* SPDX-License-Identifier: MIT
*
*/
#pragma once
#include "shared/source/helpers/hw_info.h"
#include "gtest/gtest.h"
#include "mock/mock_argument_helper.h"
namespace NEO {
class OclocFclFacadeTest : public ::testing::Test {
protected:
MockOclocArgHelper::FilesMap mockArgHelperFilesMap{};
MockOclocArgHelper mockArgHelper{mockArgHelperFilesMap};
HardwareInfo hwInfo{};
};
} // namespace NEO

View File

@ -956,6 +956,29 @@ TEST_F(OfflineCompilerTests, givenExcludeIrFromZebinInternalOptionWhenInitIsPerf
EXPECT_TRUE(mockOfflineCompiler.excludeIr);
}
TEST_F(OfflineCompilerTests, givenValidArgumentsAndFclInitFailureWhenInitIsPerformedThenFailureIsPropagatedAndErrorIsPrinted) {
std::vector<std::string> argv = {
"ocloc",
"-file",
"test_files/copybuffer.cl",
"-device",
gEnvironment->devicePrefix.c_str()};
MockOfflineCompiler mockOfflineCompiler{};
mockOfflineCompiler.mockFclFacade->shouldFailLoadingOfFclLib = true;
testing::internal::CaptureStdout();
const auto initResult = mockOfflineCompiler.initialize(argv.size(), argv);
const auto output = testing::internal::GetCapturedStdout();
std::stringstream expectedErrorMessage;
expectedErrorMessage << "Error! Loading of FCL library has failed! Filename: " << Os::frontEndDllName << "\n"
<< "Error! FCL initialization failure. Error code = -6\n";
EXPECT_EQ(OclocErrorCode::OUT_OF_HOST_MEMORY, initResult);
EXPECT_EQ(expectedErrorMessage.str(), output);
}
TEST_F(OfflineCompilerTests, givenValidArgumentsAndIgcInitFailureWhenInitIsPerformedThenFailureIsPropagatedAndErrorIsPrinted) {
std::vector<std::string> argv = {
"ocloc",
@ -1355,7 +1378,7 @@ TEST_F(OfflineCompilerTests, WhenFclNotNeededThenDontLoadIt) {
MockOfflineCompiler offlineCompiler;
auto ret = offlineCompiler.initialize(argv.size(), argv);
EXPECT_EQ(0, ret);
EXPECT_EQ(nullptr, offlineCompiler.fclDeviceCtx);
EXPECT_FALSE(offlineCompiler.fclFacade->isInitialized());
EXPECT_TRUE(offlineCompiler.igcFacade->isInitialized());
}
@ -2043,7 +2066,7 @@ TEST(OfflineCompilerTest, givenUseLlvmBcFlagWhenBuildingIrBinaryThenProperTransl
ASSERT_EQ(CL_SUCCESS, initResult);
auto mockFclOclDeviceCtx = new NEO::MockFclOclDeviceCtx();
mockOfflineCompiler.fclDeviceCtx = CIF::RAII::Pack<IGC::FclOclDeviceCtxTagOCL>(mockFclOclDeviceCtx);
mockOfflineCompiler.mockFclFacade->fclDeviceCtx = CIF::RAII::Pack<IGC::FclOclDeviceCtxTagOCL>(mockFclOclDeviceCtx);
mockOfflineCompiler.useLlvmBc = true;
const auto buildResult = mockOfflineCompiler.buildIrBinary();