1 /*=========================================================================
3 Program: CMake - Cross-Platform Makefile Generator
4 Module: $RCSfile: cmCTestTestHandler.cxx,v $
6 Date: $Date: 2009-09-11 17:34:35 $
7 Version: $Revision: 1.120 $
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"
20 #include "cmCTestBatchTestHandler.h"
22 #include "cmCTestRunTest.h"
24 #include "cmGeneratedFileStream.h"
25 #include <cmsys/Process.h>
26 #include <cmsys/RegularExpression.hxx>
27 #include <cmsys/Base64.h>
28 #include "cmMakefile.h"
29 #include "cmGlobalGenerator.h"
30 #include "cmLocalGenerator.h"
31 #include "cmCommand.h"
32 #include "cmSystemTools.h"
33 #include "cmXMLSafe.h"
39 #include <memory> // auto_ptr
41 //----------------------------------------------------------------------
42 class cmCTestSubdirCommand
: public cmCommand
46 * This is a virtual constructor for the command.
48 virtual cmCommand
* Clone()
50 cmCTestSubdirCommand
* c
= new cmCTestSubdirCommand
;
51 c
->TestHandler
= this->TestHandler
;
56 * This is called when the command is first encountered in
57 * the CMakeLists.txt file.
59 virtual bool InitialPass(std::vector
<std::string
> const& args
,
63 * The name of the command as specified in CMakeList.txt.
65 virtual const char* GetName() { return "subdirs";}
68 virtual const char* GetTerseDocumentation() { return ""; }
69 virtual const char* GetFullDocumentation() { return ""; }
71 cmTypeMacro(cmCTestSubdirCommand
, cmCommand
);
73 cmCTestTestHandler
* TestHandler
;
76 //----------------------------------------------------------------------
77 bool cmCTestSubdirCommand
78 ::InitialPass(std::vector
<std::string
> const& args
, cmExecutionStatus
&)
82 this->SetError("called with incorrect number of arguments");
85 std::vector
<std::string
>::const_iterator it
;
86 std::string cwd
= cmSystemTools::GetCurrentWorkingDirectory();
87 for ( it
= args
.begin(); it
!= args
.end(); ++ it
)
89 cmSystemTools::ChangeDirectory(cwd
.c_str());
90 std::string fname
= cwd
;
94 if ( !cmSystemTools::FileExists(fname
.c_str()) )
96 // No subdirectory? So what...
99 cmSystemTools::ChangeDirectory(fname
.c_str());
100 const char* testFilename
;
101 if( cmSystemTools::FileExists("CTestTestfile.cmake") )
103 // does the CTestTestfile.cmake exist ?
104 testFilename
= "CTestTestfile.cmake";
106 else if( cmSystemTools::FileExists("DartTestfile.txt") )
108 // does the DartTestfile.txt exist ?
109 testFilename
= "DartTestfile.txt";
113 // No CTestTestfile? Who cares...
114 cmSystemTools::ChangeDirectory(cwd
.c_str());
118 fname
+= testFilename
;
120 this->Makefile
->ReadListFile(this->Makefile
->GetCurrentListFile(),
122 cmSystemTools::ChangeDirectory(cwd
.c_str());
125 std::string m
= "Could not find include file: ";
127 this->SetError(m
.c_str());
134 //----------------------------------------------------------------------
135 class cmCTestAddSubdirectoryCommand
: public cmCommand
139 * This is a virtual constructor for the command.
141 virtual cmCommand
* Clone()
143 cmCTestAddSubdirectoryCommand
* c
= new cmCTestAddSubdirectoryCommand
;
144 c
->TestHandler
= this->TestHandler
;
149 * This is called when the command is first encountered in
150 * the CMakeLists.txt file.
152 virtual bool InitialPass(std::vector
<std::string
> const& args
,
153 cmExecutionStatus
&);
156 * The name of the command as specified in CMakeList.txt.
158 virtual const char* GetName() { return "add_subdirectory";}
161 virtual const char* GetTerseDocumentation() { return ""; }
162 virtual const char* GetFullDocumentation() { return ""; }
164 cmTypeMacro(cmCTestAddSubdirectoryCommand
, cmCommand
);
166 cmCTestTestHandler
* TestHandler
;
169 //----------------------------------------------------------------------
170 bool cmCTestAddSubdirectoryCommand
171 ::InitialPass(std::vector
<std::string
> const& args
, cmExecutionStatus
&)
175 this->SetError("called with incorrect number of arguments");
179 std::string cwd
= cmSystemTools::GetCurrentWorkingDirectory();
180 cmSystemTools::ChangeDirectory(cwd
.c_str());
181 std::string fname
= cwd
;
185 if ( !cmSystemTools::FileExists(fname
.c_str()) )
187 // No subdirectory? So what...
190 cmSystemTools::ChangeDirectory(fname
.c_str());
191 const char* testFilename
;
192 if( cmSystemTools::FileExists("CTestTestfile.cmake") )
194 // does the CTestTestfile.cmake exist ?
195 testFilename
= "CTestTestfile.cmake";
197 else if( cmSystemTools::FileExists("DartTestfile.txt") )
199 // does the DartTestfile.txt exist ?
200 testFilename
= "DartTestfile.txt";
204 // No CTestTestfile? Who cares...
205 cmSystemTools::ChangeDirectory(cwd
.c_str());
209 fname
+= testFilename
;
211 this->Makefile
->ReadListFile(this->Makefile
->GetCurrentListFile(),
213 cmSystemTools::ChangeDirectory(cwd
.c_str());
216 std::string m
= "Could not find include file: ";
218 this->SetError(m
.c_str());
224 //----------------------------------------------------------------------
225 class cmCTestAddTestCommand
: public cmCommand
229 * This is a virtual constructor for the command.
231 virtual cmCommand
* Clone()
233 cmCTestAddTestCommand
* c
= new cmCTestAddTestCommand
;
234 c
->TestHandler
= this->TestHandler
;
239 * This is called when the command is first encountered in
240 * the CMakeLists.txt file.
242 virtual bool InitialPass(std::vector
<std::string
> const&,
243 cmExecutionStatus
&);
246 * The name of the command as specified in CMakeList.txt.
248 virtual const char* GetName() { return "ADD_TEST";}
251 virtual const char* GetTerseDocumentation() { return ""; }
252 virtual const char* GetFullDocumentation() { return ""; }
254 cmTypeMacro(cmCTestAddTestCommand
, cmCommand
);
256 cmCTestTestHandler
* TestHandler
;
259 //----------------------------------------------------------------------
260 bool cmCTestAddTestCommand
261 ::InitialPass(std::vector
<std::string
> const& args
, cmExecutionStatus
&)
263 if ( args
.size() < 2 )
265 this->SetError("called with incorrect number of arguments");
268 return this->TestHandler
->AddTest(args
);
271 //----------------------------------------------------------------------
272 class cmCTestSetTestsPropertiesCommand
: public cmCommand
276 * This is a virtual constructor for the command.
278 virtual cmCommand
* Clone()
280 cmCTestSetTestsPropertiesCommand
* c
281 = new cmCTestSetTestsPropertiesCommand
;
282 c
->TestHandler
= this->TestHandler
;
287 * This is called when the command is first encountered in
288 * the CMakeLists.txt file.
290 virtual bool InitialPass(std::vector
<std::string
> const&,
291 cmExecutionStatus
&);
294 * The name of the command as specified in CMakeList.txt.
296 virtual const char* GetName() { return "SET_TESTS_PROPERTIES";}
299 virtual const char* GetTerseDocumentation() { return ""; }
300 virtual const char* GetFullDocumentation() { return ""; }
302 cmTypeMacro(cmCTestSetTestsPropertiesCommand
, cmCommand
);
304 cmCTestTestHandler
* TestHandler
;
307 //----------------------------------------------------------------------
308 bool cmCTestSetTestsPropertiesCommand
309 ::InitialPass(std::vector
<std::string
> const& args
, cmExecutionStatus
&)
311 return this->TestHandler
->SetTestsProperties(args
);
314 //----------------------------------------------------------------------
315 // get the next number in a string with numbers separated by ,
316 // pos is the start of the search and pos2 is the end of the search
317 // pos becomes pos2 after a call to GetNextNumber.
318 // -1 is returned at the end of the list.
319 inline int GetNextNumber(std::string
const& in
,
321 std::string::size_type
& pos
,
322 std::string::size_type
& pos2
)
324 pos2
= in
.find(',', pos
);
333 val
= atoi(in
.substr(pos
, pos2
-pos
).c_str());
340 if(in
.size()-pos
== 0)
346 val
= atoi(in
.substr(pos
, in
.size()-pos
).c_str());
352 //----------------------------------------------------------------------
353 // get the next number in a string with numbers separated by ,
354 // pos is the start of the search and pos2 is the end of the search
355 // pos becomes pos2 after a call to GetNextNumber.
356 // -1 is returned at the end of the list.
357 inline int GetNextRealNumber(std::string
const& in
,
359 std::string::size_type
& pos
,
360 std::string::size_type
& pos2
)
362 pos2
= in
.find(',', pos
);
371 val
= atof(in
.substr(pos
, pos2
-pos
).c_str());
378 if(in
.size()-pos
== 0)
384 val
= atof(in
.substr(pos
, in
.size()-pos
).c_str());
391 //----------------------------------------------------------------------
392 cmCTestTestHandler::cmCTestTestHandler()
394 this->UseUnion
= false;
396 this->UseIncludeLabelRegExpFlag
= false;
397 this->UseExcludeLabelRegExpFlag
= false;
398 this->UseIncludeRegExpFlag
= false;
399 this->UseExcludeRegExpFlag
= false;
400 this->UseExcludeRegExpFirst
= false;
402 this->CustomMaximumPassedTestOutputSize
= 1 * 1024;
403 this->CustomMaximumFailedTestOutputSize
= 300 * 1024;
405 this->MemCheck
= false;
409 // regex to detect <DartMeasurement>...</DartMeasurement>
410 this->DartStuff
.compile(
411 "(<DartMeasurement.*/DartMeasurement[a-zA-Z]*>)");
412 // regex to detect each individual <DartMeasurement>...</DartMeasurement>
413 this->DartStuff1
.compile(
414 "(<DartMeasurement[^<]*</DartMeasurement[a-zA-Z]*>)");
417 //----------------------------------------------------------------------
418 void cmCTestTestHandler::Initialize()
420 this->Superclass::Initialize();
422 this->ElapsedTestingTime
= -1;
424 this->TestResults
.clear();
426 this->CustomTestsIgnore
.clear();
427 this->StartTest
= "";
430 this->CustomPreTest
.clear();
431 this->CustomPostTest
.clear();
432 this->CustomMaximumPassedTestOutputSize
= 1 * 1024;
433 this->CustomMaximumFailedTestOutputSize
= 300 * 1024;
435 this->TestsToRun
.clear();
437 this->UseIncludeRegExpFlag
= false;
438 this->UseExcludeRegExpFlag
= false;
439 this->UseExcludeRegExpFirst
= false;
440 this->IncludeLabelRegularExpression
= "";
441 this->ExcludeLabelRegularExpression
= "";
442 this->IncludeRegExp
= "";
443 this->ExcludeRegExp
= "";
445 TestsToRunString
= "";
446 this->UseUnion
= false;
447 this->TestList
.clear();
450 //----------------------------------------------------------------------
451 void cmCTestTestHandler::PopulateCustomVectors(cmMakefile
*mf
)
453 this->CTest
->PopulateCustomVector(mf
, "CTEST_CUSTOM_PRE_TEST",
454 this->CustomPreTest
);
455 this->CTest
->PopulateCustomVector(mf
, "CTEST_CUSTOM_POST_TEST",
456 this->CustomPostTest
);
457 this->CTest
->PopulateCustomVector(mf
,
458 "CTEST_CUSTOM_TESTS_IGNORE",
459 this->CustomTestsIgnore
);
460 this->CTest
->PopulateCustomInteger(mf
,
461 "CTEST_CUSTOM_MAXIMUM_PASSED_TEST_OUTPUT_SIZE",
462 this->CustomMaximumPassedTestOutputSize
);
463 this->CTest
->PopulateCustomInteger(mf
,
464 "CTEST_CUSTOM_MAXIMUM_FAILED_TEST_OUTPUT_SIZE",
465 this->CustomMaximumFailedTestOutputSize
);
468 //----------------------------------------------------------------------
469 int cmCTestTestHandler::PreProcessHandler()
471 if ( !this->ExecuteCommands(this->CustomPreTest
) )
473 cmCTestLog(this->CTest
, ERROR_MESSAGE
,
474 "Problem executing pre-test command(s)." << std::endl
);
480 //----------------------------------------------------------------------
481 int cmCTestTestHandler::PostProcessHandler()
483 if ( !this->ExecuteCommands(this->CustomPostTest
) )
485 cmCTestLog(this->CTest
, ERROR_MESSAGE
,
486 "Problem executing post-test command(s)." << std::endl
);
492 //----------------------------------------------------------------------
493 //clearly it would be nice if this were broken up into a few smaller
494 //functions and commented...
495 int cmCTestTestHandler::ProcessHandler()
497 // Update internal data structure from generic one
498 this->SetTestsToRunInformation(this->GetOption("TestsToRunInformation"));
499 this->SetUseUnion(cmSystemTools::IsOn(this->GetOption("UseUnion")));
500 if(this->GetOption("ParallelLevel"))
502 this->CTest
->SetParallelLevel(atoi(this->GetOption("ParallelLevel")));
505 val
= this->GetOption("LabelRegularExpression");
508 this->UseIncludeLabelRegExpFlag
= true;
509 this->IncludeLabelRegExp
= val
;
511 val
= this->GetOption("ExcludeLabelRegularExpression");
514 this->UseExcludeLabelRegExpFlag
= true;
515 this->ExcludeLabelRegularExpression
= val
;
517 val
= this->GetOption("IncludeRegularExpression");
520 this->UseIncludeRegExp();
521 this->SetIncludeRegExp(val
);
523 val
= this->GetOption("ExcludeRegularExpression");
526 this->UseExcludeRegExp();
527 this->SetExcludeRegExp(val
);
530 this->TestResults
.clear();
532 cmCTestLog(this->CTest
, HANDLER_OUTPUT
,
533 (this->MemCheck
? "Memory check" : "Test")
534 << " project " << cmSystemTools::GetCurrentWorkingDirectory()
536 if ( ! this->PreProcessHandler() )
541 cmGeneratedFileStream mLogFile
;
542 this->StartLogFile((this->MemCheck
? "DynamicAnalysis" : "Test"), mLogFile
);
543 this->LogFile
= &mLogFile
;
545 std::vector
<cmStdString
> passed
;
546 std::vector
<cmStdString
> failed
;
549 //start the real time clock
550 double clock_start
, clock_finish
;
551 clock_start
= cmSystemTools::GetTime();
553 this->ProcessDirectory(passed
, failed
);
555 clock_finish
= cmSystemTools::GetTime();
557 total
= int(passed
.size()) + int(failed
.size());
561 if ( !this->CTest
->GetShowOnly() )
563 cmCTestLog(this->CTest
, ERROR_MESSAGE
, "No tests were found!!!"
569 if (this->HandlerVerbose
&& passed
.size() &&
570 (this->UseIncludeRegExpFlag
|| this->UseExcludeRegExpFlag
))
572 cmCTestLog(this->CTest
, HANDLER_VERBOSE_OUTPUT
, std::endl
573 << "The following tests passed:" << std::endl
);
574 for(std::vector
<cmStdString
>::iterator j
= passed
.begin();
575 j
!= passed
.end(); ++j
)
577 cmCTestLog(this->CTest
, HANDLER_VERBOSE_OUTPUT
, "\t" << *j
582 float percent
= float(passed
.size()) * 100.0f
/ total
;
583 if ( failed
.size() > 0 && percent
> 99)
588 cmCTestLog(this->CTest
, HANDLER_OUTPUT
, std::endl
589 << static_cast<int>(percent
+ .5) << "% tests passed, "
590 << failed
.size() << " tests failed out of "
591 << total
<< std::endl
);
592 if(this->CTest
->GetLabelSummary())
594 this->PrintLabelSummary();
597 sprintf(realBuf
, "%6.2f sec", (double)(clock_finish
- clock_start
));
598 cmCTestLog(this->CTest
, HANDLER_OUTPUT
, "\nTotal Test time (real) = "
599 << realBuf
<< "\n" );
603 cmGeneratedFileStream ofs
;
604 cmCTestLog(this->CTest
, ERROR_MESSAGE
, std::endl
605 << "The following tests FAILED:" << std::endl
);
606 this->StartLogFile("TestsFailed", ofs
);
608 std::vector
<cmCTestTestHandler::cmCTestTestResult
>::iterator ftit
;
609 for(ftit
= this->TestResults
.begin();
610 ftit
!= this->TestResults
.end(); ++ftit
)
612 if ( ftit
->Status
!= cmCTestTestHandler::COMPLETED
)
614 ofs
<< ftit
->TestCount
<< ":" << ftit
->Name
<< std::endl
;
615 cmCTestLog(this->CTest
, HANDLER_OUTPUT
, "\t" << std::setw(3)
616 << ftit
->TestCount
<< " - "
617 << ftit
->Name
.c_str() << " ("
618 << this->GetTestStatus(ftit
->Status
) << ")"
625 if ( this->CTest
->GetProduceXML() )
627 cmGeneratedFileStream xmlfile
;
628 if( !this->StartResultingXML(
629 (this->MemCheck
? cmCTest::PartMemCheck
: cmCTest::PartTest
),
630 (this->MemCheck
? "DynamicAnalysis" : "Test"), xmlfile
) )
632 cmCTestLog(this->CTest
, ERROR_MESSAGE
, "Cannot create "
633 << (this->MemCheck
? "memory check" : "testing")
634 << " XML file" << std::endl
);
638 this->GenerateDartOutput(xmlfile
);
641 if ( ! this->PostProcessHandler() )
647 if ( !failed
.empty() )
656 //----------------------------------------------------------------------
657 void cmCTestTestHandler::PrintLabelSummary()
659 cmCTestTestHandler::ListOfTests::iterator it
= this->TestList
.begin();
660 cmCTestTestHandler::TestResultsVector::iterator ri
=
661 this->TestResults
.begin();
662 std::map
<cmStdString
, double> labelTimes
;
663 std::set
<cmStdString
> labels
;
665 std::string::size_type maxlen
= 0;
666 for(; it
!= this->TestList
.end(); ++it
)
668 cmCTestTestProperties
& p
= *it
;
669 if(p
.Labels
.size() != 0)
671 for(std::vector
<std::string
>::iterator l
= p
.Labels
.begin();
672 l
!= p
.Labels
.end(); ++l
)
674 if((*l
).size() > maxlen
)
676 maxlen
= (*l
).size();
683 it
= this->TestList
.begin();
684 ri
= this->TestResults
.begin();
686 for(; it
!= this->TestList
.end(); ++it
, ++ri
)
688 cmCTestTestProperties
& p
= *it
;
689 cmCTestTestResult
&result
= *ri
;
690 if(p
.Labels
.size() != 0)
692 for(std::vector
<std::string
>::iterator l
= p
.Labels
.begin();
693 l
!= p
.Labels
.end(); ++l
)
695 labelTimes
[*l
] += result
.ExecutionTime
;
702 cmCTestLog(this->CTest
, HANDLER_OUTPUT
, "\nLabel Time Summary:");
704 for(std::set
<cmStdString
>::const_iterator i
= labels
.begin();
705 i
!= labels
.end(); ++i
)
707 std::string label
= *i
;
708 label
.resize(maxlen
+3, ' ');
710 sprintf(buf
, "%6.2f sec", labelTimes
[*i
]);
711 cmCTestLog(this->CTest
, HANDLER_OUTPUT
, "\n"
712 << label
<< " = " << buf
);
715 *this->LogFile
<< "\n" << *i
<< " = "
723 *this->LogFile
<< "\n";
725 cmCTestLog(this->CTest
, HANDLER_OUTPUT
, "\n");
730 //----------------------------------------------------------------------
731 void cmCTestTestHandler::CheckLabelFilterInclude(cmCTestTestProperties
& it
)
733 // if not using Labels to filter then return
734 if (!this->UseIncludeLabelRegExpFlag
)
738 // if there are no labels and we are filtering by labels
739 // then exclude the test as it does not have the label
740 if(it
.Labels
.size() == 0 )
742 it
.IsInBasedOnREOptions
= false;
745 // check to see if the label regular expression matches
746 bool found
= false; // assume it does not match
747 // loop over all labels and look for match
748 for(std::vector
<std::string
>::iterator l
= it
.Labels
.begin();
749 l
!= it
.Labels
.end(); ++l
)
751 if(this->IncludeLabelRegularExpression
.find(*l
))
756 // if no match was found, exclude the test
759 it
.IsInBasedOnREOptions
= false;
764 //----------------------------------------------------------------------
765 void cmCTestTestHandler::CheckLabelFilterExclude(cmCTestTestProperties
& it
)
767 // if not using Labels to filter then return
768 if (!this->UseExcludeLabelRegExpFlag
)
772 // if there are no labels and we are excluding by labels
773 // then do nothing as a no label can not be a match
774 if(it
.Labels
.size() == 0 )
778 // check to see if the label regular expression matches
779 bool found
= false; // assume it does not match
780 // loop over all labels and look for match
781 for(std::vector
<std::string
>::iterator l
= it
.Labels
.begin();
782 l
!= it
.Labels
.end(); ++l
)
784 if(this->ExcludeLabelRegularExpression
.find(*l
))
789 // if match was found, exclude the test
792 it
.IsInBasedOnREOptions
= false;
796 //----------------------------------------------------------------------
797 void cmCTestTestHandler::CheckLabelFilter(cmCTestTestProperties
& it
)
799 this->CheckLabelFilterInclude(it
);
800 this->CheckLabelFilterExclude(it
);
803 //----------------------------------------------------------------------
804 void cmCTestTestHandler::ComputeTestList()
806 this->TestList
.clear(); // clear list of test
807 this->GetListOfTests();
808 cmCTestTestHandler::ListOfTests::size_type tmsize
= this->TestList
.size();
809 // how many tests are in based on RegExp?
811 cmCTestTestHandler::ListOfTests::iterator it
;
812 for ( it
= this->TestList
.begin(); it
!= this->TestList
.end(); it
++ )
814 this->CheckLabelFilter(*it
);
815 if (it
->IsInBasedOnREOptions
)
820 // expand the test list based on the union flag
823 this->ExpandTestsToRunInformation((int)tmsize
);
827 this->ExpandTestsToRunInformation(inREcnt
);
829 // Now create a final list of tests to run
832 std::string last_directory
= "";
833 ListOfTests finalList
;
834 for ( it
= this->TestList
.begin(); it
!= this->TestList
.end(); it
++ )
837 if (it
->IsInBasedOnREOptions
)
844 // if it is not in the list and not in the regexp then skip
845 if ((this->TestsToRun
.size() &&
846 std::find(this->TestsToRun
.begin(), this->TestsToRun
.end(), cnt
)
847 == this->TestsToRun
.end()) && !it
->IsInBasedOnREOptions
)
854 // is this test in the list of tests to run? If not then skip it
855 if ((this->TestsToRun
.size() &&
856 std::find(this->TestsToRun
.begin(),
857 this->TestsToRun
.end(), inREcnt
)
858 == this->TestsToRun
.end()) || !it
->IsInBasedOnREOptions
)
863 it
->Index
= cnt
; // save the index into the test list for this test
864 finalList
.push_back(*it
);
866 // Save the total number of tests before exclusions
867 this->TotalNumberOfTests
= this->TestList
.size();
868 // Set the TestList to the final list of all test
869 this->TestList
= finalList
;
870 std::string::size_type max
= this->CTest
->GetMaxTestNameWidth();
871 for (it
= this->TestList
.begin();
872 it
!= this->TestList
.end(); it
++ )
874 cmCTestTestProperties
& p
= *it
;
875 if(max
< p
.Name
.size())
880 if(static_cast<std::string::size_type
>(this->CTest
->GetMaxTestNameWidth())
883 this->CTest
->SetMaxTestNameWidth(static_cast<int>(max
));
887 bool cmCTestTestHandler::GetValue(const char* tag
,
893 cmSystemTools::GetLineFromStream(fin
, line
);
897 ret
= cmSystemTools::GetLineFromStream(fin
, line
); // read blank line
901 cmCTestLog(this->CTest
, ERROR_MESSAGE
,
902 "parse error: missing tag: "
903 << tag
<< " found [" << line
<< "]" << std::endl
);
909 bool cmCTestTestHandler::GetValue(const char* tag
,
914 cmSystemTools::GetLineFromStream(fin
, line
);
919 ret
= cmSystemTools::GetLineFromStream(fin
, line
); // read blank line
923 cmCTestLog(this->CTest
, ERROR_MESSAGE
,
924 "parse error: missing tag: "
925 << tag
<< " found [" << line
<< "]" << std::endl
);
931 bool cmCTestTestHandler::GetValue(const char* tag
,
936 cmSystemTools::GetLineFromStream(fin
, line
);
951 ret
= cmSystemTools::GetLineFromStream(fin
, line
); // read blank line
955 cmCTestLog(this->CTest
, ERROR_MESSAGE
,
956 "parse error: missing tag: "
957 << tag
<< " found [" << line
<< "]" << std::endl
);
963 bool cmCTestTestHandler::GetValue(const char* tag
,
968 cmSystemTools::GetLineFromStream(fin
, line
);
973 ret
= cmSystemTools::GetLineFromStream(fin
, line
); // read blank line
977 cmCTestLog(this->CTest
, ERROR_MESSAGE
,
978 "parse error: missing tag: "
979 << tag
<< " found [" << line
.c_str() << "]" << std::endl
);
985 bool cmCTestTestHandler::GetValue(const char* tag
,
990 cmSystemTools::GetLineFromStream(fin
, line
);
994 ret
= cmSystemTools::GetLineFromStream(fin
, value
);
998 cmCTestLog(this->CTest
, ERROR_MESSAGE
,
999 "parse error: missing tag: "
1000 << tag
<< " found [" << line
<< "]" << std::endl
);
1006 //---------------------------------------------------------------------
1007 void cmCTestTestHandler::ProcessDirectory(std::vector
<cmStdString
> &passed
,
1008 std::vector
<cmStdString
> &failed
)
1010 this->ComputeTestList();
1011 this->StartTest
= this->CTest
->CurrentTime();
1012 this->StartTestTime
= static_cast<unsigned int>(cmSystemTools::GetTime());
1013 double elapsed_time_start
= cmSystemTools::GetTime();
1015 cmCTestMultiProcessHandler
* parallel
= this->CTest
->GetBatchJobs() ?
1016 new cmCTestBatchTestHandler
: new cmCTestMultiProcessHandler
;
1017 parallel
->SetCTest(this->CTest
);
1018 parallel
->SetParallelLevel(this->CTest
->GetParallelLevel());
1019 parallel
->SetTestHandler(this);
1021 *this->LogFile
<< "Start testing: "
1022 << this->CTest
->CurrentTime() << std::endl
1023 << "----------------------------------------------------------"
1026 cmCTestMultiProcessHandler::TestMap tests
;
1027 cmCTestMultiProcessHandler::PropertiesMap properties
;
1029 for (ListOfTests::iterator it
= this->TestList
.begin();
1030 it
!= this->TestList
.end(); ++it
)
1032 cmCTestTestProperties
& p
= *it
;
1033 cmCTestMultiProcessHandler::TestSet depends
;
1035 if(p
.Depends
.size())
1037 for(std::vector
<std::string
>::iterator i
= p
.Depends
.begin();
1038 i
!= p
.Depends
.end(); ++i
)
1040 for(ListOfTests::iterator it2
= this->TestList
.begin();
1041 it2
!= this->TestList
.end(); ++it2
)
1045 depends
.insert(it2
->Index
);
1046 break; // break out of test loop as name can only match 1
1051 tests
[it
->Index
] = depends
;
1052 properties
[it
->Index
] = &*it
;
1054 parallel
->SetTests(tests
, properties
);
1055 parallel
->SetPassFailVectors(&passed
, &failed
);
1056 this->TestResults
.clear();
1057 parallel
->SetTestResults(&this->TestResults
);
1058 if(this->CTest
->GetShowOnly())
1060 parallel
->PrintTestList();
1064 parallel
->RunTests();
1067 this->EndTest
= this->CTest
->CurrentTime();
1068 this->EndTestTime
= static_cast<unsigned int>(cmSystemTools::GetTime());
1069 this->ElapsedTestingTime
= cmSystemTools::GetTime() - elapsed_time_start
;
1070 *this->LogFile
<< "End testing: "
1071 << this->CTest
->CurrentTime() << std::endl
;
1074 //----------------------------------------------------------------------
1075 void cmCTestTestHandler::GenerateTestCommand(std::vector
<std::string
>&)
1079 //----------------------------------------------------------------------
1080 void cmCTestTestHandler::GenerateDartOutput(std::ostream
& os
)
1082 if ( !this->CTest
->GetProduceXML() )
1087 this->CTest
->StartXML(os
, this->AppendXML
);
1089 << "\t<StartDateTime>" << this->StartTest
<< "</StartDateTime>\n"
1090 << "\t<StartTestTime>" << this->StartTestTime
<< "</StartTestTime>\n"
1091 << "\t<TestList>\n";
1092 cmCTestTestHandler::TestResultsVector::size_type cc
;
1093 for ( cc
= 0; cc
< this->TestResults
.size(); cc
++ )
1095 cmCTestTestResult
*result
= &this->TestResults
[cc
];
1096 std::string testPath
= result
->Path
+ "/" + result
->Name
;
1097 os
<< "\t\t<Test>" << cmXMLSafe(
1098 this->CTest
->GetShortPathToFile(testPath
.c_str()))
1099 << "</Test>" << std::endl
;
1101 os
<< "\t</TestList>\n";
1102 for ( cc
= 0; cc
< this->TestResults
.size(); cc
++ )
1104 cmCTestTestResult
*result
= &this->TestResults
[cc
];
1105 this->WriteTestResultHeader(os
, result
);
1106 os
<< "\t\t<Results>" << std::endl
;
1107 if ( result
->Status
!= cmCTestTestHandler::NOT_RUN
)
1109 if ( result
->Status
!= cmCTestTestHandler::COMPLETED
||
1110 result
->ReturnValue
)
1112 os
<< "\t\t\t<NamedMeasurement type=\"text/string\" "
1113 "name=\"Exit Code\"><Value>"
1114 << cmXMLSafe(this->GetTestStatus(result
->Status
))
1116 "</NamedMeasurement>\n"
1117 << "\t\t\t<NamedMeasurement type=\"text/string\" "
1118 "name=\"Exit Value\"><Value>"
1119 << result
->ReturnValue
1120 << "</Value></NamedMeasurement>"
1123 os
<< result
->RegressionImages
;
1124 os
<< "\t\t\t<NamedMeasurement type=\"numeric/double\" "
1125 << "name=\"Execution Time\"><Value>"
1126 << result
->ExecutionTime
1127 << "</Value></NamedMeasurement>\n";
1128 if(result
->Reason
.size())
1130 const char* reasonType
= "Pass Reason";
1131 if(result
->Status
!= cmCTestTestHandler::COMPLETED
&&
1132 result
->Status
!= cmCTestTestHandler::NOT_RUN
)
1134 reasonType
= "Fail Reason";
1136 os
<< "\t\t\t<NamedMeasurement type=\"text/string\" "
1137 << "name=\"" << reasonType
<< "\"><Value>"
1138 << cmXMLSafe(result
->Reason
)
1139 << "</Value></NamedMeasurement>\n";
1142 << "\t\t\t<NamedMeasurement type=\"text/string\" "
1143 << "name=\"Completion Status\"><Value>"
1144 << cmXMLSafe(result
->CompletionStatus
)
1145 << "</Value></NamedMeasurement>\n";
1148 << "\t\t\t<NamedMeasurement type=\"text/string\" "
1149 << "name=\"Command Line\"><Value>"
1150 << cmXMLSafe(result
->FullCommandLine
)
1151 << "</Value></NamedMeasurement>\n";
1152 std::map
<cmStdString
,cmStdString
>::iterator measureIt
;
1153 for ( measureIt
= result
->Properties
->Measurements
.begin();
1154 measureIt
!= result
->Properties
->Measurements
.end();
1158 << "\t\t\t<NamedMeasurement type=\"text/string\" "
1159 << "name=\"" << measureIt
->first
.c_str() << "\"><Value>"
1160 << cmXMLSafe(measureIt
->second
)
1161 << "</Value></NamedMeasurement>\n";
1164 << "\t\t\t<Measurement>\n"
1165 << "\t\t\t\t<Value>";
1166 os
<< cmXMLSafe(result
->Output
);
1169 << "\t\t\t</Measurement>\n"
1170 << "\t\t</Results>\n";
1171 this->WriteTestResultFooter(os
, result
);
1174 os
<< "\t<EndDateTime>" << this->EndTest
<< "</EndDateTime>\n"
1175 << "\t<EndTestTime>" << this->EndTestTime
<< "</EndTestTime>\n"
1176 << "<ElapsedMinutes>"
1177 << static_cast<int>(this->ElapsedTestingTime
/6)/10.0
1178 << "</ElapsedMinutes>"
1179 << "</Testing>" << std::endl
;
1180 this->CTest
->EndXML(os
);
1183 //----------------------------------------------------------------------------
1184 void cmCTestTestHandler::WriteTestResultHeader(std::ostream
& os
,
1185 cmCTestTestResult
* result
)
1187 os
<< "\t<Test Status=\"";
1188 if ( result
->Status
== cmCTestTestHandler::COMPLETED
)
1192 else if ( result
->Status
== cmCTestTestHandler::NOT_RUN
)
1200 std::string testPath
= result
->Path
+ "/" + result
->Name
;
1202 << "\t\t<Name>" << cmXMLSafe(result
->Name
) << "</Name>\n"
1203 << "\t\t<Path>" << cmXMLSafe(
1204 this->CTest
->GetShortPathToFile(result
->Path
.c_str())) << "</Path>\n"
1205 << "\t\t<FullName>" << cmXMLSafe(
1206 this->CTest
->GetShortPathToFile(testPath
.c_str())) << "</FullName>\n"
1207 << "\t\t<FullCommandLine>"
1208 << cmXMLSafe(result
->FullCommandLine
)
1209 << "</FullCommandLine>\n";
1212 //----------------------------------------------------------------------------
1213 void cmCTestTestHandler::WriteTestResultFooter(std::ostream
& os
,
1214 cmCTestTestResult
* result
)
1216 if(!result
->Properties
->Labels
.empty())
1218 os
<< "\t\t<Labels>\n";
1219 std::vector
<std::string
> const& labels
= result
->Properties
->Labels
;
1220 for(std::vector
<std::string
>::const_iterator li
= labels
.begin();
1221 li
!= labels
.end(); ++li
)
1223 os
<< "\t\t\t<Label>" << cmXMLSafe(*li
) << "</Label>\n";
1225 os
<< "\t\t</Labels>\n";
1229 << "\t</Test>" << std::endl
;
1232 //----------------------------------------------------------------------
1233 int cmCTestTestHandler::ExecuteCommands(std::vector
<cmStdString
>& vec
)
1235 std::vector
<cmStdString
>::iterator it
;
1236 for ( it
= vec
.begin(); it
!= vec
.end(); ++it
)
1239 cmCTestLog(this->CTest
, HANDLER_VERBOSE_OUTPUT
, "Run command: " << *it
1241 if ( !cmSystemTools::RunSingleCommand(it
->c_str(), 0, &retVal
, 0, true
1242 /*this->Verbose*/) || retVal
!= 0 )
1244 cmCTestLog(this->CTest
, ERROR_MESSAGE
, "Problem running command: "
1245 << *it
<< std::endl
);
1253 //----------------------------------------------------------------------
1254 // Find the appropriate executable to run for a test
1255 std::string
cmCTestTestHandler::FindTheExecutable(const char *exe
)
1257 std::string resConfig
;
1258 std::vector
<std::string
> extraPaths
;
1259 std::vector
<std::string
> failedPaths
;
1260 return cmCTestTestHandler::FindExecutable(this->CTest
,
1266 // add additional configurations to the search path
1267 void cmCTestTestHandler
1268 ::AddConfigurations(cmCTest
*ctest
,
1269 std::vector
<std::string
> &attempted
,
1270 std::vector
<std::string
> &attemptedConfigs
,
1271 std::string filepath
,
1272 std::string
&filename
)
1274 std::string tempPath
;
1276 if (filepath
.size() &&
1277 filepath
[filepath
.size()-1] != '/')
1281 tempPath
= filepath
+ filename
;
1282 attempted
.push_back(tempPath
);
1283 attemptedConfigs
.push_back("");
1285 if(ctest
->GetConfigType().size())
1287 tempPath
= filepath
;
1288 tempPath
+= ctest
->GetConfigType();
1290 tempPath
+= filename
;
1291 attempted
.push_back(tempPath
);
1292 attemptedConfigs
.push_back(ctest
->GetConfigType());
1293 // If the file is an OSX bundle then the configtyp
1294 // will be at the start of the path
1295 tempPath
= ctest
->GetConfigType();
1297 tempPath
+= filepath
;
1298 tempPath
+= filename
;
1299 attempted
.push_back(tempPath
);
1300 attemptedConfigs
.push_back(ctest
->GetConfigType());
1304 // no config specified to try some options
1305 tempPath
= filepath
;
1306 tempPath
+= "Release/";
1307 tempPath
+= filename
;
1308 attempted
.push_back(tempPath
);
1309 attemptedConfigs
.push_back("Release");
1310 tempPath
= filepath
;
1311 tempPath
+= "Debug/";
1312 tempPath
+= filename
;
1313 attempted
.push_back(tempPath
);
1314 attemptedConfigs
.push_back("Debug");
1315 tempPath
= filepath
;
1316 tempPath
+= "MinSizeRel/";
1317 tempPath
+= filename
;
1318 attempted
.push_back(tempPath
);
1319 attemptedConfigs
.push_back("MinSizeRel");
1320 tempPath
= filepath
;
1321 tempPath
+= "RelWithDebInfo/";
1322 tempPath
+= filename
;
1323 attempted
.push_back(tempPath
);
1324 attemptedConfigs
.push_back("RelWithDebInfo");
1325 tempPath
= filepath
;
1326 tempPath
+= "Deployment/";
1327 tempPath
+= filename
;
1328 attempted
.push_back(tempPath
);
1329 attemptedConfigs
.push_back("Deployment");
1330 tempPath
= filepath
;
1331 tempPath
+= "Development/";
1332 tempPath
+= filename
;
1333 attempted
.push_back(tempPath
);
1334 attemptedConfigs
.push_back("Deployment");
1339 //----------------------------------------------------------------------
1340 // Find the appropriate executable to run for a test
1341 std::string cmCTestTestHandler
1342 ::FindExecutable(cmCTest
*ctest
,
1343 const char *testCommand
,
1344 std::string
&resultingConfig
,
1345 std::vector
<std::string
> &extraPaths
,
1346 std::vector
<std::string
> &failed
)
1348 // now run the compiled test if we can find it
1349 std::vector
<std::string
> attempted
;
1350 std::vector
<std::string
> attemptedConfigs
;
1351 std::string tempPath
;
1352 std::string filepath
=
1353 cmSystemTools::GetFilenamePath(testCommand
);
1354 std::string filename
=
1355 cmSystemTools::GetFilenameName(testCommand
);
1357 cmCTestTestHandler::AddConfigurations(ctest
, attempted
,
1361 // even if a fullpath was specified also try it relative to the current
1363 if (filepath
.size() && filepath
[0] == '/')
1365 std::string localfilepath
= filepath
.substr(1,filepath
.size()-1);
1366 cmCTestTestHandler::AddConfigurations(ctest
, attempted
,
1368 localfilepath
,filename
);
1372 // if extraPaths are provided and we were not passed a full path, try them,
1373 // try any extra paths
1374 if (filepath
.size() == 0)
1376 for (unsigned int i
= 0; i
< extraPaths
.size(); ++i
)
1378 std::string filepathExtra
=
1379 cmSystemTools::GetFilenamePath(extraPaths
[i
]);
1380 std::string filenameExtra
=
1381 cmSystemTools::GetFilenameName(extraPaths
[i
]);
1382 cmCTestTestHandler::AddConfigurations(ctest
,attempted
,
1389 // store the final location in fullPath
1390 std::string fullPath
;
1392 // now look in the paths we specified above
1393 for(unsigned int ai
=0;
1394 ai
< attempted
.size() && fullPath
.size() == 0; ++ai
)
1396 // first check without exe extension
1397 if(cmSystemTools::FileExists(attempted
[ai
].c_str())
1398 && !cmSystemTools::FileIsDirectory(attempted
[ai
].c_str()))
1400 fullPath
= cmSystemTools::CollapseFullPath(attempted
[ai
].c_str());
1401 resultingConfig
= attemptedConfigs
[ai
];
1403 // then try with the exe extension
1406 failed
.push_back(attempted
[ai
].c_str());
1407 tempPath
= attempted
[ai
];
1408 tempPath
+= cmSystemTools::GetExecutableExtension();
1409 if(cmSystemTools::FileExists(tempPath
.c_str())
1410 && !cmSystemTools::FileIsDirectory(tempPath
.c_str()))
1412 fullPath
= cmSystemTools::CollapseFullPath(tempPath
.c_str());
1413 resultingConfig
= attemptedConfigs
[ai
];
1417 failed
.push_back(tempPath
.c_str());
1422 // if everything else failed, check the users path, but only if a full path
1424 if (fullPath
.size() == 0 && filepath
.size() == 0)
1426 std::string path
= cmSystemTools::FindProgram(filename
.c_str());
1429 resultingConfig
= "";
1433 if(fullPath
.size() == 0)
1435 cmCTestLog(ctest
, HANDLER_OUTPUT
,
1436 "Could not find executable " << testCommand
<< "\n"
1437 << "Looked in the following places:\n");
1438 for(std::vector
<std::string
>::iterator i
= failed
.begin();
1439 i
!= failed
.end(); ++i
)
1441 cmCTestLog(ctest
, HANDLER_OUTPUT
,
1442 i
->c_str() << "\n");
1450 //----------------------------------------------------------------------
1451 void cmCTestTestHandler::GetListOfTests()
1453 if ( !this->IncludeLabelRegExp
.empty() )
1455 this->IncludeLabelRegularExpression
.
1456 compile(this->IncludeLabelRegExp
.c_str());
1458 if ( !this->IncludeLabelRegExp
.empty() )
1460 this->ExcludeLabelRegularExpression
.
1461 compile(this->ExcludeLabelRegExp
.c_str());
1463 if ( !this->IncludeRegExp
.empty() )
1465 this->IncludeTestsRegularExpression
.compile(this->IncludeRegExp
.c_str());
1467 if ( !this->ExcludeRegExp
.empty() )
1469 this->ExcludeTestsRegularExpression
.compile(this->ExcludeRegExp
.c_str());
1471 cmCTestLog(this->CTest
, HANDLER_VERBOSE_OUTPUT
,
1472 "Constructing a list of tests" << std::endl
);
1474 cmGlobalGenerator gg
;
1475 gg
.SetCMakeInstance(&cm
);
1476 std::auto_ptr
<cmLocalGenerator
> lg(gg
.CreateLocalGenerator());
1477 cmMakefile
*mf
= lg
->GetMakefile();
1478 mf
->AddDefinition("CTEST_CONFIGURATION_TYPE",
1479 this->CTest
->GetConfigType().c_str());
1481 // Add handler for ADD_TEST
1482 cmCTestAddTestCommand
* newCom1
= new cmCTestAddTestCommand
;
1483 newCom1
->TestHandler
= this;
1484 cm
.AddCommand(newCom1
);
1486 // Add handler for SUBDIRS
1487 cmCTestSubdirCommand
* newCom2
=
1488 new cmCTestSubdirCommand
;
1489 newCom2
->TestHandler
= this;
1490 cm
.AddCommand(newCom2
);
1492 // Add handler for ADD_SUBDIRECTORY
1493 cmCTestAddSubdirectoryCommand
* newCom3
=
1494 new cmCTestAddSubdirectoryCommand
;
1495 newCom3
->TestHandler
= this;
1496 cm
.AddCommand(newCom3
);
1498 // Add handler for SET_SOURCE_FILES_PROPERTIES
1499 cmCTestSetTestsPropertiesCommand
* newCom4
1500 = new cmCTestSetTestsPropertiesCommand
;
1501 newCom4
->TestHandler
= this;
1502 cm
.AddCommand(newCom4
);
1504 const char* testFilename
;
1505 if( cmSystemTools::FileExists("CTestTestfile.cmake") )
1507 // does the CTestTestfile.cmake exist ?
1508 testFilename
= "CTestTestfile.cmake";
1510 else if( cmSystemTools::FileExists("DartTestfile.txt") )
1512 // does the DartTestfile.txt exist ?
1513 testFilename
= "DartTestfile.txt";
1520 if ( !mf
->ReadListFile(0, testFilename
) )
1524 if ( cmSystemTools::GetErrorOccuredFlag() )
1528 cmCTestLog(this->CTest
, HANDLER_VERBOSE_OUTPUT
,
1529 "Done constructing a list of tests" << std::endl
);
1532 //----------------------------------------------------------------------
1533 void cmCTestTestHandler::UseIncludeRegExp()
1535 this->UseIncludeRegExpFlag
= true;
1538 //----------------------------------------------------------------------
1539 void cmCTestTestHandler::UseExcludeRegExp()
1541 this->UseExcludeRegExpFlag
= true;
1542 this->UseExcludeRegExpFirst
= this->UseIncludeRegExpFlag
? false : true;
1545 //----------------------------------------------------------------------
1546 const char* cmCTestTestHandler::GetTestStatus(int status
)
1548 static const char statuses
[][100] = {
1561 if ( status
< cmCTestTestHandler::NOT_RUN
||
1562 status
> cmCTestTestHandler::COMPLETED
)
1566 return statuses
[status
];
1569 //----------------------------------------------------------------------
1570 void cmCTestTestHandler::ExpandTestsToRunInformation(size_t numTests
)
1572 if (this->TestsToRunString
.empty())
1580 std::string::size_type pos
= 0;
1581 std::string::size_type pos2
;
1583 if(GetNextNumber(this->TestsToRunString
, start
, pos
, pos2
))
1586 if(GetNextNumber(this->TestsToRunString
, end
, pos
, pos2
))
1589 if(GetNextRealNumber(this->TestsToRunString
, stride
, pos
, pos2
))
1592 // now read specific numbers
1593 while(GetNextNumber(this->TestsToRunString
, val
, pos
, pos2
))
1595 this->TestsToRun
.push_back(val
);
1597 this->TestsToRun
.push_back(val
);
1602 // if start is not specified then we assume we start at 1
1608 // if end isnot specified then we assume we end with the last test
1611 end
= static_cast<int>(numTests
);
1614 // if the stride wasn't specified then it defaults to 1
1620 // if we have a range then add it
1621 if(end
!= -1 && start
!= -1 && stride
> 0)
1624 while (i
*stride
+ start
<= end
)
1626 this->TestsToRun
.push_back(static_cast<int>(i
*stride
+start
));
1632 std::sort(this->TestsToRun
.begin(), this->TestsToRun
.end(),
1634 // remove duplicates
1635 std::vector
<int>::iterator new_end
=
1636 std::unique(this->TestsToRun
.begin(), this->TestsToRun
.end());
1637 this->TestsToRun
.erase(new_end
, this->TestsToRun
.end());
1640 //----------------------------------------------------------------------
1641 // Just for convenience
1642 #define SPACE_REGEX "[ \t\r\n]"
1643 //----------------------------------------------------------------------
1644 std::string
cmCTestTestHandler::GenerateRegressionImages(
1645 const std::string
& xml
)
1647 cmsys::RegularExpression
twoattributes(
1649 SPACE_REGEX
"*(name|type|encoding|compression)=\"([^\"]*)\""
1650 SPACE_REGEX
"*(name|type|encoding|compression)=\"([^\"]*)\""
1651 SPACE_REGEX
"*>([^<]*)</DartMeasurement>");
1652 cmsys::RegularExpression
threeattributes(
1654 SPACE_REGEX
"*(name|type|encoding|compression)=\"([^\"]*)\""
1655 SPACE_REGEX
"*(name|type|encoding|compression)=\"([^\"]*)\""
1656 SPACE_REGEX
"*(name|type|encoding|compression)=\"([^\"]*)\""
1657 SPACE_REGEX
"*>([^<]*)</DartMeasurement>");
1658 cmsys::RegularExpression
fourattributes(
1660 SPACE_REGEX
"*(name|type|encoding|compression)=\"([^\"]*)\""
1661 SPACE_REGEX
"*(name|type|encoding|compression)=\"([^\"]*)\""
1662 SPACE_REGEX
"*(name|type|encoding|compression)=\"([^\"]*)\""
1663 SPACE_REGEX
"*(name|type|encoding|compression)=\"([^\"]*)\""
1664 SPACE_REGEX
"*>([^<]*)</DartMeasurement>");
1665 cmsys::RegularExpression
cdatastart(
1667 SPACE_REGEX
"*(name|type|encoding|compression)=\"([^\"]*)\""
1668 SPACE_REGEX
"*(name|type|encoding|compression)=\"([^\"]*)\""
1670 SPACE_REGEX
"*<!\\[CDATA\\[");
1671 cmsys::RegularExpression
cdataend(
1673 SPACE_REGEX
"*</DartMeasurement>");
1674 cmsys::RegularExpression
measurementfile(
1675 "<DartMeasurementFile"
1676 SPACE_REGEX
"*(name|type|encoding|compression)=\"([^\"]*)\""
1677 SPACE_REGEX
"*(name|type|encoding|compression)=\"([^\"]*)\""
1678 SPACE_REGEX
"*>([^<]*)</DartMeasurementFile>");
1680 cmOStringStream ostr
;
1682 std::string cxml
= xml
;
1685 if ( twoattributes
.find(cxml
) )
1688 << "\t\t\t<NamedMeasurement"
1689 << " " << twoattributes
.match(1) << "=\""
1690 << twoattributes
.match(2) << "\""
1691 << " " << twoattributes
.match(3) << "=\""
1692 << twoattributes
.match(4) << "\""
1693 << "><Value>" << twoattributes
.match(5)
1694 << "</Value></NamedMeasurement>"
1696 cxml
.erase(twoattributes
.start(),
1697 twoattributes
.end() - twoattributes
.start());
1699 else if ( threeattributes
.find(cxml
) )
1702 << "\t\t\t<NamedMeasurement"
1703 << " " << threeattributes
.match(1) << "=\""
1704 << threeattributes
.match(2) << "\""
1705 << " " << threeattributes
.match(3) << "=\""
1706 << threeattributes
.match(4) << "\""
1707 << " " << threeattributes
.match(5) << "=\""
1708 << threeattributes
.match(6) << "\""
1709 << "><Value>" << threeattributes
.match(7)
1710 << "</Value></NamedMeasurement>"
1712 cxml
.erase(threeattributes
.start(),
1713 threeattributes
.end() - threeattributes
.start());
1715 else if ( fourattributes
.find(cxml
) )
1718 << "\t\t\t<NamedMeasurement"
1719 << " " << fourattributes
.match(1) << "=\""
1720 << fourattributes
.match(2) << "\""
1721 << " " << fourattributes
.match(3) << "=\""
1722 << fourattributes
.match(4) << "\""
1723 << " " << fourattributes
.match(5) << "=\""
1724 << fourattributes
.match(6) << "\""
1725 << " " << fourattributes
.match(7) << "=\""
1726 << fourattributes
.match(8) << "\""
1727 << "><Value>" << fourattributes
.match(9)
1728 << "</Value></NamedMeasurement>"
1730 cxml
.erase(fourattributes
.start(),
1731 fourattributes
.end() - fourattributes
.start());
1733 else if ( cdatastart
.find(cxml
) && cdataend
.find(cxml
) )
1736 << "\t\t\t<NamedMeasurement"
1737 << " " << cdatastart
.match(1) << "=\""
1738 << cdatastart
.match(2) << "\""
1739 << " " << cdatastart
.match(3) << "=\""
1740 << cdatastart
.match(4) << "\""
1741 << "><Value><![CDATA["
1742 << cxml
.substr(cdatastart
.end(), cdataend
.start() - cdatastart
.end())
1743 << "]]></Value></NamedMeasurement>"
1745 cxml
.erase(cdatastart
.start(),
1746 cdataend
.end() - cdatastart
.start());
1748 else if ( measurementfile
.find(cxml
) )
1750 const std::string
& filename
=
1751 cmCTest::CleanString(measurementfile
.match(5));
1752 if ( cmSystemTools::FileExists(filename
.c_str()) )
1754 long len
= cmSystemTools::FileLength(filename
.c_str());
1757 std::string k1
= measurementfile
.match(1);
1758 std::string v1
= measurementfile
.match(2);
1759 std::string k2
= measurementfile
.match(3);
1760 std::string v2
= measurementfile
.match(4);
1761 if ( cmSystemTools::LowerCase(k1
) == "type" )
1765 if ( cmSystemTools::LowerCase(k2
) == "type" )
1771 << "\t\t\t<NamedMeasurement"
1772 << " " << k1
<< "=\"" << v1
<< "\""
1773 << " " << k2
<< "=\"" << v2
<< "\""
1774 << " encoding=\"none\""
1775 << "><Value>Image " << filename
.c_str()
1776 << " is empty</Value></NamedMeasurement>";
1780 std::ifstream
ifs(filename
.c_str(), std::ios::in
1785 unsigned char *file_buffer
= new unsigned char [ len
+ 1 ];
1786 ifs
.read(reinterpret_cast<char*>(file_buffer
), len
);
1787 unsigned char *encoded_buffer
1788 = new unsigned char [ static_cast<int>(len
* 1.5 + 5) ];
1791 = cmsysBase64_Encode(file_buffer
, len
, encoded_buffer
, 1);
1795 << "\t\t\t<NamedMeasurement"
1796 << " " << measurementfile
.match(1) << "=\""
1797 << measurementfile
.match(2) << "\""
1798 << " " << measurementfile
.match(3) << "=\""
1799 << measurementfile
.match(4) << "\""
1800 << " encoding=\"base64\""
1801 << ">" << std::endl
<< "\t\t\t\t<Value>";
1802 for ( cc
= 0; cc
< rlen
; cc
++ )
1804 ostr
<< encoded_buffer
[cc
];
1805 if ( cc
% 60 == 0 && cc
)
1811 << "</Value>" << std::endl
<< "\t\t\t</NamedMeasurement>"
1813 delete [] file_buffer
;
1814 delete [] encoded_buffer
;
1820 if ( measurementfile
.match(1) == "name" )
1825 << "\t\t\t<NamedMeasurement"
1826 << " name=\"" << measurementfile
.match(idx
) << "\""
1827 << " text=\"text/string\""
1828 << "><Value>File " << filename
.c_str()
1829 << " not found</Value></NamedMeasurement>"
1831 cmCTestLog(this->CTest
, HANDLER_OUTPUT
, "File \"" << filename
.c_str()
1832 << "\" not found." << std::endl
);
1834 cxml
.erase(measurementfile
.start(),
1835 measurementfile
.end() - measurementfile
.start());
1845 //----------------------------------------------------------------------
1846 void cmCTestTestHandler::SetIncludeRegExp(const char *arg
)
1848 this->IncludeRegExp
= arg
;
1851 //----------------------------------------------------------------------
1852 void cmCTestTestHandler::SetExcludeRegExp(const char *arg
)
1854 this->ExcludeRegExp
= arg
;
1857 //----------------------------------------------------------------------
1858 void cmCTestTestHandler::SetTestsToRunInformation(const char* in
)
1864 this->TestsToRunString
= in
;
1865 // if the argument is a file, then read it and use the contents as the
1867 if(cmSystemTools::FileExists(in
))
1869 std::ifstream
fin(in
);
1870 unsigned long filelen
= cmSystemTools::FileLength(in
);
1871 char* buff
= new char[filelen
+1];
1872 fin
.getline(buff
, filelen
);
1873 buff
[fin
.gcount()] = 0;
1874 this->TestsToRunString
= buff
;
1878 //----------------------------------------------------------------------
1879 bool cmCTestTestHandler::CleanTestOutput(std::string
& output
,
1880 size_t remove_threshold
)
1882 if ( remove_threshold
== 0 )
1886 if ( output
.find("CTEST_FULL_OUTPUT") != output
.npos
)
1890 cmOStringStream ostr
;
1891 std::string::size_type cc
;
1892 std::string::size_type skipsize
= 0;
1895 for ( cc
= 0; cc
< output
.size(); cc
++ )
1897 int ch
= output
[cc
];
1898 if ( ch
< 0 || ch
> 255 )
1910 if ( skipsize
< remove_threshold
)
1912 ostr
<< static_cast<char>(ch
);
1916 if ( notskip
&& skipsize
>= remove_threshold
)
1923 ostr
<< static_cast<char>(ch
);
1932 ostr
<< "..." << std::endl
<< "The rest of the test output was removed "
1933 "since it exceeds the threshold of "
1934 << remove_threshold
<< " characters." << std::endl
;
1936 output
= ostr
.str();
1940 //----------------------------------------------------------------------
1941 bool cmCTestTestHandler::SetTestsProperties(
1942 const std::vector
<std::string
>& args
)
1944 std::vector
<std::string
>::const_iterator it
;
1945 std::vector
<cmStdString
> tests
;
1947 for ( it
= args
.begin(); it
!= args
.end(); ++ it
)
1949 if ( *it
== "PROPERTIES" )
1954 tests
.push_back(*it
);
1960 ++ it
; // skip PROPERTIES
1961 for ( ; it
!= args
.end(); ++ it
)
1963 std::string key
= *it
;
1965 if ( it
== args
.end() )
1969 std::string val
= *it
;
1970 std::vector
<cmStdString
>::const_iterator tit
;
1971 for ( tit
= tests
.begin(); tit
!= tests
.end(); ++ tit
)
1973 cmCTestTestHandler::ListOfTests::iterator rtit
;
1974 for ( rtit
= this->TestList
.begin();
1975 rtit
!= this->TestList
.end();
1978 if ( *tit
== rtit
->Name
)
1980 if ( key
== "WILL_FAIL" )
1982 rtit
->WillFail
= cmSystemTools::IsOn(val
.c_str());
1984 if ( key
== "TIMEOUT" )
1986 rtit
->Timeout
= atof(val
.c_str());
1988 if ( key
== "COST" )
1990 rtit
->Cost
= atof(val
.c_str());
1992 if ( key
== "RUN_SERIAL" )
1994 rtit
->RunSerial
= cmSystemTools::IsOn(val
.c_str());
1996 if ( key
== "FAIL_REGULAR_EXPRESSION" )
1998 std::vector
<std::string
> lval
;
1999 cmSystemTools::ExpandListArgument(val
.c_str(), lval
);
2000 std::vector
<std::string
>::iterator crit
;
2001 for ( crit
= lval
.begin(); crit
!= lval
.end(); ++ crit
)
2003 rtit
->ErrorRegularExpressions
.push_back(
2004 std::pair
<cmsys::RegularExpression
, std::string
>(
2005 cmsys::RegularExpression(crit
->c_str()),
2006 std::string(crit
->c_str())));
2009 if ( key
== "PROCESSORS" )
2011 rtit
->Processors
= atoi(val
.c_str());
2012 if(rtit
->Processors
< 1)
2014 rtit
->Processors
= 1;
2017 if ( key
== "DEPENDS" )
2019 std::vector
<std::string
> lval
;
2020 cmSystemTools::ExpandListArgument(val
.c_str(), lval
);
2021 std::vector
<std::string
>::iterator crit
;
2022 for ( crit
= lval
.begin(); crit
!= lval
.end(); ++ crit
)
2024 rtit
->Depends
.push_back(*crit
);
2027 if ( key
== "ENVIRONMENT" )
2029 std::vector
<std::string
> lval
;
2030 cmSystemTools::ExpandListArgument(val
.c_str(), lval
);
2031 std::vector
<std::string
>::iterator crit
;
2032 for ( crit
= lval
.begin(); crit
!= lval
.end(); ++ crit
)
2034 rtit
->Environment
.push_back(*crit
);
2037 if ( key
== "LABELS" )
2039 std::vector
<std::string
> lval
;
2040 cmSystemTools::ExpandListArgument(val
.c_str(), lval
);
2041 std::vector
<std::string
>::iterator crit
;
2042 for ( crit
= lval
.begin(); crit
!= lval
.end(); ++ crit
)
2044 rtit
->Labels
.push_back(*crit
);
2048 if ( key
== "MEASUREMENT" )
2050 size_t pos
= val
.find_first_of("=");
2051 if ( pos
!= val
.npos
)
2053 std::string mKey
= val
.substr(0, pos
);
2054 const char* mVal
= val
.c_str() + pos
+ 1;
2055 rtit
->Measurements
[mKey
] = mVal
;
2059 rtit
->Measurements
[val
] = "1";
2062 if ( key
== "PASS_REGULAR_EXPRESSION" )
2064 std::vector
<std::string
> lval
;
2065 cmSystemTools::ExpandListArgument(val
.c_str(), lval
);
2066 std::vector
<std::string
>::iterator crit
;
2067 for ( crit
= lval
.begin(); crit
!= lval
.end(); ++ crit
)
2069 rtit
->RequiredRegularExpressions
.push_back(
2070 std::pair
<cmsys::RegularExpression
, std::string
>(
2071 cmsys::RegularExpression(crit
->c_str()),
2072 std::string(crit
->c_str())));
2082 //----------------------------------------------------------------------
2083 bool cmCTestTestHandler::AddTest(const std::vector
<std::string
>& args
)
2085 const std::string
& testname
= args
[0];
2086 cmCTestLog(this->CTest
, DEBUG
, "Add test: " << args
[0] << std::endl
);
2087 if (this->UseExcludeRegExpFlag
&&
2088 this->UseExcludeRegExpFirst
&&
2089 this->ExcludeTestsRegularExpression
.find(testname
.c_str()))
2093 if ( this->MemCheck
)
2095 std::vector
<cmStdString
>::iterator it
;
2097 for ( it
= this->CustomTestsIgnore
.begin();
2098 it
!= this->CustomTestsIgnore
.end(); ++ it
)
2100 if ( *it
== testname
)
2108 cmCTestLog(this->CTest
, HANDLER_VERBOSE_OUTPUT
, "Ignore memcheck: "
2109 << *it
<< std::endl
);
2115 std::vector
<cmStdString
>::iterator it
;
2117 for ( it
= this->CustomTestsIgnore
.begin();
2118 it
!= this->CustomTestsIgnore
.end(); ++ it
)
2120 if ( *it
== testname
)
2128 cmCTestLog(this->CTest
, HANDLER_VERBOSE_OUTPUT
, "Ignore test: "
2129 << *it
<< std::endl
);
2134 cmCTestTestProperties test
;
2135 test
.Name
= testname
;
2137 test
.Directory
= cmSystemTools::GetCurrentWorkingDirectory();
2138 cmCTestLog(this->CTest
, DEBUG
, "Set test directory: "
2139 << test
.Directory
<< std::endl
);
2141 test
.IsInBasedOnREOptions
= true;
2142 test
.WillFail
= false;
2143 test
.RunSerial
= false;
2146 test
.Processors
= 1;
2147 if (this->UseIncludeRegExpFlag
&&
2148 !this->IncludeTestsRegularExpression
.find(testname
.c_str()))
2150 test
.IsInBasedOnREOptions
= false;
2152 else if (this->UseExcludeRegExpFlag
&&
2153 !this->UseExcludeRegExpFirst
&&
2154 this->ExcludeTestsRegularExpression
.find(testname
.c_str()))
2156 test
.IsInBasedOnREOptions
= false;
2158 this->TestList
.push_back(test
);