Imported Upstream version 1.72.0
[platform/upstream/boost.git] / libs / contract / test / public_function / virtual_access.cpp
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 overrides with mixed access level from (single) base.
8
9 #include "../detail/oteststream.hpp"
10 #include <boost/contract/public_function.hpp>
11 #include <boost/contract/function.hpp>
12 #include <boost/contract/base_types.hpp>
13 #include <boost/contract/override.hpp>
14 #include <boost/contract/check.hpp>
15 #include <boost/detail/lightweight_test.hpp>
16 #include <sstream>
17
18 boost::contract::test::detail::oteststream out;
19
20 struct b { // Test all access levels (public, protected, and private).
21     friend void call(b& me) { // Test polymorphic calls (object by &).
22         me.f();
23         me.g();
24         me.h();
25     }
26
27     static void statci_inv() { out << "b::static_inv" << std::endl; }
28     void invariant() const { out << "b::inv" << std::endl; }
29
30     virtual void f(boost::contract::virtual_* v = 0) {
31         boost::contract::check c = boost::contract::public_function(v, this)
32             .precondition([] { out << "b::f::pre" << std::endl; })
33             .old([] { out << "b::f::old" << std::endl; })
34             .postcondition([] { out << "b::f::post" << std::endl; })
35         ;
36         out << "b::f::body" << std::endl;
37     }
38
39     // NOTE: Both protected and private virtual members must declare
40     // extra `virtual_* = 0` parameter (otherwise they cannot be overridden in
41     // derived classes with contracts because C++ uses also default parameters
42     // to match signature of overriding functions).
43
44 protected:
45     virtual void g(boost::contract::virtual_* /* v */= 0) {
46         boost::contract::check c = boost::contract::function()
47             .precondition([] { out << "b::g::pre" << std::endl; })
48             .old([] { out << "b::g::old" << std::endl; })
49             .postcondition([] { out << "b::g::post" << std::endl; })
50         ;
51         out << "b::g::body" << std::endl;
52     }
53
54 private:
55     virtual void h(boost::contract::virtual_* /* v */ = 0) {
56         boost::contract::check c = boost::contract::function()
57             .precondition([] { out << "b::h::pre" << std::endl; })
58             .old([] { out << "b::h::old" << std::endl; })
59             .postcondition([] { out << "b::h::post" << std::endl; })
60         ;
61         out << "b::h::body" << std::endl;
62     }
63 };
64
65 struct a // Test overrides with mixed access levels from base.
66     #define BASES public b
67     : BASES
68 {
69     typedef BOOST_CONTRACT_BASE_TYPES(BASES) base_types;
70     #undef BASES
71     
72     static void statci_inv() { out << "a::static_inv" << std::endl; }
73     void invariant() const { out << "a::inv" << std::endl; }
74
75     virtual void f(boost::contract::virtual_* v = 0) /* override */ {
76         boost::contract::check c = boost::contract::public_function<override_f>(
77                 v, &a::f, this)
78             .precondition([] { out << "a::f::pre" << std::endl; })
79             .old([] { out << "a::f::old" << std::endl; })
80             .postcondition([] { out << "a::f::post" << std::endl; })
81         ;
82         out << "a::f::body" << std::endl;
83     }
84     BOOST_CONTRACT_OVERRIDES(f)
85
86     // Following do not override public members so no `override_...` param and
87     // they do not actually subcontract.
88
89     virtual void g(boost::contract::virtual_* v = 0) /* override */ {
90         boost::contract::check c = boost::contract::public_function(v, this)
91             .precondition([] { out << "a::g::pre" << std::endl; })
92             .old([] { out << "a::g::old" << std::endl; })
93             .postcondition([] { out << "a::g::post" << std::endl; })
94         ;
95         out << "a::g::body" << std::endl;
96     }
97     
98     virtual void h(boost::contract::virtual_* v = 0) /* override */ {
99         boost::contract::check c = boost::contract::public_function(v, this)
100             .precondition([] { out << "a::h::pre" << std::endl; })
101             .old([] { out << "a::h::old" << std::endl; })
102             .postcondition([] { out << "a::h::post" << std::endl; })
103         ;
104         out << "a::h::body" << std::endl;
105     }
106 };
107
108 int main() {
109     std::ostringstream ok;
110
111     b bb;
112     out.str("");
113     call(bb);
114     ok.str(""); ok
115         #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS
116             << "b::inv" << std::endl
117         #endif
118         #ifndef BOOST_CONTRACT_NO_PRECONDITIONS
119             << "b::f::pre" << std::endl
120         #endif
121         #ifndef BOOST_CONTRACT_NO_OLDS
122             << "b::f::old" << std::endl
123         #endif
124         << "b::f::body" << std::endl
125         #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS
126             << "b::inv" << std::endl
127         #endif
128         #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS
129             << "b::f::post" << std::endl
130         #endif
131
132         #ifndef BOOST_CONTRACT_NO_PRECONDITIONS
133             << "b::g::pre" << std::endl
134         #endif
135         #ifndef BOOST_CONTRACT_NO_OLDS
136             << "b::g::old" << std::endl
137         #endif
138         << "b::g::body" << std::endl
139         #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS
140             << "b::g::post" << std::endl
141         #endif
142
143         #ifndef BOOST_CONTRACT_NO_PRECONDITIONS
144             << "b::h::pre" << std::endl
145         #endif
146         #ifndef BOOST_CONTRACT_NO_OLDS
147             << "b::h::old" << std::endl
148         #endif
149         << "b::h::body" << std::endl
150         #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS
151             << "b::h::post" << std::endl
152         #endif
153     ;
154     BOOST_TEST(out.eq(ok.str()));
155     
156     a aa;
157     out.str("");
158     call(aa);
159     ok.str(""); ok
160         #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS
161             << "b::inv" << std::endl
162             << "a::inv" << std::endl
163         #endif
164         #ifndef BOOST_CONTRACT_NO_PRECONDITIONS
165             << "b::f::pre" << std::endl
166         #endif
167         #ifndef BOOST_CONTRACT_NO_OLDS
168             << "b::f::old" << std::endl
169             << "a::f::old" << std::endl
170         #endif
171         << "a::f::body" << std::endl
172         #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS
173             << "b::inv" << std::endl
174             << "a::inv" << std::endl
175         #endif
176         #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS
177             << "b::f::old" << std::endl
178             << "b::f::post" << std::endl
179             << "a::f::post" << std::endl
180         #endif
181
182         #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS
183             << "a::inv" << std::endl
184         #endif
185         #ifndef BOOST_CONTRACT_NO_PRECONDITIONS
186             << "a::g::pre" << std::endl
187         #endif
188         #ifndef BOOST_CONTRACT_NO_OLDS
189             << "a::g::old" << std::endl
190         #endif
191         << "a::g::body" << std::endl
192         #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS
193             << "a::inv" << std::endl
194         #endif
195         #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS
196             << "a::g::post" << std::endl
197         #endif
198
199         #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS
200             << "a::inv" << std::endl
201         #endif
202         #ifndef BOOST_CONTRACT_NO_PRECONDITIONS
203             << "a::h::pre" << std::endl
204         #endif
205         #ifndef BOOST_CONTRACT_NO_OLDS
206             << "a::h::old" << std::endl
207         #endif
208         << "a::h::body" << std::endl
209         #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS
210             << "a::inv" << std::endl
211         #endif
212         #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS
213             << "a::h::post" << std::endl
214         #endif
215     ;
216     BOOST_TEST(out.eq(ok.str()));
217
218     return boost::report_errors();
219 }
220