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 | |
20 | typedef boost::error_info<struct my_tag,int> my_info; |
21 | |
22 | template <class T> |
23 | struct |
24 | may_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 | |
41 | struct |
42 | derives_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 | |
65 | struct |
66 | derives_std_exception: |
67 | std::exception |
68 | { |
69 | }; |
70 | |
71 | struct |
72 | derives_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 | |
89 | struct |
90 | derives_boost_exception: |
91 | boost::exception |
92 | { |
93 | }; |
94 | |
95 | template <class T> |
96 | void |
97 | test_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 | |
169 | template <class T> |
170 | void |
171 | test_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 | |
243 | template <class Throw,class Catch> |
244 | void |
245 | test_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 | |
307 | int |
308 | main() |
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 |