diff --git a/.gitignore b/.gitignore index 2cd9689..6a845fe 100644 --- a/.gitignore +++ b/.gitignore @@ -26,6 +26,7 @@ *.exe *.out *.app +*.stackdump # VI *.swp diff --git a/Jamroot b/Jamroot index ff05ed3..c7b354c 100644 --- a/Jamroot +++ b/Jamroot @@ -18,10 +18,7 @@ if ! [ os.environ BOOST_ROOT ] { exit "Error: Set BOOST_ROOT environment variable to Boost root directory" ; } local BOOST_ROOT = [ os.environ BOOST_ROOT ] ; - -echo "Build Boost.Contract's source, tests, examples, documentation, etc." ; echo "Using Boost libraries from (see $BOOST_ROOT): $(BOOST_ROOT)" ; -echo ; use-project boost : $(BOOST_ROOT) ; diff --git a/example/push_back.cpp b/example/push_back.cpp index 102070d..7687938 100644 --- a/example/push_back.cpp +++ b/example/push_back.cpp @@ -4,8 +4,9 @@ template struct pusahble { - void push_back(T const& value, boost::contract::virtual_body v = 0) { - auto contract = boost::contract::public_member(v, this) + virtual void push_back(T const& value, + boost::contract::virtual_* v = 0) = 0 { + boost::contract::var c = boost::contract::public_member(v, this) .precondition([&] { BOOST_CONTRACT_ASSERT(false); // Force check derived precond. }) @@ -19,8 +20,6 @@ struct pusahble { }) ; } - virtual void push_back(T const& value) = 0; // Subcontract pure-virtual. - protected: virtual T const& back() const = 0; }; @@ -38,10 +37,11 @@ public: BOOST_CONTRACT_ASSERT(empty() == (size() == 0)); } - void push_back(T const& value, boost::contract::virtual_body v = 0) { - auto old_size = BOOST_CONTRACT_OLDOF(v, size()); + virtual void push_back(T const& value, boost::contract::virtual_* v = 0) { + boost::shared_ptr old_size = + BOOST_CONTRACT_OLDOF(v, size()); boost::contract::type contract = boost::contract::public_member< - introspect_push_back>(v, this, &vector::push_back, value) + introspect_push_back>(v, this, value) .precondition([&]() { BOOST_CONTRACT_ASSERT(this->size() < this->max_size()); }) @@ -49,9 +49,9 @@ public: BOOST_CONTRACT_ASSERT(this->size() == old_size + 1); }) ; - push_back_body(value); + vector_.push_back(value); } - virtual void push_back_body(T const& value) { vector_.push_back(value); } + BOOST_CONTRACT_INTROSPECT(push_back) bool empty() const { return vector_.empty(); } unsigned size() const { return vector_.size(); } @@ -60,7 +60,18 @@ public: private: std::vector vector_; - - BOOST_CONTRACT_INTROSPECT(push_back) }; +void my_sqrt(double& x) { // My square root (with contracts). + boost::shared_ptr old_x = BOOST_CONTRACT_OLDOF(x); + boost::contract::scoped contract = boost::contract::free_function() + .precondition([&] { + BOOST_CONTRACT_ASSERT(x >= 0); + }) + .postcondition([&] { + BOOST_CONTRACT_ASSERT(x * x == old_x); + }) + ; + x = std::sqrt(x); // C++ square root (without contracts). +} + diff --git a/features.txt b/features.txt index d4139f5..5e10b5b 100644 --- a/features.txt +++ b/features.txt @@ -1,18 +1,20 @@ Features to test: -* Constructors w/ subcontracting - --> pre > (bases...) > static_inv > body > static_inv > inv > post +o Constructors w/ subcontracting + --> pre > bases' pre > for x in [bases, class] ( static_inv (but not inv) > body > static_inv > inv > post ) --> protected and private bases ALSO contract (because always part of C++ obj construction mechanism) -* Constructor preconditions checked before member initialization list -* Constructors have no `.precondition` (must use `constructor_precondition` instead) -* Overloaded Constructors with no preconditions -* Constructors above w/ bind +o Constructor preconditions checked before member initialization list +o Constructors have no `.precondition` (must use `constructor_precondition` instead) +o Overloaded Constructors, also with no preconditions +o Constructors above w/ bind -* Destructors subcontracting (w/ postconditions) - --> protected and private bases do not subcontract -* Destructors have no `.precondition` -* Destructors above w/ bind +o Destructors subcontracting (w/ postconditions) + --> for x in [class, reverse(bases)] ( static_inv > inv > body > static_inv (but not inv) > post ) + --> protected and private bases ALSO contract (because always part of C++ obj destructor mechanism) +o Destructors have no `.precondition` (because destructors have no argument) +o Destructors above w/ bind +(No overload because destructors have no argument) * Private members check pre and post, but no cv/static invariants and no subcontracting * Private members above w/ bind @@ -23,24 +25,33 @@ Features to test: * Static public members check pre, post, and static invariants, but no cv invariants and no subcontracting * Static public members above w/ bind -* Public members subcontracting (pre in logic-or, post and inv in logic-and) +* Public members subcontracting + --> pre in logic-or + --> post and inv in logic-and --> protected and private bases do not subcontract * Require, but always allow, bind for public virtual members * Require, but always allow, introspect for overriding public members * Public members above w/ bind -* Free functions pre and post (but obviously no cv/static invariants and no subcontracting) -* Free functions above w/ bind -* Check (just for free functions, other contract use same set_... classes anyways) that: - OK: nothing | pre (only) | post (only) | pre > post | port > pre - Error: pre > pre | post > post | pre > post > pre | pre > post > post +o Free functions pre and post (but obviously no cv/static invariants and no subcontracting) +o Free functions above w/ bind +o Check (just for free functions, other contract use same set_... classes anyways) that: + OK: nothing | pre (only) | post (only) | pre > post | post > pre + Error: pre > pre | post > post | pre > post > pre | post > pre > post + +For all contract types (constructors, etc.): +* Member function passed to bind must be const +* Function passed to bind must take all args as T const&, but last arg that must be boost::contract::call +* Arguments passed to bind should not be every copied (cpcnt == 0) * Old values with/without bind, with/without subcontracting --> copied and evaluated only once by OLDOF +* Test bind wit a member function taking no argument and a free function taking a single argument as pointer (to make sure these overloads can be resolved) * Result... maybe test with/without boost::optional... * On body throw... for all contract types * Failure handlers and throw on contract failure * Disable pre, post, and/or entry/exit inv (all combinations) * Overloading for all contracts * Volatile inv +* No static inv / const inv / volatile inv when static_inv / inv const / inv const volatile func not defined (for ctor, dtor, and pub member) diff --git a/include/boost/contract/aux_/call.hpp b/include/boost/contract/aux_/call.hpp index 0965492..6e04941 100644 --- a/include/boost/contract/aux_/call.hpp +++ b/include/boost/contract/aux_/call.hpp @@ -20,9 +20,10 @@ struct call : private boost::noncopyable { // Do not copy queue. check_exit_inv }; - explicit call() : action() {} + explicit call() : action(), after_contract(false), old_values() {} action_enum action; + bool after_contract; std::queue > old_values; }; diff --git a/include/boost/contract/aux_/condition/check_nothing.hpp b/include/boost/contract/aux_/condition/check_base.hpp similarity index 62% rename from include/boost/contract/aux_/condition/check_nothing.hpp rename to include/boost/contract/aux_/condition/check_base.hpp index 0e8b1dc..0e9584b 100644 --- a/include/boost/contract/aux_/condition/check_nothing.hpp +++ b/include/boost/contract/aux_/condition/check_base.hpp @@ -4,9 +4,10 @@ namespace boost { namespace contract { namespace aux { -class check_nothing { // Used as base for all contracts (and holder for RAII). +// Base class for all contracts (used to hold RAII contract object, etc.). +class check_base { public: - virtual ~check_nothing() {} + virtual ~check_base() {} }; } } } // namespace diff --git a/include/boost/contract/aux_/condition/check_pre_post.hpp b/include/boost/contract/aux_/condition/check_pre_post.hpp index 2a53295..ec4719f 100644 --- a/include/boost/contract/aux_/condition/check_pre_post.hpp +++ b/include/boost/contract/aux_/condition/check_pre_post.hpp @@ -3,12 +3,12 @@ #define BOOST_CONTRACT_AUX_CHECK_PRE_POST_HPP_ #include -#include +#include #include #include /** @cond */ #include -#include +#include // TODO: Can I reduce boost.function overhead? /** @endcond */ namespace boost { namespace contract { namespace aux { @@ -17,27 +17,26 @@ namespace boost { namespace contract { namespace aux { // (if function is a lambda) and it could be expensive... check all classes // that MUST be copiable, make sure their copies are effecient, make all other // calsses noncopyable. -class check_pre_post : public boost::contract::aux::check_nothing { +class check_pre_post : public check_base { public: explicit check_pre_post(boost::contract::from from) : from_(from) {} - explicit check_pre_post(boost::contract::from from, boost::shared_ptr< - boost::contract::aux::call> call) : - from_(from), contract_call_(call) - {} + explicit check_pre_post(boost::contract::from from, + boost::shared_ptr _call) : from_(from), decl_call_(_call) { + if(decl_call_) decl_call_->after_contract = true; + } virtual ~check_pre_post() {} template - void set_pre(F f) { pre_ = f; pre_available(); } + void set_pre(F const& f) { pre_ = f; pre_available(); } template - void set_post(F f) { post_ = f; post_available(); } + void set_post(F const& f) { post_ = f; post_available(); } protected: void check_pre(bool throw_on_failure = false) { - if(!contract_call_ || contract_call_->action == - boost::contract::aux::call::check_pre) { + if(!decl_call_ || decl_call_->action == call::check_pre) { if(pre_) { try { pre_(); } catch(...) { @@ -47,7 +46,7 @@ protected: boost::contract::precondition_failed(from_); } } - if(contract_call_) throw boost::contract::aux::no_error(); + if(decl_call_) throw no_error(); } } @@ -71,13 +70,12 @@ protected: // If call(), can't call from a dtor (as throw no_error on OK). void check_post() { - if(!contract_call_ || contract_call_->action == - boost::contract::aux::call::check_post) { + if(!decl_call_ || decl_call_->action == call::check_post) { if(post_) { try { post_(); } catch(...) { boost::contract::postcondition_failed(from_); } } - if(contract_call_) throw boost::contract::aux::no_error(); + if(decl_call_) throw no_error(); } } @@ -86,15 +84,13 @@ protected: boost::contract::from from() const { return from_; } - boost::shared_ptr contract_call() { - return contract_call_; - } + boost::shared_ptr decl_call() { return decl_call_; } private: boost::function pre_; boost::function post_; boost::contract::from from_; - boost::shared_ptr contract_call_; + boost::shared_ptr decl_call_; }; } } } 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 59ebbe6..438a9d0 100644 --- a/include/boost/contract/aux_/condition/check_pre_post_inv.hpp +++ b/include/boost/contract/aux_/condition/check_pre_post_inv.hpp @@ -16,34 +16,33 @@ namespace boost { namespace contract { namespace aux { template -class check_pre_post_inv : // Copyable (as shallow ptr). - public boost::contract::aux::check_pre_post { +class check_pre_post_inv : public check_pre_post { // Copyable (as *). public: explicit check_pre_post_inv(boost::contract::from from, C const* obj) : - boost::contract::aux::check_pre_post(from), obj_(obj) {} + check_pre_post(from), obj_(obj) {} explicit check_pre_post_inv(boost::contract::from from, boost::shared_ptr< - boost::contract::aux::call> call, C const* obj) : - boost::contract::aux::check_pre_post(from, call), obj_(obj) + call> decl_call, C const* obj) : + check_pre_post(from, decl_call), obj_(obj) {} virtual ~check_pre_post_inv() {} protected: void check_entry_inv(bool static_inv_only = false) { - if(!this->contract_call() || this->contract_call()->action == - boost::contract::aux::call::check_entry_inv) { + if(!this->decl_call() || this->decl_call()->action == + call::check_entry_inv) { check_inv(/* on_entry = */ true, static_inv_only); - if(this->contract_call()) throw no_error(); + if(this->decl_call()) throw no_error(); } } // If call(), can't call from dtor (as throw no_error on OK). void check_exit_inv(bool static_inv_only = false) { - if(!this->contract_call() || this->contract_call()->action == - boost::contract::aux::call::check_exit_inv) { + if(!this->decl_call() || this->decl_call()->action == + call::check_exit_inv) { check_inv(/* on_entry = */ false, static_inv_only); - if(this->contract_call()) throw no_error(); + if(this->decl_call()) throw no_error(); } } @@ -51,10 +50,10 @@ protected: private: void check_inv(bool on_entry, bool static_inv_only) { - check_static_inv(on_entry, boost::mpl::bool_::value>()); if(!static_inv_only) { - check_const_inv(on_entry, boost::mpl::bool_::value>()); } } 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 41fc228..b2cfc23 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 @@ -2,7 +2,7 @@ #ifndef BOOST_CONTRACT_AUX_CHECK_SUBCONTRACTED_PRE_POST_INV_HPP_ #define BOOST_CONTRACT_AUX_CHECK_SUBCONTRACTED_PRE_POST_INV_HPP_ -#include +#include #include #include #include @@ -35,12 +35,12 @@ namespace boost { namespace contract { namespace aux { // calsses noncopyable? What does truly need to be copyable and why? template -class check_subcontracted_pre_post_inv : // Copyable as shallow ptr and ref. - public boost::contract::aux::check_pre_post_inv { +class check_subcontracted_pre_post_inv : // Copyable (as * and &). + public check_pre_post_inv { // Base types as pointers because mpl::for_each will construct them. typedef typename boost::mpl::transform< - typename boost::mpl::eval_if, - boost::contract::aux::base_types_of + typename boost::mpl::eval_if, + base_types_of , boost::mpl::identity > >::type, @@ -53,19 +53,19 @@ public: C const* obj, A0 const& a0 ) : - boost::contract::aux::check_pre_post_inv(from, obj), - subcontracting_call_(boost::make_shared()), + check_pre_post_inv(from, obj), + c_(boost::make_shared()), a0_(a0) { init(); } explicit check_subcontracted_pre_post_inv( boost::contract::from from, - boost::shared_ptr call, + boost::shared_ptr decl_call, C const* obj, A0 const& a0 ) : - boost::contract::aux::check_pre_post_inv(from, call, obj), - subcontracting_call_(boost::make_shared()), + check_pre_post_inv(from, decl_call, obj), + c_(decl_call), a0_(a0) { init(); } @@ -73,56 +73,71 @@ public: protected: void copy_subcontracted_oldof() { - subcontracting_call_->action = boost::contract::aux::call::copy_oldof; - boost::mpl::for_each(check_base_); + if(this->decl_call() && this->decl_call()->action != call::copy_oldof) { + return; + } + c_.call_->action = call::copy_oldof; + boost::mpl::for_each(check_base_class_); // No this->... here (calling func old-ofs on stack or handled by bind). } void check_subcontracted_entry_inv() { - subcontracting_call_->action = - boost::contract::aux::call::check_entry_inv; - boost::mpl::for_each(check_base_); + if(this->decl_call() && this->decl_call()->action != + call::check_entry_inv) { + return; + } + c_.call_->action = call::check_entry_inv; + boost::mpl::for_each(check_base_class_); this->check_entry_inv(); } // Allow to throw on failure for relaxing subcontracted pre. void check_subcontracted_pre(bool throw_on_failure = false) { - subcontracting_call_->action = boost::contract::aux::call::check_pre; + if(this->decl_call() && this->decl_call()->action != call::check_pre) { + return; + } + c_.call_->action = call::check_pre; try { - boost::mpl::for_each(check_base_); + boost::mpl::for_each(check_base_class_); // Pre logic-or: Last check, error also throws. this->check_pre(throw_on_failure); - } catch(boost::contract::aux::no_error const&) { + } catch(no_error const&) { // Pre logic-or: Stop at 1st no_error (thrown by callee). } } void check_subcontracted_exit_inv() { - subcontracting_call_->action = - boost::contract::aux::call::check_exit_inv; - boost::mpl::for_each(check_base_); + if(this->decl_call() && this->decl_call()->action != + call::check_exit_inv) { + return; + } + c_.call_->action = call::check_exit_inv; + boost::mpl::for_each(check_base_class_); this->check_exit_inv(); } void check_subcontracted_post() { - subcontracting_call_->action = boost::contract::aux::call::check_post; - boost::mpl::for_each(check_base_); + if(this->decl_call() && this->decl_call()->action != call::check_post) { + return; + } + c_.call_->action = call::check_post; + boost::mpl::for_each(check_base_class_); this->check_post(); } private: - void init() { check_base_.nest(this); } - - class check_base { + void init() { check_base_class_.nest(this); } + + class check_base_class { // Copyable (as *). public: - explicit check_base() : nest_() {} + explicit check_base_class() : nest_() {} void nest(check_subcontracted_pre_post_inv* n) { nest_ = n; } template void operator()(B*) { typedef void result_type; - typedef boost::mpl::vector + typedef boost::mpl::vector arg_types; call( @@ -155,21 +170,14 @@ private: B const* base_obj = nest_->object(); BOOST_CONTRACT_AUX_DEBUG(base_obj); - boost::contract::call c(nest_->subcontracting_call_); - if(nest_->contract_call()) { - BOOST_CONTRACT_AUX_DEBUG(nest_->contract_call()->action == - c.call_->action); - c.call_ = nest_->contract_call(); // Use existing call. - } - try { - (base_obj->*base_func)(nest_->a0_, c); - } catch(boost::contract::aux::no_error const&) { - if(c.call_->action == boost::contract::aux::call::check_pre) { + (base_obj->*base_func)(nest_->a0_, nest_->c_); + } catch(no_error const&) { + if(nest_->c_.call_->action == call::check_pre) { throw; // Pre logic-or: 1st no_err stops (throw to caller). } } catch(...) { - if(c.call_->action == boost::contract::aux::call::check_pre) { + if(nest_->c_.call_->action == call::check_pre) { // Pre logic-or: Ignore err, possibly checks up to caller. } } @@ -178,9 +186,9 @@ private: check_subcontracted_pre_post_inv* nest_; }; - boost::shared_ptr subcontracting_call_; - check_base check_base_; - A0 const& a0_; + boost::contract::decl c_; // Copyable (as *). + check_base_class check_base_class_; // Copyable (as *). + A0 const& a0_; // TODO: Support configurable func arity. }; } } } // namespace diff --git a/include/boost/contract/aux_/function/bind.hpp b/include/boost/contract/aux_/function/bind.hpp deleted file mode 100644 index 3ae73c5..0000000 --- a/include/boost/contract/aux_/function/bind.hpp +++ /dev/null @@ -1,82 +0,0 @@ - -#ifndef BOOST_CONTRACT_AUX_BIND_HPP_ -#define BOOST_CONTRACT_AUX_BIND_HPP_ - -#include -#include -#include -#include -#include -/** @cond */ -#include -#include -/** @endcond */ - -namespace boost { namespace contract { namespace aux { - -template -class bind : // Shallow ptr copies or &. - public boost::contract::aux::check_nothing { -public: - explicit bind(F f, A0 const& a0, A1 const& a1) : - c_(boost::make_shared()), - f_(f), a0_(a0), a1_(a1) - { - execute(boost::contract::aux::call::copy_oldof); - execute(boost::contract::aux::call::check_entry_inv); - execute(boost::contract::aux::call::check_pre); - } - - ~bind() { - // Cannot check std::uncaught_exception here because it is up to - // specific function contract to check that and decide what to check if - // body threw (e.g., ctors do not check exit inv on throw but dtors do). - execute(boost::contract::aux::call::check_exit_inv); - execute(boost::contract::aux::call::check_post); - } - -private: - void execute(boost::contract::aux::call::action_enum a) { - c_.call_->action = a; - try { // Call contract decl func for given action. - call(boost::mpl::bool_::value>(), a0_, a1_); - } catch(boost::contract::aux::no_error&) { - // no_error exception used to signal OK (so just continue). - } // Else: If other exceptions, throw them to caller. - } - - // Overload dispatch to correct call: 1st arg determines if member call or - // not, other arguments determine arity when they are not none type. - - template - void call(boost::mpl::false_ const&, T0 const&, - boost::contract::aux::none const&) { - (*f_)(a0_, c_); - } - template - void call(boost::mpl::false_ const&, T0 const&, T1 const&) { - (*f_)(a0_, a1_, c_); - } - - template - void call(boost::mpl::true_ const&, T0 const&, - boost::contract::aux::none const&) { - (a0_->*f_)(c_); - } - template - void call(boost::mpl::true_ const&, T0 const&, T1 const&) { - (a0_->*f_)(a1_, c_); - } - - boost::contract::call c_; // Copy as ptr. - F f_; // Copy as func. ptr. - A0 const& a0_; // Object for member func ptrs, 1st func arg otherwise. - A1 const& a1_; -}; - - -} } } // namespace - -#endif // #include guard - diff --git a/include/boost/contract/aux_/function/constructor.hpp b/include/boost/contract/aux_/function/constructor.hpp index 4de8e78..cb9d2b2 100644 --- a/include/boost/contract/aux_/function/constructor.hpp +++ b/include/boost/contract/aux_/function/constructor.hpp @@ -29,7 +29,7 @@ private: void init() { // No object before ctor body so only static inv at entry. this->check_entry_inv(/* static_inv_only = */ true); - if(this->contract_call()) { // Throw no error (so not in dtor). + if(this->decl_call()) { // Throw no error (so not in dtor). this->check_exit_inv(/* static_inv_only = */ std::uncaught_exception()); } @@ -38,7 +38,7 @@ private: // Ctor pre checked by constructor_precondition at start of init list. void post_available() /* override */ { - if(this->contract_call() && !std::uncaught_exception()) { + if(this->decl_call() && !std::uncaught_exception()) { this->check_post(); // Throw no_error (so not in dtor). } } @@ -49,7 +49,7 @@ public: // automatically via C++ object constructor mechanism, so no calls to // check_subcontracted_... in this case). ~constructor() { - if(!this->contract_call()) { + if(!this->decl_call()) { this->check_exit_inv(/* static_inv_only = */ std::uncaught_exception()); if(!std::uncaught_exception()) this->check_post(); diff --git a/include/boost/contract/aux_/function/decl_free_function.hpp b/include/boost/contract/aux_/function/decl_free_function.hpp new file mode 100644 index 0000000..57b536f --- /dev/null +++ b/include/boost/contract/aux_/function/decl_free_function.hpp @@ -0,0 +1,57 @@ + +#ifndef BOOST_CONTRACT_AUX_BIND_FREE_FUNCTION_HPP_ +#define BOOST_CONTRACT_AUX_BIND_FREE_FUNCTION_HPP_ + +#include +#include +#include +#include +#include +/** @cond */ +#include +/** @endcond */ + +namespace boost { namespace contract { namespace aux { + +template +class decl_free_function : public check_base { // Copyable (as * and &). +public: + explicit decl_free_function(FPtr f, A0 const& a0, A1 const& a1) : + c_(boost::make_shared()), + f_(f), a0_(a0), a1_(a1) + { + execute(call::copy_oldof); + execute(call::check_pre); + } + + ~decl_free_function() { + execute(call::check_post); + } + +private: + void execute(call::action_enum a) { + c_.call_->action = a; + c_.call_->after_contract = false; + try { call(a0_, a1_); } + catch(no_error&) {} // Continue (no_error signals OK). + } + + void call(none const&, none const&) { (*f_)(c_); } + + template + void call(T0 const&, none const&) { (*f_)(a0_, c_); } + + template + void call(T0 const&, T1 const&) { (*f_)(a0_, a1_, c_); } + + boost::contract::decl c_; // Copyable as *. + FPtr f_; + A0 const& a0_; // TODO: Support configurable func arity. + A1 const& a1_; +}; + + +} } } // namespace + +#endif // #include guard + diff --git a/include/boost/contract/aux_/function/decl_member_function.hpp b/include/boost/contract/aux_/function/decl_member_function.hpp new file mode 100644 index 0000000..55cb52a --- /dev/null +++ b/include/boost/contract/aux_/function/decl_member_function.hpp @@ -0,0 +1,61 @@ + +#ifndef BOOST_CONTRACT_AUX_BIND_MEMBER_HPP_ +#define BOOST_CONTRACT_AUX_BIND_MEMBER_HPP_ + +#include +#include +#include +#include +#include +/** @cond */ +#include +/** @endcond */ + +namespace boost { namespace contract { namespace aux { + +template +class decl_member_function : public check_base { // Copyable (as * and &). +public: + explicit decl_member_function(FPtr f, C const* obj, A0 const& a0, + A1 const& a1) : + c_(boost::make_shared()), + f_(f), obj_(obj), a0_(a0), a1_(a1) + { + execute(call::copy_oldof); + execute(call::check_entry_inv); + execute(call::check_pre); + } + + ~decl_member_function() { + execute(call::check_exit_inv); + execute(call::check_post); + } + +private: + void execute(call::action_enum a) { + c_.call_->action = a; + c_.call_->after_contract = false; + try { call(a0_, a1_); } + catch(no_error&) {} // Continue (no_error signals OK). + } + + void call(none const&, none const&) { (obj_->*f_)(c_); } + + template + void call(T0 const&, none const&) { (obj_->*f_)(a0_, c_); } + + template + void call(T0 const&, T1 const&) { (obj_->*f_)(a0_, a1_, c_); } + + boost::contract::decl c_; // Copy as ptr. + FPtr f_; + C const* obj_; + A0 const& a0_; // TODO: Support configurable func arity. + A1 const& a1_; +}; + + +} } } // namespace + +#endif // #include guard + diff --git a/include/boost/contract/aux_/function/destructor.hpp b/include/boost/contract/aux_/function/destructor.hpp index 3754f1e..8ec67c1 100644 --- a/include/boost/contract/aux_/function/destructor.hpp +++ b/include/boost/contract/aux_/function/destructor.hpp @@ -31,7 +31,7 @@ private: // mechanism, so no calls to check_subcontracted_... in this case). void init() { this->check_entry_inv(); - if(this->contract_call()) { + if(this->decl_call()) { this->check_exit_inv(/* static_inv_only = */ !std::uncaught_exception()); } @@ -43,7 +43,7 @@ private: // NOTE: Even if there is no obj after dtor body, this library allows for // dtor post (e.g., to check static members for an instance counter class). void post_available() /* override */ { - if(this->contract_call() && !std::uncaught_exception()) { + if(this->decl_call() && !std::uncaught_exception()) { this->check_post(); } } @@ -57,7 +57,7 @@ public: // NOTE: In theory C++ destructors should not throw, but the language allows // for that so this library must handle such a case. ~destructor() { - if(!this->contract_call()) { + if(!this->decl_call()) { this->check_exit_inv(/* static_inv_only = */ !std::uncaught_exception()); if(!std::uncaught_exception()) this->check_post(); diff --git a/include/boost/contract/aux_/function/free_function.hpp b/include/boost/contract/aux_/function/free_function.hpp index 7b25a52..a02d478 100644 --- a/include/boost/contract/aux_/function/free_function.hpp +++ b/include/boost/contract/aux_/function/free_function.hpp @@ -3,8 +3,8 @@ #define BOOST_CONTRACT_AUX_FREE_FUNCTION_HPP_ #include -#include #include +#include /** @cond */ #include #include @@ -12,29 +12,26 @@ namespace boost { namespace contract { namespace aux { +// Also used for private and protected members. template -class basic_free_function : public boost::contract::aux::check_pre_post { +class basic_free_function : public check_pre_post { public: - explicit basic_free_function() : - boost::contract::aux::check_pre_post(From) {} + explicit basic_free_function() : check_pre_post(From) {} - explicit basic_free_function(boost::shared_ptr - call) : boost::contract::aux::check_pre_post(From, call) {} + explicit basic_free_function(boost::shared_ptr decl_call) : + check_pre_post(From, decl_call) {} private: void pre_available() /* override */ { check_pre(); } void post_available() /* override */ { - if(this->contract_call() && !std::uncaught_exception()) { - check_post(); // Throw no_error (so not in dtor). - } + // Throw no_error (so not in dtor). + if(this->decl_call() && !std::uncaught_exception()) check_post(); } public: ~basic_free_function() { - if(!this->contract_call() && !std::uncaught_exception()) { - check_post(); - } + if(!this->decl_call() && !std::uncaught_exception()) check_post(); } }; diff --git a/include/boost/contract/aux_/function/public_member.hpp b/include/boost/contract/aux_/function/public_member.hpp index c0cc134..d5157c2 100644 --- a/include/boost/contract/aux_/function/public_member.hpp +++ b/include/boost/contract/aux_/function/public_member.hpp @@ -31,14 +31,14 @@ private: this->copy_subcontracted_oldof(); this->check_subcontracted_entry_inv(); // Throw (so not in dtor). - if(this->contract_call()) this->check_subcontracted_exit_inv(); + if(this->decl_call()) this->check_subcontracted_exit_inv(); } void pre_available() /* override */ { this->check_subcontracted_pre(); } void post_available() /* override */ { // Body did not throw. - if(this->contract_call() && !std::uncaught_exception()) { + if(this->decl_call() && !std::uncaught_exception()) { // Throw no_error (so not in dtor). this->check_subcontracted_post(); } @@ -47,7 +47,7 @@ private: public: ~public_member() { // Body didn't throw. - if(!this->contract_call() && !std::uncaught_exception()) { + if(!this->decl_call() && !std::uncaught_exception()) { this->check_subcontracted_exit_inv(); this->check_subcontracted_post(); } diff --git a/include/boost/contract/bind.hpp b/include/boost/contract/bind.hpp deleted file mode 100644 index 7277fe2..0000000 --- a/include/boost/contract/bind.hpp +++ /dev/null @@ -1,35 +0,0 @@ - -#ifndef BOOST_CONTRACT_BIND_HPP_ -#define BOOST_CONTRACT_BIND_HPP_ - -/** @file */ - -#include -#include -#include -/** @cond */ -#include -/** @endcond */ - -namespace boost { namespace contract { - -// A0 is object ptr if F is member func ptr, 1st func arg otherwise. - -template -boost::contract::set_nothing bind(F f, A0 const& a0) { - return boost::contract::set_nothing(boost::make_shared< - boost::contract::aux::bind - >(f, a0, boost::contract::aux::none::value)); -} - -template -boost::contract::set_nothing bind(F f, A0 const& a0, A1 const& a1) { - return boost::contract::set_nothing(boost::make_shared< - boost::contract::aux::bind - >(f, a0, a1)); -} - -} } // namespace - -#endif // #include guard - diff --git a/include/boost/contract/constructor.hpp b/include/boost/contract/constructor.hpp index 7743ba3..03b742e 100644 --- a/include/boost/contract/constructor.hpp +++ b/include/boost/contract/constructor.hpp @@ -4,8 +4,8 @@ /** @file */ -#include -#include +#include +#include #include #include /** @cond */ @@ -15,15 +15,14 @@ namespace boost { namespace contract { template -boost::contract::set_postcondition constructor(boost::contract::call const& c, - C const* obj) { - return boost::contract::set_postcondition(boost::make_shared< +set_postcondition_only constructor(decl const& c, C const* obj) { + return set_postcondition_only(boost::make_shared< boost::contract::aux::constructor >(c.call_, obj)); } template -boost::contract::set_postcondition constructor(C const* obj) { - return boost::contract::set_postcondition(boost::make_shared< +set_postcondition_only constructor(C const* obj) { + return set_postcondition_only(boost::make_shared< boost::contract::aux::constructor >(obj)); } @@ -32,16 +31,10 @@ template struct constructor_precondition { constructor_precondition() {} // For user ctor overloads with no pre. - // TODO: All these F must be passed by const& because they could be complex - // functors with value captures and I don't want to copy these values - // multiple times. template - explicit constructor_precondition(F f) { + explicit constructor_precondition(F const& f) { try { f(); } - catch(...) { - boost::contract::precondition_failed( - boost::contract::from_constructor); - } + catch(...) { precondition_failed(from_constructor); } } }; diff --git a/include/boost/contract/core/call.hpp b/include/boost/contract/core/call.hpp deleted file mode 100644 index 82cb576..0000000 --- a/include/boost/contract/core/call.hpp +++ /dev/null @@ -1,76 +0,0 @@ - -#ifndef BOOST_CONTRACT_CALL_HPP_ -#define BOOST_CONTRACT_CALL_HPP_ - -/** @file */ - -#include -/** @cond */ -#include -/** @endcond */ - -namespace boost { - namespace contract { - class set_precondition_postcondition; - class set_postcondition; - - namespace aux { - template - class bind; - - template - class check_subcontracted_pre_post_inv; - } - } -} - -namespace boost { namespace contract { - -class call { -public: - // Nothing here (opaque object that users cannot directly use or create). - -private: // Friendship to minimize lib's public API. - friend bool copy_oldof(call const&); - friend class oldof; - - template - friend boost::contract::set_postcondition constructor( - call const&, C const*); - - template - friend boost::contract::set_postcondition destructor( - call const&, C const*); - - template - friend boost::contract::set_precondition_postcondition public_member( - call const&, C const*); - - friend boost::contract::set_precondition_postcondition protected_member( - call const&); - - friend boost::contract::set_precondition_postcondition private_member( - call const&); - - friend boost::contract::set_precondition_postcondition free_function( - call const&); - - template - friend class boost::contract::aux::bind; - - template - friend class boost::contract::aux::check_subcontracted_pre_post_inv; - - explicit call(boost::shared_ptr _call) : - call_(_call) {} - - call(call const& other) : call_(other.call_) {} // Shallow ptr copy. - call& operator=(call const&); // No copy operator. - - boost::shared_ptr call_; -}; - -} } // namespace - -#endif // #include guard - diff --git a/include/boost/contract/core/decl.hpp b/include/boost/contract/core/decl.hpp new file mode 100644 index 0000000..aaadfcf --- /dev/null +++ b/include/boost/contract/core/decl.hpp @@ -0,0 +1,83 @@ + +#ifndef BOOST_CONTRACT_DECL_HPP_ +#define BOOST_CONTRACT_DECL_HPP_ + +/** @file */ + +#include +/** @cond */ +#include +/** @endcond */ + +namespace boost { + namespace contract { + class set_precondition_postcondition; + class set_postcondition_only; + + namespace aux { + template + class check_subcontracted_pre_post_inv; + + template + class decl_free_function; + + template + class decl_member_function; + } + } +} + +namespace boost { namespace contract { + +class decl { +public: + // Nothing here (opaque object that users cannot directly use or create). + +private: + explicit decl(boost::shared_ptr call) : + call_(call) {} + + // TODO: DO I need the copy ctor? + decl(decl const& other) : call_(other.call_) {} // Shallow ptr copy. + decl& operator=(decl const&); // No copy operator. + + boost::shared_ptr call_; + + // Friendship used to limit lib's public API. + + friend bool copy_old(decl const&); + friend class old; + + template + friend set_postcondition_only constructor(decl const&, C const*); + + template + friend set_postcondition_only destructor(decl const&, C const*); + + template + friend set_precondition_postcondition public_member(decl const&, C const*); + + template + friend set_precondition_postcondition public_member(decl const&, C const*, + A0 const&); + + friend set_precondition_postcondition protected_member(decl const&); + + friend set_precondition_postcondition private_member(decl const&); + + friend set_precondition_postcondition free_function(decl const&); + + template + friend class boost::contract::aux::check_subcontracted_pre_post_inv; + + template + friend class boost::contract::aux::decl_free_function; + + template + friend class boost::contract::aux::decl_member_function; +}; + +} } // namespace + +#endif // #include guard + diff --git a/include/boost/contract/core/set_nothing.hpp b/include/boost/contract/core/set_nothing.hpp index bc576bd..8f799f9 100644 --- a/include/boost/contract/core/set_nothing.hpp +++ b/include/boost/contract/core/set_nothing.hpp @@ -4,31 +4,56 @@ /** @file */ -#include +#include /** @cond */ #include /** @endcond */ +namespace boost { + namespace contract { + class decl; + } +} + namespace boost { namespace contract { +// TODO: Make sure all friend declarations are at bottom of public if part of +// public API, or at bottom of private if part of private API. + class set_nothing { + // Friendship used to limit lib's public API. + friend class var; + friend class set_precondition_only; + friend class set_postcondition_only; + + friend set_nothing decl_function(void (* f)(decl)); + + template + friend set_nothing decl_function(A0 const&, void (* f)(A0 const&, decl)); + + template + friend set_nothing decl_function(A0 const&, A1 const&, + void (* f)(A0 const&, A1 const&, decl)); + + template + friend set_nothing decl_function(C const*, void (C::* f)(decl) const); + + template + friend set_nothing decl_function(C const*, A0 const&, + void (C::* f)(A0 const&, decl) const); + + template + friend set_nothing bind(C const*, A0 const&, A1 const&, + void (C::* f)(A0 const&, A1 const&, decl) const); + public: - // No set function member here. + // No set function members here. -private: // Friendship to minimize lib's public API. - friend class scoped; - friend class set_precondition; - friend class set_postcondition; +private: + explicit set_nothing(boost::shared_ptr< + boost::contract::aux::check_base> check) : check_(check) {} - template - friend set_nothing bind(F, A0 const&); - template - friend set_nothing bind(F, A0 const&, A1 const&); - - explicit set_nothing(boost::shared_ptr check) : check_(check) {} - - boost::shared_ptr check_; + boost::shared_ptr check_; }; } } // namespace diff --git a/include/boost/contract/core/set_postcondition.hpp b/include/boost/contract/core/set_postcondition.hpp deleted file mode 100644 index 44b1cb5..0000000 --- a/include/boost/contract/core/set_postcondition.hpp +++ /dev/null @@ -1,48 +0,0 @@ - -#ifndef BOOST_CONTRACT_SET_POSTCONDITION_HPP_ -#define BOOST_CONTRACT_SET_POSTCONDITION_HPP_ - -/** @file */ - -#include -#include -#include -/** @cond */ -#include -/** @endcond */ - -namespace boost { namespace contract { - -class set_postcondition { -public: - template - set_nothing postcondition(F f) { - check_->set_post(f); - return set_nothing(check_); - } - -private: // Friendship to minimize lib's public API. - friend class scoped; - friend class set_precondition_postcondition; - - template - friend set_postcondition constructor(C const*); - template - friend set_postcondition constructor(boost::contract::call const&, - C const*); - - template - friend set_postcondition destructor(C const*); - template - friend set_postcondition destructor(boost::contract::call const&, C const*); - - explicit set_postcondition(boost::shared_ptr check) : check_(check) {} - - boost::shared_ptr check_; -}; - -} } // namespace - -#endif // #include guard - diff --git a/include/boost/contract/core/set_postcondition_only.hpp b/include/boost/contract/core/set_postcondition_only.hpp new file mode 100644 index 0000000..abc9368 --- /dev/null +++ b/include/boost/contract/core/set_postcondition_only.hpp @@ -0,0 +1,52 @@ + +#ifndef BOOST_CONTRACT_SET_POSTCONDITION_HPP_ +#define BOOST_CONTRACT_SET_POSTCONDITION_HPP_ + +/** @file */ + +#include +#include +#include +/** @cond */ +#include +/** @endcond */ + +namespace boost { namespace contract { + +class set_postcondition_only { + // Friendship used to limit lib's public API. + friend class var; + friend class set_precondition_postcondition; + + template + friend set_postcondition_only constructor(C const*); + + template + friend set_postcondition_only constructor(decl const&, C const*); + + template + friend set_postcondition_only destructor(C const*); + + template + friend set_postcondition_only destructor(decl const&, C const*); + +public: + template + set_nothing postcondition(F const& f) { + check_->set_post(f); + return set_nothing(check_); + } + +private: + explicit set_postcondition_only(boost::shared_ptr< + boost::contract::aux::check_pre_post> check) : check_(check) {} + + // TODO: Can I use unique_ptr or some other smart ptr with less overhead + // than shared_ptr for old values, here, and everywhere? + boost::shared_ptr check_; +}; + +} } // namespace + +#endif // #include guard + diff --git a/include/boost/contract/core/set_precondition.hpp b/include/boost/contract/core/set_precondition_only.hpp similarity index 67% rename from include/boost/contract/core/set_precondition.hpp rename to include/boost/contract/core/set_precondition_only.hpp index 91fce89..c9d8e3e 100644 --- a/include/boost/contract/core/set_precondition.hpp +++ b/include/boost/contract/core/set_precondition_only.hpp @@ -12,20 +12,21 @@ namespace boost { namespace contract { -class set_precondition { +class set_precondition_only { + // Friendship used to limit lib's public API. + friend class var; + friend class set_precondition_postcondition; + public: template - set_nothing precondition(F f) { + set_nothing precondition(F const& f) { check_->set_pre(f); return set_nothing(check_); } -private: // Friendship to minimize lib's public API. - friend class scoped; - friend class set_precondition_postcondition; - - explicit set_precondition(boost::shared_ptr check) : check_(check) {} +private: + explicit set_precondition_only(boost::shared_ptr< + boost::contract::aux::check_pre_post> check) : check_(check) {} boost::shared_ptr check_; }; diff --git a/include/boost/contract/core/set_precondition_postcondition.hpp b/include/boost/contract/core/set_precondition_postcondition.hpp index 01973e4..2edaaf8 100644 --- a/include/boost/contract/core/set_precondition_postcondition.hpp +++ b/include/boost/contract/core/set_precondition_postcondition.hpp @@ -4,57 +4,63 @@ /** @file */ -#include -#include -#include +#include +#include +#include #include /** @cond */ #include /** @endcond */ namespace boost { namespace contract { + +// TODO: Read what's the best practise for namespace qualification... +// I can even write an example to test if concize namespace qualification +// gives problem when same func/class/typedef/etc in different namespaces. +// If so, I must always fully qualify... class set_precondition_postcondition { public: template - boost::contract::set_postcondition precondition(F f) { + set_postcondition_only precondition(F const& f) { check_->set_pre(f); - return boost::contract::set_postcondition(check_); + return set_postcondition_only(check_); } template - boost::contract::set_precondition postcondition(F f) { + set_precondition_only postcondition(F const& f) { check_->set_post(f); - return boost::contract::set_precondition(check_); + return set_precondition_only(check_); } -private: // Friendship to minimize lib's public API. - friend class scoped; - - // TODO: Read what's the best practise for namespace qualification... - - template - friend set_precondition_postcondition public_member(C const*, A0 const&); - template - friend set_precondition_postcondition public_member( - boost::contract::call const&, C const*); - - friend set_precondition_postcondition protected_member(); - friend set_precondition_postcondition protected_member( - boost::contract::call const&); - - friend set_precondition_postcondition private_member(); - friend set_precondition_postcondition private_member( - boost::contract::call const&); - - friend set_precondition_postcondition free_function(); - friend set_precondition_postcondition free_function( - boost::contract::call const&); - - explicit set_precondition_postcondition(boost::shared_ptr check) : check_(check) {} +private: + explicit set_precondition_postcondition(boost::shared_ptr< + boost::contract::aux::check_pre_post> check) : check_(check) {} boost::shared_ptr check_; + + // Friendship used to limit lib's public API. + + friend class var; + + template + friend set_precondition_postcondition public_member(decl const&, C const*); + + template + friend set_precondition_postcondition public_member(C const*, A0 const&); + + template + friend set_precondition_postcondition public_member(decl const&, C const*, + A0 const&); + + friend set_precondition_postcondition protected_member(); + friend set_precondition_postcondition protected_member(decl const&); + + friend set_precondition_postcondition private_member(); + friend set_precondition_postcondition private_member(decl const&); + + friend set_precondition_postcondition free_function(); + friend set_precondition_postcondition free_function(decl const&); }; } } // namespace diff --git a/include/boost/contract/decl_function.hpp b/include/boost/contract/decl_function.hpp new file mode 100644 index 0000000..520b3ef --- /dev/null +++ b/include/boost/contract/decl_function.hpp @@ -0,0 +1,92 @@ + +#ifndef BOOST_CONTRACT_DECL_FUNCTION_HPP_ +#define BOOST_CONTRACT_DECL_FUNCTION_HPP_ + +/** @file */ + +#include +#include +#include +#include +#include +/** @cond */ +#include +/** @endcond */ + +namespace boost { namespace contract { + +// NOTE: `f` last arg otherwise some compilers (MSVC) cannot always deduce it. + +// TODO: Support configurable function arity. + +// Free function. + +set_nothing decl_function(void (* f)(decl)) { + return set_nothing(boost::make_shared< + boost::contract::aux::decl_free_function< + void (*)(decl), + boost::contract::aux::none, boost::contract::aux::none + > + >(f, boost::contract::aux::none::value, boost::contract::aux::none::value)); +} + +template +set_nothing decl_function(A0 const& a0, void (* f)(A0 const&, decl)) { + return set_nothing(boost::make_shared< + boost::contract::aux::decl_free_function< + void (*)(A0 const&, decl), + A0, boost::contract::aux::none + > + >(f, a0, boost::contract::aux::none::value)); +} + +template +set_nothing decl_function(A0 const& a0, A1 const& a1, + void (* f)(A0 const&, A1 const&, decl)) { + return set_nothing(boost::make_shared< + boost::contract::aux::decl_free_function< + void (*)(A0 const&, A1 const&, decl), + A0, A1 + > + >(f, a0, a1)); +} + +// Member function (constructor and destructor included). + +template +set_nothing decl_function(C const* obj, void (C::* f)(decl) const) { + return set_nothing(boost::make_shared< + boost::contract::aux::decl_member_function< + void (C::*)(decl) const, + C, boost::contract::aux::none, boost::contract::aux::none + > + >(f, obj, boost::contract::aux::none::value, + boost::contract::aux::none::value)); +} + +template +set_nothing decl_function(C const* obj, A0 const& a0, + void (C::* f)(A0 const&, decl) const) { + return set_nothing(boost::make_shared< + boost::contract::aux::decl_member_function< + void (C::*)(A0 const&, decl) const, + C, A0, boost::contract::aux::none + > + >(f, obj, a0, boost::contract::aux::none::value)); +} + +template +set_nothing decl_function(C const* obj, A0 const& a0, A1 const& a1, + void (C::* f)(A0 const&, A1 const&, decl) const) { + return set_nothing(boost::make_shared< + boost::contract::aux::decl_member_function< + void (C::*)(A0 const&, A1 const&, decl) const, + C, A0, A1 + > + >(f, obj, a0, a1)); +} + +} } // namespace + +#endif // #include guard + diff --git a/include/boost/contract/destructor.hpp b/include/boost/contract/destructor.hpp index 233b5da..8d161a0 100644 --- a/include/boost/contract/destructor.hpp +++ b/include/boost/contract/destructor.hpp @@ -4,8 +4,8 @@ /** @file */ -#include -#include +#include +#include #include /** @cond */ #include @@ -14,15 +14,14 @@ namespace boost { namespace contract { template -boost::contract::set_postcondition destructor(C const* obj) { - return boost::contract::set_postcondition(boost::make_shared< +set_postcondition_only destructor(C const* obj) { + return set_postcondition_only(boost::make_shared< boost::contract::aux::destructor >(obj)); } template -boost::contract::set_postcondition destructor(boost::contract::call const& c, - C const* obj) { - return boost::contract::set_postcondition(boost::make_shared< +set_postcondition_only destructor(decl const& c, C const* obj) { + return set_postcondition_only(boost::make_shared< boost::contract::aux::destructor >(c.call_, obj)); } diff --git a/include/boost/contract/free_function.hpp b/include/boost/contract/free_function.hpp index dd0b30e..d439319 100644 --- a/include/boost/contract/free_function.hpp +++ b/include/boost/contract/free_function.hpp @@ -5,7 +5,7 @@ /** @file */ #include -#include +#include #include /** @cond */ #include @@ -19,7 +19,7 @@ boost::contract::set_precondition_postcondition free_function() { } boost::contract::set_precondition_postcondition free_function( - boost::contract::call const& c) { + boost::contract::decl const& c) { return boost::contract::set_precondition_postcondition(boost::make_shared< boost::contract::aux::free_function>(c.call_)); } diff --git a/include/boost/contract/oldof.hpp b/include/boost/contract/oldof.hpp index 9f7d3b9..c5e5647 100644 --- a/include/boost/contract/oldof.hpp +++ b/include/boost/contract/oldof.hpp @@ -4,7 +4,7 @@ /** @file */ -#include +#include #include #include /** @cond */ @@ -42,14 +42,14 @@ BOOST_CONTRACT_ERROR_macro_OLDOF_has_invalid_number_of_arguments_, \ #define BOOST_CONTRACT_ERROR_macro_OLDOF_has_invalid_number_of_arguments_1( \ value) \ - BOOST_CONTRACT_OLDOF_AUTO_(value)(boost::contract::oldof( \ - boost::contract::copy_oldof() ? (value) : boost::contract::oldof() \ + BOOST_CONTRACT_OLDOF_AUTO_(value)(boost::contract::old( \ + boost::contract::copy_old() ? (value) : boost::contract::old() \ )) #define BOOST_CONTRACT_ERROR_macro_OLDOF_has_invalid_number_of_arguments_2( \ c, value) \ - BOOST_CONTRACT_OLDOF_AUTO_(value)(boost::contract::oldof(c, \ - boost::contract::copy_oldof(c) ? (value) : boost::contract::oldof() \ + BOOST_CONTRACT_OLDOF_AUTO_(value)(boost::contract::old(c, \ + boost::contract::copy_old(c) ? (value) : boost::contract::old() \ )) #ifdef BOOST_NO_CXX11_AUTO_DECLARATIONS @@ -69,7 +69,7 @@ BOOST_CONTRACT_ERROR_macro_OLDOF_has_invalid_number_of_arguments_, \ namespace boost { namespace contract { -bool copy_oldof() { +bool copy_old() { #ifdef BOOST_CONTRACT_CONFIG_NO_POSTCONDITIONS return false; // Post checking disabled, so never copy old values. #else @@ -77,7 +77,7 @@ bool copy_oldof() { #endif } -bool copy_oldof(boost::contract::call const& c) { +bool copy_old(decl const& c) { #ifdef BOOST_CONTRACT_CONFIG_NO_POSTCONDITIONS return false; // Post checking disabled, so never copy old values. #else @@ -85,15 +85,15 @@ bool copy_oldof(boost::contract::call const& c) { #endif } -class oldof { +class old { public: - explicit oldof() : call_(), value_() {} + explicit old() : decl_call_(), value_() {} - explicit oldof(boost::contract::call const& c, oldof const& old) : - call_(c.call_), value_(old.value_) {} + explicit old(decl const& c, old const& other) : + decl_call_(c.call_), value_(other.value_) {} template - /* implicit */ oldof(T const& old_value) : + /* implicit */ old(T const& old_value) : value_(boost::make_shared(old_value)) { // T's one single copy. } @@ -103,21 +103,23 @@ public: template operator boost::shared_ptr() { - if(!call_) { + if(!decl_call_) { BOOST_CONTRACT_AUX_DEBUG(value_); boost::shared_ptr old_value = boost::static_pointer_cast(value_); BOOST_CONTRACT_AUX_DEBUG(old_value); return old_value; - } else if(call_->action == boost::contract::aux::call::copy_oldof) { + } else if(decl_call_->action == + boost::contract::aux::call::copy_oldof) { BOOST_CONTRACT_AUX_DEBUG(value_); - call_->old_values.push(value_); + decl_call_->old_values.push(value_); return boost::shared_ptr(); - } else if(call_->action == boost::contract::aux::call::check_post) { + } else if(decl_call_->action == + boost::contract::aux::call::check_post) { BOOST_CONTRACT_AUX_DEBUG(!value_); - boost::shared_ptr value = call_->old_values.front(); + boost::shared_ptr value = decl_call_->old_values.front(); BOOST_CONTRACT_AUX_DEBUG(value); - call_->old_values.pop(); + decl_call_->old_values.pop(); boost::shared_ptr old_value = boost::static_pointer_cast(value); BOOST_CONTRACT_AUX_DEBUG(old_value); @@ -128,7 +130,7 @@ public: } private: - boost::shared_ptr call_; + boost::shared_ptr decl_call_; boost::shared_ptr value_; }; diff --git a/include/boost/contract/public_member.hpp b/include/boost/contract/public_member.hpp index 320f9fa..b57db82 100644 --- a/include/boost/contract/public_member.hpp +++ b/include/boost/contract/public_member.hpp @@ -4,8 +4,8 @@ /** @file */ -#include #include +#include #include #include /** @cond */ @@ -14,31 +14,40 @@ namespace boost { namespace contract { -template -boost::contract::set_precondition_postcondition public_member( - boost::contract::call const& c, C const* obj) { - return boost::contract::set_precondition_postcondition(boost::make_shared< - boost::contract::aux::public_member - >(c.call_, obj, boost::contract::aux::none::value)); -} +// TODO: Support configurable function arity. template -boost::contract::set_precondition_postcondition public_member(C const* obj) { - return boost::contract::set_precondition_postcondition(boost::make_shared< +set_precondition_postcondition public_member(C const* obj) { + return set_precondition_postcondition(boost::make_shared< boost::contract::aux::public_member >(obj, boost::contract::aux::none::value)); } +template +set_precondition_postcondition public_member(decl const& c, C const* obj) { + return set_precondition_postcondition(boost::make_shared< + boost::contract::aux::public_member + >(c.call_, obj, boost::contract::aux::none::value)); +} + template -boost::contract::set_precondition_postcondition public_member(C const* obj, +set_precondition_postcondition public_member(C const* obj, A0 const& a0) { - return boost::contract::set_precondition_postcondition(boost::make_shared< + return set_precondition_postcondition(boost::make_shared< boost::contract::aux::public_member >(obj, a0)); } +template +set_precondition_postcondition public_member(decl const& c, C const* obj, + A0 const& a0) { + return set_precondition_postcondition(boost::make_shared< + boost::contract::aux::public_member + >(c.call_, obj, a0)); +} + } } // namespace #endif // #include guard diff --git a/include/boost/contract/scoped.hpp b/include/boost/contract/scoped.hpp deleted file mode 100644 index 56c1bf5..0000000 --- a/include/boost/contract/scoped.hpp +++ /dev/null @@ -1,41 +0,0 @@ - -#ifndef BOOST_CONTRACT_SCOPED_HPP_ -#define BOOST_CONTRACT_SCOPED_HPP_ - -/** @file */ - -#include -#include -#include -#include -#include -/** @cond */ -#include -/** @endcond */ - -namespace boost { namespace contract { - -class scoped { // Copyable (shallow shared ptr copies). -public: - // All implicit to allow `scoped c = ...`. - - /* implicit */ scoped(boost::contract::set_precondition_postcondition - const& contract) : check_(contract.check_) {} - - /* implicit */ scoped(boost::contract::set_precondition - const& contract) : check_(contract.check_) {} - - /* implicit */ scoped(boost::contract::set_postcondition - const& contract) : check_(contract.check_) {} - - /* implicit */ scoped(boost::contract::set_nothing - const& contract) : check_(contract.check_) {} - -private: - boost::shared_ptr check_; -}; - -} } // namespace - -#endif // #include guard - diff --git a/include/boost/contract/var.hpp b/include/boost/contract/var.hpp new file mode 100644 index 0000000..76dde69 --- /dev/null +++ b/include/boost/contract/var.hpp @@ -0,0 +1,41 @@ + +#ifndef BOOST_CONTRACT_VAR_HPP_ +#define BOOST_CONTRACT_VAR_HPP_ + +/** @file */ + +#include +#include +#include +#include +#include +/** @cond */ +#include +/** @endcond */ + +namespace boost { namespace contract { + +class var { // Copyable (as shallow *). +public: + // All implicit to allow `var contract = ...`. + + /* implicit */ var(set_precondition_postcondition const& contract) : + check_(contract.check_) {} + + /* implicit */ var(set_precondition_only const& contract) : + check_(contract.check_) {} + + /* implicit */ var(set_postcondition_only const& contract) : + check_(contract.check_) {} + + /* implicit */ var(set_nothing const& contract) : + check_(contract.check_) {} + +private: + boost::shared_ptr check_; +}; + +} } // namespace + +#endif // #include guard + diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index 9fb8ff9..03578fc 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -1,4 +1,24 @@ -subdir-run constructor : bases ; +subdir-run constructor : bases ; +subdir-run constructor : bases_decl ; +subdir-run constructor : overload ; +subdir-run constructor : overload_decl ; subdir-compile-fail constructor : no_pre-error ; +subdir-run destructor : bases ; +subdir-run destructor : bases_decl ; +subdir-compile-fail destructor : no_pre-error ; + +subdir-run public_member : bases ; + +subdir-run free_function : pre_post ; +subdir-run free_function : pre_post_decl ; +subdir-run free_function : post_pre ; +subdir-run free_function : pre_only ; +subdir-run free_function : post_only ; +subdir-run free_function : nothing ; +subdir-compile-fail free_function : pre_pre-error ; +subdir-compile-fail free_function : post_post-error ; +subdir-compile-fail free_function : pre_post_pre-error ; +subdir-compile-fail free_function : post_pre_post-error ; + diff --git a/test/aux_/cpcnt.hpp b/test/aux_/cpcnt.hpp index 6c3234b..5e2a100 100644 --- a/test/aux_/cpcnt.hpp +++ b/test/aux_/cpcnt.hpp @@ -1,30 +1,30 @@ -#ifndef BOOST_CONTRACT_AUX_TEST_OLD_HPP_ -#define BOOST_CONTRACT_AUX_TEST_OLD_HPP_ +#ifndef BOOST_CONTRACT_AUX_TEST_CPCNT_HPP_ +#define BOOST_CONTRACT_AUX_TEST_CPCNT_HPP_ namespace boost { namespace contract { namespace aux { namespace test { -// Helper to test old values only evaluated and copied once by OLDOF. +// Helper to count copies and evaluations of type (e.g., for old values). template -struct old { +struct cpcnt { T value; - old() : value() {} + cpcnt() : value() {} - old(old const& other) : value(other.value) { ++copies_; } - static old const& eval(old const& me) { ++me.evals_; return me; } + cpcnt(cpcnt const& other) : value(other.value) { ++copies_; } + static cpcnt const& eval(cpcnt const& me) { ++me.evals_; return me; } static unsigned copies() { return copies_; } static unsigned evals() { return evals_; } private: - old& operator=(old const&) /* = delete */; + cpcnt& operator=(cpcnt const&) /* = delete */; static unsigned copies_; static unsigned evals_; }; -template unsigned old::copies_ = 0; -template unsigned old::evals_ = 0; +template unsigned cpcnt::copies_ = 0; +template unsigned cpcnt::evals_ = 0; } } } } // namespace diff --git a/test/aux_/friend.hpp b/test/aux_/friend.hpp deleted file mode 100644 index 74d3c69..0000000 --- a/test/aux_/friend.hpp +++ /dev/null @@ -1,21 +0,0 @@ - -#ifndef BOOST_CONTRACT_AUX_TEST_FRIEND_HPP_ -#define BOOST_CONTRACT_AUX_TEST_FRIEND_HPP_ - -#include - -namespace boost { namespace contract { namespace aux { namespace test { - -// Made friend by a few library's types to access them to test them. -class friend_ { -public: - static bool checking_post(boost::contract::virtual_* v) { - return !v || v->action_ == boost::contract::virtual_::check_post || - v->action_ == boost::contract::virtual_::check_this_post; - } -}; - -} } } } // namespace - -#endif // #include guard - diff --git a/test/aux_/oteststream.hpp b/test/aux_/oteststream.hpp index a011893..0125d89 100644 --- a/test/aux_/oteststream.hpp +++ b/test/aux_/oteststream.hpp @@ -35,8 +35,7 @@ struct oteststream : std::string str() const { return oss_.str(); } void str(std::string const& s) { oss_.str(s); } - // If found, display mismatching characters. - bool check(std::string const& s) { + bool eq(std::string const& s) { // Also display mismatching characters. std::string r = str(); std::string::size_type i = 0; for(; i < r.size() && i < s.size(); ++i) if(r[i] != s[i]) break; diff --git a/test/const/constructor.cpp b/test/const/constructor.cpp deleted file mode 100755 index 6ba205d..0000000 --- a/test/const/constructor.cpp +++ /dev/null @@ -1,96 +0,0 @@ - -#include -#include -#include -#include -#include -#include -#include - -struct b - #define BASES private boost::contract::constructor_precondition - : BASES -{ - typedef BOOST_CONTRACT_BASE_TYPES(BASES) base_types; - #undef BASES - - void invariant() const { std::clog << "b::inv" << std::endl; } - static void static_invariant() { - std::clog << "b::static_inv" << std::endl; - } - - int y; - - static void b_precondition(int const j) { - std::clog << "b::ctor::pre" << std::endl; - BOOST_CONTRACT_ASSERT(j > 0); - } - void b_contract(int const j, boost::contract::call c) const { - boost::shared_ptr old_j = BOOST_CONTRACT_OLDOF(c, j); - boost::contract::constructor(c, this) - .postcondition([&] { - std::clog << "b::ctor::post" << std::endl; - BOOST_CONTRACT_ASSERT(y == *old_j); - BOOST_CONTRACT_ASSERT(j == -2); - }) - ; - } - explicit b(int& j) : - boost::contract::constructor_precondition( - boost::bind(&b::b_precondition, j)) - { - boost::contract::scoped contract = boost::contract::bind( - &b::b_contract, this, j); - std::clog << "b::ctor::body" << std::endl; - y = j; - j = -2; - } -}; - -struct a - #define BASES private boost::contract::constructor_precondition, public b - : BASES -{ - typedef BOOST_CONTRACT_BASE_TYPES(BASES) base_types; - #undef BASES - - void invariant() const { std::clog << "a::inv" << std::endl; } - static void static_invariant() { - std::clog << "a::static_inv" << std::endl; - } - - int x; - - static void a_precondition(int const i) { - std::clog << "a::ctor::pre" << std::endl; - BOOST_CONTRACT_ASSERT(i > 0); - } - void a_contract(int const i, boost::contract::call c) const { - boost::shared_ptr old_i = BOOST_CONTRACT_OLDOF(c, i); - boost::contract::constructor(c, this) - .postcondition([&] { - std::clog << "a::ctor::post" << std::endl; - BOOST_CONTRACT_ASSERT(x == *old_i); - BOOST_CONTRACT_ASSERT(i == -1); - }) - ; - } - explicit a(int& i) : - boost::contract::constructor_precondition( - boost::bind(&a::a_precondition, i)), - b(i) - { - boost::contract::scoped contract = boost::contract::bind( - &a::a_contract, this, i); - std::clog << "a::ctor::body" << std::endl; - x = i; - i = -1; - } -}; - -int main() { - int i = 123; - a aa(i); - return 0; -} - diff --git a/test/const/destructor.cpp b/test/const/destructor.cpp deleted file mode 100755 index 203dafd..0000000 --- a/test/const/destructor.cpp +++ /dev/null @@ -1,75 +0,0 @@ - -#include -#include -#include -#include -#include -#include - -struct b { - void invariant() const { std::clog << "b::inv" << std::endl; } - static void static_invariant() { - std::clog << "b::static_inv" << std::endl; - BOOST_CONTRACT_ASSERT(y >= 0); - } - - static int y; - b() { ++y; } - - void dtor_contract(boost::contract::call c) const { - boost::shared_ptr old_y = BOOST_CONTRACT_OLDOF(c, y); - boost::contract::destructor(c, this) - .postcondition([&] { - std::clog << "b::dtor::post" << std::endl; - BOOST_CONTRACT_ASSERT(y == *old_y - 1); - }) - ; - } - virtual ~b() { - boost::contract::scoped contract = boost::contract::bind( - &b::dtor_contract, this); - std::clog << "b::dtor::body" << std::endl; - --y; - } -}; -int b::y = 0; - -struct a - #define BASES public b - : BASES -{ - typedef BOOST_CONTRACT_BASE_TYPES(BASES) base_types; - #undef BASES - - void invariant() const { std::clog << "a::inv" << std::endl; } - static void static_invariant() { - std::clog << "a::static_inv" << std::endl; - BOOST_CONTRACT_ASSERT(x >= 0); - } - - static int x; - a() { ++x; } - - void dtor_contract(boost::contract::call c) const { - boost::shared_ptr old_x = BOOST_CONTRACT_OLDOF(c, x); - boost::contract::destructor(c, this) - .postcondition([&] { - std::clog << "a::dtor::post" << std::endl; - BOOST_CONTRACT_ASSERT(x == *old_x - 1); - }) - ; - } - ~a() { - boost::contract::scoped contract = boost::contract::bind( - &a::dtor_contract, this); - std::clog << "a::dtor::body" << std::endl; - --x; - } -}; -int a::x = 0; - -int main() { - a aa; - return 0; -} - diff --git a/test/const/free_function.cpp b/test/const/free_function.cpp deleted file mode 100644 index bd78ffa..0000000 --- a/test/const/free_function.cpp +++ /dev/null @@ -1,66 +0,0 @@ - -#include -#include -#include -#include -#include -#include -#include - -void inv1_contract(int const& x, int const& result, boost::contract::call c) { - boost::shared_ptr old_x = BOOST_CONTRACT_OLDOF(c, x); - boost::contract::free_function(c) - .precondition([&] { - std::clog << "inv1::pre" << std::endl; - BOOST_CONTRACT_ASSERT(x >= 0); - }) - .postcondition([&] { - std::clog << "inv1::post" << std::endl; - BOOST_CONTRACT_ASSERT(-x == *old_x); - BOOST_CONTRACT_ASSERT(result == *old_x); - }) - ; -} -int inv1(int& x) { - std::clog << "inv1" << std::endl; - int result; - boost::contract::scoped contract = boost::contract::bind( - &inv1_contract, x, result); - - std::clog << "inv1::body" << std::endl; - result = x; - x = -x; - return result; -} - -int inv2(int& x) { - int result; - boost::shared_ptr old_x = BOOST_CONTRACT_OLDOF(x); - boost::contract::scoped contract = boost::contract::free_function() - .precondition([&] { - std::clog << "inv2::pre" << std::endl; - BOOST_CONTRACT_ASSERT(x >= 0); - }) - .postcondition([&] { - std::clog << "inv2::post" << std::endl; - BOOST_CONTRACT_ASSERT(-x == *old_x); - BOOST_CONTRACT_ASSERT(result == *old_x); - }) - ; - - std::clog << "inv2::body" << std::endl; - result = x; - x = -x; - return result; -} - -int main() { - int x = 123; - inv1(x); - std::clog << std::endl; - - x = 456; - inv2(x); - return 0; -} - diff --git a/test/const/private_member.cpp b/test/const/private_member.cpp deleted file mode 100644 index a10b949..0000000 --- a/test/const/private_member.cpp +++ /dev/null @@ -1,80 +0,0 @@ - -#include -#include -#include -#include -#include -#include -#include -#include - -struct b { - std::string y; - b() : y("b") {} - - void invariant() const { std::clog << "b::inv" << std::endl; } - static void static_invariant() { std::clog << "b::static_inv" << std::endl;} - - // Test base contract not checked. -private: - void f_contract(std::string const& s, boost::contract::call c) const { - boost::shared_ptr old_y = BOOST_CONTRACT_OLDOF(c, y); - boost::contract::private_member(c) - .precondition([&] { std::clog << "b::f::pre" << std::endl; }) - .postcondition([&] { - std::clog << "b::f::post" << std::endl; - BOOST_CONTRACT_ASSERT(y == *old_y + s); - }) - ; - } - void f(std::string const& s) { - boost::contract::scoped contract = boost::contract::bind( - &b::f_contract, this, s); - std::clog << "b::f::body" << std::endl; - y = y + s; - } -}; - -struct a - #define BASES public b - : BASES -{ - typedef BOOST_CONTRACT_BASE_TYPES(BASES) base_types; - #undef BASES - - std::string x; - a() : x("a") {} - - // Test invariants not checked. - void invariant() const { std::clog << "a::inv" << std::endl; } - static void static_invariant() { std::clog << "a::static_inv" << std::endl;} - -private: - void f_contract(std::string const& s, boost::contract::call c) { - boost::shared_ptr old_x = BOOST_CONTRACT_OLDOF(c, x); - boost::contract::private_member(c) - .precondition([&] { std::clog << "a::f::pre" << std::endl; }) - .postcondition([&] { - std::clog << "a::f::post" << std::endl; - BOOST_CONTRACT_ASSERT(x == *old_x + s); - }) - ; - } - void f(std::string const& s) { - boost::contract::scoped contract = boost::contract::bind( - &a::f_contract, this, s); - std::clog << "a::f::body" << std::endl; - y = y + s; - x = x + s; - } - -public: - void call_f(std::string const& s) { f(s); } -}; - -int main() { - a aa; - aa.call_f("s"); - return 0; -} - diff --git a/test/const/protected_member.cpp b/test/const/protected_member.cpp deleted file mode 100644 index f987f3f..0000000 --- a/test/const/protected_member.cpp +++ /dev/null @@ -1,80 +0,0 @@ - -#include -#include -#include -#include -#include -#include -#include -#include - -struct b { - std::string y; - b() : y("b") {} - - void invariant() const { std::clog << "b::inv" << std::endl; } - static void static_invariant() { std::clog << "b::static_inv" << std::endl;} - - // Test base contract not checked. -protected: - void f_contract(std::string const& s, boost::contract::call c) const { - boost::shared_ptr old_y = BOOST_CONTRACT_OLDOF(c, y); - boost::contract::protected_member(c) - .precondition([&] { std::clog << "b::f::pre" << std::endl; }) - .postcondition([&] { - std::clog << "b::f::post" << std::endl; - BOOST_CONTRACT_ASSERT(y == *old_y + s); - }) - ; - } - virtual void f(std::string const& s) { - boost::contract::scoped contract = boost::contract::bind( - &b::f_contract, this, s); - std::clog << "b::f::body" << std::endl; - y = y + s; - } -}; - -struct a - #define BASES public b - : BASES -{ - typedef BOOST_CONTRACT_BASE_TYPES(BASES) base_types; - #undef BASES - - std::string x; - a() : x("a") {} - - // Test invariants not checked. - void invariant() const { std::clog << "a::inv" << std::endl; } - static void static_invariant() { std::clog << "a::static_inv" << std::endl;} - -protected: - void f_contract(std::string const& s, boost::contract::call c) { - boost::shared_ptr old_x = BOOST_CONTRACT_OLDOF(c, x); - boost::contract::protected_member(c) - .precondition([&] { std::clog << "a::f::pre" << std::endl; }) - .postcondition([&] { - std::clog << "a::f::post" << std::endl; - BOOST_CONTRACT_ASSERT(x == *old_x + s); - }) - ; - } - void f(std::string const& s) /* override */ { - boost::contract::scoped contract = boost::contract::bind( - &a::f_contract, this, s); - std::clog << "a::f::body" << std::endl; - y = y + s; - x = x + s; - } - -public: - void call_f(std::string const& s) { f(s); } -}; - -int main() { - a aa; - aa.call_f("s"); - return 0; -} - diff --git a/test/const/public_member.cpp b/test/const/public_member.cpp deleted file mode 100644 index 97b3449..0000000 --- a/test/const/public_member.cpp +++ /dev/null @@ -1,53 +0,0 @@ - -#include -#include -#include -#include -#include -#include - -struct a { - int x; - - void invariant() const { - std::clog << "a::inv" << std::endl; - BOOST_CONTRACT_ASSERT(x > 0); - } - static void static_invariant() { - std::clog << "a::static_inv" << std::endl; - } - - void swap_contract(int const& y, boost::contract::call c) const { - boost::shared_ptr old_x = BOOST_CONTRACT_OLDOF(c, x); - boost::shared_ptr old_y = BOOST_CONTRACT_OLDOF(c, y); - boost::contract::public_member(c, this) - .precondition([&] { - std::clog << "a::swap::pre" << std::endl; - BOOST_CONTRACT_ASSERT(x != y); - }) - .postcondition([&] { - std::clog << "a::swap::post" << std::endl; - BOOST_CONTRACT_ASSERT(x == *old_y); - BOOST_CONTRACT_ASSERT(y == *old_x); - }) - ; - } - void swap(int& y) { - boost::contract::scoped contract = boost::contract::bind( - &a::swap_contract, this, y); - - std::clog << "a::swap::body" << std::endl; - int save_x = x; - x = y; - y = save_x; - } -}; - -int main() { - a aa; - aa.x = 10; - int y = 20; - aa.swap(y); - return 0; -} - diff --git a/test/const/public_virtual_member.cpp b/test/const/public_virtual_member.cpp deleted file mode 100644 index d55fcf1..0000000 --- a/test/const/public_virtual_member.cpp +++ /dev/null @@ -1,74 +0,0 @@ - -#include -#include -#include -#include -#include -#include -#include -#include - -struct b { - std::string y; - b() : y("b") {} - - void invariant() const { std::clog << "b::inv" << std::endl; } - static void static_invariant() { std::clog << "b::static_inv" << std::endl;} - - // virtual => ..._contract - void f_contract(std::string const& s, boost::contract::call c) const { - boost::shared_ptr old_y = BOOST_CONTRACT_OLDOF(c, y); - boost::contract::public_member(c, this) - .precondition([&] { std::clog << "b::f::pre" << std::endl; }) - .postcondition([&] { - std::clog << "b::f::post" << std::endl; - BOOST_CONTRACT_ASSERT(y == *old_y + s); - }) - ; - } - virtual void f(std::string const& s) { - boost::contract::scoped contract = boost::contract::bind( - &b::f_contract, this, s); - std::clog << "b::f::body" << std::endl; - y = y + s; - } -}; - -struct a - #define BASES public b - : BASES -{ - typedef BOOST_CONTRACT_BASE_TYPES(BASES) base_types; - #undef BASES - - std::string x; - a() : x("a") {} - - void invariant() const { std::clog << "a::inv" << std::endl; } - static void static_invariant() { std::clog << "a::static_inv" << std::endl;} - - // override => introspect_... - void f(std::string const& s) /* override */ { - boost::shared_ptr old_x = BOOST_CONTRACT_OLDOF(x); - boost::contract::scoped contract = boost::contract::public_member< - introspect_f_contract>(this, s) - .precondition([&] { std::clog << "a::f::pre" << std::endl; }) - .postcondition([&] { - std::clog << "a::f::post" << std::endl; - BOOST_CONTRACT_ASSERT(x == *old_x + s); - }) - ; - - std::clog << "a::f::body" << std::endl; - y = y + s; - x = x + s; - } - BOOST_CONTRACT_INTROSPECT(f_contract) -}; - -int main() { - a aa; - aa.f("s"); - return 0; -} - diff --git a/test/constructor/bases.cpp b/test/constructor/bases.cpp index cab53f3..80ead12 100644 --- a/test/constructor/bases.cpp +++ b/test/constructor/bases.cpp @@ -1,18 +1,18 @@ +// Test constructor subcontracting. + #include "../aux_/oteststream.hpp" -#include "../aux_/old.hpp" +#include "../aux_/cpcnt.hpp" #include #include #include #include -#include +#include #include #include #include #include -// Test constructor subcontracting. - boost::contract::aux::test::oteststream out; template @@ -25,46 +25,51 @@ struct t void invariant() const { out << Id << "::inv" << std::endl; - BOOST_CONTRACT_ASSERT(x_ < 0); + BOOST_CONTRACT_ASSERT(i_ < 0); } static void static_invariant() { out << Id << "::static_inv" << std::endl; - BOOST_CONTRACT_ASSERT(i_ >= 0); + BOOST_CONTRACT_ASSERT(n.value >= 0); } + struct n_tag; typedef boost::contract::aux::test::cpcnt n_cnt; + static n_cnt n; + struct arg_tag; - typedef boost::contract::aux::test::old arg_type; + typedef boost::contract::aux::test::cpcnt arg_cnt; // MSVC 2010 errors on lambdas in template member initializations... - static void t_precondition(arg_type const& arg) { + static void constructor_precondition(arg_cnt const& arg) { out << Id << "::ctor::pre" << std::endl; BOOST_CONTRACT_ASSERT(arg.value < 0); } - explicit t(arg_type& arg) : + explicit t(arg_cnt& arg) : boost::contract::constructor_precondition >( - boost::bind(&t::t_precondition, boost::cref(arg))) + boost::bind(&t::constructor_precondition, boost::cref(arg))) { - boost::shared_ptr old_arg = - BOOST_CONTRACT_OLDOF(arg_type::eval(arg)); - boost::contract::scoped contract = boost::contract::constructor(this) + boost::shared_ptr old_arg = + BOOST_CONTRACT_OLDOF(arg_cnt::eval(arg)); + boost::shared_ptr old_n = + BOOST_CONTRACT_OLDOF(n_cnt::eval(n)); + boost::contract::var contract = boost::contract::constructor(this) .postcondition([&] { out << Id << "::ctor::post" << std::endl; - BOOST_CONTRACT_ASSERT(x_ == old_arg->value); - BOOST_CONTRACT_ASSERT(arg.value == i_); + BOOST_CONTRACT_ASSERT(i_ == old_arg->value); + BOOST_CONTRACT_ASSERT(arg.value == n.value); + BOOST_CONTRACT_ASSERT(n.value == old_n->value + 1); }) ; out << Id << "::ctor::body" << std::endl; - x_ = arg.value; - arg.value = ++i_; + i_ = arg.value; + arg.value = ++n.value; } - virtual ~t() { --i_; } + virtual ~t() { --n.value; } private: - static int i_; - int x_; + int i_; }; -template int t::i_ = 0; +template typename t::n_cnt t::n; // Test deep inheritance (2 vertical levels), multiple inheritance (4 // horizontal levels), and that all public/protected/private part of @@ -80,45 +85,50 @@ struct c void invariant() const { out << "c::inv" << std::endl; - BOOST_CONTRACT_ASSERT(x_ < 0); + BOOST_CONTRACT_ASSERT(i_ < 0); } static void static_invariant() { out << "c::static_inv" << std::endl; - BOOST_CONTRACT_ASSERT(i_ >= 0); + BOOST_CONTRACT_ASSERT(n.value >= 0); } + + struct n_tag; typedef boost::contract::aux::test::cpcnt n_cnt; + static n_cnt n; struct arg_tag; - typedef boost::contract::aux::test::old arg_type; + typedef boost::contract::aux::test::cpcnt arg_cnt; - explicit c(arg_type& arg, t<'d'>::arg_type& d_arg, t<'e'>::arg_type& e_arg, - t<'f'>::arg_type& f_arg) : + explicit c(arg_cnt& arg, t<'d'>::arg_cnt& d_arg, t<'e'>::arg_cnt& e_arg, + t<'f'>::arg_cnt& f_arg) : boost::contract::constructor_precondition([&] { out << "c::ctor::pre" << std::endl; BOOST_CONTRACT_ASSERT(arg.value < 0); }), t<'d'>(d_arg), t<'e'>(e_arg), t<'f'>(f_arg) { - boost::shared_ptr old_arg = - BOOST_CONTRACT_OLDOF(arg_type::eval(arg)); - boost::contract::scoped contract = boost::contract::constructor(this) + boost::shared_ptr old_arg = + BOOST_CONTRACT_OLDOF(arg_cnt::eval(arg)); + boost::shared_ptr old_n = + BOOST_CONTRACT_OLDOF(n_cnt::eval(n)); + boost::contract::var contract = boost::contract::constructor(this) .postcondition([&] { out << "c::ctor::post" << std::endl; - BOOST_CONTRACT_ASSERT(x_ == old_arg->value); - BOOST_CONTRACT_ASSERT(arg.value == i_); + BOOST_CONTRACT_ASSERT(i_ == old_arg->value); + BOOST_CONTRACT_ASSERT(arg.value == n.value); + BOOST_CONTRACT_ASSERT(n.value == old_n->value + 1); }) ; out << "c::ctor::body" << std::endl; - x_ = arg.value; - arg.value = ++i_; + i_ = arg.value; + arg.value = ++n.value; } - virtual ~c() { --i_; } + virtual ~c() { --n.value; } private: - static int i_; - int x_; + int i_; }; -int c::i_ = 0; +c::n_cnt c::n; // Test not (fully) contracted base is not part of constructor subcontracting. struct b @@ -135,7 +145,7 @@ struct b virtual ~b() {} }; -// Test both non-contracted and contracted bases. +// Test constructor with both non-contracted and contracted bases. struct a #define BASES private boost::contract::constructor_precondition, \ public b, public c @@ -146,18 +156,21 @@ struct a void invariant() const { out << "a::inv" << std::endl; - BOOST_CONTRACT_ASSERT(x_ < 0); + BOOST_CONTRACT_ASSERT(i_ < 0); } static void static_invariant() { out << "a::static_inv" << std::endl; - BOOST_CONTRACT_ASSERT(i_ >= 0); + BOOST_CONTRACT_ASSERT(n.value >= 0); } + + struct n_tag; typedef boost::contract::aux::test::cpcnt n_cnt; + static n_cnt n; struct arg_tag; - typedef boost::contract::aux::test::old arg_type; + typedef boost::contract::aux::test::cpcnt arg_cnt; - explicit a(arg_type& arg, c::arg_type& c_arg, t<'d'>::arg_type& d_arg, - t<'e'>::arg_type& e_arg, t<'f'>::arg_type& f_arg) : + explicit a(arg_cnt& arg, c::arg_cnt& c_arg, t<'d'>::arg_cnt& d_arg, + t<'e'>::arg_cnt& e_arg, t<'f'>::arg_cnt& f_arg) : boost::contract::constructor_precondition([&] { out << "a::ctor::pre" << std::endl; BOOST_CONTRACT_ASSERT(arg.value < 0); @@ -165,79 +178,82 @@ struct a b(), c(c_arg, d_arg, e_arg, f_arg) { - boost::shared_ptr old_arg = - BOOST_CONTRACT_OLDOF(arg_type::eval(arg)); - boost::contract::scoped contract = boost::contract::constructor(this) + boost::shared_ptr old_arg = + BOOST_CONTRACT_OLDOF(arg_cnt::eval(arg)); + boost::shared_ptr old_n = + BOOST_CONTRACT_OLDOF(n_cnt::eval(n)); + boost::contract::var contract = boost::contract::constructor(this) .postcondition([&] { out << "a::ctor::post" << std::endl; - BOOST_CONTRACT_ASSERT(x_ == old_arg->value); - BOOST_CONTRACT_ASSERT(arg.value == i_); + BOOST_CONTRACT_ASSERT(i_ == old_arg->value); + BOOST_CONTRACT_ASSERT(arg.value == n.value); + BOOST_CONTRACT_ASSERT(n.value == old_n->value + 1); }) ; out << "a::ctor::body" << std::endl; - x_ = arg.value; - arg.value = ++i_; + i_ = arg.value; + arg.value = ++n.value; } - virtual ~a() { --i_; } + virtual ~a() { --n.value; } private: - static int i_; - int x_; + int i_; }; -int a::i_ = 0; +a::n_cnt a::n; int main() { std::ostringstream ok; - t<'f'>::arg_type f_arg; f_arg.value = -5; - t<'e'>::arg_type e_arg; e_arg.value = -4; - t<'d'>::arg_type d_arg; d_arg.value = -3; - c::arg_type c_arg; c_arg.value = -2; - a::arg_type a_arg; a_arg.value = -1; + t<'f'>::arg_cnt f_arg; f_arg.value = -5; + t<'e'>::arg_cnt e_arg; e_arg.value = -4; + t<'d'>::arg_cnt d_arg; d_arg.value = -3; + c::arg_cnt c_arg; c_arg.value = -2; + a::arg_cnt a_arg; a_arg.value = -1; out.str(""); a aa(a_arg, c_arg, d_arg, e_arg, f_arg); - ok << + ok.str(""); + ok // Test all constructor pre checked first. - "a::ctor::pre" << std::endl << - "c::ctor::pre" << std::endl << - "d::ctor::pre" << std::endl << + << "a::ctor::pre" << std::endl + << "c::ctor::pre" << std::endl + << "d::ctor::pre" << std::endl // Test static inv, but not const inv, checked before constructor body. - "d::static_inv" << std::endl << - "d::ctor::body" << std::endl << - "d::static_inv" << std::endl << - "d::inv" << std::endl << - "d::ctor::post" << std::endl << - - "e::ctor::pre" << std::endl << - "e::static_inv" << std::endl << - "e::ctor::body" << std::endl << - "e::static_inv" << std::endl << - "e::inv" << std::endl << - "e::ctor::post" << std::endl << - - "f::ctor::pre" << std::endl << - "f::static_inv" << std::endl << - "f::ctor::body" << std::endl << - "f::static_inv" << std::endl << - "f::inv" << std::endl << - "f::ctor::post" << std::endl << - - "c::static_inv" << std::endl << - "c::ctor::body" << std::endl << - "c::static_inv" << std::endl << - "c::inv" << std::endl << - "c::ctor::post" << std::endl << - - "a::static_inv" << std::endl << - "a::ctor::body" << std::endl << - "a::static_inv" << std::endl << - "a::inv" << std::endl << - "a::ctor::post" << std::endl + << "d::static_inv" << std::endl + << "d::ctor::body" << std::endl + << "d::static_inv" << std::endl + << "d::inv" << std::endl + << "d::ctor::post" << std::endl + + << "e::ctor::pre" << std::endl + << "e::static_inv" << std::endl + << "e::ctor::body" << std::endl + << "e::static_inv" << std::endl + << "e::inv" << std::endl + << "e::ctor::post" << std::endl + + << "f::ctor::pre" << std::endl + << "f::static_inv" << std::endl + << "f::ctor::body" << std::endl + << "f::static_inv" << std::endl + << "f::inv" << std::endl + << "f::ctor::post" << std::endl + + << "c::static_inv" << std::endl + << "c::ctor::body" << std::endl + << "c::static_inv" << std::endl + << "c::inv" << std::endl + << "c::ctor::post" << std::endl + + << "a::static_inv" << std::endl + << "a::ctor::body" << std::endl + << "a::static_inv" << std::endl + << "a::inv" << std::endl + << "a::ctor::post" << std::endl ; - BOOST_TEST(out.check(ok.str())); + BOOST_TEST(out.eq(ok.str())); BOOST_TEST_EQ(a_arg.copies(), 1); BOOST_TEST_EQ(a_arg.evals(), 1); BOOST_TEST_EQ(c_arg.copies(), 1); BOOST_TEST_EQ(c_arg.evals(), 1); @@ -245,6 +261,12 @@ int main() { BOOST_TEST_EQ(e_arg.copies(), 1); BOOST_TEST_EQ(e_arg.evals(), 1); BOOST_TEST_EQ(f_arg.copies(), 1); BOOST_TEST_EQ(f_arg.evals(), 1); + BOOST_TEST_EQ(a::n.copies(), 1); BOOST_TEST_EQ(a::n.evals(), 1); + BOOST_TEST_EQ(c::n.copies(), 1); BOOST_TEST_EQ(c::n.evals(), 1); + BOOST_TEST_EQ(t<'d'>::n.copies(), 1); BOOST_TEST_EQ(t<'d'>::n.evals(), 1); + BOOST_TEST_EQ(t<'e'>::n.copies(), 1); BOOST_TEST_EQ(t<'e'>::n.evals(), 1); + BOOST_TEST_EQ(t<'f'>::n.copies(), 1); BOOST_TEST_EQ(t<'f'>::n.evals(), 1); + return boost::report_errors(); } diff --git a/test/constructor/bases_decl.cpp b/test/constructor/bases_decl.cpp new file mode 100644 index 0000000..fb358c8 --- /dev/null +++ b/test/constructor/bases_decl.cpp @@ -0,0 +1,300 @@ + +// Test constructor subcontracting and contract declaration functions. + +#include "../aux_/oteststream.hpp" +#include "../aux_/cpcnt.hpp" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +boost::contract::aux::test::oteststream out; + +template +struct t + #define BASES private boost::contract::constructor_precondition > + : BASES +{ + typedef BOOST_CONTRACT_BASE_TYPES(BASES) base_types; + #undef BASES + + void invariant() const { + out << Id << "::inv" << std::endl; + BOOST_CONTRACT_ASSERT(i_ < 0); + } + static void static_invariant() { + out << Id << "::static_inv" << std::endl; + BOOST_CONTRACT_ASSERT(n.value >= 0); + } + + struct n_tag; typedef boost::contract::aux::test::cpcnt n_cnt; + static n_cnt n; + + struct arg_tag; + typedef boost::contract::aux::test::cpcnt arg_cnt; + + // MSVC 2010 errors on lambdas in template member initializations... + static void constructor_precondition(arg_cnt const& arg) { + out << Id << "::ctor::pre" << std::endl; + BOOST_CONTRACT_ASSERT(arg.value < 0); + } + void constructor(arg_cnt const& arg, boost::contract::decl c) const { + boost::shared_ptr old_arg = + BOOST_CONTRACT_OLDOF(c, arg_cnt::eval(arg)); + boost::shared_ptr old_n = + BOOST_CONTRACT_OLDOF(c, n_cnt::eval(n)); + boost::contract::var contract = boost::contract::constructor(c, this) + .postcondition([&] { + out << Id << "::ctor::post" << std::endl; + BOOST_CONTRACT_ASSERT(i_ == old_arg->value); + BOOST_CONTRACT_ASSERT(arg.value == n.value); + BOOST_CONTRACT_ASSERT(n.value == old_n->value + 1); + }) + ; + } + explicit t(arg_cnt& arg) : + boost::contract::constructor_precondition >(boost::bind( + &t::constructor_precondition, boost::cref(arg))) + { + unsigned save_arg_copies = arg.copies(); + boost::contract::var contract = boost::contract::decl_function( + this, arg, &t::constructor); + // Test decl_function did not copy (only 1 copy from contract old-of). + BOOST_TEST_EQ(arg.copies(), save_arg_copies + 1); + + out << Id << "::ctor::body" << std::endl; + i_ = arg.value; + arg.value = ++n.value; + } + + virtual ~t() { --n.value; } + +private: + int i_; +}; +template typename t::n_cnt t::n; + +// Test deep inheritance (2 vertical levels), multiple inheritance (4 +// horizontal levels), and that all public/protected/private part of +// subcontracting for constructors (not just public, because all access levels +// are part of C++ object construction mechanism). +struct c + #define BASES private boost::contract::constructor_precondition, \ + public t<'d'>, protected t<'e'>, private t<'f'> + : BASES +{ + typedef BOOST_CONTRACT_BASE_TYPES(BASES) base_types; + #undef BASES + + void invariant() const { + out << "c::inv" << std::endl; + BOOST_CONTRACT_ASSERT(i_ < 0); + } + static void static_invariant() { + out << "c::static_inv" << std::endl; + BOOST_CONTRACT_ASSERT(n.value >= 0); + } + + struct n_tag; typedef boost::contract::aux::test::cpcnt n_cnt; + static n_cnt n; + + struct arg_tag; + typedef boost::contract::aux::test::cpcnt arg_cnt; + + static void constructor_precondition(arg_cnt const& arg) { + out << "c::ctor::pre" << std::endl; + BOOST_CONTRACT_ASSERT(arg.value < 0); + } + void constructor(arg_cnt const& arg, boost::contract::decl c) const { + boost::shared_ptr old_arg = + BOOST_CONTRACT_OLDOF(c, arg_cnt::eval(arg)); + boost::shared_ptr old_n = + BOOST_CONTRACT_OLDOF(c, n_cnt::eval(n)); + boost::contract::var contract = boost::contract::constructor(c, this) + .postcondition([&] { + out << "c::ctor::post" << std::endl; + BOOST_CONTRACT_ASSERT(i_ == old_arg->value); + BOOST_CONTRACT_ASSERT(arg.value == n.value); + BOOST_CONTRACT_ASSERT(n.value == old_n->value + 1); + }) + ; + } + explicit c(arg_cnt& arg, t<'d'>::arg_cnt& d_arg, t<'e'>::arg_cnt& e_arg, + t<'f'>::arg_cnt& f_arg) : + boost::contract::constructor_precondition(boost::bind( + &constructor_precondition, boost::cref(arg))), + t<'d'>(d_arg), t<'e'>(e_arg), t<'f'>(f_arg) + { + unsigned save_arg_copies = arg.copies(); + boost::contract::var contract = boost::contract::decl_function( + this, arg, &c::constructor); + // Test decl_function did not copy (only 1 copy from contract old-of). + BOOST_TEST_EQ(arg.copies(), save_arg_copies + 1); + + out << "c::ctor::body" << std::endl; + i_ = arg.value; + arg.value = ++n.value; + } + + virtual ~c() { --n.value; } + +private: + int i_; +}; +c::n_cnt c::n; + +// Test not (fully) contracted base is not part of constructor subcontracting. +struct b + #define BASES private boost::contract::constructor_precondition + : BASES +{ + typedef BOOST_CONTRACT_BASE_TYPES(BASES) base_types; + #undef BASES + + void invariant() const { out << "b::inv" << std::endl; } + static void static_invariant() { out << "b::static_inv" << std::endl; } + + explicit b() {} // No contract. + virtual ~b() {} +}; + +// Test both non-contracted and contracted bases. +struct a + #define BASES private boost::contract::constructor_precondition, \ + public b, public c + : BASES +{ + typedef BOOST_CONTRACT_BASE_TYPES(BASES) base_types; + #undef BASES + + void invariant() const { + out << "a::inv" << std::endl; + BOOST_CONTRACT_ASSERT(i_ < 0); + } + static void static_invariant() { + out << "a::static_inv" << std::endl; + BOOST_CONTRACT_ASSERT(n.value >= 0); + } + + struct n_tag; typedef boost::contract::aux::test::cpcnt n_cnt; + static n_cnt n; + + struct arg_tag; + typedef boost::contract::aux::test::cpcnt arg_cnt; + + static void constructor_precondition(arg_cnt const& arg) { + out << "a::ctor::pre" << std::endl; + BOOST_CONTRACT_ASSERT(arg.value < 0); + } + void constructor(arg_cnt const& arg, boost::contract::decl c) const { + boost::shared_ptr old_arg = + BOOST_CONTRACT_OLDOF(c, arg_cnt::eval(arg)); + boost::shared_ptr old_n = + BOOST_CONTRACT_OLDOF(c, n_cnt::eval(n)); + boost::contract::var contract = boost::contract::constructor(c, this) + .postcondition([&] { + out << "a::ctor::post" << std::endl; + BOOST_CONTRACT_ASSERT(i_ == old_arg->value); + BOOST_CONTRACT_ASSERT(arg.value == n.value); + BOOST_CONTRACT_ASSERT(n.value == old_n->value + 1); + }) + ; + } + explicit a(arg_cnt& arg, c::arg_cnt& c_arg, t<'d'>::arg_cnt& d_arg, + t<'e'>::arg_cnt& e_arg, t<'f'>::arg_cnt& f_arg) : + boost::contract::constructor_precondition(boost::bind( + &a::constructor_precondition, boost::cref(arg))), + b(), c(c_arg, d_arg, e_arg, f_arg) + { + unsigned save_arg_copies = arg.copies(); + boost::contract::var contract = boost::contract::decl_function( + this, arg, &a::constructor); + // Test decl_function did not copy (only 1 copy from contract old-of). + BOOST_TEST_EQ(arg.copies(), save_arg_copies + 1); + + out << "a::ctor::body" << std::endl; + i_ = arg.value; + arg.value = ++n.value; + } + + virtual ~a() { --n.value; } + +private: + int i_; +}; +a::n_cnt a::n; + +int main() { + std::ostringstream ok; + + t<'f'>::arg_cnt f_arg; f_arg.value = -5; + t<'e'>::arg_cnt e_arg; e_arg.value = -4; + t<'d'>::arg_cnt d_arg; d_arg.value = -3; + c::arg_cnt c_arg; c_arg.value = -2; + a::arg_cnt a_arg; a_arg.value = -1; + + out.str(""); + a aa(a_arg, c_arg, d_arg, e_arg, f_arg); + ok.str(""); + ok + // Test all constructor pre checked first. + << "a::ctor::pre" << std::endl + << "c::ctor::pre" << std::endl + << "d::ctor::pre" << std::endl + + // Test static inv, but not const inv, checked before constructor body. + << "d::static_inv" << std::endl + << "d::ctor::body" << std::endl + << "d::static_inv" << std::endl + << "d::inv" << std::endl + << "d::ctor::post" << std::endl + + << "e::ctor::pre" << std::endl + << "e::static_inv" << std::endl + << "e::ctor::body" << std::endl + << "e::static_inv" << std::endl + << "e::inv" << std::endl + << "e::ctor::post" << std::endl + + << "f::ctor::pre" << std::endl + << "f::static_inv" << std::endl + << "f::ctor::body" << std::endl + << "f::static_inv" << std::endl + << "f::inv" << std::endl + << "f::ctor::post" << std::endl + + << "c::static_inv" << std::endl + << "c::ctor::body" << std::endl + << "c::static_inv" << std::endl + << "c::inv" << std::endl + << "c::ctor::post" << std::endl + + << "a::static_inv" << std::endl + << "a::ctor::body" << std::endl + << "a::static_inv" << std::endl + << "a::inv" << std::endl + << "a::ctor::post" << std::endl + ; + BOOST_TEST(out.eq(ok.str())); + + BOOST_TEST_EQ(a_arg.copies(), 1); BOOST_TEST_EQ(a_arg.evals(), 1); + BOOST_TEST_EQ(c_arg.copies(), 1); BOOST_TEST_EQ(c_arg.evals(), 1); + BOOST_TEST_EQ(d_arg.copies(), 1); BOOST_TEST_EQ(d_arg.evals(), 1); + BOOST_TEST_EQ(e_arg.copies(), 1); BOOST_TEST_EQ(e_arg.evals(), 1); + BOOST_TEST_EQ(f_arg.copies(), 1); BOOST_TEST_EQ(f_arg.evals(), 1); + + BOOST_TEST_EQ(a::n.copies(), 1); BOOST_TEST_EQ(a::n.evals(), 1); + BOOST_TEST_EQ(c::n.copies(), 1); BOOST_TEST_EQ(c::n.evals(), 1); + BOOST_TEST_EQ(t<'d'>::n.copies(), 1); BOOST_TEST_EQ(t<'d'>::n.evals(), 1); + BOOST_TEST_EQ(t<'e'>::n.copies(), 1); BOOST_TEST_EQ(t<'e'>::n.evals(), 1); + BOOST_TEST_EQ(t<'f'>::n.copies(), 1); BOOST_TEST_EQ(t<'f'>::n.evals(), 1); + + return boost::report_errors(); +} + diff --git a/test/constructor/no_pre-error.cpp b/test/constructor/no_pre-error.cpp index ef3d9c9..690e3df 100644 --- a/test/constructor/no_pre-error.cpp +++ b/test/constructor/no_pre-error.cpp @@ -1,4 +1,6 @@ +// Test constructor cannot use `.precondition(...)`. + #include #include diff --git a/test/constructor/overload.cpp b/test/constructor/overload.cpp new file mode 100644 index 0000000..b0b728e --- /dev/null +++ b/test/constructor/overload.cpp @@ -0,0 +1,146 @@ + +// Test constructor overloads. + +#include "../aux_/oteststream.hpp" +#include "../aux_/cpcnt.hpp" +#include +#include +#include +#include +#include +#include +#include + +boost::contract::aux::test::oteststream out; + +struct a + #define BASES private boost::contract::constructor_precondition + : BASES +{ + typedef BOOST_CONTRACT_BASE_TYPES(BASES) base_types; + #undef BASES + + void invariant() const { + out << "a::inv" << std::endl; + BOOST_CONTRACT_ASSERT(i_ == -1 || i_ > 0); + } + static void static_invariant() { + out << "a::static_inv" << std::endl; + BOOST_CONTRACT_ASSERT(n.value >= 0); + } + + struct n_tag; typedef boost::contract::aux::test::cpcnt n_cnt; + static n_cnt n; + + explicit a() : // Test overload with no argument. + // Test overload with no preconditions. + i_(-1) + { + boost::shared_ptr old_n = + BOOST_CONTRACT_OLDOF(n_cnt::eval(n)); + boost::contract::var contract = boost::contract::constructor(this) + .postcondition([&] { + out << "a::ctor()::post" << std::endl; + BOOST_CONTRACT_ASSERT(i_ == -1); + BOOST_CONTRACT_ASSERT(n.value == old_n->value + 1); + }) + ; + ++n.value; + } + + explicit a(int i) : // Test overload with int. + boost::contract::constructor_precondition([&] { + out << "a::ctor(int)::pre" << std::endl; + BOOST_CONTRACT_ASSERT(i > 0); + }), + i_(i) + { + boost::shared_ptr old_n = + BOOST_CONTRACT_OLDOF(n_cnt::eval(n)); + boost::contract::var contract = boost::contract::constructor(this) + .postcondition([&] { + out << "a::ctor(int)::post" << std::endl; + BOOST_CONTRACT_ASSERT(i_ == i); + BOOST_CONTRACT_ASSERT(n.value == old_n->value + 1); + }) + ; + ++n.value; + } + + explicit a(char h) : // Test overload with char. + boost::contract::constructor_precondition([&] { + out << "a::ctor(char)::pre" << std::endl; + BOOST_CONTRACT_ASSERT(h != '\0'); + }), + i_(h) + { + boost::shared_ptr old_n = + BOOST_CONTRACT_OLDOF(n_cnt::eval(n)); + boost::contract::var contract = boost::contract::constructor(this) + .postcondition([&] { + out << "a::ctor(char)::post" << std::endl; + BOOST_CONTRACT_ASSERT(i_ == h); + BOOST_CONTRACT_ASSERT(n.value == old_n->value + 1); + }) + ; + ++n.value; + } + + ~a() { --n.value; } + +private: + int i_; +}; +a::n_cnt a::n; + +int main() { + std::ostringstream ok; + + out.str(""); + a aa; + ok.str(""); + ok + // No preconditions. + << "a::static_inv" << std::endl + << "a::static_inv" << std::endl + << "a::inv" << std::endl + << "a::ctor()::post" << std::endl + ; + BOOST_TEST(out.eq(ok.str())); + BOOST_TEST_EQ(a::n.copies(), 1); + BOOST_TEST_EQ(a::n.evals(), 1); + out << std::endl; + + out.str(""); + a ai(123); + ok.str(""); + ok + << "a::ctor(int)::pre" << std::endl + << "a::static_inv" << std::endl + << "a::static_inv" << std::endl + << "a::inv" << std::endl + << "a::ctor(int)::post" << std::endl + ; + BOOST_TEST(out.eq(ok.str())); + BOOST_TEST_EQ(a::n.copies(), 2); + BOOST_TEST_EQ(a::n.evals(), 2); + out << std::endl; + + out.str(""); + a ac('x'); + ok.str(""); + ok + << "a::ctor(char)::pre" << std::endl + << "a::static_inv" << std::endl + << "a::static_inv" << std::endl + << "a::inv" << std::endl + << "a::ctor(char)::post" << std::endl + ; + BOOST_TEST(out.eq(ok.str())); + BOOST_TEST_EQ(a::n.copies(), 3); + BOOST_TEST_EQ(a::n.evals(), 3); + out << std::endl; + + return boost::report_errors(); +} + diff --git a/test/constructor/overload_decl.cpp b/test/constructor/overload_decl.cpp new file mode 100644 index 0000000..7c86708 --- /dev/null +++ b/test/constructor/overload_decl.cpp @@ -0,0 +1,172 @@ + +// Test constructor overloads using bind. + +#include "../aux_/oteststream.hpp" +#include "../aux_/cpcnt.hpp" +#include +#include +#include +#include +#include +#include +#include +#include +#include + +boost::contract::aux::test::oteststream out; + +struct a + #define BASES private boost::contract::constructor_precondition + : BASES +{ + typedef BOOST_CONTRACT_BASE_TYPES(BASES) base_types; + #undef BASES + + void invariant() const { + out << "a::inv" << std::endl; + BOOST_CONTRACT_ASSERT(i_ == -1 || i_ > 0); + } + static void static_invariant() { + out << "a::static_inv" << std::endl; + BOOST_CONTRACT_ASSERT(n.value >= 0); + } + + struct n_tag; typedef boost::contract::aux::test::cpcnt n_cnt; + static n_cnt n; + + void constructor(boost::contract::decl c) const { + boost::shared_ptr old_n = + BOOST_CONTRACT_OLDOF(c, n_cnt::eval(n)); + boost::contract::constructor(c, this) + .postcondition([&] { + out << "a::ctor()::post" << std::endl; + BOOST_CONTRACT_ASSERT(i_ == -1); + BOOST_CONTRACT_ASSERT(n.value == old_n->value + 1); + }) + ; + } + explicit a() : // Test overload with no argument. + // Test overload with no preconditions. + i_(-1) + { + boost::contract::var contract = boost::contract::decl_function( + this, &a::constructor); + ++n.value; + } + + struct i_tag; typedef boost::contract::aux::test::cpcnt i_cnt; + + static void constructor_precondition(int const i) { + out << "a::ctor(int)::pre" << std::endl; + BOOST_CONTRACT_ASSERT(i > 0); + } + void constructor(i_cnt const& i, boost::contract::decl c) const { + boost::shared_ptr old_n = + BOOST_CONTRACT_OLDOF(c, n_cnt::eval(n)); + boost::contract::constructor(c, this) + .postcondition([&] { + out << "a::ctor(int)::post" << std::endl; + BOOST_CONTRACT_ASSERT(i_ == i.value); + BOOST_CONTRACT_ASSERT(n.value == old_n->value + 1); + }) + ; + } + explicit a(int i) : // Test overload with int. + boost::contract::constructor_precondition(boost::bind(static_cast< + void (*)(int const)>(&a::constructor_precondition), i)), + i_(i) + { + i_cnt i_arg; i_arg.value = i; + boost::contract::var contract = boost::contract::decl_function( + this, i_arg, &a::constructor); + BOOST_TEST_EQ(i_arg.copies(), 0); // Test bind args never copied. + ++n.value; + } + + struct h_tag; typedef boost::contract::aux::test::cpcnt h_cnt; + + static void constructor_precondition(char const h) { + out << "a::ctor(char)::pre" << std::endl; + BOOST_CONTRACT_ASSERT(h != '\0'); + } + void constructor(h_cnt const& h, boost::contract::decl c) const { + boost::shared_ptr old_n = + BOOST_CONTRACT_OLDOF(c, n_cnt::eval(n)); + boost::contract::constructor(c, this) + .postcondition([&] { + out << "a::ctor(char)::post" << std::endl; + BOOST_CONTRACT_ASSERT(i_ == h.value); + BOOST_CONTRACT_ASSERT(n.value == old_n->value + 1); + }) + ; + } + explicit a(char h) : // Test overload with char. + boost::contract::constructor_precondition(boost::bind(static_cast< + void (*)(char const)>(&a::constructor_precondition), h)), + i_(h) + { + h_cnt h_arg; h_arg.value = h; + boost::contract::var contract = boost::contract::decl_function( + this, h_arg, &a::constructor); + BOOST_TEST_EQ(h_arg.copies(), 0); // Test bind args never copied. + ++n.value; + } + + ~a() { --n.value; } + +private: + int i_; +}; +a::n_cnt a::n; + +int main() { + std::ostringstream ok; + + out.str(""); + a aa; + ok.str(""); + ok + // No preconditions. + << "a::static_inv" << std::endl + << "a::static_inv" << std::endl + << "a::inv" << std::endl + << "a::ctor()::post" << std::endl + ; + BOOST_TEST(out.eq(ok.str())); + BOOST_TEST_EQ(a::n.copies(), 1); + BOOST_TEST_EQ(a::n.evals(), 1); + out << std::endl; + + out.str(""); + a ai(123); + ok.str(""); + ok + << "a::ctor(int)::pre" << std::endl + << "a::static_inv" << std::endl + << "a::static_inv" << std::endl + << "a::inv" << std::endl + << "a::ctor(int)::post" << std::endl + ; + BOOST_TEST(out.eq(ok.str())); + BOOST_TEST_EQ(a::n.copies(), 2); + BOOST_TEST_EQ(a::n.evals(), 2); + out << std::endl; + + out.str(""); + a ac('x'); + ok.str(""); + ok + << "a::ctor(char)::pre" << std::endl + << "a::static_inv" << std::endl + << "a::static_inv" << std::endl + << "a::inv" << std::endl + << "a::ctor(char)::post" << std::endl + ; + BOOST_TEST(out.eq(ok.str())); + BOOST_TEST_EQ(a::n.copies(), 3); + BOOST_TEST_EQ(a::n.evals(), 3); + out << std::endl; + + return boost::report_errors(); +} + diff --git a/test/destructor/bases.cpp b/test/destructor/bases.cpp new file mode 100644 index 0000000..dcbe6e3 --- /dev/null +++ b/test/destructor/bases.cpp @@ -0,0 +1,192 @@ + +// Test destructor subcontracting. + +#include "../aux_/oteststream.hpp" +#include "../aux_/cpcnt.hpp" +#include +#include +#include +#include +#include +#include +#include + +boost::contract::aux::test::oteststream out; + +template +struct t { + void invariant() const { + out << Id << "::inv" << std::endl; + BOOST_CONTRACT_ASSERT(i_ < 0); + } + static void static_invariant() { + out << Id << "::static_inv" << std::endl; + BOOST_CONTRACT_ASSERT(n.value >= 0); + } + + struct n_tag; typedef boost::contract::aux::test::cpcnt n_cnt; + static n_cnt n; + + explicit t() : i_(-1) { ++n.value; } + + virtual ~t() { + boost::shared_ptr old_n = + BOOST_CONTRACT_OLDOF(n_cnt::eval(n)); + boost::contract::var contract = boost::contract::destructor(this) + .postcondition([old_n] { + out << Id << "::dtor::post" << std::endl; + BOOST_CONTRACT_ASSERT(t::n.value == old_n->value - 1); + }) + ; + out << Id << "::dtor::body" << std::endl; + --n.value; + } + +private: + int i_; +}; +template typename t::n_cnt t::n; + +// Test deep inheritance (2 vertical levels), multiple inheritance (4 +// horizontal levels), and that all public/protected/private part of +// subcontracting for destructors (not just public, because all access levels +// are part of C++ object destruction mechanism). +struct c + #define BASES public t<'d'>, protected t<'e'>, private t<'f'> + : BASES +{ + typedef BOOST_CONTRACT_BASE_TYPES(BASES) base_types; + #undef BASES + + void invariant() const { + out << "c::inv" << std::endl; + BOOST_CONTRACT_ASSERT(i_ < 0); + } + static void static_invariant() { + out << "c::static_inv" << std::endl; + BOOST_CONTRACT_ASSERT(n.value >= 0); + } + + struct n_tag; typedef boost::contract::aux::test::cpcnt n_cnt; + static n_cnt n; + + explicit c() : i_(-1) { ++n.value; } + + virtual ~c() { + boost::shared_ptr old_n = + BOOST_CONTRACT_OLDOF(n_cnt::eval(n)); + boost::contract::var contract = boost::contract::destructor(this) + .postcondition([old_n] { + out << "c::dtor::post" << std::endl; + BOOST_CONTRACT_ASSERT(c::n.value == old_n->value - 1); + }) + ; + out << "c::dtor::body" << std::endl; + --n.value; + } + +private: + int i_; +}; +c::n_cnt c::n; + +// Test not (fully) contracted base is not part of destructor subcontracting. +struct b { + void invariant() const { out << "b::inv" << std::endl; } + static void static_invariant() { out << "b::static_inv" << std::endl; } + + explicit b() {} + virtual ~b() {} // No contract. +}; + +// Test destructor with both non-contracted and contracted bases. +struct a + #define BASES public b, public c + : BASES +{ + typedef BOOST_CONTRACT_BASE_TYPES(BASES) base_types; + #undef BASES + + void invariant() const { + out << "a::inv" << std::endl; + BOOST_CONTRACT_ASSERT(i_ < 0); + } + static void static_invariant() { + out << "a::static_inv" << std::endl; + BOOST_CONTRACT_ASSERT(n.value >= 0); + } + + struct n_tag; typedef boost::contract::aux::test::cpcnt n_cnt; + static n_cnt n; + + explicit a() : i_(-1) { ++n.value; } + + virtual ~a() { + boost::shared_ptr old_n = + BOOST_CONTRACT_OLDOF(n_cnt::eval(n)); + boost::contract::var contract = boost::contract::destructor(this) + .postcondition([old_n] { + out << "a::dtor::post" << std::endl; + BOOST_CONTRACT_ASSERT(a::n.value == old_n->value - 1); + }) + ; + out << "a::dtor::body" << std::endl; + --n.value; + } + +private: + int i_; +}; +a::n_cnt a::n; + +int main() { + std::ostringstream ok; + + { + a aa; + out.str(""); + } // Call aa's destructor. + ok.str(""); + ok + << "a::static_inv" << std::endl + << "a::inv" << std::endl + << "a::dtor::body" << std::endl + // Test static inv, but not const inv, checked after destructor body. + << "a::static_inv" << std::endl + << "a::dtor::post" << std::endl + + << "c::static_inv" << std::endl + << "c::inv" << std::endl + << "c::dtor::body" << std::endl + << "c::static_inv" << std::endl + << "c::dtor::post" << std::endl + + << "f::static_inv" << std::endl + << "f::inv" << std::endl + << "f::dtor::body" << std::endl + << "f::static_inv" << std::endl + << "f::dtor::post" << std::endl + + << "e::static_inv" << std::endl + << "e::inv" << std::endl + << "e::dtor::body" << std::endl + << "e::static_inv" << std::endl + << "e::dtor::post" << std::endl + + << "d::static_inv" << std::endl + << "d::inv" << std::endl + << "d::dtor::body" << std::endl + << "d::static_inv" << std::endl + << "d::dtor::post" << std::endl + ; + BOOST_TEST(out.eq(ok.str())); + + BOOST_TEST_EQ(a::n.copies(), 1); BOOST_TEST_EQ(a::n.evals(), 1); + BOOST_TEST_EQ(c::n.copies(), 1); BOOST_TEST_EQ(c::n.evals(), 1); + BOOST_TEST_EQ(t<'d'>::n.copies(), 1); BOOST_TEST_EQ(t<'d'>::n.evals(), 1); + BOOST_TEST_EQ(t<'e'>::n.copies(), 1); BOOST_TEST_EQ(t<'e'>::n.evals(), 1); + BOOST_TEST_EQ(t<'f'>::n.copies(), 1); BOOST_TEST_EQ(t<'f'>::n.evals(), 1); + + return boost::report_errors(); +} + diff --git a/test/destructor/bases_decl.cpp b/test/destructor/bases_decl.cpp new file mode 100644 index 0000000..d2fa174 --- /dev/null +++ b/test/destructor/bases_decl.cpp @@ -0,0 +1,205 @@ + +// Test destructor subcontracting with contract declaration functions. + +#include "../aux_/oteststream.hpp" +#include "../aux_/cpcnt.hpp" +#include +#include +#include +#include +#include +#include +#include +#include + +boost::contract::aux::test::oteststream out; + +template +struct t { + void invariant() const { + out << Id << "::inv" << std::endl; + BOOST_CONTRACT_ASSERT(i_ < 0); + } + static void static_invariant() { + out << Id << "::static_inv" << std::endl; + BOOST_CONTRACT_ASSERT(n.value >= 0); + } + + struct n_tag; typedef boost::contract::aux::test::cpcnt n_cnt; + static n_cnt n; + + explicit t() : i_(-1) { ++n.value; } + + void destructor(boost::contract::decl c) const { + boost::shared_ptr old_n = + BOOST_CONTRACT_OLDOF(c, n_cnt::eval(n)); + boost::contract::var contract = boost::contract::destructor(c, this) + .postcondition([old_n] { // Still.. shall not capture this. + out << Id << "::dtor::post" << std::endl; + BOOST_CONTRACT_ASSERT(t::n.value == old_n->value - 1); + }) + ; + } + virtual ~t() { + boost::contract::var contract = boost::contract::decl_function( + this, &t::destructor); + out << Id << "::dtor::body" << std::endl; + --n.value; + } + +private: + int i_; +}; +template typename t::n_cnt t::n; + +// Test deep inheritance (2 vertical levels), multiple inheritance (4 +// horizontal levels), and that all public/protected/private part of +// subcontracting for destructors (not just public, because all access levels +// are part of C++ object destruction mechanism). +struct c + #define BASES public t<'d'>, protected t<'e'>, private t<'f'> + : BASES +{ + typedef BOOST_CONTRACT_BASE_TYPES(BASES) base_types; + #undef BASES + + void invariant() const { + out << "c::inv" << std::endl; + BOOST_CONTRACT_ASSERT(i_ < 0); + } + static void static_invariant() { + out << "c::static_inv" << std::endl; + BOOST_CONTRACT_ASSERT(n.value >= 0); + } + + struct n_tag; typedef boost::contract::aux::test::cpcnt n_cnt; + static n_cnt n; + + explicit c() : i_(-1) { ++n.value; } + + void destructor(boost::contract::decl c) const { + boost::shared_ptr old_n = + BOOST_CONTRACT_OLDOF(c, n_cnt::eval(n)); + boost::contract::var contract = boost::contract::destructor(c, this) + .postcondition([old_n] { + out << "c::dtor::post" << std::endl; + BOOST_CONTRACT_ASSERT(c::n.value == old_n->value - 1); + }) + ; + } + virtual ~c() { + boost::contract::var contract = boost::contract::decl_function( + this, &c::destructor); + out << "c::dtor::body" << std::endl; + --n.value; + } + +private: + int i_; +}; +c::n_cnt c::n; + +// Test not (fully) contracted base is not part of destructor subcontracting. +struct b { + void invariant() const { out << "b::inv" << std::endl; } + static void static_invariant() { out << "b::static_inv" << std::endl; } + + explicit b() {} + virtual ~b() {} // No contract. +}; + +// Test destructor with both non-contracted and contracted bases. +struct a + #define BASES public b, public c + : BASES +{ + typedef BOOST_CONTRACT_BASE_TYPES(BASES) base_types; + #undef BASES + + void invariant() const { + out << "a::inv" << std::endl; + BOOST_CONTRACT_ASSERT(i_ < 0); + } + static void static_invariant() { + out << "a::static_inv" << std::endl; + BOOST_CONTRACT_ASSERT(n.value >= 0); + } + + struct n_tag; typedef boost::contract::aux::test::cpcnt n_cnt; + static n_cnt n; + + explicit a() : i_(-1) { ++n.value; } + + void destructor(boost::contract::decl c) const { + boost::shared_ptr old_n = + BOOST_CONTRACT_OLDOF(c, n_cnt::eval(n)); + boost::contract::var contract = boost::contract::destructor(c, this) + .postcondition([old_n] { + out << "a::dtor::post" << std::endl; + BOOST_CONTRACT_ASSERT(a::n.value == old_n->value - 1); + }) + ; + } + virtual ~a() { + boost::contract::var contract = boost::contract::decl_function( + this, &a::destructor); + out << "a::dtor::body" << std::endl; + --n.value; + } + +private: + int i_; +}; +a::n_cnt a::n; + +int main() { + std::ostringstream ok; + + { + a aa; + out.str(""); + } // Call aa's destructor. + ok.str(""); + ok + << "a::static_inv" << std::endl + << "a::inv" << std::endl + << "a::dtor::body" << std::endl + // Test static inv, but not const inv, checked after destructor body. + << "a::static_inv" << std::endl + << "a::dtor::post" << std::endl + + << "c::static_inv" << std::endl + << "c::inv" << std::endl + << "c::dtor::body" << std::endl + << "c::static_inv" << std::endl + << "c::dtor::post" << std::endl + + << "f::static_inv" << std::endl + << "f::inv" << std::endl + << "f::dtor::body" << std::endl + << "f::static_inv" << std::endl + << "f::dtor::post" << std::endl + + << "e::static_inv" << std::endl + << "e::inv" << std::endl + << "e::dtor::body" << std::endl + << "e::static_inv" << std::endl + << "e::dtor::post" << std::endl + + << "d::static_inv" << std::endl + << "d::inv" << std::endl + << "d::dtor::body" << std::endl + << "d::static_inv" << std::endl + << "d::dtor::post" << std::endl + ; + BOOST_TEST(out.eq(ok.str())); + + BOOST_TEST_EQ(a::n.copies(), 1); BOOST_TEST_EQ(a::n.evals(), 1); + BOOST_TEST_EQ(c::n.copies(), 1); BOOST_TEST_EQ(c::n.evals(), 1); + BOOST_TEST_EQ(t<'d'>::n.copies(), 1); BOOST_TEST_EQ(t<'d'>::n.evals(), 1); + BOOST_TEST_EQ(t<'e'>::n.copies(), 1); BOOST_TEST_EQ(t<'e'>::n.evals(), 1); + BOOST_TEST_EQ(t<'f'>::n.copies(), 1); BOOST_TEST_EQ(t<'f'>::n.evals(), 1); + + return boost::report_errors(); +} + diff --git a/test/destructor/no_pre-error.cpp b/test/destructor/no_pre-error.cpp new file mode 100644 index 0000000..5c81da9 --- /dev/null +++ b/test/destructor/no_pre-error.cpp @@ -0,0 +1,19 @@ + +// Test destructor cannot use `.precondition(...)`. + +#include +#include + +struct a { + ~a() { + boost::contract::var contract = boost::contract::destructor(this) + .precondition([] {}) // Error (no func arg so never pre). + ; + } +}; + +int main() { + a aa; + return 0; +} + diff --git a/test/free_function/nothing.cpp b/test/free_function/nothing.cpp new file mode 100644 index 0000000..5e64653 --- /dev/null +++ b/test/free_function/nothing.cpp @@ -0,0 +1,28 @@ + +// Test no pre or post (for free func, but same for all contracts). + +#include "../aux_/oteststream.hpp" +#include +#include +#include +#include + +boost::contract::aux::test::oteststream out; + +void f() { + boost::contract::var contract = boost::contract::free_function(); + out << "f::body" << std::endl; +} + +int main() { + std::ostringstream ok; + + out.str(""); + f(); + ok.str(""); + ok << "f::body" << std::endl; + BOOST_TEST(out.eq(ok.str())); + + return boost::report_errors(); +} + diff --git a/test/function/free_function.cpp b/test/free_function/post_only.cpp similarity index 59% rename from test/function/free_function.cpp rename to test/free_function/post_only.cpp index 9d7e96c..b20c105 100644 --- a/test/function/free_function.cpp +++ b/test/free_function/post_only.cpp @@ -1,21 +1,17 @@ +// Test post only specified (for free func, but same for all contracts). + #include "../aux_/oteststream.hpp" #include +#include #include #include -// Test free-function. - boost::contract::aux::test::oteststream out; void f() { - auto c = boost::contract::free_function() - .precondition([&] { - out << "f::pre" << std::endl; - }) - .postcondition([&] { - out << "f::post" << std::endl; - }) + boost::contract::var contract = boost::contract::free_function() + .postcondition([] { out << "f::post" << std::endl; }) ; out << "f::body" << std::endl; } @@ -27,11 +23,10 @@ int main() { f(); ok.str(""); ok - << "f::pre" << std::endl << "f::body" << std::endl << "f::post" << std::endl ; - BOOST_TEST(out.check(ok.str())); + BOOST_TEST(out.eq(ok.str())); return boost::report_errors(); } diff --git a/test/free_function/post_post-error.cpp b/test/free_function/post_post-error.cpp new file mode 100644 index 0000000..2f0e58e --- /dev/null +++ b/test/free_function/post_post-error.cpp @@ -0,0 +1,18 @@ + +// Test double post error (for free func, but same for all contracts). + +#include +#include + +void f() { + boost::contract::var contract = boost::contract::free_function() + .postcondition([] {}) + .postcondition([] {}) // Error (double post). + ; +} + +int main() { + f(); + return 0; +} + diff --git a/test/free_function/post_pre.cpp b/test/free_function/post_pre.cpp new file mode 100644 index 0000000..e227583 --- /dev/null +++ b/test/free_function/post_pre.cpp @@ -0,0 +1,35 @@ + +// Test post specified before pre (for free func, but same for all contracts). + +#include "../aux_/oteststream.hpp" +#include +#include +#include +#include + +boost::contract::aux::test::oteststream out; + +void f() { + boost::contract::var contract = boost::contract::free_function() + .postcondition([] { out << "f::post" << std::endl; }) + .precondition([] { out << "f::pre" << std::endl; }) + ; + out << "f::body" << std::endl; +} + +int main() { + std::ostringstream ok; + + out.str(""); + f(); + ok.str(""); + ok + << "f::pre" << std::endl + << "f::body" << std::endl + << "f::post" << std::endl + ; + BOOST_TEST(out.eq(ok.str())); + + return boost::report_errors(); +} + diff --git a/test/free_function/post_pre_post-error.cpp b/test/free_function/post_pre_post-error.cpp new file mode 100644 index 0000000..54687ac --- /dev/null +++ b/test/free_function/post_pre_post-error.cpp @@ -0,0 +1,19 @@ + +// Test double post error (for free func, but same for all contracts). + +#include +#include + +void f() { + boost::contract::var contract = boost::contract::free_function() + .postcondition([] {}) + .precondition([] {}) + .postcondition([] {}) // Error (double post, after a pre). + ; +} + +int main() { + f(); + return 0; +} + diff --git a/test/free_function/pre_only.cpp b/test/free_function/pre_only.cpp new file mode 100644 index 0000000..8ad026b --- /dev/null +++ b/test/free_function/pre_only.cpp @@ -0,0 +1,33 @@ + +// Test pre only specified (for free func, but same for all contracts). + +#include "../aux_/oteststream.hpp" +#include +#include +#include +#include + +boost::contract::aux::test::oteststream out; + +void f() { + boost::contract::var contract = boost::contract::free_function() + .precondition([] { out << "f::pre" << std::endl; }) + ; + out << "f::body" << std::endl; +} + +int main() { + std::ostringstream ok; + + out.str(""); + f(); + ok.str(""); + ok + << "f::pre" << std::endl + << "f::body" << std::endl + ; + BOOST_TEST(out.eq(ok.str())); + + return boost::report_errors(); +} + diff --git a/test/free_function/pre_post.cpp b/test/free_function/pre_post.cpp new file mode 100644 index 0000000..11d44a4 --- /dev/null +++ b/test/free_function/pre_post.cpp @@ -0,0 +1,64 @@ + +// Test free function contracts. + +#include "../aux_/oteststream.hpp" +#include "../aux_/cpcnt.hpp" +#include +#include +#include +#include +#include +#include +#include + +boost::contract::aux::test::oteststream out; + +struct x_tag; typedef boost::contract::aux::test::cpcnt x_type; +struct y_tag; typedef boost::contract::aux::test::cpcnt y_type; + +void swap(x_type& x, y_type& y) { + boost::shared_ptr old_x = + BOOST_CONTRACT_OLDOF(x_type::eval(x)); + boost::shared_ptr old_y = + BOOST_CONTRACT_OLDOF(y_type::eval(y)); + boost::contract::var contract = boost::contract::free_function() + .precondition([&] { + out << "swap::pre" << std::endl; + BOOST_CONTRACT_ASSERT(x.value != y.value); + }) + .postcondition([&] { + out << "swap::post" << std::endl; + BOOST_CONTRACT_ASSERT(x.value == old_y->value); + BOOST_CONTRACT_ASSERT(y.value == old_x->value); + }) + ; + out << "swap::body" << std::endl; + int save_x = x.value; + x.value = y.value; + y.value = save_x; +} + +int main() { + std::ostringstream ok; + + x_type x; x.value = 123; + y_type y; y.value = 456; + + out.str(""); + swap(x, y); + BOOST_TEST_EQ(x.value, 456); + BOOST_TEST_EQ(y.value, 123); + ok.str(""); + ok + << "swap::pre" << std::endl + << "swap::body" << std::endl + << "swap::post" << std::endl + ; + BOOST_TEST(out.eq(ok.str())); + + BOOST_TEST_EQ(x.copies(), 1); BOOST_TEST_EQ(x.evals(), 1); + BOOST_TEST_EQ(y.copies(), 1); BOOST_TEST_EQ(y.evals(), 1); + + return boost::report_errors(); +} + diff --git a/test/free_function/pre_post_decl.cpp b/test/free_function/pre_post_decl.cpp new file mode 100644 index 0000000..882d8b9 --- /dev/null +++ b/test/free_function/pre_post_decl.cpp @@ -0,0 +1,68 @@ + +// Test free function contracts using contract declaration functions. + +#include "../aux_/oteststream.hpp" +#include "../aux_/cpcnt.hpp" +#include +#include +#include +#include +#include +#include +#include +#include + +boost::contract::aux::test::oteststream out; + +struct x_tag; typedef boost::contract::aux::test::cpcnt x_type; +struct y_tag; typedef boost::contract::aux::test::cpcnt y_type; + +void swap(x_type const& x, y_type const& y, boost::contract::decl c) { + boost::shared_ptr old_x = + BOOST_CONTRACT_OLDOF(c, x_type::eval(x)); + boost::shared_ptr old_y = + BOOST_CONTRACT_OLDOF(c, y_type::eval(y)); + boost::contract::var contract = boost::contract::free_function(c) + .precondition([&] { + out << "swap::pre" << std::endl; + BOOST_CONTRACT_ASSERT(x.value != y.value); + }) + .postcondition([&] { + out << "swap::post" << std::endl; + BOOST_CONTRACT_ASSERT(x.value == old_y->value); + BOOST_CONTRACT_ASSERT(y.value == old_x->value); + }) + ; +} +void swap(x_type& x, y_type& y) { + boost::contract::var contract = boost::contract::decl_function(x, y, &swap); + out << "swap::body" << std::endl; + int save_x = x.value; + x.value = y.value; + y.value = save_x; +} + +int main() { + std::ostringstream ok; + + x_type x; x.value = 123; + y_type y; y.value = 456; + + out.str(""); + swap(x, y); + BOOST_TEST_EQ(x.value, 456); + BOOST_TEST_EQ(y.value, 123); + ok.str(""); + ok + << "swap::pre" << std::endl + << "swap::body" << std::endl + << "swap::post" << std::endl + ; + BOOST_TEST(out.eq(ok.str())); + + BOOST_TEST_EQ(x.copies(), 1); BOOST_TEST_EQ(x.evals(), 1); + BOOST_TEST_EQ(y.copies(), 1); BOOST_TEST_EQ(y.evals(), 1); + + return boost::report_errors(); +} + diff --git a/test/free_function/pre_post_pre-error.cpp b/test/free_function/pre_post_pre-error.cpp new file mode 100644 index 0000000..ae5a6e3 --- /dev/null +++ b/test/free_function/pre_post_pre-error.cpp @@ -0,0 +1,19 @@ + +// Test double pre error (for free func, but same for all contracts). + +#include +#include + +void f() { + boost::contract::var contract = boost::contract::free_function() + .precondition([] {}) + .postcondition([] {}) + .precondition([] {}) // Error (double pre, after a post). + ; +} + +int main() { + f(); + return 0; +} + diff --git a/test/free_function/pre_pre-error.cpp b/test/free_function/pre_pre-error.cpp new file mode 100644 index 0000000..fd03062 --- /dev/null +++ b/test/free_function/pre_pre-error.cpp @@ -0,0 +1,18 @@ + +// Test double error (for free func, but same for all contracts). + +#include +#include + +void f() { + boost::contract::var contract = boost::contract::free_function() + .precondition([] {}) + .precondition([] {}) // Error (double pre). + ; +} + +int main() { + f(); + return 0; +} + diff --git a/test/function/constructor.cpp b/test/function/constructor.cpp deleted file mode 100644 index 95f762c..0000000 --- a/test/function/constructor.cpp +++ /dev/null @@ -1,181 +0,0 @@ - -#include "../aux_/oteststream.hpp" -#include -#include -#include -#include -#include - -// Test constructor contracts for classes with and without bases. - -boost::contract::aux::test::oteststream out; - -struct d -# define BASES private boost::contract::constructor_precondition - : BASES -{ - typedef BOOST_CONTRACT_BASE_TYPES(BASES) base_types; -# undef BASES - - void invariant() const { - out << "d::inv" << std::endl; - } - - static void static_invariant() { - out << "d::static_inv" << std::endl; - } - - explicit d(unsigned const) : - boost::contract::constructor_precondition([&] { - out << "d::ctor::pre" << std::endl; - }) - { - auto c = boost::contract::constructor(this) - .postcondition([&] { - out << "d::ctor::post" << std::endl; - }) - ; - out << "d::ctor::body" << std::endl; - } -}; - -struct c -# define BASES private boost::contract::constructor_precondition, \ - public d - : BASES -{ - typedef BOOST_CONTRACT_BASE_TYPES(BASES) base_types; -# undef BASES - - void invariant() const { - out << "c::inv" << std::endl; - } - - static void static_invariant() { - out << "c::static_inv" << std::endl; - } - - explicit c(unsigned const x) : - boost::contract::constructor_precondition([&] { - out << "c::ctor::pre" << std::endl; - }), - d(x) - { - auto c = boost::contract::constructor(this) - .postcondition([&] { - out << "c::ctor::post" << std::endl; - }) - ; - out << "c::ctor::body" << std::endl; - } -}; - -struct b -# define BASES private boost::contract::constructor_precondition - : BASES -{ - typedef BOOST_CONTRACT_BASE_TYPES(BASES) base_types; -# undef BASES - - void invariant() const { - out << "b::inv" << std::endl; - } - - static void static_invariant() { - out << "b::static_inv" << std::endl; - } - - explicit b(unsigned const) : - boost::contract::constructor_precondition([&] { - out << "b::ctor::pre" << std::endl; - }) - { - auto c = boost::contract::constructor(this) - .postcondition([&] { - out << "b::ctor::post" << std::endl; - }) - ; - out << "b::ctor::body" << std::endl; - } -}; - -struct a -# define BASES private boost::contract::constructor_precondition, \ - public b, public c - : BASES -{ - typedef BOOST_CONTRACT_BASE_TYPES(BASES) base_types; -# undef BASES - - void invariant() const { - out << "a::inv" << std::endl; - BOOST_CONTRACT_ASSERT(value > 0); - } - - static void static_invariant() { - out << "a::static_inv" << std::endl; - } - - explicit a(unsigned const x) : - boost::contract::constructor_precondition([&] { - out << "a::ctor::pre" << std::endl; - BOOST_CONTRACT_ASSERT(x > 0); - }), - b(x), - c(x), - value(x) - { - auto c = boost::contract::constructor(this) - .postcondition([&] { - out << "a::ctor::post" << std::endl; - BOOST_CONTRACT_ASSERT(this->value == x); - }) - ; - out << "a::ctor::body" << std::endl; - } - - unsigned value; -}; - -int main() { - std::ostringstream ok; - - out.str(""); - a aa(123); - ok.str(""); - ok - << "a::ctor::pre" << std::endl - - << "b::ctor::pre" << std::endl - << "b::static_inv" << std::endl - << "b::ctor::body" << std::endl - << "b::static_inv" << std::endl - << "b::inv" << std::endl - << "b::ctor::post" << std::endl - - << "c::ctor::pre" << std::endl - - << "d::ctor::pre" << std::endl - << "d::static_inv" << std::endl - << "d::ctor::body" << std::endl - << "d::static_inv" << std::endl - << "d::inv" << std::endl - << "d::ctor::post" << std::endl - - << "c::static_inv" << std::endl - << "c::ctor::body" << std::endl - << "c::static_inv" << std::endl - << "c::inv" << std::endl - << "c::ctor::post" << std::endl - - << "a::static_inv" << std::endl - << "a::ctor::body" << std::endl - << "a::static_inv" << std::endl - << "a::inv" << std::endl - << "a::ctor::post" << std::endl - ; - BOOST_TEST(out.check(ok.str())); - - return boost::report_errors(); -} - diff --git a/test/function/destructor.cpp b/test/function/destructor.cpp deleted file mode 100644 index a0cdc6b..0000000 --- a/test/function/destructor.cpp +++ /dev/null @@ -1,138 +0,0 @@ - -#include "../aux_/oteststream.hpp" -#include -#include -#include -#include -#include - -// Test destructor contracts for classes with and without bases. - -boost::contract::aux::test::oteststream out; - -struct d { // Test inheritance level 0. - void invariant() const { - out << "d::inv" << std::endl; - } - - static void static_invariant() { - out << "d::static_inv" << std::endl; - } - - ~d() { - auto c = boost::contract::destructor(this) - .postcondition([&] { - out << "d::dtor::post" << std::endl; - }) - ; - out << "d::dtor::body" << std::endl; - } -}; - -struct c // Test inheritance level 1. - #define BASES public d - : BASES -{ - typedef BOOST_CONTRACT_BASE_TYPES(BASES) base_types; - #undef BASES - - void invariant() const { - out << "c::inv" << std::endl; - } - - static void static_invariant() { - out << "c::static_inv" << std::endl; - } - - ~c() { - auto c = boost::contract::destructor(this) - .postcondition([&] { - out << "c::dtor::post" << std::endl; - }) - ; - out << "c::dtor::body" << std::endl; - } -}; - -struct b { // Test inheritance level 0. - void invariant() const { - out << "b::inv" << std::endl; - } - - static void static_invariant() { - out << "b::static_inv" << std::endl; - } - - ~b() { - auto c = boost::contract::destructor(this) - .postcondition([&] { - out << "b::dtor::post" << std::endl; - }) - ; - out << "b::dtor::body" << std::endl; - } -}; - -struct a // Test multiple inheritance and inheritance level 2. - #define BASES public b, public c - : BASES -{ - typedef BOOST_CONTRACT_BASE_TYPES(BASES) base_types; - #undef BASES - - void invariant() const { - out << "a::inv" << std::endl; - } - - static void static_invariant() { - out << "a::static_inv" << std::endl; - } - - ~a() { - auto c = boost::contract::destructor(this) - .postcondition([&] { - out << "a::dtor::post" << std::endl; - }) - ; - out << "a::dtor::body" << std::endl; - } -}; - -int main() { - std::ostringstream ok; - - { - a aa; - out.str(""); - } // `a`'s destructor called, and `out` set, here. - ok.str(""); - ok - << "a::static_inv" << std::endl - << "a::inv" << std::endl - << "a::dtor::body" << std::endl - << "a::static_inv" << std::endl - << "a::dtor::post" << std::endl - - << "c::static_inv" << std::endl - << "c::inv" << std::endl - << "c::dtor::body" << std::endl - << "c::static_inv" << std::endl - << "c::dtor::post" << std::endl - - << "d::static_inv" << std::endl - << "d::inv" << std::endl - << "d::dtor::body" << std::endl - << "d::static_inv" << std::endl - << "d::dtor::post" << std::endl - - << "b::static_inv" << std::endl - << "b::inv" << std::endl - << "b::dtor::body" << std::endl - << "b::static_inv" << std::endl - << "b::dtor::post" << std::endl - ; - BOOST_TEST(out.check(ok.str())); - - return boost::report_errors(); -} - diff --git a/test/function/private_member.cpp b/test/function/private_member.cpp deleted file mode 100644 index e15b688..0000000 --- a/test/function/private_member.cpp +++ /dev/null @@ -1,98 +0,0 @@ - -#include "../aux_/oteststream.hpp" -#include -#include -#include -#include - -// Test private member (not public API so substitution principle does not -// apply so no subcontracting, plus not public API so no invariants checked). - -boost::contract::aux::test::oteststream out; - -struct b { - void invariant() const { - out << "b::inv" << std::endl; - } - - static void static_invariant() { - out << "b::static_inv" << std::endl; - } - - friend int main(); - -private: - void f() { - auto c = boost::contract::private_member() - .precondition([&] { - out << "b::f::pre" << std::endl; - }) - .postcondition([&] { - out << "b::f::post" << std::endl; - }) - ; - out << "b::f::body" << std::endl; - } -}; - -struct a - #define BASES public b - : BASES // Test no subcontracting even if public base. -{ - typedef BOOST_CONTRACT_BASE_TYPES(BASES) base_types; - #undef BASES - - void invariant() const { // Test no invariants checked. - out << "a::inv" << std::endl; - } - - static void static_invariant() { // Test no static invariants checked. - out << "a::static_inv" << std::endl; - } - - friend int main(); - -private: - void f() { - auto c = boost::contract::private_member() - .precondition([&] { - out << "a::f::pre" << std::endl; - }) - .postcondition([&] { - out << "a::f::post" << std::endl; - }) - ; - out << "a::f::body" << std::endl; - } -}; - -int main() { - std::ostringstream ok; - - b bb; - out.str(""); - bb.f(); // Test without base. - ok.str(""); - ok - << "b::f::pre" << std::endl - << "b::f::body" << std::endl - << "b::f::post" << std::endl - ; - BOOST_TEST(out.check(ok.str())); - - out << std::endl; - - a aa; - out.str(""); - aa.f(); // Test with base. - ok.str(""); - ok - << "a::f::pre" << std::endl - << "a::f::body" << std::endl - << "a::f::post" << std::endl - ; - BOOST_TEST(out.check(ok.str())); - - return boost::report_errors(); -} - diff --git a/test/function/protected_member.cpp b/test/function/protected_member.cpp deleted file mode 100644 index 5c25109..0000000 --- a/test/function/protected_member.cpp +++ /dev/null @@ -1,98 +0,0 @@ - -#include "../aux_/oteststream.hpp" -#include -#include -#include -#include - -// Test protected member (not public API so substitution principle does not -// apply so no subcontracting, plus not public API so no invariants checked). - -boost::contract::aux::test::oteststream out; - -struct b { - void invariant() const { - out << "b::inv" << std::endl; - } - - static void static_invariant() { - out << "b::static_inv" << std::endl; - } - - friend int main(); - -protected: - void f() { - auto c = boost::contract::protected_member() - .precondition([&] { - out << "b::f::pre" << std::endl; - }) - .postcondition([&] { - out << "b::f::post" << std::endl; - }) - ; - out << "b::f::body" << std::endl; - } -}; - -struct a - #define BASES public b - : BASES // Test no subcontracting even if public base. -{ - typedef BOOST_CONTRACT_BASE_TYPES(BASES) base_types; - #undef BASES - - void invariant() const { // Test no invariants checked. - out << "a::inv" << std::endl; - } - - static void static_invariant() { // Test no static invariants checked. - out << "a::static_inv" << std::endl; - } - - friend int main(); - -protected: - void f() { - auto c = boost::contract::protected_member() - .precondition([&] { - out << "a::f::pre" << std::endl; - }) - .postcondition([&] { - out << "a::f::post" << std::endl; - }) - ; - out << "a::f::body" << std::endl; - } -}; - -int main() { - std::ostringstream ok; - - b bb; - out.str(""); - bb.f(); // Test without base. - ok.str(""); - ok - << "b::f::pre" << std::endl - << "b::f::body" << std::endl - << "b::f::post" << std::endl - ; - BOOST_TEST(out.check(ok.str())); - - out << std::endl; - - a aa; - out.str(""); - aa.f(); // Test with base. - ok.str(""); - ok - << "a::f::pre" << std::endl - << "a::f::body" << std::endl - << "a::f::post" << std::endl - ; - BOOST_TEST(out.check(ok.str())); - - return boost::report_errors(); -} - diff --git a/test/function/public_member.cpp b/test/function/public_member.cpp deleted file mode 100644 index 5e52fa3..0000000 --- a/test/function/public_member.cpp +++ /dev/null @@ -1,241 +0,0 @@ - -#include "../aux_/oteststream.hpp" -#include -#include -#include -#include -#include -#include - -// Test public member contracts for classes with and without bases, with and -// without virtual bodies. - -boost::contract::aux::test::oteststream out; - -// Test inheritance level 0 (no bases). -template -struct e { - void invariant() const { out << "e::inv" << std::endl; } - static void static_invariant() { out << "e::static_inv" << std::endl; } - - virtual ~e() {} - - // Test contract allows (but does not require) extra introspection, - // function pointer, etc. parameter because class has no bases. - boost::contract::var f_contract(T const& x, - boost::contract::virtual_* v = 0) const { - return boost::contract::public_member(v, this, x) - .precondition([&] { - out << "e::f::pre" << std::endl; - BOOST_CONTRACT_ASSERT(false); // To check subcontracted pre. - }) - .postcondition([&] { out << "e::f::post" << std::endl; }) - ; - } - virtual void f(T const& x) = 0; - BOOST_CONTRACT_INTROSPECT(f_contract) -}; - -// Test inheritance level 0 (no bases). -template -struct d { - void invariant() const { out << "d::inv" << std::endl; } - static void static_invariant() { out << "d::static_inv" << std::endl; } - - virtual ~d() {} - - // Test contract does not require (but allows) extra introspection, - // function pointer, etc. parameter because class has no bases. - boost::contract::var f_contract(T const& x, - boost::contract::virtual_* v = 0) const { - return boost::contract::public_member(v, this) - .precondition([&] { - out << "d::f::pre" << std::endl; - BOOST_CONTRACT_ASSERT(false); // To check subcontracted pre. - }) - .postcondition([&] { out << "d::f::post" << std::endl; }) - ; - } - virtual void f(T const& x) { - boost::contract::var contract = f_contract(x); - out << "d::f::body" << std::endl; - } - - // Test non-contracted virtual function in contracted base. - virtual void k() = 0; -}; - -// Test inheritance level 1 and multiple inheritance (both contracted bases). -template -struct c - #define BASES public e, public d - : BASES -{ - typedef BOOST_CONTRACT_BASE_TYPES(BASES) base_types; - #undef BASES - - void invariant() const { out << "c::inv" << std::endl; } - static void static_invariant() { out << "c::static_inv" << std::endl; } - - virtual ~c() {} - - // Test virtual overrides virtual function. - boost::contract::var f_contract(T const& x, - boost::contract::virtual_* v = 0) const { - return boost::contract::public_member(v, this, x) - .precondition([&] { - out << "c::f::pre" << std::endl; - BOOST_CONTRACT_ASSERT(x < 0); // To check subcontracted pre. - }) - .postcondition([&] { out << "c::f::post" << std::endl; }) - ; - } - virtual void f(T const& x) { - boost::contract::var contract = f_contract(x); - out << "c::f::body" << std::endl; - } - BOOST_CONTRACT_INTROSPECT(f_contract) - - void k() {} -}; - -// Test a non-contracted base. -template -struct b { - virtual ~b() {} - virtual void g() = 0; - virtual void h() {} -}; - -// Test inheritance level 2 and multiple inheritance (one contracted base, -// and one not). -template -struct a - #define BASES public c, public b - : BASES -{ - typedef BOOST_CONTRACT_BASE_TYPES(BASES) base_types; - #undef BASES - - void invariant() const { out << "a::inv" << std::endl; } - static void static_invariant() { out << "a::static_inv" << std::endl; } - - virtual ~a() {} - - // Test non-virtual overrides virtual function. - void f(T const& x) { - boost::contract::var contract = boost::contract::public_member< - introspect_f_contract>(this, x) - .precondition([&] { out << "a::f::pre" << std::endl; }) - .postcondition([&] { out << "a::f::post" << std::endl; }) - ; - out << "a::f::body" << std::endl; - } - BOOST_CONTRACT_INTROSPECT(f_contract) - -private: - void g() {} -}; - -int main() { - std::ostringstream ok; - ok.str(""); - ok - << "e::static_inv" << std::endl - << "e::inv" << std::endl - << "d::static_inv" << std::endl - << "d::inv" << std::endl - << "c::static_inv" << std::endl - << "c::inv" << std::endl - << "a::static_inv" << std::endl - << "a::inv" << std::endl - - << "e::f::pre" << std::endl - << "d::f::pre" << std::endl - << "c::f::pre" << std::endl - << "a::f::pre" << std::endl - - << "a::f::body" << std::endl - - << "e::static_inv" << std::endl - << "e::inv" << std::endl - << "d::static_inv" << std::endl - << "d::inv" << std::endl - << "c::static_inv" << std::endl - << "c::inv" << std::endl - << "a::static_inv" << std::endl - << "a::inv" << std::endl - - << "e::f::post" << std::endl - << "d::f::post" << std::endl - << "c::f::post" << std::endl - << "a::f::post" << std::endl - ; - - typedef int i; - typedef unsigned int u; - i x = 123; - - // Test virtual call via derived class. - a ai; - out.str(""); - ai.f(x); - BOOST_TEST(out.check(ok.str())); - - // Test virtual call via base class reference. - out << std::endl; - c& ci = ai; - out.str(""); - ci.f(x); - BOOST_TEST(out.check(ok.str())); - - // Test virtual call via base class pointer. - out << std::endl; - d* di = &ai; - out.str(""); - di->f(x); - BOOST_TEST(out.check(ok.str())); - - // Test pure virtual call via abstract base class (reference). - out << std::endl; - e& ei = ci; - out.str(""); - ei.f(x); - BOOST_TEST(out.check(ok.str())); - - // Test virtual call to derived class c (to double check no a's contracts). - out << std::endl; - c cii; - out.str(""); - cii.f(-x); // Negative x so c::f pre will pass this time (not base anymore). - ok.str(""); - ok - << "e::static_inv" << std::endl - << "e::inv" << std::endl - << "d::static_inv" << std::endl - << "d::inv" << std::endl - << "c::static_inv" << std::endl - << "c::inv" << std::endl - - << "e::f::pre" << std::endl - << "d::f::pre" << std::endl - << "c::f::pre" << std::endl - - << "c::f::body" << std::endl - - << "e::static_inv" << std::endl - << "e::inv" << std::endl - << "d::static_inv" << std::endl - << "d::inv" << std::endl - << "c::static_inv" << std::endl - << "c::inv" << std::endl - - << "e::f::post" << std::endl - << "d::f::post" << std::endl - << "c::f::post" << std::endl - ; - BOOST_TEST(out.check(ok.str())); - - return boost::report_errors(); -} - diff --git a/test/function/public_static_member.cpp b/test/function/public_static_member.cpp deleted file mode 100644 index dca0f1b..0000000 --- a/test/function/public_static_member.cpp +++ /dev/null @@ -1,96 +0,0 @@ - -#include "../aux_/oteststream.hpp" -#include -#include -#include -#include - -// Test static member (no object so substitution principle does not apply so no -// subcontracting, plus no object so only static invariants checked). - -boost::contract::aux::test::oteststream out; - -struct b { - void invariant() const { - out << "b::inv" << std::endl; - } - - static void static_invariant() { - out << "b::static_inv" << std::endl; - } - - static void s() { - auto c = boost::contract::public_member() - .precondition([&] { - out << "b::s::pre" << std::endl; - }) - .postcondition([&] { - out << "b::s::post" << std::endl; - }) - ; - out << "b::s::body" << std::endl; - } -}; - - -struct a - #define BASES public b - : BASES // Test no subcontracting even if public base. -{ - typedef BOOST_CONTRACT_BASE_TYPES(BASES) base_types; - #undef BASES - - void invariant() const { // Test no invariants checked. - out << "a::inv" << std::endl; - } - - static void static_invariant() { // Test static invariants checked. - out << "a::static_inv" << std::endl; - } - - static void s() { - auto c = boost::contract::public_member() - .precondition([&] { - out << "a::s::pre" << std::endl; - }) - .postcondition([&] { - out << "a::s::post" << std::endl; - }) - ; - out << "a::s::body" << std::endl; - } -}; - -int main() { - std::ostringstream ok; - - out.str(""); - b::s(); // Test static call directly from class (no object) and no base. - ok.str(""); - ok - << "b::static_inv" << std::endl - << "b::s::pre" << std::endl - << "b::s::body" << std::endl - << "b::static_inv" << std::endl - << "b::s::post" << std::endl - ; - BOOST_TEST(out.check(ok.str())); - - out << std::endl; - - a aa; - out.str(""); - aa.s(); // Test static call from object and with base. - ok.str(""); - ok - << "a::static_inv" << std::endl - << "a::s::pre" << std::endl - << "a::s::body" << std::endl - << "a::static_inv" << std::endl - << "a::s::post" << std::endl - ; - BOOST_TEST(out.check(ok.str())); - - return boost::report_errors(); -} - diff --git a/test/oldof/oldof.cpp b/test/oldof/oldof.cpp deleted file mode 100644 index 62aa14d..0000000 --- a/test/oldof/oldof.cpp +++ /dev/null @@ -1,51 +0,0 @@ - -#include -#include -#include - -// Test old-values evaluated and copied only once. - -unsigned copy_count, eval_count; - -struct num { - int i; - explicit num(int const _i) : i(_i) {} - num(num const& n) : i(n.i) { ++copy_count; } -private: - num& operator=(num const&); -}; - -num const& eval(num const& n) { ++eval_count; return n; } - -void swap(num& a, num& b) { - // Test explicit type declaration. - boost::shared_ptr old_a = BOOST_CONTRACT_OLDOF(eval(a)); - // Test auto type declaration (C++11). - auto old_b = BOOST_CONTRACT_OLDOF(eval(b)); - boost::contract::var contract = boost::contract::free_function() - .precondition([&] {}) - .postcondition([&] { - BOOST_TEST_EQ(a.i, old_b->i); - BOOST_TEST_EQ(b.i, old_a->i); - }) - ; - int a_i = a.i; - a.i = b.i; - b.i = a_i; -} - -int main() { - copy_count = eval_count = 0; - num a(1), b(2); - swap(a, b); -#ifndef BOOST_CONTRACT_CONFIG_NO_POSTCONDITIONS - BOOST_TEST_EQ(copy_count, 2); - BOOST_TEST_EQ(eval_count, 2); -#else - BOOST_TEST_EQ(copy_count, 0); - BOOST_TEST_EQ(eval_count, 0); -#endif - - return boost::report_errors(); -} - diff --git a/test/oldof/oldof_auto_const_error.cpp b/test/oldof/oldof_auto_const_error.cpp deleted file mode 100644 index ed573aa..0000000 --- a/test/oldof/oldof_auto_const_error.cpp +++ /dev/null @@ -1,23 +0,0 @@ - -#include -#include -#include - -// Test auto old value declarations (C++11) must be const. - -void inc(int& x) { - auto old_x = BOOST_CONTRACT_OLDOF(x); // OK. - auto c = boost::contract::free_function() - .postcondition([&] { - BOOST_CONTRACT_ASSERT(*old_x = x - 1); // Error. - }) - ; - ++x; -} - -int main() { - int x = 1; - inc(x); - return 0; -} - diff --git a/test/oldof/oldof_const_error.cpp b/test/oldof/oldof_const_error.cpp deleted file mode 100644 index b55d846..0000000 --- a/test/oldof/oldof_const_error.cpp +++ /dev/null @@ -1,24 +0,0 @@ - -#include -#include -#include -#include - -// Test old value declarations must be const. - -void inc(int& x) { - boost::shared_ptr old_x = BOOST_CONTRACT_OLDOF(x); // Error. - auto c = boost::contract::free_function() - .postcondition([&] { - BOOST_CONTRACT_ASSERT(*old_x == x - 1); // OK. - }) - ; - ++x; -} - -int main() { - int x = 1; - inc(x); - return 0; -} - diff --git a/test/oldof/oldof_v.cpp b/test/oldof/oldof_v.cpp deleted file mode 100644 index 4d78093..0000000 --- a/test/oldof/oldof_v.cpp +++ /dev/null @@ -1,184 +0,0 @@ - -#include -#include "../aux_/friend.hpp" -#include -#include -#include -#include -#include -#include - -// Test old-values evaluated and copied only once, in virtual calls. - -unsigned copy_count, eval_count; - -struct str { - std::string x; - str(std::string const& _x) : x(_x) {} - str(str const& s) : x(s.x) { ++copy_count; } -private: - str& operator=(str const&); -}; - -str const& eval(str const& s) { ++eval_count; return s; } - -struct d { - str s; - - d() : s("d") {} - - void invariant() const {} - static void static_invariant() {} - - boost::contract::var f_contract(char const& z, - boost::contract::virtual_* v = 0) const { - // Test explicit type declaration. - boost::shared_ptr old_s = BOOST_CONTRACT_OLDOF(v, eval(s)); - if(boost::contract::aux::test::friend_::checking_post(v)) { - BOOST_TEST(old_s); - BOOST_TEST_EQ(old_s->x, "d"); - } else { - BOOST_TEST(!old_s); - } - return boost::contract::public_member(v, this) - .precondition([&] {}) - .postcondition([&] { BOOST_TEST_EQ(old_s->x, "d"); }) - ; - } - virtual void f(char const z) { - boost::contract::var contract = f_contract(z); - s.x += z; - } -}; - -struct c - #define BASES public d - : BASES -{ - typedef BOOST_CONTRACT_BASE_TYPES(BASES) base_types; - #undef BASES - - str s; - - c() : s("c") {} - - void invariant() const {} - static void static_invariant() {} - - boost::contract::var f_contract(char const& z, - boost::contract::virtual_* v = 0) const { - // Test auto type declaration (C++11). - auto old_s = BOOST_CONTRACT_OLDOF(v, eval(s)); - if(boost::contract::aux::test::friend_::checking_post(v)) { - BOOST_TEST(old_s); - BOOST_TEST_EQ(old_s->x, "c"); - } else { - BOOST_TEST(!old_s); - } - return boost::contract::public_member(v, this, z) - .precondition([&] {}) - .postcondition([&] { BOOST_TEST_EQ(old_s->x, "c"); }) - ; - } - virtual void f(char const z) = 0; - BOOST_CONTRACT_INTROSPECT(f_contract) -}; - -struct b { - str s; - - b() : s("b") {} - - void invariant() const {} - static void static_invariant() {} - - boost::contract::var f_contract(char const& z, - boost::contract::virtual_* v = 0) const { - boost::shared_ptr old_s = BOOST_CONTRACT_OLDOF(v, eval(s)); - if(boost::contract::aux::test::friend_::checking_post(v)) { - BOOST_TEST(old_s); - BOOST_TEST_EQ(old_s->x, "b"); - } else { - BOOST_TEST(!old_s); - } - return boost::contract::public_member(v, this) - .precondition([&] {}) - .postcondition([&] { BOOST_TEST_EQ(old_s->x, "b"); }) - ; - } - virtual void f(char const z) = 0; -}; - -struct a - #define BASES public b, public c - : BASES -{ - typedef BOOST_CONTRACT_BASE_TYPES(BASES) base_types; - #undef BASES - - str s; - - a() : s("a") {} - - void invariant() const {} - static void static_invariant() {} - - boost::contract::var f_contract(char const& z, - boost::contract::virtual_* v = 0) const { - auto old_s = BOOST_CONTRACT_OLDOF(v, eval(s)); - if(boost::contract::aux::test::friend_::checking_post(v)) { - BOOST_TEST(old_s); - BOOST_TEST_EQ(old_s->x, "a"); - } else { - BOOST_TEST(!old_s); - } - return boost::contract::public_member(v, this, z) - .precondition([&] { - // std::clog << "pre>>>" << old_s->x << "<<<" << std::endl; - }) - .postcondition([&] { - std::clog << "post>>> " << old_s->x << "<<<" << std::endl; - BOOST_TEST_EQ(old_s->x, "a"); - }) - ; - } - virtual void f(char const z) { - boost::shared_ptr v = - boost::make_shared(); - boost::contract::var contract = f_contract(z, v.get()); - std::clog << v->old_values_.size() << std::endl; - std::clog << "body start" << std::endl; - s.x += z; - std::clog << "body finish" << std::endl; - } - BOOST_CONTRACT_INTROSPECT(f_contract) -}; - -int main() { - // Test with `v` and bases. - copy_count = eval_count = 0; - a aa; - aa.f('z'); -#ifndef BOOST_CONTRACT_CONFIG_NO_POSTCONDITIONS - BOOST_TEST_EQ(copy_count, 4); - BOOST_TEST_EQ(eval_count, 4); -#else - BOOST_TEST_EQ(copy_count, 0); - BOOST_TEST_EQ(eval_count, 0); -#endif - -// // Test with `v` but without bases. -// copy_count = eval_count = 0; -// d dd; -// dd.f('z'); -//#ifndef BOOST_CONTRACT_CONFIG_NO_POSTCONDITIONS -// BOOST_TEST_EQ(copy_count, 1); -// BOOST_TEST_EQ(eval_count, 1); -//#else -// BOOST_TEST_EQ(copy_count, 0); -// BOOST_TEST_EQ(eval_count, 0); -//#endif - - return boost::report_errors(); -} - diff --git a/test/oldof/oldof_v_auto_const_error.cpp b/test/oldof/oldof_v_auto_const_error.cpp deleted file mode 100644 index 2f997cc..0000000 --- a/test/oldof/oldof_v_auto_const_error.cpp +++ /dev/null @@ -1,32 +0,0 @@ - -#include -#include -#include -#include - -// Test virtual auto old value declarations (C++11) must be const. - -struct num { - int x; - - void inc(int const delta, boost::contract::virtual_body v = 0) { - auto old_x = BOOST_CONTRACT_OLDOF(v, x); // OK. - auto c = boost::contract::public_member(v, - this, &num::inc, delta) - .postcondition([&] { - BOOST_CONTRACT_ASSERT(*old_x = x - delta); // Error. - }) - ; - inc_body(delta); - } - virtual void inc_body(int const delta) { x = x + delta; } - BOOST_CONTRACT_INTROSPECT(inc) -}; - -int main() { - num n; - n.x = 10; - n.inc(5); - return 0; -} - diff --git a/test/oldof/oldof_v_const_error.cpp b/test/oldof/oldof_v_const_error.cpp deleted file mode 100644 index ba8e37b..0000000 --- a/test/oldof/oldof_v_const_error.cpp +++ /dev/null @@ -1,32 +0,0 @@ - -#include -#include -#include -#include - -// Test virtual old value declarations must be const. - -struct num { - int x; - - void inc(int const delta, boost::contract::virtual_body v = 0) { - boost::shared_ptr old_x = BOOST_CONTRACT_OLDOF(v, x); // Error. - auto c = boost::contract::public_member(v, - this, &num::inc, delta) - .postcondition([&] { - BOOST_CONTRACT_ASSERT(*old_x == x - delta); // OK. - }) - ; - inc_body(delta); - } - virtual void inc_body(int const delta) { x = x + delta; } - BOOST_CONTRACT_INTROSPECT(inc) -}; - -int main() { - num n; - n.x = 10; - n.inc(5); - return 0; -} - diff --git a/test/public_member/bases.cpp b/test/public_member/bases.cpp new file mode 100644 index 0000000..dfbb4e0 --- /dev/null +++ b/test/public_member/bases.cpp @@ -0,0 +1,164 @@ + +// Test public member subcontracting. + +#include "../aux_/oteststream.hpp" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +boost::contract::aux::test::oteststream out; + +template +struct t { + void invariant() const { + out << Id << "::inv" << std::endl; + BOOST_CONTRACT_ASSERT(z != ""); + } + static void static_invariant() { out << Id << "::static_inv" << std::endl; } + + std::string z; + t() : z("") { z.push_back(Id); } + + void f(std::string const& s, boost::contract::decl c) const { + boost::shared_ptr old_u = BOOST_CONTRACT_OLDOF(c, z); + boost::shared_ptr old_s = BOOST_CONTRACT_OLDOF(c, s); + boost::contract::var contract = boost::contract::public_member(c, this) + .precondition([&] { + out << Id << "::f::pre" << std::endl; + BOOST_CONTRACT_ASSERT(s != ""); +// BOOST_CONTRACT_ASSERT(false); + }) + .postcondition([&] { + out << Id << "::f::post" << std::endl; + BOOST_CONTRACT_ASSERT(z == *old_u + *old_s); + BOOST_CONTRACT_ASSERT(s.find(*old_u) != std::string::npos); + }) + ; + } + // Test pure virtual (=> decl). + virtual void f(std::string& s) = 0; +}; + +struct c + #define BASES public t<'d'>, protected t<'p'>, private t<'q'>, public t<'e'> + : BASES +{ + typedef BOOST_CONTRACT_BASE_TYPES(BASES) base_types; + #undef BASES + + void invariant() const { + out << "c::inv" << std::endl; + BOOST_CONTRACT_ASSERT(y != ""); + } + static void static_invariant() { out << "c::static_inv" << std::endl; } + + std::string y; + c() : y("c") {} + + void f(std::string const& s, boost::contract::decl c) const { + boost::shared_ptr old_y = BOOST_CONTRACT_OLDOF(c, y); + boost::shared_ptr old_s = BOOST_CONTRACT_OLDOF(c, s); + boost::contract::var contract = boost::contract::public_member< + introspect_f>(c, this, s) + .precondition([&] { + out << "c::f::pre" << std::endl; + BOOST_CONTRACT_ASSERT(s != ""); +// BOOST_CONTRACT_ASSERT(false); + }) + .postcondition([&] { + out << "c::f::post" << std::endl; + BOOST_CONTRACT_ASSERT(y == *old_y + *old_s); + BOOST_CONTRACT_ASSERT(s.find(*old_y) != std::string::npos); + }) + ; + } + // Test both overriding (=> introspect) and virtual (=> decl). + virtual void f(std::string& s) /* override */ { + boost::contract::var contract = boost::contract::decl_function( + this, s, &c::f); + out << "c::f::body" << std::endl; + } + BOOST_CONTRACT_INTROSPECT(f) +}; + +// Test not (fully) contracted base is not part of subcontracting. +struct b { + virtual void f(std::string&) = 0; // No contract. +}; + +// Test public member with both non-contracted and contracted bases. +struct a + #define BASES public b, public c + : BASES +{ + typedef BOOST_CONTRACT_BASE_TYPES(BASES) base_types; + #undef BASES + + void invariant() const { + out << "a::inv" << std::endl; + BOOST_CONTRACT_ASSERT(x != ""); + } + static void static_invariant() { out << "a::static_inv" << std::endl; } + + std::string x; + a() : x("a") {} + + // Test overriding (=> introspect). + void f(std::string& s) /* override */ { + boost::shared_ptr old_x = BOOST_CONTRACT_OLDOF(x); + boost::shared_ptr old_s = BOOST_CONTRACT_OLDOF(s); + boost::contract::var contract = boost::contract::public_member< + introspect_f>(this, s) + .precondition([&] { + out << "a::f::pre" << std::endl; + BOOST_CONTRACT_ASSERT(s != ""); + }) + .postcondition([&] { + out << "a::f::post" << std::endl; + BOOST_CONTRACT_ASSERT(x == *old_x + *old_s); + BOOST_CONTRACT_ASSERT(s.find(*old_x) != std::string::npos); + }) + ; + out << "a::f::body" << std::endl; + + std::string save_s = s; + std::string save = x; + x += save_s; + s = save; + + save = y; + y += save_s; + s += save; + + save = t<'d'>::z; + t<'d'>::z += save_s; + s += save; + + save = t<'e'>::z; + t<'e'>::z += save_s; + s += save; + } + BOOST_CONTRACT_INTROSPECT(f) +}; + +int main() { + a aa; + std::string s = "!"; + aa.f(s); + std::cout << s << std::endl; + std::cout << aa.x << std::endl; + std::cout << aa.y << std::endl; + std::cout << aa.t<'d'>::z << std::endl; + //BOOST_TEST_EQ(aa.val(), 456); + //BOOST_TEST_EQ(i, 123); + + return boost::report_errors(); +} + diff --git a/test/set/creation_set_post_nothing_comb.cpp b/test/set/creation_set_post_nothing_comb.cpp deleted file mode 100644 index b7067b2..0000000 --- a/test/set/creation_set_post_nothing_comb.cpp +++ /dev/null @@ -1,95 +0,0 @@ - -#include "../aux_/oteststream.hpp" -#include -#include -#include - -// Test post or nothing combinations that can be set for constructors -// (destructors use same setter objects, so no need to test those too). - -boost::contract::aux::test::oteststream out; - -struct nothing { - void invariant() const { out << "inv" << std::endl; } - static void static_invariant() { out << "static_inv" << std::endl; } - - explicit nothing() { - auto c = boost::contract::constructor(this); - out << "body" << std::endl; - } -}; - -struct pre_only : private boost::contract::constructor_precondition { - void invariant() const { out << "inv" << std::endl; } - static void static_invariant() { out << "static_inv" << std::endl; } - - explicit pre_only() : - boost::contract::constructor_precondition([&] { - out << "pre" << std::endl; - }) - { - auto c = boost::contract::constructor(this); - out << "body" << std::endl; - } -}; - -struct post_only { - void invariant() const { out << "inv" << std::endl; } - static void static_invariant() { out << "static_inv" << std::endl; } - - explicit post_only() { - auto c = boost::contract::constructor(this) - .postcondition([&] { out << "post" << std::endl; }) - ; - out << "body" << std::endl; - } -}; - -struct pre_post : private boost::contract::constructor_precondition { - void invariant() const { out << "inv" << std::endl; } - static void static_invariant() { out << "static_inv" << std::endl; } - - explicit pre_post() : - boost::contract::constructor_precondition([&] { - out << "pre" << std::endl; - }) - { - auto c = boost::contract::constructor(this) - .postcondition([&] { out << "post" << std::endl; }) - ; - out << "body" << std::endl; - } -}; - -int main() { - std::ostringstream ok; - - out.str(""); - nothing n; - ok.str(""); ok << "static_inv" << std::endl << "body" << std::endl << - "static_inv" << std::endl << "inv" << std::endl; - BOOST_TEST(out.check(ok.str())); - - out.str(""); - pre_only e; - ok.str(""); ok << "pre" << std::endl << "static_inv" << std::endl << "body" - << std::endl << "static_inv" << std::endl << "inv" << std::endl; - BOOST_TEST(out.check(ok.str())); - - out.str(""); - post_only o; - ok.str(""); ok << "static_inv" << std::endl << "body" << std::endl << - "static_inv" << std::endl << "inv" << std::endl << "post" << - std::endl; - BOOST_TEST(out.check(ok.str())); - - out.str(""); - pre_post pp; - ok.str(""); ok << "pre" << std::endl << "static_inv" << std::endl << "body" - << std::endl << "static_inv" << std::endl << "inv" << std::endl << - "post" << std::endl; - BOOST_TEST(out.check(ok.str())); - - return boost::report_errors(); -} - diff --git a/test/set/creation_set_post_post_error.cpp b/test/set/creation_set_post_post_error.cpp deleted file mode 100644 index 1010a94..0000000 --- a/test/set/creation_set_post_post_error.cpp +++ /dev/null @@ -1,20 +0,0 @@ - -#include - -// Test post cannot be set twice for constructors -// (destructors use same setter objects, so no need to test those too). - -struct a { - explicit a() { - auto c = boost::contract::constructor(this) - .postcondition([&] {}) - .postcondition([&] {}) // Error. - ; - } -}; - -int main() { - a aa; - return 0; -} - diff --git a/test/set/creation_set_post_pre_error.cpp b/test/set/creation_set_post_pre_error.cpp deleted file mode 100644 index d8ef05d..0000000 --- a/test/set/creation_set_post_pre_error.cpp +++ /dev/null @@ -1,20 +0,0 @@ - -#include - -// Test pre cannot be set (not even after post) for constructors -// (destructors use same setter objects, so no need to test those too). - -struct a { - explicit a() { - auto c = boost::contract::constructor(this) - .postcondition([&] {}) - .precondition([&] {}) // Error. - ; - } -}; - -int main() { - a aa; - return 0; -} - diff --git a/test/set/creation_set_pre_error.cpp b/test/set/creation_set_pre_error.cpp deleted file mode 100644 index 0aee147..0000000 --- a/test/set/creation_set_pre_error.cpp +++ /dev/null @@ -1,19 +0,0 @@ - -#include - -// Test pre cannot be set for constructors -// (destructors use same setter objects, so no need to test those too). - -struct a { - explicit a() { - auto c = boost::contract::constructor(this) - .precondition([&] {}) // Error. - ; - } -}; - -int main() { - a aa; - return 0; -} - diff --git a/test/set/function_set_post_post_error.cpp b/test/set/function_set_post_post_error.cpp deleted file mode 100644 index 64d5dbf..0000000 --- a/test/set/function_set_post_post_error.cpp +++ /dev/null @@ -1,14 +0,0 @@ - -#include - -// Test post cannot be set twice for free functions -// (member functions use same setter objects, so no need to test those too). - -int main() { - auto c = boost::contract::free_function() - .postcondition([&] {}) - .postcondition([&] {}) // Error. - ; - return 0; -} - diff --git a/test/set/function_set_post_pre_post_error.cpp b/test/set/function_set_post_pre_post_error.cpp deleted file mode 100644 index 8354a43..0000000 --- a/test/set/function_set_post_pre_post_error.cpp +++ /dev/null @@ -1,15 +0,0 @@ - -#include - -// Test post cannot be set twice (not even after pre) for free functions -// (member functions use same setter objects, so no need to test those too). - -int main() { - auto c = boost::contract::free_function() - .postcondition([&] {}) - .precondition([&] {}) - .postcondition([&] {}) // Error. - ; - return 0; -} - diff --git a/test/set/function_set_post_pre_pre_error.cpp b/test/set/function_set_post_pre_pre_error.cpp deleted file mode 100644 index 412e585..0000000 --- a/test/set/function_set_post_pre_pre_error.cpp +++ /dev/null @@ -1,15 +0,0 @@ - -#include - -// Test pre cannot be set twice (not even after post) for free functions -// (member functions use same setter objects, so no need to test those too). - -int main() { - auto c = boost::contract::free_function() - .postcondition([&] {}) - .precondition([&] {}) - .precondition([&] {}) // Error. - ; - return 0; -} - diff --git a/test/set/function_set_pre_post_nothing_comb.cpp b/test/set/function_set_pre_post_nothing_comb.cpp deleted file mode 100644 index b06213b..0000000 --- a/test/set/function_set_pre_post_nothing_comb.cpp +++ /dev/null @@ -1,78 +0,0 @@ - -#include "../aux_/oteststream.hpp" -#include -#include -#include - -// Test pre and post, or nothing combinations that can be set for free functions -// (member functions use same setter objects, so no need to test those too). - -boost::contract::aux::test::oteststream out; - -void nothing() { - auto c = boost::contract::free_function(); - out << "body" << std::endl; -} - -void pre_only() { - auto c = boost::contract::free_function() - .precondition([&] { out << "pre" << std::endl; }) - ; - out << "body" << std::endl; -} - -void post_only() { - auto c = boost::contract::free_function() - .postcondition([&] { out << "post" << std::endl; }) - ; - out << "body" << std::endl; -} - -void pre_post() { - auto c = boost::contract::free_function() - .precondition([&] { out << "pre" << std::endl; }) - .postcondition([&] { out << "post" << std::endl; }) - ; - out << "body" << std::endl; -} - -void post_pre() { - auto c = boost::contract::free_function() - .postcondition([&] { out << "post" << std::endl; }) - .precondition([&] { out << "pre" << std::endl; }) - ; - out << "body" << std::endl; -} - -int main() { - std::ostringstream ok; - - out.str(""); - nothing(); - ok.str(""); ok << "body" << std::endl; - BOOST_TEST(out.check(ok.str())); - - out.str(""); - pre_only(); - ok.str(""); ok << "pre" << std::endl << "body" << std::endl; - BOOST_TEST(out.check(ok.str())); - - out.str(""); - post_only(); - ok.str(""); ok << "body" << std::endl << "post" << std::endl; - BOOST_TEST(out.check(ok.str())); - - ok.str(""); ok << "pre" << std::endl << "body" << std::endl << "post" << - std::endl; - - out.str(""); - pre_post(); - BOOST_TEST(out.check(ok.str())); - - out.str(""); - post_pre(); - BOOST_TEST(out.check(ok.str())); - - return boost::report_errors(); -} - diff --git a/test/set/function_set_pre_post_post_error.cpp b/test/set/function_set_pre_post_post_error.cpp deleted file mode 100644 index 637f722..0000000 --- a/test/set/function_set_pre_post_post_error.cpp +++ /dev/null @@ -1,15 +0,0 @@ - -#include - -// Test post cannot be set twice (not even after pre) for free functions -// (member functions use same setter object, so no need to test those too). - -int main() { - auto c = boost::contract::free_function() - .precondition([&] {}) - .postcondition([&] {}) - .postcondition([&] {}) // Error. - ; - return 0; -} - diff --git a/test/set/function_set_pre_post_pre_error.cpp b/test/set/function_set_pre_post_pre_error.cpp deleted file mode 100644 index c5b4f9c..0000000 --- a/test/set/function_set_pre_post_pre_error.cpp +++ /dev/null @@ -1,15 +0,0 @@ - -#include - -// Test pre cannot be set twice (not even after post) for free functions -// (member functions use same setter objects, so no need to test those too). - -int main() { - auto c = boost::contract::free_function() - .precondition([&] {}) - .postcondition([&] {}) - .precondition([&] {}) // Error. - ; - return 0; -} - diff --git a/test/set/function_set_pre_pre_error.cpp b/test/set/function_set_pre_pre_error.cpp deleted file mode 100644 index 81757cb..0000000 --- a/test/set/function_set_pre_pre_error.cpp +++ /dev/null @@ -1,14 +0,0 @@ - -#include - -// Test pre cannot be set twice for free functions -// (member functions use same setter objects, so no need to test those too). - -int main() { - auto c = boost::contract::free_function() - .precondition([&] {}) - .precondition([&] {}) // Error. - ; - return 0; -} - diff --git a/test/type_traits/base_types.cpp b/test/type_traits/base_types.cpp deleted file mode 100644 index 3366d85..0000000 --- a/test/type_traits/base_types.cpp +++ /dev/null @@ -1,62 +0,0 @@ - -#include -#include -#include -#include - -struct A; struct AA; -struct X; struct XX; -struct U; struct UU; - -template struct a2; -template struct x2; -template struct u2; - -struct a0; -struct x0; -struct u0; - -int main() { - typedef BOOST_CONTRACT_BASE_TYPES( - public a2 - , private b2 - , protected c2 - - , virtual public x2 - , virtual private y2 - , virtual protected z2 - - , public virtual u2 - , private virtual v2 - , protected virtual w2 - ) base_types2; - BOOST_TEST((boost::is_same, x2, u2 > - >::value)); - - typedef BOOST_CONTRACT_BASE_TYPES( - private b1 - , protected c1 - - , virtual private y1 - , virtual protected z1 - - , private virtual v1 - , protected virtual w1 - ) base_types1; - BOOST_TEST((boost::is_same - >::value)); - - typedef BOOST_CONTRACT_BASE_TYPES( - public a0 - , virtual public x0 - , public virtual u0 - ) base_types0; - BOOST_TEST((boost::is_same - >::value)); - - return boost::report_errors(); -} - diff --git a/test/type_traits/has_bases.cpp b/test/type_traits/has_bases.cpp deleted file mode 100644 index d915d1f..0000000 --- a/test/type_traits/has_bases.cpp +++ /dev/null @@ -1,20 +0,0 @@ - -#include -#include -#include - -struct y {}; -struct z {}; - -struct x : y, z { - typedef boost::mpl::vector base_types; -}; - -int main() { - BOOST_TEST(!boost::contract::aux::type_traits::has_bases::value); - BOOST_TEST(boost::contract::aux::type_traits::has_bases::value); - BOOST_TEST((boost::is_same:: - type, boost::mpl::vector >::value)); - return boost::report_errors(); -} - diff --git a/test/type_traits/has_invariant.cpp b/test/type_traits/has_invariant.cpp deleted file mode 100644 index c1b45c8..0000000 --- a/test/type_traits/has_invariant.cpp +++ /dev/null @@ -1,66 +0,0 @@ - -#include -#include - -struct x {}; // Test no invariants. - -struct c { - void invariant() const {} // Test const invariant. -}; - -struct cv { - void invariant() const volatile {} // Test const volatile invariant. -}; - -struct i { - void invariant() {} // Test non-const, non-volatile invariant. -}; - -struct si { - static void invariant() {} // Test static invariant. -}; - -struct s { - static void static_invariant() {} // Test static invariant. -}; - -struct ns { - void static_invariant() {} // Test non-static invariant. -}; - -int main() { - using namespace boost::contract::aux::type_traits; - - BOOST_TEST(!has_const_invariant::value); - BOOST_TEST(!has_const_volatile_invariant::value); - BOOST_TEST(!has_invariant::value); - BOOST_TEST(!has_static_invariant::value); - BOOST_TEST(!has_non_static_invariant::value); - - BOOST_TEST( has_const_invariant::value); - BOOST_TEST(!has_const_volatile_invariant::value); - BOOST_TEST(!has_invariant::value); - BOOST_TEST(!has_static_invariant::value); - BOOST_TEST(!has_non_static_invariant::value); - - BOOST_TEST(!has_const_invariant::value); - BOOST_TEST( has_const_volatile_invariant::value); - BOOST_TEST(!has_invariant::value); - BOOST_TEST(!has_static_invariant::value); - BOOST_TEST(!has_non_static_invariant::value); - - BOOST_TEST(!has_const_invariant::value); - BOOST_TEST(!has_const_volatile_invariant::value); - BOOST_TEST( has_invariant::value); - BOOST_TEST(!has_static_invariant::value); - BOOST_TEST(!has_non_static_invariant::value); - - BOOST_TEST(!has_const_invariant::value); - BOOST_TEST(!has_const_volatile_invariant::value); - BOOST_TEST(!has_invariant::value); - BOOST_TEST(!has_static_invariant::value); - BOOST_TEST( has_non_static_invariant::value); - - return boost::report_errors(); -} - diff --git a/test/type_traits/introspect.cpp b/test/type_traits/introspect.cpp deleted file mode 100644 index e21e7d7..0000000 --- a/test/type_traits/introspect.cpp +++ /dev/null @@ -1,39 +0,0 @@ - -#include -#include -#include - -struct w {}; - -struct z { - char f(int) { return 'z'; } -}; - -struct y { - int f(char) { return -1; } -}; - -struct x { - int f(char) { - BOOST_TEST((introspect_f::has_member_function >::value)); - BOOST_TEST((!introspect_f::has_member_function >::value)); - BOOST_TEST((!introspect_f::has_member_function >::value)); - - BOOST_TEST((introspect_f::member_function_address() == &y::f)); - - return 'x'; - } -private: - BOOST_CONTRACT_INTROSPECT(f) -}; - -int main() { - x xx; - xx.f('a'); - return 0; -} -