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