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