1 2 // Copyright (C) 2008-2018 Lorenzo Caminiti 3 // Distributed under the Boost Software License, Version 1.0 (see accompanying 4 // file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt). 5 // See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html 6 7 // Test throw from destructor body (in middle branch of inheritance tree). 8 9 #include "../detail/oteststream.hpp" 10 #include <boost/contract/destructor.hpp> 11 #include <boost/contract/base_types.hpp> 12 #include <boost/contract/check.hpp> 13 #include <boost/config.hpp> 14 #include <boost/detail/lightweight_test.hpp> 15 #include <sstream> 16 17 boost::contract::test::detail::oteststream out; 18 19 struct c { static_invariantc20 static void static_invariant() { out << "c::static_inv" << std::endl; } invariantc21 void invariant() const { out << "c::inv" << std::endl; } 22 BOOST_NOEXCEPT_IFc23 ~c() BOOST_NOEXCEPT_IF(false) { 24 boost::contract::check c = boost::contract::destructor(this) 25 .old([] { out << "c::dtor::old" << std::endl; }) 26 .postcondition([] { out << "c::dtor::post" << std::endl; }) 27 .except([] { out << "c::dtor::except" << std::endl; }) 28 ; 29 out << "c::dtor::body" << std::endl; 30 // Do not throw (from inheritance root). 31 } 32 }; 33 34 struct b_err {}; // Global decl so visible in MSVC10 lambdas. 35 36 struct b 37 #define BASES public c 38 : BASES 39 { 40 typedef BOOST_CONTRACT_BASE_TYPES(BASES) base_types; 41 #undef BASES 42 static_invariantb43 static void static_invariant() { out << "b::static_inv" << std::endl; } invariantb44 void invariant() const { out << "b::inv" << std::endl; } 45 BOOST_NOEXCEPT_IFb46 ~b() BOOST_NOEXCEPT_IF(false) { 47 boost::contract::check c = boost::contract::destructor(this) 48 .old([] { out << "b::dtor::old" << std::endl; }) 49 .postcondition([] { out << "b::dtor::post" << std::endl; }) 50 .except([] { out << "b::dtor::except" << std::endl; }) 51 ; 52 out << "b::dtor::body" << std::endl; 53 throw b_err(); // Test body throw (from inheritance mid branch). 54 } 55 }; 56 57 struct a 58 #define BASES public b 59 : BASES 60 { 61 typedef BOOST_CONTRACT_BASE_TYPES(BASES) base_types; 62 #undef BASES 63 static_invarianta64 static void static_invariant() { out << "a::static_inv" << std::endl; } invarianta65 void invariant() const { out << "a::inv" << std::endl; } 66 BOOST_NOEXCEPT_IFa67 ~a() BOOST_NOEXCEPT_IF(false) { 68 boost::contract::check c = boost::contract::destructor(this) 69 .old([] { out << "a::dtor::old" << std::endl; }) 70 .postcondition([] { out << "a::dtor::post" << std::endl; }) 71 .except([] { out << "a::dtor::except" << std::endl; }) 72 ; 73 out << "a::dtor::body" << std::endl; 74 // Do not throw (from inheritance leaf). 75 } 76 }; 77 main()78int main() { 79 std::ostringstream ok; 80 81 try { 82 { 83 a aa; 84 out.str(""); 85 } 86 BOOST_TEST(false); 87 } catch(b_err const&) { 88 ok.str(""); ok 89 #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS 90 << "a::static_inv" << std::endl 91 << "a::inv" << std::endl 92 #endif 93 #ifndef BOOST_CONTRACT_NO_OLDS 94 << "a::dtor::old" << std::endl 95 #endif 96 << "a::dtor::body" << std::endl 97 // Test a destructed (so only static_inv and post, but no inv). 98 #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS 99 << "a::static_inv" << std::endl 100 #endif 101 #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS 102 << "a::dtor::post" << std::endl 103 #endif 104 105 #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS 106 << "b::static_inv" << std::endl 107 << "b::inv" << std::endl 108 #endif 109 #ifndef BOOST_CONTRACT_NO_OLDS 110 << "b::dtor::old" << std::endl 111 #endif 112 << "b::dtor::body" << std::endl // Test this threw. 113 // Test b not destructed (so static_inv, inv, and except, no post). 114 #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS 115 << "b::static_inv" << std::endl 116 << "b::inv" << std::endl 117 #endif 118 #ifndef BOOST_CONTRACT_NO_EXCEPTS 119 << "b::dtor::except" << std::endl 120 #endif 121 122 #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS 123 << "c::static_inv" << std::endl 124 << "c::inv" << std::endl 125 #endif 126 #ifndef BOOST_CONTRACT_NO_OLDS 127 << "c::dtor::old" << std::endl 128 #endif 129 << "c::dtor::body" << std::endl 130 // Test c not destructed (so static_inv, inv, and except, no post). 131 #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS 132 << "c::static_inv" << std::endl 133 << "c::inv" << std::endl 134 #endif 135 #ifndef BOOST_CONTRACT_NO_EXCEPTS 136 << "c::dtor::except" << std::endl 137 #endif 138 ; 139 BOOST_TEST(out.eq(ok.str())); 140 } catch(...) { BOOST_TEST(false); } 141 142 return boost::report_errors(); 143 } 144 145