diff options
Diffstat (limited to 'boost/test/impl/framework.ipp')
-rw-r--r-- | boost/test/impl/framework.ipp | 242 |
1 files changed, 213 insertions, 29 deletions
diff --git a/boost/test/impl/framework.ipp b/boost/test/impl/framework.ipp index 78459bac27..a513c612e1 100644 --- a/boost/test/impl/framework.ipp +++ b/boost/test/impl/framework.ipp @@ -22,6 +22,7 @@ #include <boost/test/unit_test_parameters.hpp> #include <boost/test/unit_test_log.hpp> +#include <boost/test/unit_test_log_formatter.hpp> #include <boost/test/unit_test_monitor.hpp> #include <boost/test/results_collector.hpp> #include <boost/test/progress_monitor.hpp> @@ -39,6 +40,7 @@ #include <boost/test/utils/foreach.hpp> #include <boost/test/utils/basic_cstring/io.hpp> +#include <boost/test/utils/basic_cstring/compare.hpp> #include <boost/test/detail/global_typedef.hpp> #include <boost/test/detail/throw_exception.hpp> @@ -53,6 +55,7 @@ #include <set> #include <cstdlib> #include <ctime> +#include <numeric> #ifdef BOOST_NO_STDC_NAMESPACE namespace std { using ::time; using ::srand; } @@ -98,7 +101,7 @@ tu_depth( test_unit_id tu_id, test_unit_id master_tu_id, order_info_per_tu& tuoi return 0; order_info& info = tuoi[tu_id]; - + if( info.depth == -1 ) info.depth = tu_depth( get_tu_parent( tu_id ), master_tu_id, tuoi ) + 1; @@ -236,12 +239,12 @@ public: name_filter( test_unit_id_list& targ_list, const_string filter_expr ) : m_targ_list( targ_list ), m_depth( 0 ) { #ifdef BOOST_TEST_SUPPORT_TOKEN_ITERATOR - utils::string_token_iterator tit( filter_expr, (utils::dropped_delimeters = "/", + utils::string_token_iterator tit( filter_expr, (utils::dropped_delimeters = "/", utils::kept_delimeters = utils::dt_none) ); while( tit != utils::string_token_iterator() ) { - m_components.push_back( - std::vector<component>( utils::string_token_iterator( *tit, (utils::dropped_delimeters = ",", + m_components.push_back( + std::vector<component>( utils::string_token_iterator( *tit, (utils::dropped_delimeters = ",", utils::kept_delimeters = utils::dt_none) ), utils::string_token_iterator() ) ); @@ -261,6 +264,7 @@ private: std::vector<component> const& filters = m_components[m_depth-1]; // look for match + using namespace boost::placeholders; return std::find_if( filters.begin(), filters.end(), bind( &component::pass, _1, boost::ref(tu) ) ) != filters.end(); } @@ -351,8 +355,8 @@ private: if( dep.p_run_status == tu.p_run_status ) continue; - BOOST_TEST_MESSAGE( "Including test " << dep.p_type_name << ' ' << dep.full_name() << - " as a dependency of test " << tu.p_type_name << ' ' << tu.full_name() ); + BOOST_TEST_FRAMEWORK_MESSAGE( "Including test " << dep.p_type_name << ' ' << dep.full_name() << + " as a dependency of test " << tu.p_type_name << ' ' << tu.full_name() ); m_dep_collector->push_back( dep_id ); } @@ -397,22 +401,32 @@ parse_filters( test_unit_id master_tu_id, test_unit_id_list& tu_to_enable, test_ BOOST_TEST_FOREACH( const_string, filter, filters ) { BOOST_TEST_SETUP_ASSERT( !filter.is_empty(), "Invalid filter specification" ); - enum { SELECTOR, ENABLER, DISABLER } filter_type = SELECTOR; + // each --run_test command may also be separated by a ':' (environment variable) + utils::string_token_iterator t_filter_it( filter, (utils::dropped_delimeters = ":", + utils::kept_delimeters = utils::dt_none) ); - // 11. Deduce filter type - if( filter[0] == '!' || filter[0] == '+' ) { - filter_type = filter[0] == '+' ? ENABLER : DISABLER; - filter.trim_left( 1 ); - BOOST_TEST_SETUP_ASSERT( !filter.is_empty(), "Invalid filter specification" ); - } + while( t_filter_it != utils::string_token_iterator() ) { + const_string filter_token = *t_filter_it; + + enum { SELECTOR, ENABLER, DISABLER } filter_type = SELECTOR; + + // 11. Deduce filter type + if( filter_token[0] == '!' || filter_token[0] == '+' ) { + filter_type = filter_token[0] == '+' ? ENABLER : DISABLER; + filter_token.trim_left( 1 ); + BOOST_TEST_SETUP_ASSERT( !filter_token.is_empty(), "Invalid filter specification" ); + } - had_selector_filter |= filter_type == SELECTOR; + had_selector_filter |= filter_type == SELECTOR; - // 12. Add test units to corresponding list - switch( filter_type ) { - case SELECTOR: - case ENABLER: add_filtered_test_units( master_tu_id, filter, tu_to_enable ); break; - case DISABLER: add_filtered_test_units( master_tu_id, filter, tu_to_disable ); break; + // 12. Add test units to corresponding list + switch( filter_type ) { + case SELECTOR: + case ENABLER: add_filtered_test_units( master_tu_id, filter_token, tu_to_enable ); break; + case DISABLER: add_filtered_test_units( master_tu_id, filter_token, tu_to_disable ); break; + } + + ++t_filter_it; } } @@ -437,7 +451,7 @@ public: , m_next_test_suite_id( MIN_TEST_SUITE_ID ) , m_test_in_progress( false ) , m_context_idx( 0 ) - , m_log_sink( std::cout ) + , m_log_sinks( ) , m_report_sink( std::cerr ) { } @@ -787,7 +801,7 @@ public: boost::execution_monitor m_aux_em; - runtime_config::stream_holder m_log_sink; + std::map<output_format, runtime_config::stream_holder> m_log_sinks; runtime_config::stream_holder m_report_sink; }; @@ -809,7 +823,178 @@ setup_for_execution( test_unit const& tu ) { s_frk_state().deduce_run_status( tu.p_id ); } - + +struct sum_to_first_only { + sum_to_first_only() : is_first(true) {} + template <class T, class U> + T operator()(T const& l_, U const& r_) { + if(is_first) { + is_first = false; + return l_ + r_.first; + } + return l_ + ", " + r_.first; + } + + bool is_first; +}; + +void +setup_loggers() +{ + + BOOST_TEST_I_TRY { + + + +#ifdef BOOST_TEST_SUPPORT_TOKEN_ITERATOR + bool has_combined_logger = runtime_config::has( runtime_config::COMBINED_LOGGER ) + && !runtime_config::get< std::vector<std::string> >( runtime_config::COMBINED_LOGGER ).empty(); +#else + bool has_combined_logger = false; +#endif + + if( !has_combined_logger ) { + unit_test_log.set_threshold_level( runtime_config::get<log_level>( runtime_config::LOG_LEVEL ) ); + const output_format format = runtime_config::get<output_format>( runtime_config::LOG_FORMAT ); + unit_test_log.set_format( format ); + + runtime_config::stream_holder& stream_logger = s_frk_state().m_log_sinks[format]; + if( runtime_config::has( runtime_config::LOG_SINK ) ) + stream_logger.setup( runtime_config::get<const_string>( runtime_config::LOG_SINK ) ); + unit_test_log.set_stream( stream_logger.ref() ); + } + else + { + + const std::vector<std::string>& v_output_format = runtime_config::get< std::vector<std::string> >( runtime_config::COMBINED_LOGGER ) ; + + static const std::pair<const char*, log_level> all_log_levels[] = { + std::make_pair( "all" , log_successful_tests ), + std::make_pair( "success" , log_successful_tests ), + std::make_pair( "test_suite" , log_test_units ), + std::make_pair( "unit_scope" , log_test_units ), + std::make_pair( "message" , log_messages ), + std::make_pair( "warning" , log_warnings ), + std::make_pair( "error" , log_all_errors ), + std::make_pair( "cpp_exception" , log_cpp_exception_errors ), + std::make_pair( "system_error" , log_system_errors ), + std::make_pair( "fatal_error" , log_fatal_errors ), + std::make_pair( "nothing" , log_nothing ) + }; + + static const std::pair<const char*, output_format> all_formats[] = { + std::make_pair( "HRF" , OF_CLF ), + std::make_pair( "CLF" , OF_CLF ), + std::make_pair( "XML" , OF_XML ), + std::make_pair( "JUNIT", OF_JUNIT ) + }; + + + bool is_first = true; + + BOOST_TEST_FOREACH( const_string, current_multi_config, v_output_format ) { + +#ifdef BOOST_TEST_SUPPORT_TOKEN_ITERATOR + utils::string_token_iterator current_config( current_multi_config, (utils::dropped_delimeters = ":", + utils::kept_delimeters = utils::dt_none) ); + + for( ; current_config != utils::string_token_iterator() ; ++current_config) { + + utils::string_token_iterator current_format_specs( *current_config, (utils::keep_empty_tokens, + utils::dropped_delimeters = ",", + utils::kept_delimeters = utils::dt_none) ); + + output_format format = OF_INVALID ; // default + if( current_format_specs != utils::string_token_iterator() && + current_format_specs->size() ) { + + for(size_t elem=0; elem < sizeof(all_formats)/sizeof(all_formats[0]); elem++) { + if(const_string(all_formats[elem].first) == *current_format_specs) { + format = all_formats[elem].second; + break; + } + } + } + + BOOST_TEST_I_ASSRT( format != OF_INVALID, + boost::runtime::access_to_missing_argument() + << "Unable to determine the logger type from '" + << *current_config + << "'. Possible choices are: " + << std::accumulate(all_formats, + all_formats + sizeof(all_formats)/sizeof(all_formats[0]), + std::string(""), + sum_to_first_only()) + ); + + // activates this format + if( is_first ) { + unit_test_log.set_format( format ); + } + else { + unit_test_log.add_format( format ); + } + is_first = false; + + unit_test_log_formatter * const formatter = unit_test_log.get_formatter(format); + BOOST_TEST_SETUP_ASSERT( formatter, "Logger setup error" ); + + log_level formatter_log_level = invalid_log_level; + if( !current_format_specs->size() ) { + formatter_log_level = formatter->get_log_level(); // default log level given by the formatter + } + else if( ++current_format_specs != utils::string_token_iterator() ) { + + for(size_t elem=0; elem < sizeof(all_log_levels)/sizeof(all_log_levels[0]); elem++) { + if(const_string(all_log_levels[elem].first) == *current_format_specs) { + formatter_log_level = all_log_levels[elem].second; + break; + } + } + } + + + BOOST_TEST_I_ASSRT( formatter_log_level != invalid_log_level, + boost::runtime::access_to_missing_argument() + << "Unable to determine the log level from '" + << *current_config + << "'. Possible choices are: " + << std::accumulate(all_log_levels, + all_log_levels + sizeof(all_log_levels)/sizeof(all_log_levels[0]), + std::string(""), + sum_to_first_only()) + ); + + unit_test_log.set_threshold_level( format, formatter_log_level ); + + runtime_config::stream_holder& stream_logger = s_frk_state().m_log_sinks[format]; + if( ++current_format_specs != utils::string_token_iterator() && + current_format_specs->size() ) { + stream_logger.setup( *current_format_specs ); + } + else { + stream_logger.setup( formatter->get_default_stream_description() ); + } + unit_test_log.set_stream( format, stream_logger.ref() ); + + } +#endif + } + + } + } + BOOST_TEST_I_CATCH( boost::runtime::init_error, ex ) { + BOOST_TEST_SETUP_ASSERT( false, ex.msg ); + } + BOOST_TEST_I_CATCH( boost::runtime::input_error, ex ) { + std::cerr << ex.msg << "\n\n"; + + BOOST_TEST_I_THROW( framework::nothing_to_test( boost::exit_exception_failure ) ); + } + + +} + //____________________________________________________________________________// } // namespace impl @@ -829,15 +1014,14 @@ init( init_unit_test_func init_func, int argc, char* argv[] ) runtime_config::init( argc, argv ); // 20. Set the desired log level, format and sink - unit_test_log.set_threshold_level( runtime_config::get<log_level>( runtime_config::LOG_LEVEL ) ); - unit_test_log.set_format( runtime_config::get<output_format>( runtime_config::LOG_FORMAT ) ); - s_frk_state().m_log_sink.setup( runtime_config::LOG_SINK ); - unit_test_log.set_stream( s_frk_state().m_log_sink.ref() ); + impl::setup_loggers(); // 30. Set the desired report level, format and sink results_reporter::set_level( runtime_config::get<report_level>( runtime_config::REPORT_LEVEL ) ); results_reporter::set_format( runtime_config::get<output_format>( runtime_config::REPORT_FORMAT ) ); - s_frk_state().m_report_sink.setup( runtime_config::REPORT_SINK ); + + if( runtime_config::has( runtime_config::REPORT_SINK ) ) + s_frk_state().m_report_sink.setup( runtime_config::get<const_string>( runtime_config::REPORT_SINK ) ); results_reporter::set_stream( s_frk_state().m_report_sink.ref() ); // 40. Register default test observers @@ -845,7 +1029,7 @@ init( init_unit_test_func init_func, int argc, char* argv[] ) register_observer( unit_test_log ); if( runtime_config::get<bool>( runtime_config::SHOW_PROGRESS ) ) { - progress_monitor.set_stream( s_frk_state().m_log_sink.ref() ); + progress_monitor.set_stream( std::cout ); // defaults to stdout register_observer( progress_monitor ); } @@ -1235,7 +1419,7 @@ run( test_unit_id id, bool continue_test ) case 1: seed = static_cast<unsigned>( std::rand() ^ std::time( 0 ) ); // better init using std::rand() ^ ... default: - BOOST_TEST_MESSAGE( "Test cases order is shuffled using seed: " << seed ); + BOOST_TEST_FRAMEWORK_MESSAGE( "Test cases order is shuffled using seed: " << seed ); std::srand( seed ); } |