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