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