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()91test_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()165test_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()239test_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()302main() 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