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 .old() (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([] { 49 out << "b::dtor::old" << std::endl; 50 throw b_err(); // Test this throws (from mid branch). 51 }) 52 .postcondition([] { out << "b::dtor::post" << std::endl; }) 53 .except([] { out << "b::dtor::except" << std::endl; }) 54 ; 55 out << "b::dtor::body" << std::endl; 56 } 57 }; 58 59 struct a 60 #define BASES public b 61 : BASES 62 { 63 typedef BOOST_CONTRACT_BASE_TYPES(BASES) base_types; 64 #undef BASES 65 static_invarianta66 static void static_invariant() { out << "a::static_inv" << std::endl; } invarianta67 void invariant() const { out << "a::inv" << std::endl; } 68 BOOST_NOEXCEPT_IFa69 ~a() BOOST_NOEXCEPT_IF(false) { 70 boost::contract::check c = boost::contract::destructor(this) 71 .old([] { out << "a::dtor::old" << std::endl; }) 72 .postcondition([] { out << "a::dtor::post" << std::endl; }) 73 .except([] { out << "a::dtor::except" << std::endl; }) 74 ; 75 out << "a::dtor::body" << std::endl; 76 // Do not throw (from inheritance leaf). 77 } 78 }; 79 main()80int main() { 81 std::ostringstream ok; 82 83 boost::contract::set_old_failure([] (boost::contract::from) { throw; }); 84 85 try { 86 { 87 a aa; 88 out.str(""); 89 } 90 #ifndef BOOST_CONTRACT_NO_OLDS 91 BOOST_TEST(false); 92 } catch(b_err const&) { 93 #endif 94 ok.str(""); ok 95 #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS 96 << "a::static_inv" << std::endl 97 << "a::inv" << std::endl 98 #endif 99 #ifndef BOOST_CONTRACT_NO_OLDS 100 << "a::dtor::old" << std::endl 101 #endif 102 << "a::dtor::body" << std::endl 103 #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS 104 // Test a destructed (so only static_inv and post, but no inv). 105 << "a::static_inv" << std::endl 106 #endif 107 #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS 108 << "a::dtor::post" << std::endl 109 #endif 110 111 #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS 112 << "b::static_inv" << std::endl 113 << "b::inv" << std::endl 114 #endif 115 #ifndef BOOST_CONTRACT_NO_OLDS 116 << "b::dtor::old" << std::endl // Test this threw. 117 #else 118 << "b::dtor::body" << std::endl 119 #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS 120 << "b::static_inv" << std::endl 121 #endif 122 #endif 123 124 #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS 125 << "c::static_inv" << std::endl 126 << "c::inv" << std::endl 127 #endif 128 #ifndef BOOST_CONTRACT_NO_OLDS 129 << "c::dtor::old" << std::endl 130 #endif 131 << "c::dtor::body" << std::endl 132 #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS 133 << "c::static_inv" << std::endl 134 #endif 135 #ifndef BOOST_CONTRACT_NO_OLDS 136 // Test c not destructed (so both inv and except). 137 #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS 138 << "c::inv" << std::endl 139 #endif 140 #ifndef BOOST_CONTRACT_NO_EXCEPTS 141 << "c::dtor::except" << std::endl 142 #endif 143 #endif 144 ; 145 BOOST_TEST(out.eq(ok.str())); 146 } catch(...) { BOOST_TEST(false); } 147 148 return boost::report_errors(); 149 } 150 151