[Cmake-commits] [cmake-commits] zach.mullen committed cmCTestRunTest.cxx NONE 1.1 cmCTestRunTest.h NONE 1.1 cmCTestTestHandler.cxx 1.103 1.104 cmCTestTestHandler.h 1.37 1.38

cmake-commits at cmake.org cmake-commits at cmake.org
Wed Aug 19 08:58:39 EDT 2009


Update of /cvsroot/CMake/CMake/Source/CTest
In directory public:/mounts/ram/cvs-serv12806/Source/CTest

Modified Files:
	cmCTestTestHandler.cxx cmCTestTestHandler.h 
Added Files:
	cmCTestRunTest.cxx cmCTestRunTest.h 
Log Message:
ENH: Refactored CTest test execution code into an object


Index: cmCTestTestHandler.cxx
===================================================================
RCS file: /cvsroot/CMake/CMake/Source/CTest/cmCTestTestHandler.cxx,v
retrieving revision 1.103
retrieving revision 1.104
diff -C 2 -d -r1.103 -r1.104
*** cmCTestTestHandler.cxx	18 Aug 2009 18:03:50 -0000	1.103
--- cmCTestTestHandler.cxx	19 Aug 2009 12:58:34 -0000	1.104
***************
*** 19,22 ****
--- 19,23 ----
  #include "cmCTestMultiProcessHandler.h"
  #include "cmCTest.h"
+ #include "cmCTestRunTest.h"
  #include "cmake.h"
  #include "cmGeneratedFileStream.h"
***************
*** 590,602 ****
          totalTestTime += result->ExecutionTime;
          }
!       this->PrintLabelSummary();
        char buf[1024];
        sprintf(buf, "%6.2f sec", totalTestTime); 
        cmCTestLog(this->CTest, HANDLER_OUTPUT, "\nTotal Test time = " 
                   <<  buf << "\n" );
!       if ( this->LogFile )
!         {
!         *this->LogFile << "\nTotal Test time = " << buf << std::endl;
!         }
        }
  
--- 591,600 ----
          totalTestTime += result->ExecutionTime;
          }
!       
        char buf[1024];
        sprintf(buf, "%6.2f sec", totalTestTime); 
        cmCTestLog(this->CTest, HANDLER_OUTPUT, "\nTotal Test time = " 
                   <<  buf << "\n" );
!       
        }
  
***************
*** 661,716 ****
  
  //----------------------------------------------------------------------
- void cmCTestTestHandler::PrintLabelSummary()
- {
-   cmCTestTestHandler::ListOfTests::iterator it = this->TestList.begin();
-   cmCTestTestHandler::TestResultsVector::iterator ri =
-     this->TestResults.begin(); 
-   std::map<cmStdString, double> labelTimes;
-   std::set<cmStdString> labels;
-   // initialize maps
-   for(; it != this->TestList.end(); ++it)
-     {
-     cmCTestTestProperties& p = *it;
-     if(p.Labels.size() != 0)
-       { 
-       for(std::vector<std::string>::iterator l = p.Labels.begin();
-           l !=  p.Labels.end(); ++l)
-         {
-         labels.insert(*l);
-         labelTimes[*l] = 0;
-         }
-       }
-     }
-   it = this->TestList.begin();
-   ri = this->TestResults.begin(); 
-   // fill maps
-   for(; it != this->TestList.end(); ++it, ++ri)
-     {
-     cmCTestTestProperties& p = *it;
-     cmCTestTestResult &result = *ri;
-     if(p.Labels.size() != 0)
-       { 
-       for(std::vector<std::string>::iterator l = p.Labels.begin();
-           l !=  p.Labels.end(); ++l)
-         {
-         labelTimes[*l] += result.ExecutionTime;
-         }
-       }
-     }
-   // now print times
-   for(std::set<cmStdString>::const_iterator i = labels.begin();
-       i != labels.end(); ++i)
-     {
-     cmCTestLog(this->CTest, HANDLER_OUTPUT, "\nTime in " 
-                << *i << " = " << labelTimes[*i] << " sec" ); 
-     if ( this->LogFile )
-         {
-         *this->LogFile << "\nTime in " << *i << " = "
-                        << labelTimes[*i] << " sec"  << std::endl;
-         }
-     }
- }
- 
- //----------------------------------------------------------------------
  void cmCTestTestHandler::ProcessOneTest(cmCTestTestProperties *it,
                                          std::vector<cmStdString> &passed,
--- 659,662 ----
***************
*** 951,958 ****
      sprintf(buf, "%6.2f sec", cres.ExecutionTime);
      cmCTestLog(this->CTest, HANDLER_OUTPUT, buf << "\n" );
-     if ( this->LogFile )
-       {
-       *this->LogFile << "\nTest time = " << buf << std::endl;
-       }
      if (!output.empty() && output.find("<DartMeasurement") != output.npos)
        {
--- 897,900 ----
***************
*** 1600,1603 ****
--- 1542,1546 ----
      << std::endl;
    std::string last_directory = "";
+ 
    // run each test
    for (ListOfTests::iterator it = this->TestList.begin();
***************
*** 1614,1620 ****
        }
      // process this one test
!     this->ProcessOneTest(&(*it), passed, failed, it->Index, 
!                          static_cast<int>(this->TotalNumberOfTests));
!     }
    this->EndTest = this->CTest->CurrentTime();
    this->EndTestTime = static_cast<unsigned int>(cmSystemTools::GetTime());
--- 1557,1574 ----
        }
      // process this one test
