1//  (C) Copyright Gennadiy Rozental 2005-2014.
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 : implements compiler like Log formatter
13// ***************************************************************************
14
15#ifndef BOOST_TEST_COMPILER_LOG_FORMATTER_IPP_020105GER
16#define BOOST_TEST_COMPILER_LOG_FORMATTER_IPP_020105GER
17
18// Boost.Test
19#include <boost/test/framework.hpp>
20#include <boost/test/execution_monitor.hpp>
21#include <boost/test/tree/test_unit.hpp>
22#include <boost/test/utils/basic_cstring/io.hpp>
23#include <boost/test/utils/lazy_ostream.hpp>
24#include <boost/test/utils/setcolor.hpp>
25#include <boost/test/output/compiler_log_formatter.hpp>
26#include <boost/test/unit_test_parameters.hpp>
27
28// Boost
29#include <boost/version.hpp>
30
31// STL
32#include <iostream>
33
34#include <boost/test/detail/suppress_warnings.hpp>
35
36//____________________________________________________________________________//
37
38namespace boost {
39namespace unit_test {
40namespace output {
41
42// ************************************************************************** //
43// **************            compiler_log_formatter            ************** //
44// ************************************************************************** //
45
46namespace {
47
48std::string
49test_phase_identifier()
50{
51    return framework::test_in_progress() ? framework::current_test_case().full_name() : std::string( "Test setup" );
52}
53
54} // local namespace
55
56//____________________________________________________________________________//
57
58void
59compiler_log_formatter::log_start( std::ostream& output, counter_t test_cases_amount )
60{
61    if( test_cases_amount > 0 )
62        output  << "Running " << test_cases_amount << " test "
63                << (test_cases_amount > 1 ? "cases" : "case") << "...\n";
64}
65
66//____________________________________________________________________________//
67
68void
69compiler_log_formatter::log_finish( std::ostream& ostr )
70{
71    ostr.flush();
72}
73
74//____________________________________________________________________________//
75
76void
77compiler_log_formatter::log_build_info( std::ostream& output )
78{
79    output  << "Platform: " << BOOST_PLATFORM            << '\n'
80            << "Compiler: " << BOOST_COMPILER            << '\n'
81            << "STL     : " << BOOST_STDLIB              << '\n'
82            << "Boost   : " << BOOST_VERSION/100000      << "."
83                            << BOOST_VERSION/100 % 1000  << "."
84                            << BOOST_VERSION % 100       << std::endl;
85}
86
87//____________________________________________________________________________//
88
89void
90compiler_log_formatter::test_unit_start( std::ostream& output, test_unit const& tu )
91{
92    BOOST_TEST_SCOPE_SETCOLOR( output, term_attr::BRIGHT, term_color::BLUE );
93
94    print_prefix( output, tu.p_file_name, tu.p_line_num );
95
96    output << "Entering test " << tu.p_type_name << " \"" << tu.p_name << "\"" << std::endl;
97}
98
99//____________________________________________________________________________//
100
101void
102compiler_log_formatter::test_unit_finish( std::ostream& output, test_unit const& tu, unsigned long elapsed )
103{
104    BOOST_TEST_SCOPE_SETCOLOR( output, term_attr::BRIGHT, term_color::BLUE );
105
106    print_prefix( output, tu.p_file_name, tu.p_line_num );
107
108    output << "Leaving test " << tu.p_type_name << " \"" << tu.p_name << "\"";
109
110    if( elapsed > 0 ) {
111        output << "; testing time: ";
112        if( elapsed % 1000 == 0 )
113            output << elapsed/1000 << "ms";
114        else
115            output << elapsed << "us";
116    }
117
118    output << std::endl;
119}
120
121//____________________________________________________________________________//
122
123void
124compiler_log_formatter::test_unit_skipped( std::ostream& output, test_unit const& tu, const_string reason )
125{
126    BOOST_TEST_SCOPE_SETCOLOR( output, term_attr::BRIGHT, term_color::YELLOW );
127
128    print_prefix( output, tu.p_file_name, tu.p_line_num );
129
130    output  << "Test " << tu.p_type_name << " \"" << tu.full_name() << "\"" << " is skipped because " << reason << std::endl;
131}
132
133//____________________________________________________________________________//
134
135void
136compiler_log_formatter::log_exception_start( std::ostream& output, log_checkpoint_data const& checkpoint_data, execution_exception const& ex )
137{
138    execution_exception::location const& loc = ex.where();
139
140    print_prefix( output, loc.m_file_name, loc.m_line_num );
141
142    {
143        BOOST_TEST_SCOPE_SETCOLOR( output, term_attr::BLINK, term_color::RED );
144
145        output << "fatal error: in \"" << (loc.m_function.is_empty() ? test_phase_identifier() : loc.m_function ) << "\": "
146               << ex.what();
147    }
148
149    if( !checkpoint_data.m_file_name.is_empty() ) {
150        output << '\n';
151        print_prefix( output, checkpoint_data.m_file_name, checkpoint_data.m_line_num );
152
153        BOOST_TEST_SCOPE_SETCOLOR( output, term_attr::BRIGHT, term_color::CYAN );
154
155        output << "last checkpoint";
156        if( !checkpoint_data.m_message.empty() )
157            output << ": " << checkpoint_data.m_message;
158    }
159}
160
161//____________________________________________________________________________//
162
163void
164compiler_log_formatter::log_exception_finish( std::ostream& output )
165{
166    output << std::endl;
167}
168
169//____________________________________________________________________________//
170
171void
172compiler_log_formatter::log_entry_start( std::ostream& output, log_entry_data const& entry_data, log_entry_types let )
173{
174    switch( let ) {
175        case BOOST_UTL_ET_INFO:
176            print_prefix( output, entry_data.m_file_name, entry_data.m_line_num );
177            if( runtime_config::color_output() )
178                output << setcolor( term_attr::BRIGHT, term_color::GREEN );
179            output << "info: ";
180            break;
181        case BOOST_UTL_ET_MESSAGE:
182            if( runtime_config::color_output() )
183                output << setcolor( term_attr::BRIGHT, term_color::CYAN );
184            break;
185        case BOOST_UTL_ET_WARNING:
186            print_prefix( output, entry_data.m_file_name, entry_data.m_line_num );
187            if( runtime_config::color_output() )
188                output << setcolor( term_attr::BRIGHT, term_color::YELLOW );
189            output << "warning: in \"" << test_phase_identifier() << "\": ";
190            break;
191        case BOOST_UTL_ET_ERROR:
192            print_prefix( output, entry_data.m_file_name, entry_data.m_line_num );
193            if( runtime_config::color_output() )
194                output << setcolor( term_attr::BRIGHT, term_color::RED );
195            output << "error: in \"" << test_phase_identifier() << "\": ";
196            break;
197        case BOOST_UTL_ET_FATAL_ERROR:
198            print_prefix( output, entry_data.m_file_name, entry_data.m_line_num );
199            if( runtime_config::color_output() )
200                output << setcolor( term_attr::BLINK, term_color::RED );
201            output << "fatal error: in \"" << test_phase_identifier() << "\": ";
202            break;
203    }
204}
205
206//____________________________________________________________________________//
207
208void
209compiler_log_formatter::log_entry_value( std::ostream& output, const_string value )
210{
211    output << value;
212}
213
214//____________________________________________________________________________//
215
216void
217compiler_log_formatter::log_entry_value( std::ostream& output, lazy_ostream const& value )
218{
219    output << value;
220}
221
222//____________________________________________________________________________//
223
224void
225compiler_log_formatter::log_entry_finish( std::ostream& output )
226{
227    if( runtime_config::color_output() )
228        output << setcolor();
229
230    output << std::endl;
231}
232
233
234//____________________________________________________________________________//
235
236void
237compiler_log_formatter::print_prefix( std::ostream& output, const_string file_name, std::size_t line_num )
238{
239    if( !file_name.empty() )
240    {
241#ifdef __APPLE_CC__
242        // Xcode-compatible logging format, idea by Richard Dingwall at
243        // <http://richarddingwall.name/2008/06/01/using-the-boost-unit-test-framework-with-xcode-3/>.
244        output << file_name << ':' << line_num << ": ";
245#else
246        output << file_name << '(' << line_num << "): ";
247#endif
248    }
249}
250
251//____________________________________________________________________________//
252
253void
254compiler_log_formatter::entry_context_start( std::ostream& output, log_level l )
255{
256    output << (l == log_successful_tests ? "\nAssertion" : "\nFailure" ) << " occurred in a following context:";
257}
258
259//____________________________________________________________________________//
260
261void
262compiler_log_formatter::entry_context_finish( std::ostream& output )
263{
264    output.flush();
265}
266
267//____________________________________________________________________________//
268
269void
270compiler_log_formatter::log_entry_context( std::ostream& output, const_string context_descr )
271{
272    output << "\n    " << context_descr;
273}
274
275//____________________________________________________________________________//
276
277} // namespace output
278} // namespace unit_test
279} // namespace boost
280
281#include <boost/test/detail/enable_warnings.hpp>
282
283#endif // BOOST_TEST_COMPILER_LOG_FORMATTER_IPP_020105GER
284