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 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 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 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 46 XmlTestReporter::XmlTestReporter(ostream& ostream) 47 : m_ostream(ostream) 48 { 49 } 50 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 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 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 93 void XmlTestReporter::EndResults(std::ostream& os) 94 { 95 os << "</unittest-results>"; 96 } 97 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 106 void XmlTestReporter::EndTest(std::ostream& os, DeferredTestResult const& result) 107 { 108 if (result.failed) 109 os << "</test>"; 110 else 111 os << "/>"; 112 } 113 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