!     cmCTestRunTest testRun;
!     testRun.SetTestProperties(&(*it));
!     testRun.SetTestHandler(this);
! 
!     bool testPassed = testRun.Execute(); //run the test
!     if(testPassed && !this->CTest->GetShowOnly())
!       {
!       passed.push_back(it->Name);
!       }
!     else if(!testPassed)
!       {
!       failed.push_back(it->Name);
!       }
!     }  
    this->EndTest = this->CTest->CurrentTime();
    this->EndTestTime = static_cast<unsigned int>(cmSystemTools::GetTime());

Index: cmCTestTestHandler.h
===================================================================
RCS file: /cvsroot/CMake/CMake/Source/CTest/cmCTestTestHandler.h,v
retrieving revision 1.37
retrieving revision 1.38
diff -C 2 -d -r1.37 -r1.38
*** cmCTestTestHandler.h	18 Aug 2009 17:34:05 -0000	1.37
--- cmCTestTestHandler.h	19 Aug 2009 12:58:36 -0000	1.38
***************
*** 31,34 ****
--- 31,35 ----
  class cmCTestTestHandler : public cmCTestGenericHandler
  {
+   friend class cmCTestRunTest;
  public:
    cmTypeMacro(cmCTestTestHandler, cmCTestGenericHandler);
***************
*** 186,190 ****
    virtual void GenerateDartOutput(std::ostream& os);
  
-   void PrintLabelSummary();
    /**
     * Run the tests for a directory and any subdirectories
--- 187,190 ----

--- NEW FILE: cmCTestRunTest.h ---
/*=========================================================================

  Program:   CMake - Cross-Platform Makefile Generator
  Module:    $RCSfile: cmCTestRunTest.h,v $
  Language:  C++
  Date:      $Date: 2009-08-19 12:58:32 $
  Version:   $Revision: 1.1 $

  Copyright (c) 2002 Kitware, Inc., Insight Consortium.  All rights reserved.
  See Copyright.txt or http://www.cmake.org/HTML/Copyright.html for details.

     This software is distributed WITHOUT ANY WARRANTY; without even
     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
     PURPOSE.  See the above copyright notices for more information.

=========================================================================*/
#ifndef cmCTestRunTest_h
#define cmCTestRunTest_h

#include <cmStandardIncludes.h>
#include <cmCTestTestHandler.h>

/** \class cmRunTest
 * \brief represents a single test to be run
 *
 * cmRunTest contains the information related to running a single test
 */
class cmCTestRunTest
{
public:
  cmCTestRunTest();
  ~cmCTestRunTest();

  void SetTestProperties(cmCTestTestHandler::cmCTestTestProperties * prop)
  { this->TestProperties = prop; }

  cmCTestTestHandler::cmCTestTestProperties * GetTestProperties()
  { return this->TestProperties; }
  
  void SetTestHandler(cmCTestTestHandler * handler);
  
  void SetOptimizeForCTest(bool optimize)
  { this->OptimizeForCTest = optimize; }

  bool GetOptimizeForCTest()
  { return this->OptimizeForCTest; }

  std::string GetProcessOutput()
  { return this->ProcessOutput; }

  //Provides a handle to the log stream in case someone wants
  // to asynchronously process the log
  std::ostream * GetLogStream()
  { return this->TestHandler->LogFile; }

  cmCTestTestHandler::cmCTestTestResult GetTestResults()
  { return this->TestResult; }

  //Runs the test
  bool Execute();
protected:
  void DartProcessing(std::string& output);
  int RunTestProcess(std::vector<const char*> argv,
                     std::string* output, int *retVal,
                     std::ostream* log, double testTimeOut,
                     std::vector<std::string>* environment);
private:
  cmCTestTestHandler::cmCTestTestProperties * TestProperties;
  //Pointer back to the "parent"; the handler that invoked this test run
  cmCTestTestHandler * TestHandler;
  cmCTest * CTest;
  //If the executable to run is ctest, don't create a new process; 
  //just instantiate a new cmTest.  (Can be disabled for a single test
  //if this option is set to false.)
  bool OptimizeForCTest;
  std::string ProcessOutput;
  //The test results
  cmCTestTestHandler::cmCTestTestResult TestResult;
};

#endif


--- NEW FILE: cmCTestRunTest.cxx ---
/*=========================================================================

  Program:   CMake - Cross-Platform Makefile Generator
  Module:    $RCSfile: cmCTestRunTest.cxx,v $
  Language:  C++
  Date:      $Date: 2009-08-19 12:58:32 $
  Version:   $Revision: 1.1 $

  Copyright (c) 2002 Kitware, Inc., Insight Consortium.  All rights reserved.
  See Copyright.txt or http://www.cmake.org/HTML/Copyright.html for details.

     This software is distributed WITHOUT ANY WARRANTY; without even
     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
     PURPOSE.  See the above copyright notices for more information.

=========================================================================*/

#include "cmCTestRunTest.h"
#include "cmCTest.h"
#include "cmSystemTools.h"

cmCTestRunTest::cmCTestRunTest()
{
  this->OptimizeForCTest = true;
  cmCTestTestHandler::cmCTestTestResult result;
  this->TestResult = result;
}

cmCTestRunTest::~cmCTestRunTest()
{
}

void cmCTestRunTest::SetTestHandler(cmCTestTestHandler * handler)
{
  this->TestHandler = handler;
  this->CTest = handler->CTest;
}

//----------------------------------------------------------------------
// Executes a test.  Returns whether it passed or failed
bool cmCTestRunTest::Execute()
{
  const std::string& testname = this->TestProperties->Name;
  std::vector<std::string>& args = this->TestProperties->Args;
  this->TestResult.Properties = this->TestProperties;
  this->TestResult.ExecutionTime = 0;
  this->TestResult.ReturnValue = -1;
  this->TestResult.Status = cmCTestTestHandler::NOT_RUN;
  this->TestResult.TestCount = this->TestProperties->Index;  
  this->TestResult.Name = testname;
  this->TestResult.Path = this->TestProperties->Directory.c_str();

  cmCTestLog(this->CTest, HANDLER_OUTPUT, std::setw(3) 
             << this->TestProperties->Index << "/");
  cmCTestLog(this->CTest, HANDLER_OUTPUT, std::setw(3) 
             << this->TestHandler->TotalNumberOfTests << " ");
  if ( this->TestHandler->MemCheck )
    {
    cmCTestLog(this->CTest, HANDLER_OUTPUT, "Memory Check");
    }
  else
    {
    cmCTestLog(this->CTest, HANDLER_OUTPUT, "Testing");
    }
  cmCTestLog(this->CTest, HANDLER_OUTPUT, " ");
  const int maxTestNameWidth = this->CTest->GetMaxTestNameWidth();
  std::string outname = testname + " ";
  outname.resize(maxTestNameWidth, '.');
  *this->TestHandler->LogFile << this->TestProperties->Index << "/" 
    << this->TestHandler->TotalNumberOfTests << " Testing: " 
    << testname << std::endl;

  if ( this->CTest->GetShowOnly() )
    {
    cmCTestLog(this->CTest, HANDLER_OUTPUT, outname.c_str() << std::endl);
    }
  else
    {
    cmCTestLog(this->CTest, HANDLER_OUTPUT, outname.c_str());
    }

  cmCTestLog(this->CTest, DEBUG, "Testing " << args[0].c_str() << " ... ");
  // find the test executable
  std::string actualCommand 
    = this->TestHandler->FindTheExecutable(args[1].c_str());
  std::string testCommand
    = cmSystemTools::ConvertToOutputPath(actualCommand.c_str());

  // continue if we did not find the executable
  if (testCommand == "")
    {
    *this->TestHandler->LogFile << "Unable to find executable: " 
                   << args[1].c_str() << std::endl;
    cmCTestLog(this->CTest, ERROR_MESSAGE, "Unable to find executable: "
               << args[1].c_str() << std::endl);
    this->TestResult.Output = "Unable to find executable: " + args[1];
    if ( !this->CTest->GetShowOnly() )
      {
      this->TestResult.FullCommandLine = actualCommand;
      this->TestHandler->TestResults.push_back( this->TestResult );
      return false;
      }
    }

  // add the arguments
  std::vector<std::string>::const_iterator j = args.begin();
  ++j; // skip test name
  ++j; // skip command as it is in actualCommand
  std::vector<const char*> arguments;
  this->TestHandler->GenerateTestCommand(arguments);
  arguments.push_back(actualCommand.c_str());
  for(;j != args.end(); ++j)
    {
    testCommand += " ";
    testCommand += cmSystemTools::EscapeSpaces(j->c_str());
    arguments.push_back(j->c_str());
    }
  arguments.push_back(0);

  /**
   * Run an executable command and put the stdout in output.
   */
  std::string output;
  int retVal = 0;

  cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT, std::endl
             << (this->TestHandler->MemCheck?"MemCheck":"Test") 
             << " command: " << testCommand
             << std::endl);
  *this->TestHandler->LogFile << this->TestProperties->Index << "/" 
                 << this->TestHandler->TotalNumberOfTests
                 << " Test: " << testname.c_str() << std::endl;
  *this->TestHandler->LogFile << "Command: ";
  std::vector<cmStdString>::size_type ll;
  for ( ll = 0; ll < arguments.size()-1; ll ++ )
    {
    *this->TestHandler->LogFile << "\"" << arguments[ll] << "\" ";
    }
  *this->TestHandler->LogFile
    << std::endl
    << "Directory: " << this->TestProperties->Directory << std::endl
    << "\"" << testname.c_str() << "\" start time: "
    << this->CTest->CurrentTime() << std::endl
    << "Output:" << std::endl
    << "----------------------------------------------------------"
    << std::endl;
  int res = 0;
  double clock_start, clock_finish;
  clock_start = cmSystemTools::GetTime();

  if ( !this->CTest->GetShowOnly() )
    {
    res = this->RunTestProcess(arguments, &output, &retVal,
                               this->TestHandler->LogFile,
                               this->TestProperties->Timeout,
                               &this->TestProperties->Environment);
    this->ProcessOutput = output; //save process output in the object
    }

  clock_finish = cmSystemTools::GetTime();  

  this->TestResult.ExecutionTime = (double)(clock_finish - clock_start);
  this->TestResult.FullCommandLine = testCommand;
  std::string reason;

  bool passed = true;

  if ( !this->CTest->GetShowOnly() )
    {
    std::vector<std::pair<cmsys::RegularExpression,
      std::string> >::iterator passIt;
    bool forceFail = false;
    if ( this->TestProperties->RequiredRegularExpressions.size() > 0 )
      {
      bool found = false;
      for ( passIt = this->TestProperties->RequiredRegularExpressions.begin();
            passIt != this->TestProperties->RequiredRegularExpressions.end();
            ++ passIt )
        {
        if ( passIt->first.find(output.c_str()) )
          {
          found = true;
          reason = "Required regular expression found.";
          }
        }
      if ( !found )
        { 
        reason = "Required regular expression not found.";
        forceFail = true;
        }
      reason +=  "Regex=["; 
      for ( passIt = this->TestProperties->RequiredRegularExpressions.begin();
            passIt != this->TestProperties->RequiredRegularExpressions.end();
            ++ passIt )
        {
        reason += passIt->second;
        reason += "\n";
        }
      reason += "]";
      }
    if ( this->TestProperties->ErrorRegularExpressions.size() > 0 )
      {
      for ( passIt = this->TestProperties->ErrorRegularExpressions.begin();
            passIt != this->TestProperties->ErrorRegularExpressions.end();
            ++ passIt )
        {
        if ( passIt->first.find(output.c_str()) )
          {
          reason = "Error regular expression found in output.";
          reason += " Regex=[";
          reason += passIt->second;
          reason += "]";
          forceFail = true;
          }
        }
      }

    if (res == cmsysProcess_State_Exited)
      {
      bool success = 
        !forceFail &&  (retVal == 0 || 
        this->TestProperties->RequiredRegularExpressions.size());
      if((success && !this->TestProperties->WillFail) 
        || (!success && this->TestProperties->WillFail))
        {
        this->TestResult.Status = cmCTestTestHandler::COMPLETED;
        cmCTestLog(this->CTest, HANDLER_OUTPUT,   "   Passed  " );
        }
      else
        {
        this->TestResult.Status = cmCTestTestHandler::FAILED;
        cmCTestLog(this->CTest, HANDLER_OUTPUT,
                   "***Failed  " << reason );
        }
      }
    else if ( res == cmsysProcess_State_Expired )
      {
      cmCTestLog(this->CTest, HANDLER_OUTPUT, "***Timeout");
      this->TestResult.Status = cmCTestTestHandler::TIMEOUT;
      }
    else if ( res == cmsysProcess_State_Exception )
      {
      cmCTestLog(this->CTest, HANDLER_OUTPUT, "***Exception: ");
      switch ( retVal )
        {
        case cmsysProcess_Exception_Fault:
          cmCTestLog(this->CTest, HANDLER_OUTPUT, "SegFault");
          this->TestResult.Status = cmCTestTestHandler::SEGFAULT;
          break;
        case cmsysProcess_Exception_Illegal:
          cmCTestLog(this->CTest, HANDLER_OUTPUT, "Illegal");
          this->TestResult.Status = cmCTestTestHandler::ILLEGAL;
          break;
        case cmsysProcess_Exception_Interrupt:
          cmCTestLog(this->CTest, HANDLER_OUTPUT, "Interrupt");
          this->TestResult.Status = cmCTestTestHandler::INTERRUPT;
          break;
        case cmsysProcess_Exception_Numerical:
          cmCTestLog(this->CTest, HANDLER_OUTPUT, "Numerical");
          this->TestResult.Status = cmCTestTestHandler::NUMERICAL;
          break;
        default:
          cmCTestLog(this->CTest, HANDLER_OUTPUT, "Other");
          this->TestResult.Status = cmCTestTestHandler::OTHER_FAULT;
        }
      }
    else // if ( res == cmsysProcess_State_Error )
      {
      cmCTestLog(this->CTest, HANDLER_OUTPUT, "***Bad command " << res );
      this->TestResult.Status = cmCTestTestHandler::BAD_COMMAND;
      }

    passed = this->TestResult.Status == cmCTestTestHandler::COMPLETED;

    char buf[1024];
    sprintf(buf, "%6.2f sec", this->TestResult.ExecutionTime);
    cmCTestLog(this->CTest, HANDLER_OUTPUT, buf << "\n" );
    if ( this->TestHandler->LogFile )
      {
      *this->TestHandler->LogFile << "\nTest time = " << buf << std::endl;
      }
    this->DartProcessing(output);
    } 

  // if this is doing MemCheck then all the output needs to be put into
  // Output since that is what is parsed by cmCTestMemCheckHandler
  if(!this->TestHandler->MemCheck)
    {
    if ( this->TestResult.Status == cmCTestTestHandler::COMPLETED )
      {
      this->TestHandler->CleanTestOutput(output, static_cast<size_t>
                     (this->TestHandler->CustomMaximumPassedTestOutputSize));
      }
    else
      {
      this->TestHandler->CleanTestOutput(output, static_cast<size_t>
                     (this->TestHandler->CustomMaximumFailedTestOutputSize));
      }
    }
  this->TestResult.Reason = reason;
  if ( this->TestHandler->LogFile )
    {
    bool pass = true;
    const char* reasonType = "Test Pass Reason";
    if(this->TestResult.Status != cmCTestTestHandler::COMPLETED &&
       this->TestResult.Status != cmCTestTestHandler::NOT_RUN)
      {
      reasonType = "Test Fail Reason";
      pass = false;
      }
    double ttime = clock_finish - clock_start;
    int hours = static_cast<int>(ttime / (60 * 60));
    int minutes = static_cast<int>(ttime / 60) % 60;
    int seconds = static_cast<int>(ttime) % 60;
    char buffer[100];
    sprintf(buffer, "%02d:%02d:%02d", hours, minutes, seconds);
    *this->TestHandler->LogFile
      << "----------------------------------------------------------"
      << std::endl;
    if(this->TestResult.Reason.size())
      {
      *this->TestHandler->LogFile << reasonType << ":\n" 
        << this->TestResult.Reason << "\n";
      }
    else 
      {
      if(pass)
        {
        *this->TestHandler->LogFile << "Test Passed.\n";
        }
      else
        {
        *this->TestHandler->LogFile << "Test Failed.\n";
        }
      }
    *this->TestHandler->LogFile << "\"" << testname.c_str() << "\" end time: "
      << this->CTest->CurrentTime() << std::endl
      << "\"" << testname.c_str() << "\" time elapsed: "
      << buffer << std::endl
      << "----------------------------------------------------------"
      << std::endl << std::endl;
    }
  this->TestResult.Output = output;
  this->TestResult.ReturnValue = retVal;
  this->TestResult.CompletionStatus = "Completed";
  this->TestHandler->TestResults.push_back( this->TestResult );

  return passed;
}

