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