LCOV - code coverage report
Current view: top level - opt/homebrew/include/boost/test/impl - test_tree.ipp (source / functions) Hit Total Coverage
Test: total_coverage.info Lines: 148 277 53.4 %
Date: 2026-06-25 07:23:43 Functions: 25 56 44.6 %

          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
       9             : /// Provides core implementation for Unit Test Framework.
      10             : /// Extensions can be provided in separate files
      11             : // ***************************************************************************
      12             : 
      13             : #ifndef BOOST_TEST_UNIT_TEST_SUITE_IPP_012205GER
      14             : #define BOOST_TEST_UNIT_TEST_SUITE_IPP_012205GER
      15             : 
      16             : // Boost.Test
      17             : #include <boost/detail/workaround.hpp>
      18             : 
      19             : #include <boost/test/framework.hpp>
      20             : #include <boost/test/results_collector.hpp>
      21             : 
      22             : #include <boost/test/tree/test_unit.hpp>
      23             : #include <boost/test/tree/visitor.hpp>
      24             : #include <boost/test/tree/traverse.hpp>
      25             : #include <boost/test/tree/auto_registration.hpp>
      26             : #include <boost/test/tree/global_fixture.hpp>
      27             : 
      28             : #include <boost/test/utils/foreach.hpp>
      29             : #include <boost/test/utils/basic_cstring/io.hpp>
      30             : 
      31             : #include <boost/test/unit_test_parameters.hpp>
      32             : 
      33             : // STL
      34             : #include <algorithm>
      35             : #include <vector>
      36             : #include <set>
      37             : 
      38             : #include <boost/test/detail/suppress_warnings.hpp>
      39             : 
      40             : //____________________________________________________________________________//
      41             : 
      42             : namespace boost {
      43             : namespace unit_test {
      44             : 
      45             : // ************************************************************************** //
      46             : // **************                   test_unit                  ************** //
      47             : // ************************************************************************** //
      48             : 
      49      491728 : test_unit::test_unit( const_string name, const_string file_name, std::size_t line_num, test_unit_type t )
      50      122932 : : p_type( t )
      51      122932 : , p_type_name( t == TUT_CASE ? "case" : "suite" )
      52      122932 : , p_file_name( file_name )
      53      122932 : , p_line_num( line_num )
      54      122932 : , p_id( INV_TEST_UNIT_ID )
      55      122932 : , p_parent_id( INV_TEST_UNIT_ID )
      56      122932 : , p_name( std::string( name.begin(), name.size() ) )
      57      122932 : , p_timeout( 0 )
      58      122932 : , p_expected_failures( 0 )
      59      122932 : , p_default_status( RS_INHERIT )
      60      122932 : , p_run_status( RS_INVALID )
      61      122932 : , p_sibling_rank(0)
      62           0 : {
      63      122932 : }
      64             : 
      65             : //____________________________________________________________________________//
      66             : 
      67         730 : test_unit::test_unit( const_string module_name )
      68         146 : : p_type( TUT_SUITE )
      69         146 : , p_type_name( "module" )
      70         146 : , p_line_num( 0 )
      71         146 : , p_id( INV_TEST_UNIT_ID )
      72         146 : , p_parent_id( INV_TEST_UNIT_ID )
      73         146 : , p_name( std::string( module_name.begin(), module_name.size() ) )
      74         146 : , p_timeout( 0 )
      75         146 : , p_expected_failures( 0 )
      76         146 : , p_default_status( RS_INHERIT )
      77         146 : , p_run_status( RS_INVALID )
      78         146 : , p_sibling_rank(0)
      79           0 : {
      80         146 : }
      81             : 
      82             : //____________________________________________________________________________//
      83             : 
      84           0 : test_unit::~test_unit()
      85           0 : {
      86           0 :     framework::deregister_test_unit( this );
      87           0 : }
      88             : 
      89             : //____________________________________________________________________________//
      90             : 
      91             : void
      92           0 : test_unit::depends_on( test_unit* tu )
      93             : {
      94           0 :     BOOST_TEST_SETUP_ASSERT( p_id != framework::master_test_suite().p_id, 
      95             :                              "Can't add dependency to the master test suite" );
      96             : 
      97           0 :     p_dependencies.value.push_back( tu->p_id );
      98           0 : }
      99             : 
     100             : //____________________________________________________________________________//
     101             : 
     102             : void
     103           0 : test_unit::add_precondition( precondition_t const& pc )
     104             : {
     105           0 :     p_preconditions.value.push_back( pc );
     106           0 : }
     107             : 
     108             : //____________________________________________________________________________//
     109             : 
     110             : test_tools::assertion_result
     111        1023 : test_unit::check_preconditions() const
     112             : {
     113        1023 :     BOOST_TEST_FOREACH( test_unit_id, dep_id, p_dependencies.get() ) {
     114           0 :         test_unit const& dep = framework::get( dep_id, TUT_ANY );
     115             : 
     116           0 :         if( !dep.is_enabled() ) {
     117           0 :             test_tools::assertion_result res(false);
     118           0 :             res.message() << "dependency test " << dep.p_type_name << " \"" << dep.full_name() << "\" is disabled";
     119           0 :             return res;
     120           0 :         }
     121             : 
     122           0 :         test_results const& test_rslt = unit_test::results_collector.results( dep_id );
     123           0 :         if( !test_rslt.passed() ) {
     124           0 :             test_tools::assertion_result res(false);
     125           0 :             res.message() << "dependency test " << dep.p_type_name << " \"" << dep.full_name() << (test_rslt.skipped() ? "\" was skipped":"\" has failed");
     126           0 :             return res;
     127           0 :         }
     128             : 
     129           0 :         if( test_rslt.p_test_cases_skipped > 0 ) {
     130           0 :             test_tools::assertion_result res(false);
     131           0 :             res.message() << "dependency test " << dep.p_type_name << " \"" << dep.full_name() << "\" has skipped test cases";
     132           0 :             return res;
     133           0 :         }
     134           0 :     }
     135             : 
     136        1023 :     BOOST_TEST_FOREACH( precondition_t, precondition, p_preconditions.get() ) {
     137           0 :         test_tools::assertion_result res = precondition( p_id );
     138           0 :         if( !res ) {
     139           0 :             test_tools::assertion_result res_out(false);
     140           0 :             res_out.message() << "precondition failed";
     141           0 :             if( !res.has_empty_message() )
     142           0 :                 res_out.message() << ": " << res.message();
     143           0 :             return res_out;
     144           0 :         }
     145           0 :     }
     146             : 
     147        1023 :     return true;
     148        1023 : }
     149             : 
     150             : //____________________________________________________________________________//
     151             : 
     152             : void
     153           0 : test_unit::increase_exp_fail( counter_t num )
     154             : {
     155           0 :     p_expected_failures.value += num;
     156             : 
     157           0 :     if( p_parent_id != INV_TEST_UNIT_ID )
     158           0 :         framework::get<test_suite>( p_parent_id ).increase_exp_fail( num );
     159           0 : }
     160             : 
     161             : //____________________________________________________________________________//
     162             : 
     163             : std::string
     164       21008 : test_unit::full_name() const
     165             : {
     166       21008 :     if( p_parent_id == INV_TEST_UNIT_ID || p_parent_id == framework::master_test_suite().p_id )
     167       21005 :         return p_name;
     168             : 
     169           3 :     std::string res = framework::get<test_suite>( p_parent_id ).full_name();
     170           3 :     res.append("/");
     171             : 
     172           3 :     res.append( p_name );
     173             : 
     174           3 :     return res;
     175       21011 : }
     176             : 
     177             : //____________________________________________________________________________//
     178             : 
     179             : void
     180           0 : test_unit::add_label( const_string l )
     181             : {
     182           0 :     p_labels.value.push_back( std::string() + l );
     183           0 : }
     184             : 
     185             : //____________________________________________________________________________//
     186             : 
     187             : bool
     188           0 : test_unit::has_label( const_string l ) const
     189             : {
     190           0 :     return std::find( p_labels->begin(), p_labels->end(), l ) != p_labels->end();
     191             : }
     192             : 
     193             : //____________________________________________________________________________//
     194             : 
     195             : // ************************************************************************** //
     196             : // **************                   test_case                  ************** //
     197             : // ************************************************************************** //
     198             : 
     199           0 : test_case::test_case( const_string name, boost::function<void ()> const& test_func )
     200           0 : : test_unit( name, "", 0, static_cast<test_unit_type>(type) )
     201           0 : , p_test_func( test_func )
     202           0 : {
     203           0 :     framework::register_test_unit( this );
     204           0 : }
     205             : 
     206             : //____________________________________________________________________________//
     207             : 
     208      203524 : test_case::test_case( const_string name, const_string file_name, std::size_t line_num, boost::function<void ()> const& test_func )
     209      101762 : : test_unit( name, file_name, line_num, static_cast<test_unit_type>(type) )
     210      101762 : , p_test_func( test_func )
     211      101762 : {
     212      101762 :     framework::register_test_unit( this );
     213      203524 : }
     214             : 
     215             : //____________________________________________________________________________//
     216             : 
     217             : // ************************************************************************** //
     218             : // **************                  test_suite                  ************** //
     219             : // ************************************************************************** //
     220             : 
     221             : //____________________________________________________________________________//
     222             : 
     223       63510 : test_suite::test_suite( const_string name, const_string file_name, std::size_t line_num )
     224       21170 : : test_unit( ut_detail::normalize_test_case_name( name ), file_name, line_num, static_cast<test_unit_type>(type) )
     225       63510 : {
     226       21170 :     framework::register_test_unit( this );
     227       42340 : }
     228             : 
     229             : //____________________________________________________________________________//
     230             : 
     231         292 : test_suite::test_suite( const_string module_name )
     232         146 : : test_unit( module_name )
     233         292 : {
     234         146 :     framework::register_test_unit( this );
     235         146 : }
     236             : 
     237             : //____________________________________________________________________________//
     238             : 
     239             : void
     240      122932 : test_suite::add( test_unit* tu, counter_t expected_failures, unsigned timeout )
     241             : {
     242      122932 :     tu->p_timeout.value = timeout;
     243             : 
     244      122932 :     m_children.push_back( tu->p_id );
     245      122932 :     tu->p_parent_id.value = p_id;
     246             : 
     247      122932 :     if( tu->p_expected_failures != 0 )
     248           0 :         increase_exp_fail( tu->p_expected_failures );
     249             : 
     250      122932 :     if( expected_failures )
     251           0 :         tu->increase_exp_fail( expected_failures );
     252      122932 : }
     253             : 
     254             : //____________________________________________________________________________//
     255             : 
     256             : void
     257           0 : test_suite::add( test_unit_generator const& gen, unsigned timeout )
     258             : {
     259             :     test_unit* tu;
     260           0 :     while((tu = gen.next()) != 0)
     261           0 :         add( tu, 0, timeout );
     262           0 : }
     263             : 
     264             : //____________________________________________________________________________//
     265             : 
     266             : void
     267           0 : test_suite::add( test_unit_generator const& gen, decorator::collector_t& decorators )
     268             : {
     269             :     test_unit* tu;
     270           0 :     while((tu = gen.next()) != 0) {
     271           0 :         decorators.store_in( *tu );
     272           0 :         add( tu, 0 );
     273             :     }
     274           0 :     decorators.reset();
     275           0 : }
     276             : 
     277             : //____________________________________________________________________________//
     278             : 
     279             : void
     280           0 : test_suite::add( boost::shared_ptr<test_unit_generator> gen_ptr, decorator::collector_t& decorators )
     281             : {
     282           0 :     std::pair<boost::shared_ptr<test_unit_generator>, std::vector<decorator::base_ptr> > tmp_p(gen_ptr, decorators.get_lazy_decorators() );
     283           0 :     m_generators.push_back(tmp_p);
     284           0 :     decorators.reset();
     285           0 : }
     286             : 
     287             : //____________________________________________________________________________//
     288             : 
     289             : void
     290       21316 : test_suite::generate( )
     291             : {
     292             :     typedef std::pair<boost::shared_ptr<test_unit_generator>, std::vector<decorator::base_ptr> > element_t;
     293             :   
     294       21316 :     for(std::vector<element_t>::iterator it(m_generators.begin()), ite(m_generators.end());
     295       21316 :         it < ite;
     296           0 :         ++it)
     297             :     {
     298             :       test_unit* tu;
     299           0 :       while((tu = it->first->next()) != 0) {
     300           0 :           tu->p_decorators.value.insert( tu->p_decorators.value.end(), it->second.begin(), it->second.end() );
     301             :           //it->second.store_in( *tu );
     302           0 :           add( tu, 0 );
     303             :       }
     304             : 
     305           0 :     }
     306       21316 :     m_generators.clear();
     307             :     
     308             :     #if 0
     309             :     test_unit* tu;
     310             :     while((tu = gen.next()) != 0) {
     311             :         decorators.store_in( *tu );
     312             :         add( tu, 0 );
     313             :     }
     314             :     #endif
     315       21316 : }
     316             : 
     317             : //____________________________________________________________________________//
     318             : 
     319             : void
     320       21316 : test_suite::check_for_duplicate_test_cases() {
     321             :     // check for clashing names #12597
     322       21316 :     std::set<std::string> names;
     323      144248 :     for( test_unit_id_list::const_iterator it(m_children.begin()), ite(m_children.end());
     324      144248 :          it < ite;
     325      122932 :          ++it) {
     326      122932 :          std::string name = framework::get(*it, TUT_ANY).p_name;
     327      122932 :          std::pair<std::set<std::string>::iterator, bool> ret = names.insert(name);
     328      122932 :          BOOST_TEST_SETUP_ASSERT(ret.second,
     329             :             "test unit with name '"
     330             :             + name
     331             :             + std::string("' registered multiple times in the test suite '")
     332             :             + this->p_name.value
     333             :             + "'");
     334      122932 :     }
     335             : 
     336             :     return;
     337       21316 : }
     338             : 
     339             : //____________________________________________________________________________//
     340             : 
     341             : void
     342           0 : test_suite::remove( test_unit_id id )
     343             : {
     344           0 :     test_unit_id_list::iterator it = std::find( m_children.begin(), m_children.end(), id );
     345             : 
     346           0 :     if( it != m_children.end() )
     347           0 :         m_children.erase( it );
     348           0 : }
     349             : 
     350             : //____________________________________________________________________________//
     351             : 
     352             : test_unit_id
     353       21170 : test_suite::get( const_string tu_name ) const
     354             : {
     355     3069650 :     BOOST_TEST_FOREACH( test_unit_id, id, m_children ) {
     356     1524240 :         if( tu_name == framework::get( id, ut_detail::test_id_2_unit_type( id ) ).p_name.get() )
     357           0 :             return id;
     358     1524240 :     }
     359             : 
     360       21170 :     return INV_TEST_UNIT_ID;
     361       21170 : }
     362             : 
     363             : //____________________________________________________________________________//
     364             : 
     365             : // ************************************************************************** //
     366             : // **************               master_test_suite              ************** //
     367             : // ************************************************************************** //
     368             : 
     369         292 : master_test_suite_t::master_test_suite_t()
     370         146 : : test_suite( "Master Test Suite" )
     371         146 : , argc( 0 )
     372         146 : , argv( 0 )
     373         292 : {
     374         146 :     p_default_status.value = RS_ENABLED;
     375         292 : }
     376             : 
     377             : // ************************************************************************** //
     378             : // **************               traverse_test_tree             ************** //
     379             : // ************************************************************************** //
     380             : 
     381             : void
     382      307405 : traverse_test_tree( test_case const& tc, test_tree_visitor& V, bool ignore_status )
     383             : {
     384      307405 :     if( tc.is_enabled() || ignore_status )
     385      307405 :         V.visit( tc );
     386      307405 : }
     387             : 
     388             : //____________________________________________________________________________//
     389             : 
     390             : void
     391      149043 : traverse_test_tree( test_suite const& suite, test_tree_visitor& V, bool ignore_status )
     392             : {
     393             :     // skip disabled test suite unless we asked to ignore this condition
     394      149043 :     if( !ignore_status && !suite.is_enabled() )
     395       42048 :         return;
     396             : 
     397             :     // Invoke test_suite_start callback
     398      106995 :     if( !V.test_suite_start( suite ) )
     399       42195 :         return;
     400             : 
     401             :     // Recurse into children
     402       64800 :     std::size_t total_children = suite.m_children.size();
     403      499080 :     for( std::size_t i=0; i < total_children; ) {
     404             :         // this statement can remove the test unit from this list
     405      434280 :         traverse_test_tree( suite.m_children[i], V, ignore_status );
     406      434280 :         if( total_children > suite.m_children.size() )
     407           0 :             total_children = suite.m_children.size();
     408             :         else
     409      434280 :             ++i;
     410             :     }
     411             : 
     412             :     // Invoke test_suite_finish callback
     413       64800 :     V.test_suite_finish( suite );
     414      149043 : }
     415             : 
     416             : //____________________________________________________________________________//
     417             : 
     418             : void
     419      435156 : traverse_test_tree( test_unit_id id, test_tree_visitor& V, bool ignore_status )
     420             : {
     421      435156 :     if( ut_detail::test_id_2_unit_type( id ) == TUT_CASE )
     422      307405 :         traverse_test_tree( framework::get<test_case>( id ), V, ignore_status );
     423             :     else
     424      127751 :         traverse_test_tree( framework::get<test_suite>( id ), V, ignore_status );
     425      435156 : }
     426             : 
     427             : //____________________________________________________________________________//
     428             : 
     429             : // ************************************************************************** //
     430             : // **************               object generators              ************** //
     431             : // ************************************************************************** //
     432             : 
     433             : namespace ut_detail {
     434             : 
     435             : std::string
     436      122932 : normalize_test_case_name( const_string name )
     437             : {
     438      122932 :     std::string norm_name( name.begin(), name.end() );
     439             : 
     440      122932 :     if( name[0] == '&' )
     441           0 :         norm_name = norm_name.substr( 1 );
     442             : 
     443             :     // trim spaces
     444      122932 :     std::size_t first_not_space = norm_name.find_first_not_of(' ');
     445      122932 :     if( first_not_space ) {
     446           0 :         norm_name.erase(0, first_not_space);
     447           0 :     }
     448             : 
     449      122932 :     std::size_t last_not_space = norm_name.find_last_not_of(' ');
     450      122932 :     if( last_not_space !=std::string::npos ) {
     451      122932 :         norm_name.erase(last_not_space + 1);
     452      122932 :     }
     453             : 
     454             :     // sanitize all chars that might be used in runtime filters
     455             :     static const char to_replace[] = { ':', '*', '@', '+', '!', '/', ',' };
     456      983456 :     for(std::size_t index = 0;
     457      983456 :         index < sizeof(to_replace)/sizeof(to_replace[0]);
     458      860524 :         index++) {
     459      860524 :         std::replace(norm_name.begin(), norm_name.end(), to_replace[index], '_');
     460      860524 :     }
     461             : 
     462      122932 :     return norm_name;
     463      122932 : }
     464             : 
     465             : //____________________________________________________________________________//
     466             : 
     467             : // ************************************************************************** //
     468             : // **************           auto_test_unit_registrar           ************** //
     469             : // ************************************************************************** //
     470             : 
     471      203524 : auto_test_unit_registrar::auto_test_unit_registrar( test_case* tc, decorator::collector_t& decorators, counter_t exp_fail )
     472      101762 : {
     473      101762 :     framework::current_auto_test_suite().add( tc, exp_fail );
     474             : 
     475      101762 :     decorators.store_in( *tc );
     476      101762 :     decorators.reset();
     477      203524 : }
     478             : 
     479             : //____________________________________________________________________________//
     480             : 
     481       42340 : auto_test_unit_registrar::auto_test_unit_registrar( const_string ts_name, const_string ts_file, std::size_t ts_line, decorator::collector_t& decorators )
     482       21170 : {
     483       21170 :     test_unit_id id = framework::current_auto_test_suite().get( ts_name );
     484             : 
     485             :     test_suite* ts;
     486             : 
     487       21170 :     if( id != INV_TEST_UNIT_ID ) {
     488           0 :         ts = &framework::get<test_suite>( id );
     489           0 :         BOOST_ASSERT( ts->p_parent_id == framework::current_auto_test_suite().p_id );
     490           0 :     }
     491             :     else {
     492       21170 :         ts = new test_suite( ts_name, ts_file, ts_line );
     493       21170 :         framework::current_auto_test_suite().add( ts );
     494             :     }
     495             : 
     496       21170 :     decorators.store_in( *ts );
     497       21170 :     decorators.reset();
     498             : 
     499       21170 :     framework::current_auto_test_suite( ts );
     500       42340 : }
     501             : 
     502             : //____________________________________________________________________________//
     503             : 
     504           0 : auto_test_unit_registrar::auto_test_unit_registrar( test_unit_generator const& tc_generator, decorator::collector_t& decorators )
     505           0 : {
     506           0 :     framework::current_auto_test_suite().add( tc_generator, decorators );
     507           0 : }
     508             : 
     509             : //____________________________________________________________________________//
     510             : 
     511           0 : auto_test_unit_registrar::auto_test_unit_registrar( boost::shared_ptr<test_unit_generator> tc_generator, decorator::collector_t& decorators )
     512           0 : {
     513           0 :     framework::current_auto_test_suite().add( tc_generator, decorators );
     514           0 : }
     515             : 
     516             : 
     517             : //____________________________________________________________________________//
     518             : 
     519       42340 : auto_test_unit_registrar::auto_test_unit_registrar( int )
     520       21170 : {
     521       21170 :     framework::current_auto_test_suite( 0, false );
     522       42340 : }
     523             : 
     524             : //____________________________________________________________________________//
     525             : 
     526             : } // namespace ut_detail
     527             : 
     528             : // ************************************************************************** //
     529             : // **************                global_fixture                ************** //
     530             : // ************************************************************************** //
     531             : 
     532           0 : global_fixture::global_fixture(): registered(false)
     533           0 : {
     534           0 :     framework::register_global_fixture( *this );
     535           0 :     registered = true;
     536           0 : }
     537             : 
     538           0 : void global_fixture::unregister_from_framework() {
     539             :     // not accessing the framework singleton after deregistering -> release
     540             :     // of the observer from the framework
     541           0 :     if(registered) {
     542           0 :         framework::deregister_global_fixture( *this );
     543           0 :     }
     544           0 :     registered = false;
     545           0 : }
     546             : 
     547           0 : global_fixture::~global_fixture()
     548           0 : {
     549           0 :     this->unregister_from_framework();
     550           0 : }
     551             : 
     552             : // ************************************************************************** //
     553             : // **************            global_configuration              ************** //
     554             : // ************************************************************************** //
     555             : 
     556           0 : global_configuration::global_configuration(): registered(false)
     557           0 : {
     558           0 :     framework::register_observer( *this );
     559           0 :     registered = true;
     560           0 : }
     561             : 
     562           0 : void global_configuration::unregister_from_framework()
     563             : {
     564             :     // not accessing the framework singleton after deregistering -> release
     565             :     // of the observer from the framework
     566           0 :     if(registered) {
     567           0 :         framework::deregister_observer( *this );
     568           0 :     }
     569           0 :     registered = false;
     570           0 : }
     571             : 
     572           0 : global_configuration::~global_configuration()
     573           0 : {
     574           0 :     this->unregister_from_framework();
     575           0 : }
     576             : 
     577             : //____________________________________________________________________________//
     578             : 
     579             : } // namespace unit_test
     580             : } // namespace boost
     581             : 
     582             : #include <boost/test/detail/enable_warnings.hpp>
     583             : 
     584             : #endif // BOOST_TEST_UNIT_TEST_SUITE_IPP_012205GER

Generated by: LCOV version 1.16