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 old inits/ftors and of mixed types up inheritance tree.
8
9 #include "../detail/oteststream.hpp"
10 #include <boost/contract/public_function.hpp>
11 #include <boost/contract/base_types.hpp>
12 #include <boost/contract/assert.hpp>
13 #include <boost/contract/old.hpp>
14 #include <boost/contract/check.hpp>
15 #include <boost/contract/override.hpp>
16 #include <boost/lexical_cast.hpp>
17 #include <boost/detail/lightweight_test.hpp>
18 #include <sstream>
19 #include <string>
20
21 boost::contract::test::detail::oteststream out;
22
23 struct num {
makenum24 static num make(int i) { // Test no ctor (not even explicit) but for copy.
25 num n;
26 n.value(i);
27 return n;
28 }
29
numnum30 num(num const& other) : value_(other.value_) {}
31
valuenum32 void value(int i) { value_ = boost::lexical_cast<std::string>(i); }
valuenum33 int value() const { return boost::lexical_cast<int>(value_); }
34
operator +num35 num operator+(int left) {
36 num n;
37 n.value(value() + left);
38 return n;
39 }
40
41 private:
numnum42 num() {} // Test no visible default ctor (only copy ctor).
43 num& operator=(num const&); // Test no copy operator (only copy ctor).
44
45 std::string value_; // Test this size-of != from other old type `int` below.
46 };
47
48 struct c {
fc49 virtual void f(int& i, num& n, boost::contract::virtual_* v = 0) {
50 boost::contract::old_ptr<int> old_a = BOOST_CONTRACT_OLDOF(v, i + 1);
51 boost::contract::old_ptr<num> old_b = BOOST_CONTRACT_OLDOF(v, n + 2);
52 boost::contract::old_ptr<int> old_x;
53 boost::contract::old_ptr<num> old_y;
54 boost::contract::check c = boost::contract::public_function(v, this)
55 .old([&] {
56 out << "c::f::old" << std::endl;
57 old_x = BOOST_CONTRACT_OLDOF(v, i + 3);
58 old_y = BOOST_CONTRACT_OLDOF(v, n + 4);
59 })
60 .postcondition([&] {
61 out << "c::f::post" << std::endl;
62 BOOST_CONTRACT_ASSERT(*old_a == n.value() + 1);
63 BOOST_CONTRACT_ASSERT(old_b->value() == i + 2);
64 BOOST_CONTRACT_ASSERT(*old_x == n.value() + 3);
65 BOOST_CONTRACT_ASSERT(old_y->value() == i + 4);
66 })
67 ;
68 out << "c::f::body" << std::endl;
69 int tmp = i;
70 i = n.value();
71 n.value(tmp);
72 }
73 };
74
75 struct b
76 #define BASES public c
77 : BASES
78 {
79 typedef BOOST_CONTRACT_BASE_TYPES(BASES) base_types;
80 #undef BASES
81
fb82 virtual void f(int& i, num& n, boost::contract::virtual_* v = 0)
83 /* override */ {
84 boost::contract::old_ptr<int> old_a = BOOST_CONTRACT_OLDOF(v, i + 1);
85 boost::contract::old_ptr<num> old_b = BOOST_CONTRACT_OLDOF(v, n + 2);
86 boost::contract::old_ptr<int> old_x;
87 boost::contract::old_ptr<num> old_y;
88 boost::contract::check c = boost::contract::public_function<
89 override_f>(v, &c::f, this, i, n)
90 .old([&] {
91 out << "b::f::old" << std::endl;
92 old_x = BOOST_CONTRACT_OLDOF(v, i + 3);
93 old_y = BOOST_CONTRACT_OLDOF(v, n + 4);
94 })
95 .postcondition([&] {
96 out << "b::f::post" << std::endl;
97 BOOST_CONTRACT_ASSERT(*old_a == n.value() + 1);
98 BOOST_CONTRACT_ASSERT(old_b->value() == i + 2);
99 BOOST_CONTRACT_ASSERT(*old_x == n.value() + 3);
100 BOOST_CONTRACT_ASSERT(old_y->value() == i + 4);
101 })
102 ;
103 out << "b::f::body" << std::endl;
104 int tmp = i;
105 i = n.value();
106 n.value(tmp);
107 }
108 BOOST_CONTRACT_OVERRIDE(f)
109 };
110
111 struct a
112 #define BASES public b
113 : BASES
114 {
115 typedef BOOST_CONTRACT_BASE_TYPES(BASES) base_types;
116 #undef BASES
117
fa118 virtual void f(int& i, num& n, boost::contract::virtual_* v = 0)
119 /* override */ {
120 boost::contract::old_ptr<int> old_a = BOOST_CONTRACT_OLDOF(v, i + 1);
121 boost::contract::old_ptr<num> old_b = BOOST_CONTRACT_OLDOF(v, n + 2);
122 boost::contract::old_ptr<int> old_x;
123 boost::contract::old_ptr<num> old_y;
124 boost::contract::check c = boost::contract::public_function<
125 override_f>(v, &c::f, this, i, n)
126 .old([&] {
127 out << "a::f::old" << std::endl;
128 old_x = BOOST_CONTRACT_OLDOF(v, i + 3);
129 old_y = BOOST_CONTRACT_OLDOF(v, n + 4);
130 })
131 .postcondition([&] {
132 out << "a::f::post" << std::endl;
133 BOOST_CONTRACT_ASSERT(*old_a == n.value() + 1);
134 BOOST_CONTRACT_ASSERT(old_b->value() == i + 2);
135 BOOST_CONTRACT_ASSERT(*old_x == n.value() + 3);
136 BOOST_CONTRACT_ASSERT(old_y->value() == i + 4);
137 })
138 ;
139 out << "a::f::body" << std::endl;
140 int tmp = i;
141 i = n.value();
142 n.value(tmp);
143 }
144 BOOST_CONTRACT_OVERRIDE(f)
145 };
146
main()147 int main() {
148 std::ostringstream ok;
149 int i = 0;
150 num n = num::make(0);
151
152 i = 123;
153 n.value(-123);
154 a aa; // Test virtual call with 2 bases.
155 out.str("");
156 aa.f(i, n);
157 ok.str(""); ok
158 #ifndef BOOST_CONTRACT_NO_OLDS
159 << "c::f::old" << std::endl
160 << "b::f::old" << std::endl
161 << "a::f::old" << std::endl
162 #endif
163 << "a::f::body" << std::endl
164 #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS
165 << "c::f::old" << std::endl
166 << "c::f::post" << std::endl
167 << "b::f::old" << std::endl
168 << "b::f::post" << std::endl
169 // No old call here because not a base object.
170 << "a::f::post" << std::endl
171 #endif
172 ;
173 BOOST_TEST(out.eq(ok.str()));
174
175 i = 456;
176 n.value(-456);
177 b bb; // Test virtual call with 1 base.
178 out.str("");
179 bb.f(i, n);
180 ok.str(""); ok
181 #ifndef BOOST_CONTRACT_NO_OLDS
182 << "c::f::old" << std::endl
183 << "b::f::old" << std::endl
184 #endif
185 << "b::f::body" << std::endl
186 #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS
187 << "c::f::old" << std::endl
188 << "c::f::post" << std::endl
189 // No old call here because not a base object.
190 << "b::f::post" << std::endl
191 #endif
192 ;
193 BOOST_TEST(out.eq(ok.str()));
194
195 i = 789;
196 n.value(-789);
197 c cc; // Test virtual call with no bases.
198 out.str("");
199 cc.f(i, n);
200 ok.str(""); ok
201 #ifndef BOOST_CONTRACT_NO_OLDS
202 << "c::f::old" << std::endl
203 #endif
204 << "c::f::body" << std::endl
205 #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS
206 // No old call here because not a base object.
207 << "c::f::post" << std::endl
208 #endif
209 ;
210 BOOST_TEST(out.eq(ok.str()));
211
212 return boost::report_errors();
213 }
214
215