1// (C) Copyright Gennadiy Rozental 2001. 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 : $RCSfile$ 9// 10// Version : $Revision$ 11// 12// Description : implemets Unit Test Log 13// *************************************************************************** 14 15#ifndef BOOST_TEST_UNIT_TEST_LOG_IPP_012205GER 16#define BOOST_TEST_UNIT_TEST_LOG_IPP_012205GER 17 18// Boost.Test 19#include <boost/test/unit_test_log.hpp> 20#include <boost/test/unit_test_log_formatter.hpp> 21#include <boost/test/execution_monitor.hpp> 22#include <boost/test/framework.hpp> 23#include <boost/test/unit_test_parameters.hpp> 24 25#include <boost/test/utils/basic_cstring/compare.hpp> 26#include <boost/test/utils/foreach.hpp> 27 28#include <boost/test/output/compiler_log_formatter.hpp> 29#include <boost/test/output/xml_log_formatter.hpp> 30#include <boost/test/output/junit_log_formatter.hpp> 31 32// Boost 33#include <boost/shared_ptr.hpp> 34#include <boost/io/ios_state.hpp> 35typedef ::boost::io::ios_base_all_saver io_saver_type; 36 37#include <boost/test/detail/suppress_warnings.hpp> 38 39//____________________________________________________________________________// 40 41namespace boost { 42namespace unit_test { 43 44// ************************************************************************** // 45// ************** entry_value_collector ************** // 46// ************************************************************************** // 47 48namespace ut_detail { 49 50entry_value_collector const& 51entry_value_collector::operator<<( lazy_ostream const& v ) const 52{ 53 unit_test_log << v; 54 55 return *this; 56} 57 58//____________________________________________________________________________// 59 60entry_value_collector const& 61entry_value_collector::operator<<( const_string v ) const 62{ 63 unit_test_log << v; 64 65 return *this; 66} 67 68//____________________________________________________________________________// 69 70entry_value_collector::~entry_value_collector() 71{ 72 if( m_last ) 73 unit_test_log << log::end(); 74} 75 76//____________________________________________________________________________// 77 78} // namespace ut_detail 79 80// ************************************************************************** // 81// ************** unit_test_log ************** // 82// ************************************************************************** // 83 84namespace { 85 86// log data 87struct unit_test_log_data_helper_impl { 88 typedef boost::shared_ptr<unit_test_log_formatter> formatter_ptr; 89 typedef boost::shared_ptr<io_saver_type> saver_ptr; 90 91 bool m_enabled; 92 output_format m_format; 93 std::ostream* m_stream; 94 saver_ptr m_stream_state_saver; 95 formatter_ptr m_log_formatter; 96 bool m_entry_in_progress; 97 98 unit_test_log_data_helper_impl(unit_test_log_formatter* p_log_formatter, output_format format, bool enabled = false) 99 : m_enabled( enabled ) 100 , m_format( format ) 101 , m_stream( &std::cout ) 102 , m_stream_state_saver( new io_saver_type( std::cout ) ) 103 , m_log_formatter() 104 , m_entry_in_progress( false ) 105 { 106 m_log_formatter.reset(p_log_formatter); 107 m_log_formatter->set_log_level(log_all_errors); 108 } 109 110 // helper functions 111 std::ostream& stream() 112 { 113 return *m_stream; 114 } 115 116 log_level get_log_level() const 117 { 118 return m_log_formatter->get_log_level(); 119 } 120}; 121 122struct unit_test_log_impl { 123 // Constructor 124 unit_test_log_impl() 125 { 126 m_log_formatter_data.push_back( unit_test_log_data_helper_impl(new output::compiler_log_formatter, OF_CLF, true) ); // only this one is active by default, 127 m_log_formatter_data.push_back( unit_test_log_data_helper_impl(new output::xml_log_formatter, OF_XML, false) ); 128 m_log_formatter_data.push_back( unit_test_log_data_helper_impl(new output::junit_log_formatter, OF_JUNIT, false) ); 129 } 130 131 typedef std::vector<unit_test_log_data_helper_impl> v_formatter_data_t; 132 v_formatter_data_t m_log_formatter_data; 133 134 typedef std::vector<unit_test_log_data_helper_impl*> vp_formatter_data_t; 135 vp_formatter_data_t m_active_log_formatter_data; 136 137 // entry data 138 log_entry_data m_entry_data; 139 140 bool has_entry_in_progress() const { 141 for( vp_formatter_data_t::const_iterator it(m_active_log_formatter_data.begin()), ite(m_active_log_formatter_data.end()); 142 it < ite; 143 ++it) 144 { 145 unit_test_log_data_helper_impl& current_logger_data = **it; 146 if( current_logger_data.m_entry_in_progress ) 147 return true; 148 } 149 return false; 150 } 151 152 // check point data 153 log_checkpoint_data m_checkpoint_data; 154 155 void set_checkpoint( const_string file, std::size_t line_num, const_string msg ) 156 { 157 assign_op( m_checkpoint_data.m_message, msg, 0 ); 158 m_checkpoint_data.m_file_name = file; 159 m_checkpoint_data.m_line_num = line_num; 160 } 161}; 162 163unit_test_log_impl& s_log_impl() { static unit_test_log_impl the_inst; return the_inst; } 164 165 166//____________________________________________________________________________// 167 168void 169log_entry_context( log_level l, unit_test_log_data_helper_impl& current_logger_data) 170{ 171 framework::context_generator const& context = framework::get_context(); 172 if( context.is_empty() ) 173 return; 174 175 const_string frame; 176 current_logger_data.m_log_formatter->entry_context_start( current_logger_data.stream(), l ); 177 while( !(frame=context.next()).is_empty() ) 178 { 179 current_logger_data.m_log_formatter->log_entry_context( current_logger_data.stream(), l, frame ); 180 } 181 current_logger_data.m_log_formatter->entry_context_finish( current_logger_data.stream(), l ); 182} 183 184//____________________________________________________________________________// 185 186void 187clear_entry_context() 188{ 189 framework::clear_context(); 190} 191 192// convenience 193typedef unit_test_log_impl::vp_formatter_data_t vp_logger_t; 194typedef unit_test_log_impl::v_formatter_data_t v_logger_t; 195 196} // local namespace 197 198//____________________________________________________________________________// 199 200BOOST_TEST_SINGLETON_CONS_IMPL( unit_test_log_t ) 201 202void 203unit_test_log_t::configure( ) 204{ 205 // configure is not test_start: 206 // test_start pushes the necessary log information when the test module is starting, and implies configure. 207 // configure: should be called each time the set of loggers, stream or configuration is changed. 208 s_log_impl().m_active_log_formatter_data.clear(); 209 for( unit_test_log_impl::v_formatter_data_t::iterator it(s_log_impl().m_log_formatter_data.begin()), 210 ite(s_log_impl().m_log_formatter_data.end()); 211 it < ite; 212 ++it) 213 { 214 if( !it->m_enabled || it->get_log_level() == log_nothing ) 215 continue; 216 217 s_log_impl().m_active_log_formatter_data.push_back(&*it); 218 it->m_entry_in_progress = false; 219 } 220} 221 222//____________________________________________________________________________// 223 224void 225unit_test_log_t::test_start( counter_t test_cases_amount, test_unit_id ) 226{ 227 configure(); 228 vp_logger_t& vloggers = s_log_impl().m_active_log_formatter_data; 229 for( vp_logger_t::iterator it(vloggers.begin()), ite(vloggers.end()); it < ite; ++it) 230 { 231 unit_test_log_data_helper_impl& current_logger_data = **it; 232 233 current_logger_data.m_log_formatter->log_start( current_logger_data.stream(), test_cases_amount ); 234 current_logger_data.m_log_formatter->log_build_info( 235 current_logger_data.stream(), 236 runtime_config::get<bool>( runtime_config::btrt_build_info )); 237 238 //current_logger_data.stream().flush(); 239 } 240} 241 242//____________________________________________________________________________// 243 244void 245unit_test_log_t::test_finish() 246{ 247 vp_logger_t& vloggers = s_log_impl().m_active_log_formatter_data; 248 for( vp_logger_t::iterator it(vloggers.begin()), ite(vloggers.end()); it < ite; ++it) 249 { 250 unit_test_log_data_helper_impl& current_logger_data = **it; 251 current_logger_data.m_log_formatter->log_finish( current_logger_data.stream() ); 252 current_logger_data.stream().flush(); 253 } 254} 255 256//____________________________________________________________________________// 257 258void 259unit_test_log_t::test_aborted() 260{ 261 BOOST_TEST_LOG_ENTRY( log_messages ) << "Test is aborted"; 262} 263 264//____________________________________________________________________________// 265 266void 267unit_test_log_t::test_unit_start( test_unit const& tu ) 268{ 269 if( s_log_impl().has_entry_in_progress() ) 270 *this << log::end(); 271 272 vp_logger_t& vloggers = s_log_impl().m_active_log_formatter_data; 273 for( vp_logger_t::iterator it(vloggers.begin()), ite(vloggers.end()); it < ite; ++it) 274 { 275 unit_test_log_data_helper_impl& current_logger_data = **it; 276 if( current_logger_data.get_log_level() > log_test_units ) 277 continue; 278 current_logger_data.m_log_formatter->test_unit_start( current_logger_data.stream(), tu ); 279 } 280} 281 282//____________________________________________________________________________// 283 284void 285unit_test_log_t::test_unit_finish( test_unit const& tu, unsigned long elapsed ) 286{ 287 s_log_impl().m_checkpoint_data.clear(); 288 289 if( s_log_impl().has_entry_in_progress() ) 290 *this << log::end(); 291 292 vp_logger_t& vloggers = s_log_impl().m_active_log_formatter_data; 293 for( vp_logger_t::iterator it(vloggers.begin()), ite(vloggers.end()); it < ite; ++it) 294 { 295 unit_test_log_data_helper_impl& current_logger_data = **it; 296 if( current_logger_data.get_log_level() > log_test_units ) 297 continue; 298 299 current_logger_data.m_log_formatter->test_unit_finish( current_logger_data.stream(), tu, elapsed ); 300 } 301} 302 303//____________________________________________________________________________// 304 305void 306unit_test_log_t::test_unit_skipped( test_unit const& tu, const_string reason ) 307{ 308 if( s_log_impl().has_entry_in_progress() ) 309 *this << log::end(); 310 311 vp_logger_t& vloggers = s_log_impl().m_active_log_formatter_data; 312 for( vp_logger_t::iterator it(vloggers.begin()), ite(vloggers.end()); it < ite; ++it) 313 { 314 unit_test_log_data_helper_impl& current_logger_data = **it; 315 if( current_logger_data.get_log_level() > log_test_units ) 316 continue; 317 318 current_logger_data.m_log_formatter->test_unit_skipped( current_logger_data.stream(), tu, reason ); 319 } 320} 321 322void 323unit_test_log_t::test_unit_aborted( test_unit const& tu ) 324{ 325 if( s_log_impl().has_entry_in_progress() ) 326 *this << log::end(); 327 328 vp_logger_t& vloggers = s_log_impl().m_active_log_formatter_data; 329 for( vp_logger_t::iterator it(vloggers.begin()), ite(vloggers.end()); it < ite; ++it) 330 { 331 unit_test_log_data_helper_impl& current_logger_data = **it; 332 if( current_logger_data.get_log_level() > log_test_units ) 333 continue; 334 335 current_logger_data.m_log_formatter->test_unit_aborted(current_logger_data.stream(), tu ); 336 } 337} 338 339void 340unit_test_log_t::test_unit_timed_out( test_unit const& tu ) 341{ 342 if( s_log_impl().has_entry_in_progress() ) 343 *this << log::end(); 344 345 vp_logger_t& vloggers = s_log_impl().m_active_log_formatter_data; 346 for( vp_logger_t::iterator it(vloggers.begin()), ite(vloggers.end()); it < ite; ++it) 347 { 348 unit_test_log_data_helper_impl& current_logger_data = **it; 349 if( current_logger_data.get_log_level() > log_test_units ) 350 continue; 351 352 current_logger_data.m_log_formatter->test_unit_timed_out(current_logger_data.stream(), tu ); 353 } 354} 355 356//____________________________________________________________________________// 357 358void 359unit_test_log_t::exception_caught( execution_exception const& ex ) 360{ 361 log_level l = 362 ex.code() <= execution_exception::cpp_exception_error ? log_cpp_exception_errors : 363 (ex.code() <= execution_exception::timeout_error ? log_system_errors 364 : log_fatal_errors ); 365 366 if( s_log_impl().has_entry_in_progress() ) 367 *this << log::end(); 368 369 vp_logger_t& vloggers = s_log_impl().m_active_log_formatter_data; 370 for( vp_logger_t::iterator it(vloggers.begin()), ite(vloggers.end()); it < ite; ++it) 371 { 372 unit_test_log_data_helper_impl& current_logger_data = **it; 373 374 if( l >= current_logger_data.get_log_level() ) { 375 376 current_logger_data.m_log_formatter->log_exception_start( current_logger_data.stream(), s_log_impl().m_checkpoint_data, ex ); 377 378 log_entry_context( l, current_logger_data ); 379 380 current_logger_data.m_log_formatter->log_exception_finish( current_logger_data.stream() ); 381 } 382 } 383 clear_entry_context(); 384} 385 386//____________________________________________________________________________// 387 388void 389unit_test_log_t::set_checkpoint( const_string file, std::size_t line_num, const_string msg ) 390{ 391 s_log_impl().set_checkpoint( file, line_num, msg ); 392} 393 394//____________________________________________________________________________// 395 396char 397set_unix_slash( char in ) 398{ 399 return in == '\\' ? '/' : in; 400} 401 402unit_test_log_t& 403unit_test_log_t::operator<<( log::begin const& b ) 404{ 405 if( s_log_impl().has_entry_in_progress() ) 406 *this << log::end(); 407 408 vp_logger_t& vloggers = s_log_impl().m_active_log_formatter_data; 409 for( vp_logger_t::iterator it(vloggers.begin()), ite(vloggers.end()); it < ite; ++it) 410 { 411 unit_test_log_data_helper_impl& current_logger_data = **it; 412 current_logger_data.m_stream_state_saver->restore(); 413 } 414 415 s_log_impl().m_entry_data.clear(); 416 417 assign_op( s_log_impl().m_entry_data.m_file_name, b.m_file_name, 0 ); 418 419 // normalize file name 420 std::transform( s_log_impl().m_entry_data.m_file_name.begin(), s_log_impl().m_entry_data.m_file_name.end(), 421 s_log_impl().m_entry_data.m_file_name.begin(), 422 &set_unix_slash ); 423 424 s_log_impl().m_entry_data.m_line_num = b.m_line_num; 425 426 return *this; 427} 428 429//____________________________________________________________________________// 430 431unit_test_log_t& 432unit_test_log_t::operator<<( log::end const& ) 433{ 434 if( s_log_impl().has_entry_in_progress() ) { 435 vp_logger_t& vloggers = s_log_impl().m_active_log_formatter_data; 436 log_level l = s_log_impl().m_entry_data.m_level; 437 for( vp_logger_t::iterator it(vloggers.begin()), ite(vloggers.end()); it < ite; ++it) 438 { 439 unit_test_log_data_helper_impl& current_logger_data = **it; 440 if( current_logger_data.m_entry_in_progress ) { 441 if( l >= current_logger_data.get_log_level() ) { 442 log_entry_context( l, current_logger_data ); 443 } 444 current_logger_data.m_log_formatter->log_entry_finish( current_logger_data.stream() ); 445 } 446 current_logger_data.m_entry_in_progress = false; 447 } 448 } 449 450 clear_entry_context(); 451 452 return *this; 453} 454 455//____________________________________________________________________________// 456 457unit_test_log_t& 458unit_test_log_t::operator<<( log_level l ) 459{ 460 s_log_impl().m_entry_data.m_level = l; 461 462 return *this; 463} 464 465//____________________________________________________________________________// 466 467ut_detail::entry_value_collector 468unit_test_log_t::operator()( log_level l ) 469{ 470 *this << l; 471 472 return ut_detail::entry_value_collector(); 473} 474 475//____________________________________________________________________________// 476 477bool 478log_entry_start(unit_test_log_data_helper_impl ¤t_logger_data) 479{ 480 if( current_logger_data.m_entry_in_progress ) 481 return true; 482 483 switch( s_log_impl().m_entry_data.m_level ) { 484 case log_successful_tests: 485 current_logger_data.m_log_formatter->log_entry_start( current_logger_data.stream(), s_log_impl().m_entry_data, 486 unit_test_log_formatter::BOOST_UTL_ET_INFO ); 487 break; 488 case log_messages: 489 current_logger_data.m_log_formatter->log_entry_start( current_logger_data.stream(), s_log_impl().m_entry_data, 490 unit_test_log_formatter::BOOST_UTL_ET_MESSAGE ); 491 break; 492 case log_warnings: 493 current_logger_data.m_log_formatter->log_entry_start( current_logger_data.stream(), s_log_impl().m_entry_data, 494 unit_test_log_formatter::BOOST_UTL_ET_WARNING ); 495 break; 496 case log_all_errors: 497 case log_cpp_exception_errors: 498 case log_system_errors: 499 current_logger_data.m_log_formatter->log_entry_start( current_logger_data.stream(), s_log_impl().m_entry_data, 500 unit_test_log_formatter::BOOST_UTL_ET_ERROR ); 501 break; 502 case log_fatal_errors: 503 current_logger_data.m_log_formatter->log_entry_start( current_logger_data.stream(), s_log_impl().m_entry_data, 504 unit_test_log_formatter::BOOST_UTL_ET_FATAL_ERROR ); 505 break; 506 case log_nothing: 507 case log_test_units: 508 case invalid_log_level: 509 return false; 510 } 511 512 current_logger_data.m_entry_in_progress = true; 513 return true; 514} 515 516//____________________________________________________________________________// 517 518unit_test_log_t& 519unit_test_log_t::operator<<( const_string value ) 520{ 521 if(value.empty()) { 522 return *this; 523 } 524 525 vp_logger_t& vloggers = s_log_impl().m_active_log_formatter_data; 526 for( vp_logger_t::iterator it(vloggers.begin()), ite(vloggers.end()); it < ite; ++it) 527 { 528 unit_test_log_data_helper_impl& current_logger_data = **it; 529 if( s_log_impl().m_entry_data.m_level >= current_logger_data.get_log_level() ) 530 if( log_entry_start(current_logger_data) ) { 531 current_logger_data.m_log_formatter->log_entry_value( current_logger_data.stream(), value ); 532 } 533 } 534 return *this; 535} 536 537//____________________________________________________________________________// 538 539unit_test_log_t& 540unit_test_log_t::operator<<( lazy_ostream const& value ) 541{ 542 if(value.empty()) { 543 return *this; 544 } 545 546 vp_logger_t& vloggers = s_log_impl().m_active_log_formatter_data; 547 for( vp_logger_t::iterator it(vloggers.begin()), ite(vloggers.end()); it < ite; ++it) 548 { 549 unit_test_log_data_helper_impl& current_logger_data = **it; 550 if( s_log_impl().m_entry_data.m_level >= current_logger_data.get_log_level() ) { 551 if( log_entry_start(current_logger_data) ) { 552 current_logger_data.m_log_formatter->log_entry_value( current_logger_data.stream(), value ); 553 } 554 } 555 } 556 return *this; 557} 558 559//____________________________________________________________________________// 560 561void 562unit_test_log_t::set_stream( std::ostream& str ) 563{ 564 if( s_log_impl().has_entry_in_progress() ) 565 return; 566 567 v_logger_t& vloggers = s_log_impl().m_log_formatter_data; 568 for( v_logger_t::iterator it(vloggers.begin()), ite(vloggers.end()); it < ite; ++it) 569 { 570 unit_test_log_data_helper_impl& current_logger_data = *it; 571 572 current_logger_data.m_stream = &str; 573 current_logger_data.m_stream_state_saver.reset( new io_saver_type( str ) ); 574 } 575} 576 577//____________________________________________________________________________// 578 579void 580unit_test_log_t::set_stream( output_format log_format, std::ostream& str ) 581{ 582 if( s_log_impl().has_entry_in_progress() ) 583 return; 584 585 v_logger_t& vloggers = s_log_impl().m_log_formatter_data; 586 for( v_logger_t::iterator it(vloggers.begin()), ite(vloggers.end()); it < ite; ++it) 587 { 588 unit_test_log_data_helper_impl& current_logger_data = *it; 589 if( current_logger_data.m_format == log_format) { 590 current_logger_data.m_stream = &str; 591 current_logger_data.m_stream_state_saver.reset( new io_saver_type( str ) ); 592 break; 593 } 594 } 595} 596 597std::ostream* 598unit_test_log_t::get_stream( output_format log_format ) const 599{ 600 v_logger_t& vloggers = s_log_impl().m_log_formatter_data; 601 for( v_logger_t::iterator it(vloggers.begin()), ite(vloggers.end()); it < ite; ++it) 602 { 603 unit_test_log_data_helper_impl& current_logger_data = *it; 604 if( current_logger_data.m_format == log_format) { 605 return current_logger_data.m_stream; 606 } 607 } 608 return 0; 609} 610 611//____________________________________________________________________________// 612 613log_level 614unit_test_log_t::set_threshold_level( log_level lev ) 615{ 616 if( s_log_impl().has_entry_in_progress() || lev == invalid_log_level ) 617 return invalid_log_level; 618 619 log_level ret = log_nothing; 620 v_logger_t& vloggers = s_log_impl().m_log_formatter_data; 621 for( v_logger_t::iterator it(vloggers.begin()), ite(vloggers.end()); it < ite; ++it) 622 { 623 unit_test_log_data_helper_impl& current_logger_data = *it; 624 ret = (std::min)(ret, current_logger_data.m_log_formatter->get_log_level()); 625 current_logger_data.m_log_formatter->set_log_level( lev ); 626 } 627 return ret; 628} 629 630//____________________________________________________________________________// 631 632log_level 633unit_test_log_t::set_threshold_level( output_format log_format, log_level lev ) 634{ 635 if( s_log_impl().has_entry_in_progress() || lev == invalid_log_level ) 636 return invalid_log_level; 637 638 log_level ret = log_nothing; 639 v_logger_t& vloggers = s_log_impl().m_log_formatter_data; 640 for( v_logger_t::iterator it(vloggers.begin()), ite(vloggers.end()); it < ite; ++it) 641 { 642 unit_test_log_data_helper_impl& current_logger_data = *it; 643 if( current_logger_data.m_format == log_format) { 644 ret = current_logger_data.m_log_formatter->get_log_level(); 645 current_logger_data.m_log_formatter->set_log_level( lev ); 646 break; 647 } 648 } 649 return ret; 650} 651 652//____________________________________________________________________________// 653 654void 655unit_test_log_t::set_format( output_format log_format ) 656{ 657 if( s_log_impl().has_entry_in_progress() ) 658 return; 659 660 v_logger_t& vloggers = s_log_impl().m_log_formatter_data; 661 for( v_logger_t::iterator it(vloggers.begin()), ite(vloggers.end()); it < ite; ++it) 662 { 663 unit_test_log_data_helper_impl& current_logger_data = *it; 664 current_logger_data.m_enabled = current_logger_data.m_format == log_format; 665 } 666} 667 668//____________________________________________________________________________// 669 670void 671unit_test_log_t::add_format( output_format log_format ) 672{ 673 if( s_log_impl().has_entry_in_progress() ) 674 return; 675 676 v_logger_t& vloggers = s_log_impl().m_log_formatter_data; 677 for( v_logger_t::iterator it(vloggers.begin()), ite(vloggers.end()); it < ite; ++it) 678 { 679 unit_test_log_data_helper_impl& current_logger_data = *it; 680 if( current_logger_data.m_format == log_format) { 681 current_logger_data.m_enabled = true; 682 break; 683 } 684 } 685} 686 687//____________________________________________________________________________// 688 689unit_test_log_formatter* 690unit_test_log_t::get_formatter( output_format log_format ) { 691 692 v_logger_t& vloggers = s_log_impl().m_log_formatter_data; 693 for( v_logger_t::iterator it(vloggers.begin()), ite(vloggers.end()); it < ite; ++it) 694 { 695 unit_test_log_data_helper_impl& current_logger_data = *it; 696 if( current_logger_data.m_format == log_format) { 697 return current_logger_data.m_log_formatter.get(); 698 } 699 } 700 return 0; 701} 702 703 704void 705unit_test_log_t::add_formatter( unit_test_log_formatter* the_formatter ) 706{ 707 // remove only user defined logger 708 v_logger_t& vloggers = s_log_impl().m_log_formatter_data; 709 for(v_logger_t::iterator it(vloggers.begin()), ite(vloggers.end()); it < ite; ++it) 710 { 711 if( it->m_format == OF_CUSTOM_LOGGER) { 712 s_log_impl().m_log_formatter_data.erase(it); 713 break; 714 } 715 } 716 717 if( the_formatter ) { 718 s_log_impl().m_active_log_formatter_data.clear(); // otherwise dandling references 719 vloggers.push_back( unit_test_log_data_helper_impl(the_formatter, OF_CUSTOM_LOGGER, true) ); 720 } 721} 722 723void 724unit_test_log_t::set_formatter( unit_test_log_formatter* the_formatter ) 725{ 726 if( s_log_impl().has_entry_in_progress() ) 727 return; 728 729 // remove only user defined logger 730 log_level current_level = invalid_log_level; 731 std::ostream *current_stream = 0; 732 output_format previous_format = OF_INVALID; 733 v_logger_t& vloggers = s_log_impl().m_log_formatter_data; 734 for(v_logger_t::iterator it(vloggers.begin()), ite(vloggers.end()); it < ite; ++it) 735 { 736 if( it->m_enabled ) { 737 if( current_level == invalid_log_level || it->m_format < previous_format || it->m_format == OF_CUSTOM_LOGGER) { 738 current_level = it->get_log_level(); 739 current_stream = &(it->stream()); 740 previous_format = it->m_format; 741 } 742 } 743 } 744 745 if( the_formatter ) { 746 add_formatter(the_formatter); 747 set_format(OF_CUSTOM_LOGGER); 748 set_threshold_level(OF_CUSTOM_LOGGER, current_level); 749 set_stream(OF_CUSTOM_LOGGER, *current_stream); 750 } 751 752 configure(); 753} 754 755//____________________________________________________________________________// 756 757// ************************************************************************** // 758// ************** unit_test_log_formatter ************** // 759// ************************************************************************** // 760 761void 762unit_test_log_formatter::log_entry_value( std::ostream& ostr, lazy_ostream const& value ) 763{ 764 log_entry_value( ostr, (wrap_stringstream().ref() << value).str() ); 765} 766 767void 768unit_test_log_formatter::set_log_level(log_level new_log_level) 769{ 770 m_log_level = new_log_level; 771} 772 773log_level 774unit_test_log_formatter::get_log_level() const 775{ 776 return m_log_level; 777} 778 779//____________________________________________________________________________// 780 781} // namespace unit_test 782} // namespace boost 783 784#include <boost/test/detail/enable_warnings.hpp> 785 786#endif // BOOST_TEST_UNIT_TEST_LOG_IPP_012205GER 787 788