diff --git a/Jamroot b/Jamroot index 507c69f..5501054 100644 --- a/Jamroot +++ b/Jamroot @@ -1,12 +1,13 @@ import testing ; import os ; +import feature ; if ! [ os.environ BOOST_ROOT ] { - exit "error: set BOOST_ROOT environment variable to Boost root directory" ; + exit "Error: set BOOST_ROOT environment variable to Boost root directory" ; } local BOOST_ROOT = [ os.environ BOOST_ROOT ] ; -echo "using: Boost libraries from \"$(BOOST_ROOT)\" (see $BOOST_ROOT)" ; +echo "Using Boost libraries from \"$(BOOST_ROOT)\" (see $BOOST_ROOT)" ; use-project boost : $(BOOST_ROOT) ; project @@ -20,15 +21,28 @@ project ; rule subdir-usage ( ) { - echo ; - echo "usage: [time] bjam [-aq toolset=msvc,gcc,clang] DIR_NAME[-FILE_NAME[-no_...]] [--clean] [; echo $?]" ; - echo "where: -no_... = -no[_entryinv][_pre][_exitinv][_post] | -no_all | n/a" ; - echo ; + echo " +Usage: [time] bjam [-aq] [OPTION]... DIR[-CPP_FILE_NAME] [--clean] [; echo $?] +Build and run Boost.Contract tests and examples. + +Options: + toolset=msvc,gcc,clang use different compilers + boost_contract-link=shared,static, compile Boost.Contract lib as shared, + header static, or header-only + boost_contract-no=all_on,entryinv, selectively turn off contract checking + pre,exitinv,post, + entryinv_pre,entryinv_exitinv,entryinv_post,pre_exitinv, + pre_post,exitinv_post,pre_exitinv_post, + entryinv_exitinv_post,entryinv_pre_post, + entryinv_pre_exitinv,entryinv_pre_exitinv_post +" ; } rule subdir-compile-fail ( subdir : cpp_fname : requirements * ) { compile-fail $(subdir)/$(cpp_fname).cpp : + shared:../build//boost_contract + static:../build//boost_contract $(subdir) $(requirements) : @@ -39,6 +53,8 @@ rule subdir-compile-fail ( subdir : cpp_fname : requirements * ) { rule subdir-run ( subdir : cpp_fname : requirements * ) { run $(subdir)/$(cpp_fname).cpp : : : + shared:../build//boost_contract + static:../build//boost_contract $(subdir) $(requirements) : @@ -46,170 +62,110 @@ rule subdir-run ( subdir : cpp_fname : requirements * ) { ; } -rule subdir-run-withno ( subdir : cpp_fname : requirements * ) { - subdir-run $(subdir) : $(cpp_fname) : $(requirements) ; - # Compilation of 1 contract off. - run $(subdir)/$(cpp_fname).cpp : : +rule subdir-lib ( subdir : cpp_fname : requirements * ) { + lib $(subdir)-$(cpp_fname) : $(subdir)/$(cpp_fname).cpp : - BOOST_CONTRACT_CONFIG_NO_ENTRY_INVARIANTS - $(subdir) + shared:../build//boost_contract + static:../build//boost_contract $(requirements) - : - $(subdir)-$(cpp_fname)-no_entryinv - ; - run $(subdir)/$(cpp_fname).cpp : : - : - BOOST_CONTRACT_CONFIG_NO_PRECONDITIONS - $(subdir) - $(requirements) - : - $(subdir)-$(cpp_fname)-no_pre - ; - run $(subdir)/$(cpp_fname).cpp : : - : - BOOST_CONTRACT_CONFIG_NO_EXIT_INVARIANTS - $(subdir) - $(requirements) - : - $(subdir)-$(cpp_fname)-no_exitinv - ; - run $(subdir)/$(cpp_fname).cpp : : - : - BOOST_CONTRACT_CONFIG_NO_POSTCONDITIONS - $(subdir) - $(requirements) - : - $(subdir)-$(cpp_fname)-no_post - ; - # Compilation of 2 contracts off. - run $(subdir)/$(cpp_fname).cpp : : - : - BOOST_CONTRACT_CONFIG_NO_ENTRY_INVARIANTS - BOOST_CONTRACT_CONFIG_NO_PRECONDITIONS - $(subdir) - $(requirements) - : - $(subdir)-$(cpp_fname)-no_entryinv_pre - ; - run $(subdir)/$(cpp_fname).cpp : : - : - BOOST_CONTRACT_CONFIG_NO_ENTRY_INVARIANTS - BOOST_CONTRACT_CONFIG_NO_EXIT_INVARIANTS - $(subdir) - $(requirements) - : - $(subdir)-$(cpp_fname)-no_entryinv_exitinv - ; - run $(subdir)/$(cpp_fname).cpp : : - : - BOOST_CONTRACT_CONFIG_NO_ENTRY_INVARIANTS - BOOST_CONTRACT_CONFIG_NO_POSTCONDITIONS - $(subdir) - $(requirements) - : - $(subdir)-$(cpp_fname)-no_entryinv_post - ; - run $(subdir)/$(cpp_fname).cpp : : - : - BOOST_CONTRACT_CONFIG_NO_PRECONDITIONS - BOOST_CONTRACT_CONFIG_NO_EXIT_INVARIANTS - $(subdir) - $(requirements) - : - $(subdir)-$(cpp_fname)-no_pre_exitinv - ; - run $(subdir)/$(cpp_fname).cpp : : - : - BOOST_CONTRACT_CONFIG_NO_PRECONDITIONS - BOOST_CONTRACT_CONFIG_NO_POSTCONDITIONS - $(subdir) - $(requirements) - : - $(subdir)-$(cpp_fname)-no_pre_post - ; - run $(subdir)/$(cpp_fname).cpp : : - : - BOOST_CONTRACT_CONFIG_NO_EXIT_INVARIANTS - BOOST_CONTRACT_CONFIG_NO_POSTCONDITIONS - $(subdir) - $(requirements) - : - $(subdir)-$(cpp_fname)-no_exitinv_post - ; - # Compilation of 3 contracts off. - run $(subdir)/$(cpp_fname).cpp : : - : - BOOST_CONTRACT_CONFIG_NO_PRECONDITIONS - BOOST_CONTRACT_CONFIG_NO_EXIT_INVARIANTS - BOOST_CONTRACT_CONFIG_NO_POSTCONDITIONS - $(subdir) - $(requirements) - : - $(subdir)-$(cpp_fname)-no_pre_exitinv_post - ; - run $(subdir)/$(cpp_fname).cpp : : - : - BOOST_CONTRACT_CONFIG_NO_ENTRY_INVARIANTS - BOOST_CONTRACT_CONFIG_NO_EXIT_INVARIANTS - BOOST_CONTRACT_CONFIG_NO_POSTCONDITIONS - $(subdir) - $(requirements) - : - $(subdir)-$(cpp_fname)-no_entryinv_exitinv_post - ; - run $(subdir)/$(cpp_fname).cpp : : - : - BOOST_CONTRACT_CONFIG_NO_ENTRY_INVARIANTS - BOOST_CONTRACT_CONFIG_NO_PRECONDITIONS - BOOST_CONTRACT_CONFIG_NO_POSTCONDITIONS - $(subdir) - $(requirements) - : - $(subdir)-$(cpp_fname)-no_entryinv_pre_post - ; - run $(subdir)/$(cpp_fname).cpp : : - : - BOOST_CONTRACT_CONFIG_NO_ENTRY_INVARIANTS - BOOST_CONTRACT_CONFIG_NO_PRECONDITIONS - BOOST_CONTRACT_CONFIG_NO_EXIT_INVARIANTS - $(subdir) - $(requirements) - : - $(subdir)-$(cpp_fname)-no_entryinv_pre_exitinv - ; - # Compilation of all 4 contracts off. - run $(subdir)/$(cpp_fname).cpp : : - : - BOOST_CONTRACT_CONFIG_NO_ENTRY_INVARIANTS - BOOST_CONTRACT_CONFIG_NO_PRECONDITIONS - BOOST_CONTRACT_CONFIG_NO_EXIT_INVARIANTS - BOOST_CONTRACT_CONFIG_NO_POSTCONDITIONS - $(subdir) - $(requirements) - : - $(subdir)-$(cpp_fname)-no_entryinv_pre_exitinv_post - ; - # Group all compilation off targets. - test-suite $(subdir)-$(cpp_fname)-no_all - : - $(subdir)-$(cpp_fname)-no_entryinv - $(subdir)-$(cpp_fname)-no_pre - $(subdir)-$(cpp_fname)-no_exitinv - $(subdir)-$(cpp_fname)-no_post - - $(subdir)-$(cpp_fname)-no_entryinv_pre - $(subdir)-$(cpp_fname)-no_entryinv_exitinv - $(subdir)-$(cpp_fname)-no_entryinv_post - $(subdir)-$(cpp_fname)-no_pre_exitinv - $(subdir)-$(cpp_fname)-no_pre_post - $(subdir)-$(cpp_fname)-no_exitinv_post - - $(subdir)-$(cpp_fname)-no_pre_exitinv_post - $(subdir)-$(cpp_fname)-no_entryinv_exitinv_post - $(subdir)-$(cpp_fname)-no_entryinv_pre_post - $(subdir)-$(cpp_fname)-no_entryinv_pre_exitinv - - $(subdir)-$(cpp_fname)-no_entryinv_pre_exitinv_post ; } +feature.feature boost_contract-link : shared static header : + composite propagated link-incompatible ; +feature.compose shared : shared ; +feature.compose static : static ; +feature.compose header : + BOOST_CONTRACT_HEADER_ONLY ; + +feature.feature boost_contract-no +: + all_on entryinv pre exitinv post entryinv_pre entryinv_exitinv + entryinv_post pre_exitinv pre_post exitinv_post pre_exitinv_post + entryinv_exitinv_post entryinv_pre_post entryinv_pre_exitinv + entryinv_pre_exitinv_post +: + composite propagated link-incompatible +; +# 1 contract off. +feature.compose entryinv +: + BOOST_CONTRACT_CONFIG_NO_ENTRY_INVARIANTS +; +feature.compose pre +: + BOOST_CONTRACT_CONFIG_NO_PRECONDITIONS +; +feature.compose exitinv +: + BOOST_CONTRACT_CONFIG_NO_EXIT_INVARIANTS +; +feature.compose post +: + BOOST_CONTRACT_CONFIG_NO_POSTCONDITIONS +; +# 2 contracts off. +feature.compose entryinv_pre +: + BOOST_CONTRACT_CONFIG_NO_ENTRY_INVARIANTS + BOOST_CONTRACT_CONFIG_NO_PRECONDITIONS +; +feature.compose entryinv_exitinv +: + BOOST_CONTRACT_CONFIG_NO_ENTRY_INVARIANTS + BOOST_CONTRACT_CONFIG_NO_EXIT_INVARIANTS +; +feature.compose entryinv_post +: + BOOST_CONTRACT_CONFIG_NO_ENTRY_INVARIANTS + BOOST_CONTRACT_CONFIG_NO_POSTCONDITIONS +; +feature.compose pre_exitinv +: + BOOST_CONTRACT_CONFIG_NO_PRECONDITIONS + BOOST_CONTRACT_CONFIG_NO_EXIT_INVARIANTS +; +feature.compose pre_post +: + BOOST_CONTRACT_CONFIG_NO_PRECONDITIONS + BOOST_CONTRACT_CONFIG_NO_POSTCONDITIONS +; +feature.compose exitinv_post +: + BOOST_CONTRACT_CONFIG_NO_EXIT_INVARIANTS + BOOST_CONTRACT_CONFIG_NO_POSTCONDITIONS +; +# 3 contracts off. +feature.compose pre_exitinv_post +: + BOOST_CONTRACT_CONFIG_NO_PRECONDITIONS + BOOST_CONTRACT_CONFIG_NO_EXIT_INVARIANTS + BOOST_CONTRACT_CONFIG_NO_POSTCONDITIONS +; +feature.compose entryinv_exitinv_post +: + BOOST_CONTRACT_CONFIG_NO_ENTRY_INVARIANTS + BOOST_CONTRACT_CONFIG_NO_EXIT_INVARIANTS + BOOST_CONTRACT_CONFIG_NO_POSTCONDITIONS +; +feature.compose entryinv_pre_post +: + BOOST_CONTRACT_CONFIG_NO_ENTRY_INVARIANTS + BOOST_CONTRACT_CONFIG_NO_PRECONDITIONS + BOOST_CONTRACT_CONFIG_NO_POSTCONDITIONS +; +feature.compose entryinv_pre_exitinv +: + BOOST_CONTRACT_CONFIG_NO_ENTRY_INVARIANTS + BOOST_CONTRACT_CONFIG_NO_PRECONDITIONS + BOOST_CONTRACT_CONFIG_NO_EXIT_INVARIANTS +; +# All 4 contracts oof. +feature.compose entryinv_pre_exitinv_post +: + BOOST_CONTRACT_CONFIG_NO_ENTRY_INVARIANTS + BOOST_CONTRACT_CONFIG_NO_PRECONDITIONS + BOOST_CONTRACT_CONFIG_NO_EXIT_INVARIANTS + BOOST_CONTRACT_CONFIG_NO_POSTCONDITIONS +; + diff --git a/build/Jamfile.v2 b/build/Jamfile.v2 new file mode 100644 index 0000000..6ed2188 --- /dev/null +++ b/build/Jamfile.v2 @@ -0,0 +1,4 @@ + +lib boost_contract : ../src/contract.cpp : + shared:BOOST_CONTRACT_DYN_LINK ; + diff --git a/include/boost/contract/aux_/check_guard.hpp b/include/boost/contract/aux_/check_guard.hpp index f02a4b0..3c90a41 100644 --- a/include/boost/contract/aux_/check_guard.hpp +++ b/include/boost/contract/aux_/check_guard.hpp @@ -3,6 +3,7 @@ #define BOOST_CONTRACT_AUX_CHECK_GUARD_HPP_ /** @cond */ +#include #include /** @endcond */ @@ -10,23 +11,26 @@ namespace boost { namespace contract { namespace aux { // TODO: Consider what to do with multi-threads... shall I use multi-reads/one-write locks via boost::shared_mutex? should each thread have its own contract checking bool resource? If global locks must be introduced, provide a NO_TREAD_SAFE configuration macro to disable them. -class check_guard : +class BOOST_CONTRACT_AUX_DECL check_guard : private boost::noncopyable // Non-copyable resource (might use mutex, etc.). { public: - explicit check_guard() { checking_ = true; } - ~check_guard() { checking_ = false; } + explicit check_guard(); + ~check_guard(); - static bool checking() { return checking_; } + static bool checking(); private: static bool checking_; }; // TODO: This and all other lib states (failure handler functors from exception.hpp, etc.) must go into a .cpp with dyn linking (DLL). Also move as much as code as possible to .cpp files (and try to minimize template is not strictly necessary) so to speed up compilation. -bool check_guard::checking_ = false; } } } // namespace +#if BOOST_CONTRACT_HEADER_ONLY + #include +#endif + #endif // #include guard diff --git a/include/boost/contract/aux_/decl.hpp b/include/boost/contract/aux_/decl.hpp index 093c7a1..942d1b4 100644 --- a/include/boost/contract/aux_/decl.hpp +++ b/include/boost/contract/aux_/decl.hpp @@ -11,9 +11,23 @@ #include #include #endif +#include /* PUBLIC */ +// IMPORTANT: In general, this library should always and only be compiled and +// used as a shared library. Otherwise, lib's state won't be shared among +// different user programs and user libraries. +#if defined(BOOST_ALL_DYN_LINK) || defined(BOOST_CONTRACT_DYN_LINK) + #ifdef BOOST_CONTRACT_AUX_CONFIG_SOURCE + #define BOOST_CONTRACT_AUX_DECL BOOST_SYMBOL_EXPORT + #else + #define BOOST_CONTRACT_AUX_DECL BOOST_SYMBOL_IMPORT + #endif +#else + #define BOOST_CONTRACT_AUX_DECL /* nothing */ +#endif + #define BOOST_CONTRACT_AUX_DECL_OVERRIDING_PUBLIC_FUNCTION_Z(z, \ arity, is_friend, has_result, \ O, R, F, C, Args, \ diff --git a/include/boost/contract/aux_/inlined/aux_/check_guard.hpp b/include/boost/contract/aux_/inlined/aux_/check_guard.hpp new file mode 100644 index 0000000..25ba2b8 --- /dev/null +++ b/include/boost/contract/aux_/inlined/aux_/check_guard.hpp @@ -0,0 +1,20 @@ + +#ifndef BOOST_CONTRACT_AUX_INLINED_AUX_CHECK_GUARD_HPP_ +#define BOOST_CONTRACT_AUX_INLINED_AUX_CHECK_GUARD_HPP_ + +#include + +namespace boost { namespace contract { namespace aux { + +check_guard::check_guard() { checking_ = true; } + +check_guard::~check_guard() { checking_ = false; } + +bool check_guard::checking() { return checking_; } + +bool check_guard::checking_ = false; + +} } } // namespace + +#endif + diff --git a/include/boost/contract/aux_/inlined/core/exception.hpp b/include/boost/contract/aux_/inlined/core/exception.hpp new file mode 100644 index 0000000..a3a334b --- /dev/null +++ b/include/boost/contract/aux_/inlined/core/exception.hpp @@ -0,0 +1,219 @@ + +#ifndef BOOST_CONTRACT_AUX_INLINED_EXCEPTION_HPP_ +#define BOOST_CONTRACT_AUX_INLINED_EXCEPTION_HPP_ + +#include +#include +#include +#include +#include +#include +#include +#include + +/* PRIVATE */ + +// TODO: Re-enable these mutexes for failure handlers. +#define BOOST_CONTRACT_EXCEPTION_HANDLER_SCOPED_LOCK_(_mutex) \ + /*boost::mutex::scoped_lock lock(_mutex);*/ + +#define BOOST_CONTRACT_EXCEPTION_HANDLER_SET_(_mutex, handler, f) \ + BOOST_CONTRACT_EXCEPTION_HANDLER_SCOPED_LOCK_(_mutex); \ + assertion_failure_handler result = handler; \ + handler = f; \ + return result; + +#define BOOST_CONTRACT_EXCEPTION_HANDLER_GET_(_mutex, handler) \ + BOOST_CONTRACT_EXCEPTION_HANDLER_SCOPED_LOCK_(_mutex); \ + return handler; + +#define BOOST_CONTRACT_EXCEPTION_HANDLER_(_mutex, handler, where) \ + BOOST_CONTRACT_EXCEPTION_HANDLER_SCOPED_LOCK_(_mutex); \ + handler(where); + +/* CODE */ + +namespace boost { namespace contract { + +exception::~exception() {} + +bad_virtual_result_cast::bad_virtual_result_cast(char const* from_type_name, + char const* to_type_name) { + std::ostringstream text; + text + << "incompatible contracted virtual function result type " + << "conversion from '" << from_type_name << "' to '" + << to_type_name << "'" + ; + what_ = text.str(); +} + +bad_virtual_result_cast::~bad_virtual_result_cast() {} + +char const* bad_virtual_result_cast::what() const BOOST_NOEXCEPT { + return what_.c_str(); +} + +assertion_failure::assertion_failure(char const* const file, + unsigned long const line, char const* const code) : + file_(file), line_(line), code_(code) +{ init(); } + +assertion_failure::assertion_failure(char const* const code) : + file_(""), line_(0), code_(code) +{ init(); } + +assertion_failure::~assertion_failure() {} + +char const* assertion_failure::what() const BOOST_NOEXCEPT { + return what_.c_str(); +} + +char const* const assertion_failure::file() const { return file_; } + +unsigned long assertion_failure::line() const { return line_; } + +char const* const assertion_failure::code() const { return code_; } + +void assertion_failure::init() { + std::ostringstream text; + text << "assertion"; + if(std::string(code_) != "") text << " \"" << code_ << "\""; + text << " failed"; + if(std::string(file_) != "") { + text << ": file \"" << file_ << "\""; + if(line_ != 0) text << ", line " << line_; + } + what_ = text.str(); +} + +namespace exception_ { + enum failure_key { pre_key, post_key, entry_inv_key, exit_inv_key }; + + template + void default_handler(from) { + std::string k = ""; + switch(Key) { + case pre_key: k = "precondition "; break; + case post_key: k = "postcondition "; break; + case entry_inv_key: k = "entry invariant "; break; + case exit_inv_key: k = "exit invariant "; break; + // No default (so compiler warning/error on missing enum case). + } + try { + throw; + } catch(boost::contract::assertion_failure const& error) { + // what = "assertion '...' failed: ...". + std::cerr << k << error.what() << std::endl; + } catch(...) { + std::cerr << k << "checking threw following exception:" << std::endl + << boost::current_exception_diagnostic_information(); + } + std::terminate(); // Default handlers log and call terminate. + } + + // TODO: These (and all other globals) need extern, etc. + + //boost::mutex pre_failure_mutex; + BOOST_CONTRACT_AUX_DECL assertion_failure_handler + pre_failure_handler = &default_handler; + + //boost::mutex post_failure_mutex; + BOOST_CONTRACT_AUX_DECL assertion_failure_handler + post_failure_handler = &default_handler; + + //boost::mutex entry_inv_failure_mutex; + BOOST_CONTRACT_AUX_DECL assertion_failure_handler + entry_inv_failure_handler = &default_handler; + + //boost::mutex exit_inv_failure_mutex; + BOOST_CONTRACT_AUX_DECL assertion_failure_handler + exit_inv_failure_handler = &default_handler; +} + +// Contract compilation on/off cannot change following set/get impl. + +assertion_failure_handler set_precondition_failure( + assertion_failure_handler const& f) BOOST_NOEXCEPT_OR_NOTHROW { + BOOST_CONTRACT_EXCEPTION_HANDLER_SET_(exception_::pre_failure_mutex, + exception_::pre_failure_handler, f); +} + +assertion_failure_handler get_precondition_failure() + BOOST_NOEXCEPT_OR_NOTHROW { + BOOST_CONTRACT_EXCEPTION_HANDLER_GET_(exception_::pre_failure_mutex, + exception_::pre_failure_handler); +} + +void precondition_failure(from where) /* can throw */ { + BOOST_CONTRACT_EXCEPTION_HANDLER_(exception_::pre_failure_mutex, + exception_::pre_failure_handler, where) +} + +assertion_failure_handler set_postcondition_failure( + assertion_failure_handler const& f) BOOST_NOEXCEPT_OR_NOTHROW { + BOOST_CONTRACT_EXCEPTION_HANDLER_SET_(exception_::post_failure_mutex, + exception_::post_failure_handler, f); +} + +assertion_failure_handler get_postcondition_failure() + BOOST_NOEXCEPT_OR_NOTHROW { + BOOST_CONTRACT_EXCEPTION_HANDLER_GET_(exception_::post_failure_mutex, + exception_::post_failure_handler); +} + +void postcondition_failure(from where) /* can throw */ { + BOOST_CONTRACT_EXCEPTION_HANDLER_(exception_::post_failure_mutex, + exception_::post_failure_handler, where); +} + +assertion_failure_handler set_entry_invariant_failure( + assertion_failure_handler const& f) BOOST_NOEXCEPT_OR_NOTHROW { + BOOST_CONTRACT_EXCEPTION_HANDLER_SET_(exception_::entry_inv_failure_mutex, + exception_::entry_inv_failure_handler, f); +} + +assertion_failure_handler get_entry_invariant_failure() + BOOST_NOEXCEPT_OR_NOTHROW { + BOOST_CONTRACT_EXCEPTION_HANDLER_GET_(exception_::entry_inv_failure_mutex, + exception_::entry_inv_failure_handler); +} + +void entry_invariant_failure(from where) /* can throw */ { + BOOST_CONTRACT_EXCEPTION_HANDLER_(exception_::entry_inv_failure_mutex, + exception_::entry_inv_failure_handler, where); +} + +assertion_failure_handler set_exit_invariant_failure( + assertion_failure_handler const& f) BOOST_NOEXCEPT_OR_NOTHROW { + BOOST_CONTRACT_EXCEPTION_HANDLER_SET_(exception_::exit_inv_failure_mutex, + exception_::exit_inv_failure_handler, f); +} + +assertion_failure_handler get_exit_invariant_failure() + BOOST_NOEXCEPT_OR_NOTHROW { + BOOST_CONTRACT_EXCEPTION_HANDLER_GET_(exception_::exit_inv_failure_mutex, + exception_::exit_inv_failure_handler); +} + +void exit_invariant_failure(from where) /* can throw */ { + BOOST_CONTRACT_EXCEPTION_HANDLER_(exception_::exit_inv_failure_mutex, + exception_::exit_inv_failure_handler, where); +} + +void set_invariant_failure(assertion_failure_handler const& f) + BOOST_NOEXCEPT_OR_NOTHROW { + set_entry_invariant_failure(f); + set_exit_invariant_failure(f); +} + +void set_failure(assertion_failure_handler const& f) BOOST_NOEXCEPT_OR_NOTHROW { + set_precondition_failure(f); + set_postcondition_failure(f); + set_invariant_failure(f); +} + +} } // namespace + +#endif // #include guard + diff --git a/include/boost/contract/core/config.hpp b/include/boost/contract/core/config.hpp index 8d79872..3952151 100644 --- a/include/boost/contract/core/config.hpp +++ b/include/boost/contract/core/config.hpp @@ -4,12 +4,19 @@ /** @file */ -// IMPORTANT: This header MUST NOT #include any other header. That way users -// can #include this header and not #include any of this lib headers after that -// depending on the contract 0/1 macros below ensuring no compilation overhead. +// IMPORTANT: This header MUST NOT #include any other header of this lib. +// That way users can #include this header and not #include any of this lib +// headers after that depending on the contract 0/1 macros below ensuring no +// compilation overhead. // TODO: Can I compile lib1 with some contract on/off, lib2 with other contracts on/off and then link the two together? +// TODO: To be consistent... should I use CONFIG only for staff below that has a default #define, but for PREMISSIVE, etc. do not use CONFIG? +// BOOST_CONTRACT_DYN_LINK +// BOOST_CONTRACT_HEADER_ONLY + +// BOOST_CONTRACT_THREAD_DISABLE + #ifndef BOOST_CONTRACT_CONFIG_MAX_ARGS # define BOOST_CONTRACT_CONFIG_MAX_ARGS 10 #endif diff --git a/include/boost/contract/core/exception.hpp b/include/boost/contract/core/exception.hpp index 6aa3025..037ddeb 100644 --- a/include/boost/contract/core/exception.hpp +++ b/include/boost/contract/core/exception.hpp @@ -4,16 +4,11 @@ /** @file */ -#include -/** @cond */ +#include #include -#include #include #include -#include #include -#include -/** @endcond */ // NOTE: This code should not change (not even its impl) based on the // CONFIG_NO_... macros. For example, preconditions_failure() should still call @@ -21,88 +16,49 @@ // #defined, because user code might explicitly call precondition_failure() (for // whatever reason...). Otherwise, the public API of this lib will change. -/* PRIVATE */ - -#define BOOST_CONTRACT_EXCEPTION_HANDLER_SCOPED_LOCK_(_mutex) \ - /*boost::mutex::scoped_lock lock(_mutex);*/ - -#define BOOST_CONTRACT_EXCEPTION_HANDLER_SET_(_mutex, handler, f) \ - BOOST_CONTRACT_EXCEPTION_HANDLER_SCOPED_LOCK_(_mutex); \ - assertion_failure_handler result = handler; \ - handler = f; \ - return result; - -#define BOOST_CONTRACT_EXCEPTION_HANDLER_GET_(_mutex, handler) \ - BOOST_CONTRACT_EXCEPTION_HANDLER_SCOPED_LOCK_(_mutex); \ - return handler; - -#define BOOST_CONTRACT_EXCEPTION_HANDLER_(_mutex, handler, where) \ - BOOST_CONTRACT_EXCEPTION_HANDLER_SCOPED_LOCK_(_mutex); \ - handler(where); - -/* CODE */ - namespace boost { namespace contract { // Placeholder base class to group all this lib exceptions. // IMPORTANT: Must not inherit from std::exception as derived exceptions will. -class exception {}; +class BOOST_CONTRACT_AUX_DECL exception { +public: + virtual ~exception(); +}; // Rationale: boost::bad_any_cast exception does not print from/to type names, // so throw custom exception. -class bad_virtual_result_cast : // Copyable (as string, etc.). +// Copyable (as string, etc.). +class BOOST_CONTRACT_AUX_DECL bad_virtual_result_cast : public std::bad_cast, public boost::contract::exception { public: explicit bad_virtual_result_cast(char const* from_type_name, - char const* to_type_name) { - std::ostringstream text; - text - << "incompatible contracted virtual function result type " - << "conversion from '" << from_type_name << "' to '" - << to_type_name << "'" - ; - what_ = text.str(); - } + char const* to_type_name); + virtual ~bad_virtual_result_cast(); - virtual char const* what() const BOOST_NOEXCEPT { return what_.c_str(); } + virtual char const* what() const BOOST_NOEXCEPT; private: std::string what_; }; -class assertion_failure : // Copyable (as string, etc.). +// Copyable (as string, etc.). +class BOOST_CONTRACT_AUX_DECL assertion_failure : public std::exception, public boost::contract::exception { public: explicit assertion_failure(char const* const file = "", - unsigned long const line = 0, char const* const code = "") : - file_(file), line_(line), code_(code) - { init(); } - - explicit assertion_failure(char const* const code) : - file_(""), line_(0), code_(code) - { init(); } + unsigned long const line = 0, char const* const code = ""); + explicit assertion_failure(char const* const code); + virtual ~assertion_failure(); - virtual ~assertion_failure() {} + // Return something like `assertion "..." failed: file "...", line ...`. + virtual char const* what() const BOOST_NOEXCEPT; - // Return `assertion "..." failed: file "...", line ...`. - virtual char const* what() const BOOST_NOEXCEPT { return what_.c_str(); } - - char const* const file() const { return file_; } - unsigned long line() const { return line_; } - char const* const code() const { return code_; } + char const* const file() const; + unsigned long line() const; + char const* const code() const; private: - void init() { - std::ostringstream text; - text << "assertion"; - if(std::string(code_) != "") text << " \"" << code_ << "\""; - text << " failed"; - if(std::string(file_) != "") { - text << ": file \"" << file_ << "\""; - if(line_ != 0) text << ", line " << line_; - } - what_ = text.str(); - } + void init(); char const* const file_; unsigned long const line_; @@ -110,134 +66,57 @@ private: std::string what_; }; -enum from { - from_constructor, - from_destructor, - from_function -}; +enum from { from_constructor, from_destructor, from_function }; // Use Boost.Function to handle also lambdas, binds, etc, typedef boost::function assertion_failure_handler; -namespace exception_ { - enum failure_key { pre_key, post_key, entry_inv_key, exit_inv_key }; +assertion_failure_handler BOOST_CONTRACT_AUX_DECL set_precondition_failure( + assertion_failure_handler const& f) BOOST_NOEXCEPT_OR_NOTHROW; - template - void default_handler(from) { - std::string k = ""; - switch(Key) { - case pre_key: k = "precondition "; break; - case post_key: k = "postcondition "; break; - case entry_inv_key: k = "entry invariant "; break; - case exit_inv_key: k = "exit invariant "; break; - // No default (so compiler warning/error on missing enum case). - } - try { - throw; - } catch(boost::contract::assertion_failure const& error) { - // what = "assertion '...' failed: ...". - std::cerr << k << error.what() << std::endl; - } catch(...) { - std::cerr << k << "checking threw following exception:" << std::endl - << boost::current_exception_diagnostic_information(); - } - std::terminate(); // Default handlers log and call terminate. - } +assertion_failure_handler BOOST_CONTRACT_AUX_DECL get_precondition_failure() + BOOST_NOEXCEPT_OR_NOTHROW; - //boost::mutex pre_failure_mutex; - assertion_failure_handler pre_failure_handler = - &default_handler; - - //boost::mutex post_failure_mutex; - assertion_failure_handler post_failure_handler = - &default_handler; - - //boost::mutex entry_inv_failure_mutex; - assertion_failure_handler entry_inv_failure_handler = - &default_handler; - - //boost::mutex exit_inv_failure_mutex; - assertion_failure_handler exit_inv_failure_handler = - &default_handler; -} +void BOOST_CONTRACT_AUX_DECL precondition_failure(from where) /* can throw */; -// Contract compilation on/off cannot change following set/get. +assertion_failure_handler BOOST_CONTRACT_AUX_DECL set_postcondition_failure( + assertion_failure_handler const& f) BOOST_NOEXCEPT_OR_NOTHROW; -assertion_failure_handler set_precondition_failure( - assertion_failure_handler const& f) BOOST_NOEXCEPT_OR_NOTHROW { - BOOST_CONTRACT_EXCEPTION_HANDLER_SET_(exception_::pre_failure_mutex, - exception_::pre_failure_handler, f); -} +assertion_failure_handler BOOST_CONTRACT_AUX_DECL get_postcondition_failure() + BOOST_NOEXCEPT_OR_NOTHROW; -assertion_failure_handler get_precondition_failure() - BOOST_NOEXCEPT_OR_NOTHROW { - BOOST_CONTRACT_EXCEPTION_HANDLER_GET_(exception_::pre_failure_mutex, - exception_::pre_failure_handler); -} +void BOOST_CONTRACT_AUX_DECL postcondition_failure(from where) /* can throw */; -void precondition_failure(from where) /* can throw */ { - BOOST_CONTRACT_EXCEPTION_HANDLER_(exception_::pre_failure_mutex, - exception_::pre_failure_handler, where) -} +assertion_failure_handler BOOST_CONTRACT_AUX_DECL set_entry_invariant_failure( + assertion_failure_handler const& f) BOOST_NOEXCEPT_OR_NOTHROW; -assertion_failure_handler set_postcondition_failure( - assertion_failure_handler const& f) BOOST_NOEXCEPT_OR_NOTHROW { - BOOST_CONTRACT_EXCEPTION_HANDLER_SET_(exception_::post_failure_mutex, - exception_::post_failure_handler, f); -} +assertion_failure_handler BOOST_CONTRACT_AUX_DECL get_entry_invariant_failure() + BOOST_NOEXCEPT_OR_NOTHROW; -assertion_failure_handler get_postcondition_failure() - BOOST_NOEXCEPT_OR_NOTHROW { - BOOST_CONTRACT_EXCEPTION_HANDLER_GET_(exception_::post_failure_mutex, - exception_::post_failure_handler); -} +void BOOST_CONTRACT_AUX_DECL entry_invariant_failure(from where) + /* can throw */; -void postcondition_failure(from where) /* can throw */ { - BOOST_CONTRACT_EXCEPTION_HANDLER_(exception_::post_failure_mutex, - exception_::post_failure_handler, where); -} +assertion_failure_handler BOOST_CONTRACT_AUX_DECL set_exit_invariant_failure( + assertion_failure_handler const& f) BOOST_NOEXCEPT_OR_NOTHROW; -assertion_failure_handler set_entry_invariant_failure( - assertion_failure_handler const& f) BOOST_NOEXCEPT_OR_NOTHROW { - BOOST_CONTRACT_EXCEPTION_HANDLER_SET_(exception_::entry_inv_failure_mutex, - exception_::entry_inv_failure_handler, f); -} +assertion_failure_handler BOOST_CONTRACT_AUX_DECL get_exit_invariant_failure() + BOOST_NOEXCEPT_OR_NOTHROW; -assertion_failure_handler get_entry_invariant_failure() - BOOST_NOEXCEPT_OR_NOTHROW { - BOOST_CONTRACT_EXCEPTION_HANDLER_GET_(exception_::entry_inv_failure_mutex, - exception_::entry_inv_failure_handler); -} +void BOOST_CONTRACT_AUX_DECL exit_invariant_failure(from where) /* can throw */; -void entry_invariant_failure(from where) /* can throw */ { - BOOST_CONTRACT_EXCEPTION_HANDLER_(exception_::entry_inv_failure_mutex, - exception_::entry_inv_failure_handler, where); -} +// Set all inv failures (entry inv and exit inv) at once. +void BOOST_CONTRACT_AUX_DECL set_invariant_failure( + assertion_failure_handler const& f) BOOST_NOEXCEPT_OR_NOTHROW; -assertion_failure_handler set_exit_invariant_failure( - assertion_failure_handler const& f) BOOST_NOEXCEPT_OR_NOTHROW { - BOOST_CONTRACT_EXCEPTION_HANDLER_SET_(exception_::exit_inv_failure_mutex, - exception_::exit_inv_failure_handler, f); -} - -assertion_failure_handler get_exit_invariant_failure() - BOOST_NOEXCEPT_OR_NOTHROW { - BOOST_CONTRACT_EXCEPTION_HANDLER_GET_(exception_::exit_inv_failure_mutex, - exception_::exit_inv_failure_handler); -} - -void exit_invariant_failure(from where) /* can throw */ { - BOOST_CONTRACT_EXCEPTION_HANDLER_(exception_::exit_inv_failure_mutex, - exception_::exit_inv_failure_handler, where); -} - -void set_invariant_failure(assertion_failure_handler const& f) - BOOST_NOEXCEPT_OR_NOTHROW { - set_entry_invariant_failure(f); - set_exit_invariant_failure(f); -} +// Set all failures (pre, post, entry inv, and exit int) at once. +void BOOST_CONTRACT_AUX_DECL set_failure( + assertion_failure_handler const& f) BOOST_NOEXCEPT_OR_NOTHROW; } } // namespace +#if BOOST_CONTRACT_HEADER_ONLY + #include +#endif + #endif // #include guard diff --git a/src/contract.cpp b/src/contract.cpp new file mode 100644 index 0000000..ddcf928 --- /dev/null +++ b/src/contract.cpp @@ -0,0 +1,5 @@ + +#define BOOST_CONTRACT_AUX_CONFIG_SOURCE +#include +#include + diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index 4ddee82..b0b887a 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -3,39 +3,39 @@ subdir-usage ; test-suite constructor : - [ subdir-run-withno constructor : decl_pre_all ] - [ subdir-run-withno constructor : decl_pre_ends ] - [ subdir-run-withno constructor : decl_pre_mid ] - [ subdir-run-withno constructor : decl_pre_none ] + [ subdir-run constructor : decl_pre_all ] + [ subdir-run constructor : decl_pre_ends ] + [ subdir-run constructor : decl_pre_mid ] + [ subdir-run constructor : decl_pre_none ] - [ subdir-run-withno constructor : decl_post_all ] - [ subdir-run-withno constructor : decl_post_ends ] - [ subdir-run-withno constructor : decl_post_mid ] - [ subdir-run-withno constructor : decl_post_none ] + [ subdir-run constructor : decl_post_all ] + [ subdir-run constructor : decl_post_ends ] + [ subdir-run constructor : decl_post_mid ] + [ subdir-run constructor : decl_post_none ] - [ subdir-run-withno constructor : decl_entry_static_inv_all ] - [ subdir-run-withno constructor : decl_entry_static_inv_ends ] - [ subdir-run-withno constructor : decl_entry_static_inv_mid ] - [ subdir-run-withno constructor : decl_entry_static_inv_none ] + [ subdir-run constructor : decl_entry_static_inv_all ] + [ subdir-run constructor : decl_entry_static_inv_ends ] + [ subdir-run constructor : decl_entry_static_inv_mid ] + [ subdir-run constructor : decl_entry_static_inv_none ] - [ subdir-run-withno constructor : decl_exit_static_inv_all ] - [ subdir-run-withno constructor : decl_exit_static_inv_ends ] - [ subdir-run-withno constructor : decl_exit_static_inv_mid ] - [ subdir-run-withno constructor : decl_exit_static_inv_none ] + [ subdir-run constructor : decl_exit_static_inv_all ] + [ subdir-run constructor : decl_exit_static_inv_ends ] + [ subdir-run constructor : decl_exit_static_inv_mid ] + [ subdir-run constructor : decl_exit_static_inv_none ] # No decl_entry_static_inv_... for constructors. - [ subdir-run-withno constructor : decl_exit_inv_all ] - [ subdir-run-withno constructor : decl_exit_inv_ends ] - [ subdir-run-withno constructor : decl_exit_inv_mid ] - [ subdir-run-withno constructor : decl_exit_inv_none ] + [ subdir-run constructor : decl_exit_inv_all ] + [ subdir-run constructor : decl_exit_inv_ends ] + [ subdir-run constructor : decl_exit_inv_mid ] + [ subdir-run constructor : decl_exit_inv_none ] - [ subdir-run-withno constructor : bases ] - [ subdir-run-withno constructor : access ] - [ subdir-run-withno constructor : no_contracts ] + [ subdir-run constructor : bases ] + [ subdir-run constructor : access ] + [ subdir-run constructor : no_contracts ] - [ subdir-run-withno constructor : body_throw ] - [ subdir-run-withno constructor : old_throw ] + [ subdir-run constructor : body_throw ] + [ subdir-run constructor : old_throw ] [ subdir-compile-fail constructor : pre_error ] ; @@ -44,189 +44,196 @@ test-suite destructor : # No decl_pre_... for destructors. - [ subdir-run-withno destructor : decl_post_all ] - [ subdir-run-withno destructor : decl_post_ends ] - [ subdir-run-withno destructor : decl_post_mid ] - [ subdir-run-withno destructor : decl_post_none ] + [ subdir-run destructor : decl_post_all ] + [ subdir-run destructor : decl_post_ends ] + [ subdir-run destructor : decl_post_mid ] + [ subdir-run destructor : decl_post_none ] - [ subdir-run-withno destructor : decl_entry_static_inv_all ] - [ subdir-run-withno destructor : decl_entry_static_inv_ends ] - [ subdir-run-withno destructor : decl_entry_static_inv_mid ] - [ subdir-run-withno destructor : decl_entry_static_inv_none ] + [ subdir-run destructor : decl_entry_static_inv_all ] + [ subdir-run destructor : decl_entry_static_inv_ends ] + [ subdir-run destructor : decl_entry_static_inv_mid ] + [ subdir-run destructor : decl_entry_static_inv_none ] - [ subdir-run-withno destructor : decl_exit_static_inv_all ] - [ subdir-run-withno destructor : decl_exit_static_inv_ends ] - [ subdir-run-withno destructor : decl_exit_static_inv_mid ] - [ subdir-run-withno destructor : decl_exit_static_inv_none ] + [ subdir-run destructor : decl_exit_static_inv_all ] + [ subdir-run destructor : decl_exit_static_inv_ends ] + [ subdir-run destructor : decl_exit_static_inv_mid ] + [ subdir-run destructor : decl_exit_static_inv_none ] - [ subdir-run-withno destructor : decl_entry_inv_all ] - [ subdir-run-withno destructor : decl_entry_inv_ends ] - [ subdir-run-withno destructor : decl_entry_inv_mid ] - [ subdir-run-withno destructor : decl_entry_inv_none ] + [ subdir-run destructor : decl_entry_inv_all ] + [ subdir-run destructor : decl_entry_inv_ends ] + [ subdir-run destructor : decl_entry_inv_mid ] + [ subdir-run destructor : decl_entry_inv_none ] # No decl_exit_inv_... for destructors. - [ subdir-run-withno destructor : bases ] - [ subdir-run-withno destructor : access ] - [ subdir-run-withno destructor : no_contracts ] + [ subdir-run destructor : bases ] + [ subdir-run destructor : access ] + [ subdir-run destructor : no_contracts ] - [ subdir-run-withno destructor : body_throw ] - [ subdir-run-withno destructor : old_throw ] + [ subdir-run destructor : body_throw ] + [ subdir-run destructor : old_throw ] [ subdir-compile-fail destructor : pre_error ] ; test-suite public_function : - [ subdir-run-withno public_function : decl_pre_all ] - [ subdir-run-withno public_function : decl_pre_ends ] - [ subdir-run-withno public_function : decl_pre_mid ] - [ subdir-run-withno public_function : decl_pre_none ] + [ subdir-run public_function : decl_pre_all ] + [ subdir-run public_function : decl_pre_ends ] + [ subdir-run public_function : decl_pre_mid ] + [ subdir-run public_function : decl_pre_none ] - [ subdir-run-withno public_function : decl_post_all ] - [ subdir-run-withno public_function : decl_post_ends ] - [ subdir-run-withno public_function : decl_post_mid ] - [ subdir-run-withno public_function : decl_post_none ] + [ subdir-run public_function : decl_post_all ] + [ subdir-run public_function : decl_post_ends ] + [ subdir-run public_function : decl_post_mid ] + [ subdir-run public_function : decl_post_none ] - [ subdir-run-withno public_function : decl_entry_static_inv_all ] - [ subdir-run-withno public_function : decl_entry_static_inv_ends ] - [ subdir-run-withno public_function : decl_entry_static_inv_mid ] - [ subdir-run-withno public_function : decl_entry_static_inv_none ] + [ subdir-run public_function : decl_entry_static_inv_all ] + [ subdir-run public_function : decl_entry_static_inv_ends ] + [ subdir-run public_function : decl_entry_static_inv_mid ] + [ subdir-run public_function : decl_entry_static_inv_none ] - [ subdir-run-withno public_function : decl_exit_static_inv_all ] - [ subdir-run-withno public_function : decl_exit_static_inv_ends ] - [ subdir-run-withno public_function : decl_exit_static_inv_mid ] - [ subdir-run-withno public_function : decl_exit_static_inv_none ] + [ subdir-run public_function : decl_exit_static_inv_all ] + [ subdir-run public_function : decl_exit_static_inv_ends ] + [ subdir-run public_function : decl_exit_static_inv_mid ] + [ subdir-run public_function : decl_exit_static_inv_none ] - [ subdir-run-withno public_function : decl_entry_inv_all ] - [ subdir-run-withno public_function : decl_entry_inv_ends ] - [ subdir-run-withno public_function : decl_entry_inv_mid ] - [ subdir-run-withno public_function : decl_entry_inv_none ] + [ subdir-run public_function : decl_entry_inv_all ] + [ subdir-run public_function : decl_entry_inv_ends ] + [ subdir-run public_function : decl_entry_inv_mid ] + [ subdir-run public_function : decl_entry_inv_none ] - [ subdir-run-withno public_function : decl_exit_inv_all ] - [ subdir-run-withno public_function : decl_exit_inv_ends ] - [ subdir-run-withno public_function : decl_exit_inv_mid ] - [ subdir-run-withno public_function : decl_exit_inv_none ] + [ subdir-run public_function : decl_exit_inv_all ] + [ subdir-run public_function : decl_exit_inv_ends ] + [ subdir-run public_function : decl_exit_inv_mid ] + [ subdir-run public_function : decl_exit_inv_none ] - [ subdir-run-withno public_function : bases ] - [ subdir-run-withno public_function : bases_virtual ] - [ subdir-run-withno public_function : bases_branch ] - [ subdir-run-withno public_function : bases_sparse ] - [ subdir-run-withno public_function : bases_protected ] + [ subdir-run public_function : bases ] + [ subdir-run public_function : bases_virtual ] + [ subdir-run public_function : bases_branch ] + [ subdir-run public_function : bases_sparse ] + [ subdir-run public_function : bases_protected ] [ subdir-compile-fail public_function : bases_protected_error ] - [ subdir-run-withno public_function : access ] - [ subdir-run-withno public_function : no_contracts ] + [ subdir-run public_function : access ] + [ subdir-run public_function : no_contracts ] - [ subdir-run-withno public_function : body_throw ] - [ subdir-run-withno public_function : old_throw ] + [ subdir-run public_function : body_throw ] + [ subdir-run public_function : old_throw ] - [ subdir-run-withno public_function : max_args0 ] - [ subdir-run-withno public_function : max_args0_no_tva ] - [ subdir-run-withno public_function : max_args1 ] - [ subdir-run-withno public_function : max_args1_no_tva ] - [ subdir-run-withno public_function : max_args2 ] - [ subdir-run-withno public_function : max_args2_no_tva ] - [ subdir-run-withno public_function : max_args ] - [ subdir-run-withno public_function : max_args_no_tva ] + [ subdir-run public_function : max_args0 ] + [ subdir-run public_function : max_args0_no_tva ] + [ subdir-run public_function : max_args1 ] + [ subdir-run public_function : max_args1_no_tva ] + [ subdir-run public_function : max_args2 ] + [ subdir-run public_function : max_args2_no_tva ] + [ subdir-run public_function : max_args ] + [ subdir-run public_function : max_args_no_tva ] - [ subdir-run-withno public_function : max_bases ] + [ subdir-run public_function : max_bases ] - [ subdir-run-withno public_function : overload ] - [ subdir-run-withno public_function : overload_no_tva ] + [ subdir-run public_function : overload ] + [ subdir-run public_function : overload_no_tva ] [ subdir-compile-fail public_function : override_error ] - [ subdir-run-withno public_function : override_permissive ] + [ subdir-run public_function : override_permissive ] - [ subdir-run-withno public_function : static ] - [ subdir-run-withno public_function : static_body_throw ] - [ subdir-run-withno public_function : static_old_throw ] - [ subdir-run-withno public_function : static_no_contracts ] -; - -test-suite function -: - [ subdir-run-withno function : decl_pre_all ] - [ subdir-run-withno function : decl_pre_none ] - - [ subdir-run-withno function : decl_post_all ] - [ subdir-run-withno function : decl_post_none ] - - [ subdir-run-withno function : func ] - [ subdir-run-withno function : no_contracts ] - - [ subdir-run-withno function : body_throw ] - [ subdir-run-withno function : old_throw ] + [ subdir-run public_function : static ] + [ subdir-run public_function : static_body_throw ] + [ subdir-run public_function : static_old_throw ] + [ subdir-run public_function : static_no_contracts ] ; test-suite invariant : - [ subdir-run-withno invariant : decl_static_cv_const ] - [ subdir-run-withno invariant : decl_static_cv ] - [ subdir-run-withno invariant : decl_cv_const ] - [ subdir-run-withno invariant : decl_static_const ] - [ subdir-run-withno invariant : decl_static ] - [ subdir-run-withno invariant : decl_cv ] - [ subdir-run-withno invariant : decl_const ] - [ subdir-run-withno invariant : decl_nothing ] + [ subdir-run invariant : decl_static_cv_const ] + [ subdir-run invariant : decl_static_cv ] + [ subdir-run invariant : decl_cv_const ] + [ subdir-run invariant : decl_static_const ] + [ subdir-run invariant : decl_static ] + [ subdir-run invariant : decl_cv ] + [ subdir-run invariant : decl_const ] + [ subdir-run invariant : decl_nothing ] [ subdir-compile-fail invariant : static_inv_mutable_error ] - [ subdir-run-withno invariant : static_inv_mutable_permissive ] + [ subdir-run invariant : static_inv_mutable_permissive ] [ subdir-compile-fail invariant : static_inv_const_error ] - [ subdir-run-withno invariant : static_inv_const_permissive ] + [ subdir-run invariant : static_inv_const_permissive ] [ subdir-compile-fail invariant : static_inv_volatile_error ] - [ subdir-run-withno invariant : static_inv_volatile_permissive ] + [ subdir-run invariant : static_inv_volatile_permissive ] [ subdir-compile-fail invariant : static_inv_cv_error ] - [ subdir-run-withno invariant : static_inv_cv_permissive ] + [ subdir-run invariant : static_inv_cv_permissive ] [ subdir-compile-fail invariant : inv_static_error ] - [ subdir-run-withno invariant : inv_static_permissive ] + [ subdir-run invariant : inv_static_permissive ] [ subdir-compile-fail invariant : inv_mutable_error ] - [ subdir-run-withno invariant : inv_mutable_permissive ] + [ subdir-run invariant : inv_mutable_permissive ] [ subdir-compile-fail invariant : inv_volatile_error ] - [ subdir-run-withno invariant : inv_volatile_permissive ] + [ subdir-run invariant : inv_volatile_permissive ] ; + +test-suite function +: + [ subdir-run function : decl_pre_all ] + [ subdir-run function : decl_pre_none ] + [ subdir-run function : decl_post_all ] + [ subdir-run function : decl_post_none ] + + [ subdir-run function : func ] + [ subdir-run function : no_contracts ] + + [ subdir-run function : body_throw ] + [ subdir-run function : old_throw ] +; + test-suite result : - [ subdir-run-withno result : mixed_optional ] - [ subdir-run-withno result : mixed_optional_ref ] + [ subdir-run result : mixed_optional ] + [ subdir-run result : mixed_optional_ref ] [ subdir-compile-fail result : type_mismatch_error ] ; test-suite old : - [ subdir-run-withno old : auto ] + [ subdir-run old : auto ] - [ subdir-run-withno old : no_macros ] + [ subdir-run old : no_macros ] [ subdir-compile-fail old : no_make_old_error ] - [ subdir-run-withno old : noncopyable ] + [ subdir-run old : noncopyable ] [ subdir-compile-fail old : noncopyable_error ] - [ subdir-run-withno old : no_equal ] + [ subdir-run old : no_equal ] [ subdir-compile-fail old : no_equal_error ] ; test-suite disable : - [ subdir-run-withno disable : checking ] - [ subdir-run-withno disable : checking_pre_disable_nothing ] + [ subdir-run disable : prog ] + [ subdir-run disable : prog_pre_disable_nothing ] + + [ subdir-lib disable : lib_a : + shared:BOOST_CONTRACT_TEST_LIB_A_DYN_LINK ] + [ subdir-lib disable : lib_b : disable-lib_a + shared:BOOST_CONTRACT_TEST_LIB_B_DYN_LINK ] + [ subdir-run disable : libs : + disable-lib_a disable-lib_b ] ; test-suite set : - [ subdir-run-withno set : pre_old_post ] - [ subdir-run-withno set : pre_old ] - [ subdir-run-withno set : old_post ] - [ subdir-run-withno set : pre_post ] - [ subdir-run-withno set : pre ] - [ subdir-run-withno set : old ] - [ subdir-run-withno set : post ] - [ subdir-run-withno set : nothing ] + [ subdir-run set : pre_old_post ] + [ subdir-run set : pre_old ] + [ subdir-run set : old_post ] + [ subdir-run set : pre_post ] + [ subdir-run set : pre ] + [ subdir-run set : old ] + [ subdir-run set : post ] + [ subdir-run set : nothing ] - [ subdir-run-withno set : no_guard ] + [ subdir-run set : no_guard ] [ subdir-compile-fail set : old_pre_error ] [ subdir-compile-fail set : post_old_error ] @@ -244,7 +251,7 @@ test-suite call_if [ subdir-run call_if : equal_to ] ; -# C++14 supported only by Clang... so in its own suite and explicit. +# C++14 supported only by Clang... so in its own test-suite and explicit. test-suite cxx14 : [ subdir-run call_if : equal_to_cxx14 : diff --git a/test/aux_/oteststream.hpp b/test/aux_/oteststream.hpp index 4e2cba7..a01540c 100644 --- a/test/aux_/oteststream.hpp +++ b/test/aux_/oteststream.hpp @@ -35,8 +35,10 @@ struct oteststream : std::string str() const { return oss_.str(); } void str(std::string const& s) { oss_.str(s); } - bool eq(std::string const& s) { // Also display mismatching characters. - std::string r = str(); + bool eq(std::string const& s) { return eq(str(), s); } + + // Also display mismatching characters. + static bool eq(std::string const& r, std::string const& s) { std::string::size_type i = 0; for(; i < r.size() && i < s.size(); ++i) if(r[i] != s[i]) break; if(i < r.size() || i < s.size()) { diff --git a/test/constructor/bases.cpp b/test/constructor/bases.cpp index f1a7575..f949c2d 100644 --- a/test/constructor/bases.cpp +++ b/test/constructor/bases.cpp @@ -347,7 +347,6 @@ int main() { BOOST_TEST_EQ(a::x_type::evals(), BOOST_PP_IIF(BOOST_CONTRACT_POSTCONDITIONS, 1, 0)); BOOST_TEST_EQ(a::x_type::ctors(), a::x_type::dtors()); // No leak. - // TODO: I should check these ctors() == dtors() every where cnt_type is used, in all tests. BOOST_TEST_EQ(c::y_type::copies(), BOOST_PP_IIF(BOOST_CONTRACT_POSTCONDITIONS, 1, 0)); diff --git a/test/disable/checking.cpp b/test/disable/checking.cpp deleted file mode 100644 index 3204259..0000000 --- a/test/disable/checking.cpp +++ /dev/null @@ -1,6 +0,0 @@ - -// Test other contract checking disabled within contract checking. - -#undef BOOST_CONTRACT_CONFIG_PRECONDITIONS_DISABLE_NOTHING -#include "checking.hpp" - diff --git a/test/disable/checking.hpp b/test/disable/checking.hpp deleted file mode 100644 index 54d85bc..0000000 --- a/test/disable/checking.hpp +++ /dev/null @@ -1,162 +0,0 @@ - -// Test contract checking and old value copies disabled within contracts. - -#include "../aux_/oteststream.hpp" -#include "../aux_/counter.hpp" -#include -#include -#include -#include -#include -#include - -boost::contract::test::aux::oteststream out; - -struct a { - static void static_invariant() { out << "a::static_inv" << std::endl; } - void invariant() const { out << "a::inv" << std::endl; } - - struct x_tag; - typedef boost::contract::test::aux::counter x_type; - - int f(x_type& x) { - int result; - boost::contract::old_ptr old_x = BOOST_CONTRACT_OLDOF( - x_type::eval(x)); - boost::contract::guard c = boost::contract::public_function(this) - .precondition([&] { out << "a::f::pre" << std::endl; }) - .old([&] { out << "a::f::old" << std::endl; }) - .postcondition([&] { - out << "a::f::post" << std::endl; - BOOST_CONTRACT_ASSERT(x.value == -old_x->value); - BOOST_CONTRACT_ASSERT(result == old_x->value); - }) - ; - out << "a::f::body" << std::endl; - result = x.value; - x.value = -x.value; - return result; - } -}; - -bool call_f() { - a aa; - a::x_type x; x.value = -123; - return aa.f(x) == -123; -} - -struct b { - static void static_invariant() { out << "b::static_inv" << std::endl; } - void invariant() const { out << "b::inv" << std::endl; } - - void g() { - boost::contract::guard c = boost::contract::public_function(this) - .precondition([&] { - out << "b::g::pre" << std::endl; - BOOST_CONTRACT_ASSERT(call_f()); - }) - .old([&] { out << "b::g::old" << std::endl; }) - .postcondition([&] { - out << "b::g::post" << std::endl; - BOOST_CONTRACT_ASSERT(call_f()); - }) - ; - out << "b::g::body" << std::endl; - } -}; - -int main() { - std::ostringstream ok; - b bb; - - out.str(""); - bb.g(); - ok.str(""); ok - #if BOOST_CONTRACT_ENTRY_INVARIANTS - << "b::static_inv" << std::endl - << "b::inv" << std::endl - #endif - #if BOOST_CONTRACT_PRECONDITIONS - << "b::g::pre" << std::endl - #ifndef BOOST_CONTRACT_CONFIG_PRECONDITIONS_DISABLE_NOTHING - // Test call while checking executes body (but no contracts). - << "a::f::body" << std::endl - #else - // Test preconditions have disabled no contract. - #if BOOST_CONTRACT_ENTRY_INVARIANTS - << "a::static_inv" << std::endl - << "a::inv" << std::endl - #endif - << "a::f::pre" << std::endl - #if BOOST_CONTRACT_POSTCONDITIONS - << "a::f::old" << std::endl - #endif - << "a::f::body" << std::endl - #if BOOST_CONTRACT_EXIT_INVARIANTS - << "a::static_inv" << std::endl - << "a::inv" << std::endl - #endif - #if BOOST_CONTRACT_POSTCONDITIONS - << "a::f::post" << std::endl - #endif - #endif - #endif - #if BOOST_CONTRACT_POSTCONDITIONS - << "b::g::old" << std::endl - #endif - << "b::g::body" << std::endl - #if BOOST_CONTRACT_EXIT_INVARIANTS - << "b::static_inv" << std::endl - << "b::inv" << std::endl - #endif - #if BOOST_CONTRACT_POSTCONDITIONS - << "b::g::post" << std::endl - // Test call while checking executes body (but no contracts). - << "a::f::body" << std::endl - #endif - ; - BOOST_TEST(out.eq(ok.str())); - - // Test old values not copied for disabled contracts. - unsigned const cnt = - #if defined(BOOST_CONTRACT_CONFIG_PRECONDITIONS_DISABLE_NOTHING) && \ - BOOST_CONTRACT_PRECONDITIONS && BOOST_CONTRACT_POSTCONDITIONS - 1 - #else - 0 - #endif - ; - BOOST_TEST_EQ(a::x_type::copies(), cnt); - BOOST_TEST_EQ(a::x_type::evals(), cnt); - BOOST_TEST_EQ(a::x_type::ctors(), a::x_type::dtors()); - - out << std::endl; - - out.str(""); - call_f(); - // Double check a call to f outside another contract checks f's contracts. - ok.str(""); ok - #if BOOST_CONTRACT_ENTRY_INVARIANTS - << "a::static_inv" << std::endl - << "a::inv" << std::endl - #endif - #if BOOST_CONTRACT_PRECONDITIONS - << "a::f::pre" << std::endl - #endif - #if BOOST_CONTRACT_POSTCONDITIONS - << "a::f::old" << std::endl - #endif - << "a::f::body" << std::endl - #if BOOST_CONTRACT_EXIT_INVARIANTS - << "a::static_inv" << std::endl - << "a::inv" << std::endl - #endif - #if BOOST_CONTRACT_POSTCONDITIONS - << "a::f::post" << std::endl - #endif - ; - BOOST_TEST(out.eq(ok.str())); - - return boost::report_errors(); -} - diff --git a/test/disable/lib_a.cpp b/test/disable/lib_a.cpp new file mode 100644 index 0000000..08945a6 --- /dev/null +++ b/test/disable/lib_a.cpp @@ -0,0 +1,6 @@ + +// Test other contract checking disabled within contract checking [among libs]. + +#define BOOST_CONTRACT_TEST_LIB_A_SOURCE +#include "lib_a_inlined.hpp" + diff --git a/test/disable/lib_a.hpp b/test/disable/lib_a.hpp new file mode 100644 index 0000000..a5c2a06 --- /dev/null +++ b/test/disable/lib_a.hpp @@ -0,0 +1,42 @@ + +#ifndef BOOST_CONTRACT_TEST_LIB_A_HPP_ +#define BOOST_CONTRACT_TEST_LIB_A_HPP_ + +#include "../aux_/counter.hpp" +#include +#include + +// Test other contract checking disabled within contract checking [among libs]. + +#ifdef BOOST_CONTRACT_TEST_LIB_A_DYN_LINK + #ifdef BOOST_CONTRACT_TEST_LIB_A_SOURCE + #define BOOST_CONTRACT_TEST_LIB_A_DECL BOOST_SYMBOL_EXPORT + #else + #define BOOST_CONTRACT_TEST_LIB_A_DECL BOOST_SYMBOL_IMPORT + #endif +#else + #define BOOST_CONTRACT_TEST_LIB_A_DECL /* nothing */ +#endif + +void BOOST_CONTRACT_TEST_LIB_A_DECL out(std::string const& text); +bool BOOST_CONTRACT_TEST_LIB_A_DECL out_eq(std::string const& text); + +struct BOOST_CONTRACT_TEST_LIB_A_DECL a { + static void static_invariant(); + void invariant() const; + + struct x_tag; + typedef boost::contract::test::aux::counter x_type; + + int f(x_type& x); + + static void disable_pre_failure(); + static void disable_post_failure(); + static void disable_entry_inv_failure(); + static void disable_exit_inv_failure(); + static void disable_inv_failure(); + static void disable_failure(); +}; + +#endif // #include guard + diff --git a/test/disable/lib_a_inlined.hpp b/test/disable/lib_a_inlined.hpp new file mode 100644 index 0000000..b4d4dd5 --- /dev/null +++ b/test/disable/lib_a_inlined.hpp @@ -0,0 +1,81 @@ + +#ifndef BOOST_TEST_LIB_A_INLINED_HPP_ +#define BOOST_TEST_LIB_A_INLINED_HPP_ + +// Test other contract checking disabled within contract checking [among libs]. + +#include "lib_a.hpp" +#include "../aux_/oteststream.hpp" +#include +#include +#include +#include + +std::string out_; + +void out(std::string const& text) { + if(text == "") out_ = ""; + else { + out_ = out_ + text; + std::clog << text; + } +} + +bool out_eq(std::string const& text) { + return boost::contract::test::aux::oteststream::eq(out_, text); +} + +void a::static_invariant() { out("a::static_inv\n"); } +void a::invariant() const { out("a::inv\n"); } + +int a::f(x_type& x) { + int result; + boost::contract::old_ptr old_x = BOOST_CONTRACT_OLDOF( + x_type::eval(x)); + boost::contract::guard c = boost::contract::public_function(this) + .precondition([&] { out("a::f::pre\n"); }) + .old([&] { out("a::f::old\n"); }) + .postcondition([&] { + out("a::f::post\n"); + BOOST_CONTRACT_ASSERT(x.value == -old_x->value); + BOOST_CONTRACT_ASSERT(result == old_x->value); + }) + ; + out("a::f::body\n"); + result = x.value; + x.value = -x.value; + return result; +} + +void a::disable_pre_failure() { + boost::contract::set_precondition_failure([] (boost::contract::from) + { out("a::pre_failure"); }); +} + +void a::disable_post_failure() { + boost::contract::set_postcondition_failure([] (boost::contract::from) + { out("a::post_failure"); }); +} + +void a::disable_entry_inv_failure() { + boost::contract::set_entry_invariant_failure([] (boost::contract::from) + { out("a::entry_inv_failure"); }); +} + +void a::disable_exit_inv_failure() { + boost::contract::set_exit_invariant_failure([] (boost::contract::from) + { out("a::exit_inv_failure"); }); +} + +void a::disable_inv_failure() { + boost::contract::set_invariant_failure([] (boost::contract::from) + { out("a::inv_failure"); }); +} + +void a::disable_failure() { + boost::contract::set_failure([] (boost::contract::from) + { out("a::failure"); }); +} + +#endif // #include guard + diff --git a/test/disable/lib_b.cpp b/test/disable/lib_b.cpp new file mode 100644 index 0000000..b1936b9 --- /dev/null +++ b/test/disable/lib_b.cpp @@ -0,0 +1,6 @@ + +// Test other contract checking disabled within contract checking [among libs]. + +#define BOOST_CONTRACT_TEST_LIB_B_SOURCE +#include "lib_b_inlined.hpp" + diff --git a/test/disable/lib_b.hpp b/test/disable/lib_b.hpp new file mode 100644 index 0000000..2e38042 --- /dev/null +++ b/test/disable/lib_b.hpp @@ -0,0 +1,38 @@ + +#ifndef BOOST_CONTRACT_TEST_LIB_B_HPP_ +#define BOOST_CONTRACT_TEST_LIB_B_HPP_ + +// Test other contract checking disabled within contract checking [among libs]. + +#include + +#ifdef BOOST_CONTRACT_TEST_LIB_B_DYN_LINK + #ifdef BOOST_CONTRACT_TEST_LIB_B_SOURCE + #define BOOST_CONTRACT_TEST_LIB_B_DECL BOOST_SYMBOL_EXPORT + #else + #define BOOST_CONTRACT_TEST_LIB_B_DECL BOOST_SYMBOL_IMPORT + #endif +#else + #define BOOST_CONTRACT_TEST_LIB_B_DECL /* nothing */ +#endif + +bool BOOST_CONTRACT_TEST_LIB_B_DECL call_f(); + +struct BOOST_CONTRACT_TEST_LIB_B_DECL b { + static void static_invariant(); + void invariant() const; + + void g(); + + static bool test_disable_pre_failure(); + static bool test_disable_post_failure(); + static bool test_disable_entry_inv_failure(); + static bool test_disable_exit_inv_failure(); + static bool test_disable_inv_failure(); + static bool test_disable_failure(); + +}; + +#endif // #include guard + + diff --git a/test/disable/lib_b_inlined.hpp b/test/disable/lib_b_inlined.hpp new file mode 100644 index 0000000..d1a79bb --- /dev/null +++ b/test/disable/lib_b_inlined.hpp @@ -0,0 +1,94 @@ + +#ifndef BOOST_TEST_LIB_B_INLINED_HPP_ +#define BOOST_TEST_LIB_B_INLINED_HPP_ + +// Test other contract checking disabled within contract checking [among libs]. + +#include "lib_b.hpp" +#include "lib_a.hpp" +#include +#include +#include + +bool call_f() { + a aa; + a::x_type x; x.value = -123; + return aa.f(x) == -123; +} + +void b::static_invariant() { out("b::static_inv\n"); } +void b::invariant() const { out("b::inv\n"); } + +void b::g() { + boost::contract::guard c = boost::contract::public_function(this) + .precondition([&] { + out("b::g::pre\n"); + BOOST_CONTRACT_ASSERT(call_f()); + }) + .old([&] { out("b::g::old\n"); }) + .postcondition([&] { + out("b::g::post\n"); + BOOST_CONTRACT_ASSERT(call_f()); + }) + ; + out("b::g::body\n"); +} + +bool b::test_disable_pre_failure() { + a::disable_pre_failure(); + out(""); + boost::contract::precondition_failure(boost::contract::from()); + return out_eq("a::pre_failure"); +} + +bool b::test_disable_post_failure() { + a::disable_post_failure(); + out(""); + boost::contract::postcondition_failure(boost::contract::from()); + return out_eq("a::post_failure"); +} + +bool b::test_disable_entry_inv_failure() { + a::disable_entry_inv_failure(); + out(""); + boost::contract::entry_invariant_failure(boost::contract::from()); + return out_eq("a::entry_inv_failure"); +} + +bool b::test_disable_exit_inv_failure() { + a::disable_exit_inv_failure(); + out(""); + boost::contract::exit_invariant_failure(boost::contract::from()); + return out_eq("a::exit_inv_failure"); +} + +bool b::test_disable_inv_failure() { + a::disable_inv_failure(); + out(""); + boost::contract::entry_invariant_failure(boost::contract::from()); + bool entry_inv = out_eq("a::inv_failure"); + out(""); + boost::contract::exit_invariant_failure(boost::contract::from()); + bool exit_inv = out_eq("a::inv_failure"); + return entry_inv && exit_inv; +} + +bool b::test_disable_failure() { + a::disable_failure(); + out(""); + boost::contract::precondition_failure(boost::contract::from()); + bool pre = out_eq("a::failure"); + out(""); + boost::contract::postcondition_failure(boost::contract::from()); + bool post = out_eq("a::failure"); + out(""); + boost::contract::entry_invariant_failure(boost::contract::from()); + bool entry_inv = out_eq("a::failure"); + out(""); + boost::contract::exit_invariant_failure(boost::contract::from()); + bool exit_inv = out_eq("a::failure"); + return pre && post && entry_inv && exit_inv; +} + +#endif // #include guard + diff --git a/test/disable/libs.cpp b/test/disable/libs.cpp new file mode 100644 index 0000000..b001167 --- /dev/null +++ b/test/disable/libs.cpp @@ -0,0 +1,5 @@ + +// Test other contract checking disabled within contract checking among libs. + +#include "libs.hpp" + diff --git a/test/disable/libs.hpp b/test/disable/libs.hpp new file mode 100644 index 0000000..12707f5 --- /dev/null +++ b/test/disable/libs.hpp @@ -0,0 +1,158 @@ + +// Test other contract checking disabled within contract checking [among libs]. + +#include "lib_a.hpp" +#include "lib_b.hpp" +#include +#include +#include +#include +#include +#include + +std::string ok_f() { + std::ostringstream ok; ok + #if BOOST_CONTRACT_ENTRY_INVARIANTS + << "a::static_inv" << std::endl + << "a::inv" << std::endl + #endif + #if BOOST_CONTRACT_PRECONDITIONS + << "a::f::pre" << std::endl + #endif + #if BOOST_CONTRACT_POSTCONDITIONS + << "a::f::old" << std::endl + #endif + << "a::f::body" << std::endl + #if BOOST_CONTRACT_EXIT_INVARIANTS + << "a::static_inv" << std::endl + << "a::inv" << std::endl + #endif + #if BOOST_CONTRACT_POSTCONDITIONS + << "a::f::post" << std::endl + #endif + ; + return ok.str(); +} + +int main() { + std::ostringstream ok; + b bb; + + out(""); + bb.g(); + ok.str(""); ok + #if BOOST_CONTRACT_ENTRY_INVARIANTS + << "b::static_inv" << std::endl + << "b::inv" << std::endl + #endif + #if BOOST_CONTRACT_PRECONDITIONS + << "b::g::pre" << std::endl + #ifdef BOOST_CONTRACT_HEADER_ONLY + // Test preconditions have disabled no contract (incorrect, but + // only possible behaviour if shared linking not used ad doc). + << ok_f() + #elif defined(BOOST_CONTRACT_CONFIG_PRECONDITIONS_DISABLE_NOTHING) + // Test preconditions have disabled no contract. + << ok_f() + #else + // Test call while checking executes body (but no contracts). + << "a::f::body" << std::endl + #endif + #endif + #if BOOST_CONTRACT_POSTCONDITIONS + << "b::g::old" << std::endl + #endif + << "b::g::body" << std::endl + #if BOOST_CONTRACT_EXIT_INVARIANTS + << "b::static_inv" << std::endl + << "b::inv" << std::endl + #endif + #if BOOST_CONTRACT_POSTCONDITIONS + << "b::g::post" << std::endl + #ifdef BOOST_CONTRACT_HEADER_ONLY + // Test preconditions have disabled no contract (incorrect, but + // only possible behaviour if shared linking not used ad doc). + << ok_f() + #else + // Test call while checking executes body (but no contracts). + << "a::f::body" << std::endl + #endif + #endif + ; + BOOST_TEST(out_eq(ok.str())); + + // Test old values not copied for disabled contracts. + unsigned const cnt = + #if defined(BOOST_CONTRACT_CONFIG_PRECONDITIONS_DISABLE_NOTHING) && \ + BOOST_CONTRACT_PRECONDITIONS && BOOST_CONTRACT_POSTCONDITIONS + 1 + #else + 0 + #endif + ; + BOOST_TEST_EQ(a::x_type::copies(), cnt); + BOOST_TEST_EQ(a::x_type::evals(), cnt); + BOOST_TEST_EQ(a::x_type::ctors(), a::x_type::dtors()); + + // Double check a call to f outside another contract checks f's contracts. + out(""); + call_f(); + BOOST_TEST(out_eq(ok_f())); + + // Test setting failure handlers (from this program using a lib). + + a::disable_pre_failure(); + out(""); + boost::contract::precondition_failure(boost::contract::from()); + BOOST_TEST(out_eq("a::pre_failure")); + + a::disable_post_failure(); + out(""); + boost::contract::postcondition_failure(boost::contract::from()); + BOOST_TEST(out_eq("a::post_failure")); + + a::disable_entry_inv_failure(); + out(""); + boost::contract::entry_invariant_failure(boost::contract::from()); + BOOST_TEST(out_eq("a::entry_inv_failure")); + + a::disable_exit_inv_failure(); + out(""); + boost::contract::exit_invariant_failure(boost::contract::from()); + BOOST_TEST(out_eq("a::exit_inv_failure")); + + a::disable_inv_failure(); + out(""); + boost::contract::entry_invariant_failure(boost::contract::from()); + BOOST_TEST(out_eq("a::inv_failure")); + out(""); + boost::contract::exit_invariant_failure(boost::contract::from()); + BOOST_TEST(out_eq("a::inv_failure")); + + a::disable_failure(); + out(""); + boost::contract::precondition_failure(boost::contract::from()); + BOOST_TEST(out_eq("a::failure")); + out(""); + boost::contract::postcondition_failure(boost::contract::from()); + BOOST_TEST(out_eq("a::failure")); + out(""); + boost::contract::entry_invariant_failure(boost::contract::from()); + BOOST_TEST(out_eq("a::failure")); + out(""); + boost::contract::exit_invariant_failure(boost::contract::from()); + BOOST_TEST(out_eq("a::failure")); + + + // Test setting failure handlers (from a lib using another lib). + + BOOST_TEST(b::test_disable_pre_failure()); + BOOST_TEST(b::test_disable_post_failure()); + BOOST_TEST(b::test_disable_entry_inv_failure()); + BOOST_TEST(b::test_disable_exit_inv_failure()); + BOOST_TEST(b::test_disable_inv_failure()); + BOOST_TEST(b::test_disable_failure()); + + return boost::report_errors(); +} + diff --git a/test/disable/prog.cpp b/test/disable/prog.cpp new file mode 100644 index 0000000..0350ab9 --- /dev/null +++ b/test/disable/prog.cpp @@ -0,0 +1,9 @@ + +// Test other contract checking disabled within contract checking (in a prog). + +#include "lib_a.hpp" +#include "lib_a_inlined.hpp" +#include "lib_b.hpp" +#include "lib_b_inlined.hpp" +#include "libs.hpp" + diff --git a/test/disable/checking_pre_disable_nothing.cpp b/test/disable/prog_pre_disable_nothing.cpp similarity index 53% rename from test/disable/checking_pre_disable_nothing.cpp rename to test/disable/prog_pre_disable_nothing.cpp index 07c8119..fc2a1c0 100644 --- a/test/disable/checking_pre_disable_nothing.cpp +++ b/test/disable/prog_pre_disable_nothing.cpp @@ -2,5 +2,9 @@ // Test other contract checking but pre disabled within contract checking. #define BOOST_CONTRACT_CONFIG_PRECONDITIONS_DISABLE_NOTHING -#include "checking.hpp" +#include "lib_a.hpp" +#include "lib_a_inlined.hpp" +#include "lib_b.hpp" +#include "lib_b_inlined.hpp" +#include "libs.hpp" diff --git a/test/public_function/bases.cpp b/test/public_function/bases.cpp index f7d23b4..8aab1c4 100644 --- a/test/public_function/bases.cpp +++ b/test/public_function/bases.cpp @@ -67,35 +67,35 @@ int main() { BOOST_PP_IIF(BOOST_CONTRACT_POSTCONDITIONS, 4, 0)); BOOST_TEST_EQ(s.evals(), BOOST_PP_IIF(BOOST_CONTRACT_POSTCONDITIONS, 4, 0)); - BOOST_TEST_EQ(s.ctors(), s.dtors()); + BOOST_TEST_EQ(s.ctors(), s.dtors() + 1); // 1 for local var. BOOST_TEST_EQ(aa.x.value, "aA"); BOOST_TEST_EQ(aa.x.copies(), BOOST_PP_IIF(BOOST_CONTRACT_POSTCONDITIONS, 1, 0)); BOOST_TEST_EQ(aa.x.evals(), BOOST_PP_IIF(BOOST_CONTRACT_POSTCONDITIONS, 1, 0)); - BOOST_TEST_EQ(aa.x.ctors(), aa.x.dtors()); + BOOST_TEST_EQ(aa.x.ctors(), aa.x.dtors() + 1); // 1 for member var. BOOST_TEST_EQ(aa.y.value, "cA"); BOOST_TEST_EQ(aa.y.copies(), BOOST_PP_IIF(BOOST_CONTRACT_POSTCONDITIONS, 1, 0)); BOOST_TEST_EQ(aa.y.evals(), BOOST_PP_IIF(BOOST_CONTRACT_POSTCONDITIONS, 1, 0)); - BOOST_TEST_EQ(aa.y.ctors(), aa.y.dtors()); + BOOST_TEST_EQ(aa.y.ctors(), aa.y.dtors() + 1); // 1 for member var. BOOST_TEST_EQ(aa.t<'d'>::z.value, "dA"); BOOST_TEST_EQ(aa.t<'d'>::z.copies(), BOOST_PP_IIF(BOOST_CONTRACT_POSTCONDITIONS, 1, 0)); BOOST_TEST_EQ(aa.t<'d'>::z.evals(), BOOST_PP_IIF(BOOST_CONTRACT_POSTCONDITIONS, 1, 0)); - BOOST_TEST_EQ(aa.t<'d'>::z.ctors(), aa.t<'d'>::z.dtors()); + BOOST_TEST_EQ(aa.t<'d'>::z.ctors(), aa.t<'d'>::z.dtors() + 1); // 1 member. BOOST_TEST_EQ(aa.t<'e'>::z.value, "eA"); BOOST_TEST_EQ(aa.t<'e'>::z.copies(), BOOST_PP_IIF(BOOST_CONTRACT_POSTCONDITIONS, 1, 0)); BOOST_TEST_EQ(aa.t<'e'>::z.evals(), BOOST_PP_IIF(BOOST_CONTRACT_POSTCONDITIONS, 1, 0)); - BOOST_TEST_EQ(aa.t<'e'>::z.ctors(), aa.t<'e'>::z.dtors()); + BOOST_TEST_EQ(aa.t<'e'>::z.ctors(), aa.t<'e'>::z.dtors() + 1); // 1 member. return boost::report_errors(); } diff --git a/test/result/mixed_optional.hpp b/test/result/mixed_optional.hpp index 236a1f9..a658dbc 100644 --- a/test/result/mixed_optional.hpp +++ b/test/result/mixed_optional.hpp @@ -29,7 +29,7 @@ typedef boost::contract::test::aux::counter ch_type; #else // Test with result types by value. #define BOOST_CONTRACT_TEST_CH_TYPE ch_type #define BOOST_CONTRACT_TEST_CH_INIT /* nothing */ - unsigned const ch_extras = 1; // Only 1 local (no global) var. + unsigned const ch_extras = 1; // 1 for local var (no global var). #endif bool tested_d_copies = false;