/* * Copyright (C) 2022-2025 Intel Corporation * * SPDX-License-Identifier: MIT * */ #include "shared/offline_compiler/source/ocloc_api.h" #include "shared/source/device_binary_format/ar/ar_encoder.h" #include "shared/source/device_binary_format/elf/elf_encoder.h" #include "shared/test/common/mocks/mock_modules_zebin.h" #include "gtest/gtest.h" #include "mock/mock_argument_helper.h" #include "mock/mock_ocloc_concat.h" #include "platforms.h" #include namespace NEO { TEST(OclocConcatTest, GivenNoArgumentsWhenInitializingThenErrorIsReturned) { MockOclocArgHelper::FilesMap mockArgHelperFilesMap{}; MockOclocArgHelper mockArgHelper{mockArgHelperFilesMap}; auto oclocConcat = MockOclocConcat(&mockArgHelper); std::vector args = {"ocloc", "concat"}; mockArgHelper.messagePrinter.setSuppressMessages(true); auto error = oclocConcat.initialize(args); const auto output = mockArgHelper.getLog(); EXPECT_EQ(static_cast(OCLOC_INVALID_COMMAND_LINE), error); const std::string expectedOutput = "No files to concatenate were provided.\n"; EXPECT_EQ(expectedOutput, output); } TEST(OclocConcatTest, GivenMissingFilesWhenInitializingThenErrorIsReturned) { MockOclocArgHelper::FilesMap mockArgHelperFilesMap{}; MockOclocArgHelper mockArgHelper{mockArgHelperFilesMap}; auto oclocConcat = MockOclocConcat(&mockArgHelper); std::vector args = {"ocloc", "concat", "fatBinary1.ar", "fatBinary2.ar"}; mockArgHelper.messagePrinter.setSuppressMessages(true); auto error = oclocConcat.initialize(args); const auto output = mockArgHelper.getLog(); EXPECT_EQ(static_cast(OCLOC_INVALID_COMMAND_LINE), error); const std::string expectedOutput = "fatBinary1.ar doesn't exist!\nfatBinary2.ar doesn't exist!\n"; EXPECT_EQ(expectedOutput, output); } TEST(OclocConcatTest, GivenValidArgsWhenInitializingThenFileNamesToConcatAndOutputFileNameAreSetCorrectlyAndSuccessIsReturned) { MockOclocArgHelper::FilesMap mockArgHelperFilesMap{ {"fatBinary1.ar", "fatBinary1Data"}, {"fatBinary2.ar", "fatBinary2Data"}}; MockOclocArgHelper mockArgHelper{mockArgHelperFilesMap}; auto oclocConcat = MockOclocConcat(&mockArgHelper); std::vector args = {"ocloc", "concat", "fatBinary1.ar", "fatBinary2.ar", "-out", "fatBinary.ar"}; mockArgHelper.messagePrinter.setSuppressMessages(true); auto error = oclocConcat.initialize(args); const auto output = mockArgHelper.getLog(); EXPECT_EQ(static_cast(OCLOC_SUCCESS), error); EXPECT_TRUE(output.empty()); EXPECT_EQ(args[2], oclocConcat.fileNamesToConcat[0]); EXPECT_EQ(args[3], oclocConcat.fileNamesToConcat[1]); EXPECT_EQ(args[5], oclocConcat.fatBinaryName); } TEST(OclocConcatTest, GivenMissingOutFileNameAfterOutArgumentWhenInitalizingThenErrorIsReturned) { MockOclocArgHelper::FilesMap mockArgHelperFilesMap{}; MockOclocArgHelper mockArgHelper{mockArgHelperFilesMap}; auto oclocConcat = MockOclocConcat(&mockArgHelper); std::vector args = {"ocloc", "concat", "fatBinary1.ar", "fatBinary2.ar", "-out"}; mockArgHelper.messagePrinter.setSuppressMessages(true); auto error = oclocConcat.initialize(args); const auto output = mockArgHelper.getLog(); EXPECT_EQ(static_cast(OCLOC_INVALID_COMMAND_LINE), error); const std::string expectedOutput = "Missing out file name after \"-out\" argument\n"; EXPECT_EQ(expectedOutput, output); } TEST(OclocConcatTest, GivenErrorDuringDecodingArWhenConcatenatingThenErrorIsReturned) { MockOclocArgHelper::FilesMap mockArgHelperFilesMap{ {"fatBinary1.ar", "!\nInvalidAr"}, {"fatBinary2.ar", "!\nfatBinary2Data"}}; MockOclocArgHelper mockArgHelper{mockArgHelperFilesMap}; auto oclocConcat = MockOclocConcat(&mockArgHelper); mockArgHelper.messagePrinter.setSuppressMessages(true); oclocConcat.shouldFailDecodingAr = true; oclocConcat.fileNamesToConcat = {"fatBinary1.ar", "fatBinary2.ar"}; auto error = oclocConcat.concatenate(); const auto output = mockArgHelper.messagePrinter.getLog().str(); EXPECT_EQ(static_cast(OCLOC_INVALID_FILE), error); EXPECT_EQ("fatBinary1.ar : Error while decoding AR file\n", output); } TEST(OclocConcatTest, GivenBinaryFileNonZebinWhenConcatenatingThenErrorIsReturned) { MockOclocArgHelper::FilesMap mockArgHelperFilesMap{ {"binary.bin", "NOT Zebin"}}; MockOclocArgHelper mockArgHelper{mockArgHelperFilesMap}; auto oclocConcat = MockOclocConcat(&mockArgHelper); mockArgHelper.messagePrinter.setSuppressMessages(true); oclocConcat.fileNamesToConcat = {"binary.bin"}; auto error = oclocConcat.concatenate(); const auto output = mockArgHelper.messagePrinter.getLog().str(); EXPECT_EQ(static_cast(OCLOC_INVALID_FILE), error); EXPECT_EQ("binary.bin : Not a zebin file\n", output); } TEST(OclocConcatTest, GivenZebinWithoutAOTProductConfigWhenConcatenatingThenErrorIsReturned) { ZebinTestData::ValidEmptyProgram zebin64; ZebinTestData::ValidEmptyProgram zebin32; for (auto zebin : {&zebin64.storage, &zebin32.storage}) { MockOclocArgHelper::FilesMap mockArgHelperFilesMap{ {"zebin.bin", std::string(reinterpret_cast(zebin->data()), zebin->size())}}; MockOclocArgHelper mockArgHelper{mockArgHelperFilesMap}; auto oclocConcat = MockOclocConcat(&mockArgHelper); mockArgHelper.messagePrinter.setSuppressMessages(true); oclocConcat.fileNamesToConcat = {"zebin.bin"}; auto error = oclocConcat.concatenate(); const auto output = mockArgHelper.messagePrinter.getLog().str(); EXPECT_EQ(static_cast(OCLOC_INVALID_FILE), error); EXPECT_EQ("zebin.bin : Couldn't find AOT product configuration in intelGTNotes section.\n", output); } } TEST(OclocConcatTest, GivenZebinWithAOTNoteAndFatBinaryWhenConcatenatingThenCorrectFatBinaryIsProduced) { std::vector fatBinary; { std::array file{0}; NEO::Ar::ArEncoder arEncoder(true); arEncoder.appendFileEntry("10.0.0", ArrayRef::fromAny(file.data(), file.size())); arEncoder.appendFileEntry("11.0.0", ArrayRef::fromAny(file.data(), file.size())); fatBinary = arEncoder.encode(); } ZebinTestData::ValidEmptyProgram zebin; { AOT::PRODUCT_CONFIG productConfig = AOT::PRODUCT_CONFIG::TGL; // 12.0.0 zebin.appendSection(Elf::SHT_NOTE, Zebin::Elf::SectionNames::noteIntelGT, ZebinTestData::createIntelGTNoteSection(versionToString(NEO::Zebin::ZeInfo::zeInfoDecoderVersion), productConfig)); } MockOclocArgHelper::FilesMap mockArgHelperFilesMap{ {"binary.bin", std::string(reinterpret_cast(zebin.storage.data()), zebin.storage.size())}, {"fatBinary.ar", std::string(reinterpret_cast(fatBinary.data()), fatBinary.size())}}; MockOclocArgHelper mockArgHelper{mockArgHelperFilesMap}; mockArgHelper.interceptOutput = true; mockArgHelper.messagePrinter.setSuppressMessages(true); auto oclocConcat = MockOclocConcat(&mockArgHelper); oclocConcat.fileNamesToConcat = { "fatBinary.ar", "binary.bin", }; auto error = oclocConcat.concatenate(); const auto output = mockArgHelper.messagePrinter.getLog().str(); EXPECT_EQ(static_cast(OCLOC_SUCCESS), error); EXPECT_TRUE(output.empty()); EXPECT_EQ(1U, mockArgHelper.interceptedFiles.size()); std::string errors, warnings; auto &concatedFatBinary = mockArgHelper.interceptedFiles["concat.ar"]; auto concatedAr = NEO::Ar::decodeAr(ArrayRef::fromAny(reinterpret_cast(concatedFatBinary.data()), concatedFatBinary.size()), errors, warnings); EXPECT_TRUE(errors.empty()); EXPECT_TRUE(warnings.empty()); ASSERT_EQ(6U, concatedAr.files.size()); EXPECT_EQ("10.0.0", concatedAr.files[1].fileName); EXPECT_EQ("11.0.0", concatedAr.files[3].fileName); EXPECT_EQ("12.0.0", concatedAr.files[5].fileName); } } // namespace NEO