stdcpp/tsrc/Boost_test/test_framework/src/execution_monitor.cpp
changeset 0 e4d67989cc36
equal deleted inserted replaced
-1:000000000000 0:e4d67989cc36
       
     1 //  (C) Copyright Gennadiy Rozental 2001-2005.
       
     2 //  (C) Copyright Beman Dawes and Ullrich Koethe 1995-2001.
       
     3 //  Use, modification, and distribution are subject to the
       
     4 //  Boost Software License, Version 1.0. (See accompanying file
       
     5 //  http://www.boost.org/LICENSE_1_0.txt)
       
     6 
       
     7 //  See http://www.boost.org/libs/test for the library home page.
       
     8 //
       
     9 //  File        : $RCSfile: execution_monitor.ipp,v $
       
    10 //
       
    11 //  Version     : $Revision: 1.13 $
       
    12 //
       
    13 //  Description : provides execution monitor implementation for all supported
       
    14 //  configurations, including Microsoft structured exception based, unix signals
       
    15 //  based and special workarounds for borland
       
    16 //
       
    17 //  Note that when testing requirements or user wishes preclude use of this
       
    18 //  file as a separate compilation unit, it may be included as a header file.
       
    19 //
       
    20 //  Header dependencies are deliberately restricted to reduce coupling to other
       
    21 //  boost libraries.
       
    22 // ***************************************************************************
       
    23 /*
       
    24  * © Portions copyright (c) 2006-2007 Nokia Corporation.  All rights reserved.
       
    25 */
       
    26 
       
    27 #ifndef BOOST_TEST_EXECUTION_MONITOR_IPP_012205GER
       
    28 #define BOOST_TEST_EXECUTION_MONITOR_IPP_012205GER
       
    29 
       
    30 // Boost.Test
       
    31 #include <boost/test/detail/config.hpp>
       
    32 #include <boost/test/detail/workaround.hpp>
       
    33 #include <boost/test/execution_monitor.hpp>
       
    34 
       
    35 // Boost
       
    36 #include <boost/cstdlib.hpp>  // for exit codes
       
    37 #include <boost/config.hpp>   // for workarounds
       
    38 
       
    39 // STL
       
    40 #include <string>             // for std::string
       
    41 #include <new>                // for std::bad_alloc
       
    42 #include <typeinfo>           // for std::bad_cast, std::bad_typeid
       
    43 #include <exception>          // for std::exception, std::bad_exception
       
    44 #include <stdexcept>          // for std exception hierarchy
       
    45 #include <cstring>            // for C string API
       
    46 #include <cassert>            // for assert
       
    47 #include <cstddef>            // for NULL
       
    48 
       
    49 #ifdef BOOST_NO_STDC_NAMESPACE
       
    50 namespace std { using ::strlen; using ::strncat; }
       
    51 #endif
       
    52 
       
    53 // Microsoft + other compatible compilers such as Intel
       
    54 
       
    55 #if !defined(BOOST_DISABLE_WIN32) &&                                        \
       
    56     !defined(__BORLANDC__) &&                                               \
       
    57     (defined(_MSC_VER) && !defined(__COMO__)) ||                            \
       
    58     !(defined(__SYMBIAN32__))
       
    59 
       
    60 
       
    61     //(BOOST_WORKAROUND(__MWERKS__, >= 0x3000) && defined(__INTEL__)) &&      \
       
    62 
       
    63 #  define BOOST_MS_STRUCTURED_EXCEPTION_HANDLING
       
    64 
       
    65 #  ifndef _WIN32_WINNT
       
    66 #    ifdef _WINBASE_
       
    67 #      warning Debugger check disabled. Either define _WIN32_WINNT or include Boost.Test header in front of winbase.h
       
    68 #    else
       
    69 #      define BOOST_TEST_DEBUGGER_CHECK
       
    70 #      define _WIN32_WINNT 0x0400
       
    71 #    endif
       
    72 #  endif
       
    73 
       
    74 #  include <wtypes.h>
       
    75 #  include <winbase.h>
       
    76 #  include <excpt.h>
       
    77 #  include <eh.h>
       
    78 
       
    79 #  if !defined(NDEBUG) && !defined(__MWERKS__)  // __MWERKS__ does not seem to supply implementation of C runtime debug hooks, causing linking errors
       
    80 #    define BOOST_MS_CRT_DEBUG_HOOKS
       
    81 #    include <crtdbg.h>
       
    82 #  endif
       
    83 
       
    84 #elif (defined(__BORLANDC__) && defined(_Windows) && !defined(BOOST_DISABLE_WIN32))
       
    85 
       
    86 #  define BOOST_MS_STRUCTURED_EXCEPTION_HANDLING
       
    87 #  include <windows.h>  // Borland 5.5.1 has its own way of doing things.
       
    88 
       
    89 #elif defined(BOOST_HAS_SIGACTION)
       
    90 
       
    91 #  define BOOST_SIGACTION_BASED_SIGNAL_HANDLING
       
    92 
       
    93 #  include <unistd.h>
       
    94 #  include <signal.h>
       
    95 #  include <setjmp.h>
       
    96 
       
    97 #else
       
    98 
       
    99 #  define BOOST_NO_SIGNAL_HANDLING
       
   100 
       
   101 #endif
       
   102 
       
   103 #include <boost/test/detail/suppress_warnings.hpp>
       
   104 
       
   105 //____________________________________________________________________________//
       
   106 
       
   107 namespace boost {
       
   108 
       
   109 namespace detail {
       
   110 
       
   111 using unit_test::const_string;
       
   112 
       
   113 //  boost::execution_monitor::execute() calls boost::detail::report_error(...) to
       
   114 //    report any caught exception and throw execution_exception
       
   115 
       
   116 const std::size_t REPORT_ERROR_BUFFER_SIZE = 512;
       
   117 
       
   118 static void report_error(
       
   119     execution_exception::error_code   ec,
       
   120     const_string                      msg1,         // first part of the message
       
   121     const_string                      msg2 = "" );  // second part of the message; sum length msg1 + msg2 should not
       
   122                                                     // exceed REPORT_ERROR_BUFFER_SIZE; never concatenate messages
       
   123                                                     // manually, cause it should work even in case of memory lack
       
   124 
       
   125 //____________________________________________________________________________//
       
   126 
       
   127 // Declaration for Microsoft structured exception handling (unix alternative - signal)
       
   128 #ifdef BOOST_MS_STRUCTURED_EXCEPTION_HANDLING
       
   129 
       
   130 //  this class defined per the Microsoft structured exception documentation
       
   131 class ms_se_exception {
       
   132 public:
       
   133     // Constructor
       
   134     EXPORT_C explicit        ms_se_exception( unsigned int n )
       
   135     : m_se_id( n )                      {}
       
   136 
       
   137     // Destructor
       
   138                     ~ms_se_exception()  {}
       
   139 
       
   140     // access methods
       
   141    EXPORT_C unsigned int    id() const          { return m_se_id; }
       
   142 
       
   143 private:
       
   144     // Data members
       
   145     unsigned int    m_se_id;
       
   146 };
       
   147 
       
   148 //____________________________________________________________________________//
       
   149 
       
   150 void BOOST_TEST_CALL_DECL ms_se_trans_func( unsigned int id, _EXCEPTION_POINTERS* exps );
       
   151 void BOOST_TEST_CALL_DECL ms_se_forward_func( unsigned int id, _EXCEPTION_POINTERS* exps );
       
   152 static void               report_ms_se_error( unsigned int id );
       
   153 
       
   154 //____________________________________________________________________________//
       
   155 
       
   156 // Declarations for unix-style signal handling
       
   157 #elif defined(BOOST_SIGACTION_BASED_SIGNAL_HANDLING)
       
   158 
       
   159 class unix_signal_exception {
       
   160     typedef execution_exception::error_code error_code_type;
       
   161 public:
       
   162     // Constructor
       
   163    EXPORT_C  unix_signal_exception( execution_exception::error_code ec, const_string em )
       
   164     : m_error_code( ec ), m_error_message( em )             {}
       
   165 
       
   166     // Destructor
       
   167     ~unix_signal_exception()                                {}
       
   168 
       
   169     // access methods
       
   170    EXPORT_C  error_code_type error_code() const      { return m_error_code;    }
       
   171     EXPORT_C const_string    error_message() const   { return m_error_message; }
       
   172 private:
       
   173     // Data members
       
   174     error_code_type m_error_code;
       
   175     const_string    m_error_message;
       
   176 };
       
   177 
       
   178 #endif
       
   179 
       
   180 //____________________________________________________________________________//
       
   181 
       
   182 #if defined(BOOST_MS_CRT_DEBUG_HOOKS)
       
   183 
       
   184 EXPORT_C int
       
   185 assert_reporting_function( int reportType, char* userMessage, int* retVal )
       
   186 {
       
   187     switch( reportType ) {
       
   188     case _CRT_ASSERT:
       
   189         detail::report_error( execution_exception::user_error, userMessage );
       
   190 
       
   191         return 1; // return value and retVal are not important since we never reach this line
       
   192     case _CRT_ERROR:
       
   193         detail::report_error( execution_exception::system_error, userMessage );
       
   194 
       
   195         return 1; // return value and retVal are not important since we never reach this line
       
   196     default:
       
   197         return 0; // use usual reporting method
       
   198     }
       
   199 }
       
   200 
       
   201 #endif
       
   202 
       
   203 } // namespace detail
       
   204 
       
   205 // ************************************************************************** //
       
   206 // **************               execution_monitor              ************** //
       
   207 // ************************************************************************** //
       
   208 
       
   209 EXPORT_C  int
       
   210 execution_monitor::execute( unit_test::callback0<int> const& F, bool catch_system_errors, int timeout )
       
   211 {
       
   212     using unit_test::const_string;
       
   213 
       
   214 # ifdef BOOST_TEST_DEBUGGER_CHECK
       
   215     if( IsDebuggerPresent() )
       
   216         catch_system_errors = false;
       
   217 #endif
       
   218 
       
   219 #if defined(BOOST_MS_STRUCTURED_EXCEPTION_HANDLING) && !defined(__BORLANDC__)
       
   220     if( catch_system_errors )
       
   221         _set_se_translator( detail::ms_se_trans_func );
       
   222     else
       
   223         _set_se_translator( detail::ms_se_forward_func );
       
   224 #endif
       
   225 
       
   226 #ifdef BOOST_MS_CRT_DEBUG_HOOKS
       
   227     if( catch_system_errors )
       
   228         _CrtSetReportHook( &detail::assert_reporting_function );
       
   229 #endif
       
   230 
       
   231     try {
       
   232         return catch_signals( F, catch_system_errors, timeout );
       
   233     }
       
   234 
       
   235     //  Catch-clause reference arguments are a bit different from function
       
   236     //  arguments (ISO 15.3 paragraphs 18 & 19).  Apparently const isn't
       
   237     //  required.  Programmers ask for const anyhow, so we supply it.  That's
       
   238     //  easier than answering questions about non-const usage.
       
   239 
       
   240     catch( char const* ex )
       
   241       { detail::report_error( execution_exception::cpp_exception_error, "C string: ", ex ); }
       
   242     catch( std::string const& ex )
       
   243       { detail::report_error( execution_exception::cpp_exception_error, "std::string: ", ex.c_str() ); }
       
   244 
       
   245     //  std:: exceptions
       
   246 
       
   247     catch( std::bad_alloc const& ex )
       
   248       { detail::report_error( execution_exception::cpp_exception_error, "std::bad_alloc: ", ex.what() ); }
       
   249 #ifndef __SYMBIAN32__
       
   250 #if BOOST_WORKAROUND(__BORLANDC__, <= 0x0551)
       
   251     catch( std::bad_cast const& ex )
       
   252       { detail::report_error( execution_exception::cpp_exception_error, "std::bad_cast" ); }
       
   253     catch( std::bad_typeid const& ex )
       
   254       { detail::report_error( execution_exception::cpp_exception_error, "std::bad_typeid" ); }
       
   255 #else
       
   256 #endif //__SYMBIAN32__
       
   257     catch( std::bad_cast const& ex )
       
   258       { detail::report_error( execution_exception::cpp_exception_error, "std::bad_cast: ", ex.what() ); }
       
   259     catch( std::bad_typeid const& ex )
       
   260       { detail::report_error( execution_exception::cpp_exception_error, "std::bad_typeid: ", ex.what() ); }
       
   261 #ifndef __SYMBIAN32__
       
   262 #endif //BOOST_WORKAROUND
       
   263 #endif//__SYMBIAN32__
       
   264 
       
   265     catch( std::bad_exception const& ex )
       
   266       { detail::report_error( execution_exception::cpp_exception_error, "std::bad_exception: ", ex.what() ); }
       
   267     catch( std::domain_error const& ex )
       
   268       { detail::report_error( execution_exception::cpp_exception_error, "std::domain_error: ", ex.what() ); }
       
   269     catch( std::invalid_argument const& ex )
       
   270       { detail::report_error( execution_exception::cpp_exception_error, "std::invalid_argument: ", ex.what() ); }
       
   271     catch( std::length_error const& ex )
       
   272       { detail::report_error( execution_exception::cpp_exception_error, "std::length_error: ", ex.what() ); }
       
   273     catch( std::out_of_range const& ex )
       
   274       { detail::report_error( execution_exception::cpp_exception_error, "std::out_of_range: ", ex.what() ); }
       
   275     catch( std::range_error const& ex )
       
   276       { detail::report_error( execution_exception::cpp_exception_error, "std::range_error: ", ex.what() ); }
       
   277     catch( std::overflow_error const& ex )
       
   278       { detail::report_error( execution_exception::cpp_exception_error, "std::overflow_error: ", ex.what() ); }
       
   279     catch( std::underflow_error const& ex )
       
   280       { detail::report_error( execution_exception::cpp_exception_error, "std::underflow_error: ", ex.what() ); }
       
   281     catch( std::logic_error const& ex )
       
   282       { detail::report_error( execution_exception::cpp_exception_error, "std::logic_error: ", ex.what() ); }
       
   283     catch( std::runtime_error const& ex )
       
   284       { detail::report_error( execution_exception::cpp_exception_error, "std::runtime_error: ", ex.what() ); }
       
   285     catch( std::exception const& ex )
       
   286       { detail::report_error( execution_exception::cpp_exception_error, "std::exception: ", ex.what() ); }
       
   287 
       
   288 #if   defined(BOOST_MS_STRUCTURED_EXCEPTION_HANDLING)
       
   289     catch( detail::ms_se_exception const& ex )
       
   290       { detail::report_ms_se_error( ex.id() ); }
       
   291 #elif defined(BOOST_SIGACTION_BASED_SIGNAL_HANDLING)
       
   292     catch( detail::unix_signal_exception const& ex )
       
   293       { detail::report_error( ex.error_code(), ex.error_message() ); }
       
   294 #endif  // BOOST_SIGACTION_BASED_SIGNAL_HANDLING
       
   295 
       
   296     catch( execution_aborted const& )
       
   297       { return 0; }
       
   298 
       
   299     catch( execution_exception const& )
       
   300       { throw; }
       
   301 
       
   302     catch( ... )
       
   303       { detail::report_error( execution_exception::cpp_exception_error, "unknown type" ); }
       
   304 
       
   305     return 0;  // never reached; supplied to quiet compiler warnings
       
   306 } // execute
       
   307 
       
   308 //____________________________________________________________________________//
       
   309 
       
   310 #if defined(BOOST_SIGACTION_BASED_SIGNAL_HANDLING)
       
   311 
       
   312 // ************************************************************************** //
       
   313 // **************          boost::detail::signal_handler       ************** //
       
   314 // ************************************************************************** //
       
   315 
       
   316 namespace detail {
       
   317 
       
   318 class signal_handler {
       
   319 public:
       
   320     // Constructor
       
   321    EXPORT_C explicit signal_handler( bool catch_system_errors, int timeout );
       
   322 
       
   323     // Destructor
       
   324     ~signal_handler();
       
   325 
       
   326     // access methods
       
   327     static sigjmp_buf&      jump_buffer()
       
   328     {
       
   329         assert( !!s_active_handler );
       
   330 
       
   331         return s_active_handler->m_sigjmp_buf;
       
   332     }
       
   333 
       
   334 private:
       
   335     // Data members
       
   336     struct sigaction        m_same_action_for_all_signals;
       
   337     struct sigaction        m_old_SIGFPE_action;
       
   338     struct sigaction        m_old_SIGTRAP_action;
       
   339     struct sigaction        m_old_SIGSEGV_action;
       
   340     struct sigaction        m_old_SIGBUS_action;
       
   341     struct sigaction        m_old_SIGABRT_action;
       
   342     struct sigaction        m_old_SIGALRM_action;
       
   343 
       
   344     sigjmp_buf              m_sigjmp_buf;
       
   345 
       
   346     signal_handler*         m_prev_handler;
       
   347     static signal_handler*  s_active_handler;
       
   348 
       
   349     bool                    m_catch_system_errors;
       
   350     bool                    m_set_timeout;
       
   351 };
       
   352 
       
   353 signal_handler* signal_handler::s_active_handler = NULL; // !! need to be placed in thread specific storage
       
   354 
       
   355 //____________________________________________________________________________//
       
   356 
       
   357 extern "C" {
       
   358 
       
   359 static void execution_monitor_signal_handler( int sig )
       
   360 {
       
   361     siglongjmp( signal_handler::jump_buffer(), sig );
       
   362 }
       
   363 
       
   364 }
       
   365 
       
   366 //____________________________________________________________________________//
       
   367 
       
   368 signal_handler::signal_handler( bool catch_system_errors, int timeout )
       
   369 : m_prev_handler( s_active_handler )
       
   370 , m_catch_system_errors( catch_system_errors )
       
   371 , m_set_timeout( timeout > 0 )
       
   372 {
       
   373     s_active_handler = this;
       
   374 
       
   375     if( m_catch_system_errors || m_set_timeout ) {
       
   376         m_same_action_for_all_signals.sa_flags   = 0;
       
   377         m_same_action_for_all_signals.sa_handler = &execution_monitor_signal_handler;
       
   378         sigemptyset( &m_same_action_for_all_signals.sa_mask );
       
   379     }
       
   380 
       
   381     if( m_catch_system_errors ) {
       
   382         sigaction( SIGFPE , &m_same_action_for_all_signals, &m_old_SIGFPE_action  );
       
   383         sigaction( SIGTRAP, &m_same_action_for_all_signals, &m_old_SIGTRAP_action );
       
   384         sigaction( SIGSEGV, &m_same_action_for_all_signals, &m_old_SIGSEGV_action );
       
   385         sigaction( SIGBUS , &m_same_action_for_all_signals, &m_old_SIGBUS_action  );
       
   386         sigaction( SIGABRT, &m_same_action_for_all_signals, &m_old_SIGABRT_action  );
       
   387     }
       
   388 
       
   389     if( m_set_timeout ) {
       
   390         sigaction( SIGALRM , &m_same_action_for_all_signals, &m_old_SIGALRM_action );
       
   391         alarm( timeout );
       
   392     }
       
   393 }
       
   394 
       
   395 //____________________________________________________________________________//
       
   396 
       
   397 signal_handler::~signal_handler()
       
   398 {
       
   399     typedef struct sigaction* sigaction_ptr;
       
   400 
       
   401     assert( s_active_handler == this );
       
   402 
       
   403     if( m_set_timeout ) {
       
   404         alarm( 0 );
       
   405         sigaction( SIGALRM, &m_old_SIGALRM_action, sigaction_ptr() );
       
   406     }
       
   407 
       
   408     if( m_catch_system_errors ) {
       
   409         sigaction( SIGFPE , &m_old_SIGFPE_action , sigaction_ptr() );
       
   410         sigaction( SIGTRAP, &m_old_SIGTRAP_action, sigaction_ptr() );
       
   411         sigaction( SIGSEGV, &m_old_SIGSEGV_action, sigaction_ptr() );
       
   412         sigaction( SIGBUS , &m_old_SIGBUS_action , sigaction_ptr() );
       
   413         sigaction( SIGABRT, &m_old_SIGABRT_action, sigaction_ptr() );
       
   414     }
       
   415 
       
   416     s_active_handler = m_prev_handler;
       
   417 }
       
   418 
       
   419 //____________________________________________________________________________//
       
   420 
       
   421 } // namespace detail
       
   422 
       
   423 // ************************************************************************** //
       
   424 // **************        execution_monitor::catch_signals      ************** //
       
   425 // ************************************************************************** //
       
   426 
       
   427 EXPORT_C int
       
   428 execution_monitor::catch_signals( unit_test::callback0<int> const& F, bool catch_system_errors, int timeout )
       
   429 {
       
   430     using namespace detail;
       
   431 
       
   432     signal_handler local_signal_handler( catch_system_errors, timeout );
       
   433 
       
   434     volatile int   sigtype = sigsetjmp( signal_handler::jump_buffer(), 1 );
       
   435 
       
   436     typedef execution_exception::error_code ec_type;
       
   437     int            result = 0;
       
   438     ec_type        ec     = execution_exception::no_error;
       
   439     const_string   em;
       
   440 
       
   441     if( sigtype == 0 ) {
       
   442         result = m_custom_translators ? (*m_custom_translators)( F ) : F();
       
   443     }
       
   444     else {
       
   445         switch(sigtype) {
       
   446         case SIGALRM:
       
   447             ec = execution_exception::timeout_error;
       
   448             em = BOOST_TEST_L( "signal: SIGALRM (timeout while executing function)" );
       
   449             break;
       
   450         case SIGTRAP:
       
   451             ec = execution_exception::system_error;
       
   452             em = BOOST_TEST_L( "signal: SIGTRAP (perhaps integer divide by zero)" );
       
   453             break;
       
   454         case SIGFPE:
       
   455             ec = execution_exception::system_error;
       
   456             em = BOOST_TEST_L( "signal: SIGFPE (arithmetic exception)" );
       
   457             break;
       
   458         case SIGABRT:
       
   459             ec = execution_exception::system_error;
       
   460             em = BOOST_TEST_L( "signal: SIGABRT (application abort requested)" );
       
   461             break;
       
   462         case SIGSEGV:
       
   463         case SIGBUS:
       
   464             ec = execution_exception::system_fatal_error;
       
   465             em = BOOST_TEST_L( "memory access violation" );
       
   466             break;
       
   467         default:
       
   468             ec = execution_exception::system_error;
       
   469             em = BOOST_TEST_L( "unrecognized signal" );
       
   470         }
       
   471     }
       
   472 
       
   473     if( ec != execution_exception::no_error )
       
   474         throw unix_signal_exception( ec, em );
       
   475 
       
   476     return result;
       
   477 }  // unix catch_signals
       
   478 
       
   479 //____________________________________________________________________________//
       
   480 
       
   481 #elif (defined(__BORLANDC__) && defined(_Windows) && !defined(BOOST_DISABLE_WIN32))
       
   482 
       
   483 // this works for Borland but not other Win32 compilers (which trap too many cases)
       
   484 EXPORT_C int
       
   485 execution_monitor::catch_signals( unit_test::callback0<int> const& F, bool catch_system_errors, int )
       
   486 {
       
   487     int result;
       
   488 
       
   489     if( catch_system_errors ) {
       
   490         __try { result = m_custom_translators ? (*m_custom_translators)( F ) : F(); }
       
   491 
       
   492         __except (1) {
       
   493             throw detail::ms_se_exception( GetExceptionCode() );
       
   494         }
       
   495     }
       
   496     else
       
   497         result = m_custom_translators ? (*m_custom_translators)( F ) : F();
       
   498 
       
   499     return result;
       
   500 }
       
   501 
       
   502 #else  // default signal handler
       
   503 
       
   504 EXPORT_C int
       
   505 execution_monitor::catch_signals( unit_test::callback0<int> const& F, bool, int )
       
   506 {
       
   507     return m_custom_translators ? (*m_custom_translators)( F ) : F();
       
   508 }
       
   509 
       
   510 #endif  // choose signal handler
       
   511 
       
   512 // ************************************************************************** //
       
   513 // **************   Microsoft structured exception handling    ************** //
       
   514 // ************************************************************************** //
       
   515 
       
   516 #if defined(BOOST_MS_STRUCTURED_EXCEPTION_HANDLING)
       
   517 
       
   518 namespace detail {
       
   519 
       
   520 EXPORT_C void
       
   521 ms_se_trans_func( unsigned int id, _EXCEPTION_POINTERS* /* exps */ )
       
   522 {
       
   523     throw ms_se_exception( id );
       
   524 }
       
   525 
       
   526 //____________________________________________________________________________//
       
   527 
       
   528 EXPORT_C void
       
   529 ms_se_forward_func( unsigned int /* id */, _EXCEPTION_POINTERS* /* exps */ )
       
   530 {
       
   531     throw;
       
   532 }
       
   533 
       
   534 //____________________________________________________________________________//
       
   535 
       
   536 EXPORT_C void
       
   537 report_ms_se_error( unsigned int id )
       
   538 {
       
   539     switch( id ) {
       
   540         // cases classified as fatal_system_error
       
   541     case EXCEPTION_ACCESS_VIOLATION:
       
   542         detail::report_error( execution_exception::system_fatal_error, "memory access violation" );
       
   543         break;
       
   544 
       
   545     case EXCEPTION_ILLEGAL_INSTRUCTION:
       
   546         detail::report_error( execution_exception::system_fatal_error, "illegal instruction" );
       
   547         break;
       
   548 
       
   549     case EXCEPTION_PRIV_INSTRUCTION:
       
   550         detail::report_error( execution_exception::system_fatal_error, "privileged instruction" );
       
   551         break;
       
   552 
       
   553     case EXCEPTION_IN_PAGE_ERROR:
       
   554         detail::report_error( execution_exception::system_fatal_error, "memory page error" );
       
   555         break;
       
   556 
       
   557     case EXCEPTION_STACK_OVERFLOW:
       
   558         detail::report_error( execution_exception::system_fatal_error, "stack overflow" );
       
   559         break;
       
   560 
       
   561         // cases classified as (non-fatal) system_trap
       
   562     case EXCEPTION_DATATYPE_MISALIGNMENT:
       
   563         detail::report_error( execution_exception::system_error, "data misalignment" );
       
   564         break;
       
   565 
       
   566     case EXCEPTION_INT_DIVIDE_BY_ZERO:
       
   567         detail::report_error( execution_exception::system_error, "integer divide by zero" );
       
   568         break;
       
   569 
       
   570     case EXCEPTION_INT_OVERFLOW:
       
   571         detail::report_error( execution_exception::system_error, "integer overflow" );
       
   572         break;
       
   573 
       
   574     case EXCEPTION_ARRAY_BOUNDS_EXCEEDED:
       
   575         detail::report_error( execution_exception::system_error, "array bounds exceeded" );
       
   576         break;
       
   577 
       
   578     case EXCEPTION_FLT_DIVIDE_BY_ZERO:
       
   579         detail::report_error( execution_exception::system_error, "floating point divide by zero" );
       
   580         break;
       
   581 
       
   582     case EXCEPTION_FLT_STACK_CHECK:
       
   583         detail::report_error( execution_exception::system_error, "floating point stack check" );
       
   584         break;
       
   585 
       
   586     case EXCEPTION_FLT_DENORMAL_OPERAND:
       
   587     case EXCEPTION_FLT_INEXACT_RESULT:
       
   588     case EXCEPTION_FLT_INVALID_OPERATION:
       
   589     case EXCEPTION_FLT_OVERFLOW:
       
   590     case EXCEPTION_FLT_UNDERFLOW:
       
   591         detail::report_error( execution_exception::system_error, "floating point error" );
       
   592         break;
       
   593 
       
   594     default:
       
   595         detail::report_error( execution_exception::system_error, "unrecognized exception or signal" );
       
   596         break;
       
   597     }  // switch
       
   598 }  // report_ms_se_error
       
   599 
       
   600 //____________________________________________________________________________//
       
   601 
       
   602 } // namespace detail
       
   603 
       
   604 #endif  // Microsoft structured exception handling
       
   605 
       
   606 // ************************************************************************** //
       
   607 // **************                  report_error                ************** //
       
   608 // ************************************************************************** //
       
   609 
       
   610 namespace detail {
       
   611 
       
   612 static void report_error( execution_exception::error_code ec, const_string msg1, const_string msg2 )
       
   613 {
       
   614     static char buf[REPORT_ERROR_BUFFER_SIZE];
       
   615 
       
   616     buf[0] = '\0';
       
   617 
       
   618     std::strncat( buf, msg1.begin(), sizeof(buf)-1 );
       
   619     std::strncat( buf, msg2.begin(), sizeof(buf) - msg1.size() - 1 );
       
   620 
       
   621     throw execution_exception( ec, buf );
       
   622 }
       
   623 
       
   624 //____________________________________________________________________________//
       
   625 
       
   626 } // namespace detail
       
   627 
       
   628 // ************************************************************************** //
       
   629 // **************              detect_memory_leaks             ************** //
       
   630 // ************************************************************************** //
       
   631 
       
   632 EXPORT_C void
       
   633 detect_memory_leaks( bool on_off )
       
   634 {
       
   635     unit_test::ut_detail::ignore_unused_variable_warning( on_off );
       
   636 
       
   637 #ifdef BOOST_MS_CRT_DEBUG_HOOKS
       
   638     int flags = _CrtSetDbgFlag( _CRTDBG_REPORT_FLAG );
       
   639 
       
   640     if( !on_off )
       
   641         flags &= ~_CRTDBG_LEAK_CHECK_DF;
       
   642     else  {
       
   643         flags |= _CRTDBG_LEAK_CHECK_DF;
       
   644         _CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE);
       
   645         _CrtSetReportFile(_CRT_WARN, _CRTDBG_FILE_STDOUT);
       
   646     }
       
   647 
       
   648     _CrtSetDbgFlag ( flags );
       
   649 #endif // BOOST_MS_CRT_DEBUG_HOOKS
       
   650 }
       
   651 
       
   652 //____________________________________________________________________________//
       
   653 
       
   654 EXPORT_C void
       
   655 break_memory_alloc( long mem_alloc_order_num )
       
   656 {
       
   657     unit_test::ut_detail::ignore_unused_variable_warning( mem_alloc_order_num );
       
   658 
       
   659 #ifdef BOOST_MS_CRT_DEBUG_HOOKS
       
   660     _CrtSetBreakAlloc( mem_alloc_order_num );
       
   661 #endif // BOOST_MS_CRT_DEBUG_HOOKS
       
   662 }
       
   663 
       
   664 } // namespace boost
       
   665 
       
   666 //____________________________________________________________________________//
       
   667 
       
   668 #include <boost/test/detail/enable_warnings.hpp>
       
   669 
       
   670 // ***************************************************************************
       
   671 //  Revision History :
       
   672 //
       
   673 //  $Log: execution_monitor.ipp,v $
       
   674 //  Revision 1.13  2006/02/22 16:14:45  rogeeff
       
   675 //  reagance to eliminate warning
       
   676 //
       
   677 //  Revision 1.12  2006/01/30 07:29:49  rogeeff
       
   678 //  split memory leaks detection API in two to get more functions with better defined roles
       
   679 //
       
   680 //  Revision 1.11  2006/01/15 09:47:43  rogeeff
       
   681 //  make common message
       
   682 //
       
   683 //  Revision 1.10  2005/12/14 05:52:49  rogeeff
       
   684 //  *** empty log message ***
       
   685 //
       
   686 //  Revision 1.9  2005/04/30 17:07:22  rogeeff
       
   687 //  ignore_warning included
       
   688 //
       
   689 //  Revision 1.8  2005/04/30 16:46:50  rogeeff
       
   690 //  warning suppressed
       
   691 //
       
   692 //  Revision 1.7  2005/04/13 05:32:03  rogeeff
       
   693 //  typo fix
       
   694 //
       
   695 //  Revision 1.6  2005/04/05 06:11:37  rogeeff
       
   696 //  memory leak allocation point detection\nextra help with _WIN32_WINNT
       
   697 //
       
   698 //  Revision 1.5  2005/02/20 08:27:07  rogeeff
       
   699 //  This a major update for Boost.Test framework. See release docs for complete list of fixes/updates
       
   700 //
       
   701 //  Revision 1.4  2005/02/01 06:40:07  rogeeff
       
   702 //  copyright update
       
   703 //  old log entries removed
       
   704 //  minor stilistic changes
       
   705 //  depricated tools removed
       
   706 //
       
   707 //  Revision 1.3  2005/01/31 07:50:06  rogeeff
       
   708 //  cdecl portability fix
       
   709 //
       
   710 //  Revision 1.2  2005/01/31 05:58:03  rogeeff
       
   711 //  detect_memory_leak feature added
       
   712 //
       
   713 //  Revision 1.1  2005/01/22 19:22:12  rogeeff
       
   714 //  implementation moved into headers section to eliminate dependency of included/minimal component on src directory
       
   715 //
       
   716 //  Revision 1.36  2005/01/21 07:21:38  rogeeff
       
   717 //  detect presence of debugger under VC and automatically prevent catching system errors
       
   718 //
       
   719 // ***************************************************************************
       
   720 
       
   721 #endif // BOOST_TEST_EXECUTION_MONITOR_IPP_012205GER