• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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)18 std::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)40 std::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)62 std::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()87 int 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