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