1//  (C) Copyright Gennadiy Rozental 2001-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: 54633 $
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/unit_test_suite_impl.hpp>
22#include <boost/test/results_reporter.hpp>
23
24#include <boost/test/detail/unit_test_parameters.hpp>
25
26#if !defined(__BORLANDC__) && !BOOST_WORKAROUND( BOOST_MSVC, < 1300 ) && !BOOST_WORKAROUND( __SUNPRO_CC, < 0x5100 )
27#define BOOST_TEST_SUPPORT_RUN_BY_NAME
28#include <boost/test/utils/iterator/token_iterator.hpp>
29#endif
30
31// Boost
32#include <boost/cstdlib.hpp>
33#include <boost/bind.hpp>
34
35// STL
36#include <stdexcept>
37#include <iostream>
38
39#include <boost/test/detail/suppress_warnings.hpp>
40
41//____________________________________________________________________________//
42
43namespace boost {
44
45namespace unit_test {
46
47// ************************************************************************** //
48// **************                 test_case_filter             ************** //
49// ************************************************************************** //
50
51class test_case_filter : public test_tree_visitor {
52public:
53    struct single_filter {
54        single_filter( const_string in )
55        {
56            if( in == "*" )
57                m_kind  = SFK_ALL;
58            else if( first_char( in ) == '*' && last_char( in ) == '*' ) {
59                m_kind  = SFK_SUBSTR;
60                m_value = in.substr( 1, in.size()-1 );
61            }
62            else if( first_char( in ) == '*' ) {
63                m_kind  = SFK_TRAILING;
64                m_value = in.substr( 1 );
65            }
66            else if( last_char( in ) == '*' ) {
67                m_kind  = SFK_LEADING;
68                m_value = in.substr( 0, in.size()-1 );
69            }
70            else {
71                m_kind  = SFK_MATCH;
72                m_value = in;
73            }
74        };
75
76        bool            pass( test_unit const& tu ) const
77        {
78            const_string name( tu.p_name );
79
80            switch( m_kind ) {
81            default:
82            case SFK_ALL:
83                return true;
84
85            case SFK_LEADING:
86                return name.substr( 0, m_value.size() ) == m_value;
87
88            case SFK_TRAILING:
89                return name.size() >= m_value.size() && name.substr( name.size() - m_value.size() ) == m_value;
90
91            case SFK_SUBSTR:
92                return name.find( m_value ) != const_string::npos;
93
94            case SFK_MATCH:
95                return m_value == tu.p_name.get();
96            }
97        }
98        enum kind { SFK_ALL, SFK_LEADING, SFK_TRAILING, SFK_SUBSTR, SFK_MATCH };
99
100        kind            m_kind;
101        const_string    m_value;
102    };
103    // Constructor
104#ifndef BOOST_TEST_SUPPORT_RUN_BY_NAME
105    explicit        test_case_filter( const_string ) : m_depth( 0 ) {}
106#else
107    explicit        test_case_filter( const_string tc_to_run )
108    : m_depth( 0 )
109    {
110        string_token_iterator tit( tc_to_run, (dropped_delimeters = "/", kept_delimeters = dt_none) );
111
112        while( tit != string_token_iterator() ) {
113            m_filters.push_back(
114                std::vector<single_filter>( string_token_iterator( *tit, (dropped_delimeters = ",", kept_delimeters = dt_none)  ),
115                                            string_token_iterator() ) );
116
117            ++tit;
118        }
119    }
120#endif
121
122    void            filter_unit( test_unit const& tu )
123    {
124        if( (++m_depth - 1) > m_filters.size() ) {
125            tu.p_enabled.value = true;
126            return;
127        }
128
129        if( m_depth == 1 )
130            return;
131
132        std::vector<single_filter> const& filters = m_filters[m_depth-2];
133
134        tu.p_enabled.value =
135            std::find_if( filters.begin(), filters.end(), bind( &single_filter::pass, _1, boost::ref(tu) ) ) != filters.end();
136    }
137
138    // test tree visitor interface
139    virtual void    visit( test_case const& tc )
140    {
141        if( m_depth < m_filters.size() ) {
142            tc.p_enabled.value = false;
143            return;
144        }
145
146        filter_unit( tc );
147
148        --m_depth;
149    }
150
151    virtual bool    test_suite_start( test_suite const& ts )
152    {
153        filter_unit( ts );
154
155        if( !ts.p_enabled )
156            --m_depth;
157
158        return ts.p_enabled;
159    }
160
161    virtual void    test_suite_finish( test_suite const& )  { --m_depth; }
162
163private:
164    // Data members
165    std::vector<std::vector<single_filter> >    m_filters;
166    unsigned                                    m_depth;
167};
168
169// ************************************************************************** //
170// **************                  unit_test_main              ************** //
171// ************************************************************************** //
172
173int BOOST_TEST_DECL
174unit_test_main( init_unit_test_func init_func, int argc, char* argv[] )
175{
176    try {
177        framework::init( init_func, argc, argv );
178
179        if( !runtime_config::test_to_run().is_empty() ) {
180            test_case_filter filter( runtime_config::test_to_run() );
181
182            traverse_test_tree( framework::master_test_suite().p_id, filter );
183        }
184
185        framework::run();
186
187        results_reporter::make_report();
188
189        return runtime_config::no_result_code()
190                    ? boost::exit_success
191                    : results_collector.results( framework::master_test_suite().p_id ).result_code();
192    }
193    catch( framework::nothing_to_test const& ) {
194        return boost::exit_success;
195    }
196    catch( framework::internal_error const& ex ) {
197        results_reporter::get_stream() << "Boost.Test framework internal error: " << ex.what() << std::endl;
198
199        return boost::exit_exception_failure;
200    }
201    catch( framework::setup_error const& ex ) {
202        results_reporter::get_stream() << "Test setup error: " << ex.what() << std::endl;
203
204        return boost::exit_exception_failure;
205    }
206    catch( ... ) {
207        results_reporter::get_stream() << "Boost.Test framework internal error: unknown reason" << std::endl;
208
209        return boost::exit_exception_failure;
210    }
211}
212
213} // namespace unit_test
214
215} // namespace boost
216
217#if !defined(BOOST_TEST_DYN_LINK) && !defined(BOOST_TEST_NO_MAIN)
218
219// ************************************************************************** //
220// **************        main function for tests using lib     ************** //
221// ************************************************************************** //
222
223int BOOST_TEST_CALL_DECL
224main( int argc, char* argv[] )
225{
226    // prototype for user's unit test init function
227#ifdef BOOST_TEST_ALTERNATIVE_INIT_API
228    extern bool init_unit_test();
229
230    boost::unit_test::init_unit_test_func init_func = &init_unit_test;
231#else
232    extern ::boost::unit_test::test_suite* init_unit_test_suite( int argc, char* argv[] );
233
234    boost::unit_test::init_unit_test_func init_func = &init_unit_test_suite;
235#endif
236
237    return ::boost::unit_test::unit_test_main( init_func, argc, argv );
238}
239
240#endif // !BOOST_TEST_DYN_LINK && !BOOST_TEST_NO_MAIN
241
242//____________________________________________________________________________//
243
244#include <boost/test/detail/enable_warnings.hpp>
245
246#endif // BOOST_TEST_UNIT_TEST_MAIN_IPP_012205GER
247