blob: a1abc8bf6489d7a63377b9fc60597ea9945c9248 [file] [log] [blame]
Jeff Thompsonef2d5a42013-08-22 19:09:24 -07001// (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
Jeff Thompson3d613fd2013-10-15 15:39:04 -070032#ifndef NDNBOOST_TEST_EXECUTION_MONITOR_HPP_071894GER
33#define NDNBOOST_TEST_EXECUTION_MONITOR_HPP_071894GER
Jeff Thompsonef2d5a42013-08-22 19:09:24 -070034
35// Boost.Test
36#include <ndnboost/test/detail/global_typedef.hpp>
37#include <ndnboost/test/detail/fwd_decl.hpp>
38#include <ndnboost/test/utils/callback.hpp>
39#include <ndnboost/test/utils/class_properties.hpp>
40
41// Boost
42#include <ndnboost/scoped_ptr.hpp>
43#include <ndnboost/scoped_array.hpp>
44#include <ndnboost/type.hpp>
45#include <ndnboost/cstdlib.hpp>
46
47#include <ndnboost/test/detail/suppress_warnings.hpp>
48
49//____________________________________________________________________________//
50
51namespace ndnboost {
52
53namespace detail {
54
55// ************************************************************************** //
56// ************** detail::translate_exception_base ************** //
57// ************************************************************************** //
58
Jeff Thompson3d613fd2013-10-15 15:39:04 -070059class NDNBOOST_TEST_DECL translate_exception_base {
Jeff Thompsonef2d5a42013-08-22 19:09:24 -070060public:
61 // Constructor
62 explicit translate_exception_base( ndnboost::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
72protected:
73 // Data members
74 ndnboost::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
Jeff Thompson3d613fd2013-10-15 15:39:04 -070085class NDNBOOST_TEST_DECL execution_exception {
Jeff Thompsonef2d5a42013-08-22 19:09:24 -070086 typedef ndnboost::unit_test::const_string const_string;
87public:
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
Jeff Thompson3d613fd2013-10-15 15:39:04 -0700116 struct NDNBOOST_TEST_DECL location {
Jeff Thompsonef2d5a42013-08-22 19:09:24 -0700117 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
132private:
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
Jeff Thompson3d613fd2013-10-15 15:39:04 -0700143class NDNBOOST_TEST_DECL execution_monitor {
Jeff Thompsonef2d5a42013-08-22 19:09:24 -0700144public:
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, ndnboost::type<Exception>* = 0 );
187
188private:
189 // implementation helpers
190 int catch_signals( unit_test::callback0<int> const& F );
191
192 // Data members
193 ndnboost::scoped_ptr<detail::translate_exception_base> m_custom_translators;
194 ndnboost::scoped_array<char> m_alt_stack;
195}; // execution_monitor
196
197namespace detail {
198
199// ************************************************************************** //
200// ************** detail::translate_exception ************** //
201// ************************************************************************** //
202
203template<typename Exception, typename ExceptionTranslator>
204class translate_exception : public translate_exception_base
205{
206 typedef ndnboost::scoped_ptr<translate_exception_base> base_ptr;
207public:
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 ndnboost::exit_exception_failure;
218 }
219 }
220
221private:
222 // Data members
223 ExceptionTranslator m_translator;
224};
225
226} // namespace detail
227
228template<typename Exception, typename ExceptionTranslator>
229void
230execution_monitor::register_exception_translator( ExceptionTranslator const& tr, ndnboost::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
240struct execution_aborted {};
241
242// ************************************************************************** //
243// ************** system_error ************** //
244// ************************************************************************** //
245
246class system_error {
247public:
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
Jeff Thompson3d613fd2013-10-15 15:39:04 -0700255#define NDNBOOST_TEST_SYS_ASSERT( exp ) if( (exp) ) ; else throw ::ndnboost::system_error( NDNBOOST_STRINGIZE( exp ) )
Jeff Thompsonef2d5a42013-08-22 19:09:24 -0700256
257} // namespace ndnboost
258
259//____________________________________________________________________________//
260
261#include <ndnboost/test/detail/enable_warnings.hpp>
262
263#endif