Boost logo

Boost-Commit :

Subject: [Boost-commit] svn:boost r74402 - in trunk/boost/test: . impl
From: gennadiy.rozental_at_[hidden]
Date: 2011-09-15 23:26:17


Author: rogeeff
Date: 2011-09-15 23:26:16 EDT (Thu, 15 Sep 2011)
New Revision: 74402
URL: http://svn.boost.org/trac/boost/changeset/74402

Log:
introduced support for "run by label"
run by name/label now recognizes dependencies
traverse_test_tree now able traverse whole tree ignoring enable/disable status
dependencies became public property of test unit
Text files modified:
   trunk/boost/test/framework.hpp | 6
   trunk/boost/test/impl/framework.ipp | 285 +++++++++++++++++++++++++++++++++++++++
   trunk/boost/test/impl/unit_test_main.ipp | 141 +++----------------
   trunk/boost/test/impl/unit_test_suite.ipp | 40 +++-
   trunk/boost/test/unit_test_suite_impl.hpp | 24 ++-
   5 files changed, 354 insertions(+), 142 deletions(-)

Modified: trunk/boost/test/framework.hpp
==============================================================================
--- trunk/boost/test/framework.hpp (original)
+++ trunk/boost/test/framework.hpp 2011-09-15 23:26:16 EDT (Thu, 15 Sep 2011)
@@ -103,6 +103,12 @@
 BOOST_TEST_DECL void exception_caught( execution_exception const& );
 BOOST_TEST_DECL void test_unit_aborted( test_unit const& );
 
+namespace impl { // publisized to facilitate internal unit test only
+
+void apply_filters( test_unit_id );
+
+} // namespace impl
+
 // ************************************************************************** //
 // ************** framework errors ************** //
 // ************************************************************************** //

Modified: trunk/boost/test/impl/framework.ipp
==============================================================================
--- trunk/boost/test/impl/framework.ipp (original)
+++ trunk/boost/test/impl/framework.ipp 2011-09-15 23:26:16 EDT (Thu, 15 Sep 2011)
@@ -28,6 +28,11 @@
 #include <boost/test/results_reporter.hpp>
 #include <boost/test/test_tools.hpp>
 
+#if !defined(__BORLANDC__) && !BOOST_WORKAROUND( BOOST_MSVC, < 1300 ) && !BOOST_WORKAROUND( __SUNPRO_CC, < 0x5100 )
+#define BOOST_TEST_SUPPORT_RUN_BY_NAME
+#include <boost/test/utils/iterator/token_iterator.hpp>
+#endif
+
 #include <boost/test/detail/unit_test_parameters.hpp>
 #include <boost/test/detail/global_typedef.hpp>
 
@@ -35,6 +40,7 @@
 
 // Boost
 #include <boost/timer.hpp>
+#include <boost/bind.hpp>
 
 // STL
 #include <map>
