| //Copyright (c) 2006-2009 Emil Dotchevski and Reverge Studios, Inc. |
| |
| //Distributed under the Boost Software License, Version 1.0. (See accompanying |
| //file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) |
| |
| #include <boost/exception_ptr.hpp> |
| #include <boost/exception/get_error_info.hpp> |
| #include <boost/exception/errinfo_nested_exception.hpp> |
| #include <boost/detail/lightweight_test.hpp> |
| #include <boost/detail/workaround.hpp> |
| #include <string> |
| |
| typedef boost::error_info<struct my_tag,int> my_info; |
| |
| template <class T> |
| struct |
| may_throw_on_copy |
| { |
| may_throw_on_copy(): |
| throw_(false) |
| { |
| } |
| |
| may_throw_on_copy( may_throw_on_copy const & x ): |
| throw_(x.throw_) |
| { |
| if( throw_ ) |
| throw T(); |
| } |
| |
| bool throw_; |
| }; |
| |
| struct |
| derives_nothing |
| { |
| int & count; |
| |
| explicit |
| derives_nothing( int & c ): |
| count(c) |
| { |
| ++count; |
| } |
| |
| derives_nothing( derives_nothing const & x ): |
| count(x.count) |
| { |
| ++count; |
| } |
| |
| ~derives_nothing() |
| { |
| --count; |
| } |
| }; |
| |
| struct |
| derives_std_exception: |
| std::exception |
| { |
| }; |
| |
| struct |
| derives_std_boost_exception: |
| std::exception, |
| boost::exception |
| { |
| char const * const wh_; |
| |
| derives_std_boost_exception( char const * wh="derives_std_boost_exception" ): |
| wh_(wh) |
| { |
| } |
| |
| char const * what() const throw() |
| { |
| return wh_; |
| } |
| }; |
| |
| struct |
| derives_boost_exception: |
| boost::exception |
| { |
| }; |
| |
| template <class T> |
| void |
| test_std_exception() |
| { |
| try |
| { |
| throw T(); |
| } |
| catch( |
| ... ) |
| { |
| boost::exception_ptr p = boost::current_exception(); |
| BOOST_TEST(!(p==boost::exception_ptr())); |
| BOOST_TEST(p!=boost::exception_ptr()); |
| BOOST_TEST(p); |
| try |
| { |
| rethrow_exception(p); |
| BOOST_TEST(false); |
| } |
| catch( |
| T & ) |
| { |
| boost::exception_ptr p = boost::current_exception(); |
| BOOST_TEST(!(p==boost::exception_ptr())); |
| BOOST_TEST(p!=boost::exception_ptr()); |
| BOOST_TEST(p); |
| try |
| { |
| rethrow_exception(p); |
| BOOST_TEST(false); |
| } |
| catch( |
| T & ) |
| { |
| } |
| catch( |
| ... ) |
| { |
| BOOST_TEST(false); |
| } |
| } |
| catch( |
| ... ) |
| { |
| BOOST_TEST(false); |
| } |
| try |
| { |
| rethrow_exception(p); |
| BOOST_TEST(false); |
| } |
| catch( |
| boost::exception & x ) |
| { |
| #ifndef BOOST_NO_RTTI |
| std::type_info const * const * t=boost::get_error_info<boost::original_exception_type>(x); |
| BOOST_TEST(t!=0 && *t!=0 && **t==typeid(T)); |
| #endif |
| } |
| catch( |
| ... ) |
| { |
| BOOST_TEST(false); |
| } |
| } |
| } |
| |
| template <class T> |
| void |
| test_std_exception_what() |
| { |
| try |
| { |
| throw T("what"); |
| } |
| catch( |
| ... ) |
| { |
| boost::exception_ptr p = boost::current_exception(); |
| BOOST_TEST(!(p==boost::exception_ptr())); |
| BOOST_TEST(p!=boost::exception_ptr()); |
| BOOST_TEST(p); |
| try |
| { |
| rethrow_exception(p); |
| BOOST_TEST(false); |
| } |
| catch( |
| T & x ) |
| { |
| BOOST_TEST(std::string("what")==x.what()); |
| boost::exception_ptr p = boost::current_exception(); |
| BOOST_TEST(!(p==boost::exception_ptr())); |
| BOOST_TEST(p!=boost::exception_ptr()); |
| BOOST_TEST(p); |
| try |
| { |
| rethrow_exception(p); |
| BOOST_TEST(false); |
| } |
| catch( |
| T & x ) |
| { |
| BOOST_TEST(std::string("what")==x.what()); |
| } |
| catch( |
| ... ) |
| { |
| BOOST_TEST(false); |
| } |
| } |
| catch( |
| ... ) |
| { |
| BOOST_TEST(false); |
| } |
| try |
| { |
| rethrow_exception(p); |
| BOOST_TEST(false); |
| } |
| catch( |
| boost::exception & x ) |
| { |
| #ifndef BOOST_NO_RTTI |
| std::type_info const * const * t=boost::get_error_info<boost::original_exception_type>(x); |
| BOOST_TEST(t!=0 && *t!=0 && **t==typeid(T)); |
| #endif |
| } |
| catch( |
| ... ) |
| { |
| BOOST_TEST(false); |
| } |
| } |
| } |
| |
| template <class Throw,class Catch> |
| void |
| test_throw_on_copy() |
| { |
| try |
| { |
| try |
| { |
| throw boost::enable_current_exception(may_throw_on_copy<Throw>()); |
| } |
| catch( |
| may_throw_on_copy<Throw> & x ) |
| { |
| x.throw_=true; |
| throw; |
| } |
| catch( |
| ... ) |
| { |
| BOOST_TEST(false); |
| } |
| } |
| catch( |
| ... ) |
| { |
| boost::exception_ptr p = boost::current_exception(); |
| BOOST_TEST(!(p==boost::exception_ptr())); |
| BOOST_TEST(p!=boost::exception_ptr()); |
| BOOST_TEST(p); |
| try |
| { |
| rethrow_exception(p); |
| BOOST_TEST(false); |
| } |
| catch( |
| Catch & ) |
| { |
| boost::exception_ptr p = boost::current_exception(); |
| BOOST_TEST(!(p==boost::exception_ptr())); |
| BOOST_TEST(p!=boost::exception_ptr()); |
| BOOST_TEST(p); |
| try |
| { |
| boost::rethrow_exception(p); |
| BOOST_TEST(false); |
| } |
| catch( |
| Catch & ) |
| { |
| } |
| catch( |
| ... ) |
| { |
| BOOST_TEST(false); |
| } |
| } |
| catch( |
| ... ) |
| { |
| BOOST_TEST(false); |
| } |
| } |
| } |
| |
| int |
| main() |
| { |
| BOOST_TEST( boost::exception_ptr()==boost::exception_ptr() ); |
| BOOST_TEST( !(boost::exception_ptr()!=boost::exception_ptr()) ); |
| BOOST_TEST( !boost::exception_ptr() ); |
| |
| int count=0; |
| try |
| { |
| throw boost::enable_current_exception(derives_nothing(count)); |
| } |
| catch( |
| ... ) |
| { |
| boost::exception_ptr p = boost::current_exception(); |
| BOOST_TEST(!(p==boost::exception_ptr())); |
| BOOST_TEST(p!=boost::exception_ptr()); |
| BOOST_TEST(p); |
| try |
| { |
| rethrow_exception(p); |
| BOOST_TEST(false); |
| } |
| catch( |
| derives_nothing & ) |
| { |
| } |
| catch( |
| ... ) |
| { |
| BOOST_TEST(false); |
| } |
| } |
| BOOST_TEST(count==0); |
| |
| try |
| { |
| throw boost::enable_current_exception(derives_std_exception()); |
| } |
| catch( |
| ... ) |
| { |
| boost::exception_ptr p = boost::current_exception(); |
| BOOST_TEST(!(p==boost::exception_ptr())); |
| BOOST_TEST(p!=boost::exception_ptr()); |
| BOOST_TEST(p); |
| try |
| { |
| rethrow_exception(p); |
| BOOST_TEST(false); |
| } |
| catch( |
| derives_std_exception & ) |
| { |
| boost::exception_ptr p = boost::current_exception(); |
| BOOST_TEST(!(p==boost::exception_ptr())); |
| BOOST_TEST(p!=boost::exception_ptr()); |
| BOOST_TEST(p); |
| try |
| { |
| rethrow_exception(p); |
| BOOST_TEST(false); |
| } |
| catch( |
| derives_std_exception & ) |
| { |
| } |
| catch( |
| ... ) |
| { |
| BOOST_TEST(false); |
| } |
| } |
| catch( |
| ... ) |
| { |
| BOOST_TEST(false); |
| } |
| } |
| |
| try |
| { |
| throw derives_std_exception(); |
| } |
| catch( |
| ... ) |
| { |
| boost::exception_ptr p = boost::current_exception(); |
| BOOST_TEST(!(p==boost::exception_ptr())); |
| BOOST_TEST(p!=boost::exception_ptr()); |
| BOOST_TEST(p); |
| try |
| { |
| rethrow_exception(p); |
| BOOST_TEST(false); |
| } |
| catch( |
| boost::unknown_exception & e ) |
| { |
| #ifndef BOOST_NO_RTTI |
| std::type_info const * const * t=boost::get_error_info<boost::original_exception_type>(e); |
| BOOST_TEST(t!=0 && *t!=0 && **t==typeid(derives_std_exception)); |
| #endif |
| } |
| catch( |
| ... ) |
| { |
| BOOST_TEST(false); |
| } |
| } |
| |
| test_std_exception_what<std::domain_error>(); |
| test_std_exception_what<std::invalid_argument>(); |
| test_std_exception_what<std::length_error>(); |
| test_std_exception_what<std::out_of_range>(); |
| test_std_exception_what<std::logic_error>(); |
| test_std_exception_what<std::range_error>(); |
| test_std_exception_what<std::overflow_error>(); |
| test_std_exception_what<std::underflow_error>(); |
| test_std_exception_what<std::ios_base::failure>(); |
| test_std_exception_what<std::runtime_error>(); |
| test_std_exception<std::bad_alloc>(); |
| #ifndef BOOST_NO_TYPEID |
| test_std_exception<std::bad_cast>(); |
| test_std_exception<std::bad_typeid>(); |
| #endif |
| test_std_exception<std::bad_exception>(); |
| test_std_exception<std::exception>(); |
| |
| try |
| { |
| throw derives_std_boost_exception() << my_info(42); |
| } |
| catch( |
| ... ) |
| { |
| boost::exception_ptr p = boost::current_exception(); |
| BOOST_TEST(!(p==boost::exception_ptr())); |
| BOOST_TEST(p!=boost::exception_ptr()); |
| BOOST_TEST(p); |
| try |
| { |
| rethrow_exception(p); |
| BOOST_TEST(false); |
| } |
| catch( |
| boost::unknown_exception & x ) |
| { |
| BOOST_TEST(boost::get_error_info<my_info>(x)); |
| if( int const * p=boost::get_error_info<my_info>(x) ) |
| BOOST_TEST(*p==42); |
| #ifndef BOOST_NO_RTTI |
| { |
| std::type_info const * const * t=boost::get_error_info<boost::original_exception_type>(x); |
| BOOST_TEST(t && *t && **t==typeid(derives_std_boost_exception)); |
| } |
| #endif |
| boost::exception_ptr p = boost::current_exception(); |
| BOOST_TEST(!(p==boost::exception_ptr())); |
| BOOST_TEST(p!=boost::exception_ptr()); |
| BOOST_TEST(p); |
| try |
| { |
| rethrow_exception(p); |
| BOOST_TEST(false); |
| } |
| catch( |
| boost::unknown_exception & x ) |
| { |
| BOOST_TEST(boost::get_error_info<my_info>(x)); |
| if( int const * p=boost::get_error_info<my_info>(x) ) |
| BOOST_TEST(*p==42); |
| #ifndef BOOST_NO_RTTI |
| std::type_info const * const * t=boost::get_error_info<boost::original_exception_type>(x); |
| BOOST_TEST(t && *t && **t==typeid(derives_std_boost_exception)); |
| #endif |
| } |
| catch( |
| ... ) |
| { |
| BOOST_TEST(false); |
| } |
| } |
| catch( |
| ... ) |
| { |
| BOOST_TEST(false); |
| } |
| } |
| |
| try |
| { |
| throw derives_boost_exception() << my_info(42); |
| } |
| catch( |
| ... ) |
| { |
| boost::exception_ptr p = boost::current_exception(); |
| BOOST_TEST(!(p==boost::exception_ptr())); |
| BOOST_TEST(p!=boost::exception_ptr()); |
| BOOST_TEST(p); |
| try |
| { |
| rethrow_exception(p); |
| BOOST_TEST(false); |
| } |
| catch( |
| boost::unknown_exception & x ) |
| { |
| BOOST_TEST(boost::get_error_info<my_info>(x)); |
| if( int const * p=boost::get_error_info<my_info>(x) ) |
| BOOST_TEST(*p==42); |
| #ifndef BOOST_NO_RTTI |
| { |
| std::type_info const * const * t=boost::get_error_info<boost::original_exception_type>(x); |
| BOOST_TEST(t && *t && **t==typeid(derives_boost_exception)); |
| } |
| #endif |
| boost::exception_ptr p = boost::current_exception(); |
| BOOST_TEST(!(p==boost::exception_ptr())); |
| BOOST_TEST(p!=boost::exception_ptr()); |
| BOOST_TEST(p); |
| try |
| { |
| rethrow_exception(p); |
| BOOST_TEST(false); |
| } |
| catch( |
| boost::unknown_exception & x ) |
| { |
| BOOST_TEST(boost::get_error_info<my_info>(x)); |
| if( int const * p=boost::get_error_info<my_info>(x) ) |
| BOOST_TEST(*p==42); |
| } |
| catch( |
| ... ) |
| { |
| BOOST_TEST(false); |
| } |
| } |
| catch( |
| ... ) |
| { |
| BOOST_TEST(false); |
| } |
| } |
| |
| test_throw_on_copy<std::bad_alloc,std::bad_alloc>(); |
| test_throw_on_copy<int,std::bad_exception>(); |
| |
| try |
| { |
| throw boost::enable_current_exception(derives_std_boost_exception("what1")); |
| } |
| catch( |
| ... ) |
| { |
| boost::exception_ptr p=boost::current_exception(); |
| { |
| std::string s=diagnostic_information(p); |
| BOOST_TEST(s.find("what1")!=s.npos); |
| } |
| try |
| { |
| throw boost::enable_current_exception(derives_std_boost_exception("what2") << boost::errinfo_nested_exception(p) ); |
| } |
| catch( |
| ... ) |
| { |
| std::string s=boost::current_exception_diagnostic_information(); |
| BOOST_TEST(s.find("what1")!=s.npos); |
| BOOST_TEST(s.find("what2")!=s.npos); |
| } |
| } |
| BOOST_TEST(!diagnostic_information(boost::exception_ptr()).empty()); |
| return boost::report_errors(); |
| } |