Merge topic 'ctest-xml-refactor'

de2ef305 cmCTest: Drop unused method overloads
b04500a7 cmCTest{Test,MemCheck}Handler: Port to cmXMLWriter
8fbc509a cmCTestCoverageHandler: Port to cmXMLWriter
82455a9d cmCTestBuildHandler: Port to cmXMLWriter
1dbd86fd cmCTestLaunch: Port to cmXMLWriter
a53bd63e cmCTest: Port GenerateNotesFile to cmXMLWriter
9c0bb7d8 cmCTestConfigureHandler: Port to cmXMLWriter
6cf5cc71 cmCTestUploadHandler: Port to cmXMLWriter
ed42c203 cmCTestUpdateHandler: Port to cmXMLWriter
18825baf cmCTest: Port to cmXMLWriter
f6413400 Add cmXMLWriter class to consolidate XML generation
This commit is contained in:
Brad King 2015-05-28 09:56:53 -04:00 committed by CMake Topic Stage
commit 0c24c2311b
26 changed files with 907 additions and 702 deletions

View File

@ -347,6 +347,8 @@ set(SRCS
cmXMLParser.h
cmXMLSafe.cxx
cmXMLSafe.h
cmXMLWriter.cxx
cmXMLWriter.h
cmake.cxx
cmake.h

View File

@ -18,7 +18,7 @@
#include "cmLocalGenerator.h"
#include "cmGlobalGenerator.h"
#include "cmGeneratedFileStream.h"
#include "cmXMLSafe.h"
#include "cmXMLWriter.h"
#include "cmFileTimeComparison.h"
#include "cmAlgorithms.h"
@ -523,16 +523,17 @@ int cmCTestBuildHandler::ProcessHandler()
<< std::endl);
return -1;
}
this->GenerateXMLHeader(xofs);
cmXMLWriter xml(xofs);
this->GenerateXMLHeader(xml);
if(this->UseCTestLaunch)
{
this->GenerateXMLLaunched(xofs);
this->GenerateXMLLaunched(xml);
}
else
{
this->GenerateXMLLogScraped(xofs);
this->GenerateXMLLogScraped(xml);
}
this->GenerateXMLFooter(xofs, elapsed_build_time);
this->GenerateXMLFooter(xml, elapsed_build_time);
if (res != cmsysProcess_State_Exited || retVal || this->TotalErrors > 0)
{
@ -552,17 +553,14 @@ int cmCTestBuildHandler::ProcessHandler()
}
//----------------------------------------------------------------------------
void cmCTestBuildHandler::GenerateXMLHeader(std::ostream& os)
void cmCTestBuildHandler::GenerateXMLHeader(cmXMLWriter& xml)
{
this->CTest->StartXML(os, this->AppendXML);
os << "<Build>\n"
<< "\t<StartDateTime>" << this->StartBuild << "</StartDateTime>\n"
<< "\t<StartBuildTime>" <<
static_cast<unsigned int>(this->StartBuildTime)
<< "</StartBuildTime>\n"
<< "<BuildCommand>"
<< cmXMLSafe(this->GetMakeCommand())
<< "</BuildCommand>" << std::endl;
this->CTest->StartXML(xml, this->AppendXML);
xml.StartElement("Build");
xml.Element("StartDateTime", this->StartBuild);
xml.Element("StartBuildTime",
static_cast<unsigned int>(this->StartBuildTime));
xml.Element("BuildCommand", this->GetMakeCommand());
}
//----------------------------------------------------------------------------
@ -591,7 +589,7 @@ private:
};
//----------------------------------------------------------------------------
void cmCTestBuildHandler::GenerateXMLLaunched(std::ostream& os)
void cmCTestBuildHandler::GenerateXMLLaunched(cmXMLWriter& xml)
{
if(this->CTestLaunchDir.empty())
{
@ -632,12 +630,12 @@ void cmCTestBuildHandler::GenerateXMLLaunched(std::ostream& os)
for(Fragments::const_iterator fi = fragments.begin();
fi != fragments.end(); ++fi)
{
this->GenerateXMLLaunchedFragment(os, fi->c_str());
xml.FragmentFile(fi->c_str());
}
}
//----------------------------------------------------------------------------
void cmCTestBuildHandler::GenerateXMLLogScraped(std::ostream& os)
void cmCTestBuildHandler::GenerateXMLLogScraped(cmXMLWriter& xml)
{
std::vector<cmCTestBuildErrorWarning>& ew = this->ErrorsAndWarnings;
std::vector<cmCTestBuildErrorWarning>::iterator it;
@ -665,10 +663,9 @@ void cmCTestBuildHandler::GenerateXMLLogScraped(std::ostream& os)
{
numWarningsAllowed--;
}
os << "\t<" << (cm->Error ? "Error" : "Warning") << ">\n"
<< "\t\t<BuildLogLine>" << cm->LogLine << "</BuildLogLine>\n"
<< "\t\t<Text>" << cmXMLSafe(cm->Text).Quotes(false)
<< "\n</Text>" << std::endl;
xml.StartElement(cm->Error ? "Error" : "Warning");
xml.Element("BuildLogLine", cm->LogLine);
xml.Element("Text", cm->Text);
std::vector<cmCTestCompileErrorWarningRex>::iterator rit;
for ( rit = this->ErrorWarningFileLineRegex.begin();
rit != this->ErrorWarningFileLineRegex.end(); ++ rit )
@ -706,62 +703,48 @@ void cmCTestBuildHandler::GenerateXMLLogScraped(std::ostream& os)
{
if (!cm->SourceFile.empty())
{
os << "\t\t<SourceFile>" << cm->SourceFile << "</SourceFile>"
<< std::endl;
xml.Element("SourceFile", cm->SourceFile);
}
if (!cm->SourceFileTail.empty())
{
os << "\t\t<SourceFileTail>" << cm->SourceFileTail
<< "</SourceFileTail>" << std::endl;
xml.Element("SourceFileTail", cm->SourceFileTail);
}
if ( cm->LineNumber >= 0 )
{
os << "\t\t<SourceLineNumber>" << cm->LineNumber
<< "</SourceLineNumber>" << std::endl;
xml.Element("SourceLineNumber", cm->LineNumber);
}
}
os << "\t\t<PreContext>" << cmXMLSafe(cm->PreContext).Quotes(false)
<< "</PreContext>\n"
<< "\t\t<PostContext>" << cmXMLSafe(cm->PostContext).Quotes(false);
xml.Element("PreContext", cm->PreContext);
xml.StartElement("PostContext");
xml.Content(cm->PostContext);
// is this the last warning or error, if so notify
if ((cm->Error && !numErrorsAllowed) ||
(!cm->Error && !numWarningsAllowed))
{
os << "\nThe maximum number of reported warnings or errors has been "
"reached!!!\n";
xml.Content("\nThe maximum number of reported warnings or errors "
"has been reached!!!\n");
}
os << "</PostContext>\n"
<< "\t\t<RepeatCount>0</RepeatCount>\n"
<< "</" << (cm->Error ? "Error" : "Warning") << ">\n\n"
<< std::endl;
xml.EndElement(); // PostContext
xml.Element("RepeatCount", "0");
xml.EndElement(); // "Error" / "Warning"
}
}
}
//----------------------------------------------------------------------------
void cmCTestBuildHandler::GenerateXMLFooter(std::ostream& os,
void cmCTestBuildHandler::GenerateXMLFooter(cmXMLWriter& xml,
double elapsed_build_time)
{
os << "\t<Log Encoding=\"base64\" Compression=\"/bin/gzip\">\n\t</Log>\n"
<< "\t<EndDateTime>" << this->EndBuild << "</EndDateTime>\n"
<< "\t<EndBuildTime>" << static_cast<unsigned int>(this->EndBuildTime)
<< "</EndBuildTime>\n"
<< "<ElapsedMinutes>" << static_cast<int>(elapsed_build_time/6)/10.0
<< "</ElapsedMinutes>"
<< "</Build>" << std::endl;
this->CTest->EndXML(os);
}
xml.StartElement("Log");
xml.Attribute("Encoding", "base64");
xml.Attribute("Compression", "bin/gzip");
xml.EndElement(); // Log
//----------------------------------------------------------------------------
void cmCTestBuildHandler::GenerateXMLLaunchedFragment(std::ostream& os,
const char* fname)
{
cmsys::ifstream fin(fname, std::ios::in | std::ios::binary);
std::string line;
while(cmSystemTools::GetLineFromStream(fin, line))
{
os << line << "\n";
}
xml.Element("EndDateTime", this->EndBuild);
xml.Element("EndBuildTime", static_cast<unsigned int>(this->EndBuildTime));
xml.Element("ElapsedMinutes", static_cast<int>(elapsed_build_time/6)/10.0);
xml.EndElement(); // Build
this->CTest->EndXML(xml);
}
//----------------------------------------------------------------------------

View File

@ -22,6 +22,7 @@
#include <deque>
class cmMakefile;
class cmXMLWriter;
/** \class cmCTestBuildHandler
* \brief A class that handles ctest -S invocations
@ -86,11 +87,10 @@ private:
};
// generate the XML output
void GenerateXMLHeader(std::ostream& os);
void GenerateXMLLaunched(std::ostream& os);
void GenerateXMLLogScraped(std::ostream& os);
void GenerateXMLFooter(std::ostream& os, double elapsed_build_time);
void GenerateXMLLaunchedFragment(std::ostream& os, const char* fname);
void GenerateXMLHeader(cmXMLWriter& xml);
void GenerateXMLLaunched(cmXMLWriter& xml);
void GenerateXMLLogScraped(cmXMLWriter& xml);
void GenerateXMLFooter(cmXMLWriter& xml, double elapsed_build_time);
bool IsLaunchedErrorFile(const char* fname);
bool IsLaunchedWarningFile(const char* fname);

View File

@ -13,7 +13,7 @@
#include "cmCTest.h"
#include "cmSystemTools.h"
#include "cmXMLSafe.h"
#include "cmXMLWriter.h"
#include <cmsys/RegularExpression.hxx>
#include <cmsys/FStream.hxx>
@ -266,13 +266,13 @@ void cmCTestCVS::LoadRevisions(std::string const& file,
}
//----------------------------------------------------------------------------
void cmCTestCVS::WriteXMLDirectory(std::ostream& xml,
void cmCTestCVS::WriteXMLDirectory(cmXMLWriter& xml,
std::string const& path,
Directory const& dir)
{
const char* slash = path.empty()? "":"/";
xml << "\t<Directory>\n"
<< "\t\t<Name>" << cmXMLSafe(path) << "</Name>\n";
xml.StartElement("Directory");
xml.Element("Name", path);
// Lookup the branch checked out in the working tree.
std::string branchFlag = this->ComputeBranchFlag(path);
@ -298,11 +298,11 @@ void cmCTestCVS::WriteXMLDirectory(std::ostream& xml,
File f(fi->second, &revisions[0], &revisions[1]);
this->WriteXMLEntry(xml, path, fi->first, full, f);
}
xml << "\t</Directory>\n";
xml.EndElement(); // Directory
}
//----------------------------------------------------------------------------
bool cmCTestCVS::WriteXMLUpdates(std::ostream& xml)
bool cmCTestCVS::WriteXMLUpdates(cmXMLWriter& xml)
{
cmCTestLog(this->CTest, HANDLER_OUTPUT,
" Gathering version information (one . per updated file):\n"

View File

@ -29,7 +29,7 @@ public:
private:
// Implement cmCTestVC internal API.
virtual bool UpdateImpl();
virtual bool WriteXMLUpdates(std::ostream& xml);
virtual bool WriteXMLUpdates(cmXMLWriter& xml);
// Update status for files in each directory.
class Directory: public std::map<std::string, PathStatus> {};
@ -38,7 +38,7 @@ private:
std::string ComputeBranchFlag(std::string const& dir);
void LoadRevisions(std::string const& file, const char* branchFlag,
std::vector<Revision>& revisions);
void WriteXMLDirectory(std::ostream& xml, std::string const& path,
void WriteXMLDirectory(cmXMLWriter& xml, std::string const& path,
Directory const& dir);
// Parsing helper classes.

View File

@ -15,7 +15,7 @@
#include "cmCTest.h"
#include "cmGeneratedFileStream.h"
#include "cmake.h"
#include "cmXMLSafe.h"
#include "cmXMLWriter.h"
#include <cmsys/Process.h>
@ -89,28 +89,22 @@ int cmCTestConfigureHandler::ProcessHandler()
if ( os )
{
this->CTest->StartXML(os, this->AppendXML);
os << "<Configure>\n"
<< "\t<StartDateTime>" << start_time << "</StartDateTime>"
<< std::endl
<< "\t<StartConfigureTime>" << start_time_time
<< "</StartConfigureTime>\n";
os << "<ConfigureCommand>" << cCommand << "</ConfigureCommand>"
<< std::endl;
cmXMLWriter xml(os);
this->CTest->StartXML(xml, this->AppendXML);
xml.StartElement("Configure");
xml.Element("StartDateTime", start_time);
xml.Element("StartConfigureTime", start_time_time);
xml.Element("ConfigureCommand", cCommand);
cmCTestOptionalLog(this->CTest, DEBUG, "End" << std::endl, this->Quiet);
os << "<Log>" << cmXMLSafe(output) << "</Log>" << std::endl;
std::string end_time = this->CTest->CurrentTime();
os << "\t<ConfigureStatus>" << retVal << "</ConfigureStatus>\n"
<< "\t<EndDateTime>" << end_time << "</EndDateTime>\n"
<< "\t<EndConfigureTime>" <<
static_cast<unsigned int>(cmSystemTools::GetTime())
<< "</EndConfigureTime>\n"
<< "<ElapsedMinutes>"
<< static_cast<int>(
(cmSystemTools::GetTime() - elapsed_time_start)/6)/10.0
<< "</ElapsedMinutes>"
<< "</Configure>" << std::endl;
this->CTest->EndXML(os);
xml.Element("Log", output);
xml.Element("ConfigureStatus", retVal);
xml.Element("EndDateTime", this->CTest->CurrentTime());
xml.Element("EndConfigureTime",
static_cast<unsigned int>(cmSystemTools::GetTime()));
xml.Element("ElapsedMinutes", static_cast<int>(
(cmSystemTools::GetTime() - elapsed_time_start)/6)/10.0);
xml.EndElement(); // Configure
this->CTest->EndXML(xml);
}
}
else

View File

@ -22,7 +22,7 @@
#include "cmMakefile.h"
#include "cmSystemTools.h"
#include "cmGeneratedFileStream.h"
#include "cmXMLSafe.h"
#include "cmXMLWriter.h"
#include <cmsys/Process.h>
#include <cmsys/RegularExpression.hxx>
@ -185,14 +185,6 @@ bool cmCTestCoverageHandler::StartCoverageLogFile(
<< covLogFilename << std::endl);
return false;
}
std::string local_start_time = this->CTest->CurrentTime();
this->CTest->StartXML(covLogFile, this->AppendXML);
covLogFile << "<CoverageLog>" << std::endl
<< "\t<StartDateTime>" << local_start_time << "</StartDateTime>"
<< "\t<StartTime>"
<< static_cast<unsigned int>(cmSystemTools::GetTime())
<< "</StartTime>"
<< std::endl;
return true;
}
@ -200,13 +192,6 @@ bool cmCTestCoverageHandler::StartCoverageLogFile(
void cmCTestCoverageHandler::EndCoverageLogFile(cmGeneratedFileStream& ostr,
int logFileCount)
{
std::string local_end_time = this->CTest->CurrentTime();
ostr << "\t<EndDateTime>" << local_end_time << "</EndDateTime>" << std::endl
<< "\t<EndTime>" <<
static_cast<unsigned int>(cmSystemTools::GetTime())
<< "</EndTime>" << std::endl
<< "</CoverageLog>" << std::endl;
this->CTest->EndXML(ostr);
char covLogFilename[1024];
sprintf(covLogFilename, "CoverageLog-%d.xml", logFileCount);
cmCTestOptionalLog(this->CTest, HANDLER_VERBOSE_OUTPUT, "Close file: "
@ -214,6 +199,25 @@ void cmCTestCoverageHandler::EndCoverageLogFile(cmGeneratedFileStream& ostr,
ostr.Close();
}
//----------------------------------------------------------------------
void cmCTestCoverageHandler::StartCoverageLogXML(cmXMLWriter& xml)
{
this->CTest->StartXML(xml, this->AppendXML);
xml.StartElement("CoverageLog");
xml.Element("StartDateTime", this->CTest->CurrentTime());
xml.Element("StartTime",
static_cast<unsigned int>(cmSystemTools::GetTime()));
}
//----------------------------------------------------------------------
void cmCTestCoverageHandler::EndCoverageLogXML(cmXMLWriter& xml)
{
xml.Element("EndDateTime", this->CTest->CurrentTime());
xml.Element("EndTime", static_cast<unsigned int>(cmSystemTools::GetTime()));
xml.EndElement(); // CoverageLog
this->CTest->EndXML(xml);
}
//----------------------------------------------------------------------
bool cmCTestCoverageHandler::ShouldIDoCoverage(const char* file,
const char* srcDir,
@ -451,6 +455,8 @@ int cmCTestCoverageHandler::ProcessHandler()
}
cmGeneratedFileStream covSumFile;
cmGeneratedFileStream covLogFile;
cmXMLWriter covSumXML(covSumFile);
cmXMLWriter covLogXML(covLogFile);
if(!this->StartResultingXML(cmCTest::PartCoverage, "Coverage", covSumFile))
{
@ -458,20 +464,21 @@ int cmCTestCoverageHandler::ProcessHandler()
"Cannot open coverage summary file." << std::endl);
return -1;
}
covSumFile.setf(std::ios::fixed, std::ios::floatfield);
covSumFile.precision(2);
this->CTest->StartXML(covSumFile, this->AppendXML);
this->CTest->StartXML(covSumXML, this->AppendXML);
// Produce output xml files
covSumFile << "<Coverage>" << std::endl
<< "\t<StartDateTime>" << coverage_start_time << "</StartDateTime>"
<< std::endl
<< "\t<StartTime>" << coverage_start_time_time << "</StartTime>"
<< std::endl;
covSumXML.StartElement("Coverage");
covSumXML.Element("StartDateTime", coverage_start_time);
covSumXML.Element("StartTime", coverage_start_time_time);
int logFileCount = 0;
if ( !this->StartCoverageLogFile(covLogFile, logFileCount) )
{
return -1;
}
this->StartCoverageLogXML(covLogXML);
cmCTestCoverageHandlerContainer::TotalCoverageMap::iterator fileIterator;
int cnt = 0;
long total_tested = 0;
@ -528,12 +535,14 @@ int cmCTestCoverageHandler::ProcessHandler()
if ( ++cnt % 100 == 0 )
{
this->EndCoverageLogXML(covLogXML);
this->EndCoverageLogFile(covLogFile, logFileCount);
logFileCount ++;
if ( !this->StartCoverageLogFile(covLogFile, logFileCount) )
{
return -1;
}
this->StartCoverageLogXML(covLogXML);
}
const std::string fileName
@ -542,9 +551,10 @@ int cmCTestCoverageHandler::ProcessHandler()
this->CTest->GetShortPathToFile(fullFileName.c_str());
const cmCTestCoverageHandlerContainer::SingleFileCoverageVector& fcov
= fileIterator->second;
covLogFile << "\t<File Name=\"" << cmXMLSafe(fileName)
<< "\" FullPath=\"" << cmXMLSafe(shortFileName) << "\">\n"
<< "\t\t<Report>" << std::endl;
covLogXML.StartElement("File");
covLogXML.Attribute("Name", fileName);
covLogXML.Attribute("FullPath", shortFileName);
covLogXML.StartElement("Report");
cmsys::ifstream ifs(fullFileName.c_str());
if ( !ifs)
@ -576,9 +586,11 @@ int cmCTestCoverageHandler::ProcessHandler()
error ++;
break;
}
covLogFile << "\t\t<Line Number=\"" << cc << "\" Count=\"" << fcov[cc]
<< "\">"
<< cmXMLSafe(line) << "</Line>" << std::endl;
covLogXML.StartElement("Line");
covLogXML.Attribute("Number", cc);
covLogXML.Attribute("Count", fcov[cc]);
covLogXML.Content(line);
covLogXML.EndElement(); // Line
if ( fcov[cc] == 0 )
{
untested ++;
@ -605,24 +617,19 @@ int cmCTestCoverageHandler::ProcessHandler()
}
total_tested += tested;
total_untested += untested;
covLogFile << "\t\t</Report>" << std::endl
<< "\t</File>" << std::endl;
covSumFile << "\t<File Name=\"" << cmXMLSafe(fileName)
<< "\" FullPath=\"" << cmXMLSafe(
this->CTest->GetShortPathToFile(fullFileName.c_str()))
<< "\" Covered=\"" << (tested+untested > 0 ? "true":"false") << "\">\n"
<< "\t\t<LOCTested>" << tested << "</LOCTested>\n"
<< "\t\t<LOCUnTested>" << untested << "</LOCUnTested>\n"
<< "\t\t<PercentCoverage>";
covSumFile.setf(std::ios::fixed, std::ios::floatfield);
covSumFile.precision(2);
covSumFile << (cper) << "</PercentCoverage>\n"
<< "\t\t<CoverageMetric>";
covSumFile.setf(std::ios::fixed, std::ios::floatfield);
covSumFile.precision(2);
covSumFile << (cmet) << "</CoverageMetric>\n";
this->WriteXMLLabels(covSumFile, shortFileName);
covSumFile << "\t</File>" << std::endl;
covLogXML.EndElement(); // Report
covLogXML.EndElement(); // File
covSumXML.StartElement("File");
covSumXML.Attribute("Name", fileName);
covSumXML.Attribute("FullPath",
this->CTest->GetShortPathToFile(fullFileName.c_str()));
covSumXML.Attribute("Covered", tested + untested > 0 ? "true" : "false");
covSumXML.Element("LOCTested", tested);
covSumXML.Element("LOCUnTested", untested);
covSumXML.Element("PercentCoverage", cper);
covSumXML.Element("CoverageMetric", cmet);
this->WriteXMLLabels(covSumXML, shortFileName);
covSumXML.EndElement(); // File
}
//Handle all the files in the extra coverage globs that have no cov data
@ -632,9 +639,10 @@ int cmCTestCoverageHandler::ProcessHandler()
std::string fileName = cmSystemTools::GetFilenameName(*i);
std::string fullPath = cont.SourceDir + "/" + *i;
covLogFile << "\t<File Name=\"" << cmXMLSafe(fileName)
<< "\" FullPath=\"" << cmXMLSafe(*i) << "\">\n"
<< "\t\t<Report>" << std::endl;
covLogXML.StartElement("File");
covLogXML.Attribute("Name", fileName);
covLogXML.Attribute("FullPath", *i);
covLogXML.StartElement("Report");
cmsys::ifstream ifs(fullPath.c_str());
if (!ifs)
@ -651,24 +659,30 @@ int cmCTestCoverageHandler::ProcessHandler()
"Actually performing coverage for: " << *i << std::endl, this->Quiet);
while (cmSystemTools::GetLineFromStream(ifs, line))
{
covLogFile << "\t\t<Line Number=\"" << untested << "\" Count=\"0\">"
<< cmXMLSafe(line) << "</Line>" << std::endl;
covLogXML.StartElement("Line");
covLogXML.Attribute("Number", untested);
covLogXML.Attribute("Count", 0);
covLogXML.Content(line);
covLogXML.EndElement(); // Line
untested ++;
}
covLogFile << "\t\t</Report>\n\t</File>" << std::endl;
covLogXML.EndElement(); // Report
covLogXML.EndElement(); // File
total_untested += untested;
covSumFile << "\t<File Name=\"" << cmXMLSafe(fileName)
<< "\" FullPath=\"" << cmXMLSafe(i->c_str())
<< "\" Covered=\"true\">\n"
<< "\t\t<LOCTested>0</LOCTested>\n"
<< "\t\t<LOCUnTested>" << untested << "</LOCUnTested>\n"
<< "\t\t<PercentCoverage>0</PercentCoverage>\n"
<< "\t\t<CoverageMetric>0</CoverageMetric>\n";
this->WriteXMLLabels(covSumFile, *i);
covSumFile << "\t</File>" << std::endl;
covSumXML.StartElement("File");
covSumXML.Attribute("Name", fileName);
covSumXML.Attribute("FullPath", *i);
covSumXML.Attribute("Covered", "true");
covSumXML.Element("LOCTested", 0);
covSumXML.Element("LOCUnTested", untested);
covSumXML.Element("PercentCoverage", 0);
covSumXML.Element("CoverageMetric", 0);
this->WriteXMLLabels(covSumXML, *i);
covSumXML.EndElement(); // File
}
this->EndCoverageLogXML(covLogXML);
this->EndCoverageLogFile(covLogFile, logFileCount);
if (!errorsWhileAccumulating.empty())
@ -696,22 +710,17 @@ int cmCTestCoverageHandler::ProcessHandler()
std::string end_time = this->CTest->CurrentTime();
covSumFile << "\t<LOCTested>" << total_tested << "</LOCTested>\n"
<< "\t<LOCUntested>" << total_untested << "</LOCUntested>\n"
<< "\t<LOC>" << total_lines << "</LOC>\n"
<< "\t<PercentCoverage>";
covSumFile.setf(std::ios::fixed, std::ios::floatfield);
covSumFile.precision(2);
covSumFile << (percent_coverage)<< "</PercentCoverage>\n"
<< "\t<EndDateTime>" << end_time << "</EndDateTime>\n"
<< "\t<EndTime>" <<
static_cast<unsigned int>(cmSystemTools::GetTime())
<< "</EndTime>\n";
covSumFile << "<ElapsedMinutes>" <<
static_cast<int>((cmSystemTools::GetTime() - elapsed_time_start)/6)/10.0
<< "</ElapsedMinutes>"
<< "</Coverage>" << std::endl;
this->CTest->EndXML(covSumFile);
covSumXML.Element("LOCTested", total_tested);
covSumXML.Element("LOCUntested", total_untested);
covSumXML.Element("LOC", total_lines);
covSumXML.Element("PercentCoverage", percent_coverage);
covSumXML.Element("EndDateTime", end_time);
covSumXML.Element("EndTime",
static_cast<unsigned int>(cmSystemTools::GetTime()));
covSumXML.Element("ElapsedMinutes",
static_cast<int>((cmSystemTools::GetTime() - elapsed_time_start)/6)/10.0);
covSumXML.EndElement(); // Coverage
this->CTest->EndXML(covSumXML);
cmCTestLog(this->CTest, HANDLER_OUTPUT, "" << std::endl
<< "\tCovered LOC: "
@ -1952,11 +1961,13 @@ int cmCTestCoverageHandler::RunBullseyeCoverageBranch(
}
// create the output stream for the CoverageLog-N.xml file
cmGeneratedFileStream covLogFile;
cmXMLWriter covLogXML(covLogFile);
int logFileCount = 0;
if ( !this->StartCoverageLogFile(covLogFile, logFileCount) )
{
return -1;
}
this->StartCoverageLogXML(covLogXML);
// for each file run covbr on that file to get the coverage
// information for that file
std::string outputFile;
@ -2009,20 +2020,22 @@ int cmCTestCoverageHandler::RunBullseyeCoverageBranch(
// if we are in a valid file close it because a new one started
if(valid)
{
covLogFile << "\t\t</Report>" << std::endl
<< "\t</File>" << std::endl;
covLogXML.EndElement(); // Report
covLogXML.EndElement(); // File
}
// only allow 100 files in each log file
if ( count != 0 && count % 100 == 0 )
{
cmCTestOptionalLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
"start a new log file: " << count << std::endl, this->Quiet);
this->EndCoverageLogXML(covLogXML);
this->EndCoverageLogFile(covLogFile, logFileCount);
logFileCount ++;
if ( !this->StartCoverageLogFile(covLogFile, logFileCount) )
{
return -1;
}
this->StartCoverageLogXML(covLogXML);
count++; // move on one
}
std::map<std::string, std::string>::iterator
@ -2036,19 +2049,20 @@ int cmCTestCoverageHandler::RunBullseyeCoverageBranch(
"Produce coverage for file: " << file << " " << count
<< std::endl, this->Quiet);
// start the file output
covLogFile << "\t<File Name=\""
<< cmXMLSafe(i->first)
<< "\" FullPath=\"" << cmXMLSafe(
this->CTest->GetShortPathToFile(
i->second.c_str())) << "\">" << std::endl
<< "\t\t<Report>" << std::endl;
covLogXML.StartElement("File");
covLogXML.Attribute("Name", i->first);
covLogXML.Attribute("FullPath",
this->CTest->GetShortPathToFile(i->second.c_str()));
covLogXML.StartElement("Report");
// write the bullseye header
line =0;
for(int k =0; bullseyeHelp[k] != 0; ++k)
{
covLogFile << "\t\t<Line Number=\"" << line << "\" Count=\"-1\">"
<< cmXMLSafe(bullseyeHelp[k])
<< "</Line>" << std::endl;
covLogXML.StartElement("Line");
covLogXML.Attribute("Number", line);
covLogXML.Attribute("Count", -1);
covLogXML.Content(bullseyeHelp[k]);
covLogXML.EndElement(); // Line
line++;
}
valid = true; // we are in a valid file section
@ -2062,18 +2076,21 @@ int cmCTestCoverageHandler::RunBullseyeCoverageBranch(
// we are not at a start file, and we are in a valid file output the line
else if(valid)
{
covLogFile << "\t\t<Line Number=\"" << line << "\" Count=\"-1\">"
<< cmXMLSafe(lineIn)
<< "</Line>" << std::endl;
covLogXML.StartElement("Line");
covLogXML.Attribute("Number", line);
covLogXML.Attribute("Count", -1);
covLogXML.Content(lineIn);
covLogXML.EndElement(); // Line
line++;
}
}
// if we ran out of lines a valid file then close that file
if(valid)
{
covLogFile << "\t\t</Report>" << std::endl
<< "\t</File>" << std::endl;
covLogXML.EndElement(); // Report
covLogXML.EndElement(); // File
}
this->EndCoverageLogXML(covLogXML);
this->EndCoverageLogFile(covLogFile, logFileCount);
return 1;
}
@ -2143,23 +2160,20 @@ int cmCTestCoverageHandler::RunBullseyeSourceSummary(
std::ostream& tmpLog = *cont->OFS;
// copen the Coverage.xml file in the Testing directory
cmGeneratedFileStream covSumFile;
cmXMLWriter xml(covSumFile);
if(!this->StartResultingXML(cmCTest::PartCoverage, "Coverage", covSumFile))
{
cmCTestLog(this->CTest, ERROR_MESSAGE,
"Cannot open coverage summary file." << std::endl);
return 0;
}
this->CTest->StartXML(covSumFile, this->AppendXML);
this->CTest->StartXML(xml, this->AppendXML);
double elapsed_time_start = cmSystemTools::GetTime();
std::string coverage_start_time = this->CTest->CurrentTime();
covSumFile << "<Coverage>" << std::endl
<< "\t<StartDateTime>"
<< coverage_start_time << "</StartDateTime>"
<< std::endl
<< "\t<StartTime>"
<< static_cast<unsigned int>(cmSystemTools::GetTime())
<< "</StartTime>"
<< std::endl;
xml.StartElement("Coverage");
xml.Element("StartDateTime", coverage_start_time);
xml.Element("StartTime",
static_cast<unsigned int>(cmSystemTools::GetTime()));
std::string stdline;
std::string errline;
// expected output:
@ -2271,58 +2285,35 @@ int cmCTestCoverageHandler::RunBullseyeSourceSummary(
tmpLog << "percentBranch: " << percentBranch << "\n";
tmpLog << "percentCoverage: " << percent_coverage << "\n";
tmpLog << "coverage metric: " << cmet << "\n";
covSumFile << "\t<File Name=\"" << cmXMLSafe(sourceFile)
<< "\" FullPath=\"" << cmXMLSafe(shortFileName)
<< "\" Covered=\"" << (cmet>0?"true":"false") << "\">\n"
<< "\t\t<BranchesTested>"
<< branchCovered
<< "</BranchesTested>\n"
<< "\t\t<BranchesUnTested>"
<< totalBranches - branchCovered
<< "</BranchesUnTested>\n"
<< "\t\t<FunctionsTested>"
<< functionsCalled
<< "</FunctionsTested>\n"
<< "\t\t<FunctionsUnTested>"
<< totalFunctions - functionsCalled
<< "</FunctionsUnTested>\n"
// Hack for conversion of function to loc assume a function
// has 100 lines of code
<< "\t\t<LOCTested>" << functionsCalled *100
<< "</LOCTested>\n"
<< "\t\t<LOCUnTested>"
<< (totalFunctions - functionsCalled)*100
<< "</LOCUnTested>\n"
<< "\t\t<PercentCoverage>";
covSumFile.setf(std::ios::fixed, std::ios::floatfield);
covSumFile.precision(2);
covSumFile << (cper) << "</PercentCoverage>\n"
<< "\t\t<CoverageMetric>";
covSumFile.setf(std::ios::fixed, std::ios::floatfield);
covSumFile.precision(2);
covSumFile << (cmet) << "</CoverageMetric>\n";
this->WriteXMLLabels(covSumFile, shortFileName);
covSumFile << "\t</File>" << std::endl;
xml.StartElement("File");
xml.Attribute("Name", sourceFile);
xml.Attribute("FullPath", shortFileName);
xml.Attribute("Covered", cmet > 0 ? "true" : "false");
xml.Element("BranchesTested", branchCovered);
xml.Element("BranchesUnTested", totalBranches - branchCovered);
xml.Element("FunctionsTested", functionsCalled);
xml.Element("FunctionsUnTested", totalFunctions - functionsCalled);
// Hack for conversion of function to loc assume a function
// has 100 lines of code
xml.Element("LOCTested", functionsCalled * 100);
xml.Element("LOCUnTested", (totalFunctions - functionsCalled) * 100);
xml.Element("PercentCoverage", cper);
xml.Element("CoverageMetric", cmet);
this->WriteXMLLabels(xml, shortFileName);
xml.EndElement(); // File
}
}
std::string end_time = this->CTest->CurrentTime();
covSumFile << "\t<LOCTested>" << total_tested << "</LOCTested>\n"
<< "\t<LOCUntested>" << total_untested << "</LOCUntested>\n"
<< "\t<LOC>" << total_functions << "</LOC>\n"
<< "\t<PercentCoverage>";
covSumFile.setf(std::ios::fixed, std::ios::floatfield);
covSumFile.precision(2);
covSumFile
<< SAFEDIV(percent_coverage,number_files)<< "</PercentCoverage>\n"
<< "\t<EndDateTime>" << end_time << "</EndDateTime>\n"
<< "\t<EndTime>" << static_cast<unsigned int>(cmSystemTools::GetTime())
<< "</EndTime>\n";
covSumFile
<< "<ElapsedMinutes>" <<
static_cast<int>((cmSystemTools::GetTime() - elapsed_time_start)/6)/10.0
<< "</ElapsedMinutes>"
<< "</Coverage>" << std::endl;
this->CTest->EndXML(covSumFile);
xml.Element("LOCTested", total_tested);
xml.Element("LOCUntested", total_untested);
xml.Element("LOC", total_functions);
xml.Element("PercentCoverage", SAFEDIV(percent_coverage, number_files));
xml.Element("EndDateTime", end_time);
xml.Element("EndTime", static_cast<unsigned int>(cmSystemTools::GetTime()));
xml.Element("ElapsedMinutes",
static_cast<int>((cmSystemTools::GetTime() - elapsed_time_start)/6)/10.0);
xml.EndElement(); // Coverage
this->CTest->EndXML(xml);
// Now create the coverage information for each file
return this->RunBullseyeCoverageBranch(cont,
@ -2514,19 +2505,19 @@ void cmCTestCoverageHandler::LoadLabels(const char* dir)
}
//----------------------------------------------------------------------
void cmCTestCoverageHandler::WriteXMLLabels(std::ostream& os,
void cmCTestCoverageHandler::WriteXMLLabels(cmXMLWriter& xml,
std::string const& source)
{
LabelMapType::const_iterator li = this->SourceLabels.find(source);
if(li != this->SourceLabels.end() && !li->second.empty())
{
os << "\t\t<Labels>\n";
xml.StartElement("Labels");
for(LabelSet::const_iterator lsi = li->second.begin();
lsi != li->second.end(); ++lsi)
{
os << "\t\t\t<Label>" << cmXMLSafe(this->Labels[*lsi]) << "</Label>\n";
xml.Element("Label", this->Labels[*lsi]);
}
os << "\t\t</Labels>\n";
xml.EndElement(); // Labels
}
}

View File

@ -20,6 +20,7 @@
#include <cmsys/RegularExpression.hxx>
class cmGeneratedFileStream;
class cmXMLWriter;
class cmCTestCoverageHandlerContainer
{
public:
@ -65,6 +66,9 @@ private:
bool StartCoverageLogFile(cmGeneratedFileStream& ostr, int logFileCount);
void EndCoverageLogFile(cmGeneratedFileStream& ostr, int logFileCount);
void StartCoverageLogXML(cmXMLWriter& xml);
void EndCoverageLogXML(cmXMLWriter& xml);
//! Handle coverage using GCC's GCov
int HandleGCovCoverage(cmCTestCoverageHandlerContainer* cont);
void FindGCovFiles(std::vector<std::string>& files);
@ -146,7 +150,7 @@ private:
// Label reading and writing methods.
void LoadLabels();
void LoadLabels(const char* dir);
void WriteXMLLabels(std::ostream& os, std::string const& source);
void WriteXMLLabels(cmXMLWriter& xml, std::string const& source);
// Label-based filtering.
std::set<int> LabelFilter;

View File

@ -13,7 +13,7 @@
#include "cmCTest.h"
#include "cmSystemTools.h"
#include "cmXMLSafe.h"
#include "cmXMLWriter.h"
#include <cmsys/RegularExpression.hxx>
@ -91,36 +91,36 @@ void cmCTestGlobalVC::DoModification(PathStatus status,
}
//----------------------------------------------------------------------------
void cmCTestGlobalVC::WriteXMLDirectory(std::ostream& xml,
void cmCTestGlobalVC::WriteXMLDirectory(cmXMLWriter& xml,
std::string const& path,
Directory const& dir)
{
const char* slash = path.empty()? "":"/";
xml << "\t<Directory>\n"
<< "\t\t<Name>" << cmXMLSafe(path) << "</Name>\n";
xml.StartElement("Directory");
xml.Element("Name", path);
for(Directory::const_iterator fi = dir.begin(); fi != dir.end(); ++fi)
{
std::string full = path + slash + fi->first;
this->WriteXMLEntry(xml, path, fi->first, full, fi->second);
}
xml << "\t</Directory>\n";
xml.EndElement(); // Directory
}
//----------------------------------------------------------------------------
void cmCTestGlobalVC::WriteXMLGlobal(std::ostream& xml)
void cmCTestGlobalVC::WriteXMLGlobal(cmXMLWriter& xml)
{
if(!this->NewRevision.empty())
{
xml << "\t<Revision>" << this->NewRevision << "</Revision>\n";
xml.Element("Revision", this->NewRevision);
}
if(!this->OldRevision.empty() && this->OldRevision != this->NewRevision)
{
xml << "\t<PriorRevision>" << this->OldRevision << "</PriorRevision>\n";
xml.Element("PriorRevision", this->OldRevision);
}
}
//----------------------------------------------------------------------------
bool cmCTestGlobalVC::WriteXMLUpdates(std::ostream& xml)
bool cmCTestGlobalVC::WriteXMLUpdates(cmXMLWriter& xml)
{
cmCTestLog(this->CTest, HANDLER_OUTPUT,
" Gathering version information (one . per revision):\n"

View File

@ -30,7 +30,7 @@ public:
protected:
// Implement cmCTestVC internal API.
virtual bool WriteXMLUpdates(std::ostream& xml);
virtual bool WriteXMLUpdates(cmXMLWriter& xml);
/** Represent a vcs-reported action for one path in a revision. */
struct Change
@ -62,8 +62,8 @@ protected:
virtual void LoadModifications() = 0;
virtual void LoadRevisions() = 0;
virtual void WriteXMLGlobal(std::ostream& xml);
void WriteXMLDirectory(std::ostream& xml, std::string const& path,
virtual void WriteXMLGlobal(cmXMLWriter& xml);
void WriteXMLDirectory(cmXMLWriter& xml, std::string const& path,
Directory const& dir);
};

View File

@ -13,7 +13,7 @@
#include "cmGeneratedFileStream.h"
#include "cmSystemTools.h"
#include "cmXMLSafe.h"
#include "cmXMLWriter.h"
#include "cmake.h"
#include <cmsys/MD5.h>
@ -407,35 +407,32 @@ void cmCTestLaunch::WriteXML()
// Use cmGeneratedFileStream to atomically create the report file.
cmGeneratedFileStream fxml(logXML.c_str());
fxml << "\t<Failure type=\""
<< (this->IsError()? "Error" : "Warning") << "\">\n";
this->WriteXMLAction(fxml);
this->WriteXMLCommand(fxml);
this->WriteXMLResult(fxml);
this->WriteXMLLabels(fxml);
fxml << "\t</Failure>\n";
cmXMLWriter xml(fxml, 2);
xml.StartElement("Failure");
xml.Attribute("type", this->IsError() ? "Error" : "Warning");
this->WriteXMLAction(xml);
this->WriteXMLCommand(xml);
this->WriteXMLResult(xml);
this->WriteXMLLabels(xml);
xml.EndElement(); // Failure
}
//----------------------------------------------------------------------------
void cmCTestLaunch::WriteXMLAction(std::ostream& fxml)
void cmCTestLaunch::WriteXMLAction(cmXMLWriter& xml)
{
fxml << "\t\t<!-- Meta-information about the build action -->\n";
fxml << "\t\t<Action>\n";
xml.Comment("Meta-information about the build action");
xml.StartElement("Action");
// TargetName
if(!this->OptionTargetName.empty())
{
fxml << "\t\t\t<TargetName>"
<< cmXMLSafe(this->OptionTargetName)
<< "</TargetName>\n";
xml.Element("TargetName", this->OptionTargetName);
}
// Language
if(!this->OptionLanguage.empty())
{
fxml << "\t\t\t<Language>"
<< cmXMLSafe(this->OptionLanguage)
<< "</Language>\n";
xml.Element("Language", this->OptionLanguage);
}
// SourceFile
@ -454,17 +451,13 @@ void cmCTestLaunch::WriteXMLAction(std::ostream& fxml)
source.c_str());
}
fxml << "\t\t\t<SourceFile>"
<< cmXMLSafe(source)
<< "</SourceFile>\n";
xml.Element("SourceFile", source);
}
// OutputFile
if(!this->OptionOutput.empty())
{
fxml << "\t\t\t<OutputFile>"
<< cmXMLSafe(this->OptionOutput)
<< "</OutputFile>\n";
xml.Element("OutputFile", this->OptionOutput);
}
// OutputType
@ -494,103 +487,94 @@ void cmCTestLaunch::WriteXMLAction(std::ostream& fxml)
}
if(outputType)
{
fxml << "\t\t\t<OutputType>"
<< cmXMLSafe(outputType)
<< "</OutputType>\n";
xml.Element("OutputType", outputType);
}
fxml << "\t\t</Action>\n";
xml.EndElement(); // Action
}
//----------------------------------------------------------------------------
void cmCTestLaunch::WriteXMLCommand(std::ostream& fxml)
void cmCTestLaunch::WriteXMLCommand(cmXMLWriter& xml)
{
fxml << "\n";
fxml << "\t\t<!-- Details of command -->\n";
fxml << "\t\t<Command>\n";
xml.Comment("Details of command");
xml.StartElement("Command");
if(!this->CWD.empty())
{
fxml << "\t\t\t<WorkingDirectory>"
<< cmXMLSafe(this->CWD)
<< "</WorkingDirectory>\n";
xml.Element("WorkingDirectory", this->CWD);
}
for(std::vector<std::string>::const_iterator ai = this->RealArgs.begin();
ai != this->RealArgs.end(); ++ai)
{
fxml << "\t\t\t<Argument>"
<< cmXMLSafe(ai->c_str())
<< "</Argument>\n";
xml.Element("Argument", *ai);
}
fxml << "\t\t</Command>\n";
xml.EndElement(); // Command
}
//----------------------------------------------------------------------------
void cmCTestLaunch::WriteXMLResult(std::ostream& fxml)
void cmCTestLaunch::WriteXMLResult(cmXMLWriter& xml)
{
fxml << "\n";
fxml << "\t\t<!-- Result of command -->\n";
fxml << "\t\t<Result>\n";
xml.Comment("Result of command");
xml.StartElement("Result");
// StdOut
fxml << "\t\t\t<StdOut>";
this->DumpFileToXML(fxml, this->LogOut);
fxml << "</StdOut>\n";
xml.StartElement("StdOut");
this->DumpFileToXML(xml, this->LogOut);
xml.EndElement(); // StdOut
// StdErr
fxml << "\t\t\t<StdErr>";
this->DumpFileToXML(fxml, this->LogErr);
fxml << "</StdErr>\n";
xml.StartElement("StdErr");
this->DumpFileToXML(xml, this->LogErr);
xml.EndElement(); // StdErr
// ExitCondition
fxml << "\t\t\t<ExitCondition>";
xml.StartElement("ExitCondition");
cmsysProcess* cp = this->Process;
switch (cmsysProcess_GetState(cp))
{
case cmsysProcess_State_Starting:
fxml << "No process has been executed"; break;
xml.Content("No process has been executed"); break;
case cmsysProcess_State_Executing:
fxml << "The process is still executing"; break;
xml.Content("The process is still executing"); break;
case cmsysProcess_State_Disowned:
fxml << "Disowned"; break;
xml.Content("Disowned"); break;
case cmsysProcess_State_Killed:
fxml << "Killed by parent"; break;
xml.Content("Killed by parent"); break;
case cmsysProcess_State_Expired:
fxml << "Killed when timeout expired"; break;
xml.Content("Killed when timeout expired"); break;
case cmsysProcess_State_Exited:
fxml << this->ExitCode; break;
xml.Content(this->ExitCode); break;
case cmsysProcess_State_Exception:
fxml << "Terminated abnormally: "
<< cmXMLSafe(cmsysProcess_GetExceptionString(cp)); break;
xml.Content("Terminated abnormally: ");
xml.Content(cmsysProcess_GetExceptionString(cp)); break;
case cmsysProcess_State_Error:
fxml << "Error administrating child process: "
<< cmXMLSafe(cmsysProcess_GetErrorString(cp)); break;
xml.Content("Error administrating child process: ");
xml.Content(cmsysProcess_GetErrorString(cp)); break;
};
fxml << "</ExitCondition>\n";
xml.EndElement(); // ExitCondition
fxml << "\t\t</Result>\n";
xml.EndElement(); // Result
}
//----------------------------------------------------------------------------
void cmCTestLaunch::WriteXMLLabels(std::ostream& fxml)
void cmCTestLaunch::WriteXMLLabels(cmXMLWriter& xml)
{
this->LoadLabels();
if(!this->Labels.empty())
{
fxml << "\n";
fxml << "\t\t<!-- Interested parties -->\n";
fxml << "\t\t<Labels>\n";
xml.Comment("Interested parties");
xml.StartElement("Labels");
for(std::set<std::string>::const_iterator li = this->Labels.begin();
li != this->Labels.end(); ++li)
{
fxml << "\t\t\t<Label>" << cmXMLSafe(*li) << "</Label>\n";
xml.Element("Label", *li);
}
fxml << "\t\t</Labels>\n";
xml.EndElement(); // Labels
}
}
//----------------------------------------------------------------------------
void cmCTestLaunch::DumpFileToXML(std::ostream& fxml,
void cmCTestLaunch::DumpFileToXML(cmXMLWriter& xml,
std::string const& fname)
{
cmsys::ifstream fin(fname.c_str(), std::ios::in | std::ios::binary);
@ -605,7 +589,8 @@ void cmCTestLaunch::DumpFileToXML(std::ostream& fxml,
continue;
}
fxml << sep << cmXMLSafe(line).Quotes(false);
xml.Content(sep);
xml.Content(line);
sep = "\n";
}
}

View File

@ -15,6 +15,8 @@
#include "cmStandardIncludes.h"
#include <cmsys/RegularExpression.hxx>
class cmXMLWriter;
/** \class cmCTestLaunch
* \brief Launcher for make rules to report results for ctest
*
@ -92,11 +94,11 @@ private:
// Methods to generate the xml fragment.
void WriteXML();
void WriteXMLAction(std::ostream& fxml);
void WriteXMLCommand(std::ostream& fxml);
void WriteXMLResult(std::ostream& fxml);
void WriteXMLLabels(std::ostream& fxml);
void DumpFileToXML(std::ostream& fxml, std::string const& fname);
void WriteXMLAction(cmXMLWriter& xml);
void WriteXMLCommand(cmXMLWriter& xml);
void WriteXMLResult(cmXMLWriter& xml);
void WriteXMLLabels(cmXMLWriter& xml);
void DumpFileToXML(cmXMLWriter& xml, std::string const& fname);
// Configuration
void LoadConfig();

View File

@ -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);
}
//----------------------------------------------------------------------

View File

@ -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;

View File

@ -14,7 +14,7 @@
#include "cmCTest.h"
#include "cmSystemTools.h"
#include "cmXMLParser.h"
#include "cmXMLSafe.h"
#include "cmXMLWriter.h"
#include <cmsys/RegularExpression.hxx>
@ -535,11 +535,11 @@ void cmCTestSVN::LoadModifications()
}
//----------------------------------------------------------------------------
void cmCTestSVN::WriteXMLGlobal(std::ostream& xml)
void cmCTestSVN::WriteXMLGlobal(cmXMLWriter& xml)
{
this->cmCTestGlobalVC::WriteXMLGlobal(xml);
xml << "\t<SVNPath>" << this->RootInfo->Base << "</SVNPath>\n";
xml.Element("SVNPath", this->RootInfo->Base);
}
//----------------------------------------------------------------------------

View File

@ -84,7 +84,7 @@ private:
void DoRevisionSVN(Revision const& revision,
std::vector<Change> const& changes);
void WriteXMLGlobal(std::ostream& xml);
void WriteXMLGlobal(cmXMLWriter& xml);
// Parsing helper classes.
class InfoParser;

View File

@ -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";
xml.StartElement("NamedMeasurement");
xml.Attribute("type", "text/string");
xml.Attribute("name", "Completion Status");
xml.Element("Value", result->CompletionStatus);
xml.EndElement(); // NamedMeasurement
}
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", "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";
xml.StartElement("NamedMeasurement");
xml.Attribute("type", "text/string");
xml.Attribute("name", measureIt->first);
xml.Element("Value", measureIt->second);
xml.EndElement(); // NamedMeasurement
}
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";
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(os, result);
this->WriteTestResultFooter(os, result);
this->AttachFiles(xml, result);
this->WriteTestResultFooter(xml, 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.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
}
}
@ -1828,7 +1825,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"
@ -1864,69 +1861,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());
}
else if ( cdatastart.find(cxml) && cdataend.find(cxml) )
{
ostr
<< "\t\t\t<NamedMeasurement"
<< " " << cdatastart.match(1) << "=\""
<< cdatastart.match(2) << "\""
<< " " << cdatastart.match(3) << "=\""
<< cdatastart.match(4) << "\""
<< "><Value><![CDATA["
<< cxml.substr(cdatastart.end(), cdataend.start() - cdatastart.end())
<< "]]></Value></NamedMeasurement>"
<< std::endl;
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());
}
@ -1952,13 +1941,12 @@ void cmCTestTestHandler::GenerateRegressionImages(
v2 = "text/string";
}
ostr
<< "\t\t\t<NamedMeasurement"
<< " " << k1 << "=\"" << v1 << "\""
<< " " << k2 << "=\"" << v2 << "\""
<< " encoding=\"none\""
<< "><Value>Image " << filename
<< " is empty</Value></NamedMeasurement>";
xml.StartElement("NamedMeasurement");
xml.Attribute(k1.c_str(), v1);
xml.Attribute(k2.c_str(), v2);
xml.Attribute("encoding", "none");
xml.Element("Value", "Image " + filename + " is empty");
xml.EndElement();
}
else
{
@ -1976,14 +1964,13 @@ void cmCTestTestHandler::GenerateRegressionImages(
size_t rlen
= cmsysBase64_Encode(file_buffer, len, encoded_buffer, 1);
ostr
<< "\t\t\t<NamedMeasurement"
<< " " << measurementfile.match(1) << "=\""
<< measurementfile.match(2) << "\""
<< " " << measurementfile.match(3) << "=\""
<< measurementfile.match(4) << "\""
<< " encoding=\"base64\""
<< ">" << std::endl << "\t\t\t\t<Value>";
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("encoding", "base64");
std::stringstream ostr;
for (size_t cc = 0; cc < rlen; cc ++ )
{
ostr << encoded_buffer[cc];
@ -1992,9 +1979,8 @@ void cmCTestTestHandler::GenerateRegressionImages(
ostr << std::endl;
}
}
ostr
<< "</Value>" << std::endl << "\t\t\t</NamedMeasurement>"
<< std::endl;
xml.Element("Value", ostr.str());
xml.EndElement(); // NamedMeasurement
delete [] file_buffer;
delete [] encoded_buffer;
}
@ -2006,13 +1992,11 @@ void cmCTestTestHandler::GenerateRegressionImages(
{
idx = 2;
}
ostr
<< "\t\t\t<NamedMeasurement"
<< " name=\"" << measurementfile.match(idx) << "\""
<< " text=\"text/string\""
<< "><Value>File " << filename
<< " not found</Value></NamedMeasurement>"
<< std::endl;
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);
}

View File

@ -18,6 +18,7 @@
#include <cmsys/RegularExpression.hxx>
class cmMakefile;
class cmXMLWriter;
/** \class cmCTestTestHandler
* \brief A class that handles ctest -S invocations
@ -164,10 +165,10 @@ protected:
virtual void GenerateTestCommand(std::vector<std::string>& args, int test);
int ExecuteCommands(std::vector<std::string>& vec);
void WriteTestResultHeader(std::ostream& os, cmCTestTestResult* result);
void WriteTestResultFooter(std::ostream& os, cmCTestTestResult* result);
void WriteTestResultHeader(cmXMLWriter& xml, cmCTestTestResult* result);
void WriteTestResultFooter(cmXMLWriter& xml, cmCTestTestResult* result);
// Write attached test files into the xml
void AttachFiles(std::ostream& os, cmCTestTestResult* result);
void AttachFiles(cmXMLWriter& xml, cmCTestTestResult* result);
//! Clean test output to specified length
bool CleanTestOutput(std::string& output, size_t length);
@ -204,7 +205,7 @@ private:
/**
* Generate the Dart compatible output
*/
virtual void GenerateDartOutput(std::ostream& os);
virtual void GenerateDartOutput(cmXMLWriter& xml);
void PrintLabelSummary();
/**
@ -270,7 +271,7 @@ private:
cmsys::RegularExpression IncludeTestsRegularExpression;
cmsys::RegularExpression ExcludeTestsRegularExpression;
void GenerateRegressionImages(std::ostream& ostr, const std::string& xml);
void GenerateRegressionImages(cmXMLWriter& xml, const std::string& dart);
cmsys::RegularExpression DartStuff1;
void CheckLabelFilter(cmCTestTestProperties& it);
void CheckLabelFilterExclude(cmCTestTestProperties& it);

View File

@ -20,7 +20,7 @@
#include "cmVersion.h"
#include "cmGeneratedFileStream.h"
#include "cmXMLParser.h"
#include "cmXMLSafe.h"
#include "cmXMLWriter.h"
#include "cmCLocaleEnvironmentScope.h"
#include "cmCTestVC.h"
@ -224,24 +224,24 @@ int cmCTestUpdateHandler::ProcessHandler()
bool updated = vc->Update();
std::string buildname = cmCTest::SafeBuildIdField(
this->CTest->GetCTestConfiguration("BuildName"));
os << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
<< "<Update mode=\"Client\" Generator=\"ctest-"
<< cmVersion::GetCMakeVersion() << "\">\n"
<< "\t<Site>" << this->CTest->GetCTestConfiguration("Site") << "</Site>\n"
<< "\t<BuildName>" << buildname
<< "</BuildName>\n"
<< "\t<BuildStamp>" << this->CTest->GetCurrentTag() << "-"
<< 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()).Quotes(false)
<< "</UpdateCommand>\n"
<< "\t<UpdateType>" << cmXMLSafe(
cmCTestUpdateHandlerUpdateToString(this->UpdateType))
<< "</UpdateType>\n";
vc->WriteXML(os);
cmXMLWriter xml(os);
xml.StartDocument();
xml.StartElement("Update");
xml.Attribute("mode", "Client");
xml.Attribute("Generator",
std::string("ctest-") + cmVersion::GetCMakeVersion());
xml.Element("Site", this->CTest->GetCTestConfiguration("Site"));
xml.Element("BuildName", buildname);
xml.Element("BuildStamp", this->CTest->GetCurrentTag() + "-" +
this->CTest->GetTestModelString());
xml.Element("StartDateTime", start_time);
xml.Element("StartTime", start_time_time);
xml.Element("UpdateCommand", vc->GetUpdateCommandLine());
xml.Element("UpdateType",
cmCTestUpdateHandlerUpdateToString(this->UpdateType));
vc->WriteXML(xml);
int localModifications = 0;
int numUpdated = vc->GetPathCount(cmCTestVC::PathUpdated);
@ -265,29 +265,30 @@ int cmCTestUpdateHandler::ProcessHandler()
cmCTestOptionalLog(this->CTest, DEBUG, "End" << std::endl, this->Quiet);
std::string end_time = this->CTest->CurrentTime();
os << "\t<EndDateTime>" << end_time << "</EndDateTime>\n"
<< "\t<EndTime>" << static_cast<unsigned int>(cmSystemTools::GetTime())
<< "</EndTime>\n"
<< "<ElapsedMinutes>" <<
static_cast<int>((cmSystemTools::GetTime() - elapsed_time_start)/6)/10.0
<< "</ElapsedMinutes>\n"
<< "\t<UpdateReturnStatus>";
xml.Element("EndDateTime", end_time);
xml.Element("EndTime", static_cast<unsigned int>(cmSystemTools::GetTime()));
xml.Element("ElapsedMinutes",
static_cast<int>((cmSystemTools::GetTime() - elapsed_time_start)/6)/10.0);
xml.StartElement("UpdateReturnStatus");
if(localModifications)
{
os << "Update error: There are modified or conflicting files in the "
"repository";
xml.Content("Update error: "
"There are modified or conflicting files in the repository");
cmCTestLog(this->CTest, ERROR_MESSAGE,
" There are modified or conflicting files in the repository"
<< std::endl);
}
if(!updated)
{
os << "Update command failed:\n" << vc->GetUpdateCommandLine();
xml.Content("Update command failed:\n");
xml.Content(vc->GetUpdateCommandLine());
cmCTestLog(this->CTest, ERROR_MESSAGE, " Update command failed: "
<< vc->GetUpdateCommandLine() << "\n");
}
os << "</UpdateReturnStatus>" << std::endl;
os << "</Update>" << std::endl;
xml.EndElement(); // UpdateReturnStatus
xml.EndElement(); // Update
xml.EndDocument();
return numUpdated;
}

View File

@ -13,7 +13,7 @@
#include "cmGeneratedFileStream.h"
#include "cmVersion.h"
#include "cmXMLSafe.h"
#include "cmXMLWriter.h"
//----------------------------------------------------------------------------
cmCTestUploadHandler::cmCTestUploadHandler()
@ -47,32 +47,36 @@ int cmCTestUploadHandler::ProcessHandler()
std::string buildname = cmCTest::SafeBuildIdField(
this->CTest->GetCTestConfiguration("BuildName"));
cmCTest::SetOfStrings::const_iterator it;
ofs << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
<< "<?xml-stylesheet type=\"text/xsl\" "
cmXMLWriter xml(ofs);
xml.StartDocument();
xml.ProcessingInstruction("xml-stylesheet", "type=\"text/xsl\" "
"href=\"Dart/Source/Server/XSL/Build.xsl "
"<file:///Dart/Source/Server/XSL/Build.xsl> \"?>\n"
<< "<Site BuildName=\""
<< buildname
<< "\" BuildStamp=\""
<< this->CTest->GetCurrentTag() << "-"
<< this->CTest->GetTestModelString() << "\" Name=\""
<< this->CTest->GetCTestConfiguration("Site") << "\" Generator=\"ctest"
<< cmVersion::GetCMakeVersion()
<< "\">\n";
this->CTest->AddSiteProperties(ofs);
ofs << "<Upload>\n";
"<file:///Dart/Source/Server/XSL/Build.xsl> \"");
xml.StartElement("Site");
xml.Attribute("BuildName", buildname);
xml.Attribute("BuildStamp",
this->CTest->GetCurrentTag() + "-" + this->CTest->GetTestModelString());
xml.Attribute("Name", this->CTest->GetCTestConfiguration("Site"));
xml.Attribute("Generator",
std::string("ctest") + cmVersion::GetCMakeVersion());
this->CTest->AddSiteProperties(xml);
xml.StartElement("Upload");
for ( it = this->Files.begin(); it != this->Files.end(); it ++ )
{
cmCTestOptionalLog(this->CTest, OUTPUT,
"\tUpload file: " << *it << std::endl, this->Quiet);
ofs << "<File filename=\"" << cmXMLSafe(*it) << "\">\n"
<< "<Content encoding=\"base64\">\n";
ofs << this->CTest->Base64EncodeFile(*it);
ofs << "\n</Content>\n"
<< "</File>\n";
xml.StartElement("File");
xml.Attribute("filename", *it);
xml.StartElement("Content");
xml.Attribute("encoding", "base64");
xml.Content(this->CTest->Base64EncodeFile(*it));
xml.EndElement(); // Content
xml.EndElement(); // File
}
ofs << "</Upload>\n"
<< "</Site>\n";
xml.EndElement(); // Upload
xml.EndElement(); // Site
xml.EndDocument();
return 0;
}

View File

@ -13,7 +13,7 @@
#include "cmCTest.h"
#include "cmSystemTools.h"
#include "cmXMLSafe.h"
#include "cmXMLWriter.h"
#include <cmsys/Process.h>
@ -202,7 +202,7 @@ bool cmCTestVC::UpdateImpl()
}
//----------------------------------------------------------------------------
bool cmCTestVC::WriteXML(std::ostream& xml)
bool cmCTestVC::WriteXML(cmXMLWriter& xml)
{
this->Log << "--- Begin Revisions ---\n";
bool result = this->WriteXMLUpdates(xml);
@ -211,7 +211,7 @@ bool cmCTestVC::WriteXML(std::ostream& xml)
}
//----------------------------------------------------------------------------
bool cmCTestVC::WriteXMLUpdates(std::ostream&)
bool cmCTestVC::WriteXMLUpdates(cmXMLWriter&)
{
cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
"* CTest cannot extract updates for this VCS tool.\n");
@ -219,7 +219,7 @@ bool cmCTestVC::WriteXMLUpdates(std::ostream&)
}
//----------------------------------------------------------------------------
void cmCTestVC::WriteXMLEntry(std::ostream& xml,
void cmCTestVC::WriteXMLEntry(cmXMLWriter& xml,
std::string const& path,
std::string const& name,
std::string const& full,
@ -228,21 +228,19 @@ void cmCTestVC::WriteXMLEntry(std::ostream& xml,
static const char* desc[3] = { "Updated", "Modified", "Conflicting"};
Revision const& rev = f.Rev? *f.Rev : this->Unknown;
std::string prior = f.PriorRev? f.PriorRev->Rev : std::string("Unknown");
xml << "\t\t<" << desc[f.Status] << ">\n"
<< "\t\t\t<File>" << cmXMLSafe(name) << "</File>\n"
<< "\t\t\t<Directory>" << cmXMLSafe(path) << "</Directory>\n"
<< "\t\t\t<FullName>" << cmXMLSafe(full) << "</FullName>\n"
<< "\t\t\t<CheckinDate>" << cmXMLSafe(rev.Date) << "</CheckinDate>\n"
<< "\t\t\t<Author>" << cmXMLSafe(rev.Author) << "</Author>\n"
<< "\t\t\t<Email>" << cmXMLSafe(rev.EMail) << "</Email>\n"
<< "\t\t\t<Committer>" << cmXMLSafe(rev.Committer) << "</Committer>\n"
<< "\t\t\t<CommitterEmail>" << cmXMLSafe(rev.CommitterEMail)
<< "</CommitterEmail>\n"
<< "\t\t\t<CommitDate>" << cmXMLSafe(rev.CommitDate)
<< "</CommitDate>\n"
<< "\t\t\t<Log>" << cmXMLSafe(rev.Log) << "</Log>\n"
<< "\t\t\t<Revision>" << cmXMLSafe(rev.Rev) << "</Revision>\n"
<< "\t\t\t<PriorRevision>" << cmXMLSafe(prior) << "</PriorRevision>\n"
<< "\t\t</" << desc[f.Status] << ">\n";
xml.StartElement(desc[f.Status]);
xml.Element("File", name);
xml.Element("Directory", path);
xml.Element("FullName", full);
xml.Element("CheckinDate", rev.Date);
xml.Element("Author", rev.Author);
xml.Element("Email", rev.EMail);
xml.Element("Committer", rev.Committer);
xml.Element("CommitterEmail", rev.CommitterEMail);
xml.Element("CommitDate", rev.CommitDate);
xml.Element("Log", rev.Log);
xml.Element("Revision", rev.Rev);
xml.Element("PriorRevision", prior);
xml.EndElement();
++this->PathCount[f.Status];
}

View File

@ -15,6 +15,7 @@
#include "cmProcessTools.h"
class cmCTest;
class cmXMLWriter;
/** \class cmCTestVC
* \brief Base class for version control system handlers
@ -51,7 +52,7 @@ public:
{ return this->UpdateCommandLine; }
/** Write Update.xml entries for the updates found. */
bool WriteXML(std::ostream& xml);
bool WriteXML(cmXMLWriter& xml);
/** Enumerate non-trivial working tree states during update. */
enum PathStatus { PathUpdated, PathModified, PathConflicting };
@ -65,7 +66,7 @@ protected:
virtual void NoteOldRevision();
virtual bool UpdateImpl();
virtual void NoteNewRevision();
virtual bool WriteXMLUpdates(std::ostream& xml);
virtual bool WriteXMLUpdates(cmXMLWriter& xml);
#if defined(__SUNPRO_CC) && __SUNPRO_CC <= 0x510
public: // Sun CC 5.1 needs help to allow cmCTestSVN::Revision to see this
@ -110,7 +111,7 @@ protected:
OutputParser* out, OutputParser* err = 0);
/** Write xml element for one file. */
void WriteXMLEntry(std::ostream& xml, std::string const& path,
void WriteXMLEntry(cmXMLWriter& xml, std::string const& path,
std::string const& name, std::string const& full,
File const& f);

View File

@ -28,6 +28,7 @@
#include "cmCTestStartCommand.h"
#include "cmAlgorithms.h"
#include "cmState.h"
#include "cmXMLWriter.h"
#include "cmCTestBuildHandler.h"
#include "cmCTestBuildAndTestHandler.h"
@ -1489,7 +1490,7 @@ std::string cmCTest::SafeBuildIdField(const std::string& value)
}
//----------------------------------------------------------------------
void cmCTest::StartXML(std::ostream& ostr, bool append)
void cmCTest::StartXML(cmXMLWriter& xml, bool append)
{
if(this->CurrentTag.empty())
{
@ -1512,42 +1513,45 @@ void cmCTest::StartXML(std::ostream& ostr, bool append)
std::string site = cmCTest::SafeBuildIdField(
this->GetCTestConfiguration("Site"));
ostr << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
<< "<Site BuildName=\"" << buildname << "\"\n"
<< "\tBuildStamp=\"" << stamp << "\"\n"
<< "\tName=\"" << site << "\"\n"
<< "\tGenerator=\"ctest-" << cmVersion::GetCMakeVersion() << "\"\n"
<< (append? "\tAppend=\"true\"\n":"")
<< "\tCompilerName=\"" << this->GetCTestConfiguration("Compiler")
<< "\"\n"
xml.StartDocument();
xml.StartElement("Site");
xml.Attribute("BuildName", buildname);
xml.BreakAttributes();
xml.Attribute("BuildStamp", stamp);
xml.Attribute("Name", site);
xml.Attribute("Generator",
std::string("ctest-") + cmVersion::GetCMakeVersion());
if(append)
{
xml.Attribute("Append", "true");
}
xml.Attribute("CompilerName", this->GetCTestConfiguration("Compiler"));
#ifdef _COMPILER_VERSION
<< "\tCompilerVersion=\"_COMPILER_VERSION\"\n"
xml.Attribute("CompilerVersion", _COMPILER_VERSION);
#endif
<< "\tOSName=\"" << info.GetOSName() << "\"\n"
<< "\tHostname=\"" << info.GetHostname() << "\"\n"
<< "\tOSRelease=\"" << info.GetOSRelease() << "\"\n"
<< "\tOSVersion=\"" << info.GetOSVersion() << "\"\n"
<< "\tOSPlatform=\"" << info.GetOSPlatform() << "\"\n"
<< "\tIs64Bits=\"" << info.Is64Bits() << "\"\n"
<< "\tVendorString=\"" << info.GetVendorString() << "\"\n"
<< "\tVendorID=\"" << info.GetVendorID() << "\"\n"
<< "\tFamilyID=\"" << info.GetFamilyID() << "\"\n"
<< "\tModelID=\"" << info.GetModelID() << "\"\n"
<< "\tProcessorCacheSize=\"" << info.GetProcessorCacheSize() << "\"\n"
<< "\tNumberOfLogicalCPU=\"" << info.GetNumberOfLogicalCPU() << "\"\n"
<< "\tNumberOfPhysicalCPU=\""<< info.GetNumberOfPhysicalCPU() << "\"\n"
<< "\tTotalVirtualMemory=\"" << info.GetTotalVirtualMemory() << "\"\n"
<< "\tTotalPhysicalMemory=\""<< info.GetTotalPhysicalMemory() << "\"\n"
<< "\tLogicalProcessorsPerPhysical=\""
<< info.GetLogicalProcessorsPerPhysical() << "\"\n"
<< "\tProcessorClockFrequency=\""
<< info.GetProcessorClockFrequency() << "\"\n"
<< ">" << std::endl;
this->AddSiteProperties(ostr);
xml.Attribute("OSName", info.GetOSName());
xml.Attribute("Hostname", info.GetHostname());
xml.Attribute("OSRelease", info.GetOSRelease());
xml.Attribute("OSVersion", info.GetOSVersion());
xml.Attribute("OSPlatform", info.GetOSPlatform());
xml.Attribute("Is64Bits", info.Is64Bits());
xml.Attribute("VendorString", info.GetVendorString());
xml.Attribute("VendorID", info.GetVendorID());
xml.Attribute("FamilyID", info.GetFamilyID());
xml.Attribute("ModelID", info.GetModelID());
xml.Attribute("ProcessorCacheSize", info.GetProcessorCacheSize());
xml.Attribute("NumberOfLogicalCPU", info.GetNumberOfLogicalCPU());
xml.Attribute("NumberOfPhysicalCPU", info.GetNumberOfPhysicalCPU());
xml.Attribute("TotalVirtualMemory", info.GetTotalVirtualMemory());
xml.Attribute("TotalPhysicalMemory", info.GetTotalPhysicalMemory());
xml.Attribute("LogicalProcessorsPerPhysical",
info.GetLogicalProcessorsPerPhysical());
xml.Attribute("ProcessorClockFrequency", info.GetProcessorClockFrequency());
this->AddSiteProperties(xml);
}
//----------------------------------------------------------------------
void cmCTest::AddSiteProperties(std::ostream& ostr)
void cmCTest::AddSiteProperties(cmXMLWriter& xml)
{
cmCTestScriptHandler* ch =
static_cast<cmCTestScriptHandler*>(this->GetHandler("script"));
@ -1563,92 +1567,95 @@ void cmCTest::AddSiteProperties(std::ostream& ostr)
->GetGlobalProperty("SubProject");
if(subproject)
{
ostr << "<Subproject name=\"" << subproject << "\">\n";
xml.StartElement("Subproject");
xml.Attribute("name", subproject);
const char* labels =
ch->GetCMake()->GetState()
->GetGlobalProperty("SubProjectLabels");
if(labels)
{
ostr << " <Labels>\n";
xml.StartElement("Labels");
std::string l = labels;
std::vector<std::string> args;
cmSystemTools::ExpandListArgument(l, args);
for(std::vector<std::string>::iterator i = args.begin();
i != args.end(); ++i)
{
ostr << " <Label>" << *i << "</Label>\n";
xml.Element("Label", *i);
}
ostr << " </Labels>\n";
xml.EndElement();
}
ostr << "</Subproject>\n";
xml.EndElement();
}
// This code should stay when cdash only does label based sub-projects
const char* label = cm->GetState()->GetGlobalProperty("Label");
if(label)
{
ostr << "<Labels>\n";
ostr << " <Label>" << label << "</Label>\n";
ostr << "</Labels>\n";
xml.StartElement("Labels");
xml.Element("Label", label);
xml.EndElement();
}
}
//----------------------------------------------------------------------
void cmCTest::EndXML(std::ostream& ostr)
void cmCTest::EndXML(cmXMLWriter& xml)
{
ostr << "</Site>" << std::endl;
xml.EndElement(); // Site
xml.EndDocument();
}
//----------------------------------------------------------------------
int cmCTest::GenerateCTestNotesOutput(std::ostream& os,
int cmCTest::GenerateCTestNotesOutput(cmXMLWriter& xml,
const cmCTest::VectorOfStrings& files)
{
std::string buildname = cmCTest::SafeBuildIdField(
this->GetCTestConfiguration("BuildName"));
cmCTest::VectorOfStrings::const_iterator it;
os << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
<< "<?xml-stylesheet type=\"text/xsl\" "
xml.StartDocument();
xml.ProcessingInstruction("xml-stylesheet", "type=\"text/xsl\" "
"href=\"Dart/Source/Server/XSL/Build.xsl "
"<file:///Dart/Source/Server/XSL/Build.xsl> \"?>\n"
<< "<Site BuildName=\"" << buildname
<< "\" BuildStamp=\""
<< this->CurrentTag << "-" << this->GetTestModelString() << "\" Name=\""
<< this->GetCTestConfiguration("Site") << "\" Generator=\"ctest"
<< cmVersion::GetCMakeVersion()
<< "\">\n";
this->AddSiteProperties(os);
os << "<Notes>" << std::endl;
"<file:///Dart/Source/Server/XSL/Build.xsl> \"");
xml.StartElement("Site");
xml.Attribute("BuildName", buildname);
xml.Attribute("BuildStamp", this->CurrentTag+"-"+this->GetTestModelString());
xml.Attribute("Name", this->GetCTestConfiguration("Site"));
xml.Attribute("Generator",std::string("ctest")+cmVersion::GetCMakeVersion());
this->AddSiteProperties(xml);
xml.StartElement("Notes");
for ( it = files.begin(); it != files.end(); it ++ )
{
cmCTestLog(this, OUTPUT, "\tAdd file: " << *it << std::endl);
std::string note_time = this->CurrentTime();
os << "<Note Name=\"" << cmXMLSafe(*it) << "\">\n"
<< "<Time>" << cmSystemTools::GetTime() << "</Time>\n"
<< "<DateTime>" << note_time << "</DateTime>\n"
<< "<Text>" << std::endl;
xml.StartElement("Note");
xml.Attribute("Name", *it);
xml.Element("Time", cmSystemTools::GetTime());
xml.Element("DateTime", note_time);
xml.StartElement("Text");
cmsys::ifstream ifs(it->c_str());
if ( ifs )
{
std::string line;
while ( cmSystemTools::GetLineFromStream(ifs, line) )
{
os << cmXMLSafe(line) << std::endl;
xml.Content(line);
xml.Content("\n");
}
ifs.close();
}
else
{
os << "Problem reading file: " << *it << std::endl;
xml.Content("Problem reading file: " + *it + "\n");
cmCTestLog(this, ERROR_MESSAGE, "Problem reading file: " << *it
<< " while creating notes" << std::endl);
}
os << "</Text>\n"
<< "</Note>" << std::endl;
xml.EndElement(); // Text
xml.EndElement(); // Note
}
os << "</Notes>\n"
<< "</Site>" << std::endl;
xml.EndElement(); // Notes
xml.EndElement(); // Site
xml.EndDocument();
return 1;
}
@ -1661,8 +1668,8 @@ int cmCTest::GenerateNotesFile(const VectorOfStrings &files)
cmCTestLog(this, ERROR_MESSAGE, "Cannot open notes file" << std::endl);
return 1;
}
this->GenerateCTestNotesOutput(ofs, files);
cmXMLWriter xml(ofs);
this->GenerateCTestNotesOutput(xml, files);
return 0;
}

