File indexing completed on 2025-01-30 10:00:59
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012 #ifndef BOOST_TEST_JUNIT_LOG_FORMATTER_IPP__
0013 #define BOOST_TEST_JUNIT_LOG_FORMATTER_IPP__
0014
0015
0016 #include <boost/test/output/junit_log_formatter.hpp>
0017 #include <boost/test/execution_monitor.hpp>
0018 #include <boost/test/framework.hpp>
0019 #include <boost/test/tree/test_unit.hpp>
0020 #include <boost/test/utils/basic_cstring/io.hpp>
0021 #include <boost/test/utils/xml_printer.hpp>
0022 #include <boost/test/utils/string_cast.hpp>
0023 #include <boost/test/framework.hpp>
0024
0025 #include <boost/test/tree/visitor.hpp>
0026 #include <boost/test/tree/traverse.hpp>
0027 #include <boost/test/results_collector.hpp>
0028
0029 #include <boost/test/utils/algorithm.hpp>
0030 #include <boost/test/utils/string_cast.hpp>
0031
0032
0033
0034
0035
0036 #include <boost/version.hpp>
0037 #include <boost/core/ignore_unused.hpp>
0038
0039
0040 #include <iostream>
0041 #include <fstream>
0042 #include <set>
0043
0044 #include <boost/test/detail/suppress_warnings.hpp>
0045
0046
0047
0048
0049 namespace boost {
0050 namespace unit_test {
0051 namespace output {
0052
0053
0054 struct s_replace_chars {
0055 template <class T>
0056 void operator()(T& to_replace)
0057 {
0058 if(to_replace == '/')
0059 to_replace = '.';
0060 else if(to_replace == ' ')
0061 to_replace = '_';
0062 }
0063 };
0064
0065 inline std::string tu_name_normalize(std::string full_name)
0066 {
0067
0068 std::for_each(full_name.begin(), full_name.end(), s_replace_chars());
0069 return full_name;
0070 }
0071
0072 inline std::string tu_name_remove_newlines(std::string full_name)
0073 {
0074 full_name.erase(std::remove(full_name.begin(), full_name.end(), '\n'), full_name.end());
0075 return full_name;
0076 }
0077
0078 const_string file_basename(const_string filename) {
0079
0080 const_string path_sep( "\\/" );
0081 const_string::iterator it = unit_test::utils::find_last_of( filename.begin(), filename.end(),
0082 path_sep.begin(), path_sep.end() );
0083 if( it != filename.end() )
0084 filename.trim_left( it + 1 );
0085
0086 return filename;
0087
0088 }
0089
0090
0091
0092
0093
0094 void
0095 junit_log_formatter::log_start( std::ostream& , counter_t )
0096 {
0097 map_tests.clear();
0098 list_path_to_root.clear();
0099 runner_log_entry.clear();
0100 }
0101
0102
0103
0104 class junit_result_helper : public test_tree_visitor {
0105 private:
0106 typedef junit_impl::junit_log_helper::assertion_entry assertion_entry;
0107 typedef std::vector< assertion_entry >::const_iterator vect_assertion_entry_citerator;
0108 typedef std::list<std::string>::const_iterator list_str_citerator;
0109
0110 public:
0111 explicit junit_result_helper(
0112 std::ostream& stream,
0113 test_unit const& ts,
0114 junit_log_formatter::map_trace_t const& mt,
0115 junit_impl::junit_log_helper const& runner_log_,
0116 bool display_build_info )
0117 : m_stream(stream)
0118 , m_ts( ts )
0119 , m_map_test( mt )
0120 , runner_log( runner_log_ )
0121 , m_id( 0 )
0122 , m_display_build_info(display_build_info)
0123 { }
0124
0125 void add_log_entry(assertion_entry const& log) const
0126 {
0127 std::string entry_type;
0128 if( log.log_entry == assertion_entry::log_entry_failure ) {
0129 entry_type = "failure";
0130 }
0131 else if( log.log_entry == assertion_entry::log_entry_error ) {
0132 entry_type = "error";
0133 }
0134 else {
0135 return;
0136 }
0137
0138 m_stream
0139 << "<" << entry_type
0140 << " message" << utils::attr_value() << log.logentry_message
0141 << " type" << utils::attr_value() << log.logentry_type
0142 << ">";
0143
0144 if(!log.output.empty()) {
0145 m_stream << utils::cdata() << "\n" + log.output;
0146 }
0147
0148 m_stream << "</" << entry_type << ">";
0149 }
0150
0151 struct conditional_cdata_helper {
0152 std::ostream &ostr;
0153 std::string const field;
0154 bool empty;
0155
0156 conditional_cdata_helper(std::ostream &ostr_, std::string field_)
0157 : ostr(ostr_)
0158 , field(field_)
0159 , empty(true)
0160 {}
0161
0162 ~conditional_cdata_helper() {
0163 if(!empty) {
0164 ostr << BOOST_TEST_L( "]]>" ) << "</" << field << '>' << std::endl;
0165 }
0166 }
0167
0168 void operator()(const std::string& s) {
0169 bool current_empty = s.empty();
0170 if(empty) {
0171 if(!current_empty) {
0172 empty = false;
0173 ostr << '<' << field << '>' << BOOST_TEST_L( "<![CDATA[" );
0174 }
0175 }
0176 if(!current_empty) {
0177 ostr << s;
0178 }
0179 }
0180 };
0181
0182 std::list<std::string> build_skipping_chain(test_unit const & tu) const
0183 {
0184
0185
0186 assert(m_map_test.count(tu.p_id) == 0 || results_collector.results( tu.p_id ).p_skipped);
0187
0188 std::list<std::string> out;
0189
0190 test_unit_id id(tu.p_id);
0191 while( id != m_ts.p_id && id != INV_TEST_UNIT_ID) {
0192 test_unit const& tu_hierarchy = boost::unit_test::framework::get( id, TUT_ANY );
0193 out.push_back("- disabled test unit: '" + tu_name_remove_newlines(tu_hierarchy.full_name()) + "'\n");
0194 if(m_map_test.count(id) > 0)
0195 {
0196
0197 break;
0198 }
0199 id = tu_hierarchy.p_parent_id;
0200 }
0201 junit_log_formatter::map_trace_t::const_iterator it_element_stack(m_map_test.find(id));
0202 if( it_element_stack != m_map_test.end() )
0203 {
0204 out.push_back("- reason: '" + it_element_stack->second.skipping_reason + "'");
0205 out.push_front("Test case disabled because of the following chain of decision:\n");
0206 }
0207
0208 return out;
0209 }
0210
0211 std::string get_class_name(test_unit const & tu_class) const {
0212 std::string classname;
0213 test_unit_id id(tu_class.p_parent_id);
0214 while( id != m_ts.p_id && id != INV_TEST_UNIT_ID ) {
0215 test_unit const& tu = boost::unit_test::framework::get( id, TUT_ANY );
0216 classname = tu_name_normalize(tu.p_name) + "." + classname;
0217 id = tu.p_parent_id;
0218 }
0219
0220
0221 if(!classname.empty() && *classname.rbegin() == '.') {
0222 classname.erase(classname.size()-1);
0223 }
0224
0225 return classname;
0226 }
0227
0228 void write_testcase_header(test_unit const & tu,
0229 test_results const *tr,
0230 int nb_assertions) const
0231 {
0232 std::string name;
0233 std::string classname;
0234
0235 if(tu.p_id == m_ts.p_id ) {
0236 name = "boost_test";
0237 }
0238 else {
0239 classname = get_class_name(tu);
0240 name = tu_name_normalize(tu.p_name);
0241 }
0242
0243 if( tu.p_type == TUT_SUITE ) {
0244 if(tr->p_timed_out)
0245 name += "-timed-execution";
0246 else
0247 name += "-setup-teardown";
0248 }
0249
0250 m_stream << "<testcase assertions" << utils::attr_value() << nb_assertions;
0251 if(!classname.empty())
0252 m_stream << " classname" << utils::attr_value() << classname;
0253
0254
0255 m_stream
0256 << " name" << utils::attr_value() << name
0257 << " time" << utils::attr_value() << double(tr->p_duration_microseconds) * 1E-6
0258 << ">" << std::endl;
0259 }
0260
0261 void write_testcase_system_out(junit_impl::junit_log_helper const &detailed_log,
0262 test_unit const * tu,
0263 bool skipped) const
0264 {
0265
0266 conditional_cdata_helper system_out_helper(m_stream, "system-out");
0267
0268
0269 if( skipped ) {
0270 std::list<std::string> skipping_decision_chain = build_skipping_chain(*tu);
0271 for(list_str_citerator it(skipping_decision_chain.begin()), ite(skipping_decision_chain.end());
0272 it != ite;
0273 ++it)
0274 {
0275 system_out_helper(*it);
0276 }
0277 }
0278
0279
0280 for(list_str_citerator it(detailed_log.system_out.begin()), ite(detailed_log.system_out.end());
0281 it != ite;
0282 ++it)
0283 {
0284 system_out_helper(*it);
0285 }
0286
0287
0288 for(vect_assertion_entry_citerator it(detailed_log.assertion_entries.begin());
0289 it != detailed_log.assertion_entries.end();
0290 ++it)
0291 {
0292 if(it->log_entry != assertion_entry::log_entry_info)
0293 continue;
0294 system_out_helper(it->output);
0295 }
0296 }
0297
0298 void write_testcase_system_err(junit_impl::junit_log_helper const &detailed_log,
0299 test_unit const * tu,
0300 test_results const *tr) const
0301 {
0302
0303 bool has_failed = (tr != 0) ? !tr->p_skipped && !tr->passed() : false;
0304 if(!detailed_log.system_err.empty() || has_failed)
0305 {
0306 std::ostringstream o;
0307 if(has_failed) {
0308 o << "Failures detected in:" << std::endl;
0309 }
0310 else {
0311 o << "ERROR STREAM:" << std::endl;
0312 }
0313
0314 if(tu->p_type == TUT_SUITE) {
0315 if( tu->p_id == m_ts.p_id ) {
0316 o << " boost.test global setup/teardown" << std::endl;
0317 } else {
0318 o << "- test suite: " << tu_name_remove_newlines(tu->full_name()) << std::endl;
0319 }
0320 }
0321 else {
0322 o << "- test case: " << tu_name_remove_newlines(tu->full_name());
0323 if(!tu->p_description.value.empty())
0324 o << " '" << tu->p_description << "'";
0325
0326 o << std::endl
0327 << "- file: " << file_basename(tu->p_file_name) << std::endl
0328 << "- line: " << tu->p_line_num << std::endl
0329 ;
0330 }
0331
0332 if(!detailed_log.system_err.empty())
0333 o << std::endl << "STDERR BEGIN: ------------" << std::endl;
0334
0335 for(list_str_citerator it(detailed_log.system_err.begin()), ite(detailed_log.system_err.end());
0336 it != ite;
0337 ++it)
0338 {
0339 o << *it;
0340 }
0341
0342 if(!detailed_log.system_err.empty())
0343 o << std::endl << "STDERR END ------------" << std::endl;
0344
0345 conditional_cdata_helper system_err_helper(m_stream, "system-err");
0346 system_err_helper(o.str());
0347 }
0348 }
0349
0350 int get_nb_assertions(junit_impl::junit_log_helper const &detailed_log,
0351 test_unit const & tu,
0352 test_results const *tr) const {
0353 int nb_assertions(-1);
0354 if( tu.p_type == TUT_SUITE ) {
0355 nb_assertions = 0;
0356 for(vect_assertion_entry_citerator it(detailed_log.assertion_entries.begin());
0357 it != detailed_log.assertion_entries.end();
0358 ++it)
0359 {
0360 if(it->log_entry != assertion_entry::log_entry_info)
0361 nb_assertions++;
0362 }
0363 }
0364 else {
0365 nb_assertions = static_cast<int>(tr->p_assertions_passed + tr->p_assertions_failed);
0366 }
0367
0368 return nb_assertions;
0369 }
0370
0371 void output_detailed_logs(junit_impl::junit_log_helper const &detailed_log,
0372 test_unit const & tu,
0373 bool skipped,
0374 test_results const *tr) const
0375 {
0376 int nb_assertions = get_nb_assertions(detailed_log, tu, tr);
0377 if(!nb_assertions && tu.p_type == TUT_SUITE)
0378 return;
0379
0380 write_testcase_header(tu, tr, nb_assertions);
0381
0382 if( skipped ) {
0383 m_stream << "<skipped/>" << std::endl;
0384 }
0385 else {
0386
0387 for(vect_assertion_entry_citerator it(detailed_log.assertion_entries.begin());
0388 it != detailed_log.assertion_entries.end();
0389 ++it)
0390 {
0391 add_log_entry(*it);
0392 }
0393 }
0394
0395 write_testcase_system_out(detailed_log, &tu, skipped);
0396 write_testcase_system_err(detailed_log, &tu, tr);
0397 m_stream << "</testcase>" << std::endl;
0398 }
0399
0400 void visit( test_case const& tc ) BOOST_OVERRIDE
0401 {
0402
0403 test_results const& tr = results_collector.results( tc.p_id );
0404 junit_log_formatter::map_trace_t::const_iterator it_find = m_map_test.find(tc.p_id);
0405 if(it_find == m_map_test.end())
0406 {
0407
0408 output_detailed_logs(junit_impl::junit_log_helper(), tc, true, &tr);
0409 }
0410 else {
0411 output_detailed_logs(it_find->second, tc, tr.p_skipped, &tr);
0412 }
0413 }
0414
0415 bool test_suite_start( test_suite const& ts ) BOOST_OVERRIDE
0416 {
0417 test_results const& tr = results_collector.results( ts.p_id );
0418
0419
0420 if( m_ts.p_id == ts.p_id ) {
0421 m_stream << "<testsuite";
0422
0423
0424
0425
0426
0427
0428
0429 m_stream
0430
0431 << " tests" << utils::attr_value()
0432 << tr.p_test_cases_passed
0433 + tr.p_test_cases_failed
0434
0435 << " skipped" << utils::attr_value() << tr.p_test_cases_skipped
0436 << " errors" << utils::attr_value() << tr.p_test_cases_aborted
0437 << " failures" << utils::attr_value()
0438 << tr.p_test_cases_failed
0439 + tr.p_test_suites_timed_out
0440 + tr.p_test_cases_timed_out
0441 - tr.p_test_cases_aborted
0442 << " id" << utils::attr_value() << m_id++
0443 << " name" << utils::attr_value() << tu_name_normalize(ts.p_name)
0444 << " time" << utils::attr_value() << (tr.p_duration_microseconds * 1E-6)
0445 << ">" << std::endl;
0446
0447 if(m_display_build_info)
0448 {
0449 m_stream << "<properties>" << std::endl;
0450 m_stream << "<property name=\"platform\" value" << utils::attr_value() << BOOST_PLATFORM << " />" << std::endl;
0451 m_stream << "<property name=\"compiler\" value" << utils::attr_value() << BOOST_COMPILER << " />" << std::endl;
0452 m_stream << "<property name=\"stl\" value" << utils::attr_value() << BOOST_STDLIB << " />" << std::endl;
0453
0454 std::ostringstream o;
0455 o << BOOST_VERSION/100000 << "." << BOOST_VERSION/100 % 1000 << "." << BOOST_VERSION % 100;
0456 m_stream << "<property name=\"boost\" value" << utils::attr_value() << o.str() << " />" << std::endl;
0457 m_stream << "</properties>" << std::endl;
0458 }
0459 }
0460
0461 if( !tr.p_skipped ) {
0462
0463
0464
0465 junit_log_formatter::map_trace_t::const_iterator it_find = m_map_test.find(ts.p_id);
0466 if(it_find != m_map_test.end()) {
0467 output_detailed_logs(it_find->second, ts, false, &tr);
0468 }
0469 }
0470
0471 return true;
0472 }
0473
0474 void test_suite_finish( test_suite const& ts ) BOOST_OVERRIDE
0475 {
0476 if( m_ts.p_id == ts.p_id ) {
0477 write_testcase_system_out(runner_log, 0, false);
0478 write_testcase_system_err(runner_log, 0, 0);
0479
0480 m_stream << "</testsuite>";
0481 return;
0482 }
0483 }
0484
0485 private:
0486
0487 std::ostream& m_stream;
0488 test_unit const& m_ts;
0489 junit_log_formatter::map_trace_t const& m_map_test;
0490 junit_impl::junit_log_helper const& runner_log;
0491 size_t m_id;
0492 bool m_display_build_info;
0493 };
0494
0495
0496
0497 void
0498 junit_log_formatter::log_finish( std::ostream& ostr )
0499 {
0500 ostr << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" << std::endl;
0501
0502
0503 if(!map_tests.empty()) {
0504 test_unit* root = &boost::unit_test::framework::get( map_tests.begin()->first, TUT_ANY );
0505
0506
0507 while(root->p_parent_id != INV_TEST_UNIT_ID && map_tests.count(root->p_parent_id) > 0) {
0508 root = &boost::unit_test::framework::get( root->p_parent_id, TUT_ANY );
0509 }
0510 junit_result_helper ch( ostr, *root, map_tests, this->runner_log_entry, m_display_build_info );
0511 traverse_test_tree( root->p_id, ch, true );
0512 }
0513 else {
0514 ostr << "<testsuites errors=\"1\">";
0515 ostr << "<testsuite errors=\"1\" name=\"boost-test-framework\">";
0516 ostr << "<testcase assertions=\"1\" name=\"test-setup\">";
0517 ostr << "<system-out>Incorrect setup: no test case executed</system-out>";
0518 ostr << "</testcase></testsuite></testsuites>";
0519 }
0520 return;
0521 }
0522
0523
0524
0525 void
0526 junit_log_formatter::log_build_info( std::ostream& , bool log_build_info )
0527 {
0528 m_display_build_info = log_build_info;
0529 }
0530
0531
0532
0533 void
0534 junit_log_formatter::test_unit_start( std::ostream& , test_unit const& tu )
0535 {
0536 list_path_to_root.push_back( tu.p_id );
0537 map_tests.insert(std::make_pair(tu.p_id, junit_impl::junit_log_helper()));
0538 }
0539
0540
0541
0542
0543
0544
0545 void
0546 junit_log_formatter::test_unit_finish( std::ostream& , test_unit const& tu, unsigned long )
0547 {
0548
0549 boost::ignore_unused( tu );
0550 assert( tu.p_id == list_path_to_root.back() );
0551 list_path_to_root.pop_back();
0552 }
0553
0554 void
0555 junit_log_formatter::test_unit_aborted( std::ostream& , test_unit const& tu )
0556 {
0557 boost::ignore_unused( tu );
0558 assert( tu.p_id == list_path_to_root.back() );
0559
0560 }
0561
0562
0563
0564 void
0565 junit_log_formatter::test_unit_timed_out( std::ostream& , test_unit const& tu)
0566 {
0567 if(tu.p_type == TUT_SUITE)
0568 {
0569
0570
0571 junit_impl::junit_log_helper& last_entry = get_current_log_entry();
0572 junit_impl::junit_log_helper::assertion_entry entry;
0573 entry.logentry_message = "test-suite time out";
0574 entry.logentry_type = "execution timeout";
0575 entry.log_entry = junit_impl::junit_log_helper::assertion_entry::log_entry_error;
0576 entry.output = "the current suite exceeded the allocated execution time";
0577 last_entry.assertion_entries.push_back(entry);
0578 }
0579 }
0580
0581
0582
0583 void
0584 junit_log_formatter::test_unit_skipped( std::ostream& , test_unit const& tu, const_string reason )
0585 {
0586
0587
0588
0589 junit_impl::junit_log_helper& v = map_tests[tu.p_id];
0590 v.skipping_reason.assign(reason.begin(), reason.end());
0591 }
0592
0593
0594
0595 void
0596 junit_log_formatter::log_exception_start( std::ostream& , log_checkpoint_data const& checkpoint_data, execution_exception const& ex )
0597 {
0598 std::ostringstream o;
0599 execution_exception::location const& loc = ex.where();
0600
0601 m_is_last_assertion_or_error = false;
0602
0603 junit_impl::junit_log_helper& last_entry = get_current_log_entry();
0604
0605 junit_impl::junit_log_helper::assertion_entry entry;
0606
0607 entry.logentry_message = "unexpected exception";
0608 entry.log_entry = junit_impl::junit_log_helper::assertion_entry::log_entry_error;
0609
0610 switch(ex.code())
0611 {
0612 case execution_exception::cpp_exception_error:
0613 entry.logentry_type = "uncaught exception";
0614 break;
0615 case execution_exception::timeout_error:
0616 entry.logentry_type = "execution timeout";
0617 break;
0618 case execution_exception::user_error:
0619 entry.logentry_type = "user, assert() or CRT error";
0620 break;
0621 case execution_exception::user_fatal_error:
0622
0623 entry.logentry_type = "user fatal error";
0624 break;
0625 case execution_exception::system_error:
0626 entry.logentry_type = "system error";
0627 break;
0628 case execution_exception::system_fatal_error:
0629 entry.logentry_type = "system fatal error";
0630 break;
0631 default:
0632 entry.logentry_type = "no error";
0633 break;
0634 }
0635
0636 o << "UNCAUGHT EXCEPTION:" << std::endl;
0637 if( !loc.m_function.is_empty() )
0638 o << "- function: \"" << loc.m_function << "\"" << std::endl;
0639
0640 o << "- file: " << file_basename(loc.m_file_name) << std::endl
0641 << "- line: " << loc.m_line_num << std::endl
0642 << std::endl;
0643
0644 o << "\nEXCEPTION STACK TRACE: --------------\n" << ex.what()
0645 << "\n-------------------------------------";
0646
0647 if( !checkpoint_data.m_file_name.is_empty() ) {
0648 o << std::endl << std::endl
0649 << "Last checkpoint:" << std::endl
0650 << "- message: \"" << checkpoint_data.m_message << "\"" << std::endl
0651 << "- file: " << file_basename(checkpoint_data.m_file_name) << std::endl
0652 << "- line: " << checkpoint_data.m_line_num << std::endl
0653 ;
0654 }
0655
0656 entry.output = o.str();
0657
0658 last_entry.assertion_entries.push_back(entry);
0659 }
0660
0661
0662
0663 void
0664 junit_log_formatter::log_exception_finish( std::ostream& )
0665 {
0666
0667 assert(!get_current_log_entry().assertion_entries.back().sealed);
0668 get_current_log_entry().assertion_entries.back().sealed = true;
0669 }
0670
0671
0672
0673 void
0674 junit_log_formatter::log_entry_start( std::ostream& , log_entry_data const& entry_data, log_entry_types let )
0675 {
0676 junit_impl::junit_log_helper& last_entry = get_current_log_entry();
0677 last_entry.skipping = false;
0678 m_is_last_assertion_or_error = true;
0679 switch(let)
0680 {
0681 case unit_test_log_formatter::BOOST_UTL_ET_INFO:
0682 {
0683 if(m_log_level_internal > log_successful_tests) {
0684 last_entry.skipping = true;
0685 break;
0686 }
0687 BOOST_FALLTHROUGH;
0688 }
0689 case unit_test_log_formatter::BOOST_UTL_ET_MESSAGE:
0690 {
0691 if(m_log_level_internal > log_messages) {
0692 last_entry.skipping = true;
0693 break;
0694 }
0695 BOOST_FALLTHROUGH;
0696 }
0697 case unit_test_log_formatter::BOOST_UTL_ET_WARNING:
0698 {
0699 if(m_log_level_internal > log_warnings) {
0700 last_entry.skipping = true;
0701 break;
0702 }
0703 std::ostringstream o;
0704 junit_impl::junit_log_helper::assertion_entry entry;
0705
0706 entry.log_entry = junit_impl::junit_log_helper::assertion_entry::log_entry_info;
0707 entry.logentry_message = "info";
0708 entry.logentry_type = "message";
0709
0710 o << (let == unit_test_log_formatter::BOOST_UTL_ET_WARNING ?
0711 "WARNING:" : (let == unit_test_log_formatter::BOOST_UTL_ET_MESSAGE ?
0712 "MESSAGE:" : "INFO:"))
0713 << std::endl
0714 << "- file : " << file_basename(entry_data.m_file_name) << std::endl
0715 << "- line : " << entry_data.m_line_num << std::endl
0716 << "- message: ";
0717
0718 entry.output += o.str();
0719 last_entry.assertion_entries.push_back(entry);
0720 break;
0721 }
0722 default:
0723 case unit_test_log_formatter::BOOST_UTL_ET_ERROR:
0724 case unit_test_log_formatter::BOOST_UTL_ET_FATAL_ERROR:
0725 {
0726 std::ostringstream o;
0727 junit_impl::junit_log_helper::assertion_entry entry;
0728 entry.log_entry = junit_impl::junit_log_helper::assertion_entry::log_entry_failure;
0729 entry.logentry_message = "failure";
0730 entry.logentry_type = (let == unit_test_log_formatter::BOOST_UTL_ET_ERROR ? "assertion error" : "fatal error");
0731
0732 o << "ASSERTION FAILURE:" << std::endl
0733 << "- file : " << file_basename(entry_data.m_file_name) << std::endl
0734 << "- line : " << entry_data.m_line_num << std::endl
0735 << "- message: " ;
0736
0737 entry.output += o.str();
0738 last_entry.assertion_entries.push_back(entry);
0739 break;
0740 }
0741 }
0742 }
0743
0744
0745
0746 void
0747 junit_log_formatter::log_entry_value( std::ostream& , const_string value )
0748 {
0749 junit_impl::junit_log_helper& last_entry = get_current_log_entry();
0750 if(last_entry.skipping)
0751 return;
0752
0753 assert(last_entry.assertion_entries.empty() || !last_entry.assertion_entries.back().sealed);
0754
0755 if(!last_entry.assertion_entries.empty())
0756 {
0757 junit_impl::junit_log_helper::assertion_entry& log_entry = last_entry.assertion_entries.back();
0758 log_entry.output += value;
0759 }
0760 else
0761 {
0762
0763
0764 last_entry.system_out.push_back(std::string(value.begin(), value.end()));
0765 }
0766 }
0767
0768
0769
0770 void
0771 junit_log_formatter::log_entry_finish( std::ostream& )
0772 {
0773 junit_impl::junit_log_helper& last_entry = get_current_log_entry();
0774 if(!last_entry.skipping)
0775 {
0776 assert(last_entry.assertion_entries.empty() || !last_entry.assertion_entries.back().sealed);
0777
0778 if(!last_entry.assertion_entries.empty()) {
0779 junit_impl::junit_log_helper::assertion_entry& log_entry = last_entry.assertion_entries.back();
0780 log_entry.output += "\n\n";
0781 log_entry.sealed = true;
0782 }
0783 else {
0784 last_entry.system_out.push_back("\n\n");
0785 }
0786 }
0787
0788 last_entry.skipping = false;
0789 }
0790
0791
0792
0793 void
0794 junit_log_formatter::entry_context_start( std::ostream& , log_level )
0795 {
0796 junit_impl::junit_log_helper& last_entry = get_current_log_entry();
0797 if(last_entry.skipping)
0798 return;
0799
0800 std::vector< junit_impl::junit_log_helper::assertion_entry > &v_failure_or_error = last_entry.assertion_entries;
0801 assert(!v_failure_or_error.back().sealed);
0802
0803 junit_impl::junit_log_helper::assertion_entry& last_log_entry = v_failure_or_error.back();
0804 if(m_is_last_assertion_or_error)
0805 {
0806 last_log_entry.output += "\n- context:\n";
0807 }
0808 else
0809 {
0810 last_log_entry.output += "\n\nCONTEXT:\n";
0811 }
0812 }
0813
0814
0815
0816 void
0817 junit_log_formatter::entry_context_finish( std::ostream& , log_level )
0818 {
0819
0820 junit_impl::junit_log_helper& last_entry = get_current_log_entry();
0821 if(last_entry.skipping)
0822 return;
0823 assert(!get_current_log_entry().assertion_entries.back().sealed);
0824 }
0825
0826
0827
0828 void
0829 junit_log_formatter::log_entry_context( std::ostream& , log_level , const_string context_descr )
0830 {
0831 junit_impl::junit_log_helper& last_entry = get_current_log_entry();
0832 if(last_entry.skipping)
0833 return;
0834
0835 assert(!last_entry.assertion_entries.back().sealed);
0836 junit_impl::junit_log_helper::assertion_entry& last_log_entry = get_current_log_entry().assertion_entries.back();
0837
0838 last_log_entry.output +=
0839 (m_is_last_assertion_or_error ? " - '": "- '") + std::string(context_descr.begin(), context_descr.end()) + "'\n";
0840 }
0841
0842
0843
0844
0845 std::string
0846 junit_log_formatter::get_default_stream_description() const {
0847 std::string name = framework::master_test_suite().p_name.value;
0848
0849 static const std::string to_replace[] = { " ", "\"", "/", "\\", ":"};
0850 static const std::string replacement[] = { "_", "_" , "_", "_" , "_"};
0851
0852 name = unit_test::utils::replace_all_occurrences_of(
0853 name,
0854 to_replace, to_replace + sizeof(to_replace)/sizeof(to_replace[0]),
0855 replacement, replacement + sizeof(replacement)/sizeof(replacement[0]));
0856
0857 std::ifstream check_init((name + ".xml").c_str());
0858 if(!check_init)
0859 return name + ".xml";
0860
0861 int index = 0;
0862 for(; index < 100; index++) {
0863 std::string candidate = name + "_" + utils::string_cast(index) + ".xml";
0864 std::ifstream file(candidate.c_str());
0865 if(!file)
0866 return candidate;
0867 }
0868
0869 return name + ".xml";
0870 }
0871
0872 }
0873 }
0874 }
0875
0876 #include <boost/test/detail/enable_warnings.hpp>
0877
0878 #endif