blob: c5b7c12f959b16299b18abc4546ffba46e0fc347 [file] [log] [blame]
Jeff Thompsonef2d5a42013-08-22 19:09:24 -07001// (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
Jeff Thompson3d613fd2013-10-15 15:39:04 -070015#ifndef NDNBOOST_TEST_UNIT_TEST_LOG_IPP_012205GER
16#define NDNBOOST_TEST_UNIT_TEST_LOG_IPP_012205GER
Jeff Thompsonef2d5a42013-08-22 19:09:24 -070017
18// Boost.Test
19#include <ndnboost/test/unit_test_log.hpp>
20#include <ndnboost/test/unit_test_log_formatter.hpp>
21#include <ndnboost/test/unit_test_suite_impl.hpp>
22#include <ndnboost/test/execution_monitor.hpp>
23
24#include <ndnboost/test/detail/unit_test_parameters.hpp>
25
26#include <ndnboost/test/utils/basic_cstring/compare.hpp>
27
28#include <ndnboost/test/output/compiler_log_formatter.hpp>
29#include <ndnboost/test/output/xml_log_formatter.hpp>
30
31// Boost
32#include <ndnboost/scoped_ptr.hpp>
33#include <ndnboost/io/ios_state.hpp>
34typedef ::ndnboost::io::ios_base_all_saver io_saver_type;
35
36#include <ndnboost/test/detail/suppress_warnings.hpp>
37
38//____________________________________________________________________________//
39
40namespace ndnboost {
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{
Jeff Thompson3d613fd2013-10-15 15:39:04 -0700161 NDNBOOST_TEST_LOG_ENTRY( log_messages ) << "Test is aborted";
Jeff Thompsonef2d5a42013-08-22 19:09:24 -0700162}
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,
Jeff Thompson3d613fd2013-10-15 15:39:04 -0700324 unit_test_log_formatter::NDNBOOST_UTL_ET_INFO );
Jeff Thompsonef2d5a42013-08-22 19:09:24 -0700325 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,
Jeff Thompson3d613fd2013-10-15 15:39:04 -0700328 unit_test_log_formatter::NDNBOOST_UTL_ET_MESSAGE );
Jeff Thompsonef2d5a42013-08-22 19:09:24 -0700329 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,
Jeff Thompson3d613fd2013-10-15 15:39:04 -0700332 unit_test_log_formatter::NDNBOOST_UTL_ET_WARNING );
Jeff Thompsonef2d5a42013-08-22 19:09:24 -0700333 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,
Jeff Thompson3d613fd2013-10-15 15:39:04 -0700338 unit_test_log_formatter::NDNBOOST_UTL_ET_ERROR );
Jeff Thompsonef2d5a42013-08-22 19:09:24 -0700339 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,
Jeff Thompson3d613fd2013-10-15 15:39:04 -0700342 unit_test_log_formatter::NDNBOOST_UTL_ET_FATAL_ERROR );
Jeff Thompsonef2d5a42013-08-22 19:09:24 -0700343 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 ndnboost
439
440//____________________________________________________________________________//
441
442#include <ndnboost/test/detail/enable_warnings.hpp>
443
Jeff Thompson3d613fd2013-10-15 15:39:04 -0700444#endif // NDNBOOST_TEST_UNIT_TEST_LOG_IPP_012205GER