1 /*=========================================================================
3 Program: CMake - Cross-Platform Makefile Generator
4 Module: $RCSfile: cmCTestTestHandler.cxx,v $
6 Date: $Date: 2009-02-27 21:28:07 $
7 Version: $Revision: 1.94 $
9 Copyright (c) 2002 Kitware, Inc., Insight Consortium. All rights reserved.
10 See Copyright.txt or http://www.cmake.org/HTML/Copyright.html for details.
12 This software is distributed WITHOUT ANY WARRANTY; without even
13 the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
14 PURPOSE. See the above copyright notices for more information.
16 =========================================================================*/
18 #include "cmCTestTestHandler.h"
19 #include "cmCTestMultiProcessHandler.h"
22 #include "cmGeneratedFileStream.h"
23 #include <cmsys/Process.h>
24 #include <cmsys/RegularExpression.hxx>
25 #include <cmsys/Base64.h>
26 #include "cmMakefile.h"
27 #include "cmGlobalGenerator.h"
28 #include "cmLocalGenerator.h"
29 #include "cmCommand.h"
30 #include "cmSystemTools.h"
31 #include "cmXMLSafe.h"
37 #include <memory> // auto_ptr
39 //----------------------------------------------------------------------
40 class cmCTestSubdirCommand
: public cmCommand
44 * This is a virtual constructor for the command.
46 virtual cmCommand
* Clone()
48 cmCTestSubdirCommand
* c
= new cmCTestSubdirCommand
;
49 c
->TestHandler
= this->TestHandler
;
54 * This is called when the command is first encountered in
55 * the CMakeLists.txt file.
57 virtual bool InitialPass(std::vector
<std::string
> const& args
,
61 * The name of the command as specified in CMakeList.txt.
63 virtual const char* GetName() { return "subdirs";}
66 virtual const char* GetTerseDocumentation() { return ""; }
67 virtual const char* GetFullDocumentation() { return ""; }
69 cmTypeMacro(cmCTestSubdirCommand
, cmCommand
);
71 cmCTestTestHandler
* TestHandler
;
74 //----------------------------------------------------------------------
75 bool cmCTestSubdirCommand
76 ::InitialPass(std::vector
<std::string
> const& args
, cmExecutionStatus
&)
80 this->SetError("called with incorrect number of arguments");
83 std::vector
<std::string
>::const_iterator it
;
84 std::string cwd
= cmSystemTools::GetCurrentWorkingDirectory();
85 for ( it
= args
.begin(); it
!= args
.end(); ++ it
)
87 cmSystemTools::ChangeDirectory(cwd
.c_str());
88 std::string fname
= cwd
;
92 if ( !cmSystemTools::FileExists(fname
.c_str()) )
94 // No subdirectory? So what...
97 cmSystemTools::ChangeDirectory(fname
.c_str());
98 const char* testFilename
;
99 if( cmSystemTools::FileExists("CTestTestfile.cmake") )
101 // does the CTestTestfile.cmake exist ?
102 testFilename
= "CTestTestfile.cmake";
104 else if( cmSystemTools::FileExists("DartTestfile.txt") )
106 // does the DartTestfile.txt exist ?
107 testFilename
= "DartTestfile.txt";
111 // No CTestTestfile? Who cares...
112 cmSystemTools::ChangeDirectory(cwd
.c_str());
116 fname
+= testFilename
;
118 this->Makefile
->ReadListFile(this->Makefile
->GetCurrentListFile(),
120 cmSystemTools::ChangeDirectory(cwd
.c_str());
123 std::string m
= "Could not find include file: ";
125 this->SetError(m
.c_str());
132 //----------------------------------------------------------------------
133 class cmCTestAddSubdirectoryCommand
: public cmCommand
137 * This is a virtual constructor for the command.
139 virtual cmCommand
* Clone()
141 cmCTestAddSubdirectoryCommand
* c
= new cmCTestAddSubdirectoryCommand
;
142 c
->TestHandler
= this->TestHandler
;
147 * This is called when the command is first encountered in
148 * the CMakeLists.txt file.
150 virtual bool InitialPass(std::vector
<std::string
> const& args
,
151 cmExecutionStatus
&);
154 * The name of the command as specified in CMakeList.txt.
156 virtual const char* GetName() { return "add_subdirectory";}
159 virtual const char* GetTerseDocumentation() { return ""; }
160 virtual const char* GetFullDocumentation() { return ""; }
162 cmTypeMacro(cmCTestAddSubdirectoryCommand
, cmCommand
);
164 cmCTestTestHandler
* TestHandler
;
167 //----------------------------------------------------------------------
168 bool cmCTestAddSubdirectoryCommand
169 ::InitialPass(std::vector
<std::string
> const& args
, cmExecutionStatus
&)
173 this->SetError("called with incorrect number of arguments");
177 std::string cwd
= cmSystemTools::GetCurrentWorkingDirectory();
178 cmSystemTools::ChangeDirectory(cwd
.c_str());
179 std::string fname
= cwd
;
183 if ( !cmSystemTools::FileExists(fname
.c_str()) )
185 // No subdirectory? So what...
188 cmSystemTools::ChangeDirectory(fname
.c_str());
189 const char* testFilename
;
190 if( cmSystemTools::FileExists("CTestTestfile.cmake") )
192 // does the CTestTestfile.cmake exist ?
193 testFilename
= "CTestTestfile.cmake";
195 else if( cmSystemTools::FileExists("DartTestfile.txt") )
197 // does the DartTestfile.txt exist ?
198 testFilename
= "DartTestfile.txt";
202 // No CTestTestfile? Who cares...
203 cmSystemTools::ChangeDirectory(cwd
.c_str());
207 fname
+= testFilename
;
209 this->Makefile
->ReadListFile(this->Makefile
->GetCurrentListFile(),
211 cmSystemTools::ChangeDirectory(cwd
.c_str());
214 std::string m
= "Could not find include file: ";
216 this->SetError(m
.c_str());
222 //----------------------------------------------------------------------
223 class cmCTestAddTestCommand
: public cmCommand
227 * This is a virtual constructor for the command.
229 virtual cmCommand
* Clone()
231 cmCTestAddTestCommand
* c
= new cmCTestAddTestCommand
;
232 c
->TestHandler
= this->TestHandler
;
237 * This is called when the command is first encountered in
238 * the CMakeLists.txt file.
240 virtual bool InitialPass(std::vector
<std::string
> const&,
241 cmExecutionStatus
&);
244 * The name of the command as specified in CMakeList.txt.
246 virtual const char* GetName() { return "ADD_TEST";}
249 virtual const char* GetTerseDocumentation() { return ""; }
250 virtual const char* GetFullDocumentation() { return ""; }
252 cmTypeMacro(cmCTestAddTestCommand
, cmCommand
);
254 cmCTestTestHandler
* TestHandler
;
257 //----------------------------------------------------------------------
258 bool cmCTestAddTestCommand
259 ::InitialPass(std::vector
<std::string
> const& args
, cmExecutionStatus
&)
261 if ( args
.size() < 2 )
263 this->SetError("called with incorrect number of arguments");
266 return this->TestHandler
->AddTest(args
);
269 //----------------------------------------------------------------------
270 class cmCTestSetTestsPropertiesCommand
: public cmCommand
274 * This is a virtual constructor for the command.
276 virtual cmCommand
* Clone()
278 cmCTestSetTestsPropertiesCommand
* c
279 = new cmCTestSetTestsPropertiesCommand
;
280 c
->TestHandler
= this->TestHandler
;
285 * This is called when the command is first encountered in
286 * the CMakeLists.txt file.
288 virtual bool InitialPass(std::vector
<std::string
> const&,
289 cmExecutionStatus
&);
292 * The name of the command as specified in CMakeList.txt.
294 virtual const char* GetName() { return "SET_TESTS_PROPERTIES";}
297 virtual const char* GetTerseDocumentation() { return ""; }
298 virtual const char* GetFullDocumentation() { return ""; }
300 cmTypeMacro(cmCTestSetTestsPropertiesCommand
, cmCommand
);
302 cmCTestTestHandler
* TestHandler
;
305 //----------------------------------------------------------------------
306 bool cmCTestSetTestsPropertiesCommand
307 ::InitialPass(std::vector
<std::string
> const& args
, cmExecutionStatus
&)
309 return this->TestHandler
->SetTestsProperties(args
);
312 //----------------------------------------------------------------------
313 // get the next number in a string with numbers separated by ,
314 // pos is the start of the search and pos2 is the end of the search
315 // pos becomes pos2 after a call to GetNextNumber.
316 // -1 is returned at the end of the list.
317 inline int GetNextNumber(std::string
const& in
,
319 std::string::size_type
& pos
,
320 std::string::size_type
& pos2
)
322 pos2
= in
.find(',', pos
);
331 val
= atoi(in
.substr(pos
, pos2
-pos
).c_str());
338 if(in
.size()-pos
== 0)
344 val
= atoi(in
.substr(pos
, in
.size()-pos
).c_str());
350 //----------------------------------------------------------------------
351 // get the next number in a string with numbers separated by ,
352 // pos is the start of the search and pos2 is the end of the search
353 // pos becomes pos2 after a call to GetNextNumber.
354 // -1 is returned at the end of the list.
355 inline int GetNextRealNumber(std::string
const& in
,
357 std::string::size_type
& pos
,
358 std::string::size_type
& pos2
)
360 pos2
= in
.find(',', pos
);
369 val
= atof(in
.substr(pos
, pos2
-pos
).c_str());
376 if(in
.size()-pos
== 0)
382 val
= atof(in
.substr(pos
, in
.size()-pos
).c_str());
389 //----------------------------------------------------------------------
390 cmCTestTestHandler::cmCTestTestHandler()
392 this->UseUnion
= false;
394 this->UseIncludeLabelRegExpFlag
= false;
395 this->UseExcludeLabelRegExpFlag
= false;
396 this->UseIncludeRegExpFlag
= false;
397 this->UseExcludeRegExpFlag
= false;
398 this->UseExcludeRegExpFirst
= false;
400 this->CustomMaximumPassedTestOutputSize
= 1 * 1024;
401 this->CustomMaximumFailedTestOutputSize
= 300 * 1024;
403 this->MemCheck
= false;
407 // regex to detect <DartMeasurement>...</DartMeasurement>
408 this->DartStuff
.compile(
409 "(<DartMeasurement.*/DartMeasurement[a-zA-Z]*>)");
410 // regex to detect each individual <DartMeasurement>...</DartMeasurement>
411 this->DartStuff1
.compile(
412 "(<DartMeasurement[^<]*</DartMeasurement[a-zA-Z]*>)");
415 //----------------------------------------------------------------------
416 void cmCTestTestHandler::Initialize()
418 this->Superclass::Initialize();
420 this->ElapsedTestingTime
= -1;
422 this->TestResults
.clear();
424 this->CustomTestsIgnore
.clear();
425 this->StartTest
= "";
428 this->CustomPreTest
.clear();
429 this->CustomPostTest
.clear();
430 this->CustomMaximumPassedTestOutputSize
= 1 * 1024;
431 this->CustomMaximumFailedTestOutputSize
= 300 * 1024;
433 this->TestsToRun
.clear();
435 this->UseIncludeRegExpFlag
= false;
436 this->UseExcludeRegExpFlag
= false;
437 this->UseExcludeRegExpFirst
= false;
438 this->IncludeLabelRegularExpression
= "";
439 this->ExcludeLabelRegularExpression
= "";
440 this->IncludeRegExp
= "";
441 this->ExcludeRegExp
= "";
443 TestsToRunString
= "";
444 this->UseUnion
= false;
445 this->TestList
.clear();
448 //----------------------------------------------------------------------
449 void cmCTestTestHandler::PopulateCustomVectors(cmMakefile
*mf
)
451 this->CTest
->PopulateCustomVector(mf
, "CTEST_CUSTOM_PRE_TEST",
452 this->CustomPreTest
);
453 this->CTest
->PopulateCustomVector(mf
, "CTEST_CUSTOM_POST_TEST",
454 this->CustomPostTest
);
455 this->CTest
->PopulateCustomVector(mf
,
456 "CTEST_CUSTOM_TESTS_IGNORE",
457 this->CustomTestsIgnore
);
458 this->CTest
->PopulateCustomInteger(mf
,
459 "CTEST_CUSTOM_MAXIMUM_PASSED_TEST_OUTPUT_SIZE",
460 this->CustomMaximumPassedTestOutputSize
);
461 this->CTest
->PopulateCustomInteger(mf
,
462 "CTEST_CUSTOM_MAXIMUM_FAILED_TEST_OUTPUT_SIZE",
463 this->CustomMaximumFailedTestOutputSize
);
466 //----------------------------------------------------------------------
467 int cmCTestTestHandler::PreProcessHandler()
469 if ( !this->ExecuteCommands(this->CustomPreTest
) )
471 cmCTestLog(this->CTest
, ERROR_MESSAGE
,
472 "Problem executing pre-test command(s)." << std::endl
);
478 //----------------------------------------------------------------------
479 int cmCTestTestHandler::PostProcessHandler()
481 if ( !this->ExecuteCommands(this->CustomPostTest
) )
483 cmCTestLog(this->CTest
, ERROR_MESSAGE
,
484 "Problem executing post-test command(s)." << std::endl
);
490 //----------------------------------------------------------------------
491 //clearly it would be nice if this were broken up into a few smaller
492 //functions and commented...
493 int cmCTestTestHandler::ProcessHandler()
495 // Update internal data structure from generic one
496 this->SetTestsToRunInformation(this->GetOption("TestsToRunInformation"));
497 this->SetUseUnion(cmSystemTools::IsOn(this->GetOption("UseUnion")));
499 val
= this->GetOption("LabelRegularExpression");
502 this->UseIncludeLabelRegExpFlag
= true;
503 this->IncludeLabelRegExp
= val
;
505 val
= this->GetOption("ExcludeLabelRegularExpression");
508 this->UseExcludeLabelRegExpFlag
= true;
509 this->ExcludeLabelRegularExpression
= val
;
511 val
= this->GetOption("IncludeRegularExpression");
514 this->UseIncludeRegExp();
515 this->SetIncludeRegExp(val
);
517 val
= this->GetOption("ExcludeRegularExpression");
520 this->UseExcludeRegExp();
521 this->SetExcludeRegExp(val
);
524 this->TestResults
.clear();
525 // do not output startup if this is a sub-process for parallel tests
526 if(!this->CTest
->GetParallelSubprocess())
528 cmCTestLog(this->CTest
, HANDLER_OUTPUT
,
529 (this->MemCheck
? "Memory check" : "Test")
530 << " project " << cmSystemTools::GetCurrentWorkingDirectory()
533 if ( ! this->PreProcessHandler() )
538 cmGeneratedFileStream mLogFile
;
539 this->StartLogFile((this->MemCheck
? "DynamicAnalysis" : "Test"), mLogFile
);
540 this->LogFile
= &mLogFile
;
542 std::vector
<cmStdString
> passed
;
543 std::vector
<cmStdString
> failed
;
545 this->ProcessDirectory(passed
, failed
);
547 total
= int(passed
.size()) + int(failed
.size());
551 if ( !this->CTest
->GetShowOnly() )
553 cmCTestLog(this->CTest
, ERROR_MESSAGE
, "No tests were found!!!"
559 if (this->HandlerVerbose
&& passed
.size() &&
560 (this->UseIncludeRegExpFlag
|| this->UseExcludeRegExpFlag
))
562 cmCTestLog(this->CTest
, HANDLER_VERBOSE_OUTPUT
, std::endl
563 << "The following tests passed:" << std::endl
);
564 for(std::vector
<cmStdString
>::iterator j
= passed
.begin();
565 j
!= passed
.end(); ++j
)
567 cmCTestLog(this->CTest
, HANDLER_VERBOSE_OUTPUT
, "\t" << *j
572 float percent
= float(passed
.size()) * 100.0f
/ total
;
573 if ( failed
.size() > 0 && percent
> 99)
577 if(!this->CTest
->GetParallelSubprocess())
579 cmCTestLog(this->CTest
, HANDLER_OUTPUT
, std::endl
580 << static_cast<int>(percent
+ .5) << "% tests passed, "
581 << failed
.size() << " tests failed out of "
582 << total
<< std::endl
);
587 cmGeneratedFileStream ofs
;
588 if(!this->CTest
->GetParallelSubprocess())
590 cmCTestLog(this->CTest
, ERROR_MESSAGE
, std::endl
591 << "The following tests FAILED:" << std::endl
);
592 this->StartLogFile("TestsFailed", ofs
);
594 std::vector
<cmCTestTestHandler::cmCTestTestResult
>::iterator ftit
;
595 for(ftit
= this->TestResults
.begin();
596 ftit
!= this->TestResults
.end(); ++ftit
)
598 if ( ftit
->Status
!= cmCTestTestHandler::COMPLETED
)
600 ofs
<< ftit
->TestCount
<< ":" << ftit
->Name
<< std::endl
;
601 cmCTestLog(this->CTest
, HANDLER_OUTPUT
, "\t" << std::setw(3)
602 << ftit
->TestCount
<< " - "
603 << ftit
->Name
.c_str() << " ("
604 << this->GetTestStatus(ftit
->Status
) << ")"
613 if ( this->CTest
->GetProduceXML() )
615 cmGeneratedFileStream xmlfile
;
616 if( !this->StartResultingXML(
617 (this->MemCheck
? cmCTest::PartMemCheck
: cmCTest::PartTest
),
618 (this->MemCheck
? "DynamicAnalysis" : "Test"), xmlfile
) )
620 cmCTestLog(this->CTest
, ERROR_MESSAGE
, "Cannot create "
621 << (this->MemCheck
? "memory check" : "testing")
622 << " XML file" << std::endl
);
626 this->GenerateDartOutput(xmlfile
);
629 if ( ! this->PostProcessHandler() )
635 if ( !failed
.empty() )
644 //----------------------------------------------------------------------
645 void cmCTestTestHandler::ProcessOneTest(cmCTestTestProperties
*it
,
646 std::vector
<cmStdString
> &passed
,
647 std::vector
<cmStdString
> &failed
,
650 const std::string
& testname
= it
->Name
;
651 std::vector
<std::string
>& args
= it
->Args
;
652 cmCTestTestResult cres
;
653 cres
.Properties
= &*it
;
654 cres
.ExecutionTime
= 0;
655 cres
.ReturnValue
= -1;
656 cres
.Status
= cmCTestTestHandler::NOT_RUN
;
657 cres
.TestCount
= cnt
;
658 cres
.Name
= testname
;
659 cres
.Path
= it
->Directory
.c_str();
661 cmCTestLog(this->CTest
, HANDLER_OUTPUT
, std::setw(3) << cnt
<< "/");
662 cmCTestLog(this->CTest
, HANDLER_OUTPUT
, std::setw(3) << tmsize
<< " ");
663 if ( this->MemCheck
)
665 cmCTestLog(this->CTest
, HANDLER_OUTPUT
, "Memory Check");
669 cmCTestLog(this->CTest
, HANDLER_OUTPUT
, "Testing");
671 cmCTestLog(this->CTest
, HANDLER_OUTPUT
, " ");
672 const int maxTestNameWidth
= this->CTest
->GetMaxTestNameWidth();
673 std::string outname
= testname
+ " ";
674 outname
.resize(maxTestNameWidth
, '.');
675 *this->LogFile
<< cnt
<< "/" << tmsize
<< " Testing: " << testname
678 if ( this->CTest
->GetShowOnly() )
680 cmCTestLog(this->CTest
, HANDLER_OUTPUT
, outname
.c_str() << std::endl
);
684 cmCTestLog(this->CTest
, HANDLER_OUTPUT
, outname
.c_str());
687 cmCTestLog(this->CTest
, DEBUG
, "Testing " << args
[0].c_str() << " ... ");
688 // find the test executable
689 std::string actualCommand
= this->FindTheExecutable(args
[1].c_str());
690 std::string testCommand
691 = cmSystemTools::ConvertToOutputPath(actualCommand
.c_str());
693 // continue if we did not find the executable
694 if (testCommand
== "")
696 *this->LogFile
<< "Unable to find executable: " << args
[1].c_str()
698 cmCTestLog(this->CTest
, ERROR_MESSAGE
, "Unable to find executable: "
699 << args
[1].c_str() << std::endl
);
700 cres
.Output
= "Unable to find executable: " + args
[1];
701 if ( !this->CTest
->GetShowOnly() )
703 cres
.FullCommandLine
= actualCommand
;
704 this->TestResults
.push_back( cres
);
705 failed
.push_back(testname
);
711 std::vector
<std::string
>::const_iterator j
= args
.begin();
712 ++j
; // skip test name
713 ++j
; // skip command as it is in actualCommand
714 std::vector
<const char*> arguments
;
715 this->GenerateTestCommand(arguments
);
716 arguments
.push_back(actualCommand
.c_str());
717 for(;j
!= args
.end(); ++j
)
720 testCommand
+= cmSystemTools::EscapeSpaces(j
->c_str());
721 arguments
.push_back(j
->c_str());
723 arguments
.push_back(0);
726 * Run an executable command and put the stdout in output.
732 cmCTestLog(this->CTest
, HANDLER_VERBOSE_OUTPUT
, std::endl
733 << (this->MemCheck
?"MemCheck":"Test")
734 << " command: " << testCommand
736 *this->LogFile
<< cnt
<< "/" << tmsize
737 << " Test: " << testname
.c_str() << std::endl
;
738 *this->LogFile
<< "Command: ";
739 std::vector
<cmStdString
>::size_type ll
;
740 for ( ll
= 0; ll
< arguments
.size()-1; ll
++ )
742 *this->LogFile
<< "\"" << arguments
[ll
] << "\" ";
746 << "Directory: " << it
->Directory
<< std::endl
747 << "\"" << testname
.c_str() << "\" start time: "
748 << this->CTest
->CurrentTime() << std::endl
749 << "Output:" << std::endl
750 << "----------------------------------------------------------"
753 double clock_start
, clock_finish
;
754 clock_start
= cmSystemTools::GetTime();
756 if ( !this->CTest
->GetShowOnly() )
758 res
= this->CTest
->RunTest(arguments
, &output
, &retVal
, this->LogFile
,
759 it
->Timeout
, &it
->Environment
);
762 clock_finish
= cmSystemTools::GetTime();
766 cres
.ExecutionTime
= (double)(clock_finish
- clock_start
);
767 cres
.FullCommandLine
= testCommand
;
769 if ( !this->CTest
->GetShowOnly() )
771 bool testFailed
= false;
772 std::vector
<std::pair
<cmsys::RegularExpression
,
773 std::string
> >::iterator passIt
;
774 bool forceFail
= false;
775 if ( it
->RequiredRegularExpressions
.size() > 0 )
778 for ( passIt
= it
->RequiredRegularExpressions
.begin();
779 passIt
!= it
->RequiredRegularExpressions
.end();
782 if ( passIt
->first
.find(output
.c_str()) )
785 reason
= "Required regular expression found.";
790 reason
= "Required regular expression not found.";
794 for ( passIt
= it
->RequiredRegularExpressions
.begin();
795 passIt
!= it
->RequiredRegularExpressions
.end();
798 reason
+= passIt
->second
;
803 if ( it
->ErrorRegularExpressions
.size() > 0 )
805 for ( passIt
= it
->ErrorRegularExpressions
.begin();
806 passIt
!= it
->ErrorRegularExpressions
.end();
809 if ( passIt
->first
.find(output
.c_str()) )
811 reason
= "Error regular expression found in output.";
812 reason
+= " Regex=[";
813 reason
+= passIt
->second
;
820 if (res
== cmsysProcess_State_Exited
&&
821 (retVal
== 0 || it
->RequiredRegularExpressions
.size()) &&
824 cmCTestLog(this->CTest
, HANDLER_OUTPUT
, " Passed");
827 cmCTestLog(this->CTest
, HANDLER_OUTPUT
, " - But it should fail!");
828 cres
.Status
= cmCTestTestHandler::FAILED
;
833 cres
.Status
= cmCTestTestHandler::COMPLETED
;
835 cmCTestLog(this->CTest
, HANDLER_OUTPUT
, std::endl
);
841 cres
.Status
= cmCTestTestHandler::FAILED
;
842 if ( res
== cmsysProcess_State_Expired
)
844 cmCTestLog(this->CTest
, HANDLER_OUTPUT
, "***Timeout" << std::endl
);
845 cres
.Status
= cmCTestTestHandler::TIMEOUT
;
847 else if ( res
== cmsysProcess_State_Exception
)
849 cmCTestLog(this->CTest
, HANDLER_OUTPUT
, "***Exception: ");
852 case cmsysProcess_Exception_Fault
:
853 cmCTestLog(this->CTest
, HANDLER_OUTPUT
, "SegFault");
854 cres
.Status
= cmCTestTestHandler::SEGFAULT
;
856 case cmsysProcess_Exception_Illegal
:
857 cmCTestLog(this->CTest
, HANDLER_OUTPUT
, "Illegal");
858 cres
.Status
= cmCTestTestHandler::ILLEGAL
;
860 case cmsysProcess_Exception_Interrupt
:
861 cmCTestLog(this->CTest
, HANDLER_OUTPUT
, "Interrupt");
862 cres
.Status
= cmCTestTestHandler::INTERRUPT
;
864 case cmsysProcess_Exception_Numerical
:
865 cmCTestLog(this->CTest
, HANDLER_OUTPUT
, "Numerical");
866 cres
.Status
= cmCTestTestHandler::NUMERICAL
;
869 cmCTestLog(this->CTest
, HANDLER_OUTPUT
, "Other");
870 cres
.Status
= cmCTestTestHandler::OTHER_FAULT
;
872 cmCTestLog(this->CTest
, HANDLER_OUTPUT
, std::endl
);
874 else if ( res
== cmsysProcess_State_Error
)
876 cmCTestLog(this->CTest
, HANDLER_OUTPUT
, "***Bad command " << res
878 cres
.Status
= cmCTestTestHandler::BAD_COMMAND
;
882 // Force fail will also be here?
883 cmCTestLog(this->CTest
, HANDLER_OUTPUT
, "***Failed " << reason
);
886 cres
.Status
= cmCTestTestHandler::COMPLETED
;
887 cmCTestLog(this->CTest
, HANDLER_OUTPUT
, " - supposed to fail");
890 cmCTestLog(this->CTest
, HANDLER_OUTPUT
, std::endl
);
895 failed
.push_back(testname
);
899 passed
.push_back(testname
);
901 if (!output
.empty() && output
.find("<DartMeasurement") != output
.npos
)
903 if (this->DartStuff
.find(output
.c_str()))
905 std::string dartString
= this->DartStuff
.match(1);
906 // keep searching and replacing until none are left
907 while (this->DartStuff1
.find(output
.c_str()))
909 // replace the exact match for the string
910 cmSystemTools::ReplaceString(output
,
911 this->DartStuff1
.match(1).c_str(), "");
913 cres
.RegressionImages
914 = this->GenerateRegressionImages(dartString
);
919 // if this is doing MemCheck then all the output needs to be put into
920 // Output since that it what is parsed to by cmCTestMemCheckHandler
923 if ( cres
.Status
== cmCTestTestHandler::COMPLETED
)
925 this->CleanTestOutput(output
, static_cast<size_t>
926 (this->CustomMaximumPassedTestOutputSize
));
930 this->CleanTestOutput(output
, static_cast<size_t>
931 (this->CustomMaximumFailedTestOutputSize
));
934 cres
.Reason
= reason
;
938 const char* reasonType
= "Test Pass Reason";
939 if(cres
.Status
!= cmCTestTestHandler::COMPLETED
&&
940 cres
.Status
!= cmCTestTestHandler::NOT_RUN
)
942 reasonType
= "Test Fail Reason";
945 double ttime
= clock_finish
- clock_start
;
946 int hours
= static_cast<int>(ttime
/ (60 * 60));
947 int minutes
= static_cast<int>(ttime
/ 60) % 60;
948 int seconds
= static_cast<int>(ttime
) % 60;
950 sprintf(buffer
, "%02d:%02d:%02d", hours
, minutes
, seconds
);
952 << "----------------------------------------------------------"
954 if(cres
.Reason
.size())
956 *this->LogFile
<< reasonType
<< ":\n" << cres
.Reason
<< "\n";
962 *this->LogFile
<< "Test Passed.\n";
966 *this->LogFile
<< "Test Failed.\n";
969 *this->LogFile
<< "\"" << testname
.c_str() << "\" end time: "
970 << this->CTest
->CurrentTime() << std::endl
971 << "\"" << testname
.c_str() << "\" time elapsed: "
972 << buffer
<< std::endl
973 << "----------------------------------------------------------"
974 << std::endl
<< std::endl
;
976 cres
.Output
= output
;
977 cres
.ReturnValue
= retVal
;
978 cres
.CompletionStatus
= "Completed";
979 this->TestResults
.push_back( cres
);
982 //----------------------------------------------------------------------
983 void cmCTestTestHandler::CheckLabelFilterInclude(cmCTestTestProperties
& it
)
985 // if not using Labels to filter then return
986 if (!this->UseIncludeLabelRegExpFlag
)
990 // if there are no labels and we are filtering by labels
991 // then exclude the test as it does not have the label
992 if(it
.Labels
.size() == 0 )
994 it
.IsInBasedOnREOptions
= false;
997 // check to see if the label regular expression matches
998 bool found
= false; // assume it does not match
999 // loop over all labels and look for match
1000 for(std::vector
<std::string
>::iterator l
= it
.Labels
.begin();
1001 l
!= it
.Labels
.end(); ++l
)
1003 if(this->IncludeLabelRegularExpression
.find(*l
))
1008 // if no match was found, exclude the test
1011 it
.IsInBasedOnREOptions
= false;
1016 //----------------------------------------------------------------------
1017 void cmCTestTestHandler::CheckLabelFilterExclude(cmCTestTestProperties
& it
)
1019 // if not using Labels to filter then return
1020 if (!this->UseExcludeLabelRegExpFlag
)
1024 // if there are no labels and we are excluding by labels
1025 // then do nothing as a no label can not be a match
1026 if(it
.Labels
.size() == 0 )
1030 // check to see if the label regular expression matches
1031 bool found
= false; // assume it does not match
1032 // loop over all labels and look for match
1033 for(std::vector
<std::string
>::iterator l
= it
.Labels
.begin();
1034 l
!= it
.Labels
.end(); ++l
)
1036 if(this->ExcludeLabelRegularExpression
.find(*l
))
1041 // if match was found, exclude the test
1044 it
.IsInBasedOnREOptions
= false;
1048 //----------------------------------------------------------------------
1049 void cmCTestTestHandler::CheckLabelFilter(cmCTestTestProperties
& it
)
1051 this->CheckLabelFilterInclude(it
);
1052 this->CheckLabelFilterExclude(it
);
1055 //----------------------------------------------------------------------
1056 void cmCTestTestHandler::ComputeTestList()
1058 this->TestList
.clear(); // clear list of test
1059 if(this->CTest
->GetParallelSubprocess())
1061 this->LoadTestList();
1066 this->GetListOfTests();
1068 cmCTestTestHandler::ListOfTests::size_type tmsize
= this->TestList
.size();
1069 // how many tests are in based on RegExp?
1071 cmCTestTestHandler::ListOfTests::iterator it
;
1072 for ( it
= this->TestList
.begin(); it
!= this->TestList
.end(); it
++ )
1074 this->CheckLabelFilter(*it
);
1075 if (it
->IsInBasedOnREOptions
)
1080 // expand the test list based on the union flag
1083 this->ExpandTestsToRunInformation((int)tmsize
);
1087 this->ExpandTestsToRunInformation(inREcnt
);
1089 // Now create a final list of tests to run
1092 std::string last_directory
= "";
1093 ListOfTests finalList
;
1094 for ( it
= this->TestList
.begin(); it
!= this->TestList
.end(); it
++ )
1097 if (it
->IsInBasedOnREOptions
)
1104 // if it is not in the list and not in the regexp then skip
1105 if ((this->TestsToRun
.size() &&
1106 std::find(this->TestsToRun
.begin(), this->TestsToRun
.end(), cnt
)
1107 == this->TestsToRun
.end()) && !it
->IsInBasedOnREOptions
)
1114 // is this test in the list of tests to run? If not then skip it
1115 if ((this->TestsToRun
.size() &&
1116 std::find(this->TestsToRun
.begin(),
1117 this->TestsToRun
.end(), inREcnt
)
1118 == this->TestsToRun
.end()) || !it
->IsInBasedOnREOptions
)
1123 it
->Index
= cnt
; // save the index into the test list for this test
1124 finalList
.push_back(*it
);
1126 // Save the total number of tests before exclusions
1127 this->TotalNumberOfTests
= this->TestList
.size();
1128 // Set the TestList to the final list of all test
1129 this->TestList
= finalList
;
1132 bool cmCTestTestHandler::GetValue(const char* tag
,
1138 cmSystemTools::GetLineFromStream(fin
, line
);
1142 ret
= cmSystemTools::GetLineFromStream(fin
, line
); // read blank line
1146 cmCTestLog(this->CTest
, ERROR_MESSAGE
,
1147 "parse error: missing tag: "
1148 << tag
<< " found [" << line
<< "]" << std::endl
);
1154 bool cmCTestTestHandler::GetValue(const char* tag
,
1159 cmSystemTools::GetLineFromStream(fin
, line
);
1164 ret
= cmSystemTools::GetLineFromStream(fin
, line
); // read blank line
1168 cmCTestLog(this->CTest
, ERROR_MESSAGE
,
1169 "parse error: missing tag: "
1170 << tag
<< " found [" << line
<< "]" << std::endl
);
1176 bool cmCTestTestHandler::GetValue(const char* tag
,
1181 cmSystemTools::GetLineFromStream(fin
, line
);
1196 ret
= cmSystemTools::GetLineFromStream(fin
, line
); // read blank line
1200 cmCTestLog(this->CTest
, ERROR_MESSAGE
,
1201 "parse error: missing tag: "
1202 << tag
<< " found [" << line
<< "]" << std::endl
);
1208 bool cmCTestTestHandler::GetValue(const char* tag
,
1213 cmSystemTools::GetLineFromStream(fin
, line
);
1218 ret
= cmSystemTools::GetLineFromStream(fin
, line
); // read blank line
1222 cmCTestLog(this->CTest
, ERROR_MESSAGE
,
1223 "parse error: missing tag: "
1224 << tag
<< " found [" << line
.c_str() << "]" << std::endl
);
1230 bool cmCTestTestHandler::GetValue(const char* tag
,
1235 cmSystemTools::GetLineFromStream(fin
, line
);
1239 ret
= cmSystemTools::GetLineFromStream(fin
, value
);
1243 cmCTestLog(this->CTest
, ERROR_MESSAGE
,
1244 "parse error: missing tag: "
1245 << tag
<< " found [" << line
<< "]" << std::endl
);
1252 // This should load only one test and is used in -j N mode.
1253 // it is used by the sub-process ctest runs which should have
1254 // only one -I N test to run.
1255 void cmCTestTestHandler::LoadTestList()
1257 this->TestList
.clear();
1258 std::string fname
= this->CTest
->GetBinaryDir()
1259 + "/Testing/Temporary/PCache.txt";
1260 std::ifstream
fin(fname
.c_str());
1264 cmCTestLog(this->CTest
, ERROR_MESSAGE
,
1265 "Could not load PCache.txt file: "
1266 << fname
.c_str() << std::endl
);
1270 int numTestsToRun
= 0;
1271 ok
= ok
&& this->GetValue("TotalNumberOfTests:",
1272 this->TotalNumberOfTests
, fin
);
1273 ok
= ok
&& this->GetValue("NumberOfTestsToRun:", numTestsToRun
, fin
);
1274 this->ExpandTestsToRunInformation(this->TotalNumberOfTests
);
1275 if(this->TestsToRun
.size() != 1)
1277 cmCTestLog(this->CTest
, ERROR_MESSAGE
,
1278 "Error when in parallel mode only one test should be run: "
1279 << this->TestsToRun
.size() << std::endl
);
1281 int testIndexToRun
= this->TestsToRun
[0];
1282 this->CTest
->SetParallelSubprocessId(testIndexToRun
);
1287 for(int i
=0; i
< numTestsToRun
; i
++)
1289 cmCTestTestProperties p
;
1291 ok
= this->GetValue("Name:", p
.Name
, fin
);
1292 ok
= ok
&& this->GetValue("Directory:", p
.Directory
, fin
);
1293 ok
= ok
&& this->GetValue("Args:", numArgs
, fin
);
1294 for(int j
=0; j
< numArgs
; ++j
)
1296 cmSystemTools::GetLineFromStream(fin
, line
);
1297 p
.Args
.push_back(line
);
1300 ok
= ok
&& this->GetValue("Depends:", numDep
, fin
);
1301 for(int j
=0; j
< numDep
; ++j
)
1303 cmSystemTools::GetLineFromStream(fin
, line
);
1304 p
.Depends
.push_back(line
);
1306 int numErrRegex
= 0;
1307 ok
= ok
&& this->GetValue("ErrorRegularExpressions:",
1309 for(int j
=0; j
< numErrRegex
; j
++)
1311 cmSystemTools::GetLineFromStream(fin
, line
);
1312 std::pair
<cmsys::RegularExpression
, std::string
> rpair
;
1313 rpair
.first
.compile(line
.c_str());
1314 rpair
.second
= line
;
1315 p
.ErrorRegularExpressions
.push_back(rpair
);
1317 int numReqRegex
= 0;
1318 ok
= ok
&& this->GetValue("RequiredRegularExpressions:",
1320 for(int j
=0; j
< numReqRegex
; j
++)
1322 cmSystemTools::GetLineFromStream(fin
, line
);
1323 std::pair
<cmsys::RegularExpression
, std::string
> rpair
;
1324 rpair
.first
.compile(line
.c_str());
1325 rpair
.second
= line
;
1326 p
.RequiredRegularExpressions
.push_back(rpair
);
1329 ok
= ok
&& this->GetValue("Measurements:",
1331 for(int j
=0; j
< numMeasure
; j
++)
1335 cmSystemTools::GetLineFromStream(fin
, line
);
1337 cmSystemTools::GetLineFromStream(fin
, line
);
1339 p
.Measurements
[m
] = v
;
1342 ok
= ok
&& this->GetValue("IsInBasedOnREOptions:", isinre
, fin
);
1343 ok
= ok
&& this->GetValue("WillFail:", p
.WillFail
, fin
);
1344 ok
= ok
&& this->GetValue("TimeOut:", p
.Timeout
, fin
);
1345 ok
= ok
&& this->GetValue("Index:", p
.Index
, fin
);
1347 ok
= ok
&& this->GetValue("Environment:",
1349 for(int j
=0; j
< numEnv
; j
++)
1351 cmSystemTools::GetLineFromStream(fin
, line
);
1352 p
.Environment
.push_back(line
);
1355 ok
= ok
&& this->GetValue("Labels:",
1357 for(int j
=0; j
< numLabels
; j
++)
1359 cmSystemTools::GetLineFromStream(fin
, line
);
1360 p
.Labels
.push_back(line
);
1364 cmCTestLog(this->CTest
, ERROR_MESSAGE
,
1365 "Internal Error reading cached test information."
1369 if(p
.Index
== testIndexToRun
)
1371 // add the one test and stop reading
1372 this->TestList
.push_back(p
);
1377 std::string
cmCTestTestHandler::SaveTestList()
1379 std::string fname
= this->CTest
->GetBinaryDir()
1380 + "/Testing/Temporary/PCache.txt";
1381 cmGeneratedFileStream
fout(fname
.c_str());
1384 cmCTestLog(this->CTest
, ERROR_MESSAGE
, std::endl
1385 << "Could not open PCache.txt for write:"
1389 fout
<< "TotalNumberOfTests:\n";
1390 fout
<< this->TotalNumberOfTests
<< "\n";
1391 fout
<< "NumberOfTestsToRun:\n";
1392 fout
<< this->TestList
.size() << "\n";
1393 for (ListOfTests::iterator it
= this->TestList
.begin();
1394 it
!= this->TestList
.end(); it
++ )
1396 cmCTestTestProperties
& p
= *it
;
1400 << p
.Directory
.c_str()
1402 << p
.Args
.size() << "\n";
1403 for(std::vector
<std::string
>::iterator i
= p
.Args
.begin();
1404 i
!= p
.Args
.end(); ++i
)
1406 fout
<< i
->c_str() << "\n";
1408 fout
<< "Depends:\n" << p
.Depends
.size() << "\n";
1409 for(std::vector
<std::string
>::iterator i
= p
.Depends
.begin();
1410 i
!= p
.Depends
.end(); ++i
)
1412 fout
<< i
->c_str() << "\n";
1414 std::vector
<std::pair
<cmsys::RegularExpression
,
1415 std::string
> >::iterator regxi
;
1416 fout
<< "ErrorRegularExpressions:\n" <<
1417 p
.ErrorRegularExpressions
.size() << "\n";
1418 for(regxi
= p
.ErrorRegularExpressions
.begin();
1419 regxi
!= p
.ErrorRegularExpressions
.end(); regxi
++)
1421 fout
<< regxi
->second
<< "\n";
1423 fout
<< "RequiredRegularExpressions:\n" <<
1424 p
.RequiredRegularExpressions
.size() << "\n";
1425 for(regxi
= p
.RequiredRegularExpressions
.begin();
1426 regxi
!= p
.RequiredRegularExpressions
.end(); regxi
++)
1428 fout
<< regxi
->second
<< "\n";
1430 fout
<< "Measurements:\n" <<
1431 p
.Measurements
.size() << "\n";
1432 for(std::map
<cmStdString
, cmStdString
>::const_iterator m
=
1433 p
.Measurements
.begin(); m
!= p
.Measurements
.end(); ++m
)
1435 fout
<< m
->first
<< "\n";
1436 fout
<< m
->second
<< "\n";
1439 fout
<< "IsInBasedOnREOptions:\n"
1440 << p
.IsInBasedOnREOptions
1447 fout
<< "Environment:\n" <<
1448 p
.Environment
.size() << "\n";
1449 for(std::vector
<std::string
>::const_iterator e
=
1450 p
.Environment
.begin(); e
!= p
.Environment
.end(); ++e
)
1454 fout
<< "Labels:\n" <<
1455 p
.Labels
.size() << "\n";
1456 for(std::vector
<std::string
>::const_iterator e
=
1457 p
.Labels
.begin(); e
!= p
.Labels
.end(); ++e
)
1466 void cmCTestTestHandler::ProcessParallel(std::vector
<cmStdString
> &passed
,
1467 std::vector
<cmStdString
> &failed
)
1469 this->ComputeTestList();
1470 cmCTestMultiProcessHandler parallel
;
1471 parallel
.SetCTest(this->CTest
);
1472 parallel
.SetParallelLevel(this->CTest
->GetParallelLevel());
1473 cmCTestMultiProcessHandler::TestSet depends
;
1474 cmCTestMultiProcessHandler::TestMap tests
;
1475 std::map
<int, cmStdString
> testnames
;
1476 for (ListOfTests::iterator it
= this->TestList
.begin();
1477 it
!= this->TestList
.end(); it
++ )
1479 cmCTestTestProperties
& p
= *it
;
1480 testnames
[p
.Index
] = p
.Name
;
1481 if(p
.Depends
.size())
1483 for(std::vector
<std::string
>::iterator i
= p
.Depends
.begin();
1484 i
!= p
.Depends
.end(); ++i
)
1486 for(ListOfTests::iterator it2
= this->TestList
.begin();
1487 it2
!= this->TestList
.end(); it2
++ )
1491 depends
.insert(it2
->Index
);
1492 break; // break out of test loop as name can only match 1
1497 tests
[it
->Index
] = depends
;
1499 parallel
.SetCTestCommand(this->CTest
->GetCTestExecutable());
1500 parallel
.SetTests(tests
, testnames
);
1501 std::string fname
= this->SaveTestList();
1502 parallel
.SetTestCacheFile(fname
.c_str());
1503 parallel
.SetPassFailVectors(&passed
, &failed
);
1504 this->TestResults
.clear();
1505 parallel
.SetTestResults(&this->TestResults
);
1506 parallel
.RunTests();
1507 cmSystemTools::RemoveFile(fname
.c_str());
1511 //----------------------------------------------------------------------
1512 void cmCTestTestHandler::ProcessDirectory(std::vector
<cmStdString
> &passed
,
1513 std::vector
<cmStdString
> &failed
)
1515 if(this->CTest
->GetParallelLevel() > 0)
1517 this->ProcessParallel(passed
, failed
);
1520 // save the current working directory
1521 std::string current_dir
= cmSystemTools::GetCurrentWorkingDirectory();
1522 // compute the list of tests to run
1523 this->ComputeTestList();
1524 this->StartTest
= this->CTest
->CurrentTime();
1525 this->StartTestTime
= static_cast<unsigned int>(cmSystemTools::GetTime());
1526 double elapsed_time_start
= cmSystemTools::GetTime();
1527 *this->LogFile
<< "Start testing: " << this->StartTest
<< std::endl
1528 << "----------------------------------------------------------"
1530 std::string last_directory
= "";
1532 for (ListOfTests::iterator it
= this->TestList
.begin();
1533 it
!= this->TestList
.end(); it
++ )
1535 if (!(last_directory
== it
->Directory
))
1537 cmCTestLog(this->CTest
, HANDLER_VERBOSE_OUTPUT
,
1538 "Changing directory into " << it
->Directory
.c_str() << "\n");
1539 *this->LogFile
<< "Changing directory into: " << it
->Directory
.c_str()
1541 last_directory
= it
->Directory
;
1542 cmSystemTools::ChangeDirectory(it
->Directory
.c_str());
1544 // process this one test
1545 this->ProcessOneTest(&(*it
), passed
, failed
, it
->Index
,
1546 static_cast<int>(this->TotalNumberOfTests
));
1549 this->EndTest
= this->CTest
->CurrentTime();
1550 this->EndTestTime
= static_cast<unsigned int>(cmSystemTools::GetTime());
1551 this->ElapsedTestingTime
= cmSystemTools::GetTime() - elapsed_time_start
;
1552 if ( this->LogFile
)
1554 *this->LogFile
<< "End testing: " << this->EndTest
<< std::endl
;
1556 cmSystemTools::ChangeDirectory(current_dir
.c_str());
1559 //----------------------------------------------------------------------
1560 void cmCTestTestHandler::GenerateTestCommand(std::vector
<const char*>&)
1564 //----------------------------------------------------------------------
1565 void cmCTestTestHandler::GenerateDartOutput(std::ostream
& os
)
1567 if ( !this->CTest
->GetProduceXML() )
1572 this->CTest
->StartXML(os
, this->AppendXML
);
1574 << "\t<StartDateTime>" << this->StartTest
<< "</StartDateTime>\n"
1575 << "\t<StartTestTime>" << this->StartTestTime
<< "</StartTestTime>\n"
1576 << "\t<TestList>\n";
1577 cmCTestTestHandler::TestResultsVector::size_type cc
;
1578 for ( cc
= 0; cc
< this->TestResults
.size(); cc
++ )
1580 cmCTestTestResult
*result
= &this->TestResults
[cc
];
1581 std::string testPath
= result
->Path
+ "/" + result
->Name
;
1582 os
<< "\t\t<Test>" << cmXMLSafe(
1583 this->CTest
->GetShortPathToFile(testPath
.c_str()))
1584 << "</Test>" << std::endl
;
1586 os
<< "\t</TestList>\n";
1587 for ( cc
= 0; cc
< this->TestResults
.size(); cc
++ )
1589 cmCTestTestResult
*result
= &this->TestResults
[cc
];
1590 this->WriteTestResultHeader(os
, result
);
1591 os
<< "\t\t<Results>" << std::endl
;
1592 if ( result
->Status
!= cmCTestTestHandler::NOT_RUN
)
1594 if ( result
->Status
!= cmCTestTestHandler::COMPLETED
||
1595 result
->ReturnValue
)
1597 os
<< "\t\t\t<NamedMeasurement type=\"text/string\" "
1598 "name=\"Exit Code\"><Value>"
1599 << cmXMLSafe(this->GetTestStatus(result
->Status
))
1601 "</NamedMeasurement>\n"
1602 << "\t\t\t<NamedMeasurement type=\"text/string\" "
1603 "name=\"Exit Value\"><Value>"
1604 << result
->ReturnValue
1605 << "</Value></NamedMeasurement>"
1608 os
<< result
->RegressionImages
;
1609 os
<< "\t\t\t<NamedMeasurement type=\"numeric/double\" "
1610 << "name=\"Execution Time\"><Value>"
1611 << result
->ExecutionTime
1612 << "</Value></NamedMeasurement>\n";
1613 if(result
->Reason
.size())
1615 const char* reasonType
= "Pass Reason";
1616 if(result
->Status
!= cmCTestTestHandler::COMPLETED
&&
1617 result
->Status
!= cmCTestTestHandler::NOT_RUN
)
1619 reasonType
= "Fail Reason";
1621 os
<< "\t\t\t<NamedMeasurement type=\"text/string\" "
1622 << "name=\"" << reasonType
<< "\"><Value>"
1623 << cmXMLSafe(result
->Reason
)
1624 << "</Value></NamedMeasurement>\n";
1627 << "\t\t\t<NamedMeasurement type=\"text/string\" "
1628 << "name=\"Completion Status\"><Value>"
1629 << cmXMLSafe(result
->CompletionStatus
)
1630 << "</Value></NamedMeasurement>\n";
1633 << "\t\t\t<NamedMeasurement type=\"text/string\" "
1634 << "name=\"Command Line\"><Value>"
1635 << cmXMLSafe(result
->FullCommandLine
)
1636 << "</Value></NamedMeasurement>\n";
1637 std::map
<cmStdString
,cmStdString
>::iterator measureIt
;
1638 for ( measureIt
= result
->Properties
->Measurements
.begin();
1639 measureIt
!= result
->Properties
->Measurements
.end();
1643 << "\t\t\t<NamedMeasurement type=\"text/string\" "
1644 << "name=\"" << measureIt
->first
.c_str() << "\"><Value>"
1645 << cmXMLSafe(measureIt
->second
)
1646 << "</Value></NamedMeasurement>\n";
1649 << "\t\t\t<Measurement>\n"
1650 << "\t\t\t\t<Value>";
1651 os
<< cmXMLSafe(result
->Output
);
1654 << "\t\t\t</Measurement>\n"
1655 << "\t\t</Results>\n";
1656 this->WriteTestResultFooter(os
, result
);
1659 os
<< "\t<EndDateTime>" << this->EndTest
<< "</EndDateTime>\n"
1660 << "\t<EndTestTime>" << this->EndTestTime
<< "</EndTestTime>\n"
1661 << "<ElapsedMinutes>"
1662 << static_cast<int>(this->ElapsedTestingTime
/6)/10.0
1663 << "</ElapsedMinutes>"
1664 << "</Testing>" << std::endl
;
1665 this->CTest
->EndXML(os
);
1668 //----------------------------------------------------------------------------
1669 void cmCTestTestHandler::WriteTestResultHeader(std::ostream
& os
,
1670 cmCTestTestResult
* result
)
1672 os
<< "\t<Test Status=\"";
1673 if ( result
->Status
== cmCTestTestHandler::COMPLETED
)
1677 else if ( result
->Status
== cmCTestTestHandler::NOT_RUN
)
1685 std::string testPath
= result
->Path
+ "/" + result
->Name
;
1687 << "\t\t<Name>" << cmXMLSafe(result
->Name
) << "</Name>\n"
1688 << "\t\t<Path>" << cmXMLSafe(
1689 this->CTest
->GetShortPathToFile(result
->Path
.c_str())) << "</Path>\n"
1690 << "\t\t<FullName>" << cmXMLSafe(
1691 this->CTest
->GetShortPathToFile(testPath
.c_str())) << "</FullName>\n"
1692 << "\t\t<FullCommandLine>"
1693 << cmXMLSafe(result
->FullCommandLine
)
1694 << "</FullCommandLine>\n";
1697 //----------------------------------------------------------------------------
1698 void cmCTestTestHandler::WriteTestResultFooter(std::ostream
& os
,
1699 cmCTestTestResult
* result
)
1701 if(!result
->Properties
->Labels
.empty())
1703 os
<< "\t\t<Labels>\n";
1704 std::vector
<std::string
> const& labels
= result
->Properties
->Labels
;
1705 for(std::vector
<std::string
>::const_iterator li
= labels
.begin();
1706 li
!= labels
.end(); ++li
)
1708 os
<< "\t\t\t<Label>" << cmXMLSafe(*li
) << "</Label>\n";
1710 os
<< "\t\t</Labels>\n";
1714 << "\t</Test>" << std::endl
;
1717 //----------------------------------------------------------------------
1718 int cmCTestTestHandler::ExecuteCommands(std::vector
<cmStdString
>& vec
)
1720 std::vector
<cmStdString
>::iterator it
;
1721 for ( it
= vec
.begin(); it
!= vec
.end(); ++it
)
1724 cmCTestLog(this->CTest
, HANDLER_VERBOSE_OUTPUT
, "Run command: " << *it
1726 if ( !cmSystemTools::RunSingleCommand(it
->c_str(), 0, &retVal
, 0, true
1727 /*this->Verbose*/) || retVal
!= 0 )
1729 cmCTestLog(this->CTest
, ERROR_MESSAGE
, "Problem running command: "
1730 << *it
<< std::endl
);
1738 //----------------------------------------------------------------------
1739 // Find the appropriate executable to run for a test
1740 std::string
cmCTestTestHandler::FindTheExecutable(const char *exe
)
1742 std::string resConfig
;
1743 std::vector
<std::string
> extraPaths
;
1744 std::vector
<std::string
> failedPaths
;
1745 return cmCTestTestHandler::FindExecutable(this->CTest
,
1751 // add additional configurations to the search path
1752 void cmCTestTestHandler
1753 ::AddConfigurations(cmCTest
*ctest
,
1754 std::vector
<std::string
> &attempted
,
1755 std::vector
<std::string
> &attemptedConfigs
,
1756 std::string filepath
,
1757 std::string
&filename
)
1759 std::string tempPath
;
1761 if (filepath
.size() &&
1762 filepath
[filepath
.size()-1] != '/')
1766 tempPath
= filepath
+ filename
;
1767 attempted
.push_back(tempPath
);
1768 attemptedConfigs
.push_back("");
1770 if(ctest
->GetConfigType().size())
1772 tempPath
= filepath
;
1773 tempPath
+= ctest
->GetConfigType();
1775 tempPath
+= filename
;
1776 attempted
.push_back(tempPath
);
1777 attemptedConfigs
.push_back(ctest
->GetConfigType());
1778 // If the file is an OSX bundle then the configtyp
1779 // will be at the start of the path
1780 tempPath
= ctest
->GetConfigType();
1782 tempPath
+= filepath
;
1783 tempPath
+= filename
;
1784 attempted
.push_back(tempPath
);
1785 attemptedConfigs
.push_back(ctest
->GetConfigType());
1789 // no config specified to try some options
1790 tempPath
= filepath
;
1791 tempPath
+= "Release/";
1792 tempPath
+= filename
;
1793 attempted
.push_back(tempPath
);
1794 attemptedConfigs
.push_back("Release");
1795 tempPath
= filepath
;
1796 tempPath
+= "Debug/";
1797 tempPath
+= filename
;
1798 attempted
.push_back(tempPath
);
1799 attemptedConfigs
.push_back("Debug");
1800 tempPath
= filepath
;
1801 tempPath
+= "MinSizeRel/";
1802 tempPath
+= filename
;
1803 attempted
.push_back(tempPath
);
1804 attemptedConfigs
.push_back("MinSizeRel");
1805 tempPath
= filepath
;
1806 tempPath
+= "RelWithDebInfo/";
1807 tempPath
+= filename
;
1808 attempted
.push_back(tempPath
);
1809 attemptedConfigs
.push_back("RelWithDebInfo");
1810 tempPath
= filepath
;
1811 tempPath
+= "Deployment/";
1812 tempPath
+= filename
;
1813 attempted
.push_back(tempPath
);
1814 attemptedConfigs
.push_back("Deployment");
1815 tempPath
= filepath
;
1816 tempPath
+= "Development/";
1817 tempPath
+= filename
;
1818 attempted
.push_back(tempPath
);
1819 attemptedConfigs
.push_back("Deployment");
1824 //----------------------------------------------------------------------
1825 // Find the appropriate executable to run for a test
1826 std::string cmCTestTestHandler
1827 ::FindExecutable(cmCTest
*ctest
,
1828 const char *testCommand
,
1829 std::string
&resultingConfig
,
1830 std::vector
<std::string
> &extraPaths
,
1831 std::vector
<std::string
> &failed
)
1833 // now run the compiled test if we can find it
1834 std::vector
<std::string
> attempted
;
1835 std::vector
<std::string
> attemptedConfigs
;
1836 std::string tempPath
;
1837 std::string filepath
=
1838 cmSystemTools::GetFilenamePath(testCommand
);
1839 std::string filename
=
1840 cmSystemTools::GetFilenameName(testCommand
);
1842 cmCTestTestHandler::AddConfigurations(ctest
, attempted
,
1846 // even if a fullpath was specified also try it relative to the current
1848 if (filepath
.size() && filepath
[0] == '/')
1850 std::string localfilepath
= filepath
.substr(1,filepath
.size()-1);
1851 cmCTestTestHandler::AddConfigurations(ctest
, attempted
,
1853 localfilepath
,filename
);
1857 // if extraPaths are provided and we were not passed a full path, try them,
1858 // try any extra paths
1859 if (filepath
.size() == 0)
1861 for (unsigned int i
= 0; i
< extraPaths
.size(); ++i
)
1863 std::string filepathExtra
=
1864 cmSystemTools::GetFilenamePath(extraPaths
[i
]);
1865 std::string filenameExtra
=
1866 cmSystemTools::GetFilenameName(extraPaths
[i
]);
1867 cmCTestTestHandler::AddConfigurations(ctest
,attempted
,
1874 // store the final location in fullPath
1875 std::string fullPath
;
1877 // now look in the paths we specified above
1878 for(unsigned int ai
=0;
1879 ai
< attempted
.size() && fullPath
.size() == 0; ++ai
)
1881 // first check without exe extension
1882 if(cmSystemTools::FileExists(attempted
[ai
].c_str())
1883 && !cmSystemTools::FileIsDirectory(attempted
[ai
].c_str()))
1885 fullPath
= cmSystemTools::CollapseFullPath(attempted
[ai
].c_str());
1886 resultingConfig
= attemptedConfigs
[ai
];
1888 // then try with the exe extension
1891 failed
.push_back(attempted
[ai
].c_str());
1892 tempPath
= attempted
[ai
];
1893 tempPath
+= cmSystemTools::GetExecutableExtension();
1894 if(cmSystemTools::FileExists(tempPath
.c_str())
1895 && !cmSystemTools::FileIsDirectory(tempPath
.c_str()))
1897 fullPath
= cmSystemTools::CollapseFullPath(tempPath
.c_str());
1898 resultingConfig
= attemptedConfigs
[ai
];
1902 failed
.push_back(tempPath
.c_str());
1907 // if everything else failed, check the users path, but only if a full path
1909 if (fullPath
.size() == 0 && filepath
.size() == 0)
1911 std::string path
= cmSystemTools::FindProgram(filename
.c_str());
1914 resultingConfig
= "";
1918 if(fullPath
.size() == 0)
1920 cmCTestLog(ctest
, HANDLER_OUTPUT
,
1921 "Could not find executable " << testCommand
<< "\n"
1922 << "Looked in the following places:\n");
1923 for(std::vector
<std::string
>::iterator i
= failed
.begin();
1924 i
!= failed
.end(); ++i
)
1926 cmCTestLog(ctest
, HANDLER_OUTPUT
,
1927 i
->c_str() << "\n");
1935 //----------------------------------------------------------------------
1936 void cmCTestTestHandler::GetListOfTests()
1938 if ( !this->IncludeLabelRegExp
.empty() )
1940 this->IncludeLabelRegularExpression
.
1941 compile(this->IncludeLabelRegExp
.c_str());
1943 if ( !this->IncludeLabelRegExp
.empty() )
1945 this->ExcludeLabelRegularExpression
.
1946 compile(this->ExcludeLabelRegExp
.c_str());
1948 if ( !this->IncludeRegExp
.empty() )
1950 this->IncludeTestsRegularExpression
.compile(this->IncludeRegExp
.c_str());
1952 if ( !this->ExcludeRegExp
.empty() )
1954 this->ExcludeTestsRegularExpression
.compile(this->ExcludeRegExp
.c_str());
1956 cmCTestLog(this->CTest
, HANDLER_VERBOSE_OUTPUT
,
1957 "Constructing a list of tests" << std::endl
);
1959 cmGlobalGenerator gg
;
1960 gg
.SetCMakeInstance(&cm
);
1961 std::auto_ptr
<cmLocalGenerator
> lg(gg
.CreateLocalGenerator());
1962 lg
->SetGlobalGenerator(&gg
);
1963 cmMakefile
*mf
= lg
->GetMakefile();
1964 mf
->AddDefinition("CTEST_CONFIGURATION_TYPE",
1965 this->CTest
->GetConfigType().c_str());
1967 // Add handler for ADD_TEST
1968 cmCTestAddTestCommand
* newCom1
= new cmCTestAddTestCommand
;
1969 newCom1
->TestHandler
= this;
1970 cm
.AddCommand(newCom1
);
1972 // Add handler for SUBDIRS
1973 cmCTestSubdirCommand
* newCom2
=
1974 new cmCTestSubdirCommand
;
1975 newCom2
->TestHandler
= this;
1976 cm
.AddCommand(newCom2
);
1978 // Add handler for ADD_SUBDIRECTORY
1979 cmCTestAddSubdirectoryCommand
* newCom3
=
1980 new cmCTestAddSubdirectoryCommand
;
1981 newCom3
->TestHandler
= this;
1982 cm
.AddCommand(newCom3
);
1984 // Add handler for SET_SOURCE_FILES_PROPERTIES
1985 cmCTestSetTestsPropertiesCommand
* newCom4
1986 = new cmCTestSetTestsPropertiesCommand
;
1987 newCom4
->TestHandler
= this;
1988 cm
.AddCommand(newCom4
);
1990 const char* testFilename
;
1991 if( cmSystemTools::FileExists("CTestTestfile.cmake") )
1993 // does the CTestTestfile.cmake exist ?
1994 testFilename
= "CTestTestfile.cmake";
1996 else if( cmSystemTools::FileExists("DartTestfile.txt") )
1998 // does the DartTestfile.txt exist ?
1999 testFilename
= "DartTestfile.txt";
2006 if ( !mf
->ReadListFile(0, testFilename
) )
2010 if ( cmSystemTools::GetErrorOccuredFlag() )
2014 cmCTestLog(this->CTest
, HANDLER_VERBOSE_OUTPUT
,
2015 "Done constructing a list of tests" << std::endl
);
2018 //----------------------------------------------------------------------
2019 void cmCTestTestHandler::UseIncludeRegExp()
2021 this->UseIncludeRegExpFlag
= true;
2024 //----------------------------------------------------------------------
2025 void cmCTestTestHandler::UseExcludeRegExp()
2027 this->UseExcludeRegExpFlag
= true;
2028 this->UseExcludeRegExpFirst
= this->UseIncludeRegExpFlag
? false : true;
2031 //----------------------------------------------------------------------
2032 const char* cmCTestTestHandler::GetTestStatus(int status
)
2034 static const char statuses
[][100] = {
2047 if ( status
< cmCTestTestHandler::NOT_RUN
||
2048 status
> cmCTestTestHandler::COMPLETED
)
2052 return statuses
[status
];
2055 //----------------------------------------------------------------------
2056 void cmCTestTestHandler::ExpandTestsToRunInformation(size_t numTests
)
2058 if (this->TestsToRunString
.empty())
2066 std::string::size_type pos
= 0;
2067 std::string::size_type pos2
;
2069 if(GetNextNumber(this->TestsToRunString
, start
, pos
, pos2
))
2072 if(GetNextNumber(this->TestsToRunString
, end
, pos
, pos2
))
2075 if(GetNextRealNumber(this->TestsToRunString
, stride
, pos
, pos2
))
2078 // now read specific numbers
2079 while(GetNextNumber(this->TestsToRunString
, val
, pos
, pos2
))
2081 this->TestsToRun
.push_back(val
);
2083 this->TestsToRun
.push_back(val
);
2088 // if start is not specified then we assume we start at 1
2094 // if end isnot specified then we assume we end with the last test
2097 end
= static_cast<int>(numTests
);
2100 // if the stride wasn't specified then it defaults to 1
2106 // if we have a range then add it
2107 if(end
!= -1 && start
!= -1 && stride
> 0)
2110 while (i
*stride
+ start
<= end
)
2112 this->TestsToRun
.push_back(static_cast<int>(i
*stride
+start
));
2118 std::sort(this->TestsToRun
.begin(), this->TestsToRun
.end(),
2120 // remove duplicates
2121 std::vector
<int>::iterator new_end
=
2122 std::unique(this->TestsToRun
.begin(), this->TestsToRun
.end());
2123 this->TestsToRun
.erase(new_end
, this->TestsToRun
.end());
2126 //----------------------------------------------------------------------
2127 // Just for convenience
2128 #define SPACE_REGEX "[ \t\r\n]"
2129 //----------------------------------------------------------------------
2130 std::string
cmCTestTestHandler::GenerateRegressionImages(
2131 const std::string
& xml
)
2133 cmsys::RegularExpression
twoattributes(
2135 SPACE_REGEX
"*(name|type|encoding|compression)=\"([^\"]*)\""
2136 SPACE_REGEX
"*(name|type|encoding|compression)=\"([^\"]*)\""
2137 SPACE_REGEX
"*>([^<]*)</DartMeasurement>");
2138 cmsys::RegularExpression
threeattributes(
2140 SPACE_REGEX
"*(name|type|encoding|compression)=\"([^\"]*)\""
2141 SPACE_REGEX
"*(name|type|encoding|compression)=\"([^\"]*)\""
2142 SPACE_REGEX
"*(name|type|encoding|compression)=\"([^\"]*)\""
2143 SPACE_REGEX
"*>([^<]*)</DartMeasurement>");
2144 cmsys::RegularExpression
fourattributes(
2146 SPACE_REGEX
"*(name|type|encoding|compression)=\"([^\"]*)\""
2147 SPACE_REGEX
"*(name|type|encoding|compression)=\"([^\"]*)\""
2148 SPACE_REGEX
"*(name|type|encoding|compression)=\"([^\"]*)\""
2149 SPACE_REGEX
"*(name|type|encoding|compression)=\"([^\"]*)\""
2150 SPACE_REGEX
"*>([^<]*)</DartMeasurement>");
2151 cmsys::RegularExpression
cdatastart(
2153 SPACE_REGEX
"*(name|type|encoding|compression)=\"([^\"]*)\""
2154 SPACE_REGEX
"*(name|type|encoding|compression)=\"([^\"]*)\""
2156 SPACE_REGEX
"*<!\\[CDATA\\[");
2157 cmsys::RegularExpression
cdataend(
2159 SPACE_REGEX
"*</DartMeasurement>");
2160 cmsys::RegularExpression
measurementfile(
2161 "<DartMeasurementFile"
2162 SPACE_REGEX
"*(name|type|encoding|compression)=\"([^\"]*)\""
2163 SPACE_REGEX
"*(name|type|encoding|compression)=\"([^\"]*)\""
2164 SPACE_REGEX
"*>([^<]*)</DartMeasurementFile>");
2166 cmOStringStream ostr
;
2168 std::string cxml
= xml
;
2171 if ( twoattributes
.find(cxml
) )
2174 << "\t\t\t<NamedMeasurement"
2175 << " " << twoattributes
.match(1) << "=\""
2176 << twoattributes
.match(2) << "\""
2177 << " " << twoattributes
.match(3) << "=\""
2178 << twoattributes
.match(4) << "\""
2179 << "><Value>" << twoattributes
.match(5)
2180 << "</Value></NamedMeasurement>"
2182 cxml
.erase(twoattributes
.start(),
2183 twoattributes
.end() - twoattributes
.start());
2185 else if ( threeattributes
.find(cxml
) )
2188 << "\t\t\t<NamedMeasurement"
2189 << " " << threeattributes
.match(1) << "=\""
2190 << threeattributes
.match(2) << "\""
2191 << " " << threeattributes
.match(3) << "=\""
2192 << threeattributes
.match(4) << "\""
2193 << " " << threeattributes
.match(5) << "=\""
2194 << threeattributes
.match(6) << "\""
2195 << "><Value>" << threeattributes
.match(7)
2196 << "</Value></NamedMeasurement>"
2198 cxml
.erase(threeattributes
.start(),
2199 threeattributes
.end() - threeattributes
.start());
2201 else if ( fourattributes
.find(cxml
) )
2204 << "\t\t\t<NamedMeasurement"
2205 << " " << fourattributes
.match(1) << "=\""
2206 << fourattributes
.match(2) << "\""
2207 << " " << fourattributes
.match(3) << "=\""
2208 << fourattributes
.match(4) << "\""
2209 << " " << fourattributes
.match(5) << "=\""
2210 << fourattributes
.match(6) << "\""
2211 << " " << fourattributes
.match(7) << "=\""
2212 << fourattributes
.match(8) << "\""
2213 << "><Value>" << fourattributes
.match(9)
2214 << "</Value></NamedMeasurement>"
2216 cxml
.erase(fourattributes
.start(),
2217 fourattributes
.end() - fourattributes
.start());
2219 else if ( cdatastart
.find(cxml
) && cdataend
.find(cxml
) )
2222 << "\t\t\t<NamedMeasurement"
2223 << " " << cdatastart
.match(1) << "=\""
2224 << cdatastart
.match(2) << "\""
2225 << " " << cdatastart
.match(3) << "=\""
2226 << cdatastart
.match(4) << "\""
2227 << "><Value><![CDATA["
2228 << cxml
.substr(cdatastart
.end(), cdataend
.start() - cdatastart
.end())
2229 << "]]></Value></NamedMeasurement>"
2231 cxml
.erase(cdatastart
.start(),
2232 cdataend
.end() - cdatastart
.start());
2234 else if ( measurementfile
.find(cxml
) )
2236 const std::string
& filename
=
2237 cmCTest::CleanString(measurementfile
.match(5));
2238 if ( cmSystemTools::FileExists(filename
.c_str()) )
2240 long len
= cmSystemTools::FileLength(filename
.c_str());
2243 std::string k1
= measurementfile
.match(1);
2244 std::string v1
= measurementfile
.match(2);
2245 std::string k2
= measurementfile
.match(3);
2246 std::string v2
= measurementfile
.match(4);
2247 if ( cmSystemTools::LowerCase(k1
) == "type" )
2251 if ( cmSystemTools::LowerCase(k2
) == "type" )
2257 << "\t\t\t<NamedMeasurement"
2258 << " " << k1
<< "=\"" << v1
<< "\""
2259 << " " << k2
<< "=\"" << v2
<< "\""
2260 << " encoding=\"none\""
2261 << "><Value>Image " << filename
.c_str()
2262 << " is empty</Value></NamedMeasurement>";
2266 std::ifstream
ifs(filename
.c_str(), std::ios::in
2271 unsigned char *file_buffer
= new unsigned char [ len
+ 1 ];
2272 ifs
.read(reinterpret_cast<char*>(file_buffer
), len
);
2273 unsigned char *encoded_buffer
2274 = new unsigned char [ static_cast<int>(len
* 1.5 + 5) ];
2277 = cmsysBase64_Encode(file_buffer
, len
, encoded_buffer
, 1);
2281 << "\t\t\t<NamedMeasurement"
2282 << " " << measurementfile
.match(1) << "=\""
2283 << measurementfile
.match(2) << "\""
2284 << " " << measurementfile
.match(3) << "=\""
2285 << measurementfile
.match(4) << "\""
2286 << " encoding=\"base64\""
2287 << ">" << std::endl
<< "\t\t\t\t<Value>";
2288 for ( cc
= 0; cc
< rlen
; cc
++ )
2290 ostr
<< encoded_buffer
[cc
];
2291 if ( cc
% 60 == 0 && cc
)
2297 << "</Value>" << std::endl
<< "\t\t\t</NamedMeasurement>"
2299 delete [] file_buffer
;
2300 delete [] encoded_buffer
;
2306 if ( measurementfile
.match(1) == "name" )
2311 << "\t\t\t<NamedMeasurement"
2312 << " name=\"" << measurementfile
.match(idx
) << "\""
2313 << " text=\"text/string\""
2314 << "><Value>File " << filename
.c_str()
2315 << " not found</Value></NamedMeasurement>"
2317 cmCTestLog(this->CTest
, HANDLER_OUTPUT
, "File \"" << filename
.c_str()
2318 << "\" not found." << std::endl
);
2320 cxml
.erase(measurementfile
.start(),
2321 measurementfile
.end() - measurementfile
.start());
2331 //----------------------------------------------------------------------
2332 void cmCTestTestHandler::SetIncludeRegExp(const char *arg
)
2334 this->IncludeRegExp
= arg
;
2337 //----------------------------------------------------------------------
2338 void cmCTestTestHandler::SetExcludeRegExp(const char *arg
)
2340 this->ExcludeRegExp
= arg
;
2343 //----------------------------------------------------------------------
2344 void cmCTestTestHandler::SetTestsToRunInformation(const char* in
)
2350 this->TestsToRunString
= in
;
2351 // if the argument is a file, then read it and use the contents as the
2353 if(cmSystemTools::FileExists(in
))
2355 std::ifstream
fin(in
);
2356 unsigned long filelen
= cmSystemTools::FileLength(in
);
2357 char* buff
= new char[filelen
+1];
2358 fin
.getline(buff
, filelen
);
2359 buff
[fin
.gcount()] = 0;
2360 this->TestsToRunString
= buff
;
2364 //----------------------------------------------------------------------
2365 bool cmCTestTestHandler::CleanTestOutput(std::string
& output
,
2366 size_t remove_threshold
)
2368 if ( remove_threshold
== 0 )
2372 if ( output
.find("CTEST_FULL_OUTPUT") != output
.npos
)
2376 cmOStringStream ostr
;
2377 std::string::size_type cc
;
2378 std::string::size_type skipsize
= 0;
2381 for ( cc
= 0; cc
< output
.size(); cc
++ )
2383 int ch
= output
[cc
];
2384 if ( ch
< 0 || ch
> 255 )
2396 if ( skipsize
< remove_threshold
)
2398 ostr
<< static_cast<char>(ch
);
2402 if ( notskip
&& skipsize
>= remove_threshold
)
2409 ostr
<< static_cast<char>(ch
);
2418 ostr
<< "..." << std::endl
<< "The rest of the test output was removed "
2419 "since it exceeds the threshold of "
2420 << remove_threshold
<< " characters." << std::endl
;
2422 output
= ostr
.str();
2426 //----------------------------------------------------------------------
2427 bool cmCTestTestHandler::SetTestsProperties(
2428 const std::vector
<std::string
>& args
)
2430 std::vector
<std::string
>::const_iterator it
;
2431 std::vector
<cmStdString
> tests
;
2433 for ( it
= args
.begin(); it
!= args
.end(); ++ it
)
2435 if ( *it
== "PROPERTIES" )
2440 tests
.push_back(*it
);
2446 ++ it
; // skip PROPERTIES
2447 for ( ; it
!= args
.end(); ++ it
)
2449 std::string key
= *it
;
2451 if ( it
== args
.end() )
2455 std::string val
= *it
;
2456 std::vector
<cmStdString
>::const_iterator tit
;
2457 for ( tit
= tests
.begin(); tit
!= tests
.end(); ++ tit
)
2459 cmCTestTestHandler::ListOfTests::iterator rtit
;
2460 for ( rtit
= this->TestList
.begin();
2461 rtit
!= this->TestList
.end();
2464 if ( *tit
== rtit
->Name
)
2466 if ( key
== "WILL_FAIL" )
2468 rtit
->WillFail
= cmSystemTools::IsOn(val
.c_str());
2470 if ( key
== "TIMEOUT" )
2472 rtit
->Timeout
= atof(val
.c_str());
2474 if ( key
== "FAIL_REGULAR_EXPRESSION" )
2476 std::vector
<std::string
> lval
;
2477 cmSystemTools::ExpandListArgument(val
.c_str(), lval
);
2478 std::vector
<std::string
>::iterator crit
;
2479 for ( crit
= lval
.begin(); crit
!= lval
.end(); ++ crit
)
2481 rtit
->ErrorRegularExpressions
.push_back(
2482 std::pair
<cmsys::RegularExpression
, std::string
>(
2483 cmsys::RegularExpression(crit
->c_str()),
2484 std::string(crit
->c_str())));
2487 if ( key
== "DEPENDS" )
2489 std::vector
<std::string
> lval
;
2490 cmSystemTools::ExpandListArgument(val
.c_str(), lval
);
2491 std::vector
<std::string
>::iterator crit
;
2492 for ( crit
= lval
.begin(); crit
!= lval
.end(); ++ crit
)
2494 rtit
->Depends
.push_back(*crit
);
2497 if ( key
== "ENVIRONMENT" )
2499 std::vector
<std::string
> lval
;
2500 cmSystemTools::ExpandListArgument(val
.c_str(), lval
);
2501 std::vector
<std::string
>::iterator crit
;
2502 for ( crit
= lval
.begin(); crit
!= lval
.end(); ++ crit
)
2504 rtit
->Environment
.push_back(*crit
);
2507 if ( key
== "LABELS" )
2509 std::vector
<std::string
> lval
;
2510 cmSystemTools::ExpandListArgument(val
.c_str(), lval
);
2511 std::vector
<std::string
>::iterator crit
;
2512 for ( crit
= lval
.begin(); crit
!= lval
.end(); ++ crit
)
2514 rtit
->Labels
.push_back(*crit
);
2518 if ( key
== "MEASUREMENT" )
2520 size_t pos
= val
.find_first_of("=");
2521 if ( pos
!= val
.npos
)
2523 std::string mKey
= val
.substr(0, pos
);
2524 const char* mVal
= val
.c_str() + pos
+ 1;
2525 rtit
->Measurements
[mKey
] = mVal
;
2529 rtit
->Measurements
[val
] = "1";
2532 if ( key
== "PASS_REGULAR_EXPRESSION" )
2534 std::vector
<std::string
> lval
;
2535 cmSystemTools::ExpandListArgument(val
.c_str(), lval
);
2536 std::vector
<std::string
>::iterator crit
;
2537 for ( crit
= lval
.begin(); crit
!= lval
.end(); ++ crit
)
2539 rtit
->RequiredRegularExpressions
.push_back(
2540 std::pair
<cmsys::RegularExpression
, std::string
>(
2541 cmsys::RegularExpression(crit
->c_str()),
2542 std::string(crit
->c_str())));
2552 //----------------------------------------------------------------------
2553 bool cmCTestTestHandler::AddTest(const std::vector
<std::string
>& args
)
2555 const std::string
& testname
= args
[0];
2556 cmCTestLog(this->CTest
, DEBUG
, "Add test: " << args
[0] << std::endl
);
2557 if (this->UseExcludeRegExpFlag
&&
2558 this->UseExcludeRegExpFirst
&&
2559 this->ExcludeTestsRegularExpression
.find(testname
.c_str()))
2563 if ( this->MemCheck
)
2565 std::vector
<cmStdString
>::iterator it
;
2567 for ( it
= this->CustomTestsIgnore
.begin();
2568 it
!= this->CustomTestsIgnore
.end(); ++ it
)
2570 if ( *it
== testname
)
2578 cmCTestLog(this->CTest
, HANDLER_VERBOSE_OUTPUT
, "Ignore memcheck: "
2579 << *it
<< std::endl
);
2585 std::vector
<cmStdString
>::iterator it
;
2587 for ( it
= this->CustomTestsIgnore
.begin();
2588 it
!= this->CustomTestsIgnore
.end(); ++ it
)
2590 if ( *it
== testname
)
2598 cmCTestLog(this->CTest
, HANDLER_VERBOSE_OUTPUT
, "Ignore test: "
2599 << *it
<< std::endl
);
2604 cmCTestTestProperties test
;
2605 test
.Name
= testname
;
2607 test
.Directory
= cmSystemTools::GetCurrentWorkingDirectory();
2608 cmCTestLog(this->CTest
, DEBUG
, "Set test directory: "
2609 << test
.Directory
<< std::endl
);
2611 test
.IsInBasedOnREOptions
= true;
2612 test
.WillFail
= false;
2614 if (this->UseIncludeRegExpFlag
&&
2615 !this->IncludeTestsRegularExpression
.find(testname
.c_str()))
2617 test
.IsInBasedOnREOptions
= false;
2619 else if (this->UseExcludeRegExpFlag
&&
2620 !this->UseExcludeRegExpFirst
&&
2621 this->ExcludeTestsRegularExpression
.find(testname
.c_str()))
2623 test
.IsInBasedOnREOptions
= false;
2625 this->TestList
.push_back(test
);