• 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 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