summaryrefslogtreecommitdiffstats
path: root/Source
diff options
context:
space:
mode:
authorAndy Cedilnik <andy.cedilnik@kitware.com>2005-06-14 15:42:53 (GMT)
committerAndy Cedilnik <andy.cedilnik@kitware.com>2005-06-14 15:42:53 (GMT)
commita95a4b000db076d7a7c1dff163508b1922344339 (patch)
treebcb6f47e078359cca656cf44b021d337cff5e21d /Source
parent02f12a82be59f44b640ed86da39eaf469025a2be (diff)
downloadCMake-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.cxx42
-rw-r--r--Source/CTest/cmCTestUpdateHandler.cxx47
-rw-r--r--Source/cmCTest.cxx107
-rw-r--r--Source/cmCTest.h26
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);