From fbc9266e22b85d762acadfa4dbdec62eec78ef7a Mon Sep 17 00:00:00 2001 From: Gennadiy Rozental Date: Sat, 28 Nov 2009 09:19:18 +0000 Subject: [PATCH] merge into release [SVN r57992] --- .../test/detail/unit_test_parameters.hpp | 39 ++-- include/boost/test/execution_monitor.hpp | 21 ++- .../boost/test/floating_point_comparison.hpp | 4 +- .../test/impl/compiler_log_formatter.ipp | 32 ++-- include/boost/test/impl/debug.ipp | 4 +- include/boost/test/impl/execution_monitor.ipp | 166 ++++++++++++++---- include/boost/test/impl/progress_monitor.ipp | 4 +- include/boost/test/impl/results_collector.ipp | 6 +- include/boost/test/impl/results_reporter.ipp | 6 +- include/boost/test/impl/unit_test_log.ipp | 9 +- .../boost/test/impl/unit_test_parameters.ipp | 49 +++++- include/boost/test/impl/xml_log_formatter.ipp | 24 ++- .../test/output/compiler_log_formatter.hpp | 2 +- .../boost/test/output/xml_log_formatter.hpp | 2 +- .../boost/test/unit_test_log_formatter.hpp | 9 +- include/boost/test/unit_test_suite.hpp | 13 +- .../utils/basic_cstring/basic_cstring.hpp | 2 +- include/boost/test/utils/runtime/argument.hpp | 14 +- .../utils/runtime/cla/argument_factory.hpp | 26 +-- .../test/utils/runtime/cla/argv_traverser.hpp | 2 +- .../test/utils/runtime/cla/id_policy.hpp | 2 +- .../utils/runtime/cla/iface/id_policy.hpp | 2 +- .../boost/test/utils/runtime/cla/parser.hpp | 6 +- include/boost/test/utils/runtime/config.hpp | 9 + .../test/utils/runtime/env/environment.ipp | 8 + include/boost/test/utils/xml_printer.hpp | 9 +- 26 files changed, 343 insertions(+), 127 deletions(-) diff --git a/include/boost/test/detail/unit_test_parameters.hpp b/include/boost/test/detail/unit_test_parameters.hpp index 2a0814e6..740dc5d6 100644 --- a/include/boost/test/detail/unit_test_parameters.hpp +++ b/include/boost/test/detail/unit_test_parameters.hpp @@ -20,6 +20,9 @@ #include +// STL +#include + //____________________________________________________________________________// namespace boost { @@ -32,24 +35,26 @@ namespace unit_test { namespace runtime_config { -void BOOST_TEST_DECL init( int& argc, char** argv ); +BOOST_TEST_DECL void init( int& argc, char** argv ); -unit_test::log_level BOOST_TEST_DECL log_level(); -bool BOOST_TEST_DECL no_result_code(); -unit_test::report_level BOOST_TEST_DECL report_level(); -const_string BOOST_TEST_DECL test_to_run(); -const_string BOOST_TEST_DECL break_exec_path(); -bool BOOST_TEST_DECL save_pattern(); -bool BOOST_TEST_DECL show_build_info(); -bool BOOST_TEST_DECL show_progress(); -bool BOOST_TEST_DECL catch_sys_errors(); -bool BOOST_TEST_DECL auto_start_dbg(); -bool BOOST_TEST_DECL use_alt_stack(); -bool BOOST_TEST_DECL detect_fp_exceptions(); -output_format BOOST_TEST_DECL report_format(); -output_format BOOST_TEST_DECL log_format(); -long BOOST_TEST_DECL detect_memory_leaks(); -int BOOST_TEST_DECL random_seed(); +BOOST_TEST_DECL unit_test::log_level log_level(); +BOOST_TEST_DECL bool no_result_code(); +BOOST_TEST_DECL unit_test::report_level report_level(); +BOOST_TEST_DECL const_string test_to_run(); +BOOST_TEST_DECL const_string break_exec_path(); +BOOST_TEST_DECL bool save_pattern(); +BOOST_TEST_DECL bool show_build_info(); +BOOST_TEST_DECL bool show_progress(); +BOOST_TEST_DECL bool catch_sys_errors(); +BOOST_TEST_DECL bool auto_start_dbg(); +BOOST_TEST_DECL bool use_alt_stack(); +BOOST_TEST_DECL bool detect_fp_exceptions(); +BOOST_TEST_DECL output_format report_format(); +BOOST_TEST_DECL output_format log_format(); +BOOST_TEST_DECL std::ostream* report_sink(); +BOOST_TEST_DECL std::ostream* log_sink(); +BOOST_TEST_DECL long detect_memory_leaks(); +BOOST_TEST_DECL int random_seed(); } // namespace runtime_config diff --git a/include/boost/test/execution_monitor.hpp b/include/boost/test/execution_monitor.hpp index 8adf24d3..a1c2ee61 100644 --- a/include/boost/test/execution_monitor.hpp +++ b/include/boost/test/execution_monitor.hpp @@ -113,18 +113,27 @@ public: // is unreasonable to continue execution. }; - // Constructor - execution_exception( error_code ec_, const_string what_msg_ ) // max length 256 inc '\0' - : m_error_code( ec_ ), m_what( what_msg_ ) {} + struct BOOST_TEST_DECL location { + explicit location( char const* file_name = 0, size_t line_num = 0, char const* func = 0 ); - // access methods - error_code code() const { return m_error_code; } - const_string what() const { return m_what; } + const_string m_file_name; + size_t m_line_num; + const_string m_function; + }; + + // Constructor + execution_exception( error_code ec_, const_string what_msg_, location const& location_ ); // max length 256 inc '\0' + + // Access methods + error_code code() const { return m_error_code; } + const_string what() const { return m_what; } + location const& where() const { return m_location; } private: // Data members error_code m_error_code; const_string m_what; + location m_location; }; // execution_exception // ************************************************************************** // diff --git a/include/boost/test/floating_point_comparison.hpp b/include/boost/test/floating_point_comparison.hpp index 8ec7eb41..5a5a3269 100644 --- a/include/boost/test/floating_point_comparison.hpp +++ b/include/boost/test/floating_point_comparison.hpp @@ -54,9 +54,9 @@ namespace tt_detail { // FPT is Floating-Point Type: float, double, long double or User-Defined. template inline FPT -fpt_abs( FPT arg ) +fpt_abs( FPT fpv ) { - return arg < static_cast(0) ? -arg : arg; + return fpv < static_cast(0) ? -fpv : fpv; } //____________________________________________________________________________// diff --git a/include/boost/test/impl/compiler_log_formatter.ipp b/include/boost/test/impl/compiler_log_formatter.ipp index a10f3a5a..8fc08ccf 100644 --- a/include/boost/test/impl/compiler_log_formatter.ipp +++ b/include/boost/test/impl/compiler_log_formatter.ipp @@ -42,6 +42,20 @@ namespace output { // ************** compiler_log_formatter ************** // // ************************************************************************** // +namespace { + +const_string +test_phase_identifier() +{ + return framework::is_initialized() + ? const_string( framework::current_test_case().p_name.get() ) + : BOOST_TEST_L( "Test setup" ); +} + +} // local namespace + +//____________________________________________________________________________// + void compiler_log_formatter::log_start( std::ostream& output, counter_t test_cases_amount ) { @@ -108,16 +122,14 @@ compiler_log_formatter::test_unit_skipped( std::ostream& output, test_unit const //____________________________________________________________________________// void -compiler_log_formatter::log_exception( std::ostream& output, log_checkpoint_data const& checkpoint_data, const_string explanation ) +compiler_log_formatter::log_exception( std::ostream& output, log_checkpoint_data const& checkpoint_data, execution_exception const& ex ) { - print_prefix( output, BOOST_TEST_L( "unknown location" ), 0 ); - output << "fatal error in \"" << framework::current_test_case().p_name << "\": "; + execution_exception::location const& loc = ex.where(); + print_prefix( output, loc.m_file_name, loc.m_line_num ); - if( !explanation.is_empty() ) - output << explanation; - else - output << "uncaught exception, system error or abort requested"; + output << "fatal error in \"" << (loc.m_function.is_empty() ? test_phase_identifier() : loc.m_function ) << "\": "; + output << ex.what(); if( !checkpoint_data.m_file_name.is_empty() ) { output << '\n'; @@ -144,15 +156,15 @@ compiler_log_formatter::log_entry_start( std::ostream& output, log_entry_data co break; case BOOST_UTL_ET_WARNING: print_prefix( output, entry_data.m_file_name, entry_data.m_line_num ); - output << "warning in \"" << framework::current_test_case().p_name << "\": "; + output << "warning in \"" << test_phase_identifier() << "\": "; break; case BOOST_UTL_ET_ERROR: print_prefix( output, entry_data.m_file_name, entry_data.m_line_num ); - output << "error in \"" << framework::current_test_case().p_name << "\": "; + output << "error in \"" << test_phase_identifier() << "\": "; break; case BOOST_UTL_ET_FATAL_ERROR: print_prefix( output, entry_data.m_file_name, entry_data.m_line_num ); - output << "fatal error in \"" << framework::current_test_case().p_name << "\": "; + output << "fatal error in \"" << test_phase_identifier() << "\": "; break; } } diff --git a/include/boost/test/impl/debug.ipp b/include/boost/test/impl/debug.ipp index 19960518..78c3aa8e 100644 --- a/include/boost/test/impl/debug.ipp +++ b/include/boost/test/impl/debug.ipp @@ -23,7 +23,7 @@ #include #include -// Implementation in windows +// Implementation on Windows #if defined(_WIN32) && !defined(UNDER_CE) && !defined(BOOST_DISABLE_WIN32) // ******* WIN32 # define BOOST_WIN32_BASED_DEBUG @@ -653,7 +653,7 @@ under_debugger() if( dbg_list.find( pi.binary_name() ) != const_string::npos ) return true; - pid = pi.parent_pid(); + pid = (pi.parent_pid() == pid ? 0 : pi.parent_pid()); } return false; diff --git a/include/boost/test/impl/execution_monitor.ipp b/include/boost/test/impl/execution_monitor.ipp index dbf2443f..07484b19 100644 --- a/include/boost/test/impl/execution_monitor.ipp +++ b/include/boost/test/impl/execution_monitor.ipp @@ -33,6 +33,8 @@ // Boost #include // for exit codes #include // for workarounds +#include // for get_error_info +#include // for current_exception_cast // STL #include // for std::string @@ -218,21 +220,56 @@ namespace detail { # define BOOST_TEST_VSNPRINTF( a1, a2, a3, a4 ) vsnprintf( (a1), (a2), (a3), (a4) ) #endif +template +typename ErrorInfo::value_type +extract( boost::exception const* ex ) +{ + if( !ex ) + return 0; + + typename ErrorInfo::value_type const * val = boost::get_error_info( *ex ); + + return val ? *val : 0; +} + +//____________________________________________________________________________// + static void -report_error( execution_exception::error_code ec, char const* format, ... ) +report_error( execution_exception::error_code ec, boost::exception const* be, char const* format, va_list* args ) { static const int REPORT_ERROR_BUFFER_SIZE = 512; static char buf[REPORT_ERROR_BUFFER_SIZE]; + BOOST_TEST_VSNPRINTF( buf, sizeof(buf)-1, format, *args ); + buf[sizeof(buf)-1] = 0; + + va_end( *args ); + + throw execution_exception( ec, buf, execution_exception::location( extract( be ), + extract( be ), + extract( be ) ) ); +} + +//____________________________________________________________________________// + +static void +report_error( execution_exception::error_code ec, char const* format, ... ) +{ va_list args; va_start( args, format ); - BOOST_TEST_VSNPRINTF( buf, sizeof(buf)-1, format, args ); - buf[sizeof(buf)-1] = 0; + report_error( ec, 0, format, &args ); +} - va_end( args ); +//____________________________________________________________________________// - throw execution_exception( ec, buf ); +static void +report_error( execution_exception::error_code ec, boost::exception const* be, char const* format, ... ) +{ + va_list args; + va_start( args, format ); + + report_error( ec, be, format, &args ); } //____________________________________________________________________________// @@ -751,7 +788,14 @@ signal_handler::~signal_handler() ::alarm( 0 ); #ifdef BOOST_TEST_USE_ALT_STACK - stack_t sigstk = {}; +#ifdef __GNUC__ + // We shouldn't need to explicitly initialize all the members here, + // but gcc warns if we don't, so add initializers for each of the + // members specified in the POSIX std: + stack_t sigstk = { 0, 0, 0 }; +#else + stack_t sigstk = { }; +#endif sigstk.ss_size = MINSIGSTKSZ; sigstk.ss_flags = SS_DISABLE; @@ -1090,7 +1134,7 @@ int execution_monitor::catch_signals( unit_test::callback0 const& F ) { _invalid_parameter_handler old_iph = _invalid_parameter_handler(); - BOOST_TEST_CRT_HOOK_TYPE old_crt_hook; + BOOST_TEST_CRT_HOOK_TYPE old_crt_hook = 0; if( !p_catch_system_errors ) _set_se_translator( &detail::seh_catch_preventer ); @@ -1173,60 +1217,105 @@ execution_monitor::execute( unit_test::callback0 const& F ) // easier than answering questions about non-const usage. catch( char const* ex ) - { detail::report_error( execution_exception::cpp_exception_error, "C string: %s", ex ); } + { detail::report_error( execution_exception::cpp_exception_error, + "C string: %s", ex ); } catch( std::string const& ex ) - { detail::report_error( execution_exception::cpp_exception_error, "std::string: %s", ex.c_str() ); } + { detail::report_error( execution_exception::cpp_exception_error, + "std::string: %s", ex.c_str() ); } // std:: exceptions catch( std::bad_alloc const& ex ) - { detail::report_error( execution_exception::cpp_exception_error, "std::bad_alloc: %s", ex.what() ); } + { detail::report_error( execution_exception::cpp_exception_error, + current_exception_cast(), + "std::bad_alloc: %s", ex.what() ); } #if BOOST_WORKAROUND(__BORLANDC__, <= 0x0551) catch( std::bad_cast const& ex ) - { detail::report_error( execution_exception::cpp_exception_error, "std::bad_cast" ); } + { detail::report_error( execution_exception::cpp_exception_error, + current_exception_cast(), + "std::bad_cast" ); } catch( std::bad_typeid const& ex ) - { detail::report_error( execution_exception::cpp_exception_error, "std::bad_typeid" ); } + { detail::report_error( execution_exception::cpp_exception_error, + current_exception_cast(), + "std::bad_typeid" ); } #else catch( std::bad_cast const& ex ) - { detail::report_error( execution_exception::cpp_exception_error, "std::bad_cast: %s", ex.what() ); } + { detail::report_error( execution_exception::cpp_exception_error, + current_exception_cast(), + "std::bad_cast: %s", ex.what() ); } catch( std::bad_typeid const& ex ) - { detail::report_error( execution_exception::cpp_exception_error, "std::bad_typeid: %s", ex.what() ); } + { detail::report_error( execution_exception::cpp_exception_error, + current_exception_cast(), + "std::bad_typeid: %s", ex.what() ); } #endif catch( std::bad_exception const& ex ) - { detail::report_error( execution_exception::cpp_exception_error, "std::bad_exception: %s", ex.what() ); } + { detail::report_error( execution_exception::cpp_exception_error, + current_exception_cast(), + "std::bad_exception: %s", ex.what() ); } catch( std::domain_error const& ex ) - { detail::report_error( execution_exception::cpp_exception_error, "std::domain_error: %s", ex.what() ); } + { detail::report_error( execution_exception::cpp_exception_error, + current_exception_cast(), + "std::domain_error: %s", ex.what() ); } catch( std::invalid_argument const& ex ) - { detail::report_error( execution_exception::cpp_exception_error, "std::invalid_argument: %s", ex.what() ); } + { detail::report_error( execution_exception::cpp_exception_error, + current_exception_cast(), + "std::invalid_argument: %s", ex.what() ); } catch( std::length_error const& ex ) - { detail::report_error( execution_exception::cpp_exception_error, "std::length_error: %s", ex.what() ); } + { detail::report_error( execution_exception::cpp_exception_error, + current_exception_cast(), + "std::length_error: %s", ex.what() ); } catch( std::out_of_range const& ex ) - { detail::report_error( execution_exception::cpp_exception_error, "std::out_of_range: %s", ex.what() ); } + { detail::report_error( execution_exception::cpp_exception_error, + current_exception_cast(), + "std::out_of_range: %s", ex.what() ); } catch( std::range_error const& ex ) - { detail::report_error( execution_exception::cpp_exception_error, "std::range_error: %s", ex.what() ); } + { detail::report_error( execution_exception::cpp_exception_error, + current_exception_cast(), + "std::range_error: %s", ex.what() ); } catch( std::overflow_error const& ex ) - { detail::report_error( execution_exception::cpp_exception_error, "std::overflow_error: %s", ex.what() ); } + { detail::report_error( execution_exception::cpp_exception_error, + current_exception_cast(), + "std::overflow_error: %s", ex.what() ); } catch( std::underflow_error const& ex ) - { detail::report_error( execution_exception::cpp_exception_error, "std::underflow_error: %s", ex.what() ); } + { detail::report_error( execution_exception::cpp_exception_error, + current_exception_cast(), + "std::underflow_error: %s", ex.what() ); } catch( std::logic_error const& ex ) - { detail::report_error( execution_exception::cpp_exception_error, "std::logic_error: %s", ex.what() ); } + { detail::report_error( execution_exception::cpp_exception_error, + current_exception_cast(), + "std::logic_error: %s", ex.what() ); } catch( std::runtime_error const& ex ) - { detail::report_error( execution_exception::cpp_exception_error, "std::runtime_error: %s", ex.what() ); } + { detail::report_error( execution_exception::cpp_exception_error, + current_exception_cast(), + "std::runtime_error: %s", ex.what() ); } catch( std::exception const& ex ) - { detail::report_error( execution_exception::cpp_exception_error, "std::exception: %s", ex.what() ); } + { detail::report_error( execution_exception::cpp_exception_error, + current_exception_cast(), + "std::exception: %s", ex.what() ); } + + catch( boost::exception const& ex ) + { detail::report_error( execution_exception::cpp_exception_error, + &ex, + "unknown boost::exception" ); } + + // system errors catch( system_error const& ex ) - { detail::report_error( execution_exception::cpp_exception_error, "system_error produced by: %s: %s", - ex.p_failed_exp.get(), - std::strerror( ex.p_errno ) ); } + { detail::report_error( execution_exception::cpp_exception_error, + "system_error produced by: %s: %s", ex.p_failed_exp.get(), std::strerror( ex.p_errno ) ); } catch( detail::system_signal_exception const& ex ) { ex.report(); } + + // not an error catch( execution_aborted const& ) { return 0; } + + // just forward catch( execution_exception const& ) { throw; } + // unknown error catch( ... ) { detail::report_error( execution_exception::cpp_exception_error, "unknown type" ); } @@ -1248,13 +1337,30 @@ system_error::system_error( char const* exp ) , p_failed_exp( exp ) {} +//____________________________________________________________________________// + +// ************************************************************************** // +// ************** execution_exception ************** // +// ************************************************************************** // + +execution_exception::execution_exception( error_code ec_, const_string what_msg_, location const& location_ ) +: m_error_code( ec_ ) +, m_what( what_msg_.empty() ? BOOST_TEST_L( "uncaught exception, system error or abort requested" ) : what_msg_ ) +, m_location( location_ ) +{} + +//____________________________________________________________________________// + +execution_exception::location::location( char const* file_name, size_t line_num, char const* func ) +: m_file_name( file_name ? file_name : "unknown location" ) +, m_line_num( line_num ) +, m_function( func ) +{} //____________________________________________________________________________// } // namespace boost -//____________________________________________________________________________// - #include #endif // BOOST_TEST_EXECUTION_MONITOR_IPP_012205GER diff --git a/include/boost/test/impl/progress_monitor.ipp b/include/boost/test/impl/progress_monitor.ipp index ae633f96..5175755c 100644 --- a/include/boost/test/impl/progress_monitor.ipp +++ b/include/boost/test/impl/progress_monitor.ipp @@ -19,6 +19,8 @@ #include #include +#include + // Boost #include #include @@ -40,7 +42,7 @@ namespace { struct progress_monitor_impl { // Constructor progress_monitor_impl() - : m_stream( &std::cout ) + : m_stream( runtime_config::log_sink() ) {} std::ostream* m_stream; diff --git a/include/boost/test/impl/results_collector.ipp b/include/boost/test/impl/results_collector.ipp index 2d07fcdb..0d5691aa 100644 --- a/include/boost/test/impl/results_collector.ipp +++ b/include/boost/test/impl/results_collector.ipp @@ -215,9 +215,9 @@ results_collector_t::test_unit_finish( test_unit const& tu, unsigned long ) if( !num_failures_match ) BOOST_TEST_MESSAGE( "Test case " << tu.p_name << " has fewer failures than expected" ); - bool run_any_assertions = tr.p_aborted || (tr.p_assertions_failed != 0) || (tr.p_assertions_passed != 0); - if( !run_any_assertions ) - BOOST_TEST_MESSAGE( "Test case " << tu.p_name << " did not run any assertions" ); + bool check_any_assertions = tr.p_aborted || (tr.p_assertions_failed != 0) || (tr.p_assertions_passed != 0); + if( !check_any_assertions ) + BOOST_TEST_MESSAGE( "Test case " << tu.p_name << " did not check any assertions" ); } } diff --git a/include/boost/test/impl/results_reporter.ipp b/include/boost/test/impl/results_reporter.ipp index e9ef2fa2..54447c39 100644 --- a/include/boost/test/impl/results_reporter.ipp +++ b/include/boost/test/impl/results_reporter.ipp @@ -23,6 +23,8 @@ #include #include +#include + // Boost #include #include @@ -50,8 +52,8 @@ namespace { struct results_reporter_impl : test_tree_visitor { // Constructor results_reporter_impl() - : m_output( &std::cerr ) - , m_stream_state_saver( new io_saver_type( std::cerr ) ) + : m_output( runtime_config::report_sink() ) + , m_stream_state_saver( new io_saver_type( *m_output ) ) , m_report_level( CONFIRMATION_REPORT ) , m_formatter( new output::plain_report_formatter ) {} diff --git a/include/boost/test/impl/unit_test_log.ipp b/include/boost/test/impl/unit_test_log.ipp index 08693cdf..7cb4f4b4 100644 --- a/include/boost/test/impl/unit_test_log.ipp +++ b/include/boost/test/impl/unit_test_log.ipp @@ -33,9 +33,6 @@ #include typedef ::boost::io::ios_base_all_saver io_saver_type; -// STL -#include - #include //____________________________________________________________________________// @@ -89,8 +86,8 @@ namespace { struct unit_test_log_impl { // Constructor unit_test_log_impl() - : m_stream( &std::cout ) - , m_stream_state_saver( new io_saver_type( std::cout ) ) + : m_stream( runtime_config::log_sink() ) + , m_stream_state_saver( new io_saver_type( *m_stream ) ) , m_threshold_level( log_all_errors ) , m_log_formatter( new output::compiler_log_formatter ) { @@ -238,7 +235,7 @@ unit_test_log_t::exception_caught( execution_exception const& ex ) if( s_log_impl().m_entry_in_progress ) *this << log::end(); - s_log_impl().m_log_formatter->log_exception( s_log_impl().stream(), s_log_impl().m_checkpoint_data, ex.what() ); + s_log_impl().m_log_formatter->log_exception( s_log_impl().stream(), s_log_impl().m_checkpoint_data, ex ); } } diff --git a/include/boost/test/impl/unit_test_parameters.ipp b/include/boost/test/impl/unit_test_parameters.ipp index e15fd61b..6f2efb41 100644 --- a/include/boost/test/impl/unit_test_parameters.ipp +++ b/include/boost/test/impl/unit_test_parameters.ipp @@ -52,6 +52,7 @@ namespace env = rt::env; #include #include #include +#include #include @@ -161,10 +162,12 @@ std::string DETECT_FP_EXCEPT = "detect_fp_exceptions"; std::string DETECT_MEM_LEAKS = "detect_memory_leaks"; std::string LOG_FORMAT = "log_format"; std::string LOG_LEVEL = "log_level"; +std::string LOG_SINK = "log_sink"; std::string OUTPUT_FORMAT = "output_format"; std::string RANDOM_SEED = "random"; std::string REPORT_FORMAT = "report_format"; std::string REPORT_LEVEL = "report_level"; +std::string REPORT_SINK = "report_sink"; std::string RESULT_CODE = "result_code"; std::string TESTS_TO_RUN = "run_test"; std::string SAVE_TEST_PATTERN = "save_pattern"; @@ -180,10 +183,12 @@ fixed_mapping parameter_2_env_var( DETECT_MEM_LEAKS , "BOOST_TEST_DETECT_MEMORY_LEAK", LOG_FORMAT , "BOOST_TEST_LOG_FORMAT", LOG_LEVEL , "BOOST_TEST_LOG_LEVEL", + LOG_SINK , "BOOST_TEST_LOG_SINK", OUTPUT_FORMAT , "BOOST_TEST_OUTPUT_FORMAT", RANDOM_SEED , "BOOST_TEST_RANDOM", REPORT_FORMAT , "BOOST_TEST_REPORT_FORMAT", REPORT_LEVEL , "BOOST_TEST_REPORT_LEVEL", + REPORT_SINK , "BOOST_TEST_REPORT_SINK", RESULT_CODE , "BOOST_TEST_RESULT_CODE", TESTS_TO_RUN , "BOOST_TESTS_TO_RUN", SAVE_TEST_PATTERN , "BOOST_TEST_SAVE_PATTERN", @@ -216,9 +221,9 @@ retrieve_parameter( const_string parameter_name, cla::parser const& s_cla_parser optional val = s_cla_parser.get >( parameter_name ); if( val ) - return *val; + return *val; else - return optional_value; + return optional_value; } boost::optional v; @@ -268,6 +273,9 @@ init( int& argc, char** argv ) << cla::dual_name_parameter( LOG_LEVEL + "|l" ) - (cla::prefix = "--|-",cla::separator = "=| ",cla::guess_name,cla::optional, cla::description = "Specifies log level") + << cla::dual_name_parameter( LOG_SINK + "|k" ) + - (cla::prefix = "--|-",cla::separator = "=| ",cla::guess_name,cla::optional, + cla::description = "Specifies log sink:stdout(default),stderr or file name") << cla::dual_name_parameter( OUTPUT_FORMAT + "|o" ) - (cla::prefix = "--|-",cla::separator = "=| ",cla::guess_name,cla::optional, cla::description = "Specifies output format (both log and report)") @@ -281,6 +289,9 @@ init( int& argc, char** argv ) << cla::dual_name_parameter(REPORT_LEVEL + "|r") - (cla::prefix = "--|-",cla::separator = "=| ",cla::guess_name,cla::optional, cla::description = "Specifies report level") + << cla::dual_name_parameter( REPORT_SINK + "|e" ) + - (cla::prefix = "--|-",cla::separator = "=| ",cla::guess_name,cla::optional, + cla::description = "Specifies report sink:stderr(default),stdout or file name") << cla::dual_name_parameter( RESULT_CODE + "|c" ) - (cla::prefix = "--|-",cla::separator = "=| ",cla::guess_name,cla::optional, cla::description = "Allows to disable test modules's result code generation") @@ -453,6 +464,40 @@ log_format() //____________________________________________________________________________// +std::ostream* +report_sink() +{ + std::string sink_name = retrieve_parameter( REPORT_SINK, s_cla_parser, s_empty ); + + if( sink_name.empty() || sink_name == "stderr" ) + return &std::cerr; + + if( sink_name == "stdout" ) + return &std::cout; + + static std::ofstream log_file( sink_name.c_str() ); + return &log_file; +} + +//____________________________________________________________________________// + +std::ostream* +log_sink() +{ + std::string sink_name = retrieve_parameter( LOG_SINK, s_cla_parser, s_empty ); + + if( sink_name.empty() || sink_name == "stdout" ) + return &std::cout; + + if( sink_name == "stderr" ) + return &std::cerr; + + static std::ofstream report_file( sink_name.c_str() ); + return &report_file; +} + +//____________________________________________________________________________// + long detect_memory_leaks() { diff --git a/include/boost/test/impl/xml_log_formatter.ipp b/include/boost/test/impl/xml_log_formatter.ipp index 760eb165..6c0127bb 100644 --- a/include/boost/test/impl/xml_log_formatter.ipp +++ b/include/boost/test/impl/xml_log_formatter.ipp @@ -110,15 +110,23 @@ xml_log_formatter::test_unit_skipped( std::ostream& ostr, test_unit const& tu ) //____________________________________________________________________________// void -xml_log_formatter::log_exception( std::ostream& ostr, log_checkpoint_data const& checkpoint_data, const_string explanation ) +xml_log_formatter::log_exception( std::ostream& ostr, log_checkpoint_data const& checkpoint_data, execution_exception const& ex ) { - ostr << "" << pcdata() << explanation; + execution_exception::location const& loc = ex.where(); + + ostr << "" << cdata() << ex.what(); if( !checkpoint_data.m_file_name.is_empty() ) { ostr << "" - << pcdata() << checkpoint_data.m_message + << cdata() << checkpoint_data.m_message << ""; } @@ -134,9 +142,9 @@ xml_log_formatter::log_entry_start( std::ostream& ostr, log_entry_data const& en m_curr_tag = xml_tags[let]; ostr << '<' << m_curr_tag - << " file" << attr_value() << entry_data.m_file_name - << " line" << attr_value() << entry_data.m_line_num - << ">"; + << BOOST_TEST_L( " file" ) << attr_value() << entry_data.m_file_name + << BOOST_TEST_L( " line" ) << attr_value() << entry_data.m_line_num + << BOOST_TEST_L( ">"; + ostr << BOOST_TEST_L( "]]>" ); m_curr_tag.clear(); } diff --git a/include/boost/test/output/compiler_log_formatter.hpp b/include/boost/test/output/compiler_log_formatter.hpp index 657e1b83..23795b99 100644 --- a/include/boost/test/output/compiler_log_formatter.hpp +++ b/include/boost/test/output/compiler_log_formatter.hpp @@ -44,7 +44,7 @@ public: void test_unit_finish( std::ostream&, test_unit const& tu, unsigned long elapsed ); void test_unit_skipped( std::ostream&, test_unit const& tu ); - void log_exception( std::ostream&, log_checkpoint_data const&, const_string explanation ); + void log_exception( std::ostream&, log_checkpoint_data const&, execution_exception const& ex ); void log_entry_start( std::ostream&, log_entry_data const&, log_entry_types let ); void log_entry_value( std::ostream&, const_string value ); diff --git a/include/boost/test/output/xml_log_formatter.hpp b/include/boost/test/output/xml_log_formatter.hpp index 901a0f01..43b4ce82 100644 --- a/include/boost/test/output/xml_log_formatter.hpp +++ b/include/boost/test/output/xml_log_formatter.hpp @@ -47,7 +47,7 @@ public: void test_unit_finish( std::ostream&, test_unit const& tu, unsigned long elapsed ); void test_unit_skipped( std::ostream&, test_unit const& tu ); - void log_exception( std::ostream&, log_checkpoint_data const&, const_string explanation ); + void log_exception( std::ostream&, log_checkpoint_data const&, execution_exception const& ex ); void log_entry_start( std::ostream&, log_entry_data const&, log_entry_types let ); using unit_test_log_formatter::log_entry_value; // bring base class functions into overload set diff --git a/include/boost/test/unit_test_log_formatter.hpp b/include/boost/test/unit_test_log_formatter.hpp index ce5ea8c4..81f156b4 100644 --- a/include/boost/test/unit_test_log_formatter.hpp +++ b/include/boost/test/unit_test_log_formatter.hpp @@ -20,6 +20,8 @@ #include #include +#include + // STL #include #include // for std::string @@ -96,7 +98,12 @@ public: virtual void test_unit_finish( std::ostream&, test_unit const& tu, unsigned long elapsed ) = 0; virtual void test_unit_skipped( std::ostream&, test_unit const& ) = 0; - virtual void log_exception( std::ostream&, log_checkpoint_data const&, const_string explanation ) = 0; + virtual void log_exception( std::ostream& os, log_checkpoint_data const& cd, execution_exception const& ex ) + { + // for backward compatibility + log_exception( os, cd, ex.what() ); + } + virtual void log_exception( std::ostream&, log_checkpoint_data const&, const_string /* explanation */ ) {} virtual void log_entry_start( std::ostream&, log_entry_data const&, log_entry_types let ) = 0; virtual void log_entry_value( std::ostream&, const_string value ) = 0; diff --git a/include/boost/test/unit_test_suite.hpp b/include/boost/test/unit_test_suite.hpp index 94f09297..048a75f6 100644 --- a/include/boost/test/unit_test_suite.hpp +++ b/include/boost/test/unit_test_suite.hpp @@ -116,12 +116,12 @@ BOOST_FIXTURE_TEST_CASE( test_name, BOOST_AUTO_TEST_CASE_FIXTURE ) /**/ // ************************************************************************** // -// ************** BOOST_AUTO_TEST_CASE_TEMPLATE ************** // +// ************** BOOST_FIXTURE_TEST_CASE_TEMPLATE ************** // // ************************************************************************** // -#define BOOST_AUTO_TEST_CASE_TEMPLATE( test_name, type_name, TL ) \ +#define BOOST_FIXTURE_TEST_CASE_TEMPLATE( test_name, type_name, TL, F ) \ template \ -struct test_name : public BOOST_AUTO_TEST_CASE_FIXTURE \ +struct test_name : public F \ { void test_method(); }; \ \ struct BOOST_AUTO_TC_INVOKER( test_name ) { \ @@ -142,6 +142,13 @@ template \ void test_name::test_method() \ /**/ +// ************************************************************************** // +// ************** BOOST_AUTO_TEST_CASE_TEMPLATE ************** // +// ************************************************************************** // + +#define BOOST_AUTO_TEST_CASE_TEMPLATE( test_name, type_name, TL ) \ +BOOST_FIXTURE_TEST_CASE_TEMPLATE( test_name, type_name, TL, BOOST_AUTO_TEST_CASE_FIXTURE ) + // ************************************************************************** // // ************** BOOST_TEST_CASE_TEMPLATE ************** // // ************************************************************************** // diff --git a/include/boost/test/utils/basic_cstring/basic_cstring.hpp b/include/boost/test/utils/basic_cstring/basic_cstring.hpp index 7eb19d9b..14742c49 100644 --- a/include/boost/test/utils/basic_cstring/basic_cstring.hpp +++ b/include/boost/test/utils/basic_cstring/basic_cstring.hpp @@ -548,7 +548,7 @@ basic_cstring::rfind( basic_cstring str ) const --it; } - return it == last ? npos : it - begin(); + return it == last ? static_cast(npos) : static_cast(it - begin()); } //____________________________________________________________________________// diff --git a/include/boost/test/utils/runtime/argument.hpp b/include/boost/test/utils/runtime/argument.hpp index a2d229e6..d0f420aa 100644 --- a/include/boost/test/utils/runtime/argument.hpp +++ b/include/boost/test/utils/runtime/argument.hpp @@ -43,7 +43,7 @@ namespace BOOST_RT_PARAM_NAMESPACE { class argument { public: // Constructor - argument( parameter const& p, call_traits::param_type value_type ) + argument( parameter const& p, rtti::id_t value_type ) : p_formal_parameter( p ) , p_value_type( value_type ) {} @@ -81,22 +81,22 @@ public: template inline T const& -arg_value( argument const& arg ) +arg_value( argument const& arg_ ) { - assert( arg.p_value_type == rtti::type_id() ); // detect logic error + assert( arg_.p_value_type == rtti::type_id() ); // detect logic error - return static_cast const&>( arg ).p_value.value; + return static_cast const&>( arg_ ).p_value.value; } //____________________________________________________________________________// template inline T& -arg_value( argument& arg ) +arg_value( argument& arg_ ) { - assert( arg.p_value_type == rtti::type_id() ); // detect logic error + assert( arg_.p_value_type == rtti::type_id() ); // detect logic error - return static_cast&>( arg ).p_value.value; + return static_cast&>( arg_ ).p_value.value; } #ifdef BOOST_MSVC diff --git a/include/boost/test/utils/runtime/cla/argument_factory.hpp b/include/boost/test/utils/runtime/cla/argument_factory.hpp index ffa86cc7..19ccc08c 100644 --- a/include/boost/test/utils/runtime/cla/argument_factory.hpp +++ b/include/boost/test/utils/runtime/cla/argument_factory.hpp @@ -135,42 +135,42 @@ typed_argument_factory::produce_using( parameter& p, argv_traverser& tr ) throw; } - argument_ptr arg = p.actual_argument(); + argument_ptr actual_arg = p.actual_argument(); BOOST_RT_CLA_VALIDATE_INPUT( !!value || p.p_optional_value, tr, BOOST_RT_PARAM_LITERAL( "Argument value missing for parameter " ) << p.id_2_report() ); - BOOST_RT_CLA_VALIDATE_INPUT( !arg || p.p_multiplicable, tr, + BOOST_RT_CLA_VALIDATE_INPUT( !actual_arg || p.p_multiplicable, tr, BOOST_RT_PARAM_LITERAL( "Unexpected repetition of the parameter " ) << p.id_2_report() ); if( !!value && !!m_value_handler ) m_value_handler( p, *value ); if( !p.p_multiplicable ) - arg.reset( p.p_optional_value && (rtti::type_id() != rtti::type_id()) + actual_arg.reset( p.p_optional_value && (rtti::type_id() != rtti::type_id()) ? static_cast(new typed_argument >( p, value )) : static_cast(new typed_argument( p, *value )) ); else { typedef std::list > optional_list; - if( !arg ) - arg.reset( p.p_optional_value + if( !actual_arg ) + actual_arg.reset( p.p_optional_value ? static_cast(new typed_argument( p )) : static_cast(new typed_argument >( p )) ); if( p.p_optional_value ) { - optional_list& values = arg_value( *arg ); + optional_list& values = arg_value( *actual_arg ); values.push_back( value ); } else { - std::list& values = arg_value >( *arg ); + std::list& values = arg_value >( *actual_arg ); values.push_back( *value ); } } - return arg; + return actual_arg; } //____________________________________________________________________________// @@ -179,23 +179,23 @@ template inline argument_ptr typed_argument_factory::produce_using( parameter& p, parser const& pa ) { - argument_ptr arg; + argument_ptr actual_arg; if( !m_value_generator ) - return arg; + return actual_arg; boost::optional value; m_value_generator( pa, value ); if( !value ) - return arg; + return actual_arg; if( !!m_value_handler ) m_value_handler( p, *value ); - arg.reset( new typed_argument( p, *value ) ); + actual_arg.reset( new typed_argument( p, *value ) ); - return arg; + return actual_arg; } //____________________________________________________________________________// diff --git a/include/boost/test/utils/runtime/cla/argv_traverser.hpp b/include/boost/test/utils/runtime/cla/argv_traverser.hpp index 386a626a..58cf2fe5 100644 --- a/include/boost/test/utils/runtime/cla/argv_traverser.hpp +++ b/include/boost/test/utils/runtime/cla/argv_traverser.hpp @@ -72,7 +72,7 @@ public: private: // Data members - dstring m_buffer; + dstring m_buffer; cstring m_work_buffer; cstring m_token; diff --git a/include/boost/test/utils/runtime/cla/id_policy.hpp b/include/boost/test/utils/runtime/cla/id_policy.hpp index 30d48f77..596805ea 100644 --- a/include/boost/test/utils/runtime/cla/id_policy.hpp +++ b/include/boost/test/utils/runtime/cla/id_policy.hpp @@ -62,7 +62,7 @@ public: } protected: - explicit basic_naming_policy( call_traits::param_type dyn_type ) + explicit basic_naming_policy( rtti::id_t dyn_type ) : identification_policy( dyn_type ) {} BOOST_RT_PARAM_UNNEEDED_VIRTUAL ~basic_naming_policy() {} diff --git a/include/boost/test/utils/runtime/cla/iface/id_policy.hpp b/include/boost/test/utils/runtime/cla/iface/id_policy.hpp index 9c1287e5..1e2d684c 100644 --- a/include/boost/test/utils/runtime/cla/iface/id_policy.hpp +++ b/include/boost/test/utils/runtime/cla/iface/id_policy.hpp @@ -54,7 +54,7 @@ public: protected: // Constructor - explicit identification_policy( call_traits::param_type dyn_type ) + explicit identification_policy( rtti::id_t dyn_type ) : p_type_id( dyn_type ) {} BOOST_TEST_PROTECTED_VIRTUAL ~identification_policy() {} diff --git a/include/boost/test/utils/runtime/cla/parser.hpp b/include/boost/test/utils/runtime/cla/parser.hpp index 4b8dcf88..f95d26a0 100644 --- a/include/boost/test/utils/runtime/cla/parser.hpp +++ b/include/boost/test/utils/runtime/cla/parser.hpp @@ -114,10 +114,10 @@ public: template void get( cstring string_id, boost::optional& res ) const { - const_argument_ptr arg = (*this)[string_id]; + const_argument_ptr actual_arg = (*this)[string_id]; - if( arg ) - res = arg_value( *arg ); + if( actual_arg ) + res = arg_value( *actual_arg ); else res.reset(); } diff --git a/include/boost/test/utils/runtime/config.hpp b/include/boost/test/utils/runtime/config.hpp index 22563a3b..771a8ee7 100644 --- a/include/boost/test/utils/runtime/config.hpp +++ b/include/boost/test/utils/runtime/config.hpp @@ -67,6 +67,11 @@ typedef std::ostream out_stream; typedef std::basic_ostream out_stream; #endif +#ifdef BOOST_MSVC +#pragma warning(push) +#pragma warning(disable:4996) // putenv +#endif + #ifndef UNDER_CE #if defined(__COMO__) && 0 inline void @@ -92,6 +97,10 @@ putenv_impl( cstring name, cstring value ) #endif #endif +#ifdef BOOST_MSVC +#pragma warning(pop) +#endif + #define BOOST_RT_PARAM_LITERAL( l ) l #define BOOST_RT_PARAM_CSTRING_LITERAL( l ) cstring( l, sizeof( l ) - 1 ) #define BOOST_RT_PARAM_GETENV getenv diff --git a/include/boost/test/utils/runtime/env/environment.ipp b/include/boost/test/utils/runtime/env/environment.ipp index 42ef3ad7..5a320003 100644 --- a/include/boost/test/utils/runtime/env/environment.ipp +++ b/include/boost/test/utils/runtime/env/environment.ipp @@ -75,6 +75,11 @@ find_var_record( cstring var_name ) //____________________________________________________________________________// +#ifdef BOOST_MSVC +#pragma warning(push) +#pragma warning(disable:4996) // getenv +#endif + BOOST_RT_PARAM_INLINE cstring sys_read_var( cstring var_name ) { @@ -82,6 +87,9 @@ sys_read_var( cstring var_name ) return BOOST_RT_PARAM_GETENV( var_name.begin() ); } +#ifdef BOOST_MSVC +#pragma warning(pop) +#endif //____________________________________________________________________________// BOOST_RT_PARAM_INLINE void diff --git a/include/boost/test/utils/xml_printer.hpp b/include/boost/test/utils/xml_printer.hpp index 1bdcc6aa..ae73cce1 100644 --- a/include/boost/test/utils/xml_printer.hpp +++ b/include/boost/test/utils/xml_printer.hpp @@ -20,6 +20,7 @@ #include #include #include +#include // Boost #include @@ -96,14 +97,12 @@ operator<<( custom_printer const& p, T const& value ) //____________________________________________________________________________// -typedef custom_manip pcdata; +typedef custom_manip cdata; inline std::ostream& -operator<<( custom_printer const& p, const_string value ) +operator<<( custom_printer const& p, const_string value ) { - print_escaped( *p, value ); - - return *p; + return *p << BOOST_TEST_L( "" ); } //____________________________________________________________________________//