LCOV - code coverage report
Current view: top level - opt/homebrew/include/boost/test/impl - junit_log_formatter.ipp (source / functions) Hit Total Coverage
Test: test_dash_coverage.info Lines: 0 464 0.0 %
Date: 2026-06-25 07:23:51 Functions: 0 42 0.0 %

          Line data    Source code
       1             : //  (C) Copyright 2016 Raffi Enficiaud.
       2             : //  Distributed under the Boost Software License, Version 1.0.
       3             : //  (See accompanying file LICENSE_1_0.txt or copy at
       4             : //  http://www.boost.org/LICENSE_1_0.txt)
       5             : 
       6             : //  See http://www.boost.org/libs/test for the library home page.
       7             : //
       8             : ///@file
       9             : ///@brief Contains the implementatoin of the Junit log formatter (OF_JUNIT)
      10             : // ***************************************************************************
      11             : 
      12             : #ifndef BOOST_TEST_JUNIT_LOG_FORMATTER_IPP__
      13             : #define BOOST_TEST_JUNIT_LOG_FORMATTER_IPP__
      14             : 
      15             : // Boost.Test
      16             : #include <boost/test/output/junit_log_formatter.hpp>
      17             : #include <boost/test/execution_monitor.hpp>
      18             : #include <boost/test/framework.hpp>
      19             : #include <boost/test/tree/test_unit.hpp>
      20             : #include <boost/test/utils/basic_cstring/io.hpp>
      21             : #include <boost/test/utils/xml_printer.hpp>
      22             : #include <boost/test/utils/string_cast.hpp>
      23             : #include <boost/test/framework.hpp>
      24             : 
      25             : #include <boost/test/tree/visitor.hpp>
      26             : #include <boost/test/tree/traverse.hpp>
      27             : #include <boost/test/results_collector.hpp>
      28             : 
      29             : #include <boost/test/utils/algorithm.hpp>
      30             : #include <boost/test/utils/string_cast.hpp>
      31             : 
      32             : //#include <boost/test/results_reporter.hpp>
      33             : 
      34             : 
      35             : // Boost
      36             : #include <boost/version.hpp>
      37             : #include <boost/core/ignore_unused.hpp>
      38             : 
      39             : // STL
      40             : #include <iostream>
      41             : #include <fstream>
      42             : #include <set>
      43             : 
      44             : #include <boost/test/detail/suppress_warnings.hpp>
      45             : 
      46             : 
      47             : //____________________________________________________________________________//
      48             : 
      49             : namespace boost {
      50             : namespace unit_test {
      51             : namespace output {
      52             : 
      53             : 
      54             : struct s_replace_chars {
      55             :   template <class T>
      56           0 :   void operator()(T& to_replace)
      57             :   {
      58           0 :     if(to_replace == '/')
      59           0 :       to_replace = '.';
      60           0 :     else if(to_replace == ' ')
      61           0 :       to_replace = '_';
      62           0 :   }
      63             : };
      64             : 
      65           0 : inline std::string tu_name_normalize(std::string full_name)
      66             : {
      67             :   // maybe directly using normalize_test_case_name instead?
      68           0 :   std::for_each(full_name.begin(), full_name.end(), s_replace_chars());
      69           0 :   return full_name;
      70             : }
      71             : 
      72           0 : inline std::string tu_name_remove_newlines(std::string full_name)
      73             : {
      74           0 :   full_name.erase(std::remove(full_name.begin(), full_name.end(), '\n'), full_name.end());
      75           0 :   return full_name;
      76             : }
      77             : 
      78           0 : const_string file_basename(const_string filename) {
      79             : 
      80           0 :     const_string path_sep( "\\/" );
      81           0 :     const_string::iterator it = unit_test::utils::find_last_of( filename.begin(), filename.end(),
      82           0 :                                                                 path_sep.begin(), path_sep.end() );
      83           0 :     if( it != filename.end() )
      84           0 :         filename.trim_left( it + 1 );
      85             : 
      86           0 :     return filename;
      87             : 
      88             : }
      89             : 
      90             : // ************************************************************************** //
      91             : // **************               junit_log_formatter              ************** //
      92             : // ************************************************************************** //
      93             : 
      94             : void
      95           0 : junit_log_formatter::log_start( std::ostream& /*ostr*/, counter_t /*test_cases_amount*/)
      96             : {
      97           0 :     map_tests.clear();
      98           0 :     list_path_to_root.clear();
      99           0 :     runner_log_entry.clear();
     100           0 : }
     101             : 
     102             : //____________________________________________________________________________//
     103             : 
     104             : class junit_result_helper : public test_tree_visitor {
     105             : private:
     106             :     typedef junit_impl::junit_log_helper::assertion_entry assertion_entry;
     107             :     typedef std::vector< assertion_entry >::const_iterator vect_assertion_entry_citerator;
     108             :     typedef std::list<std::string>::const_iterator list_str_citerator;
     109             : 
     110             : public:
     111           0 :     explicit junit_result_helper(
     112             :         std::ostream& stream,
     113             :         test_unit const& ts,
     114             :         junit_log_formatter::map_trace_t const& mt,
     115             :         junit_impl::junit_log_helper const& runner_log_,
     116             :         bool display_build_info )
     117           0 :     : m_stream(stream)
     118           0 :     , m_ts( ts )
     119           0 :     , m_map_test( mt )
     120           0 :     , runner_log( runner_log_ )
     121           0 :     , m_id( 0 )
     122           0 :     , m_display_build_info(display_build_info)
     123           0 :     { }
     124             : 
     125           0 :     void add_log_entry(assertion_entry const& log) const
     126             :     {
     127           0 :         std::string entry_type;
     128           0 :         if( log.log_entry == assertion_entry::log_entry_failure ) {
     129           0 :             entry_type = "failure";
     130           0 :         }
     131           0 :         else if( log.log_entry == assertion_entry::log_entry_error ) {
     132           0 :             entry_type = "error";
     133           0 :         }
     134             :         else {
     135           0 :             return;
     136             :         }
     137             : 
     138           0 :         m_stream
     139           0 :             << "<" << entry_type
     140           0 :             << " message" << utils::attr_value() << log.logentry_message
     141           0 :             << " type" << utils::attr_value() << log.logentry_type
     142           0 :             << ">";
     143             : 
     144           0 :         if(!log.output.empty()) {
     145           0 :             m_stream << utils::cdata() << "\n" + log.output;
     146           0 :         }
     147             : 
     148           0 :         m_stream << "</" << entry_type << ">";
     149           0 :     }
     150             : 
     151             :     struct conditional_cdata_helper {
     152             :         std::ostream &ostr;
     153             :         std::string const field;
     154             :         bool empty;
     155             : 
     156           0 :         conditional_cdata_helper(std::ostream &ostr_, std::string field_)
     157           0 :         : ostr(ostr_)
     158           0 :         , field(field_)
     159           0 :         , empty(true)
     160           0 :         {}
     161             : 
     162           0 :         ~conditional_cdata_helper() {
     163           0 :             if(!empty) {
     164           0 :                 ostr << BOOST_TEST_L( "]]>" ) << "</" << field << '>' << std::endl;
     165           0 :             }
     166           0 :         }
     167             : 
     168           0 :         void operator()(const std::string& s) {
     169           0 :             bool current_empty = s.empty();
     170           0 :             if(empty) {
     171           0 :                 if(!current_empty) {
     172           0 :                     empty = false;
     173           0 :                     ostr << '<' << field << '>' << BOOST_TEST_L( "<![CDATA[" );
     174           0 :                 }
     175           0 :             }
     176           0 :             if(!current_empty) {
     177           0 :                 ostr << s;
     178           0 :             }
     179           0 :         }
     180             :     };
     181             : 
     182           0 :     std::list<std::string> build_skipping_chain(test_unit const & tu) const
     183             :     {
     184             :         // we enter here because we know that the tu has been skipped.
     185             :         // either junit has not seen this tu, or it is indicated as disabled
     186           0 :         assert(m_map_test.count(tu.p_id) == 0 || results_collector.results( tu.p_id ).p_skipped);
     187             : 
     188           0 :         std::list<std::string> out;
     189             : 
     190           0 :         test_unit_id id(tu.p_id);
     191           0 :         while( id != m_ts.p_id && id != INV_TEST_UNIT_ID) {
     192           0 :             test_unit const& tu_hierarchy = boost::unit_test::framework::get( id, TUT_ANY );
     193           0 :             out.push_back("- disabled test unit: '" + tu_name_remove_newlines(tu_hierarchy.full_name()) + "'\n");
     194           0 :             if(m_map_test.count(id) > 0)
     195             :             {
     196             :                 // junit has seen the reason: this is enough for constructing the chain
     197           0 :                 break;
     198             :             }
     199           0 :             id = tu_hierarchy.p_parent_id;
     200             :         }
     201           0 :         junit_log_formatter::map_trace_t::const_iterator it_element_stack(m_map_test.find(id));
     202           0 :         if( it_element_stack != m_map_test.end() )
     203             :         {
     204           0 :             out.push_back("- reason: '" + it_element_stack->second.skipping_reason + "'");
     205           0 :             out.push_front("Test case disabled because of the following chain of decision:\n");
     206           0 :         }
     207             : 
     208           0 :         return out;
     209           0 :     }
     210             : 
     211           0 :     std::string get_class_name(test_unit const & tu_class) const {
     212           0 :         std::string classname;
     213           0 :         test_unit_id id(tu_class.p_parent_id);
     214           0 :         while( id != m_ts.p_id && id != INV_TEST_UNIT_ID ) {
     215           0 :             test_unit const& tu = boost::unit_test::framework::get( id, TUT_ANY );
     216           0 :             classname = tu_name_normalize(tu.p_name) + "." + classname;
     217           0 :             id = tu.p_parent_id;
     218             :         }
     219             : 
     220             :         // removes the trailing dot
     221           0 :         if(!classname.empty() && *classname.rbegin() == '.') {
     222           0 :             classname.erase(classname.size()-1);
     223           0 :         }
     224             : 
     225           0 :         return classname;
     226           0 :     }
     227             : 
     228           0 :     void    write_testcase_header(test_unit const & tu,
     229             :                                   test_results const *tr,
     230             :                                   int nb_assertions) const
     231             :     {
     232           0 :         std::string name;
     233           0 :         std::string classname;
     234             : 
     235           0 :         if(tu.p_id == m_ts.p_id ) {
     236           0 :             name = "boost_test";
     237           0 :         }
     238             :         else {
     239           0 :             classname = get_class_name(tu);
     240           0 :             name = tu_name_normalize(tu.p_name);
     241             :         }
     242             : 
     243           0 :         if( tu.p_type == TUT_SUITE ) {
     244           0 :             if(tr->p_timed_out)
     245           0 :               name += "-timed-execution";
     246             :             else
     247           0 :               name += "-setup-teardown";
     248           0 :         }
     249             : 
     250           0 :         m_stream << "<testcase assertions" << utils::attr_value() << nb_assertions;
     251           0 :         if(!classname.empty())
     252           0 :             m_stream << " classname" << utils::attr_value() << classname;
     253             : 
     254             :         // test case name and time taken
     255           0 :         m_stream
     256           0 :             << " name"      << utils::attr_value() << name
     257           0 :             << " time"      << utils::attr_value() << double(tr->p_duration_microseconds) * 1E-6
     258           0 :             << ">" << std::endl;
     259           0 :     }
     260             : 
     261           0 :     void    write_testcase_system_out(junit_impl::junit_log_helper const &detailed_log,
     262             :                                       test_unit const * tu,
     263             :                                       bool skipped) const
     264             :     {
     265             :         // system-out + all info/messages, the object skips the empty entries
     266           0 :         conditional_cdata_helper system_out_helper(m_stream, "system-out");
     267             : 
     268             :         // indicate why the test has been skipped first
     269           0 :         if( skipped ) {
     270           0 :             std::list<std::string> skipping_decision_chain = build_skipping_chain(*tu);
     271           0 :             for(list_str_citerator it(skipping_decision_chain.begin()), ite(skipping_decision_chain.end());
     272           0 :                 it != ite;
     273           0 :                 ++it)
     274             :             {
     275           0 :               system_out_helper(*it);
     276           0 :             }
     277           0 :         }
     278             : 
     279             :         // stdout
     280           0 :         for(list_str_citerator it(detailed_log.system_out.begin()), ite(detailed_log.system_out.end());
     281           0 :             it != ite;
     282           0 :             ++it)
     283             :         {
     284           0 :           system_out_helper(*it);
     285           0 :         }
     286             : 
     287             :         // warning/info message last
     288           0 :         for(vect_assertion_entry_citerator it(detailed_log.assertion_entries.begin());
     289           0 :             it != detailed_log.assertion_entries.end();
     290           0 :             ++it)
     291             :         {
     292           0 :             if(it->log_entry != assertion_entry::log_entry_info)
     293           0 :                 continue;
     294           0 :             system_out_helper(it->output);
     295           0 :         }
     296           0 :     }
     297             : 
     298           0 :     void    write_testcase_system_err(junit_impl::junit_log_helper const &detailed_log,
     299             :                                       test_unit const * tu,
     300             :                                       test_results const *tr) const
     301             :     {
     302             :         // system-err output + test case informations
     303           0 :         bool has_failed = (tr != 0) ? !tr->p_skipped && !tr->passed() : false;
     304           0 :         if(!detailed_log.system_err.empty() || has_failed)
     305             :         {
     306           0 :             std::ostringstream o;
     307           0 :             if(has_failed) {
     308           0 :                 o << "Failures detected in:" << std::endl;
     309           0 :             }
     310             :             else {
     311           0 :                 o << "ERROR STREAM:" << std::endl;
     312             :             }
     313             : 
     314           0 :             if(tu->p_type == TUT_SUITE) {
     315           0 :                 if( tu->p_id == m_ts.p_id ) {
     316           0 :                     o << " boost.test global setup/teardown" << std::endl;
     317           0 :                 } else {
     318           0 :                     o << "- test suite: " << tu_name_remove_newlines(tu->full_name()) << std::endl;
     319             :                 }
     320           0 :             }
     321             :             else {
     322           0 :               o << "- test case: " << tu_name_remove_newlines(tu->full_name());
     323           0 :               if(!tu->p_description.value.empty())
     324           0 :                   o << " '" << tu->p_description << "'";
     325             : 
     326           0 :               o << std::endl
     327           0 :                   << "- file: " << file_basename(tu->p_file_name) << std::endl
     328           0 :                   << "- line: " << tu->p_line_num << std::endl
     329             :                   ;
     330             :             }
     331             : 
     332           0 :             if(!detailed_log.system_err.empty())
     333           0 :                 o << std::endl << "STDERR BEGIN: ------------" << std::endl;
     334             : 
     335           0 :             for(list_str_citerator it(detailed_log.system_err.begin()), ite(detailed_log.system_err.end());
     336           0 :                 it != ite;
     337           0 :                 ++it)
     338             :             {
     339           0 :               o << *it;
     340           0 :             }
     341             : 
     342           0 :             if(!detailed_log.system_err.empty())
     343           0 :                 o << std::endl << "STDERR END    ------------" << std::endl;
     344             : 
     345           0 :             conditional_cdata_helper system_err_helper(m_stream, "system-err");
     346           0 :             system_err_helper(o.str());
     347           0 :         }
     348           0 :     }
     349             : 
     350           0 :     int     get_nb_assertions(junit_impl::junit_log_helper const &detailed_log,
     351             :                               test_unit const & tu,
     352             :                               test_results const *tr) const {
     353           0 :         int nb_assertions(-1);
     354           0 :         if( tu.p_type == TUT_SUITE ) {
     355           0 :             nb_assertions = 0;
     356           0 :             for(vect_assertion_entry_citerator it(detailed_log.assertion_entries.begin());
     357           0 :                 it != detailed_log.assertion_entries.end();
     358           0 :                 ++it)
     359             :             {
     360           0 :                 if(it->log_entry != assertion_entry::log_entry_info)
     361           0 :                     nb_assertions++;
     362           0 :             }
     363           0 :         }
     364             :         else {
     365           0 :             nb_assertions = static_cast<int>(tr->p_assertions_passed + tr->p_assertions_failed);
     366             :         }
     367             : 
     368           0 :         return nb_assertions;
     369             :     }
     370             : 
     371           0 :     void    output_detailed_logs(junit_impl::junit_log_helper const &detailed_log,
     372             :                                  test_unit const & tu,
     373             :                                  bool skipped,
     374             :                                  test_results const *tr) const
     375             :     {
     376           0 :         int nb_assertions = get_nb_assertions(detailed_log, tu, tr);
     377           0 :         if(!nb_assertions && tu.p_type == TUT_SUITE)
     378           0 :             return;
     379             : 
     380           0 :         write_testcase_header(tu, tr, nb_assertions);
     381             : 
     382           0 :         if( skipped ) {
     383           0 :             m_stream << "<skipped/>" << std::endl;
     384           0 :         }
     385             :         else {
     386             : 
     387           0 :           for(vect_assertion_entry_citerator it(detailed_log.assertion_entries.begin());
     388           0 :               it != detailed_log.assertion_entries.end();
     389           0 :               ++it)
     390             :           {
     391           0 :               add_log_entry(*it);
     392           0 :           }
     393             :         }
     394             : 
     395           0 :         write_testcase_system_out(detailed_log, &tu, skipped);
     396           0 :         write_testcase_system_err(detailed_log, &tu, tr);
     397           0 :         m_stream << "</testcase>" << std::endl;
     398           0 :     }
     399             : 
     400           0 :     void    visit( test_case const& tc ) BOOST_OVERRIDE
     401             :     {
     402             : 
     403           0 :         test_results const& tr = results_collector.results( tc.p_id );
     404           0 :         junit_log_formatter::map_trace_t::const_iterator it_find = m_map_test.find(tc.p_id);
     405           0 :         if(it_find == m_map_test.end())
     406             :         {
     407             :             // test has been skipped and not seen by the logger
     408           0 :             output_detailed_logs(junit_impl::junit_log_helper(), tc, true, &tr);
     409           0 :         }
     410             :         else {
     411           0 :             output_detailed_logs(it_find->second, tc, tr.p_skipped, &tr);
     412             :         }
     413           0 :     }
     414             : 
     415           0 :     bool    test_suite_start( test_suite const& ts ) BOOST_OVERRIDE
     416             :     {
     417           0 :         test_results const& tr = results_collector.results( ts.p_id );
     418             : 
     419             :         // unique test suite, without s, nesting not supported in CI
     420           0 :         if( m_ts.p_id == ts.p_id ) {
     421           0 :             m_stream << "<testsuite";
     422             : 
     423             :             // think about: maybe we should add the number of fixtures of a test_suite as
     424             :             // independent tests (field p_fixtures).
     425             :             // same goes for the timed-execution: we can think of that as a separate test-unit
     426             :             // in the suite.
     427             :             // see https://llg.cubic.org/docs/junit/ and
     428             :             // http://svn.apache.org/viewvc/ant/core/trunk/src/main/org/apache/tools/ant/taskdefs/optional/junit/XMLJUnitResultFormatter.java?view=markup
     429           0 :             m_stream
     430             :               // << "disabled=\"" << tr.p_test_cases_skipped << "\" "
     431           0 :               << " tests"     << utils::attr_value()
     432           0 :                   << tr.p_test_cases_passed
     433           0 :                      + tr.p_test_cases_failed
     434             :                      // + tr.p_test_cases_aborted // aborted is also failed, we avoid counting it twice
     435           0 :               << " skipped"   << utils::attr_value() << tr.p_test_cases_skipped
     436           0 :               << " errors"    << utils::attr_value() << tr.p_test_cases_aborted
     437           0 :               << " failures"  << utils::attr_value()
     438           0 :                   << tr.p_test_cases_failed
     439           0 :                      + tr.p_test_suites_timed_out
     440           0 :                      + tr.p_test_cases_timed_out
     441           0 :                      - tr.p_test_cases_aborted // failed is not aborted in the Junit sense
     442           0 :               << " id"        << utils::attr_value() << m_id++
     443           0 :               << " name"      << utils::attr_value() << tu_name_normalize(ts.p_name)
     444           0 :               << " time"      << utils::attr_value() << (tr.p_duration_microseconds * 1E-6)
     445           0 :               << ">" << std::endl;
     446             : 
     447           0 :             if(m_display_build_info)
     448             :             {
     449           0 :                 m_stream  << "<properties>" << std::endl;
     450           0 :                 m_stream  << "<property name=\"platform\" value" << utils::attr_value() << BOOST_PLATFORM << " />" << std::endl;
     451           0 :                 m_stream  << "<property name=\"compiler\" value" << utils::attr_value() << BOOST_COMPILER << " />" << std::endl;
     452           0 :                 m_stream  << "<property name=\"stl\" value" << utils::attr_value() << BOOST_STDLIB << " />" << std::endl;
     453             : 
     454           0 :                 std::ostringstream o;
     455           0 :                 o << BOOST_VERSION/100000 << "." << BOOST_VERSION/100 % 1000 << "." << BOOST_VERSION % 100;
     456           0 :                 m_stream  << "<property name=\"boost\" value" << utils::attr_value() << o.str() << " />" << std::endl;
     457           0 :                 m_stream  << "</properties>" << std::endl;
     458           0 :             }
     459           0 :         }
     460             : 
     461           0 :         if( !tr.p_skipped ) {
     462             :             // if we land here, then this is a chance that we are logging the fixture setup/teardown of a test-suite.
     463             :             // the setup/teardown logging of a test-case is part of the test case.
     464             :             // we do not care about the test-suite that were skipped (really??)
     465           0 :             junit_log_formatter::map_trace_t::const_iterator it_find = m_map_test.find(ts.p_id);
     466           0 :             if(it_find != m_map_test.end()) {
     467           0 :                 output_detailed_logs(it_find->second, ts, false, &tr);
     468           0 :             }
     469           0 :         }
     470             : 
     471           0 :         return true; // indicates that the children should also be parsed
     472           0 :     }
     473             : 
     474           0 :     void    test_suite_finish( test_suite const& ts ) BOOST_OVERRIDE
     475             :     {
     476           0 :         if( m_ts.p_id == ts.p_id ) {
     477           0 :             write_testcase_system_out(runner_log, 0, false);
     478           0 :             write_testcase_system_err(runner_log, 0, 0);
     479             : 
     480           0 :             m_stream << "</testsuite>";
     481           0 :             return;
     482             :         }
     483           0 :     }
     484             : 
     485             : private:
     486             :     // Data members
     487             :     std::ostream& m_stream;
     488             :     test_unit const& m_ts;
     489             :     junit_log_formatter::map_trace_t const& m_map_test;
     490             :     junit_impl::junit_log_helper const& runner_log;
     491             :     size_t m_id;
     492             :     bool m_display_build_info;
     493             : };
     494             : 
     495             : 
     496             : 
     497             : void
     498           0 : junit_log_formatter::log_finish( std::ostream& ostr )
     499             : {
     500           0 :     ostr << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" << std::endl;
     501             : 
     502             :     // getting the root test suite
     503           0 :     if(!map_tests.empty()) {
     504           0 :         test_unit* root = &boost::unit_test::framework::get( map_tests.begin()->first, TUT_ANY );
     505             : 
     506             :         // looking for the root of the SUBtree (we stay in the subtree)
     507           0 :         while(root->p_parent_id != INV_TEST_UNIT_ID && map_tests.count(root->p_parent_id) > 0) {
     508           0 :             root = &boost::unit_test::framework::get( root->p_parent_id, TUT_ANY );
     509             :         }
     510           0 :         junit_result_helper ch( ostr, *root, map_tests, this->runner_log_entry, m_display_build_info );
     511           0 :         traverse_test_tree( root->p_id, ch, true ); // last is to ignore disabled suite special handling
     512           0 :     }
     513             :     else {
     514           0 :         ostr << "<testsuites errors=\"1\">";
     515           0 :         ostr << "<testsuite errors=\"1\" name=\"boost-test-framework\">";
     516           0 :         ostr << "<testcase assertions=\"1\" name=\"test-setup\">";
     517           0 :         ostr << "<system-out>Incorrect setup: no test case executed</system-out>";
     518           0 :         ostr << "</testcase></testsuite></testsuites>";
     519             :     }
     520           0 :     return;
     521           0 : }
     522             : 
     523             : //____________________________________________________________________________//
     524             : 
     525             : void
     526           0 : junit_log_formatter::log_build_info( std::ostream& /*ostr*/, bool log_build_info )
     527             : {
     528           0 :     m_display_build_info = log_build_info;
     529           0 : }
     530             : 
     531             : //____________________________________________________________________________//
     532             : 
     533             : void
     534           0 : junit_log_formatter::test_unit_start( std::ostream& /*ostr*/, test_unit const& tu )
     535             : {
     536           0 :     list_path_to_root.push_back( tu.p_id );
     537           0 :     map_tests.insert(std::make_pair(tu.p_id, junit_impl::junit_log_helper())); // current_test_case_id not working here
     538           0 : }
     539             : 
     540             : 
     541             : 
     542             : //____________________________________________________________________________//
     543             : 
     544             : 
     545             : void
     546           0 : junit_log_formatter::test_unit_finish( std::ostream& /*ostr*/, test_unit const& tu, unsigned long /*elapsed*/ )
     547             : {
     548             :     // the time is already stored in the result_reporter
     549           0 :     boost::ignore_unused( tu );
     550           0 :     assert( tu.p_id == list_path_to_root.back() );
     551           0 :     list_path_to_root.pop_back();
     552           0 : }
     553             : 
     554             : void
     555           0 : junit_log_formatter::test_unit_aborted( std::ostream& /*ostr*/, test_unit const& tu )
     556             : {
     557           0 :     boost::ignore_unused( tu );
     558           0 :     assert( tu.p_id == list_path_to_root.back() );
     559             :     //list_path_to_root.pop_back();
     560           0 : }
     561             : 
     562             : //____________________________________________________________________________//
     563             : 
     564             : void
     565           0 : junit_log_formatter::test_unit_timed_out( std::ostream& /*os*/, test_unit const& tu)
     566             : {
     567           0 :     if(tu.p_type == TUT_SUITE)
     568             :     {
     569             :         // if we reach this call, it means that the test has already started and
     570             :         // test_unit_start has already been called on the tu.
     571           0 :         junit_impl::junit_log_helper& last_entry = get_current_log_entry();
     572           0 :         junit_impl::junit_log_helper::assertion_entry entry;
     573           0 :         entry.logentry_message = "test-suite time out";
     574           0 :         entry.logentry_type = "execution timeout";
     575           0 :         entry.log_entry = junit_impl::junit_log_helper::assertion_entry::log_entry_error;
     576           0 :         entry.output = "the current suite exceeded the allocated execution time";
     577           0 :         last_entry.assertion_entries.push_back(entry);
     578           0 :     }
     579           0 : }
     580             : 
     581             : //____________________________________________________________________________//
     582             : 
     583             : void
     584           0 : junit_log_formatter::test_unit_skipped( std::ostream& /*ostr*/, test_unit const& tu, const_string reason )
     585             : {
     586             :     // if a test unit is skipped, then the start of this TU has not been called yet.
     587             :     // we cannot use get_current_log_entry here, but the TU id should appear in the map.
     588             :     // The "skip" boolean is given by the boost.test framework
     589           0 :     junit_impl::junit_log_helper& v = map_tests[tu.p_id]; // not sure if we can use get_current_log_entry()
     590           0 :     v.skipping_reason.assign(reason.begin(), reason.end());
     591           0 : }
     592             : 
     593             : //____________________________________________________________________________//
     594             : 
     595             : void
     596           0 : junit_log_formatter::log_exception_start( std::ostream& /*ostr*/, log_checkpoint_data const& checkpoint_data, execution_exception const& ex )
     597             : {
     598           0 :     std::ostringstream o;
     599           0 :     execution_exception::location const& loc = ex.where();
     600             : 
     601           0 :     m_is_last_assertion_or_error = false;
     602             : 
     603           0 :     junit_impl::junit_log_helper& last_entry = get_current_log_entry();
     604             : 
     605           0 :     junit_impl::junit_log_helper::assertion_entry entry;
     606             : 
     607           0 :     entry.logentry_message = "unexpected exception";
     608           0 :     entry.log_entry = junit_impl::junit_log_helper::assertion_entry::log_entry_error;
     609             : 
     610           0 :     switch(ex.code())
     611             :     {
     612             :     case execution_exception::cpp_exception_error:
     613           0 :         entry.logentry_type = "uncaught exception";
     614           0 :         break;
     615             :     case execution_exception::timeout_error:
     616           0 :         entry.logentry_type = "execution timeout";
     617           0 :         break;
     618             :     case execution_exception::user_error:
     619           0 :         entry.logentry_type = "user, assert() or CRT error";
     620           0 :         break;
     621             :     case execution_exception::user_fatal_error:
     622             :         // Looks like never used
     623           0 :         entry.logentry_type = "user fatal error";
     624           0 :         break;
     625             :     case execution_exception::system_error:
     626           0 :         entry.logentry_type = "system error";
     627           0 :         break;
     628             :     case execution_exception::system_fatal_error:
     629           0 :         entry.logentry_type = "system fatal error";
     630           0 :         break;
     631             :     default:
     632           0 :         entry.logentry_type = "no error"; // not sure how to handle this one
     633           0 :         break;
     634             :     }
     635             : 
     636           0 :     o << "UNCAUGHT EXCEPTION:" << std::endl;
     637           0 :     if( !loc.m_function.is_empty() )
     638           0 :         o << "- function: \""   << loc.m_function << "\"" << std::endl;
     639             : 
     640           0 :     o << "- file: " << file_basename(loc.m_file_name) << std::endl
     641           0 :       << "- line: " << loc.m_line_num << std::endl
     642           0 :       << std::endl;
     643             : 
     644           0 :     o << "\nEXCEPTION STACK TRACE: --------------\n" << ex.what()
     645           0 :       << "\n-------------------------------------";
     646             : 
     647           0 :     if( !checkpoint_data.m_file_name.is_empty() ) {
     648           0 :         o << std::endl << std::endl
     649           0 :           << "Last checkpoint:" << std::endl
     650           0 :           << "- message: \"" << checkpoint_data.m_message << "\"" << std::endl
     651           0 :           << "- file: " << file_basename(checkpoint_data.m_file_name) << std::endl
     652           0 :           << "- line: " << checkpoint_data.m_line_num << std::endl
     653             :         ;
     654           0 :     }
     655             : 
     656           0 :     entry.output = o.str();
     657             : 
     658           0 :     last_entry.assertion_entries.push_back(entry);
     659           0 : }
     660             : 
     661             : //____________________________________________________________________________//
     662             : 
     663             : void
     664           0 : junit_log_formatter::log_exception_finish( std::ostream& /*ostr*/ )
     665             : {
     666             :     // sealing the last entry
     667           0 :     assert(!get_current_log_entry().assertion_entries.back().sealed);
     668           0 :     get_current_log_entry().assertion_entries.back().sealed = true;
     669           0 : }
     670             : 
     671             : //____________________________________________________________________________//
     672             : 
     673             : void
     674           0 : junit_log_formatter::log_entry_start( std::ostream& /*ostr*/, log_entry_data const& entry_data, log_entry_types let )
     675             : {
     676           0 :     junit_impl::junit_log_helper& last_entry = get_current_log_entry();
     677           0 :     last_entry.skipping = false;
     678           0 :     m_is_last_assertion_or_error = true;
     679           0 :     switch(let)
     680             :     {
     681             :       case unit_test_log_formatter::BOOST_UTL_ET_INFO:
     682             :       {
     683           0 :         if(m_log_level_internal > log_successful_tests) {
     684           0 :           last_entry.skipping = true;
     685           0 :           break;
     686             :         }
     687             :         BOOST_FALLTHROUGH;
     688           0 :       }
     689             :       case unit_test_log_formatter::BOOST_UTL_ET_MESSAGE:
     690             :       {
     691           0 :         if(m_log_level_internal > log_messages) {
     692           0 :           last_entry.skipping = true;
     693           0 :           break;
     694             :         }
     695             :         BOOST_FALLTHROUGH;
     696           0 :       }
     697             :       case unit_test_log_formatter::BOOST_UTL_ET_WARNING:
     698             :       {
     699           0 :         if(m_log_level_internal > log_warnings) {
     700           0 :           last_entry.skipping = true;
     701           0 :           break;
     702             :         }
     703           0 :         std::ostringstream o;
     704           0 :         junit_impl::junit_log_helper::assertion_entry entry;
     705             : 
     706           0 :         entry.log_entry = junit_impl::junit_log_helper::assertion_entry::log_entry_info;
     707           0 :         entry.logentry_message = "info";
     708           0 :         entry.logentry_type = "message";
     709             : 
     710           0 :         o << (let == unit_test_log_formatter::BOOST_UTL_ET_WARNING ?
     711           0 :               "WARNING:" : (let == unit_test_log_formatter::BOOST_UTL_ET_MESSAGE ?
     712             :                             "MESSAGE:" : "INFO:"))
     713           0 :              << std::endl
     714           0 :           << "- file   : " << file_basename(entry_data.m_file_name) << std::endl
     715           0 :           << "- line   : " << entry_data.m_line_num << std::endl
     716           0 :           << "- message: "; // no CR
     717             : 
     718           0 :         entry.output += o.str();
     719           0 :         last_entry.assertion_entries.push_back(entry);
     720             :         break;
     721           0 :       }
     722             :       default:
     723             :       case unit_test_log_formatter::BOOST_UTL_ET_ERROR:
     724             :       case unit_test_log_formatter::BOOST_UTL_ET_FATAL_ERROR:
     725             :       {
     726           0 :         std::ostringstream o;
     727           0 :         junit_impl::junit_log_helper::assertion_entry entry;
     728           0 :         entry.log_entry = junit_impl::junit_log_helper::assertion_entry::log_entry_failure;
     729           0 :         entry.logentry_message = "failure";
     730           0 :         entry.logentry_type = (let == unit_test_log_formatter::BOOST_UTL_ET_ERROR ? "assertion error" : "fatal error");
     731             : 
     732           0 :         o << "ASSERTION FAILURE:" << std::endl
     733           0 :           << "- file   : " << file_basename(entry_data.m_file_name) << std::endl
     734           0 :           << "- line   : " << entry_data.m_line_num << std::endl
     735           0 :           << "- message: " ; // no CR
     736             : 
     737           0 :         entry.output += o.str();
     738           0 :         last_entry.assertion_entries.push_back(entry);
     739             :         break;
     740           0 :       }
     741             :     }
     742           0 : }
     743             : 
     744             : //____________________________________________________________________________//
     745             : 
     746             : void
     747           0 : junit_log_formatter::log_entry_value( std::ostream& /*ostr*/, const_string value )
     748             : {
     749           0 :     junit_impl::junit_log_helper& last_entry = get_current_log_entry();
     750           0 :     if(last_entry.skipping)
     751           0 :         return;
     752             : 
     753           0 :     assert(last_entry.assertion_entries.empty() || !last_entry.assertion_entries.back().sealed);
     754             : 
     755           0 :     if(!last_entry.assertion_entries.empty())
     756             :     {
     757           0 :         junit_impl::junit_log_helper::assertion_entry& log_entry = last_entry.assertion_entries.back();
     758           0 :         log_entry.output += value;
     759           0 :     }
     760             :     else
     761             :     {
     762             :         // this may be a message coming from another observer
     763             :         // the prefix is set in the log_entry_start
     764           0 :         last_entry.system_out.push_back(std::string(value.begin(), value.end()));
     765             :     }
     766           0 : }
     767             : 
     768             : //____________________________________________________________________________//
     769             : 
     770             : void
     771           0 : junit_log_formatter::log_entry_finish( std::ostream& /*ostr*/ )
     772             : {
     773           0 :     junit_impl::junit_log_helper& last_entry = get_current_log_entry();
     774           0 :     if(!last_entry.skipping)
     775             :     {
     776           0 :         assert(last_entry.assertion_entries.empty() || !last_entry.assertion_entries.back().sealed);
     777             : 
     778           0 :         if(!last_entry.assertion_entries.empty()) {
     779           0 :             junit_impl::junit_log_helper::assertion_entry& log_entry = last_entry.assertion_entries.back();
     780           0 :             log_entry.output += "\n\n"; // quote end, CR
     781           0 :             log_entry.sealed = true;
     782           0 :         }
     783             :         else {
     784           0 :             last_entry.system_out.push_back("\n\n"); // quote end, CR
     785             :         }
     786           0 :     }
     787             : 
     788           0 :     last_entry.skipping = false;
     789           0 : }
     790             : 
     791             : //____________________________________________________________________________//
     792             : 
     793             : void
     794           0 : junit_log_formatter::entry_context_start( std::ostream& /*ostr*/, log_level )
     795             : {
     796           0 :     junit_impl::junit_log_helper& last_entry = get_current_log_entry();
     797           0 :     if(last_entry.skipping)
     798           0 :         return;
     799             : 
     800           0 :     std::vector< junit_impl::junit_log_helper::assertion_entry > &v_failure_or_error = last_entry.assertion_entries;
     801           0 :     assert(!v_failure_or_error.back().sealed);
     802             : 
     803           0 :     junit_impl::junit_log_helper::assertion_entry& last_log_entry = v_failure_or_error.back();
     804           0 :     if(m_is_last_assertion_or_error)
     805             :     {
     806           0 :         last_log_entry.output += "\n- context:\n";
     807           0 :     }
     808             :     else
     809             :     {
     810           0 :         last_log_entry.output += "\n\nCONTEXT:\n";
     811             :     }
     812           0 : }
     813             : 
     814             : //____________________________________________________________________________//
     815             : 
     816             : void
     817           0 : junit_log_formatter::entry_context_finish( std::ostream& /*ostr*/, log_level )
     818             : {
     819             :     // no op, may be removed
     820           0 :     junit_impl::junit_log_helper& last_entry = get_current_log_entry();
     821           0 :     if(last_entry.skipping)
     822           0 :         return;
     823           0 :     assert(!get_current_log_entry().assertion_entries.back().sealed);
     824           0 : }
     825             : 
     826             : //____________________________________________________________________________//
     827             : 
     828             : void
     829           0 : junit_log_formatter::log_entry_context( std::ostream& /*ostr*/, log_level , const_string context_descr )
     830             : {
     831           0 :     junit_impl::junit_log_helper& last_entry = get_current_log_entry();
     832           0 :     if(last_entry.skipping)
     833           0 :         return;
     834             : 
     835           0 :     assert(!last_entry.assertion_entries.back().sealed);
     836           0 :     junit_impl::junit_log_helper::assertion_entry& last_log_entry = get_current_log_entry().assertion_entries.back();
     837             : 
     838           0 :     last_log_entry.output +=
     839           0 :         (m_is_last_assertion_or_error ? "  - '": "- '") + std::string(context_descr.begin(), context_descr.end()) + "'\n"; // quote end
     840           0 : }
     841             : 
     842             : //____________________________________________________________________________//
     843             : 
     844             : 
     845             : std::string
     846           0 : junit_log_formatter::get_default_stream_description() const {
     847           0 :     std::string name = framework::master_test_suite().p_name.value;
     848             : 
     849             :     static const std::string to_replace[] =  { " ", "\"", "/", "\\", ":"};
     850             :     static const std::string replacement[] = { "_", "_" , "_", "_" , "_"};
     851             : 
     852           0 :     name = unit_test::utils::replace_all_occurrences_of(
     853           0 :         name,
     854             :         to_replace, to_replace + sizeof(to_replace)/sizeof(to_replace[0]),
     855             :         replacement, replacement + sizeof(replacement)/sizeof(replacement[0]));
     856             : 
     857           0 :     std::ifstream check_init((name + ".xml").c_str());
     858           0 :     if(!check_init)
     859           0 :         return name + ".xml";
     860             : 
     861           0 :     int index = 0;
     862           0 :     for(; index < 100; index++) {
     863           0 :       std::string candidate = name + "_" + utils::string_cast(index) + ".xml";
     864           0 :       std::ifstream file(candidate.c_str());
     865           0 :       if(!file)
     866           0 :           return candidate;
     867           0 :     }
     868             : 
     869           0 :     return name + ".xml";
     870           0 : }
     871             : 
     872             : } // namespace output
     873             : } // namespace unit_test
     874             : } // namespace boost
     875             : 
     876             : #include <boost/test/detail/enable_warnings.hpp>
     877             : 
     878             : #endif // BOOST_TEST_junit_log_formatter_IPP_020105GER

Generated by: LCOV version 1.16