From d143f0dca4369d8a675ec01883dcbd84cdf9a748 Mon Sep 17 00:00:00 2001 From: Gennadiy Rozental Date: Sat, 22 Jan 2005 19:26:38 +0000 Subject: [PATCH] implementation moved into headers section to eliminate dependency of included/minimal component on src directory [SVN r26813] --- .../test/detail/supplied_log_formatters.hpp | 4 +- .../boost/test/detail/unit_test_config.hpp | 17 +- .../boost/test/floating_point_comparison.hpp | 5 +- include/boost/test/impl/cpp_main.ipp | 120 ++++ include/boost/test/impl/execution_monitor.ipp | 636 +++++++++++++++++ .../test/impl/supplied_log_formatters.ipp | 374 ++++++++++ include/boost/test/impl/test_main.ipp | 137 ++++ include/boost/test/impl/test_tools.ipp | 479 +++++++++++++ include/boost/test/impl/unit_test_log.ipp | 485 +++++++++++++ include/boost/test/impl/unit_test_main.ipp | 130 ++++ include/boost/test/impl/unit_test_monitor.ipp | 134 ++++ .../boost/test/impl/unit_test_parameters.ipp | 115 ++++ include/boost/test/impl/unit_test_result.ipp | 649 ++++++++++++++++++ include/boost/test/impl/unit_test_suite.ipp | 339 +++++++++ .../boost/test/included/prg_exec_monitor.hpp | 7 +- .../boost/test/included/test_exec_monitor.hpp | 21 +- .../test/included/unit_test_framework.hpp | 21 +- include/boost/test/minimal.hpp | 7 +- include/boost/test/test_tools.hpp | 7 +- include/boost/test/unit_test_suite.hpp | 5 +- .../utils/basic_cstring/basic_cstring.hpp | 7 +- .../test/utils/basic_cstring/compare.hpp | 5 +- include/boost/test/utils/basic_cstring/io.hpp | 5 +- include/boost/test/utils/class_properties.hpp | 16 +- .../utils/iterator/ifstream_line_iterator.hpp | 5 +- .../utils/iterator/istream_line_iterator.hpp | 7 +- .../test/utils/iterator/token_iterator.hpp | 7 +- include/boost/test/utils/xml_printer.hpp | 17 +- src/cpp_main.cpp | 100 +-- src/execution_monitor.cpp | 620 +---------------- src/supplied_log_formatters.cpp | 353 +--------- src/test_main.cpp | 122 +--- src/test_tools.cpp | 461 +------------ src/unit_test_log.cpp | 465 +------------ src/unit_test_main.cpp | 111 +-- src/unit_test_monitor.cpp | 116 +--- src/unit_test_parameters.cpp | 94 +-- src/unit_test_result.cpp | 631 +---------------- src/unit_test_suite.cpp | 318 +-------- 39 files changed, 3770 insertions(+), 3382 deletions(-) create mode 100644 include/boost/test/impl/cpp_main.ipp create mode 100644 include/boost/test/impl/execution_monitor.ipp create mode 100644 include/boost/test/impl/supplied_log_formatters.ipp create mode 100644 include/boost/test/impl/test_main.ipp create mode 100644 include/boost/test/impl/test_tools.ipp create mode 100644 include/boost/test/impl/unit_test_log.ipp create mode 100644 include/boost/test/impl/unit_test_main.ipp create mode 100644 include/boost/test/impl/unit_test_monitor.ipp create mode 100644 include/boost/test/impl/unit_test_parameters.ipp create mode 100644 include/boost/test/impl/unit_test_result.ipp create mode 100644 include/boost/test/impl/unit_test_suite.ipp diff --git a/include/boost/test/detail/supplied_log_formatters.hpp b/include/boost/test/detail/supplied_log_formatters.hpp index 5312b46b..fa1fff2d 100755 --- a/include/boost/test/detail/supplied_log_formatters.hpp +++ b/include/boost/test/detail/supplied_log_formatters.hpp @@ -17,7 +17,6 @@ // Boost.Test #include -#include // BOOST #include @@ -97,6 +96,9 @@ private: // Revision History : // // $Log$ +// Revision 1.11 2005/01/22 19:22:12 rogeeff +// implementation moved into headers section to eliminate dependency of included/minimal component on src directory +// // Revision 1.10 2005/01/21 07:30:45 rogeeff // to log testing time log formatter interfaces changed // diff --git a/include/boost/test/detail/unit_test_config.hpp b/include/boost/test/detail/unit_test_config.hpp index fece2acd..a5c2c340 100644 --- a/include/boost/test/detail/unit_test_config.hpp +++ b/include/boost/test/detail/unit_test_config.hpp @@ -32,8 +32,8 @@ #endif // Boost.Test -#include -#include +#include +#include #define BOOST_TEST_STRING_LITERAL( s ) boost::unit_test::literal_string( s, sizeof( s ) - 1 ) #define BOOST_TEST_EMPTY_STRING BOOST_TEST_STRING_LITERAL( "" ) @@ -41,6 +41,16 @@ #define BOOST_TEST_SUPPORT_TIMEOUT #endif +#if BOOST_WORKAROUND(__BORLANDC__, <= 0x570) || \ + BOOST_WORKAROUND( __COMO__, <= 0x433 ) || \ + BOOST_WORKAROUND( __INTEL_COMPILER, <= 800 ) || \ + BOOST_WORKAROUND(__GNUC__, < 3) || \ + defined(__sgi) && _COMPILER_VERSION <= 730 || \ + BOOST_WORKAROUND(__IBMCPP__, BOOST_TESTED_AT(600)) || \ + defined(__DECCXX) +#define BOOST_TEST_NO_PROTECTED_USING +#endif + // STL #include // for std::distance #include // for std::ptrdiff_t @@ -81,6 +91,9 @@ namespace unit_test_framework = unit_test; // Revision History : // // $Log$ +// Revision 1.25 2005/01/22 19:22:12 rogeeff +// implementation moved into headers section to eliminate dependency of included/minimal component on src directory +// // Revision 1.24 2005/01/21 07:33:20 rogeeff // BOOST_TEST_SUPPORT_TIMEOUT flag introduced to be used by used to switch code by timeout support // diff --git a/include/boost/test/floating_point_comparison.hpp b/include/boost/test/floating_point_comparison.hpp index 2b02ff80..6a288db1 100644 --- a/include/boost/test/floating_point_comparison.hpp +++ b/include/boost/test/floating_point_comparison.hpp @@ -17,7 +17,7 @@ #include // for std::numeric_limits -#include +#include namespace boost { @@ -120,6 +120,9 @@ compute_tolerance( FPT percentage_tolerance ) // Revision History : // // $Log$ +// Revision 1.19 2005/01/22 19:22:12 rogeeff +// implementation moved into headers section to eliminate dependency of included/minimal component on src directory +// // Revision 1.18 2004/07/19 12:14:09 rogeeff // guard rename // tolerance parameter renamed for clarity diff --git a/include/boost/test/impl/cpp_main.ipp b/include/boost/test/impl/cpp_main.ipp new file mode 100644 index 00000000..39c3650d --- /dev/null +++ b/include/boost/test/impl/cpp_main.ipp @@ -0,0 +1,120 @@ +// (C) Copyright Gennadiy Rozental 2001-2004. +// (C) Copyright Beman Dawes 1995-2001. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +// See http://www.boost.org/libs/test for the library home page. +// +// File : $RCSfile$ +// +// Version : $Revision$ +// +// Description : main function implementation for Program Executon Monitor +// *************************************************************************** + +#ifndef BOOST_CPP_MAIN_IPP_012205GER +#define BOOST_CPP_MAIN_IPP_012205GER + +// Boost.Test +#include +#include + +// BOOST +#include +#include + +// STL +#include +#include + +#ifdef BOOST_NO_STDC_NAMESPACE +namespace std { using ::getenv; using ::strcmp; } +#endif + +int cpp_main( int argc, char* argv[] ); // prototype for user's cpp_main() + +namespace { + +class cpp_main_caller : public boost::execution_monitor { +public: + cpp_main_caller( int argc, char** argv ) + : m_argc( argc ), m_argv( argv ) {} + + int function() { return cpp_main( m_argc, m_argv ); } + +private: + int m_argc; + char** m_argv; +}; + +} + +// ************************************************************************** // +// ************** cpp main ************** // +// ************************************************************************** // + +int main( int argc, char* argv[] ) +{ + cpp_main_caller caller( argc, argv ); + + int result; + + boost::unit_test::const_string p( std::getenv( "BOOST_TEST_CATCH_SYSTEM_ERRORS" ) ); + bool catch_system_errors = p != "no"; + + try { + result = caller.execute( catch_system_errors ); + + if( result == 0 ) + result = boost::exit_success; + else if( result != boost::exit_success ) { + std::cout << "\n**** error return code: " << result << std::endl; + result = boost::exit_failure; + } + } + catch( boost::execution_exception const& exex ) { + std::cout << "\n**** exception(" << exex.code() << "): " << exex.what() << std::endl; + result = boost::exit_exception_failure; + } + + if( result != boost::exit_success ) { + std::cerr << "******** errors detected; see standard output for details ********" << std::endl; + } + else { + // Some prefer a confirming message when all is well, while others don't + // like the clutter. Use an environment variable to avoid command + // line argument modifications; for use in production programs + // that's a no-no in some organizations. + boost::unit_test::const_string p( std::getenv( "BOOST_PRG_MON_CONFIRM" ) ); + if( p != "no" ) { + std::cerr << std::flush << "no errors detected" << std::endl; + } + } + + return result; +} + +//____________________________________________________________________________// + +// *************************************************************************** +// Revision History : +// +// $Log$ +// Revision 1.1 2005/01/22 19:22:12 rogeeff +// implementation moved into headers section to eliminate dependency of included/minimal component on src directory +// +// Revision 1.15 2004/05/21 06:26:09 rogeeff +// licence update +// +// Revision 1.14 2004/05/11 11:04:44 rogeeff +// basic_cstring introduced and used everywhere +// class properties reworked +// namespace names shortened +// +// Revision 1.13 2003/12/01 00:42:37 rogeeff +// prerelease cleaning +// +// *************************************************************************** + +#endif // BOOST_CPP_MAIN_IPP_012205GER diff --git a/include/boost/test/impl/execution_monitor.ipp b/include/boost/test/impl/execution_monitor.ipp new file mode 100644 index 00000000..c1a5bc47 --- /dev/null +++ b/include/boost/test/impl/execution_monitor.ipp @@ -0,0 +1,636 @@ +// (C) Copyright Gennadiy Rozental 2001-2004. +// (C) Copyright Beman Dawes and Ullrich Koethe 1995-2001. +// Use, modification, and distribution are subject to the +// Boost Software License, Version 1.0. (See accompanying file +// http://www.boost.org/LICENSE_1_0.txt) + +// See http://www.boost.org/libs/test for the library home page. +// +// File : $RCSfile$ +// +// Version : $Revision$ +// +// Description : provides execution monitor implementation for all supported +// configurations, including Microsoft structured exception based, unix signals +// based and special workarounds for borland +// +// Note that when testing requirements or user wishes preclude use of this +// file as a separate compilation unit, it may be included as a header file. +// +// Header dependencies are deliberately restricted to reduce coupling to other +// boost libraries. +// *************************************************************************** + +#ifndef BOOST_EXECUTION_MONITOR_IPP_012205GER +#define BOOST_EXECUTION_MONITOR_IPP_012205GER + +// Boost.Test +#include + +// BOOST +#include // for exit codes +#include // for workarounds + +// STL +#include // for string +#include // for bad_alloc +#include // for bad_cast, bad_typeid +#include // for exception, bad_exception +#include // for std exception hierarchy +#include // for C string API +#include // for assert +#include // for NULL + +#ifdef BOOST_NO_STDC_NAMESPACE +namespace std { using ::strlen; using ::strncat; } +#endif + +// Microsoft + other compatible compilers such as Intel +#if !defined(BOOST_DISABLE_WIN32) && \ + !defined(__BORLANDC__) && \ + (defined(_MSC_VER) && !defined(__COMO__)) || \ + (defined(__INTEL__) && defined(__MWERKS__) && __MWERKS__ >= 0x3000) + +#define BOOST_MS_STRCTURED_EXCEPTION_HANDLING +#if !defined(_WIN32_WINNT) +#define _WIN32_WINNT 0x0400 +#endif + +#include +#include +#include +#include + +#if !defined(NDEBUG) && !defined(__MWERKS__) // __MWERKS__ does not seem to supply implementation of C runtime debug hooks, causing linking errors +#define BOOST_MS_CRT_DEBUG_HOOK +#include +#endif + +#elif (defined(__BORLANDC__) && defined(_Windows) && !defined(BOOST_DISABLE_WIN32)) +#define BOOST_MS_STRCTURED_EXCEPTION_HANDLING +#include // Borland 5.5.1 has its own way of doing things. + +#elif defined(BOOST_HAS_SIGACTION) + +#define BOOST_SIGACTION_BASED_SIGNAL_HANDLING +#include +#include +#include + +#else + +#define BOOST_NO_SIGNAL_HANDLING + +#endif + +#include + +namespace boost { + +namespace detail { + +using unit_test::const_string; + +// boost::execution_monitor::execute() calls boost::detail::catch_signals() to +// execute user function with signals control +// boost::execution_monitor::execute() calls boost::detail::report_error(...) to +// report any caught exception and throw execution_exception + +const std::size_t REPORT_ERROR_BUFFER_SIZE = 512; + +static int catch_signals( execution_monitor & exmon, bool catch_system_errors, int timeout ); // timeout is in seconds. 0 implies none. + +static void report_error( + execution_exception::error_code ec, + const_string msg1, // first part of the message + const_string msg2 = "" ); // second part of the message; sum length msg1 + msg2 should not + // exceed REPORT_ERROR_BUFFER_SIZE; never concatenate messages + // manually, cause it should work even in case of memory lack + +//____________________________________________________________________________// + +// Declaration for Microsoft structured exception handling (unix alternative - signal) +#ifdef BOOST_MS_STRCTURED_EXCEPTION_HANDLING + +// this class defined per the Microsoft structured exception documentation +class ms_se_exception { +public: + // Constructor + explicit ms_se_exception( unsigned int n ) + : m_se_id( n ) {} + + // Destructor + ~ms_se_exception() {} + + // access methods + unsigned int id() const { return m_se_id; } + +private: + // Data members + unsigned int m_se_id; +}; + +//____________________________________________________________________________// + +void ms_se_trans_func( unsigned int id, _EXCEPTION_POINTERS* exps ); +void ms_se_forward_func( unsigned int id, _EXCEPTION_POINTERS* exps ); +static void report_ms_se_error( unsigned int id ); + +//____________________________________________________________________________// + +// Declarations for unix-style signal handling +#elif defined(BOOST_SIGACTION_BASED_SIGNAL_HANDLING) + +class unix_signal_exception { + typedef execution_exception::error_code error_code_type; +public: + // Constructor + unix_signal_exception( execution_exception::error_code ec, const_string em ) + : m_error_code( ec ), m_error_message( em ) {} + + // Destructor + ~unix_signal_exception() {} + + // access methods + error_code_type error_code() const { return m_error_code; } + const_string error_message() const { return m_error_message; } +private: + // Data members + error_code_type m_error_code; + const_string m_error_message; +}; + +#endif + +//____________________________________________________________________________// + +#if defined(BOOST_MS_CRT_DEBUG_HOOK) + +int +assert_reporting_function( int reportType, char* userMessage, int* retVal ) +{ + switch( reportType ) { + case _CRT_ASSERT: + detail::report_error( execution_exception::user_error, userMessage ); + + return 1; // return value and retVal are not important since we never reach this line + case _CRT_ERROR: + detail::report_error( execution_exception::system_error, userMessage ); + + return 1; // return value and retVal are not important since we never reach this line + default: + return 0; // use usual reporting method + } +} + +#endif + +} // namespace detail + +// ************************************************************************** // +// ************** execution_monitor ************** // +// ************************************************************************** // + +int +execution_monitor::run_function() +{ + return m_custom_translators ? (*m_custom_translators)( *this ) : function(); +} + +//____________________________________________________________________________// + +int +execution_monitor::execute( bool catch_system_errors, int timeout ) +{ + using unit_test::const_string; + +#if defined(BOOST_MS_STRCTURED_EXCEPTION_HANDLING) && !defined(__BORLANDC__) + if( IsDebuggerPresent() ) + catch_system_errors = false; + + if( catch_system_errors ) + _set_se_translator( detail::ms_se_trans_func ); + else + _set_se_translator( detail::ms_se_forward_func ); +#endif + +#if defined(BOOST_MS_CRT_DEBUG_HOOK) + if( catch_system_errors ) + _CrtSetReportHook( &detail::assert_reporting_function ); +#endif + + try { + return detail::catch_signals( *this, catch_system_errors, timeout ); + } + + // Catch-clause reference arguments are a bit different from function + // arguments (ISO 15.3 paragraphs 18 & 19). Apparently const isn't + // required. Programmers ask for const anyhow, so we supply it. That's + // easier than answering questions about non-const usage. + + catch( char const* ex ) + { detail::report_error( execution_exception::cpp_exception_error, "C string: ", ex ); } + catch( std::string const& ex ) + { detail::report_error( execution_exception::cpp_exception_error, "std::string: ", ex.c_str() ); } + + // std:: exceptions + + catch( std::bad_alloc const& ex ) + { detail::report_error( execution_exception::cpp_exception_error, "std::bad_alloc: ", ex.what() ); } + +#if !defined(__BORLANDC__) || __BORLANDC__ > 0x0551 + catch( std::bad_cast const& ex ) + { detail::report_error( execution_exception::cpp_exception_error, "std::bad_cast: ", ex.what() ); } + catch( std::bad_typeid const& ex ) + { detail::report_error( execution_exception::cpp_exception_error, "std::bad_typeid: ", ex.what() ); } +#else + catch( std::bad_cast const& ex ) + { detail::report_error( execution_exception::cpp_exception_error, "std::bad_cast" ); } + catch( std::bad_typeid const& ex ) + { detail::report_error( execution_exception::cpp_exception_error, "std::bad_typeid" ); } +#endif + + catch( std::bad_exception const& ex ) + { detail::report_error( execution_exception::cpp_exception_error, "std::bad_exception: ", ex.what() ); } + catch( std::domain_error const& ex ) + { detail::report_error( execution_exception::cpp_exception_error, "std::domain_error: ", ex.what() ); } + catch( std::invalid_argument const& ex ) + { detail::report_error( execution_exception::cpp_exception_error, "std::invalid_argument: ", ex.what() ); } + catch( std::length_error const& ex ) + { detail::report_error( execution_exception::cpp_exception_error, "std::length_error: ", ex.what() ); } + catch( std::out_of_range const& ex ) + { detail::report_error( execution_exception::cpp_exception_error, "std::out_of_range: ", ex.what() ); } + catch( std::range_error const& ex ) + { detail::report_error( execution_exception::cpp_exception_error, "std::range_error: ", ex.what() ); } + catch( std::overflow_error const& ex ) + { detail::report_error( execution_exception::cpp_exception_error, "std::overflow_error: ", ex.what() ); } + catch( std::underflow_error const& ex ) + { detail::report_error( execution_exception::cpp_exception_error, "std::underflow_error: ", ex.what() ); } + catch( std::logic_error const& ex ) + { detail::report_error( execution_exception::cpp_exception_error, "std::logic_error: ", ex.what() ); } + catch( std::runtime_error const& ex ) + { detail::report_error( execution_exception::cpp_exception_error, "std::runtime_error: ", ex.what() ); } + catch( std::exception const& ex ) + { detail::report_error( execution_exception::cpp_exception_error, "std::exception: ", ex.what() ); } + +#if defined(BOOST_MS_STRCTURED_EXCEPTION_HANDLING) + catch( detail::ms_se_exception const& ex ) + { detail::report_ms_se_error( ex.id() ); } +#elif defined(BOOST_SIGACTION_BASED_SIGNAL_HANDLING) + catch( detail::unix_signal_exception const& ex ) + { detail::report_error( ex.error_code(), ex.error_message() ); } +#endif // BOOST_SIGACTION_BASED_SIGNAL_HANDLING + + catch( execution_exception const& ) { throw; } + + catch( ... ) + { detail::report_error( execution_exception::cpp_exception_error, "unknown type" ); } + + return 0; // never reached; supplied to quiet compiler warnings +} // execute + +//____________________________________________________________________________// + +namespace detail { + +#if defined(BOOST_SIGACTION_BASED_SIGNAL_HANDLING) + +// ************************************************************************** // +// ************** boost::detail::signal_handler ************** // +// ************************************************************************** // + +class signal_handler { +public: + // Constructor + explicit signal_handler( bool catch_system_errors, int timeout ); + + // Destructor + ~signal_handler(); + + // access methods + static sigjmp_buf& jump_buffer() + { + assert( !!s_active_handler ); + + return s_active_handler->m_sigjmp_buf; + } + +private: + // Data members + struct sigaction m_same_action_for_all_signals; + struct sigaction m_old_SIGFPE_action; + struct sigaction m_old_SIGTRAP_action; + struct sigaction m_old_SIGSEGV_action; + struct sigaction m_old_SIGBUS_action; + struct sigaction m_old_SIGABRT_action; + struct sigaction m_old_SIGALRM_action; + + sigjmp_buf m_sigjmp_buf; + + signal_handler* m_prev_handler; + static signal_handler* s_active_handler; + + bool m_catch_system_errors; + bool m_set_timeout; +}; + +signal_handler* signal_handler::s_active_handler = NULL; //!! need to be placed in thread specific storage + +//____________________________________________________________________________// + +extern "C" { + +static void execution_monitor_signal_handler( int sig ) +{ + siglongjmp( signal_handler::jump_buffer(), sig ); +} + +} + +//____________________________________________________________________________// + +signal_handler::signal_handler( bool catch_system_errors, int timeout ) +: m_prev_handler( s_active_handler ), + m_catch_system_errors( catch_system_errors ), + m_set_timeout( timeout > 0 ) +{ + s_active_handler = this; + + if( m_catch_system_errors || m_set_timeout ) { + m_same_action_for_all_signals.sa_flags = 0; + m_same_action_for_all_signals.sa_handler = &execution_monitor_signal_handler; + sigemptyset( &m_same_action_for_all_signals.sa_mask ); + } + + if( m_catch_system_errors ) { + sigaction( SIGFPE , &m_same_action_for_all_signals, &m_old_SIGFPE_action ); + sigaction( SIGTRAP, &m_same_action_for_all_signals, &m_old_SIGTRAP_action ); + sigaction( SIGSEGV, &m_same_action_for_all_signals, &m_old_SIGSEGV_action ); + sigaction( SIGBUS , &m_same_action_for_all_signals, &m_old_SIGBUS_action ); + sigaction( SIGABRT, &m_same_action_for_all_signals, &m_old_SIGABRT_action ); + } + + if( m_set_timeout ) { + sigaction( SIGALRM , &m_same_action_for_all_signals, &m_old_SIGALRM_action ); + alarm( timeout ); + } +} + +//____________________________________________________________________________// + +signal_handler::~signal_handler() +{ + typedef struct sigaction* sigaction_ptr; + + assert( s_active_handler == this ); + + if( m_set_timeout ) { + alarm( 0 ); + sigaction( SIGALRM, &m_old_SIGALRM_action, sigaction_ptr() ); + } + + if( m_catch_system_errors ) { + sigaction( SIGFPE , &m_old_SIGFPE_action , sigaction_ptr() ); + sigaction( SIGTRAP, &m_old_SIGTRAP_action, sigaction_ptr() ); + sigaction( SIGSEGV, &m_old_SIGSEGV_action, sigaction_ptr() ); + sigaction( SIGBUS , &m_old_SIGBUS_action , sigaction_ptr() ); + sigaction( SIGABRT, &m_old_SIGABRT_action, sigaction_ptr() ); + } + + s_active_handler = m_prev_handler; +} + +//____________________________________________________________________________// + +// ************************************************************************** // +// ************** boost::detail::catch_signals ************** // +// ************************************************************************** // + +int catch_signals( execution_monitor & exmon, bool catch_system_errors, int timeout ) +{ + signal_handler local_signal_handler( catch_system_errors, timeout ); + int result = 0; + execution_exception::error_code ec = execution_exception::no_error; + const_string em; + + volatile int sigtype = sigsetjmp( signal_handler::jump_buffer(), 1 ); + if( sigtype == 0 ) { + result = exmon.run_function(); + } + else { + switch(sigtype) { + case SIGALRM: + ec = execution_exception::timeout_error; + em = BOOST_TEST_L( "signal: SIGALRM (timeout while executing function)" ); + break; + case SIGTRAP: + ec = execution_exception::system_error; + em = BOOST_TEST_L( "signal: SIGTRAP (perhaps integer divide by zero)" ); + break; + case SIGFPE: + ec = execution_exception::system_error; + em = BOOST_TEST_L( "signal: SIGFPE (arithmetic exception)" ); + break; + case SIGABRT: + ec = execution_exception::system_error; + em = BOOST_TEST_L( "signal: SIGABRT (application abort requested)" ); + break; + case SIGSEGV: + case SIGBUS: + ec = execution_exception::system_fatal_error; + em = BOOST_TEST_L( "signal: memory access violation" ); + break; + default: + ec = execution_exception::system_error; + em = BOOST_TEST_L( "signal: unrecognized signal" ); + } + } + + if( ec != execution_exception::no_error ) { + throw unix_signal_exception( ec, em ); + } + + return result; +} // unix catch_signals + +//____________________________________________________________________________// + +#elif (defined(__BORLANDC__) && defined(_Windows) && !defined(BOOST_DISABLE_WIN32)) + +// this works for Borland but not other Win32 compilers (which trap too many cases) +int catch_signals( execution_monitor & exmon, bool catch_system_errors, int ) +{ + int result; + + if( catch_system_errors ) { + __try { result = exmon.run_function(); } + + __except (1) + { + throw ms_se_exception( GetExceptionCode() ); + } + } + else { + result = exmon.run_function(); + } + return result; +} + +#else // default signal handler + +int catch_signals( execution_monitor& exmon, bool, int ) +{ + return exmon.run_function(); +} + +#endif // choose signal handler + +// ************************************************************************** // +// ************** Microsoft structured exception handling ************** // +// ************************************************************************** // + +#if defined(BOOST_MS_STRCTURED_EXCEPTION_HANDLING) + +void +ms_se_trans_func( unsigned int id, _EXCEPTION_POINTERS* /* exps */ ) +{ + throw ms_se_exception( id ); +} + +//____________________________________________________________________________// + +void +ms_se_forward_func( unsigned int /* id */, _EXCEPTION_POINTERS* /* exps */ ) +{ + throw; +} + +//____________________________________________________________________________// + +void +report_ms_se_error( unsigned int id ) +{ + switch( id ) { + // cases classified as fatal_system_error + case EXCEPTION_ACCESS_VIOLATION: + detail::report_error( execution_exception::system_fatal_error, "memory access violation" ); + break; + + case EXCEPTION_ILLEGAL_INSTRUCTION: + detail::report_error( execution_exception::system_fatal_error, "illegal instruction" ); + break; + + case EXCEPTION_PRIV_INSTRUCTION: + detail::report_error( execution_exception::system_fatal_error, "privileged instruction" ); + break; + + case EXCEPTION_IN_PAGE_ERROR: + detail::report_error( execution_exception::system_fatal_error, "memory page error" ); + break; + + case EXCEPTION_STACK_OVERFLOW: + detail::report_error( execution_exception::system_fatal_error, "stack overflow" ); + break; + + // cases classified as (non-fatal) system_trap + case EXCEPTION_DATATYPE_MISALIGNMENT: + detail::report_error( execution_exception::system_error, "data misalignment" ); + break; + + case EXCEPTION_INT_DIVIDE_BY_ZERO: + detail::report_error( execution_exception::system_error, "integer divide by zero" ); + break; + + case EXCEPTION_INT_OVERFLOW: + detail::report_error( execution_exception::system_error, "integer overflow" ); + break; + + case EXCEPTION_ARRAY_BOUNDS_EXCEEDED: + detail::report_error( execution_exception::system_error, "array bounds exceeded" ); + break; + + case EXCEPTION_FLT_DIVIDE_BY_ZERO: + detail::report_error( execution_exception::system_error, "floating point divide by zero" ); + break; + + case EXCEPTION_FLT_STACK_CHECK: + detail::report_error( execution_exception::system_error, "floating point stack check" ); + break; + + case EXCEPTION_FLT_DENORMAL_OPERAND: + case EXCEPTION_FLT_INEXACT_RESULT: + case EXCEPTION_FLT_INVALID_OPERATION: + case EXCEPTION_FLT_OVERFLOW: + case EXCEPTION_FLT_UNDERFLOW: + detail::report_error( execution_exception::system_error, "floating point error" ); + break; + + default: + detail::report_error( execution_exception::system_error, "unrecognized exception or signal" ); + break; + } // switch +} // report_ms_se_error + +//____________________________________________________________________________// + +#endif // Microsoft structured exception handling + +// ************************************************************************** // +// ************** report_error ************** // +// ************************************************************************** // + +static void report_error( execution_exception::error_code ec, const_string msg1, const_string msg2 ) +{ + static char buf[REPORT_ERROR_BUFFER_SIZE]; + + buf[0] = '\0'; + + std::strncat( buf, msg1.begin(), sizeof(buf)-1 ); + std::strncat( buf, msg2.begin(), sizeof(buf) - msg1.size() - 1 ); + + throw execution_exception( ec, buf ); +} + +//____________________________________________________________________________// + +} // namespace detail + +} // namespace boost + +// *************************************************************************** +// Revision History : +// +// $Log$ +// Revision 1.1 2005/01/22 19:22:12 rogeeff +// implementation moved into headers section to eliminate dependency of included/minimal component on src directory +// +// Revision 1.36 2005/01/21 07:21:38 rogeeff +// detect presence of debugger under VC and automatically prevent catching system errors +// +// Revision 1.35 2004/08/19 00:02:21 rogeeff +// another tru64cxx65 workaround +// +// Revision 1.34 2004/07/19 12:08:12 rogeeff +// suppress warnings +// +// Revision 1.33 2004/06/07 07:34:22 rogeeff +// detail namespace renamed +// +// Revision 1.32 2004/05/21 06:26:09 rogeeff +// licence update +// +// Revision 1.31 2004/05/11 11:04:44 rogeeff +// basic_cstring introduced and used everywhere +// class properties reworked +// namespace names shortened +// +// Revision 1.30 2003/12/20 11:27:28 johnmaddock +// Added fixes for Borland C++ 6.0 compiler (With EDG frontend). +// +// Revision 1.29 2003/12/01 00:42:37 rogeeff +// prerelease cleaning +// + +// *************************************************************************** + +#endif // BOOST_EXECUTION_MONITOR_IPP_012205GER diff --git a/include/boost/test/impl/supplied_log_formatters.ipp b/include/boost/test/impl/supplied_log_formatters.ipp new file mode 100644 index 00000000..7edf5386 --- /dev/null +++ b/include/boost/test/impl/supplied_log_formatters.ipp @@ -0,0 +1,374 @@ +// (C) Copyright Gennadiy Rozental 2001-2004. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +// See http://www.boost.org/libs/test for the library home page. +// +// File : $RCSfile$ +// +// Version : $Revision$ +// +// Description : implements Unit Test Log formatters +// *************************************************************************** + +#ifndef BOOST_SUPPLIED_LOG_FORMATTERS_IPP_012205GER +#define BOOST_SUPPLIED_LOG_FORMATTERS_IPP_012205GER + +// Boost.Test +#include +#include +#include +#include + +#include + +// BOOST +#include + +// STL +#include +#include +#include +#include + +namespace boost { + +namespace unit_test { + +namespace ut_detail { + +// ************************************************************************** // +// ************** compiler_log_formatter ************** // +// ************************************************************************** // + +void +compiler_log_formatter::start_log( std::ostream& output, bool log_build_info ) +{ + if( log_build_info ) + output << "Platform: " << BOOST_PLATFORM << '\n' + << "Compiler: " << BOOST_COMPILER << '\n' + << "STL : " << BOOST_STDLIB << '\n' + << "Boost : " << BOOST_VERSION/100000 << "." + << BOOST_VERSION/100 % 1000 << "." + << BOOST_VERSION % 100 << '\n'; +} + +//____________________________________________________________________________// + +void +compiler_log_formatter::log_header( std::ostream& output, unit_test_counter test_cases_amount ) +{ + output << "Running " << test_cases_amount << " test " + << (test_cases_amount > 1 ? "cases" : "case") << "...\n"; +} + +//____________________________________________________________________________// + +void +compiler_log_formatter::finish_log( std::ostream& /* output */ ) +{ +} + +//____________________________________________________________________________// + +void +compiler_log_formatter::track_test_case_enter( std::ostream& output, test_case const& tc ) +{ + output << "Entering test " << ( tc.p_type ? "case" : "suite" ) << " \"" << tc.p_name << "\""; +} + +//____________________________________________________________________________// + +void +compiler_log_formatter::track_test_case_exit( std::ostream& output, test_case const& tc, long testing_time_in_mks ) +{ + output << "Leaving test " << ( tc.p_type ? "case" : "suite" ) << " \"" << tc.p_name << "\""; + if( testing_time_in_mks > 0 ) { + output << "; testing time: "; + if( testing_time_in_mks % 1000 == 0 ) + output << testing_time_in_mks/1000 << "ms"; + else + output << testing_time_in_mks << "ms"; + } +} + +//____________________________________________________________________________// + +void +compiler_log_formatter::log_exception( std::ostream& output, log_checkpoint_data const& checkpoint_data , + const_string test_case_name, const_string explanation ) +{ + output << "Exception in \"" << test_case_name << "\": " << explanation; + + if( !checkpoint_data.m_message.empty() ) { + output << '\n'; + print_prefix( output, checkpoint_data.m_file, checkpoint_data.m_line ); + output << "last checkpoint: " << checkpoint_data.m_message; + } +} + +//____________________________________________________________________________// + +void +compiler_log_formatter::begin_log_entry( std::ostream& output, log_entry_data const& entry_data, log_entry_types let ) +{ + switch( let ) { + case BOOST_UTL_ET_INFO: + print_prefix( output, entry_data.m_file, entry_data.m_line ); + output << "info: "; + break; + case BOOST_UTL_ET_MESSAGE: + break; + case BOOST_UTL_ET_WARNING: + print_prefix( output, entry_data.m_file, entry_data.m_line ); + output << "warning in \"" << unit_test_result::instance().test_case_name() << "\": "; + break; + case BOOST_UTL_ET_ERROR: + print_prefix( output, entry_data.m_file, entry_data.m_line ); + output << "error in \"" << unit_test_result::instance().test_case_name() << "\": "; + break; + case BOOST_UTL_ET_FATAL_ERROR: + print_prefix( output, entry_data.m_file, entry_data.m_line ); + output << "fatal error in \"" << unit_test_result::instance().test_case_name() << "\": "; + break; + } +} + +//____________________________________________________________________________// + +void +compiler_log_formatter::log_entry_value( std::ostream& output, const_string value ) +{ + output << value; +} + +//____________________________________________________________________________// + +void +compiler_log_formatter::end_log_entry( std::ostream& /* output */ ) +{ +} + +//____________________________________________________________________________// + +void +compiler_log_formatter::print_prefix( std::ostream& output, const_string file, std::size_t line ) +{ + output << file << '(' << line << "): "; +} + +//____________________________________________________________________________// + +// ************************************************************************** // +// ************** xml_log_formatter ************** // +// ************************************************************************** // + +xml_log_formatter::xml_log_formatter() +: m_indent( 0 ) +{ +} + +//____________________________________________________________________________// + +void +xml_log_formatter::start_log( std::ostream& output, bool log_build_info ) +{ + output << "\n"; +} + +//____________________________________________________________________________// + +void +xml_log_formatter::log_header( std::ostream& /* output */, unit_test_counter /* test_cases_amount */ ) +{ +} + +//____________________________________________________________________________// + +void +xml_log_formatter::finish_log( std::ostream& output ) +{ + output << "\n"; +} + +//____________________________________________________________________________// + +void +xml_log_formatter::track_test_case_enter( std::ostream& output, test_case const& tc ) +{ + print_indent( output ); + + output << "<" << ( tc.p_type ? "TestCase" : "TestSuite" ) + << " name" << attr_value() << tc.p_name + << ">"; + + m_indent += 2; +} + +//____________________________________________________________________________// + +void +xml_log_formatter::track_test_case_exit( std::ostream& output, test_case const& tc, long testing_time_in_mks ) +{ + m_indent -= 2; + + print_indent( output ); + + output << ""; +} + +//____________________________________________________________________________// + +void +xml_log_formatter::log_exception( std::ostream& output, log_checkpoint_data const& checkpoint_data, const_string test_case_name, const_string explanation ) +{ + print_indent( output ); + output << "\n"; + + m_indent += 2; + + print_indent( output ); + output << pcdata() << explanation << '\n'; + + if( !checkpoint_data.m_message.empty() ) { + print_indent( output ); + output << "\n"; + + m_indent += 2; + + print_indent( output ); + output << pcdata() << checkpoint_data.m_message << "\n"; + + m_indent -= 2; + + print_indent( output ); + output << "\n"; + } + + m_indent -= 2; + print_indent( output ); + + output << ""; +} + +//____________________________________________________________________________// + +void +xml_log_formatter::begin_log_entry( std::ostream& output, log_entry_data const& entry_data, log_entry_types let ) +{ + static literal_string xml_tags[] = { "Info", "Message", "Warning", "Error", "FatalError" }; + + print_indent( output ); + + m_curr_tag = xml_tags[let]; + output << '<' << m_curr_tag + << " file" << attr_value() << entry_data.m_file + << " line" << attr_value() << entry_data.m_line + << ">\n"; + + m_indent += 2; + print_indent( output ); +} + +//____________________________________________________________________________// + +void +xml_log_formatter::log_entry_value( std::ostream& output, const_string value ) +{ + output << pcdata() << value; +} + +//____________________________________________________________________________// + +void +xml_log_formatter::end_log_entry( std::ostream& output ) +{ + if( m_curr_tag.is_empty() ) + return; + + output << '\n'; + + m_indent -= 2; + print_indent( output ); + + output << ""; + + m_curr_tag.clear(); +} + +//____________________________________________________________________________// + +void +xml_log_formatter::print_indent( std::ostream& output ) +{ + output << std::setw( m_indent ) << ""; +} + +//____________________________________________________________________________// + +} // namespace ut_detail + +} // namespace unit_test + +} // namespace boost + +// *************************************************************************** +// Revision History : +// +// $Log$ +// Revision 1.1 2005/01/22 19:22:12 rogeeff +// implementation moved into headers section to eliminate dependency of included/minimal component on src directory +// +// Revision 1.15 2005/01/21 07:23:49 rogeeff +// added automatic test case run timing +// +// Revision 1.13 2005/01/18 08:29:59 rogeeff +// unit_test_log rework: +// eliminated need for ::instance() +// eliminated need for << end and ...END macro +// straitend interface between log and formatters +// change compiler like formatter name +// minimized unit_test_log interface and reworked to use explicit calls +// +// Revision 1.12 2004/07/20 17:03:55 dgregor +// Documentation update from Jon T. Pedant +// +// Revision 1.11 2004/07/19 12:09:25 rogeeff +// added proper encoded of XML PCDATA +// +// Revision 1.10 2004/06/07 07:34:22 rogeeff +// detail namespace renamed +// +// Revision 1.9 2004/05/21 06:26:09 rogeeff +// licence update +// +// Revision 1.8 2004/05/13 09:04:43 rogeeff +// added fixed_mapping +// +// Revision 1.7 2004/05/11 11:04:44 rogeeff +// basic_cstring introduced and used everywhere +// class properties reworked +// namespace names shortened +// +// Revision 1.6 2003/12/01 00:42:37 rogeeff +// prerelease cleaning +// +// *************************************************************************** + +#endif // BOOST_SUPPLIED_LOG_FORMATTERS_IPP_012205GER diff --git a/include/boost/test/impl/test_main.ipp b/include/boost/test/impl/test_main.ipp new file mode 100644 index 00000000..a19bf6b6 --- /dev/null +++ b/include/boost/test/impl/test_main.ipp @@ -0,0 +1,137 @@ +// (C) Copyright Gennadiy Rozental 2001-2004. +// (C) Copyright Beman Dawes 1995-2001. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +// See http://www.boost.org/libs/test for the library home page. +// +// File : $RCSfile$ +// +// Version : $$Revision$ +// +// Description : implements main function for Test Execution Monitor. +// *************************************************************************** + +#ifndef BOOST_TEST_MAIN_IPP_012205GER +#define BOOST_TEST_MAIN_IPP_012205GER + +// Boost.Test +#include // for unit test framework +#include +#include +#include + +// BOOST +#include + +// STL +#include // for cout, cerr + +int test_main( int argc, char* argv[] ); // prototype for user's test_main() + +namespace { + int argc_; + char** argv_; + int test_main_result; + + void call_test_main() + { + test_main_result = test_main( argc_, argv_ ); + + // translate a test_main non-success return into a test error + BOOST_CHECK( test_main_result == 0 || test_main_result == boost::exit_success ); + } +} + +// ************************************************************************** // +// ************** test main ************** // +// ************************************************************************** // + +int main( int argc, char* argv[] ) { + using namespace boost::unit_test; + + // set the log level + unit_test_log.set_threshold_level_by_name( retrieve_framework_parameter( LOG_LEVEL, &argc, argv ) ); + + // set the report level + const_string reportlevel = retrieve_framework_parameter( REPORT_LEVEL, &argc, argv ); + + // set the log/report format + const_string output_format = retrieve_framework_parameter( OUTPUT_FORMAT, &argc, argv ); + + if( output_format.empty() ) { + unit_test_log.set_format( retrieve_framework_parameter( LOG_FORMAT, &argc, argv ) ); + unit_test_result::set_report_format( retrieve_framework_parameter( REPORT_FORMAT, &argc, argv ) ); + } + else { + unit_test_log.set_format( output_format ); + unit_test_result::set_report_format( output_format ); + } + + // set the result code flag + bool no_result_code = retrieve_framework_parameter( NO_RESULT_CODE, &argc, argv ) == "no"; + + // set catch_system_error switch + ut_detail::unit_test_monitor::catch_system_errors( retrieve_framework_parameter( CATCH_SYS_ERRORS, &argc, argv ) != "no" ); + + // set up the test + argc_ = argc; + argv_ = argv; + boost::scoped_ptr test_main_tc( BOOST_TEST_CASE( &call_test_main ) ); + + // start testing + unit_test_log.start( retrieve_framework_parameter( BUILD_INFO, &argc, argv ) == "yes" ); + test_main_tc->run(); + unit_test_log.finish( 1 ); + + // report results + unit_test_result::instance().report( reportlevel, std::cout ); + + // return code + return no_result_code + ? boost::exit_success + : ( test_main_result != 0 && test_main_result != boost::exit_success + ? test_main_result + : unit_test_result::instance().result_code() + ); +} + +// *************************************************************************** +// Revision History : +// +// $Log$ +// Revision 1.1 2005/01/22 19:22:12 rogeeff +// implementation moved into headers section to eliminate dependency of included/minimal component on src directory +// +// Revision 1.20 2005/01/19 16:34:06 vawjr +// Changed the \r\r\n back to \r\n on windows so we don't get errors when compiling +// on VC++8.0. I don't know why Microsoft thinks it's a good idea to call this an error, +// but they do. I also don't know why people insist on checking out files on Windows and +// copying them to a unix system to check them in (which will cause exactly this problem) +// +// Revision 1.19 2005/01/18 08:30:08 rogeeff +// unit_test_log rework: +// eliminated need for ::instance() +// eliminated need for << end and ...END macro +// straitend interface between log and formatters +// change compiler like formatter name +// minimized unit_test_log interface and reworked to use explicit calls +// +// Revision 1.18 2004/06/07 07:34:22 rogeeff +// detail namespace renamed +// +// Revision 1.17 2004/05/21 06:26:09 rogeeff +// licence update +// +// Revision 1.16 2004/05/11 11:04:44 rogeeff +// basic_cstring introduced and used everywhere +// class properties reworked +// namespace names shortened +// +// Revision 1.15 2003/12/01 00:42:37 rogeeff +// prerelease cleaning +// +// *************************************************************************** + +#endif // BOOST_TEST_MAIN_IPP_012205GER diff --git a/include/boost/test/impl/test_tools.ipp b/include/boost/test/impl/test_tools.ipp new file mode 100644 index 00000000..05edad29 --- /dev/null +++ b/include/boost/test/impl/test_tools.ipp @@ -0,0 +1,479 @@ +// (C) Copyright Gennadiy Rozental 2001-2004. +// (C) Copyright Ullrich Koethe 2001. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +// See http://www.boost.org/libs/test for the library home page. +// +// File : $RCSfile$ +// +// Version : $Revision$ +// +// Description : supplies offline implementation for the Test Tools +// *************************************************************************** + +#ifndef BOOST_TEST_TOOLS_IPP_012205GER +#define BOOST_TEST_TOOLS_IPP_012205GER + +// Boost.Test +#include +#include + +// BOOST +#include + +// STL +#include +#include +#include +#include +#include +#include +#include +#ifdef BOOST_STANDARD_IOSTREAMS +#include +#endif + +# ifdef BOOST_NO_STDC_NAMESPACE +namespace std { using ::strcmp; using ::strlen; using ::isprint; } +#if !defined( BOOST_NO_CWCHAR ) +namespace std { using ::wcscmp; } +#endif +# endif + +#include + +namespace boost { + +namespace test_tools { + +#define LOG BOOST_UT_LOG_ENTRY_FL( file_name, line_num ) + +namespace tt_detail { + +// ************************************************************************** // +// ************** TOOL BOX Implementation ************** // +// ************************************************************************** // + +void +checkpoint_impl( wrap_stringstream& message, const_string file_name, std::size_t line_num ) +{ + LOG( unit_test::log_test_suites ) << unit_test::checkpoint( message.str() ); +} + +//____________________________________________________________________________// + +void +message_impl( wrap_stringstream& message, const_string file_name, std::size_t line_num ) +{ + LOG( unit_test::log_messages ) << message.str(); +} + +//____________________________________________________________________________// + +void +warn_and_continue_impl( bool predicate, wrap_stringstream& message, + const_string file_name, std::size_t line_num, bool add_fail_pass ) +{ + if( !predicate ) { + LOG( unit_test::log_warnings ) << (add_fail_pass ? "condition " : "") << message.str() + << (add_fail_pass ? " is not satisfied" : "" ); + } + else { + LOG( unit_test::log_successful_tests ) << "condition " << message.str() << " is satisfied"; + } +} + +//____________________________________________________________________________// + +void +warn_and_continue_impl( extended_predicate_value const& v, wrap_stringstream& message, + const_string file_name, std::size_t line_num, bool add_fail_pass ) +{ + warn_and_continue_impl( !!v, + wrap_stringstream().ref() << (add_fail_pass ? "condition " : "") << message + << (add_fail_pass && !v ? " is not satisfied. " : "" ) << *(v.p_message), + file_name, line_num, false ); +} + +//____________________________________________________________________________// + +bool +test_and_continue_impl( bool predicate, wrap_stringstream& message, + const_string file_name, std::size_t line_num, bool add_fail_pass, + unit_test::log_level loglevel ) +{ + if( !predicate ) { + unit_test::unit_test_result::instance().inc_failed_assertions(); + + LOG( loglevel ) << (add_fail_pass ? "test " : "") << message.str() << (add_fail_pass ? " failed" : ""); + + return true; + } + else { + unit_test::unit_test_result::instance().inc_passed_assertions(); + + LOG( unit_test::log_successful_tests ) << (add_fail_pass ? "test " : "") << message.str() + << (add_fail_pass ? " passed" : ""); + + return false; + } +} + +//____________________________________________________________________________// + +bool +test_and_continue_impl( extended_predicate_value const& v, wrap_stringstream& message, + const_string file_name, std::size_t line_num, bool add_fail_pass, + unit_test::log_level loglevel ) +{ + return test_and_continue_impl( !!v, + wrap_stringstream().ref() << (add_fail_pass ? "test " : "") << message + << (add_fail_pass ? (!v ? " failed. " : " passed. ") : "") << *(v.p_message), + file_name, line_num, false, loglevel ); +} + +//____________________________________________________________________________// + +void +test_and_throw_impl( bool predicate, wrap_stringstream& message, + const_string file_name, std::size_t line_num, + bool add_fail_pass, unit_test::log_level loglevel ) +{ + if( test_and_continue_impl( predicate, message, file_name, line_num, add_fail_pass, loglevel ) ) + throw test_tool_failed(); // error already reported by test_and_continue_impl +} + +//____________________________________________________________________________// + +void +test_and_throw_impl( extended_predicate_value const& v, wrap_stringstream& message, + const_string file_name, std::size_t line_num, + bool add_fail_pass, unit_test::log_level loglevel ) +{ + if( test_and_continue_impl( v, message, file_name, line_num, add_fail_pass, loglevel ) ) + throw test_tool_failed(); // error already reported by test_and_continue_impl +} + +//____________________________________________________________________________// + +bool +equal_and_continue_impl( char const* left, char const* right, wrap_stringstream& message, + const_string file_name, std::size_t line_num, + unit_test::log_level loglevel ) +{ + bool predicate = (left && right) ? std::strcmp( left, right ) == 0 : (left == right); + + left = left ? left : "null string"; + right = right ? right : "null string"; + + if( !predicate ) { + return test_and_continue_impl( false, + wrap_stringstream().ref() << "test " << message.str() << " failed [" << left << " != " << right << "]", + file_name, line_num, false, loglevel ); + } + + return test_and_continue_impl( true, message, file_name, line_num, true, loglevel ); +} + +//____________________________________________________________________________// + +#if !defined( BOOST_NO_CWCHAR ) +bool +equal_and_continue_impl( wchar_t const* left, wchar_t const* right, wrap_stringstream& message, + const_string file_name, std::size_t line_num, + unit_test::log_level loglevel ) +{ + bool predicate = (left && right) ? std::wcscmp( left, right ) == 0 : (left == right); + + left = left ? left : L"null string"; + right = right ? right : L"null string"; + + if( !predicate ) { + return test_and_continue_impl( false, + wrap_stringstream().ref() << "test " << message.str() << " failed", + file_name, line_num, false, loglevel ); + } + + return test_and_continue_impl( true, message, file_name, line_num, true, loglevel ); +} +#endif // !defined( BOOST_NO_CWCHAR ) + +//____________________________________________________________________________// + +bool +is_defined_impl( const_string symbol_name, const_string symbol_value ) +{ + symbol_value.trim_left( 2 ); + return symbol_name != symbol_value; +} + +//____________________________________________________________________________// + +// ************************************************************************** // +// ************** log print helper ************** // +// ************************************************************************** // + +void +print_log_value::operator()( std::ostream& ostr, char t ) +{ + if( (std::isprint)( t ) ) + ostr << '\'' << t << '\''; + else + ostr << std::hex + // showbase is only available for new style streams: +#ifndef BOOST_NO_STD_LOCALE + << std::showbase +#else + << "0x" +#endif + << (int)t; +} + +//____________________________________________________________________________// + +void +print_log_value::operator()( std::ostream& ostr, unsigned char t ) +{ + ostr << std::hex + // showbase is only available for new style streams: +#ifndef BOOST_NO_STD_LOCALE + << std::showbase +#else + << "0x" +#endif + << (int)t; +} + +//____________________________________________________________________________// + +} // namespace tt_detail + +// ************************************************************************** // +// ************** output_test_stream ************** // +// ************************************************************************** // + +struct output_test_stream::Impl +{ + std::fstream m_pattern_to_match_or_save; + bool m_match_or_save; + std::string m_synced_string; + + char get_char() + { + char res; + do { + m_pattern_to_match_or_save.get( res ); + } while( res == '\r' && + !m_pattern_to_match_or_save.fail() && + !m_pattern_to_match_or_save.eof() ); + + return res; + } + + void check_and_fill( extended_predicate_value& res ) + { + if( !res.p_predicate_value ) + *(res.p_message) << "Output content: \"" << m_synced_string << '\"'; + } +}; + +//____________________________________________________________________________// + +output_test_stream::output_test_stream( const_string pattern_file_name, bool match_or_save ) +: m_pimpl( new Impl ) +{ + if( !pattern_file_name.is_empty() ) + m_pimpl->m_pattern_to_match_or_save.open( pattern_file_name.begin(), match_or_save ? std::ios::in : std::ios::out ); + + m_pimpl->m_match_or_save = match_or_save; +} + +//____________________________________________________________________________// + +output_test_stream::~output_test_stream() +{ +} + +//____________________________________________________________________________// + +extended_predicate_value +output_test_stream::is_empty( bool flush_stream ) +{ + sync(); + + result_type res( m_pimpl->m_synced_string.empty() ); + + m_pimpl->check_and_fill( res ); + + if( flush_stream ) + flush(); + + return res; +} + +//____________________________________________________________________________// + +extended_predicate_value +output_test_stream::check_length( std::size_t length_, bool flush_stream ) +{ + sync(); + + result_type res( m_pimpl->m_synced_string.length() == length_ ); + + m_pimpl->check_and_fill( res ); + + if( flush_stream ) + flush(); + + return res; +} + +//____________________________________________________________________________// + +extended_predicate_value +output_test_stream::is_equal( const_string arg, bool flush_stream ) +{ + sync(); + + result_type res( const_string( m_pimpl->m_synced_string ) == arg ); + + m_pimpl->check_and_fill( res ); + + if( flush_stream ) + flush(); + + return res; +} + +//____________________________________________________________________________// + +extended_predicate_value +output_test_stream::match_pattern( bool flush_stream ) +{ + sync(); + + result_type result( true ); + + if( !m_pimpl->m_pattern_to_match_or_save.is_open() ) { + result = false; + *(result.p_message) << "Couldn't open pattern file for " + << ( m_pimpl->m_match_or_save ? "reading" : "writing"); + } + else { + if( m_pimpl->m_match_or_save ) { + for ( std::string::size_type i = 0; i < m_pimpl->m_synced_string.length(); ++i ) { + char c = m_pimpl->get_char(); + + result = !m_pimpl->m_pattern_to_match_or_save.fail() && + !m_pimpl->m_pattern_to_match_or_save.eof() && + (m_pimpl->m_synced_string[i] == c); + + if( !result ) { + std::string::size_type suffix_size = (std::min)( m_pimpl->m_synced_string.length() - i, + static_cast(5) ); + + // try to log area around the mismatch + *(result.p_message) << "Mismatch at position " << i << '\n' + << "..." << m_pimpl->m_synced_string.substr( i, suffix_size ) << "..." << '\n' + << "..." << c; + + std::string::size_type counter = suffix_size; + while( --counter ) { + char c = m_pimpl->get_char(); + + if( m_pimpl->m_pattern_to_match_or_save.fail() || + m_pimpl->m_pattern_to_match_or_save.eof() ) + break; + + *(result.p_message) << c; + } + + *(result.p_message) << "..."; + + // skip rest of the bytes. May help for further matching + m_pimpl->m_pattern_to_match_or_save.ignore( m_pimpl->m_synced_string.length() - i - suffix_size); + break; + } + } + } + else { + m_pimpl->m_pattern_to_match_or_save.write( m_pimpl->m_synced_string.c_str(), + static_cast( m_pimpl->m_synced_string.length() ) ); + m_pimpl->m_pattern_to_match_or_save.flush(); + } + } + + if( flush_stream ) + flush(); + + return result; +} + +//____________________________________________________________________________// + +void +output_test_stream::flush() +{ + m_pimpl->m_synced_string.erase(); + +#ifndef BOOST_NO_STRINGSTREAM + str( std::string() ); +#else + seekp( 0, std::ios::beg ); +#endif +} + +//____________________________________________________________________________// + +std::size_t +output_test_stream::length() +{ + sync(); + + return m_pimpl->m_synced_string.length(); +} + +//____________________________________________________________________________// + +void +output_test_stream::sync() +{ +#ifdef BOOST_NO_STRINGSTREAM + m_pimpl->m_synced_string.assign( str(), pcount() ); + freeze( false ); +#else + m_pimpl->m_synced_string = str(); +#endif +} + +//____________________________________________________________________________// + +} // namespace test_tools + +#undef LOG + +} // namespace boost + +// *************************************************************************** +// Revision History : +// +// $Log$ +// Revision 1.1 2005/01/22 19:22:12 rogeeff +// implementation moved into headers section to eliminate dependency of included/minimal component on src directory +// +// Revision 1.43 2005/01/19 06:40:05 vawjr +// deleted redundant \r in many \r\r\n sequences of the source. VC8.0 doesn't like them +// +// Revision 1.42 2005/01/18 08:30:08 rogeeff +// unit_test_log rework: +// eliminated need for ::instance() +// eliminated need for << end and ...END macro +// straitend interface between log and formatters +// change compiler like formatter name +// minimized unit_test_log interface and reworked to use explicit calls +// +// *************************************************************************** + +#endif // BOOST_TEST_TOOLS_IPP_012205GER diff --git a/include/boost/test/impl/unit_test_log.ipp b/include/boost/test/impl/unit_test_log.ipp new file mode 100644 index 00000000..43aff3fa --- /dev/null +++ b/include/boost/test/impl/unit_test_log.ipp @@ -0,0 +1,485 @@ +// (C) Copyright Gennadiy Rozental 2001-2004. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +// See http://www.boost.org/libs/test for the library home page. +// +// File : $RCSfile$ +// +// Version : $Revision$ +// +// Description : implemets Unit Test Log, Majority of implementation details +// are hidden in this file with use of pimpl idiom. +// *************************************************************************** + +#ifndef BOOST_UNIT_TEST_LOG_IPP_012205GER +#define BOOST_UNIT_TEST_LOG_IPP_012205GER + +// Boost.Test +#include +#include +#include +#include +#include +#include +#include + +// BOOST +#include +#include + +// STL +#include +#include + +# ifdef BOOST_NO_STDC_NAMESPACE +namespace std { using ::strcmp; } +# endif + +namespace boost { + +namespace unit_test { + +// ************************************************************************** // +// ************** entry_value_collector ************** // +// ************************************************************************** // + +namespace ut_detail { + +entry_value_collector +entry_value_collector::operator<<( const_string v ) +{ + unit_test_log.log_value( v ); + + m_last = false; + + entry_value_collector res; + return res; +} + +//____________________________________________________________________________// + +entry_value_collector +entry_value_collector::operator<<( checkpoint const& cp ) +{ + unit_test_log << cp; + + m_last = false; + + entry_value_collector res; + return res; +} + +//____________________________________________________________________________// + +entry_value_collector::~entry_value_collector() +{ + if( m_last ) + unit_test_log << end(); +} + +//____________________________________________________________________________// + +} // namespace ut_detail + +// ************************************************************************** // +// ************** unit_test_log ************** // +// ************************************************************************** // + +namespace { + +struct unit_test_log_impl { + // Constructor + unit_test_log_impl() : m_stream( &std::cout ) {} + + // log data + std::ostream* m_stream; + log_level m_threshold_level; + boost::scoped_ptr m_progress_display; + boost::scoped_ptr m_log_formatter; + + // entry data + bool m_entry_in_progress; + bool m_entry_has_value; + log_entry_data m_entry_data; + + // checkpoint data + log_checkpoint_data m_checkpoint_data; + + // helper functions + std::ostream& stream() { return *m_stream; } + void flush_entry() { stream() << std::endl; } + void clear_entry_data() + { + m_entry_data.clear(); + m_entry_in_progress = false; + m_entry_has_value = false; + } + void set_checkpoint( checkpoint const& cp ) + { + cp.m_message.assign_to( m_checkpoint_data.m_message ); + m_checkpoint_data.m_file = m_entry_data.m_file; + m_checkpoint_data.m_line = m_entry_data.m_line; + } + void clear_checkpoint() { m_checkpoint_data.clear(); } +}; + +unit_test_log_impl& s_impl() { static unit_test_log_impl the_inst; return the_inst; } + +} // local namespace + +//____________________________________________________________________________// + +unit_test_log_t::unit_test_log_t() +{ + s_impl().m_threshold_level = log_all_errors; + + s_impl().m_log_formatter.reset( new ut_detail::compiler_log_formatter ); + + s_impl().clear_entry_data(); + s_impl().clear_checkpoint(); +} + +//____________________________________________________________________________// + +unit_test_log_t& +unit_test_log_t::instance() +{ + static unit_test_log_t the_instance; + + return the_instance; +} + +//____________________________________________________________________________// + +void +unit_test_log_t::set_stream( std::ostream& str ) +{ + if( s_impl().m_entry_in_progress ) + return; + + s_impl().m_stream = &str; +} + +//____________________________________________________________________________// + +void +unit_test_log_t::set_threshold_level( log_level lev ) +{ + if( s_impl().m_entry_in_progress || lev == invalid_log_level ) + return; + + s_impl().m_threshold_level = lev; +} + +//____________________________________________________________________________// + +void +unit_test_log_t::set_threshold_level_by_name( const_string lev ) +{ + static fixed_mapping log_level_name( + "all" , log_successful_tests, + "success" , log_successful_tests, + "test_suite" , log_test_suites, + "messages" , log_messages, + "warnings" , log_warnings, + "all_errors" , log_all_errors, + "cpp_exceptions", log_cpp_exception_errors, + "system_errors" , log_system_errors, + "fatal_errors" , log_fatal_errors, + "progress" , log_progress_only, + "nothing" , log_nothing, + + invalid_log_level + ); + + if( s_impl().m_entry_in_progress ) + return; + + set_threshold_level( log_level_name[lev] ); +} + +//____________________________________________________________________________// + +void +unit_test_log_t::track_test_case_enter( test_case const& tc ) +{ + if( s_impl().m_threshold_level > log_test_suites ) + return; + + *this << begin(); + + s_impl().m_log_formatter->track_test_case_enter( s_impl().stream(), tc ); + s_impl().m_entry_has_value = true; + + *this << end(); +} + +//____________________________________________________________________________// + +void +unit_test_log_t::track_test_case_exit( test_case const& tc, long testing_time_in_mks ) +{ + if( s_impl().m_threshold_level > log_test_suites ) + return; + + s_impl().clear_checkpoint(); + + *this << begin(); + + s_impl().m_log_formatter->track_test_case_exit( s_impl().stream(), tc, testing_time_in_mks ); + s_impl().m_entry_has_value = true; + + *this << end(); +} + +//____________________________________________________________________________// + +unit_test_log_t& +unit_test_log_t::operator<<( begin const& ) +{ + if( s_impl().m_entry_in_progress ) + *this << end(); + + s_impl().m_entry_in_progress = true; + + return *this; +} + +//____________________________________________________________________________// + +unit_test_log_t& +unit_test_log_t::operator<<( end const& ) +{ + if( s_impl().m_entry_has_value ) { + s_impl().m_log_formatter->end_log_entry( s_impl().stream() ); + s_impl().flush_entry(); + } + + s_impl().clear_entry_data(); + + return *this; +} + +//____________________________________________________________________________// + +char +set_unix_slash( char in ) +{ + return in == '\\' ? '/' : in; +} + +unit_test_log_t& +unit_test_log_t::operator<<( file const& f ) +{ + if( s_impl().m_entry_in_progress ) { + f.m_file_name.assign_to( s_impl().m_entry_data.m_file ); + + // normalize file name + std::transform( s_impl().m_entry_data.m_file.begin(), s_impl().m_entry_data.m_file.end(), + s_impl().m_entry_data.m_file.begin(), + &set_unix_slash ); + } + + return *this; +} + +//____________________________________________________________________________// + +unit_test_log_t& +unit_test_log_t::operator<<( line const& l ) +{ + if( s_impl().m_entry_in_progress ) + s_impl().m_entry_data.m_line = l.m_line_num; + + return *this; +} + +//____________________________________________________________________________// + +unit_test_log_t& +unit_test_log_t::operator<<( checkpoint const& cp ) +{ + if( s_impl().m_entry_in_progress ) + s_impl().set_checkpoint( cp ); + + return *this; +} + +//____________________________________________________________________________// + +ut_detail::entry_value_collector +unit_test_log_t::operator()( log_level const& l ) +{ + if( !s_impl().m_entry_in_progress ) + *this << begin(); + + s_impl().m_entry_data.m_level = l; + + ut_detail::entry_value_collector res; + return res; +} + +//____________________________________________________________________________// + +void +unit_test_log_t::log_exception( log_level l, const_string what ) +{ + *this << begin(); + + if( l >= s_impl().m_threshold_level ) { + s_impl().m_log_formatter->log_exception( s_impl().stream(), s_impl().m_checkpoint_data, + unit_test_result::instance().test_case_name(), what ); + s_impl().m_entry_has_value = true; + } + + *this << end(); +} + +//____________________________________________________________________________// + +void +unit_test_log_t::log_progress() +{ + *this << begin(); + + if( s_impl().m_progress_display ) + ++(*s_impl().m_progress_display); + + *this << end(); +} + +//____________________________________________________________________________// + +void +unit_test_log_t::log_value( const_string value ) +{ + if( s_impl().m_entry_in_progress && s_impl().m_entry_data.m_level >= s_impl().m_threshold_level && !value.empty() ) { + if( !s_impl().m_entry_has_value ) { + switch( s_impl().m_entry_data.m_level ) { + case log_successful_tests: + s_impl().m_log_formatter->begin_log_entry( s_impl().stream(), s_impl().m_entry_data, + unit_test_log_formatter::BOOST_UTL_ET_INFO ); + break; + case log_messages: + s_impl().m_log_formatter->begin_log_entry( s_impl().stream(), s_impl().m_entry_data, + unit_test_log_formatter::BOOST_UTL_ET_MESSAGE ); + break; + case log_warnings: + s_impl().m_log_formatter->begin_log_entry( s_impl().stream(), s_impl().m_entry_data, + unit_test_log_formatter::BOOST_UTL_ET_WARNING ); + break; + case log_all_errors: + case log_cpp_exception_errors: + case log_system_errors: + s_impl().m_log_formatter->begin_log_entry( s_impl().stream(), s_impl().m_entry_data, + unit_test_log_formatter::BOOST_UTL_ET_ERROR ); + break; + case log_fatal_errors: + s_impl().m_log_formatter->begin_log_entry( s_impl().stream(), s_impl().m_entry_data, + unit_test_log_formatter::BOOST_UTL_ET_FATAL_ERROR ); + break; + case log_progress_only: + case log_nothing: + case log_test_suites: + case invalid_log_level: + return; + } + } + + s_impl().m_log_formatter->log_entry_value( s_impl().stream(), value ); + s_impl().m_entry_has_value = true; + } +} + +//____________________________________________________________________________// + +void +unit_test_log_t::start( bool log_build_info ) +{ + s_impl().m_log_formatter->start_log( s_impl().stream(), log_build_info ); +} + +//____________________________________________________________________________// + +void +unit_test_log_t::header( unit_test_counter test_cases_amount ) +{ + if( s_impl().m_threshold_level != log_nothing && test_cases_amount > 0 ) + s_impl().m_log_formatter->log_header( s_impl().stream(), test_cases_amount ); + + if( s_impl().m_threshold_level == log_progress_only ) + s_impl().m_progress_display.reset( + new boost::progress_display( test_cases_amount, s_impl().stream() ) ); + else + s_impl().m_progress_display.reset(); +} + +//____________________________________________________________________________// + +void +unit_test_log_t::finish( unit_test_counter test_cases_amount ) +{ + if( test_cases_amount == 1 ) + log_progress(); + + s_impl().m_log_formatter->finish_log( s_impl().stream() ); +} + +//____________________________________________________________________________// + +void +unit_test_log_t::set_format( const_string log_format_name ) +{ + if( s_impl().m_entry_in_progress ) + return; + + static fixed_mapping > log_format( + "HRF", HRF, + "XML", XML, + + HRF + ); + + if( log_format[log_format_name] == HRF ) + set_formatter( new ut_detail::compiler_log_formatter ); + else + set_formatter( new ut_detail::xml_log_formatter ); +} + +//____________________________________________________________________________// + +void +unit_test_log_t::set_formatter( unit_test_log_formatter* the_formatter ) +{ + s_impl().m_log_formatter.reset( the_formatter ); +} + +//____________________________________________________________________________// + +} // namespace unit_test + +} // namespace boost + +// *************************************************************************** +// Revision History : +// +// $Log$ +// Revision 1.1 2005/01/22 19:22:13 rogeeff +// implementation moved into headers section to eliminate dependency of included/minimal component on src directory +// +// Revision 1.27 2005/01/21 07:23:49 rogeeff +// added automatic test case run timing +// +// Revision 1.25 2005/01/18 08:30:08 rogeeff +// unit_test_log rework: +// eliminated need for ::instance() +// eliminated need for << end and ...END macro +// straitend interface between log and formatters +// change compiler like formatter name +// minimized unit_test_log interface and reworked to use explicit calls +// +// *************************************************************************** + +#endif // BOOST_UNIT_TEST_LOG_IPP_012205GER diff --git a/include/boost/test/impl/unit_test_main.ipp b/include/boost/test/impl/unit_test_main.ipp new file mode 100644 index 00000000..24359589 --- /dev/null +++ b/include/boost/test/impl/unit_test_main.ipp @@ -0,0 +1,130 @@ +// (C) Copyright Gennadiy Rozental 2001-2004. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +// See http://www.boost.org/libs/test for the library home page. +// +// File : $RCSfile$ +// +// Version : $Revision$ +// +// Description : main function implementation for Unit Test Framework +// *************************************************************************** + +#ifndef BOOST_UNIT_TEST_MAIN_IPP_012205GER +#define BOOST_UNIT_TEST_MAIN_IPP_012205GER + +// Boost.Test +#include // for unit_test framework +#include +#include +#include +#include + +// BOOST +#include + +// STL +#include +#include // for cout, cerr + +extern boost::unit_test::test_suite* init_unit_test_suite( int argc, char* argv[] ); // prototype for user's test suite init function + +// ************************************************************************** // +// ************** unit test main ************** // +// ************************************************************************** // + +int +main( int argc, char* argv[] ) +{ + using namespace boost::unit_test; + using namespace boost::unit_test::ut_detail; + + bool no_result_code; + bool print_build_info; + + // set the log level + unit_test_log.set_threshold_level_by_name( retrieve_framework_parameter( LOG_LEVEL, &argc, argv ) ); + + // set the log/report format + const_string output_format = retrieve_framework_parameter( OUTPUT_FORMAT, &argc, argv ); + + if( output_format.empty() ) { + unit_test_log.set_format( retrieve_framework_parameter( LOG_FORMAT, &argc, argv ) ); + unit_test_result::set_report_format( retrieve_framework_parameter( REPORT_FORMAT, &argc, argv ) ); + } + else { + unit_test_log.set_format( output_format ); + unit_test_result::set_report_format( output_format ); + } + + // set the result code and build info flags + no_result_code = retrieve_framework_parameter( NO_RESULT_CODE, &argc, argv ) == "no"; + print_build_info = retrieve_framework_parameter( BUILD_INFO, &argc, argv ) == "yes"; + + // set catch_system_error switch + unit_test_monitor::catch_system_errors( retrieve_framework_parameter( CATCH_SYS_ERRORS, &argc, argv ) != "no" ); + + // save report level for future reporting + const_string report_level = retrieve_framework_parameter( REPORT_LEVEL, &argc, argv ); + + // init master unit test suite + boost::scoped_ptr test( init_unit_test_suite( argc, argv ) ); + if( !test ) { + std::cerr << "*** Fail to initialize test suite" << std::endl; + return boost::exit_test_failure; + } + + // start testing + unit_test_log.start( print_build_info ); + unit_test_log.header( test->size() ); + test->run(); + unit_test_log.finish( test->size() ); + + // report results + unit_test_result::instance().report( report_level, std::cerr ); + + // return code + return no_result_code ? boost::exit_success : unit_test_result::instance().result_code(); +} + +// *************************************************************************** +// Revision History : +// +// $Log$ +// Revision 1.1 2005/01/22 19:22:13 rogeeff +// implementation moved into headers section to eliminate dependency of included/minimal component on src directory +// +// Revision 1.18 2005/01/19 16:34:07 vawjr +// Changed the \r\r\n back to \r\n on windows so we don't get errors when compiling +// on VC++8.0. I don't know why Microsoft thinks it's a good idea to call this an error, +// but they do. I also don't know why people insist on checking out files on Windows and +// copying them to a unix system to check them in (which will cause exactly this problem) +// +// Revision 1.17 2005/01/18 08:30:08 rogeeff +// unit_test_log rework: +// eliminated need for ::instance() +// eliminated need for << end and ...END macro +// straitend interface between log and formatters +// change compiler like formatter name +// minimized unit_test_log interface and reworked to use explicit calls +// +// Revision 1.16 2004/06/07 07:34:23 rogeeff +// detail namespace renamed +// +// Revision 1.15 2004/05/21 06:26:10 rogeeff +// licence update +// +// Revision 1.14 2004/05/11 11:05:04 rogeeff +// basic_cstring introduced and used everywhere +// class properties reworked +// namespace names shortened +// +// Revision 1.13 2003/12/01 00:42:37 rogeeff +// prerelease cleaning +// + +// *************************************************************************** + +#endif // BOOST_UNIT_TEST_MAIN_IPP_012205GER diff --git a/include/boost/test/impl/unit_test_monitor.ipp b/include/boost/test/impl/unit_test_monitor.ipp new file mode 100644 index 00000000..4230c12e --- /dev/null +++ b/include/boost/test/impl/unit_test_monitor.ipp @@ -0,0 +1,134 @@ +// (C) Copyright Gennadiy Rozental 2001-2004. +// (C) Copyright Ullrich Koethe 2001. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +// See http://www.boost.org/libs/test for the library home page. +// +// File : $RCSfile$ +// +// Version : $Revision$ +// +// Description : implements specific subclass of Executon Monitor used by Unit +// Test Framework to monitor test cases run. +// *************************************************************************** + +#ifndef BOOST_UNIT_TEST_MONITOR_IPP_012205GER +#define BOOST_UNIT_TEST_MONITOR_IPP_012205GER + +// Boost.Test +#include +#include +#include +#include +#include + +namespace boost { + +namespace unit_test { + +namespace ut_detail { + +// ************************************************************************** // +// ************** unit_test_monitor ************** // +// ************************************************************************** // + +bool unit_test_monitor::s_catch_system_errors = true; + +unit_test_monitor::error_level +unit_test_monitor::execute_and_translate( test_case* target_test_case, function_to_monitor f, int timeout ) +{ + m_test_case = target_test_case; + m_test_case_method = f; + + try { + execute( s_catch_system_errors, timeout ); + } + catch( execution_exception const& exex ) { + log_level loglevel = + exex.code() <= execution_exception::cpp_exception_error ? log_cpp_exception_errors : + (exex.code() <= execution_exception::timeout_error ? log_system_errors : + log_fatal_errors); + unit_test_log.log_exception( loglevel, exex.what() ); + + unit_test_result::instance().caught_exception(); + + // translate execution_exception::error_code to error_level + switch( exex.code() ) { + case execution_exception::no_error: return test_ok; + case execution_exception::user_error: return unexpected_exception; + case execution_exception::cpp_exception_error: return unexpected_exception; + case execution_exception::system_error: return os_exception; + case execution_exception::timeout_error: return os_timeout; + case execution_exception::user_fatal_error: + case execution_exception::system_fatal_error: return fatal_error; + default: return unexpected_exception; + } + } + + return test_ok; +} + +//____________________________________________________________________________// + +int +unit_test_monitor::function() +{ + try { + (m_test_case->*m_test_case_method)(); + } + catch( test_tools::tt_detail::test_tool_failed const& /*e*/ ) { // e not used; error already reported + // nothing to do + } + + return 0; +} + +//____________________________________________________________________________// + +} // namespace ut_detail + +} // namespace unit_test + +} // namespace boost + +// *************************************************************************** +// Revision History : +// +// $Log$ +// Revision 1.1 2005/01/22 19:22:13 rogeeff +// implementation moved into headers section to eliminate dependency of included/minimal component on src directory +// +// Revision 1.17 2005/01/19 16:34:07 vawjr +// Changed the \r\r\n back to \r\n on windows so we don't get errors when compiling +// on VC++8.0. I don't know why Microsoft thinks it's a good idea to call this an error, +// but they do. I also don't know why people insist on checking out files on Windows and +// copying them to a unix system to check them in (which will cause exactly this problem) +// +// Revision 1.16 2005/01/18 08:30:08 rogeeff +// unit_test_log rework: +// eliminated need for ::instance() +// eliminated need for << end and ...END macro +// straitend interface between log and formatters +// change compiler like formatter name +// minimized unit_test_log interface and reworked to use explicit calls +// +// Revision 1.15 2004/06/07 07:34:23 rogeeff +// detail namespace renamed +// +// Revision 1.14 2004/05/21 06:26:10 rogeeff +// licence update +// +// Revision 1.13 2004/05/11 11:05:04 rogeeff +// basic_cstring introduced and used everywhere +// class properties reworked +// namespace names shortened +// +// Revision 1.12 2003/12/01 00:42:37 rogeeff +// prerelease cleaning +// + +// *************************************************************************** + +#endif // BOOST_UNIT_TEST_MONITOR_IPP_012205GER diff --git a/include/boost/test/impl/unit_test_parameters.ipp b/include/boost/test/impl/unit_test_parameters.ipp new file mode 100644 index 00000000..daada181 --- /dev/null +++ b/include/boost/test/impl/unit_test_parameters.ipp @@ -0,0 +1,115 @@ +// (C) Copyright Gennadiy Rozental 2001-2004. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +// See http://www.boost.org/libs/test for the library home page. +// +// File : $RCSfile$ +// +// Version : $Revision$ +// +// Description : simple implementation for Unit Test Framework parameter +// handling routines. May be rewritten in future to use some kind of +// command-line arguments parsing facility and environment variable handling +// facility +// *************************************************************************** + +#ifndef BOOST_UNIT_TEST_PARAMETERS_IPP_012205GER +#define BOOST_UNIT_TEST_PARAMETERS_IPP_012205GER + +// Boost.Test +#include +#include +#include + +//BOOST +#include // for broken compiler workarounds +#include +#include + +# ifdef BOOST_NO_STDC_NAMESPACE +namespace std { using ::getenv; using ::strncmp; using ::strcmp; } +# endif + +namespace boost { + +namespace unit_test { + +const_string +retrieve_framework_parameter( const_string parameter_name, int* argc, char** argv ) +{ + static fixed_mapping parameter_2_cla_name_map( + LOG_LEVEL , "--log_level", + NO_RESULT_CODE , "--result_code", + REPORT_LEVEL , "--report_level", + TESTS_TO_RUN , "--run_test", + SAVE_TEST_PATTERN , "--save_pattern", + BUILD_INFO , "--build_info", + CATCH_SYS_ERRORS , "--catch_system_errors", + REPORT_FORMAT , "--report_format", + LOG_FORMAT , "--log_format", + OUTPUT_FORMAT , "--output_format", + + "" + ); + + // first try to find parameter among command line arguments if present + if( argc ) { + // locate corresponding cla name + const_string cla_name = parameter_2_cla_name_map[parameter_name]; + + if( !cla_name.is_empty() ) { + for( int i = 1; i < *argc; ++i ) { + if( cla_name == const_string( argv[i], cla_name.size() ) && + argv[i][cla_name.size()] == '=' ) { + const_string result = argv[i] + cla_name.size() + 1; + + for( int j = i; j < *argc; ++j ) { + argv[j] = argv[j+1]; + } + --(*argc); + + return result; + } + } + } + } + + return std::getenv( parameter_name.begin() ); +} + +//____________________________________________________________________________// + +} // namespace unit_test + +} // namespace boost + +// *************************************************************************** +// Revision History : +// +// $Log$ +// Revision 1.1 2005/01/22 19:22:13 rogeeff +// implementation moved into headers section to eliminate dependency of included/minimal component on src directory +// +// Revision 1.15 2004/05/21 06:26:10 rogeeff +// licence update +// +// Revision 1.14 2004/05/18 13:34:15 dgregor +// Needed to include to get std::getenv. +// +// Revision 1.13 2004/05/13 09:04:43 rogeeff +// added fixed_mapping +// +// Revision 1.12 2004/05/11 11:05:04 rogeeff +// basic_cstring introduced and used everywhere +// class properties reworked +// namespace names shortened +// +// Revision 1.11 2003/12/01 00:42:37 rogeeff +// prerelease cleaning +// + +// *************************************************************************** + +#endif // BOOST_UNIT_TEST_PARAMETERS_IPP_012205GER diff --git a/include/boost/test/impl/unit_test_result.ipp b/include/boost/test/impl/unit_test_result.ipp new file mode 100644 index 00000000..3606c21d --- /dev/null +++ b/include/boost/test/impl/unit_test_result.ipp @@ -0,0 +1,649 @@ +// (C) Copyright Gennadiy Rozental 2001-2004. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +// See http://www.boost.org/libs/test for the library home page. +// +// File : $RCSfile$ +// +// Version : $Revision$ +// +// Description : implements Unit Test Result reporting facility. Note that majority of +// implementation is hidden in this file using pimple idiom. +// *************************************************************************** + +#ifndef BOOST_UNIT_TEST_RESULT_IPP_012205GER +#define BOOST_UNIT_TEST_RESULT_IPP_012205GER + +// Boost.Test +#include +#include +#include +#include +#include +#include + +// BOOST +#include +#include +#include + +// STL +#include +#include +#include +#include +#include +#include +#include + +# ifdef BOOST_NO_STDC_NAMESPACE +namespace std { using ::log10; using ::strncmp; } +# endif + +namespace boost { + +namespace unit_test { + +typedef unit_test_result* unit_test_result_ptr; + +// ************************************************************************** // +// ************** report_formatter ************** // +// ************************************************************************** // + +class report_formatter { +public: + // Destructor + virtual ~report_formatter() {} + + virtual void start_result_report( std::ostream& where_to ) = 0; + virtual void finish_result_report( std::ostream& where_to ) = 0; + + virtual void start_test_case_report( std::ostream& where_to, std::size_t indent, + const_string test_case_name, bool case_suite, bool failed ) = 0; + + virtual void start_confirmation_report( std::ostream& where_to, + const_string test_case_name, bool case_suite, bool failed, + unit_test_counter num_failed, unit_test_counter num_expected ) = 0; + + virtual void finish_test_case_report( std::ostream& where_to, std::size_t indent, + const_string test_case_name, bool case_suite, bool aborted ) = 0; + + virtual void report_sub_test_cases_stat( std::ostream& where_to, std::size_t indent, + unit_test_counter num_passed, unit_test_counter num_failed ) = 0; + + virtual void report_assertions_stat( std::ostream& where_to, std::size_t indent, + unit_test_counter num_passed, + unit_test_counter num_failed, + unit_test_counter num_expected ) = 0; + +}; + +//____________________________________________________________________________// + +// ************************************************************************** // +// ************** hrf_report_formatter ************** // +// ************************************************************************** // + +class hrf_report_formatter : public report_formatter { + struct quote { + explicit quote( const_string str ) : m_str( str ) {} + + friend std::ostream& operator<<( std::ostream& os, quote const& q ) + { + return os << '"' << q.m_str << '"'; + } + + private: + const_string m_str; + }; +public: + void start_result_report( std::ostream& /* where_to */ ) {} + void finish_result_report( std::ostream& /* where_to */ ) {} + + void start_test_case_report( std::ostream& where_to, std::size_t indent, + const_string test_case_name, bool case_suite, bool failed ) + { + where_to << "\n" << std::setw( indent ) << "" << "Test " << cs_name( case_suite ) << " " << quote( test_case_name ) + << (failed ? " failed with:\n" : " passed with:\n"); + + } + + void start_confirmation_report( std::ostream& where_to, + const_string test_case_name, bool case_suite, bool failed, + unit_test_counter num_failed, unit_test_counter num_expected ) + { + if( failed ) { + if( num_failed == 0 ) { + where_to << "\n*** errors detected in test " << cs_name( case_suite ) << " " << quote( test_case_name ) + << "; see standard output for details\n"; + return; + } + + + where_to << "\n*** " << num_failed << ps_name( num_failed != 1, " failure" ) << " detected"; + + if( num_expected > 0 ) + where_to << " (" << num_expected << ps_name( num_expected != 1, " failure" ) << " expected)"; + + where_to << " in test " << cs_name( case_suite ) << " " << quote( test_case_name ) << "\n"; + } + else + where_to << "\n*** No errors detected\n"; + } + + void finish_test_case_report( std::ostream& where_to, std::size_t indent, + const_string test_case_name, bool case_suite, bool aborted ) + { + if( aborted ) + where_to << std::setw( indent ) << "" << "Test " << cs_name( case_suite ) << " " << quote( test_case_name ) + << " was aborted due to uncaught exception, user assert or system error\n"; + + where_to.flush(); + } + + void report_sub_test_cases_stat( std::ostream& where_to, std::size_t indent, + unit_test_counter num_passed, unit_test_counter num_failed ) + { + unit_test_counter total_test_cases = num_passed + num_failed; + std::size_t width = static_cast( std::log10( (float)(std::max)( num_passed, num_failed ) ) ) + 1; + + where_to << std::setw( indent ) << "" << std::setw( width ) << num_passed + << " test " << ps_name( num_passed != 1, "case" ) << " out of " << total_test_cases << " passed\n" + << std::setw( indent ) << "" << std::setw( width ) << num_failed + << " test " << ps_name( num_failed != 1, "case" ) << " out of " << total_test_cases << " failed\n"; + + } + + void report_assertions_stat( std::ostream& where_to, std::size_t indent, + unit_test_counter num_passed, unit_test_counter num_failed, unit_test_counter num_expected ) + { + unit_test_counter total_assertions = num_passed + num_failed; + std::size_t width = total_assertions > 0 + ? static_cast( std::log10( (float)(std::max)( num_passed, num_failed ) ) ) + 1 + : 1; + + where_to << std::setw( indent ) << "" << std::setw( width ) << num_passed + << ps_name( num_passed != 1, " assertion" ) << " out of " << total_assertions << " passed\n" + << std::setw( indent ) << "" << std::setw( width ) << num_failed + << ps_name( num_failed != 1, " assertion" ) << " out of " << total_assertions << " failed\n"; + + if( num_expected > 0 ) + where_to << std::setw( indent ) << "" << "while " << num_expected + << ps_name( num_expected != 1, " failure" ) << " expected\n"; + } + +private: + static std::string ps_name( bool p_s, std::string singular_form ) + { + return p_s ? singular_form.append( "s" ) : singular_form; + } + static std::string cs_name( bool c_s ) + { + return c_s ? "case" : "suite"; + } +}; + +// ************************************************************************** // +// ************** xml_report_formatter ************** // +// ************************************************************************** // + +class xml_report_formatter : public report_formatter { +public: + void start_result_report( std::ostream& where_to ) + { + where_to << "\n"; + } + void finish_result_report( std::ostream& where_to ) + { + where_to << "\n"; + } + + void start_test_case_report( std::ostream& where_to, std::size_t indent, + const_string test_case_name, bool case_suite, bool failed ) + { + where_to << std::setw( indent ) << "" + << "<" << ( case_suite ? "TestCase" : "TestSuite" ) + << " name" << attr_value() << test_case_name + << " result" << attr_value() << (failed ? "failed" : "passed") << ">\n"; + } + + void start_confirmation_report( std::ostream& where_to, + const_string test_case_name, bool case_suite, bool failed, + unit_test_counter num_failed, unit_test_counter num_expected ) + { + where_to << "<" << ( case_suite ? "TestCase" : "TestSuite" ) + << " name" << attr_value() << test_case_name + << " result" << attr_value() << (failed ? "failed" : "passed"); + + if( failed ) { + where_to << " num_of_failures" << attr_value() << num_failed + << " expected_failures" << attr_value() << num_expected; + } + + where_to << ">\n"; + } + + void finish_test_case_report( std::ostream& where_to, std::size_t indent, + const_string /* test_case_name */, bool case_suite, bool aborted ) + { + if( aborted ) { + where_to << std::setw( indent+2 ) << "" + << "<" << "aborted" + << " reason" << attr_value() << "due to uncaught exception, user assert or system error" + << "/>\n"; + } + + where_to << std::setw( indent ) << "" + << "\n"; + } + + void report_sub_test_cases_stat( std::ostream& where_to, std::size_t indent, + unit_test_counter num_passed, unit_test_counter num_failed ) + { + where_to << std::setw( indent+2 ) << "" + << "\n"; + } + + void report_assertions_stat( std::ostream& where_to, std::size_t indent, + unit_test_counter num_passed, + unit_test_counter num_failed, + unit_test_counter num_expected ) + { + where_to << std::setw( indent+2 ) << "" + << "\n"; + } +}; + +// ************************************************************************** // +// ************** unit_test_result ************** // +// ************************************************************************** // + +struct unit_test_result::Impl { + unit_test_result_ptr m_parent; + std::list m_children; + unit_test_counter m_assertions_passed; + unit_test_counter m_assertions_failed; + unit_test_counter m_expected_failures; + unit_test_counter m_test_cases_passed; + unit_test_counter m_test_cases_failed; + bool m_exception_caught; + std::string m_test_case_name; + + static boost::scoped_ptr m_head; + static unit_test_result_ptr m_curr; + static boost::scoped_ptr m_report_formatter; + + bool has_failed() + { + return m_test_cases_failed != 0 || m_assertions_failed != m_expected_failures || m_exception_caught; + } + int result_code() + { + return has_failed() + ? ( (m_assertions_failed != 0) + ? boost::exit_test_failure + : boost::exit_exception_failure ) + : boost::exit_success; + } +}; + +boost::scoped_ptr unit_test_result::Impl::m_head; +unit_test_result_ptr unit_test_result::Impl::m_curr = unit_test_result_ptr(); +boost::scoped_ptr unit_test_result::Impl::m_report_formatter( new hrf_report_formatter ); + +//____________________________________________________________________________// + +unit_test_result::unit_test_result( unit_test_result_ptr parent, const_string test_case_name, unit_test_counter exp_fail ) +: m_pimpl( new Impl ) +{ + m_pimpl->m_parent = parent; + test_case_name.assign_to( m_pimpl->m_test_case_name ); + + m_pimpl->m_assertions_passed = 0; + m_pimpl->m_assertions_failed = 0; + m_pimpl->m_expected_failures = exp_fail; + m_pimpl->m_test_cases_passed = 0; + m_pimpl->m_test_cases_failed = 0; + m_pimpl->m_exception_caught = false; + +} + +//____________________________________________________________________________// + +static void safe_delete( unit_test_result_ptr ptr ) { boost::checked_delete( ptr ); } + +unit_test_result::~unit_test_result() +{ + std::list::iterator beg = m_pimpl->m_children.begin(); + std::list::iterator end = m_pimpl->m_children.end(); + + std::for_each( beg, end, &safe_delete ); +} + +//____________________________________________________________________________// + +unit_test_result& +unit_test_result::instance() +{ + assert( !!Impl::m_head ); + + return Impl::m_curr ? *Impl::m_curr : *Impl::m_head; +} + +//____________________________________________________________________________// + +void +unit_test_result::test_case_start( const_string name, unit_test_counter expected_failures ) +{ + unit_test_result_ptr new_test_case_result_inst = new unit_test_result( Impl::m_curr, name, expected_failures ); + + if( Impl::m_curr ) + Impl::m_curr->m_pimpl->m_children.push_back( new_test_case_result_inst ); + else + Impl::m_head.reset( new_test_case_result_inst ); + + Impl::m_curr = new_test_case_result_inst; +} + +//____________________________________________________________________________// + +void +unit_test_result::test_case_end() +{ + assert( !!Impl::m_curr ); + + Impl* curr_impl = Impl::m_curr->m_pimpl.get(); + unit_test_result_ptr parent = curr_impl->m_parent; + + if( parent ) { + // accumulate results + parent->m_pimpl->m_assertions_passed += curr_impl->m_assertions_passed; + parent->m_pimpl->m_assertions_failed += curr_impl->m_assertions_failed; + parent->m_pimpl->m_test_cases_passed += curr_impl->m_test_cases_passed; + parent->m_pimpl->m_test_cases_failed += curr_impl->m_test_cases_failed; + + // for test_cases (vs. test_suite) //!! need better identification + if( curr_impl->m_test_cases_passed == 0 && curr_impl->m_test_cases_failed == 0 ) { + if( curr_impl->has_failed() ) + parent->m_pimpl->m_test_cases_failed++; + else + parent->m_pimpl->m_test_cases_passed++; + } + + } + + Impl::m_curr = parent; +} + +//____________________________________________________________________________// + +struct report_format_name_map : std::map +{ + report_format_name_map() { + } +}; + +void +unit_test_result::set_report_format( const_string report_format_name ) +{ + static fixed_mapping > report_format( + "HRF", HRF, + "XML", XML, + + HRF + ); + + if( report_format[report_format_name] == HRF ) + Impl::m_report_formatter.reset( new hrf_report_formatter ); + else + Impl::m_report_formatter.reset( new xml_report_formatter ); +} + +//____________________________________________________________________________// + +void +unit_test_result::increase_expected_failures( unit_test_counter amount ) +{ + m_pimpl->m_expected_failures += amount; + + if( m_pimpl->m_parent ) + m_pimpl->m_parent->increase_expected_failures( amount ); +} + +//____________________________________________________________________________// + +void +unit_test_result::inc_failed_assertions() +{ + m_pimpl->m_assertions_failed++; + + if( m_pimpl->m_assertions_failed == 1 ) + first_failed_assertion(); +} + +//____________________________________________________________________________// + +void +unit_test_result::inc_passed_assertions() +{ + m_pimpl->m_assertions_passed++; +} + +//____________________________________________________________________________// + +void +unit_test_result::caught_exception() +{ + m_pimpl->m_exception_caught = true; +} + +//____________________________________________________________________________// + +const_string +unit_test_result::test_case_name() +{ + return m_pimpl->m_test_case_name; +} + +//____________________________________________________________________________// + +void +unit_test_result::reset_current_result_set() +{ + static unit_test_result_ptr backup = unit_test_result_ptr(); + static boost::scoped_ptr temporary_substitute; + + assert( !!Impl::m_curr ); + + if( backup ) { + Impl::m_curr = backup; + backup = unit_test_result_ptr(); + temporary_substitute.reset(); + } + else { + backup = Impl::m_curr; + Impl::m_curr = new unit_test_result( NULL, Impl::m_curr->test_case_name(), 0 ); + temporary_substitute.reset( Impl::m_curr ); + } +} + +//____________________________________________________________________________// + +void +unit_test_result::failures_details( unit_test_counter& num_of_failures, bool& exception_caught ) +{ + num_of_failures = m_pimpl->m_assertions_failed; + exception_caught = m_pimpl->m_exception_caught; +} + +//____________________________________________________________________________// + +void +unit_test_result::report( const_string reportlevel, std::ostream& where_to_ ) +{ + static int const map_size = sizeof(report_level_names)/sizeof(const_string); + + report_level rl = UNDEF_REPORT; + if( reportlevel.empty() ) + rl = CONFIRMATION_REPORT; + else { + for( int i = 0; i < map_size; i++ ) { + if( reportlevel == report_level_names[i] ) { + rl = (report_level)i; + break; + } + } + } + + switch( rl ) { + case CONFIRMATION_REPORT: + confirmation_report( where_to_ ); + break; + case SHORT_REPORT: + case DETAILED_REPORT: + m_pimpl->m_report_formatter->start_result_report( where_to_ ); + report_result( where_to_, 0, rl == DETAILED_REPORT ); + m_pimpl->m_report_formatter->finish_result_report( where_to_ ); + break; + case NO_REPORT: + break; + default: + where_to_ << "*** Unrecognized report level" << std::endl; + break; + } +} + +//____________________________________________________________________________// + +void +unit_test_result::confirmation_report( std::ostream& where_to ) +{ + assert( !!this ); + + m_pimpl->m_report_formatter->start_result_report( where_to ); + + m_pimpl->m_report_formatter->start_confirmation_report( where_to, + m_pimpl->m_test_case_name, m_pimpl->m_children.empty(), + m_pimpl->m_test_cases_failed != 0 || m_pimpl->has_failed(), + m_pimpl->m_assertions_failed, m_pimpl->m_expected_failures ); + + m_pimpl->m_report_formatter->finish_test_case_report( where_to, 0, + m_pimpl->m_test_case_name, m_pimpl->m_children.empty(), + m_pimpl->m_exception_caught ); + + m_pimpl->m_report_formatter->finish_result_report( where_to ); +} + +//____________________________________________________________________________// + +void +unit_test_result::report_result( std::ostream& where_to, std::size_t indent, bool detailed ) +{ + assert( !!this ); + + m_pimpl->m_report_formatter->start_test_case_report( where_to, indent, + m_pimpl->m_test_case_name, m_pimpl->m_children.empty(), + m_pimpl->m_test_cases_failed != 0 || m_pimpl->has_failed() ); + + if( m_pimpl->m_test_cases_passed + m_pimpl->m_test_cases_failed > 1 ) + m_pimpl->m_report_formatter->report_sub_test_cases_stat( where_to, indent, + m_pimpl->m_test_cases_passed, m_pimpl->m_test_cases_failed ); + + m_pimpl->m_report_formatter->report_assertions_stat( where_to, indent, + m_pimpl->m_assertions_passed, + m_pimpl->m_assertions_failed, + m_pimpl->m_expected_failures ); + + if( detailed ) { + std::list::iterator it = m_pimpl->m_children.begin(); + std::list::iterator end = m_pimpl->m_children.end(); + + while( it != end ) { + unit_test_result_ptr next = *(it++); + next->report_result( where_to, indent+2, true ); + } + } + + m_pimpl->m_report_formatter->finish_test_case_report( where_to, indent, + m_pimpl->m_test_case_name, m_pimpl->m_children.empty(), + m_pimpl->m_exception_caught ); +} + +//____________________________________________________________________________// + +int +unit_test_result::result_code() const +{ + return m_pimpl->result_code(); +} + +//____________________________________________________________________________// + +bool +unit_test_result::has_passed() const +{ + return !m_pimpl->has_failed(); +} + +//____________________________________________________________________________// + +} // namespace unit_test + +} // namespace boost + +// *************************************************************************** +// Revision History : +// +// $Log$ +// Revision 1.1 2005/01/22 19:22:13 rogeeff +// implementation moved into headers section to eliminate dependency of included/minimal component on src directory +// +// Revision 1.32 2005/01/21 07:26:41 rogeeff +// xml printing helpers reworked to employ generic custom manipulators +// +// Revision 1.31 2004/09/17 12:34:13 rogeeff +// XML typo +// +// Revision 1.30 2004/08/10 04:02:18 rogeeff +// first tru64cxx65 fix +// +// Revision 1.29 2004/07/19 12:10:56 rogeeff +// added proper encoded of XML PCDATA +// min->max bug fix +// +// Revision 1.28 2004/06/29 04:33:20 rogeeff +// use std::min +// +// Revision 1.27 2004/06/23 04:49:48 eric_niebler +// remove std_min and std_max, update minmax coding guidelines +// +// Revision 1.26 2004/05/21 06:26:10 rogeeff +// licence update +// +// Revision 1.25 2004/05/13 09:04:44 rogeeff +// added fixed_mapping +// +// Revision 1.24 2004/05/11 11:05:04 rogeeff +// basic_cstring introduced and used everywhere +// class properties reworked +// namespace names shortened +// +// Revision 1.23 2004/02/26 18:27:02 eric_niebler +// remove minmax hack from win32.hpp and fix all places that could be affected by the minmax macros +// +// Revision 1.22 2003/12/01 00:42:37 rogeeff +// prerelease cleaning +// + +// *************************************************************************** + +#endif // BOOST_UNIT_TEST_RESULT_IPP_012205GER diff --git a/include/boost/test/impl/unit_test_suite.ipp b/include/boost/test/impl/unit_test_suite.ipp new file mode 100644 index 00000000..76b8af6e --- /dev/null +++ b/include/boost/test/impl/unit_test_suite.ipp @@ -0,0 +1,339 @@ +// (C) Copyright Gennadiy Rozental 2001-2004. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +// See http://www.boost.org/libs/test for the library home page. +// +// File : $RCSfile$ +// +// Version : $Revision$ +// +// Description : privide core implementation for Unit Test Framework. +// Extensions could be provided in separate files +// *************************************************************************** + +#ifndef BOOST_UNIT_TEST_MAIN_IPP_012205GER +#define BOOST_UNIT_TEST_MAIN_IPP_012205GER + +// Boost.Test +#include +#include +#include +#include + +// BOOST +#include +#include + +// STL +#include +#include + +#include + +namespace boost { + +namespace unit_test { + +// ************************************************************************** // +// ************** test_case_scope_tracker ************** // +// ************************************************************************** // + +struct test_case_scope_tracker { + explicit test_case_scope_tracker( test_case const& tc ) + : m_tc( tc ) + { + unit_test_log.track_test_case_enter( m_tc ); + } + ~test_case_scope_tracker() + { + unit_test_log.track_test_case_exit( m_tc, (long)(m_timer.elapsed() * 1e6) ); + } + +private: + test_case const& m_tc; + boost::timer m_timer; +}; + +// ************************************************************************** // +// ************** test_case ************** // +// ************************************************************************** // + +ut_detail::unit_test_monitor the_monitor; + +typedef unit_test_result const* unit_test_result_cptr; + +struct test_case::Impl { + Impl( bool monitor_run_ ) : m_monitor_run( monitor_run_ ), m_results_set( unit_test_result_cptr() ) {} + + bool m_monitor_run; // true - unit_test_monitor will be user to monitor running + // of implementation function + std::list m_dependencies_list; // list of test cases this test case depends on. We won't run it until they pass + unit_test_result_cptr m_results_set; // results set instance reference for this test case + + static bool s_abort_testing; // used to flag critical error and try gracefully stop testing + + bool check_dependencies(); +}; + +bool test_case::Impl::s_abort_testing = false; + +//____________________________________________________________________________// + + +inline bool +test_case::Impl::check_dependencies() +{ + return std::find_if( m_dependencies_list.begin(), + m_dependencies_list.end(), + std::not1( boost::mem_fn( &test_case::has_passed ) ) ) == m_dependencies_list.end(); +} + +//____________________________________________________________________________// + +test_case::test_case( const_string name_, bool type, unit_test_counter stages_amount_, bool monitor_run_ ) +: p_timeout( 0 ), p_expected_failures( 0 ), p_type( type ), + p_name( std::string( name_.begin(), name_.end() ) ), + p_compound_stage( false ), p_stages_amount( stages_amount_ ), + m_pimpl( new Impl( monitor_run_ ) ) +{ +} + +//____________________________________________________________________________// + +unit_test_counter +test_case::size() const +{ + return 1; +} + +//____________________________________________________________________________// + +void +test_case::depends_on( test_case const* rhs ) +{ + m_pimpl->m_dependencies_list.push_back( rhs ); +} + +//____________________________________________________________________________// + +bool +test_case::has_passed() const +{ + return m_pimpl->m_results_set != unit_test_result_cptr() && m_pimpl->m_results_set->has_passed(); +} + +//____________________________________________________________________________// + +void +test_case::run() +{ + using ut_detail::unit_test_monitor; + + test_case_scope_tracker scope_tracker( *this ); + + // 0. Check if we allowed to run this test case + if( !m_pimpl->check_dependencies() ) + return; + + m_pimpl->s_abort_testing = false; + + // 1. Init test results + unit_test_result_tracker result_tracker( p_name.get(), p_expected_failures ); + m_pimpl->m_results_set = &unit_test_result::instance(); + + // 2. Initialize test case + if( m_pimpl->m_monitor_run ) { + error_level_type setup_result = + the_monitor.execute_and_translate( this, &test_case::do_init, p_timeout ); + + if( setup_result != unit_test_monitor::test_ok ) { + m_pimpl->s_abort_testing = unit_test_monitor::is_critical_error( setup_result ); + + BOOST_UT_LOG_ENTRY( log_fatal_errors ) << "Test case setup has failed"; + + return; + } + } + else { + do_init(); + } + + // 3. Run test case (all stages) + for( unit_test_counter i=0; i != p_stages_amount; ++i ) { + p_compound_stage.value = false; // could be set by do_run to mark compound stage; + // than no need to report progress here + + if( m_pimpl->m_monitor_run ) { + error_level_type run_result = + the_monitor.execute_and_translate( this, &test_case::do_run, p_timeout ); + + if( unit_test_monitor::is_critical_error( run_result ) ) { + m_pimpl->s_abort_testing = true; + + BOOST_UT_LOG_ENTRY( log_fatal_errors ) << "Testing aborted"; + } + + if( m_pimpl->s_abort_testing ) + return; + } + else { + do_run(); + } + + if( p_stages_amount != 1 && !p_compound_stage ) // compound test + unit_test_log.log_progress(); + } + + // 3. Finalize test case + if( m_pimpl->m_monitor_run ) { + error_level_type teardown_result = + the_monitor.execute_and_translate( this, &test_case::do_destroy, p_timeout ); + + m_pimpl->s_abort_testing = unit_test_monitor::is_critical_error( teardown_result ); + } + else { + do_destroy(); + } +} + +//____________________________________________________________________________// + +// ************************************************************************** // +// ************** test_suite ************** // +// ************************************************************************** // + +struct test_suite::Impl { + std::list m_test_cases; + std::list::iterator m_curr_test_case; + unit_test_counter m_cumulative_size; +}; + +//____________________________________________________________________________// + +test_suite::test_suite( const_string name ) +: test_case( name, false, 0, false ), m_pimpl( new Impl ) +{ + m_pimpl->m_cumulative_size = 0; +} + +//____________________________________________________________________________// + +static void safe_delete_test_case( test_case* ptr ) { boost::checked_delete( ptr ); } + +test_suite::~test_suite() +{ + std::for_each( m_pimpl->m_test_cases.begin(), m_pimpl->m_test_cases.end(), &safe_delete_test_case ); +} + +//____________________________________________________________________________// + +void +test_suite::add( test_case* tc, unit_test_counter exp_fail, int timeout ) +{ + if( exp_fail != 0 ) { + tc->p_expected_failures.value = exp_fail; + } + + p_expected_failures.value += tc->p_expected_failures; + + if( timeout != 0 ) + tc->p_timeout.value = timeout; + + m_pimpl->m_test_cases.push_back( tc ); + m_pimpl->m_cumulative_size += tc->size(); + + p_stages_amount.value = p_stages_amount + 1; +} + +//____________________________________________________________________________// + +unit_test_counter +test_suite::size() const +{ + return m_pimpl->m_cumulative_size; +} + +//____________________________________________________________________________// + +void +test_suite::do_init() +{ + m_pimpl->m_curr_test_case = m_pimpl->m_test_cases.begin(); +} + +//____________________________________________________________________________// + +void +test_suite::do_run() +{ + if( (*m_pimpl->m_curr_test_case)->size() > 1 ) + p_compound_stage.value = true; + (*m_pimpl->m_curr_test_case)->run(); + ++m_pimpl->m_curr_test_case; +} + +//____________________________________________________________________________// + +// ************************************************************************** // +// ************** object generators ************** // +// ************************************************************************** // + +namespace ut_detail { + +std::string const& +normalize_test_case_name( std::string& name_ ) +{ + if( name_[0] == '&' ) + name_.erase( 0, 1 ); + + return name_; +} + +} // namespace ut_detail + +} // namespace unit_test + +} // namespace boost + +#include + +// *************************************************************************** +// Revision History : +// +// $Log$ +// Revision 1.1 2005/01/22 19:22:13 rogeeff +// implementation moved into headers section to eliminate dependency of included/minimal component on src directory +// +// Revision 1.19 2005/01/21 07:26:41 rogeeff +// xml printing helpers reworked to employ generic custom manipulators +// +// Revision 1.17 2005/01/18 08:30:08 rogeeff +// unit_test_log rework: +// eliminated need for ::instance() +// eliminated need for << end and ...END macro +// straitend interface between log and formatters +// change compiler like formatter name +// minimized unit_test_log interface and reworked to use explicit calls +// +// Revision 1.16 2004/06/07 07:34:23 rogeeff +// detail namespace renamed +// +// Revision 1.15 2004/05/21 06:26:10 rogeeff +// licence update +// +// Revision 1.14 2004/05/18 13:26:47 dgregor +// unit_test_suite.cpp: Try to work around an Intel 7.1 bug with conversions in a base class. +// +// Revision 1.13 2004/05/11 11:05:04 rogeeff +// basic_cstring introduced and used everywhere +// class properties reworked +// namespace names shortened +// +// Revision 1.12 2003/12/01 00:42:37 rogeeff +// prerelease cleaning +// +// *************************************************************************** + +#endif // BOOST_UNIT_TEST_MAIN_IPP_012205GER diff --git a/include/boost/test/included/prg_exec_monitor.hpp b/include/boost/test/included/prg_exec_monitor.hpp index c4a5ed38..6b69b0f3 100644 --- a/include/boost/test/included/prg_exec_monitor.hpp +++ b/include/boost/test/included/prg_exec_monitor.hpp @@ -15,14 +15,17 @@ #ifndef BOOST_INCLUDED_PRG_EXEC_MONITOR_HPP_071894GER #define BOOST_INCLUDED_PRG_EXEC_MONITOR_HPP_071894GER -#include +#include -#include +#include // *************************************************************************** // Revision History : // // $Log$ +// Revision 1.8 2005/01/22 19:22:13 rogeeff +// implementation moved into headers section to eliminate dependency of included/minimal component on src directory +// // Revision 1.7 2004/07/19 12:30:49 rogeeff // guard rename // diff --git a/include/boost/test/included/test_exec_monitor.hpp b/include/boost/test/included/test_exec_monitor.hpp index 376268e1..a708fd02 100644 --- a/include/boost/test/included/test_exec_monitor.hpp +++ b/include/boost/test/included/test_exec_monitor.hpp @@ -16,23 +16,26 @@ #define BOOST_INCLUDED_TEST_EXEC_MONITOR_HPP_071894GER #include //!! for borland workaround -#include +#include -#include +#include -#include -#include -#include -#include -#include -#include +#include +#include +#include +#include +#include +#include -#include +#include // *************************************************************************** // Revision History : // // $Log$ +// Revision 1.10 2005/01/22 19:22:13 rogeeff +// implementation moved into headers section to eliminate dependency of included/minimal component on src directory +// // Revision 1.9 2004/07/19 12:30:49 rogeeff // guard rename // diff --git a/include/boost/test/included/unit_test_framework.hpp b/include/boost/test/included/unit_test_framework.hpp index b0ae7be1..4c0d85d8 100644 --- a/include/boost/test/included/unit_test_framework.hpp +++ b/include/boost/test/included/unit_test_framework.hpp @@ -15,23 +15,26 @@ #ifndef BOOST_INCLUDED_UNIT_TEST_FRAMEWORK_HPP_071894GER #define BOOST_INCLUDED_UNIT_TEST_FRAMEWORK_HPP_071894GER -#include +#include -#include +#include -#include -#include -#include -#include -#include -#include +#include +#include +#include +#include +#include +#include -#include +#include // *************************************************************************** // Revision History : // // $Log$ +// Revision 1.10 2005/01/22 19:22:13 rogeeff +// implementation moved into headers section to eliminate dependency of included/minimal component on src directory +// // Revision 1.9 2004/07/19 12:30:49 rogeeff // guard rename // diff --git a/include/boost/test/minimal.hpp b/include/boost/test/minimal.hpp index 3233106c..00f6810c 100644 --- a/include/boost/test/minimal.hpp +++ b/include/boost/test/minimal.hpp @@ -41,8 +41,8 @@ //____________________________________________________________________________// // Boost.Test -#include -#include +#include +#include // BOOST #include // for exit codes @@ -148,6 +148,9 @@ int main( int argc, char* argv[] ) // Revision History : // // $Log$ +// Revision 1.15 2005/01/22 19:22:12 rogeeff +// implementation moved into headers section to eliminate dependency of included/minimal component on src directory +// // Revision 1.14 2004/07/19 12:14:34 rogeeff // guard rename // diff --git a/include/boost/test/test_tools.hpp b/include/boost/test/test_tools.hpp index 6c0f7db2..9a37ef3c 100644 --- a/include/boost/test/test_tools.hpp +++ b/include/boost/test/test_tools.hpp @@ -19,8 +19,8 @@ // Boost.Test #include #include -#include -#include +#include +#include // BOOST #include // for boost::exit_success; @@ -576,6 +576,9 @@ namespace test_toolbox = test_tools; // Revision History : // // $Log$ +// Revision 1.47 2005/01/22 19:22:12 rogeeff +// implementation moved into headers section to eliminate dependency of included/minimal component on src directory +// // Revision 1.46 2005/01/18 08:26:01 rogeeff // unit_test_log rework: // eliminated need for ::instance() diff --git a/include/boost/test/unit_test_suite.hpp b/include/boost/test/unit_test_suite.hpp index 55cb5c55..64138dd2 100644 --- a/include/boost/test/unit_test_suite.hpp +++ b/include/boost/test/unit_test_suite.hpp @@ -20,7 +20,7 @@ // Boost.Test #include #include -#include +#include // BOOST #include @@ -324,6 +324,9 @@ create_test_case( void (UserTestCase::*fct_)( ParamType ), std::string name_, bo // Revision History : // // $Log$ +// Revision 1.25 2005/01/22 19:22:12 rogeeff +// implementation moved into headers section to eliminate dependency of included/minimal component on src directory +// // Revision 1.24 2004/07/19 12:16:41 rogeeff // guard rename // diff --git a/include/boost/test/utils/basic_cstring/basic_cstring.hpp b/include/boost/test/utils/basic_cstring/basic_cstring.hpp index 139d2d02..1e96fdc2 100644 --- a/include/boost/test/utils/basic_cstring/basic_cstring.hpp +++ b/include/boost/test/utils/basic_cstring/basic_cstring.hpp @@ -17,8 +17,8 @@ #define BASIC_CSTRING_HPP_071894GER // Boost.Test -#include -#include +#include +#include // STL #include @@ -714,6 +714,9 @@ last_char( basic_cstring source ) // Revision History : // // $Log$ +// Revision 1.2 2005/01/22 19:22:13 rogeeff +// implementation moved into headers section to eliminate dependency of included/minimal component on src directory +// // Revision 1.1 2005/01/22 18:21:40 rogeeff // moved sharable staff into utils // diff --git a/include/boost/test/utils/basic_cstring/compare.hpp b/include/boost/test/utils/basic_cstring/compare.hpp index 46991425..13ae2068 100644 --- a/include/boost/test/utils/basic_cstring/compare.hpp +++ b/include/boost/test/utils/basic_cstring/compare.hpp @@ -16,7 +16,7 @@ #define BASIC_CSTRING_COMPARE_HPP_071894GER // Boost.Test -#include +#include // STL #include @@ -107,6 +107,9 @@ operator <( basic_cstring x, basic_cstring y ) // Revision History : // // $Log$ +// Revision 1.2 2005/01/22 19:22:13 rogeeff +// implementation moved into headers section to eliminate dependency of included/minimal component on src directory +// // Revision 1.1 2005/01/22 18:21:40 rogeeff // moved sharable staff into utils // diff --git a/include/boost/test/utils/basic_cstring/io.hpp b/include/boost/test/utils/basic_cstring/io.hpp index 2c02c55a..1b95a1cc 100644 --- a/include/boost/test/utils/basic_cstring/io.hpp +++ b/include/boost/test/utils/basic_cstring/io.hpp @@ -16,7 +16,7 @@ #define BASIC_CSTRING_IO_HPP_071894GER // Boost.Test -#include +#include // STL #include @@ -68,6 +68,9 @@ operator<<( std::basic_ostream& os, basic_cstring const& str // Revision History : // // $Log$ +// Revision 1.2 2005/01/22 19:22:13 rogeeff +// implementation moved into headers section to eliminate dependency of included/minimal component on src directory +// // Revision 1.1 2005/01/22 18:21:40 rogeeff // moved sharable staff into utils // diff --git a/include/boost/test/utils/class_properties.hpp b/include/boost/test/utils/class_properties.hpp index 995dfae0..60de9f4d 100644 --- a/include/boost/test/utils/class_properties.hpp +++ b/include/boost/test/utils/class_properties.hpp @@ -20,8 +20,9 @@ #include // BOOST -#include +#if !BOOST_WORKAROUND(__IBMCPP__, BOOST_TESTED_AT(600)) #include +#endif #include #include #include @@ -30,16 +31,6 @@ // STL #include -#if BOOST_WORKAROUND(__BORLANDC__, <= 0x570) || \ - BOOST_WORKAROUND( __COMO__, <= 0x433 ) || \ - BOOST_WORKAROUND( __INTEL_COMPILER, <= 800 ) || \ - BOOST_WORKAROUND(__GNUC__, < 3) || \ - defined(__sgi) && _COMPILER_VERSION <= 730 || \ - BOOST_WORKAROUND(__IBMCPP__, BOOST_TESTED_AT(600)) || \ - defined(__DECCXX) -#define BOOST_TEST_NO_PROTECTED_USING -#endif - namespace boost { namespace unit_test { @@ -223,6 +214,9 @@ public: // Revision History : // // $Log$ +// Revision 1.2 2005/01/22 19:22:13 rogeeff +// implementation moved into headers section to eliminate dependency of included/minimal component on src directory +// // Revision 1.1 2005/01/22 18:21:39 rogeeff // moved sharable staff into utils // diff --git a/include/boost/test/utils/iterator/ifstream_line_iterator.hpp b/include/boost/test/utils/iterator/ifstream_line_iterator.hpp index 85b453f7..3b8d6676 100644 --- a/include/boost/test/utils/iterator/ifstream_line_iterator.hpp +++ b/include/boost/test/utils/iterator/ifstream_line_iterator.hpp @@ -16,7 +16,7 @@ #define BOOST_IFSTREAM_LINE_ITERATOR_HPP_071894GER // Boost -#include +#include // STL #include @@ -87,6 +87,9 @@ typedef basic_ifstream_line_iterator wifstream_line_iterator; // Revision History : // // $Log$ +// Revision 1.2 2005/01/22 19:22:13 rogeeff +// implementation moved into headers section to eliminate dependency of included/minimal component on src directory +// // Revision 1.1 2005/01/22 18:21:40 rogeeff // moved sharable staff into utils // diff --git a/include/boost/test/utils/iterator/istream_line_iterator.hpp b/include/boost/test/utils/iterator/istream_line_iterator.hpp index e735ab72..bcef8502 100644 --- a/include/boost/test/utils/iterator/istream_line_iterator.hpp +++ b/include/boost/test/utils/iterator/istream_line_iterator.hpp @@ -16,8 +16,8 @@ #define BOOST_ISTREAM_LINE_ITERATOR_HPP_071894GER // Boost -#include -#include +#include +#include // STL #include @@ -89,6 +89,9 @@ typedef basic_istream_line_iterator wistream_line_iterator; // Revision History : // // $Log$ +// Revision 1.2 2005/01/22 19:22:14 rogeeff +// implementation moved into headers section to eliminate dependency of included/minimal component on src directory +// // Revision 1.1 2005/01/22 18:21:40 rogeeff // moved sharable staff into utils // diff --git a/include/boost/test/utils/iterator/token_iterator.hpp b/include/boost/test/utils/iterator/token_iterator.hpp index a3a003a1..fb91b504 100644 --- a/include/boost/test/utils/iterator/token_iterator.hpp +++ b/include/boost/test/utils/iterator/token_iterator.hpp @@ -19,8 +19,8 @@ #include #include -#include -#include +#include +#include // STL #include @@ -565,6 +565,9 @@ make_range_token_iterator( Iter begin, Iter end, M1 const& m1, M2 const& m2, M3 // Revision History : // // $Log$ +// Revision 1.2 2005/01/22 19:22:14 rogeeff +// implementation moved into headers section to eliminate dependency of included/minimal component on src directory +// // Revision 1.1 2005/01/22 18:21:40 rogeeff // moved sharable staff into utils // diff --git a/include/boost/test/utils/xml_printer.hpp b/include/boost/test/utils/xml_printer.hpp index ec8348a0..ad88426e 100644 --- a/include/boost/test/utils/xml_printer.hpp +++ b/include/boost/test/utils/xml_printer.hpp @@ -16,9 +16,9 @@ #define BOOST_TEST_XML_PRINTER_HPP_071894GER // Boost.Test -#include -#include -#include +#include +#include +#include // BOOST #include @@ -32,10 +32,6 @@ namespace boost { namespace unit_test { -#if !defined(BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP) && !BOOST_WORKAROUND(__BORLANDC__, < 0x564) -namespace ut_detail { -#endif - // ************************************************************************** // // ************** xml print helpers ************** // // ************************************************************************** // @@ -100,10 +96,6 @@ operator<<( custom_printer const& p, const_string value ) //____________________________________________________________________________// -#if !defined(BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP) && !BOOST_WORKAROUND(__BORLANDC__, < 0x564) -} // namespace ut_detail -#endif - } // namespace unit_test } // namespace boost @@ -114,6 +106,9 @@ operator<<( custom_printer const& p, const_string value ) // Revision History : // // $Log$ +// Revision 1.2 2005/01/22 19:22:13 rogeeff +// implementation moved into headers section to eliminate dependency of included/minimal component on src directory +// // Revision 1.1 2005/01/22 18:21:40 rogeeff // moved sharable staff into utils // diff --git a/src/cpp_main.cpp b/src/cpp_main.cpp index dfd5ea79..92c4b93f 100644 --- a/src/cpp_main.cpp +++ b/src/cpp_main.cpp @@ -1,5 +1,4 @@ -// (C) Copyright Gennadiy Rozental 2001-2004. -// (C) Copyright Beman Dawes 1995-2001. +// (C) Copyright Gennadiy Rozental 2005. // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) @@ -10,107 +9,18 @@ // // Version : $Revision$ // -// Description : main function implementation for Program Executon Monitor +// Description : forwarding source // *************************************************************************** -// Boost.Test -#include -#include - -// BOOST -#include -#include - -// STL -#include -#include - -#ifdef BOOST_NO_STDC_NAMESPACE -namespace std { using ::getenv; using ::strcmp; } -#endif - -int cpp_main( int argc, char* argv[] ); // prototype for user's cpp_main() - -namespace -{ - -class cpp_main_caller : public boost::execution_monitor { -public: - cpp_main_caller( int argc, char** argv ) - : m_argc( argc ), m_argv( argv ) {} - - int function() { return cpp_main( m_argc, m_argv ); } - -private: - int m_argc; - char** m_argv; -}; - -} - -// ************************************************************************** // -// ************** cpp main ************** // -// ************************************************************************** // - -int main( int argc, char* argv[] ) -{ - cpp_main_caller caller( argc, argv ); - - int result; - - boost::unit_test::const_string p( std::getenv( "BOOST_TEST_CATCH_SYSTEM_ERRORS" ) ); - bool catch_system_errors = p != "no"; - - try { - result = caller.execute( catch_system_errors ); - - if( result == 0 ) - result = boost::exit_success; - else if( result != boost::exit_success ) { - std::cout << "\n**** error return code: " << result << std::endl; - result = boost::exit_failure; - } - } - catch( boost::execution_exception const& exex ) { - std::cout << "\n**** exception(" << exex.code() << "): " << exex.what() << std::endl; - result = boost::exit_exception_failure; - } - - if( result != boost::exit_success ) { - std::cerr << "******** errors detected; see standard output for details ********" << std::endl; - } - else { - // Some prefer a confirming message when all is well, while others don't - // like the clutter. Use an environment variable to avoid command - // line argument modifications; for use in production programs - // that's a no-no in some organizations. - boost::unit_test::const_string p( std::getenv( "BOOST_PRG_MON_CONFIRM" ) ); - if( p != "no" ) { - std::cerr << std::flush << "no errors detected" << std::endl; - } - } - - return result; -} - -//____________________________________________________________________________// +#include // *************************************************************************** // Revision History : // // $Log$ -// Revision 1.15 2004/05/21 06:26:09 rogeeff -// licence update +// Revision 1.16 2005/01/22 19:26:35 rogeeff +// implementation moved into headers section to eliminate dependency of included/minimal component on src directory // -// Revision 1.14 2004/05/11 11:04:44 rogeeff -// basic_cstring introduced and used everywhere -// class properties reworked -// namespace names shortened -// -// Revision 1.13 2003/12/01 00:42:37 rogeeff -// prerelease cleaning -// - // *************************************************************************** // EOF diff --git a/src/execution_monitor.cpp b/src/execution_monitor.cpp index bc858994..ccb4aa9e 100644 --- a/src/execution_monitor.cpp +++ b/src/execution_monitor.cpp @@ -1,7 +1,6 @@ -// (C) Copyright Gennadiy Rozental 2001-2004. -// (C) Copyright Beman Dawes and Ullrich Koethe 1995-2001. -// Use, modification, and distribution are subject to the -// Boost Software License, Version 1.0. (See accompanying file +// (C) Copyright Gennadiy Rozental 2005. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) // See http://www.boost.org/libs/test for the library home page. @@ -10,621 +9,18 @@ // // Version : $Revision$ // -// Description : provides execution monitor implementation for all supported -// configurations, including Microsoft structured exception based, unix signals -// based and special workarounds for borland -// -// Note that when testing requirements or user wishes preclude use of this -// file as a separate compilation unit, it may be included as a header file. -// -// Header dependencies are deliberately restricted to reduce coupling to other -// boost libraries. +// Description : forwarding source // *************************************************************************** -// Boost.Test -#include - -// BOOST -#include // for exit codes -#include // for workarounds - -// STL -#include // for string -#include // for bad_alloc -#include // for bad_cast, bad_typeid -#include // for exception, bad_exception -#include // for std exception hierarchy -#include // for C string API -#include // for assert -#include // for NULL - -#ifdef BOOST_NO_STDC_NAMESPACE -namespace std { using ::strlen; using ::strncat; } -#endif - -// Microsoft + other compatible compilers such as Intel -#if !defined(BOOST_DISABLE_WIN32) && \ - !defined(__BORLANDC__) && \ - (defined(_MSC_VER) && !defined(__COMO__)) || \ - (defined(__INTEL__) && defined(__MWERKS__) && __MWERKS__ >= 0x3000) - -#define BOOST_MS_STRCTURED_EXCEPTION_HANDLING -#if !defined(_WIN32_WINNT) -#define _WIN32_WINNT 0x0400 -#endif - -#include -#include -#include -#include - -#if !defined(NDEBUG) && !defined(__MWERKS__) // __MWERKS__ does not seem to supply implementation of C runtime debug hooks, causing linking errors -#define BOOST_MS_CRT_DEBUG_HOOK -#include -#endif - -#elif (defined(__BORLANDC__) && defined(_Windows) && !defined(BOOST_DISABLE_WIN32)) -#define BOOST_MS_STRCTURED_EXCEPTION_HANDLING -#include // Borland 5.5.1 has its own way of doing things. - -#elif defined(BOOST_HAS_SIGACTION) - -#define BOOST_SIGACTION_BASED_SIGNAL_HANDLING -#include -#include -#include - -#else - -#define BOOST_NO_SIGNAL_HANDLING - -#endif - -#include - -namespace boost { - -namespace detail { - -using unit_test::const_string; - -// boost::execution_monitor::execute() calls boost::detail::catch_signals() to -// execute user function with signals control -// boost::execution_monitor::execute() calls boost::detail::report_error(...) to -// report any caught exception and throw execution_exception - -const std::size_t REPORT_ERROR_BUFFER_SIZE = 512; - -static int catch_signals( execution_monitor & exmon, bool catch_system_errors, int timeout ); // timeout is in seconds. 0 implies none. - -static void report_error( - execution_exception::error_code ec, - const_string msg1, // first part of the message - const_string msg2 = "" ); // second part of the message; sum length msg1 + msg2 should not - // exceed REPORT_ERROR_BUFFER_SIZE; never concatenate messages - // manually, cause it should work even in case of memory lack - -//____________________________________________________________________________// - -// Declaration for Microsoft structured exception handling (unix alternative - signal) -#ifdef BOOST_MS_STRCTURED_EXCEPTION_HANDLING - -// this class defined per the Microsoft structured exception documentation -class ms_se_exception { -public: - // Constructor - explicit ms_se_exception( unsigned int n ) - : m_se_id( n ) {} - - // Destructor - ~ms_se_exception() {} - - // access methods - unsigned int id() const { return m_se_id; } - -private: - // Data members - unsigned int m_se_id; -}; - -//____________________________________________________________________________// - -void ms_se_trans_func( unsigned int id, _EXCEPTION_POINTERS* exps ); -void ms_se_forward_func( unsigned int id, _EXCEPTION_POINTERS* exps ); -static void report_ms_se_error( unsigned int id ); - -//____________________________________________________________________________// - -// Declarations for unix-style signal handling -#elif defined(BOOST_SIGACTION_BASED_SIGNAL_HANDLING) - -class unix_signal_exception { - typedef execution_exception::error_code error_code_type; -public: - // Constructor - unix_signal_exception( execution_exception::error_code ec, const_string em ) - : m_error_code( ec ), m_error_message( em ) {} - - // Destructor - ~unix_signal_exception() {} - - // access methods - error_code_type error_code() const { return m_error_code; } - const_string error_message() const { return m_error_message; } -private: - // Data members - error_code_type m_error_code; - const_string m_error_message; -}; - -#endif - -//____________________________________________________________________________// - -#if defined(BOOST_MS_CRT_DEBUG_HOOK) - -int -assert_reporting_function( int reportType, char* userMessage, int* retVal ) -{ - switch( reportType ) { - case _CRT_ASSERT: - detail::report_error( execution_exception::user_error, userMessage ); - - return 1; // return value and retVal are not important since we never reach this line - case _CRT_ERROR: - detail::report_error( execution_exception::system_error, userMessage ); - - return 1; // return value and retVal are not important since we never reach this line - default: - return 0; // use usual reporting method - } -} - -#endif - -} // namespace detail - -// ************************************************************************** // -// ************** execution_monitor ************** // -// ************************************************************************** // - -int -execution_monitor::run_function() -{ - return m_custom_translators ? (*m_custom_translators)( *this ) : function(); -} - -//____________________________________________________________________________// - -int -execution_monitor::execute( bool catch_system_errors, int timeout ) -{ - using unit_test::const_string; - -#if defined(BOOST_MS_STRCTURED_EXCEPTION_HANDLING) && !defined(__BORLANDC__) - if( IsDebuggerPresent() ) - catch_system_errors = false; - - if( catch_system_errors ) - _set_se_translator( detail::ms_se_trans_func ); - else - _set_se_translator( detail::ms_se_forward_func ); -#endif - -#if defined(BOOST_MS_CRT_DEBUG_HOOK) - if( catch_system_errors ) - _CrtSetReportHook( &detail::assert_reporting_function ); -#endif - - try { - return detail::catch_signals( *this, catch_system_errors, timeout ); - } - - // Catch-clause reference arguments are a bit different from function - // arguments (ISO 15.3 paragraphs 18 & 19). Apparently const isn't - // required. Programmers ask for const anyhow, so we supply it. That's - // easier than answering questions about non-const usage. - - catch( char const* ex ) - { detail::report_error( execution_exception::cpp_exception_error, "C string: ", ex ); } - catch( std::string const& ex ) - { detail::report_error( execution_exception::cpp_exception_error, "std::string: ", ex.c_str() ); } - - // std:: exceptions - - catch( std::bad_alloc const& ex ) - { detail::report_error( execution_exception::cpp_exception_error, "std::bad_alloc: ", ex.what() ); } - -#if !defined(__BORLANDC__) || __BORLANDC__ > 0x0551 - catch( std::bad_cast const& ex ) - { detail::report_error( execution_exception::cpp_exception_error, "std::bad_cast: ", ex.what() ); } - catch( std::bad_typeid const& ex ) - { detail::report_error( execution_exception::cpp_exception_error, "std::bad_typeid: ", ex.what() ); } -#else - catch( std::bad_cast const& ex ) - { detail::report_error( execution_exception::cpp_exception_error, "std::bad_cast" ); } - catch( std::bad_typeid const& ex ) - { detail::report_error( execution_exception::cpp_exception_error, "std::bad_typeid" ); } -#endif - - catch( std::bad_exception const& ex ) - { detail::report_error( execution_exception::cpp_exception_error, "std::bad_exception: ", ex.what() ); } - catch( std::domain_error const& ex ) - { detail::report_error( execution_exception::cpp_exception_error, "std::domain_error: ", ex.what() ); } - catch( std::invalid_argument const& ex ) - { detail::report_error( execution_exception::cpp_exception_error, "std::invalid_argument: ", ex.what() ); } - catch( std::length_error const& ex ) - { detail::report_error( execution_exception::cpp_exception_error, "std::length_error: ", ex.what() ); } - catch( std::out_of_range const& ex ) - { detail::report_error( execution_exception::cpp_exception_error, "std::out_of_range: ", ex.what() ); } - catch( std::range_error const& ex ) - { detail::report_error( execution_exception::cpp_exception_error, "std::range_error: ", ex.what() ); } - catch( std::overflow_error const& ex ) - { detail::report_error( execution_exception::cpp_exception_error, "std::overflow_error: ", ex.what() ); } - catch( std::underflow_error const& ex ) - { detail::report_error( execution_exception::cpp_exception_error, "std::underflow_error: ", ex.what() ); } - catch( std::logic_error const& ex ) - { detail::report_error( execution_exception::cpp_exception_error, "std::logic_error: ", ex.what() ); } - catch( std::runtime_error const& ex ) - { detail::report_error( execution_exception::cpp_exception_error, "std::runtime_error: ", ex.what() ); } - catch( std::exception const& ex ) - { detail::report_error( execution_exception::cpp_exception_error, "std::exception: ", ex.what() ); } - -#if defined(BOOST_MS_STRCTURED_EXCEPTION_HANDLING) - catch( detail::ms_se_exception const& ex ) - { detail::report_ms_se_error( ex.id() ); } -#elif defined(BOOST_SIGACTION_BASED_SIGNAL_HANDLING) - catch( detail::unix_signal_exception const& ex ) - { detail::report_error( ex.error_code(), ex.error_message() ); } -#endif // BOOST_SIGACTION_BASED_SIGNAL_HANDLING - - catch( execution_exception const& ) { throw; } - - catch( ... ) - { detail::report_error( execution_exception::cpp_exception_error, "unknown type" ); } - - return 0; // never reached; supplied to quiet compiler warnings -} // execute - -//____________________________________________________________________________// - -namespace detail { - -#if defined(BOOST_SIGACTION_BASED_SIGNAL_HANDLING) - -// ************************************************************************** // -// ************** boost::detail::signal_handler ************** // -// ************************************************************************** // - -class signal_handler { -public: - // Constructor - explicit signal_handler( bool catch_system_errors, int timeout ); - - // Destructor - ~signal_handler(); - - // access methods - static sigjmp_buf& jump_buffer() - { - assert( !!s_active_handler ); - - return s_active_handler->m_sigjmp_buf; - } - -private: - // Data members - struct sigaction m_same_action_for_all_signals; - struct sigaction m_old_SIGFPE_action; - struct sigaction m_old_SIGTRAP_action; - struct sigaction m_old_SIGSEGV_action; - struct sigaction m_old_SIGBUS_action; - struct sigaction m_old_SIGABRT_action; - struct sigaction m_old_SIGALRM_action; - - sigjmp_buf m_sigjmp_buf; - - signal_handler* m_prev_handler; - static signal_handler* s_active_handler; - - bool m_catch_system_errors; - bool m_set_timeout; -}; - -signal_handler* signal_handler::s_active_handler = NULL; //!! need to be placed in thread specific storage - -//____________________________________________________________________________// - -extern "C" { - -static void execution_monitor_signal_handler( int sig ) -{ - siglongjmp( signal_handler::jump_buffer(), sig ); -} - -} - -//____________________________________________________________________________// - -signal_handler::signal_handler( bool catch_system_errors, int timeout ) -: m_prev_handler( s_active_handler ), - m_catch_system_errors( catch_system_errors ), - m_set_timeout( timeout > 0 ) -{ - s_active_handler = this; - - if( m_catch_system_errors || m_set_timeout ) { - m_same_action_for_all_signals.sa_flags = 0; - m_same_action_for_all_signals.sa_handler = &execution_monitor_signal_handler; - sigemptyset( &m_same_action_for_all_signals.sa_mask ); - } - - if( m_catch_system_errors ) { - sigaction( SIGFPE , &m_same_action_for_all_signals, &m_old_SIGFPE_action ); - sigaction( SIGTRAP, &m_same_action_for_all_signals, &m_old_SIGTRAP_action ); - sigaction( SIGSEGV, &m_same_action_for_all_signals, &m_old_SIGSEGV_action ); - sigaction( SIGBUS , &m_same_action_for_all_signals, &m_old_SIGBUS_action ); - sigaction( SIGABRT, &m_same_action_for_all_signals, &m_old_SIGABRT_action ); - } - - if( m_set_timeout ) { - sigaction( SIGALRM , &m_same_action_for_all_signals, &m_old_SIGALRM_action ); - alarm( timeout ); - } -} - -//____________________________________________________________________________// - -signal_handler::~signal_handler() -{ - typedef struct sigaction* sigaction_ptr; - - assert( s_active_handler == this ); - - if( m_set_timeout ) { - alarm( 0 ); - sigaction( SIGALRM, &m_old_SIGALRM_action, sigaction_ptr() ); - } - - if( m_catch_system_errors ) { - sigaction( SIGFPE , &m_old_SIGFPE_action , sigaction_ptr() ); - sigaction( SIGTRAP, &m_old_SIGTRAP_action, sigaction_ptr() ); - sigaction( SIGSEGV, &m_old_SIGSEGV_action, sigaction_ptr() ); - sigaction( SIGBUS , &m_old_SIGBUS_action , sigaction_ptr() ); - sigaction( SIGABRT, &m_old_SIGABRT_action, sigaction_ptr() ); - } - - s_active_handler = m_prev_handler; -} - -//____________________________________________________________________________// - -// ************************************************************************** // -// ************** boost::detail::catch_signals ************** // -// ************************************************************************** // - -int catch_signals( execution_monitor & exmon, bool catch_system_errors, int timeout ) -{ - signal_handler local_signal_handler( catch_system_errors, timeout ); - int result = 0; - execution_exception::error_code ec = execution_exception::no_error; - const_string em; - - volatile int sigtype = sigsetjmp( signal_handler::jump_buffer(), 1 ); - if( sigtype == 0 ) { - result = exmon.run_function(); - } - else { - switch(sigtype) { - case SIGALRM: - ec = execution_exception::timeout_error; - em = BOOST_TEST_L( "signal: SIGALRM (timeout while executing function)" ); - break; - case SIGTRAP: - ec = execution_exception::system_error; - em = BOOST_TEST_L( "signal: SIGTRAP (perhaps integer divide by zero)" ); - break; - case SIGFPE: - ec = execution_exception::system_error; - em = BOOST_TEST_L( "signal: SIGFPE (arithmetic exception)" ); - break; - case SIGABRT: - ec = execution_exception::system_error; - em = BOOST_TEST_L( "signal: SIGABRT (application abort requested)" ); - break; - case SIGSEGV: - case SIGBUS: - ec = execution_exception::system_fatal_error; - em = BOOST_TEST_L( "signal: memory access violation" ); - break; - default: - ec = execution_exception::system_error; - em = BOOST_TEST_L( "signal: unrecognized signal" ); - } - } - - if( ec != execution_exception::no_error ) { - throw unix_signal_exception( ec, em ); - } - - return result; -} // unix catch_signals - -//____________________________________________________________________________// - -#elif (defined(__BORLANDC__) && defined(_Windows) && !defined(BOOST_DISABLE_WIN32)) - -// this works for Borland but not other Win32 compilers (which trap too many cases) -int catch_signals( execution_monitor & exmon, bool catch_system_errors, int ) -{ - int result; - - if( catch_system_errors ) { - __try { result = exmon.run_function(); } - - __except (1) - { - throw ms_se_exception( GetExceptionCode() ); - } - } - else { - result = exmon.run_function(); - } - return result; -} - -#else // default signal handler - -int catch_signals( execution_monitor& exmon, bool, int ) -{ - return exmon.run_function(); -} - -#endif // choose signal handler - -// ************************************************************************** // -// ************** Microsoft structured exception handling ************** // -// ************************************************************************** // - -#if defined(BOOST_MS_STRCTURED_EXCEPTION_HANDLING) - -void -ms_se_trans_func( unsigned int id, _EXCEPTION_POINTERS* /* exps */ ) -{ - throw ms_se_exception( id ); -} - -//____________________________________________________________________________// - -void -ms_se_forward_func( unsigned int /* id */, _EXCEPTION_POINTERS* /* exps */ ) -{ - throw; -} - -//____________________________________________________________________________// - -void -report_ms_se_error( unsigned int id ) -{ - switch( id ) { - // cases classified as fatal_system_error - case EXCEPTION_ACCESS_VIOLATION: - detail::report_error( execution_exception::system_fatal_error, "memory access violation" ); - break; - - case EXCEPTION_ILLEGAL_INSTRUCTION: - detail::report_error( execution_exception::system_fatal_error, "illegal instruction" ); - break; - - case EXCEPTION_PRIV_INSTRUCTION: - detail::report_error( execution_exception::system_fatal_error, "privileged instruction" ); - break; - - case EXCEPTION_IN_PAGE_ERROR: - detail::report_error( execution_exception::system_fatal_error, "memory page error" ); - break; - - case EXCEPTION_STACK_OVERFLOW: - detail::report_error( execution_exception::system_fatal_error, "stack overflow" ); - break; - - // cases classified as (non-fatal) system_trap - case EXCEPTION_DATATYPE_MISALIGNMENT: - detail::report_error( execution_exception::system_error, "data misalignment" ); - break; - - case EXCEPTION_INT_DIVIDE_BY_ZERO: - detail::report_error( execution_exception::system_error, "integer divide by zero" ); - break; - - case EXCEPTION_INT_OVERFLOW: - detail::report_error( execution_exception::system_error, "integer overflow" ); - break; - - case EXCEPTION_ARRAY_BOUNDS_EXCEEDED: - detail::report_error( execution_exception::system_error, "array bounds exceeded" ); - break; - - case EXCEPTION_FLT_DIVIDE_BY_ZERO: - detail::report_error( execution_exception::system_error, "floating point divide by zero" ); - break; - - case EXCEPTION_FLT_STACK_CHECK: - detail::report_error( execution_exception::system_error, "floating point stack check" ); - break; - - case EXCEPTION_FLT_DENORMAL_OPERAND: - case EXCEPTION_FLT_INEXACT_RESULT: - case EXCEPTION_FLT_INVALID_OPERATION: - case EXCEPTION_FLT_OVERFLOW: - case EXCEPTION_FLT_UNDERFLOW: - detail::report_error( execution_exception::system_error, "floating point error" ); - break; - - default: - detail::report_error( execution_exception::system_error, "unrecognized exception or signal" ); - break; - } // switch -} // report_ms_se_error - -//____________________________________________________________________________// - -#endif // Microsoft structured exception handling - -// ************************************************************************** // -// ************** report_error ************** // -// ************************************************************************** // - -static void report_error( execution_exception::error_code ec, const_string msg1, const_string msg2 ) -{ - static char buf[REPORT_ERROR_BUFFER_SIZE]; - - buf[0] = '\0'; - - std::strncat( buf, msg1.begin(), sizeof(buf)-1 ); - std::strncat( buf, msg2.begin(), sizeof(buf) - msg1.size() - 1 ); - - throw execution_exception( ec, buf ); -} - -//____________________________________________________________________________// - -} // namespace detail - -} // namespace boost +#include // *************************************************************************** // Revision History : -// +// // $Log$ -// Revision 1.36 2005/01/21 07:21:38 rogeeff -// detect presence of debugger under VC and automatically prevent catching system errors +// Revision 1.37 2005/01/22 19:26:36 rogeeff +// implementation moved into headers section to eliminate dependency of included/minimal component on src directory // -// Revision 1.35 2004/08/19 00:02:21 rogeeff -// another tru64cxx65 workaround -// -// Revision 1.34 2004/07/19 12:08:12 rogeeff -// suppress warnings -// -// Revision 1.33 2004/06/07 07:34:22 rogeeff -// detail namespace renamed -// -// Revision 1.32 2004/05/21 06:26:09 rogeeff -// licence update -// -// Revision 1.31 2004/05/11 11:04:44 rogeeff -// basic_cstring introduced and used everywhere -// class properties reworked -// namespace names shortened -// -// Revision 1.30 2003/12/20 11:27:28 johnmaddock -// Added fixes for Borland C++ 6.0 compiler (With EDG frontend). -// -// Revision 1.29 2003/12/01 00:42:37 rogeeff -// prerelease cleaning -// - // *************************************************************************** // EOF diff --git a/src/supplied_log_formatters.cpp b/src/supplied_log_formatters.cpp index ae7742e5..409dbcd6 100755 --- a/src/supplied_log_formatters.cpp +++ b/src/supplied_log_formatters.cpp @@ -1,4 +1,4 @@ -// (C) Copyright Gennadiy Rozental 2001-2004. +// (C) Copyright Gennadiy Rozental 2005. // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) @@ -9,359 +9,18 @@ // // Version : $Revision$ // -// Description : implements Unit Test Log formatters +// Description : forwarding source // *************************************************************************** -// Boost.Test -#include -#include -#include -#include - -// BOOST -#include - -// STL -#include -#include -#include -#include - -namespace boost { - -namespace unit_test { - -namespace ut_detail { - -// ************************************************************************** // -// ************** compiler_log_formatter ************** // -// ************************************************************************** // - -void -compiler_log_formatter::start_log( std::ostream& output, bool log_build_info ) -{ - if( log_build_info ) - output << "Platform: " << BOOST_PLATFORM << '\n' - << "Compiler: " << BOOST_COMPILER << '\n' - << "STL : " << BOOST_STDLIB << '\n' - << "Boost : " << BOOST_VERSION/100000 << "." - << BOOST_VERSION/100 % 1000 << "." - << BOOST_VERSION % 100 << '\n'; -} - -//____________________________________________________________________________// - -void -compiler_log_formatter::log_header( std::ostream& output, unit_test_counter test_cases_amount ) -{ - output << "Running " << test_cases_amount << " test " - << (test_cases_amount > 1 ? "cases" : "case") << "...\n"; -} - -//____________________________________________________________________________// - -void -compiler_log_formatter::finish_log( std::ostream& /* output */ ) -{ -} - -//____________________________________________________________________________// - -void -compiler_log_formatter::track_test_case_enter( std::ostream& output, test_case const& tc ) -{ - output << "Entering test " << ( tc.p_type ? "case" : "suite" ) << " \"" << tc.p_name << "\""; -} - -//____________________________________________________________________________// - -void -compiler_log_formatter::track_test_case_exit( std::ostream& output, test_case const& tc, long testing_time_in_mks ) -{ - output << "Leaving test " << ( tc.p_type ? "case" : "suite" ) << " \"" << tc.p_name << "\""; - if( testing_time_in_mks > 0 ) { - output << "; testing time: "; - if( testing_time_in_mks % 1000 == 0 ) - output << testing_time_in_mks/1000 << "ms"; - else - output << testing_time_in_mks << "ms"; - } -} - -//____________________________________________________________________________// - -void -compiler_log_formatter::log_exception( std::ostream& output, log_checkpoint_data const& checkpoint_data , - const_string test_case_name, const_string explanation ) -{ - output << "Exception in \"" << test_case_name << "\": " << explanation; - - if( !checkpoint_data.m_message.empty() ) { - output << '\n'; - print_prefix( output, checkpoint_data.m_file, checkpoint_data.m_line ); - output << "last checkpoint: " << checkpoint_data.m_message; - } -} - -//____________________________________________________________________________// - -void -compiler_log_formatter::begin_log_entry( std::ostream& output, log_entry_data const& entry_data, log_entry_types let ) -{ - switch( let ) { - case BOOST_UTL_ET_INFO: - print_prefix( output, entry_data.m_file, entry_data.m_line ); - output << "info: "; - break; - case BOOST_UTL_ET_MESSAGE: - break; - case BOOST_UTL_ET_WARNING: - print_prefix( output, entry_data.m_file, entry_data.m_line ); - output << "warning in \"" << unit_test_result::instance().test_case_name() << "\": "; - break; - case BOOST_UTL_ET_ERROR: - print_prefix( output, entry_data.m_file, entry_data.m_line ); - output << "error in \"" << unit_test_result::instance().test_case_name() << "\": "; - break; - case BOOST_UTL_ET_FATAL_ERROR: - print_prefix( output, entry_data.m_file, entry_data.m_line ); - output << "fatal error in \"" << unit_test_result::instance().test_case_name() << "\": "; - break; - } -} - -//____________________________________________________________________________// - -void -compiler_log_formatter::log_entry_value( std::ostream& output, const_string value ) -{ - output << value; -} - -//____________________________________________________________________________// - -void -compiler_log_formatter::end_log_entry( std::ostream& /* output */ ) -{ -} - -//____________________________________________________________________________// - -void -compiler_log_formatter::print_prefix( std::ostream& output, const_string file, std::size_t line ) -{ - output << file << '(' << line << "): "; -} - -//____________________________________________________________________________// - -// ************************************************************************** // -// ************** xml_log_formatter ************** // -// ************************************************************************** // - -xml_log_formatter::xml_log_formatter() -: m_indent( 0 ) -{ -} - -//____________________________________________________________________________// - -void -xml_log_formatter::start_log( std::ostream& output, bool log_build_info ) -{ - output << "\n"; -} - -//____________________________________________________________________________// - -void -xml_log_formatter::log_header( std::ostream& /* output */, unit_test_counter /* test_cases_amount */ ) -{ -} - -//____________________________________________________________________________// - -void -xml_log_formatter::finish_log( std::ostream& output ) -{ - output << "\n"; -} - -//____________________________________________________________________________// - -void -xml_log_formatter::track_test_case_enter( std::ostream& output, test_case const& tc ) -{ - print_indent( output ); - - output << "<" << ( tc.p_type ? "TestCase" : "TestSuite" ) - << " name" << attr_value() << tc.p_name - << ">"; - - m_indent += 2; -} - -//____________________________________________________________________________// - -void -xml_log_formatter::track_test_case_exit( std::ostream& output, test_case const& tc, long testing_time_in_mks ) -{ - m_indent -= 2; - - print_indent( output ); - - output << ""; -} - -//____________________________________________________________________________// - -void -xml_log_formatter::log_exception( std::ostream& output, log_checkpoint_data const& checkpoint_data, const_string test_case_name, const_string explanation ) -{ - print_indent( output ); - output << "\n"; - - m_indent += 2; - - print_indent( output ); - output << pcdata() << explanation << '\n'; - - if( !checkpoint_data.m_message.empty() ) { - print_indent( output ); - output << "\n"; - - m_indent += 2; - - print_indent( output ); - output << pcdata() << checkpoint_data.m_message << "\n"; - - m_indent -= 2; - - print_indent( output ); - output << "\n"; - } - - m_indent -= 2; - print_indent( output ); - - output << ""; -} - -//____________________________________________________________________________// - -void -xml_log_formatter::begin_log_entry( std::ostream& output, log_entry_data const& entry_data, log_entry_types let ) -{ - static literal_string xml_tags[] = { "Info", "Message", "Warning", "Error", "FatalError" }; - - print_indent( output ); - - m_curr_tag = xml_tags[let]; - output << '<' << m_curr_tag - << " file" << attr_value() << entry_data.m_file - << " line" << attr_value() << entry_data.m_line - << ">\n"; - - m_indent += 2; - print_indent( output ); -} - -//____________________________________________________________________________// - -void -xml_log_formatter::log_entry_value( std::ostream& output, const_string value ) -{ - output << pcdata() << value; -} - -//____________________________________________________________________________// - -void -xml_log_formatter::end_log_entry( std::ostream& output ) -{ - if( m_curr_tag.is_empty() ) - return; - - output << '\n'; - - m_indent -= 2; - print_indent( output ); - - output << ""; - - m_curr_tag.clear(); -} - -//____________________________________________________________________________// - -void -xml_log_formatter::print_indent( std::ostream& output ) -{ - output << std::setw( m_indent ) << ""; -} - -//____________________________________________________________________________// - -} // namespace ut_detail - -} // namespace unit_test - -} // namespace boost +#include // *************************************************************************** // Revision History : -// +// // $Log$ -// Revision 1.15 2005/01/21 07:23:49 rogeeff -// added automatic test case run timing +// Revision 1.16 2005/01/22 19:26:37 rogeeff +// implementation moved into headers section to eliminate dependency of included/minimal component on src directory // -// Revision 1.13 2005/01/18 08:29:59 rogeeff -// unit_test_log rework: -// eliminated need for ::instance() -// eliminated need for << end and ...END macro -// straitend interface between log and formatters -// change compiler like formatter name -// minimized unit_test_log interface and reworked to use explicit calls -// -// Revision 1.12 2004/07/20 17:03:55 dgregor -// Documentation update from Jon T. Pedant -// -// Revision 1.11 2004/07/19 12:09:25 rogeeff -// added proper encoded of XML PCDATA -// -// Revision 1.10 2004/06/07 07:34:22 rogeeff -// detail namespace renamed -// -// Revision 1.9 2004/05/21 06:26:09 rogeeff -// licence update -// -// Revision 1.8 2004/05/13 09:04:43 rogeeff -// added fixed_mapping -// -// Revision 1.7 2004/05/11 11:04:44 rogeeff -// basic_cstring introduced and used everywhere -// class properties reworked -// namespace names shortened -// -// Revision 1.6 2003/12/01 00:42:37 rogeeff -// prerelease cleaning -// - // *************************************************************************** // EOF diff --git a/src/test_main.cpp b/src/test_main.cpp index 85be3d01..399163b5 100644 --- a/src/test_main.cpp +++ b/src/test_main.cpp @@ -1,132 +1,26 @@ -// (C) Copyright Gennadiy Rozental 2001-2004. -// (C) Copyright Beman Dawes 1995-2001. +// (C) Copyright Gennadiy Rozental 2005. // Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at +// (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) // See http://www.boost.org/libs/test for the library home page. // // File : $RCSfile$ // -// Version : $$Revision$ +// Version : $Revision$ // -// Description : implements main function for Test Execution Monitor. +// Description : forwarding source // *************************************************************************** -// Boost.Test -#include // for unit test framework -#include -#include -#include - -// BOOST -#include - -// STL -#include // for cout, cerr - -int test_main( int argc, char* argv[] ); // prototype for user's test_main() - -namespace { - int argc_; - char** argv_; - int test_main_result; - - void call_test_main() - { - test_main_result = test_main( argc_, argv_ ); - - // translate a test_main non-success return into a test error - BOOST_CHECK( test_main_result == 0 || test_main_result == boost::exit_success ); - } -} - -// ************************************************************************** // -// ************** test main ************** // -// ************************************************************************** // - -int main( int argc, char* argv[] ) { - using namespace boost::unit_test; - - // set the log level - unit_test_log.set_threshold_level_by_name( retrieve_framework_parameter( LOG_LEVEL, &argc, argv ) ); - - // set the report level - const_string reportlevel = retrieve_framework_parameter( REPORT_LEVEL, &argc, argv ); - - // set the log/report format - const_string output_format = retrieve_framework_parameter( OUTPUT_FORMAT, &argc, argv ); - - if( output_format.empty() ) { - unit_test_log.set_format( retrieve_framework_parameter( LOG_FORMAT, &argc, argv ) ); - unit_test_result::set_report_format( retrieve_framework_parameter( REPORT_FORMAT, &argc, argv ) ); - } - else { - unit_test_log.set_format( output_format ); - unit_test_result::set_report_format( output_format ); - } - - // set the result code flag - bool no_result_code = retrieve_framework_parameter( NO_RESULT_CODE, &argc, argv ) == "no"; - - // set catch_system_error switch - ut_detail::unit_test_monitor::catch_system_errors( retrieve_framework_parameter( CATCH_SYS_ERRORS, &argc, argv ) != "no" ); - - // set up the test - argc_ = argc; - argv_ = argv; - boost::scoped_ptr test_main_tc( BOOST_TEST_CASE( &call_test_main ) ); - - // start testing - unit_test_log.start( retrieve_framework_parameter( BUILD_INFO, &argc, argv ) == "yes" ); - test_main_tc->run(); - unit_test_log.finish( 1 ); - - // report results - unit_test_result::instance().report( reportlevel, std::cout ); - - // return code - return no_result_code - ? boost::exit_success - : ( test_main_result != 0 && test_main_result != boost::exit_success - ? test_main_result - : unit_test_result::instance().result_code() - ); -} +#include // *************************************************************************** // Revision History : -// +// // $Log$ -// Revision 1.20 2005/01/19 16:34:06 vawjr -// Changed the \r\r\n back to \r\n on windows so we don't get errors when compiling -// on VC++8.0. I don't know why Microsoft thinks it's a good idea to call this an error, -// but they do. I also don't know why people insist on checking out files on Windows and -// copying them to a unix system to check them in (which will cause exactly this problem) +// Revision 1.21 2005/01/22 19:26:37 rogeeff +// implementation moved into headers section to eliminate dependency of included/minimal component on src directory // -// Revision 1.19 2005/01/18 08:30:08 rogeeff -// unit_test_log rework: -// eliminated need for ::instance() -// eliminated need for << end and ...END macro -// straitend interface between log and formatters -// change compiler like formatter name -// minimized unit_test_log interface and reworked to use explicit calls -// -// Revision 1.18 2004/06/07 07:34:22 rogeeff -// detail namespace renamed -// -// Revision 1.17 2004/05/21 06:26:09 rogeeff -// licence update -// -// Revision 1.16 2004/05/11 11:04:44 rogeeff -// basic_cstring introduced and used everywhere -// class properties reworked -// namespace names shortened -// -// Revision 1.15 2003/12/01 00:42:37 rogeeff -// prerelease cleaning -// - // *************************************************************************** // EOF diff --git a/src/test_tools.cpp b/src/test_tools.cpp index 6158e066..cbd416d7 100644 --- a/src/test_tools.cpp +++ b/src/test_tools.cpp @@ -1,7 +1,6 @@ -// (C) Copyright Gennadiy Rozental 2001-2004. -// (C) Copyright Ullrich Koethe 2001. +// (C) Copyright Gennadiy Rozental 2005. // Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at +// (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) // See http://www.boost.org/libs/test for the library home page. @@ -10,463 +9,17 @@ // // Version : $Revision$ // -// Description : supplies offline implementation for the Test Tools +// Description : forwarding source // *************************************************************************** -// Boost.Test -#include -#include - -// BOOST -#include - -// STL -#include -#include -#include -#include -#include -#include -#include -#ifdef BOOST_STANDARD_IOSTREAMS -#include -#endif - -# ifdef BOOST_NO_STDC_NAMESPACE -namespace std { using ::strcmp; using ::strlen; using ::isprint; } -#if !defined( BOOST_NO_CWCHAR ) -namespace std { using ::wcscmp; } -#endif -# endif - -#include - -namespace boost { - -namespace test_tools { - -#define LOG BOOST_UT_LOG_ENTRY_FL( file_name, line_num ) - -namespace tt_detail { - -// ************************************************************************** // -// ************** TOOL BOX Implementation ************** // -// ************************************************************************** // - -void -checkpoint_impl( wrap_stringstream& message, const_string file_name, std::size_t line_num ) -{ - LOG( unit_test::log_test_suites ) << unit_test::checkpoint( message.str() ); -} - -//____________________________________________________________________________// - -void -message_impl( wrap_stringstream& message, const_string file_name, std::size_t line_num ) -{ - LOG( unit_test::log_messages ) << message.str(); -} - -//____________________________________________________________________________// - -void -warn_and_continue_impl( bool predicate, wrap_stringstream& message, - const_string file_name, std::size_t line_num, bool add_fail_pass ) -{ - if( !predicate ) { - LOG( unit_test::log_warnings ) << (add_fail_pass ? "condition " : "") << message.str() - << (add_fail_pass ? " is not satisfied" : "" ); - } - else { - LOG( unit_test::log_successful_tests ) << "condition " << message.str() << " is satisfied"; - } -} - -//____________________________________________________________________________// - -void -warn_and_continue_impl( extended_predicate_value const& v, wrap_stringstream& message, - const_string file_name, std::size_t line_num, bool add_fail_pass ) -{ - warn_and_continue_impl( !!v, - wrap_stringstream().ref() << (add_fail_pass ? "condition " : "") << message - << (add_fail_pass && !v ? " is not satisfied. " : "" ) << *(v.p_message), - file_name, line_num, false ); -} - -//____________________________________________________________________________// - -bool -test_and_continue_impl( bool predicate, wrap_stringstream& message, - const_string file_name, std::size_t line_num, bool add_fail_pass, - unit_test::log_level loglevel ) -{ - if( !predicate ) { - unit_test::unit_test_result::instance().inc_failed_assertions(); - - LOG( loglevel ) << (add_fail_pass ? "test " : "") << message.str() << (add_fail_pass ? " failed" : ""); - - return true; - } - else { - unit_test::unit_test_result::instance().inc_passed_assertions(); - - LOG( unit_test::log_successful_tests ) << (add_fail_pass ? "test " : "") << message.str() - << (add_fail_pass ? " passed" : ""); - - return false; - } -} - -//____________________________________________________________________________// - -bool -test_and_continue_impl( extended_predicate_value const& v, wrap_stringstream& message, - const_string file_name, std::size_t line_num, bool add_fail_pass, - unit_test::log_level loglevel ) -{ - return test_and_continue_impl( !!v, - wrap_stringstream().ref() << (add_fail_pass ? "test " : "") << message - << (add_fail_pass ? (!v ? " failed. " : " passed. ") : "") << *(v.p_message), - file_name, line_num, false, loglevel ); -} - -//____________________________________________________________________________// - -void -test_and_throw_impl( bool predicate, wrap_stringstream& message, - const_string file_name, std::size_t line_num, - bool add_fail_pass, unit_test::log_level loglevel ) -{ - if( test_and_continue_impl( predicate, message, file_name, line_num, add_fail_pass, loglevel ) ) - throw test_tool_failed(); // error already reported by test_and_continue_impl -} - -//____________________________________________________________________________// - -void -test_and_throw_impl( extended_predicate_value const& v, wrap_stringstream& message, - const_string file_name, std::size_t line_num, - bool add_fail_pass, unit_test::log_level loglevel ) -{ - if( test_and_continue_impl( v, message, file_name, line_num, add_fail_pass, loglevel ) ) - throw test_tool_failed(); // error already reported by test_and_continue_impl -} - -//____________________________________________________________________________// - -bool -equal_and_continue_impl( char const* left, char const* right, wrap_stringstream& message, - const_string file_name, std::size_t line_num, - unit_test::log_level loglevel ) -{ - bool predicate = (left && right) ? std::strcmp( left, right ) == 0 : (left == right); - - left = left ? left : "null string"; - right = right ? right : "null string"; - - if( !predicate ) { - return test_and_continue_impl( false, - wrap_stringstream().ref() << "test " << message.str() << " failed [" << left << " != " << right << "]", - file_name, line_num, false, loglevel ); - } - - return test_and_continue_impl( true, message, file_name, line_num, true, loglevel ); -} - -//____________________________________________________________________________// - -#if !defined( BOOST_NO_CWCHAR ) -bool -equal_and_continue_impl( wchar_t const* left, wchar_t const* right, wrap_stringstream& message, - const_string file_name, std::size_t line_num, - unit_test::log_level loglevel ) -{ - bool predicate = (left && right) ? std::wcscmp( left, right ) == 0 : (left == right); - - left = left ? left : L"null string"; - right = right ? right : L"null string"; - - if( !predicate ) { - return test_and_continue_impl( false, - wrap_stringstream().ref() << "test " << message.str() << " failed", - file_name, line_num, false, loglevel ); - } - - return test_and_continue_impl( true, message, file_name, line_num, true, loglevel ); -} -#endif // !defined( BOOST_NO_CWCHAR ) - -//____________________________________________________________________________// - -bool -is_defined_impl( const_string symbol_name, const_string symbol_value ) -{ - symbol_value.trim_left( 2 ); - return symbol_name != symbol_value; -} - -//____________________________________________________________________________// - -// ************************************************************************** // -// ************** log print helper ************** // -// ************************************************************************** // - -void -print_log_value::operator()( std::ostream& ostr, char t ) -{ - if( (std::isprint)( t ) ) - ostr << '\'' << t << '\''; - else - ostr << std::hex - // showbase is only available for new style streams: -#ifndef BOOST_NO_STD_LOCALE - << std::showbase -#else - << "0x" -#endif - << (int)t; -} - -//____________________________________________________________________________// - -void -print_log_value::operator()( std::ostream& ostr, unsigned char t ) -{ - ostr << std::hex - // showbase is only available for new style streams: -#ifndef BOOST_NO_STD_LOCALE - << std::showbase -#else - << "0x" -#endif - << (int)t; -} - -//____________________________________________________________________________// - -} // namespace tt_detail - -// ************************************************************************** // -// ************** output_test_stream ************** // -// ************************************************************************** // - -struct output_test_stream::Impl -{ - std::fstream m_pattern_to_match_or_save; - bool m_match_or_save; - std::string m_synced_string; - - char get_char() - { - char res; - do { - m_pattern_to_match_or_save.get( res ); - } while( res == '\r' && - !m_pattern_to_match_or_save.fail() && - !m_pattern_to_match_or_save.eof() ); - - return res; - } - - void check_and_fill( extended_predicate_value& res ) - { - if( !res.p_predicate_value ) - *(res.p_message) << "Output content: \"" << m_synced_string << '\"'; - } -}; - -//____________________________________________________________________________// - -output_test_stream::output_test_stream( const_string pattern_file_name, bool match_or_save ) -: m_pimpl( new Impl ) -{ - if( !pattern_file_name.is_empty() ) - m_pimpl->m_pattern_to_match_or_save.open( pattern_file_name.begin(), match_or_save ? std::ios::in : std::ios::out ); - - m_pimpl->m_match_or_save = match_or_save; -} - -//____________________________________________________________________________// - -output_test_stream::~output_test_stream() -{ -} - -//____________________________________________________________________________// - -extended_predicate_value -output_test_stream::is_empty( bool flush_stream ) -{ - sync(); - - result_type res( m_pimpl->m_synced_string.empty() ); - - m_pimpl->check_and_fill( res ); - - if( flush_stream ) - flush(); - - return res; -} - -//____________________________________________________________________________// - -extended_predicate_value -output_test_stream::check_length( std::size_t length_, bool flush_stream ) -{ - sync(); - - result_type res( m_pimpl->m_synced_string.length() == length_ ); - - m_pimpl->check_and_fill( res ); - - if( flush_stream ) - flush(); - - return res; -} - -//____________________________________________________________________________// - -extended_predicate_value -output_test_stream::is_equal( const_string arg, bool flush_stream ) -{ - sync(); - - result_type res( const_string( m_pimpl->m_synced_string ) == arg ); - - m_pimpl->check_and_fill( res ); - - if( flush_stream ) - flush(); - - return res; -} - -//____________________________________________________________________________// - -extended_predicate_value -output_test_stream::match_pattern( bool flush_stream ) -{ - sync(); - - result_type result( true ); - - if( !m_pimpl->m_pattern_to_match_or_save.is_open() ) { - result = false; - *(result.p_message) << "Couldn't open pattern file for " - << ( m_pimpl->m_match_or_save ? "reading" : "writing"); - } - else { - if( m_pimpl->m_match_or_save ) { - for ( std::string::size_type i = 0; i < m_pimpl->m_synced_string.length(); ++i ) { - char c = m_pimpl->get_char(); - - result = !m_pimpl->m_pattern_to_match_or_save.fail() && - !m_pimpl->m_pattern_to_match_or_save.eof() && - (m_pimpl->m_synced_string[i] == c); - - if( !result ) { - std::string::size_type suffix_size = (std::min)( m_pimpl->m_synced_string.length() - i, - static_cast(5) ); - - // try to log area around the mismatch - *(result.p_message) << "Mismatch at position " << i << '\n' - << "..." << m_pimpl->m_synced_string.substr( i, suffix_size ) << "..." << '\n' - << "..." << c; - - std::string::size_type counter = suffix_size; - while( --counter ) { - char c = m_pimpl->get_char(); - - if( m_pimpl->m_pattern_to_match_or_save.fail() || - m_pimpl->m_pattern_to_match_or_save.eof() ) - break; - - *(result.p_message) << c; - } - - *(result.p_message) << "..."; - - // skip rest of the bytes. May help for further matching - m_pimpl->m_pattern_to_match_or_save.ignore( m_pimpl->m_synced_string.length() - i - suffix_size); - break; - } - } - } - else { - m_pimpl->m_pattern_to_match_or_save.write( m_pimpl->m_synced_string.c_str(), - static_cast( m_pimpl->m_synced_string.length() ) ); - m_pimpl->m_pattern_to_match_or_save.flush(); - } - } - - if( flush_stream ) - flush(); - - return result; -} - -//____________________________________________________________________________// - -void -output_test_stream::flush() -{ - m_pimpl->m_synced_string.erase(); - -#ifndef BOOST_NO_STRINGSTREAM - str( std::string() ); -#else - seekp( 0, std::ios::beg ); -#endif -} - -//____________________________________________________________________________// - -std::size_t -output_test_stream::length() -{ - sync(); - - return m_pimpl->m_synced_string.length(); -} - -//____________________________________________________________________________// - -void -output_test_stream::sync() -{ -#ifdef BOOST_NO_STRINGSTREAM - m_pimpl->m_synced_string.assign( str(), pcount() ); - freeze( false ); -#else - m_pimpl->m_synced_string = str(); -#endif -} - -//____________________________________________________________________________// - -} // namespace test_tools - -#undef LOG - -} // namespace boost +#include // *************************************************************************** // Revision History : -// +// // $Log$ -// Revision 1.43 2005/01/19 06:40:05 vawjr -// deleted redundant \r in many \r\r\n sequences of the source. VC8.0 doesn't like them -// -// Revision 1.42 2005/01/18 08:30:08 rogeeff -// unit_test_log rework: -// eliminated need for ::instance() -// eliminated need for << end and ...END macro -// straitend interface between log and formatters -// change compiler like formatter name -// minimized unit_test_log interface and reworked to use explicit calls +// Revision 1.44 2005/01/22 19:26:37 rogeeff +// implementation moved into headers section to eliminate dependency of included/minimal component on src directory // // *************************************************************************** diff --git a/src/unit_test_log.cpp b/src/unit_test_log.cpp index 53a77b40..e3507b8f 100644 --- a/src/unit_test_log.cpp +++ b/src/unit_test_log.cpp @@ -1,4 +1,4 @@ -// (C) Copyright Gennadiy Rozental 2001-2004. +// (C) Copyright Gennadiy Rozental 2005. // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) @@ -9,470 +9,17 @@ // // Version : $Revision$ // -// Description : implemets Unit Test Log, Majority of implementation details -// are hidden in this file with use of pimpl idiom. +// Description : forwarding source // *************************************************************************** -// Boost.Test -#include -#include -#include -#include -#include -#include -#include - -// BOOST -#include -#include - -// STL -#include -#include - -# ifdef BOOST_NO_STDC_NAMESPACE -namespace std { using ::strcmp; } -# endif - -namespace boost { - -namespace unit_test { - -// ************************************************************************** // -// ************** entry_value_collector ************** // -// ************************************************************************** // - -namespace ut_detail { - -entry_value_collector -entry_value_collector::operator<<( const_string v ) -{ - unit_test_log.log_value( v ); - - m_last = false; - - entry_value_collector res; - return res; -} - -//____________________________________________________________________________// - -entry_value_collector -entry_value_collector::operator<<( checkpoint const& cp ) -{ - unit_test_log << cp; - - m_last = false; - - entry_value_collector res; - return res; -} - -//____________________________________________________________________________// - -entry_value_collector::~entry_value_collector() -{ - if( m_last ) - unit_test_log << end(); -} - -//____________________________________________________________________________// - -} // namespace ut_detail - -// ************************************************************************** // -// ************** unit_test_log ************** // -// ************************************************************************** // - -namespace { - -struct unit_test_log_impl { - // Constructor - unit_test_log_impl() : m_stream( &std::cout ) {} - - // log data - std::ostream* m_stream; - log_level m_threshold_level; - boost::scoped_ptr m_progress_display; - boost::scoped_ptr m_log_formatter; - - // entry data - bool m_entry_in_progress; - bool m_entry_has_value; - log_entry_data m_entry_data; - - // checkpoint data - log_checkpoint_data m_checkpoint_data; - - // helper functions - std::ostream& stream() { return *m_stream; } - void flush_entry() { stream() << std::endl; } - void clear_entry_data() - { - m_entry_data.clear(); - m_entry_in_progress = false; - m_entry_has_value = false; - } - void set_checkpoint( checkpoint const& cp ) - { - cp.m_message.assign_to( m_checkpoint_data.m_message ); - m_checkpoint_data.m_file = m_entry_data.m_file; - m_checkpoint_data.m_line = m_entry_data.m_line; - } - void clear_checkpoint() { m_checkpoint_data.clear(); } -}; - -unit_test_log_impl& s_impl() { static unit_test_log_impl the_inst; return the_inst; } - -} // local namespace - -//____________________________________________________________________________// - -unit_test_log_t::unit_test_log_t() -{ - s_impl().m_threshold_level = log_all_errors; - - s_impl().m_log_formatter.reset( new ut_detail::compiler_log_formatter ); - - s_impl().clear_entry_data(); - s_impl().clear_checkpoint(); -} - -//____________________________________________________________________________// - -unit_test_log_t& -unit_test_log_t::instance() -{ - static unit_test_log_t the_instance; - - return the_instance; -} - -//____________________________________________________________________________// - -void -unit_test_log_t::set_stream( std::ostream& str ) -{ - if( s_impl().m_entry_in_progress ) - return; - - s_impl().m_stream = &str; -} - -//____________________________________________________________________________// - -void -unit_test_log_t::set_threshold_level( log_level lev ) -{ - if( s_impl().m_entry_in_progress || lev == invalid_log_level ) - return; - - s_impl().m_threshold_level = lev; -} - -//____________________________________________________________________________// - -void -unit_test_log_t::set_threshold_level_by_name( const_string lev ) -{ - static fixed_mapping log_level_name( - "all" , log_successful_tests, - "success" , log_successful_tests, - "test_suite" , log_test_suites, - "messages" , log_messages, - "warnings" , log_warnings, - "all_errors" , log_all_errors, - "cpp_exceptions", log_cpp_exception_errors, - "system_errors" , log_system_errors, - "fatal_errors" , log_fatal_errors, - "progress" , log_progress_only, - "nothing" , log_nothing, - - invalid_log_level - ); - - if( s_impl().m_entry_in_progress ) - return; - - set_threshold_level( log_level_name[lev] ); -} - -//____________________________________________________________________________// - -void -unit_test_log_t::track_test_case_enter( test_case const& tc ) -{ - if( s_impl().m_threshold_level > log_test_suites ) - return; - - *this << begin(); - - s_impl().m_log_formatter->track_test_case_enter( s_impl().stream(), tc ); - s_impl().m_entry_has_value = true; - - *this << end(); -} - -//____________________________________________________________________________// - -void -unit_test_log_t::track_test_case_exit( test_case const& tc, long testing_time_in_mks ) -{ - if( s_impl().m_threshold_level > log_test_suites ) - return; - - s_impl().clear_checkpoint(); - - *this << begin(); - - s_impl().m_log_formatter->track_test_case_exit( s_impl().stream(), tc, testing_time_in_mks ); - s_impl().m_entry_has_value = true; - - *this << end(); -} - -//____________________________________________________________________________// - -unit_test_log_t& -unit_test_log_t::operator<<( begin const& ) -{ - if( s_impl().m_entry_in_progress ) - *this << end(); - - s_impl().m_entry_in_progress = true; - - return *this; -} - -//____________________________________________________________________________// - -unit_test_log_t& -unit_test_log_t::operator<<( end const& ) -{ - if( s_impl().m_entry_has_value ) { - s_impl().m_log_formatter->end_log_entry( s_impl().stream() ); - s_impl().flush_entry(); - } - - s_impl().clear_entry_data(); - - return *this; -} - -//____________________________________________________________________________// - -char -set_unix_slash( char in ) -{ - return in == '\\' ? '/' : in; -} - -unit_test_log_t& -unit_test_log_t::operator<<( file const& f ) -{ - if( s_impl().m_entry_in_progress ) { - f.m_file_name.assign_to( s_impl().m_entry_data.m_file ); - - // normalize file name - std::transform( s_impl().m_entry_data.m_file.begin(), s_impl().m_entry_data.m_file.end(), - s_impl().m_entry_data.m_file.begin(), - &set_unix_slash ); - } - - return *this; -} - -//____________________________________________________________________________// - -unit_test_log_t& -unit_test_log_t::operator<<( line const& l ) -{ - if( s_impl().m_entry_in_progress ) - s_impl().m_entry_data.m_line = l.m_line_num; - - return *this; -} - -//____________________________________________________________________________// - -unit_test_log_t& -unit_test_log_t::operator<<( checkpoint const& cp ) -{ - if( s_impl().m_entry_in_progress ) - s_impl().set_checkpoint( cp ); - - return *this; -} - -//____________________________________________________________________________// - -ut_detail::entry_value_collector -unit_test_log_t::operator()( log_level const& l ) -{ - if( !s_impl().m_entry_in_progress ) - *this << begin(); - - s_impl().m_entry_data.m_level = l; - - ut_detail::entry_value_collector res; - return res; -} - -//____________________________________________________________________________// - -void -unit_test_log_t::log_exception( log_level l, const_string what ) -{ - *this << begin(); - - if( l >= s_impl().m_threshold_level ) { - s_impl().m_log_formatter->log_exception( s_impl().stream(), s_impl().m_checkpoint_data, - unit_test_result::instance().test_case_name(), what ); - s_impl().m_entry_has_value = true; - } - - *this << end(); -} - -//____________________________________________________________________________// - -void -unit_test_log_t::log_progress() -{ - *this << begin(); - - if( s_impl().m_progress_display ) - ++(*s_impl().m_progress_display); - - *this << end(); -} - -//____________________________________________________________________________// - -void -unit_test_log_t::log_value( const_string value ) -{ - if( s_impl().m_entry_in_progress && s_impl().m_entry_data.m_level >= s_impl().m_threshold_level && !value.empty() ) { - if( !s_impl().m_entry_has_value ) { - switch( s_impl().m_entry_data.m_level ) { - case log_successful_tests: - s_impl().m_log_formatter->begin_log_entry( s_impl().stream(), s_impl().m_entry_data, - unit_test_log_formatter::BOOST_UTL_ET_INFO ); - break; - case log_messages: - s_impl().m_log_formatter->begin_log_entry( s_impl().stream(), s_impl().m_entry_data, - unit_test_log_formatter::BOOST_UTL_ET_MESSAGE ); - break; - case log_warnings: - s_impl().m_log_formatter->begin_log_entry( s_impl().stream(), s_impl().m_entry_data, - unit_test_log_formatter::BOOST_UTL_ET_WARNING ); - break; - case log_all_errors: - case log_cpp_exception_errors: - case log_system_errors: - s_impl().m_log_formatter->begin_log_entry( s_impl().stream(), s_impl().m_entry_data, - unit_test_log_formatter::BOOST_UTL_ET_ERROR ); - break; - case log_fatal_errors: - s_impl().m_log_formatter->begin_log_entry( s_impl().stream(), s_impl().m_entry_data, - unit_test_log_formatter::BOOST_UTL_ET_FATAL_ERROR ); - break; - case log_progress_only: - case log_nothing: - case log_test_suites: - case invalid_log_level: - return; - } - } - - s_impl().m_log_formatter->log_entry_value( s_impl().stream(), value ); - s_impl().m_entry_has_value = true; - } -} - -//____________________________________________________________________________// - -void -unit_test_log_t::start( bool log_build_info ) -{ - s_impl().m_log_formatter->start_log( s_impl().stream(), log_build_info ); -} - -//____________________________________________________________________________// - -void -unit_test_log_t::header( unit_test_counter test_cases_amount ) -{ - if( s_impl().m_threshold_level != log_nothing && test_cases_amount > 0 ) - s_impl().m_log_formatter->log_header( s_impl().stream(), test_cases_amount ); - - if( s_impl().m_threshold_level == log_progress_only ) - s_impl().m_progress_display.reset( - new boost::progress_display( test_cases_amount, s_impl().stream() ) ); - else - s_impl().m_progress_display.reset(); -} - -//____________________________________________________________________________// - -void -unit_test_log_t::finish( unit_test_counter test_cases_amount ) -{ - if( test_cases_amount == 1 ) - log_progress(); - - s_impl().m_log_formatter->finish_log( s_impl().stream() ); -} - -//____________________________________________________________________________// - -void -unit_test_log_t::set_format( const_string log_format_name ) -{ - if( s_impl().m_entry_in_progress ) - return; - - static fixed_mapping > log_format( - "HRF", HRF, - "XML", XML, - - HRF - ); - - if( log_format[log_format_name] == HRF ) - set_formatter( new ut_detail::compiler_log_formatter ); - else - set_formatter( new ut_detail::xml_log_formatter ); -} - -//____________________________________________________________________________// - -void -unit_test_log_t::set_formatter( unit_test_log_formatter* the_formatter ) -{ - s_impl().m_log_formatter.reset( the_formatter ); -} - -//____________________________________________________________________________// - -} // namespace unit_test - -} // namespace boost +#include // *************************************************************************** // Revision History : -// +// // $Log$ -// Revision 1.27 2005/01/21 07:23:49 rogeeff -// added automatic test case run timing -// -// Revision 1.25 2005/01/18 08:30:08 rogeeff -// unit_test_log rework: -// eliminated need for ::instance() -// eliminated need for << end and ...END macro -// straitend interface between log and formatters -// change compiler like formatter name -// minimized unit_test_log interface and reworked to use explicit calls +// Revision 1.28 2005/01/22 19:26:37 rogeeff +// implementation moved into headers section to eliminate dependency of included/minimal component on src directory // // *************************************************************************** diff --git a/src/unit_test_main.cpp b/src/unit_test_main.cpp index 5fe03a74..41bcb267 100644 --- a/src/unit_test_main.cpp +++ b/src/unit_test_main.cpp @@ -1,6 +1,6 @@ -// (C) Copyright Gennadiy Rozental 2001-2004. +// (C) Copyright Gennadiy Rozental 2005. // Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at +// (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) // See http://www.boost.org/libs/test for the library home page. @@ -9,115 +9,18 @@ // // Version : $Revision$ // -// Description : main function implementation for Unit Test Framework +// Description : forwarding source // *************************************************************************** -#include // for unit_test framework -#include -#include -#include -#include - -// BOOST -#include - -// STL -#include -#include // for cout, cerr - -extern boost::unit_test::test_suite* init_unit_test_suite( int argc, char* argv[] ); // prototype for user's test suite init function - -// ************************************************************************** // -// ************** unit test main ************** // -// ************************************************************************** // - -int -main( int argc, char* argv[] ) -{ - using namespace boost::unit_test; - using namespace boost::unit_test::ut_detail; - - bool no_result_code; - bool print_build_info; - - // set the log level - unit_test_log.set_threshold_level_by_name( retrieve_framework_parameter( LOG_LEVEL, &argc, argv ) ); - - // set the log/report format - const_string output_format = retrieve_framework_parameter( OUTPUT_FORMAT, &argc, argv ); - - if( output_format.empty() ) { - unit_test_log.set_format( retrieve_framework_parameter( LOG_FORMAT, &argc, argv ) ); - unit_test_result::set_report_format( retrieve_framework_parameter( REPORT_FORMAT, &argc, argv ) ); - } - else { - unit_test_log.set_format( output_format ); - unit_test_result::set_report_format( output_format ); - } - - // set the result code and build info flags - no_result_code = retrieve_framework_parameter( NO_RESULT_CODE, &argc, argv ) == "no"; - print_build_info = retrieve_framework_parameter( BUILD_INFO, &argc, argv ) == "yes"; - - // set catch_system_error switch - unit_test_monitor::catch_system_errors( retrieve_framework_parameter( CATCH_SYS_ERRORS, &argc, argv ) != "no" ); - - // save report level for future reporting - const_string report_level = retrieve_framework_parameter( REPORT_LEVEL, &argc, argv ); - - // init master unit test suite - boost::scoped_ptr test( init_unit_test_suite( argc, argv ) ); - if( !test ) { - std::cerr << "*** Fail to initialize test suite" << std::endl; - return boost::exit_test_failure; - } - - // start testing - unit_test_log.start( print_build_info ); - unit_test_log.header( test->size() ); - test->run(); - unit_test_log.finish( test->size() ); - - // report results - unit_test_result::instance().report( report_level, std::cerr ); - - // return code - return no_result_code ? boost::exit_success : unit_test_result::instance().result_code(); -} +#include // *************************************************************************** // Revision History : -// +// // $Log$ -// Revision 1.18 2005/01/19 16:34:07 vawjr -// Changed the \r\r\n back to \r\n on windows so we don't get errors when compiling -// on VC++8.0. I don't know why Microsoft thinks it's a good idea to call this an error, -// but they do. I also don't know why people insist on checking out files on Windows and -// copying them to a unix system to check them in (which will cause exactly this problem) +// Revision 1.19 2005/01/22 19:26:37 rogeeff +// implementation moved into headers section to eliminate dependency of included/minimal component on src directory // -// Revision 1.17 2005/01/18 08:30:08 rogeeff -// unit_test_log rework: -// eliminated need for ::instance() -// eliminated need for << end and ...END macro -// straitend interface between log and formatters -// change compiler like formatter name -// minimized unit_test_log interface and reworked to use explicit calls -// -// Revision 1.16 2004/06/07 07:34:23 rogeeff -// detail namespace renamed -// -// Revision 1.15 2004/05/21 06:26:10 rogeeff -// licence update -// -// Revision 1.14 2004/05/11 11:05:04 rogeeff -// basic_cstring introduced and used everywhere -// class properties reworked -// namespace names shortened -// -// Revision 1.13 2003/12/01 00:42:37 rogeeff -// prerelease cleaning -// - // *************************************************************************** // EOF diff --git a/src/unit_test_monitor.cpp b/src/unit_test_monitor.cpp index 4d107c94..05fa9b17 100644 --- a/src/unit_test_monitor.cpp +++ b/src/unit_test_monitor.cpp @@ -1,7 +1,6 @@ -// (C) Copyright Gennadiy Rozental 2001-2004. -// (C) Copyright Ullrich Koethe 2001. +// (C) Copyright Gennadiy Rozental 2005. // Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at +// (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) // See http://www.boost.org/libs/test for the library home page. @@ -10,119 +9,18 @@ // // Version : $Revision$ // -// Description : implements specific subclass of Executon Monitor used by Unit -// Test Framework to monitor test cases run. +// Description : forwarding source // *************************************************************************** -// Boost.Test -#include -#include -#include -#include -#include - -namespace boost { - -namespace unit_test { - -namespace ut_detail { - -// ************************************************************************** // -// ************** unit_test_monitor ************** // -// ************************************************************************** // - -bool unit_test_monitor::s_catch_system_errors = true; - -unit_test_monitor::error_level -unit_test_monitor::execute_and_translate( test_case* target_test_case, function_to_monitor f, int timeout ) -{ - m_test_case = target_test_case; - m_test_case_method = f; - - try { - execute( s_catch_system_errors, timeout ); - } - catch( execution_exception const& exex ) { - log_level loglevel = - exex.code() <= execution_exception::cpp_exception_error ? log_cpp_exception_errors : - (exex.code() <= execution_exception::timeout_error ? log_system_errors : - log_fatal_errors); - unit_test_log.log_exception( loglevel, exex.what() ); - - unit_test_result::instance().caught_exception(); - - // translate execution_exception::error_code to error_level - switch( exex.code() ) { - case execution_exception::no_error: return test_ok; - case execution_exception::user_error: return unexpected_exception; - case execution_exception::cpp_exception_error: return unexpected_exception; - case execution_exception::system_error: return os_exception; - case execution_exception::timeout_error: return os_timeout; - case execution_exception::user_fatal_error: - case execution_exception::system_fatal_error: return fatal_error; - default: return unexpected_exception; - } - } - - return test_ok; -} - -//____________________________________________________________________________// - -int -unit_test_monitor::function() -{ - try { - (m_test_case->*m_test_case_method)(); - } - catch( test_tools::tt_detail::test_tool_failed const& /*e*/ ) { // e not used; error already reported - // nothing to do - } - - return 0; -} - -//____________________________________________________________________________// - -} // namespace ut_detail - -} // namespace unit_test - -} // namespace boost +#include // *************************************************************************** // Revision History : -// +// // $Log$ -// Revision 1.17 2005/01/19 16:34:07 vawjr -// Changed the \r\r\n back to \r\n on windows so we don't get errors when compiling -// on VC++8.0. I don't know why Microsoft thinks it's a good idea to call this an error, -// but they do. I also don't know why people insist on checking out files on Windows and -// copying them to a unix system to check them in (which will cause exactly this problem) +// Revision 1.18 2005/01/22 19:26:37 rogeeff +// implementation moved into headers section to eliminate dependency of included/minimal component on src directory // -// Revision 1.16 2005/01/18 08:30:08 rogeeff -// unit_test_log rework: -// eliminated need for ::instance() -// eliminated need for << end and ...END macro -// straitend interface between log and formatters -// change compiler like formatter name -// minimized unit_test_log interface and reworked to use explicit calls -// -// Revision 1.15 2004/06/07 07:34:23 rogeeff -// detail namespace renamed -// -// Revision 1.14 2004/05/21 06:26:10 rogeeff -// licence update -// -// Revision 1.13 2004/05/11 11:05:04 rogeeff -// basic_cstring introduced and used everywhere -// class properties reworked -// namespace names shortened -// -// Revision 1.12 2003/12/01 00:42:37 rogeeff -// prerelease cleaning -// - // *************************************************************************** // EOF diff --git a/src/unit_test_parameters.cpp b/src/unit_test_parameters.cpp index 72dc69b1..0c4de87d 100644 --- a/src/unit_test_parameters.cpp +++ b/src/unit_test_parameters.cpp @@ -1,4 +1,4 @@ -// (C) Copyright Gennadiy Rozental 2001-2004. +// (C) Copyright Gennadiy Rozental 2005. // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) @@ -9,102 +9,18 @@ // // Version : $Revision$ // -// Description : simple implementation for Unit Test Framework parameter -// handling routines. May be rewritten in future to use some kind of -// command-line arguments parsing facility and environment variable handling -// facility +// Description : forwarding source // *************************************************************************** -// Boost.Test -#include -#include -#include - -//BOOST -#include // for broken compiler workarounds -#include -#include - -# ifdef BOOST_NO_STDC_NAMESPACE -namespace std { using ::getenv; using ::strncmp; using ::strcmp; } -# endif - -namespace boost { - -namespace unit_test { - -const_string -retrieve_framework_parameter( const_string parameter_name, int* argc, char** argv ) -{ - static fixed_mapping parameter_2_cla_name_map( - LOG_LEVEL , "--log_level", - NO_RESULT_CODE , "--result_code", - REPORT_LEVEL , "--report_level", - TESTS_TO_RUN , "--run_test", - SAVE_TEST_PATTERN , "--save_pattern", - BUILD_INFO , "--build_info", - CATCH_SYS_ERRORS , "--catch_system_errors", - REPORT_FORMAT , "--report_format", - LOG_FORMAT , "--log_format", - OUTPUT_FORMAT , "--output_format", - - "" - ); - - // first try to find parameter among command line arguments if present - if( argc ) { - // locate corresponding cla name - const_string cla_name = parameter_2_cla_name_map[parameter_name]; - - if( !cla_name.is_empty() ) { - for( int i = 1; i < *argc; ++i ) { - if( cla_name == const_string( argv[i], cla_name.size() ) && - argv[i][cla_name.size()] == '=' ) { - const_string result = argv[i] + cla_name.size() + 1; - - for( int j = i; j < *argc; ++j ) { - argv[j] = argv[j+1]; - } - --(*argc); - - return result; - } - } - } - } - - return std::getenv( parameter_name.begin() ); -} - -//____________________________________________________________________________// - -} // namespace unit_test - -} // namespace boost +#include // *************************************************************************** // Revision History : // // $Log$ -// Revision 1.15 2004/05/21 06:26:10 rogeeff -// licence update +// Revision 1.16 2005/01/22 19:26:37 rogeeff +// implementation moved into headers section to eliminate dependency of included/minimal component on src directory // -// Revision 1.14 2004/05/18 13:34:15 dgregor -// Needed to include to get std::getenv. -// -// Revision 1.13 2004/05/13 09:04:43 rogeeff -// added fixed_mapping -// -// Revision 1.12 2004/05/11 11:05:04 rogeeff -// basic_cstring introduced and used everywhere -// class properties reworked -// namespace names shortened -// -// Revision 1.11 2003/12/01 00:42:37 rogeeff -// prerelease cleaning -// - // *************************************************************************** // EOF - diff --git a/src/unit_test_result.cpp b/src/unit_test_result.cpp index bfdb92f1..d589259d 100644 --- a/src/unit_test_result.cpp +++ b/src/unit_test_result.cpp @@ -1,4 +1,4 @@ -// (C) Copyright Gennadiy Rozental 2001-2004. +// (C) Copyright Gennadiy Rozental 2005. // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) @@ -9,639 +9,18 @@ // // Version : $Revision$ // -// Description : implements Unit Test Result reporting facility. Note that majority of -// implementation is hidden in this file using pimple idiom. +// Description : forwarding source // *************************************************************************** -// Boost.Test -#include -#include -#include -#include -#include -#include - -// BOOST -#include -#include -#include - -// STL -#include -#include -#include -#include -#include -#include -#include - -# ifdef BOOST_NO_STDC_NAMESPACE -namespace std { using ::log10; using ::strncmp; } -# endif - -namespace boost { - -namespace unit_test { - -#if !defined(BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP) && !BOOST_WORKAROUND(__BORLANDC__, < 0x564) -using ut_detail::attr_value; -#endif - -typedef unit_test_result* unit_test_result_ptr; - -// ************************************************************************** // -// ************** report_formatter ************** // -// ************************************************************************** // - -class report_formatter { -public: - // Destructor - virtual ~report_formatter() {} - - virtual void start_result_report( std::ostream& where_to ) = 0; - virtual void finish_result_report( std::ostream& where_to ) = 0; - - virtual void start_test_case_report( std::ostream& where_to, std::size_t indent, - const_string test_case_name, bool case_suite, bool failed ) = 0; - - virtual void start_confirmation_report( std::ostream& where_to, - const_string test_case_name, bool case_suite, bool failed, - unit_test_counter num_failed, unit_test_counter num_expected ) = 0; - - virtual void finish_test_case_report( std::ostream& where_to, std::size_t indent, - const_string test_case_name, bool case_suite, bool aborted ) = 0; - - virtual void report_sub_test_cases_stat( std::ostream& where_to, std::size_t indent, - unit_test_counter num_passed, unit_test_counter num_failed ) = 0; - - virtual void report_assertions_stat( std::ostream& where_to, std::size_t indent, - unit_test_counter num_passed, - unit_test_counter num_failed, - unit_test_counter num_expected ) = 0; - -}; - -//____________________________________________________________________________// - -// ************************************************************************** // -// ************** hrf_report_formatter ************** // -// ************************************************************************** // - -class hrf_report_formatter : public report_formatter { - struct quote { - explicit quote( const_string str ) : m_str( str ) {} - - friend std::ostream& operator<<( std::ostream& os, quote const& q ) - { - return os << '"' << q.m_str << '"'; - } - - private: - const_string m_str; - }; -public: - void start_result_report( std::ostream& /* where_to */ ) {} - void finish_result_report( std::ostream& /* where_to */ ) {} - - void start_test_case_report( std::ostream& where_to, std::size_t indent, - const_string test_case_name, bool case_suite, bool failed ) - { - where_to << "\n" << std::setw( indent ) << "" << "Test " << cs_name( case_suite ) << " " << quote( test_case_name ) - << (failed ? " failed with:\n" : " passed with:\n"); - - } - - void start_confirmation_report( std::ostream& where_to, - const_string test_case_name, bool case_suite, bool failed, - unit_test_counter num_failed, unit_test_counter num_expected ) - { - if( failed ) { - if( num_failed == 0 ) { - where_to << "\n*** errors detected in test " << cs_name( case_suite ) << " " << quote( test_case_name ) - << "; see standard output for details\n"; - return; - } - - - where_to << "\n*** " << num_failed << ps_name( num_failed != 1, " failure" ) << " detected"; - - if( num_expected > 0 ) - where_to << " (" << num_expected << ps_name( num_expected != 1, " failure" ) << " expected)"; - - where_to << " in test " << cs_name( case_suite ) << " " << quote( test_case_name ) << "\n"; - } - else - where_to << "\n*** No errors detected\n"; - } - - void finish_test_case_report( std::ostream& where_to, std::size_t indent, - const_string test_case_name, bool case_suite, bool aborted ) - { - if( aborted ) - where_to << std::setw( indent ) << "" << "Test " << cs_name( case_suite ) << " " << quote( test_case_name ) - << " was aborted due to uncaught exception, user assert or system error\n"; - - where_to.flush(); - } - - void report_sub_test_cases_stat( std::ostream& where_to, std::size_t indent, - unit_test_counter num_passed, unit_test_counter num_failed ) - { - unit_test_counter total_test_cases = num_passed + num_failed; - std::size_t width = static_cast( std::log10( (float)(std::max)( num_passed, num_failed ) ) ) + 1; - - where_to << std::setw( indent ) << "" << std::setw( width ) << num_passed - << " test " << ps_name( num_passed != 1, "case" ) << " out of " << total_test_cases << " passed\n" - << std::setw( indent ) << "" << std::setw( width ) << num_failed - << " test " << ps_name( num_failed != 1, "case" ) << " out of " << total_test_cases << " failed\n"; - - } - - void report_assertions_stat( std::ostream& where_to, std::size_t indent, - unit_test_counter num_passed, unit_test_counter num_failed, unit_test_counter num_expected ) - { - unit_test_counter total_assertions = num_passed + num_failed; - std::size_t width = total_assertions > 0 - ? static_cast( std::log10( (float)(std::max)( num_passed, num_failed ) ) ) + 1 - : 1; - - where_to << std::setw( indent ) << "" << std::setw( width ) << num_passed - << ps_name( num_passed != 1, " assertion" ) << " out of " << total_assertions << " passed\n" - << std::setw( indent ) << "" << std::setw( width ) << num_failed - << ps_name( num_failed != 1, " assertion" ) << " out of " << total_assertions << " failed\n"; - - if( num_expected > 0 ) - where_to << std::setw( indent ) << "" << "while " << num_expected - << ps_name( num_expected != 1, " failure" ) << " expected\n"; - } - -private: - static std::string ps_name( bool p_s, std::string singular_form ) - { - return p_s ? singular_form.append( "s" ) : singular_form; - } - static std::string cs_name( bool c_s ) - { - return c_s ? "case" : "suite"; - } -}; - -// ************************************************************************** // -// ************** xml_report_formatter ************** // -// ************************************************************************** // - -class xml_report_formatter : public report_formatter { -public: - void start_result_report( std::ostream& where_to ) - { - where_to << "\n"; - } - void finish_result_report( std::ostream& where_to ) - { - where_to << "\n"; - } - - void start_test_case_report( std::ostream& where_to, std::size_t indent, - const_string test_case_name, bool case_suite, bool failed ) - { - where_to << std::setw( indent ) << "" - << "<" << ( case_suite ? "TestCase" : "TestSuite" ) - << " name" << attr_value() << test_case_name - << " result" << attr_value() << (failed ? "failed" : "passed") << ">\n"; - } - - void start_confirmation_report( std::ostream& where_to, - const_string test_case_name, bool case_suite, bool failed, - unit_test_counter num_failed, unit_test_counter num_expected ) - { - where_to << "<" << ( case_suite ? "TestCase" : "TestSuite" ) - << " name" << attr_value() << test_case_name - << " result" << attr_value() << (failed ? "failed" : "passed"); - - if( failed ) { - where_to << " num_of_failures" << attr_value() << num_failed - << " expected_failures" << attr_value() << num_expected; - } - - where_to << ">\n"; - } - - void finish_test_case_report( std::ostream& where_to, std::size_t indent, - const_string /* test_case_name */, bool case_suite, bool aborted ) - { - if( aborted ) { - where_to << std::setw( indent+2 ) << "" - << "<" << "aborted" - << " reason" << attr_value() << "due to uncaught exception, user assert or system error" - << "/>\n"; - } - - where_to << std::setw( indent ) << "" - << "\n"; - } - - void report_sub_test_cases_stat( std::ostream& where_to, std::size_t indent, - unit_test_counter num_passed, unit_test_counter num_failed ) - { - where_to << std::setw( indent+2 ) << "" - << "\n"; - } - - void report_assertions_stat( std::ostream& where_to, std::size_t indent, - unit_test_counter num_passed, - unit_test_counter num_failed, - unit_test_counter num_expected ) - { - where_to << std::setw( indent+2 ) << "" - << "\n"; - } -}; - -// ************************************************************************** // -// ************** unit_test_result ************** // -// ************************************************************************** // - -struct unit_test_result::Impl { - unit_test_result_ptr m_parent; - std::list m_children; - unit_test_counter m_assertions_passed; - unit_test_counter m_assertions_failed; - unit_test_counter m_expected_failures; - unit_test_counter m_test_cases_passed; - unit_test_counter m_test_cases_failed; - bool m_exception_caught; - std::string m_test_case_name; - - static boost::scoped_ptr m_head; - static unit_test_result_ptr m_curr; - static boost::scoped_ptr m_report_formatter; - - bool has_failed() - { - return m_test_cases_failed != 0 || m_assertions_failed != m_expected_failures || m_exception_caught; - } - int result_code() - { - return has_failed() - ? ( (m_assertions_failed != 0) - ? boost::exit_test_failure - : boost::exit_exception_failure ) - : boost::exit_success; - } -}; - -boost::scoped_ptr unit_test_result::Impl::m_head; -unit_test_result_ptr unit_test_result::Impl::m_curr = unit_test_result_ptr(); -boost::scoped_ptr unit_test_result::Impl::m_report_formatter( new hrf_report_formatter ); - -//____________________________________________________________________________// - -unit_test_result::unit_test_result( unit_test_result_ptr parent, const_string test_case_name, unit_test_counter exp_fail ) -: m_pimpl( new Impl ) -{ - m_pimpl->m_parent = parent; - test_case_name.assign_to( m_pimpl->m_test_case_name ); - - m_pimpl->m_assertions_passed = 0; - m_pimpl->m_assertions_failed = 0; - m_pimpl->m_expected_failures = exp_fail; - m_pimpl->m_test_cases_passed = 0; - m_pimpl->m_test_cases_failed = 0; - m_pimpl->m_exception_caught = false; - -} - -//____________________________________________________________________________// - -static void safe_delete( unit_test_result_ptr ptr ) { boost::checked_delete( ptr ); } - -unit_test_result::~unit_test_result() -{ - std::list::iterator beg = m_pimpl->m_children.begin(); - std::list::iterator end = m_pimpl->m_children.end(); - - std::for_each( beg, end, &safe_delete ); -} - -//____________________________________________________________________________// - -unit_test_result& -unit_test_result::instance() -{ - assert( !!Impl::m_head ); - - return Impl::m_curr ? *Impl::m_curr : *Impl::m_head; -} - -//____________________________________________________________________________// - -void -unit_test_result::test_case_start( const_string name, unit_test_counter expected_failures ) -{ - unit_test_result_ptr new_test_case_result_inst = new unit_test_result( Impl::m_curr, name, expected_failures ); - - if( Impl::m_curr ) - Impl::m_curr->m_pimpl->m_children.push_back( new_test_case_result_inst ); - else - Impl::m_head.reset( new_test_case_result_inst ); - - Impl::m_curr = new_test_case_result_inst; -} - -//____________________________________________________________________________// - -void -unit_test_result::test_case_end() -{ - assert( !!Impl::m_curr ); - - Impl* curr_impl = Impl::m_curr->m_pimpl.get(); - unit_test_result_ptr parent = curr_impl->m_parent; - - if( parent ) { - // accumulate results - parent->m_pimpl->m_assertions_passed += curr_impl->m_assertions_passed; - parent->m_pimpl->m_assertions_failed += curr_impl->m_assertions_failed; - parent->m_pimpl->m_test_cases_passed += curr_impl->m_test_cases_passed; - parent->m_pimpl->m_test_cases_failed += curr_impl->m_test_cases_failed; - - // for test_cases (vs. test_suite) //!! need better identification - if( curr_impl->m_test_cases_passed == 0 && curr_impl->m_test_cases_failed == 0 ) { - if( curr_impl->has_failed() ) - parent->m_pimpl->m_test_cases_failed++; - else - parent->m_pimpl->m_test_cases_passed++; - } - - } - - Impl::m_curr = parent; -} - -//____________________________________________________________________________// - -struct report_format_name_map : std::map -{ - report_format_name_map() { - } -}; - -void -unit_test_result::set_report_format( const_string report_format_name ) -{ - static fixed_mapping > report_format( - "HRF", HRF, - "XML", XML, - - HRF - ); - - if( report_format[report_format_name] == HRF ) - Impl::m_report_formatter.reset( new hrf_report_formatter ); - else - Impl::m_report_formatter.reset( new xml_report_formatter ); -} - -//____________________________________________________________________________// - -void -unit_test_result::increase_expected_failures( unit_test_counter amount ) -{ - m_pimpl->m_expected_failures += amount; - - if( m_pimpl->m_parent ) - m_pimpl->m_parent->increase_expected_failures( amount ); -} - -//____________________________________________________________________________// - -void -unit_test_result::inc_failed_assertions() -{ - m_pimpl->m_assertions_failed++; - - if( m_pimpl->m_assertions_failed == 1 ) - first_failed_assertion(); -} - -//____________________________________________________________________________// - -void -unit_test_result::inc_passed_assertions() -{ - m_pimpl->m_assertions_passed++; -} - -//____________________________________________________________________________// - -void -unit_test_result::caught_exception() -{ - m_pimpl->m_exception_caught = true; -} - -//____________________________________________________________________________// - -const_string -unit_test_result::test_case_name() -{ - return m_pimpl->m_test_case_name; -} - -//____________________________________________________________________________// - -void -unit_test_result::reset_current_result_set() -{ - static unit_test_result_ptr backup = unit_test_result_ptr(); - static boost::scoped_ptr temporary_substitute; - - assert( !!Impl::m_curr ); - - if( backup ) { - Impl::m_curr = backup; - backup = unit_test_result_ptr(); - temporary_substitute.reset(); - } - else { - backup = Impl::m_curr; - Impl::m_curr = new unit_test_result( NULL, Impl::m_curr->test_case_name(), 0 ); - temporary_substitute.reset( Impl::m_curr ); - } -} - -//____________________________________________________________________________// - -void -unit_test_result::failures_details( unit_test_counter& num_of_failures, bool& exception_caught ) -{ - num_of_failures = m_pimpl->m_assertions_failed; - exception_caught = m_pimpl->m_exception_caught; -} - -//____________________________________________________________________________// - -void -unit_test_result::report( const_string reportlevel, std::ostream& where_to_ ) -{ - static int const map_size = sizeof(report_level_names)/sizeof(const_string); - - report_level rl = UNDEF_REPORT; - if( reportlevel.empty() ) - rl = CONFIRMATION_REPORT; - else { - for( int i = 0; i < map_size; i++ ) { - if( reportlevel == report_level_names[i] ) { - rl = (report_level)i; - break; - } - } - } - - switch( rl ) { - case CONFIRMATION_REPORT: - confirmation_report( where_to_ ); - break; - case SHORT_REPORT: - case DETAILED_REPORT: - m_pimpl->m_report_formatter->start_result_report( where_to_ ); - report_result( where_to_, 0, rl == DETAILED_REPORT ); - m_pimpl->m_report_formatter->finish_result_report( where_to_ ); - break; - case NO_REPORT: - break; - default: - where_to_ << "*** Unrecognized report level" << std::endl; - break; - } -} - -//____________________________________________________________________________// - -void -unit_test_result::confirmation_report( std::ostream& where_to ) -{ - assert( !!this ); - - m_pimpl->m_report_formatter->start_result_report( where_to ); - - m_pimpl->m_report_formatter->start_confirmation_report( where_to, - m_pimpl->m_test_case_name, m_pimpl->m_children.empty(), - m_pimpl->m_test_cases_failed != 0 || m_pimpl->has_failed(), - m_pimpl->m_assertions_failed, m_pimpl->m_expected_failures ); - - m_pimpl->m_report_formatter->finish_test_case_report( where_to, 0, - m_pimpl->m_test_case_name, m_pimpl->m_children.empty(), - m_pimpl->m_exception_caught ); - - m_pimpl->m_report_formatter->finish_result_report( where_to ); -} - -//____________________________________________________________________________// - -void -unit_test_result::report_result( std::ostream& where_to, std::size_t indent, bool detailed ) -{ - assert( !!this ); - - m_pimpl->m_report_formatter->start_test_case_report( where_to, indent, - m_pimpl->m_test_case_name, m_pimpl->m_children.empty(), - m_pimpl->m_test_cases_failed != 0 || m_pimpl->has_failed() ); - - if( m_pimpl->m_test_cases_passed + m_pimpl->m_test_cases_failed > 1 ) - m_pimpl->m_report_formatter->report_sub_test_cases_stat( where_to, indent, - m_pimpl->m_test_cases_passed, m_pimpl->m_test_cases_failed ); - - m_pimpl->m_report_formatter->report_assertions_stat( where_to, indent, - m_pimpl->m_assertions_passed, - m_pimpl->m_assertions_failed, - m_pimpl->m_expected_failures ); - - if( detailed ) { - std::list::iterator it = m_pimpl->m_children.begin(); - std::list::iterator end = m_pimpl->m_children.end(); - - while( it != end ) { - unit_test_result_ptr next = *(it++); - next->report_result( where_to, indent+2, true ); - } - } - - m_pimpl->m_report_formatter->finish_test_case_report( where_to, indent, - m_pimpl->m_test_case_name, m_pimpl->m_children.empty(), - m_pimpl->m_exception_caught ); -} - -//____________________________________________________________________________// - -int -unit_test_result::result_code() const -{ - return m_pimpl->result_code(); -} - -//____________________________________________________________________________// - -bool -unit_test_result::has_passed() const -{ - return !m_pimpl->has_failed(); -} - -//____________________________________________________________________________// - -} // namespace unit_test - -} // namespace boost +#include // *************************************************************************** // Revision History : // // $Log$ -// Revision 1.32 2005/01/21 07:26:41 rogeeff -// xml printing helpers reworked to employ generic custom manipulators +// Revision 1.33 2005/01/22 19:26:37 rogeeff +// implementation moved into headers section to eliminate dependency of included/minimal component on src directory // -// Revision 1.31 2004/09/17 12:34:13 rogeeff -// XML typo -// -// Revision 1.30 2004/08/10 04:02:18 rogeeff -// first tru64cxx65 fix -// -// Revision 1.29 2004/07/19 12:10:56 rogeeff -// added proper encoded of XML PCDATA -// min->max bug fix -// -// Revision 1.28 2004/06/29 04:33:20 rogeeff -// use std::min -// -// Revision 1.27 2004/06/23 04:49:48 eric_niebler -// remove std_min and std_max, update minmax coding guidelines -// -// Revision 1.26 2004/05/21 06:26:10 rogeeff -// licence update -// -// Revision 1.25 2004/05/13 09:04:44 rogeeff -// added fixed_mapping -// -// Revision 1.24 2004/05/11 11:05:04 rogeeff -// basic_cstring introduced and used everywhere -// class properties reworked -// namespace names shortened -// -// Revision 1.23 2004/02/26 18:27:02 eric_niebler -// remove minmax hack from win32.hpp and fix all places that could be affected by the minmax macros -// -// Revision 1.22 2003/12/01 00:42:37 rogeeff -// prerelease cleaning -// - // *************************************************************************** // EOF diff --git a/src/unit_test_suite.cpp b/src/unit_test_suite.cpp index 72d07682..e83ba292 100644 --- a/src/unit_test_suite.cpp +++ b/src/unit_test_suite.cpp @@ -1,4 +1,4 @@ -// (C) Copyright Gennadiy Rozental 2001-2004. +// (C) Copyright Gennadiy Rozental 2005. // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) @@ -9,326 +9,18 @@ // // Version : $Revision$ // -// Description : privide core implementation for Unit Test Framework. -// Extensions could be provided in separate files +// Description : forwarding source // *************************************************************************** -// Boost.Test -#include -#include -#include -#include - -// BOOST -#include -#include - -// STL -#include -#include - -#include - -namespace boost { - -namespace unit_test { - -// ************************************************************************** // -// ************** test_case_scope_tracker ************** // -// ************************************************************************** // - -struct test_case_scope_tracker { - explicit test_case_scope_tracker( test_case const& tc ) - : m_tc( tc ) - { - unit_test_log.track_test_case_enter( m_tc ); - } - ~test_case_scope_tracker() - { - unit_test_log.track_test_case_exit( m_tc, (long)(m_timer.elapsed() * 1e6) ); - } - -private: - test_case const& m_tc; - boost::timer m_timer; -}; - -// ************************************************************************** // -// ************** test_case ************** // -// ************************************************************************** // - -ut_detail::unit_test_monitor the_monitor; - -typedef unit_test_result const* unit_test_result_cptr; - -struct test_case::Impl { - Impl( bool monitor_run_ ) : m_monitor_run( monitor_run_ ), m_results_set( unit_test_result_cptr() ) {} - - bool m_monitor_run; // true - unit_test_monitor will be user to monitor running - // of implementation function - std::list m_dependencies_list; // list of test cases this test case depends on. We won't run it until they pass - unit_test_result_cptr m_results_set; // results set instance reference for this test case - - static bool s_abort_testing; // used to flag critical error and try gracefully stop testing - - bool check_dependencies(); -}; - -bool test_case::Impl::s_abort_testing = false; - -//____________________________________________________________________________// - - -inline bool -test_case::Impl::check_dependencies() -{ - return std::find_if( m_dependencies_list.begin(), - m_dependencies_list.end(), - std::not1( boost::mem_fn( &test_case::has_passed ) ) ) == m_dependencies_list.end(); -} - -//____________________________________________________________________________// - -test_case::test_case( const_string name_, bool type, unit_test_counter stages_amount_, bool monitor_run_ ) -: p_timeout( 0 ), p_expected_failures( 0 ), p_type( type ), - p_name( std::string( name_.begin(), name_.end() ) ), - p_compound_stage( false ), p_stages_amount( stages_amount_ ), - m_pimpl( new Impl( monitor_run_ ) ) -{ -} - -//____________________________________________________________________________// - -unit_test_counter -test_case::size() const -{ - return 1; -} - -//____________________________________________________________________________// - -void -test_case::depends_on( test_case const* rhs ) -{ - m_pimpl->m_dependencies_list.push_back( rhs ); -} - -//____________________________________________________________________________// - -bool -test_case::has_passed() const -{ - return m_pimpl->m_results_set != unit_test_result_cptr() && m_pimpl->m_results_set->has_passed(); -} - -//____________________________________________________________________________// - -void -test_case::run() -{ - using ut_detail::unit_test_monitor; - - test_case_scope_tracker scope_tracker( *this ); - - // 0. Check if we allowed to run this test case - if( !m_pimpl->check_dependencies() ) - return; - - m_pimpl->s_abort_testing = false; - - // 1. Init test results - unit_test_result_tracker result_tracker( p_name.get(), p_expected_failures ); - m_pimpl->m_results_set = &unit_test_result::instance(); - - // 2. Initialize test case - if( m_pimpl->m_monitor_run ) { - error_level_type setup_result = - the_monitor.execute_and_translate( this, &test_case::do_init, p_timeout ); - - if( setup_result != unit_test_monitor::test_ok ) { - m_pimpl->s_abort_testing = unit_test_monitor::is_critical_error( setup_result ); - - BOOST_UT_LOG_ENTRY( log_fatal_errors ) << "Test case setup has failed"; - - return; - } - } - else { - do_init(); - } - - // 3. Run test case (all stages) - for( unit_test_counter i=0; i != p_stages_amount; ++i ) { - p_compound_stage.value = false; // could be set by do_run to mark compound stage; - // than no need to report progress here - - if( m_pimpl->m_monitor_run ) { - error_level_type run_result = - the_monitor.execute_and_translate( this, &test_case::do_run, p_timeout ); - - if( unit_test_monitor::is_critical_error( run_result ) ) { - m_pimpl->s_abort_testing = true; - - BOOST_UT_LOG_ENTRY( log_fatal_errors ) << "Testing aborted"; - } - - if( m_pimpl->s_abort_testing ) - return; - } - else { - do_run(); - } - - if( p_stages_amount != 1 && !p_compound_stage ) // compound test - unit_test_log.log_progress(); - } - - // 3. Finalize test case - if( m_pimpl->m_monitor_run ) { - error_level_type teardown_result = - the_monitor.execute_and_translate( this, &test_case::do_destroy, p_timeout ); - - m_pimpl->s_abort_testing = unit_test_monitor::is_critical_error( teardown_result ); - } - else { - do_destroy(); - } -} - -//____________________________________________________________________________// - -// ************************************************************************** // -// ************** test_suite ************** // -// ************************************************************************** // - -struct test_suite::Impl { - std::list m_test_cases; - std::list::iterator m_curr_test_case; - unit_test_counter m_cumulative_size; -}; - -//____________________________________________________________________________// - -test_suite::test_suite( const_string name ) -: test_case( name, false, 0, false ), m_pimpl( new Impl ) -{ - m_pimpl->m_cumulative_size = 0; -} - -//____________________________________________________________________________// - -static void safe_delete_test_case( test_case* ptr ) { boost::checked_delete( ptr ); } - -test_suite::~test_suite() -{ - std::for_each( m_pimpl->m_test_cases.begin(), m_pimpl->m_test_cases.end(), &safe_delete_test_case ); -} - -//____________________________________________________________________________// - -void -test_suite::add( test_case* tc, unit_test_counter exp_fail, int timeout ) -{ - if( exp_fail != 0 ) { - tc->p_expected_failures.value = exp_fail; - } - - p_expected_failures.value += tc->p_expected_failures; - - if( timeout != 0 ) - tc->p_timeout.value = timeout; - - m_pimpl->m_test_cases.push_back( tc ); - m_pimpl->m_cumulative_size += tc->size(); - - p_stages_amount.value = p_stages_amount + 1; -} - -//____________________________________________________________________________// - -unit_test_counter -test_suite::size() const -{ - return m_pimpl->m_cumulative_size; -} - -//____________________________________________________________________________// - -void -test_suite::do_init() -{ - m_pimpl->m_curr_test_case = m_pimpl->m_test_cases.begin(); -} - -//____________________________________________________________________________// - -void -test_suite::do_run() -{ - if( (*m_pimpl->m_curr_test_case)->size() > 1 ) - p_compound_stage.value = true; - (*m_pimpl->m_curr_test_case)->run(); - ++m_pimpl->m_curr_test_case; -} - -//____________________________________________________________________________// - -// ************************************************************************** // -// ************** object generators ************** // -// ************************************************************************** // - -namespace ut_detail { - -std::string const& -normalize_test_case_name( std::string& name_ ) -{ - if( name_[0] == '&' ) - name_.erase( 0, 1 ); - - return name_; -} - -} // namespace ut_detail - -} // namespace unit_test - -} // namespace boost - -#include +#include // *************************************************************************** // Revision History : // // $Log$ -// Revision 1.19 2005/01/21 07:26:41 rogeeff -// xml printing helpers reworked to employ generic custom manipulators +// Revision 1.20 2005/01/22 19:26:38 rogeeff +// implementation moved into headers section to eliminate dependency of included/minimal component on src directory // -// Revision 1.17 2005/01/18 08:30:08 rogeeff -// unit_test_log rework: -// eliminated need for ::instance() -// eliminated need for << end and ...END macro -// straitend interface between log and formatters -// change compiler like formatter name -// minimized unit_test_log interface and reworked to use explicit calls -// -// Revision 1.16 2004/06/07 07:34:23 rogeeff -// detail namespace renamed -// -// Revision 1.15 2004/05/21 06:26:10 rogeeff -// licence update -// -// Revision 1.14 2004/05/18 13:26:47 dgregor -// unit_test_suite.cpp: Try to work around an Intel 7.1 bug with conversions in a base class. -// -// Revision 1.13 2004/05/11 11:05:04 rogeeff -// basic_cstring introduced and used everywhere -// class properties reworked -// namespace names shortened -// -// Revision 1.12 2003/12/01 00:42:37 rogeeff -// prerelease cleaning -// - // *************************************************************************** // EOF