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