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, '&', "&");
27 ReplaceChar(escaped, '<', "<");
28 ReplaceChar(escaped, '>', ">");
29 ReplaceChar(escaped, '\'', "'");
30 ReplaceChar(escaped, '\"', """);
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