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 }
50 
ReportSummary(int totalTestCount,int failedTestCount,int failureCount,float secondsElapsed)51 void XmlTestReporter::ReportSummary(int totalTestCount, int failedTestCount,
52                                     int failureCount, float secondsElapsed)
53 {
54     AddXmlElement(m_ostream, NULL);
55 
56     BeginResults(m_ostream, totalTestCount, failedTestCount, failureCount, secondsElapsed);
57 
58     DeferredTestResultList const& results = GetResults();
59     for (DeferredTestResultList::const_iterator i = results.begin(); i != results.end(); ++i)
60     {
61         BeginTest(m_ostream, *i);
62 
63         if (i->failed)
64             AddFailure(m_ostream, *i);
65 
66         EndTest(m_ostream, *i);
67     }
68 
69     EndResults(m_ostream);
70 }
71 
AddXmlElement(ostream & os,char const * encoding)72 void XmlTestReporter::AddXmlElement(ostream& os, char const* encoding)
73 {
74     os << "<?xml version=\"1.0\"";
75 
76     if (encoding != NULL)
77         os << " encoding=\"" << encoding << "\"";
78 
79     os << "?>";
80 }
81 
BeginResults(std::ostream & os,int totalTestCount,int failedTestCount,int failureCount,float secondsElapsed)82 void XmlTestReporter::BeginResults(std::ostream& os, int totalTestCount, int failedTestCount,
83                                    int failureCount, float secondsElapsed)
84 {
85    os << "<unittest-results"
86        << " tests=\"" << totalTestCount << "\""
87        << " failedtests=\"" << failedTestCount << "\""
88        << " failures=\"" << failureCount << "\""
89        << " time=\"" << secondsElapsed << "\""
90        << ">";
91 }
92 
EndResults(std::ostream & os)93 void XmlTestReporter::EndResults(std::ostream& os)
94 {
95     os << "</unittest-results>";
96 }
97 
BeginTest(std::ostream & os,DeferredTestResult const & result)98 void XmlTestReporter::BeginTest(std::ostream& os, DeferredTestResult const& result)
99 {
100     os << "<test"
101         << " suite=\"" << result.suiteName << "\""
102         << " name=\"" << result.testName << "\""
103         << " time=\"" << result.timeElapsed << "\"";
104 }
105 
EndTest(std::ostream & os,DeferredTestResult const & result)106 void XmlTestReporter::EndTest(std::ostream& os, DeferredTestResult const& result)
107 {
108     if (result.failed)
109         os << "</test>";
110     else
111         os << "/>";
112 }
113 
AddFailure(std::ostream & os,DeferredTestResult const & result)114 void XmlTestReporter::AddFailure(std::ostream& os, DeferredTestResult const& result)
115 {
116     os << ">"; // close <test> element
117 
118     for (DeferredTestResult::FailureVec::const_iterator it = result.failures.begin();
119          it != result.failures.end();
120          ++it)
121     {
122 		string const escapedMessage = XmlEscape(std::string(it->failureStr));
123         string const message = BuildFailureMessage(result.failureFile, it->lineNumber, escapedMessage);
124 
125         os << "<failure" << " message=\"" << message << "\"" << "/>";
126     }
127 }
128 
129 }
130 
131 #endif
132