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) .pre(). 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([] { out << "c::f::post" << std::endl; }) 34 .except([] { out << "c::f::except" << std::endl; }) 35 ; 36 out << "c::f::body" << std::endl; 37 } 38 }; 39 40 struct b_err {}; // Global decl so visible in MSVC10 lambdas. 41 42 struct b 43 #define BASES public c 44 : BASES 45 { 46 typedef BOOST_CONTRACT_BASE_TYPES(BASES) base_types; 47 #undef BASES 48 static_invariantb49 static void static_invariant() { out << "b::static_inv" << std::endl; } invariantb50 void invariant() const { out << "b::inv" << std::endl; } 51 fb52 virtual void f(boost::contract::virtual_* v = 0) /* override */ { 53 boost::contract::check c = boost::contract::public_function<override_f>( 54 v, &b::f, this) 55 .precondition([] { 56 out << "b::f::pre" << std::endl; 57 BOOST_CONTRACT_ASSERT(false); // To check derived pre. 58 }) 59 .old([] { out << "b::f::old" << std::endl; }) 60 .postcondition([] { out << "b::f::post" << std::endl; }) 61 .except([] { out << "b::f::except" << std::endl; }) 62 ; 63 out << "b::f::body" << std::endl; 64 } 65 BOOST_CONTRACT_OVERRIDE(f) 66 }; 67 68 struct a_err {}; // Global decl so visible in MSVC10 lambdas. 69 70 struct a 71 #define BASES public b 72 : BASES 73 { 74 typedef BOOST_CONTRACT_BASE_TYPES(BASES) base_types; 75 #undef BASES 76 static_invarianta77 static void static_invariant() { out << "a::static_inv" << std::endl; } invarianta78 void invariant() const { out << "a::inv" << std::endl; } 79 fa80 void f(boost::contract::virtual_* v = 0) /* override */ { 81 boost::contract::check c = boost::contract::public_function<override_f>( 82 v, &a::f, this) 83 .precondition([] { 84 out << "a::f::pre" << std::endl; 85 throw a_err(); // Test this throws. 86 }) 87 .old([] { out << "a::f::old" << std::endl; }) 88 .postcondition([] { out << "a::f::post" << std::endl; }) 89 .except([] { out << "a::f::except" << std::endl; }) 90 ; 91 out << "a::f::body" << std::endl; 92 } 93 BOOST_CONTRACT_OVERRIDE(f) 94 }; 95 main()96int main() { 97 std::ostringstream ok; 98 99 boost::contract::set_precondition_failure( 100 [] (boost::contract::from) { throw; }); 101 102 a aa; 103 b& ba = aa; // Test as virtual call via polymorphism. 104 try { 105 out.str(""); 106 ba.f(); 107 #ifndef BOOST_CONTRACT_NO_PRECONDITIONS 108 BOOST_TEST(false); 109 } catch(a_err const&) { 110 #endif 111 ok.str(""); ok 112 #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS 113 << "c::static_inv" << std::endl 114 << "c::inv" << std::endl 115 << "b::static_inv" << std::endl 116 << "b::inv" << std::endl 117 << "a::static_inv" << std::endl 118 << "a::inv" << std::endl 119 #endif 120 #ifndef BOOST_CONTRACT_NO_PRECONDITIONS 121 << "c::f::pre" << std::endl 122 << "b::f::pre" << std::endl 123 << "a::f::pre" << std::endl // Test this threw. 124 #else 125 #ifndef BOOST_CONTRACT_NO_OLDS 126 << "c::f::old" << std::endl 127 << "b::f::old" << std::endl 128 << "a::f::old" << std::endl 129 #endif 130 << "a::f::body" << std::endl 131 #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS 132 << "c::static_inv" << std::endl 133 << "c::inv" << std::endl 134 << "b::static_inv" << std::endl 135 << "b::inv" << std::endl 136 << "a::static_inv" << std::endl 137 << "a::inv" << std::endl 138 #endif 139 #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS 140 << "c::f::old" << std::endl 141 << "c::f::post" << std::endl 142 << "b::f::old" << std::endl 143 << "b::f::post" << std::endl 144 // No old call here because not a base object. 145 << "a::f::post" << std::endl 146 #endif 147 #endif 148 ; 149 BOOST_TEST(out.eq(ok.str())); 150 } catch(...) { BOOST_TEST(false); } 151 152 return boost::report_errors(); 153 } 154 155