/* * Copyright (C) 2018-2024 Intel Corporation * * SPDX-License-Identifier: MIT * */ #include "shared/source/compiler_interface/compiler_cache.h" #include "shared/source/compiler_interface/compiler_interface.h" #include "shared/source/compiler_interface/compiler_interface.inl" #include "shared/source/compiler_interface/compiler_options.h" #include "shared/source/compiler_interface/oclc_extensions.h" #include "shared/source/helpers/compiler_product_helper.h" #include "shared/source/helpers/file_io.h" #include "shared/source/helpers/hw_info.h" #include "shared/source/os_interface/os_inc_base.h" #include "shared/test/common/fixtures/device_fixture.h" #include "shared/test/common/helpers/debug_manager_state_restore.h" #include "shared/test/common/helpers/test_files.h" #include "shared/test/common/helpers/unit_test_helper.h" #include "shared/test/common/libult/global_environment.h" #include "shared/test/common/mocks/mock_cif.h" #include "shared/test/common/mocks/mock_compiler_interface.h" #include "shared/test/common/mocks/mock_compilers.h" #include "shared/test/common/mocks/mock_device.h" #include "shared/test/common/test_macros/hw_test.h" #include "gtest/gtest.h" #include using namespace NEO; #if defined(_WIN32) const char *gBadDompilerDllName = "bad_compiler.dll"; #elif defined(__linux__) const char *gCBadDompilerDllName = "libbad_compiler.so"; #else #error "Unknown OS!" #endif class CompilerInterfaceTest : public DeviceFixture, public ::testing::Test { public: void SetUp() override { DeviceFixture::setUp(); // create the compiler interface this->pCompilerInterface = new MockCompilerInterface(); bool initRet = pCompilerInterface->initialize(std::make_unique(CompilerCacheConfig{}), true); ASSERT_TRUE(initRet); pDevice->getExecutionEnvironment()->rootDeviceEnvironments[pDevice->getRootDeviceIndex()]->compilerInterface.reset(pCompilerInterface); std::string testFile; testFile.append(clFiles); testFile.append("CopyBuffer_simd32.cl"); pSource = loadDataFromFile( testFile.c_str(), sourceSize); ASSERT_NE(0u, sourceSize); ASSERT_NE(nullptr, pSource); inputArgs.src = ArrayRef(pSource.get(), sourceSize); } void TearDown() override { pSource.reset(); DeviceFixture::tearDown(); } MockCompilerInterface *pCompilerInterface; TranslationInput inputArgs = {IGC::CodeType::oclC, IGC::CodeType::oclGenBin}; std::unique_ptr pSource = nullptr; size_t sourceSize = 0; }; TEST(CompilerInterface, WhenInitializeIsCalledThenFailIfCompilerCacheHandlerIsEmpty) { MockCompilerInterface ci; ci.failLoadFcl = false; ci.failLoadIgc = false; bool initSuccess = ci.initialize(nullptr, true); EXPECT_FALSE(initSuccess); } TEST(CompilerInterface, WhenInitializeIsCalledThenFailIfOneOfRequiredCompilersIsUnavailable) { bool initSuccess = false; bool requireFcl = true; MockCompilerInterface ci; ci.failLoadFcl = false; ci.failLoadIgc = false; requireFcl = true; initSuccess = ci.initialize(std::make_unique(CompilerCacheConfig{}), requireFcl); EXPECT_TRUE(initSuccess); ci.failLoadFcl = false; ci.failLoadIgc = false; requireFcl = false; initSuccess = ci.initialize(std::make_unique(CompilerCacheConfig{}), requireFcl); EXPECT_TRUE(initSuccess); ci.failLoadFcl = true; ci.failLoadIgc = false; requireFcl = false; initSuccess = ci.initialize(std::make_unique(CompilerCacheConfig{}), requireFcl); EXPECT_TRUE(initSuccess); ci.failLoadFcl = true; ci.failLoadIgc = false; requireFcl = true; initSuccess = ci.initialize(std::make_unique(CompilerCacheConfig{}), requireFcl); EXPECT_FALSE(initSuccess); ci.failLoadFcl = false; ci.failLoadIgc = true; requireFcl = true; initSuccess = ci.initialize(std::make_unique(CompilerCacheConfig{}), requireFcl); EXPECT_FALSE(initSuccess); ci.failLoadFcl = false; ci.failLoadIgc = true; requireFcl = false; initSuccess = ci.initialize(std::make_unique(CompilerCacheConfig{}), requireFcl); EXPECT_FALSE(initSuccess); ci.failLoadFcl = true; ci.failLoadIgc = true; requireFcl = false; initSuccess = ci.initialize(std::make_unique(CompilerCacheConfig{}), requireFcl); EXPECT_FALSE(initSuccess); ci.failLoadFcl = true; ci.failLoadIgc = true; requireFcl = true; initSuccess = ci.initialize(std::make_unique(CompilerCacheConfig{}), requireFcl); EXPECT_FALSE(initSuccess); } TEST(CompilerInterfaceCreateInstance, WhenInitializeFailedThenReturnNull) { struct FailInitializeCompilerInterface : CompilerInterface { bool initialize(std::unique_ptr &&cache, bool requireFcl) override { return false; } }; EXPECT_EQ(nullptr, CompilerInterface::createInstance(std::make_unique(CompilerCacheConfig{}), false)); } TEST_F(CompilerInterfaceTest, WhenCompilingToIsaThenSuccessIsReturned) { TranslationOutput translationOutput; auto err = pCompilerInterface->build(*pDevice, inputArgs, translationOutput); EXPECT_EQ(TranslationOutput::ErrorCode::success, err); } TEST_F(CompilerInterfaceTest, WhenPreferredIntermediateRepresentationSpecifiedThenPreserveIt) { CompilerCacheConfig config = {}; config.enabled = false; auto tempCompilerCache = std::make_unique(config); pCompilerInterface->cache.reset(tempCompilerCache.release()); TranslationOutput translationOutput; inputArgs.preferredIntermediateType = IGC::CodeType::llvmLl; auto err = pCompilerInterface->build(*pDevice, inputArgs, translationOutput); EXPECT_EQ(IGC::CodeType::llvmLl, translationOutput.intermediateCodeType); EXPECT_EQ(TranslationOutput::ErrorCode::success, err); } TEST_F(CompilerInterfaceTest, whenCompilerIsNotAvailableThenBuildFailsGracefully) { pCompilerInterface->igcMain.reset(nullptr); TranslationOutput translationOutput = {}; auto err = pCompilerInterface->build(*pDevice, inputArgs, translationOutput); EXPECT_EQ(TranslationOutput::ErrorCode::compilerNotAvailable, err); } TEST_F(CompilerInterfaceTest, whenFclTranslatorReturnsNullptrThenBuildFailsGracefully) { CompilerCacheConfig config = {}; config.enabled = false; auto tempCompilerCache = std::make_unique(config); pCompilerInterface->cache.reset(tempCompilerCache.release()); pCompilerInterface->failCreateFclTranslationCtx = true; TranslationOutput translationOutput = {}; auto err = pCompilerInterface->build(*pDevice, inputArgs, translationOutput); pCompilerInterface->failCreateFclTranslationCtx = false; EXPECT_EQ(TranslationOutput::ErrorCode::unknownError, err); } TEST_F(CompilerInterfaceTest, whenIgcTranslatorReturnsNullptrThenBuildFailsGracefully) { CompilerCacheConfig config = {}; config.enabled = false; auto tempCompilerCache = std::make_unique(config); pCompilerInterface->cache.reset(tempCompilerCache.release()); pCompilerInterface->failCreateIgcTranslationCtx = true; TranslationOutput translationOutput = {}; auto err = pCompilerInterface->build(*pDevice, inputArgs, translationOutput); pCompilerInterface->failCreateIgcTranslationCtx = true; EXPECT_EQ(TranslationOutput::ErrorCode::unknownError, err); } TEST_F(CompilerInterfaceTest, GivenOptionsWhenCompilingToIsaThenSuccessIsReturned) { std::string internalOptions = "SOME_OPTION"; MockCompilerDebugVars fclDebugVars; fclDebugVars.fileName = gEnvironment->fclGetMockFile(); fclDebugVars.internalOptionsExpected = true; gEnvironment->fclPushDebugVars(fclDebugVars); MockCompilerDebugVars igcDebugVars; igcDebugVars.fileName = gEnvironment->igcGetMockFile(); igcDebugVars.internalOptionsExpected = true; gEnvironment->igcPushDebugVars(igcDebugVars); inputArgs.internalOptions = ArrayRef(internalOptions.c_str(), internalOptions.length()); TranslationOutput translationOutput = {}; auto err = pCompilerInterface->build(*pDevice, inputArgs, translationOutput); EXPECT_EQ(TranslationOutput::ErrorCode::success, err); gEnvironment->fclPopDebugVars(); gEnvironment->igcPopDebugVars(); } TEST_F(CompilerInterfaceTest, WhenCompilingToIrThenSuccessIsReturned) { MockCompilerDebugVars fclDebugVars; retrieveBinaryKernelFilename(fclDebugVars.fileName, "CopyBuffer_simd32_", ".spv"); gEnvironment->fclPushDebugVars(fclDebugVars); TranslationOutput translationOutput = {}; auto err = pCompilerInterface->compile(*pDevice, inputArgs, translationOutput); EXPECT_EQ(TranslationOutput::ErrorCode::success, err); gEnvironment->fclPopDebugVars(); } TEST_F(CompilerInterfaceTest, GivenProgramCreatedFromIrWhenCompileIsCalledThenDontRecompile) { TranslationOutput translationOutput = {}; inputArgs.srcType = IGC::CodeType::spirV; auto err = pCompilerInterface->compile(*pDevice, inputArgs, translationOutput); EXPECT_EQ(TranslationOutput::ErrorCode::alreadyCompiled, err); inputArgs.srcType = IGC::CodeType::llvmBc; err = pCompilerInterface->compile(*pDevice, inputArgs, translationOutput); EXPECT_EQ(TranslationOutput::ErrorCode::alreadyCompiled, err); inputArgs.srcType = IGC::CodeType::llvmLl; err = pCompilerInterface->compile(*pDevice, inputArgs, translationOutput); EXPECT_EQ(TranslationOutput::ErrorCode::alreadyCompiled, err); inputArgs.srcType = IGC::CodeType::oclGenBin; err = pCompilerInterface->compile(*pDevice, inputArgs, translationOutput); EXPECT_EQ(TranslationOutput::ErrorCode::alreadyCompiled, err); } TEST_F(CompilerInterfaceTest, whenCompilerIsNotAvailableThenCompileFailsGracefully) { MockCompilerDebugVars fclDebugVars; fclDebugVars.fileName = clFiles + "copybuffer.elf"; gEnvironment->fclPushDebugVars(fclDebugVars); pCompilerInterface->igcMain->Release(); pCompilerInterface->setIgcMain(nullptr); TranslationOutput translationOutput = {}; auto err = pCompilerInterface->compile(*pDevice, inputArgs, translationOutput); EXPECT_EQ(TranslationOutput::ErrorCode::compilerNotAvailable, err); gEnvironment->fclPopDebugVars(); } TEST_F(CompilerInterfaceTest, whenFclTranslatorReturnsNullptrThenCompileFailsGracefully) { MockCompilerDebugVars fclDebugVars; fclDebugVars.fileName = clFiles + "copybuffer.elf"; gEnvironment->fclPushDebugVars(fclDebugVars); pCompilerInterface->failCreateFclTranslationCtx = true; TranslationOutput translationOutput = {}; auto err = pCompilerInterface->compile(*pDevice, inputArgs, translationOutput); pCompilerInterface->failCreateFclTranslationCtx = false; EXPECT_EQ(TranslationOutput::ErrorCode::unknownError, err); gEnvironment->fclPopDebugVars(); } TEST_F(CompilerInterfaceTest, GivenForceBuildFailureWhenCompilingToIrThenCompilationFailureErrorIsReturned) { MockCompilerDebugVars fclDebugVars; fclDebugVars.fileName = "../copybuffer.elf"; fclDebugVars.forceBuildFailure = true; gEnvironment->fclPushDebugVars(fclDebugVars); TranslationOutput translationOutput = {}; auto err = pCompilerInterface->compile(*pDevice, inputArgs, translationOutput); EXPECT_EQ(TranslationOutput::ErrorCode::compilationFailure, err); gEnvironment->fclPopDebugVars(); } TEST_F(CompilerInterfaceTest, GivenForceBuildFailureWhenLinkingIrThenLinkFailureErrorIsReturned) { MockCompilerDebugVars igcDebugVars; igcDebugVars.fileName = "../copybuffer.ll"; igcDebugVars.forceBuildFailure = true; gEnvironment->igcPushDebugVars(igcDebugVars); TranslationOutput translationOutput = {}; auto err = pCompilerInterface->link(*pDevice, inputArgs, translationOutput); EXPECT_EQ(TranslationOutput::ErrorCode::linkFailure, err); gEnvironment->igcPopDebugVars(); } TEST_F(CompilerInterfaceTest, WhenLinkIsCalledThenOclGenBinIsTheTranslationTarget) { // link only from .ll to gen ISA MockCompilerDebugVars igcDebugVars; retrieveBinaryKernelFilename(igcDebugVars.fileName, "CopyBuffer_simd32_", ".spv"); gEnvironment->igcPushDebugVars(igcDebugVars); TranslationOutput translationOutput = {}; auto err = pCompilerInterface->link(*pDevice, inputArgs, translationOutput); gEnvironment->igcPopDebugVars(); ASSERT_EQ(TranslationOutput::ErrorCode::success, err); ASSERT_EQ(1u, pCompilerInterface->requestedTranslationCtxs.size()); MockCompilerInterface::TranslationOpT translation = {IGC::CodeType::elf, IGC::CodeType::oclGenBin}; EXPECT_EQ(translation, pCompilerInterface->requestedTranslationCtxs[0]); } TEST_F(CompilerInterfaceTest, whenCompilerIsNotAvailableThenLinkFailsGracefully) { MockCompilerDebugVars igcDebugVars; igcDebugVars.fileName = clFiles + "copybuffer.ll"; gEnvironment->igcPushDebugVars(igcDebugVars); pCompilerInterface->igcMain->Release(); pCompilerInterface->setIgcMain(nullptr); TranslationOutput translationOutput = {}; auto err = pCompilerInterface->link(*pDevice, inputArgs, translationOutput); EXPECT_EQ(TranslationOutput::ErrorCode::compilerNotAvailable, err); gEnvironment->igcPopDebugVars(); } TEST_F(CompilerInterfaceTest, whenSrcAllocationFailsThenLinkFailsGracefully) { MockCompilerDebugVars igcDebugVars; igcDebugVars.fileName = clFiles + "copybuffer.ll"; gEnvironment->igcPushDebugVars(igcDebugVars); MockCIFBuffer::failAllocations = true; TranslationOutput translationOutput = {}; auto err = pCompilerInterface->link(*pDevice, inputArgs, translationOutput); MockCIFBuffer::failAllocations = false; EXPECT_EQ(TranslationOutput::ErrorCode::unknownError, err); gEnvironment->igcPopDebugVars(); } TEST_F(CompilerInterfaceTest, whenTranslateReturnsNullptrThenLinkFailsGracefully) { MockCompilerDebugVars igcDebugVars; igcDebugVars.fileName = clFiles + "copybuffer.ll"; gEnvironment->igcPushDebugVars(igcDebugVars); pCompilerInterface->failCreateIgcTranslationCtx = true; TranslationOutput translationOutput = {}; auto err = pCompilerInterface->link(*pDevice, inputArgs, translationOutput); pCompilerInterface->failCreateIgcTranslationCtx = false; EXPECT_EQ(TranslationOutput::ErrorCode::unknownError, err); gEnvironment->igcPopDebugVars(); } TEST_F(CompilerInterfaceTest, GivenForceBuildFailureWhenCreatingLibraryThenLinkFailureErrorIsReturned) { // create library from .ll to IR MockCompilerDebugVars igcDebugVars; igcDebugVars.fileName = "../copybuffer.ll"; igcDebugVars.forceBuildFailure = true; gEnvironment->igcPushDebugVars(igcDebugVars); TranslationOutput translationOutput = {}; auto err = pCompilerInterface->createLibrary(*pDevice, inputArgs, translationOutput); EXPECT_EQ(TranslationOutput::ErrorCode::linkFailure, err); gEnvironment->igcPopDebugVars(); } TEST_F(CompilerInterfaceTest, WhenCreateLibraryIsCalledThenLlvmBcIsUsedAsIntermediateRepresentation) { // create library from .ll to IR MockCompilerDebugVars igcDebugVars; retrieveBinaryKernelFilename(igcDebugVars.fileName, "CopyBuffer_simd32_", ".spv"); gEnvironment->igcPushDebugVars(igcDebugVars); TranslationOutput translationOutput = {}; auto err = pCompilerInterface->createLibrary(*pDevice, inputArgs, translationOutput); gEnvironment->igcPopDebugVars(); EXPECT_EQ(TranslationOutput::ErrorCode::success, err); ASSERT_EQ(1U, pCompilerInterface->requestedTranslationCtxs.size()); EXPECT_EQ(IGC::CodeType::llvmBc, pCompilerInterface->requestedTranslationCtxs[0].second); } TEST_F(CompilerInterfaceTest, whenCompilerIsNotAvailableThenCreateLibraryFailsGracefully) { MockCompilerDebugVars igcDebugVars; igcDebugVars.fileName = clFiles + "copybuffer.ll"; gEnvironment->igcPushDebugVars(igcDebugVars); pCompilerInterface->igcMain->Release(); pCompilerInterface->setIgcMain(nullptr); TranslationOutput translationOutput = {}; auto err = pCompilerInterface->createLibrary(*pDevice, inputArgs, translationOutput); EXPECT_EQ(TranslationOutput::ErrorCode::compilerNotAvailable, err); gEnvironment->igcPopDebugVars(); } TEST_F(CompilerInterfaceTest, whenIgcTranslatorReturnsNullptrThenCreateLibraryFailsGracefully) { MockCompilerDebugVars igcDebugVars; igcDebugVars.fileName = clFiles + "copybuffer.ll"; gEnvironment->igcPushDebugVars(igcDebugVars); pCompilerInterface->failCreateIgcTranslationCtx = true; TranslationOutput translationOutput = {}; auto err = pCompilerInterface->createLibrary(*pDevice, inputArgs, translationOutput); pCompilerInterface->failCreateIgcTranslationCtx = false; EXPECT_EQ(TranslationOutput::ErrorCode::unknownError, err); gEnvironment->igcPopDebugVars(); } TEST_F(CompilerInterfaceTest, GivenForceBuildFailureWhenFclBuildingThenBuildFailureErrorIsReturned) { CompilerCacheConfig config = {}; config.enabled = false; auto tempCompilerCache = std::make_unique(config); pCompilerInterface->cache.reset(tempCompilerCache.release()); MockCompilerDebugVars fclDebugVars; fclDebugVars.forceCreateFailure = false; fclDebugVars.forceBuildFailure = true; fclDebugVars.forceRegisterFail = false; fclDebugVars.fileName = "copybuffer_skl.spv"; gEnvironment->fclPushDebugVars(fclDebugVars); TranslationOutput translationOutput = {}; auto err = pCompilerInterface->build(*pDevice, inputArgs, translationOutput); EXPECT_EQ(TranslationOutput::ErrorCode::buildFailure, err); gEnvironment->fclPopDebugVars(); } TEST_F(CompilerInterfaceTest, GivenForceBuildFailureWhenIgcBuildingThenBuildFailureErrorIsReturned) { CompilerCacheConfig config = {}; config.enabled = false; auto tempCompilerCache = std::make_unique(config); pCompilerInterface->cache.reset(tempCompilerCache.release()); MockCompilerDebugVars igcDebugVars; igcDebugVars.forceCreateFailure = false; igcDebugVars.forceBuildFailure = true; igcDebugVars.forceRegisterFail = false; igcDebugVars.fileName = "copybuffer_skl.gen"; gEnvironment->igcPushDebugVars(igcDebugVars); TranslationOutput translationOutput = {}; auto err = pCompilerInterface->build(*pDevice, inputArgs, translationOutput); EXPECT_EQ(TranslationOutput::ErrorCode::buildFailure, err); gEnvironment->igcPopDebugVars(); } struct TranslationCtxMock { bool returnNullptr = false; bool returnNullptrOutput = false; bool returnNullptrLog = false; bool returnNullptrDebugData = false; CIF::Builtins::BufferSimple *receivedSrc = nullptr; CIF::Builtins::BufferSimple *receivedOpt = nullptr; CIF::Builtins::BufferSimple *receivedIntOpt = nullptr; CIF::Builtins::BufferSimple *receivedTracingOpt = nullptr; CIF::RAII::UPtr_t Translate(CIF::Builtins::BufferSimple *src, // NOLINT(readability-identifier-naming) CIF::Builtins::BufferSimple *options, CIF::Builtins::BufferSimple *internalOptions, CIF::Builtins::BufferSimple *tracingOptions, uint32_t tracingOptionsCount) { this->receivedSrc = src; this->receivedOpt = options; this->receivedIntOpt = internalOptions; this->receivedTracingOpt = tracingOptions; if (returnNullptr) { return CIF::RAII::UPtr_t(nullptr); } auto ret = new MockOclTranslationOutput(); if (returnNullptrOutput) { ret->output->Release(); ret->output = nullptr; } if (returnNullptrLog) { ret->log->Release(); ret->log = nullptr; } if (returnNullptrDebugData) { ret->debugData->Release(); ret->debugData = nullptr; } return CIF::RAII::UPtr_t(ret); } CIF::RAII::UPtr_t Translate(CIF::Builtins::BufferSimple *src, // NOLINT(readability-identifier-naming) CIF::Builtins::BufferSimple *options, CIF::Builtins::BufferSimple *internalOptions, CIF::Builtins::BufferSimple *tracingOptions, uint32_t tracingOptionsCount, void *gtpinInit) { return this->Translate(src, options, internalOptions, tracingOptions, tracingOptionsCount); } CIF::RAII::UPtr_t Translate(CIF::Builtins::BufferSimple *src, // NOLINT(readability-identifier-naming) CIF::Builtins::BufferSimple *specConstantsIds, CIF::Builtins::BufferSimple *specConstantsValues, CIF::Builtins::BufferSimple *options, CIF::Builtins::BufferSimple *internalOptions, CIF::Builtins::BufferSimple *tracingOptions, uint32_t tracingOptionsCount, void *gtPinInput) { return this->Translate(src, options, internalOptions, tracingOptions, tracingOptionsCount); } }; TEST(TranslateTest, whenArgsAreValidAndTranslatorReturnsValidOutputThenValidOutputIsReturned) { TranslationCtxMock mockTranslationCtx; auto mockSrc = std::make_unique(); auto mockOpt = std::make_unique(); auto mockIntOpt = std::make_unique(); auto ret = NEO::translate(&mockTranslationCtx, mockSrc.get(), mockOpt.get(), mockIntOpt.get()); EXPECT_NE(nullptr, ret); EXPECT_EQ(mockSrc.get(), mockTranslationCtx.receivedSrc); EXPECT_EQ(mockOpt.get(), mockTranslationCtx.receivedOpt); EXPECT_EQ(mockIntOpt.get(), mockTranslationCtx.receivedIntOpt); } TEST(TranslateTest, givenGtPinInputWhenArgsAreValidAndTranslatorReturnsValidOutputThenValidOutputIsReturned) { TranslationCtxMock mockTranslationCtx; auto mockSrc = std::make_unique(); auto mockOpt = std::make_unique(); auto mockIntOpt = std::make_unique(); auto ret = NEO::translate(&mockTranslationCtx, mockSrc.get(), mockOpt.get(), mockIntOpt.get(), nullptr); EXPECT_NE(nullptr, ret); EXPECT_EQ(mockSrc.get(), mockTranslationCtx.receivedSrc); EXPECT_EQ(mockOpt.get(), mockTranslationCtx.receivedOpt); EXPECT_EQ(mockIntOpt.get(), mockTranslationCtx.receivedIntOpt); } TEST(TranslateTest, whenArgsAreInvalidThenNullptrIsReturned) { auto mockSrc = std::make_unique(); auto mockOpt = std::make_unique(); auto mockIntOpt = std::make_unique(); auto ret = NEO::translate(nullptr, mockSrc.get(), mockOpt.get(), mockIntOpt.get()); EXPECT_EQ(nullptr, ret); } TEST(TranslateTest, givenGtPinInputWhenArgsAreInvalidThenNullptrIsReturned) { auto mockSrc = std::make_unique(); auto mockOpt = std::make_unique(); auto mockIntOpt = std::make_unique(); auto ret = NEO::translate(nullptr, mockSrc.get(), mockOpt.get(), mockIntOpt.get(), nullptr); EXPECT_EQ(nullptr, ret); } TEST(TranslateTest, whenTranslatorReturnsNullptrThenNullptrIsReturned) { TranslationCtxMock mockTranslationCtx; mockTranslationCtx.returnNullptr = true; auto mockCifBuffer = std::make_unique(); auto ret = NEO::translate(&mockTranslationCtx, mockCifBuffer.get(), mockCifBuffer.get(), mockCifBuffer.get()); EXPECT_EQ(nullptr, ret); } TEST(TranslateTest, givenSpecConstantsBuffersWhenTranslatorReturnsNullptrThenNullptrIsReturned) { TranslationCtxMock mockTranslationCtx; mockTranslationCtx.returnNullptr = true; auto mockCifBuffer = std::make_unique(); auto ret = NEO::translate(&mockTranslationCtx, mockCifBuffer.get(), mockCifBuffer.get(), mockCifBuffer.get(), mockCifBuffer.get(), mockCifBuffer.get(), nullptr); EXPECT_EQ(nullptr, ret); } TEST(TranslateTest, givenNullPtrAsGtPinInputWhenTranslatorReturnsNullptrThenNullptrIsReturned) { TranslationCtxMock mockTranslationCtx; mockTranslationCtx.returnNullptr = true; auto mockCifBuffer = std::make_unique(); auto ret = NEO::translate(&mockTranslationCtx, mockCifBuffer.get(), mockCifBuffer.get(), mockCifBuffer.get(), nullptr); EXPECT_EQ(nullptr, ret); } TEST(TranslateTest, whenTranslatorReturnsInvalidOutputThenNullptrIsReturned) { TranslationCtxMock mockTranslationCtx; auto mockCifBuffer = std::make_unique(); for (uint32_t i = 1; i <= maxNBitValue(3); ++i) { mockTranslationCtx.returnNullptrDebugData = (i & 1) != 0; mockTranslationCtx.returnNullptrLog = (i & (1 << 1)) != 0; mockTranslationCtx.returnNullptrOutput = (i & (1 << 2)) != 0; auto ret = NEO::translate(&mockTranslationCtx, mockCifBuffer.get(), mockCifBuffer.get(), mockCifBuffer.get()); EXPECT_EQ(nullptr, ret); } } TEST(TranslateTest, givenNullPtrAsGtPinInputWhenTranslatorReturnsInvalidOutputThenNullptrIsReturned) { TranslationCtxMock mockTranslationCtx; auto mockCifBuffer = std::make_unique(); for (uint32_t i = 1; i <= maxNBitValue(3); ++i) { mockTranslationCtx.returnNullptrDebugData = (i & 1) != 0; mockTranslationCtx.returnNullptrLog = (i & (1 << 1)) != 0; mockTranslationCtx.returnNullptrOutput = (i & (1 << 2)) != 0; auto ret = NEO::translate(&mockTranslationCtx, mockCifBuffer.get(), mockCifBuffer.get(), mockCifBuffer.get(), nullptr); EXPECT_EQ(nullptr, ret); } } TEST(TranslateTest, givenSpecConstantsBuffersAndNullPtrAsGtPinInputWhenTranslatorReturnsInvalidOutputThenNullptrIsReturned) { TranslationCtxMock mockTranslationCtx; auto mockCifBuffer = std::make_unique(); for (uint32_t i = 1; i <= maxNBitValue(3); ++i) { mockTranslationCtx.returnNullptrDebugData = (i & 1) != 0; mockTranslationCtx.returnNullptrLog = (i & (1 << 1)) != 0; mockTranslationCtx.returnNullptrOutput = (i & (1 << 2)) != 0; auto ret = NEO::translate(&mockTranslationCtx, mockCifBuffer.get(), mockCifBuffer.get(), mockCifBuffer.get(), mockCifBuffer.get(), mockCifBuffer.get(), nullptr); EXPECT_EQ(nullptr, ret); } } TEST(TranslateTest, whenAnyArgIsNullThenNullptrIsReturnedAndTranslatorIsNotInvoked) { TranslationCtxMock mockTranslationCtx; auto mockCifBuffer = std::make_unique(); for (uint32_t i = 0; i < maxNBitValue(3); ++i) { auto src = (i & 1) ? mockCifBuffer.get() : nullptr; auto opts = (i & (1 << 1)) ? mockCifBuffer.get() : nullptr; auto intOpts = (i & (1 << 2)) ? mockCifBuffer.get() : nullptr; auto ret = NEO::translate(&mockTranslationCtx, src, opts, intOpts); EXPECT_EQ(nullptr, ret); } EXPECT_EQ(nullptr, mockTranslationCtx.receivedSrc); EXPECT_EQ(nullptr, mockTranslationCtx.receivedOpt); EXPECT_EQ(nullptr, mockTranslationCtx.receivedIntOpt); EXPECT_EQ(nullptr, mockTranslationCtx.receivedTracingOpt); } TEST(LoadCompilerTest, whenEverythingIsOkThenReturnsTrueAndValidOutputs) { std::unique_ptr retLib; CIF::RAII::UPtr_t retMain; bool retVal = loadCompiler("", retLib, retMain); EXPECT_TRUE(retVal); EXPECT_NE(nullptr, retLib.get()); EXPECT_NE(nullptr, retMain.get()); } TEST(LoadCompilerTest, whenCouldNotLoadLibraryThenReturnFalseAndNullOutputs) { std::unique_ptr retLib; CIF::RAII::UPtr_t retMain; bool retVal = loadCompiler("_falseName.notRealLib", retLib, retMain); EXPECT_FALSE(retVal); EXPECT_EQ(nullptr, retLib.get()); EXPECT_EQ(nullptr, retMain.get()); } TEST(LoadCompilerTest, whenCreateMainFailsThenReturnFalseAndNullOutputs) { NEO::failCreateCifMain = true; std::unique_ptr retLib; CIF::RAII::UPtr_t retMain; bool retVal = loadCompiler("", retLib, retMain); EXPECT_FALSE(retVal); EXPECT_EQ(nullptr, retLib.get()); EXPECT_EQ(nullptr, retMain.get()); NEO::failCreateCifMain = false; } TEST(LoadCompilerTest, whenEntrypointInterfaceIsNotCompatibleThenReturnFalseAndNullOutputs) { std::unique_ptr retLib; CIF::RAII::UPtr_t retMain; bool retVal = loadCompiler("", retLib, retMain); EXPECT_FALSE(retVal); EXPECT_EQ(nullptr, retLib.get()); EXPECT_EQ(nullptr, retMain.get()); } TEST(LoadCompilerTest, whenLoadCompilerWhenEntryIgcOclDeviceCtxThenIgnoreIgcsIcbeVersion) { std::unique_ptr retLib; CIF::RAII::UPtr_t retMain; bool retVal = loadCompiler("", retLib, retMain); EXPECT_TRUE(retVal); EXPECT_NE(nullptr, retLib.get()); EXPECT_NE(nullptr, retMain.get()); } template struct MockCompilerDeviceCtx : DeviceCtxBase { TranslationCtx *CreateTranslationCtxImpl(CIF::Version_t ver, IGC::CodeType::CodeType_t inType, IGC::CodeType::CodeType_t outType) override { returned = new TranslationCtx; return returned; } TranslationCtx *returned = nullptr; }; template struct LockListener { LockListener(NEO::Device *device, bool createDeviceCtxOnLock = true) : device(device), createDeviceCtxOnLock(createDeviceCtxOnLock) { } static void listener(MockCompilerInterface &compInt) { auto data = (LockListener *)compInt.lockListenerData; data->lockCount += 1; if (data->createDeviceCtxOnLock && compInt.getDeviceContexts().empty()) { auto deviceCtx = CIF::RAII::UPtr(new MockDeviceCtx); compInt.setDeviceCtx(*data->device, deviceCtx.get()); data->createdDeviceCtx = deviceCtx.get(); } } NEO::Device *device = nullptr; MockDeviceCtx *createdDeviceCtx = nullptr; bool createDeviceCtxOnLock = false; int lockCount = 0; }; struct WasLockedListener { static void listener(MockCompilerInterface &compInt) { auto data = (WasLockedListener *)compInt.lockListenerData; data->wasLocked = true; } bool wasLocked = false; }; TEST_F(CompilerInterfaceTest, givenUpdatedSpecConstValuesWhenBuildProgramThenProperValuesArePassed) { struct MockTranslationContextSpecConst : public MockIgcOclTranslationCtx { IGC::OclTranslationOutputBase *TranslateImpl( CIF::Version_t outVersion, CIF::Builtins::BufferSimple *src, CIF::Builtins::BufferSimple *specConstantsIds, CIF::Builtins::BufferSimple *specConstantsValues, CIF::Builtins::BufferSimple *options, CIF::Builtins::BufferSimple *internalOptions, CIF::Builtins::BufferSimple *tracingOptions, uint32_t tracingOptionsCount, void *gtPinInput) override { EXPECT_EQ(10u, specConstantsIds->GetMemory()[0]); EXPECT_EQ(100u, specConstantsValues->GetMemory()[0]); return new MockOclTranslationOutput(); } }; auto specConstCtx = CIF::RAII::UPtr(new MockCompilerDeviceCtx()); pCompilerInterface->setDeviceCtx(*pDevice, specConstCtx.get()); specConstValuesMap specConst{{10, 100}}; inputArgs.specializedValues = specConst; TranslationOutput translationOutput; auto err = pCompilerInterface->build(*pDevice, inputArgs, translationOutput); EXPECT_EQ(TranslationOutput::ErrorCode::success, err); } TEST_F(CompilerInterfaceTest, GivenRequestForNewFclTranslationCtxWhenDeviceCtxIsNotAvailableThenCreateNewDeviceCtxAndUseItToReturnValidTranslationCtx) { auto device = this->pDevice; auto ret = this->pCompilerInterface->createFclTranslationCtx(*device, IGC::CodeType::oclC, IGC::CodeType::spirV); EXPECT_NE(nullptr, ret.get()); auto firstBaseCtx = this->pCompilerInterface->getFclBaseTranslationCtx(); EXPECT_NE(nullptr, firstBaseCtx); MockDevice md; auto ret2 = this->pCompilerInterface->createFclTranslationCtx(md, IGC::CodeType::oclC, IGC::CodeType::spirV); EXPECT_NE(nullptr, ret2.get()); EXPECT_EQ(firstBaseCtx, this->pCompilerInterface->getFclBaseTranslationCtx()); } TEST_F(CompilerInterfaceTest, GivenRequestForNewFclTranslationCtxWhenDeviceCtxIsAlreadyAvailableThenUseItToReturnValidTranslationCtx) { auto device = this->pDevice; auto deviceCtx = CIF::RAII::UPtr(new MockCompilerDeviceCtx); this->pCompilerInterface->setFclDeviceCtx(*device, deviceCtx.get()); auto ret = this->pCompilerInterface->createFclTranslationCtx(*device, IGC::CodeType::oclC, IGC::CodeType::spirV); EXPECT_NE(nullptr, ret.get()); EXPECT_EQ(deviceCtx->returned, ret.get()); } TEST_F(CompilerInterfaceTest, GivenSimultaneousRequestForNewFclTranslationContextsWhenDeviceCtxIsNotAlreadyAvailableThenSynchronizeToCreateOnlyOneNewDeviceCtx) { auto device = this->pDevice; using ListenerT = LockListener; ListenerT listenerData(device); this->pCompilerInterface->lockListenerData = &listenerData; this->pCompilerInterface->lockListener = ListenerT::listener; EXPECT_EQ(0, listenerData.lockCount); auto ret = this->pCompilerInterface->createFclTranslationCtx(*device, IGC::CodeType::oclC, IGC::CodeType::spirV); EXPECT_EQ(2, listenerData.lockCount); EXPECT_NE(nullptr, ret.get()); ASSERT_EQ(1U, this->pCompilerInterface->getFclDeviceContexts().size()); ASSERT_NE(this->pCompilerInterface->getFclDeviceContexts().end(), this->pCompilerInterface->getFclDeviceContexts().find(device)); EXPECT_NE(nullptr, listenerData.createdDeviceCtx); EXPECT_EQ(listenerData.createdDeviceCtx, this->pCompilerInterface->getFclDeviceContexts()[device].get()); WasLockedListener wasLockedListenerData; this->pCompilerInterface->lockListenerData = &wasLockedListenerData; this->pCompilerInterface->lockListener = WasLockedListener::listener; ret = this->pCompilerInterface->createFclTranslationCtx(*device, IGC::CodeType::spirV, IGC::CodeType::oclGenBin); EXPECT_NE(nullptr, ret.get()); ASSERT_EQ(1U, this->pCompilerInterface->getFclDeviceContexts().size()); EXPECT_TRUE(wasLockedListenerData.wasLocked); } TEST_F(CompilerInterfaceTest, GivenRequestForNewTranslationCtxWhenFclMainIsNotAvailableThenReturnNullptr) { NEO::failCreateCifMain = true; auto device = this->pDevice; MockCompilerInterface tempCompilerInterface; auto retFcl = tempCompilerInterface.createFclTranslationCtx(*device, IGC::CodeType::oclC, IGC::CodeType::spirV); EXPECT_EQ(nullptr, retFcl); auto retIgc = tempCompilerInterface.createIgcTranslationCtx(*device, IGC::CodeType::oclC, IGC::CodeType::spirV); EXPECT_EQ(nullptr, retIgc); NEO::failCreateCifMain = false; } TEST_F(CompilerInterfaceTest, GivenRequestForNewTranslationCtxWhenCouldNotCreateDeviceCtxThenReturnNullptr) { auto device = this->pDevice; auto befFclMock = NEO::MockCIFMain::getGlobalCreatorFunc(); auto befIgcMock = NEO::MockCIFMain::getGlobalCreatorFunc(); NEO::MockCIFMain::setGlobalCreatorFunc(nullptr); NEO::MockCIFMain::setGlobalCreatorFunc(nullptr); auto retFcl = pCompilerInterface->createFclTranslationCtx(*device, IGC::CodeType::oclC, IGC::CodeType::spirV); EXPECT_EQ(nullptr, retFcl); auto retIgc = pCompilerInterface->createIgcTranslationCtx(*device, IGC::CodeType::oclC, IGC::CodeType::spirV); EXPECT_EQ(nullptr, retIgc); NEO::MockCIFMain::setGlobalCreatorFunc(befFclMock); NEO::MockCIFMain::setGlobalCreatorFunc(befIgcMock); } TEST_F(CompilerInterfaceTest, GivenRequestForNewIgcTranslationCtxWhenDeviceCtxIsAlreadyAvailableThenUseItToReturnValidTranslationCtx) { auto device = this->pDevice; auto deviceCtx = CIF::RAII::UPtr(new MockCompilerDeviceCtx); this->pCompilerInterface->setIgcDeviceCtx(*device, deviceCtx.get()); auto ret = this->pCompilerInterface->createIgcTranslationCtx(*device, IGC::CodeType::spirV, IGC::CodeType::oclGenBin); EXPECT_NE(nullptr, ret.get()); EXPECT_EQ(deviceCtx->returned, ret.get()); } TEST_F(CompilerInterfaceTest, GivenSimultaneousRequestForNewIgcTranslationContextsWhenDeviceCtxIsNotAlreadyAvailableThenSynchronizeToCreateOnlyOneNewDeviceCtx) { auto device = this->pDevice; using ListenerT = LockListener; ListenerT listenerData{device}; this->pCompilerInterface->lockListenerData = &listenerData; this->pCompilerInterface->lockListener = ListenerT::listener; auto ret = this->pCompilerInterface->createIgcTranslationCtx(*device, IGC::CodeType::spirV, IGC::CodeType::oclGenBin); EXPECT_NE(nullptr, ret.get()); ASSERT_EQ(1U, this->pCompilerInterface->getIgcDeviceContexts().size()); ASSERT_NE(this->pCompilerInterface->getIgcDeviceContexts().end(), this->pCompilerInterface->getIgcDeviceContexts().find(device)); EXPECT_NE(nullptr, listenerData.createdDeviceCtx); EXPECT_EQ(listenerData.createdDeviceCtx, this->pCompilerInterface->getIgcDeviceContexts()[device].get()); WasLockedListener wasLockedListenerData; this->pCompilerInterface->lockListenerData = &wasLockedListenerData; this->pCompilerInterface->lockListener = WasLockedListener::listener; ret = this->pCompilerInterface->createIgcTranslationCtx(*device, IGC::CodeType::spirV, IGC::CodeType::oclGenBin); EXPECT_NE(nullptr, ret.get()); ASSERT_EQ(1U, this->pCompilerInterface->getIgcDeviceContexts().size()); EXPECT_TRUE(wasLockedListenerData.wasLocked); } TEST_F(CompilerInterfaceTest, GivenRequestForNewIgcTranslationCtxWhenCouldNotPopulatePlatformInfoThenReturnNullptr) { auto device = this->pDevice; auto prevDebugVars = getIgcDebugVars(); for (uint32_t i = 1; i < (1 << 3); ++i) { this->pCompilerInterface->getIgcDeviceContexts().clear(); auto debugVars = prevDebugVars; debugVars.failCreatePlatformInterface = (i & 1) != 0; debugVars.failCreateIgcFeWaInterface = (i & (1 << 2)) != 0; debugVars.failCreateGtSystemInfoInterface = (i & (1 << 1)) != 0; setIgcDebugVars(debugVars); auto ret = pCompilerInterface->createIgcTranslationCtx(*device, IGC::CodeType::spirV, IGC::CodeType::oclGenBin); EXPECT_EQ(nullptr, ret); } setIgcDebugVars(prevDebugVars); } HWTEST_F(CompilerInterfaceTest, givenNoDbgKeyForceUseDifferentPlatformWhenRequestForNewTranslationCtxThenUseDefaultPlatform) { auto device = this->pDevice; auto retIgc = pCompilerInterface->createIgcTranslationCtx(*device, IGC::CodeType::spirV, IGC::CodeType::oclGenBin); EXPECT_NE(nullptr, retIgc); IGC::IgcOclDeviceCtxTagOCL *devCtx = pCompilerInterface->peekIgcDeviceCtx(device); auto igcPlatform = devCtx->GetPlatformHandle(); auto igcSysInfo = devCtx->GetGTSystemInfoHandle(); auto hwInfo = device->getHardwareInfo(); device->getCompilerProductHelper().adjustHwInfoForIgc(hwInfo); EXPECT_EQ(hwInfo.platform.eProductFamily, igcPlatform->GetProductFamily()); EXPECT_EQ(hwInfo.platform.eRenderCoreFamily, igcPlatform->GetRenderCoreFamily()); EXPECT_EQ(hwInfo.gtSystemInfo.SliceCount, igcSysInfo->GetSliceCount()); EXPECT_EQ(hwInfo.gtSystemInfo.SubSliceCount, igcSysInfo->GetSubSliceCount()); EXPECT_EQ(hwInfo.gtSystemInfo.EUCount, igcSysInfo->GetEUCount()); EXPECT_EQ(hwInfo.gtSystemInfo.ThreadCount, igcSysInfo->GetThreadCount()); } HWTEST_F(CompilerInterfaceTest, givenDbgKeyForceUseDifferentPlatformWhenRequestForNewTranslationCtxThenUseDbgKeyPlatform) { DebugManagerStateRestore dbgRestore; auto dbgProdFamily = defaultHwInfo->platform.eProductFamily; std::string dbgPlatformString(hardwarePrefix[dbgProdFamily]); const GT_SYSTEM_INFO dbgSystemInfo = hardwareInfoTable[dbgProdFamily]->gtSystemInfo; debugManager.flags.ForceCompilerUsePlatform.set(dbgPlatformString); auto device = this->pDevice; device->getRootDeviceEnvironment().getMutableHardwareInfo()->platform.eProductFamily = IGFX_UNKNOWN; device->getRootDeviceEnvironment().getMutableHardwareInfo()->platform.eRenderCoreFamily = IGFX_UNKNOWN_CORE; auto retIgc = pCompilerInterface->createIgcTranslationCtx(*device, IGC::CodeType::spirV, IGC::CodeType::oclGenBin); EXPECT_NE(nullptr, retIgc); IGC::IgcOclDeviceCtxTagOCL *devCtx = pCompilerInterface->peekIgcDeviceCtx(device); auto igcPlatform = devCtx->GetPlatformHandle(); auto igcSysInfo = devCtx->GetGTSystemInfoHandle(); auto hwInfo = *hardwareInfoTable[dbgProdFamily]; device->getCompilerProductHelper().adjustHwInfoForIgc(hwInfo); EXPECT_EQ(hwInfo.platform.eProductFamily, igcPlatform->GetProductFamily()); EXPECT_EQ(hwInfo.platform.eRenderCoreFamily, igcPlatform->GetRenderCoreFamily()); EXPECT_EQ(dbgSystemInfo.SliceCount, igcSysInfo->GetSliceCount()); EXPECT_EQ(dbgSystemInfo.SubSliceCount, igcSysInfo->GetSubSliceCount()); EXPECT_EQ(dbgSystemInfo.DualSubSliceCount, igcSysInfo->GetSubSliceCount()); EXPECT_EQ(dbgSystemInfo.EUCount, igcSysInfo->GetEUCount()); EXPECT_EQ(dbgSystemInfo.ThreadCount, igcSysInfo->GetThreadCount()); } TEST_F(CompilerInterfaceTest, GivenCompilerWhenGettingCompilerAvailabilityThenCompilerHasCorrectCapabilities) { ASSERT_TRUE(this->pCompilerInterface->igcMain && this->pCompilerInterface->fclMain); EXPECT_TRUE(this->pCompilerInterface->isFclAvailable()); EXPECT_TRUE(this->pCompilerInterface->isIgcAvailable()); EXPECT_TRUE(this->pCompilerInterface->isCompilerAvailable(IGC::CodeType::oclC, IGC::CodeType::oclGenBin)); EXPECT_TRUE(this->pCompilerInterface->isCompilerAvailable(IGC::CodeType::oclC, IGC::CodeType::spirV)); EXPECT_TRUE(this->pCompilerInterface->isCompilerAvailable(IGC::CodeType::oclC, IGC::CodeType::llvmBc)); EXPECT_TRUE(this->pCompilerInterface->isCompilerAvailable(IGC::CodeType::oclC, IGC::CodeType::llvmLl)); EXPECT_TRUE(this->pCompilerInterface->isCompilerAvailable(IGC::CodeType::spirV, IGC::CodeType::oclGenBin)); EXPECT_TRUE(this->pCompilerInterface->isCompilerAvailable(IGC::CodeType::llvmBc, IGC::CodeType::oclGenBin)); EXPECT_TRUE(this->pCompilerInterface->isCompilerAvailable(IGC::CodeType::llvmLl, IGC::CodeType::oclGenBin)); EXPECT_TRUE(this->pCompilerInterface->isCompilerAvailable(IGC::CodeType::elf, IGC::CodeType::llvmBc)); EXPECT_TRUE(this->pCompilerInterface->isCompilerAvailable(IGC::CodeType::elf, IGC::CodeType::oclGenBin)); auto befIgcImain = std::move(this->pCompilerInterface->igcMain); EXPECT_TRUE(this->pCompilerInterface->isFclAvailable()); EXPECT_FALSE(this->pCompilerInterface->isIgcAvailable()); EXPECT_FALSE(this->pCompilerInterface->isCompilerAvailable(IGC::CodeType::oclC, IGC::CodeType::oclGenBin)); EXPECT_TRUE(this->pCompilerInterface->isCompilerAvailable(IGC::CodeType::oclC, IGC::CodeType::spirV)); EXPECT_TRUE(this->pCompilerInterface->isCompilerAvailable(IGC::CodeType::oclC, IGC::CodeType::llvmBc)); EXPECT_TRUE(this->pCompilerInterface->isCompilerAvailable(IGC::CodeType::oclC, IGC::CodeType::llvmLl)); EXPECT_FALSE(this->pCompilerInterface->isCompilerAvailable(IGC::CodeType::spirV, IGC::CodeType::oclGenBin)); EXPECT_FALSE(this->pCompilerInterface->isCompilerAvailable(IGC::CodeType::llvmBc, IGC::CodeType::oclGenBin)); EXPECT_FALSE(this->pCompilerInterface->isCompilerAvailable(IGC::CodeType::llvmLl, IGC::CodeType::oclGenBin)); EXPECT_FALSE(this->pCompilerInterface->isCompilerAvailable(IGC::CodeType::elf, IGC::CodeType::llvmBc)); EXPECT_FALSE(this->pCompilerInterface->isCompilerAvailable(IGC::CodeType::elf, IGC::CodeType::oclGenBin)); this->pCompilerInterface->igcMain = std::move(befIgcImain); auto befFclImain = std::move(this->pCompilerInterface->fclMain); EXPECT_FALSE(this->pCompilerInterface->isFclAvailable()); EXPECT_TRUE(this->pCompilerInterface->isIgcAvailable()); EXPECT_FALSE(this->pCompilerInterface->isCompilerAvailable(IGC::CodeType::oclC, IGC::CodeType::oclGenBin)); EXPECT_FALSE(this->pCompilerInterface->isCompilerAvailable(IGC::CodeType::oclC, IGC::CodeType::spirV)); EXPECT_FALSE(this->pCompilerInterface->isCompilerAvailable(IGC::CodeType::oclC, IGC::CodeType::llvmBc)); EXPECT_FALSE(this->pCompilerInterface->isCompilerAvailable(IGC::CodeType::oclC, IGC::CodeType::llvmLl)); EXPECT_TRUE(this->pCompilerInterface->isCompilerAvailable(IGC::CodeType::spirV, IGC::CodeType::oclGenBin)); EXPECT_TRUE(this->pCompilerInterface->isCompilerAvailable(IGC::CodeType::llvmBc, IGC::CodeType::oclGenBin)); EXPECT_TRUE(this->pCompilerInterface->isCompilerAvailable(IGC::CodeType::llvmLl, IGC::CodeType::oclGenBin)); EXPECT_TRUE(this->pCompilerInterface->isCompilerAvailable(IGC::CodeType::elf, IGC::CodeType::llvmBc)); EXPECT_TRUE(this->pCompilerInterface->isCompilerAvailable(IGC::CodeType::elf, IGC::CodeType::oclGenBin)); this->pCompilerInterface->fclMain = std::move(befFclImain); befIgcImain = std::move(this->pCompilerInterface->igcMain); befFclImain = std::move(this->pCompilerInterface->fclMain); EXPECT_FALSE(this->pCompilerInterface->isFclAvailable()); EXPECT_FALSE(this->pCompilerInterface->isIgcAvailable()); EXPECT_FALSE(this->pCompilerInterface->isCompilerAvailable(IGC::CodeType::oclC, IGC::CodeType::oclGenBin)); EXPECT_FALSE(this->pCompilerInterface->isCompilerAvailable(IGC::CodeType::oclC, IGC::CodeType::spirV)); EXPECT_FALSE(this->pCompilerInterface->isCompilerAvailable(IGC::CodeType::oclC, IGC::CodeType::llvmBc)); EXPECT_FALSE(this->pCompilerInterface->isCompilerAvailable(IGC::CodeType::oclC, IGC::CodeType::llvmLl)); EXPECT_FALSE(this->pCompilerInterface->isCompilerAvailable(IGC::CodeType::spirV, IGC::CodeType::oclGenBin)); EXPECT_FALSE(this->pCompilerInterface->isCompilerAvailable(IGC::CodeType::llvmBc, IGC::CodeType::oclGenBin)); EXPECT_FALSE(this->pCompilerInterface->isCompilerAvailable(IGC::CodeType::llvmLl, IGC::CodeType::oclGenBin)); EXPECT_FALSE(this->pCompilerInterface->isCompilerAvailable(IGC::CodeType::elf, IGC::CodeType::llvmBc)); EXPECT_FALSE(this->pCompilerInterface->isCompilerAvailable(IGC::CodeType::elf, IGC::CodeType::oclGenBin)); this->pCompilerInterface->igcMain = std::move(befIgcImain); this->pCompilerInterface->fclMain = std::move(befFclImain); } TEST_F(CompilerInterfaceTest, whenCompilerIsNotAvailableThenGetSipKernelBinaryFailsGracefully) { pCompilerInterface->igcMain.reset(); std::vector sipBinary; std::vector stateAreaHeader; auto err = pCompilerInterface->getSipKernelBinary(*this->pDevice, SipKernelType::csr, sipBinary, stateAreaHeader); EXPECT_EQ(TranslationOutput::ErrorCode::compilerNotAvailable, err); EXPECT_EQ(0U, sipBinary.size()); } TEST_F(CompilerInterfaceTest, whenIgcReturnsErrorThenGetSipKernelBinaryFailsGracefully) { MockCompilerDebugVars igcDebugVars; igcDebugVars.forceBuildFailure = true; gEnvironment->igcPushDebugVars(igcDebugVars); std::vector sipBinary; std::vector stateAreaHeader; auto err = pCompilerInterface->getSipKernelBinary(*this->pDevice, SipKernelType::csr, sipBinary, stateAreaHeader); EXPECT_EQ(TranslationOutput::ErrorCode::unknownError, err); EXPECT_EQ(0U, sipBinary.size()); gEnvironment->igcPopDebugVars(); } TEST_F(CompilerInterfaceTest, whenGetIgcDeviceCtxReturnsNullptrThenGetSipKernelBinaryFailsGracefully) { pCompilerInterface->failGetIgcDeviceCtx = true; std::vector sipBinary; std::vector stateAreaHeader; auto err = pCompilerInterface->getSipKernelBinary(*this->pDevice, SipKernelType::csr, sipBinary, stateAreaHeader); EXPECT_EQ(TranslationOutput::ErrorCode::unknownError, err); } TEST_F(CompilerInterfaceTest, whenEverythingIsOkThenGetSipKernelReturnsIgcsOutputAsSipBinary) { MockCompilerDebugVars igcDebugVars; retrieveBinaryKernelFilename(igcDebugVars.fileName, "CopyBuffer_simd32_", ".spv"); gEnvironment->igcPushDebugVars(igcDebugVars); std::vector sipBinary; std::vector stateAreaHeader; auto err = pCompilerInterface->getSipKernelBinary(*this->pDevice, SipKernelType::csr, sipBinary, stateAreaHeader); EXPECT_EQ(TranslationOutput::ErrorCode::success, err); EXPECT_NE(0U, sipBinary.size()); gEnvironment->igcPopDebugVars(); } TEST_F(CompilerInterfaceTest, whenRequestingSipKernelBinaryThenProperSystemRoutineIsSelectedFromCompiler) { MockCompilerDebugVars igcDebugVars; gEnvironment->igcPushDebugVars(igcDebugVars); std::vector sipBinary; std::vector stateAreaHeader; auto err = pCompilerInterface->getSipKernelBinary(*this->pDevice, SipKernelType::csr, sipBinary, stateAreaHeader); EXPECT_EQ(TranslationOutput::ErrorCode::success, err); EXPECT_NE(0U, sipBinary.size()); EXPECT_EQ(IGC::SystemRoutineType::contextSaveRestore, getIgcDebugVars().typeOfSystemRoutine); err = pCompilerInterface->getSipKernelBinary(*this->pDevice, SipKernelType::dbgCsr, sipBinary, stateAreaHeader); EXPECT_EQ(TranslationOutput::ErrorCode::success, err); EXPECT_NE(0U, sipBinary.size()); EXPECT_EQ(IGC::SystemRoutineType::debug, getIgcDebugVars().typeOfSystemRoutine); err = pCompilerInterface->getSipKernelBinary(*this->pDevice, SipKernelType::dbgCsrLocal, sipBinary, stateAreaHeader); EXPECT_EQ(TranslationOutput::ErrorCode::success, err); EXPECT_NE(0U, sipBinary.size()); EXPECT_EQ(IGC::SystemRoutineType::debugSlm, getIgcDebugVars().typeOfSystemRoutine); gEnvironment->igcPopDebugVars(); } TEST_F(CompilerInterfaceTest, WhenRequestingBindlessDebugSipThenProperSystemRoutineIsSelectedFromCompiler) { MockCompilerDebugVars igcDebugVars; gEnvironment->igcPushDebugVars(igcDebugVars); std::vector sipBinary; std::vector stateAreaHeader; auto err = pCompilerInterface->getSipKernelBinary(*this->pDevice, SipKernelType::csr, sipBinary, stateAreaHeader); EXPECT_EQ(TranslationOutput::ErrorCode::success, err); EXPECT_NE(0U, sipBinary.size()); EXPECT_EQ(IGC::SystemRoutineType::contextSaveRestore, getIgcDebugVars().typeOfSystemRoutine); EXPECT_EQ(MockCompilerDebugVars::SipAddressingType::bindful, getIgcDebugVars().receivedSipAddressingType); err = pCompilerInterface->getSipKernelBinary(*this->pDevice, SipKernelType::dbgCsrLocal, sipBinary, stateAreaHeader); EXPECT_EQ(TranslationOutput::ErrorCode::success, err); EXPECT_NE(0U, sipBinary.size()); EXPECT_EQ(IGC::SystemRoutineType::debugSlm, getIgcDebugVars().typeOfSystemRoutine); EXPECT_EQ(MockCompilerDebugVars::SipAddressingType::bindful, getIgcDebugVars().receivedSipAddressingType); err = pCompilerInterface->getSipKernelBinary(*this->pDevice, SipKernelType::dbgBindless, sipBinary, stateAreaHeader); EXPECT_EQ(TranslationOutput::ErrorCode::success, err); EXPECT_NE(0U, sipBinary.size()); EXPECT_EQ(IGC::SystemRoutineType::debug, getIgcDebugVars().typeOfSystemRoutine); EXPECT_EQ(MockCompilerDebugVars::SipAddressingType::bindless, getIgcDebugVars().receivedSipAddressingType); gEnvironment->igcPopDebugVars(); } TEST_F(CompilerInterfaceTest, whenRequestingInvalidSipKernelBinaryThenErrorIsReturned) { MockCompilerDebugVars igcDebugVars; gEnvironment->igcPushDebugVars(igcDebugVars); std::vector sipBinary; std::vector stateAreaHeader; auto err = pCompilerInterface->getSipKernelBinary(*this->pDevice, SipKernelType::count, sipBinary, stateAreaHeader); EXPECT_EQ(TranslationOutput::ErrorCode::unknownError, err); EXPECT_EQ(0U, sipBinary.size()); EXPECT_EQ(IGC::SystemRoutineType::undefined, getIgcDebugVars().typeOfSystemRoutine); gEnvironment->igcPopDebugVars(); } TEST_F(CompilerInterfaceTest, whenCompilerIsNotAvailableThenGetSpecializationConstantsFails) { pCompilerInterface->igcMain.reset(); NEO::SpecConstantInfo sci; auto err = pCompilerInterface->getSpecConstantsInfo(*pDevice, ArrayRef{}, sci); EXPECT_EQ(TranslationOutput::ErrorCode::compilerNotAvailable, err); } TEST_F(CompilerInterfaceTest, givenCompilerInterfacewhenGettingIgcFeaturesAndWorkaroundsThenValidPointerIsReturned) { auto igcFeaturesAndWorkarounds = pCompilerInterface->getIgcFeaturesAndWorkarounds(*pDevice); EXPECT_NE(igcFeaturesAndWorkarounds, nullptr); EXPECT_EQ(igcFeaturesAndWorkarounds->GetMaxOCLParamSize(), 0u); } TEST_F(CompilerInterfaceTest, GivenRequestForNewFclTranslationCtxWhenInterfaceVersionAbove4ThenPopulatePlatformInfo) { auto device = this->pDevice; auto prevDebugVars = getFclDebugVars(); auto debugVars = prevDebugVars; debugVars.overrideFclDeviceCtxVersion = 5; setFclDebugVars(debugVars); auto ret = pCompilerInterface->createFclTranslationCtx(*device, IGC::CodeType::oclC, IGC::CodeType::spirV); ASSERT_NE(nullptr, ret); ASSERT_EQ(1U, pCompilerInterface->fclDeviceContexts.size()); auto platform = pCompilerInterface->fclDeviceContexts.begin()->second->GetPlatformHandle(); ASSERT_NE(nullptr, platform); EXPECT_EQ(device->getHardwareInfo().platform.eProductFamily, platform->GetProductFamily()); setFclDebugVars(prevDebugVars); } TEST_F(CompilerInterfaceTest, GivenRequestForNewFclTranslationCtxWhenCouldNotPopulatePlatformInfoAndInterfaceVersionAbove4ThenReturnNullptr) { auto device = this->pDevice; auto prevDebugVars = getFclDebugVars(); auto debugVars = prevDebugVars; debugVars.failCreatePlatformInterface = true; debugVars.overrideFclDeviceCtxVersion = 5; setFclDebugVars(debugVars); auto ret = pCompilerInterface->createFclTranslationCtx(*device, IGC::CodeType::oclC, IGC::CodeType::spirV); EXPECT_EQ(nullptr, ret); setFclDebugVars(prevDebugVars); } TEST_F(CompilerInterfaceTest, GivenRequestForNewFclTranslationCtxWhenInterfaceVersion4ThenDontPopulatePlatformInfo) { auto device = this->pDevice; auto prevDebugVars = getFclDebugVars(); auto debugVars = prevDebugVars; debugVars.failCreatePlatformInterface = true; debugVars.overrideFclDeviceCtxVersion = 4; setFclDebugVars(debugVars); auto ret = pCompilerInterface->createFclTranslationCtx(*device, IGC::CodeType::oclC, IGC::CodeType::spirV); EXPECT_NE(nullptr, ret); setFclDebugVars(prevDebugVars); } struct SpecConstantsTranslationCtxMock { bool returnFalse = false; CIF::Builtins::BufferSimple *receivedSrc = nullptr; CIF::Builtins::BufferSimple *receivedOutSpecConstantsIds = nullptr; CIF::Builtins::BufferSimple *receivedOutSpecConstantsSizes = nullptr; bool GetSpecConstantsInfoImpl(CIFBuffer *src, CIFBuffer *outSpecConstantsIds, CIFBuffer *outSpecConstantsSizes) { // NOLINT(readability-identifier-naming) this->receivedSrc = src; this->receivedOutSpecConstantsIds = outSpecConstantsIds; this->receivedOutSpecConstantsSizes = outSpecConstantsSizes; return !returnFalse; } }; TEST(GetSpecConstantsTest, givenNullptrTranslationContextAndBuffersWhenGetSpecializationConstantsThenErrorIsReturned) { EXPECT_FALSE(NEO::getSpecConstantsInfoImpl(nullptr, nullptr, nullptr, nullptr)); } TEST(GetSpecConstantsTest, whenGetSpecializationConstantsSuccedThenSuccessIsReturnedAndBuffersArePassed) { SpecConstantsTranslationCtxMock tCtxMock; auto mockSrc = std::make_unique(); auto mockIds = std::make_unique(); auto mockSizes = std::make_unique(); auto ret = NEO::getSpecConstantsInfoImpl(&tCtxMock, mockSrc.get(), mockIds.get(), mockSizes.get()); EXPECT_TRUE(ret); EXPECT_EQ(mockSrc.get(), tCtxMock.receivedSrc); EXPECT_EQ(mockIds.get(), tCtxMock.receivedOutSpecConstantsIds); EXPECT_EQ(mockSizes.get(), tCtxMock.receivedOutSpecConstantsSizes); } TEST(GetSpecConstantsTest, whenGetSpecializationConstantsFailThenErrorIsReturnedAndBuffersArePassed) { SpecConstantsTranslationCtxMock tCtxMock; tCtxMock.returnFalse = true; auto mockSrc = std::make_unique(); auto mockIds = std::make_unique(); auto mockSizes = std::make_unique(); auto ret = NEO::getSpecConstantsInfoImpl(&tCtxMock, mockSrc.get(), mockIds.get(), mockSizes.get()); EXPECT_FALSE(ret); EXPECT_EQ(mockSrc.get(), tCtxMock.receivedSrc); EXPECT_EQ(mockIds.get(), tCtxMock.receivedOutSpecConstantsIds); EXPECT_EQ(mockSizes.get(), tCtxMock.receivedOutSpecConstantsSizes); } TEST_F(CompilerInterfaceTest, whenIgcTranlationContextCreationFailsThenErrorIsReturned) { pCompilerInterface->failCreateIgcTranslationCtx = true; NEO::SpecConstantInfo specConstInfo; auto err = pCompilerInterface->getSpecConstantsInfo(*pDevice, inputArgs.src, specConstInfo); EXPECT_EQ(TranslationOutput::ErrorCode::unknownError, err); } TEST_F(CompilerInterfaceTest, givenCompilerInterfaceWhenGetSpecializationConstantsThenSuccessIsReturned) { TranslationOutput translationOutput; NEO::SpecConstantInfo specConstInfo; auto err = pCompilerInterface->getSpecConstantsInfo(*pDevice, inputArgs.src, specConstInfo); EXPECT_EQ(TranslationOutput::ErrorCode::success, err); } struct UnknownInterfaceCIFMain : MockCIFMain { CIF::InterfaceId_t FindIncompatibleImpl(CIF::InterfaceId_t entryPointInterface, CIF::CompatibilityDataHandle handle) const override { return CIF::UnknownInterface; } }; struct MockCompilerInterfaceWithUnknownInterfaceCIFMain : MockCompilerInterface { bool loadFcl() override { CompilerInterface::loadFcl(); fclMain.reset(new UnknownInterfaceCIFMain()); if (failLoadFcl) { return false; } return true; } bool loadIgc() override { CompilerInterface::loadIgc(); igcMain.reset(new UnknownInterfaceCIFMain()); if (failLoadIgc) { return false; } return true; } }; TEST(TestCompilerInterface, givenNullCompilerCacheAndFlagZebinIgnoreIcbeVersionDisabledWhenVerifyIcbeVersionReturnFalseThenInitializationNotSuccess) { DebugManagerStateRestore dbgRestore; debugManager.flags.EnableDebugBreak.set(0); debugManager.flags.PrintDebugMessages.set(0); debugManager.flags.ZebinIgnoreIcbeVersion.set(0); MockCompilerInterfaceWithUnknownInterfaceCIFMain ci; ci.failLoadFcl = false; ci.failLoadIgc = false; bool initSuccess = ci.initialize(nullptr, true); EXPECT_FALSE(initSuccess); } TEST(TestCompilerInterface, givenRequiredFclAndFlagZebinIgnoreIcbeVersionDisabledWhenVerifyIcbeVersionReturnFalseThenInitializationNotSuccess) { DebugManagerStateRestore dbgRestore; debugManager.flags.EnableDebugBreak.set(0); debugManager.flags.PrintDebugMessages.set(0); debugManager.flags.ZebinIgnoreIcbeVersion.set(0); MockCompilerInterfaceWithUnknownInterfaceCIFMain ci; bool requireFcl = true; ci.failLoadFcl = false; ci.failLoadIgc = false; EXPECT_FALSE(ci.initialize(std::make_unique(CompilerCacheConfig{}), requireFcl)); } TEST(TestCompilerInterface, givenNotRequiredFclAndFlagZebinIgnoreIcbeVersionDisabledWhenVerifyIcbeVersionReturnFalseThenInitializationNotSuccess) { DebugManagerStateRestore dbgRestore; debugManager.flags.EnableDebugBreak.set(0); debugManager.flags.PrintDebugMessages.set(0); debugManager.flags.ZebinIgnoreIcbeVersion.set(0); MockCompilerInterfaceWithUnknownInterfaceCIFMain ci; bool requireFcl = false; ci.failLoadFcl = false; ci.failLoadIgc = false; EXPECT_FALSE(ci.initialize(std::make_unique(CompilerCacheConfig{}), requireFcl)); } TEST(TestCompilerInterface, givenNotRequiredFclAndFclLoadFaildAndFlagZebinIgnoreIcbeVersionDisabledWhenVerifyIcbeVersionReturnFalseThenInitializationNotSuccess) { DebugManagerStateRestore dbgRestore; debugManager.flags.EnableDebugBreak.set(0); debugManager.flags.PrintDebugMessages.set(0); debugManager.flags.ZebinIgnoreIcbeVersion.set(0); MockCompilerInterfaceWithUnknownInterfaceCIFMain ci; bool requireFcl = false; ci.failLoadFcl = true; ci.failLoadIgc = false; EXPECT_FALSE(ci.initialize(std::make_unique(CompilerCacheConfig{}), requireFcl)); } TEST(TestCompilerInterface, givenRequiredFclAndFclLoadFaildAndFlagZebinIgnoreIcbeVersionDisabledWhenVerifyIcbeVersionReturnFalseThenInitializationNotSuccess) { DebugManagerStateRestore dbgRestore; debugManager.flags.EnableDebugBreak.set(0); debugManager.flags.PrintDebugMessages.set(0); debugManager.flags.ZebinIgnoreIcbeVersion.set(0); MockCompilerInterfaceWithUnknownInterfaceCIFMain ci; bool requireFcl = true; ci.failLoadFcl = true; ci.failLoadIgc = false; EXPECT_FALSE(ci.initialize(std::make_unique(CompilerCacheConfig{}), requireFcl)); } TEST(TestCompilerInterface, givenRequiredFclAndIgcLoadFaildAndFlagZebinIgnoreIcbeVersionDisabledWhenVerifyIcbeVersionReturnFalseThenInitializationNotSuccess) { DebugManagerStateRestore dbgRestore; debugManager.flags.EnableDebugBreak.set(0); debugManager.flags.PrintDebugMessages.set(0); debugManager.flags.ZebinIgnoreIcbeVersion.set(0); MockCompilerInterfaceWithUnknownInterfaceCIFMain ci; bool requireFcl = true; ci.failLoadFcl = false; ci.failLoadIgc = true; EXPECT_FALSE(ci.initialize(std::make_unique(CompilerCacheConfig{}), requireFcl)); } TEST(TestCompilerInterface, givenNotRequiredFclAndIgcLoadFaildAndFlagZebinIgnoreIcbeVersionDisabledWhenVerifyIcbeVersionReturnFalseThenInitializationNotSuccess) { DebugManagerStateRestore dbgRestore; debugManager.flags.EnableDebugBreak.set(0); debugManager.flags.PrintDebugMessages.set(0); debugManager.flags.ZebinIgnoreIcbeVersion.set(0); MockCompilerInterfaceWithUnknownInterfaceCIFMain ci; bool requireFcl = false; ci.failLoadFcl = false; ci.failLoadIgc = true; EXPECT_FALSE(ci.initialize(std::make_unique(CompilerCacheConfig{}), requireFcl)); } TEST(TestCompilerInterface, givenNotRequiredFclAndFclAndIgcLoadFaildAndFlagZebinIgnoreIcbeVersionDisabledWhenVerifyIcbeVersionReturnFalseThenInitializationNotSuccess) { DebugManagerStateRestore dbgRestore; debugManager.flags.EnableDebugBreak.set(0); debugManager.flags.PrintDebugMessages.set(0); debugManager.flags.ZebinIgnoreIcbeVersion.set(0); MockCompilerInterfaceWithUnknownInterfaceCIFMain ci; bool requireFcl = false; ci.failLoadFcl = true; ci.failLoadIgc = true; EXPECT_FALSE(ci.initialize(std::make_unique(CompilerCacheConfig{}), requireFcl)); } TEST(TestCompilerInterface, givenRequiredFclAndFclAndIgcLoadFaildAndFlagZebinIgnoreIcbeVersionDisabledWhenVerifyIcbeVersionReturnFalseThenInitializationNotSuccess) { DebugManagerStateRestore dbgRestore; debugManager.flags.EnableDebugBreak.set(0); debugManager.flags.PrintDebugMessages.set(0); debugManager.flags.ZebinIgnoreIcbeVersion.set(0); MockCompilerInterfaceWithUnknownInterfaceCIFMain ci; bool requireFcl = true; ci.failLoadFcl = true; ci.failLoadIgc = true; EXPECT_FALSE(ci.initialize(std::make_unique(CompilerCacheConfig{}), requireFcl)); } TEST(TestCompilerInterface, givenZebinIgnoreIcbeVersionFlagWhenVerifyIcbeVersionFailThenInitializationReturnProperValues) { DebugManagerStateRestore dbgRestore; debugManager.flags.EnableDebugBreak.set(0); debugManager.flags.PrintDebugMessages.set(1); debugManager.flags.ZebinIgnoreIcbeVersion.set(1); auto mockCompilerInterface = std::make_unique(); testing::internal::CaptureStderr(); bool initializationOfCompilerInterfaceSuccessed = mockCompilerInterface->initialize(std::make_unique(CompilerCacheConfig{}), true); EXPECT_TRUE(initializationOfCompilerInterfaceSuccessed); std::string stderrString = testing::internal::GetCapturedStderr(); EXPECT_TRUE(stderrString.empty()); debugManager.flags.ZebinIgnoreIcbeVersion.set(0); testing::internal::CaptureStderr(); initializationOfCompilerInterfaceSuccessed = mockCompilerInterface->initialize(std::make_unique(CompilerCacheConfig{}), true); EXPECT_FALSE(initializationOfCompilerInterfaceSuccessed); stderrString = testing::internal::GetCapturedStderr(); EXPECT_FALSE(stderrString.empty()); } TEST(TestCompilerInterface, givenUnknownInterfaceForIgcAndFclWhenCheckIcbeVersionThenPrintProperDebugMessageOnce) { auto dummy = std::make_unique(); auto mockCompilerInterface = std::make_unique(); DebugManagerStateRestore dbgRestore; debugManager.flags.EnableDebugBreak.set(0); debugManager.flags.PrintDebugMessages.set(1); std::string dummyString = "dummy"; std::string expectedError = "Installed Compiler Library " + dummyString + " is incompatible\n"; testing::internal::CaptureStderr(); auto err = mockCompilerInterface->checkIcbeVersionOnce(dummy.get(), dummyString.c_str()); EXPECT_FALSE(err); std::string stderrString = testing::internal::GetCapturedStderr(); EXPECT_EQ(expectedError, stderrString); testing::internal::CaptureStderr(); err = mockCompilerInterface->checkIcbeVersionOnce(dummy.get(), dummyString.c_str()); EXPECT_FALSE(err); stderrString = testing::internal::GetCapturedStderr(); EXPECT_EQ(expectedError, stderrString); // second check for the same EntryPointTs testing::internal::CaptureStderr(); mockCompilerInterface->checkIcbeVersionOnce(dummy.get(), dummyString.c_str()); stderrString = testing::internal::GetCapturedStderr(); EXPECT_TRUE(stderrString.empty()); testing::internal::CaptureStderr(); mockCompilerInterface->checkIcbeVersionOnce(dummy.get(), dummyString.c_str()); stderrString = testing::internal::GetCapturedStderr(); EXPECT_TRUE(stderrString.empty()); } TEST(TestCompilerInterface, givenUnknownInterfaceAndFclMainWhenverifyIcbeVersionThenPrintProperDebugMessage) { DebugManagerStateRestore dbgRestore; debugManager.flags.EnableDebugBreak.set(0); debugManager.flags.PrintDebugMessages.set(1); auto dummy = new UnknownInterfaceCIFMain(); auto mockCompilerInterface = std::make_unique(); mockCompilerInterface->fclMain.reset(dummy); mockCompilerInterface->igcMain.reset(nullptr); std::string expectedError = "Installed Compiler Library " + std::string(Os::frontEndDllName) + " is incompatible\n"; testing::internal::CaptureStderr(); auto err = mockCompilerInterface->verifyIcbeVersion(); EXPECT_FALSE(err); std::string stderrString = testing::internal::GetCapturedStderr(); EXPECT_FALSE(stderrString.empty()); } TEST(TestCompilerInterface, givenUnknownInterfaceAndIgcMainWhenverifyIcbeVersionThenPrintProperDebugMessage) { DebugManagerStateRestore dbgRestore; debugManager.flags.EnableDebugBreak.set(0); debugManager.flags.PrintDebugMessages.set(1); auto dummy = new UnknownInterfaceCIFMain(); auto mockCompilerInterface = std::make_unique(); mockCompilerInterface->igcMain.reset(dummy); mockCompilerInterface->fclMain.reset(nullptr); std::string expectedError = "Installed Compiler Library " + std::string(Os::igcDllName) + " is incompatible\n"; testing::internal::CaptureStderr(); EXPECT_FALSE(mockCompilerInterface->verifyIcbeVersion()); std::string stderrString = testing::internal::GetCapturedStderr(); EXPECT_EQ(expectedError, stderrString); } TEST(TestCompilerInterface, givenUnknownInterfaceAndFclMainAndIgcMainWhenVerifyIcbeVersionThenPrintProperDebugMessage) { DebugManagerStateRestore dbgRestore; debugManager.flags.EnableDebugBreak.set(0); debugManager.flags.PrintDebugMessages.set(1); auto dummyIgc = new UnknownInterfaceCIFMain(); auto dummyFcl = new UnknownInterfaceCIFMain(); auto mockCompilerInterface = std::make_unique(); mockCompilerInterface->igcMain.reset(dummyIgc); mockCompilerInterface->fclMain.reset(dummyFcl); std::string expectedError = "Installed Compiler Library " + std::string(Os::frontEndDllName) + " is incompatible\n" + "Installed Compiler Library " + std::string(Os::igcDllName) + " is incompatible\n"; testing::internal::CaptureStderr(); EXPECT_FALSE(mockCompilerInterface->verifyIcbeVersion()); std::string stderrString = testing::internal::GetCapturedStderr(); EXPECT_EQ(expectedError, stderrString); } TEST(TestCompilerInterface, givenInvalidIcbeVersionWhenAddOptionDisableZebinThenFalseIsReturned) { DebugManagerStateRestore dbgRestore; debugManager.flags.EnableDebugBreak.set(0); debugManager.flags.PrintDebugMessages.set(0); auto dummyInValid = new UnknownInterfaceCIFMain(); auto mockCompilerInterface = std::make_unique(); mockCompilerInterface->igcMain.reset(dummyInValid); std::string option = ""; std::string internalOption = ""; EXPECT_FALSE(mockCompilerInterface->addOptionDisableZebin(option, internalOption)); } TEST(TestCompilerInterface, givenOptionsWhenCallDisableZebinThenProperOptionsAreSet) { DebugManagerStateRestore dbgRestore; debugManager.flags.EnableDebugBreak.set(0); debugManager.flags.PrintDebugMessages.set(0); auto dummyValid = new MockCIFMain(); auto mockCompilerInterface = std::make_unique(); mockCompilerInterface->igcMain.reset(dummyValid); std::string options = ""; std::string internalOptions = ""; EXPECT_TRUE(mockCompilerInterface->disableZebin(options, internalOptions)); EXPECT_TRUE(CompilerOptions::contains(internalOptions, NEO::CompilerOptions::disableZebin.str())); } TEST(TranslationOutput, givenNonEmptyPointerAndSizeWhenMakingCopyThenCloneInputData) { MockCIFBuffer src; src.data.assign({2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37}); std::string dstString; TranslationOutput::makeCopy(dstString, &src); ASSERT_EQ(src.GetSize(), dstString.size()); EXPECT_EQ(0, memcmp(src.GetMemory(), dstString.c_str(), dstString.size())); TranslationOutput::MemAndSize dstBuffer; TranslationOutput::makeCopy(dstBuffer, &src); ASSERT_EQ(src.GetSize(), dstBuffer.size); ASSERT_NE(nullptr, dstBuffer.mem); EXPECT_EQ(0, memcmp(src.GetMemory(), dstBuffer.mem.get(), dstBuffer.size)); } TEST(TranslationOutput, givenNullPointerWhenMakingCopyThenClearOutOutput) { MockCIFBuffer src; src.data.assign({2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37}); std::string dstString; TranslationOutput::makeCopy(dstString, &src); TranslationOutput::MemAndSize dstBuffer; TranslationOutput::makeCopy(dstBuffer, &src); EXPECT_NE(0U, dstString.size()); TranslationOutput::makeCopy(dstString, nullptr); EXPECT_EQ(0U, dstString.size()); EXPECT_NE(0U, dstBuffer.size); EXPECT_NE(nullptr, dstBuffer.mem); TranslationOutput::makeCopy(dstBuffer, nullptr); EXPECT_EQ(0U, dstBuffer.size); EXPECT_EQ(nullptr, dstBuffer.mem); } TEST(TranslationOutput, givenZeroSizeWhenMakingCopyThenClearOutOutput) { MockCIFBuffer src; src.data.assign({2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37}); std::string dstString; TranslationOutput::makeCopy(dstString, &src); TranslationOutput::MemAndSize dstBuffer; TranslationOutput::makeCopy(dstBuffer, &src); MockCIFBuffer emptySrc; EXPECT_NE(0U, dstString.size()); TranslationOutput::makeCopy(dstString, &emptySrc); EXPECT_EQ(0U, dstString.size()); EXPECT_NE(0U, dstBuffer.size); EXPECT_NE(nullptr, dstBuffer.mem); TranslationOutput::makeCopy(dstBuffer, &emptySrc); EXPECT_EQ(0U, dstBuffer.size); EXPECT_EQ(nullptr, dstBuffer.mem); } TEST(getOclCExtensionVersion, whenQueryingVersionOfIntegerDotProductExtensionThenReturns200) { cl_version defaultVer = CL_MAKE_VERSION(7, 2, 5); cl_version ver = NEO::getOclCExtensionVersion("cl_khr_integer_dot_product", defaultVer); cl_version expectedVer = CL_MAKE_VERSION(2, 0, 0); EXPECT_EQ(expectedVer, ver); } TEST(getOclCExtensionVersion, whenCheckingVersionOfExternalMemoryExtensionThenReturns091) { cl_version defaultVer = CL_MAKE_VERSION(7, 2, 5); cl_version ver = NEO::getOclCExtensionVersion("cl_khr_external_memory", defaultVer); cl_version expectedVer = CL_MAKE_VERSION(0, 9, 1); EXPECT_EQ(expectedVer, ver); } TEST(getOclCExtensionVersion, whenCheckingVersionOfUntrackedExtensionThenReturnsDefaultValue) { cl_version defaultVer = CL_MAKE_VERSION(7, 2, 5); cl_version ver = NEO::getOclCExtensionVersion("other", defaultVer); EXPECT_EQ(defaultVer, ver); }