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 public function (derived and bases) .old(). 8 9 #include "../detail/oteststream.hpp" 10 #include <boost/contract/public_function.hpp> 11 #include <boost/contract/assert.hpp> 12 #include <boost/contract/base_types.hpp> 13 #include <boost/contract/override.hpp> 14 #include <boost/contract/check.hpp> 15 #include <boost/detail/lightweight_test.hpp> 16 #include <sstream> 17 18 boost::contract::test::detail::oteststream out; 19 20 struct c_err {}; // Global decl so visible in MSVC10 lambdas. 21 22 struct c { static_invariantc23 static void static_invariant() { out << "c::static_inv" << std::endl; } invariantc24 void invariant() const { out << "c::inv" << std::endl; } 25 fc26 virtual void f(boost::contract::virtual_* v = 0) { 27 boost::contract::check c = boost::contract::public_function(v, this) 28 .precondition([] { 29 out << "c::f::pre" << std::endl; 30 BOOST_CONTRACT_ASSERT(false); // To check derived pre. 31 }) 32 .old([] { 33 out << "c::f::old" << std::endl; 34 throw c_err(); // Test this throws. 35 }) 36 .postcondition([] { out << "c::f::post" << std::endl; }) 37 .except([] { out << "c::f::except" << std::endl; }) 38 ; 39 out << "c::f::body" << std::endl; 40 } 41 }; 42 43 struct b_err {}; // Global decl so visible in MSVC10 lambdas. 44 45 struct b 46 #define BASES public c 47 : BASES 48 { 49 typedef BOOST_CONTRACT_BASE_TYPES(BASES) base_types; 50 #undef BASES 51 static_invariantb52 static void static_invariant() { out << "b::static_inv" << std::endl; } invariantb53 void invariant() const { out << "b::inv" << std::endl; } 54 fb55 virtual void f(boost::contract::virtual_* v = 0) /* override */ { 56 boost::contract::check c = boost::contract::public_function<override_f>( 57 v, &b::f, this) 58 .precondition([] { 59 out << "b::f::pre" << std::endl; 60 BOOST_CONTRACT_ASSERT(false); // To check derived pre. 61 }) 62 .old([] { 63 out << "b::f::old" << std::endl; 64 throw b_err(); // Test this throws. 65 }) 66 .postcondition([] { out << "b::f::post" << std::endl; }) 67 .except([] { out << "b::f::except" << std::endl; }) 68 ; 69 out << "b::f::body" << std::endl; 70 } 71 BOOST_CONTRACT_OVERRIDE(f) 72 }; 73 74 struct a_err {}; // Global decl so visible in MSVC10 lambdas. 75 76 struct a 77 #define BASES public b 78 : BASES 79 { 80 typedef BOOST_CONTRACT_BASE_TYPES(BASES) base_types; 81 #undef BASES 82 static_invarianta83 static void static_invariant() { out << "a::static_inv" << std::endl; } invarianta84 void invariant() const { out << "a::inv" << std::endl; } 85 fa86 void f(boost::contract::virtual_* v = 0) /* override */ { 87 boost::contract::check c = boost::contract::public_function<override_f>( 88 v, &a::f, this) 89 .precondition([] { out << "a::f::pre" << std::endl; }) 90 .old([] { 91 out << "a::f::old" << std::endl; 92 throw a_err(); // Test this throws. 93 }) 94 .postcondition([] { out << "a::f::post" << std::endl; }) 95 .except([] { out << "a::f::except" << std::endl; }) 96 ; 97 out << "a::f::body" << std::endl; 98 } 99 BOOST_CONTRACT_OVERRIDE(f) 100 }; 101 main()102int main() { 103 std::ostringstream ok; 104 105 boost::contract::set_old_failure([] (boost::contract::from) { throw; }); 106 107 a aa; 108 b& ba = aa; // Test as virtual call via polymorphism. 109 try { 110 out.str(""); 111 ba.f(); 112 #ifndef BOOST_CONTRACT_NO_OLDS 113 BOOST_TEST(false); 114 } catch(c_err const&) { 115 #endif 116 ok.str(""); ok 117 #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS 118 << "c::static_inv" << std::endl 119 << "c::inv" << std::endl 120 << "b::static_inv" << std::endl 121 << "b::inv" << std::endl 122 << "a::static_inv" << std::endl 123 << "a::inv" << std::endl 124 #endif 125 #ifndef BOOST_CONTRACT_NO_PRECONDITIONS 126 << "c::f::pre" << std::endl 127 << "b::f::pre" << std::endl 128 << "a::f::pre" << std::endl 129 #endif 130 #ifndef BOOST_CONTRACT_NO_OLDS 131 << "c::f::old" << std::endl // Test this threw. 132 #else 133 << "a::f::body" << std::endl 134 #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS 135 << "c::static_inv" << std::endl 136 << "c::inv" << std::endl 137 << "b::static_inv" << std::endl 138 << "b::inv" << std::endl 139 << "a::static_inv" << std::endl 140 << "a::inv" << std::endl 141 #endif 142 #endif 143 ; 144 BOOST_TEST(out.eq(ok.str())); 145 } catch(...) { BOOST_TEST(false); } 146 147 return boost::report_errors(); 148 } 149 150