1 /*=========================================================================
3 Program: CMake - Cross-Platform Makefile Generator
4 Module: $RCSfile: cmCTestTestHandler.cxx,v $
6 Date: $Date: 2008/01/31 21:33:07 $
7 Version: $Revision: 1.68 $
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"
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"
36 #include <memory> // auto_ptr
38 //----------------------------------------------------------------------
39 class cmCTestSubdirCommand
: public cmCommand
43 * This is a virtual constructor for the command.
45 virtual cmCommand
* Clone()
47 cmCTestSubdirCommand
* c
= new cmCTestSubdirCommand
;
48 c
->TestHandler
= this->TestHandler
;
53 * This is called when the command is first encountered in
54 * the CMakeLists.txt file.
56 virtual bool InitialPass(std::vector
<std::string
> const& args
,
60 * The name of the command as specified in CMakeList.txt.
62 virtual const char* GetName() { return "subdirs";}
65 virtual const char* GetTerseDocumentation() { return ""; }
66 virtual const char* GetFullDocumentation() { return ""; }
68 cmTypeMacro(cmCTestSubdirCommand
, cmCommand
);
70 cmCTestTestHandler
* TestHandler
;
73 //----------------------------------------------------------------------
74 bool cmCTestSubdirCommand
75 ::InitialPass(std::vector
<std::string
> const& args
, cmExecutionStatus
&)
79 this->SetError("called with incorrect number of arguments");
82 std::vector
<std::string
>::const_iterator it
;
83 std::string cwd
= cmSystemTools::GetCurrentWorkingDirectory();
84 for ( it
= args
.begin(); it
!= args
.end(); ++ it
)
86 cmSystemTools::ChangeDirectory(cwd
.c_str());
87 std::string fname
= cwd
;
91 if ( !cmSystemTools::FileExists(fname
.c_str()) )
93 // No subdirectory? So what...
96 cmSystemTools::ChangeDirectory(fname
.c_str());
97 const char* testFilename
;
98 if( cmSystemTools::FileExists("CTestTestfile.cmake") )
100 // does the CTestTestfile.cmake exist ?
101 testFilename
= "CTestTestfile.cmake";
103 else if( cmSystemTools::FileExists("DartTestfile.txt") )
105 // does the DartTestfile.txt exist ?
106 testFilename
= "DartTestfile.txt";
110 // No CTestTestfile? Who cares...
111 cmSystemTools::ChangeDirectory(cwd
.c_str());
115 fname
+= testFilename
;
117 this->Makefile
->ReadListFile(this->Makefile
->GetCurrentListFile(),
119 cmSystemTools::ChangeDirectory(cwd
.c_str());
122 std::string m
= "Could not find include file: ";
124 this->SetError(m
.c_str());
131 //----------------------------------------------------------------------
132 class cmCTestAddSubdirectoryCommand
: public cmCommand
136 * This is a virtual constructor for the command.
138 virtual cmCommand
* Clone()
140 cmCTestAddSubdirectoryCommand
* c
= new cmCTestAddSubdirectoryCommand
;
141 c
->TestHandler
= this->TestHandler
;
146 * This is called when the command is first encountered in
147 * the CMakeLists.txt file.
149 virtual bool InitialPass(std::vector
<std::string
> const& args
,
150 cmExecutionStatus
&);
153 * The name of the command as specified in CMakeList.txt.
155 virtual const char* GetName() { return "add_subdirectory";}
158 virtual const char* GetTerseDocumentation() { return ""; }
159 virtual const char* GetFullDocumentation() { return ""; }
161 cmTypeMacro(cmCTestAddSubdirectoryCommand
, cmCommand
);
163 cmCTestTestHandler
* TestHandler
;
166 //----------------------------------------------------------------------
167 bool cmCTestAddSubdirectoryCommand
168 ::InitialPass(std::vector
<std::string
> const& args
, cmExecutionStatus
&)
172 this->SetError("called with incorrect number of arguments");
176 std::string cwd
= cmSystemTools::GetCurrentWorkingDirectory();
177 cmSystemTools::ChangeDirectory(cwd
.c_str());
178 std::string fname
= cwd
;
182 if ( !cmSystemTools::FileExists(fname
.c_str()) )
184 // No subdirectory? So what...
187 cmSystemTools::ChangeDirectory(fname
.c_str());
188 const char* testFilename
;
189 if( cmSystemTools::FileExists("CTestTestfile.cmake") )
191 // does the CTestTestfile.cmake exist ?
192 testFilename
= "CTestTestfile.cmake";
194 else if( cmSystemTools::FileExists("DartTestfile.txt") )
196 // does the DartTestfile.txt exist ?
197 testFilename
= "DartTestfile.txt";
201 // No CTestTestfile? Who cares...
202 cmSystemTools::ChangeDirectory(cwd
.c_str());
206 fname
+= testFilename
;
208 this->Makefile
->ReadListFile(this->Makefile
->GetCurrentListFile(),
210 cmSystemTools::ChangeDirectory(cwd
.c_str());
213 std::string m
= "Could not find include file: ";
215 this->SetError(m
.c_str());
221 //----------------------------------------------------------------------
222 class cmCTestAddTestCommand
: public cmCommand
226 * This is a virtual constructor for the command.
228 virtual cmCommand
* Clone()
230 cmCTestAddTestCommand
* c
= new cmCTestAddTestCommand
;
231 c
->TestHandler
= this->TestHandler
;
236 * This is called when the command is first encountered in
237 * the CMakeLists.txt file.
239 virtual bool InitialPass(std::vector
<std::string
> const&,
240 cmExecutionStatus
&);
243 * The name of the command as specified in CMakeList.txt.
245 virtual const char* GetName() { return "ADD_TEST";}
248 virtual const char* GetTerseDocumentation() { return ""; }
249 virtual const char* GetFullDocumentation() { return ""; }
251 cmTypeMacro(cmCTestAddTestCommand
, cmCommand
);
253 cmCTestTestHandler
* TestHandler
;
256 //----------------------------------------------------------------------
257 bool cmCTestAddTestCommand
258 ::InitialPass(std::vector
<std::string
> const& args
, cmExecutionStatus
&)
260 if ( args
.size() < 2 )
262 this->SetError("called with incorrect number of arguments");
265 return this->TestHandler
->AddTest(args
);
268 //----------------------------------------------------------------------
269 class cmCTestSetTestsPropertiesCommand
: public cmCommand
273 * This is a virtual constructor for the command.
275 virtual cmCommand
* Clone()
277 cmCTestSetTestsPropertiesCommand
* c
278 = new cmCTestSetTestsPropertiesCommand
;
279 c
->TestHandler
= this->TestHandler
;
284 * This is called when the command is first encountered in
285 * the CMakeLists.txt file.
287 virtual bool InitialPass(std::vector
<std::string
> const&,
288 cmExecutionStatus
&);
291 * The name of the command as specified in CMakeList.txt.
293 virtual const char* GetName() { return "SET_TESTS_PROPERTIES";}
296 virtual const char* GetTerseDocumentation() { return ""; }
297 virtual const char* GetFullDocumentation() { return ""; }
299 cmTypeMacro(cmCTestSetTestsPropertiesCommand
, cmCommand
);
301 cmCTestTestHandler
* TestHandler
;
304 //----------------------------------------------------------------------
305 bool cmCTestSetTestsPropertiesCommand
306 ::InitialPass(std::vector
<std::string
> const& args
, cmExecutionStatus
&)
308 return this->TestHandler
->SetTestsProperties(args
);
311 //----------------------------------------------------------------------
312 // get the next number in a string with numbers separated by ,
313 // pos is the start of the search and pos2 is the end of the search
314 // pos becomes pos2 after a call to GetNextNumber.
315 // -1 is returned at the end of the list.
316 inline int GetNextNumber(std::string
const& in
,
318 std::string::size_type
& pos
,
319 std::string::size_type
& pos2
)
321 pos2
= in
.find(',', pos
);
330 val
= atoi(in
.substr(pos
, pos2
-pos
).c_str());
337 if(in
.size()-pos
== 0)
343 val
= atoi(in
.substr(pos
, in
.size()-pos
).c_str());
349 //----------------------------------------------------------------------
350 // get the next number in a string with numbers separated by ,
351 // pos is the start of the search and pos2 is the end of the search
352 // pos becomes pos2 after a call to GetNextNumber.
353 // -1 is returned at the end of the list.
354 inline int GetNextRealNumber(std::string
const& in
,
356 std::string::size_type
& pos
,
357 std::string::size_type
& pos2
)
359 pos2
= in
.find(',', pos
);
368 val
= atof(in
.substr(pos
, pos2
-pos
).c_str());
375 if(in
.size()-pos
== 0)
381 val
= atof(in
.substr(pos
, in
.size()-pos
).c_str());
388 //----------------------------------------------------------------------
389 cmCTestTestHandler::cmCTestTestHandler()
391 this->UseUnion
= false;
393 this->UseIncludeRegExpFlag
= false;
394 this->UseExcludeRegExpFlag
= false;
395 this->UseExcludeRegExpFirst
= false;
397 this->CustomMaximumPassedTestOutputSize
= 1 * 1024;
398 this->CustomMaximumFailedTestOutputSize
= 300 * 1024;
400 this->MemCheck
= false;
404 this->DartStuff
.compile("(<DartMeasurement.*/DartMeasurement[a-zA-Z]*>)");
407 //----------------------------------------------------------------------
408 void cmCTestTestHandler::Initialize()
410 this->Superclass::Initialize();
412 this->ElapsedTestingTime
= -1;
414 this->TestResults
.clear();
416 this->CustomTestsIgnore
.clear();
417 this->StartTest
= "";
420 this->CustomPreTest
.clear();
421 this->CustomPostTest
.clear();
422 this->CustomMaximumPassedTestOutputSize
= 1 * 1024;
423 this->CustomMaximumFailedTestOutputSize
= 300 * 1024;
425 this->TestsToRun
.clear();
427 this->UseIncludeRegExpFlag
= false;
428 this->UseExcludeRegExpFlag
= false;
429 this->UseExcludeRegExpFirst
= false;
430 this->IncludeRegExp
= "";
431 this->ExcludeRegExp
= "";
433 TestsToRunString
= "";
434 this->UseUnion
= false;
435 this->TestList
.clear();
438 //----------------------------------------------------------------------
439 void cmCTestTestHandler::PopulateCustomVectors(cmMakefile
*mf
)
441 this->CTest
->PopulateCustomVector(mf
, "CTEST_CUSTOM_PRE_TEST",
442 this->CustomPreTest
);
443 this->CTest
->PopulateCustomVector(mf
, "CTEST_CUSTOM_POST_TEST",
444 this->CustomPostTest
);
445 this->CTest
->PopulateCustomVector(mf
,
446 "CTEST_CUSTOM_TESTS_IGNORE",
447 this->CustomTestsIgnore
);
448 this->CTest
->PopulateCustomInteger(mf
,
449 "CTEST_CUSTOM_MAXIMUM_PASSED_TEST_OUTPUT_SIZE",
450 this->CustomMaximumPassedTestOutputSize
);
451 this->CTest
->PopulateCustomInteger(mf
,
452 "CTEST_CUSTOM_MAXIMUM_FAILED_TEST_OUTPUT_SIZE",
453 this->CustomMaximumFailedTestOutputSize
);
456 //----------------------------------------------------------------------
457 int cmCTestTestHandler::PreProcessHandler()
459 if ( !this->ExecuteCommands(this->CustomPreTest
) )
461 cmCTestLog(this->CTest
, ERROR_MESSAGE
,
462 "Problem executing pre-test command(s)." << std::endl
);
468 //----------------------------------------------------------------------
469 int cmCTestTestHandler::PostProcessHandler()
471 if ( !this->ExecuteCommands(this->CustomPostTest
) )
473 cmCTestLog(this->CTest
, ERROR_MESSAGE
,
474 "Problem executing post-test command(s)." << std::endl
);
480 //----------------------------------------------------------------------
481 //clearly it would be nice if this were broken up into a few smaller
482 //functions and commented...
483 int cmCTestTestHandler::ProcessHandler()
485 // Update internal data structure from generic one
486 this->SetTestsToRunInformation(this->GetOption("TestsToRunInformation"));
487 this->SetUseUnion(cmSystemTools::IsOn(this->GetOption("UseUnion")));
489 val
= this->GetOption("IncludeRegularExpression");
492 this->UseIncludeRegExp();
493 this->SetIncludeRegExp(val
);
495 val
= this->GetOption("ExcludeRegularExpression");
498 this->UseExcludeRegExp();
499 this->SetExcludeRegExp(val
);
502 this->TestResults
.clear();
504 cmCTestLog(this->CTest
, HANDLER_OUTPUT
,
505 (this->MemCheck
? "Memory check" : "Test")
506 << " project " << cmSystemTools::GetCurrentWorkingDirectory()
508 if ( ! this->PreProcessHandler() )
513 cmGeneratedFileStream mLogFile
;
514 this->StartLogFile((this->MemCheck
? "DynamicAnalysis" : "Test"), mLogFile
);
515 this->LogFile
= &mLogFile
;
517 std::vector
<cmStdString
> passed
;
518 std::vector
<cmStdString
> failed
;
521 this->ProcessDirectory(passed
, failed
);
523 total
= int(passed
.size()) + int(failed
.size());
527 if ( !this->CTest
->GetShowOnly() )
529 cmCTestLog(this->CTest
, ERROR_MESSAGE
, "No tests were found!!!"
535 if (this->HandlerVerbose
&& passed
.size() &&
536 (this->UseIncludeRegExpFlag
|| this->UseExcludeRegExpFlag
))
538 cmCTestLog(this->CTest
, HANDLER_VERBOSE_OUTPUT
, std::endl
539 << "The following tests passed:" << std::endl
);
540 for(std::vector
<cmStdString
>::iterator j
= passed
.begin();
541 j
!= passed
.end(); ++j
)
543 cmCTestLog(this->CTest
, HANDLER_VERBOSE_OUTPUT
, "\t" << *j
548 float percent
= float(passed
.size()) * 100.0f
/ total
;
549 if ( failed
.size() > 0 && percent
> 99)
553 cmCTestLog(this->CTest
, HANDLER_OUTPUT
, std::endl
554 << static_cast<int>(percent
+ .5) << "% tests passed, "
555 << failed
.size() << " tests failed out of " << total
<< std::endl
);
556 //fprintf(stderr,"\n%.0f%% tests passed, %i tests failed out of %i\n",
557 // percent, int(failed.size()), total);
561 cmGeneratedFileStream ofs
;
563 cmCTestLog(this->CTest
, ERROR_MESSAGE
, std::endl
564 << "The following tests FAILED:" << std::endl
);
565 this->StartLogFile("TestsFailed", ofs
);
567 std::vector
<cmCTestTestHandler::cmCTestTestResult
>::iterator ftit
;
568 for(ftit
= this->TestResults
.begin();
569 ftit
!= this->TestResults
.end(); ++ftit
)
571 if ( ftit
->Status
!= cmCTestTestHandler::COMPLETED
)
573 ofs
<< ftit
->TestCount
<< ":" << ftit
->Name
<< std::endl
;
574 cmCTestLog(this->CTest
, HANDLER_OUTPUT
, "\t" << std::setw(3)
575 << ftit
->TestCount
<< " - " << ftit
->Name
.c_str() << " ("
576 << this->GetTestStatus(ftit
->Status
) << ")" << std::endl
);
583 if ( this->CTest
->GetProduceXML() )
585 cmGeneratedFileStream xmlfile
;
586 if( !this->StartResultingXML(
587 (this->MemCheck
? "DynamicAnalysis" : "Test"), xmlfile
) )
589 cmCTestLog(this->CTest
, ERROR_MESSAGE
, "Cannot create "
590 << (this->MemCheck
? "memory check" : "testing")
591 << " XML file" << std::endl
);
595 this->GenerateDartOutput(xmlfile
);
598 if ( ! this->PostProcessHandler() )
604 if ( !failed
.empty() )
613 //----------------------------------------------------------------------
614 void cmCTestTestHandler::ProcessOneTest(cmCTestTestProperties
*it
,
615 std::vector
<cmStdString
> &passed
,
616 std::vector
<cmStdString
> &failed
,
619 const std::string
& testname
= it
->Name
;
620 std::vector
<std::string
>& args
= it
->Args
;
621 cmCTestTestResult cres
;
622 cres
.Properties
= &*it
;
623 cres
.ExecutionTime
= 0;
624 cres
.ReturnValue
= -1;
625 cres
.Status
= cmCTestTestHandler::NOT_RUN
;
626 cres
.TestCount
= cnt
;
627 cres
.Name
= testname
;
628 cres
.Path
= it
->Directory
.c_str();
630 cmCTestLog(this->CTest
, HANDLER_OUTPUT
, std::setw(3) << cnt
<< "/");
631 cmCTestLog(this->CTest
, HANDLER_OUTPUT
, std::setw(3) << tmsize
<< " ");
632 if ( this->MemCheck
)
634 cmCTestLog(this->CTest
, HANDLER_OUTPUT
, "Memory Check");
638 cmCTestLog(this->CTest
, HANDLER_OUTPUT
, "Testing");
640 cmCTestLog(this->CTest
, HANDLER_OUTPUT
, " ");
641 std::string outname
= testname
;
642 outname
.resize(30, ' ');
643 *this->LogFile
<< cnt
<< "/" << tmsize
<< " Testing: " << testname
646 if ( this->CTest
->GetShowOnly() )
648 cmCTestLog(this->CTest
, HANDLER_OUTPUT
, outname
.c_str() << std::endl
);
652 cmCTestLog(this->CTest
, HANDLER_OUTPUT
, outname
.c_str());
655 cmCTestLog(this->CTest
, DEBUG
, "Testing " << args
[0].c_str() << " ... ");
656 // find the test executable
657 std::string actualCommand
= this->FindTheExecutable(args
[1].c_str());
658 std::string testCommand
659 = cmSystemTools::ConvertToOutputPath(actualCommand
.c_str());
661 // continue if we did not find the executable
662 if (testCommand
== "")
664 *this->LogFile
<< "Unable to find executable: " << args
[1].c_str()
666 cmCTestLog(this->CTest
, ERROR_MESSAGE
, "Unable to find executable: "
667 << args
[1].c_str() << std::endl
);
668 cres
.Output
= "Unable to find executable: " + args
[1];
669 if ( !this->CTest
->GetShowOnly() )
671 cres
.FullCommandLine
= actualCommand
;
672 this->TestResults
.push_back( cres
);
673 failed
.push_back(testname
);
679 std::vector
<std::string
>::const_iterator j
= args
.begin();
682 std::vector
<const char*> arguments
;
683 this->GenerateTestCommand(arguments
);
684 arguments
.push_back(actualCommand
.c_str());
685 for(;j
!= args
.end(); ++j
)
688 testCommand
+= cmSystemTools::EscapeSpaces(j
->c_str());
689 arguments
.push_back(j
->c_str());
691 arguments
.push_back(0);
694 * Run an executable command and put the stdout in output.
700 cmCTestLog(this->CTest
, HANDLER_VERBOSE_OUTPUT
, std::endl
701 << (this->MemCheck
?"MemCheck":"Test")
702 << " command: " << testCommand
704 *this->LogFile
<< cnt
<< "/" << tmsize
705 << " Test: " << testname
.c_str() << std::endl
;
706 *this->LogFile
<< "Command: ";
707 std::vector
<cmStdString
>::size_type ll
;
708 for ( ll
= 0; ll
< arguments
.size()-1; ll
++ )
710 *this->LogFile
<< "\"" << arguments
[ll
] << "\" ";
714 << "Directory: " << it
->Directory
<< std::endl
715 << "\"" << testname
.c_str() << "\" start time: "
716 << this->CTest
->CurrentTime() << std::endl
717 << "Output:" << std::endl
718 << "----------------------------------------------------------"
721 double clock_start
, clock_finish
;
722 clock_start
= cmSystemTools::GetTime();
724 if ( !this->CTest
->GetShowOnly() )
726 res
= this->CTest
->RunTest(arguments
, &output
, &retVal
, this->LogFile
,
730 clock_finish
= cmSystemTools::GetTime();
734 double ttime
= clock_finish
- clock_start
;
735 int hours
= static_cast<int>(ttime
/ (60 * 60));
736 int minutes
= static_cast<int>(ttime
/ 60) % 60;
737 int seconds
= static_cast<int>(ttime
) % 60;
739 sprintf(buffer
, "%02d:%02d:%02d", hours
, minutes
, seconds
);
741 << "----------------------------------------------------------"
743 << "\"" << testname
.c_str() << "\" end time: "
744 << this->CTest
->CurrentTime() << std::endl
745 << "\"" << testname
.c_str() << "\" time elapsed: "
746 << buffer
<< std::endl
747 << "----------------------------------------------------------"
748 << std::endl
<< std::endl
;
751 cres
.ExecutionTime
= (double)(clock_finish
- clock_start
);
752 cres
.FullCommandLine
= testCommand
;
754 if ( !this->CTest
->GetShowOnly() )
756 bool testFailed
= false;
757 std::vector
<std::pair
<cmsys::RegularExpression
,
758 std::string
> >::iterator passIt
;
759 bool forceFail
= false;
760 if ( it
->RequiredRegularExpressions
.size() > 0 )
763 for ( passIt
= it
->RequiredRegularExpressions
.begin();
764 passIt
!= it
->RequiredRegularExpressions
.end();
767 if ( passIt
->first
.find(output
.c_str()) )
774 reason
= "Required regular expression not found.";
776 for ( passIt
= it
->RequiredRegularExpressions
.begin();
777 passIt
!= it
->RequiredRegularExpressions
.end();
780 reason
+= passIt
->second
;
787 if ( it
->ErrorRegularExpressions
.size() > 0 )
789 for ( passIt
= it
->ErrorRegularExpressions
.begin();
790 passIt
!= it
->ErrorRegularExpressions
.end();
793 if ( passIt
->first
.find(output
.c_str()) )
795 reason
= "Error regular expression found in output.";
796 reason
+= " Regex=[";
797 reason
+= passIt
->second
;
804 if (res
== cmsysProcess_State_Exited
&&
805 (retVal
== 0 || it
->RequiredRegularExpressions
.size()) &&
808 cmCTestLog(this->CTest
, HANDLER_OUTPUT
, " Passed");
811 cmCTestLog(this->CTest
, HANDLER_OUTPUT
, " - But it should fail!");
812 cres
.Status
= cmCTestTestHandler::FAILED
;
817 cres
.Status
= cmCTestTestHandler::COMPLETED
;
819 cmCTestLog(this->CTest
, HANDLER_OUTPUT
, std::endl
);
825 cres
.Status
= cmCTestTestHandler::FAILED
;
826 if ( res
== cmsysProcess_State_Expired
)
828 cmCTestLog(this->CTest
, HANDLER_OUTPUT
, "***Timeout" << std::endl
);
829 cres
.Status
= cmCTestTestHandler::TIMEOUT
;
831 else if ( res
== cmsysProcess_State_Exception
)
833 cmCTestLog(this->CTest
, HANDLER_OUTPUT
, "***Exception: ");
836 case cmsysProcess_Exception_Fault
:
837 cmCTestLog(this->CTest
, HANDLER_OUTPUT
, "SegFault");
838 cres
.Status
= cmCTestTestHandler::SEGFAULT
;
840 case cmsysProcess_Exception_Illegal
:
841 cmCTestLog(this->CTest
, HANDLER_OUTPUT
, "Illegal");
842 cres
.Status
= cmCTestTestHandler::ILLEGAL
;
844 case cmsysProcess_Exception_Interrupt
:
845 cmCTestLog(this->CTest
, HANDLER_OUTPUT
, "Interrupt");
846 cres
.Status
= cmCTestTestHandler::INTERRUPT
;
848 case cmsysProcess_Exception_Numerical
:
849 cmCTestLog(this->CTest
, HANDLER_OUTPUT
, "Numerical");
850 cres
.Status
= cmCTestTestHandler::NUMERICAL
;
853 cmCTestLog(this->CTest
, HANDLER_OUTPUT
, "Other");
854 cres
.Status
= cmCTestTestHandler::OTHER_FAULT
;
856 cmCTestLog(this->CTest
, HANDLER_OUTPUT
, std::endl
);
858 else if ( res
== cmsysProcess_State_Error
)
860 cmCTestLog(this->CTest
, HANDLER_OUTPUT
, "***Bad command " << res
862 cres
.Status
= cmCTestTestHandler::BAD_COMMAND
;
866 // Force fail will also be here?
867 cmCTestLog(this->CTest
, HANDLER_OUTPUT
, "***Failed " << reason
);
870 cres
.Status
= cmCTestTestHandler::COMPLETED
;
871 cmCTestLog(this->CTest
, HANDLER_OUTPUT
, " - supposed to fail");
874 cmCTestLog(this->CTest
, HANDLER_OUTPUT
, std::endl
);
879 failed
.push_back(testname
);
883 passed
.push_back(testname
);
885 if (!output
.empty() && output
.find("<DartMeasurement") != output
.npos
)
887 if (this->DartStuff
.find(output
.c_str()))
889 std::string dartString
= this->DartStuff
.match(1);
890 cmSystemTools::ReplaceString(output
, dartString
.c_str(),"");
891 cres
.RegressionImages
892 = this->GenerateRegressionImages(dartString
);
897 // if this is doing MemCheck then all the output needs to be put into
898 // Output since that it what is parsed to by cmCTestMemCheckHandler
901 if ( cres
.Status
== cmCTestTestHandler::COMPLETED
)
903 this->CleanTestOutput(output
, static_cast<size_t>
904 (this->CustomMaximumPassedTestOutputSize
));
908 this->CleanTestOutput(output
, static_cast<size_t>
909 (this->CustomMaximumFailedTestOutputSize
));
913 cres
.Output
= output
;
914 cres
.ReturnValue
= retVal
;
915 cres
.CompletionStatus
= "Completed";
916 this->TestResults
.push_back( cres
);
919 //----------------------------------------------------------------------
920 void cmCTestTestHandler::ProcessDirectory(std::vector
<cmStdString
> &passed
,
921 std::vector
<cmStdString
> &failed
)
923 std::string current_dir
= cmSystemTools::GetCurrentWorkingDirectory();
924 this->TestList
.clear();
926 this->GetListOfTests();
927 cmCTestTestHandler::ListOfTests::size_type tmsize
= this->TestList
.size();
929 this->StartTest
= this->CTest
->CurrentTime();
930 this->StartTestTime
= static_cast<unsigned int>(cmSystemTools::GetTime());
931 double elapsed_time_start
= cmSystemTools::GetTime();
933 *this->LogFile
<< "Start testing: " << this->StartTest
<< std::endl
934 << "----------------------------------------------------------"
937 // how many tests are in based on RegExp?
939 cmCTestTestHandler::ListOfTests::iterator it
;
940 for ( it
= this->TestList
.begin(); it
!= this->TestList
.end(); it
++ )
942 if (it
->IsInBasedOnREOptions
)
947 // expand the test list based on the union flag
950 this->ExpandTestsToRunInformation((int)tmsize
);
954 this->ExpandTestsToRunInformation(inREcnt
);
959 std::string last_directory
= "";
960 for ( it
= this->TestList
.begin(); it
!= this->TestList
.end(); it
++ )
963 if (it
->IsInBasedOnREOptions
)
968 // if we are out of time then skip this test, we leave two minutes
970 if (this->CTest
->GetRemainingTimeAllowed() - 120 <= 0)
975 if (!(last_directory
== it
->Directory
))
977 cmCTestLog(this->CTest
, HANDLER_VERBOSE_OUTPUT
,
978 "Changing directory into " << it
->Directory
.c_str() << "\n");
979 *this->LogFile
<< "Changing directory into: " << it
->Directory
.c_str()
981 last_directory
= it
->Directory
;
982 cmSystemTools::ChangeDirectory(it
->Directory
.c_str());
987 // if it is not in the list and not in the regexp then skip
988 if ((this->TestsToRun
.size() &&
989 std::find(this->TestsToRun
.begin(), this->TestsToRun
.end(), cnt
)
990 == this->TestsToRun
.end()) && !it
->IsInBasedOnREOptions
)
997 // is this test in the list of tests to run? If not then skip it
998 if ((this->TestsToRun
.size() &&
999 std::find(this->TestsToRun
.begin(),
1000 this->TestsToRun
.end(), inREcnt
)
1001 == this->TestsToRun
.end()) || !it
->IsInBasedOnREOptions
)
1007 // process this one test
1008 this->ProcessOneTest(&(*it
), passed
, failed
, cnt
,
1009 static_cast<int>(tmsize
));
1012 this->EndTest
= this->CTest
->CurrentTime();
1013 this->EndTestTime
= static_cast<unsigned int>(cmSystemTools::GetTime());
1014 this->ElapsedTestingTime
= cmSystemTools::GetTime() - elapsed_time_start
;
1015 if ( this->LogFile
)
1017 *this->LogFile
<< "End testing: " << this->EndTest
<< std::endl
;
1019 cmSystemTools::ChangeDirectory(current_dir
.c_str());
1022 //----------------------------------------------------------------------
1023 void cmCTestTestHandler::GenerateTestCommand(std::vector
<const char*>&)
1027 //----------------------------------------------------------------------
1028 void cmCTestTestHandler::GenerateDartOutput(std::ostream
& os
)
1030 if ( !this->CTest
->GetProduceXML() )
1035 this->CTest
->StartXML(os
);
1037 << "\t<StartDateTime>" << this->StartTest
<< "</StartDateTime>\n"
1038 << "\t<StartTestTime>" << this->StartTestTime
<< "</StartTestTime>\n"
1039 << "\t<TestList>\n";
1040 cmCTestTestHandler::TestResultsVector::size_type cc
;
1041 for ( cc
= 0; cc
< this->TestResults
.size(); cc
++ )
1043 cmCTestTestResult
*result
= &this->TestResults
[cc
];
1044 std::string testPath
= result
->Path
+ "/" + result
->Name
;
1045 os
<< "\t\t<Test>" << cmCTest::MakeXMLSafe(
1046 this->CTest
->GetShortPathToFile(testPath
.c_str()))
1047 << "</Test>" << std::endl
;
1049 os
<< "\t</TestList>\n";
1050 for ( cc
= 0; cc
< this->TestResults
.size(); cc
++ )
1052 cmCTestTestResult
*result
= &this->TestResults
[cc
];
1053 os
<< "\t<Test Status=\"";
1054 if ( result
->Status
== cmCTestTestHandler::COMPLETED
)
1058 else if ( result
->Status
== cmCTestTestHandler::NOT_RUN
)
1066 std::string testPath
= result
->Path
+ "/" + result
->Name
;
1068 << "\t\t<Name>" << cmCTest::MakeXMLSafe(result
->Name
) << "</Name>\n"
1069 << "\t\t<Path>" << cmCTest::MakeXMLSafe(
1070 this->CTest
->GetShortPathToFile(result
->Path
.c_str())) << "</Path>\n"
1071 << "\t\t<FullName>" << cmCTest::MakeXMLSafe(
1072 this->CTest
->GetShortPathToFile(testPath
.c_str())) << "</FullName>\n"
1073 << "\t\t<FullCommandLine>"
1074 << cmCTest::MakeXMLSafe(result
->FullCommandLine
)
1075 << "</FullCommandLine>\n"
1076 << "\t\t<Results>" << std::endl
;
1077 if ( result
->Status
!= cmCTestTestHandler::NOT_RUN
)
1079 if ( result
->Status
!= cmCTestTestHandler::COMPLETED
||
1080 result
->ReturnValue
)
1082 os
<< "\t\t\t<NamedMeasurement type=\"text/string\" "
1083 "name=\"Exit Code\"><Value>"
1084 << this->GetTestStatus(result
->Status
) << "</Value>"
1085 "</NamedMeasurement>\n"
1086 << "\t\t\t<NamedMeasurement type=\"text/string\" "
1087 "name=\"Exit Value\"><Value>"
1088 << result
->ReturnValue
<< "</Value></NamedMeasurement>"
1091 os
<< result
->RegressionImages
;
1092 os
<< "\t\t\t<NamedMeasurement type=\"numeric/double\" "
1093 << "name=\"Execution Time\"><Value>"
1094 << result
->ExecutionTime
<< "</Value></NamedMeasurement>\n";
1096 << "\t\t\t<NamedMeasurement type=\"text/string\" "
1097 << "name=\"Completion Status\"><Value>"
1098 << result
->CompletionStatus
<< "</Value></NamedMeasurement>\n";
1101 << "\t\t\t<NamedMeasurement type=\"text/string\" "
1102 << "name=\"Command Line\"><Value>"
1103 << result
->FullCommandLine
<< "</Value></NamedMeasurement>\n";
1104 std::map
<cmStdString
,cmStdString
>::iterator measureIt
;
1105 for ( measureIt
= result
->Properties
->Measurements
.begin();
1106 measureIt
!= result
->Properties
->Measurements
.end();
1110 << "\t\t\t<NamedMeasurement type=\"text/string\" "
1111 << "name=\"" << measureIt
->first
.c_str() << "\"><Value>"
1112 << measureIt
->second
.c_str() << "</Value></NamedMeasurement>\n";
1115 << "\t\t\t<Measurement>\n"
1116 << "\t\t\t\t<Value>";
1117 os
<< cmCTest::MakeXMLSafe(result
->Output
);
1120 << "\t\t\t</Measurement>\n"
1121 << "\t\t</Results>\n"
1122 << "\t</Test>" << std::endl
;
1125 os
<< "\t<EndDateTime>" << this->EndTest
<< "</EndDateTime>\n"
1126 << "\t<EndTestTime>" << this->EndTestTime
<< "</EndTestTime>\n"
1127 << "<ElapsedMinutes>"
1128 << static_cast<int>(this->ElapsedTestingTime
/6)/10.0
1129 << "</ElapsedMinutes>"
1130 << "</Testing>" << std::endl
;
1131 this->CTest
->EndXML(os
);
1134 //----------------------------------------------------------------------
1135 int cmCTestTestHandler::ExecuteCommands(std::vector
<cmStdString
>& vec
)
1137 std::vector
<cmStdString
>::iterator it
;
1138 for ( it
= vec
.begin(); it
!= vec
.end(); ++it
)
1141 cmCTestLog(this->CTest
, HANDLER_VERBOSE_OUTPUT
, "Run command: " << *it
1143 if ( !cmSystemTools::RunSingleCommand(it
->c_str(), 0, &retVal
, 0, true
1144 /*this->Verbose*/) || retVal
!= 0 )
1146 cmCTestLog(this->CTest
, ERROR_MESSAGE
, "Problem running command: "
1147 << *it
<< std::endl
);
1155 //----------------------------------------------------------------------
1156 // Find the appropriate executable to run for a test
1157 std::string
cmCTestTestHandler::FindTheExecutable(const char *exe
)
1159 std::string resConfig
;
1160 std::vector
<std::string
> extraPaths
;
1161 std::vector
<std::string
> failedPaths
;
1162 return cmCTestTestHandler::FindExecutable(this->CTest
,
1168 // add additional configuraitons to the search path
1169 void cmCTestTestHandler
1170 ::AddConfigurations(cmCTest
*ctest
,
1171 std::vector
<std::string
> &attempted
,
1172 std::vector
<std::string
> &attemptedConfigs
,
1173 std::string filepath
,
1174 std::string
&filename
)
1176 std::string tempPath
;
1178 if (filepath
.size())
1182 tempPath
= filepath
+ filename
;
1183 attempted
.push_back(tempPath
);
1184 attemptedConfigs
.push_back("");
1186 if(ctest
->GetConfigType().size())
1188 tempPath
= filepath
;
1189 tempPath
+= ctest
->GetConfigType();
1191 tempPath
+= filename
;
1192 attempted
.push_back(tempPath
);
1193 attemptedConfigs
.push_back(ctest
->GetConfigType());
1194 // If the file is an OSX bundle then the configtyp
1195 // will be at the start of the path
1196 tempPath
= ctest
->GetConfigType();
1198 tempPath
+= filepath
;
1199 tempPath
+= filename
;
1200 attempted
.push_back(tempPath
);
1201 attemptedConfigs
.push_back(ctest
->GetConfigType());
1205 // no config specified to try some options
1206 tempPath
= filepath
;
1207 tempPath
+= "Release/";
1208 tempPath
+= filename
;
1209 attempted
.push_back(tempPath
);
1210 attemptedConfigs
.push_back("Release");
1211 tempPath
= filepath
;
1212 tempPath
+= "Debug/";
1213 tempPath
+= filename
;
1214 attempted
.push_back(tempPath
);
1215 attemptedConfigs
.push_back("Debug");
1216 tempPath
= filepath
;
1217 tempPath
+= "MinSizeRel/";
1218 tempPath
+= filename
;
1219 attempted
.push_back(tempPath
);
1220 attemptedConfigs
.push_back("MinSizeRel");
1221 tempPath
= filepath
;
1222 tempPath
+= "RelWithDebInfo/";
1223 tempPath
+= filename
;
1224 attempted
.push_back(tempPath
);
1225 attemptedConfigs
.push_back("RelWithDebInfo");
1226 tempPath
= filepath
;
1227 tempPath
+= "Deployment/";
1228 tempPath
+= filename
;
1229 attempted
.push_back(tempPath
);
1230 attemptedConfigs
.push_back("Deployment");
1231 tempPath
= filepath
;
1232 tempPath
+= "Development/";
1233 tempPath
+= filename
;
1234 attempted
.push_back(tempPath
);
1235 attemptedConfigs
.push_back("Deployment");
1240 //----------------------------------------------------------------------
1241 // Find the appropriate executable to run for a test
1242 std::string cmCTestTestHandler
1243 ::FindExecutable(cmCTest
*ctest
,
1244 const char *testCommand
,
1245 std::string
&resultingConfig
,
1246 std::vector
<std::string
> &extraPaths
,
1247 std::vector
<std::string
> &failed
)
1249 // now run the compiled test if we can find it
1250 std::vector
<std::string
> attempted
;
1251 std::vector
<std::string
> attemptedConfigs
;
1252 std::string tempPath
;
1253 std::string filepath
=
1254 cmSystemTools::GetFilenamePath(testCommand
);
1255 std::string filename
=
1256 cmSystemTools::GetFilenameName(testCommand
);
1258 cmCTestTestHandler::AddConfigurations(ctest
, attempted
,
1262 // if extraPaths are provided and we were not passed a full path, try them,
1263 // try any extra paths
1264 if (filepath
.size() == 0)
1266 for (unsigned int i
= 0; i
< extraPaths
.size(); ++i
)
1268 std::string filepathExtra
=
1269 cmSystemTools::GetFilenamePath(extraPaths
[i
]);
1270 std::string filenameExtra
=
1271 cmSystemTools::GetFilenameName(extraPaths
[i
]);
1272 cmCTestTestHandler::AddConfigurations(ctest
,attempted
,
1279 // store the final location in fullPath
1280 std::string fullPath
;
1282 // now look in the paths we specified above
1283 for(unsigned int ai
=0;
1284 ai
< attempted
.size() && fullPath
.size() == 0; ++ai
)
1286 // first check without exe extension
1287 if(cmSystemTools::FileExists(attempted
[ai
].c_str())
1288 && !cmSystemTools::FileIsDirectory(attempted
[ai
].c_str()))
1290 fullPath
= cmSystemTools::CollapseFullPath(attempted
[ai
].c_str());
1291 resultingConfig
= attemptedConfigs
[ai
];
1293 // then try with the exe extension
1296 failed
.push_back(attempted
[ai
].c_str());
1297 tempPath
= attempted
[ai
];
1298 tempPath
+= cmSystemTools::GetExecutableExtension();
1299 if(cmSystemTools::FileExists(tempPath
.c_str())
1300 && !cmSystemTools::FileIsDirectory(tempPath
.c_str()))
1302 fullPath
= cmSystemTools::CollapseFullPath(tempPath
.c_str());
1303 resultingConfig
= attemptedConfigs
[ai
];
1307 failed
.push_back(tempPath
.c_str());
1312 // if everything else failed, check the users path, but only if a full path
1314 if (fullPath
.size() == 0 && filepath
.size() == 0)
1316 std::string path
= cmSystemTools::FindProgram(filename
.c_str());
1319 resultingConfig
= "";
1323 if(fullPath
.size() == 0)
1325 cmCTestLog(ctest
, HANDLER_OUTPUT
,
1326 "Could not find executable " << testCommand
<< "\n"
1327 << "Looked in the following places:\n");
1328 for(std::vector
<std::string
>::iterator i
= failed
.begin();
1329 i
!= failed
.end(); ++i
)
1331 cmCTestLog(ctest
, HANDLER_OUTPUT
,
1332 i
->c_str() << "\n");
1340 //----------------------------------------------------------------------
1341 void cmCTestTestHandler::GetListOfTests()
1343 if ( !this->IncludeRegExp
.empty() )
1345 this->IncludeTestsRegularExpression
.compile(this->IncludeRegExp
.c_str());
1347 if ( !this->ExcludeRegExp
.empty() )
1349 this->ExcludeTestsRegularExpression
.compile(this->ExcludeRegExp
.c_str());
1351 cmCTestLog(this->CTest
, HANDLER_VERBOSE_OUTPUT
,
1352 "Constructing a list of tests" << std::endl
);
1354 cmGlobalGenerator gg
;
1355 gg
.SetCMakeInstance(&cm
);
1356 std::auto_ptr
<cmLocalGenerator
> lg(gg
.CreateLocalGenerator());
1357 lg
->SetGlobalGenerator(&gg
);
1358 cmMakefile
*mf
= lg
->GetMakefile();
1359 mf
->AddDefinition("CTEST_CONFIGURATION_TYPE",
1360 this->CTest
->GetConfigType().c_str());
1362 // Add handler for ADD_TEST
1363 cmCTestAddTestCommand
* newCom1
= new cmCTestAddTestCommand
;
1364 newCom1
->TestHandler
= this;
1365 cm
.AddCommand(newCom1
);
1367 // Add handler for SUBDIRS
1368 cmCTestSubdirCommand
* newCom2
=
1369 new cmCTestSubdirCommand
;
1370 newCom2
->TestHandler
= this;
1371 cm
.AddCommand(newCom2
);
1373 // Add handler for ADD_SUBDIRECTORY
1374 cmCTestAddSubdirectoryCommand
* newCom3
=
1375 new cmCTestAddSubdirectoryCommand
;
1376 newCom3
->TestHandler
= this;
1377 cm
.AddCommand(newCom3
);
1379 // Add handler for SET_SOURCE_FILES_PROPERTIES
1380 cmCTestSetTestsPropertiesCommand
* newCom4
1381 = new cmCTestSetTestsPropertiesCommand
;
1382 newCom4
->TestHandler
= this;
1383 cm
.AddCommand(newCom4
);
1385 const char* testFilename
;
1386 if( cmSystemTools::FileExists("CTestTestfile.cmake") )
1388 // does the CTestTestfile.cmake exist ?
1389 testFilename
= "CTestTestfile.cmake";
1391 else if( cmSystemTools::FileExists("DartTestfile.txt") )
1393 // does the DartTestfile.txt exist ?
1394 testFilename
= "DartTestfile.txt";
1401 if ( !mf
->ReadListFile(0, testFilename
) )
1405 if ( cmSystemTools::GetErrorOccuredFlag() )
1409 cmCTestLog(this->CTest
, HANDLER_VERBOSE_OUTPUT
,
1410 "Done constructing a list of tests" << std::endl
);
1413 //----------------------------------------------------------------------
1414 void cmCTestTestHandler::UseIncludeRegExp()
1416 this->UseIncludeRegExpFlag
= true;
1419 //----------------------------------------------------------------------
1420 void cmCTestTestHandler::UseExcludeRegExp()
1422 this->UseExcludeRegExpFlag
= true;
1423 this->UseExcludeRegExpFirst
= this->UseIncludeRegExpFlag
? false : true;
1426 //----------------------------------------------------------------------
1427 const char* cmCTestTestHandler::GetTestStatus(int status
)
1429 static const char statuses
[][100] = {
1442 if ( status
< cmCTestTestHandler::NOT_RUN
||
1443 status
> cmCTestTestHandler::COMPLETED
)
1447 return statuses
[status
];
1450 //----------------------------------------------------------------------
1451 void cmCTestTestHandler::ExpandTestsToRunInformation(int numTests
)
1453 if (this->TestsToRunString
.empty())
1461 std::string::size_type pos
= 0;
1462 std::string::size_type pos2
;
1464 if(GetNextNumber(this->TestsToRunString
, start
, pos
, pos2
))
1467 if(GetNextNumber(this->TestsToRunString
, end
, pos
, pos2
))
1470 if(GetNextRealNumber(this->TestsToRunString
, stride
, pos
, pos2
))
1473 // now read specific numbers
1474 while(GetNextNumber(this->TestsToRunString
, val
, pos
, pos2
))
1476 this->TestsToRun
.push_back(val
);
1478 this->TestsToRun
.push_back(val
);
1483 // if start is not specified then we assume we start at 1
1489 // if end isnot specified then we assume we end with the last test
1495 // if the stride wasn't specified then it defaults to 1
1501 // if we have a range then add it
1502 if(end
!= -1 && start
!= -1 && stride
> 0)
1505 while (i
*stride
+ start
<= end
)
1507 this->TestsToRun
.push_back(static_cast<int>(i
*stride
+start
));
1513 std::sort(this->TestsToRun
.begin(), this->TestsToRun
.end(),
1515 // remove duplicates
1516 std::vector
<int>::iterator new_end
=
1517 std::unique(this->TestsToRun
.begin(), this->TestsToRun
.end());
1518 this->TestsToRun
.erase(new_end
, this->TestsToRun
.end());
1521 //----------------------------------------------------------------------
1522 // Just for convenience
1523 #define SPACE_REGEX "[ \t\r\n]"
1524 //----------------------------------------------------------------------
1525 std::string
cmCTestTestHandler::GenerateRegressionImages(
1526 const std::string
& xml
)
1528 cmsys::RegularExpression
twoattributes(
1530 SPACE_REGEX
"*(name|type|encoding|compression)=\"([^\"]*)\""
1531 SPACE_REGEX
"*(name|type|encoding|compression)=\"([^\"]*)\""
1532 SPACE_REGEX
"*>([^<]*)</DartMeasurement>");
1533 cmsys::RegularExpression
threeattributes(
1535 SPACE_REGEX
"*(name|type|encoding|compression)=\"([^\"]*)\""
1536 SPACE_REGEX
"*(name|type|encoding|compression)=\"([^\"]*)\""
1537 SPACE_REGEX
"*(name|type|encoding|compression)=\"([^\"]*)\""
1538 SPACE_REGEX
"*>([^<]*)</DartMeasurement>");
1539 cmsys::RegularExpression
fourattributes(
1541 SPACE_REGEX
"*(name|type|encoding|compression)=\"([^\"]*)\""
1542 SPACE_REGEX
"*(name|type|encoding|compression)=\"([^\"]*)\""
1543 SPACE_REGEX
"*(name|type|encoding|compression)=\"([^\"]*)\""
1544 SPACE_REGEX
"*(name|type|encoding|compression)=\"([^\"]*)\""
1545 SPACE_REGEX
"*>([^<]*)</DartMeasurement>");
1546 cmsys::RegularExpression
measurementfile(
1547 "<DartMeasurementFile"
1548 SPACE_REGEX
"*(name|type|encoding|compression)=\"([^\"]*)\""
1549 SPACE_REGEX
"*(name|type|encoding|compression)=\"([^\"]*)\""
1550 SPACE_REGEX
"*>([^<]*)</DartMeasurementFile>");
1552 cmOStringStream ostr
;
1554 std::string cxml
= xml
;
1557 if ( twoattributes
.find(cxml
) )
1560 << "\t\t\t<NamedMeasurement"
1561 << " " << twoattributes
.match(1) << "=\""
1562 << twoattributes
.match(2) << "\""
1563 << " " << twoattributes
.match(3) << "=\""
1564 << twoattributes
.match(4) << "\""
1565 << "><Value>" << twoattributes
.match(5)
1566 << "</Value></NamedMeasurement>"
1568 cxml
.erase(twoattributes
.start(),
1569 twoattributes
.end() - twoattributes
.start());
1571 else if ( threeattributes
.find(cxml
) )
1574 << "\t\t\t<NamedMeasurement"
1575 << " " << threeattributes
.match(1) << "=\""
1576 << threeattributes
.match(2) << "\""
1577 << " " << threeattributes
.match(3) << "=\""
1578 << threeattributes
.match(4) << "\""
1579 << " " << threeattributes
.match(5) << "=\""
1580 << threeattributes
.match(6) << "\""
1581 << "><Value>" << threeattributes
.match(7)
1582 << "</Value></NamedMeasurement>"
1584 cxml
.erase(threeattributes
.start(),
1585 threeattributes
.end() - threeattributes
.start());
1587 else if ( fourattributes
.find(cxml
) )
1590 << "\t\t\t<NamedMeasurement"
1591 << " " << fourattributes
.match(1) << "=\""
1592 << fourattributes
.match(2) << "\""
1593 << " " << fourattributes
.match(3) << "=\""
1594 << fourattributes
.match(4) << "\""
1595 << " " << fourattributes
.match(5) << "=\""
1596 << fourattributes
.match(6) << "\""
1597 << " " << fourattributes
.match(7) << "=\""
1598 << fourattributes
.match(8) << "\""
1599 << "><Value>" << fourattributes
.match(9)
1600 << "</Value></NamedMeasurement>"
1602 cxml
.erase(fourattributes
.start(),
1603 fourattributes
.end() - fourattributes
.start());
1605 else if ( measurementfile
.find(cxml
) )
1607 const std::string
& filename
=
1608 cmCTest::CleanString(measurementfile
.match(5));
1609 if ( cmSystemTools::FileExists(filename
.c_str()) )
1611 long len
= cmSystemTools::FileLength(filename
.c_str());
1614 std::string k1
= measurementfile
.match(1);
1615 std::string v1
= measurementfile
.match(2);
1616 std::string k2
= measurementfile
.match(3);
1617 std::string v2
= measurementfile
.match(4);
1618 if ( cmSystemTools::LowerCase(k1
) == "type" )
1622 if ( cmSystemTools::LowerCase(k2
) == "type" )
1628 << "\t\t\t<NamedMeasurement"
1629 << " " << k1
<< "=\"" << v1
<< "\""
1630 << " " << k2
<< "=\"" << v2
<< "\""
1631 << " encoding=\"none\""
1632 << "><Value>Image " << filename
.c_str()
1633 << " is empty</Value></NamedMeasurement>";
1637 std::ifstream
ifs(filename
.c_str(), std::ios::in
1642 unsigned char *file_buffer
= new unsigned char [ len
+ 1 ];
1643 ifs
.read(reinterpret_cast<char*>(file_buffer
), len
);
1644 unsigned char *encoded_buffer
1645 = new unsigned char [ static_cast<int>(len
* 1.5 + 5) ];
1648 = cmsysBase64_Encode(file_buffer
, len
, encoded_buffer
, 1);
1652 << "\t\t\t<NamedMeasurement"
1653 << " " << measurementfile
.match(1) << "=\""
1654 << measurementfile
.match(2) << "\""
1655 << " " << measurementfile
.match(3) << "=\""
1656 << measurementfile
.match(4) << "\""
1657 << " encoding=\"base64\""
1658 << ">" << std::endl
<< "\t\t\t\t<Value>";
1659 for ( cc
= 0; cc
< rlen
; cc
++ )
1661 ostr
<< encoded_buffer
[cc
];
1662 if ( cc
% 60 == 0 && cc
)
1668 << "</Value>" << std::endl
<< "\t\t\t</NamedMeasurement>"
1670 delete [] file_buffer
;
1671 delete [] encoded_buffer
;
1677 if ( measurementfile
.match(1) == "name" )
1682 << "\t\t\t<NamedMeasurement"
1683 << " name=\"" << measurementfile
.match(idx
) << "\""
1684 << " text=\"text/string\""
1685 << "><Value>File " << filename
.c_str()
1686 << " not found</Value></NamedMeasurement>"
1688 cmCTestLog(this->CTest
, HANDLER_OUTPUT
, "File \"" << filename
.c_str()
1689 << "\" not found." << std::endl
);
1691 cxml
.erase(measurementfile
.start(),
1692 measurementfile
.end() - measurementfile
.start());
1702 //----------------------------------------------------------------------
1703 void cmCTestTestHandler::SetIncludeRegExp(const char *arg
)
1705 this->IncludeRegExp
= arg
;
1708 //----------------------------------------------------------------------
1709 void cmCTestTestHandler::SetExcludeRegExp(const char *arg
)
1711 this->ExcludeRegExp
= arg
;
1714 //----------------------------------------------------------------------
1715 void cmCTestTestHandler::SetTestsToRunInformation(const char* in
)
1721 this->TestsToRunString
= in
;
1722 // if the argument is a file, then read it and use the contents as the
1724 if(cmSystemTools::FileExists(in
))
1726 std::ifstream
fin(in
);
1727 unsigned long filelen
= cmSystemTools::FileLength(in
);
1728 char* buff
= new char[filelen
+1];
1729 fin
.getline(buff
, filelen
);
1730 buff
[fin
.gcount()] = 0;
1731 this->TestsToRunString
= buff
;
1735 //----------------------------------------------------------------------
1736 bool cmCTestTestHandler::CleanTestOutput(std::string
& output
,
1737 size_t remove_threshold
)
1739 if ( remove_threshold
== 0 )
1743 if ( output
.find("CTEST_FULL_OUTPUT") != output
.npos
)
1747 cmOStringStream ostr
;
1748 std::string::size_type cc
;
1749 std::string::size_type skipsize
= 0;
1752 for ( cc
= 0; cc
< output
.size(); cc
++ )
1754 int ch
= output
[cc
];
1755 if ( ch
< 0 || ch
> 255 )
1767 if ( skipsize
< remove_threshold
)
1769 ostr
<< static_cast<char>(ch
);
1773 if ( notskip
&& skipsize
>= remove_threshold
)
1780 ostr
<< static_cast<char>(ch
);
1789 ostr
<< "..." << std::endl
<< "The rest of the test output was removed "
1790 "since it exceeds the threshold of "
1791 << remove_threshold
<< " characters." << std::endl
;
1793 output
= ostr
.str();
1797 //----------------------------------------------------------------------
1798 bool cmCTestTestHandler::SetTestsProperties(
1799 const std::vector
<std::string
>& args
)
1801 std::vector
<std::string
>::const_iterator it
;
1802 std::vector
<cmStdString
> tests
;
1804 for ( it
= args
.begin(); it
!= args
.end(); ++ it
)
1806 if ( *it
== "PROPERTIES" )
1811 tests
.push_back(*it
);
1817 ++ it
; // skip PROPERTIES
1818 for ( ; it
!= args
.end(); ++ it
)
1820 std::string key
= *it
;
1822 if ( it
== args
.end() )
1826 std::string val
= *it
;
1827 std::vector
<cmStdString
>::const_iterator tit
;
1828 for ( tit
= tests
.begin(); tit
!= tests
.end(); ++ tit
)
1830 cmCTestTestHandler::ListOfTests::iterator rtit
;
1831 for ( rtit
= this->TestList
.begin();
1832 rtit
!= this->TestList
.end();
1835 if ( *tit
== rtit
->Name
)
1837 if ( key
== "WILL_FAIL" )
1839 rtit
->WillFail
= cmSystemTools::IsOn(val
.c_str());
1841 if ( key
== "TIMEOUT" )
1843 rtit
->Timeout
= atof(val
.c_str());
1845 if ( key
== "FAIL_REGULAR_EXPRESSION" )
1847 std::vector
<std::string
> lval
;
1848 cmSystemTools::ExpandListArgument(val
.c_str(), lval
);
1849 std::vector
<std::string
>::iterator crit
;
1850 for ( crit
= lval
.begin(); crit
!= lval
.end(); ++ crit
)
1852 rtit
->ErrorRegularExpressions
.push_back(
1853 std::pair
<cmsys::RegularExpression
, std::string
>(
1854 cmsys::RegularExpression(crit
->c_str()),
1855 std::string(crit
->c_str())));
1858 if ( key
== "MEASUREMENT" )
1860 size_t pos
= val
.find_first_of("=");
1861 if ( pos
!= val
.npos
)
1863 std::string mKey
= val
.substr(0, pos
);
1864 const char* mVal
= val
.c_str() + pos
+ 1;
1865 rtit
->Measurements
[mKey
] = mVal
;
1869 rtit
->Measurements
[val
] = "1";
1872 if ( key
== "PASS_REGULAR_EXPRESSION" )
1874 std::vector
<std::string
> lval
;
1875 cmSystemTools::ExpandListArgument(val
.c_str(), lval
);
1876 std::vector
<std::string
>::iterator crit
;
1877 for ( crit
= lval
.begin(); crit
!= lval
.end(); ++ crit
)
1879 rtit
->RequiredRegularExpressions
.push_back(
1880 std::pair
<cmsys::RegularExpression
, std::string
>(
1881 cmsys::RegularExpression(crit
->c_str()),
1882 std::string(crit
->c_str())));
1892 //----------------------------------------------------------------------
1893 bool cmCTestTestHandler::AddTest(const std::vector
<std::string
>& args
)
1895 const std::string
& testname
= args
[0];
1896 cmCTestLog(this->CTest
, DEBUG
, "Add test: " << args
[0] << std::endl
);
1897 if (this->UseExcludeRegExpFlag
&&
1898 this->UseExcludeRegExpFirst
&&
1899 this->ExcludeTestsRegularExpression
.find(testname
.c_str()))
1903 if ( this->MemCheck
)
1905 std::vector
<cmStdString
>::iterator it
;
1907 for ( it
= this->CustomTestsIgnore
.begin();
1908 it
!= this->CustomTestsIgnore
.end(); ++ it
)
1910 if ( *it
== testname
)
1918 cmCTestLog(this->CTest
, HANDLER_VERBOSE_OUTPUT
, "Ignore memcheck: "
1919 << *it
<< std::endl
);
1925 std::vector
<cmStdString
>::iterator it
;
1927 for ( it
= this->CustomTestsIgnore
.begin();
1928 it
!= this->CustomTestsIgnore
.end(); ++ it
)
1930 if ( *it
== testname
)
1938 cmCTestLog(this->CTest
, HANDLER_VERBOSE_OUTPUT
, "Ignore test: "
1939 << *it
<< std::endl
);
1944 cmCTestTestProperties test
;
1945 test
.Name
= testname
;
1947 test
.Directory
= cmSystemTools::GetCurrentWorkingDirectory();
1948 cmCTestLog(this->CTest
, DEBUG
, "Set test directory: "
1949 << test
.Directory
<< std::endl
);
1951 test
.IsInBasedOnREOptions
= true;
1952 test
.WillFail
= false;
1954 if (this->UseIncludeRegExpFlag
&&
1955 !this->IncludeTestsRegularExpression
.find(testname
.c_str()))
1957 test
.IsInBasedOnREOptions
= false;
1959 else if (this->UseExcludeRegExpFlag
&&
1960 !this->UseExcludeRegExpFirst
&&
1961 this->ExcludeTestsRegularExpression
.find(testname
.c_str()))
1963 test
.IsInBasedOnREOptions
= false;
1965 this->TestList
.push_back(test
);