| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348 | /*============================================================================  CMake - Cross Platform Makefile Generator  Copyright 2000-2009 Kitware, Inc., Insight Software Consortium  Distributed under the OSI-approved BSD License (the "License");  see accompanying file Copyright.txt for details.  This software is distributed WITHOUT ANY WARRANTY; without even the  implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the License for more information.============================================================================*/#include "cmCTestTestHandler.h"#include "cmCTestMultiProcessHandler.h"#include "cmCTestBatchTestHandler.h"#include "cmCTest.h"#include "cmCTestRunTest.h"#include "cmake.h"#include "cmGeneratedFileStream.h"#include <cmsys/Process.h>#include <cmsys/RegularExpression.hxx>#include <cmsys/Base64.h>#include <cmsys/Directory.hxx>#include <cmsys/FStream.hxx>#include "cmMakefile.h"#include "cmGlobalGenerator.h"#include "cmCommand.h"#include "cmSystemTools.h"#include "cmXMLWriter.h"#include "cm_utf8.h"#include <stdlib.h>#include <math.h>#include <float.h>#include <set>//----------------------------------------------------------------------class cmCTestSubdirCommand : public cmCommand{public:  /**   * This is a virtual constructor for the command.   */  virtual cmCommand* Clone()    {    cmCTestSubdirCommand* c = new cmCTestSubdirCommand;    c->TestHandler = this->TestHandler;    return c;    }  /**   * This is called when the command is first encountered in   * the CMakeLists.txt file.   */  virtual bool InitialPass(std::vector<std::string> const& args,                           cmExecutionStatus &);  /**   * The name of the command as specified in CMakeList.txt.   */  virtual std::string GetName() const { return "subdirs";}  cmTypeMacro(cmCTestSubdirCommand, cmCommand);  cmCTestTestHandler* TestHandler;};//----------------------------------------------------------------------bool cmCTestSubdirCommand::InitialPass(std::vector<std::string> const& args, cmExecutionStatus &){  if(args.size() < 1 )    {    this->SetError("called with incorrect number of arguments");    return false;    }  std::vector<std::string>::const_iterator it;  std::string cwd = cmSystemTools::GetCurrentWorkingDirectory();  for ( it = args.begin(); it != args.end(); ++ it )    {    std::string fname;    if(cmSystemTools::FileIsFullPath(it->c_str()))      {      fname = *it;      }    else      {      fname = cwd;      fname += "/";      fname += *it;      }    if ( !cmSystemTools::FileIsDirectory(fname) )      {      // No subdirectory? So what...      continue;      }    cmSystemTools::ChangeDirectory(fname);    const char* testFilename;    if( cmSystemTools::FileExists("CTestTestfile.cmake") )      {      // does the CTestTestfile.cmake exist ?      testFilename = "CTestTestfile.cmake";      }    else if( cmSystemTools::FileExists("DartTestfile.txt") )      {      // does the DartTestfile.txt exist ?      testFilename = "DartTestfile.txt";      }    else      {      // No CTestTestfile? Who cares...      continue;      }    fname += "/";    fname += testFilename;    bool readit = this->Makefile->ReadDependentFile(fname.c_str());    cmSystemTools::ChangeDirectory(cwd);    if(!readit)      {      std::string m = "Could not find include file: ";      m += fname;      this->SetError(m);      return false;      }    }  cmSystemTools::ChangeDirectory(cwd);  return true;}//----------------------------------------------------------------------class cmCTestAddSubdirectoryCommand : public cmCommand{public:  /**   * This is a virtual constructor for the command.   */  virtual cmCommand* Clone()    {    cmCTestAddSubdirectoryCommand* c = new cmCTestAddSubdirectoryCommand;    c->TestHandler = this->TestHandler;    return c;    }  /**   * This is called when the command is first encountered in   * the CMakeLists.txt file.   */  virtual bool InitialPass(std::vector<std::string> const& args,                           cmExecutionStatus &);  /**   * The name of the command as specified in CMakeList.txt.   */  virtual std::string GetName() const { return "add_subdirectory";}  cmTypeMacro(cmCTestAddSubdirectoryCommand, cmCommand);  cmCTestTestHandler* TestHandler;};//----------------------------------------------------------------------bool cmCTestAddSubdirectoryCommand::InitialPass(std::vector<std::string> const& args, cmExecutionStatus &){  if(args.size() < 1 )    {    this->SetError("called with incorrect number of arguments");    return false;    }  std::string cwd = cmSystemTools::GetCurrentWorkingDirectory();  cmSystemTools::ChangeDirectory(cwd);  std::string fname = cwd;  fname += "/";  fname += args[0];  if ( !cmSystemTools::FileExists(fname.c_str()) )    {    // No subdirectory? So what...    return true;    }  cmSystemTools::ChangeDirectory(fname);  const char* testFilename;  if( cmSystemTools::FileExists("CTestTestfile.cmake") )    {    // does the CTestTestfile.cmake exist ?    testFilename = "CTestTestfile.cmake";    }  else if( cmSystemTools::FileExists("DartTestfile.txt") )    {    // does the DartTestfile.txt exist ?    testFilename = "DartTestfile.txt";    }  else    {    // No CTestTestfile? Who cares...    cmSystemTools::ChangeDirectory(cwd);    return true;    }  fname += "/";  fname += testFilename;  bool readit = this->Makefile->ReadDependentFile(fname.c_str());  cmSystemTools::ChangeDirectory(cwd);  if(!readit)    {    std::string m = "Could not find include file: ";    m += fname;    this->SetError(m);    return false;    }  return true;}//----------------------------------------------------------------------class cmCTestAddTestCommand : public cmCommand{public:  /**   * This is a virtual constructor for the command.   */  virtual cmCommand* Clone()    {    cmCTestAddTestCommand* c = new cmCTestAddTestCommand;    c->TestHandler = this->TestHandler;    return c;    }  /**   * This is called when the command is first encountered in   * the CMakeLists.txt file.   */  virtual bool InitialPass(std::vector<std::string> const&,                           cmExecutionStatus &);  /**   * The name of the command as specified in CMakeList.txt.   */  virtual std::string GetName() const { return "add_test";}  cmTypeMacro(cmCTestAddTestCommand, cmCommand);  cmCTestTestHandler* TestHandler;};//----------------------------------------------------------------------bool cmCTestAddTestCommand::InitialPass(std::vector<std::string> const& args, cmExecutionStatus &){  if ( args.size() < 2 )    {    this->SetError("called with incorrect number of arguments");    return false;    }  return this->TestHandler->AddTest(args);}//----------------------------------------------------------------------class cmCTestSetTestsPropertiesCommand : public cmCommand{public:  /**   * This is a virtual constructor for the command.   */  virtual cmCommand* Clone()    {    cmCTestSetTestsPropertiesCommand* c      = new cmCTestSetTestsPropertiesCommand;    c->TestHandler = this->TestHandler;    return c;    }  /**   * This is called when the command is first encountered in   * the CMakeLists.txt file.  */  virtual bool InitialPass(std::vector<std::string> const&,                           cmExecutionStatus &);  /**   * The name of the command as specified in CMakeList.txt.   */  virtual std::string GetName() const { return "set_tests_properties";}  cmTypeMacro(cmCTestSetTestsPropertiesCommand, cmCommand);  cmCTestTestHandler* TestHandler;};//----------------------------------------------------------------------bool cmCTestSetTestsPropertiesCommand::InitialPass(std::vector<std::string> const& args, cmExecutionStatus &){  return this->TestHandler->SetTestsProperties(args);}//----------------------------------------------------------------------// get the next number in a string with numbers separated by ,// pos is the start of the search and pos2 is the end of the search// pos becomes pos2 after a call to GetNextNumber.// -1 is returned at the end of the list.inline int GetNextNumber(std::string const& in,                         int& val,                         std::string::size_type& pos,                         std::string::size_type& pos2){  pos2 = in.find(',', pos);  if(pos2 != in.npos)    {    if(pos2-pos == 0)      {      val = -1;      }    else      {      val = atoi(in.substr(pos, pos2-pos).c_str());      }    pos = pos2+1;    return 1;    }  else    {    if(in.size()-pos == 0)      {       val = -1;      }    else      {      val = atoi(in.substr(pos, in.size()-pos).c_str());      }    return 0;    }}//----------------------------------------------------------------------// get the next number in a string with numbers separated by ,// pos is the start of the search and pos2 is the end of the search// pos becomes pos2 after a call to GetNextNumber.// -1 is returned at the end of the list.inline int GetNextRealNumber(std::string const& in,                             double& val,                             std::string::size_type& pos,                             std::string::size_type& pos2){  pos2 = in.find(',', pos);  if(pos2 != in.npos)    {    if(pos2-pos == 0)      {      val = -1;      }    else      {      val = atof(in.substr(pos, pos2-pos).c_str());      }    pos = pos2+1;    return 1;    }  else    {    if(in.size()-pos == 0)      {       val = -1;      }    else      {      val = atof(in.substr(pos, in.size()-pos).c_str());      }    return 0;    }}//----------------------------------------------------------------------cmCTestTestHandler::cmCTestTestHandler(){  this->UseUnion = false;  this->UseIncludeLabelRegExpFlag   = false;  this->UseExcludeLabelRegExpFlag   = false;  this->UseIncludeRegExpFlag   = false;  this->UseExcludeRegExpFlag   = false;  this->UseExcludeRegExpFirst  = false;  this->CustomMaximumPassedTestOutputSize = 1 * 1024;  this->CustomMaximumFailedTestOutputSize = 300 * 1024;  this->MemCheck = false;  this->LogFile = 0;  // regex to detect <DartMeasurement>...</DartMeasurement>  this->DartStuff.compile(    "(<DartMeasurement.*/DartMeasurement[a-zA-Z]*>)");  // regex to detect each individual <DartMeasurement>...</DartMeasurement>  this->DartStuff1.compile(    "(<DartMeasurement[^<]*</DartMeasurement[a-zA-Z]*>)");}//----------------------------------------------------------------------void cmCTestTestHandler::Initialize(){  this->Superclass::Initialize();  this->ElapsedTestingTime = -1;  this->TestResults.clear();  this->CustomTestsIgnore.clear();  this->StartTest = "";  this->EndTest = "";  this->CustomPreTest.clear();  this->CustomPostTest.clear();  this->CustomMaximumPassedTestOutputSize = 1 * 1024;  this->CustomMaximumFailedTestOutputSize = 300 * 1024;  this->TestsToRun.clear();  this->UseIncludeLabelRegExpFlag = false;  this->UseExcludeLabelRegExpFlag = false;  this->UseIncludeRegExpFlag = false;  this->UseExcludeRegExpFlag = false;  this->UseExcludeRegExpFirst = false;  this->IncludeLabelRegularExpression = "";  this->ExcludeLabelRegularExpression = "";  this->IncludeRegExp = "";  this->ExcludeRegExp = "";  TestsToRunString = "";  this->UseUnion = false;  this->TestList.clear();}//----------------------------------------------------------------------void cmCTestTestHandler::PopulateCustomVectors(cmMakefile *mf){  this->CTest->PopulateCustomVector(mf, "CTEST_CUSTOM_PRE_TEST",                                this->CustomPreTest);  this->CTest->PopulateCustomVector(mf, "CTEST_CUSTOM_POST_TEST",                                this->CustomPostTest);  this->CTest->PopulateCustomVector(mf,                             "CTEST_CUSTOM_TESTS_IGNORE",                             this->CustomTestsIgnore);  this->CTest->PopulateCustomInteger(mf,                             "CTEST_CUSTOM_MAXIMUM_PASSED_TEST_OUTPUT_SIZE",                             this->CustomMaximumPassedTestOutputSize);  this->CTest->PopulateCustomInteger(mf,                             "CTEST_CUSTOM_MAXIMUM_FAILED_TEST_OUTPUT_SIZE",                             this->CustomMaximumFailedTestOutputSize);}//----------------------------------------------------------------------int cmCTestTestHandler::PreProcessHandler(){  if ( !this->ExecuteCommands(this->CustomPreTest) )    {    cmCTestLog(this->CTest, ERROR_MESSAGE,      "Problem executing pre-test command(s)." << std::endl);    return 0;    }  return 1;}//----------------------------------------------------------------------int cmCTestTestHandler::PostProcessHandler(){  if ( !this->ExecuteCommands(this->CustomPostTest) )    {    cmCTestLog(this->CTest, ERROR_MESSAGE,      "Problem executing post-test command(s)." << std::endl);    return 0;    }  return 1;}//----------------------------------------------------------------------//clearly it would be nice if this were broken up into a few smaller//functions and commented...int cmCTestTestHandler::ProcessHandler(){  // Update internal data structure from generic one  this->SetTestsToRunInformation(this->GetOption("TestsToRunInformation"));  this->SetUseUnion(cmSystemTools::IsOn(this->GetOption("UseUnion")));  if(cmSystemTools::IsOn(this->GetOption("ScheduleRandom")))    {    this->CTest->SetScheduleType("Random");    }  if(this->GetOption("ParallelLevel"))    {    this->CTest->SetParallelLevel(atoi(this->GetOption("ParallelLevel")));    }  const char* val;  val = this->GetOption("LabelRegularExpression");  if ( val )    {    this->UseIncludeLabelRegExpFlag = true;    this->IncludeLabelRegExp = val;    }  val = this->GetOption("ExcludeLabelRegularExpression");  if ( val )    {    this->UseExcludeLabelRegExpFlag = true;    this->ExcludeLabelRegExp = val;    }  val = this->GetOption("IncludeRegularExpression");  if ( val )    {    this->UseIncludeRegExp();    this->SetIncludeRegExp(val);    }  val = this->GetOption("ExcludeRegularExpression");  if ( val )    {    this->UseExcludeRegExp();    this->SetExcludeRegExp(val);    }  this->SetRerunFailed(cmSystemTools::IsOn(this->GetOption("RerunFailed")));  this->TestResults.clear();  cmCTestOptionalLog(this->CTest, HANDLER_OUTPUT,             (this->MemCheck ? "Memory check" : "Test")             << " project " << cmSystemTools::GetCurrentWorkingDirectory()             << std::endl, this->Quiet);  if ( ! this->PreProcessHandler() )    {    return -1;    }  cmGeneratedFileStream mLogFile;  this->StartLogFile((this->MemCheck ? "DynamicAnalysis" : "Test"), mLogFile);  this->LogFile = &mLogFile;  std::vector<std::string> passed;  std::vector<std::string> failed;  int total;  //start the real time clock  double clock_start, clock_finish;  clock_start = cmSystemTools::GetTime();  this->ProcessDirectory(passed, failed);  clock_finish = cmSystemTools::GetTime();  total = int(passed.size()) + int(failed.size());  if (total == 0)    {    if ( !this->CTest->GetShowOnly() && !this->CTest->ShouldPrintLabels() )      {      cmCTestLog(this->CTest, ERROR_MESSAGE, "No tests were found!!!"        << std::endl);      }    }  else    {    if (this->HandlerVerbose && !passed.empty() &&      (this->UseIncludeRegExpFlag || this->UseExcludeRegExpFlag))      {      cmCTestOptionalLog(this->CTest, HANDLER_VERBOSE_OUTPUT, std::endl        << "The following tests passed:" << std::endl, this->Quiet);      for(std::vector<std::string>::iterator j = passed.begin();          j != passed.end(); ++j)        {        cmCTestOptionalLog(this->CTest, HANDLER_VERBOSE_OUTPUT, "\t" << *j          << std::endl, this->Quiet);        }      }    float percent = float(passed.size()) * 100.0f / float(total);    if (!failed.empty() && percent > 99)      {      percent = 99;      }    cmCTestLog(this->CTest, HANDLER_OUTPUT, std::endl               << static_cast<int>(percent + .5f) << "% tests passed, "               << failed.size() << " tests failed out of "               << total << std::endl);    if(this->CTest->GetLabelSummary())      {      this->PrintLabelSummary();      }    char realBuf[1024];    sprintf(realBuf, "%6.2f sec", (double)(clock_finish - clock_start));    cmCTestOptionalLog(this->CTest, HANDLER_OUTPUT,      "\nTotal Test time (real) = " << realBuf << "\n", this->Quiet );    if (!failed.empty())      {      cmGeneratedFileStream ofs;      cmCTestLog(this->CTest, HANDLER_OUTPUT, std::endl                 << "The following tests FAILED:" << std::endl);      this->StartLogFile("TestsFailed", ofs);      typedef std::set<cmCTestTestHandler::cmCTestTestResult,                       cmCTestTestResultLess> SetOfTests;      SetOfTests resultsSet(this->TestResults.begin(),                            this->TestResults.end());      for(SetOfTests::iterator ftit = resultsSet.begin();          ftit != resultsSet.end(); ++ftit)        {        if ( ftit->Status != cmCTestTestHandler::COMPLETED )          {          ofs << ftit->TestCount << ":" << ftit->Name << std::endl;          cmCTestLog(this->CTest, HANDLER_OUTPUT, "\t" << std::setw(3)                     << ftit->TestCount << " - "                     << ftit->Name << " ("                     << this->GetTestStatus(ftit->Status) << ")"                     << std::endl);          }        }      }    }  if ( this->CTest->GetProduceXML() )    {    cmGeneratedFileStream xmlfile;    if( !this->StartResultingXML(          (this->MemCheck ? cmCTest::PartMemCheck : cmCTest::PartTest),        (this->MemCheck ? "DynamicAnalysis" : "Test"), xmlfile) )      {      cmCTestLog(this->CTest, ERROR_MESSAGE, "Cannot create "        << (this->MemCheck ? "memory check" : "testing")        << " XML file" << std::endl);      this->LogFile = 0;      return 1;      }    cmXMLWriter xml(xmlfile);    this->GenerateDartOutput(xml);    }  if ( ! this->PostProcessHandler() )    {    this->LogFile = 0;    return -1;    }  if ( !failed.empty() )    {    this->LogFile = 0;    return -1;    }  this->LogFile = 0;  return 0;}//----------------------------------------------------------------------void cmCTestTestHandler::PrintLabelSummary(){  cmCTestTestHandler::ListOfTests::iterator it = this->TestList.begin();  std::map<std::string, double> labelTimes;  std::map<std::string, int> labelCounts;  std::set<std::string> labels;  // initialize maps  std::string::size_type maxlen = 0;  for(; it != this->TestList.end(); ++it)    {    cmCTestTestProperties& p = *it;    if(!p.Labels.empty())      {      for(std::vector<std::string>::iterator l = p.Labels.begin();          l !=  p.Labels.end(); ++l)        {        if((*l).size() > maxlen)          {          maxlen = (*l).size();          }        labels.insert(*l);        labelTimes[*l] = 0;        labelCounts[*l] = 0;        }      }    }  cmCTestTestHandler::TestResultsVector::iterator ri =      this->TestResults.begin();  // fill maps  for(; ri != this->TestResults.end(); ++ri)    {    cmCTestTestResult &result = *ri;    cmCTestTestProperties& p = *result.Properties;    if(!p.Labels.empty())      {      for(std::vector<std::string>::iterator l = p.Labels.begin();          l !=  p.Labels.end(); ++l)        {        labelTimes[*l] += result.ExecutionTime;        ++labelCounts[*l];        }      }    }  // now print times  if(!labels.empty())    {    cmCTestOptionalLog(this->CTest, HANDLER_OUTPUT, "\nLabel Time Summary:",      this->Quiet);    }  for(std::set<std::string>::const_iterator i = labels.begin();      i != labels.end(); ++i)    {    std::string label = *i;    label.resize(maxlen +3, ' ');    char buf[1024];    sprintf(buf, "%6.2f sec", labelTimes[*i]);    std::ostringstream labelCountStr;    labelCountStr << "(" << labelCounts[*i] << " test";    if (labelCounts[*i] > 1)      {      labelCountStr << "s";      }    labelCountStr << ")";    cmCTestOptionalLog(this->CTest, HANDLER_OUTPUT, "\n"               << label << " = " << buf << " " << labelCountStr.str(),               this->Quiet );    if ( this->LogFile )      {      *this->LogFile << "\n" << *i << " = "                     << buf << "\n";      }    }  if(!labels.empty())    {    if(this->LogFile)      {      *this->LogFile << "\n";      }    cmCTestOptionalLog(this->CTest, HANDLER_OUTPUT, "\n", this->Quiet);    }}//----------------------------------------------------------------------void cmCTestTestHandler::CheckLabelFilterInclude(cmCTestTestProperties& it){  // if not using Labels to filter then return  if (!this->UseIncludeLabelRegExpFlag )    {    return;    }  // if there are no labels and we are filtering by labels  // then exclude the test as it does not have the label  if(it.Labels.empty())    {    it.IsInBasedOnREOptions = false;    return;    }  // check to see if the label regular expression matches  bool found = false;  // assume it does not match  // loop over all labels and look for match  for(std::vector<std::string>::iterator l = it.Labels.begin();      l !=  it.Labels.end(); ++l)    {    if(this->IncludeLabelRegularExpression.find(*l))      {      found = true;      }    }  // if no match was found, exclude the test  if(!found)    {    it.IsInBasedOnREOptions = false;    }}//----------------------------------------------------------------------void cmCTestTestHandler::CheckLabelFilterExclude(cmCTestTestProperties& it){  // if not using Labels to filter then return  if (!this->UseExcludeLabelRegExpFlag )    {    return;    }  // if there are no labels and we are excluding by labels  // then do nothing as a no label can not be a match  if(it.Labels.empty())    {    return;    }  // check to see if the label regular expression matches  bool found = false;  // assume it does not match  // loop over all labels and look for match  for(std::vector<std::string>::iterator l = it.Labels.begin();      l !=  it.Labels.end(); ++l)    {    if(this->ExcludeLabelRegularExpression.find(*l))      {      found = true;      }    }  // if match was found, exclude the test  if(found)    {    it.IsInBasedOnREOptions = false;    }}//----------------------------------------------------------------------void cmCTestTestHandler::CheckLabelFilter(cmCTestTestProperties& it){  this->CheckLabelFilterInclude(it);  this->CheckLabelFilterExclude(it);}//----------------------------------------------------------------------void cmCTestTestHandler::ComputeTestList(){  this->TestList.clear(); // clear list of test  this->GetListOfTests();  if (this->RerunFailed)    {    this->ComputeTestListForRerunFailed();    return;    }  cmCTestTestHandler::ListOfTests::size_type tmsize = this->TestList.size();  // how many tests are in based on RegExp?  int inREcnt = 0;  cmCTestTestHandler::ListOfTests::iterator it;  for ( it = this->TestList.begin(); it != this->TestList.end(); it ++ )    {    this->CheckLabelFilter(*it);    if (it->IsInBasedOnREOptions)      {      inREcnt ++;      }    }  // expand the test list based on the union flag  if (this->UseUnion)    {    this->ExpandTestsToRunInformation((int)tmsize);    }  else    {    this->ExpandTestsToRunInformation(inREcnt);    }  // Now create a final list of tests to run  int cnt = 0;  inREcnt = 0;  std::string last_directory = "";  ListOfTests finalList;  for ( it = this->TestList.begin(); it != this->TestList.end(); it ++ )    {    cnt ++;    if (it->IsInBasedOnREOptions)      {      inREcnt++;      }    if (this->UseUnion)      {      // if it is not in the list and not in the regexp then skip      if ((!this->TestsToRun.empty() &&           std::find(this->TestsToRun.begin(), this->TestsToRun.end(), cnt)           == this->TestsToRun.end()) && !it->IsInBasedOnREOptions)        {        continue;        }      }    else      {      // is this test in the list of tests to run? If not then skip it      if ((!this->TestsToRun.empty() &&           std::find(this->TestsToRun.begin(),                     this->TestsToRun.end(), inREcnt)           == this->TestsToRun.end()) || !it->IsInBasedOnREOptions)        {        continue;        }      }    it->Index = cnt;  // save the index into the test list for this test    finalList.push_back(*it);    }  // Save the total number of tests before exclusions  this->TotalNumberOfTests = this->TestList.size();  // Set the TestList to the final list of all test  this->TestList = finalList;  this->UpdateMaxTestNameWidth();}void cmCTestTestHandler::ComputeTestListForRerunFailed(){  this->ExpandTestsToRunInformationForRerunFailed();  cmCTestTestHandler::ListOfTests::iterator it;  ListOfTests finalList;  int cnt = 0;  for ( it = this->TestList.begin(); it != this->TestList.end(); it ++ )    {    cnt ++;    // if this test is not in our list of tests to run, then skip it.    if ((!this->TestsToRun.empty() &&         std::find(this->TestsToRun.begin(), this->TestsToRun.end(), cnt)         == this->TestsToRun.end()))      {      continue;      }    it->Index = cnt;    finalList.push_back(*it);    }  // Save the total number of tests before exclusions  this->TotalNumberOfTests = this->TestList.size();  // Set the TestList to the list of failed tests to rerun  this->TestList = finalList;  this->UpdateMaxTestNameWidth();}void cmCTestTestHandler::UpdateMaxTestNameWidth(){  std::string::size_type max = this->CTest->GetMaxTestNameWidth();  for ( cmCTestTestHandler::ListOfTests::iterator it = this->TestList.begin();        it != this->TestList.end(); it ++ )    {    cmCTestTestProperties& p = *it;    if(max < p.Name.size())      {      max = p.Name.size();      }    }  if(static_cast<std::string::size_type>(this->CTest->GetMaxTestNameWidth())     != max)    {    this->CTest->SetMaxTestNameWidth(static_cast<int>(max));    }}bool cmCTestTestHandler::GetValue(const char* tag,                                  int& value,                                  std::istream& fin){  std::string line;  bool ret = true;  cmSystemTools::GetLineFromStream(fin, line);  if(line == tag)    {    fin >> value;    ret = cmSystemTools::GetLineFromStream(fin, line); // read blank line    }  else    {    cmCTestLog(this->CTest, ERROR_MESSAGE,               "parse error: missing tag: "               << tag << " found [" << line << "]" << std::endl);    ret = false;    }  return ret;}bool cmCTestTestHandler::GetValue(const char* tag,                                  double& value,                                  std::istream& fin){  std::string line;  cmSystemTools::GetLineFromStream(fin, line);  bool ret = true;  if(line == tag)    {    fin >> value;    ret = cmSystemTools::GetLineFromStream(fin, line); // read blank line    }  else    {    cmCTestLog(this->CTest, ERROR_MESSAGE,               "parse error: missing tag: "               << tag << " found [" << line << "]" << std::endl);    ret = false;    }  return ret;}bool cmCTestTestHandler::GetValue(const char* tag,                                  bool& value,                                  std::istream& fin){  std::string line;  cmSystemTools::GetLineFromStream(fin, line);  bool ret = true;  if(line == tag)    {#ifdef __HAIKU__    int tmp = 0;    fin >> tmp;    value = false;    if(tmp)      {      value = true;      }#else    fin >> value;#endif    ret = cmSystemTools::GetLineFromStream(fin, line); // read blank line    }  else    {    cmCTestLog(this->CTest, ERROR_MESSAGE,               "parse error: missing tag: "               << tag << " found [" << line << "]" << std::endl);    ret = false;    }  return ret;}bool cmCTestTestHandler::GetValue(const char* tag,                                  size_t& value,                                  std::istream& fin){  std::string line;  cmSystemTools::GetLineFromStream(fin, line);  bool ret = true;  if(line == tag)    {    fin >> value;    ret = cmSystemTools::GetLineFromStream(fin, line); // read blank line    }  else    {    cmCTestLog(this->CTest, ERROR_MESSAGE,               "parse error: missing tag: "               << tag << " found [" << line << "]" << std::endl);    ret = false;    }  return ret;}bool cmCTestTestHandler::GetValue(const char* tag,                                  std::string& value,                                  std::istream& fin){  std::string line;  cmSystemTools::GetLineFromStream(fin, line);  bool ret = true;  if(line == tag)    {    ret =  cmSystemTools::GetLineFromStream(fin, value);    }  else    {    cmCTestLog(this->CTest, ERROR_MESSAGE,               "parse error: missing tag: "               << tag << " found [" << line << "]" << std::endl);    ret = false;    }  return ret;}//---------------------------------------------------------------------void cmCTestTestHandler::ProcessDirectory(std::vector<std::string> &passed,                                         std::vector<std::string> &failed){  this->ComputeTestList();  this->StartTest = this->CTest->CurrentTime();  this->StartTestTime = static_cast<unsigned int>(cmSystemTools::GetTime());  double elapsed_time_start = cmSystemTools::GetTime();  cmCTestMultiProcessHandler* parallel = this->CTest->GetBatchJobs() ?    new cmCTestBatchTestHandler : new cmCTestMultiProcessHandler;  parallel->SetCTest(this->CTest);  parallel->SetParallelLevel(this->CTest->GetParallelLevel());  parallel->SetTestHandler(this);  parallel->SetQuiet(this->Quiet);  if(this->TestLoad > 0)    {    parallel->SetTestLoad(this->TestLoad);    }  else    {    parallel->SetTestLoad(this->CTest->GetTestLoad());    }  *this->LogFile << "Start testing: "    << this->CTest->CurrentTime() << std::endl    << "----------------------------------------------------------"    << std::endl;  cmCTestMultiProcessHandler::TestMap tests;  cmCTestMultiProcessHandler::PropertiesMap properties;  bool randomSchedule = this->CTest->GetScheduleType() == "Random";  if(randomSchedule)    {    srand((unsigned)time(0));    }  for (ListOfTests::iterator it = this->TestList.begin();       it != this->TestList.end(); ++it)    {    cmCTestTestProperties& p = *it;    cmCTestMultiProcessHandler::TestSet depends;    if(randomSchedule)      {      p.Cost = static_cast<float>(rand());      }    if(p.Timeout == 0 && this->CTest->GetGlobalTimeout() != 0)      {      p.Timeout = this->CTest->GetGlobalTimeout();      }    if(!p.Depends.empty())      {      for(std::vector<std::string>::iterator i = p.Depends.begin();          i != p.Depends.end(); ++i)        {        for(ListOfTests::iterator it2 = this->TestList.begin();            it2 != this->TestList.end(); ++it2)          {          if(it2->Name == *i)            {            depends.insert(it2->Index);            break; // break out of test loop as name can only match 1            }          }        }      }    tests[it->Index] = depends;    properties[it->Index] = &*it;    }  parallel->SetTests(tests, properties);  parallel->SetPassFailVectors(&passed, &failed);  this->TestResults.clear();  parallel->SetTestResults(&this->TestResults);  if(this->CTest->ShouldPrintLabels())    {    parallel->PrintLabels();    }  else if(this->CTest->GetShowOnly())    {    parallel->PrintTestList();    }  else    {    parallel->RunTests();    }  delete parallel;  this->EndTest = this->CTest->CurrentTime();  this->EndTestTime = static_cast<unsigned int>(cmSystemTools::GetTime());  this->ElapsedTestingTime = cmSystemTools::GetTime() - elapsed_time_start;  *this->LogFile << "End testing: "     << this->CTest->CurrentTime() << std::endl;}//----------------------------------------------------------------------void cmCTestTestHandler::GenerateTestCommand(std::vector<std::string>&, int){}//----------------------------------------------------------------------void cmCTestTestHandler::GenerateDartOutput(cmXMLWriter& xml){  if ( !this->CTest->GetProduceXML() )    {    return;    }  this->CTest->StartXML(xml, this->AppendXML);  xml.StartElement("Testing");  xml.Element("StartDateTime", this->StartTest);  xml.Element("StartTestTime", this->StartTestTime);  xml.StartElement("TestList");  cmCTestTestHandler::TestResultsVector::size_type cc;  for ( cc = 0; cc < this->TestResults.size(); cc ++ )    {    cmCTestTestResult *result = &this->TestResults[cc];    std::string testPath = result->Path + "/" + result->Name;    xml.Element("Test", this->CTest->GetShortPathToFile(testPath.c_str()));    }  xml.EndElement(); // TestList  for ( cc = 0; cc < this->TestResults.size(); cc ++ )    {    cmCTestTestResult *result = &this->TestResults[cc];    this->WriteTestResultHeader(xml, result);    xml.StartElement("Results");    if ( result->Status != cmCTestTestHandler::NOT_RUN )      {      if ( result->Status != cmCTestTestHandler::COMPLETED ||        result->ReturnValue )        {        xml.StartElement("NamedMeasurement");        xml.Attribute("type", "text/string");        xml.Attribute("name", "Exit Code");        xml.Element("Value", this->GetTestStatus(result->Status));        xml.EndElement(); // NamedMeasurement        xml.StartElement("NamedMeasurement");        xml.Attribute("type", "text/string");        xml.Attribute("name", "Exit Value");        xml.Element("Value", result->ReturnValue);        xml.EndElement(); // NamedMeasurement        }      this->GenerateRegressionImages(xml, result->DartString);      xml.StartElement("NamedMeasurement");      xml.Attribute("type", "numeric/double");      xml.Attribute("name", "Execution Time");      xml.Element("Value", result->ExecutionTime);      xml.EndElement(); // NamedMeasurement      if(!result->Reason.empty())        {        const char* reasonType = "Pass Reason";        if(result->Status != cmCTestTestHandler::COMPLETED &&           result->Status != cmCTestTestHandler::NOT_RUN)          {          reasonType = "Fail Reason";          }        xml.StartElement("NamedMeasurement");        xml.Attribute("type", "text/string");        xml.Attribute("name", reasonType);        xml.Element("Value", result->Reason);        xml.EndElement(); // NamedMeasurement        }      xml.StartElement("NamedMeasurement");      xml.Attribute("type", "text/string");      xml.Attribute("name", "Completion Status");      xml.Element("Value", result->CompletionStatus);      xml.EndElement(); // NamedMeasurement      }    xml.StartElement("NamedMeasurement");    xml.Attribute("type", "text/string");    xml.Attribute("name", "Command Line");    xml.Element("Value", result->FullCommandLine);    xml.EndElement(); // NamedMeasurement    std::map<std::string,std::string>::iterator measureIt;    for ( measureIt = result->Properties->Measurements.begin();      measureIt != result->Properties->Measurements.end();      ++ measureIt )      {      xml.StartElement("NamedMeasurement");      xml.Attribute("type", "text/string");      xml.Attribute("name", measureIt->first);      xml.Element("Value", measureIt->second);      xml.EndElement(); // NamedMeasurement      }    xml.StartElement("Measurement");    xml.StartElement("Value");    if (result->CompressOutput)      {      xml.Attribute("encoding", "base64");      xml.Attribute("compression", "gzip");      }    xml.Content(result->Output);    xml.EndElement(); // Value    xml.EndElement(); // Measurement    xml.EndElement(); // Results    this->AttachFiles(xml, result);    this->WriteTestResultFooter(xml, result);    }  xml.Element("EndDateTime", this->EndTest);  xml.Element("EndTestTime", this->EndTestTime);  xml.Element("ElapsedMinutes",    static_cast<int>(this->ElapsedTestingTime/6)/10.0);  xml.EndElement(); // Testing  this->CTest->EndXML(xml);}//----------------------------------------------------------------------------void cmCTestTestHandler::WriteTestResultHeader(cmXMLWriter& xml,                                               cmCTestTestResult* result){  xml.StartElement("Test");  if ( result->Status == cmCTestTestHandler::COMPLETED )    {    xml.Attribute("Status", "passed");    }  else if ( result->Status == cmCTestTestHandler::NOT_RUN )    {    xml.Attribute("Status", "notrun");    }  else    {    xml.Attribute("Status", "failed");    }  std::string testPath = result->Path + "/" + result->Name;  xml.Element("Name", result->Name);  xml.Element("Path", this->CTest->GetShortPathToFile(result->Path.c_str()));  xml.Element("FullName", this->CTest->GetShortPathToFile(testPath.c_str()));  xml.Element("FullCommandLine", result->FullCommandLine);}//----------------------------------------------------------------------------void cmCTestTestHandler::WriteTestResultFooter(cmXMLWriter& xml,                                               cmCTestTestResult* result){  if(!result->Properties->Labels.empty())    {    xml.StartElement("Labels");    std::vector<std::string> const& labels = result->Properties->Labels;    for(std::vector<std::string>::const_iterator li = labels.begin();        li != labels.end(); ++li)      {      xml.Element("Label", *li);      }    xml.EndElement(); // Labels    }  xml.EndElement(); // Test}//----------------------------------------------------------------------void cmCTestTestHandler::AttachFiles(cmXMLWriter& xml,                                     cmCTestTestResult* result){  if(result->Status != cmCTestTestHandler::COMPLETED     && result->Properties->AttachOnFail.size())    {    result->Properties->AttachedFiles.insert(      result->Properties->AttachedFiles.end(),      result->Properties->AttachOnFail.begin(),      result->Properties->AttachOnFail.end());    }  for(std::vector<std::string>::const_iterator file =      result->Properties->AttachedFiles.begin();      file != result->Properties->AttachedFiles.end(); ++file)    {    const std::string &base64 = this->CTest->Base64GzipEncodeFile(*file);    std::string fname = cmSystemTools::GetFilenameName(*file);    xml.StartElement("NamedMeasurement");    xml.Attribute("name", "Attached File");    xml.Attribute("encoding", "base64");    xml.Attribute("compression", "tar/gzip");    xml.Attribute("filename", fname);    xml.Attribute("type", "file");    xml.Element("Value", base64);    xml.EndElement(); // NamedMeasurement    }}//----------------------------------------------------------------------int cmCTestTestHandler::ExecuteCommands(std::vector<std::string>& vec){  std::vector<std::string>::iterator it;  for ( it = vec.begin(); it != vec.end(); ++it )    {    int retVal = 0;    cmCTestOptionalLog(this->CTest, HANDLER_VERBOSE_OUTPUT, "Run command: " <<      *it << std::endl, this->Quiet);    if ( !cmSystemTools::RunSingleCommand(it->c_str(), 0, 0, &retVal, 0,                                          cmSystemTools::OUTPUT_MERGE        /*this->Verbose*/) || retVal != 0 )      {      cmCTestLog(this->CTest, ERROR_MESSAGE, "Problem running command: "        << *it << std::endl);      return 0;      }    }  return 1;}//----------------------------------------------------------------------// Find the appropriate executable to run for a teststd::string cmCTestTestHandler::FindTheExecutable(const char *exe){  std::string resConfig;  std::vector<std::string> extraPaths;  std::vector<std::string> failedPaths;  if(strcmp(exe, "NOT_AVAILABLE") == 0)    {    return exe;    }  return cmCTestTestHandler::FindExecutable(this->CTest,                                            exe, resConfig,                                            extraPaths,                                            failedPaths);}// add additional configurations to the search pathvoid cmCTestTestHandler::AddConfigurations(cmCTest *ctest,                    std::vector<std::string> &attempted,                    std::vector<std::string> &attemptedConfigs,                    std::string filepath,                    std::string &filename){  std::string tempPath;  if (!filepath.empty() &&      filepath[filepath.size()-1] != '/')    {    filepath += "/";    }  tempPath = filepath + filename;  attempted.push_back(tempPath);  attemptedConfigs.push_back("");  if(!ctest->GetConfigType().empty())    {    tempPath = filepath;    tempPath += ctest->GetConfigType();    tempPath += "/";    tempPath += filename;    attempted.push_back(tempPath);    attemptedConfigs.push_back(ctest->GetConfigType());    // If the file is an OSX bundle then the configtype    // will be at the start of the path    tempPath = ctest->GetConfigType();    tempPath += "/";    tempPath += filepath;    tempPath += filename;    attempted.push_back(tempPath);    attemptedConfigs.push_back(ctest->GetConfigType());    }  else    {    // no config specified - try some options...    tempPath = filepath;    tempPath += "Release/";    tempPath += filename;    attempted.push_back(tempPath);    attemptedConfigs.push_back("Release");    tempPath = filepath;    tempPath += "Debug/";    tempPath += filename;    attempted.push_back(tempPath);    attemptedConfigs.push_back("Debug");    tempPath = filepath;    tempPath += "MinSizeRel/";    tempPath += filename;    attempted.push_back(tempPath);    attemptedConfigs.push_back("MinSizeRel");    tempPath = filepath;    tempPath += "RelWithDebInfo/";    tempPath += filename;    attempted.push_back(tempPath);    attemptedConfigs.push_back("RelWithDebInfo");    tempPath = filepath;    tempPath += "Deployment/";    tempPath += filename;    attempted.push_back(tempPath);    attemptedConfigs.push_back("Deployment");    tempPath = filepath;    tempPath += "Development/";    tempPath += filename;    attempted.push_back(tempPath);    attemptedConfigs.push_back("Deployment");    }}//----------------------------------------------------------------------// Find the appropriate executable to run for a teststd::string cmCTestTestHandler::FindExecutable(cmCTest *ctest,                 const char *testCommand,                 std::string &resultingConfig,                 std::vector<std::string> &extraPaths,                 std::vector<std::string> &failed){  // now run the compiled test if we can find it  std::vector<std::string> attempted;  std::vector<std::string> attemptedConfigs;  std::string tempPath;  std::string filepath =    cmSystemTools::GetFilenamePath(testCommand);  std::string filename =    cmSystemTools::GetFilenameName(testCommand);  cmCTestTestHandler::AddConfigurations(ctest, attempted,                                        attemptedConfigs,                                        filepath,filename);  // even if a fullpath was specified also try it relative to the current  // directory  if (!filepath.empty() && filepath[0] == '/')    {    std::string localfilepath = filepath.substr(1,filepath.size()-1);    cmCTestTestHandler::AddConfigurations(ctest, attempted,                                          attemptedConfigs,                                          localfilepath,filename);    }  // if extraPaths are provided and we were not passed a full path, try them,  // try any extra paths  if (filepath.empty())    {    for (unsigned int i = 0; i < extraPaths.size(); ++i)      {      std::string filepathExtra =        cmSystemTools::GetFilenamePath(extraPaths[i]);      std::string filenameExtra =        cmSystemTools::GetFilenameName(extraPaths[i]);      cmCTestTestHandler::AddConfigurations(ctest,attempted,                                            attemptedConfigs,                                            filepathExtra,                                            filenameExtra);      }    }  // store the final location in fullPath  std::string fullPath;  // now look in the paths we specified above  for(unsigned int ai=0;      ai < attempted.size() && fullPath.empty(); ++ai)    {    // first check without exe extension    if(cmSystemTools::FileExists(attempted[ai].c_str())       && !cmSystemTools::FileIsDirectory(attempted[ai]))      {      fullPath = cmSystemTools::CollapseFullPath(attempted[ai]);      resultingConfig = attemptedConfigs[ai];      }    // then try with the exe extension    else      {      failed.push_back(attempted[ai]);      tempPath = attempted[ai];      tempPath += cmSystemTools::GetExecutableExtension();      if(cmSystemTools::FileExists(tempPath.c_str())         && !cmSystemTools::FileIsDirectory(tempPath))        {        fullPath = cmSystemTools::CollapseFullPath(tempPath);        resultingConfig = attemptedConfigs[ai];        }      else        {        failed.push_back(tempPath);        }      }    }  // if everything else failed, check the users path, but only if a full path  // wasn't specified  if (fullPath.empty() && filepath.empty())    {    std::string path = cmSystemTools::FindProgram(filename.c_str());    if (path != "")      {      resultingConfig = "";      return path;      }    }  if(fullPath.empty())    {    cmCTestLog(ctest, HANDLER_OUTPUT,               "Could not find executable " << testCommand << "\n"               << "Looked in the following places:\n");    for(std::vector<std::string>::iterator i = failed.begin();        i != failed.end(); ++i)      {      cmCTestLog(ctest, HANDLER_OUTPUT, i->c_str() << "\n");      }    }  return fullPath;}//----------------------------------------------------------------------void cmCTestTestHandler::GetListOfTests(){  if ( !this->IncludeLabelRegExp.empty() )    {    this->IncludeLabelRegularExpression.      compile(this->IncludeLabelRegExp.c_str());    }  if ( !this->ExcludeLabelRegExp.empty() )    {    this->ExcludeLabelRegularExpression.      compile(this->ExcludeLabelRegExp.c_str());    }  if ( !this->IncludeRegExp.empty() )    {    this->IncludeTestsRegularExpression.compile(this->IncludeRegExp.c_str());    }  if ( !this->ExcludeRegExp.empty() )    {    this->ExcludeTestsRegularExpression.compile(this->ExcludeRegExp.c_str());    }  cmCTestOptionalLog(this->CTest, HANDLER_VERBOSE_OUTPUT,    "Constructing a list of tests" << std::endl, this->Quiet);  cmake cm;  cm.SetHomeDirectory("");  cm.SetHomeOutputDirectory("");  cm.GetCurrentSnapshot().SetDefaultDefinitions();  cmGlobalGenerator gg(&cm);  cmsys::auto_ptr<cmMakefile> mf(new cmMakefile(&gg, cm.GetCurrentSnapshot()));  mf->AddDefinition("CTEST_CONFIGURATION_TYPE",    this->CTest->GetConfigType().c_str());  // Add handler for ADD_TEST  cmCTestAddTestCommand* newCom1 = new cmCTestAddTestCommand;  newCom1->TestHandler = this;  cm.GetState()->AddCommand(newCom1);  // Add handler for SUBDIRS  cmCTestSubdirCommand* newCom2 =    new cmCTestSubdirCommand;  newCom2->TestHandler = this;  cm.GetState()->AddCommand(newCom2);  // Add handler for ADD_SUBDIRECTORY  cmCTestAddSubdirectoryCommand* newCom3 =    new cmCTestAddSubdirectoryCommand;  newCom3->TestHandler = this;  cm.GetState()->AddCommand(newCom3);  // Add handler for SET_SOURCE_FILES_PROPERTIES  cmCTestSetTestsPropertiesCommand* newCom4    = new cmCTestSetTestsPropertiesCommand;  newCom4->TestHandler = this;  cm.GetState()->AddCommand(newCom4);  const char* testFilename;  if( cmSystemTools::FileExists("CTestTestfile.cmake") )    {    // does the CTestTestfile.cmake exist ?    testFilename = "CTestTestfile.cmake";    }  else if( cmSystemTools::FileExists("DartTestfile.txt") )    {    // does the DartTestfile.txt exist ?    testFilename = "DartTestfile.txt";    }  else    {    return;    }  if ( !mf->ReadListFile(testFilename) )    {    return;    }  if ( cmSystemTools::GetErrorOccuredFlag() )    {    return;    }  cmCTestOptionalLog(this->CTest, HANDLER_VERBOSE_OUTPUT,    "Done constructing a list of tests" << std::endl, this->Quiet);}//----------------------------------------------------------------------void cmCTestTestHandler::UseIncludeRegExp(){  this->UseIncludeRegExpFlag = true;}//----------------------------------------------------------------------void cmCTestTestHandler::UseExcludeRegExp(){  this->UseExcludeRegExpFlag = true;  this->UseExcludeRegExpFirst = this->UseIncludeRegExpFlag ? false : true;}//----------------------------------------------------------------------const char* cmCTestTestHandler::GetTestStatus(int status){  static const char statuses[][100] = {    "Not Run",    "Timeout",    "SEGFAULT",    "ILLEGAL",    "INTERRUPT",    "NUMERICAL",    "OTHER_FAULT",    "Failed",    "BAD_COMMAND",    "Completed"  };  if ( status < cmCTestTestHandler::NOT_RUN ||       status > cmCTestTestHandler::COMPLETED )    {    return "No Status";    }  return statuses[status];}//----------------------------------------------------------------------void cmCTestTestHandler::ExpandTestsToRunInformation(size_t numTests){  if (this->TestsToRunString.empty())    {    return;    }  int start;  int end = -1;  double stride = -1;  std::string::size_type pos = 0;  std::string::size_type pos2;  // read start  if(GetNextNumber(this->TestsToRunString, start, pos, pos2))    {    // read end    if(GetNextNumber(this->TestsToRunString, end, pos, pos2))      {      // read stride      if(GetNextRealNumber(this->TestsToRunString, stride, pos, pos2))        {        int val =0;        // now read specific numbers        while(GetNextNumber(this->TestsToRunString, val, pos, pos2))          {          this->TestsToRun.push_back(val);          }        this->TestsToRun.push_back(val);        }      }    }  // if start is not specified then we assume we start at 1  if(start == -1)    {    start = 1;    }  // if end isnot specified then we assume we end with the last test  if(end == -1)    {    end = static_cast<int>(numTests);    }  // if the stride wasn't specified then it defaults to 1  if(stride == -1)    {    stride = 1;    }  // if we have a range then add it  if(end != -1 && start != -1 && stride > 0)    {    int i = 0;    while (i*stride + start <= end)      {      this->TestsToRun.push_back(static_cast<int>(i*stride+start));      ++i;      }    }  // sort the array  std::sort(this->TestsToRun.begin(), this->TestsToRun.end(),    std::less<int>());  // remove duplicates  std::vector<int>::iterator new_end =    std::unique(this->TestsToRun.begin(), this->TestsToRun.end());  this->TestsToRun.erase(new_end, this->TestsToRun.end());}void cmCTestTestHandler::ExpandTestsToRunInformationForRerunFailed(){  std::string dirName = this->CTest->GetBinaryDir() + "/Testing/Temporary";  cmsys::Directory directory;  if (directory.Load(dirName) == 0)    {    cmCTestLog(this->CTest, ERROR_MESSAGE, "Unable to read the contents of "      << dirName << std::endl);    return;    }  int numFiles = static_cast<int>    (cmsys::Directory::GetNumberOfFilesInDirectory(dirName));  std::string pattern = "LastTestsFailed";  std::string logName = "";  for (int i = 0; i < numFiles; ++i)    {    std::string fileName = directory.GetFile(i);    // bcc crashes if we attempt a normal substring comparison,    // hence the following workaround    std::string fileNameSubstring = fileName.substr(0, pattern.length());    if (fileNameSubstring.compare(pattern) != 0)      {      continue;      }    if (logName == "")      {      logName = fileName;      }    else      {      // if multiple matching logs were found we use the most recently      // modified one.      int res;      cmSystemTools::FileTimeCompare(logName, fileName, &res);      if (res == -1)        {        logName = fileName;        }      }    }  std::string lastTestsFailedLog = this->CTest->GetBinaryDir()    + "/Testing/Temporary/" + logName;  if ( !cmSystemTools::FileExists(lastTestsFailedLog.c_str()) )    {    if ( !this->CTest->GetShowOnly() && !this->CTest->ShouldPrintLabels() )      {      cmCTestLog(this->CTest, ERROR_MESSAGE, lastTestsFailedLog        << " does not exist!" << std::endl);      }    return;    }  // parse the list of tests to rerun from LastTestsFailed.log  cmsys::ifstream ifs(lastTestsFailedLog.c_str());  if ( ifs )    {    std::string line;    std::string::size_type pos;    while ( cmSystemTools::GetLineFromStream(ifs, line) )      {      pos = line.find(':', 0);      if (pos == line.npos)        {        continue;        }      int val = atoi(line.substr(0, pos).c_str());      this->TestsToRun.push_back(val);      }    ifs.close();    }  else if ( !this->CTest->GetShowOnly() && !this->CTest->ShouldPrintLabels() )    {    cmCTestLog(this->CTest, ERROR_MESSAGE, "Problem reading file: "      << lastTestsFailedLog <<      " while generating list of previously failed tests." << std::endl);    }}//----------------------------------------------------------------------// Just for convenience#define SPACE_REGEX "[ \t\r\n]"//----------------------------------------------------------------------void cmCTestTestHandler::GenerateRegressionImages(  cmXMLWriter& xml, const std::string& dart){  cmsys::RegularExpression twoattributes(    "<DartMeasurement"    SPACE_REGEX "*(name|type|encoding|compression)=\"([^\"]*)\""    SPACE_REGEX "*(name|type|encoding|compression)=\"([^\"]*)\""    SPACE_REGEX "*>([^<]*)</DartMeasurement>");  cmsys::RegularExpression threeattributes(    "<DartMeasurement"    SPACE_REGEX "*(name|type|encoding|compression)=\"([^\"]*)\""    SPACE_REGEX "*(name|type|encoding|compression)=\"([^\"]*)\""    SPACE_REGEX "*(name|type|encoding|compression)=\"([^\"]*)\""    SPACE_REGEX "*>([^<]*)</DartMeasurement>");  cmsys::RegularExpression fourattributes(    "<DartMeasurement"    SPACE_REGEX "*(name|type|encoding|compression)=\"([^\"]*)\""    SPACE_REGEX "*(name|type|encoding|compression)=\"([^\"]*)\""    SPACE_REGEX "*(name|type|encoding|compression)=\"([^\"]*)\""    SPACE_REGEX "*(name|type|encoding|compression)=\"([^\"]*)\""    SPACE_REGEX "*>([^<]*)</DartMeasurement>");  cmsys::RegularExpression cdatastart(    "<DartMeasurement"    SPACE_REGEX "*(name|type|encoding|compression)=\"([^\"]*)\""    SPACE_REGEX "*(name|type|encoding|compression)=\"([^\"]*)\""    SPACE_REGEX "*>"    SPACE_REGEX "*<!\\[CDATA\\[");  cmsys::RegularExpression cdataend(    "]]>"    SPACE_REGEX "*</DartMeasurement>");  cmsys::RegularExpression measurementfile(    "<DartMeasurementFile"    SPACE_REGEX "*(name|type|encoding|compression)=\"([^\"]*)\""    SPACE_REGEX "*(name|type|encoding|compression)=\"([^\"]*)\""    SPACE_REGEX "*>([^<]*)</DartMeasurementFile>");  bool done = false;  std::string cxml = dart;  while ( ! done )    {    if ( twoattributes.find(cxml) )      {      xml.StartElement("NamedMeasurement");      xml.Attribute(twoattributes.match(1).c_str(),                    twoattributes.match(2));      xml.Attribute(twoattributes.match(3).c_str(),                    twoattributes.match(4));      xml.Element("Value", twoattributes.match(5));      xml.EndElement();      cxml.erase(twoattributes.start(),        twoattributes.end() - twoattributes.start());      }    else if ( threeattributes.find(cxml) )      {      xml.StartElement("NamedMeasurement");      xml.Attribute(threeattributes.match(1).c_str(),                    threeattributes.match(2));      xml.Attribute(threeattributes.match(3).c_str(),                    threeattributes.match(4));      xml.Attribute(threeattributes.match(5).c_str(),                    threeattributes.match(6));      xml.Element("Value", twoattributes.match(7));      xml.EndElement();      cxml.erase(threeattributes.start(),        threeattributes.end() - threeattributes.start());      }    else if ( fourattributes.find(cxml) )      {      xml.StartElement("NamedMeasurement");      xml.Attribute(fourattributes.match(1).c_str(),                    fourattributes.match(2));      xml.Attribute(fourattributes.match(3).c_str(),                    fourattributes.match(4));      xml.Attribute(fourattributes.match(5).c_str(),                    fourattributes.match(6));      xml.Attribute(fourattributes.match(7).c_str(),                    fourattributes.match(8));      xml.Element("Value", twoattributes.match(9));      xml.EndElement();      cxml.erase(fourattributes.start(),        fourattributes.end() - fourattributes.start());      }    else if ( cdatastart.find(cxml) && cdataend.find(cxml) )      {      xml.StartElement("NamedMeasurement");      xml.Attribute(cdatastart.match(1).c_str(), cdatastart.match(2));      xml.Attribute(cdatastart.match(3).c_str(), cdatastart.match(4));      xml.StartElement("Value");      xml.CData(          cxml.substr(cdatastart.end(), cdataend.start() - cdatastart.end()));      xml.EndElement(); // Value      xml.EndElement(); // NamedMeasurement      cxml.erase(cdatastart.start(),        cdataend.end() - cdatastart.start());      }    else if ( measurementfile.find(cxml) )      {      const std::string& filename =        cmCTest::CleanString(measurementfile.match(5));      if ( cmSystemTools::FileExists(filename.c_str()) )        {        long len = cmSystemTools::FileLength(filename);        if ( len == 0 )          {          std::string k1 = measurementfile.match(1);          std::string v1 = measurementfile.match(2);          std::string k2 = measurementfile.match(3);          std::string v2 = measurementfile.match(4);          if ( cmSystemTools::LowerCase(k1) == "type" )            {            v1 = "text/string";            }          if ( cmSystemTools::LowerCase(k2) == "type" )            {            v2 = "text/string";            }          xml.StartElement("NamedMeasurement");          xml.Attribute(k1.c_str(), v1);          xml.Attribute(k2.c_str(), v2);          xml.Attribute("encoding", "none");          xml.Element("Value", "Image " + filename + " is empty");          xml.EndElement();          }        else          {          cmsys::ifstream ifs(filename.c_str(), std::ios::in#ifdef _WIN32                            | std::ios::binary#endif            );          unsigned char *file_buffer = new unsigned char [ len + 1 ];          ifs.read(reinterpret_cast<char*>(file_buffer), len);          unsigned char *encoded_buffer            = new unsigned char [ static_cast<int>(                static_cast<double>(len) * 1.5 + 5.0) ];          size_t rlen            = cmsysBase64_Encode(file_buffer, len, encoded_buffer, 1);          xml.StartElement("NamedMeasurement");          xml.Attribute(measurementfile.match(1).c_str(),                        measurementfile.match(2));          xml.Attribute(measurementfile.match(3).c_str(),                        measurementfile.match(4));          xml.Attribute("encoding", "base64");          std::stringstream ostr;          for (size_t cc = 0; cc < rlen; cc ++ )            {            ostr << encoded_buffer[cc];            if ( cc % 60 == 0 && cc )              {              ostr << std::endl;              }            }          xml.Element("Value", ostr.str());          xml.EndElement(); // NamedMeasurement          delete [] file_buffer;          delete [] encoded_buffer;          }        }      else        {        int idx = 4;        if ( measurementfile.match(1) == "name" )          {          idx = 2;          }        xml.StartElement("NamedMeasurement");        xml.Attribute("name", measurementfile.match(idx));        xml.Attribute("text", "text/string");        xml.Element("Value", "File " + filename + " not found");        xml.EndElement();        cmCTestOptionalLog(this->CTest, HANDLER_OUTPUT, "File \"" << filename          << "\" not found." << std::endl, this->Quiet);        }      cxml.erase(measurementfile.start(),        measurementfile.end() - measurementfile.start());      }    else      {      done = true;      }    }}//----------------------------------------------------------------------void cmCTestTestHandler::SetIncludeRegExp(const char *arg){  this->IncludeRegExp = arg;}//----------------------------------------------------------------------void cmCTestTestHandler::SetExcludeRegExp(const char *arg){  this->ExcludeRegExp = arg;}//----------------------------------------------------------------------void cmCTestTestHandler::SetTestsToRunInformation(const char* in){  if ( !in )    {    return;    }  this->TestsToRunString = in;  // if the argument is a file, then read it and use the contents as the  // string  if(cmSystemTools::FileExists(in))    {    cmsys::ifstream fin(in);    unsigned long filelen = cmSystemTools::FileLength(in);    char* buff = new char[filelen+1];    fin.getline(buff, filelen);    buff[fin.gcount()] = 0;    this->TestsToRunString = buff;    delete [] buff;    }}//----------------------------------------------------------------------------bool cmCTestTestHandler::CleanTestOutput(std::string& output, size_t length){  if(!length || length >= output.size() ||     output.find("CTEST_FULL_OUTPUT") != output.npos)    {    return true;    }  // Truncate at given length but do not break in the middle of a multi-byte  // UTF-8 encoding.  char const* const begin = output.c_str();  char const* const end = begin + output.size();  char const* const truncate = begin + length;  char const* current = begin;  while(current < truncate)    {    unsigned int ch;    if(const char* next = cm_utf8_decode_character(current, end, &ch))      {      if(next > truncate)        {        break;        }      current = next;      }    else // Bad byte will be handled by cmXMLWriter.      {      ++current;      }    }  output = output.substr(0, current - begin);  // Append truncation message.  std::ostringstream msg;  msg << "...\n"    "The rest of the test output was removed since it exceeds the threshold "    "of " << length << " bytes.\n";  output += msg.str();  return true;}//----------------------------------------------------------------------bool cmCTestTestHandler::SetTestsProperties(  const std::vector<std::string>& args){  std::vector<std::string>::const_iterator it;  std::vector<std::string> tests;  bool found = false;  for ( it = args.begin(); it != args.end(); ++ it )    {    if ( *it == "PROPERTIES" )      {      found = true;      break;      }    tests.push_back(*it);    }  if ( !found )    {    return false;    }  ++ it; // skip PROPERTIES  for ( ; it != args.end(); ++ it )    {    std::string key = *it;    ++ it;    if ( it == args.end() )      {      break;      }    std::string val = *it;    std::vector<std::string>::const_iterator tit;    for ( tit = tests.begin(); tit != tests.end(); ++ tit )      {      cmCTestTestHandler::ListOfTests::iterator rtit;      for ( rtit = this->TestList.begin();        rtit != this->TestList.end();        ++ rtit )        {        if ( *tit == rtit->Name )          {          if ( key == "WILL_FAIL" )            {            rtit->WillFail = cmSystemTools::IsOn(val.c_str());            }          if ( key == "ATTACHED_FILES" )            {            cmSystemTools::ExpandListArgument(val, rtit->AttachedFiles);            }          if ( key == "ATTACHED_FILES_ON_FAIL" )            {            cmSystemTools::ExpandListArgument(val, rtit->AttachOnFail);            }          if ( key == "RESOURCE_LOCK" )            {            std::vector<std::string> lval;            cmSystemTools::ExpandListArgument(val, lval);            rtit->LockedResources.insert(lval.begin(), lval.end());            }          if ( key == "TIMEOUT" )            {            rtit->Timeout = atof(val.c_str());            rtit->ExplicitTimeout = true;            }          if ( key == "COST" )            {            rtit->Cost = static_cast<float>(atof(val.c_str()));            }          if ( key == "REQUIRED_FILES" )            {            cmSystemTools::ExpandListArgument(val, rtit->RequiredFiles);            }          if ( key == "RUN_SERIAL" )            {            rtit->RunSerial = cmSystemTools::IsOn(val.c_str());            }          if ( key == "FAIL_REGULAR_EXPRESSION" )            {            std::vector<std::string> lval;            cmSystemTools::ExpandListArgument(val, lval);            std::vector<std::string>::iterator crit;            for ( crit = lval.begin(); crit != lval.end(); ++ crit )              {              rtit->ErrorRegularExpressions.push_back(                std::pair<cmsys::RegularExpression, std::string>(                  cmsys::RegularExpression(crit->c_str()),                  std::string(*crit)));              }            }          if ( key == "PROCESSORS" )            {            rtit->Processors = atoi(val.c_str());            if(rtit->Processors < 1)              {              rtit->Processors = 1;              }            }          if ( key == "SKIP_RETURN_CODE" )            {            rtit->SkipReturnCode = atoi(val.c_str());            if(rtit->SkipReturnCode < 0 || rtit->SkipReturnCode > 255)              {              rtit->SkipReturnCode = -1;              }            }          if ( key == "DEPENDS" )            {            cmSystemTools::ExpandListArgument(val, rtit->Depends);            }          if ( key == "ENVIRONMENT" )            {            cmSystemTools::ExpandListArgument(val, rtit->Environment);            }          if ( key == "LABELS" )            {            cmSystemTools::ExpandListArgument(val, rtit->Labels);            }          if ( key == "MEASUREMENT" )            {            size_t pos = val.find_first_of("=");            if ( pos != val.npos )              {              std::string mKey = val.substr(0, pos);              const char* mVal = val.c_str() + pos + 1;              rtit->Measurements[mKey] = mVal;              }            else              {              rtit->Measurements[val] = "1";              }            }          if ( key == "PASS_REGULAR_EXPRESSION" )            {            std::vector<std::string> lval;            cmSystemTools::ExpandListArgument(val, lval);            std::vector<std::string>::iterator crit;            for ( crit = lval.begin(); crit != lval.end(); ++ crit )              {              rtit->RequiredRegularExpressions.push_back(                std::pair<cmsys::RegularExpression, std::string>(                  cmsys::RegularExpression(crit->c_str()),                  std::string(*crit)));              }            }          if ( key == "WORKING_DIRECTORY" )            {            rtit->Directory = val;            }          }        }      }    }  return true;}//----------------------------------------------------------------------bool cmCTestTestHandler::AddTest(const std::vector<std::string>& args){  const std::string& testname = args[0];  cmCTestOptionalLog(this->CTest, DEBUG, "Add test: " << args[0] << std::endl,    this->Quiet);  if (this->UseExcludeRegExpFlag &&    this->UseExcludeRegExpFirst &&    this->ExcludeTestsRegularExpression.find(testname.c_str()))    {    return true;    }  if ( this->MemCheck )    {    std::vector<std::string>::iterator it;    bool found = false;    for ( it = this->CustomTestsIgnore.begin();      it != this->CustomTestsIgnore.end(); ++ it )      {      if ( *it == testname )        {        found = true;        break;        }      }    if ( found )      {      cmCTestOptionalLog(this->CTest, HANDLER_VERBOSE_OUTPUT,        "Ignore memcheck: " << *it << std::endl, this->Quiet);      return true;      }    }  else    {    std::vector<std::string>::iterator it;    bool found = false;    for ( it = this->CustomTestsIgnore.begin();      it != this->CustomTestsIgnore.end(); ++ it )      {      if ( *it == testname )        {        found = true;        break;        }      }    if ( found )      {      cmCTestOptionalLog(this->CTest, HANDLER_VERBOSE_OUTPUT, "Ignore test: "        << *it << std::endl, this->Quiet);      return true;      }    }  cmCTestTestProperties test;  test.Name = testname;  test.Args = args;  test.Directory = cmSystemTools::GetCurrentWorkingDirectory();  cmCTestOptionalLog(this->CTest, DEBUG, "Set test directory: "    << test.Directory << std::endl, this->Quiet);  test.IsInBasedOnREOptions = true;  test.WillFail = false;  test.RunSerial = false;  test.Timeout = 0;  test.ExplicitTimeout = false;  test.Cost = 0;  test.Processors = 1;  test.SkipReturnCode = -1;  test.PreviousRuns = 0;  if (this->UseIncludeRegExpFlag &&    !this->IncludeTestsRegularExpression.find(testname.c_str()))    {    test.IsInBasedOnREOptions = false;    }  else if (this->UseExcludeRegExpFlag &&    !this->UseExcludeRegExpFirst &&    this->ExcludeTestsRegularExpression.find(testname.c_str()))    {    test.IsInBasedOnREOptions = false;    }  this->TestList.push_back(test);  return true;}
 |