Implement ULTs for IgaWrapper

This change:
- implements mock for functions from IGA DLL
- implements ULTs for IgaWrapper
- implements RAII wrapper for GTEST's capture of stdout
- adds ASAN and TSAN flags to ocloc_tests

Related-To: NEO-6834
Signed-off-by: Patryk Wrobel <patryk.wrobel@intel.com>
This commit is contained in:
Patryk Wrobel 2022-04-15 11:13:33 +00:00 committed by Compute-Runtime-Automation
parent 303c12bc5b
commit a8680c0b82
12 changed files with 820 additions and 42 deletions

View File

@ -53,8 +53,12 @@ set(IGDRCL_SRCS_offline_compiler_tests
${CMAKE_CURRENT_SOURCE_DIR}/CMakeLists.txt
${CMAKE_CURRENT_SOURCE_DIR}/decoder/decoder_tests.cpp
${CMAKE_CURRENT_SOURCE_DIR}/decoder/encoder_tests.cpp
${CMAKE_CURRENT_SOURCE_DIR}/decoder/iga_wrapper_tests.cpp
${CMAKE_CURRENT_SOURCE_DIR}/decoder/iga_wrapper_tests.h
${CMAKE_CURRENT_SOURCE_DIR}/environment.h
${CMAKE_CURRENT_SOURCE_DIR}/main.cpp
${CMAKE_CURRENT_SOURCE_DIR}/mock/mock_iga_dll.cpp
${CMAKE_CURRENT_SOURCE_DIR}/mock/mock_iga_dll.h
${CMAKE_CURRENT_SOURCE_DIR}/ocloc_api_tests.cpp
${CMAKE_CURRENT_SOURCE_DIR}/ocloc_fatbinary_tests.cpp
${CMAKE_CURRENT_SOURCE_DIR}/ocloc_fatbinary_tests.h
@ -68,6 +72,7 @@ set(IGDRCL_SRCS_offline_compiler_tests
${CMAKE_CURRENT_SOURCE_DIR}/offline_compiler_tests.h
${CMAKE_CURRENT_SOURCE_DIR}/offline_linker_tests.cpp
${CMAKE_CURRENT_SOURCE_DIR}/offline_linker_tests.h
${CMAKE_CURRENT_SOURCE_DIR}/stdout_capturer.h
${NEO_SHARED_DIRECTORY}/helpers/abort.cpp
${NEO_SHARED_DIRECTORY}/helpers/file_io.cpp
${NEO_SHARED_DIRECTORY}/memory_manager/deferred_deleter.cpp
@ -124,7 +129,7 @@ endif()
get_property(CLOC_LIB_FOLDER TARGET ocloc_lib PROPERTY FOLDER)
get_property(CLOC_LIB_COMPILE_FLAGS TARGET ocloc_lib PROPERTY COMPILE_FLAGS)
set_property(TARGET ocloc_tests PROPERTY FOLDER ${CLOC_LIB_FOLDER})
set_property(TARGET ocloc_tests APPEND_STRING PROPERTY COMPILE_FLAGS ${CLOC_LIB_COMPILE_FLAGS})
set_property(TARGET ocloc_tests APPEND_STRING PROPERTY COMPILE_FLAGS ${CLOC_LIB_COMPILE_FLAGS} ${ASAN_FLAGS} ${TSAN_FLAGS})
string(TOLOWER ${DEFAULT_TESTED_PLATFORM} CLOC_LIB_DEFAULT_DEVICE)

View File

@ -0,0 +1,314 @@
/*
* Copyright (C) 2022 Intel Corporation
*
* SPDX-License-Identifier: MIT
*
*/
#include "iga_wrapper_tests.h"
#include "opencl/test/unit_test/offline_compiler/mock/mock_iga_dll_guard.h"
#include "opencl/test/unit_test/offline_compiler/stdout_capturer.h"
#include <array>
namespace NEO {
TEST_F(IgaWrapperTest, GivenInvalidPathToIgaLibraryWhenDisassemblingGenIsaThenFalseIsReturnedAndErrorMessageIsPrinted) {
MockIgaDllGuard mockIgaDllGuard{"some_invalid_path_to_library"};
mockIgaDllGuard.enable();
const std::string kernel{"INPUT TO DISASM"};
std::string out;
StdoutCapturer capturer{};
const auto result = testedIgaWrapper.tryDisassembleGenISA(kernel.c_str(), static_cast<uint32_t>(kernel.size()), out);
const auto output{capturer.acquireOutput()};
EXPECT_FALSE(result);
EXPECT_EQ("Warning: couldn't load iga - kernel binaries won't be disassembled.\n", output);
EXPECT_EQ(0, igaDllMock->contextCreateCalledCount);
}
TEST_F(IgaWrapperTest, GivenContextCreationFailureWhenDisassemblingGenIsaThenFalseIsReturnedAndErrorMessageIsPrinted) {
igaDllMock->contextCreateReturnValue = igaStatusFailure;
igaDllMock->statusToStringReturnValue = "SOME_CONTEXT_ERROR";
const std::string kernel{"INPUT TO DISASM"};
std::string out;
StdoutCapturer capturer{};
const auto result = testedIgaWrapper.tryDisassembleGenISA(kernel.c_str(), static_cast<uint32_t>(kernel.size()), out);
const auto output{capturer.acquireOutput()};
EXPECT_FALSE(result);
EXPECT_EQ("Error while creating IGA Context! Error msg: SOME_CONTEXT_ERROR", output);
EXPECT_EQ(1, igaDllMock->contextCreateCalledCount);
EXPECT_EQ(1, igaDllMock->statusToStringCalledCount);
}
TEST_F(IgaWrapperTest, GivenContextCreationSuccessAndDisassemblationFailureAndNoContextErrorsWhenDisassemblingGenIsaThenFalseIsReturnedAndErrorMessageIsPrinted) {
const std::array mockSetupFlags = {
&IgaDllMock::shouldContextGetErrorsReturnNullptrAndNonZeroSize,
&IgaDllMock::shouldContextGetErrorsReturnZeroSizeAndNonNullptr};
for (const auto &mockSetupFlag : mockSetupFlags) {
igaDllMock = nullptr;
igaDllMock = std::make_unique<IgaDllMock>();
igaDllMock->contextCreateReturnValue = igaStatusSuccess;
igaDllMock->disassembleReturnValue = igaStatusFailure;
igaDllMock->statusToStringReturnValue = "SOME_DISASSEMBLE_ERROR";
igaDllMock->contextGetErrorsReturnValue = igaStatusFailure;
igaDllMock->contextReleaseReturnValue = igaStatusSuccess;
*igaDllMock.*mockSetupFlag = true;
const std::string kernel{"INPUT TO DISASM"};
std::string out;
StdoutCapturer capturer{};
const auto result = testedIgaWrapper.tryDisassembleGenISA(kernel.c_str(), static_cast<uint32_t>(kernel.size()), out);
const auto output{capturer.acquireOutput()};
EXPECT_FALSE(result);
EXPECT_EQ("Error while disassembling with IGA!\nStatus msg: SOME_DISASSEMBLE_ERROR\n", output);
EXPECT_EQ(1, igaDllMock->contextCreateCalledCount);
EXPECT_EQ(1, igaDllMock->disassembleCalledCount);
EXPECT_EQ(1, igaDllMock->statusToStringCalledCount);
EXPECT_EQ(1, igaDllMock->contextGetErrorsCalledCount);
EXPECT_EQ(1, igaDllMock->contextReleaseCalledCount);
}
}
TEST_F(IgaWrapperTest, GivenContextCreationSuccessAndDisassemblationFailureAndContextErrorsWhenDisassemblingGenIsaThenFalseIsReturnedAndErrorMessageIsPrinted) {
igaDllMock->contextCreateReturnValue = igaStatusSuccess;
igaDllMock->disassembleReturnValue = igaStatusFailure;
igaDllMock->statusToStringReturnValue = "SOME_DISASSEMBLE_ERROR";
igaDllMock->contextGetErrorsReturnValue = igaStatusSuccess;
igaDllMock->contextGetErrorsOutputString = "SPECIFIC_ERROR";
igaDllMock->contextReleaseReturnValue = igaStatusSuccess;
const std::string kernel{"INPUT TO DISASM"};
std::string out;
StdoutCapturer capturer{};
const auto result = testedIgaWrapper.tryDisassembleGenISA(kernel.c_str(), static_cast<uint32_t>(kernel.size()), out);
const auto output{capturer.acquireOutput()};
EXPECT_FALSE(result);
EXPECT_EQ("Error while disassembling with IGA!\nStatus msg: SOME_DISASSEMBLE_ERROR\n"
"Errors: SPECIFIC_ERROR\n",
output);
EXPECT_EQ(1, igaDllMock->contextCreateCalledCount);
EXPECT_EQ(1, igaDllMock->disassembleCalledCount);
EXPECT_EQ(1, igaDllMock->statusToStringCalledCount);
EXPECT_EQ(1, igaDllMock->contextGetErrorsCalledCount);
EXPECT_EQ(1, igaDllMock->contextReleaseCalledCount);
}
TEST_F(IgaWrapperTest, GivenContextCreationSuccessAndDisassemblationSuccessAndNoWarningsWhenDisassemblingGenIsaThenTrueIsReturnedAndNoMessageIsPrinted) {
const std::array mockSetupFlags = {
&IgaDllMock::shouldContextGetWarningsReturnNullptrAndNonZeroSize,
&IgaDllMock::shouldContextGetWarningsReturnZeroSizeAndNonNullptr};
for (const auto &mockSetupFlag : mockSetupFlags) {
igaDllMock = nullptr;
igaDllMock = std::make_unique<IgaDllMock>();
igaDllMock->contextCreateReturnValue = igaStatusSuccess;
igaDllMock->disassembleReturnValue = igaStatusSuccess;
igaDllMock->contextGetWarningsReturnValue = igaStatusSuccess;
igaDllMock->contextReleaseReturnValue = igaStatusSuccess;
igaDllMock->disassembleOutputKernelText = "Some kernel text!";
*igaDllMock.*mockSetupFlag = true;
const std::string kernel{"INPUT TO DISASM"};
std::string out;
StdoutCapturer capturer{};
const auto result = testedIgaWrapper.tryDisassembleGenISA(kernel.c_str(), static_cast<uint32_t>(kernel.size()), out);
const auto output{capturer.acquireOutput()};
EXPECT_TRUE(result);
EXPECT_TRUE(output.empty()) << output;
EXPECT_EQ(1, igaDllMock->contextCreateCalledCount);
EXPECT_EQ(1, igaDllMock->disassembleCalledCount);
EXPECT_EQ(0, igaDllMock->statusToStringCalledCount);
EXPECT_EQ(0, igaDllMock->contextGetErrorsCalledCount);
EXPECT_EQ(1, igaDllMock->contextGetWarningsCalledCount);
EXPECT_EQ(1, igaDllMock->contextReleaseCalledCount);
EXPECT_EQ("Some kernel text!", out);
}
}
TEST_F(IgaWrapperTest, GivenContextCreationSuccessAndDisassemblationSuccessAndWarningsWhenDisassemblingGenIsaThenTrueIsReturnedAndWarningIsPrinted) {
igaDllMock->contextCreateReturnValue = igaStatusSuccess;
igaDllMock->disassembleReturnValue = igaStatusSuccess;
igaDllMock->contextGetWarningsReturnValue = igaStatusSuccess;
igaDllMock->contextGetWarningsOutputString = "SOME_WARNING_MESSAGE";
igaDllMock->contextReleaseReturnValue = igaStatusSuccess;
igaDllMock->disassembleOutputKernelText = "Some kernel text!";
const std::string kernel{"INPUT TO DISASM"};
std::string out;
StdoutCapturer capturer{};
const auto result = testedIgaWrapper.tryDisassembleGenISA(kernel.c_str(), static_cast<uint32_t>(kernel.size()), out);
const auto output{capturer.acquireOutput()};
EXPECT_TRUE(result);
EXPECT_EQ("Warnings: SOME_WARNING_MESSAGE\n", output);
EXPECT_EQ(1, igaDllMock->contextCreateCalledCount);
EXPECT_EQ(1, igaDllMock->disassembleCalledCount);
EXPECT_EQ(0, igaDllMock->statusToStringCalledCount);
EXPECT_EQ(0, igaDllMock->contextGetErrorsCalledCount);
EXPECT_EQ(1, igaDllMock->contextGetWarningsCalledCount);
EXPECT_EQ(1, igaDllMock->contextReleaseCalledCount);
EXPECT_EQ("Some kernel text!", out);
}
TEST_F(IgaWrapperTest, GivenInvalidPathToIgaLibraryWhenAssemblingGenIsaThenFalseIsReturnedAndErrorMessageIsPrinted) {
MockIgaDllGuard mockIgaDllGuard{"some_invalid_path_to_library"};
mockIgaDllGuard.enable();
const std::string inAsm{"Input ASM"};
std::string out;
StdoutCapturer capturer{};
const auto result = testedIgaWrapper.tryAssembleGenISA(inAsm, out);
const auto output{capturer.acquireOutput()};
EXPECT_FALSE(result);
EXPECT_EQ("Warning: couldn't load iga - kernel binaries won't be assembled.\n", output);
EXPECT_EQ(0, igaDllMock->contextCreateCalledCount);
}
TEST_F(IgaWrapperTest, GivenContextCreationFailureWhenAssemblingGenIsaThenFalseIsReturnedAndErrorMessageIsPrinted) {
igaDllMock->contextCreateReturnValue = igaStatusFailure;
igaDllMock->statusToStringReturnValue = "SOME_CONTEXT_ERROR";
const std::string inAsm{"Input ASM"};
std::string out;
StdoutCapturer capturer{};
const auto result = testedIgaWrapper.tryAssembleGenISA(inAsm, out);
const auto output{capturer.acquireOutput()};
EXPECT_FALSE(result);
EXPECT_EQ("Error while creating IGA Context! Error msg: SOME_CONTEXT_ERROR", output);
EXPECT_EQ(1, igaDllMock->contextCreateCalledCount);
EXPECT_EQ(1, igaDllMock->statusToStringCalledCount);
}
TEST_F(IgaWrapperTest, GivenContextCreationSuccessAndAssemblationFailureAndContextErrorsWhenAssemblingGenIsaThenFalseIsReturnedAndErrorMessageIsPrinted) {
igaDllMock->contextCreateReturnValue = igaStatusSuccess;
igaDllMock->assembleReturnValue = igaStatusFailure;
igaDllMock->statusToStringReturnValue = "SOME_ASSEMBLE_ERROR";
igaDllMock->contextGetErrorsReturnValue = igaStatusSuccess;
igaDllMock->contextGetErrorsOutputString = "SPECIFIC_ERROR";
igaDllMock->contextReleaseReturnValue = igaStatusSuccess;
const std::string inAsm{"Input ASM"};
std::string out;
StdoutCapturer capturer{};
const auto result = testedIgaWrapper.tryAssembleGenISA(inAsm, out);
const auto output{capturer.acquireOutput()};
EXPECT_FALSE(result);
EXPECT_EQ("Error while assembling with IGA!\nStatus msg: SOME_ASSEMBLE_ERROR\n"
"Errors: SPECIFIC_ERROR\n",
output);
EXPECT_EQ(1, igaDllMock->contextCreateCalledCount);
EXPECT_EQ(1, igaDllMock->assembleCalledCount);
EXPECT_EQ(1, igaDllMock->statusToStringCalledCount);
EXPECT_EQ(1, igaDllMock->contextGetErrorsCalledCount);
EXPECT_EQ(1, igaDllMock->contextReleaseCalledCount);
}
TEST_F(IgaWrapperTest, GivenContextCreationSuccessAndAssemblationSuccessAndNoWarningsWhenAssemblingGenIsaThenTrueIsReturnedAndLogsAreNotPrinted) {
igaDllMock->contextCreateReturnValue = igaStatusSuccess;
igaDllMock->assembleReturnValue = igaStatusSuccess;
igaDllMock->assembleOutput = "DISASSEMBLED OUTPUT";
igaDllMock->contextGetErrorsReturnValue = igaStatusSuccess;
igaDllMock->contextReleaseReturnValue = igaStatusSuccess;
const std::string inAsm{"Input ASM"};
std::string out;
StdoutCapturer capturer{};
const auto result = testedIgaWrapper.tryAssembleGenISA(inAsm, out);
const auto output{capturer.acquireOutput()};
EXPECT_TRUE(result);
EXPECT_TRUE(output.empty()) << output;
EXPECT_EQ(1, igaDllMock->contextCreateCalledCount);
EXPECT_EQ(1, igaDllMock->assembleCalledCount);
EXPECT_EQ(0, igaDllMock->statusToStringCalledCount);
EXPECT_EQ(0, igaDllMock->contextGetErrorsCalledCount);
EXPECT_EQ(1, igaDllMock->contextGetWarningsCalledCount);
EXPECT_EQ(1, igaDllMock->contextReleaseCalledCount);
EXPECT_STREQ("DISASSEMBLED OUTPUT", out.c_str());
}
TEST_F(IgaWrapperTest, GivenIgcWrapperWhenLoadingLibraryTwiceWithPathChangeInTheMiddleThenLazyLoadingOccursAndLibraryIsLoadedOnlyOnce) {
struct TestedIgaWrapper : public IgaWrapper {
using IgaWrapper::tryLoadIga;
};
TestedIgaWrapper igaWrapper{};
EXPECT_TRUE(igaWrapper.tryLoadIga());
MockIgaDllGuard mockIgaDllGuard{"some_invalid_path_to_library"};
mockIgaDllGuard.enable();
// Lazy loading should prevent loading from wrong path.
EXPECT_TRUE(igaWrapper.tryLoadIga());
}
TEST_F(IgaWrapperTest, GivenIgcWrapperWhenCallingSetGfxCoreMultipleTimesThenFirstValidGfxCoreFamilyIsPreserved) {
ASSERT_FALSE(testedIgaWrapper.isKnownPlatform());
constexpr auto invalidGfxCoreFamily = IGFX_MAX_CORE;
testedIgaWrapper.setGfxCore(invalidGfxCoreFamily);
EXPECT_FALSE(testedIgaWrapper.isKnownPlatform());
testedIgaWrapper.setGfxCore(IGFX_GEN11LP_CORE);
EXPECT_TRUE(testedIgaWrapper.isKnownPlatform());
// Expect that a valid family is preserved.
testedIgaWrapper.setGfxCore(invalidGfxCoreFamily);
EXPECT_TRUE(testedIgaWrapper.isKnownPlatform());
}
TEST_F(IgaWrapperTest, GivenIgcWrapperWhenCallingSetProductFamilyMultipleTimesThenFirstValidProductFamilyIsPreserved) {
ASSERT_FALSE(testedIgaWrapper.isKnownPlatform());
constexpr auto invalidProductFamily = IGFX_MAX_PRODUCT;
testedIgaWrapper.setProductFamily(invalidProductFamily);
EXPECT_FALSE(testedIgaWrapper.isKnownPlatform());
testedIgaWrapper.setProductFamily(IGFX_SKYLAKE);
EXPECT_TRUE(testedIgaWrapper.isKnownPlatform());
// Expect that a valid family is preserved.
testedIgaWrapper.setProductFamily(invalidProductFamily);
EXPECT_TRUE(testedIgaWrapper.isKnownPlatform());
}
} // namespace NEO

View File

@ -0,0 +1,35 @@
/*
* Copyright (C) 2022 Intel Corporation
*
* SPDX-License-Identifier: MIT
*
*/
#pragma once
#include "shared/offline_compiler/source/decoder/helper.h"
#include "shared/offline_compiler/source/decoder/iga_wrapper.h"
#include "opencl/test/unit_test/offline_compiler/mock/mock_iga_dll.h"
#include "gtest/gtest.h"
namespace NEO {
class IgaWrapperTest : public ::testing::Test {
public:
void SetUp() override {
igaDllMock = std::make_unique<IgaDllMock>();
testedIgaWrapper.setMessagePrinter(messagePrinter);
}
protected:
static constexpr int igaStatusSuccess{0};
static constexpr int igaStatusFailure{1};
std::unique_ptr<IgaDllMock> igaDllMock{};
MessagePrinter messagePrinter{};
IgaWrapper testedIgaWrapper{};
};
} // namespace NEO

View File

@ -1,5 +1,5 @@
/*
* Copyright (C) 2018-2021 Intel Corporation
* Copyright (C) 2018-2022 Intel Corporation
*
* SPDX-License-Identifier: MIT
*
@ -13,11 +13,12 @@
#include "shared/test/common/mocks/mock_compilers.h"
#include "gtest/gtest.h"
#include "mock/mock_iga_dll_guard.h"
class Environment : public ::testing::Environment {
public:
Environment(const std::string &devicePrefix, const std::string &familyNameWithType)
: libraryFrontEnd(nullptr), libraryIGC(nullptr), devicePrefix(devicePrefix), familyNameWithType(familyNameWithType) {
: devicePrefix(devicePrefix), familyNameWithType(familyNameWithType) {
}
void SetInputFileName(
@ -31,19 +32,16 @@ class Environment : public ::testing::Environment {
}
void SetUp() override {
mockIgaDllGuard.enable();
mockCompilerGuard.Enable();
SetInputFileName("copybuffer");
}
void TearDown() override {
delete libraryFrontEnd;
delete libraryIGC;
mockCompilerGuard.Disable();
mockIgaDllGuard.disable();
}
NEO::OsLibrary *libraryFrontEnd;
NEO::OsLibrary *libraryIGC;
NEO::MockCompilerDebugVars igcDebugVars;
NEO::MockCompilerDebugVars fclDebugVars;
@ -51,6 +49,7 @@ class Environment : public ::testing::Environment {
void (*fclSetDebugVarsFPtr)(NEO::MockCompilerDebugVars &debugVars);
NEO::MockCompilerEnableGuard mockCompilerGuard;
NEO::MockIgaDllGuard mockIgaDllGuard;
const std::string devicePrefix;
const std::string familyNameWithType;

View File

@ -0,0 +1,212 @@
/*
* Copyright (C) 2022 Intel Corporation
*
* SPDX-License-Identifier: MIT
*
*/
#include "mock_iga_dll.h"
#include "shared/source/helpers/debug_helpers.h"
#include <cstdlib>
#include <iostream>
#include <sstream>
#include <stdexcept>
#define REQUIRE_NOT_NULL(pointer) throwIfNullptr(pointer, #pointer, __LINE__, __FILE__)
extern "C" IGA_API iga_status_t iga_assemble(
iga_context_t ctx,
const iga_assemble_options_t *opts,
const char *kernelText,
void **output,
uint32_t *outputSize) {
return NEO::IgaDllMock::getUsedInstance().assemble(ctx, opts, kernelText, output, outputSize);
}
extern "C" IGA_API iga_status_t iga_context_create(
const iga_context_options_t *opts,
iga_context_t *ctx) {
return NEO::IgaDllMock::getUsedInstance().contextCreate(opts, ctx);
}
extern "C" IGA_API iga_status_t iga_context_get_errors(
iga_context_t ctx,
const iga_diagnostic_t **ds,
uint32_t *dsLen) {
return NEO::IgaDllMock::getUsedInstance().contextGetErrors(ctx, ds, dsLen);
}
extern "C" IGA_API iga_status_t iga_context_get_warnings(
iga_context_t ctx,
const iga_diagnostic_t **ds,
uint32_t *dsLen) {
return NEO::IgaDllMock::getUsedInstance().contextGetWarnings(ctx, ds, dsLen);
}
extern "C" IGA_API iga_status_t iga_context_release(iga_context_t ctx) {
return NEO::IgaDllMock::getUsedInstance().contextRelease(ctx);
}
extern "C" IGA_API iga_status_t iga_disassemble(
iga_context_t ctx,
const iga_disassemble_options_t *opts,
const void *input,
uint32_t inputSize,
const char *(*fmtLabelName)(int32_t, void *),
void *fmtLabelCtx,
char **kernelText) {
return NEO::IgaDllMock::getUsedInstance().disassemble(ctx, opts, input, inputSize, fmtLabelName, fmtLabelCtx, kernelText);
}
extern "C" IGA_API const char *iga_status_to_string(const iga_status_t st) {
return NEO::IgaDllMock::getUsedInstance().statusToString(st);
}
namespace NEO {
template <typename T>
void throwIfNullptr(const T *ptr, const char *variableName, const int lineNumber, const char *file) {
if (!ptr) {
std::stringstream errorMessage{};
errorMessage << "IgaDllMock expected a valid pointer, but received NULL!\n"
<< "Variable: " << variableName << '\n'
<< "File: " << file << '\n'
<< "Line:" << lineNumber << '\n';
throw std::invalid_argument{errorMessage.str()};
}
}
IgaDllMock::IgaDllMock() {
if (usedInstance) {
std::cerr << "Logic error! Used instance of IgaDllMock already registered! Aborting..." << std::endl;
std::exit(EXIT_FAILURE);
}
usedInstance = this;
}
IgaDllMock::~IgaDllMock() {
usedInstance = nullptr;
}
IgaDllMock &IgaDllMock::getUsedInstance() {
if (!usedInstance) {
std::cerr << "Logic error! Used instance of IgaDllMock has not been registered! Aborting..." << std::endl;
std::exit(EXIT_FAILURE);
}
return *usedInstance;
}
iga_status_t IgaDllMock::assemble(
iga_context_t ctx,
const iga_assemble_options_t *opts,
const char *kernelText,
void **output,
uint32_t *outputSize) {
++assembleCalledCount;
if (assembleOutput.has_value()) {
REQUIRE_NOT_NULL(output);
REQUIRE_NOT_NULL(outputSize);
*output = assembleOutput->data();
*outputSize = static_cast<uint32_t>(assembleOutput->size() + 1u);
}
return static_cast<iga_status_t>(assembleReturnValue);
}
iga_status_t IgaDllMock::contextCreate(
const iga_context_options_t *opts,
iga_context_t *ctx) {
++contextCreateCalledCount;
return static_cast<iga_status_t>(contextCreateReturnValue);
}
iga_status_t IgaDllMock::contextGetErrors(
iga_context_t ctx,
const iga_diagnostic_t **ds,
uint32_t *dsLen) {
++contextGetErrorsCalledCount;
REQUIRE_NOT_NULL(ds);
REQUIRE_NOT_NULL(dsLen);
if (shouldContextGetErrorsReturnZeroSizeAndNonNullptr) {
*ds = &contextGetErrorsOutput;
*dsLen = 0;
} else if (shouldContextGetErrorsReturnNullptrAndNonZeroSize) {
*ds = nullptr;
*dsLen = 1;
} else if (contextGetErrorsOutputString.has_value()) {
contextGetErrorsOutput.message = contextGetErrorsOutputString->c_str();
*ds = &contextGetErrorsOutput;
*dsLen = static_cast<uint32_t>(contextGetErrorsOutputString->size() + 1);
} else {
*ds = nullptr;
*dsLen = 0;
}
return static_cast<iga_status_t>(contextGetErrorsReturnValue);
}
iga_status_t IgaDllMock::contextGetWarnings(
iga_context_t ctx,
const iga_diagnostic_t **ds,
uint32_t *dsLen) {
++contextGetWarningsCalledCount;
REQUIRE_NOT_NULL(ds);
REQUIRE_NOT_NULL(dsLen);
if (shouldContextGetWarningsReturnZeroSizeAndNonNullptr) {
*ds = &contextGetWarningsOutput;
*dsLen = 0;
} else if (shouldContextGetWarningsReturnNullptrAndNonZeroSize) {
*ds = nullptr;
*dsLen = 1;
} else if (contextGetWarningsOutputString.has_value()) {
contextGetWarningsOutput.message = contextGetWarningsOutputString->c_str();
*ds = &contextGetWarningsOutput;
*dsLen = static_cast<uint32_t>(contextGetWarningsOutputString->size() + 1);
} else {
*ds = nullptr;
*dsLen = 0;
}
return static_cast<iga_status_t>(contextGetWarningsReturnValue);
}
iga_status_t IgaDllMock::contextRelease(iga_context_t ctx) {
++contextReleaseCalledCount;
return static_cast<iga_status_t>(contextReleaseReturnValue);
}
iga_status_t IgaDllMock::disassemble(
iga_context_t ctx,
const iga_disassemble_options_t *opts,
const void *input,
uint32_t inputSize,
const char *(*fmtLabelName)(int32_t, void *),
void *fmtLabelCtx,
char **kernelText) {
++disassembleCalledCount;
if (disassembleOutputKernelText.has_value()) {
REQUIRE_NOT_NULL(kernelText);
*kernelText = disassembleOutputKernelText->data();
}
return static_cast<iga_status_t>(disassembleReturnValue);
}
const char *IgaDllMock::statusToString(const iga_status_t st) {
++statusToStringCalledCount;
return statusToStringReturnValue.c_str();
}
} // namespace NEO

View File

@ -0,0 +1,101 @@
/*
* Copyright (C) 2022 Intel Corporation
*
* SPDX-License-Identifier: MIT
*
*/
#pragma once
#define IGA_BUILDING_DLL
#include "igad.h"
#undef IGA_BUILDING_DLL
#include <cstdint>
#include <optional>
#include <string>
namespace NEO {
class IgaDllMock {
public:
IgaDllMock();
~IgaDllMock();
IgaDllMock(const IgaDllMock &other) = delete;
IgaDllMock(IgaDllMock &&other) = delete;
IgaDllMock &operator=(const IgaDllMock &other) = delete;
IgaDllMock &operator=(IgaDllMock &&other) = delete;
static IgaDllMock &getUsedInstance();
iga_status_t assemble(
iga_context_t ctx,
const iga_assemble_options_t *opts,
const char *kernelText,
void **output,
uint32_t *outputSize);
iga_status_t contextCreate(
const iga_context_options_t *opts,
iga_context_t *ctx);
iga_status_t contextGetErrors(
iga_context_t ctx,
const iga_diagnostic_t **ds,
uint32_t *dsLen);
iga_status_t contextGetWarnings(
iga_context_t ctx,
const iga_diagnostic_t **ds,
uint32_t *dsLen);
iga_status_t contextRelease(iga_context_t ctx);
iga_status_t disassemble(
iga_context_t ctx,
const iga_disassemble_options_t *opts,
const void *input,
uint32_t inputSize,
const char *(*fmtLabelName)(int32_t, void *),
void *fmtLabelCtx,
char **kernelText);
const char *statusToString(const iga_status_t st);
int assembleCalledCount{0};
int assembleReturnValue{0};
std::optional<std::string> assembleOutput{};
int contextCreateCalledCount{0};
int contextCreateReturnValue{0};
int contextGetErrorsCalledCount{0};
int contextGetErrorsReturnValue{0};
iga_diagnostic_t contextGetErrorsOutput{};
std::optional<std::string> contextGetErrorsOutputString{};
bool shouldContextGetErrorsReturnZeroSizeAndNonNullptr{false};
bool shouldContextGetErrorsReturnNullptrAndNonZeroSize{false};
int contextGetWarningsCalledCount{0};
int contextGetWarningsReturnValue{0};
iga_diagnostic_t contextGetWarningsOutput{};
std::optional<std::string> contextGetWarningsOutputString{};
bool shouldContextGetWarningsReturnZeroSizeAndNonNullptr{false};
bool shouldContextGetWarningsReturnNullptrAndNonZeroSize{false};
int contextReleaseCalledCount{0};
int contextReleaseReturnValue{0};
int disassembleCalledCount{0};
int disassembleReturnValue{0};
std::optional<std::string> disassembleOutputKernelText{};
int statusToStringCalledCount{0};
std::string statusToStringReturnValue{};
private:
inline static IgaDllMock *usedInstance{nullptr};
};
} // namespace NEO

View File

@ -0,0 +1,40 @@
/*
* Copyright (C) 2022 Intel Corporation
*
* SPDX-License-Identifier: MIT
*
*/
#pragma once
#include "shared/offline_compiler/source/ocloc_dll_options.h"
#include <utility>
namespace NEO {
class MockIgaDllGuard {
public:
MockIgaDllGuard(const char *newPath = "") : newDllPath{newPath} {
}
~MockIgaDllGuard() {
disable();
}
void enable() {
oldDllPath = std::exchange(Os::igaDllName, newDllPath);
}
void disable() {
if (oldDllPath) {
Os::igaDllName = std::exchange(oldDllPath, nullptr);
}
}
private:
const char *oldDllPath{};
const char *newDllPath{};
};
} // namespace NEO

View File

@ -0,0 +1,42 @@
/*
* Copyright (C) 2022 Intel Corporation
*
* SPDX-License-Identifier: MIT
*
*/
#pragma once
#include "gtest/gtest.h"
#include <string>
namespace NEO {
/*
* This class is a RAII wrapper for GTEST's mechanism, which allows capturing stdout.
* We must ensure that GetCapturedStdout() is called after CaptureStdout().
* If it is not invoked, then next call to CaptureStdout() will cause abort of the test application.
*/
class StdoutCapturer {
public:
StdoutCapturer() {
::testing::internal::CaptureStdout();
}
~StdoutCapturer() {
if (!outputAcquired) {
::testing::internal::GetCapturedStdout();
}
}
std::string acquireOutput() {
outputAcquired = true;
return ::testing::internal::GetCapturedStdout();
}
private:
bool outputAcquired{false};
};
} // namespace NEO

View File

@ -60,6 +60,8 @@ set(CLOC_LIB_SRCS_LIB
${OCLOC_DIRECTORY}/source/ocloc_api.h
${OCLOC_DIRECTORY}/source/ocloc_arg_helper.cpp
${OCLOC_DIRECTORY}/source/ocloc_arg_helper.h
${OCLOC_DIRECTORY}/source/ocloc_dll_options.cpp
${OCLOC_DIRECTORY}/source/ocloc_dll_options.h
${OCLOC_DIRECTORY}/source/ocloc_error_code.h
${OCLOC_DIRECTORY}/source/ocloc_fatbinary.cpp
${OCLOC_DIRECTORY}/source/ocloc_fatbinary.h
@ -187,7 +189,7 @@ target_include_directories(${OCLOC_NAME}_lib BEFORE PRIVATE ${CLOC_LIB_INCLUDES}
target_include_directories(${OCLOC_NAME}_lib BEFORE PRIVATE ${IGA_INCLUDE_DIR})
target_compile_definitions(${OCLOC_NAME}_lib PUBLIC ${CLOC_LIB_LIB_FLAGS_DEFINITIONS} ${SUPPORTED_CORE_FLAGS_DEFINITONS} DEFAULT_PLATFORM=${DEFAULT_SUPPORTED_PLATFORM}
IGA_LIBRARY_NAME=${CMAKE_SHARED_LIBRARY_PREFIX}${IGA_LIBRARY_NAME}${CMAKE_SHARED_LIBRARY_SUFFIX}
IGA_LIBRARY_NAME="${CMAKE_SHARED_LIBRARY_PREFIX}${IGA_LIBRARY_NAME}${CMAKE_SHARED_LIBRARY_SUFFIX}"
)
target_compile_definitions(${OCLOC_NAME}_lib PUBLIC ${NEO__IGC_COMPILE_DEFINITIONS})

View File

@ -1,5 +1,5 @@
/*
* Copyright (C) 2019-2021 Intel Corporation
* Copyright (C) 2019-2022 Intel Corporation
*
* SPDX-License-Identifier: MIT
*
@ -7,8 +7,8 @@
#include "iga_wrapper.h"
#include "shared/offline_compiler/source/ocloc_dll_options.h"
#include "shared/source/helpers/hw_info.h"
#include "shared/source/os_interface/os_inc_base.h"
#include "shared/source/os_interface/os_library.h"
#include "helper.h"
@ -43,16 +43,14 @@ struct IgaWrapper::Impl {
iga.OptsContext.cb = sizeof(igaLib.OptsContext);
iga.OptsContext.gen = igaGen;
#define STR2(X) #X
#define STR(X) STR2(X)
iga.library.reset(NEO::OsLibrary::load(STR(IGA_LIBRARY_NAME)));
iga.library.reset(NEO::OsLibrary::load(Os::igaDllName));
if (iga.library == nullptr) {
return;
}
#define LOAD_OR_ERROR(MEMBER, FUNC_NAME) \
if (nullptr == (iga.MEMBER = reinterpret_cast<decltype(iga.MEMBER)>(iga.library->getProcAddress(FUNC_NAME)))) { \
printf("Warning : Couldn't find %s in %s\n", FUNC_NAME, STR(IGA_LIBRARY_NAME)); \
printf("Warning : Couldn't find %s in %s\n", FUNC_NAME, Os::igaDllName); \
return; \
}
@ -65,11 +63,31 @@ struct IgaWrapper::Impl {
LOAD_OR_ERROR(statusToString, IGA_STATUS_TO_STRING_STR);
#undef LOAD_OR_ERROR
#undef STR
#undef STR2
this->igaLib = std::move(iga);
}
void printContextErrors(MessagePrinter &messagePrinter, iga_context_t &context) {
const iga_diagnostic_t *errors{};
uint32_t errorsSize{};
this->igaLib.contextGetErrors(context, &errors, &errorsSize);
if (errorsSize > 0 && errors != nullptr) {
messagePrinter.printf("Errors: %s\n", errors->message);
}
}
void printContextWarnings(MessagePrinter &messagePrinter, iga_context_t &context) {
const iga_diagnostic_t *warnings{};
uint32_t warningsSize{};
this->igaLib.contextGetWarnings(context, &warnings, &warningsSize);
if (warningsSize > 0 && warnings != nullptr) {
messagePrinter.printf("Warnings: %s\n", warnings->message);
}
}
};
IgaWrapper::IgaWrapper()
@ -100,22 +118,13 @@ bool IgaWrapper::tryDisassembleGenISA(const void *kernelPtr, uint32_t kernelSize
stat = pimpl->igaLib.disassemble(context, &disassembleOptions, kernelPtr, kernelSize, nullptr, nullptr, &pKernelText);
if (stat != 0) {
messagePrinter->printf("Error while disassembling with IGA!\nStatus msg: %s\n", pimpl->igaLib.statusToString(stat));
const iga_diagnostic_t *errors;
uint32_t size = 100;
pimpl->igaLib.contextGetErrors(context, &errors, &size);
if (errors != nullptr) {
messagePrinter->printf("Errors: %s\n", errors->message);
}
pimpl->printContextErrors(*messagePrinter, context);
pimpl->igaLib.contextRelease(context);
return false;
}
const iga_diagnostic_t *warnings;
uint32_t warningsSize = 100;
pimpl->igaLib.contextGetWarnings(context, &warnings, &warningsSize);
if (warningsSize > 0 && warnings != nullptr) {
messagePrinter->printf("Warnings: %s\n", warnings->message);
}
pimpl->printContextWarnings(*messagePrinter, context);
out = pKernelText;
pimpl->igaLib.contextRelease(context);
@ -143,24 +152,13 @@ bool IgaWrapper::tryAssembleGenISA(const std::string &inAsm, std::string &outBin
stat = pimpl->igaLib.assemble(context, &assembleOptions, inAsm.c_str(), &pOutput, &size);
if (stat != 0) {
messagePrinter->printf("Error while assembling with IGA!\nStatus msg: %s\n", pimpl->igaLib.statusToString(stat));
const iga_diagnostic_t *errors;
uint32_t size = 100;
pimpl->igaLib.contextGetErrors(context, &errors, &size);
if (errors != nullptr) {
messagePrinter->printf("Errors: %s\n", errors->message);
}
pimpl->printContextErrors(*messagePrinter, context);
pimpl->igaLib.contextRelease(context);
return false;
}
const iga_diagnostic_t *warnings;
uint32_t context_size;
pimpl->igaLib.contextGetWarnings(context, &warnings, &context_size);
if (context_size > 0 && warnings != nullptr) {
messagePrinter->printf("Warnings: %s\n", warnings->message);
}
pimpl->printContextWarnings(*messagePrinter, context);
outBinary.assign(reinterpret_cast<char *>(pOutput), reinterpret_cast<char *>(pOutput) + size);

View File

@ -0,0 +1,14 @@
/*
* Copyright (C) 2022 Intel Corporation
*
* SPDX-License-Identifier: MIT
*
*/
#include "ocloc_dll_options.h"
namespace Os {
const char *igaDllName = IGA_LIBRARY_NAME;
} // namespace Os

View File

@ -0,0 +1,16 @@
/*
* Copyright (C) 2022 Intel Corporation
*
* SPDX-License-Identifier: MIT
*
*/
#pragma once
#include "shared/source/os_interface/os_inc_base.h"
namespace Os {
extern const char *igaDllName;
} // namespace Os