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 free function contracts.
8
9 #include "../detail/oteststream.hpp"
10 #include "../detail/counter.hpp"
11 #include <boost/contract/function.hpp>
12 #include <boost/contract/old.hpp>
13 #include <boost/contract/assert.hpp>
14 #include <boost/contract/check.hpp>
15 #include <boost/preprocessor/control/iif.hpp>
16 #include <boost/detail/lightweight_test.hpp>
17 #include <sstream>
18
19 boost::contract::test::detail::oteststream out;
20
21 struct x_tag; typedef boost::contract::test::detail::counter<x_tag, int> x_type;
22 struct y_tag; typedef boost::contract::test::detail::counter<y_tag, int> y_type;
23
swap(x_type & x,y_type & y)24 bool swap(x_type& x, y_type& y) {
25 bool result;
26 boost::contract::old_ptr<x_type> old_x =
27 BOOST_CONTRACT_OLDOF(x_type::eval(x));
28 boost::contract::old_ptr<y_type> old_y;
29 boost::contract::check c = boost::contract::function()
30 .precondition([&] {
31 out << "swap::pre" << std::endl;
32 BOOST_CONTRACT_ASSERT(x.value != y.value);
33 })
34 .old([&] {
35 out << "swap::old" << std::endl;
36 old_y = BOOST_CONTRACT_OLDOF(y_type::eval(y));
37 })
38 .postcondition([&] {
39 out << "swap::post" << std::endl;
40 BOOST_CONTRACT_ASSERT(x.value == old_y->value);
41 BOOST_CONTRACT_ASSERT(y.value == old_x->value);
42 BOOST_CONTRACT_ASSERT(result == (old_x->value != old_y->value));
43 })
44 ;
45
46 out << "swap::body" << std::endl;
47 if(x.value == y.value) return result = false;
48 int save_x = x.value;
49 x.value = y.value;
50 y.value = save_x;
51 return result = true;
52 }
53
main()54 int main() {
55 std::ostringstream ok;
56
57 {
58 x_type x; x.value = 123;
59 y_type y; y.value = 456;
60
61 out.str("");
62 bool r = swap(x, y);
63 ok.str(""); ok
64 #ifndef BOOST_CONTRACT_NO_PRECONDITIONS
65 << "swap::pre" << std::endl
66 #endif
67 #ifndef BOOST_CONTRACT_NO_OLDS
68 << "swap::old" << std::endl
69 #endif
70 << "swap::body" << std::endl
71 #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS
72 << "swap::post" << std::endl
73 #endif
74 ;
75 BOOST_TEST(out.eq(ok.str()));
76
77 BOOST_TEST(r);
78 BOOST_TEST_EQ(x.value, 456);
79 BOOST_TEST_EQ(y.value, 123);
80 }
81
82 #ifndef BOOST_CONTRACT_NO_OLDS
83 #define BOOST_CONTRACT_TEST_old 1u
84 #else
85 #define BOOST_CONTRACT_TEST_old 0u
86 #endif
87
88 BOOST_TEST_EQ(x_type::copies(), BOOST_CONTRACT_TEST_old);
89 BOOST_TEST_EQ(x_type::evals(), BOOST_CONTRACT_TEST_old);
90 BOOST_TEST_EQ(x_type::ctors(), x_type::dtors()); // No leak.
91
92 BOOST_TEST_EQ(y_type::copies(), BOOST_CONTRACT_TEST_old);
93 BOOST_TEST_EQ(y_type::evals(), BOOST_CONTRACT_TEST_old);
94 BOOST_TEST_EQ(y_type::ctors(), y_type::dtors()); // No leak.
95
96 #undef BOOST_CONTRACT_TEST_old
97 return boost::report_errors();
98 }
99
100