diff options
Diffstat (limited to 'Source/CTest/cmCTestTestHandler.cxx')
| -rw-r--r-- | Source/CTest/cmCTestTestHandler.cxx | 239 |
1 files changed, 87 insertions, 152 deletions
diff --git a/Source/CTest/cmCTestTestHandler.cxx b/Source/CTest/cmCTestTestHandler.cxx index 730ec0f..6e97a83 100644 --- a/Source/CTest/cmCTestTestHandler.cxx +++ b/Source/CTest/cmCTestTestHandler.cxx @@ -32,17 +32,18 @@ #include "cmCTest.h" #include "cmCTestMultiProcessHandler.h" #include "cmCTestResourceGroupsLexerHelper.h" +#include "cmCTestTestMeasurementXMLParser.h" #include "cmDuration.h" #include "cmExecutionStatus.h" #include "cmGeneratedFileStream.h" #include "cmGlobalGenerator.h" #include "cmMakefile.h" -#include "cmProperty.h" #include "cmState.h" #include "cmStateSnapshot.h" #include "cmStringAlgorithms.h" #include "cmSystemTools.h" #include "cmTimestamp.h" +#include "cmValue.h" #include "cmWorkingDirectory.h" #include "cmXMLWriter.h" #include "cmake.h" @@ -303,15 +304,24 @@ cmCTestTestHandler::cmCTestTestHandler() // Support for JUnit XML output. this->JUnitXMLFileName = ""; - // regex to detect <DartMeasurement>...</DartMeasurement> - this->DartStuff.compile("(<DartMeasurement.*/DartMeasurement[a-zA-Z]*>)"); - // regex to detect each individual <DartMeasurement>...</DartMeasurement> - this->DartStuff1.compile( - "(<DartMeasurement[^<]*</DartMeasurement[a-zA-Z]*>)"); + // Regular expressions to scan test output for custom measurements. - // regex to detect <CTestDetails>...</CTestDetails> + // Capture the whole section of test output from the first opening + // <(CTest|Dart)Measurement*> tag to the last </(CTest|Dart)Measurement*> + // closing tag. + this->AllTestMeasurementsRegex.compile( + "(<(CTest|Dart)Measurement.*/(CTest|Dart)Measurement[a-zA-Z]*>)"); + + // Capture a single <(CTest|Dart)Measurement*> XML element. + this->SingleTestMeasurementRegex.compile( + "(<(CTest|Dart)Measurement[^<]*</(CTest|Dart)Measurement[a-zA-Z]*>)"); + + // Capture content from <CTestDetails>...</CTestDetails> this->CustomCompletionStatusRegex.compile( "<CTestDetails>(.*)</CTestDetails>"); + + // Capture content from <CTestLabel>...</CTestLabel> + this->CustomLabelRegex.compile("<CTestLabel>(.*)</CTestLabel>"); } void cmCTestTestHandler::Initialize() @@ -511,7 +521,7 @@ bool cmCTestTestHandler::ProcessOptions() if (cmIsOn(this->GetOption("ScheduleRandom"))) { this->CTest->SetScheduleType("Random"); } - if (const char* repeat = this->GetOption("Repeat")) { + if (cmValue repeat = this->GetOption("Repeat")) { cmsys::RegularExpression repeatRegex( "^(UNTIL_FAIL|UNTIL_PASS|AFTER_TIMEOUT):([0-9]+)$"); if (repeatRegex.find(repeat)) { @@ -536,7 +546,7 @@ bool cmCTestTestHandler::ProcessOptions() } } if (this->GetOption("ParallelLevel")) { - this->CTest->SetParallelLevel(atoi(this->GetOption("ParallelLevel"))); + this->CTest->SetParallelLevel(std::stoi(this->GetOption("ParallelLevel"))); } if (this->GetOption("StopOnFailure")) { @@ -547,7 +557,7 @@ bool cmCTestTestHandler::ProcessOptions() this->IncludeLabelRegularExpressions); BuildLabelRE(this->GetMultiOption("ExcludeLabelRegularExpression"), this->ExcludeLabelRegularExpressions); - const char* val = this->GetOption("IncludeRegularExpression"); + cmValue val = this->GetOption("IncludeRegularExpression"); if (val) { this->UseIncludeRegExp(); this->SetIncludeRegExp(val); @@ -559,19 +569,19 @@ bool cmCTestTestHandler::ProcessOptions() } val = this->GetOption("ExcludeFixtureRegularExpression"); if (val) { - this->ExcludeFixtureRegExp = val; + this->ExcludeFixtureRegExp = *val; } val = this->GetOption("ExcludeFixtureSetupRegularExpression"); if (val) { - this->ExcludeFixtureSetupRegExp = val; + this->ExcludeFixtureSetupRegExp = *val; } val = this->GetOption("ExcludeFixtureCleanupRegularExpression"); if (val) { - this->ExcludeFixtureCleanupRegExp = val; + this->ExcludeFixtureCleanupRegExp = *val; } val = this->GetOption("ResourceSpecFile"); if (val) { - this->ResourceSpecFile = val; + this->ResourceSpecFile = *val; } this->SetRerunFailed(cmIsOn(this->GetOption("RerunFailed"))); @@ -692,7 +702,22 @@ bool cmCTestTestHandler::GenerateXML() return false; } cmXMLWriter xml(xmlfile); - this->GenerateDartOutput(xml); + this->GenerateCTestXML(xml); + } + + if (this->MemCheck) { + cmGeneratedFileStream xmlfile; + if (!this->StartResultingXML(cmCTest::PartTest, "DynamicAnalysis-Test", + xmlfile)) { + cmCTestLog(this->CTest, ERROR_MESSAGE, + "Cannot create testing XML file" << std::endl); + this->LogFile = nullptr; + return false; + } + cmXMLWriter xml(xmlfile); + // Explicitly call this class' `GenerateCTestXML` method to make `Test.xml` + // as well. + this->cmCTestTestHandler::GenerateCTestXML(xml); } return true; @@ -1400,7 +1425,7 @@ void cmCTestTestHandler::GenerateTestCommand( { } -void cmCTestTestHandler::GenerateDartOutput(cmXMLWriter& xml) +void cmCTestTestHandler::GenerateCTestXML(cmXMLWriter& xml) { if (!this->CTest->GetProduceXML()) { return; @@ -1436,7 +1461,7 @@ void cmCTestTestHandler::GenerateDartOutput(cmXMLWriter& xml) xml.Element("Value", result.ReturnValue); xml.EndElement(); // NamedMeasurement } - this->GenerateRegressionImages(xml, result.DartString); + this->RecordCustomTestMeasurements(xml, result.TestMeasurementsOutput); xml.StartElement("NamedMeasurement"); xml.Attribute("type", "numeric/double"); xml.Attribute("name", "Execution Time"); @@ -1804,7 +1829,7 @@ bool cmCTestTestHandler::GetListOfTests() // SEND_ERROR or FATAL_ERROR in CTestTestfile or TEST_INCLUDE_FILES return false; } - cmProp specFile = mf.GetDefinition("CTEST_RESOURCE_SPEC_FILE"); + cmValue specFile = mf.GetDefinition("CTEST_RESOURCE_SPEC_FILE"); if (this->ResourceSpecFile.empty() && specFile) { this->ResourceSpecFile = *specFile; } @@ -1976,124 +2001,48 @@ void cmCTestTestHandler::ExpandTestsToRunInformationForRerunFailed() } } -// Just for convenience -#define SPACE_REGEX "[ \t\r\n]" -void cmCTestTestHandler::GenerateRegressionImages(cmXMLWriter& xml, - const std::string& dart) -{ - cmsys::RegularExpression twoattributes( - "<DartMeasurement" SPACE_REGEX - "*(name|type|encoding|compression)=\"([^\"]*)\"" SPACE_REGEX - "*(name|type|encoding|compression)=\"([^\"]*)\"" SPACE_REGEX - "*>([^<]*)</DartMeasurement>"); - cmsys::RegularExpression threeattributes( - "<DartMeasurement" SPACE_REGEX - "*(name|type|encoding|compression)=\"([^\"]*)\"" SPACE_REGEX - "*(name|type|encoding|compression)=\"([^\"]*)\"" SPACE_REGEX - "*(name|type|encoding|compression)=\"([^\"]*)\"" SPACE_REGEX - "*>([^<]*)</DartMeasurement>"); - cmsys::RegularExpression fourattributes( - "<DartMeasurement" SPACE_REGEX - "*(name|type|encoding|compression)=\"([^\"]*)\"" SPACE_REGEX - "*(name|type|encoding|compression)=\"([^\"]*)\"" SPACE_REGEX - "*(name|type|encoding|compression)=\"([^\"]*)\"" SPACE_REGEX - "*(name|type|encoding|compression)=\"([^\"]*)\"" SPACE_REGEX - "*>([^<]*)</DartMeasurement>"); - cmsys::RegularExpression cdatastart( - "<DartMeasurement" SPACE_REGEX - "*(name|type|encoding|compression)=\"([^\"]*)\"" SPACE_REGEX - "*(name|type|encoding|compression)=\"([^\"]*)\"" SPACE_REGEX - "*>" SPACE_REGEX "*<!\\[CDATA\\["); - cmsys::RegularExpression cdataend("]]>" SPACE_REGEX "*</DartMeasurement>"); - cmsys::RegularExpression measurementfile( - "<DartMeasurementFile" SPACE_REGEX - "*(name|type|encoding|compression)=\"([^\"]*)\"" SPACE_REGEX - "*(name|type|encoding|compression)=\"([^\"]*)\"" SPACE_REGEX - "*>([^<]*)</DartMeasurementFile>"); - - bool done = false; - std::string cxml = dart; - while (!done) { - if (twoattributes.find(cxml)) { - xml.StartElement("NamedMeasurement"); - xml.Attribute(twoattributes.match(1).c_str(), twoattributes.match(2)); - xml.Attribute(twoattributes.match(3).c_str(), twoattributes.match(4)); - xml.Element("Value", twoattributes.match(5)); - xml.EndElement(); - cxml.erase(twoattributes.start(), - twoattributes.end() - twoattributes.start()); - } else if (threeattributes.find(cxml)) { - xml.StartElement("NamedMeasurement"); - xml.Attribute(threeattributes.match(1).c_str(), - threeattributes.match(2)); - xml.Attribute(threeattributes.match(3).c_str(), - threeattributes.match(4)); - xml.Attribute(threeattributes.match(5).c_str(), - threeattributes.match(6)); - xml.Element("Value", twoattributes.match(7)); - xml.EndElement(); - cxml.erase(threeattributes.start(), - threeattributes.end() - threeattributes.start()); - } else if (fourattributes.find(cxml)) { +void cmCTestTestHandler::RecordCustomTestMeasurements(cmXMLWriter& xml, + std::string content) +{ + while (this->SingleTestMeasurementRegex.find(content)) { + // Extract regex match from content and parse it as an XML element. + auto measurement_str = this->SingleTestMeasurementRegex.match(1); + auto parser = cmCTestTestMeasurementXMLParser(); + parser.Parse(measurement_str.c_str()); + + if (parser.ElementName == "CTestMeasurement" || + parser.ElementName == "DartMeasurement") { xml.StartElement("NamedMeasurement"); - xml.Attribute(fourattributes.match(1).c_str(), fourattributes.match(2)); - xml.Attribute(fourattributes.match(3).c_str(), fourattributes.match(4)); - xml.Attribute(fourattributes.match(5).c_str(), fourattributes.match(6)); - xml.Attribute(fourattributes.match(7).c_str(), fourattributes.match(8)); - xml.Element("Value", twoattributes.match(9)); + xml.Attribute("type", parser.MeasurementType); + xml.Attribute("name", parser.MeasurementName); + xml.Element("Value", parser.CharacterData); xml.EndElement(); - cxml.erase(fourattributes.start(), - fourattributes.end() - fourattributes.start()); - } else if (cdatastart.find(cxml) && cdataend.find(cxml)) { - xml.StartElement("NamedMeasurement"); - xml.Attribute(cdatastart.match(1).c_str(), cdatastart.match(2)); - xml.Attribute(cdatastart.match(3).c_str(), cdatastart.match(4)); - xml.StartElement("Value"); - xml.CData( - cxml.substr(cdatastart.end(), cdataend.start() - cdatastart.end())); - xml.EndElement(); // Value - xml.EndElement(); // NamedMeasurement - cxml.erase(cdatastart.start(), cdataend.end() - cdatastart.start()); - } else if (measurementfile.find(cxml)) { - const std::string& filename = - cmCTest::CleanString(measurementfile.match(5)); - if (cmSystemTools::FileExists(filename)) { + } else if (parser.ElementName == "CTestMeasurementFile" || + parser.ElementName == "DartMeasurementFile") { + const std::string& filename = cmCTest::CleanString(parser.CharacterData); + if (!cmSystemTools::FileExists(filename)) { + xml.StartElement("NamedMeasurement"); + xml.Attribute("name", parser.MeasurementName); + xml.Attribute("text", "text/string"); + xml.Element("Value", "File " + filename + " not found"); + xml.EndElement(); + cmCTestOptionalLog( + this->CTest, HANDLER_OUTPUT, + "File \"" << filename << "\" not found." << std::endl, this->Quiet); + } else { long len = cmSystemTools::FileLength(filename); - std::string k1 = measurementfile.match(1); - std::string v1 = measurementfile.match(2); - std::string k2 = measurementfile.match(3); - std::string v2 = measurementfile.match(4); if (len == 0) { - if (cmSystemTools::LowerCase(k1) == "type") { - v1 = "text/string"; - } - if (cmSystemTools::LowerCase(k2) == "type") { - v2 = "text/string"; - } - xml.StartElement("NamedMeasurement"); - xml.Attribute(k1.c_str(), v1); - xml.Attribute(k2.c_str(), v2); + xml.Attribute("name", parser.MeasurementName); + xml.Attribute("type", "text/string"); xml.Attribute("encoding", "none"); xml.Element("Value", "Image " + filename + " is empty"); xml.EndElement(); } else { - std::string type; - std::string name; - if (cmSystemTools::LowerCase(k1) == "type") { - type = v1; - } else if (cmSystemTools::LowerCase(k2) == "type") { - type = v2; - } - if (cmSystemTools::LowerCase(k1) == "name") { - name = v1; - } else if (cmSystemTools::LowerCase(k2) == "name") { - name = v2; - } - if (type == "file") { + if (parser.MeasurementType == "file") { // Treat this measurement like an "ATTACHED_FILE" when the type // is explicitly "file" (not an image). - this->AttachFile(xml, filename, name); + this->AttachFile(xml, filename, parser.MeasurementName); } else { cmsys::ifstream ifs(filename.c_str(), std::ios::in @@ -2110,10 +2059,8 @@ void cmCTestTestHandler::GenerateRegressionImages(cmXMLWriter& xml, encoded_buffer.get(), 1); xml.StartElement("NamedMeasurement"); - xml.Attribute(measurementfile.match(1).c_str(), - measurementfile.match(2)); - xml.Attribute(measurementfile.match(3).c_str(), - measurementfile.match(4)); + xml.Attribute("name", parser.MeasurementName); + xml.Attribute("type", parser.MeasurementType); xml.Attribute("encoding", "base64"); std::ostringstream ostr; for (size_t cc = 0; cc < rlen; cc++) { @@ -2126,48 +2073,34 @@ void cmCTestTestHandler::GenerateRegressionImages(cmXMLWriter& xml, xml.EndElement(); // NamedMeasurement } } - } else { - int idx = 4; - if (measurementfile.match(1) == "name") { - idx = 2; - } - xml.StartElement("NamedMeasurement"); - xml.Attribute("name", measurementfile.match(idx)); - xml.Attribute("text", "text/string"); - xml.Element("Value", "File " + filename + " not found"); - xml.EndElement(); - cmCTestOptionalLog( - this->CTest, HANDLER_OUTPUT, - "File \"" << filename << "\" not found." << std::endl, this->Quiet); } - cxml.erase(measurementfile.start(), - measurementfile.end() - measurementfile.start()); - } else { - done = true; } + + // Remove this element from content. + cmSystemTools::ReplaceString(content, measurement_str.c_str(), ""); } } -void cmCTestTestHandler::SetIncludeRegExp(const char* arg) +void cmCTestTestHandler::SetIncludeRegExp(const std::string& arg) { this->IncludeRegExp = arg; } -void cmCTestTestHandler::SetExcludeRegExp(const char* arg) +void cmCTestTestHandler::SetExcludeRegExp(const std::string& arg) { this->ExcludeRegExp = arg; } -void cmCTestTestHandler::SetTestsToRunInformation(const char* in) +void cmCTestTestHandler::SetTestsToRunInformation(cmValue in) { if (!in) { return; } - this->TestsToRunString = in; + this->TestsToRunString = *in; // if the argument is a file, then read it and use the contents as the // string if (cmSystemTools::FileExists(in)) { - cmsys::ifstream fin(in); + cmsys::ifstream fin(in->c_str()); unsigned long filelen = cmSystemTools::FileLength(in); auto buff = cm::make_unique<char[]>(filelen + 1); fin.getline(buff.get(), filelen); @@ -2247,7 +2180,7 @@ bool cmCTestTestHandler::SetTestsProperties( // Ensure we have complete triples otherwise the data is corrupt. if (triples.size() % 3 == 0) { - cmState state; + cmState state(cmState::Unknown); rt.Backtrace = cmListFileBacktrace(state.CreateBaseSnapshot()); // the first entry represents the top of the trace so we need to @@ -2327,6 +2260,8 @@ bool cmCTestTestHandler::SetTestsProperties( cmExpandList(val, rt.Depends); } else if (key == "ENVIRONMENT"_s) { cmExpandList(val, rt.Environment); + } else if (key == "ENVIRONMENT_MODIFICATION"_s) { + cmExpandList(val, rt.EnvironmentModification); } else if (key == "LABELS"_s) { std::vector<std::string> Labels = cmExpandedList(val); rt.Labels.insert(rt.Labels.end(), Labels.begin(), Labels.end()); |
