From d4adde13d7d507f5896b8c7912e46bbbcb71b539 Mon Sep 17 00:00:00 2001 From: Zach Mullen Date: Thu, 3 Sep 2009 15:33:44 -0400 Subject: [PATCH] Allowed tests to pull more than one line of output in their quantum. Fixed uninitialized variables in the case that the test process could not start. --- Source/CTest/cmCTestMultiProcessHandler.cxx | 5 +- Source/CTest/cmCTestRunTest.cxx | 54 +++++--- Source/CTest/cmCTestRunTest.h | 2 +- Source/CTest/cmProcess.cxx | 131 ++++++++++---------- Source/CTest/cmProcess.h | 5 +- 5 files changed, 104 insertions(+), 93 deletions(-) diff --git a/Source/CTest/cmCTestMultiProcessHandler.cxx b/Source/CTest/cmCTestMultiProcessHandler.cxx index f0d926cdd..9fc4c079f 100644 --- a/Source/CTest/cmCTestMultiProcessHandler.cxx +++ b/Source/CTest/cmCTestMultiProcessHandler.cxx @@ -100,7 +100,8 @@ void cmCTestMultiProcessHandler::StartTestProcess(int test) } else { - testRun->EndTest(this->Completed, this->Total); + this->Completed++; + testRun->EndTest(this->Completed, this->Total, false); } } @@ -209,7 +210,7 @@ bool cmCTestMultiProcessHandler::CheckOutput() cmCTestRunTest* p = *i; int test = p->GetIndex(); - if(p->EndTest(this->Completed, this->Total)) + if(p->EndTest(this->Completed, this->Total, true)) { this->Passed->push_back(p->GetTestProperties()->Name); } diff --git a/Source/CTest/cmCTestRunTest.cxx b/Source/CTest/cmCTestRunTest.cxx index 81dff52d8..85e8601d2 100644 --- a/Source/CTest/cmCTestRunTest.cxx +++ b/Source/CTest/cmCTestRunTest.cxx @@ -38,25 +38,36 @@ bool cmCTestRunTest::IsRunning() void cmCTestRunTest::CheckOutput() { std::string out, err; - int pipe = this->TestProcess->CheckOutput(.1, out, err); - if(pipe == cmsysProcess_Pipe_STDOUT) + int pipe = this->TestProcess->CheckOutput(.1); + //start our timeout for reading the process output + double clock_start = cmSystemTools::GetTime(); + while(this->TestProcess->GetNextOutputLine(out, err)) { - cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT, - this->GetIndex() << ": " << out << std::endl); - this->ProcessOutput += out; - this->ProcessOutput += "\n"; - } - else if(pipe == cmsysProcess_Pipe_STDERR) - { - cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT, - this->GetIndex() << ": " << err << std::endl); - this->ProcessOutput += err; - this->ProcessOutput += "\n"; + + if(pipe == cmsysProcess_Pipe_STDOUT) + { + cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT, + this->GetIndex() << ": " << out << std::endl); + this->ProcessOutput += out; + this->ProcessOutput += "\n"; + } + else if(pipe == cmsysProcess_Pipe_STDERR) + { + cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT, + this->GetIndex() << ": " << err << std::endl); + this->ProcessOutput += err; + this->ProcessOutput += "\n"; + } + //timeout while reading process output (could denote infinite output) + if(cmSystemTools::GetTime() - clock_start > .1) + { + break; + } } } //--------------------------------------------------------- -bool cmCTestRunTest::EndTest(size_t completed, size_t total) +bool cmCTestRunTest::EndTest(size_t completed, size_t total, bool started) { //restore the old environment if (this->ModifyEnv) @@ -240,12 +251,14 @@ bool cmCTestRunTest::EndTest(size_t completed, size_t total) << "----------------------------------------------------------" << std::endl << std::endl; } - this->TestResult.Output = this->ProcessOutput; - this->TestResult.ReturnValue = this->TestProcess->GetExitValue(); - this->TestResult.CompletionStatus = "Completed"; - this->TestResult.ExecutionTime = this->TestProcess->GetTotalTime(); - this->TestHandler->TestResults.push_back( this->TestResult ); - + if(started) + { + this->TestResult.Output = this->ProcessOutput; + this->TestResult.ReturnValue = this->TestProcess->GetExitValue(); + this->TestResult.CompletionStatus = "Completed"; + this->TestResult.ExecutionTime = this->TestProcess->GetTotalTime(); + this->TestHandler->TestResults.push_back( this->TestResult ); + } this->MemCheckPostProcess(); delete this->TestProcess; @@ -290,6 +303,7 @@ bool cmCTestRunTest::StartTest() this->TestResult.Properties = this->TestProperties; this->TestResult.ExecutionTime = 0; this->TestResult.ReturnValue = -1; + this->TestResult.CompletionStatus = "Not Run"; this->TestResult.Status = cmCTestTestHandler::NOT_RUN; this->TestResult.TestCount = this->TestProperties->Index; this->TestResult.Name = this->TestProperties->Name; diff --git a/Source/CTest/cmCTestRunTest.h b/Source/CTest/cmCTestRunTest.h index 8248b1793..2895dbb63 100644 --- a/Source/CTest/cmCTestRunTest.h +++ b/Source/CTest/cmCTestRunTest.h @@ -56,7 +56,7 @@ public: //launch the test process, return whether it started correctly bool StartTest(); //capture and report the test results - bool EndTest(size_t completed, size_t total); + bool EndTest(size_t completed, size_t total, bool started); //Called by ctest -N to log the command string void ComputeArguments(); private: diff --git a/Source/CTest/cmProcess.cxx b/Source/CTest/cmProcess.cxx index 75db654ed..a44868403 100644 --- a/Source/CTest/cmProcess.cxx +++ b/Source/CTest/cmProcess.cxx @@ -68,72 +68,80 @@ bool cmProcess::StartProcess() return (cmsysProcess_GetState(this->Process) == cmsysProcess_State_Executing); } - -// return true if there is a new line of data -// return false if there is no new data -int cmProcess::CheckOutput(double timeout, - std::string& stdOutLine, + +bool cmProcess::GetNextOutputLine(std::string& stdOutLine, std::string& stdErrLine) { + if(this->StdErrorBuffer.empty() && this->StdOutBuffer.empty()) + { + return false; + } stdOutLine = ""; stdErrLine = ""; std::vector::iterator outiter = this->StdOutBuffer.begin(); std::vector::iterator erriter = this->StdErrorBuffer.begin(); + // Check for a newline in stdout. + for(;outiter != this->StdOutBuffer.end(); ++outiter) + { + if((*outiter == '\r') && ((outiter+1) == this->StdOutBuffer.end())) + { + break; + } + else if(*outiter == '\n' || *outiter == '\0') + { + int length = outiter-this->StdOutBuffer.begin(); + if(length > 1 && *(outiter-1) == '\r') + { + --length; + } + if(length > 0) + { + stdOutLine.append(&this->StdOutBuffer[0], length); + } + this->StdOutBuffer.erase(this->StdOutBuffer.begin(), outiter+1); + this->LastOutputPipe = cmsysProcess_Pipe_STDOUT; + return true; + } + } + + // Check for a newline in stderr. + for(;erriter != this->StdErrorBuffer.end(); ++erriter) + { + if((*erriter == '\r') && ((erriter+1) == this->StdErrorBuffer.end())) + { + break; + } + else if(*erriter == '\n' || *erriter == '\0') + { + int length = erriter-this->StdErrorBuffer.begin(); + if(length > 1 && *(erriter-1) == '\r') + { + --length; + } + if(length > 0) + { + stdErrLine.append(&this->StdErrorBuffer[0], length); + } + this->StdErrorBuffer.erase(this->StdErrorBuffer.begin(), erriter+1); + this->LastOutputPipe = cmsysProcess_Pipe_STDERR; + return true; + } + } + //If we get here, we have stuff waiting in the buffers, but no newline + return false; +} +// return true if there is a new line of data +// return false if there is no new data +int cmProcess::CheckOutput(double timeout) +{ + // Wait for data from the process. + int length; + char* data; + while(1) { - // Check for a newline in stdout. - for(;outiter != this->StdOutBuffer.end(); ++outiter) - { - if((*outiter == '\r') && ((outiter+1) == this->StdOutBuffer.end())) - { - break; - } - else if(*outiter == '\n' || *outiter == '\0') - { - int length = outiter-this->StdOutBuffer.begin(); - if(length > 1 && *(outiter-1) == '\r') - { - --length; - } - if(length > 0) - { - stdOutLine.append(&this->StdOutBuffer[0], length); - } - this->StdOutBuffer.erase(this->StdOutBuffer.begin(), outiter+1); - this->LastOutputPipe = cmsysProcess_Pipe_STDOUT; - return this->LastOutputPipe;; - } - } - - // Check for a newline in stderr. - for(;erriter != this->StdErrorBuffer.end(); ++erriter) - { - if((*erriter == '\r') && ((erriter+1) == this->StdErrorBuffer.end())) - { - break; - } - else if(*erriter == '\n' || *erriter == '\0') - { - int length = erriter-this->StdErrorBuffer.begin(); - if(length > 1 && *(erriter-1) == '\r') - { - --length; - } - if(length > 0) - { - stdErrLine.append(&this->StdErrorBuffer[0], length); - } - this->StdErrorBuffer.erase(this->StdErrorBuffer.begin(), erriter+1); - this->LastOutputPipe = cmsysProcess_Pipe_STDERR; - return this->LastOutputPipe; - } - } - - // No newlines found. Wait for more data from the process. - int length; - char* data; int pipe = cmsysProcess_WaitForData(this->Process, &data, &length, &timeout); if(pipe == cmsysProcess_Pipe_Timeout) @@ -147,7 +155,6 @@ int cmProcess::CheckOutput(double timeout, // Append to the stdout buffer. std::vector::size_type size = this->StdOutBuffer.size(); this->StdOutBuffer.insert(this->StdOutBuffer.end(), data, data+length); - outiter = this->StdOutBuffer.begin()+size; } else if(pipe == cmsysProcess_Pipe_STDERR) { @@ -155,26 +162,17 @@ int cmProcess::CheckOutput(double timeout, std::vector::size_type size = this->StdErrorBuffer.size(); this->StdErrorBuffer.insert(this->StdErrorBuffer.end(), data, data+length); - erriter = this->StdErrorBuffer.begin()+size; } else if(pipe == cmsysProcess_Pipe_None) { // Both stdout and stderr pipes have broken. Return leftover data. if(!this->StdOutBuffer.empty()) { - stdOutLine.append(&this->StdOutBuffer[0], - outiter-this->StdOutBuffer.begin()); - this->StdOutBuffer.erase(this->StdOutBuffer.begin(), - this->StdOutBuffer.end()); this->LastOutputPipe = cmsysProcess_Pipe_STDOUT; return this->LastOutputPipe; } else if(!this->StdErrorBuffer.empty()) { - stdErrLine.append(&this->StdErrorBuffer[0], - erriter-this->StdErrorBuffer.begin()); - this->StdErrorBuffer.erase(this->StdErrorBuffer.begin(), - this->StdErrorBuffer.end()); this->LastOutputPipe = cmsysProcess_Pipe_STDERR; return this->LastOutputPipe; } @@ -187,7 +185,6 @@ int cmProcess::CheckOutput(double timeout, } } - // return the process status int cmProcess::GetProcessStatus() { diff --git a/Source/CTest/cmProcess.h b/Source/CTest/cmProcess.h index 8b943c09e..9def3908f 100644 --- a/Source/CTest/cmProcess.h +++ b/Source/CTest/cmProcess.h @@ -41,9 +41,7 @@ public: bool StartProcess(); // return process state - int CheckOutput(double timeout, - std::string& stdOutLine, - std::string& stdErrLine); + int CheckOutput(double timeout); // return the process status int GetProcessStatus(); // return true if the process is running @@ -54,6 +52,7 @@ public: void SetId(int id) { this->Id = id;} int GetExitValue() { return this->ExitValue;} double GetTotalTime() { return this->TotalTime;} + bool GetNextOutputLine(std::string& stdOutLine, std::string& stdErrLine); private: int LastOutputPipe; double Timeout;