LCOV - code coverage report
Current view: top level - opt/homebrew/include/boost/test/impl - framework.ipp (source / functions) Hit Total Coverage
Test: total_coverage.info Lines: 413 754 54.8 %
Date: 2026-06-25 07:23:43 Functions: 72 126 57.1 %

          Line data    Source code
       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 : implements framework API - main driver for the test
      13             : // ***************************************************************************
      14             : 
      15             : #ifndef BOOST_TEST_FRAMEWORK_IPP_021005GER
      16             : #define BOOST_TEST_FRAMEWORK_IPP_021005GER
      17             : 
      18             : // Boost.Test
      19             : #include <boost/test/framework.hpp>
      20             : #include <boost/test/execution_monitor.hpp>
      21             : #include <boost/test/debug.hpp>
      22             : #include <boost/test/unit_test_parameters.hpp>
      23             : 
      24             : #include <boost/test/unit_test_log.hpp>
      25             : #include <boost/test/unit_test_log_formatter.hpp>
      26             : #include <boost/test/unit_test_monitor.hpp>
      27             : #include <boost/test/results_collector.hpp>
      28             : #include <boost/test/progress_monitor.hpp>
      29             : #include <boost/test/results_reporter.hpp>
      30             : #include <boost/test/test_framework_init_observer.hpp>
      31             : 
      32             : #include <boost/test/tree/observer.hpp>
      33             : #include <boost/test/tree/test_unit.hpp>
      34             : #include <boost/test/tree/visitor.hpp>
      35             : #include <boost/test/tree/traverse.hpp>
      36             : #include <boost/test/tree/test_case_counter.hpp>
      37             : #include <boost/test/tree/global_fixture.hpp>
      38             : 
      39             : #if BOOST_TEST_SUPPORT_TOKEN_ITERATOR
      40             : #include <boost/test/utils/iterator/token_iterator.hpp>
      41             : #endif
      42             : 
      43             : #include <boost/test/utils/foreach.hpp>
      44             : #include <boost/test/utils/basic_cstring/io.hpp>
      45             : #include <boost/test/utils/basic_cstring/compare.hpp>
      46             : 
      47             : #include <boost/test/detail/global_typedef.hpp>
      48             : #include <boost/test/detail/throw_exception.hpp>
      49             : 
      50             : // Boost
      51             : #include <boost/test/utils/timer.hpp>
      52             : #include <boost/bind/bind.hpp>
      53             : 
      54             : // STL
      55             : #include <limits>
      56             : #include <map>
      57             : #include <set>
      58             : #include <cstdlib>
      59             : #include <ctime>
      60             : #include <numeric>
      61             : #include <cmath>
      62             : #include <iterator>
      63             : 
      64             : #ifdef BOOST_NO_STDC_NAMESPACE
      65             : namespace std { using ::time; using ::srand; }
      66             : #endif
      67             : 
      68             : #include <boost/test/detail/suppress_warnings.hpp>
      69             : 
      70             : //____________________________________________________________________________//
      71             : 
      72             : namespace boost {
      73             : namespace unit_test {
      74             : namespace framework {
      75             : 
      76             : namespace impl {
      77             : 
      78             : // ************************************************************************** //
      79             : // **************            order detection helpers           ************** //
      80             : // ************************************************************************** //
      81             : 
      82             : struct order_info {
      83      245864 :     order_info() : depth(-1) {}
      84             : 
      85             :     int                         depth;
      86             :     std::vector<test_unit_id>   dependant_siblings;
      87             : };
      88             : 
      89             : typedef std::set<test_unit_id> tu_id_set;
      90             : typedef std::map<test_unit_id,order_info> order_info_per_tu; // !! ?? unordered map
      91             : 
      92             : //____________________________________________________________________________//
      93             : 
      94             : static test_unit_id
      95           0 : get_tu_parent( test_unit_id tu_id )
      96             : {
      97           0 :     return framework::get( tu_id, TUT_ANY ).p_parent_id;
      98             : }
      99             : 
     100             : //____________________________________________________________________________//
     101             : 
     102             : static int
     103           0 : tu_depth( test_unit_id tu_id, test_unit_id master_tu_id, order_info_per_tu& tuoi )
     104             : {
     105           0 :     if( tu_id == master_tu_id )
     106           0 :         return 0;
     107             : 
     108           0 :     order_info& info = tuoi[tu_id];
     109             : 
     110           0 :     if( info.depth == -1 )
     111           0 :         info.depth = tu_depth( get_tu_parent( tu_id ), master_tu_id, tuoi ) + 1;
     112             : 
     113           0 :     return info.depth;
     114           0 : }
     115             : 
     116             : //____________________________________________________________________________//
     117             : 
     118             : static void
     119           0 : collect_dependant_siblings( test_unit_id from, test_unit_id to, test_unit_id master_tu_id, order_info_per_tu& tuoi )
     120             : {
     121           0 :     int from_depth  = tu_depth( from, master_tu_id, tuoi );
     122           0 :     int to_depth    = tu_depth( to, master_tu_id, tuoi );
     123             : 
     124           0 :     while(from_depth > to_depth) {
     125           0 :         from = get_tu_parent( from );
     126           0 :         --from_depth;
     127             :     }
     128             : 
     129           0 :     while(from_depth < to_depth) {
     130           0 :         to = get_tu_parent( to );
     131           0 :         --to_depth;
     132             :     }
     133             : 
     134           0 :     while(true) {
     135           0 :         test_unit_id from_parent = get_tu_parent( from );
     136           0 :         test_unit_id to_parent = get_tu_parent( to );
     137           0 :         if( from_parent == to_parent )
     138           0 :             break;
     139           0 :         from = from_parent;
     140           0 :         to   = to_parent;
     141             :     }
     142             : 
     143           0 :     tuoi[from].dependant_siblings.push_back( to );
     144           0 : }
     145             : 
     146             : //____________________________________________________________________________//
     147             : 
     148             : static counter_t
     149      122932 : assign_sibling_rank( test_unit_id tu_id, order_info_per_tu& tuoi )
     150             : {
     151      122932 :     test_unit& tu = framework::get( tu_id, TUT_ANY );
     152             : 
     153      122932 :     BOOST_TEST_SETUP_ASSERT( tu.p_sibling_rank != (std::numeric_limits<counter_t>::max)(),
     154             :                              "Cyclic dependency detected involving test unit \"" + tu.full_name() + "\"" );
     155             : 
     156      122932 :     if( tu.p_sibling_rank != 0 )
     157           0 :         return tu.p_sibling_rank;
     158             : 
     159      122932 :     order_info const& info = tuoi[tu_id];
     160             : 
     161             :     // indicate in progress
     162      122932 :     tu.p_sibling_rank.value = (std::numeric_limits<counter_t>::max)();
     163             : 
     164      122932 :     counter_t new_rank = 1;
     165      122932 :     BOOST_TEST_FOREACH( test_unit_id, sibling_id, info.dependant_siblings )
     166           0 :         new_rank = (std::max)(new_rank, assign_sibling_rank( sibling_id, tuoi ) + 1);
     167             : 
     168      122932 :     return tu.p_sibling_rank.value = new_rank;
     169      122932 : }
     170             : 
     171             : //____________________________________________________________________________//
     172             : 
     173             : // ************************************************************************** //
     174             : // **************            test_init call wrapper            ************** //
     175             : // ************************************************************************** //
     176             : 
     177             : static void
     178         146 : invoke_init_func( init_unit_test_func init_func )
     179             : {
     180             : #ifdef BOOST_TEST_ALTERNATIVE_INIT_API
     181             :     BOOST_TEST_I_ASSRT( (*init_func)(), std::runtime_error( "test module initialization failed" ) );
     182             : #else
     183         146 :     test_suite*  manual_test_units = (*init_func)( framework::master_test_suite().argc, framework::master_test_suite().argv );
     184             : 
     185         146 :     if( manual_test_units )
     186           0 :         framework::master_test_suite().add( manual_test_units );
     187             : #endif
     188         146 : }
     189             : 
     190             : // ************************************************************************** //
     191             : // **************                  name_filter                 ************** //
     192             : // ************************************************************************** //
     193             : 
     194             : class name_filter : public test_tree_visitor {
     195             :     struct component {
     196         292 :         component( const_string name ) // has to be implicit
     197         146 :         {
     198         146 :             if( name == "*" )
     199           0 :                 m_kind  = SFK_ALL;
     200         146 :             else if( first_char( name ) == '*' && last_char( name ) == '*' ) {
     201           0 :                 m_kind  = SFK_SUBSTR;
     202           0 :                 m_name  = name.substr( 1, name.size()-1 );
     203           0 :             }
     204         146 :             else if( first_char( name ) == '*' ) {
     205           0 :                 m_kind  = SFK_TRAILING;
     206           0 :                 m_name  = name.substr( 1 );
     207           0 :             }
     208         146 :             else if( last_char( name ) == '*' ) {
     209           0 :                 m_kind  = SFK_LEADING;
     210           0 :                 m_name  = name.substr( 0, name.size()-1 );
     211           0 :             }
     212             :             else {
     213         146 :                 m_kind  = SFK_MATCH;
     214         146 :                 m_name  = name;
     215             :             }
     216         292 :         }
     217             : 
     218       21170 :         bool            pass( test_unit const& tu ) const
     219             :         {
     220       21170 :             const_string name( tu.p_name );
     221             : 
     222       21170 :             switch( m_kind ) {
     223             :             default:
     224             :             case SFK_ALL:
     225           0 :                 return true;
     226             :             case SFK_LEADING:
     227           0 :                 return name.substr( 0, m_name.size() ) == m_name;
     228             :             case SFK_TRAILING:
     229           0 :                 return name.size() >= m_name.size() && name.substr( name.size() - m_name.size() ) == m_name;
     230             :             case SFK_SUBSTR:
     231           0 :                 return name.find( m_name ) != const_string::npos;
     232             :             case SFK_MATCH:
     233       21170 :                 return m_name == tu.p_name.get();
     234             :             }
     235       21170 :         }
     236             :         enum kind { SFK_ALL, SFK_LEADING, SFK_TRAILING, SFK_SUBSTR, SFK_MATCH };
     237             : 
     238             :         kind            m_kind;
     239             :         const_string    m_name;
     240             :     };
     241             : 
     242             : public:
     243             :     // Constructor
     244         438 :     name_filter( test_unit_id_list& targ_list, const_string filter_expr ) : m_targ_list( targ_list ), m_depth( 0 )
     245         292 :     {
     246             : #ifdef BOOST_TEST_SUPPORT_TOKEN_ITERATOR
     247         292 :         utils::string_token_iterator tit( filter_expr, (utils::dropped_delimeters = "/",
     248         146 :                                                         utils::kept_delimeters = utils::dt_none) );
     249             : 
     250         292 :         while( tit != utils::string_token_iterator() ) {
     251         292 :             m_components.push_back(
     252         438 :                 std::vector<component>( utils::string_token_iterator( *tit, (utils::dropped_delimeters = ",",
     253         146 :                                                                              utils::kept_delimeters = utils::dt_none) ),
     254         146 :                                         utils::string_token_iterator() ) );
     255             : 
     256         146 :             ++tit;
     257             :         }
     258             : #endif
     259         292 :     }
     260             : 
     261             : private:
     262       21316 :     bool            filter_unit( test_unit const& tu )
     263             :     {
     264             :         // skip master test suite
     265       21316 :         if( m_depth == 0 )
     266         146 :             return true;
     267             : 
     268             :         // corresponding name filters are at level m_depth-1
     269       21170 :         std::vector<component> const& filters = m_components[m_depth-1];
     270             : 
     271             :         // look for match
     272             :         using namespace boost::placeholders;
     273       21170 :         return std::find_if( filters.begin(), filters.end(), bind( &component::pass, _1, boost::ref(tu) ) ) != filters.end();
     274       21316 :     }
     275             : 
     276             :     // test_tree_visitor interface
     277           0 :     void    visit( test_case const& tc ) BOOST_OVERRIDE
     278             :     {
     279             :         // make sure we only accept test cases if we match last component of the filter
     280           0 :         if( m_depth == m_components.size() && filter_unit( tc ) )
     281           0 :             m_targ_list.push_back( tc.p_id ); // found a test case
     282           0 :     }
     283       21316 :     bool    test_suite_start( test_suite const& ts ) BOOST_OVERRIDE
     284             :     {
     285       21316 :         if( !filter_unit( ts ) )
     286       21024 :             return false;
     287             : 
     288         292 :         if( m_depth < m_components.size() ) {
     289         146 :             ++m_depth;
     290         146 :             return true;
     291             :         }
     292             : 
     293         146 :         m_targ_list.push_back( ts.p_id ); // found a test suite
     294             : 
     295         146 :         return false;
     296       21316 :     }
     297         146 :     void    test_suite_finish( test_suite const& /*ts*/ ) BOOST_OVERRIDE
     298             :     {
     299         146 :         --m_depth;
     300         146 :     }
     301             : 
     302             :     // Data members
     303             :     typedef std::vector<std::vector<component> > components_per_level;
     304             : 
     305             :     components_per_level    m_components;
     306             :     test_unit_id_list&      m_targ_list;
     307             :     unsigned                m_depth;
     308             : };
     309             : 
     310             : // ************************************************************************** //
     311             : // **************                 label_filter                 ************** //
     312             : // ************************************************************************** //
     313             : 
     314             : class label_filter : public test_tree_visitor {
     315             : public:
     316           0 :     label_filter( test_unit_id_list& targ_list, const_string label )
     317           0 :     : m_targ_list( targ_list )
     318           0 :     , m_label( label )
     319           0 :     {}
     320             : 
     321             : private:
     322             :     // test_tree_visitor interface
     323           0 :     bool    visit( test_unit const& tu ) BOOST_OVERRIDE
     324             :     {
     325           0 :         if( tu.has_label( m_label ) ) {
     326             :             // found a test unit; add it to list of tu to enable with children and stop recursion in case of suites
     327           0 :             m_targ_list.push_back( tu.p_id );
     328           0 :             return false;
     329             :         }
     330             : 
     331           0 :         return true;
     332           0 :     }
     333             : 
     334             :     // Data members
     335             :     test_unit_id_list&  m_targ_list;
     336             :     const_string        m_label;
     337             : };
     338             : 
     339             : // ************************************************************************** //
     340             : // **************                set_run_status                ************** //
     341             : // ************************************************************************** //
     342             : 
     343             : class set_run_status : public test_tree_visitor {
     344             : public:
     345         584 :     explicit set_run_status( test_unit::run_status rs, test_unit_id_list* dep_collector = 0 )
     346         292 :     : m_new_status( rs )
     347         292 :     , m_dep_collector( dep_collector )
     348         876 :     {}
     349             : 
     350             :     // test_tree_visitor interface
     351      123973 :     bool    visit( test_unit const& tu ) BOOST_OVERRIDE
     352             :     {
     353      123973 :         const_cast<test_unit&>(tu).p_run_status.value = m_new_status == test_unit::RS_INVALID ? tu.p_default_status : m_new_status;
     354      123973 :         if( m_dep_collector ) {
     355         895 :             BOOST_TEST_FOREACH( test_unit_id, dep_id, tu.p_dependencies.get() ) {
     356           0 :                 test_unit const& dep = framework::get( dep_id, TUT_ANY );
     357             : 
     358           0 :                 if( dep.p_run_status == tu.p_run_status )
     359           0 :                     continue;
     360             : 
     361           0 :                 BOOST_TEST_FRAMEWORK_MESSAGE( "Including test " << dep.p_type_name << ' ' << dep.full_name() <<
     362             :                                               " as a dependency of test " << tu.p_type_name << ' ' << tu.full_name() );
     363             : 
     364           0 :                 m_dep_collector->push_back( dep_id );
     365           0 :             }
     366         895 :         }
     367      123973 :         return true;
     368           0 :     }
     369             : 
     370             : private:
     371             :     // Data members
     372             :     test_unit::run_status   m_new_status;
     373             :     test_unit_id_list*      m_dep_collector;
     374             : };
     375             : 
     376             : // ************************************************************************** //
     377             : // **************                 parse_filters                ************** //
     378             : // ************************************************************************** //
     379             : 
     380             : static void
     381         146 : add_filtered_test_units( test_unit_id master_tu_id, const_string filter, test_unit_id_list& targ )
     382             : {
     383             :     // Choose between two kinds of filters
     384         146 :     if( filter[0] == '@' ) {
     385           0 :         filter.trim_left( 1 );
     386           0 :         label_filter lf( targ, filter );
     387           0 :         traverse_test_tree( master_tu_id, lf, true );
     388           0 :     }
     389             :     else {
     390         146 :         name_filter nf( targ, filter );
     391         146 :         traverse_test_tree( master_tu_id, nf, true );
     392         146 :     }
     393         146 : }
     394             : 
     395             : //____________________________________________________________________________//
     396             : 
     397             : static bool
     398         146 : parse_filters( test_unit_id master_tu_id, test_unit_id_list& tu_to_enable, test_unit_id_list& tu_to_disable )
     399             : {
     400             :     // 10. collect tu to enable and disable based on filters
     401         146 :     bool had_selector_filter = false;
     402             : 
     403         146 :     std::vector<std::string> const& filters = runtime_config::get<std::vector<std::string> >( runtime_config::btrt_run_filters );
     404             : 
     405         438 :     BOOST_TEST_FOREACH( const_string, filter, filters ) {
     406         146 :         BOOST_TEST_SETUP_ASSERT( !filter.is_empty(), "Invalid filter specification" );
     407             : 
     408             :         // each --run_test command may also be separated by a ':' (environment variable)
     409         292 :         utils::string_token_iterator t_filter_it( filter, (utils::dropped_delimeters = ":",
     410         146 :                                                            utils::kept_delimeters = utils::dt_none) );
     411             : 
     412         292 :         while( t_filter_it != utils::string_token_iterator() ) {
     413         146 :             const_string filter_token = *t_filter_it;
     414             : 
     415         146 :             enum { SELECTOR, ENABLER, DISABLER } filter_type = SELECTOR;
     416             : 
     417             :             // 11. Deduce filter type
     418         146 :             if( filter_token[0] == '!' || filter_token[0] == '+' ) {
     419           0 :                 filter_type = filter_token[0] == '+' ? ENABLER : DISABLER;
     420           0 :                 filter_token.trim_left( 1 );
     421           0 :                 BOOST_TEST_SETUP_ASSERT( !filter_token.is_empty(), "Invalid filter specification" );
     422           0 :             }
     423             : 
     424         146 :             had_selector_filter |= filter_type == SELECTOR;
     425             : 
     426             :             // 12. Add test units to corresponding list
     427         146 :             switch( filter_type ) {
     428             :             case SELECTOR:
     429         146 :             case ENABLER:  add_filtered_test_units( master_tu_id, filter_token, tu_to_enable ); break;
     430           0 :             case DISABLER: add_filtered_test_units( master_tu_id, filter_token, tu_to_disable ); break;
     431             :             }
     432             : 
     433         146 :             ++t_filter_it;
     434             :         }
     435         146 :     }
     436             : 
     437         146 :     return had_selector_filter;
     438           0 : }
     439             : 
     440             : //____________________________________________________________________________//
     441             : 
     442             : // a poor man's implementation of random_shuffle, deprecated in C++11
     443             : template< class RandomIt, class RandomFunc >
     444           0 : void random_shuffle( RandomIt first, RandomIt last, RandomFunc &r )
     445             : {
     446             :     typedef typename std::iterator_traits<RandomIt>::difference_type difference_type;
     447           0 :     difference_type n = last - first;
     448           0 :     for (difference_type i = n-1; i > 0; --i) {
     449           0 :         difference_type j = r(i+1);
     450           0 :         if (j != i) {
     451             :             using std::swap;
     452           0 :             swap(first[i], first[j]);
     453           0 :         }
     454           0 :     }
     455           0 : }
     456             : 
     457             : // A simple handle for registering the global fixtures to the master test suite
     458             : // without deleting an existing static object (the global fixture itself) when the program
     459             : // terminates (shared_ptr).
     460             : class global_fixture_handle : public test_unit_fixture {
     461             : public:
     462           0 :     global_fixture_handle(test_unit_fixture* fixture) : m_global_fixture(fixture) {}
     463           0 :     ~global_fixture_handle() BOOST_OVERRIDE {}
     464             : 
     465           0 :     void    setup() BOOST_OVERRIDE {
     466           0 :         m_global_fixture->setup();
     467           0 :     }
     468           0 :     void    teardown() BOOST_OVERRIDE {
     469           0 :         m_global_fixture->teardown();
     470           0 :     }
     471             : 
     472             : private:
     473             :     test_unit_fixture* m_global_fixture;
     474             : };
     475             : 
     476             : 
     477             : } // namespace impl
     478             : 
     479             : // ************************************************************************** //
     480             : // **************               framework::state               ************** //
     481             : // ************************************************************************** //
     482             : 
     483             : unsigned long int const TIMEOUT_EXCEEDED = static_cast<unsigned long int>( -1 );
     484             : 
     485             : class state {
     486             : public:
     487         876 :     state()
     488         146 :     : m_master_test_suite( 0 )
     489         146 :     , m_curr_test_unit( INV_TEST_UNIT_ID )
     490         146 :     , m_next_test_case_id( MIN_TEST_CASE_ID )
     491         146 :     , m_next_test_suite_id( MIN_TEST_SUITE_ID )
     492         146 :     , m_test_in_progress( false )
     493         146 :     , m_context_idx( 0 )
     494         146 :     , m_log_sinks( )
     495         146 :     , m_report_sink( std::cerr )
     496         146 :     {
     497         292 :     }
     498             : 
     499           0 :     ~state() { clear(); }
     500             : 
     501           0 :     void            clear()
     502             :     {
     503           0 :         while( !m_test_units.empty() ) {
     504           0 :             test_unit_store::value_type const& tu     = *m_test_units.begin();
     505           0 :             test_unit const*                   tu_ptr = tu.second;
     506             : 
     507             :             // the delete will erase this element from map
     508           0 :             if( ut_detail::test_id_2_unit_type( tu.second->p_id ) == TUT_SUITE )
     509           0 :                 delete static_cast<test_suite const*>(tu_ptr);
     510             :             else
     511           0 :                 delete static_cast<test_case const*>(tu_ptr);
     512             :         }
     513           0 :     }
     514             : 
     515      123078 :     void            set_tu_id( test_unit& tu, test_unit_id id ) { tu.p_id.value = id; }
     516             : 
     517             :     //////////////////////////////////////////////////////////////////
     518             : 
     519             :     // Validates the dependency graph and deduces the sibling dependency rank for each child
     520      123078 :     void       deduce_siblings_order( test_unit_id tu_id, test_unit_id master_tu_id, impl::order_info_per_tu& tuoi )
     521             :     {
     522      123078 :         test_unit& tu = framework::get( tu_id, TUT_ANY );
     523             : 
     524             :         // collect all sibling dependencies from tu own list
     525      123078 :         BOOST_TEST_FOREACH( test_unit_id, dep_id, tu.p_dependencies.get() )
     526           0 :             collect_dependant_siblings( tu_id, dep_id, master_tu_id, tuoi );
     527             : 
     528      123078 :         if( tu.p_type != TUT_SUITE )
     529      101762 :             return;
     530             : 
     531       21316 :         test_suite& ts = static_cast<test_suite&>(tu);
     532             : 
     533             :         // recursive call to children first
     534      267180 :         BOOST_TEST_FOREACH( test_unit_id, chld_id, ts.m_children )
     535      122932 :             deduce_siblings_order( chld_id, master_tu_id, tuoi );
     536             : 
     537       21316 :         ts.m_ranked_children.clear();
     538      267180 :         BOOST_TEST_FOREACH( test_unit_id, chld_id, ts.m_children ) {
     539      122932 :             counter_t rank = assign_sibling_rank( chld_id, tuoi );
     540      122932 :             ts.m_ranked_children.insert( std::make_pair( rank, chld_id ) );
     541      122932 :         }
     542      123078 :     }
     543             : 
     544             :     //////////////////////////////////////////////////////////////////
     545             : 
     546             :     // Finalize default run status:
     547             :     //  1) inherit run status from parent where applicable
     548             :     //  2) if any of test units in test suite enabled enable it as well
     549      123078 :     bool            finalize_default_run_status( test_unit_id tu_id, test_unit::run_status parent_status )
     550             :     {
     551      123078 :         test_unit& tu = framework::get( tu_id, TUT_ANY );
     552             : 
     553      123078 :         if( tu.p_default_status == test_suite::RS_INHERIT )
     554      122932 :             tu.p_default_status.value = parent_status;
     555             : 
     556             :         // go through list of children
     557      123078 :         if( tu.p_type == TUT_SUITE ) {
     558       21316 :             bool has_enabled_child = false;
     559      267180 :             BOOST_TEST_FOREACH( test_unit_id, chld_id, static_cast<test_suite const&>(tu).m_children )
     560      122932 :                 has_enabled_child |= finalize_default_run_status( chld_id, tu.p_default_status );
     561             : 
     562       21316 :             tu.p_default_status.value = has_enabled_child ? test_suite::RS_ENABLED : test_suite::RS_DISABLED;
     563       21316 :         }
     564             : 
     565      123078 :         return tu.p_default_status == test_suite::RS_ENABLED;
     566             :     }
     567             : 
     568             :     //////////////////////////////////////////////////////////////////
     569             : 
     570      123078 :     bool            finalize_run_status( test_unit_id tu_id )
     571             :     {
     572      123078 :         test_unit& tu = framework::get( tu_id, TUT_ANY );
     573             : 
     574             :         // go through list of children
     575      123078 :         if( tu.p_type == TUT_SUITE ) {
     576       21316 :             bool has_enabled_child = false;
     577      267180 :             BOOST_TEST_FOREACH( test_unit_id, chld_id, static_cast<test_suite const&>(tu).m_children)
     578      122932 :                 has_enabled_child |= finalize_run_status( chld_id );
     579             : 
     580       21316 :             tu.p_run_status.value = has_enabled_child ? test_suite::RS_ENABLED : test_suite::RS_DISABLED;
     581       21316 :         }
     582             : 
     583      123078 :         return tu.is_enabled();
     584             :     }
     585             : 
     586             :     //////////////////////////////////////////////////////////////////
     587             : 
     588         146 :     void            deduce_run_status( test_unit_id master_tu_id )
     589             :     {
     590             :         using namespace framework::impl;
     591         146 :         test_unit_id_list tu_to_enable;
     592         146 :         test_unit_id_list tu_to_disable;
     593             : 
     594             :         // 10. If there are any filters supplied, figure out lists of test units to enable/disable
     595         292 :         bool had_selector_filter = !runtime_config::get<std::vector<std::string> >( runtime_config::btrt_run_filters ).empty() &&
     596         146 :                                    parse_filters( master_tu_id, tu_to_enable, tu_to_disable );
     597             : 
     598             :         // 20. Set the stage: either use default run status or disable all test units
     599         146 :         set_run_status initial_setter( had_selector_filter ? test_unit::RS_DISABLED : test_unit::RS_INVALID );
     600         146 :         traverse_test_tree( master_tu_id, initial_setter, true );
     601             : 
     602             :         // 30. Apply all selectors and enablers.
     603         292 :         while( !tu_to_enable.empty() ) {
     604         146 :             test_unit& tu = framework::get( tu_to_enable.back(), TUT_ANY );
     605             : 
     606         146 :             tu_to_enable.pop_back();
     607             : 
     608             :             // 35. Ignore test units which are already enabled
     609         146 :             if( tu.is_enabled() )
     610           0 :                 continue;
     611             : 
     612             :             // set new status and add all dependencies into tu_to_enable
     613         146 :             set_run_status enabler( test_unit::RS_ENABLED, &tu_to_enable );
     614         146 :             traverse_test_tree( tu.p_id, enabler, true );
     615             : 
     616             :             // Add the dependencies of the parent suites, see trac #13149
     617         146 :             test_unit_id parent_id = tu.p_parent_id;
     618         292 :             while(   parent_id != INV_TEST_UNIT_ID
     619         146 :                   && parent_id != master_tu_id )
     620             :             {
     621             :                 // we do not use the traverse_test_tree as otherwise it would enable the siblings and subtree
     622             :                 // of the test case we want to enable (we need to enable the parent suites and their dependencies only)
     623             :                 // the parent_id needs to be enabled in order to be properly parsed by finalize_run_status, the visit
     624             :                 // does the job
     625           0 :                 test_unit& tu_parent = framework::get( parent_id, TUT_ANY );
     626           0 :                 enabler.visit( tu_parent );
     627           0 :                 parent_id = tu_parent.p_parent_id;
     628             :             }
     629         146 :         }
     630             : 
     631             :         // 40. Apply all disablers
     632         146 :         while( !tu_to_disable.empty() ) {
     633           0 :             test_unit const& tu = framework::get( tu_to_disable.back(), TUT_ANY );
     634             : 
     635           0 :             tu_to_disable.pop_back();
     636             : 
     637             :             // 35. Ignore test units which already disabled
     638           0 :             if( !tu.is_enabled() )
     639           0 :                 continue;
     640             : 
     641           0 :             set_run_status disabler( test_unit::RS_DISABLED );
     642           0 :             traverse_test_tree( tu.p_id, disabler, true );
     643           0 :         }
     644             : 
     645             :         // 50. Make sure parents of enabled test units are also enabled
     646         146 :         finalize_run_status( master_tu_id );
     647         146 :     }
     648             : 
     649             :     //////////////////////////////////////////////////////////////////
     650             : 
     651             :     typedef unit_test_monitor_t::error_level execution_result;
     652             : 
     653             :     // Random generator using the std::rand function (seeded prior to the call)
     654             :     struct random_generator_helper {
     655           0 :       size_t operator()(size_t i) const {
     656           0 :         return std::rand() % i;
     657             :       }
     658             :     };
     659             : 
     660             :     // Executes the test tree with the root at specified test unit
     661       22022 :     execution_result execute_test_tree( test_unit_id tu_id,
     662             :                                         unsigned long int timeout_microseconds = 0,
     663             :                                         random_generator_helper const * const p_random_generator = 0)
     664             :     {
     665       22022 :         test_unit const& tu = framework::get( tu_id, TUT_ANY );
     666             : 
     667       22022 :         execution_result result = unit_test_monitor_t::test_ok;
     668             : 
     669       22022 :         if( !tu.is_enabled() ) {
     670      105010 :             BOOST_TEST_FOREACH( test_observer*, to, m_observers )
     671       42004 :                 to->test_unit_skipped( tu, "disabled" );
     672       21002 :             return result;
     673             :         }
     674             : 
     675             :         // 10. Check preconditions, including zero time left for execution and
     676             :         // successful execution of all dependencies
     677        1020 :         if( timeout_microseconds == TIMEOUT_EXCEEDED ) {
     678             :             // notify all observers about skipped test unit
     679           0 :             BOOST_TEST_FOREACH( test_observer*, to, m_observers )
     680           0 :                 to->test_unit_skipped( tu, "timeout for the test unit is exceeded" );
     681             : 
     682           0 :             return unit_test_monitor_t::os_timeout;
     683             :         }
     684        1020 :         else if( timeout_microseconds == 0 || (tu.p_timeout > 0 && timeout_microseconds > (tu.p_timeout * 1000000) ) ) // deduce timeout for this test unit
     685        1023 :             timeout_microseconds = tu.p_timeout * 1000000;
     686             : 
     687             : 
     688        1026 :         test_tools::assertion_result const precondition_res = tu.check_preconditions();
     689        1026 :         if( !precondition_res ) {
     690             :             // notify all observers about skipped test unit
     691           0 :             BOOST_TEST_FOREACH( test_observer*, to, m_observers )
     692           0 :                 to->test_unit_skipped( tu, precondition_res.message() );
     693             : 
     694             :             // It is not an error to skip the test if any of the parent tests
     695             :             // have failed. This one should be reported as skipped as if it was
     696             :             // disabled
     697           0 :             return unit_test_monitor_t::test_ok;
     698             :         }
     699             : 
     700             :         // 20. Notify all observers about the start of the test unit
     701        5115 :         BOOST_TEST_FOREACH( test_observer*, to, m_observers )
     702        2046 :             to->test_unit_start( tu );
     703             : 
     704             :         // 30. Execute setup fixtures if any; any failure here leads to test unit abortion
     705        1023 :         BOOST_TEST_FOREACH( test_unit_fixture_ptr, F, tu.p_fixtures.get() ) {
     706           0 :             ut_detail::test_unit_id_restore restore_current_test_unit(m_curr_test_unit, tu.p_id);
     707           0 :             result = unit_test_monitor.execute_and_translate( boost::bind( &test_unit_fixture::setup, F ) );
     708           0 :             if( result != unit_test_monitor_t::test_ok )
     709           0 :                 break;
     710           0 :             test_results const& test_rslt = unit_test::results_collector.results( m_curr_test_unit );
     711           0 :             if( test_rslt.aborted() ) {
     712           0 :                 result = unit_test_monitor_t::test_setup_failure;
     713           0 :                 break;
     714             :             }
     715           0 :         }
     716             : 
     717             :         // This is the time we are going to spend executing the test unit (in microseconds
     718             :         // as expected by test_observer::test_unit_finish)
     719        1023 :         unsigned long elapsed_microseconds = 0;
     720             : 
     721        1023 :         if( result == unit_test_monitor_t::test_ok ) {
     722             :             // 40. We are going to time the execution
     723        1023 :             boost::unit_test::timer::timer tu_timer;
     724             : 
     725             :             // we pass the random generator
     726        1023 :             const random_generator_helper& rand_gen = p_random_generator ? *p_random_generator : random_generator_helper();
     727             : 
     728        1023 :             if( tu.p_type == TUT_SUITE ) {
     729         292 :                 test_suite const& ts = static_cast<test_suite const&>( tu );
     730             : 
     731         292 :                 if( runtime_config::get<unsigned>( runtime_config::btrt_random_seed ) == 0 ) {
     732             :                     typedef std::pair<counter_t,test_unit_id> value_type;
     733             : 
     734       44046 :                     BOOST_TEST_FOREACH( value_type, chld, ts.m_ranked_children ) {
     735             :                         // tu_timer.elapsed() returns nanosec, timeout and child_timeout in microsec
     736       21879 :                         unsigned long int chld_timeout = child_timeout(
     737       21879 :                             timeout_microseconds,
     738       21879 :                             static_cast<unsigned long int>( microsecond_wall_time(tu_timer.elapsed()) ));
     739             : 
     740       21879 :                         result = (std::min)( result, execute_test_tree( chld.second, chld_timeout, &rand_gen ) );
     741             : 
     742       21877 :                         if( unit_test_monitor.is_critical_error( result ) )
     743           0 :                             break;
     744             : 
     745             :                         // we check for the time elapsed. If this is too high, we fail the current suite and return from here
     746       21877 :                         elapsed_microseconds = static_cast<unsigned long int>( microsecond_wall_time(tu_timer.elapsed()) );
     747             : 
     748       21877 :                         if( (timeout_microseconds > 0) && (elapsed_microseconds > timeout_microseconds) && (timeout_microseconds != TIMEOUT_EXCEEDED ) ) {
     749           0 :                             BOOST_TEST_FOREACH( test_observer*, to, m_observers ) {
     750           0 :                                 to->test_unit_timed_out(tu);
     751           0 :                             }
     752           0 :                             result = (std::min)( result, unit_test_monitor_t::os_timeout );
     753           0 :                             timeout_microseconds = TIMEOUT_EXCEEDED;
     754             :                             //break;
     755             :                             // we continue to explore the children, such that we can at least update their
     756             :                             // status to skipped
     757           0 :                         }
     758       21877 :                     }
     759         290 :                 }
     760             :                 else {
     761             :                     // Go through ranges of children with the same dependency rank and shuffle them
     762             :                     // independently. Execute each subtree in this order
     763           0 :                     test_unit_id_list children_with_the_same_rank;
     764             : 
     765             :                     typedef test_suite::children_per_rank::const_iterator it_type;
     766           0 :                     it_type it = ts.m_ranked_children.begin();
     767           0 :                     while( it != ts.m_ranked_children.end() ) {
     768           0 :                         children_with_the_same_rank.clear();
     769             : 
     770           0 :                         std::pair<it_type,it_type> range = ts.m_ranked_children.equal_range( it->first );
     771           0 :                         it = range.first;
     772           0 :                         while( it != range.second ) {
     773           0 :                             children_with_the_same_rank.push_back( it->second );
     774           0 :                             it++;
     775             :                         }
     776             : 
     777           0 :                         impl::random_shuffle( children_with_the_same_rank.begin(), children_with_the_same_rank.end(), rand_gen );
     778             : 
     779           0 :                         BOOST_TEST_FOREACH( test_unit_id, chld, children_with_the_same_rank ) {
     780           0 :                             unsigned long int chld_timeout = child_timeout(
     781           0 :                                 timeout_microseconds,
     782           0 :                                 static_cast<unsigned long int>(microsecond_wall_time(tu_timer.elapsed())) );
     783             : 
     784           0 :                             result = (std::min)( result, execute_test_tree( chld, chld_timeout, &rand_gen ) );
     785             : 
     786           0 :                             if( unit_test_monitor.is_critical_error( result ) )
     787           0 :                                 break;
     788             : 
     789             :                             // we check for the time elapsed. If this is too high, we fail the current suite and return from here
     790           0 :                             elapsed_microseconds = static_cast<unsigned long int>( microsecond_wall_time(tu_timer.elapsed()) );
     791           0 :                             if( (timeout_microseconds > 0) && (elapsed_microseconds > timeout_microseconds) && (timeout_microseconds != TIMEOUT_EXCEEDED ) ) {
     792           0 :                                 BOOST_TEST_FOREACH( test_observer*, to, m_observers ) {
     793           0 :                                     to->test_unit_timed_out(tu);
     794           0 :                                 }
     795           0 :                                 result = (std::min)( result, unit_test_monitor_t::os_timeout );
     796           0 :                                 timeout_microseconds = TIMEOUT_EXCEEDED;
     797             :                                 //break;
     798             :                                 // we continue to explore the children, such that we can at least update their
     799             :                                 // status to skipped
     800           0 :                             }
     801           0 :                         }
     802             :                     }
     803           0 :                 }
     804         290 :             }
     805             :             else { // TUT_CASE
     806         731 :                 test_case const& tc = static_cast<test_case const&>( tu );
     807             : 
     808             :                 // setup contexts
     809         731 :                 m_context_idx = 0;
     810             : 
     811             :                 // setup current test case
     812         731 :                 ut_detail::test_unit_id_restore restore_current_test_unit(m_curr_test_unit, tc.p_id);
     813             : 
     814             :                 // execute the test case body, transforms the time out to seconds
     815         732 :                 result = unit_test_monitor.execute_and_translate( tc.p_test_func, timeout_microseconds );
     816         730 :                 elapsed_microseconds = static_cast<unsigned long int>( microsecond_wall_time(tu_timer.elapsed()) );
     817             : 
     818             :                 // cleanup leftover context
     819         730 :                 m_context.clear();
     820             : 
     821             :                 // restore state (scope exit) and abort if necessary
     822         732 :             }
     823        1020 :         }
     824             : 
     825             :         // if run error is critical skip teardown, who knows what the state of the program at this point
     826        1020 :         if( !unit_test_monitor.is_critical_error( result ) ) {
     827             :             // execute teardown fixtures if any in reverse order
     828        1020 :             BOOST_TEST_REVERSE_FOREACH( test_unit_fixture_ptr, F, tu.p_fixtures.get() ) {
     829           0 :                 ut_detail::test_unit_id_restore restore_current_test_unit(m_curr_test_unit, tu.p_id);
     830           0 :                 result = (std::min)( result, unit_test_monitor.execute_and_translate( boost::bind( &test_unit_fixture::teardown, F ), 0 ) );
     831             : 
     832           0 :                 if( unit_test_monitor.is_critical_error( result ) )
     833           0 :                     break;
     834           0 :             }
     835        1020 :         }
     836             : 
     837             :         // notify all observers about abortion
     838        1020 :         if( unit_test_monitor.is_critical_error( result ) ) {
     839           0 :             BOOST_TEST_FOREACH( test_observer*, to, m_observers )
     840           0 :                 to->test_aborted();
     841           0 :         }
     842             : 
     843             :         // notify all observers about completion
     844        5100 :         BOOST_TEST_REVERSE_FOREACH( test_observer*, to, m_observers )
     845        2040 :             to->test_unit_finish( tu, elapsed_microseconds );
     846             : 
     847        1020 :         return result;
     848       22030 :     }
     849             : 
     850             :     //////////////////////////////////////////////////////////////////
     851             : 
     852       21879 :     unsigned long int child_timeout( unsigned long tu_timeout_microseconds, unsigned long elpsed_microsec )
     853             :     {
     854       21879 :       if( tu_timeout_microseconds == 0UL || tu_timeout_microseconds == TIMEOUT_EXCEEDED)
     855       21879 :           return tu_timeout_microseconds;
     856             : 
     857           0 :       return tu_timeout_microseconds > elpsed_microsec ?
     858           0 :                 tu_timeout_microseconds - elpsed_microsec
     859             :                 : TIMEOUT_EXCEEDED;
     860       21879 :     }
     861             : 
     862             :     struct priority_order {
     863        2181 :         bool operator()( test_observer* lhs, test_observer* rhs ) const
     864             :         {
     865        3634 :             return (lhs->priority() < rhs->priority()) ||
     866        1453 :                 ((lhs->priority() == rhs->priority()) && std::less<test_observer*>()(lhs, rhs));
     867             :         }
     868             :     };
     869             : 
     870             :     // Data members
     871             :     typedef std::map<test_unit_id,test_unit*>       test_unit_store;
     872             :     typedef std::set<test_observer*,priority_order> observer_store;
     873             :     struct context_frame {
     874           0 :         context_frame( std::string const& d, int id, bool sticky )
     875           0 :         : descr( d )
     876           0 :         , frame_id( id )
     877           0 :         , is_sticky( sticky )
     878           0 :         {}
     879             : 
     880             :         std::string descr;
     881             :         int         frame_id;
     882             :         bool        is_sticky;
     883             :     };
     884             :     typedef std::vector<context_frame> context_data;
     885             : 
     886             :     master_test_suite_t* m_master_test_suite;
     887             :     std::vector<test_suite*> m_auto_test_suites;
     888             : 
     889             :     test_unit_id    m_curr_test_unit;
     890             :     test_unit_store m_test_units;
     891             : 
     892             :     test_unit_id    m_next_test_case_id;
     893             :     test_unit_id    m_next_test_suite_id;
     894             : 
     895             :     bool            m_test_in_progress;
     896             : 
     897             :     observer_store  m_observers;
     898             :     context_data    m_context;
     899             :     int             m_context_idx;
     900             : 
     901             :     std::set<global_fixture*>  m_global_fixtures;
     902             : 
     903             :     boost::execution_monitor m_aux_em;
     904             : 
     905             :     std::map<output_format, runtime_config::stream_holder> m_log_sinks;
     906             :     runtime_config::stream_holder m_report_sink;
     907             : };
     908             : 
     909             : //____________________________________________________________________________//
     910             : 
     911             : namespace impl {
     912             : namespace {
     913             : 
     914             : #if defined(__CYGWIN__)
     915             : framework::state& s_frk_state() { static framework::state* the_inst = 0; if(!the_inst) the_inst = new framework::state; return *the_inst; }
     916             : #else
     917   188716644 : framework::state& s_frk_state() { static framework::state the_inst; return the_inst; }
     918             : #endif
     919             : 
     920             : } // local namespace
     921             : 
     922             : void
     923           0 : setup_for_execution( test_unit const& tu )
     924             : {
     925           0 :     s_frk_state().deduce_run_status( tu.p_id );
     926           0 : }
     927             : 
     928             : struct sum_to_first_only {
     929           0 :     sum_to_first_only() : is_first(true) {}
     930             :     template <class T, class U>
     931           0 :     T operator()(T const& l_, U const& r_) {
     932           0 :         if(is_first) {
     933           0 :             is_first = false;
     934           0 :             return l_ + r_.first;
     935             :         }
     936           0 :         return l_ + ", " + r_.first;
     937           0 :     }
     938             : 
     939             :     bool is_first;
     940             : };
     941             : 
     942             : void
     943         145 : shutdown_loggers_and_reports()
     944             : {
     945         145 :     s_frk_state().m_log_sinks.clear();
     946         145 :     s_frk_state().m_report_sink.setup( "stderr" );
     947         145 : }
     948             : 
     949             : void
     950         145 : unregister_global_fixture_and_configuration()
     951             : {
     952             :     // we make a copy as the set will change in the iteration
     953         145 :     std::set<global_fixture*> gfixture_copy(s_frk_state().m_global_fixtures);
     954         145 :     BOOST_TEST_FOREACH( global_fixture*, tuf, gfixture_copy ) {
     955           0 :         tuf->unregister_from_framework();
     956           0 :     }
     957         145 :     s_frk_state().m_global_fixtures.clear();
     958             : 
     959         145 :     state::observer_store gobserver_copy(s_frk_state().m_observers);
     960         725 :     BOOST_TEST_FOREACH( test_observer*, to, gobserver_copy ) {
     961         290 :         framework::deregister_observer( *to );
     962         290 :     }
     963         145 :     s_frk_state().m_observers.clear();
     964         145 : }
     965             : 
     966             : void
     967         146 : setup_loggers()
     968             : {
     969             : 
     970             :     BOOST_TEST_I_TRY {
     971             : 
     972             : #ifdef BOOST_TEST_SUPPORT_TOKEN_ITERATOR
     973         292 :         bool has_combined_logger = runtime_config::has( runtime_config::btrt_combined_logger )
     974         146 :             && !runtime_config::get< std::vector<std::string> >( runtime_config::btrt_combined_logger ).empty();
     975             : #else
     976             :         bool has_combined_logger = false;
     977             : #endif
     978             : 
     979         146 :         if( !has_combined_logger ) {
     980         146 :             unit_test_log.set_threshold_level( runtime_config::get<log_level>( runtime_config::btrt_log_level ) );
     981         146 :             const output_format format = runtime_config::get<output_format>( runtime_config::btrt_log_format );
     982         146 :             unit_test_log.set_format( format );
     983             : 
     984         146 :             runtime_config::stream_holder& stream_logger = s_frk_state().m_log_sinks[format];
     985         146 :             if( runtime_config::has( runtime_config::btrt_log_sink ) ) {
     986             :                 // we remove all streams in this case, so we do not specify the format
     987           0 :                 boost::function< void () > log_cleaner = boost::bind( &unit_test_log_t::set_stream,
     988           0 :                                                                       &unit_test_log,
     989           0 :                                                                       boost::ref(std::cout)
     990             :                                                                       );
     991           0 :                 stream_logger.setup( runtime_config::get<std::string>( runtime_config::btrt_log_sink ),
     992             :                                      log_cleaner );
     993           0 :             }
     994         146 :             unit_test_log.set_stream( stream_logger.ref() );
     995         146 :             unit_test_log.configure();
     996         146 :         }
     997             :         else
     998             :         {
     999             : 
    1000           0 :             const std::vector<std::string>& v_output_format = runtime_config::get< std::vector<std::string> >( runtime_config::btrt_combined_logger ) ;
    1001             : 
    1002             :             static const std::pair<const char*, log_level> all_log_levels[] = {
    1003             :                 std::make_pair( "all"           , log_successful_tests ),
    1004             :                 std::make_pair( "success"       , log_successful_tests ),
    1005             :                 std::make_pair( "test_suite"    , log_test_units ),
    1006             :                 std::make_pair( "unit_scope"    , log_test_units ),
    1007             :                 std::make_pair( "message"       , log_messages ),
    1008             :                 std::make_pair( "warning"       , log_warnings ),
    1009             :                 std::make_pair( "error"         , log_all_errors ),
    1010             :                 std::make_pair( "cpp_exception" , log_cpp_exception_errors ),
    1011             :                 std::make_pair( "system_error"  , log_system_errors ),
    1012             :                 std::make_pair( "fatal_error"   , log_fatal_errors ),
    1013             :                 std::make_pair( "nothing"       , log_nothing )
    1014             :             };
    1015             : 
    1016             :             static const std::pair<const char*, output_format> all_formats[] = {
    1017             :                 std::make_pair( "HRF"  , OF_CLF ),
    1018             :                 std::make_pair( "CLF"  , OF_CLF ),
    1019             :                 std::make_pair( "XML"  , OF_XML ),
    1020             :                 std::make_pair( "JUNIT", OF_JUNIT )
    1021             :             };
    1022             : 
    1023             : 
    1024           0 :             bool is_first = true;
    1025             : 
    1026           0 :             BOOST_TEST_FOREACH( const_string, current_multi_config, v_output_format ) {
    1027             : 
    1028             :     #ifdef BOOST_TEST_SUPPORT_TOKEN_ITERATOR
    1029             : 
    1030             :                 // ':' may be used for file names: C:/tmp/mylogsink.xml
    1031             :                 // we merge the tokens that start with / or \ with the previous one.
    1032           0 :                 std::vector<std::string> v_processed_tokens;
    1033             : 
    1034             :                 {
    1035           0 :                     utils::string_token_iterator current_config( current_multi_config, (utils::dropped_delimeters = ":",
    1036           0 :                                                                                         utils::kept_delimeters = utils::dt_none) );
    1037             : 
    1038           0 :                     for( ; current_config != utils::string_token_iterator() ; ++current_config) {
    1039           0 :                         std::string str_copy(current_config->begin(), current_config->end());
    1040           0 :                         if( ( str_copy[0] == '\\' || str_copy[0] == '/' )
    1041           0 :                             && v_processed_tokens.size() > 0) {
    1042           0 :                             v_processed_tokens.back() += ":" + str_copy; // ':' has been eaten up
    1043           0 :                         }
    1044             :                         else {
    1045           0 :                             v_processed_tokens.push_back(str_copy);
    1046             :                         }
    1047           0 :                     }
    1048             :                 }
    1049             : 
    1050           0 :                 BOOST_TEST_FOREACH( std::string const&, current_config, v_processed_tokens ) {
    1051             : 
    1052           0 :                     utils::string_token_iterator current_format_specs( current_config, (utils::keep_empty_tokens,
    1053           0 :                                                                                         utils::dropped_delimeters = ",",
    1054           0 :                                                                                         utils::kept_delimeters = utils::dt_none) );
    1055             : 
    1056           0 :                     output_format format = OF_INVALID ; // default
    1057           0 :                     if( current_format_specs != utils::string_token_iterator() &&
    1058           0 :                         current_format_specs->size() ) {
    1059             : 
    1060           0 :                         for(size_t elem=0; elem < sizeof(all_formats)/sizeof(all_formats[0]); elem++) {
    1061           0 :                             if(const_string(all_formats[elem].first) == *current_format_specs) {
    1062           0 :                                 format = all_formats[elem].second;
    1063           0 :                                 break;
    1064             :                             }
    1065           0 :                         }
    1066           0 :                     }
    1067             : 
    1068           0 :                     BOOST_TEST_I_ASSRT( format != OF_INVALID,
    1069             :                                         boost::runtime::access_to_missing_argument()
    1070             :                                             << "Unable to determine the logger type from '"
    1071             :                                             << current_config
    1072             :                                             << "'. Possible choices are: "
    1073             :                                             << std::accumulate(all_formats,
    1074             :                                                                all_formats + sizeof(all_formats)/sizeof(all_formats[0]),
    1075             :                                                                std::string(""),
    1076             :                                                                sum_to_first_only())
    1077             :                                       );
    1078             : 
    1079             :                     // activates this format
    1080           0 :                     if( is_first ) {
    1081           0 :                         unit_test_log.set_format( format );
    1082           0 :                     }
    1083             :                     else {
    1084           0 :                         unit_test_log.add_format( format );
    1085             :                     }
    1086           0 :                     is_first = false;
    1087             : 
    1088           0 :                     unit_test_log_formatter * const formatter = unit_test_log.get_formatter(format);
    1089           0 :                     BOOST_TEST_SETUP_ASSERT( formatter, "Logger setup error" );
    1090             : 
    1091           0 :                     log_level formatter_log_level = invalid_log_level;
    1092           0 :                     ++current_format_specs ;
    1093           0 :                     if( !current_format_specs->size() ) {
    1094           0 :                         formatter_log_level = formatter->get_log_level(); // default log level given by the formatter
    1095           0 :                     }
    1096           0 :                     else if( current_format_specs != utils::string_token_iterator() ) {
    1097             : 
    1098           0 :                         for(size_t elem=0; elem < sizeof(all_log_levels)/sizeof(all_log_levels[0]); elem++) {
    1099           0 :                             if(const_string(all_log_levels[elem].first) == *current_format_specs) {
    1100           0 :                                 formatter_log_level = all_log_levels[elem].second;
    1101           0 :                                 break;
    1102             :                             }
    1103           0 :                         }
    1104           0 :                     }
    1105             : 
    1106           0 :                     BOOST_TEST_I_ASSRT( formatter_log_level != invalid_log_level,
    1107             :                                         boost::runtime::access_to_missing_argument()
    1108             :                                             << "Unable to determine the log level from '"
    1109             :                                             << current_config
    1110             :                                             << "'. Possible choices are: "
    1111             :                                             << std::accumulate(all_log_levels,
    1112             :                                                                all_log_levels + sizeof(all_log_levels)/sizeof(all_log_levels[0]),
    1113             :                                                                std::string(""),
    1114             :                                                                sum_to_first_only())
    1115             :                                        );
    1116             : 
    1117           0 :                     unit_test_log.set_threshold_level( format, formatter_log_level );
    1118             : 
    1119           0 :                     runtime_config::stream_holder& stream_logger = s_frk_state().m_log_sinks[format];
    1120           0 :                     boost::function< void () > log_cleaner = boost::bind( &unit_test_log_t::set_stream,
    1121           0 :                                                                           &unit_test_log,
    1122           0 :                                                                           format,
    1123           0 :                                                                           boost::ref(std::cout) );
    1124           0 :                     if( ++current_format_specs != utils::string_token_iterator() &&
    1125           0 :                         current_format_specs->size() ) {
    1126           0 :                         stream_logger.setup( *current_format_specs,
    1127             :                                              log_cleaner );
    1128           0 :                     }
    1129             :                     else {
    1130           0 :                         stream_logger.setup( formatter->get_default_stream_description(),
    1131             :                                              log_cleaner );
    1132             :                     }
    1133           0 :                     unit_test_log.set_stream( format, stream_logger.ref() );
    1134           0 :                 }
    1135             :     #endif
    1136           0 :             } // for each logger
    1137             : 
    1138             :         } // if/else new logger API
    1139         146 :     } // BOOST_TEST_I_TRY
    1140             :     BOOST_TEST_I_CATCH( boost::runtime::init_error, ex ) {
    1141           0 :         BOOST_TEST_SETUP_ASSERT( false, ex.msg );
    1142           0 :     }
    1143             :     BOOST_TEST_I_CATCH( boost::runtime::input_error, ex ) {
    1144           0 :         std::cerr << ex.msg << "\n\n";
    1145             : 
    1146           0 :         BOOST_TEST_I_THROW( framework::nothing_to_test( boost::exit_exception_failure ) );
    1147           0 :     }
    1148             : 
    1149             : 
    1150         146 : }
    1151             : 
    1152             : //____________________________________________________________________________//
    1153             : 
    1154             : } // namespace impl
    1155             : 
    1156             : //____________________________________________________________________________//
    1157             : 
    1158             : // ************************************************************************** //
    1159             : // **************                framework::init               ************** //
    1160             : // ************************************************************************** //
    1161             : 
    1162             : void
    1163         146 : init( init_unit_test_func init_func, int argc, char* argv[] )
    1164             : {
    1165             :     using namespace impl;
    1166             : 
    1167             :     // 10. Set up runtime parameters
    1168         146 :     runtime_config::init( argc, argv );
    1169             : 
    1170             :     // 20. Set the desired log level, format and sink
    1171         146 :     impl::setup_loggers();
    1172             : 
    1173             :     // 30. Set the desired report level, format and sink
    1174         146 :     results_reporter::set_level( runtime_config::get<report_level>( runtime_config::btrt_report_level ) );
    1175         146 :     results_reporter::set_format( runtime_config::get<output_format>( runtime_config::btrt_report_format ) );
    1176             : 
    1177         146 :     if( runtime_config::has( runtime_config::btrt_report_sink ) ) {
    1178           0 :         boost::function< void () > report_cleaner = boost::bind( &results_reporter::set_stream,
    1179           0 :                                                                  boost::ref(std::cerr)
    1180             :                                                                 );
    1181           0 :         s_frk_state().m_report_sink.setup( runtime_config::get<std::string>( runtime_config::btrt_report_sink ),
    1182             :                                            report_cleaner );
    1183           0 :     }
    1184             : 
    1185         146 :     results_reporter::set_stream( s_frk_state().m_report_sink.ref() );
    1186             : 
    1187             :     // 40. Register default test observers
    1188         146 :     register_observer( results_collector );
    1189         146 :     register_observer( unit_test_log );
    1190             : 
    1191         146 :     if( runtime_config::get<bool>( runtime_config::btrt_show_progress ) ) {
    1192           0 :         progress_monitor.set_stream( std::cout ); // defaults to stdout
    1193           0 :         register_observer( progress_monitor );
    1194           0 :     }
    1195             : 
    1196             :     // 50. Set up memory leak detection
    1197         146 :     unsigned long detect_mem_leak = runtime_config::get<unsigned long>( runtime_config::btrt_detect_mem_leaks );
    1198         146 :     if( detect_mem_leak > 0 ) {
    1199         146 :         debug::detect_memory_leaks( true, runtime_config::get<std::string>( runtime_config::btrt_report_mem_leaks ) );
    1200         146 :         debug::break_memory_alloc( (long)detect_mem_leak );
    1201         146 :     }
    1202             : 
    1203             :     // 60. Initialize master unit test suite
    1204         146 :     master_test_suite().argc = argc;
    1205         146 :     master_test_suite().argv = argv;
    1206             : 
    1207             :     // 70. Invoke test module initialization routine
    1208             :     BOOST_TEST_I_TRY {
    1209         146 :         s_frk_state().m_aux_em.vexecute( boost::bind( &impl::invoke_init_func, init_func ) );
    1210         146 :     }
    1211             :     BOOST_TEST_I_CATCH( execution_exception, ex )  {
    1212           0 :         BOOST_TEST_SETUP_ASSERT( false, ex.what() );
    1213           0 :     }
    1214         146 : }
    1215             : 
    1216             : //____________________________________________________________________________//
    1217             : 
    1218             : void
    1219         146 : finalize_setup_phase( test_unit_id master_tu_id )
    1220             : {
    1221         146 :     if( master_tu_id == INV_TEST_UNIT_ID )
    1222         146 :         master_tu_id = master_test_suite().p_id;
    1223             : 
    1224             :     // 10. Apply all decorators to the auto test units
    1225             :     // 10. checks for consistency (duplicate names, etc)
    1226             :     class apply_decorators : public test_tree_visitor {
    1227             :     private:
    1228             :         // test_tree_visitor interface
    1229             : 
    1230       21316 :         bool    test_suite_start( test_suite const& ts) BOOST_OVERRIDE
    1231             :         {
    1232       21316 :             const_cast<test_suite&>(ts).generate();
    1233       21316 :             const_cast<test_suite&>(ts).check_for_duplicate_test_cases();
    1234       21316 :             return test_tree_visitor::test_suite_start(ts);
    1235             :         }
    1236             : 
    1237      123078 :         bool    visit( test_unit const& tu ) BOOST_OVERRIDE
    1238             :         {
    1239      123078 :             BOOST_TEST_FOREACH( decorator::base_ptr, d, tu.p_decorators.get() )
    1240           0 :                 d->apply( const_cast<test_unit&>(tu) );
    1241             : 
    1242      123078 :             return true;
    1243           0 :         }
    1244         146 :     } ad;
    1245         146 :     traverse_test_tree( master_tu_id, ad, true );
    1246             : 
    1247             :     // 20. Finalize setup phase
    1248         146 :     impl::order_info_per_tu tuoi;
    1249         146 :     impl::s_frk_state().deduce_siblings_order( master_tu_id, master_tu_id, tuoi );
    1250         146 :     impl::s_frk_state().finalize_default_run_status( master_tu_id, test_unit::RS_INVALID );
    1251         146 : }
    1252             : 
    1253             : // ************************************************************************** //
    1254             : // **************               test_in_progress               ************** //
    1255             : // ************************************************************************** //
    1256             : 
    1257             : bool
    1258     8816805 : test_in_progress()
    1259             : {
    1260     8816805 :     return impl::s_frk_state().m_test_in_progress;
    1261             : }
    1262             : 
    1263             : //____________________________________________________________________________//
    1264             : 
    1265             : // ************************************************************************** //
    1266             : // **************             framework::shutdown              ************** //
    1267             : // ************************************************************************** //
    1268             : 
    1269             : void
    1270         145 : shutdown()
    1271             : {
    1272             :     // shuts down the loggers singleton to avoid any further reference to the
    1273             :     // framework during the destruction of those
    1274         145 :     impl::shutdown_loggers_and_reports();
    1275             : 
    1276             :     // unregisters any global fixture and configuration object
    1277         145 :     impl::unregister_global_fixture_and_configuration();
    1278             : 
    1279             :     // eliminating some fake memory leak reports. See for more details:
    1280             :     // http://connect.microsoft.com/VisualStudio/feedback/details/106937/memory-leaks-reported-by-debug-crt-inside-typeinfo-name
    1281             : 
    1282             : #  if BOOST_WORKAROUND(BOOST_MSVC,  <= 1600 ) && !defined(_DLL) && defined(_DEBUG)
    1283             : #  if BOOST_WORKAROUND(BOOST_MSVC,  < 1600 )
    1284             : #define _Next next
    1285             : #define _MemPtr memPtr
    1286             : #endif
    1287             :    __type_info_node* pNode   = __type_info_root_node._Next;
    1288             :    __type_info_node* tmpNode = &__type_info_root_node;
    1289             : 
    1290             :    for( ; pNode!=NULL; pNode = tmpNode ) {
    1291             :       tmpNode = pNode->_Next;
    1292             :       delete pNode->_MemPtr;
    1293             :       delete pNode;
    1294             :    }
    1295             : #  if BOOST_WORKAROUND(BOOST_MSVC,  < 1600 )
    1296             : #undef _Next
    1297             : #undef _MemPtr
    1298             : #endif
    1299             : #  endif
    1300         145 : }
    1301             : 
    1302             : //____________________________________________________________________________//
    1303             : 
    1304             : // ************************************************************************** //
    1305             : // **************              register_test_unit              ************** //
    1306             : // ************************************************************************** //
    1307             : 
    1308             : void
    1309      101762 : register_test_unit( test_case* tc )
    1310             : {
    1311      101762 :     BOOST_TEST_SETUP_ASSERT( tc->p_id == INV_TEST_UNIT_ID, BOOST_TEST_L( "test case already registered" ) );
    1312             : 
    1313      101762 :     test_unit_id new_id = impl::s_frk_state().m_next_test_case_id;
    1314             : 
    1315      101762 :     BOOST_TEST_SETUP_ASSERT( new_id != MAX_TEST_CASE_ID, BOOST_TEST_L( "too many test cases" ) );
    1316             : 
    1317             :     typedef state::test_unit_store::value_type map_value_type;
    1318             : 
    1319      101762 :     impl::s_frk_state().m_test_units.insert( map_value_type( new_id, tc ) );
    1320      101762 :     impl::s_frk_state().m_next_test_case_id++;
    1321             : 
    1322      101762 :     impl::s_frk_state().set_tu_id( *tc, new_id );
    1323      101762 : }
    1324             : 
    1325             : //____________________________________________________________________________//
    1326             : 
    1327             : // ************************************************************************** //
    1328             : // **************              register_test_unit              ************** //
    1329             : // ************************************************************************** //
    1330             : 
    1331             : void
    1332       21316 : register_test_unit( test_suite* ts )
    1333             : {
    1334       21316 :     BOOST_TEST_SETUP_ASSERT( ts->p_id == INV_TEST_UNIT_ID, BOOST_TEST_L( "test suite already registered" ) );
    1335             : 
    1336       21316 :     test_unit_id new_id = impl::s_frk_state().m_next_test_suite_id;
    1337             : 
    1338       21316 :     BOOST_TEST_SETUP_ASSERT( new_id != MAX_TEST_SUITE_ID, BOOST_TEST_L( "too many test suites" ) );
    1339             : 
    1340             :     typedef state::test_unit_store::value_type map_value_type;
    1341             : 
    1342       21316 :     impl::s_frk_state().m_test_units.insert( map_value_type( new_id, ts ) );
    1343       21316 :     impl::s_frk_state().m_next_test_suite_id++;
    1344             : 
    1345       21316 :     impl::s_frk_state().set_tu_id( *ts, new_id );
    1346       21316 : }
    1347             : 
    1348             : //____________________________________________________________________________//
    1349             : 
    1350             : // ************************************************************************** //
    1351             : // **************             deregister_test_unit             ************** //
    1352             : // ************************************************************************** //
    1353             : 
    1354             : void
    1355           0 : deregister_test_unit( test_unit* tu )
    1356             : {
    1357           0 :     impl::s_frk_state().m_test_units.erase( tu->p_id );
    1358           0 : }
    1359             : 
    1360             : //____________________________________________________________________________//
    1361             : 
    1362             : // ************************************************************************** //
    1363             : // **************                     clear                    ************** //
    1364             : // ************************************************************************** //
    1365             : 
    1366             : void
    1367           0 : clear()
    1368             : {
    1369           0 :     impl::s_frk_state().clear();
    1370           0 : }
    1371             : 
    1372             : //____________________________________________________________________________//
    1373             : 
    1374             : // ************************************************************************** //
    1375             : // **************               register_observer              ************** //
    1376             : // ************************************************************************** //
    1377             : 
    1378             : void
    1379         583 : register_observer( test_observer& to )
    1380             : {
    1381         583 :     impl::s_frk_state().m_observers.insert( &to );
    1382         583 : }
    1383             : 
    1384             : //____________________________________________________________________________//
    1385             : 
    1386             : // ************************************************************************** //
    1387             : // **************              deregister_observer             ************** //
    1388             : // ************************************************************************** //
    1389             : 
    1390             : void
    1391         581 : deregister_observer( test_observer& to )
    1392             : {
    1393         581 :     impl::s_frk_state().m_observers.erase( &to );
    1394         581 : }
    1395             : 
    1396             : //____________________________________________________________________________//
    1397             : 
    1398             : // ************************************************************************** //
    1399             : // **************           register_global_fixture            ************** //
    1400             : // ************************************************************************** //
    1401             : 
    1402             : void
    1403           0 : register_global_fixture( global_fixture& tuf )
    1404             : {
    1405           0 :     impl::s_frk_state().m_global_fixtures.insert( &tuf );
    1406           0 : }
    1407             : 
    1408             : //____________________________________________________________________________//
    1409             : 
    1410             : // ************************************************************************** //
    1411             : // **************           deregister_global_fixture          ************** //
    1412             : // ************************************************************************** //
    1413             : 
    1414             : void
    1415           0 : deregister_global_fixture( global_fixture &tuf )
    1416             : {
    1417           0 :     impl::s_frk_state().m_global_fixtures.erase( &tuf );
    1418           0 : }
    1419             : 
    1420             : //____________________________________________________________________________//
    1421             : 
    1422             : // ************************************************************************** //
    1423             : // **************                  add_context                 ************** //
    1424             : // ************************************************************************** //
    1425             : 
    1426             : int
    1427           0 : add_context( ::boost::unit_test::lazy_ostream const& context_descr, bool sticky )
    1428             : {
    1429           0 :     std::stringstream buffer;
    1430           0 :     context_descr( buffer );
    1431           0 :     int res_idx  = impl::s_frk_state().m_context_idx++;
    1432             : 
    1433           0 :     impl::s_frk_state().m_context.push_back( state::context_frame( buffer.str(), res_idx, sticky ) );
    1434             : 
    1435           0 :     return res_idx;
    1436           0 : }
    1437             : 
    1438             : //____________________________________________________________________________//
    1439             : 
    1440             : // ************************************************************************** //
    1441             : // **************                 clear_context                ************** //
    1442             : // ************************************************************************** //
    1443             : 
    1444             : struct frame_with_id {
    1445           0 :     explicit frame_with_id( int id ) : m_id( id ) {}
    1446             : 
    1447           0 :     bool    operator()( state::context_frame const& f )
    1448             :     {
    1449           0 :         return f.frame_id == m_id;
    1450             :     }
    1451             :     int     m_id;
    1452             : };
    1453             : 
    1454             : //____________________________________________________________________________//
    1455             : 
    1456             : void
    1457     8816787 : clear_context( int frame_id )
    1458             : {
    1459     8816787 :     if( frame_id == -1 ) {   // clear all non sticky frames
    1460     8816787 :         for( int i=static_cast<int>(impl::s_frk_state().m_context.size())-1; i>=0; i-- )
    1461           0 :             if( !impl::s_frk_state().m_context[i].is_sticky )
    1462           0 :                 impl::s_frk_state().m_context.erase( impl::s_frk_state().m_context.begin()+i );
    1463     8816787 :     }
    1464             : 
    1465             :     else { // clear specific frame
    1466             :         state::context_data::iterator it =
    1467           0 :             std::find_if( impl::s_frk_state().m_context.begin(), impl::s_frk_state().m_context.end(), frame_with_id( frame_id ) );
    1468             : 
    1469           0 :         if( it != impl::s_frk_state().m_context.end() ) // really an internal error if this is not true
    1470           0 :             impl::s_frk_state().m_context.erase( it );
    1471             :     }
    1472     8816787 : }
    1473             : 
    1474             : //____________________________________________________________________________//
    1475             : 
    1476             : // ************************************************************************** //
    1477             : // **************                  get_context                 ************** //
    1478             : // ************************************************************************** //
    1479             : 
    1480             : context_generator
    1481         128 : get_context()
    1482             : {
    1483         128 :     return context_generator();
    1484             : }
    1485             : 
    1486             : //____________________________________________________________________________//
    1487             : 
    1488             : // ************************************************************************** //
    1489             : // **************               context_generator              ************** //
    1490             : // ************************************************************************** //
    1491             : 
    1492             : bool
    1493         128 : context_generator::is_empty() const
    1494             : {
    1495         128 :     return impl::s_frk_state().m_context.empty();
    1496             : }
    1497             : 
    1498             : //____________________________________________________________________________//
    1499             : 
    1500             : const_string
    1501           0 : context_generator::next() const
    1502             : {
    1503           0 :     return m_curr_frame < impl::s_frk_state().m_context.size() ? impl::s_frk_state().m_context[m_curr_frame++].descr : const_string();
    1504             : }
    1505             : 
    1506             : //____________________________________________________________________________//
    1507             : 
    1508             : // ************************************************************************** //
    1509             : // **************               master_test_suite              ************** //
    1510             : // ************************************************************************** //
    1511             : 
    1512             : master_test_suite_t&
    1513       24550 : master_test_suite()
    1514             : {
    1515       24550 :     if( !impl::s_frk_state().m_master_test_suite )
    1516         146 :         impl::s_frk_state().m_master_test_suite = new master_test_suite_t;
    1517             : 
    1518       24550 :     return *impl::s_frk_state().m_master_test_suite;
    1519           0 : }
    1520             : 
    1521             : namespace impl {
    1522             : 
    1523         292 : master_test_suite_name_setter::master_test_suite_name_setter(const_string name) {
    1524         146 :   assign_op( master_test_suite().p_name.value, name.trim( "\"" ), 0 );
    1525         292 : }
    1526             : 
    1527             : }
    1528             : 
    1529             : //____________________________________________________________________________//
    1530             : 
    1531             : // ************************************************************************** //
    1532             : // **************            current_auto_test_suite           ************** //
    1533             : // ************************************************************************** //
    1534             : 
    1535             : test_suite&
    1536      186442 : current_auto_test_suite( test_suite* ts, bool push_or_pop )
    1537             : {
    1538      186442 :     if( impl::s_frk_state().m_auto_test_suites.empty() )
    1539         146 :         impl::s_frk_state().m_auto_test_suites.push_back( &framework::master_test_suite() );
    1540             : 
    1541      186442 :     if( !push_or_pop )
    1542       21170 :         impl::s_frk_state().m_auto_test_suites.pop_back();
    1543      165272 :     else if( ts )
    1544       21170 :         impl::s_frk_state().m_auto_test_suites.push_back( ts );
    1545             : 
    1546      186442 :     return *impl::s_frk_state().m_auto_test_suites.back();
    1547             : }
    1548             : 
    1549             : //____________________________________________________________________________//
    1550             : 
    1551             : // ************************************************************************** //
    1552             : // **************               current_test_case              ************** //
    1553             : // ************************************************************************** //
    1554             : 
    1555             : test_case const&
    1556           0 : current_test_case()
    1557             : {
    1558           0 :     return get<test_case>( impl::s_frk_state().m_curr_test_unit );
    1559             : }
    1560             : 
    1561             : 
    1562             : test_unit const&
    1563           0 : current_test_unit()
    1564             : {
    1565           0 :     return *impl::s_frk_state().m_test_units[impl::s_frk_state().m_curr_test_unit];
    1566             : }
    1567             : 
    1568             : //____________________________________________________________________________//
    1569             : 
    1570             : test_unit_id
    1571     8816659 : current_test_case_id()
    1572             : {
    1573     8816659 :     return impl::s_frk_state().m_curr_test_unit;
    1574             : }
    1575             : 
    1576             : //____________________________________________________________________________//
    1577             : 
    1578             : // ************************************************************************** //
    1579             : // **************                framework::get                ************** //
    1580             : // ************************************************************************** //
    1581             : 
    1582             : test_unit&
    1583     2596959 : get( test_unit_id id, test_unit_type t )
    1584             : {
    1585     2596959 :     test_unit* res = impl::s_frk_state().m_test_units[id];
    1586             : 
    1587     2596959 :     BOOST_TEST_I_ASSRT( (res->p_type & t) != 0, internal_error( "Invalid test unit type" ) );
    1588             : 
    1589     2596959 :     return *res;
    1590           0 : }
    1591             : 
    1592             : //____________________________________________________________________________//
    1593             : 
    1594             : // ************************************************************************** //
    1595             : // **************                framework::run                ************** //
    1596             : // ************************************************************************** //
    1597             : 
    1598             : template <class Cont>
    1599             : struct swap_on_delete {
    1600         292 :     swap_on_delete(Cont& c1, Cont& c2) : m_c1(c1), m_c2(c2){}
    1601         290 :     ~swap_on_delete() {
    1602         145 :         m_c1.swap(m_c2);
    1603         290 :     }
    1604             : 
    1605             :     Cont& m_c1;
    1606             :     Cont& m_c2;
    1607             : };
    1608             : 
    1609             : struct register_observer_helper {
    1610         292 :   register_observer_helper(test_observer& observer)
    1611         146 :   : m_observer(observer)
    1612         146 :   { 
    1613         146 :     register_obs();
    1614         292 :   }
    1615             : 
    1616         290 :   ~register_observer_helper() {
    1617         145 :     if(m_registered)
    1618         145 :       deregister_observer( m_observer );
    1619         290 :   }
    1620             : 
    1621         146 :   void deregister_obs() {
    1622         146 :     m_registered = false;
    1623         146 :     deregister_observer( m_observer );
    1624         146 :   }
    1625             : 
    1626         291 :   void register_obs() {
    1627         291 :     m_registered = true;
    1628         291 :     register_observer( m_observer );
    1629         291 :   }
    1630             :   
    1631             : 
    1632             :   test_observer& m_observer;
    1633             :   bool m_registered;
    1634             : };
    1635             : 
    1636             : void
    1637         147 : run( test_unit_id id, bool continue_test )
    1638             : {
    1639         147 :     if( id == INV_TEST_UNIT_ID )
    1640         146 :         id = master_test_suite().p_id;
    1641             : 
    1642             :     // Figure out run status for execution phase
    1643         147 :     impl::s_frk_state().deduce_run_status( id );
    1644             : 
    1645         147 :     test_case_counter tcc;
    1646         147 :     traverse_test_tree( id, tcc );
    1647             : 
    1648         146 :     BOOST_TEST_SETUP_ASSERT( tcc.p_count != 0 , runtime_config::get<std::vector<std::string> >( runtime_config::btrt_run_filters ).empty()
    1649             :         ? BOOST_TEST_L( "test tree is empty" )
    1650             :         : BOOST_TEST_L( "no test cases matching filter or all test cases were disabled" ) );
    1651             : 
    1652         146 :     bool    was_in_progress     = framework::test_in_progress();
    1653         146 :     bool    call_start_finish   = !continue_test || !was_in_progress;
    1654         146 :     bool    init_ok             = true;
    1655         146 :     const_string setup_error;
    1656             : 
    1657         146 :     framework_init_observer_t local_init_observer;
    1658         147 :     register_observer_helper init_observer_helper( local_init_observer );
    1659             : 
    1660         147 :     if( call_start_finish ) {
    1661             :         // indicates the framework that no test is in progress now if observers need to be notified
    1662         146 :         impl::s_frk_state().m_test_in_progress = false;
    1663             :         // unit_test::framework_init_observer will get cleared first
    1664        1022 :         BOOST_TEST_FOREACH( test_observer*, to, impl::s_frk_state().m_observers ) {
    1665             :             BOOST_TEST_I_TRY {
    1666         438 :                 ut_detail::test_unit_id_restore restore_current_test_unit(impl::s_frk_state().m_curr_test_unit, id);
    1667         438 :                 unit_test_monitor_t::error_level result = unit_test_monitor.execute_and_translate( boost::bind( &test_observer::test_start, to, tcc.p_count, id ) );
    1668         438 :                 if( init_ok ) {
    1669         438 :                     if( result != unit_test_monitor_t::test_ok ) {
    1670           0 :                         init_ok = false;
    1671           0 :                     }
    1672             :                     else {
    1673         438 :                         if( local_init_observer.has_failed() ) {
    1674           0 :                             init_ok = false;
    1675           0 :                         }
    1676             :                     }
    1677         438 :                 }
    1678         438 :             }
    1679             :             BOOST_TEST_I_CATCH( execution_exception, ex ) {
    1680           0 :                 if( init_ok ) {
    1681             :                     // log only the first error
    1682           0 :                     init_ok = false;
    1683           0 :                     setup_error = ex.what();
    1684           0 :                 }
    1685             :                 // break; // we should continue otherwise loggers may have improper structure (XML start missing for instance)
    1686           0 :             }
    1687         438 :         }
    1688         146 :     }
    1689             : 
    1690             :     // removing this observer as it should not be of any use for the tests
    1691         147 :     init_observer_helper.deregister_obs();
    1692             : 
    1693         146 :     if( init_ok ) {
    1694             : 
    1695             :         // attaching the global fixtures to the main entry point
    1696         146 :         test_unit& entry_test_unit = framework::get( id, TUT_ANY );
    1697         292 :         std::vector<test_unit_fixture_ptr> v_saved_fixture(entry_test_unit.p_fixtures.value.begin(),
    1698         146 :                                                            entry_test_unit.p_fixtures.value.end());
    1699             : 
    1700         147 :         BOOST_TEST_FOREACH( test_unit_fixture*, tuf, impl::s_frk_state().m_global_fixtures ) {
    1701           0 :             entry_test_unit.p_fixtures.value.insert( entry_test_unit.p_fixtures.value.begin(),
    1702           0 :                                                      test_unit_fixture_ptr(new impl::global_fixture_handle(tuf)) );
    1703           0 :         }
    1704             : 
    1705         146 :         swap_on_delete< std::vector<test_unit_fixture_ptr> > raii_fixture(v_saved_fixture, entry_test_unit.p_fixtures.value);
    1706             : 
    1707             :         // now work in progress
    1708         147 :         impl::s_frk_state().m_test_in_progress = true;
    1709         146 :         unsigned seed = runtime_config::get<unsigned>( runtime_config::btrt_random_seed );
    1710         146 :         switch( seed ) {
    1711             :         case 0:
    1712         146 :             break;
    1713             :         case 1:
    1714           0 :             seed = static_cast<unsigned>( std::rand() ^ std::time( 0 ) ); // better init using std::rand() ^ ...
    1715             :             BOOST_FALLTHROUGH;
    1716             :         default:
    1717           0 :             BOOST_TEST_FRAMEWORK_MESSAGE( "Test cases order is shuffled using seed: " << seed );
    1718           0 :             std::srand( seed );
    1719           0 :         }
    1720             : 
    1721             :         // executing the test tree
    1722         146 :         impl::s_frk_state().execute_test_tree( id );
    1723             : 
    1724             :         // removing previously added global fixtures: dtor raii_fixture
    1725         145 :     }
    1726             : 
    1727         145 :     impl::s_frk_state().m_test_in_progress = false;
    1728             : 
    1729         145 :     results_reporter::make_report( INV_REPORT_LEVEL, id );
    1730             : 
    1731             :     // reinstalling this observer
    1732         145 :     init_observer_helper.register_obs();
    1733             : 
    1734         145 :     local_init_observer.clear();
    1735         145 :     if( call_start_finish ) {
    1736             :         // indicates the framework that no test is in progress anymore if observers need to be notified
    1737             :         // and this is a teardown, so assertions should not raise any exception otherwise an exception
    1738             :         // might be raised in a dtor of a global fixture
    1739         145 :         impl::s_frk_state().m_test_in_progress = false;
    1740        1015 :         BOOST_TEST_REVERSE_FOREACH( test_observer*, to, impl::s_frk_state().m_observers ) {
    1741         435 :             ut_detail::test_unit_id_restore restore_current_test_unit(impl::s_frk_state().m_curr_test_unit, id);
    1742         435 :             to->test_finish();
    1743         435 :         }
    1744         145 :     }
    1745             : 
    1746         145 :     impl::s_frk_state().m_test_in_progress = was_in_progress;
    1747             : 
    1748             :     // propagates the init/teardown error if any
    1749         145 :     BOOST_TEST_SETUP_ASSERT( init_ok && !local_init_observer.has_failed(), setup_error );
    1750         153 : }
    1751             : 
    1752             : //____________________________________________________________________________//
    1753             : 
    1754             : void
    1755           0 : run( test_unit const* tu, bool continue_test )
    1756             : {
    1757           0 :     run( tu->p_id, continue_test );
    1758           0 : }
    1759             : 
    1760             : //____________________________________________________________________________//
    1761             : 
    1762             : // ************************************************************************** //
    1763             : // **************               assertion_result               ************** //
    1764             : // ************************************************************************** //
    1765             : 
    1766             : void
    1767     8816659 : assertion_result( unit_test::assertion_result ar )
    1768             : {
    1769    44083295 :     BOOST_TEST_FOREACH( test_observer*, to, impl::s_frk_state().m_observers )
    1770    17633318 :         to->assertion_result( ar );
    1771     8816659 : }
    1772             : 
    1773             : //____________________________________________________________________________//
    1774             : 
    1775             : // ************************************************************************** //
    1776             : // **************               exception_caught               ************** //
    1777             : // ************************************************************************** //
    1778             : 
    1779             : void
    1780           0 : exception_caught( execution_exception const& ex )
    1781             : {
    1782           0 :     BOOST_TEST_FOREACH( test_observer*, to, impl::s_frk_state().m_observers )
    1783           0 :         to->exception_caught( ex );
    1784           0 : }
    1785             : 
    1786             : //____________________________________________________________________________//
    1787             : 
    1788             : // ************************************************************************** //
    1789             : // **************               test_unit_aborted              ************** //
    1790             : // ************************************************************************** //
    1791             : 
    1792             : void
    1793           0 : test_unit_aborted( test_unit const& tu )
    1794             : {
    1795           0 :     BOOST_TEST_FOREACH( test_observer*, to, impl::s_frk_state().m_observers )
    1796           0 :         to->test_unit_aborted( tu );
    1797           0 : }
    1798             : 
    1799             : // ************************************************************************** //
    1800             : // **************               test_aborted                   ************** //
    1801             : // ************************************************************************** //
    1802             : 
    1803             : void
    1804           0 : test_aborted( )
    1805             : {
    1806           0 :     BOOST_TEST_FOREACH( test_observer*, to, impl::s_frk_state().m_observers )
    1807           0 :         to->test_aborted( );
    1808           0 : }
    1809             : 
    1810             : 
    1811             : //____________________________________________________________________________//
    1812             : 
    1813             : } // namespace framework
    1814             : } // namespace unit_test
    1815             : } // namespace boost
    1816             : 
    1817             : #include <boost/test/detail/enable_warnings.hpp>
    1818             : 
    1819             : #endif // BOOST_TEST_FRAMEWORK_IPP_021005GER

Generated by: LCOV version 1.16