2 #ifndef TUT_CPPUNIT_REPORTER
\r 
   3 #define TUT_CPPUNIT_REPORTER
\r 
   5 #include <tut/tut.hpp>
\r 
  16  * CppUnit TUT reporter
\r 
  18 class cppunit_reporter : public tut::callback
\r 
  20     std::vector<tut::test_result> failed_tests_;
\r 
  21     std::vector<tut::test_result> passed_tests_;
\r 
  22     const std::string filename_;
\r 
  23     std::auto_ptr<std::ostream> stream_;
\r 
  26     cppunit_reporter(const cppunit_reporter &);
\r 
  27     cppunit_reporter &operator=(const cppunit_reporter &);
\r 
  30     explicit cppunit_reporter(const std::string &filename = "testResult.xml")
\r 
  33           filename_(filename),
\r 
  34           stream_(new std::ofstream(filename_.c_str()))
\r 
  36         if (!stream_->good()) {
\r 
  37             throw tut_error("Cannot open output file `" + filename_ + "`");
\r 
  41     explicit cppunit_reporter(std::ostream &stream)
\r 
  51         if(filename_.empty())
\r 
  59         failed_tests_.clear();
\r 
  60         passed_tests_.clear();
\r 
  63     void test_completed(const tut::test_result& tr)
\r 
  65         assert(tr.result != test_result::dummy );
\r 
  66         if ( (tr.result == test_result::ok) ||
\r 
  67              (tr.result == test_result::skipped) )
\r 
  69             passed_tests_.push_back(tr);
\r 
  73             failed_tests_.push_back(tr);
\r 
  77     void run_completed()
\r 
  81         std::string failure_type;
\r 
  82         std::string failure_msg;
\r 
  84         *stream_ << "<?xml version=\"1.0\" encoding=\"utf-8\" standalone=\"yes\" ?>" << std::endl
\r 
  85                  << "<TestRun>" << std::endl;
\r 
  87         if (failed_tests_.size() > 0)
\r 
  89             *stream_ << "  <FailedTests>" << std::endl;
\r 
  91             for (unsigned int i=0; i<failed_tests_.size(); i++)
\r 
  93                 switch (failed_tests_[i].result)
\r 
  95                     case test_result::fail:
\r 
  96                         failure_type = "Assertion";
\r 
 100                     case test_result::ex:
\r 
 101                         failure_type = "Assertion";
\r 
 102                         failure_msg  = "Thrown exception: " + failed_tests_[i].exception_typeid + '\n';
\r 
 105                     case test_result::warn:
\r 
 106                         failure_type = "Assertion";
\r 
 107                         failure_msg  = "Destructor failed\n";
\r 
 110                     case test_result::term:
\r 
 111                         failure_type = "Error";
\r 
 112                         failure_msg  = "Test application terminated abnormally\n";
\r 
 115                     case test_result::ex_ctor:
\r 
 116                         failure_type = "Error";
\r 
 117                         failure_msg  = "Constructor has thrown an exception: " + failed_tests_[i].exception_typeid + '\n';
\r 
 120                     case test_result::rethrown:
\r 
 121                         failure_type = "Assertion";
\r 
 122                         failure_msg  = "Child failed\n";
\r 
 125                     default: // ok, skipped, dummy
\r 
 126                         failure_type = "Error";
\r 
 127                         failure_msg  = "Unknown test status, this should have never happened. "
\r 
 128                                        "You may just have found a bug in TUT, please report it immediately.\n";
\r 
 133                 *stream_ << "    <FailedTest id=\"" << failed_tests_[i].test << "\">" << std::endl
\r 
 134                             << "      <Name>" << encode(failed_tests_[i].group) + "::" + encode(failed_tests_[i].name) << "</Name>" << std::endl
\r 
 135                             << "      <FailureType>" << failure_type << "</FailureType>" << std::endl
\r 
 136                             << "      <Location>" << std::endl
\r 
 137                             << "        <File>Unknown</File>" << std::endl
\r 
 138                             << "        <Line>Unknown</Line>" << std::endl
\r 
 139                             << "      </Location>" << std::endl
\r 
 140                             << "      <Message>" << encode(failure_msg + failed_tests_[i].message) << "</Message>" << std::endl
\r 
 141                             << "    </FailedTest>" << std::endl;
\r 
 144             *stream_ << "  </FailedTests>" << std::endl;
\r 
 147         /* *********************** passed tests ***************************** */
\r 
 148         if (passed_tests_.size() > 0) {
\r 
 149             *stream_ << "  <SuccessfulTests>" << std::endl;
\r 
 151             for (unsigned int i=0; i<passed_tests_.size(); i++)
\r 
 153                 *stream_ << "    <Test id=\"" << passed_tests_[i].test << "\">" << std::endl
\r 
 154                             << "      <Name>" << encode(passed_tests_[i].group) + "::" + encode(passed_tests_[i].name) << "</Name>" << std::endl
\r 
 155                             << "    </Test>" << std::endl;
\r 
 158             *stream_ << "  </SuccessfulTests>" << std::endl;
\r 
 161         /* *********************** statistics ***************************** */
\r 
 162         *stream_ << "  <Statistics>" << std::endl
\r 
 163                     << "    <Tests>" << (failed_tests_.size() + passed_tests_.size()) << "</Tests>" << std::endl
\r 
 164                     << "    <FailuresTotal>" << failed_tests_.size() << "</FailuresTotal>" << std::endl
\r 
 165                     << "    <Errors>" << errors << "</Errors>" << std::endl
\r 
 166                     << "    <Failures>" << failures << "</Failures>" << std::endl
\r 
 167                     << "  </Statistics>" << std::endl;
\r 
 169         /* *********************** footer ***************************** */
\r 
 170         *stream_ << "</TestRun>" << std::endl;
\r 
 173     virtual bool all_ok() const
\r 
 175         return failed_tests_.empty();
\r 
 179      * \brief Encodes text to XML
\r 
 180      * XML-reserved characters (e.g. "<") are encoded according to specification
\r 
 181      * @param text text to be encoded
\r 
 182      * @return encoded string
\r 
 184     static std::string encode(const std::string & text)
\r 
 188         for (unsigned int i=0; i<text.length(); ++i) {
\r