diff --git a/opencl/test/unit_test/offline_compiler/mock/mock_offline_compiler.h b/opencl/test/unit_test/offline_compiler/mock/mock_offline_compiler.h index 9cdb5ff718..6783531ba6 100644 --- a/opencl/test/unit_test/offline_compiler/mock/mock_offline_compiler.h +++ b/opencl/test/unit_test/offline_compiler/mock/mock_offline_compiler.h @@ -11,6 +11,7 @@ #include "opencl/test/unit_test/offline_compiler/mock/mock_argument_helper.h" +#include #include namespace NEO { @@ -65,6 +66,16 @@ class MockOfflineCompiler : public OfflineCompiler { OfflineCompiler::storeBinary(genBinary, genBinarySize, pSrc, srcSize); } + int build() override { + ++buildCalledCount; + + if (buildReturnValue.has_value()) { + return *buildReturnValue; + } + + return OfflineCompiler::build(); + } + int buildSourceCode() override { if (overrideBuildSourceCodeStatus) { return buildSourceCodeStatus; @@ -94,5 +105,8 @@ class MockOfflineCompiler : public OfflineCompiler { uint32_t generateElfBinaryCalled = 0u; uint32_t writeOutAllFilesCalled = 0u; std::unique_ptr uniqueHelper; + int buildCalledCount{0}; + std::optional buildReturnValue{}; }; + } // namespace NEO diff --git a/opencl/test/unit_test/offline_compiler/ocloc_fatbinary_tests.cpp b/opencl/test/unit_test/offline_compiler/ocloc_fatbinary_tests.cpp index 0ffa4a66f8..198001173e 100644 --- a/opencl/test/unit_test/offline_compiler/ocloc_fatbinary_tests.cpp +++ b/opencl/test/unit_test/offline_compiler/ocloc_fatbinary_tests.cpp @@ -15,9 +15,15 @@ #include "shared/source/device_binary_format/elf/ocl_elf.h" #include "shared/source/helpers/hw_helper.h" +#include "environment.h" +#include "mock/mock_argument_helper.h" +#include "mock/mock_offline_compiler.h" + #include #include +extern Environment *gEnvironment; + namespace NEO { auto searchInArchiveByFilename(const Ar::Ar &archive, const ConstStringRef &name) { @@ -41,6 +47,15 @@ std::string prepareTwoDevices(MockOclocArgHelper *argHelper) { return cfg1 + "," + cfg2; } +std::string getDeviceConfig(const OfflineCompiler &offlineCompiler) { + const auto &hwInfo = offlineCompiler.getHardwareInfo(); + + const std::string product = hardwarePrefix[hwInfo.platform.eProductFamily]; + const auto stepping = hwInfo.platform.usRevId; + + return product + "." + std::to_string(stepping); +} + TEST(OclocFatBinaryRequestedFatBinary, WhenDeviceArgMissingThenReturnsFalse) { const char *args[] = {"ocloc", "-aaa", "*", "-device", "*"}; @@ -1231,4 +1246,142 @@ TEST_F(OclocFatBinaryTest, GivenInvalidIrFileWhenAppendingGenericIrThenInvalidFi EXPECT_EQ(expectedErrorMessage, output); } +TEST(OclocFatBinaryHelpersTest, GivenPreviousCompilationErrorWhenBuildingFatbinaryForTargetThenNothingIsDoneAndErrorIsReturned) { + const std::vector argv = { + "ocloc", + "-file", + "test_files/copybuffer.cl", + "-device", + gEnvironment->devicePrefix.c_str()}; + + MockOfflineCompiler mockOfflineCompiler{}; + mockOfflineCompiler.initialize(argv.size(), argv); + + // We expect that nothing is done and error is returned. + // Therefore, if offline compiler is used, ensure that it just returns error code, + // which is different than expected one. + mockOfflineCompiler.buildReturnValue = OclocErrorCode::SUCCESS; + + Ar::ArEncoder ar; + const std::string pointerSize{"32"}; + const auto mockArgHelper = mockOfflineCompiler.uniqueHelper.get(); + const auto deviceConfig = getDeviceConfig(mockOfflineCompiler); + + const int previousReturnValue{OclocErrorCode::INVALID_FILE}; + const auto buildResult = buildFatBinaryForTarget(previousReturnValue, argv, pointerSize, ar, &mockOfflineCompiler, mockArgHelper, deviceConfig); + + EXPECT_EQ(OclocErrorCode::INVALID_FILE, buildResult); + EXPECT_EQ(0, mockOfflineCompiler.buildCalledCount); +} + +TEST(OclocFatBinaryHelpersTest, GivenPreviousCompilationSuccessAndFailingBuildWhenBuildingFatbinaryForTargetThenCompilationIsInvokedAndErrorLogIsPrinted) { + const std::vector argv = { + "ocloc", + "-file", + "test_files/copybuffer.cl", + "-device", + gEnvironment->devicePrefix.c_str()}; + + MockOfflineCompiler mockOfflineCompiler{}; + mockOfflineCompiler.initialize(argv.size(), argv); + + mockOfflineCompiler.buildReturnValue = OclocErrorCode::INVALID_FILE; + + Ar::ArEncoder ar; + const std::string pointerSize{"32"}; + const auto mockArgHelper = mockOfflineCompiler.uniqueHelper.get(); + const auto deviceConfig = getDeviceConfig(mockOfflineCompiler); + + ::testing::internal::CaptureStdout(); + const int previousReturnValue{OclocErrorCode::SUCCESS}; + const auto buildResult = buildFatBinaryForTarget(previousReturnValue, argv, pointerSize, ar, &mockOfflineCompiler, mockArgHelper, deviceConfig); + const auto output{::testing::internal::GetCapturedStdout()}; + + EXPECT_EQ(OclocErrorCode::INVALID_FILE, buildResult); + EXPECT_EQ(1, mockOfflineCompiler.buildCalledCount); + + std::string commandString{}; + for (const auto &arg : argv) { + commandString += " "; + commandString += arg; + } + + const std::string expectedOutput{ + "Build failed for : " + deviceConfig + " with error code: -5151\n" + "Command was:" + + commandString + "\n"}; + EXPECT_EQ(expectedOutput, output); +} + +TEST(OclocFatBinaryHelpersTest, GivenNonEmptyBuildLogWhenBuildingFatbinaryForTargetThenBuildLogIsPrinted) { + using namespace std::string_literals; + + const std::vector argv = { + "ocloc", + "-file", + "test_files/copybuffer.cl", + "-device", + gEnvironment->devicePrefix.c_str()}; + + MockOfflineCompiler mockOfflineCompiler{}; + mockOfflineCompiler.initialize(argv.size(), argv); + + const char buildWarning[] = "Warning: This is a build log!"; + mockOfflineCompiler.updateBuildLog(buildWarning, sizeof(buildWarning)); + mockOfflineCompiler.buildReturnValue = OclocErrorCode::SUCCESS; + + // Dummy value + mockOfflineCompiler.elfBinary = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + + Ar::ArEncoder ar; + const std::string pointerSize{"32"}; + const auto mockArgHelper = mockOfflineCompiler.uniqueHelper.get(); + const auto deviceConfig = getDeviceConfig(mockOfflineCompiler); + + ::testing::internal::CaptureStdout(); + const int previousReturnValue{OclocErrorCode::SUCCESS}; + const auto buildResult = buildFatBinaryForTarget(previousReturnValue, argv, pointerSize, ar, &mockOfflineCompiler, mockArgHelper, deviceConfig); + const auto output{::testing::internal::GetCapturedStdout()}; + + EXPECT_EQ(OclocErrorCode::SUCCESS, buildResult); + EXPECT_EQ(1, mockOfflineCompiler.buildCalledCount); + + const std::string expectedOutput{buildWarning + "\nBuild succeeded for : "s + deviceConfig + ".\n"s}; + EXPECT_EQ(expectedOutput, output); +} + +TEST(OclocFatBinaryHelpersTest, GivenQuietModeWhenBuildingFatbinaryForTargetThenNothingIsPrinted) { + using namespace std::string_literals; + + const std::vector argv = { + "ocloc", + "-file", + "test_files/copybuffer.cl", + "-q", + "-device", + gEnvironment->devicePrefix.c_str()}; + + MockOfflineCompiler mockOfflineCompiler{}; + mockOfflineCompiler.initialize(argv.size(), argv); + + // Dummy value + mockOfflineCompiler.elfBinary = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + mockOfflineCompiler.buildReturnValue = OclocErrorCode::SUCCESS; + + Ar::ArEncoder ar; + const std::string pointerSize{"32"}; + const auto mockArgHelper = mockOfflineCompiler.uniqueHelper.get(); + const auto deviceConfig = getDeviceConfig(mockOfflineCompiler); + + ::testing::internal::CaptureStdout(); + const int previousReturnValue{OclocErrorCode::SUCCESS}; + const auto buildResult = buildFatBinaryForTarget(previousReturnValue, argv, pointerSize, ar, &mockOfflineCompiler, mockArgHelper, deviceConfig); + const auto output{::testing::internal::GetCapturedStdout()}; + + EXPECT_EQ(OclocErrorCode::SUCCESS, buildResult); + EXPECT_EQ(1, mockOfflineCompiler.buildCalledCount); + + EXPECT_TRUE(output.empty()) << output; +} + } // namespace NEO \ No newline at end of file diff --git a/shared/offline_compiler/source/ocloc_fatbinary.cpp b/shared/offline_compiler/source/ocloc_fatbinary.cpp index 1c4dad664a..858abf6b3e 100644 --- a/shared/offline_compiler/source/ocloc_fatbinary.cpp +++ b/shared/offline_compiler/source/ocloc_fatbinary.cpp @@ -309,7 +309,7 @@ std::vector getTargetConfigsForFatbinary(ConstStringRef deviceArg return retVal; } -int buildFatBinaryForTarget(int retVal, std::vector argsCopy, std::string pointerSize, Ar::ArEncoder &fatbinary, +int buildFatBinaryForTarget(int retVal, const std::vector &argsCopy, std::string pointerSize, Ar::ArEncoder &fatbinary, OfflineCompiler *pCompiler, OclocArgHelper *argHelper, const std::string &deviceConfig) { std::string product = hardwarePrefix[pCompiler->getHardwareInfo().platform.eProductFamily]; auto stepping = pCompiler->getHardwareInfo().platform.usRevId; diff --git a/shared/offline_compiler/source/ocloc_fatbinary.h b/shared/offline_compiler/source/ocloc_fatbinary.h index 5b64d802e5..1636ed4159 100644 --- a/shared/offline_compiler/source/ocloc_fatbinary.h +++ b/shared/offline_compiler/source/ocloc_fatbinary.h @@ -47,7 +47,7 @@ std::vector getProductConfigsForSpecificTargets(CompilerOptions:: std::vector getPlatformsForSpecificTargets(CompilerOptions::TokenizedString targets, OclocArgHelper *argHelper); std::vector toProductNames(const std::vector &productIds); PRODUCT_FAMILY asProductId(ConstStringRef product, const std::vector &allSupportedPlatforms); -int buildFatBinaryForTarget(int retVal, std::vector argsCopy, std::string pointerSize, Ar::ArEncoder &fatbinary, +int buildFatBinaryForTarget(int retVal, const std::vector &argsCopy, std::string pointerSize, Ar::ArEncoder &fatbinary, OfflineCompiler *pCompiler, OclocArgHelper *argHelper, const std::string &deviceConfig); int appendGenericIr(Ar::ArEncoder &fatbinary, const std::string &inputFile, OclocArgHelper *argHelper); std::vector createEncodedElfWithSpirv(const ArrayRef &spirv); diff --git a/shared/offline_compiler/source/offline_compiler.h b/shared/offline_compiler/source/offline_compiler.h index c18755a9d0..5c1e5f51e8 100644 --- a/shared/offline_compiler/source/offline_compiler.h +++ b/shared/offline_compiler/source/offline_compiler.h @@ -36,7 +36,7 @@ class OfflineCompiler { static int query(size_t numArgs, const std::vector &allArgs, OclocArgHelper *helper); static OfflineCompiler *create(size_t numArgs, const std::vector &allArgs, bool dumpFiles, int &retVal, OclocArgHelper *helper); - int build(); + MOCKABLE_VIRTUAL int build(); std::string &getBuildLog(); void printUsage(); std::string getDevicesConfigs();