Create mock elf for elf process binary ULTs

Instead of using data loaded from the compiled binary, ULTs testing elf
binary data processing will use mock elf created for this purpose.
This will ensure mentioned ULTs independence from binary format in the
context of incoming zebin switch.

Related-To: NEO-6646
Signed-off-by: Kacper Nowak <kacper.nowak@intel.com>
This commit is contained in:
Kacper Nowak
2022-05-11 02:24:18 +00:00
committed by Compute-Runtime-Automation
parent 95ff289bde
commit ee4a177296

View File

@ -5,6 +5,7 @@
*
*/
#include "shared/source/compiler_interface/intermediate_representations.h"
#include "shared/source/device/device.h"
#include "shared/source/device_binary_format/elf/elf.h"
#include "shared/source/device_binary_format/elf/elf_decoder.h"
@ -13,11 +14,13 @@
#include "shared/source/helpers/string.h"
#include "shared/test/common/helpers/test_files.h"
#include "shared/test/common/mocks/mock_device.h"
#include "shared/test/common/mocks/mock_elf.h"
#include "shared/test/unit_test/device_binary_format/patchtokens_tests.h"
#include "shared/test/unit_test/helpers/gtest_helpers.h"
#include "opencl/test/unit_test/mocks/mock_cl_device.h"
#include "opencl/test/unit_test/mocks/mock_program.h"
#include "opencl/test/unit_test/test_files/patch_list.h"
#include "compiler_options.h"
#include "gtest/gtest.h"
@ -26,6 +29,52 @@
using namespace NEO;
enum class enabledIrFormat {
NONE,
ENABLE_SPIRV,
ENABLE_LLVM
};
template <enabledIrFormat irFormat = enabledIrFormat::NONE>
struct MockElfBinaryPatchtokens {
MockElfBinaryPatchtokens(const HardwareInfo &hwInfo) : MockElfBinaryPatchtokens(std::string{}, hwInfo){};
MockElfBinaryPatchtokens(const std::string &buildOptions, const HardwareInfo &hwInfo) {
mockDevBinaryHeader.Device = hwInfo.platform.eRenderCoreFamily;
mockDevBinaryHeader.GPUPointerSizeInBytes = sizeof(void *);
mockDevBinaryHeader.Version = iOpenCL::CURRENT_ICBE_VERSION;
constexpr size_t mockDevBinaryDataSize = sizeof(mockDevBinaryHeader) + mockDataSize;
constexpr size_t mockSpirvBinaryDataSize = sizeof(spirvMagic) + mockDataSize;
constexpr size_t mockLlvmBinaryDataSize = sizeof(llvmBcMagic) + mockDataSize;
char mockDevBinaryData[mockDevBinaryDataSize];
memcpy_s(mockDevBinaryData, mockDevBinaryDataSize, &mockDevBinaryHeader, sizeof(mockDevBinaryHeader));
memset(mockDevBinaryData + sizeof(mockDevBinaryHeader), '\x01', mockDataSize);
char mockSpirvBinaryData[mockSpirvBinaryDataSize];
memcpy_s(mockSpirvBinaryData, mockSpirvBinaryDataSize, spirvMagic.data(), spirvMagic.size());
memset(mockSpirvBinaryData + spirvMagic.size(), '\x02', mockDataSize);
char mockLlvmBinaryData[mockLlvmBinaryDataSize];
memcpy_s(mockLlvmBinaryData, mockLlvmBinaryDataSize, llvmBcMagic.data(), llvmBcMagic.size());
memset(mockLlvmBinaryData + llvmBcMagic.size(), '\x03', mockDataSize);
Elf::ElfEncoder<Elf::EI_CLASS_64> enc;
enc.getElfFileHeader().identity = Elf::ElfFileHeaderIdentity(Elf::EI_CLASS_64);
enc.getElfFileHeader().type = NEO::Elf::ET_OPENCL_EXECUTABLE;
enc.appendSection(Elf::SHT_OPENCL_DEV_BINARY, Elf::SectionNamesOpenCl::deviceBinary, ArrayRef<const uint8_t>::fromAny(mockDevBinaryData, mockDevBinaryDataSize));
if (irFormat == enabledIrFormat::ENABLE_SPIRV)
enc.appendSection(Elf::SHT_OPENCL_SPIRV, Elf::SectionNamesOpenCl::spirvObject, ArrayRef<const uint8_t>::fromAny(mockSpirvBinaryData, mockSpirvBinaryDataSize));
else if (irFormat == enabledIrFormat::ENABLE_LLVM)
enc.appendSection(Elf::SHT_OPENCL_LLVM_BINARY, Elf::SectionNamesOpenCl::llvmObject, ArrayRef<const uint8_t>::fromAny(mockLlvmBinaryData, mockLlvmBinaryDataSize));
if (false == buildOptions.empty())
enc.appendSection(Elf::SHT_OPENCL_OPTIONS, Elf::SectionNamesOpenCl::buildOptions, ArrayRef<const uint8_t>::fromAny(buildOptions.data(), buildOptions.size()));
storage = enc.encode();
}
static constexpr size_t mockDataSize = 0x10;
SProgramBinaryHeader mockDevBinaryHeader = SProgramBinaryHeader{MAGIC_CL, 0, 0, 0, 0, 0, 0};
std::vector<uint8_t> storage;
};
class ProcessElfBinaryTests : public ::testing::Test {
public:
void SetUp() override {
@ -52,15 +101,14 @@ TEST_F(ProcessElfBinaryTests, GivenInvalidBinaryWhenCreatingProgramFromBinaryThe
}
TEST_F(ProcessElfBinaryTests, GivenValidBinaryWhenCreatingProgramFromBinaryThenSuccessIsReturned) {
std::string filePath;
retrieveBinaryKernelFilename(filePath, "CopyBuffer_simd16_", ".bin");
auto mockElf = std::make_unique<MockElfBinaryPatchtokens<>>(device->getHardwareInfo());
auto pBinary = mockElf->storage;
auto binarySize = mockElf->storage.size();
size_t binarySize = 0;
auto pBinary = loadDataFromFile(filePath.c_str(), binarySize);
cl_int retVal = program->createProgramFromBinary(pBinary.get(), binarySize, *device);
cl_int retVal = program->createProgramFromBinary(pBinary.data(), binarySize, *device);
EXPECT_EQ(CL_SUCCESS, retVal);
EXPECT_EQ(0, memcmp(pBinary.get(), program->buildInfos[rootDeviceIndex].packedDeviceBinary.get(), binarySize));
EXPECT_EQ(0, memcmp(pBinary.data(), program->buildInfos[rootDeviceIndex].packedDeviceBinary.get(), binarySize));
}
TEST_F(ProcessElfBinaryTests, GivenValidSpirBinaryWhenCreatingProgramFromBinaryThenSuccessIsReturned) {
@ -119,19 +167,17 @@ class ProcessElfBinaryTestsWithBinaryType : public ::testing::TestWithParam<unsi
device = std::make_unique<MockClDevice>(MockDevice::createWithNewExecutionEnvironment<MockDevice>(nullptr, rootDeviceIndex));
program = std::make_unique<MockProgram>(nullptr, false, toClDeviceVector(*device));
}
std::unique_ptr<MockProgram> program;
std::unique_ptr<ClDevice> device;
const uint32_t rootDeviceIndex = 1;
};
TEST_P(ProcessElfBinaryTestsWithBinaryType, GivenBinaryTypeWhenResolveProgramThenProgramIsProperlyResolved) {
std::string filePath;
retrieveBinaryKernelFilename(filePath, "CopyBuffer_simd16_", ".bin");
auto mockElf = std::make_unique<MockElfBinaryPatchtokens<enabledIrFormat::ENABLE_SPIRV>>(device->getHardwareInfo());
auto pBinary = mockElf->storage;
auto binarySize = mockElf->storage.size();
size_t binarySize = 0;
auto pBinary = loadDataFromFile(filePath.c_str(), binarySize);
cl_int retVal = program->createProgramFromBinary(pBinary.get(), binarySize, *device);
cl_int retVal = program->createProgramFromBinary(pBinary.data(), binarySize, *device);
auto options = program->options;
auto genBinary = makeCopy(program->buildInfos[rootDeviceIndex].unpackedDeviceBinary.get(), program->buildInfos[rootDeviceIndex].unpackedDeviceBinarySize);
auto genBinarySize = program->buildInfos[rootDeviceIndex].unpackedDeviceBinarySize;
@ -140,7 +186,7 @@ TEST_P(ProcessElfBinaryTestsWithBinaryType, GivenBinaryTypeWhenResolveProgramThe
EXPECT_EQ(CL_SUCCESS, retVal);
ASSERT_EQ(binarySize, program->buildInfos[rootDeviceIndex].packedDeviceBinarySize);
EXPECT_EQ(0, memcmp(pBinary.get(), program->buildInfos[rootDeviceIndex].packedDeviceBinary.get(), binarySize));
EXPECT_EQ(0, memcmp(pBinary.data(), program->buildInfos[rootDeviceIndex].packedDeviceBinary.get(), binarySize));
// delete program's elf reference to force a resolve
program->buildInfos[rootDeviceIndex].packedDeviceBinary.reset();
@ -178,7 +224,6 @@ TEST_P(ProcessElfBinaryTestsWithBinaryType, GivenBinaryTypeWhenResolveProgramThe
ASSERT_EQ(options.size(), decodedOptions.size());
ASSERT_EQ(genBinarySize, decodedDeviceBinary.size());
ASSERT_EQ(irBinarySize, decodedIr.size());
EXPECT_EQ(0, memcmp(genBinary.get(), decodedDeviceBinary.begin(), genBinarySize));
EXPECT_EQ(0, memcmp(irBinary.get(), decodedIr.begin(), irBinarySize));
}
@ -187,34 +232,12 @@ INSTANTIATE_TEST_CASE_P(ResolveBinaryTests,
ProcessElfBinaryTestsWithBinaryType,
::testing::ValuesIn(BinaryTypeValues));
TEST_F(ProcessElfBinaryTests, GivenMultipleCallsWhenCreatingProgramFromBinaryThenEachProgramIsCorrect) {
std::string filePath;
retrieveBinaryKernelFilename(filePath, "CopyBuffer_simd16_", ".bin");
size_t binarySize = 0;
auto pBinary = loadDataFromFile(filePath.c_str(), binarySize);
cl_int retVal = program->createProgramFromBinary(pBinary.get(), binarySize, *device);
EXPECT_EQ(CL_SUCCESS, retVal);
EXPECT_EQ(0, memcmp(pBinary.get(), program->buildInfos[rootDeviceIndex].packedDeviceBinary.get(), binarySize));
std::string filePath2;
retrieveBinaryKernelFilename(filePath2, "simple_arg_int_", ".bin");
pBinary = loadDataFromFile(filePath2.c_str(), binarySize);
retVal = program->createProgramFromBinary(pBinary.get(), binarySize, *device);
EXPECT_EQ(CL_SUCCESS, retVal);
EXPECT_EQ(0, memcmp(pBinary.get(), program->buildInfos[rootDeviceIndex].packedDeviceBinary.get(), binarySize));
}
TEST_F(ProcessElfBinaryTests, GivenEmptyBuildOptionsWhenCreatingProgramFromBinaryThenSuccessIsReturned) {
std::string filePath;
retrieveBinaryKernelFilename(filePath, "simple_kernels_", ".bin");
auto mockElf = std::make_unique<MockElfBinaryPatchtokens<>>(device->getHardwareInfo());
auto pBinary = mockElf->storage;
auto binarySize = mockElf->storage.size();
size_t binarySize = 0;
auto pBinary = loadDataFromFile(filePath.c_str(), binarySize);
cl_int retVal = program->createProgramFromBinary(pBinary.get(), binarySize, *device);
cl_int retVal = program->createProgramFromBinary(pBinary.data(), binarySize, *device);
EXPECT_EQ(CL_SUCCESS, retVal);
const auto &options = program->getOptions();
@ -223,16 +246,15 @@ TEST_F(ProcessElfBinaryTests, GivenEmptyBuildOptionsWhenCreatingProgramFromBinar
}
TEST_F(ProcessElfBinaryTests, GivenNonEmptyBuildOptionsWhenCreatingProgramFromBinaryThenSuccessIsReturned) {
std::string filePath;
retrieveBinaryKernelFilename(filePath, "simple_kernels_opts_", ".bin");
auto buildOptionsNotEmpty = CompilerOptions::concatenate(CompilerOptions::optDisable, "-DDEF_WAS_SPECIFIED=1");
auto mockElf = std::make_unique<MockElfBinaryPatchtokens<>>(buildOptionsNotEmpty, device->getHardwareInfo());
auto pBinary = mockElf->storage;
auto binarySize = mockElf->storage.size();
size_t binarySize = 0;
auto pBinary = loadDataFromFile(filePath.c_str(), binarySize);
cl_int retVal = program->createProgramFromBinary(pBinary.get(), binarySize, *device);
cl_int retVal = program->createProgramFromBinary(pBinary.data(), binarySize, *device);
EXPECT_EQ(CL_SUCCESS, retVal);
const auto &options = program->getOptions();
std::string buildOptionsNotEmpty = CompilerOptions::concatenate(CompilerOptions::optDisable, "-DDEF_WAS_SPECIFIED=1");
EXPECT_TRUE(hasSubstr(options, buildOptionsNotEmpty));
}
@ -256,4 +278,4 @@ TEST_F(ProcessElfBinaryTests, GivenBinaryWhenIncompatiblePatchtokenVerionThenPro
cl_int retVal = program->createProgramFromBinary(elfBinary.data(), elfBinary.size(), *device);
EXPECT_EQ(CL_INVALID_BINARY, retVal);
}
}
}