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) .post(). 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([] { out << "c::f::old" << std::endl; }) 33 .postcondition([] { 34 out << "c::f::post" << std::endl; 35 // Test derived will throw. 36 }) 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([] { out << "b::f::old" << std::endl; }) 63 .postcondition([] { 64 out << "b::f::post" << std::endl; 65 throw b_err(); // Test this (both derived and base) throws. 66 }) 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([] { out << "a::f::old" << std::endl; }) 91 .postcondition([] { 92 out << "a::f::post" << std::endl; 93 throw a_err(); // Test base already threw. 94 }) 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_postcondition_failure( 106 [] (boost::contract::from) { throw; }); 107 108 a aa; 109 b& ba = aa; // Test as virtual call via polymorphism. 110 try { 111 out.str(""); 112 ba.f(); 113 #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS 114 BOOST_TEST(false); 115 } catch(b_err const&) { 116 #endif 117 ok.str(""); ok 118 #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS 119 << "c::static_inv" << std::endl 120 << "c::inv" << std::endl 121 << "b::static_inv" << std::endl 122 << "b::inv" << std::endl 123 << "a::static_inv" << std::endl 124 << "a::inv" << std::endl 125 #endif 126 #ifndef BOOST_CONTRACT_NO_PRECONDITIONS 127 << "c::f::pre" << std::endl 128 << "b::f::pre" << std::endl 129 << "a::f::pre" << std::endl 130 #endif 131 #ifndef BOOST_CONTRACT_NO_OLDS 132 << "c::f::old" << std::endl 133 << "b::f::old" << std::endl 134 << "a::f::old" << std::endl 135 #endif 136 << "a::f::body" << std::endl 137 #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS 138 << "c::static_inv" << std::endl 139 << "c::inv" << std::endl 140 << "b::static_inv" << std::endl 141 << "b::inv" << std::endl 142 << "a::static_inv" << std::endl 143 << "a::inv" << std::endl 144 #endif 145 #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS 146 << "c::f::old" << std::endl 147 << "c::f::post" << std::endl 148 << "b::f::old" << std::endl 149 << "b::f::post" << std::endl // Test this threw. 150 #endif 151 ; 152 BOOST_TEST(out.eq(ok.str())); 153 } catch(...) { BOOST_TEST(false); } 154 155 return boost::report_errors(); 156 } 157 158