summaryrefslogtreecommitdiffstats
path: root/Source/CTest
diff options
context:
space:
mode:
Diffstat (limited to 'Source/CTest')
-rw-r--r--Source/CTest/cmCTestBuildCommand.cxx6
-rw-r--r--Source/CTest/cmCTestBuildHandler.cxx1
-rw-r--r--Source/CTest/cmCTestConfigureCommand.cxx6
-rw-r--r--Source/CTest/cmCTestConfigureHandler.cxx1
-rw-r--r--Source/CTest/cmCTestMemCheckHandler.cxx1
-rw-r--r--Source/CTest/cmCTestRunTest.cxx5
-rw-r--r--Source/CTest/cmCTestScriptHandler.cxx2
-rw-r--r--Source/CTest/cmCTestTestCommand.cxx6
-rw-r--r--Source/CTest/cmCTestTestHandler.cxx207
-rw-r--r--Source/CTest/cmCTestTestHandler.h10
-rw-r--r--Source/CTest/cmProcess.cxx5
-rw-r--r--Source/CTest/cmProcess.h1
12 files changed, 234 insertions, 17 deletions
diff --git a/Source/CTest/cmCTestBuildCommand.cxx b/Source/CTest/cmCTestBuildCommand.cxx
index 4c82760..64ef8de 100644
--- a/Source/CTest/cmCTestBuildCommand.cxx
+++ b/Source/CTest/cmCTestBuildCommand.cxx
@@ -153,6 +153,12 @@ cmCTestGenericHandler* cmCTestBuildCommand::InitializeHandler()
this->Quiet);
}
+ if (const char* labelsForSubprojects =
+ this->Makefile->GetDefinition("CTEST_LABELS_FOR_SUBPROJECTS")) {
+ this->CTest->SetCTestConfiguration("LabelsForSubprojects",
+ labelsForSubprojects, this->Quiet);
+ }
+
handler->SetQuiet(this->Quiet);
return handler;
}
diff --git a/Source/CTest/cmCTestBuildHandler.cxx b/Source/CTest/cmCTestBuildHandler.cxx
index 18ef05c..f9116e3 100644
--- a/Source/CTest/cmCTestBuildHandler.cxx
+++ b/Source/CTest/cmCTestBuildHandler.cxx
@@ -488,6 +488,7 @@ int cmCTestBuildHandler::ProcessHandler()
void cmCTestBuildHandler::GenerateXMLHeader(cmXMLWriter& xml)
{
this->CTest->StartXML(xml, this->AppendXML);
+ this->CTest->GenerateSubprojectsOutput(xml);
xml.StartElement("Build");
xml.Element("StartDateTime", this->StartBuild);
xml.Element("StartBuildTime",
diff --git a/Source/CTest/cmCTestConfigureCommand.cxx b/Source/CTest/cmCTestConfigureCommand.cxx
index 73e893d..aca5bd3 100644
--- a/Source/CTest/cmCTestConfigureCommand.cxx
+++ b/Source/CTest/cmCTestConfigureCommand.cxx
@@ -141,6 +141,12 @@ cmCTestGenericHandler* cmCTestConfigureCommand::InitializeHandler()
}
}
+ if (const char* labelsForSubprojects =
+ this->Makefile->GetDefinition("CTEST_LABELS_FOR_SUBPROJECTS")) {
+ this->CTest->SetCTestConfiguration("LabelsForSubprojects",
+ labelsForSubprojects, this->Quiet);
+ }
+
cmCTestGenericHandler* handler =
this->CTest->GetInitializedHandler("configure");
if (!handler) {
diff --git a/Source/CTest/cmCTestConfigureHandler.cxx b/Source/CTest/cmCTestConfigureHandler.cxx
index 5d87f3f..56a038e 100644
--- a/Source/CTest/cmCTestConfigureHandler.cxx
+++ b/Source/CTest/cmCTestConfigureHandler.cxx
@@ -73,6 +73,7 @@ int cmCTestConfigureHandler::ProcessHandler()
if (os) {
cmXMLWriter xml(os);
this->CTest->StartXML(xml, this->AppendXML);
+ this->CTest->GenerateSubprojectsOutput(xml);
xml.StartElement("Configure");
xml.Element("StartDateTime", start_time);
xml.Element("StartConfigureTime", start_time_time);
diff --git a/Source/CTest/cmCTestMemCheckHandler.cxx b/Source/CTest/cmCTestMemCheckHandler.cxx
index c35f0bc..6026a2a 100644
--- a/Source/CTest/cmCTestMemCheckHandler.cxx
+++ b/Source/CTest/cmCTestMemCheckHandler.cxx
@@ -291,6 +291,7 @@ void cmCTestMemCheckHandler::GenerateDartOutput(cmXMLWriter& xml)
return;
}
this->CTest->StartXML(xml, this->AppendXML);
+ this->CTest->GenerateSubprojectsOutput(xml);
xml.StartElement("DynamicAnalysis");
switch (this->MemoryTesterStyle) {
case cmCTestMemCheckHandler::VALGRIND:
diff --git a/Source/CTest/cmCTestRunTest.cxx b/Source/CTest/cmCTestRunTest.cxx
index 0c4269e..9274c01 100644
--- a/Source/CTest/cmCTestRunTest.cxx
+++ b/Source/CTest/cmCTestRunTest.cxx
@@ -237,6 +237,8 @@ bool cmCTestRunTest::EndTest(size_t completed, size_t total, bool started)
} else if (res == cmsysProcess_State_Exception) {
outputTestErrorsToConsole = this->CTest->OutputTestOutputOnTestFailure;
cmCTestLog(this->CTest, HANDLER_OUTPUT, "***Exception: ");
+ this->TestResult.ExceptionStatus =
+ this->TestProcess->GetExitExceptionString();
switch (this->TestProcess->GetExitException()) {
case cmsysProcess_Exception_Fault:
cmCTestLog(this->CTest, HANDLER_OUTPUT, "SegFault");
@@ -255,7 +257,8 @@ bool cmCTestRunTest::EndTest(size_t completed, size_t total, bool started)
this->TestResult.Status = cmCTestTestHandler::NUMERICAL;
break;
default:
- cmCTestLog(this->CTest, HANDLER_OUTPUT, "Other");
+ cmCTestLog(this->CTest, HANDLER_OUTPUT,
+ this->TestResult.ExceptionStatus);
this->TestResult.Status = cmCTestTestHandler::OTHER_FAULT;
}
} else if ("Disabled" == this->TestResult.CompletionStatus) {
diff --git a/Source/CTest/cmCTestScriptHandler.cxx b/Source/CTest/cmCTestScriptHandler.cxx
index 1d29dfa..c566c5c 100644
--- a/Source/CTest/cmCTestScriptHandler.cxx
+++ b/Source/CTest/cmCTestScriptHandler.cxx
@@ -394,7 +394,7 @@ int cmCTestScriptHandler::ReadInScript(const std::string& total_script_arg)
return 0;
}
-// extract variabels from the script to set ivars
+// extract variables from the script to set ivars
int cmCTestScriptHandler::ExtractVariables()
{
// Temporary variables
diff --git a/Source/CTest/cmCTestTestCommand.cxx b/Source/CTest/cmCTestTestCommand.cxx
index 075b140..3346d86 100644
--- a/Source/CTest/cmCTestTestCommand.cxx
+++ b/Source/CTest/cmCTestTestCommand.cxx
@@ -124,6 +124,12 @@ cmCTestGenericHandler* cmCTestTestCommand::InitializeHandler()
}
handler->SetTestLoad(testLoad);
+ if (const char* labelsForSubprojects =
+ this->Makefile->GetDefinition("CTEST_LABELS_FOR_SUBPROJECTS")) {
+ this->CTest->SetCTestConfiguration("LabelsForSubprojects",
+ labelsForSubprojects, this->Quiet);
+ }
+
handler->SetQuiet(this->Quiet);
return handler;
}
diff --git a/Source/CTest/cmCTestTestHandler.cxx b/Source/CTest/cmCTestTestHandler.cxx
index 674be60..8797204 100644
--- a/Source/CTest/cmCTestTestHandler.cxx
+++ b/Source/CTest/cmCTestTestHandler.cxx
@@ -1,12 +1,10 @@
/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmCTestTestHandler.h"
-
-#include "cmsys/Base64.h"
-#include "cmsys/Directory.hxx"
-#include "cmsys/FStream.hxx"
-#include "cmsys/RegularExpression.hxx"
#include <algorithm>
+#include <cmsys/Base64.h>
+#include <cmsys/Directory.hxx>
+#include <cmsys/RegularExpression.hxx>
#include <functional>
#include <iomanip>
#include <iterator>
@@ -33,6 +31,7 @@
#include "cm_auto_ptr.hxx"
#include "cm_utf8.h"
#include "cmake.h"
+#include "cmsys/FStream.hxx"
class cmExecutionStatus;
@@ -238,6 +237,36 @@ bool cmCTestSetTestsPropertiesCommand::InitialPass(
return this->TestHandler->SetTestsProperties(args);
}
+class cmCTestSetDirectoryPropertiesCommand : public cmCommand
+{
+public:
+ /**
+ * This is a virtual constructor for the command.
+ */
+ cmCommand* Clone() CM_OVERRIDE
+ {
+ cmCTestSetDirectoryPropertiesCommand* c =
+ new cmCTestSetDirectoryPropertiesCommand;
+ c->TestHandler = this->TestHandler;
+ return c;
+ }
+
+ /**
+ * This is called when the command is first encountered in
+ * the CMakeLists.txt file.
+ */
+ bool InitialPass(std::vector<std::string> const& /*unused*/,
+ cmExecutionStatus& /*unused*/) CM_OVERRIDE;
+
+ cmCTestTestHandler* TestHandler;
+};
+
+bool cmCTestSetDirectoryPropertiesCommand::InitialPass(
+ std::vector<std::string> const& args, cmExecutionStatus&)
+{
+ return this->TestHandler->SetDirectoryProperties(args);
+}
+
// get the next number in a string with numbers separated by ,
// pos is the start of the search and pos2 is the end of the search
// pos becomes pos2 after a call to GetNextNumber.
@@ -506,9 +535,14 @@ int cmCTestTestHandler::ProcessHandler()
<< static_cast<int>(percent + .5f) << "% tests passed, "
<< failed.size() << " tests failed out of " << total
<< std::endl);
- if (this->CTest->GetLabelSummary()) {
+
+ if (!this->CTest->GetLabelsForSubprojects().empty() &&
+ this->CTest->GetSubprojectSummary()) {
+ this->PrintSubprojectSummary();
+ } else if (this->CTest->GetLabelSummary()) {
this->PrintLabelSummary();
}
+
char realBuf[1024];
sprintf(realBuf, "%6.2f sec", (double)(clock_finish - clock_start));
cmCTestOptionalLog(this->CTest, HANDLER_OUTPUT,
@@ -549,10 +583,10 @@ int cmCTestTestHandler::ProcessHandler()
!cmHasLiteralPrefix(ftit->CompletionStatus, "SKIP_RETURN_CODE=") &&
ftit->CompletionStatus != "Disabled") {
ofs << ftit->TestCount << ":" << ftit->Name << std::endl;
- cmCTestLog(
- this->CTest, HANDLER_OUTPUT, "\t"
- << std::setw(3) << ftit->TestCount << " - " << ftit->Name << " ("
- << this->GetTestStatus(ftit->Status) << ")" << std::endl);
+ cmCTestLog(this->CTest, HANDLER_OUTPUT, "\t"
+ << std::setw(3) << ftit->TestCount << " - "
+ << ftit->Name << " (" << this->GetTestStatus(&*ftit)
+ << ")" << std::endl);
}
}
}
@@ -658,6 +692,84 @@ void cmCTestTestHandler::PrintLabelSummary()
}
}
+void cmCTestTestHandler::PrintSubprojectSummary()
+{
+ std::vector<std::string> subprojects =
+ this->CTest->GetLabelsForSubprojects();
+
+ cmCTestTestHandler::ListOfTests::iterator it = this->TestList.begin();
+ std::map<std::string, double> labelTimes;
+ std::map<std::string, int> labelCounts;
+ std::set<std::string> labels;
+ // initialize maps
+ std::string::size_type maxlen = 0;
+ for (; it != this->TestList.end(); ++it) {
+ cmCTestTestProperties& p = *it;
+ for (std::vector<std::string>::iterator l = p.Labels.begin();
+ l != p.Labels.end(); ++l) {
+ std::vector<std::string>::iterator subproject =
+ std::find(subprojects.begin(), subprojects.end(), *l);
+ if (subproject != subprojects.end()) {
+ if ((*l).size() > maxlen) {
+ maxlen = (*l).size();
+ }
+ labels.insert(*l);
+ labelTimes[*l] = 0;
+ labelCounts[*l] = 0;
+ }
+ }
+ }
+ cmCTestTestHandler::TestResultsVector::iterator ri =
+ this->TestResults.begin();
+ // fill maps
+ for (; ri != this->TestResults.end(); ++ri) {
+ cmCTestTestResult& result = *ri;
+ cmCTestTestProperties& p = *result.Properties;
+ for (std::vector<std::string>::iterator l = p.Labels.begin();
+ l != p.Labels.end(); ++l) {
+ std::vector<std::string>::iterator subproject =
+ std::find(subprojects.begin(), subprojects.end(), *l);
+ if (subproject != subprojects.end()) {
+ labelTimes[*l] += result.ExecutionTime;
+ ++labelCounts[*l];
+ }
+ }
+ }
+ // now print times
+ if (!labels.empty()) {
+ cmCTestOptionalLog(this->CTest, HANDLER_OUTPUT,
+ "\nSubproject Time Summary:", this->Quiet);
+ }
+ for (std::set<std::string>::const_iterator i = labels.begin();
+ i != labels.end(); ++i) {
+ std::string label = *i;
+ label.resize(maxlen + 3, ' ');
+
+ char buf[1024];
+ sprintf(buf, "%6.2f sec", labelTimes[*i]);
+
+ std::ostringstream labelCountStr;
+ labelCountStr << "(" << labelCounts[*i] << " test";
+ if (labelCounts[*i] > 1) {
+ labelCountStr << "s";
+ }
+ labelCountStr << ")";
+
+ cmCTestOptionalLog(this->CTest, HANDLER_OUTPUT, "\n"
+ << label << " = " << buf << " "
+ << labelCountStr.str(),
+ this->Quiet);
+ if (this->LogFile) {
+ *this->LogFile << "\n" << *i << " = " << buf << "\n";
+ }
+ }
+ if (!labels.empty()) {
+ if (this->LogFile) {
+ *this->LogFile << "\n";
+ }
+ cmCTestOptionalLog(this->CTest, HANDLER_OUTPUT, "\n", this->Quiet);
+ }
+}
void cmCTestTestHandler::CheckLabelFilterInclude(cmCTestTestProperties& it)
{
// if not using Labels to filter then return
@@ -1277,6 +1389,7 @@ void cmCTestTestHandler::GenerateDartOutput(cmXMLWriter& xml)
}
this->CTest->StartXML(xml, this->AppendXML);
+ this->CTest->GenerateSubprojectsOutput(xml);
xml.StartElement("Testing");
xml.Element("StartDateTime", this->StartTest);
xml.Element("StartTestTime", this->StartTestTime);
@@ -1299,7 +1412,7 @@ void cmCTestTestHandler::GenerateDartOutput(cmXMLWriter& xml)
xml.StartElement("NamedMeasurement");
xml.Attribute("type", "text/string");
xml.Attribute("name", "Exit Code");
- xml.Element("Value", this->GetTestStatus(result->Status));
+ xml.Element("Value", this->GetTestStatus(result));
xml.EndElement(); // NamedMeasurement
xml.StartElement("NamedMeasurement");
@@ -1660,6 +1773,12 @@ void cmCTestTestHandler::GetListOfTests()
newCom4->TestHandler = this;
cm.GetState()->AddBuiltinCommand("set_tests_properties", newCom4);
+ // Add handler for SET_DIRECTORY_PROPERTIES
+ cmCTestSetDirectoryPropertiesCommand* newCom5 =
+ new cmCTestSetDirectoryPropertiesCommand;
+ newCom5->TestHandler = this;
+ cm.GetState()->AddBuiltinCommand("set_directory_properties", newCom5);
+
const char* testFilename;
if (cmSystemTools::FileExists("CTestTestfile.cmake")) {
// does the CTestTestfile.cmake exist ?
@@ -1693,17 +1812,20 @@ void cmCTestTestHandler::UseExcludeRegExp()
this->UseExcludeRegExpFirst = !this->UseIncludeRegExpFlag;
}
-const char* cmCTestTestHandler::GetTestStatus(int status)
+const char* cmCTestTestHandler::GetTestStatus(const cmCTestTestResult* result)
{
static const char* statuses[] = { "Not Run", "Timeout", "SEGFAULT",
"ILLEGAL", "INTERRUPT", "NUMERICAL",
"OTHER_FAULT", "Failed", "BAD_COMMAND",
"Completed" };
-
+ int status = result->Status;
if (status < cmCTestTestHandler::NOT_RUN ||
status > cmCTestTestHandler::COMPLETED) {
return "No Status";
}
+ if (status == cmCTestTestHandler::OTHER_FAULT) {
+ return result->ExceptionStatus.c_str();
+ }
return statuses[status];
}
@@ -2171,7 +2293,16 @@ bool cmCTestTestHandler::SetTestsProperties(
cmSystemTools::ExpandListArgument(val, rtit->Environment);
}
if (key == "LABELS") {
- cmSystemTools::ExpandListArgument(val, rtit->Labels);
+ std::vector<std::string> Labels;
+ cmSystemTools::ExpandListArgument(val, Labels);
+ rtit->Labels.insert(rtit->Labels.end(), Labels.begin(),
+ Labels.end());
+ // sort the array
+ std::sort(rtit->Labels.begin(), rtit->Labels.end());
+ // remove duplicates
+ std::vector<std::string>::iterator new_end =
+ std::unique(rtit->Labels.begin(), rtit->Labels.end());
+ rtit->Labels.erase(new_end, rtit->Labels.end());
}
if (key == "MEASUREMENT") {
size_t pos = val.find_first_of('=');
@@ -2224,6 +2355,54 @@ bool cmCTestTestHandler::SetTestsProperties(
return true;
}
+bool cmCTestTestHandler::SetDirectoryProperties(
+ const std::vector<std::string>& args)
+{
+ std::vector<std::string>::const_iterator it;
+ std::vector<std::string> tests;
+ bool found = false;
+ for (it = args.begin(); it != args.end(); ++it) {
+ if (*it == "PROPERTIES") {
+ found = true;
+ break;
+ }
+ tests.push_back(*it);
+ }
+
+ if (!found) {
+ return false;
+ }
+ ++it; // skip PROPERTIES
+ for (; it != args.end(); ++it) {
+ std::string key = *it;
+ ++it;
+ if (it == args.end()) {
+ break;
+ }
+ std::string val = *it;
+ cmCTestTestHandler::ListOfTests::iterator rtit;
+ for (rtit = this->TestList.begin(); rtit != this->TestList.end(); ++rtit) {
+ std::string cwd = cmSystemTools::GetCurrentWorkingDirectory();
+ if (cwd == rtit->Directory) {
+ if (key == "LABELS") {
+ std::vector<std::string> DirectoryLabels;
+ cmSystemTools::ExpandListArgument(val, DirectoryLabels);
+ rtit->Labels.insert(rtit->Labels.end(), DirectoryLabels.begin(),
+ DirectoryLabels.end());
+
+ // sort the array
+ std::sort(rtit->Labels.begin(), rtit->Labels.end());
+ // remove duplicates
+ std::vector<std::string>::iterator new_end =
+ std::unique(rtit->Labels.begin(), rtit->Labels.end());
+ rtit->Labels.erase(new_end, rtit->Labels.end());
+ }
+ }
+ }
+ }
+ return true;
+}
+
bool cmCTestTestHandler::AddTest(const std::vector<std::string>& args)
{
const std::string& testname = args[0];
diff --git a/Source/CTest/cmCTestTestHandler.h b/Source/CTest/cmCTestTestHandler.h
index 0edcb14..6dbbcf8 100644
--- a/Source/CTest/cmCTestTestHandler.h
+++ b/Source/CTest/cmCTestTestHandler.h
@@ -90,6 +90,11 @@ public:
*/
bool SetTestsProperties(const std::vector<std::string>& args);
+ /**
+ * Set directory properties
+ */
+ bool SetDirectoryProperties(const std::vector<std::string>& args);
+
void Initialize() CM_OVERRIDE;
// NOTE: This struct is Saved/Restored
@@ -144,6 +149,7 @@ public:
double ExecutionTime;
int ReturnValue;
int Status;
+ std::string ExceptionStatus;
bool CompressOutput;
std::string CompletionStatus;
std::string Output;
@@ -227,6 +233,8 @@ private:
virtual void GenerateDartOutput(cmXMLWriter& xml);
void PrintLabelSummary();
+ void PrintSubprojectSummary();
+
/**
* Run the tests for a directory and any subdirectories
*/
@@ -262,7 +270,7 @@ private:
*/
std::string FindTheExecutable(const char* exe);
- const char* GetTestStatus(int status);
+ const char* GetTestStatus(const cmCTestTestResult*);
void ExpandTestsToRunInformation(size_t numPossibleTests);
void ExpandTestsToRunInformationForRerunFailed();
diff --git a/Source/CTest/cmProcess.cxx b/Source/CTest/cmProcess.cxx
index f4ec6da..9680a69 100644
--- a/Source/CTest/cmProcess.cxx
+++ b/Source/CTest/cmProcess.cxx
@@ -240,3 +240,8 @@ int cmProcess::GetExitException()
{
return cmsysProcess_GetExitException(this->Process);
}
+
+std::string cmProcess::GetExitExceptionString()
+{
+ return cmsysProcess_GetExceptionString(this->Process);
+}
diff --git a/Source/CTest/cmProcess.h b/Source/CTest/cmProcess.h
index 86e905a..dfb02fe 100644
--- a/Source/CTest/cmProcess.h
+++ b/Source/CTest/cmProcess.h
@@ -38,6 +38,7 @@ public:
int GetExitValue() { return this->ExitValue; }
double GetTotalTime() { return this->TotalTime; }
int GetExitException();
+ std::string GetExitExceptionString();
/**
* Read one line of output but block for no more than timeout.
* Returns: