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 cmXMLParser.h
cmXMLSafe.cxx cmXMLSafe.cxx
cmXMLSafe.h cmXMLSafe.h
cmXMLWriter.cxx
cmXMLWriter.h
cmake.cxx cmake.cxx
cmake.h cmake.h

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -13,7 +13,7 @@
#include "cmCTest.h" #include "cmCTest.h"
#include "cmSystemTools.h" #include "cmSystemTools.h"
#include "cmXMLSafe.h" #include "cmXMLWriter.h"
#include <cmsys/RegularExpression.hxx> #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, std::string const& path,
Directory const& dir) Directory const& dir)
{ {
const char* slash = path.empty()? "":"/"; const char* slash = path.empty()? "":"/";
xml << "\t<Directory>\n" xml.StartElement("Directory");
<< "\t\t<Name>" << cmXMLSafe(path) << "</Name>\n"; xml.Element("Name", path);
for(Directory::const_iterator fi = dir.begin(); fi != dir.end(); ++fi) for(Directory::const_iterator fi = dir.begin(); fi != dir.end(); ++fi)
{ {
std::string full = path + slash + fi->first; std::string full = path + slash + fi->first;
this->WriteXMLEntry(xml, path, fi->first, full, fi->second); 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()) if(!this->NewRevision.empty())
{ {
xml << "\t<Revision>" << this->NewRevision << "</Revision>\n"; xml.Element("Revision", this->NewRevision);
} }
if(!this->OldRevision.empty() && this->OldRevision != 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, cmCTestLog(this->CTest, HANDLER_OUTPUT,
" Gathering version information (one . per revision):\n" " Gathering version information (one . per revision):\n"

View File

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

View File

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

View File

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

View File

@ -21,7 +21,7 @@
#include <cmsys/Glob.hxx> #include <cmsys/Glob.hxx>
#include <cmsys/FStream.hxx> #include <cmsys/FStream.hxx>
#include "cmMakefile.h" #include "cmMakefile.h"
#include "cmXMLSafe.h" #include "cmXMLWriter.h"
#include <stdlib.h> #include <stdlib.h>
#include <math.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() ) if ( !this->CTest->GetProduceXML() )
{ {
return; return;
} }
this->CTest->StartXML(os, this->AppendXML); this->CTest->StartXML(xml, this->AppendXML);
os << "<DynamicAnalysis Checker=\""; xml.StartElement("DynamicAnalysis");
switch ( this->MemoryTesterStyle ) switch ( this->MemoryTesterStyle )
{ {
case cmCTestMemCheckHandler::VALGRIND: case cmCTestMemCheckHandler::VALGRIND:
os << "Valgrind"; xml.Attribute("Checker", "Valgrind");
break; break;
case cmCTestMemCheckHandler::PURIFY: case cmCTestMemCheckHandler::PURIFY:
os << "Purify"; xml.Attribute("Checker", "Purify");
break; break;
case cmCTestMemCheckHandler::BOUNDS_CHECKER: case cmCTestMemCheckHandler::BOUNDS_CHECKER:
os << "BoundsChecker"; xml.Attribute("Checker", "BoundsChecker");
break; break;
case cmCTestMemCheckHandler::ADDRESS_SANITIZER: case cmCTestMemCheckHandler::ADDRESS_SANITIZER:
os << "AddressSanitizer"; xml.Attribute("Checker", "AddressSanitizer");
break; break;
case cmCTestMemCheckHandler::THREAD_SANITIZER: case cmCTestMemCheckHandler::THREAD_SANITIZER:
os << "ThreadSanitizer"; xml.Attribute("Checker", "ThreadSanitizer");
break; break;
case cmCTestMemCheckHandler::MEMORY_SANITIZER: case cmCTestMemCheckHandler::MEMORY_SANITIZER:
os << "MemorySanitizer"; xml.Attribute("Checker", "MemorySanitizer");
break; break;
case cmCTestMemCheckHandler::UB_SANITIZER: case cmCTestMemCheckHandler::UB_SANITIZER:
os << "UndefinedBehaviorSanitizer"; xml.Attribute("Checker", "UndefinedBehaviorSanitizer");
break; break;
default: default:
os << "Unknown"; xml.Attribute("Checker", "Unknown");
} }
os << "\">" << std::endl;
os << "\t<StartDateTime>" << this->StartTest << "</StartDateTime>\n" xml.Element("StartDateTime", this->StartTest);
<< "\t<StartTestTime>" << this->StartTestTime << "</StartTestTime>\n" xml.Element("StartTestTime", this->StartTestTime);
<< "\t<TestList>\n"; xml.StartElement("TestList");
cmCTestMemCheckHandler::TestResultsVector::size_type cc; cmCTestMemCheckHandler::TestResultsVector::size_type cc;
for ( cc = 0; cc < this->TestResults.size(); cc ++ ) for ( cc = 0; cc < this->TestResults.size(); cc ++ )
{ {
cmCTestTestResult *result = &this->TestResults[cc]; cmCTestTestResult *result = &this->TestResults[cc];
std::string testPath = result->Path + "/" + result->Name; std::string testPath = result->Path + "/" + result->Name;
os << "\t\t<Test>" << cmXMLSafe( xml.Element("Test", this->CTest->GetShortPathToFile(testPath.c_str()));
this->CTest->GetShortPathToFile(testPath.c_str()))
<< "</Test>" << std::endl;
} }
os << "\t</TestList>\n"; xml.EndElement(); // TestList
cmCTestOptionalLog(this->CTest, HANDLER_OUTPUT, cmCTestOptionalLog(this->CTest, HANDLER_OUTPUT,
"-- Processing memory checking output: ", this->Quiet); "-- Processing memory checking output: ", this->Quiet);
size_t total = this->TestResults.size(); size_t total = this->TestResults.size();
@ -419,37 +416,33 @@ void cmCTestMemCheckHandler::GenerateDartOutput(std::ostream& os)
} }
this->CleanTestOutput(memcheckstr, this->CleanTestOutput(memcheckstr,
static_cast<size_t>(this->CustomMaximumFailedTestOutputSize)); static_cast<size_t>(this->CustomMaximumFailedTestOutputSize));
this->WriteTestResultHeader(os, result); this->WriteTestResultHeader(xml, result);
os << "\t\t<Results>" << std::endl; xml.StartElement("Results");
for(std::vector<int>::size_type kk = 0; for(std::vector<int>::size_type kk = 0;
kk < memcheckresults.size(); ++kk) kk < memcheckresults.size(); ++kk)
{ {
if ( memcheckresults[kk] ) if ( memcheckresults[kk] )
{ {
os << "\t\t\t<Defect type=\"" << this->ResultStringsLong[kk] xml.StartElement("Defect");
<< "\">" xml.Attribute("type", this->ResultStringsLong[kk]);
<< memcheckresults[kk] xml.Content(memcheckresults[kk]);
<< "</Defect>" << std::endl; xml.EndElement(); // Defect
} }
this->GlobalResults[kk] += memcheckresults[kk]; this->GlobalResults[kk] += memcheckresults[kk];
} }
xml.EndElement(); // Results
std::string logTag; xml.StartElement("Log");
if(this->CTest->ShouldCompressMemCheckOutput()) if(this->CTest->ShouldCompressMemCheckOutput())
{ {
this->CTest->CompressString(memcheckstr); this->CTest->CompressString(memcheckstr);
logTag = "\t<Log compression=\"gzip\" encoding=\"base64\">\n"; xml.Attribute("compression", "gzip");
} xml.Attribute("encoding", "base64");
else
{
logTag = "\t<Log>\n";
} }
xml.Content(memcheckstr);
xml.EndElement(); // Log
os this->WriteTestResultFooter(xml, result);
<< "\t\t</Results>\n"
<< logTag << cmXMLSafe(memcheckstr) << std::endl
<< "\t</Log>\n";
this->WriteTestResultFooter(os, result);
if ( current < cc ) if ( current < cc )
{ {
cmCTestOptionalLog(this->CTest, HANDLER_OUTPUT, "#" << std::flush, 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, std::endl, this->Quiet);
cmCTestOptionalLog(this->CTest, HANDLER_OUTPUT, "Memory checking results:" cmCTestOptionalLog(this->CTest, HANDLER_OUTPUT, "Memory checking results:"
<< std::endl, this->Quiet); << std::endl, this->Quiet);
os << "\t<DefectList>" << std::endl; xml.StartElement("DefectList");
for ( cc = 0; cc < this->GlobalResults.size(); cc ++ ) for ( cc = 0; cc < this->GlobalResults.size(); cc ++ )
{ {
if ( this->GlobalResults[cc] ) if ( this->GlobalResults[cc] )
@ -473,21 +466,20 @@ void cmCTestMemCheckHandler::GenerateDartOutput(std::ostream& os)
cmCTestOptionalLog(this->CTest, HANDLER_OUTPUT, cmCTestOptionalLog(this->CTest, HANDLER_OUTPUT,
this->ResultStringsLong[cc] << " - " this->ResultStringsLong[cc] << " - "
<< this->GlobalResults[cc] << std::endl, this->Quiet); << this->GlobalResults[cc] << std::endl, this->Quiet);
os << "\t\t<Defect Type=\"" << this->ResultStringsLong[cc] xml.StartElement("Defect");
<< "\"/>" << std::endl; xml.Attribute("Type", this->ResultStringsLong[cc]);
xml.EndElement();
} }
} }
os << "\t</DefectList>" << std::endl; xml.EndElement(); // DefectList
os << "\t<EndDateTime>" << this->EndTest << "</EndDateTime>" << std::endl; xml.Element("EndDateTime", this->EndTest);
os << "\t<EndTestTime>" << this->EndTestTime xml.Element("EndTestTime", this->EndTestTime);
<< "</EndTestTime>" << std::endl; xml.Element("ElapsedMinutes",
os << "<ElapsedMinutes>" static_cast<int>(this->ElapsedTestingTime/6)/10.0);
<< static_cast<int>(this->ElapsedTestingTime/6)/10.0
<< "</ElapsedMinutes>\n";
os << "</DynamicAnalysis>" << std::endl; xml.EndElement(); // DynamicAnalysis
this->CTest->EndXML(os); this->CTest->EndXML(xml);
} }
//---------------------------------------------------------------------- //----------------------------------------------------------------------

View File

@ -21,6 +21,7 @@
#include <string> #include <string>
class cmMakefile; class cmMakefile;
class cmXMLWriter;
/** \class cmCTestMemCheckHandler /** \class cmCTestMemCheckHandler
* \brief A class that handles ctest -S invocations * \brief A class that handles ctest -S invocations
@ -119,7 +120,7 @@ private:
/** /**
* Generate the Dart compatible output * Generate the Dart compatible output
*/ */
void GenerateDartOutput(std::ostream& os); void GenerateDartOutput(cmXMLWriter& xml);
std::vector<std::string> CustomPreMemCheck; std::vector<std::string> CustomPreMemCheck;
std::vector<std::string> CustomPostMemCheck; std::vector<std::string> CustomPostMemCheck;

View File

@ -14,7 +14,7 @@
#include "cmCTest.h" #include "cmCTest.h"
#include "cmSystemTools.h" #include "cmSystemTools.h"
#include "cmXMLParser.h" #include "cmXMLParser.h"
#include "cmXMLSafe.h" #include "cmXMLWriter.h"
#include <cmsys/RegularExpression.hxx> #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); 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, void DoRevisionSVN(Revision const& revision,
std::vector<Change> const& changes); std::vector<Change> const& changes);
void WriteXMLGlobal(std::ostream& xml); void WriteXMLGlobal(cmXMLWriter& xml);
// Parsing helper classes. // Parsing helper classes.
class InfoParser; class InfoParser;

