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 |
---|