diff --git a/include/boost/contract.hpp b/include/boost/contract.hpp index 2106fc4..a060168 100644 --- a/include/boost/contract.hpp +++ b/include/boost/contract.hpp @@ -16,6 +16,8 @@ #include #include +// TODO: Consider renaming all/most *.i to *.hpp. + // TODO: Should C++11 move preserve class invariants at exit and/or on throw? Maybe not because after move no other public member can be called (but dtor can... so dtor should not check inv at that time...). If so, users could use an internal moved_ data member to guard class invariant checking and set that after the move operation... How can I program C++11 move operations with this lib? Should I used boost::contract::function instead of public_function? (But probably not because that does not subcontract and does not check inv at entry...) // TODO: What shall I do with unions? Can/shall I contract them? Double check which members C++11 unions can have (ctor, dtor, etc?). diff --git a/include/boost/contract/assert.hpp b/include/boost/contract/assert.hpp index eb5378e..a9ddc02 100644 --- a/include/boost/contract/assert.hpp +++ b/include/boost/contract/assert.hpp @@ -11,11 +11,11 @@ /* PUBLIC */ +// Must use ternary operator expr here (instead of if-statement) so this macro +// can always be used with if-statements and all other C++ constructs. #define BOOST_CONTRACT_ASSERT(condition) \ - if(!(condition)) { \ - throw boost::contract::assertion_failure(__FILE__, __LINE__, \ - BOOST_PP_STRINGIZE(condition)); \ - } + ((condition) ? (void*)0 : throw boost::contract::assertion_failure( \ + __FILE__, __LINE__, BOOST_PP_STRINGIZE(condition))) #endif // #include guard diff --git a/include/boost/contract/aux_/condition/check_base.hpp b/include/boost/contract/aux_/condition/check_base.hpp index 2b64167..6978a0f 100644 --- a/include/boost/contract/aux_/condition/check_base.hpp +++ b/include/boost/contract/aux_/condition/check_base.hpp @@ -6,6 +6,7 @@ /** @cond */ // TODO: Can I reduce boost.function overhead? Check also everywhere else boost.function is used. #include +#include #include /** @endcond */ @@ -15,15 +16,17 @@ class check_base { // Base to hold all contract objects for RAII. public: explicit check_base(boost::contract::from from) : BOOST_CONTRACT_ERROR_missing_guard_declaration(false), - from_(from) + from_(from), + failed_(false) {} - virtual ~check_base() { assert_guarded(); } // Assert in case derived don't. - void guard() { // Must be called by contract guard ctor. BOOST_CONTRACT_ERROR_missing_guard_declaration = true; this->init(); // All inits (pre, old, post) done after guard decl. } + + // Assert in case derived don't. + virtual ~check_base() BOOST_NOEXCEPT_IF(false) { assert_guarded(); } void assert_guarded() { // Derived dtors should call this (earlier errors). assert(BOOST_CONTRACT_ERROR_missing_guard_declaration); @@ -38,29 +41,41 @@ public: protected: virtual void init() {} - void check_pre(bool throw_on_failure = false) { - try { if(pre_) pre_(); } + bool check_pre(bool throw_on_failure = false) { + if(!pre_) return false; + if(failed()) return true; + try { pre_(); } catch(...) { // Subcontracted pre must throw on failure (instead of // calling failure handler) so to be checked in logic-or. if(throw_on_failure) throw; - boost::contract::precondition_failed(from()); + fail(&boost::contract::precondition_failed); } + return true; } void copy_old() { + if(failed()) return; // TODO: Document that when old copies throw, using .old() calls post failure handler (more correct), while using = OLDOF makes enclosing user function throw (less correct). Plus of course using .old() makes old copies after inv and pre are checked, while using = OLDOF makes old copies before inv and pre checking (this is less correct in theory, but it should not really matter in most practical cases unless the old copy are programmed assuming inv and pre are satisfied). try { if(old_) old_(); } - catch(...) { boost::contract::postcondition_failed(from()); } + catch(...) { fail(&boost::contract::postcondition_failed); } } - boost::contract::from from() const { return from_; } + void fail(void (*h)(boost::contract::from)) { + failed(true); + if(h) h(from_); + } + + // Virtual so overriding public functions can use virtual_::failed_ instead. + virtual bool failed() const { return failed_; } + virtual void failed(bool value) { failed_ = value; } private: bool BOOST_CONTRACT_ERROR_missing_guard_declaration; boost::contract::from from_; boost::function pre_; boost::function old_; + bool failed_; }; } } } // namespace diff --git a/include/boost/contract/aux_/condition/check_pre_post.hpp b/include/boost/contract/aux_/condition/check_pre_post.hpp index b78b678..99237a5 100644 --- a/include/boost/contract/aux_/condition/check_pre_post.hpp +++ b/include/boost/contract/aux_/condition/check_pre_post.hpp @@ -12,6 +12,7 @@ #include #include #include +#include /** @endcond */ namespace boost { namespace contract { namespace aux { @@ -30,7 +31,7 @@ class check_pre_post : public check_base { public: explicit check_pre_post(boost::contract::from from) : check_base(from) {} - virtual ~check_pre_post() {} + virtual ~check_pre_post() BOOST_NOEXCEPT_IF(false) {} template void set_post(F const& f) { @@ -39,11 +40,12 @@ public: protected: void check_post(r_cref const& r) { + if(failed()) return; try { if(BOOST_CONTRACT_ERROR_postcondition_result_parameter_required) { BOOST_CONTRACT_ERROR_postcondition_result_parameter_required(r); } - } catch(...) { boost::contract::postcondition_failed(from()); } + } catch(...) { fail(&boost::contract::postcondition_failed); } } private: @@ -65,11 +67,12 @@ public: protected: void check_post(none const&) { + if(failed()) return; try { if(BOOST_CONTRACT_ERROR_postcondition_result_parameter_not_allowed){ BOOST_CONTRACT_ERROR_postcondition_result_parameter_not_allowed(); } - } catch(...) { boost::contract::postcondition_failed(from()); } + } catch(...) { fail(&boost::contract::postcondition_failed); } } private: diff --git a/include/boost/contract/aux_/condition/check_pre_post_inv.hpp b/include/boost/contract/aux_/condition/check_pre_post_inv.hpp index 1ddb639..11f8a84 100644 --- a/include/boost/contract/aux_/condition/check_pre_post_inv.hpp +++ b/include/boost/contract/aux_/condition/check_pre_post_inv.hpp @@ -10,10 +10,16 @@ #include #include #include +#include +#include +#include +#include #include #include #include +#include #include +#include /** @endcond */ namespace boost { namespace contract { namespace aux { @@ -71,7 +77,7 @@ public: explicit check_pre_post_inv(boost::contract::from from, C* obj) : check_pre_post(from), obj_(obj) {} - virtual ~check_pre_post_inv() {} + virtual ~check_pre_post_inv() BOOST_NOEXCEPT_IF(false) {} protected: void check_exit_inv() { check_inv(false, false); } @@ -84,6 +90,7 @@ protected: private: void check_inv(bool on_entry, bool static_inv_only) { + if(this->failed()) return; try { // Static members only check static inv. check_static_inv(); @@ -94,23 +101,28 @@ private: check_const_inv(); } } catch(...) { - if(on_entry) boost::contract::entry_invariant_failed(from()); - else boost::contract::exit_invariant_failed(from()); + if(on_entry) this->fail(&boost::contract::entry_invariant_failed); + else this->fail(&boost::contract::exit_invariant_failed); } } - template typename boost::enable_if< boost::contract::access::has_static_invariant >::type - check_static_inv() { boost::contract::access::static_invariant(); } + check_static_inv() { + // SFINAE HAS_STATIC_... returns true even when member is inherited so + // need extra run-time check here (that's not the case for non static). + if(!inherited::apply()) { + boost::contract::access::static_invariant(); + } + } template typename boost::disable_if< boost::contract::access::has_static_invariant >::type check_static_inv() {} - template typename boost::enable_if< boost::contract::access::has_cv_invariant >::type @@ -138,11 +150,51 @@ private: template typename boost::disable_if >::type check_const_inv() {} + + // Check is class's func is inherited from its base types or not. + template class HasFunc, template class FuncAddr> + struct inherited { + static bool apply() { + try { + boost::mpl::for_each< + // For now, no reason to deeply search inheritance tree (as + // SFINAE HAS_STATIC_... already fails in that case). + typename boost::mpl::transform< + typename boost::mpl::copy_if< + typename boost::mpl::eval_if, + typename boost::contract::access:: + base_types_of + , + boost::mpl::vector<> + >::type, + HasFunc + >::type, + boost::add_pointer + >::type + >(compare_func_addr()); + } catch(signal_equal const&) { return true; } + return false; + } + + private: + struct signal_equal {}; // Exception to stop for_each as soon as found. + + struct compare_func_addr { + template + void operator()(B*) { + // Inherited func has same addr as in its base. + if(FuncAddr::apply() == FuncAddr::apply()) { + throw signal_equal(); + } + } + }; + }; C* obj_; }; -} } } +} } } // namespace #endif // #include guard diff --git a/include/boost/contract/aux_/condition/check_subcontracted_pre_post_inv.hpp b/include/boost/contract/aux_/condition/check_subcontracted_pre_post_inv.hpp index cec583e..e7ee7e0 100644 --- a/include/boost/contract/aux_/condition/check_subcontracted_pre_post_inv.hpp +++ b/include/boost/contract/aux_/condition/check_subcontracted_pre_post_inv.hpp @@ -23,7 +23,9 @@ #include #include #include +#include #include +#include #include #include #include @@ -33,16 +35,17 @@ #include #include #include +#include #include #include /** @endcond */ -// TODO: If overriding function does not specify .precondition(...), make sure the overridden preconditions are still checked (and not that subcontracted preconditions always pass just because the overriding function does not specify them). - namespace boost { namespace contract { namespace aux { namespace check_subcontracted_pre_post_inv_ { - struct no_error {}; // Exception to signal OK (must not inherit). + // Exception signals (must not inherit). + struct signal_no_error {}; + struct signal_not_checked {}; } // O, R, F, and A-i can be none types (but C cannot). @@ -128,59 +131,58 @@ public: v_->result_optional_ = is_optional::value; } else v_ = 0; } - check_base_.nest(this); } - virtual ~check_subcontracted_pre_post_inv() { + virtual ~check_subcontracted_pre_post_inv() BOOST_NOEXCEPT_IF(false) { if(!base_call_ && v_) delete v_; } protected: void init_subcontracted_old() { - // Old values of overloaded func on stack (so no functor `f` here). - execute(boost::contract::virtual_::push_old_init); + exec_and(boost::contract::virtual_::push_old_init + /* old values of overloaded func on stack (so no `f` here) */); } void check_subcontracted_entry_inv() { - execute(boost::contract::virtual_::check_entry_inv, + exec_and(boost::contract::virtual_::check_entry_inv, &check_subcontracted_pre_post_inv::check_entry_inv); } - // Allow to throw on failure for relaxing subcontracted pre. void check_subcontracted_pre() { - if(!base_call_ || v_->action_ == - boost::contract::virtual_::check_pre) { - try { - if(!base_call_ && v_) { - v_->action_ = boost::contract::virtual_::check_pre; - boost::mpl::for_each(check_base_); - } - // Pre logic-or: Last check, error also throws. - this->check_pre(/* throw_on_failure = */ base_call_); - } catch(check_subcontracted_pre_post_inv_::no_error const&) { - // Pre logic-or: Stop at 1st no_error (thrown by callee). - } - if(base_call_) throw check_subcontracted_pre_post_inv_::no_error(); - } + exec_or( + boost::contract::virtual_::check_pre, + &check_subcontracted_pre_post_inv::check_pre, + &boost::contract::precondition_failed + ); } void copy_subcontracted_old() { - execute(boost::contract::virtual_::call_old_copy, + exec_and(boost::contract::virtual_::call_old_copy, &check_subcontracted_pre_post_inv::copy_old_v); } void check_subcontracted_exit_inv() { - execute(boost::contract::virtual_::check_exit_inv, + exec_and(boost::contract::virtual_::check_exit_inv, &check_subcontracted_pre_post_inv::check_exit_inv); } void check_subcontracted_post() { - execute(boost::contract::virtual_::check_post, + exec_and(boost::contract::virtual_::check_post, &check_subcontracted_pre_post_inv::check_post_v); } bool base_call() const { return base_call_; } + bool failed() const /* override */ { + if(v_) return v_->failed_; + else return check_base::failed(); + } + + void failed(bool value) /* override */ { + if(v_) v_->failed_ = value; + else check_base::failed(value); + } + private: void copy_old_v() { boost::contract::virtual_::action_enum a; @@ -217,7 +219,7 @@ private: throw boost::contract::bad_virtual_result_cast( v_->result_type_name_, typeid(r_type).name()); } catch(...) { - boost::contract::postcondition_failed(from()); + this->fail(&boost::contract::postcondition_failed); } } } @@ -228,11 +230,15 @@ private: try { throw boost::contract::bad_virtual_result_cast( v_->result_type_name_, typeid(r_type).name()); - } catch(...) { boost::contract::postcondition_failed(from()); } + } catch(...) { + this->fail(&boost::contract::postcondition_failed); + } } } check_post_r(r); } + + // TODO: See if these and other enable_if can be replaced using template specializations and a base class for template where to put common code (that might be faster to compile... not sure...). template typename boost::enable_if >::type @@ -245,51 +251,108 @@ private: this->check_post(*r); } - void execute(boost::contract::virtual_::action_enum a, - void (check_subcontracted_pre_post_inv::* f)() = 0) { + void exec_and( + boost::contract::virtual_::action_enum a, + void (check_subcontracted_pre_post_inv::* f)() = 0 + ) { + if(failed()) return; if(!base_call_ || v_->action_ == a) { if(!base_call_ && v_) { v_->action_ = a; - boost::mpl::for_each(check_base_); + boost::mpl::for_each(call_base(this)); } if(f) (this->*f)(); - if(base_call_) throw check_subcontracted_pre_post_inv_::no_error(); + if(base_call_) { + throw check_subcontracted_pre_post_inv_::signal_no_error(); + } } } - class check_base { // Copyable (as *). - public: - explicit check_base() : nest_() {} + void exec_or( + boost::contract::virtual_::action_enum a, + bool (check_subcontracted_pre_post_inv::* f)(bool) = 0, + void (*h)(boost::contract::from) = 0 + ) { + if(failed()) return; + if(!base_call_ || v_->action_ == a) { + if(!base_call_ && v_) { + v_->action_ = a; + try { + exec_or_bases(); + return; // At lest one base checked with no error (done). + } catch(...) { + bool checked = f ? + (this->*f)(/* throw_on_failure = */ false) : false; + if(!checked) { + try { throw; } // Report latest exception found. + catch(...) { this->fail(h); } + } + return; // Checked and no exception (done). + } + } + bool checked = f ? + (this->*f)(/* throw_on_failure = */ base_call_) : false; + if(base_call_) { + if(!checked) { + throw check_subcontracted_pre_post_inv_:: + signal_not_checked(); + } + throw check_subcontracted_pre_post_inv_::signal_no_error(); + } + } + } + + template + typename boost::enable_if, bool>::type + exec_or_bases() { return false; } - void nest(check_subcontracted_pre_post_inv* n) { nest_ = n; } + template + typename boost::disable_if, bool>::type + exec_or_bases() { + if(boost::mpl::empty::value) return false; + try { + call_base(this)(typename boost::mpl::front::type()); + } catch(check_subcontracted_pre_post_inv_::signal_not_checked const&) { + return exec_or_bases< + typename boost::mpl::pop_front::type>(); + } catch(...) { + bool checked = false; + try { + checked = exec_or_bases< + typename boost::mpl::pop_front::type>(); + } catch(...) { checked = false; } + if(!checked) throw; + } + return true; + } + + class call_base { // Copyable (as *). + public: + explicit call_base(check_subcontracted_pre_post_inv* outer) : + outer_(outer) { + BOOST_CONTRACT_AUX_DEBUG(outer_); + } template void operator()(B*) { - BOOST_CONTRACT_AUX_DEBUG(nest_->object()); - BOOST_CONTRACT_AUX_DEBUG(nest_->v_); - BOOST_CONTRACT_AUX_DEBUG(nest_->v_->action_ != + BOOST_CONTRACT_AUX_DEBUG(outer_->object()); + BOOST_CONTRACT_AUX_DEBUG(outer_->v_); + BOOST_CONTRACT_AUX_DEBUG(outer_->v_->action_ != boost::contract::virtual_::no_action); try { - O::template BOOST_CONTRACT_AUX_NAME1(base_call)( - nest_->object(), nest_->a0_, nest_->a1_, nest_->v_); - } catch(check_subcontracted_pre_post_inv_::no_error const&) { - if(nest_->v_->action_ == boost::contract::virtual_::check_pre) { - throw; // Pre logic-or: 1st no_err stops (throw to caller). - } - } catch(...) { - if(nest_->v_->action_ == boost::contract::virtual_::check_pre) { - // Pre logic-or: Ignore err, possibly checks up to caller. - } + O::template BOOST_CONTRACT_AUX_NAME1(call_base)( + outer_->object(), outer_->a0_, outer_->a1_, outer_->v_); + } catch(check_subcontracted_pre_post_inv_::signal_no_error const&) { + // No error (do not throw). } } private: - check_subcontracted_pre_post_inv* nest_; + check_subcontracted_pre_post_inv* outer_; }; - + boost::contract::virtual_* v_; bool base_call_; - check_base check_base_; // Copyable (as *). R& r_; // TODO: Support configurable func arity (using both C++11 variadic templates and boost.preprocessor when C++11 variadic template are not supported). A0& a0_; diff --git a/include/boost/contract/aux_/debug.hpp b/include/boost/contract/aux_/debug.hpp index b7479ba..654deaa 100644 --- a/include/boost/contract/aux_/debug.hpp +++ b/include/boost/contract/aux_/debug.hpp @@ -6,7 +6,7 @@ #include /** @endcond */ -// Usually, never #defined (and debug assertions always on in the code). +// Usually, never #defined (and debug assertions always in the code). #ifdef BOOST_CONTRACT_AUX_CONFIG_NDEBUG # define BOOST_CONTRACT_AUX_DEBUG(cond) #else diff --git a/include/boost/contract/aux_/operation/constructor.hpp b/include/boost/contract/aux_/operation/constructor.hpp index fe131aa..5df7458 100644 --- a/include/boost/contract/aux_/operation/constructor.hpp +++ b/include/boost/contract/aux_/operation/constructor.hpp @@ -7,6 +7,7 @@ #include #include /** @cond */ +#include #include /** @endcond */ @@ -34,7 +35,7 @@ private: } public: - ~constructor() { + ~constructor() BOOST_NOEXCEPT_IF(false) { this->assert_guarded(); if(check_guard::checking()) return; check_guard checking; diff --git a/include/boost/contract/aux_/operation/destructor.hpp b/include/boost/contract/aux_/operation/destructor.hpp index 94bcfd4..59a3435 100644 --- a/include/boost/contract/aux_/operation/destructor.hpp +++ b/include/boost/contract/aux_/operation/destructor.hpp @@ -7,6 +7,7 @@ #include #include /** @cond */ +#include #include /** @endcond */ @@ -34,7 +35,7 @@ private: } public: - ~destructor() { + ~destructor() BOOST_NOEXCEPT_IF(false) { this->assert_guarded(); if(check_guard::checking()) return; check_guard checking; diff --git a/include/boost/contract/aux_/operation/function.hpp b/include/boost/contract/aux_/operation/function.hpp index cb041dd..c0b1198 100644 --- a/include/boost/contract/aux_/operation/function.hpp +++ b/include/boost/contract/aux_/operation/function.hpp @@ -6,7 +6,7 @@ #include #include /** @cond */ -#include +#include #include /** @endcond */ @@ -30,7 +30,7 @@ private: } public: - ~function() { + ~function() BOOST_NOEXCEPT_IF(false) { this->assert_guarded(); if(check_guard::checking()) return; check_guard checking; diff --git a/include/boost/contract/aux_/operation/public_function.hpp b/include/boost/contract/aux_/operation/public_function.hpp index d48b89a..a0aeb5f 100644 --- a/include/boost/contract/aux_/operation/public_function.hpp +++ b/include/boost/contract/aux_/operation/public_function.hpp @@ -7,6 +7,7 @@ #include #include /** @cond */ +#include #include /** @endcond */ @@ -43,7 +44,7 @@ private: } public: - ~public_function() { + ~public_function() BOOST_NOEXCEPT_IF(false) { this->assert_guarded(); if(!this->base_call()) { if(check_guard::checking()) return; diff --git a/include/boost/contract/aux_/operation/public_static_function.hpp b/include/boost/contract/aux_/operation/public_static_function.hpp index dd31fb3..4928e20 100644 --- a/include/boost/contract/aux_/operation/public_static_function.hpp +++ b/include/boost/contract/aux_/operation/public_static_function.hpp @@ -8,7 +8,7 @@ #include #include /** @cond */ -#include +#include #include /** @endcond */ @@ -35,7 +35,7 @@ private: } public: - ~public_static_function() { + ~public_static_function() BOOST_NOEXCEPT_IF(false) { this->assert_guarded(); if(check_guard::checking()) return; check_guard checking; diff --git a/include/boost/contract/aux_/operator_safe_bool.hpp b/include/boost/contract/aux_/operator_safe_bool.hpp index eb8ecf8..df31145 100644 --- a/include/boost/contract/aux_/operator_safe_bool.hpp +++ b/include/boost/contract/aux_/operator_safe_bool.hpp @@ -31,6 +31,8 @@ #elif defined(_MANAGED) +// TODO: All code below should use BOOST_CONTRACT_AUX_NAME(...) instead of boost_contract_aux_... + #define BOOST_CONTRACT_AUX_OPERATOR_SAFE_BOOL(this_type, bool_expr) \ static void boost_contract_aux_operator_safe_bool_func(this_type***) {} \ typedef void (*boost_contract_aux_operator_safe_bool_type)(this_type***); \ diff --git a/include/boost/contract/constructor.hpp b/include/boost/contract/constructor.hpp index 84931a3..c272c71 100644 --- a/include/boost/contract/constructor.hpp +++ b/include/boost/contract/constructor.hpp @@ -7,16 +7,13 @@ #include #include #include -/** @cond */ -#include -/** @endcond */ namespace boost { namespace contract { template set_old_postcondition<> constructor(C* obj) { - return set_old_postcondition<>(boost::make_shared< - boost::contract::aux::constructor >(obj)); + return set_old_postcondition<>( + new boost::contract::aux::constructor(obj)); } // Uses C tparam to avoid multiple inheritance from same type. diff --git a/include/boost/contract/core/access.hpp b/include/boost/contract/core/access.hpp index c3893be..5459e39 100644 --- a/include/boost/contract/core/access.hpp +++ b/include/boost/contract/core/access.hpp @@ -61,6 +61,15 @@ class access { C::BOOST_CONTRACT_CONFIG_STATIC_INVARIANT(); } + template + class static_invariant_addr { // Tpl instead of func to pass it as tparam. + typedef void (*func_ptr)(); + public: + static func_ptr apply() { + return &C::BOOST_CONTRACT_CONFIG_STATIC_INVARIANT; + } + }; + BOOST_CONTRACT_AUX_INTROSPECTION_HAS_MEMBER_FUNCTION( has_invariant_f, BOOST_CONTRACT_CONFIG_INVARIANT) diff --git a/include/boost/contract/core/exception.hpp b/include/boost/contract/core/exception.hpp index d18d7ac..a0bc8e1 100644 --- a/include/boost/contract/core/exception.hpp +++ b/include/boost/contract/core/exception.hpp @@ -5,6 +5,7 @@ /** @file */ /** @cond */ +#include #include #include #include @@ -87,7 +88,8 @@ enum from { from_function }; -typedef void (*assertion_failed_handler)(from); +// Must us boost::function to allow users to pass lambdas, binds, etc. +typedef boost::function assertion_failed_handler; namespace exception_ { enum failed_key { pre_key, post_key, entry_inv_key, exit_inv_key }; @@ -146,8 +148,8 @@ namespace exception_ { /*boost::mutex::scoped_lock lock(exception_::_mutex);*/ \ exception_::handler(where); -assertion_failed_handler set_precondition_failed(assertion_failed_handler f) - BOOST_NOEXCEPT_OR_NOTHROW { +assertion_failed_handler set_precondition_failed( + assertion_failed_handler const& f) BOOST_NOEXCEPT_OR_NOTHROW { BOOST_CONTRACT_EXCEPTION_SET_HANDLER_(pre_failed_mutex, pre_failed_handler, f) } @@ -161,8 +163,8 @@ void precondition_failed(from where) /* can throw */ { where) } -assertion_failed_handler set_postcondition_failed(assertion_failed_handler f) - BOOST_NOEXCEPT_OR_NOTHROW { +assertion_failed_handler set_postcondition_failed( + assertion_failed_handler const& f) BOOST_NOEXCEPT_OR_NOTHROW { BOOST_CONTRACT_EXCEPTION_SET_HANDLER_(post_failed_mutex, post_failed_handler, f) } @@ -177,8 +179,8 @@ void postcondition_failed(from where) /* can throw */ { post_failed_handler, where) } -assertion_failed_handler set_entry_invariant_failed(assertion_failed_handler f) - BOOST_NOEXCEPT_OR_NOTHROW { +assertion_failed_handler set_entry_invariant_failed( + assertion_failed_handler const& f) BOOST_NOEXCEPT_OR_NOTHROW { BOOST_CONTRACT_EXCEPTION_SET_HANDLER_(entry_inv_failed_mutex, entry_inv_failed_handler, f) } @@ -194,8 +196,8 @@ void entry_invariant_failed(from where) /* can throw */ { entry_inv_failed_handler, where) } -assertion_failed_handler set_exit_invariant_failed(assertion_failed_handler f) - BOOST_NOEXCEPT_OR_NOTHROW { +assertion_failed_handler set_exit_invariant_failed( + assertion_failed_handler const& f) BOOST_NOEXCEPT_OR_NOTHROW { BOOST_CONTRACT_EXCEPTION_SET_HANDLER_(exit_inv_failed_mutex, exit_inv_failed_handler, f) } @@ -210,8 +212,8 @@ void exit_invariant_failed(from where) /* can throw */ { exit_inv_failed_handler, where) } -void set_invariant_failed(assertion_failed_handler f) - BOOST_NOEXCEPT_OR_NOTHROW { +void set_invariant_failed( + assertion_failed_handler const& f) BOOST_NOEXCEPT_OR_NOTHROW { set_entry_invariant_failed(f); set_exit_invariant_failed(f); } diff --git a/include/boost/contract/core/set_nothing.hpp b/include/boost/contract/core/set_nothing.hpp index b2f389b..740f5b4 100644 --- a/include/boost/contract/core/set_nothing.hpp +++ b/include/boost/contract/core/set_nothing.hpp @@ -5,9 +5,7 @@ /** @file */ #include -/** @cond */ -#include -/** @endcond */ +#include namespace boost { namespace contract { @@ -24,15 +22,14 @@ namespace boost { namespace boost { namespace contract { -// TODO: Do I need to store contracts as shared_ptr or unique_ptr is sufficient? Actually, double check all shared_ptr used in the lib anywhere (also in old_ptr, etc.) and see if unique_ptr would be sufficient there. - class set_nothing { // Copyable as shared * (OK also for RAII). public: // No set member functions here. private: - typedef boost::shared_ptr check_ptr; - explicit set_nothing(check_ptr check): check_(check) {} + typedef boost::contract::aux::check_base* check_ptr; + explicit set_nothing(check_ptr check) : + check_(check) { BOOST_CONTRACT_AUX_DEBUG(check); } check_ptr check_; // Friendship used to limit library's public API. diff --git a/include/boost/contract/core/set_old_postcondition.hpp b/include/boost/contract/core/set_old_postcondition.hpp index b7cdd5e..95da020 100644 --- a/include/boost/contract/core/set_old_postcondition.hpp +++ b/include/boost/contract/core/set_old_postcondition.hpp @@ -8,9 +8,7 @@ #include #include #include -/** @cond */ -#include -/** @endcond */ +#include namespace boost { namespace contract { @@ -37,9 +35,10 @@ public: } private: - typedef boost::shared_ptr::type> > check_ptr; - explicit set_old_postcondition(check_ptr check) : check_(check) {} + typedef boost::contract::aux::check_pre_post< + typename boost::contract::aux::none_if_void::type>* check_ptr; + explicit set_old_postcondition(check_ptr check) : + check_(check) { BOOST_CONTRACT_AUX_DEBUG(check_); } check_ptr check_; // Friendship used to limit library's public API. diff --git a/include/boost/contract/core/set_postcondition_only.hpp b/include/boost/contract/core/set_postcondition_only.hpp index 01da1e7..3ede8a4 100644 --- a/include/boost/contract/core/set_postcondition_only.hpp +++ b/include/boost/contract/core/set_postcondition_only.hpp @@ -7,9 +7,7 @@ #include #include #include -/** @cond */ -#include -/** @endcond */ +#include namespace boost { namespace contract { @@ -33,9 +31,10 @@ public: } private: - typedef boost::shared_ptr::type> > check_ptr; - explicit set_postcondition_only(check_ptr check) : check_(check) {} + typedef boost::contract::aux::check_pre_post< + typename boost::contract::aux::none_if_void::type>* check_ptr; + explicit set_postcondition_only(check_ptr check) : + check_(check) { BOOST_CONTRACT_AUX_DEBUG(check_); } check_ptr check_; // Friendship used to limit library's public API. diff --git a/include/boost/contract/core/set_precondition_old_postcondition.hpp b/include/boost/contract/core/set_precondition_old_postcondition.hpp index 6ba4e14..632ef8d 100644 --- a/include/boost/contract/core/set_precondition_old_postcondition.hpp +++ b/include/boost/contract/core/set_precondition_old_postcondition.hpp @@ -9,9 +9,7 @@ #include #include #include -/** @cond */ -#include -/** @endcond */ +#include namespace boost { namespace contract { @@ -43,10 +41,10 @@ public: } private: - typedef boost::shared_ptr::type> > check_ptr; + typedef boost::contract::aux::check_pre_post< + typename boost::contract::aux::none_if_void::type>* check_ptr; explicit set_precondition_old_postcondition(check_ptr check) : - check_(check) {} + check_(check) { BOOST_CONTRACT_AUX_DEBUG(check_); } check_ptr check_; // Friendship used to limit library's public API. diff --git a/include/boost/contract/core/virtual.hpp b/include/boost/contract/core/virtual.hpp index 25e6aa8..9172dc3 100644 --- a/include/boost/contract/core/virtual.hpp +++ b/include/boost/contract/core/virtual.hpp @@ -21,7 +21,8 @@ namespace boost { namespace boost { namespace contract { -class virtual_ : private boost::noncopyable { // Non copyable (no queue copy). +class virtual_ : + private boost::noncopyable { // To void queue, stack, etc, copies. // No public API (so users cannot use it directly). private: enum action_enum { @@ -38,8 +39,8 @@ private: pop_old_init = check_post // These must be the same value. }; - explicit virtual_(action_enum a) : action_(a), result_ptr_(), - result_optional_() {} + explicit virtual_(action_enum a) : action_(a), result_type_name_(), + result_optional_(), failed_(false) {} action_enum action_; @@ -50,6 +51,8 @@ private: char const* result_type_name_; bool result_optional_; + bool failed_; + // Friendship used to limit library's public API. friend bool copy_old(virtual_*); friend class convertible_old; diff --git a/include/boost/contract/destructor.hpp b/include/boost/contract/destructor.hpp index 867e79b..f01e223 100644 --- a/include/boost/contract/destructor.hpp +++ b/include/boost/contract/destructor.hpp @@ -6,16 +6,13 @@ #include #include -/** @cond */ -#include -/** @endcond */ namespace boost { namespace contract { template set_old_postcondition<> destructor(C* obj) { - return set_old_postcondition<>(boost::make_shared< - boost::contract::aux::destructor >(obj)); + return set_old_postcondition<>( + new boost::contract::aux::destructor(obj)); } } } // namespace diff --git a/include/boost/contract/function.hpp b/include/boost/contract/function.hpp index 87c3083..7825283 100644 --- a/include/boost/contract/function.hpp +++ b/include/boost/contract/function.hpp @@ -6,15 +6,12 @@ #include #include -/** @cond */ -#include -/** @endcond */ namespace boost { namespace contract { set_precondition_old_postcondition<> function() { - return set_precondition_old_postcondition<>(boost::make_shared< - boost::contract::aux::function>()); + return set_precondition_old_postcondition<>( + new boost::contract::aux::function()); } } } // namespace diff --git a/include/boost/contract/guard.hpp b/include/boost/contract/guard.hpp index 071efea..da0101c 100644 --- a/include/boost/contract/guard.hpp +++ b/include/boost/contract/guard.hpp @@ -9,34 +9,51 @@ #include #include #include +#include /** @cond */ -#include #include +#include /** @endcond */ +// TODO: Add a test for when `guard c = ...` is missing. + namespace boost { namespace contract { -class guard { // Copyable as shared * (OK also for RAII). +class guard { // Copyable as * (OK also for RAII). public: - // All implicit to allow `guard c = ...`. + // Following all implicit to allow syntax `guard c = ...`. template /* implicit */ guard(set_precondition_old_postcondition const& contract) - : check_(contract.check_) { check_->guard(); } + : check_(contract.check_) { + BOOST_CONTRACT_AUX_DEBUG(check_); + check_->guard(); + } template /* implicit */ guard(set_old_postcondition const& contract) - : check_(contract.check_) { check_->guard(); } + : check_(contract.check_) { + BOOST_CONTRACT_AUX_DEBUG(check_); + check_->guard(); + } template /* implicit */ guard(set_postcondition_only const& contract) - : check_(contract.check_) { check_->guard(); } + : check_(contract.check_) { + BOOST_CONTRACT_AUX_DEBUG(check_); + check_->guard(); + } /* implicit */ guard(set_nothing const& contract) - : check_(contract.check_) { check_->guard(); } + : check_(contract.check_) { + BOOST_CONTRACT_AUX_DEBUG(check_); + check_->guard(); + } + + ~guard() BOOST_NOEXCEPT_IF(false) { delete check_; } // Also for RAII. private: - boost::shared_ptr check_; + boost::contract::aux::check_base* check_; }; } } // namespace diff --git a/include/boost/contract/override.hpp b/include/boost/contract/override.hpp index b280570..a87fdc3 100644 --- a/include/boost/contract/override.hpp +++ b/include/boost/contract/override.hpp @@ -26,7 +26,7 @@ class BOOST_CONTRACT_AUX_NAME1(B), \ class BOOST_CONTRACT_AUX_NAME1(C) \ > \ - static void BOOST_CONTRACT_AUX_NAME1(base_call)( \ + static void BOOST_CONTRACT_AUX_NAME1(call_base)( \ BOOST_CONTRACT_AUX_NAME1(C)* BOOST_CONTRACT_AUX_NAME1(obj), \ boost::contract::aux::none&, \ boost::contract::aux::none&, \ @@ -42,7 +42,7 @@ class BOOST_CONTRACT_AUX_NAME1(C), \ typename BOOST_CONTRACT_AUX_NAME1(A0) \ > \ - static void BOOST_CONTRACT_AUX_NAME1(base_call)( \ + static void BOOST_CONTRACT_AUX_NAME1(call_base)( \ BOOST_CONTRACT_AUX_NAME1(C)* BOOST_CONTRACT_AUX_NAME1(obj), \ BOOST_CONTRACT_AUX_NAME1(A0)& BOOST_CONTRACT_AUX_NAME1(a0), \ boost::contract::aux::none&, \ @@ -60,7 +60,7 @@ typename BOOST_CONTRACT_AUX_NAME1(A0), \ typename BOOST_CONTRACT_AUX_NAME1(A1) \ > \ - static void BOOST_CONTRACT_AUX_NAME1(base_call)( \ + static void BOOST_CONTRACT_AUX_NAME1(call_base)( \ BOOST_CONTRACT_AUX_NAME1(C)* BOOST_CONTRACT_AUX_NAME1(obj), \ BOOST_CONTRACT_AUX_NAME1(A0)& BOOST_CONTRACT_AUX_NAME1(a0), \ BOOST_CONTRACT_AUX_NAME1(A1)& BOOST_CONTRACT_AUX_NAME1(a1), \ diff --git a/include/boost/contract/public_function.hpp b/include/boost/contract/public_function.hpp index b41376d..541af64 100644 --- a/include/boost/contract/public_function.hpp +++ b/include/boost/contract/public_function.hpp @@ -12,7 +12,6 @@ #include /** @cond */ #include -#include #include #include #include @@ -77,23 +76,23 @@ namespace public_function_ { // For static member functions. template set_precondition_old_postcondition<> public_function() { - return set_precondition_old_postcondition<>(boost::make_shared< - boost::contract::aux::public_static_function >()); + return set_precondition_old_postcondition<>( + new boost::contract::aux::public_static_function()); } // For non-virtual, non-overriding member functions. template set_precondition_old_postcondition<> public_function(C* obj) { boost::contract::aux::none n; - return set_precondition_old_postcondition<>(boost::make_shared< - boost::contract::aux::public_function< + return set_precondition_old_postcondition<>( + new boost::contract::aux::public_function< boost::contract::aux::none, boost::contract::aux::none, boost::contract::aux::none, C, boost::contract::aux::none, boost::contract::aux::none - > - >(static_cast(0), obj, n, n, n)); + >(static_cast(0), obj, n, n, n) + ); } // NOTE: O and R (optionally) allowed only when v is present because: @@ -114,15 +113,15 @@ template set_precondition_old_postcondition<> public_function(virtual_* v, C* obj) { // NOTE: No F so cannot enforce enclosing function is void (up to user). boost::contract::aux::none n; - return set_precondition_old_postcondition<>(boost::make_shared< - boost::contract::aux::public_function< + return set_precondition_old_postcondition<>( + new boost::contract::aux::public_function< boost::contract::aux::none, boost::contract::aux::none, boost::contract::aux::none, C, boost::contract::aux::none, boost::contract::aux::none - > - >(v, obj, n, n, n)); + >(v, obj, n, n, n) + ); } // For virtual, non-overriding, non-void member functions. @@ -131,15 +130,15 @@ set_precondition_old_postcondition public_function( virtual_* v, R& r, C* obj) { // NOTE: No F so cannot enforce enclosing function returns R (up to user). boost::contract::aux::none n; - return set_precondition_old_postcondition(boost::make_shared< - boost::contract::aux::public_function< + return set_precondition_old_postcondition( + new boost::contract::aux::public_function< boost::contract::aux::none, R, boost::contract::aux::none, C, boost::contract::aux::none, boost::contract::aux::none - > - >(v, obj, r, n, n)); + >(v, obj, r, n, n) + ); } /* Overriding (arity = 0) */ @@ -151,15 +150,15 @@ set_precondition_old_postcondition<> public_function(virtual_* v, F, C* obj) { BOOST_CONTRACT_PUBLIC_FUNCTION_HAS_VOID_RESULT_(F) BOOST_CONTRACT_PUBLIC_FUNCTION_HAS_BASE_TYPES_(C) boost::contract::aux::none n; - return set_precondition_old_postcondition<>(boost::make_shared< - boost::contract::aux::public_function< + return set_precondition_old_postcondition<>( + new boost::contract::aux::public_function< O, boost::contract::aux::none, F, C, boost::contract::aux::none, boost::contract::aux::none - > - >(v, obj, n, n, n)); + >(v, obj, n, n, n) + ); } // For virtual, overriding, non-void member functions of class with bases. @@ -170,15 +169,15 @@ set_precondition_old_postcondition public_function( BOOST_CONTRACT_PUBLIC_FUNCTION_HAS_RESULT_(F, R) BOOST_CONTRACT_PUBLIC_FUNCTION_HAS_BASE_TYPES_(C) boost::contract::aux::none n; - return set_precondition_old_postcondition(boost::make_shared< - boost::contract::aux::public_function< + return set_precondition_old_postcondition( + new boost::contract::aux::public_function< O, R, F, C, boost::contract::aux::none, boost::contract::aux::none - > - >(v, obj, r, n, n)); + >(v, obj, r, n, n) + ); } /* Overriding (arity = 1) */ @@ -190,15 +189,15 @@ set_precondition_old_postcondition<> public_function( BOOST_CONTRACT_PUBLIC_FUNCTION_HAS_VOID_RESULT_(F) BOOST_CONTRACT_PUBLIC_FUNCTION_HAS_BASE_TYPES_(C) boost::contract::aux::none n; - return set_precondition_old_postcondition<>(boost::make_shared< - boost::contract::aux::public_function< + return set_precondition_old_postcondition<>( + new boost::contract::aux::public_function< O, boost::contract::aux::none, F, C, A0, boost::contract::aux::none - > - >(v, obj, n, a0, n)); + >(v, obj, n, a0, n) + ); } template @@ -208,15 +207,15 @@ set_precondition_old_postcondition public_function( BOOST_CONTRACT_PUBLIC_FUNCTION_HAS_RESULT_(F, R) BOOST_CONTRACT_PUBLIC_FUNCTION_HAS_BASE_TYPES_(C) boost::contract::aux::none n; - return set_precondition_old_postcondition(boost::make_shared< - boost::contract::aux::public_function< + return set_precondition_old_postcondition( + new boost::contract::aux::public_function< O, R, F, C, A0, boost::contract::aux::none - > - >(v, obj, r, a0, n)); + >(v, obj, r, a0, n) + ); } /* Overriding (arity = 2) */ @@ -228,15 +227,15 @@ set_precondition_old_postcondition<> public_function( BOOST_CONTRACT_PUBLIC_FUNCTION_HAS_VOID_RESULT_(F) BOOST_CONTRACT_PUBLIC_FUNCTION_HAS_BASE_TYPES_(C) boost::contract::aux::none n; - return set_precondition_old_postcondition<>(boost::make_shared< - boost::contract::aux::public_function< + return set_precondition_old_postcondition<>( + new boost::contract::aux::public_function< O, boost::contract::aux::none, F, C, A0, A1 - > - >(v, obj, n, a0, a1)); + >(v, obj, n, a0, a1) + ); } template @@ -245,15 +244,15 @@ set_precondition_old_postcondition public_function( BOOST_CONTRACT_PUBLIC_FUNCTION_HAS_ARITY(F, 2) BOOST_CONTRACT_PUBLIC_FUNCTION_HAS_RESULT_(F, R) BOOST_CONTRACT_PUBLIC_FUNCTION_HAS_BASE_TYPES_(C) - return set_precondition_old_postcondition(boost::make_shared< - boost::contract::aux::public_function< + return set_precondition_old_postcondition( + new boost::contract::aux::public_function< O, R, F, C, A0, A1 - > - >(v, obj, r, a0, a1)); + >(v, obj, r, a0, a1) + ); } } } // namespace diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index 41159b0..4ad5d3a 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -17,11 +17,10 @@ test-suite destructor : test-suite public_function : [ subdir-run public_function : bases ] - [ subdir-run public_function : bases_pre ] [ subdir-run public_function : bases_virtual ] [ subdir-run public_function : bases_branch ] [ subdir-run public_function : bases_sparse ] - + [ subdir-run public_function : body_throw ] [ subdir-run public_function : access ] @@ -30,10 +29,41 @@ test-suite public_function : [ subdir-compile-fail public_function : override_error ] [ subdir-run public_function : override_permissive ] + + [ subdir-run public_function : decl_pre_all ] + [ subdir-run public_function : decl_pre_sides ] + [ subdir-run public_function : decl_pre_middle ] + [ subdir-run public_function : decl_pre_none ] + + [ subdir-run public_function : decl_post_all ] + [ subdir-run public_function : decl_post_sides ] + [ subdir-run public_function : decl_post_middle ] + [ subdir-run public_function : decl_post_none ] + + [ subdir-run public_function : decl_entry_static_inv_all ] + [ subdir-run public_function : decl_entry_static_inv_sides ] + [ subdir-run public_function : decl_entry_static_inv_middle ] + [ subdir-run public_function : decl_entry_static_inv_none ] + + [ subdir-run public_function : decl_exit_static_inv_all ] + [ subdir-run public_function : decl_exit_static_inv_sides ] + [ subdir-run public_function : decl_exit_static_inv_middle ] + [ subdir-run public_function : decl_exit_static_inv_none ] + + [ subdir-run public_function : decl_entry_inv_all ] + [ subdir-run public_function : decl_entry_inv_sides ] + [ subdir-run public_function : decl_entry_inv_middle ] + [ subdir-run public_function : decl_entry_inv_none ] + + [ subdir-run public_function : decl_exit_inv_all ] + [ subdir-run public_function : decl_exit_inv_sides ] + [ subdir-run public_function : decl_exit_inv_middle ] + [ subdir-run public_function : decl_exit_inv_none ] ; test-suite function : - [ subdir-run function : pre_post ] + [ subdir-run function : func ] + [ subdir-run function : decl_pre_none ] [ subdir-run function : body_throw ] ; diff --git a/test/function/decl_pre_none.cpp b/test/function/decl_pre_none.cpp new file mode 100644 index 0000000..9c4c500 --- /dev/null +++ b/test/function/decl_pre_none.cpp @@ -0,0 +1,36 @@ + +// Test no precondition. + +#include "../aux_/oteststream.hpp" +#include +#include +#include +#include + +boost::contract::aux::test::oteststream out; + +void f() { + boost::contract::guard c = boost::contract::function() + // No `.precondition(...)` here. + .old([] { out << "f::old" << std::endl; }) + .postcondition([] { out << "f::post" << std::endl; }) + ; + out << "f::body" << std::endl; +} + + +int main() { + std::ostringstream ok; + + out.str(""); + f(); + ok.str(""); ok // Did not check pre, but did not fail contract. + << "f::old" << std::endl + << "f::body" << std::endl + << "f::post" << std::endl + ; + BOOST_TEST(out.eq(ok.str())); + + return boost::report_errors(); +} + diff --git a/test/function/pre_post.cpp b/test/function/func.cpp similarity index 100% rename from test/function/pre_post.cpp rename to test/function/func.cpp diff --git a/test/invariant/all_static_cv_const.cpp b/test/invariant/all_static_cv_const.cpp index 188097b..75e368e 100644 --- a/test/invariant/all_static_cv_const.cpp +++ b/test/invariant/all_static_cv_const.cpp @@ -4,5 +4,5 @@ #define BOOST_CONTRACT_AUX_TEST_STATIC_INV #define BOOST_CONTRACT_AUX_TEST_CV_INV #define BOOST_CONTRACT_AUX_TEST_CONST_INV -#include "combinations.i" +#include "combinations.hpp" diff --git a/test/invariant/both_cv_const.cpp b/test/invariant/both_cv_const.cpp index a566dff..6c87aaf 100644 --- a/test/invariant/both_cv_const.cpp +++ b/test/invariant/both_cv_const.cpp @@ -4,5 +4,5 @@ #undef BOOST_CONTRACT_AUX_TEST_STATIC_INV #define BOOST_CONTRACT_AUX_TEST_CV_INV #define BOOST_CONTRACT_AUX_TEST_CONST_INV -#include "combinations.i" +#include "combinations.hpp" diff --git a/test/invariant/both_static_const.cpp b/test/invariant/both_static_const.cpp index 043dfbd..540b05f 100644 --- a/test/invariant/both_static_const.cpp +++ b/test/invariant/both_static_const.cpp @@ -4,5 +4,5 @@ #define BOOST_CONTRACT_AUX_TEST_STATIC_INV #undef BOOST_CONTRACT_AUX_TEST_CV_INV #define BOOST_CONTRACT_AUX_TEST_CONST_INV -#include "combinations.i" +#include "combinations.hpp" diff --git a/test/invariant/both_static_cv.cpp b/test/invariant/both_static_cv.cpp index 3458c78..59d9dd3 100644 --- a/test/invariant/both_static_cv.cpp +++ b/test/invariant/both_static_cv.cpp @@ -4,5 +4,5 @@ #define BOOST_CONTRACT_AUX_TEST_STATIC_INV #define BOOST_CONTRACT_AUX_TEST_CV_INV #undef BOOST_CONTRACT_AUX_TEST_CONST_INV -#include "combinations.i" +#include "combinations.hpp" diff --git a/test/invariant/combinations.i b/test/invariant/combinations.hpp similarity index 99% rename from test/invariant/combinations.i rename to test/invariant/combinations.hpp index ad97a3a..a2abdb9 100644 --- a/test/invariant/combinations.i +++ b/test/invariant/combinations.hpp @@ -1,4 +1,6 @@ +// no #include guard + // Test all invariants combinations (static/cv/const-only) for all operations. #include "../aux_/oteststream.hpp" diff --git a/test/invariant/inv_mutable.i b/test/invariant/inv_mutable.hpp similarity index 95% rename from test/invariant/inv_mutable.i rename to test/invariant/inv_mutable.hpp index ff1d584..381f38e 100644 --- a/test/invariant/inv_mutable.i +++ b/test/invariant/inv_mutable.hpp @@ -1,4 +1,6 @@ +// no #include guard + // Test error if non-static inv declared mutable (unless PERMISSIVE #defined). #include diff --git a/test/invariant/inv_mutable_error.cpp b/test/invariant/inv_mutable_error.cpp index d488ccd..b9dfdd3 100644 --- a/test/invariant/inv_mutable_error.cpp +++ b/test/invariant/inv_mutable_error.cpp @@ -1,3 +1,3 @@ -#include "inv_mutable.i" +#include "inv_mutable.hpp" diff --git a/test/invariant/inv_mutable_permissive.cpp b/test/invariant/inv_mutable_permissive.cpp index 2473a7a..21e1f3e 100644 --- a/test/invariant/inv_mutable_permissive.cpp +++ b/test/invariant/inv_mutable_permissive.cpp @@ -1,4 +1,4 @@ #define BOOST_CONTRACT_CONFIG_PERMISSIVE -#include "inv_mutable.i" +#include "inv_mutable.hpp" diff --git a/test/invariant/inv_static.i b/test/invariant/inv_static.hpp similarity index 95% rename from test/invariant/inv_static.i rename to test/invariant/inv_static.hpp index 0029683..6474407 100644 --- a/test/invariant/inv_static.i +++ b/test/invariant/inv_static.hpp @@ -1,4 +1,6 @@ +// no #include guard + // Test error if non-static inv declared static (unless PERMISSIVE #defined). #include diff --git a/test/invariant/inv_static_error.cpp b/test/invariant/inv_static_error.cpp index 5374204..89ae865 100644 --- a/test/invariant/inv_static_error.cpp +++ b/test/invariant/inv_static_error.cpp @@ -1,3 +1,3 @@ -#include "inv_static.i" +#include "inv_static.hpp" diff --git a/test/invariant/inv_static_permissive.cpp b/test/invariant/inv_static_permissive.cpp index 75eb16e..96bc326 100644 --- a/test/invariant/inv_static_permissive.cpp +++ b/test/invariant/inv_static_permissive.cpp @@ -1,4 +1,4 @@ #define BOOST_CONTRACT_CONFIG_PERMISSIVE -#include "inv_static.i" +#include "inv_static.hpp" diff --git a/test/invariant/inv_volatile.i b/test/invariant/inv_volatile.hpp similarity index 100% rename from test/invariant/inv_volatile.i rename to test/invariant/inv_volatile.hpp diff --git a/test/invariant/inv_volatile_error.cpp b/test/invariant/inv_volatile_error.cpp index 8229413..b045262 100644 --- a/test/invariant/inv_volatile_error.cpp +++ b/test/invariant/inv_volatile_error.cpp @@ -1,3 +1,3 @@ -#include "inv_volatile.i" +#include "inv_volatile.hpp" diff --git a/test/invariant/inv_volatile_permissive.cpp b/test/invariant/inv_volatile_permissive.cpp index 611052f..c294054 100644 --- a/test/invariant/inv_volatile_permissive.cpp +++ b/test/invariant/inv_volatile_permissive.cpp @@ -1,4 +1,4 @@ #define BOOST_CONTRACT_CONFIG_PERMISSIVE -#include "inv_volatile.i" +#include "inv_volatile.hpp" diff --git a/test/invariant/no_inv.cpp b/test/invariant/no_inv.cpp index 8359a9d..433acf7 100644 --- a/test/invariant/no_inv.cpp +++ b/test/invariant/no_inv.cpp @@ -4,5 +4,5 @@ #undef BOOST_CONTRACT_AUX_TEST_STATIC_INV #undef BOOST_CONTRACT_AUX_TEST_CV_INV #undef BOOST_CONTRACT_AUX_TEST_CONST_INV -#include "combinations.i" +#include "combinations.hpp" diff --git a/test/invariant/only_const.cpp b/test/invariant/only_const.cpp index 62c4144..a708b94 100644 --- a/test/invariant/only_const.cpp +++ b/test/invariant/only_const.cpp @@ -4,5 +4,5 @@ #undef BOOST_CONTRACT_AUX_TEST_STATIC_INV #undef BOOST_CONTRACT_AUX_TEST_CV_INV #define BOOST_CONTRACT_AUX_TEST_CONST_INV -#include "combinations.i" +#include "combinations.hpp" diff --git a/test/invariant/only_cv.cpp b/test/invariant/only_cv.cpp index 5b5b41d..6ca2f7c 100644 --- a/test/invariant/only_cv.cpp +++ b/test/invariant/only_cv.cpp @@ -4,5 +4,5 @@ #undef BOOST_CONTRACT_AUX_TEST_STATIC_INV #define BOOST_CONTRACT_AUX_TEST_CV_INV #undef BOOST_CONTRACT_AUX_TEST_CONST_INV -#include "combinations.i" +#include "combinations.hpp" diff --git a/test/invariant/only_static.cpp b/test/invariant/only_static.cpp index 0e6b319..7862e5b 100644 --- a/test/invariant/only_static.cpp +++ b/test/invariant/only_static.cpp @@ -4,5 +4,5 @@ #define BOOST_CONTRACT_AUX_TEST_STATIC_INV #undef BOOST_CONTRACT_AUX_TEST_CV_INV #undef BOOST_CONTRACT_AUX_TEST_CONST_INV -#include "combinations.i" +#include "combinations.hpp" diff --git a/test/invariant/static_inv_const.i b/test/invariant/static_inv_const.hpp similarity index 95% rename from test/invariant/static_inv_const.i rename to test/invariant/static_inv_const.hpp index 6611d5d..a036f29 100644 --- a/test/invariant/static_inv_const.i +++ b/test/invariant/static_inv_const.hpp @@ -1,4 +1,6 @@ +// no #include guard + // Test error if static inv declared const (unless PERMISSIVE #defined). #include diff --git a/test/invariant/static_inv_const_error.cpp b/test/invariant/static_inv_const_error.cpp index 523bca5..930d8c1 100644 --- a/test/invariant/static_inv_const_error.cpp +++ b/test/invariant/static_inv_const_error.cpp @@ -1,3 +1,3 @@ -#include "static_inv_const.i" +#include "static_inv_const.hpp" diff --git a/test/invariant/static_inv_const_permissive.cpp b/test/invariant/static_inv_const_permissive.cpp index a4631bd..78dc7b9 100644 --- a/test/invariant/static_inv_const_permissive.cpp +++ b/test/invariant/static_inv_const_permissive.cpp @@ -1,4 +1,4 @@ #define BOOST_CONTRACT_CONFIG_PERMISSIVE -#include "static_inv_const.i" +#include "static_inv_const.hpp" diff --git a/test/invariant/static_inv_cv.i b/test/invariant/static_inv_cv.hpp similarity index 100% rename from test/invariant/static_inv_cv.i rename to test/invariant/static_inv_cv.hpp diff --git a/test/invariant/static_inv_cv_error.cpp b/test/invariant/static_inv_cv_error.cpp index 960a8e7..acdd7a0 100644 --- a/test/invariant/static_inv_cv_error.cpp +++ b/test/invariant/static_inv_cv_error.cpp @@ -1,3 +1,3 @@ -#include "static_inv_cv.i" +#include "static_inv_cv.hpp" diff --git a/test/invariant/static_inv_cv_permissive.cpp b/test/invariant/static_inv_cv_permissive.cpp index 1460f32..eefbf81 100644 --- a/test/invariant/static_inv_cv_permissive.cpp +++ b/test/invariant/static_inv_cv_permissive.cpp @@ -1,4 +1,4 @@ #define BOOST_CONTRACT_CONFIG_PERMISSIVE -#include "static_inv_cv.i" +#include "static_inv_cv.hpp" diff --git a/test/invariant/static_inv_mutable.i b/test/invariant/static_inv_mutable.hpp similarity index 100% rename from test/invariant/static_inv_mutable.i rename to test/invariant/static_inv_mutable.hpp diff --git a/test/invariant/static_inv_mutable_error.cpp b/test/invariant/static_inv_mutable_error.cpp index fe90b2e..496604b 100644 --- a/test/invariant/static_inv_mutable_error.cpp +++ b/test/invariant/static_inv_mutable_error.cpp @@ -1,3 +1,3 @@ -#include "static_inv_mutable.i" +#include "static_inv_mutable.hpp" diff --git a/test/invariant/static_inv_mutable_permissive.cpp b/test/invariant/static_inv_mutable_permissive.cpp index 46bd297..afc4dc6 100644 --- a/test/invariant/static_inv_mutable_permissive.cpp +++ b/test/invariant/static_inv_mutable_permissive.cpp @@ -1,4 +1,4 @@ #define BOOST_CONTRACT_CONFIG_PERMISSIVE -#include "static_inv_mutable.i" +#include "static_inv_mutable.hpp" diff --git a/test/invariant/static_inv_volatile.i b/test/invariant/static_inv_volatile.hpp similarity index 100% rename from test/invariant/static_inv_volatile.i rename to test/invariant/static_inv_volatile.hpp diff --git a/test/invariant/static_inv_volatile_error.cpp b/test/invariant/static_inv_volatile_error.cpp index 33ed96d..bd8a350 100644 --- a/test/invariant/static_inv_volatile_error.cpp +++ b/test/invariant/static_inv_volatile_error.cpp @@ -1,3 +1,3 @@ -#include "static_inv_volatile.i" +#include "static_inv_volatile.hpp" diff --git a/test/invariant/static_inv_volatile_permissive.cpp b/test/invariant/static_inv_volatile_permissive.cpp index 9806ffd..0af4bac 100644 --- a/test/invariant/static_inv_volatile_permissive.cpp +++ b/test/invariant/static_inv_volatile_permissive.cpp @@ -1,4 +1,4 @@ #define BOOST_CONTRACT_CONFIG_PERMISSIVE -#include "static_inv_volatile.i" +#include "static_inv_volatile.hpp" diff --git a/test/public_function/bases_pre.cpp b/test/public_function/bases_pre.cpp deleted file mode 100644 index 7ec6f2d..0000000 --- a/test/public_function/bases_pre.cpp +++ /dev/null @@ -1,59 +0,0 @@ - -// Test overriding func has no pre (but overridden pre still checked). - -#include "../aux_/oteststream.hpp" -#include -#include -#include -#include -#include -#include -#include - -boost::contract::aux::test::oteststream out; - -struct b { - static void static_invariant() { out << "b::static_inv" << std::endl; } - void invariant() const { out << "b::inv" << std::endl; } - - virtual void f(char ch, boost::contract::virtual_* v = 0) { - boost::contract::guard c = boost::contract::public_function(v, this) - .precondition([&] { - out << "b::pre" << std::endl; - BOOST_CONTRACT_ASSERT(ch == 'b'); - }) - .old([] { out << "a::f::old" << std::endl; }) - .postcondition([] { out << "a::f::post" << std::endl; }) - ; - out << "a::f::body" << std::endl; - } -}; - -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 void f(char ch, boost::contract::virtual_* v = 0) /* override */ { - boost::contract::guard c = boost::contract::public_function( - v, &a::f, this, ch) - // Test no .precondition(...) here. - .old([] { out << "a::f::old" << std::endl; }) - .postcondition([] { out << "a::f::post" << std::endl; }) - ; - out << "a::f::body" << std::endl; - } - BOOST_CONTRACT_OVERRIDE(f) -}; - -int main() { - a aa; - aa.f('a'); - return boost::report_errors(); -} - diff --git a/test/public_function/decl.hpp b/test/public_function/decl.hpp new file mode 100644 index 0000000..ca1f744 --- /dev/null +++ b/test/public_function/decl.hpp @@ -0,0 +1,157 @@ + +#ifndef BOOST_CONTRACT_TEST_PUBLIC_FUNCTION_DECL_HPP_ +#define BOOST_CONTRACT_TEST_PUBLIC_FUNCTION_DECL_HPP_ + +// Test with and without pre, post, and inv declarations. + +#include "../aux_/oteststream.hpp" +#include +#include +#include +#include +#include + +boost::contract::aux::test::oteststream out; + +bool c_pre = true, c_post = true; +bool c_entering_static_inv = true, c_entry_static_inv = true, + c_exit_static_inv = true; +bool c_entering_inv = true, c_entry_inv = true, c_exit_inv = true; +struct c { +#ifndef BOOST_CONTRACT_AUX_TEST_NO_C_STATIC_INV + static void static_invariant() { + out << "c::static_inv" << std::endl; + if(c_entering_static_inv) BOOST_CONTRACT_ASSERT(c_entry_static_inv); + else BOOST_CONTRACT_ASSERT(c_exit_static_inv); + c_entering_static_inv = false; + } +#endif +#ifndef BOOST_CONTRACT_AUX_TEST_NO_C_INV + void invariant() const { + out << "c::inv" << std::endl; + if(c_entering_inv) BOOST_CONTRACT_ASSERT(c_entry_inv); + else BOOST_CONTRACT_ASSERT(c_exit_inv); + c_entering_inv = false; + } +#endif + + virtual void f(boost::contract::virtual_* v = 0) { + boost::contract::guard c = boost::contract::public_function(v, this) +#ifndef BOOST_CONTRACT_AUX_TEST_NO_C_PRE + .precondition([&] { + out << "c::f::pre" << std::endl; + BOOST_CONTRACT_ASSERT(c_pre); + }) +#endif + .old([] { out << "c::f::old" << std::endl; }) +#ifndef BOOST_CONTRACT_AUX_TEST_NO_C_POST + .postcondition([] { + out << "c::f::post" << std::endl; + BOOST_CONTRACT_ASSERT(c_post); + }) +#endif + ; + out << "c::f::body" << std::endl; + } +}; + +bool b_pre = true, b_post = true; +bool b_entering_static_inv = true, b_entry_static_inv = true, + b_exit_static_inv = true; +bool b_entering_inv = true, b_entry_inv = true, b_exit_inv = true; +struct b + #define BASES public c + : BASES +{ + typedef BOOST_CONTRACT_BASE_TYPES(BASES) base_types; + #undef BASES + +#ifndef BOOST_CONTRACT_AUX_TEST_NO_B_STATIC_INV + static void static_invariant() { + out << "b::static_inv" << std::endl; + if(b_entering_static_inv) BOOST_CONTRACT_ASSERT(b_entry_static_inv); + else BOOST_CONTRACT_ASSERT(b_exit_static_inv); + b_entering_static_inv = false; + } +#endif +#ifndef BOOST_CONTRACT_AUX_TEST_NO_B_INV + void invariant() const { + out << "b::inv" << std::endl; + if(b_entering_inv) BOOST_CONTRACT_ASSERT(b_entry_inv); + else BOOST_CONTRACT_ASSERT(b_exit_inv); + b_entering_inv = false; + } +#endif + + virtual void f(boost::contract::virtual_* v = 0) { + boost::contract::guard c = boost::contract::public_function(v, this) +#ifndef BOOST_CONTRACT_AUX_TEST_NO_B_PRE + .precondition([&] { + out << "b::f::pre" << std::endl; + BOOST_CONTRACT_ASSERT(b_pre); + }) +#endif + .old([] { out << "b::f::old" << std::endl; }) +#ifndef BOOST_CONTRACT_AUX_TEST_NO_B_POST + .postcondition([] { + out << "b::f::post" << std::endl; + BOOST_CONTRACT_ASSERT(b_post); + }) +#endif + ; + out << "a::f::body" << std::endl; + } +}; + +bool a_pre = true, a_post = true; +bool a_entering_static_inv = true, a_entry_static_inv = true, + a_exit_static_inv = true; +bool a_entering_inv = true, a_entry_inv = true, a_exit_inv = true; +struct a + #define BASES public b + : BASES +{ + typedef BOOST_CONTRACT_BASE_TYPES(BASES) base_types; + #undef BASES + +#ifndef BOOST_CONTRACT_AUX_TEST_NO_A_STATIC_INV + static void static_invariant() { + out << "a::static_inv" << std::endl; + if(a_entering_static_inv) BOOST_CONTRACT_ASSERT(a_entry_static_inv); + else BOOST_CONTRACT_ASSERT(a_exit_static_inv); + a_entering_static_inv = false; + } +#endif +#ifndef BOOST_CONTRACT_AUX_TEST_NO_A_INV + void invariant() const { + out << "a::inv" << std::endl; + if(a_entering_inv) BOOST_CONTRACT_ASSERT(a_entry_inv); + else BOOST_CONTRACT_ASSERT(a_exit_inv); + a_entering_inv = false; + } +#endif + + virtual void f(boost::contract::virtual_* v = 0) /* override */ { + boost::contract::guard c = boost::contract::public_function( + v, &a::f, this) +#ifndef BOOST_CONTRACT_AUX_TEST_NO_A_PRE + .precondition([&] { + out << "a::f::pre" << std::endl; + BOOST_CONTRACT_ASSERT(a_pre); + }) +#endif + .old([] { out << "a::f::old" << std::endl; }) +#ifndef BOOST_CONTRACT_AUX_TEST_NO_A_POST + .postcondition([] { + out << "a::f::post" << std::endl; + BOOST_CONTRACT_ASSERT(a_post); + }) +#endif + ; + out << "a::f::body" << std::endl; + } + BOOST_CONTRACT_OVERRIDE(f) +}; + +#endif // #include guard + diff --git a/test/public_function/decl_entry_inv_all.cpp b/test/public_function/decl_entry_inv_all.cpp new file mode 100644 index 0000000..e342326 --- /dev/null +++ b/test/public_function/decl_entry_inv_all.cpp @@ -0,0 +1,94 @@ + +// Test derived and base classes all with entry invariants. + +#undef BOOST_CONTRACT_AUX_TEST_NO_A_INV +#undef BOOST_CONTRACT_AUX_TEST_NO_B_INV +#undef BOOST_CONTRACT_AUX_TEST_NO_C_INV +#include "./decl.hpp" + +#include "../aux_/oteststream.hpp" +#include +#include + +int main() { + std::ostringstream ok; + + struct err {}; + boost::contract::set_entry_invariant_failed( + [] (boost::contract::from) { throw err(); }); + + a aa; + + a_entry_inv = false; + b_entry_inv = true; + c_entry_inv = true; + out.str(""); + try { + a_entering_inv = b_entering_inv = c_entering_inv = true; + aa.f(); + BOOST_TEST(false); + } catch(err const&) { + ok.str(""); ok + << "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 // Test this failed. + ; + BOOST_TEST(out.eq(ok.str())); + } catch(...) { BOOST_TEST(false); } + + a_entry_inv = true; + b_entry_inv = false; + c_entry_inv = true; + out.str(""); + try { + a_entering_inv = b_entering_inv = c_entering_inv = true; + aa.f(); + BOOST_TEST(false); + } catch(err const&) { + ok.str(""); ok + << "c::static_inv" << std::endl + << "c::inv" << std::endl + << "b::static_inv" << std::endl + << "b::inv" << std::endl // Test this failed. + ; + BOOST_TEST(out.eq(ok.str())); + } catch(...) { BOOST_TEST(false); } + + a_entry_inv = true; + b_entry_inv = true; + c_entry_inv = false; + out.str(""); + try { + a_entering_inv = b_entering_inv = c_entering_inv = true; + aa.f(); + BOOST_TEST(false); + } catch(err const&) { + ok.str(""); ok + << "c::static_inv" << std::endl + << "c::inv" << std::endl // Test this failed. + ; + BOOST_TEST(out.eq(ok.str())); + } catch(...) { BOOST_TEST(false); } + + a_entry_inv = false; + b_entry_inv = false; + c_entry_inv = false; + out.str(""); + try { + a_entering_inv = b_entering_inv = c_entering_inv = true; + aa.f(); + BOOST_TEST(false); + } catch(err const&) { + ok.str(""); ok + << "c::static_inv" << std::endl + << "c::inv" << std::endl // Test this failed (as all did). + ; + BOOST_TEST(out.eq(ok.str())); + } catch(...) { BOOST_TEST(false); } + + return boost::report_errors(); +} + diff --git a/test/public_function/decl_entry_inv_middle.cpp b/test/public_function/decl_entry_inv_middle.cpp new file mode 100644 index 0000000..05ab805 --- /dev/null +++ b/test/public_function/decl_entry_inv_middle.cpp @@ -0,0 +1,128 @@ + +// Test only middle base class has entry invariants. + +#define BOOST_CONTRACT_AUX_TEST_NO_A_INV +#undef BOOST_CONTRACT_AUX_TEST_NO_B_INV +#define BOOST_CONTRACT_AUX_TEST_NO_C_INV +#include "./decl.hpp" + +#include "../aux_/oteststream.hpp" +#include +#include + +int main() { + std::ostringstream ok; + + struct err {}; + boost::contract::set_entry_invariant_failed( + [] (boost::contract::from) { throw err(); }); + + a aa; + + a_entry_inv = false; + b_entry_inv = true; + c_entry_inv = true; + out.str(""); + try { + a_entering_inv = b_entering_inv = c_entering_inv = true; + aa.f(); + ok.str(""); ok + << "c::static_inv" << std::endl + << "b::static_inv" << std::endl + << "b::inv" << std::endl + << "a::static_inv" << std::endl + + << "c::f::pre" << std::endl + + << "c::f::old" << std::endl + << "b::f::old" << std::endl + << "a::f::old" << std::endl + + << "a::f::body" << std::endl + + << "c::static_inv" << std::endl + << "b::static_inv" << std::endl + << "b::inv" << std::endl + << "a::static_inv" << 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 + ; + BOOST_TEST(out.eq(ok.str())); + } catch(...) { BOOST_TEST(false); } + + a_entry_inv = true; + b_entry_inv = false; + c_entry_inv = true; + out.str(""); + try { + a_entering_inv = b_entering_inv = c_entering_inv = true; + aa.f(); + BOOST_TEST(false); + } catch(err const&) { + ok.str(""); ok + << "c::static_inv" << std::endl + << "b::static_inv" << std::endl + << "b::inv" << std::endl // Test this fail. + ; + BOOST_TEST(out.eq(ok.str())); + } catch(...) { BOOST_TEST(false); } + + a_entry_inv = true; + b_entry_inv = true; + c_entry_inv = false; + out.str(""); + try { + a_entering_inv = b_entering_inv = c_entering_inv = true; + aa.f(); + ok.str(""); ok + << "c::static_inv" << std::endl + << "b::static_inv" << std::endl + << "b::inv" << std::endl + << "a::static_inv" << std::endl + + << "c::f::pre" << std::endl + + << "c::f::old" << std::endl + << "b::f::old" << std::endl + << "a::f::old" << std::endl + + << "a::f::body" << std::endl + + << "c::static_inv" << std::endl + << "b::static_inv" << std::endl + << "b::inv" << std::endl + << "a::static_inv" << 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 + ; + BOOST_TEST(out.eq(ok.str())); + } catch(...) { BOOST_TEST(false); } + + a_entry_inv = false; + b_entry_inv = false; + c_entry_inv = false; + out.str(""); + try { + a_entering_inv = b_entering_inv = c_entering_inv = true; + aa.f(); + BOOST_TEST(false); + } catch(err const&) { + ok.str(""); ok + << "c::static_inv" << std::endl + << "b::static_inv" << std::endl + << "b::inv" << std::endl // Test this failed (as all did). + ; + BOOST_TEST(out.eq(ok.str())); + } catch(...) { BOOST_TEST(false); } + + return boost::report_errors(); +} + diff --git a/test/public_function/decl_entry_inv_none.cpp b/test/public_function/decl_entry_inv_none.cpp new file mode 100644 index 0000000..5a94e0f --- /dev/null +++ b/test/public_function/decl_entry_inv_none.cpp @@ -0,0 +1,80 @@ + +// Test derived and base classes all without entry invariants. + +#define BOOST_CONTRACT_AUX_TEST_NO_A_INV +#define BOOST_CONTRACT_AUX_TEST_NO_B_INV +#define BOOST_CONTRACT_AUX_TEST_NO_C_INV +#include "./decl.hpp" + +#include "../aux_/oteststream.hpp" +#include +#include + +int main() { + std::ostringstream ok; + ok.str(""); ok + // Test no invariants. + << "c::static_inv" << std::endl + << "b::static_inv" << std::endl + << "a::static_inv" << std::endl + + << "c::f::pre" << std::endl + + << "c::f::old" << std::endl + << "b::f::old" << std::endl + << "a::f::old" << std::endl + + << "a::f::body" << std::endl + + << "c::static_inv" << std::endl + << "b::static_inv" << std::endl + << "a::static_inv" << 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 + ; + + struct err {}; + boost::contract::set_entry_invariant_failed( + [] (boost::contract::from) { throw err(); }); + + a aa; + + a_entry_inv = false; + b_entry_inv = true; + c_entry_inv = true; + out.str(""); + a_entering_inv = b_entering_inv = c_entering_inv = true; + aa.f(); + BOOST_TEST(out.eq(ok.str())); + + a_entry_inv = true; + b_entry_inv = false; + c_entry_inv = true; + out.str(""); + a_entering_inv = b_entering_inv = c_entering_inv = true; + aa.f(); + BOOST_TEST(out.eq(ok.str())); + + a_entry_inv = true; + b_entry_inv = true; + c_entry_inv = false; + out.str(""); + a_entering_inv = b_entering_inv = c_entering_inv = true; + aa.f(); + BOOST_TEST(out.eq(ok.str())); + + a_entry_inv = false; + b_entry_inv = false; + c_entry_inv = false; + out.str(""); + a_entering_inv = b_entering_inv = c_entering_inv = true; + aa.f(); + BOOST_TEST(out.eq(ok.str())); + + return boost::report_errors(); +} + diff --git a/test/public_function/decl_entry_inv_sides.cpp b/test/public_function/decl_entry_inv_sides.cpp new file mode 100644 index 0000000..1eb9e1a --- /dev/null +++ b/test/public_function/decl_entry_inv_sides.cpp @@ -0,0 +1,112 @@ + +// Test only derived and grandparent classes (sides) have entry invariants. + +#undef BOOST_CONTRACT_AUX_TEST_NO_A_INV +#define BOOST_CONTRACT_AUX_TEST_NO_B_INV +#undef BOOST_CONTRACT_AUX_TEST_NO_C_INV +#include "./decl.hpp" + +#include "../aux_/oteststream.hpp" +#include +#include + +int main() { + std::ostringstream ok; + + struct err {}; + boost::contract::set_entry_invariant_failed( + [] (boost::contract::from) { throw err(); }); + + a aa; + + a_entry_inv = false; + b_entry_inv = true; + c_entry_inv = true; + out.str(""); + try { + a_entering_inv = b_entering_inv = c_entering_inv = true; + aa.f(); + BOOST_TEST(false); + } catch(err const&) { + ok.str(""); ok + << "c::static_inv" << std::endl + << "c::inv" << std::endl + << "b::static_inv" << std::endl + << "a::static_inv" << std::endl + << "a::inv" << std::endl // Test this failed. + ; + BOOST_TEST(out.eq(ok.str())); + } catch(...) { BOOST_TEST(false); } + + a_entry_inv = true; + b_entry_inv = false; + c_entry_inv = true; + out.str(""); + try { + a_entering_inv = b_entering_inv = c_entering_inv = true; + aa.f(); + ok.str(""); ok + << "c::static_inv" << std::endl + << "c::inv" << std::endl + << "b::static_inv" << std::endl + << "a::static_inv" << std::endl + << "a::inv" << std::endl + + << "c::f::pre" << std::endl + + << "c::f::old" << std::endl + << "b::f::old" << std::endl + << "a::f::old" << std::endl + + << "a::f::body" << std::endl + + << "c::static_inv" << std::endl + << "c::inv" << std::endl + << "b::static_inv" << std::endl + << "a::static_inv" << std::endl + << "a::inv" << 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 + ; + BOOST_TEST(out.eq(ok.str())); + } catch(...) { BOOST_TEST(false); } + + a_entry_inv = true; + b_entry_inv = true; + c_entry_inv = false; + out.str(""); + try { + a_entering_inv = b_entering_inv = c_entering_inv = true; + aa.f(); + BOOST_TEST(false); + } catch(err const&) { + ok.str(""); ok + << "c::static_inv" << std::endl + << "c::inv" << std::endl // Test this failed. + ; + BOOST_TEST(out.eq(ok.str())); + } catch(...) { BOOST_TEST(false); } + + a_entry_inv = false; + b_entry_inv = false; + c_entry_inv = false; + out.str(""); + try { + a_entering_inv = b_entering_inv = c_entering_inv = true; + aa.f(); + BOOST_TEST(false); + } catch(err const&) { + ok.str(""); ok + << "c::static_inv" << std::endl + << "c::inv" << std::endl // Test this failed (as all did). + ; + BOOST_TEST(out.eq(ok.str())); + } catch(...) { BOOST_TEST(false); } + + return boost::report_errors(); +} + diff --git a/test/public_function/decl_entry_static_inv_all.cpp b/test/public_function/decl_entry_static_inv_all.cpp new file mode 100644 index 0000000..854be13 --- /dev/null +++ b/test/public_function/decl_entry_static_inv_all.cpp @@ -0,0 +1,94 @@ + +// Test derived and base classes all with entry static invariants. + +#undef BOOST_CONTRACT_AUX_TEST_NO_A_STATIC_INV +#undef BOOST_CONTRACT_AUX_TEST_NO_B_STATIC_INV +#undef BOOST_CONTRACT_AUX_TEST_NO_C_STATIC_INV +#include "./decl.hpp" + +#include "../aux_/oteststream.hpp" +#include +#include + +int main() { + std::ostringstream ok; + + struct err {}; + boost::contract::set_entry_invariant_failed( + [] (boost::contract::from) { throw err(); }); + + a aa; + + a_entry_static_inv = false; + b_entry_static_inv = true; + c_entry_static_inv = true; + out.str(""); + try { + a_entering_static_inv = b_entering_static_inv = c_entering_static_inv = + true; + aa.f(); + BOOST_TEST(false); + } catch(err const&) { + ok.str(""); ok + << "c::static_inv" << std::endl + << "c::inv" << std::endl + << "b::static_inv" << std::endl + << "b::inv" << std::endl + << "a::static_inv" << std::endl // Test this failed. + ; + BOOST_TEST(out.eq(ok.str())); + } catch(...) { BOOST_TEST(false); } + + a_entry_static_inv = true; + b_entry_static_inv = false; + c_entry_static_inv = true; + out.str(""); + try { + a_entering_static_inv = b_entering_static_inv = c_entering_static_inv = + true; + aa.f(); + BOOST_TEST(false); + } catch(err const&) { + ok.str(""); ok + << "c::static_inv" << std::endl + << "c::inv" << std::endl + << "b::static_inv" << std::endl // Test this failed. + ; + BOOST_TEST(out.eq(ok.str())); + } catch(...) { BOOST_TEST(false); } + + a_entry_static_inv = true; + b_entry_static_inv = true; + c_entry_static_inv = false; + out.str(""); + try { + a_entering_static_inv = b_entering_static_inv = c_entering_static_inv = + true; + aa.f(); + BOOST_TEST(false); + } catch(err const&) { + ok.str(""); ok + << "c::static_inv" << std::endl // Test this failed. + ; + BOOST_TEST(out.eq(ok.str())); + } catch(...) { BOOST_TEST(false); } + + a_entry_static_inv = false; + b_entry_static_inv = false; + c_entry_static_inv = false; + out.str(""); + try { + a_entering_static_inv = b_entering_static_inv = c_entering_static_inv = + true; + aa.f(); + BOOST_TEST(false); + } catch(err const&) { + ok.str(""); ok + << "c::static_inv" << std::endl // Test this failed (as all did). + ; + BOOST_TEST(out.eq(ok.str())); + } catch(...) { BOOST_TEST(false); } + + return boost::report_errors(); +} + diff --git a/test/public_function/decl_entry_static_inv_middle.cpp b/test/public_function/decl_entry_static_inv_middle.cpp new file mode 100644 index 0000000..1023143 --- /dev/null +++ b/test/public_function/decl_entry_static_inv_middle.cpp @@ -0,0 +1,130 @@ + +// Test only middle base class has entry static invariants. + +#define BOOST_CONTRACT_AUX_TEST_NO_A_STATIC_INV +#undef BOOST_CONTRACT_AUX_TEST_NO_B_STATIC_INV +#define BOOST_CONTRACT_AUX_TEST_NO_C_STATIC_INV +#include "./decl.hpp" + +#include "../aux_/oteststream.hpp" +#include +#include + +int main() { + std::ostringstream ok; + + struct err {}; + boost::contract::set_entry_invariant_failed( + [] (boost::contract::from) { throw err(); }); + + a aa; + + a_entry_static_inv = false; + b_entry_static_inv = true; + c_entry_static_inv = true; + out.str(""); + try { + a_entering_static_inv = b_entering_static_inv = c_entering_static_inv = + true; + aa.f(); + ok.str(""); ok + << "c::inv" << std::endl + << "b::static_inv" << std::endl + << "b::inv" << std::endl + << "a::inv" << std::endl + + << "c::f::pre" << std::endl + + << "c::f::old" << std::endl + << "b::f::old" << std::endl + << "a::f::old" << std::endl + + << "a::f::body" << std::endl + + << "c::inv" << std::endl + << "b::static_inv" << std::endl + << "b::inv" << std::endl + << "a::inv" << 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 + ; + BOOST_TEST(out.eq(ok.str())); + } catch(...) { BOOST_TEST(false); } + + a_entry_static_inv = true; + b_entry_static_inv = false; + c_entry_static_inv = true; + out.str(""); + try { + a_entering_static_inv = b_entering_static_inv = c_entering_static_inv = + true; + aa.f(); + BOOST_TEST(false); + } catch(err const&) { + ok.str(""); ok + << "c::inv" << std::endl + << "b::static_inv" << std::endl // Test this fail. + ; + BOOST_TEST(out.eq(ok.str())); + } catch(...) { BOOST_TEST(false); } + + a_entry_static_inv = true; + b_entry_static_inv = true; + c_entry_static_inv = false; + out.str(""); + try { + a_entering_static_inv = b_entering_static_inv = c_entering_static_inv = + true; + aa.f(); + ok.str(""); ok + << "c::inv" << std::endl + << "b::static_inv" << std::endl + << "b::inv" << std::endl + << "a::inv" << std::endl + + << "c::f::pre" << std::endl + + << "c::f::old" << std::endl + << "b::f::old" << std::endl + << "a::f::old" << std::endl + + << "a::f::body" << std::endl + + << "c::inv" << std::endl + << "b::static_inv" << std::endl + << "b::inv" << std::endl + << "a::inv" << 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 + ; + BOOST_TEST(out.eq(ok.str())); + } catch(...) { BOOST_TEST(false); } + + a_entry_static_inv = false; + b_entry_static_inv = false; + c_entry_static_inv = false; + out.str(""); + try { + a_entering_static_inv = b_entering_static_inv = c_entering_static_inv = + true; + aa.f(); + BOOST_TEST(false); + } catch(err const&) { + ok.str(""); ok + << "c::inv" << std::endl + << "b::static_inv" << std::endl // Test this failed (as all did). + ; + BOOST_TEST(out.eq(ok.str())); + } catch(...) { BOOST_TEST(false); } + + return boost::report_errors(); +} + diff --git a/test/public_function/decl_entry_static_inv_none.cpp b/test/public_function/decl_entry_static_inv_none.cpp new file mode 100644 index 0000000..23a282f --- /dev/null +++ b/test/public_function/decl_entry_static_inv_none.cpp @@ -0,0 +1,79 @@ + +// Test derived and base classes all without entry static invariants. + +#define BOOST_CONTRACT_AUX_TEST_NO_A_STATIC_INV +#define BOOST_CONTRACT_AUX_TEST_NO_B_STATIC_INV +#define BOOST_CONTRACT_AUX_TEST_NO_C_STATIC_INV +#include "./decl.hpp" + +#include "../aux_/oteststream.hpp" +#include +#include + +int main() { + std::ostringstream ok; ok + // Test no static invariants. + << "c::inv" << std::endl + << "b::inv" << std::endl + << "a::inv" << std::endl + + << "c::f::pre" << std::endl + + << "c::f::old" << std::endl + << "b::f::old" << std::endl + << "a::f::old" << std::endl + + << "a::f::body" << std::endl + + << "c::inv" << std::endl + << "b::inv" << std::endl + << "a::inv" << 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 + ; + + a aa; + + a_entry_static_inv = false; + b_entry_static_inv = true; + c_entry_static_inv = true; + out.str(""); + a_entering_static_inv = b_entering_static_inv = c_entering_static_inv = + true; + aa.f(); + BOOST_TEST(out.eq(ok.str())); + + a_entry_static_inv = true; + b_entry_static_inv = false; + c_entry_static_inv = true; + out.str(""); + a_entering_static_inv = b_entering_static_inv = c_entering_static_inv = + true; + aa.f(); + BOOST_TEST(out.eq(ok.str())); + + a_entry_static_inv = true; + b_entry_static_inv = true; + c_entry_static_inv = false; + out.str(""); + a_entering_static_inv = b_entering_static_inv = c_entering_static_inv = + true; + aa.f(); + BOOST_TEST(out.eq(ok.str())); + + a_entry_static_inv = false; + b_entry_static_inv = false; + c_entry_static_inv = false; + out.str(""); + a_entering_static_inv = b_entering_static_inv = c_entering_static_inv = + true; + aa.f(); + BOOST_TEST(out.eq(ok.str())); + + return boost::report_errors(); +} + diff --git a/test/public_function/decl_entry_static_inv_sides.cpp b/test/public_function/decl_entry_static_inv_sides.cpp new file mode 100644 index 0000000..72260c5 --- /dev/null +++ b/test/public_function/decl_entry_static_inv_sides.cpp @@ -0,0 +1,113 @@ + +// Test only derived and grandparent classes (sides) have entry static inv. + +#undef BOOST_CONTRACT_AUX_TEST_NO_A_STATIC_INV +#define BOOST_CONTRACT_AUX_TEST_NO_B_STATIC_INV +#undef BOOST_CONTRACT_AUX_TEST_NO_C_STATIC_INV +#include "./decl.hpp" + +#include "../aux_/oteststream.hpp" +#include +#include + +int main() { + std::ostringstream ok; + + struct err {}; + boost::contract::set_entry_invariant_failed( + [] (boost::contract::from) { throw err(); }); + + a aa; + + a_entry_static_inv = false; + b_entry_static_inv = true; + c_entry_static_inv = true; + out.str(""); + try { + a_entering_static_inv = b_entering_static_inv = c_entering_static_inv = + true; + aa.f(); + BOOST_TEST(false); + } catch(err const&) { + ok.str(""); ok + << "c::static_inv" << std::endl + << "c::inv" << std::endl + << "b::inv" << std::endl + << "a::static_inv" << std::endl // Test this failed. + ; + BOOST_TEST(out.eq(ok.str())); + } catch(...) { BOOST_TEST(false); } + + a_entry_static_inv = true; + b_entry_static_inv = false; + c_entry_static_inv = true; + out.str(""); + try { + a_entering_static_inv = b_entering_static_inv = c_entering_static_inv = + true; + aa.f(); + ok.str(""); ok + << "c::static_inv" << std::endl + << "c::inv" << std::endl + << "b::inv" << std::endl + << "a::static_inv" << std::endl + << "a::inv" << std::endl + + << "c::f::pre" << std::endl + + << "c::f::old" << std::endl + << "b::f::old" << std::endl + << "a::f::old" << std::endl + + << "a::f::body" << std::endl + + << "c::static_inv" << std::endl + << "c::inv" << std::endl + << "b::inv" << std::endl + << "a::static_inv" << std::endl + << "a::inv" << 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 + ; + BOOST_TEST(out.eq(ok.str())); + } catch(...) { BOOST_TEST(false); } + + a_entry_static_inv = true; + b_entry_static_inv = true; + c_entry_static_inv = false; + out.str(""); + try { + a_entering_static_inv = b_entering_static_inv = c_entering_static_inv = + true; + aa.f(); + BOOST_TEST(false); + } catch(err const&) { + ok.str(""); ok + << "c::static_inv" << std::endl // Test this failed. + ; + BOOST_TEST(out.eq(ok.str())); + } catch(...) { BOOST_TEST(false); } + + a_entry_static_inv = false; + b_entry_static_inv = false; + c_entry_static_inv = false; + out.str(""); + try { + a_entering_static_inv = b_entering_static_inv = c_entering_static_inv = + true; + aa.f(); + BOOST_TEST(false); + } catch(err const&) { + ok.str(""); ok + << "c::static_inv" << std::endl // Test this failed (as all did). + ; + BOOST_TEST(out.eq(ok.str())); + } catch(...) { BOOST_TEST(false); } + + return boost::report_errors(); +} + diff --git a/test/public_function/decl_exit_inv_all.cpp b/test/public_function/decl_exit_inv_all.cpp new file mode 100644 index 0000000..57defb6 --- /dev/null +++ b/test/public_function/decl_exit_inv_all.cpp @@ -0,0 +1,154 @@ + +// Test derived and base classes all with exit invariants. + +#undef BOOST_CONTRACT_AUX_TEST_NO_A_INV +#undef BOOST_CONTRACT_AUX_TEST_NO_B_INV +#undef BOOST_CONTRACT_AUX_TEST_NO_C_INV +#include "./decl.hpp" + +#include "../aux_/oteststream.hpp" +#include +#include + +int main() { + std::ostringstream ok; + + struct err {}; + boost::contract::set_exit_invariant_failed( + [] (boost::contract::from) { throw err(); }); + + a aa; + + a_exit_inv = false; + b_exit_inv = true; + c_exit_inv = true; + out.str(""); + try { + a_entering_inv = b_entering_inv = c_entering_inv = true; + aa.f(); + BOOST_TEST(false); + } catch(err const&) { + ok.str(""); ok + << "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 + + << "c::f::pre" << std::endl + + << "c::f::old" << std::endl + << "b::f::old" << std::endl + << "a::f::old" << std::endl + + << "a::f::body" << 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 // Test this failed. + ; + BOOST_TEST(out.eq(ok.str())); + } catch(...) { BOOST_TEST(false); } + + a_exit_inv = true; + b_exit_inv = false; + c_exit_inv = true; + out.str(""); + try { + a_entering_inv = b_entering_inv = c_entering_inv = true; + aa.f(); + BOOST_TEST(false); + } catch(err const&) { + ok.str(""); ok + << "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 + + << "c::f::pre" << std::endl + + << "c::f::old" << std::endl + << "b::f::old" << std::endl + << "a::f::old" << std::endl + + << "a::f::body" << std::endl + + << "c::static_inv" << std::endl + << "c::inv" << std::endl + << "b::static_inv" << std::endl + << "b::inv" << std::endl // Test this failed. + ; + BOOST_TEST(out.eq(ok.str())); + } catch(...) { BOOST_TEST(false); } + + a_exit_inv = true; + b_exit_inv = true; + c_exit_inv = false; + out.str(""); + try { + a_entering_inv = b_entering_inv = c_entering_inv = true; + aa.f(); + BOOST_TEST(false); + } catch(err const&) { + ok.str(""); ok + << "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 + + << "c::f::pre" << std::endl + + << "c::f::old" << std::endl + << "b::f::old" << std::endl + << "a::f::old" << std::endl + + << "a::f::body" << std::endl + + << "c::static_inv" << std::endl + << "c::inv" << std::endl // Test this failed. + ; + BOOST_TEST(out.eq(ok.str())); + } catch(...) { BOOST_TEST(false); } + + a_exit_inv = false; + b_exit_inv = false; + c_exit_inv = false; + out.str(""); + try { + a_entering_inv = b_entering_inv = c_entering_inv = true; + aa.f(); + BOOST_TEST(false); + } catch(err const&) { + ok.str(""); ok + << "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 + + << "c::f::pre" << std::endl + + << "c::f::old" << std::endl + << "b::f::old" << std::endl + << "a::f::old" << std::endl + + << "a::f::body" << std::endl + + << "c::static_inv" << std::endl + << "c::inv" << std::endl // Test this failed (as all did). + ; + BOOST_TEST(out.eq(ok.str())); + } catch(...) { BOOST_TEST(false); } + + return boost::report_errors(); +} + diff --git a/test/public_function/decl_exit_inv_middle.cpp b/test/public_function/decl_exit_inv_middle.cpp new file mode 100644 index 0000000..1404177 --- /dev/null +++ b/test/public_function/decl_exit_inv_middle.cpp @@ -0,0 +1,154 @@ + +// Test only middle base class has exit invariants. + +#define BOOST_CONTRACT_AUX_TEST_NO_A_INV +#undef BOOST_CONTRACT_AUX_TEST_NO_B_INV +#define BOOST_CONTRACT_AUX_TEST_NO_C_INV +#include "./decl.hpp" + +#include "../aux_/oteststream.hpp" +#include +#include + +int main() { + std::ostringstream ok; + + struct err {}; + boost::contract::set_exit_invariant_failed( + [] (boost::contract::from) { throw err(); }); + + a aa; + + a_exit_inv = false; + b_exit_inv = true; + c_exit_inv = true; + out.str(""); + try { + a_entering_inv = b_entering_inv = c_entering_inv = true; + aa.f(); + ok.str(""); ok + << "c::static_inv" << std::endl + << "b::static_inv" << std::endl + << "b::inv" << std::endl + << "a::static_inv" << std::endl + + << "c::f::pre" << std::endl + + << "c::f::old" << std::endl + << "b::f::old" << std::endl + << "a::f::old" << std::endl + + << "a::f::body" << std::endl + + << "c::static_inv" << std::endl + << "b::static_inv" << std::endl + << "b::inv" << std::endl + << "a::static_inv" << 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 + ; + BOOST_TEST(out.eq(ok.str())); + } catch(...) { BOOST_TEST(false); } + + a_exit_inv = true; + b_exit_inv = false; + c_exit_inv = true; + out.str(""); + try { + a_entering_inv = b_entering_inv = c_entering_inv = true; + aa.f(); + BOOST_TEST(false); + } catch(err const&) { + ok.str(""); ok + << "c::static_inv" << std::endl + << "b::static_inv" << std::endl + << "b::inv" << std::endl + << "a::static_inv" << std::endl + + << "c::f::pre" << std::endl + + << "c::f::old" << std::endl + << "b::f::old" << std::endl + << "a::f::old" << std::endl + + << "a::f::body" << std::endl + + << "c::static_inv" << std::endl + << "b::static_inv" << std::endl + << "b::inv" << std::endl // Test this failed. + ; + BOOST_TEST(out.eq(ok.str())); + } catch(...) { BOOST_TEST(false); } + + a_exit_inv = true; + b_exit_inv = true; + c_exit_inv = false; + out.str(""); + try { + a_entering_inv = b_entering_inv = c_entering_inv = true; + aa.f(); + ok.str(""); ok + << "c::static_inv" << std::endl + << "b::static_inv" << std::endl + << "b::inv" << std::endl + << "a::static_inv" << std::endl + + << "c::f::pre" << std::endl + + << "c::f::old" << std::endl + << "b::f::old" << std::endl + << "a::f::old" << std::endl + + << "a::f::body" << std::endl + + << "c::static_inv" << std::endl + << "b::static_inv" << std::endl + << "b::inv" << std::endl + << "a::static_inv" << 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 + ; + BOOST_TEST(out.eq(ok.str())); + } catch(...) { BOOST_TEST(false); } + + a_exit_inv = false; + b_exit_inv = false; + c_exit_inv = false; + out.str(""); + try { + a_entering_inv = b_entering_inv = c_entering_inv = true; + aa.f(); + BOOST_TEST(false); + } catch(err const&) { + ok.str(""); ok + << "c::static_inv" << std::endl + << "b::static_inv" << std::endl + << "b::inv" << std::endl + << "a::static_inv" << std::endl + + << "c::f::pre" << std::endl + + << "c::f::old" << std::endl + << "b::f::old" << std::endl + << "a::f::old" << std::endl + + << "a::f::body" << std::endl + + << "c::static_inv" << std::endl + << "b::static_inv" << std::endl + << "b::inv" << std::endl // Test this failed (as all did). + ; + BOOST_TEST(out.eq(ok.str())); + } catch(...) { BOOST_TEST(false); } + + return boost::report_errors(); +} + diff --git a/test/public_function/decl_exit_inv_none.cpp b/test/public_function/decl_exit_inv_none.cpp new file mode 100644 index 0000000..d1c6d30 --- /dev/null +++ b/test/public_function/decl_exit_inv_none.cpp @@ -0,0 +1,80 @@ + +// Test derived and base classes all without exit invariants. + +#define BOOST_CONTRACT_AUX_TEST_NO_A_INV +#define BOOST_CONTRACT_AUX_TEST_NO_B_INV +#define BOOST_CONTRACT_AUX_TEST_NO_C_INV +#include "./decl.hpp" + +#include "../aux_/oteststream.hpp" +#include +#include + +int main() { + std::ostringstream ok; + ok.str(""); ok + // Test no invariants. + << "c::static_inv" << std::endl + << "b::static_inv" << std::endl + << "a::static_inv" << std::endl + + << "c::f::pre" << std::endl + + << "c::f::old" << std::endl + << "b::f::old" << std::endl + << "a::f::old" << std::endl + + << "a::f::body" << std::endl + + << "c::static_inv" << std::endl + << "b::static_inv" << std::endl + << "a::static_inv" << 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 + ; + + struct err {}; + boost::contract::set_exit_invariant_failed( + [] (boost::contract::from) { throw err(); }); + + a aa; + + a_exit_inv = false; + b_exit_inv = true; + c_exit_inv = true; + out.str(""); + a_entering_inv = b_entering_inv = c_entering_inv = true; + aa.f(); + BOOST_TEST(out.eq(ok.str())); + + a_exit_inv = true; + b_exit_inv = false; + c_exit_inv = true; + out.str(""); + a_entering_inv = b_entering_inv = c_entering_inv = true; + aa.f(); + BOOST_TEST(out.eq(ok.str())); + + a_exit_inv = true; + b_exit_inv = true; + c_exit_inv = false; + out.str(""); + a_entering_inv = b_entering_inv = c_entering_inv = true; + aa.f(); + BOOST_TEST(out.eq(ok.str())); + + a_exit_inv = false; + b_exit_inv = false; + c_exit_inv = false; + out.str(""); + a_entering_inv = b_entering_inv = c_entering_inv = true; + aa.f(); + BOOST_TEST(out.eq(ok.str())); + + return boost::report_errors(); +} + diff --git a/test/public_function/decl_exit_inv_sides.cpp b/test/public_function/decl_exit_inv_sides.cpp new file mode 100644 index 0000000..c8ba684 --- /dev/null +++ b/test/public_function/decl_exit_inv_sides.cpp @@ -0,0 +1,154 @@ + +// Test only derived and grandparent classes (sides) have exit invariants. + +#undef BOOST_CONTRACT_AUX_TEST_NO_A_INV +#define BOOST_CONTRACT_AUX_TEST_NO_B_INV +#undef BOOST_CONTRACT_AUX_TEST_NO_C_INV +#include "./decl.hpp" + +#include "../aux_/oteststream.hpp" +#include +#include + +int main() { + std::ostringstream ok; + + struct err {}; + boost::contract::set_exit_invariant_failed( + [] (boost::contract::from) { throw err(); }); + + a aa; + + a_exit_inv = false; + b_exit_inv = true; + c_exit_inv = true; + out.str(""); + try { + a_entering_inv = b_entering_inv = c_entering_inv = true; + aa.f(); + BOOST_TEST(false); + } catch(err const&) { + ok.str(""); ok + << "c::static_inv" << std::endl + << "c::inv" << std::endl + << "b::static_inv" << std::endl + << "a::static_inv" << std::endl + << "a::inv" << std::endl + + << "c::f::pre" << std::endl + + << "c::f::old" << std::endl + << "b::f::old" << std::endl + << "a::f::old" << std::endl + + << "a::f::body" << std::endl + + << "c::static_inv" << std::endl + << "c::inv" << std::endl + << "b::static_inv" << std::endl + << "a::static_inv" << std::endl + << "a::inv" << std::endl // Test this failed. + ; + BOOST_TEST(out.eq(ok.str())); + } catch(...) { BOOST_TEST(false); } + + a_exit_inv = true; + b_exit_inv = false; + c_exit_inv = true; + out.str(""); + try { + a_entering_inv = b_entering_inv = c_entering_inv = true; + aa.f(); + ok.str(""); ok + << "c::static_inv" << std::endl + << "c::inv" << std::endl + << "b::static_inv" << std::endl + << "a::static_inv" << std::endl + << "a::inv" << std::endl + + << "c::f::pre" << std::endl + + << "c::f::old" << std::endl + << "b::f::old" << std::endl + << "a::f::old" << std::endl + + << "a::f::body" << std::endl + + << "c::static_inv" << std::endl + << "c::inv" << std::endl + << "b::static_inv" << std::endl + << "a::static_inv" << std::endl + << "a::inv" << 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 + ; + BOOST_TEST(out.eq(ok.str())); + } catch(...) { BOOST_TEST(false); } + + a_exit_inv = true; + b_exit_inv = true; + c_exit_inv = false; + out.str(""); + try { + a_entering_inv = b_entering_inv = c_entering_inv = true; + aa.f(); + BOOST_TEST(false); + } catch(err const&) { + ok.str(""); ok + << "c::static_inv" << std::endl + << "c::inv" << std::endl + << "b::static_inv" << std::endl + << "a::static_inv" << std::endl + << "a::inv" << std::endl + + << "c::f::pre" << std::endl + + << "c::f::old" << std::endl + << "b::f::old" << std::endl + << "a::f::old" << std::endl + + << "a::f::body" << std::endl + + << "c::static_inv" << std::endl + << "c::inv" << std::endl // Test this failed. + ; + BOOST_TEST(out.eq(ok.str())); + } catch(...) { BOOST_TEST(false); } + + a_exit_inv = false; + b_exit_inv = false; + c_exit_inv = false; + out.str(""); + try { + a_entering_inv = b_entering_inv = c_entering_inv = true; + aa.f(); + BOOST_TEST(false); + } catch(err const&) { + ok.str(""); ok + << "c::static_inv" << std::endl + << "c::inv" << std::endl + << "b::static_inv" << std::endl + << "a::static_inv" << std::endl + << "a::inv" << std::endl + + << "c::f::pre" << std::endl + + << "c::f::old" << std::endl + << "b::f::old" << std::endl + << "a::f::old" << std::endl + + << "a::f::body" << std::endl + + << "c::static_inv" << std::endl + << "c::inv" << std::endl // Test this failed (as all did). + ; + BOOST_TEST(out.eq(ok.str())); + } catch(...) { BOOST_TEST(false); } + + return boost::report_errors(); +} + diff --git a/test/public_function/decl_exit_static_inv_all.cpp b/test/public_function/decl_exit_static_inv_all.cpp new file mode 100644 index 0000000..f986c51 --- /dev/null +++ b/test/public_function/decl_exit_static_inv_all.cpp @@ -0,0 +1,154 @@ + +// Test derived and base classes all with exit static invariants. + +#undef BOOST_CONTRACT_AUX_TEST_NO_A_STATIC_INV +#undef BOOST_CONTRACT_AUX_TEST_NO_B_STATIC_INV +#undef BOOST_CONTRACT_AUX_TEST_NO_C_STATIC_INV +#include "./decl.hpp" + +#include "../aux_/oteststream.hpp" +#include +#include + +int main() { + std::ostringstream ok; + + struct err {}; + boost::contract::set_exit_invariant_failed( + [] (boost::contract::from) { throw err(); }); + + a aa; + + a_exit_static_inv = false; + b_exit_static_inv = true; + c_exit_static_inv = true; + out.str(""); + try { + a_entering_static_inv = b_entering_static_inv = c_entering_static_inv = + true; + aa.f(); + BOOST_TEST(false); + } catch(err const&) { + ok.str(""); ok + << "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 + + << "c::f::pre" << std::endl + + << "c::f::old" << std::endl + << "b::f::old" << std::endl + << "a::f::old" << std::endl + + << "a::f::body" << 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 // Test this failed. + ; + BOOST_TEST(out.eq(ok.str())); + } catch(...) { BOOST_TEST(false); } + + a_exit_static_inv = true; + b_exit_static_inv = false; + c_exit_static_inv = true; + out.str(""); + try { + a_entering_static_inv = b_entering_static_inv = c_entering_static_inv = + true; + aa.f(); + BOOST_TEST(false); + } catch(err const&) { + ok.str(""); ok + << "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 + + << "c::f::pre" << std::endl + + << "c::f::old" << std::endl + << "b::f::old" << std::endl + << "a::f::old" << std::endl + + << "a::f::body" << std::endl + + << "c::static_inv" << std::endl + << "c::inv" << std::endl + << "b::static_inv" << std::endl // Test this failed. + ; + BOOST_TEST(out.eq(ok.str())); + } catch(...) { BOOST_TEST(false); } + + a_exit_static_inv = true; + b_exit_static_inv = true; + c_exit_static_inv = false; + out.str(""); + try { + a_entering_static_inv = b_entering_static_inv = c_entering_static_inv = + true; + aa.f(); + BOOST_TEST(false); + } catch(err const&) { + ok.str(""); ok + << "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 + + << "c::f::pre" << std::endl + + << "c::f::old" << std::endl + << "b::f::old" << std::endl + << "a::f::old" << std::endl + + << "a::f::body" << std::endl + + << "c::static_inv" << std::endl // Test this failed. + ; + BOOST_TEST(out.eq(ok.str())); + } catch(...) { BOOST_TEST(false); } + + a_exit_static_inv = false; + b_exit_static_inv = false; + c_exit_static_inv = false; + out.str(""); + try { + a_entering_static_inv = b_entering_static_inv = c_entering_static_inv = + true; + aa.f(); + BOOST_TEST(false); + } catch(err const&) { + ok.str(""); ok + << "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 + + << "c::f::pre" << std::endl + + << "c::f::old" << std::endl + << "b::f::old" << std::endl + << "a::f::old" << std::endl + + << "a::f::body" << std::endl + + << "c::static_inv" << std::endl // Test this failed (as all did). + ; + BOOST_TEST(out.eq(ok.str())); + } catch(...) { BOOST_TEST(false); } + + return boost::report_errors(); +} + diff --git a/test/public_function/decl_exit_static_inv_middle.cpp b/test/public_function/decl_exit_static_inv_middle.cpp new file mode 100644 index 0000000..d9452ed --- /dev/null +++ b/test/public_function/decl_exit_static_inv_middle.cpp @@ -0,0 +1,156 @@ + +// Test middle base class with exit static invariants. + +#define BOOST_CONTRACT_AUX_TEST_NO_A_STATIC_INV +#undef BOOST_CONTRACT_AUX_TEST_NO_B_STATIC_INV +#define BOOST_CONTRACT_AUX_TEST_NO_C_STATIC_INV +#include "./decl.hpp" + +#include "../aux_/oteststream.hpp" +#include +#include + +int main() { + std::ostringstream ok; + + struct err {}; + boost::contract::set_exit_invariant_failed( + [] (boost::contract::from) { throw err(); }); + + a aa; + + a_exit_static_inv = false; + b_exit_static_inv = true; + c_exit_static_inv = true; + out.str(""); + try { + a_entering_static_inv = b_entering_static_inv = c_entering_static_inv = + true; + aa.f(); + ok.str(""); ok + << "c::inv" << std::endl + << "b::static_inv" << std::endl + << "b::inv" << std::endl + << "a::inv" << std::endl + + << "c::f::pre" << std::endl + + << "c::f::old" << std::endl + << "b::f::old" << std::endl + << "a::f::old" << std::endl + + << "a::f::body" << std::endl + + << "c::inv" << std::endl + << "b::static_inv" << std::endl + << "b::inv" << std::endl + << "a::inv" << 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 + ; + BOOST_TEST(out.eq(ok.str())); + } catch(...) { BOOST_TEST(false); } + + a_exit_static_inv = true; + b_exit_static_inv = false; + c_exit_static_inv = true; + out.str(""); + try { + a_entering_static_inv = b_entering_static_inv = c_entering_static_inv = + true; + aa.f(); + BOOST_TEST(false); + } catch(err const&) { + ok.str(""); ok + << "c::inv" << std::endl + << "b::static_inv" << std::endl + << "b::inv" << std::endl + << "a::inv" << std::endl + + << "c::f::pre" << std::endl + + << "c::f::old" << std::endl + << "b::f::old" << std::endl + << "a::f::old" << std::endl + + << "a::f::body" << std::endl + + << "c::inv" << std::endl + << "b::static_inv" << std::endl // Test this failed. + ; + BOOST_TEST(out.eq(ok.str())); + } catch(...) { BOOST_TEST(false); } + + a_exit_static_inv = true; + b_exit_static_inv = true; + c_exit_static_inv = false; + out.str(""); + try { + a_entering_static_inv = b_entering_static_inv = c_entering_static_inv = + true; + aa.f(); + ok.str(""); ok + << "c::inv" << std::endl + << "b::static_inv" << std::endl + << "b::inv" << std::endl + << "a::inv" << std::endl + + << "c::f::pre" << std::endl + + << "c::f::old" << std::endl + << "b::f::old" << std::endl + << "a::f::old" << std::endl + + << "a::f::body" << std::endl + + << "c::inv" << std::endl + << "b::static_inv" << std::endl + << "b::inv" << std::endl + << "a::inv" << 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 + ; + BOOST_TEST(out.eq(ok.str())); + } catch(...) { BOOST_TEST(false); } + + a_exit_static_inv = false; + b_exit_static_inv = false; + c_exit_static_inv = false; + out.str(""); + try { + a_entering_static_inv = b_entering_static_inv = c_entering_static_inv = + true; + aa.f(); + BOOST_TEST(false); + } catch(err const&) { + ok.str(""); ok + << "c::inv" << std::endl + << "b::static_inv" << std::endl + << "b::inv" << std::endl + << "a::inv" << std::endl + + << "c::f::pre" << std::endl + + << "c::f::old" << std::endl + << "b::f::old" << std::endl + << "a::f::old" << std::endl + + << "a::f::body" << std::endl + + << "c::inv" << std::endl + << "b::static_inv" << std::endl // Test this failed (as all did). + ; + BOOST_TEST(out.eq(ok.str())); + } catch(...) { BOOST_TEST(false); } + + return boost::report_errors(); +} + diff --git a/test/public_function/decl_exit_static_inv_none.cpp b/test/public_function/decl_exit_static_inv_none.cpp new file mode 100644 index 0000000..bbaa840 --- /dev/null +++ b/test/public_function/decl_exit_static_inv_none.cpp @@ -0,0 +1,83 @@ + +// Test derived and base classes all without exit static invariants. + +#define BOOST_CONTRACT_AUX_TEST_NO_A_STATIC_INV +#define BOOST_CONTRACT_AUX_TEST_NO_B_STATIC_INV +#define BOOST_CONTRACT_AUX_TEST_NO_C_STATIC_INV +#include "./decl.hpp" + +#include "../aux_/oteststream.hpp" +#include +#include + +int main() { + std::ostringstream ok; ok + // Test no static invariants. + << "c::inv" << std::endl + << "b::inv" << std::endl + << "a::inv" << std::endl + + << "c::f::pre" << std::endl + + << "c::f::old" << std::endl + << "b::f::old" << std::endl + << "a::f::old" << std::endl + + << "a::f::body" << std::endl + + << "c::inv" << std::endl + << "b::inv" << std::endl + << "a::inv" << 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 + ; + + struct err {}; + boost::contract::set_exit_invariant_failed( + [] (boost::contract::from) { throw err(); }); + + a aa; + + a_exit_static_inv = false; + b_exit_static_inv = true; + c_exit_static_inv = true; + out.str(""); + a_entering_static_inv = b_entering_static_inv = c_entering_static_inv = + true; + aa.f(); + BOOST_TEST(out.eq(ok.str())); + + a_exit_static_inv = true; + b_exit_static_inv = false; + c_exit_static_inv = true; + out.str(""); + a_entering_static_inv = b_entering_static_inv = c_entering_static_inv = + true; + aa.f(); + BOOST_TEST(out.eq(ok.str())); + + a_exit_static_inv = true; + b_exit_static_inv = true; + c_exit_static_inv = false; + out.str(""); + a_entering_static_inv = b_entering_static_inv = c_entering_static_inv = + true; + aa.f(); + BOOST_TEST(out.eq(ok.str())); + + a_exit_static_inv = false; + b_exit_static_inv = false; + c_exit_static_inv = false; + out.str(""); + a_entering_static_inv = b_entering_static_inv = c_entering_static_inv = + true; + aa.f(); + BOOST_TEST(out.eq(ok.str())); + + return boost::report_errors(); +} + diff --git a/test/public_function/decl_exit_static_inv_sides.cpp b/test/public_function/decl_exit_static_inv_sides.cpp new file mode 100644 index 0000000..ce82f3d --- /dev/null +++ b/test/public_function/decl_exit_static_inv_sides.cpp @@ -0,0 +1,155 @@ + +// Test derived and grandparent classes (sides) all with exit static invariants. + +#undef BOOST_CONTRACT_AUX_TEST_NO_A_STATIC_INV +#define BOOST_CONTRACT_AUX_TEST_NO_B_STATIC_INV +#undef BOOST_CONTRACT_AUX_TEST_NO_C_STATIC_INV +#include "./decl.hpp" + +#include "../aux_/oteststream.hpp" +#include +#include + +int main() { + std::ostringstream ok; + + struct err {}; + boost::contract::set_exit_invariant_failed( + [] (boost::contract::from) { throw err(); }); + + a aa; + + a_exit_static_inv = false; + b_exit_static_inv = true; + c_exit_static_inv = true; + out.str(""); + try { + a_entering_static_inv = b_entering_static_inv = c_entering_static_inv = + true; + aa.f(); + BOOST_TEST(false); + } catch(err const&) { + ok.str(""); ok + << "c::static_inv" << std::endl + << "c::inv" << std::endl + << "b::inv" << std::endl + << "a::static_inv" << std::endl + << "a::inv" << std::endl + + << "c::f::pre" << std::endl + + << "c::f::old" << std::endl + << "b::f::old" << std::endl + << "a::f::old" << std::endl + + << "a::f::body" << std::endl + + << "c::static_inv" << std::endl + << "c::inv" << std::endl + << "b::inv" << std::endl + << "a::static_inv" << std::endl // Test this failed. + ; + BOOST_TEST(out.eq(ok.str())); + } catch(...) { BOOST_TEST(false); } + + a_exit_static_inv = true; + b_exit_static_inv = false; + c_exit_static_inv = true; + out.str(""); + try { + a_entering_static_inv = b_entering_static_inv = c_entering_static_inv = + true; + aa.f(); + ok.str(""); ok + << "c::static_inv" << std::endl + << "c::inv" << std::endl + << "b::inv" << std::endl + << "a::static_inv" << std::endl + << "a::inv" << std::endl + + << "c::f::pre" << std::endl + + << "c::f::old" << std::endl + << "b::f::old" << std::endl + << "a::f::old" << std::endl + + << "a::f::body" << std::endl + + << "c::static_inv" << std::endl + << "c::inv" << std::endl + << "b::inv" << std::endl + << "a::static_inv" << std::endl + << "a::inv" << 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 + ; + BOOST_TEST(out.eq(ok.str())); + } catch(...) { BOOST_TEST(false); } + + a_exit_static_inv = true; + b_exit_static_inv = true; + c_exit_static_inv = false; + out.str(""); + try { + a_entering_static_inv = b_entering_static_inv = c_entering_static_inv = + true; + aa.f(); + BOOST_TEST(false); + } catch(err const&) { + ok.str(""); ok + << "c::static_inv" << std::endl + << "c::inv" << std::endl + << "b::inv" << std::endl + << "a::static_inv" << std::endl + << "a::inv" << std::endl + + << "c::f::pre" << std::endl + + << "c::f::old" << std::endl + << "b::f::old" << std::endl + << "a::f::old" << std::endl + + << "a::f::body" << std::endl + + << "c::static_inv" << std::endl // Test this failed. + ; + BOOST_TEST(out.eq(ok.str())); + } catch(...) { BOOST_TEST(false); } + + a_exit_static_inv = false; + b_exit_static_inv = false; + c_exit_static_inv = false; + out.str(""); + try { + a_entering_static_inv = b_entering_static_inv = c_entering_static_inv = + true; + aa.f(); + BOOST_TEST(false); + } catch(err const&) { + ok.str(""); ok + << "c::static_inv" << std::endl + << "c::inv" << std::endl + << "b::inv" << std::endl + << "a::static_inv" << std::endl + << "a::inv" << std::endl + + << "c::f::pre" << std::endl + + << "c::f::old" << std::endl + << "b::f::old" << std::endl + << "a::f::old" << std::endl + + << "a::f::body" << std::endl + + << "c::static_inv" << std::endl // Test this failed (as all did). + ; + BOOST_TEST(out.eq(ok.str())); + } catch(...) { BOOST_TEST(false); } + + return boost::report_errors(); +} + diff --git a/test/public_function/decl_post_all.cpp b/test/public_function/decl_post_all.cpp new file mode 100644 index 0000000..9d8b8a5 --- /dev/null +++ b/test/public_function/decl_post_all.cpp @@ -0,0 +1,177 @@ + +// Test derived and base classes all with postconditions. + +#undef BOOST_CONTRACT_AUX_TEST_NO_A_POST +#undef BOOST_CONTRACT_AUX_TEST_NO_B_POST +#undef BOOST_CONTRACT_AUX_TEST_NO_C_POST +#include "./decl.hpp" + +#include "../aux_/oteststream.hpp" +#include +#include + +int main() { + std::ostringstream ok; + + struct err {}; + boost::contract::set_postcondition_failed( + [] (boost::contract::from) { throw err(); }); + + a aa; + + a_post = false; + b_post = true; + c_post = true; + out.str(""); + try { + aa.f(); + BOOST_TEST(false); + } catch(err const&) { + ok.str(""); ok + << "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 + + << "c::f::pre" << std::endl + + << "c::f::old" << std::endl + << "b::f::old" << std::endl + << "a::f::old" << std::endl + + << "a::f::body" << 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 + + << "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 // Test this failed. + ; + BOOST_TEST(out.eq(ok.str())); + } catch(...) { BOOST_TEST(false); } + + a_post = true; + b_post = false; + c_post = true; + out.str(""); + try { + aa.f(); + BOOST_TEST(false); + } catch(err const&) { + ok.str(""); ok + << "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 + + << "c::f::pre" << std::endl + + << "c::f::old" << std::endl + << "b::f::old" << std::endl + << "a::f::old" << std::endl + + << "a::f::body" << 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 + + << "c::f::old" << std::endl + << "c::f::post" << std::endl + << "b::f::old" << std::endl + << "b::f::post" << std::endl // Test this failed. + ; + BOOST_TEST(out.eq(ok.str())); + } catch(...) { BOOST_TEST(false); } + + a_post = true; + b_post = true; + c_post = false; + out.str(""); + try { + aa.f(); + BOOST_TEST(false); + } catch(err const&) { + ok.str(""); ok + << "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 + + << "c::f::pre" << std::endl + + << "c::f::old" << std::endl + << "b::f::old" << std::endl + << "a::f::old" << std::endl + + << "a::f::body" << 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 + + << "c::f::old" << std::endl + << "c::f::post" << std::endl // Test this failed. + ; + BOOST_TEST(out.eq(ok.str())); + } catch(...) { BOOST_TEST(false); } + + a_post = false; + b_post = false; + c_post = false; + out.str(""); + try { + aa.f(); + BOOST_TEST(false); + } catch(err const&) { + ok.str(""); ok + << "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 + + << "c::f::pre" << std::endl + + << "c::f::old" << std::endl + << "b::f::old" << std::endl + << "a::f::old" << std::endl + + << "a::f::body" << 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 + + << "c::f::old" << std::endl + << "c::f::post" << std::endl // Test this failed (as all did). + ; + BOOST_TEST(out.eq(ok.str())); + } catch(...) { BOOST_TEST(false); } + + return boost::report_errors(); +} + diff --git a/test/public_function/decl_post_middle.cpp b/test/public_function/decl_post_middle.cpp new file mode 100644 index 0000000..1cc445d --- /dev/null +++ b/test/public_function/decl_post_middle.cpp @@ -0,0 +1,172 @@ + +// Test only middle base class has postconditions. + +#define BOOST_CONTRACT_AUX_TEST_NO_A_POST +#undef BOOST_CONTRACT_AUX_TEST_NO_B_POST +#define BOOST_CONTRACT_AUX_TEST_NO_C_POST +#include "./decl.hpp" + +#include "../aux_/oteststream.hpp" +#include +#include + +int main() { + std::ostringstream ok; + + struct err {}; + boost::contract::set_postcondition_failed( + [] (boost::contract::from) { throw err(); }); + + a aa; + + a_post = false; + b_post = true; + c_post = true; + out.str(""); + try { + aa.f(); + ok.str(""); ok + << "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 + + << "c::f::pre" << std::endl + + << "c::f::old" << std::endl + << "b::f::old" << std::endl + << "a::f::old" << std::endl + + << "a::f::body" << 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 + + << "c::f::old" << std::endl + << "b::f::old" << std::endl + << "b::f::post" << std::endl + ; + BOOST_TEST(out.eq(ok.str())); + } catch(...) { BOOST_TEST(false); } + + a_post = true; + b_post = false; + c_post = true; + out.str(""); + try { + aa.f(); + BOOST_TEST(false); + } catch(err const&) { + ok.str(""); ok + << "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 + + << "c::f::pre" << std::endl + + << "c::f::old" << std::endl + << "b::f::old" << std::endl + << "a::f::old" << std::endl + + << "a::f::body" << 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 + + << "c::f::old" << std::endl + << "b::f::old" << std::endl + << "b::f::post" << std::endl // Test this failed. + ; + BOOST_TEST(out.eq(ok.str())); + } catch(...) { BOOST_TEST(false); } + + a_post = true; + b_post = true; + c_post = false; + out.str(""); + try { + aa.f(); + ok.str(""); ok + << "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 + + << "c::f::pre" << std::endl + + << "c::f::old" << std::endl + << "b::f::old" << std::endl + << "a::f::old" << std::endl + + << "a::f::body" << 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 + + << "c::f::old" << std::endl + << "b::f::old" << std::endl + << "b::f::post" << std::endl + ; + BOOST_TEST(out.eq(ok.str())); + } catch(...) { BOOST_TEST(false); } + + a_post = false; + b_post = false; + c_post = false; + out.str(""); + try { + aa.f(); + BOOST_TEST(false); + } catch(err const&) { + ok.str(""); ok + << "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 + + << "c::f::pre" << std::endl + + << "c::f::old" << std::endl + << "b::f::old" << std::endl + << "a::f::old" << std::endl + + << "a::f::body" << 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 + + << "c::f::old" << std::endl + << "b::f::old" << std::endl + << "b::f::post" << std::endl // Test this failed (as all did). + ; + BOOST_TEST(out.eq(ok.str())); + } catch(...) { BOOST_TEST(false); } + + return boost::report_errors(); +} + diff --git a/test/public_function/decl_post_none.cpp b/test/public_function/decl_post_none.cpp new file mode 100644 index 0000000..7331ac4 --- /dev/null +++ b/test/public_function/decl_post_none.cpp @@ -0,0 +1,74 @@ + +// Test derived and base classes all without postconditions. + +#define BOOST_CONTRACT_AUX_TEST_NO_A_POST +#define BOOST_CONTRACT_AUX_TEST_NO_B_POST +#define BOOST_CONTRACT_AUX_TEST_NO_C_POST +#include "./decl.hpp" + +#include "../aux_/oteststream.hpp" +#include +#include + +int main() { + std::ostringstream ok; ok + << "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 + + << "c::f::pre" << std::endl + + << "c::f::old" << std::endl + << "b::f::old" << std::endl + << "a::f::old" << std::endl + + << "a::f::body" << 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 + + // Test no postconditions. + << "c::f::old" << std::endl + << "b::f::old" << std::endl + ; + + a aa; + + a_post = false; + b_post = true; + c_post = true; + out.str(""); + aa.f(); + BOOST_TEST(out.eq(ok.str())); + + a_post = true; + b_post = false; + c_post = true; + out.str(""); + aa.f(); + BOOST_TEST(out.eq(ok.str())); + + a_post = true; + b_post = true; + c_post = false; + out.str(""); + aa.f(); + BOOST_TEST(out.eq(ok.str())); + + a_post = false; + b_post = false; + c_post = false; + out.str(""); + aa.f(); + BOOST_TEST(out.eq(ok.str())); + + return boost::report_errors(); +} + diff --git a/test/public_function/decl_post_sides.cpp b/test/public_function/decl_post_sides.cpp new file mode 100644 index 0000000..527d317 --- /dev/null +++ b/test/public_function/decl_post_sides.cpp @@ -0,0 +1,174 @@ + +// Test only derived and grandparent classes (sides) have postconditions. + +#undef BOOST_CONTRACT_AUX_TEST_NO_A_POST +#define BOOST_CONTRACT_AUX_TEST_NO_B_POST +#undef BOOST_CONTRACT_AUX_TEST_NO_C_POST +#include "./decl.hpp" + +#include "../aux_/oteststream.hpp" +#include +#include + +int main() { + std::ostringstream ok; + + struct err {}; + boost::contract::set_postcondition_failed( + [] (boost::contract::from) { throw err(); }); + + a aa; + + a_post = false; + b_post = true; + c_post = true; + out.str(""); + try { + aa.f(); + BOOST_TEST(false); + } catch(err const&) { + ok.str(""); ok + << "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 + + << "c::f::pre" << std::endl + + << "c::f::old" << std::endl + << "b::f::old" << std::endl + << "a::f::old" << std::endl + + << "a::f::body" << 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 + + << "c::f::old" << std::endl + << "c::f::post" << std::endl + << "b::f::old" << std::endl + << "a::f::post" << std::endl // Test this failed. + ; + BOOST_TEST(out.eq(ok.str())); + } catch(...) { BOOST_TEST(false); } + + a_post = true; + b_post = false; + c_post = true; + out.str(""); + try { + aa.f(); + ok.str(""); ok + << "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 + + << "c::f::pre" << std::endl + + << "c::f::old" << std::endl + << "b::f::old" << std::endl + << "a::f::old" << std::endl + + << "a::f::body" << 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 + + << "c::f::old" << std::endl + << "c::f::post" << std::endl + << "b::f::old" << std::endl + << "a::f::post" << std::endl + ; + BOOST_TEST(out.eq(ok.str())); + } catch(...) { BOOST_TEST(false); } + + a_post = true; + b_post = true; + c_post = false; + out.str(""); + try { + aa.f(); + BOOST_TEST(false); + } catch(err const&) { + ok.str(""); ok + << "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 + + << "c::f::pre" << std::endl + + << "c::f::old" << std::endl + << "b::f::old" << std::endl + << "a::f::old" << std::endl + + << "a::f::body" << 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 + + << "c::f::old" << std::endl + << "c::f::post" << std::endl // Test this failed. + ; + BOOST_TEST(out.eq(ok.str())); + } catch(...) { BOOST_TEST(false); } + + a_post = false; + b_post = false; + c_post = false; + out.str(""); + try { + aa.f(); + BOOST_TEST(false); + } catch(err const&) { + ok.str(""); ok + << "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 + + << "c::f::pre" << std::endl + + << "c::f::old" << std::endl + << "b::f::old" << std::endl + << "a::f::old" << std::endl + + << "a::f::body" << 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 + + << "c::f::old" << std::endl + << "c::f::post" << std::endl // Test this failed (as all did). + ; + BOOST_TEST(out.eq(ok.str())); + } catch(...) { BOOST_TEST(false); } + + return boost::report_errors(); +} + diff --git a/test/public_function/decl_pre_all.cpp b/test/public_function/decl_pre_all.cpp new file mode 100644 index 0000000..5754aba --- /dev/null +++ b/test/public_function/decl_pre_all.cpp @@ -0,0 +1,159 @@ + +// Test derived and base classes all with preconditions. + +#undef BOOST_CONTRACT_AUX_TEST_NO_A_PRE +#undef BOOST_CONTRACT_AUX_TEST_NO_B_PRE +#undef BOOST_CONTRACT_AUX_TEST_NO_C_PRE +#include "./decl.hpp" + +#include "../aux_/oteststream.hpp" +#include +#include + +int main() { + std::ostringstream ok; + + a aa; + + a_pre = true; + b_pre = false; + c_pre = false; + out.str(""); + aa.f(); + ok.str(""); ok + << "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 + + << "c::f::pre" << std::endl + << "b::f::pre" << std::endl + << "a::f::pre" << std::endl // Test all pre checked. + + << "c::f::old" << std::endl + << "b::f::old" << std::endl + << "a::f::old" << std::endl + + << "a::f::body" << 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 + + << "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 + ; + BOOST_TEST(out.eq(ok.str())); + + a_pre = false; + b_pre = true; + c_pre = false; + out.str(""); + aa.f(); + ok.str(""); ok + << "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 + + << "c::f::pre" << std::endl + << "b::f::pre" << std::endl + // Test only a::f::pre not checked. + + << "c::f::old" << std::endl + << "b::f::old" << std::endl + << "a::f::old" << std::endl + + << "a::f::body" << 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 + + << "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 + ; + BOOST_TEST(out.eq(ok.str())); + + a_pre = false; + b_pre = false; + c_pre = true; + out.str(""); + aa.f(); + ok.str(""); ok + << "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 + + << "c::f::pre" << std::endl // Test only c::f::pre checked. + + << "c::f::old" << std::endl + << "b::f::old" << std::endl + << "a::f::old" << std::endl + + << "a::f::body" << 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 + + << "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 + ; + BOOST_TEST(out.eq(ok.str())); + + struct err {}; + boost::contract::set_precondition_failed( + [] (boost::contract::from) { throw err(); }); + + a_pre = false; + b_pre = false; + c_pre = false; + out.str(""); + try { + aa.f(); + BOOST_TEST(false); + } catch(err const&) { + ok.str(""); ok + << "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 + + << "c::f::pre" << std::endl + << "b::f::pre" << std::endl + << "a::f::pre" << std::endl // Test all pre checked and failed. + ; + BOOST_TEST(out.eq(ok.str())); + } catch(...) { BOOST_TEST(false); } + + return boost::report_errors(); +} + diff --git a/test/public_function/decl_pre_middle.cpp b/test/public_function/decl_pre_middle.cpp new file mode 100644 index 0000000..c1037d2 --- /dev/null +++ b/test/public_function/decl_pre_middle.cpp @@ -0,0 +1,104 @@ + +// Test only middle base class has preconditions. + +#define BOOST_CONTRACT_AUX_TEST_NO_A_PRE +#undef BOOST_CONTRACT_AUX_TEST_NO_B_PRE +#define BOOST_CONTRACT_AUX_TEST_NO_C_PRE +#include "./decl.hpp" + +#include "../aux_/oteststream.hpp" +#include +#include + +int main() { + std::ostringstream ok; + + a aa; + + a_pre = false; + b_pre = true; + c_pre = false; + out.str(""); + aa.f(); + ok.str(""); ok + << "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 + + << "b::f::pre" << std::endl + + << "c::f::old" << std::endl + << "b::f::old" << std::endl + << "a::f::old" << std::endl + + << "a::f::body" << 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 + + << "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 + ; + BOOST_TEST(out.eq(ok.str())); + + struct err {}; + boost::contract::set_precondition_failed( + [] (boost::contract::from) { throw err(); }); + + ok.str(""); ok + << "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 + + << "b::f::pre" << std::endl // Test only middle pre checked and failed. + ; + + a_pre = true; + b_pre = false; + c_pre = false; + out.str(""); + try { + aa.f(); + BOOST_TEST(false); + } catch(err const&) { + BOOST_TEST(out.eq(ok.str())); + } catch(...) { BOOST_TEST(false); } + + a_pre = false; + b_pre = false; + c_pre = true; + out.str(""); + try { + aa.f(); + BOOST_TEST(false); + } catch(err const&) { + BOOST_TEST(out.eq(ok.str())); + } catch(...) { BOOST_TEST(false); } + + a_pre = false; + b_pre = false; + c_pre = false; + out.str(""); + try { + aa.f(); + BOOST_TEST(false); + } catch(err const&) { + BOOST_TEST(out.eq(ok.str())); + } catch(...) { BOOST_TEST(false); } + + return boost::report_errors(); +} + diff --git a/test/public_function/decl_pre_none.cpp b/test/public_function/decl_pre_none.cpp new file mode 100644 index 0000000..fac2532 --- /dev/null +++ b/test/public_function/decl_pre_none.cpp @@ -0,0 +1,76 @@ + +// Test derived and base classes all without preconditions. + +#define BOOST_CONTRACT_AUX_TEST_NO_A_PRE +#define BOOST_CONTRACT_AUX_TEST_NO_B_PRE +#define BOOST_CONTRACT_AUX_TEST_NO_C_PRE +#include "./decl.hpp" + +#include "../aux_/oteststream.hpp" +#include +#include + +int main() { + std::ostringstream ok; ok + << "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 + + // Test no preconditions. + + << "c::f::old" << std::endl + << "b::f::old" << std::endl + << "a::f::old" << std::endl + + << "a::f::body" << 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 + + << "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 + ; + + a aa; + + a_pre = true; + b_pre = false; + c_pre = false; + out.str(""); + aa.f(); + BOOST_TEST(out.eq(ok.str())); + + a_pre = false; + b_pre = true; + c_pre = false; + out.str(""); + aa.f(); + BOOST_TEST(out.eq(ok.str())); + + a_pre = false; + b_pre = false; + c_pre = true; + out.str(""); + aa.f(); + BOOST_TEST(out.eq(ok.str())); + + a_pre = false; + b_pre = false; + c_pre = false; + out.str(""); + aa.f(); + BOOST_TEST(out.eq(ok.str())); + + return boost::report_errors(); +} + diff --git a/test/public_function/decl_pre_sides.cpp b/test/public_function/decl_pre_sides.cpp new file mode 100644 index 0000000..e452a14 --- /dev/null +++ b/test/public_function/decl_pre_sides.cpp @@ -0,0 +1,133 @@ + +// Test only derived and grandparent classes (sides) have preconditions. + +#undef BOOST_CONTRACT_AUX_TEST_NO_A_PRE +#define BOOST_CONTRACT_AUX_TEST_NO_B_PRE +#undef BOOST_CONTRACT_AUX_TEST_NO_C_PRE +#include "./decl.hpp" + +#include "../aux_/oteststream.hpp" +#include +#include + +int main() { + std::ostringstream ok; + + a aa; + + a_pre = true; + b_pre = false; + c_pre = false; + out.str(""); + aa.f(); + ok.str(""); ok + << "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 + + << "c::f::pre" << std::endl + // Test b's pre not checked. + << "a::f::pre" << std::endl + + << "c::f::old" << std::endl + << "b::f::old" << std::endl + << "a::f::old" << std::endl + + << "a::f::body" << 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 + + << "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 + ; + BOOST_TEST(out.eq(ok.str())); + + a_pre = false; + b_pre = false; + c_pre = true; + out.str(""); + aa.f(); + ok.str(""); ok + << "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 + + << "c::f::pre" << std::endl + // Test only c pre checked. + + << "c::f::old" << std::endl + << "b::f::old" << std::endl + << "a::f::old" << std::endl + + << "a::f::body" << 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 + + << "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 + ; + BOOST_TEST(out.eq(ok.str())); + + struct err {}; + boost::contract::set_precondition_failed( + [] (boost::contract::from) { throw err(); }); + + ok.str(""); ok + << "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 + + << "c::f::pre" << std::endl + << "a::f::pre" << std::endl // Only first/last pre checked and failed. + ; + + a_pre = false; + b_pre = true; + c_pre = false; + out.str(""); + try { + aa.f(); + BOOST_TEST(false); + } catch(err const&) { + BOOST_TEST(out.eq(ok.str())); + } catch(...) { BOOST_TEST(false); } + + a_pre = false; + b_pre = false; + c_pre = false; + out.str(""); + try { + aa.f(); + BOOST_TEST(false); + } catch(err const&) { + BOOST_TEST(out.eq(ok.str())); + } catch(...) { BOOST_TEST(false); } + + return boost::report_errors(); +} + diff --git a/test/public_function/override.i b/test/public_function/override.hpp similarity index 97% rename from test/public_function/override.i rename to test/public_function/override.hpp index 394a061..9bc1fb8 100644 --- a/test/public_function/override.i +++ b/test/public_function/override.hpp @@ -1,4 +1,6 @@ +// no #include guard + // Test error if override func does not actually override (unless PERMISSIVE). #include diff --git a/test/public_function/override_error.cpp b/test/public_function/override_error.cpp index 0bb1b8c..b76bbe3 100644 --- a/test/public_function/override_error.cpp +++ b/test/public_function/override_error.cpp @@ -1,3 +1,3 @@ -#include "override.i" +#include "override.hpp" diff --git a/test/public_function/override_permissive.cpp b/test/public_function/override_permissive.cpp index a639be5..c3005da 100644 --- a/test/public_function/override_permissive.cpp +++ b/test/public_function/override_permissive.cpp @@ -1,4 +1,4 @@ #define BOOST_CONTRACT_CONFIG_PERMISSIVE -#include "override.i" +#include "override.hpp" diff --git a/test/result/mixed_optional.cpp b/test/result/mixed_optional.cpp index 6bcc2d7..cff4d5b 100644 --- a/test/result/mixed_optional.cpp +++ b/test/result/mixed_optional.cpp @@ -1,3 +1,3 @@ -#include "mixed_optional.i" +#include "mixed_optional.hpp" diff --git a/test/result/mixed_optional.i b/test/result/mixed_optional.hpp similarity index 99% rename from test/result/mixed_optional.i rename to test/result/mixed_optional.hpp index c769f2d..98909ef 100644 --- a/test/result/mixed_optional.i +++ b/test/result/mixed_optional.hpp @@ -1,4 +1,6 @@ +// no #include guard + // Test base and derived classes mixing boost::optional and non- result types. #include "../aux_/oteststream.hpp" diff --git a/test/result/mixed_optional_ref.cpp b/test/result/mixed_optional_ref.cpp index 407d7b0..c60c45f 100644 --- a/test/result/mixed_optional_ref.cpp +++ b/test/result/mixed_optional_ref.cpp @@ -1,4 +1,4 @@ #define BOOST_CONTRACT_AUX_TEST_ref -#include "mixed_optional.i" +#include "mixed_optional.hpp"