• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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>
12 #include <ios>
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     {
may_throw_on_copymay_throw_on_copy20     may_throw_on_copy():
21         throw_(false)
22         {
23         }
24 
may_throw_on_copymay_throw_on_copy25     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
derives_nothingderives_nothing41     derives_nothing( int & c ):
42         count(c)
43         {
44         ++count;
45         }
46 
derives_nothingderives_nothing47     derives_nothing( derives_nothing const & x ):
48         count(x.count)
49         {
50         ++count;
51         }
52 
~derives_nothingderives_nothing53     ~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 
derives_std_boost_exceptionderives_std_boost_exception72     derives_std_boost_exception( char const * wh="derives_std_boost_exception" ):
73         wh_(wh)
74         {
75         }
76 
whatderives_std_boost_exception77     char const * what() const BOOST_NOEXCEPT_OR_NOTHROW
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
test_std_exception()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
test_std_exception_what()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
test_throw_on_copy()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
main()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     }
600