123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410 |
- // no #include guard
- // Copyright (C) 2008-2018 Lorenzo Caminiti
- // Distributed under the Boost Software License, Version 1.0 (see accompanying
- // file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt).
- // See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html
- // Test base and derived classes mixing boost::optional and non- result types.
- #include "../detail/oteststream.hpp"
- #include "../detail/counter.hpp"
- #include <boost/contract/base_types.hpp>
- #include <boost/contract/public_function.hpp>
- #include <boost/contract/override.hpp>
- #include <boost/contract/check.hpp>
- #include <boost/contract/assert.hpp>
- #include <boost/optional.hpp>
- #include <boost/detail/lightweight_test.hpp>
- #include <boost/config.hpp>
- #include <sstream>
- #include <cassert>
- boost::contract::test::detail::oteststream out;
- struct ch_tag;
- typedef boost::contract::test::detail::counter<ch_tag, char> ch_type;
- #ifdef BOOST_CONTRACT_TEST_REF // Test with result types by reference.
- #define BOOST_CONTRACT_TEST_CH_TYPE ch_type&
- #define BOOST_CONTRACT_TEST_CH_INIT = ch_init
- ch_type ch_init;
- unsigned const ch_extras = 2; // 1 local and 1 global var.
- #else // Test with result types by value.
- #define BOOST_CONTRACT_TEST_CH_TYPE ch_type
- #define BOOST_CONTRACT_TEST_CH_INIT /* nothing */
- unsigned const ch_extras = 1; // 1 for local var (no global var).
- #endif
- bool tested_d_copies = false;
- struct d {
- static void static_invariant() { out << "d::static_inv" << std::endl; }
- void invariant() const { out << "d::inv" << std::endl; }
-
- virtual BOOST_CONTRACT_TEST_CH_TYPE f(
- ch_type& ch, boost::contract::virtual_* v = 0) {
- unsigned const old_ch_copies = ch_type::copies();
- boost::optional<BOOST_CONTRACT_TEST_CH_TYPE> result;
- boost::contract::check c = boost::contract::public_function(
- v, result, this)
- .precondition([&] {
- out << "d::f::pre" << std::endl;
- BOOST_CONTRACT_ASSERT(ch.value == 'd');
- })
- .old([] { out << "d::f::old" << std::endl; })
- .postcondition([&] (boost::optional<ch_type const&> const& result) {
- out << "d::f::post" << std::endl;
- BOOST_CONTRACT_ASSERT(result->value == ch.value);
- })
- ;
- BOOST_TEST_EQ(ch_type::copies(), old_ch_copies);
- tested_d_copies = true;
- out << "d::f::body" << std::endl;
- return *(result = ch);
- }
- };
- bool tested_c_copies = false;
- struct c
- #define BASES public d
- : BASES
- {
- typedef BOOST_CONTRACT_BASE_TYPES(BASES) base_types;
- #undef BASES
- static void static_invariant() { out << "c::static_inv" << std::endl; }
- void invariant() const { out << "c::inv" << std::endl; }
-
- virtual BOOST_CONTRACT_TEST_CH_TYPE f(
- ch_type& ch, boost::contract::virtual_* v = 0) /* override */ {
- unsigned const old_ch_copies = ch_type::copies();
- boost::optional<BOOST_CONTRACT_TEST_CH_TYPE> result;
- boost::contract::check c = boost::contract::public_function<override_f>(
- v, result, &c::f, this, ch)
- .precondition([&] {
- out << "c::f::pre" << std::endl;
- BOOST_CONTRACT_ASSERT(ch.value == 'c');
- })
- .old([] { out << "c::f::old" << std::endl; })
- .postcondition([&] (boost::optional<ch_type const&> const& result) {
- out << "c::f::post" << std::endl;
- BOOST_CONTRACT_ASSERT(result->value == ch.value);
- })
- ;
- BOOST_TEST_EQ(ch_type::copies(), old_ch_copies);
- tested_c_copies = true;
- out << "c::f::body" << std::endl;
- return *(result = ch);
- }
- BOOST_CONTRACT_OVERRIDE(f)
- };
- bool tested_b_copies = false;
- struct b
- #define BASES public c
- : BASES
- {
- typedef BOOST_CONTRACT_BASE_TYPES(BASES) base_types;
- #undef BASES
-
- static void static_invariant() { out << "b::static_inv" << std::endl; }
- void invariant() const { out << "b::inv" << std::endl; }
- virtual BOOST_CONTRACT_TEST_CH_TYPE f(
- ch_type& ch, boost::contract::virtual_* v = 0) /* override */ {
- unsigned const old_ch_copies = ch_type::copies();
- BOOST_CONTRACT_TEST_CH_TYPE result BOOST_CONTRACT_TEST_CH_INIT;
- boost::contract::check c = boost::contract::public_function<override_f>(
- v, result, &b::f, this, ch)
- .precondition([&] {
- out << "b::f::pre" << std::endl;
- BOOST_CONTRACT_ASSERT(ch.value == 'b');
- })
- .old([] { out << "b::f::old" << std::endl; })
- .postcondition([&] (ch_type const& result) {
- out << "b::f::post" << std::endl;
- BOOST_CONTRACT_ASSERT(result.value == ch.value);
- })
- ;
- BOOST_TEST_EQ(ch_type::copies(), old_ch_copies);
- tested_b_copies = true;
- out << "b::f::body" << std::endl;
- return result = ch;
- }
- BOOST_CONTRACT_OVERRIDE(f)
- };
- bool tested_a_copies = false;
- struct a
- #define BASES public b
- : BASES
- {
- typedef BOOST_CONTRACT_BASE_TYPES(BASES) base_types;
- #undef BASES
- static void static_invariant() { out << "a::static_inv" << std::endl; }
- void invariant() const { out << "a::inv" << std::endl; }
- virtual BOOST_CONTRACT_TEST_CH_TYPE f(
- ch_type& ch, boost::contract::virtual_* v = 0) /* override */ {
- unsigned const old_ch_copies = ch_type::copies();
- boost::optional<BOOST_CONTRACT_TEST_CH_TYPE> result;
- boost::contract::check c = boost::contract::public_function<override_f>(
- v, result, &a::f, this, ch)
- .precondition([&] {
- out << "a::f::pre" << std::endl;
- BOOST_CONTRACT_ASSERT(ch.value == 'a');
- })
- .old([] { out << "a::f::old" << std::endl; })
- .postcondition([&] (boost::optional<ch_type const&> const& result) {
- out << "a::f::post" << std::endl;
- BOOST_CONTRACT_ASSERT(result->value == ch.value);
- })
- ;
- BOOST_TEST_EQ(ch_type::copies(), old_ch_copies);
- tested_a_copies = true;
- out << "a::f::body" << std::endl;
- return *(result = ch);
- }
- BOOST_CONTRACT_OVERRIDE(f)
- };
- bool tested_e_copies = false;
- struct e
- #define BASES public b
- : BASES
- {
- typedef BOOST_CONTRACT_BASE_TYPES(BASES) base_types;
- #undef BASES
-
- static void static_invariant() { out << "e::static_inv" << std::endl; }
- void invariant() const { out << "e::inv" << std::endl; }
- virtual BOOST_CONTRACT_TEST_CH_TYPE f(
- ch_type& ch, boost::contract::virtual_* v = 0) /* override */ {
- unsigned const old_ch_copies = ch_type::copies();
- BOOST_CONTRACT_TEST_CH_TYPE result BOOST_CONTRACT_TEST_CH_INIT;
- boost::contract::check c = boost::contract::public_function<override_f>(
- v, result, &e::f, this, ch)
- .precondition([&] {
- out << "e::f::pre" << std::endl;
- BOOST_CONTRACT_ASSERT(ch.value == 'e');
- })
- .old([] { out << "e::f::old" << std::endl; })
- .postcondition([&] (ch_type const& result) {
- out << "e::f::post" << std::endl;
- BOOST_CONTRACT_ASSERT(result.value == ch.value);
- })
- ;
- BOOST_TEST_EQ(ch_type::copies(), old_ch_copies);
- tested_e_copies = true;
- out << "e::f::body" << std::endl;
- return result = ch;
- }
- BOOST_CONTRACT_OVERRIDE(f)
- };
- int main() {
- std::ostringstream ok;
- ch_type ch;
- #ifdef BOOST_CONTRACT_TEST_REF
- ch_init.value = '\0';
- #endif
- // Test optional in overriding a::f and non-optional in overridden b::f.
- a aa;
- ch.value = 'a';
- out.str("");
- aa.f(ch);
- ok.str(""); ok
- #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS
- << "d::static_inv" << std::endl
- << "d::inv" << std::endl
- << "c::static_inv" << std::endl
- << "c::inv" << std::endl
- << "b::static_inv" << std::endl
- << "b::inv" << std::endl
- << "a::static_inv" << std::endl
- << "a::inv" << std::endl
- #endif
- #ifndef BOOST_CONTRACT_NO_PRECONDITIONS
- << "d::f::pre" << std::endl
- << "c::f::pre" << std::endl
- << "b::f::pre" << std::endl
- << "a::f::pre" << std::endl
- #endif
- #ifndef BOOST_CONTRACT_NO_OLDS
- << "d::f::old" << std::endl
- << "c::f::old" << std::endl
- << "b::f::old" << std::endl
- << "a::f::old" << std::endl
- #endif
- << "a::f::body" << std::endl
- #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS
- << "d::static_inv" << std::endl
- << "d::inv" << std::endl
- << "c::static_inv" << std::endl
- << "c::inv" << std::endl
- << "b::static_inv" << std::endl
- << "b::inv" << std::endl
- << "a::static_inv" << std::endl
- << "a::inv" << std::endl
- #endif
- #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS
- << "d::f::old" << std::endl
- << "d::f::post" << std::endl
- << "c::f::old" << std::endl
- << "c::f::post" << std::endl
- << "b::f::old" << std::endl
- << "b::f::post" << std::endl
- << "a::f::post" << std::endl
- #endif
- ;
- BOOST_TEST(out.eq(ok.str()));
- BOOST_TEST(tested_a_copies);
- BOOST_TEST_EQ(ch_type::ctors(), ch_type::dtors() + ch_extras);
- // Test non-optional in overriding b::f and optional in overridden c::f.
- b bb;
- ch.value = 'b';
- out.str("");
- bb.f(ch);
- ok.str(""); ok
- #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS
- << "d::static_inv" << std::endl
- << "d::inv" << std::endl
- << "c::static_inv" << std::endl
- << "c::inv" << std::endl
- << "b::static_inv" << std::endl
- << "b::inv" << std::endl
- #endif
- #ifndef BOOST_CONTRACT_NO_PRECONDITIONS
- << "d::f::pre" << std::endl
- << "c::f::pre" << std::endl
- << "b::f::pre" << std::endl
- #endif
- #ifndef BOOST_CONTRACT_NO_OLDS
- << "d::f::old" << std::endl
- << "c::f::old" << std::endl
- << "b::f::old" << std::endl
- #endif
- << "b::f::body" << std::endl
- #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS
- << "d::static_inv" << std::endl
- << "d::inv" << std::endl
- << "c::static_inv" << std::endl
- << "c::inv" << std::endl
- << "b::static_inv" << std::endl
- << "b::inv" << std::endl
- #endif
- #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS
- << "d::f::old" << std::endl
- << "d::f::post" << std::endl
- << "c::f::old" << std::endl
- << "c::f::post" << std::endl
- << "b::f::post" << std::endl
- #endif
- ;
- BOOST_TEST(out.eq(ok.str()));
- BOOST_TEST(tested_b_copies);
- BOOST_TEST_EQ(ch_type::ctors(), ch_type::dtors() + ch_extras);
-
- // Test optional in both overriding c::f and overridden d::f.
- c cc;
- ch.value = 'c';
- out.str("");
- cc.f(ch);
- ok.str(""); ok
- #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS
- << "d::static_inv" << std::endl
- << "d::inv" << std::endl
- << "c::static_inv" << std::endl
- << "c::inv" << std::endl
- #endif
- #ifndef BOOST_CONTRACT_NO_PRECONDITIONS
- << "d::f::pre" << std::endl
- << "c::f::pre" << std::endl
- #endif
- #ifndef BOOST_CONTRACT_NO_OLDS
- << "d::f::old" << std::endl
- << "c::f::old" << std::endl
- #endif
- << "c::f::body" << std::endl
- #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS
- << "d::static_inv" << std::endl
- << "d::inv" << std::endl
- << "c::static_inv" << std::endl
- << "c::inv" << std::endl
- #endif
- #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS
- << "d::f::old" << std::endl
- << "d::f::post" << std::endl
- << "c::f::post" << std::endl
- #endif
- ;
- BOOST_TEST(out.eq(ok.str()));
- BOOST_TEST(tested_c_copies);
- BOOST_TEST_EQ(ch_type::ctors(), ch_type::dtors() + ch_extras);
-
- // Test non-optional in both overriding c::f and overridden d::f.
- e ee;
- ch.value = 'e';
- out.str("");
- ee.f(ch);
- ok.str(""); ok
- #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS
- << "d::static_inv" << std::endl
- << "d::inv" << std::endl
- << "c::static_inv" << std::endl
- << "c::inv" << std::endl
- << "b::static_inv" << std::endl
- << "b::inv" << std::endl
- << "e::static_inv" << std::endl
- << "e::inv" << std::endl
- #endif
- #ifndef BOOST_CONTRACT_NO_PRECONDITIONS
- << "d::f::pre" << std::endl
- << "c::f::pre" << std::endl
- << "b::f::pre" << std::endl
- << "e::f::pre" << std::endl
- #endif
- #ifndef BOOST_CONTRACT_NO_OLDS
- << "d::f::old" << std::endl
- << "c::f::old" << std::endl
- << "b::f::old" << std::endl
- << "e::f::old" << std::endl
- #endif
- << "e::f::body" << std::endl
- #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS
- << "d::static_inv" << std::endl
- << "d::inv" << std::endl
- << "c::static_inv" << std::endl
- << "c::inv" << std::endl
- << "b::static_inv" << std::endl
- << "b::inv" << std::endl
- << "e::static_inv" << std::endl
- << "e::inv" << std::endl
- #endif
- #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS
- << "d::f::old" << std::endl
- << "d::f::post" << std::endl
- << "c::f::old" << std::endl
- << "c::f::post" << std::endl
- << "b::f::old" << std::endl
- << "b::f::post" << std::endl
- << "e::f::post" << std::endl
- #endif
- ;
- BOOST_TEST(out.eq(ok.str()));
- BOOST_TEST(tested_e_copies);
- BOOST_TEST_EQ(ch_type::ctors(), ch_type::dtors() + ch_extras);
- return boost::report_errors();
- }
|