Improve code coverage of BinaryDecoder

This change contains ULTs for BinaryDecoder.
It is intended to improve code coverage.

Related-To: NEO-6834
Signed-off-by: Patryk Wrobel <patryk.wrobel@intel.com>
This commit is contained in:
Patryk Wrobel
2022-04-26 16:43:47 +00:00
committed by Compute-Runtime-Automation
parent e007ba499f
commit e3b1d8b43c
4 changed files with 237 additions and 19 deletions

View File

@ -8,8 +8,10 @@
#include "shared/offline_compiler/source/decoder/translate_platform_base.h"
#include "shared/source/helpers/array_count.h"
#include "shared/test/common/helpers/test_files.h"
#include "shared/test/common/helpers/variable_backup.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"
@ -19,8 +21,14 @@
#include <array>
#include <fstream>
#include <sstream>
#include <string>
#include <utility>
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};
}
@ -36,6 +44,200 @@ SKernelBinaryHeaderCommon createKernelBinaryHeaderCommon(const uint32_t kernelNa
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",

View File

@ -19,9 +19,9 @@
class MockDecoder : public BinaryDecoder {
public:
using BinaryDecoder::decode;
using BinaryDecoder::getDevBinary;
using BinaryDecoder::dumpField;
using BinaryDecoder::getSize;
using BinaryDecoder::parseTokens;
using BinaryDecoder::loadPatchList;
using BinaryDecoder::processBinary;
using BinaryDecoder::processKernel;
using BinaryDecoder::readPatchTokens;
@ -53,6 +53,24 @@ class MockDecoder : public BinaryDecoder {
return static_cast<MockIgaWrapper *>(iga.get());
}
const void *getDevBinary() override {
if (callBaseGetDevBinary) {
return BinaryDecoder::getDevBinary();
}
return devBinaryToReturn;
}
void parseTokens() override {
if (callBaseParseTokens) {
return BinaryDecoder::parseTokens();
}
}
std::map<std::string, std::string> filesMap{};
std::unique_ptr<MockOclocArgHelper> mockArgHelper{};
bool callBaseParseTokens{true};
bool callBaseGetDevBinary{true};
const void *devBinaryToReturn{nullptr};
};

View File

@ -44,7 +44,8 @@ int BinaryDecoder::decode() {
auto devBinPtr = getDevBinary();
if (devBinPtr == nullptr) {
argHelper->printf("Error! Device Binary section was not found.\n");
exit(1);
abortOclocExecution(1);
return -1;
}
return processBinary(devBinPtr, ptmFile);
}
@ -74,7 +75,7 @@ void BinaryDecoder::dumpField(const void *&binaryPtr, const PTField &field, std:
}
default:
argHelper->printf("Error! Unknown size.\n");
exit(1);
abortOclocExecution(1);
}
binaryPtr = ptrOffset(binaryPtr, field.size);
}
@ -215,28 +216,25 @@ void BinaryDecoder::parseTokens() {
size_t pos = findPos(patchList, "struct SProgramBinaryHeader");
if (pos == patchList.size()) {
argHelper->printf("While parsing patchtoken definitions: couldn't find SProgramBinaryHeader.");
exit(1);
abortOclocExecution(1);
}
pos = findPos(patchList, "enum PATCH_TOKEN");
if (pos == patchList.size()) {
size_t patchTokenEnumPos = findPos(patchList, "enum PATCH_TOKEN");
if (patchTokenEnumPos == patchList.size()) {
argHelper->printf("While parsing patchtoken definitions: couldn't find enum PATCH_TOKEN.");
exit(1);
abortOclocExecution(1);
}
pos = findPos(patchList, "struct SKernelBinaryHeader");
if (pos == patchList.size()) {
argHelper->printf("While parsing patchtoken definitions: couldn't find SKernelBinaryHeader.");
exit(1);
abortOclocExecution(1);
}
pos = findPos(patchList, "struct SKernelBinaryHeaderCommon :");
if (pos == patchList.size()) {
argHelper->printf("While parsing patchtoken definitions: couldn't find SKernelBinaryHeaderCommon.");
exit(1);
}
// Reading all Patch Tokens and according structs
size_t patchTokenEnumPos = findPos(patchList, "enum PATCH_TOKEN");
if (patchTokenEnumPos == patchList.size()) {
exit(1);
abortOclocExecution(1);
}
for (auto i = patchTokenEnumPos + 1; i < patchList.size(); ++i) {
@ -396,7 +394,7 @@ void BinaryDecoder::processKernel(const void *&ptr, std::ostream &ptmFile) {
if (KernelNameSize == 0) {
argHelper->printf("Error! KernelNameSize was 0.\n");
exit(1);
abortOclocExecution(1);
}
ptmFile << "\tKernelName ";

View File

@ -58,9 +58,9 @@ class BinaryDecoder {
void dumpField(const void *&binaryPtr, const PTField &field, std::ostream &ptmFile);
uint8_t getSize(const std::string &typeStr);
const void *getDevBinary();
MOCKABLE_VIRTUAL const void *getDevBinary();
std::vector<std::string> loadPatchList();
void parseTokens();
MOCKABLE_VIRTUAL void parseTokens();
int processBinary(const void *&ptr, std::ostream &ptmFile);
void processKernel(const void *&ptr, std::ostream &ptmFile);
void readPatchTokens(const void *&patchListPtr, uint32_t patchListSize, std::ostream &ptmFile);