cloning_test.cpp 15 KB

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