/* * Copyright Andrey Semashev 2007 - 2015. * 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) */ /*! * \file util_exception_handler.cpp * \author Andrey Semashev * \date 13.07.2009 * * \brief This header contains tests for the exception handler functional objects. */ #define BOOST_TEST_MODULE util_exception_handler #include #include #include #include #include #include #include namespace logging = boost::log; namespace { struct my_handler1 { typedef void result_type; std::type_info const*& m_pExceptionType; my_handler1(std::type_info const*& p) : m_pExceptionType(p) {} void operator() (std::exception&) const { m_pExceptionType = &typeid(std::exception); } void operator() (std::runtime_error&) const { m_pExceptionType = &typeid(std::runtime_error); } }; struct my_handler2 { typedef void result_type; typedef boost::mpl::vector< std::runtime_error, std::exception >::type exception_types; std::type_info const*& m_pExceptionType; explicit my_handler2(std::type_info const*& p) : m_pExceptionType(p) {} void operator() (std::exception&) const { m_pExceptionType = &typeid(std::exception); } void operator() (std::runtime_error&) const { m_pExceptionType = &typeid(std::runtime_error); } }; struct my_handler1_nothrow { typedef void result_type; std::type_info const*& m_pExceptionType; my_handler1_nothrow(std::type_info const*& p) : m_pExceptionType(p) {} void operator() (std::exception&) const { m_pExceptionType = &typeid(std::exception); } void operator() (std::runtime_error&) const { m_pExceptionType = &typeid(std::runtime_error); } void operator() () const { m_pExceptionType = &typeid(void); } }; struct my_handler2_nothrow { typedef void result_type; typedef boost::mpl::vector< std::runtime_error, std::exception >::type exception_types; std::type_info const*& m_pExceptionType; explicit my_handler2_nothrow(std::type_info const*& p) : m_pExceptionType(p) {} void operator() (std::exception&) const { m_pExceptionType = &typeid(std::exception); } void operator() (std::runtime_error&) const { m_pExceptionType = &typeid(std::runtime_error); } void operator() () const { m_pExceptionType = &typeid(void); } }; struct my_exception {}; struct my_function0 { struct impl_base { virtual ~impl_base() {} virtual void invoke() = 0; }; template< typename T > struct impl : public impl_base { T m_Fun; explicit impl(T const& fun) : m_Fun(fun) {} void invoke() { m_Fun(); } }; private: boost::scoped_ptr< impl_base > m_pImpl; public: template< typename T > my_function0& operator= (T const& fun) { m_pImpl.reset(new impl< T >(fun)); return *this; } void operator() () const { m_pImpl->invoke(); } }; } // namespace // Tests for handler with explicit exception types specification BOOST_AUTO_TEST_CASE(explicit_exception_types) { std::type_info const* pExceptionType = 0; my_function0 handler; handler = logging::make_exception_handler< std::runtime_error, std::exception >(my_handler1(pExceptionType)); try { throw std::runtime_error("error"); } catch (...) { handler(); } BOOST_REQUIRE(pExceptionType != 0); BOOST_CHECK(*pExceptionType == typeid(std::runtime_error)); pExceptionType = 0; try { throw std::logic_error("error"); } catch (...) { handler(); } BOOST_REQUIRE(pExceptionType != 0); BOOST_CHECK(*pExceptionType == typeid(std::exception)); pExceptionType = 0; try { throw my_exception(); } catch (...) { BOOST_CHECK_THROW(handler(), my_exception); } BOOST_REQUIRE(pExceptionType == 0); // Verify that exception types are checked in the specified order handler = logging::make_exception_handler< std::exception, std::runtime_error >(my_handler1(pExceptionType)); try { throw std::runtime_error("error"); } catch (...) { handler(); } BOOST_REQUIRE(pExceptionType != 0); BOOST_CHECK(*pExceptionType == typeid(std::exception)); pExceptionType = 0; } // Tests for handler with explicit exception types specification (no-throw version) BOOST_AUTO_TEST_CASE(explicit_exception_types_nothrow) { std::type_info const* pExceptionType = 0; my_function0 handler; handler = logging::make_exception_handler< std::runtime_error, std::exception >(my_handler1_nothrow(pExceptionType), std::nothrow); try { throw std::runtime_error("error"); } catch (...) { handler(); } BOOST_REQUIRE(pExceptionType != 0); BOOST_CHECK(*pExceptionType == typeid(std::runtime_error)); pExceptionType = 0; try { throw std::logic_error("error"); } catch (...) { handler(); } BOOST_REQUIRE(pExceptionType != 0); BOOST_CHECK(*pExceptionType == typeid(std::exception)); pExceptionType = 0; try { throw my_exception(); } catch (...) { BOOST_CHECK_NO_THROW(handler()); } BOOST_REQUIRE(pExceptionType != 0); BOOST_CHECK(*pExceptionType == typeid(void)); pExceptionType = 0; // Verify that exception types are checked in the specified order handler = logging::make_exception_handler< std::exception, std::runtime_error >(my_handler1_nothrow(pExceptionType), std::nothrow); try { throw std::runtime_error("error"); } catch (...) { handler(); } BOOST_REQUIRE(pExceptionType != 0); BOOST_CHECK(*pExceptionType == typeid(std::exception)); pExceptionType = 0; } // Tests for handler with self-contained exception types BOOST_AUTO_TEST_CASE(self_contained_exception_types) { std::type_info const* pExceptionType = 0; my_function0 handler; handler = logging::make_exception_handler(my_handler2(pExceptionType)); try { throw std::runtime_error("error"); } catch (...) { handler(); } BOOST_REQUIRE(pExceptionType != 0); BOOST_CHECK(*pExceptionType == typeid(std::runtime_error)); pExceptionType = 0; try { throw std::logic_error("error"); } catch (...) { handler(); } BOOST_REQUIRE(pExceptionType != 0); BOOST_CHECK(*pExceptionType == typeid(std::exception)); pExceptionType = 0; try { throw my_exception(); } catch (...) { BOOST_CHECK_THROW(handler(), my_exception); } BOOST_REQUIRE(pExceptionType == 0); } // Tests for handler with self-contained exception types (no-throw version) BOOST_AUTO_TEST_CASE(self_contained_exception_types_nothrow) { std::type_info const* pExceptionType = 0; my_function0 handler; handler = logging::make_exception_handler(my_handler2_nothrow(pExceptionType), std::nothrow); try { throw std::runtime_error("error"); } catch (...) { handler(); } BOOST_REQUIRE(pExceptionType != 0); BOOST_CHECK(*pExceptionType == typeid(std::runtime_error)); pExceptionType = 0; try { throw std::logic_error("error"); } catch (...) { handler(); } BOOST_REQUIRE(pExceptionType != 0); BOOST_CHECK(*pExceptionType == typeid(std::exception)); pExceptionType = 0; try { throw my_exception(); } catch (...) { BOOST_CHECK_NO_THROW(handler()); } BOOST_REQUIRE(pExceptionType != 0); BOOST_CHECK(*pExceptionType == typeid(void)); pExceptionType = 0; }