diff options
author | Andy Cedilnik <andy.cedilnik@kitware.com> | 2005-06-14 15:42:53 (GMT) |
---|---|---|
committer | Andy Cedilnik <andy.cedilnik@kitware.com> | 2005-06-14 15:42:53 (GMT) |
commit | a95a4b000db076d7a7c1dff163508b1922344339 (patch) | |
tree | bcb6f47e078359cca656cf44b021d337cff5e21d /Source | |
parent | 02f12a82be59f44b640ed86da39eaf469025a2be (diff) | |
download | CMake-a95a4b000db076d7a7c1dff163508b1922344339.zip CMake-a95a4b000db076d7a7c1dff163508b1922344339.tar.gz CMake-a95a4b000db076d7a7c1dff163508b1922344339.tar.bz2 |
ENH: Separate standard output and standard error for problematic commands
Diffstat (limited to 'Source')
-rw-r--r-- | Source/CTest/cmCTestCoverageHandler.cxx | 42 | ||||
-rw-r--r-- | Source/CTest/cmCTestUpdateHandler.cxx | 47 | ||||
-rw-r--r-- | Source/cmCTest.cxx | 107 | ||||
-rw-r--r-- | Source/cmCTest.h | 26 |
4 files changed, 200 insertions, 22 deletions
diff --git a/Source/CTest/cmCTestCoverageHandler.cxx b/Source/CTest/cmCTestCoverageHandler.cxx index f5cc3eb..31b1bb1 100644 --- a/Source/CTest/cmCTestCoverageHandler.cxx +++ b/Source/CTest/cmCTestCoverageHandler.cxx @@ -155,6 +155,15 @@ int cmCTestCoverageHandler::ProcessHandler() std::string binaryDir = m_CTest->GetCTestConfiguration("BuildDirectory"); std::string gcovCommand = m_CTest->GetCTestConfiguration("CoverageCommand"); + cmGeneratedFileStream ofs; + double elapsed_time_start = cmSystemTools::GetTime(); + if ( !m_CTest->OpenOutputFile("Temporary", "LastCoverage.log", ofs) ) + { + cmCTestLog(m_CTest, ERROR_MESSAGE, "Cannot create LastCoverage.log file" << std::endl); + } + + ofs << "Performing coverage: " << elapsed_time_start << std::endl; + cmSystemTools::ConvertToUnixSlashes(sourceDir); cmSystemTools::ConvertToUnixSlashes(binaryDir); @@ -165,7 +174,6 @@ int cmCTestCoverageHandler::ProcessHandler() std::string gcovOutputRex2 = "^Creating (.*\\.gcov)\\."; cmCTestLog(m_CTest, HANDLER_OUTPUT, "Performing coverage" << std::endl); - double elapsed_time_start = cmSystemTools::GetTime(); std::string coverage_start_time = m_CTest->CurrentTime(); @@ -204,19 +212,26 @@ int cmCTestCoverageHandler::ProcessHandler() std::string command = "\"" + gcovCommand + "\" -l -o \"" + fileDir + "\" \"" + *it + "\""; cmCTestLog(m_CTest, HANDLER_VERBOSE_OUTPUT, command.c_str() << std::endl); std::string output = ""; + std::string errors = ""; int retVal = 0; - int res = cmSystemTools::RunSingleCommand(command.c_str(), &output, - &retVal, tempDir.c_str(), - false, 0 /*m_TimeOut*/); + ofs << "* Run coverage for: " << fileDir.c_str() << std::endl; + ofs << " Command: " << command.c_str() << std::endl; + int res = m_CTest->RunCommand(command.c_str(), &output, &errors, + &retVal, tempDir.c_str(), 0 /*m_TimeOut*/); + + ofs << " Output: " << output.c_str() << std::endl; + ofs << " Errors: " << errors.c_str() << std::endl; if ( ! res ) { cmCTestLog(m_CTest, ERROR_MESSAGE, "Problem running coverage on file: " << it->c_str() << std::endl); + cmCTestLog(m_CTest, ERROR_MESSAGE, "Command produced error: " << error << std::endl); error ++; continue; } if ( retVal != 0 ) { cmCTestLog(m_CTest, ERROR_MESSAGE, "Coverage command returned: " << retVal << " while processing: " << it->c_str() << std::endl); + cmCTestLog(m_CTest, ERROR_MESSAGE, "Command produced error: " << error << std::endl); } std::vector<cmStdString> lines; std::vector<cmStdString>::iterator line; @@ -232,7 +247,8 @@ int cmCTestCoverageHandler::ProcessHandler() file.substr(0, sourceDir.size()) == sourceDir && file[sourceDir.size()] == '/' ) { - cmCTestLog(m_CTest, HANDLER_VERBOSE_OUTPUT, " produced s: " << file << std::endl); + cmCTestLog(m_CTest, HANDLER_VERBOSE_OUTPUT, " produced s: " << file.c_str() << std::endl); + ofs << " produced in source dir: " << file.c_str() << std::endl; cfile = file; } // Binary dir? @@ -240,7 +256,8 @@ int cmCTestCoverageHandler::ProcessHandler() file.substr(0, binaryDir.size()) == binaryDir && file[binaryDir.size()] == '/' ) { - cmCTestLog(m_CTest, HANDLER_VERBOSE_OUTPUT, " produce b: " << file << std::endl); + cmCTestLog(m_CTest, HANDLER_VERBOSE_OUTPUT, " produce b: " << file.c_str() << std::endl); + ofs << " produced in binary dir: " << file.c_str() << std::endl; cfile = file; } if ( cfile.empty() ) @@ -249,6 +266,9 @@ int cmCTestCoverageHandler::ProcessHandler() cmCTestLog(m_CTest, ERROR_MESSAGE, "File: [" << file << "]" << std::endl); cmCTestLog(m_CTest, ERROR_MESSAGE, "s: [" << file.substr(0, sourceDir.size()) << "]" << std::endl); cmCTestLog(m_CTest, ERROR_MESSAGE, "b: [" << file.substr(0, binaryDir.size()) << "]" << std::endl); + ofs << " Something went wrong. Cannot find: " << file.c_str() + << " in source dir: " << sourceDir.c_str() + << " or binary dir: " << binaryDir.c_str() << std::endl; } } else if ( re2.find(line->c_str() ) ) @@ -258,6 +278,7 @@ int cmCTestCoverageHandler::ProcessHandler() { singleFileCoverageVector* vec = &totalCoverage[cfile]; cmCTestLog(m_CTest, HANDLER_VERBOSE_OUTPUT, " in file: " << fname << std::endl); + ofs << " In file: " << fname << std::endl; std::ifstream ifile(fname.c_str()); if ( ! ifile ) { @@ -299,6 +320,7 @@ int cmCTestCoverageHandler::ProcessHandler() else { cmCTestLog(m_CTest, ERROR_MESSAGE, "Unknown line: " << line->c_str() << std::endl); + ofs << " Unknown line: " << line->c_str() << std::endl; error ++; } } @@ -476,6 +498,14 @@ int cmCTestCoverageHandler::ProcessHandler() << std::setprecision(2) << (percent_coverage) << "%" << std::endl); + ofs << "\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; + cmSystemTools::ChangeDirectory(currentDirectory.c_str()); if ( error ) diff --git a/Source/CTest/cmCTestUpdateHandler.cxx b/Source/CTest/cmCTestUpdateHandler.cxx index 6799a80..8b34ecb 100644 --- a/Source/CTest/cmCTestUpdateHandler.cxx +++ b/Source/CTest/cmCTestUpdateHandler.cxx @@ -308,6 +308,7 @@ int cmCTestUpdateHandler::ProcessHandler() int svn_use_status = 0; std::string goutput; + std::string errors; int retVal = 0; bool res = true; @@ -320,9 +321,13 @@ int cmCTestUpdateHandler::ProcessHandler() cmCTestLog(m_CTest, HANDLER_VERBOSE_OUTPUT, "* Get repository information: " << command.c_str() << std::endl); if ( !m_CTest->GetShowOnly() ) { - res = cmSystemTools::RunSingleCommand(command.c_str(), &goutput, - &retVal, sourceDirectory, - m_HandlerVerbose, 0 /*m_TimeOut*/); + ofs << "* Get repository information" << std::endl; + ofs << " Command: " << command.c_str() << std::endl; + res = m_CTest->RunCommand(command.c_str(), &goutput, &errors, + &retVal, sourceDirectory, 0 /*m_TimeOut*/); + + ofs << " Output: " << goutput.c_str() << std::endl; + ofs << " Errors: " << errors.c_str() << std::endl; if ( ofs ) { ofs << "--- Update information ---" << std::endl; @@ -373,22 +378,31 @@ int cmCTestUpdateHandler::ProcessHandler() case cmCTestUpdateHandler::e_CVS: command = updateCommand + " -z3 update " + updateOptions + " " + extra_update_opts; - res = cmSystemTools::RunSingleCommand(command.c_str(), &goutput, - &retVal, sourceDirectory, - m_HandlerVerbose, 0 /*m_TimeOut*/); + ofs << "* Update repository: " << std::endl; + ofs << " Command: " << command.c_str() << std::endl; + res = m_CTest->RunCommand(command.c_str(), &goutput, &errors, + &retVal, sourceDirectory, 0 /*m_TimeOut*/); + ofs << " Output: " << goutput.c_str() << std::endl; + ofs << " Errors: " << errors.c_str() << std::endl; break; case cmCTestUpdateHandler::e_SVN: { std::string partialOutput; command = updateCommand + " update " + updateOptions + " " + extra_update_opts; - bool res1 = cmSystemTools::RunSingleCommand(command.c_str(), &partialOutput, - &retVal, sourceDirectory, - m_HandlerVerbose, 0 /*m_TimeOut*/); + ofs << "* Update repository: " << std::endl; + ofs << " Command: " << command.c_str() << std::endl; + bool res1 = m_CTest->RunCommand(command.c_str(), &partialOutput, &errors, + &retVal, sourceDirectory, 0 /*m_TimeOut*/); + ofs << " Output: " << partialOutput.c_str() << std::endl; + ofs << " Errors: " << errors.c_str() << std::endl; command = updateCommand + " status"; - res = cmSystemTools::RunSingleCommand(command.c_str(), &partialOutput, - &retVal, sourceDirectory, - m_HandlerVerbose, 0 /*m_TimeOut*/); + ofs << "* Status repository: " << std::endl; + ofs << " Command: " << command.c_str() << std::endl; + res = m_CTest->RunCommand(command.c_str(), &partialOutput, &errors, + &retVal, sourceDirectory, 0 /*m_TimeOut*/); + ofs << " Output: " << partialOutput.c_str() << std::endl; + ofs << " Errors: " << errors.c_str() << std::endl; goutput += partialOutput; res = res && res1; } @@ -505,9 +519,12 @@ int cmCTestUpdateHandler::ProcessHandler() } cmCTestLog(m_CTest, DEBUG, "Do log: " << logcommand << std::endl); cmCTestLog(m_CTest, HANDLER_VERBOSE_OUTPUT, "* Get file update information: " << logcommand.c_str() << std::endl); - res = cmSystemTools::RunSingleCommand(logcommand.c_str(), &output, - &retVal, sourceDirectory, - m_HandlerVerbose, 0 /*m_TimeOut*/); + ofs << "* Get log information for file: " << file << std::endl; + ofs << " Command: " << logcommand.c_str() << std::endl; + res = m_CTest->RunCommand(logcommand.c_str(), &output, &errors, + &retVal, sourceDirectory, 0 /*m_TimeOut*/); + ofs << " Output: " << output.c_str() << std::endl; + ofs << " Errors: " << errors.c_str() << std::endl; if ( ofs ) { ofs << output << std::endl; diff --git a/Source/cmCTest.cxx b/Source/cmCTest.cxx index 5f72a06..fe06804 100644 --- a/Source/cmCTest.cxx +++ b/Source/cmCTest.cxx @@ -1786,6 +1786,113 @@ bool cmCTest::SetCTestConfigurationFromCMakeVariable(cmMakefile* mf, const char* return true; } +bool cmCTest::RunCommand( + const char* command, + std::string* stdOut, + std::string* stdErr, + int *retVal, + const char* dir, + double timeout) +{ + std::vector<cmStdString> args = cmSystemTools::ParseArguments(command); + + if(args.size() < 1) + { + return false; + } + + std::vector<const char*> argv; + for(std::vector<cmStdString>::const_iterator a = args.begin(); + a != args.end(); ++a) + { + argv.push_back(a->c_str()); + } + argv.push_back(0); + + *stdOut = ""; + *stdErr = ""; + + cmsysProcess* cp = cmsysProcess_New(); + cmsysProcess_SetCommand(cp, &*argv.begin()); + cmsysProcess_SetWorkingDirectory(cp, dir); + if(cmSystemTools::GetRunCommandHideConsole()) + { + cmsysProcess_SetOption(cp, cmsysProcess_Option_HideWindow, 1); + } + cmsysProcess_SetTimeout(cp, timeout); + cmsysProcess_Execute(cp); + + std::vector<char> tempOutput; + std::vector<char> tempError; + char* data; + int length; + int res; + bool done = false; + while(!done) + { + res = cmsysProcess_WaitForData(cp, &data, &length, 0); + switch ( res ) + { + case cmsysProcess_Pipe_STDOUT: + tempOutput.insert(tempOutput.end(), data, data+length); + break; + case cmsysProcess_Pipe_STDERR: + tempError.insert(tempError.end(), data, data+length); + break; + default: + done = true; + } + if(m_ExtraVerbose) + { + cmSystemTools::Stdout(data, length); + } + } + + cmsysProcess_WaitForExit(cp, 0); + stdOut->append(&*tempOutput.begin(), tempOutput.size()); + stdErr->append(&*tempError.begin(), tempError.size()); + + bool result = true; + if(cmsysProcess_GetState(cp) == cmsysProcess_State_Exited) + { + if ( retVal ) + { + *retVal = cmsysProcess_GetExitValue(cp); + } + else + { + if ( cmsysProcess_GetExitValue(cp) != 0 ) + { + result = false; + } + } + } + else if(cmsysProcess_GetState(cp) == cmsysProcess_State_Exception) + { + const char* exception_str = cmsysProcess_GetExceptionString(cp); + cmCTestLog(this, ERROR_MESSAGE, exception_str << std::endl); + stdErr->append(exception_str, strlen(exception_str)); + result = false; + } + else if(cmsysProcess_GetState(cp) == cmsysProcess_State_Error) + { + const char* error_str = cmsysProcess_GetErrorString(cp); + cmCTestLog(this, ERROR_MESSAGE, error_str << std::endl); + stdErr->append(error_str, strlen(error_str)); + result = false; + } + else if(cmsysProcess_GetState(cp) == cmsysProcess_State_Expired) + { + const char* error_str = "Process terminated due to timeout\n"; + cmCTestLog(this, ERROR_MESSAGE, error_str << std::endl); + stdErr->append(error_str, strlen(error_str)); + result = false; + } + + cmsysProcess_Delete(cp); + return result; +} + //---------------------------------------------------------------------- void cmCTest::SetOutputLogFileName(const char* name) { diff --git a/Source/cmCTest.h b/Source/cmCTest.h index bb5cf4c..e49bd0b 100644 --- a/Source/cmCTest.h +++ b/Source/cmCTest.h @@ -140,7 +140,31 @@ public: ///! Should we only show what we would do? bool GetShowOnly(); - + + /** + * Run a single executable command and put the stdout and stderr + * in output. + * + * If verbose is false, no user-viewable output from the program + * being run will be generated. + * + * If timeout is specified, the command will be terminated after + * timeout expires. Timeout is specified in seconds. + * + * Argument retVal should be a pointer to the location where the + * exit code will be stored. If the retVal is not specified and + * the program exits with a code other than 0, then the this + * function will return false. + * + * If the command has spaces in the path the caller MUST call + * cmSystemTools::ConvertToRunCommandPath on the command before passing + * it into this function or it will not work. The command must be correctly + * escaped for this to with spaces. + */ + bool RunCommand(const char* command, + std::string* stdOut, std::string* stdErr, + int* retVal = 0, const char* dir = 0, double timeout = 0.0); + //! Start CTest XML output file void StartXML(std::ostream& ostr); |