//----------------------------------------------------------------------
void cmCTestRunTest::DartProcessing(std::string& output)
{
  if (!output.empty() && output.find("<DartMeasurement") != output.npos)
    {
    if (this->TestHandler->DartStuff.find(output.c_str()))
      {
      std::string dartString = this->TestHandler->DartStuff.match(1);
      // keep searching and replacing until none are left
      while (this->TestHandler->DartStuff1.find(output.c_str()))
        {
        // replace the exact match for the string
        cmSystemTools::ReplaceString(output,
                         this->TestHandler->DartStuff1.match(1).c_str(), "");
        }
      this->TestResult.RegressionImages
        = this->TestHandler->GenerateRegressionImages(dartString);
      }
    }
}

//----------------------------------------------------------------------
int cmCTestRunTest::RunTestProcess(std::vector<const char*> argv,
                     std::string* output, int *retVal,
                     std::ostream* log, double testTimeOut,
                     std::vector<std::string>* environment)
{
  std::vector<std::string> origEnv;
  bool modifyEnv = (environment && environment->size()>0);

  // determine how much time we have
  double timeout = this->CTest->GetRemainingTimeAllowed() - 120;
  if (this->CTest->GetTimeOut() && this->CTest->GetTimeOut() < timeout)
    {
    timeout = this->CTest->GetTimeOut();
    }
  if (testTimeOut 
      && testTimeOut < this->CTest->GetRemainingTimeAllowed())
    {
    timeout = testTimeOut;
    }

  // always have at least 1 second if we got to here
  if (timeout <= 0)
    {
    timeout = 1;
    }
  cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
             "Test timeout computed to be: " << timeout << "\n");

  if(cmSystemTools::SameFile(argv[0], this->CTest->CTestSelf.c_str()) &&
     !this->CTest->ForceNewCTestProcess &&
     this->OptimizeForCTest)
    {
    cmCTest inst;
    inst.ConfigType = this->CTest->ConfigType;
    inst.TimeOut = timeout;

    // Capture output of the child ctest.
    cmOStringStream oss;
    inst.SetStreams(&oss, &oss);

    std::vector<std::string> args;
    for(unsigned int i =0; i < argv.size(); ++i)
      {
      if(argv[i])
        {
        // make sure we pass the timeout in for any build and test 
        // invocations. Since --build-generator is required this is a 
        // good place to check for it, and to add the arguments in
        if (strcmp(argv[i],"--build-generator") == 0 && timeout)
          {
          args.push_back("--test-timeout");
          cmOStringStream msg;
          msg << timeout;
          args.push_back(msg.str());
          }
        args.push_back(argv[i]);
        }
      }
    if ( log )
      {
      *log << "* Run internal CTest" << std::endl;
      }
    std::string oldpath = cmSystemTools::GetCurrentWorkingDirectory();

    if (modifyEnv)
      {
      origEnv = cmSystemTools::AppendEnv(environment);
      }

    *retVal = inst.Run(args, output);
    *output += oss.str();
    if ( log )
      {
      *log << output->c_str();
      }
    cmSystemTools::ChangeDirectory(oldpath.c_str());

    cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
      "Internal cmCTest object used to run test." << std::endl
      <<  *output << std::endl);

    if (modifyEnv)
      {
      cmSystemTools::RestoreEnv(origEnv);
      }

    return cmsysProcess_State_Exited;
    }
  std::vector<char> tempOutput;
  if ( output )
    {
    *output = "";
    }

  if (modifyEnv)
    {
    origEnv = cmSystemTools::AppendEnv(environment);
    }

  cmsysProcess* cp = cmsysProcess_New();
  cmsysProcess_SetCommand(cp, &*argv.begin());
  cmCTestLog(this->CTest, DEBUG, "Command is: " << argv[0] << std::endl);
  if(cmSystemTools::GetRunCommandHideConsole())
    {
    cmsysProcess_SetOption(cp, cmsysProcess_Option_HideWindow, 1);
    }

  cmsysProcess_SetTimeout(cp, timeout);
  cmsysProcess_Execute(cp);

  char* data;
  int length;
  while(cmsysProcess_WaitForData(cp, &data, &length, 0))
    {
    if ( output )
      {
      tempOutput.insert(tempOutput.end(), data, data+length);
      }
    cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT, cmCTestLogWrite(data, length));
    if ( log )
      {
      log->write(data, length);
      }
    }

  cmsysProcess_WaitForExit(cp, 0);
  if(output && tempOutput.begin() != tempOutput.end())
    {
    //We are waiting for exit before finally appending to the output
    output->append(&*tempOutput.begin(), tempOutput.size());
    }
  cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT, "-- Process completed"
    << std::endl);

  int result = cmsysProcess_GetState(cp);

  if(result == cmsysProcess_State_Exited)
    {
    *retVal = cmsysProcess_GetExitValue(cp);
    if(*retVal != 0 && this->CTest->OutputTestOutputOnTestFailure)
      {
        this->CTest->OutputTestErrors(tempOutput);
      }
    }
  else if(result == cmsysProcess_State_Exception)
    {
    if(this->CTest->OutputTestOutputOnTestFailure)
      {
        this->CTest->OutputTestErrors(tempOutput);
      }
    *retVal = cmsysProcess_GetExitException(cp);
    std::string outerr = "\n*** Exception executing: ";
    outerr += cmsysProcess_GetExceptionString(cp);
    *output += outerr;
    cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT, outerr.c_str() << std::endl
      << std::flush);
    }
  else if(result == cmsysProcess_State_Error)
    {
    std::string outerr = "\n*** ERROR executing: ";
    outerr += cmsysProcess_GetErrorString(cp);
    *output += outerr;
    cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT, outerr.c_str() << std::endl
      << std::flush);
    }
  cmsysProcess_Delete(cp);

  if (modifyEnv)
    {
    cmSystemTools::RestoreEnv(origEnv);
    }

  return result;
}




More information about the Cmake-commits mailing list