diff options
Diffstat (limited to 'Source/CTest')
39 files changed, 881 insertions, 566 deletions
diff --git a/Source/CTest/cmCTestBZR.cxx b/Source/CTest/cmCTestBZR.cxx index 015220091..365f26774 100644 --- a/Source/CTest/cmCTestBZR.cxx +++ b/Source/CTest/cmCTestBZR.cxx @@ -155,8 +155,9 @@ bool cmCTestBZR::NoteOldRevision() { this->OldRevision = this->LoadInfo(); this->Log << "Revision before update: " << this->OldRevision << "\n"; - cmCTestLog(this->CTest, HANDLER_OUTPUT, " Old revision of repository is: " - << this->OldRevision << "\n"); + cmCTestLog(this->CTest, HANDLER_OUTPUT, + " Old revision of repository is: " << this->OldRevision + << "\n"); this->PriorRev.Rev = this->OldRevision; return true; } @@ -165,14 +166,16 @@ bool cmCTestBZR::NoteNewRevision() { this->NewRevision = this->LoadInfo(); this->Log << "Revision after update: " << this->NewRevision << "\n"; - cmCTestLog(this->CTest, HANDLER_OUTPUT, " New revision of repository is: " - << this->NewRevision << "\n"); + cmCTestLog(this->CTest, HANDLER_OUTPUT, + " New revision of repository is: " << this->NewRevision + << "\n"); this->Log << "URL = " << this->URL << "\n"; return true; } -class cmCTestBZR::LogParser : public cmCTestVC::OutputLogger, - private cmXMLParser +class cmCTestBZR::LogParser + : public cmCTestVC::OutputLogger + , private cmXMLParser { public: LogParser(cmCTestBZR* bzr, const char* prefix) diff --git a/Source/CTest/cmCTestBuildAndTestHandler.cxx b/Source/CTest/cmCTestBuildAndTestHandler.cxx index 2e1ea4c3a..fccbc9530 100644 --- a/Source/CTest/cmCTestBuildAndTestHandler.cxx +++ b/Source/CTest/cmCTestBuildAndTestHandler.cxx @@ -11,6 +11,7 @@ #include "cmsys/Process.h" #include <chrono> +#include <cstring> #include <ratio> #include <stdlib.h> @@ -196,6 +197,16 @@ int cmCTestBuildAndTestHandler::RunCMakeAndTest(std::string* outstring) cmSystemTools::MakeDirectory(this->BinaryDir); } cmWorkingDirectory workdir(this->BinaryDir); + if (workdir.Failed()) { + auto msg = "Failed to change working directory to " + this->BinaryDir + + " : " + std::strerror(workdir.GetLastResult()) + "\n"; + if (outstring) { + *outstring = msg; + } else { + cmCTestLog(this->CTest, ERROR_MESSAGE, msg); + } + return 1; + } if (this->BuildNoCMake) { // Make the generator available for the Build call below. @@ -242,9 +253,9 @@ int cmCTestBuildAndTestHandler::RunCMakeAndTest(std::string* outstring) config = "Debug"; } int retVal = cm.GetGlobalGenerator()->Build( - this->SourceDir, this->BinaryDir, this->BuildProject, tar, output, - this->BuildMakeProgram, config, !this->BuildNoClean, false, false, - remainingTime); + cmake::NO_BUILD_PARALLEL_LEVEL, this->SourceDir, this->BinaryDir, + this->BuildProject, tar, output, this->BuildMakeProgram, config, + !this->BuildNoClean, false, false, remainingTime); out << output; // if the build failed then return if (retVal) { @@ -307,7 +318,16 @@ int cmCTestBuildAndTestHandler::RunCMakeAndTest(std::string* outstring) // run the test from the this->BuildRunDir if set if (!this->BuildRunDir.empty()) { out << "Run test in directory: " << this->BuildRunDir << "\n"; - cmSystemTools::ChangeDirectory(this->BuildRunDir); + if (!workdir.SetDirectory(this->BuildRunDir)) { + out << "Failed to change working directory : " + << std::strerror(workdir.GetLastResult()) << "\n"; + if (outstring) { + *outstring = out.str(); + } else { + cmCTestLog(this->CTest, ERROR_MESSAGE, out.str()); + } + return 1; + } } out << "Running test command: \"" << fullPath << "\""; for (std::string const& testCommandArg : this->TestCommandArgs) { diff --git a/Source/CTest/cmCTestBuildHandler.cxx b/Source/CTest/cmCTestBuildHandler.cxx index ce6fbc75d..8527d5497 100644 --- a/Source/CTest/cmCTestBuildHandler.cxx +++ b/Source/CTest/cmCTestBuildHandler.cxx @@ -299,7 +299,8 @@ int cmCTestBuildHandler::ProcessHandler() this->ErrorWarningFileLineRegex.push_back(std::move(r)); } else { cmCTestLog( - this->CTest, ERROR_MESSAGE, "Problem Compiling regular expression: " + this->CTest, ERROR_MESSAGE, + "Problem Compiling regular expression: " << cmCTestWarningErrorFileLine[entry].RegularExpressionString << std::endl); } @@ -331,8 +332,8 @@ int cmCTestBuildHandler::ProcessHandler() cmGeneratedFileStream ofs; auto elapsed_time_start = std::chrono::steady_clock::now(); if (!this->StartLogFile("Build", ofs)) { - cmCTestLog(this->CTest, ERROR_MESSAGE, "Cannot create build log file" - << std::endl); + cmCTestLog(this->CTest, ERROR_MESSAGE, + "Cannot create build log file" << std::endl); } // Create lists of regular expression strings for errors, error exceptions, @@ -352,7 +353,7 @@ int cmCTestBuildHandler::ProcessHandler() this->CustomWarningExceptions.push_back(cmCTestWarningExceptions[cc]); } -// Pre-compile regular expressions objects for all regular expressions + // Pre-compile regular expressions objects for all regular expressions #define cmCTestBuildHandlerPopulateRegexVector(strings, regexes) \ regexes.clear(); \ @@ -452,8 +453,8 @@ int cmCTestBuildHandler::ProcessHandler() // Generate XML output cmGeneratedFileStream xofs; if (!this->StartResultingXML(cmCTest::PartBuild, "Build", xofs)) { - cmCTestLog(this->CTest, ERROR_MESSAGE, "Cannot create build XML file" - << std::endl); + cmCTestLog(this->CTest, ERROR_MESSAGE, + "Cannot create build XML file" << std::endl); return -1; } cmXMLWriter xml(xofs); @@ -466,19 +467,20 @@ int cmCTestBuildHandler::ProcessHandler() this->GenerateXMLFooter(xml, elapsed_build_time); if (res != cmsysProcess_State_Exited || retVal || this->TotalErrors > 0) { - cmCTestLog(this->CTest, ERROR_MESSAGE, "Error(s) when building project" - << std::endl); + cmCTestLog(this->CTest, ERROR_MESSAGE, + "Error(s) when building project" << std::endl); } // Display message about number of errors and warnings - cmCTestLog(this->CTest, HANDLER_OUTPUT, " " - << this->TotalErrors - << (this->TotalErrors >= this->MaxErrors ? " or more" : "") - << " Compiler errors" << std::endl); - cmCTestLog(this->CTest, HANDLER_OUTPUT, " " - << this->TotalWarnings - << (this->TotalWarnings >= this->MaxWarnings ? " or more" : "") - << " Compiler warnings" << std::endl); + cmCTestLog(this->CTest, HANDLER_OUTPUT, + " " << this->TotalErrors + << (this->TotalErrors >= this->MaxErrors ? " or more" : "") + << " Compiler errors" << std::endl); + cmCTestLog( + this->CTest, HANDLER_OUTPUT, + " " << this->TotalWarnings + << (this->TotalWarnings >= this->MaxWarnings ? " or more" : "") + << " Compiler warnings" << std::endl); return retVal; } @@ -779,8 +781,8 @@ int cmCTestBuildHandler::RunMakeCommand(const char* command, int* retVal, } argv.push_back(nullptr); - cmCTestOptionalLog(this->CTest, HANDLER_VERBOSE_OUTPUT, "Run command:", - this->Quiet); + cmCTestOptionalLog(this->CTest, HANDLER_VERBOSE_OUTPUT, + "Run command:", this->Quiet); for (char const* arg : argv) { if (!arg) { break; @@ -812,7 +814,8 @@ int cmCTestBuildHandler::RunMakeCommand(const char* command, int* retVal, cmProcessOutput processOutput(encoding); std::string strdata; cmCTestOptionalLog( - this->CTest, HANDLER_PROGRESS_OUTPUT, " Each symbol represents " + this->CTest, HANDLER_PROGRESS_OUTPUT, + " Each symbol represents " << tick_len << " bytes of output." << std::endl << (this->UseCTestLaunch ? "" @@ -868,7 +871,8 @@ int cmCTestBuildHandler::RunMakeCommand(const char* command, int* retVal, &this->BuildProcessingQueue); this->ProcessBuffer(nullptr, 0, tick, tick_len, ofs, &this->BuildProcessingErrorQueue); - cmCTestOptionalLog(this->CTest, HANDLER_PROGRESS_OUTPUT, " Size of output: " + cmCTestOptionalLog(this->CTest, HANDLER_PROGRESS_OUTPUT, + " Size of output: " << ((this->BuildOutputLogSize + 512) / 1024) << "K" << std::endl, this->Quiet); @@ -921,8 +925,9 @@ int cmCTestBuildHandler::RunMakeCommand(const char* command, int* retVal, errorwarning.Error = true; this->ErrorsAndWarnings.push_back(std::move(errorwarning)); this->TotalErrors++; - cmCTestLog(this->CTest, ERROR_MESSAGE, "There was an error: " - << cmsysProcess_GetErrorString(cp) << std::endl); + cmCTestLog(this->CTest, ERROR_MESSAGE, + "There was an error: " << cmsysProcess_GetErrorString(cp) + << std::endl); } cmsysProcess_Delete(cp); @@ -1049,7 +1054,8 @@ void cmCTestBuildHandler::ProcessBuffer(const char* data, size_t length, this->LastTickChar, this->Quiet); tickDisplayed = true; if (tick % tick_line_len == 0 && tick > 0) { - cmCTestOptionalLog(this->CTest, HANDLER_PROGRESS_OUTPUT, " Size: " + cmCTestOptionalLog(this->CTest, HANDLER_PROGRESS_OUTPUT, + " Size: " << ((this->BuildOutputLogSize + 512) / 1024) << "K" << std::endl << " ", @@ -1103,7 +1109,8 @@ int cmCTestBuildHandler::ProcessSingleLine(const char* data) for (cmsys::RegularExpression& rx : this->ErrorExceptionRegex) { if (rx.find(data)) { errorLine = 0; - cmCTestOptionalLog(this->CTest, DEBUG, " Not an error Line: " + cmCTestOptionalLog(this->CTest, DEBUG, + " Not an error Line: " << data << " (matches: " << this->CustomErrorExceptions[wrxCnt] << ")" << std::endl, @@ -1119,7 +1126,8 @@ int cmCTestBuildHandler::ProcessSingleLine(const char* data) for (cmsys::RegularExpression& rx : this->WarningMatchRegex) { if (rx.find(data)) { warningLine = 1; - cmCTestOptionalLog(this->CTest, DEBUG, " Warning Line: " + cmCTestOptionalLog(this->CTest, DEBUG, + " Warning Line: " << data << " (matches: " << this->CustomWarningMatches[wrxCnt] << ")" << std::endl, @@ -1134,7 +1142,8 @@ int cmCTestBuildHandler::ProcessSingleLine(const char* data) for (cmsys::RegularExpression& rx : this->WarningExceptionRegex) { if (rx.find(data)) { warningLine = 0; - cmCTestOptionalLog(this->CTest, DEBUG, " Not a warning Line: " + cmCTestOptionalLog(this->CTest, DEBUG, + " Not a warning Line: " << data << " (matches: " << this->CustomWarningExceptions[wrxCnt] << ")" << std::endl, diff --git a/Source/CTest/cmCTestCVS.cxx b/Source/CTest/cmCTestCVS.cxx index 5779935aa..4fb3273bb 100644 --- a/Source/CTest/cmCTestCVS.cxx +++ b/Source/CTest/cmCTestCVS.cxx @@ -134,8 +134,9 @@ private: bool ProcessLine() override { - if (this->Line == ("=======================================" - "======================================")) { + if (this->Line == + ("=======================================" + "======================================")) { // This line ends the revision list. if (this->Section == SectionRevisions) { this->FinishRevision(); diff --git a/Source/CTest/cmCTestConfigureHandler.cxx b/Source/CTest/cmCTestConfigureHandler.cxx index 821a94a00..5967b7458 100644 --- a/Source/CTest/cmCTestConfigureHandler.cxx +++ b/Source/CTest/cmCTestConfigureHandler.cxx @@ -51,8 +51,8 @@ int cmCTestConfigureHandler::ProcessHandler() if (!this->CTest->GetShowOnly()) { cmGeneratedFileStream os; if (!this->StartResultingXML(cmCTest::PartConfigure, "Configure", os)) { - cmCTestLog(this->CTest, ERROR_MESSAGE, "Cannot open configure file" - << std::endl); + cmCTestLog(this->CTest, ERROR_MESSAGE, + "Cannot open configure file" << std::endl); return 1; } std::string start_time = this->CTest->CurrentTime(); diff --git a/Source/CTest/cmCTestCoverageHandler.cxx b/Source/CTest/cmCTestCoverageHandler.cxx index 9c66e73f3..43a2baec3 100644 --- a/Source/CTest/cmCTestCoverageHandler.cxx +++ b/Source/CTest/cmCTestCoverageHandler.cxx @@ -23,6 +23,7 @@ #include "cmsys/RegularExpression.hxx" #include <algorithm> #include <chrono> +#include <cstring> #include <iomanip> #include <iterator> #include <sstream> @@ -196,10 +197,10 @@ bool cmCTestCoverageHandler::ShouldIDoCoverage(std::string const& file, for (cmsys::RegularExpression& rx : this->CustomCoverageExcludeRegex) { if (rx.find(file)) { - cmCTestOptionalLog(this->CTest, HANDLER_VERBOSE_OUTPUT, " File " - << file << " is excluded in CTestCustom.ctest" - << std::endl; - , this->Quiet); + cmCTestOptionalLog( + this->CTest, HANDLER_VERBOSE_OUTPUT, + " File " << file << " is excluded in CTestCustom.ctest" << std::endl; + , this->Quiet); return false; } } @@ -390,8 +391,8 @@ int cmCTestCoverageHandler::ProcessHandler() if (!this->StartResultingXML(cmCTest::PartCoverage, "Coverage", covSumFile)) { - cmCTestLog(this->CTest, ERROR_MESSAGE, "Cannot open coverage summary file." - << std::endl); + cmCTestLog(this->CTest, ERROR_MESSAGE, + "Cannot open coverage summary file." << std::endl); return -1; } covSumFile.setf(std::ios::fixed, std::ios::floatfield); @@ -428,9 +429,10 @@ int cmCTestCoverageHandler::ProcessHandler() this->Quiet); file_count++; if (file_count % 50 == 0) { - cmCTestOptionalLog(this->CTest, HANDLER_OUTPUT, " processed: " - << file_count << " out of " - << cont.TotalCoverage.size() << std::endl, + cmCTestOptionalLog(this->CTest, HANDLER_OUTPUT, + " processed: " << file_count << " out of " + << cont.TotalCoverage.size() + << std::endl, this->Quiet); cmCTestOptionalLog(this->CTest, HANDLER_OUTPUT, " ", this->Quiet); } @@ -523,8 +525,9 @@ int cmCTestCoverageHandler::ProcessHandler() float cper = 0; float cmet = 0; if (tested + untested > 0) { - cper = (100 * SAFEDIV(static_cast<float>(tested), - static_cast<float>(tested + untested))); + cper = (100 * + SAFEDIV(static_cast<float>(tested), + static_cast<float>(tested + untested))); cmet = (SAFEDIV(static_cast<float>(tested + 10), static_cast<float>(tested + untested + 10))); } @@ -628,14 +631,14 @@ int cmCTestCoverageHandler::ProcessHandler() covSumXML.EndElement(); // Coverage this->CTest->EndXML(covSumXML); - cmCTestLog(this->CTest, HANDLER_OUTPUT, "" - << std::endl - << "\tCovered LOC: " << total_tested << std::endl - << "\tNot covered LOC: " << total_untested << std::endl - << "\tTotal LOC: " << total_lines << std::endl - << "\tPercentage Coverage: " - << std::setiosflags(std::ios::fixed) << std::setprecision(2) - << (percent_coverage) << "%" << std::endl); + cmCTestLog(this->CTest, HANDLER_OUTPUT, + "" << std::endl + << "\tCovered LOC: " << total_tested << std::endl + << "\tNot covered LOC: " << total_untested << std::endl + << "\tTotal LOC: " << total_lines << std::endl + << "\tPercentage Coverage: " + << std::setiosflags(std::ios::fixed) << std::setprecision(2) + << (percent_coverage) << "%" << std::endl); ofs << "\tCovered LOC: " << total_tested << std::endl << "\tNot covered LOC: " << total_untested << std::endl @@ -676,9 +679,9 @@ void cmCTestCoverageHandler::PopulateCustomVectors(cmMakefile* mf) // Compare file names: fnc(fn1) == fnc(fn2) // fnc == file name compare // #ifdef _WIN32 -#define fnc(s) cmSystemTools::LowerCase(s) +# define fnc(s) cmSystemTools::LowerCase(s) #else -#define fnc(s) s +# define fnc(s) s #endif bool IsFileInDir(const std::string& infile, const std::string& indir) @@ -927,7 +930,8 @@ int cmCTestCoverageHandler::HandleGCovCoverage( std::string gcovCommand = this->CTest->GetCTestConfiguration("CoverageCommand"); if (gcovCommand.empty()) { - cmCTestLog(this->CTest, WARNING, "Could not find gcov." << std::endl); + cmCTestOptionalLog(this->CTest, HANDLER_VERBOSE_OUTPUT, + "Could not find gcov." << std::endl, this->Quiet); return 0; } std::string gcovExtraFlags = @@ -975,7 +979,12 @@ int cmCTestCoverageHandler::HandleGCovCoverage( std::string testingDir = this->CTest->GetBinaryDir() + "/Testing"; std::string tempDir = testingDir + "/CoverageInfo"; - cmSystemTools::MakeDirectory(tempDir); + if (!cmSystemTools::MakeDirectory(tempDir)) { + cmCTestLog(this->CTest, ERROR_MESSAGE, + "Unable to make directory: " << tempDir << std::endl); + cont->Error++; + return 0; + } cmWorkingDirectory workdir(tempDir); int gcovStyle = 0; @@ -1038,7 +1047,8 @@ int cmCTestCoverageHandler::HandleGCovCoverage( continue; } if (retVal != 0) { - cmCTestLog(this->CTest, ERROR_MESSAGE, "Coverage command returned: " + cmCTestLog(this->CTest, ERROR_MESSAGE, + "Coverage command returned: " << retVal << " while processing: " << f << std::endl); cmCTestLog(this->CTest, ERROR_MESSAGE, "Command produced error: " << cont->Error << std::endl); @@ -1070,8 +1080,8 @@ int cmCTestCoverageHandler::HandleGCovCoverage( gcovStyle = 1; } if (gcovStyle != 1) { - cmCTestLog(this->CTest, ERROR_MESSAGE, "Unknown gcov output style e1" - << std::endl); + cmCTestLog(this->CTest, ERROR_MESSAGE, + "Unknown gcov output style e1" << std::endl); cont->Error++; break; } @@ -1083,8 +1093,8 @@ int cmCTestCoverageHandler::HandleGCovCoverage( gcovStyle = 1; } if (gcovStyle != 1) { - cmCTestLog(this->CTest, ERROR_MESSAGE, "Unknown gcov output style e2" - << std::endl); + cmCTestLog(this->CTest, ERROR_MESSAGE, + "Unknown gcov output style e2" << std::endl); cont->Error++; break; } @@ -1095,8 +1105,8 @@ int cmCTestCoverageHandler::HandleGCovCoverage( gcovStyle = 2; } if (gcovStyle != 2) { - cmCTestLog(this->CTest, ERROR_MESSAGE, "Unknown gcov output style e3" - << std::endl); + cmCTestLog(this->CTest, ERROR_MESSAGE, + "Unknown gcov output style e3" << std::endl); cont->Error++; break; } @@ -1108,8 +1118,8 @@ int cmCTestCoverageHandler::HandleGCovCoverage( gcovStyle = 2; } if (gcovStyle != 2) { - cmCTestLog(this->CTest, ERROR_MESSAGE, "Unknown gcov output style e4" - << std::endl); + cmCTestLog(this->CTest, ERROR_MESSAGE, + "Unknown gcov output style e4" << std::endl); cont->Error++; break; } @@ -1118,8 +1128,8 @@ int cmCTestCoverageHandler::HandleGCovCoverage( gcovStyle = 2; } if (gcovStyle != 2) { - cmCTestLog(this->CTest, ERROR_MESSAGE, "Unknown gcov output style e5" - << std::endl); + cmCTestLog(this->CTest, ERROR_MESSAGE, + "Unknown gcov output style e5" << std::endl); cont->Error++; break; } @@ -1130,8 +1140,8 @@ int cmCTestCoverageHandler::HandleGCovCoverage( gcovStyle = 2; } if (gcovStyle != 2) { - cmCTestLog(this->CTest, ERROR_MESSAGE, "Unknown gcov output style e6" - << std::endl); + cmCTestLog(this->CTest, ERROR_MESSAGE, + "Unknown gcov output style e6" << std::endl); cont->Error++; break; } @@ -1145,37 +1155,40 @@ int cmCTestCoverageHandler::HandleGCovCoverage( gcovStyle = 2; } if (gcovStyle != 2) { - cmCTestLog(this->CTest, ERROR_MESSAGE, "Unknown gcov output style e7" - << std::endl); + cmCTestLog(this->CTest, ERROR_MESSAGE, + "Unknown gcov output style e7" << std::endl); cont->Error++; break; } - cmCTestOptionalLog(this->CTest, WARNING, "Warning: Cannot open file: " - << st2re5.match(1) << std::endl, + cmCTestOptionalLog(this->CTest, WARNING, + "Warning: Cannot open file: " << st2re5.match(1) + << std::endl, this->Quiet); } else if (st2re6.find(line.c_str())) { if (gcovStyle == 0) { gcovStyle = 2; } if (gcovStyle != 2) { - cmCTestLog(this->CTest, ERROR_MESSAGE, "Unknown gcov output style e8" - << std::endl); + cmCTestLog(this->CTest, ERROR_MESSAGE, + "Unknown gcov output style e8" << std::endl); cont->Error++; break; } - cmCTestOptionalLog(this->CTest, WARNING, "Warning: File: " - << st2re6.match(1) << " is newer than " - << st2re6.match(2) << std::endl, + cmCTestOptionalLog(this->CTest, WARNING, + "Warning: File: " << st2re6.match(1) + << " is newer than " + << st2re6.match(2) << std::endl, this->Quiet); } else { // gcov 4.7 can have output lines saying "No executable lines" and // "Removing 'filename.gcov'"... Don't log those as "errors." if (line != "No executable lines" && !cmSystemTools::StringStartsWith(line.c_str(), "Removing ")) { - cmCTestLog(this->CTest, ERROR_MESSAGE, "Unknown gcov output line: [" - << line << "]" << std::endl); + cmCTestLog(this->CTest, ERROR_MESSAGE, + "Unknown gcov output line: [" << line << "]" + << std::endl); cont->Error++; // abort(); } @@ -1376,6 +1389,14 @@ int cmCTestCoverageHandler::HandleLCovCoverage( this->Quiet); std::string fileDir = cmSystemTools::GetFilenamePath(f); cmWorkingDirectory workdir(fileDir); + if (workdir.Failed()) { + cmCTestLog(this->CTest, ERROR_MESSAGE, + "Unable to change working directory to " + << fileDir << " : " + << std::strerror(workdir.GetLastResult()) << std::endl); + cont->Error++; + continue; + } cmCTestOptionalLog(this->CTest, HANDLER_VERBOSE_OUTPUT, "Current coverage dir: " << fileDir << std::endl, @@ -1403,7 +1424,8 @@ int cmCTestCoverageHandler::HandleLCovCoverage( continue; } if (retVal != 0) { - cmCTestLog(this->CTest, ERROR_MESSAGE, "Coverage command returned: " + cmCTestLog(this->CTest, ERROR_MESSAGE, + "Coverage command returned: " << retVal << " while processing: " << f << std::endl); cmCTestLog(this->CTest, ERROR_MESSAGE, "Command produced error: " << cont->Error << std::endl); @@ -1600,6 +1622,12 @@ bool cmCTestCoverageHandler::FindLCovFiles(std::vector<std::string>& files) gl.RecurseThroughSymlinksOff(); std::string buildDir = this->CTest->GetCTestConfiguration("BuildDirectory"); cmWorkingDirectory workdir(buildDir); + if (workdir.Failed()) { + cmCTestLog(this->CTest, ERROR_MESSAGE, + "Unable to change working directory to " << buildDir + << std::endl); + return false; + } // Run profmerge to merge all *.dyn files into dpi files if (!cmSystemTools::RunSingleCommand("profmerge")) { @@ -1796,7 +1824,8 @@ int cmCTestCoverageHandler::RunBullseyeCoverageBranch( "run covbr: " << std::endl, this->Quiet); if (!this->RunBullseyeCommand(cont, "covbr", nullptr, outputFile)) { - cmCTestLog(this->CTest, ERROR_MESSAGE, "error running covbr for." + cmCTestLog(this->CTest, ERROR_MESSAGE, + "error running covbr for." << "\n"); return -1; } @@ -1960,8 +1989,8 @@ int cmCTestCoverageHandler::RunBullseyeSourceSummary( cmXMLWriter xml(covSumFile); if (!this->StartResultingXML(cmCTest::PartCoverage, "Coverage", covSumFile)) { - cmCTestLog(this->CTest, ERROR_MESSAGE, "Cannot open coverage summary file." - << std::endl); + cmCTestLog(this->CTest, ERROR_MESSAGE, + "Cannot open coverage summary file." << std::endl); return 0; } this->CTest->StartXML(xml, this->AppendXML); @@ -2177,7 +2206,8 @@ bool cmCTestCoverageHandler::ParseBullsEyeCovsrcLine( } // should be at the end now if (pos != std::string::npos) { - cmCTestLog(this->CTest, ERROR_MESSAGE, "Error parsing input : " + cmCTestLog(this->CTest, ERROR_MESSAGE, + "Error parsing input : " << inputLine << " last pos not npos = " << pos << "\n"); } return true; diff --git a/Source/CTest/cmCTestCurl.cxx b/Source/CTest/cmCTestCurl.cxx index 7b5ea6005..6eb43546d 100644 --- a/Source/CTest/cmCTestCurl.cxx +++ b/Source/CTest/cmCTestCurl.cxx @@ -3,6 +3,7 @@ #include "cmCTestCurl.h" #include "cmCTest.h" +#include "cmCurl.h" #include "cmSystemTools.h" #include <ostream> @@ -76,6 +77,7 @@ bool cmCTestCurl::InitCurl() if (!this->Curl) { return false; } + cmCurlSetCAInfo(this->Curl); if (this->VerifyPeerOff) { curl_easy_setopt(this->Curl, CURLOPT_SSL_VERIFYPEER, 0); } @@ -146,7 +148,7 @@ bool cmCTestCurl::UploadFile(std::string const& local_file, ::curl_slist_append(nullptr, "Content-Type: text/xml"); // Add any additional headers that the user specified. for (std::string const& h : this->HttpHeaders) { - cmCTestOptionalLog(this->CTest, HANDLER_OUTPUT, + cmCTestOptionalLog(this->CTest, DEBUG, " Add HTTP Header: \"" << h << "\"" << std::endl, this->Quiet); headers = ::curl_slist_append(headers, h.c_str()); @@ -175,7 +177,8 @@ bool cmCTestCurl::UploadFile(std::string const& local_file, "Curl debug: [" << curlDebug << "]\n", this->Quiet); } if (response.empty()) { - cmCTestLog(this->CTest, ERROR_MESSAGE, "No response from server.\n" + cmCTestLog(this->CTest, ERROR_MESSAGE, + "No response from server.\n" << curlDebug); return false; } @@ -186,7 +189,8 @@ bool cmCTestCurl::HttpRequest(std::string const& url, std::string const& fields, std::string& response) { response.clear(); - cmCTestOptionalLog(this->CTest, DEBUG, "HttpRequest\n" + cmCTestOptionalLog(this->CTest, DEBUG, + "HttpRequest\n" << "url: " << url << "\n" << "fields " << fields << "\n", this->Quiet); @@ -212,7 +216,7 @@ bool cmCTestCurl::HttpRequest(std::string const& url, struct curl_slist* headers = nullptr; if (!this->HttpHeaders.empty()) { for (std::string const& h : this->HttpHeaders) { - cmCTestOptionalLog(this->CTest, HANDLER_OUTPUT, + cmCTestOptionalLog(this->CTest, DEBUG, " Add HTTP Header: \"" << h << "\"" << std::endl, this->Quiet); headers = ::curl_slist_append(headers, h.c_str()); diff --git a/Source/CTest/cmCTestCurl.h b/Source/CTest/cmCTestCurl.h index 427a39232..86d948995 100644 --- a/Source/CTest/cmCTestCurl.h +++ b/Source/CTest/cmCTestCurl.h @@ -16,7 +16,7 @@ class cmCTestCurl public: cmCTestCurl(cmCTest*); ~cmCTestCurl(); - bool UploadFile(std::string const& url, std::string const& file, + bool UploadFile(std::string const& local_file, std::string const& url, std::string const& fields, std::string& response); bool HttpRequest(std::string const& url, std::string const& fields, std::string& response); diff --git a/Source/CTest/cmCTestGIT.cxx b/Source/CTest/cmCTestGIT.cxx index e85af5edb..b919c7934 100644 --- a/Source/CTest/cmCTestGIT.cxx +++ b/Source/CTest/cmCTestGIT.cxx @@ -70,8 +70,9 @@ std::string cmCTestGIT::GetWorkingRevision() bool cmCTestGIT::NoteOldRevision() { this->OldRevision = this->GetWorkingRevision(); - cmCTestLog(this->CTest, HANDLER_OUTPUT, " Old revision of repository is: " - << this->OldRevision << "\n"); + cmCTestLog(this->CTest, HANDLER_OUTPUT, + " Old revision of repository is: " << this->OldRevision + << "\n"); this->PriorRev.Rev = this->OldRevision; return true; } @@ -79,8 +80,9 @@ bool cmCTestGIT::NoteOldRevision() bool cmCTestGIT::NoteNewRevision() { this->NewRevision = this->GetWorkingRevision(); - cmCTestLog(this->CTest, HANDLER_OUTPUT, " New revision of repository is: " - << this->NewRevision << "\n"); + cmCTestLog(this->CTest, HANDLER_OUTPUT, + " New revision of repository is: " << this->NewRevision + << "\n"); return true; } diff --git a/Source/CTest/cmCTestGenericHandler.cxx b/Source/CTest/cmCTestGenericHandler.cxx index ce8f70998..dc1bba051 100644 --- a/Source/CTest/cmCTestGenericHandler.cxx +++ b/Source/CTest/cmCTestGenericHandler.cxx @@ -100,8 +100,9 @@ bool cmCTestGenericHandler::StartResultingXML(cmCTest::Part part, } if (!this->CTest->OpenOutputFile(this->CTest->GetCurrentTag(), ostr.str(), xofs, true)) { - cmCTestLog(this->CTest, ERROR_MESSAGE, "Cannot create resulting XML file: " - << ostr.str() << std::endl); + cmCTestLog(this->CTest, ERROR_MESSAGE, + "Cannot create resulting XML file: " << ostr.str() + << std::endl); return false; } this->CTest->AddSubmitFile(part, ostr.str().c_str()); diff --git a/Source/CTest/cmCTestGenericHandler.h b/Source/CTest/cmCTestGenericHandler.h index e881252c9..cf91b4fa6 100644 --- a/Source/CTest/cmCTestGenericHandler.h +++ b/Source/CTest/cmCTestGenericHandler.h @@ -25,7 +25,7 @@ class cmCTestGenericHandler { public: /** - * If verbose then more informaiton is printed out + * If verbose then more information is printed out */ void SetVerbose(bool val) { diff --git a/Source/CTest/cmCTestHG.cxx b/Source/CTest/cmCTestHG.cxx index 525dacc1d..c3c5da460 100644 --- a/Source/CTest/cmCTestHG.cxx +++ b/Source/CTest/cmCTestHG.cxx @@ -107,8 +107,9 @@ std::string cmCTestHG::GetWorkingRevision() bool cmCTestHG::NoteOldRevision() { this->OldRevision = this->GetWorkingRevision(); - cmCTestLog(this->CTest, HANDLER_OUTPUT, " Old revision of repository is: " - << this->OldRevision << "\n"); + cmCTestLog(this->CTest, HANDLER_OUTPUT, + " Old revision of repository is: " << this->OldRevision + << "\n"); this->PriorRev.Rev = this->OldRevision; return true; } @@ -116,8 +117,9 @@ bool cmCTestHG::NoteOldRevision() bool cmCTestHG::NoteNewRevision() { this->NewRevision = this->GetWorkingRevision(); - cmCTestLog(this->CTest, HANDLER_OUTPUT, " New revision of repository is: " - << this->NewRevision << "\n"); + cmCTestLog(this->CTest, HANDLER_OUTPUT, + " New revision of repository is: " << this->NewRevision + << "\n"); return true; } @@ -157,8 +159,9 @@ bool cmCTestHG::UpdateImpl() return this->RunUpdateCommand(&hg_update[0], &out, &err); } -class cmCTestHG::LogParser : public cmCTestVC::OutputLogger, - private cmXMLParser +class cmCTestHG::LogParser + : public cmCTestVC::OutputLogger + , private cmXMLParser { public: LogParser(cmCTestHG* hg, const char* prefix) @@ -168,6 +171,7 @@ public: this->InitializeParser(); } ~LogParser() override { this->CleanupParser(); } + private: cmCTestHG* HG; diff --git a/Source/CTest/cmCTestHandlerCommand.cxx b/Source/CTest/cmCTestHandlerCommand.cxx index 5a7baf545..8863dc847 100644 --- a/Source/CTest/cmCTestHandlerCommand.cxx +++ b/Source/CTest/cmCTestHandlerCommand.cxx @@ -9,6 +9,7 @@ #include "cmWorkingDirectory.h" #include "cmake.h" +#include <cstring> #include <sstream> #include <stdlib.h> @@ -157,13 +158,14 @@ bool cmCTestHandlerCommand::InitialPass(std::vector<std::string> const& args, "BuildDirectory", cmSystemTools::CollapseFullPath(bdir).c_str(), this->Quiet); } else { - cmCTestLog(this->CTest, ERROR_MESSAGE, "CTEST_BINARY_DIRECTORY not set" - << std::endl;); + cmCTestLog(this->CTest, ERROR_MESSAGE, + "CTEST_BINARY_DIRECTORY not set" << std::endl;); } } if (this->Values[ct_SOURCE]) { - cmCTestLog(this->CTest, DEBUG, "Set source directory to: " - << this->Values[ct_SOURCE] << std::endl); + cmCTestLog(this->CTest, DEBUG, + "Set source directory to: " << this->Values[ct_SOURCE] + << std::endl); this->CTest->SetCTestConfiguration( "SourceDirectory", cmSystemTools::CollapseFullPath(this->Values[ct_SOURCE]).c_str(), @@ -185,8 +187,9 @@ bool cmCTestHandlerCommand::InitialPass(std::vector<std::string> const& args, cmCTestLog(this->CTest, DEBUG, "Initialize handler" << std::endl;); cmCTestGenericHandler* handler = this->InitializeHandler(); if (!handler) { - cmCTestLog(this->CTest, ERROR_MESSAGE, "Cannot instantiate test handler " - << this->GetName() << std::endl); + cmCTestLog(this->CTest, ERROR_MESSAGE, + "Cannot instantiate test handler " << this->GetName() + << std::endl); if (capureCMakeError) { this->Makefile->AddDefinition(this->Values[ct_CAPTURE_CMAKE_ERROR], "-1"); @@ -218,6 +221,21 @@ bool cmCTestHandlerCommand::InitialPass(std::vector<std::string> const& args, } cmWorkingDirectory workdir( this->CTest->GetCTestConfiguration("BuildDirectory")); + if (workdir.Failed()) { + this->SetError("failed to change directory to " + + this->CTest->GetCTestConfiguration("BuildDirectory") + + " : " + std::strerror(workdir.GetLastResult())); + if (capureCMakeError) { + this->Makefile->AddDefinition(this->Values[ct_CAPTURE_CMAKE_ERROR], + "-1"); + cmCTestLog(this->CTest, ERROR_MESSAGE, + this->GetName() << " " << this->GetError() << "\n"); + // return success because failure is recorded in CAPTURE_CMAKE_ERROR + return true; + } + return false; + } + int res = handler->ProcessHandler(); if (this->Values[ct_RETURN_VALUE] && *this->Values[ct_RETURN_VALUE]) { std::ostringstream str; @@ -287,8 +305,8 @@ bool cmCTestHandlerCommand::CheckArgumentValue(std::string const& arg) return true; } this->Values[k] = arg.c_str(); - cmCTestLog(this->CTest, DEBUG, "Set " << this->Arguments[k] << " to " - << arg << "\n"); + cmCTestLog(this->CTest, DEBUG, + "Set " << this->Arguments[k] << " to " << arg << "\n"); return true; } return false; diff --git a/Source/CTest/cmCTestLaunch.cxx b/Source/CTest/cmCTestLaunch.cxx index 30f76a927..0bffde3dc 100644 --- a/Source/CTest/cmCTestLaunch.cxx +++ b/Source/CTest/cmCTestLaunch.cxx @@ -21,9 +21,9 @@ #include "cmake.h" #ifdef _WIN32 -#include <fcntl.h> // for _O_BINARY -#include <io.h> // for _setmode -#include <stdio.h> // for std{out,err} and fileno +# include <fcntl.h> // for _O_BINARY +# include <io.h> // for _setmode +# include <stdio.h> // for std{out,err} and fileno #endif cmCTestLaunch::cmCTestLaunch(int argc, const char* const* argv) @@ -347,28 +347,27 @@ void cmCTestLaunch::WriteXML() // Use cmGeneratedFileStream to atomically create the report file. cmGeneratedFileStream fxml(logXML.c_str()); cmXMLWriter xml(fxml, 2); - xml.StartElement("Failure"); - xml.Attribute("type", this->IsError() ? "Error" : "Warning"); - this->WriteXMLAction(xml); - this->WriteXMLCommand(xml); - this->WriteXMLResult(xml); - this->WriteXMLLabels(xml); - xml.EndElement(); // Failure + cmXMLElement e2(xml, "Failure"); + e2.Attribute("type", this->IsError() ? "Error" : "Warning"); + this->WriteXMLAction(e2); + this->WriteXMLCommand(e2); + this->WriteXMLResult(e2); + this->WriteXMLLabels(e2); } -void cmCTestLaunch::WriteXMLAction(cmXMLWriter& xml) +void cmCTestLaunch::WriteXMLAction(cmXMLElement& e2) { - xml.Comment("Meta-information about the build action"); - xml.StartElement("Action"); + e2.Comment("Meta-information about the build action"); + cmXMLElement e3(e2, "Action"); // TargetName if (!this->OptionTargetName.empty()) { - xml.Element("TargetName", this->OptionTargetName); + e3.Element("TargetName", this->OptionTargetName); } // Language if (!this->OptionLanguage.empty()) { - xml.Element("Language", this->OptionLanguage); + e3.Element("Language", this->OptionLanguage); } // SourceFile @@ -383,12 +382,12 @@ void cmCTestLaunch::WriteXMLAction(cmXMLWriter& xml) source = cmSystemTools::RelativePath(this->SourceDir, source); } - xml.Element("SourceFile", source); + e3.Element("SourceFile", source); } // OutputFile if (!this->OptionOutput.empty()) { - xml.Element("OutputFile", this->OptionOutput); + e3.Element("OutputFile", this->OptionOutput); } // OutputType @@ -407,97 +406,88 @@ void cmCTestLaunch::WriteXMLAction(cmXMLWriter& xml) outputType = "object file"; } if (outputType) { - xml.Element("OutputType", outputType); + e3.Element("OutputType", outputType); } - - xml.EndElement(); // Action } -void cmCTestLaunch::WriteXMLCommand(cmXMLWriter& xml) +void cmCTestLaunch::WriteXMLCommand(cmXMLElement& e2) { - xml.Comment("Details of command"); - xml.StartElement("Command"); + e2.Comment("Details of command"); + cmXMLElement e3(e2, "Command"); if (!this->CWD.empty()) { - xml.Element("WorkingDirectory", this->CWD); + e3.Element("WorkingDirectory", this->CWD); } for (std::string const& realArg : this->RealArgs) { - xml.Element("Argument", realArg); + e3.Element("Argument", realArg); } - xml.EndElement(); // Command } -void cmCTestLaunch::WriteXMLResult(cmXMLWriter& xml) +void cmCTestLaunch::WriteXMLResult(cmXMLElement& e2) { - xml.Comment("Result of command"); - xml.StartElement("Result"); + e2.Comment("Result of command"); + cmXMLElement e3(e2, "Result"); // StdOut - xml.StartElement("StdOut"); - this->DumpFileToXML(xml, this->LogOut); - xml.EndElement(); // StdOut + this->DumpFileToXML(e3, "StdOut", this->LogOut); // StdErr - xml.StartElement("StdErr"); - this->DumpFileToXML(xml, this->LogErr); - xml.EndElement(); // StdErr + this->DumpFileToXML(e3, "StdErr", this->LogErr); // ExitCondition - xml.StartElement("ExitCondition"); + cmXMLElement e4(e3, "ExitCondition"); cmsysProcess* cp = this->Process; switch (cmsysProcess_GetState(cp)) { case cmsysProcess_State_Starting: - xml.Content("No process has been executed"); + e4.Content("No process has been executed"); break; case cmsysProcess_State_Executing: - xml.Content("The process is still executing"); + e4.Content("The process is still executing"); break; case cmsysProcess_State_Disowned: - xml.Content("Disowned"); + e4.Content("Disowned"); break; case cmsysProcess_State_Killed: - xml.Content("Killed by parent"); + e4.Content("Killed by parent"); break; case cmsysProcess_State_Expired: - xml.Content("Killed when timeout expired"); + e4.Content("Killed when timeout expired"); break; case cmsysProcess_State_Exited: - xml.Content(this->ExitCode); + e4.Content(this->ExitCode); break; case cmsysProcess_State_Exception: - xml.Content("Terminated abnormally: "); - xml.Content(cmsysProcess_GetExceptionString(cp)); + e4.Content("Terminated abnormally: "); + e4.Content(cmsysProcess_GetExceptionString(cp)); break; case cmsysProcess_State_Error: - xml.Content("Error administrating child process: "); - xml.Content(cmsysProcess_GetErrorString(cp)); + e4.Content("Error administrating child process: "); + e4.Content(cmsysProcess_GetErrorString(cp)); break; - }; - xml.EndElement(); // ExitCondition - - xml.EndElement(); // Result + } } -void cmCTestLaunch::WriteXMLLabels(cmXMLWriter& xml) +void cmCTestLaunch::WriteXMLLabels(cmXMLElement& e2) { this->LoadLabels(); if (!this->Labels.empty()) { - xml.Comment("Interested parties"); - xml.StartElement("Labels"); + e2.Comment("Interested parties"); + cmXMLElement e3(e2, "Labels"); for (std::string const& label : this->Labels) { - xml.Element("Label", label); + e3.Element("Label", label); } - xml.EndElement(); // Labels } } -void cmCTestLaunch::DumpFileToXML(cmXMLWriter& xml, std::string const& fname) +void cmCTestLaunch::DumpFileToXML(cmXMLElement& e3, const char* tag, + std::string const& fname) { cmsys::ifstream fin(fname.c_str(), std::ios::in | std::ios::binary); std::string line; const char* sep = ""; + cmXMLElement e4(e3, tag); while (cmSystemTools::GetLineFromStream(fin, line)) { if (MatchesFilterPrefix(line)) { continue; @@ -507,8 +497,8 @@ void cmCTestLaunch::DumpFileToXML(cmXMLWriter& xml, std::string const& fname) } else if (this->Match(line, this->RegexWarning)) { line = "[CTest: warning matched] " + line; } - xml.Content(sep); - xml.Content(line); + e4.Content(sep); + e4.Content(line); sep = "\n"; } } diff --git a/Source/CTest/cmCTestLaunch.h b/Source/CTest/cmCTestLaunch.h index 29986ff60..debbe59d7 100644 --- a/Source/CTest/cmCTestLaunch.h +++ b/Source/CTest/cmCTestLaunch.h @@ -10,7 +10,7 @@ #include <string> #include <vector> -class cmXMLWriter; +class cmXMLElement; /** \class cmCTestLaunch * \brief Launcher for make rules to report results for ctest @@ -89,11 +89,11 @@ private: // Methods to generate the xml fragment. void WriteXML(); - void WriteXMLAction(cmXMLWriter& xml); - void WriteXMLCommand(cmXMLWriter& xml); - void WriteXMLResult(cmXMLWriter& xml); - void WriteXMLLabels(cmXMLWriter& xml); - void DumpFileToXML(cmXMLWriter& xml, std::string const& fname); + void WriteXMLAction(cmXMLElement&); + void WriteXMLCommand(cmXMLElement&); + void WriteXMLResult(cmXMLElement&); + void WriteXMLLabels(cmXMLElement&); + void DumpFileToXML(cmXMLElement&, const char* tag, std::string const& fname); // Configuration void LoadConfig(); diff --git a/Source/CTest/cmCTestMemCheckHandler.cxx b/Source/CTest/cmCTestMemCheckHandler.cxx index cb1d947c8..04d1839ab 100644 --- a/Source/CTest/cmCTestMemCheckHandler.cxx +++ b/Source/CTest/cmCTestMemCheckHandler.cxx @@ -37,8 +37,9 @@ static CatToErrorType cmCTestMemCheckBoundsChecker[] = { static void xmlReportError(int line, const char* msg, void* data) { cmCTest* ctest = static_cast<cmCTest*>(data); - cmCTestLog(ctest, ERROR_MESSAGE, "Error parsing XML in stream at line " - << line << ": " << msg << std::endl); + cmCTestLog(ctest, ERROR_MESSAGE, + "Error parsing XML in stream at line " << line << ": " << msg + << std::endl); } // parse the xml file containing the results of last BoundsChecker run @@ -366,10 +367,10 @@ void cmCTestMemCheckHandler::GenerateDartOutput(cmXMLWriter& xml) const int maxTestNameWidth = this->CTest->GetMaxTestNameWidth(); std::string outname = result.Name + " "; outname.resize(maxTestNameWidth + 4, '.'); - cmCTestOptionalLog(this->CTest, HANDLER_OUTPUT, cc + 1 - << "/" << total << " MemCheck: #" - << result.TestCount << ": " << outname - << " Defects: " << memoryErrors << std::endl, + cmCTestOptionalLog(this->CTest, HANDLER_OUTPUT, + cc + 1 << "/" << total << " MemCheck: #" + << result.TestCount << ": " << outname + << " Defects: " << memoryErrors << std::endl, this->Quiet); } xml.StartElement("Log"); @@ -773,8 +774,9 @@ bool cmCTestMemCheckHandler::ProcessMemCheckPurifyOutput( } } if (cc == this->ResultStrings.size()) { - cmCTestLog(this->CTest, ERROR_MESSAGE, "Unknown Purify memory fault: " - << pfW.match(1) << std::endl); + cmCTestLog(this->CTest, ERROR_MESSAGE, + "Unknown Purify memory fault: " << pfW.match(1) + << std::endl); ostr << "*** Unknown Purify memory fault: " << pfW.match(1) << std::endl; } @@ -918,11 +920,12 @@ bool cmCTestMemCheckHandler::ProcessMemCheckValgrindOutput( break; // stop the copy of output if we are full } } - cmCTestOptionalLog( - this->CTest, DEBUG, "End test (elapsed: " - << cmDurationTo<unsigned int>(std::chrono::steady_clock::now() - sttime) - << "s)" << std::endl, - this->Quiet); + cmCTestOptionalLog(this->CTest, DEBUG, + "End test (elapsed: " + << cmDurationTo<unsigned int>( + std::chrono::steady_clock::now() - sttime) + << "s)" << std::endl, + this->Quiet); log = ostr.str(); this->DefectCount += defects; return defects == 0; @@ -963,11 +966,12 @@ bool cmCTestMemCheckHandler::ProcessMemCheckBoundsCheckerOutput( results[err]++; defects++; } - cmCTestOptionalLog( - this->CTest, DEBUG, "End test (elapsed: " - << cmDurationTo<unsigned int>(std::chrono::steady_clock::now() - sttime) - << "s)" << std::endl, - this->Quiet); + cmCTestOptionalLog(this->CTest, DEBUG, + "End test (elapsed: " + << cmDurationTo<unsigned int>( + std::chrono::steady_clock::now() - sttime) + << "s)" << std::endl, + this->Quiet); if (defects) { // only put the output of Bounds Checker if there were // errors or leaks detected diff --git a/Source/CTest/cmCTestMemCheckHandler.h b/Source/CTest/cmCTestMemCheckHandler.h index 921829429..8880dac9a 100644 --- a/Source/CTest/cmCTestMemCheckHandler.h +++ b/Source/CTest/cmCTestMemCheckHandler.h @@ -127,7 +127,7 @@ private: //! Parse Valgrind/Purify/Bounds Checker result out of the output // string. After running, log holds the output and results hold the - // different memmory errors. + // different memory errors. bool ProcessMemCheckOutput(const std::string& str, std::string& log, std::vector<int>& results); bool ProcessMemCheckValgrindOutput(const std::string& str, std::string& log, diff --git a/Source/CTest/cmCTestMultiProcessHandler.cxx b/Source/CTest/cmCTestMultiProcessHandler.cxx index 50c2d86d7..dcef8a037 100644 --- a/Source/CTest/cmCTestMultiProcessHandler.cxx +++ b/Source/CTest/cmCTestMultiProcessHandler.cxx @@ -2,6 +2,7 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmCTestMultiProcessHandler.h" +#include "cmAffinity.h" #include "cmCTest.h" #include "cmCTestRunTest.h" #include "cmCTestScriptHandler.h" @@ -19,6 +20,7 @@ #include <algorithm> #include <chrono> +#include <cstring> #include <iomanip> #include <list> #include <math.h> @@ -53,6 +55,8 @@ cmCTestMultiProcessHandler::cmCTestMultiProcessHandler() this->TestLoad = 0; this->Completed = 0; this->RunningCount = 0; + this->ProcessorsAvailable = cmAffinity::GetProcessorsAvailable(); + this->HaveAffinity = this->ProcessorsAvailable.size(); this->StopTimePassed = false; this->HasCycles = false; this->SerialTestRunning = false; @@ -120,13 +124,29 @@ bool cmCTestMultiProcessHandler::StartTestProcess(int test) std::chrono::system_clock::time_point stop_time = this->CTest->GetStopTime(); if (stop_time != std::chrono::system_clock::time_point() && stop_time <= std::chrono::system_clock::now()) { - cmCTestLog(this->CTest, ERROR_MESSAGE, "The stop time has been passed. " - "Stopping all tests." + cmCTestLog(this->CTest, ERROR_MESSAGE, + "The stop time has been passed. " + "Stopping all tests." << std::endl); this->StopTimePassed = true; return false; } + if (this->HaveAffinity && this->Properties[test]->WantAffinity) { + size_t needProcessors = this->GetProcessorsUsed(test); + if (needProcessors > this->ProcessorsAvailable.size()) { + return false; + } + std::vector<size_t> affinity; + affinity.reserve(needProcessors); + for (size_t i = 0; i < needProcessors; ++i) { + auto p = this->ProcessorsAvailable.begin(); + affinity.push_back(*p); + this->ProcessorsAvailable.erase(p); + } + this->Properties[test]->Affinity = std::move(affinity); + } + cmCTestOptionalLog(this->CTest, HANDLER_VERBOSE_OUTPUT, "test " << test << "\n", this->Quiet); this->TestRunningMap[test] = true; // mark the test as running @@ -151,13 +171,19 @@ bool cmCTestMultiProcessHandler::StartTestProcess(int test) } } - cmWorkingDirectory workdir(this->Properties[test]->Directory); - - // Lock the resources we'll be using + // Always lock the resources we'll be using, even if we fail to set the + // working directory because FinishTestProcess() will try to unlock them this->LockResources(test); - if (testRun->StartTest(this->Total)) { - return true; + cmWorkingDirectory workdir(this->Properties[test]->Directory); + if (workdir.Failed()) { + testRun->StartFailure("Failed to change working directory to " + + this->Properties[test]->Directory + " : " + + std::strerror(workdir.GetLastResult())); + } else { + if (testRun->StartTest(this->Total)) { + return true; + } } this->FinishTestProcess(testRun, false); @@ -200,6 +226,11 @@ inline size_t cmCTestMultiProcessHandler::GetProcessorsUsed(int test) if (processors > this->ParallelLevel) { processors = this->ParallelLevel; } + // Cap tests that want affinity to the maximum affinity available. + if (this->HaveAffinity && processors > this->HaveAffinity && + this->Properties[test]->WantAffinity) { + processors = this->HaveAffinity; + } return processors; } @@ -300,10 +331,10 @@ void cmCTestMultiProcessHandler::StartNextTests() bool testLoadOk = true; if (this->TestLoad > 0) { if (processors <= spareLoad) { - cmCTestLog(this->CTest, DEBUG, "OK to run " - << GetName(test) << ", it requires " << processors - << " procs & system load is: " << systemLoad - << std::endl); + cmCTestLog(this->CTest, DEBUG, + "OK to run " << GetName(test) << ", it requires " + << processors << " procs & system load is: " + << systemLoad << std::endl); allTestsFailedTestLoadCheck = false; } else { testLoadOk = false; @@ -398,6 +429,11 @@ void cmCTestMultiProcessHandler::FinishTestProcess(cmCTestRunTest* runner, this->UnlockResources(test); this->RunningCount -= GetProcessorsUsed(test); + for (auto p : properties->Affinity) { + this->ProcessorsAvailable.insert(p); + } + properties->Affinity.clear(); + delete runner; if (started) { this->StartNextTests(); @@ -666,6 +702,8 @@ void cmCTestMultiProcessHandler::PrintTestList() count++; cmCTestTestHandler::cmCTestTestProperties& p = *it.second; + // Don't worry if this fails, we are only showing the test list, not + // running the tests cmWorkingDirectory workdir(p.Directory); cmCTestRunTest testRun(*this); @@ -675,8 +713,8 @@ void cmCTestMultiProcessHandler::PrintTestList() if (!p.Labels.empty()) // print the labels { - cmCTestOptionalLog(this->CTest, HANDLER_VERBOSE_OUTPUT, "Labels:", - this->Quiet); + cmCTestOptionalLog(this->CTest, HANDLER_VERBOSE_OUTPUT, + "Labels:", this->Quiet); } for (std::string const& label : p.Labels) { cmCTestOptionalLog(this->CTest, HANDLER_VERBOSE_OUTPUT, " " << label, @@ -710,7 +748,8 @@ void cmCTestMultiProcessHandler::PrintTestList() cmCTestOptionalLog(this->CTest, HANDLER_OUTPUT, std::endl, this->Quiet); } - cmCTestOptionalLog(this->CTest, HANDLER_OUTPUT, std::endl + cmCTestOptionalLog(this->CTest, HANDLER_OUTPUT, + std::endl << "Total Tests: " << this->Total << std::endl, this->Quiet); } diff --git a/Source/CTest/cmCTestMultiProcessHandler.h b/Source/CTest/cmCTestMultiProcessHandler.h index 7837ff910..203170e13 100644 --- a/Source/CTest/cmCTestMultiProcessHandler.h +++ b/Source/CTest/cmCTestMultiProcessHandler.h @@ -74,6 +74,7 @@ public: cmCTestTestHandler* GetTestHandler() { return this->TestHandler; } void SetQuiet(bool b) { this->Quiet = b; } + protected: // Start the next test or tests as many as are allowed by // ParallelLevel @@ -119,6 +120,8 @@ protected: // Number of tests that are complete size_t Completed; size_t RunningCount; + std::set<size_t> ProcessorsAvailable; + size_t HaveAffinity; bool StopTimePassed; // list of test properties (indices concurrent to the test map) PropertiesMap Properties; diff --git a/Source/CTest/cmCTestP4.cxx b/Source/CTest/cmCTestP4.cxx index fdf893243..511dbd2ec 100644 --- a/Source/CTest/cmCTestP4.cxx +++ b/Source/CTest/cmCTestP4.cxx @@ -372,8 +372,9 @@ bool cmCTestP4::NoteOldRevision() { this->OldRevision = this->GetWorkingRevision(); - cmCTestLog(this->CTest, HANDLER_OUTPUT, " Old revision of repository is: " - << this->OldRevision << "\n"); + cmCTestLog(this->CTest, HANDLER_OUTPUT, + " Old revision of repository is: " << this->OldRevision + << "\n"); this->PriorRev.Rev = this->OldRevision; return true; } @@ -382,8 +383,9 @@ bool cmCTestP4::NoteNewRevision() { this->NewRevision = this->GetWorkingRevision(); - cmCTestLog(this->CTest, HANDLER_OUTPUT, " New revision of repository is: " - << this->NewRevision << "\n"); + cmCTestLog(this->CTest, HANDLER_OUTPUT, + " New revision of repository is: " << this->NewRevision + << "\n"); return true; } @@ -398,7 +400,8 @@ bool cmCTestP4::LoadRevisions() // If any revision is unknown it means we couldn't contact the server. // Do not process updates if (this->OldRevision == "<unknown>" || this->NewRevision == "<unknown>") { - cmCTestLog(this->CTest, HANDLER_OUTPUT, " At least one of the revisions " + cmCTestLog(this->CTest, HANDLER_OUTPUT, + " At least one of the revisions " << "is unknown. No repository changes will be reported.\n"); return false; } diff --git a/Source/CTest/cmCTestRunTest.cxx b/Source/CTest/cmCTestRunTest.cxx index 30ad38ca1..927797af0 100644 --- a/Source/CTest/cmCTestRunTest.cxx +++ b/Source/CTest/cmCTestRunTest.cxx @@ -14,6 +14,7 @@ #include "cmsys/RegularExpression.hxx" #include <chrono> #include <cmAlgorithms.h> +#include <cstring> #include <iomanip> #include <ratio> #include <sstream> @@ -40,8 +41,8 @@ cmCTestRunTest::cmCTestRunTest(cmCTestMultiProcessHandler& multiHandler) void cmCTestRunTest::CheckOutput(std::string const& line) { - cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT, this->GetIndex() - << ": " << line << std::endl); + cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT, + this->GetIndex() << ": " << line << std::endl); this->ProcessOutput += line; this->ProcessOutput += "\n"; @@ -49,7 +50,8 @@ void cmCTestRunTest::CheckOutput(std::string const& line) if (!this->TestProperties->TimeoutRegularExpressions.empty()) { for (auto& reg : this->TestProperties->TimeoutRegularExpressions) { if (reg.first.find(this->ProcessOutput.c_str())) { - cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT, this->GetIndex() + cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT, + this->GetIndex() << ": " << "Test timeout changed to " << std::chrono::duration_cast<std::chrono::seconds>( @@ -248,11 +250,7 @@ bool cmCTestRunTest::EndTest(size_t completed, size_t total, bool started) *this->TestHandler->LogFile << "Test time = " << buf << std::endl; } - // Set the working directory to the tests directory to process Dart files. - { - cmWorkingDirectory workdir(this->TestProperties->Directory); - this->DartProcessing(); - } + this->DartProcessing(); // if this is doing MemCheck then all the output needs to be put into // Output since that is what is parsed by cmCTestMemCheckHandler @@ -338,6 +336,13 @@ bool cmCTestRunTest::StartAgain() this->RunAgain = false; // reset // change to tests directory cmWorkingDirectory workdir(this->TestProperties->Directory); + if (workdir.Failed()) { + this->StartFailure("Failed to change working directory to " + + this->TestProperties->Directory + " : " + + std::strerror(workdir.GetLastResult())); + return true; + } + this->StartTest(this->TotalNumberOfTests); return true; } @@ -376,21 +381,53 @@ void cmCTestRunTest::MemCheckPostProcess() if (!this->TestHandler->MemCheck) { return; } - cmCTestOptionalLog(this->CTest, HANDLER_VERBOSE_OUTPUT, this->Index - << ": process test output now: " - << this->TestProperties->Name << " " - << this->TestResult.Name << std::endl, + cmCTestOptionalLog(this->CTest, HANDLER_VERBOSE_OUTPUT, + this->Index << ": process test output now: " + << this->TestProperties->Name << " " + << this->TestResult.Name << std::endl, this->TestHandler->GetQuiet()); cmCTestMemCheckHandler* handler = static_cast<cmCTestMemCheckHandler*>(this->TestHandler); handler->PostProcessTest(this->TestResult, this->Index); } +void cmCTestRunTest::StartFailure(std::string const& output) +{ + // Still need to log the Start message so the test summary records our + // attempt to start this test + cmCTestLog(this->CTest, HANDLER_OUTPUT, + std::setw(2 * getNumWidth(this->TotalNumberOfTests) + 8) + << "Start " + << std::setw(getNumWidth(this->TestHandler->GetMaxIndex())) + << this->TestProperties->Index << ": " + << this->TestProperties->Name << std::endl); + + this->ProcessOutput.clear(); + if (!output.empty()) { + *this->TestHandler->LogFile << output << std::endl; + cmCTestLog(this->CTest, ERROR_MESSAGE, output << std::endl); + } + + this->TestResult.Properties = this->TestProperties; + this->TestResult.ExecutionTime = cmDuration::zero(); + this->TestResult.CompressOutput = false; + this->TestResult.ReturnValue = -1; + this->TestResult.CompletionStatus = "Failed to start"; + this->TestResult.Status = cmCTestTestHandler::NOT_RUN; + this->TestResult.TestCount = this->TestProperties->Index; + this->TestResult.Name = this->TestProperties->Name; + this->TestResult.Path = this->TestProperties->Directory; + this->TestResult.Output = output; + this->TestResult.FullCommandLine.clear(); + this->TestProcess = cm::make_unique<cmProcess>(*this); +} + // Starts the execution of a test. Returns once it has started bool cmCTestRunTest::StartTest(size_t total) { this->TotalNumberOfTests = total; // save for rerun case - cmCTestLog(this->CTest, HANDLER_OUTPUT, std::setw(2 * getNumWidth(total) + 8) + cmCTestLog(this->CTest, HANDLER_OUTPUT, + std::setw(2 * getNumWidth(total) + 8) << "Start " << std::setw(getNumWidth(this->TestHandler->GetMaxIndex())) << this->TestProperties->Index << ": " @@ -515,12 +552,13 @@ bool cmCTestRunTest::StartTest(size_t total) } return this->ForkProcess(timeout, this->TestProperties->ExplicitTimeout, - &this->TestProperties->Environment); + &this->TestProperties->Environment, + &this->TestProperties->Affinity); } void cmCTestRunTest::ComputeArguments() { - this->Arguments.clear(); // reset becaue this might be a rerun + this->Arguments.clear(); // reset because this might be a rerun std::vector<std::string>::const_iterator j = this->TestProperties->Args.begin(); ++j; // skip test name @@ -556,20 +594,21 @@ void cmCTestRunTest::ComputeArguments() this->TestResult.FullCommandLine = testCommand; // Print the test command in verbose mode - cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT, std::endl + cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT, + std::endl << this->Index << ": " << (this->TestHandler->MemCheck ? "MemCheck" : "Test") << " command: " << testCommand << std::endl); // Print any test-specific env vars in verbose mode if (!this->TestProperties->Environment.empty()) { - cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT, this->Index - << ": " - << "Environment variables: " << std::endl); + cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT, + this->Index << ": " + << "Environment variables: " << std::endl); } for (std::string const& env : this->TestProperties->Environment) { - cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT, this->Index << ": " << env - << std::endl); + cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT, + this->Index << ": " << env << std::endl); } } @@ -591,7 +630,8 @@ void cmCTestRunTest::DartProcessing() } bool cmCTestRunTest::ForkProcess(cmDuration testTimeOut, bool explicitTimeout, - std::vector<std::string>* environment) + std::vector<std::string>* environment, + std::vector<size_t>* affinity) { this->TestProcess = cm::make_unique<cmProcess>(*this); this->TestProcess->SetId(this->Index); @@ -621,10 +661,11 @@ bool cmCTestRunTest::ForkProcess(cmDuration testTimeOut, bool explicitTimeout, if (testTimeOut == cmDuration::zero() && explicitTimeout) { timeout = cmDuration::zero(); } - cmCTestOptionalLog(this->CTest, HANDLER_VERBOSE_OUTPUT, this->Index - << ": " - << "Test timeout computed to be: " - << cmDurationTo<unsigned int>(timeout) << "\n", + cmCTestOptionalLog(this->CTest, HANDLER_VERBOSE_OUTPUT, + this->Index << ": " + << "Test timeout computed to be: " + << cmDurationTo<unsigned int>(timeout) + << "\n", this->TestHandler->GetQuiet()); this->TestProcess->SetTimeout(timeout); @@ -637,7 +678,8 @@ bool cmCTestRunTest::ForkProcess(cmDuration testTimeOut, bool explicitTimeout, cmSystemTools::AppendEnv(*environment); } - return this->TestProcess->StartProcess(this->MultiTestHandler.Loop); + return this->TestProcess->StartProcess(this->MultiTestHandler.Loop, + affinity); } void cmCTestRunTest::WriteLogOutputTop(size_t completed, size_t total) @@ -649,20 +691,20 @@ void cmCTestRunTest::WriteLogOutputTop(size_t completed, size_t total) // got for run until pass. Trick is when this is called we don't // yet know if we are passing or failing. if (this->NumberOfRunsLeft == 1) { - cmCTestLog(this->CTest, HANDLER_OUTPUT, std::setw(getNumWidth(total)) - << completed << "/"); - cmCTestLog(this->CTest, HANDLER_OUTPUT, std::setw(getNumWidth(total)) - << total << " "); + cmCTestLog(this->CTest, HANDLER_OUTPUT, + std::setw(getNumWidth(total)) << completed << "/"); + cmCTestLog(this->CTest, HANDLER_OUTPUT, + std::setw(getNumWidth(total)) << total << " "); } // if this is one of several runs of a test just print blank space // to keep things neat else { - cmCTestLog(this->CTest, HANDLER_OUTPUT, std::setw(getNumWidth(total)) - << " " - << " "); - cmCTestLog(this->CTest, HANDLER_OUTPUT, std::setw(getNumWidth(total)) - << " " - << " "); + cmCTestLog(this->CTest, HANDLER_OUTPUT, + std::setw(getNumWidth(total)) << " " + << " "); + cmCTestLog(this->CTest, HANDLER_OUTPUT, + std::setw(getNumWidth(total)) << " " + << " "); } if (this->TestHandler->MemCheck) { @@ -708,8 +750,8 @@ void cmCTestRunTest::WriteLogOutputTop(size_t completed, size_t total) << std::endl; cmCTestLog(this->CTest, HANDLER_OUTPUT, outname.c_str()); - cmCTestLog(this->CTest, DEBUG, "Testing " << this->TestProperties->Name - << " ... "); + cmCTestLog(this->CTest, DEBUG, + "Testing " << this->TestProperties->Name << " ... "); } void cmCTestRunTest::FinalizeTest() diff --git a/Source/CTest/cmCTestRunTest.h b/Source/CTest/cmCTestRunTest.h index 4d573572f..3b1d674da 100644 --- a/Source/CTest/cmCTestRunTest.h +++ b/Source/CTest/cmCTestRunTest.h @@ -74,6 +74,8 @@ public: bool StartAgain(); + void StartFailure(std::string const& output); + cmCTest* GetCTest() const { return this->CTest; } void FinalizeTest(); @@ -83,7 +85,8 @@ private: void DartProcessing(); void ExeNotFound(std::string exe); bool ForkProcess(cmDuration testTimeOut, bool explicitTimeout, - std::vector<std::string>* environment); + std::vector<std::string>* environment, + std::vector<size_t>* affinity); void WriteLogOutputTop(size_t completed, size_t total); // Run post processing of the process output for MemCheck void MemCheckPostProcess(); diff --git a/Source/CTest/cmCTestSVN.cxx b/Source/CTest/cmCTestSVN.cxx index 73184fc05..58d9b3dcf 100644 --- a/Source/CTest/cmCTestSVN.cxx +++ b/Source/CTest/cmCTestSVN.cxx @@ -107,9 +107,10 @@ bool cmCTestSVN::NoteOldRevision() svninfo.OldRevision = this->LoadInfo(svninfo); this->Log << "Revision for repository '" << svninfo.LocalPath << "' before update: " << svninfo.OldRevision << "\n"; - cmCTestLog( - this->CTest, HANDLER_OUTPUT, " Old revision of external repository '" - << svninfo.LocalPath << "' is: " << svninfo.OldRevision << "\n"); + cmCTestLog(this->CTest, HANDLER_OUTPUT, + " Old revision of external repository '" + << svninfo.LocalPath << "' is: " << svninfo.OldRevision + << "\n"); } // Set the global old revision to the one of the root @@ -128,9 +129,10 @@ bool cmCTestSVN::NoteNewRevision() svninfo.NewRevision = this->LoadInfo(svninfo); this->Log << "Revision for repository '" << svninfo.LocalPath << "' after update: " << svninfo.NewRevision << "\n"; - cmCTestLog( - this->CTest, HANDLER_OUTPUT, " New revision of external repository '" - << svninfo.LocalPath << "' is: " << svninfo.NewRevision << "\n"); + cmCTestLog(this->CTest, HANDLER_OUTPUT, + " New revision of external repository '" + << svninfo.LocalPath << "' is: " << svninfo.NewRevision + << "\n"); // svninfo.Root = ""; // uncomment to test GuessBase this->Log << "Repository '" << svninfo.LocalPath @@ -290,8 +292,9 @@ bool cmCTestSVN::RunSVNCommand(std::vector<char const*> const& parameters, return RunChild(&args[0], out, err); } -class cmCTestSVN::LogParser : public cmCTestVC::OutputLogger, - private cmXMLParser +class cmCTestSVN::LogParser + : public cmCTestVC::OutputLogger + , private cmXMLParser { public: LogParser(cmCTestSVN* svn, const char* prefix, SVNInfo& svninfo) @@ -302,6 +305,7 @@ public: this->InitializeParser(); } ~LogParser() override { this->CleanupParser(); } + private: cmCTestSVN* SVN; cmCTestSVN::SVNInfo& SVNRepo; diff --git a/Source/CTest/cmCTestScriptHandler.cxx b/Source/CTest/cmCTestScriptHandler.cxx index e0bffd476..333c899be 100644 --- a/Source/CTest/cmCTestScriptHandler.cxx +++ b/Source/CTest/cmCTestScriptHandler.cxx @@ -39,9 +39,9 @@ #include "cmake.h" #ifdef _WIN32 -#include <windows.h> +# include <windows.h> #else -#include <unistd.h> +# include <unistd.h> #endif class cmExecutionStatus; @@ -184,8 +184,9 @@ int cmCTestScriptHandler::ExecuteScript(const std::string& total_script_arg) argv.push_back("-SR"); argv.push_back(total_script_arg.c_str()); - cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT, "Executable for CTest is: " - << cmSystemTools::GetCTestCommand() << "\n"); + cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT, + "Executable for CTest is: " << cmSystemTools::GetCTestCommand() + << "\n"); // now pass through all the other arguments std::vector<std::string>& initArgs = @@ -210,8 +211,8 @@ int cmCTestScriptHandler::ExecuteScript(const std::string& total_script_arg) int pipe = cmSystemTools::WaitForLine(cp, line, std::chrono::seconds(100), out, err); while (pipe != cmsysProcess_Pipe_None) { - cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT, "Output: " << line - << "\n"); + cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT, + "Output: " << line << "\n"); if (pipe == cmsysProcess_Pipe_STDERR) { cmCTestLog(this->CTest, ERROR_MESSAGE, line << "\n"); } else if (pipe == cmsysProcess_Pipe_STDOUT) { @@ -230,17 +231,19 @@ int cmCTestScriptHandler::ExecuteScript(const std::string& total_script_arg) retVal = cmsysProcess_GetExitValue(cp); } else if (result == cmsysProcess_State_Exception) { retVal = cmsysProcess_GetExitException(cp); - cmCTestLog(this->CTest, ERROR_MESSAGE, "\tThere was an exception: " + cmCTestLog(this->CTest, ERROR_MESSAGE, + "\tThere was an exception: " << cmsysProcess_GetExceptionString(cp) << " " << retVal << std::endl); failed = true; } else if (result == cmsysProcess_State_Expired) { - cmCTestLog(this->CTest, ERROR_MESSAGE, "\tThere was a timeout" - << std::endl); + cmCTestLog(this->CTest, ERROR_MESSAGE, + "\tThere was a timeout" << std::endl); failed = true; } else if (result == cmsysProcess_State_Error) { - cmCTestLog(this->CTest, ERROR_MESSAGE, "\tError executing ctest: " - << cmsysProcess_GetErrorString(cp) << std::endl); + cmCTestLog(this->CTest, ERROR_MESSAGE, + "\tError executing ctest: " << cmsysProcess_GetErrorString(cp) + << std::endl); failed = true; } cmsysProcess_Delete(cp); @@ -253,8 +256,8 @@ int cmCTestScriptHandler::ExecuteScript(const std::string& total_script_arg) message << arg << " "; } } - cmCTestLog(this->CTest, ERROR_MESSAGE, message.str() << argv[0] - << std::endl); + cmCTestLog(this->CTest, ERROR_MESSAGE, + message.str() << argv[0] << std::endl); return -1; } return retVal; @@ -372,8 +375,8 @@ int cmCTestScriptHandler::ReadInScript(const std::string& total_script_arg) this->Makefile->GetModulesFile("CTestScriptMode.cmake"); if (!this->Makefile->ReadListFile(systemFile.c_str()) || cmSystemTools::GetErrorOccuredFlag()) { - cmCTestLog(this->CTest, ERROR_MESSAGE, "Error in read:" << systemFile - << "\n"); + cmCTestLog(this->CTest, ERROR_MESSAGE, + "Error in read:" << systemFile << "\n"); return 2; } @@ -527,7 +530,7 @@ int cmCTestScriptHandler::RunConfigurationScript( return result; } - // only run the curent script if we should + // only run the current script if we should if (this->Makefile && this->Makefile->IsOn("CTEST_RUN_CURRENT_SCRIPT") && this->ShouldRunCurrentScript) { return this->RunCurrentScript(); diff --git a/Source/CTest/cmCTestStartCommand.cxx b/Source/CTest/cmCTestStartCommand.cxx index 38ee62308..3911540f6 100644 --- a/Source/CTest/cmCTestStartCommand.cxx +++ b/Source/CTest/cmCTestStartCommand.cxx @@ -28,41 +28,41 @@ bool cmCTestStartCommand::InitialPass(std::vector<std::string> const& args, } size_t cnt = 0; - const char* smodel = args[cnt].c_str(); + const char* smodel = nullptr; const char* src_dir = nullptr; const char* bld_dir = nullptr; - cnt++; - - this->CTest->SetSpecificTrack(nullptr); - if (cnt < args.size() - 1) { + while (cnt < args.size()) { if (args[cnt] == "TRACK") { cnt++; + if (cnt >= args.size() || args[cnt] == "APPEND" || + args[cnt] == "QUIET") { + this->SetError("TRACK argument missing track name"); + return false; + } this->CTest->SetSpecificTrack(args[cnt].c_str()); cnt++; - } - } - - if (cnt < args.size()) { - if (args[cnt] == "APPEND") { + } else if (args[cnt] == "APPEND") { cnt++; this->CreateNewTag = false; - } - } - if (cnt < args.size()) { - if (args[cnt] == "QUIET") { + } else if (args[cnt] == "QUIET") { cnt++; this->Quiet = true; - } - } - - if (cnt < args.size()) { - src_dir = args[cnt].c_str(); - cnt++; - if (cnt < args.size()) { + } else if (!smodel) { + smodel = args[cnt].c_str(); + cnt++; + } else if (!src_dir) { + src_dir = args[cnt].c_str(); + cnt++; + } else if (!bld_dir) { bld_dir = args[cnt].c_str(); + cnt++; + } else { + this->SetError("Too many arguments"); + return false; } } + if (!src_dir) { src_dir = this->Makefile->GetDefinition("CTEST_SOURCE_DIRECTORY"); } @@ -79,6 +79,11 @@ bool cmCTestStartCommand::InitialPass(std::vector<std::string> const& args, "as an argument or set CTEST_BINARY_DIRECTORY"); return false; } + if (!smodel && this->CreateNewTag) { + this->SetError("no test model specified and APPEND not specified. Specify " + "either a test model or the APPEND argument"); + return false; + } cmSystemTools::AddKeepPath(src_dir); cmSystemTools::AddKeepPath(bld_dir); @@ -92,11 +97,22 @@ bool cmCTestStartCommand::InitialPass(std::vector<std::string> const& args, this->CTest->SetCTestConfiguration("BuildDirectory", binaryDir.c_str(), this->Quiet); - cmCTestOptionalLog(this->CTest, HANDLER_OUTPUT, "Run dashboard with model " - << smodel << std::endl - << " Source directory: " << src_dir << std::endl - << " Build directory: " << bld_dir << std::endl, - this->Quiet); + if (smodel) { + cmCTestOptionalLog(this->CTest, HANDLER_OUTPUT, + "Run dashboard with model " + << smodel << std::endl + << " Source directory: " << src_dir << std::endl + << " Build directory: " << bld_dir << std::endl, + this->Quiet); + } else { + cmCTestOptionalLog(this->CTest, HANDLER_OUTPUT, + "Run dashboard with " + "to-be-determined model" + << std::endl + << " Source directory: " << src_dir << std::endl + << " Build directory: " << bld_dir << std::endl, + this->Quiet); + } const char* track = this->CTest->GetSpecificTrack(); if (track) { cmCTestOptionalLog(this->CTest, HANDLER_OUTPUT, @@ -128,7 +144,12 @@ bool cmCTestStartCommand::InitialPass(std::vector<std::string> const& args, this->CTest->SetRunCurrentScript(false); this->CTest->SetSuppressUpdatingCTestConfiguration(true); - int model = this->CTest->GetTestModelFromString(smodel); + int model; + if (smodel) { + model = this->CTest->GetTestModelFromString(smodel); + } else { + model = cmCTest::UNKNOWN; + } this->CTest->SetTestModel(model); this->CTest->SetProduceXML(true); diff --git a/Source/CTest/cmCTestSubmitHandler.cxx b/Source/CTest/cmCTestSubmitHandler.cxx index 08d05c8e8..4c2b75ee3 100644 --- a/Source/CTest/cmCTestSubmitHandler.cxx +++ b/Source/CTest/cmCTestSubmitHandler.cxx @@ -7,6 +7,7 @@ #include "cm_jsoncpp_value.h" #include "cmsys/Process.h" #include <chrono> +#include <cstring> #include <sstream> #include <stdio.h> #include <stdlib.h> @@ -27,9 +28,9 @@ #include "cmake.h" #if defined(CTEST_USE_XMLRPC) -#include "cmVersion.h" -#include "cm_sys_stat.h" -#include "cm_xmlrpc.h" +# include "cmVersion.h" +# include "cm_sys_stat.h" +# include "cm_xmlrpc.h" #endif #define SUBMIT_TIMEOUT_IN_SECONDS_DEFAULT 120 @@ -247,14 +248,16 @@ bool cmCTestSubmitHandler::SubmitUsingFTP(const std::string& localprefix, res = ::curl_easy_perform(curl); if (!chunk.empty()) { - cmCTestOptionalLog(this->CTest, DEBUG, "CURL output: [" + cmCTestOptionalLog(this->CTest, DEBUG, + "CURL output: [" << cmCTestLogWrite(&*chunk.begin(), chunk.size()) << "]" << std::endl, this->Quiet); } if (!chunkDebug.empty()) { cmCTestOptionalLog( - this->CTest, DEBUG, "CURL debug output: [" + this->CTest, DEBUG, + "CURL debug output: [" << cmCTestLogWrite(&*chunkDebug.begin(), chunkDebug.size()) << "]" << std::endl, this->Quiet); @@ -262,8 +265,9 @@ bool cmCTestSubmitHandler::SubmitUsingFTP(const std::string& localprefix, fclose(ftpfile); if (res) { - cmCTestLog(this->CTest, ERROR_MESSAGE, " Error when uploading file: " - << local_file << std::endl); + cmCTestLog(this->CTest, ERROR_MESSAGE, + " Error when uploading file: " << local_file + << std::endl); cmCTestLog(this->CTest, ERROR_MESSAGE, " Error message was: " << error_buffer << std::endl); *this->LogFile << " Error when uploading file: " << local_file @@ -273,7 +277,8 @@ bool cmCTestSubmitHandler::SubmitUsingFTP(const std::string& localprefix, // avoid dereference of empty vector if (!chunk.empty()) { *this->LogFile << cmCTestLogWrite(&*chunk.begin(), chunk.size()); - cmCTestLog(this->CTest, ERROR_MESSAGE, "CURL output: [" + cmCTestLog(this->CTest, ERROR_MESSAGE, + "CURL output: [" << cmCTestLogWrite(&*chunk.begin(), chunk.size()) << "]" << std::endl); } @@ -309,7 +314,7 @@ bool cmCTestSubmitHandler::SubmitUsingHTTP(const std::string& localprefix, // Add any additional headers that the user specified. for (std::string const& h : this->HttpHeaders) { - cmCTestOptionalLog(this->CTest, HANDLER_OUTPUT, + cmCTestOptionalLog(this->CTest, DEBUG, " Add HTTP Header: \"" << h << "\"" << std::endl, this->Quiet); headers = ::curl_slist_append(headers, h.c_str()); @@ -417,8 +422,8 @@ bool cmCTestSubmitHandler::SubmitUsingHTTP(const std::string& localprefix, } } std::string upload_as = url + - ((url.find('?') == std::string::npos) ? '?' : '&') + "FileName=" + - ofile; + ((url.find('?') == std::string::npos) ? '?' : '&') + + "FileName=" + ofile; upload_as += "&MD5="; @@ -474,7 +479,8 @@ bool cmCTestSubmitHandler::SubmitUsingHTTP(const std::string& localprefix, res = ::curl_easy_perform(curl); if (!chunk.empty()) { - cmCTestOptionalLog(this->CTest, DEBUG, "CURL output: [" + cmCTestOptionalLog(this->CTest, DEBUG, + "CURL output: [" << cmCTestLogWrite(&*chunk.begin(), chunk.size()) << "]" << std::endl, this->Quiet); @@ -482,7 +488,8 @@ bool cmCTestSubmitHandler::SubmitUsingHTTP(const std::string& localprefix, } if (!chunkDebug.empty()) { cmCTestOptionalLog( - this->CTest, DEBUG, "CURL debug output: [" + this->CTest, DEBUG, + "CURL debug output: [" << cmCTestLogWrite(&*chunkDebug.begin(), chunkDebug.size()) << "]" << std::endl, this->Quiet); @@ -536,7 +543,8 @@ bool cmCTestSubmitHandler::SubmitUsingHTTP(const std::string& localprefix, if (!chunk.empty()) { cmCTestOptionalLog( - this->CTest, DEBUG, "CURL output: [" + this->CTest, DEBUG, + "CURL output: [" << cmCTestLogWrite(&*chunk.begin(), chunk.size()) << "]" << std::endl, this->Quiet); @@ -551,8 +559,9 @@ bool cmCTestSubmitHandler::SubmitUsingHTTP(const std::string& localprefix, fclose(ftpfile); if (res) { - cmCTestLog(this->CTest, ERROR_MESSAGE, " Error when uploading file: " - << local_file << std::endl); + cmCTestLog(this->CTest, ERROR_MESSAGE, + " Error when uploading file: " << local_file + << std::endl); cmCTestLog(this->CTest, ERROR_MESSAGE, " Error message was: " << error_buffer << std::endl); *this->LogFile << " Error when uploading file: " << local_file @@ -564,7 +573,8 @@ bool cmCTestSubmitHandler::SubmitUsingHTTP(const std::string& localprefix, *this->LogFile << " Curl output was: " << cmCTestLogWrite(&*chunk.begin(), chunk.size()) << std::endl; - cmCTestLog(this->CTest, ERROR_MESSAGE, "CURL output: [" + cmCTestLog(this->CTest, ERROR_MESSAGE, + "CURL output: [" << cmCTestLogWrite(&*chunk.begin(), chunk.size()) << "]" << std::endl); } @@ -611,7 +621,8 @@ void cmCTestSubmitHandler::ParseResponse( } if (this->HasWarnings || this->HasErrors) { - cmCTestLog(this->CTest, HANDLER_OUTPUT, " Server Response:\n" + cmCTestLog(this->CTest, HANDLER_OUTPUT, + " Server Response:\n" << cmCTestLogWrite(&*chunk.begin(), chunk.size()) << "\n"); } } @@ -688,8 +699,8 @@ bool cmCTestSubmitHandler::TriggerUsingHTTP(const std::set<std::string>& files, } } std::string turl = url + - ((url.find('?') == std::string::npos) ? '?' : '&') + "xmlfile=" + - ofile; + ((url.find('?') == std::string::npos) ? '?' : '&') + + "xmlfile=" + ofile; *this->LogFile << "Trigger url: " << turl << std::endl; cmCTestOptionalLog(this->CTest, HANDLER_VERBOSE_OUTPUT, " Trigger url: " << turl << std::endl, this->Quiet); @@ -708,7 +719,8 @@ bool cmCTestSubmitHandler::TriggerUsingHTTP(const std::set<std::string>& files, *this->LogFile << " Curl output was: " << cmCTestLogWrite(&*chunk.begin(), chunk.size()) << std::endl; - cmCTestLog(this->CTest, ERROR_MESSAGE, "CURL output: [" + cmCTestLog(this->CTest, ERROR_MESSAGE, + "CURL output: [" << cmCTestLogWrite(&*chunk.begin(), chunk.size()) << "]" << std::endl); } @@ -718,14 +730,16 @@ bool cmCTestSubmitHandler::TriggerUsingHTTP(const std::set<std::string>& files, } if (!chunk.empty()) { - cmCTestOptionalLog(this->CTest, DEBUG, "CURL output: [" + cmCTestOptionalLog(this->CTest, DEBUG, + "CURL output: [" << cmCTestLogWrite(&*chunk.begin(), chunk.size()) << "]" << std::endl, this->Quiet); } if (!chunkDebug.empty()) { cmCTestOptionalLog( - this->CTest, DEBUG, "CURL debug output: [" + this->CTest, DEBUG, + "CURL debug output: [" << cmCTestLogWrite(&*chunkDebug.begin(), chunkDebug.size()) << "]" << std::endl, this->Quiet); @@ -776,9 +790,9 @@ bool cmCTestSubmitHandler::SubmitUsingSCP(const std::string& scp_command, argv[1] = lfname.c_str(); std::string rfname = url + "/" + remoteprefix + file; argv[2] = rfname.c_str(); - cmCTestOptionalLog(this->CTest, HANDLER_VERBOSE_OUTPUT, "Execute \"" - << argv[0] << "\" \"" << argv[1] << "\" \"" << argv[2] - << "\"" << std::endl, + cmCTestOptionalLog(this->CTest, HANDLER_VERBOSE_OUTPUT, + "Execute \"" << argv[0] << "\" \"" << argv[1] << "\" \"" + << argv[2] << "\"" << std::endl, this->Quiet); *this->LogFile << "Execute \"" << argv[0] << "\" \"" << argv[1] << "\" \"" << argv[2] << "\"" << std::endl; @@ -823,13 +837,14 @@ bool cmCTestSubmitHandler::SubmitUsingSCP(const std::string& scp_command, *this->LogFile << "\tThere was an exception: " << retVal << std::endl; problems++; } else if (result == cmsysProcess_State_Expired) { - cmCTestLog(this->CTest, ERROR_MESSAGE, "\tThere was a timeout" - << std::endl); + cmCTestLog(this->CTest, ERROR_MESSAGE, + "\tThere was a timeout" << std::endl); *this->LogFile << "\tThere was a timeout" << std::endl; problems++; } else if (result == cmsysProcess_State_Error) { - cmCTestLog(this->CTest, ERROR_MESSAGE, "\tError executing SCP: " - << cmsysProcess_GetErrorString(cp) << std::endl); + cmCTestLog(this->CTest, ERROR_MESSAGE, + "\tError executing SCP: " << cmsysProcess_GetErrorString(cp) + << std::endl); *this->LogFile << "\tError executing SCP: " << cmsysProcess_GetErrorString(cp) << std::endl; problems++; @@ -863,8 +878,9 @@ bool cmCTestSubmitHandler::SubmitUsingCP(const std::string& localprefix, lfname += "/" + file; std::string rfname = destination + "/" + remoteprefix + file; cmSystemTools::CopyFileAlways(lfname, rfname); - cmCTestOptionalLog(this->CTest, HANDLER_VERBOSE_OUTPUT, " Copy file: " - << lfname << " to " << rfname << std::endl, + cmCTestOptionalLog(this->CTest, HANDLER_VERBOSE_OUTPUT, + " Copy file: " << lfname << " to " << rfname + << std::endl, this->Quiet); } std::string tagDoneFile = destination + "/" + remoteprefix + "DONE"; @@ -891,8 +907,9 @@ bool cmCTestSubmitHandler::SubmitUsingXMLRPC( xmlrpc_env_init(&env); /* Call the famous server at UserLand. */ - cmCTestOptionalLog(this->CTest, HANDLER_OUTPUT, " Submitting to: " - << realURL << " (" << remoteprefix << ")" << std::endl, + cmCTestOptionalLog(this->CTest, HANDLER_OUTPUT, + " Submitting to: " << realURL << " (" << remoteprefix + << ")" << std::endl, this->Quiet); for (std::string const& file : files) { xmlrpc_value* result; @@ -915,8 +932,8 @@ bool cmCTestSubmitHandler::SubmitUsingXMLRPC( // make sure the file is not too big. if (static_cast<off_t>(static_cast<size_t>(st.st_size)) != static_cast<off_t>(st.st_size)) { - cmCTestLog(this->CTest, ERROR_MESSAGE, " File too big: " << local_file - << std::endl); + cmCTestLog(this->CTest, ERROR_MESSAGE, + " File too big: " << local_file << std::endl); return false; } size_t fileSize = static_cast<size_t>(st.st_size); @@ -946,9 +963,10 @@ bool cmCTestSubmitHandler::SubmitUsingXMLRPC( delete[] fileBuffer; if (env.fault_occurred) { - cmCTestLog(this->CTest, ERROR_MESSAGE, " Submission problem: " - << env.fault_string << " (" << env.fault_code << ")" - << std::endl); + cmCTestLog(this->CTest, ERROR_MESSAGE, + " Submission problem: " << env.fault_string << " (" + << env.fault_code << ")" + << std::endl); xmlrpc_env_clean(&env); xmlrpc_client_cleanup(); return false; @@ -1003,8 +1021,8 @@ int cmCTestSubmitHandler::HandleCDashUploadFile(std::string const& file, return -1; } if (!cmSystemTools::FileExists(file)) { - cmCTestLog(this->CTest, ERROR_MESSAGE, "Upload file not found: '" - << file << "'\n"); + cmCTestLog(this->CTest, ERROR_MESSAGE, + "Upload file not found: '" << file << "'\n"); return -1; } cmCTestCurl curl(this->CTest); @@ -1039,8 +1057,9 @@ int cmCTestSubmitHandler::HandleCDashUploadFile(std::string const& file, unsigned long retryDelayValue = 0; if (!cmSystemTools::StringToULong(retryDelayString.c_str(), &retryDelayValue)) { - cmCTestLog(this->CTest, WARNING, "Invalid value for 'RETRY_DELAY' : " - << retryDelayString << std::endl); + cmCTestLog(this->CTest, WARNING, + "Invalid value for 'RETRY_DELAY' : " << retryDelayString + << std::endl); } else { retryDelay = std::chrono::seconds(retryDelayValue); } @@ -1048,8 +1067,9 @@ int cmCTestSubmitHandler::HandleCDashUploadFile(std::string const& file, unsigned long retryCount = 0; if (!retryCountString.empty()) { if (!cmSystemTools::StringToULong(retryCountString.c_str(), &retryCount)) { - cmCTestLog(this->CTest, WARNING, "Invalid value for 'RETRY_DELAY' : " - << retryCountString << std::endl); + cmCTestLog(this->CTest, WARNING, + "Invalid value for 'RETRY_DELAY' : " << retryCountString + << std::endl); } } @@ -1117,7 +1137,8 @@ int cmCTestSubmitHandler::HandleCDashUploadFile(std::string const& file, } } if (!internalTest && !requestSucceeded) { - cmCTestLog(this->CTest, ERROR_MESSAGE, "Error in HttpRequest\n" + cmCTestLog(this->CTest, ERROR_MESSAGE, + "Error in HttpRequest\n" << response); return -1; } @@ -1127,7 +1148,8 @@ int cmCTestSubmitHandler::HandleCDashUploadFile(std::string const& file, Json::Value json; Json::Reader reader; if (!internalTest && !reader.parse(response, json)) { - cmCTestLog(this->CTest, ERROR_MESSAGE, "error parsing json string [" + cmCTestLog(this->CTest, ERROR_MESSAGE, + "error parsing json string [" << response << "]\n" << reader.getFormattedErrorMessages() << "\n"); return -1; @@ -1194,12 +1216,14 @@ int cmCTestSubmitHandler::HandleCDashUploadFile(std::string const& file, } if (!uploadSucceeded) { - cmCTestLog(this->CTest, ERROR_MESSAGE, "error uploading to CDash. " - << file << " " << url << " " << fstr.str()); + cmCTestLog(this->CTest, ERROR_MESSAGE, + "error uploading to CDash. " << file << " " << url << " " + << fstr.str()); return -1; } if (!reader.parse(response, json)) { - cmCTestLog(this->CTest, ERROR_MESSAGE, "error parsing json string [" + cmCTestLog(this->CTest, ERROR_MESSAGE, + "error parsing json string [" << response << "]\n" << reader.getFormattedErrorMessages() << "\n"); return -1; @@ -1356,7 +1380,8 @@ int cmCTestSubmitHandler::ProcessHandler() cnt++; } } - cmCTestOptionalLog(this->CTest, HANDLER_OUTPUT, "Submit files (using " + cmCTestOptionalLog(this->CTest, HANDLER_OUTPUT, + "Submit files (using " << this->CTest->GetCTestConfiguration("DropMethod") << ")" << std::endl, this->Quiet); @@ -1379,8 +1404,9 @@ int cmCTestSubmitHandler::ProcessHandler() std::string url = "ftp://"; url += cmCTest::MakeURLSafe( this->CTest->GetCTestConfiguration("DropSiteUser")) + - ":" + cmCTest::MakeURLSafe( - this->CTest->GetCTestConfiguration("DropSitePassword")) + + ":" + + cmCTest::MakeURLSafe( + this->CTest->GetCTestConfiguration("DropSitePassword")) + "@" + this->CTest->GetCTestConfiguration("DropSite") + cmCTest::MakeURLSafe(this->CTest->GetCTestConfiguration("DropLocation")); if (!this->CTest->GetCTestConfiguration("DropSiteUser").empty()) { @@ -1408,12 +1434,13 @@ int cmCTestSubmitHandler::ProcessHandler() return -1; } if (!this->CDash) { - cmCTestOptionalLog( - this->CTest, HANDLER_OUTPUT, " Using HTTP trigger method" - << std::endl - << " Trigger site: " - << this->CTest->GetCTestConfiguration("TriggerSite") << std::endl, - this->Quiet); + cmCTestOptionalLog(this->CTest, HANDLER_OUTPUT, + " Using HTTP trigger method" + << std::endl + << " Trigger site: " + << this->CTest->GetCTestConfiguration("TriggerSite") + << std::endl, + this->Quiet); if (!this->TriggerUsingHTTP( files, prefix, this->CTest->GetCTestConfiguration("TriggerSite"))) { @@ -1465,12 +1492,13 @@ int cmCTestSubmitHandler::ProcessHandler() return -1; } if (!this->CDash) { - cmCTestOptionalLog( - this->CTest, HANDLER_OUTPUT, " Using HTTP trigger method" - << std::endl - << " Trigger site: " - << this->CTest->GetCTestConfiguration("TriggerSite") << std::endl, - this->Quiet); + cmCTestOptionalLog(this->CTest, HANDLER_OUTPUT, + " Using HTTP trigger method" + << std::endl + << " Trigger site: " + << this->CTest->GetCTestConfiguration("TriggerSite") + << std::endl, + this->Quiet); if (!this->TriggerUsingHTTP( files, prefix, this->CTest->GetCTestConfiguration("TriggerSite"))) { @@ -1481,15 +1509,17 @@ int cmCTestSubmitHandler::ProcessHandler() } } if (this->HasErrors) { - cmCTestLog(this->CTest, HANDLER_OUTPUT, " Errors occurred during " - "submission." + cmCTestLog(this->CTest, HANDLER_OUTPUT, + " Errors occurred during " + "submission." << std::endl); ofs << " Errors occurred during submission. " << std::endl; } else { - cmCTestOptionalLog( - this->CTest, HANDLER_OUTPUT, " Submission successful" - << (this->HasWarnings ? ", with warnings." : "") << std::endl, - this->Quiet); + cmCTestOptionalLog(this->CTest, HANDLER_OUTPUT, + " Submission successful" + << (this->HasWarnings ? ", with warnings." : "") + << std::endl, + this->Quiet); ofs << " Submission successful" << (this->HasWarnings ? ", with warnings." : "") << std::endl; } @@ -1532,6 +1562,15 @@ int cmCTestSubmitHandler::ProcessHandler() // change to the build directory so that we can uses a relative path // on windows since scp doesn't support "c:" a drive in the path cmWorkingDirectory workdir(buildDirectory); + if (workdir.Failed()) { + cmCTestLog(this->CTest, ERROR_MESSAGE, + " Failed to change directory to " + << buildDirectory << " : " + << std::strerror(workdir.GetLastResult()) << std::endl); + ofs << " Failed to change directory to " << buildDirectory << " : " + << std::strerror(workdir.GetLastResult()) << std::endl; + return -1; + } if (!this->SubmitUsingSCP(this->CTest->GetCTestConfiguration("ScpCommand"), "Testing/" + this->CTest->GetCurrentTag(), files, @@ -1551,6 +1590,15 @@ int cmCTestSubmitHandler::ProcessHandler() // change to the build directory so that we can uses a relative path // on windows since scp doesn't support "c:" a drive in the path cmWorkingDirectory workdir(buildDirectory); + if (workdir.Failed()) { + cmCTestLog(this->CTest, ERROR_MESSAGE, + " Failed to change directory to " + << buildDirectory << " : " + << std::strerror(workdir.GetLastResult()) << std::endl); + ofs << " Failed to change directory to " << buildDirectory << " : " + << std::strerror(workdir.GetLastResult()) << std::endl; + return -1; + } cmCTestOptionalLog(this->CTest, HANDLER_VERBOSE_OUTPUT, " Change directory: " << buildDirectory << std::endl, this->Quiet); @@ -1568,8 +1616,9 @@ int cmCTestSubmitHandler::ProcessHandler() return 0; } - cmCTestLog(this->CTest, ERROR_MESSAGE, " Unknown submission method: \"" - << dropMethod << "\"" << std::endl); + cmCTestLog(this->CTest, ERROR_MESSAGE, + " Unknown submission method: \"" << dropMethod << "\"" + << std::endl); return -1; } diff --git a/Source/CTest/cmCTestTestCommand.cxx b/Source/CTest/cmCTestTestCommand.cxx index daedf6255..895ca1267 100644 --- a/Source/CTest/cmCTestTestCommand.cxx +++ b/Source/CTest/cmCTestTestCommand.cxx @@ -112,14 +112,16 @@ cmCTestGenericHandler* cmCTestTestCommand::InitializeHandler() if (!cmSystemTools::StringToULong(this->Values[ctt_TEST_LOAD], &testLoad)) { testLoad = 0; - cmCTestLog(this->CTest, WARNING, "Invalid value for 'TEST_LOAD' : " + cmCTestLog(this->CTest, WARNING, + "Invalid value for 'TEST_LOAD' : " << this->Values[ctt_TEST_LOAD] << std::endl); } } else if (ctestTestLoad && *ctestTestLoad) { if (!cmSystemTools::StringToULong(ctestTestLoad, &testLoad)) { testLoad = 0; - cmCTestLog(this->CTest, WARNING, "Invalid value for 'CTEST_TEST_LOAD' : " - << ctestTestLoad << std::endl); + cmCTestLog(this->CTest, WARNING, + "Invalid value for 'CTEST_TEST_LOAD' : " << ctestTestLoad + << std::endl); } } else { testLoad = this->CTest->GetTestLoad(); diff --git a/Source/CTest/cmCTestTestHandler.cxx b/Source/CTest/cmCTestTestHandler.cxx index 84d8926ea..91b92a37d 100644 --- a/Source/CTest/cmCTestTestHandler.cxx +++ b/Source/CTest/cmCTestTestHandler.cxx @@ -6,6 +6,7 @@ #include <cmsys/Base64.h> #include <cmsys/Directory.hxx> #include <cmsys/RegularExpression.hxx> +#include <cstring> #include <functional> #include <iomanip> #include <iterator> @@ -14,7 +15,6 @@ #include <sstream> #include <stdio.h> #include <stdlib.h> -#include <string.h> #include <time.h> #include "cmAlgorithms.h" @@ -85,6 +85,11 @@ bool cmCTestSubdirCommand::InitialPass(std::vector<std::string> const& args, bool readit = false; { cmWorkingDirectory workdir(fname); + if (workdir.Failed()) { + this->SetError("Failed to change directory to " + fname + " : " + + std::strerror(workdir.GetLastResult())); + return false; + } const char* testFilename; if (cmSystemTools::FileExists("CTestTestfile.cmake")) { // does the CTestTestfile.cmake exist ? @@ -254,7 +259,7 @@ public: /** * This is called when the command is first encountered in * the CMakeLists.txt file. - */ + */ bool InitialPass(std::vector<std::string> const& /*unused*/, cmExecutionStatus& /*unused*/) override; @@ -467,11 +472,12 @@ int cmCTestTestHandler::ProcessHandler() this->TestResults.clear(); - cmCTestOptionalLog( - this->CTest, HANDLER_OUTPUT, (this->MemCheck ? "Memory check" : "Test") - << " project " << cmSystemTools::GetCurrentWorkingDirectory() - << std::endl, - this->Quiet); + cmCTestOptionalLog(this->CTest, HANDLER_OUTPUT, + (this->MemCheck ? "Memory check" : "Test") + << " project " + << cmSystemTools::GetCurrentWorkingDirectory() + << std::endl, + this->Quiet); if (!this->PreProcessHandler()) { return -1; } @@ -495,13 +501,14 @@ int cmCTestTestHandler::ProcessHandler() if (total == 0) { if (!this->CTest->GetShowOnly() && !this->CTest->ShouldPrintLabels()) { - cmCTestLog(this->CTest, ERROR_MESSAGE, "No tests were found!!!" - << std::endl); + cmCTestLog(this->CTest, ERROR_MESSAGE, + "No tests were found!!!" << std::endl); } } else { if (this->HandlerVerbose && !passed.empty() && (this->UseIncludeRegExpFlag || this->UseExcludeRegExpFlag)) { - cmCTestOptionalLog(this->CTest, HANDLER_VERBOSE_OUTPUT, std::endl + cmCTestOptionalLog(this->CTest, HANDLER_VERBOSE_OUTPUT, + std::endl << "The following tests passed:" << std::endl, this->Quiet); for (std::string const& j : passed) { @@ -528,7 +535,8 @@ int cmCTestTestHandler::ProcessHandler() percent = 99; } - cmCTestLog(this->CTest, HANDLER_OUTPUT, std::endl + cmCTestLog(this->CTest, HANDLER_OUTPUT, + std::endl << static_cast<int>(percent + .5f) << "% tests passed, " << failed.size() << " tests failed out of " << total << std::endl); @@ -548,7 +556,8 @@ int cmCTestTestHandler::ProcessHandler() if (!disabledTests.empty()) { cmGeneratedFileStream ofs; - cmCTestLog(this->CTest, HANDLER_OUTPUT, std::endl + cmCTestLog(this->CTest, HANDLER_OUTPUT, + std::endl << "The following tests did not run:" << std::endl); this->StartLogFile("TestsDisabled", ofs); @@ -560,15 +569,16 @@ int cmCTestTestHandler::ProcessHandler() } else { disabled_reason = "Skipped"; } - cmCTestLog(this->CTest, HANDLER_OUTPUT, "\t" - << std::setw(3) << dt.TestCount << " - " << dt.Name - << " (" << disabled_reason << ")" << std::endl); + cmCTestLog(this->CTest, HANDLER_OUTPUT, + "\t" << std::setw(3) << dt.TestCount << " - " << dt.Name + << " (" << disabled_reason << ")" << std::endl); } } if (!failed.empty()) { cmGeneratedFileStream ofs; - cmCTestLog(this->CTest, HANDLER_OUTPUT, std::endl + cmCTestLog(this->CTest, HANDLER_OUTPUT, + std::endl << "The following tests FAILED:" << std::endl); this->StartLogFile("TestsFailed", ofs); @@ -577,9 +587,10 @@ int cmCTestTestHandler::ProcessHandler() !cmHasLiteralPrefix(ft.CompletionStatus, "SKIP_RETURN_CODE=") && ft.CompletionStatus != "Disabled") { ofs << ft.TestCount << ":" << ft.Name << std::endl; - cmCTestLog(this->CTest, HANDLER_OUTPUT, "\t" - << std::setw(3) << ft.TestCount << " - " << ft.Name - << " (" << this->GetTestStatus(ft) << ")" << std::endl); + cmCTestLog(this->CTest, HANDLER_OUTPUT, + "\t" << std::setw(3) << ft.TestCount << " - " << ft.Name + << " (" << this->GetTestStatus(ft) << ")" + << std::endl); } } } @@ -590,7 +601,8 @@ int cmCTestTestHandler::ProcessHandler() if (!this->StartResultingXML( (this->MemCheck ? cmCTest::PartMemCheck : cmCTest::PartTest), (this->MemCheck ? "DynamicAnalysis" : "Test"), xmlfile)) { - cmCTestLog(this->CTest, ERROR_MESSAGE, "Cannot create " + cmCTestLog(this->CTest, ERROR_MESSAGE, + "Cannot create " << (this->MemCheck ? "memory check" : "testing") << " XML file" << std::endl); this->LogFile = nullptr; @@ -666,8 +678,8 @@ void cmCTestTestHandler::PrintLabelOrSubprojectSummary(bool doSubProject) cmCTestOptionalLog(this->CTest, HANDLER_OUTPUT, "\nSubproject Time Summary:", this->Quiet); } else { - cmCTestOptionalLog(this->CTest, HANDLER_OUTPUT, "\nLabel Time Summary:", - this->Quiet); + cmCTestOptionalLog(this->CTest, HANDLER_OUTPUT, + "\nLabel Time Summary:", this->Quiet); } for (std::string const& i : labels) { std::string label = i; @@ -682,7 +694,8 @@ void cmCTestTestHandler::PrintLabelOrSubprojectSummary(bool doSubProject) labelCountStr << "s"; } labelCountStr << ")"; - cmCTestOptionalLog(this->CTest, HANDLER_OUTPUT, "\n" + cmCTestOptionalLog(this->CTest, HANDLER_OUTPUT, + "\n" << label << " = " << buf << " " << labelCountStr.str(), this->Quiet); @@ -1084,9 +1097,10 @@ void cmCTestTestHandler::UpdateForFixtures(ListOfTests& tests) const } } - cmCTestOptionalLog(this->CTest, HANDLER_VERBOSE_OUTPUT, "Added " - << fixtureTestsAdded - << " tests to meet fixture requirements" << std::endl, + cmCTestOptionalLog(this->CTest, HANDLER_VERBOSE_OUTPUT, + "Added " << fixtureTestsAdded + << " tests to meet fixture requirements" + << std::endl, this->Quiet); } @@ -1114,8 +1128,9 @@ bool cmCTestTestHandler::GetValue(const char* tag, int& value, fin >> value; ret = cmSystemTools::GetLineFromStream(fin, line); // read blank line } else { - cmCTestLog(this->CTest, ERROR_MESSAGE, "parse error: missing tag: " - << tag << " found [" << line << "]" << std::endl); + cmCTestLog(this->CTest, ERROR_MESSAGE, + "parse error: missing tag: " << tag << " found [" << line << "]" + << std::endl); ret = false; } return ret; @@ -1131,8 +1146,9 @@ bool cmCTestTestHandler::GetValue(const char* tag, double& value, fin >> value; ret = cmSystemTools::GetLineFromStream(fin, line); // read blank line } else { - cmCTestLog(this->CTest, ERROR_MESSAGE, "parse error: missing tag: " - << tag << " found [" << line << "]" << std::endl); + cmCTestLog(this->CTest, ERROR_MESSAGE, + "parse error: missing tag: " << tag << " found [" << line << "]" + << std::endl); ret = false; } return ret; @@ -1157,8 +1173,9 @@ bool cmCTestTestHandler::GetValue(const char* tag, bool& value, #endif ret = cmSystemTools::GetLineFromStream(fin, line); // read blank line } else { - cmCTestLog(this->CTest, ERROR_MESSAGE, "parse error: missing tag: " - << tag << " found [" << line << "]" << std::endl); + cmCTestLog(this->CTest, ERROR_MESSAGE, + "parse error: missing tag: " << tag << " found [" << line << "]" + << std::endl); ret = false; } return ret; @@ -1174,8 +1191,9 @@ bool cmCTestTestHandler::GetValue(const char* tag, size_t& value, fin >> value; ret = cmSystemTools::GetLineFromStream(fin, line); // read blank line } else { - cmCTestLog(this->CTest, ERROR_MESSAGE, "parse error: missing tag: " - << tag << " found [" << line << "]" << std::endl); + cmCTestLog(this->CTest, ERROR_MESSAGE, + "parse error: missing tag: " << tag << " found [" << line << "]" + << std::endl); ret = false; } return ret; @@ -1190,8 +1208,9 @@ bool cmCTestTestHandler::GetValue(const char* tag, std::string& value, if (line == tag) { ret = cmSystemTools::GetLineFromStream(fin, value); } else { - cmCTestLog(this->CTest, ERROR_MESSAGE, "parse error: missing tag: " - << tag << " found [" << line << "]" << std::endl); + cmCTestLog(this->CTest, ERROR_MESSAGE, + "parse error: missing tag: " << tag << " found [" << line << "]" + << std::endl); ret = false; } return ret; @@ -1606,7 +1625,8 @@ std::string cmCTestTestHandler::FindExecutable( } } if (fullPath.empty()) { - cmCTestLog(ctest, HANDLER_OUTPUT, "Could not find executable " + cmCTestLog(ctest, HANDLER_OUTPUT, + "Could not find executable " << testCommand << "\n" << "Looked in the following places:\n"); for (std::string const& f : failed) { @@ -1788,8 +1808,8 @@ void cmCTestTestHandler::ExpandTestsToRunInformationForRerunFailed() cmsys::Directory directory; if (directory.Load(dirName) == 0) { - cmCTestLog(this->CTest, ERROR_MESSAGE, "Unable to read the contents of " - << dirName << std::endl); + cmCTestLog(this->CTest, ERROR_MESSAGE, + "Unable to read the contents of " << dirName << std::endl); return; } @@ -1824,8 +1844,8 @@ void cmCTestTestHandler::ExpandTestsToRunInformationForRerunFailed() if (!cmSystemTools::FileExists(lastTestsFailedLog)) { if (!this->CTest->GetShowOnly() && !this->CTest->ShouldPrintLabels()) { - cmCTestLog(this->CTest, ERROR_MESSAGE, lastTestsFailedLog - << " does not exist!" << std::endl); + cmCTestLog(this->CTest, ERROR_MESSAGE, + lastTestsFailedLog << " does not exist!" << std::endl); } return; } @@ -1847,7 +1867,8 @@ void cmCTestTestHandler::ExpandTestsToRunInformationForRerunFailed() ifs.close(); } else if (!this->CTest->GetShowOnly() && !this->CTest->ShouldPrintLabels()) { - cmCTestLog(this->CTest, ERROR_MESSAGE, "Problem reading file: " + cmCTestLog(this->CTest, ERROR_MESSAGE, + "Problem reading file: " << lastTestsFailedLog << " while generating list of previously failed tests." << std::endl); @@ -1956,11 +1977,12 @@ void cmCTestTestHandler::GenerateRegressionImages(cmXMLWriter& xml, xml.Element("Value", "Image " + filename + " is empty"); xml.EndElement(); } else { - cmsys::ifstream ifs(filename.c_str(), std::ios::in + cmsys::ifstream ifs(filename.c_str(), + std::ios::in #ifdef _WIN32 | std::ios::binary #endif - ); + ); unsigned char* file_buffer = new unsigned char[len + 1]; ifs.read(reinterpret_cast<char*>(file_buffer), len); unsigned char* encoded_buffer = new unsigned char[static_cast<int>( @@ -1997,9 +2019,9 @@ void cmCTestTestHandler::GenerateRegressionImages(cmXMLWriter& xml, xml.Attribute("text", "text/string"); xml.Element("Value", "File " + filename + " not found"); xml.EndElement(); - cmCTestOptionalLog(this->CTest, HANDLER_OUTPUT, "File \"" - << filename << "\" not found." << std::endl, - this->Quiet); + cmCTestOptionalLog( + this->CTest, HANDLER_OUTPUT, + "File \"" << filename << "\" not found." << std::endl, this->Quiet); } cxml.erase(measurementfile.start(), measurementfile.end() - measurementfile.start()); @@ -2165,6 +2187,9 @@ bool cmCTestTestHandler::SetTestsProperties( rt.Processors = 1; } } + if (key == "PROCESSOR_AFFINITY") { + rt.WantAffinity = cmSystemTools::IsOn(val.c_str()); + } if (key == "SKIP_RETURN_CODE") { rt.SkipReturnCode = atoi(val.c_str()); if (rt.SkipReturnCode < 0 || rt.SkipReturnCode > 255) { @@ -2336,6 +2361,7 @@ bool cmCTestTestHandler::AddTest(const std::vector<std::string>& args) test.ExplicitTimeout = false; test.Cost = 0; test.Processors = 1; + test.WantAffinity = false; test.SkipReturnCode = -1; test.PreviousRuns = 0; if (this->UseIncludeRegExpFlag && diff --git a/Source/CTest/cmCTestTestHandler.h b/Source/CTest/cmCTestTestHandler.h index f4978b677..d2694a114 100644 --- a/Source/CTest/cmCTestTestHandler.h +++ b/Source/CTest/cmCTestTestHandler.h @@ -130,6 +130,8 @@ public: int Index; // Requested number of process slots int Processors; + bool WantAffinity; + std::vector<size_t> Affinity; // return code of test which will mark test as "not run" int SkipReturnCode; std::vector<std::string> Environment; diff --git a/Source/CTest/cmCTestUpdateHandler.cxx b/Source/CTest/cmCTestUpdateHandler.cxx index 504b2102a..57e40ce35 100644 --- a/Source/CTest/cmCTestUpdateHandler.cxx +++ b/Source/CTest/cmCTestUpdateHandler.cxx @@ -47,7 +47,8 @@ void cmCTestUpdateHandler::Initialize() int cmCTestUpdateHandler::DetermineType(const char* cmd, const char* type) { - cmCTestOptionalLog(this->CTest, DEBUG, "Determine update type from command: " + cmCTestOptionalLog(this->CTest, DEBUG, + "Determine update type from command: " << cmd << " and type: " << type << std::endl, this->Quiet); if (type && *type) { @@ -130,7 +131,8 @@ int cmCTestUpdateHandler::ProcessHandler() return -1; } - cmCTestOptionalLog(this->CTest, HANDLER_OUTPUT, " Use " + cmCTestOptionalLog(this->CTest, HANDLER_OUTPUT, + " Use " << cmCTestUpdateHandlerUpdateToString(this->UpdateType) << " repository type" << std::endl; , this->Quiet); @@ -171,8 +173,8 @@ int cmCTestUpdateHandler::ProcessHandler() // cmGeneratedFileStream os; if (!this->StartResultingXML(cmCTest::PartUpdate, "Update", os)) { - cmCTestLog(this->CTest, ERROR_MESSAGE, "Cannot open log file" - << std::endl); + cmCTestLog(this->CTest, ERROR_MESSAGE, + "Cannot open log file" << std::endl); return -1; } std::string start_time = this->CTest->CurrentTime(); @@ -191,7 +193,8 @@ int cmCTestUpdateHandler::ProcessHandler() std::string("ctest-") + cmVersion::GetCMakeVersion()); xml.Element("Site", this->CTest->GetCTestConfiguration("Site")); xml.Element("BuildName", buildname); - xml.Element("BuildStamp", this->CTest->GetCurrentTag() + "-" + + xml.Element("BuildStamp", + this->CTest->GetCurrentTag() + "-" + this->CTest->GetTestModelString()); xml.Element("StartDateTime", start_time); xml.Element("StartTime", start_time_time); @@ -209,9 +212,9 @@ int cmCTestUpdateHandler::ProcessHandler() this->Quiet); } if (int numModified = vc->GetPathCount(cmCTestVC::PathModified)) { - cmCTestOptionalLog(this->CTest, HANDLER_OUTPUT, " Found " - << numModified << " locally modified files\n", - this->Quiet); + cmCTestOptionalLog( + this->CTest, HANDLER_OUTPUT, + " Found " << numModified << " locally modified files\n", this->Quiet); localModifications += numModified; } if (int numConflicting = vc->GetPathCount(cmCTestVC::PathConflicting)) { @@ -241,8 +244,9 @@ int cmCTestUpdateHandler::ProcessHandler() if (!updated) { xml.Content("Update command failed:\n"); xml.Content(vc->GetUpdateCommandLine()); - cmCTestLog(this->CTest, HANDLER_OUTPUT, " Update command failed: " - << vc->GetUpdateCommandLine() << "\n"); + cmCTestLog(this->CTest, HANDLER_OUTPUT, + " Update command failed: " << vc->GetUpdateCommandLine() + << "\n"); } xml.EndElement(); // UpdateReturnStatus xml.EndElement(); // Update diff --git a/Source/CTest/cmCTestUploadHandler.cxx b/Source/CTest/cmCTestUploadHandler.cxx index 59a5de484..261ecab9a 100644 --- a/Source/CTest/cmCTestUploadHandler.cxx +++ b/Source/CTest/cmCTestUploadHandler.cxx @@ -30,8 +30,8 @@ int cmCTestUploadHandler::ProcessHandler() cmGeneratedFileStream ofs; if (!this->CTest->OpenOutputFile(this->CTest->GetCurrentTag(), "Upload.xml", ofs)) { - cmCTestLog(this->CTest, ERROR_MESSAGE, "Cannot open Upload.xml file" - << std::endl); + cmCTestLog(this->CTest, ERROR_MESSAGE, + "Cannot open Upload.xml file" << std::endl); return -1; } std::string buildname = @@ -45,7 +45,8 @@ int cmCTestUploadHandler::ProcessHandler() "<file:///Dart/Source/Server/XSL/Build.xsl> \""); xml.StartElement("Site"); xml.Attribute("BuildName", buildname); - xml.Attribute("BuildStamp", this->CTest->GetCurrentTag() + "-" + + xml.Attribute("BuildStamp", + this->CTest->GetCurrentTag() + "-" + this->CTest->GetTestModelString()); xml.Attribute("Name", this->CTest->GetCTestConfiguration("Site")); xml.Attribute("Generator", diff --git a/Source/CTest/cmCTestVC.cxx b/Source/CTest/cmCTestVC.cxx index 13fa6e1f5..a59d671dd 100644 --- a/Source/CTest/cmCTestVC.cxx +++ b/Source/CTest/cmCTestVC.cxx @@ -69,8 +69,8 @@ bool cmCTestVC::InitialCheckout(const char* command) bool result = this->RunChild(&vc_co[0], &out, &err, parent.c_str()); this->Log << "--- End Initial Checkout ---\n"; if (!result) { - cmCTestLog(this->CTest, ERROR_MESSAGE, "Initial checkout failed!" - << std::endl); + cmCTestLog(this->CTest, ERROR_MESSAGE, + "Initial checkout failed!" << std::endl); } return result; } diff --git a/Source/CTest/cmParseCacheCoverage.cxx b/Source/CTest/cmParseCacheCoverage.cxx index 4cd6588be..ca1fe70e4 100644 --- a/Source/CTest/cmParseCacheCoverage.cxx +++ b/Source/CTest/cmParseCacheCoverage.cxx @@ -100,10 +100,11 @@ bool cmParseCacheCoverage::ReadCMCovFile(const char* file) std::string line; std::vector<std::string> separateLine; if (!cmSystemTools::GetLineFromStream(in, line)) { - cmCTestLog(this->CTest, ERROR_MESSAGE, "Empty file : " - << file << " referenced in this line of cmcov data:\n" - "[" - << line << "]\n"); + cmCTestLog(this->CTest, ERROR_MESSAGE, + "Empty file : " << file + << " referenced in this line of cmcov data:\n" + "[" + << line << "]\n"); return false; } separateLine.clear(); @@ -112,8 +113,9 @@ bool cmParseCacheCoverage::ReadCMCovFile(const char* file) separateLine[1] != "Line" || separateLine[2] != "RtnLine" || separateLine[3] != "Code") { cmCTestLog(this->CTest, ERROR_MESSAGE, - "Bad first line of cmcov file : " << file << " line:\n" - "[" + "Bad first line of cmcov file : " << file + << " line:\n" + "[" << line << "]\n"); } std::string routine; @@ -128,8 +130,9 @@ bool cmParseCacheCoverage::ReadCMCovFile(const char* file) if (separateLine.size() < 4) { cmCTestLog(this->CTest, ERROR_MESSAGE, "Bad line of cmcov file expected at least 4 found: " - << separateLine.size() << " " << file << " line:\n" - "[" + << separateLine.size() << " " << file + << " line:\n" + "[" << line << "]\n"); for (std::string::size_type i = 0; i < separateLine.size(); ++i) { cmCTestLog(this->CTest, ERROR_MESSAGE, "" << separateLine[1] << " "); diff --git a/Source/CTest/cmParseDelphiCoverage.cxx b/Source/CTest/cmParseDelphiCoverage.cxx index 6d82cb2e7..cc8197951 100644 --- a/Source/CTest/cmParseDelphiCoverage.cxx +++ b/Source/CTest/cmParseDelphiCoverage.cxx @@ -108,8 +108,9 @@ public: while (true) { lastoffset = line.find('(', pos); if (lastoffset == std::string::npos) { - cmCTestOptionalLog(this->CTest, HANDLER_VERBOSE_OUTPUT, endnamepos - << "File not found " << lastoffset << std::endl, + cmCTestOptionalLog(this->CTest, HANDLER_VERBOSE_OUTPUT, + endnamepos << "File not found " << lastoffset + << std::endl, this->Coverage.Quiet); return false; } diff --git a/Source/CTest/cmParseGTMCoverage.cxx b/Source/CTest/cmParseGTMCoverage.cxx index f965048bb..822363d2d 100644 --- a/Source/CTest/cmParseGTMCoverage.cxx +++ b/Source/CTest/cmParseGTMCoverage.cxx @@ -75,7 +75,8 @@ bool cmParseGTMCoverage::ReadMCovFile(const char* file) this->Coverage.TotalCoverage[lastpath][lastoffset + linenumber] += count; } else { - cmCTestLog(this->CTest, ERROR_MESSAGE, "Can not find mumps file : " + cmCTestLog(this->CTest, ERROR_MESSAGE, + "Can not find mumps file : " << lastroutine << " referenced in this line of mcov data:\n" "[" @@ -102,9 +103,11 @@ bool cmParseGTMCoverage::ReadMCovFile(const char* file) lastoffset = lineoffset; } } else { - cmCTestLog(this->CTest, ERROR_MESSAGE, "Can not find mumps file : " - << routine << " referenced in this line of mcov data:\n" - "[" + cmCTestLog(this->CTest, ERROR_MESSAGE, + "Can not find mumps file : " + << routine + << " referenced in this line of mcov data:\n" + "[" << line << "]\n"); } lastfunction = function; @@ -144,8 +147,9 @@ bool cmParseGTMCoverage::FindFunctionInMumpsFile(std::string const& filepath, linenum++; // move to next line count } lineoffset = 0; - cmCTestLog(this->CTest, ERROR_MESSAGE, "Could not find entry point : " - << function << " in " << filepath << "\n"); + cmCTestLog(this->CTest, ERROR_MESSAGE, + "Could not find entry point : " << function << " in " << filepath + << "\n"); return false; } @@ -221,8 +225,8 @@ bool cmParseGTMCoverage::ParseMCOVLine(std::string const& line, } // less then two arguments is an error if (args.size() < 2) { - cmCTestLog(this->CTest, ERROR_MESSAGE, "Error parsing mcov line: [" - << line << "]\n"); + cmCTestLog(this->CTest, ERROR_MESSAGE, + "Error parsing mcov line: [" << line << "]\n"); return false; } routine = args[0]; // the routine is the first argument diff --git a/Source/CTest/cmParseJacocoCoverage.cxx b/Source/CTest/cmParseJacocoCoverage.cxx index 7acb5ca3f..31e7cd4d4 100644 --- a/Source/CTest/cmParseJacocoCoverage.cxx +++ b/Source/CTest/cmParseJacocoCoverage.cxx @@ -38,8 +38,9 @@ protected: if (this->PackagePath.empty()) { if (!this->FindPackagePath(fileName)) { - cmCTestLog(this->CTest, ERROR_MESSAGE, "Cannot find file: " - << this->PackageName << "/" << fileName << std::endl); + cmCTestLog(this->CTest, ERROR_MESSAGE, + "Cannot find file: " << this->PackageName << "/" + << fileName << std::endl); this->Coverage.Error++; return; } diff --git a/Source/CTest/cmParsePHPCoverage.cxx b/Source/CTest/cmParsePHPCoverage.cxx index 761ebec65..a6e65c9df 100644 --- a/Source/CTest/cmParsePHPCoverage.cxx +++ b/Source/CTest/cmParsePHPCoverage.cxx @@ -153,7 +153,8 @@ bool cmParsePHPCoverage::ReadFileInformation(std::istream& in) delete[] s; // read close quote if (in.get(c) && c != '"') { - cmCTestLog(this->CTest, ERROR_MESSAGE, "failed to read close quote\n" + cmCTestLog(this->CTest, ERROR_MESSAGE, + "failed to read close quote\n" << "read [" << c << "]\n"); return false; } @@ -184,8 +185,8 @@ bool cmParsePHPCoverage::ReadPHPData(const char* file) } for (int i = 0; i < size; i++) { if (!this->ReadFileInformation(in)) { - cmCTestLog(this->CTest, ERROR_MESSAGE, "Failed to read file #" << i - << "\n"); + cmCTestLog(this->CTest, ERROR_MESSAGE, + "Failed to read file #" << i << "\n"); return false; } in.get(c); diff --git a/Source/CTest/cmProcess.cxx b/Source/CTest/cmProcess.cxx index 09ed0a914..39cea8795 100644 --- a/Source/CTest/cmProcess.cxx +++ b/Source/CTest/cmProcess.cxx @@ -13,13 +13,13 @@ #include <signal.h> #include <string> #if !defined(_WIN32) -#include <unistd.h> +# include <unistd.h> #endif #define CM_PROCESS_BUF_SIZE 65536 #if defined(_WIN32) && !defined(__CYGWIN__) -#include <io.h> +# include <io.h> static int cmProcessGetPipes(int* fds) { @@ -40,7 +40,7 @@ static int cmProcessGetPipes(int* fds) return 0; } #else -#include <errno.h> +# include <errno.h> static int cmProcessGetPipes(int* fds) { @@ -83,7 +83,7 @@ void cmProcess::SetCommandArguments(std::vector<std::string> const& args) this->Arguments = args; } -bool cmProcess::StartProcess(uv_loop_t& loop) +bool cmProcess::StartProcess(uv_loop_t& loop, std::vector<size_t>* affinity) { this->ProcessState = cmProcess::State::Error; if (this->Command.empty()) { @@ -138,6 +138,22 @@ bool cmProcess::StartProcess(uv_loop_t& loop) options.stdio_count = 3; // in, out and err options.exit_cb = &cmProcess::OnExitCB; options.stdio = stdio; +#if !defined(CMAKE_USE_SYSTEM_LIBUV) + std::vector<char> cpumask; + if (affinity && !affinity->empty()) { + cpumask.resize(static_cast<size_t>(uv_cpumask_size()), 0); + for (auto p : *affinity) { + cpumask[p] = 1; + } + options.cpumask = cpumask.data(); + options.cpumask_size = cpumask.size(); + } else { + options.cpumask = nullptr; + options.cpumask_size = 0; + } +#else + static_cast<void>(affinity); +#endif status = uv_read_start(pipe_reader, &cmProcess::OnAllocateCB, &cmProcess::OnReadCB); @@ -151,8 +167,9 @@ bool cmProcess::StartProcess(uv_loop_t& loop) status = this->Process.spawn(loop, options, this); if (status != 0) { - cmCTestLog(this->Runner.GetCTest(), ERROR_MESSAGE, "Process not started\n " - << this->Command << "\n[" << uv_strerror(status) << "]\n"); + cmCTestLog(this->Runner.GetCTest(), ERROR_MESSAGE, + "Process not started\n " << this->Command << "\n[" + << uv_strerror(status) << "]\n"); return false; } @@ -329,7 +346,7 @@ void cmProcess::OnExit(int64_t exit_status, int term_signal) #else term_signal != 0 #endif - ) { + ) { this->ProcessState = cmProcess::State::Exception; } else { this->ProcessState = cmProcess::State::Exited; @@ -375,7 +392,7 @@ cmProcess::Exception cmProcess::GetExitException() { auto exception = Exception::None; #if defined(_WIN32) && !defined(__CYGWIN__) - auto exit_code = (DWORD) this->ExitValue; + auto exit_code = (DWORD)this->ExitValue; if ((exit_code & 0xF0000000) != 0xC0000000) { return exception; } @@ -399,12 +416,12 @@ cmProcess::Exception cmProcess::GetExitException() case STATUS_FLOAT_OVERFLOW: case STATUS_FLOAT_STACK_CHECK: case STATUS_FLOAT_UNDERFLOW: -#ifdef STATUS_FLOAT_MULTIPLE_FAULTS +# ifdef STATUS_FLOAT_MULTIPLE_FAULTS case STATUS_FLOAT_MULTIPLE_FAULTS: -#endif -#ifdef STATUS_FLOAT_MULTIPLE_TRAPS +# endif +# ifdef STATUS_FLOAT_MULTIPLE_TRAPS case STATUS_FLOAT_MULTIPLE_TRAPS: -#endif +# endif case STATUS_INTEGER_DIVIDE_BY_ZERO: case STATUS_INTEGER_OVERFLOW: exception = Exception::Numerical; @@ -472,16 +489,16 @@ std::string cmProcess::GetExitExceptionString() case STATUS_FLOAT_UNDERFLOW: exception_str = "Floating-point underflow"; break; -#ifdef STATUS_FLOAT_MULTIPLE_FAULTS +# ifdef STATUS_FLOAT_MULTIPLE_FAULTS case STATUS_FLOAT_MULTIPLE_FAULTS: exception_str = "Floating-point exception (multiple faults)"; break; -#endif -#ifdef STATUS_FLOAT_MULTIPLE_TRAPS +# endif +# ifdef STATUS_FLOAT_MULTIPLE_TRAPS case STATUS_FLOAT_MULTIPLE_TRAPS: exception_str = "Floating-point exception (multiple traps)"; break; -#endif +# endif case STATUS_INTEGER_DIVIDE_BY_ZERO: exception_str = "Integer divide-by-zero"; break; @@ -528,188 +545,188 @@ std::string cmProcess::GetExitExceptionString() } #else switch (this->Signal) { -#ifdef SIGSEGV +# ifdef SIGSEGV case SIGSEGV: exception_str = "Segmentation fault"; break; -#endif -#ifdef SIGBUS -#if !defined(SIGSEGV) || SIGBUS != SIGSEGV +# endif +# ifdef SIGBUS +# if !defined(SIGSEGV) || SIGBUS != SIGSEGV case SIGBUS: exception_str = "Bus error"; break; -#endif -#endif -#ifdef SIGFPE +# endif +# endif +# ifdef SIGFPE case SIGFPE: exception_str = "Floating-point exception"; break; -#endif -#ifdef SIGILL +# endif +# ifdef SIGILL case SIGILL: exception_str = "Illegal instruction"; break; -#endif -#ifdef SIGINT +# endif +# ifdef SIGINT case SIGINT: exception_str = "User interrupt"; break; -#endif -#ifdef SIGABRT +# endif +# ifdef SIGABRT case SIGABRT: exception_str = "Child aborted"; break; -#endif -#ifdef SIGKILL +# endif +# ifdef SIGKILL case SIGKILL: exception_str = "Child killed"; break; -#endif -#ifdef SIGTERM +# endif +# ifdef SIGTERM case SIGTERM: exception_str = "Child terminated"; break; -#endif -#ifdef SIGHUP +# endif +# ifdef SIGHUP case SIGHUP: exception_str = "SIGHUP"; break; -#endif -#ifdef SIGQUIT +# endif +# ifdef SIGQUIT case SIGQUIT: exception_str = "SIGQUIT"; break; -#endif -#ifdef SIGTRAP +# endif +# ifdef SIGTRAP case SIGTRAP: exception_str = "SIGTRAP"; break; -#endif -#ifdef SIGIOT -#if !defined(SIGABRT) || SIGIOT != SIGABRT +# endif +# ifdef SIGIOT +# if !defined(SIGABRT) || SIGIOT != SIGABRT case SIGIOT: exception_str = "SIGIOT"; break; -#endif -#endif -#ifdef SIGUSR1 +# endif +# endif +# ifdef SIGUSR1 case SIGUSR1: exception_str = "SIGUSR1"; break; -#endif -#ifdef SIGUSR2 +# endif +# ifdef SIGUSR2 case SIGUSR2: exception_str = "SIGUSR2"; break; -#endif -#ifdef SIGPIPE +# endif +# ifdef SIGPIPE case SIGPIPE: exception_str = "SIGPIPE"; break; -#endif -#ifdef SIGALRM +# endif +# ifdef SIGALRM case SIGALRM: exception_str = "SIGALRM"; break; -#endif -#ifdef SIGSTKFLT +# endif +# ifdef SIGSTKFLT case SIGSTKFLT: exception_str = "SIGSTKFLT"; break; -#endif -#ifdef SIGCHLD +# endif +# ifdef SIGCHLD case SIGCHLD: exception_str = "SIGCHLD"; break; -#elif defined(SIGCLD) +# elif defined(SIGCLD) case SIGCLD: exception_str = "SIGCLD"; break; -#endif -#ifdef SIGCONT +# endif +# ifdef SIGCONT case SIGCONT: exception_str = "SIGCONT"; break; -#endif -#ifdef SIGSTOP +# endif +# ifdef SIGSTOP case SIGSTOP: exception_str = "SIGSTOP"; break; -#endif -#ifdef SIGTSTP +# endif +# ifdef SIGTSTP case SIGTSTP: exception_str = "SIGTSTP"; break; -#endif -#ifdef SIGTTIN +# endif +# ifdef SIGTTIN case SIGTTIN: exception_str = "SIGTTIN"; break; -#endif -#ifdef SIGTTOU +# endif +# ifdef SIGTTOU case SIGTTOU: exception_str = "SIGTTOU"; break; -#endif -#ifdef SIGURG +# endif +# ifdef SIGURG case SIGURG: exception_str = "SIGURG"; break; -#endif -#ifdef SIGXCPU +# endif +# ifdef SIGXCPU case SIGXCPU: exception_str = "SIGXCPU"; break; -#endif -#ifdef SIGXFSZ +# endif +# ifdef SIGXFSZ case SIGXFSZ: exception_str = "SIGXFSZ"; break; -#endif -#ifdef SIGVTALRM +# endif +# ifdef SIGVTALRM case SIGVTALRM: exception_str = "SIGVTALRM"; break; -#endif -#ifdef SIGPROF +# endif +# ifdef SIGPROF case SIGPROF: exception_str = "SIGPROF"; break; -#endif -#ifdef SIGWINCH +# endif +# ifdef SIGWINCH case SIGWINCH: exception_str = "SIGWINCH"; break; -#endif -#ifdef SIGPOLL +# endif +# ifdef SIGPOLL case SIGPOLL: exception_str = "SIGPOLL"; break; -#endif -#ifdef SIGIO -#if !defined(SIGPOLL) || SIGIO != SIGPOLL +# endif +# ifdef SIGIO +# if !defined(SIGPOLL) || SIGIO != SIGPOLL case SIGIO: exception_str = "SIGIO"; break; -#endif -#endif -#ifdef SIGPWR +# endif +# endif +# ifdef SIGPWR case SIGPWR: exception_str = "SIGPWR"; break; -#endif -#ifdef SIGSYS +# endif +# ifdef SIGSYS case SIGSYS: exception_str = "SIGSYS"; break; -#endif -#ifdef SIGUNUSED -#if !defined(SIGSYS) || SIGUNUSED != SIGSYS +# endif +# ifdef SIGUNUSED +# if !defined(SIGSYS) || SIGUNUSED != SIGSYS case SIGUNUSED: exception_str = "SIGUNUSED"; break; -#endif -#endif +# endif +# endif default: exception_str = "Signal "; exception_str += std::to_string(this->Signal); diff --git a/Source/CTest/cmProcess.h b/Source/CTest/cmProcess.h index 20e24b9d2..b2d87fab3 100644 --- a/Source/CTest/cmProcess.h +++ b/Source/CTest/cmProcess.h @@ -36,7 +36,7 @@ public: void ChangeTimeout(cmDuration t); void ResetStartTime(); // Return true if the process starts - bool StartProcess(uv_loop_t& loop); + bool StartProcess(uv_loop_t& loop, std::vector<size_t>* affinity); enum class State { |