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 friend functions (also forcing them to check invariants).
8
9 #include "../detail/oteststream.hpp"
10 #include <boost/contract/public_function.hpp>
11 #include <boost/contract/function.hpp>
12 #include <boost/contract/check.hpp>
13 #include <boost/contract/assert.hpp>
14 #include <boost/detail/lightweight_test.hpp>
15 #include <sstream>
16
17 boost::contract::test::detail::oteststream out;
18
19 class y;
20 class z;
21
22 class x {
23 public:
invariant() const24 void invariant() const {
25 out << "x::inv" << std::endl;
26 BOOST_CONTRACT_ASSERT(get() >= 0);
27 }
28
x()29 x() : value_(0) {}
get() const30 int get() const { return value_; }
31
32 friend void f(x&, y&, int value);
33
34 private:
35 int value_;
36 };
37
38 class y {
39 public:
invariant() const40 void invariant() const {
41 out << "y::inv" << std::endl;
42 BOOST_CONTRACT_ASSERT(get() >= 0);
43 }
44
y()45 y() : value_(0) {}
get() const46 int get() const { return value_; }
47
48 friend void f(x&, y&, int value);
49
50 private:
51 int value_;
52 };
53
f(x & a,y & b,int value)54 void f(x& a, y& b, int value) {
55 boost::contract::check post = boost::contract::function()
56 .postcondition([&] {
57 out << "f::post" << std::endl;
58 BOOST_CONTRACT_ASSERT(a.get() == value);
59 BOOST_CONTRACT_ASSERT(b.get() == value);
60 })
61 ;
62 boost::contract::check inv_b = boost::contract::public_function(&b);
63 boost::contract::check inv_a = boost::contract::public_function(&a);
64 boost::contract::check pre = boost::contract::function()
65 .precondition([&] {
66 out << "f::pre" << std::endl;
67 BOOST_CONTRACT_ASSERT(value > 0);
68 })
69 ;
70
71 out << "f::body" << std::endl;
72 a.value_ = b.value_ = value;
73 }
74
main()75 int main() {
76 std::ostringstream ok;
77
78 x a;
79 y b;
80
81 out.str("");
82 f(a, b, 123);
83 ok.str(""); ok
84 #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS
85 << "y::inv" << std::endl
86 << "x::inv" << std::endl
87 #endif
88 #ifndef BOOST_CONTRACT_NO_PRECONDITIONS
89 << "f::pre" << std::endl
90 #endif
91 << "f::body" << std::endl
92 #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS
93 << "x::inv" << std::endl
94 << "y::inv" << std::endl
95 #endif
96 #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS
97 << "f::post" << std::endl
98 #endif
99 ;
100 BOOST_TEST(out.eq(ok.str()));
101
102 BOOST_TEST_EQ(a.get(), 123);
103 BOOST_TEST_EQ(b.get(), 123);
104
105 return boost::report_errors();
106 }
107
108