#include "Config.h"
 
#ifndef UNITTEST_NO_DEFERRED_REPORTER
 
 
 
#include "XmlTestReporter.h"
 
 
 
#include <iostream>
 
#include <sstream>
 
#include <string>
 
 
 
using std::string;
 
using std::ostringstream;
 
using std::ostream;
 
 
 
namespace {
 
 
 
   void ReplaceChar(string& str, char c, string const& replacement)
 
   {
 
      for (size_t pos = str.find(c); pos != string::npos; pos = str.find(c, pos + 1))
 
         str.replace(pos, 1, replacement);
 
   }
 
 
 
   string XmlEscape(string const& value)
 
   {
 
      string escaped = value;
 
 
 
      ReplaceChar(escaped, '&', "&");
 
      ReplaceChar(escaped, '<', "<");
 
      ReplaceChar(escaped, '>', ">");
 
      ReplaceChar(escaped, '\'', "'");
 
      ReplaceChar(escaped, '\"', """);
 
 
 
      return escaped;
 
   }
 
 
 
   string BuildFailureMessage(string const& file, int line, string const& message)
 
   {
 
      ostringstream failureMessage;
 
      failureMessage << file << "(" << line << ") : " << message;
 
      return failureMessage.str();
 
   }
 
 
 
}
 
 
 
namespace UnitTest {
 
 
 
   XmlTestReporter::XmlTestReporter(ostream& ostream)
 
      : m_ostream(ostream)
 
   {}
 
 
 
   void XmlTestReporter::ReportSummary(int totalTestCount, int failedTestCount,
 
                                       int failureCount, float secondsElapsed)
 
   {
 
      AddXmlElement(m_ostream, NULL);
 
 
 
      BeginResults(m_ostream, totalTestCount, failedTestCount, failureCount, secondsElapsed);
 
 
 
      DeferredTestResultList const& results = GetResults();
 
      for (DeferredTestResultList::const_iterator i = results.begin(); i != results.end(); ++i)
 
      {
 
         BeginTest(m_ostream, *i);
 
 
 
         if (i->failed)
 
            AddFailure(m_ostream, *i);
 
 
 
         EndTest(m_ostream, *i);
 
      }
 
 
 
      EndResults(m_ostream);
 
   }
 
 
 
   void XmlTestReporter::AddXmlElement(ostream& os, char const* encoding)
 
   {
 
      os << "<?xml version=\"1.0\"";
 
 
 
      if (encoding != NULL)
 
         os << " encoding=\"" << encoding << "\"";
 
 
 
      os << "?>";
 
   }
 
 
 
   void XmlTestReporter::BeginResults(std::ostream& os, int totalTestCount, int failedTestCount,
 
                                      int failureCount, float secondsElapsed)
 
   {
 
      os << "<unittest-results"
 
         << " tests=\"" << totalTestCount << "\""
 
         << " failedtests=\"" << failedTestCount << "\""
 
         << " failures=\"" << failureCount << "\""
 
         << " time=\"" << secondsElapsed << "\""
 
         << ">";
 
   }
 
 
 
   void XmlTestReporter::EndResults(std::ostream& os)
 
   {
 
      os << "</unittest-results>";
 
   }
 
 
 
   void XmlTestReporter::BeginTest(std::ostream& os, DeferredTestResult const& result)
 
   {
 
      os << "<test"
 
         << " suite=\"" << result.suiteName << "\""
 
         << " name=\"" << result.testName << "\""
 
         << " time=\"" << result.timeElapsed << "\"";
 
   }
 
 
 
   void XmlTestReporter::EndTest(std::ostream& os, DeferredTestResult const& result)
 
   {
 
      if (result.failed)
 
         os << "</test>";
 
      else
 
         os << "/>";
 
   }
 
 
 
   void XmlTestReporter::AddFailure(std::ostream& os, DeferredTestResult const& result)
 
   {
 
      os << ">"; // close <test> element
 
 
 
      for (DeferredTestResult::FailureVec::const_iterator it = result.failures.begin();
 
           it != result.failures.end();
 
           ++it)
 
      {
 
         string const escapedMessage = XmlEscape(std::string(it->failureStr));
 
         string const message = BuildFailureMessage(result.failureFile, it->lineNumber, escapedMessage);
 
 
 
         os << "<failure" << " message=\"" << message << "\"" << "/>";
 
      }
 
   }
 
 
 
}
 
 
 
#endif