From ee4a1772962ed08cee9c3edc0a74d6be52617d2d Mon Sep 17 00:00:00 2001 From: Kacper Nowak Date: Wed, 11 May 2022 02:24:18 +0000 Subject: [PATCH] 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 --- .../program/process_elf_binary_tests.cpp | 116 +++++++++++------- 1 file changed, 69 insertions(+), 47 deletions(-) diff --git a/opencl/test/unit_test/program/process_elf_binary_tests.cpp b/opencl/test/unit_test/program/process_elf_binary_tests.cpp index 89c402a07f..8286b6ed0a 100644 --- a/opencl/test/unit_test/program/process_elf_binary_tests.cpp +++ b/opencl/test/unit_test/program/process_elf_binary_tests.cpp @@ -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 +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 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::fromAny(mockDevBinaryData, mockDevBinaryDataSize)); + if (irFormat == enabledIrFormat::ENABLE_SPIRV) + enc.appendSection(Elf::SHT_OPENCL_SPIRV, Elf::SectionNamesOpenCl::spirvObject, ArrayRef::fromAny(mockSpirvBinaryData, mockSpirvBinaryDataSize)); + else if (irFormat == enabledIrFormat::ENABLE_LLVM) + enc.appendSection(Elf::SHT_OPENCL_LLVM_BINARY, Elf::SectionNamesOpenCl::llvmObject, ArrayRef::fromAny(mockLlvmBinaryData, mockLlvmBinaryDataSize)); + if (false == buildOptions.empty()) + enc.appendSection(Elf::SHT_OPENCL_OPTIONS, Elf::SectionNamesOpenCl::buildOptions, ArrayRef::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 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>(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(MockDevice::createWithNewExecutionEnvironment(nullptr, rootDeviceIndex)); program = std::make_unique(nullptr, false, toClDeviceVector(*device)); } - std::unique_ptr program; std::unique_ptr device; const uint32_t rootDeviceIndex = 1; }; TEST_P(ProcessElfBinaryTestsWithBinaryType, GivenBinaryTypeWhenResolveProgramThenProgramIsProperlyResolved) { - std::string filePath; - retrieveBinaryKernelFilename(filePath, "CopyBuffer_simd16_", ".bin"); + auto mockElf = std::make_unique>(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>(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>(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); } -} +} \ No newline at end of file