View File

@ -24,6 +24,7 @@ class cmGeneratedFileStream;
class cmCTestCommand;
class cmCTestScriptHandler;
class cmCTestStartCommand;
class cmXMLWriter;
#define cmCTestLog(ctSelf, logType, msg) \
do { \
@ -273,10 +274,10 @@ public:
static std::string SafeBuildIdField(const std::string& value);
//! Start CTest XML output file
void StartXML(std::ostream& ostr, bool append);
void StartXML(cmXMLWriter& xml, bool append);
//! End CTest XML output file
void EndXML(std::ostream& ostr);
void EndXML(cmXMLWriter& xml);
//! Run command specialized for make and configure. Returns process status
// and retVal is return value or exception.
@ -420,7 +421,7 @@ public:
/** Direct process output to given streams. */
void SetStreams(std::ostream* out, std::ostream* err)
{ this->StreamOut = out; this->StreamErr = err; }
void AddSiteProperties(std::ostream& );
void AddSiteProperties(cmXMLWriter& xml);
bool GetLabelSummary() { return this->LabelSummary;}
std::string GetCostDataFile();
@ -553,7 +554,7 @@ private:
bool UpdateCTestConfiguration();
//! Create note from files.
int GenerateCTestNotesOutput(std::ostream& os,
int GenerateCTestNotesOutput(cmXMLWriter& xml,
const VectorOfStrings& files);
//! Check if the argument is the one specified

134
Source/cmXMLWriter.cxx Normal file
View File

@ -0,0 +1,134 @@
/*============================================================================
CMake - Cross Platform Makefile Generator
Copyright 2015 Daniel Pfeifer <daniel@pfeifer-mail.de>
Distributed under the OSI-approved BSD License (the "License");
see accompanying file Copyright.txt for details.
This software is distributed WITHOUT ANY WARRANTY; without even the
implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the License for more information.
============================================================================*/
#include "cmXMLWriter.h"
#include "cmXMLSafe.h"
#include <cassert>
#include <fstream>
cmXMLWriter::cmXMLWriter(std::ostream& output, std::size_t level)
: Output(output)
, Level(level)
, ElementOpen(false)
, BreakAttrib(false)
, IsContent(false)
{
}
cmXMLWriter::~cmXMLWriter()
{
assert(this->Elements.empty());
}
void cmXMLWriter::StartDocument(const char* encoding)
{
this->Output << "<?xml version=\"1.0\" encoding=\"" << encoding << "\"?>";
}
void cmXMLWriter::EndDocument()
{
assert(this->Elements.empty());
this->Output << '\n';
}
void cmXMLWriter::StartElement(std::string const& name)
{
this->CloseStartElement();
this->ConditionalLineBreak(!this->IsContent, this->Elements.size());
this->Output << '<' << name;
this->Elements.push(name);
this->ElementOpen = true;
this->BreakAttrib = false;
}
void cmXMLWriter::EndElement()
{
assert(!this->Elements.empty());
if (this->ElementOpen)
{
this->Output << "/>";
}
else
{
this->ConditionalLineBreak(!this->IsContent, this->Elements.size() - 1);
this->IsContent = false;
this->Output << "</" << this->Elements.top() << '>';
}
this->Elements.pop();
this->ElementOpen = false;
}
void cmXMLWriter::BreakAttributes()
{
this->BreakAttrib = true;
}
void cmXMLWriter::Comment(const char* comment)
{
this->CloseStartElement();
this->ConditionalLineBreak(!this->IsContent, this->Elements.size());
this->Output << "<!-- " << comment << " -->";
}
void cmXMLWriter::CData(std::string const& data)
{
this->PreContent();
this->Output << "<![CDATA[" << data << "]]>";
}
void cmXMLWriter::ProcessingInstruction(const char* target, const char* data)
{
this->CloseStartElement();
this->ConditionalLineBreak(!this->IsContent, this->Elements.size());
this->Output << "<?" << target << ' ' << data << "?>";
}
void cmXMLWriter::FragmentFile(const char* fname)
{
this->CloseStartElement();
std::ifstream fin(fname, std::ios::in | std::ios::binary);
this->Output << fin.rdbuf();
}
void cmXMLWriter::ConditionalLineBreak(bool condition, std::size_t indent)
{
if (condition)
{
this->Output << '\n' << std::string(indent + this->Level, '\t');
}
}
void cmXMLWriter::PreAttribute()
{
assert(this->ElementOpen);
this->ConditionalLineBreak(this->BreakAttrib, this->Elements.size());
if (!this->BreakAttrib)
{
this->Output << ' ';
}
}
void cmXMLWriter::PreContent()
{
this->CloseStartElement();
this->IsContent = true;
}
void cmXMLWriter::CloseStartElement()
{
if (this->ElementOpen)
{
this->ConditionalLineBreak(this->BreakAttrib, this->Elements.size());
this->Output << '>';
this->ElementOpen = false;
}
}

120
Source/cmXMLWriter.h Normal file
View File

@ -0,0 +1,120 @@
/*============================================================================
CMake - Cross Platform Makefile Generator
Copyright 2015 Daniel Pfeifer <daniel@pfeifer-mail.de>
Distributed under the OSI-approved BSD License (the "License");
see accompanying file Copyright.txt for details.
This software is distributed WITHOUT ANY WARRANTY; without even the
implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the License for more information.
============================================================================*/
#ifndef cmXMLWiter_h
#define cmXMLWiter_h
#include "cmStandardIncludes.h"
#include "cmXMLSafe.h"
#include <ostream>
#include <stack>
#include <string>
#include <vector>
class cmXMLWriter
{
public:
cmXMLWriter(std::ostream& output, std::size_t level = 0);
~cmXMLWriter();
void StartDocument(const char* encoding = "UTF-8");
void EndDocument();
void StartElement(std::string const& name);
void EndElement();
void BreakAttributes();
template <typename T>
void Attribute(const char* name, T const& value)
{
this->PreAttribute();
this->Output << name << "=\"" << SafeAttribute(value) << '"';
}
template <typename T>
void Element(std::string const& name, T const& value)
{
this->StartElement(name);
this->Content(value);
this->EndElement();
}
template <typename T>
void Content(T const& content)
{
this->PreContent();
this->Output << SafeContent(content);
}
void Comment(const char* comment);
void CData(std::string const& data);
void ProcessingInstruction(const char* target, const char* data);
void FragmentFile(const char* fname);
private:
cmXMLWriter(const cmXMLWriter&);
cmXMLWriter& operator=(const cmXMLWriter&);
void ConditionalLineBreak(bool condition, std::size_t indent);
void PreAttribute();
void PreContent();
void CloseStartElement();
private:
static cmXMLSafe SafeAttribute(const char* value)
{
return cmXMLSafe(value);
}
static cmXMLSafe SafeAttribute(std::string const& value)
{
return cmXMLSafe(value);
}
template <typename T>
static T SafeAttribute(T value)
{
return value;
}
static cmXMLSafe SafeContent(const char* value)
{
return cmXMLSafe(value).Quotes(false);
}
static cmXMLSafe SafeContent(std::string const& value)
{
return cmXMLSafe(value).Quotes(false);
}
template <typename T>
static T SafeContent(T value)
{
return value;
}
private:
std::ostream& Output;
std::stack<std::string, std::vector<std::string> > Elements;
std::size_t Level;
bool ElementOpen;
bool BreakAttrib;
bool IsContent;
};
#endif