Commit b04500a7 authored by Daniel Pfeifer's avatar Daniel Pfeifer Committed by Brad King
Browse files

cmCTest{Test,MemCheck}Handler: Port to cmXMLWriter

parent 8fbc509a
......@@ -21,7 +21,7 @@
#include <cmsys/Glob.hxx>
#include <cmsys/FStream.hxx>
#include "cmMakefile.h"
#include "cmXMLSafe.h"
#include "cmXMLWriter.h"
#include <stdlib.h>
#include <math.h>
......@@ -352,55 +352,52 @@ void cmCTestMemCheckHandler::PopulateCustomVectors(cmMakefile *mf)
}
//----------------------------------------------------------------------
void cmCTestMemCheckHandler::GenerateDartOutput(std::ostream& os)
void cmCTestMemCheckHandler::GenerateDartOutput(cmXMLWriter& xml)
{
if ( !this->CTest->GetProduceXML() )
{
return;
}
this->CTest->StartXML(os, this->AppendXML);
os << "<DynamicAnalysis Checker=\"";
this->CTest->StartXML(xml, this->AppendXML);
xml.StartElement("DynamicAnalysis");
switch ( this->MemoryTesterStyle )
{
case cmCTestMemCheckHandler::VALGRIND:
os << "Valgrind";
xml.Attribute("Checker", "Valgrind");
break;
case cmCTestMemCheckHandler::PURIFY:
os << "Purify";
xml.Attribute("Checker", "Purify");
break;
case cmCTestMemCheckHandler::BOUNDS_CHECKER:
os << "BoundsChecker";
xml.Attribute("Checker", "BoundsChecker");
break;
case cmCTestMemCheckHandler::ADDRESS_SANITIZER:
os << "AddressSanitizer";
xml.Attribute("Checker", "AddressSanitizer");
break;
case cmCTestMemCheckHandler::THREAD_SANITIZER:
os << "ThreadSanitizer";
xml.Attribute("Checker", "ThreadSanitizer");
break;
case cmCTestMemCheckHandler::MEMORY_SANITIZER:
os << "MemorySanitizer";
xml.Attribute("Checker", "MemorySanitizer");
break;
case cmCTestMemCheckHandler::UB_SANITIZER:
os << "UndefinedBehaviorSanitizer";
xml.Attribute("Checker", "UndefinedBehaviorSanitizer");
break;
default:
os << "Unknown";
xml.Attribute("Checker", "Unknown");
}
os << "\">" << std::endl;
os << "\t<StartDateTime>" << this->StartTest << "</StartDateTime>\n"
<< "\t<StartTestTime>" << this->StartTestTime << "</StartTestTime>\n"
<< "\t<TestList>\n";
xml.Element("StartDateTime", this->StartTest);
xml.Element("StartTestTime", this->StartTestTime);
xml.StartElement("TestList");
cmCTestMemCheckHandler::TestResultsVector::size_type cc;
for ( cc = 0; cc < this->TestResults.size(); cc ++ )
{
cmCTestTestResult *result = &this->TestResults[cc];
std::string testPath = result->Path + "/" + result->Name;
os << "\t\t<Test>" << cmXMLSafe(
this->CTest->GetShortPathToFile(testPath.c_str()))
<< "</Test>" << std::endl;
xml.Element("Test", this->CTest->GetShortPathToFile(testPath.c_str()));
}
os << "\t</TestList>\n";
xml.EndElement(); // TestList
cmCTestOptionalLog(this->CTest, HANDLER_OUTPUT,
"-- Processing memory checking output: ", this->Quiet);
size_t total = this->TestResults.size();
......@@ -419,37 +416,33 @@ void cmCTestMemCheckHandler::GenerateDartOutput(std::ostream& os)
}
this->CleanTestOutput(memcheckstr,
static_cast<size_t>(this->CustomMaximumFailedTestOutputSize));
this->WriteTestResultHeader(os, result);
os << "\t\t<Results>" << std::endl;
this->WriteTestResultHeader(xml, result);
xml.StartElement("Results");
for(std::vector<int>::size_type kk = 0;
kk < memcheckresults.size(); ++kk)
{
if ( memcheckresults[kk] )
{
os << "\t\t\t<Defect type=\"" << this->ResultStringsLong[kk]
<< "\">"
<< memcheckresults[kk]
<< "</Defect>" << std::endl;
xml.StartElement("Defect");
xml.Attribute("type", this->ResultStringsLong[kk]);
xml.Content(memcheckresults[kk]);
xml.EndElement(); // Defect
}
this->GlobalResults[kk] += memcheckresults[kk];
}
xml.EndElement(); // Results
std::string logTag;
xml.StartElement("Log");
if(this->CTest->ShouldCompressMemCheckOutput())
{
this->CTest->CompressString(memcheckstr);
logTag = "\t<Log compression=\"gzip\" encoding=\"base64\">\n";
}
else
{
logTag = "\t<Log>\n";
xml.Attribute("compression", "gzip");
xml.Attribute("encoding", "base64");
}
xml.Content(memcheckstr);
xml.EndElement(); // Log
os
<< "\t\t</Results>\n"
<< logTag << cmXMLSafe(memcheckstr) << std::endl
<< "\t</Log>\n";
this->WriteTestResultFooter(os, result);
this->WriteTestResultFooter(xml, result);
if ( current < cc )
{
cmCTestOptionalLog(this->CTest, HANDLER_OUTPUT, "#" << std::flush,
......@@ -460,7 +453,7 @@ void cmCTestMemCheckHandler::GenerateDartOutput(std::ostream& os)
cmCTestOptionalLog(this->CTest, HANDLER_OUTPUT, std::endl, this->Quiet);
cmCTestOptionalLog(this->CTest, HANDLER_OUTPUT, "Memory checking results:"
<< std::endl, this->Quiet);
os << "\t<DefectList>" << std::endl;
xml.StartElement("DefectList");
for ( cc = 0; cc < this->GlobalResults.size(); cc ++ )
{
if ( this->GlobalResults[cc] )
......@@ -473,21 +466,20 @@ void cmCTestMemCheckHandler::GenerateDartOutput(std::ostream& os)
cmCTestOptionalLog(this->CTest, HANDLER_OUTPUT,
this->ResultStringsLong[cc] << " - "
<< this->GlobalResults[cc] << std::endl, this->Quiet);
os << "\t\t<Defect Type=\"" << this->ResultStringsLong[cc]
<< "\"/>" << std::endl;
xml.StartElement("Defect");
xml.Attribute("Type", this->ResultStringsLong[cc]);
xml.EndElement();
}
}
os << "\t</DefectList>" << std::endl;
xml.EndElement(); // DefectList
os << "\t<EndDateTime>" << this->EndTest << "</EndDateTime>" << std::endl;
os << "\t<EndTestTime>" << this->EndTestTime
<< "</EndTestTime>" << std::endl;
os << "<ElapsedMinutes>"
<< static_cast<int>(this->ElapsedTestingTime/6)/10.0
<< "</ElapsedMinutes>\n";
xml.Element("EndDateTime", this->EndTest);
xml.Element("EndTestTime", this->EndTestTime);
xml.Element("ElapsedMinutes",
static_cast<int>(this->ElapsedTestingTime/6)/10.0);
os << "</DynamicAnalysis>" << std::endl;
this->CTest->EndXML(os);
xml.EndElement(); // DynamicAnalysis
this->CTest->EndXML(xml);
}
//----------------------------------------------------------------------
......
......@@ -21,6 +21,7 @@
#include <string>
class cmMakefile;
class cmXMLWriter;
/** \class cmCTestMemCheckHandler
* \brief A class that handles ctest -S invocations
......@@ -119,7 +120,7 @@ private:
/**
* Generate the Dart compatible output
*/
void GenerateDartOutput(std::ostream& os);
void GenerateDartOutput(cmXMLWriter& xml);
std::vector<std::string> CustomPreMemCheck;
std::vector<std::string> CustomPostMemCheck;
......
......@@ -27,7 +27,7 @@
#include "cmLocalGenerator.h"
#include "cmCommand.h"
#include "cmSystemTools.h"
#include "cmXMLSafe.h"
#include "cmXMLWriter.h"
#include "cm_utf8.h"
#include <stdlib.h>
......@@ -633,7 +633,8 @@ int cmCTestTestHandler::ProcessHandler()
this->LogFile = 0;
return 1;
}
this->GenerateDartOutput(xmlfile);
cmXMLWriter xml(xmlfile);
this->GenerateDartOutput(xml);
}
if ( ! this->PostProcessHandler() )
......@@ -1142,54 +1143,53 @@ void cmCTestTestHandler::GenerateTestCommand(std::vector<std::string>&, int)
}
//----------------------------------------------------------------------
void cmCTestTestHandler::GenerateDartOutput(std::ostream& os)
void cmCTestTestHandler::GenerateDartOutput(cmXMLWriter& xml)
{
if ( !this->CTest->GetProduceXML() )
{
return;
}
this->CTest->StartXML(os, this->AppendXML);
os << "<Testing>\n"
<< "\t<StartDateTime>" << this->StartTest << "</StartDateTime>\n"
<< "\t<StartTestTime>" << this->StartTestTime << "</StartTestTime>\n"
<< "\t<TestList>\n";
this->CTest->StartXML(xml, this->AppendXML);
xml.StartElement("Testing");
xml.Element("StartDateTime", this->StartTest);
xml.Element("StartTestTime", this->StartTestTime);
xml.StartElement("TestList");
cmCTestTestHandler::TestResultsVector::size_type cc;
for ( cc = 0; cc < this->TestResults.size(); cc ++ )
{
cmCTestTestResult *result = &this->TestResults[cc];
std::string testPath = result->Path + "/" + result->Name;
os << "\t\t<Test>" << cmXMLSafe(
this->CTest->GetShortPathToFile(testPath.c_str()))
<< "</Test>" << std::endl;
xml.Element("Test", this->CTest->GetShortPathToFile(testPath.c_str()));
}
os << "\t</TestList>\n";
xml.EndElement(); // TestList
for ( cc = 0; cc < this->TestResults.size(); cc ++ )
{
cmCTestTestResult *result = &this->TestResults[cc];
this->WriteTestResultHeader(os, result);
os << "\t\t<Results>" << std::endl;
this->WriteTestResultHeader(xml, result);
xml.StartElement("Results");
if ( result->Status != cmCTestTestHandler::NOT_RUN )
{
if ( result->Status != cmCTestTestHandler::COMPLETED ||
result->ReturnValue )
{
os << "\t\t\t<NamedMeasurement type=\"text/string\" "
"name=\"Exit Code\"><Value>"
<< cmXMLSafe(this->GetTestStatus(result->Status))
<< "</Value>"
"</NamedMeasurement>\n"
<< "\t\t\t<NamedMeasurement type=\"text/string\" "
"name=\"Exit Value\"><Value>"
<< result->ReturnValue
<< "</Value></NamedMeasurement>"
<< std::endl;
xml.StartElement("NamedMeasurement");
xml.Attribute("type", "text/string");
xml.Attribute("name", "Exit Code");
xml.Element("Value", this->GetTestStatus(result->Status));
xml.EndElement(); // NamedMeasurement
xml.StartElement("NamedMeasurement");
xml.Attribute("type", "text/string");
xml.Attribute("name", "Exit Value");
xml.Element("Value", result->ReturnValue);
xml.EndElement(); // NamedMeasurement
}
this->GenerateRegressionImages(os, result->DartString);
os << "\t\t\t<NamedMeasurement type=\"numeric/double\" "
<< "name=\"Execution Time\"><Value>"
<< result->ExecutionTime
<< "</Value></NamedMeasurement>\n";
this->GenerateRegressionImages(xml, result->DartString);
xml.StartElement("NamedMeasurement");
xml.Attribute("type", "numeric/double");
xml.Attribute("name", "Execution Time");
xml.Element("Value", result->ExecutionTime);
xml.EndElement(); // NamedMeasurement
if(!result->Reason.empty())
{
const char* reasonType = "Pass Reason";
......@@ -1198,109 +1198,103 @@ void cmCTestTestHandler::GenerateDartOutput(std::ostream& os)
{
reasonType = "Fail Reason";
}
os << "\t\t\t<NamedMeasurement type=\"text/string\" "
<< "name=\"" << reasonType << "\"><Value>"
<< cmXMLSafe(result->Reason)
<< "</Value></NamedMeasurement>\n";
xml.StartElement("NamedMeasurement");
xml.Attribute("type", "text/string");
xml.Attribute("name", reasonType);
xml.Element("Value", result->Reason);
xml.EndElement(); // NamedMeasurement
}
os
<< "\t\t\t<NamedMeasurement type=\"text/string\" "
<< "name=\"Completion Status\"><Value>"
<< cmXMLSafe(result->CompletionStatus)
<< "</Value></NamedMeasurement>\n";
}
os
<< "\t\t\t<NamedMeasurement type=\"text/string\" "
<< "name=\"Command Line\"><Value>"
<< cmXMLSafe(result->FullCommandLine)
<< "</Value></NamedMeasurement>\n";
xml.StartElement("NamedMeasurement");
xml.Attribute("type", "text/string");
xml.Attribute("name", "Completion Status");
xml.Element("Value", result->CompletionStatus);
xml.EndElement(); // NamedMeasurement
}
xml.StartElement("NamedMeasurement");
xml.Attribute("type", "text/string");
xml.Attribute("name", "Command Line");
xml.Element("Value", result->FullCommandLine);
xml.EndElement(); // NamedMeasurement
std::map<std::string,std::string>::iterator measureIt;
for ( measureIt = result->Properties->Measurements.begin();
measureIt != result->Properties->Measurements.end();
++ measureIt )
{
os
<< "\t\t\t<NamedMeasurement type=\"text/string\" "
<< "name=\"" << measureIt->first << "\"><Value>"
<< cmXMLSafe(measureIt->second)
<< "</Value></NamedMeasurement>\n";
}
os
<< "\t\t\t<Measurement>\n"
<< "\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);
}
os << "\t<EndDateTime>" << this->EndTest << "</EndDateTime>\n"
<< "\t<EndTestTime>" << this->EndTestTime << "</EndTestTime>\n"
<< "<ElapsedMinutes>"
<< static_cast<int>(this->ElapsedTestingTime/6)/10.0
<< "</ElapsedMinutes>"
<< "</Testing>" << std::endl;
this->CTest->EndXML(os);
xml.StartElement("NamedMeasurement");
xml.Attribute("type", "text/string");
xml.Attribute("name", measureIt->first);
xml.Element("Value", measureIt->second);
xml.EndElement(); // NamedMeasurement
}
xml.StartElement("Measurement");
xml.StartElement("Value");
if (result->CompressOutput)
{
xml.Attribute("encoding", "base64");
xml.Attribute("compression", "gzip");
}
xml.Content(result->Output);
xml.EndElement(); // Value
xml.EndElement(); // Measurement
xml.EndElement(); // Results
this->AttachFiles(xml, result);
this->WriteTestResultFooter(xml, result);
}
xml.Element("EndDateTime", this->EndTest);
xml.Element("EndTestTime", this->EndTestTime);
xml.Element("ElapsedMinutes",
static_cast<int>(this->ElapsedTestingTime/6)/10.0);
xml.EndElement(); // Testing
this->CTest->EndXML(xml);
}
//----------------------------------------------------------------------------
void cmCTestTestHandler::WriteTestResultHeader(std::ostream& os,
void cmCTestTestHandler::WriteTestResultHeader(cmXMLWriter& xml,
cmCTestTestResult* result)
{
os << "\t<Test Status=\"";
xml.StartElement("Test");
if ( result->Status == cmCTestTestHandler::COMPLETED )
{
os << "passed";
xml.Attribute("Status", "passed");
}
else if ( result->Status == cmCTestTestHandler::NOT_RUN )
{
os << "notrun";
xml.Attribute("Status", "notrun");
}
else
{
os << "failed";
xml.Attribute("Status", "failed");
}
std::string testPath = result->Path + "/" + result->Name;
os << "\">\n"
<< "\t\t<Name>" << cmXMLSafe(result->Name) << "</Name>\n"
<< "\t\t<Path>" << cmXMLSafe(
this->CTest->GetShortPathToFile(result->Path.c_str())) << "</Path>\n"
<< "\t\t<FullName>" << cmXMLSafe(
this->CTest->GetShortPathToFile(testPath.c_str())) << "</FullName>\n"
<< "\t\t<FullCommandLine>"
<< cmXMLSafe(result->FullCommandLine)
<< "</FullCommandLine>\n";
xml.Element("Name", result->Name);
xml.Element("Path", this->CTest->GetShortPathToFile(result->Path.c_str()));
xml.Element("FullName", this->CTest->GetShortPathToFile(testPath.c_str()));
xml.Element("FullCommandLine", result->FullCommandLine);
}
//----------------------------------------------------------------------------
void cmCTestTestHandler::WriteTestResultFooter(std::ostream& os,
void cmCTestTestHandler::WriteTestResultFooter(cmXMLWriter& xml,
cmCTestTestResult* result)
{
if(!result->Properties->Labels.empty())
{
os << "\t\t<Labels>\n";
xml.StartElement("Labels");
std::vector<std::string> const& labels = result->Properties->Labels;
for(std::vector<std::string>::const_iterator li = labels.begin();
li != labels.end(); ++li)
{
os << "\t\t\t<Label>" << cmXMLSafe(*li) << "</Label>\n";
xml.Element("Label", *li);
}
os << "\t\t</Labels>\n";
xml.EndElement(); // Labels
}
os
<< "\t</Test>" << std::endl;
xml.EndElement(); // Test
}
//----------------------------------------------------------------------
void cmCTestTestHandler::AttachFiles(std::ostream& os,
void cmCTestTestHandler::AttachFiles(cmXMLWriter& xml,
cmCTestTestResult* result)
{
if(result->Status != cmCTestTestHandler::COMPLETED
......@@ -1317,11 +1311,14 @@ void cmCTestTestHandler::AttachFiles(std::ostream& os,
{
const std::string &base64 = this->CTest->Base64GzipEncodeFile(*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";
xml.StartElement("NamedMeasurement");
xml.Attribute("name", "Attached File");
xml.Attribute("encoding", "base64");
xml.Attribute("compression", "tar/gzip");
xml.Attribute("filename", fname);
xml.Attribute("type", "file");
xml.Element("Value", base64);
xml.EndElement(); // NamedMeasurement
}
}
......@@ -1829,7 +1826,7 @@ void cmCTestTestHandler::ExpandTestsToRunInformationForRerunFailed()
#define SPACE_REGEX "[ \t\r\n]"
//----------------------------------------------------------------------
void cmCTestTestHandler::GenerateRegressionImages(
std::ostream& ostr, const std::string& xml)
cmXMLWriter& xml, const std::string& dart)
{
cmsys::RegularExpression twoattributes(
"<DartMeasurement"
......@@ -1865,69 +1862,61 @@ void cmCTestTestHandler::GenerateRegressionImages(
SPACE_REGEX "*>([^<]*)</DartMeasurementFile>");
bool done = false;
std::string cxml = xml;
std::string cxml = dart;
while ( ! done )
{
if ( twoattributes.find(cxml) )
{
ostr
<< "\t\t\t<NamedMeasurement"
<< " " << twoattributes.match(1) << "=\""
<< twoattributes.match(2) << "\""
<< " " << twoattributes.match(3) << "=\""
<< twoattributes.match(4) << "\""
<< "><Value>" << twoattributes.match(5)
<< "</Value></NamedMeasurement>"
<< std::endl;
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) )
{
ostr
<< "\t\t\t<NamedMeasurement"
<< " " << threeattributes.match(1) << "=\""
<< threeattributes.match(2) << "\""
<< " " << threeattributes.match(3) << "=\""
<< threeattributes.match(4) << "\""
<< " " << threeattributes.match(5) << "=\""
<< threeattributes.match(6) << "\""
<< "><Value>" << threeattributes.match(7)
<< "</Value></NamedMeasurement>"
<< std::endl;
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) )
{
ostr
<< "\t\t\t<NamedMeasurement"
<< " " << fourattributes.match(1) << "=\""
<< fourattributes.match(2) << "\""
<< " " << fourattributes.match(3) << "=\""
<< fourattributes.match(4) << "\""
<< " " << fourattributes.match(5) << "=\""
<< fourattributes.match(6) << "\""
<< " " << fourattributes.match(7) << "=\""
<< fourattributes.match(8) << "\""
<< "><Value>" << fourattributes.match(9)
<< "</Value></NamedMeasurement>"
<< std::endl;
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.EndElement();
cxml.erase(fourattributes.start(),
fourattributes.end() - fourattributes.start());