1 #include "Config.h"
2 #ifndef UNITTEST_NO_DEFERRED_REPORTER
3 
4 #include "XmlTestReporter.h"
5 
6 #include <iostream>
7 #include <sstream>
8 #include <string>
9 
10 using std::string;
11 using std::ostringstream;
12 using std::ostream;
13 
14 namespace {
15 
ReplaceChar(string & str,char c,string const & replacement)16    void ReplaceChar(string& str, char c, string const& replacement)
17    {
18       for (size_t pos = str.find(c); pos != string::npos; pos = str.find(c, pos + 1))
19          str.replace(pos, 1, replacement);
20    }
21 
XmlEscape(string const & value)22    string XmlEscape(string const& value)
23    {
24       string escaped = value;
25 
26       ReplaceChar(escaped, '&', "&amp;");
27       ReplaceChar(escaped, '<', "&lt;");
28       ReplaceChar(escaped, '>', "&gt;");
29       ReplaceChar(escaped, '\'', "&apos;");
30       ReplaceChar(escaped, '\"', "&quot;");
31 
32       return escaped;
33    }
34 
BuildFailureMessage(string const & file,int line,string const & message)35    string BuildFailureMessage(string const& file, int line, string const& message)
36    {
37       ostringstream failureMessage;
38       failureMessage << file << "(" << line << ") : " << message;
39       return failureMessage.str();
40    }
41 
42 }
43 
44 namespace UnitTest {
45 
XmlTestReporter(ostream & ostream)46    XmlTestReporter::XmlTestReporter(ostream& ostream)
47       : m_ostream(ostream)
48    {}
49 
ReportSummary(int totalTestCount,int failedTestCount,int failureCount,float secondsElapsed)50    void XmlTestReporter::ReportSummary(int totalTestCount, int failedTestCount,
51                                        int failureCount, float secondsElapsed)
52    {
53       AddXmlElement(m_ostream, NULL);
54 
55       BeginResults(m_ostream, totalTestCount, failedTestCount, failureCount, secondsElapsed);
56 
57       DeferredTestResultList const& results = GetResults();
58       for (DeferredTestResultList::const_iterator i = results.begin(); i != results.end(); ++i)
59       {
60          BeginTest(m_ostream, *i);
61 
62          if (i->failed)
63             AddFailure(m_ostream, *i);
64 
65          EndTest(m_ostream, *i);
66       }
67 
68       EndResults(m_ostream);
69    }
70 
AddXmlElement(ostream & os,char const * encoding)71    void XmlTestReporter::AddXmlElement(ostream& os, char const* encoding)
72    {
73       os << "<?xml version=\"1.0\"";
74 
75       if (encoding != NULL)
76          os << " encoding=\"" << encoding << "\"";
77 
78       os << "?>";
79    }
80 
BeginResults(std::ostream & os,int totalTestCount,int failedTestCount,int failureCount,float secondsElapsed)81    void XmlTestReporter::BeginResults(std::ostream& os, int totalTestCount, int failedTestCount,
82                                       int failureCount, float secondsElapsed)
83    {
84       os << "<unittest-results"
85          << " tests=\"" << totalTestCount << "\""
86          << " failedtests=\"" << failedTestCount << "\""
87          << " failures=\"" << failureCount << "\""
88          << " time=\"" << secondsElapsed << "\""
89          << ">";
90    }
91 
EndResults(std::ostream & os)92    void XmlTestReporter::EndResults(std::ostream& os)
93    {
94       os << "</unittest-results>";
95    }
96 
BeginTest(std::ostream & os,DeferredTestResult const & result)97    void XmlTestReporter::BeginTest(std::ostream& os, DeferredTestResult const& result)
98    {
99       os << "<test"
100          << " suite=\"" << result.suiteName << "\""
101          << " name=\"" << result.testName << "\""
102          << " time=\"" << result.timeElapsed << "\"";
103    }
104 
EndTest(std::ostream & os,DeferredTestResult const & result)105    void XmlTestReporter::EndTest(std::ostream& os, DeferredTestResult const& result)
106    {
107       if (result.failed)
108          os << "</test>";
109       else
110          os << "/>";
111    }
112 
AddFailure(std::ostream & os,DeferredTestResult const & result)113    void XmlTestReporter::AddFailure(std::ostream& os, DeferredTestResult const& result)
114    {
115       os << ">"; // close <test> element
116 
117       for (DeferredTestResult::FailureVec::const_iterator it = result.failures.begin();
118            it != result.failures.end();
119            ++it)
120       {
121          string const escapedMessage = XmlEscape(std::string(it->failureStr));
122          string const message = BuildFailureMessage(result.failureFile, it->lineNumber, escapedMessage);
123 
124          os << "<failure" << " message=\"" << message << "\"" << "/>";
125       }
126    }
127 
128 }
129 
130 #endif
131