summaryrefslogtreecommitdiffstats
path: root/Source/CTest
diff options
context:
space:
mode:
authorBrad King <brad.king@kitware.com>2010-01-28 21:48:20 (GMT)
committerBrad King <brad.king@kitware.com>2010-01-28 21:48:20 (GMT)
commitdc1d2189ae922be9d6e7f5fde698532db47e46aa (patch)
tree28ef61aac78f0bdc190a760d53b6cb89b24262cd /Source/CTest
parent612409e5b01a7e4823bb379ee9e002177793eb75 (diff)
downloadCMake-dc1d2189ae922be9d6e7f5fde698532db47e46aa.zip
CMake-dc1d2189ae922be9d6e7f5fde698532db47e46aa.tar.gz
CMake-dc1d2189ae922be9d6e7f5fde698532db47e46aa.tar.bz2
CMake 2.8.1-rc1
Diffstat (limited to 'Source/CTest')
-rw-r--r--Source/CTest/cmCTestBuildCommand.cxx52
-rw-r--r--Source/CTest/cmCTestBuildCommand.h4
-rw-r--r--Source/CTest/cmCTestBuildHandler.cxx36
-rw-r--r--Source/CTest/cmCTestBuildHandler.h3
-rw-r--r--Source/CTest/cmCTestConfigureCommand.cxx45
-rw-r--r--Source/CTest/cmCTestGIT.cxx22
-rw-r--r--Source/CTest/cmCTestGlobalVC.cxx15
-rw-r--r--Source/CTest/cmCTestGlobalVC.h1
-rw-r--r--Source/CTest/cmCTestHandlerCommand.cxx11
-rw-r--r--Source/CTest/cmCTestMultiProcessHandler.cxx15
-rw-r--r--Source/CTest/cmCTestRunTest.cxx140
-rw-r--r--Source/CTest/cmCTestRunTest.h11
-rw-r--r--Source/CTest/cmCTestSVN.cxx8
-rw-r--r--Source/CTest/cmCTestSVN.h2
-rw-r--r--Source/CTest/cmCTestScriptHandler.cxx4
-rw-r--r--Source/CTest/cmCTestStartCommand.cxx78
-rw-r--r--Source/CTest/cmCTestStartCommand.h20
-rw-r--r--Source/CTest/cmCTestSubmitHandler.cxx57
-rw-r--r--Source/CTest/cmCTestSubmitHandler.h4
-rw-r--r--Source/CTest/cmCTestTestCommand.cxx8
-rw-r--r--Source/CTest/cmCTestTestCommand.h8
-rw-r--r--Source/CTest/cmCTestTestHandler.cxx140
-rw-r--r--Source/CTest/cmCTestTestHandler.h8
-rw-r--r--Source/CTest/cmCTestUpdateCommand.cxx26
-rw-r--r--Source/CTest/cmCTestUpdateHandler.cxx38
-rw-r--r--Source/CTest/cmCTestUpdateHandler.h1
-rw-r--r--Source/CTest/cmProcess.cxx5
27 files changed, 622 insertions, 140 deletions
diff --git a/Source/CTest/cmCTestBuildCommand.cxx b/Source/CTest/cmCTestBuildCommand.cxx
index 3fe1c00..b984e85 100644
--- a/Source/CTest/cmCTestBuildCommand.cxx
+++ b/Source/CTest/cmCTestBuildCommand.cxx
@@ -23,7 +23,11 @@ cmCTestBuildCommand::cmCTestBuildCommand()
{
this->GlobalGenerator = 0;
this->Arguments[ctb_NUMBER_ERRORS] = "NUMBER_ERRORS";
- this->Arguments[ctb_NUMBER_WARNINGS] = "NUMBER_WARNINGS";
+ this->Arguments[ctb_NUMBER_WARNINGS] = "NUMBER_WARNINGS";
+ this->Arguments[ctb_TARGET] = "TARGET";
+ this->Arguments[ctb_CONFIGURATION] = "CONFIGURATION";
+ this->Arguments[ctb_FLAGS] = "FLAGS";
+ this->Arguments[ctb_PROJECT_NAME] = "PROJECT_NAME";
this->Arguments[ctb_LAST] = 0;
this->Last = ctb_LAST;
}
@@ -49,6 +53,7 @@ cmCTestGenericHandler* cmCTestBuildCommand::InitializeHandler()
return 0;
}
this->Handler = (cmCTestBuildHandler*)handler;
+
const char* ctestBuildCommand
= this->Makefile->GetDefinition("CTEST_BUILD_COMMAND");
if ( ctestBuildCommand && *ctestBuildCommand )
@@ -60,13 +65,33 @@ cmCTestGenericHandler* cmCTestBuildCommand::InitializeHandler()
const char* cmakeGeneratorName
= this->Makefile->GetDefinition("CTEST_CMAKE_GENERATOR");
const char* cmakeProjectName
- = this->Makefile->GetDefinition("CTEST_PROJECT_NAME");
- const char* cmakeBuildConfiguration
+ = (this->Values[ctb_PROJECT_NAME] && *this->Values[ctb_PROJECT_NAME])
+ ? this->Values[ctb_PROJECT_NAME]
+ : this->Makefile->GetDefinition("CTEST_PROJECT_NAME");
+
+ // Build configuration is determined by: CONFIGURATION argument,
+ // or CTEST_BUILD_CONFIGURATION script variable, or
+ // CTEST_CONFIGURATION_TYPE script variable, or ctest -C command
+ // line argument... in that order.
+ //
+ const char* ctestBuildConfiguration
= this->Makefile->GetDefinition("CTEST_BUILD_CONFIGURATION");
+ const char* cmakeBuildConfiguration
+ = (this->Values[ctb_CONFIGURATION] && *this->Values[ctb_CONFIGURATION])
+ ? this->Values[ctb_CONFIGURATION]
+ : ((ctestBuildConfiguration && *ctestBuildConfiguration)
+ ? ctestBuildConfiguration
+ : this->CTest->GetConfigType().c_str());
+
const char* cmakeBuildAdditionalFlags
- = this->Makefile->GetDefinition("CTEST_BUILD_FLAGS");
+ = (this->Values[ctb_FLAGS] && *this->Values[ctb_FLAGS])
+ ? this->Values[ctb_FLAGS]
+ : this->Makefile->GetDefinition("CTEST_BUILD_FLAGS");
const char* cmakeBuildTarget
- = this->Makefile->GetDefinition("CTEST_BUILD_TARGET");
+ = (this->Values[ctb_TARGET] && *this->Values[ctb_TARGET])
+ ? this->Values[ctb_TARGET]
+ : this->Makefile->GetDefinition("CTEST_BUILD_TARGET");
+
if ( cmakeGeneratorName && *cmakeGeneratorName &&
cmakeProjectName && *cmakeProjectName )
{
@@ -104,7 +129,7 @@ cmCTestGenericHandler* cmCTestBuildCommand::InitializeHandler()
}
cmakeBuildConfiguration = config;
}
-
+
std::string buildCommand
= this->GlobalGenerator->
GenerateBuildCommand(cmakeMakeProgram,
@@ -119,10 +144,17 @@ cmCTestGenericHandler* cmCTestBuildCommand::InitializeHandler()
else
{
cmOStringStream ostr;
- ostr << "CTEST_BUILD_COMMAND or CTEST_CMAKE_GENERATOR not specified. "
- "Please specify the CTEST_CMAKE_GENERATOR and CTEST_PROJECT_NAME if "
- "this is a CMake project, or specify the CTEST_BUILD_COMMAND for "
- "cmake or any other project.";
+ ostr << "has no project to build. If this is a "
+ "\"built with CMake\" project, verify that CTEST_CMAKE_GENERATOR "
+ "and CTEST_PROJECT_NAME are set."
+ "\n"
+ "CTEST_PROJECT_NAME is usually set in CTestConfig.cmake. Verify "
+ "that CTestConfig.cmake exists, or CTEST_PROJECT_NAME "
+ "is set in the script, or PROJECT_NAME is passed as an argument "
+ "to ctest_build."
+ "\n"
+ "Alternatively, set CTEST_BUILD_COMMAND to build the project "
+ "with a custom command line.";
this->SetError(ostr.str().c_str());
return 0;
}
diff --git a/Source/CTest/cmCTestBuildCommand.h b/Source/CTest/cmCTestBuildCommand.h
index 8122eee..228067e 100644
--- a/Source/CTest/cmCTestBuildCommand.h
+++ b/Source/CTest/cmCTestBuildCommand.h
@@ -82,6 +82,10 @@ protected:
ctb_BUILD = ct_LAST,
ctb_NUMBER_ERRORS,
ctb_NUMBER_WARNINGS,
+ ctb_TARGET,
+ ctb_CONFIGURATION,
+ ctb_FLAGS,
+ ctb_PROJECT_NAME,
ctb_LAST
};
diff --git a/Source/CTest/cmCTestBuildHandler.cxx b/Source/CTest/cmCTestBuildHandler.cxx
index 0095bbc..a125459 100644
--- a/Source/CTest/cmCTestBuildHandler.cxx
+++ b/Source/CTest/cmCTestBuildHandler.cxx
@@ -265,6 +265,32 @@ void cmCTestBuildHandler::PopulateCustomVectors(cmMakefile *mf)
}
//----------------------------------------------------------------------
+std::string cmCTestBuildHandler::GetMakeCommand()
+{
+ std::string makeCommand
+ = this->CTest->GetCTestConfiguration("MakeCommand");
+ cmCTestLog(this->CTest,
+ HANDLER_VERBOSE_OUTPUT, "MakeCommand:" << makeCommand <<
+ "\n");
+
+ std::string configType = this->CTest->GetConfigType();
+ if (configType == "")
+ {
+ configType
+ = this->CTest->GetCTestConfiguration("DefaultCTestConfigurationType");
+ }
+ if (configType == "")
+ {
+ configType = "Release";
+ }
+
+ cmSystemTools::ReplaceString(makeCommand,
+ "${CTEST_CONFIGURATION_TYPE}", configType.c_str());
+
+ return makeCommand;
+}
+
+//----------------------------------------------------------------------
//clearly it would be nice if this were broken up into a few smaller
//functions and commented...
int cmCTestBuildHandler::ProcessHandler()
@@ -300,11 +326,7 @@ int cmCTestBuildHandler::ProcessHandler()
}
// Determine build command and build directory
- const std::string &makeCommand
- = this->CTest->GetCTestConfiguration("MakeCommand");
- cmCTestLog(this->CTest,
- HANDLER_VERBOSE_OUTPUT, "MakeCommand:" << makeCommand <<
- "\n");
+ std::string makeCommand = this->GetMakeCommand();
if ( makeCommand.size() == 0 )
{
cmCTestLog(this->CTest, ERROR_MESSAGE,
@@ -312,6 +334,7 @@ int cmCTestBuildHandler::ProcessHandler()
<< std::endl);
return -1;
}
+
const std::string &buildDirectory
= this->CTest->GetCTestConfiguration("BuildDirectory");
if ( buildDirectory.size() == 0 )
@@ -519,8 +542,7 @@ void cmCTestBuildHandler::GenerateXMLHeader(std::ostream& os)
static_cast<unsigned int>(this->StartBuildTime)
<< "</StartBuildTime>\n"
<< "<BuildCommand>"
- << cmXMLSafe(
- this->CTest->GetCTestConfiguration("MakeCommand"))
+ << cmXMLSafe(this->GetMakeCommand())
<< "</BuildCommand>" << std::endl;
}
diff --git a/Source/CTest/cmCTestBuildHandler.h b/Source/CTest/cmCTestBuildHandler.h
index 7ee50be..439efd6 100644
--- a/Source/CTest/cmCTestBuildHandler.h
+++ b/Source/CTest/cmCTestBuildHandler.h
@@ -46,7 +46,10 @@ public:
int GetTotalErrors() { return this->TotalErrors;}
int GetTotalWarnings() { return this->TotalWarnings;}
+
private:
+ std::string GetMakeCommand();
+
//! Run command specialized for make and configure. Returns process status
// and retVal is return value or exception.
int RunMakeCommand(const char* command,
diff --git a/Source/CTest/cmCTestConfigureCommand.cxx b/Source/CTest/cmCTestConfigureCommand.cxx
index 00d9ec5..147173f 100644
--- a/Source/CTest/cmCTestConfigureCommand.cxx
+++ b/Source/CTest/cmCTestConfigureCommand.cxx
@@ -11,6 +11,7 @@
============================================================================*/
#include "cmCTestConfigureCommand.h"
+#include "cmGlobalGenerator.h"
#include "cmCTest.h"
#include "cmCTestGenericHandler.h"
@@ -66,6 +67,7 @@ cmCTestGenericHandler* cmCTestConfigureCommand::InitializeHandler()
const char* ctestConfigureCommand
= this->Makefile->GetDefinition("CTEST_CONFIGURE_COMMAND");
+
if ( ctestConfigureCommand && *ctestConfigureCommand )
{
this->CTest->SetCTestConfiguration("ConfigureCommand",
@@ -86,6 +88,29 @@ cmCTestGenericHandler* cmCTestConfigureCommand::InitializeHandler()
"variable");
return 0;
}
+
+ const std::string cmakelists_file = source_dir + "/CMakeLists.txt";
+ if ( !cmSystemTools::FileExists(cmakelists_file.c_str()) )
+ {
+ cmOStringStream e;
+ e << "CMakeLists.txt file does not exist ["
+ << cmakelists_file << "]";
+ this->SetError(e.str().c_str());
+ return 0;
+ }
+
+ bool multiConfig = false;
+ bool cmakeBuildTypeInOptions = false;
+
+ cmGlobalGenerator *gg =
+ this->Makefile->GetCMakeInstance()->CreateGlobalGenerator(
+ cmakeGeneratorName);
+ if(gg)
+ {
+ multiConfig = gg->IsMultiConfig();
+ delete gg;
+ }
+
std::string cmakeConfigureCommand = "\"";
cmakeConfigureCommand += this->CTest->GetCMakeExecutable();
cmakeConfigureCommand += "\"";
@@ -95,9 +120,23 @@ cmCTestGenericHandler* cmCTestConfigureCommand::InitializeHandler()
for (it= options.begin(); it!=options.end(); ++it)
{
option = *it;
+
cmakeConfigureCommand += " \"";
cmakeConfigureCommand += option;
cmakeConfigureCommand += "\"";
+
+ if ((0 != strstr(option.c_str(), "CMAKE_BUILD_TYPE=")) ||
+ (0 != strstr(option.c_str(), "CMAKE_BUILD_TYPE:STRING=")))
+ {
+ cmakeBuildTypeInOptions = true;
+ }
+ }
+
+ if (!multiConfig && !cmakeBuildTypeInOptions)
+ {
+ cmakeConfigureCommand += " \"-DCMAKE_BUILD_TYPE:STRING=";
+ cmakeConfigureCommand += this->CTest->GetConfigType();
+ cmakeConfigureCommand += "\"";
}
cmakeConfigureCommand += " \"-G";
@@ -113,9 +152,9 @@ cmCTestGenericHandler* cmCTestConfigureCommand::InitializeHandler()
}
else
{
- this->SetError("Configure command is not specified. If this is a CMake "
- "project, specify CTEST_CMAKE_GENERATOR, or if this is not CMake "
- "project, specify CTEST_CONFIGURE_COMMAND.");
+ this->SetError("Configure command is not specified. If this is a "
+ "\"built with CMake\" project, set CTEST_CMAKE_GENERATOR. If not, "
+ "set CTEST_CONFIGURE_COMMAND.");
return 0;
}
}
diff --git a/Source/CTest/cmCTestGIT.cxx b/Source/CTest/cmCTestGIT.cxx
index 5b0e8ff..8108b19 100644
--- a/Source/CTest/cmCTestGIT.cxx
+++ b/Source/CTest/cmCTestGIT.cxx
@@ -19,6 +19,8 @@
#include <cmsys/ios/sstream>
#include <cmsys/Process.h>
+#include <sys/types.h>
+#include <time.h>
#include <ctype.h>
//----------------------------------------------------------------------------
@@ -336,16 +338,28 @@ private:
Person author;
this->ParsePerson(this->Line.c_str()+7, author);
this->Rev.Author = author.Name;
- char buf[1024];
+
+ // Convert the time to a human-readable format that is also easy
+ // to machine-parse: "CCYY-MM-DD hh:mm:ss".
+ time_t seconds = static_cast<time_t>(author.Time);
+ struct tm* t = gmtime(&seconds);
+ char dt[1024];
+ sprintf(dt, "%04d-%02d-%02d %02d:%02d:%02d",
+ t->tm_year+1900, t->tm_mon+1, t->tm_mday,
+ t->tm_hour, t->tm_min, t->tm_sec);
+ this->Rev.Date = dt;
+
+ // Add the time-zone field "+zone" or "-zone".
+ char tz[32];
if(author.TimeZone >= 0)
{
- sprintf(buf, "%lu +%04ld", author.Time, author.TimeZone);
+ sprintf(tz, " +%04ld", author.TimeZone);
}
else
{
- sprintf(buf, "%lu -%04ld", author.Time, -author.TimeZone);
+ sprintf(tz, " -%04ld", -author.TimeZone);
}
- this->Rev.Date = buf;
+ this->Rev.Date += tz;
}
}
diff --git a/Source/CTest/cmCTestGlobalVC.cxx b/Source/CTest/cmCTestGlobalVC.cxx
index 73a36da..8c51102 100644
--- a/Source/CTest/cmCTestGlobalVC.cxx
+++ b/Source/CTest/cmCTestGlobalVC.cxx
@@ -107,6 +107,19 @@ void cmCTestGlobalVC::WriteXMLDirectory(std::ostream& xml,
}
//----------------------------------------------------------------------------
+void cmCTestGlobalVC::WriteXMLGlobal(std::ostream& xml)
+{
+ if(!this->NewRevision.empty())
+ {
+ xml << "\t<Revision>" << this->NewRevision << "</Revision>\n";
+ }
+ if(!this->OldRevision.empty() && this->OldRevision != this->NewRevision)
+ {
+ xml << "\t<PriorRevision>" << this->OldRevision << "</PriorRevision>\n";
+ }
+}
+
+//----------------------------------------------------------------------------
bool cmCTestGlobalVC::WriteXMLUpdates(std::ostream& xml)
{
cmCTestLog(this->CTest, HANDLER_OUTPUT,
@@ -117,6 +130,8 @@ bool cmCTestGlobalVC::WriteXMLUpdates(std::ostream& xml)
this->LoadModifications();
+ this->WriteXMLGlobal(xml);
+
for(std::map<cmStdString, Directory>::const_iterator
di = this->Dirs.begin(); di != this->Dirs.end(); ++di)
{
diff --git a/Source/CTest/cmCTestGlobalVC.h b/Source/CTest/cmCTestGlobalVC.h
index d88016b..a648a59 100644
--- a/Source/CTest/cmCTestGlobalVC.h
+++ b/Source/CTest/cmCTestGlobalVC.h
@@ -60,6 +60,7 @@ protected:
virtual void LoadModifications() = 0;
virtual void LoadRevisions() = 0;
+ virtual void WriteXMLGlobal(std::ostream& xml);
void WriteXMLDirectory(std::ostream& xml, std::string const& path,
Directory const& dir);
};
diff --git a/Source/CTest/cmCTestHandlerCommand.cxx b/Source/CTest/cmCTestHandlerCommand.cxx
index 1c9f080..1957e04 100644
--- a/Source/CTest/cmCTestHandlerCommand.cxx
+++ b/Source/CTest/cmCTestHandlerCommand.cxx
@@ -59,6 +59,17 @@ bool cmCTestHandlerCommand
}
}
+ // Set the config type of this ctest to the current value of the
+ // CTEST_CONFIGURATION_TYPE script variable if it is defined.
+ // The current script value trumps the -C argument on the command
+ // line.
+ const char* ctestConfigType =
+ this->Makefile->GetDefinition("CTEST_CONFIGURATION_TYPE");
+ if (ctestConfigType)
+ {
+ this->CTest->SetConfigType(ctestConfigType);
+ }
+
cmCTestLog(this->CTest, DEBUG, "Initialize handler" << std::endl;);
cmCTestGenericHandler* handler = this->InitializeHandler();
if ( !handler )
diff --git a/Source/CTest/cmCTestMultiProcessHandler.cxx b/Source/CTest/cmCTestMultiProcessHandler.cxx
index 336303a..a79f131 100644
--- a/Source/CTest/cmCTestMultiProcessHandler.cxx
+++ b/Source/CTest/cmCTestMultiProcessHandler.cxx
@@ -43,8 +43,11 @@ cmCTestMultiProcessHandler::SetTests(TestMap& tests,
this->TestRunningMap[i->first] = false;
this->TestFinishMap[i->first] = false;
}
- this->ReadCostData();
- this->CreateTestCostList();
+ if(!this->CTest->GetShowOnly())
+ {
+ this->ReadCostData();
+ this->CreateTestCostList();
+ }
}
// Set the max number of tests that can be run at the same time.
@@ -102,6 +105,7 @@ void cmCTestMultiProcessHandler::StartTestProcess(int test)
this->RunningCount -= GetProcessorsUsed(test);
testRun->EndTest(this->Completed, this->Total, false);
this->Failed->push_back(this->Properties[test]->Name);
+ delete testRun;
}
cmSystemTools::ChangeDirectory(current_dir.c_str());
}
@@ -412,12 +416,9 @@ void cmCTestMultiProcessHandler::CheckResume()
fin.close();
}
}
- else
+ else if(cmSystemTools::FileExists(fname.c_str(), true))
{
- if(cmSystemTools::FileExists(fname.c_str(), true))
- {
- cmSystemTools::RemoveFile(fname.c_str());
- }
+ cmSystemTools::RemoveFile(fname.c_str());
}
}
diff --git a/Source/CTest/cmCTestRunTest.cxx b/Source/CTest/cmCTestRunTest.cxx
index 3e4757b..24d1d9f 100644
--- a/Source/CTest/cmCTestRunTest.cxx
+++ b/Source/CTest/cmCTestRunTest.cxx
@@ -15,6 +15,9 @@
#include "cmCTest.h"
#include "cmSystemTools.h"
+#include <cm_zlib.h>
+#include <cmsys/Base64.h>
+
cmCTestRunTest::cmCTestRunTest(cmCTestTestHandler* handler)
{
this->CTest = handler->CTest;
@@ -23,9 +26,12 @@ cmCTestRunTest::cmCTestRunTest(cmCTestTestHandler* handler)
this->TestProcess = 0;
this->TestResult.ExecutionTime =0;
this->TestResult.ReturnValue = 0;
- this->TestResult.Status = 0;
+ this->TestResult.Status = cmCTestTestHandler::NOT_RUN;
this->TestResult.TestCount = 0;
this->TestResult.Properties = 0;
+ this->ProcessOutput = "";
+ this->CompressedOutput = "";
+ this->CompressionRatio = 2;
}
cmCTestRunTest::~cmCTestRunTest()
@@ -52,7 +58,7 @@ bool cmCTestRunTest::CheckOutput()
{
// Store this line of output.
cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
- this->GetIndex() << ": " << line << std::endl);
+ this->GetIndex() << ": " << line << std::endl);
this->ProcessOutput += line;
this->ProcessOutput += "\n";
}
@@ -65,8 +71,73 @@ bool cmCTestRunTest::CheckOutput()
}
//---------------------------------------------------------
+// Streamed compression of test output. The compressed data
+// is appended to this->CompressedOutput
+void cmCTestRunTest::CompressOutput()
+{
+ int ret;
+ z_stream strm;
+
+ unsigned char* in =
+ reinterpret_cast<unsigned char*>(
+ const_cast<char*>(this->ProcessOutput.c_str()));
+ //zlib makes the guarantee that this is the maximum output size
+ int outSize = static_cast<int>(this->ProcessOutput.size() * 1.001 + 13);
+ unsigned char* out = new unsigned char[outSize];
+
+ strm.zalloc = Z_NULL;
+ strm.zfree = Z_NULL;
+ strm.opaque = Z_NULL;
+ ret = deflateInit(&strm, -1); //default compression level
+ if (ret != Z_OK)
+ {
+ return;
+ }
+
+ strm.avail_in = static_cast<uInt>(this->ProcessOutput.size());
+ strm.next_in = in;
+ strm.avail_out = outSize;
+ strm.next_out = out;
+ ret = deflate(&strm, Z_FINISH);
+
+ if(ret == Z_STREAM_ERROR || ret != Z_STREAM_END)
+ {
+ cmCTestLog(this->CTest, ERROR_MESSAGE, "Error during output "
+ "compression. Sending uncompressed output." << std::endl);
+ return;
+ }
+
+ (void)deflateEnd(&strm);
+
+ unsigned char *encoded_buffer
+ = new unsigned char[static_cast<int>(outSize * 1.5)];
+
+ unsigned long rlen
+ = cmsysBase64_Encode(out, strm.total_out, encoded_buffer, 1);
+
+ for(unsigned long i = 0; i < rlen; i++)
+ {
+ this->CompressedOutput += encoded_buffer[i];
+ }
+
+ if(strm.total_in)
+ {
+ this->CompressionRatio = static_cast<double>(strm.total_out) /
+ static_cast<double>(strm.total_in);
+ }
+
+ delete [] encoded_buffer;
+ delete [] out;
+}
+
+//---------------------------------------------------------
bool cmCTestRunTest::EndTest(size_t completed, size_t total, bool started)
{
+ if (this->CTest->ShouldCompressTestOutput())
+ {
+ this->CompressOutput();
+ }
+
//restore the old environment
if (this->ModifyEnv)
{
@@ -146,7 +217,7 @@ bool cmCTestRunTest::EndTest(size_t completed, size_t total, bool started)
}
else if ( res == cmsysProcess_State_Expired )
{
- cmCTestLog(this->CTest, HANDLER_OUTPUT, "***Timeout");
+ cmCTestLog(this->CTest, HANDLER_OUTPUT, "***Timeout ");
this->TestResult.Status = cmCTestTestHandler::TIMEOUT;
outputTestErrorsToConsole = this->CTest->OutputTestOutputOnTestFailure;
}
@@ -177,10 +248,9 @@ bool cmCTestRunTest::EndTest(size_t completed, size_t total, bool started)
this->TestResult.Status = cmCTestTestHandler::OTHER_FAULT;
}
}
- else // if ( res == cmsysProcess_State_Error )
+ else //cmsysProcess_State_Error
{
- cmCTestLog(this->CTest, HANDLER_OUTPUT, "***Bad command " << res );
- this->TestResult.Status = cmCTestTestHandler::BAD_COMMAND;
+ cmCTestLog(this->CTest, HANDLER_OUTPUT, "***Not Run ");
}
passed = this->TestResult.Status == cmCTestTestHandler::COMPLETED;
@@ -202,18 +272,11 @@ bool cmCTestRunTest::EndTest(size_t completed, size_t total, bool started)
// Output since that is what is parsed by cmCTestMemCheckHandler
if(!this->TestHandler->MemCheck && started)
{
- if (this->TestResult.Status == cmCTestTestHandler::COMPLETED)
- {
this->TestHandler->CleanTestOutput(this->ProcessOutput,
static_cast<size_t>
- (this->TestHandler->CustomMaximumPassedTestOutputSize));
- }
- else
- {
- this->TestHandler->CleanTestOutput(this->ProcessOutput,
- static_cast<size_t>
- (this->TestHandler->CustomMaximumFailedTestOutputSize));
- }
+ (this->TestResult.Status == cmCTestTestHandler::COMPLETED ?
+ this->TestHandler->CustomMaximumPassedTestOutputSize :
+ this->TestHandler->CustomMaximumFailedTestOutputSize));
}
this->TestResult.Reason = reason;
if (this->TestHandler->LogFile)
@@ -258,16 +321,23 @@ bool cmCTestRunTest::EndTest(size_t completed, size_t total, bool started)
<< "----------------------------------------------------------"
<< std::endl << std::endl;
}
+ // if the test actually started and ran
+ // record the results in TestResult
if(started)
{
- this->TestResult.Output = this->ProcessOutput;
+ bool compress = this->CompressionRatio < 1 &&
+ this->CTest->ShouldCompressTestOutput();
+ this->TestResult.Output = compress ? this->CompressedOutput
+ : this->ProcessOutput;
+ this->TestResult.CompressOutput = compress;
this->TestResult.ReturnValue = this->TestProcess->GetExitValue();
this->TestResult.CompletionStatus = "Completed";
this->TestResult.ExecutionTime = this->TestProcess->GetTotalTime();
- this->TestHandler->TestResults.push_back(this->TestResult);
-
this->MemCheckPostProcess();
}
+ // Always push the current TestResult onto the
+ // TestHandler vector
+ this->TestHandler->TestResults.push_back(this->TestResult);
delete this->TestProcess;
return passed;
}
@@ -308,16 +378,41 @@ bool cmCTestRunTest::StartTest(size_t total)
std::vector<std::string>& args = this->TestProperties->Args;
this->TestResult.Properties = this->TestProperties;
this->TestResult.ExecutionTime = 0;
+ this->TestResult.CompressOutput = false;
this->TestResult.ReturnValue = -1;
- this->TestResult.CompletionStatus = "Not Run";
- this->TestResult.Status = cmCTestTestHandler::NOT_RUN;
+ this->TestResult.CompletionStatus = "Failed to start";
+ this->TestResult.Status = cmCTestTestHandler::BAD_COMMAND;
this->TestResult.TestCount = this->TestProperties->Index;
this->TestResult.Name = this->TestProperties->Name;
this->TestResult.Path = this->TestProperties->Directory.c_str();
+ // Check if all required files exist
+ for(std::vector<std::string>::iterator i =
+ this->TestProperties->RequiredFiles.begin();
+ i != this->TestProperties->RequiredFiles.end(); ++i)
+ {
+ std::string file = *i;
+
+ if(!cmSystemTools::FileExists(file.c_str()))
+ {
+ //Required file was not found
+ this->TestProcess = new cmProcess;
+ *this->TestHandler->LogFile << "Unable to find required file: "
+ << file.c_str() << std::endl;
+ cmCTestLog(this->CTest, ERROR_MESSAGE, "Unable to find required file: "
+ << file.c_str() << std::endl);
+ this->TestResult.Output = "Unable to find required file: " + file;
+ this->TestResult.FullCommandLine = "";
+ this->TestResult.CompletionStatus = "Not Run";
+ this->TestResult.Status = cmCTestTestHandler::NOT_RUN;
+ return false;
+ }
+ }
// log and return if we did not find the executable
if (this->ActualCommand == "")
{
+ // if the command was not found create a TestResult object
+ // that has that information
this->TestProcess = new cmProcess;
*this->TestHandler->LogFile << "Unable to find executable: "
<< args[1].c_str() << std::endl;
@@ -325,7 +420,8 @@ bool cmCTestRunTest::StartTest(size_t total)
<< args[1].c_str() << std::endl);
this->TestResult.Output = "Unable to find executable: " + args[1];
this->TestResult.FullCommandLine = "";
- this->TestHandler->TestResults.push_back(this->TestResult);
+ this->TestResult.CompletionStatus = "Not Run";
+ this->TestResult.Status = cmCTestTestHandler::NOT_RUN;
return false;
}
this->StartTime = this->CTest->CurrentTime();
diff --git a/Source/CTest/cmCTestRunTest.h b/Source/CTest/cmCTestRunTest.h
index bfeda20..1084643 100644
--- a/Source/CTest/cmCTestRunTest.h
+++ b/Source/CTest/cmCTestRunTest.h
@@ -45,6 +45,9 @@ public:
// Read and store output. Returns true if it must be called again.
bool CheckOutput();
+ // Compresses the output, writing to CompressedOutput
+ void CompressOutput();
+
//launch the test process, return whether it started correctly
bool StartTest(size_t total);
//capture and report the test results
@@ -53,6 +56,7 @@ public:
void ComputeArguments();
private:
void DartProcessing();
+ void ExeNotFound(std::string exe);
bool CreateProcess(double testTimeOut,
std::vector<std::string>* environment);
void WriteLogOutputTop(size_t completed, size_t total);
@@ -71,9 +75,15 @@ private:
//flag for whether the env was modified for this run
bool ModifyEnv;
+
+ bool UsePrefixCommand;
+ std::string PrefixCommand;
+
//stores the original environment if we are modifying it
std::vector<std::string> OrigEnv;
std::string ProcessOutput;
+ std::string CompressedOutput;
+ double CompressionRatio;
//The test results
cmCTestTestHandler::cmCTestTestResult TestResult;
int Index;
@@ -96,5 +106,6 @@ inline int getNumWidth(size_t n)
}
return numWidth;
}
+
#endif
diff --git a/Source/CTest/cmCTestSVN.cxx b/Source/CTest/cmCTestSVN.cxx
index 82e5845..fab9a8c 100644
--- a/Source/CTest/cmCTestSVN.cxx
+++ b/Source/CTest/cmCTestSVN.cxx
@@ -440,3 +440,11 @@ void cmCTestSVN::LoadModifications()
OutputLogger err(this->Log, "status-err> ");
this->RunChild(svn_status, &out, &err);
}
+
+//----------------------------------------------------------------------------
+void cmCTestSVN::WriteXMLGlobal(std::ostream& xml)
+{
+ this->cmCTestGlobalVC::WriteXMLGlobal(xml);
+
+ xml << "\t<SVNPath>" << this->Base << "</SVNPath>\n";
+}
diff --git a/Source/CTest/cmCTestSVN.h b/Source/CTest/cmCTestSVN.h
index ff9ff0f..f72c58f 100644
--- a/Source/CTest/cmCTestSVN.h
+++ b/Source/CTest/cmCTestSVN.h
@@ -52,6 +52,8 @@ private:
void DoRevision(Revision const& revision,
std::vector<Change> const& changes);
+ void WriteXMLGlobal(std::ostream& xml);
+
// Parsing helper classes.
class InfoParser;
class LogParser;
diff --git a/Source/CTest/cmCTestScriptHandler.cxx b/Source/CTest/cmCTestScriptHandler.cxx
index 5983e68..fdf17e0 100644
--- a/Source/CTest/cmCTestScriptHandler.cxx
+++ b/Source/CTest/cmCTestScriptHandler.cxx
@@ -583,6 +583,10 @@ void cmCTestScriptHandler::SleepInSeconds(unsigned int secondsToWait)
int cmCTestScriptHandler::RunConfigurationScript
(const std::string& total_script_arg, bool pscope)
{
+#ifdef CMAKE_BUILD_WITH_CMAKE
+ cmSystemTools::SaveRestoreEnvironment sre;
+#endif
+
int result;
this->ScriptStartTime =
diff --git a/Source/CTest/cmCTestStartCommand.cxx b/Source/CTest/cmCTestStartCommand.cxx
index 779a38c..228a173 100644
--- a/Source/CTest/cmCTestStartCommand.cxx
+++ b/Source/CTest/cmCTestStartCommand.cxx
@@ -14,6 +14,13 @@
#include "cmCTest.h"
#include "cmLocalGenerator.h"
#include "cmGlobalGenerator.h"
+#include "cmCTestVC.h"
+#include "cmGeneratedFileStream.h"
+
+cmCTestStartCommand::cmCTestStartCommand()
+{
+ this->CreateNewTag = true;
+}
bool cmCTestStartCommand
::InitialPass(std::vector<std::string> const& args, cmExecutionStatus &)
@@ -42,6 +49,15 @@ bool cmCTestStartCommand
}
}
+ if (cnt < args.size())
+ {
+ if (args[cnt] == "APPEND")
+ {
+ cnt ++;
+ this->CreateNewTag = false;
+ }
+ }
+
if ( cnt < args.size() )
{
src_dir = args[cnt].c_str();
@@ -76,10 +92,11 @@ bool cmCTestStartCommand
cmSystemTools::AddKeepPath(bld_dir);
this->CTest->EmptyCTestConfiguration();
- this->CTest->SetCTestConfiguration("SourceDirectory",
- cmSystemTools::CollapseFullPath(src_dir).c_str());
- this->CTest->SetCTestConfiguration("BuildDirectory",
- cmSystemTools::CollapseFullPath(bld_dir).c_str());
+
+ std::string sourceDir = cmSystemTools::CollapseFullPath(src_dir);
+ std::string binaryDir = cmSystemTools::CollapseFullPath(bld_dir);
+ this->CTest->SetCTestConfiguration("SourceDirectory", sourceDir.c_str());
+ this->CTest->SetCTestConfiguration("BuildDirectory", binaryDir.c_str());
cmCTestLog(this->CTest, HANDLER_OUTPUT, "Run dashboard with model "
<< smodel << std::endl
@@ -92,13 +109,62 @@ bool cmCTestStartCommand
" Track: " << track << std::endl);
}
+ // Log startup actions.
+ std::string startLogFile = binaryDir + "/Testing/Temporary/LastStart.log";
+ cmGeneratedFileStream ofs(startLogFile.c_str());
+ if(!ofs)
+ {
+ cmCTestLog(this->CTest, ERROR_MESSAGE,
+ "Cannot create log file: LastStart.log" << std::endl);
+ return false;
+ }
+
+ // Make sure the source directory exists.
+ if(!this->InitialCheckout(ofs, sourceDir))
+ {
+ return false;
+ }
+ if(!cmSystemTools::FileIsDirectory(sourceDir.c_str()))
+ {
+ cmOStringStream e;
+ e << "given source path\n"
+ << " " << sourceDir << "\n"
+ << "which is not an existing directory. "
+ << "Set CTEST_CHECKOUT_COMMAND to a command line to create it.";
+ this->SetError(e.str().c_str());
+ return false;
+ }
+
this->Makefile->AddDefinition("CTEST_RUN_CURRENT_SCRIPT", "OFF");
this->CTest->SetSuppressUpdatingCTestConfiguration(true);
int model = this->CTest->GetTestModelFromString(smodel);
this->CTest->SetTestModel(model);
this->CTest->SetProduceXML(true);
- return this->CTest->InitializeFromCommand(this, true);
+ return this->CTest->InitializeFromCommand(this);
}
-
+//----------------------------------------------------------------------------
+bool cmCTestStartCommand::InitialCheckout(
+ std::ostream& ofs, std::string const& sourceDir)
+{
+ // Use the user-provided command to create the source tree.
+ const char* initialCheckoutCommand
+ = this->Makefile->GetDefinition("CTEST_CHECKOUT_COMMAND");
+ if(!initialCheckoutCommand)
+ {
+ initialCheckoutCommand =
+ this->Makefile->GetDefinition("CTEST_CVS_CHECKOUT");
+ }
+ if(initialCheckoutCommand)
+ {
+ // Use a generic VC object to run and log the command.
+ cmCTestVC vc(this->CTest, ofs);
+ vc.SetSourceDirectory(sourceDir.c_str());
+ if(!vc.InitialCheckout(initialCheckoutCommand))
+ {
+ return false;
+ }
+ }
+ return true;
+}
diff --git a/Source/CTest/cmCTestStartCommand.h b/Source/CTest/cmCTestStartCommand.h
index 84f7631..afbc77b 100644
--- a/Source/CTest/cmCTestStartCommand.h
+++ b/Source/CTest/cmCTestStartCommand.h
@@ -23,7 +23,7 @@ class cmCTestStartCommand : public cmCTestCommand
{
public:
- cmCTestStartCommand() {}
+ cmCTestStartCommand();
/**
* This is a virtual constructor for the command.
@@ -33,6 +33,7 @@ public:
cmCTestStartCommand* ni = new cmCTestStartCommand;
ni->CTest = this->CTest;
ni->CTestScriptHandler = this->CTestScriptHandler;
+ ni->CreateNewTag = this->CreateNewTag;
return ni;
}
@@ -44,6 +45,14 @@ public:
cmExecutionStatus &status);
/**
+ * Will this invocation of ctest_start create a new TAG file?
+ */
+ bool ShouldCreateNewTag()
+ {
+ return this->CreateNewTag;
+ }
+
+ /**
* The name of the command as specified in CMakeList.txt.
*/
virtual const char* GetName() { return "ctest_start";}
@@ -62,16 +71,21 @@ public:
virtual const char* GetFullDocumentation()
{
return
- " ctest_start(Model [TRACK <track>] [source [binary]])\n"
+ " ctest_start(Model [TRACK <track>] [APPEND] [source [binary]])\n"
"Starts the testing for a given model. The command should be called "
"after the binary directory is initialized. If the 'source' and "
"'binary' directory are not specified, it reads the "
"CTEST_SOURCE_DIRECTORY and CTEST_BINARY_DIRECTORY. If the track is "
- "specified, the submissions will go to the specified track.";
+ "specified, the submissions will go to the specified track. "
+ "If APPEND is used, the existing TAG is used rather than "
+ "creating a new one based on the current time stamp.";
}
cmTypeMacro(cmCTestStartCommand, cmCTestCommand);
+private:
+ bool InitialCheckout(std::ostream& ofs, std::string const& sourceDir);
+ bool CreateNewTag;
};
diff --git a/Source/CTest/cmCTestSubmitHandler.cxx b/Source/CTest/cmCTestSubmitHandler.cxx
index cbef1f1..7b4f38b 100644
--- a/Source/CTest/cmCTestSubmitHandler.cxx
+++ b/Source/CTest/cmCTestSubmitHandler.cxx
@@ -72,6 +72,8 @@ void cmCTestSubmitHandler::Initialize()
this->SubmitPart[p] = true;
}
this->CDash = false;
+ this->HasWarnings = false;
+ this->HasErrors = false;
this->Superclass::Initialize();
this->HTTPProxy = "";
this->HTTPProxyType = 0;
@@ -309,7 +311,12 @@ bool cmCTestSubmitHandler::SubmitUsingHTTP(const cmStdString& localprefix,
}
}
}
-
+ if(this->CTest->ShouldUseHTTP10())
+ {
+ curl_easy_setopt(curl, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0);
+ }
+ // enable HTTP ERROR parsing
+ curl_easy_setopt(curl, CURLOPT_FAILONERROR, 1);
/* enable uploading */
curl_easy_setopt(curl, CURLOPT_UPLOAD, 1);
@@ -409,6 +416,7 @@ bool cmCTestSubmitHandler::SubmitUsingHTTP(const cmStdString& localprefix,
cmCTestLog(this->CTest, DEBUG, "CURL output: ["
<< cmCTestLogWrite(&*chunk.begin(), chunk.size()) << "]"
<< std::endl);
+ this->ParseResponse(chunk);
}
if ( chunkDebug.size() > 0 )
{
@@ -455,6 +463,36 @@ bool cmCTestSubmitHandler::SubmitUsingHTTP(const cmStdString& localprefix,
}
//----------------------------------------------------------------------------
+void cmCTestSubmitHandler
+::ParseResponse(cmCTestSubmitHandlerVectorOfChar chunk)
+{
+ std::string output = "";
+
+ for(cmCTestSubmitHandlerVectorOfChar::iterator i = chunk.begin();
+ i != chunk.end(); ++i)
+ {
+ output += *i;
+ }
+ output = cmSystemTools::UpperCase(output);
+
+ if(output.find("WARNING") != std::string::npos)
+ {
+ this->HasWarnings = true;
+ }
+ if(output.find("ERROR") != std::string::npos)
+ {
+ this->HasErrors = true;
+ }
+
+ if(this->HasWarnings || this->HasErrors)
+ {
+ cmCTestLog(this->CTest, HANDLER_OUTPUT, " Server Response:\n" <<
+ cmCTestLogWrite(&*chunk.begin(), chunk.size()) << "\n");
+ }
+
+}
+
+//----------------------------------------------------------------------------
bool cmCTestSubmitHandler::TriggerUsingHTTP(
const std::set<cmStdString>& files,
const cmStdString& remoteprefix,
@@ -1149,9 +1187,20 @@ int cmCTestSubmitHandler::ProcessHandler()
return -1;
}
}
- cmCTestLog(this->CTest, HANDLER_OUTPUT, " Submission successful"
- << std::endl);
- ofs << " Submission successful" << std::endl;
+ if(this->HasErrors)
+ {
+ cmCTestLog(this->CTest, HANDLER_OUTPUT, " Errors occurred during "
+ "submission." << std::endl);
+ ofs << " Errors occurred during submission. " << std::endl;
+ }
+ else
+ {
+ cmCTestLog(this->CTest, HANDLER_OUTPUT, " Submission successful" <<
+ (this->HasWarnings ? ", with warnings." : "") << std::endl);
+ ofs << " Submission successful" <<
+ (this->HasWarnings ? ", with warnings." : "") << std::endl;
+ }
+
return 0;
}
else if ( dropMethod == "xmlrpc" )
diff --git a/Source/CTest/cmCTestSubmitHandler.h b/Source/CTest/cmCTestSubmitHandler.h
index d93f94d..8b011ea 100644
--- a/Source/CTest/cmCTestSubmitHandler.h
+++ b/Source/CTest/cmCTestSubmitHandler.h
@@ -75,6 +75,8 @@ private:
const cmStdString& remoteprefix,
const cmStdString& url);
+ void ParseResponse(std::vector<char>);
+
std::string GetSubmitResultsPrefix();
cmStdString HTTPProxy;
@@ -85,6 +87,8 @@ private:
std::ostream* LogFile;
bool SubmitPart[cmCTest::PartCount];
bool CDash;
+ bool HasWarnings;
+ bool HasErrors;
cmCTest::SetOfStrings Files;
};
diff --git a/Source/CTest/cmCTestTestCommand.cxx b/Source/CTest/cmCTestTestCommand.cxx
index a719b09..b0adf22 100644
--- a/Source/CTest/cmCTestTestCommand.cxx
+++ b/Source/CTest/cmCTestTestCommand.cxx
@@ -24,6 +24,7 @@ cmCTestTestCommand::cmCTestTestCommand()
this->Arguments[ctt_EXCLUDE_LABEL] = "EXCLUDE_LABEL";
this->Arguments[ctt_INCLUDE_LABEL] = "INCLUDE_LABEL";
this->Arguments[ctt_PARALLEL_LEVEL] = "PARALLEL_LEVEL";
+ this->Arguments[ctt_SCHEDULE_RANDOM] = "SCHEDULE_RANDOM";
this->Arguments[ctt_LAST] = 0;
this->Last = ctt_LAST;
}
@@ -32,6 +33,7 @@ cmCTestGenericHandler* cmCTestTestCommand::InitializeHandler()
{
const char* ctestTimeout =
this->Makefile->GetDefinition("CTEST_TEST_TIMEOUT");
+
double timeout = this->CTest->GetTimeOut();
if ( ctestTimeout )
{
@@ -91,6 +93,11 @@ cmCTestGenericHandler* cmCTestTestCommand::InitializeHandler()
handler->SetOption("ParallelLevel",
this->Values[ctt_PARALLEL_LEVEL]);
}
+ if(this->Values[ctt_SCHEDULE_RANDOM])
+ {
+ handler->SetOption("ScheduleRandom",
+ this->Values[ctt_SCHEDULE_RANDOM]);
+ }
return handler;
}
@@ -98,4 +105,3 @@ cmCTestGenericHandler* cmCTestTestCommand::InitializeActualHandler()
{
return this->CTest->GetInitializedHandler("test");
}
-
diff --git a/Source/CTest/cmCTestTestCommand.h b/Source/CTest/cmCTestTestCommand.h
index 73ce913..12314df 100644
--- a/Source/CTest/cmCTestTestCommand.h
+++ b/Source/CTest/cmCTestTestCommand.h
@@ -61,7 +61,8 @@ public:
" [INCLUDE include regex] [RETURN_VALUE res] \n"
" [EXCLUDE_LABEL exclude regex] \n"
" [INCLUDE_LABEL label regex] \n"
- " [PARALLEL_LEVEL level]) \n"
+ " [PARALLEL_LEVEL level] \n"
+ " [SCHEDULE_RANDOM on]) \n"
"Tests the given build directory and stores results in Test.xml. The "
"second argument is a variable that will hold value. Optionally, "
"you can specify the starting test number START, the ending test number "
@@ -70,7 +71,9 @@ public:
"to not run EXCLUDE. EXCLUDE_LABEL and INCLUDE_LABEL are regular "
"expression for test to be included or excluded by the test "
"property LABEL. PARALLEL_LEVEL should be set to a positive number "
- "representing the number of tests to be run in parallel."
+ "representing the number of tests to be run in parallel. "
+ "SCHEDULE_RANDOM will launch tests in a random order, and is "
+ "typically used to detect implicit test dependencies."
"\n"
CTEST_COMMAND_APPEND_OPTION_DOCS;
}
@@ -92,6 +95,7 @@ protected:
ctt_EXCLUDE_LABEL,
ctt_INCLUDE_LABEL,
ctt_PARALLEL_LEVEL,
+ ctt_SCHEDULE_RANDOM,
ctt_LAST
};
};
diff --git a/Source/CTest/cmCTestTestHandler.cxx b/Source/CTest/cmCTestTestHandler.cxx
index 2491d19..78f2c30 100644
--- a/Source/CTest/cmCTestTestHandler.cxx
+++ b/Source/CTest/cmCTestTestHandler.cxx
@@ -500,11 +500,16 @@ int cmCTestTestHandler::ProcessHandler()
{
// Update internal data structure from generic one
this->SetTestsToRunInformation(this->GetOption("TestsToRunInformation"));
- this->SetUseUnion(cmSystemTools::IsOn(this->GetOption("UseUnion")));
+ this->SetUseUnion(cmSystemTools::IsOn(this->GetOption("UseUnion")));
+ if(cmSystemTools::IsOn(this->GetOption("ScheduleRandom")))
+ {
+ this->CTest->SetScheduleType("Random");
+ }
if(this->GetOption("ParallelLevel"))
{
this->CTest->SetParallelLevel(atoi(this->GetOption("ParallelLevel")));
}
+
const char* val;
val = this->GetOption("LabelRegularExpression");
if ( val )
@@ -684,13 +689,12 @@ void cmCTestTestHandler::PrintLabelSummary()
}
}
}
- it = this->TestList.begin();
ri = this->TestResults.begin();
// fill maps
- for(; it != this->TestList.end(); ++it, ++ri)
+ for(; ri != this->TestResults.end(); ++ri)
{
- cmCTestTestProperties& p = *it;
- cmCTestTestResult &result = *ri;
+ cmCTestTestResult &result = *ri;
+ cmCTestTestProperties& p = *result.Properties;
if(p.Labels.size() != 0)
{
for(std::vector<std::string>::iterator l = p.Labels.begin();
@@ -1030,12 +1034,28 @@ void cmCTestTestHandler::ProcessDirectory(std::vector<cmStdString> &passed,
cmCTestMultiProcessHandler::TestMap tests;
cmCTestMultiProcessHandler::PropertiesMap properties;
+ bool randomSchedule = this->CTest->GetScheduleType() == "Random";
+ if(randomSchedule)
+ {
+ srand((unsigned)time(0));
+ }
+
for (ListOfTests::iterator it = this->TestList.begin();
it != this->TestList.end(); ++it)
{
cmCTestTestProperties& p = *it;
cmCTestMultiProcessHandler::TestSet depends;
+ if(randomSchedule)
+ {
+ p.Cost = rand();
+ }
+
+ if(p.Timeout == 0 && this->CTest->GetGlobalTimeout() != 0)
+ {
+ p.Timeout = this->CTest->GetGlobalTimeout();
+ }
+
if(p.Depends.size())
{
for(std::vector<std::string>::iterator i = p.Depends.begin();
@@ -1166,12 +1186,17 @@ void cmCTestTestHandler::GenerateDartOutput(std::ostream& os)
}
os
<< "\t\t\t<Measurement>\n"
- << "\t\t\t\t<Value>";
+ << "\t\t\t\t<Value"
+ << (result->CompressOutput ?
+ " encoding=\"base64\" compression=\"gzip\">"
+ : ">");
os << cmXMLSafe(result->Output);
os
<< "</Value>\n"
<< "\t\t\t</Measurement>\n"
<< "\t\t</Results>\n";
+
+ this->AttachFiles(os, result);
this->WriteTestResultFooter(os, result);
}
@@ -1234,6 +1259,73 @@ void cmCTestTestHandler::WriteTestResultFooter(std::ostream& os,
}
//----------------------------------------------------------------------
+void cmCTestTestHandler::AttachFiles(std::ostream& os,
+ cmCTestTestResult* result)
+{
+ if(result->Status != cmCTestTestHandler::COMPLETED
+ && result->Properties->AttachOnFail.size())
+ {
+ result->Properties->AttachedFiles.insert(
+ result->Properties->AttachedFiles.end(),
+ result->Properties->AttachOnFail.begin(),
+ result->Properties->AttachOnFail.end());
+ }
+ for(std::vector<std::string>::const_iterator file =
+ result->Properties->AttachedFiles.begin();
+ file != result->Properties->AttachedFiles.end(); ++file)
+ {
+ std::string base64 = this->EncodeFile(*file);
+ std::string fname = cmSystemTools::GetFilenameName(*file);
+ os << "\t\t<NamedMeasurement name=\"Attached File\" encoding=\"base64\" "
+ "compression=\"tar/gzip\" filename=\"" << fname << "\" type=\"file\">"
+ "\n\t\t\t<Value>\n\t\t\t"
+ << base64
+ << "\n\t\t\t</Value>\n\t\t</NamedMeasurement>\n";
+ }
+}
+
+//----------------------------------------------------------------------
+std::string cmCTestTestHandler::EncodeFile(std::string file)
+{
+ std::string tarFile = file + "_temp.tar.gz";
+ std::vector<cmStdString> files;
+ files.push_back(file);
+
+ if(!cmSystemTools::CreateTar(tarFile.c_str(), files, true, false))
+ {
+ cmCTestLog(this->CTest, ERROR_MESSAGE, "Error creating tar while "
+ "attaching file: " << file << std::endl);
+ return "";
+ }
+ long len = cmSystemTools::FileLength(tarFile.c_str());
+ std::ifstream ifs(tarFile.c_str(), std::ios::in
+#ifdef _WIN32
+ | std::ios::binary
+#endif
+ );
+ unsigned char *file_buffer = new unsigned char [ len + 1 ];
+ ifs.read(reinterpret_cast<char*>(file_buffer), len);
+ ifs.close();
+ cmSystemTools::RemoveFile(tarFile.c_str());
+
+ unsigned char *encoded_buffer
+ = new unsigned char [ static_cast<int>(len * 1.5 + 5) ];
+
+ unsigned long rlen
+ = cmsysBase64_Encode(file_buffer, len, encoded_buffer, 1);
+
+ std::string base64 = "";
+ for(unsigned long i = 0; i < rlen; i++)
+ {
+ base64 += encoded_buffer[i];
+ }
+ delete [] file_buffer;
+ delete [] encoded_buffer;
+
+ return base64;
+}
+
+//----------------------------------------------------------------------
int cmCTestTestHandler::ExecuteCommands(std::vector<cmStdString>& vec)
{
std::vector<cmStdString>::iterator it;
@@ -1274,7 +1366,7 @@ void cmCTestTestHandler
std::vector<std::string> &attemptedConfigs,
std::string filepath,
std::string &filename)
-{
+{
std::string tempPath;
if (filepath.size() &&
@@ -1985,6 +2077,28 @@ bool cmCTestTestHandler::SetTestsProperties(
{
rtit->WillFail = cmSystemTools::IsOn(val.c_str());
}
+ if ( key == "ATTACHED_FILES" )
+ {
+ std::vector<std::string> lval;
+ cmSystemTools::ExpandListArgument(val.c_str(), lval);
+
+ for(std::vector<std::string>::iterator f = lval.begin();
+ f != lval.end(); ++f)
+ {
+ rtit->AttachedFiles.push_back(*f);
+ }
+ }
+ if ( key == "ATTACHED_FILES_ON_FAIL" )
+ {
+ std::vector<std::string> lval;
+ cmSystemTools::ExpandListArgument(val.c_str(), lval);
+
+ for(std::vector<std::string>::iterator f = lval.begin();
+ f != lval.end(); ++f)
+ {
+ rtit->AttachOnFail.push_back(*f);
+ }
+ }
if ( key == "TIMEOUT" )
{
rtit->Timeout = atof(val.c_str());
@@ -1993,6 +2107,17 @@ bool cmCTestTestHandler::SetTestsProperties(
{
rtit->Cost = static_cast<float>(atof(val.c_str()));
}
+ if ( key == "REQUIRED_FILES" )
+ {
+ std::vector<std::string> lval;
+ cmSystemTools::ExpandListArgument(val.c_str(), lval);
+
+ for(std::vector<std::string>::iterator f = lval.begin();
+ f != lval.end(); ++f)
+ {
+ rtit->RequiredFiles.push_back(*f);
+ }
+ }
if ( key == "RUN_SERIAL" )
{
rtit->RunSerial = cmSystemTools::IsOn(val.c_str());
@@ -2088,6 +2213,7 @@ bool cmCTestTestHandler::AddTest(const std::vector<std::string>& args)
{
const std::string& testname = args[0];
cmCTestLog(this->CTest, DEBUG, "Add test: " << args[0] << std::endl);
+
if (this->UseExcludeRegExpFlag &&
this->UseExcludeRegExpFirst &&
this->ExcludeTestsRegularExpression.find(testname.c_str()))
diff --git a/Source/CTest/cmCTestTestHandler.h b/Source/CTest/cmCTestTestHandler.h
index ceb5020..1513410 100644
--- a/Source/CTest/cmCTestTestHandler.h
+++ b/Source/CTest/cmCTestTestHandler.h
@@ -84,7 +84,10 @@ public:
cmStdString Name;
cmStdString Directory;
std::vector<std::string> Args;
+ std::vector<std::string> RequiredFiles;
std::vector<std::string> Depends;
+ std::vector<std::string> AttachedFiles;
+ std::vector<std::string> AttachOnFail;
std::vector<std::pair<cmsys::RegularExpression,
std::string> > ErrorRegularExpressions;
std::vector<std::pair<cmsys::RegularExpression,
@@ -111,6 +114,7 @@ public:
double ExecutionTime;
int ReturnValue;
int Status;
+ bool CompressOutput;
std::string CompletionStatus;
std::string Output;
std::string RegressionImages;
@@ -142,6 +146,10 @@ protected:
void WriteTestResultHeader(std::ostream& os, cmCTestTestResult* result);
void WriteTestResultFooter(std::ostream& os, cmCTestTestResult* result);
+ // Write attached test files into the xml
+ void AttachFiles(std::ostream& os, cmCTestTestResult* result);
+ // Helper function to encode attached test files
+ std::string EncodeFile(std::string file);
//! Clean test output to specified length
bool CleanTestOutput(std::string& output, size_t length);
diff --git a/Source/CTest/cmCTestUpdateCommand.cxx b/Source/CTest/cmCTestUpdateCommand.cxx
index 6dbe815..571745d 100644
--- a/Source/CTest/cmCTestUpdateCommand.cxx
+++ b/Source/CTest/cmCTestUpdateCommand.cxx
@@ -56,14 +56,6 @@ cmCTestGenericHandler* cmCTestUpdateCommand::InitializeHandler()
this->CTest->SetCTestConfigurationFromCMakeVariable(this->Makefile,
"HGUpdateOptions", "CTEST_HG_UPDATE_OPTIONS");
- const char* initialCheckoutCommand
- = this->Makefile->GetDefinition("CTEST_CHECKOUT_COMMAND");
- if ( !initialCheckoutCommand )
- {
- initialCheckoutCommand =
- this->Makefile->GetDefinition("CTEST_CVS_CHECKOUT");
- }
-
cmCTestGenericHandler* handler
= this->CTest->GetInitializedHandler("update");
if ( !handler )
@@ -78,24 +70,6 @@ cmCTestGenericHandler* cmCTestUpdateCommand::InitializeHandler()
return 0;
}
handler->SetOption("SourceDirectory", source_dir.c_str());
- if ( initialCheckoutCommand )
- {
- handler->SetOption("InitialCheckout", initialCheckoutCommand);
- }
- if ( (!cmSystemTools::FileExists(source_dir.c_str()) ||
- !cmSystemTools::FileIsDirectory(source_dir.c_str()))
- && !initialCheckoutCommand )
- {
- cmOStringStream str;
- str << "cannot find source directory: " << source_dir.c_str() << ".";
- if ( !cmSystemTools::FileExists(source_dir.c_str()) )
- {
- str << " Looks like it is not checked out yet. Please specify "
- "CTEST_CHECKOUT_COMMAND.";
- }
- this->SetError(str.str().c_str());
- return 0;
- }
return handler;
}
diff --git a/Source/CTest/cmCTestUpdateHandler.cxx b/Source/CTest/cmCTestUpdateHandler.cxx
index cd2f661..f87b37c 100644
--- a/Source/CTest/cmCTestUpdateHandler.cxx
+++ b/Source/CTest/cmCTestUpdateHandler.cxx
@@ -201,15 +201,6 @@ int cmCTestUpdateHandler::ProcessHandler()
this->StartLogFile("Update", ofs);
}
- cmCTestLog(this->CTest, HANDLER_OUTPUT,
- "Updating the repository" << std::endl);
-
- // Make sure the source directory exists.
- if(!this->InitialCheckout(ofs))
- {
- return -1;
- }
-
cmCTestLog(this->CTest, HANDLER_OUTPUT, " Updating the repository: "
<< sourceDirectory << std::endl);
@@ -267,7 +258,8 @@ int cmCTestUpdateHandler::ProcessHandler()
<< this->CTest->GetTestModelString() << "</BuildStamp>" << std::endl;
os << "\t<StartDateTime>" << start_time << "</StartDateTime>\n"
<< "\t<StartTime>" << start_time_time << "</StartTime>\n"
- << "\t<UpdateCommand>" << cmXMLSafe(vc->GetUpdateCommandLine())
+ << "\t<UpdateCommand>"
+ << cmXMLSafe(vc->GetUpdateCommandLine()).Quotes(false)
<< "</UpdateCommand>\n"
<< "\t<UpdateType>" << cmXMLSafe(
cmCTestUpdateHandlerUpdateToString(this->UpdateType))
@@ -323,32 +315,6 @@ int cmCTestUpdateHandler::ProcessHandler()
}
//----------------------------------------------------------------------
-bool cmCTestUpdateHandler::InitialCheckout(std::ostream& ofs)
-{
- // Use the user-provided command to create the source tree.
- if(const char* command = this->GetOption("InitialCheckout"))
- {
- // Use a generic VC object to run and log the command.
- cmCTestVC vc(this->CTest, ofs);
- vc.SetSourceDirectory(this->GetOption("SourceDirectory"));
- if(!vc.InitialCheckout(command))
- {
- return false;
- }
-
- if(!this->CTest->InitializeFromCommand(this->Command))
- {
- cmCTestLog(this->CTest, HANDLER_OUTPUT,
- " Fatal Error in initialize: "
- << std::endl);
- cmSystemTools::SetFatalErrorOccured();
- return false;
- }
- }
- return true;
-}
-
-//----------------------------------------------------------------------
int cmCTestUpdateHandler::DetectVCS(const char* dir)
{
std::string sourceDirectory = dir;
diff --git a/Source/CTest/cmCTestUpdateHandler.h b/Source/CTest/cmCTestUpdateHandler.h
index 78426ea..55ec974 100644
--- a/Source/CTest/cmCTestUpdateHandler.h
+++ b/Source/CTest/cmCTestUpdateHandler.h
@@ -65,7 +65,6 @@ private:
std::string UpdateCommand;
int UpdateType;
- bool InitialCheckout(std::ostream& ofs);
int DetectVCS(const char* dir);
bool SelectVCS();
};
diff --git a/Source/CTest/cmProcess.cxx b/Source/CTest/cmProcess.cxx
index 1895066..b028cc0 100644
--- a/Source/CTest/cmProcess.cxx
+++ b/Source/CTest/cmProcess.cxx
@@ -79,7 +79,10 @@ bool cmProcess::Buffer::GetLine(std::string& line)
// Extract the range first..last as a line.
const char* text = &*this->begin() + this->First;
size_type length = this->Last - this->First;
- length -= (length && text[length-1] == '\r')? 1:0;
+ while(length && text[length-1] == '\r')
+ {
+ length --;
+ }
line.assign(text, length);
// Start a new range for the next line.