Allow ocloc to link files

Added 'link' option to ocloc CLI, which allows linking of
several IR files to single output file. Supported formats
of output file are ELF and LLVM BC.

Related-To: NEO-6163
Signed-off-by: Patryk Wrobel <patryk.wrobel@intel.com>
This commit is contained in:
Patryk Wrobel
2022-01-12 15:27:20 +00:00
committed by Compute-Runtime-Automation
parent 504b49effa
commit 53482e6821
24 changed files with 1747 additions and 93 deletions

View File

@ -1,5 +1,5 @@
#
# Copyright (C) 2018-2021 Intel Corporation
# Copyright (C) 2018-2022 Intel Corporation
#
# SPDX-License-Identifier: MIT
#
@ -10,6 +10,7 @@ set(IGDRCL_SRCS_cloc
${OCLOC_DIRECTORY}/source/decoder/binary_decoder.cpp
${OCLOC_DIRECTORY}/source/decoder/binary_encoder.cpp
${OCLOC_DIRECTORY}/source/offline_compiler.cpp
${OCLOC_DIRECTORY}/source/offline_linker.cpp
${OCLOC_DIRECTORY}/source/ocloc_fatbinary.cpp
)
@ -19,12 +20,13 @@ 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_offline_compiler.h
${CMAKE_CURRENT_SOURCE_DIR}/mock/mock_offline_linker.h
${CMAKE_CURRENT_SOURCE_DIR}/mock/mock_sip_ocloc_tests.cpp
)
set(CLOC_LIB_SRCS_UTILITIES
${OCLOC_DIRECTORY}/source/utilities/safety_caller.h
${OCLOC_DIRECTORY}/source/utilities//get_current_dir.h
${OCLOC_DIRECTORY}/source/utilities/get_current_dir.h
)
if(WIN32)
@ -58,6 +60,8 @@ set(IGDRCL_SRCS_offline_compiler_tests
${CMAKE_CURRENT_SOURCE_DIR}/ocloc_validator_tests.cpp
${CMAKE_CURRENT_SOURCE_DIR}/offline_compiler_tests.cpp
${CMAKE_CURRENT_SOURCE_DIR}/offline_compiler_tests.h
${CMAKE_CURRENT_SOURCE_DIR}/offline_linker_tests.cpp
${CMAKE_CURRENT_SOURCE_DIR}/offline_linker_tests.h
${NEO_SHARED_DIRECTORY}/helpers/abort.cpp
${NEO_SHARED_DIRECTORY}/helpers/file_io.cpp
${NEO_SHARED_DIRECTORY}/memory_manager/deferred_deleter.cpp

View File

@ -1,12 +1,14 @@
/*
* Copyright (C) 2020-2021 Intel Corporation
* Copyright (C) 2020-2022 Intel Corporation
*
* SPDX-License-Identifier: MIT
*
*/
#include "shared/offline_compiler/source/ocloc_arg_helper.h"
#include "shared/source/helpers/string.h"
#include <algorithm>
#include <map>
#include <string>
@ -17,6 +19,10 @@ class MockOclocArgHelper : public OclocArgHelper {
using FilesMap = std::map<FileName, FileData>;
using OclocArgHelper::deviceProductTable;
FilesMap &filesMap;
bool interceptOutput{false};
bool shouldReturnReadingError{false};
FilesMap interceptedFiles;
MockOclocArgHelper(FilesMap &filesMap) : OclocArgHelper(
0, nullptr, nullptr, nullptr, 0, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr),
filesMap(filesMap){};
@ -30,4 +36,33 @@ class MockOclocArgHelper : public OclocArgHelper {
auto file = filesMap[filename];
return std::vector<char>(file.begin(), file.end());
}
std::unique_ptr<char[]> loadDataFromFile(const std::string &filename, size_t &retSize) override {
if (shouldReturnReadingError) {
return nullptr;
}
if (!fileExists(filename)) {
return OclocArgHelper::loadDataFromFile(filename, retSize);
}
const auto &file = filesMap[filename];
std::unique_ptr<char[]> result{new char[file.size()]};
std::copy(file.begin(), file.end(), result.get());
retSize = file.size();
return result;
}
void saveOutput(const std::string &filename, const void *pData, const size_t &dataSize) override {
if (interceptOutput) {
auto &fileContent = interceptedFiles[filename];
fileContent.resize(dataSize, '\0');
memcpy_s(fileContent.data(), fileContent.size(), pData, dataSize);
} else {
OclocArgHelper::saveOutput(filename, pData, dataSize);
}
}
};

View File

@ -0,0 +1,103 @@
/*
* Copyright (C) 2022 Intel Corporation
*
* SPDX-License-Identifier: MIT
*
*/
#pragma once
#include "shared/offline_compiler/source/offline_linker.h"
namespace NEO {
class MockOfflineLinker : public OfflineLinker {
public:
using OfflineLinker::InputFileContent;
using OfflineLinker::OperationMode;
using OfflineLinker::initHardwareInfo;
using OfflineLinker::initialize;
using OfflineLinker::loadInputFilesContent;
using OfflineLinker::parseCommand;
using OfflineLinker::prepareIgc;
using OfflineLinker::tryToStoreBuildLog;
using OfflineLinker::verifyLinkerCommand;
using OfflineLinker::hwInfo;
using OfflineLinker::inputFilenames;
using OfflineLinker::inputFilesContent;
using OfflineLinker::internalOptions;
using OfflineLinker::operationMode;
using OfflineLinker::options;
using OfflineLinker::outputFilename;
using OfflineLinker::outputFormat;
bool shouldReturnEmptyHardwareInfoTable{false};
bool shouldFailLoadingOfIgcLib{false};
bool shouldFailLoadingOfIgcCreateMainFunction{false};
bool shouldFailCreationOfIgcMain{false};
bool shouldFailCreationOfIgcDeviceContext{false};
bool shouldReturnInvalidIgcPlatformHandle{false};
bool shouldReturnInvalidGTSystemInfoHandle{false};
MockOfflineLinker(OclocArgHelper *argHelper) : OfflineLinker{argHelper} {}
ArrayRef<const HardwareInfo *> getHardwareInfoTable() const override {
if (shouldReturnEmptyHardwareInfoTable) {
return {};
} else {
return OfflineLinker::getHardwareInfoTable();
}
}
std::unique_ptr<OsLibrary> loadIgcLibrary() const override {
if (shouldFailLoadingOfIgcLib) {
return nullptr;
} else {
return OfflineLinker::loadIgcLibrary();
}
}
CIF::CreateCIFMainFunc_t loadCreateIgcMainFunction() const override {
if (shouldFailLoadingOfIgcCreateMainFunction) {
return nullptr;
} else {
return OfflineLinker::loadCreateIgcMainFunction();
}
}
CIF::RAII::UPtr_t<CIF::CIFMain> createIgcMain(CIF::CreateCIFMainFunc_t createMainFunction) const override {
if (shouldFailCreationOfIgcMain) {
return nullptr;
} else {
return OfflineLinker::createIgcMain(createMainFunction);
}
}
CIF::RAII::UPtr_t<IGC::IgcOclDeviceCtxTagOCL> createIgcDeviceContext() const override {
if (shouldFailCreationOfIgcDeviceContext) {
return nullptr;
} else {
return OfflineLinker::createIgcDeviceContext();
}
}
CIF::RAII::UPtr_t<IGC::PlatformTagOCL> getIgcPlatformHandle() const override {
if (shouldReturnInvalidIgcPlatformHandle) {
return nullptr;
} else {
return OfflineLinker::getIgcPlatformHandle();
}
}
CIF::RAII::UPtr_t<IGC::GTSystemInfoTagOCL> getGTSystemInfoHandle() const override {
if (shouldReturnInvalidGTSystemInfoHandle) {
return nullptr;
} else {
return OfflineLinker::getGTSystemInfoHandle();
}
}
};
} // namespace NEO

View File

@ -1,11 +1,12 @@
/*
* Copyright (C) 2020-2021 Intel Corporation
* Copyright (C) 2020-2022 Intel Corporation
*
* SPDX-License-Identifier: MIT
*
*/
#include "shared/offline_compiler/source/ocloc_api.h"
#include "shared/offline_compiler/source/ocloc_error_code.h"
#include "shared/offline_compiler/source/queries.h"
#include "shared/offline_compiler/source/utilities/get_git_version_info.h"
#include "shared/source/device_binary_format/elf/elf_decoder.h"
@ -43,7 +44,7 @@ TEST(OclocApiTests, WhenGoodArgsAreGivenThenSuccessIsReturned) {
nullptr, nullptr, nullptr, nullptr);
std::string output = testing::internal::GetCapturedStdout();
EXPECT_EQ(retVal, NEO::OfflineCompiler::ErrorCode::SUCCESS);
EXPECT_EQ(retVal, NEO::OclocErrorCode::SUCCESS);
EXPECT_EQ(std::string::npos, output.find("Command was: ocloc -file test_files/copybuffer.cl -device "s + argv[4]));
}
@ -61,7 +62,7 @@ TEST(OclocApiTests, GivenNeoRevisionQueryWhenQueryingThenNeoRevisionIsReturned)
0, nullptr, nullptr, nullptr,
0, nullptr, nullptr, nullptr,
&numOutputs, &dataOutputs, &lenOutputs, &nameOutputs);
EXPECT_EQ(retVal, NEO::OfflineCompiler::SUCCESS);
EXPECT_EQ(retVal, NEO::OclocErrorCode::SUCCESS);
EXPECT_EQ(numOutputs, 2u);
int queryOutputIndex = -1;
@ -92,7 +93,7 @@ TEST(OclocApiTests, GivenOclDriverVersionQueryWhenQueryingThenNeoRevisionIsRetur
0, nullptr, nullptr, nullptr,
0, nullptr, nullptr, nullptr,
&numOutputs, &dataOutputs, &lenOutputs, &nameOutputs);
EXPECT_EQ(retVal, NEO::OfflineCompiler::SUCCESS);
EXPECT_EQ(retVal, NEO::OclocErrorCode::SUCCESS);
EXPECT_EQ(numOutputs, 2u);
int queryOutputIndex = -1;
@ -121,7 +122,7 @@ TEST(OclocApiTests, GivenNoQueryWhenQueryingThenErrorIsReturned) {
nullptr, nullptr, nullptr, nullptr);
std::string output = testing::internal::GetCapturedStdout();
EXPECT_EQ(retVal, NEO::OfflineCompiler::INVALID_COMMAND_LINE);
EXPECT_EQ(retVal, NEO::OclocErrorCode::INVALID_COMMAND_LINE);
EXPECT_STREQ("Error: Invalid command line. Expected ocloc query <argument>", output.c_str());
}
@ -138,7 +139,7 @@ TEST(OclocApiTests, GivenInvalidQueryWhenQueryingThenErrorIsReturned) {
nullptr, nullptr, nullptr, nullptr);
std::string output = testing::internal::GetCapturedStdout();
EXPECT_EQ(retVal, NEO::OfflineCompiler::INVALID_COMMAND_LINE);
EXPECT_EQ(retVal, NEO::OclocErrorCode::INVALID_COMMAND_LINE);
EXPECT_STREQ("Error: Invalid command line. Uknown argument unknown_query.", output.c_str());
}
@ -158,7 +159,7 @@ TEST(OclocApiTests, WhenGoodFamilyNameIsProvidedThenSuccessIsReturned) {
nullptr, nullptr, nullptr, nullptr);
std::string output = testing::internal::GetCapturedStdout();
EXPECT_EQ(retVal, NEO::OfflineCompiler::ErrorCode::SUCCESS);
EXPECT_EQ(retVal, NEO::OclocErrorCode::SUCCESS);
EXPECT_EQ(std::string::npos, output.find("Command was: ocloc -file test_files/copybuffer.cl -device "s + argv[4]));
}
@ -179,7 +180,7 @@ TEST(OclocApiTests, WhenArgsWithMissingFileAreGivenThenErrorMessageIsProduced) {
nullptr, nullptr, nullptr, nullptr);
std::string output = testing::internal::GetCapturedStdout();
EXPECT_EQ(retVal, NEO::OfflineCompiler::ErrorCode::INVALID_FILE);
EXPECT_EQ(retVal, NEO::OclocErrorCode::INVALID_FILE);
EXPECT_NE(std::string::npos, output.find("Command was: ocloc -q -file test_files/IDoNotExist.cl -device "s + argv[5]));
}
@ -200,7 +201,7 @@ TEST(OclocApiTests, givenInputOptionsAndInternalOptionsWhenCmdlineIsPrintedThenB
0, nullptr, nullptr, nullptr,
nullptr, nullptr, nullptr, nullptr);
std::string output = testing::internal::GetCapturedStdout();
EXPECT_NE(retVal, NEO::OfflineCompiler::ErrorCode::SUCCESS);
EXPECT_NE(retVal, NEO::OclocErrorCode::SUCCESS);
EXPECT_TRUE(output.find("Command was: ocloc -q -file test_files/IDoNotExist.cl -device "s +
gEnvironment->devicePrefix.c_str() +
" -options \"-D DEBUG -cl-kernel-arg-info\" -internal_options \"-internalOption1 -internal-option-2\"") != std::string::npos);
@ -226,7 +227,7 @@ TEST(OclocApiTests, givenInputOptionsCalledOptionsWhenCmdlineIsPrintedThenQuotes
0, nullptr, nullptr, nullptr,
nullptr, nullptr, nullptr, nullptr);
std::string output = testing::internal::GetCapturedStdout();
EXPECT_NE(retVal, NEO::OfflineCompiler::ErrorCode::SUCCESS);
EXPECT_NE(retVal, NEO::OclocErrorCode::SUCCESS);
EXPECT_TRUE(output.find("Command was: ocloc -q -file test_files/IDoNotExist.cl -device "s +
gEnvironment->devicePrefix.c_str() +
" -options \"-options\" -internal_options \"-internalOption\"") != std::string::npos);
@ -255,7 +256,7 @@ TEST(OclocApiTests, givenInvalidInputOptionsAndInternalOptionsFilesWhenCmdlineIs
0, nullptr, nullptr, nullptr,
nullptr, nullptr, nullptr, nullptr);
std::string output = testing::internal::GetCapturedStdout();
EXPECT_NE(retVal, NEO::OfflineCompiler::ErrorCode::SUCCESS);
EXPECT_NE(retVal, NEO::OclocErrorCode::SUCCESS);
EXPECT_TRUE(output.find("Compiling options read from file were:\n"
"-shouldfailOptions") != std::string::npos);
@ -283,7 +284,7 @@ TEST(OclocApiTests, givenInvalidOclocOptionsFileWhenCmdlineIsPrintedThenTheyAreP
0, nullptr, nullptr, nullptr,
nullptr, nullptr, nullptr, nullptr);
std::string output = testing::internal::GetCapturedStdout();
EXPECT_NE(retVal, NEO::OfflineCompiler::ErrorCode::SUCCESS);
EXPECT_NE(retVal, NEO::OclocErrorCode::SUCCESS);
EXPECT_TRUE(output.find("Failed with ocloc options from file:\n"
"-invalid_ocloc_option") != std::string::npos);
@ -396,7 +397,7 @@ TEST(OclocApiTests, GivenHelpParameterWhenDecodingThenHelpMsgIsPrintedAndSuccess
nullptr, nullptr, nullptr, nullptr);
std::string output = testing::internal::GetCapturedStdout();
EXPECT_FALSE(output.empty());
EXPECT_EQ(retVal, NEO::OfflineCompiler::ErrorCode::SUCCESS);
EXPECT_EQ(retVal, NEO::OclocErrorCode::SUCCESS);
}
TEST(OclocApiTests, GivenHelpParameterWhenEncodingThenHelpMsgIsPrintedAndSuccessIsReturned) {
@ -413,5 +414,109 @@ TEST(OclocApiTests, GivenHelpParameterWhenEncodingThenHelpMsgIsPrintedAndSuccess
nullptr, nullptr, nullptr, nullptr);
std::string output = testing::internal::GetCapturedStdout();
EXPECT_FALSE(output.empty());
EXPECT_EQ(retVal, NEO::OfflineCompiler::ErrorCode::SUCCESS);
EXPECT_EQ(retVal, NEO::OclocErrorCode::SUCCESS);
}
TEST(OclocApiTests, GivenNonexistentFileWhenValidateIsInvokedThenErrorIsPrinted) {
const char *argv[] = {
"ocloc",
"validate",
"-file",
"some_special_nonexistent_file.gen"};
unsigned int argc = sizeof(argv) / sizeof(argv[0]);
testing::internal::CaptureStdout();
int retVal = oclocInvoke(argc, argv,
0, nullptr, nullptr, nullptr,
0, nullptr, nullptr, nullptr,
nullptr, nullptr, nullptr, nullptr);
const auto output = testing::internal::GetCapturedStdout();
EXPECT_EQ(-1, retVal);
const std::string expectedErrorMessage{"Error : Input file missing : some_special_nonexistent_file.gen\n"};
EXPECT_EQ(expectedErrorMessage, output);
}
TEST(OclocApiTests, GivenZeroArgumentsWhenOclocIsInvokedThenHelpIsPrinted) {
testing::internal::CaptureStdout();
int retVal = oclocInvoke(0, nullptr,
0, nullptr, nullptr, nullptr,
0, nullptr, nullptr, nullptr,
nullptr, nullptr, nullptr, nullptr);
const auto output = testing::internal::GetCapturedStdout();
EXPECT_EQ(NEO::OclocErrorCode::INVALID_COMMAND_LINE, retVal);
EXPECT_FALSE(output.empty());
}
TEST(OclocApiTests, GivenCommandWithoutArgsWhenOclocIsInvokedThenHelpIsPrinted) {
const char *argv[] = {
"ocloc"};
unsigned int argc = sizeof(argv) / sizeof(argv[0]);
testing::internal::CaptureStdout();
int retVal = oclocInvoke(argc, argv,
0, nullptr, nullptr, nullptr,
0, nullptr, nullptr, nullptr,
nullptr, nullptr, nullptr, nullptr);
const auto output = testing::internal::GetCapturedStdout();
EXPECT_EQ(NEO::OclocErrorCode::SUCCESS, retVal);
EXPECT_FALSE(output.empty());
}
TEST(OclocApiTests, GivenLongHelpArgumentWhenOclocIsInvokedThenHelpIsPrinted) {
const char *argv[] = {
"ocloc",
"--help"};
unsigned int argc = sizeof(argv) / sizeof(argv[0]);
testing::internal::CaptureStdout();
int retVal = oclocInvoke(argc, argv,
0, nullptr, nullptr, nullptr,
0, nullptr, nullptr, nullptr,
nullptr, nullptr, nullptr, nullptr);
const auto output = testing::internal::GetCapturedStdout();
EXPECT_EQ(NEO::OclocErrorCode::SUCCESS, retVal);
EXPECT_FALSE(output.empty());
}
TEST(OclocApiTests, GivenHelpParameterWhenLinkingThenHelpMsgIsPrintedAndSuccessIsReturned) {
const char *argv[] = {
"ocloc",
"link",
"--help"};
unsigned int argc = sizeof(argv) / sizeof(argv[0]);
testing::internal::CaptureStdout();
int retVal = oclocInvoke(argc, argv,
0, nullptr, nullptr, nullptr,
0, nullptr, nullptr, nullptr,
nullptr, nullptr, nullptr, nullptr);
std::string output = testing::internal::GetCapturedStdout();
EXPECT_FALSE(output.empty());
EXPECT_EQ(NEO::OclocErrorCode::SUCCESS, retVal);
}
TEST(OclocApiTests, GivenInvalidParameterWhenLinkingThenErrorIsReturned) {
const char *argv[] = {
"ocloc",
"link",
"--dummy_param"};
unsigned int argc = sizeof(argv) / sizeof(argv[0]);
testing::internal::CaptureStdout();
int retVal = oclocInvoke(argc, argv,
0, nullptr, nullptr, nullptr,
0, nullptr, nullptr, nullptr,
nullptr, nullptr, nullptr, nullptr);
std::string output = testing::internal::GetCapturedStdout();
EXPECT_EQ(NEO::OclocErrorCode::INVALID_COMMAND_LINE, retVal);
const std::string expectedInitError{"Invalid option (arg 2): --dummy_param\n"};
const std::string expectedExecuteError{"Error: Linker cannot be executed due to unsuccessful initialization!\n"};
const std::string expectedErrorMessage = expectedInitError + expectedExecuteError;
EXPECT_EQ(expectedErrorMessage, output);
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (C) 2020-2021 Intel Corporation
* Copyright (C) 2020-2022 Intel Corporation
*
* SPDX-License-Identifier: MIT
*
@ -8,6 +8,7 @@
#include "opencl/test/unit_test/offline_compiler/ocloc_fatbinary_tests.h"
#include "shared/offline_compiler/source/ocloc_arg_helper.h"
#include "shared/offline_compiler/source/ocloc_error_code.h"
#include "shared/source/helpers/hw_helper.h"
#include <algorithm>
@ -505,7 +506,7 @@ TEST_F(OclocFatBinaryGetTargetConfigsForFatbinary, GivenMutiplePlatformWhenSecon
testing::internal::CaptureStdout();
int retVal = buildFatBinary(argv, argHelper.get());
auto output = testing::internal::GetCapturedStdout();
EXPECT_NE(retVal, NEO::OfflineCompiler::ErrorCode::SUCCESS);
EXPECT_NE(retVal, NEO::OclocErrorCode::SUCCESS);
resString << "Unknown device : unk\n";
resString << "Failed to parse target devices from : " << platformTarget << "\n";
@ -536,7 +537,7 @@ TEST_F(OclocFatBinaryGetTargetConfigsForFatbinary, GivenClosedRangeTooExtensiveW
testing::internal::CaptureStdout();
int retVal = buildFatBinary(argv, argHelper.get());
auto output = testing::internal::GetCapturedStdout();
EXPECT_NE(retVal, NEO::OfflineCompiler::ErrorCode::SUCCESS);
EXPECT_NE(retVal, NEO::OclocErrorCode::SUCCESS);
resString << "Invalid range : " << configString.str() << " - should be from-to or -to or from-"
<< "\n";
resString << "Failed to parse target devices from : " << configString.str() << "\n";
@ -641,7 +642,7 @@ TEST_F(OclocFatBinaryGetTargetConfigsForFatbinary, GivenTwoPlatformsWhenFatBinar
testing::internal::CaptureStdout();
int retVal = buildFatBinary(argv, argHelper.get());
auto output = testing::internal::GetCapturedStdout();
EXPECT_EQ(retVal, NEO::OfflineCompiler::ErrorCode::SUCCESS);
EXPECT_EQ(retVal, NEO::OclocErrorCode::SUCCESS);
for (uint32_t i = 0; i < got.size(); i++) {
resString << "Build succeeded for : " << expected[i].str() + "." + platformsRevision[i] + ".\n";
@ -695,7 +696,7 @@ TEST_F(OclocFatBinaryGetTargetConfigsForFatbinary, GivenPlatformsClosedRangeWhen
testing::internal::CaptureStdout();
int retVal = buildFatBinary(argv, argHelper.get());
auto output = testing::internal::GetCapturedStdout();
EXPECT_EQ(retVal, NEO::OfflineCompiler::ErrorCode::SUCCESS);
EXPECT_EQ(retVal, NEO::OclocErrorCode::SUCCESS);
for (uint32_t i = 0; i < got.size(); i++) {
resString << "Build succeeded for : " << expected[i].str() + "." + platformsRevisions[i] + ".\n";
@ -744,7 +745,7 @@ TEST_F(OclocFatBinaryGetTargetConfigsForFatbinary, GivenPlatformsOpenRangeToWhen
testing::internal::CaptureStdout();
int retVal = buildFatBinary(argv, argHelper.get());
auto output = testing::internal::GetCapturedStdout();
EXPECT_EQ(retVal, NEO::OfflineCompiler::ErrorCode::SUCCESS);
EXPECT_EQ(retVal, NEO::OclocErrorCode::SUCCESS);
for (uint32_t i = 0; i < got.size(); i++) {
resString << "Build succeeded for : " << expected[i].str() + "." + platformsRevisions[i] + ".\n";
@ -793,7 +794,7 @@ TEST_F(OclocFatBinaryGetTargetConfigsForFatbinary, GivenPlatformsOpenRangeFromWh
testing::internal::CaptureStdout();
int retVal = buildFatBinary(argv, argHelper.get());
auto output = testing::internal::GetCapturedStdout();
EXPECT_EQ(retVal, NEO::OfflineCompiler::ErrorCode::SUCCESS);
EXPECT_EQ(retVal, NEO::OclocErrorCode::SUCCESS);
for (uint32_t i = 0; i < got.size(); i++) {
resString << "Build succeeded for : " << expected[i].str() + "." + platformsRevisions[i] + ".\n";
@ -847,7 +848,7 @@ TEST_F(OclocFatBinaryGetTargetConfigsForFatbinary, GivenTwoConfigsWhenFatBinaryB
testing::internal::CaptureStdout();
int retVal = buildFatBinary(argv, argHelper.get());
auto output = testing::internal::GetCapturedStdout();
EXPECT_EQ(retVal, NEO::OfflineCompiler::ErrorCode::SUCCESS);
EXPECT_EQ(retVal, NEO::OclocErrorCode::SUCCESS);
for (auto deviceConfig : expected) {
std::string platformName = hardwarePrefix[deviceConfig.hwInfo->platform.eProductFamily];
@ -893,7 +894,7 @@ TEST_F(OclocFatBinaryGetTargetConfigsForFatbinary, GivenProductConfigOpenRangeFr
testing::internal::CaptureStdout();
int retVal = buildFatBinary(argv, argHelper.get());
auto output = testing::internal::GetCapturedStdout();
EXPECT_EQ(retVal, NEO::OfflineCompiler::ErrorCode::SUCCESS);
EXPECT_EQ(retVal, NEO::OclocErrorCode::SUCCESS);
for (auto deviceConfig : expected) {
std::string platformName = hardwarePrefix[deviceConfig.hwInfo->platform.eProductFamily];
@ -939,7 +940,7 @@ TEST_F(OclocFatBinaryGetTargetConfigsForFatbinary, GivenProductConfigOpenRangeTo
testing::internal::CaptureStdout();
int retVal = buildFatBinary(argv, argHelper.get());
auto output = testing::internal::GetCapturedStdout();
EXPECT_EQ(retVal, NEO::OfflineCompiler::ErrorCode::SUCCESS);
EXPECT_EQ(retVal, NEO::OclocErrorCode::SUCCESS);
for (auto deviceConfig : expected) {
std::string platformName = hardwarePrefix[deviceConfig.hwInfo->platform.eProductFamily];
@ -993,7 +994,7 @@ TEST_F(OclocFatBinaryGetTargetConfigsForFatbinary, GivenProductConfigClosedRange
testing::internal::CaptureStdout();
int retVal = buildFatBinary(argv, argHelper.get());
auto output = testing::internal::GetCapturedStdout();
EXPECT_EQ(retVal, NEO::OfflineCompiler::ErrorCode::SUCCESS);
EXPECT_EQ(retVal, NEO::OclocErrorCode::SUCCESS);
for (auto deviceConfig : expected) {
std::string platformName = hardwarePrefix[deviceConfig.hwInfo->platform.eProductFamily];

View File

@ -238,7 +238,7 @@ TEST_F(MultiCommandTests, GivenMissingTextFileWithArgsWhenBuildingMultiCommandTh
EXPECT_STRNE(output.c_str(), "");
EXPECT_EQ(nullptr, pMultiCommand);
EXPECT_EQ(OfflineCompiler::ErrorCode::INVALID_FILE, retVal);
EXPECT_EQ(OclocErrorCode::INVALID_FILE, retVal);
DebugManager.flags.PrintDebugMessages.set(false);
}
TEST_F(MultiCommandTests, GivenLackOfClFileWhenBuildingMultiCommandThenInvalidFileErrorIsReturned) {
@ -263,7 +263,7 @@ TEST_F(MultiCommandTests, GivenLackOfClFileWhenBuildingMultiCommandThenInvalidFi
std::string output = testing::internal::GetCapturedStdout();
EXPECT_EQ(nullptr, pMultiCommand);
EXPECT_EQ(OfflineCompiler::ErrorCode::INVALID_FILE, retVal);
EXPECT_EQ(OclocErrorCode::INVALID_FILE, retVal);
DebugManager.flags.PrintDebugMessages.set(false);
deleteFileWithArgs();
@ -318,7 +318,7 @@ TEST_F(OfflineCompilerTests, GivenHelpOptionOnQueryThenSuccessIsReturned) {
std::string output = testing::internal::GetCapturedStdout();
EXPECT_STREQ(OfflineCompiler::queryHelp.data(), output.c_str());
EXPECT_EQ(OfflineCompiler::ErrorCode::SUCCESS, retVal);
EXPECT_EQ(OclocErrorCode::SUCCESS, retVal);
}
TEST_F(OfflineCompilerTests, GivenArgsWhenQueryIsCalledThenSuccessIsReturned) {
@ -329,7 +329,7 @@ TEST_F(OfflineCompilerTests, GivenArgsWhenQueryIsCalledThenSuccessIsReturned) {
int retVal = OfflineCompiler::query(argv.size(), argv, oclocArgHelperWithoutInput.get());
EXPECT_EQ(OfflineCompiler::ErrorCode::SUCCESS, retVal);
EXPECT_EQ(OclocErrorCode::SUCCESS, retVal);
}
TEST_F(OfflineCompilerTests, GivenArgsWhenOfflineCompilerIsCreatedThenSuccessIsReturned) {
@ -587,7 +587,7 @@ TEST_F(OfflineCompilerTests, givenExcludeIrArgumentWhenCompilingKernelThenIrShou
mockOfflineCompiler.initialize(argv.size(), argv);
const auto buildResult{mockOfflineCompiler.build()};
ASSERT_EQ(OfflineCompiler::SUCCESS, buildResult);
ASSERT_EQ(OclocErrorCode::SUCCESS, buildResult);
std::string errorReason{};
std::string warning{};
@ -611,7 +611,7 @@ TEST_F(OfflineCompilerTests, givenLackOfExcludeIrArgumentWhenCompilingKernelThen
mockOfflineCompiler.initialize(argv.size(), argv);
const auto buildResult{mockOfflineCompiler.build()};
ASSERT_EQ(OfflineCompiler::SUCCESS, buildResult);
ASSERT_EQ(OclocErrorCode::SUCCESS, buildResult);
std::string errorReason{};
std::string warning{};
@ -872,7 +872,7 @@ TEST_F(OfflineCompilerTests, GivenHelpOptionThenBuildDoesNotOccur) {
pOfflineCompiler = OfflineCompiler::create(argv.size(), argv, true, retVal, oclocArgHelperWithoutInput.get());
std::string output = testing::internal::GetCapturedStdout();
EXPECT_STRNE("", output.c_str());
EXPECT_EQ(OfflineCompiler::ErrorCode::SUCCESS, retVal);
EXPECT_EQ(OclocErrorCode::SUCCESS, retVal);
delete pOfflineCompiler;
}
@ -890,7 +890,7 @@ TEST_F(OfflineCompilerTests, GivenInvalidFileWhenBuildingThenInvalidFileErrorIsR
std::string output = testing::internal::GetCapturedStdout();
EXPECT_STRNE(output.c_str(), "");
EXPECT_EQ(nullptr, pOfflineCompiler);
EXPECT_EQ(OfflineCompiler::ErrorCode::INVALID_FILE, retVal);
EXPECT_EQ(OclocErrorCode::INVALID_FILE, retVal);
DebugManager.flags.PrintDebugMessages.set(false);
delete pOfflineCompiler;
}
@ -908,7 +908,7 @@ TEST_F(OfflineCompilerTests, GivenInvalidFlagWhenBuildingThenInvalidCommandLineE
std::string output = testing::internal::GetCapturedStdout();
EXPECT_STRNE(output.c_str(), "");
EXPECT_EQ(nullptr, pOfflineCompiler);
EXPECT_EQ(OfflineCompiler::ErrorCode::INVALID_COMMAND_LINE, retVal);
EXPECT_EQ(OclocErrorCode::INVALID_COMMAND_LINE, retVal);
delete pOfflineCompiler;
}
@ -925,7 +925,7 @@ TEST_F(OfflineCompilerTests, GivenInvalidOptionsWhenBuildingThenInvalidCommandLi
EXPECT_STRNE(output.c_str(), "");
EXPECT_EQ(nullptr, pOfflineCompiler);
EXPECT_EQ(OfflineCompiler::ErrorCode::INVALID_COMMAND_LINE, retVal);
EXPECT_EQ(OclocErrorCode::INVALID_COMMAND_LINE, retVal);
delete pOfflineCompiler;
@ -939,7 +939,7 @@ TEST_F(OfflineCompilerTests, GivenInvalidOptionsWhenBuildingThenInvalidCommandLi
output = testing::internal::GetCapturedStdout();
EXPECT_STRNE(output.c_str(), "");
EXPECT_EQ(nullptr, pOfflineCompiler);
EXPECT_EQ(OfflineCompiler::ErrorCode::INVALID_COMMAND_LINE, retVal);
EXPECT_EQ(OclocErrorCode::INVALID_COMMAND_LINE, retVal);
delete pOfflineCompiler;
}
@ -1724,7 +1724,7 @@ TEST(OfflineCompilerTest, givenCompilerWhenBuildSourceCodeFailsThenGenerateElfBi
MockOfflineCompiler compiler;
compiler.overrideBuildSourceCodeStatus = true;
auto expectedError = OfflineCompiler::ErrorCode::BUILD_PROGRAM_FAILURE;
auto expectedError = OclocErrorCode::BUILD_PROGRAM_FAILURE;
compiler.buildSourceCodeStatus = expectedError;
EXPECT_EQ(0u, compiler.generateElfBinaryCalled);
@ -1755,7 +1755,7 @@ TEST(OfflineCompilerTest, givenDeviceSpecificKernelFileWhenCompilerIsInitialized
gEnvironment->devicePrefix.c_str()};
int retVal = mockOfflineCompiler->initialize(argv.size(), argv);
EXPECT_EQ(OfflineCompiler::ErrorCode::SUCCESS, retVal);
EXPECT_EQ(OclocErrorCode::SUCCESS, retVal);
EXPECT_STREQ("-cl-opt-disable", mockOfflineCompiler->options.c_str());
}
@ -1774,7 +1774,7 @@ TEST(OfflineCompilerTest, givenHexadecimalRevisionIdWhenCompilerIsInitializedThe
"0x11"};
int retVal = mockOfflineCompiler->initialize(argv.size(), argv);
EXPECT_EQ(OfflineCompiler::ErrorCode::SUCCESS, retVal);
EXPECT_EQ(OclocErrorCode::SUCCESS, retVal);
EXPECT_EQ(mockOfflineCompiler->hwInfo.platform.usRevId, 17);
}
@ -1796,7 +1796,7 @@ TEST(OfflineCompilerTest, givenDebugVariableSetWhenInitializingThenOverrideRevis
"0x11"};
int retVal = mockOfflineCompiler->initialize(argv.size(), argv);
EXPECT_EQ(OfflineCompiler::ErrorCode::SUCCESS, retVal);
EXPECT_EQ(OclocErrorCode::SUCCESS, retVal);
EXPECT_EQ(mockOfflineCompiler->hwInfo.platform.usRevId, 123);
}
@ -1815,7 +1815,7 @@ TEST(OfflineCompilerTest, givenDecimalRevisionIdWhenCompilerIsInitializedThenPas
"17"};
int retVal = mockOfflineCompiler->initialize(argv.size(), argv);
EXPECT_EQ(OfflineCompiler::ErrorCode::SUCCESS, retVal);
EXPECT_EQ(OclocErrorCode::SUCCESS, retVal);
EXPECT_EQ(mockOfflineCompiler->hwInfo.platform.usRevId, 17);
}
@ -1834,7 +1834,7 @@ TEST(OfflineCompilerTest, givenNoRevisionIdWhenCompilerIsInitializedThenHwInfoHa
mockOfflineCompiler->initHardwareInfo(gEnvironment->devicePrefix.c_str());
auto revId = mockOfflineCompiler->hwInfo.platform.usRevId;
int retVal = mockOfflineCompiler->initialize(argv.size(), argv);
EXPECT_EQ(OfflineCompiler::ErrorCode::SUCCESS, retVal);
EXPECT_EQ(OclocErrorCode::SUCCESS, retVal);
EXPECT_EQ(mockOfflineCompiler->hwInfo.platform.usRevId, revId);
}
@ -1851,7 +1851,7 @@ TEST(OfflineCompilerTest, whenDeviceIsSpecifiedThenDefaultConfigFromTheDeviceIsU
gEnvironment->devicePrefix.c_str()};
int retVal = mockOfflineCompiler->initialize(argv.size(), argv);
EXPECT_EQ(OfflineCompiler::ErrorCode::SUCCESS, retVal);
EXPECT_EQ(OclocErrorCode::SUCCESS, retVal);
HardwareInfo hwInfo = mockOfflineCompiler->hwInfo;

View File

@ -1,12 +1,14 @@
/*
* Copyright (C) 2018-2021 Intel Corporation
* Copyright (C) 2018-2022 Intel Corporation
*
* SPDX-License-Identifier: MIT
*
*/
#pragma once
#include "shared/offline_compiler/source/multi_command.h"
#include "shared/offline_compiler/source/ocloc_error_code.h"
#include "shared/offline_compiler/source/offline_compiler.h"
#include "gtest/gtest.h"
@ -19,7 +21,7 @@ namespace NEO {
class OfflineCompilerTests : public ::testing::Test {
public:
OfflineCompiler *pOfflineCompiler = nullptr;
int retVal = OfflineCompiler::ErrorCode::SUCCESS;
int retVal = OclocErrorCode::SUCCESS;
std::unique_ptr<OclocArgHelper> oclocArgHelperWithoutInput = std::make_unique<OclocArgHelper>();
};
@ -31,7 +33,7 @@ class MultiCommandTests : public ::testing::Test {
MultiCommand *pMultiCommand = nullptr;
std::string nameOfFileWithArgs;
std::string outFileList;
int retVal = OfflineCompiler::ErrorCode::SUCCESS;
int retVal = OclocErrorCode::SUCCESS;
std::unique_ptr<OclocArgHelper> oclocArgHelperWithoutInput = std::make_unique<OclocArgHelper>();
};
} // namespace NEO

View File

@ -0,0 +1,793 @@
/*
* Copyright (C) 2022 Intel Corporation
*
* SPDX-License-Identifier: MIT
*
*/
#include "offline_linker_tests.h"
#include "shared/offline_compiler/source/ocloc_error_code.h"
#include "shared/source/device_binary_format/elf/elf_decoder.h"
#include "shared/source/device_binary_format/elf/ocl_elf.h"
#include "shared/source/helpers/string.h"
#include "shared/source/os_interface/os_inc_base.h"
#include "shared/test/common/mocks/mock_compilers.h"
#include "environment.h"
#include <algorithm>
#include <array>
#include <cstring>
#include <iterator>
#include <memory>
#include <sstream>
#include <string>
#include <vector>
extern Environment *gEnvironment;
namespace NEO {
using OperationMode = MockOfflineLinker::OperationMode;
void OfflineLinkerTest::SetUp() {
MockCompilerDebugVars igcDebugVars{gEnvironment->igcDebugVars};
igcDebugVars.binaryToReturn = binaryToReturn;
igcDebugVars.binaryToReturnSize = sizeof(binaryToReturn);
setIgcDebugVars(igcDebugVars);
}
void OfflineLinkerTest::TearDown() {
setIgcDebugVars(gEnvironment->igcDebugVars);
}
std::string OfflineLinkerTest::getEmptySpirvFile() const {
std::string spirv{"\x07\x23\x02\x03"};
spirv.resize(64, '\0');
return spirv;
}
std::string OfflineLinkerTest::getEmptyLlvmBcFile() const {
std::string llvmbc{"BC\xc0\xde"};
llvmbc.resize(64, '\0');
return llvmbc;
}
MockOfflineLinker::InputFileContent OfflineLinkerTest::createFileContent(const std::string &content, IGC::CodeType::CodeType_t codeType) const {
std::unique_ptr<char[]> bytes{new char[content.size()]};
std::copy(content.begin(), content.end(), bytes.get());
return {std::move(bytes), content.size(), codeType};
}
TEST_F(OfflineLinkerTest, GivenDefaultConstructedLinkerThenRequiredFieldsHaveDefaultValues) {
MockOfflineLinker mockOfflineLinker{&mockArgHelper};
EXPECT_EQ(OperationMode::SKIP_EXECUTION, mockOfflineLinker.operationMode);
EXPECT_EQ("linker_output", mockOfflineLinker.outputFilename);
EXPECT_EQ(IGC::CodeType::llvmBc, mockOfflineLinker.outputFormat);
}
TEST_F(OfflineLinkerTest, GivenLessThanTwoArgumentsWhenParsingThenInvalidCommandIsReturned) {
const std::vector<std::string> argv = {
"ocloc.exe"};
MockOfflineLinker mockOfflineLinker{&mockArgHelper};
const auto result = mockOfflineLinker.parseCommand(argv.size(), argv);
EXPECT_EQ(OclocErrorCode::INVALID_COMMAND_LINE, result);
}
TEST_F(OfflineLinkerTest, GivenInputFilesArgumentsWhenParsingThenListOfFilenamesIsPopulated) {
const std::string firstFile{"sample_input_1.spv"};
const std::string secondFile{"sample_input_2.spv"};
const std::vector<std::string> argv = {
"ocloc.exe",
"link",
"-file",
firstFile,
"-file",
secondFile};
MockOfflineLinker mockOfflineLinker{&mockArgHelper};
const auto result = mockOfflineLinker.parseCommand(argv.size(), argv);
ASSERT_EQ(OclocErrorCode::SUCCESS, result);
ASSERT_EQ(2u, mockOfflineLinker.inputFilenames.size());
EXPECT_EQ(firstFile, mockOfflineLinker.inputFilenames[0]);
EXPECT_EQ(secondFile, mockOfflineLinker.inputFilenames[1]);
}
TEST_F(OfflineLinkerTest, GivenOutputFilenameArgumentWhenParsingThenOutputFilenameIsSetAccordingly) {
const std::string outputFilename{"my_custom_output_filename"};
const std::vector<std::string> argv = {
"ocloc.exe",
"link",
"-out",
outputFilename};
MockOfflineLinker mockOfflineLinker{&mockArgHelper};
const auto result = mockOfflineLinker.parseCommand(argv.size(), argv);
ASSERT_EQ(OclocErrorCode::SUCCESS, result);
EXPECT_EQ(outputFilename, mockOfflineLinker.outputFilename);
}
TEST_F(OfflineLinkerTest, GivenValidOutputFileFormatWhenParsingThenOutputFormatIsSetAccordingly) {
const std::vector<std::string> argv = {
"ocloc.exe",
"link",
"-out_format",
"LLVM_BC"};
MockOfflineLinker mockOfflineLinker{&mockArgHelper};
const auto result = mockOfflineLinker.parseCommand(argv.size(), argv);
ASSERT_EQ(OclocErrorCode::SUCCESS, result);
EXPECT_EQ(IGC::CodeType::llvmBc, mockOfflineLinker.outputFormat);
}
TEST_F(OfflineLinkerTest, GivenUnknownOutputFileFormatWhenParsingThenInvalidFormatIsSet) {
const std::vector<std::string> argv = {
"ocloc.exe",
"link",
"-out_format",
"StrangeFormat"};
MockOfflineLinker mockOfflineLinker{&mockArgHelper};
const auto result = mockOfflineLinker.parseCommand(argv.size(), argv);
ASSERT_EQ(OclocErrorCode::SUCCESS, result);
EXPECT_EQ(IGC::CodeType::invalid, mockOfflineLinker.outputFormat);
}
TEST_F(OfflineLinkerTest, GivenOptionsArgumentWhenParsingThenOptionsAreSet) {
const std::string options{"-g"};
const std::vector<std::string> argv = {
"ocloc.exe",
"link",
"-options",
options};
MockOfflineLinker mockOfflineLinker{&mockArgHelper};
const auto result = mockOfflineLinker.parseCommand(argv.size(), argv);
ASSERT_EQ(OclocErrorCode::SUCCESS, result);
EXPECT_EQ(options, mockOfflineLinker.options);
}
TEST_F(OfflineLinkerTest, GivenInternalOptionsArgumentWhenParsingThenInternalOptionsAreSet) {
const std::string internalOptions{"-ze-allow-zebin"};
const std::vector<std::string> argv = {
"ocloc.exe",
"link",
"-internal_options",
internalOptions};
MockOfflineLinker mockOfflineLinker{&mockArgHelper};
const auto result = mockOfflineLinker.parseCommand(argv.size(), argv);
ASSERT_EQ(OclocErrorCode::SUCCESS, result);
EXPECT_EQ(internalOptions, mockOfflineLinker.internalOptions);
}
TEST_F(OfflineLinkerTest, GivenHelpArgumentWhenParsingThenShowHelpOperationIsSet) {
const std::vector<std::string> argv = {
"ocloc.exe",
"link",
"--help"};
MockOfflineLinker mockOfflineLinker{&mockArgHelper};
const auto result = mockOfflineLinker.parseCommand(argv.size(), argv);
ASSERT_EQ(OclocErrorCode::SUCCESS, result);
EXPECT_EQ(OperationMode::SHOW_HELP, mockOfflineLinker.operationMode);
}
TEST_F(OfflineLinkerTest, GivenUnknownArgumentWhenParsingThenErrorIsReported) {
const std::vector<std::string> argv = {
"ocloc.exe",
"link",
"-some_new_unknown_command"};
::testing::internal::CaptureStdout();
MockOfflineLinker mockOfflineLinker{&mockArgHelper};
const auto result = mockOfflineLinker.initialize(argv.size(), argv);
const auto output{::testing::internal::GetCapturedStdout()};
EXPECT_EQ(OclocErrorCode::INVALID_COMMAND_LINE, result);
const std::string expectedErrorMessage{"Invalid option (arg 2): -some_new_unknown_command\n"};
EXPECT_EQ(expectedErrorMessage, output);
}
TEST_F(OfflineLinkerTest, GivenFlagsWhichRequireMoreArgsWithoutThemWhenParsingThenErrorIsReported) {
const std::array<std::string, 5> flagsToTest = {
"-file", "-out", "-out_format", "-options", "-internal_options"};
for (const auto &flag : flagsToTest) {
const std::vector<std::string> argv = {
"ocloc.exe",
"link",
flag};
MockOfflineLinker mockOfflineLinker{&mockArgHelper};
::testing::internal::CaptureStdout();
const auto result = mockOfflineLinker.parseCommand(argv.size(), argv);
const auto output{::testing::internal::GetCapturedStdout()};
EXPECT_EQ(OclocErrorCode::INVALID_COMMAND_LINE, result);
const std::string expectedErrorMessage{"Invalid option (arg 2): " + flag + "\n"};
EXPECT_EQ(expectedErrorMessage, output);
}
}
TEST_F(OfflineLinkerTest, GivenCommandWithoutInputFilesWhenVerificationIsPerformedThenErrorIsReturned) {
MockOfflineLinker mockOfflineLinker{&mockArgHelper};
mockOfflineLinker.inputFilenames = {};
::testing::internal::CaptureStdout();
const auto verificationResult = mockOfflineLinker.verifyLinkerCommand();
const auto output{::testing::internal::GetCapturedStdout()};
EXPECT_EQ(OclocErrorCode::INVALID_COMMAND_LINE, verificationResult);
const std::string expectedErrorMessage{"Error: Input name is missing! At least one input file is required!\n"};
EXPECT_EQ(expectedErrorMessage, output);
}
TEST_F(OfflineLinkerTest, GivenCommandWithEmptyFilenameWhenVerificationIsPerformedThenErrorIsReturned) {
const std::vector<std::string> argv = {
"ocloc.exe",
"link",
"-file",
""};
MockOfflineLinker mockOfflineLinker{&mockArgHelper};
::testing::internal::CaptureStdout();
const auto verificationResult = mockOfflineLinker.initialize(argv.size(), argv);
const auto output{::testing::internal::GetCapturedStdout()};
EXPECT_EQ(OclocErrorCode::INVALID_COMMAND_LINE, verificationResult);
const std::string expectedErrorMessage{"Error: Empty filename cannot be used!\n"};
EXPECT_EQ(expectedErrorMessage, output);
}
TEST_F(OfflineLinkerTest, GivenCommandWithNonexistentInputFileWhenVerificationIsPerformedThenErrorIsReturned) {
const std::vector<std::string> argv = {
"ocloc.exe",
"link",
"-file",
"some_file1.spv",
"-file",
"some_file2.spv"};
MockOfflineLinker mockOfflineLinker{&mockArgHelper};
const auto parsingResult = mockOfflineLinker.parseCommand(argv.size(), argv);
ASSERT_EQ(OclocErrorCode::SUCCESS, parsingResult);
::testing::internal::CaptureStdout();
const auto verificationResult = mockOfflineLinker.verifyLinkerCommand();
const auto output{::testing::internal::GetCapturedStdout()};
EXPECT_EQ(OclocErrorCode::INVALID_FILE, verificationResult);
const std::string expectedErrorMessage{"Error: Input file some_file1.spv missing.\n"};
EXPECT_EQ(expectedErrorMessage, output);
}
TEST_F(OfflineLinkerTest, GivenCommandWithInvalidOutputFormatWhenVerificationIsPerformedThenErrorIsReturned) {
mockArgHelperFilesMap["some_file.spv"] = getEmptySpirvFile();
const std::vector<std::string> argv = {
"ocloc.exe",
"link",
"-file",
"some_file.spv",
"-out_format",
"SomeDummyUnknownFormat"};
MockOfflineLinker mockOfflineLinker{&mockArgHelper};
const auto parsingResult = mockOfflineLinker.parseCommand(argv.size(), argv);
ASSERT_EQ(OclocErrorCode::SUCCESS, parsingResult);
::testing::internal::CaptureStdout();
const auto verificationResult = mockOfflineLinker.verifyLinkerCommand();
const auto output{::testing::internal::GetCapturedStdout()};
EXPECT_EQ(OclocErrorCode::INVALID_COMMAND_LINE, verificationResult);
const std::string expectedErrorMessage{"Error: Invalid output type!\n"};
EXPECT_EQ(expectedErrorMessage, output);
}
TEST_F(OfflineLinkerTest, GivenValidCommandWhenVerificationIsPerformedThenSuccessIsReturned) {
mockArgHelperFilesMap["some_file1.spv"] = getEmptySpirvFile();
mockArgHelperFilesMap["some_file2.spv"] = getEmptySpirvFile();
const std::vector<std::string> argv = {
"ocloc.exe",
"link",
"-file",
"some_file1.spv",
"-file",
"some_file2.spv"};
MockOfflineLinker mockOfflineLinker{&mockArgHelper};
const auto parsingResult = mockOfflineLinker.parseCommand(argv.size(), argv);
ASSERT_EQ(OclocErrorCode::SUCCESS, parsingResult);
::testing::internal::CaptureStdout();
const auto verificationResult = mockOfflineLinker.verifyLinkerCommand();
const auto output{::testing::internal::GetCapturedStdout()};
EXPECT_EQ(OclocErrorCode::SUCCESS, verificationResult);
EXPECT_TRUE(output.empty());
}
TEST_F(OfflineLinkerTest, GivenEmptyFileWhenLoadingInputFilesThenErrorIsReturned) {
const std::string filename{"some_file.spv"};
// Empty file is treated as an error.
mockArgHelperFilesMap[filename] = "";
const std::vector<std::string> argv = {
"ocloc.exe",
"link",
"-file",
filename};
MockOfflineLinker mockOfflineLinker{&mockArgHelper};
::testing::internal::CaptureStdout();
const auto readingResult = mockOfflineLinker.initialize(argv.size(), argv);
const auto output{::testing::internal::GetCapturedStdout()};
ASSERT_EQ(OclocErrorCode::INVALID_FILE, readingResult);
const std::string expectedErrorMessage{"Error: Cannot read input file: some_file.spv\n"};
EXPECT_EQ(expectedErrorMessage, output);
}
TEST_F(OfflineLinkerTest, GivenValidFileWithUnknownFormatWhenLoadingInputFilesThenErrorIsReturned) {
const std::string filename{"some_file.unknown"};
// Spir-V or LLVM-BC magic constants are required. This should be treated as error.
mockArgHelperFilesMap[filename] = "Some unknown format!";
MockOfflineLinker mockOfflineLinker{&mockArgHelper};
mockOfflineLinker.inputFilenames.push_back(filename);
::testing::internal::CaptureStdout();
const auto readingResult = mockOfflineLinker.loadInputFilesContent();
const auto output{::testing::internal::GetCapturedStdout()};
ASSERT_EQ(OclocErrorCode::INVALID_PROGRAM, readingResult);
const std::string expectedErrorMessage{"Error: Unsupported format of input file: some_file.unknown\n"};
EXPECT_EQ(expectedErrorMessage, output);
}
TEST_F(OfflineLinkerTest, GivenReadingErrorWhenLoadingInputFilesThenErrorIsReturned) {
const std::string filename{"some_file1.spv"};
mockArgHelperFilesMap[filename] = getEmptySpirvFile();
mockArgHelper.shouldReturnReadingError = true;
MockOfflineLinker mockOfflineLinker{&mockArgHelper};
mockOfflineLinker.inputFilenames.push_back(filename);
::testing::internal::CaptureStdout();
const auto readingResult = mockOfflineLinker.loadInputFilesContent();
const auto output{::testing::internal::GetCapturedStdout()};
ASSERT_EQ(OclocErrorCode::INVALID_FILE, readingResult);
const std::string expectedErrorMessage{"Error: Cannot read input file: some_file1.spv\n"};
EXPECT_EQ(expectedErrorMessage, output);
}
TEST_F(OfflineLinkerTest, GivenValidFilesWithValidFormatsWhenLoadingInputFilesThenFilesAreLoadedAndSuccessIsReturned) {
const std::string firstFilename{"some_file1.spv"};
const std::string secondFilename{"some_file2.llvmbc"};
mockArgHelperFilesMap[firstFilename] = getEmptySpirvFile();
mockArgHelperFilesMap[secondFilename] = getEmptyLlvmBcFile();
MockOfflineLinker mockOfflineLinker{&mockArgHelper};
mockOfflineLinker.inputFilenames.push_back(firstFilename);
mockOfflineLinker.inputFilenames.push_back(secondFilename);
::testing::internal::CaptureStdout();
const auto readingResult = mockOfflineLinker.loadInputFilesContent();
const auto output{::testing::internal::GetCapturedStdout()};
ASSERT_EQ(OclocErrorCode::SUCCESS, readingResult);
EXPECT_TRUE(output.empty());
const auto &firstExpectedContent = mockArgHelperFilesMap[firstFilename];
const auto &firstActualContent = mockOfflineLinker.inputFilesContent[0];
ASSERT_EQ(firstExpectedContent.size(), firstActualContent.size);
const auto isFirstPairEqual = std::equal(firstExpectedContent.begin(), firstExpectedContent.end(), firstActualContent.bytes.get());
EXPECT_TRUE(isFirstPairEqual);
const auto &secondExpectedContent = mockArgHelperFilesMap[secondFilename];
const auto &secondActualContent = mockOfflineLinker.inputFilesContent[1];
ASSERT_EQ(secondExpectedContent.size(), secondActualContent.size);
const auto isSecondPairEqual = std::equal(secondExpectedContent.begin(), secondExpectedContent.end(), secondActualContent.bytes.get());
EXPECT_TRUE(isSecondPairEqual);
}
TEST_F(OfflineLinkerTest, GivenValidFilesWhenInitializationIsSuccessfulThenLinkModeOfOperationIsSet) {
const std::string firstFilename{"some_file1.spv"};
const std::string secondFilename{"some_file2.llvmbc"};
mockArgHelperFilesMap[firstFilename] = getEmptySpirvFile();
mockArgHelperFilesMap[secondFilename] = getEmptyLlvmBcFile();
const std::vector<std::string> argv = {
"ocloc.exe",
"link",
"-file",
firstFilename,
"-file",
secondFilename};
MockOfflineLinker mockOfflineLinker{&mockArgHelper};
::testing::internal::CaptureStdout();
const auto readingResult = mockOfflineLinker.initialize(argv.size(), argv);
const auto output{::testing::internal::GetCapturedStdout()};
EXPECT_EQ(OclocErrorCode::SUCCESS, readingResult);
EXPECT_TRUE(output.empty());
EXPECT_EQ(OperationMode::LINK_FILES, mockOfflineLinker.operationMode);
}
TEST_F(OfflineLinkerTest, GivenSPIRVandLLVMBCFilesWhenElfOutputIsRequestedThenElfWithSPIRVAndLLVMSectionsIsCreated) {
auto spirvFileContent = createFileContent(getEmptySpirvFile(), IGC::CodeType::spirV);
auto llvmbcFileContent = createFileContent(getEmptyLlvmBcFile(), IGC::CodeType::llvmBc);
mockArgHelper.interceptOutput = true;
MockOfflineLinker mockOfflineLinker{&mockArgHelper};
mockOfflineLinker.inputFilesContent.emplace_back(std::move(spirvFileContent.bytes), spirvFileContent.size, spirvFileContent.codeType);
mockOfflineLinker.inputFilesContent.emplace_back(std::move(llvmbcFileContent.bytes), llvmbcFileContent.size, llvmbcFileContent.codeType);
mockOfflineLinker.outputFormat = IGC::CodeType::elf;
mockOfflineLinker.operationMode = OperationMode::LINK_FILES;
const auto linkingResult{mockOfflineLinker.execute()};
ASSERT_EQ(OclocErrorCode::SUCCESS, linkingResult);
ASSERT_EQ(1u, mockArgHelper.interceptedFiles.count("linker_output"));
const auto &rawOutput{mockArgHelper.interceptedFiles.at("linker_output")};
const auto encodedElf{ArrayRef<const uint8_t>::fromAny(rawOutput.data(), rawOutput.size())};
std::string errorReason{};
std::string warning{};
const auto elf{Elf::decodeElf(encodedElf, errorReason, warning)};
ASSERT_TRUE(errorReason.empty());
EXPECT_TRUE(warning.empty());
// SPIR-V bitcode section.
EXPECT_EQ(Elf::SHT_OPENCL_SPIRV, elf.sectionHeaders[1].header->type);
const auto &expectedFirstSection = mockOfflineLinker.inputFilesContent[0];
const auto &actualFirstSection = elf.sectionHeaders[1];
ASSERT_EQ(expectedFirstSection.size, actualFirstSection.header->size);
const auto isFirstSectionContentEqual = std::memcmp(actualFirstSection.data.begin(), expectedFirstSection.bytes.get(), expectedFirstSection.size) == 0;
EXPECT_TRUE(isFirstSectionContentEqual);
// LLVM bitcode section.
EXPECT_EQ(Elf::SHT_OPENCL_LLVM_BINARY, elf.sectionHeaders[2].header->type);
const auto &expectedSecondSection = mockOfflineLinker.inputFilesContent[1];
const auto &actualSecondSection = elf.sectionHeaders[2];
ASSERT_EQ(expectedSecondSection.size, actualSecondSection.header->size);
const auto isSecondSectionContentEqual = std::memcmp(actualSecondSection.data.begin(), expectedSecondSection.bytes.get(), expectedSecondSection.size) == 0;
EXPECT_TRUE(isSecondSectionContentEqual);
}
TEST_F(OfflineLinkerTest, GivenValidInputFileContentsWhenLlvmBcOutputIsRequestedThenSuccessIsReturnedAndFileIsWritten) {
auto spirvFileContent = createFileContent(getEmptySpirvFile(), IGC::CodeType::spirV);
auto llvmbcFileContent = createFileContent(getEmptyLlvmBcFile(), IGC::CodeType::llvmBc);
mockArgHelper.interceptOutput = true;
MockOfflineLinker mockOfflineLinker{&mockArgHelper};
mockOfflineLinker.inputFilesContent.emplace_back(std::move(spirvFileContent.bytes), spirvFileContent.size, spirvFileContent.codeType);
mockOfflineLinker.inputFilesContent.emplace_back(std::move(llvmbcFileContent.bytes), llvmbcFileContent.size, llvmbcFileContent.codeType);
mockOfflineLinker.outputFormat = IGC::CodeType::llvmBc;
mockOfflineLinker.operationMode = OperationMode::LINK_FILES;
const auto igcInitializationResult{mockOfflineLinker.prepareIgc()};
ASSERT_EQ(OclocErrorCode::SUCCESS, igcInitializationResult);
const auto linkingResult{mockOfflineLinker.execute()};
ASSERT_EQ(OclocErrorCode::SUCCESS, linkingResult);
ASSERT_EQ(1u, mockArgHelper.interceptedFiles.count("linker_output"));
const auto &actualOutput{mockArgHelper.interceptedFiles.at("linker_output")};
const auto &expectedOutput{binaryToReturn};
ASSERT_EQ(sizeof(expectedOutput), actualOutput.size());
const auto isActualOutputSameAsExpected{std::equal(std::begin(expectedOutput), std::end(expectedOutput), std::begin(actualOutput))};
EXPECT_TRUE(isActualOutputSameAsExpected);
}
TEST_F(OfflineLinkerTest, GivenValidInputFileContentsAndFailingIGCWhenLlvmBcOutputIsRequestedThenErrorIsReturned) {
MockCompilerDebugVars igcDebugVars{gEnvironment->igcDebugVars};
igcDebugVars.forceBuildFailure = true;
setIgcDebugVars(igcDebugVars);
auto spirvFileContent = createFileContent(getEmptySpirvFile(), IGC::CodeType::spirV);
auto llvmbcFileContent = createFileContent(getEmptyLlvmBcFile(), IGC::CodeType::llvmBc);
mockArgHelper.interceptOutput = true;
MockOfflineLinker mockOfflineLinker{&mockArgHelper};
mockOfflineLinker.inputFilesContent.emplace_back(std::move(spirvFileContent.bytes), spirvFileContent.size, spirvFileContent.codeType);
mockOfflineLinker.inputFilesContent.emplace_back(std::move(llvmbcFileContent.bytes), llvmbcFileContent.size, llvmbcFileContent.codeType);
mockOfflineLinker.outputFormat = IGC::CodeType::llvmBc;
mockOfflineLinker.operationMode = OperationMode::LINK_FILES;
const auto igcInitializationResult{mockOfflineLinker.prepareIgc()};
ASSERT_EQ(OclocErrorCode::SUCCESS, igcInitializationResult);
::testing::internal::CaptureStdout();
const auto linkingResult{mockOfflineLinker.execute()};
const auto output{::testing::internal::GetCapturedStdout()};
ASSERT_EQ(OclocErrorCode::BUILD_PROGRAM_FAILURE, linkingResult);
EXPECT_EQ(0u, mockArgHelper.interceptedFiles.count("linker_output"));
const std::string expectedErrorMessage{"Error: Translation has failed! IGC returned empty output.\n"};
EXPECT_EQ(expectedErrorMessage, output);
}
TEST_F(OfflineLinkerTest, GivenValidInputFileContentsAndInvalidTranslationOutputWhenLlvmBcOutputIsRequestedThenErrorIsReturned) {
MockCompilerDebugVars igcDebugVars{gEnvironment->igcDebugVars};
igcDebugVars.shouldReturnInvalidTranslationOutput = true;
setIgcDebugVars(igcDebugVars);
auto spirvFileContent = createFileContent(getEmptySpirvFile(), IGC::CodeType::spirV);
auto llvmbcFileContent = createFileContent(getEmptyLlvmBcFile(), IGC::CodeType::llvmBc);
mockArgHelper.interceptOutput = true;
MockOfflineLinker mockOfflineLinker{&mockArgHelper};
mockOfflineLinker.inputFilesContent.emplace_back(std::move(spirvFileContent.bytes), spirvFileContent.size, spirvFileContent.codeType);
mockOfflineLinker.inputFilesContent.emplace_back(std::move(llvmbcFileContent.bytes), llvmbcFileContent.size, llvmbcFileContent.codeType);
mockOfflineLinker.outputFormat = IGC::CodeType::llvmBc;
mockOfflineLinker.operationMode = OperationMode::LINK_FILES;
const auto igcInitializationResult{mockOfflineLinker.prepareIgc()};
ASSERT_EQ(OclocErrorCode::SUCCESS, igcInitializationResult);
::testing::internal::CaptureStdout();
const auto linkingResult{mockOfflineLinker.execute()};
const auto output{::testing::internal::GetCapturedStdout()};
ASSERT_EQ(OclocErrorCode::OUT_OF_HOST_MEMORY, linkingResult);
EXPECT_EQ(0u, mockArgHelper.interceptedFiles.count("linker_output"));
const std::string expectedErrorMessage{"Error: Translation has failed! IGC output is nullptr!\n"};
EXPECT_EQ(expectedErrorMessage, output);
}
TEST_F(OfflineLinkerTest, GivenUninitializedLinkerWhenExecuteIsInvokedThenErrorIsIssued) {
MockOfflineLinker mockOfflineLinker{&mockArgHelper};
::testing::internal::CaptureStdout();
const auto executionResult{mockOfflineLinker.execute()};
const auto output{::testing::internal::GetCapturedStdout()};
ASSERT_EQ(OclocErrorCode::INVALID_COMMAND_LINE, executionResult);
ASSERT_FALSE(output.empty());
}
TEST_F(OfflineLinkerTest, GivenHelpRequestWhenExecuteIsInvokedThenHelpIsPrinted) {
MockOfflineLinker mockOfflineLinker{&mockArgHelper};
mockOfflineLinker.operationMode = OperationMode::SHOW_HELP;
::testing::internal::CaptureStdout();
const auto executionResult{mockOfflineLinker.execute()};
const auto output{::testing::internal::GetCapturedStdout()};
ASSERT_EQ(OclocErrorCode::SUCCESS, executionResult);
ASSERT_FALSE(output.empty());
}
TEST_F(OfflineLinkerTest, GivenInvalidOperationModeWhenExecuteIsInvokedThenErrorIsIssued) {
MockOfflineLinker mockOfflineLinker{&mockArgHelper};
mockOfflineLinker.operationMode = static_cast<OperationMode>(7);
::testing::internal::CaptureStdout();
const auto executionResult{mockOfflineLinker.execute()};
const auto output{::testing::internal::GetCapturedStdout()};
ASSERT_EQ(OclocErrorCode::INVALID_COMMAND_LINE, executionResult);
ASSERT_FALSE(output.empty());
}
TEST_F(OfflineLinkerTest, GivenUninitializedHwInfoWhenInitIsCalledThenHwInfoIsInitialized) {
MockOfflineLinker mockOfflineLinker{&mockArgHelper};
ASSERT_EQ(IGFX_UNKNOWN, mockOfflineLinker.hwInfo.platform.eProductFamily);
const auto hwInfoInitializationResult{mockOfflineLinker.initHardwareInfo()};
ASSERT_EQ(OclocErrorCode::SUCCESS, hwInfoInitializationResult);
EXPECT_NE(IGFX_UNKNOWN, mockOfflineLinker.hwInfo.platform.eProductFamily);
}
TEST_F(OfflineLinkerTest, GivenEmptyHwInfoTableWhenInitializationIsPerformedThenItFailsOnHwInit) {
const std::string firstFilename{"some_file1.spv"};
const std::string secondFilename{"some_file2.llvmbc"};
mockArgHelperFilesMap[firstFilename] = getEmptySpirvFile();
mockArgHelperFilesMap[secondFilename] = getEmptyLlvmBcFile();
const std::vector<std::string> argv = {
"ocloc.exe",
"link",
"-file",
firstFilename,
"-file",
secondFilename};
MockOfflineLinker mockOfflineLinker{&mockArgHelper};
mockOfflineLinker.shouldReturnEmptyHardwareInfoTable = true;
::testing::internal::CaptureStdout();
const auto readingResult = mockOfflineLinker.initialize(argv.size(), argv);
const auto output{::testing::internal::GetCapturedStdout()};
EXPECT_EQ(OclocErrorCode::INVALID_DEVICE, readingResult);
const std::string expectedErrorMessage{"Error! Cannot retrieve any valid hardware information!\n"};
EXPECT_EQ(expectedErrorMessage, output);
}
TEST_F(OfflineLinkerTest, GivenMissingIgcLibraryWhenInitializationIsPerformedThenItFailsOnIgcPreparation) {
const std::string firstFilename{"some_file1.spv"};
const std::string secondFilename{"some_file2.llvmbc"};
mockArgHelperFilesMap[firstFilename] = getEmptySpirvFile();
mockArgHelperFilesMap[secondFilename] = getEmptyLlvmBcFile();
const std::vector<std::string> argv = {
"ocloc.exe",
"link",
"-file",
firstFilename,
"-file",
secondFilename};
MockOfflineLinker mockOfflineLinker{&mockArgHelper};
mockOfflineLinker.shouldFailLoadingOfIgcLib = true;
::testing::internal::CaptureStdout();
const auto readingResult = mockOfflineLinker.initialize(argv.size(), argv);
const auto output{::testing::internal::GetCapturedStdout()};
EXPECT_EQ(OclocErrorCode::OUT_OF_HOST_MEMORY, readingResult);
std::stringstream expectedErrorMessage;
expectedErrorMessage << "Error! Loading of IGC library has failed! Filename: " << Os::igcDllName << "\n";
EXPECT_EQ(expectedErrorMessage.str(), output);
}
TEST_F(OfflineLinkerTest, GivenOfflineLinkerWhenStoringValidBuildLogThenItIsSaved) {
const std::string someValidLog{"Warning: This is a build log!"};
MockOfflineLinker mockOfflineLinker{&mockArgHelper};
mockOfflineLinker.tryToStoreBuildLog(someValidLog.data(), someValidLog.size());
EXPECT_EQ(someValidLog, mockOfflineLinker.getBuildLog());
}
TEST_F(OfflineLinkerTest, GivenOfflineLinkerWhenStoringInvalidBuildLogThenItIsIgnored) {
MockOfflineLinker mockOfflineLinker{&mockArgHelper};
mockOfflineLinker.tryToStoreBuildLog(nullptr, 0);
const auto buildLog{mockOfflineLinker.getBuildLog()};
EXPECT_TRUE(buildLog.empty());
// Invalid size has been passed.
const char *log{"Info: This is a log!"};
mockOfflineLinker.tryToStoreBuildLog(log, 0);
const auto buildLog2{mockOfflineLinker.getBuildLog()};
EXPECT_TRUE(buildLog2.empty());
}
TEST_F(OfflineLinkerTest, GivenFailingLoadingOfIgcSymbolsWhenPreparingIgcThenFailureIsReported) {
MockOfflineLinker mockOfflineLinker{&mockArgHelper};
mockOfflineLinker.shouldFailLoadingOfIgcCreateMainFunction = true;
::testing::internal::CaptureStdout();
const auto igcPreparationResult{mockOfflineLinker.prepareIgc()};
const auto output{::testing::internal::GetCapturedStdout()};
EXPECT_EQ(OclocErrorCode::OUT_OF_HOST_MEMORY, igcPreparationResult);
const std::string expectedErrorMessage{"Error! Cannot load required functions from IGC library.\n"};
EXPECT_EQ(expectedErrorMessage, output);
}
TEST_F(OfflineLinkerTest, GivenFailingCreationOfIgcMainWhenPreparingIgcThenFailureIsReported) {
MockOfflineLinker mockOfflineLinker{&mockArgHelper};
mockOfflineLinker.shouldFailCreationOfIgcMain = true;
::testing::internal::CaptureStdout();
const auto igcPreparationResult{mockOfflineLinker.prepareIgc()};
const auto output{::testing::internal::GetCapturedStdout()};
EXPECT_EQ(OclocErrorCode::OUT_OF_HOST_MEMORY, igcPreparationResult);
const std::string expectedErrorMessage{"Error! Cannot create IGC main component!\n"};
EXPECT_EQ(expectedErrorMessage, output);
}
TEST_F(OfflineLinkerTest, GivenFailingCreationOfIgcDeviceContextWhenPreparingIgcThenFailureIsReported) {
MockOfflineLinker mockOfflineLinker{&mockArgHelper};
mockOfflineLinker.shouldFailCreationOfIgcDeviceContext = true;
::testing::internal::CaptureStdout();
const auto igcPreparationResult{mockOfflineLinker.prepareIgc()};
const auto output{::testing::internal::GetCapturedStdout()};
EXPECT_EQ(OclocErrorCode::OUT_OF_HOST_MEMORY, igcPreparationResult);
const std::string expectedErrorMessage{"Error! Cannot create IGC device context!\n"};
EXPECT_EQ(expectedErrorMessage, output);
}
TEST_F(OfflineLinkerTest, GivenInvalidIgcPlatformHandleWhenPreparingIgcThenFailureIsReported) {
MockOfflineLinker mockOfflineLinker{&mockArgHelper};
mockOfflineLinker.shouldReturnInvalidIgcPlatformHandle = true;
::testing::internal::CaptureStdout();
const auto igcPreparationResult{mockOfflineLinker.prepareIgc()};
const auto output{::testing::internal::GetCapturedStdout()};
EXPECT_EQ(OclocErrorCode::OUT_OF_HOST_MEMORY, igcPreparationResult);
const std::string expectedErrorMessage{"Error! IGC device context has not been properly created!\n"};
EXPECT_EQ(expectedErrorMessage, output);
}
TEST_F(OfflineLinkerTest, GivenInvalidIgcGTSystemInfoHandleWhenPreparingIgcThenFailureIsReported) {
MockOfflineLinker mockOfflineLinker{&mockArgHelper};
mockOfflineLinker.shouldReturnInvalidGTSystemInfoHandle = true;
::testing::internal::CaptureStdout();
const auto igcPreparationResult{mockOfflineLinker.prepareIgc()};
const auto output{::testing::internal::GetCapturedStdout()};
EXPECT_EQ(OclocErrorCode::OUT_OF_HOST_MEMORY, igcPreparationResult);
const std::string expectedErrorMessage{"Error! IGC device context has not been properly created!\n"};
EXPECT_EQ(expectedErrorMessage, output);
}
} // namespace NEO

View File

@ -0,0 +1,31 @@
/*
* Copyright (C) 2022 Intel Corporation
*
* SPDX-License-Identifier: MIT
*
*/
#pragma once
#include "gmock/gmock.h"
#include "mock/mock_argument_helper.h"
#include "mock/mock_offline_linker.h"
namespace NEO {
class OfflineLinkerTest : public ::testing::Test {
public:
void SetUp() override;
void TearDown() override;
std::string getEmptySpirvFile() const;
std::string getEmptyLlvmBcFile() const;
MockOfflineLinker::InputFileContent createFileContent(const std::string &content, IGC::CodeType::CodeType_t codeType) const;
protected:
MockOclocArgHelper::FilesMap mockArgHelperFilesMap{};
MockOclocArgHelper mockArgHelper{mockArgHelperFilesMap};
char binaryToReturn[8]{7, 7, 7, 7, 0, 1, 2, 3};
};
} // namespace NEO