@@ -55,7 +61,7 @@
 namespace unit_test {
 
 // ************************************************************************** //
-// ************** test_start calls wrapper ************** //
+// ************** test_start calls wrapper ************** //
 // ************************************************************************** //
 
 namespace ut_detail {
@@ -102,7 +108,198 @@
     init_unit_test_func m_init_func;
 };
 
-}
+// ************************************************************************** //
+// ************** tu_enabler ************** //
+// ************************************************************************** //
+
+struct tu_enabler : public test_tree_visitor {
+ explicit tu_enabler( bool on_off ) : m_on_off( on_off ) {}
+private:
+ virtual void visit( test_case const& tc ) { tc.p_enabled.value = m_on_off; }
+ virtual bool test_suite_start( test_suite const& ts ) { ts.p_enabled.value = m_on_off; return true; }
+
+ // Data members
+ bool m_on_off;
+};
+
+// ************************************************************************** //
+// ************** name_filter ************** //
+// ************************************************************************** //
+
+typedef std::list<std::pair<test_unit_id,bool> > tu_enable_list;
+
+class name_filter : public test_tree_visitor {
+ struct component {
+ component( const_string name ) // has to be implicit
+ {
+ if( name == "*" )
+ m_kind = SFK_ALL;
+ else if( first_char( name ) == '*' && last_char( name ) == '*' ) {
+ m_kind = SFK_SUBSTR;
+ m_name = name.substr( 1, name.size()-1 );
+ }
+ else if( first_char( name ) == '*' ) {
+ m_kind = SFK_TRAILING;
+ m_name = name.substr( 1 );
+ }
+ else if( last_char( name ) == '*' ) {
+ m_kind = SFK_LEADING;
+ m_name = name.substr( 0, name.size()-1 );
+ }
+ else {
+ m_kind = SFK_MATCH;
+ m_name = name;
+ }
+ };
+
+ bool pass( test_unit const& tu ) const
+ {
+ const_string name( tu.p_name );
+
+ switch( m_kind ) {
+ default:
+ case SFK_ALL:
+ return true;
+ case SFK_LEADING:
+ return name.substr( 0, m_name.size() ) == m_name;
+ case SFK_TRAILING:
+ return name.size() >= m_name.size() && name.substr( name.size() - m_name.size() ) == m_name;
+ case SFK_SUBSTR:
+ return name.find( m_name ) != const_string::npos;
+ case SFK_MATCH:
+ return m_name == tu.p_name.get();
+ }
+ }
+ enum kind { SFK_ALL, SFK_LEADING, SFK_TRAILING, SFK_SUBSTR, SFK_MATCH };
+
+ kind m_kind;
+ const_string m_name;
+ };
+
+public:
+ // Constructor
+ name_filter( tu_enable_list& tu_to_enable, const_string tc_to_run ) : m_tu_to_enable( tu_to_enable ), m_depth( 0 )
+ {
+#ifdef BOOST_TEST_SUPPORT_RUN_BY_NAME
+ string_token_iterator tit( tc_to_run, (dropped_delimeters = "/", kept_delimeters = dt_none) );
+
+ while( tit != string_token_iterator() ) {
+ m_components.push_back( std::vector<component>( string_token_iterator( *tit, (dropped_delimeters = ",", kept_delimeters = dt_none) ),
+ string_token_iterator() ) );
+
+ ++tit;
+ }
+#endif
+ }
+
+private:
+ bool filter_unit( test_unit const& tu )
+ {
+ // skip master test suite
+ if( m_depth == 0 )
+ return true;
+
+ // corresponding name filters are at level m_depth-1
+ std::vector<component> const& filters = m_components[m_depth-1];
+
+ // look for match
+ return std::find_if( filters.begin(), filters.end(), bind( &component::pass, _1, boost::ref(tu) ) ) != filters.end();
+ }
+
+ // test_tree_visitor interface
+ virtual void visit( test_case const& tc )
+ {
+ if( filter_unit( tc ) )
+ m_tu_to_enable.push_back( std::make_pair( tc.p_id, false ) ); // found a test case; add it to enable list without children
+ }
+ virtual bool test_suite_start( test_suite const& ts )
+ {
+ if( filter_unit( ts ) ) {
+ if( m_depth < m_components.size() ) {
+ ++m_depth;
+ return true;
+ }
+
+ m_tu_to_enable.push_back( std::make_pair( ts.p_id, true ) ); // found a test suite; add it to enable list with children and stop recursion
+ }
+
+ return false;
+ }
+
+ // Data members
+ typedef std::vector<std::vector<component> > components_per_level;
+
+ components_per_level m_components;
+ tu_enable_list& m_tu_to_enable;
+ unsigned m_depth;
+};
+
+// ************************************************************************** //
+// ************** label_filter ************** //
+// ************************************************************************** //
+
+class label_filter : public test_tree_visitor {
+public:
+ label_filter( tu_enable_list& tu_to_enable, const_string label )
+ : m_tu_to_enable( tu_to_enable )
+ , m_label( label )
+ {}
+
+private:
+ bool filter_unit( test_unit const& tu )
+ {
+ return tu.has_label( m_label );
+ }
+
+ // test_tree_visitor interface
+ virtual void visit( test_case const& tc )
+ {
+ if( filter_unit( tc ) )
+ m_tu_to_enable.push_back( std::make_pair( tc.p_id, false ) ); // found a test case; add it to enable list without children
+ }
+ virtual bool test_suite_start( test_suite const& ts )
+ {
+ if( filter_unit( ts ) ) {
+ m_tu_to_enable.push_back( std::make_pair( ts.p_id, true ) ); // found a test suite; add it to enable list with children and stop recursion
+ return false;
+ }
+
+ return true;
+ }
+
+ // Data members
+ const_string m_label;
+ tu_enable_list& m_tu_to_enable;
+};
+
+// ************************************************************************** //
+// ************** tu_collector ************** //
+// ************************************************************************** //
+
+class tu_collector : public test_tree_visitor {
+public:
+ explicit tu_collector( tu_enable_list& tu_to_enable ) : m_tu_to_enable( tu_to_enable ) {}
+
+private:
+ // test_tree_visitor interface
+ virtual void visit( test_case const& tc )
+ {
+ if( !tc.p_enabled )
+ m_tu_to_enable.push_back( std::make_pair( tc.p_id, false ) );
+ }
+ virtual bool test_suite_start( test_suite const& ts )
+ {
+ if( !ts.p_enabled )
+ m_tu_to_enable.push_back( std::make_pair( ts.p_id, false ) );
+
+ return true;
+ }
+
+ // Data members
+ tu_enable_list& m_tu_to_enable;
+};
+
+} // namespace ut_detail
 
 // ************************************************************************** //
 // ************** framework ************** //
