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
swap(i_type & i,j_type & j,boost::contract::virtual_ * v)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);
59 }
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
swapa68 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
swap(x_type & x,y_type & y)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
main()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
191