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> |
35 | typedef ::boost::io::ios_base_all_saver io_saver_type; |
36 | |
37 | #include <boost/test/detail/suppress_warnings.hpp> |
38 | |
39 | //____________________________________________________________________________// |
40 | |
41 | namespace boost { |
42 | namespace unit_test { |
43 | |
44 | // ************************************************************************** // |
45 | // ************** entry_value_collector ************** // |
46 | // ************************************************************************** // |
47 | |
48 | namespace ut_detail { |
49 | |
50 | entry_value_collector const& |
51 | entry_value_collector::operator<<( lazy_ostream const& v ) const |
52 | { |
53 | unit_test_log << v; |
54 | |
55 | return *this; |
56 | } |
57 | |
58 | //____________________________________________________________________________// |
59 | |
60 | entry_value_collector const& |
61 | entry_value_collector::operator<<( const_string v ) const |
62 | { |
63 | unit_test_log << v; |
64 | |
65 | return *this; |
66 | } |
67 | |
68 | //____________________________________________________________________________// |
69 | |
70 | entry_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 | |
84 | namespace { |
85 | |
86 | // log data |
87 | struct 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: 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 | |
122 | struct unit_test_log_impl { |
123 | // Constructor |
124 | unit_test_log_impl() |
125 | { |
126 | m_log_formatter_data.push_back( x: 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( x: unit_test_log_data_helper_impl(new output::xml_log_formatter, OF_XML, false) ); |
128 | m_log_formatter_data.push_back( x: 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( target&: m_checkpoint_data.m_message, src: msg, 0 ); |
158 | m_checkpoint_data.m_file_name = file; |
159 | m_checkpoint_data.m_line_num = line_num; |
160 | } |
161 | }; |
162 | |
163 | unit_test_log_impl& s_log_impl() { static unit_test_log_impl the_inst; return the_inst; } |
164 | |
165 | |
166 | //____________________________________________________________________________// |
167 | |
168 | void |
169 | log_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( os&: current_logger_data.stream(), l ); |
177 | while( !(frame=context.next()).is_empty() ) |
178 | { |
179 | current_logger_data.m_log_formatter->log_entry_context( os&: current_logger_data.stream(), l, value: frame ); |
180 | } |
181 | current_logger_data.m_log_formatter->entry_context_finish( os&: current_logger_data.stream(), l ); |
182 | } |
183 | |
184 | //____________________________________________________________________________// |
185 | |
186 | void |
187 | clear_entry_context() |
188 | { |
189 | framework::clear_context(); |
190 | } |
191 | |
192 | // convenience |
193 | typedef unit_test_log_impl::vp_formatter_data_t vp_logger_t; |
194 | typedef unit_test_log_impl::v_formatter_data_t v_logger_t; |
195 | |
196 | } // local namespace |
197 | |
198 | //____________________________________________________________________________// |
199 | |
200 | BOOST_TEST_SINGLETON_CONS_IMPL( unit_test_log_t ) |
201 | |
202 | void |
203 | unit_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(x: &*it); |
218 | it->m_entry_in_progress = false; |
219 | } |
220 | } |
221 | |
222 | //____________________________________________________________________________// |
223 | |
224 | void |
225 | unit_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( os&: current_logger_data.stream(), test_cases_amount ); |
234 | current_logger_data.m_log_formatter->log_build_info( |
235 | os&: current_logger_data.stream(), |
236 | log_build_info: runtime_config::get<bool>( parameter_name: runtime_config::btrt_build_info )); |
237 | |
238 | //current_logger_data.stream().flush(); |
239 | } |
240 | } |
241 | |
242 | //____________________________________________________________________________// |
243 | |
244 | void |
245 | unit_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( os&: current_logger_data.stream() ); |
252 | current_logger_data.stream().flush(); |
253 | } |
254 | } |
255 | |
256 | //____________________________________________________________________________// |
257 | |
258 | void |
259 | unit_test_log_t::test_aborted() |
260 | { |
261 | BOOST_TEST_LOG_ENTRY( log_messages ) << "Test is aborted" ; |
262 | } |
263 | |
264 | //____________________________________________________________________________// |
265 | |
266 | void |
267 | unit_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( os&: current_logger_data.stream(), tu ); |
279 | } |
280 | } |
281 | |
282 | //____________________________________________________________________________// |
283 | |
284 | void |
285 | unit_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( os&: current_logger_data.stream(), tu, elapsed ); |
300 | } |
301 | } |
302 | |
303 | //____________________________________________________________________________// |
304 | |
305 | void |
306 | unit_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( os&: current_logger_data.stream(), tu, reason ); |
319 | } |
320 | } |
321 | |
322 | void |
323 | unit_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 | |
339 | void |
340 | unit_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 | |
358 | void |
359 | unit_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( os&: current_logger_data.stream(), lcd: 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( os&: current_logger_data.stream() ); |
381 | } |
382 | } |
383 | clear_entry_context(); |
384 | } |
385 | |
386 | //____________________________________________________________________________// |
387 | |
388 | void |
389 | unit_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 | |
396 | char |
397 | set_unix_slash( char in ) |
398 | { |
399 | return in == '\\' ? '/' : in; |
400 | } |
401 | |
402 | unit_test_log_t& |
403 | unit_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( target&: s_log_impl().m_entry_data.m_file_name, src: b.m_file_name, 0 ); |
418 | |
419 | // normalize file name |
420 | std::transform( first: s_log_impl().m_entry_data.m_file_name.begin(), last: s_log_impl().m_entry_data.m_file_name.end(), |
421 | result: s_log_impl().m_entry_data.m_file_name.begin(), |
422 | unary_op: &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 | |
431 | unit_test_log_t& |
432 | unit_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( os&: 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 | |
457 | unit_test_log_t& |
458 | unit_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 | |
467 | ut_detail::entry_value_collector |
468 | unit_test_log_t::operator()( log_level l ) |
469 | { |
470 | *this << l; |
471 | |
472 | return ut_detail::entry_value_collector(); |
473 | } |
474 | |
475 | //____________________________________________________________________________// |
476 | |
477 | bool |
478 | log_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( os&: current_logger_data.stream(), led: s_log_impl().m_entry_data, |
486 | let: unit_test_log_formatter::BOOST_UTL_ET_INFO ); |
487 | break; |
488 | case log_messages: |
489 | current_logger_data.m_log_formatter->log_entry_start( os&: current_logger_data.stream(), led: s_log_impl().m_entry_data, |
490 | let: unit_test_log_formatter::BOOST_UTL_ET_MESSAGE ); |
491 | break; |
492 | case log_warnings: |
493 | current_logger_data.m_log_formatter->log_entry_start( os&: current_logger_data.stream(), led: s_log_impl().m_entry_data, |
494 | let: 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( os&: current_logger_data.stream(), led: s_log_impl().m_entry_data, |
500 | let: 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( os&: current_logger_data.stream(), led: s_log_impl().m_entry_data, |
504 | let: 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 | |
518 | unit_test_log_t& |
519 | unit_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( os&: current_logger_data.stream(), value ); |
532 | } |
533 | } |
534 | return *this; |
535 | } |
536 | |
537 | //____________________________________________________________________________// |
538 | |
539 | unit_test_log_t& |
540 | unit_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( os&: current_logger_data.stream(), value ); |
553 | } |
554 | } |
555 | } |
556 | return *this; |
557 | } |
558 | |
559 | //____________________________________________________________________________// |
560 | |
561 | void |
562 | unit_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( p: new io_saver_type( str ) ); |
574 | } |
575 | } |
576 | |
577 | //____________________________________________________________________________// |
578 | |
579 | void |
580 | unit_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( p: new io_saver_type( str ) ); |
592 | break; |
593 | } |
594 | } |
595 | } |
596 | |
597 | std::ostream* |
598 | unit_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 | |
613 | log_level |
614 | unit_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)(a: ret, b: 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 | |
632 | log_level |
633 | unit_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 | |
654 | void |
655 | unit_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 | |
670 | void |
671 | unit_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 | |
689 | unit_test_log_formatter* |
690 | unit_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 | |
704 | void |
705 | unit_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(position: 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( x: unit_test_log_data_helper_impl(the_formatter, OF_CUSTOM_LOGGER, true) ); |
720 | } |
721 | } |
722 | |
723 | void |
724 | unit_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(log_format: OF_CUSTOM_LOGGER, lev: current_level); |
749 | set_stream(log_format: OF_CUSTOM_LOGGER, str&: *current_stream); |
750 | } |
751 | |
752 | configure(); |
753 | } |
754 | |
755 | //____________________________________________________________________________// |
756 | |
757 | // ************************************************************************** // |
758 | // ************** unit_test_log_formatter ************** // |
759 | // ************************************************************************** // |
760 | |
761 | void |
762 | unit_test_log_formatter::log_entry_value( std::ostream& ostr, lazy_ostream const& value ) |
763 | { |
764 | log_entry_value( os&: ostr, value: (wrap_stringstream().ref() << value).str() ); |
765 | } |
766 | |
767 | void |
768 | unit_test_log_formatter::set_log_level(log_level new_log_level) |
769 | { |
770 | m_log_level = new_log_level; |
771 | } |
772 | |
773 | log_level |
774 | unit_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 | |