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 .post() (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([] { 50 out << "b::dtor::post" << std::endl; 51 throw b_err(); // Test this throws (from mid branch). 52 }) 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_postcondition_failure( 84 [] (boost::contract::from) { throw; }); 85 86 try { 87 { 88 a aa; 89 out.str(""); 90 } 91 #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS 92 BOOST_TEST(false); 93 } catch(b_err const&) { 94 #endif 95 ok.str(""); ok 96 #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS 97 << "a::static_inv" << std::endl 98 << "a::inv" << std::endl 99 #endif 100 #ifndef BOOST_CONTRACT_NO_OLDS 101 << "a::dtor::old" << std::endl 102 #endif 103 << "a::dtor::body" << std::endl 104 #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS 105 // Test a destructed (so only static_inv and post, but no inv). 106 << "a::static_inv" << std::endl 107 #endif 108 #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS 109 << "a::dtor::post" << std::endl 110 #endif 111 112 #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS 113 << "b::static_inv" << std::endl 114 << "b::inv" << std::endl 115 #endif 116 #ifndef BOOST_CONTRACT_NO_OLDS 117 << "b::dtor::old" << std::endl 118 #endif 119 << "b::dtor::body" << std::endl 120 #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS 121 << "b::static_inv" << std::endl 122 #endif 123 #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS 124 << "b::dtor::post" << std::endl // Test this threw. 125 #endif 126 127 #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS 128 << "c::static_inv" << std::endl 129 << "c::inv" << std::endl 130 #endif 131 #ifndef BOOST_CONTRACT_NO_OLDS 132 << "c::dtor::old" << std::endl 133 #endif 134 << "c::dtor::body" << std::endl 135 #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS 136 << "c::static_inv" << std::endl 137 #endif 138 #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS 139 // Test c not destructed (so both inv and except). 140 #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS 141 << "c::inv" << std::endl 142 #endif 143 #ifndef BOOST_CONTRACT_NO_EXCEPTS 144 << "c::dtor::except" << std::endl 145 #endif 146 #endif 147 ; 148 BOOST_TEST(out.eq(ok.str())); 149 } catch(...) { BOOST_TEST(false); } 150 151 return boost::report_errors(); 152 } 153 154