@@ -155,7 +352,6 @@
         BOOST_TEST_FOREACH( test_observer*, to, m_observers )
             to->test_unit_start( tc );
 
-
         // execute the test case body
         boost::timer tc_timer;
         test_unit_id bkup = m_curr_test_case;
@@ -225,7 +421,7 @@
 
         std::string descr;
         int frame_id;
- bool is_sticky;
+ bool is_sticky;
     };
     typedef std::vector<context_frame> context_data;
 
@@ -299,11 +495,90 @@
         throw setup_error( ex.what() );
     }
 
+ impl::apply_filters( master_test_suite().p_id );
+
     s_frk_impl().m_is_initialized = true;
 }
 
 //____________________________________________________________________________//
 
+namespace impl {
+void
+apply_filters( test_unit_id tu_id )
+{
+ if( runtime_config::test_to_run().empty() ) {
+ ut_detail::tu_enabler enable( true );
+
+ traverse_test_tree( tu_id, enable );
+ }
+ else {
+ // 10. first disable all tu
+ ut_detail::tu_enabler disable( false );
+ traverse_test_tree( tu_id, disable );
+
+ // 20. collect tu to enable based on filters
+ ut_detail::tu_enable_list tu_to_enable;
+
+ BOOST_TEST_FOREACH( std::string const&, filter, runtime_config::test_to_run() ) {
+ if( filter.empty() )
+ continue;
+
+ if( filter[0] == '@' ) {
+ ut_detail::label_filter lf( tu_to_enable, const_string(filter).trim_left(1) );
+ traverse_test_tree( tu_id, lf, true );
+ }
+ else {
+ ut_detail::name_filter nf( tu_to_enable, filter );
+ traverse_test_tree( tu_id, nf, true );
+ }
+ }
+
+ // 30. enable all tu collected along with their parents, dependencies and children where necessary
+ while( !tu_to_enable.empty() ) {
+ std::pair<test_unit_id,bool> data = tu_to_enable.front();
+ test_unit const& tu = framework::get( data.first, tut_any );
+
+ tu_to_enable.pop_front();
+
+ if( tu.p_enabled )
+ continue;
+
+ // 31. enable tu
+ tu.p_enabled.value = true;
+
+ // 32. master test suite - we are done
+ if( tu.p_id == tu_id )
+ continue;
+
+ // 33. add parent to the list (without children)
+ if( !framework::get( tu.p_parent_id, tut_any ).p_enabled )
+ tu_to_enable.push_back( std::make_pair( tu.p_parent_id, false ) );
+
+ // 34. add dependencies to the list (with children)
+ BOOST_TEST_FOREACH( test_unit_id, dep_id, tu.p_dependencies.get() ) {
+ test_unit const& dep = framework::get( dep_id, tut_any );
+
+ if( !dep.p_enabled ) {
+ BOOST_TEST_MESSAGE( "Including test " << dep.p_type_name << ' ' << dep.p_name <<
+ " as a dependacy of test " << tu.p_type_name << ' ' << tu.p_name );
+
+ tu_to_enable.push_back( std::make_pair( dep_id, true ) );
+ }
+ }
+
+ // 35. add all children to the list recursively
+ if( data.second && tu.p_type == tut_suite ) {
+ ut_detail::tu_collector collect( tu_to_enable );
+ traverse_test_tree( tu.p_id, collect, true );
+ }
+ }
+ }
+}
+
+} // namespace impl
+
+//____________________________________________________________________________//
+
 bool
 is_initialized()
 {
@@ -498,7 +773,7 @@
     test_case_counter tcc;
     traverse_test_tree( id, tcc );
 
- BOOST_TEST_SETUP_ASSERT( tcc.p_count != 0 , runtime_config::test_to_run().is_empty()
+ BOOST_TEST_SETUP_ASSERT( tcc.p_count != 0 , runtime_config::test_to_run().empty()
         ? BOOST_TEST_L( "test tree is empty" )
         : BOOST_TEST_L( "no test cases matching filter" ) );
 

Modified: trunk/boost/test/impl/unit_test_main.ipp
==============================================================================
--- trunk/boost/test/impl/unit_test_main.ipp (original)
+++ trunk/boost/test/impl/unit_test_main.ipp 2011-09-15 23:26:16 EDT (Thu, 15 Sep 2011)
@@ -23,18 +23,13 @@
 
 #include <boost/test/detail/unit_test_parameters.hpp>
 
-#if !defined(__BORLANDC__) && !BOOST_WORKAROUND( BOOST_MSVC, < 1300 ) && !BOOST_WORKAROUND( __SUNPRO_CC, < 0x5100 )
-#define BOOST_TEST_SUPPORT_RUN_BY_NAME
-#include <boost/test/utils/iterator/token_iterator.hpp>
-#endif
-
 // Boost
 #include <boost/cstdlib.hpp>
-#include <boost/bind.hpp>
 
 // STL
 #include <stdexcept>
 #include <iostream>
+#include <iomanip>
 
 #include <boost/test/detail/suppress_warnings.hpp>
 
@@ -44,128 +39,38 @@
 
 namespace unit_test {
 
+namespace ut_detail {
+
 // ************************************************************************** //
-// ************** test_case_filter ************** //
+// ************** test_tree_reporter ************** //
 // ************************************************************************** //
 
-class test_case_filter : public test_tree_visitor {
-public:
- struct single_filter {
- single_filter( const_string in )
- {
- if( in == "*" )
- m_kind = SFK_ALL;
- else if( first_char( in ) == '*' && last_char( in ) == '*' ) {
- m_kind = SFK_SUBSTR;
- m_value = in.substr( 1, in.size()-1 );
- }
- else if( first_char( in ) == '*' ) {
- m_kind = SFK_TRAILING;
- m_value = in.substr( 1 );
- }
- else if( last_char( in ) == '*' ) {
- m_kind = SFK_LEADING;
- m_value = in.substr( 0, in.size()-1 );
- }
- else {
- m_kind = SFK_MATCH;
- m_value = in;
- }
- };
-
- bool pass( test_unit const& tu ) const
- {
- const_string name( tu.p_name );
-
- switch( m_kind ) {
- default:
- case SFK_ALL:
- return true;
-
- case SFK_LEADING:
- return name.substr( 0, m_value.size() ) == m_value;
-
- case SFK_TRAILING:
- return name.size() >= m_value.size() && name.substr( name.size() - m_value.size() ) == m_value;
-
- case SFK_SUBSTR:
- return name.find( m_value ) != const_string::npos;
-
- case SFK_MATCH:
- return m_value == tu.p_name.get();
- }
- }
- enum kind { SFK_ALL, SFK_LEADING, SFK_TRAILING, SFK_SUBSTR, SFK_MATCH };
+struct test_tree_reporter : test_tree_visitor {
+ test_tree_reporter() : m_indent( -4 ) {} // skip master test suite
 
- kind m_kind;
- const_string m_value;
- };
- // Constructor
-#ifndef BOOST_TEST_SUPPORT_RUN_BY_NAME
- explicit test_case_filter( const_string ) : m_depth( 0 ) {}
-#else
- explicit test_case_filter( const_string tc_to_run )
- : m_depth( 0 )
+private:
+ virtual void visit( test_case const& tc )
     {
- string_token_iterator tit( tc_to_run, (dropped_delimeters = "/", kept_delimeters = dt_none) );
-
- while( tit != string_token_iterator() ) {
- m_filters.push_back(
- std::vector<single_filter>( string_token_iterator( *tit, (dropped_delimeters = ",", kept_delimeters = dt_none) ),
- string_token_iterator() ) );
-
- ++tit;
- }
+ results_reporter::get_stream() << std::setw( m_indent ) << "" << tc.p_name << "\n";
     }
-#endif
-
- void filter_unit( test_unit const& tu )
+ virtual bool test_suite_start( test_suite const& ts )
     {
- if( (++m_depth - 1) > m_filters.size() ) {
- tu.p_enabled.value = true;
- return;
- }
-
- if( m_depth == 1 )
- return;
-
- std::vector<single_filter> const& filters = m_filters[m_depth-2];
-
- tu.p_enabled.value =
- std::find_if( filters.begin(), filters.end(), bind( &single_filter::pass, _1, boost::ref(tu) ) ) != filters.end();
+ if( m_indent >= 0 )
+ results_reporter::get_stream() << std::setw( m_indent ) << "" << ts.p_name << "\n";
+ m_indent += 4;
+ return true;
     }
-
- // test tree visitor interface
- virtual void visit( test_case const& tc )
+ virtual void test_suite_finish( test_suite const& )
     {
- if( m_depth < m_filters.size() ) {
- tc.p_enabled.value = false;
- return;
- }
-
- filter_unit( tc );
-
- --m_depth;
+ m_indent -= 4;
     }
 
- virtual bool test_suite_start( test_suite const& ts )
- {
- filter_unit( ts );
-
- if( !ts.p_enabled )
- --m_depth;
-
- return ts.p_enabled;
- }
-
- virtual void test_suite_finish( test_suite const& ) { --m_depth; }
-
-private:
     // Data members
- std::vector<std::vector<single_filter> > m_filters;
- unsigned m_depth;
+ int m_indent;
 };
 
+} // namespace ut_detail
+
 // ************************************************************************** //
 // ************** unit_test_main ************** //
 // ************************************************************************** //
@@ -176,10 +81,12 @@
     try {
         framework::init( init_func, argc, argv );
 
- if( !runtime_config::test_to_run().is_empty() ) {
- test_case_filter filter( runtime_config::test_to_run() );
+ if( runtime_config::list_content() ) {
+ ut_detail::test_tree_reporter content_reporter;
+
+ traverse_test_tree( framework::master_test_suite().p_id, content_reporter );
 
- traverse_test_tree( framework::master_test_suite().p_id, filter );
+ return boost::exit_success;
         }
 
         framework::run();

Modified: trunk/boost/test/impl/unit_test_suite.ipp
==============================================================================
--- trunk/boost/test/impl/unit_test_suite.ipp (original)
+++ trunk/boost/test/impl/unit_test_suite.ipp 2011-09-15 23:26:16 EDT (Thu, 15 Sep 2011)
@@ -70,7 +70,7 @@
 void
 test_unit::depends_on( test_unit* tu )
 {
- m_dependencies.push_back( tu->p_id );
+ p_dependencies.value.push_back( tu->p_id );
 }
 
 //____________________________________________________________________________//
@@ -78,7 +78,7 @@
 bool
 test_unit::check_dependencies() const
 {
- BOOST_TEST_FOREACH( test_unit_id, tu_id, m_dependencies ) {
+ BOOST_TEST_FOREACH( test_unit_id, tu_id, p_dependencies.get() ) {
         if( !unit_test::results_collector.results( tu_id ).passed() )
             return false;
     }
@@ -99,6 +99,22 @@
 
 //____________________________________________________________________________//
 
+void
+test_unit::add_label( const_string l )
+{
+ m_labels.push_back( std::string( l.begin(), l.end() ) );
+}
+
+//____________________________________________________________________________//
+
+bool
+test_unit::has_label( const_string l ) const
+{
+ return std::find( m_labels.begin(), m_labels.end(), l ) != m_labels.end();
+}
+
+//____________________________________________________________________________//
+
 // ************************************************************************** //
 // ************** test_case ************** //
 // ************************************************************************** //
@@ -187,30 +203,30 @@
 // ************************************************************************** //
 
 void
-traverse_test_tree( test_case const& tc, test_tree_visitor& V )
+traverse_test_tree( test_case const& tc, test_tree_visitor& V, bool ignore_status )
 {
- if( tc.p_enabled )
- V.visit( tc );
+ if( tc.p_enabled || ignore_status )
+ V.visit( tc );
 }
 
 //____________________________________________________________________________//
 
 void
-traverse_test_tree( test_suite const& suite, test_tree_visitor& V )
+traverse_test_tree( test_suite const& suite, test_tree_visitor& V, bool ignore_status )
 {
- if( !suite.p_enabled || !V.test_suite_start( suite ) )
+ if( (!suite.p_enabled && !ignore_status) || !V.test_suite_start( suite ) )
         return;
 
     try {
         if( runtime_config::random_seed() == 0 ) {
             BOOST_TEST_FOREACH( test_unit_id, id, suite.m_members )
- traverse_test_tree( id, V );
+ traverse_test_tree( id, V, ignore_status );
         }
         else {
             std::vector<test_unit_id> members( suite.m_members );
             std::random_shuffle( members.begin(), members.end() );
             BOOST_TEST_FOREACH( test_unit_id, id, members )
- traverse_test_tree( id, V );
+ traverse_test_tree( id, V, ignore_status );
         }
         
     } catch( test_being_aborted const& ) {
@@ -226,12 +242,12 @@
 //____________________________________________________________________________//
 
 void
-traverse_test_tree( test_unit_id id, test_tree_visitor& V )
+traverse_test_tree( test_unit_id id, test_tree_visitor& V, bool ignore_status )
 {
     if( ut_detail::test_id_2_unit_type( id ) == tut_case )
- traverse_test_tree( framework::get<test_case>( id ), V );
+ traverse_test_tree( framework::get<test_case>( id ), V, ignore_status );
     else
- traverse_test_tree( framework::get<test_suite>( id ), V );
+ traverse_test_tree( framework::get<test_suite>( id ), V, ignore_status );
 }
 
 //____________________________________________________________________________//

Modified: trunk/boost/test/unit_test_suite_impl.hpp
==============================================================================
--- trunk/boost/test/unit_test_suite_impl.hpp (original)
+++ trunk/boost/test/unit_test_suite_impl.hpp 2011-09-15 23:26:16 EDT (Thu, 15 Sep 2011)
@@ -52,6 +52,7 @@
 class BOOST_TEST_DECL test_unit {
 public:
     enum { type = tut_any };
+ typedef std::list<test_unit_id> id_list;
 
     // Constructor
     test_unit( const_string tu_name, test_unit_type t );
@@ -60,13 +61,20 @@
     void depends_on( test_unit* tu );
     bool check_dependencies() const;
 
+ // labels management
+ void add_label( const_string l );
+ bool has_label( const_string l ) const;
+
     // Public r/o properties
     typedef BOOST_READONLY_PROPERTY(test_unit_id,(framework_impl)) id_t;
     typedef BOOST_READONLY_PROPERTY(test_unit_id,(test_suite)) parent_id_t;
+ typedef BOOST_READONLY_PROPERTY(id_list,(test_unit)) id_list_t;
+
     readonly_property<test_unit_type> p_type; // type for this test unit
     readonly_property<const_string> p_type_name; // "case"/"suite"
     id_t p_id; // unique id for this test unit
     parent_id_t p_parent_id; // parent test suite id
+ id_list_t p_dependencies; // list of test units this one depends on
 
     // Public r/w properties
     readwrite_property<std::string> p_name; // name for this test unit
@@ -81,7 +89,7 @@
 
 private:
     // Data members
- std::list<test_unit_id> m_dependencies;
+ std::list<std::string> m_labels;
 };
 
 // ************************************************************************** //
@@ -141,7 +149,7 @@
 
 protected:
     friend BOOST_TEST_DECL
- void traverse_test_tree( test_suite const&, test_tree_visitor& );
+ void traverse_test_tree( test_suite const&, test_tree_visitor&, bool );
     friend class framework_impl;
     virtual ~test_suite() {}
 
@@ -185,19 +193,19 @@
 // ************** traverse_test_tree ************** //
 // ************************************************************************** //
 
-BOOST_TEST_DECL void traverse_test_tree( test_case const&, test_tree_visitor& );
-BOOST_TEST_DECL void traverse_test_tree( test_suite const&, test_tree_visitor& );
-BOOST_TEST_DECL void traverse_test_tree( test_unit_id , test_tree_visitor& );
+BOOST_TEST_DECL void traverse_test_tree( test_case const&, test_tree_visitor&, bool ignore_status = false );
+BOOST_TEST_DECL void traverse_test_tree( test_suite const&, test_tree_visitor&, bool ignore_status = false );
+BOOST_TEST_DECL void traverse_test_tree( test_unit_id , test_tree_visitor&, bool ignore_status = false );
 
 //____________________________________________________________________________//
 
 inline void
-traverse_test_tree( test_unit const& tu, test_tree_visitor& V )
+traverse_test_tree( test_unit const& tu, test_tree_visitor& V, bool ignore_status = false )
 {
     if( tu.p_type == tut_case )
- traverse_test_tree( static_cast<test_case const&>( tu ), V );
+ traverse_test_tree( static_cast<test_case const&>( tu ), V, ignore_status );
     else
- traverse_test_tree( static_cast<test_suite const&>( tu ), V );
+ traverse_test_tree( static_cast<test_suite const&>( tu ), V, ignore_status );
 }
 
 //____________________________________________________________________________//


Boost-Commit list run by bdawes at acm.org, david.abrahams at rcn.com, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk