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 only middle base class with entry invariants. 8 9 #define BOOST_CONTRACT_TEST_NO_A_INV 10 #undef BOOST_CONTRACT_TEST_NO_B_INV 11 #define BOOST_CONTRACT_TEST_NO_C_INV 12 #include "decl.hpp" 13 14 #include <boost/detail/lightweight_test.hpp> 15 #include <sstream> 16 #include <string> 17 ok_a()18std::string ok_a() { 19 std::ostringstream ok; ok 20 #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS 21 << "a::static_inv" << std::endl 22 #endif 23 #ifndef BOOST_CONTRACT_NO_OLDS 24 << "a::dtor::old" << std::endl 25 #endif 26 << "a::dtor::body" << std::endl 27 #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS 28 << "a::static_inv" << std::endl 29 #endif 30 #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS 31 << "a::dtor::post" << std::endl 32 #endif 33 ; 34 return ok.str(); 35 } 36 ok_b(bool failed=false)37std::string ok_b(bool failed = false) { 38 std::ostringstream ok; ok << "" // Suppress a warning. 39 #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS 40 << "b::static_inv" << std::endl 41 << "b::inv" << std::endl // This can fail. 42 #endif 43 ; 44 if(!failed) ok 45 #ifndef BOOST_CONTRACT_NO_OLDS 46 << "b::dtor::old" << std::endl 47 #endif 48 << "b::dtor::body" << std::endl 49 #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS 50 << "b::static_inv" << std::endl 51 #endif 52 #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS 53 << "b::dtor::post" << std::endl 54 #endif 55 ; 56 return ok.str(); 57 } 58 ok_c(bool threw=false)59std::string ok_c(bool threw = false) { 60 std::ostringstream ok; ok 61 #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS 62 << "c::static_inv" << std::endl 63 #endif 64 #ifndef BOOST_CONTRACT_NO_OLDS 65 << "c::dtor::old" << std::endl 66 #endif 67 << "c::dtor::body" << std::endl 68 #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS 69 << "c::static_inv" << std::endl 70 // No b::inv here (not even when threw). 71 #endif 72 #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS 73 << (!threw ? "c::dtor::post\n" : "") 74 #endif 75 ; 76 return ok.str(); 77 } 78 79 struct err {}; // Global decl so visible in MSVC10 lambdas. 80 main()81int main() { 82 std::ostringstream ok; 83 84 a_entry_inv = true; 85 b_entry_inv = true; 86 c_entry_inv = true; 87 { 88 a aa; 89 out.str(""); 90 } 91 ok.str(""); ok // Test nothing failed. 92 << ok_a() 93 << ok_b() 94 << ok_c() 95 ; 96 BOOST_TEST(out.eq(ok.str())); 97 98 boost::contract::set_entry_invariant_failure([&ok] (boost::contract::from) { 99 BOOST_TEST(out.eq(ok.str())); // Must check before dtor throws... 100 throw err(); // for testing (as dtors should never throw anyways). 101 }); 102 103 a_entry_inv = false; 104 b_entry_inv = true; 105 c_entry_inv = true; 106 try { 107 { 108 a aa; 109 ok.str(""); 110 out.str(""); 111 } 112 ok.str(""); ok 113 << ok_a() // Test no entry a::inv so no failure here. 114 << ok_b() 115 << ok_c() 116 ; 117 BOOST_TEST(out.eq(ok.str())); 118 } catch(...) { BOOST_TEST(false); } 119 120 #ifdef BOOST_CONTRACT_NO_ENTRY_INVARIANTS 121 #define BOOST_CONTRACT_TEST_entry_inv 0 122 #else 123 #define BOOST_CONTRACT_TEST_entry_inv 2 124 #endif 125 126 a_entry_inv = true; 127 b_entry_inv = false; 128 c_entry_inv = true; 129 try { 130 { 131 a aa; 132 ok.str(""); ok 133 << ok_a() 134 // Test entry b::inv failed... 135 << ok_b(bool(BOOST_CONTRACT_TEST_entry_inv)) 136 ; 137 out.str(""); 138 } 139 #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS 140 BOOST_TEST(false); 141 } catch(err const&) { 142 #endif 143 ok // ...then exec other dtors and check inv on throw (as dtor threw). 144 << ok_c(bool(BOOST_CONTRACT_TEST_entry_inv)) 145 ; 146 BOOST_TEST(out.eq(ok.str())); 147 } catch(...) { BOOST_TEST(false); } 148 149 a_entry_inv = true; 150 b_entry_inv = true; 151 c_entry_inv = false; 152 try { 153 { 154 a aa; 155 ok.str(""); 156 out.str(""); 157 } 158 ok.str(""); ok 159 << ok_a() 160 << ok_b() 161 << ok_c() // Test no entry c::inv so no failure here. 162 ; 163 BOOST_TEST(out.eq(ok.str())); 164 } catch(...) { BOOST_TEST(false); } 165 166 boost::contract::set_entry_invariant_failure([] (boost::contract::from) { 167 // Testing multiple failures so dtors must not throw multiple 168 // exceptions, just ignore failure and continue test program... 169 }); 170 171 a_entry_inv = false; 172 b_entry_inv = false; 173 c_entry_inv = false; 174 { 175 a aa; 176 out.str(""); 177 } 178 ok.str(""); ok 179 << ok_a() // Test no entry a::inv so no failure here. 180 181 // Test entry b::inv failed (as all did). 182 << ok_b(bool(BOOST_CONTRACT_TEST_entry_inv)) 183 #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS 184 << "b::dtor::body" << std::endl 185 #endif 186 187 << ok_c() // Test no entry c::inv so no failure here. 188 ; 189 BOOST_TEST(out.eq(ok.str())); 190 191 #undef BOOST_CONTRACT_TEST_entry_inv 192 return boost::report_errors(); 193 } 194 195