execution_monitor.hpp 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263
  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. // See http://www.boost.org/libs/test for the library home page.
  7. //
  8. // File : $RCSfile$
  9. //
  10. // Version : $Revision: 57992 $
  11. //
  12. // Description : defines abstract monitor interfaces and implements execution exception
  13. // The original Boost Test Library included an implementation detail function
  14. // named catch_exceptions() which caught otherwise uncaught C++ exceptions.
  15. // It was derived from an existing test framework by Beman Dawes. The
  16. // intent was to expand later to catch other detectable but platform dependent
  17. // error events like Unix signals or Windows structured C exceptions.
  18. //
  19. // Requests from early adopters of the Boost Test Library included
  20. // configurable levels of error message detail, elimination of templates,
  21. // separation of error reporting, and making the catch_exceptions() facilities
  22. // available as a public interface. Support for unit testing also stretched
  23. // the function based design. Implementation within the header became less
  24. // attractive due to the need to include many huge system dependent headers,
  25. // although still preferable in certain cases.
  26. //
  27. // All those issues have been addressed by introducing the class-based
  28. // design presented here.
  29. // ***************************************************************************
  30. #ifndef BOOST_TEST_EXECUTION_MONITOR_HPP_071894GER
  31. #define BOOST_TEST_EXECUTION_MONITOR_HPP_071894GER
  32. // Boost.Test
  33. #include <boost/test/detail/global_typedef.hpp>
  34. #include <boost/test/detail/fwd_decl.hpp>
  35. #include <boost/test/utils/callback.hpp>
  36. #include <boost/test/utils/class_properties.hpp>
  37. // Boost
  38. #include <boost/scoped_ptr.hpp>
  39. #include <boost/scoped_array.hpp>
  40. #include <boost/type.hpp>
  41. #include <boost/cstdlib.hpp>
  42. #include <boost/test/detail/suppress_warnings.hpp>
  43. //____________________________________________________________________________//
  44. namespace boost {
  45. namespace detail {
  46. // ************************************************************************** //
  47. // ************** detail::translate_exception_base ************** //
  48. // ************************************************************************** //
  49. class BOOST_TEST_DECL translate_exception_base {
  50. public:
  51. // Constructor
  52. explicit translate_exception_base( boost::scoped_ptr<translate_exception_base>& next )
  53. {
  54. next.swap( m_next );
  55. }
  56. // Destructor
  57. virtual ~translate_exception_base() {}
  58. virtual int operator()( unit_test::callback0<int> const& F ) = 0;
  59. protected:
  60. // Data members
  61. boost::scoped_ptr<translate_exception_base> m_next;
  62. };
  63. } // namespace detail
  64. // ************************************************************************** //
  65. // ************** execution_exception ************** //
  66. // ************************************************************************** //
  67. // design rationale: fear of being out (or nearly out) of memory.
  68. class BOOST_TEST_DECL execution_exception {
  69. typedef boost::unit_test::const_string const_string;
  70. public:
  71. enum error_code {
  72. // These values are sometimes used as program return codes.
  73. // The particular values have been chosen to avoid conflicts with
  74. // commonly used program return codes: values < 100 are often user
  75. // assigned, values > 255 are sometimes used to report system errors.
  76. // Gaps in values allow for orderly expansion.
  77. no_error = 0, // for completeness only; never returned
  78. user_error = 200, // user reported non-fatal error
  79. cpp_exception_error = 205, // see note (1) below
  80. system_error = 210, // see note (2) below
  81. timeout_error = 215, // only detectable on certain platforms
  82. user_fatal_error = 220, // user reported fatal error
  83. system_fatal_error = 225 // see note (2) below
  84. // Note 1: Only uncaught C++ exceptions are treated as errors.
  85. // If the application catches a C++ exception, it will never reach
  86. // the execution_monitor.
  87. // Note 2: These errors include Unix signals and Windows structured
  88. // exceptions. They are often initiated by hardware traps.
  89. //
  90. // The implementation decides what is a fatal_system_exception and what is
  91. // just a system_exception. Fatal errors are so likely to have corrupted
  92. // machine state (like a stack overflow or addressing exception) that it
  93. // is unreasonable to continue execution.
  94. };
  95. struct BOOST_TEST_DECL location {
  96. explicit location( char const* file_name = 0, size_t line_num = 0, char const* func = 0 );
  97. const_string m_file_name;
  98. size_t m_line_num;
  99. const_string m_function;
  100. };
  101. // Constructor
  102. execution_exception( error_code ec_, const_string what_msg_, location const& location_ ); // max length 256 inc '\0'
  103. // Access methods
  104. error_code code() const { return m_error_code; }
  105. const_string what() const { return m_what; }
  106. location const& where() const { return m_location; }
  107. private:
  108. // Data members
  109. error_code m_error_code;
  110. const_string m_what;
  111. location m_location;
  112. }; // execution_exception
  113. // ************************************************************************** //
  114. // ************** execution_monitor ************** //
  115. // ************************************************************************** //
  116. class BOOST_TEST_DECL execution_monitor {
  117. public:
  118. // Constructor
  119. execution_monitor()
  120. : p_catch_system_errors( true )
  121. , p_auto_start_dbg( false )
  122. , p_timeout( 0 )
  123. , p_use_alt_stack( true )
  124. , p_detect_fp_exceptions( false )
  125. {}
  126. // Public properties
  127. // The p_catch_system_errors parameter specifies whether the monitor should
  128. // try to catch system errors/exceptions that would cause program to crash
  129. // in regular case
  130. unit_test::readwrite_property<bool> p_catch_system_errors;
  131. // The p_auto_start_dbg parameter specifies whether the monitor should
  132. // try to attach debugger in case of caught system error
  133. unit_test::readwrite_property<bool> p_auto_start_dbg;
  134. // The p_timeout parameter specifies the seconds that elapse before
  135. // a timer_error occurs. May be ignored on some platforms.
  136. unit_test::readwrite_property<int> p_timeout;
  137. // The p_use_alt_stack parameter specifies whether the monitor should
  138. // use alternative stack for the signal catching
  139. unit_test::readwrite_property<bool> p_use_alt_stack;
  140. // The p_detect_fp_exceptions parameter specifies whether the monitor should
  141. // try to detect hardware floating point exceptions
  142. unit_test::readwrite_property<bool> p_detect_fp_exceptions;
  143. int execute( unit_test::callback0<int> const& F );
  144. // Returns: Value returned by function call F().
  145. //
  146. // Effects: Calls executes supplied function F inside a try/catch block which also may
  147. // include other unspecified platform dependent error detection code.
  148. //
  149. // Throws: execution_exception on an uncaught C++ exception,
  150. // a hardware or software signal, trap, or other exception.
  151. //
  152. // Note: execute() doesn't consider it an error for F to return a non-zero value.
  153. // register custom (user supplied) exception translator
  154. template<typename Exception, typename ExceptionTranslator>
  155. void register_exception_translator( ExceptionTranslator const& tr, boost::type<Exception>* = 0 );
  156. private:
  157. // implementation helpers
  158. int catch_signals( unit_test::callback0<int> const& F );
  159. // Data members
  160. boost::scoped_ptr<detail::translate_exception_base> m_custom_translators;
  161. boost::scoped_array<char> m_alt_stack;
  162. }; // execution_monitor
  163. namespace detail {
  164. // ************************************************************************** //
  165. // ************** detail::translate_exception ************** //
  166. // ************************************************************************** //
  167. template<typename Exception, typename ExceptionTranslator>
  168. class translate_exception : public translate_exception_base
  169. {
  170. typedef boost::scoped_ptr<translate_exception_base> base_ptr;
  171. public:
  172. explicit translate_exception( ExceptionTranslator const& tr, base_ptr& next )
  173. : translate_exception_base( next ), m_translator( tr ) {}
  174. int operator()( unit_test::callback0<int> const& F )
  175. {
  176. try {
  177. return m_next ? (*m_next)( F ) : F();
  178. } catch( Exception const& e ) {
  179. m_translator( e );
  180. return boost::exit_exception_failure;
  181. }
  182. }
  183. private:
  184. // Data members
  185. ExceptionTranslator m_translator;
  186. };
  187. } // namespace detail
  188. template<typename Exception, typename ExceptionTranslator>
  189. void
  190. execution_monitor::register_exception_translator( ExceptionTranslator const& tr, boost::type<Exception>* )
  191. {
  192. m_custom_translators.reset(
  193. new detail::translate_exception<Exception,ExceptionTranslator>( tr,m_custom_translators ) );
  194. }
  195. // ************************************************************************** //
  196. // ************** execution_aborted ************** //
  197. // ************************************************************************** //
  198. struct execution_aborted {};
  199. // ************************************************************************** //
  200. // ************** system_error ************** //
  201. // ************************************************************************** //
  202. class system_error {
  203. public:
  204. // Constructor
  205. explicit system_error( char const* exp );
  206. unit_test::readonly_property<long> p_errno;
  207. unit_test::readonly_property<char const*> p_failed_exp;
  208. };
  209. #define BOOST_TEST_SYS_ASSERT( exp ) if( (exp) ) ; else throw ::boost::system_error( BOOST_STRINGIZE( exp ) )
  210. } // namespace boost
  211. //____________________________________________________________________________//
  212. #include <boost/test/detail/enable_warnings.hpp>
  213. #endif