1 // (C) Copyright Gennadiy Rozental 2001-2008. 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$ 10 // 11 // Version : $Revision: 57992 $ 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 #include <boost/test/utils/class_properties.hpp> 40 41 // Boost 42 #include <boost/scoped_ptr.hpp> 43 #include <boost/scoped_array.hpp> 44 #include <boost/type.hpp> 45 #include <boost/cstdlib.hpp> 46 47 #include <boost/test/detail/suppress_warnings.hpp> 48 49 //____________________________________________________________________________// 50 51 namespace boost { 52 53 namespace detail { 54 55 // ************************************************************************** // 56 // ************** detail::translate_exception_base ************** // 57 // ************************************************************************** // 58 59 class BOOST_TEST_DECL translate_exception_base { 60 public: 61 // Constructor 62 explicit translate_exception_base( boost::scoped_ptr<translate_exception_base>& next ) 63 { 64 next.swap( m_next ); 65 } 66 67 // Destructor 68 virtual ~translate_exception_base() {} 69 70 virtual int operator()( unit_test::callback0<int> const& F ) = 0; 71 72 protected: 73 // Data members 74 boost::scoped_ptr<translate_exception_base> m_next; 75 }; 76 77 } // namespace detail 78 79 // ************************************************************************** // 80 // ************** execution_exception ************** // 81 // ************************************************************************** // 82 83 // design rationale: fear of being out (or nearly out) of memory. 84 85 class BOOST_TEST_DECL execution_exception { 86 typedef boost::unit_test::const_string const_string; 87 public: 88 enum error_code { 89 // These values are sometimes used as program return codes. 90 // The particular values have been chosen to avoid conflicts with 91 // commonly used program return codes: values < 100 are often user 92 // assigned, values > 255 are sometimes used to report system errors. 93 // Gaps in values allow for orderly expansion. 94 95 no_error = 0, // for completeness only; never returned 96 user_error = 200, // user reported non-fatal error 97 cpp_exception_error = 205, // see note (1) below 98 system_error = 210, // see note (2) below 99 timeout_error = 215, // only detectable on certain platforms 100 user_fatal_error = 220, // user reported fatal error 101 system_fatal_error = 225 // see note (2) below 102 103 // Note 1: Only uncaught C++ exceptions are treated as errors. 104 // If the application catches a C++ exception, it will never reach 105 // the execution_monitor. 106 107 // Note 2: These errors include Unix signals and Windows structured 108 // exceptions. They are often initiated by hardware traps. 109 // 110 // The implementation decides what is a fatal_system_exception and what is 111 // just a system_exception. Fatal errors are so likely to have corrupted 112 // machine state (like a stack overflow or addressing exception) that it 113 // is unreasonable to continue execution. 114 }; 115 116 struct BOOST_TEST_DECL location { 117 explicit location( char const* file_name = 0, size_t line_num = 0, char const* func = 0 ); 118 119 const_string m_file_name; 120 size_t m_line_num; 121 const_string m_function; 122 }; 123 124 // Constructor 125 execution_exception( error_code ec_, const_string what_msg_, location const& location_ ); // max length 256 inc '\0' 126 127 // Access methods 128 error_code code() const { return m_error_code; } 129 const_string what() const { return m_what; } 130 location const& where() const { return m_location; } 131 132 private: 133 // Data members 134 error_code m_error_code; 135 const_string m_what; 136 location m_location; 137 }; // execution_exception 138 139 // ************************************************************************** // 140 // ************** execution_monitor ************** // 141 // ************************************************************************** // 142 143 class BOOST_TEST_DECL execution_monitor { 144 public: 145 // Constructor 146 execution_monitor() 147 : p_catch_system_errors( true ) 148 , p_auto_start_dbg( false ) 149 , p_timeout( 0 ) 150 , p_use_alt_stack( true ) 151 , p_detect_fp_exceptions( false ) 152 {} 153 154 // Public properties 155 156 // The p_catch_system_errors parameter specifies whether the monitor should 157 // try to catch system errors/exceptions that would cause program to crash 158 // in regular case 159 unit_test::readwrite_property<bool> p_catch_system_errors; 160 // The p_auto_start_dbg parameter specifies whether the monitor should 161 // try to attach debugger in case of caught system error 162 unit_test::readwrite_property<bool> p_auto_start_dbg; 163 // The p_timeout parameter specifies the seconds that elapse before 164 // a timer_error occurs. May be ignored on some platforms. 165 unit_test::readwrite_property<int> p_timeout; 166 // The p_use_alt_stack parameter specifies whether the monitor should 167 // use alternative stack for the signal catching 168 unit_test::readwrite_property<bool> p_use_alt_stack; 169 // The p_detect_fp_exceptions parameter specifies whether the monitor should 170 // try to detect hardware floating point exceptions 171 unit_test::readwrite_property<bool> p_detect_fp_exceptions; 172 173 int execute( unit_test::callback0<int> const& F ); 174 // Returns: Value returned by function call F(). 175 // 176 // Effects: Calls executes supplied function F inside a try/catch block which also may 177 // include other unspecified platform dependent error detection code. 178 // 179 // Throws: execution_exception on an uncaught C++ exception, 180 // a hardware or software signal, trap, or other exception. 181 // 182 // Note: execute() doesn't consider it an error for F to return a non-zero value. 183 184 // register custom (user supplied) exception translator 185 template<typename Exception, typename ExceptionTranslator> 186 void register_exception_translator( ExceptionTranslator const& tr, boost::type<Exception>* = 0 ); 187 188 private: 189 // implementation helpers 190 int catch_signals( unit_test::callback0<int> const& F ); 191 192 // Data members 193 boost::scoped_ptr<detail::translate_exception_base> m_custom_translators; 194 boost::scoped_array<char> m_alt_stack; 195 }; // execution_monitor 196 197 namespace detail { 198 199 // ************************************************************************** // 200 // ************** detail::translate_exception ************** // 201 // ************************************************************************** // 202 203 template<typename Exception, typename ExceptionTranslator> 204 class translate_exception : public translate_exception_base 205 { 206 typedef boost::scoped_ptr<translate_exception_base> base_ptr; 207 public: 208 explicit translate_exception( ExceptionTranslator const& tr, base_ptr& next ) 209 : translate_exception_base( next ), m_translator( tr ) {} 210 211 int operator()( unit_test::callback0<int> const& F ) 212 { 213 try { 214 return m_next ? (*m_next)( F ) : F(); 215 } catch( Exception const& e ) { 216 m_translator( e ); 217 return boost::exit_exception_failure; 218 } 219 } 220 221 private: 222 // Data members 223 ExceptionTranslator m_translator; 224 }; 225 226 } // namespace detail 227 228 template<typename Exception, typename ExceptionTranslator> 229 void 230 execution_monitor::register_exception_translator( ExceptionTranslator const& tr, boost::type<Exception>* ) 231 { 232 m_custom_translators.reset( 233 new detail::translate_exception<Exception,ExceptionTranslator>( tr,m_custom_translators ) ); 234 } 235 236 // ************************************************************************** // 237 // ************** execution_aborted ************** // 238 // ************************************************************************** // 239 240 struct execution_aborted {}; 241 242 // ************************************************************************** // 243 // ************** system_error ************** // 244 // ************************************************************************** // 245 246 class system_error { 247 public: 248 // Constructor 249 explicit system_error( char const* exp ); 250 251 unit_test::readonly_property<long> p_errno; 252 unit_test::readonly_property<char const*> p_failed_exp; 253 }; 254 255 #define BOOST_TEST_SYS_ASSERT( exp ) if( (exp) ) ; else throw ::boost::system_error( BOOST_STRINGIZE( exp ) ) 256 257 } // namespace boost 258 259 //____________________________________________________________________________// 260 261 #include <boost/test/detail/enable_warnings.hpp> 262 263 #endif 264