1// (C) Copyright Gennadiy Rozental 2005-2008. 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: 57992 $ 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/unit_test_suite_impl.hpp> 22#include <boost/test/execution_monitor.hpp> 23 24#include <boost/test/detail/unit_test_parameters.hpp> 25 26#include <boost/test/utils/basic_cstring/compare.hpp> 27 28#include <boost/test/output/compiler_log_formatter.hpp> 29#include <boost/test/output/xml_log_formatter.hpp> 30 31// Boost 32#include <boost/scoped_ptr.hpp> 33#include <boost/io/ios_state.hpp> 34typedef ::boost::io::ios_base_all_saver io_saver_type; 35 36#include <boost/test/detail/suppress_warnings.hpp> 37 38//____________________________________________________________________________// 39 40namespace boost { 41 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 86struct unit_test_log_impl { 87 // Constructor 88 unit_test_log_impl() 89 : m_stream( runtime_config::log_sink() ) 90 , m_stream_state_saver( new io_saver_type( *m_stream ) ) 91 , m_threshold_level( log_all_errors ) 92 , m_log_formatter( new output::compiler_log_formatter ) 93 { 94 } 95 96 // log data 97 typedef scoped_ptr<unit_test_log_formatter> formatter_ptr; 98 typedef scoped_ptr<io_saver_type> saver_ptr; 99 100 std::ostream* m_stream; 101 saver_ptr m_stream_state_saver; 102 log_level m_threshold_level; 103 formatter_ptr m_log_formatter; 104 105 // entry data 106 bool m_entry_in_progress; 107 bool m_entry_started; 108 log_entry_data m_entry_data; 109 110 // check point data 111 log_checkpoint_data m_checkpoint_data; 112 113 // helper functions 114 std::ostream& stream() { return *m_stream; } 115 void set_checkpoint( const_string file, std::size_t line_num, const_string msg ) 116 { 117 assign_op( m_checkpoint_data.m_message, msg, 0 ); 118 m_checkpoint_data.m_file_name = file; 119 m_checkpoint_data.m_line_num = line_num; 120 } 121}; 122 123unit_test_log_impl& s_log_impl() { static unit_test_log_impl the_inst; return the_inst; } 124 125} // local namespace 126 127//____________________________________________________________________________// 128 129void 130unit_test_log_t::test_start( counter_t test_cases_amount ) 131{ 132 if( s_log_impl().m_threshold_level == log_nothing ) 133 return; 134 135 s_log_impl().m_log_formatter->log_start( s_log_impl().stream(), test_cases_amount ); 136 137 if( runtime_config::show_build_info() ) 138 s_log_impl().m_log_formatter->log_build_info( s_log_impl().stream() ); 139 140 s_log_impl().m_entry_in_progress = false; 141} 142 143//____________________________________________________________________________// 144 145void 146unit_test_log_t::test_finish() 147{ 148 if( s_log_impl().m_threshold_level == log_nothing ) 149 return; 150 151 s_log_impl().m_log_formatter->log_finish( s_log_impl().stream() ); 152 153 s_log_impl().stream().flush(); 154} 155 156//____________________________________________________________________________// 157 158void 159unit_test_log_t::test_aborted() 160{ 161 BOOST_TEST_LOG_ENTRY( log_messages ) << "Test is aborted"; 162} 163 164//____________________________________________________________________________// 165 166void 167unit_test_log_t::test_unit_start( test_unit const& tu ) 168{ 169 if( s_log_impl().m_threshold_level > log_test_units ) 170 return; 171 172 if( s_log_impl().m_entry_in_progress ) 173 *this << log::end(); 174 175 s_log_impl().m_log_formatter->test_unit_start( s_log_impl().stream(), tu ); 176} 177 178//____________________________________________________________________________// 179 180void 181unit_test_log_t::test_unit_finish( test_unit const& tu, unsigned long elapsed ) 182{ 183 if( s_log_impl().m_threshold_level > log_test_units ) 184 return; 185 186 s_log_impl().m_checkpoint_data.clear(); 187 188 if( s_log_impl().m_entry_in_progress ) 189 *this << log::end(); 190 191 s_log_impl().m_log_formatter->test_unit_finish( s_log_impl().stream(), tu, elapsed ); 192} 193 194//____________________________________________________________________________// 195 196void 197unit_test_log_t::test_unit_skipped( test_unit const& tu ) 198{ 199 if( s_log_impl().m_threshold_level > log_test_units ) 200 return; 201 202 if( s_log_impl().m_entry_in_progress ) 203 *this << log::end(); 204 205 s_log_impl().m_log_formatter->test_unit_skipped( s_log_impl().stream(), tu ); 206} 207 208//____________________________________________________________________________// 209 210void 211unit_test_log_t::test_unit_aborted( test_unit const& ) 212{ 213 // do nothing 214} 215 216//____________________________________________________________________________// 217 218void 219unit_test_log_t::assertion_result( bool ) 220{ 221 // do nothing 222} 223 224//____________________________________________________________________________// 225 226void 227unit_test_log_t::exception_caught( execution_exception const& ex ) 228{ 229 log_level l = 230 ex.code() <= execution_exception::cpp_exception_error ? log_cpp_exception_errors : 231 (ex.code() <= execution_exception::timeout_error ? log_system_errors 232 : log_fatal_errors ); 233 234 if( l >= s_log_impl().m_threshold_level ) { 235 if( s_log_impl().m_entry_in_progress ) 236 *this << log::end(); 237 238 s_log_impl().m_log_formatter->log_exception( s_log_impl().stream(), s_log_impl().m_checkpoint_data, ex ); 239 } 240} 241 242//____________________________________________________________________________// 243 244void 245unit_test_log_t::set_checkpoint( const_string file, std::size_t line_num, const_string msg ) 246{ 247 s_log_impl().set_checkpoint( file, line_num, msg ); 248} 249 250//____________________________________________________________________________// 251 252char 253set_unix_slash( char in ) 254{ 255 return in == '\\' ? '/' : in; 256} 257 258unit_test_log_t& 259unit_test_log_t::operator<<( log::begin const& b ) 260{ 261 if( s_log_impl().m_entry_in_progress ) 262 *this << log::end(); 263 264 s_log_impl().m_stream_state_saver->restore(); 265 266 s_log_impl().m_entry_data.clear(); 267 268 assign_op( s_log_impl().m_entry_data.m_file_name, b.m_file_name, 0 ); 269 270 // normalize file name 271 std::transform( s_log_impl().m_entry_data.m_file_name.begin(), s_log_impl().m_entry_data.m_file_name.end(), 272 s_log_impl().m_entry_data.m_file_name.begin(), 273 &set_unix_slash ); 274 275 s_log_impl().m_entry_data.m_line_num = b.m_line_num; 276 277 return *this; 278} 279 280//____________________________________________________________________________// 281 282unit_test_log_t& 283unit_test_log_t::operator<<( log::end const& ) 284{ 285 if( s_log_impl().m_entry_in_progress ) 286 s_log_impl().m_log_formatter->log_entry_finish( s_log_impl().stream() ); 287 288 s_log_impl().m_entry_in_progress = false; 289 290 return *this; 291} 292 293//____________________________________________________________________________// 294 295unit_test_log_t& 296unit_test_log_t::operator<<( log_level l ) 297{ 298 s_log_impl().m_entry_data.m_level = l; 299 300 return *this; 301} 302 303//____________________________________________________________________________// 304 305ut_detail::entry_value_collector 306unit_test_log_t::operator()( log_level l ) 307{ 308 *this << l; 309 310 return ut_detail::entry_value_collector(); 311} 312 313//____________________________________________________________________________// 314 315bool 316unit_test_log_t::log_entry_start() 317{ 318 if( s_log_impl().m_entry_in_progress ) 319 return true; 320 321 switch( s_log_impl().m_entry_data.m_level ) { 322 case log_successful_tests: 323 s_log_impl().m_log_formatter->log_entry_start( s_log_impl().stream(), s_log_impl().m_entry_data, 324 unit_test_log_formatter::BOOST_UTL_ET_INFO ); 325 break; 326 case log_messages: 327 s_log_impl().m_log_formatter->log_entry_start( s_log_impl().stream(), s_log_impl().m_entry_data, 328 unit_test_log_formatter::BOOST_UTL_ET_MESSAGE ); 329 break; 330 case log_warnings: 331 s_log_impl().m_log_formatter->log_entry_start( s_log_impl().stream(), s_log_impl().m_entry_data, 332 unit_test_log_formatter::BOOST_UTL_ET_WARNING ); 333 break; 334 case log_all_errors: 335 case log_cpp_exception_errors: 336 case log_system_errors: 337 s_log_impl().m_log_formatter->log_entry_start( s_log_impl().stream(), s_log_impl().m_entry_data, 338 unit_test_log_formatter::BOOST_UTL_ET_ERROR ); 339 break; 340 case log_fatal_errors: 341 s_log_impl().m_log_formatter->log_entry_start( s_log_impl().stream(), s_log_impl().m_entry_data, 342 unit_test_log_formatter::BOOST_UTL_ET_FATAL_ERROR ); 343 break; 344 case log_nothing: 345 case log_test_units: 346 case invalid_log_level: 347 return false; 348 } 349 350 s_log_impl().m_entry_in_progress = true; 351 352 return true; 353} 354 355//____________________________________________________________________________// 356 357unit_test_log_t& 358unit_test_log_t::operator<<( const_string value ) 359{ 360 if( s_log_impl().m_entry_data.m_level >= s_log_impl().m_threshold_level && !value.empty() && log_entry_start() ) 361 s_log_impl().m_log_formatter->log_entry_value( s_log_impl().stream(), value ); 362 363 return *this; 364} 365 366//____________________________________________________________________________// 367 368unit_test_log_t& 369unit_test_log_t::operator<<( lazy_ostream const& value ) 370{ 371 if( s_log_impl().m_entry_data.m_level >= s_log_impl().m_threshold_level && !value.empty() && log_entry_start() ) 372 s_log_impl().m_log_formatter->log_entry_value( s_log_impl().stream(), value ); 373 374 return *this; 375} 376 377//____________________________________________________________________________// 378 379void 380unit_test_log_t::set_stream( std::ostream& str ) 381{ 382 if( s_log_impl().m_entry_in_progress ) 383 return; 384 385 s_log_impl().m_stream = &str; 386 s_log_impl().m_stream_state_saver.reset( new io_saver_type( str ) ); 387} 388 389//____________________________________________________________________________// 390 391void 392unit_test_log_t::set_threshold_level( log_level lev ) 393{ 394 if( s_log_impl().m_entry_in_progress || lev == invalid_log_level ) 395 return; 396 397 s_log_impl().m_threshold_level = lev; 398} 399 400//____________________________________________________________________________// 401 402void 403unit_test_log_t::set_format( output_format log_format ) 404{ 405 if( s_log_impl().m_entry_in_progress ) 406 return; 407 408 if( log_format == CLF ) 409 set_formatter( new output::compiler_log_formatter ); 410 else 411 set_formatter( new output::xml_log_formatter ); 412} 413 414//____________________________________________________________________________// 415 416void 417unit_test_log_t::set_formatter( unit_test_log_formatter* the_formatter ) 418{ 419 s_log_impl().m_log_formatter.reset( the_formatter ); 420} 421 422//____________________________________________________________________________// 423 424// ************************************************************************** // 425// ************** unit_test_log_formatter ************** // 426// ************************************************************************** // 427 428void 429unit_test_log_formatter::log_entry_value( std::ostream& ostr, lazy_ostream const& value ) 430{ 431 log_entry_value( ostr, (wrap_stringstream().ref() << value).str() ); 432} 433 434//____________________________________________________________________________// 435 436} // namespace unit_test 437 438} // namespace boost 439 440//____________________________________________________________________________// 441 442#include <boost/test/detail/enable_warnings.hpp> 443 444#endif // BOOST_TEST_UNIT_TEST_LOG_IPP_012205GER 445