BUG: Capture cout and cerr from internal ctest

When CTest detects that a test is running its own executable it
optimizes the test by using an internal instance of cmCTest instead of
creating a new process.  However, the internal instance was using cout
and cerr directly.  This redirects the output to a string stream to
avoid direct display of the internal test's output.
This commit is contained in:
Brad King 2009-01-05 14:14:10 -05:00
parent 86aeefc7c9
commit 2703d51b8f
2 changed files with 42 additions and 18 deletions

View File

@ -258,6 +258,7 @@ cmCTest::cmCTest()
this->OutputLogFileLastTag = -1; this->OutputLogFileLastTag = -1;
this->SuppressUpdatingCTestConfiguration = false; this->SuppressUpdatingCTestConfiguration = false;
this->DartVersion = 1; this->DartVersion = 1;
this->InitStreams();
int cc; int cc;
for ( cc=0; cc < cmCTest::LAST_TEST; cc ++ ) for ( cc=0; cc < cmCTest::LAST_TEST; cc ++ )
@ -1136,6 +1137,11 @@ int cmCTest::RunTest(std::vector<const char*> argv,
cmCTest inst; cmCTest inst;
inst.ConfigType = this->ConfigType; inst.ConfigType = this->ConfigType;
inst.TimeOut = timeout; inst.TimeOut = timeout;
// Capture output of the child ctest.
cmOStringStream oss;
inst.SetStreams(&oss, &oss);
std::vector<std::string> args; std::vector<std::string> args;
for(unsigned int i =0; i < argv.size(); ++i) for(unsigned int i =0; i < argv.size(); ++i)
{ {
@ -1166,6 +1172,7 @@ int cmCTest::RunTest(std::vector<const char*> argv,
} }
*retVal = inst.Run(args, output); *retVal = inst.Run(args, output);
*output += oss.str();
if ( log ) if ( log )
{ {
*log << output->c_str(); *log << output->c_str();
@ -2602,6 +2609,13 @@ static const char* cmCTestStringLogType[] =
(stream) << std::endl << file << ":" << line << " "; \ (stream) << std::endl << file << ":" << line << " "; \
} }
void cmCTest::InitStreams()
{
// By default we write output to the process output streams.
this->StreamOut = &std::cout;
this->StreamErr = &std::cerr;
}
void cmCTest::Log(int logType, const char* file, int line, const char* msg) void cmCTest::Log(int logType, const char* file, int line, const char* msg)
{ {
if ( !msg || !*msg ) if ( !msg || !*msg )
@ -2640,47 +2654,49 @@ void cmCTest::Log(int logType, const char* file, int line, const char* msg)
} }
if ( !this->Quiet ) if ( !this->Quiet )
{ {
std::ostream& out = *this->StreamOut;
std::ostream& err = *this->StreamErr;
switch ( logType ) switch ( logType )
{ {
case DEBUG: case DEBUG:
if ( this->Debug ) if ( this->Debug )
{ {
cmCTestLogOutputFileLine(std::cout); cmCTestLogOutputFileLine(out);
std::cout << msg; out << msg;
std::cout.flush(); out.flush();
} }
break; break;
case OUTPUT: case HANDLER_OUTPUT: case OUTPUT: case HANDLER_OUTPUT:
if ( this->Debug || this->Verbose ) if ( this->Debug || this->Verbose )
{ {
cmCTestLogOutputFileLine(std::cout); cmCTestLogOutputFileLine(out);
std::cout << msg; out << msg;
std::cout.flush(); out.flush();
} }
break; break;
case HANDLER_VERBOSE_OUTPUT: case HANDLER_VERBOSE_OUTPUT:
if ( this->Debug || this->ExtraVerbose ) if ( this->Debug || this->ExtraVerbose )
{ {
cmCTestLogOutputFileLine(std::cout); cmCTestLogOutputFileLine(out);
std::cout << msg; out << msg;
std::cout.flush(); out.flush();
} }
break; break;
case WARNING: case WARNING:
cmCTestLogOutputFileLine(std::cerr); cmCTestLogOutputFileLine(err);
std::cerr << msg; err << msg;
std::cerr.flush(); err.flush();
break; break;
case ERROR_MESSAGE: case ERROR_MESSAGE:
cmCTestLogOutputFileLine(std::cerr); cmCTestLogOutputFileLine(err);
std::cerr << msg; err << msg;
std::cerr.flush(); err.flush();
cmSystemTools::SetErrorOccured(); cmSystemTools::SetErrorOccured();
break; break;
default: default:
cmCTestLogOutputFileLine(std::cout); cmCTestLogOutputFileLine(out);
std::cout << msg; out << msg;
std::cout.flush(); out.flush();
} }
} }
} }

View File

@ -331,6 +331,10 @@ public:
bool GetVerbose() { return this->Verbose;} bool GetVerbose() { return this->Verbose;}
bool GetExtraVerbose() { return this->ExtraVerbose;} bool GetExtraVerbose() { return this->ExtraVerbose;}
/** Direct process output to given streams. */
void SetStreams(std::ostream* out, std::ostream* err)
{ this->StreamOut = out; this->StreamErr = err; }
private: private:
std::string ConfigType; std::string ConfigType;
bool Verbose; bool Verbose;
@ -402,6 +406,10 @@ private:
bool CompressXMLFiles; bool CompressXMLFiles;
void InitStreams();
std::ostream* StreamOut;
std::ostream* StreamErr;
void BlockTestErrorDiagnostics(); void BlockTestErrorDiagnostics();