Files
compute-runtime/opencl/test/unit_test/offline_compiler/decoder/decoder_tests.cpp
Daria Hinz 9e6d3d93e7 Fix ocloc decoder ULTs for IGA
This PR fixes the decoder tests in ocloc to improve single SKUs.
In tests, checking the existence of the platform in IGA has been added.

Signed-off-by: Daria Hinz <daria.hinz@intel.com>
Related-To: NEO-7509
2022-11-25 10:53:15 +01:00

795 lines
32 KiB
C++

/*
* Copyright (C) 2018-2022 Intel Corporation
*
* SPDX-License-Identifier: MIT
*
*/
#include "shared/offline_compiler/source/decoder/translate_platform_base.h"
#include "shared/source/helpers/array_count.h"
#include "shared/test/common/helpers/gtest_helpers.h"
#include "shared/test/common/helpers/test_files.h"
#include "shared/test/common/helpers/variable_backup.h"
#include "opencl/test/unit_test/offline_compiler/environment.h"
#include "opencl/test/unit_test/offline_compiler/mock/mock_argument_helper.h"
#include "opencl/test/unit_test/offline_compiler/stdout_capturer.h"
#include "opencl/test/unit_test/test_files/patch_list.h"
#include "gtest/gtest.h"
#include "igad.h"
#include "igfxfmid.h"
#include "mock/mock_decoder.h"
#include <array>
#include <fstream>
#include <sstream>
#include <string>
#include <utility>
extern Environment *gEnvironment;
static void abortOclocExecutionMock(int code) {
throw std::runtime_error{"Exit called with code = " + std::to_string(code)};
}
SProgramBinaryHeader createProgramBinaryHeader(const uint32_t numberOfKernels, const uint32_t patchListSize) {
return SProgramBinaryHeader{MAGIC_CL, 0, 0, 0, numberOfKernels, 0, patchListSize};
}
SKernelBinaryHeaderCommon createKernelBinaryHeaderCommon(const uint32_t kernelNameSize, const uint32_t patchListSize) {
SKernelBinaryHeaderCommon kernelHeader = {};
kernelHeader.CheckSum = 0xFFFFFFFF;
kernelHeader.ShaderHashCode = 0xFFFFFFFFFFFFFFFF;
kernelHeader.KernelNameSize = kernelNameSize;
kernelHeader.PatchListSize = patchListSize;
return kernelHeader;
}
namespace NEO {
TEST(DecoderTests, GivenArgHelperWithHeadersWhenLoadingPatchListThenHeadersAreReturned) {
const char input[] = "First\nSecond\nThird";
const auto inputLength{sizeof(input)};
const auto filename{"some_file.txt"};
Source source{reinterpret_cast<const uint8_t *>(input), inputLength, filename};
MockDecoder decoder;
decoder.mockArgHelper->headers.push_back(source);
const auto lines = decoder.loadPatchList();
ASSERT_EQ(3u, lines.size());
EXPECT_EQ("First", lines[0]);
EXPECT_EQ("Second", lines[1]);
EXPECT_EQ("Third", lines[2]);
}
TEST(DecoderTests, GivenHeadersWithoutProgramBinaryHeaderWhenParsingTokensThenErrorIsRaised) {
VariableBackup oclocAbortBackup{&abortOclocExecution, &abortOclocExecutionMock};
const char input[] = "First\nSecond\nThird";
const auto inputLength{sizeof(input)};
const auto filename{"some_file.txt"};
Source source{reinterpret_cast<const uint8_t *>(input), inputLength, filename};
MockDecoder decoder{false};
decoder.mockArgHelper->headers.push_back(source);
StdoutCapturer capturer{};
EXPECT_ANY_THROW(decoder.parseTokens());
const auto output{capturer.acquireOutput()};
EXPECT_EQ("While parsing patchtoken definitions: couldn't find SProgramBinaryHeader.", output);
}
TEST(DecoderTests, GivenHeadersWithoutPatchTokenEnumWhenParsingTokensThenErrorIsRaised) {
VariableBackup oclocAbortBackup{&abortOclocExecution, &abortOclocExecutionMock};
const char input[] = "struct SProgramBinaryHeader\n{};";
const auto inputLength{sizeof(input)};
const auto filename{"some_file.txt"};
Source source{reinterpret_cast<const uint8_t *>(input), inputLength, filename};
MockDecoder decoder{false};
decoder.mockArgHelper->headers.push_back(source);
StdoutCapturer capturer{};
EXPECT_ANY_THROW(decoder.parseTokens());
const auto output{capturer.acquireOutput()};
EXPECT_EQ("While parsing patchtoken definitions: couldn't find enum PATCH_TOKEN.", output);
}
TEST(DecoderTests, GivenHeadersWithoutKernelBinaryHeaderWhenParsingTokensThenErrorIsRaised) {
VariableBackup oclocAbortBackup{&abortOclocExecution, &abortOclocExecutionMock};
const char input[] = "struct SProgramBinaryHeader\n{};\nenum PATCH_TOKEN\n{};";
const auto inputLength{sizeof(input)};
const auto filename{"some_file.txt"};
Source source{reinterpret_cast<const uint8_t *>(input), inputLength, filename};
MockDecoder decoder{false};
decoder.mockArgHelper->headers.push_back(source);
StdoutCapturer capturer{};
EXPECT_ANY_THROW(decoder.parseTokens());
const auto output{capturer.acquireOutput()};
EXPECT_EQ("While parsing patchtoken definitions: couldn't find SKernelBinaryHeader.", output);
}
TEST(DecoderTests, GivenHeadersWithoutKernelBinaryHeaderCommonWhenParsingTokensThenErrorIsRaised) {
VariableBackup oclocAbortBackup{&abortOclocExecution, &abortOclocExecutionMock};
const char input[] = "struct SProgramBinaryHeader\n{};\nenum PATCH_TOKEN\n{};struct SKernelBinaryHeader\n{};";
const auto inputLength{sizeof(input)};
const auto filename{"some_file.txt"};
Source source{reinterpret_cast<const uint8_t *>(input), inputLength, filename};
MockDecoder decoder{false};
decoder.mockArgHelper->headers.push_back(source);
StdoutCapturer capturer{};
EXPECT_ANY_THROW(decoder.parseTokens());
const auto output{capturer.acquireOutput()};
EXPECT_EQ("While parsing patchtoken definitions: couldn't find SKernelBinaryHeaderCommon.", output);
}
TEST(DecoderTests, GivenFieldsWithSizeWhenDumpingThemThenTheyAreWrittenToPtmFileStream) {
VariableBackup oclocAbortBackup{&abortOclocExecution, &abortOclocExecutionMock};
// Raw data contains 4 variables:
// 1. UINT8_T = 0x01.
// 2. UINT16_T = 0x0202
// 3. UINT32_T = 0x03030303
// 4. UINT64_T = 0x0404040404040404
uint8_t rawData[] = {
0x1,
0x2, 0x2,
0x3, 0x3, 0x3, 0x3,
0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4};
MockDecoder decoder;
std::stringstream ptFileOutputStream;
ptFileOutputStream << std::hex;
const void *memoryPtr = rawData;
for (uint8_t varSize = 1; varSize <= 8; varSize *= 2) {
PTField field{varSize, "SomeUINT_" + std::to_string(varSize)};
decoder.dumpField(memoryPtr, field, ptFileOutputStream);
}
const std::string expectedPtFileContent{
"\t1 SomeUINT_1 1\n"
"\t2 SomeUINT_2 202\n"
"\t4 SomeUINT_4 3030303\n"
"\t8 SomeUINT_8 404040404040404\n"};
EXPECT_EQ(expectedPtFileContent, ptFileOutputStream.str());
}
TEST(DecoderTests, GivenInvalidFieldSizeWhenDumpingItThenErrorIsRaised) {
VariableBackup oclocAbortBackup{&abortOclocExecution, &abortOclocExecutionMock};
uint8_t rawData[] = {
0x1,
0x2, 0x2,
0x3, 0x3, 0x3, 0x3};
MockDecoder decoder{false};
std::stringstream ptFileOutputStream;
const void *memoryPtr = rawData;
PTField badField{7, "SomeUINT_7"};
StdoutCapturer capturer{};
EXPECT_ANY_THROW(decoder.dumpField(memoryPtr, badField, ptFileOutputStream));
const auto output{capturer.acquireOutput()};
EXPECT_EQ("Error! Unknown size.\n", output);
}
TEST(DecoderTests, GivenPassingParsingAndNullptrDevBinaryWhenDecodingThenErrorIsRaised) {
VariableBackup oclocAbortBackup{&abortOclocExecution, &abortOclocExecutionMock};
MockDecoder decoder{false};
decoder.callBaseParseTokens = false;
decoder.callBaseGetDevBinary = false;
decoder.devBinaryToReturn = nullptr;
StdoutCapturer capturer{};
EXPECT_ANY_THROW(decoder.decode());
const auto output{capturer.acquireOutput()};
EXPECT_EQ("Error! Device Binary section was not found.\n", output);
}
TEST(DecoderTests, GivenPassingParsingAndEmptyDevBinaryWhenDecodingThenWarningAboutZeroKernelIsPrinted) {
VariableBackup oclocAbortBackup{&abortOclocExecution, &abortOclocExecutionMock};
MockDecoder decoder{false};
decoder.callBaseParseTokens = false;
decoder.callBaseGetDevBinary = false;
decoder.devBinaryToReturn = "";
int decodeReturnValue{-1};
StdoutCapturer capturer{};
ASSERT_NO_THROW(decodeReturnValue = decoder.decode());
const auto output{capturer.acquireOutput()};
EXPECT_EQ(0, decodeReturnValue);
EXPECT_EQ("Warning! Number of Kernels is 0.\n", output);
}
TEST(DecoderTests, GivenEmptyKernelHeaderWhenProcessingKernelThenErrorIsRaised) {
VariableBackup oclocAbortBackup{&abortOclocExecution, &abortOclocExecutionMock};
MockDecoder decoder{false};
const void *memory = "abcdef";
std::stringstream ptFile;
StdoutCapturer capturer{};
EXPECT_ANY_THROW(decoder.processKernel(memory, ptFile));
const auto output{capturer.acquireOutput()};
EXPECT_EQ("Error! KernelNameSize was 0.\n", output);
}
TEST(DecoderTests, WhenParsingValidListOfParametersThenReturnValueIsZero) {
const std::vector<std::string> args = {
"ocloc",
"disasm",
"-file",
"test_files/binary.bin",
"-patch",
"test_files/patch",
"-dump",
"test_files/created"};
MockDecoder decoder;
EXPECT_EQ(0, decoder.validateInput(args));
}
TEST(DecoderTests, GivenFlagsWhichRequireMoreArgsWithoutThemWhenParsingThenErrorIsReported) {
const std::array<std::string, 4> flagsToTest = {
"-file", "-device", "-patch", "-dump"};
for (const auto &flag : flagsToTest) {
const std::vector<std::string> args = {
"ocloc",
"disasm",
flag};
constexpr auto suppressMessages{false};
MockDecoder decoder{suppressMessages};
::testing::internal::CaptureStdout();
const auto result = decoder.validateInput(args);
const auto output{::testing::internal::GetCapturedStdout()};
EXPECT_EQ(-1, result);
const std::string expectedErrorMessage{"Unknown argument " + flag + "\n"};
EXPECT_EQ(expectedErrorMessage, output);
}
}
TEST(DecoderTests, givenUnknownDeviceNameWhenValidateInputThenCorrectWarningIsReported) {
const std::vector<std::string> args = {
"ocloc",
"disasm",
"-device",
"unk"};
constexpr auto suppressMessages{false};
MockDecoder decoder{suppressMessages};
::testing::internal::CaptureStdout();
const auto result = decoder.validateInput(args);
const auto output{::testing::internal::GetCapturedStdout()};
EXPECT_EQ(result, 0);
const std::string expectedWarningMessage{"Warning : missing or invalid -device parameter - results may be inaccurate\n"};
EXPECT_TRUE(hasSubstr(output, expectedWarningMessage));
}
TEST(DecoderTests, givenDeprecatedDeviceNamesWhenValidateInputThenCorrectWarningIsReported) {
constexpr auto suppressMessages{false};
MockDecoder decoder{suppressMessages};
auto deprecatedAcronyms = decoder.mockArgHelper->productConfigHelper->getDeprecatedAcronyms();
for (const auto &acronym : deprecatedAcronyms) {
const std::vector<std::string> args = {
"ocloc",
"disasm",
"-device",
acronym.str()};
::testing::internal::CaptureStdout();
const auto result = decoder.validateInput(args);
const auto output{::testing::internal::GetCapturedStdout()};
EXPECT_EQ(result, 0);
const std::string expectedWarningMessage{"Warning : Deprecated device name is being used.\n"};
EXPECT_TRUE(hasSubstr(output, expectedWarningMessage));
}
}
TEST(DecoderTests, givenProductNamesThatExistsForIgaWhenValidateInputThenSuccessIsReturned) {
constexpr auto suppressMessages{false};
MockDecoder decoder{suppressMessages};
if (!decoder.getMockIga()->isValidPlatform()) {
GTEST_SKIP();
}
decoder.mockArgHelper->hasOutput = true;
auto aotInfos = decoder.mockArgHelper->productConfigHelper->getDeviceAotInfo();
for (const auto &device : aotInfos) {
if (productFamily != device.hwInfo->platform.eProductFamily)
continue;
for (const auto &acronym : device.acronyms) {
const std::vector<std::string> args = {
"ocloc",
"disasm",
"-device",
acronym.str()};
::testing::internal::CaptureStdout();
const auto result = decoder.validateInput(args);
const auto output{::testing::internal::GetCapturedStdout()};
EXPECT_EQ(result, 0);
EXPECT_TRUE(output.empty());
}
}
decoder.mockArgHelper->hasOutput = false;
}
TEST(DecoderTests, GivenIgnoreIsaPaddingFlagWhenParsingValidListOfParametersThenReturnValueIsZeroAndInternalFlagIsSet) {
const std::vector<std::string> args = {
"ocloc",
"disasm",
"-file",
"test_files/binary.bin",
"-patch",
"test_files/patch",
"-dump",
"test_files/created",
"-ignore_isa_padding"};
MockDecoder decoder;
EXPECT_EQ(0, decoder.validateInput(args));
EXPECT_TRUE(decoder.ignoreIsaPadding);
}
TEST(DecoderTests, GivenQuietModeFlagWhenParsingValidListOfParametersThenReturnValueIsZeroAndMessagesAreSuppressed) {
const std::vector<std::string> args = {
"ocloc",
"disasm",
"-file",
"test_files/binary.bin",
"-patch",
"test_files/patch",
"-dump",
"test_files/created",
"-q"};
constexpr auto suppressMessages{false};
MockDecoder decoder{suppressMessages};
EXPECT_EQ(0, decoder.validateInput(args));
EXPECT_TRUE(decoder.argHelper->getPrinterRef().isSuppressed());
}
TEST(DecoderTests, GivenMissingDumpFlagWhenParsingValidListOfParametersThenReturnValueIsZeroAndWarningAboutCreationOfDefaultDirectoryIsPrinted) {
constexpr auto suppressMessages{false};
MockDecoder decoder{suppressMessages};
if (gEnvironment->productConfig.empty() || !decoder.getMockIga()->isValidPlatform()) {
GTEST_SKIP();
}
const std::vector<std::string> args = {
"ocloc",
"disasm",
"-file",
"test_files/binary.bin",
"-device",
gEnvironment->productConfig.c_str(),
"-patch",
"test_files/patch"};
::testing::internal::CaptureStdout();
const auto result = decoder.validateInput(args);
const auto output{::testing::internal::GetCapturedStdout()};
EXPECT_EQ(0, result);
const std::string expectedErrorMessage{"Warning : Path to dump folder not specificed - using ./dump as default.\n"};
EXPECT_TRUE(hasSubstr(output, expectedErrorMessage));
}
TEST(DecoderTests, GivenMissingDumpFlagAndArgHelperOutputEnabledWhenParsingValidListOfParametersThenReturnValueIsZeroAndDefaultDirectoryWarningIsNotEmitted) {
constexpr auto suppressMessages{false};
MockDecoder decoder{suppressMessages};
if (gEnvironment->productConfig.empty() || !decoder.getMockIga()->isValidPlatform()) {
GTEST_SKIP();
}
const std::vector<std::string> args = {
"ocloc",
"disasm",
"-file",
"test_files/binary.bin",
"-device",
gEnvironment->productConfig.c_str(),
"-patch",
"test_files/patch"};
decoder.mockArgHelper->hasOutput = true;
::testing::internal::CaptureStdout();
const auto result = decoder.validateInput(args);
const auto output{::testing::internal::GetCapturedStdout()};
EXPECT_EQ(0, result);
EXPECT_TRUE(output.empty()) << output;
decoder.mockArgHelper->hasOutput = false;
}
TEST(DecoderTests, GivenValidSizeStringWhenGettingSizeThenProperOutcomeIsExpectedAndExceptionIsNotThrown) {
MockDecoder decoder;
EXPECT_EQ(static_cast<uint8_t>(1), decoder.getSize("uint8_t"));
EXPECT_EQ(static_cast<uint8_t>(2), decoder.getSize("uint16_t"));
EXPECT_EQ(static_cast<uint8_t>(4), decoder.getSize("uint32_t"));
EXPECT_EQ(static_cast<uint8_t>(8), decoder.getSize("uint64_t"));
}
TEST(DecoderTests, GivenProperStructWhenReadingStructFieldsThenFieldsVectorGetsPopulatedCorrectly) {
std::vector<std::string> lines;
lines.push_back("/* */");
lines.push_back("struct SPatchSamplerStateArray :");
lines.push_back(" SPatchItemHeader");
lines.push_back("{");
lines.push_back(" uint64_t SomeField;");
lines.push_back(" uint32_t Offset;");
lines.push_back("");
lines.push_back(" uint16_t Count;");
lines.push_back(" uint8_t BorderColorOffset;");
lines.push_back("};");
std::vector<PTField> fields;
MockDecoder decoder;
size_t pos = 4;
uint32_t fullSize = decoder.readStructFields(lines, pos, fields);
EXPECT_EQ(static_cast<uint32_t>(15), fullSize);
EXPECT_EQ(static_cast<uint8_t>(8), fields[0].size);
EXPECT_EQ("SomeField", fields[0].name);
EXPECT_EQ(static_cast<uint8_t>(4), fields[1].size);
EXPECT_EQ("Offset", fields[1].name);
EXPECT_EQ(static_cast<uint8_t>(2), fields[2].size);
EXPECT_EQ("Count", fields[2].name);
EXPECT_EQ(static_cast<uint8_t>(1), fields[3].size);
EXPECT_EQ("BorderColorOffset", fields[3].name);
}
TEST(DecoderTests, GivenProperPatchListFileWhenParsingTokensThenFileIsParsedCorrectly) {
MockDecoder decoder;
decoder.pathToPatch = clFiles;
decoder.parseTokens();
EXPECT_EQ(static_cast<uint32_t>(28), (decoder.programHeader.size));
EXPECT_EQ(static_cast<uint8_t>(4), (decoder.programHeader.fields[0].size));
EXPECT_EQ("Magic", (decoder.programHeader.fields[0].name));
EXPECT_EQ(static_cast<uint8_t>(4), (decoder.programHeader.fields[1].size));
EXPECT_EQ("Version", (decoder.programHeader.fields[1].name));
EXPECT_EQ(static_cast<uint8_t>(4), (decoder.programHeader.fields[2].size));
EXPECT_EQ("Device", (decoder.programHeader.fields[2].name));
EXPECT_EQ(static_cast<uint8_t>(4), (decoder.programHeader.fields[3].size));
EXPECT_EQ("GPUPointerSizeInBytes", (decoder.programHeader.fields[3].name));
EXPECT_EQ(static_cast<uint8_t>(4), (decoder.programHeader.fields[4].size));
EXPECT_EQ("NumberOfKernels", (decoder.programHeader.fields[4].name));
EXPECT_EQ(static_cast<uint8_t>(4), (decoder.programHeader.fields[5].size));
EXPECT_EQ("SteppingId", (decoder.programHeader.fields[5].name));
EXPECT_EQ(static_cast<uint8_t>(4), (decoder.programHeader.fields[6].size));
EXPECT_EQ("PatchListSize", (decoder.programHeader.fields[6].name));
EXPECT_EQ(static_cast<uint8_t>(40), (decoder.kernelHeader.size));
EXPECT_EQ(static_cast<uint8_t>(4), (decoder.kernelHeader.fields[0].size));
EXPECT_EQ("CheckSum", (decoder.kernelHeader.fields[0].name));
EXPECT_EQ(static_cast<uint8_t>(8), (decoder.kernelHeader.fields[1].size));
EXPECT_EQ("ShaderHashCode", (decoder.kernelHeader.fields[1].name));
EXPECT_EQ(static_cast<uint8_t>(4), (decoder.kernelHeader.fields[2].size));
EXPECT_EQ("KernelNameSize", (decoder.kernelHeader.fields[2].name));
EXPECT_EQ(static_cast<uint8_t>(4), (decoder.kernelHeader.fields[3].size));
EXPECT_EQ("PatchListSize", (decoder.kernelHeader.fields[3].name));
EXPECT_EQ(static_cast<uint8_t>(4), (decoder.kernelHeader.fields[4].size));
EXPECT_EQ("KernelHeapSize", (decoder.kernelHeader.fields[4].name));
EXPECT_EQ(static_cast<uint8_t>(4), (decoder.kernelHeader.fields[5].size));
EXPECT_EQ("GeneralStateHeapSize", (decoder.kernelHeader.fields[5].name));
EXPECT_EQ(static_cast<uint8_t>(4), (decoder.kernelHeader.fields[6].size));
EXPECT_EQ("DynamicStateHeapSize", (decoder.kernelHeader.fields[6].name));
EXPECT_EQ(static_cast<uint8_t>(4), (decoder.kernelHeader.fields[7].size));
EXPECT_EQ("SurfaceStateHeapSize", (decoder.kernelHeader.fields[7].name));
EXPECT_EQ(static_cast<uint8_t>(4), (decoder.kernelHeader.fields[8].size));
EXPECT_EQ("KernelUnpaddedSize", (decoder.kernelHeader.fields[8].name));
EXPECT_EQ(static_cast<uint8_t>(4), (decoder.patchTokens[2]->size));
EXPECT_EQ("PATCH_TOKEN_STATE_SIP", (decoder.patchTokens[2]->name));
EXPECT_EQ(static_cast<uint8_t>(4), (decoder.patchTokens[2]->fields[0].size));
EXPECT_EQ("SystemKernelOffset", (decoder.patchTokens[2]->fields[0].name));
EXPECT_EQ(static_cast<uint8_t>(12), decoder.patchTokens[5]->size);
EXPECT_EQ("PATCH_TOKEN_SAMPLER_STATE_ARRAY", decoder.patchTokens[5]->name);
EXPECT_EQ(static_cast<uint8_t>(4), (decoder.patchTokens[5]->fields[0].size));
EXPECT_EQ("Offset", (decoder.patchTokens[5]->fields[0].name));
EXPECT_EQ(static_cast<uint8_t>(4), (decoder.patchTokens[5]->fields[1].size));
EXPECT_EQ("Count", (decoder.patchTokens[5]->fields[1].name));
EXPECT_EQ(static_cast<uint8_t>(4), (decoder.patchTokens[5]->fields[2].size));
EXPECT_EQ("BorderColorOffset", (decoder.patchTokens[5]->fields[2].name));
EXPECT_EQ(static_cast<uint8_t>(8), decoder.patchTokens[42]->size);
EXPECT_EQ("PATCH_TOKEN_ALLOCATE_CONSTANT_MEMORY_SURFACE_PROGRAM_BINARY_INFO", decoder.patchTokens[42]->name);
EXPECT_EQ(static_cast<uint8_t>(4), (decoder.patchTokens[42]->fields[0].size));
EXPECT_EQ("ConstantBufferIndex", (decoder.patchTokens[42]->fields[0].name));
EXPECT_EQ(static_cast<uint8_t>(4), (decoder.patchTokens[42]->fields[1].size));
EXPECT_EQ("InlineDataSize", (decoder.patchTokens[42]->fields[1].name));
EXPECT_EQ(static_cast<uint8_t>(4), decoder.patchTokens[19]->size);
EXPECT_EQ("PATCH_TOKEN_MEDIA_INTERFACE_DESCRIPTOR_LOAD", decoder.patchTokens[19]->name);
EXPECT_EQ(static_cast<uint8_t>(4), (decoder.patchTokens[19]->fields[0].size));
EXPECT_EQ("InterfaceDescriptorDataOffset", (decoder.patchTokens[19]->fields[0].name));
}
TEST(DecoderTests, WhenPathToPatchTokensNotProvidedThenUseDefaults) {
MockDecoder decoder;
decoder.pathToPatch = "";
decoder.parseTokens();
EXPECT_NE(0U, decoder.programHeader.size);
EXPECT_NE(0U, decoder.kernelHeader.size);
}
TEST(DecoderTests, GivenValidBinaryWhenReadingPatchTokensFromBinaryThenBinaryIsReadCorrectly) {
std::string binaryString;
std::stringstream binarySS;
uint8_t byte;
uint32_t byte4;
byte4 = 4;
binarySS.write(reinterpret_cast<char *>(&byte4), sizeof(uint32_t));
byte4 = 16;
binarySS.write(reinterpret_cast<char *>(&byte4), sizeof(uint32_t));
byte4 = 1234;
binarySS.write(reinterpret_cast<char *>(&byte4), sizeof(uint32_t));
byte4 = 5678;
binarySS.write(reinterpret_cast<char *>(&byte4), sizeof(uint32_t));
byte4 = 2;
binarySS.write(reinterpret_cast<char *>(&byte4), sizeof(uint32_t));
byte4 = 12;
binarySS.write(reinterpret_cast<char *>(&byte4), sizeof(uint32_t));
byte = 255;
for (auto i = 0; i < 4; ++i) {
binarySS.write(reinterpret_cast<char *>(&byte), sizeof(uint8_t));
}
binaryString = binarySS.str();
std::vector<char> binary(binaryString.begin(), binaryString.end());
MockDecoder decoder;
std::stringstream out;
auto patchToken = std::make_unique<PatchToken>();
patchToken->size = 20;
patchToken->name = "Example patchtoken";
patchToken->fields.push_back(PTField{4, "First"});
patchToken->fields.push_back(PTField{4, "Second"});
decoder.patchTokens.insert(std::pair<uint8_t, std::unique_ptr<PatchToken>>(4, std::move(patchToken)));
const void *ptr = reinterpret_cast<void *>(binary.data());
decoder.readPatchTokens(ptr, 28, out);
std::string s = "Example patchtoken:\n\t4 Token 4\n\t4 Size 16\n\t4 First 1234\n\t4 Second 5678\nUnidentified PatchToken:\n\t4 Token 2\n\t4 Size 12\n\tHex ff ff ff ff\n";
EXPECT_EQ(s, out.str());
}
TEST(DecoderTests, GivenValidBinaryWithoutPatchTokensWhenProcessingBinaryThenBinaryIsReadCorrectly) {
auto programHeader = createProgramBinaryHeader(1, 0);
std::string kernelName("ExampleKernel");
auto kernelHeader = createKernelBinaryHeaderCommon(static_cast<uint32_t>(kernelName.size() + 1), 0);
std::stringstream binarySS;
binarySS.write(reinterpret_cast<char *>(&programHeader), sizeof(SProgramBinaryHeader));
binarySS.write(reinterpret_cast<char *>(&kernelHeader), sizeof(SKernelBinaryHeaderCommon));
binarySS.write(kernelName.c_str(), kernelHeader.KernelNameSize);
std::stringstream ptmFile;
MockDecoder decoder;
decoder.pathToPatch = clFiles;
decoder.pathToDump = "non_existing_folder/";
decoder.parseTokens();
std::string binaryString = binarySS.str();
std::vector<unsigned char> binary(binaryString.begin(), binaryString.end());
const void *ptr = reinterpret_cast<void *>(binary.data());
int retVal = decoder.processBinary(ptr, ptmFile);
EXPECT_EQ(0, retVal);
std::string expectedOutput = "ProgramBinaryHeader:\n\t4 Magic 1229870147\n\t4 Version 0\n\t4 Device 0\n\t4 GPUPointerSizeInBytes 0\n\t4 NumberOfKernels 1\n\t4 SteppingId 0\n\t4 PatchListSize 0\nKernel #0\nKernelBinaryHeader:\n\t4 CheckSum 4294967295\n\t8 ShaderHashCode 18446744073709551615\n\t4 KernelNameSize 14\n\t4 PatchListSize 0\n\t4 KernelHeapSize 0\n\t4 GeneralStateHeapSize 0\n\t4 DynamicStateHeapSize 0\n\t4 SurfaceStateHeapSize 0\n\t4 KernelUnpaddedSize 0\n\tKernelName ExampleKernel\n";
EXPECT_EQ(expectedOutput, ptmFile.str());
}
TEST(DecoderTests, GivenValidBinaryWhenProcessingBinaryThenProgramAndKernelAndPatchTokensAreReadCorrectly) {
std::stringstream binarySS;
// ProgramBinaryHeader
auto programHeader = createProgramBinaryHeader(1, 30);
binarySS.write(reinterpret_cast<const char *>(&programHeader), sizeof(SProgramBinaryHeader));
// PATCH_TOKEN_ALLOCATE_CONSTANT_MEMORY_SURFACE_PROGRAM_BINARY_INFO
SPatchAllocateConstantMemorySurfaceProgramBinaryInfo patchAllocateConstantMemory;
patchAllocateConstantMemory.Token = 42;
patchAllocateConstantMemory.Size = 16;
patchAllocateConstantMemory.ConstantBufferIndex = 0;
patchAllocateConstantMemory.InlineDataSize = 14;
binarySS.write(reinterpret_cast<const char *>(&patchAllocateConstantMemory), sizeof(patchAllocateConstantMemory));
// InlineData
for (uint8_t i = 0; i < 14; ++i) {
binarySS.write(reinterpret_cast<char *>(&i), sizeof(uint8_t));
}
// KernelBinaryHeader
std::string kernelName("ExampleKernel");
auto kernelHeader = createKernelBinaryHeaderCommon(static_cast<uint32_t>(kernelName.size() + 1), 12);
binarySS.write(reinterpret_cast<const char *>(&kernelHeader), sizeof(SKernelBinaryHeaderCommon));
binarySS.write(kernelName.c_str(), kernelHeader.KernelNameSize);
// PATCH_TOKEN_MEDIA_INTERFACE_DESCRIPTOR_LOAD
SPatchMediaInterfaceDescriptorLoad patchMediaInterfaceDescriptorLoad;
patchMediaInterfaceDescriptorLoad.Token = 19;
patchMediaInterfaceDescriptorLoad.Size = 12;
patchMediaInterfaceDescriptorLoad.InterfaceDescriptorDataOffset = 0;
binarySS.write(reinterpret_cast<const char *>(&patchMediaInterfaceDescriptorLoad), sizeof(SPatchMediaInterfaceDescriptorLoad));
std::string binaryString = binarySS.str();
std::vector<char> binary(binaryString.begin(), binaryString.end());
std::stringstream ptmFile;
MockDecoder decoder;
decoder.pathToPatch = clFiles;
decoder.pathToDump = "non_existing_folder/";
decoder.parseTokens();
const void *ptr = reinterpret_cast<void *>(binary.data());
int retVal = decoder.processBinary(ptr, ptmFile);
EXPECT_EQ(0, retVal);
std::string expectedOutput = "ProgramBinaryHeader:\n\t4 Magic 1229870147\n\t4 Version 0\n\t4 Device 0\n\t4 GPUPointerSizeInBytes 0\n\t4 NumberOfKernels 1\n\t4 SteppingId 0\n\t4 PatchListSize 30\nPATCH_TOKEN_ALLOCATE_CONSTANT_MEMORY_SURFACE_PROGRAM_BINARY_INFO:\n\t4 Token 42\n\t4 Size 16\n\t4 ConstantBufferIndex 0\n\t4 InlineDataSize 14\n\tHex 0 1 2 3 4 5 6 7 8 9 a b c d\nKernel #0\nKernelBinaryHeader:\n\t4 CheckSum 4294967295\n\t8 ShaderHashCode 18446744073709551615\n\t4 KernelNameSize 14\n\t4 PatchListSize 12\n\t4 KernelHeapSize 0\n\t4 GeneralStateHeapSize 0\n\t4 DynamicStateHeapSize 0\n\t4 SurfaceStateHeapSize 0\n\t4 KernelUnpaddedSize 0\n\tKernelName ExampleKernel\nPATCH_TOKEN_MEDIA_INTERFACE_DESCRIPTOR_LOAD:\n\t4 Token 19\n\t4 Size 12\n\t4 InterfaceDescriptorDataOffset 0\n";
EXPECT_EQ(expectedOutput, ptmFile.str());
EXPECT_TRUE(decoder.getMockIga()->disasmWasCalled);
EXPECT_FALSE(decoder.getMockIga()->asmWasCalled);
}
TEST(DecoderTests, givenNonPatchtokensBinaryFormatWhenTryingToGetDevBinaryFormatThenDoNotReturnRawData) {
MockDecoder decoder;
std::map<std::string, std::string> files;
auto mockArgHelper = std::make_unique<MockOclocArgHelper>(files);
decoder.argHelper = mockArgHelper.get();
files["mockgen.gen"] = "NOTMAGIC\n\n\n\n\n\n\n";
decoder.binaryFile = "mockgen.gen";
auto data = decoder.getDevBinary();
EXPECT_EQ(nullptr, data);
}
TEST(DecoderTests, givenPatchtokensBinaryFormatWhenTryingToGetDevBinaryThenRawDataIsReturned) {
MockDecoder decoder;
std::map<std::string, std::string> files;
auto mockArgHelper = std::make_unique<MockOclocArgHelper>(files);
decoder.argHelper = mockArgHelper.get();
size_t dataSize = 11u;
files["mockgen.gen"] = "CTNI\n\n\n\n\n\n\n";
decoder.binaryFile = "mockgen.gen";
auto data = decoder.getDevBinary();
std::string dataString(static_cast<const char *>(data), dataSize);
EXPECT_STREQ("CTNI\n\n\n\n\n\n\n", dataString.c_str());
}
TEST(DecoderHelperTest, GivenTextSeparatedByTabsWhenSearchingForExistingTextThenItsIndexIsReturned) {
const std::vector<std::string> lines = {"Some\tNice\tText"};
const auto position = findPos(lines, "Nice");
EXPECT_EQ(0u, position);
}
TEST(DecoderHelperTest, GivenTextSeparatedByNewLinesWhenSearchingForExistingTextThenItsIndexIsReturned) {
const std::vector<std::string> lines = {"Some\nNice\nText"};
const auto position = findPos(lines, "Nice");
EXPECT_EQ(0u, position);
}
TEST(DecoderHelperTest, GivenTextSeparatedByCarriageReturnWhenSearchingForExistingTextThenItsIndexIsReturned) {
const std::vector<std::string> lines = {"Some\rNice\rText"};
const auto position = findPos(lines, "Nice");
EXPECT_EQ(0u, position);
}
TEST(DecoderHelperTest, GivenOnlyMatchingSubstringWhenSearchingForExistingTextThenInvalidIndexIsReturned) {
const std::vector<std::string> lines = {"Carpet"};
const auto position = findPos(lines, "Car");
EXPECT_EQ(lines.size(), position);
}
TEST(DecoderHelperTest, GivenPathEndedBySlashWhenCallingAddSlashThenNothingIsDone) {
std::string path{"./some/path/"};
addSlash(path);
EXPECT_EQ("./some/path/", path);
}
TEST(DecoderHelperTest, GivenPathEndedByBackSlashWhenCallingAddSlashThenNothingIsDone) {
std::string path{".\\some\\path\\"};
addSlash(path);
EXPECT_EQ(".\\some\\path\\", path);
}
TEST(DecoderHelperTest, GivenGfxCoreFamilyWhenTranslatingToIgaGenBaseThenExpectedIgaGenBaseIsReturned) {
constexpr static std::array translations = {
std::pair{IGFX_GEN8_CORE, IGA_GEN8},
std::pair{IGFX_GEN9_CORE, IGA_GEN9},
std::pair{IGFX_GEN11_CORE, IGA_GEN11},
std::pair{IGFX_GEN11LP_CORE, IGA_GEN11},
std::pair{IGFX_GEN12LP_CORE, IGA_XE},
std::pair{IGFX_XE_HP_CORE, IGA_XE_HP},
std::pair{IGFX_XE_HPG_CORE, IGA_XE_HPG},
std::pair{IGFX_XE_HPC_CORE, IGA_XE_HPC},
std::pair{IGFX_UNKNOWN_CORE, IGA_GEN_INVALID}};
for (const auto &[input, expectedOutput] : translations) {
EXPECT_EQ(expectedOutput, translateToIgaGen(input));
}
}
TEST(DecoderHelperTest, GivenProductFamilyWhenTranslatingToIgaGenBaseThenExpectedIgaGenBaseIsReturned) {
constexpr static std::array translations = {
std::pair{IGFX_BROADWELL, IGA_GEN8},
std::pair{IGFX_CHERRYVIEW, IGA_GEN8lp},
std::pair{IGFX_SKYLAKE, IGA_GEN9},
std::pair{IGFX_BROXTON, IGA_GEN9lp},
std::pair{IGFX_KABYLAKE, IGA_GEN9p5},
std::pair{IGFX_COFFEELAKE, IGA_GEN9p5},
std::pair{IGFX_ICELAKE, IGA_GEN11},
std::pair{IGFX_ICELAKE_LP, IGA_GEN11},
std::pair{IGFX_LAKEFIELD, IGA_GEN11},
std::pair{IGFX_ELKHARTLAKE, IGA_GEN11},
std::pair{IGFX_TIGERLAKE_LP, IGA_XE},
std::pair{IGFX_ROCKETLAKE, IGA_XE},
std::pair{IGFX_ALDERLAKE_N, IGA_XE},
std::pair{IGFX_ALDERLAKE_P, IGA_XE},
std::pair{IGFX_ALDERLAKE_S, IGA_XE},
std::pair{IGFX_DG1, IGA_XE},
std::pair{IGFX_XE_HP_SDV, IGA_XE_HP},
std::pair{IGFX_DG2, IGA_XE_HPG},
std::pair{IGFX_PVC, IGA_XE_HPC},
std::pair{IGFX_UNKNOWN, IGA_GEN_INVALID}};
for (const auto &[input, expectedOutput] : translations) {
EXPECT_EQ(expectedOutput, translateToIgaGen(input));
}
}
} // namespace NEO