• 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 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)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 
40 enum checked { passed, failed, threw };
41 
ok_b(checked check=passed)42 std::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)65 std::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()90 int 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