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