• 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 subcontracting with sparse and complex inheritance graph.
8 
9 #include "../detail/oteststream.hpp"
10 #include <boost/contract/public_function.hpp>
11 #include <boost/contract/assert.hpp>
12 #include <boost/contract/check.hpp>
13 #include <boost/contract/override.hpp>
14 #include <boost/contract/base_types.hpp>
15 #include <boost/detail/lightweight_test.hpp>
16 #include <sstream>
17 
18 boost::contract::test::detail::oteststream out;
19 
20 struct j {
static_invariantj21     static void static_invariant() { out << "j::static_inv" << std::endl; }
invariantj22     void invariant() const { out << "j::inv" << std::endl; }
23 
fj24     virtual void f(char ch, boost::contract::virtual_* v = 0) {
25         boost::contract::check c = boost::contract::public_function(v, this)
26             .precondition([&] {
27                 out << "j::f::pre" << std::endl;
28                 BOOST_CONTRACT_ASSERT(ch == 'j');
29             })
30             .old([] { out << "j::f::old" << std::endl; })
31             .postcondition([] { out << "j::f::post" << std::endl; })
32         ;
33         out << "j::f::body" << std::endl;
34     }
35 };
36 
37 struct i {
static_invarianti38     static void static_invariant() { out << "i::static_inv" << std::endl; }
invarianti39     void invariant() const { out << "i::inv" << std::endl; }
40 
fi41     virtual void f(char ch, boost::contract::virtual_* v = 0) {
42         boost::contract::check c = boost::contract::public_function(v, this)
43             .precondition([&] {
44                 out << "i::f::pre" << std::endl;
45                 BOOST_CONTRACT_ASSERT(ch == 'i');
46             })
47             .old([] { out << "i::f::old" << std::endl; })
48             .postcondition([] { out << "i::f::post" << std::endl; })
49         ;
50         out << "i::f::body" << std::endl;
51     }
52 };
53 
54 struct k {};
55 
56 struct h
57     #define BASES public j
58     : BASES
59 {
60     typedef BOOST_CONTRACT_BASE_TYPES(BASES) base_types;
61     #undef BASES
62 
static_invarianth63     static void static_invariant() { out << "h::static_inv" << std::endl; }
invarianth64     void invariant() const { out << "h::inv" << std::endl; }
65 
fh66     virtual void f(char ch, boost::contract::virtual_* v = 0) /* override */ {
67         boost::contract::check c = boost::contract::public_function<
68                 override_f>(v, &h::f, this, ch)
69             .precondition([&] {
70                 out << "h::f::pre" << std::endl;
71                 BOOST_CONTRACT_ASSERT(ch == 'h');
72             })
73             .old([] { out << "h::f::old" << std::endl; })
74             .postcondition([] { out << "h::f::post" << std::endl; })
75         ;
76         out << "h::f::body" << std::endl;
77     }
78     BOOST_CONTRACT_OVERRIDE(f)
79 };
80 
81 struct e
82     #define BASES public virtual i
83     : BASES
84 {
85     typedef BOOST_CONTRACT_BASE_TYPES(BASES) base_types;
86     #undef BASES
87 
static_invariante88     static void static_invariant() { out << "e::static_inv" << std::endl; }
invariante89     void invariant() const { out << "e::inv" << std::endl; }
90 
fe91     virtual void f(char ch, boost::contract::virtual_* v = 0) /* override */ {
92         boost::contract::check c = boost::contract::public_function<
93                 override_f>(v, &e::f, this, ch)
94             .precondition([&] {
95                 out << "e::f::pre" << std::endl;
96                 BOOST_CONTRACT_ASSERT(ch == 'e');
97             })
98             .old([] { out << "e::f::old" << std::endl; })
99             .postcondition([] { out << "e::f::post" << std::endl; })
100         ;
101         out << "e::f::body" << std::endl;
102     }
103     BOOST_CONTRACT_OVERRIDE(f)
104 };
105 
106 struct d
107     #define BASES public k, virtual public i
108     : BASES
109 {
110     typedef BOOST_CONTRACT_BASE_TYPES(BASES) base_types;
111     #undef BASES
112 
static_invariantd113     static void static_invariant() { out << "d::static_inv" << std::endl; }
invariantd114     void invariant() const { out << "d::inv" << std::endl; }
115 };
116 
117 struct c {
static_invariantc118     static void static_invariant() { out << "c::static_inv" << std::endl; }
invariantc119     void invariant() const { out << "c::inv" << std::endl; }
120 
fc121     virtual void f(char ch, boost::contract::virtual_* v = 0) {
122         boost::contract::check c = boost::contract::public_function(v, this)
123             .precondition([&] {
124                 out << "c::f::pre" << std::endl;
125                 BOOST_CONTRACT_ASSERT(ch == 'c');
126             })
127             .old([] { out << "c::f::old" << std::endl; })
128             .postcondition([] { out << "c::f::post" << std::endl; })
129         ;
130         out << "c::f::body" << std::endl;
131     }
132 };
133 
134 struct b
135     #define BASES public c, public d
136     : BASES
137 {
138     typedef BOOST_CONTRACT_BASE_TYPES(BASES) base_types;
139     #undef BASES
140 
static_invariantb141     static void static_invariant() { out << "b::static_inv" << std::endl; }
invariantb142     void invariant() const { out << "b::inv" << std::endl; }
143 };
144 
145 struct x {};
146 struct y {};
147 struct z {};
148 
149 struct a
150     #define BASES public b, public x, public e, protected y, public h, \
151             private z
152     : BASES
153 {
154     typedef BOOST_CONTRACT_BASE_TYPES(BASES) base_types;
155     #undef BASES
156 
static_invarianta157     static void static_invariant() { out << "a::static_inv" << std::endl; }
invarianta158     void invariant() const { out << "a::inv" << std::endl; }
159 
fa160     virtual void f(char ch, boost::contract::virtual_* v = 0) /* override */ {
161         boost::contract::check c = boost::contract::public_function<
162                 override_f>(v, &a::f, this, ch)
163             .precondition([&] {
164                 out << "a::f::pre" << std::endl;
165                 BOOST_CONTRACT_ASSERT(ch == 'a');
166             })
167             .old([] { out << "a::f::old" << std::endl; })
168             .postcondition([] { out << "a::f::post" << std::endl; })
169         ;
170         out << "a::f::body" << std::endl;
171     }
172     BOOST_CONTRACT_OVERRIDE(f)
173 };
174 
main()175 int main() {
176     std::ostringstream ok;
177 
178     a aa;
179     out.str("");
180     aa.f('a');
181     ok.str(""); ok
182         #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS
183             << "c::static_inv" << std::endl
184             << "c::inv" << std::endl
185             << "i::static_inv" << std::endl
186             << "i::inv" << std::endl
187             << "e::static_inv" << std::endl
188             << "e::inv" << std::endl
189             << "j::static_inv" << std::endl
190             << "j::inv" << std::endl
191             << "h::static_inv" << std::endl
192             << "h::inv" << std::endl
193             << "a::static_inv" << std::endl
194             << "a::inv" << std::endl
195         #endif
196         #ifndef BOOST_CONTRACT_NO_PRECONDITIONS
197             << "c::f::pre" << std::endl
198             << "i::f::pre" << std::endl
199             << "e::f::pre" << std::endl
200             << "j::f::pre" << std::endl
201             << "h::f::pre" << std::endl
202             << "a::f::pre" << std::endl
203         #endif
204         #ifndef BOOST_CONTRACT_NO_OLDS
205             << "c::f::old" << std::endl
206             << "i::f::old" << std::endl
207             << "e::f::old" << std::endl
208             << "j::f::old" << std::endl
209             << "h::f::old" << std::endl
210             << "a::f::old" << std::endl
211         #endif
212         << "a::f::body" << std::endl
213         #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS
214             << "c::static_inv" << std::endl
215             << "c::inv" << std::endl
216             << "i::static_inv" << std::endl
217             << "i::inv" << std::endl
218             << "e::static_inv" << std::endl
219             << "e::inv" << std::endl
220             << "j::static_inv" << std::endl
221             << "j::inv" << std::endl
222             << "h::static_inv" << std::endl
223             << "h::inv" << std::endl
224             << "a::static_inv" << std::endl
225             << "a::inv" << std::endl
226         #endif
227         #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS
228             << "c::f::old" << std::endl
229             << "c::f::post" << std::endl
230             << "i::f::old" << std::endl
231             << "i::f::post" << std::endl
232             << "e::f::old" << std::endl
233             << "e::f::post" << std::endl
234             << "j::f::old" << std::endl
235             << "j::f::post" << std::endl
236             << "h::f::old" << std::endl
237             << "h::f::post" << std::endl
238             // No old call here because not a base object.
239             << "a::f::post" << std::endl
240         #endif
241     ;
242     BOOST_TEST(out.eq(ok.str()));
243 
244     c cc;
245     out.str("");
246     cc.f('c');
247     ok.str(""); ok
248         #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS
249             << "c::static_inv" << std::endl
250             << "c::inv" << std::endl
251         #endif
252         #ifndef BOOST_CONTRACT_NO_PRECONDITIONS
253             << "c::f::pre" << std::endl
254         #endif
255         #ifndef BOOST_CONTRACT_NO_OLDS
256             << "c::f::old" << std::endl
257         #endif
258         << "c::f::body" << std::endl
259         #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS
260             << "c::static_inv" << std::endl
261             << "c::inv" << std::endl
262         #endif
263         #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS
264             // No old call here because not a base object.
265             << "c::f::post" << std::endl
266         #endif
267     ;
268     BOOST_TEST(out.eq(ok.str()));
269 
270     d dd;
271     out.str("");
272     dd.f('i'); // d's f inherited from i.
273     ok.str(""); ok
274         #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS
275             << "i::static_inv" << std::endl
276             << "i::inv" << std::endl
277         #endif
278         #ifndef BOOST_CONTRACT_NO_PRECONDITIONS
279             << "i::f::pre" << std::endl
280         #endif
281         #ifndef BOOST_CONTRACT_NO_OLDS
282             << "i::f::old" << std::endl
283         #endif
284         << "i::f::body" << std::endl
285         #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS
286             << "i::static_inv" << std::endl
287             << "i::inv" << std::endl
288         #endif
289         #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS
290             // No old call here because not a base object.
291             << "i::f::post" << std::endl
292         #endif
293     ;
294     BOOST_TEST(out.eq(ok.str()));
295 
296     e ee;
297     out.str("");
298     ee.f('e');
299     ok.str(""); ok
300         #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS
301             << "i::static_inv" << std::endl
302             << "i::inv" << std::endl
303             << "e::static_inv" << std::endl
304             << "e::inv" << std::endl
305         #endif
306         #ifndef BOOST_CONTRACT_NO_PRECONDITIONS
307             << "i::f::pre" << std::endl
308             << "e::f::pre" << std::endl
309         #endif
310         #ifndef BOOST_CONTRACT_NO_OLDS
311             << "i::f::old" << std::endl
312             << "e::f::old" << std::endl
313         #endif
314         << "e::f::body" << std::endl
315         #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS
316             << "i::static_inv" << std::endl
317             << "i::inv" << std::endl
318             << "e::static_inv" << std::endl
319             << "e::inv" << std::endl
320         #endif
321         #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS
322             << "i::f::old" << std::endl
323             << "i::f::post" << std::endl
324             // No old call here because not a base object.
325             << "e::f::post" << std::endl
326         #endif
327     ;
328     BOOST_TEST(out.eq(ok.str()));
329 
330     i ii;
331     out.str("");
332     ii.f('i');
333     ok.str(""); ok
334         #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS
335             << "i::static_inv" << std::endl
336             << "i::inv" << std::endl
337         #endif
338         #ifndef BOOST_CONTRACT_NO_PRECONDITIONS
339             << "i::f::pre" << std::endl
340         #endif
341         #ifndef BOOST_CONTRACT_NO_OLDS
342             << "i::f::old" << std::endl
343         #endif
344         << "i::f::body" << std::endl
345         #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS
346             << "i::static_inv" << std::endl
347             << "i::inv" << std::endl
348         #endif
349         #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS
350             // No old call here because not a base object.
351             << "i::f::post" << std::endl
352         #endif
353     ;
354     BOOST_TEST(out.eq(ok.str()));
355 
356     h hh;
357     out.str("");
358     hh.f('h');
359     ok.str(""); ok
360         #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS
361             << "j::static_inv" << std::endl
362             << "j::inv" << std::endl
363             << "h::static_inv" << std::endl
364             << "h::inv" << std::endl
365         #endif
366         #ifndef BOOST_CONTRACT_NO_PRECONDITIONS
367             << "j::f::pre" << std::endl
368             << "h::f::pre" << std::endl
369         #endif
370         #ifndef BOOST_CONTRACT_NO_OLDS
371             << "j::f::old" << std::endl
372             << "h::f::old" << std::endl
373         #endif
374         << "h::f::body" << std::endl
375         #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS
376             << "j::static_inv" << std::endl
377             << "j::inv" << std::endl
378             << "h::static_inv" << std::endl
379             << "h::inv" << std::endl
380         #endif
381         #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS
382             << "j::f::old" << std::endl
383             << "j::f::post" << std::endl
384             // No old call here because not a base object.
385             << "h::f::post" << std::endl
386         #endif
387     ;
388     BOOST_TEST(out.eq(ok.str()));
389 
390     j jj;
391     out.str("");
392     jj.f('j');
393     ok.str(""); ok
394         #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS
395             << "j::static_inv" << std::endl
396             << "j::inv" << std::endl
397         #endif
398         #ifndef BOOST_CONTRACT_NO_PRECONDITIONS
399             << "j::f::pre" << std::endl
400         #endif
401         #ifndef BOOST_CONTRACT_NO_OLDS
402             << "j::f::old" << std::endl
403         #endif
404         << "j::f::body" << std::endl
405         #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS
406             << "j::static_inv" << std::endl
407             << "j::inv" << std::endl
408         #endif
409         #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS
410             // No old call here because not a base object.
411             << "j::f::post" << std::endl
412         #endif
413     ;
414     BOOST_TEST(out.eq(ok.str()));
415 
416     return boost::report_errors();
417 }
418 
419