1 /*
2 * Copyright Andrey Semashev 2007 - 2015.
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 /*!
8 * \file util_exception_handler.cpp
9 * \author Andrey Semashev
10 * \date 13.07.2009
11 *
12 * \brief This header contains tests for the exception handler functional objects.
13 */
14
15 #define BOOST_TEST_MODULE util_exception_handler
16
17 #include <string>
18 #include <typeinfo>
19 #include <stdexcept>
20 #include <boost/mpl/vector.hpp>
21 #include <boost/smart_ptr/scoped_ptr.hpp>
22 #include <boost/test/unit_test.hpp>
23 #include <boost/log/utility/exception_handler.hpp>
24
25 namespace logging = boost::log;
26
27 namespace {
28
29 struct my_handler1
30 {
31 typedef void result_type;
32
33 std::type_info const*& m_pExceptionType;
34
my_handler1__anonb44072340111::my_handler135 my_handler1(std::type_info const*& p) : m_pExceptionType(p) {}
36
operator ()__anonb44072340111::my_handler137 void operator() (std::exception&) const
38 {
39 m_pExceptionType = &typeid(std::exception);
40 }
operator ()__anonb44072340111::my_handler141 void operator() (std::runtime_error&) const
42 {
43 m_pExceptionType = &typeid(std::runtime_error);
44 }
45 };
46
47 struct my_handler2
48 {
49 typedef void result_type;
50 typedef boost::mpl::vector< std::runtime_error, std::exception >::type exception_types;
51
52 std::type_info const*& m_pExceptionType;
53
my_handler2__anonb44072340111::my_handler254 explicit my_handler2(std::type_info const*& p) : m_pExceptionType(p) {}
55
operator ()__anonb44072340111::my_handler256 void operator() (std::exception&) const
57 {
58 m_pExceptionType = &typeid(std::exception);
59 }
operator ()__anonb44072340111::my_handler260 void operator() (std::runtime_error&) const
61 {
62 m_pExceptionType = &typeid(std::runtime_error);
63 }
64 };
65
66 struct my_handler1_nothrow
67 {
68 typedef void result_type;
69
70 std::type_info const*& m_pExceptionType;
71
my_handler1_nothrow__anonb44072340111::my_handler1_nothrow72 my_handler1_nothrow(std::type_info const*& p) : m_pExceptionType(p) {}
73
operator ()__anonb44072340111::my_handler1_nothrow74 void operator() (std::exception&) const
75 {
76 m_pExceptionType = &typeid(std::exception);
77 }
operator ()__anonb44072340111::my_handler1_nothrow78 void operator() (std::runtime_error&) const
79 {
80 m_pExceptionType = &typeid(std::runtime_error);
81 }
operator ()__anonb44072340111::my_handler1_nothrow82 void operator() () const
83 {
84 m_pExceptionType = &typeid(void);
85 }
86 };
87
88 struct my_handler2_nothrow
89 {
90 typedef void result_type;
91 typedef boost::mpl::vector< std::runtime_error, std::exception >::type exception_types;
92
93 std::type_info const*& m_pExceptionType;
94
my_handler2_nothrow__anonb44072340111::my_handler2_nothrow95 explicit my_handler2_nothrow(std::type_info const*& p) : m_pExceptionType(p) {}
96
operator ()__anonb44072340111::my_handler2_nothrow97 void operator() (std::exception&) const
98 {
99 m_pExceptionType = &typeid(std::exception);
100 }
operator ()__anonb44072340111::my_handler2_nothrow101 void operator() (std::runtime_error&) const
102 {
103 m_pExceptionType = &typeid(std::runtime_error);
104 }
operator ()__anonb44072340111::my_handler2_nothrow105 void operator() () const
106 {
107 m_pExceptionType = &typeid(void);
108 }
109 };
110
111 struct my_exception {};
112
113 struct my_function0
114 {
115 struct impl_base
116 {
~impl_base__anonb44072340111::my_function0::impl_base117 virtual ~impl_base() {}
118 virtual void invoke() = 0;
119 };
120
121 template< typename T >
122 struct impl : public impl_base
123 {
124 T m_Fun;
125
impl__anonb44072340111::my_function0::impl126 explicit impl(T const& fun) : m_Fun(fun) {}
invoke__anonb44072340111::my_function0::impl127 void invoke() { m_Fun(); }
128 };
129
130 private:
131 boost::scoped_ptr< impl_base > m_pImpl;
132
133 public:
134 template< typename T >
operator =__anonb44072340111::my_function0135 my_function0& operator= (T const& fun)
136 {
137 m_pImpl.reset(new impl< T >(fun));
138 return *this;
139 }
140
operator ()__anonb44072340111::my_function0141 void operator() () const
142 {
143 m_pImpl->invoke();
144 }
145 };
146
147 } // namespace
148
149 // Tests for handler with explicit exception types specification
BOOST_AUTO_TEST_CASE(explicit_exception_types)150 BOOST_AUTO_TEST_CASE(explicit_exception_types)
151 {
152 std::type_info const* pExceptionType = 0;
153 my_function0 handler;
154 handler = logging::make_exception_handler<
155 std::runtime_error,
156 std::exception
157 >(my_handler1(pExceptionType));
158
159 try
160 {
161 throw std::runtime_error("error");
162 }
163 catch (...)
164 {
165 handler();
166 }
167 BOOST_REQUIRE(pExceptionType != 0);
168 BOOST_CHECK(*pExceptionType == typeid(std::runtime_error));
169 pExceptionType = 0;
170
171 try
172 {
173 throw std::logic_error("error");
174 }
175 catch (...)
176 {
177 handler();
178 }
179 BOOST_REQUIRE(pExceptionType != 0);
180 BOOST_CHECK(*pExceptionType == typeid(std::exception));
181 pExceptionType = 0;
182
183 try
184 {
185 throw my_exception();
186 }
187 catch (...)
188 {
189 BOOST_CHECK_THROW(handler(), my_exception);
190 }
191 BOOST_REQUIRE(pExceptionType == 0);
192
193 // Verify that exception types are checked in the specified order
194 handler = logging::make_exception_handler<
195 std::exception,
196 std::runtime_error
197 >(my_handler1(pExceptionType));
198
199 try
200 {
201 throw std::runtime_error("error");
202 }
203 catch (...)
204 {
205 handler();
206 }
207 BOOST_REQUIRE(pExceptionType != 0);
208 BOOST_CHECK(*pExceptionType == typeid(std::exception));
209 pExceptionType = 0;
210 }
211
212 // Tests for handler with explicit exception types specification (no-throw version)
BOOST_AUTO_TEST_CASE(explicit_exception_types_nothrow)213 BOOST_AUTO_TEST_CASE(explicit_exception_types_nothrow)
214 {
215 std::type_info const* pExceptionType = 0;
216 my_function0 handler;
217 handler = logging::make_exception_handler<
218 std::runtime_error,
219 std::exception
220 >(my_handler1_nothrow(pExceptionType), std::nothrow);
221
222 try
223 {
224 throw std::runtime_error("error");
225 }
226 catch (...)
227 {
228 handler();
229 }
230 BOOST_REQUIRE(pExceptionType != 0);
231 BOOST_CHECK(*pExceptionType == typeid(std::runtime_error));
232 pExceptionType = 0;
233
234 try
235 {
236 throw std::logic_error("error");
237 }
238 catch (...)
239 {
240 handler();
241 }
242 BOOST_REQUIRE(pExceptionType != 0);
243 BOOST_CHECK(*pExceptionType == typeid(std::exception));
244 pExceptionType = 0;
245
246 try
247 {
248 throw my_exception();
249 }
250 catch (...)
251 {
252 BOOST_CHECK_NO_THROW(handler());
253 }
254 BOOST_REQUIRE(pExceptionType != 0);
255 BOOST_CHECK(*pExceptionType == typeid(void));
256 pExceptionType = 0;
257
258 // Verify that exception types are checked in the specified order
259 handler = logging::make_exception_handler<
260 std::exception,
261 std::runtime_error
262 >(my_handler1_nothrow(pExceptionType), std::nothrow);
263
264 try
265 {
266 throw std::runtime_error("error");
267 }
268 catch (...)
269 {
270 handler();
271 }
272 BOOST_REQUIRE(pExceptionType != 0);
273 BOOST_CHECK(*pExceptionType == typeid(std::exception));
274 pExceptionType = 0;
275 }
276
277 // Tests for handler with self-contained exception types
BOOST_AUTO_TEST_CASE(self_contained_exception_types)278 BOOST_AUTO_TEST_CASE(self_contained_exception_types)
279 {
280 std::type_info const* pExceptionType = 0;
281 my_function0 handler;
282 handler = logging::make_exception_handler(my_handler2(pExceptionType));
283
284 try
285 {
286 throw std::runtime_error("error");
287 }
288 catch (...)
289 {
290 handler();
291 }
292 BOOST_REQUIRE(pExceptionType != 0);
293 BOOST_CHECK(*pExceptionType == typeid(std::runtime_error));
294 pExceptionType = 0;
295
296 try
297 {
298 throw std::logic_error("error");
299 }
300 catch (...)
301 {
302 handler();
303 }
304 BOOST_REQUIRE(pExceptionType != 0);
305 BOOST_CHECK(*pExceptionType == typeid(std::exception));
306 pExceptionType = 0;
307
308 try
309 {
310 throw my_exception();
311 }
312 catch (...)
313 {
314 BOOST_CHECK_THROW(handler(), my_exception);
315 }
316 BOOST_REQUIRE(pExceptionType == 0);
317 }
318
319 // Tests for handler with self-contained exception types (no-throw version)
BOOST_AUTO_TEST_CASE(self_contained_exception_types_nothrow)320 BOOST_AUTO_TEST_CASE(self_contained_exception_types_nothrow)
321 {
322 std::type_info const* pExceptionType = 0;
323 my_function0 handler;
324 handler = logging::make_exception_handler(my_handler2_nothrow(pExceptionType), std::nothrow);
325
326 try
327 {
328 throw std::runtime_error("error");
329 }
330 catch (...)
331 {
332 handler();
333 }
334 BOOST_REQUIRE(pExceptionType != 0);
335 BOOST_CHECK(*pExceptionType == typeid(std::runtime_error));
336 pExceptionType = 0;
337
338 try
339 {
340 throw std::logic_error("error");
341 }
342 catch (...)
343 {
344 handler();
345 }
346 BOOST_REQUIRE(pExceptionType != 0);
347 BOOST_CHECK(*pExceptionType == typeid(std::exception));
348 pExceptionType = 0;
349
350 try
351 {
352 throw my_exception();
353 }
354 catch (...)
355 {
356 BOOST_CHECK_NO_THROW(handler());
357 }
358 BOOST_REQUIRE(pExceptionType != 0);
359 BOOST_CHECK(*pExceptionType == typeid(void));
360 pExceptionType = 0;
361 }
362