Imported Upstream version 1.64.0
[platform/upstream/boost.git] / boost / test / impl / unit_test_main.ipp
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 : main function implementation for Unit Test Framework
13 // ***************************************************************************
14
15 #ifndef BOOST_TEST_UNIT_TEST_MAIN_IPP_012205GER
16 #define BOOST_TEST_UNIT_TEST_MAIN_IPP_012205GER
17
18 // Boost.Test
19 #include <boost/test/framework.hpp>
20 #include <boost/test/results_collector.hpp>
21 #include <boost/test/results_reporter.hpp>
22
23 #include <boost/test/tree/visitor.hpp>
24 #include <boost/test/tree/test_unit.hpp>
25 #include <boost/test/tree/traverse.hpp>
26
27 #include <boost/test/unit_test_parameters.hpp>
28
29 #include <boost/test/utils/foreach.hpp>
30 #include <boost/test/utils/basic_cstring/io.hpp>
31
32 // Boost
33 #include <boost/cstdlib.hpp>
34
35 // STL
36 #include <cstdio>
37 #include <stdexcept>
38 #include <iostream>
39 #include <iomanip>
40 #include <set>
41
42 #include <boost/test/detail/suppress_warnings.hpp>
43
44 //____________________________________________________________________________//
45
46 namespace boost {
47 namespace unit_test {
48
49 namespace ut_detail {
50
51 // ************************************************************************** //
52 // **************             hrf_content_reporter             ************** //
53 // ************************************************************************** //
54
55 struct hrf_content_reporter : test_tree_visitor {
56     explicit        hrf_content_reporter( std::ostream& os ) : m_os( os ), m_indent( -4 ) {} // skip master test suite
57
58 private:
59     void            report_test_unit( test_unit const& tu )
60     {
61         m_os << std::setw( m_indent ) << "" << tu.p_name;
62         m_os << (tu.p_default_status == test_unit::RS_ENABLED ? "*" : " ");
63         //m_os << '[' << tu.p_sibling_rank << ']';
64         if( !tu.p_description->empty() )
65             m_os << ": " << tu.p_description;
66
67         m_os << "\n";
68     }
69     virtual void    visit( test_case const& tc ) { report_test_unit( tc ); }
70     virtual bool    test_suite_start( test_suite const& ts )
71     {
72         if( m_indent >= 0 )
73             report_test_unit( ts );
74         m_indent += 4;
75         return true;
76     }
77     virtual void    test_suite_finish( test_suite const& )
78     {
79         m_indent -= 4;
80     }
81
82     // Data members
83     std::ostream&   m_os;
84     int             m_indent;
85 };
86
87 // ************************************************************************** //
88 // **************             dot_content_reporter             ************** //
89 // ************************************************************************** //
90
91 struct dot_content_reporter : test_tree_visitor {
92     explicit        dot_content_reporter( std::ostream& os ) : m_os( os ) {}
93
94 private:
95     void            report_test_unit( test_unit const& tu )
96     {
97         bool master_ts = tu.p_parent_id == INV_TEST_UNIT_ID;
98
99         m_os << "tu" << tu.p_id;
100
101         m_os << (master_ts ? "[shape=ellipse,peripheries=2" : "[shape=Mrecord" );
102
103         m_os << ",fontname=Helvetica";
104
105         m_os << (tu.p_default_status == test_unit::RS_ENABLED ? ",color=green" : ",color=yellow");
106
107         if( master_ts )
108             m_os << ",label=\"" << tu.p_name << "\"];\n";
109         else {
110             m_os << ",label=\"" << tu.p_name << "|" << tu.p_file_name << "(" << tu.p_line_num << ")";
111             if( tu.p_timeout > 0  )
112                 m_os << "|timeout=" << tu.p_timeout;
113             if( tu.p_expected_failures != 0  )
114                 m_os << "|expected failures=" << tu.p_expected_failures;
115             if( !tu.p_labels->empty() ) {
116                 m_os << "|labels:";
117
118                 BOOST_TEST_FOREACH( std::string const&, l, tu.p_labels.get() )
119                     m_os << " @" << l;
120             }
121             m_os << "\"];\n";
122         }
123
124         if( !master_ts )
125             m_os << "tu" << tu.p_parent_id << " -> " << "tu" << tu.p_id << ";\n";
126
127         BOOST_TEST_FOREACH( test_unit_id, dep_id, tu.p_dependencies.get() ) {
128             test_unit const& dep = framework::get( dep_id, TUT_ANY );
129
130             m_os << "tu" << tu.p_id << " -> " << "tu" << dep.p_id << "[color=red,style=dotted,constraint=false];\n";
131         }
132
133     }
134     virtual void    visit( test_case const& tc )
135     { 
136         report_test_unit( tc );
137     }
138     virtual bool    test_suite_start( test_suite const& ts )
139     {
140         if( ts.p_parent_id == INV_TEST_UNIT_ID )
141             m_os << "digraph G {rankdir=LR;\n";
142
143         report_test_unit( ts );
144
145         m_os << "{\n";
146
147         return true;
148     }
149     virtual void    test_suite_finish( test_suite const& ts )
150     {
151         m_os << "}\n";
152         if( ts.p_parent_id == INV_TEST_UNIT_ID )
153             m_os << "}\n";
154     }
155
156     std::ostream&   m_os;
157 };
158
159 // ************************************************************************** //
160 // **************               labels_collector               ************** //
161 // ************************************************************************** //
162
163 struct labels_collector : test_tree_visitor {
164     std::set<std::string> const& labels() const { return m_labels; }
165
166 private:
167     virtual bool            visit( test_unit const& tu ) 
168     {
169         m_labels.insert( tu.p_labels->begin(), tu.p_labels->end() );
170         return true;
171     }
172
173     // Data members
174     std::set<std::string>   m_labels;
175 };
176
177 } // namespace ut_detail
178
179 // ************************************************************************** //
180 // **************                  unit_test_main              ************** //
181 // ************************************************************************** //
182
183 int BOOST_TEST_DECL
184 unit_test_main( init_unit_test_func init_func, int argc, char* argv[] )
185 {
186     int result_code = 0;
187
188     BOOST_TEST_I_TRY {
189         framework::init( init_func, argc, argv );
190
191         if( runtime_config::get<bool>( runtime_config::btrt_wait_for_debugger ) ) {
192             results_reporter::get_stream() << "Press any key to continue..." << std::endl;
193
194             // getchar is defined as a macro in uClibc. Use parenthesis to fix
195             // gcc bug 58952 for gcc <= 4.8.2.
196             (std::getchar)();
197             results_reporter::get_stream() << "Continuing..." << std::endl;
198         }
199
200         framework::finalize_setup_phase();
201
202         output_format list_cont = runtime_config::get<output_format>( runtime_config::btrt_list_content );
203         if( list_cont != unit_test::OF_INVALID ) {
204             if( list_cont == unit_test::OF_DOT ) {
205                 ut_detail::dot_content_reporter reporter( results_reporter::get_stream() );
206
207                 traverse_test_tree( framework::master_test_suite().p_id, reporter, true );
208             }
209             else {
210                 ut_detail::hrf_content_reporter reporter( results_reporter::get_stream() );
211
212                 traverse_test_tree( framework::master_test_suite().p_id, reporter, true );
213             }
214
215             return boost::exit_success;
216         }
217
218         if( runtime_config::get<bool>( runtime_config::btrt_list_labels ) ) {
219             ut_detail::labels_collector collector;
220
221             traverse_test_tree( framework::master_test_suite().p_id, collector, true );
222
223             results_reporter::get_stream() << "Available labels:\n  ";
224             std::copy( collector.labels().begin(), collector.labels().end(), 
225                        std::ostream_iterator<std::string>( results_reporter::get_stream(), "\n  " ) );
226             results_reporter::get_stream() << "\n";
227
228             return boost::exit_success;
229         }
230
231         framework::run();
232
233         results_reporter::make_report();
234
235         result_code = !runtime_config::get<bool>( runtime_config::btrt_result_code )
236                         ? boost::exit_success
237                         : results_collector.results( framework::master_test_suite().p_id ).result_code();
238     }
239     BOOST_TEST_I_CATCH( framework::nothing_to_test, ex ) {
240         result_code = ex.m_result_code;
241     }
242     BOOST_TEST_I_CATCH( framework::internal_error, ex ) {
243         results_reporter::get_stream() << "Boost.Test framework internal error: " << ex.what() << std::endl;
244
245         result_code = boost::exit_exception_failure;
246     }
247     BOOST_TEST_I_CATCH( framework::setup_error, ex ) {
248         results_reporter::get_stream() << "Test setup error: " << ex.what() << std::endl;
249
250         result_code = boost::exit_exception_failure;
251     }
252     BOOST_TEST_I_CATCHALL() {
253         results_reporter::get_stream() << "Boost.Test framework internal error: unknown reason" << std::endl;
254
255         result_code = boost::exit_exception_failure;
256     }
257
258     framework::shutdown();
259
260     return result_code;
261 }
262
263 } // namespace unit_test
264 } // namespace boost
265
266 #if !defined(BOOST_TEST_DYN_LINK) && !defined(BOOST_TEST_NO_MAIN)
267
268 // ************************************************************************** //
269 // **************        main function for tests using lib     ************** //
270 // ************************************************************************** //
271
272 int BOOST_TEST_CALL_DECL
273 main( int argc, char* argv[] )
274 {
275     // prototype for user's unit test init function
276 #ifdef BOOST_TEST_ALTERNATIVE_INIT_API
277     extern bool init_unit_test();
278
279     boost::unit_test::init_unit_test_func init_func = &init_unit_test;
280 #else
281     extern ::boost::unit_test::test_suite* init_unit_test_suite( int argc, char* argv[] );
282
283     boost::unit_test::init_unit_test_func init_func = &init_unit_test_suite;
284 #endif
285
286     return ::boost::unit_test::unit_test_main( init_func, argc, argv );
287 }
288
289 #endif // !BOOST_TEST_DYN_LINK && !BOOST_TEST_NO_MAIN
290
291 //____________________________________________________________________________//
292
293 #include <boost/test/detail/enable_warnings.hpp>
294
295 #endif // BOOST_TEST_UNIT_TEST_MAIN_IPP_012205GER