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 { may_throw_on_copymay_throw_on_copy26 may_throw_on_copy(): 27 throw_(false) 28 { 29 } 30 may_throw_on_copymay_throw_on_copy31 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 derives_nothingderives_nothing47 derives_nothing( int & c ): 48 count(c) 49 { 50 ++count; 51 } 52 derives_nothingderives_nothing53 derives_nothing( derives_nothing const & x ): 54 count(x.count) 55 { 56 ++count; 57 } 58 ~derives_nothingderives_nothing59 ~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 derives_std_boost_exceptionderives_std_boost_exception78 derives_std_boost_exception( char const * wh="derives_std_boost_exception" ): 79 wh_(wh) 80 { 81 } 82 whatderives_std_boost_exception83 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 test_std_exception()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>(x); 152 BOOST_TEST(t!=0 && *t!=0 && **t==typeid(T)); 153 std::string s=diagnostic_information(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 test_std_exception_what()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>(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 test_throw_on_copy()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 307 int main()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(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(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>(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>(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>(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>(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>(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>(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>(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>(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>(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>(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(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(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