| 1 | // (C) Copyright Gennadiy Rozental 2001-2005. |
|---|
| 2 | // (C) Copyright Beman Dawes 2001. |
|---|
| 3 | // Distributed under the Boost Software License, Version 1.0. |
|---|
| 4 | // (See accompanying file LICENSE_1_0.txt or copy at |
|---|
| 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.hpp,v $ |
|---|
| 10 | // |
|---|
| 11 | // Version : $Revision: 1.25 $ |
|---|
| 12 | // |
|---|
| 13 | // Description : defines abstract monitor interfaces and implements execution exception |
|---|
| 14 | // The original Boost Test Library included an implementation detail function |
|---|
| 15 | // named catch_exceptions() which caught otherwise uncaught C++ exceptions. |
|---|
| 16 | // It was derived from an existing test framework by Beman Dawes. The |
|---|
| 17 | // intent was to expand later to catch other detectable but platform dependent |
|---|
| 18 | // error events like Unix signals or Windows structured C exceptions. |
|---|
| 19 | // |
|---|
| 20 | // Requests from early adopters of the Boost Test Library included |
|---|
| 21 | // configurable levels of error message detail, elimination of templates, |
|---|
| 22 | // separation of error reporting, and making the catch_exceptions() facilities |
|---|
| 23 | // available as a public interface. Support for unit testing also stretched |
|---|
| 24 | // the function based design. Implementation within the header became less |
|---|
| 25 | // attractive due to the need to include many huge system dependent headers, |
|---|
| 26 | // although still preferable in certain cases. |
|---|
| 27 | // |
|---|
| 28 | // All those issues have been addressed by introducing the class-based |
|---|
| 29 | // design presented here. |
|---|
| 30 | // *************************************************************************** |
|---|
| 31 | |
|---|
| 32 | #ifndef BOOST_TEST_EXECUTION_MONITOR_HPP_071894GER |
|---|
| 33 | #define BOOST_TEST_EXECUTION_MONITOR_HPP_071894GER |
|---|
| 34 | |
|---|
| 35 | // Boost.Test |
|---|
| 36 | #include <boost/test/detail/global_typedef.hpp> |
|---|
| 37 | #include <boost/test/detail/fwd_decl.hpp> |
|---|
| 38 | #include <boost/test/utils/callback.hpp> |
|---|
| 39 | |
|---|
| 40 | // Boost |
|---|
| 41 | #include <boost/scoped_ptr.hpp> |
|---|
| 42 | #include <boost/type.hpp> |
|---|
| 43 | #include <boost/cstdlib.hpp> |
|---|
| 44 | |
|---|
| 45 | #include <boost/test/detail/suppress_warnings.hpp> |
|---|
| 46 | |
|---|
| 47 | //____________________________________________________________________________// |
|---|
| 48 | |
|---|
| 49 | namespace boost { |
|---|
| 50 | |
|---|
| 51 | namespace detail { |
|---|
| 52 | |
|---|
| 53 | // ************************************************************************** // |
|---|
| 54 | // ************** detail::translate_exception_base ************** // |
|---|
| 55 | // ************************************************************************** // |
|---|
| 56 | |
|---|
| 57 | class BOOST_TEST_DECL translate_exception_base { |
|---|
| 58 | public: |
|---|
| 59 | // Constructor |
|---|
| 60 | explicit translate_exception_base( boost::scoped_ptr<translate_exception_base>& next ) |
|---|
| 61 | { |
|---|
| 62 | next.swap( m_next ); |
|---|
| 63 | } |
|---|
| 64 | |
|---|
| 65 | // Destructor |
|---|
| 66 | virtual ~translate_exception_base() {} |
|---|
| 67 | |
|---|
| 68 | virtual int operator()( unit_test::callback0<int> const& F ) = 0; |
|---|
| 69 | |
|---|
| 70 | protected: |
|---|
| 71 | // Data members |
|---|
| 72 | boost::scoped_ptr<translate_exception_base> m_next; |
|---|
| 73 | }; |
|---|
| 74 | |
|---|
| 75 | } // namespace detail |
|---|
| 76 | |
|---|
| 77 | // ************************************************************************** // |
|---|
| 78 | // ************** execution_exception ************** // |
|---|
| 79 | // ************************************************************************** // |
|---|
| 80 | |
|---|
| 81 | // design rationale: fear of being out (or nearly out) of memory. |
|---|
| 82 | |
|---|
| 83 | class BOOST_TEST_DECL execution_exception { |
|---|
| 84 | typedef boost::unit_test::const_string const_string; |
|---|
| 85 | public: |
|---|
| 86 | enum error_code { |
|---|
| 87 | // These values are sometimes used as program return codes. |
|---|
| 88 | // The particular values have been chosen to avoid conflicts with |
|---|
| 89 | // commonly used program return codes: values < 100 are often user |
|---|
| 90 | // assigned, values > 255 are sometimes used to report system errors. |
|---|
| 91 | // Gaps in values allow for orderly expansion. |
|---|
| 92 | |
|---|
| 93 | no_error = 0, // for completeness only; never returned |
|---|
| 94 | user_error = 200, // user reported non-fatal error |
|---|
| 95 | cpp_exception_error = 205, // see note (1) below |
|---|
| 96 | system_error = 210, // see note (2) below |
|---|
| 97 | timeout_error = 215, // only detectable on certain platforms |
|---|
| 98 | user_fatal_error = 220, // user reported fatal error |
|---|
| 99 | system_fatal_error = 225 // see note (2) below |
|---|
| 100 | |
|---|
| 101 | // Note 1: Only uncaught C++ exceptions are treated as errors. |
|---|
| 102 | // If the application catches a C++ exception, it will never reach |
|---|
| 103 | // the execution_monitor. |
|---|
| 104 | |
|---|
| 105 | // Note 2: These errors include Unix signals and Windows structured |
|---|
| 106 | // exceptions. They are often initiated by hardware traps. |
|---|
| 107 | // |
|---|
| 108 | // The implementation decides what is a fatal_system_exception and what is |
|---|
| 109 | // just a system_exception. Fatal errors are so likely to have corrupted |
|---|
| 110 | // machine state (like a stack overflow or addressing exception) that it |
|---|
| 111 | // is unreasonable to continue execution. |
|---|
| 112 | }; |
|---|
| 113 | |
|---|
| 114 | // Constructor |
|---|
| 115 | execution_exception( error_code ec_, const_string what_msg_ ) // max length 256 inc '\0' |
|---|
| 116 | : m_error_code( ec_ ), m_what( what_msg_ ) {} |
|---|
| 117 | |
|---|
| 118 | // access methods |
|---|
| 119 | error_code code() const { return m_error_code; } |
|---|
| 120 | const_string what() const { return m_what; } |
|---|
| 121 | |
|---|
| 122 | private: |
|---|
| 123 | // Data members |
|---|
| 124 | error_code m_error_code; |
|---|
| 125 | const_string m_what; |
|---|
| 126 | }; // execution_exception |
|---|
| 127 | |
|---|
| 128 | // ************************************************************************** // |
|---|
| 129 | // ************** execution_monitor ************** // |
|---|
| 130 | // ************************************************************************** // |
|---|
| 131 | |
|---|
| 132 | class BOOST_TEST_DECL execution_monitor { |
|---|
| 133 | public: |
|---|
| 134 | int execute( unit_test::callback0<int> const& F, bool catch_system_errors = true, int timeout = 0 ); |
|---|
| 135 | // The catch_system_errors parameter specifies whether the monitor should |
|---|
| 136 | // try to catch system errors/exceptions that would cause program to crash |
|---|
| 137 | // in regular case |
|---|
| 138 | // The timeout argument specifies the seconds that elapse before |
|---|
| 139 | // a timer_error occurs. May be ignored on some platforms. |
|---|
| 140 | // |
|---|
| 141 | // Returns: Value returned by function(). |
|---|
| 142 | // |
|---|
| 143 | // Effects: Calls executes supplied function F inside a try/catch block which also may |
|---|
| 144 | // include other unspecified platform dependent error detection code. |
|---|
| 145 | // |
|---|
| 146 | // Throws: execution_exception on an uncaught C++ exception, |
|---|
| 147 | // a hardware or software signal, trap, or other exception. |
|---|
| 148 | // |
|---|
| 149 | // Note: execute() doesn't consider it an error for F to return a non-zero value. |
|---|
| 150 | |
|---|
| 151 | // register custom (user supplied) exception translator |
|---|
| 152 | template<typename Exception, typename ExceptionTranslator> |
|---|
| 153 | void register_exception_translator( ExceptionTranslator const& tr, boost::type<Exception>* = 0 ); |
|---|
| 154 | |
|---|
| 155 | private: |
|---|
| 156 | // implementation helpers |
|---|
| 157 | int catch_signals( unit_test::callback0<int> const& F, bool catch_system_errors, int timeout ); |
|---|
| 158 | |
|---|
| 159 | // Data members |
|---|
| 160 | boost::scoped_ptr<detail::translate_exception_base> m_custom_translators; |
|---|
| 161 | }; // execution_monitor |
|---|
| 162 | |
|---|
| 163 | namespace detail { |
|---|
| 164 | |
|---|
| 165 | // ************************************************************************** // |
|---|
| 166 | // ************** detail::translate_exception ************** // |
|---|
| 167 | // ************************************************************************** // |
|---|
| 168 | |
|---|
| 169 | template<typename Exception, typename ExceptionTranslator> |
|---|
| 170 | class translate_exception : public translate_exception_base |
|---|
| 171 | { |
|---|
| 172 | typedef boost::scoped_ptr<translate_exception_base> base_ptr; |
|---|
| 173 | public: |
|---|
| 174 | explicit translate_exception( ExceptionTranslator const& tr, base_ptr& next ) |
|---|
| 175 | : translate_exception_base( next ), m_translator( tr ) {} |
|---|
| 176 | |
|---|
| 177 | int operator()( unit_test::callback0<int> const& F ) |
|---|
| 178 | { |
|---|
| 179 | try { |
|---|
| 180 | return m_next ? (*m_next)( F ) : F(); |
|---|
| 181 | } catch( Exception const& e ) { |
|---|
| 182 | m_translator( e ); |
|---|
| 183 | return boost::exit_exception_failure; |
|---|
| 184 | } |
|---|
| 185 | } |
|---|
| 186 | |
|---|
| 187 | private: |
|---|
| 188 | // Data members |
|---|
| 189 | ExceptionTranslator m_translator; |
|---|
| 190 | }; |
|---|
| 191 | |
|---|
| 192 | } // namespace detail |
|---|
| 193 | |
|---|
| 194 | template<typename Exception, typename ExceptionTranslator> |
|---|
| 195 | void |
|---|
| 196 | execution_monitor::register_exception_translator( ExceptionTranslator const& tr, boost::type<Exception>* ) |
|---|
| 197 | { |
|---|
| 198 | m_custom_translators.reset( |
|---|
| 199 | new detail::translate_exception<Exception,ExceptionTranslator>( tr,m_custom_translators ) ); |
|---|
| 200 | } |
|---|
| 201 | |
|---|
| 202 | // ************************************************************************** // |
|---|
| 203 | // ************** detect_memory_leaks ************** // |
|---|
| 204 | // ************************************************************************** // |
|---|
| 205 | |
|---|
| 206 | // turn on system memory leak detection |
|---|
| 207 | void BOOST_TEST_DECL detect_memory_leaks( bool on_off ); |
|---|
| 208 | // break program execution on mem_alloc_order_num's allocation |
|---|
| 209 | void BOOST_TEST_DECL break_memory_alloc( long mem_alloc_order_num ); |
|---|
| 210 | |
|---|
| 211 | // ************************************************************************** // |
|---|
| 212 | // ************** execution_aborted ************** // |
|---|
| 213 | // ************************************************************************** // |
|---|
| 214 | |
|---|
| 215 | struct BOOST_TEST_DECL execution_aborted {}; |
|---|
| 216 | |
|---|
| 217 | } // namespace boost |
|---|
| 218 | |
|---|
| 219 | //____________________________________________________________________________// |
|---|
| 220 | |
|---|
| 221 | #include <boost/test/detail/enable_warnings.hpp> |
|---|
| 222 | |
|---|
| 223 | // *************************************************************************** |
|---|
| 224 | // Revision History : |
|---|
| 225 | // |
|---|
| 226 | // $Log: execution_monitor.hpp,v $ |
|---|
| 227 | // Revision 1.25 2006/01/30 07:29:49 rogeeff |
|---|
| 228 | // split memory leaks detection API in two to get more functions with better defined roles |
|---|
| 229 | // |
|---|
| 230 | // Revision 1.24 2005/12/14 05:05:58 rogeeff |
|---|
| 231 | // dll support introduced |
|---|
| 232 | // |
|---|
| 233 | // Revision 1.23 2005/04/05 06:11:37 rogeeff |
|---|
| 234 | // memory leak allocation point detection\nextra help with _WIN32_WINNT |
|---|
| 235 | // |
|---|
| 236 | // Revision 1.22 2005/02/20 08:27:05 rogeeff |
|---|
| 237 | // This a major update for Boost.Test framework. See release docs for complete list of fixes/updates |
|---|
| 238 | // |
|---|
| 239 | // Revision 1.21 2005/02/01 08:59:28 rogeeff |
|---|
| 240 | // supplied_log_formatters split |
|---|
| 241 | // change formatters interface to simplify result interface |
|---|
| 242 | // |
|---|
| 243 | // Revision 1.20 2005/02/01 06:40:06 rogeeff |
|---|
| 244 | // copyright update |
|---|
| 245 | // old log entries removed |
|---|
| 246 | // minor stilistic changes |
|---|
| 247 | // depricated tools removed |
|---|
| 248 | // |
|---|
| 249 | // Revision 1.19 2005/01/31 05:59:18 rogeeff |
|---|
| 250 | // detect_memory_leak feature added |
|---|
| 251 | // |
|---|
| 252 | // *************************************************************************** |
|---|
| 253 | |
|---|
| 254 | #endif |
|---|