diff --git a/Source/cmCTest.cxx b/Source/cmCTest.cxx index 52e75d367..f2fcd6166 100644 --- a/Source/cmCTest.cxx +++ b/Source/cmCTest.cxx @@ -1685,6 +1685,7 @@ void cmCTest::ProcessDirectory(std::vector &passed, } cmCTestTestResult cres; + cres.m_Status = cmCTest::NOT_RUN; if (firstTest) { @@ -1737,11 +1738,10 @@ void cmCTest::ProcessDirectory(std::vector &passed, { std::cout << std::endl << "Test command: " << testCommand << std::endl; } - bool res = true; + int res = 0; if ( !m_ShowOnly ) { - res = cmSystemTools::RunSingleCommand(testCommand.c_str(), &output, - &retVal, 0, false, m_TimeOut); + res = this->RunTest(testCommand.c_str(), &output, &retVal); } clock_finish = cmSystemTools::GetTime(); @@ -1750,41 +1750,63 @@ void cmCTest::ProcessDirectory(std::vector &passed, if ( !m_ShowOnly ) { - if (!res || retVal != 0) + if (res == cmsysProcess_State_Exited && retVal ) { - fprintf(stderr,"***Failed\n"); - if (output != "") - { - if (dartStuff.find(output.c_str())) - { - std::string dartString = dartStuff.match(1); - cmSystemTools::ReplaceString(output, dartString.c_str(),""); - cres.m_RegressionImages = this->GenerateRegressionImages(dartString); - } - if (output != "" && m_Verbose) - { - std::cerr << output.c_str() << "\n"; - } - } - failed.push_back(args[0].Value); + fprintf(stderr," Passed\n"); + passed.push_back(args[0].Value); } else { - fprintf(stderr," Passed\n"); - if (output != "") + if ( res == cmsysProcess_State_Expired ) { - if (dartStuff.find(output.c_str())) + fprintf(stderr,"***Timeout\n"); + cres.m_Status = cmCTest::TIMEOUT; + } + else if ( res == cmsysProcess_State_Exception ) + { + fprintf(stderr,"***Exception: "); + switch ( retVal ) { - std::string dartString = dartStuff.match(1); - cmSystemTools::ReplaceString(output, dartString.c_str(),""); - cres.m_RegressionImages = this->GenerateRegressionImages(dartString); - } - if (output != "" && m_Verbose) - { - std::cerr << output.c_str() << "\n"; + case cmsysProcess_Exception_Fault: + fprintf(stderr,"SegFault"); + cres.m_Status = cmCTest::SEGFAULT; + break; + case cmsysProcess_Exception_Illegal: + fprintf(stderr,"SegFault"); + cres.m_Status = cmCTest::ILLEGAL; + break; + case cmsysProcess_Exception_Interrupt: + fprintf(stderr,"SegFault"); + cres.m_Status = cmCTest::INTERRUPT; + break; + case cmsysProcess_Exception_Numerical: + fprintf(stderr,"SegFault"); + cres.m_Status = cmCTest::NUMERICAL; + break; + default: + fprintf(stderr,"Other"); + cres.m_Status = cmCTest::OTHER_FAULT; } } - passed.push_back(args[0].Value); + else if ( res == cmsysProcess_State_Error ) + { + fprintf(stderr,"***Bad command\n"); + cres.m_Status = cmCTest::BAD_COMMAND; + } + else + { + fprintf(stderr,"***Failed\n"); + } + failed.push_back(args[0].Value); + } + if (output != "") + { + if (dartStuff.find(output.c_str())) + { + std::string dartString = dartStuff.match(1); + cmSystemTools::ReplaceString(output, dartString.c_str(),""); + cres.m_RegressionImages = this->GenerateRegressionImages(dartString); + } } } cres.m_Output = output; @@ -2018,7 +2040,7 @@ void cmCTest::GenerateDartTestOutput(std::ostream& os) for ( cc = 0; cc < m_TestResults.size(); cc ++ ) { cmCTestTestResult *result = &m_TestResults[cc]; - os << "\tm_ReturnValue?"failed":"passed") + os << "\tm_Status==cmCTest::COMPLETED?"passed":"failed") << "\">\n" << "\t\t" << this->MakeXMLSafe(result->m_Name) << "\n" << "\t\t" << this->MakeXMLSafe(result->m_Path) << "\n" @@ -2028,14 +2050,14 @@ void cmCTest::GenerateDartTestOutput(std::ostream& os) << this->MakeXMLSafe(result->m_FullCommandLine) << "\n" << "\t\t" << std::endl; - if ( result->m_ReturnValue ) + if ( result->m_Status != cmCTest::COMPLETED || result->m_ReturnValue ) { os << "\t\t\t" - << "CHILDSTATUS" << "\n" + << this->GetTestStatus(result->m_Status) << "\n" << "\t\t\t" << result->m_ReturnValue << "" << std::endl; - os << result->m_RegressionImages; } + os << result->m_RegressionImages; os << "\t\t\t" << result->m_ExecutionTime << "\n" @@ -2354,3 +2376,89 @@ bool cmCTest::RunMakeCommand(const char* command, std::string* output, return result; } +int cmCTest::RunTest( const char* command, std::string* output, int *retVal) +{ + std::vector args = cmSystemTools::ParseArguments(command); + + if(args.size() < 1) + { + return false; + } + + std::vector argv; + for(std::vector::const_iterator a = args.begin(); + a != args.end(); ++a) + { + argv.push_back(a->c_str()); + } + argv.push_back(0); + + if ( output ) + { + *output = ""; + } + + cmsysProcess* cp = cmsysProcess_New(); + cmsysProcess_SetCommand(cp, &*argv.begin()); + if(cmSystemTools::GetRunCommandHideConsole()) + { + cmsysProcess_SetOption(cp, cmsysProcess_Option_HideWindow, 1); + } + cmsysProcess_SetTimeout(cp, m_TimeOut); + cmsysProcess_Execute(cp); + + char* data; + int length; + while(cmsysProcess_WaitForData(cp, (cmsysProcess_Pipe_STDOUT | + cmsysProcess_Pipe_STDERR), + &data, &length, 0)) + { + if ( output ) + { + output->append(data, length); + } + } + + cmsysProcess_WaitForExit(cp, 0); + + int result = cmsysProcess_GetState(cp); + + if(result == cmsysProcess_State_Exited) + { + *retVal = cmsysProcess_GetExitValue(cp); + } + else if(result == cmsysProcess_State_Exception) + { + *retVal = cmsysProcess_GetExitException(cp); + } + else if(result == cmsysProcess_State_Error) + { + *output += "\n*** ERROR executing: "; + *output += cmsysProcess_GetErrorString(cp); + } + + cmsysProcess_Delete(cp); + + return result; +} + +const char* cmCTest::GetTestStatus(int status) +{ + static const char statuses[][100] = { + "Not Run", + "Timeout", + "SEGFAULT", + "ILLEGAL", + "INTERRUPT", + "NUMERICAL", + "OTHER_FAULT", + "BAD_COMMAND", + "Completed" + }; + + if ( status < cmCTest::NOT_RUN || status > cmCTest::COMPLETED ) + { + return "No Status"; + } + return statuses[status]; +} diff --git a/Source/cmCTest.h b/Source/cmCTest.h index fe26f5b60..78f5e5e59 100644 --- a/Source/cmCTest.h +++ b/Source/cmCTest.h @@ -141,6 +141,18 @@ private: LAST_TEST = 10 }; + enum { // Program statuses + NOT_RUN = 0, + TIMEOUT, + SEGFAULT, + ILLEGAL, + INTERRUPT, + NUMERICAL, + OTHER_FAULT, + BAD_COMMAND, + COMPLETED + }; + struct cmCTestTestResult { std::string m_Name; @@ -148,6 +160,7 @@ private: std::string m_FullCommandLine; double m_ExecutionTime; int m_ReturnValue; + int m_Status; std::string m_CompletionStatus; std::string m_Output; std::string m_RegressionImages; @@ -227,8 +240,10 @@ private: bool RunMakeCommand(const char* command, std::string* output, int* retVal, const char* dir, bool verbose, int timeout, std::ofstream& ofs); + int RunTest( const char* command, std::string* output, int *retVal); std::string GenerateRegressionImages(const std::string& xml); + const char* GetTestStatus(int status); }; #endif