• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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