View File

@ -27,7 +27,7 @@
#include "cmLocalGenerator.h" #include "cmLocalGenerator.h"
#include "cmCommand.h" #include "cmCommand.h"
#include "cmSystemTools.h" #include "cmSystemTools.h"
#include "cmXMLSafe.h" #include "cmXMLWriter.h"
#include "cm_utf8.h" #include "cm_utf8.h"
#include <stdlib.h> #include <stdlib.h>
@ -633,7 +633,8 @@ int cmCTestTestHandler::ProcessHandler()
this->LogFile = 0; this->LogFile = 0;
return 1; return 1;
} }
this->GenerateDartOutput(xmlfile); cmXMLWriter xml(xmlfile);
this->GenerateDartOutput(xml);
} }
if ( ! this->PostProcessHandler() ) 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() ) if ( !this->CTest->GetProduceXML() )
{ {
return; return;
} }
this->CTest->StartXML(os, this->AppendXML); this->CTest->StartXML(xml, this->AppendXML);
os << "<Testing>\n" xml.StartElement("Testing");
<< "\t<StartDateTime>" << this->StartTest << "</StartDateTime>\n" xml.Element("StartDateTime", this->StartTest);
<< "\t<StartTestTime>" << this->StartTestTime << "</StartTestTime>\n" xml.Element("StartTestTime", this->StartTestTime);
<< "\t<TestList>\n"; xml.StartElement("TestList");
cmCTestTestHandler::TestResultsVector::size_type cc; cmCTestTestHandler::TestResultsVector::size_type cc;
for ( cc = 0; cc < this->TestResults.size(); cc ++ ) for ( cc = 0; cc < this->TestResults.size(); cc ++ )
{ {
cmCTestTestResult *result = &this->TestResults[cc]; cmCTestTestResult *result = &this->TestResults[cc];
std::string testPath = result->Path + "/" + result->Name; std::string testPath = result->Path + "/" + result->Name;
os << "\t\t<Test>" << cmXMLSafe( xml.Element("Test", this->CTest->GetShortPathToFile(testPath.c_str()));
this->CTest->GetShortPathToFile(testPath.c_str()))
<< "</Test>" << std::endl;
} }
os << "\t</TestList>\n"; xml.EndElement(); // TestList
for ( cc = 0; cc < this->TestResults.size(); cc ++ ) for ( cc = 0; cc < this->TestResults.size(); cc ++ )
{ {
cmCTestTestResult *result = &this->TestResults[cc]; cmCTestTestResult *result = &this->TestResults[cc];
this->WriteTestResultHeader(os, result); this->WriteTestResultHeader(xml, result);
os << "\t\t<Results>" << std::endl; xml.StartElement("Results");
if ( result->Status != cmCTestTestHandler::NOT_RUN ) if ( result->Status != cmCTestTestHandler::NOT_RUN )
{ {
if ( result->Status != cmCTestTestHandler::COMPLETED || if ( result->Status != cmCTestTestHandler::COMPLETED ||
result->ReturnValue ) result->ReturnValue )
{ {
os << "\t\t\t<NamedMeasurement type=\"text/string\" " xml.StartElement("NamedMeasurement");
"name=\"Exit Code\"><Value>" xml.Attribute("type", "text/string");
<< cmXMLSafe(this->GetTestStatus(result->Status)) xml.Attribute("name", "Exit Code");
<< "</Value>" xml.Element("Value", this->GetTestStatus(result->Status));
"</NamedMeasurement>\n" xml.EndElement(); // NamedMeasurement
<< "\t\t\t<NamedMeasurement type=\"text/string\" " xml.StartElement("NamedMeasurement");
"name=\"Exit Value\"><Value>" xml.Attribute("type", "text/string");
<< result->ReturnValue xml.Attribute("name", "Exit Value");
<< "</Value></NamedMeasurement>" xml.Element("Value", result->ReturnValue);
<< std::endl; xml.EndElement(); // NamedMeasurement
} }
this->GenerateRegressionImages(os, result->DartString); this->GenerateRegressionImages(xml, result->DartString);
os << "\t\t\t<NamedMeasurement type=\"numeric/double\" " xml.StartElement("NamedMeasurement");
<< "name=\"Execution Time\"><Value>" xml.Attribute("type", "numeric/double");
<< result->ExecutionTime xml.Attribute("name", "Execution Time");
<< "</Value></NamedMeasurement>\n"; xml.Element("Value", result->ExecutionTime);
xml.EndElement(); // NamedMeasurement
if(!result->Reason.empty()) if(!result->Reason.empty())
{ {
const char* reasonType = "Pass Reason"; const char* reasonType = "Pass Reason";
@ -1198,109 +1198,103 @@ void cmCTestTestHandler::GenerateDartOutput(std::ostream& os)
{ {
reasonType = "Fail Reason"; reasonType = "Fail Reason";
} }
os << "\t\t\t<NamedMeasurement type=\"text/string\" " xml.StartElement("NamedMeasurement");
<< "name=\"" << reasonType << "\"><Value>" xml.Attribute("type", "text/string");
<< cmXMLSafe(result->Reason) xml.Attribute("name", reasonType);
<< "</Value></NamedMeasurement>\n"; xml.Element("Value", result->Reason);
xml.EndElement(); // NamedMeasurement
} }
os xml.StartElement("NamedMeasurement");
<< "\t\t\t<NamedMeasurement type=\"text/string\" " xml.Attribute("type", "text/string");
<< "name=\"Completion Status\"><Value>" xml.Attribute("name", "Completion Status");
<< cmXMLSafe(result->CompletionStatus) xml.Element("Value", result->CompletionStatus);
<< "</Value></NamedMeasurement>\n"; xml.EndElement(); // NamedMeasurement
} }
os xml.StartElement("NamedMeasurement");
<< "\t\t\t<NamedMeasurement type=\"text/string\" " xml.Attribute("type", "text/string");
<< "name=\"Command Line\"><Value>" xml.Attribute("name", "Command Line");
<< cmXMLSafe(result->FullCommandLine) xml.Element("Value", result->FullCommandLine);
<< "</Value></NamedMeasurement>\n"; xml.EndElement(); // NamedMeasurement
std::map<std::string,std::string>::iterator measureIt; std::map<std::string,std::string>::iterator measureIt;
for ( measureIt = result->Properties->Measurements.begin(); for ( measureIt = result->Properties->Measurements.begin();
measureIt != result->Properties->Measurements.end(); measureIt != result->Properties->Measurements.end();
++ measureIt ) ++ measureIt )
{ {
os xml.StartElement("NamedMeasurement");
<< "\t\t\t<NamedMeasurement type=\"text/string\" " xml.Attribute("type", "text/string");
<< "name=\"" << measureIt->first << "\"><Value>" xml.Attribute("name", measureIt->first);
<< cmXMLSafe(measureIt->second) xml.Element("Value", measureIt->second);
<< "</Value></NamedMeasurement>\n"; xml.EndElement(); // NamedMeasurement
} }
os xml.StartElement("Measurement");
<< "\t\t\t<Measurement>\n" xml.StartElement("Value");
<< "\t\t\t\t<Value" if (result->CompressOutput)
<< (result->CompressOutput ? {
" encoding=\"base64\" compression=\"gzip\">" xml.Attribute("encoding", "base64");
: ">"); xml.Attribute("compression", "gzip");
os << cmXMLSafe(result->Output); }
os xml.Content(result->Output);
<< "</Value>\n" xml.EndElement(); // Value
<< "\t\t\t</Measurement>\n" xml.EndElement(); // Measurement
<< "\t\t</Results>\n"; xml.EndElement(); // Results
this->AttachFiles(os, result); this->AttachFiles(xml, result);
this->WriteTestResultFooter(os, result); this->WriteTestResultFooter(xml, result);
} }
os << "\t<EndDateTime>" << this->EndTest << "</EndDateTime>\n" xml.Element("EndDateTime", this->EndTest);
<< "\t<EndTestTime>" << this->EndTestTime << "</EndTestTime>\n" xml.Element("EndTestTime", this->EndTestTime);
<< "<ElapsedMinutes>" xml.Element("ElapsedMinutes",
<< static_cast<int>(this->ElapsedTestingTime/6)/10.0 static_cast<int>(this->ElapsedTestingTime/6)/10.0);
<< "</ElapsedMinutes>" xml.EndElement(); // Testing
<< "</Testing>" << std::endl; this->CTest->EndXML(xml);
this->CTest->EndXML(os);
} }
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
void cmCTestTestHandler::WriteTestResultHeader(std::ostream& os, void cmCTestTestHandler::WriteTestResultHeader(cmXMLWriter& xml,
cmCTestTestResult* result) cmCTestTestResult* result)
{ {
os << "\t<Test Status=\""; xml.StartElement("Test");
if ( result->Status == cmCTestTestHandler::COMPLETED ) if ( result->Status == cmCTestTestHandler::COMPLETED )
{ {
os << "passed"; xml.Attribute("Status", "passed");
} }
else if ( result->Status == cmCTestTestHandler::NOT_RUN ) else if ( result->Status == cmCTestTestHandler::NOT_RUN )
{ {
os << "notrun"; xml.Attribute("Status", "notrun");
} }
else else
{ {
os << "failed"; xml.Attribute("Status", "failed");
} }
std::string testPath = result->Path + "/" + result->Name; std::string testPath = result->Path + "/" + result->Name;
os << "\">\n" xml.Element("Name", result->Name);
<< "\t\t<Name>" << cmXMLSafe(result->Name) << "</Name>\n" xml.Element("Path", this->CTest->GetShortPathToFile(result->Path.c_str()));
<< "\t\t<Path>" << cmXMLSafe( xml.Element("FullName", this->CTest->GetShortPathToFile(testPath.c_str()));
this->CTest->GetShortPathToFile(result->Path.c_str())) << "</Path>\n" xml.Element("FullCommandLine", result->FullCommandLine);
<< "\t\t<FullName>" << cmXMLSafe(
this->CTest->GetShortPathToFile(testPath.c_str())) << "</FullName>\n"
<< "\t\t<FullCommandLine>"
<< cmXMLSafe(result->FullCommandLine)
<< "</FullCommandLine>\n";
} }
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
void cmCTestTestHandler::WriteTestResultFooter(std::ostream& os, void cmCTestTestHandler::WriteTestResultFooter(cmXMLWriter& xml,
cmCTestTestResult* result) cmCTestTestResult* result)
{ {
if(!result->Properties->Labels.empty()) if(!result->Properties->Labels.empty())
{ {
os << "\t\t<Labels>\n"; xml.StartElement("Labels");
std::vector<std::string> const& labels = result->Properties->Labels; std::vector<std::string> const& labels = result->Properties->Labels;
for(std::vector<std::string>::const_iterator li = labels.begin(); for(std::vector<std::string>::const_iterator li = labels.begin();
li != labels.end(); ++li) 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 xml.EndElement(); // Test
<< "\t</Test>" << std::endl;
} }
//---------------------------------------------------------------------- //----------------------------------------------------------------------
void cmCTestTestHandler::AttachFiles(std::ostream& os, void cmCTestTestHandler::AttachFiles(cmXMLWriter& xml,
cmCTestTestResult* result) cmCTestTestResult* result)
{ {
if(result->Status != cmCTestTestHandler::COMPLETED if(result->Status != cmCTestTestHandler::COMPLETED
@ -1317,11 +1311,14 @@ void cmCTestTestHandler::AttachFiles(std::ostream& os,
{ {
const std::string &base64 = this->CTest->Base64GzipEncodeFile(*file); const std::string &base64 = this->CTest->Base64GzipEncodeFile(*file);
std::string fname = cmSystemTools::GetFilenameName(*file); std::string fname = cmSystemTools::GetFilenameName(*file);
os << "\t\t<NamedMeasurement name=\"Attached File\" encoding=\"base64\" " xml.StartElement("NamedMeasurement");
"compression=\"tar/gzip\" filename=\"" << fname << "\" type=\"file\">" xml.Attribute("name", "Attached File");
"\n\t\t\t<Value>\n\t\t\t" xml.Attribute("encoding", "base64");
<< base64 xml.Attribute("compression", "tar/gzip");
<< "\n\t\t\t</Value>\n\t\t</NamedMeasurement>\n"; 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]" #define SPACE_REGEX "[ \t\r\n]"
//---------------------------------------------------------------------- //----------------------------------------------------------------------
void cmCTestTestHandler::GenerateRegressionImages( void cmCTestTestHandler::GenerateRegressionImages(
std::ostream& ostr, const std::string& xml) cmXMLWriter& xml, const std::string& dart)
{ {
cmsys::RegularExpression twoattributes( cmsys::RegularExpression twoattributes(
"<DartMeasurement" "<DartMeasurement"
@ -1864,69 +1861,61 @@ void cmCTestTestHandler::GenerateRegressionImages(
SPACE_REGEX "*>([^<]*)</DartMeasurementFile>"); SPACE_REGEX "*>([^<]*)</DartMeasurementFile>");
bool done = false; bool done = false;
std::string cxml = xml; std::string cxml = dart;
while ( ! done ) while ( ! done )
{ {
if ( twoattributes.find(cxml) ) if ( twoattributes.find(cxml) )
{ {
ostr xml.StartElement("NamedMeasurement");
<< "\t\t\t<NamedMeasurement" xml.Attribute(twoattributes.match(1).c_str(),
<< " " << twoattributes.match(1) << "=\"" twoattributes.match(2));
<< twoattributes.match(2) << "\"" xml.Attribute(twoattributes.match(3).c_str(),
<< " " << twoattributes.match(3) << "=\"" twoattributes.match(4));
<< twoattributes.match(4) << "\"" xml.Element("Value", twoattributes.match(5));
<< "><Value>" << twoattributes.match(5) xml.EndElement();
<< "</Value></NamedMeasurement>"
<< std::endl;
cxml.erase(twoattributes.start(), cxml.erase(twoattributes.start(),
twoattributes.end() - twoattributes.start()); twoattributes.end() - twoattributes.start());
} }
else if ( threeattributes.find(cxml) ) else if ( threeattributes.find(cxml) )
{ {
ostr xml.StartElement("NamedMeasurement");
<< "\t\t\t<NamedMeasurement" xml.Attribute(threeattributes.match(1).c_str(),
<< " " << threeattributes.match(1) << "=\"" threeattributes.match(2));
<< threeattributes.match(2) << "\"" xml.Attribute(threeattributes.match(3).c_str(),
<< " " << threeattributes.match(3) << "=\"" threeattributes.match(4));
<< threeattributes.match(4) << "\"" xml.Attribute(threeattributes.match(5).c_str(),
<< " " << threeattributes.match(5) << "=\"" threeattributes.match(6));
<< threeattributes.match(6) << "\"" xml.Element("Value", twoattributes.match(7));
<< "><Value>" << threeattributes.match(7) xml.EndElement();
<< "</Value></NamedMeasurement>"
<< std::endl;
cxml.erase(threeattributes.start(), cxml.erase(threeattributes.start(),
threeattributes.end() - threeattributes.start()); threeattributes.end() - threeattributes.start());
} }
else if ( fourattributes.find(cxml) ) else if ( fourattributes.find(cxml) )
{ {
ostr xml.StartElement("NamedMeasurement");
<< "\t\t\t<NamedMeasurement" xml.Attribute(fourattributes.match(1).c_str(),
<< " " << fourattributes.match(1) << "=\"" fourattributes.match(2));
<< fourattributes.match(2) << "\"" xml.Attribute(fourattributes.match(3).c_str(),
<< " " << fourattributes.match(3) << "=\"" fourattributes.match(4));
<< fourattributes.match(4) << "\"" xml.Attribute(fourattributes.match(5).c_str(),
<< " " << fourattributes.match(5) << "=\"" fourattributes.match(6));
<< fourattributes.match(6) << "\"" xml.Attribute(fourattributes.match(7).c_str(),
<< " " << fourattributes.match(7) << "=\"" fourattributes.match(8));
<< fourattributes.match(8) << "\"" xml.Element("Value", twoattributes.match(9));
<< "><Value>" << fourattributes.match(9) xml.EndElement();
<< "</Value></NamedMeasurement>"
<< std::endl;
cxml.erase(fourattributes.start(), cxml.erase(fourattributes.start(),
fourattributes.end() - fourattributes.start()); fourattributes.end() - fourattributes.start());
} }
else if ( cdatastart.find(cxml) && cdataend.find(cxml) ) else if ( cdatastart.find(cxml) && cdataend.find(cxml) )
{ {
ostr xml.StartElement("NamedMeasurement");
<< "\t\t\t<NamedMeasurement" xml.Attribute(cdatastart.match(1).c_str(), cdatastart.match(2));
<< " " << cdatastart.match(1) << "=\"" xml.Attribute(cdatastart.match(3).c_str(), cdatastart.match(4));
<< cdatastart.match(2) << "\"" xml.StartElement("Value");
<< " " << cdatastart.match(3) << "=\"" xml.CData(
<< cdatastart.match(4) << "\"" cxml.substr(cdatastart.end(), cdataend.start() - cdatastart.end()));
<< "><Value><![CDATA[" xml.EndElement(); // Value
<< cxml.substr(cdatastart.end(), cdataend.start() - cdatastart.end()) xml.EndElement(); // NamedMeasurement
<< "]]></Value></NamedMeasurement>"
<< std::endl;
cxml.erase(cdatastart.start(), cxml.erase(cdatastart.start(),
cdataend.end() - cdatastart.start()); cdataend.end() - cdatastart.start());
} }
@ -1952,13 +1941,12 @@ void cmCTestTestHandler::GenerateRegressionImages(
v2 = "text/string"; v2 = "text/string";
} }
ostr xml.StartElement("NamedMeasurement");
<< "\t\t\t<NamedMeasurement" xml.Attribute(k1.c_str(), v1);
<< " " << k1 << "=\"" << v1 << "\"" xml.Attribute(k2.c_str(), v2);
<< " " << k2 << "=\"" << v2 << "\"" xml.Attribute("encoding", "none");
<< " encoding=\"none\"" xml.Element("Value", "Image " + filename + " is empty");
<< "><Value>Image " << filename xml.EndElement();
<< " is empty</Value></NamedMeasurement>";
} }
else else
{ {
@ -1976,14 +1964,13 @@ void cmCTestTestHandler::GenerateRegressionImages(
size_t rlen size_t rlen
= cmsysBase64_Encode(file_buffer, len, encoded_buffer, 1); = cmsysBase64_Encode(file_buffer, len, encoded_buffer, 1);
ostr xml.StartElement("NamedMeasurement");
<< "\t\t\t<NamedMeasurement" xml.Attribute(measurementfile.match(1).c_str(),
<< " " << measurementfile.match(1) << "=\"" measurementfile.match(2));
<< measurementfile.match(2) << "\"" xml.Attribute(measurementfile.match(3).c_str(),
<< " " << measurementfile.match(3) << "=\"" measurementfile.match(4));
<< measurementfile.match(4) << "\"" xml.Attribute("encoding", "base64");
<< " encoding=\"base64\"" std::stringstream ostr;
<< ">" << std::endl << "\t\t\t\t<Value>";
for (size_t cc = 0; cc < rlen; cc ++ ) for (size_t cc = 0; cc < rlen; cc ++ )
{ {
ostr << encoded_buffer[cc]; ostr << encoded_buffer[cc];
@ -1992,9 +1979,8 @@ void cmCTestTestHandler::GenerateRegressionImages(
ostr << std::endl; ostr << std::endl;
} }
} }
ostr xml.Element("Value", ostr.str());
<< "</Value>" << std::endl << "\t\t\t</NamedMeasurement>" xml.EndElement(); // NamedMeasurement
<< std::endl;
delete [] file_buffer; delete [] file_buffer;
delete [] encoded_buffer; delete [] encoded_buffer;
} }
@ -2006,13 +1992,11 @@ void cmCTestTestHandler::GenerateRegressionImages(
{ {
idx = 2; idx = 2;
} }
ostr xml.StartElement("NamedMeasurement");
<< "\t\t\t<NamedMeasurement" xml.Attribute("name", measurementfile.match(idx));
<< " name=\"" << measurementfile.match(idx) << "\"" xml.Attribute("text", "text/string");
<< " text=\"text/string\"" xml.Element("Value", "File " + filename + " not found");
<< "><Value>File " << filename xml.EndElement();
<< " not found</Value></NamedMeasurement>"
<< std::endl;
cmCTestOptionalLog(this->CTest, HANDLER_OUTPUT, "File \"" << filename cmCTestOptionalLog(this->CTest, HANDLER_OUTPUT, "File \"" << filename
<< "\" not found." << std::endl, this->Quiet); << "\" not found." << std::endl, this->Quiet);
} }

View File

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

View File

@ -20,7 +20,7 @@
#include "cmVersion.h" #include "cmVersion.h"
#include "cmGeneratedFileStream.h" #include "cmGeneratedFileStream.h"
#include "cmXMLParser.h" #include "cmXMLParser.h"
#include "cmXMLSafe.h" #include "cmXMLWriter.h"
#include "cmCLocaleEnvironmentScope.h" #include "cmCLocaleEnvironmentScope.h"
#include "cmCTestVC.h" #include "cmCTestVC.h"
@ -224,24 +224,24 @@ int cmCTestUpdateHandler::ProcessHandler()
bool updated = vc->Update(); bool updated = vc->Update();
std::string buildname = cmCTest::SafeBuildIdField( std::string buildname = cmCTest::SafeBuildIdField(
this->CTest->GetCTestConfiguration("BuildName")); 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 localModifications = 0;
int numUpdated = vc->GetPathCount(cmCTestVC::PathUpdated); int numUpdated = vc->GetPathCount(cmCTestVC::PathUpdated);
@ -265,29 +265,30 @@ int cmCTestUpdateHandler::ProcessHandler()
cmCTestOptionalLog(this->CTest, DEBUG, "End" << std::endl, this->Quiet); cmCTestOptionalLog(this->CTest, DEBUG, "End" << std::endl, this->Quiet);
std::string end_time = this->CTest->CurrentTime(); std::string end_time = this->CTest->CurrentTime();
os << "\t<EndDateTime>" << end_time << "</EndDateTime>\n" xml.Element("EndDateTime", end_time);
<< "\t<EndTime>" << static_cast<unsigned int>(cmSystemTools::GetTime()) xml.Element("EndTime", static_cast<unsigned int>(cmSystemTools::GetTime()));
<< "</EndTime>\n" xml.Element("ElapsedMinutes",
<< "<ElapsedMinutes>" << static_cast<int>((cmSystemTools::GetTime() - elapsed_time_start)/6)/10.0);
static_cast<int>((cmSystemTools::GetTime() - elapsed_time_start)/6)/10.0
<< "</ElapsedMinutes>\n" xml.StartElement("UpdateReturnStatus");
<< "\t<UpdateReturnStatus>";
if(localModifications) if(localModifications)
{ {
os << "Update error: There are modified or conflicting files in the " xml.Content("Update error: "
"repository"; "There are modified or conflicting files in the repository");
cmCTestLog(this->CTest, ERROR_MESSAGE, cmCTestLog(this->CTest, ERROR_MESSAGE,
" There are modified or conflicting files in the repository" " There are modified or conflicting files in the repository"
<< std::endl); << std::endl);
} }
if(!updated) 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: " cmCTestLog(this->CTest, ERROR_MESSAGE, " Update command failed: "
<< vc->GetUpdateCommandLine() << "\n"); << vc->GetUpdateCommandLine() << "\n");
} }
os << "</UpdateReturnStatus>" << std::endl; xml.EndElement(); // UpdateReturnStatus
os << "</Update>" << std::endl; xml.EndElement(); // Update
xml.EndDocument();
return numUpdated; return numUpdated;
} }

View File

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

View File

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

View File

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

View File

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

View File

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