Imported Upstream version 2.8.9
[platform/upstream/cmake.git] / Source / cmCTest.cxx
1 /*============================================================================
2   CMake - Cross Platform Makefile Generator
3   Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
4
5   Distributed under the OSI-approved BSD License (the "License");
6   see accompanying file Copyright.txt for details.
7
8   This software is distributed WITHOUT ANY WARRANTY; without even the
9   implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
10   See the License for more information.
11 ============================================================================*/
12 #include "cm_curl.h"
13
14 #include "cmCTest.h"
15 #include "cmake.h"
16 #include "cmMakefile.h"
17 #include "cmLocalGenerator.h"
18 #include "cmGlobalGenerator.h"
19 #include <cmsys/Base64.h>
20 #include <cmsys/Directory.hxx>
21 #include <cmsys/SystemInformation.hxx>
22 #include "cmDynamicLoader.h"
23 #include "cmGeneratedFileStream.h"
24 #include "cmXMLSafe.h"
25 #include "cmVersionMacros.h"
26 #include "cmCTestCommand.h"
27 #include "cmCTestStartCommand.h"
28
29 #include "cmCTestBuildHandler.h"
30 #include "cmCTestBuildAndTestHandler.h"
31 #include "cmCTestConfigureHandler.h"
32 #include "cmCTestCoverageHandler.h"
33 #include "cmCTestMemCheckHandler.h"
34 #include "cmCTestScriptHandler.h"
35 #include "cmCTestSubmitHandler.h"
36 #include "cmCTestTestHandler.h"
37 #include "cmCTestUpdateHandler.h"
38 #include "cmCTestUploadHandler.h"
39
40 #include "cmVersion.h"
41
42 #include <cmsys/RegularExpression.hxx>
43 #include <cmsys/Process.h>
44 #include <cmsys/Glob.hxx>
45
46 #include <stdlib.h>
47 #include <math.h>
48 #include <float.h>
49 #include <ctype.h>
50
51 #include <cmsys/auto_ptr.hxx>
52
53 #include <cm_zlib.h>
54 #include <cmsys/Base64.h>
55
56 #if defined(__BEOS__) && !defined(__HAIKU__)
57 #include <be/kernel/OS.h>   /* disable_debugger() API. */
58 #endif
59
60 #if defined(__HAIKU__)
61 #include <os/kernel/OS.h>   /* disable_debugger() API. */
62 #endif
63
64
65 #define DEBUGOUT std::cout << __LINE__ << " "; std::cout
66 #define DEBUGERR std::cerr << __LINE__ << " "; std::cerr
67
68 //----------------------------------------------------------------------
69 struct tm* cmCTest::GetNightlyTime(std::string str,
70                                    bool tomorrowtag)
71 {
72   struct tm* lctime;
73   time_t tctime = time(0);
74   lctime = gmtime(&tctime);
75   char buf[1024];
76   // add todays year day and month to the time in str because
77   // curl_getdate no longer assumes the day is today
78   sprintf(buf, "%d%02d%02d %s", 
79           lctime->tm_year+1900, 
80           lctime->tm_mon +1,
81           lctime->tm_mday,
82           str.c_str());
83   cmCTestLog(this, OUTPUT, "Determine Nightly Start Time" << std::endl
84     << "   Specified time: " << str.c_str() << std::endl);
85   //Convert the nightly start time to seconds. Since we are
86   //providing only a time and a timezone, the current date of
87   //the local machine is assumed. Consequently, nightlySeconds
88   //is the time at which the nightly dashboard was opened or
89   //will be opened on the date of the current client machine.
90   //As such, this time may be in the past or in the future.
91   time_t ntime = curl_getdate(buf, &tctime);
92   cmCTestLog(this, DEBUG, "   Get curl time: " << ntime << std::endl);
93   tctime = time(0);
94   cmCTestLog(this, DEBUG, "   Get the current time: " << tctime << std::endl);
95
96   const int dayLength = 24 * 60 * 60;
97   cmCTestLog(this, DEBUG, "Seconds: " << tctime << std::endl);
98   while ( ntime > tctime )
99     {
100     // If nightlySeconds is in the past, this is the current
101     // open dashboard, then return nightlySeconds.  If
102     // nightlySeconds is in the future, this is the next
103     // dashboard to be opened, so subtract 24 hours to get the
104     // time of the current open dashboard
105     ntime -= dayLength;
106     cmCTestLog(this, DEBUG, "Pick yesterday" << std::endl);
107     cmCTestLog(this, DEBUG, "   Future time, subtract day: " << ntime
108       << std::endl);
109     }
110   while ( tctime > (ntime + dayLength) )
111     {
112     ntime += dayLength;
113     cmCTestLog(this, DEBUG, "   Past time, add day: " << ntime << std::endl);
114     }
115   cmCTestLog(this, DEBUG, "nightlySeconds: " << ntime << std::endl);
116   cmCTestLog(this, DEBUG, "   Current time: " << tctime
117     << " Nightly time: " << ntime << std::endl);
118   if ( tomorrowtag )
119     {
120     cmCTestLog(this, OUTPUT, "   Use future tag, Add a day" << std::endl);
121     ntime += dayLength;
122     }
123   lctime = gmtime(&ntime);
124   return lctime;
125 }
126
127 //----------------------------------------------------------------------
128 std::string cmCTest::CleanString(const std::string& str)
129 {
130   std::string::size_type spos = str.find_first_not_of(" \n\t\r\f\v");
131   std::string::size_type epos = str.find_last_not_of(" \n\t\r\f\v");
132   if ( spos == str.npos )
133     {
134     return std::string();
135     }
136   if ( epos != str.npos )
137     {
138     epos = epos - spos + 1;
139     }
140   return str.substr(spos, epos);
141 }
142
143 //----------------------------------------------------------------------
144 std::string cmCTest::CurrentTime()
145 {
146   time_t currenttime = time(0);
147   struct tm* t = localtime(&currenttime);
148   //return ::CleanString(ctime(&currenttime));
149   char current_time[1024];
150   if ( this->ShortDateFormat )
151     {
152     strftime(current_time, 1000, "%b %d %H:%M %Z", t);
153     }
154   else
155     {
156     strftime(current_time, 1000, "%a %b %d %H:%M:%S %Z %Y", t);
157     }
158   cmCTestLog(this, DEBUG, "   Current_Time: " << current_time << std::endl);
159   return cmXMLSafe(cmCTest::CleanString(current_time)).str();
160 }
161
162 //----------------------------------------------------------------------
163 std::string cmCTest::GetCostDataFile()
164 {
165   std::string fname = this->GetCTestConfiguration("CostDataFile");
166   if(fname == "")
167     {
168     fname= this->GetBinaryDir() + "/Testing/Temporary/CTestCostData.txt";
169     }
170   return fname;
171 }
172
173 #ifdef CMAKE_BUILD_WITH_CMAKE
174 //----------------------------------------------------------------------------
175 static size_t
176 HTTPResponseCallback(void *ptr, size_t size, size_t nmemb, void *data)
177 {
178   register int realsize = (int)(size * nmemb);
179
180   std::string *response
181     = static_cast<std::string*>(data);
182   const char* chPtr = static_cast<char*>(ptr);
183   *response += chPtr;
184
185   return realsize;
186 }
187
188 //----------------------------------------------------------------------------
189 int cmCTest::HTTPRequest(std::string url, HTTPMethod method,
190                                        std::string& response,
191                                        std::string fields,
192                                        std::string putFile, int timeout)
193 {
194   CURL* curl;
195   FILE* file;
196   ::curl_global_init(CURL_GLOBAL_ALL);
197   curl = ::curl_easy_init();
198
199   //set request options based on method
200   switch(method)
201     {
202     case cmCTest::HTTP_POST:
203       ::curl_easy_setopt(curl, CURLOPT_POST, 1);
204       ::curl_easy_setopt(curl, CURLOPT_POSTFIELDS, fields.c_str());
205       break;
206     case cmCTest::HTTP_PUT:
207       if(!cmSystemTools::FileExists(putFile.c_str()))
208         {
209         response = "Error: File ";
210         response += putFile + " does not exist.\n";
211         return -1;
212         }
213       ::curl_easy_setopt(curl, CURLOPT_PUT, 1);
214       file = ::fopen(putFile.c_str(), "rb");
215       ::curl_easy_setopt(curl, CURLOPT_INFILE, file);
216       //fall through to append GET fields
217     case cmCTest::HTTP_GET:
218       if(fields.size())
219         {
220         url += "?" + fields;
221         }
222       break;
223     default:
224       break;
225     }
226   
227   ::curl_easy_setopt(curl, CURLOPT_URL, url.c_str());
228   ::curl_easy_setopt(curl, CURLOPT_TIMEOUT, timeout);
229   ::curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1);
230
231   //set response options
232   ::curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, HTTPResponseCallback);
233   ::curl_easy_setopt(curl, CURLOPT_FILE, (void *)&response);
234   ::curl_easy_setopt(curl, CURLOPT_FAILONERROR, 1);
235
236   CURLcode res = ::curl_easy_perform(curl);
237
238   ::curl_easy_cleanup(curl);
239   ::curl_global_cleanup();
240   
241   return static_cast<int>(res);
242 }
243 #endif
244
245 //----------------------------------------------------------------------
246 std::string cmCTest::MakeURLSafe(const std::string& str)
247 {
248   cmOStringStream ost;
249   char buffer[10];
250   for ( std::string::size_type pos = 0; pos < str.size(); pos ++ )
251     {
252     unsigned char ch = str[pos];
253     if ( ( ch > 126 || ch < 32 ||
254            ch == '&' ||
255            ch == '%' ||
256            ch == '+' ||
257            ch == '=' ||
258            ch == '@'
259           ) && ch != 9 )
260       {
261       sprintf(buffer, "%02x;", (unsigned int)ch);
262       ost << buffer;
263       }
264     else
265       {
266       ost << ch;
267       }
268     }
269   return ost.str();
270 }
271
272 //----------------------------------------------------------------------------
273 std::string cmCTest::DecodeURL(const std::string& in)
274 {
275   std::string out;
276   for(const char* c = in.c_str(); *c; ++c)
277     {
278     if(*c == '%' && isxdigit(*(c+1)) && isxdigit(*(c+2)))
279       {
280       char buf[3] = {*(c+1), *(c+2), 0};
281       out.append(1, char(strtoul(buf, 0, 16)));
282       c += 2;
283       }
284     else
285       {
286       out.append(1, *c);
287       }
288     }
289   return out;
290 }
291
292 //----------------------------------------------------------------------
293 cmCTest::cmCTest()
294 {
295   this->LabelSummary           = true;
296   this->ParallelLevel          = 1;
297   this->SubmitIndex            = 0;
298   this->Failover               = false;
299   this->BatchJobs              = false;
300   this->ForceNewCTestProcess   = false;
301   this->TomorrowTag            = false;
302   this->Verbose                = false;
303   
304   this->Debug                  = false;
305   this->ShowLineNumbers        = false;
306   this->Quiet                  = false;
307   this->ExtraVerbose           = false;
308   this->ProduceXML             = false;
309   this->ShowOnly               = false;
310   this->RunConfigurationScript = false;
311   this->UseHTTP10              = false;
312   this->PrintLabels            = false;
313   this->CompressTestOutput     = true;
314   this->CompressMemCheckOutput = true;
315   this->TestModel              = cmCTest::EXPERIMENTAL;
316   this->MaxTestNameWidth       = 30;
317   this->InteractiveDebugMode   = true;
318   this->TimeOut                = 0;
319   this->GlobalTimeout          = 0;
320   this->LastStopTimeout        = 24 * 60 * 60;
321   this->CompressXMLFiles       = false;
322   this->CTestConfigFile        = "";
323   this->ScheduleType           = "";
324   this->StopTime               = "";
325   this->NextDayStopTime        = false;
326   this->OutputLogFile          = 0;
327   this->OutputLogFileLastTag   = -1;
328   this->SuppressUpdatingCTestConfiguration = false;
329   this->DartVersion            = 1;
330   this->OutputTestOutputOnTestFailure = false;
331   this->ComputedCompressTestOutput = false;
332   this->ComputedCompressMemCheckOutput = false;
333   if(cmSystemTools::GetEnv("CTEST_OUTPUT_ON_FAILURE"))
334     {
335     this->OutputTestOutputOnTestFailure = true;
336     }
337   this->InitStreams();
338
339   this->Parts[PartStart].SetName("Start");
340   this->Parts[PartUpdate].SetName("Update");
341   this->Parts[PartConfigure].SetName("Configure");
342   this->Parts[PartBuild].SetName("Build");
343   this->Parts[PartTest].SetName("Test");
344   this->Parts[PartCoverage].SetName("Coverage");
345   this->Parts[PartMemCheck].SetName("MemCheck");
346   this->Parts[PartSubmit].SetName("Submit");
347   this->Parts[PartNotes].SetName("Notes");
348   this->Parts[PartExtraFiles].SetName("ExtraFiles");
349   this->Parts[PartUpload].SetName("Upload");
350
351   // Fill the part name-to-id map.
352   for(Part p = PartStart; p != PartCount; p = Part(p+1))
353     {
354     this->PartMap[cmSystemTools::LowerCase(this->Parts[p].GetName())] = p;
355     }
356
357   this->ShortDateFormat        = true;
358
359   this->TestingHandlers["build"]     = new cmCTestBuildHandler;
360   this->TestingHandlers["buildtest"] = new cmCTestBuildAndTestHandler;
361   this->TestingHandlers["coverage"]  = new cmCTestCoverageHandler;
362   this->TestingHandlers["script"]    = new cmCTestScriptHandler;
363   this->TestingHandlers["test"]      = new cmCTestTestHandler;
364   this->TestingHandlers["update"]    = new cmCTestUpdateHandler;
365   this->TestingHandlers["configure"] = new cmCTestConfigureHandler;
366   this->TestingHandlers["memcheck"]  = new cmCTestMemCheckHandler;
367   this->TestingHandlers["submit"]    = new cmCTestSubmitHandler;
368   this->TestingHandlers["upload"]    = new cmCTestUploadHandler;
369
370   cmCTest::t_TestingHandlers::iterator it;
371   for ( it = this->TestingHandlers.begin();
372     it != this->TestingHandlers.end(); ++ it )
373     {
374     it->second->SetCTestInstance(this);
375     }
376
377   // Make sure we can capture the build tool output.
378   cmSystemTools::EnableVSConsoleOutput();
379 }
380
381 //----------------------------------------------------------------------
382 cmCTest::~cmCTest()
383 {
384   cmCTest::t_TestingHandlers::iterator it;
385   for ( it = this->TestingHandlers.begin();
386     it != this->TestingHandlers.end(); ++ it )
387     {
388     delete it->second;
389     it->second = 0;
390     }
391   this->SetOutputLogFileName(0);
392 }
393
394 void cmCTest::SetParallelLevel(int level)
395 {
396   this->ParallelLevel = level < 1 ? 1 : level;
397 }
398
399 //----------------------------------------------------------------------------
400 bool cmCTest::ShouldCompressTestOutput()
401 {
402   if(!this->ComputedCompressTestOutput)
403     {
404     std::string cdashVersion = this->GetCDashVersion();
405     //version >= 1.6?
406     bool cdashSupportsGzip = cmSystemTools::VersionCompare(
407       cmSystemTools::OP_GREATER, cdashVersion.c_str(), "1.6") ||
408       cmSystemTools::VersionCompare(cmSystemTools::OP_EQUAL,
409       cdashVersion.c_str(), "1.6");
410     this->CompressTestOutput &= cdashSupportsGzip;
411     this->ComputedCompressTestOutput = true;
412     }
413   return this->CompressTestOutput;
414 }
415
416 //----------------------------------------------------------------------------
417 bool cmCTest::ShouldCompressMemCheckOutput()
418 {
419   if(!this->ComputedCompressMemCheckOutput)
420     {
421     std::string cdashVersion = this->GetCDashVersion();
422
423     bool compressionSupported = cmSystemTools::VersionCompare(
424       cmSystemTools::OP_GREATER, cdashVersion.c_str(), "1.9.0");
425     this->CompressMemCheckOutput &= compressionSupported;
426     this->ComputedCompressMemCheckOutput = true;
427     }
428   return this->CompressMemCheckOutput;
429 }
430
431 //----------------------------------------------------------------------------
432 std::string cmCTest::GetCDashVersion()
433 {
434 #ifdef CMAKE_BUILD_WITH_CMAKE
435   //First query the server.  If that fails, fall back to the local setting
436   std::string response;
437   std::string url = "http://";
438   url += this->GetCTestConfiguration("DropSite");
439
440   std::string cdashUri = this->GetCTestConfiguration("DropLocation");
441   cdashUri = cdashUri.substr(0, cdashUri.find("/submit.php"));
442
443   int res = 1;
444   if ( ! cdashUri.empty() )
445   {
446     url += cdashUri + "/api/getversion.php";
447     res = cmCTest::HTTPRequest(url, cmCTest::HTTP_GET, response, "", "", 3);
448   }
449
450   return res ? this->GetCTestConfiguration("CDashVersion") : response;
451 #else
452   return this->GetCTestConfiguration("CDashVersion");
453 #endif
454 }
455
456 //----------------------------------------------------------------------------
457 cmCTest::Part cmCTest::GetPartFromName(const char* name)
458 {
459   // Look up by lower-case to make names case-insensitive.
460   std::string lower_name = cmSystemTools::LowerCase(name);
461   PartMapType::const_iterator i = this->PartMap.find(lower_name);
462   if(i != this->PartMap.end())
463     {
464     return i->second;
465     }
466
467   // The string does not name a valid part.
468   return PartCount;
469 }
470
471 //----------------------------------------------------------------------
472 int cmCTest::Initialize(const char* binary_dir, cmCTestStartCommand* command)
473 {
474   cmCTestLog(this, DEBUG, "Here: " << __LINE__ << std::endl);
475   if(!this->InteractiveDebugMode)
476     {
477     this->BlockTestErrorDiagnostics();
478     }
479   else
480     {
481     cmSystemTools::PutEnv("CTEST_INTERACTIVE_DEBUG_MODE=1");
482     }
483
484   this->BinaryDir = binary_dir;
485   cmSystemTools::ConvertToUnixSlashes(this->BinaryDir);
486
487   this->UpdateCTestConfiguration();
488
489   cmCTestLog(this, DEBUG, "Here: " << __LINE__ << std::endl);
490   if ( this->ProduceXML )
491     {
492     cmCTestLog(this, DEBUG, "Here: " << __LINE__ << std::endl);
493     cmCTestLog(this, OUTPUT,
494       "   Site: " << this->GetCTestConfiguration("Site") << std::endl
495       << "   Build name: " << this->GetCTestConfiguration("BuildName")
496       << std::endl);
497     cmCTestLog(this, DEBUG, "Produce XML is on" << std::endl);
498     if ( this->TestModel == cmCTest::NIGHTLY &&
499          this->GetCTestConfiguration("NightlyStartTime").empty() )
500       {
501       cmCTestLog(this, WARNING,
502                  "WARNING: No nightly start time found please set in"
503                  " CTestConfig.cmake or DartConfig.cmake" << std::endl);
504       cmCTestLog(this, DEBUG, "Here: " << __LINE__ << std::endl);
505       return 0;
506       }
507     }
508
509   cmake cm;
510   cmGlobalGenerator gg;
511   gg.SetCMakeInstance(&cm);
512   cmsys::auto_ptr<cmLocalGenerator> lg(gg.CreateLocalGenerator());
513   cmMakefile *mf = lg->GetMakefile();
514   if ( !this->ReadCustomConfigurationFileTree(this->BinaryDir.c_str(), mf) )
515     {
516     cmCTestLog(this, DEBUG, "Cannot find custom configuration file tree"
517       << std::endl);
518     return 0;
519     }
520
521   if ( this->ProduceXML )
522     {
523     // Verify "Testing" directory exists:
524     //
525     std::string testingDir = this->BinaryDir + "/Testing";
526     if ( cmSystemTools::FileExists(testingDir.c_str()) )
527       {
528       if ( !cmSystemTools::FileIsDirectory(testingDir.c_str()) )
529         {
530         cmCTestLog(this, ERROR_MESSAGE, "File " << testingDir
531           << " is in the place of the testing directory" << std::endl);
532         return 0;
533         }
534       }
535     else
536       {
537       if ( !cmSystemTools::MakeDirectory(testingDir.c_str()) )
538         {
539         cmCTestLog(this, ERROR_MESSAGE, "Cannot create directory "
540           << testingDir << std::endl);
541         return 0;
542         }
543       }
544
545     // Create new "TAG" file or read existing one:
546     //
547     bool createNewTag = true;
548     if (command)
549       {
550       createNewTag = command->ShouldCreateNewTag();
551       }
552
553     std::string tagfile = testingDir + "/TAG";
554     std::ifstream tfin(tagfile.c_str());
555     std::string tag;
556
557     if (createNewTag)
558       {
559       time_t tctime = time(0);
560       if ( this->TomorrowTag )
561         {
562         tctime += ( 24 * 60 * 60 );
563         }
564       struct tm *lctime = gmtime(&tctime);
565       if ( tfin && cmSystemTools::GetLineFromStream(tfin, tag) )
566         {
567         int year = 0;
568         int mon = 0;
569         int day = 0;
570         int hour = 0;
571         int min = 0;
572         sscanf(tag.c_str(), "%04d%02d%02d-%02d%02d",
573                &year, &mon, &day, &hour, &min);
574         if ( year != lctime->tm_year + 1900 ||
575              mon != lctime->tm_mon+1 ||
576              day != lctime->tm_mday )
577           {
578           tag = "";
579           }
580         std::string tagmode;
581         if ( cmSystemTools::GetLineFromStream(tfin, tagmode) )
582           {
583           if (tagmode.size() > 4 && !this->Parts[PartStart])
584             {
585             this->TestModel = cmCTest::GetTestModelFromString(tagmode.c_str());
586             }
587           }
588         tfin.close();
589         }
590       if (tag.size() == 0 || (0 != command) || this->Parts[PartStart])
591         {
592         cmCTestLog(this, DEBUG, "TestModel: " << this->GetTestModelString()
593           << std::endl);
594         cmCTestLog(this, DEBUG, "TestModel: " << this->TestModel << std::endl);
595         if ( this->TestModel == cmCTest::NIGHTLY )
596           {
597           lctime = this->GetNightlyTime(
598             this->GetCTestConfiguration("NightlyStartTime"),
599             this->TomorrowTag);
600           }
601         char datestring[100];
602         sprintf(datestring, "%04d%02d%02d-%02d%02d",
603                 lctime->tm_year + 1900,
604                 lctime->tm_mon+1,
605                 lctime->tm_mday,
606                 lctime->tm_hour,
607                 lctime->tm_min);
608         tag = datestring;
609         std::ofstream ofs(tagfile.c_str());
610         if ( ofs )
611           {
612           ofs << tag << std::endl;
613           ofs << this->GetTestModelString() << std::endl;
614           }
615         ofs.close();
616         if ( 0 == command )
617           {
618           cmCTestLog(this, OUTPUT, "Create new tag: " << tag << " - "
619             << this->GetTestModelString() << std::endl);
620           }
621         }
622       }
623     else
624       {
625       if ( tfin )
626         {
627         cmSystemTools::GetLineFromStream(tfin, tag);
628         tfin.close();
629         }
630
631       if ( tag.empty() )
632         {
633         cmCTestLog(this, ERROR_MESSAGE,
634           "Cannot read existing TAG file in " << testingDir
635           << std::endl);
636         return 0;
637         }
638
639       cmCTestLog(this, OUTPUT, "  Use existing tag: " << tag << " - "
640         << this->GetTestModelString() << std::endl);
641       }
642
643     this->CurrentTag = tag;
644     }
645
646   return 1;
647 }
648
649 //----------------------------------------------------------------------
650 bool cmCTest::InitializeFromCommand(cmCTestStartCommand* command)
651 {
652   std::string src_dir
653     = this->GetCTestConfiguration("SourceDirectory").c_str();
654   std::string bld_dir = this->GetCTestConfiguration("BuildDirectory").c_str();
655   this->DartVersion = 1;
656   for(Part p = PartStart; p != PartCount; p = Part(p+1))
657     {
658     this->Parts[p].SubmitFiles.clear();
659     }
660
661   cmMakefile* mf = command->GetMakefile();
662   std::string fname;
663
664   std::string src_dir_fname = src_dir;
665   src_dir_fname += "/CTestConfig.cmake";
666   cmSystemTools::ConvertToUnixSlashes(src_dir_fname);
667
668   std::string bld_dir_fname = bld_dir;
669   bld_dir_fname += "/CTestConfig.cmake";
670   cmSystemTools::ConvertToUnixSlashes(bld_dir_fname);
671
672   if ( cmSystemTools::FileExists(bld_dir_fname.c_str()) )
673     {
674     fname = bld_dir_fname;
675     }
676   else if ( cmSystemTools::FileExists(src_dir_fname.c_str()) )
677     {
678     fname = src_dir_fname;
679     }
680
681   if ( !fname.empty() )
682     {
683     cmCTestLog(this, OUTPUT, "   Reading ctest configuration file: "
684       << fname.c_str() << std::endl);
685     bool readit = mf->ReadListFile(mf->GetCurrentListFile(),
686       fname.c_str() );
687     if(!readit)
688       {
689       std::string m = "Could not find include file: ";
690       m += fname;
691       command->SetError(m.c_str());
692       return false;
693       }
694     }
695   else
696     {
697     cmCTestLog(this, WARNING,
698       "Cannot locate CTest configuration: in BuildDirectory: "
699       << bld_dir_fname.c_str() << std::endl);
700     cmCTestLog(this, WARNING,
701       "Cannot locate CTest configuration: in SourceDirectory: "
702       << src_dir_fname.c_str() << std::endl);
703     }
704
705   this->SetCTestConfigurationFromCMakeVariable(mf, "NightlyStartTime",
706     "CTEST_NIGHTLY_START_TIME");
707   this->SetCTestConfigurationFromCMakeVariable(mf, "Site", "CTEST_SITE");
708   this->SetCTestConfigurationFromCMakeVariable(mf, "BuildName",
709     "CTEST_BUILD_NAME");
710   const char* dartVersion = mf->GetDefinition("CTEST_DART_SERVER_VERSION");
711   if ( dartVersion )
712     {
713     this->DartVersion = atoi(dartVersion);
714     if ( this->DartVersion < 0 )
715       {
716       cmCTestLog(this, ERROR_MESSAGE, "Invalid Dart server version: "
717         << dartVersion << ". Please specify the version number."
718         << std::endl);
719       return false;
720       }
721     }
722
723   if ( !this->Initialize(bld_dir.c_str(), command) )
724     {
725     return false;
726     }
727   cmCTestLog(this, OUTPUT, "   Use " << this->GetTestModelString()
728     << " tag: " << this->GetCurrentTag() << std::endl);
729   return true;
730 }
731
732
733 //----------------------------------------------------------------------
734 bool cmCTest::UpdateCTestConfiguration()
735 {
736   if ( this->SuppressUpdatingCTestConfiguration )
737     {
738     return true;
739     }
740   std::string fileName = this->CTestConfigFile;
741   if ( fileName.empty() )
742     {
743     fileName = this->BinaryDir + "/CTestConfiguration.ini";
744     if ( !cmSystemTools::FileExists(fileName.c_str()) )
745       {
746       fileName = this->BinaryDir + "/DartConfiguration.tcl";
747       }
748     }
749   cmCTestLog(this, HANDLER_VERBOSE_OUTPUT, "UpdateCTestConfiguration  from :"
750              << fileName.c_str() << "\n");
751   if ( !cmSystemTools::FileExists(fileName.c_str()) )
752     {
753     // No need to exit if we are not producing XML
754     if ( this->ProduceXML )
755       {
756       cmCTestLog(this, ERROR_MESSAGE, "Cannot find file: " << fileName.c_str()
757         << std::endl);
758       return false;
759       }
760     }
761   else
762     {
763     cmCTestLog(this, HANDLER_VERBOSE_OUTPUT, "Parse Config file:" 
764                << fileName.c_str() << "\n");
765     // parse the dart test file
766     std::ifstream fin(fileName.c_str());
767
768     if(!fin)
769       {
770       return false;
771       }
772
773     char buffer[1024];
774     while ( fin )
775       {
776       buffer[0] = 0;
777       fin.getline(buffer, 1023);
778       buffer[1023] = 0;
779       std::string line = cmCTest::CleanString(buffer);
780       if(line.size() == 0)
781         {
782         continue;
783         }
784       while ( fin && (line[line.size()-1] == '\\') )
785         {
786         line = line.substr(0, line.size()-1);
787         buffer[0] = 0;
788         fin.getline(buffer, 1023);
789         buffer[1023] = 0;
790         line += cmCTest::CleanString(buffer);
791         }
792       if ( line[0] == '#' )
793         {
794         continue;
795         }
796       std::string::size_type cpos = line.find_first_of(":");
797       if ( cpos == line.npos )
798         {
799         continue;
800         }
801       std::string key = line.substr(0, cpos);
802       std::string value
803         = cmCTest::CleanString(line.substr(cpos+1, line.npos));
804       this->CTestConfiguration[key] = value;
805       }
806     fin.close();
807     }
808   if ( !this->GetCTestConfiguration("BuildDirectory").empty() )
809     {
810     this->BinaryDir = this->GetCTestConfiguration("BuildDirectory");
811     cmSystemTools::ChangeDirectory(this->BinaryDir.c_str());
812     }
813   this->TimeOut = atoi(this->GetCTestConfiguration("TimeOut").c_str());
814   if ( this->ProduceXML )
815     {
816     this->CompressXMLFiles = cmSystemTools::IsOn(
817       this->GetCTestConfiguration("CompressSubmission").c_str());
818     }
819   return true;
820 }
821
822 //----------------------------------------------------------------------
823 void cmCTest::BlockTestErrorDiagnostics()
824 {
825   cmSystemTools::PutEnv("DART_TEST_FROM_DART=1");
826   cmSystemTools::PutEnv("DASHBOARD_TEST_FROM_CTEST=" CMake_VERSION);
827 #if defined(_WIN32)
828   SetErrorMode(SEM_FAILCRITICALERRORS | SEM_NOGPFAULTERRORBOX);
829 #elif defined(__BEOS__) || defined(__HAIKU__)
830   disable_debugger(1);
831 #endif
832 }
833
834 //----------------------------------------------------------------------
835 void cmCTest::SetTestModel(int mode)
836 {
837   this->InteractiveDebugMode = false;
838   this->TestModel = mode;
839 }
840
841 //----------------------------------------------------------------------
842 bool cmCTest::SetTest(const char* ttype, bool report)
843 {
844   if ( cmSystemTools::LowerCase(ttype) == "all" )
845     {
846     for(Part p = PartStart; p != PartCount; p = Part(p+1))
847       {
848       this->Parts[p].Enable();
849       }
850     return true;
851     }
852   Part p = this->GetPartFromName(ttype);
853   if(p != PartCount)
854     {
855     this->Parts[p].Enable();
856     return true;
857     }
858   else
859     {
860     if ( report )
861       {
862       cmCTestLog(this, ERROR_MESSAGE, "Don't know about test \"" << ttype
863         << "\" yet..." << std::endl);
864       }
865     return false;
866     }
867 }
868
869 //----------------------------------------------------------------------
870 void cmCTest::Finalize()
871 {
872 }
873
874 //----------------------------------------------------------------------
875 bool cmCTest::OpenOutputFile(const std::string& path,
876                      const std::string& name, cmGeneratedFileStream& stream,
877                      bool compress)
878 {
879   std::string testingDir = this->BinaryDir + "/Testing";
880   if ( path.size() > 0 )
881     {
882     testingDir += "/" + path;
883     }
884   if ( cmSystemTools::FileExists(testingDir.c_str()) )
885     {
886     if ( !cmSystemTools::FileIsDirectory(testingDir.c_str()) )
887       {
888       cmCTestLog(this, ERROR_MESSAGE, "File " << testingDir
889                 << " is in the place of the testing directory"
890                 << std::endl);
891       return false;
892       }
893     }
894   else
895     {
896     if ( !cmSystemTools::MakeDirectory(testingDir.c_str()) )
897       {
898       cmCTestLog(this, ERROR_MESSAGE, "Cannot create directory " << testingDir
899                 << std::endl);
900       return false;
901       }
902     }
903   std::string filename = testingDir + "/" + name;
904   stream.Open(filename.c_str());
905   if( !stream )
906     {
907     cmCTestLog(this, ERROR_MESSAGE, "Problem opening file: " << filename
908       << std::endl);
909     return false;
910     }
911   if ( compress )
912     {
913     if ( this->CompressXMLFiles )
914       {
915       stream.SetCompression(true);
916       }
917     }
918   return true;
919 }
920
921 //----------------------------------------------------------------------
922 bool cmCTest::AddIfExists(Part part, const char* file)
923 {
924   if ( this->CTestFileExists(file) )
925     {
926     this->AddSubmitFile(part, file);
927     }
928   else
929     {
930     std::string name = file;
931     name += ".gz";
932     if ( this->CTestFileExists(name.c_str()) )
933       {
934       this->AddSubmitFile(part, file);
935       }
936     else
937       {
938       return false;
939       }
940     }
941   return true;
942 }
943
944 //----------------------------------------------------------------------
945 bool cmCTest::CTestFileExists(const std::string& filename)
946 {
947   std::string testingDir = this->BinaryDir + "/Testing/" + 
948     this->CurrentTag + "/" + filename;
949   return cmSystemTools::FileExists(testingDir.c_str());
950 }
951
952 //----------------------------------------------------------------------
953 cmCTestGenericHandler* cmCTest::GetInitializedHandler(const char* handler)
954 {
955   cmCTest::t_TestingHandlers::iterator it = 
956     this->TestingHandlers.find(handler);
957   if ( it == this->TestingHandlers.end() )
958     {
959     return 0;
960     }
961   it->second->Initialize();
962   return it->second;
963 }
964
965 //----------------------------------------------------------------------
966 cmCTestGenericHandler* cmCTest::GetHandler(const char* handler)
967 {
968   cmCTest::t_TestingHandlers::iterator it = 
969     this->TestingHandlers.find(handler);
970   if ( it == this->TestingHandlers.end() )
971     {
972     return 0;
973     }
974   return it->second;
975 }
976
977 //----------------------------------------------------------------------
978 int cmCTest::ExecuteHandler(const char* shandler)
979 {
980   cmCTestGenericHandler* handler = this->GetHandler(shandler);
981   if ( !handler )
982     {
983     return -1;
984     }
985   handler->Initialize();
986   return handler->ProcessHandler();
987 }
988
989 //----------------------------------------------------------------------
990 int cmCTest::ProcessTests()
991 {
992   int res = 0;
993   bool notest = true;
994   int update_count = 0;
995
996   for(Part p = PartStart; notest && p != PartCount; p = Part(p+1))
997     {
998     notest = !this->Parts[p];
999     }
1000   if (this->Parts[PartUpdate] &&
1001       (this->GetRemainingTimeAllowed() - 120 > 0))
1002     {
1003     cmCTestGenericHandler* uphandler = this->GetHandler("update");
1004     uphandler->SetPersistentOption("SourceDirectory",
1005       this->GetCTestConfiguration("SourceDirectory").c_str());
1006     update_count = uphandler->ProcessHandler();
1007     if ( update_count < 0 )
1008       {
1009       res |= cmCTest::UPDATE_ERRORS;
1010       }
1011     }
1012   if ( this->TestModel == cmCTest::CONTINUOUS && !update_count )
1013     {
1014     return 0;
1015     }
1016   if (this->Parts[PartConfigure] &&
1017       (this->GetRemainingTimeAllowed() - 120 > 0))
1018     {
1019     if (this->GetHandler("configure")->ProcessHandler() < 0)
1020       {
1021       res |= cmCTest::CONFIGURE_ERRORS;
1022       }
1023     }
1024   if (this->Parts[PartBuild] &&
1025       (this->GetRemainingTimeAllowed() - 120 > 0))
1026     {
1027     this->UpdateCTestConfiguration();
1028     if (this->GetHandler("build")->ProcessHandler() < 0)
1029       {
1030       res |= cmCTest::BUILD_ERRORS;
1031       }
1032     }
1033   if ((this->Parts[PartTest] || notest) &&
1034       (this->GetRemainingTimeAllowed() - 120 > 0))
1035     {
1036     this->UpdateCTestConfiguration();
1037     if (this->GetHandler("test")->ProcessHandler() < 0)
1038       {
1039       res |= cmCTest::TEST_ERRORS;
1040       }
1041     }
1042   if (this->Parts[PartCoverage] &&
1043       (this->GetRemainingTimeAllowed() - 120 > 0))
1044     {
1045     this->UpdateCTestConfiguration();
1046     if (this->GetHandler("coverage")->ProcessHandler() < 0)
1047       {
1048       res |= cmCTest::COVERAGE_ERRORS;
1049       }
1050     }
1051   if (this->Parts[PartMemCheck] &&
1052       (this->GetRemainingTimeAllowed() - 120 > 0))
1053     {
1054     this->UpdateCTestConfiguration();
1055     if (this->GetHandler("memcheck")->ProcessHandler() < 0)
1056       {
1057       res |= cmCTest::MEMORY_ERRORS;
1058       }
1059     }
1060   if ( !notest )
1061     {
1062     std::string notes_dir = this->BinaryDir + "/Testing/Notes";
1063     if ( cmSystemTools::FileIsDirectory(notes_dir.c_str()) )
1064       {
1065       cmsys::Directory d;
1066       d.Load(notes_dir.c_str());
1067       unsigned long kk;
1068       for ( kk = 0; kk < d.GetNumberOfFiles(); kk ++ )
1069         {
1070         const char* file = d.GetFile(kk);
1071         std::string fullname = notes_dir + "/" + file;
1072         if ( cmSystemTools::FileExists(fullname.c_str()) &&
1073           !cmSystemTools::FileIsDirectory(fullname.c_str()) )
1074           {
1075           if ( this->NotesFiles.size() > 0 )
1076             {
1077             this->NotesFiles += ";";
1078             }
1079           this->NotesFiles += fullname;
1080           this->Parts[PartNotes].Enable();
1081           }
1082         }
1083       }
1084     }
1085   if (this->Parts[PartNotes])
1086     {
1087     this->UpdateCTestConfiguration();
1088     if ( this->NotesFiles.size() )
1089       {
1090       this->GenerateNotesFile(this->NotesFiles.c_str());
1091       }
1092     }
1093   if (this->Parts[PartSubmit])
1094     {
1095     this->UpdateCTestConfiguration();
1096     if (this->GetHandler("submit")->ProcessHandler() < 0)
1097       {
1098       res |= cmCTest::SUBMIT_ERRORS;
1099       }
1100     }
1101   if ( res != 0 )
1102     {
1103     cmCTestLog(this, ERROR_MESSAGE, "Errors while running CTest"
1104                  << std::endl);
1105     }
1106   return res;
1107 }
1108
1109 //----------------------------------------------------------------------
1110 std::string cmCTest::GetTestModelString()
1111 {
1112   if ( !this->SpecificTrack.empty() )
1113     {
1114     return this->SpecificTrack;
1115     }
1116   switch ( this->TestModel )
1117     {
1118   case cmCTest::NIGHTLY:
1119     return "Nightly";
1120   case cmCTest::CONTINUOUS:
1121     return "Continuous";
1122     }
1123   return "Experimental";
1124 }
1125
1126 //----------------------------------------------------------------------
1127 int cmCTest::GetTestModelFromString(const char* str)
1128 {
1129   if ( !str )
1130     {
1131     return cmCTest::EXPERIMENTAL;
1132     }
1133   std::string rstr = cmSystemTools::LowerCase(str);
1134   if ( strncmp(rstr.c_str(), "cont", 4) == 0 )
1135     {
1136     return cmCTest::CONTINUOUS;
1137     }
1138   if ( strncmp(rstr.c_str(), "nigh", 4) == 0 )
1139     {
1140     return cmCTest::NIGHTLY;
1141     }
1142   return cmCTest::EXPERIMENTAL;
1143 }
1144
1145 //######################################################################
1146 //######################################################################
1147 //######################################################################
1148 //######################################################################
1149
1150 //----------------------------------------------------------------------
1151 int cmCTest::RunMakeCommand(const char* command, std::string* output,
1152   int* retVal, const char* dir, int timeout, std::ofstream& ofs)
1153 {
1154   // First generate the command and arguments
1155   std::vector<cmStdString> args = cmSystemTools::ParseArguments(command);
1156
1157   if(args.size() < 1)
1158     {
1159     return false;
1160     }
1161
1162   std::vector<const char*> argv;
1163   for(std::vector<cmStdString>::const_iterator a = args.begin();
1164     a != args.end(); ++a)
1165     {
1166     argv.push_back(a->c_str());
1167     }
1168   argv.push_back(0);
1169
1170   if ( output )
1171     {
1172     *output = "";
1173     }
1174
1175   cmCTestLog(this, HANDLER_VERBOSE_OUTPUT, "Run command:");
1176   std::vector<const char*>::iterator ait;
1177   for ( ait = argv.begin(); ait != argv.end() && *ait; ++ ait )
1178     {
1179     cmCTestLog(this, HANDLER_VERBOSE_OUTPUT, " \"" << *ait << "\"");
1180     }
1181   cmCTestLog(this, HANDLER_VERBOSE_OUTPUT, std::endl);
1182
1183   // Now create process object
1184   cmsysProcess* cp = cmsysProcess_New();
1185   cmsysProcess_SetCommand(cp, &*argv.begin());
1186   cmsysProcess_SetWorkingDirectory(cp, dir);
1187   cmsysProcess_SetOption(cp, cmsysProcess_Option_HideWindow, 1);
1188   cmsysProcess_SetTimeout(cp, timeout);
1189   cmsysProcess_Execute(cp);
1190
1191   // Initialize tick's
1192   std::string::size_type tick = 0;
1193   std::string::size_type tick_len = 1024;
1194   std::string::size_type tick_line_len = 50;
1195
1196   char* data;
1197   int length;
1198   cmCTestLog(this, HANDLER_OUTPUT,
1199     "   Each . represents " << tick_len << " bytes of output" << std::endl
1200     << "    " << std::flush);
1201   while(cmsysProcess_WaitForData(cp, &data, &length, 0))
1202     {
1203     if ( output )
1204       {
1205       for(int cc =0; cc < length; ++cc)
1206         {
1207         if(data[cc] == 0)
1208           {
1209           data[cc] = '\n';
1210           }
1211         }
1212
1213       output->append(data, length);
1214       while ( output->size() > (tick * tick_len) )
1215         {
1216         tick ++;
1217         cmCTestLog(this, HANDLER_OUTPUT, "." << std::flush);
1218         if ( tick % tick_line_len == 0 && tick > 0 )
1219           {
1220           cmCTestLog(this, HANDLER_OUTPUT, "  Size: "
1221             << int((double(output->size()) / 1024.0) + 1) << "K" << std::endl
1222             << "    " << std::flush);
1223           }
1224         }
1225       }
1226     cmCTestLog(this, HANDLER_VERBOSE_OUTPUT, cmCTestLogWrite(data, length));
1227     if ( ofs )
1228       {
1229       ofs << cmCTestLogWrite(data, length);
1230       }
1231     }
1232   cmCTestLog(this, OUTPUT, " Size of output: "
1233     << int(double(output->size()) / 1024.0) << "K" << std::endl);
1234
1235   cmsysProcess_WaitForExit(cp, 0);
1236
1237   int result = cmsysProcess_GetState(cp);
1238
1239   if(result == cmsysProcess_State_Exited)
1240     {
1241     *retVal = cmsysProcess_GetExitValue(cp);
1242     cmCTestLog(this, HANDLER_VERBOSE_OUTPUT, "Command exited with the value: "
1243       << *retVal << std::endl);
1244     }
1245   else if(result == cmsysProcess_State_Exception)
1246     {
1247     *retVal = cmsysProcess_GetExitException(cp);
1248     cmCTestLog(this, WARNING, "There was an exception: " << *retVal
1249       << std::endl);
1250     }
1251   else if(result == cmsysProcess_State_Expired)
1252     {
1253     cmCTestLog(this, WARNING, "There was a timeout" << std::endl);
1254     }
1255   else if(result == cmsysProcess_State_Error)
1256     {
1257     *output += "\n*** ERROR executing: ";
1258     *output += cmsysProcess_GetErrorString(cp);
1259     *output += "\n***The build process failed.";
1260     cmCTestLog(this, ERROR_MESSAGE, "There was an error: "
1261       << cmsysProcess_GetErrorString(cp) << std::endl);
1262     }
1263
1264   cmsysProcess_Delete(cp);
1265
1266   return result;
1267 }
1268
1269 //######################################################################
1270 //######################################################################
1271 //######################################################################
1272 //######################################################################
1273
1274 //----------------------------------------------------------------------
1275 int cmCTest::RunTest(std::vector<const char*> argv,
1276                      std::string* output, int *retVal,
1277                      std::ostream* log, double testTimeOut,
1278                      std::vector<std::string>* environment)
1279 {
1280   bool modifyEnv = (environment && environment->size()>0);
1281
1282   // determine how much time we have
1283   double timeout = this->GetRemainingTimeAllowed() - 120;
1284   if (this->TimeOut > 0 && this->TimeOut < timeout)
1285     {
1286     timeout = this->TimeOut;
1287     }
1288   if (testTimeOut > 0
1289       && testTimeOut < this->GetRemainingTimeAllowed())
1290     {
1291     timeout = testTimeOut;
1292     }
1293
1294   // always have at least 1 second if we got to here
1295   if (timeout <= 0)
1296     {
1297     timeout = 1;
1298     }
1299   cmCTestLog(this, HANDLER_VERBOSE_OUTPUT,
1300              "Test timeout computed to be: " << timeout << "\n");
1301   if(cmSystemTools::SameFile(argv[0], this->CTestSelf.c_str()) &&
1302      !this->ForceNewCTestProcess)
1303     {
1304     cmCTest inst;
1305     inst.ConfigType = this->ConfigType;
1306     inst.TimeOut = timeout;
1307
1308     // Capture output of the child ctest.
1309     cmOStringStream oss;
1310     inst.SetStreams(&oss, &oss);
1311
1312     std::vector<std::string> args;
1313     for(unsigned int i =0; i < argv.size(); ++i)
1314       {
1315       if(argv[i])
1316         {
1317         // make sure we pass the timeout in for any build and test 
1318         // invocations. Since --build-generator is required this is a 
1319         // good place to check for it, and to add the arguments in
1320         if (strcmp(argv[i],"--build-generator") == 0 && timeout > 0)
1321           {
1322           args.push_back("--test-timeout");
1323           cmOStringStream msg;
1324           msg << timeout;
1325           args.push_back(msg.str());
1326           }
1327         args.push_back(argv[i]);
1328         }
1329       }
1330     if ( log )
1331       {
1332       *log << "* Run internal CTest" << std::endl;
1333       }
1334     std::string oldpath = cmSystemTools::GetCurrentWorkingDirectory();
1335
1336     cmsys::auto_ptr<cmSystemTools::SaveRestoreEnvironment> saveEnv;
1337     if (modifyEnv)
1338       {
1339       saveEnv.reset(new cmSystemTools::SaveRestoreEnvironment);
1340       cmSystemTools::AppendEnv(*environment);
1341       }
1342
1343     *retVal = inst.Run(args, output);
1344     *output += oss.str();
1345     if ( log )
1346       {
1347       *log << output->c_str();
1348       }
1349     cmSystemTools::ChangeDirectory(oldpath.c_str());
1350
1351     cmCTestLog(this, HANDLER_VERBOSE_OUTPUT,
1352       "Internal cmCTest object used to run test." << std::endl
1353       <<  *output << std::endl);
1354
1355     return cmsysProcess_State_Exited;
1356     }
1357   std::vector<char> tempOutput;
1358   if ( output )
1359     {
1360     *output = "";
1361     }
1362
1363   cmsys::auto_ptr<cmSystemTools::SaveRestoreEnvironment> saveEnv;
1364   if (modifyEnv)
1365     {
1366     saveEnv.reset(new cmSystemTools::SaveRestoreEnvironment);
1367     cmSystemTools::AppendEnv(*environment);
1368     }
1369
1370   cmsysProcess* cp = cmsysProcess_New();
1371   cmsysProcess_SetCommand(cp, &*argv.begin());
1372   cmCTestLog(this, DEBUG, "Command is: " << argv[0] << std::endl);
1373   if(cmSystemTools::GetRunCommandHideConsole())
1374     {
1375     cmsysProcess_SetOption(cp, cmsysProcess_Option_HideWindow, 1);
1376     }
1377
1378   cmsysProcess_SetTimeout(cp, timeout);
1379   cmsysProcess_Execute(cp);
1380
1381   char* data;
1382   int length;
1383   while(cmsysProcess_WaitForData(cp, &data, &length, 0))
1384     {
1385     if ( output )
1386       {
1387       tempOutput.insert(tempOutput.end(), data, data+length);
1388       }
1389     cmCTestLog(this, HANDLER_VERBOSE_OUTPUT, cmCTestLogWrite(data, length));
1390     if ( log )
1391       {
1392       log->write(data, length);
1393       }
1394     }
1395
1396   cmsysProcess_WaitForExit(cp, 0);
1397   if(output && tempOutput.begin() != tempOutput.end())
1398     {
1399     output->append(&*tempOutput.begin(), tempOutput.size());
1400     }
1401   cmCTestLog(this, HANDLER_VERBOSE_OUTPUT, "-- Process completed"
1402     << std::endl);
1403
1404   int result = cmsysProcess_GetState(cp);
1405
1406   if(result == cmsysProcess_State_Exited)
1407     {
1408     *retVal = cmsysProcess_GetExitValue(cp);
1409     if(*retVal != 0 && this->OutputTestOutputOnTestFailure)
1410       {
1411         OutputTestErrors(tempOutput);
1412       }
1413     }
1414   else if(result == cmsysProcess_State_Exception)
1415     {
1416     if(this->OutputTestOutputOnTestFailure)
1417       {
1418         OutputTestErrors(tempOutput);
1419       }
1420     *retVal = cmsysProcess_GetExitException(cp);
1421     std::string outerr = "\n*** Exception executing: ";
1422     outerr += cmsysProcess_GetExceptionString(cp);
1423     *output += outerr;
1424     cmCTestLog(this, HANDLER_VERBOSE_OUTPUT, outerr.c_str() << std::endl
1425       << std::flush);
1426     }
1427   else if(result == cmsysProcess_State_Error)
1428     {
1429     std::string outerr = "\n*** ERROR executing: ";
1430     outerr += cmsysProcess_GetErrorString(cp);
1431     *output += outerr;
1432     cmCTestLog(this, HANDLER_VERBOSE_OUTPUT, outerr.c_str() << std::endl
1433       << std::flush);
1434     }
1435   cmsysProcess_Delete(cp);
1436
1437   return result;
1438 }
1439
1440 //----------------------------------------------------------------------
1441 std::string cmCTest::SafeBuildIdField(const std::string& value)
1442 {
1443   std::string safevalue(value);
1444
1445   if (safevalue != "")
1446     {
1447     // Disallow non-filename and non-space whitespace characters.
1448     // If they occur, replace them with ""
1449     //
1450     const char *disallowed = "\\/:*?\"<>|\n\r\t\f\v";
1451
1452     if (safevalue.find_first_of(disallowed) != value.npos)
1453       {
1454       std::string::size_type i = 0;
1455       std::string::size_type n = strlen(disallowed);
1456       char replace[2];
1457       replace[1] = 0;
1458
1459       for (i= 0; i<n; ++i)
1460         {
1461         replace[0] = disallowed[i];
1462         cmSystemTools::ReplaceString(safevalue, replace, "");
1463         }
1464       }
1465
1466     safevalue = cmXMLSafe(safevalue).str();
1467     }
1468
1469   if (safevalue == "")
1470     {
1471     safevalue = "(empty)";
1472     }
1473
1474   return safevalue;
1475 }
1476
1477 //----------------------------------------------------------------------
1478 void cmCTest::StartXML(std::ostream& ostr, bool append)
1479 {
1480   if(this->CurrentTag.empty())
1481     {
1482     cmCTestLog(this, ERROR_MESSAGE,
1483                "Current Tag empty, this may mean"
1484                " NightlStartTime was not set correctly." << std::endl);
1485     cmSystemTools::SetFatalErrorOccured();
1486     }
1487
1488   // find out about the system
1489   cmsys::SystemInformation info;
1490   info.RunCPUCheck();
1491   info.RunOSCheck();
1492   info.RunMemoryCheck();
1493
1494   std::string buildname = cmCTest::SafeBuildIdField(
1495     this->GetCTestConfiguration("BuildName"));
1496   std::string stamp = cmCTest::SafeBuildIdField(
1497     this->CurrentTag + "-" + this->GetTestModelString());
1498   std::string site = cmCTest::SafeBuildIdField(
1499     this->GetCTestConfiguration("Site"));
1500
1501   ostr << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
1502        << "<Site BuildName=\"" << buildname << "\"\n"
1503        << "\tBuildStamp=\"" << stamp << "\"\n"
1504        << "\tName=\"" << site << "\"\n"
1505        << "\tGenerator=\"ctest-" << cmVersion::GetCMakeVersion() << "\"\n"
1506        << (append? "\tAppend=\"true\"\n":"")
1507        << "\tCompilerName=\"" << this->GetCTestConfiguration("Compiler")
1508        << "\"\n"
1509 #ifdef _COMPILER_VERSION
1510        << "\tCompilerVersion=\"_COMPILER_VERSION\"\n"
1511 #endif
1512        << "\tOSName=\"" << info.GetOSName() << "\"\n"
1513        << "\tHostname=\"" << info.GetHostname() << "\"\n"
1514        << "\tOSRelease=\"" << info.GetOSRelease() << "\"\n"
1515        << "\tOSVersion=\"" << info.GetOSVersion() << "\"\n"
1516        << "\tOSPlatform=\"" << info.GetOSPlatform() << "\"\n"
1517        << "\tIs64Bits=\"" << info.Is64Bits() << "\"\n"
1518        << "\tVendorString=\"" << info.GetVendorString() << "\"\n"
1519        << "\tVendorID=\"" << info.GetVendorID() << "\"\n"
1520        << "\tFamilyID=\"" << info.GetFamilyID() << "\"\n"
1521        << "\tModelID=\"" << info.GetModelID() << "\"\n"
1522        << "\tProcessorCacheSize=\"" << info.GetProcessorCacheSize() << "\"\n"
1523        << "\tNumberOfLogicalCPU=\"" << info.GetNumberOfLogicalCPU() << "\"\n"
1524        << "\tNumberOfPhysicalCPU=\""<< info.GetNumberOfPhysicalCPU() << "\"\n"
1525        << "\tTotalVirtualMemory=\"" << info.GetTotalVirtualMemory() << "\"\n"
1526        << "\tTotalPhysicalMemory=\""<< info.GetTotalPhysicalMemory() << "\"\n"
1527        << "\tLogicalProcessorsPerPhysical=\"" 
1528        << info.GetLogicalProcessorsPerPhysical() << "\"\n"
1529        << "\tProcessorClockFrequency=\"" 
1530        << info.GetProcessorClockFrequency() << "\"\n" 
1531        << ">" << std::endl;
1532   this->AddSiteProperties(ostr); 
1533 }
1534
1535 //----------------------------------------------------------------------
1536 void cmCTest::AddSiteProperties(std::ostream& ostr)
1537 {
1538   cmCTestScriptHandler* ch = 
1539     static_cast<cmCTestScriptHandler*>(this->GetHandler("script"));
1540   cmake* cm =  ch->GetCMake();
1541   // if no CMake then this is the old style script and props like
1542   // this will not work anyway.
1543   if(!cm)
1544     {
1545     return;
1546     }
1547   // This code should go when cdash is changed to use labels only
1548   const char* subproject = cm->GetProperty("SubProject", cmProperty::GLOBAL);
1549   if(subproject)
1550     { 
1551     ostr << "<Subproject name=\"" << subproject << "\">\n";
1552     const char* labels = 
1553       ch->GetCMake()->GetProperty("SubProjectLabels", cmProperty::GLOBAL);
1554     if(labels)
1555       {
1556       ostr << "  <Labels>\n";
1557       std::string l = labels;
1558       std::vector<std::string> args;
1559       cmSystemTools::ExpandListArgument(l, args);
1560       for(std::vector<std::string>::iterator i = args.begin();
1561           i != args.end(); ++i)
1562         {
1563         ostr << "    <Label>" << i->c_str() << "</Label>\n";
1564         }
1565       ostr << "  </Labels>\n";
1566       }
1567     ostr << "</Subproject>\n";
1568     }
1569   
1570   // This code should stay when cdash only does label based sub-projects
1571   const char* label = cm->GetProperty("Label", cmProperty::GLOBAL);
1572   if(label)
1573     { 
1574     ostr << "<Labels>\n";
1575     ostr << "  <Label>" << label << "</Label>\n";
1576     ostr << "</Labels>\n";
1577     }
1578 }
1579
1580
1581 //----------------------------------------------------------------------
1582 void cmCTest::EndXML(std::ostream& ostr)
1583 {
1584   ostr << "</Site>" << std::endl;
1585 }
1586
1587 //----------------------------------------------------------------------
1588 int cmCTest::GenerateCTestNotesOutput(std::ostream& os,
1589   const cmCTest::VectorOfStrings& files)
1590 {
1591   cmCTest::VectorOfStrings::const_iterator it;
1592   os << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
1593      << "<?xml-stylesheet type=\"text/xsl\" "
1594     "href=\"Dart/Source/Server/XSL/Build.xsl "
1595     "<file:///Dart/Source/Server/XSL/Build.xsl> \"?>\n"
1596      << "<Site BuildName=\"" << this->GetCTestConfiguration("BuildName")
1597      << "\" BuildStamp=\""
1598      << this->CurrentTag << "-" << this->GetTestModelString() << "\" Name=\""
1599      << this->GetCTestConfiguration("Site") << "\" Generator=\"ctest"
1600      << cmVersion::GetCMakeVersion()
1601      << "\">\n";
1602   this->AddSiteProperties(os);
1603   os << "<Notes>" << std::endl;
1604
1605   for ( it = files.begin(); it != files.end(); it ++ )
1606     {
1607     cmCTestLog(this, OUTPUT, "\tAdd file: " << it->c_str() << std::endl);
1608     std::string note_time = this->CurrentTime();
1609     os << "<Note Name=\"" << cmXMLSafe(*it) << "\">\n"
1610       << "<Time>" << cmSystemTools::GetTime() << "</Time>\n"
1611       << "<DateTime>" << note_time << "</DateTime>\n"
1612       << "<Text>" << std::endl;
1613     std::ifstream ifs(it->c_str());
1614     if ( ifs )
1615       {
1616       std::string line;
1617       while ( cmSystemTools::GetLineFromStream(ifs, line) )
1618         {
1619         os << cmXMLSafe(line) << std::endl;
1620         }
1621       ifs.close();
1622       }
1623     else
1624       {
1625       os << "Problem reading file: " << it->c_str() << std::endl;
1626       cmCTestLog(this, ERROR_MESSAGE, "Problem reading file: " << it->c_str()
1627         << " while creating notes" << std::endl);
1628       }
1629     os << "</Text>\n"
1630       << "</Note>" << std::endl;
1631     }
1632   os << "</Notes>\n"
1633     << "</Site>" << std::endl;
1634   return 1;
1635 }
1636
1637 //----------------------------------------------------------------------
1638 int cmCTest::GenerateNotesFile(const std::vector<cmStdString> &files)
1639 {
1640   cmGeneratedFileStream ofs;
1641   if ( !this->OpenOutputFile(this->CurrentTag, "Notes.xml", ofs) )
1642     {
1643     cmCTestLog(this, ERROR_MESSAGE, "Cannot open notes file" << std::endl);
1644     return 1;
1645     }
1646
1647   this->GenerateCTestNotesOutput(ofs, files);
1648   return 0;
1649 }
1650
1651 //----------------------------------------------------------------------
1652 int cmCTest::GenerateNotesFile(const char* cfiles)
1653 {
1654   if ( !cfiles )
1655     {
1656     return 1;
1657     }
1658
1659   std::vector<cmStdString> files;
1660
1661   cmCTestLog(this, OUTPUT, "Create notes file" << std::endl);
1662
1663   files = cmSystemTools::SplitString(cfiles, ';');
1664   if ( files.size() == 0 )
1665     {
1666     return 1;
1667     }
1668
1669   return this->GenerateNotesFile(files);
1670 }
1671
1672 //----------------------------------------------------------------------
1673 std::string cmCTest::Base64GzipEncodeFile(std::string file)
1674 {
1675   std::string tarFile = file + "_temp.tar.gz";
1676   std::vector<cmStdString> files;
1677   files.push_back(file);
1678
1679   if(!cmSystemTools::CreateTar(tarFile.c_str(), files, true, false, false))
1680     {
1681     cmCTestLog(this, ERROR_MESSAGE, "Error creating tar while "
1682       "encoding file: " << file << std::endl);
1683     return "";
1684     }
1685   std::string base64 = this->Base64EncodeFile(tarFile);
1686   cmSystemTools::RemoveFile(tarFile.c_str());
1687   return base64;
1688 }
1689
1690 //----------------------------------------------------------------------
1691 std::string cmCTest::Base64EncodeFile(std::string file)
1692 {
1693   long len = cmSystemTools::FileLength(file.c_str());
1694   std::ifstream ifs(file.c_str(), std::ios::in
1695 #ifdef _WIN32
1696     | std::ios::binary
1697 #endif
1698     );
1699   unsigned char *file_buffer = new unsigned char [ len + 1 ];
1700   ifs.read(reinterpret_cast<char*>(file_buffer), len);
1701   ifs.close();
1702
1703   unsigned char *encoded_buffer
1704     = new unsigned char [ static_cast<int>(
1705         static_cast<double>(len) * 1.5 + 5.0) ];
1706
1707   unsigned long rlen
1708     = cmsysBase64_Encode(file_buffer, len, encoded_buffer, 1);
1709
1710   std::string base64 = "";
1711   for(unsigned long i = 0; i < rlen; i++)
1712     {
1713     base64 += encoded_buffer[i];
1714     }
1715   delete [] file_buffer;
1716   delete [] encoded_buffer;
1717
1718   return base64;
1719 }
1720
1721
1722 //----------------------------------------------------------------------
1723 bool cmCTest::SubmitExtraFiles(const std::vector<cmStdString> &files)
1724 {
1725   std::vector<cmStdString>::const_iterator it;
1726   for ( it = files.begin();
1727     it != files.end();
1728     ++ it )
1729     {
1730     if ( !cmSystemTools::FileExists(it->c_str()) )
1731       {
1732       cmCTestLog(this, ERROR_MESSAGE, "Cannot find extra file: "
1733         << it->c_str() << " to submit."
1734         << std::endl;);
1735       return false;
1736       }
1737     this->AddSubmitFile(PartExtraFiles, it->c_str());
1738     }
1739   return true;
1740 }
1741
1742 //----------------------------------------------------------------------
1743 bool cmCTest::SubmitExtraFiles(const char* cfiles)
1744 {
1745   if ( !cfiles )
1746     {
1747     return 1;
1748     }
1749
1750   std::vector<cmStdString> files;
1751
1752   cmCTestLog(this, OUTPUT, "Submit extra files" << std::endl);
1753
1754   files = cmSystemTools::SplitString(cfiles, ';');
1755   if ( files.size() == 0 )
1756     {
1757     return 1;
1758     }
1759
1760   return this->SubmitExtraFiles(files);
1761 }
1762
1763
1764 //-------------------------------------------------------
1765 // for a -D argument convert the next argument into 
1766 // the proper list of dashboard steps via SetTest
1767 bool cmCTest::AddTestsForDashboardType(std::string &targ)
1768 {
1769   if ( targ == "Experimental" )
1770     {
1771     this->SetTestModel(cmCTest::EXPERIMENTAL);
1772     this->SetTest("Start");
1773     this->SetTest("Configure");
1774     this->SetTest("Build");
1775     this->SetTest("Test");
1776     this->SetTest("Coverage");
1777     this->SetTest("Submit");
1778     }
1779   else if ( targ == "ExperimentalStart" )
1780     {
1781     this->SetTestModel(cmCTest::EXPERIMENTAL);
1782     this->SetTest("Start");
1783     }
1784   else if ( targ == "ExperimentalUpdate" )
1785     {
1786     this->SetTestModel(cmCTest::EXPERIMENTAL);
1787     this->SetTest("Update");
1788     }
1789   else if ( targ == "ExperimentalConfigure" )
1790     {
1791     this->SetTestModel(cmCTest::EXPERIMENTAL);
1792     this->SetTest("Configure");
1793     }
1794   else if ( targ == "ExperimentalBuild" )
1795     {
1796     this->SetTestModel(cmCTest::EXPERIMENTAL);
1797     this->SetTest("Build");
1798     }
1799   else if ( targ == "ExperimentalTest" )
1800     {
1801     this->SetTestModel(cmCTest::EXPERIMENTAL);
1802     this->SetTest("Test");
1803     }
1804   else if ( targ == "ExperimentalMemCheck"
1805             || targ == "ExperimentalPurify" )
1806     {
1807     this->SetTestModel(cmCTest::EXPERIMENTAL);
1808     this->SetTest("MemCheck");
1809     }
1810   else if ( targ == "ExperimentalCoverage" )
1811     {
1812     this->SetTestModel(cmCTest::EXPERIMENTAL);
1813     this->SetTest("Coverage");
1814     }
1815   else if ( targ == "ExperimentalSubmit" )
1816     {
1817     this->SetTestModel(cmCTest::EXPERIMENTAL);
1818     this->SetTest("Submit");
1819     }
1820   else if ( targ == "Continuous" )
1821     {
1822     this->SetTestModel(cmCTest::CONTINUOUS);
1823     this->SetTest("Start");
1824     this->SetTest("Update");
1825     this->SetTest("Configure");
1826     this->SetTest("Build");
1827     this->SetTest("Test");
1828     this->SetTest("Coverage");
1829     this->SetTest("Submit");
1830     }
1831   else if ( targ == "ContinuousStart" )
1832     {
1833     this->SetTestModel(cmCTest::CONTINUOUS);
1834     this->SetTest("Start");
1835     }
1836   else if ( targ == "ContinuousUpdate" )
1837     {
1838     this->SetTestModel(cmCTest::CONTINUOUS);
1839     this->SetTest("Update");
1840     }
1841   else if ( targ == "ContinuousConfigure" )
1842     {
1843     this->SetTestModel(cmCTest::CONTINUOUS);
1844     this->SetTest("Configure");
1845     }
1846   else if ( targ == "ContinuousBuild" )
1847     {
1848     this->SetTestModel(cmCTest::CONTINUOUS);
1849     this->SetTest("Build");
1850     }
1851   else if ( targ == "ContinuousTest" )
1852     {
1853     this->SetTestModel(cmCTest::CONTINUOUS);
1854     this->SetTest("Test");
1855     }
1856   else if ( targ == "ContinuousMemCheck"
1857         || targ == "ContinuousPurify" )
1858     {
1859     this->SetTestModel(cmCTest::CONTINUOUS);
1860     this->SetTest("MemCheck");
1861     }
1862   else if ( targ == "ContinuousCoverage" )
1863     {
1864     this->SetTestModel(cmCTest::CONTINUOUS);
1865     this->SetTest("Coverage");
1866     }
1867   else if ( targ == "ContinuousSubmit" )
1868     {
1869     this->SetTestModel(cmCTest::CONTINUOUS);
1870     this->SetTest("Submit");
1871     }
1872   else if ( targ == "Nightly" )
1873     {
1874     this->SetTestModel(cmCTest::NIGHTLY);
1875     this->SetTest("Start");
1876     this->SetTest("Update");
1877     this->SetTest("Configure");
1878     this->SetTest("Build");
1879     this->SetTest("Test");
1880     this->SetTest("Coverage");
1881     this->SetTest("Submit");
1882     }
1883   else if ( targ == "NightlyStart" )
1884     {
1885     this->SetTestModel(cmCTest::NIGHTLY);
1886     this->SetTest("Start");
1887     }
1888   else if ( targ == "NightlyUpdate" )
1889     {
1890     this->SetTestModel(cmCTest::NIGHTLY);
1891     this->SetTest("Update");
1892     }
1893   else if ( targ == "NightlyConfigure" )
1894     {
1895     this->SetTestModel(cmCTest::NIGHTLY);
1896     this->SetTest("Configure");
1897     }
1898   else if ( targ == "NightlyBuild" )
1899     {
1900     this->SetTestModel(cmCTest::NIGHTLY);
1901     this->SetTest("Build");
1902     }
1903   else if ( targ == "NightlyTest" )
1904     {
1905     this->SetTestModel(cmCTest::NIGHTLY);
1906     this->SetTest("Test");
1907     }
1908   else if ( targ == "NightlyMemCheck"
1909             || targ == "NightlyPurify" )
1910     {
1911     this->SetTestModel(cmCTest::NIGHTLY);
1912     this->SetTest("MemCheck");
1913     }
1914   else if ( targ == "NightlyCoverage" )
1915     {
1916     this->SetTestModel(cmCTest::NIGHTLY);
1917     this->SetTest("Coverage");
1918     }
1919   else if ( targ == "NightlySubmit" )
1920     {
1921     this->SetTestModel(cmCTest::NIGHTLY);
1922     this->SetTest("Submit");
1923     }
1924   else if ( targ == "MemoryCheck" )
1925     {
1926     this->SetTestModel(cmCTest::EXPERIMENTAL);
1927     this->SetTest("Start");
1928     this->SetTest("Configure");
1929     this->SetTest("Build");
1930     this->SetTest("MemCheck");
1931     this->SetTest("Coverage");
1932     this->SetTest("Submit");
1933     }
1934   else if ( targ == "NightlyMemoryCheck" )
1935     {
1936     this->SetTestModel(cmCTest::NIGHTLY);
1937     this->SetTest("Start");
1938     this->SetTest("Update");
1939     this->SetTest("Configure");
1940     this->SetTest("Build");
1941     this->SetTest("MemCheck");
1942     this->SetTest("Coverage");
1943     this->SetTest("Submit");
1944     }
1945   else
1946     {
1947     return false;
1948     }
1949   return true;
1950 }
1951
1952
1953 //----------------------------------------------------------------------
1954 void cmCTest::ErrorMessageUnknownDashDValue(std::string &val)
1955 {
1956   cmCTestLog(this, ERROR_MESSAGE,
1957     "CTest -D called with incorrect option: " << val << std::endl);
1958
1959   cmCTestLog(this, ERROR_MESSAGE,
1960     "Available options are:" << std::endl
1961     << "  ctest -D Continuous" << std::endl
1962     << "  ctest -D Continuous(Start|Update|Configure|Build)" << std::endl
1963     << "  ctest -D Continuous(Test|Coverage|MemCheck|Submit)" << std::endl
1964     << "  ctest -D Experimental" << std::endl
1965     << "  ctest -D Experimental(Start|Update|Configure|Build)" << std::endl
1966     << "  ctest -D Experimental(Test|Coverage|MemCheck|Submit)" << std::endl
1967     << "  ctest -D Nightly" << std::endl
1968     << "  ctest -D Nightly(Start|Update|Configure|Build)" << std::endl
1969     << "  ctest -D Nightly(Test|Coverage|MemCheck|Submit)" << std::endl
1970     << "  ctest -D NightlyMemoryCheck" << std::endl);
1971 }
1972
1973
1974 //----------------------------------------------------------------------
1975 bool cmCTest::CheckArgument(const std::string& arg, const char* varg1,
1976   const char* varg2)
1977 {
1978   return (varg1 && arg == varg1) || (varg2 && arg == varg2);
1979 }
1980
1981
1982 //----------------------------------------------------------------------
1983 // Processes one command line argument (and its arguments if any) 
1984 // for many simple options and then returns
1985 void cmCTest::HandleCommandLineArguments(size_t &i, 
1986                                          std::vector<std::string> &args)
1987 {
1988   std::string arg = args[i];
1989
1990   if(this->CheckArgument(arg, "-F"))
1991     {
1992     this->Failover = true;
1993     }
1994   if(this->CheckArgument(arg, "-j", "--parallel") && i < args.size() - 1)
1995     {
1996     i++;
1997     int plevel = atoi(args[i].c_str());
1998     this->SetParallelLevel(plevel);
1999     }
2000   else if(arg.find("-j") == 0)
2001     {
2002     int plevel = atoi(arg.substr(2).c_str());
2003     this->SetParallelLevel(plevel);
2004     }
2005
2006   if(this->CheckArgument(arg, "--no-compress-output"))
2007     {
2008     this->CompressTestOutput = false;
2009     this->CompressMemCheckOutput = false;
2010     }
2011
2012   if(this->CheckArgument(arg, "--print-labels"))
2013     {
2014     this->PrintLabels = true;
2015     }
2016
2017   if(this->CheckArgument(arg, "--http1.0"))
2018     {
2019     this->UseHTTP10 = true;
2020     }
2021
2022   if(this->CheckArgument(arg, "--timeout") && i < args.size() - 1)
2023     {
2024     i++;
2025     double timeout = (double)atof(args[i].c_str());
2026     this->GlobalTimeout = timeout;
2027     }
2028
2029   if(this->CheckArgument(arg, "--stop-time") && i < args.size() - 1)
2030     {
2031     i++;
2032     this->SetStopTime(args[i]);
2033     }
2034   
2035   if(this->CheckArgument(arg, "-C", "--build-config") &&
2036      i < args.size() - 1)
2037     {
2038     i++;
2039     this->SetConfigType(args[i].c_str());
2040     }
2041   
2042   if(this->CheckArgument(arg, "--debug"))
2043     {
2044     this->Debug = true;
2045     this->ShowLineNumbers = true;
2046     }
2047   if(this->CheckArgument(arg, "--track") && i < args.size() - 1)
2048     {
2049     i++;
2050     this->SpecificTrack = args[i];
2051     }
2052   if(this->CheckArgument(arg, "--show-line-numbers"))
2053     {
2054     this->ShowLineNumbers = true;
2055     }
2056   if(this->CheckArgument(arg, "--no-label-summary"))
2057     {
2058     this->LabelSummary = false;
2059     }
2060   if(this->CheckArgument(arg, "-Q", "--quiet"))
2061     {
2062     this->Quiet = true;
2063     }
2064   if(this->CheckArgument(arg, "-V", "--verbose"))
2065     {
2066     this->Verbose = true;
2067     }
2068   if(this->CheckArgument(arg, "-B"))
2069     {
2070     this->BatchJobs = true;
2071     }
2072   if(this->CheckArgument(arg, "-VV", "--extra-verbose"))
2073     {
2074     this->ExtraVerbose = true;
2075     this->Verbose = true;
2076     }
2077   if(this->CheckArgument(arg, "--output-on-failure"))
2078     {
2079     this->OutputTestOutputOnTestFailure = true;
2080     }
2081   
2082   if(this->CheckArgument(arg, "-N", "--show-only"))
2083     {
2084     this->ShowOnly = true;
2085     }
2086
2087   if(this->CheckArgument(arg, "-O", "--output-log") && i < args.size() - 1 )
2088     {
2089     i++;
2090     this->SetOutputLogFileName(args[i].c_str());
2091     }
2092
2093   if(this->CheckArgument(arg, "--tomorrow-tag"))
2094     {
2095     this->TomorrowTag = true;
2096     }
2097   if(this->CheckArgument(arg, "--force-new-ctest-process"))
2098     {
2099     this->ForceNewCTestProcess = true;
2100     }
2101   if(this->CheckArgument(arg, "-W", "--max-width") && i < args.size() - 1)
2102     {
2103     i++;
2104     this->MaxTestNameWidth = atoi(args[i].c_str());
2105     }
2106   if(this->CheckArgument(arg, "--interactive-debug-mode") &&
2107      i < args.size() - 1 )
2108     {
2109     i++;
2110     this->InteractiveDebugMode = cmSystemTools::IsOn(args[i].c_str());
2111     }
2112   if(this->CheckArgument(arg, "--submit-index") && i < args.size() - 1 )
2113     {
2114     i++;
2115     this->SubmitIndex = atoi(args[i].c_str());
2116     if ( this->SubmitIndex < 0 )
2117       {
2118       this->SubmitIndex = 0;
2119       }
2120     }
2121   
2122   if(this->CheckArgument(arg, "--overwrite") && i < args.size() - 1)
2123     {
2124     i++;
2125     this->AddCTestConfigurationOverwrite(args[i].c_str());
2126     }
2127   if(this->CheckArgument(arg, "-A", "--add-notes") && i < args.size() - 1)
2128     {
2129     this->ProduceXML = true;
2130     this->SetTest("Notes");
2131     i++;
2132     this->SetNotesFiles(args[i].c_str());
2133     }
2134
2135   // options that control what tests are run
2136   if(this->CheckArgument(arg, "-I", "--tests-information") &&
2137      i < args.size() - 1)
2138     {
2139     i++;
2140     this->GetHandler("test")->SetPersistentOption("TestsToRunInformation",
2141                                                   args[i].c_str());
2142     this->GetHandler("memcheck")->
2143       SetPersistentOption("TestsToRunInformation",args[i].c_str());
2144     }
2145   if(this->CheckArgument(arg, "-U", "--union"))
2146     {
2147     this->GetHandler("test")->SetPersistentOption("UseUnion", "true");
2148     this->GetHandler("memcheck")->SetPersistentOption("UseUnion", "true");
2149     }
2150   if(this->CheckArgument(arg, "-R", "--tests-regex") && i < args.size() - 1)
2151     {
2152     i++;
2153     this->GetHandler("test")->
2154       SetPersistentOption("IncludeRegularExpression", args[i].c_str());
2155     this->GetHandler("memcheck")->
2156       SetPersistentOption("IncludeRegularExpression", args[i].c_str());
2157     }
2158   if(this->CheckArgument(arg, "-L", "--label-regex") && i < args.size() - 1)
2159     {
2160     i++;
2161     this->GetHandler("test")->
2162       SetPersistentOption("LabelRegularExpression", args[i].c_str());
2163     this->GetHandler("memcheck")->
2164       SetPersistentOption("LabelRegularExpression", args[i].c_str());
2165     }
2166   if(this->CheckArgument(arg, "-LE", "--label-exclude") && i < args.size() - 1)
2167     {
2168     i++;
2169     this->GetHandler("test")->
2170       SetPersistentOption("ExcludeLabelRegularExpression", args[i].c_str());
2171     this->GetHandler("memcheck")->
2172       SetPersistentOption("ExcludeLabelRegularExpression", args[i].c_str());
2173     }
2174   
2175   if(this->CheckArgument(arg, "-E", "--exclude-regex") &&
2176      i < args.size() - 1)
2177     {
2178     i++;
2179     this->GetHandler("test")->
2180       SetPersistentOption("ExcludeRegularExpression", args[i].c_str());
2181     this->GetHandler("memcheck")->
2182       SetPersistentOption("ExcludeRegularExpression", args[i].c_str());
2183     }  
2184 }
2185
2186 //----------------------------------------------------------------------
2187 // handle the -S -SR and -SP arguments
2188 void cmCTest::HandleScriptArguments(size_t &i, 
2189                                     std::vector<std::string> &args,
2190                                     bool &SRArgumentSpecified)
2191 {
2192   std::string arg = args[i];
2193   if(this->CheckArgument(arg, "-SP", "--script-new-process") && 
2194      i < args.size() - 1 )
2195     {
2196     this->RunConfigurationScript = true;
2197     i++;
2198     cmCTestScriptHandler* ch
2199       = static_cast<cmCTestScriptHandler*>(this->GetHandler("script"));
2200     // -SR is an internal argument, -SP should be ignored when it is passed
2201     if (!SRArgumentSpecified)
2202       {
2203       ch->AddConfigurationScript(args[i].c_str(),false);
2204       }
2205     }
2206   
2207   if(this->CheckArgument(arg, "-SR", "--script-run") && 
2208      i < args.size() - 1 )
2209     {
2210     SRArgumentSpecified = true;
2211     this->RunConfigurationScript = true;
2212     i++;
2213     cmCTestScriptHandler* ch
2214       = static_cast<cmCTestScriptHandler*>(this->GetHandler("script"));
2215     ch->AddConfigurationScript(args[i].c_str(),true);
2216     }
2217   
2218   if(this->CheckArgument(arg, "-S", "--script") && i < args.size() - 1 )
2219     {
2220     this->RunConfigurationScript = true;
2221     i++;
2222     cmCTestScriptHandler* ch
2223       = static_cast<cmCTestScriptHandler*>(this->GetHandler("script"));
2224     // -SR is an internal argument, -S should be ignored when it is passed
2225     if (!SRArgumentSpecified)
2226       {
2227       ch->AddConfigurationScript(args[i].c_str(),true);
2228       }
2229     }
2230 }
2231
2232 //----------------------------------------------------------------------
2233 bool cmCTest::AddVariableDefinition(const std::string &arg)
2234 {
2235   std::string name;
2236   std::string value;
2237   cmCacheManager::CacheEntryType type = cmCacheManager::UNINITIALIZED;
2238
2239   if (cmCacheManager::ParseEntry(arg.c_str(), name, value, type))
2240     {
2241     this->Definitions[name] = value;
2242     return true;
2243     }
2244
2245   return false;
2246 }
2247
2248 //----------------------------------------------------------------------
2249 // the main entry point of ctest, called from main
2250 int cmCTest::Run(std::vector<std::string> &args, std::string* output)
2251 {
2252   this->FindRunningCMake();
2253   const char* ctestExec = "ctest";
2254   bool cmakeAndTest = false;
2255   bool executeTests = true;
2256   bool SRArgumentSpecified = false;
2257
2258   // copy the command line
2259   for(size_t i=0; i < args.size(); ++i)
2260     {
2261     this->InitialCommandLineArguments.push_back(args[i]);
2262     }
2263
2264   // process the command line arguments
2265   for(size_t i=1; i < args.size(); ++i)
2266     {
2267     // handle the simple commandline arguments
2268     this->HandleCommandLineArguments(i,args);
2269
2270     // handle the script arguments -S -SR -SP
2271     this->HandleScriptArguments(i,args,SRArgumentSpecified);
2272
2273     // handle a request for a dashboard
2274     std::string arg = args[i];
2275     if(this->CheckArgument(arg, "-D", "--dashboard") && i < args.size() - 1 )
2276       {
2277       this->ProduceXML = true;
2278       i++;
2279       std::string targ = args[i];
2280       // AddTestsForDashboard parses the dashboard type and converts it
2281       // into the separate stages
2282       if (!this->AddTestsForDashboardType(targ))
2283         {
2284         if (!this->AddVariableDefinition(targ))
2285           {
2286           this->ErrorMessageUnknownDashDValue(targ);
2287           executeTests = false;
2288           }
2289         }
2290       }
2291
2292     // If it's not exactly -D, but it starts with -D, then try to parse out
2293     // a variable definition from it, same as CMake does. Unsuccessful
2294     // attempts are simply ignored since previous ctest versions ignore
2295     // this too. (As well as many other unknown command line args.)
2296     //
2297     if(arg != "-D" && cmSystemTools::StringStartsWith(arg.c_str(), "-D"))
2298       {
2299       std::string input = arg.substr(2);
2300       this->AddVariableDefinition(input);
2301       }
2302
2303     if(this->CheckArgument(arg, "-T", "--test-action") &&
2304       (i < args.size() -1) )
2305       {
2306       this->ProduceXML = true;
2307       i++;
2308       if ( !this->SetTest(args[i].c_str(), false) )
2309         {
2310         executeTests = false;
2311         cmCTestLog(this, ERROR_MESSAGE,
2312           "CTest -T called with incorrect option: "
2313           << args[i].c_str() << std::endl);
2314         cmCTestLog(this, ERROR_MESSAGE, "Available options are:" << std::endl
2315           << "  " << ctestExec << " -T all" << std::endl
2316           << "  " << ctestExec << " -T start" << std::endl
2317           << "  " << ctestExec << " -T update" << std::endl
2318           << "  " << ctestExec << " -T configure" << std::endl
2319           << "  " << ctestExec << " -T build" << std::endl
2320           << "  " << ctestExec << " -T test" << std::endl
2321           << "  " << ctestExec << " -T coverage" << std::endl
2322           << "  " << ctestExec << " -T memcheck" << std::endl
2323           << "  " << ctestExec << " -T notes" << std::endl
2324           << "  " << ctestExec << " -T submit" << std::endl);
2325         }
2326       }
2327
2328     // what type of test model
2329     if(this->CheckArgument(arg, "-M", "--test-model") &&
2330       (i < args.size() -1) )
2331       {
2332       i++;
2333       std::string const& str = args[i];
2334       if ( cmSystemTools::LowerCase(str) == "nightly" )
2335         {
2336         this->SetTestModel(cmCTest::NIGHTLY);
2337         }
2338       else if ( cmSystemTools::LowerCase(str) == "continuous" )
2339         {
2340         this->SetTestModel(cmCTest::CONTINUOUS);
2341         }
2342       else if ( cmSystemTools::LowerCase(str) == "experimental" )
2343         {
2344         this->SetTestModel(cmCTest::EXPERIMENTAL);
2345         }
2346       else
2347         {
2348         executeTests = false;
2349         cmCTestLog(this, ERROR_MESSAGE,
2350           "CTest -M called with incorrect option: " << str.c_str()
2351           << std::endl);
2352         cmCTestLog(this, ERROR_MESSAGE, "Available options are:" << std::endl
2353           << "  " << ctestExec << " -M Continuous" << std::endl
2354           << "  " << ctestExec << " -M Experimental" << std::endl
2355                    << "  " << ctestExec << " -M Nightly" << std::endl);
2356         }
2357       }
2358
2359     if(this->CheckArgument(arg, "--extra-submit") && i < args.size() - 1)
2360       {
2361       this->ProduceXML = true;
2362       this->SetTest("Submit");
2363       i++;
2364       if ( !this->SubmitExtraFiles(args[i].c_str()) )
2365         {
2366         return 0;
2367         }
2368       }
2369
2370     // --build-and-test options
2371     if(this->CheckArgument(arg, "--build-and-test") && i < args.size() - 1)
2372       {
2373       cmakeAndTest = true;
2374       }
2375
2376     if(this->CheckArgument(arg, "--schedule-random"))
2377       {
2378       this->ScheduleType = "Random";
2379       }
2380
2381     // pass the argument to all the handlers as well, but i may no longer be
2382     // set to what it was originally so I'm not sure this is working as
2383     // intended
2384     cmCTest::t_TestingHandlers::iterator it;
2385     for ( it = this->TestingHandlers.begin();
2386       it != this->TestingHandlers.end();
2387       ++ it )
2388       {
2389       if ( !it->second->ProcessCommandLineArguments(arg, i, args) )
2390         {
2391         cmCTestLog(this, ERROR_MESSAGE,
2392           "Problem parsing command line arguments within a handler");
2393         return 0;
2394         }
2395       }
2396     } // the close of the for argument loop
2397
2398
2399   // now what sould cmake do? if --build-and-test was specified then 
2400   // we run the build and test handler and return
2401   if(cmakeAndTest)
2402     {
2403     this->Verbose = true;
2404     cmCTestBuildAndTestHandler* handler =
2405       static_cast<cmCTestBuildAndTestHandler*>(this->GetHandler("buildtest"));
2406     int retv = handler->ProcessHandler();
2407     *output = handler->GetOutput();
2408 #ifdef CMAKE_BUILD_WITH_CMAKE
2409     cmDynamicLoader::FlushCache();
2410 #endif
2411     if(retv != 0)
2412       {
2413       cmCTestLog(this, DEBUG, "build and test failing returing: " << retv 
2414                  << std::endl);
2415       }
2416     return retv;
2417     }
2418
2419   if(executeTests)
2420     {
2421     int res;
2422     // call process directory
2423     if (this->RunConfigurationScript)
2424       {
2425       if ( this->ExtraVerbose )
2426         {
2427         cmCTestLog(this, OUTPUT, "* Extra verbosity turned on" << std::endl);
2428         }
2429       cmCTest::t_TestingHandlers::iterator it;
2430       for ( it = this->TestingHandlers.begin();
2431         it != this->TestingHandlers.end();
2432         ++ it )
2433         {
2434         it->second->SetVerbose(this->ExtraVerbose);
2435         it->second->SetSubmitIndex(this->SubmitIndex);
2436         }
2437       this->GetHandler("script")->SetVerbose(this->Verbose);
2438       res = this->GetHandler("script")->ProcessHandler();
2439       if(res != 0)
2440         {
2441         cmCTestLog(this, DEBUG, "running script failing returning: " << res 
2442                    << std::endl);
2443         }
2444
2445       }
2446     else
2447       {
2448       // What is this?  -V seems to be the same as -VV, 
2449       // and Verbose is always on in this case
2450       this->ExtraVerbose = this->Verbose;
2451       this->Verbose = true;
2452       cmCTest::t_TestingHandlers::iterator it;
2453       for ( it = this->TestingHandlers.begin();
2454         it != this->TestingHandlers.end();
2455         ++ it )
2456         {
2457         it->second->SetVerbose(this->Verbose);
2458         it->second->SetSubmitIndex(this->SubmitIndex);
2459         }
2460       std::string cwd = cmSystemTools::GetCurrentWorkingDirectory();
2461       if(!this->Initialize(cwd.c_str(), 0))
2462         {
2463         res = 12;
2464         cmCTestLog(this, ERROR_MESSAGE, "Problem initializing the dashboard."
2465           << std::endl);
2466         }
2467       else
2468         {
2469         res = this->ProcessTests();
2470         }
2471       this->Finalize();
2472       }
2473     if(res != 0)
2474       {
2475       cmCTestLog(this, DEBUG, "Running a test(s) failed returning : " << res 
2476                  << std::endl);
2477       }
2478     return res;
2479     }
2480
2481   return 1;
2482 }
2483
2484 //----------------------------------------------------------------------
2485 void cmCTest::FindRunningCMake()
2486 {
2487   // Find our own executable.
2488   this->CTestSelf = cmSystemTools::GetExecutableDirectory();
2489   this->CTestSelf += "/ctest";
2490   this->CTestSelf += cmSystemTools::GetExecutableExtension();
2491   if(!cmSystemTools::FileExists(this->CTestSelf.c_str()))
2492     {
2493     cmSystemTools::Error("CTest executable cannot be found at ",
2494                          this->CTestSelf.c_str());
2495     }
2496
2497   this->CMakeSelf = cmSystemTools::GetExecutableDirectory();
2498   this->CMakeSelf += "/cmake";
2499   this->CMakeSelf += cmSystemTools::GetExecutableExtension();
2500   if(!cmSystemTools::FileExists(this->CMakeSelf.c_str()))
2501     {
2502     cmSystemTools::Error("CMake executable cannot be found at ",
2503                          this->CMakeSelf.c_str());
2504     }
2505 }
2506
2507 //----------------------------------------------------------------------
2508 void cmCTest::SetNotesFiles(const char* notes)
2509 {
2510   if ( !notes )
2511     {
2512     return;
2513     }
2514   this->NotesFiles = notes;
2515 }
2516
2517 //----------------------------------------------------------------------
2518 void cmCTest::SetStopTime(std::string time)
2519 {
2520   this->StopTime = time;
2521   this->DetermineNextDayStop();
2522 }
2523
2524 //----------------------------------------------------------------------
2525 int cmCTest::ReadCustomConfigurationFileTree(const char* dir, cmMakefile* mf)
2526 {
2527   bool found = false;
2528   VectorOfStrings dirs;
2529   VectorOfStrings ndirs;
2530   cmCTestLog(this, DEBUG, "* Read custom CTest configuration directory: "
2531     << dir << std::endl);
2532
2533   std::string fname = dir;
2534   fname += "/CTestCustom.cmake";
2535   cmCTestLog(this, DEBUG, "* Check for file: "
2536     << fname.c_str() << std::endl);
2537   if ( cmSystemTools::FileExists(fname.c_str()) )
2538     {
2539     cmCTestLog(this, DEBUG, "* Read custom CTest configuration file: "
2540       << fname.c_str() << std::endl);
2541     bool erroroc = cmSystemTools::GetErrorOccuredFlag();
2542     cmSystemTools::ResetErrorOccuredFlag();
2543
2544     if ( !mf->ReadListFile(0, fname.c_str()) ||
2545       cmSystemTools::GetErrorOccuredFlag() )
2546       {
2547       cmCTestLog(this, ERROR_MESSAGE,
2548         "Problem reading custom configuration: "
2549         << fname.c_str() << std::endl);
2550       }
2551     found = true;
2552     if ( erroroc )
2553       {
2554       cmSystemTools::SetErrorOccured();
2555       }
2556     }
2557
2558   std::string rexpr = dir;
2559   rexpr += "/CTestCustom.ctest";
2560   cmCTestLog(this, DEBUG, "* Check for file: "
2561     << rexpr.c_str() << std::endl);
2562   if ( !found && cmSystemTools::FileExists(rexpr.c_str()) )
2563     {
2564     cmsys::Glob gl;
2565     gl.RecurseOn();
2566     gl.FindFiles(rexpr);
2567     std::vector<std::string>& files = gl.GetFiles();
2568     std::vector<std::string>::iterator fileIt;
2569     for ( fileIt = files.begin(); fileIt != files.end();
2570       ++ fileIt )
2571       {
2572       cmCTestLog(this, DEBUG, "* Read custom CTest configuration file: "
2573         << fileIt->c_str() << std::endl);
2574       if ( !mf->ReadListFile(0, fileIt->c_str()) ||
2575         cmSystemTools::GetErrorOccuredFlag() )
2576         {
2577         cmCTestLog(this, ERROR_MESSAGE,
2578           "Problem reading custom configuration: "
2579           << fileIt->c_str() << std::endl);
2580         }
2581       }
2582     found = true;
2583     }
2584
2585   if ( found )
2586     {
2587     cmCTest::t_TestingHandlers::iterator it;
2588     for ( it = this->TestingHandlers.begin();
2589       it != this->TestingHandlers.end(); ++ it )
2590       {
2591       cmCTestLog(this, DEBUG,
2592         "* Read custom CTest configuration vectors for handler: "
2593         << it->first.c_str() << " (" << it->second << ")" << std::endl);
2594       it->second->PopulateCustomVectors(mf);
2595       }
2596     }
2597
2598   return 1;
2599 }
2600
2601 //----------------------------------------------------------------------
2602 void cmCTest::PopulateCustomVector(cmMakefile* mf, const char* def,
2603   VectorOfStrings& vec)
2604 {
2605   if ( !def)
2606     {
2607     return;
2608     }
2609   const char* dval = mf->GetDefinition(def);
2610   if ( !dval )
2611     {
2612     return;
2613     }
2614   cmCTestLog(this, DEBUG, "PopulateCustomVector: " << def << std::endl);
2615   std::vector<std::string> slist;
2616   cmSystemTools::ExpandListArgument(dval, slist);
2617   std::vector<std::string>::iterator it;
2618
2619   vec.clear();
2620
2621   for ( it = slist.begin(); it != slist.end(); ++it )
2622     {
2623     cmCTestLog(this, DEBUG, "  -- " << it->c_str() << std::endl);
2624     vec.push_back(it->c_str());
2625     }
2626 }
2627
2628 //----------------------------------------------------------------------
2629 void cmCTest::PopulateCustomInteger(cmMakefile* mf, const char* def, int& val)
2630 {
2631   if ( !def)
2632     {
2633     return;
2634     }
2635   const char* dval = mf->GetDefinition(def);
2636   if ( !dval )
2637     {
2638     return;
2639     }
2640   val = atoi(dval);
2641 }
2642
2643 //----------------------------------------------------------------------
2644 std::string cmCTest::GetShortPathToFile(const char* cfname)
2645 {
2646   const std::string& sourceDir
2647     = cmSystemTools::CollapseFullPath(
2648         this->GetCTestConfiguration("SourceDirectory").c_str());
2649   const std::string& buildDir
2650     = cmSystemTools::CollapseFullPath(
2651         this->GetCTestConfiguration("BuildDirectory").c_str());
2652   std::string fname = cmSystemTools::CollapseFullPath(cfname);
2653
2654   // Find relative paths to both directories
2655   std::string srcRelpath
2656     = cmSystemTools::RelativePath(sourceDir.c_str(), fname.c_str());
2657   std::string bldRelpath
2658     = cmSystemTools::RelativePath(buildDir.c_str(), fname.c_str());
2659
2660   // If any contains "." it is not parent directory
2661   bool inSrc = srcRelpath.find("..") == srcRelpath.npos;
2662   bool inBld = bldRelpath.find("..") == bldRelpath.npos;
2663   // TODO: Handle files with .. in their name
2664
2665   std::string* res = 0;
2666
2667   if ( inSrc && inBld )
2668     {
2669     // If both have relative path with no dots, pick the shorter one
2670     if ( srcRelpath.size() < bldRelpath.size() )
2671       {
2672       res = &srcRelpath;
2673       }
2674     else
2675       {
2676       res = &bldRelpath;
2677       }
2678     }
2679   else if ( inSrc )
2680     {
2681     res = &srcRelpath;
2682     }
2683   else if ( inBld )
2684     {
2685     res = &bldRelpath;
2686     }
2687
2688   std::string path;
2689
2690   if ( !res )
2691     {
2692     path = fname;
2693     }
2694   else
2695     {
2696     cmSystemTools::ConvertToUnixSlashes(*res);
2697
2698     path = "./" + *res;
2699     if ( path[path.size()-1] == '/' )
2700       {
2701       path = path.substr(0, path.size()-1);
2702       }
2703     }
2704
2705   cmsys::SystemTools::ReplaceString(path, ":", "_");
2706   cmsys::SystemTools::ReplaceString(path, " ", "_");
2707   return path;
2708 }
2709
2710 //----------------------------------------------------------------------
2711 std::string cmCTest::GetCTestConfiguration(const char *name)
2712 {
2713   if ( this->CTestConfigurationOverwrites.find(name) !=
2714     this->CTestConfigurationOverwrites.end() )
2715     {
2716     return this->CTestConfigurationOverwrites[name];
2717     }
2718   return this->CTestConfiguration[name];
2719 }
2720
2721 //----------------------------------------------------------------------
2722 void cmCTest::EmptyCTestConfiguration()
2723 {
2724   this->CTestConfiguration.clear();
2725 }
2726
2727 //----------------------------------------------------------------------
2728 void cmCTest::DetermineNextDayStop()
2729 {
2730   struct tm* lctime;
2731   time_t current_time = time(0);
2732   lctime = gmtime(&current_time);
2733   int gm_hour = lctime->tm_hour;
2734   time_t gm_time = mktime(lctime);
2735   lctime = localtime(&current_time);
2736   int local_hour = lctime->tm_hour;
2737
2738   int tzone_offset = local_hour - gm_hour;
2739   if(gm_time > current_time && gm_hour < local_hour)
2740     {
2741     // this means gm_time is on the next day
2742     tzone_offset -= 24;
2743     }
2744   else if(gm_time < current_time && gm_hour > local_hour)
2745     {
2746     // this means gm_time is on the previous day
2747     tzone_offset += 24;
2748     }
2749
2750   tzone_offset *= 100;
2751   char buf[1024];
2752   sprintf(buf, "%d%02d%02d %s %+05i",
2753           lctime->tm_year + 1900,
2754           lctime->tm_mon + 1,
2755           lctime->tm_mday,
2756           this->StopTime.c_str(),
2757           tzone_offset);
2758
2759   time_t stop_time = curl_getdate(buf, &current_time);
2760
2761   if(stop_time < current_time)
2762     {
2763     this->NextDayStopTime = true;
2764     }
2765 }
2766
2767 //----------------------------------------------------------------------
2768 void cmCTest::SetCTestConfiguration(const char *name, const char* value)
2769 {
2770   cmCTestLog(this, HANDLER_VERBOSE_OUTPUT, "SetCTestConfiguration:"
2771     << name << ":" << (value ? value : "(null)") << "\n");
2772
2773   if ( !name )
2774     {
2775     return;
2776     }
2777   if ( !value )
2778     {
2779     this->CTestConfiguration.erase(name);
2780     return;
2781     }
2782   this->CTestConfiguration[name] = value;
2783 }
2784
2785
2786 //----------------------------------------------------------------------
2787 std::string cmCTest::GetCurrentTag()
2788 {
2789   return this->CurrentTag;
2790 }
2791
2792 //----------------------------------------------------------------------
2793 std::string cmCTest::GetBinaryDir()
2794 {
2795   return this->BinaryDir;
2796 }
2797
2798 //----------------------------------------------------------------------
2799 std::string const& cmCTest::GetConfigType()
2800 {
2801   return this->ConfigType;
2802 }
2803
2804 //----------------------------------------------------------------------
2805 bool cmCTest::GetShowOnly()
2806 {
2807   return this->ShowOnly;
2808 }
2809
2810 //----------------------------------------------------------------------
2811 int cmCTest::GetMaxTestNameWidth() const
2812 {
2813   return this->MaxTestNameWidth;
2814 }
2815
2816 //----------------------------------------------------------------------
2817 void cmCTest::SetProduceXML(bool v)
2818 {
2819   this->ProduceXML = v;
2820 }
2821
2822 //----------------------------------------------------------------------
2823 bool cmCTest::GetProduceXML()
2824 {
2825   return this->ProduceXML;
2826 }
2827
2828 //----------------------------------------------------------------------
2829 const char* cmCTest::GetSpecificTrack()
2830 {
2831   if ( this->SpecificTrack.empty() )
2832     {
2833     return 0;
2834     }
2835   return this->SpecificTrack.c_str();
2836 }
2837
2838 //----------------------------------------------------------------------
2839 void cmCTest::SetSpecificTrack(const char* track)
2840 {
2841   if ( !track )
2842     {
2843     this->SpecificTrack = "";
2844     return;
2845     }
2846   this->SpecificTrack = track;
2847 }
2848
2849 //----------------------------------------------------------------------
2850 void cmCTest::AddSubmitFile(Part part, const char* name)
2851 {
2852   this->Parts[part].SubmitFiles.push_back(name);
2853 }
2854
2855 //----------------------------------------------------------------------
2856 void cmCTest::AddCTestConfigurationOverwrite(const char* encstr)
2857 {
2858   std::string overStr = encstr;
2859   size_t epos = overStr.find("=");
2860   if ( epos == overStr.npos )
2861     {
2862     cmCTestLog(this, ERROR_MESSAGE,
2863       "CTest configuration overwrite specified in the wrong format."
2864       << std::endl
2865       << "Valid format is: --overwrite key=value" << std::endl
2866       << "The specified was: --overwrite " << overStr.c_str() << std::endl);
2867     return;
2868     }
2869   std::string key = overStr.substr(0, epos);
2870   std::string value = overStr.substr(epos+1, overStr.npos);
2871   this->CTestConfigurationOverwrites[key] = value;
2872 }
2873
2874 //----------------------------------------------------------------------
2875 void cmCTest::SetConfigType(const char* ct)
2876 {
2877   this->ConfigType = ct?ct:"";
2878   cmSystemTools::ReplaceString(this->ConfigType, ".\\", "");
2879   std::string confTypeEnv
2880     = "CMAKE_CONFIG_TYPE=" + this->ConfigType;
2881   cmSystemTools::PutEnv(confTypeEnv.c_str());
2882 }
2883
2884 //----------------------------------------------------------------------
2885 bool cmCTest::SetCTestConfigurationFromCMakeVariable(cmMakefile* mf,
2886   const char* dconfig, const char* cmake_var)
2887 {
2888   const char* ctvar;
2889   ctvar = mf->GetDefinition(cmake_var);
2890   if ( !ctvar )
2891     {
2892     return false;
2893     }
2894   cmCTestLog(this, HANDLER_VERBOSE_OUTPUT,
2895              "SetCTestConfigurationFromCMakeVariable:"
2896              << dconfig << ":" << cmake_var << std::endl);
2897   this->SetCTestConfiguration(dconfig, ctvar);
2898   return true;
2899 }
2900
2901 bool cmCTest::RunCommand(
2902   const char* command,
2903   std::string* stdOut,
2904   std::string* stdErr,
2905   int *retVal,
2906   const char* dir,
2907   double timeout)
2908 {
2909   std::vector<cmStdString> args = cmSystemTools::ParseArguments(command);
2910
2911   if(args.size() < 1)
2912     {
2913     return false;
2914     }
2915
2916   std::vector<const char*> argv;
2917   for(std::vector<cmStdString>::const_iterator a = args.begin();
2918       a != args.end(); ++a)
2919     {
2920     argv.push_back(a->c_str());
2921     }
2922   argv.push_back(0);
2923
2924   *stdOut = "";
2925   *stdErr = "";
2926
2927   cmsysProcess* cp = cmsysProcess_New();
2928   cmsysProcess_SetCommand(cp, &*argv.begin());
2929   cmsysProcess_SetWorkingDirectory(cp, dir);
2930   if(cmSystemTools::GetRunCommandHideConsole())
2931     {
2932     cmsysProcess_SetOption(cp, cmsysProcess_Option_HideWindow, 1);
2933     }
2934   cmsysProcess_SetTimeout(cp, timeout);
2935   cmsysProcess_Execute(cp);
2936
2937   std::vector<char> tempOutput;
2938   std::vector<char> tempError;
2939   char* data;
2940   int length;
2941   int res;
2942   bool done = false;
2943   while(!done)
2944     {
2945     res = cmsysProcess_WaitForData(cp, &data, &length, 0);
2946     switch ( res )
2947       {
2948     case cmsysProcess_Pipe_STDOUT:
2949       tempOutput.insert(tempOutput.end(), data, data+length);
2950       break;
2951     case cmsysProcess_Pipe_STDERR:
2952       tempError.insert(tempError.end(), data, data+length);
2953       break;
2954     default:
2955       done = true;
2956       }
2957     if ( (res == cmsysProcess_Pipe_STDOUT ||
2958         res == cmsysProcess_Pipe_STDERR) && this->ExtraVerbose )
2959       {
2960       cmSystemTools::Stdout(data, length);
2961       }
2962     }
2963
2964   cmsysProcess_WaitForExit(cp, 0);
2965   if ( tempOutput.size() > 0 )
2966     {
2967     stdOut->append(&*tempOutput.begin(), tempOutput.size());
2968     }
2969   if ( tempError.size() > 0 )
2970     {
2971     stdErr->append(&*tempError.begin(), tempError.size());
2972     }
2973
2974   bool result = true;
2975   if(cmsysProcess_GetState(cp) == cmsysProcess_State_Exited)
2976     {
2977     if ( retVal )
2978       {
2979       *retVal = cmsysProcess_GetExitValue(cp);
2980       }
2981     else
2982       {
2983       if ( cmsysProcess_GetExitValue(cp) !=  0 )
2984         {
2985         result = false;
2986         }
2987       }
2988     }
2989   else if(cmsysProcess_GetState(cp) == cmsysProcess_State_Exception)
2990     {
2991     const char* exception_str = cmsysProcess_GetExceptionString(cp);
2992     cmCTestLog(this, ERROR_MESSAGE, exception_str << std::endl);
2993     stdErr->append(exception_str, strlen(exception_str));
2994     result = false;
2995     }
2996   else if(cmsysProcess_GetState(cp) == cmsysProcess_State_Error)
2997     {
2998     const char* error_str = cmsysProcess_GetErrorString(cp);
2999     cmCTestLog(this, ERROR_MESSAGE, error_str << std::endl);
3000     stdErr->append(error_str, strlen(error_str));
3001     result = false;
3002     }
3003   else if(cmsysProcess_GetState(cp) == cmsysProcess_State_Expired)
3004     {
3005     const char* error_str = "Process terminated due to timeout\n";
3006     cmCTestLog(this, ERROR_MESSAGE, error_str << std::endl);
3007     stdErr->append(error_str, strlen(error_str));
3008     result = false;
3009     }
3010
3011   cmsysProcess_Delete(cp);
3012   return result;
3013 }
3014
3015 //----------------------------------------------------------------------
3016 void cmCTest::SetOutputLogFileName(const char* name)
3017 {
3018   if ( this->OutputLogFile)
3019     {
3020     delete this->OutputLogFile;
3021     this->OutputLogFile= 0;
3022     }
3023   if ( name )
3024     {
3025     this->OutputLogFile = new cmGeneratedFileStream(name);
3026     }
3027 }
3028
3029 //----------------------------------------------------------------------
3030 static const char* cmCTestStringLogType[] =
3031 {
3032   "DEBUG",
3033   "OUTPUT",
3034   "HANDLER_OUTPUT",
3035   "HANDLER_VERBOSE_OUTPUT",
3036   "WARNING",
3037   "ERROR_MESSAGE",
3038   0
3039 };
3040
3041 //----------------------------------------------------------------------
3042 #ifdef cerr
3043 #  undef cerr
3044 #endif
3045 #ifdef cout
3046 #  undef cout
3047 #endif
3048
3049 #define cmCTestLogOutputFileLine(stream) \
3050   if ( this->ShowLineNumbers ) \
3051     { \
3052     (stream) << std::endl << file << ":" << line << " "; \
3053     }
3054
3055 void cmCTest::InitStreams()
3056 {
3057   // By default we write output to the process output streams.
3058   this->StreamOut = &std::cout;
3059   this->StreamErr = &std::cerr;
3060 }
3061
3062 void cmCTest::Log(int logType, const char* file, int line, const char* msg)
3063 {
3064   if ( !msg || !*msg )
3065     {
3066     return;
3067     }
3068   if ( this->OutputLogFile )
3069     {
3070     bool display = true;
3071     if ( logType == cmCTest::DEBUG && !this->Debug ) { display = false; }
3072     if ( logType == cmCTest::HANDLER_VERBOSE_OUTPUT && !this->Debug &&
3073       !this->ExtraVerbose ) { display = false; }
3074     if ( display )
3075       {
3076       cmCTestLogOutputFileLine(*this->OutputLogFile);
3077       if ( logType != this->OutputLogFileLastTag )
3078         {
3079         *this->OutputLogFile << "[";
3080         if ( logType >= OTHER || logType < 0 )
3081           {
3082           *this->OutputLogFile << "OTHER";
3083           }
3084         else
3085           {
3086           *this->OutputLogFile << cmCTestStringLogType[logType];
3087           }
3088         *this->OutputLogFile << "] " << std::endl << std::flush;
3089         }
3090       *this->OutputLogFile << msg << std::flush;
3091       if ( logType != this->OutputLogFileLastTag )
3092         {
3093         *this->OutputLogFile << std::endl << std::flush;
3094         this->OutputLogFileLastTag = logType;
3095         }
3096       }
3097     }
3098   if ( !this->Quiet )
3099     {
3100     std::ostream& out = *this->StreamOut;
3101     std::ostream& err = *this->StreamErr;
3102     switch ( logType )
3103       {
3104     case DEBUG:
3105       if ( this->Debug )
3106         {
3107         cmCTestLogOutputFileLine(out);
3108         out << msg;
3109         out.flush();
3110         }
3111       break;
3112     case OUTPUT: case HANDLER_OUTPUT:
3113       if ( this->Debug || this->Verbose )
3114         {
3115         cmCTestLogOutputFileLine(out);
3116         out << msg;
3117         out.flush();
3118         }
3119       break;
3120     case HANDLER_VERBOSE_OUTPUT:
3121       if ( this->Debug || this->ExtraVerbose )
3122         {
3123         cmCTestLogOutputFileLine(out);
3124         out << msg;
3125         out.flush();
3126         }
3127       break;
3128     case WARNING:
3129       cmCTestLogOutputFileLine(err);
3130       err << msg;
3131       err.flush();
3132       break;
3133     case ERROR_MESSAGE:
3134       cmCTestLogOutputFileLine(err);
3135       err << msg;
3136       err.flush();
3137       cmSystemTools::SetErrorOccured();
3138       break;
3139     default:
3140       cmCTestLogOutputFileLine(out);
3141       out << msg;
3142       out.flush();
3143       }
3144     }
3145 }
3146
3147 //-------------------------------------------------------------------------
3148 double cmCTest::GetRemainingTimeAllowed()
3149 {
3150   if (!this->GetHandler("script"))
3151     {
3152     return 1.0e7;
3153     }
3154
3155   cmCTestScriptHandler* ch
3156     = static_cast<cmCTestScriptHandler*>(this->GetHandler("script"));
3157
3158   return ch->GetRemainingTimeAllowed();
3159 }
3160
3161 //----------------------------------------------------------------------
3162 void cmCTest::OutputTestErrors(std::vector<char> const &process_output)
3163 {
3164   std::string test_outputs("\n*** Test Failed:\n");
3165   if(process_output.size())
3166     {
3167     test_outputs.append(&*process_output.begin(), process_output.size());
3168     }
3169   cmCTestLog(this, HANDLER_OUTPUT, test_outputs << std::endl << std::flush);
3170 }
3171
3172 //----------------------------------------------------------------------
3173 bool cmCTest::CompressString(std::string& str)
3174 {
3175   int ret;
3176   z_stream strm;
3177
3178   unsigned char* in = reinterpret_cast<unsigned char*>(
3179     const_cast<char*>(str.c_str()));
3180   //zlib makes the guarantee that this is the maximum output size
3181   int outSize = static_cast<int>(
3182     static_cast<double>(str.size()) * 1.001 + 13.0);
3183   unsigned char* out = new unsigned char[outSize];
3184
3185   strm.zalloc = Z_NULL;
3186   strm.zfree = Z_NULL;
3187   strm.opaque = Z_NULL;
3188   ret = deflateInit(&strm, -1); //default compression level
3189   if (ret != Z_OK)
3190     {
3191     delete[] out;
3192     return false;
3193     }
3194
3195   strm.avail_in = static_cast<uInt>(str.size());
3196   strm.next_in = in;
3197   strm.avail_out = outSize;
3198   strm.next_out = out;
3199   ret = deflate(&strm, Z_FINISH);
3200
3201   if(ret == Z_STREAM_ERROR || ret != Z_STREAM_END)
3202     {
3203     cmCTestLog(this, ERROR_MESSAGE, "Error during gzip compression."
3204       << std::endl);
3205     delete[] out;
3206     return false;
3207     }
3208
3209   (void)deflateEnd(&strm);
3210
3211   // Now base64 encode the resulting binary string
3212   unsigned char* base64EncodedBuffer
3213     = new unsigned char[static_cast<int>(outSize * 1.5)];
3214
3215   unsigned long rlen
3216     = cmsysBase64_Encode(out, strm.total_out, base64EncodedBuffer, 1);
3217
3218   str = "";
3219   str.append(reinterpret_cast<char*>(base64EncodedBuffer), rlen);
3220
3221   delete [] base64EncodedBuffer;
3222   delete [] out;
3223
3224   return true;
3225 }