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