/* * Copyright (C) 2020-2022 Intel Corporation * * SPDX-License-Identifier: MIT * */ #include "shared/offline_compiler/source/decoder/helper.h" #include "shared/offline_compiler/source/ocloc_api.h" #include "shared/offline_compiler/source/ocloc_error_code.h" #include "shared/offline_compiler/source/queries.h" #include "shared/offline_compiler/source/utilities/get_git_version_info.h" #include "shared/source/device_binary_format/elf/elf_decoder.h" #include "shared/source/device_binary_format/elf/ocl_elf.h" #include "shared/source/helpers/file_io.h" #include "shared/test/common/helpers/variable_backup.h" #include "environment.h" #include "gtest/gtest.h" #include "hw_cmds.h" #include #include #include #include extern Environment *gEnvironment; using namespace std::string_literals; void mockedAbortOclocExecution(int errorCode) { throw std::runtime_error{"mockedAbortOclocExecution() called with error code = " + std::to_string(errorCode)}; } TEST(OclocApiTests, WhenOclocVersionIsCalledThenCurrentOclocVersionIsReturned) { EXPECT_EQ(ocloc_version_t::OCLOC_VERSION_CURRENT, oclocVersion()); } TEST(OclocApiTests, WhenGoodArgsAreGivenThenSuccessIsReturned) { std::string clFileName(clFiles + "copybuffer.cl"); const char *argv[] = { "ocloc", "-file", clFileName.c_str(), "-device", gEnvironment->devicePrefix.c_str()}; unsigned int argc = sizeof(argv) / sizeof(const char *); testing::internal::CaptureStdout(); int retVal = oclocInvoke(argc, argv, 0, nullptr, nullptr, nullptr, 0, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr); std::string output = testing::internal::GetCapturedStdout(); EXPECT_EQ(retVal, NEO::OclocErrorCode::SUCCESS); EXPECT_EQ(std::string::npos, output.find("Command was: ocloc -file test_files/copybuffer.cl -device "s + argv[4])); EXPECT_NE(std::string::npos, output.find("Build succeeded.\n")); } TEST(OclocApiTests, GivenQuietModeAndValidArgumentsWhenRunningOclocThenSuccessIsReturnedAndBuildSucceededMessageIsNotPrinted) { std::string clFileName(clFiles + "copybuffer.cl"); const char *argv[] = { "ocloc", "-file", clFileName.c_str(), "-q", "-device", gEnvironment->devicePrefix.c_str()}; unsigned int argc = sizeof(argv) / sizeof(const char *); testing::internal::CaptureStdout(); int retVal = oclocInvoke(argc, argv, 0, nullptr, nullptr, nullptr, 0, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr); std::string output = testing::internal::GetCapturedStdout(); EXPECT_EQ(NEO::OclocErrorCode::SUCCESS, retVal); EXPECT_EQ(std::string::npos, output.find("Command was: ocloc -file test_files/copybuffer.cl -device "s + argv[4])); EXPECT_EQ(std::string::npos, output.find("Build succeeded.\n")); } TEST(OclocApiTests, GivenNeoRevisionQueryWhenQueryingThenNeoRevisionIsReturned) { uint32_t numOutputs; uint64_t *lenOutputs; uint8_t **dataOutputs; char **nameOutputs; const char *argv[] = { "ocloc", "query", NEO::Queries::queryNeoRevision.data()}; unsigned int argc = sizeof(argv) / sizeof(const char *); int retVal = oclocInvoke(argc, argv, 0, nullptr, nullptr, nullptr, 0, nullptr, nullptr, nullptr, &numOutputs, &dataOutputs, &lenOutputs, &nameOutputs); EXPECT_EQ(retVal, NEO::OclocErrorCode::SUCCESS); EXPECT_EQ(numOutputs, 2u); int queryOutputIndex = -1; for (uint32_t i = 0; i < numOutputs; ++i) { if (strcmp(NEO::Queries::queryNeoRevision.data(), nameOutputs[i]) == 0) { queryOutputIndex = i; } } ASSERT_NE(-1, queryOutputIndex); NEO::ConstStringRef queryOutput(reinterpret_cast(dataOutputs[queryOutputIndex]), static_cast(lenOutputs[queryOutputIndex])); EXPECT_STREQ(NEO::getRevision().c_str(), queryOutput.data()); oclocFreeOutput(&numOutputs, &dataOutputs, &lenOutputs, &nameOutputs); } TEST(OclocApiTests, GivenOclDriverVersionQueryWhenQueryingThenNeoRevisionIsReturned) { uint32_t numOutputs; uint64_t *lenOutputs; uint8_t **dataOutputs; char **nameOutputs; const char *argv[] = { "ocloc", "query", NEO::Queries::queryOCLDriverVersion.data()}; unsigned int argc = sizeof(argv) / sizeof(const char *); int retVal = oclocInvoke(argc, argv, 0, nullptr, nullptr, nullptr, 0, nullptr, nullptr, nullptr, &numOutputs, &dataOutputs, &lenOutputs, &nameOutputs); EXPECT_EQ(retVal, NEO::OclocErrorCode::SUCCESS); EXPECT_EQ(numOutputs, 2u); int queryOutputIndex = -1; for (uint32_t i = 0; i < numOutputs; ++i) { if (strcmp(NEO::Queries::queryOCLDriverVersion.data(), nameOutputs[i]) == 0) { queryOutputIndex = i; } } ASSERT_NE(-1, queryOutputIndex); NEO::ConstStringRef queryOutput(reinterpret_cast(dataOutputs[queryOutputIndex]), static_cast(lenOutputs[queryOutputIndex])); EXPECT_STREQ(NEO::getOclDriverVersion().c_str(), queryOutput.data()); oclocFreeOutput(&numOutputs, &dataOutputs, &lenOutputs, &nameOutputs); } TEST(OclocApiTests, GivenNoQueryWhenQueryingThenErrorIsReturned) { const char *argv[] = { "ocloc", "query"}; unsigned int argc = sizeof(argv) / sizeof(const char *); testing::internal::CaptureStdout(); int retVal = oclocInvoke(argc, argv, 0, nullptr, nullptr, nullptr, 0, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr); std::string output = testing::internal::GetCapturedStdout(); EXPECT_EQ(retVal, NEO::OclocErrorCode::INVALID_COMMAND_LINE); EXPECT_STREQ("Error: Invalid command line. Expected ocloc query ", output.c_str()); } TEST(OclocApiTests, GivenInvalidQueryWhenQueryingThenErrorIsReturned) { const char *argv[] = { "ocloc", "query", "unknown_query"}; unsigned int argc = sizeof(argv) / sizeof(const char *); testing::internal::CaptureStdout(); int retVal = oclocInvoke(argc, argv, 0, nullptr, nullptr, nullptr, 0, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr); std::string output = testing::internal::GetCapturedStdout(); EXPECT_EQ(retVal, NEO::OclocErrorCode::INVALID_COMMAND_LINE); EXPECT_STREQ("Error: Invalid command line. Uknown argument unknown_query.", output.c_str()); } TEST(OclocApiTests, WhenGoodFamilyNameIsProvidedThenSuccessIsReturned) { std::string clFileName(clFiles + "copybuffer.cl"); const char *argv[] = { "ocloc", "-file", clFileName.c_str(), "-device", NEO::familyName[NEO::DEFAULT_PLATFORM::hwInfo.platform.eRenderCoreFamily]}; unsigned int argc = sizeof(argv) / sizeof(const char *); testing::internal::CaptureStdout(); int retVal = oclocInvoke(argc, argv, 0, nullptr, nullptr, nullptr, 0, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr); std::string output = testing::internal::GetCapturedStdout(); EXPECT_EQ(retVal, NEO::OclocErrorCode::SUCCESS); EXPECT_EQ(std::string::npos, output.find("Command was: ocloc -file test_files/copybuffer.cl -device "s + argv[4])); } TEST(OclocApiTests, WhenArgsWithMissingFileAreGivenThenErrorMessageIsProduced) { const char *argv[] = { "ocloc", "-q", "-file", "test_files/IDoNotExist.cl", "-device", gEnvironment->devicePrefix.c_str()}; unsigned int argc = sizeof(argv) / sizeof(const char *); testing::internal::CaptureStdout(); int retVal = oclocInvoke(argc, argv, 0, nullptr, nullptr, nullptr, 0, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr); std::string output = testing::internal::GetCapturedStdout(); EXPECT_EQ(retVal, NEO::OclocErrorCode::INVALID_FILE); EXPECT_NE(std::string::npos, output.find("Command was: ocloc -q -file test_files/IDoNotExist.cl -device "s + argv[5])); } TEST(OclocApiTests, givenInputOptionsAndInternalOptionsWhenCmdlineIsPrintedThenBothAreInQuotes) { const char *argv[] = { "ocloc", "-q", "-file", "test_files/IDoNotExist.cl", "-device", gEnvironment->devicePrefix.c_str(), "-options", "-D DEBUG -cl-kernel-arg-info", "-internal_options", "-internalOption1 -internal-option-2"}; unsigned int argc = sizeof(argv) / sizeof(const char *); testing::internal::CaptureStdout(); int retVal = oclocInvoke(argc, argv, 0, nullptr, nullptr, nullptr, 0, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr); std::string output = testing::internal::GetCapturedStdout(); EXPECT_NE(retVal, NEO::OclocErrorCode::SUCCESS); EXPECT_TRUE(output.find("Command was: ocloc -q -file test_files/IDoNotExist.cl -device "s + gEnvironment->devicePrefix.c_str() + " -options \"-D DEBUG -cl-kernel-arg-info\" -internal_options \"-internalOption1 -internal-option-2\"") != std::string::npos); size_t quotesCount = std::count(output.begin(), output.end(), '\"'); EXPECT_EQ(quotesCount, 4u); } TEST(OclocApiTests, givenInputOptionsCalledOptionsWhenCmdlineIsPrintedThenQuotesAreCorrect) { const char *argv[] = { "ocloc", "-q", "-file", "test_files/IDoNotExist.cl", "-device", gEnvironment->devicePrefix.c_str(), "-options", "-options", "-internal_options", "-internalOption"}; unsigned int argc = sizeof(argv) / sizeof(const char *); testing::internal::CaptureStdout(); int retVal = oclocInvoke(argc, argv, 0, nullptr, nullptr, nullptr, 0, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr); std::string output = testing::internal::GetCapturedStdout(); EXPECT_NE(retVal, NEO::OclocErrorCode::SUCCESS); EXPECT_TRUE(output.find("Command was: ocloc -q -file test_files/IDoNotExist.cl -device "s + gEnvironment->devicePrefix.c_str() + " -options \"-options\" -internal_options \"-internalOption\"") != std::string::npos); size_t quotesCount = std::count(output.begin(), output.end(), '\"'); EXPECT_EQ(quotesCount, 4u); } TEST(OclocApiTests, givenInvalidInputOptionsAndInternalOptionsFilesWhenCmdlineIsPrintedThenTheyArePrinted) { ASSERT_TRUE(fileExists(clFiles + "shouldfail.cl")); ASSERT_TRUE(fileExists(clFiles + "shouldfail_options.txt")); ASSERT_TRUE(fileExists(clFiles + "shouldfail_internal_options.txt")); std::string clFileName(clFiles + "shouldfail.cl"); const char *argv[] = { "ocloc", "-q", "-file", clFileName.c_str(), "-device", gEnvironment->devicePrefix.c_str()}; unsigned int argc = sizeof(argv) / sizeof(const char *); testing::internal::CaptureStdout(); int retVal = oclocInvoke(argc, argv, 0, nullptr, nullptr, nullptr, 0, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr); std::string output = testing::internal::GetCapturedStdout(); EXPECT_NE(retVal, NEO::OclocErrorCode::SUCCESS); EXPECT_TRUE(output.find("Compiling options read from file were:\n" "-shouldfailOptions") != std::string::npos); EXPECT_TRUE(output.find("Internal options read from file were:\n" "-shouldfailInternalOptions") != std::string::npos); } TEST(OclocApiTests, GivenInvalidOptionsAndInternalOptionsCommandArgumentsWhenCmdlineIsPrintedThenTheyAreNotPrinted) { std::string clFileName(clFiles + "shouldfail.cl"); ASSERT_TRUE(fileExists(clFileName)); const char *argv[] = { "ocloc", "-q", "-options", "-invalid_option", "-internal_options", "-invalid_internal_option", "-file", clFileName.c_str(), "-device", gEnvironment->devicePrefix.c_str()}; unsigned int argc = sizeof(argv) / sizeof(const char *); testing::internal::CaptureStdout(); int retVal = oclocInvoke(argc, argv, 0, nullptr, nullptr, nullptr, 0, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr); std::string output = testing::internal::GetCapturedStdout(); EXPECT_NE(NEO::OclocErrorCode::SUCCESS, retVal); EXPECT_FALSE(output.find("Compiling options read from file were:\n" "-shouldfailOptions") != std::string::npos); EXPECT_FALSE(output.find("Internal options read from file were:\n" "-shouldfailInternalOptions") != std::string::npos); } TEST(OclocApiTests, givenInvalidOclocOptionsFileWhenCmdlineIsPrintedThenTheyArePrinted) { ASSERT_TRUE(fileExists(clFiles + "valid_kernel.cl")); ASSERT_TRUE(fileExists(clFiles + "valid_kernel_ocloc_options.txt")); std::string clFileName(clFiles + "valid_kernel.cl"); const char *argv[] = { "ocloc", "-q", "-file", clFileName.c_str(), "-device", gEnvironment->devicePrefix.c_str()}; unsigned int argc = sizeof(argv) / sizeof(const char *); testing::internal::CaptureStdout(); int retVal = oclocInvoke(argc, argv, 0, nullptr, nullptr, nullptr, 0, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr); std::string output = testing::internal::GetCapturedStdout(); EXPECT_NE(retVal, NEO::OclocErrorCode::SUCCESS); EXPECT_TRUE(output.find("Failed with ocloc options from file:\n" "-invalid_ocloc_option") != std::string::npos); EXPECT_FALSE(output.find("Building with ocloc options:") != std::string::npos); } TEST(OclocApiTests, GivenIncludeHeadersWhenCompilingThenPassesToFclHeadersPackedAsElf) { auto prevFclDebugVars = NEO::getFclDebugVars(); auto debugVars = prevFclDebugVars; std::string receivedInput; debugVars.receivedInput = &receivedInput; setFclDebugVars(debugVars); const char *argv[] = { "ocloc", "-file", "main.cl", "-device", gEnvironment->devicePrefix.c_str()}; unsigned int argc = sizeof(argv) / sizeof(const char *); const char *headerA = R"===( void foo() {} )==="; const char *headerB = R"===( void bar() {} )==="; const char *main = R"===( #include "includeA.h" #include "includeB.h" __kernel void k(){ foo(); bar(); } )==="; const char *sourcesNames[] = {"main.cl"}; const uint8_t *sources[] = {reinterpret_cast(main)}; const uint64_t sourcesLen[] = {strlen(main) + 1}; const char *headersNames[] = {"includeA.h", "includeB.h"}; const uint8_t *headers[] = {reinterpret_cast(headerA), reinterpret_cast(headerB)}; const uint64_t headersLen[] = {strlen(headerA) + 1, strlen(headerB) + 1}; uint32_t numOutputs = 0U; uint8_t **outputs = nullptr; uint64_t *outputsLen = nullptr; char **ouputsNames = nullptr; oclocInvoke(argc, argv, 1, sources, sourcesLen, sourcesNames, 2, headers, headersLen, headersNames, &numOutputs, &outputs, &outputsLen, &ouputsNames); NEO::setFclDebugVars(prevFclDebugVars); std::string decodeErr, decodeWarn; ArrayRef rawElf(reinterpret_cast(receivedInput.data()), receivedInput.size()); auto elf = NEO::Elf::decodeElf(rawElf, decodeErr, decodeWarn); ASSERT_NE(nullptr, elf.elfFileHeader) << decodeWarn << " " << decodeErr; EXPECT_EQ(NEO::Elf::ET_OPENCL_SOURCE, elf.elfFileHeader->type); using SectionT = std::remove_reference_t; const SectionT *sourceSection, *headerASection, *headerBSection; ASSERT_NE(NEO::Elf::SHN_UNDEF, elf.elfFileHeader->shStrNdx); auto sectionNamesSection = elf.sectionHeaders.begin() + elf.elfFileHeader->shStrNdx; auto elfStrings = sectionNamesSection->data.toArrayRef(); for (const auto §ion : elf.sectionHeaders) { if (NEO::Elf::SHT_OPENCL_SOURCE == section.header->type) { sourceSection = §ion; } else if (NEO::Elf::SHT_OPENCL_HEADER == section.header->type) { auto sectionName = elfStrings.begin() + section.header->name; if (0 == strcmp("includeA.h", sectionName)) { headerASection = §ion; } else if (0 == strcmp("includeB.h", sectionName)) { headerBSection = §ion; } else { EXPECT_FALSE(true) << sectionName; } } } ASSERT_NE(nullptr, sourceSection); EXPECT_EQ(sourcesLen[0], sourceSection->data.size()); EXPECT_STREQ(main, reinterpret_cast(sourceSection->data.begin())); ASSERT_NE(nullptr, headerASection); EXPECT_EQ(sourcesLen[0], sourceSection->data.size()); EXPECT_STREQ(headerA, reinterpret_cast(headerASection->data.begin())); ASSERT_NE(nullptr, headerBSection); EXPECT_EQ(sourcesLen[0], sourceSection->data.size()); EXPECT_STREQ(headerB, reinterpret_cast(headerBSection->data.begin())); } TEST(OclocApiTests, GivenHelpParameterWhenDecodingThenHelpMsgIsPrintedAndSuccessIsReturned) { const char *argv[] = { "ocloc", "disasm", "--help"}; unsigned int argc = sizeof(argv) / sizeof(const char *); testing::internal::CaptureStdout(); int retVal = oclocInvoke(argc, argv, 0, nullptr, nullptr, nullptr, 0, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr); std::string output = testing::internal::GetCapturedStdout(); EXPECT_FALSE(output.empty()); EXPECT_EQ(retVal, NEO::OclocErrorCode::SUCCESS); } TEST(OclocApiTests, GivenNonExistingFileWhenDecodingThenAbortIsCalled) { VariableBackup oclocAbortBackup{&abortOclocExecution, &mockedAbortOclocExecution}; const char *argv[] = { "ocloc", "disasm", "-file", "nonexistent_file_that_should_fail", "-dump", "test_files/created"}; unsigned int argc = sizeof(argv) / sizeof(const char *); testing::internal::CaptureStdout(); const auto retVal = oclocInvoke(argc, argv, 0, nullptr, nullptr, nullptr, 0, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr); const auto output = testing::internal::GetCapturedStdout(); EXPECT_NE(std::string::npos, output.find("mockedAbortOclocExecution() called with error code = 1")); EXPECT_EQ(-1, retVal); } TEST(OclocApiTests, GivenMissingFileNameWhenDecodingThenErrorIsReturned) { const char *argv[] = { "ocloc", "disasm", "-file"}; unsigned int argc = sizeof(argv) / sizeof(const char *); testing::internal::CaptureStdout(); const auto retVal = oclocInvoke(argc, argv, 0, nullptr, nullptr, nullptr, 0, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr); const auto output = testing::internal::GetCapturedStdout(); EXPECT_NE(std::string::npos, output.find("Unknown argument -file\n")); EXPECT_EQ(-1, retVal); } TEST(OclocApiTests, GivenHelpParameterWhenEncodingThenHelpMsgIsPrintedAndSuccessIsReturned) { const char *argv[] = { "ocloc", "asm", "--help"}; unsigned int argc = sizeof(argv) / sizeof(const char *); testing::internal::CaptureStdout(); int retVal = oclocInvoke(argc, argv, 0, nullptr, nullptr, nullptr, 0, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr); std::string output = testing::internal::GetCapturedStdout(); EXPECT_FALSE(output.empty()); EXPECT_EQ(retVal, NEO::OclocErrorCode::SUCCESS); } TEST(OclocApiTests, GivenMissingDumpFileNameWhenEncodingThenErrorIsReturned) { const char *argv[] = { "ocloc", "asm", "-dump"}; unsigned int argc = sizeof(argv) / sizeof(const char *); testing::internal::CaptureStdout(); const auto retVal = oclocInvoke(argc, argv, 0, nullptr, nullptr, nullptr, 0, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr); const auto output = testing::internal::GetCapturedStdout(); EXPECT_NE(std::string::npos, output.find("Unknown argument -dump\n")); EXPECT_EQ(-1, retVal); } TEST(OclocApiTests, GivenValidArgumentsAndMissingPtmFileWhenEncodingThenErrorIsReturned) { const char *argv[] = { "ocloc", "asm", "-dump", "test_files/dump", "-out", "test_files/binary_gen.bin"}; unsigned int argc = sizeof(argv) / sizeof(const char *); testing::internal::CaptureStdout(); const auto retVal = oclocInvoke(argc, argv, 0, nullptr, nullptr, nullptr, 0, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr); const auto output = testing::internal::GetCapturedStdout(); EXPECT_NE(std::string::npos, output.find("Error! Couldn't find PTM.txt")); EXPECT_EQ(-1, retVal); } TEST(OclocApiTests, GiveMultiCommandHelpArgumentsWhenInvokingOclocThenHelpIsPrinted) { const char *argv[] = { "ocloc", "multi", "--help"}; unsigned int argc = sizeof(argv) / sizeof(const char *); testing::internal::CaptureStdout(); const auto retVal = oclocInvoke(argc, argv, 0, nullptr, nullptr, nullptr, 0, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr); const auto output = testing::internal::GetCapturedStdout(); EXPECT_FALSE(output.empty()); EXPECT_EQ(-1, retVal); } TEST(OclocApiTests, GivenNonexistentFileWhenValidateIsInvokedThenErrorIsPrinted) { const char *argv[] = { "ocloc", "validate", "-file", "some_special_nonexistent_file.gen"}; unsigned int argc = sizeof(argv) / sizeof(argv[0]); testing::internal::CaptureStdout(); int retVal = oclocInvoke(argc, argv, 0, nullptr, nullptr, nullptr, 0, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr); const auto output = testing::internal::GetCapturedStdout(); EXPECT_EQ(-1, retVal); const std::string expectedErrorMessage{"Error : Input file missing : some_special_nonexistent_file.gen\n"}; EXPECT_EQ(expectedErrorMessage, output); } TEST(OclocApiTests, GivenZeroArgumentsWhenOclocIsInvokedThenHelpIsPrinted) { testing::internal::CaptureStdout(); int retVal = oclocInvoke(0, nullptr, 0, nullptr, nullptr, nullptr, 0, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr); const auto output = testing::internal::GetCapturedStdout(); EXPECT_EQ(NEO::OclocErrorCode::INVALID_COMMAND_LINE, retVal); EXPECT_FALSE(output.empty()); } TEST(OclocApiTests, GivenCommandWithoutArgsWhenOclocIsInvokedThenHelpIsPrinted) { const char *argv[] = { "ocloc"}; unsigned int argc = sizeof(argv) / sizeof(argv[0]); testing::internal::CaptureStdout(); int retVal = oclocInvoke(argc, argv, 0, nullptr, nullptr, nullptr, 0, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr); const auto output = testing::internal::GetCapturedStdout(); EXPECT_EQ(NEO::OclocErrorCode::SUCCESS, retVal); EXPECT_FALSE(output.empty()); } TEST(OclocApiTests, GivenHelpArgumentWhenOclocIsInvokedThenHelpIsPrinted) { constexpr std::array flagsToTest = {"-h", "--help"}; for (const auto helpFlag : flagsToTest) { const char *argv[] = { "ocloc", helpFlag}; unsigned int argc = sizeof(argv) / sizeof(argv[0]); testing::internal::CaptureStdout(); int retVal = oclocInvoke(argc, argv, 0, nullptr, nullptr, nullptr, 0, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr); const auto output = testing::internal::GetCapturedStdout(); EXPECT_EQ(NEO::OclocErrorCode::SUCCESS, retVal); EXPECT_FALSE(output.empty()); } } TEST(OclocApiTests, GivenHelpParameterWhenLinkingThenHelpMsgIsPrintedAndSuccessIsReturned) { const char *argv[] = { "ocloc", "link", "--help"}; unsigned int argc = sizeof(argv) / sizeof(argv[0]); testing::internal::CaptureStdout(); int retVal = oclocInvoke(argc, argv, 0, nullptr, nullptr, nullptr, 0, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr); std::string output = testing::internal::GetCapturedStdout(); EXPECT_FALSE(output.empty()); EXPECT_EQ(NEO::OclocErrorCode::SUCCESS, retVal); } TEST(OclocApiTests, GivenInvalidParameterWhenLinkingThenErrorIsReturned) { const char *argv[] = { "ocloc", "link", "--dummy_param"}; unsigned int argc = sizeof(argv) / sizeof(argv[0]); testing::internal::CaptureStdout(); int retVal = oclocInvoke(argc, argv, 0, nullptr, nullptr, nullptr, 0, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr); std::string output = testing::internal::GetCapturedStdout(); EXPECT_EQ(NEO::OclocErrorCode::INVALID_COMMAND_LINE, retVal); const std::string expectedInitError{"Invalid option (arg 2): --dummy_param\n"}; const std::string expectedExecuteError{"Error: Linker cannot be executed due to unsuccessful initialization!\n"}; const std::string expectedErrorMessage = expectedInitError + expectedExecuteError; EXPECT_EQ(expectedErrorMessage, output); }