]>
Commit | Line | Data |
---|---|---|
11fdf7f2 TL |
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 values without BOOST_CONTRACT_OLD macro. | |
8 | ||
9 | #ifndef BOOST_CONTRACT_TEST_OLD_PTR_TYPE | |
10 | #error "must define BOOST_CONTRACT_TEST_OLD_PTR_TYPE" | |
11 | #endif | |
12 | ||
13 | #include "../detail/oteststream.hpp" | |
14 | #include "../detail/counter.hpp" | |
15 | #include <boost/contract/function.hpp> | |
16 | #include <boost/contract/public_function.hpp> | |
17 | #include <boost/contract/base_types.hpp> | |
18 | #include <boost/contract/override.hpp> | |
19 | #include <boost/contract/assert.hpp> | |
20 | #include <boost/contract/old.hpp> | |
21 | #include <boost/contract/check.hpp> | |
22 | #include <boost/detail/lightweight_test.hpp> | |
23 | #include <cassert> | |
24 | ||
25 | boost::contract::test::detail::oteststream out; | |
26 | ||
27 | struct i_tag; typedef boost::contract::test::detail::counter<i_tag, int> i_type; | |
28 | struct j_tag; typedef boost::contract::test::detail::counter<j_tag, int> j_type; | |
29 | ||
30 | struct b { | |
31 | virtual void swap(i_type& i, j_type& j, boost::contract::virtual_* v = 0); | |
32 | }; | |
33 | ||
34 | void b::swap(i_type& i, j_type& j, boost::contract::virtual_* v) { | |
35 | BOOST_CONTRACT_TEST_OLD_PTR_TYPE<i_type> old_i = boost::contract::make_old( | |
36 | v, boost::contract::copy_old(v) ? | |
37 | i_type::eval(i) | |
38 | : | |
39 | boost::contract::null_old() | |
40 | ); | |
41 | BOOST_CONTRACT_TEST_OLD_PTR_TYPE<j_type> old_j; | |
42 | boost::contract::check c = boost::contract::public_function(v, this) | |
43 | .precondition([&] { | |
44 | out << "b::swap::pre" << std::endl; | |
45 | BOOST_CONTRACT_ASSERT(i.value != j.value); | |
46 | }) | |
47 | .old([&] { | |
48 | out << "b::swap::old" << std::endl; | |
49 | old_j = boost::contract::make_old(v, boost::contract::copy_old(v) ? | |
50 | j_type::eval(j) : boost::contract::null_old()); | |
51 | }) | |
52 | .postcondition([&] { | |
53 | out << "b::swap::post" << std::endl; | |
54 | BOOST_CONTRACT_ASSERT(i.value == old_j->value); | |
55 | BOOST_CONTRACT_ASSERT(j.value == old_i->value); | |
56 | }) | |
57 | ; | |
58 | assert(false); | |
92f5a8d4 | 59 | } |
11fdf7f2 TL |
60 | |
61 | struct a | |
62 | #define BASES public b | |
63 | : BASES | |
64 | { | |
65 | typedef BOOST_CONTRACT_BASE_TYPES(BASES) base_types; | |
66 | #undef BASES | |
67 | ||
68 | void swap(i_type& i, j_type& j, boost::contract::virtual_* v = 0) | |
69 | /* override */ { | |
70 | boost::contract::check c = boost::contract::public_function< | |
71 | override_swap>(v, &a::swap, this, i, j); | |
72 | ||
73 | out << "a::swap::body" << std::endl; | |
74 | int t = i.value; | |
75 | i.value = j.value; | |
76 | j.value = t; | |
77 | } | |
78 | BOOST_CONTRACT_OVERRIDE(swap) | |
79 | }; | |
80 | ||
81 | struct x_tag; | |
82 | typedef boost::contract::test::detail::counter<x_tag, char> x_type; | |
83 | ||
84 | struct y_tag; | |
85 | typedef boost::contract::test::detail::counter<y_tag, char> y_type; | |
86 | ||
87 | void swap(x_type& x, y_type& y) { | |
88 | BOOST_CONTRACT_TEST_OLD_PTR_TYPE<x_type> old_x = boost::contract::make_old( | |
89 | boost::contract::copy_old() ? | |
90 | x_type::eval(x) | |
91 | : | |
92 | boost::contract::null_old() | |
93 | ); | |
94 | BOOST_CONTRACT_TEST_OLD_PTR_TYPE<y_type> old_y; | |
95 | boost::contract::check c = boost::contract::function() | |
96 | .precondition([&] { | |
97 | out << "swap::pre" << std::endl; | |
98 | BOOST_CONTRACT_ASSERT(x.value != y.value); | |
99 | }) | |
100 | .old([&] { | |
101 | out << "swap::old" << std::endl; | |
102 | old_y = boost::contract::make_old(boost::contract::copy_old() ? | |
103 | y_type::eval(y) : boost::contract::null_old()); | |
104 | }) | |
105 | .postcondition([&] { | |
106 | out << "swap::post" << std::endl; | |
107 | BOOST_CONTRACT_ASSERT(x.value == old_y->value); | |
108 | BOOST_CONTRACT_ASSERT(y.value == old_x->value); | |
109 | }) | |
110 | ; | |
111 | ||
112 | out << "swap::body" << std::endl; | |
113 | char t = x.value; | |
114 | x.value = y.value; | |
115 | y.value = t; | |
116 | } | |
117 | ||
118 | int main() { | |
119 | std::ostringstream ok; | |
120 | ||
121 | out.str(""); | |
122 | x_type x; x.value = 'a'; | |
123 | y_type y; y.value = 'b'; | |
124 | swap(x, y); | |
125 | ||
126 | ok.str(""); ok | |
127 | #ifndef BOOST_CONTRACT_NO_PRECONDITIONS | |
128 | << "swap::pre" << std::endl | |
129 | #endif | |
130 | #ifndef BOOST_CONTRACT_NO_OLDS | |
131 | << "swap::old" << std::endl | |
132 | #endif | |
133 | << "swap::body" << std::endl | |
134 | #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS | |
135 | << "swap::post" << std::endl | |
136 | #endif | |
137 | ; | |
138 | BOOST_TEST(out.eq(ok.str())); | |
139 | ||
140 | #ifndef BOOST_CONTRACT_NO_OLDS | |
141 | #define BOOST_CONTRACT_TEST_old 1u | |
142 | #else | |
143 | #define BOOST_CONTRACT_TEST_old 0u | |
144 | #endif | |
145 | ||
146 | BOOST_TEST_EQ(x.value, 'b'); | |
147 | BOOST_TEST_EQ(x.copies(), BOOST_CONTRACT_TEST_old); | |
148 | BOOST_TEST_EQ(x.evals(), BOOST_CONTRACT_TEST_old); | |
149 | BOOST_TEST_EQ(x.ctors(), x.dtors() + 1); // 1 for local var. | |
150 | ||
151 | BOOST_TEST_EQ(y.value, 'a'); | |
152 | BOOST_TEST_EQ(y.copies(), BOOST_CONTRACT_TEST_old); | |
153 | BOOST_TEST_EQ(y.evals(), BOOST_CONTRACT_TEST_old); | |
154 | BOOST_TEST_EQ(y.ctors(), y.dtors() + 1); // 1 for local var. | |
155 | ||
156 | a aa; | |
157 | i_type i; i.value = 1; | |
158 | j_type j; j.value = 2; | |
159 | out.str(""); | |
160 | aa.swap(i, j); | |
161 | ||
162 | ok.str(""); ok | |
163 | #ifndef BOOST_CONTRACT_NO_PRECONDITIONS | |
164 | << "b::swap::pre" << std::endl | |
165 | #endif | |
166 | #ifndef BOOST_CONTRACT_NO_OLDS | |
167 | << "b::swap::old" << std::endl | |
168 | #endif | |
169 | << "a::swap::body" << std::endl | |
170 | #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS | |
171 | << "b::swap::old" << std::endl | |
172 | << "b::swap::post" << std::endl | |
173 | #endif | |
174 | ; | |
175 | BOOST_TEST(out.eq(ok.str())); | |
176 | ||
177 | BOOST_TEST_EQ(i.value, 2); | |
178 | BOOST_TEST_EQ(i.copies(), BOOST_CONTRACT_TEST_old); | |
179 | BOOST_TEST_EQ(i.evals(), BOOST_CONTRACT_TEST_old); | |
180 | BOOST_TEST_EQ(i.ctors(), i.dtors() + 1); // 1 for local var. | |
181 | ||
182 | BOOST_TEST_EQ(j.value, 1); | |
183 | BOOST_TEST_EQ(j.copies(), BOOST_CONTRACT_TEST_old); | |
184 | BOOST_TEST_EQ(j.evals(), BOOST_CONTRACT_TEST_old); | |
185 | BOOST_TEST_EQ(j.ctors(), j.dtors() + 1); // 1 for local var. | |
186 | ||
187 | #undef BOOST_CONTRACT_TEST_old | |
188 | return boost::report_errors(); | |
189 | } | |
190 |