1//Copyright (c) 2006-2009 Emil Dotchevski and Reverge Studios, Inc.
2
3//Distributed under the Boost Software License, Version 1.0. (See accompanying
4//file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
5
6#include <boost/config.hpp>
7
8#if defined( BOOST_NO_EXCEPTIONS )
9# error This program requires exception handling.
10#endif
11
12#include <boost/exception_ptr.hpp>
13#include <boost/exception/get_error_info.hpp>
14#include <boost/exception/errinfo_nested_exception.hpp>
15#include <boost/detail/lightweight_test.hpp>
16#include <boost/detail/workaround.hpp>
17#include <string>
18#include <ios>
19
20typedef boost::error_info<struct my_tag,int> my_info;
21
22template <class T>
23struct
24may_throw_on_copy
25 {
26 may_throw_on_copy():
27 throw_(false)
28 {
29 }
30
31 may_throw_on_copy( may_throw_on_copy const & x ):
32 throw_(x.throw_)
33 {
34 if( throw_ )
35 throw T();
36 }
37
38 bool throw_;
39 };
40
41struct
42derives_nothing
43 {
44 int & count;
45
46 explicit
47 derives_nothing( int & c ):
48 count(c)
49 {
50 ++count;
51 }
52
53 derives_nothing( derives_nothing const & x ):
54 count(x.count)
55 {
56 ++count;
57 }
58
59 ~derives_nothing()
60 {
61 --count;
62 }
63 };
64
65struct
66derives_std_exception:
67 std::exception
68 {
69 };
70
71struct
72derives_std_boost_exception:
73 std::exception,
74 boost::exception
75 {
76 char const * const wh_;
77
78 derives_std_boost_exception( char const * wh="derives_std_boost_exception" ):
79 wh_(wh)
80 {
81 }
82
83 char const * what() const BOOST_NOEXCEPT_OR_NOTHROW
84 {
85 return wh_;
86 }
87 };
88
89struct
90derives_boost_exception:
91 boost::exception
92 {
93 };
94
95template <class T>
96void
97test_std_exception()
98 {
99 try
100 {
101 throw T();
102 }
103 catch(
104 ... )
105 {
106 boost::exception_ptr p = boost::current_exception();
107 BOOST_TEST(!(p==boost::exception_ptr()));
108 BOOST_TEST(p!=boost::exception_ptr());
109 BOOST_TEST(p);
110 try
111 {
112 rethrow_exception(p);
113 BOOST_TEST(false);
114 }
115 catch(
116 T & )
117 {
118 boost::exception_ptr p = boost::current_exception();
119 BOOST_TEST(!(p==boost::exception_ptr()));
120 BOOST_TEST(p!=boost::exception_ptr());
121 BOOST_TEST(p);
122 try
123 {
124 rethrow_exception(p);
125 BOOST_TEST(false);
126 }
127 catch(
128 T & )
129 {
130 }
131 catch(
132 ... )
133 {
134 BOOST_TEST(false);
135 }
136 }
137 catch(
138 ... )
139 {
140 BOOST_TEST(false);
141 }
142 try
143 {
144 rethrow_exception(p);
145 BOOST_TEST(false);
146 }
147 catch(
148 boost::exception & x )
149 {
150#ifndef BOOST_NO_RTTI
151 std::type_info const * const * t=boost::get_error_info<boost::original_exception_type>(some_exception&: x);
152 BOOST_TEST(t!=0 && *t!=0 && **t==typeid(T));
153 std::string s=diagnostic_information(e: x);
154 BOOST_TEST(!s.empty());
155#endif
156 }
157 catch(
158 T & )
159 {
160 }
161 catch(
162 ... )
163 {
164 BOOST_TEST(false);
165 }
166 }
167 }
168
169template <class T>
170void
171test_std_exception_what()
172 {
173 try
174 {
175 throw T("what");
176 }
177 catch(
178 ... )
179 {
180 boost::exception_ptr p = boost::current_exception();
181 BOOST_TEST(!(p==boost::exception_ptr()));
182 BOOST_TEST(p!=boost::exception_ptr());
183 BOOST_TEST(p);
184 try
185 {
186 rethrow_exception(p);
187 BOOST_TEST(false);
188 }
189 catch(
190 T & x )
191 {
192 BOOST_TEST(std::string(x.what()).find("what")!=std::string::npos);
193 boost::exception_ptr p = boost::current_exception();
194 BOOST_TEST(!(p==boost::exception_ptr()));
195 BOOST_TEST(p!=boost::exception_ptr());
196 BOOST_TEST(p);
197 try
198 {
199 rethrow_exception(p);
200 BOOST_TEST(false);
201 }
202 catch(
203 T & x )
204 {
205 BOOST_TEST(std::string(x.what()).find("what")!=std::string::npos);
206 }
207 catch(
208 ... )
209 {
210 BOOST_TEST(false);
211 }
212 }
213 catch(
214 ... )
215 {
216 BOOST_TEST(false);
217 }
218 try
219 {
220 rethrow_exception(p);
221 BOOST_TEST(false);
222 }
223 catch(
224 boost::exception & x )
225 {
226#ifndef BOOST_NO_RTTI
227 std::type_info const * const * t=boost::get_error_info<boost::original_exception_type>(some_exception&: x);
228 BOOST_TEST(t!=0 && *t!=0 && **t==typeid(T));
229#endif
230 }
231 catch(
232 T & )
233 {
234 }
235 catch(
236 ... )
237 {
238 BOOST_TEST(false);
239 }
240 }
241 }
242
243template <class Throw,class Catch>
244void
245test_throw_on_copy()
246 {
247 try
248 {
249 try
250 {
251 throw boost::enable_current_exception(may_throw_on_copy<Throw>());
252 }
253 catch(
254 may_throw_on_copy<Throw> & x )
255 {
256 x.throw_=true;
257 throw;
258 }
259 catch(
260 ... )
261 {
262 BOOST_TEST(false);
263 }
264 }
265 catch(
266 ... )
267 {
268 boost::exception_ptr p = boost::current_exception();
269 BOOST_TEST(!(p==boost::exception_ptr()));
270 BOOST_TEST(p!=boost::exception_ptr());
271 BOOST_TEST(p);
272 try
273 {
274 rethrow_exception(p);
275 BOOST_TEST(false);
276 }
277 catch(
278 Catch & )
279 {
280 boost::exception_ptr p = boost::current_exception();
281 BOOST_TEST(!(p==boost::exception_ptr()));
282 BOOST_TEST(p!=boost::exception_ptr());
283 BOOST_TEST(p);
284 try
285 {
286 boost::rethrow_exception(p);
287 BOOST_TEST(false);
288 }
289 catch(
290 Catch & )
291 {
292 }
293 catch(
294 ... )
295 {
296 BOOST_TEST(false);
297 }
298 }
299 catch(
300 ... )
301 {
302 BOOST_TEST(false);
303 }
304 }
305 }
306
307int
308main()
309 {
310 BOOST_TEST( boost::exception_ptr()==boost::exception_ptr() );
311 BOOST_TEST( !(boost::exception_ptr()!=boost::exception_ptr()) );
312 BOOST_TEST( !boost::exception_ptr() );
313
314 int count=0;
315 try
316 {
317 throw boost::enable_current_exception(x: derives_nothing(count));
318 }
319 catch(
320 ... )
321 {
322 boost::exception_ptr p = boost::current_exception();
323 BOOST_TEST(!(p==boost::exception_ptr()));
324 BOOST_TEST(p!=boost::exception_ptr());
325 BOOST_TEST(p);
326 try
327 {
328 rethrow_exception(p);
329 BOOST_TEST(false);
330 }
331 catch(
332 derives_nothing & )
333 {
334 }
335 catch(
336 ... )
337 {
338 BOOST_TEST(false);
339 }
340 }
341 BOOST_TEST(count==0);
342
343 try
344 {
345 throw boost::enable_current_exception(x: derives_std_exception());
346 }
347 catch(
348 ... )
349 {
350 boost::exception_ptr p = boost::current_exception();
351 BOOST_TEST(!(p==boost::exception_ptr()));
352 BOOST_TEST(p!=boost::exception_ptr());
353 BOOST_TEST(p);
354 try
355 {
356 rethrow_exception(p);
357 BOOST_TEST(false);
358 }
359 catch(
360 derives_std_exception & )
361 {
362 boost::exception_ptr p = boost::current_exception();
363 BOOST_TEST(!(p==boost::exception_ptr()));
364 BOOST_TEST(p!=boost::exception_ptr());
365 BOOST_TEST(p);
366 try
367 {
368 rethrow_exception(p);
369 BOOST_TEST(false);
370 }
371 catch(
372 derives_std_exception & )
373 {
374 }
375 catch(
376 ... )
377 {
378 BOOST_TEST(false);
379 }
380 }
381 catch(
382 ... )
383 {
384 BOOST_TEST(false);
385 }
386 }
387
388 try
389 {
390 throw derives_std_exception();
391 }
392 catch(
393 ... )
394 {
395 boost::exception_ptr p = boost::current_exception();
396 BOOST_TEST(!(p==boost::exception_ptr()));
397 BOOST_TEST(p!=boost::exception_ptr());
398 BOOST_TEST(p);
399 try
400 {
401 rethrow_exception(p);
402 BOOST_TEST(false);
403 }
404 catch(
405 derives_std_exception & )
406 {
407 //Yay! Non-intrusive cloning supported!
408 }
409 catch(
410 boost::unknown_exception & e )
411 {
412#ifndef BOOST_NO_RTTI
413 std::type_info const * const * t=boost::get_error_info<boost::original_exception_type>(some_exception&: e);
414 BOOST_TEST(t!=0 && *t!=0 && **t==typeid(derives_std_exception));
415#endif
416 }
417 catch(
418 ... )
419 {
420 BOOST_TEST(false);
421 }
422 }
423
424 test_std_exception_what<std::domain_error>();
425 test_std_exception_what<std::invalid_argument>();
426 test_std_exception_what<std::length_error>();
427 test_std_exception_what<std::out_of_range>();
428 test_std_exception_what<std::logic_error>();
429 test_std_exception_what<std::range_error>();
430 test_std_exception_what<std::overflow_error>();
431 test_std_exception_what<std::underflow_error>();
432#if !defined(_GLIBCXX_USE_CXX11_ABI) || !_GLIBCXX_USE_CXX11_ABI
433 test_std_exception_what<std::ios_base::failure>();
434#endif
435 test_std_exception_what<std::runtime_error>();
436 test_std_exception<std::bad_alloc>();
437#ifndef BOOST_NO_TYPEID
438 test_std_exception<std::bad_cast>();
439 test_std_exception<std::bad_typeid>();
440#endif
441 test_std_exception<std::bad_exception>();
442 test_std_exception<std::exception>();
443
444 try
445 {
446 throw derives_std_boost_exception() << my_info(42);
447 }
448 catch(
449 ... )
450 {
451 boost::exception_ptr p = boost::current_exception();
452 BOOST_TEST(!(p==boost::exception_ptr()));
453 BOOST_TEST(p!=boost::exception_ptr());
454 BOOST_TEST(p);
455 try
456 {
457 rethrow_exception(p);
458 BOOST_TEST(false);
459 }
460 catch(
461 derives_std_boost_exception & x )
462 {
463 //Yay! Non-intrusive cloning supported!
464 BOOST_TEST(boost::get_error_info<my_info>(x));
465 if( int const * p=boost::get_error_info<my_info>(some_exception&: x) )
466 BOOST_TEST(*p==42);
467 }
468 catch(
469 boost::unknown_exception & x )
470 {
471 BOOST_TEST(boost::get_error_info<my_info>(x));
472 if( int const * p=boost::get_error_info<my_info>(some_exception&: x) )
473 BOOST_TEST(*p==42);
474#ifndef BOOST_NO_RTTI
475 {
476 std::type_info const * const * t=boost::get_error_info<boost::original_exception_type>(some_exception&: x);
477 BOOST_TEST(t && *t && **t==typeid(derives_std_boost_exception));
478 }
479#endif
480 boost::exception_ptr p = boost::current_exception();
481 BOOST_TEST(!(p==boost::exception_ptr()));
482 BOOST_TEST(p!=boost::exception_ptr());
483 BOOST_TEST(p);
484 try
485 {
486 rethrow_exception(p);
487 BOOST_TEST(false);
488 }
489 catch(
490 boost::unknown_exception & x )
491 {
492 BOOST_TEST(boost::get_error_info<my_info>(x));
493 if( int const * p=boost::get_error_info<my_info>(some_exception&: x) )
494 BOOST_TEST(*p==42);
495#ifndef BOOST_NO_RTTI
496 std::type_info const * const * t=boost::get_error_info<boost::original_exception_type>(some_exception&: x);
497 BOOST_TEST(t && *t && **t==typeid(derives_std_boost_exception));
498#endif
499 }
500 catch(
501 ... )
502 {
503 BOOST_TEST(false);
504 }
505 }
506 catch(
507 ... )
508 {
509 BOOST_TEST(false);
510 }
511 }
512
513 try
514 {
515 throw derives_boost_exception() << my_info(42);
516 }
517 catch(
518 ... )
519 {
520 boost::exception_ptr p = boost::current_exception();
521 BOOST_TEST(!(p==boost::exception_ptr()));
522 BOOST_TEST(p!=boost::exception_ptr());
523 BOOST_TEST(p);
524 try
525 {
526 rethrow_exception(p);
527 BOOST_TEST(false);
528 }
529 catch(
530 derives_boost_exception & x )
531 {
532 //Yay! Non-intrusive cloning supported!
533 BOOST_TEST(boost::get_error_info<my_info>(x));
534 if( int const * p=boost::get_error_info<my_info>(some_exception&: x) )
535 BOOST_TEST(*p==42);
536 }
537 catch(
538 boost::unknown_exception & x )
539 {
540 BOOST_TEST(boost::get_error_info<my_info>(x));
541 if( int const * p=boost::get_error_info<my_info>(some_exception&: x) )
542 BOOST_TEST(*p==42);
543#ifndef BOOST_NO_RTTI
544 {
545 std::type_info const * const * t=boost::get_error_info<boost::original_exception_type>(some_exception&: x);
546 BOOST_TEST(t && *t && **t==typeid(derives_boost_exception));
547 }
548#endif
549 boost::exception_ptr p = boost::current_exception();
550 BOOST_TEST(!(p==boost::exception_ptr()));
551 BOOST_TEST(p!=boost::exception_ptr());
552 BOOST_TEST(p);
553 try
554 {
555 rethrow_exception(p);
556 BOOST_TEST(false);
557 }
558 catch(
559 boost::unknown_exception & x )
560 {
561 BOOST_TEST(boost::get_error_info<my_info>(x));
562 if( int const * p=boost::get_error_info<my_info>(some_exception&: x) )
563 BOOST_TEST(*p==42);
564 }
565 catch(
566 ... )
567 {
568 BOOST_TEST(false);
569 }
570 }
571 catch(
572 ... )
573 {
574 BOOST_TEST(false);
575 }
576 }
577
578 test_throw_on_copy<std::bad_alloc,std::bad_alloc>();
579 test_throw_on_copy<int,std::bad_exception>();
580
581 try
582 {
583 throw boost::enable_current_exception(x: derives_std_boost_exception("what1"));
584 }
585 catch(
586 ... )
587 {
588 boost::exception_ptr p=boost::current_exception();
589 {
590 std::string s=diagnostic_information(p);
591 BOOST_TEST(s.find("what1")!=s.npos);
592 }
593 try
594 {
595 throw boost::enable_current_exception(x: derives_std_boost_exception("what2") << boost::errinfo_nested_exception(p) );
596 }
597 catch(
598 ... )
599 {
600 std::string s=boost::current_exception_diagnostic_information();
601 BOOST_TEST(s.find("what1")!=s.npos);
602 BOOST_TEST(s.find("what2")!=s.npos);
603 }
604 }
605 BOOST_TEST(!diagnostic_information(boost::exception_ptr()).empty());
606 return boost::report_errors();
607 }
608

source code of boost/libs/exception/test/cloning_test.cpp