diff --git a/offline_compiler/CMakeLists.txt b/offline_compiler/CMakeLists.txt index 0579d0dae3..7926e7af4e 100644 --- a/offline_compiler/CMakeLists.txt +++ b/offline_compiler/CMakeLists.txt @@ -16,6 +16,8 @@ ${IGDRCL_SOURCE_DIR}/offline_compiler/decoder/helper.h ${IGDRCL_SOURCE_DIR}/offline_compiler/helper.cpp ${IGDRCL_SOURCE_DIR}/offline_compiler/offline_compiler.cpp ${IGDRCL_SOURCE_DIR}/offline_compiler/offline_compiler.h +${IGDRCL_SOURCE_DIR}/offline_compiler/multi_command.cpp +${IGDRCL_SOURCE_DIR}/offline_compiler/multi_command.h ${IGDRCL_SOURCE_DIR}/offline_compiler/options.cpp ${IGDRCL_SOURCE_DIR}/runtime/compiler_interface/create_main.cpp ${IGDRCL_SOURCE_DIR}/runtime/helpers/abort.cpp diff --git a/offline_compiler/main.cpp b/offline_compiler/main.cpp index 623f082b47..cb7d8fdb73 100644 --- a/offline_compiler/main.cpp +++ b/offline_compiler/main.cpp @@ -5,14 +5,17 @@ * */ +#include "offline_compiler/multi_command.h" #include "offline_compiler/offline_compiler.h" -#include "offline_compiler/utilities/safety_caller.h" #include "runtime/os_interface/os_library.h" #include "decoder/binary_decoder.h" #include "decoder/binary_encoder.h" #include +#include +#include + using namespace NEO; int main(int numArgs, const char *argv[]) { @@ -33,9 +36,20 @@ int main(int numArgs, const char *argv[]) { } else { return retVal; } + } else if (numArgs > 1 && !strcmp(argv[1], "-multi")) { + int retValue = CL_SUCCESS; + + auto pMulti = std::unique_ptr(MultiCommand::create(numArgs, argv, retValue)); + + return retValue; } else { int retVal = CL_SUCCESS; - OfflineCompiler *pCompiler = OfflineCompiler::create(numArgs, argv, retVal); + std::vector allArgs; + if (numArgs > 1) { + allArgs.assign(argv, argv + numArgs); + } + + OfflineCompiler *pCompiler = OfflineCompiler::create(numArgs, allArgs, retVal); if (retVal == CL_SUCCESS) { retVal = buildWithSafetyGuard(pCompiler); diff --git a/offline_compiler/multi_command.cpp b/offline_compiler/multi_command.cpp new file mode 100644 index 0000000000..da45066058 --- /dev/null +++ b/offline_compiler/multi_command.cpp @@ -0,0 +1,226 @@ +/* + * Copyright (C) 2019 Intel Corporation + * + * SPDX-License-Identifier: MIT + * + */ + +#include "offline_compiler/multi_command.h" + +namespace NEO { +int MultiCommand::singleBuild(size_t numArgs, const std::vector &allArgs) { + int retVal; + std::string buildLog; + OfflineCompiler *pCompiler = OfflineCompiler::create(numArgs, allArgs, retVal); + if (retVal == CL_SUCCESS) { + retVal = buildWithSafetyGuard(pCompiler); + + buildLog = pCompiler->getBuildLog(); + if (buildLog.empty() == false) { + printf("%s\n", buildLog.c_str()); + } + + if (retVal == CL_SUCCESS) { + if (!pCompiler->isQuiet()) + printf("Build succeeded.\n"); + } else { + printf("Build failed with error code: %d\n", retVal); + } + } + if (buildLog.empty() == false) { + singleBuilds.push_back(pCompiler); + } else { + delete pCompiler; + } + return retVal; +} + +MultiCommand::MultiCommand() = default; + +MultiCommand::~MultiCommand() { + deleteBuildsWithWarnigs(); +} + +void MultiCommand::deleteBuildsWithWarnigs() { + for (OfflineCompiler *pSingle : singleBuilds) + delete pSingle; + singleBuilds.clear(); +} + +MultiCommand *MultiCommand::create(int numArgs, const char *argv[], int &retVal) { + retVal = CL_SUCCESS; + auto pMultiCommand = new MultiCommand(); + + if (pMultiCommand) { + retVal = pMultiCommand->initialize(numArgs, argv); + } + + if (retVal != CL_SUCCESS) { + delete pMultiCommand; + pMultiCommand = nullptr; + } + + return pMultiCommand; +} + +std::string MultiCommand::eraseExtensionFromPath(std::string &filePath) { + size_t extPos = filePath.find_last_of(".", filePath.size()); + if (extPos == std::string::npos) { + extPos = filePath.size(); + } + std::string fileName; + std::string fileTrunk = filePath.substr(0, extPos); + + return fileTrunk; +} + +void MultiCommand::addAdditionalOptionsToSingleCommandLine(std::vector &singleLineWithArguments, int buildId) { + std::string OutFileName; + bool hasOutDir = false; + bool hasSpecificName = false; + for (auto arg : singleLineWithArguments) { + if (arg == "-out_dir") { + hasOutDir = true; + } + if (arg == "-output") { + hasSpecificName = true; + } + } + if (!hasOutDir) { + singleLineWithArguments.push_back("-out_dir"); + OutDirForBuilds = eraseExtensionFromPath(pathToCMD); + singleLineWithArguments.push_back(OutDirForBuilds); + } + if (!hasSpecificName) { + singleLineWithArguments.push_back("-output"); + OutFileName = "build_no_" + std::to_string(buildId + 1); + singleLineWithArguments.push_back(OutFileName); + } + if (quiet) + singleLineWithArguments.push_back("-q"); +} + +int MultiCommand::initialize(int numArgs, const char *argv[]) { + int retVal = CL_SUCCESS; + + if (numArgs > 2) + pathToCMD = argv[2]; + else { + printf("Lack of file with build arguments\n"); + return INVALID_COMMAND_LINE; + } + if (numArgs > 3 && strcmp(argv[3], "-q") == 0) + quiet = true; + + //save file with builds arguments to vector of strings, line by line + openFileWithBuildsArguments(); + if (!lines.empty()) { + for (unsigned int i = 0; i < lines.size(); i++) { + std::vector singleLineWithArguments; + unsigned int numberOfArg; + + singleLineWithArguments.push_back(argv[0]); + retVal = splitLineInSeparateArgs(singleLineWithArguments, lines[i], i); + if (retVal != CL_SUCCESS) { + retValues.push_back(retVal); + continue; + } + + addAdditionalOptionsToSingleCommandLine(singleLineWithArguments, i); + + numberOfArg = static_cast(singleLineWithArguments.size()); + + if (!quiet) + printf("\nCommand number %d: ", i + 1); + retVal = singleBuild(numberOfArg, singleLineWithArguments); + retValues.push_back(retVal); + } + + return showResults(); + } else + return INVALID_COMMAND_LINE; +} + +int MultiCommand::splitLineInSeparateArgs(std::vector &qargs, const std::string &command, int numberOfBuild) { + unsigned int len = static_cast(command.length()); + + bool qot = false, sqot = false; + int arglen; + + for (unsigned int i = 0; i < len; i++) { + int start = i; + if (command[i] == '\"') { + qot = true; + } else if (command[i] == '\'') + sqot = true; + + if (qot) { + i++; + start++; + while (i < len && command[i] != '\"') + i++; + if (i < len) + qot = false; + arglen = i - start; + i++; + } else if (sqot) { + i++; + while (i < len && command[i] != '\'') + i++; + if (i < len) + sqot = false; + arglen = i - start; + i++; + } else { + while (i < len && command[i] != ' ') + i++; + arglen = i - start; + } + qargs.push_back(command.substr(start, arglen)); + } + if (qot || sqot) { + printf("One of the quotes is open in build number %d\n", numberOfBuild + 1); + return INVALID_COMMAND_LINE; + } + return CL_SUCCESS; +} + +void MultiCommand::openFileWithBuildsArguments() { + std::fstream multiCmdFile; + std::stringstream fileContent; + multiCmdFile.open(pathToCMD, std::fstream::in); + + if (multiCmdFile.is_open()) { + std::string param; + fileContent << multiCmdFile.rdbuf(); + multiCmdFile.close(); + while (std::getline(fileContent, param, '\n')) { + param.erase(param.find_last_not_of(" \r\t") + 1); + param.erase(0, param.find_first_not_of(" \r\t")); + if (!param.empty()) { + lines.push_back(param); + } + } + } else { + printf("Can not open file with builds arguments\n"); + } +} + +int MultiCommand::showResults() { + int retValue = CL_SUCCESS; + int indexRetVal = 0; + for (int retVal : retValues) { + if (retVal != CL_SUCCESS) { + if (retValue == CL_SUCCESS) + retValue = retVal; + if (!quiet) + printf("Build %d: failed. Error code: %d\n", indexRetVal, retVal); + } else { + if (!quiet) + printf("Build %d: successful\n", indexRetVal); + } + indexRetVal++; + } + return retValue; +} +} // namespace NEO diff --git a/offline_compiler/multi_command.h b/offline_compiler/multi_command.h new file mode 100644 index 0000000000..805298b969 --- /dev/null +++ b/offline_compiler/multi_command.h @@ -0,0 +1,50 @@ +/* + * Copyright (C) 2019 Intel Corporation + * + * SPDX-License-Identifier: MIT + * + */ + +#include "offline_compiler/offline_compiler.h" +#include "offline_compiler/utilities/safety_caller.h" +#include "runtime/os_interface/os_library.h" + +#include "decoder/binary_decoder.h" +#include "decoder/binary_encoder.h" +#include + +#include +#include + +namespace NEO { + +class MultiCommand { + public: + static MultiCommand *create(int numArgs, const char *argv[], int &retVal); + void deleteBuildsWithWarnigs(); + + std::vector singleBuilds; + + MultiCommand &operator=(const MultiCommand &) = delete; + MultiCommand(const MultiCommand &) = delete; + ~MultiCommand(); + + std::string OutDirForBuilds; + + protected: + int splitLineInSeparateArgs(std::vector &qargs, const std::string &command, int numberOfBuild); + void openFileWithBuildsArguments(); + void addAdditionalOptionsToSingleCommandLine(std::vector &, int); + int initialize(int numArgs, const char *argv[]); + int showResults(); + int singleBuild(size_t numArgs, const std::vector &allArgs); + std::string eraseExtensionFromPath(std::string &filePath); + + std::vector retValues; + std::string pathToCMD; + std::vector lines; + bool quiet = false; + + MultiCommand(); +}; +} // namespace NEO diff --git a/offline_compiler/offline_compiler.cpp b/offline_compiler/offline_compiler.cpp index d62792c7b4..4234bd0a26 100644 --- a/offline_compiler/offline_compiler.cpp +++ b/offline_compiler/offline_compiler.cpp @@ -55,6 +55,12 @@ bool stringsAreEqual(const char *string1, const char *string2) { return (strcmp(string1, string2) == 0); } +bool stringsAreEqual(std::string string1, std::string string2) { + if (string2.empty()) + return false; + return (string1 == string2); +} + //////////////////////////////////////////////////////////////////////////////// // convertToPascalCase //////////////////////////////////////////////////////////////////////////////// @@ -91,12 +97,12 @@ OfflineCompiler::~OfflineCompiler() { //////////////////////////////////////////////////////////////////////////////// // Create //////////////////////////////////////////////////////////////////////////////// -OfflineCompiler *OfflineCompiler::create(size_t numArgs, const char *const *argv, int &retVal) { +OfflineCompiler *OfflineCompiler::create(size_t numArgs, const std::vector &allArgs, int &retVal) { retVal = CL_SUCCESS; auto pOffCompiler = new OfflineCompiler(); if (pOffCompiler) { - retVal = pOffCompiler->initialize(numArgs, argv); + retVal = pOffCompiler->initialize(numArgs, allArgs); } if (retVal != CL_SUCCESS) { @@ -270,13 +276,13 @@ std::string OfflineCompiler::getStringWithinDelimiters(const std::string &src) { //////////////////////////////////////////////////////////////////////////////// // Initialize //////////////////////////////////////////////////////////////////////////////// -int OfflineCompiler::initialize(size_t numArgs, const char *const *argv) { +int OfflineCompiler::initialize(size_t numArgs, const std::vector &allArgs) { int retVal = CL_SUCCESS; const char *pSource = nullptr; void *pSourceFromFile = nullptr; size_t sourceFromFileSize = 0; - retVal = parseCommandLine(numArgs, argv); + retVal = parseCommandLine(numArgs, allArgs); if (retVal != CL_SUCCESS) { return retVal; } @@ -434,7 +440,7 @@ int OfflineCompiler::initialize(size_t numArgs, const char *const *argv) { //////////////////////////////////////////////////////////////////////////////// // ParseCommandLine //////////////////////////////////////////////////////////////////////////////// -int OfflineCompiler::parseCommandLine(size_t numArgs, const char *const *argv) { +int OfflineCompiler::parseCommandLine(size_t numArgs, const std::vector &argv) { int retVal = CL_SUCCESS; bool compile32 = false; bool compile64 = false; @@ -493,7 +499,7 @@ int OfflineCompiler::parseCommandLine(size_t numArgs, const char *const *argv) { printUsage(); retVal = PRINT_USAGE; } else { - printf("Invalid option (arg %d): %s\n", argIndex, argv[argIndex]); + printf("Invalid option (arg %d): %s\n", argIndex, argv[argIndex].c_str()); retVal = INVALID_COMMAND_LINE; break; } @@ -642,6 +648,13 @@ void OfflineCompiler::printUsage() { printf(" -device Indicates which device for which we will compile.\n"); printf(" can be: %s\n", getDevicesTypes().c_str()); printf("\n"); + printf(" -multi Indicates the txt file with multi commands\n"); + printf(" where each line is a single build in format:\n"); + printf(" '-file -device [OPTIONS]'\n"); + printf(" Argument '-multi' must be first argument. \n"); + printf(" Result of builds will be output in directory named \n"); + printf(" like .txt file with build commands.\n"); + printf("\n"); printf(" -output Indicates output files core name.\n"); printf(" -out_dir Indicates the directory into which the compiled files\n"); printf(" will be placed.\n"); diff --git a/offline_compiler/offline_compiler.h b/offline_compiler/offline_compiler.h index 7b5a15bb45..c1e506cb7c 100644 --- a/offline_compiler/offline_compiler.h +++ b/offline_compiler/offline_compiler.h @@ -33,7 +33,7 @@ std::string generateFilePath(const std::string &directory, const std::string &fi class OfflineCompiler { public: - static OfflineCompiler *create(size_t numArgs, const char *const *argv, int &retVal); + static OfflineCompiler *create(size_t numArgs, const std::vector &allArgs, int &retVal); int build(); std::string &getBuildLog(); void printUsage(); @@ -55,8 +55,8 @@ class OfflineCompiler { int getHardwareInfo(const char *pDeviceName); std::string getFileNameTrunk(std::string &filePath); std::string getStringWithinDelimiters(const std::string &src); - int initialize(size_t numArgs, const char *const *argv); - int parseCommandLine(size_t numArgs, const char *const *argv); + int initialize(size_t numArgs, const std::vector &allArgs); + int parseCommandLine(size_t numArgs, const std::vector &allArgs); void setStatelessToStatefullBufferOffsetFlag(); void parseDebugSettings(); void storeBinary(char *&pDst, size_t &dstSize, const void *pSrc, const size_t srcSize); diff --git a/unit_tests/offline_compiler/CMakeLists.txt b/unit_tests/offline_compiler/CMakeLists.txt index 3bea07828b..b7df0bcddd 100644 --- a/unit_tests/offline_compiler/CMakeLists.txt +++ b/unit_tests/offline_compiler/CMakeLists.txt @@ -1,11 +1,12 @@ # -# Copyright (C) 2018 Intel Corporation +# Copyright (C) 2018-2019 Intel Corporation # # SPDX-License-Identifier: MIT # project(ocloc_tests) + set(IGDRCL_SRCS_cloc ${IGDRCL_SOURCE_DIR}/offline_compiler/decoder/binary_decoder.cpp ${IGDRCL_SOURCE_DIR}/offline_compiler/decoder/binary_encoder.cpp @@ -18,6 +19,26 @@ ${CMAKE_CURRENT_SOURCE_DIR}/decoder/mock/mock_encoder.h ${CMAKE_CURRENT_SOURCE_DIR}/mock/mock_offline_compiler.h ) +set(CLOC_SRCS_UTILITIES + ${IGDRCL_SOURCE_DIR}/offline_compiler/utilities/safety_caller.h +) + +if(WIN32) + list(APPEND CLOC_SRCS_UTILITIES + ${IGDRCL_SOURCE_DIR}/offline_compiler/utilities/windows/safety_caller_windows.cpp + ${IGDRCL_SOURCE_DIR}/offline_compiler/utilities/windows/safety_guard_windows.h + ${IGDRCL_SOURCE_DIR}/offline_compiler/utilities/windows/seh_exception.cpp + ${IGDRCL_SOURCE_DIR}/offline_compiler/utilities/windows/seh_exception.h + ) +else() + list(APPEND CLOC_SRCS_UTILITIES + ${IGDRCL_SOURCE_DIR}/offline_compiler/utilities/linux/safety_caller_linux.cpp + ${IGDRCL_SOURCE_DIR}/offline_compiler/utilities/linux/safety_guard_linux.h + ) +endif() + + + set(IGDRCL_SRCS_offline_compiler_tests ${CMAKE_CURRENT_SOURCE_DIR}/CMakeLists.txt ${CMAKE_CURRENT_SOURCE_DIR}/decoder/decoder_tests.cpp @@ -34,6 +55,7 @@ set(IGDRCL_SRCS_offline_compiler_tests ${IGDRCL_SRCS_cloc} ${IGDRCL_SRCS_offline_compiler_mock} ${CLOC_SRCS_LIB} + ${CLOC_SRCS_UTILITIES} ) if(WIN32) @@ -57,6 +79,10 @@ target_compile_definitions(ocloc_tests PUBLIC MOCKABLE_VIRTUAL=virtual $ &argv) { return OfflineCompiler::initialize(numArgs, argv); } - int parseCommandLine(size_t numArgs, const char *const *argv) { + int parseCommandLine(size_t numArgs, const std::vector &argv) { return OfflineCompiler::parseCommandLine(numArgs, argv); } diff --git a/unit_tests/offline_compiler/offline_compiler_tests.cpp b/unit_tests/offline_compiler/offline_compiler_tests.cpp index a88ed13eca..c2ac57d146 100644 --- a/unit_tests/offline_compiler/offline_compiler_tests.cpp +++ b/unit_tests/offline_compiler/offline_compiler_tests.cpp @@ -19,6 +19,7 @@ #include "mock/mock_offline_compiler.h" #include +#include extern Environment *gEnvironment; @@ -41,24 +42,172 @@ void compilerOutputRemove(const std::string &fileName, const std::string &type) std::remove(getCompilerOutputFileName(fileName, type).c_str()); } +TEST_F(MultiCommandTests, MultiCommandSuccessfulBuildTest) { + nameOfFileWithArgs = "test_files/ImAMulitiComandMinimalGoodFile.txt"; + const char *argv[] = { + "ocloc", + "-multi", + nameOfFileWithArgs.c_str(), + "-q", + }; + int argSize = 4; + + std::vector singleArgs = { + "-file", + "test_files/copybuffer.cl", + "-device", + gEnvironment->devicePrefix.c_str()}; + + int numOfBuild = 4; + createFileWithArgs(singleArgs, numOfBuild); + + auto pMultiCommand = std::unique_ptr(MultiCommand::create(argSize, argv, retVal)); + + EXPECT_NE(nullptr, pMultiCommand); + EXPECT_EQ(CL_SUCCESS, retVal); + + deleteFileWithArgs(); +} +TEST_F(MultiCommandTests, MultiCommandSuccessfulBuildWithOutputFileTest) { + nameOfFileWithArgs = "test_files/ImAMulitiComandMinimalGoodFile.txt"; + const char *argv[] = { + "ocloc", + "-multi", + nameOfFileWithArgs.c_str(), + "-q", + }; + int argSize = 4; + + std::vector singleArgs = { + "-file", + "test_files/copybuffer.cl", + "-device", + gEnvironment->devicePrefix.c_str()}; + + int numOfBuild = 4; + createFileWithArgs(singleArgs, numOfBuild); + + auto pMultiCommand = std::unique_ptr(MultiCommand::create(argSize, argv, retVal)); + + EXPECT_NE(nullptr, pMultiCommand); + EXPECT_EQ(CL_SUCCESS, retVal); + + for (int i = 0; i < numOfBuild; i++) { + std::string outFileName = pMultiCommand->OutDirForBuilds + "/build_no_" + std::to_string(i + 1); + EXPECT_TRUE(compilerOutputExists(outFileName, "bc") || compilerOutputExists(outFileName, "spv")); + EXPECT_TRUE(compilerOutputExists(outFileName, "gen")); + EXPECT_TRUE(compilerOutputExists(outFileName, "bin")); + } + + for (OfflineCompiler *pSingle : pMultiCommand->singleBuilds) { + std::string buildLog = pSingle->getBuildLog(); + EXPECT_STREQ(buildLog.c_str(), ""); + } + + deleteFileWithArgs(); +} +TEST_F(MultiCommandTests, GoodMultiBuildTestWithspecifiedOutputDir) { + nameOfFileWithArgs = "test_files/ImAMulitiComandMinimalGoodFile.txt"; + const char *argv[] = { + "ocloc", + "-multi", + nameOfFileWithArgs.c_str(), + "-q", + }; + int argSize = 4; + + std::vector singleArgs = { + "-file", + "test_files/copybuffer.cl", + "-device", + gEnvironment->devicePrefix.c_str(), + "-out_dir", + "offline_compiler_test"}; + + int numOfBuild = 4; + createFileWithArgs(singleArgs, numOfBuild); + + pMultiCommand = MultiCommand::create(argSize, argv, retVal); + + EXPECT_NE(nullptr, pMultiCommand); + EXPECT_EQ(CL_SUCCESS, retVal); + + for (int i = 0; i < numOfBuild; i++) { + std::string outFileName = "offline_compiler_test/build_no_" + std::to_string(i + 1); + EXPECT_TRUE(compilerOutputExists(outFileName, "bc") || compilerOutputExists(outFileName, "spv")); + EXPECT_TRUE(compilerOutputExists(outFileName, "gen")); + EXPECT_TRUE(compilerOutputExists(outFileName, "bin")); + } + + deleteFileWithArgs(); + delete pMultiCommand; +} +TEST_F(MultiCommandTests, LackOfTxtFileWithArgsMultiTest) { + nameOfFileWithArgs = "test_files/ImANotExistedComandFile.txt"; + const char *argv[] = { + "ocloc", + "-multi", + "test_files/ImANaughtyFile.txt", + "-q", + }; + int argSize = 4; + + testing::internal::CaptureStdout(); + auto pMultiCommand = std::unique_ptr(MultiCommand::create(argSize, argv, retVal)); + std::string output = testing::internal::GetCapturedStdout(); + + EXPECT_STRNE(output.c_str(), ""); + EXPECT_EQ(nullptr, pMultiCommand); + EXPECT_EQ(INVALID_COMMAND_LINE, retVal); + DebugManager.flags.PrintDebugMessages.set(false); +} +TEST_F(MultiCommandTests, LackOfClFilePointedInTxtFileMultiTest) { + nameOfFileWithArgs = "test_files/ImAMulitiComandMinimalGoodFile.txt"; + const char *argv[] = { + "ocloc", + "-multi", + nameOfFileWithArgs.c_str(), + "-q", + }; + int argSize = 4; + + std::vector singleArgs = { + "-file", + "test_files/ImANaughtyFile.cl", + "-device", + gEnvironment->devicePrefix.c_str()}; + + int numOfBuild = 4; + createFileWithArgs(singleArgs, numOfBuild); + testing::internal::CaptureStdout(); + auto pMultiCommand = std::unique_ptr(MultiCommand::create(argSize, argv, retVal)); + std::string output = testing::internal::GetCapturedStdout(); + + EXPECT_STRNE(output.c_str(), ""); + EXPECT_EQ(nullptr, pMultiCommand); + EXPECT_EQ(INVALID_FILE, retVal); + DebugManager.flags.PrintDebugMessages.set(false); + + deleteFileWithArgs(); +} + TEST_F(OfflineCompilerTests, GoodArgTest) { - auto argv = { + std::vector argv = { "ocloc", "-file", "test_files/copybuffer.cl", "-device", gEnvironment->devicePrefix.c_str()}; - pOfflineCompiler = OfflineCompiler::create(argv.size(), argv.begin(), retVal); + pOfflineCompiler = OfflineCompiler::create(argv.size(), argv, retVal); EXPECT_NE(nullptr, pOfflineCompiler); EXPECT_EQ(CL_SUCCESS, retVal); delete pOfflineCompiler; } - TEST_F(OfflineCompilerTests, TestExtensions) { - auto argv = { + std::vector argv = { "ocloc", "-file", "test_files/copybuffer.cl", @@ -67,20 +216,19 @@ TEST_F(OfflineCompilerTests, TestExtensions) { auto mockOfflineCompiler = std::unique_ptr(new MockOfflineCompiler()); ASSERT_NE(nullptr, mockOfflineCompiler); - mockOfflineCompiler->parseCommandLine(argv.size(), argv.begin()); + mockOfflineCompiler->parseCommandLine(argv.size(), argv); std::string internalOptions = mockOfflineCompiler->getInternalOptions(); EXPECT_THAT(internalOptions, ::testing::HasSubstr(std::string("cl_khr_3d_image_writes"))); } - TEST_F(OfflineCompilerTests, GoodBuildTest) { - auto argv = { + std::vector argv = { "ocloc", "-file", "test_files/copybuffer.cl", "-device", gEnvironment->devicePrefix.c_str()}; - pOfflineCompiler = OfflineCompiler::create(argv.size(), argv.begin(), retVal); + pOfflineCompiler = OfflineCompiler::create(argv.size(), argv, retVal); EXPECT_NE(nullptr, pOfflineCompiler); EXPECT_EQ(CL_SUCCESS, retVal); @@ -98,9 +246,8 @@ TEST_F(OfflineCompilerTests, GoodBuildTest) { delete pOfflineCompiler; } - TEST_F(OfflineCompilerTests, GoodBuildTestWithLlvmText) { - auto argv = { + std::vector argv = { "ocloc", "-file", "test_files/copybuffer.cl", @@ -108,7 +255,7 @@ TEST_F(OfflineCompilerTests, GoodBuildTestWithLlvmText) { gEnvironment->devicePrefix.c_str(), "-llvm_text"}; - pOfflineCompiler = OfflineCompiler::create(argv.size(), argv.begin(), retVal); + pOfflineCompiler = OfflineCompiler::create(argv.size(), argv, retVal); EXPECT_NE(nullptr, pOfflineCompiler); EXPECT_EQ(CL_SUCCESS, retVal); @@ -121,16 +268,15 @@ TEST_F(OfflineCompilerTests, GoodBuildTestWithLlvmText) { delete pOfflineCompiler; } - TEST_F(OfflineCompilerTests, GoodParseBinToCharArray) { - auto argv = { + std::vector argv = { "ocloc", "-file", "test_files/copybuffer.cl", "-device", gEnvironment->devicePrefix.c_str()}; - pOfflineCompiler = OfflineCompiler::create(argv.size(), argv.begin(), retVal); + pOfflineCompiler = OfflineCompiler::create(argv.size(), argv, retVal); // clang-format off uint8_t binary[] = { 0x02, 0x23, 0x3, 0x40, 0x56, 0x7, 0x80, 0x90, 0x1, 0x03, @@ -168,9 +314,8 @@ TEST_F(OfflineCompilerTests, GoodParseBinToCharArray) { delete pOfflineCompiler; } - TEST_F(OfflineCompilerTests, GoodBuildTestWithCppFile) { - auto argv = { + std::vector argv = { "ocloc", "-file", "test_files/copybuffer.cl", @@ -178,7 +323,7 @@ TEST_F(OfflineCompilerTests, GoodBuildTestWithCppFile) { gEnvironment->devicePrefix.c_str(), "-cpp_file"}; - pOfflineCompiler = OfflineCompiler::create(argv.size(), argv.begin(), retVal); + pOfflineCompiler = OfflineCompiler::create(argv.size(), argv, retVal); EXPECT_NE(nullptr, pOfflineCompiler); EXPECT_EQ(CL_SUCCESS, retVal); @@ -192,9 +337,8 @@ TEST_F(OfflineCompilerTests, GoodBuildTestWithCppFile) { delete pOfflineCompiler; } - TEST_F(OfflineCompilerTests, GoodBuildTestWithOutputDir) { - auto argv = { + std::vector argv = { "ocloc", "-file", "test_files/copybuffer.cl", @@ -203,7 +347,7 @@ TEST_F(OfflineCompilerTests, GoodBuildTestWithOutputDir) { "-out_dir", "offline_compiler_test"}; - pOfflineCompiler = OfflineCompiler::create(argv.size(), argv.begin(), retVal); + pOfflineCompiler = OfflineCompiler::create(argv.size(), argv, retVal); EXPECT_NE(nullptr, pOfflineCompiler); EXPECT_EQ(CL_SUCCESS, retVal); @@ -216,14 +360,13 @@ TEST_F(OfflineCompilerTests, GoodBuildTestWithOutputDir) { delete pOfflineCompiler; } - TEST_F(OfflineCompilerTests, PrintUsage) { - auto argv = { + std::vector argv = { "ocloc", "-?"}; testing::internal::CaptureStdout(); - pOfflineCompiler = OfflineCompiler::create(argv.size(), argv.begin(), retVal); + pOfflineCompiler = OfflineCompiler::create(argv.size(), argv, retVal); std::string output = testing::internal::GetCapturedStdout(); EXPECT_EQ(nullptr, pOfflineCompiler); EXPECT_STRNE("", output.c_str()); @@ -231,10 +374,9 @@ TEST_F(OfflineCompilerTests, PrintUsage) { delete pOfflineCompiler; } - TEST_F(OfflineCompilerTests, NaughtyArgTest_File) { DebugManager.flags.PrintDebugMessages.set(true); - auto argv = { + std::vector argv = { "ocloc", "-file", "test_files/ImANaughtyFile.cl", @@ -242,7 +384,7 @@ TEST_F(OfflineCompilerTests, NaughtyArgTest_File) { gEnvironment->devicePrefix.c_str()}; testing::internal::CaptureStdout(); - pOfflineCompiler = OfflineCompiler::create(argv.size(), argv.begin(), retVal); + pOfflineCompiler = OfflineCompiler::create(argv.size(), argv, retVal); std::string output = testing::internal::GetCapturedStdout(); EXPECT_STRNE(output.c_str(), ""); EXPECT_EQ(nullptr, pOfflineCompiler); @@ -252,7 +394,7 @@ TEST_F(OfflineCompilerTests, NaughtyArgTest_File) { } TEST_F(OfflineCompilerTests, NaughtyArgTest_Flag) { - auto argv = { + std::vector argv = { "ocloc", "-n", "test_files/ImANaughtyFile.cl", @@ -260,7 +402,7 @@ TEST_F(OfflineCompilerTests, NaughtyArgTest_Flag) { gEnvironment->devicePrefix.c_str()}; testing::internal::CaptureStdout(); - pOfflineCompiler = OfflineCompiler::create(argv.size(), argv.begin(), retVal); + pOfflineCompiler = OfflineCompiler::create(argv.size(), argv, retVal); std::string output = testing::internal::GetCapturedStdout(); EXPECT_STRNE(output.c_str(), ""); EXPECT_EQ(nullptr, pOfflineCompiler); @@ -270,13 +412,13 @@ TEST_F(OfflineCompilerTests, NaughtyArgTest_Flag) { } TEST_F(OfflineCompilerTests, NaughtyArgTest_NumArgs) { - auto argvA = { + std::vector argvA = { "ocloc", "-file", }; testing::internal::CaptureStdout(); - pOfflineCompiler = OfflineCompiler::create(argvA.size(), argvA.begin(), retVal); + pOfflineCompiler = OfflineCompiler::create(argvA.size(), argvA, retVal); std::string output = testing::internal::GetCapturedStdout(); EXPECT_STRNE(output.c_str(), ""); @@ -285,13 +427,13 @@ TEST_F(OfflineCompilerTests, NaughtyArgTest_NumArgs) { delete pOfflineCompiler; - auto argvB = { + std::vector argvB = { "ocloc", "-file", "test_files/ImANaughtyFile.cl", "-device"}; testing::internal::CaptureStdout(); - pOfflineCompiler = OfflineCompiler::create(argvB.size(), argvB.begin(), retVal); + pOfflineCompiler = OfflineCompiler::create(argvB.size(), argvB, retVal); output = testing::internal::GetCapturedStdout(); EXPECT_STRNE(output.c_str(), ""); EXPECT_EQ(nullptr, pOfflineCompiler); @@ -301,7 +443,7 @@ TEST_F(OfflineCompilerTests, NaughtyArgTest_NumArgs) { } TEST_F(OfflineCompilerTests, GivenNonexistantDeviceWhenCompilingThenExitWithErrorMsg) { - auto argv = { + std::vector argv = { "ocloc", "-file", "test_files/copybuffer.cl", @@ -309,7 +451,7 @@ TEST_F(OfflineCompilerTests, GivenNonexistantDeviceWhenCompilingThenExitWithErro "foobar"}; testing::internal::CaptureStdout(); - pOfflineCompiler = OfflineCompiler::create(argv.size(), argv.begin(), retVal); + pOfflineCompiler = OfflineCompiler::create(argv.size(), argv, retVal); std::string output = testing::internal::GetCapturedStdout(); EXPECT_STREQ(output.c_str(), "Error: Cannot get HW Info for device foobar.\n"); EXPECT_EQ(nullptr, pOfflineCompiler); @@ -317,14 +459,14 @@ TEST_F(OfflineCompilerTests, GivenNonexistantDeviceWhenCompilingThenExitWithErro } TEST_F(OfflineCompilerTests, NaughtyKernelTest) { - auto argv = { + std::vector argv = { "ocloc", "-file", "test_files/shouldfail.cl", "-device", gEnvironment->devicePrefix.c_str()}; - pOfflineCompiler = OfflineCompiler::create(argv.size(), argv.begin(), retVal); + pOfflineCompiler = OfflineCompiler::create(argv.size(), argv, retVal); EXPECT_NE(nullptr, pOfflineCompiler); EXPECT_EQ(CL_SUCCESS, retVal); @@ -347,7 +489,7 @@ TEST_F(OfflineCompilerTests, NaughtyKernelTest) { } TEST(OfflineCompilerTest, parseCmdLine) { - auto argv = { + std::vector argv = { "ocloc", "-cl-intel-greater-than-4GB-buffer-required"}; @@ -355,7 +497,7 @@ TEST(OfflineCompilerTest, parseCmdLine) { ASSERT_NE(nullptr, mockOfflineCompiler); testing::internal::CaptureStdout(); - mockOfflineCompiler->parseCommandLine(argv.size(), argv.begin()); + mockOfflineCompiler->parseCommandLine(argv.size(), argv); std::string output = testing::internal::GetCapturedStdout(); std::string internalOptions = mockOfflineCompiler->getInternalOptions(); @@ -516,14 +658,14 @@ TEST(OfflineCompilerTest, buildSourceCode) { auto retVal = mockOfflineCompiler->buildSourceCode(); EXPECT_EQ(CL_INVALID_PROGRAM, retVal); - auto argv = { + std::vector argv = { "ocloc", "-file", "test_files/copybuffer.cl", "-device", gEnvironment->devicePrefix.c_str()}; - retVal = mockOfflineCompiler->initialize(argv.size(), argv.begin()); + retVal = mockOfflineCompiler->initialize(argv.size(), argv); EXPECT_EQ(CL_SUCCESS, retVal); EXPECT_EQ(nullptr, mockOfflineCompiler->getGenBinary()); @@ -543,14 +685,14 @@ TEST(OfflineCompilerTest, GivenKernelWhenNoCharAfterKernelSourceThenBuildWithSuc auto retVal = mockOfflineCompiler->buildSourceCode(); EXPECT_EQ(CL_INVALID_PROGRAM, retVal); - auto argv = { + std::vector argv = { "ocloc", "-file", "test_files/emptykernel.cl", "-device", gEnvironment->devicePrefix.c_str()}; - retVal = mockOfflineCompiler->initialize(argv.size(), argv.begin()); + retVal = mockOfflineCompiler->initialize(argv.size(), argv); EXPECT_EQ(CL_SUCCESS, retVal); retVal = mockOfflineCompiler->buildSourceCode(); @@ -588,7 +730,7 @@ TEST(OfflineCompilerTest, generateElfBinary) { } TEST(OfflineCompilerTest, givenLlvmInputOptionPassedWhenCmdLineParsedThenInputFileLlvmIsSetTrue) { - auto argv = { + std::vector argv = { "ocloc", "-llvm_input"}; @@ -596,7 +738,7 @@ TEST(OfflineCompilerTest, givenLlvmInputOptionPassedWhenCmdLineParsedThenInputFi ASSERT_NE(nullptr, mockOfflineCompiler); testing::internal::CaptureStdout(); - mockOfflineCompiler->parseCommandLine(argv.size(), argv.begin()); + mockOfflineCompiler->parseCommandLine(argv.size(), argv); std::string output = testing::internal::GetCapturedStdout(); EXPECT_NE(0u, output.size()); @@ -614,12 +756,12 @@ TEST(OfflineCompilerTest, givenDefaultOfflineCompilerObjectWhenNoOptionsAreChang } TEST(OfflineCompilerTest, givenSpirvInputOptionPassedWhenCmdLineParsedThenInputFileSpirvIsSetTrue) { - auto argv = {"ocloc", "-spirv_input"}; + std::vector argv = {"ocloc", "-spirv_input"}; auto mockOfflineCompiler = std::unique_ptr(new MockOfflineCompiler()); testing::internal::CaptureStdout(); - mockOfflineCompiler->parseCommandLine(argv.size(), argv.begin()); + mockOfflineCompiler->parseCommandLine(argv.size(), argv); std::string output = testing::internal::GetCapturedStdout(); EXPECT_NE(0u, output.size()); @@ -633,14 +775,14 @@ TEST(OfflineCompilerTest, givenDefaultOfflineCompilerObjectWhenNoOptionsAreChang TEST(OfflineCompilerTest, givenIntermediatedRepresentationInputWhenBuildSourceCodeIsCalledThenProperTranslationContextIsUsed) { MockOfflineCompiler mockOfflineCompiler; - auto argv = { + std::vector argv = { "ocloc", "-file", "test_files/emptykernel.cl", "-device", gEnvironment->devicePrefix.c_str()}; - auto retVal = mockOfflineCompiler.initialize(argv.size(), argv.begin()); + auto retVal = mockOfflineCompiler.initialize(argv.size(), argv); auto mockIgcOclDeviceCtx = new NEO::MockIgcOclDeviceCtx(); mockOfflineCompiler.igcDeviceCtx = CIF::RAII::Pack(mockIgcOclDeviceCtx); ASSERT_EQ(CL_SUCCESS, retVal); @@ -663,16 +805,16 @@ TEST(OfflineCompilerTest, givenIntermediatedRepresentationInputWhenBuildSourceCo } TEST(OfflineCompilerTest, givenBinaryInputThenDontTruncateSourceAtFirstZero) { - auto argvLlvm = {"ocloc", "-llvm_input", "-file", "test_files/binary_with_zeroes", - "-device", gEnvironment->devicePrefix.c_str()}; + std::vector argvLlvm = {"ocloc", "-llvm_input", "-file", "test_files/binary_with_zeroes", + "-device", gEnvironment->devicePrefix.c_str()}; auto mockOfflineCompiler = std::make_unique(); - mockOfflineCompiler->initialize(argvLlvm.size(), argvLlvm.begin()); + mockOfflineCompiler->initialize(argvLlvm.size(), argvLlvm); EXPECT_LT(0U, mockOfflineCompiler->sourceCode.size()); - auto argvSpirV = {"ocloc", "-spirv_input", "-file", "test_files/binary_with_zeroes", - "-device", gEnvironment->devicePrefix.c_str()}; + std::vector argvSpirV = {"ocloc", "-spirv_input", "-file", "test_files/binary_with_zeroes", + "-device", gEnvironment->devicePrefix.c_str()}; mockOfflineCompiler = std::make_unique(); - mockOfflineCompiler->initialize(argvSpirV.size(), argvSpirV.begin()); + mockOfflineCompiler->initialize(argvSpirV.size(), argvSpirV); EXPECT_LT(0U, mockOfflineCompiler->sourceCode.size()); } @@ -685,7 +827,7 @@ TEST(OfflineCompilerTest, givenSpirvInputFileWhenCmdLineHasOptionsThenCorrectOpt NEO::setIgcDebugVars(igcDebugVars); MockOfflineCompiler mockOfflineCompiler; - auto argv = { + std::vector argv = { "ocloc", "-file", "test_files/emptykernel.cl", @@ -695,7 +837,7 @@ TEST(OfflineCompilerTest, givenSpirvInputFileWhenCmdLineHasOptionsThenCorrectOpt "-options", "test_options_passed"}; - auto retVal = mockOfflineCompiler.initialize(argv.size(), argv.begin()); + auto retVal = mockOfflineCompiler.initialize(argv.size(), argv); auto mockIgcOclDeviceCtx = new NEO::MockIgcOclDeviceCtx(); mockOfflineCompiler.igcDeviceCtx = CIF::RAII::Pack(mockIgcOclDeviceCtx); ASSERT_EQ(CL_SUCCESS, retVal); @@ -710,7 +852,7 @@ TEST(OfflineCompilerTest, givenSpirvInputFileWhenCmdLineHasOptionsThenCorrectOpt } TEST(OfflineCompilerTest, givenOutputFileOptionWhenSourceIsCompiledThenOutputFileHasCorrectName) { - auto argv = { + std::vector argv = { "ocloc", "-file", "test_files/copybuffer.cl", @@ -722,7 +864,7 @@ TEST(OfflineCompilerTest, givenOutputFileOptionWhenSourceIsCompiledThenOutputFil auto mockOfflineCompiler = std::unique_ptr(new MockOfflineCompiler()); ASSERT_NE(nullptr, mockOfflineCompiler); - int retVal = mockOfflineCompiler->initialize(argv.size(), argv.begin()); + int retVal = mockOfflineCompiler->initialize(argv.size(), argv); EXPECT_EQ(CL_SUCCESS, retVal); EXPECT_FALSE(compilerOutputExists("myOutputFileName", "bc") || compilerOutputExists("myOutputFileName", "spv")); @@ -743,7 +885,7 @@ TEST(OfflineCompilerTest, givenOutputFileOptionWhenSourceIsCompiledThenOutputFil } TEST(OfflineCompilerTest, givenDebugDataAvailableWhenSourceIsBuiltThenDebugDataFileIsCreated) { - auto argv = { + std::vector argv = { "ocloc", "-file", "test_files/copybuffer.cl", @@ -762,7 +904,7 @@ TEST(OfflineCompilerTest, givenDebugDataAvailableWhenSourceIsBuiltThenDebugDataF auto mockOfflineCompiler = std::unique_ptr(new MockOfflineCompiler()); ASSERT_NE(nullptr, mockOfflineCompiler); - int retVal = mockOfflineCompiler->initialize(argv.size(), argv.begin()); + int retVal = mockOfflineCompiler->initialize(argv.size(), argv); EXPECT_EQ(CL_SUCCESS, retVal); EXPECT_FALSE(compilerOutputExists("myOutputFileName", "bc") || compilerOutputExists("myOutputFileName", "spv")); @@ -788,7 +930,7 @@ TEST(OfflineCompilerTest, givenDebugDataAvailableWhenSourceIsBuiltThenDebugDataF } TEST(OfflineCompilerTest, givenInternalOptionsWhenCmdLineParsedThenOptionsAreAppendedToInternalOptionsString) { - auto argv = { + std::vector argv = { "ocloc", "-internal_options", "myInternalOptions"}; @@ -797,7 +939,7 @@ TEST(OfflineCompilerTest, givenInternalOptionsWhenCmdLineParsedThenOptionsAreApp ASSERT_NE(nullptr, mockOfflineCompiler); testing::internal::CaptureStdout(); - mockOfflineCompiler->parseCommandLine(argv.size(), argv.begin()); + mockOfflineCompiler->parseCommandLine(argv.size(), argv); std::string output = testing::internal::GetCapturedStdout(); EXPECT_NE(0u, output.size()); @@ -813,7 +955,7 @@ TEST(OfflineCompilerTest, givenInputOptionsAndInternalOptionsFilesWhenOfflineCom ASSERT_TRUE(fileExists("test_files/shouldfail_options.txt")); ASSERT_TRUE(fileExists("test_files/shouldfail_internal_options.txt")); - auto argv = { + std::vector argv = { "ocloc", "-q", "-file", @@ -821,7 +963,7 @@ TEST(OfflineCompilerTest, givenInputOptionsAndInternalOptionsFilesWhenOfflineCom "-device", gEnvironment->devicePrefix.c_str()}; - int retVal = mockOfflineCompiler->initialize(argv.size(), argv.begin()); + int retVal = mockOfflineCompiler->initialize(argv.size(), argv); EXPECT_EQ(CL_SUCCESS, retVal); auto &options = mockOfflineCompiler->getOptions(); diff --git a/unit_tests/offline_compiler/offline_compiler_tests.h b/unit_tests/offline_compiler/offline_compiler_tests.h index 32dd1ff5de..269dbb77aa 100644 --- a/unit_tests/offline_compiler/offline_compiler_tests.h +++ b/unit_tests/offline_compiler/offline_compiler_tests.h @@ -6,6 +6,7 @@ */ #pragma once +#include "offline_compiler/multi_command.h" #include "offline_compiler/offline_compiler.h" #include "gtest/gtest.h" @@ -26,4 +27,34 @@ class OfflineCompilerTests : public ::testing::Test { int retVal; }; +class MultiCommandTests : public ::testing::Test { + public: + MultiCommandTests() : pMultiCommand(nullptr), + retVal(CL_SUCCESS) { + } + void createFileWithArgs(const std::vector &, int numOfBuild); + void deleteFileWithArgs(); + MultiCommand *pMultiCommand; + std::string nameOfFileWithArgs; + int retVal; +}; + +void MultiCommandTests::createFileWithArgs(const std::vector &singleArgs, int numOfBuild) { + std::ofstream myfile(nameOfFileWithArgs); + if (myfile.is_open()) { + for (int i = 0; i < numOfBuild; i++) { + for (auto singleArg : singleArgs) + myfile << singleArg + " "; + myfile << std::endl; + } + myfile.close(); + } else + printf("Unable to open file\n"); +} + +void MultiCommandTests::deleteFileWithArgs() { + if (remove(nameOfFileWithArgs.c_str()) != 0) + perror("Error deleting file"); +} + } // namespace NEO