diff options
Diffstat (limited to '')
351 files changed, 34540 insertions, 0 deletions
diff --git a/src/boost/libs/contract/Jamfile.v2 b/src/boost/libs/contract/Jamfile.v2 new file mode 100644 index 000000000..4e921c64d --- /dev/null +++ b/src/boost/libs/contract/Jamfile.v2 @@ -0,0 +1,14 @@ +# Boost.Contract Library Jamfile +# +# Use, modification, and distribution are subject to the +# Boost Software License, Version 1.0. (See accompanying file +# LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +# please order by name to ease maintenance (this is used by CI) +# +# CI build of examples disabled at repository owner's request (examples are +# meant for docs so for simplicity might omit work-around to build on all plat) +# build-project example ; +# +build-project test ; + diff --git a/src/boost/libs/contract/LICENSE_1_0.txt b/src/boost/libs/contract/LICENSE_1_0.txt new file mode 100644 index 000000000..36b7cd93c --- /dev/null +++ b/src/boost/libs/contract/LICENSE_1_0.txt @@ -0,0 +1,23 @@ +Boost Software License - Version 1.0 - August 17th, 2003 + +Permission is hereby granted, free of charge, to any person or organization +obtaining a copy of the software and accompanying documentation covered by +this license (the "Software") to use, reproduce, display, distribute, +execute, and transmit the Software, and to prepare derivative works of the +Software, and to permit third-parties to whom the Software is furnished to +do so, all subject to the following: + +The copyright notices in the Software and this entire statement, including +the above license grant, this restriction and the following disclaimer, +must be included in all copies of the Software, in whole or in part, and +all derivative works of the Software, unless such copies or derivative +works are solely in the form of machine-executable object code generated by +a source language processor. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. diff --git a/src/boost/libs/contract/README.md b/src/boost/libs/contract/README.md new file mode 100644 index 000000000..170a5e460 --- /dev/null +++ b/src/boost/libs/contract/README.md @@ -0,0 +1,41 @@ +Boost.Contract +============== + +Contract programming for C++. +All contract programming features are supported: Subcontracting, class invariants (also static and volatile), postconditions (with old and return values), preconditions, customizable actions on assertion failure (e.g., terminate or throw), optional compilation and checking of assertions, disable assertions while already checking other assertions (to avoid infinite recursion), etc. + +### License + +Distributed under the [Boost Software License, Version 1.0](http://www.boost.org/LICENSE_1_0.txt). + +### Properties + +* C++11 (C++03 possible but not recommended without lambda functions and variadic macros, see documentation for more information). +* Shared Library / DLL with `BOOST_CONTRACT_DYN_LINK` (static library with `BOOST_CONTRACT_STATIC_LINK`, header-only also possible but not recommended, see `BOOST_CONTRACT_HEADER_ONLY` documentation for more information). + +### Build Status + +Branch | Travis | Appveyor | Coverity Scan | codecov.io | Deps | Docs | Tests | +:-------------: | ------ | -------- | ------------- | ---------- | ---- | ---- | ----- | +[`master`](https://github.com/boostorg/contract/tree/master) | [![Build Status](https://travis-ci.com/boostorg/contract.svg?branch=master)](https://travis-ci.com/boostorg/contract) | [![Build status](https://ci.appveyor.com/api/projects/status/FILL-ME-IN/branch/master?svg=true)](https://ci.appveyor.com/project/lcaminiti/contract/branch/master) | [![Coverity Scan Build Status](https://scan.coverity.com/projects/18555/badge.svg)](https://scan.coverity.com/projects/boostorg-contract) | [![codecov](https://codecov.io/gh/boostorg/contract/branch/master/graph/badge.svg)](https://codecov.io/gh/boostorg/contract/branch/master)| [![Deps](https://img.shields.io/badge/deps-master-brightgreen.svg)](https://pdimov.github.io/boostdep-report/master/contract.html) | [![Documentation](https://img.shields.io/badge/docs-master-brightgreen.svg)](https://www.boost.org/doc/libs/master/libs/contract/doc/html/index.html) | [![Enter the Matrix](https://img.shields.io/badge/matrix-master-brightgreen.svg)](http://www.boost.org/development/tests/master/developer/contract.html) +[`develop`](https://github.com/boostorg/contract/tree/develop) | [![Build Status](https://travis-ci.com/boostorg/contract.svg?branch=develop)](https://travis-ci.com/boostorg/contract) | [![Build status](https://ci.appveyor.com/api/projects/status/FILL-ME-IN/branch/develop?svg=true)](https://ci.appveyor.com/project/lcaminiti/contract/branch/develop) | [![Coverity Scan Build Status](https://scan.coverity.com/projects/18555/badge.svg)](https://scan.coverity.com/projects/boostorg-contract) | [![codecov](https://codecov.io/gh/boostorg/contract/branch/develop/graph/badge.svg)](https://codecov.io/gh/boostorg/contract/branch/develop) | [![Deps](https://img.shields.io/badge/deps-develop-brightgreen.svg)](https://pdimov.github.io/boostdep-report/develop/contract.html) | [![Documentation](https://img.shields.io/badge/docs-develop-brightgreen.svg)](https://www.boost.org/doc/libs/develop/libs/contract/doc/html/index.html) | [![Enter the Matrix](https://img.shields.io/badge/matrix-develop-brightgreen.svg)](http://www.boost.org/development/tests/develop/developer/contract.html) + +### Directories + +| Name | Purpose | +| ----------- | ------------------------------ | +| `build` | Build | +| `doc` | Documentation | +| `example` | Examples | +| `include` | Header code | +| `meta` | Integration with Boost | +| `src` | Source code | +| `test` | Unit tests | + +### More Information + +* [Ask questions](http://stackoverflow.com/questions/ask?tags=c%2B%2B,boost,boost-contract). +* [Report bugs](https://github.com/boostorg/contract/issues): Be sure to mention Boost version, platform and compiler you are using. A small compilable code sample to reproduce the problem is always good as well. +* Submit your patches as pull requests against **develop** branch. Note that by submitting patches you agree to license your modifications under the [Boost Software License, Version 1.0](http://www.boost.org/LICENSE_1_0.txt). +* Discussions about the library are held on the [Boost developers mailing list](http://www.boost.org/community/groups.html#main). Be sure to read the [discussion policy](http://www.boost.org/community/policy.html) before posting and add the `[contract]` text at the beginning of the subject line. + diff --git a/src/boost/libs/contract/build/Jamfile.v2 b/src/boost/libs/contract/build/Jamfile.v2 new file mode 100644 index 000000000..3894232a0 --- /dev/null +++ b/src/boost/libs/contract/build/Jamfile.v2 @@ -0,0 +1,23 @@ + +# Copyright (C) 2008-2018 Lorenzo Caminiti +# Distributed under the Boost Software License, Version 1.0 (see accompanying +# file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt). +# See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html + +project boost/contract + : source-location ../src + : requirements + <link>shared:<define>BOOST_CONTRACT_DYN_LINK + <link>static:<define>BOOST_CONTRACT_STATIC_LINK + <threading>single:<define>BOOST_CONTRACT_DISABLE_THREADS + : usage-requirements # Independent from requirements above (need to repeat). + <link>shared:<define>BOOST_CONTRACT_DYN_LINK + <link>static:<define>BOOST_CONTRACT_STATIC_LINK + <threading>single:<define>BOOST_CONTRACT_DISABLE_THREADS +; + +# If lib as header-only, none of following will be used. +lib boost_contract : contract.cpp : <link>shared ; +lib boost_contract : contract.cpp : <link>static ; + +boost-install boost_contract ; diff --git a/src/boost/libs/contract/build/boost_contract_build.jam b/src/boost/libs/contract/build/boost_contract_build.jam new file mode 100644 index 000000000..06b7869bf --- /dev/null +++ b/src/boost/libs/contract/build/boost_contract_build.jam @@ -0,0 +1,115 @@ + +# Copyright (C) 2008-2018 Lorenzo Caminiti +# Distributed under the Boost Software License, Version 1.0 (see accompanying +# file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt). +# See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html + +# Usage: bjam [OPTION]... DIR[-CPP_FILE_NAME] +# Build and run Boost.Contract tests and examples. +# +# Options (common to BJam): +# toolset=msvc,gcc,clang,... specify compiler +# cxxstd=03,11,14,17,... specify C++ standard version +# most tests and example use C++11 features +# (lambda, variadic macros, etc.), delete +# "bin.v2/project-cache.jam" to clear previous +# feature checks +# link=shared,static build Boost.Contract as shared (default) or static +# library, this has no effect if `bc_hdr=only` +# Options (specific to this lib): +# bc_hdr=lib,only if `only` then do not build Boost.Contract as library +# and use it as header-only instead (`lib` by default) +# bc_no=all_yes, +# y,r,x,s,e,k,yr,yx,ys,ye,yk,rx,rs,re,rk,xs,xe,xk,se,sk,ek,yrx,yrs,yre,yrk,yxs,yxe,yxk,yse,ysk,yek,rxs,rxe,rxk,rse,rsk,rek,xse,xsk,xek,sek,yrxs,yrxe,yrxk,yrse,yrsk,yrek,yxse,yxsk,yxek,ysek,rxse,rxsk,rxek,rsek,xsek,yrxse,yrxsk,yrxek,yrsek,yxsek,rxsek,yrxsek +# `all_yes` (default) turns off no contract, following +# turn off specific contracts and can be combined wit each +# other (only in the listed order) to disable multiple +# contracts at once: +# y entry invariant +# r preconditions +# x exit invariant +# s postconditions +# e exception guarantees +# k implementation checks +# +# Examples (on Linux-based bash): +# Build just "test/public_function/smoke.cpp" and "example/introduction.cpp": +# [test]$ bjam cxxstd=11 public_function-smoke +# [example]$ bjam cxxstd=11 features-introduction +# Build all tests with all linkages (incl header-only) on multiple compilers: +# [test]$ bjam cxxstd=11 -q toolset=msvc,gcc,clang link=static,header +# [test]$ bjam cxxstd=11 -q toolset=msvc,gcc,clang bc_hdr=only +# Build all tests with no postconditions and exception guarantees first, and +# then again with no class invariants at exit: +# [test]$ time bjam cxxstd=11 -q bc_no=se,x +# Build most all test combinations (for shared and static lib, use bc_hdr=only +# instead of link=... for header-only combinations) but takes forever...: +# [test]$ rm -f ../../../bin.v2/project-cache.jam ; bjam cxxstd=11 -q toolset=msvc,gcc,clang link=shared,static bc_no=all_yes,y,r,x,s,e,k,yr,yx,ys,ye,yk,rx,rs,re,rk,xs,xe,xk,se,sk,ek,yrx,yrs,yre,yrk,yxs,yxe,yxk,yse,ysk,yek,rxs,rxe,rxk,rse,rsk,rek,xse,xsk,xek,sek,yrxs,yrxe,yrxk,yrse,yrsk,yrek,yxse,yxsk,yxek,ysek,rxse,rxsk,rxek,rsek,xsek,yrxse,yrxsk,yrxek,yrsek,yxsek,rxsek,yrxsek > 00.out ; echo $? + +import boost_contract_no ; +import feature ; +import testing ; +import ../../config/checks/config : requires ; + +# Iff "no", link to boost_contract (else, no lib build so don't link to it). +feature.feature bc_hdr : lib only : + composite propagated link-incompatible ; + +# This is boost_contract_no=all_yes,pre,pre_post,... +feature.feature bc_no : all_yes [ boost_contract_no.combinations ] : + composite propagated link-incompatible ; +for local comb in [ boost_contract_no.combinations ] { + feature.compose <bc_no>$(comb) : + [ boost_contract_no.defs_$(comb) ] ; +} + +module boost_contract_build { + +rule project_requirements ( subdir ) { + return + <bc_hdr>lib:<library>../build//boost_contract + <include>$(subdir) + ; +} + +# Most tests and examples require lambdas (even if lib technically does not). +# Also C++11 variadic macros are usually required (for OLDOF, BASES, etc.) but +# Boost.Config check for variadic macros is less stringent than Boost.PP's +# chec (so Boost.PP check done also in code directly when strictly needed). +cxx11_requirements = [ requires cxx11_lambdas cxx11_variadic_macros ] ; + +rule subdir-compile-fail ( subdir : cpp_fname cpp_files * : requirements * ) { + compile-fail $(subdir)/$(cpp_fname).cpp $(cpp_files) + : [ project_requirements $(subdir) ] $(requirements) + : $(subdir)-$(cpp_fname) + ; +} + +rule subdir-run ( subdir : cpp_fname cpp_files * : requirements * ) { + run $(subdir)/$(cpp_fname).cpp $(cpp_files) : : : [ project_requirements + $(subdir) ] $(requirements) : $(subdir)-$(cpp_fname) ; +} + +rule subdir-lib ( subdir : cpp_fname cpp_files * : requirements * ) { + lib $(subdir)-$(cpp_fname) : $(subdir)/$(cpp_fname).cpp $(cpp_files) : + [ project_requirements $(subdir) ] $(requirements) ; +} + +rule subdir-compile-fail-cxx11 ( subdir : cpp_fname cpp_files * : + requirements * ) { + subdir-compile-fail $(subdir) : $(cpp_fname) $(cpp_files) : + $(cxx11_requirements) $(requirements) ; +} + +rule subdir-run-cxx11 ( subdir : cpp_fname cpp_files * : requirements * ) { + subdir-run $(subdir) : $(cpp_fname) $(cpp_files) : $(cxx11_requirements) + $(requirements) ; +} + +rule subdir-lib-cxx11 ( subdir : cpp_fname cpp_files * : requirements * ) { + subdir-lib $(subdir) : $(cpp_fname) $(cpp_files) : $(cxx11_requirements) + $(requirements) ; +} + +} # module + diff --git a/src/boost/libs/contract/build/boost_contract_no.jam b/src/boost/libs/contract/build/boost_contract_no.jam new file mode 100644 index 000000000..29c2a7e66 --- /dev/null +++ b/src/boost/libs/contract/build/boost_contract_no.jam @@ -0,0 +1,142 @@ + +# Generated file `python boost_contract_no.jam-gen.py > boost_contract_no.jam`. + +# Copyright (C) 2008-2018 Lorenzo Caminiti +# Distributed under the Boost Software License, Version 1.0 (see accompanying +# file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt). +# See: https://lcaminiti.github.io/boost-contract + +module boost_contract_no { + +rule defs_y { return <define>BOOST_CONTRACT_NO_ENTRY_INVARIANTS ; } + +rule defs_r { return <define>BOOST_CONTRACT_NO_PRECONDITIONS ; } + +rule defs_x { return <define>BOOST_CONTRACT_NO_EXIT_INVARIANTS ; } + +rule defs_s { return <define>BOOST_CONTRACT_NO_POSTCONDITIONS ; } + +rule defs_e { return <define>BOOST_CONTRACT_NO_EXCEPTS ; } + +rule defs_k { return <define>BOOST_CONTRACT_NO_CHECKS ; } + +rule defs_yr { return <define>BOOST_CONTRACT_NO_ENTRY_INVARIANTS <define>BOOST_CONTRACT_NO_PRECONDITIONS ; } + +rule defs_yx { return <define>BOOST_CONTRACT_NO_ENTRY_INVARIANTS <define>BOOST_CONTRACT_NO_EXIT_INVARIANTS ; } + +rule defs_ys { return <define>BOOST_CONTRACT_NO_ENTRY_INVARIANTS <define>BOOST_CONTRACT_NO_POSTCONDITIONS ; } + +rule defs_ye { return <define>BOOST_CONTRACT_NO_ENTRY_INVARIANTS <define>BOOST_CONTRACT_NO_EXCEPTS ; } + +rule defs_yk { return <define>BOOST_CONTRACT_NO_ENTRY_INVARIANTS <define>BOOST_CONTRACT_NO_CHECKS ; } + +rule defs_rx { return <define>BOOST_CONTRACT_NO_PRECONDITIONS <define>BOOST_CONTRACT_NO_EXIT_INVARIANTS ; } + +rule defs_rs { return <define>BOOST_CONTRACT_NO_PRECONDITIONS <define>BOOST_CONTRACT_NO_POSTCONDITIONS ; } + +rule defs_re { return <define>BOOST_CONTRACT_NO_PRECONDITIONS <define>BOOST_CONTRACT_NO_EXCEPTS ; } + +rule defs_rk { return <define>BOOST_CONTRACT_NO_PRECONDITIONS <define>BOOST_CONTRACT_NO_CHECKS ; } + +rule defs_xs { return <define>BOOST_CONTRACT_NO_EXIT_INVARIANTS <define>BOOST_CONTRACT_NO_POSTCONDITIONS ; } + +rule defs_xe { return <define>BOOST_CONTRACT_NO_EXIT_INVARIANTS <define>BOOST_CONTRACT_NO_EXCEPTS ; } + +rule defs_xk { return <define>BOOST_CONTRACT_NO_EXIT_INVARIANTS <define>BOOST_CONTRACT_NO_CHECKS ; } + +rule defs_se { return <define>BOOST_CONTRACT_NO_POSTCONDITIONS <define>BOOST_CONTRACT_NO_EXCEPTS ; } + +rule defs_sk { return <define>BOOST_CONTRACT_NO_POSTCONDITIONS <define>BOOST_CONTRACT_NO_CHECKS ; } + +rule defs_ek { return <define>BOOST_CONTRACT_NO_EXCEPTS <define>BOOST_CONTRACT_NO_CHECKS ; } + +rule defs_yrx { return <define>BOOST_CONTRACT_NO_ENTRY_INVARIANTS <define>BOOST_CONTRACT_NO_PRECONDITIONS <define>BOOST_CONTRACT_NO_EXIT_INVARIANTS ; } + +rule defs_yrs { return <define>BOOST_CONTRACT_NO_ENTRY_INVARIANTS <define>BOOST_CONTRACT_NO_PRECONDITIONS <define>BOOST_CONTRACT_NO_POSTCONDITIONS ; } + +rule defs_yre { return <define>BOOST_CONTRACT_NO_ENTRY_INVARIANTS <define>BOOST_CONTRACT_NO_PRECONDITIONS <define>BOOST_CONTRACT_NO_EXCEPTS ; } + +rule defs_yrk { return <define>BOOST_CONTRACT_NO_ENTRY_INVARIANTS <define>BOOST_CONTRACT_NO_PRECONDITIONS <define>BOOST_CONTRACT_NO_CHECKS ; } + +rule defs_yxs { return <define>BOOST_CONTRACT_NO_ENTRY_INVARIANTS <define>BOOST_CONTRACT_NO_EXIT_INVARIANTS <define>BOOST_CONTRACT_NO_POSTCONDITIONS ; } + +rule defs_yxe { return <define>BOOST_CONTRACT_NO_ENTRY_INVARIANTS <define>BOOST_CONTRACT_NO_EXIT_INVARIANTS <define>BOOST_CONTRACT_NO_EXCEPTS ; } + +rule defs_yxk { return <define>BOOST_CONTRACT_NO_ENTRY_INVARIANTS <define>BOOST_CONTRACT_NO_EXIT_INVARIANTS <define>BOOST_CONTRACT_NO_CHECKS ; } + +rule defs_yse { return <define>BOOST_CONTRACT_NO_ENTRY_INVARIANTS <define>BOOST_CONTRACT_NO_POSTCONDITIONS <define>BOOST_CONTRACT_NO_EXCEPTS ; } + +rule defs_ysk { return <define>BOOST_CONTRACT_NO_ENTRY_INVARIANTS <define>BOOST_CONTRACT_NO_POSTCONDITIONS <define>BOOST_CONTRACT_NO_CHECKS ; } + +rule defs_yek { return <define>BOOST_CONTRACT_NO_ENTRY_INVARIANTS <define>BOOST_CONTRACT_NO_EXCEPTS <define>BOOST_CONTRACT_NO_CHECKS ; } + +rule defs_rxs { return <define>BOOST_CONTRACT_NO_PRECONDITIONS <define>BOOST_CONTRACT_NO_EXIT_INVARIANTS <define>BOOST_CONTRACT_NO_POSTCONDITIONS ; } + +rule defs_rxe { return <define>BOOST_CONTRACT_NO_PRECONDITIONS <define>BOOST_CONTRACT_NO_EXIT_INVARIANTS <define>BOOST_CONTRACT_NO_EXCEPTS ; } + +rule defs_rxk { return <define>BOOST_CONTRACT_NO_PRECONDITIONS <define>BOOST_CONTRACT_NO_EXIT_INVARIANTS <define>BOOST_CONTRACT_NO_CHECKS ; } + +rule defs_rse { return <define>BOOST_CONTRACT_NO_PRECONDITIONS <define>BOOST_CONTRACT_NO_POSTCONDITIONS <define>BOOST_CONTRACT_NO_EXCEPTS ; } + +rule defs_rsk { return <define>BOOST_CONTRACT_NO_PRECONDITIONS <define>BOOST_CONTRACT_NO_POSTCONDITIONS <define>BOOST_CONTRACT_NO_CHECKS ; } + +rule defs_rek { return <define>BOOST_CONTRACT_NO_PRECONDITIONS <define>BOOST_CONTRACT_NO_EXCEPTS <define>BOOST_CONTRACT_NO_CHECKS ; } + +rule defs_xse { return <define>BOOST_CONTRACT_NO_EXIT_INVARIANTS <define>BOOST_CONTRACT_NO_POSTCONDITIONS <define>BOOST_CONTRACT_NO_EXCEPTS ; } + +rule defs_xsk { return <define>BOOST_CONTRACT_NO_EXIT_INVARIANTS <define>BOOST_CONTRACT_NO_POSTCONDITIONS <define>BOOST_CONTRACT_NO_CHECKS ; } + +rule defs_xek { return <define>BOOST_CONTRACT_NO_EXIT_INVARIANTS <define>BOOST_CONTRACT_NO_EXCEPTS <define>BOOST_CONTRACT_NO_CHECKS ; } + +rule defs_sek { return <define>BOOST_CONTRACT_NO_POSTCONDITIONS <define>BOOST_CONTRACT_NO_EXCEPTS <define>BOOST_CONTRACT_NO_CHECKS ; } + +rule defs_yrxs { return <define>BOOST_CONTRACT_NO_ENTRY_INVARIANTS <define>BOOST_CONTRACT_NO_PRECONDITIONS <define>BOOST_CONTRACT_NO_EXIT_INVARIANTS <define>BOOST_CONTRACT_NO_POSTCONDITIONS ; } + +rule defs_yrxe { return <define>BOOST_CONTRACT_NO_ENTRY_INVARIANTS <define>BOOST_CONTRACT_NO_PRECONDITIONS <define>BOOST_CONTRACT_NO_EXIT_INVARIANTS <define>BOOST_CONTRACT_NO_EXCEPTS ; } + +rule defs_yrxk { return <define>BOOST_CONTRACT_NO_ENTRY_INVARIANTS <define>BOOST_CONTRACT_NO_PRECONDITIONS <define>BOOST_CONTRACT_NO_EXIT_INVARIANTS <define>BOOST_CONTRACT_NO_CHECKS ; } + +rule defs_yrse { return <define>BOOST_CONTRACT_NO_ENTRY_INVARIANTS <define>BOOST_CONTRACT_NO_PRECONDITIONS <define>BOOST_CONTRACT_NO_POSTCONDITIONS <define>BOOST_CONTRACT_NO_EXCEPTS ; } + +rule defs_yrsk { return <define>BOOST_CONTRACT_NO_ENTRY_INVARIANTS <define>BOOST_CONTRACT_NO_PRECONDITIONS <define>BOOST_CONTRACT_NO_POSTCONDITIONS <define>BOOST_CONTRACT_NO_CHECKS ; } + +rule defs_yrek { return <define>BOOST_CONTRACT_NO_ENTRY_INVARIANTS <define>BOOST_CONTRACT_NO_PRECONDITIONS <define>BOOST_CONTRACT_NO_EXCEPTS <define>BOOST_CONTRACT_NO_CHECKS ; } + +rule defs_yxse { return <define>BOOST_CONTRACT_NO_ENTRY_INVARIANTS <define>BOOST_CONTRACT_NO_EXIT_INVARIANTS <define>BOOST_CONTRACT_NO_POSTCONDITIONS <define>BOOST_CONTRACT_NO_EXCEPTS ; } + +rule defs_yxsk { return <define>BOOST_CONTRACT_NO_ENTRY_INVARIANTS <define>BOOST_CONTRACT_NO_EXIT_INVARIANTS <define>BOOST_CONTRACT_NO_POSTCONDITIONS <define>BOOST_CONTRACT_NO_CHECKS ; } + +rule defs_yxek { return <define>BOOST_CONTRACT_NO_ENTRY_INVARIANTS <define>BOOST_CONTRACT_NO_EXIT_INVARIANTS <define>BOOST_CONTRACT_NO_EXCEPTS <define>BOOST_CONTRACT_NO_CHECKS ; } + +rule defs_ysek { return <define>BOOST_CONTRACT_NO_ENTRY_INVARIANTS <define>BOOST_CONTRACT_NO_POSTCONDITIONS <define>BOOST_CONTRACT_NO_EXCEPTS <define>BOOST_CONTRACT_NO_CHECKS ; } + +rule defs_rxse { return <define>BOOST_CONTRACT_NO_PRECONDITIONS <define>BOOST_CONTRACT_NO_EXIT_INVARIANTS <define>BOOST_CONTRACT_NO_POSTCONDITIONS <define>BOOST_CONTRACT_NO_EXCEPTS ; } + +rule defs_rxsk { return <define>BOOST_CONTRACT_NO_PRECONDITIONS <define>BOOST_CONTRACT_NO_EXIT_INVARIANTS <define>BOOST_CONTRACT_NO_POSTCONDITIONS <define>BOOST_CONTRACT_NO_CHECKS ; } + +rule defs_rxek { return <define>BOOST_CONTRACT_NO_PRECONDITIONS <define>BOOST_CONTRACT_NO_EXIT_INVARIANTS <define>BOOST_CONTRACT_NO_EXCEPTS <define>BOOST_CONTRACT_NO_CHECKS ; } + +rule defs_rsek { return <define>BOOST_CONTRACT_NO_PRECONDITIONS <define>BOOST_CONTRACT_NO_POSTCONDITIONS <define>BOOST_CONTRACT_NO_EXCEPTS <define>BOOST_CONTRACT_NO_CHECKS ; } + +rule defs_xsek { return <define>BOOST_CONTRACT_NO_EXIT_INVARIANTS <define>BOOST_CONTRACT_NO_POSTCONDITIONS <define>BOOST_CONTRACT_NO_EXCEPTS <define>BOOST_CONTRACT_NO_CHECKS ; } + +rule defs_yrxse { return <define>BOOST_CONTRACT_NO_ENTRY_INVARIANTS <define>BOOST_CONTRACT_NO_PRECONDITIONS <define>BOOST_CONTRACT_NO_EXIT_INVARIANTS <define>BOOST_CONTRACT_NO_POSTCONDITIONS <define>BOOST_CONTRACT_NO_EXCEPTS ; } + +rule defs_yrxsk { return <define>BOOST_CONTRACT_NO_ENTRY_INVARIANTS <define>BOOST_CONTRACT_NO_PRECONDITIONS <define>BOOST_CONTRACT_NO_EXIT_INVARIANTS <define>BOOST_CONTRACT_NO_POSTCONDITIONS <define>BOOST_CONTRACT_NO_CHECKS ; } + +rule defs_yrxek { return <define>BOOST_CONTRACT_NO_ENTRY_INVARIANTS <define>BOOST_CONTRACT_NO_PRECONDITIONS <define>BOOST_CONTRACT_NO_EXIT_INVARIANTS <define>BOOST_CONTRACT_NO_EXCEPTS <define>BOOST_CONTRACT_NO_CHECKS ; } + +rule defs_yrsek { return <define>BOOST_CONTRACT_NO_ENTRY_INVARIANTS <define>BOOST_CONTRACT_NO_PRECONDITIONS <define>BOOST_CONTRACT_NO_POSTCONDITIONS <define>BOOST_CONTRACT_NO_EXCEPTS <define>BOOST_CONTRACT_NO_CHECKS ; } + +rule defs_yxsek { return <define>BOOST_CONTRACT_NO_ENTRY_INVARIANTS <define>BOOST_CONTRACT_NO_EXIT_INVARIANTS <define>BOOST_CONTRACT_NO_POSTCONDITIONS <define>BOOST_CONTRACT_NO_EXCEPTS <define>BOOST_CONTRACT_NO_CHECKS ; } + +rule defs_rxsek { return <define>BOOST_CONTRACT_NO_PRECONDITIONS <define>BOOST_CONTRACT_NO_EXIT_INVARIANTS <define>BOOST_CONTRACT_NO_POSTCONDITIONS <define>BOOST_CONTRACT_NO_EXCEPTS <define>BOOST_CONTRACT_NO_CHECKS ; } + +rule defs_yrxsek { return <define>BOOST_CONTRACT_NO_ENTRY_INVARIANTS <define>BOOST_CONTRACT_NO_PRECONDITIONS <define>BOOST_CONTRACT_NO_EXIT_INVARIANTS <define>BOOST_CONTRACT_NO_POSTCONDITIONS <define>BOOST_CONTRACT_NO_EXCEPTS <define>BOOST_CONTRACT_NO_CHECKS ; } + +rule combinations { return y r x s e k yr yx ys ye yk rx rs re rk xs xe xk se sk ek yrx yrs yre yrk yxs yxe yxk yse ysk yek rxs rxe rxk rse rsk rek xse xsk xek sek yrxs yrxe yrxk yrse yrsk yrek yxse yxsk yxek ysek rxse rxsk rxek rsek xsek yrxse yrxsk yrxek yrsek yxsek rxsek yrxsek ; } + +} # module + +# All combinations: y,r,x,s,e,k,yr,yx,ys,ye,yk,rx,rs,re,rk,xs,xe,xk,se,sk,ek,yrx,yrs,yre,yrk,yxs,yxe,yxk,yse,ysk,yek,rxs,rxe,rxk,rse,rsk,rek,xse,xsk,xek,sek,yrxs,yrxe,yrxk,yrse,yrsk,yrek,yxse,yxsk,yxek,ysek,rxse,rxsk,rxek,rsek,xsek,yrxse,yrxsk,yrxek,yrsek,yxsek,rxsek,yrxsek + diff --git a/src/boost/libs/contract/build/boost_contract_no.jam-gen.py b/src/boost/libs/contract/build/boost_contract_no.jam-gen.py new file mode 100644 index 000000000..2c574273a --- /dev/null +++ b/src/boost/libs/contract/build/boost_contract_no.jam-gen.py @@ -0,0 +1,47 @@ + +print ''' +# Generated file `python boost_contract_no.jam-gen.py > boost_contract_no.jam`. + +# Copyright (C) 2008-2018 Lorenzo Caminiti +# Distributed under the Boost Software License, Version 1.0 (see accompanying +# file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt). +# See: https://lcaminiti.github.io/boost-contract +''' + +import collections +import itertools + +defs = collections.OrderedDict([ + # Short keys (1-2 chars) as MSVC gives linker errors on long file names. + ('y', 'BOOST_CONTRACT_NO_ENTRY_INVARIANTS'), + ('r', 'BOOST_CONTRACT_NO_PRECONDITIONS'), + ('x', 'BOOST_CONTRACT_NO_EXIT_INVARIANTS'), + ('s', 'BOOST_CONTRACT_NO_POSTCONDITIONS'), + ('e', 'BOOST_CONTRACT_NO_EXCEPTS'), + ('k', 'BOOST_CONTRACT_NO_CHECKS') + # Add more macros here. +]) +separator = '' # Might want to set to '_' if keys longer than 1 char. + +print 'module boost_contract_no {\n' +s = '' +exit +for r in range(len(defs.keys())): + for comb in itertools.combinations(defs.keys(), r + 1): + c = '' + d = '' + sep = '' + for cond in comb: + c += sep + cond + sep = separator + d += " <define>" + defs[cond] + s += ' ' + c + print 'rule defs_{0} {{ return {1} ; }}\n'.format(c, d[1:]) + +print '''rule combinations {{ return {0} ; }} + +}} # module + +# All combinations: {1} +'''.format(s[1:], s.replace(" ", ",")[1:]) + diff --git a/src/boost/libs/contract/example/Jamfile.v2 b/src/boost/libs/contract/example/Jamfile.v2 new file mode 100644 index 000000000..3fe6e2fa0 --- /dev/null +++ b/src/boost/libs/contract/example/Jamfile.v2 @@ -0,0 +1,91 @@ + +# Copyright (C) 2008-2018 Lorenzo Caminiti +# Distributed under the Boost Software License, Version 1.0 (see accompanying +# file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt). +# See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html + +import ../build/boost_contract_build ; +import ../../config/checks/config : requires ; + +test-suite features : + [ boost_contract_build.subdir-run features : introduction_comments ] + [ boost_contract_build.subdir-run-cxx11 features : introduction ] + [ boost_contract_build.subdir-run-cxx11 features : introduction_public ] + + [ boost_contract_build.subdir-run-cxx11 features : non_member ] + [ boost_contract_build.subdir-run-cxx11 features : lambda ] + [ boost_contract_build.subdir-run-cxx11 features : loop ] + [ boost_contract_build.subdir-run-cxx11 features : code_block ] + [ boost_contract_build.subdir-run-cxx11 features : public ] + [ boost_contract_build.subdir-run-cxx11 features : base_types ] + [ boost_contract_build.subdir-run-cxx11 features : static_public ] + [ boost_contract_build.subdir-run-cxx11 features : private_protected ] + [ boost_contract_build.subdir-run-cxx11 features : + private_protected_virtual ] + [ boost_contract_build.subdir-run-cxx11 features : + private_protected_virtual_multi ] + [ boost_contract_build.subdir-run-cxx11 features : check ] + + [ boost_contract_build.subdir-run-cxx11 features : friend ] + [ boost_contract_build.subdir-run-cxx11 features : friend_invariant ] + [ boost_contract_build.subdir-run-cxx11 features : old ] + [ boost_contract_build.subdir-run-cxx11 features : optional_result ] + [ boost_contract_build.subdir-run-cxx11 features : optional_result_virtual ] + [ boost_contract_build.subdir-run-cxx11 features : pure_virtual_public ] + [ boost_contract_build.subdir-run-cxx11 features : overload ] + [ boost_contract_build.subdir-run-cxx11 features : named_override ] + [ boost_contract_build.subdir-run-cxx11 features : move ] + [ boost_contract_build.subdir-run-cxx11 features : union ] + [ boost_contract_build.subdir-run features : volatile ] + + [ boost_contract_build.subdir-run-cxx11 features : old_if_copyable ] + [ boost_contract_build.subdir-run-cxx11 features : if_constexpr : + [ requires cxx17_if_constexpr ] ] + [ boost_contract_build.subdir-run-cxx11 features : condition_if ] + [ boost_contract_build.subdir-run-cxx11 features : call_if_cxx14 : + [ requires cxx14_generic_lambdas ] ] + [ boost_contract_build.subdir-run-cxx11 features : access ] + [ boost_contract_build.subdir-run-cxx11 features : separate_body ] + [ boost_contract_build.subdir-run-cxx11 features : throw_on_failure ] + [ boost_contract_build.subdir-run-cxx11 features : ifdef ] + [ boost_contract_build.subdir-run-cxx11 features : assertion_level ] + [ boost_contract_build.subdir-run-cxx11 features : ifdef_macro ] + [ boost_contract_build.subdir-run-cxx11 features : base_types_no_macro ] + [ boost_contract_build.subdir-run-cxx11 features : old_no_macro ] + # Still needs C++11 for OLDOF variadic macros. + [ boost_contract_build.subdir-run-cxx11 features : no_lambdas ] + [ boost_contract_build.subdir-run-cxx11 features : no_lambdas_local_func ] +; + +test-suite n1962 : + [ boost_contract_build.subdir-run-cxx11 n1962 : vector ] + [ boost_contract_build.subdir-run-cxx11 n1962 : sqrt ] + [ boost_contract_build.subdir-run-cxx11 n1962 : circle ] + [ boost_contract_build.subdir-run-cxx11 n1962 : equal ] + [ boost_contract_build.subdir-run-cxx11 n1962 : factorial ] + [ boost_contract_build.subdir-run-cxx11 n1962 : sum ] +; + +test-suite meyer97 : + [ boost_contract_build.subdir-run-cxx11 meyer97 : stack4_main ] + [ boost_contract_build.subdir-run-cxx11 meyer97 : stack3 ] +; + +test-suite mitchell02 : + [ boost_contract_build.subdir-run-cxx11 mitchell02 : stack ] + [ boost_contract_build.subdir-run-cxx11 mitchell02 : simple_queue ] + [ boost_contract_build.subdir-run-cxx11 mitchell02 : dictionary ] + [ boost_contract_build.subdir-run-cxx11 mitchell02 : customer_manager ] + [ boost_contract_build.subdir-run-cxx11 mitchell02 : name_list ] + [ boost_contract_build.subdir-run-cxx11 mitchell02 : courier ] + [ boost_contract_build.subdir-run-cxx11 mitchell02 : observer_main ] + [ boost_contract_build.subdir-run-cxx11 mitchell02 : counter_main ] +; + +test-suite cline90 : + [ boost_contract_build.subdir-run-cxx11 cline90 : stack ] + [ boost_contract_build.subdir-run-cxx11 cline90 : vector_main ] + [ boost_contract_build.subdir-run-cxx11 cline90 : vstack ] + [ boost_contract_build.subdir-run-cxx11 cline90 : calendar ] +; + diff --git a/src/boost/libs/contract/example/cline90/calendar.cpp b/src/boost/libs/contract/example/cline90/calendar.cpp new file mode 100644 index 000000000..1dc76ca1e --- /dev/null +++ b/src/boost/libs/contract/example/cline90/calendar.cpp @@ -0,0 +1,93 @@ + +// Copyright (C) 2008-2018 Lorenzo Caminiti +// Distributed under the Boost Software License, Version 1.0 (see accompanying +// file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt). +// See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html + +//[cline90_calendar +#include <boost/contract.hpp> +#include <cassert> + +class calendar { + friend class boost::contract::access; + + void invariant() const { + BOOST_CONTRACT_ASSERT(month() >= 1); + BOOST_CONTRACT_ASSERT(month() <= 12); + BOOST_CONTRACT_ASSERT(date() >= 1); + BOOST_CONTRACT_ASSERT(date() <= days_in(month())); + } + +public: + calendar() : month_(1), date_(31) { + boost::contract::check c = boost::contract::constructor(this) + .postcondition([&] { + BOOST_CONTRACT_ASSERT(month() == 1); + BOOST_CONTRACT_ASSERT(date() == 31); + }) + ; + } + + virtual ~calendar() { + // Check invariants. + boost::contract::check c = boost::contract::destructor(this); + } + + int month() const { + // Check invariants. + boost::contract::check c = boost::contract::public_function(this); + return month_; + } + + int date() const { + // Check invariants. + boost::contract::check c = boost::contract::public_function(this); + return date_; + } + + void reset(int new_month) { + boost::contract::check c = boost::contract::public_function(this) + .precondition([&] { + BOOST_CONTRACT_ASSERT(new_month >= 1); + BOOST_CONTRACT_ASSERT(new_month <= 12); + }) + .postcondition([&] { + BOOST_CONTRACT_ASSERT(month() == new_month); + }) + ; + + month_ = new_month; + } + +private: + static int days_in(int month) { + int result; + boost::contract::check c = boost::contract::function() + .precondition([&] { + BOOST_CONTRACT_ASSERT(month >= 1); + BOOST_CONTRACT_ASSERT(month <= 12); + }) + .postcondition([&] { + BOOST_CONTRACT_ASSERT(result >= 1); + BOOST_CONTRACT_ASSERT(result <= 31); + }) + ; + + return result = 31; // For simplicity, assume all months have 31 days. + } + + int month_, date_; +}; + +int main() { + calendar cal; + assert(cal.date() == 31); + assert(cal.month() == 1); + + cal.reset(8); // Set month + assert(cal.month() == 8); + + return 0; +} +//] + diff --git a/src/boost/libs/contract/example/cline90/stack.cpp b/src/boost/libs/contract/example/cline90/stack.cpp new file mode 100644 index 000000000..b02c844fe --- /dev/null +++ b/src/boost/libs/contract/example/cline90/stack.cpp @@ -0,0 +1,93 @@ + +// Copyright (C) 2008-2018 Lorenzo Caminiti +// Distributed under the Boost Software License, Version 1.0 (see accompanying +// file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt). +// See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html + +//[cline90_stack +#include <boost/contract.hpp> +#include <cassert> + +// NOTE: Incomplete contract assertions, addressing only `empty` and `full`. +template<typename T> +class stack + #define BASES private boost::contract::constructor_precondition<stack<T> > + : BASES +{ + friend class boost::contract::access; + + typedef BOOST_CONTRACT_BASE_TYPES(BASES) base_types; + #undef BASES + +public: + explicit stack(int capacity) : + boost::contract::constructor_precondition<stack>([&] { + BOOST_CONTRACT_ASSERT(capacity >= 0); + }), + data_(new T[capacity]), capacity_(capacity), size_(0) + { + boost::contract::check c = boost::contract::constructor(this) + .postcondition([&] { + BOOST_CONTRACT_ASSERT(empty()); + BOOST_CONTRACT_ASSERT(full() == (capacity == 0)); + }) + ; + + for(int i = 0; i < capacity_; ++i) data_[i] = T(); + } + + virtual ~stack() { + boost::contract::check c = boost::contract::destructor(this); + delete[] data_; + } + + bool empty() const { + boost::contract::check c = boost::contract::public_function(this); + return size_ == 0; + } + + bool full() const { + boost::contract::check c = boost::contract::public_function(this); + return size_ == capacity_; + } + + void push(T const& value) { + boost::contract::check c = boost::contract::public_function(this) + .precondition([&] { + BOOST_CONTRACT_ASSERT(!full()); + }) + .postcondition([&] { + BOOST_CONTRACT_ASSERT(!empty()); + }) + ; + + data_[size_++] = value; + } + + T pop() { + boost::contract::check c = boost::contract::public_function(this) + .precondition([&] { + BOOST_CONTRACT_ASSERT(!empty()); + }) + .postcondition([&] { + BOOST_CONTRACT_ASSERT(!full()); + }) + ; + + return data_[--size_]; + } + +private: + T* data_; + int capacity_; + int size_; +}; + +int main() { + stack<int> s(3); + s.push(123); + assert(s.pop() == 123); + return 0; +} +//] + diff --git a/src/boost/libs/contract/example/cline90/vector.hpp b/src/boost/libs/contract/example/cline90/vector.hpp new file mode 100644 index 000000000..6e7126217 --- /dev/null +++ b/src/boost/libs/contract/example/cline90/vector.hpp @@ -0,0 +1,101 @@ + +// Copyright (C) 2008-2018 Lorenzo Caminiti +// Distributed under the Boost Software License, Version 1.0 (see accompanying +// file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt). +// See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html + +//[cline90_vector +#ifndef VECTOR_HPP_ +#define VECTOR_HPP_ + +#include <boost/contract.hpp> + +// NOTE: Incomplete contract assertions, addressing only `size`. +template<typename T> +class vector + #define BASES private boost::contract::constructor_precondition<vector<T> > + : BASES +{ + friend class boost::contract::access; + + typedef BOOST_CONTRACT_BASE_TYPES(BASES) base_types; + #undef BASES + + void invariant() const { + BOOST_CONTRACT_ASSERT(size() >= 0); + } + +public: + explicit vector(int count = 10) : + boost::contract::constructor_precondition<vector>([&] { + BOOST_CONTRACT_ASSERT(count >= 0); + }), + data_(new T[count]), + size_(count) + { + boost::contract::check c = boost::contract::constructor(this) + .postcondition([&] { + BOOST_CONTRACT_ASSERT(size() == count); + }) + ; + + for(int i = 0; i < size_; ++i) data_[i] = T(); + } + + virtual ~vector() { + boost::contract::check c = boost::contract::destructor(this); + delete[] data_; + } + + int size() const { + boost::contract::check c = boost::contract::public_function(this); + return size_; // Non-negative result already checked by invariant. + } + + void resize(int count) { + boost::contract::check c = boost::contract::public_function(this) + .precondition([&] { + BOOST_CONTRACT_ASSERT(count >= 0); + }) + .postcondition([&] { + BOOST_CONTRACT_ASSERT(size() == count); + }) + ; + + T* slice = new T[count]; + for(int i = 0; i < count && i < size_; ++i) slice[i] = data_[i]; + delete[] data_; + data_ = slice; + size_ = count; + } + + T& operator[](int index) { + boost::contract::check c = boost::contract::public_function(this) + .precondition([&] { + BOOST_CONTRACT_ASSERT(index >= 0); + BOOST_CONTRACT_ASSERT(index < size()); + }) + ; + + return data_[index]; + } + + T const& operator[](int index) const { + boost::contract::check c = boost::contract::public_function(this) + .precondition([&] { + BOOST_CONTRACT_ASSERT(index >= 0); + BOOST_CONTRACT_ASSERT(index < size()); + }) + ; + + return data_[index]; + } + +private: + T* data_; + int size_; +}; + +#endif // #include guard +//] + diff --git a/src/boost/libs/contract/example/cline90/vector_axx.hpp b/src/boost/libs/contract/example/cline90/vector_axx.hpp new file mode 100644 index 000000000..4a3582e61 --- /dev/null +++ b/src/boost/libs/contract/example/cline90/vector_axx.hpp @@ -0,0 +1,101 @@ + +// Copyright (C) 2008-2018 Lorenzo Caminiti +// Distributed under the Boost Software License, Version 1.0 (see accompanying +// file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt). +// See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html + +//[cline90_vector_axx +// Extra spaces, newlines, etc. for visual alignment with this library code. + + + + + +template<typename T> +class vector { + + + + + + + + +legal: // Class invariants (legal). + size() >= 0; + + +public: + explicit vector(int count = 10) : + data_(new T[count]), + size_(count) + { + for(int i = 0; i < size_; ++i) data_[i] = T(); + } + + + + + + + + + + + virtual ~vector() { delete[] data_; } + + + + + int size() const { return size_; } + + + + + void resize(int count) { + T* slice = new T[count]; + for(int i = 0; i < count && i < size_; ++i) slice[i] = data_[i]; + delete[] data_; + data_ = slice; + size_ = count; + } + + + + + + + + + + + T& operator[](int index) { return data_[index]; } + + + + + + + + + + + T& operator[](int index) const { return data_[index]; } + + + + +axioms: // Preconditions (require) and postconditions (promise) for each func. + [int count; require count >= 0; promise size() == count] vector(count); + [int count; require count >= 0; promise size() == count] resize(count); + [int index; require index >= 0 && index < size()] (*this)[x]; // Op[]. + [int index; require index >= 0 && index < size()] (*this)[x] const; // Op[]. + +private: + T* data_; + int size_; +}; + +// End. +//] + diff --git a/src/boost/libs/contract/example/cline90/vector_main.cpp b/src/boost/libs/contract/example/cline90/vector_main.cpp new file mode 100644 index 000000000..28fa3e91a --- /dev/null +++ b/src/boost/libs/contract/example/cline90/vector_main.cpp @@ -0,0 +1,23 @@ + +// Copyright (C) 2008-2018 Lorenzo Caminiti +// Distributed under the Boost Software License, Version 1.0 (see accompanying +// file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt). +// See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html + +//[cline90_vector_main +#include "vector.hpp" +#include <cassert> + +int main() { + vector<int> v (3); + assert(v.size() == 3); + + v[0] = 123; + v.resize(2); + assert(v[0] == 123); + assert(v.size() == 2); + + return 0; +} +//] + diff --git a/src/boost/libs/contract/example/cline90/vstack.cpp b/src/boost/libs/contract/example/cline90/vstack.cpp new file mode 100644 index 000000000..b210d40aa --- /dev/null +++ b/src/boost/libs/contract/example/cline90/vstack.cpp @@ -0,0 +1,239 @@ + +// Copyright (C) 2008-2018 Lorenzo Caminiti +// Distributed under the Boost Software License, Version 1.0 (see accompanying +// file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt). +// See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html + +//[cline90_vstack +#include "vector.hpp" +#include <boost/contract.hpp> +#include <boost/optional.hpp> +#include <cassert> + +// NOTE: Incomplete contract assertions, addressing only `empty` and `full`. +template<typename T> +class abstract_stack { +public: + abstract_stack() { + boost::contract::check c = boost::contract::constructor(this) + .postcondition([&] { + // AXIOM as empty() cannot actually be checked here to avoid + // calling pure virtual function length() during construction). + BOOST_CONTRACT_ASSERT_AXIOM(empty()); + }) + ; + } + + virtual ~abstract_stack() { + boost::contract::check c = boost::contract::destructor(this); + } + + bool full() const { + bool result; + boost::contract::check c = boost::contract::public_function(this) + .postcondition([&] { + BOOST_CONTRACT_ASSERT(result == (length() == capacity())); + }) + ; + + return result = (length() == capacity()); + } + + bool empty() const { + bool result; + boost::contract::check c = boost::contract::public_function(this) + .postcondition([&] { + BOOST_CONTRACT_ASSERT(result = (length() == 0)); + }) + ; + + return result = (length() == 0); + } + + virtual int length(boost::contract::virtual_* v = 0) const = 0; + virtual int capacity(boost::contract::virtual_* v = 0) const = 0; + + virtual T const& item(boost::contract::virtual_* v = 0) const = 0; + + virtual void push(T const& value, boost::contract::virtual_* v = 0) = 0; + virtual T const& pop(boost::contract::virtual_* v = 0) = 0; + + virtual void clear(boost::contract::virtual_* v = 0) = 0; +}; + +template<typename T> +int abstract_stack<T>::length(boost::contract::virtual_* v) const { + int result; + boost::contract::check c = boost::contract::public_function(v, result, this) + .postcondition([&] (int const& result) { + BOOST_CONTRACT_ASSERT(result >= 0); + }) + ; + assert(false); + return result; +} + +template<typename T> +int abstract_stack<T>::capacity(boost::contract::virtual_* v) const { + int result; + boost::contract::check c = boost::contract::public_function(v, result, this) + .postcondition([&] (int const& result) { + BOOST_CONTRACT_ASSERT(result >= 0); + }) + ; + assert(false); + return result; +} + +template<typename T> +T const& abstract_stack<T>::item(boost::contract::virtual_* v) const { + boost::optional<T const&> result; + boost::contract::check c = boost::contract::public_function(v, result, this) + .precondition([&] { + BOOST_CONTRACT_ASSERT(!empty()); + }) + ; + assert(false); + return *result; +} + +template<typename T> +void abstract_stack<T>::push(T const& value, boost::contract::virtual_* v) { + boost::contract::check c = boost::contract::public_function(v, this) + .precondition([&] { + BOOST_CONTRACT_ASSERT(!full()); + }) + .postcondition([&] { + BOOST_CONTRACT_ASSERT(!empty()); + }) + ; + assert(false); +} + +template<typename T> +T const& abstract_stack<T>::pop(boost::contract::virtual_* v) { + boost::optional<T const&> result; + boost::contract::old_ptr<T> old_item = BOOST_CONTRACT_OLDOF(v, item()); + boost::contract::check c = boost::contract::public_function(v, result, this) + .precondition([&] { + BOOST_CONTRACT_ASSERT(!empty()); + }) + .postcondition([&] (boost::optional<T const&> const& result) { + BOOST_CONTRACT_ASSERT(!full()); + BOOST_CONTRACT_ASSERT(*result == *old_item); + }) + ; + assert(false); + return *result; +} + +template<typename T> +void abstract_stack<T>::clear(boost::contract::virtual_* v) { + boost::contract::check c = boost::contract::public_function(v, this) + .postcondition([&] { + BOOST_CONTRACT_ASSERT(empty()); + }) + ; + assert(false); +} + +template<typename T> +class vstack + #define BASES private boost::contract::constructor_precondition< \ + vstack<T> >, public abstract_stack<T> + : BASES +{ + friend class boost::contract::access; + + typedef BOOST_CONTRACT_BASE_TYPES(BASES) base_types; + #undef BASES + + void invariant() const { + BOOST_CONTRACT_ASSERT(length() >= 0); + BOOST_CONTRACT_ASSERT(length() < capacity()); + } + + BOOST_CONTRACT_OVERRIDES(length, capacity, item, push, pop, clear) + +public: + explicit vstack(int count = 10) : + boost::contract::constructor_precondition<vstack>([&] { + BOOST_CONTRACT_ASSERT(count >= 0); + }), + vect_(count), // OK, executed after precondition so count >= 0. + len_(0) + { + boost::contract::check c = boost::contract::constructor(this) + .postcondition([&] { + BOOST_CONTRACT_ASSERT(length() == 0); + BOOST_CONTRACT_ASSERT(capacity() == count); + }) + ; + } + + virtual ~vstack() { + boost::contract::check c = boost::contract::destructor(this); + } + + // Inherited from abstract_stack. + + virtual int length(boost::contract::virtual_* v = 0) const /* override */ { + int result; + boost::contract::check c = boost::contract::public_function< + override_length>(v, result, &vstack::length, this); + return result = len_; + } + + virtual int capacity(boost::contract::virtual_* v = 0) + const /* override */ { + int result; + boost::contract::check c = boost::contract::public_function< + override_capacity>(v, result, &vstack::capacity, this); + return result = vect_.size(); + } + + virtual T const& item(boost::contract::virtual_* v = 0) + const /* override */ { + boost::optional<T const&> result; + boost::contract::check c = boost::contract::public_function< + override_item>(v, result, &vstack::item, this); + return *(result = vect_[len_ - 1]); + } + + virtual void push(T const& value, boost::contract::virtual_* v = 0) + /* override */ { + boost::contract::check c = boost::contract::public_function< + override_push>(v, &vstack::push, this, value); + vect_[len_++] = value; + } + + virtual T const& pop(boost::contract::virtual_* v = 0) /* override */ { + boost::optional<T const&> result; + boost::contract::check c = boost::contract::public_function< + override_pop>(v, result, &vstack::pop, this); + return *(result = vect_[--len_]); + } + + virtual void clear(boost::contract::virtual_* v = 0) /* override */ { + boost::contract::check c = boost::contract::public_function< + override_clear>(v, &vstack::clear, this); + len_ = 0; + } + +private: + vector<T> vect_; + int len_; +}; + +int main() { + vstack<int> s(3); + assert(s.capacity() == 3); + + s.push(123); + assert(s.length() == 1); + assert(s.pop() == 123); + + return 0; +} +//] + diff --git a/src/boost/libs/contract/example/features/access.cpp b/src/boost/libs/contract/example/features/access.cpp new file mode 100644 index 000000000..075861728 --- /dev/null +++ b/src/boost/libs/contract/example/features/access.cpp @@ -0,0 +1,95 @@ + +// Copyright (C) 2008-2018 Lorenzo Caminiti +// Distributed under the Boost Software License, Version 1.0 (see accompanying +// file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt). +// See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html + +#include <boost/contract.hpp> +#include <vector> +#include <cassert> + +template<typename T> +class pushable { + friend class boost::contract::access; + + void invariant() const { + BOOST_CONTRACT_ASSERT(capacity() <= max_size()); + } + +public: + virtual void push_back(T const& value, boost::contract::virtual_* v = 0) + = 0; + +protected: + virtual unsigned capacity() const = 0; + virtual unsigned max_size() const = 0; +}; + +template<typename T> +void pushable<T>::push_back(T const& value, boost::contract::virtual_* v) { + boost::contract::old_ptr<unsigned> old_capacity = + BOOST_CONTRACT_OLDOF(v, capacity()); + boost::contract::check c = boost::contract::public_function(v, this) + .precondition([&] { + BOOST_CONTRACT_ASSERT(capacity() < max_size()); + }) + .postcondition([&] { + BOOST_CONTRACT_ASSERT(capacity() >= *old_capacity); + }) + ; + assert(false); +} + +//[access +template<typename T> +class vector + #define BASES public pushable<T> + : BASES +{ // Private section of the class. + friend class boost::contract::access; // Friend `access` class so... + + typedef BOOST_CONTRACT_BASE_TYPES(BASES) base_types; // ...private bases. + #undef BASES + + void invariant() const { // ...private invariants. + BOOST_CONTRACT_ASSERT(size() <= capacity()); + } + + BOOST_CONTRACT_OVERRIDE(push_back) // ...private overrides. + +public: // Public section of the class. + void push_back(T const& value, boost::contract::virtual_* v = 0) + /* override */ { + boost::contract::old_ptr<unsigned> old_size = + BOOST_CONTRACT_OLDOF(v, size()); + boost::contract::check c = boost::contract::public_function< + override_push_back>(v, &vector::push_back, this, value) + .precondition([&] { + BOOST_CONTRACT_ASSERT(size() < max_size()); + }) + .postcondition([&] { + BOOST_CONTRACT_ASSERT(size() == *old_size + 1); + }) + ; + + vect_.push_back(value); + } + + /* ... */ +//] + + unsigned size() const { return vect_.size(); } + unsigned max_size() const { return vect_.max_size(); } + unsigned capacity() const { return vect_.capacity(); } + +private: // Another private section. + std::vector<T> vect_; +}; + +int main() { + vector<int> vect; + vect.push_back(123); + assert(vect.size() == 1); + return 0; +} + diff --git a/src/boost/libs/contract/example/features/assertion_level.cpp b/src/boost/libs/contract/example/features/assertion_level.cpp new file mode 100644 index 000000000..c347b19c7 --- /dev/null +++ b/src/boost/libs/contract/example/features/assertion_level.cpp @@ -0,0 +1,135 @@ + +// Copyright (C) 2008-2018 Lorenzo Caminiti +// Distributed under the Boost Software License, Version 1.0 (see accompanying +// file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt). +// See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html + +#include <boost/contract.hpp> +#include <vector> +#include <algorithm> +#include <iostream> +#include <cassert> + +//[assertion_level_no_impl +// If valid iterator range (cannot implement in C++ but OK to use in AXIOM). +template<typename Iter> +bool valid(Iter first, Iter last); // Only declared, not actually defined. +//] + +//[assertion_level_class_begin +template<typename T> +class vector { +//] + +public: + typedef typename std::vector<T>::iterator iterator; + + // Could program class invariants and contracts for the following. + iterator begin() { return vect_.begin(); } + iterator end() { return vect_.end(); } + unsigned capacity() const { return vect_.capacity(); } + bool operator==(vector const& other) { return vect_ == other.vect_; } + +//[assertion_level_axiom +public: + iterator insert(iterator where, T const& value) { + iterator result; + boost::contract::old_ptr<unsigned> old_capacity = + BOOST_CONTRACT_OLDOF(capacity()); + boost::contract::check c = boost::contract::public_function(this) + .postcondition([&] { + BOOST_CONTRACT_ASSERT(capacity() >= *old_capacity); + if(capacity() > *old_capacity) { + BOOST_CONTRACT_ASSERT_AXIOM(!valid(begin(), end())); + } else { + BOOST_CONTRACT_ASSERT_AXIOM(!valid(where, end())); + } + }) + ; + + return result = vect_.insert(where, value); + } +//] + +//[assertion_level_audit_old +public: + void swap(vector& other) { + boost::contract::old_ptr<vector> old_me, old_other; + #ifdef BOOST_CONTRACT_AUDITS + old_me = BOOST_CONTRACT_OLDOF(*this); + old_other = BOOST_CONTRACT_OLDOF(other); + #endif // Else, skip old value copies... + boost::contract::check c = boost::contract::public_function(this) + .postcondition([&] { + // ...and also skip related assertions. + BOOST_CONTRACT_ASSERT_AUDIT(*this == *old_other); + BOOST_CONTRACT_ASSERT_AUDIT(other == *old_me); + }) + ; + + vect_.swap(other.vect_); + } +//] + +//[assertion_level_class_end + /* ... */ + +private: + std::vector<T> vect_; +}; +//] + +//[assertion_level_audit +template<typename RandomIter, typename T> +RandomIter random_binary_search(RandomIter first, RandomIter last, + T const& value) { + RandomIter result; + boost::contract::check c = boost::contract::function() + .precondition([&] { + BOOST_CONTRACT_ASSERT(first <= last); // Default, not expensive. + // Expensive O(n) assertion (use AXIOM if prohibitive instead). + BOOST_CONTRACT_ASSERT_AUDIT(std::is_sorted(first, last)); + }) + .postcondition([&] { + if(result != last) BOOST_CONTRACT_ASSERT(*result == value); + }) + ; + + /* ... */ +//] + + RandomIter begin = first, end = last; + while(begin < end) { + RandomIter middle = begin + ((end - begin) >> 1); + BOOST_CONTRACT_CHECK(*begin <= *middle || value < *middle || + *middle < value); + + if(value < *middle) end = middle; + else if(value > *middle) begin = middle + 1; + else return result = middle; + } + return result = last; +} + +int main() { + vector<char> v; + v.insert(v.begin() + 0, 'a'); + v.insert(v.begin() + 1, 'b'); + v.insert(v.begin() + 2, 'c'); + + vector<char>::iterator i = random_binary_search(v.begin(), v.end(), 'b'); + assert(i != v.end()); + assert(*i == 'b'); + + vector<char> w; + w.insert(w.begin() + 0, 'x'); + w.insert(w.begin() + 1, 'y'); + + w.swap(v); + assert(*(w.begin() + 0) == 'a'); + assert(*(w.begin() + 1) == 'b'); + assert(*(w.begin() + 2) == 'c'); + + return 0; +} + diff --git a/src/boost/libs/contract/example/features/base_types.cpp b/src/boost/libs/contract/example/features/base_types.cpp new file mode 100644 index 000000000..56efcbfe0 --- /dev/null +++ b/src/boost/libs/contract/example/features/base_types.cpp @@ -0,0 +1,188 @@ + +// Copyright (C) 2008-2018 Lorenzo Caminiti +// Distributed under the Boost Software License, Version 1.0 (see accompanying +// file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt). +// See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html + +#include <boost/contract.hpp> +#include <vector> +#include <algorithm> +#include <cassert> + +template<typename T> +class pushable { +public: + void invariant() const { + BOOST_CONTRACT_ASSERT(capacity() <= max_size()); + } + + virtual void push_back(T x, boost::contract::virtual_* v = 0) = 0; + +protected: + virtual unsigned capacity() const = 0; + virtual unsigned max_size() const = 0; +}; + +template<typename T> +void pushable<T>::push_back(T x, boost::contract::virtual_* v) { + boost::contract::old_ptr<unsigned> old_capacity = + BOOST_CONTRACT_OLDOF(v, capacity()); + boost::contract::check c = boost::contract::public_function(v, this) + .precondition([&] { + BOOST_CONTRACT_ASSERT(capacity() < max_size()); + }) + .postcondition([&] { + BOOST_CONTRACT_ASSERT(capacity() >= *old_capacity); + }) + ; + assert(false); // Shall never execute this body. +} + +struct has_size { virtual unsigned size() const = 0; }; +struct has_empty { virtual bool empty() const = 0; }; + +class unique_chars + : private boost::contract::constructor_precondition<unique_chars> +{ +public: + void invariant() const { + BOOST_CONTRACT_ASSERT(size() >= 0); + } + + unique_chars(char from, char to) : + boost::contract::constructor_precondition<unique_chars>([&] { + BOOST_CONTRACT_ASSERT(from <= to); + }) + { + boost::contract::check c = boost::contract::constructor(this) + .postcondition([&] { + BOOST_CONTRACT_ASSERT(int(size()) == (to - from + 1)); + }) + ; + + for(char x = from; x <= to; ++x) vect_.push_back(x); + } + + virtual ~unique_chars() { + boost::contract::check c = boost::contract::destructor(this); + } + + unsigned size() const { + boost::contract::check c = boost::contract::public_function(this); + return vect_.size(); + } + + bool find(char x) const { + bool result; + boost::contract::check c = boost::contract::public_function(this) + .postcondition([&] { + if(size() == 0) BOOST_CONTRACT_ASSERT(!result); + }) + ; + + return result = std::find(vect_.begin(), vect_.end(), x) != vect_.end(); + } + + virtual void push_back(char x, boost::contract::virtual_* v = 0) { + boost::contract::old_ptr<bool> old_find = + BOOST_CONTRACT_OLDOF(v, find(x)); + boost::contract::old_ptr<unsigned> old_size = + BOOST_CONTRACT_OLDOF(v, size()); + boost::contract::check c = boost::contract::public_function(v, this) + .precondition([&] { + BOOST_CONTRACT_ASSERT(!find(x)); + }) + .postcondition([&] { + if(!*old_find) { + BOOST_CONTRACT_ASSERT(find(x)); + BOOST_CONTRACT_ASSERT(size() == *old_size + 1); + } + }) + ; + + vect_.push_back(x); + } + +protected: + unique_chars() {} + + std::vector<char> const& vect() const { return vect_; } + +private: + std::vector<char> vect_; +}; + +//[base_types +class chars + #define BASES /* local macro (for convenience) */ \ + private boost::contract::constructor_precondition<chars>, \ + public unique_chars, \ + public virtual pushable<char>, \ + virtual protected has_size, \ + private has_empty + : BASES // Bases of this class. +{ +public: + typedef BOOST_CONTRACT_BASE_TYPES(BASES) base_types; // Bases typedef. + #undef BASES // Undefine local macro. + + /* ... */ +//] + + void invariant() const { + BOOST_CONTRACT_ASSERT(empty() == (size() == 0)); + } + + chars(char from, char to) : unique_chars(from, to) { + boost::contract::check c = boost::contract::constructor(this); + } + + chars(char const* const c_str) : + boost::contract::constructor_precondition<chars>([&] { + BOOST_CONTRACT_ASSERT(c_str[0] != '\0'); + }) + { + boost::contract::check c = boost::contract::constructor(this); + + for(unsigned i = 0; c_str[i] != '\0'; ++i) push_back(c_str[i]); + } + + void push_back(char x, boost::contract::virtual_* v = 0) /* override */ { + boost::contract::old_ptr<bool> old_find = + BOOST_CONTRACT_OLDOF(v, find(x)); + boost::contract::old_ptr<unsigned> old_size = + BOOST_CONTRACT_OLDOF(v, size()); + boost::contract::check c = boost::contract::public_function< + override_push_back>(v, &chars::push_back, this, x) + .precondition([&] { + BOOST_CONTRACT_ASSERT(find(x)); + }) + .postcondition([&] { + if(*old_find) BOOST_CONTRACT_ASSERT(size() == *old_size); + }) + ; + + if(!find(x)) unique_chars::push_back(x); + } + BOOST_CONTRACT_OVERRIDE(push_back); + + bool empty() const { + boost::contract::check c = boost::contract::public_function(this); + return size() == 0; + } + + unsigned size() const { return unique_chars::size(); } + +protected: + unsigned max_size() const { return vect().max_size(); } + unsigned capacity() const { return vect().capacity(); } +}; + +int main() { + chars s("abc"); + assert(s.find('a')); + assert(s.find('b')); + assert(!s.find('x')); + return 0; +} + diff --git a/src/boost/libs/contract/example/features/base_types_no_macro.cpp b/src/boost/libs/contract/example/features/base_types_no_macro.cpp new file mode 100644 index 000000000..f9add687c --- /dev/null +++ b/src/boost/libs/contract/example/features/base_types_no_macro.cpp @@ -0,0 +1,188 @@ + +// Copyright (C) 2008-2018 Lorenzo Caminiti +// Distributed under the Boost Software License, Version 1.0 (see accompanying +// file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt). +// See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html + +#include <boost/contract.hpp> +#include <vector> +#include <algorithm> +#include <cassert> + +template<typename T> +class pushable { +public: + void invariant() const { + BOOST_CONTRACT_ASSERT(capacity() <= max_size()); + } + + virtual void push_back(T x, boost::contract::virtual_* v = 0) = 0; + +protected: + virtual unsigned capacity() const = 0; + virtual unsigned max_size() const = 0; +}; + +template<typename T> +void pushable<T>::push_back(T x, boost::contract::virtual_* v) { + boost::contract::old_ptr<unsigned> old_capacity = + BOOST_CONTRACT_OLDOF(v, capacity()); + boost::contract::check c = boost::contract::public_function(v, this) + .precondition([&] { + BOOST_CONTRACT_ASSERT(capacity() < max_size()); + }) + .postcondition([&] { + BOOST_CONTRACT_ASSERT(capacity() >= *old_capacity); + }) + ; + assert(false); // Shall never execute this body. +} + +struct has_size { virtual unsigned size() const = 0; }; +struct has_empty { virtual bool empty() const = 0; }; + +class unique_chars + : private boost::contract::constructor_precondition<unique_chars> +{ +public: + void invariant() const { + BOOST_CONTRACT_ASSERT(size() >= 0); + } + + unique_chars(char from, char to) : + boost::contract::constructor_precondition<unique_chars>([&] { + BOOST_CONTRACT_ASSERT(from <= to); + }) + { + boost::contract::check c = boost::contract::constructor(this) + .postcondition([&] { + BOOST_CONTRACT_ASSERT(int(size()) == (to - from + 1)); + }) + ; + + for(char x = from; x <= to; ++x) vect_.push_back(x); + } + + virtual ~unique_chars() { + boost::contract::check c = boost::contract::destructor(this); + } + + unsigned size() const { + boost::contract::check c = boost::contract::public_function(this); + return vect_.size(); + } + + bool find(char x) const { + bool result; + boost::contract::check c = boost::contract::public_function(this) + .postcondition([&] { + if(size() == 0) BOOST_CONTRACT_ASSERT(!result); + }) + ; + + return result = std::find(vect_.begin(), vect_.end(), x) != vect_.end(); + } + + virtual void push_back(char x, boost::contract::virtual_* v = 0) { + boost::contract::old_ptr<bool> old_find = + BOOST_CONTRACT_OLDOF(v, find(x)); + boost::contract::old_ptr<unsigned> old_size = + BOOST_CONTRACT_OLDOF(v, size()); + boost::contract::check c = boost::contract::public_function(v, this) + .precondition([&] { + BOOST_CONTRACT_ASSERT(!find(x)); + }) + .postcondition([&] { + if(!*old_find) { + BOOST_CONTRACT_ASSERT(find(x)); + BOOST_CONTRACT_ASSERT(size() == *old_size + 1); + } + }) + ; + + vect_.push_back(x); + } + +protected: + unique_chars() {} + + std::vector<char> const& vect() const { return vect_; } + +private: + std::vector<char> vect_; +}; + +//[base_types_no_macro +#include <boost/mpl/vector.hpp> + +class chars : + private boost::contract::constructor_precondition<chars>, + public unique_chars, + public virtual pushable<char>, + virtual protected has_size, + private has_empty +{ +public: + // Program `base_types` without macros (list only public bases). + typedef boost::mpl::vector<unique_chars, pushable<char> > base_types; + + /* ... */ +//] + + void invariant() const { + BOOST_CONTRACT_ASSERT(empty() == (size() == 0)); + } + + chars(char from, char to) : unique_chars(from, to) { + boost::contract::check c = boost::contract::constructor(this); + } + + chars(char const* const c_str) : + boost::contract::constructor_precondition<chars>([&] { + BOOST_CONTRACT_ASSERT(c_str[0] != '\0'); + }) + { + boost::contract::check c = boost::contract::constructor(this); + + for(unsigned i = 0; c_str[i] != '\0'; ++i) push_back(c_str[i]); + } + + void push_back(char x, boost::contract::virtual_* v = 0) /* override */ { + boost::contract::old_ptr<bool> old_find = + BOOST_CONTRACT_OLDOF(v, find(x)); + boost::contract::old_ptr<unsigned> old_size = + BOOST_CONTRACT_OLDOF(v, size()); + boost::contract::check c = boost::contract::public_function< + override_push_back>(v, &chars::push_back, this, x) + .precondition([&] { + BOOST_CONTRACT_ASSERT(find(x)); + }) + .postcondition([&] { + if(*old_find) BOOST_CONTRACT_ASSERT(size() == *old_size); + }) + ; + + if(!find(x)) unique_chars::push_back(x); + } + BOOST_CONTRACT_OVERRIDE(push_back); + + bool empty() const { + boost::contract::check c = boost::contract::public_function(this); + return size() == 0; + } + + unsigned size() const { return unique_chars::size(); } + +protected: + unsigned max_size() const { return vect().max_size(); } + unsigned capacity() const { return vect().capacity(); } +}; + +int main() { + chars s("abc"); + assert(s.find('a')); + assert(s.find('b')); + assert(!s.find('x')); + return 0; +} + diff --git a/src/boost/libs/contract/example/features/call_if_cxx14.cpp b/src/boost/libs/contract/example/features/call_if_cxx14.cpp new file mode 100644 index 000000000..bdf4f424a --- /dev/null +++ b/src/boost/libs/contract/example/features/call_if_cxx14.cpp @@ -0,0 +1,92 @@ + +// Copyright (C) 2008-2018 Lorenzo Caminiti +// Distributed under the Boost Software License, Version 1.0 (see accompanying +// file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt). +// See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html + +#include <boost/contract/call_if.hpp> +#include <type_traits> +#include <iterator> +#include <functional> // std::bind for generic lambdas. +#include <vector> +#include <list> +#include <sstream> + +template<typename Iter> +struct is_random_access_iterator : std::is_same< + typename std::iterator_traits<Iter>::iterator_category, + std::random_access_iterator_tag +> {}; + +template<typename Iter> +struct is_bidirectional_iterator : std::is_same< + typename std::iterator_traits<Iter>::iterator_category, + std::bidirectional_iterator_tag +> {}; + +template<typename Iter> +struct is_input_iterator : std::is_same< + typename std::iterator_traits<Iter>::iterator_category, + std::input_iterator_tag +> {}; + +//[call_if_cxx14 +template<typename Iter, typename Dist> +void myadvance(Iter& i, Dist n) { + Iter* p = &i; // So captures change actual pointed iterator value. + boost::contract::call_if<is_random_access_iterator<Iter> >( + std::bind([] (auto p, auto n) { // C++14 generic lambda. + *p += n; + }, p, n) + ).template else_if<is_bidirectional_iterator<Iter> >( + std::bind([] (auto p, auto n) { + if(n >= 0) while(n--) ++*p; + else while(n++) --*p; + }, p, n) + ).template else_if<is_input_iterator<Iter> >( + std::bind([] (auto p, auto n) { + while(n--) ++*p; + }, p, n) + ).else_( + std::bind([] (auto false_) { + static_assert(false_, "requires at least input iterator"); + }, std::false_type()) // Use constexpr value. + ); +} +//] + +struct x {}; // Test not an iterator (static_assert failure in else_ above). + +namespace std { + template<> + struct iterator_traits<x> { + typedef void iterator_category; + }; +} + +int main() { + std::vector<char> v; + v.push_back('a'); + v.push_back('b'); + v.push_back('c'); + v.push_back('d'); + std::vector<char>::iterator r = v.begin(); // Random iterator. + myadvance(r, 1); + assert(*r == 'b'); + + std::list<char> l(v.begin(), v.end()); + std::list<char>::iterator b = l.begin(); // Bidirectional iterator. + myadvance(b, 2); + assert(*b == 'c'); + + std::istringstream s("a b c d"); + std::istream_iterator<char> i(s); + myadvance(i, 3); + assert(*i == 'd'); + + // x j; + // myadvance(j, 0); // Error (correctly because x not even input iter). + + return 0; +} + diff --git a/src/boost/libs/contract/example/features/check.cpp b/src/boost/libs/contract/example/features/check.cpp new file mode 100644 index 000000000..36aa9da3a --- /dev/null +++ b/src/boost/libs/contract/example/features/check.cpp @@ -0,0 +1,41 @@ + +// Copyright (C) 2008-2018 Lorenzo Caminiti +// Distributed under the Boost Software License, Version 1.0 (see accompanying +// file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt). +// See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html + +#include <boost/contract.hpp> + +int gcd(int const a, int const b) { + int result; + boost::contract::check c = boost::contract::function() + .precondition([&] { + BOOST_CONTRACT_ASSERT(a > 0); + BOOST_CONTRACT_ASSERT(b > 0); + }) + .postcondition([&] { + BOOST_CONTRACT_ASSERT(result <= a); + BOOST_CONTRACT_ASSERT(result <= b); + }) + ; + + int x = a, y = b; + while(x != y) { + if(x > y) x = x - y; + else y = y - x; + } + return result = x; +} + +//[check +int main() { + // Implementation checks (via nullary functor). + boost::contract::check c = [] { + BOOST_CONTRACT_ASSERT(gcd(12, 28) == 4); + BOOST_CONTRACT_ASSERT(gcd(4, 14) == 2); + }; + + return 0; +} +//] + diff --git a/src/boost/libs/contract/example/features/check_macro.cpp b/src/boost/libs/contract/example/features/check_macro.cpp new file mode 100644 index 000000000..80d9c66c0 --- /dev/null +++ b/src/boost/libs/contract/example/features/check_macro.cpp @@ -0,0 +1,39 @@ + +// Copyright (C) 2008-2018 Lorenzo Caminiti +// Distributed under the Boost Software License, Version 1.0 (see accompanying +// file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt). +// See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html + +#include <boost/contract.hpp> + +int gcd(int const a, int const b) { + int result; + boost::contract::check c = boost::contract::function() + .precondition([&] { + BOOST_CONTRACT_ASSERT(a > 0); + BOOST_CONTRACT_ASSERT(b > 0); + }) + .postcondition([&] { + BOOST_CONTRACT_ASSERT(result <= a); + BOOST_CONTRACT_ASSERT(result <= b); + }) + ; + + int x = a, y = b; + while(x != y) { + if(x > y) x = x - y; + else y = y - x; + } + return result = x; +} + +//[check_macro +int main() { + // Implementation checks (via macro, disable run-/compile-time overhead). + BOOST_CONTRACT_CHECK(gcd(12, 28) == 4); + BOOST_CONTRACT_CHECK(gcd(4, 14) == 2); + + return 0; +} +//] + diff --git a/src/boost/libs/contract/example/features/code_block.cpp b/src/boost/libs/contract/example/features/code_block.cpp new file mode 100644 index 000000000..2ec434aa2 --- /dev/null +++ b/src/boost/libs/contract/example/features/code_block.cpp @@ -0,0 +1,43 @@ + +// Copyright (C) 2008-2018 Lorenzo Caminiti +// Distributed under the Boost Software License, Version 1.0 (see accompanying +// file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt). +// See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html + +#include <boost/contract.hpp> +#include <vector> +#include <algorithm> +#include <limits> + +int main() { + std::vector<int> v; + v.push_back(1); + v.push_back(2); + v.push_back(3); + int total = 10; + + //[code_block + /* ... */ + + // Contract for a code block. + { // Code block entry (check preconditions). + boost::contract::old_ptr<int> old_total = BOOST_CONTRACT_OLDOF(total); + boost::contract::check c = boost::contract::function() + .precondition([&] { + BOOST_CONTRACT_ASSERT(v.size() == 3); + }) + .postcondition([&] { + BOOST_CONTRACT_ASSERT(total == *old_total + v[0] + v[1] + v[2]); + }) + ; + + total += v[0] + v[1] + v[2]; // Code block body. + } // Code block exit (check postconditions and exceptions guarantees). + + /* ... */ + //] + + assert(total == 16); + return 0; +} + diff --git a/src/boost/libs/contract/example/features/condition_if.cpp b/src/boost/libs/contract/example/features/condition_if.cpp new file mode 100644 index 000000000..c8ecb964e --- /dev/null +++ b/src/boost/libs/contract/example/features/condition_if.cpp @@ -0,0 +1,58 @@ + +// Copyright (C) 2008-2018 Lorenzo Caminiti +// Distributed under the Boost Software License, Version 1.0 (see accompanying +// file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt). +// See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html + +#include <boost/contract.hpp> +#include <boost/type_traits/has_equal_to.hpp> +#include <boost/bind.hpp> +#include <vector> +#include <functional> +#include <cassert> + +//[condition_if +template<typename T> +class vector { +public: + void push_back(T const& value) { + boost::contract::check c = boost::contract::public_function(this) + .postcondition([&] { + // Instead of `ASSERT(back() == value)` for T without `==`. + BOOST_CONTRACT_ASSERT( + boost::contract::condition_if<boost::has_equal_to<T> >( + boost::bind(std::equal_to<T>(), + boost::cref(back()), + boost::cref(value) + ) + ) + ); + }) + ; + + vect_.push_back(value); + } + + /* ... */ +//] + + T const& back() const { return vect_.back(); } + +private: + std::vector<T> vect_; +}; + +int main() { + vector<int> v; + v.push_back(1); // Type `int` has `==` so check postcondition. + assert(v.back() == 1); + + struct i { int value; } j; + j.value = 10; + vector<i> w; + w.push_back(j); // Type `i` has no `==` so skip postcondition. + assert(j.value == 10); + + return 0; +} + diff --git a/src/boost/libs/contract/example/features/friend.cpp b/src/boost/libs/contract/example/features/friend.cpp new file mode 100644 index 000000000..215cfa6dd --- /dev/null +++ b/src/boost/libs/contract/example/features/friend.cpp @@ -0,0 +1,69 @@ + +// Copyright (C) 2008-2018 Lorenzo Caminiti +// Distributed under the Boost Software License, Version 1.0 (see accompanying +// file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt). +// See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html + +#include <boost/contract.hpp> +#include <string> +#include <cassert> + +//[friend_byte +class buffer; + +class byte { + friend bool operator==(buffer const& left, byte const& right); + +private: + char value_; + + /* ... */ +//] + +public: + // Could program invariants and contracts for following too. + explicit byte(char value) : value_(value) {} + bool empty() const { return value_ == '\0'; } +}; + +//[friend_buffer +class buffer { + // Friend functions are not member functions... + friend bool operator==(buffer const& left, byte const& right) { + // ...so check contracts via `function` (which won't check invariants). + boost::contract::check c = boost::contract::function() + .precondition([&] { + BOOST_CONTRACT_ASSERT(!left.empty()); + BOOST_CONTRACT_ASSERT(!right.empty()); + }) + ; + + for(char const* x = left.values_.c_str(); *x != '\0'; ++x) { + if(*x != right.value_) return false; + } + return true; + } + +private: + std::string values_; + + /* ... */ +//] + +public: + // Could program invariants and contracts for following too. + explicit buffer(std::string const& values) : values_(values) {} + bool empty() const { return values_ == ""; } +}; + +int main() { + buffer p("aaa"); + byte a('a'); + assert(p == a); + + buffer q("aba"); + assert(!(q == a)); // No operator!=. + + return 0; +} + diff --git a/src/boost/libs/contract/example/features/friend_invariant.cpp b/src/boost/libs/contract/example/features/friend_invariant.cpp new file mode 100644 index 000000000..b9f69bbea --- /dev/null +++ b/src/boost/libs/contract/example/features/friend_invariant.cpp @@ -0,0 +1,59 @@ + +// Copyright (C) 2008-2018 Lorenzo Caminiti +// Distributed under the Boost Software License, Version 1.0 (see accompanying +// file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt). +// See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html + +#include <boost/contract.hpp> +#include <cassert> + +//[friend_invariant +template<typename T> +class positive { +public: + void invariant() const { + BOOST_CONTRACT_ASSERT(value() > 0); + } + + // Can be considered an extension of enclosing class' public interface... + friend void swap(positive& object, T& value) { + boost::contract::old_ptr<T> old_object_value = + BOOST_CONTRACT_OLDOF(object.value()); + boost::contract::old_ptr<T> old_value = BOOST_CONTRACT_OLDOF(value); + // ...so it can be made to check invariants via `public_function`. + boost::contract::check c = boost::contract::public_function(&object) + .precondition([&] { + BOOST_CONTRACT_ASSERT(value > 0); + }) + .postcondition([&] { + BOOST_CONTRACT_ASSERT(object.value() == *old_value); + BOOST_CONTRACT_ASSERT(value == *old_object_value); + }) + ; + + T saved = object.value_; + object.value_ = value; + value = saved; + } + +private: + T value_; + + /* ... */ +//] + +public: + // Could program contracts for following too. + explicit positive(T const& value) : value_(value) {} + T value() const { return value_; } +}; + +int main() { + positive<int> i(123); + int x = 456; + swap(i, x); + assert(i.value() == 456); + assert(x == 123); + return 0; +} + diff --git a/src/boost/libs/contract/example/features/if_constexpr.cpp b/src/boost/libs/contract/example/features/if_constexpr.cpp new file mode 100644 index 000000000..f4561f149 --- /dev/null +++ b/src/boost/libs/contract/example/features/if_constexpr.cpp @@ -0,0 +1,113 @@ + +// Copyright (C) 2008-2019 Lorenzo Caminiti +// Distributed under the Boost Software License, Version 1.0 (see accompanying +// file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt). +// See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html + +#include <boost/contract.hpp> +#include <boost/type_traits/has_equal_to.hpp> +#include <utility> +#include <cassert> + +//[if_constexpr +template<typename T> +void swap(T& x, T& y) { + constexpr bool b = boost::contract::is_old_value_copyable<T>::value && + boost::has_equal_to<T>::value; + boost::contract::old_ptr<T> old_x, old_y; + if constexpr(b) { // Contract requires copyable T... + old_x = BOOST_CONTRACT_OLDOF(x); + old_y = BOOST_CONTRACT_OLDOF(y); + } + boost::contract::check c = boost::contract::function() + .postcondition([&] { + if constexpr(b) { // ... and T with `==`... + BOOST_CONTRACT_ASSERT(x == *old_y); + BOOST_CONTRACT_ASSERT(y == *old_x); + } + }) + ; + + T t = std::move(x); // ...but body only requires movable T. + x = std::move(y); + y = std::move(t); +} +//] + +struct i { // Non-copyable but has operator==. + explicit i(int n) : n_(n) {} + + i(i const&) = delete; // Non-copyable. + i& operator=(i const&) = delete; + + i(i const&& o) : n_(o.n_) {} + i& operator=(i const&& o) { n_ = o.n_; return *this; } + + friend bool operator==(i const& l, i const& r) { // Operator==. + return l.n_ == r.n_; + } + +private: + int n_; +}; + +struct j { // Copyable but no operator==. + explicit j(int n) : n_(n) {} + + j(j const& o) : n_(o.n_) {} // Copyable. + j& operator=(j const& o) { n_ = o.n_; return *this; } + + j(j const&& o) : n_(o.n_) {} + j& operator=(j const&& o) { n_ = o.n_; return *this; } + + // No operator==. + +private: + int n_; +}; + +struct k { // Non-copyable and no operator==. + explicit k(int n) : n_(n) {} + + k(k const&) = delete; // Non-copyable. + k& operator=(k const&) = delete; + + k(k const&& o) : n_(o.n_) {} + k& operator=(k const&& o) { n_ = o.n_; return *this; } + + // No operator==. + +private: + int n_; +}; + +int main() { + { // Copyable and operator== (so checks postconditions). + int x = 123, y = 456; + swap(x, y); + assert(x == 456); + assert(y == 123); + } + + { // Non-copyable (so does not check postconditions). + i x{123}, y{456}; + swap(x, y); + assert(x == i{456}); + assert(y == i{123}); + } + + { // No operator== (so does not check postconditions). + j x{123}, y{456}; + swap(x, y); + // Cannot assert x and y because no operator==. + } + + { // Non-copyable and no operator== (so does not check postconditions). + k x{123}, y{456}; + swap(x, y); + // Cannot assert x and y because no operator==. + } + + return 0; +} + diff --git a/src/boost/libs/contract/example/features/ifdef.cpp b/src/boost/libs/contract/example/features/ifdef.cpp new file mode 100644 index 000000000..74e74ee90 --- /dev/null +++ b/src/boost/libs/contract/example/features/ifdef.cpp @@ -0,0 +1,213 @@ + +// Copyright (C) 2008-2018 Lorenzo Caminiti +// Distributed under the Boost Software License, Version 1.0 (see accompanying +// file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt). +// See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html + +#include <vector> +#include <limits> +#include <cassert> + +//[ifdef_function +// Use #ifdef to completely disable contract code compilation. +#include <boost/contract/core/config.hpp> +#ifndef BOOST_CONTRACT_NO_ALL + #include <boost/contract.hpp> +#endif + +int inc(int& x) { + int result; + #ifndef BOOST_CONTRACT_NO_OLDS + boost::contract::old_ptr<int> old_x = BOOST_CONTRACT_OLDOF(x); + #endif + #ifndef BOOST_CONTRACT_NO_FUNCTIONS + boost::contract::check c = boost::contract::function() + #ifndef BOOST_CONTRACT_NO_PRECONDITIONS + .precondition([&] { + BOOST_CONTRACT_ASSERT(x < std::numeric_limits<int>::max()); + }) + #endif + #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS + .postcondition([&] { + BOOST_CONTRACT_ASSERT(x == *old_x + 1); + BOOST_CONTRACT_ASSERT(result == *old_x); + }) + #endif + ; + #endif + + return result = x++; +} +//] + +template<typename T> +class pushable { + #ifndef BOOST_CONTRACT_NO_ALL + friend class boost::contract::access; + #endif + + #ifndef BOOST_CONTRACT_NO_INVARIANTS + void invariant() const { + BOOST_CONTRACT_ASSERT(capacity() <= max_size()); + } + #endif + +public: + virtual void push_back( + T const& x + #ifndef BOOST_CONTRACT_NO_PUBLIC_FUNCTIONS + , boost::contract::virtual_* v = 0 + #endif + ) = 0; + +protected: + virtual unsigned capacity() const = 0; + virtual unsigned max_size() const = 0; +}; + +template<typename T> +void pushable<T>::push_back( + T const& x + #ifndef BOOST_CONTRACT_NO_PUBLIC_FUNCTIONS + , boost::contract::virtual_* v + #endif +) { + #ifndef BOOST_CONTRACT_NO_OLDS + boost::contract::old_ptr<unsigned> old_capacity = + BOOST_CONTRACT_OLDOF(v, capacity()); + #endif + #ifndef BOOST_CONTRACT_NO_PUBLIC_FUNCTIONS + boost::contract::check c = boost::contract::public_function(v, this) + #ifndef BOOST_CONTRACT_NO_PRECONDITIONS + .precondition([&] { + BOOST_CONTRACT_ASSERT(capacity() < max_size()); + }) + #endif + #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS + .postcondition([&] { + BOOST_CONTRACT_ASSERT(capacity() >= *old_capacity); + }) + #endif + ; + #endif + assert(false); // Shall never execute this body. +} + +//[ifdef_class +class integers + #define BASES public pushable<int> + : + #ifndef BOOST_CONTRACT_NO_PRECONDITIONS + private boost::contract::constructor_precondition<integers>, BASES + #else + BASES + #endif +{ + #ifndef BOOST_CONTRACT_NO_ALL + friend class boost::contract::access; + #endif + + #ifndef BOOST_CONTRACT_NO_PUBLIC_FUNCTIONS + typedef BOOST_CONTRACT_BASE_TYPES(BASES) base_types; + #endif + #undef BASES + + #ifndef BOOST_CONTRACT_NO_INVARIANTS + void invariant() const { + BOOST_CONTRACT_ASSERT(size() <= capacity()); + } + #endif + +public: + integers(int from, int to) : + #ifndef BOOST_CONTRACT_NO_PRECONDITIONS + boost::contract::constructor_precondition<integers>([&] { + BOOST_CONTRACT_ASSERT(from <= to); + }), + #endif + vect_(to - from + 1) + { + #ifndef BOOST_CONTRACT_NO_CONSTRUCTORS + boost::contract::check c = boost::contract::constructor(this) + #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS + .postcondition([&] { + BOOST_CONTRACT_ASSERT(int(size()) == (to - from + 1)); + }) + #endif + ; + #endif + + for(int x = from; x <= to; ++x) vect_.at(x - from) = x; + } + + virtual ~integers() { + #ifndef BOOST_CONTRACT_NO_DESTRUCTORS + // Check invariants. + boost::contract::check c = boost::contract::destructor(this); + #endif + } + + virtual void push_back( + int const& x + #ifndef BOOST_CONTRACT_NO_PUBLIC_FUNCTIONS + , boost::contract::virtual_* v = 0 + #endif + ) /* override */ { + #ifndef BOOST_CONTRACT_NO_OLDS + boost::contract::old_ptr<unsigned> old_size; + #endif + #ifndef BOOST_CONTRACT_NO_PUBLIC_FUNCTIONS + boost::contract::check c = boost::contract::public_function< + override_push_back>(v, &integers::push_back, this, x) + #ifndef BOOST_CONTRACT_NO_PRECONDITIONS + .precondition([&] { + BOOST_CONTRACT_ASSERT(size() < max_size()); + }) + #endif + #ifndef BOOST_CONTRACT_NO_OLDS + .old([&] { + old_size = BOOST_CONTRACT_OLDOF(v, size()); + }) + #endif + #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS + .postcondition([&] { + BOOST_CONTRACT_ASSERT(size() == *old_size + 1); + }) + #endif + #ifndef BOOST_CONTRACT_NO_EXCEPTS + .except([&] { + BOOST_CONTRACT_ASSERT(size() == *old_size); + }) + #endif + ; + #endif + + vect_.push_back(x); + } + +private: + #ifndef BOOST_CONTRACT_NO_PUBLIC_FUNCTIONS + BOOST_CONTRACT_OVERRIDE(push_back) + #endif + + /* ... */ +//] + +public: // Could program contracts for these too... + unsigned size() const { return vect_.size(); } + unsigned max_size() const { return vect_.max_size(); } + unsigned capacity() const { return vect_.capacity(); } + +private: + std::vector<int> vect_; +}; + +int main() { + integers i(1, 10); + int x = 123; + i.push_back(inc(x)); + assert(x == 124); + assert(i.size() == 11); + return 0; +} + diff --git a/src/boost/libs/contract/example/features/ifdef_macro.cpp b/src/boost/libs/contract/example/features/ifdef_macro.cpp new file mode 100644 index 000000000..cc979bfd7 --- /dev/null +++ b/src/boost/libs/contract/example/features/ifdef_macro.cpp @@ -0,0 +1,150 @@ + +// Copyright (C) 2008-2018 Lorenzo Caminiti +// Distributed under the Boost Software License, Version 1.0 (see accompanying +// file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt). +// See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html + +#include <vector> +#include <limits> +#include <cassert> + +//[ifdef_macro_function +// Use macro interface to completely disable contract code compilation. +#include <boost/contract_macro.hpp> + +int inc(int& x) { + int result; + BOOST_CONTRACT_OLD_PTR(int)(old_x, x); + BOOST_CONTRACT_FUNCTION() + BOOST_CONTRACT_PRECONDITION([&] { + BOOST_CONTRACT_ASSERT(x < std::numeric_limits<int>::max()); + }) + BOOST_CONTRACT_POSTCONDITION([&] { + BOOST_CONTRACT_ASSERT(x == *old_x + 1); + BOOST_CONTRACT_ASSERT(result == *old_x); + }) + ; + + return result = x++; +} +//] + +template<typename T> +class pushable { + friend class boost::contract::access; // Left in code (almost no overhead). + + BOOST_CONTRACT_INVARIANT({ + BOOST_CONTRACT_ASSERT(capacity() <= max_size()); + }) + +public: + virtual void push_back( + T const& x, + boost::contract::virtual_* v = 0 // Left in code (almost no overhead). + ) = 0; + +protected: + virtual unsigned capacity() const = 0; + virtual unsigned max_size() const = 0; +}; + +template<typename T> +void pushable<T>::push_back(T const& x, boost::contract::virtual_* v) { + BOOST_CONTRACT_OLD_PTR(unsigned)(v, old_capacity, capacity()); + BOOST_CONTRACT_PUBLIC_FUNCTION(v, this) + BOOST_CONTRACT_PRECONDITION([&] { + BOOST_CONTRACT_ASSERT(capacity() < max_size()); + }) + BOOST_CONTRACT_POSTCONDITION([&] { + BOOST_CONTRACT_ASSERT(capacity() >= *old_capacity); + }) + ; + assert(false); // Shall never execute this body. +} + +//[ifdef_macro_class +class integers + #define BASES public pushable<int> + : + // Left in code (almost no overhead). + private boost::contract::constructor_precondition<integers>, + BASES +{ + // Followings left in code (almost no overhead). + friend class boost::contract::access; + + typedef BOOST_CONTRACT_BASE_TYPES(BASES) base_types; + #undef BASES + + BOOST_CONTRACT_INVARIANT({ + BOOST_CONTRACT_ASSERT(size() <= capacity()); + }) + +public: + integers(int from, int to) : + BOOST_CONTRACT_CONSTRUCTOR_PRECONDITION(integers)([&] { + BOOST_CONTRACT_ASSERT(from <= to); + }), + vect_(to - from + 1) + { + BOOST_CONTRACT_CONSTRUCTOR(this) + BOOST_CONTRACT_POSTCONDITION([&] { + BOOST_CONTRACT_ASSERT(int(size()) == (to - from + 1)); + }) + ; + + for(int x = from; x <= to; ++x) vect_.at(x - from) = x; + } + + virtual ~integers() { + BOOST_CONTRACT_DESTRUCTOR(this); // Check invariants. + } + + virtual void push_back( + int const& x, + boost::contract::virtual_* v = 0 // Left in code (almost no overhead). + ) /* override */ { + BOOST_CONTRACT_OLD_PTR(unsigned)(old_size); + BOOST_CONTRACT_PUBLIC_FUNCTION_OVERRIDE(override_push_back)( + v, &integers::push_back, this, x) + BOOST_CONTRACT_PRECONDITION([&] { + BOOST_CONTRACT_ASSERT(size() < max_size()); + }) + BOOST_CONTRACT_OLD([&] { + old_size = BOOST_CONTRACT_OLDOF(v, size()); + }) + BOOST_CONTRACT_POSTCONDITION([&] { + BOOST_CONTRACT_ASSERT(size() == *old_size + 1); + }) + BOOST_CONTRACT_EXCEPT([&] { + BOOST_CONTRACT_ASSERT(size() == *old_size); + }) + ; + + vect_.push_back(x); + } + +private: + BOOST_CONTRACT_OVERRIDE(push_back) // Left in code (almost no overhead). + + /* ... */ +//] + +public: // Could program contracts for these too... + unsigned size() const { return vect_.size(); } + unsigned max_size() const { return vect_.max_size(); } + unsigned capacity() const { return vect_.capacity(); } + +private: + std::vector<int> vect_; +}; + +int main() { + integers i(1, 10); + int x = 123; + i.push_back(inc(x)); + assert(x == 124); + assert(i.size() == 11); + return 0; +} + diff --git a/src/boost/libs/contract/example/features/introduction.cpp b/src/boost/libs/contract/example/features/introduction.cpp new file mode 100644 index 000000000..25baf10fe --- /dev/null +++ b/src/boost/libs/contract/example/features/introduction.cpp @@ -0,0 +1,34 @@ + +// Copyright (C) 2008-2018 Lorenzo Caminiti +// Distributed under the Boost Software License, Version 1.0 (see accompanying +// file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt). +// See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html + +#include <limits> +#include <cassert> + +//[introduction +#include <boost/contract.hpp> + +void inc(int& x) { + boost::contract::old_ptr<int> old_x = BOOST_CONTRACT_OLDOF(x); // Old value. + boost::contract::check c = boost::contract::function() + .precondition([&] { + BOOST_CONTRACT_ASSERT(x < std::numeric_limits<int>::max()); // Line 17. + }) + .postcondition([&] { + BOOST_CONTRACT_ASSERT(x == *old_x + 1); // Line 20. + }) + ; + + ++x; // Function body. +} +//] + +int main() { + int x = 10; + inc(x); + assert(x == 11); + return 0; +} + diff --git a/src/boost/libs/contract/example/features/introduction_comments.cpp b/src/boost/libs/contract/example/features/introduction_comments.cpp new file mode 100644 index 000000000..3eba12f84 --- /dev/null +++ b/src/boost/libs/contract/example/features/introduction_comments.cpp @@ -0,0 +1,24 @@ + +// Copyright (C) 2008-2018 Lorenzo Caminiti +// Distributed under the Boost Software License, Version 1.0 (see accompanying +// file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt). +// See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html + +#include <cassert> + +//[introduction_comments +void inc(int& x) + // Precondition: x < std::numeric_limit<int>::max() + // Postcondition: x == oldof(x) + 1 +{ + ++x; // Function body. +} +//] + +int main() { + int x = 10; + inc(x); + assert(x == 11); + return 0; +} + diff --git a/src/boost/libs/contract/example/features/introduction_public.cpp b/src/boost/libs/contract/example/features/introduction_public.cpp new file mode 100644 index 000000000..2206bcab9 --- /dev/null +++ b/src/boost/libs/contract/example/features/introduction_public.cpp @@ -0,0 +1,89 @@ + +// Copyright (C) 2008-2018 Lorenzo Caminiti +// Distributed under the Boost Software License, Version 1.0 (see accompanying +// file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt). +// See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html + +#include <boost/contract.hpp> +#include <vector> +#include <cassert> + +template<typename T> +class pushable { // Somewhat arbitrary base (used just to show subcontracting). +public: + void invariant() const { + BOOST_CONTRACT_ASSERT(capacity() <= max_size()); + } + + virtual void push_back(T const& value, + boost::contract::virtual_* v = 0) = 0; // Pure virtual function. + +protected: + virtual unsigned capacity() const = 0; + virtual unsigned max_size() const = 0; +}; + +template<typename T> // Contract for pure virtual function. +void pushable<T>::push_back(T const& value, boost::contract::virtual_* v) { + boost::contract::old_ptr<unsigned> old_capacity = + BOOST_CONTRACT_OLDOF(v, capacity()); + boost::contract::check c = boost::contract::public_function(v, this) + .precondition([&] { + BOOST_CONTRACT_ASSERT(capacity() < max_size()); + }) + .postcondition([&] { + BOOST_CONTRACT_ASSERT(capacity() >= *old_capacity); + }) + ; + assert(false); // Shall never execute this body. +} + +//[introduction_public +template<typename T> +class vector + #define BASES public pushable<T> + : BASES +{ +public: + typedef BOOST_CONTRACT_BASE_TYPES(BASES) base_types; // For subcontracting. + #undef BASES + + void invariant() const { // Checked in AND with base class invariants. + BOOST_CONTRACT_ASSERT(size() <= capacity()); + } + + virtual void push_back(T const& value, + boost::contract::virtual_* v = 0) /* override */ { // For virtuals. + boost::contract::old_ptr<unsigned> old_size = + BOOST_CONTRACT_OLDOF(v, size()); // Old values for virtuals. + boost::contract::check c = boost::contract::public_function< // For overrides. + override_push_back>(v, &vector::push_back, this, value) + .precondition([&] { // Checked in OR with base preconditions. + BOOST_CONTRACT_ASSERT(size() < max_size()); + }) + .postcondition([&] { // Checked in AND with base postconditions. + BOOST_CONTRACT_ASSERT(size() == *old_size + 1); + }) + ; + + vect_.push_back(value); + } + BOOST_CONTRACT_OVERRIDE(push_back) // Define `override_push_back` above. + + // Could program contracts for those as well. + unsigned size() const { return vect_.size(); } + unsigned max_size() const { return vect_.max_size(); } + unsigned capacity() const { return vect_.capacity(); } + +private: + std::vector<T> vect_; +}; +//] + +int main() { + vector<int> vect; + vect.push_back(123); + assert(vect.size() == 1); + return 0; +} + diff --git a/src/boost/libs/contract/example/features/lambda.cpp b/src/boost/libs/contract/example/features/lambda.cpp new file mode 100644 index 000000000..6eb999801 --- /dev/null +++ b/src/boost/libs/contract/example/features/lambda.cpp @@ -0,0 +1,43 @@ + +// Copyright (C) 2008-2018 Lorenzo Caminiti +// Distributed under the Boost Software License, Version 1.0 (see accompanying +// file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt). +// See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html + +#include <boost/contract.hpp> +#include <vector> +#include <algorithm> +#include <limits> + +int main() { + std::vector<int> v; + v.push_back(1); + v.push_back(2); + v.push_back(3); + + //[lambda + int total = 0; + std::for_each(v.cbegin(), v.cend(), + // Contract for a lambda function. + [&total] (int const x) { + boost::contract::old_ptr<int> old_total = + BOOST_CONTRACT_OLDOF(total); + boost::contract::check c = boost::contract::function() + .precondition([&] { + BOOST_CONTRACT_ASSERT( + total < std::numeric_limits<int>::max() - x); + }) + .postcondition([&] { + BOOST_CONTRACT_ASSERT(total == *old_total + x); + }) + ; + + total += x; // Lambda function body. + } + ); + //] + + assert(total == 6); + return 0; +} + diff --git a/src/boost/libs/contract/example/features/loop.cpp b/src/boost/libs/contract/example/features/loop.cpp new file mode 100644 index 000000000..1d8acdd71 --- /dev/null +++ b/src/boost/libs/contract/example/features/loop.cpp @@ -0,0 +1,40 @@ + +// Copyright (C) 2008-2018 Lorenzo Caminiti +// Distributed under the Boost Software License, Version 1.0 (see accompanying +// file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt). +// See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html + +#include <boost/contract.hpp> +#include <vector> +#include <algorithm> +#include <limits> + +int main() { + std::vector<int> v; + v.push_back(1); + v.push_back(2); + v.push_back(3); + + //[loop + int total = 0; + // Contract for a for-loop (same for while- and all other loops). + for(std::vector<int>::const_iterator i = v.begin(); i != v.end(); ++i) { + boost::contract::old_ptr<int> old_total = BOOST_CONTRACT_OLDOF(total); + boost::contract::check c = boost::contract::function() + .precondition([&] { + BOOST_CONTRACT_ASSERT( + total < std::numeric_limits<int>::max() - *i); + }) + .postcondition([&] { + BOOST_CONTRACT_ASSERT(total == *old_total + *i); + }) + ; + + total += *i; // For-loop body. + } + //] + + assert(total == 6); + return 0; +} + diff --git a/src/boost/libs/contract/example/features/move.cpp b/src/boost/libs/contract/example/features/move.cpp new file mode 100644 index 000000000..de54d16a0 --- /dev/null +++ b/src/boost/libs/contract/example/features/move.cpp @@ -0,0 +1,201 @@ + +// Copyright (C) 2008-2018 Lorenzo Caminiti +// Distributed under the Boost Software License, Version 1.0 (see accompanying +// file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt). +// See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html + +#include <boost/contract.hpp> +#include <vector> +#include <utility> +#include <cassert> + +//[move +class circular_buffer : + private boost::contract::constructor_precondition<circular_buffer> { +public: + void invariant() const { + if(!moved()) { // Do not check (some) invariants for moved-from objects. + BOOST_CONTRACT_ASSERT(index() < size()); + } + // More invariants here that hold also for moved-from objects (e.g., + // all assertions necessary to successfully destroy moved-from objects). + } + + // Move constructor. + circular_buffer(circular_buffer&& other) : + boost::contract::constructor_precondition<circular_buffer>([&] { + BOOST_CONTRACT_ASSERT(!other.moved()); + }) + { + boost::contract::check c = boost::contract::constructor(this) + .postcondition([&] { + BOOST_CONTRACT_ASSERT(!moved()); + BOOST_CONTRACT_ASSERT(other.moved()); + }) + ; + + move(std::forward<circular_buffer>(other)); + } + + // Move assignment. + circular_buffer& operator=(circular_buffer&& other) { + // Moved-from can be (move) assigned (so no pre `!moved()` here). + boost::contract::check c = boost::contract::public_function(this) + .precondition([&] { + BOOST_CONTRACT_ASSERT(!other.moved()); + }) + .postcondition([&] { + BOOST_CONTRACT_ASSERT(!moved()); + BOOST_CONTRACT_ASSERT(other.moved()); + }) + ; + + return move(std::forward<circular_buffer>(other)); + } + + ~circular_buffer() { + // Moved-from can always be destroyed (in fact no preconditions). + boost::contract::check c = boost::contract::destructor(this); + } + + bool moved() const { + boost::contract::check c = boost::contract::public_function(this); + return moved_; + } + +private: + bool moved_; + + /* ... */ +//] + +public: + explicit circular_buffer(std::vector<char> const& data, + unsigned start = 0) : + boost::contract::constructor_precondition<circular_buffer>([&] { + BOOST_CONTRACT_ASSERT(start < data.size()); + }), + moved_(false), + data_(data), + index_(start) + { + boost::contract::check c = boost::contract::constructor(this) + .postcondition([&] { + BOOST_CONTRACT_ASSERT(!moved()); + }) + ; + } + + // Copy constructor. + circular_buffer(circular_buffer const& other) : + boost::contract::constructor_precondition<circular_buffer>([&] { + BOOST_CONTRACT_ASSERT(!other.moved()); + }) + { + boost::contract::check c = boost::contract::constructor(this) + .postcondition([&] { + BOOST_CONTRACT_ASSERT(!moved()); + }) + ; + + copy(other); + } + + // Copy assignment. + circular_buffer& operator=(circular_buffer const& other) { + // Moved-from can be (copy) assigned (so no pre `!moved()` here). + boost::contract::check c = boost::contract::public_function(this) + .precondition([&] { + BOOST_CONTRACT_ASSERT(!other.moved()); + }) + .postcondition([&] { + BOOST_CONTRACT_ASSERT(!moved()); + }) + ; + + return copy(other); + } + + char read() { + boost::contract::check c = boost::contract::public_function(this) + .precondition([&] { + BOOST_CONTRACT_ASSERT(!moved()); + }) + ; + + unsigned i = index_++; + if(index_ == data_.size()) index_ = 0; // Circular. + return data_.at(i); + } + +private: + circular_buffer& copy(circular_buffer const& other) { + data_ = other.data_; + index_ = other.index_; + moved_ = false; + return *this; + } + + circular_buffer& move(circular_buffer&& other) { + data_ = std::move(other.data_); + index_ = std::move(other.index_); + moved_ = false; + other.moved_ = true; // Mark moved-from object. + return *this; + } + + std::vector<char> data_; + unsigned index_; + +public: + unsigned index() const { + boost::contract::check c = boost::contract::public_function(this); + return index_; + } + + unsigned size() const { + boost::contract::check c = boost::contract::public_function(this); + return data_.size(); + } +}; + +int main() { + struct err {}; + boost::contract::set_precondition_failure( + [] (boost::contract::from) { throw err(); }); + + { + circular_buffer x({'a', 'b', 'c', 'd'}, 2); + assert(x.read() == 'c'); + + circular_buffer y1 = x; // Copy constructor. + assert(y1.read() == 'd'); + assert(x.read() == 'd'); + + circular_buffer y2({'h'}); + y2 = x; // Copy assignment. + assert(y2.read() == 'a'); + assert(x.read() == 'a'); + + circular_buffer z1 = std::move(x); // Move constructor. + assert(z1.read() == 'b'); + // Calling `x.read()` would fail `!moved()` precondition. + + x = y1; // Moved-from `x` can be copy assigned. + assert(x.read() == 'a'); + assert(y1.read() == 'a'); + + circular_buffer z2({'k'}); + z2 = std::move(x); // Move assignment. + assert(z2.read() == 'b'); + // Calling `x.read()` would fail `!moved()` precondition. + + x = std::move(y2); // Moved-from `x` can be move assigned. + assert(x.read() == 'b'); + // Calling `y2.read()` would fail `!moved()` precondition. + + } // Moved-from `y2` can be destroyed. + + return 0; +} + diff --git a/src/boost/libs/contract/example/features/named_override.cpp b/src/boost/libs/contract/example/features/named_override.cpp new file mode 100644 index 000000000..9afc5f60a --- /dev/null +++ b/src/boost/libs/contract/example/features/named_override.cpp @@ -0,0 +1,104 @@ + +// Copyright (C) 2008-2018 Lorenzo Caminiti +// Distributed under the Boost Software License, Version 1.0 (see accompanying +// file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt). +// See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html + +#include <boost/contract.hpp> +#include <boost/optional.hpp> +#include <cassert> + +//[named_override_pure_virtual_assert_false +template<typename T> +class generic_unary_pack { +public: + virtual void _1(T const& value, boost::contract::virtual_* v = 0) = 0; + virtual T _1(boost::contract::virtual_* v = 0) const = 0; +}; + +template<typename T> +void generic_unary_pack<T>::_1(T const& value, boost::contract::virtual_* v) { + boost::contract::check c = boost::contract::public_function(v, this) + .precondition([&] { + BOOST_CONTRACT_ASSERT(false); // Defer preconditions to overrides. + }) + ; + assert(false); +} + +/* ... */ +//] + +template<typename T> +T generic_unary_pack<T>::_1(boost::contract::virtual_* v) const { + boost::optional<T> result; // Do not assume T has default constructor. + boost::contract::check c = boost::contract::public_function(v, result, this) + .postcondition([&] (boost::optional<T const&> const& result) { + BOOST_CONTRACT_ASSERT(*result == _1()); + }) + ; + + assert(false); + return *result; +} + +//[named_override +template<typename T> +class positive_unary_pack + #define BASES public generic_unary_pack<T> + : BASES +{ +public: + typedef BOOST_CONTRACT_BASE_TYPES(BASES) base_types; + #undef BASES + + // BOOST_CONTRACT_OVERRIDE(_1) would generate reserved name `override__1`. + BOOST_CONTRACT_NAMED_OVERRIDE(override1, _1) // Generate `override1`. + + virtual void _1(T const& value, boost::contract::virtual_* v = 0) + /* override */ { + // Use `override1` generated by BOOST_CONTRACT_NAMED_OVERRIDE above. + boost::contract::check c = boost::contract::public_function<override1>( + v, + static_cast<void (positive_unary_pack::*)(T const&, + boost::contract::virtual_*)>(&positive_unary_pack::_1), + this, + value + ) + .precondition([&] { + BOOST_CONTRACT_ASSERT(value > 0); + }) + ; + value1_ = value; + } + + /* ... */ +//] + + virtual T _1(boost::contract::virtual_* v = 0) const /* override */ { + T result; // Class default constructor already used T's default ctor. + boost::contract::check c = boost::contract::public_function<override1>( + v, + result, + static_cast<T (positive_unary_pack::*)(boost::contract::virtual_*) + const>(&positive_unary_pack::_1), + this + ) + .postcondition([&] (T const& result) { + BOOST_CONTRACT_ASSERT(result > 0); + }) + ; + return result = value1_; + } + +private: + T value1_; +}; + +int main() { + positive_unary_pack<int> u; + u._1(123); + assert(u._1() == 123); + return 0; +} + diff --git a/src/boost/libs/contract/example/features/no_lambdas.cpp b/src/boost/libs/contract/example/features/no_lambdas.cpp new file mode 100644 index 000000000..783adce59 --- /dev/null +++ b/src/boost/libs/contract/example/features/no_lambdas.cpp @@ -0,0 +1,92 @@ + +// Copyright (C) 2008-2018 Lorenzo Caminiti +// Distributed under the Boost Software License, Version 1.0 (see accompanying +// file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt). +// See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html + +#include "no_lambdas.hpp" +#include <boost/bind.hpp> +#include <cassert> + +//[no_lambdas_cpp +iarray::iarray(unsigned max, unsigned count) : + boost::contract::constructor_precondition<iarray>(boost::bind( + &iarray::constructor_precondition, max, count)), + values_(new int[max]), // Member initializations can be here. + capacity_(max) +{ + boost::contract::old_ptr<int> old_instances; + boost::contract::check c = boost::contract::constructor(this) + .old(boost::bind(&iarray::constructor_old, boost::ref(old_instances))) + .postcondition(boost::bind( + &iarray::constructor_postcondition, + this, + boost::cref(max), + boost::cref(count), + boost::cref(old_instances) + )) + ; + + for(unsigned i = 0; i < count; ++i) values_[i] = int(); + size_ = count; + ++instances_; +} + +iarray::~iarray() { + boost::contract::old_ptr<int> old_instances; + boost::contract::check c = boost::contract::destructor(this) + .old(boost::bind(&iarray::destructor_old, this, + boost::ref(old_instances))) + .postcondition(boost::bind(&iarray::destructor_postcondition, + boost::cref(old_instances))) + ; + + delete[] values_; + --instances_; +} + +void iarray::push_back(int value, boost::contract::virtual_* v) { + boost::contract::old_ptr<unsigned> old_size; + boost::contract::check c = boost::contract::public_function(v, this) + .precondition(boost::bind(&iarray::push_back_precondition, this)) + .old(boost::bind(&iarray::push_back_old, this, boost::cref(v), + boost::ref(old_size))) + .postcondition(boost::bind(&iarray::push_back_postcondition, this, + boost::cref(old_size))) + ; + + values_[size_++] = value; +} + +unsigned iarray::capacity() const { + // Check invariants. + boost::contract::check c = boost::contract::public_function(this); + return capacity_; +} + +unsigned iarray::size() const { + // Check invariants. + boost::contract::check c = boost::contract::public_function(this); + return size_; +} + +int iarray::instances() { + // Check static invariants. + boost::contract::check c = boost::contract::public_function<iarray>(); + return instances_; +} + +int iarray::instances_ = 0; +//] + +int main() { + iarray a(3, 2); + assert(a.capacity() == 3); + assert(a.size() == 2); + + a.push_back(-123); + assert(a.size() == 3); + + return 0; +} + diff --git a/src/boost/libs/contract/example/features/no_lambdas.hpp b/src/boost/libs/contract/example/features/no_lambdas.hpp new file mode 100644 index 000000000..5f0dbe725 --- /dev/null +++ b/src/boost/libs/contract/example/features/no_lambdas.hpp @@ -0,0 +1,77 @@ + +#ifndef NO_LAMBDAS_HPP_ +#define NO_LAMBDAS_HPP_ + +// Copyright (C) 2008-2018 Lorenzo Caminiti +// Distributed under the Boost Software License, Version 1.0 (see accompanying +// file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt). +// See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html + +#include <boost/contract.hpp> + +//[no_lambdas_hpp +class iarray : + private boost::contract::constructor_precondition<iarray> { +public: + static void static_invariant() { + BOOST_CONTRACT_ASSERT(instances() >= 0); + } + + void invariant() const { + BOOST_CONTRACT_ASSERT(size() <= capacity()); + } + + explicit iarray(unsigned max, unsigned count = 0); + static void constructor_precondition(unsigned const max, + unsigned const count) { + BOOST_CONTRACT_ASSERT(count <= max); + } + static void constructor_old(boost::contract::old_ptr<int>& + old_instances) { + old_instances = BOOST_CONTRACT_OLDOF(instances()); + } + void constructor_postcondition(unsigned const max, unsigned const count, + boost::contract::old_ptr<int> const old_instances) const { + BOOST_CONTRACT_ASSERT(capacity() == max); + BOOST_CONTRACT_ASSERT(size() == count); + BOOST_CONTRACT_ASSERT(instances() == *old_instances + 1); + } + + virtual ~iarray(); + void destructor_old(boost::contract::old_ptr<int>& old_instances) + const { + old_instances = BOOST_CONTRACT_OLDOF(instances()); + } + static void destructor_postcondition(boost::contract::old_ptr<int> const + old_instances) { + BOOST_CONTRACT_ASSERT(instances() == *old_instances - 1); + } + + virtual void push_back(int value, boost::contract::virtual_* v = 0); + void push_back_precondition() const { + BOOST_CONTRACT_ASSERT(size() < capacity()); + } + void push_back_old(boost::contract::virtual_* v, + boost::contract::old_ptr<unsigned>& old_size) const { + old_size = BOOST_CONTRACT_OLDOF(v, size()); + } + void push_back_postcondition( + boost::contract::old_ptr<unsigned> const old_size) const { + BOOST_CONTRACT_ASSERT(size() == *old_size + 1); + } + + unsigned capacity() const; + unsigned size() const; + + static int instances(); + +private: + int* values_; + unsigned capacity_; + unsigned size_; + static int instances_; +}; +//] + +#endif // #include guard + diff --git a/src/boost/libs/contract/example/features/no_lambdas_local_func.cpp b/src/boost/libs/contract/example/features/no_lambdas_local_func.cpp new file mode 100644 index 000000000..801e1639a --- /dev/null +++ b/src/boost/libs/contract/example/features/no_lambdas_local_func.cpp @@ -0,0 +1,119 @@ + +// Copyright (C) 2008-2018 Lorenzo Caminiti +// Distributed under the Boost Software License, Version 1.0 (see accompanying +// file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt). +// See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html + +#include <boost/contract.hpp> +#include <boost/local_function.hpp> +#include <boost/bind.hpp> +#include <cassert> + +class iarray : + private boost::contract::constructor_precondition<iarray> { +public: + static void static_invariant() { + BOOST_CONTRACT_ASSERT(instances() >= 0); + } + + void invariant() const { + BOOST_CONTRACT_ASSERT(size() <= capacity()); + } + + static void constructor_pre(unsigned const max, unsigned const count) { + BOOST_CONTRACT_ASSERT(count <= max); + } + explicit iarray(unsigned max, unsigned count = 0) : + boost::contract::constructor_precondition<iarray>(boost::bind( + &iarray::constructor_pre, max, count)), + values_(new int[max]), + capacity_(max) + { + boost::contract::old_ptr<int> old_instances; + void BOOST_LOCAL_FUNCTION(bind& old_instances) { + old_instances = BOOST_CONTRACT_OLDOF(iarray::instances()); + } BOOST_LOCAL_FUNCTION_NAME(old) + void BOOST_LOCAL_FUNCTION(const bind this_, const bind& count, + const bind& old_instances) { + BOOST_CONTRACT_ASSERT(this_->size() == count); + BOOST_CONTRACT_ASSERT(this_->instances() == *old_instances + 1); + } BOOST_LOCAL_FUNCTION_NAME(post) + boost::contract::check c = boost::contract::constructor(this) + .old(old).postcondition(post); + + for(unsigned i = 0; i < count; ++i) values_[i] = int(); + size_ = count; + ++instances_; + } + + virtual ~iarray() { + boost::contract::old_ptr<int> old_instances; + void BOOST_LOCAL_FUNCTION(const bind this_, bind& old_instances) { + old_instances = BOOST_CONTRACT_OLDOF(this_->instances()); + } BOOST_LOCAL_FUNCTION_NAME(old) + void BOOST_LOCAL_FUNCTION(const bind& old_instances) { + BOOST_CONTRACT_ASSERT(iarray::instances() == *old_instances - 1); + } BOOST_LOCAL_FUNCTION_NAME(post) + boost::contract::check c = boost::contract::destructor(this) + .old(old).postcondition(post); + + delete[] values_; + --instances_; + } + + virtual void push_back(int value, boost::contract::virtual_* v = 0) { + boost::contract::old_ptr<unsigned> old_size; + void BOOST_LOCAL_FUNCTION(const bind this_) { + BOOST_CONTRACT_ASSERT(this_->size() < this_->capacity()); + } BOOST_LOCAL_FUNCTION_NAME(pre) + void BOOST_LOCAL_FUNCTION(const bind v, const bind this_, + bind& old_size) { + old_size = BOOST_CONTRACT_OLDOF(v, this_->size()); + } BOOST_LOCAL_FUNCTION_NAME(old) + void BOOST_LOCAL_FUNCTION(const bind this_, const bind& old_size) { + BOOST_CONTRACT_ASSERT(this_->size() == *old_size + 1); + } BOOST_LOCAL_FUNCTION_NAME(post) + boost::contract::check c = boost::contract::public_function(v, this) + .precondition(pre).old(old).postcondition(post); + + values_[size_++] = value; + } + + unsigned capacity() const { + // Check invariants. + boost::contract::check c = boost::contract::public_function(this); + return capacity_; + } + + unsigned size() const { + // Check invariants. + boost::contract::check c = boost::contract::public_function(this); + return size_; + } + + static int instances() { + // Check static invariants. + boost::contract::check c = boost::contract::public_function<iarray>(); + return instances_; + } + +private: + int* values_; + unsigned capacity_; + unsigned size_; + static int instances_; +}; + +int iarray::instances_ = 0; + +int main() { + iarray a(3, 2); + assert(a.capacity() == 3); + assert(a.size() == 2); + + a.push_back('x'); + assert(a.size() == 3); + + return 0; +} + diff --git a/src/boost/libs/contract/example/features/non_member.cpp b/src/boost/libs/contract/example/features/non_member.cpp new file mode 100644 index 000000000..122241549 --- /dev/null +++ b/src/boost/libs/contract/example/features/non_member.cpp @@ -0,0 +1,40 @@ + +// Copyright (C) 2008-2018 Lorenzo Caminiti +// Distributed under the Boost Software License, Version 1.0 (see accompanying +// file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt). +// See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html + +#include <limits> +#include <cassert> + +//[non_member +#include <boost/contract.hpp> + +// Contract for a non-member function. +int inc(int& x) { + int result; + boost::contract::old_ptr<int> old_x = BOOST_CONTRACT_OLDOF(x); + boost::contract::check c = boost::contract::function() + .precondition([&] { + BOOST_CONTRACT_ASSERT(x < std::numeric_limits<int>::max()); + }) + .postcondition([&] { + BOOST_CONTRACT_ASSERT(x == *old_x + 1); + BOOST_CONTRACT_ASSERT(result == *old_x); + }) + .except([&] { + BOOST_CONTRACT_ASSERT(x == *old_x); + }) + ; + + return result = x++; // Function body. +} +//] + +int main() { + int x = std::numeric_limits<int>::max() - 1; + assert(inc(x) == std::numeric_limits<int>::max() - 1); + assert(x == std::numeric_limits<int>::max()); + return 0; +} + diff --git a/src/boost/libs/contract/example/features/old.cpp b/src/boost/libs/contract/example/features/old.cpp new file mode 100644 index 000000000..bdf8b8c6e --- /dev/null +++ b/src/boost/libs/contract/example/features/old.cpp @@ -0,0 +1,41 @@ + +// Copyright (C) 2008-2018 Lorenzo Caminiti +// Distributed under the Boost Software License, Version 1.0 (see accompanying +// file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt). +// See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html + +#include <boost/contract.hpp> +#include <string> +#include <cassert> + +//[old +char replace(std::string& s, unsigned index, char x) { + char result; + boost::contract::old_ptr<char> old_char; // Null, old value copied later... + boost::contract::check c = boost::contract::function() + .precondition([&] { + BOOST_CONTRACT_ASSERT(index < s.size()); + }) + .old([&] { // ...after preconditions (and invariants) checked. + old_char = BOOST_CONTRACT_OLDOF(s[index]); + }) + .postcondition([&] { + BOOST_CONTRACT_ASSERT(s[index] == x); + BOOST_CONTRACT_ASSERT(result == *old_char); + }) + ; + + result = s[index]; + s[index] = x; + return result; +} +//] + +int main() { + std::string s = "abc"; + char r = replace(s, 1, '_'); + assert(s == "a_c"); + assert(r == 'b'); + return 0; +} + diff --git a/src/boost/libs/contract/example/features/old_if_copyable.cpp b/src/boost/libs/contract/example/features/old_if_copyable.cpp new file mode 100644 index 000000000..8cf1acc7b --- /dev/null +++ b/src/boost/libs/contract/example/features/old_if_copyable.cpp @@ -0,0 +1,133 @@ + +// Copyright (C) 2008-2018 Lorenzo Caminiti +// Distributed under the Boost Software License, Version 1.0 (see accompanying +// file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt). +// See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html + +#include <boost/contract.hpp> +#include <boost/type_traits.hpp> +#include <boost/noncopyable.hpp> +#include <cassert> + +//[old_if_copyable_offset +template<typename T> // T might or might not be copyable. +void offset(T& x, int count) { + // No compiler error if T has no copy constructor... + boost::contract::old_ptr_if_copyable<T> old_x = BOOST_CONTRACT_OLDOF(x); + boost::contract::check c = boost::contract::function() + .postcondition([&] { + // ...but old value null if T has no copy constructor. + if(old_x) BOOST_CONTRACT_ASSERT(x == *old_x + count); + }) + ; + + x += count; +} +//] + +//[old_if_copyable_w_decl +// Copyable type but... +class w { +public: + w(w const&) { /* Some very expensive copy operation here... */ } + + /* ... */ +//] + w() : num_(0) {} + int operator+(int i) const { return num_ + i; } + w& operator+=(int i) { num_ += i; return *this; } + bool operator==(int i) const { return long(num_) == i; } +private: + unsigned long num_; +}; + +//[old_if_copyable_w_spec +// ...never copy old values for type `w` (because its copy is too expensive). +namespace boost { namespace contract { + template<> + struct is_old_value_copyable<w> : boost::false_type {}; +} } +//] + +//[old_if_copyable_p_decl +// Non-copyable type but... +class p : private boost::noncopyable { + int* num_; + + friend struct boost::contract::old_value_copy<p>; + + /* ... */ +//] +public: + p() : num_(new int(0)) {} + ~p() { delete num_; } + int operator+(int i) const { return *num_ + i; } + p& operator+=(int i) { *num_ += i; return *this; } + bool operator==(int i) const { return *num_ == i; } +}; + +//[old_if_copyable_p_spec +// ...still copy old values for type `p` (using a deep copy). +namespace boost { namespace contract { + template<> + struct old_value_copy<p> { + explicit old_value_copy(p const& old) { + *old_.num_ = *old.num_; // Deep copy pointed value. + } + + p const& old() const { return old_; } + + private: + p old_; + }; + + template<> + struct is_old_value_copyable<p> : boost::true_type {}; +} } +//] + +//[old_if_copyable_n_decl +class n { // Do not want to use boost::noncopyable but... + int num_; + +private: + n(n const&); // ...unimplemented private copy constructor (so non-copyable). + + /* ... */ +//] + +public: + n() : num_(0) {} + int operator+(int i) const { return num_ + i; } + n& operator+=(int i) { num_ += i; return *this; } + bool operator==(int i) const { return num_ == i; } +}; + +//[old_if_copyable_n_spec +// Specialize `boost::is_copy_constructible` (no need for this on C++11). +namespace boost { namespace contract { + template<> + struct is_old_value_copyable<n> : boost::false_type {}; +} } +//] + +int main() { + int i = 0; // Copy constructor, copy and check old values. + offset(i, 3); + assert(i == 3); + + w j; // Expensive copy constructor, so never copy or check old values. + offset(j, 3); + assert(j == 3); + + p k; // No copy constructor, but still copy and check old values. + offset(k, 3); + assert(k == 3); + + n h; // No copy constructor, no compiler error but no old value checks. + offset(h, 3); + assert(h == 3); + + return 0; +} + diff --git a/src/boost/libs/contract/example/features/old_no_macro.cpp b/src/boost/libs/contract/example/features/old_no_macro.cpp new file mode 100644 index 000000000..29c06a681 --- /dev/null +++ b/src/boost/libs/contract/example/features/old_no_macro.cpp @@ -0,0 +1,46 @@ + +// Copyright (C) 2008-2018 Lorenzo Caminiti +// Distributed under the Boost Software License, Version 1.0 (see accompanying +// file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt). +// See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html + +#include <boost/contract.hpp> +#include <cassert> +#include <vector> + +//[old_no_macro +template<typename T> +class vector { +public: + virtual void push_back(T const& value, boost::contract::virtual_* v = 0) { + // Program old value instead of using `OLD(size())` macro. + boost::contract::old_ptr<unsigned> old_size = + boost::contract::make_old(v, boost::contract::copy_old(v) ? + size() : boost::contract::null_old()) + ; + + boost::contract::check c = boost::contract::public_function(v, this) + .postcondition([&] { + BOOST_CONTRACT_ASSERT(size() == *old_size + 1); + }) + ; + + vect_.push_back(value); + } + + /* ... */ +//] + + unsigned size() const { return vect_.size(); } + +private: + std::vector<T> vect_; +}; + +int main() { + vector<int> vect; + vect.push_back(123); + assert(vect.size() == 1); + return 0; +} + diff --git a/src/boost/libs/contract/example/features/optional_result.cpp b/src/boost/libs/contract/example/features/optional_result.cpp new file mode 100644 index 000000000..330c780de --- /dev/null +++ b/src/boost/libs/contract/example/features/optional_result.cpp @@ -0,0 +1,41 @@ + +// Copyright (C) 2008-2018 Lorenzo Caminiti +// Distributed under the Boost Software License, Version 1.0 (see accompanying +// file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt). +// See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html + +#include <boost/contract.hpp> +#include <boost/optional.hpp> +#include <vector> +#include <cassert> + +//[optional_result +template<unsigned Index, typename T> +T& get(std::vector<T>& vect) { + boost::optional<T&> result; // Result not initialized here... + boost::contract::check c = boost::contract::function() + .precondition([&] { + BOOST_CONTRACT_ASSERT(Index < vect.size()); + }) + .postcondition([&] { + BOOST_CONTRACT_ASSERT(*result == vect[Index]); + }) + ; + + // Function body (executed after preconditions checked). + return *(result = vect[Index]); // ...result initialized here instead. +} +//] + +int main() { + std::vector<int> v; + v.push_back(123); + v.push_back(456); + v.push_back(789); + int& x = get<1>(v); + assert(x == 456); + x = -456; + assert(v[1] == -456); + return 0; +} + diff --git a/src/boost/libs/contract/example/features/optional_result_virtual.cpp b/src/boost/libs/contract/example/features/optional_result_virtual.cpp new file mode 100644 index 000000000..724a18493 --- /dev/null +++ b/src/boost/libs/contract/example/features/optional_result_virtual.cpp @@ -0,0 +1,88 @@ + +// Copyright (C) 2008-2018 Lorenzo Caminiti +// Distributed under the Boost Software License, Version 1.0 (see accompanying +// file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt). +// See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html + +#include <boost/contract.hpp> +#include <boost/optional.hpp> +#include <vector> +#include <cassert> + +template<typename T> +class accessible { +public: + virtual T& at(unsigned index, boost::contract::virtual_* v = 0) = 0; + + // Could program class invariants and contracts for following too. + virtual T const& operator[](unsigned index) const = 0; + virtual unsigned size() const = 0; +}; + +//[optional_result_virtual +template<typename T> +T& accessible<T>::at(unsigned index, boost::contract::virtual_* v) { + boost::optional<T&> result; + // Pass `result` right after `v`... + boost::contract::check c = boost::contract::public_function(v, result, this) + .precondition([&] { + BOOST_CONTRACT_ASSERT(index < size()); + }) + // ...plus postconditions take `result` as a parameter (not capture). + .postcondition([&] (boost::optional<T const&> const& result) { + BOOST_CONTRACT_ASSERT(*result == operator[](index)); + }) + ; + + assert(false); + return *result; +} +//] + +template<typename T> +class vector + #define BASES public accessible<T> + : BASES +{ +public: + typedef BOOST_CONTRACT_BASE_TYPES(BASES) base_types; + #undef BASES + + T& at(unsigned index, boost::contract::virtual_* v = 0) /* override */ { + boost::optional<T&> result; + // Pass `result` right after `v`... + boost::contract::check c = boost::contract::public_function< + override_at>(v, result, &vector::at, this, index) + // ...plus postconditions take `result` as parameter (not capture). + .postcondition([&] (boost::optional<T const&> const& result) { + if(index == 0) BOOST_CONTRACT_ASSERT(*result == front()); + }) + ; + + return *(result = vect_[index]); + } + + // Could program class invariants and contracts for following too. + T const& operator[](unsigned index) const { return vect_[index]; } + unsigned size() const { return vect_.size(); } + T const& front() const { return vect_.front(); } + void push_back(T const& value) { vect_.push_back(value); } + + BOOST_CONTRACT_OVERRIDE(at) + +private: + std::vector<T> vect_; +}; + +int main() { + vector<int> v; + v.push_back(123); + v.push_back(456); + v.push_back(789); + int& x = v.at(1); + assert(x == 456); + x = -456; + assert(v.at(1) == -456); + return 0; +} + diff --git a/src/boost/libs/contract/example/features/overload.cpp b/src/boost/libs/contract/example/features/overload.cpp new file mode 100644 index 000000000..2feab3478 --- /dev/null +++ b/src/boost/libs/contract/example/features/overload.cpp @@ -0,0 +1,202 @@ + +// Copyright (C) 2008-2018 Lorenzo Caminiti +// Distributed under the Boost Software License, Version 1.0 (see accompanying +// file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt). +// See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html + +#include <boost/contract.hpp> +#include <boost/optional.hpp> +#include <string> +#include <sstream> +#include <cassert> + +class lines { +public: + virtual std::string str(boost::contract::virtual_* v = 0) const = 0; + virtual std::string& str(boost::contract::virtual_* v = 0) = 0; + + virtual void put(std::string const& x, + boost::contract::virtual_* v = 0) = 0; + + virtual void put(char x, boost::contract::virtual_* v = 0) = 0; + + virtual void put(int x, bool tab = false, + boost::contract::virtual_* v = 0) = 0; +}; + +std::string lines::str(boost::contract::virtual_* v) const { + std::string result; + boost::contract::check c = boost::contract::public_function(v, result, this) + .postcondition([&] (std::string const& result) { + if(result != "") BOOST_CONTRACT_ASSERT(*result.rbegin() == '\n'); + }) + ; + assert(false); + return result; +} + +std::string& lines::str(boost::contract::virtual_* v) { + boost::optional<std::string&> result; + boost::contract::check c = boost::contract::public_function(v, result, this) + .postcondition([&] (boost::optional<std::string const&> const& result) { + if(*result != "") BOOST_CONTRACT_ASSERT(*result->rbegin() == '\n'); + }) + ; + assert(false); + return *result; +} + +void lines::put(std::string const& x, boost::contract::virtual_* v) { + boost::contract::check c = boost::contract::public_function(v, this) + .precondition([&] { + BOOST_CONTRACT_ASSERT(*x.rbegin() != '\n'); + }) + ; + assert(false); +} + +void lines::put(char x, boost::contract::virtual_* v) { + boost::contract::check c = boost::contract::public_function(v, this) + .precondition([&] { + BOOST_CONTRACT_ASSERT(x != '\n'); + }) + ; + assert(false); +} + +void lines::put(int x, bool tab, + boost::contract::virtual_* v) { + boost::contract::check c = boost::contract::public_function(v, this) + .precondition([&] { + BOOST_CONTRACT_ASSERT(x >= 0); + }) + ; + assert(false); +} + +//[overload +class string_lines + #define BASES public lines + : BASES +{ +public: + typedef BOOST_CONTRACT_BASE_TYPES(BASES) base_types; + #undef BASES + + BOOST_CONTRACT_OVERRIDES(str) // Invoked only once for all `str` overloads. + + std::string str(boost::contract::virtual_* v = 0) const /* override */ { + std::string result; + boost::contract::check c = boost::contract::public_function< + override_str>( + v, result, + // `static_cast` resolves overloaded function pointer ambiguities. + static_cast<std::string (string_lines::*)( + boost::contract::virtual_*) const>(&string_lines::str), + this + ); + + return result = str_; + } + + // Overload on (absence of) `const` qualifier. + std::string& str(boost::contract::virtual_* v = 0) /* override */ { + boost::contract::check c = boost::contract::public_function< + override_str>( + v, str_, + // `static_cast` resolves overloaded function pointer ambiguities. + static_cast<std::string& (string_lines::*)( + boost::contract::virtual_*)>(&string_lines::str), + this + ); + + return str_; + } + + BOOST_CONTRACT_OVERRIDES(put) // Invoked only once for all `put` overloads. + + void put(std::string const& x, + boost::contract::virtual_* v = 0) /* override */ { + boost::contract::old_ptr<std::string> old_str = + BOOST_CONTRACT_OLDOF(v, str()); + boost::contract::check c = boost::contract::public_function< + override_put>( + v, + // `static_cast` resolves overloaded function pointer ambiguities. + static_cast<void (string_lines::*)(std::string const&, + boost::contract::virtual_*)>(&string_lines::put), + this, x + ) + .postcondition([&] { + BOOST_CONTRACT_ASSERT(str() == *old_str + x + '\n'); + }) + ; + + str_ = str_ + x + '\n'; + } + + // Overload on argument type. + void put(char x, boost::contract::virtual_* v = 0) /* override */ { + boost::contract::old_ptr<std::string> old_str = + BOOST_CONTRACT_OLDOF(v, str()); + boost::contract::check c = boost::contract::public_function< + override_put>( + v, + // `static_cast` resolves overloaded function pointer ambiguities. + static_cast<void (string_lines::*)(char, + boost::contract::virtual_*)>(&string_lines::put), + this, x + ) + .postcondition([&] { + BOOST_CONTRACT_ASSERT(str() == *old_str + x + '\n'); + }) + ; + + str_ = str_ + x + '\n'; + } + + // Overload on argument type and arity (also with default parameter). + void put(int x, bool tab = false, + boost::contract::virtual_* v = 0) /* override */ { + boost::contract::old_ptr<std::string> old_str = + BOOST_CONTRACT_OLDOF(v, str()); + boost::contract::check c = boost::contract::public_function< + override_put>( + v, + // `static_cast` resolves overloaded function pointer ambiguities. + static_cast<void (string_lines::*)(int, bool, + boost::contract::virtual_*)>(&string_lines::put), + this, x, tab + ) + .postcondition([&] { + std::ostringstream s; + s << x; + BOOST_CONTRACT_ASSERT( + str() == *old_str + (tab ? "\t" : "") + s.str() + '\n'); + }) + ; + + std::ostringstream s; + s << str_ << (tab ? "\t" : "") << x << '\n'; + str_ = s.str(); + } + +private: + std::string str_; +}; +//] + +int main() { + string_lines s; + s.put("abc"); + assert(s.str() == "abc\n"); + s.put('x'); + assert(s.str() == "abc\nx\n"); + s.put(10); + assert(s.str() == "abc\nx\n10\n"); + s.put(20, true); + lines const& l = s; + assert(l.str() == "abc\nx\n10\n\t20\n"); + return 0; +} + diff --git a/src/boost/libs/contract/example/features/private_protected.cpp b/src/boost/libs/contract/example/features/private_protected.cpp new file mode 100644 index 000000000..7651a925b --- /dev/null +++ b/src/boost/libs/contract/example/features/private_protected.cpp @@ -0,0 +1,77 @@ + +// Copyright (C) 2008-2018 Lorenzo Caminiti +// Distributed under the Boost Software License, Version 1.0 (see accompanying +// file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt). +// See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html + +#include <boost/contract.hpp> +#include <limits> +#include <cassert> + +//[private_protected +class counter { +protected: // Protected functions use `function()` (like non-members). + void set(int n) { + boost::contract::check c = boost::contract::function() + .precondition([&] { + BOOST_CONTRACT_ASSERT(n <= 0); + }) + .postcondition([&] { + BOOST_CONTRACT_ASSERT(get() == n); + }) + ; + + n_ = n; + } + +private: // Private functions use `function()` (like non-members). + void dec() { + boost::contract::old_ptr<int> old_get = BOOST_CONTRACT_OLDOF(get()); + boost::contract::check c = boost::contract::function() + .precondition([&] { + BOOST_CONTRACT_ASSERT( + get() + 1 >= std::numeric_limits<int>::min()); + }) + .postcondition([&] { + BOOST_CONTRACT_ASSERT(get() == *old_get - 1); + }) + ; + + set(get() - 1); + } + + int n_; + + /* ... */ +//] + +public: + int get() const { + int result; + boost::contract::check c = boost::contract::public_function(this) + .postcondition([&] { + BOOST_CONTRACT_ASSERT(result <= 0); + BOOST_CONTRACT_ASSERT(result == n_); + }) + ; + + return result = n_; + } + + counter() : n_(0) {} // Should contract constructor and destructor too. + + void invariant() const { + BOOST_CONTRACT_ASSERT(get() <= 0); + } + + friend int main(); +}; + +int main() { + counter cnt; + assert(cnt.get() == 0); + cnt.dec(); + assert(cnt.get() == -1); + return 0; +} + diff --git a/src/boost/libs/contract/example/features/private_protected_virtual.cpp b/src/boost/libs/contract/example/features/private_protected_virtual.cpp new file mode 100644 index 000000000..534da5087 --- /dev/null +++ b/src/boost/libs/contract/example/features/private_protected_virtual.cpp @@ -0,0 +1,145 @@ + +// Copyright (C) 2008-2018 Lorenzo Caminiti +// Distributed under the Boost Software License, Version 1.0 (see accompanying +// file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt). +// See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html + +#include <boost/contract.hpp> +#include <limits> +#include <cassert> + +//[private_protected_virtual_counter +class counter { + // Virtual private and protected functions still declare extra + // `virtual_* = 0` parameter (otherwise they cannot be overridden), but... +protected: + virtual void set(int n, boost::contract::virtual_* = 0) { + boost::contract::check c = boost::contract::function() // ...no `v`. + .precondition([&] { + BOOST_CONTRACT_ASSERT(n <= 0); + }) + .postcondition([&] { + BOOST_CONTRACT_ASSERT(get() == n); + }) + ; + + n_ = n; + } + +private: + virtual void dec(boost::contract::virtual_* = 0) { + boost::contract::old_ptr<int> old_get = BOOST_CONTRACT_OLDOF(get()); // ...no `v`. + boost::contract::check c = boost::contract::function() // ...no `v`. + .precondition([&] { + BOOST_CONTRACT_ASSERT( + get() + 1 >= std::numeric_limits<int>::min()); + }) + .postcondition([&] { + BOOST_CONTRACT_ASSERT(get() == *old_get - 1); + }) + ; + + set(get() - 1); + } + + int n_; + + /* ... */ +//] + +public: + virtual int get(boost::contract::virtual_* v = 0) const { + int result; + boost::contract::check c = boost::contract::public_function( + v, result, this) + .postcondition([&] (int const result) { + BOOST_CONTRACT_ASSERT(result <= 0); + BOOST_CONTRACT_ASSERT(result == n_); + }) + ; + + return result = n_; + } + + counter() : n_(0) {} // Should contract constructor and destructor too. + + void invariant() const { + BOOST_CONTRACT_ASSERT(get() <= 0); + } + + friend int main(); +}; + +//[private_protected_virtual_counter10 +class counter10 + #define BASES public counter + : BASES +{ +public: + typedef BOOST_CONTRACT_BASE_TYPES(BASES) base_types; + #undef BASES + + // Overriding from non-public members so no subcontracting, no override_... + + virtual void set(int n, boost::contract::virtual_* v = 0) /* override */ { + boost::contract::check c = boost::contract::public_function(v, this) + .precondition([&] { + BOOST_CONTRACT_ASSERT(n % 10 == 0); + }) + .postcondition([&] { + BOOST_CONTRACT_ASSERT(get() == n); + }) + ; + + counter::set(n); + } + + virtual void dec(boost::contract::virtual_* v = 0) /* override */ { + boost::contract::old_ptr<int> old_get = BOOST_CONTRACT_OLDOF(v, get()); + boost::contract::check c = boost::contract::public_function(v, this) + .precondition([&] { + BOOST_CONTRACT_ASSERT( + get() + 10 >= std::numeric_limits<int>::min()); + }) + .postcondition([&] { + BOOST_CONTRACT_ASSERT(get() == *old_get - 10); + }) + ; + + set(get() - 10); + } + + /* ... */ +//] + + virtual int get(boost::contract::virtual_* v = 0) const { + int result; + boost::contract::check c = boost::contract::public_function< + override_get>(v, result, &counter10::get, this); + + return result = counter::get(); + } + BOOST_CONTRACT_OVERRIDE(get) + + // Should contract default constructor and destructor too. + + void invariant() const { + BOOST_CONTRACT_ASSERT(get() % 10 == 0); + } +}; + +int main() { + counter cnt; + assert(cnt.get() == 0); + cnt.dec(); + assert(cnt.get() == -1); + + counter10 cnt10; + counter& b = cnt10; // Polymorphic calls. + assert(b.get() == 0); + b.dec(); + assert(b.get() == -10); + + return 0; +} + diff --git a/src/boost/libs/contract/example/features/private_protected_virtual_multi.cpp b/src/boost/libs/contract/example/features/private_protected_virtual_multi.cpp new file mode 100644 index 000000000..2ab875fbd --- /dev/null +++ b/src/boost/libs/contract/example/features/private_protected_virtual_multi.cpp @@ -0,0 +1,209 @@ + +// Copyright (C) 2008-2018 Lorenzo Caminiti +// Distributed under the Boost Software License, Version 1.0 (see accompanying +// file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt). +// See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html + +#include <boost/config.hpp> +#ifdef BOOST_MSVC + +// WARNING: MSVC (at least up to VS 2015) gives a compile-time error if SFINAE +// cannot introspect a member because of its private or protected access level. +// That is incorrect, SFINAE should fail in these cases without generating +// compile-time errors like GCC and CLang do. Therefore, currently it is not +// possible to override a member that is public in one base but private or +// protected in other base using this library on MSVC (that can be done instead +// using this library on GCC or CLang). +int main() { return 0; } // Trivial program for MSVC. + +#else + +#include <boost/contract.hpp> +#include <limits> +#include <cassert> + +class counter { + // Virtual private and protected functions still declare extra + // `virtual_* = 0` parameter (otherwise they cannot be overridden). +protected: + virtual void set(int n, boost::contract::virtual_* = 0) { + boost::contract::check c = boost::contract::function() + .precondition([&] { + BOOST_CONTRACT_ASSERT(n <= 0); + }) + .postcondition([&] { + BOOST_CONTRACT_ASSERT(get() == n); + }) + ; + + n_ = n; + } + +private: + virtual void dec(boost::contract::virtual_* = 0) { + boost::contract::old_ptr<int> old_get = BOOST_CONTRACT_OLDOF(get()); + boost::contract::check c = boost::contract::function() + .precondition([&] { + BOOST_CONTRACT_ASSERT( + get() + 1 >= std::numeric_limits<int>::min()); + }) + .postcondition([&] { + BOOST_CONTRACT_ASSERT(get() == *old_get - 1); + }) + ; + + set(get() - 1); + } + + int n_; + +public: + virtual int get(boost::contract::virtual_* v = 0) const { + int result; + boost::contract::check c = boost::contract::public_function( + v, result, this) + .postcondition([&] (int const result) { + BOOST_CONTRACT_ASSERT(result <= 0); + BOOST_CONTRACT_ASSERT(result == n_); + }) + ; + + return result = n_; + } + + counter() : n_(0) {} // Should contract constructor and destructor too. + + void invariant() const { + BOOST_CONTRACT_ASSERT(get() <= 0); + } + + friend int main(); +}; + +//[private_protected_virtual_multi_countable +class countable { +public: + void invariant() const { + BOOST_CONTRACT_ASSERT(get() <= 0); + } + + virtual void dec(boost::contract::virtual_* v = 0) = 0; + virtual void set(int n, boost::contract::virtual_* v = 0) = 0; + virtual int get(boost::contract::virtual_* v = 0) const = 0; +}; + +/* ... */ +//] + +void countable::dec(boost::contract::virtual_* v) { + boost::contract::old_ptr<int> old_get = BOOST_CONTRACT_OLDOF(v, get()); + boost::contract::check c = boost::contract::public_function(v, this) + .precondition([&] { + BOOST_CONTRACT_ASSERT(get() > std::numeric_limits<int>::min()); + }) + .postcondition([&] { + BOOST_CONTRACT_ASSERT(get() < *old_get); + }) + ; + assert(false); // Never executed by this library. +} + +void countable::set(int n, boost::contract::virtual_* v) { + boost::contract::check c = boost::contract::public_function( + v, this) + .precondition([&] { + BOOST_CONTRACT_ASSERT(n <= 0); + }) + .postcondition([&] { + BOOST_CONTRACT_ASSERT(get() == n); + }) + ; + assert(false); // Never executed by this library. +} + +int countable::get(boost::contract::virtual_* v) const { + int result; + boost::contract::check c = boost::contract::public_function( + v, result, this); + assert(false); // Never executed by this library. +} + +//[private_protected_virtual_multi_counter10 +class counter10 + #define BASES public countable, public counter // Multiple inheritance. + : BASES +{ +public: + typedef BOOST_CONTRACT_BASE_TYPES(BASES) base_types; + #undef BASES + + // Overriding from public members from `countable` so use `override_...`. + + virtual void set(int n, boost::contract::virtual_* v = 0) /* override */ { + boost::contract::check c = boost::contract::public_function< + override_set>(v, &counter10::set, this, n) + .precondition([&] { + BOOST_CONTRACT_ASSERT(n % 10 == 0); + }) + .postcondition([&] { + BOOST_CONTRACT_ASSERT(get() == n); + }) + ; + + counter::set(n); + } + + virtual void dec(boost::contract::virtual_* v = 0) /* override */ { + boost::contract::old_ptr<int> old_get = BOOST_CONTRACT_OLDOF(v, get()); + boost::contract::check c = boost::contract::public_function< + override_dec>(v, &counter10::dec, this) + .precondition([&] { + BOOST_CONTRACT_ASSERT( + get() + 10 >= std::numeric_limits<int>::min()); + }) + .postcondition([&] { + BOOST_CONTRACT_ASSERT(get() == *old_get - 10); + }) + ; + + set(get() - 10); + } + + BOOST_CONTRACT_OVERRIDES(set, dec) + + /* ... */ +//] + + virtual int get(boost::contract::virtual_* v = 0) const { + int result; + boost::contract::check c = boost::contract::public_function< + override_get>(v, result, &counter10::get, this); + + return result = counter::get(); + } + BOOST_CONTRACT_OVERRIDE(get) + + // Should contract default constructor and destructor too. + + void invariant() const { + BOOST_CONTRACT_ASSERT(get() % 10 == 0); + } +}; + +int main() { + counter cnt; + assert(cnt.get() == 0); + cnt.dec(); + assert(cnt.get() == -1); + + counter10 cnt10; + countable& b = cnt10; // Polymorphic calls. + assert(b.get() == 0); + b.dec(); + assert(b.get() == -10); + + return 0; +} + +#endif // MSVC + diff --git a/src/boost/libs/contract/example/features/public.cpp b/src/boost/libs/contract/example/features/public.cpp new file mode 100644 index 000000000..a6d94aa72 --- /dev/null +++ b/src/boost/libs/contract/example/features/public.cpp @@ -0,0 +1,189 @@ + +// Copyright (C) 2008-2018 Lorenzo Caminiti +// Distributed under the Boost Software License, Version 1.0 (see accompanying +// file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt). +// See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html + +#include <boost/contract.hpp> +#include <vector> +#include <algorithm> +#include <cassert> + +//[public_class_begin +class unique_identifiers : + private boost::contract::constructor_precondition<unique_identifiers> +{ +public: + void invariant() const { + BOOST_CONTRACT_ASSERT(size() >= 0); + } +//] + +//[public_constructor +public: + // Contract for a constructor. + unique_identifiers(int from, int to) : + boost::contract::constructor_precondition<unique_identifiers>([&] { + BOOST_CONTRACT_ASSERT(from >= 0); + BOOST_CONTRACT_ASSERT(to >= from); + }) + { + boost::contract::check c = boost::contract::constructor(this) + .postcondition([&] { + BOOST_CONTRACT_ASSERT(size() == (to - from + 1)); + }) + ; + + // Constructor body. + for(int id = from; id <= to; ++id) vect_.push_back(id); + } +//] + +//[public_destructor +public: + // Contract for a destructor. + virtual ~unique_identifiers() { + // Following contract checks class invariants. + boost::contract::check c = boost::contract::destructor(this); + + // Destructor body here... (do nothing in this example). + } +//] + + int size() const { + // Following contract checks invariants. + boost::contract::check c = boost::contract::public_function(this); + return vect_.size(); + } + +//[public_function +public: + // Contract for a public function (but no static, virtual, or override). + bool find(int id) const { + bool result; + boost::contract::check c = boost::contract::public_function(this) + .precondition([&] { + BOOST_CONTRACT_ASSERT(id >= 0); + }) + .postcondition([&] { + if(size() == 0) BOOST_CONTRACT_ASSERT(!result); + }) + ; + + // Function body. + return result = std::find(vect_.begin(), vect_.end(), id) != + vect_.end(); + } +//] + +//[public_virtual_function +public: + // Contract for a public virtual function (but no override). + virtual int push_back(int id, boost::contract::virtual_* v = 0) { // Extra `v`. + int result; + boost::contract::old_ptr<bool> old_find = + BOOST_CONTRACT_OLDOF(v, find(id)); // Pass `v`. + boost::contract::old_ptr<int> old_size = + BOOST_CONTRACT_OLDOF(v, size()); // Pass `v`. + boost::contract::check c = boost::contract::public_function( + v, result, this) // Pass `v` and `result`. + .precondition([&] { + BOOST_CONTRACT_ASSERT(id >= 0); + BOOST_CONTRACT_ASSERT(!find(id)); // ID cannot be already present. + }) + .postcondition([&] (int const result) { + if(!*old_find) { + BOOST_CONTRACT_ASSERT(find(id)); + BOOST_CONTRACT_ASSERT(size() == *old_size + 1); + } + BOOST_CONTRACT_ASSERT(result == id); + }) + ; + + // Function body. + vect_.push_back(id); + return result = id; + } +//] + +private: + std::vector<int> vect_; +//[public_class_end + /* ... */ +}; +//] + +//[public_derived_class_begin +class identifiers + #define BASES public unique_identifiers + : BASES +{ +public: + typedef BOOST_CONTRACT_BASE_TYPES(BASES) base_types; // Bases typedef. + #undef BASES + + void invariant() const { // Check in AND with bases. + BOOST_CONTRACT_ASSERT(empty() == (size() == 0)); + } +//] + +//[public_function_override +public: + // Contract for a public function override. + int push_back(int id, boost::contract::virtual_* v = 0) /* override */ { + int result; + boost::contract::old_ptr<bool> old_find = + BOOST_CONTRACT_OLDOF(v, find(id)); + boost::contract::old_ptr<int> old_size = + BOOST_CONTRACT_OLDOF(v, size()); + boost::contract::check c = boost::contract::public_function< + override_push_back // Pass override type plus below function pointer... + >(v, result, &identifiers::push_back, this, id) // ...and arguments. + .precondition([&] { // Check in OR with bases. + BOOST_CONTRACT_ASSERT(id >= 0); + BOOST_CONTRACT_ASSERT(find(id)); // ID can be already present. + }) + .postcondition([&] (int const result) { // Check in AND with bases. + if(*old_find) BOOST_CONTRACT_ASSERT(size() == *old_size); + }) + ; + + // Function body. + if(!find(id)) unique_identifiers::push_back(id); // Else, do nothing. + return result = id; + } + BOOST_CONTRACT_OVERRIDE(push_back) // Define `override_push_back`. +//] + + bool empty() const { + // Following contract checks invariants. + boost::contract::check c = boost::contract::public_function(this); + return size() == 0; + } + + identifiers(int from, int to) : unique_identifiers(from, to) { + // Following contract checks invariants. + boost::contract::check c = boost::contract::constructor(this); + } + +//[public_derived_class_end + /* ... */ +}; +//] + +int main() { + unique_identifiers uids(1, 4); + assert(uids.find(2)); + assert(!uids.find(5)); + uids.push_back(5); + assert(uids.find(5)); + + identifiers ids(10, 40); + assert(!ids.find(50)); + ids.push_back(50); + ids.push_back(50); + assert(ids.find(50)); + + return 0; +} + diff --git a/src/boost/libs/contract/example/features/pure_virtual_public.cpp b/src/boost/libs/contract/example/features/pure_virtual_public.cpp new file mode 100644 index 000000000..917a6c718 --- /dev/null +++ b/src/boost/libs/contract/example/features/pure_virtual_public.cpp @@ -0,0 +1,89 @@ + +// Copyright (C) 2008-2018 Lorenzo Caminiti +// Distributed under the Boost Software License, Version 1.0 (see accompanying +// file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt). +// See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html + +#include <boost/contract.hpp> +#include <vector> +#include <cassert> + +//[pure_virtual_public_base_begin +template<typename Iterator> +class range { +public: + // Pure virtual function declaration (contract in definition below). + virtual Iterator begin(boost::contract::virtual_* v = 0) = 0; +//] + + // Could program class invariants and contracts for the following too. + virtual Iterator end() = 0; + virtual bool empty() const = 0; + +//[pure_virtual_public_base_end + /* ... */ +}; +//] + +//[pure_virtual_public_base_impl +// Pure virtual function default implementation (out-of-line in C++). +template<typename Iterator> +Iterator range<Iterator>::begin(boost::contract::virtual_* v) { + Iterator result; // As usual, virtual pass `result` right after `v`... + boost::contract::check c = boost::contract::public_function(v, result, this) + .postcondition([&] (Iterator const& result) { + if(empty()) BOOST_CONTRACT_ASSERT(result == end()); + }) + ; + + // Pure function body (never executed by this library). + assert(false); + return result; +} +//] + +template<typename T> +class vector + #define BASES public range<typename std::vector<T>::iterator> + : BASES +{ +public: + typedef BOOST_CONTRACT_BASE_TYPES(BASES) base_types; + #undef BASES + typedef typename std::vector<T>::iterator iterator; + + iterator begin(boost::contract::virtual_* v = 0) /* override */ { + iterator result; + // Again, pass result right after `v`... + boost::contract::check c = boost::contract::public_function< + override_begin>(v, result, &vector::begin, this) + // ...plus postconditions take `result` as parameter (not capture). + .postcondition([&] (iterator const& result) { + if(!empty()) BOOST_CONTRACT_ASSERT(*result == front()); + }) + ; + + return result = vect_.begin(); + } + BOOST_CONTRACT_OVERRIDE(begin) + + // Could program class invariants and contracts for the following too. + iterator end() { return vect_.end(); } + bool empty() const { return vect_.empty(); } + T const& front() const { return vect_.front(); } + void push_back(T const& value) { vect_.push_back(value); } + +private: + std::vector<T> vect_; +}; + +int main() { + vector<int> v; + v.push_back(1); + v.push_back(2); + v.push_back(3); + range<std::vector<int>::iterator>& r = v; + assert(*(r.begin()) == 1); + return 0; +} + diff --git a/src/boost/libs/contract/example/features/separate_body.cpp b/src/boost/libs/contract/example/features/separate_body.cpp new file mode 100644 index 000000000..10e05b2ef --- /dev/null +++ b/src/boost/libs/contract/example/features/separate_body.cpp @@ -0,0 +1,36 @@ + +// Copyright (C) 2008-2018 Lorenzo Caminiti +// Distributed under the Boost Software License, Version 1.0 (see accompanying +// file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt). +// See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html + +#include "separate_body.hpp" +#include <cassert> + +//[separate_body_cpp +void iarray::constructor_body(unsigned max, unsigned count) { + for(unsigned i = 0; i < count; ++i) values_[i] = int(); + size_ = count; +} + +void iarray::destructor_body() { delete[] values_; } + +void iarray::push_back_body(int value) { values_[size_++] = value; } + +/* ... */ +//] + +unsigned iarray::capacity_body() const { return capacity_; } +unsigned iarray::size_body() const { return size_; } + +int main() { + iarray a(3, 2); + assert(a.capacity() == 3); + assert(a.size() == 2); + + a.push_back(-123); + assert(a.size() == 3); + + return 0; +} + diff --git a/src/boost/libs/contract/example/features/separate_body.hpp b/src/boost/libs/contract/example/features/separate_body.hpp new file mode 100644 index 000000000..6b83afd58 --- /dev/null +++ b/src/boost/libs/contract/example/features/separate_body.hpp @@ -0,0 +1,88 @@ + +#ifndef SEPARATE_BODY_HPP_ +#define SEPARATE_BODY_HPP_ + +// Copyright (C) 2008-2018 Lorenzo Caminiti +// Distributed under the Boost Software License, Version 1.0 (see accompanying +// file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt). +// See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html + +#include <boost/contract.hpp> + +//[separate_body_hpp +class iarray : + private boost::contract::constructor_precondition<iarray> { +public: + void invariant() const { + BOOST_CONTRACT_ASSERT(size() <= capacity()); + } + + explicit iarray(unsigned max, unsigned count = 0) : + boost::contract::constructor_precondition<iarray>([&] { + BOOST_CONTRACT_ASSERT(count <= max); + }), + // Still, member initializations must be here. + values_(new int[max]), + capacity_(max) + { + boost::contract::check c = boost::contract::constructor(this) + .postcondition([&] { + BOOST_CONTRACT_ASSERT(capacity() == max); + BOOST_CONTRACT_ASSERT(size() == count); + }) + ; + constructor_body(max, count); // Separate constructor body impl. + } + + virtual ~iarray() { + boost::contract::check c = boost::contract::destructor(this); // Inv. + destructor_body(); // Separate destructor body implementation. + } + + virtual void push_back(int value, boost::contract::virtual_* v = 0) { + boost::contract::old_ptr<unsigned> old_size = + BOOST_CONTRACT_OLDOF(v, size()); + boost::contract::check c = boost::contract::public_function(v, this) + .precondition([&] { + BOOST_CONTRACT_ASSERT(size() < capacity()); + }) + .postcondition([&] { + BOOST_CONTRACT_ASSERT(size() == *old_size + 1); + }) + ; + push_back_body(value); // Separate member function body implementation. + } + +private: + // Contracts in class declaration (above), but body implementations are not. + void constructor_body(unsigned max, unsigned count); + void destructor_body(); + void push_back_body(int value); + + /* ... */ +//] + +public: + unsigned capacity() const { + // Check invariants. + boost::contract::check c = boost::contract::public_function(this); + return capacity_body(); + } + + unsigned size() const { + // Check invariants. + boost::contract::check c = boost::contract::public_function(this); + return size_body(); + } + +private: + unsigned size_body() const; + unsigned capacity_body() const; + + int* values_; + unsigned capacity_; + unsigned size_; +}; + +#endif // #include guard + diff --git a/src/boost/libs/contract/example/features/static_public.cpp b/src/boost/libs/contract/example/features/static_public.cpp new file mode 100644 index 000000000..146de0fa7 --- /dev/null +++ b/src/boost/libs/contract/example/features/static_public.cpp @@ -0,0 +1,69 @@ + +// Copyright (C) 2008-2018 Lorenzo Caminiti +// Distributed under the Boost Software License, Version 1.0 (see accompanying +// file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt). +// See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html + +#include <boost/contract.hpp> +#include <cassert> + +//[static_public +template<class C> +class make { +public: + static void static_invariant() { // Static class invariants. + BOOST_CONTRACT_ASSERT(instances() >= 0); + } + + // Contract for a static public function. + static int instances() { + // Explicit template parameter `make` (check static invariants). + boost::contract::check c = boost::contract::public_function<make>(); + + return instances_; // Function body. + } + + /* ... */ +//] + + make() : object() { + boost::contract::old_ptr<int> old_instances = + BOOST_CONTRACT_OLDOF(instances()); + boost::contract::check c = boost::contract::constructor(this) + .postcondition([&] { + BOOST_CONTRACT_ASSERT(instances() == *old_instances + 1); + }) + ; + + ++instances_; + } + + ~make() { + boost::contract::old_ptr<int> old_instances = + BOOST_CONTRACT_OLDOF(instances()); + boost::contract::check c = boost::contract::destructor(this) + .postcondition([&] { // (An example of destructor postconditions.) + BOOST_CONTRACT_ASSERT(instances() == *old_instances - 1); + }) + ; + + --instances_; + } + + C object; + +private: + static int instances_; +}; + +template<class C> +int make<C>::instances_ = 0; + +int main() { + struct x {}; + make<x> x1, x2, x3; + assert(make<x>::instances() == 3); + + return 0; +} + diff --git a/src/boost/libs/contract/example/features/throw_on_failure.cpp b/src/boost/libs/contract/example/features/throw_on_failure.cpp new file mode 100644 index 000000000..4cff315f2 --- /dev/null +++ b/src/boost/libs/contract/example/features/throw_on_failure.cpp @@ -0,0 +1,145 @@ + +// Copyright (C) 2008-2018 Lorenzo Caminiti +// Distributed under the Boost Software License, Version 1.0 (see accompanying +// file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt). +// See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html + +#include <boost/contract.hpp> +#include <iostream> +#include <cstring> +#include <cassert> + +//[throw_on_failure_class_begin +struct too_large_error {}; + +template<unsigned MaxSize> +class cstring + #define BASES private boost::contract::constructor_precondition<cstring< \ + MaxSize> > + : BASES +{ +//] +public: + typedef BOOST_CONTRACT_BASE_TYPES(BASES) base_types; + #undef BASES + +//[throw_on_failure_ctor +public: + /* implicit */ cstring(char const* chars) : + boost::contract::constructor_precondition<cstring>([&] { + BOOST_CONTRACT_ASSERT(chars); // Throw `assertion_failure`. + // Or, throw user-defined exception. + if(std::strlen(chars) > MaxSize) throw too_large_error(); + }) + { +//] + boost::contract::check c = boost::contract::constructor(this) + .postcondition([&] { + BOOST_CONTRACT_ASSERT(size() == std::strlen(chars)); + }) + ; + + size_ = std::strlen(chars); + for(unsigned i = 0; i < size_; ++i) chars_[i] = chars[i]; + chars_[size_] = '\0'; + } + +//[throw_on_failure_dtor +public: + void invariant() const { + if(size() > MaxSize) throw too_large_error(); // Throw user-defined ex. + BOOST_CONTRACT_ASSERT(chars_); // Or, throw `assertion_failure`. + BOOST_CONTRACT_ASSERT(chars_[size()] == '\0'); + } + + ~cstring() noexcept { // Exception specifiers apply to contract code. + // Check invariants. + boost::contract::check c = boost::contract::destructor(this); + } +//] + + unsigned size() const { + // Check invariants. + boost::contract::check c = boost::contract::public_function(this); + return size_; + } + +private: + char chars_[MaxSize + 1]; + unsigned size_; +//[throw_on_failure_class_end + /* ... */ +}; +//] + +void bad_throwing_handler() { // For docs only (not actually used here). + //[throw_on_failure_bad_handler + /* ... */ + + // Warning... might cause destructors to throw (unless declared noexcept). + boost::contract::set_invariant_failure( + [] (boost::contract::from) { + throw; // Throw no matter if from destructor, etc. + } + ); + + /* ... */ + //] +} + +//[throw_on_failure_handlers +int main() { + boost::contract::set_precondition_failure( + boost::contract::set_postcondition_failure( + boost::contract::set_invariant_failure( + boost::contract::set_old_failure( + [] (boost::contract::from where) { + if(where == boost::contract::from_destructor) { + // Shall not throw from C++ destructors. + std::clog << "ignored destructor contract failure" << std::endl; + } else throw; // Re-throw (assertion_failure, user-defined, etc.). + } + )))); + boost::contract::set_except_failure( + [] (boost::contract::from) { + // Already an active exception so shall not throw another... + std::clog << "ignored exception guarantee failure" << std::endl; + } + ); + boost::contract::set_check_failure( + [] { + // But now CHECK shall not be used in destructor implementations. + throw; // Re-throw (assertion_failure, user-defined, etc.). + } + ); + + /* ... */ +//] + + { + cstring<3> s("abc"); + assert(s.size() == 3); + } + + #ifndef BOOST_CONTRACT_NO_PRECONDITIONS + // These failures properly handled only when preconditions checked. + + try { + char* c = 0; + cstring<3> s(c); + assert(false); + } catch(boost::contract::assertion_failure const& error) { + // OK (expected). + std::clog << "ignored: " << error.what() << std::endl; + } catch(...) { assert(false); } + + try { + cstring<3> s("abcd"); + assert(false); + } catch(too_large_error const&) {} // OK (expected). + catch(...) { assert(false); } + #endif + + return 0; +} + diff --git a/src/boost/libs/contract/example/features/union.cpp b/src/boost/libs/contract/example/features/union.cpp new file mode 100644 index 000000000..0681c774e --- /dev/null +++ b/src/boost/libs/contract/example/features/union.cpp @@ -0,0 +1,134 @@ + +// Copyright (C) 2008-2018 Lorenzo Caminiti +// Distributed under the Boost Software License, Version 1.0 (see accompanying +// file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt). +// See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html + +#include <boost/contract.hpp> +#include <boost/config.hpp> +#include <cassert> + +#ifdef BOOST_GCC // G++ does not support static union members yet. + int instances_ = 0; +#endif + +//[union +union positive { +public: + static void static_invariant() { // Static class invariants (as usual). + BOOST_CONTRACT_ASSERT(instances() >= 0); + } + + void invariant() const { // Class invariants (as usual). + BOOST_CONTRACT_ASSERT(i_ > 0); + BOOST_CONTRACT_ASSERT(d_ > 0); + } + + // Contracts for constructor, as usual but... + explicit positive(int x) : d_(0) { + // ...unions cannot have bases so constructor preconditions here. + boost::contract::constructor_precondition<positive> pre([&] { + BOOST_CONTRACT_ASSERT(x > 0); + }); + boost::contract::old_ptr<int> old_instances = + BOOST_CONTRACT_OLDOF(instances()); + boost::contract::check c = boost::contract::constructor(this) + .postcondition([&] { + { int y; get(y); BOOST_CONTRACT_ASSERT(y == x); } + BOOST_CONTRACT_ASSERT(instances() == *old_instances + 1); + }) + ; + + i_ = x; + ++instances_; + } + + // Contracts for destructor (as usual). + ~positive() { + boost::contract::old_ptr<int> old_instances = + BOOST_CONTRACT_OLDOF(instances()); + boost::contract::check c = boost::contract::destructor(this) + .postcondition([&] { + BOOST_CONTRACT_ASSERT(instances() == *old_instances - 1); + }) + ; + + --instances_; + } + + // Contracts for public function (as usual, but no virtual or override). + void get(int& x) const { + boost::contract::check c = boost::contract::public_function(this) + .postcondition([&] { + BOOST_CONTRACT_ASSERT(x > 0); + }) + ; + + x = i_; + } + + // Contracts for static public function (as usual). + static int instances() { + boost::contract::check c = boost::contract::public_function<positive>(); + return instances_; + } + +private: + int i_; + double d_; + + /* ... */ +//] + +public: + explicit positive(double x) : d_(0) { + // Unions cannot have bases so constructor preconditions here. + boost::contract::constructor_precondition<positive> pre([&] { + BOOST_CONTRACT_ASSERT(x > 0); + }); + boost::contract::old_ptr<int> old_instances = + BOOST_CONTRACT_OLDOF(instances()); + boost::contract::check c = boost::contract::constructor(this) + .postcondition([&] { + { double y; get(y); BOOST_CONTRACT_ASSERT(y == x); } + BOOST_CONTRACT_ASSERT(instances() == *old_instances + 1); + }) + ; + + d_ = x; + ++instances_; + } + + void get(double& x) const { + boost::contract::check c = boost::contract::public_function(this) + .postcondition([&] { + BOOST_CONTRACT_ASSERT(x > 0); + }) + ; + + x = d_; + } + + #ifndef BOOST_GCC // G++ does not support static union members yet. + static int instances_; + #endif +}; + +#ifndef BOOST_GCC // G++ does not support static union members yet. + int positive::instances_ = 0; +#endif + +int main() { + { + positive p(123); + assert(p.instances() == 1); + { int y = -456; p.get(y); assert(y == 123); } + + positive q(1.23); + assert(q.instances() == 2); + { double y = -4.56; q.get(y); assert(y == 1.23); } + } + assert(positive::instances() == 0); + return 0; +} + diff --git a/src/boost/libs/contract/example/features/volatile.cpp b/src/boost/libs/contract/example/features/volatile.cpp new file mode 100644 index 000000000..eb9b2e710 --- /dev/null +++ b/src/boost/libs/contract/example/features/volatile.cpp @@ -0,0 +1,102 @@ + +// Copyright (C) 2008-2018 Lorenzo Caminiti +// Distributed under the Boost Software License, Version 1.0 (see accompanying +// file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt). +// See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html + +#include <boost/contract.hpp> +#include <cassert> + +//[volatile +class u { +public: + static void static_invariant(); // Static invariants. + void invariant() const volatile; // Volatile invariants. + void invariant() const; // Const invariants. + + u() { // Check static, volatile, and const invariants. + boost::contract::check c= boost::contract::constructor(this); + } + + ~u() { // Check static, volatile, and const invariants. + boost::contract::check c = boost::contract::destructor(this); + } + + void nc() { // Check static and const invariants. + boost::contract::check c = boost::contract::public_function(this); + } + + void c() const { // Check static and const invariants. + boost::contract::check c = boost::contract::public_function(this); + } + + void v() volatile { // Check static and volatile invariants. + boost::contract::check c = boost::contract::public_function(this); + } + + void cv() const volatile { // Check static and volatile invariants. + boost::contract::check c = boost::contract::public_function(this); + } + + static void s() { // Check static invariants only. + boost::contract::check c = boost::contract::public_function<u>(); + } +}; +//] + +bool static_inv_checked, cv_inv_checked, const_inv_checked; +void u::static_invariant() { static_inv_checked = true; } +void u::invariant() const volatile { cv_inv_checked = true; } +void u::invariant() const { const_inv_checked = true; } + +int main() { + #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS + { + static_inv_checked = cv_inv_checked = const_inv_checked = false; + u x; + assert(static_inv_checked); + assert(cv_inv_checked); + assert(const_inv_checked); + + static_inv_checked = cv_inv_checked = const_inv_checked = false; + x.nc(); + assert(static_inv_checked); + assert(!cv_inv_checked); + assert(const_inv_checked); + + static_inv_checked = cv_inv_checked = const_inv_checked = false; + x.c(); + assert(static_inv_checked); + assert(!cv_inv_checked); + assert(const_inv_checked); + + static_inv_checked = cv_inv_checked = const_inv_checked = false; + x.v(); + assert(static_inv_checked); + assert(cv_inv_checked); + assert(!const_inv_checked); + + static_inv_checked = cv_inv_checked = const_inv_checked = false; + x.cv(); + assert(static_inv_checked); + assert(cv_inv_checked); + assert(!const_inv_checked); + + static_inv_checked = cv_inv_checked = const_inv_checked = false; + x.s(); + assert(static_inv_checked); + assert(!cv_inv_checked); + assert(!const_inv_checked); + + static_inv_checked = cv_inv_checked = const_inv_checked = false; + } // Call destructor. + #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS + assert(static_inv_checked); + assert(cv_inv_checked); + assert(const_inv_checked); + #endif + #endif + + return 0; +} + diff --git a/src/boost/libs/contract/example/meyer97/stack3.cpp b/src/boost/libs/contract/example/meyer97/stack3.cpp new file mode 100644 index 000000000..0da895b4f --- /dev/null +++ b/src/boost/libs/contract/example/meyer97/stack3.cpp @@ -0,0 +1,192 @@ + +// Copyright (C) 2008-2018 Lorenzo Caminiti +// Distributed under the Boost Software License, Version 1.0 (see accompanying +// file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt). +// See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html + +//[meyer97_stack3 +// File: stack3.cpp +#include "stack4.hpp" +#include <boost/contract.hpp> +#include <boost/optional.hpp> +#include <cassert> + +// Dispenser LIFO with max capacity using error codes. +template<typename T> +class stack3 { + friend class boost::contract::access; + + void invariant() const { + if(!error()) { + BOOST_CONTRACT_ASSERT(count() >= 0); // Count non-negative. + BOOST_CONTRACT_ASSERT(count() <= capacity()); // Count bounded. + // Empty if no element. + BOOST_CONTRACT_ASSERT(empty() == (count() == 0)); + } + } + +public: + enum error_code { + no_error = 0, + overflow_error, + underflow_error, + size_error + }; + + /* Initialization */ + + // Create stack for max of n elems, if n < 0 set error (no preconditions). + explicit stack3(int n, T const& default_value = T()) : + stack_(0), error_(no_error) { + boost::contract::check c = boost::contract::constructor(this) + .postcondition([&] { + // Error if impossible. + BOOST_CONTRACT_ASSERT((n < 0) == (error() == size_error)); + // No error if possible. + BOOST_CONTRACT_ASSERT((n >= 0) == !error()); + // Created if no error. + if(!error()) BOOST_CONTRACT_ASSERT(capacity() == n); + }) + ; + + if(n >= 0) stack_ = stack4<T>(n); + else error_ = size_error; + } + + /* Access */ + + // Max number of stack elements. + int capacity() const { + // Check invariants. + boost::contract::check c = boost::contract::public_function(this); + return stack_.capacity(); + } + + // Number of stack elements. + int count() const { + // Check invariants. + boost::contract::check c = boost::contract::public_function(this); + return stack_.count(); + } + + // Top element if present, otherwise none and set error (no preconditions). + boost::optional<T const&> item() const { + boost::contract::check c = boost::contract::public_function(this) + .postcondition([&] { + // Error if impossible. + BOOST_CONTRACT_ASSERT(empty() == (error() == underflow_error)); + // No error if possible. + BOOST_CONTRACT_ASSERT(!empty() == !error()); + }) + ; + + if(!empty()) { + error_ = no_error; + return boost::optional<T const&>(stack_.item()); + } else { + error_ = underflow_error; + return boost::optional<T const&>(); + } + } + + /* Status Report */ + + // Error indicator set by various operations. + error_code error() const { + // Check invariants. + boost::contract::check c = boost::contract::public_function(this); + return error_; + } + + bool empty() const { + // Check invariants. + boost::contract::check c = boost::contract::public_function(this); + return stack_.empty(); + } + + bool full() const { + // Check invariants. + boost::contract::check c = boost::contract::public_function(this); + return stack_.full(); + } + + /* Element Change */ + + // Add x to top if capacity allows, otherwise set error (no preconditions). + void put(T const& x) { + boost::contract::old_ptr<bool> old_full = BOOST_CONTRACT_OLDOF(full()); + boost::contract::old_ptr<int> old_count = BOOST_CONTRACT_OLDOF(count()); + boost::contract::check c = boost::contract::public_function(this) + .postcondition([&] { + // Error if impossible. + BOOST_CONTRACT_ASSERT(*old_full == (error() == overflow_error)); + // No error if possible. + BOOST_CONTRACT_ASSERT(!*old_full == !error()); + if(!error()) { // If no error... + BOOST_CONTRACT_ASSERT(!empty()); // ...not empty. + BOOST_CONTRACT_ASSERT(*item() == x); // ...added to top. + // ...one more. + BOOST_CONTRACT_ASSERT(count() == *old_count + 1); + } + }) + ; + + if(full()) error_ = overflow_error; + else { + stack_.put(x); + error_ = no_error; + } + } + + // Remove top element if possible, otherwise set error (no preconditions). + void remove() { + boost::contract::old_ptr<bool> old_empty = + BOOST_CONTRACT_OLDOF(empty()); + boost::contract::old_ptr<int> old_count = BOOST_CONTRACT_OLDOF(count()); + boost::contract::check c = boost::contract::public_function(this) + .postcondition([&] { + // Error if impossible. + BOOST_CONTRACT_ASSERT(*old_empty == (error() == + underflow_error)); + // No error if possible. + BOOST_CONTRACT_ASSERT(!*old_empty == !error()); + if(!error()) { // If no error... + BOOST_CONTRACT_ASSERT(!full()); // ...not full. + // ...one less. + BOOST_CONTRACT_ASSERT(count() == *old_count - 1); + } + }) + ; + + if(empty()) error_ = underflow_error; + else { + stack_.remove(); + error_ = no_error; + } + } + +private: + stack4<T> stack_; + mutable error_code error_; +}; + +int main() { + stack3<int> s(3); + assert(s.capacity() == 3); + assert(s.count() == 0); + assert(s.empty()); + assert(!s.full()); + + s.put(123); + assert(!s.empty()); + assert(!s.full()); + assert(*s.item() == 123); + + s.remove(); + assert(s.empty()); + assert(!s.full()); + + return 0; +} +//] + diff --git a/src/boost/libs/contract/example/meyer97/stack4.e b/src/boost/libs/contract/example/meyer97/stack4.e new file mode 100644 index 000000000..85d6e539d --- /dev/null +++ b/src/boost/libs/contract/example/meyer97/stack4.e @@ -0,0 +1,201 @@ + +-- Copyright (C) 2008-2018 Lorenzo Caminiti +-- Distributed under the Boost Software License, Version 1.0 (see accompanying +-- file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt). +-- See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html + +//[meyer97_stack4_e +-- Extra spaces, newlines, etc. for visual alignment with this library code. + + + + + +indexing + destription: "Dispenser with LIFO access policy and a fixed max capacity." +class interface STACK4[G] creation make -- Interface only (no implementation). + + + + + + + +invariant + count_non_negative: count >= 0 + count_bounded: count <= capacity + empty_if_no_elements: empty = (count = 0) + + + +feature -- Initialization + + -- Allocate stack for a maximum of n elements. + make(n: INTEGER) is + require + non_negative_capacity: n >= 0 + ensure + capacity_set: capacity = n + end + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +feature -- Access + + -- Max number of stack elements. + capacity: INTEGER + + + + + + -- Number of stack elements. + count: INTEGER + + + + + + -- Top element. + item: G is + require + not_empty: not empty -- i.e., count > 0 + end + + + + + + +feature -- Status report + + -- Is stack empty? + empty: BOOLEAN is + ensure + empty_definition: result = (count = 0) + end + + + + + + + + + -- Is stack full? + full: BOOLEAN is + ensure + full_definition: result = (count = capacity) + end + + + + + + + + +feature -- Element change + + -- Add x on top. + put(x: G) is + require + not_full: not full + ensure + not_empty: not empty + added_to_top: item = x + one_more_item: count = old count + 1 + end + + + + + + + + + -- Remove top element. + remove is + require + not_empty: not empty -- i.e., count > 0 + ensure + not_full: not full + one_fewer_item: count = old count - 1 + + end + + + + + + + + + + + + + + + + + + + + + + + +end -- class interface STACK4 + +-- End. +//] + diff --git a/src/boost/libs/contract/example/meyer97/stack4.hpp b/src/boost/libs/contract/example/meyer97/stack4.hpp new file mode 100644 index 000000000..541625cc9 --- /dev/null +++ b/src/boost/libs/contract/example/meyer97/stack4.hpp @@ -0,0 +1,201 @@ + +// Copyright (C) 2008-2018 Lorenzo Caminiti +// Distributed under the Boost Software License, Version 1.0 (see accompanying +// file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt). +// See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html + +//[meyer97_stack4 +// File: stack4.hpp +#ifndef STACK4_HPP_ +#define STACK4_HPP_ + +#include <boost/contract.hpp> + +// Dispenser with LIFO access policy and fixed max capacity. +template<typename T> +class stack4 + #define BASES private boost::contract::constructor_precondition<stack4<T> > + : BASES +{ + friend boost::contract::access; + typedef BOOST_CONTRACT_BASE_TYPES(BASES) base_types; + #undef BASES + + void invariant() const { + BOOST_CONTRACT_ASSERT(count() >= 0); // Count non-negative. + BOOST_CONTRACT_ASSERT(count() <= capacity()); // Count bounded. + BOOST_CONTRACT_ASSERT(empty() == (count() == 0)); // Empty if no elem. + } + +public: + /* Initialization */ + + // Allocate static from a maximum of n elements. + explicit stack4(int n) : + boost::contract::constructor_precondition<stack4>([&] { + BOOST_CONTRACT_ASSERT(n >= 0); // Non-negative capacity. + }) + { + boost::contract::check c = boost::contract::constructor(this) + .postcondition([&] { + BOOST_CONTRACT_ASSERT(capacity() == n); // Capacity set. + }) + ; + + capacity_ = n; + count_ = 0; + array_ = new T[n]; + } + + // Deep copy via constructor. + /* implicit */ stack4(stack4 const& other) { + boost::contract::check c = boost::contract::constructor(this) + .postcondition([&] { + BOOST_CONTRACT_ASSERT(capacity() == other.capacity()); + BOOST_CONTRACT_ASSERT(count() == other.count()); + BOOST_CONTRACT_ASSERT_AXIOM(*this == other); + }) + ; + + capacity_ = other.capacity_; + count_ = other.count_; + array_ = new T[other.capacity_]; + for(int i = 0; i < other.count_; ++i) array_[i] = other.array_[i]; + } + + // Deep copy via assignment. + stack4& operator=(stack4 const& other) { + boost::contract::check c = boost::contract::public_function(this) + .postcondition([&] { + BOOST_CONTRACT_ASSERT(capacity() == other.capacity()); + BOOST_CONTRACT_ASSERT(count() == other.count()); + BOOST_CONTRACT_ASSERT_AXIOM(*this == other); + }) + ; + + delete[] array_; + capacity_ = other.capacity_; + count_ = other.count_; + array_ = new T[other.capacity_]; + for(int i = 0; i < other.count_; ++i) array_[i] = other.array_[i]; + return *this; + } + + // Destroy this stack. + virtual ~stack4() { + // Check invariants. + boost::contract::check c = boost::contract::destructor(this); + delete[] array_; + } + + /* Access */ + + // Max number of stack elements. + int capacity() const { + // Check invariants. + boost::contract::check c = boost::contract::public_function(this); + return capacity_; + } + + // Number of stack elements. + int count() const { + // Check invariants. + boost::contract::check c = boost::contract::public_function(this); + return count_; + } + + // Top element. + T const& item() const { + boost::contract::check c = boost::contract::public_function(this) + .precondition([&] { + BOOST_CONTRACT_ASSERT(!empty()); // Not empty (i.e., count > 0). + }) + ; + + return array_[count_ - 1]; + } + + /* Status Report */ + + // Is stack empty? + bool empty() const { + bool result; + boost::contract::check c = boost::contract::public_function(this) + .postcondition([&] { + // Empty definition. + BOOST_CONTRACT_ASSERT(result == (count() == 0)); + }) + ; + + return result = (count_ == 0); + } + + // Is stack full? + bool full() const { + bool result; + boost::contract::check c = boost::contract::public_function(this) + .postcondition([&] { + BOOST_CONTRACT_ASSERT( // Full definition. + result == (count() == capacity())); + }) + ; + + return result = (count_ == capacity_); + } + + /* Element Change */ + + // Add x on top. + void put(T const& x) { + boost::contract::old_ptr<int> old_count = BOOST_CONTRACT_OLDOF(count()); + boost::contract::check c = boost::contract::public_function(this) + .precondition([&] { + BOOST_CONTRACT_ASSERT(!full()); // Not full. + }) + .postcondition([&] { + BOOST_CONTRACT_ASSERT(!empty()); // Not empty. + BOOST_CONTRACT_ASSERT(item() == x); // Added to top. + BOOST_CONTRACT_ASSERT(count() == *old_count + 1); // One more. + }) + ; + + array_[count_++] = x; + } + + // Remove top element. + void remove() { + boost::contract::old_ptr<int> old_count = BOOST_CONTRACT_OLDOF(count()); + boost::contract::check c = boost::contract::public_function(this) + .precondition([&] { + BOOST_CONTRACT_ASSERT(!empty()); // Not empty (i.e., count > 0). + }) + .postcondition([&] { + BOOST_CONTRACT_ASSERT(!full()); // Not full. + BOOST_CONTRACT_ASSERT(count() == *old_count - 1); // One less. + }) + ; + + --count_; + } + + /* Friend Helpers */ + + friend bool operator==(stack4 const& left, stack4 const& right) { + boost::contract::check inv1 = boost::contract::public_function(&left); + boost::contract::check inv2 = boost::contract::public_function(&right); + if(left.count_ != right.count_) return false; + for(int i = 0; i < left.count_; ++i) { + if(left.array_[i] != right.array_[i]) return false; + } + return true; + } + +private: + int capacity_; + int count_; + T* array_; // Internally use C-style array. +}; + +#endif // #include guard +//] + diff --git a/src/boost/libs/contract/example/meyer97/stack4_main.cpp b/src/boost/libs/contract/example/meyer97/stack4_main.cpp new file mode 100644 index 000000000..0ea28896e --- /dev/null +++ b/src/boost/libs/contract/example/meyer97/stack4_main.cpp @@ -0,0 +1,30 @@ + +// Copyright (C) 2008-2018 Lorenzo Caminiti +// Distributed under the Boost Software License, Version 1.0 (see accompanying +// file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt). +// See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html + +//[meyer97_stack4_main +#include "stack4.hpp" +#include <cassert> + +int main() { + stack4<int> s(3); + assert(s.capacity() == 3); + assert(s.count() == 0); + assert(s.empty()); + assert(!s.full()); + + s.put(123); + assert(!s.empty()); + assert(!s.full()); + assert(s.item() == 123); + + s.remove(); + assert(s.empty()); + assert(!s.full()); + + return 0; +} +//] + diff --git a/src/boost/libs/contract/example/mitchell02/counter/counter.hpp b/src/boost/libs/contract/example/mitchell02/counter/counter.hpp new file mode 100644 index 000000000..659edbe9f --- /dev/null +++ b/src/boost/libs/contract/example/mitchell02/counter/counter.hpp @@ -0,0 +1,71 @@ + +// Copyright (C) 2008-2018 Lorenzo Caminiti +// Distributed under the Boost Software License, Version 1.0 (see accompanying +// file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt). +// See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html + +//[mitchell02_counter +#ifndef COUNTER_HPP_ +#define COUNTER_HPP_ + +#include "../observer/subject.hpp" +#include <boost/contract.hpp> + +class counter + #define BASES public subject + : BASES +{ + friend class boost::contract::access; + + typedef BOOST_CONTRACT_BASE_TYPES(BASES) base_types; + #undef BASES + +public: + /* Creation */ + + // Construct counter with specified value. + explicit counter(int a_value = 10) : value_(a_value) { + boost::contract::check c = boost::contract::constructor(this) + .postcondition([&] { + BOOST_CONTRACT_ASSERT(value() == a_value); // Value set. + }) + ; + } + + // Destroy counter. + virtual ~counter() { + // Could have omitted contracts here (nothing to check). + boost::contract::check c = boost::contract::destructor(this); + } + + /* Queries */ + + // Current counter value. + int value() const { + // Could have omitted contracts here (nothing to check). + boost::contract::check c = boost::contract::public_function(this); + return value_; + } + + /* Commands */ + + // Decrement counter value. + void decrement() { + boost::contract::old_ptr<int> old_value = BOOST_CONTRACT_OLDOF(value()); + boost::contract::check c = boost::contract::public_function(this) + .postcondition([&] { + BOOST_CONTRACT_ASSERT(value() == *old_value - 1); // Decrement. + }) + ; + + --value_; + notify(); // Notify all attached observers. + } + +private: + int value_; +}; + +#endif // #include guard +//] + diff --git a/src/boost/libs/contract/example/mitchell02/counter/decrement_button.hpp b/src/boost/libs/contract/example/mitchell02/counter/decrement_button.hpp new file mode 100644 index 000000000..ba8ae67e9 --- /dev/null +++ b/src/boost/libs/contract/example/mitchell02/counter/decrement_button.hpp @@ -0,0 +1,94 @@ + +// Copyright (C) 2008-2018 Lorenzo Caminiti +// Distributed under the Boost Software License, Version 1.0 (see accompanying +// file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt). +// See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html + +//[mitchell02_decrement_button +#ifndef DECREMENT_BUTTON_HPP_ +#define DECREMENT_BUTTON_HPP_ + +#include "push_button.hpp" +#include "counter.hpp" +#include "../observer/observer.hpp" +#include <boost/contract.hpp> +#include <boost/noncopyable.hpp> + +class decrement_button + #define BASES public push_button, public observer, \ + private boost::noncopyable + : BASES +{ + friend class boost::contract::access; + + typedef BOOST_CONTRACT_BASE_TYPES(BASES) base_types; + #undef BASES + + BOOST_CONTRACT_OVERRIDES(on_bn_clicked, up_to_date_with_subject, update); + +public: + /* Creation */ + + explicit decrement_button(counter& a_counter) : counter_(a_counter) { + boost::contract::check c = boost::contract::constructor(this) + .postcondition([&] { + // Enable iff positive value. + BOOST_CONTRACT_ASSERT(enabled() == (a_counter.value() > 0)); + }) + ; + counter_.attach(this); + } + + // Destroy button. + virtual ~decrement_button() { + // Could have omitted contracts here (nothing to check). + boost::contract::check c = boost::contract::destructor(this); + } + + /* Commands */ + + virtual void on_bn_clicked(boost::contract::virtual_* v = 0) + /* override */ { + boost::contract::old_ptr<int> old_value = + BOOST_CONTRACT_OLDOF(v, counter_.value()); + boost::contract::check c = boost::contract::public_function< + override_on_bn_clicked + >(v, &decrement_button::on_bn_clicked, this) + .postcondition([&] { + // Counter decremented. + BOOST_CONTRACT_ASSERT(counter_.value() == *old_value - 1); + }) + ; + counter_.decrement(); + } + + virtual bool up_to_date_with_subject(boost::contract::virtual_* v = 0) + const /* override */ { + bool result; + boost::contract::check c = boost::contract::public_function< + override_up_to_date_with_subject + >(v, result, &decrement_button::up_to_date_with_subject, this); + + return result = true; // For simplicity, assume always up-to-date. + } + + virtual void update(boost::contract::virtual_* v = 0) /* override */ { + boost::contract::check c = boost::contract::public_function< + override_update>(v, &decrement_button::update, this) + .postcondition([&] { + // Enabled iff positive value. + BOOST_CONTRACT_ASSERT(enabled() == (counter_.value() > 0)); + }) + ; + + if(counter_.value() == 0) disable(); + else enable(); + } + +private: + counter& counter_; +}; + +#endif // #include guard +//] + diff --git a/src/boost/libs/contract/example/mitchell02/counter/push_button.hpp b/src/boost/libs/contract/example/mitchell02/counter/push_button.hpp new file mode 100644 index 000000000..eaa66f79d --- /dev/null +++ b/src/boost/libs/contract/example/mitchell02/counter/push_button.hpp @@ -0,0 +1,86 @@ + +// Copyright (C) 2008-2018 Lorenzo Caminiti +// Distributed under the Boost Software License, Version 1.0 (see accompanying +// file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt). +// See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html + +//[mitchell02_push_button +#ifndef PUSH_BUTTON_HPP_ +#define PUSH_BUTTON_HPP_ + +#include <boost/contract.hpp> +#include <cassert> + +class push_button { +public: + // No inv and no bases so contracts optional if no pre, post, and override. + + /* Creation */ + + // Create an enabled button. + push_button() : enabled_(true) { + boost::contract::check c = boost::contract::constructor(this) + .postcondition([&] { + BOOST_CONTRACT_ASSERT(enabled()); // Enabled. + }) + ; + } + + // Destroy button. + virtual ~push_button() { + // Could have omitted contracts here (nothing to check). + boost::contract::check c = boost::contract::destructor(this); + } + + /* Queries */ + + // If button is enabled. + bool enabled() const { + // Could have omitted contracts here (nothing to check). + boost::contract::check c = boost::contract::public_function(this); + return enabled_; + } + + /* Commands */ + + // Enable button. + void enable() { + boost::contract::check c = boost::contract::public_function(this) + .postcondition([&] { + BOOST_CONTRACT_ASSERT(enabled()); // Enabled. + }) + ; + + enabled_ = true; + } + + // Disable button. + void disable() { + boost::contract::check c = boost::contract::public_function(this) + .postcondition([&] { + BOOST_CONTRACT_ASSERT(!enabled()); // Disabled. + }) + ; + + enabled_ = false; + } + + // Invoke externally when button clicked. + virtual void on_bn_clicked(boost::contract::virtual_* v = 0) = 0; + +private: + bool enabled_; +}; + +void push_button::on_bn_clicked(boost::contract::virtual_* v) { + boost::contract::check c = boost::contract::public_function(v, this) + .precondition([&] { + BOOST_CONTRACT_ASSERT(enabled()); // Enabled. + }) + ; + assert(false); +} + +#endif // #include guard +//] + diff --git a/src/boost/libs/contract/example/mitchell02/counter_main.cpp b/src/boost/libs/contract/example/mitchell02/counter_main.cpp new file mode 100644 index 000000000..ace7b8b92 --- /dev/null +++ b/src/boost/libs/contract/example/mitchell02/counter_main.cpp @@ -0,0 +1,81 @@ + +// Copyright (C) 2008-2018 Lorenzo Caminiti +// Distributed under the Boost Software License, Version 1.0 (see accompanying +// file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt). +// See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html + +//[mitchell02_counter_main +#include "counter/counter.hpp" +#include "counter/decrement_button.hpp" +#include "observer/observer.hpp" +#include <cassert> + +int test_counter; + +class view_of_counter + #define BASES public observer + : BASES +{ + friend class boost::contract::access; + + typedef BOOST_CONTRACT_BASE_TYPES(BASES) base_types; + #undef BASES + + BOOST_CONTRACT_OVERRIDES(up_to_date_with_subject, update) + +public: + /* Creation */ + + // Create view associated with given counter. + explicit view_of_counter(counter& a_counter) : counter_(a_counter) { + // Could have omitted contracts here (nothing to check). + boost::contract::check c = boost::contract::constructor(this); + + counter_.attach(this); + assert(counter_.value() == test_counter); + } + + // Destroy view. + virtual ~view_of_counter() { + // Could have omitted contracts here (nothing to check). + boost::contract::check c = boost::contract::destructor(this); + } + + /* Commands */ + + virtual bool up_to_date_with_subject(boost::contract::virtual_* v = 0) + const /* override */ { + bool result; + boost::contract::check c = boost::contract::public_function< + override_up_to_date_with_subject + >(v, result, &view_of_counter::up_to_date_with_subject, this); + + return result = true; // For simplicity, assume always up-to-date. + } + + virtual void update(boost::contract::virtual_* v = 0) /* override */ { + boost::contract::check c = boost::contract::public_function< + override_update>(v, &view_of_counter::update, this); + + assert(counter_.value() == test_counter); + } + +private: + counter& counter_; +}; + +int main() { + counter cnt(test_counter = 1); + view_of_counter view(cnt); + + decrement_button dec(cnt); + assert(dec.enabled()); + + test_counter--; + dec.on_bn_clicked(); + assert(!dec.enabled()); + + return 0; +} +//] + diff --git a/src/boost/libs/contract/example/mitchell02/courier.cpp b/src/boost/libs/contract/example/mitchell02/courier.cpp new file mode 100644 index 000000000..e04fa0d9e --- /dev/null +++ b/src/boost/libs/contract/example/mitchell02/courier.cpp @@ -0,0 +1,207 @@ + +// Copyright (C) 2008-2018 Lorenzo Caminiti +// Distributed under the Boost Software License, Version 1.0 (see accompanying +// file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt). +// See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html + +//[mitchell02_courier +#include <boost/contract.hpp> +#include <string> +#include <cassert> + +struct package { + double weight_kg; + std::string location; + double accepted_hour; + double delivered_hour; + + explicit package( + double _weight_kg, + std::string const& _location = "", + double _accepted_hour = 0.0, + double _delivered_hour = 0.0 + ) : + weight_kg(_weight_kg), + location(_location), + accepted_hour(_accepted_hour), + delivered_hour(_delivered_hour) + {} +}; + +// Courier for package delivery. +class courier + #define BASES private boost::contract::constructor_precondition<courier> + : BASES +{ + friend class boost::contract::access; + + typedef BOOST_CONTRACT_BASE_TYPES(BASES) base_types; + #undef BASES + + static void static_invariant() { + // Positive min. insurance. + BOOST_CONTRACT_ASSERT(min_insurance_usd >= 0.0); + } + + void invariant() const { + // Above min. insurance. + BOOST_CONTRACT_ASSERT(insurance_cover_usd() >= min_insurance_usd); + } + +public: + static double min_insurance_usd; + + /* Creation */ + + // Create courier with specified insurance value. + explicit courier(double _insurance_cover_usd = min_insurance_usd) : + boost::contract::constructor_precondition<courier>([&] { + // Positive insurance. + BOOST_CONTRACT_ASSERT(_insurance_cover_usd >= 0.0); + }), + insurance_cover_usd_(_insurance_cover_usd) + { + // Check invariants. + boost::contract::check c = boost::contract::constructor(this); + } + + // Destroy courier. + virtual ~courier() { + // Check invariants. + boost::contract::check c = boost::contract::destructor(this); + } + + /* Queries */ + + // Return insurance cover. + double insurance_cover_usd() const { + // Check invariants. + boost::contract::check c = boost::contract::public_function(this); + return insurance_cover_usd_; + } + + /* Commands */ + + // Deliver package to destination. + virtual void deliver( + package& package_delivery, + std::string const& destination, + boost::contract::virtual_* v = 0 + ) { + boost::contract::check c = boost::contract::public_function(v, this) + .precondition([&] { + // Within max weight of this delivery. + BOOST_CONTRACT_ASSERT(package_delivery.weight_kg < 5.0); + }) + .postcondition([&] { + // Within max delivery type. + BOOST_CONTRACT_ASSERT(double(package_delivery.delivered_hour - + package_delivery.accepted_hour) <= 3.0); + // Delivered at destination. + BOOST_CONTRACT_ASSERT(package_delivery.location == destination); + }) + ; + + package_delivery.location = destination; + // Delivery takes 2.5 hours. + package_delivery.delivered_hour = package_delivery.accepted_hour + 2.5; + } + +private: + double insurance_cover_usd_; +}; + +double courier::min_insurance_usd = 10.0e+6; + +// Different courier for package delivery. +class different_courier + #define BASES private boost::contract::constructor_precondition< \ + different_courier>, public courier + : BASES +{ + friend class boost::contract::access; + + typedef BOOST_CONTRACT_BASE_TYPES(BASES) base_types; // Subcontracting. + #undef BASES + + static void static_invariant() { + BOOST_CONTRACT_ASSERT( // Better insurance amount. + different_insurance_usd >= courier::min_insurance_usd); + } + + void invariant() const { + // Above different insurance value. + BOOST_CONTRACT_ASSERT(insurance_cover_usd() >= different_insurance_usd); + } + + BOOST_CONTRACT_OVERRIDE(deliver) + +public: + static double different_insurance_usd; + + /* Creation */ + + // Create courier with specified insurance value. + explicit different_courier( + double insurance_cover_usd = different_insurance_usd) : + boost::contract::constructor_precondition<different_courier>([&] { + // Positive insurance value. + BOOST_CONTRACT_ASSERT(insurance_cover_usd > 0.0); + }), + courier(insurance_cover_usd) + { + // Check invariants. + boost::contract::check c = boost::contract::constructor(this); + } + + // Destroy courier. + virtual ~different_courier() { + // Check invariants. + boost::contract::check c = boost::contract::destructor(this); + } + + /* Commands */ + + virtual void deliver( + package& package_delivery, + std::string const& destination, + boost::contract::virtual_* v = 0 + ) /* override */ { + boost::contract::check c = boost::contract::public_function< + override_deliver + >(v, &different_courier::deliver, this, package_delivery, destination) + .precondition([&] { + // Package can weight more (weaker precondition). + BOOST_CONTRACT_ASSERT(package_delivery.weight_kg <= 8.0); + }) + .postcondition([&] { + // Faster delivery (stronger postcondition). + BOOST_CONTRACT_ASSERT(double(package_delivery.delivered_hour - + package_delivery.accepted_hour) <= 2.0); + // Inherited "delivery at destination" postcondition. + }) + ; + + package_delivery.location = destination; + // Delivery takes 0.5 hours. + package_delivery.delivered_hour = package_delivery.accepted_hour + 0.5; + } +}; + +double different_courier::different_insurance_usd = 20.0e+6; + +int main() { + package cups(3.6, "store"); + courier c; + c.deliver(cups, "home"); + assert(cups.location == "home"); + + package desk(7.2, "store"); + different_courier dc; + dc.deliver(desk, "office"); + assert(desk.location == "office"); + + return 0; +} +//] + diff --git a/src/boost/libs/contract/example/mitchell02/customer_manager.cpp b/src/boost/libs/contract/example/mitchell02/customer_manager.cpp new file mode 100644 index 000000000..1d92120a3 --- /dev/null +++ b/src/boost/libs/contract/example/mitchell02/customer_manager.cpp @@ -0,0 +1,137 @@ + +// Copyright (C) 2008-2018 Lorenzo Caminiti +// Distributed under the Boost Software License, Version 1.0 (see accompanying +// file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt). +// See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html + +//[mitchell02_customer_manager +#include <boost/contract.hpp> +#include <string> +#include <map> +#include <utility> +#include <cassert> + +// Basic customer information. +struct customer_info { + friend class customer_manager; + + typedef std::string identifier; + + identifier id; + + explicit customer_info(identifier const& _id) : + id(_id), name_(), address_(), birthday_() {} + +private: + std::string name_; + std::string address_; + std::string birthday_; +}; + +// Manage customers. +class customer_manager { + friend class boost::contract::access; + + void invariant() const { + BOOST_CONTRACT_ASSERT(count() >= 0); // Non-negative count. + } + +public: + /* Creation */ + + customer_manager() { + // Check invariants. + boost::contract::check c = boost::contract::constructor(this); + } + + virtual ~customer_manager() { + // Check invariants. + boost::contract::check c = boost::contract::destructor(this); + } + + /* Basic Queries */ + + int count() const { + // Check invariants. + boost::contract::check c = boost::contract::public_function(this); + return customers_.size(); + } + + bool id_active(customer_info::identifier const& id) const { + // Check invariants. + boost::contract::check c = boost::contract::public_function(this); + return customers_.find(id) != customers_.cend(); + } + + /* Derived Queries */ + + std::string const& name_for(customer_info::identifier const& id) const { + boost::contract::check c = boost::contract::public_function(this) + .precondition([&] { + BOOST_CONTRACT_ASSERT(id_active(id)); // Active. + }) + ; + + // Find != end because of preconditions (no defensive programming). + return customers_.find(id)->second.name_; + } + + /* Commands */ + + void add(customer_info const& info) { + boost::contract::old_ptr<int> old_count = BOOST_CONTRACT_OLDOF(count()); + boost::contract::check c = boost::contract::public_function(this) + .precondition([&] { + // Not already active. + BOOST_CONTRACT_ASSERT(!id_active(info.id)); + }) + .postcondition([&] { + BOOST_CONTRACT_ASSERT(count() == *old_count + 1); // Count inc. + BOOST_CONTRACT_ASSERT(id_active(info.id)); // Activated. + }) + ; + + customers_.insert(std::make_pair(info.id, customer(info))); + } + + void set_name(customer_info::identifier const& id, + std::string const& name) { + boost::contract::check c = boost::contract::public_function(this) + .precondition([&] { + BOOST_CONTRACT_ASSERT(id_active(id)); // Already active. + }) + .postcondition([&] { + BOOST_CONTRACT_ASSERT(name_for(id) == name); // Name set. + }) + ; + + // Find != end because of precondition (no defensive programming). + customers_.find(id)->second.name_ = name; + } + +private: + class agent {}; // Customer agent. + + struct customer : customer_info { + agent managing_agent; + std::string last_contact; + + explicit customer(customer_info const& info) : customer_info(info), + managing_agent(), last_contact() {} + }; + + std::map<customer_info::identifier, customer> customers_; +}; + +int main() { + customer_manager m; + customer_info const js("john_smith_123"); + m.add(js); + m.set_name(js.id, "John Smith"); + assert(m.name_for(js.id) == "John Smith"); + assert(m.count() == 1); + assert(m.id_active(js.id)); + return 0; +} +//] + diff --git a/src/boost/libs/contract/example/mitchell02/dictionary.cpp b/src/boost/libs/contract/example/mitchell02/dictionary.cpp new file mode 100644 index 000000000..c2731a38f --- /dev/null +++ b/src/boost/libs/contract/example/mitchell02/dictionary.cpp @@ -0,0 +1,128 @@ + +// Copyright (C) 2008-2018 Lorenzo Caminiti +// Distributed under the Boost Software License, Version 1.0 (see accompanying +// file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt). +// See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html + +//[mitchell02_dictionary +#include <boost/contract.hpp> +#include <utility> +#include <map> +#include <cassert> + +template<typename K, typename T> +class dictionary { + friend class boost::contract::access; + + void invariant() const { + BOOST_CONTRACT_ASSERT(count() >= 0); // Non-negative count. + } + +public: + /* Creation */ + + // Create empty dictionary. + dictionary() { + boost::contract::check c = boost::contract::constructor(this) + .postcondition([&] { + BOOST_CONTRACT_ASSERT(count() == 0); // Empty. + }) + ; + } + + // Destroy dictionary. + virtual ~dictionary() { + // Check invariants. + boost::contract::check c = boost::contract::destructor(this); + } + + /* Basic Queries */ + + // Number of key entries. + int count() const { + // Check invariants. + boost::contract::check c = boost::contract::public_function(this); + return items_.size(); + } + + // Has entry for key? + bool has(K const& key) const { + bool result; + boost::contract::check c = boost::contract::public_function(this) + .postcondition([&] { + // Empty has no key. + if(count() == 0) BOOST_CONTRACT_ASSERT(!result); + }) + ; + + return result = (items_.find(key) != items_.end()); + } + + // Value for a given key. + T const& value_for(K const& key) const { + boost::contract::check c = boost::contract::public_function(this) + .precondition([&] { + BOOST_CONTRACT_ASSERT(has(key)); // Has key. + }) + ; + + // Find != end because of precondition (no defensive programming). + return items_.find(key)->second; + } + + /* Commands */ + + // Add value of a given key. + void put(K const& key, T const& value) { + boost::contract::old_ptr<int> old_count = BOOST_CONTRACT_OLDOF(count()); + boost::contract::check c = boost::contract::public_function(this) + .precondition([&] { + BOOST_CONTRACT_ASSERT(!has(key)); // Has not key already. + }) + .postcondition([&] { + BOOST_CONTRACT_ASSERT(count() == *old_count + 1); // Count inc. + BOOST_CONTRACT_ASSERT(has(key)); // Has key. + // Value set for key. + BOOST_CONTRACT_ASSERT(value_for(key) == value); + }) + ; + + items_.insert(std::make_pair(key, value)); + } + + // Remove value for given key. + void remove(K const& key) { + boost::contract::old_ptr<int> old_count = BOOST_CONTRACT_OLDOF(count()); + boost::contract::check c = boost::contract::public_function(this) + .precondition([&] { + BOOST_CONTRACT_ASSERT(has(key)); // Has key. + }) + .postcondition([&] { + BOOST_CONTRACT_ASSERT(count() == *old_count - 1); // Count dec. + BOOST_CONTRACT_ASSERT(!has(key)); // Has not key. + }) + ; + + items_.erase(key); + } + +private: + std::map<K, T> items_; +}; + +int main() { + std::string const js = "John Smith"; + + dictionary<std::string, int> ages; + assert(!ages.has(js)); + + ages.put(js, 23); + assert(ages.value_for(js) == 23); + + ages.remove(js); + assert(ages.count() == 0); + + return 0; +} +//] + diff --git a/src/boost/libs/contract/example/mitchell02/name_list.cpp b/src/boost/libs/contract/example/mitchell02/name_list.cpp new file mode 100644 index 000000000..fa394ed59 --- /dev/null +++ b/src/boost/libs/contract/example/mitchell02/name_list.cpp @@ -0,0 +1,145 @@ + +// Copyright (C) 2008-2018 Lorenzo Caminiti +// Distributed under the Boost Software License, Version 1.0 (see accompanying +// file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt). +// See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html + +//[mitchell02_name_list +#include <boost/contract.hpp> +#include <string> +#include <vector> +#include <algorithm> +#include <cassert> + +// List of names. +class name_list { + friend class boost::contract::access; + + void invariant() const { + BOOST_CONTRACT_ASSERT(count() >= 0); // Non-negative count. + } + +public: + /* Creation */ + + // Create an empty list. + name_list() { + boost::contract::check c = boost::contract::constructor(this) + .postcondition([&] { + BOOST_CONTRACT_ASSERT(count() == 0); // Empty list. + }) + ; + } + + // Destroy list. + virtual ~name_list() { + // Check invariants. + boost::contract::check c = boost::contract::destructor(this); + } + + /* Basic Queries */ + + // Number of names in list. + int count() const { + // Check invariants. + boost::contract::check c = boost::contract::public_function(this); + return names_.size(); + } + + // Is name in list? + bool has(std::string const& name) const { + bool result; + boost::contract::check c = boost::contract::public_function(this) + .postcondition([&] { + // If empty, has not. + if(count() == 0) BOOST_CONTRACT_ASSERT(!result); + }) + ; + + return result = names_.cend() != std::find(names_.cbegin(), + names_.cend(), name); + } + + /* Commands */ + + // Add name to list, if name not already in list. + virtual void put(std::string const& name, + boost::contract::virtual_* v = 0) { + boost::contract::old_ptr<bool> old_has_name = + BOOST_CONTRACT_OLDOF(v, has(name)); + boost::contract::old_ptr<int> old_count = + BOOST_CONTRACT_OLDOF(v, count()); + boost::contract::check c = boost::contract::public_function(v, this) + .precondition([&] { + BOOST_CONTRACT_ASSERT(!has(name)); // Not already in list. + }) + .postcondition([&] { + if(!*old_has_name) { // If-guard allows to relax subcontracts. + BOOST_CONTRACT_ASSERT(has(name)); // Name in list. + BOOST_CONTRACT_ASSERT(count() == *old_count + 1); // Inc. + } + }) + ; + + names_.push_back(name); + } + +private: + std::vector<std::string> names_; +}; + +class relaxed_name_list + #define BASES public name_list + : BASES +{ + friend class boost::contract::access; + + typedef BOOST_CONTRACT_BASE_TYPES(BASES) base_types; // Subcontracting. + #undef BASES + + BOOST_CONTRACT_OVERRIDE(put); + +public: + /* Commands */ + + // Add name to list, or do nothing if name already in list (relaxed). + void put(std::string const& name, + boost::contract::virtual_* v = 0) /* override */ { + boost::contract::old_ptr<bool> old_has_name = + BOOST_CONTRACT_OLDOF(v, has(name)); + boost::contract::old_ptr<int> old_count = + BOOST_CONTRACT_OLDOF(v, count()); + boost::contract::check c = boost::contract::public_function< + override_put>(v, &relaxed_name_list::put, this, name) + .precondition([&] { // Relax inherited preconditions. + BOOST_CONTRACT_ASSERT(has(name)); // Already in list. + }) + .postcondition([&] { // Inherited post. not checked given if-guard. + if(*old_has_name) { + // Count unchanged if name already in list. + BOOST_CONTRACT_ASSERT(count() == *old_count); + } + }) + ; + + if(!has(name)) name_list::put(name); // Else, do nothing. + } +}; + +int main() { + std::string const js = "John Smith"; + + relaxed_name_list rl; + rl.put(js); + assert(rl.has(js)); + rl.put(js); // OK, relaxed contracts allow calling this again (do nothing). + + name_list nl; + nl.put(js); + assert(nl.has(js)); + // nl.put(js); // Error, contracts do not allow calling this again. + + return 0; +} +//] + diff --git a/src/boost/libs/contract/example/mitchell02/observer/observer.hpp b/src/boost/libs/contract/example/mitchell02/observer/observer.hpp new file mode 100644 index 000000000..aa8a91ed0 --- /dev/null +++ b/src/boost/libs/contract/example/mitchell02/observer/observer.hpp @@ -0,0 +1,59 @@ + +// Copyright (C) 2008-2018 Lorenzo Caminiti +// Distributed under the Boost Software License, Version 1.0 (see accompanying +// file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt). +// See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html + +//[mitchell02_observer +#ifndef OBSERVER_HPP_ +#define OBSERVER_HPP_ + +#include <boost/contract.hpp> +#include <cassert> + +// Observer. +class observer { + friend class subject; +public: + // No inv and no bases so contracts optional if no pre, post, and override. + + /* Creation */ + + observer() { + // Could have omitted contracts here (nothing to check). + boost::contract::check c = boost::contract::constructor(this); + } + + virtual ~observer() { + // Could have omitted contracts here (nothing to check). + boost::contract::check c = boost::contract::destructor(this); + } + + /* Commands */ + + // If up-to-date with related subject. + virtual bool up_to_date_with_subject(boost::contract::virtual_* v = 0) + const = 0; + + // Update this observer. + virtual void update(boost::contract::virtual_* v = 0) = 0; +}; + +bool observer::up_to_date_with_subject(boost::contract::virtual_* v) const { + boost::contract::check c = boost::contract::public_function(v, this); + assert(false); + return false; +} + +void observer::update(boost::contract::virtual_* v) { + boost::contract::check c = boost::contract::public_function(v, this) + .postcondition([&] { + BOOST_CONTRACT_ASSERT(up_to_date_with_subject()); // Up-to-date. + }) + ; + assert(false); +} + +#endif // #include guard +//] + diff --git a/src/boost/libs/contract/example/mitchell02/observer/subject.hpp b/src/boost/libs/contract/example/mitchell02/observer/subject.hpp new file mode 100644 index 000000000..12aeae71b --- /dev/null +++ b/src/boost/libs/contract/example/mitchell02/observer/subject.hpp @@ -0,0 +1,165 @@ + +// Copyright (C) 2008-2018 Lorenzo Caminiti +// Distributed under the Boost Software License, Version 1.0 (see accompanying +// file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt). +// See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html + +//[mitchell02_subject +#ifndef SUBJECT_HPP_ +#define SUBJECT_HPP_ + +#include "observer.hpp" +#include <boost/contract.hpp> +#include <vector> +#include <algorithm> +#include <cassert> + +// Subject for observer design pattern. +class subject { + friend class boost::contract::access; + + void invariant() const { + BOOST_CONTRACT_ASSERT_AUDIT(all_observers_valid(observers())); // Valid. + } + +public: + /* Creation */ + + // Construct subject with no observer. + subject() { + // Check invariant. + boost::contract::check c = boost::contract::constructor(this); + } + + // Destroy subject. + virtual ~subject() { + // Check invariant. + boost::contract::check c = boost::contract::destructor(this); + } + + /* Queries */ + + // If given object is attached. + bool attached(observer const* ob) const { + boost::contract::check c = boost::contract::public_function(this) + .precondition([&] { + BOOST_CONTRACT_ASSERT(ob); // Not null. + }) + ; + + return std::find(observers_.cbegin(), observers_.cend(), ob) != + observers_.cend(); + } + + /* Commands */ + + // Attach given object as an observer. + void attach(observer* ob) { + boost::contract::old_ptr<std::vector<observer const*> > old_observers; + #ifdef BOOST_CONTRACT_AUDITS + old_observers = BOOST_CONTRACT_OLDOF(observers()); + #endif + boost::contract::check c = boost::contract::public_function(this) + .precondition([&] { + BOOST_CONTRACT_ASSERT(ob); // Not null. + BOOST_CONTRACT_ASSERT(!attached(ob)); // Not already attached. + }) + .postcondition([&] { + BOOST_CONTRACT_ASSERT(attached(ob)); // Attached. + // Others not changed (frame rule). + BOOST_CONTRACT_ASSERT_AUDIT(other_observers_unchanged( + *old_observers, observers(), ob)); + }) + ; + + observers_.push_back(ob); + } + +protected: + // Contracts could have been omitted for protected/private with no pre/post. + + /* Queries */ + + // All observers attached to this subject. + std::vector<observer const*> observers() const { + std::vector<observer const*> obs; + for(std::vector<observer*>::const_iterator i = observers_.cbegin(); + i != observers_.cend(); ++i) { + obs.push_back(*i); + } + return obs; + } + + /* Commands */ + + // Update all attached observers. + void notify() { + // Protected members use `function` (no inv and no subcontracting). + boost::contract::check c = boost::contract::function() + .postcondition([&] { + // All updated. + BOOST_CONTRACT_ASSERT_AUDIT(all_observers_updated(observers())); + }) + ; + + for(std::vector<observer*>::iterator i = observers_.begin(); + i != observers_.end(); ++i) { + // Class invariants ensure no null pointers in observers but class + // invariants not checked for non-public functions so assert here. + assert(*i); // Pointer not null (defensive programming). + (*i)->update(); + } + } + +private: + /* Contract Helpers */ + + static bool all_observers_valid(std::vector<observer const*> const& obs) { + for(std::vector<observer const*>::const_iterator i = obs.cbegin(); + i != obs.cend(); ++i) { + if(!*i) return false; + } + return true; + } + + static bool other_observers_unchanged( + std::vector<observer const*> const& old_obs, + std::vector<observer const*> const& new_obs, + observer const* ob + ) { + // Private members use `function` (no inv and no subcontracting). + boost::contract::check c = boost::contract::function() + .precondition([&] { + BOOST_CONTRACT_ASSERT(ob); // Not null. + }) + ; + + std::vector<observer const*> remaining = new_obs; + std::remove(remaining.begin(), remaining.end(), ob); + + std::vector<observer const*>::const_iterator remaining_it = + remaining.begin(); + std::vector<observer const*>::const_iterator old_it = old_obs.begin(); + while(remaining.cend() != remaining_it && old_obs.cend() != old_it) { + if(*remaining_it != *old_it) return false; + ++remaining_it; + ++old_it; + } + return true; + } + + static bool all_observers_updated(std::vector<observer const*> const& obs) { + for(std::vector<observer const*>::const_iterator i = obs.cbegin(); + i != obs.cend(); ++i) { + if(!*i) return false; + if(!(*i)->up_to_date_with_subject()) return false; + } + return true; + } + + std::vector<observer*> observers_; +}; + +#endif // #include guard +//] + diff --git a/src/boost/libs/contract/example/mitchell02/observer_main.cpp b/src/boost/libs/contract/example/mitchell02/observer_main.cpp new file mode 100644 index 000000000..0f6c1a5b8 --- /dev/null +++ b/src/boost/libs/contract/example/mitchell02/observer_main.cpp @@ -0,0 +1,118 @@ + +// Copyright (C) 2008-2018 Lorenzo Caminiti +// Distributed under the Boost Software License, Version 1.0 (see accompanying +// file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt). +// See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html + +//[mitchell02_observer_main +#include "observer/observer.hpp" +#include "observer/subject.hpp" +#include <boost/contract.hpp> +#include <cassert> + +int test_state; // For testing only. + +// Implement an actual subject. +class concrete_subject + #define BASES public subject + : BASES +{ + friend class boost::contract::access; + + typedef BOOST_CONTRACT_BASE_TYPES(BASES) base_types; // Subcontracting. + #undef BASES + +public: + typedef int state; // Some state being observed. + + concrete_subject() : state_() { + // Could have omitted contracts here (nothing to check). + boost::contract::check c = boost::contract::constructor(this); + } + + virtual ~concrete_subject() { + // Could have omitted contracts here (nothing to check). + boost::contract::check c = boost::contract::destructor(this); + } + + void set_state(state const& new_state) { + // Could have omitted contracts here (nothing to check). + boost::contract::check c = boost::contract::public_function(this); + + state_ = new_state; + assert(state_ == test_state); + notify(); // Notify all observers. + } + + state get_state() const { + // Could have omitted contracts here (nothing to check). + boost::contract::check c = boost::contract::public_function(this); + return state_; + } + +private: + state state_; +}; + +// Implement an actual observer. +class concrete_observer + #define BASES public observer + : BASES +{ + friend class boost::contract::access; + + typedef BOOST_CONTRACT_BASE_TYPES(BASES) base_types; // Subcontracting. + #undef BASES + + BOOST_CONTRACT_OVERRIDES(up_to_date_with_subject, update) + +public: + // Create concrete observer. + explicit concrete_observer(concrete_subject const& subj) : + subject_(subj), observed_state_() { + // Could have omitted contracts here (nothing to check). + boost::contract::check c = boost::contract::constructor(this); + } + + virtual ~concrete_observer() { + // Could have omitted contracts here (nothing to check). + boost::contract::check c = boost::contract::destructor(this); + } + + // Implement base virtual functions. + + bool up_to_date_with_subject(boost::contract::virtual_* v = 0) + const /* override */ { + bool result; + boost::contract::check c = boost::contract::public_function< + override_up_to_date_with_subject + >(v, result, &concrete_observer::up_to_date_with_subject, this); + + return result = true; // For simplicity, assume always up-to-date. + } + + void update(boost::contract::virtual_* v = 0) /* override */ { + boost::contract::check c = boost::contract::public_function< + override_update>(v, &concrete_observer::update, this); + + observed_state_ = subject_.get_state(); + assert(observed_state_ == test_state); + } + +private: + concrete_subject const& subject_; + concrete_subject::state observed_state_; +}; + +int main() { + concrete_subject subj; + concrete_observer ob(subj); + subj.attach(&ob); + + subj.set_state(test_state = 123); + subj.set_state(test_state = 456); + + return 0; +} +//] + diff --git a/src/boost/libs/contract/example/mitchell02/simple_queue.cpp b/src/boost/libs/contract/example/mitchell02/simple_queue.cpp new file mode 100644 index 000000000..e0250137f --- /dev/null +++ b/src/boost/libs/contract/example/mitchell02/simple_queue.cpp @@ -0,0 +1,219 @@ + +// Copyright (C) 2008-2018 Lorenzo Caminiti +// Distributed under the Boost Software License, Version 1.0 (see accompanying +// file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt). +// See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html + +//[mitchell02_simple_queue +#include <boost/contract.hpp> +#include <boost/optional.hpp> +#include <vector> +#include <cassert> + +template<typename T> +class simple_queue + #define BASES private boost::contract::constructor_precondition< \ + simple_queue<T> > + : BASES +{ + friend class boost::contract::access; + + typedef BOOST_CONTRACT_BASE_TYPES(BASES) base_types; + #undef BASES + + void invariant() const { + BOOST_CONTRACT_ASSERT(count() >= 0); // Non-negative count. + } + +public: + /* Creation */ + + // Create empty queue. + explicit simple_queue(int a_capacity) : + boost::contract::constructor_precondition<simple_queue>([&] { + BOOST_CONTRACT_ASSERT(a_capacity > 0); // Positive capacity. + }) + { + boost::contract::check c = boost::contract::constructor(this) + .postcondition([&] { + // Capacity set. + BOOST_CONTRACT_ASSERT(capacity() == a_capacity); + BOOST_CONTRACT_ASSERT(is_empty()); // Empty. + }) + ; + + items_.reserve(a_capacity); + } + + // Destroy queue. + virtual ~simple_queue() { + // Check invariants. + boost::contract::check c = boost::contract::destructor(this); + } + + /* Basic Queries */ + + // Items in queue (in their order). + // (Somewhat exposes implementation but allows to check more contracts.) + std::vector<T> const& items() const { + // Check invariants. + boost::contract::check c = boost::contract::public_function(this); + return items_; + } + + // Max number of items queue can hold. + int capacity() const { + // Check invariants. + boost::contract::check c = boost::contract::public_function(this); + return items_.capacity(); + } + + /* Derived Queries */ + + // Number of items. + int count() const { + int result; + boost::contract::check c = boost::contract::public_function(this) + .postcondition([&] { + // Return items count. + BOOST_CONTRACT_ASSERT(result == int(items().size())); + }) + ; + + return result = items_.size(); + } + + // Item at head. + T const& head() const { + boost::optional<T const&> result; + boost::contract::check c = boost::contract::public_function(this) + .precondition([&] { + BOOST_CONTRACT_ASSERT(!is_empty()); // Not empty. + }) + .postcondition([&] { + // Return item on top. + BOOST_CONTRACT_ASSERT(*result == items().at(0)); + }) + ; + + return *(result = items_.at(0)); + } + + // If queue contains no item. + bool is_empty() const { + bool result; + boost::contract::check c = boost::contract::public_function(this) + .postcondition([&] { + // Consistent with count. + BOOST_CONTRACT_ASSERT(result == (count() == 0)); + }) + ; + + return result = (items_.size() == 0); + } + + // If queue has no room for another item. + bool is_full() const { + bool result; + boost::contract::check c = boost::contract::public_function(this) + .postcondition([&] { + BOOST_CONTRACT_ASSERT( // Consistent with size and capacity. + result == (capacity() == int(items().size()))); + }) + ; + + return result = (items_.size() == items_.capacity()); + } + + /* Commands */ + + // Remove head itme and shift all other items. + void remove() { + // Expensive all_equal postcond. and old_items copy might be skipped. + boost::contract::old_ptr<std::vector<T> > old_items; + #ifdef BOOST_CONTRACT_AUDIITS + = BOOST_CONTRACT_OLDOF(items()) + #endif // Else, leave old pointer null... + ; + boost::contract::old_ptr<int> old_count = BOOST_CONTRACT_OLDOF(count()); + boost::contract::check c = boost::contract::public_function(this) + .precondition([&] { + BOOST_CONTRACT_ASSERT(!is_empty()); // Not empty. + }) + .postcondition([&] { + BOOST_CONTRACT_ASSERT(count() == *old_count - 1); // Count dec. + // ...following skipped #ifndef AUDITS. + if(old_items) all_equal(items(), *old_items, /* shifted = */ 1); + }) + ; + + items_.erase(items_.begin()); + } + + // Add item to tail. + void put(T const& item) { + // Expensive all_equal postcond. and old_items copy might be skipped. + boost::contract::old_ptr<std::vector<T> > old_items; + #ifdef BOOST_CONTRACT_AUDITS + = BOOST_CONTRACT_OLDOF(items()) + #endif // Else, leave old pointer null... + ; + boost::contract::old_ptr<int> old_count = BOOST_CONTRACT_OLDOF(count()); + boost::contract::check c = boost::contract::public_function(this) + .precondition([&] { + BOOST_CONTRACT_ASSERT(count() < capacity()); // Room for add. + }) + .postcondition([&] { + BOOST_CONTRACT_ASSERT(count() == *old_count + 1); // Count inc. + // Second to last item. + BOOST_CONTRACT_ASSERT(items().at(count() - 1) == item); + // ...following skipped #ifndef AUDITS. + if(old_items) all_equal(items(), *old_items); + }) + ; + + items_.push_back(item); + } + +private: + // Contract helper. + static bool all_equal(std::vector<T> const& left, + std::vector<T> const& right, unsigned offset = 0) { + boost::contract::check c = boost::contract::function() + .precondition([&] { + // Correct offset. + BOOST_CONTRACT_ASSERT(right.size() == left.size() + offset); + }) + ; + + for(unsigned i = offset; i < right.size(); ++i) { + if(left.at(i - offset) != right.at(i)) return false; + } + return true; + } + + std::vector<T> items_; +}; + +int main() { + simple_queue<int> q(10); + q.put(123); + q.put(456); + + assert(q.capacity() == 10); + assert(q.head() == 123); + + assert(!q.is_empty()); + assert(!q.is_full()); + + std::vector<int> const& items = q.items(); + assert(items.at(0) == 123); + assert(items.at(1) == 456); + + q.remove(); + assert(q.count() == 1); + + return 0; +} +//] + diff --git a/src/boost/libs/contract/example/mitchell02/stack.cpp b/src/boost/libs/contract/example/mitchell02/stack.cpp new file mode 100644 index 000000000..a0bd6b144 --- /dev/null +++ b/src/boost/libs/contract/example/mitchell02/stack.cpp @@ -0,0 +1,138 @@ + +// Copyright (C) 2008-2018 Lorenzo Caminiti +// Distributed under the Boost Software License, Version 1.0 (see accompanying +// file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt). +// See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html + +//[mitchell02_stack +#include <boost/contract.hpp> +#include <boost/optional.hpp> +#include <vector> +#include <cassert> + +template<typename T> +class stack { + friend class boost::contract::access; + + void invariant() const { + BOOST_CONTRACT_ASSERT(count() >= 0); // Non-negative count. + } + +public: + /* Creation */ + + // Create empty stack. + stack() { + boost::contract::check c = boost::contract::constructor(this) + .postcondition([&] { + BOOST_CONTRACT_ASSERT(count() == 0); // Empty. + }) + ; + } + + // Destroy stack. + virtual ~stack() { + // Check invariants. + boost::contract::check c = boost::contract::destructor(this); + } + + /* Basic Queries */ + + // Number of items. + int count() const { + // Check invariants. + boost::contract::check c = boost::contract::public_function(this); + return items_.size(); + } + + // Item at index in [1, count()] (as in Eiffel). + T const& item_at(int index) const { + boost::contract::check c = boost::contract::public_function(this) + .precondition([&] { + BOOST_CONTRACT_ASSERT(index > 0); // Positive index. + BOOST_CONTRACT_ASSERT(index <= count()); // Index within count. + }) + ; + + return items_[index - 1]; + } + + /* Derived Queries */ + + // If no items. + bool is_empty() const { + bool result; + boost::contract::check c = boost::contract::public_function(this) + .postcondition([&] { + // Consistent with count. + BOOST_CONTRACT_ASSERT(result == (count() == 0)); + }) + ; + + return result = (count() == 0); + } + + // Top item. + T const& item() const { + boost::optional<T const&> result; // Avoid extra construction of T. + boost::contract::check c = boost::contract::public_function(this) + .precondition([&] { + BOOST_CONTRACT_ASSERT(count() > 0); // Not empty. + }) + .postcondition([&] { + // Item on top. + BOOST_CONTRACT_ASSERT(*result == item_at(count())); + }) + ; + + return *(result = item_at(count())); + } + + /* Commands */ + + // Push item to the top. + void put(T const& new_item) { + boost::contract::old_ptr<int> old_count = BOOST_CONTRACT_OLDOF(count()); + boost::contract::check c = boost::contract::public_function(this) + .postcondition([&] { + BOOST_CONTRACT_ASSERT(count() == *old_count + 1); // Count inc. + BOOST_CONTRACT_ASSERT(item() == new_item); // Item set. + }) + ; + + items_.push_back(new_item); + } + + // Pop top item. + void remove() { + boost::contract::old_ptr<int> old_count = BOOST_CONTRACT_OLDOF(count()); + boost::contract::check c = boost::contract::public_function(this) + .precondition([&] { + BOOST_CONTRACT_ASSERT(count() > 0); // Not empty. + }) + .postcondition([&] { + BOOST_CONTRACT_ASSERT(count() == *old_count - 1); // Count dec. + }) + ; + + items_.pop_back(); + } + +private: + std::vector<T> items_; +}; + +int main() { + stack<int> s; + assert(s.count() == 0); + + s.put(123); + assert(s.item() == 123); + + s.remove(); + assert(s.is_empty()); + + return 0; +} +//] + diff --git a/src/boost/libs/contract/example/n1962/circle.cpp b/src/boost/libs/contract/example/n1962/circle.cpp new file mode 100644 index 000000000..21f9345c5 --- /dev/null +++ b/src/boost/libs/contract/example/n1962/circle.cpp @@ -0,0 +1,80 @@ + +// Copyright (C) 2008-2018 Lorenzo Caminiti +// Distributed under the Boost Software License, Version 1.0 (see accompanying +// file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt). +// See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html + +//[n1962_circle +#include <boost/contract.hpp> +#include <cassert> + +class shape { +public: + virtual ~shape() {} + + virtual unsigned compute_area(boost::contract::virtual_* v = 0) const = 0; +}; + +unsigned shape::compute_area(boost::contract::virtual_* v) const { + unsigned result; + boost::contract::check c = boost::contract::public_function(v, result, this) + .postcondition([&] (int const& result) { + BOOST_CONTRACT_ASSERT(result > 0); + }) + ; + assert(false); + return result; +} + +class circle + #define BASES public shape + : BASES +{ + friend class boost::contract::access; + + typedef BOOST_CONTRACT_BASE_TYPES(BASES) base_types; + #undef BASES + + BOOST_CONTRACT_OVERRIDE(compute_area); + +public: + static int const pi = 3; // Truncated to int from 3.14... + + explicit circle(unsigned a_radius) : radius_(a_radius) { + boost::contract::check c = boost::contract::constructor(this) + .postcondition([&] { + BOOST_CONTRACT_ASSERT(radius() == a_radius); + }) + ; + } + + virtual unsigned compute_area(boost::contract::virtual_* v = 0) const + /* override */ { + unsigned result; + boost::contract::check c = boost::contract::public_function< + override_compute_area>(v, result, &circle::compute_area, this) + .postcondition([&] (unsigned const& result) { + BOOST_CONTRACT_ASSERT(result == pi * radius() * radius()); + }) + ; + + return result = pi * radius() * radius(); + } + + unsigned radius() const { + boost::contract::check c = boost::contract::public_function(this); + return radius_; + } + +private: + unsigned radius_; +}; + +int main() { + circle c(2); + assert(c.radius() == 2); + assert(c.compute_area() == 12); + return 0; +} +//] + diff --git a/src/boost/libs/contract/example/n1962/equal.cpp b/src/boost/libs/contract/example/n1962/equal.cpp new file mode 100644 index 000000000..c1706023a --- /dev/null +++ b/src/boost/libs/contract/example/n1962/equal.cpp @@ -0,0 +1,51 @@ + +// Copyright (C) 2008-2018 Lorenzo Caminiti +// Distributed under the Boost Software License, Version 1.0 (see accompanying +// file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt). +// See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html + +//[n1962_equal +#include <boost/contract.hpp> +#include <cassert> + +// Forward declaration because == and != contracts use one another's function. +template<typename T> +bool operator==(T const& left, T const& right); + +template<typename T> +bool operator!=(T const& left, T const& right) { + bool result; + boost::contract::check c = boost::contract::function() + .postcondition([&] { + BOOST_CONTRACT_ASSERT(result == !(left == right)); + }) + ; + + return result = (left.value != right.value); +} + +template<typename T> +bool operator==(T const& left, T const& right) { + bool result; + boost::contract::check c = boost::contract::function() + .postcondition([&] { + BOOST_CONTRACT_ASSERT(result == !(left != right)); + }) + ; + + return result = (left.value == right.value); +} + +struct number { int value; }; + +int main() { + number n; + n.value = 123; + + assert((n == n) == true); // Explicitly call operator==. + assert((n != n) == false); // Explicitly call operator!=. + + return 0; +} +//] + diff --git a/src/boost/libs/contract/example/n1962/factorial.cpp b/src/boost/libs/contract/example/n1962/factorial.cpp new file mode 100644 index 000000000..98f12a38b --- /dev/null +++ b/src/boost/libs/contract/example/n1962/factorial.cpp @@ -0,0 +1,39 @@ + +// Copyright (C) 2008-2018 Lorenzo Caminiti +// Distributed under the Boost Software License, Version 1.0 (see accompanying +// file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt). +// See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html + +//[n1962_factorial +#include <boost/contract.hpp> +#include <cassert> + +int factorial(int n) { + int result; + boost::contract::check c = boost::contract::function() + .precondition([&] { + BOOST_CONTRACT_ASSERT(n >= 0); // Non-negative natural number. + BOOST_CONTRACT_ASSERT(n <= 12); // Max function input. + }) + .postcondition([&] { + BOOST_CONTRACT_ASSERT(result >= 1); + if(n < 2) { // Select assertion. + BOOST_CONTRACT_ASSERT(result == 1); + } else { + // Assertions automatically disabled in other assertions. + // Therefore, this postcondition can recursively call the + // function without causing infinite recursion. + BOOST_CONTRACT_ASSERT_AUDIT(n * factorial(n - 1)); + } + }) + ; + + return n < 2 ? (result = 1) : (result = n * factorial(n - 1)); +} + +int main() { + assert(factorial(4) == 24); + return 0; +} +//] + diff --git a/src/boost/libs/contract/example/n1962/sqrt.cpp b/src/boost/libs/contract/example/n1962/sqrt.cpp new file mode 100644 index 000000000..52ade36bb --- /dev/null +++ b/src/boost/libs/contract/example/n1962/sqrt.cpp @@ -0,0 +1,32 @@ + +// Copyright (C) 2008-2018 Lorenzo Caminiti +// Distributed under the Boost Software License, Version 1.0 (see accompanying +// file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt). +// See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html + +//[n1962_sqrt +#include <boost/contract.hpp> +#include <cmath> +#include <cassert> + +long lsqrt(long x) { + long result; + boost::contract::check c = boost::contract::function() + .precondition([&] { + BOOST_CONTRACT_ASSERT(x >= 0); + }) + .postcondition([&] { + BOOST_CONTRACT_ASSERT(result * result <= x); + BOOST_CONTRACT_ASSERT((result + 1) * (result + 1) > x); + }) + ; + + return result = long(std::sqrt(double(x))); +} + +int main() { + assert(lsqrt(4) == 2); + return 0; +} +//] + diff --git a/src/boost/libs/contract/example/n1962/sqrt.d b/src/boost/libs/contract/example/n1962/sqrt.d new file mode 100644 index 000000000..3c550c86e --- /dev/null +++ b/src/boost/libs/contract/example/n1962/sqrt.d @@ -0,0 +1,33 @@ + +// Copyright (C) 2008-2018 Lorenzo Caminiti +// Distributed under the Boost Software License, Version 1.0 (see accompanying +// file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt). +// See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html + +//[n1962_sqrt_d +// Extra spaces, newlines, etc. for visual alignment with this library code. + + + +long lsqrt(long x) +in { + assert(x >= 0); +} +out(result) { + assert(result * result <= x); + assert((result + 1) * (result + 1) > x); +} +do { + return cast(long)std.math.sqrt(cast(real)x); +} + + + + + + + + +// End. +//] + diff --git a/src/boost/libs/contract/example/n1962/sum.cpp b/src/boost/libs/contract/example/n1962/sum.cpp new file mode 100644 index 000000000..068619ae9 --- /dev/null +++ b/src/boost/libs/contract/example/n1962/sum.cpp @@ -0,0 +1,30 @@ + +// Copyright (C) 2008-2018 Lorenzo Caminiti +// Distributed under the Boost Software License, Version 1.0 (see accompanying +// file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt). +// See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html + +//[n1962_sum +#include <boost/contract.hpp> +#include <cassert> + +int sum(int count, int* array) { + int result; + boost::contract::check c = boost::contract::function() + .precondition([&] { + BOOST_CONTRACT_ASSERT(count % 4 == 0); + }) + ; + + result = 0; + for(int i = 0; i < count; ++i) result += array[i]; + return result; +} + +int main() { + int a[4] = {1, 2, 3, 4}; + assert(sum(4, a) == 10); + return 0; +} +//] + diff --git a/src/boost/libs/contract/example/n1962/vector.cpp b/src/boost/libs/contract/example/n1962/vector.cpp new file mode 100644 index 000000000..bd06c5a7f --- /dev/null +++ b/src/boost/libs/contract/example/n1962/vector.cpp @@ -0,0 +1,725 @@ + +// Copyright (C) 2008-2018 Lorenzo Caminiti +// Distributed under the Boost Software License, Version 1.0 (see accompanying +// file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt). +// See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html + +//[n1962_vector +#include <boost/contract.hpp> +#include <boost/bind.hpp> +#include <boost/optional.hpp> +#include <boost/algorithm/cxx11/all_of.hpp> +#include <boost/type_traits/has_equal_to.hpp> +#include <boost/next_prior.hpp> +#include <vector> +#include <functional> +#include <iterator> +#include <memory> +#include <cassert> + +// Could be programmed at call site with C++14 generic lambdas. +struct all_of_equal_to { + typedef bool result_type; + + template<typename InputIter, typename T> + result_type operator()(InputIter first, InputIter last, T const& value) { + return boost::algorithm::all_of_equal(first, last, value); + } + + template<typename InputIter> + result_type operator()(InputIter first, InputIter last, InputIter where) { + for(InputIter i = first, j = where; i != last; ++i, ++j) { + if(*i != *j) return false; + } + return true; + } +}; + +template<typename Iter> +bool valid(Iter first, Iter last); // Cannot implement in C++ (for axiom only). + +template<typename Iter> +bool contained(Iter first1, Iter last1, Iter first2, Iter last2); // For axiom. + +// STL vector requires T copyable but not equality comparable. +template<typename T, class Allocator = std::allocator<T> > +class vector { + friend class boost::contract::access; + + void invariant() const { + BOOST_CONTRACT_ASSERT(empty() == (size() == 0)); + BOOST_CONTRACT_ASSERT(std::distance(begin(), end()) == int(size())); + BOOST_CONTRACT_ASSERT(std::distance(rbegin(), rend()) == int(size())); + BOOST_CONTRACT_ASSERT(size() <= capacity()); + BOOST_CONTRACT_ASSERT(capacity() <= max_size()); + } + +public: + typedef typename std::vector<T, Allocator>::allocator_type allocator_type; + typedef typename std::vector<T, Allocator>::pointer pointer; + typedef typename std::vector<T, Allocator>::const_pointer const_pointer; + typedef typename std::vector<T, Allocator>::reference reference; + typedef typename std::vector<T, Allocator>::const_reference const_reference; + typedef typename std::vector<T, Allocator>::value_type value_type; + typedef typename std::vector<T, Allocator>::iterator iterator; + typedef typename std::vector<T, Allocator>::const_iterator const_iterator; + typedef typename std::vector<T, Allocator>::size_type size_type; + typedef typename std::vector<T, Allocator>::difference_type difference_type; + typedef typename std::vector<T, Allocator>::reverse_iterator + reverse_iterator; + typedef typename std::vector<T, Allocator>::const_reverse_iterator + const_reverse_iterator; + + vector() : vect_() { + boost::contract::check c = boost::contract::constructor(this) + .postcondition([&] { + BOOST_CONTRACT_ASSERT(empty()); + }) + ; + } + + explicit vector(Allocator const& alloc) : vect_(alloc) { + boost::contract::check c = boost::contract::constructor(this) + .postcondition([&] { + BOOST_CONTRACT_ASSERT(empty()); + BOOST_CONTRACT_ASSERT(get_allocator() == alloc); + }) + ; + } + + explicit vector(size_type count) : vect_(count) { + boost::contract::check c = boost::contract::constructor(this) + .postcondition([&] { + BOOST_CONTRACT_ASSERT(size() == count); + BOOST_CONTRACT_ASSERT( + boost::contract::condition_if<boost::has_equal_to<T> >( + boost::bind(all_of_equal_to(), begin(), end(), T()) + ) + ); + }) + ; + } + + vector(size_type count, T const& value) : vect_(count, value) { + boost::contract::check c = boost::contract::constructor(this) + .postcondition([&] { + BOOST_CONTRACT_ASSERT(size() == count); + BOOST_CONTRACT_ASSERT( + boost::contract::condition_if<boost::has_equal_to<T> >( + boost::bind(all_of_equal_to(), begin(), end(), + boost::cref(value)) + ) + ); + }) + ; + } + + vector(size_type count, T const& value, Allocator const& alloc) : + vect_(count, value, alloc) { + boost::contract::check c = boost::contract::constructor(this) + .postcondition([&] { + BOOST_CONTRACT_ASSERT(size() == count); + BOOST_CONTRACT_ASSERT( + boost::contract::condition_if<boost::has_equal_to<T> >( + boost::bind(all_of_equal_to(), begin(), end(), + boost::cref(value)) + ) + ); + BOOST_CONTRACT_ASSERT(get_allocator() == alloc); + }) + ; + } + + template<typename InputIter> + vector(InputIter first, InputIter last) : vect_(first, last) { + boost::contract::check c = boost::contract::constructor(this) + .postcondition([&] { + BOOST_CONTRACT_ASSERT(std::distance(first, last) == + int(size())); + }) + ; + } + + template<typename InputIter> + vector(InputIter first, InputIter last, Allocator const& alloc) : + vect_(first, last, alloc) { + boost::contract::check c = boost::contract::constructor(this) + .postcondition([&] { + BOOST_CONTRACT_ASSERT(std::distance(first, last) == + int(size())); + BOOST_CONTRACT_ASSERT(get_allocator() == alloc); + }) + ; + } + + /* implicit */ vector(vector const& other) : vect_(other.vect_) { + boost::contract::check c = boost::contract::constructor(this) + .postcondition([&] { + BOOST_CONTRACT_ASSERT( + boost::contract::condition_if<boost::has_equal_to<T> >( + boost::bind(std::equal_to<vector<T> >(), + boost::cref(*this), boost::cref(other)) + ) + ); + }) + ; + } + + vector& operator=(vector const& other) { + boost::optional<vector&> result; + boost::contract::check c = boost::contract::public_function(this) + .postcondition([&] { + BOOST_CONTRACT_ASSERT( + boost::contract::condition_if<boost::has_equal_to<T> >( + boost::bind(std::equal_to<vector<T> >(), + boost::cref(*this), boost::cref(other)) + ) + ); + BOOST_CONTRACT_ASSERT( + boost::contract::condition_if<boost::has_equal_to<T> >( + boost::bind(std::equal_to<vector<T> >(), + boost::cref(*result), boost::cref(*this)) + ) + ); + }) + ; + + if(this != &other) vect_ = other.vect_; + return *(result = *this); + } + + virtual ~vector() { + // Check invariants. + boost::contract::check c = boost::contract::destructor(this); + } + + void reserve(size_type count) { + boost::contract::check c = boost::contract::public_function(this) + .precondition([&] { + BOOST_CONTRACT_ASSERT(count < max_size()); + }) + .postcondition([&] { + BOOST_CONTRACT_ASSERT(capacity() >= count); + }) + ; + + vect_.reserve(count); + } + + size_type capacity() const { + size_type result; + boost::contract::check c = boost::contract::public_function(this) + .postcondition([&] { + BOOST_CONTRACT_ASSERT(result >= size()); + }) + ; + + return result = vect_.capacity(); + } + + iterator begin() { + iterator result; + boost::contract::check c = boost::contract::public_function(this) + .postcondition([&] { + if(empty()) BOOST_CONTRACT_ASSERT(result == end()); + }) + ; + + return result = vect_.begin(); + } + + const_iterator begin() const { + const_iterator result; + boost::contract::check c = boost::contract::public_function(this) + .postcondition([&] { + if(empty()) BOOST_CONTRACT_ASSERT(result == end()); + }) + ; + + return result = vect_.begin(); + } + + iterator end() { + // Check invariants. + boost::contract::check c = boost::contract::public_function(this); + return vect_.end(); + } + + const_iterator end() const { + // Check invariants. + boost::contract::check c = boost::contract::public_function(this); + return vect_.end(); + } + + reverse_iterator rbegin() { + iterator result; + boost::contract::check c = boost::contract::public_function(this) + .postcondition([&] { + if(empty()) BOOST_CONTRACT_ASSERT(result == rend()); + }) + ; + + return result = vect_.rbegin(); + } + + const_reverse_iterator rbegin() const { + const_reverse_iterator result; + boost::contract::check c = boost::contract::public_function(this) + .postcondition([&] { + if(empty()) BOOST_CONTRACT_ASSERT(result == rend()); + }) + ; + + return result = vect_.rbegin(); + } + + reverse_iterator rend() { + // Check invariants. + boost::contract::check c = boost::contract::public_function(this); + return vect_.rend(); + } + + const_reverse_iterator rend() const { + // Check invariants. + boost::contract::check c = boost::contract::public_function(this); + return vect_.rend(); + } + + void resize(size_type count, T const& value = T()) { + boost::contract::old_ptr<size_type> old_size = + BOOST_CONTRACT_OLDOF(size()); + boost::contract::check c = boost::contract::public_function(this) + .postcondition([&] { + BOOST_CONTRACT_ASSERT(size() == count); + if(count > *old_size) { + BOOST_CONTRACT_ASSERT( + boost::contract::condition_if<boost::has_equal_to<T> >( + boost::bind(all_of_equal_to(), begin() + *old_size, + end(), boost::cref(value)) + ) + ); + } + }) + ; + + vect_.resize(count, value); + } + + size_type size() const { + size_type result; + boost::contract::check c = boost::contract::public_function(this) + .postcondition([&] { + BOOST_CONTRACT_ASSERT(result <= capacity()); + }) + ; + + return result = vect_.size(); + } + + size_type max_size() const { + size_type result; + boost::contract::check c = boost::contract::public_function(this) + .postcondition([&] { + BOOST_CONTRACT_ASSERT(result >= capacity()); + }) + ; + + return result = vect_.max_size(); + } + + bool empty() const { + bool result; + boost::contract::check c = boost::contract::public_function(this) + .postcondition([&] { + BOOST_CONTRACT_ASSERT(result == (size() == 0)); + }) + ; + + return result = vect_.empty(); + } + + Allocator get_allocator() const { + // Check invariants. + boost::contract::check c = boost::contract::public_function(this); + return vect_.get_allocator(); + } + + reference at(size_type index) { + // Check invariants, no pre (throw out_of_range for invalid index). + boost::contract::check c = boost::contract::public_function(this); + return vect_.at(index); + } + + const_reference at(size_type index) const { + // Check invariants, no pre (throw out_of_range for invalid index). + boost::contract::check c = boost::contract::public_function(this); + return vect_.at(index); + } + + reference operator[](size_type index) { + boost::contract::check c = boost::contract::public_function(this) + .precondition([&] { + BOOST_CONTRACT_ASSERT(index < size()); + }) + ; + + return vect_[index]; + } + + const_reference operator[](size_type index) const { + boost::contract::check c = boost::contract::public_function(this) + .precondition([&] { + BOOST_CONTRACT_ASSERT(index < size()); + }) + ; + + return vect_[index]; + } + + reference front() { + boost::contract::check c = boost::contract::public_function(this) + .precondition([&] { + BOOST_CONTRACT_ASSERT(!empty()); + }) + ; + + return vect_.front(); + } + + const_reference front() const { + boost::contract::check c = boost::contract::public_function(this) + .precondition([&] { + BOOST_CONTRACT_ASSERT(!empty()); + }) + ; + + return vect_.front(); + } + + reference back() { + boost::contract::check c = boost::contract::public_function(this) + .precondition([&] { + BOOST_CONTRACT_ASSERT(!empty()); + }) + ; + + return vect_.back(); + } + + const_reference back() const { + boost::contract::check c = boost::contract::public_function(this) + .precondition([&] { + BOOST_CONTRACT_ASSERT(!empty()); + }) + ; + + return vect_.back(); + } + + void push_back(T const& value) { + boost::contract::old_ptr<size_type> old_size = + BOOST_CONTRACT_OLDOF(size()); + boost::contract::old_ptr<size_type> old_capacity = + BOOST_CONTRACT_OLDOF(capacity()); + boost::contract::check c = boost::contract::public_function(this) + .precondition([&] { + BOOST_CONTRACT_ASSERT(size() < max_size()); + }) + .postcondition([&] { + BOOST_CONTRACT_ASSERT(size() == *old_size + 1); + BOOST_CONTRACT_ASSERT(capacity() >= *old_capacity); + BOOST_CONTRACT_ASSERT( + boost::contract::condition_if<boost::has_equal_to<T> >( + boost::bind(std::equal_to<T>(), boost::cref(back()), + boost::cref(value)) + ) + ); + }) + ; + + vect_.push_back(value); + } + + void pop_back() { + boost::contract::old_ptr<size_type> old_size = + BOOST_CONTRACT_OLDOF(size()); + boost::contract::check c = boost::contract::public_function(this) + .precondition([&] { + BOOST_CONTRACT_ASSERT(!empty()); + }) + .postcondition([&] { + BOOST_CONTRACT_ASSERT(size() == *old_size - 1); + }) + ; + + vect_.pop_back(); + } + + template<typename InputIter> + void assign(InputIter first, InputIter last) { + boost::contract::check c = boost::contract::public_function(this) + .precondition([&] { + BOOST_CONTRACT_ASSERT_AXIOM( + !contained(begin(), end(), first, last)); + }) + .postcondition([&] { + BOOST_CONTRACT_ASSERT(std::distance(first, last) == + int(size())); + }) + ; + + vect_.assign(first, last); + } + + void assign(size_type count, T const& value) { + boost::contract::check c = boost::contract::public_function(this) + .precondition([&] { + BOOST_CONTRACT_ASSERT(count <= max_size()); + }) + .postcondition([&] { + BOOST_CONTRACT_ASSERT( + boost::contract::condition_if<boost::has_equal_to<T> >( + boost::bind(all_of_equal_to(), begin(), end(), + boost::cref(value)) + ) + ); + }) + ; + + vect_.assign(count, value); + } + + iterator insert(iterator where, T const& value) { + iterator result; + boost::contract::old_ptr<size_type> old_size = + BOOST_CONTRACT_OLDOF(size()); + boost::contract::old_ptr<size_type> old_capacity = + BOOST_CONTRACT_OLDOF(capacity()); + boost::contract::check c = boost::contract::public_function(this) + .precondition([&] { + BOOST_CONTRACT_ASSERT(size() < max_size()); + }) + .postcondition([&] { + BOOST_CONTRACT_ASSERT(size() == *old_size + 1); + BOOST_CONTRACT_ASSERT(capacity() >= *old_capacity); + BOOST_CONTRACT_ASSERT( + boost::contract::condition_if<boost::has_equal_to<T> >( + boost::bind(std::equal_to<T>(), boost::cref(*result), + boost::cref(value)) + ) + ); + if(capacity() > *old_capacity) { + BOOST_CONTRACT_ASSERT_AXIOM(!valid(begin(), end())); + } else { + BOOST_CONTRACT_ASSERT_AXIOM(!valid(where, end())); + } + }) + ; + + return result = vect_.insert(where, value); + } + + void insert(iterator where, size_type count, T const& value) { + boost::contract::old_ptr<size_type> old_size = + BOOST_CONTRACT_OLDOF(size()); + boost::contract::old_ptr<size_type> old_capacity = + BOOST_CONTRACT_OLDOF(capacity()); + boost::contract::old_ptr<iterator> old_where = + BOOST_CONTRACT_OLDOF(where); + boost::contract::check c = boost::contract::public_function(this) + .precondition([&] { + BOOST_CONTRACT_ASSERT(size() + count < max_size()); + }) + .postcondition([&] { + BOOST_CONTRACT_ASSERT(size() == *old_size + count); + BOOST_CONTRACT_ASSERT(capacity() >= *old_capacity); + if(capacity() == *old_capacity) { + BOOST_CONTRACT_ASSERT( + boost::contract::condition_if<boost::has_equal_to<T> >( + boost::bind(all_of_equal_to(), + boost::prior(*old_where), + boost::prior(*old_where) + count, + boost::cref(value) + ) + ) + ); + BOOST_CONTRACT_ASSERT_AXIOM(!valid(where, end())); + } else BOOST_CONTRACT_ASSERT_AXIOM(!valid(begin(), end())); + }) + ; + + vect_.insert(where, count, value); + } + + template<typename InputIter> + void insert(iterator where, InputIter first, InputIter last) { + boost::contract::old_ptr<size_type> old_size = + BOOST_CONTRACT_OLDOF(size()); + boost::contract::old_ptr<size_type> old_capacity = + BOOST_CONTRACT_OLDOF(capacity()); + boost::contract::old_ptr<iterator> old_where = + BOOST_CONTRACT_OLDOF(where); + boost::contract::check c = boost::contract::public_function(this) + .precondition([&] { + BOOST_CONTRACT_ASSERT(size() + std::distance(first, last) < + max_size()); + BOOST_CONTRACT_ASSERT_AXIOM( + !contained(first, last, begin(), end())); + }) + .postcondition([&] { + BOOST_CONTRACT_ASSERT(size() == *old_size() + + std::distance(first, last)); + BOOST_CONTRACT_ASSERT(capacity() >= *old_capacity); + if(capacity() == *old_capacity) { + BOOST_CONTRACT_ASSERT( + boost::contract::condition_if<boost::has_equal_to<T> >( + boost::bind(all_of_equal_to(), first, last, + *old_where) + ) + ); + BOOST_CONTRACT_ASSERT_AXIOM(!valid(where, end())); + } else BOOST_CONTRACT_ASSERT_AXIOM(!valid(begin(), end())); + }) + ; + + vect_.insert(where, first, last); + } + + iterator erase(iterator where) { + iterator result; + boost::contract::old_ptr<size_type> old_size = + BOOST_CONTRACT_OLDOF(size()); + boost::contract::check c = boost::contract::public_function(this) + .precondition([&] { + BOOST_CONTRACT_ASSERT(!empty()); + BOOST_CONTRACT_ASSERT(where != end()); + }) + .postcondition([&] { + BOOST_CONTRACT_ASSERT(size() == *old_size - 1); + if(empty()) BOOST_CONTRACT_ASSERT(result == end()); + BOOST_CONTRACT_ASSERT_AXIOM(!valid(where, end())); + }) + ; + + return result = vect_.erase(where); + } + + iterator erase(iterator first, iterator last) { + iterator result; + boost::contract::old_ptr<size_type> old_size = + BOOST_CONTRACT_OLDOF(size()); + boost::contract::check c = boost::contract::public_function(this) + .precondition([&] { + BOOST_CONTRACT_ASSERT(size() >= std::distance(first, last)); + }) + .postcondition([&] { + BOOST_CONTRACT_ASSERT(size() == *old_size - + std::distance(first, last)); + if(empty()) BOOST_CONTRACT_ASSERT(result == end()); + BOOST_CONTRACT_ASSERT_AXIOM(!valid(first, last)); + }) + ; + + return result = vect_.erase(first, last); + } + + void clear() { + boost::contract::check c = boost::contract::public_function(this) + .postcondition([&] { + BOOST_CONTRACT_ASSERT(empty()); + }) + ; + + vect_.clear(); + } + + void swap(vector& other) { + boost::contract::old_ptr<vector> old_me, old_other; + #ifdef BOOST_CONTRACT_AUDITS + old_me = BOOST_CONTRACT_OLDOF(*this); + old_other = BOOST_CONTRACT_OLDOF(other); + #endif + boost::contract::check c = boost::contract::public_function(this) + .precondition([&] { + BOOST_CONTRACT_ASSERT(get_allocator() == other.get_allocator()); + }) + .postcondition([&] { + BOOST_CONTRACT_ASSERT_AUDIT( + boost::contract::condition_if<boost::has_equal_to< + vector<T> > >( + boost::bind(std::equal_to<vector<T> >(), + boost::cref(*this), boost::cref(*old_other)) + ) + ); + BOOST_CONTRACT_ASSERT_AUDIT( + boost::contract::condition_if<boost::has_equal_to< + vector<T> > >( + boost::bind(std::equal_to<vector<T> >(), + boost::cref(other), boost::cref(*old_me)) + ) + ); + }) + ; + + vect_.swap(other); + } + + friend bool operator==(vector const& left, vector const& right) { + // Check class invariants for left and right objects. + boost::contract::check left_inv = + boost::contract::public_function(&left); + boost::contract::check right_inv = + boost::contract::public_function(&right); + return left.vect_ == right.vect_; + } + +private: + std::vector<T, Allocator> vect_; +}; + +int main() { + // char type has operator==. + + vector<char> v(3); + assert(v.size() == 3); + assert(boost::algorithm::all_of_equal(v, '\0')); + + vector<char> const& cv = v; + assert(cv == v); + + vector<char> w(v); + assert(w == v); + + typename vector<char>::iterator i = v.begin(); + assert(*i == '\0'); + + typename vector<char>::const_iterator ci = cv.begin(); + assert(*ci == '\0'); + + v.insert(i, 2, 'a'); + assert(v[0] == 'a'); + assert(v[1] == 'a'); + + v.push_back('b'); + assert(v.back() == 'b'); + + struct x {}; // x type doest not have operator==. + + vector<x> y(3); + assert(y.size() == 3); + + vector<x> const& cy = y; + vector<x> z(y); + + typename vector<x>::iterator j = y.begin(); + assert(j != y.end()); + typename vector<x>::const_iterator cj = cy.begin(); + assert(cj != cy.end()); + + y.insert(j, 2, x()); + y.push_back(x()); + + return 0; +} +//] + diff --git a/src/boost/libs/contract/example/n1962/vector_n1962.hpp b/src/boost/libs/contract/example/n1962/vector_n1962.hpp new file mode 100644 index 000000000..2ea88df21 --- /dev/null +++ b/src/boost/libs/contract/example/n1962/vector_n1962.hpp @@ -0,0 +1,725 @@ + +// Copyright (C) 2008-2018 Lorenzo Caminiti +// Distributed under the Boost Software License, Version 1.0 (see accompanying +// file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt). +// See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html + +//[n1962_vector_n1962 +// Extra spaces, newlines, etc. for visual alignment with this library code. + +#include <boost/algorithm/cxx11/all_of.hpp> +#include <boost/type_traits/has_equal_to.hpp> +#include <boost/next_prior.hpp> +#include <vector> +#include <iterator> +#include <memory> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +template< class T, class Allocator = std::allocator<T> > +class vector { + + + invariant { + empty() == (size() == 0); + std::distance(begin(), end()) == int(size()); + std::distance(rbegin(), rend()) == int(size()); + size() <= capacity(); + capacity() <= max_size(); + } + +public: + typedef typename std::vector<T, Allocator>::allocator_type allocator_type; + typedef typename std::vector<T, Allocator>::pointer pointer; + typedef typename std::vector<T, Allocator>::const_pointer const_pointer; + typedef typename std::vector<T, Allocator>::reference reference; + typedef typename std::vector<T, Allocator>::const_reference const_reference; + typedef typename std::vector<T, Allocator>::value_type value_type; + typedef typename std::vector<T, Allocator>::iterator iterator; + typedef typename std::vector<T, Allocator>::const_iterator const_iterator; + typedef typename std::vector<T, Allocator>::size_type size_type; + typedef typename std::vector<T, Allocator>::difference_type difference_type; + typedef typename std::vector<T, Allocator>::reverse_iterator + reverse_iterator; + typedef typename std::vector<T, Allocator>::const_reverse_iterator + const_reverse_iterator; + + vector() + postcondition { + empty(); + } + : vect_() + {} + + + explicit vector(Allocator const& alloc) + postcondition { + empty(); + get_allocator() == alloc; + } + : vect_(alloc) + {} + + + explicit vector(size_type count) + postcondition { + size() == count; + if constexpr(boost::has_equal_to<T>::value) { + boost::algorithm::all_of_equal(begin(), end(), T()); + } + } + : vect_(count) + {} + + + + + vector(size_type count, T const& value) + postcondition { + size() == count; + if constexpr(boost::has_equal_to<T>::value) { + boost::algorithm::all_of_equal(begin(), end(), value); + } + } + : vect_(count, value) + {} + + + + + + vector(size_type count, T const& value, Allocator const& alloc) + postcondition { + size() == count; + if constexpr(boost::has_equal_to<T>::value) { + boost::algorithm::all_of_equal(begin(), end(), value); + } + get_allocator() == alloc; + } + : vect_(count, value, alloc) + {} + + + + + + + template<typename InputIter> + vector(InputIter first, InputIter last) + postcondition { + std::distance(first, last) == int(size()); + } + : vect_(first, last) + {} + + + + template<typename InputIter> + vector(InputIter first, InputIter last, Allocator const& alloc) + postcondition { + std::distance(first, last) == int(size()); + get_allocator() == alloc; + } + : vect_(first, last, alloc) + {} + + + + + /* implicit */ vector(vector const& other) + postcondition { + if constexpr(boost::has_equal_to<T>::value) { + *this == other; + } + } + : vect_(other.vect_) + {} + + + + + + vector& operator=(vector const& other) + postcondition(result) { + if constexpr(boost::has_equal_to<T>::value) { + *this == other; + result == *this; + } + } + { + if(this != &other) vect_ = other.vect_; + return *this; + } + + + + + + + + + + + + + virtual ~vector() {} + + + + + void reserve(size_type count) + precondition { + count < max_size(); + } + postcondition { + capacity() >= count; + } + { + vect_.reserve(count); + } + + + + size_type capacity() const + postcondition(result) { + result >= size(); + } + { + return vect_.capacity(); + } + + + + + iterator begin() + postcondition { + if(empty()) result == end(); + } + { + return vect_.begin(); + } + + + + + const_iterator begin() const + postcondition(result) { + if(empty()) result == end(); + } + { + return vect_.begin(); + } + + + + + iterator end() { + return vect_.end(); + } + + + + const_iterator end() const { + return vect_.end(); + } + + + + reverse_iterator rbegin() + postcondition(result) { + if(empty()) result == rend(); + } + { + return vect_.rbegin(); + } + + + + + const_reverse_iterator rbegin() const + postcondition(result) { + if(empty()) result == rend(); + } + { + return vect_.rbegin(); + } + + + + + reverse_iterator rend() { + return vect_.rend(); + } + + + + const_reverse_iterator rend() const { + return vect_.rend(); + } + + + + void resize(size_type count, T const& value = T()) + postcondition { + size() == count; + if constexpr(boost::has_equal_to<T>::value) { + if(count > oldof(size())) { + boost::algorithm::all_of_equal(begin() + oldof(size()), + end(), value); + } + } + } + { + vect_.resize(count, value); + } + + + + + + + + size_type size() const + postcondition(result) { + result <= capacity(); + } + { + return vect_.size(); + } + + + + + size_type max_size() const + postcondition(result) { + result >= capacity(); + } + { + return vect_.max_size(); + } + + + + + bool empty() const + postcondition(result) { + result == (size() == 0); + } + { + return vect_.empty(); + } + + + + + Alloctor get_allocator() const { + return vect_.get_allocator(); + } + + + + reference at(size_type index) { + // No precondition (throw out_of_range for invalid index). + return vect_.at(index); + } + + + const_reference at(size_type index) const { + // No precondition (throw out_of_range for invalid index). + return vect_.at(index); + } + + + reference operator[](size_type index) + precondition { + index < size(); + } + { + return vect_[index]; + } + + + + const_reference operator[](size_type index) const + precondition { + index < size(); + } + { + return vect_[index]; + } + + + + reference front() + precondition { + !empty(); + } + { + return vect_.front(); + } + + + + const_reference front() const + precondition { + !empty(); + } + { + return vect_.front(); + } + + + + reference back() + precondition { + !empty(); + } + { + return vect_.back(); + } + + + + const_reference back() const + precondition { + !empty(); + } + { + return vect_.back(); + } + + + + void push_back(T const& value) + precondition { + size() < max_size(); + } + postcondition { + size() == oldof(size()) + 1; + capacity() >= oldof(capacity()) + if constexpr(boost::has_equal_to<T>::value) { + back() == value; + } + } + { + vect_.push_back(value); + } + + + + + + + + + + + void pop_back() + precondition { + !empty(); + } + postcondition { + size() == oldof(size()) - 1; + } + { + vect_.pop_back(); + } + + + + + + template<typename InputIter> + void assign(InputIter first, InputIter last) + // Precondition: [begin(), end()) does not contain [first, last). + postcondition { + std::distance(first, last) == int(size()); + } + { + vect_.assign(first, last); + } + + + + + + + + void assign(size_type count, T const& vallue) + precondition { + count <= max_size(); + } + postcondition { + if constexpr(boost::has_equal_to<T>::value) { + boost::algorithm::all_of_equal(begin(), end(), value); + } + } + { + vect_.assign(count, value); + } + + + + + + + iterator insert(iterator where, T const& value) + precondition { + size() < max_size(); + } + postcondition(result) { + size() == oldof(size()) + 1; + capacity() >= oldof(capacity()); + if constexpr(boost::has_equal_to<T>::value) { + *result == value; + } + // if(capacity() > oldof(capacity())) + // [begin(), end()) is invalid + // else + // [where, end()) is invalid + } + { + return vect_.insert(where, value); + } + + + + + + + + + + + + + void insert(iterator where, size_type count, T const& value) + precondition { + size() + count < max_size(); + } + postcondition { + size() == oldof(size()) + count; + capacity() >= oldof(capacity()); + if(capacity() == oldof(capacity())) { + if constexpr(boost::has_equal_to<T>::value) { + boost::algorithm::all_of_equal(boost::prior(oldof(where)), + boost::prior(oldof(where)) + count, value); + } + // [where, end()) is invalid + } + // else [begin(), end()) is invalid + } + { + vect_.insert(where, count, value); + } + + + + + + + + + + + + + + template<typename InputIter> + void insert(iterator where, Iterator first, Iterator last) + precondition { + size() + std::distance(first, last) < max_size(); + // [first, last) is not contained in [begin(), end()) + } + postcondition { + size() == oldof(size()) + std::distance(first, last); + capacity() >= oldof(capacity()); + if(capacity() == oldof(capacity())) { + if constexpr(boost::has_equal_to<T>::value) { + boost::algorithm::all_of_equal(first, last, oldof(where)); + } + // [where, end()) is invalid + } + // else [begin(), end()) is invalid + } + { + vect_.insert(where, first, last); + } + + + + + + + + + + + + + + + iterator erase(iterator where) + precondition { + !empty(); + where != end(); + } + postcondition(result) { + size() == oldod size() - 1; + if(empty()) result == end(); + // [where, end()) is invalid + } + { + return vect_.erase(where); + } + + + + + + + iterator erase(iterator first, iterator last) + precondition { + size() >= std::distance(first, lasst); + } + postcondition(result) { + size() == oldof(size()) - std::distance(first, last); + if(empty()) result == end(); + // [first, last) is invalid + } + { + return vect_.erase(first, last); + } + + + + + + + + void clear() + postcondition { + empty(); + } + { + vect_.clear(); + } + + + + void swap(vector& other) + precondition { + get_allocator() == other.get_allocator(); + } + postcondition { + if constexpr(boost::has_equal_to<T>::value) { + *this == oldof(other); + other == oldof(*this); + } + } + { + vect_.swap(other); + } + + + + + + + + + + + + + + + + + + + friend bool operator==(vector const& left, vector const& right) { + // Cannot check class invariants for left and right objects. + return left.vect_ == right.vect_; + } + + + + + +private: + std::vector<T, Allocator> vect_; +}; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +// End. +//] + diff --git a/src/boost/libs/contract/index.html b/src/boost/libs/contract/index.html new file mode 100644 index 000000000..6861cd172 --- /dev/null +++ b/src/boost/libs/contract/index.html @@ -0,0 +1,15 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> +<html> + <head> + <meta http-equiv="refresh" content="0; URL=doc/html/index.html"> + </head> + <body> + Automatic redirection failed, click this + <a href="doc/html/index.html">link</a> <hr> + <p>© Copyright Lorenzo Caminiti, 2008-2016</p> + <p>Distributed under the Boost Software License, Version 1.0 (see + accompanying file LICENSE_1_0.txt or a copy at + <a href="http://www.boost.org/LICENSE_1_0.txt">www.boost.org/LICENSE_1_0.txt + </a>)</p> + </body> +</html> diff --git a/src/boost/libs/contract/meta/explicit-failures-markup.xml b/src/boost/libs/contract/meta/explicit-failures-markup.xml new file mode 100644 index 000000000..b17fa3618 --- /dev/null +++ b/src/boost/libs/contract/meta/explicit-failures-markup.xml @@ -0,0 +1,220 @@ +<?xml version="1.0" encoding="utf-8"?> + +<!-- +Copyright (C) 2008-2018 Lorenzo Caminiti +Distributed under the Boost Software License, Version 1.0 (see accompanying +file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt). +See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html +--> + +<!-- +PLEASE VALIDATE THE XML BEFORE COMMITTING YOUR CHANGES! + +For example, cut-n-paste <library> tag below into main file +"boost/status/explicit-failures-markup.xml" and validate as indicated in that +main file. +--> + +<explicit-failures-markup> + <!-- contract --> + <library name="contract"> + <mark-unusable> + <toolset name="clang-darwin-ubsan"/> + <note author="Lorenzo Caminiti"> + On this compiler, Boost.Function gives a run-time error when + calling non-nullary lambdas as used by the tests of this library + to program contract failure handlers. + It might still be possible to use this library on this compiler + using default contract failure handlers or programming custom + contract failure handlers but without using non-nullary lambdas + (however, the authors did not confirm that). + </note> + </mark-unusable> + <mark-unusable> + <toolset name="gcc-3.*"/> + <toolset name="gcc-4.*"/> + <note author="Lorenzo Caminiti"> + Even tests that do not use C++11 lambda functions fail on this + compiler because it incorrectly attempts an extra copy when + objects are constructed using `boost::check c = ...`. + This is fixed in MinGW GCC 4.3. + </note> + </mark-unusable> + <mark-unusable> + <toolset name="msvc-7.*"/> + <note author="Lorenzo Caminiti"> + Even tests that do not use C++11 lambda functions fail on this + compiler because of a number of issues (Boost.Exception is not + supported on this compiler but it is used by this library + implementation, some aspects of `friend` and `volatile` are not + properly implemented on this compiler, etc.). + These specific issues are fixed in MSVC 9.0 (but only MSVC 11.0 + has adequate lambda function support that makes this library + actually usable). + </note> + </mark-unusable> + <mark-expected-failures> + <test name="disable-audit"/> + <toolset name="gcc-4.9"/> + <toolset name="clang-linux-3.6"/> + <toolset name="clang-linux-3.7"/> + <toolset name="clang-linux-3.8"/> + <note author="Lorenzo Caminiti"> + This test fails on this compiler because of a bug with + exceptions (see http://grokbase.com/t/gg/android-ndk/1656csqqtp/assertion-ttypeencoding-dw-eh-pe-absptr-unexpected-ttypeencoding-failed). + </note> + </mark-expected-failures> + <mark-expected-failures> + <test name="invariant-ifdef"/> + <test name="specify-nothing"/> + <toolset name="clang-linux-3.6"/> + <toolset name="clang-linux-3.7"/> + <toolset name="clang-linux-3.8"/> + <note author="Lorenzo Caminiti"> + This test fails on this compiler because of a bug in its STL + implementation (undefined references to + `std::ios_base::failure::failure`). + </note> + </mark-expected-failures> + <mark-expected-failures> + <test name="destructor-throwing_old"/> + <test name="destructor-throwing_post"/> + <test name="public_function-decl_pre_all"/> + <test name="public_function-decl_pre_ends"/> + <test name="public_function-smoke"/> + <test name="public_function-throwing_post"/> + <test name="public_function-virtual"/> + <test name="public_function-virtual_branch"/> + <toolset name="clang-linux-*~gnu++*"/> + <note author="Lorenzo Caminiti"> + This test fails because of a libcxxrt bug on Clang for FreeBSD + which causes `std::uncaught_exception` to not work properly on + re-throws (see https://github.com/pathscale/libcxxrt/issues/49). + </note> + </mark-expected-failures> + <mark-expected-failures> + <test name="old-if_copyable"/> + <test name="old-if_copyable_macro"/> + <toolset name="gcc-4.6*"/> + <toolset name="gcc-4.7*"/> + <toolset name="msvc-10.*"/> + <toolset name="msvc-11.*"/> + <note author="Lorenzo Caminiti"> + This test fails because this complier does not properly + implement SFINAE giving incorrect errors on substitution + failures for private members. + This seems to be fixed in GCC 4.8 and MSVC 12.0. + </note> + </mark-expected-failures> + <mark-expected-failures> + <test name="public_function-protected_error"/> + <toolset name="clang-linux-3.0~*"/> + <toolset name="gcc-4.6*"/> + <note author="Lorenzo Caminiti"> + This test fails because SFINAE on this complier seems to not + fail as it should when a derived class tries to call a + protected member function on a base class object via a function + pointer instead of via inheritance. + This seems to be fixed in Clang 3.1, and to be specific to + version 4.6 of GCC. + </note> + </mark-expected-failures> + <mark-expected-failures> + <test name="public_function-virtual_access_multi"/> + <toolset name="gcc-4.6*"/> + <toolset name="gcc-4.7*"/> + <note author="Lorenzo Caminiti"> + This test fails because this compiler seems to incorrectly check + access level of members in base classes in a context when only + derived class members are used. + This seems to be fixed in GCC 4.8 (possibly related to + https://gcc.gnu.org/bugzilla/show_bug.cgi?id=57973). + </note> + </mark-expected-failures> + <mark-expected-failures> + <test name="constructor-throwing_body"/> + <test name="destructor-decl_entry_inv_all"/> + <test name="destructor-decl_entry_inv_ends"/> + <test name="destructor-decl_entry_static_inv_all"/> + <test name="destructor-decl_entry_static_inv_ends"/> + <test name="destructor-decl_entry_static_inv_mid"/> + <test name="destructor-decl_exit_static_inv_all"/> + <test name="destructor-decl_exit_static_inv_ends"/> + <test name="destructor-decl_exit_static_inv_mid"/> + <test name="destructor-throwing_body"/> + <test name="destructor-throwing_old"/> + <test name="destructor-throwing_post"/> + <test name="function-ifdef_macro"/> + <test name="function-throwing_body"/> + <test name="public_function-static_throwing_body"/> + <test name="public_function-throwing_body"/> + <test name="public_function-throwing_body_virtual"/> + <test name="public_function-throwing_body_virtual_branch"/> + <toolset name="qcc-4.7*"/> + <note author="Lorenzo Caminiti"> + This test fails because `std::unchaught_exception` seems to + always return zero on this compiler (even if the authors could + not find a direct reference to this possible compiler issue + online). + </note> + </mark-expected-failures> + <mark-expected-failures> + <test name="invariant-ifdef"/> + <test name="invariant-ifdef_macro"/> + <test name="invariant-volatile_error"/> + <toolset name="msvc-8.*"/> + <note author="Lorenzo Caminiti"> + This test fails because this complier seems to dispatch calls + incorrectly when both `const` and `const volatile` overloads + are present (even if the authors could not find a direct + reference to this possible compiler issue online). + This is fixed in MSVC 9.0 (but only MSVC 11.0 has adequate + lambda function support). + </note> + </mark-expected-failures> + <mark-expected-failures> + <test name="call_if-no_equal_call_if"/> + <toolset name="msvc-10.*"/> + <note author="Lorenzo Caminiti"> + This test fails because MSVC 10.0 is not able to properly deduce + a template specialization. + This is fixed in MSVC 11.0. + </note> + </mark-expected-failures> + <mark-expected-failures> + <test name="constructor-ifdef_macro"/> + <test name="constructor-smoke"/> + <toolset name="msvc-10.*"/> + <note author="Lorenzo Caminiti"> + This test fails because of a MSVC 10.0 bug with lambdas within + template class initialization list. + This can be worked around using a functor bind instead of a + lambda, but it is fixed in MSVC 11.0. + </note> + </mark-expected-failures> + <mark-expected-failures> + <test name="destructor-smoke"/> + <toolset name="msvc-10.*"/> + <note author="Lorenzo Caminiti"> + This test fails because of a MSVC 10.0 bug for which lambdas + cannot access typedefs declared within classes. + This can be worked around declaring typedefs outside of + classes, but it is fixed in MSVC 11.0. + </note> + </mark-expected-failures> + <mark-expected-failures> + <test name="disable-no_post_except_lib"/> + <test name="disable-no_post_except_unit"/> + <test name="disable-nothing_for_pre_prog"/> + <test name="disable-other_assertions_lib"/> + <test name="disable-other_assertions_prog"/> + <test name="disable-other_assertions_unit"/> + <toolset name="msvc-10.*"/> + <note author="Lorenzo Caminiti"> + This test fails because of an internal MSVC 10.0 compiler bug. + This is fixed in MSVC 11.0. + </note> + </mark-expected-failures> + </library> +</explicit-failures-markup> + diff --git a/src/boost/libs/contract/meta/libraries.json b/src/boost/libs/contract/meta/libraries.json new file mode 100644 index 000000000..38ae42d0b --- /dev/null +++ b/src/boost/libs/contract/meta/libraries.json @@ -0,0 +1,14 @@ +{ + "key": "contract", + "name": "Contract", + "authors": [ + "Lorenzo Caminiti" + ], + "maintainers": [ + "Lorenzo Caminiti <lorcaminiti -at- gmail.com>" + ], + "description": "Contract programming for C++. All contract programming features are supported: Subcontracting, class invariants, postconditions (with old and return values), preconditions, customizable actions on assertion failure (e.g., terminate or throw), optional compilation and checking of assertions, etc.", + "category": [ + "Correctness" + ] +} diff --git a/src/boost/libs/contract/src/contract.cpp b/src/boost/libs/contract/src/contract.cpp new file mode 100644 index 000000000..e3f36cf08 --- /dev/null +++ b/src/boost/libs/contract/src/contract.cpp @@ -0,0 +1,13 @@ + +// Copyright (C) 2008-2018 Lorenzo Caminiti +// Distributed under the Boost Software License, Version 1.0 (see accompanying +// file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt). +// See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html + +#include <boost/contract/core/config.hpp> +// For shared (default) and static lib only. +#ifndef BOOST_CONTRACT_HEADER_ONLY // This is not an #include guard. + #define BOOST_CONTRACT_SOURCE + #include <boost/contract/detail/inlined.hpp> +#endif // Else (header-only), make sure nothing is compiled here. + diff --git a/src/boost/libs/contract/test/Jamfile.v2 b/src/boost/libs/contract/test/Jamfile.v2 new file mode 100644 index 000000000..2026b8de0 --- /dev/null +++ b/src/boost/libs/contract/test/Jamfile.v2 @@ -0,0 +1,449 @@ + +# Copyright (C) 2008-2018 Lorenzo Caminiti +# Distributed under the Boost Software License, Version 1.0 (see accompanying +# file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt). +# See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html + +import ../build/boost_contract_build ; +import ../../config/checks/config : requires ; + +test-suite constructor : + [ boost_contract_build.subdir-run-cxx11 constructor : smoke ] + + [ boost_contract_build.subdir-run-cxx11 constructor : decl_pre_all ] + [ boost_contract_build.subdir-run-cxx11 constructor : decl_pre_ends ] + [ boost_contract_build.subdir-run-cxx11 constructor : decl_pre_mid ] + [ boost_contract_build.subdir-run-cxx11 constructor : decl_pre_none ] + + [ boost_contract_build.subdir-run-cxx11 constructor : decl_post_all ] + [ boost_contract_build.subdir-run-cxx11 constructor : decl_post_ends ] + [ boost_contract_build.subdir-run-cxx11 constructor : decl_post_mid ] + [ boost_contract_build.subdir-run-cxx11 constructor : decl_post_none ] + + [ boost_contract_build.subdir-run-cxx11 constructor : + decl_entry_static_inv_all ] + [ boost_contract_build.subdir-run-cxx11 constructor : + decl_entry_static_inv_ends ] + [ boost_contract_build.subdir-run-cxx11 constructor : + decl_entry_static_inv_mid ] + [ boost_contract_build.subdir-run-cxx11 constructor : + decl_entry_static_inv_none ] + + [ boost_contract_build.subdir-run-cxx11 constructor : + decl_exit_static_inv_all ] + [ boost_contract_build.subdir-run-cxx11 constructor : + decl_exit_static_inv_ends ] + [ boost_contract_build.subdir-run-cxx11 constructor : + decl_exit_static_inv_mid ] + [ boost_contract_build.subdir-run-cxx11 constructor : + decl_exit_static_inv_none ] + + # No decl_entry_static_inv_... (as no obj before ctor). + + [ boost_contract_build.subdir-run-cxx11 constructor : decl_exit_inv_all ] + [ boost_contract_build.subdir-run-cxx11 constructor : decl_exit_inv_ends ] + [ boost_contract_build.subdir-run-cxx11 constructor : decl_exit_inv_mid ] + [ boost_contract_build.subdir-run-cxx11 constructor : decl_exit_inv_none ] + + [ boost_contract_build.subdir-run-cxx11 constructor : access ] + + [ boost_contract_build.subdir-run-cxx11 constructor : ifdef ] + [ boost_contract_build.subdir-run-cxx11 constructor : ifdef_macro ] + + [ boost_contract_build.subdir-run-cxx11 constructor : throwing_pre ] + [ boost_contract_build.subdir-run-cxx11 constructor : throwing_old ] + [ boost_contract_build.subdir-run-cxx11 constructor : throwing_body ] + [ boost_contract_build.subdir-run-cxx11 constructor : throwing_post ] + # No throwing_except test (as throwing twice calls terminate). + + [ boost_contract_build.subdir-compile-fail-cxx11 constructor : pre_error ] +; + +test-suite destructor : + [ boost_contract_build.subdir-run-cxx11 destructor : smoke ] + + # No decl_pre_... (as dtors have no pre). + + [ boost_contract_build.subdir-run-cxx11 destructor : decl_post_all ] + [ boost_contract_build.subdir-run-cxx11 destructor : decl_post_ends ] + [ boost_contract_build.subdir-run-cxx11 destructor : decl_post_mid ] + [ boost_contract_build.subdir-run-cxx11 destructor : decl_post_none ] + + [ boost_contract_build.subdir-run-cxx11 destructor : + decl_entry_static_inv_all ] + [ boost_contract_build.subdir-run-cxx11 destructor : + decl_entry_static_inv_ends ] + [ boost_contract_build.subdir-run-cxx11 destructor : + decl_entry_static_inv_mid ] + [ boost_contract_build.subdir-run-cxx11 destructor : + decl_entry_static_inv_none ] + + [ boost_contract_build.subdir-run-cxx11 destructor : + decl_exit_static_inv_all ] + [ boost_contract_build.subdir-run-cxx11 destructor : + decl_exit_static_inv_ends ] + [ boost_contract_build.subdir-run-cxx11 destructor : + decl_exit_static_inv_mid ] + [ boost_contract_build.subdir-run-cxx11 destructor : + decl_exit_static_inv_none ] + + [ boost_contract_build.subdir-run-cxx11 destructor : decl_entry_inv_all ] + [ boost_contract_build.subdir-run-cxx11 destructor : decl_entry_inv_ends ] + [ boost_contract_build.subdir-run-cxx11 destructor : decl_entry_inv_mid ] + [ boost_contract_build.subdir-run-cxx11 destructor : decl_entry_inv_none ] + + # No decl_exit_inv_... (as no obj after dtor). + + [ boost_contract_build.subdir-run-cxx11 destructor : access ] + + [ boost_contract_build.subdir-run-cxx11 destructor : ifdef ] + [ boost_contract_build.subdir-run-cxx11 destructor : ifdef_macro ] + + # No throwing_pre test (as dtors have no pre). + [ boost_contract_build.subdir-run-cxx11 destructor : throwing_old ] + [ boost_contract_build.subdir-run-cxx11 destructor : throwing_body ] + [ boost_contract_build.subdir-run-cxx11 destructor : throwing_post ] + # No throwing_except test (as throwing twice calls terminate). + + [ boost_contract_build.subdir-compile-fail-cxx11 destructor : pre_error ] +; + +test-suite public_function : + [ boost_contract_build.subdir-run-cxx11 public_function : smoke ] + + [ boost_contract_build.subdir-run-cxx11 public_function : decl_pre_all ] + [ boost_contract_build.subdir-run-cxx11 public_function : decl_pre_ends ] + [ boost_contract_build.subdir-run-cxx11 public_function : decl_pre_mid ] + [ boost_contract_build.subdir-run-cxx11 public_function : decl_pre_none ] + + [ boost_contract_build.subdir-run-cxx11 public_function : decl_post_all ] + [ boost_contract_build.subdir-run-cxx11 public_function : decl_post_ends ] + [ boost_contract_build.subdir-run-cxx11 public_function : decl_post_mid ] + [ boost_contract_build.subdir-run-cxx11 public_function : decl_post_none ] + + [ boost_contract_build.subdir-run-cxx11 public_function : + decl_entry_static_inv_all ] + [ boost_contract_build.subdir-run-cxx11 public_function : + decl_entry_static_inv_ends ] + [ boost_contract_build.subdir-run-cxx11 public_function : + decl_entry_static_inv_mid ] + [ boost_contract_build.subdir-run-cxx11 public_function : + decl_entry_static_inv_none ] + + [ boost_contract_build.subdir-run-cxx11 public_function : + decl_exit_static_inv_all ] + [ boost_contract_build.subdir-run-cxx11 public_function : + decl_exit_static_inv_ends ] + [ boost_contract_build.subdir-run-cxx11 public_function : + decl_exit_static_inv_mid ] + [ boost_contract_build.subdir-run-cxx11 public_function : + decl_exit_static_inv_none ] + + [ boost_contract_build.subdir-run-cxx11 public_function : + decl_entry_inv_all ] + [ boost_contract_build.subdir-run-cxx11 public_function : + decl_entry_inv_ends ] + [ boost_contract_build.subdir-run-cxx11 public_function : + decl_entry_inv_mid ] + [ boost_contract_build.subdir-run-cxx11 public_function : + decl_entry_inv_none ] + + [ boost_contract_build.subdir-run-cxx11 public_function : + decl_exit_inv_all ] + [ boost_contract_build.subdir-run-cxx11 public_function : + decl_exit_inv_ends ] + [ boost_contract_build.subdir-run-cxx11 public_function : + decl_exit_inv_mid ] + [ boost_contract_build.subdir-run-cxx11 public_function : + decl_exit_inv_none ] + + [ boost_contract_build.subdir-run-cxx11 public_function : access ] + + [ boost_contract_build.subdir-run-cxx11 public_function : ifdef ] + [ boost_contract_build.subdir-run-cxx11 public_function : ifdef_macro ] + + [ boost_contract_build.subdir-run-cxx11 public_function : virtual ] + [ boost_contract_build.subdir-run-cxx11 public_function : virtual_branch ] + [ boost_contract_build.subdir-run-cxx11 public_function : virtual_sparse ] + [ boost_contract_build.subdir-run-cxx11 public_function : virtual_access ] + [ boost_contract_build.subdir-run-cxx11 public_function : + virtual_access_multi ] + [ boost_contract_build.subdir-run-cxx11 public_function : old_virtual ] + + [ boost_contract_build.subdir-run-cxx11 public_function : protected ] + [ boost_contract_build.subdir-compile-fail public_function : + protected_error ] + [ boost_contract_build.subdir-run-cxx11 public_function : friend ] + + [ boost_contract_build.subdir-run-cxx11 public_function : throwing_pre ] + [ boost_contract_build.subdir-run-cxx11 public_function : throwing_old ] + [ boost_contract_build.subdir-run-cxx11 public_function : throwing_body ] + [ boost_contract_build.subdir-run-cxx11 public_function : + throwing_body_virtual ] + [ boost_contract_build.subdir-run-cxx11 public_function : + throwing_body_virtual_branch ] + [ boost_contract_build.subdir-run-cxx11 public_function : throwing_post ] + # No throwing_except test (as throwing twice calls terminate). + + [ boost_contract_build.subdir-run-cxx11 public_function : max_args0 : + <define>BOOST_CONTRACT_MAX_ARGS=0 ] + [ boost_contract_build.subdir-run-cxx11 public_function : max_args0_no_tva : + <define>BOOST_CONTRACT_MAX_ARGS=0 + <define>BOOST_NO_CXX11_VARIADIC_TEMPLATES + ] + [ boost_contract_build.subdir-run-cxx11 public_function : max_args1 : + <define>BOOST_CONTRACT_MAX_ARGS=1 ] + [ boost_contract_build.subdir-run-cxx11 public_function : max_args1_no_tva : + <define>BOOST_CONTRACT_MAX_ARGS=1 + <define>BOOST_NO_CXX11_VARIADIC_TEMPLATES + ] + [ boost_contract_build.subdir-run-cxx11 public_function : max_args2 : + <define>BOOST_CONTRACT_MAX_ARGS=2 ] + [ boost_contract_build.subdir-run-cxx11 public_function : max_args2_no_tva : + <define>BOOST_CONTRACT_MAX_ARGS=2 + <define>BOOST_NO_CXX11_VARIADIC_TEMPLATES + ] + [ boost_contract_build.subdir-run-cxx11 public_function : max_args ] + [ boost_contract_build.subdir-run-cxx11 public_function : max_args_no_tva : + <define>BOOST_NO_CXX11_VARIADIC_TEMPLATES ] + + [ boost_contract_build.subdir-run-cxx11 public_function : + max_bases ] # C++11 for BASES(...) variadic macros. + + [ boost_contract_build.subdir-run-cxx11 public_function : overload ] + [ boost_contract_build.subdir-run-cxx11 public_function : overload_no_tva : + <define>BOOST_NO_CXX11_VARIADIC_TEMPLATES ] + + [ boost_contract_build.subdir-compile-fail-cxx11 public_function : + override_error ] # C++11 for BASES(...) variadic macros. + [ boost_contract_build.subdir-run-cxx11 public_function : # C++11 for BASES. + override_permissive : <define>BOOST_CONTRACT_PERMISSIVE ] + + [ boost_contract_build.subdir-run-cxx11 public_function : static ] + [ boost_contract_build.subdir-run-cxx11 public_function : static_ifdef ] + [ boost_contract_build.subdir-run-cxx11 public_function : + static_ifdef_macro ] + [ boost_contract_build.subdir-run-cxx11 public_function : + static_throwing_pre ] + [ boost_contract_build.subdir-run-cxx11 public_function : + static_throwing_old ] + [ boost_contract_build.subdir-run-cxx11 public_function : + static_throwing_body ] + [ boost_contract_build.subdir-run-cxx11 public_function : + static_throwing_post ] + # No throwing_except test (as throwing twice calls terminate). +; + +test-suite invariant : + [ boost_contract_build.subdir-run-cxx11 invariant : decl_static_cv_const ] + [ boost_contract_build.subdir-run-cxx11 invariant : decl_static_cv ] + [ boost_contract_build.subdir-run-cxx11 invariant : decl_cv_const ] + [ boost_contract_build.subdir-run-cxx11 invariant : decl_static_const ] + [ boost_contract_build.subdir-run-cxx11 invariant : decl_static ] + [ boost_contract_build.subdir-run-cxx11 invariant : decl_cv ] + [ boost_contract_build.subdir-run-cxx11 invariant : decl_const ] + [ boost_contract_build.subdir-run-cxx11 invariant : decl_nothing ] + + [ boost_contract_build.subdir-run invariant : ifdef ] + [ boost_contract_build.subdir-run-cxx11 invariant : ifdef_macro ] + + [ boost_contract_build.subdir-compile-fail invariant : + static_mutable_error ] + [ boost_contract_build.subdir-run invariant : static_mutable_permissive : + <define>BOOST_CONTRACT_PERMISSIVE ] + [ boost_contract_build.subdir-compile-fail invariant : static_const_error ] + [ boost_contract_build.subdir-run invariant : static_const_permissive : + <define>BOOST_CONTRACT_PERMISSIVE ] + [ boost_contract_build.subdir-compile-fail invariant : + static_volatile_error ] + [ boost_contract_build.subdir-run invariant : static_volatile_permissive : + <define>BOOST_CONTRACT_PERMISSIVE ] + [ boost_contract_build.subdir-compile-fail invariant : static_cv_error ] + [ boost_contract_build.subdir-run invariant : static_cv_permissive : + <define>BOOST_CONTRACT_PERMISSIVE ] + + [ boost_contract_build.subdir-compile-fail invariant : static_error ] + [ boost_contract_build.subdir-run invariant : static_permissive : + <define>BOOST_CONTRACT_PERMISSIVE ] + [ boost_contract_build.subdir-compile-fail invariant : mutable_error ] + [ boost_contract_build.subdir-run invariant : mutable_permissive : + <define>BOOST_CONTRACT_PERMISSIVE ] + [ boost_contract_build.subdir-compile-fail invariant : volatile_error ] + [ boost_contract_build.subdir-run invariant : volatile_permissive : + <define>BOOST_CONTRACT_PERMISSIVE ] +; + +test-suite function : + [ boost_contract_build.subdir-run-cxx11 function : smoke ] + + [ boost_contract_build.subdir-run-cxx11 function : decl_pre_all ] + [ boost_contract_build.subdir-run-cxx11 function : decl_pre_none ] + + [ boost_contract_build.subdir-run-cxx11 function : decl_post_all ] + [ boost_contract_build.subdir-run-cxx11 function : decl_post_none ] + + [ boost_contract_build.subdir-run-cxx11 function : ifdef ] + [ boost_contract_build.subdir-run-cxx11 function : ifdef_macro ] + + [ boost_contract_build.subdir-run-cxx11 function : throwing_pre ] + [ boost_contract_build.subdir-run-cxx11 function : throwing_old ] + [ boost_contract_build.subdir-run-cxx11 function : throwing_body ] + [ boost_contract_build.subdir-run-cxx11 function : throwing_post ] + # No throwing_except test (as throwing twice calls terminate). +; + +test-suite check : + [ boost_contract_build.subdir-run-cxx11 check : decl_class ] + [ boost_contract_build.subdir-run-cxx11 check : decl_macro ] + + [ boost_contract_build.subdir-run-cxx11 check : ifdef ] + [ boost_contract_build.subdir-run-cxx11 check : ifdef_macro ] + + [ boost_contract_build.subdir-run-cxx11 check : audit : + <define>BOOST_CONTRACT_AUDITS ] + [ boost_contract_build.subdir-compile-fail-cxx11 check : audit_error ] + [ boost_contract_build.subdir-run-cxx11 check : audit_disabled ] + [ boost_contract_build.subdir-compile-fail-cxx11 check : + audit_disabled_error ] + [ boost_contract_build.subdir-run check : axiom ] + [ boost_contract_build.subdir-compile-fail check : axiom_error ] +; + +test-suite result : + [ boost_contract_build.subdir-run-cxx11 result : mixed_optional ] + [ boost_contract_build.subdir-run-cxx11 result : mixed_optional_ref ] + + [ boost_contract_build.subdir-compile-fail-cxx11 result : + type_mismatch_error ] # C++11 for BASES(...) variadic macros. +; + +test-suite old : + [ boost_contract_build.subdir-run old : auto : + [ requires cxx11_auto_declarations ] ] + + [ boost_contract_build.subdir-run-cxx11 old : no_macro ] + [ boost_contract_build.subdir-run-cxx11 old : no_macro_if_copyable ] + + [ boost_contract_build.subdir-compile-fail old : no_make_old_error ] + [ boost_contract_build.subdir-compile-fail old : + no_make_old_if_copyable_error ] + + [ boost_contract_build.subdir-run-cxx11 old : if_copyable ] + [ boost_contract_build.subdir-compile-fail-cxx11 old : if_copyable_error ] + [ boost_contract_build.subdir-run-cxx11 old : if_copyable_macro ] + + [ boost_contract_build.subdir-run old : copyable_traits ] +; + +test-suite disable : + [ boost_contract_build.subdir-run-cxx11 disable : nothing_for_pre_prog : + <define>BOOST_CONTRACT_PRECONDITIONS_DISABLE_NO_ASSERTION ] + [ boost_contract_build.subdir-run-cxx11 disable : other_assertions_prog ] + + [ boost_contract_build.subdir-lib-cxx11 disable : lib_a : + <link>shared:<define>BOOST_CONTRACT_TEST_LIB_A_DYN_LINK ] + [ boost_contract_build.subdir-lib-cxx11 disable : lib_b : + <library>disable-lib_a + <link>shared:<define>BOOST_CONTRACT_TEST_LIB_B_DYN_LINK + ] + [ boost_contract_build.subdir-run-cxx11 disable : other_assertions_lib : + <library>disable-lib_a <library>disable-lib_b ] + + [ boost_contract_build.subdir-run-cxx11 disable : other_assertions_unit + disable/lib_a.cpp disable/lib_b.cpp ] + + [ boost_contract_build.subdir-lib-cxx11 disable : lib_x : + <define>BOOST_CONTRACT_NO_POSTCONDITIONS + <define>BOOST_CONTRACT_NO_EXCEPTS + <link>shared:<define>BOOST_CONTRACT_TEST_LIB_X_DYN_LINK + ] + [ boost_contract_build.subdir-lib-cxx11 disable : lib_y : + <library>disable-lib_x + <define>BOOST_CONTRACT_NO_POSTCONDITIONS + <define>BOOST_CONTRACT_NO_EXCEPTS + <link>shared:<define>BOOST_CONTRACT_TEST_LIB_Y_DYN_LINK + ] + [ boost_contract_build.subdir-run-cxx11 disable : no_post_except_lib : + <library>disable-lib_x <library>disable-lib_y ] + + [ boost_contract_build.subdir-run-cxx11 disable : no_post_except_unit + disable/lib_x.cpp disable/lib_y.cpp : + <define>BOOST_CONTRACT_NO_POSTCONDITIONS + <define>BOOST_CONTRACT_NO_EXCEPTS + ] + + [ boost_contract_build.subdir-run disable : audit : + <define>BOOST_CONTRACT_AUDITS ] + [ boost_contract_build.subdir-compile-fail disable : audit_error ] + [ boost_contract_build.subdir-run disable : audit_disabled ] + [ boost_contract_build.subdir-compile-fail disable : audit_disabled_error ] + [ boost_contract_build.subdir-run disable : axiom ] + [ boost_contract_build.subdir-compile-fail disable : axiom_error ] +; + +test-suite specify : + [ boost_contract_build.subdir-run-cxx11 specify : pre_old_post_except ] + + [ boost_contract_build.subdir-run-cxx11 specify : pre_old_post ] + [ boost_contract_build.subdir-run-cxx11 specify : pre_old_except ] + [ boost_contract_build.subdir-run-cxx11 specify : pre_post_except ] + [ boost_contract_build.subdir-run-cxx11 specify : old_post_except ] + + [ boost_contract_build.subdir-run-cxx11 specify : pre_old ] + [ boost_contract_build.subdir-run-cxx11 specify : pre_post ] + [ boost_contract_build.subdir-run-cxx11 specify : pre_except ] + [ boost_contract_build.subdir-run-cxx11 specify : old_post ] + [ boost_contract_build.subdir-run-cxx11 specify : old_except ] + [ boost_contract_build.subdir-run-cxx11 specify : post_except ] + + [ boost_contract_build.subdir-run-cxx11 specify : pre ] + [ boost_contract_build.subdir-run-cxx11 specify : old ] + [ boost_contract_build.subdir-run-cxx11 specify : post ] + [ boost_contract_build.subdir-run-cxx11 specify : except ] + + [ boost_contract_build.subdir-run specify : nothing ] + + [ boost_contract_build.subdir-compile-fail-cxx11 specify : + except_post_error ] + [ boost_contract_build.subdir-compile-fail-cxx11 specify : + except_old_error ] + [ boost_contract_build.subdir-compile-fail-cxx11 specify : + except_pre_error ] + [ boost_contract_build.subdir-compile-fail-cxx11 specify : post_old_error ] + [ boost_contract_build.subdir-compile-fail-cxx11 specify : post_pre_error ] + [ boost_contract_build.subdir-compile-fail-cxx11 specify : old_pre_error ] + + [ boost_contract_build.subdir-run-cxx11 specify : missing_check : + <define>BOOST_CONTRACT_ON_MISSING_CHECK_DECL=\"\{\ throw\ err()\;\ \}\" + ] + + [ boost_contract_build.subdir-compile-fail specify : auto_error : + [ requires cxx11_auto_declarations ] ] + [ boost_contract_build.subdir-compile-fail-cxx11 specify : auto_pre_error : + [ requires cxx11_auto_declarations ] ] + [ boost_contract_build.subdir-compile-fail-cxx11 specify : + auto_pre_old_error : [ requires cxx11_auto_declarations ] ] + [ boost_contract_build.subdir-compile-fail-cxx11 specify : + auto_pre_old_post_error : [ requires cxx11_auto_declarations ] ] + [ boost_contract_build.subdir-compile-fail-cxx11 specify + : auto_pre_old_post_except_error + : [ requires cxx11_auto_declarations ] + ] +; + +test-suite call_if : + [ boost_contract_build.subdir-run-cxx11 call_if : true_ ] + [ boost_contract_build.subdir-run-cxx11 call_if : false_ ] + + [ boost_contract_build.subdir-run-cxx11 call_if : true_void ] + [ boost_contract_build.subdir-run-cxx11 call_if : false_void ] + + [ boost_contract_build.subdir-run-cxx11 call_if : equal_to ] + [ boost_contract_build.subdir-run-cxx11 call_if : equal_to_cxx14 : + [ requires cxx14_generic_lambdas ] ] + + [ boost_contract_build.subdir-run-cxx11 call_if : no_equal_condition_if ] + [ boost_contract_build.subdir-run-cxx11 call_if : no_equal_call_if ] + [ boost_contract_build.subdir-compile-fail-cxx11 call_if : no_equal_error ] +; + diff --git a/src/boost/libs/contract/test/call_if/equal_to.cpp b/src/boost/libs/contract/test/call_if/equal_to.cpp new file mode 100644 index 000000000..a71c12bf8 --- /dev/null +++ b/src/boost/libs/contract/test/call_if/equal_to.cpp @@ -0,0 +1,86 @@ + +// Copyright (C) 2008-2018 Lorenzo Caminiti +// Distributed under the Boost Software License, Version 1.0 (see accompanying +// file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt). +// See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html + +// Test STL equal_to with call_if. + +// C++17 warning from Boost.Bind. +#define _SILENCE_CXX17_ADAPTOR_TYPEDEFS_DEPRECATION_WARNING + +#include "../detail/oteststream.hpp" +#include <boost/contract/call_if.hpp> +#include <boost/bind.hpp> +#include <boost/type_traits/has_equal_to.hpp> +#include <boost/detail/lightweight_test.hpp> +#include <functional> +#include <sstream> +#include <ios> + +boost::contract::test::detail::oteststream out; + +template<typename T> +struct void_equal_to { + typedef void result_type; // Test void result type. + + void operator()(T const& left, T const& right) const { + out << (left == right) << std::endl; + } +}; + +struct x {}; // Doest not have operator==. + +int main() { + std::ostringstream ok; + ok << std::boolalpha; + out << std::boolalpha; + x x1, x2;; + + out.str(""); + out << // Test on true condition with non-void result type. + boost::contract::call_if<boost::has_equal_to<int> >( + boost::bind(std::equal_to<int>(), 123, 123) // True. + ).else_( + // Compiler-error... but not called. + boost::bind(std::equal_to<x>(), x1, x2) + ) + << std::endl; + ok.str(""); ok << true << std::endl; + BOOST_TEST(out.eq(ok.str())); + + out.str(""); + out << // Test on false condition with non-void result type. + boost::contract::call_if<boost::has_equal_to<x> >( + // Compiler-error... but not called. + boost::bind(std::equal_to<x>(), x1, x2) + ).else_([] { return true; }) + << std::endl; + ok.str(""); ok << true << std::endl; + BOOST_TEST(out.eq(ok.str())); + + out.str(""); + // Test on true condition void result type. + boost::contract::call_if<boost::has_equal_to<int> >( + boost::bind(void_equal_to<int>(), 123, 456) // False. + ).else_( + // Compiler-error... but not called. + boost::bind(void_equal_to<x>(), x1, x1) + ); + ok.str(""); ok << false << std::endl; + BOOST_TEST(out.eq(ok.str())); + + out.str(""); + // Test on false condition with void result type. + boost::contract::call_if<boost::has_equal_to<x> >( + // Compiler-error... but not called. + boost::bind(void_equal_to<x>(), x1, x1) + ).else_( + boost::bind(void_equal_to<int>(), 123, 456) // False. + ); + ok.str(""); ok << false << std::endl; + BOOST_TEST(out.eq(ok.str())); + + return boost::report_errors(); +} + diff --git a/src/boost/libs/contract/test/call_if/equal_to_cxx14.cpp b/src/boost/libs/contract/test/call_if/equal_to_cxx14.cpp new file mode 100644 index 000000000..4ab59863f --- /dev/null +++ b/src/boost/libs/contract/test/call_if/equal_to_cxx14.cpp @@ -0,0 +1,56 @@ + +// Copyright (C) 2008-2018 Lorenzo Caminiti +// Distributed under the Boost Software License, Version 1.0 (see accompanying +// file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt). +// See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html + +// Test call_if equality check with C++14 generic lambdas. + +#include "../detail/oteststream.hpp" +#include <boost/contract/call_if.hpp> +#include <boost/type_traits/has_equal_to.hpp> +#include <boost/detail/lightweight_test.hpp> +#include <functional> // std::bind for generic lambdas. +#include <sstream> +#include <ios> + +boost::contract::test::detail::oteststream out; + +struct x {}; // Does not have operator==. + +int main() { + std::ostringstream ok; + ok << std::boolalpha; + out << std::boolalpha; + x x1, x2; + + out.str(""); + out << + boost::contract::call_if<boost::has_equal_to<int> >( + std::bind([] (auto a, auto b) { return a == b; }, 123, 456) + ).else_([] { return true; }) + << std::endl; + ok.str(""); ok << false << std::endl; + BOOST_TEST(out.eq(ok.str())); + + out.str(""); + out << + boost::contract::call_if<boost::has_equal_to<x> >( + std::bind([] (auto a, auto b) { return a == b; }, x1, x2) + ).else_([] { return true; }) + << std::endl; + ok.str(""); ok << true << std::endl; + BOOST_TEST(out.eq(ok.str())); + + out.str(""); + out << // Test explicit result, cannot deduce from lambda missing `-> bool`. + boost::contract::call_if<boost::has_equal_to<x> >( + std::bind([] (auto a, auto b) { return a == b; }, x1, x2) + ).else_([] { return true; }) + << std::endl; + ok.str(""); ok << true << std::endl; + BOOST_TEST(out.eq(ok.str())); + + return boost::report_errors(); +} + diff --git a/src/boost/libs/contract/test/call_if/false_.cpp b/src/boost/libs/contract/test/call_if/false_.cpp new file mode 100644 index 000000000..c604f6d82 --- /dev/null +++ b/src/boost/libs/contract/test/call_if/false_.cpp @@ -0,0 +1,65 @@ + +// Copyright (C) 2008-2018 Lorenzo Caminiti +// Distributed under the Boost Software License, Version 1.0 (see accompanying +// file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt). +// See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html + +// Test call_if with false condition and non-void result type. + +#include "../detail/oteststream.hpp" +#include <boost/contract/call_if.hpp> +#include <boost/bind.hpp> +#include <boost/type_traits/has_equal_to.hpp> +#include <boost/detail/lightweight_test.hpp> +#include <sstream> +#include <ios> + +boost::contract::test::detail::oteststream out; + +struct eq { + typedef bool result_type; // Test non-void result type. + + template<typename L, typename R> + result_type operator()(L left, R right) const { + return left == right; // Requires operator==. + } +}; + +struct x {}; // Doest not have operator==. + +int main() { + std::ostringstream ok; + ok << std::boolalpha; + out << std::boolalpha; + x x1, x2;; + + out.str(""); + out << + boost::contract::call_if<boost::has_equal_to<x> >( + boost::bind(eq(), x1, x1) // Compiler-error... but not called. + ).else_([] { return false; }) // Test else. + << std::endl; + ok.str(""); ok << false << std::endl; + BOOST_TEST(out.eq(ok.str())); + + out.str(""); + out << + boost::contract::call_if<boost::has_equal_to<x> >( + boost::bind(eq(), x1, x2) // Compiler-error... but not called. + ).else_([] { return true; }) + << std::endl; + ok.str(""); ok << true << std::endl; + BOOST_TEST(out.eq(ok.str())); + + out.str(""); + out << // Test "..._c". + boost::contract::call_if_c<boost::has_equal_to<x>::value>( + boost::bind(eq(), x1, x2) // Compiler-error...but not called. + ).else_([] { return true; }) + << std::endl; + ok.str(""); ok << true << std::endl; + BOOST_TEST(out.eq(ok.str())); + + return boost::report_errors(); +} + diff --git a/src/boost/libs/contract/test/call_if/false_void.cpp b/src/boost/libs/contract/test/call_if/false_void.cpp new file mode 100644 index 000000000..ca6465cd6 --- /dev/null +++ b/src/boost/libs/contract/test/call_if/false_void.cpp @@ -0,0 +1,55 @@ + +// Copyright (C) 2008-2018 Lorenzo Caminiti +// Distributed under the Boost Software License, Version 1.0 (see accompanying +// file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt). +// See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html + +// Test call_if with false condition and void result type. + +#include "../detail/oteststream.hpp" +#include <boost/contract/call_if.hpp> +#include <boost/bind.hpp> +#include <boost/type_traits/has_equal_to.hpp> +#include <boost/detail/lightweight_test.hpp> +#include <sstream> +#include <ios> + +boost::contract::test::detail::oteststream out; + +struct eq { + typedef void result_type; // Test void result type. + + template<typename L, typename R> + result_type operator()(L left, R right) const { + out << (left == right) << std::endl; // Requires operator==. + } +}; + +struct x {}; // Doest not have operator==. + +int main() { + std::ostringstream ok; + ok << std::boolalpha; + out << std::boolalpha; + x x1, x2;; + + out.str(""); + boost::contract::call_if<boost::has_equal_to<x> >( + boost::bind(eq(), x1, x2) // Compiler-error... but not called. + ); // Test no else. + ok.str(""); + BOOST_TEST(out.eq(ok.str())); + + out.str(""); + // Test "..._c". + boost::contract::call_if_c<boost::has_equal_to<x>::value>( + boost::bind(eq(), x1, x2) // Compiler-error...but not called. + ).else_( + [] { out << true << std::endl; } // Test else. + ); + ok.str(""); ok << true << std::endl; + BOOST_TEST(out.eq(ok.str())); + + return boost::report_errors(); +} + diff --git a/src/boost/libs/contract/test/call_if/no_equal_call_if.cpp b/src/boost/libs/contract/test/call_if/no_equal_call_if.cpp new file mode 100644 index 000000000..854cffc5c --- /dev/null +++ b/src/boost/libs/contract/test/call_if/no_equal_call_if.cpp @@ -0,0 +1,66 @@ + +// Copyright (C) 2008-2018 Lorenzo Caminiti +// Distributed under the Boost Software License, Version 1.0 (see accompanying +// file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt). +// See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html + +// Test assertions skipped when operations to check them missing (e.g., `==`). + +// C++17 warning from Boost.Bind. +#define _SILENCE_CXX17_ADAPTOR_TYPEDEFS_DEPRECATION_WARNING + +#include <boost/contract/function.hpp> +#include <boost/contract/check.hpp> +#include <boost/contract/assert.hpp> +#include <boost/contract/call_if.hpp> +#include <boost/bind.hpp> +#include <boost/type_traits/has_equal_to.hpp> +#include <boost/detail/lightweight_test.hpp> +#include <functional> +#include <vector> + +unsigned equal_skips; + +template<typename T> +void push_back(std::vector<T>& vect, T const& value) { + boost::contract::check c = boost::contract::function() + .postcondition([&] { + BOOST_CONTRACT_ASSERT( + boost::contract::call_if<boost::has_equal_to<T> >( + boost::bind(std::equal_to<T>(), boost::cref(vect.back()), + boost::cref(value)) + // Explicit bool return and [&] needed for MSVC10 lambdas. + ).else_([&] () -> bool { ++equal_skips; return true; }) + ); + }) + ; + vect.push_back(value); +} + +struct j { // Type without operator==. + explicit j(int /* i */) {} +}; + +int main() { + std::vector<int> vi; + equal_skips = 0; + push_back(vi, 123); + BOOST_TEST_EQ(equal_skips, 0); + + unsigned const cnt = + #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS + 1 + #else + 0 + #endif + ; + + j jj(456); + std::vector<j> vj; + equal_skips = 0; + push_back(vj, jj); + BOOST_TEST_EQ(equal_skips, cnt); + + return boost::report_errors(); +} + diff --git a/src/boost/libs/contract/test/call_if/no_equal_condition_if.cpp b/src/boost/libs/contract/test/call_if/no_equal_condition_if.cpp new file mode 100644 index 000000000..e4929d164 --- /dev/null +++ b/src/boost/libs/contract/test/call_if/no_equal_condition_if.cpp @@ -0,0 +1,66 @@ + +// Copyright (C) 2008-2018 Lorenzo Caminiti +// Distributed under the Boost Software License, Version 1.0 (see accompanying +// file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt). +// See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html + +// Test assertions skipped when operations to check them missing (e.g., `==`). + +// C++17 warning from Boost.Bind. +#define _SILENCE_CXX17_ADAPTOR_TYPEDEFS_DEPRECATION_WARNING + +#include <boost/contract/function.hpp> +#include <boost/contract/check.hpp> +#include <boost/contract/assert.hpp> +#include <boost/contract/call_if.hpp> +#include <boost/bind.hpp> +#include <boost/type_traits/has_equal_to.hpp> +#include <boost/detail/lightweight_test.hpp> +#include <functional> +#include <vector> + +unsigned equal_skips; + +template<typename T> +void push_back(std::vector<T>& vect, T const& value) { + boost::contract::check c = boost::contract::function() + .postcondition([&] { + BOOST_CONTRACT_ASSERT( + boost::contract::condition_if<boost::has_equal_to<T> >( + boost::bind(std::equal_to<T>(), boost::cref(vect.back()), + boost::cref(value)) + ) + ); + if(!boost::has_equal_to<T>::value) ++equal_skips; + }) + ; + vect.push_back(value); +} + +struct j { // Type without operator==. + explicit j(int /* i */) {} +}; + +int main() { + std::vector<int> vi; + equal_skips = 0; + push_back(vi, 123); + BOOST_TEST_EQ(equal_skips, 0u); + + unsigned const cnt = + #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS + 1 + #else + 0 + #endif + ; + + j jj(456); + std::vector<j> vj; + equal_skips = 0; + push_back(vj, jj); + BOOST_TEST_EQ(equal_skips, cnt); + + return boost::report_errors(); +} + diff --git a/src/boost/libs/contract/test/call_if/no_equal_error.cpp b/src/boost/libs/contract/test/call_if/no_equal_error.cpp new file mode 100644 index 000000000..025e9c765 --- /dev/null +++ b/src/boost/libs/contract/test/call_if/no_equal_error.cpp @@ -0,0 +1,41 @@ + +// Copyright (C) 2008-2018 Lorenzo Caminiti +// Distributed under the Boost Software License, Version 1.0 (see accompanying +// file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt). +// See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html + +// Test assertion error when operations to check them missing (e.g., `==`). + +#include <boost/contract/function.hpp> +#include <boost/contract/check.hpp> +#include <boost/contract/assert.hpp> +#include <vector> + +template<typename T> +void push_back(std::vector<T>& vect, T const& value) { + boost::contract::check c = boost::contract::function() + .postcondition([&] { + BOOST_CONTRACT_ASSERT(vect.back() == value); // Error (j has no ==). + #ifdef BOOST_CONTRACT_NO_ALL + #error "force error if no contracts (ASSERT expands to nothing)" + #endif + }) + ; + vect.push_back(value); +} + +struct j { // Type without operator==. + explicit j(int /* i */) {} +}; + +int main() { + std::vector<int> vi; + push_back(vi, 123); + + j jj(456); + std::vector<j> vj; + push_back(vj, jj); + + return 0; +} + diff --git a/src/boost/libs/contract/test/call_if/true_.cpp b/src/boost/libs/contract/test/call_if/true_.cpp new file mode 100644 index 000000000..d8c47f491 --- /dev/null +++ b/src/boost/libs/contract/test/call_if/true_.cpp @@ -0,0 +1,67 @@ + +// Copyright (C) 2008-2018 Lorenzo Caminiti +// Distributed under the Boost Software License, Version 1.0 (see accompanying +// file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt). +// See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html + +// Test call_if with true condition and non-void result type. + +#include "../detail/oteststream.hpp" +#include <boost/contract/call_if.hpp> +#include <boost/bind.hpp> +#include <boost/type_traits/has_equal_to.hpp> +#include <boost/detail/lightweight_test.hpp> +#include <sstream> +#include <ios> + +boost::contract::test::detail::oteststream out; + +struct eq { + typedef bool result_type; // Test non-void result type. + + template<typename L, typename R> + result_type operator()(L left, R right) const { + return left == right; // Requires operator==. + } +}; + +struct x {}; // Doest not have operator==. + +int main() { + std::ostringstream ok; + ok << std::boolalpha; + out << std::boolalpha; + x x1, x2;; + + out.str(""); + out << + boost::contract::call_if<boost::has_equal_to<int> >( + boost::bind(eq(), 123, 456) // False. + ) // Test no else (not called). + << std::endl; + ok.str(""); ok << false << std::endl; + BOOST_TEST(out.eq(ok.str())); + + out.str(""); + out << + boost::contract::call_if<boost::has_equal_to<int> >( + boost::bind(eq(), 123, 123) // True. + ).else_([] { return false; }) // Test else not called. + << std::endl; + ok.str(""); ok << true << std::endl; + BOOST_TEST(out.eq(ok.str())); + + out.str(""); + out << // Test "..._c". + boost::contract::call_if_c<boost::has_equal_to<int>::value>( + boost::bind(eq(), 123, 123) // True. + ).else_( // Test else not called. + boost::bind(eq(), x1, x2) // Compiler-error... but not called. + ) + << std::endl; + ok.str(""); ok << true << std::endl; + BOOST_TEST(out.eq(ok.str())); + + return boost::report_errors(); +} + diff --git a/src/boost/libs/contract/test/call_if/true_void.cpp b/src/boost/libs/contract/test/call_if/true_void.cpp new file mode 100644 index 000000000..d3279c803 --- /dev/null +++ b/src/boost/libs/contract/test/call_if/true_void.cpp @@ -0,0 +1,64 @@ + +// Copyright (C) 2008-2018 Lorenzo Caminiti +// Distributed under the Boost Software License, Version 1.0 (see accompanying +// file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt). +// See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html + +// Test call_if with true condition and void result type. + +#include "../detail/oteststream.hpp" +#include <boost/contract/call_if.hpp> +#include <boost/bind.hpp> +#include <boost/type_traits/has_equal_to.hpp> +#include <boost/detail/lightweight_test.hpp> +#include <sstream> +#include <ios> + +boost::contract::test::detail::oteststream out; + +struct eq { + typedef void result_type; // Test void result type. + + template<typename L, typename R> + result_type operator()(L left, R right) const { + out << (left == right) << std::endl; // Requires operator==. + } +}; + +struct x {}; // Doest not have operator==. + +int main() { + std::ostringstream ok; + ok << std::boolalpha; + out << std::boolalpha; + x x1, x2;; + + out.str(""); + boost::contract::call_if<boost::has_equal_to<int> >( + boost::bind(eq(), 123, 456) // False. + ); // Test no else (not called). + ok.str(""); ok << false << std::endl; + BOOST_TEST(out.eq(ok.str())); + + out.str(""); + boost::contract::call_if<boost::has_equal_to<int> >( + boost::bind(eq(), 123, 123) // True. + ).else_( + [] { return false; } + ); // Test else (not called). + ok.str(""); ok << true << std::endl; + BOOST_TEST(out.eq(ok.str())); + + out.str(""); + // Test "..._c". + boost::contract::call_if_c<boost::has_equal_to<int>::value>( + boost::bind(eq(), 123, 123) // True. + ).else_( // Test else (not called). + boost::bind(eq(), x1, x2) // Compiler-error... but not called. + ); + ok.str(""); ok << true << std::endl; + BOOST_TEST(out.eq(ok.str())); + + return boost::report_errors(); +} + diff --git a/src/boost/libs/contract/test/check/audit.cpp b/src/boost/libs/contract/test/check/audit.cpp new file mode 100644 index 000000000..cb0765ea7 --- /dev/null +++ b/src/boost/libs/contract/test/check/audit.cpp @@ -0,0 +1,11 @@ + +// Copyright (C) 2008-2018 Lorenzo Caminiti +// Distributed under the Boost Software License, Version 1.0 (see accompanying +// file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt). +// See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html + +#ifndef BOOST_CONTRACT_AUDITS + #error "build must define AUDITS" +#endif +#include "audit.hpp" + diff --git a/src/boost/libs/contract/test/check/audit.hpp b/src/boost/libs/contract/test/check/audit.hpp new file mode 100644 index 000000000..0b649ed96 --- /dev/null +++ b/src/boost/libs/contract/test/check/audit.hpp @@ -0,0 +1,36 @@ + +// no #include guard + +// Copyright (C) 2008-2018 Lorenzo Caminiti +// Distributed under the Boost Software License, Version 1.0 (see accompanying +// file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt). +// See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html + +#include <boost/contract/check.hpp> +#include <boost/contract/core/exception.hpp> +#include <boost/detail/lightweight_test.hpp> + +struct err {}; // Global decl so visible in MSVC10 lambdas. + +int main() { + boost::contract::set_check_failure([] { throw err(); }); + + bool threw = false; + try { + #ifdef BOOST_CONTRACT_TEST_ERROR + BOOST_CONTRACT_CHECK_AUDIT( + BOOST_CONTRACT_TEST_ERROR_expected_undeclared_identifier); + #else + BOOST_CONTRACT_CHECK_AUDIT(false); + #endif + } catch(err const&) { threw = true; } + + #if defined(BOOST_CONTRACT_AUDITS) && !defined(BOOST_CONTRACT_NO_CHECKS) + BOOST_TEST(threw); + #else + BOOST_TEST(!threw); + #endif + + return boost::report_errors(); +} + diff --git a/src/boost/libs/contract/test/check/audit_disabled.cpp b/src/boost/libs/contract/test/check/audit_disabled.cpp new file mode 100644 index 000000000..18c6ad03f --- /dev/null +++ b/src/boost/libs/contract/test/check/audit_disabled.cpp @@ -0,0 +1,8 @@ + +// Copyright (C) 2008-2018 Lorenzo Caminiti +// Distributed under the Boost Software License, Version 1.0 (see accompanying +// file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt). +// See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html + +#include "audit.hpp" + diff --git a/src/boost/libs/contract/test/check/audit_disabled_error.cpp b/src/boost/libs/contract/test/check/audit_disabled_error.cpp new file mode 100644 index 000000000..c58714dce --- /dev/null +++ b/src/boost/libs/contract/test/check/audit_disabled_error.cpp @@ -0,0 +1,9 @@ + +// Copyright (C) 2008-2018 Lorenzo Caminiti +// Distributed under the Boost Software License, Version 1.0 (see accompanying +// file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt). +// See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html + +#define BOOST_CONTRACT_TEST_ERROR +#include "audit.hpp" + diff --git a/src/boost/libs/contract/test/check/audit_error.cpp b/src/boost/libs/contract/test/check/audit_error.cpp new file mode 100644 index 000000000..c58714dce --- /dev/null +++ b/src/boost/libs/contract/test/check/audit_error.cpp @@ -0,0 +1,9 @@ + +// Copyright (C) 2008-2018 Lorenzo Caminiti +// Distributed under the Boost Software License, Version 1.0 (see accompanying +// file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt). +// See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html + +#define BOOST_CONTRACT_TEST_ERROR +#include "audit.hpp" + diff --git a/src/boost/libs/contract/test/check/axiom.cpp b/src/boost/libs/contract/test/check/axiom.cpp new file mode 100644 index 000000000..b24af7a4f --- /dev/null +++ b/src/boost/libs/contract/test/check/axiom.cpp @@ -0,0 +1,8 @@ + +// Copyright (C) 2008-2018 Lorenzo Caminiti +// Distributed under the Boost Software License, Version 1.0 (see accompanying +// file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt). +// See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html + +#include "axiom.hpp" + diff --git a/src/boost/libs/contract/test/check/axiom.hpp b/src/boost/libs/contract/test/check/axiom.hpp new file mode 100644 index 000000000..ddf87f8c8 --- /dev/null +++ b/src/boost/libs/contract/test/check/axiom.hpp @@ -0,0 +1,23 @@ + +// no #include guard + +// Copyright (C) 2008-2018 Lorenzo Caminiti +// Distributed under the Boost Software License, Version 1.0 (see accompanying +// file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt). +// See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html + +#include <boost/contract/check.hpp> + +bool no_impl(); // Test func that cannot be impl in C++ sill OK in axioms. + +int main() { + #ifdef BOOST_CONTRACT_TEST_ERROR + BOOST_CONTRACT_CHECK_AXIOM( + BOOST_CONTRACT_TEST_ERROR_expected_undeclared_identifier); + #else + BOOST_CONTRACT_CHECK_AXIOM(false); // Test always false, OK. + BOOST_CONTRACT_CHECK_AXIOM(no_impl()); // Test no implementation, OK. + #endif + return 0; +} + diff --git a/src/boost/libs/contract/test/check/axiom_error.cpp b/src/boost/libs/contract/test/check/axiom_error.cpp new file mode 100644 index 000000000..a7c4c406d --- /dev/null +++ b/src/boost/libs/contract/test/check/axiom_error.cpp @@ -0,0 +1,9 @@ + +// Copyright (C) 2008-2018 Lorenzo Caminiti +// Distributed under the Boost Software License, Version 1.0 (see accompanying +// file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt). +// See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html + +#define BOOST_CONTRACT_TEST_ERROR +#include "axiom.hpp" + diff --git a/src/boost/libs/contract/test/check/decl.hpp b/src/boost/libs/contract/test/check/decl.hpp new file mode 100644 index 000000000..1b592fb3c --- /dev/null +++ b/src/boost/libs/contract/test/check/decl.hpp @@ -0,0 +1,66 @@ + +// Copyright (C) 2008-2018 Lorenzo Caminiti +// Distributed under the Boost Software License, Version 1.0 (see accompanying +// file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt). +// See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html + +// Test check (class and macro). + +#include "../detail/oteststream.hpp" +#include <boost/contract/check.hpp> +#include <boost/contract/assert.hpp> +#include <boost/detail/lightweight_test.hpp> +#include <sstream> + +boost::contract::test::detail::oteststream out; + +struct err {}; // Global decl so visible in MSVC10 lambdas. + +void f(bool check) { + #ifdef BOOST_CONTRACT_TEST_CHECK_MACRO + BOOST_CONTRACT_CHECK([&] () -> bool { + out << "f::check" << std::endl; + return check; + }()); + #else + boost::contract::check c = [&] { + out << "f::check" << std::endl; + BOOST_CONTRACT_ASSERT(check); + }; + #endif + out << "f::body" << std::endl; +} + +int main() { + std::ostringstream ok; + + out.str(""); + f(true); + ok.str(""); ok + #ifndef BOOST_CONTRACT_NO_CHECKS + << "f::check" << std::endl + #endif + << "f::body" << std::endl + ; + BOOST_TEST(out.eq(ok.str())); + + boost::contract::set_check_failure([] { throw err(); }); + + out.str(""); + try { + f(false); + #ifndef BOOST_CONTRACT_NO_CHECKS + BOOST_TEST(false); + } catch(err const&) { + ok.str(""); + ok << "f::check" << std::endl; + #else + ok.str(""); + ok << "f::body" << std::endl; + #endif + BOOST_TEST(out.eq(ok.str())); + } catch(...) { BOOST_TEST(false); } + + return boost::report_errors(); +} + diff --git a/src/boost/libs/contract/test/check/decl_class.cpp b/src/boost/libs/contract/test/check/decl_class.cpp new file mode 100644 index 000000000..eb5863410 --- /dev/null +++ b/src/boost/libs/contract/test/check/decl_class.cpp @@ -0,0 +1,11 @@ + +// Copyright (C) 2008-2018 Lorenzo Caminiti +// Distributed under the Boost Software License, Version 1.0 (see accompanying +// file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt). +// See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html + +// Test check class. + +#undef BOOST_CONTRACT_TEST_CHECK_MACRO +#include "decl.hpp" + diff --git a/src/boost/libs/contract/test/check/decl_macro.cpp b/src/boost/libs/contract/test/check/decl_macro.cpp new file mode 100644 index 000000000..f36ce189c --- /dev/null +++ b/src/boost/libs/contract/test/check/decl_macro.cpp @@ -0,0 +1,11 @@ + +// Copyright (C) 2008-2018 Lorenzo Caminiti +// Distributed under the Boost Software License, Version 1.0 (see accompanying +// file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt). +// See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html + +// Test check macro. + +#define BOOST_CONTRACT_TEST_CHECK_MACRO +#include "decl.hpp" + diff --git a/src/boost/libs/contract/test/check/ifdef.cpp b/src/boost/libs/contract/test/check/ifdef.cpp new file mode 100644 index 000000000..561eb76ee --- /dev/null +++ b/src/boost/libs/contract/test/check/ifdef.cpp @@ -0,0 +1,90 @@ + +// Copyright (C) 2008-2018 Lorenzo Caminiti +// Distributed under the Boost Software License, Version 1.0 (see accompanying +// file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt). +// See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html + +// Test contract compilation on/off. + +#include "../detail/oteststream.hpp" +#include <boost/contract/core/config.hpp> +#ifndef BOOST_CONTRACT_NO_CHECKS + #include <boost/contract/check.hpp> + #include <boost/contract/assert.hpp> +#else + #include <boost/contract/core/check_macro.hpp> + #include <boost/contract/core/exception.hpp> +#endif +#include <boost/detail/lightweight_test.hpp> +#include <sstream> + +boost::contract::test::detail::oteststream out; + +void f(bool check1, bool check2) { + BOOST_CONTRACT_CHECK([&] () -> bool { // Macro already so #ifdef needed. + out << "f::check1" << std::endl; + return check1; + }()); + #ifndef BOOST_CONTRACT_NO_CHECKS + boost::contract::check c = [&] { + out << "f::check2" << std::endl; + BOOST_CONTRACT_ASSERT(check2); + }; + #endif + out << "f::body" << std::endl; +} + +struct err {}; // Global decl so visible in MSVC10 lambdas. + +int main() { + std::ostringstream ok; + + out.str(""); + f(true, true); + ok.str(""); ok + #ifndef BOOST_CONTRACT_NO_CHECKS + << "f::check1" << std::endl + << "f::check2" << std::endl + #endif + << "f::body" << std::endl + ; + BOOST_TEST(out.eq(ok.str())); + + boost::contract::set_check_failure([] { throw err(); }); + + out.str(""); + try { + f(false, true); + #ifndef BOOST_CONTRACT_NO_CHECKS + BOOST_TEST(false); + } catch(err const&) { + ok.str(""); + ok << "f::check1" << std::endl; + #else + ok.str(""); + ok << "f::body" << std::endl; + #endif + BOOST_TEST(out.eq(ok.str())); + } catch(...) { BOOST_TEST(false); } + + out.str(""); + try { + f(true, false); + #ifndef BOOST_CONTRACT_NO_CHECKS + BOOST_TEST(false); + } catch(err const&) { + ok.str(""); + ok << "f::check1" << std::endl; + ok << "f::check2" << std::endl; + #else + ok.str(""); + ok << "f::body" << std::endl; + #endif + BOOST_TEST(out.eq(ok.str())); + } catch(...) { BOOST_TEST(false); } + + // No need to test `f(false, false)` because same as `f(false, true)`. + + return boost::report_errors(); +} + diff --git a/src/boost/libs/contract/test/check/ifdef_macro.cpp b/src/boost/libs/contract/test/check/ifdef_macro.cpp new file mode 100644 index 000000000..67616a892 --- /dev/null +++ b/src/boost/libs/contract/test/check/ifdef_macro.cpp @@ -0,0 +1,63 @@ + +// Copyright (C) 2008-2018 Lorenzo Caminiti +// Distributed under the Boost Software License, Version 1.0 (see accompanying +// file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt). +// See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html + +// Test contract compilation on/off (using macro interface only). + +#include "../detail/oteststream.hpp" +#include "../detail/unprotected_commas.hpp" +#include <boost/contract_macro.hpp> +#include <boost/detail/lightweight_test.hpp> +#include <sstream> + +boost::contract::test::detail::oteststream out; + +void f(bool check) { + BOOST_CONTRACT_CHECK(( + [&] () -> bool { + boost::contract::test::detail::unprotected_commas<void, void, void> + ::call(); + out << "f::check" << std::endl; + return check; + }() + )); + out << "f::body" << std::endl; +} + +struct err {}; // Global decl so visible in MSVC10 lambdas. + +int main() { + std::ostringstream ok; + + out.str(""); + f(true); + ok.str(""); ok + #ifndef BOOST_CONTRACT_NO_CHECKS + << "f::check" << std::endl + #endif + << "f::body" << std::endl + ; + BOOST_TEST(out.eq(ok.str())); + + boost::contract::set_check_failure([] { throw err(); }); + + out.str(""); + try { + f(false); + #ifndef BOOST_CONTRACT_NO_CHECKS + BOOST_TEST(false); + } catch(err const&) { + ok.str(""); + ok << "f::check" << std::endl; + #else + ok.str(""); + ok << "f::body" << std::endl; + #endif + BOOST_TEST(out.eq(ok.str())); + } catch(...) { BOOST_TEST(false); } + + return boost::report_errors(); +} + diff --git a/src/boost/libs/contract/test/constructor/access.cpp b/src/boost/libs/contract/test/constructor/access.cpp new file mode 100644 index 000000000..19eae17d9 --- /dev/null +++ b/src/boost/libs/contract/test/constructor/access.cpp @@ -0,0 +1,136 @@ + +// Copyright (C) 2008-2018 Lorenzo Caminiti +// Distributed under the Boost Software License, Version 1.0 (see accompanying +// file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt). +// See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html + +// Test making all contract extra declarations (base types, inv, etc.) private. + +#include "../detail/oteststream.hpp" +#include <boost/contract/constructor.hpp> +#include <boost/contract/base_types.hpp> +#include <boost/contract/check.hpp> +#include <boost/detail/lightweight_test.hpp> +#include <sstream> + +boost::contract::test::detail::oteststream out; + +class b + #define BASES private boost::contract::constructor_precondition<b> + : BASES +{ + friend class boost::contract::access; + + typedef BOOST_CONTRACT_BASE_TYPES(BASES) base_types; + #undef BASES + + static void static_invariant() { out << "b::static_inv" << std::endl; } + void invariant() const { out << "b::inv" << std::endl; } + +public: + b() : boost::contract::constructor_precondition<b>([] { + out << "b::ctor::pre" << std::endl; + }) { + boost::contract::check c = boost::contract::constructor(this) + .old([] { out << "b::ctor::old" << std::endl; }) + .postcondition([] { out << "b::ctor::post" << std::endl; }) + ; + out << "b::ctor::body" << std::endl; + } +}; + +class a + #define BASES private boost::contract::constructor_precondition<a>, public b + : BASES +{ + friend class boost::contract::access; + + // Private base types (always OK because never used by ctors). + typedef BOOST_CONTRACT_BASE_TYPES(BASES) base_types; + #undef BASES + + // Private invariants. + static void static_invariant() { out << "a::static_inv" << std::endl; } + void invariant() const { out << "a::inv" << std::endl; } + +public: + a() : boost::contract::constructor_precondition<a>([] { + out << "a::ctor::pre" << std::endl; + }) { + boost::contract::check c = boost::contract::constructor(this) + .old([] { out << "a::ctor::old" << std::endl; }) + .postcondition([] { out << "a::ctor::post" << std::endl; }) + ; + out << "a::ctor::body" << std::endl; + } +}; + +int main() { + std::ostringstream ok; + + out.str(""); + a aa; + ok.str(""); ok + #ifndef BOOST_CONTRACT_NO_PRECONDITIONS + << "a::ctor::pre" << std::endl + << "b::ctor::pre" << std::endl + #endif + + #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS + << "b::static_inv" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_OLDS + << "b::ctor::old" << std::endl + #endif + << "b::ctor::body" << std::endl + #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS + << "b::static_inv" << std::endl + << "b::inv" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS + << "b::ctor::post" << std::endl + #endif + + #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS + << "a::static_inv" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_OLDS + << "a::ctor::old" << std::endl + #endif + << "a::ctor::body" << std::endl + #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS + << "a::static_inv" << std::endl + << "a::inv" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS + << "a::ctor::post" << std::endl + #endif + ; + BOOST_TEST(out.eq(ok.str())); + + out.str(""); + b bb; + ok.str(""); ok + #ifndef BOOST_CONTRACT_NO_PRECONDITIONS + << "b::ctor::pre" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS + << "b::static_inv" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_OLDS + << "b::ctor::old" << std::endl + #endif + << "b::ctor::body" << std::endl + #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS + << "b::static_inv" << std::endl + << "b::inv" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS + << "b::ctor::post" << std::endl + #endif + ; + BOOST_TEST(out.eq(ok.str())); + + return boost::report_errors(); +} + diff --git a/src/boost/libs/contract/test/constructor/decl.hpp b/src/boost/libs/contract/test/constructor/decl.hpp new file mode 100644 index 000000000..59e42128c --- /dev/null +++ b/src/boost/libs/contract/test/constructor/decl.hpp @@ -0,0 +1,170 @@ + +#ifndef BOOST_CONTRACT_TEST_CONSTRUCTOR_DECL_HPP_ +#define BOOST_CONTRACT_TEST_CONSTRUCTOR_DECL_HPP_ + +// Copyright (C) 2008-2018 Lorenzo Caminiti +// Distributed under the Boost Software License, Version 1.0 (see accompanying +// file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt). +// See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html + +// Test with and without pre, post, and inv declarations. + +#include "../detail/oteststream.hpp" +#include <boost/contract/constructor.hpp> +#include <boost/contract/base_types.hpp> +#include <boost/contract/check.hpp> +#include <boost/contract/assert.hpp> + +boost::contract::test::detail::oteststream out; + +bool c_pre = true, c_post = true; +bool c_entering_static_inv = true, c_entry_static_inv = true, + c_exit_static_inv = true; +bool c_exit_inv = true; // Only exit non-static inv for ctors. +struct c + #ifndef BOOST_CONTRACT_TEST_NO_C_PRE + : private boost::contract::constructor_precondition<c> + #endif +{ + #ifndef BOOST_CONTRACT_TEST_NO_C_STATIC_INV + static void static_invariant() { + out << "c::static_inv" << std::endl; + if(c_entering_static_inv) BOOST_CONTRACT_ASSERT(c_entry_static_inv); + else BOOST_CONTRACT_ASSERT(c_exit_static_inv); + c_entering_static_inv = false; + } + #endif + #ifndef BOOST_CONTRACT_TEST_NO_C_INV + void invariant() const { + out << "c::inv" << std::endl; + BOOST_CONTRACT_ASSERT(c_exit_inv); + } + #endif + + c() + #ifndef BOOST_CONTRACT_TEST_NO_C_PRE + : boost::contract::constructor_precondition<c>([] { + out << "c::ctor::pre" << std::endl; + BOOST_CONTRACT_ASSERT(c_pre); + }) + #endif + { + boost::contract::check c = boost::contract::constructor(this) + .old([] { out << "c::ctor::old" << std::endl; }) + #ifndef BOOST_CONTRACT_TEST_NO_C_POST + .postcondition([] { + out << "c::ctor::post" << std::endl; + BOOST_CONTRACT_ASSERT(c_post); + }) + #endif + ; + out << "c::ctor::body" << std::endl; + } +}; + +bool b_pre = true, b_post = true; +bool b_entering_static_inv = true, b_entry_static_inv = true, + b_exit_static_inv = true; +bool b_exit_inv = true; // Only exit non-static inv for ctors. +struct b + #ifndef BOOST_CONTRACT_TEST_NO_B_PRE + #define BASES \ + private boost::contract::constructor_precondition<b>, public c + #else + #define BASES public c + #endif + : BASES +{ + typedef BOOST_CONTRACT_BASE_TYPES(BASES) base_types; + #undef BASES + + #ifndef BOOST_CONTRACT_TEST_NO_B_STATIC_INV + static void static_invariant() { + out << "b::static_inv" << std::endl; + if(b_entering_static_inv) BOOST_CONTRACT_ASSERT(b_entry_static_inv); + else BOOST_CONTRACT_ASSERT(b_exit_static_inv); + b_entering_static_inv = false; + } + #endif + #ifndef BOOST_CONTRACT_TEST_NO_B_INV + void invariant() const { + out << "b::inv" << std::endl; + BOOST_CONTRACT_ASSERT(b_exit_inv); + } + #endif + + b() + #ifndef BOOST_CONTRACT_TEST_NO_B_PRE + : boost::contract::constructor_precondition<b>([] { + out << "b::ctor::pre" << std::endl; + BOOST_CONTRACT_ASSERT(b_pre); + }) + #endif + { + boost::contract::check c = boost::contract::constructor(this) + .old([] { out << "b::ctor::old" << std::endl; }) + #ifndef BOOST_CONTRACT_TEST_NO_B_POST + .postcondition([] { + out << "b::ctor::post" << std::endl; + BOOST_CONTRACT_ASSERT(b_post); + }) + #endif + ; + out << "b::ctor::body" << std::endl; + } +}; + +bool a_pre = true, a_post = true; +bool a_entering_static_inv = true, a_entry_static_inv = true, + a_exit_static_inv = true; +bool a_exit_inv = true; // Only exit non-static inv for ctors. +struct a + #ifndef BOOST_CONTRACT_TEST_NO_A_PRE + #define BASES \ + private boost::contract::constructor_precondition<a>, public b + #else + #define BASES public b + #endif + : BASES +{ + typedef BOOST_CONTRACT_BASE_TYPES(BASES) base_types; + #undef BASES + + #ifndef BOOST_CONTRACT_TEST_NO_A_STATIC_INV + static void static_invariant() { + out << "a::static_inv" << std::endl; + if(a_entering_static_inv) BOOST_CONTRACT_ASSERT(a_entry_static_inv); + else BOOST_CONTRACT_ASSERT(a_exit_static_inv); + a_entering_static_inv = false; + } + #endif + #ifndef BOOST_CONTRACT_TEST_NO_A_INV + void invariant() const { + out << "a::inv" << std::endl; + BOOST_CONTRACT_ASSERT(a_exit_inv); + } + #endif + + a() + #ifndef BOOST_CONTRACT_TEST_NO_A_PRE + : boost::contract::constructor_precondition<a>([] { + out << "a::ctor::pre" << std::endl; + BOOST_CONTRACT_ASSERT(a_pre); + }) + #endif + { + boost::contract::check c = boost::contract::constructor(this) + .old([] { out << "a::ctor::old" << std::endl; }) + #ifndef BOOST_CONTRACT_TEST_NO_A_POST + .postcondition([] { + out << "a::ctor::post" << std::endl; + BOOST_CONTRACT_ASSERT(a_post); + }) + #endif + ; + out << "a::ctor::body" << std::endl; + } +}; + +#endif // #include guard + diff --git a/src/boost/libs/contract/test/constructor/decl_entry_static_inv_all.cpp b/src/boost/libs/contract/test/constructor/decl_entry_static_inv_all.cpp new file mode 100644 index 000000000..b5f4ad6fe --- /dev/null +++ b/src/boost/libs/contract/test/constructor/decl_entry_static_inv_all.cpp @@ -0,0 +1,219 @@ + +// Copyright (C) 2008-2018 Lorenzo Caminiti +// Distributed under the Boost Software License, Version 1.0 (see accompanying +// file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt). +// See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html + +// Test all derived and base classes with entry static invariants. + +#undef BOOST_CONTRACT_TEST_NO_A_STATIC_INV +#undef BOOST_CONTRACT_TEST_NO_B_STATIC_INV +#undef BOOST_CONTRACT_TEST_NO_C_STATIC_INV +#include "decl.hpp" + +#include <boost/preprocessor/control/iif.hpp> +#include <boost/detail/lightweight_test.hpp> +#include <sstream> +#include <string> + +std::string ok_c() { + std::ostringstream ok; ok << "" // Suppress a warning. + #ifndef BOOST_CONTRACT_NO_PRECONDITIONS + << "a::ctor::pre" << std::endl + << "b::ctor::pre" << std::endl + << "c::ctor::pre" << std::endl + #endif + + #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS + << "c::static_inv" << std::endl // Might fail. + #endif + ; + return ok.str(); +} + +std::string ok_b() { + std::ostringstream ok; ok + #ifndef BOOST_CONTRACT_NO_OLDS + << "c::ctor::old" << std::endl + #endif + << "c::ctor::body" << std::endl + #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS + << "c::static_inv" << std::endl + << "c::inv" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS + << "c::ctor::post" << std::endl + #endif + + #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS + << "b::static_inv" << std::endl // Might fail. + #endif + ; + return ok.str(); +} + +std::string ok_a() { + std::ostringstream ok; ok + #ifndef BOOST_CONTRACT_NO_OLDS + << "b::ctor::old" << std::endl + #endif + << "b::ctor::body" << std::endl + #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS + << "b::static_inv" << std::endl + << "b::inv" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS + << "b::ctor::post" << std::endl + #endif + + #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS + << "a::static_inv" << std::endl // Might fail. + #endif + ; + return ok.str(); +} + +std::string ok_end() { + std::ostringstream ok; ok + #ifndef BOOST_CONTRACT_NO_OLDS + << "a::ctor::old" << std::endl + #endif + << "a::ctor::body" << std::endl + #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS + << "a::static_inv" << std::endl + << "a::inv" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS + << "a::ctor::post" << std::endl + #endif + ; + return ok.str(); +} + +struct err {}; // Global decl so visible in MSVC10 lambdas. + +int main() { + std::ostringstream ok; + + #ifdef BOOST_CONTRACT_NO_ENTRY_INVARIANTS + #define BOOST_CONTRACT_TEST_entry_inv 0 + #else + #define BOOST_CONTRACT_TEST_entry_inv 1 + #endif + + a_entry_static_inv = true; + b_entry_static_inv = true; + c_entry_static_inv = true; + a_entering_static_inv = b_entering_static_inv = c_entering_static_inv = + BOOST_PP_IIF(BOOST_CONTRACT_TEST_entry_inv, true, false); + { + out.str(""); + a aa; + ok.str(""); ok // Test nothing failed. + << ok_c() + << ok_b() + << ok_a() + << ok_end() + ; + BOOST_TEST(out.eq(ok.str())); + } + + boost::contract::set_entry_invariant_failure( + [] (boost::contract::from) { throw err(); }); + + a_entry_static_inv = false; + b_entry_static_inv = true; + c_entry_static_inv = true; + a_entering_static_inv = b_entering_static_inv = c_entering_static_inv = + BOOST_PP_IIF(BOOST_CONTRACT_TEST_entry_inv, true, false); + try { + out.str(""); + a aa; + #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS + BOOST_TEST(false); + } catch(err const&) { + #endif + ok.str(""); ok + << ok_c() + << ok_b() + << ok_a() // Test a::static_inv failed. + #ifdef BOOST_CONTRACT_NO_ENTRY_INVARIANTS + << ok_end() + #endif + ; + BOOST_TEST(out.eq(ok.str())); + } catch(...) { BOOST_TEST(false); } + + a_entry_static_inv = true; + b_entry_static_inv = false; + c_entry_static_inv = true; + a_entering_static_inv = b_entering_static_inv = c_entering_static_inv = + BOOST_PP_IIF(BOOST_CONTRACT_TEST_entry_inv, true, false); + try { + out.str(""); + a aa; + #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS + BOOST_TEST(false); + } catch(err const&) { + #endif + ok.str(""); ok + << ok_c() + << ok_b() // Test b::static_inv failed. + #ifdef BOOST_CONTRACT_NO_ENTRY_INVARIANTS + << ok_a() + << ok_end() + #endif + ; + BOOST_TEST(out.eq(ok.str())); + } catch(...) { BOOST_TEST(false); } + + a_entry_static_inv = true; + b_entry_static_inv = true; + c_entry_static_inv = false; + a_entering_static_inv = b_entering_static_inv = c_entering_static_inv = + BOOST_PP_IIF(BOOST_CONTRACT_TEST_entry_inv, true, false); + try { + out.str(""); + a aa; + #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS + BOOST_TEST(false); + } catch(err const&) { + #endif + ok.str(""); ok + << ok_c() // Test c::static_inv failed. + #ifdef BOOST_CONTRACT_NO_ENTRY_INVARIANTS + << ok_b() + << ok_a() + << ok_end() + #endif + ; + BOOST_TEST(out.eq(ok.str())); + } catch(...) { BOOST_TEST(false); } + + a_entry_static_inv = false; + b_entry_static_inv = false; + c_entry_static_inv = false; + a_entering_static_inv = b_entering_static_inv = c_entering_static_inv = + BOOST_PP_IIF(BOOST_CONTRACT_TEST_entry_inv, true, false); + try { + out.str(""); + a aa; + #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS + BOOST_TEST(false); + } catch(err const&) { + #endif + ok.str(""); ok + << ok_c() // Test c::static_inv failed (as all did). + #ifdef BOOST_CONTRACT_NO_ENTRY_INVARIANTS + << ok_b() + << ok_a() + << ok_end() + #endif + ; + BOOST_TEST(out.eq(ok.str())); + } catch(...) { BOOST_TEST(false); } + + #undef BOOST_CONTRACT_TEST_entry_inv + return boost::report_errors(); +} + diff --git a/src/boost/libs/contract/test/constructor/decl_entry_static_inv_ends.cpp b/src/boost/libs/contract/test/constructor/decl_entry_static_inv_ends.cpp new file mode 100644 index 000000000..32168cb93 --- /dev/null +++ b/src/boost/libs/contract/test/constructor/decl_entry_static_inv_ends.cpp @@ -0,0 +1,209 @@ + +// Copyright (C) 2008-2018 Lorenzo Caminiti +// Distributed under the Boost Software License, Version 1.0 (see accompanying +// file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt). +// See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html + +// Test only derived and grandparent classes (ends) with entry static inv. + +#undef BOOST_CONTRACT_TEST_NO_A_STATIC_INV +#define BOOST_CONTRACT_TEST_NO_B_STATIC_INV +#undef BOOST_CONTRACT_TEST_NO_C_STATIC_INV +#include "decl.hpp" + +#include <boost/preprocessor/control/iif.hpp> +#include <boost/detail/lightweight_test.hpp> +#include <sstream> +#include <string> + +std::string ok_c() { + std::ostringstream ok; ok << "" // Suppress a warning. + #ifndef BOOST_CONTRACT_NO_PRECONDITIONS + << "a::ctor::pre" << std::endl + << "b::ctor::pre" << std::endl + << "c::ctor::pre" << std::endl + #endif + + #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS + << "c::static_inv" << std::endl // This might fail. + #endif + ; + return ok.str(); +} + +std::string ok_b() { + std::ostringstream ok; ok + #ifndef BOOST_CONTRACT_NO_OLDS + << "c::ctor::old" << std::endl + #endif + << "c::ctor::body" << std::endl + #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS + << "c::static_inv" << std::endl + << "c::inv" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS + << "c::ctor::post" << std::endl + // No b::static_inv to fail. + #endif + ; + return ok.str(); +} + +std::string ok_a() { + std::ostringstream ok; ok + #ifndef BOOST_CONTRACT_NO_OLDS + << "b::ctor::old" << std::endl + #endif + << "b::ctor::body" << std::endl + #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS + << "b::inv" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS + << "b::ctor::post" << std::endl + #endif + + #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS + << "a::static_inv" << std::endl // This might fail. + #endif + ; + return ok.str(); +} + +std::string ok_end() { + std::ostringstream ok; ok + #ifndef BOOST_CONTRACT_NO_OLDS + << "a::ctor::old" << std::endl + #endif + << "a::ctor::body" << std::endl + #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS + << "a::static_inv" << std::endl + << "a::inv" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS + << "a::ctor::post" << std::endl + #endif + ; + return ok.str(); +} + +struct err {}; // Global decl so visible in MSVC10 lambdas. + +int main() { + std::ostringstream ok; + + #ifdef BOOST_CONTRACT_NO_ENTRY_INVARIANTS + #define BOOST_CONTRACT_TEST_entry_inv 0 + #else + #define BOOST_CONTRACT_TEST_entry_inv 1 + #endif + + a_entry_static_inv = true; + b_entry_static_inv = true; + c_entry_static_inv = true; + a_entering_static_inv = b_entering_static_inv = c_entering_static_inv = + BOOST_PP_IIF(BOOST_CONTRACT_TEST_entry_inv, true, false); + { + out.str(""); + a aa; + ok.str(""); ok // Test nothing failed. + << ok_c() + << ok_b() + << ok_a() + << ok_end() + ; + BOOST_TEST(out.eq(ok.str())); + } + + boost::contract::set_entry_invariant_failure( + [] (boost::contract::from) { throw err(); }); + + a_entry_static_inv = false; + b_entry_static_inv = true; + c_entry_static_inv = true; + a_entering_static_inv = b_entering_static_inv = c_entering_static_inv = + BOOST_PP_IIF(BOOST_CONTRACT_TEST_entry_inv, true, false); + try { + out.str(""); + a aa; + #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS + BOOST_TEST(false); + } catch(err const&) { + #endif + ok.str(""); ok + << ok_c() + << ok_b() + << ok_a() // Test a::static_inv failed. + #ifdef BOOST_CONTRACT_NO_ENTRY_INVARIANTS + << ok_end() + #endif + ; + BOOST_TEST(out.eq(ok.str())); + } catch(...) { BOOST_TEST(false); } + + a_entry_static_inv = true; + b_entry_static_inv = false; + c_entry_static_inv = true; + a_entering_static_inv = b_entering_static_inv = c_entering_static_inv = + BOOST_PP_IIF(BOOST_CONTRACT_TEST_entry_inv, true, false); + { + out.str(""); + a aa; + ok.str(""); ok + << ok_c() + << ok_b() + << ok_a() + << ok_end() + ; + BOOST_TEST(out.eq(ok.str())); + } + + a_entry_static_inv = true; + b_entry_static_inv = true; + c_entry_static_inv = false; + a_entering_static_inv = b_entering_static_inv = c_entering_static_inv = + BOOST_PP_IIF(BOOST_CONTRACT_TEST_entry_inv, true, false); + try { + out.str(""); + a aa; + #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS + BOOST_TEST(false); + } catch(err const&) { + #endif + ok.str(""); ok + << ok_c() // Test c::static_inv failed. + #ifdef BOOST_CONTRACT_NO_ENTRY_INVARIANTS + << ok_b() + << ok_a() + << ok_end() + #endif + ; + BOOST_TEST(out.eq(ok.str())); + } catch(...) { BOOST_TEST(false); } + + a_entry_static_inv = false; + b_entry_static_inv = false; + c_entry_static_inv = false; + a_entering_static_inv = b_entering_static_inv = c_entering_static_inv = + BOOST_PP_IIF(BOOST_CONTRACT_TEST_entry_inv, true, false); + try { + out.str(""); + a aa; + #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS + BOOST_TEST(false); + } catch(err const&) { + #endif + ok.str(""); ok + << ok_c() // Test c::static_inv failed (as all did). + #ifdef BOOST_CONTRACT_NO_ENTRY_INVARIANTS + << ok_b() + << ok_a() + << ok_end() + #endif + ; + BOOST_TEST(out.eq(ok.str())); + } catch(...) { BOOST_TEST(false); } + + #undef BOOST_CONTRACT_TEST_entry_inv + return boost::report_errors(); +} + diff --git a/src/boost/libs/contract/test/constructor/decl_entry_static_inv_mid.cpp b/src/boost/libs/contract/test/constructor/decl_entry_static_inv_mid.cpp new file mode 100644 index 000000000..104388be6 --- /dev/null +++ b/src/boost/libs/contract/test/constructor/decl_entry_static_inv_mid.cpp @@ -0,0 +1,204 @@ + +// Copyright (C) 2008-2018 Lorenzo Caminiti +// Distributed under the Boost Software License, Version 1.0 (see accompanying +// file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt). +// See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html + +// Test only middle base class with entry static invariants. + +#define BOOST_CONTRACT_TEST_NO_A_STATIC_INV +#undef BOOST_CONTRACT_TEST_NO_B_STATIC_INV +#define BOOST_CONTRACT_TEST_NO_C_STATIC_INV +#include "decl.hpp" + +#include <boost/preprocessor/control/iif.hpp> +#include <boost/detail/lightweight_test.hpp> +#include <sstream> +#include <string> + +std::string ok_c() { + std::ostringstream ok; ok << "" // Suppress a warning. + #ifndef BOOST_CONTRACT_NO_PRECONDITIONS + << "a::ctor::pre" << std::endl + << "b::ctor::pre" << std::endl + << "c::ctor::pre" << std::endl + #endif + // No c::static_inv here. + ; + return ok.str(); +} + +std::string ok_b() { + std::ostringstream ok; ok + #ifndef BOOST_CONTRACT_NO_OLDS + << "c::ctor::old" << std::endl + #endif + << "c::ctor::body" << std::endl + #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS + << "c::inv" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS + << "c::ctor::post" << std::endl + #endif + + #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS + << "b::static_inv" << std::endl // This might fail. + #endif + ; + return ok.str(); +} + +std::string ok_a() { + std::ostringstream ok; ok + #ifndef BOOST_CONTRACT_NO_OLDS + << "b::ctor::old" << std::endl + #endif + << "b::ctor::body" << std::endl + #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS + << "b::static_inv" << std::endl + << "b::inv" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS + << "b::ctor::post" << std::endl + #endif + + // No a::static_inv here. + ; + return ok.str(); +} + +std::string ok_end() { + std::ostringstream ok; ok + #ifndef BOOST_CONTRACT_NO_OLDS + << "a::ctor::old" << std::endl + #endif + << "a::ctor::body" << std::endl + #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS + << "a::inv" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS + << "a::ctor::post" << std::endl + #endif + ; + return ok.str(); +} + +struct err {}; // Global decl so visible in MSVC10 lambdas. + +int main() { + std::ostringstream ok; + + #ifdef BOOST_CONTRACT_NO_ENTRY_INVARIANTS + #define BOOST_CONTRACT_TEST_entry_inv 0 + #else + #define BOOST_CONTRACT_TEST_entry_inv 1 + #endif + + a_entry_static_inv = true; + b_entry_static_inv = true; + c_entry_static_inv = true; + a_entering_static_inv = b_entering_static_inv = c_entering_static_inv = + BOOST_PP_IIF(BOOST_CONTRACT_TEST_entry_inv, true, false); + { + out.str(""); + a aa; + ok.str(""); ok // Test nothing failed. + << ok_c() + << ok_b() + << ok_a() + << ok_end() + ; + BOOST_TEST(out.eq(ok.str())); + } + + boost::contract::set_entry_invariant_failure( + [] (boost::contract::from) { throw err(); }); + + a_entry_static_inv = false; + b_entry_static_inv = true; + c_entry_static_inv = true; + a_entering_static_inv = b_entering_static_inv = c_entering_static_inv = + BOOST_PP_IIF(BOOST_CONTRACT_TEST_entry_inv, true, false); + { + out.str(""); + a aa; + ok.str(""); ok + << ok_c() + << ok_b() + << ok_a() // Test no a::static_inv so no failure. + << ok_end() + ; + BOOST_TEST(out.eq(ok.str())); + } + + std::cout << "---" << std::endl; + + a_entry_static_inv = true; + b_entry_static_inv = false; + c_entry_static_inv = true; + a_entering_static_inv = b_entering_static_inv = c_entering_static_inv = + BOOST_PP_IIF(BOOST_CONTRACT_TEST_entry_inv, true, false); + try { + out.str(""); + a aa; + #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS + BOOST_TEST(false); + } catch(err const&) { + #endif + ok.str(""); ok + << ok_c() + << ok_b() // Test b::static_inv failed. + #ifdef BOOST_CONTRACT_NO_ENTRY_INVARIANTS + << ok_a() + << ok_end() + #endif + ; + BOOST_TEST(out.eq(ok.str())); + } catch(...) { BOOST_TEST(false); } + + std::cout << "===" << std::endl; + + a_entry_static_inv = true; + b_entry_static_inv = true; + c_entry_static_inv = false; + a_entering_static_inv = b_entering_static_inv = c_entering_static_inv = + BOOST_PP_IIF(BOOST_CONTRACT_TEST_entry_inv, true, false); + { + out.str(""); + a aa; + ok.str(""); ok + << ok_c() // Test no c::static_inv so no failure. + << ok_b() + << ok_a() + << ok_end() + ; + BOOST_TEST(out.eq(ok.str())); + } + + a_entry_static_inv = false; + b_entry_static_inv = false; + c_entry_static_inv = false; + a_entering_static_inv = b_entering_static_inv = c_entering_static_inv = + BOOST_PP_IIF(BOOST_CONTRACT_TEST_entry_inv, true, false); + try { + out.str(""); + a aa; + #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS + BOOST_TEST(false); + } catch(err const&) { + #endif + ok.str(""); ok + << ok_c() + << ok_b() // Test b::static_inv failed (as all did). + #ifdef BOOST_CONTRACT_NO_ENTRY_INVARIANTS + << ok_a() + << ok_end() + #endif + ; + BOOST_TEST(out.eq(ok.str())); + } catch(...) { BOOST_TEST(false); } + + #undef BOOST_CONTRACT_TEST_entry_inv + return boost::report_errors(); +} + diff --git a/src/boost/libs/contract/test/constructor/decl_entry_static_inv_none.cpp b/src/boost/libs/contract/test/constructor/decl_entry_static_inv_none.cpp new file mode 100644 index 000000000..58b711d7f --- /dev/null +++ b/src/boost/libs/contract/test/constructor/decl_entry_static_inv_none.cpp @@ -0,0 +1,124 @@ + +// Copyright (C) 2008-2018 Lorenzo Caminiti +// Distributed under the Boost Software License, Version 1.0 (see accompanying +// file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt). +// See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html + +// Test only middle base class with entry static invariants. + +#define BOOST_CONTRACT_TEST_NO_A_STATIC_INV +#define BOOST_CONTRACT_TEST_NO_B_STATIC_INV +#define BOOST_CONTRACT_TEST_NO_C_STATIC_INV +#include "decl.hpp" + +#include <boost/preprocessor/control/iif.hpp> +#include <boost/detail/lightweight_test.hpp> +#include <sstream> + +int main() { + std::ostringstream ok; ok // Test nothing fails. + #ifndef BOOST_CONTRACT_NO_PRECONDITIONS + << "a::ctor::pre" << std::endl + << "b::ctor::pre" << std::endl + << "c::ctor::pre" << std::endl + #endif + + #ifndef BOOST_CONTRACT_NO_OLDS + << "c::ctor::old" << std::endl + #endif + << "c::ctor::body" << std::endl + #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS + << "c::inv" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS + << "c::ctor::post" << std::endl + #endif + + #ifndef BOOST_CONTRACT_NO_OLDS + << "b::ctor::old" << std::endl + #endif + << "b::ctor::body" << std::endl + #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS + << "b::inv" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS + << "b::ctor::post" << std::endl + #endif + + #ifndef BOOST_CONTRACT_NO_OLDS + << "a::ctor::old" << std::endl + #endif + << "a::ctor::body" << std::endl + #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS + << "a::inv" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS + << "a::ctor::post" << std::endl + #endif + ; + + #ifdef BOOST_CONTRACT_ENTRY_INVARIANTS + #define BOOST_CONTRACT_TEST_entry_inv 0 + #else + #define BOOST_CONTRACT_TEST_entry_inv 1 + #endif + + a_entry_static_inv = true; + b_entry_static_inv = true; + c_entry_static_inv = true; + a_entering_static_inv = b_entering_static_inv = c_entering_static_inv = + BOOST_PP_IIF(BOOST_CONTRACT_TEST_entry_inv, true, false); + { + out.str(""); + a aa; + BOOST_TEST(out.eq(ok.str())); + } + + a_entry_static_inv = false; + b_entry_static_inv = true; + c_entry_static_inv = true; + a_entering_static_inv = b_entering_static_inv = c_entering_static_inv = + BOOST_PP_IIF(BOOST_CONTRACT_TEST_entry_inv, true, false); + { + out.str(""); + a aa; + BOOST_TEST(out.eq(ok.str())); + } + + a_entry_static_inv = true; + b_entry_static_inv = false; + c_entry_static_inv = true; + a_entering_static_inv = b_entering_static_inv = c_entering_static_inv = + BOOST_PP_IIF(BOOST_CONTRACT_TEST_entry_inv, true, false); + { + out.str(""); + a aa; + BOOST_TEST(out.eq(ok.str())); + } + + a_entry_static_inv = true; + b_entry_static_inv = true; + c_entry_static_inv = false; + a_entering_static_inv = b_entering_static_inv = c_entering_static_inv = + BOOST_PP_IIF(BOOST_CONTRACT_TEST_entry_inv, true, false); + { + out.str(""); + a aa; + BOOST_TEST(out.eq(ok.str())); + } + + a_entry_static_inv = false; + b_entry_static_inv = false; + c_entry_static_inv = false; + a_entering_static_inv = b_entering_static_inv = c_entering_static_inv = + BOOST_PP_IIF(BOOST_CONTRACT_TEST_entry_inv, true, false); + { + out.str(""); + a aa; + BOOST_TEST(out.eq(ok.str())); + } + + #undef BOOST_CONTRACT_TEST_entry_inv + return boost::report_errors(); +} + diff --git a/src/boost/libs/contract/test/constructor/decl_exit_inv_all.cpp b/src/boost/libs/contract/test/constructor/decl_exit_inv_all.cpp new file mode 100644 index 000000000..3aee1cc47 --- /dev/null +++ b/src/boost/libs/contract/test/constructor/decl_exit_inv_all.cpp @@ -0,0 +1,201 @@ + +// Copyright (C) 2008-2018 Lorenzo Caminiti +// Distributed under the Boost Software License, Version 1.0 (see accompanying +// file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt). +// See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html + +// Test all derived and base classes with exit invariants. + +#undef BOOST_CONTRACT_TEST_NO_A_INV +#undef BOOST_CONTRACT_TEST_NO_B_INV +#undef BOOST_CONTRACT_TEST_NO_C_INV +#include "decl.hpp" + +#include <boost/detail/lightweight_test.hpp> +#include <sstream> +#include <string> + +std::string ok_c() { + std::ostringstream ok; ok << "" // Suppress a warning. + #ifndef BOOST_CONTRACT_NO_PRECONDITIONS + << "a::ctor::pre" << std::endl + << "b::ctor::pre" << std::endl + << "c::ctor::pre" << std::endl + #endif + + #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS + << "c::static_inv" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_OLDS + << "c::ctor::old" << std::endl + #endif + << "c::ctor::body" << std::endl + #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS + << "c::static_inv" << std::endl + << "c::inv" << std::endl // This can fail. + #endif + ; + return ok.str(); +} + +std::string ok_b() { + std::ostringstream ok; ok + #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS + << "c::ctor::post" << std::endl + #endif + + #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS + << "b::static_inv" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_OLDS + << "b::ctor::old" << std::endl + #endif + << "b::ctor::body" << std::endl + #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS + << "b::static_inv" << std::endl + << "b::inv" << std::endl // This can fail. + #endif + ; + return ok.str(); +} + +std::string ok_a() { + std::ostringstream ok; ok + #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS + << "b::ctor::post" << std::endl + #endif + + #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS + << "a::static_inv" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_OLDS + << "a::ctor::old" << std::endl + #endif + << "a::ctor::body" << std::endl + #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS + << "a::static_inv" << std::endl + << "a::inv" << std::endl // This can fail. + #endif + ; + return ok.str(); +} + +std::string ok_end() { + std::ostringstream ok; ok << "" // Suppress a warning. + #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS + << "a::ctor::post" << std::endl + #endif + ; + return ok.str(); +} + +struct err {}; // Global decl so visible in MSVC10 lambdas. + +int main() { + std::ostringstream ok; + + a_exit_inv = true; + b_exit_inv = true; + c_exit_inv = true; + { + out.str(""); + a aa; + ok.str(""); ok // Test nothing fails. + << ok_c() + << ok_b() + << ok_a() + << ok_end() + ; + BOOST_TEST(out.eq(ok.str())); + } + + boost::contract::set_exit_invariant_failure( + [] (boost::contract::from) { throw err(); }); + + a_exit_inv = false; + b_exit_inv = true; + c_exit_inv = true; + try { + out.str(""); + a aa; + #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS + BOOST_TEST(false); + } catch(err const&) { + #endif + ok.str(""); ok + << ok_c() + << ok_b() + << ok_a() // Test a::inv failed. + #ifdef BOOST_CONTRACT_NO_EXIT_INVARIANTS + << ok_end() + #endif + ; + BOOST_TEST(out.eq(ok.str())); + } catch(...) { BOOST_TEST(false); } + + a_exit_inv = true; + b_exit_inv = false; + c_exit_inv = true; + try { + out.str(""); + a aa; + #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS + BOOST_TEST(false); + } catch(err const&) { + #endif + ok.str(""); ok + << ok_c() + << ok_b() // Test bb::inv failed. + #ifdef BOOST_CONTRACT_NO_EXIT_INVARIANTS + << ok_a() + << ok_end() + #endif + ; + BOOST_TEST(out.eq(ok.str())); + } catch(...) { BOOST_TEST(false); } + + a_exit_inv = true; + b_exit_inv = true; + c_exit_inv = false; + try { + out.str(""); + a aa; + #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS + BOOST_TEST(false); + } catch(err const&) { + #endif + ok.str(""); ok + << ok_c() // Test c::inv failed. + #ifdef BOOST_CONTRACT_NO_EXIT_INVARIANTS + << ok_b() + << ok_a() + << ok_end() + #endif + ; + BOOST_TEST(out.eq(ok.str())); + } catch(...) { BOOST_TEST(false); } + + a_exit_inv = false; + b_exit_inv = false; + c_exit_inv = false; + try { + out.str(""); + a aa; + #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS + BOOST_TEST(false); + } catch(err const&) { + #endif + ok.str(""); ok + << ok_c() // Test c::inv failed. + #ifdef BOOST_CONTRACT_NO_EXIT_INVARIANTS + << ok_b() + << ok_a() + << ok_end() + #endif + ; + BOOST_TEST(out.eq(ok.str())); + } catch(...) { BOOST_TEST(false); } + + return boost::report_errors(); +} + diff --git a/src/boost/libs/contract/test/constructor/decl_exit_inv_ends.cpp b/src/boost/libs/contract/test/constructor/decl_exit_inv_ends.cpp new file mode 100644 index 000000000..ac45eac27 --- /dev/null +++ b/src/boost/libs/contract/test/constructor/decl_exit_inv_ends.cpp @@ -0,0 +1,195 @@ + +// Copyright (C) 2008-2018 Lorenzo Caminiti +// Distributed under the Boost Software License, Version 1.0 (see accompanying +// file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt). +// See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html + +// Test only derived and grandparent classes (ends) with exit invariants. + +#undef BOOST_CONTRACT_TEST_NO_A_INV +#define BOOST_CONTRACT_TEST_NO_B_INV +#undef BOOST_CONTRACT_TEST_NO_C_INV +#include "decl.hpp" + +#include <boost/detail/lightweight_test.hpp> +#include <sstream> +#include <string> + +std::string ok_c() { + std::ostringstream ok; ok << "" // Suppress a warning. + #ifndef BOOST_CONTRACT_NO_PRECONDITIONS + << "a::ctor::pre" << std::endl + << "b::ctor::pre" << std::endl + << "c::ctor::pre" << std::endl + #endif + + #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS + << "c::static_inv" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_OLDS + << "c::ctor::old" << std::endl + #endif + << "c::ctor::body" << std::endl + #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS + << "c::static_inv" << std::endl + << "c::inv" << std::endl // This can fail. + #endif + ; + return ok.str(); +} + +std::string ok_b() { + std::ostringstream ok; ok + #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS + << "c::ctor::post" << std::endl + #endif + + #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS + << "b::static_inv" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_OLDS + << "b::ctor::old" << std::endl + #endif + << "b::ctor::body" << std::endl + #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS + << "b::static_inv" << std::endl + // No failure here. + #endif + ; + return ok.str(); +} + +std::string ok_a() { + std::ostringstream ok; ok + #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS + << "b::ctor::post" << std::endl + #endif + + #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS + << "a::static_inv" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_OLDS + << "a::ctor::old" << std::endl + #endif + << "a::ctor::body" << std::endl + #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS + << "a::static_inv" << std::endl + << "a::inv" << std::endl // This can fail. + #endif + ; + return ok.str(); +} + +std::string ok_end() { + std::ostringstream ok; ok << "" // Suppress a warning. + #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS + << "a::ctor::post" << std::endl + #endif + ; + return ok.str(); +} + +struct err {}; // Global decl so visible in MSVC10 lambdas. + +int main() { + std::ostringstream ok; + + a_exit_inv = true; + b_exit_inv = true; + c_exit_inv = true; + { + out.str(""); + a aa; + ok.str(""); ok // Test no failure. + << ok_c() + << ok_b() + << ok_a() + << ok_end() + ; + BOOST_TEST(out.eq(ok.str())); + } + + boost::contract::set_exit_invariant_failure( + [] (boost::contract::from) { throw err(); }); + + a_exit_inv = false; + b_exit_inv = true; + c_exit_inv = true; + try { + out.str(""); + a aa; + #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS + BOOST_TEST(false); + } catch(err const&) { + #endif + ok.str(""); ok + << ok_c() + << ok_b() + << ok_a() // Test a::inv failed. + #ifdef BOOST_CONTRACT_NO_EXIT_INVARIANTS + << ok_end() + #endif + ; + BOOST_TEST(out.eq(ok.str())); + } catch(...) { BOOST_TEST(false); } + + a_exit_inv = true; + b_exit_inv = false; + c_exit_inv = true; + try { + out.str(""); + a aa; + ok.str(""); ok + << ok_c() + << ok_b() // Test no b::inv so no failure. + << ok_a() + << ok_end() + ; + BOOST_TEST(out.eq(ok.str())); + } catch(...) { BOOST_TEST(false); } + + a_exit_inv = true; + b_exit_inv = true; + c_exit_inv = false; + try { + out.str(""); + a aa; + #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS + BOOST_TEST(false); + } catch(err const&) { + #endif + ok.str(""); ok + << ok_c() // Test c::inv failed. + #ifdef BOOST_CONTRACT_NO_EXIT_INVARIANTS + << ok_b() + << ok_a() + << ok_end() + #endif + ; + BOOST_TEST(out.eq(ok.str())); + } catch(...) { BOOST_TEST(false); } + + a_exit_inv = false; + b_exit_inv = false; + c_exit_inv = false; + try { + out.str(""); + a aa; + #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS + BOOST_TEST(false); + } catch(err const&) { + #endif + ok.str(""); ok + << ok_c() // Test c::inv failed. + #ifdef BOOST_CONTRACT_NO_EXIT_INVARIANTS + << ok_b() + << ok_a() + << ok_end() + #endif + ; + BOOST_TEST(out.eq(ok.str())); + } catch(...) { BOOST_TEST(false); } + + return boost::report_errors(); +} + diff --git a/src/boost/libs/contract/test/constructor/decl_exit_inv_mid.cpp b/src/boost/libs/contract/test/constructor/decl_exit_inv_mid.cpp new file mode 100644 index 000000000..d9c8bcd45 --- /dev/null +++ b/src/boost/libs/contract/test/constructor/decl_exit_inv_mid.cpp @@ -0,0 +1,189 @@ + +// Copyright (C) 2008-2018 Lorenzo Caminiti +// Distributed under the Boost Software License, Version 1.0 (see accompanying +// file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt). +// See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html + +// Test only middle class with exit invariants. + +#define BOOST_CONTRACT_TEST_NO_A_INV +#undef BOOST_CONTRACT_TEST_NO_B_INV +#define BOOST_CONTRACT_TEST_NO_C_INV +#include "decl.hpp" + +#include <boost/detail/lightweight_test.hpp> +#include <sstream> +#include <string> + +std::string ok_c() { + std::ostringstream ok; ok << "" // Suppress a warning. + #ifndef BOOST_CONTRACT_NO_PRECONDITIONS + << "a::ctor::pre" << std::endl + << "b::ctor::pre" << std::endl + << "c::ctor::pre" << std::endl + #endif + + #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS + << "c::static_inv" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_OLDS + << "c::ctor::old" << std::endl + #endif + << "c::ctor::body" << std::endl + #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS + << "c::static_inv" << std::endl + // No failure here. + #endif + ; + return ok.str(); +} + +std::string ok_b() { + std::ostringstream ok; ok + #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS + << "c::ctor::post" << std::endl + #endif + + #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS + << "b::static_inv" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_OLDS + << "b::ctor::old" << std::endl + #endif + << "b::ctor::body" << std::endl + #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS + << "b::static_inv" << std::endl + << "b::inv" << std::endl // This can fail. + #endif + ; + return ok.str(); +} + +std::string ok_a() { + std::ostringstream ok; ok + #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS + << "b::ctor::post" << std::endl + #endif + + #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS + << "a::static_inv" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_OLDS + << "a::ctor::old" << std::endl + #endif + << "a::ctor::body" << std::endl + #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS + << "a::static_inv" << std::endl + // No failure here. + #endif + ; + return ok.str(); +} + +std::string ok_end() { + std::ostringstream ok; ok << "" // Suppress a warning. + #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS + << "a::ctor::post" << std::endl + #endif + ; + return ok.str(); +} + +struct err {}; // Global decl so visible in MSVC10 lambdas. + +int main() { + std::ostringstream ok; + + a_exit_inv = true; + b_exit_inv = true; + c_exit_inv = true; + { + out.str(""); + a aa; + ok.str(""); ok // Test nothing failed. + << ok_c() + << ok_b() + << ok_a() + << ok_end() + ; + BOOST_TEST(out.eq(ok.str())); + } + + boost::contract::set_exit_invariant_failure( + [] (boost::contract::from) { throw err(); }); + + a_exit_inv = false; + b_exit_inv = true; + c_exit_inv = true; + try { + out.str(""); + a aa; + ok.str(""); ok + << ok_c() + << ok_b() + << ok_a() // Test no failure here. + << ok_end() + ; + BOOST_TEST(out.eq(ok.str())); + } catch(...) { BOOST_TEST(false); } + + a_exit_inv = true; + b_exit_inv = false; + c_exit_inv = true; + try { + out.str(""); + a aa; + #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS + BOOST_TEST(false); + } catch(err const&) { + #endif + ok.str(""); ok + << ok_c() + << ok_b() // Test b::inv failed. + #ifdef BOOST_CONTRACT_NO_EXIT_INVARIANTS + << ok_a() + << ok_end() + #endif + ; + BOOST_TEST(out.eq(ok.str())); + } catch(...) { BOOST_TEST(false); } + + a_exit_inv = true; + b_exit_inv = true; + c_exit_inv = false; + try { + out.str(""); + a aa; + ok.str(""); ok + << ok_c() // Test no failure here. + << ok_b() + << ok_a() + << ok_end() + ; + BOOST_TEST(out.eq(ok.str())); + } catch(...) { BOOST_TEST(false); } + + a_exit_inv = false; + b_exit_inv = false; + c_exit_inv = false; + try { + out.str(""); + a aa; + #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS + BOOST_TEST(false); + } catch(err const&) { + #endif + ok.str(""); ok + << ok_c() + << ok_b() // Test b::inv failed. + #ifdef BOOST_CONTRACT_NO_EXIT_INVARIANTS + << ok_a() + << ok_end() + #endif + ; + BOOST_TEST(out.eq(ok.str())); + } catch(...) { BOOST_TEST(false); } + + return boost::report_errors(); +} + diff --git a/src/boost/libs/contract/test/constructor/decl_exit_inv_none.cpp b/src/boost/libs/contract/test/constructor/decl_exit_inv_none.cpp new file mode 100644 index 000000000..baf898138 --- /dev/null +++ b/src/boost/libs/contract/test/constructor/decl_exit_inv_none.cpp @@ -0,0 +1,115 @@ + +// Copyright (C) 2008-2018 Lorenzo Caminiti +// Distributed under the Boost Software License, Version 1.0 (see accompanying +// file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt). +// See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html + +// Test all derived and grandparent classes (ends) with exit invariants. + +#define BOOST_CONTRACT_TEST_NO_A_INV +#define BOOST_CONTRACT_TEST_NO_B_INV +#define BOOST_CONTRACT_TEST_NO_C_INV +#include "decl.hpp" + +#include <boost/detail/lightweight_test.hpp> +#include <sstream> + +int main() { + std::ostringstream ok; ok // Test nothing fails. + #ifndef BOOST_CONTRACT_NO_PRECONDITIONS + << "a::ctor::pre" << std::endl + << "b::ctor::pre" << std::endl + << "c::ctor::pre" << std::endl + #endif + + #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS + << "c::static_inv" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_OLDS + << "c::ctor::old" << std::endl + #endif + << "c::ctor::body" << std::endl + #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS + << "c::static_inv" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS + << "c::ctor::post" << std::endl + #endif + + #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS + << "b::static_inv" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_OLDS + << "b::ctor::old" << std::endl + #endif + << "b::ctor::body" << std::endl + #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS + << "b::static_inv" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS + << "b::ctor::post" << std::endl + #endif + + #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS + << "a::static_inv" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_OLDS + << "a::ctor::old" << std::endl + #endif + << "a::ctor::body" << std::endl + #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS + << "a::static_inv" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS + << "a::ctor::post" << std::endl + #endif + ; + + a_exit_inv = true; + b_exit_inv = true; + c_exit_inv = true; + { + out.str(""); + a aa; + BOOST_TEST(out.eq(ok.str())); + } + + a_exit_inv = false; + b_exit_inv = true; + c_exit_inv = true; + { + out.str(""); + a aa; + BOOST_TEST(out.eq(ok.str())); + } + + a_exit_inv = true; + b_exit_inv = false; + c_exit_inv = true; + { + out.str(""); + a aa; + BOOST_TEST(out.eq(ok.str())); + } + + a_exit_inv = true; + b_exit_inv = true; + c_exit_inv = false; + { + out.str(""); + a aa; + BOOST_TEST(out.eq(ok.str())); + } + + a_exit_inv = false; + b_exit_inv = false; + c_exit_inv = false; + { + out.str(""); + a aa; + BOOST_TEST(out.eq(ok.str())); + } + + return boost::report_errors(); +} + diff --git a/src/boost/libs/contract/test/constructor/decl_exit_static_inv_all.cpp b/src/boost/libs/contract/test/constructor/decl_exit_static_inv_all.cpp new file mode 100644 index 000000000..e33e4cd1c --- /dev/null +++ b/src/boost/libs/contract/test/constructor/decl_exit_static_inv_all.cpp @@ -0,0 +1,224 @@ + +// Copyright (C) 2008-2018 Lorenzo Caminiti +// Distributed under the Boost Software License, Version 1.0 (see accompanying +// file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt). +// See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html + +// Test all derived and base classes with exit static invariants. + +#undef BOOST_CONTRACT_TEST_NO_A_STATIC_INV +#undef BOOST_CONTRACT_TEST_NO_B_STATIC_INV +#undef BOOST_CONTRACT_TEST_NO_C_STATIC_INV +#include "decl.hpp" + +#include <boost/preprocessor/control/iif.hpp> +#include <boost/detail/lightweight_test.hpp> +#include <sstream> +#include <string> + +std::string ok_c() { + std::ostringstream ok; ok << "" // Suppress a warning. + #ifndef BOOST_CONTRACT_NO_PRECONDITIONS + << "a::ctor::pre" << std::endl + << "b::ctor::pre" << std::endl + << "c::ctor::pre" << std::endl + #endif + + #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS + << "c::static_inv" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_OLDS + << "c::ctor::old" << std::endl + #endif + << "c::ctor::body" << std::endl + #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS + << "c::static_inv" << std::endl // This can fail. + #endif + ; + return ok.str(); +} + +std::string ok_b() { + std::ostringstream ok; ok + #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS + << "c::inv" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS + << "c::ctor::post" << std::endl + #endif + + #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS + << "b::static_inv" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_OLDS + << "b::ctor::old" << std::endl + #endif + << "b::ctor::body" << std::endl + #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS + << "b::static_inv" << std::endl // This can fail. + #endif + ; + return ok.str(); +} + +std::string ok_a() { + std::ostringstream ok; ok + #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS + << "b::inv" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS + << "b::ctor::post" << std::endl + #endif + + #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS + << "a::static_inv" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_OLDS + << "a::ctor::old" << std::endl + #endif + << "a::ctor::body" << std::endl + #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS + << "a::static_inv" << std::endl // This can fail. + #endif + ; + return ok.str(); +} + +std::string ok_end() { + std::ostringstream ok; ok << "" // Suppress a warning. + #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS + << "a::inv" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS + << "a::ctor::post" << std::endl + #endif + ; + return ok.str(); +} + +struct err {}; // Global decl so visible in MSVC10 lambdas. + +int main() { + std::ostringstream ok; + + #ifdef BOOST_CONTRACT_NO_ENTRY_INVARIANTS + #define BOOST_CONTRACT_TEST_entry_inv 0 + #else + #define BOOST_CONTRACT_TEST_entry_inv 1 + #endif + + a_exit_static_inv = true; + b_exit_static_inv = true; + c_exit_static_inv = true; + a_entering_static_inv = b_entering_static_inv = c_entering_static_inv = + BOOST_PP_IIF(BOOST_CONTRACT_TEST_entry_inv, true, false); + { + out.str(""); + a aa; + ok.str(""); ok // Test nothing failed. + << ok_c() + << ok_b() + << ok_a() + << ok_end() + ; + BOOST_TEST(out.eq(ok.str())); + } + + boost::contract::set_exit_invariant_failure( + [] (boost::contract::from) { throw err(); }); + + a_exit_static_inv = false; + b_exit_static_inv = true; + c_exit_static_inv = true; + a_entering_static_inv = b_entering_static_inv = c_entering_static_inv = + BOOST_PP_IIF(BOOST_CONTRACT_TEST_entry_inv, true, false); + try { + out.str(""); + a aa; + #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS + BOOST_TEST(false); + } catch(err const&) { + #endif + ok.str(""); ok + << ok_c() + << ok_b() + << ok_a() // Test exit a::static_inv failed. + #ifdef BOOST_CONTRACT_NO_EXIT_INVARIANTS + << ok_end() + #endif + ; + BOOST_TEST(out.eq(ok.str())); + } catch(...) { BOOST_TEST(false); } + + a_exit_static_inv = true; + b_exit_static_inv = false; + c_exit_static_inv = true; + a_entering_static_inv = b_entering_static_inv = c_entering_static_inv = + BOOST_PP_IIF(BOOST_CONTRACT_TEST_entry_inv, true, false); + try { + out.str(""); + a aa; + #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS + BOOST_TEST(false); + } catch(err const&) { + #endif + ok.str(""); ok + << ok_c() + << ok_b() // Test exit b::static_inv failed. + #ifdef BOOST_CONTRACT_NO_EXIT_INVARIANTS + << ok_a() + << ok_end() + #endif + ; + BOOST_TEST(out.eq(ok.str())); + } catch(...) { BOOST_TEST(false); } + + a_exit_static_inv = true; + b_exit_static_inv = true; + c_exit_static_inv = false; + a_entering_static_inv = b_entering_static_inv = c_entering_static_inv = + BOOST_PP_IIF(BOOST_CONTRACT_TEST_entry_inv, true, false); + try { + out.str(""); + a aa; + #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS + BOOST_TEST(false); + } catch(err const&) { + #endif + ok.str(""); ok + << ok_c() // Test exit c::static_inv failed. + #ifdef BOOST_CONTRACT_NO_EXIT_INVARIANTS + << ok_b() + << ok_a() + << ok_end() + #endif + ; + BOOST_TEST(out.eq(ok.str())); + } catch(...) { BOOST_TEST(false); } + + a_exit_static_inv = false; + b_exit_static_inv = false; + c_exit_static_inv = false; + a_entering_static_inv = b_entering_static_inv = c_entering_static_inv = + BOOST_PP_IIF(BOOST_CONTRACT_TEST_entry_inv, true, false); + try { + out.str(""); + a aa; + #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS + BOOST_TEST(false); + } catch(err const&) { + #endif + ok.str(""); ok + << ok_c() // Test exit c::static_inv failed (as all did). + #ifdef BOOST_CONTRACT_NO_EXIT_INVARIANTS + << ok_b() + << ok_a() + << ok_end() + #endif + ; + BOOST_TEST(out.eq(ok.str())); + } catch(...) { BOOST_TEST(false); } + + return boost::report_errors(); +} + diff --git a/src/boost/libs/contract/test/constructor/decl_exit_static_inv_ends.cpp b/src/boost/libs/contract/test/constructor/decl_exit_static_inv_ends.cpp new file mode 100644 index 000000000..a8b2f5e60 --- /dev/null +++ b/src/boost/libs/contract/test/constructor/decl_exit_static_inv_ends.cpp @@ -0,0 +1,213 @@ + +// Copyright (C) 2008-2018 Lorenzo Caminiti +// Distributed under the Boost Software License, Version 1.0 (see accompanying +// file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt). +// See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html + +// Test all derived and grandparent classes (ends) with exit static invariants. + +#undef BOOST_CONTRACT_TEST_NO_A_STATIC_INV +#define BOOST_CONTRACT_TEST_NO_B_STATIC_INV +#undef BOOST_CONTRACT_TEST_NO_C_STATIC_INV +#include "decl.hpp" + +#include <boost/preprocessor/control/iif.hpp> +#include <boost/detail/lightweight_test.hpp> +#include <sstream> +#include <string> + +std::string ok_c() { + std::ostringstream ok; ok << "" // Suppress a warning. + #ifndef BOOST_CONTRACT_NO_PRECONDITIONS + << "a::ctor::pre" << std::endl + << "b::ctor::pre" << std::endl + << "c::ctor::pre" << std::endl + #endif + + #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS + << "c::static_inv" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_OLDS + << "c::ctor::old" << std::endl + #endif + << "c::ctor::body" << std::endl + #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS + << "c::static_inv" << std::endl // This can fail. + #endif + ; + return ok.str(); +} + +std::string ok_b() { + std::ostringstream ok; ok + #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS + << "c::inv" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS + << "c::ctor::post" << std::endl + #endif + + #ifndef BOOST_CONTRACT_NO_OLDS + << "b::ctor::old" << std::endl + #endif + << "b::ctor::body" << std::endl + ; + return ok.str(); +} + +std::string ok_a() { + std::ostringstream ok; ok + #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS + << "b::inv" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS + << "b::ctor::post" << std::endl + #endif + + #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS + << "a::static_inv" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_OLDS + << "a::ctor::old" << std::endl + #endif + << "a::ctor::body" << std::endl + #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS + << "a::static_inv" << std::endl + #endif + ; + return ok.str(); +} + +std::string ok_end() { + std::ostringstream ok; ok << "" // Suppress a warning. + #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS + << "a::inv" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS + << "a::ctor::post" << std::endl + #endif + ; + return ok.str(); +} + +struct err {}; // Global decl so visible in MSVC10 lambdas. + +int main() { + std::ostringstream ok; + + #ifdef BOOST_CONTRACT_NO_ENTRY_INVARIANTS + #define BOOST_CONTRACT_TEST_entry_inv 0 + #else + #define BOOST_CONTRACT_TEST_entry_inv 1 + #endif + + a_exit_static_inv = true; + b_exit_static_inv = true; + c_exit_static_inv = true; + a_entering_static_inv = b_entering_static_inv = c_entering_static_inv = + BOOST_PP_IIF(BOOST_CONTRACT_TEST_entry_inv, true, false); + { + out.str(""); + a aa; + ok.str(""); ok // Test nothing failed. + << ok_c() + << ok_b() + << ok_a() + << ok_end() + ; + BOOST_TEST(out.eq(ok.str())); + } + + boost::contract::set_exit_invariant_failure( + [] (boost::contract::from) { throw err(); }); + + a_exit_static_inv = false; + b_exit_static_inv = true; + c_exit_static_inv = true; + a_entering_static_inv = b_entering_static_inv = c_entering_static_inv = + BOOST_PP_IIF(BOOST_CONTRACT_TEST_entry_inv, true, false); + try { + out.str(""); + a aa; + #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS + BOOST_TEST(false); + } catch(err const&) { + #endif + ok.str(""); ok + << ok_c() + << ok_b() + << ok_a() // Test a::static_inv failed. + #ifdef BOOST_CONTRACT_NO_EXIT_INVARIANTS + << ok_end() + #endif + ; + BOOST_TEST(out.eq(ok.str())); + } catch(...) { BOOST_TEST(false); } + + a_exit_static_inv = true; + b_exit_static_inv = false; + c_exit_static_inv = true; + a_entering_static_inv = b_entering_static_inv = c_entering_static_inv = + BOOST_PP_IIF(BOOST_CONTRACT_TEST_entry_inv, true, false); + try { + out.str(""); + a aa; + ok.str(""); ok + << ok_c() + << ok_b() + << ok_a() + << ok_end() + ; + BOOST_TEST(out.eq(ok.str())); + } catch(...) { BOOST_TEST(false); } + + a_exit_static_inv = true; + b_exit_static_inv = true; + c_exit_static_inv = false; + a_entering_static_inv = b_entering_static_inv = c_entering_static_inv = + BOOST_PP_IIF(BOOST_CONTRACT_TEST_entry_inv, true, false); + try { + out.str(""); + a aa; + #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS + BOOST_TEST(false); + } catch(err const&) { + #endif + ok.str(""); ok + << ok_c() // Test c::static_inv failed (as all did). + #ifdef BOOST_CONTRACT_NO_EXIT_INVARIANTS + << ok_b() + << ok_a() + << ok_end() + #endif + ; + BOOST_TEST(out.eq(ok.str())); + } catch(...) { BOOST_TEST(false); } + + a_exit_static_inv = false; + b_exit_static_inv = false; + c_exit_static_inv = false; + a_entering_static_inv = b_entering_static_inv = c_entering_static_inv = + BOOST_PP_IIF(BOOST_CONTRACT_TEST_entry_inv, true, false); + try { + out.str(""); + a aa; + #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS + BOOST_TEST(false); + } catch(err const&) { + #endif + ok.str(""); ok + << ok_c() // Test c::static_inv failed (as all did). + #ifdef BOOST_CONTRACT_NO_EXIT_INVARIANTS + << ok_b() + << ok_a() + << ok_end() + #endif + ; + BOOST_TEST(out.eq(ok.str())); + } catch(...) { BOOST_TEST(false); } + + #undef BOOST_CONTRACT_TEST_entry_inv + return boost::report_errors(); +} + diff --git a/src/boost/libs/contract/test/constructor/decl_exit_static_inv_mid.cpp b/src/boost/libs/contract/test/constructor/decl_exit_static_inv_mid.cpp new file mode 100644 index 000000000..c8a24bde5 --- /dev/null +++ b/src/boost/libs/contract/test/constructor/decl_exit_static_inv_mid.cpp @@ -0,0 +1,202 @@ + +// Copyright (C) 2008-2018 Lorenzo Caminiti +// Distributed under the Boost Software License, Version 1.0 (see accompanying +// file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt). +// See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html + +// Test only middle base class with exit static invariants. + +#define BOOST_CONTRACT_TEST_NO_A_STATIC_INV +#undef BOOST_CONTRACT_TEST_NO_B_STATIC_INV +#define BOOST_CONTRACT_TEST_NO_C_STATIC_INV +#include "decl.hpp" + +#include <boost/preprocessor/control/iif.hpp> +#include <boost/detail/lightweight_test.hpp> +#include <sstream> +#include <string> + +std::string ok_c() { + std::ostringstream ok; ok << "" // Suppress a warning. + #ifndef BOOST_CONTRACT_NO_PRECONDITIONS + << "a::ctor::pre" << std::endl + << "b::ctor::pre" << std::endl + << "c::ctor::pre" << std::endl + #endif + + #ifndef BOOST_CONTRACT_NO_OLDS + << "c::ctor::old" << std::endl + #endif + << "c::ctor::body" << std::endl + // No failure here. + ; + return ok.str(); +} + +std::string ok_b() { + std::ostringstream ok; ok + #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS + << "c::inv" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS + << "c::ctor::post" << std::endl + #endif + + #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS + << "b::static_inv" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_OLDS + << "b::ctor::old" << std::endl + #endif + << "b::ctor::body" << std::endl + #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS + << "b::static_inv" << std::endl // This can fail. + #endif + ; + return ok.str(); +} + +std::string ok_a() { + std::ostringstream ok; ok + #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS + << "b::inv" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS + << "b::ctor::post" << std::endl + #endif + + #ifndef BOOST_CONTRACT_NO_OLDS + << "a::ctor::old" << std::endl + #endif + << "a::ctor::body" << std::endl + // No failure here. + ; + return ok.str(); +} + +std::string ok_end() { + std::ostringstream ok; ok << "" // Suppress a warning. + #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS + << "a::inv" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS + << "a::ctor::post" << std::endl + #endif + ; + return ok.str(); +} + +struct err {}; // Global decl so visible in MSVC10 lambdas. + +int main() { + std::ostringstream ok; + + #ifdef BOOST_CONTRACT_NO_ENTRY_INVARIANTS + #define BOOST_CONTRACT_TEST_entry_inv 0 + #else + #define BOOST_CONTRACT_TEST_entry_inv 1 + #endif + + a_exit_static_inv = true; + b_exit_static_inv = true; + c_exit_static_inv = true; + a_entering_static_inv = b_entering_static_inv = c_entering_static_inv = + BOOST_PP_IIF(BOOST_CONTRACT_TEST_entry_inv, true, false); + { + out.str(""); + a aa; + ok.str(""); ok // Test nothing fails. + << ok_c() + << ok_b() + << ok_a() + << ok_end() + ; + BOOST_TEST(out.eq(ok.str())); + } + + boost::contract::set_exit_invariant_failure( + [] (boost::contract::from) { throw err(); }); + + a_exit_static_inv = false; + b_exit_static_inv = true; + c_exit_static_inv = true; + a_entering_static_inv = b_entering_static_inv = c_entering_static_inv = + BOOST_PP_IIF(BOOST_CONTRACT_TEST_entry_inv, true, false); + try { + out.str(""); + a aa; + ok.str(""); ok + << ok_c() + << ok_b() + << ok_a() // Test no a::static_inv so no failure. + << ok_end() + ; + BOOST_TEST(out.eq(ok.str())); + } catch(...) { BOOST_TEST(false); } + + a_exit_static_inv = true; + b_exit_static_inv = false; + c_exit_static_inv = true; + a_entering_static_inv = b_entering_static_inv = c_entering_static_inv = + BOOST_PP_IIF(BOOST_CONTRACT_TEST_entry_inv, true, false); + try { + out.str(""); + a aa; + #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS + BOOST_TEST(false); + } catch(err const&) { + #endif + ok.str(""); ok + << ok_c() + << ok_b() // Test b::static_inv failed. + #ifdef BOOST_CONTRACT_NO_EXIT_INVARIANTS + << ok_a() + << ok_end() + #endif + ; + BOOST_TEST(out.eq(ok.str())); + } catch(...) { BOOST_TEST(false); } + + a_exit_static_inv = true; + b_exit_static_inv = true; + c_exit_static_inv = false; + a_entering_static_inv = b_entering_static_inv = c_entering_static_inv = + BOOST_PP_IIF(BOOST_CONTRACT_TEST_entry_inv, true, false); + try { + out.str(""); + a aa; + ok.str(""); ok + << ok_c() // Test no c::static_inv so no failure. + << ok_b() + << ok_a() + << ok_end() + ; + BOOST_TEST(out.eq(ok.str())); + } catch(...) { BOOST_TEST(false); } + + a_exit_static_inv = false; + b_exit_static_inv = false; + c_exit_static_inv = false; + a_entering_static_inv = b_entering_static_inv = c_entering_static_inv = + BOOST_PP_IIF(BOOST_CONTRACT_TEST_entry_inv, true, false); + try { + out.str(""); + a aa; + #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS + BOOST_TEST(false); + } catch(err const&) { + #endif + ok.str(""); ok + << ok_c() + << ok_b() // Test b::static_inv failed. + #ifdef BOOST_CONTRACT_NO_EXIT_INVARIANTS + << ok_a() + << ok_end() + #endif + ; + BOOST_TEST(out.eq(ok.str())); + } catch(...) { BOOST_TEST(false); } + + return boost::report_errors(); +} + diff --git a/src/boost/libs/contract/test/constructor/decl_exit_static_inv_none.cpp b/src/boost/libs/contract/test/constructor/decl_exit_static_inv_none.cpp new file mode 100644 index 000000000..79ceaf793 --- /dev/null +++ b/src/boost/libs/contract/test/constructor/decl_exit_static_inv_none.cpp @@ -0,0 +1,123 @@ + +// Copyright (C) 2008-2018 Lorenzo Caminiti +// Distributed under the Boost Software License, Version 1.0 (see accompanying +// file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt). +// See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html + +// Test all derived and base classes without exit static invariants. + +#define BOOST_CONTRACT_TEST_NO_A_STATIC_INV +#define BOOST_CONTRACT_TEST_NO_B_STATIC_INV +#define BOOST_CONTRACT_TEST_NO_C_STATIC_INV +#include "decl.hpp" + +#include <boost/preprocessor/control/iif.hpp> +#include <boost/detail/lightweight_test.hpp> +#include <sstream> + +int main() { + std::ostringstream ok; ok // Test nothing fails. + #ifndef BOOST_CONTRACT_NO_PRECONDITIONS + << "a::ctor::pre" << std::endl + << "b::ctor::pre" << std::endl + << "c::ctor::pre" << std::endl + #endif + + #ifndef BOOST_CONTRACT_NO_OLDS + << "c::ctor::old" << std::endl + #endif + << "c::ctor::body" << std::endl + #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS + << "c::inv" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS + << "c::ctor::post" << std::endl + #endif + + #ifndef BOOST_CONTRACT_NO_OLDS + << "b::ctor::old" << std::endl + #endif + << "b::ctor::body" << std::endl + #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS + << "b::inv" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS + << "b::ctor::post" << std::endl + #endif + + #ifndef BOOST_CONTRACT_NO_OLDS + << "a::ctor::old" << std::endl + #endif + << "a::ctor::body" << std::endl + #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS + << "a::inv" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS + << "a::ctor::post" << std::endl + #endif + ; + + #ifdef BOOST_CONTRACT_NO_ENTRY_INVARIANTS + #define BOOST_CONTRACT_TEST_entry_inv 0 + #else + #define BOOST_CONTRACT_TEST_entry_inv 1 + #endif + + a_exit_static_inv = true; + b_exit_static_inv = true; + c_exit_static_inv = true; + a_entering_static_inv = b_entering_static_inv = c_entering_static_inv = + BOOST_PP_IIF(BOOST_CONTRACT_TEST_entry_inv, true, false); + { + out.str(""); + a aa; + BOOST_TEST(out.eq(ok.str())); + } + + a_exit_static_inv = false; + b_exit_static_inv = true; + c_exit_static_inv = true; + a_entering_static_inv = b_entering_static_inv = c_entering_static_inv = + BOOST_PP_IIF(BOOST_CONTRACT_TEST_entry_inv, true, false); + { + out.str(""); + a aa; + BOOST_TEST(out.eq(ok.str())); + } + + a_exit_static_inv = true; + b_exit_static_inv = false; + c_exit_static_inv = true; + a_entering_static_inv = b_entering_static_inv = c_entering_static_inv = + BOOST_PP_IIF(BOOST_CONTRACT_TEST_entry_inv, true, false); + { + out.str(""); + a aa; + BOOST_TEST(out.eq(ok.str())); + } + + a_exit_static_inv = true; + b_exit_static_inv = true; + c_exit_static_inv = false; + a_entering_static_inv = b_entering_static_inv = c_entering_static_inv = + BOOST_PP_IIF(BOOST_CONTRACT_TEST_entry_inv, true, false); + { + out.str(""); + a aa; + BOOST_TEST(out.eq(ok.str())); + } + + a_exit_static_inv = false; + b_exit_static_inv = false; + c_exit_static_inv = false; + a_entering_static_inv = b_entering_static_inv = c_entering_static_inv = + BOOST_PP_IIF(BOOST_CONTRACT_TEST_entry_inv, true, false); + { + out.str(""); + a aa; + BOOST_TEST(out.eq(ok.str())); + } + + return boost::report_errors(); +} + diff --git a/src/boost/libs/contract/test/constructor/decl_post_all.cpp b/src/boost/libs/contract/test/constructor/decl_post_all.cpp new file mode 100644 index 000000000..b4e38a1c4 --- /dev/null +++ b/src/boost/libs/contract/test/constructor/decl_post_all.cpp @@ -0,0 +1,186 @@ + +// Copyright (C) 2008-2018 Lorenzo Caminiti +// Distributed under the Boost Software License, Version 1.0 (see accompanying +// file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt). +// See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html + +// Test all derived and base classes with postconditions. + +#undef BOOST_CONTRACT_TEST_NO_A_POST +#undef BOOST_CONTRACT_TEST_NO_B_POST +#undef BOOST_CONTRACT_TEST_NO_C_POST +#include "decl.hpp" + +#include <boost/detail/lightweight_test.hpp> +#include <sstream> +#include <string> + +std::string ok_c() { + std::ostringstream ok; ok + #ifndef BOOST_CONTRACT_NO_PRECONDITIONS + << "a::ctor::pre" << std::endl + << "b::ctor::pre" << std::endl + << "c::ctor::pre" << std::endl + #endif + + #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS + << "c::static_inv" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_OLDS + << "c::ctor::old" << std::endl + #endif + << "c::ctor::body" << std::endl + #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS + << "c::static_inv" << std::endl + << "c::inv" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS + << "c::ctor::post" << std::endl + #endif + ; + return ok.str(); +} + +std::string ok_b() { + std::ostringstream ok; ok + #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS + << "b::static_inv" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_OLDS + << "b::ctor::old" << std::endl + #endif + << "b::ctor::body" << std::endl + #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS + << "b::static_inv" << std::endl + << "b::inv" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS + << "b::ctor::post" << std::endl + #endif + ; + return ok.str(); +} + +std::string ok_a() { + std::ostringstream ok; ok + #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS + << "a::static_inv" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_OLDS + << "a::ctor::old" << std::endl + #endif + << "a::ctor::body" << std::endl + #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS + << "a::static_inv" << std::endl + << "a::inv" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS + << "a::ctor::post" << std::endl + #endif + ; + return ok.str(); +} + +struct err {}; // Global decl so visible in MSVC10 lambdas. + +int main() { + std::ostringstream ok; + + a_post = true; + b_post = true; + c_post = true; + out.str(""); + { + a aa; + ok.str(""); ok // Test nothing failed. + << ok_c() + << ok_b() + << ok_a() + ; + BOOST_TEST(out.eq(ok.str())); + } + + boost::contract::set_postcondition_failure( + [] (boost::contract::from) { throw err(); }); + + a_post = false; + b_post = true; + c_post = true; + out.str(""); + try { + a aa; + #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS + BOOST_TEST(false); + } catch(err const&) { + #endif + ok.str(""); ok + << ok_c() + << ok_b() + << ok_a() + ; + BOOST_TEST(out.eq(ok.str())); + } catch(...) { BOOST_TEST(false); } + + a_post = true; + b_post = false; + c_post = true; + out.str(""); + try { + a aa; + #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS + BOOST_TEST(false); + } catch(err const&) { + #endif + ok.str(""); ok + << ok_c() + << ok_b() // Test b::ctor::post failed. + #ifdef BOOST_CONTRACT_NO_POSTCONDITIONS + << ok_a() + #endif + ; + BOOST_TEST(out.eq(ok.str())); + } catch(...) { BOOST_TEST(false); } + + a_post = true; + b_post = true; + c_post = false; + out.str(""); + try { + a aa; + #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS + BOOST_TEST(false); + } catch(err const&) { + #endif + ok.str(""); ok + << ok_c() // Test c::ctor::post failed. + #ifdef BOOST_CONTRACT_NO_POSTCONDITIONS + << ok_b() + << ok_a() + #endif + ; + BOOST_TEST(out.eq(ok.str())); + } catch(...) { BOOST_TEST(false); } + + a_post = false; + b_post = false; + c_post = false; + out.str(""); + try { + a aa; + #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS + BOOST_TEST(false); + } catch(err const&) { + #endif + ok.str(""); ok + << ok_c() // Test c::ctor::post failed (as all did) + #ifdef BOOST_CONTRACT_NO_POSTCONDITIONS + << ok_b() + << ok_a() + #endif + ; + BOOST_TEST(out.eq(ok.str())); + } catch(...) { BOOST_TEST(false); } + + return boost::report_errors(); +} + diff --git a/src/boost/libs/contract/test/constructor/decl_post_ends.cpp b/src/boost/libs/contract/test/constructor/decl_post_ends.cpp new file mode 100644 index 000000000..b98af74f3 --- /dev/null +++ b/src/boost/libs/contract/test/constructor/decl_post_ends.cpp @@ -0,0 +1,168 @@ + +// Copyright (C) 2008-2018 Lorenzo Caminiti +// Distributed under the Boost Software License, Version 1.0 (see accompanying +// file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt). +// See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html + +// Test only derived and grandparent classes (ends) with postconditions. + +#undef BOOST_CONTRACT_TEST_NO_A_POST +#define BOOST_CONTRACT_TEST_NO_B_POST +#undef BOOST_CONTRACT_TEST_NO_C_POST +#include "decl.hpp" + +#include <boost/detail/lightweight_test.hpp> +#include <sstream> +#include <string> + +std::string ok_c() { + std::ostringstream ok; ok + #ifndef BOOST_CONTRACT_NO_PRECONDITIONS + << "a::ctor::pre" << std::endl + << "b::ctor::pre" << std::endl + << "c::ctor::pre" << std::endl + #endif + + #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS + << "c::static_inv" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_OLDS + << "c::ctor::old" << std::endl + #endif + << "c::ctor::body" << std::endl + #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS + << "c::static_inv" << std::endl + << "c::inv" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS + << "c::ctor::post" << std::endl + #endif + ; + return ok.str(); +} + +std::string ok_ba() { + std::ostringstream ok; ok + #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS + << "b::static_inv" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_OLDS + << "b::ctor::old" << std::endl + #endif + << "b::ctor::body" << std::endl + #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS + << "b::static_inv" << std::endl + << "b::inv" << std::endl + #endif + // No b::ctor::post here. + + #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS + << "a::static_inv" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_OLDS + << "a::ctor::old" << std::endl + #endif + << "a::ctor::body" << std::endl + #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS + << "a::static_inv" << std::endl + << "a::inv" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS + << "a::ctor::post" << std::endl + #endif + ; + return ok.str(); +} + +struct err {}; // Global decl so visible in MSVC10 lambdas. + +int main() { + std::ostringstream ok; + + a_post = true; + b_post = true; + c_post = true; + { + out.str(""); + a aa; + ok.str(""); ok // Test nothing failed. + << ok_c() + << ok_ba() + ; + BOOST_TEST(out.eq(ok.str())); + } + + boost::contract::set_postcondition_failure( + [] (boost::contract::from) { throw err(); }); + + a_post = false; + b_post = true; + c_post = true; + try { + out.str(""); + a aa; + #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS + BOOST_TEST(false); + } catch(err const&) { + #endif + ok.str(""); ok + << ok_c() + << ok_ba() // Test a::ctor::post failed. + ; + BOOST_TEST(out.eq(ok.str())); + } catch(...) { BOOST_TEST(false); } + + a_post = true; + b_post = false; + c_post = true; + { + out.str(""); + a aa; + ok.str(""); ok + << ok_c() + << ok_ba() // Test no b::ctor::post so no failure. + ; + BOOST_TEST(out.eq(ok.str())); + } + + a_post = true; + b_post = true; + c_post = false; + try { + out.str(""); + a aa; + #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS + BOOST_TEST(false); + } catch(err const&) { + #endif + ok.str(""); ok + << ok_c() // Test c::ctor::post failed. + #ifdef BOOST_CONTRACT_NO_POSTCONDITIONS + << ok_ba() + #endif + ; + BOOST_TEST(out.eq(ok.str())); + } catch(...) { BOOST_TEST(false); } + + a_post = false; + b_post = false; + c_post = false; + try { + out.str(""); + a aa; + #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS + BOOST_TEST(false); + } catch(err const&) { + #endif + ok.str(""); ok + << ok_c() // Test c::ctor::post failed (as all did). + #ifdef BOOST_CONTRACT_NO_POSTCONDITIONS + << ok_ba() + #endif + ; + BOOST_TEST(out.eq(ok.str())); + } catch(...) { BOOST_TEST(false); } + + return boost::report_errors(); +} + diff --git a/src/boost/libs/contract/test/constructor/decl_post_mid.cpp b/src/boost/libs/contract/test/constructor/decl_post_mid.cpp new file mode 100644 index 000000000..a6afce6bd --- /dev/null +++ b/src/boost/libs/contract/test/constructor/decl_post_mid.cpp @@ -0,0 +1,160 @@ + +// Copyright (C) 2008-2018 Lorenzo Caminiti +// Distributed under the Boost Software License, Version 1.0 (see accompanying +// file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt). +// See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html + +// Test only middle base class with postconditions. + +#define BOOST_CONTRACT_TEST_NO_A_POST +#undef BOOST_CONTRACT_TEST_NO_B_POST +#define BOOST_CONTRACT_TEST_NO_C_POST +#include "decl.hpp" + +#include <boost/detail/lightweight_test.hpp> +#include <sstream> +#include <string> + +std::string ok_cb() { + std::ostringstream ok; ok + #ifndef BOOST_CONTRACT_NO_PRECONDITIONS + << "a::ctor::pre" << std::endl + << "b::ctor::pre" << std::endl + << "c::ctor::pre" << std::endl + #endif + + #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS + << "c::static_inv" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_OLDS + << "c::ctor::old" << std::endl + #endif + << "c::ctor::body" << std::endl + #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS + << "c::static_inv" << std::endl + << "c::inv" << std::endl + #endif + + #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS + << "b::static_inv" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_OLDS + << "b::ctor::old" << std::endl + #endif + << "b::ctor::body" << std::endl + #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS + << "b::static_inv" << std::endl + << "b::inv" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS + << "b::ctor::post" << std::endl + #endif + ; + return ok.str(); +} + +std::string ok_a() { + std::ostringstream ok; ok + #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS + << "a::static_inv" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_OLDS + << "a::ctor::old" << std::endl + #endif + << "a::ctor::body" << std::endl + #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS + << "a::static_inv" << std::endl + << "a::inv" << std::endl + #endif + ; + return ok.str(); +} + +struct err {}; // Global decl so visible in MSVC10 lambdas. + +int main() { + std::ostringstream ok; + + a_post = true; + b_post = true; + c_post = true; + { + out.str(""); + a aa; + ok.str(""); ok // Test nothing failed. + << ok_cb() + << ok_a() + ; + BOOST_TEST(out.eq(ok.str())); + } + + boost::contract::set_postcondition_failure( + [] (boost::contract::from) { throw err(); }); + + a_post = false; + b_post = true; + c_post = true; + { + out.str(""); + a aa; + ok.str(""); ok + << ok_cb() + << ok_a() // Test no a::ctor::post so no failure. + ; + BOOST_TEST(out.eq(ok.str())); + } + + a_post = true; + b_post = false; + c_post = true; + try { + out.str(""); + a aa; + #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS + BOOST_TEST(false); + } catch(err const&) { + #endif + ok.str(""); ok + << ok_cb() // Test b::ctor::post failed. + #ifdef BOOST_CONTRACT_NO_POSTCONDITIONS + << ok_a() + #endif + ; + BOOST_TEST(out.eq(ok.str())); + } catch(...) { BOOST_TEST(false); } + + a_post = true; + b_post = true; + c_post = false; + { + out.str(""); + a aa; + ok.str(""); ok + << ok_cb() // Test no c::ctor::post so no failure. + << ok_a() + ; + BOOST_TEST(out.eq(ok.str())); + } + + a_post = false; + b_post = false; + c_post = false; + try { + out.str(""); + a aa; + #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS + BOOST_TEST(false); + } catch(err const&) { + #endif + ok.str(""); ok + << ok_cb() // Test b::ctor::post failed (as all did). + #ifdef BOOST_CONTRACT_NO_POSTCONDITIONS + << ok_a() + #endif + ; + BOOST_TEST(out.eq(ok.str())); + } catch(...) { BOOST_TEST(false); } + + return boost::report_errors(); +} + diff --git a/src/boost/libs/contract/test/constructor/decl_post_none.cpp b/src/boost/libs/contract/test/constructor/decl_post_none.cpp new file mode 100644 index 000000000..2b837e192 --- /dev/null +++ b/src/boost/libs/contract/test/constructor/decl_post_none.cpp @@ -0,0 +1,109 @@ + +// Copyright (C) 2008-2018 Lorenzo Caminiti +// Distributed under the Boost Software License, Version 1.0 (see accompanying +// file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt). +// See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html + +// Test only middle base class with postconditions. + +#define BOOST_CONTRACT_TEST_NO_A_POST +#define BOOST_CONTRACT_TEST_NO_B_POST +#define BOOST_CONTRACT_TEST_NO_C_POST +#include "decl.hpp" + +#include <boost/detail/lightweight_test.hpp> +#include <sstream> + +int main() { + std::ostringstream ok; ok // Test nothing fails. + #ifndef BOOST_CONTRACT_NO_PRECONDITIONS + << "a::ctor::pre" << std::endl + << "b::ctor::pre" << std::endl + << "c::ctor::pre" << std::endl + #endif + + #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS + << "c::static_inv" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_OLDS + << "c::ctor::old" << std::endl + #endif + << "c::ctor::body" << std::endl + #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS + << "c::static_inv" << std::endl + << "c::inv" << std::endl + #endif + + #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS + << "b::static_inv" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_OLDS + << "b::ctor::old" << std::endl + #endif + << "b::ctor::body" << std::endl + #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS + << "b::static_inv" << std::endl + << "b::inv" << std::endl + #endif + + #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS + << "a::static_inv" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_OLDS + << "a::ctor::old" << std::endl + #endif + << "a::ctor::body" << std::endl + #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS + << "a::static_inv" << std::endl + << "a::inv" << std::endl + #endif + ; + + a_post = true; + b_post = true; + c_post = true; + { + out.str(""); + a aa; + BOOST_TEST(out.eq(ok.str())); + } + + a_post = false; + b_post = true; + c_post = true; + { + out.str(""); + a aa; + BOOST_TEST(out.eq(ok.str())); + } + + a_post = true; + b_post = false; + c_post = true; + { + out.str(""); + a aa; + BOOST_TEST(out.eq(ok.str())); + } + + a_post = true; + b_post = true; + c_post = false; + { + out.str(""); + a aa; + BOOST_TEST(out.eq(ok.str())); + } + + a_post = false; + b_post = false; + c_post = false; + { + out.str(""); + a aa; + BOOST_TEST(out.eq(ok.str())); + } + + return boost::report_errors(); +} + diff --git a/src/boost/libs/contract/test/constructor/decl_pre_all.cpp b/src/boost/libs/contract/test/constructor/decl_pre_all.cpp new file mode 100644 index 000000000..4714a742d --- /dev/null +++ b/src/boost/libs/contract/test/constructor/decl_pre_all.cpp @@ -0,0 +1,178 @@ + +// Copyright (C) 2008-2018 Lorenzo Caminiti +// Distributed under the Boost Software License, Version 1.0 (see accompanying +// file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt). +// See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html + +// Test all derived and base classes with preconditions. + +#undef BOOST_CONTRACT_TEST_NO_A_PRE +#undef BOOST_CONTRACT_TEST_NO_B_PRE +#undef BOOST_CONTRACT_TEST_NO_C_PRE +#include "decl.hpp" + +#include <boost/detail/lightweight_test.hpp> +#include <sstream> +#include <string> + +std::string ok_after() { + std::ostringstream ok; ok + #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS + << "c::static_inv" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_OLDS + << "c::ctor::old" << std::endl + #endif + << "c::ctor::body" << std::endl + #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS + << "c::static_inv" << std::endl + << "c::inv" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS + << "c::ctor::post" << std::endl + #endif + + #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS + << "b::static_inv" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_OLDS + << "b::ctor::old" << std::endl + #endif + << "b::ctor::body" << std::endl + #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS + << "b::static_inv" << std::endl + << "b::inv" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS + << "b::ctor::post" << std::endl + #endif + + #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS + << "a::static_inv" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_OLDS + << "a::ctor::old" << std::endl + #endif + << "a::ctor::body" << std::endl + #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS + << "a::static_inv" << std::endl + << "a::inv" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS + << "a::ctor::post" << std::endl + #endif + ; + return ok.str(); +} + +struct err {}; // Global decl so visible in MSVC10 lambdas. + +int main() { + std::ostringstream ok; + + a_pre = true; + b_pre = true; + c_pre = true; + { + out.str(""); + a aa; + ok.str(""); ok // Test nothing failed. + #ifndef BOOST_CONTRACT_NO_PRECONDITIONS + << "a::ctor::pre" << std::endl + << "b::ctor::pre" << std::endl + << "c::ctor::pre" << std::endl + #endif + << ok_after() + ; + BOOST_TEST(out.eq(ok.str())); + } + + boost::contract::set_precondition_failure( + [] (boost::contract::from) { throw err(); }); + + a_pre = false; + b_pre = true; + c_pre = true; + try { + out.str(""); + a aa; + #ifndef BOOST_CONTRACT_NO_PRECONDITIONS + BOOST_TEST(false); + } catch(err const&) { + #endif + ok.str(""); ok + #ifndef BOOST_CONTRACT_NO_PRECONDITIONS + << "a::ctor::pre" << std::endl // Test this failed. + #else + << ok_after() + #endif + ; + BOOST_TEST(out.eq(ok.str())); + } catch(...) { BOOST_TEST(false); } + + a_pre = true; + b_pre = false; + c_pre = true; + try { + out.str(""); + a aa; + #ifndef BOOST_CONTRACT_NO_PRECONDITIONS + BOOST_TEST(false); + } catch(err const&) { + #endif + ok.str(""); ok + #ifndef BOOST_CONTRACT_NO_PRECONDITIONS + << "a::ctor::pre" << std::endl + << "b::ctor::pre" << std::endl // Test this failed. + #else + << ok_after() + #endif + ; + BOOST_TEST(out.eq(ok.str())); + } catch(...) { BOOST_TEST(false); } + + a_pre = true; + b_pre = true; + c_pre = false; + try { + out.str(""); + a aa; + #ifndef BOOST_CONTRACT_NO_PRECONDITIONS + BOOST_TEST(false); + } catch(err const&) { + #endif + ok.str(""); ok + #ifndef BOOST_CONTRACT_NO_PRECONDITIONS + << "a::ctor::pre" << std::endl + << "b::ctor::pre" << std::endl + << "c::ctor::pre" << std::endl // Test this failed. + #else + << ok_after() + #endif + ; + BOOST_TEST(out.eq(ok.str())); + } catch(...) { BOOST_TEST(false); } + + a_pre = false; + b_pre = false; + c_pre = false; + try { + out.str(""); + a aa; + #ifndef BOOST_CONTRACT_NO_PRECONDITIONS + BOOST_TEST(false); + } catch(err const&) { + #endif + ok.str(""); ok + #ifndef BOOST_CONTRACT_NO_PRECONDITIONS + << "a::ctor::pre" << std::endl // Test this failed (as all did). + #else + << ok_after() + #endif + ; + BOOST_TEST(out.eq(ok.str())); + } catch(...) { BOOST_TEST(false); } + + return boost::report_errors(); +} + diff --git a/src/boost/libs/contract/test/constructor/decl_pre_ends.cpp b/src/boost/libs/contract/test/constructor/decl_pre_ends.cpp new file mode 100644 index 000000000..6a6a1c131 --- /dev/null +++ b/src/boost/libs/contract/test/constructor/decl_pre_ends.cpp @@ -0,0 +1,172 @@ + +// Copyright (C) 2008-2018 Lorenzo Caminiti +// Distributed under the Boost Software License, Version 1.0 (see accompanying +// file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt). +// See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html + +// Test only derived and grandparent classes (ends) with preconditions. + +#undef BOOST_CONTRACT_TEST_NO_A_PRE +#define BOOST_CONTRACT_TEST_NO_B_PRE +#undef BOOST_CONTRACT_TEST_NO_C_PRE +#include "decl.hpp" + +#include <boost/detail/lightweight_test.hpp> +#include <sstream> +#include <string> + +std::string ok_after() { + std::ostringstream ok; ok + #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS + << "c::static_inv" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_OLDS + << "c::ctor::old" << std::endl + #endif + << "c::ctor::body" << std::endl + #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS + << "c::static_inv" << std::endl + << "c::inv" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS + << "c::ctor::post" << std::endl + #endif + + #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS + << "b::static_inv" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_OLDS + << "b::ctor::old" << std::endl + #endif + << "b::ctor::body" << std::endl + #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS + << "b::static_inv" << std::endl + << "b::inv" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS + << "b::ctor::post" << std::endl + #endif + + #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS + << "a::static_inv" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_OLDS + << "a::ctor::old" << std::endl + #endif + << "a::ctor::body" << std::endl + #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS + << "a::static_inv" << std::endl + << "a::inv" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS + << "a::ctor::post" << std::endl + #endif + ; + return ok.str(); +} + +struct err {}; // Global decl so visible in MSVC10 lambdas. + +int main() { + std::ostringstream ok; + + a_pre = true; + b_pre = true; + c_pre = true; + { + out.str(""); + a aa; + ok.str(""); ok // Test nothing failed. + #ifndef BOOST_CONTRACT_NO_PRECONDITIONS + << "a::ctor::pre" << std::endl + << "c::ctor::pre" << std::endl + #endif + << ok_after() + ; + BOOST_TEST(out.eq(ok.str())); + } + + boost::contract::set_precondition_failure( + [] (boost::contract::from) { throw err(); }); + + a_pre = false; + b_pre = true; + c_pre = true; + try { + out.str(""); + a aa; + #ifndef BOOST_CONTRACT_NO_PRECONDITIONS + BOOST_TEST(false); + } catch(err const&) { + #endif + ok.str(""); ok + #ifndef BOOST_CONTRACT_NO_PRECONDITIONS + << "a::ctor::pre" << std::endl // Test this failed. + #else + << ok_after() + #endif + ; + BOOST_TEST(out.eq(ok.str())); + } catch(...) { BOOST_TEST(false); } + + a_pre = true; + b_pre = false; + c_pre = true; + { + out.str(""); + a aa; + ok.str(""); ok + #ifndef BOOST_CONTRACT_NO_PRECONDITIONS + << "a::ctor::pre" << std::endl + // Test no failure here. + << "c::ctor::pre" << std::endl + #endif + << ok_after() + ; + BOOST_TEST(out.eq(ok.str())); + } + + a_pre = true; + b_pre = true; + c_pre = false; + try { + out.str(""); + a aa; + #ifndef BOOST_CONTRACT_NO_PRECONDITIONS + BOOST_TEST(false); + } catch(err const&) { + #endif + ok.str(""); ok + #ifndef BOOST_CONTRACT_NO_PRECONDITIONS + << "a::ctor::pre" << std::endl + << "c::ctor::pre" << std::endl // Test this failed. + #else + << ok_after() + #endif + ; + BOOST_TEST(out.eq(ok.str())); + } catch(...) { BOOST_TEST(false); } + + a_pre = false; + b_pre = false; + c_pre = false; + try { + out.str(""); + a aa; + #ifndef BOOST_CONTRACT_NO_PRECONDITIONS + BOOST_TEST(false); + } catch(err const&) { + #endif + ok.str(""); ok + #ifndef BOOST_CONTRACT_NO_PRECONDITIONS + << "a::ctor::pre" << std::endl // Test this failed (as all did). + #else + << ok_after() + #endif + ; + BOOST_TEST(out.eq(ok.str())); + } catch(...) { BOOST_TEST(false); } + + return boost::report_errors(); +} + diff --git a/src/boost/libs/contract/test/constructor/decl_pre_mid.cpp b/src/boost/libs/contract/test/constructor/decl_pre_mid.cpp new file mode 100644 index 000000000..a4e7761ee --- /dev/null +++ b/src/boost/libs/contract/test/constructor/decl_pre_mid.cpp @@ -0,0 +1,164 @@ + +// Copyright (C) 2008-2018 Lorenzo Caminiti +// Distributed under the Boost Software License, Version 1.0 (see accompanying +// file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt). +// See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html + +// Test only middle base classes with preconditions. + +#define BOOST_CONTRACT_TEST_NO_A_PRE +#undef BOOST_CONTRACT_TEST_NO_B_PRE +#define BOOST_CONTRACT_TEST_NO_C_PRE +#include "decl.hpp" + +#include <boost/detail/lightweight_test.hpp> +#include <sstream> +#include <string> + +std::string ok_after() { + std::ostringstream ok; ok + #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS + << "c::static_inv" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_OLDS + << "c::ctor::old" << std::endl + #endif + << "c::ctor::body" << std::endl + #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS + << "c::static_inv" << std::endl + << "c::inv" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS + << "c::ctor::post" << std::endl + #endif + + #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS + << "b::static_inv" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_OLDS + << "b::ctor::old" << std::endl + #endif + << "b::ctor::body" << std::endl + #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS + << "b::static_inv" << std::endl + << "b::inv" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS + << "b::ctor::post" << std::endl + #endif + + #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS + << "a::static_inv" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_OLDS + << "a::ctor::old" << std::endl + #endif + << "a::ctor::body" << std::endl + #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS + << "a::static_inv" << std::endl + << "a::inv" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS + << "a::ctor::post" << std::endl + #endif + ; + return ok.str(); +} + +struct err {}; // Global decl so visible in MSVC10 lambdas. + +int main() { + std::ostringstream ok; + + a_pre = true; + b_pre = true; + c_pre = true; + { + out.str(""); + a aa; + ok.str(""); ok // Test nothing failed. + #ifndef BOOST_CONTRACT_NO_PRECONDITIONS + << "b::ctor::pre" << std::endl + #endif + << ok_after() + ; + BOOST_TEST(out.eq(ok.str())); + } + + boost::contract::set_precondition_failure( + [] (boost::contract::from) { throw err(); }); + + a_pre = false; + b_pre = true; + c_pre = true; + { + out.str(""); + a aa; + ok.str(""); ok + #ifndef BOOST_CONTRACT_NO_PRECONDITIONS + << "b::ctor::pre" << std::endl // Test no failure here. + #endif + << ok_after() + ; + BOOST_TEST(out.eq(ok.str())); + } + + a_pre = true; + b_pre = false; + c_pre = true; + try { + out.str(""); + a aa; + #ifndef BOOST_CONTRACT_NO_PRECONDITIONS + BOOST_TEST(false); + } catch(err const&) { + #endif + ok.str(""); ok + #ifndef BOOST_CONTRACT_NO_PRECONDITIONS + << "b::ctor::pre" << std::endl // Test this failed. + #else + << ok_after() + #endif + ; + BOOST_TEST(out.eq(ok.str())); + } catch(...) { BOOST_TEST(false); } + + + a_pre = true; + b_pre = true; + c_pre = false; + { + out.str(""); + a aa; + ok.str(""); ok + #ifndef BOOST_CONTRACT_NO_PRECONDITIONS + << "b::ctor::pre" << std::endl // Test no failure here. + #endif + << ok_after() + ; + BOOST_TEST(out.eq(ok.str())); + } + + a_pre = false; + b_pre = false; + c_pre = false; + try { + out.str(""); + a aa; + #ifndef BOOST_CONTRACT_NO_PRECONDITIONS + BOOST_TEST(false); + } catch(err const&) { + #endif + ok.str(""); ok + #ifndef BOOST_CONTRACT_NO_PRECONDITIONS + << "b::ctor::pre" << std::endl // Test this failed (as all did). + #else + << ok_after() + #endif + ; + BOOST_TEST(out.eq(ok.str())); + } catch(...) { BOOST_TEST(false); } + + return boost::report_errors(); +} + diff --git a/src/boost/libs/contract/test/constructor/decl_pre_none.cpp b/src/boost/libs/contract/test/constructor/decl_pre_none.cpp new file mode 100644 index 000000000..4fa27f030 --- /dev/null +++ b/src/boost/libs/contract/test/constructor/decl_pre_none.cpp @@ -0,0 +1,114 @@ + +// Copyright (C) 2008-2018 Lorenzo Caminiti +// Distributed under the Boost Software License, Version 1.0 (see accompanying +// file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt). +// See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html + +// Test all derived and base classes without preconditions. + +#define BOOST_CONTRACT_TEST_NO_A_PRE +#define BOOST_CONTRACT_TEST_NO_B_PRE +#define BOOST_CONTRACT_TEST_NO_C_PRE +#include "decl.hpp" + +#include <boost/detail/lightweight_test.hpp> +#include <sstream> + +int main() { + std::ostringstream ok; ok + // Test no preconditions here. + + #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS + << "c::static_inv" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_OLDS + << "c::ctor::old" << std::endl + #endif + << "c::ctor::body" << std::endl + #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS + << "c::static_inv" << std::endl + << "c::inv" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS + << "c::ctor::post" << std::endl + #endif + + #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS + << "b::static_inv" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_OLDS + << "b::ctor::old" << std::endl + #endif + << "b::ctor::body" << std::endl + #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS + << "b::static_inv" << std::endl + << "b::inv" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS + << "b::ctor::post" << std::endl + #endif + + #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS + << "a::static_inv" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_OLDS + << "a::ctor::old" << std::endl + #endif + << "a::ctor::body" << std::endl + #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS + << "a::static_inv" << std::endl + << "a::inv" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS + << "a::ctor::post" << std::endl + #endif + ; + + a_pre = true; + b_pre = true; + c_pre = true; + { + out.str(""); + a aa; + BOOST_TEST(out.eq(ok.str())); + } + + a_pre = false; + b_pre = true; + c_pre = true; + { + out.str(""); + a aa; + BOOST_TEST(out.eq(ok.str())); + } + + a_pre = true; + b_pre = false; + c_pre = true; + { + out.str(""); + a aa; + BOOST_TEST(out.eq(ok.str())); + } + + a_pre = true; + b_pre = true; + c_pre = false; + { + out.str(""); + a aa; + BOOST_TEST(out.eq(ok.str())); + } + + a_pre = false; + b_pre = false; + c_pre = false; + { + out.str(""); + a aa; + BOOST_TEST(out.eq(ok.str())); + } + + return boost::report_errors(); +} + diff --git a/src/boost/libs/contract/test/constructor/ifdef.cpp b/src/boost/libs/contract/test/constructor/ifdef.cpp new file mode 100644 index 000000000..8f58c5b95 --- /dev/null +++ b/src/boost/libs/contract/test/constructor/ifdef.cpp @@ -0,0 +1,133 @@ + +// Copyright (C) 2008-2018 Lorenzo Caminiti +// Distributed under the Boost Software License, Version 1.0 (see accompanying +// file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt). +// See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html + +// Test contract compilation on/off. + +#include "../detail/oteststream.hpp" +#include <boost/contract/core/config.hpp> +#if !defined(BOOST_CONTRACT_NO_CONSTRUCTORS) || \ + !defined(BOOST_CONTRACT_NO_PRECONDITIONS) + #include <boost/contract/constructor.hpp> +#endif +#ifndef BOOST_CONTRACT_NO_CONSTRUCTORS + #include <boost/contract/check.hpp> + #include <boost/contract/old.hpp> +#endif +#include <boost/detail/lightweight_test.hpp> +#include <sstream> + +boost::contract::test::detail::oteststream out; + +struct b + #ifndef BOOST_CONTRACT_NO_PRECONDITIONS + : private boost::contract::constructor_precondition<b> + #endif +{ + #ifndef BOOST_CONTRACT_NO_INVARIANTS + static void static_invariant() { out << "b::static_inv" << std::endl; } + void invariant() const { out << "b::inv" << std::endl; } + #endif + + explicit b(int x) + #ifndef BOOST_CONTRACT_NO_PRECONDITIONS + : boost::contract::constructor_precondition<b>([] { + out << "b::ctor::pre" << std::endl; + }) + #endif + { + #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS + boost::contract::old_ptr<int> old_x = BOOST_CONTRACT_OLDOF(x); + #endif + #ifndef BOOST_CONTRACT_NO_CONSTRUCTORS + boost::contract::check c = boost::contract::constructor(this) + #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS + .old([] { out << "b::f::old" << std::endl; }) + .postcondition([] { out << "b::ctor::post" << std::endl; }) + #endif + ; + #endif + out << "b::ctor::body" << std::endl; + } +}; + +struct a : + #ifndef BOOST_CONTRACT_NO_PRECONDITIONS + private boost::contract::constructor_precondition<a>, + #endif + public b +{ + #ifndef BOOST_CONTRACT_NO_INVARIANTS + static void static_invariant() { out << "a::static_inv" << std::endl; } + void invariant() const { out << "a::inv" << std::endl; } + #endif + + explicit a(int x) : + #ifndef BOOST_CONTRACT_NO_PRECONDITIONS + boost::contract::constructor_precondition<a>([] { + out << "a::ctor::pre" << std::endl; + }), + #endif + b(x) + { + #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS + boost::contract::old_ptr<int> old_x = BOOST_CONTRACT_OLDOF(x); + #endif + #ifndef BOOST_CONTRACT_NO_CONSTRUCTORS + boost::contract::check c = boost::contract::constructor(this) + #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS + .old([] { out << "a::f::old" << std::endl; }) + .postcondition([] { out << "a::ctor::post" << std::endl; }) + #endif + ; + #endif + out << "a::ctor::body" << std::endl; + } +}; + +int main() { + std::ostringstream ok; + out.str(""); + a aa(123); + ok.str(""); ok + #ifndef BOOST_CONTRACT_NO_PRECONDITIONS + << "a::ctor::pre" << std::endl + << "b::ctor::pre" << std::endl + #endif + + #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS + << "b::static_inv" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS + << "b::f::old" << std::endl + #endif + << "b::ctor::body" << std::endl + #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS + << "b::static_inv" << std::endl + << "b::inv" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS + << "b::ctor::post" << std::endl + #endif + + #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS + << "a::static_inv" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS + << "a::f::old" << std::endl + #endif + << "a::ctor::body" << std::endl + #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS + << "a::static_inv" << std::endl + << "a::inv" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS + << "a::ctor::post" << std::endl + #endif + ; + BOOST_TEST(out.eq(ok.str())); + return boost::report_errors(); +} + diff --git a/src/boost/libs/contract/test/constructor/ifdef_macro.cpp b/src/boost/libs/contract/test/constructor/ifdef_macro.cpp new file mode 100644 index 000000000..2041cdaa0 --- /dev/null +++ b/src/boost/libs/contract/test/constructor/ifdef_macro.cpp @@ -0,0 +1,157 @@ + +// Copyright (C) 2008-2018 Lorenzo Caminiti +// Distributed under the Boost Software License, Version 1.0 (see accompanying +// file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt). +// See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html + +// Test contract compilation on/off (using macro interface). + +#include "../detail/oteststream.hpp" +#include "../detail/unprotected_commas.hpp" +#include <boost/contract/core/config.hpp> +#include <boost/contract/constructor.hpp> // Outside #if below for ctor pre. +#include <boost/contract_macro.hpp> +#include <boost/detail/lightweight_test.hpp> +#include <sstream> + +boost::contract::test::detail::oteststream out; + +struct b : + private boost::contract::constructor_precondition<b> // OK, always in code. +{ + BOOST_CONTRACT_STATIC_INVARIANT({ + boost::contract::test::detail::unprotected_commas<void, void, void>:: + call(); + out << "b::static_inv" << std::endl; + }) + + BOOST_CONTRACT_INVARIANT({ + boost::contract::test::detail::unprotected_commas<void, void, void>:: + call(); + out << "b::inv" << std::endl; + }) + + explicit b(int x) : + BOOST_CONTRACT_CONSTRUCTOR_PRECONDITION(b)([] { + boost::contract::test::detail::unprotected_commas<void, void, void> + ::call(); + out << "b::ctor::pre" << std::endl; + }) + { + BOOST_CONTRACT_OLD_PTR( + boost::contract::test::detail::unprotected_commas<int, void, + void>::type1 + )( + old_x, + (boost::contract::test::detail::unprotected_commas<void, void, + void>::same(x)) + ); + BOOST_CONTRACT_CONSTRUCTOR(this) + BOOST_CONTRACT_OLD([] { + boost::contract::test::detail::unprotected_commas< + void, void, void>::call(); + out << "b::f::old" << std::endl; + }) + BOOST_CONTRACT_POSTCONDITION([] { + boost::contract::test::detail::unprotected_commas< + void, void, void>::call(); + out << "b::ctor::post" << std::endl; + }) + ; + out << "b::ctor::body" << std::endl; + } +}; + +struct a: + private boost::contract::constructor_precondition<a>, // OK, always in code. + public b +{ + BOOST_CONTRACT_STATIC_INVARIANT({ + boost::contract::test::detail::unprotected_commas<void, void, void>:: + call(); + out << "a::static_inv" << std::endl; + }) + + BOOST_CONTRACT_INVARIANT({ + boost::contract::test::detail::unprotected_commas<void, void, void>:: + call(); + out << "a::inv" << std::endl; + }) + + explicit a(int x) : + BOOST_CONTRACT_CONSTRUCTOR_PRECONDITION(a)([] { + boost::contract::test::detail::unprotected_commas<void, void, void> + ::call(); + out << "a::ctor::pre" << std::endl; } + ), + b(x) + { + BOOST_CONTRACT_OLD_PTR( + boost::contract::test::detail::unprotected_commas<int, void, + void>::type1 + )( + old_x, + (boost::contract::test::detail::unprotected_commas<void, void, + void>::same(x)) + ); + BOOST_CONTRACT_CONSTRUCTOR(boost::contract::test::detail:: + unprotected_commas<void, void, void>::same(this)) + BOOST_CONTRACT_OLD([] { + boost::contract::test::detail::unprotected_commas< + void, void, void>::call(); + out << "a::f::old" << std::endl; + }) + BOOST_CONTRACT_POSTCONDITION([] { + boost::contract::test::detail::unprotected_commas< + void, void, void>::call(); + out << "a::ctor::post" << std::endl; + }) + ; + out << "a::ctor::body" << std::endl; + } +}; + +int main() { + std::ostringstream ok; + out.str(""); + a aa(123); + ok.str(""); ok + #ifndef BOOST_CONTRACT_NO_PRECONDITIONS + << "a::ctor::pre" << std::endl + << "b::ctor::pre" << std::endl + #endif + + #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS + << "b::static_inv" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_OLDS + << "b::f::old" << std::endl + #endif + << "b::ctor::body" << std::endl + #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS + << "b::static_inv" << std::endl + << "b::inv" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS + << "b::ctor::post" << std::endl + #endif + + #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS + << "a::static_inv" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_OLDS + << "a::f::old" << std::endl + #endif + << "a::ctor::body" << std::endl + #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS + << "a::static_inv" << std::endl + << "a::inv" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS + << "a::ctor::post" << std::endl + #endif + ; + BOOST_TEST(out.eq(ok.str())); + return boost::report_errors(); +} + diff --git a/src/boost/libs/contract/test/constructor/pre_error.cpp b/src/boost/libs/contract/test/constructor/pre_error.cpp new file mode 100644 index 000000000..36e06c4c5 --- /dev/null +++ b/src/boost/libs/contract/test/constructor/pre_error.cpp @@ -0,0 +1,24 @@ + +// Copyright (C) 2008-2018 Lorenzo Caminiti +// Distributed under the Boost Software License, Version 1.0 (see accompanying +// file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt). +// See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html + +// Test constructor cannot use `.precondition(...)`. + +#include <boost/contract/constructor.hpp> +#include <boost/contract/check.hpp> + +struct a { + a() { + boost::contract::check c = boost::contract::constructor(this) + .precondition([] {}) // Error (must use constructor_precondition). + ; + } +}; + +int main() { + a aa; + return 0; +} + diff --git a/src/boost/libs/contract/test/constructor/smoke.cpp b/src/boost/libs/contract/test/constructor/smoke.cpp new file mode 100644 index 000000000..133cc1405 --- /dev/null +++ b/src/boost/libs/contract/test/constructor/smoke.cpp @@ -0,0 +1,410 @@ + +// Copyright (C) 2008-2018 Lorenzo Caminiti +// Distributed under the Boost Software License, Version 1.0 (see accompanying +// file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt). +// See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html + +// Test constructor subcontracting. + +#include "../detail/oteststream.hpp" +#include "../detail/counter.hpp" +#include <boost/contract/constructor.hpp> +#include <boost/contract/base_types.hpp> +#include <boost/contract/assert.hpp> +#include <boost/contract/old.hpp> +#include <boost/contract/check.hpp> +#include <boost/bind.hpp> +#include <boost/ref.hpp> +#include <boost/detail/lightweight_test.hpp> +#include <sstream> + +boost::contract::test::detail::oteststream out; + +template<char Id> +struct t + #define BASES private boost::contract::constructor_precondition<t<Id> > + : BASES +{ + typedef BOOST_CONTRACT_BASE_TYPES(BASES) base_types; + #undef BASES + + static void static_invariant() { + out << Id << "::static_inv" << std::endl; + BOOST_CONTRACT_ASSERT(l.value >= 0); + } + + void invariant() const { + out << Id << "::inv" << std::endl; + BOOST_CONTRACT_ASSERT(k_ < 0); + } + + struct l_tag; + typedef boost::contract::test::detail::counter<l_tag, int> l_type; + static l_type l; + + struct z_tag; + typedef boost::contract::test::detail::counter<z_tag, int> z_type; + + explicit t(z_type& z) : + boost::contract::constructor_precondition<t<Id> >([&] { + out << Id << "::ctor::pre" << std::endl; + BOOST_CONTRACT_ASSERT(z.value < 0); + }) + { + boost::contract::old_ptr<z_type> old_z; + boost::contract::old_ptr<l_type> old_l = + BOOST_CONTRACT_OLDOF(l_type::eval(l)); + boost::contract::check c = boost::contract::constructor(this) + .old([&] { + out << Id << "::ctor::old" << std::endl; + old_z = BOOST_CONTRACT_OLDOF(z_type::eval(z)); + }) + .postcondition([&] { + out << Id << "::ctor::post" << std::endl; + BOOST_CONTRACT_ASSERT(k_ == old_z->value); + BOOST_CONTRACT_ASSERT(z.value == l.value); + BOOST_CONTRACT_ASSERT(l.value == old_l->value + 1); + }) + ; + out << Id << "::ctor::body" << std::endl; + k_ = z.value; + z.value = ++l.value; + } + + virtual ~t() { --l.value; } + +private: + int k_; +}; +template<char Id> typename t<Id>::l_type t<Id>::l; + +// 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<c>, \ + public t<'d'>, protected t<'p'>, private t<'q'>, public t<'e'> + : BASES +{ + typedef BOOST_CONTRACT_BASE_TYPES(BASES) base_types; + #undef BASES + + static void static_invariant() { + out << "c::static_inv" << std::endl; + BOOST_CONTRACT_ASSERT(m.value >= 0); + } + + void invariant() const { + out << "c::inv" << std::endl; + BOOST_CONTRACT_ASSERT(j_ < 0); + } + + struct m_tag; + typedef boost::contract::test::detail::counter<m_tag, int> m_type; + static m_type m; + + struct y_tag; + typedef boost::contract::test::detail::counter<y_tag, int> y_type; + + explicit c(y_type& y, t<'d'>::z_type& dz, t<'p'>::z_type& pz, + t<'q'>::z_type& qz, t<'e'>::z_type& ez) : + boost::contract::constructor_precondition<c>([&] { + out << "c::ctor::pre" << std::endl; + BOOST_CONTRACT_ASSERT(y.value < 0); + }), + t<'d'>(dz), t<'p'>(pz), t<'q'>(qz), t<'e'>(ez) + { + boost::contract::old_ptr<y_type> old_y = + BOOST_CONTRACT_OLDOF(y_type::eval(y)); + boost::contract::old_ptr<m_type> old_m; + boost::contract::check c = boost::contract::constructor(this) + .old([&] { + out << "c::ctor::old" << std::endl; + old_m = BOOST_CONTRACT_OLDOF(m_type::eval(m)); + }) + .postcondition([&] { + out << "c::ctor::post" << std::endl; + BOOST_CONTRACT_ASSERT(j_ == old_y->value); + BOOST_CONTRACT_ASSERT(y.value == m.value); + BOOST_CONTRACT_ASSERT(m.value == old_m->value + 1); + }) + ; + out << "c::ctor::body" << std::endl; + j_ = y.value; + y.value = ++m.value; + } + + virtual ~c() { --m.value; } + +private: + int j_; +}; +c::m_type c::m; + +// Test not (fully) contracted base is not part of constructor subcontracting. +struct b + #define BASES private boost::contract::constructor_precondition<b> + : BASES +{ + typedef BOOST_CONTRACT_BASE_TYPES(BASES) base_types; + #undef BASES + + static void static_invariant() { out << "b::static_inv" << std::endl; } + void invariant() const { out << "b::inv" << std::endl; } + + explicit b() {} // No contract. + virtual ~b() {} +}; + +// Test constructor with both non-contracted and contracted bases. +struct a + #define BASES private boost::contract::constructor_precondition<a>, \ + public b, public c + : BASES +{ + typedef BOOST_CONTRACT_BASE_TYPES(BASES) base_types; + #undef BASES + + static void static_invariant() { + out << "a::static_inv" << std::endl; + BOOST_CONTRACT_ASSERT(n.value >= 0); + } + + void invariant() const { + out << "a::inv" << std::endl; + BOOST_CONTRACT_ASSERT(i_ < 0); + } + + struct n_tag; + typedef boost::contract::test::detail::counter<n_tag, int> n_type; + static n_type n; + + struct x_tag; + typedef boost::contract::test::detail::counter<x_tag, int> x_type; + + explicit a(x_type& x, c::y_type& y, t<'d'>::z_type& dz, + t<'p'>::z_type& pz, t<'q'>::z_type& qz, t<'e'>::z_type& ez) : + boost::contract::constructor_precondition<a>([&] { + out << "a::ctor::pre" << std::endl; + BOOST_CONTRACT_ASSERT(x.value < 0); + }), + b(), c(y, dz, pz, qz, ez) + { + boost::contract::old_ptr<x_type> old_x; + boost::contract::old_ptr<n_type> old_n = + BOOST_CONTRACT_OLDOF(n_type::eval(n)); + boost::contract::check c = boost::contract::constructor(this) + .old([&] { + out << "a::ctor::old" << std::endl; + old_x = BOOST_CONTRACT_OLDOF(x_type::eval(x)); + }) + .postcondition([&] { + out << "a::ctor::post" << std::endl; + BOOST_CONTRACT_ASSERT(i_ == old_x->value); + BOOST_CONTRACT_ASSERT(x.value == n.value); + BOOST_CONTRACT_ASSERT(n.value == old_n->value + 1); + }) + ; + out << "a::ctor::body" << std::endl; + i_ = x.value; + x.value = ++n.value; + } + + virtual ~a() { --n.value; } + +private: + int i_; +}; +a::n_type a::n; + +int main() { + std::ostringstream ok; + + { + t<'e'>::z_type ez; ez.value = -5; + t<'q'>::z_type qz; qz.value = -5; + t<'p'>::z_type pz; pz.value = -4; + t<'d'>::z_type dz; dz.value = -3; + c::y_type y; y.value = -2; + a::x_type x; x.value = -1; + + out.str(""); + a aa(x, y, dz, pz, qz, ez); + ok.str(""); ok + // Test all constructor pre checked first. + #ifndef BOOST_CONTRACT_NO_PRECONDITIONS + << "a::ctor::pre" << std::endl + << "c::ctor::pre" << std::endl + #endif + + // Test static inv, but not const inv, checked before ctor body. + #ifndef BOOST_CONTRACT_NO_PRECONDITIONS + << "d::ctor::pre" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS + << "d::static_inv" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_OLDS + << "d::ctor::old" << std::endl + #endif + << "d::ctor::body" << std::endl + #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS + << "d::static_inv" << std::endl + << "d::inv" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS + << "d::ctor::post" << std::endl + #endif + + // Test check also protected bases (because part of C++ constr.). + #ifndef BOOST_CONTRACT_NO_PRECONDITIONS + << "p::ctor::pre" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS + << "p::static_inv" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_OLDS + << "p::ctor::old" << std::endl + #endif + << "p::ctor::body" << std::endl + #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS + << "p::static_inv" << std::endl + << "p::inv" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS + << "p::ctor::post" << std::endl + #endif + + // Test check also private bases (because part of C++ constr.). + #ifndef BOOST_CONTRACT_NO_PRECONDITIONS + << "q::ctor::pre" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS + << "q::static_inv" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_OLDS + << "q::ctor::old" << std::endl + #endif + << "q::ctor::body" << std::endl + #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS + << "q::static_inv" << std::endl + << "q::inv" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS + << "q::ctor::post" << std::endl + #endif + + #ifndef BOOST_CONTRACT_NO_PRECONDITIONS + << "e::ctor::pre" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS + << "e::static_inv" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_OLDS + << "e::ctor::old" << std::endl + #endif + << "e::ctor::body" << std::endl + #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS + << "e::static_inv" << std::endl + << "e::inv" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS + << "e::ctor::post" << std::endl + #endif + + #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS + << "c::static_inv" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_OLDS + << "c::ctor::old" << std::endl + #endif + << "c::ctor::body" << std::endl + #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS + << "c::static_inv" << std::endl + << "c::inv" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS + << "c::ctor::post" << std::endl + #endif + + #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS + << "a::static_inv" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_OLDS + << "a::ctor::old" << std::endl + #endif + << "a::ctor::body" << std::endl + #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS + << "a::static_inv" << std::endl + << "a::inv" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS + << "a::ctor::post" << std::endl + #endif + ; + BOOST_TEST(out.eq(ok.str())); + } + + #ifndef BOOST_CONTRACT_NO_OLDS + #define BOOST_CONTRACT_TEST_old 1u + #else + #define BOOST_CONTRACT_TEST_old 0u + #endif + + std::clog << a::x_type::copies() << std::endl; + std::clog << BOOST_CONTRACT_TEST_old << std::endl; + BOOST_TEST_EQ(a::x_type::copies(), BOOST_CONTRACT_TEST_old); + BOOST_TEST_EQ(a::x_type::evals(), BOOST_CONTRACT_TEST_old); + BOOST_TEST_EQ(a::x_type::ctors(), a::x_type::dtors()); // No leak. + + BOOST_TEST_EQ(c::y_type::copies(), BOOST_CONTRACT_TEST_old); + BOOST_TEST_EQ(c::y_type::evals(), BOOST_CONTRACT_TEST_old); + BOOST_TEST_EQ(c::y_type::ctors(), c::y_type::dtors()); // No leak. + + BOOST_TEST_EQ(t<'d'>::z_type::copies(), BOOST_CONTRACT_TEST_old); + BOOST_TEST_EQ(t<'d'>::z_type::evals(), BOOST_CONTRACT_TEST_old); + BOOST_TEST_EQ(t<'d'>::z_type::ctors(), t<'d'>::z_type::dtors()); // No leak. + + BOOST_TEST_EQ(t<'p'>::z_type::copies(), BOOST_CONTRACT_TEST_old); + BOOST_TEST_EQ(t<'p'>::z_type::evals(), BOOST_CONTRACT_TEST_old); + BOOST_TEST_EQ(t<'p'>::z_type::ctors(), t<'p'>::z_type::dtors()); // No leak. + + BOOST_TEST_EQ(t<'q'>::z_type::copies(), BOOST_CONTRACT_TEST_old); + BOOST_TEST_EQ(t<'q'>::z_type::evals(), BOOST_CONTRACT_TEST_old); + BOOST_TEST_EQ(t<'q'>::z_type::ctors(), t<'q'>::z_type::dtors()); // No leak. + + BOOST_TEST_EQ(t<'e'>::z_type::copies(), BOOST_CONTRACT_TEST_old); + BOOST_TEST_EQ(t<'e'>::z_type::evals(), BOOST_CONTRACT_TEST_old); + BOOST_TEST_EQ(t<'e'>::z_type::ctors(), t<'e'>::z_type::dtors()); // No leak. + + // Following destroy only copies (actual objects are static data members). + + BOOST_TEST_EQ(a::n_type::copies(), BOOST_CONTRACT_TEST_old); + BOOST_TEST_EQ(a::n_type::evals(), BOOST_CONTRACT_TEST_old); + BOOST_TEST_EQ(a::n_type::copies(), a::n_type::dtors()); // No leak. + + BOOST_TEST_EQ(c::m_type::copies(), BOOST_CONTRACT_TEST_old); + BOOST_TEST_EQ(c::m_type::evals(), BOOST_CONTRACT_TEST_old); + BOOST_TEST_EQ(c::m_type::copies(), c::m_type::dtors()); // No leak. + + BOOST_TEST_EQ(t<'d'>::l_type::copies(), BOOST_CONTRACT_TEST_old); + BOOST_TEST_EQ(t<'d'>::l_type::evals(), BOOST_CONTRACT_TEST_old); + BOOST_TEST_EQ(t<'e'>::l_type::copies(), t<'e'>::l_type::dtors()); // No leak + + BOOST_TEST_EQ(t<'p'>::l_type::copies(), BOOST_CONTRACT_TEST_old); + BOOST_TEST_EQ(t<'p'>::l_type::evals(), BOOST_CONTRACT_TEST_old); + BOOST_TEST_EQ(t<'e'>::l_type::copies(), t<'e'>::l_type::dtors()); // No leak + + BOOST_TEST_EQ(t<'q'>::l_type::copies(), BOOST_CONTRACT_TEST_old); + BOOST_TEST_EQ(t<'q'>::l_type::evals(), BOOST_CONTRACT_TEST_old); + BOOST_TEST_EQ(t<'e'>::l_type::copies(), t<'e'>::l_type::dtors()); // No leak + + BOOST_TEST_EQ(t<'e'>::l_type::copies(), BOOST_CONTRACT_TEST_old); + BOOST_TEST_EQ(t<'e'>::l_type::evals(), BOOST_CONTRACT_TEST_old); + BOOST_TEST_EQ(t<'e'>::l_type::copies(), t<'e'>::l_type::dtors()); // No leak + + #undef BOOST_CONTRACT_TEST_old + return boost::report_errors(); +} + diff --git a/src/boost/libs/contract/test/constructor/throwing_body.cpp b/src/boost/libs/contract/test/constructor/throwing_body.cpp new file mode 100644 index 000000000..cb385eb73 --- /dev/null +++ b/src/boost/libs/contract/test/constructor/throwing_body.cpp @@ -0,0 +1,145 @@ + +// Copyright (C) 2008-2018 Lorenzo Caminiti +// Distributed under the Boost Software License, Version 1.0 (see accompanying +// file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt). +// See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html + +// Test throw form constructor body (in middle branch of inheritance tree). + +#include "../detail/oteststream.hpp" +#include <boost/contract/constructor.hpp> +#include <boost/contract/base_types.hpp> +#include <boost/contract/check.hpp> +#include <boost/detail/lightweight_test.hpp> +#include <sstream> + +boost::contract::test::detail::oteststream out; + +struct c + #define BASES private boost::contract::constructor_precondition<c> + : BASES +{ + typedef BOOST_CONTRACT_BASE_TYPES(BASES) base_types; + #undef BASES + + static void static_invariant() { out << "c::static_inv" << std::endl; } + void invariant() const { out << "c::inv" << std::endl; } + + c() : + boost::contract::constructor_precondition<c>([] { + out << "c::ctor::pre" << std::endl; + }) + { + boost::contract::check c = boost::contract::constructor(this) + .old([] { out << "c::ctor::old" << std::endl; }) + .postcondition([] { out << "c::ctor::post" << std::endl; }) + .except([] { out << "c::ctor::except" << std::endl; }) + ; + out << "c::ctor::body" << std::endl; + // Do not throw (from inheritance root). + } +}; + +struct b_err {}; // Global decl so visible in MSVC10 lambdas. + +struct b + #define BASES private boost::contract::constructor_precondition<b>, public c + : BASES +{ + typedef BOOST_CONTRACT_BASE_TYPES(BASES) base_types; + #undef BASES + + static void static_invariant() { out << "b::static_inv" << std::endl; } + void invariant() const { out << "b::inv" << std::endl; } + + b() : + boost::contract::constructor_precondition<b>([] { + out << "b::ctor::pre" << std::endl; + }) + { + boost::contract::check c = boost::contract::constructor(this) + .old([] { out << "b::ctor::old" << std::endl; }) + .postcondition([] { out << "b::ctor::post" << std::endl; }) + .except([] { out << "b::ctor::except" << std::endl; }) + ; + out << "b::ctor::body" << std::endl; + throw b_err(); // Test body throws (from inheritance mid branch). + } +}; + +struct a + #define BASES private boost::contract::constructor_precondition<a>, public b + : BASES +{ + typedef BOOST_CONTRACT_BASE_TYPES(BASES) base_types; + #undef BASES + + static void static_invariant() { out << "a::static_inv" << std::endl; } + void invariant() const { out << "a::inv" << std::endl; } + + a() : + boost::contract::constructor_precondition<a>([] { + out << "a::ctor::pre" << std::endl; + }) + { + boost::contract::check c = boost::contract::constructor(this) + .old([] { out << "a::ctor::old" << std::endl; }) + .postcondition([] { out << "a::ctor::post" << std::endl; }) + .except([] { out << "a::ctor::except" << std::endl; }) + ; + out << "a::ctor::body" << std::endl; + // Do not throw (from inheritance leaf). + } +}; + +int main() { + std::ostringstream ok; + + try { + out.str(""); + a aa; + BOOST_TEST(false); + } catch(b_err const&) { + ok.str(""); ok + #ifndef BOOST_CONTRACT_NO_PRECONDITIONS + << "a::ctor::pre" << std::endl + << "b::ctor::pre" << std::endl + << "c::ctor::pre" << std::endl + #endif + + #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS + << "c::static_inv" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_OLDS + << "c::ctor::old" << std::endl + #endif + << "c::ctor::body" << std::endl + #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS + << "c::static_inv" << std::endl + << "c::inv" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS + << "c::ctor::post" << std::endl + #endif + + #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS + << "b::static_inv" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_OLDS + << "b::ctor::old" << std::endl + #endif + << "b::ctor::body" << std::endl // Test this threw... + // ... so check only following after (no post, no a ctor, etc.). + #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS + << "b::static_inv" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_EXCEPTS + << "b::ctor::except" << std::endl + #endif + ; + BOOST_TEST(out.eq(ok.str())); + } catch(...) { BOOST_TEST(false); } + + return boost::report_errors(); +} + diff --git a/src/boost/libs/contract/test/constructor/throwing_old.cpp b/src/boost/libs/contract/test/constructor/throwing_old.cpp new file mode 100644 index 000000000..432641e1d --- /dev/null +++ b/src/boost/libs/contract/test/constructor/throwing_old.cpp @@ -0,0 +1,158 @@ + +// Copyright (C) 2008-2018 Lorenzo Caminiti +// Distributed under the Boost Software License, Version 1.0 (see accompanying +// file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt). +// See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html + +// Test throw form constructor .old() (in middle branch of inheritance tree). + +#include "../detail/oteststream.hpp" +#include <boost/contract/constructor.hpp> +#include <boost/contract/base_types.hpp> +#include <boost/contract/check.hpp> +#include <boost/detail/lightweight_test.hpp> +#include <sstream> + +boost::contract::test::detail::oteststream out; + +struct c + #define BASES private boost::contract::constructor_precondition<c> + : BASES +{ + typedef BOOST_CONTRACT_BASE_TYPES(BASES) base_types; + #undef BASES + + static void static_invariant() { out << "c::static_inv" << std::endl; } + void invariant() const { out << "c::inv" << std::endl; } + + c() : + boost::contract::constructor_precondition<c>([] { + out << "c::ctor::pre" << std::endl; + }) + { + boost::contract::check c = boost::contract::constructor(this) + .old([] { out << "c::ctor::old" << std::endl; }) + .postcondition([] { out << "c::ctor::post" << std::endl; }) + .except([] { out << "c::ctor::except" << std::endl; }) + ; + out << "c::ctor::body" << std::endl; + // Do not throw (from inheritance root). + } +}; + +struct b_err {}; // Global decl so visible in MSVC10 lambdas. + +struct b + #define BASES private boost::contract::constructor_precondition<b>, public c + : BASES +{ + typedef BOOST_CONTRACT_BASE_TYPES(BASES) base_types; + #undef BASES + + static void static_invariant() { out << "b::static_inv" << std::endl; } + void invariant() const { out << "b::inv" << std::endl; } + + b() : + boost::contract::constructor_precondition<b>([] { + out << "b::ctor::pre" << std::endl; + }) + { + boost::contract::check c = boost::contract::constructor(this) + .old([] { + out << "b::ctor::old" << std::endl; + throw b_err(); // Test this throws (from mid branch). + }) + .postcondition([] { out << "b::ctor::post" << std::endl; }) + .except([] { out << "b::ctor::except" << std::endl; }) + ; + out << "b::ctor::body" << std::endl; + } +}; + +struct a + #define BASES private boost::contract::constructor_precondition<a>, public b + : BASES +{ + typedef BOOST_CONTRACT_BASE_TYPES(BASES) base_types; + #undef BASES + + static void static_invariant() { out << "a::static_inv" << std::endl; } + void invariant() const { out << "a::inv" << std::endl; } + + a() : + boost::contract::constructor_precondition<a>([] { + out << "a::ctor::pre" << std::endl; + }) + { + boost::contract::check c = boost::contract::constructor(this) + .old([] { out << "a::ctor::old" << std::endl; }) + .postcondition([] { out << "a::ctor::post" << std::endl; }) + .except([] { out << "a::ctor::except" << std::endl; }) + ; + out << "a::ctor::body" << std::endl; + // Do not throw (from inheritance leaf). + } +}; + +int main() { + std::ostringstream ok; + + boost::contract::set_old_failure([] (boost::contract::from) { throw; }); + + try { + out.str(""); + a aa; + #ifndef BOOST_CONTRACT_NO_OLDS + BOOST_TEST(false); + } catch(b_err const&) { + #endif + ok.str(""); ok + #ifndef BOOST_CONTRACT_NO_PRECONDITIONS + << "a::ctor::pre" << std::endl + << "b::ctor::pre" << std::endl + << "c::ctor::pre" << std::endl + #endif + + #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS + << "c::static_inv" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_OLDS + << "c::ctor::old" << std::endl + #endif + << "c::ctor::body" << std::endl + #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS + << "c::static_inv" << std::endl + << "c::inv" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS + << "c::ctor::post" << std::endl + #endif + + #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS + << "b::static_inv" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_OLDS + << "b::ctor::old" << std::endl // Test this threw. + #else + << "b::ctor::body" << std::endl + #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS + << "b::static_inv" << std::endl + << "b::inv" << std::endl + #endif + + #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS + << "a::static_inv" << std::endl + #endif + << "a::ctor::body" << std::endl + #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS + << "a::static_inv" << std::endl + << "a::inv" << std::endl + #endif + #endif + ; + BOOST_TEST(out.eq(ok.str())); + } catch(...) { BOOST_TEST(false); } + + return boost::report_errors(); +} + diff --git a/src/boost/libs/contract/test/constructor/throwing_post.cpp b/src/boost/libs/contract/test/constructor/throwing_post.cpp new file mode 100644 index 000000000..beaa31ac2 --- /dev/null +++ b/src/boost/libs/contract/test/constructor/throwing_post.cpp @@ -0,0 +1,164 @@ + +// Copyright (C) 2008-2018 Lorenzo Caminiti +// Distributed under the Boost Software License, Version 1.0 (see accompanying +// file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt). +// See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html + +// Test throw form constructor .post() (in middle branch of inheritance tree). + +#include "../detail/oteststream.hpp" +#include <boost/contract/constructor.hpp> +#include <boost/contract/base_types.hpp> +#include <boost/contract/check.hpp> +#include <boost/detail/lightweight_test.hpp> +#include <sstream> + +boost::contract::test::detail::oteststream out; + +struct c + #define BASES private boost::contract::constructor_precondition<c> + : BASES +{ + typedef BOOST_CONTRACT_BASE_TYPES(BASES) base_types; + #undef BASES + + static void static_invariant() { out << "c::static_inv" << std::endl; } + void invariant() const { out << "c::inv" << std::endl; } + + c() : + boost::contract::constructor_precondition<c>([] { + out << "c::ctor::pre" << std::endl; + }) + { + boost::contract::check c = boost::contract::constructor(this) + .old([] { out << "c::ctor::old" << std::endl; }) + .postcondition([] { out << "c::ctor::post" << std::endl; }) + .except([] { out << "c::ctor::except" << std::endl; }) + ; + out << "c::ctor::body" << std::endl; + // Do not throw (from inheritance root). + } +}; + +struct b_err {}; // Global decl so visible in MSVC10 lambdas. + +struct b + #define BASES private boost::contract::constructor_precondition<b>, public c + : BASES +{ + typedef BOOST_CONTRACT_BASE_TYPES(BASES) base_types; + #undef BASES + + static void static_invariant() { out << "b::static_inv" << std::endl; } + void invariant() const { out << "b::inv" << std::endl; } + + b() : + boost::contract::constructor_precondition<b>([] { + out << "b::ctor::pre" << std::endl; + }) + { + boost::contract::check c = boost::contract::constructor(this) + .old([] { out << "b::ctor::old" << std::endl; }) + .postcondition([] { + out << "b::ctor::post" << std::endl; + throw b_err(); // Test this throws (from mid branch). + }) + .except([] { out << "b::ctor::except" << std::endl; }) + ; + out << "b::ctor::body" << std::endl; + } +}; + +struct a + #define BASES private boost::contract::constructor_precondition<a>, public b + : BASES +{ + typedef BOOST_CONTRACT_BASE_TYPES(BASES) base_types; + #undef BASES + + static void static_invariant() { out << "a::static_inv" << std::endl; } + void invariant() const { out << "a::inv" << std::endl; } + + a() : + boost::contract::constructor_precondition<a>([] { + out << "a::ctor::pre" << std::endl; + }) + { + boost::contract::check c = boost::contract::constructor(this) + .old([] { out << "a::ctor::old" << std::endl; }) + .postcondition([] { out << "a::ctor::post" << std::endl; }) + .except([] { out << "a::ctor::except" << std::endl; }) + ; + out << "a::ctor::body" << std::endl; + // Do not throw (from inheritance leaf). + } +}; + +int main() { + std::ostringstream ok; + + boost::contract::set_postcondition_failure( + [] (boost::contract::from) { throw; }); + + try { + out.str(""); + a aa; + #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS + BOOST_TEST(false); + } catch(b_err const&) { + #endif + ok.str(""); ok + #ifndef BOOST_CONTRACT_NO_PRECONDITIONS + << "a::ctor::pre" << std::endl + << "b::ctor::pre" << std::endl + << "c::ctor::pre" << std::endl + #endif + + #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS + << "c::static_inv" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_OLDS + << "c::ctor::old" << std::endl + #endif + << "c::ctor::body" << std::endl + #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS + << "c::static_inv" << std::endl + << "c::inv" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS + << "c::ctor::post" << std::endl + #endif + + #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS + << "b::static_inv" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_OLDS + << "b::ctor::old" << std::endl + #endif + << "b::ctor::body" << std::endl + #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS + << "b::static_inv" << std::endl + << "b::inv" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS + << "b::ctor::post" << std::endl // Test this threw. + #else + #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS + << "a::static_inv" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_OLDS + << "a::ctor::old" << std::endl + #endif + << "a::ctor::body" << std::endl + #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS + << "a::static_inv" << std::endl + << "a::inv" << std::endl + #endif + #endif + ; + BOOST_TEST(out.eq(ok.str())); + } catch(...) { BOOST_TEST(false); } + + return boost::report_errors(); +} + diff --git a/src/boost/libs/contract/test/constructor/throwing_pre.cpp b/src/boost/libs/contract/test/constructor/throwing_pre.cpp new file mode 100644 index 000000000..e06a8542e --- /dev/null +++ b/src/boost/libs/contract/test/constructor/throwing_pre.cpp @@ -0,0 +1,164 @@ + +// Copyright (C) 2008-2018 Lorenzo Caminiti +// Distributed under the Boost Software License, Version 1.0 (see accompanying +// file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt). +// See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html + +// Test throw form constructor .pre() (in middle branch of inheritance tree). + +#include "../detail/oteststream.hpp" +#include <boost/contract/constructor.hpp> +#include <boost/contract/base_types.hpp> +#include <boost/contract/check.hpp> +#include <boost/detail/lightweight_test.hpp> +#include <sstream> + +boost::contract::test::detail::oteststream out; + +struct c + #define BASES private boost::contract::constructor_precondition<c> + : BASES +{ + typedef BOOST_CONTRACT_BASE_TYPES(BASES) base_types; + #undef BASES + + static void static_invariant() { out << "c::static_inv" << std::endl; } + void invariant() const { out << "c::inv" << std::endl; } + + c() : + boost::contract::constructor_precondition<c>([] { + out << "c::ctor::pre" << std::endl; + }) + { + boost::contract::check c = boost::contract::constructor(this) + .old([] { out << "c::ctor::old" << std::endl; }) + .postcondition([] { out << "c::ctor::post" << std::endl; }) + .except([] { out << "c::ctor::except" << std::endl; }) + ; + out << "c::ctor::body" << std::endl; + // Do not throw (from inheritance root). + } +}; + +struct b_err {}; // Global decl so visible in MSVC10 lambdas. + +struct b + #define BASES private boost::contract::constructor_precondition<b>, public c + : BASES +{ + typedef BOOST_CONTRACT_BASE_TYPES(BASES) base_types; + #undef BASES + + static void static_invariant() { out << "b::static_inv" << std::endl; } + void invariant() const { out << "b::inv" << std::endl; } + + b() : + boost::contract::constructor_precondition<b>([] { + out << "b::ctor::pre" << std::endl; + throw b_err(); // Test this throws (from mid branch). + }) + { + boost::contract::check c = boost::contract::constructor(this) + .old([] { out << "b::ctor::old" << std::endl; }) + .postcondition([] { out << "b::ctor::post" << std::endl; }) + .except([] { out << "b::ctor::except" << std::endl; }) + ; + out << "b::ctor::body" << std::endl; + } +}; + +struct a + #define BASES private boost::contract::constructor_precondition<a>, public b + : BASES +{ + typedef BOOST_CONTRACT_BASE_TYPES(BASES) base_types; + #undef BASES + + static void static_invariant() { out << "a::static_inv" << std::endl; } + void invariant() const { out << "a::inv" << std::endl; } + + a() : + boost::contract::constructor_precondition<a>([] { + out << "a::ctor::pre" << std::endl; + }) + { + boost::contract::check c = boost::contract::constructor(this) + .old([] { out << "a::ctor::old" << std::endl; }) + .postcondition([] { out << "a::ctor::post" << std::endl; }) + .except([] { out << "a::ctor::except" << std::endl; }) + ; + out << "a::ctor::body" << std::endl; + // Do not throw (from inheritance leaf). + } +}; + +int main() { + std::ostringstream ok; + + boost::contract::set_precondition_failure( + [] (boost::contract::from) { throw; }); + + try { + out.str(""); + a aa; +#ifndef BOOST_CONTRACT_NO_PRECONDITIONS + BOOST_TEST(false); + } catch(b_err const&) { +#endif + ok.str(""); ok + #ifndef BOOST_CONTRACT_NO_PRECONDITIONS + << "a::ctor::pre" << std::endl + << "b::ctor::pre" << std::endl // Test this threw. + #else + #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS + << "c::static_inv" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_OLDS + << "c::ctor::old" << std::endl + #endif + << "c::ctor::body" << std::endl + #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS + << "c::static_inv" << std::endl + << "c::inv" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS + << "c::ctor::post" << std::endl + #endif + + #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS + << "b::static_inv" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_OLDS + << "b::ctor::old" << std::endl + #endif + << "b::ctor::body" << std::endl + #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS + << "b::static_inv" << std::endl + << "b::inv" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS + << "b::ctor::post" << std::endl + #endif + + #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS + << "a::static_inv" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_OLDS + << "a::ctor::old" << std::endl + #endif + << "a::ctor::body" << std::endl + #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS + << "a::static_inv" << std::endl + << "a::inv" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS + << "a::ctor::post" << std::endl + #endif + #endif + ; + BOOST_TEST(out.eq(ok.str())); + } catch(...) { BOOST_TEST(false); } + + return boost::report_errors(); +} + diff --git a/src/boost/libs/contract/test/destructor/access.cpp b/src/boost/libs/contract/test/destructor/access.cpp new file mode 100644 index 000000000..757248e61 --- /dev/null +++ b/src/boost/libs/contract/test/destructor/access.cpp @@ -0,0 +1,122 @@ + +// Copyright (C) 2008-2018 Lorenzo Caminiti +// Distributed under the Boost Software License, Version 1.0 (see accompanying +// file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt). +// See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html + +// Test making all contract extra declarations (base types, inv, etc.) private. + +#include "../detail/oteststream.hpp" +#include <boost/contract/destructor.hpp> +#include <boost/contract/base_types.hpp> +#include <boost/contract/check.hpp> +#include <boost/detail/lightweight_test.hpp> +#include <sstream> + +boost::contract::test::detail::oteststream out; + +class b { + friend class boost::contract::access; + + static void static_invariant() { out << "b::static_inv" << std::endl; } + void invariant() const { out << "b::inv" << std::endl; } + +public: + virtual ~b() { + boost::contract::check c = boost::contract::destructor(this) + .old([] { out << "b::dtor::old" << std::endl; }) + .postcondition([] { out << "b::dtor::post" << std::endl; }) + ; + out << "b::dtor::body" << std::endl; + } +}; + +class a + #define BASES public b + : BASES +{ + friend class boost::contract::access; + + // Private base types (always OK because never used by dtors). + typedef BOOST_CONTRACT_BASE_TYPES(BASES) base_types; + #undef BASES + + // Private invariants. + static void static_invariant() { out << "a::static_inv" << std::endl; } + void invariant() const { out << "a::inv" << std::endl; } + +public: + virtual ~a() { + boost::contract::check c = boost::contract::destructor(this) + .old([] { out << "a::dtor::old" << std::endl; }) + .postcondition([] { out << "a::dtor::post" << std::endl; }) + ; + out << "a::dtor::body" << std::endl; + } +}; + +int main() { + std::ostringstream ok; + + { + a aa; + out.str(""); + } // Call aa's destructor. + ok.str(""); ok + #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS + << "a::static_inv" << std::endl + << "a::inv" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_OLDS + << "a::dtor::old" << std::endl + #endif + << "a::dtor::body" << std::endl + #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS + << "a::static_inv" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS + << "a::dtor::post" << std::endl + #endif + + #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS + << "b::static_inv" << std::endl + << "b::inv" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_OLDS + << "b::dtor::old" << std::endl + #endif + << "b::dtor::body" << std::endl + #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS + << "b::static_inv" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS + << "b::dtor::post" << std::endl + #endif + ; + BOOST_TEST(out.eq(ok.str())); + + { + b bb; + out.str(""); + } // Call bb's destructor. + ok.str(""); ok + #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS + << "b::static_inv" << std::endl + << "b::inv" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_OLDS + << "b::dtor::old" << std::endl + #endif + << "b::dtor::body" << std::endl + #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS + << "b::static_inv" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS + << "b::dtor::post" << std::endl + #endif + ; + BOOST_TEST(out.eq(ok.str())); + + return boost::report_errors(); +} + diff --git a/src/boost/libs/contract/test/destructor/decl.hpp b/src/boost/libs/contract/test/destructor/decl.hpp new file mode 100644 index 000000000..8fdc8c3d3 --- /dev/null +++ b/src/boost/libs/contract/test/destructor/decl.hpp @@ -0,0 +1,145 @@ + +#ifndef BOOST_CONTRACT_TEST_DESTRUCTOR_DECL_HPP_ +#define BOOST_CONTRACT_TEST_DESTRUCTOR_DECL_HPP_ + +// Copyright (C) 2008-2018 Lorenzo Caminiti +// Distributed under the Boost Software License, Version 1.0 (see accompanying +// file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt). +// See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html + +// Test with and without pre, post, and inv declarations. + +#include "../detail/oteststream.hpp" +#include <boost/contract/destructor.hpp> +#include <boost/contract/base_types.hpp> +#include <boost/contract/check.hpp> +#include <boost/contract/assert.hpp> +#include <boost/config.hpp> + +boost::contract::test::detail::oteststream out; + +bool c_pre = true, c_post = true; +bool c_entering_static_inv = true, c_entry_static_inv = true, + c_exit_static_inv = true; +bool c_entry_inv = true; // Only entry non-static inv for dtors. +struct c { + #ifndef BOOST_CONTRACT_TEST_NO_C_STATIC_INV + static void static_invariant() { + out << "c::static_inv" << std::endl; + if(c_entering_static_inv) BOOST_CONTRACT_ASSERT(c_entry_static_inv); + else BOOST_CONTRACT_ASSERT(c_exit_static_inv); + c_entering_static_inv = false; + } + #endif + #ifndef BOOST_CONTRACT_TEST_NO_C_INV + void invariant() const { + out << "c::inv" << std::endl; + BOOST_CONTRACT_ASSERT(c_entry_inv); + } + #endif + + virtual ~c() BOOST_NOEXCEPT_IF(false) { + boost::contract::check c = boost::contract::destructor(this) + #ifdef BOOST_CONTRACT_TEST_NO_C_PRE + #error "destructors cannot have preconditions" + #endif + .old([] { out << "c::dtor::old" << std::endl; }) + #ifndef BOOST_CONTRACT_TEST_NO_C_POST + .postcondition([] { + out << "c::dtor::post" << std::endl; + BOOST_CONTRACT_ASSERT(c_post); + }) + #endif + ; + out << "c::dtor::body" << std::endl; + } +}; + +bool b_pre = true, b_post = true; +bool b_entering_static_inv = true, b_entry_static_inv = true, + b_exit_static_inv = true; +bool b_entry_inv = true; // Only entry non-static inv for dtors. +struct b + #define BASES public c + : BASES +{ + typedef BOOST_CONTRACT_BASE_TYPES(BASES) base_types; + #undef BASES + + #ifndef BOOST_CONTRACT_TEST_NO_B_STATIC_INV + static void static_invariant() { + out << "b::static_inv" << std::endl; + if(b_entering_static_inv) BOOST_CONTRACT_ASSERT(b_entry_static_inv); + else BOOST_CONTRACT_ASSERT(b_exit_static_inv); + b_entering_static_inv = false; + } + #endif + #ifndef BOOST_CONTRACT_TEST_NO_B_INV + void invariant() const { + out << "b::inv" << std::endl; + BOOST_CONTRACT_ASSERT(b_entry_inv); + } + #endif + + virtual ~b() BOOST_NOEXCEPT_IF(false) { + boost::contract::check c = boost::contract::destructor(this) + #ifdef BOOST_CONTRACT_TEST_NO_B_PRE + #error "destructors cannot have preconditions" + #endif + .old([] { out << "b::dtor::old" << std::endl; }) + #ifndef BOOST_CONTRACT_TEST_NO_B_POST + .postcondition([] { + out << "b::dtor::post" << std::endl; + BOOST_CONTRACT_ASSERT(b_post); + }) + #endif + ; + out << "b::dtor::body" << std::endl; + } +}; + +bool a_pre = true, a_post = true; +bool a_entering_static_inv = true, a_entry_static_inv = true, + a_exit_static_inv = true; +bool a_entry_inv = true; // Only entry non-static inv for dtors. +struct a + #define BASES public b + : BASES +{ + typedef BOOST_CONTRACT_BASE_TYPES(BASES) base_types; + #undef BASES + + #ifndef BOOST_CONTRACT_TEST_NO_A_STATIC_INV + static void static_invariant() { + out << "a::static_inv" << std::endl; + if(a_entering_static_inv) BOOST_CONTRACT_ASSERT(a_entry_static_inv); + else BOOST_CONTRACT_ASSERT(a_exit_static_inv); + a_entering_static_inv = false; + } + #endif + #ifndef BOOST_CONTRACT_TEST_NO_A_INV + void invariant() const { + out << "a::inv" << std::endl; + BOOST_CONTRACT_ASSERT(a_entry_inv); + } + #endif + + virtual ~a() BOOST_NOEXCEPT_IF(false) { + boost::contract::check c = boost::contract::destructor(this) + #ifdef BOOST_CONTRACT_TEST_NO_A_PRE + #error "destructors cannot have preconditions" + #endif + .old([] { out << "a::dtor::old" << std::endl; }) + #ifndef BOOST_CONTRACT_TEST_NO_A_POST + .postcondition([] { + out << "a::dtor::post" << std::endl; + BOOST_CONTRACT_ASSERT(a_post); + }) + #endif + ; + out << "a::dtor::body" << std::endl; + } +}; + +#endif // #include guard + diff --git a/src/boost/libs/contract/test/destructor/decl_entry_inv_all.cpp b/src/boost/libs/contract/test/destructor/decl_entry_inv_all.cpp new file mode 100644 index 000000000..39395c7aa --- /dev/null +++ b/src/boost/libs/contract/test/destructor/decl_entry_inv_all.cpp @@ -0,0 +1,222 @@ + +// Copyright (C) 2008-2018 Lorenzo Caminiti +// Distributed under the Boost Software License, Version 1.0 (see accompanying +// file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt). +// See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html + +// Test all derived and base classes with entry static invariants. + +#undef BOOST_CONTRACT_TEST_NO_A_INV +#undef BOOST_CONTRACT_TEST_NO_B_INV +#undef BOOST_CONTRACT_TEST_NO_C_INV +#include "decl.hpp" + +#include <boost/detail/lightweight_test.hpp> +#include <sstream> +#include <string> + +std::string ok_a(bool failed = false) { + std::ostringstream ok; ok << "" // Suppress a warning. + #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS + << "a::static_inv" << std::endl + << "a::inv" << std::endl // This can fail. + #endif + ; + if(!failed) ok + #ifndef BOOST_CONTRACT_NO_OLDS + << "a::dtor::old" << std::endl + #endif + << "a::dtor::body" << std::endl + #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS + << "a::static_inv" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS + << "a::dtor::post" << std::endl + #endif + ; + return ok.str(); +} + +enum checked { passed, failed, threw }; + +std::string ok_b(checked check = passed) { + std::ostringstream ok; ok << "" // Suppress a warning. + #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS + << "b::static_inv" << std::endl + << "b::inv" << std::endl // This can fail. + #endif + ; + if(check != failed) ok + #ifndef BOOST_CONTRACT_NO_OLDS + << "b::dtor::old" << std::endl + #endif + << "b::dtor::body" << std::endl + #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS + << "b::static_inv" << std::endl + << (check == threw ? "b::inv\n" : "") + #endif + #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS + << (check == passed ? "b::dtor::post\n" : "") + #endif + ; + return ok.str(); +} + +std::string ok_c(checked check = passed) { + std::ostringstream ok; ok << "" // Suppress a warning. + #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS + << "c::static_inv" << std::endl + << "c::inv" << std::endl // This can fail. + #endif + ; + if(check != failed) ok + #ifndef BOOST_CONTRACT_NO_OLDS + << "c::dtor::old" << std::endl + #endif + << "c::dtor::body" << std::endl + #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS + << "c::static_inv" << std::endl + << (check == threw ? "c::inv\n" : "") + #endif + #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS + << (check == passed ? "c::dtor::post\n" : "") + #endif + ; + return ok.str(); +} + +struct err {}; // Global decl so visible in MSVC10 lambdas. + +int main() { + std::ostringstream ok; + + a_entry_inv = true; + b_entry_inv = true; + c_entry_inv = true; + { + a aa; + out.str(""); + } + ok.str(""); ok // Test nothing failed. + << ok_a() + << ok_b() + << ok_c() + ; + BOOST_TEST(out.eq(ok.str())); + + boost::contract::set_entry_invariant_failure([&ok] (boost::contract::from) { + BOOST_TEST(out.eq(ok.str())); // Must check before dtor throws. + throw err(); // For testing only (dtors should never throw otherwise). + }); + + #ifdef BOOST_CONTRACT_NO_ENTRY_INVARIANTS + #define BOOST_CONTRACT_TEST_entry_inv 0 + #else + #define BOOST_CONTRACT_TEST_entry_inv 1 + #endif + + a_entry_inv = false; + b_entry_inv = true; + c_entry_inv = true; + try { + { + a aa; + ok.str(""); ok + // Test entry a::inv failed... + << ok_a(BOOST_CONTRACT_TEST_entry_inv) + ; + out.str(""); + } + #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS + BOOST_TEST(false); + } catch(err const&) { + #endif + ok // ...then exec other dtors and check inv on throw (as dtor threw). + << ok_b(BOOST_CONTRACT_TEST_entry_inv ? threw : passed) + << ok_c(BOOST_CONTRACT_TEST_entry_inv ? threw : passed) + ; + BOOST_TEST(out.eq(ok.str())); + } catch(...) { BOOST_TEST(false); } + + a_entry_inv = true; + b_entry_inv = false; + c_entry_inv = true; + try { + { + a aa; + ok.str(""); ok + << ok_a() + // Test entry b::inv failed... + << ok_b(BOOST_CONTRACT_TEST_entry_inv ? failed : passed) + ; + out.str(""); + } + #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS + BOOST_TEST(false); + } catch(err const&) { + #endif + ok // ...then exec other dtors and check inv on throw (as dtor threw). + << ok_c(BOOST_CONTRACT_TEST_entry_inv ? threw : passed) + ; + BOOST_TEST(out.eq(ok.str())); + } catch(...) { BOOST_TEST(false); } + + a_entry_inv = true; + b_entry_inv = true; + c_entry_inv = false; + try { + { + a aa; + ok.str(""); ok + << ok_a() + << ok_b() + // Test entry c::inv failed... + << ok_c(BOOST_CONTRACT_TEST_entry_inv ? failed : passed) + ; + out.str(""); + } + #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS + BOOST_TEST(false); + } catch(err const&) { + #endif + // ...then exec other dtors and check inv on throw (as dtor threw). + BOOST_TEST(out.eq(ok.str())); + } catch(...) { BOOST_TEST(false); } + + boost::contract::set_entry_invariant_failure([] (boost::contract::from) { + // Testing multiple failures so dtors must not throw multiple except, + // just ignore failure and continue test program (for testing only). + }); + + a_entry_inv = false; + b_entry_inv = false; + c_entry_inv = false; + { + a aa; + out.str(""); + } + ok.str(""); ok + // Test entry a::inv failed (as all did). + << ok_a(BOOST_CONTRACT_TEST_entry_inv) + #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS + << "a::dtor::body" << std::endl + #endif + + // Test entry b::inv failed (as all did). + << ok_b(BOOST_CONTRACT_TEST_entry_inv ? failed : passed) + #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS + << "b::dtor::body" << std::endl + #endif + + // Test entry c::inv failed (as all did). + << ok_c(BOOST_CONTRACT_TEST_entry_inv ? failed : passed) + #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS + << "c::dtor::body" << std::endl + #endif + ; + BOOST_TEST(out.eq(ok.str())); + + #undef BOOST_CONTRACT_TEST_entry_inv + return boost::report_errors(); +} + diff --git a/src/boost/libs/contract/test/destructor/decl_entry_inv_ends.cpp b/src/boost/libs/contract/test/destructor/decl_entry_inv_ends.cpp new file mode 100644 index 000000000..f7cee609a --- /dev/null +++ b/src/boost/libs/contract/test/destructor/decl_entry_inv_ends.cpp @@ -0,0 +1,206 @@ + +// Copyright (C) 2008-2018 Lorenzo Caminiti +// Distributed under the Boost Software License, Version 1.0 (see accompanying +// file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt). +// See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html + +// Test only derived and grandparent classes (ends) with entry invariants. + +#undef BOOST_CONTRACT_TEST_NO_A_INV +#define BOOST_CONTRACT_TEST_NO_B_INV +#undef BOOST_CONTRACT_TEST_NO_C_INV +#include "decl.hpp" + +#include <boost/detail/lightweight_test.hpp> +#include <sstream> +#include <string> + +std::string ok_a(bool failed = false) { + std::ostringstream ok; ok << "" // Suppress a warning. + #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS + << "a::static_inv" << std::endl + << "a::inv" << std::endl // This can fail. + #endif + ; + if(!failed) ok + #ifndef BOOST_CONTRACT_NO_OLDS + << "a::dtor::old" << std::endl + #endif + << "a::dtor::body" << std::endl + #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS + << "a::static_inv" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS + << "a::dtor::post" << std::endl + #endif + ; + return ok.str(); +} + +std::string ok_b(bool threw = false) { + std::ostringstream ok; ok << "" // Suppress a warning. + #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS + << "b::static_inv" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_OLDS + << "b::dtor::old" << std::endl + #endif + << "b::dtor::body" << std::endl + #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS + << "b::static_inv" << std::endl + // No b::inv here (not even when threw). + #endif + #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS + << (!threw ? "b::dtor::post\n" : "") + #endif + ; + return ok.str(); +} + +enum checked { passed, failed, threw }; + +std::string ok_c(checked check = passed) { + std::ostringstream ok; ok << "" // Suppress a warning. + #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS + << "c::static_inv" << std::endl + << "c::inv" << std::endl // This can fail. + #endif + ; + if(check != failed) ok + #ifndef BOOST_CONTRACT_NO_OLDS + << "c::dtor::old" << std::endl + #endif + << "c::dtor::body" << std::endl + #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS + << "c::static_inv" << std::endl + << (check == threw ? "c::inv\n" : "") + #endif + #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS + << (check == passed ? "c::dtor::post\n" : "") + #endif + ; + return ok.str(); +} + +struct err {}; // Global decl so visible in MSVC10 lambdas. + +int main() { + std::ostringstream ok; + + a_entry_inv = true; + b_entry_inv = true; + c_entry_inv = true; + { + a aa; + out.str(""); + } + ok.str(""); ok // Test nothing failed. + << ok_a() + << ok_b() + << ok_c() + ; + BOOST_TEST(out.eq(ok.str())); + + boost::contract::set_entry_invariant_failure([&ok] (boost::contract::from) { + BOOST_TEST(out.eq(ok.str())); // Must check before dtor throws... + throw err(); // for testing (as dtors should never throw anyways). + }); + + #ifdef BOOST_CONTRACT_NO_ENTRY_INVARIANTS + #define BOOST_CONTRACT_TEST_entry_inv 0 + #else + #define BOOST_CONTRACT_TEST_entry_inv 1 + #endif + + a_entry_inv = false; + b_entry_inv = true; + c_entry_inv = true; + try { + { + a aa; + ok.str(""); ok + // Test entry a::inv failed... + << ok_a(BOOST_CONTRACT_TEST_entry_inv) + ; + out.str(""); + } + #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS + BOOST_TEST(false); + } catch(err const&) { + #endif + ok // ...then exec other dtors and check inv on throw (as dtor threw). + << ok_b(BOOST_CONTRACT_TEST_entry_inv) + << ok_c(BOOST_CONTRACT_TEST_entry_inv ? threw : passed) + ; + BOOST_TEST(out.eq(ok.str())); + } catch(...) { BOOST_TEST(false); } + + a_entry_inv = true; + b_entry_inv = false; + c_entry_inv = true; + { + a aa; + out.str(""); + } + ok.str(""); ok + << ok_a() + << ok_b() // Test no entry b::inv so no failure here. + << ok_c() + ; + BOOST_TEST(out.eq(ok.str())); + + a_entry_inv = true; + b_entry_inv = true; + c_entry_inv = false; + try { + { + a aa; + ok.str(""); ok + << ok_a() + << ok_b() + // Test entry c::inv failed... + << ok_c(BOOST_CONTRACT_TEST_entry_inv ? failed : passed) + ; + out.str(""); + } + #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS + BOOST_TEST(false); + } catch(err const&) { + #endif + // ...then exec other dtors and check inv on throw (as dtor threw). + BOOST_TEST(out.eq(ok.str())); + } catch(...) { BOOST_TEST(false); } + + boost::contract::set_entry_invariant_failure([] (boost::contract::from) { + // Testing multiple failures so dtors must not throw multiple + // exceptions, just ignore failure and continue test program... + }); + + a_entry_inv = false; + b_entry_inv = false; + c_entry_inv = false; + { + a aa; + out.str(""); + } + ok.str(""); ok + // Test entry a::inv failed (as all did). + << ok_a(BOOST_CONTRACT_TEST_entry_inv) + #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS + << "a::dtor::body" << std::endl + #endif + + << ok_b() // Test no entry b::inv so no failure here. + + // Test entry c::inv failed (as all did). + << ok_c(BOOST_CONTRACT_TEST_entry_inv ? failed : passed) + #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS + << "c::dtor::body" << std::endl + #endif + ; + BOOST_TEST(out.eq(ok.str())); + + #undef BOOST_CONTRACT_TEST_entry_inv + return boost::report_errors(); +} + diff --git a/src/boost/libs/contract/test/destructor/decl_entry_inv_mid.cpp b/src/boost/libs/contract/test/destructor/decl_entry_inv_mid.cpp new file mode 100644 index 000000000..247d68cee --- /dev/null +++ b/src/boost/libs/contract/test/destructor/decl_entry_inv_mid.cpp @@ -0,0 +1,194 @@ + +// Copyright (C) 2008-2018 Lorenzo Caminiti +// Distributed under the Boost Software License, Version 1.0 (see accompanying +// file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt). +// See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html + +// Test only middle base class with entry invariants. + +#define BOOST_CONTRACT_TEST_NO_A_INV +#undef BOOST_CONTRACT_TEST_NO_B_INV +#define BOOST_CONTRACT_TEST_NO_C_INV +#include "decl.hpp" + +#include <boost/detail/lightweight_test.hpp> +#include <sstream> +#include <string> + +std::string ok_a() { + std::ostringstream ok; ok + #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS + << "a::static_inv" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_OLDS + << "a::dtor::old" << std::endl + #endif + << "a::dtor::body" << std::endl + #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS + << "a::static_inv" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS + << "a::dtor::post" << std::endl + #endif + ; + return ok.str(); +} + +std::string ok_b(bool failed = false) { + std::ostringstream ok; ok << "" // Suppress a warning. + #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS + << "b::static_inv" << std::endl + << "b::inv" << std::endl // This can fail. + #endif + ; + if(!failed) ok + #ifndef BOOST_CONTRACT_NO_OLDS + << "b::dtor::old" << std::endl + #endif + << "b::dtor::body" << std::endl + #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS + << "b::static_inv" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS + << "b::dtor::post" << std::endl + #endif + ; + return ok.str(); +} + +std::string ok_c(bool threw = false) { + std::ostringstream ok; ok + #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS + << "c::static_inv" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_OLDS + << "c::dtor::old" << std::endl + #endif + << "c::dtor::body" << std::endl + #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS + << "c::static_inv" << std::endl + // No b::inv here (not even when threw). + #endif + #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS + << (!threw ? "c::dtor::post\n" : "") + #endif + ; + return ok.str(); +} + +struct err {}; // Global decl so visible in MSVC10 lambdas. + +int main() { + std::ostringstream ok; + + a_entry_inv = true; + b_entry_inv = true; + c_entry_inv = true; + { + a aa; + out.str(""); + } + ok.str(""); ok // Test nothing failed. + << ok_a() + << ok_b() + << ok_c() + ; + BOOST_TEST(out.eq(ok.str())); + + boost::contract::set_entry_invariant_failure([&ok] (boost::contract::from) { + BOOST_TEST(out.eq(ok.str())); // Must check before dtor throws... + throw err(); // for testing (as dtors should never throw anyways). + }); + + a_entry_inv = false; + b_entry_inv = true; + c_entry_inv = true; + try { + { + a aa; + ok.str(""); + out.str(""); + } + ok.str(""); ok + << ok_a() // Test no entry a::inv so no failure here. + << ok_b() + << ok_c() + ; + BOOST_TEST(out.eq(ok.str())); + } catch(...) { BOOST_TEST(false); } + + #ifdef BOOST_CONTRACT_NO_ENTRY_INVARIANTS + #define BOOST_CONTRACT_TEST_entry_inv 0 + #else + #define BOOST_CONTRACT_TEST_entry_inv 2 + #endif + + a_entry_inv = true; + b_entry_inv = false; + c_entry_inv = true; + try { + { + a aa; + ok.str(""); ok + << ok_a() + // Test entry b::inv failed... + << ok_b(bool(BOOST_CONTRACT_TEST_entry_inv)) + ; + out.str(""); + } + #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS + BOOST_TEST(false); + } catch(err const&) { + #endif + ok // ...then exec other dtors and check inv on throw (as dtor threw). + << ok_c(bool(BOOST_CONTRACT_TEST_entry_inv)) + ; + BOOST_TEST(out.eq(ok.str())); + } catch(...) { BOOST_TEST(false); } + + a_entry_inv = true; + b_entry_inv = true; + c_entry_inv = false; + try { + { + a aa; + ok.str(""); + out.str(""); + } + ok.str(""); ok + << ok_a() + << ok_b() + << ok_c() // Test no entry c::inv so no failure here. + ; + BOOST_TEST(out.eq(ok.str())); + } catch(...) { BOOST_TEST(false); } + + boost::contract::set_entry_invariant_failure([] (boost::contract::from) { + // Testing multiple failures so dtors must not throw multiple + // exceptions, just ignore failure and continue test program... + }); + + a_entry_inv = false; + b_entry_inv = false; + c_entry_inv = false; + { + a aa; + out.str(""); + } + ok.str(""); ok + << ok_a() // Test no entry a::inv so no failure here. + + // Test entry b::inv failed (as all did). + << ok_b(bool(BOOST_CONTRACT_TEST_entry_inv)) + #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS + << "b::dtor::body" << std::endl + #endif + + << ok_c() // Test no entry c::inv so no failure here. + ; + BOOST_TEST(out.eq(ok.str())); + + #undef BOOST_CONTRACT_TEST_entry_inv + return boost::report_errors(); +} + diff --git a/src/boost/libs/contract/test/destructor/decl_entry_inv_none.cpp b/src/boost/libs/contract/test/destructor/decl_entry_inv_none.cpp new file mode 100644 index 000000000..342a78935 --- /dev/null +++ b/src/boost/libs/contract/test/destructor/decl_entry_inv_none.cpp @@ -0,0 +1,109 @@ + +// Copyright (C) 2008-2018 Lorenzo Caminiti +// Distributed under the Boost Software License, Version 1.0 (see accompanying +// file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt). +// See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html + +// Test all derived and base classes without entry invariants. + +#define BOOST_CONTRACT_TEST_NO_A_INV +#define BOOST_CONTRACT_TEST_NO_B_INV +#define BOOST_CONTRACT_TEST_NO_C_INV +#include "decl.hpp" + +#include <boost/detail/lightweight_test.hpp> +#include <sstream> + +int main() { + std::ostringstream ok; ok // Test nothing fails. + #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS + << "a::static_inv" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_OLDS + << "a::dtor::old" << std::endl + #endif + << "a::dtor::body" << std::endl + #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS + << "a::static_inv" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS + << "a::dtor::post" << std::endl + #endif + + #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS + << "b::static_inv" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_OLDS + << "b::dtor::old" << std::endl + #endif + << "b::dtor::body" << std::endl + #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS + << "b::static_inv" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS + << "b::dtor::post" << std::endl + #endif + + #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS + << "c::static_inv" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_OLDS + << "c::dtor::old" << std::endl + #endif + << "c::dtor::body" << std::endl + #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS + << "c::static_inv" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS + << "c::dtor::post" << std::endl + #endif + ; + + a_entry_inv = true; + b_entry_inv = true; + c_entry_inv = true; + { + a aa; + out.str(""); + } + BOOST_TEST(out.eq(ok.str())); + + a_entry_inv = false; + b_entry_inv = true; + c_entry_inv = true; + { + a aa; + out.str(""); + } + BOOST_TEST(out.eq(ok.str())); + + a_entry_inv = true; + b_entry_inv = false; + c_entry_inv = true; + { + a aa; + out.str(""); + } + BOOST_TEST(out.eq(ok.str())); + + a_entry_inv = true; + b_entry_inv = true; + c_entry_inv = false; + { + a aa; + out.str(""); + } + BOOST_TEST(out.eq(ok.str())); + + a_entry_inv = false; + b_entry_inv = false; + c_entry_inv = false; + { + a aa; + out.str(""); + } + BOOST_TEST(out.eq(ok.str())); + + return boost::report_errors(); +} + diff --git a/src/boost/libs/contract/test/destructor/decl_entry_static_inv_all.cpp b/src/boost/libs/contract/test/destructor/decl_entry_static_inv_all.cpp new file mode 100644 index 000000000..34476bb87 --- /dev/null +++ b/src/boost/libs/contract/test/destructor/decl_entry_static_inv_all.cpp @@ -0,0 +1,231 @@ + +// Copyright (C) 2008-2018 Lorenzo Caminiti +// Distributed under the Boost Software License, Version 1.0 (see accompanying +// file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt). +// See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html + +// Test all derived and base classes with entry static invariants. + +#undef BOOST_CONTRACT_TEST_NO_A_STATIC_INV +#undef BOOST_CONTRACT_TEST_NO_B_STATIC_INV +#undef BOOST_CONTRACT_TEST_NO_C_STATIC_INV +#include "decl.hpp" + +#include <boost/preprocessor/control/iif.hpp> +#include <boost/detail/lightweight_test.hpp> +#include <sstream> +#include <string> + +std::string ok_a() { + std::ostringstream ok; ok + #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS + << "a::static_inv" << std::endl + << "a::inv" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_OLDS + << "a::dtor::old" << std::endl + #endif + << "a::dtor::body" << std::endl + #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS + << "a::static_inv" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS + << "a::dtor::post" << std::endl + #endif + ; + return ok.str(); +} + +std::string ok_b(bool threw = false) { + std::ostringstream ok; ok + #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS + << "b::static_inv" << std::endl + << "b::inv" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_OLDS + << "b::dtor::old" << std::endl + #endif + << "b::dtor::body" << std::endl + #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS + << "b::static_inv" << std::endl + << (threw ? "b::inv\n" : "") + #endif + #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS + << (!threw ? "b::dtor::post\n" : "") + #endif + ; + return ok.str(); +} + +std::string ok_c(bool threw = false) { + std::ostringstream ok; ok + #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS + << "c::static_inv" << std::endl + << "c::inv" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_OLDS + << "c::dtor::old" << std::endl + #endif + << "c::dtor::body" << std::endl + #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS + << "c::static_inv" << std::endl + << (threw ? "c::inv\n" : "") + #endif + #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS + << (!threw ? "c::dtor::post\n" : "") + #endif + ; + return ok.str(); +} + +struct err {}; // Global decl so visible in MSVC10 lambdas. + +int main() { + std::ostringstream ok; + + #ifdef BOOST_CONTRACT_NO_ENTRY_INVARIANTS + #define BOOST_CONTRACT_TEST_entry_inv 0 + #else + #define BOOST_CONTRACT_TEST_entry_inv 1 + #endif + + a_entry_static_inv = true; + b_entry_static_inv = true; + c_entry_static_inv = true; + a_entering_static_inv = b_entering_static_inv = c_entering_static_inv = + BOOST_PP_IIF(BOOST_CONTRACT_TEST_entry_inv, true, false); + { + a aa; + out.str(""); + } + ok.str(""); ok // Test nothing failed. + << ok_a() + << ok_b() + << ok_c() + ; + BOOST_TEST(out.eq(ok.str())); + + boost::contract::set_entry_invariant_failure([&ok] (boost::contract::from) { + BOOST_TEST(out.eq(ok.str())); // Must check before dtor throws. + throw err(); // For testing only (dtors should never throw otherwise). + }); + + a_entry_static_inv = false; + b_entry_static_inv = true; + c_entry_static_inv = true; + a_entering_static_inv = b_entering_static_inv = c_entering_static_inv = + BOOST_PP_IIF(BOOST_CONTRACT_TEST_entry_inv, true, false); + try { + { + a aa; + ok.str(""); ok + #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS + << "a::static_inv" << std::endl // Test this failed... + #else + << ok_a() + #endif + ; + out.str(""); + } + #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS + BOOST_TEST(false); + } catch(err const&) { + #endif + ok // ...then exec other dtors and check inv on throw (as dtor threw). + << ok_b(BOOST_CONTRACT_TEST_entry_inv) + << ok_c(BOOST_CONTRACT_TEST_entry_inv) + ; + BOOST_TEST(out.eq(ok.str())); + } catch(...) { BOOST_TEST(false); } + + a_entry_static_inv = true; + b_entry_static_inv = false; + c_entry_static_inv = true; + a_entering_static_inv = b_entering_static_inv = c_entering_static_inv = + BOOST_PP_IIF(BOOST_CONTRACT_TEST_entry_inv, true, false); + try { + { + a aa; + ok.str(""); ok + << ok_a() + #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS + << "b::static_inv" << std::endl // Test this failed... + #else + << ok_b() + #endif + ; + out.str(""); + } + #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS + BOOST_TEST(false); + } catch(err const&) { + #endif + ok // ...then exec other dtors and check inv on throw (as dtor threw). + << ok_c(BOOST_CONTRACT_TEST_entry_inv) + ; + BOOST_TEST(out.eq(ok.str())); + } catch(...) { BOOST_TEST(false); } + + a_entry_static_inv = true; + b_entry_static_inv = true; + c_entry_static_inv = false; + a_entering_static_inv = b_entering_static_inv = c_entering_static_inv = + BOOST_PP_IIF(BOOST_CONTRACT_TEST_entry_inv, true, false); + try { + { + a aa; + ok.str(""); ok + << ok_a() + << ok_b() + #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS + << "c::static_inv" << std::endl // Test this failed... + #else + << ok_c() + #endif + ; + out.str(""); + } + #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS + BOOST_TEST(false); + } catch(err const&) { + #endif + // ...then exec other dtors and check inv on throw (as dtor threw). + BOOST_TEST(out.eq(ok.str())); + } catch(...) { BOOST_TEST(false); } + + boost::contract::set_entry_invariant_failure([] (boost::contract::from) { + // Testing multiple failures so dtors must not throw multiple + // exceptions, just ignore failure and continue test program... + }); + + a_entry_static_inv = false; + b_entry_static_inv = false; + c_entry_static_inv = false; + a_entering_static_inv = b_entering_static_inv = c_entering_static_inv = + BOOST_PP_IIF(BOOST_CONTRACT_TEST_entry_inv, true, false); + { + a aa; + out.str(""); + } + ok.str(""); ok + #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS + << "a::static_inv" << std::endl // Test this failed (as all did)... + << "a::dtor::body" << std::endl + + << "b::static_inv" << std::endl // Test this failed (as all did)... + << "b::dtor::body" << std::endl + + << "c::static_inv" << std::endl // Test this failed (as all did)... + << "c::dtor::body" << std::endl + #else + << ok_a() + << ok_b() + << ok_c() + #endif + ; + BOOST_TEST(out.eq(ok.str())); + + #undef BOOST_CONTRACT_TEST_entry_inv + return boost::report_errors(); +} + diff --git a/src/boost/libs/contract/test/destructor/decl_entry_static_inv_ends.cpp b/src/boost/libs/contract/test/destructor/decl_entry_static_inv_ends.cpp new file mode 100644 index 000000000..11bb1ced5 --- /dev/null +++ b/src/boost/libs/contract/test/destructor/decl_entry_static_inv_ends.cpp @@ -0,0 +1,216 @@ + +// Copyright (C) 2008-2018 Lorenzo Caminiti +// Distributed under the Boost Software License, Version 1.0 (see accompanying +// file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt). +// See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html + +// Test only derived and grandparent classes (ends) with entry static inv. + +#undef BOOST_CONTRACT_TEST_NO_A_STATIC_INV +#define BOOST_CONTRACT_TEST_NO_B_STATIC_INV +#undef BOOST_CONTRACT_TEST_NO_C_STATIC_INV +#include "decl.hpp" + +#include <boost/preprocessor/control/iif.hpp> +#include <boost/detail/lightweight_test.hpp> +#include <sstream> +#include <string> + +std::string ok_a() { + std::ostringstream ok; ok + #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS + << "a::static_inv" << std::endl + << "a::inv" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_OLDS + << "a::dtor::old" << std::endl + #endif + << "a::dtor::body" << std::endl + #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS + << "a::static_inv" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS + << "a::dtor::post" << std::endl + #endif + ; + return ok.str(); +} + +std::string ok_b(bool threw = false) { + std::ostringstream ok; ok + #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS + << "b::inv" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_OLDS + << "b::dtor::old" << std::endl + #endif + << "b::dtor::body" << std::endl + #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS + << (threw ? "b::inv\n" : "") + #endif + #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS + << (!threw ? "b::dtor::post\n" : "") + #endif + ; + return ok.str(); +} + +std::string ok_c(bool threw = false) { + std::ostringstream ok; ok + #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS + << "c::static_inv" << std::endl + << "c::inv" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_OLDS + << "c::dtor::old" << std::endl + #endif + << "c::dtor::body" << std::endl + #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS + << "c::static_inv" << std::endl + << (threw ? "c::inv\n" : "") + #endif + #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS + << (!threw ? "c::dtor::post\n" : "") + #endif + ; + return ok.str(); +} + +struct err {}; // Global decl so visible in MSVC10 lambdas. + +int main() { + std::ostringstream ok; + + #ifdef BOOST_CONTRACT_NO_ENTRY_INVARIANTS + #define BOOST_CONTRACT_TEST_entry_inv 0 + #else + #define BOOST_CONTRACT_TEST_entry_inv 1 + #endif + + a_entry_static_inv = true; + b_entry_static_inv = true; + c_entry_static_inv = true; + a_entering_static_inv = b_entering_static_inv = c_entering_static_inv = + BOOST_PP_IIF(BOOST_CONTRACT_TEST_entry_inv, true, false); + { + a aa; + out.str(""); + } + ok.str(""); ok // Test nothing failed. + << ok_a() + << ok_b() + << ok_c() + ; + BOOST_TEST(out.eq(ok.str())); + + boost::contract::set_entry_invariant_failure([&ok] (boost::contract::from) { + BOOST_TEST(out.eq(ok.str())); // Must check before dtor throws. + throw err(); // For testing only (dtors should never throw otherwise). + }); + + a_entry_static_inv = false; + b_entry_static_inv = true; + c_entry_static_inv = true; + a_entering_static_inv = b_entering_static_inv = c_entering_static_inv = + BOOST_PP_IIF(BOOST_CONTRACT_TEST_entry_inv, true, false); + try { + { + a aa; + ok.str(""); ok + #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS + << "a::static_inv" << std::endl // Test this failed... + #else + << ok_a() + #endif + ; + out.str(""); + } + #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS + BOOST_TEST(false); + } catch(err const&) { + #endif + ok // ...then exec other dtors and check inv on throw (as dtor threw). + << ok_b(BOOST_CONTRACT_TEST_entry_inv) + << ok_c(BOOST_CONTRACT_TEST_entry_inv) + ; + BOOST_TEST(out.eq(ok.str())); + } catch(...) { BOOST_TEST(false); } + + a_entry_static_inv = true; + b_entry_static_inv = false; + c_entry_static_inv = true; + a_entering_static_inv = b_entering_static_inv = c_entering_static_inv = + BOOST_PP_IIF(BOOST_CONTRACT_TEST_entry_inv, true, false); + { + a aa; + out.str(""); + } + ok.str(""); ok + << ok_a() + << ok_b() // Test no b::static_inv so no failure here. + << ok_c() + ; + BOOST_TEST(out.eq(ok.str())); + + a_entry_static_inv = true; + b_entry_static_inv = true; + c_entry_static_inv = false; + a_entering_static_inv = b_entering_static_inv = c_entering_static_inv = + BOOST_PP_IIF(BOOST_CONTRACT_TEST_entry_inv, true, false); + try { + { + a aa; + ok.str(""); ok + << ok_a() + << ok_b() + #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS + << "c::static_inv" << std::endl // Test this failed... + #else + << ok_c() + #endif + ; + out.str(""); + } + #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS + BOOST_TEST(false); + } catch(err const&) { + #endif + // ...then exec other dtors and check inv on throw (as dtor threw). + BOOST_TEST(out.eq(ok.str())); + } catch(...) { BOOST_TEST(false); } + + boost::contract::set_entry_invariant_failure([] (boost::contract::from) { + // Testing multiple failures so dtors must not throw multiple + // exceptions, just ignore failure and continue test program. + }); + + a_entry_static_inv = false; + b_entry_static_inv = false; + c_entry_static_inv = false; + a_entering_static_inv = b_entering_static_inv = c_entering_static_inv = + BOOST_PP_IIF(BOOST_CONTRACT_TEST_entry_inv, true, false); + { + a aa; + out.str(""); + } + ok.str(""); ok + #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS + << "a::static_inv" << std::endl // Test this failed (as all did). + << "a::dtor::body" << std::endl + + << ok_b() // Test no b::static_inv so no failure here. + + << "c::static_inv" << std::endl // Test this failed (as all did). + << "c::dtor::body" << std::endl + #else + << ok_a() + << ok_b() + << ok_c() + #endif + ; + BOOST_TEST(out.eq(ok.str())); + + #undef BOOST_CONTRACT_TEST_entry_inv + return boost::report_errors(); +} + diff --git a/src/boost/libs/contract/test/destructor/decl_entry_static_inv_mid.cpp b/src/boost/libs/contract/test/destructor/decl_entry_static_inv_mid.cpp new file mode 100644 index 000000000..6f8132123 --- /dev/null +++ b/src/boost/libs/contract/test/destructor/decl_entry_static_inv_mid.cpp @@ -0,0 +1,203 @@ + +// Copyright (C) 2008-2018 Lorenzo Caminiti +// Distributed under the Boost Software License, Version 1.0 (see accompanying +// file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt). +// See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html + +// Test only middle base class with entry static invariants. + +#define BOOST_CONTRACT_TEST_NO_A_STATIC_INV +#undef BOOST_CONTRACT_TEST_NO_B_STATIC_INV +#define BOOST_CONTRACT_TEST_NO_C_STATIC_INV +#include "decl.hpp" + +#include <boost/preprocessor/control/iif.hpp> +#include <boost/detail/lightweight_test.hpp> +#include <sstream> +#include <string> + +std::string ok_a() { + std::ostringstream ok; ok + #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS + << "a::inv" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_OLDS + << "a::dtor::old" << std::endl + #endif + << "a::dtor::body" << std::endl + #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS + << "a::dtor::post" << std::endl + #endif + ; + return ok.str(); +} + +std::string ok_b() { + std::ostringstream ok; ok + #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS + << "b::static_inv" << std::endl + << "b::inv" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_OLDS + << "b::dtor::old" << std::endl + #endif + << "b::dtor::body" << std::endl + #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS + << "b::static_inv" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS + << "b::dtor::post" << std::endl + #endif + ; + return ok.str(); +} + +std::string ok_c(bool threw = false) { + std::ostringstream ok; ok + #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS + << "c::inv" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_OLDS + << "c::dtor::old" << std::endl + #endif + << "c::dtor::body" << std::endl + #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS + << (threw ? "c::inv\n" : "") + #endif + #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS + << (!threw ? "c::dtor::post\n" : "") + #endif + ; + return ok.str(); +} + +struct err {}; // Global decl so visible in MSVC10 lambdas. + +int main() { + std::ostringstream ok; + + #ifdef BOOST_CONTRACT_NO_ENTRY_INVARIANTS + #define BOOST_CONTRACT_TEST_entry_inv 0 + #else + #define BOOST_CONTRACT_TEST_entry_inv 1 + #endif + + a_entry_static_inv = true; + b_entry_static_inv = true; + c_entry_static_inv = true; + a_entering_static_inv = b_entering_static_inv = c_entering_static_inv = + BOOST_PP_IIF(BOOST_CONTRACT_TEST_entry_inv, true, false); + { + a aa; + out.str(""); + } + ok.str(""); ok // Test nothing failed. + << ok_a() + << ok_b() + << ok_c() + ; + BOOST_TEST(out.eq(ok.str())); + + boost::contract::set_entry_invariant_failure([&ok] (boost::contract::from) { + BOOST_TEST(out.eq(ok.str())); // Must check before dtor throws. + throw err(); // For testing only (dtors should never throw otherwise). + }); + + a_entry_static_inv = false; + b_entry_static_inv = true; + c_entry_static_inv = true; + a_entering_static_inv = b_entering_static_inv = c_entering_static_inv = + BOOST_PP_IIF(BOOST_CONTRACT_TEST_entry_inv, true, false); + try { + { + a aa; + out.str(""); + } + ok.str(""); ok + << ok_a() // Test no a::static_inv so no failure here. + << ok_b() + << ok_c() + ; + BOOST_TEST(out.eq(ok.str())); + } catch(...) { BOOST_TEST(false); } + + a_entry_static_inv = true; + b_entry_static_inv = false; + c_entry_static_inv = true; + a_entering_static_inv = b_entering_static_inv = c_entering_static_inv = + BOOST_PP_IIF(BOOST_CONTRACT_TEST_entry_inv, true, false); + try { + { + a aa; + ok.str(""); ok + << ok_a() + #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS + << "b::static_inv" << std::endl // Test this failed... + #else + << ok_b() + #endif + ; + out.str(""); + } + #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS + BOOST_TEST(false); + } catch(err const&) { + #endif + ok // ...then exec other dtors and check inv on throw (as dtor threw). + << ok_c(BOOST_CONTRACT_TEST_entry_inv) + ; + BOOST_TEST(out.eq(ok.str())); + } catch(...) { BOOST_TEST(false); } + + a_entry_static_inv = true; + b_entry_static_inv = true; + c_entry_static_inv = false; + a_entering_static_inv = b_entering_static_inv = c_entering_static_inv = + BOOST_PP_IIF(BOOST_CONTRACT_TEST_entry_inv, true, false); + try { + { + a aa; + out.str(""); + } + ok.str(""); ok + << ok_a() + << ok_b() + << ok_c() // Test no c::static_inv so no failure here. + ; + BOOST_TEST(out.eq(ok.str())); + } catch(...) { BOOST_TEST(false); } + + boost::contract::set_entry_invariant_failure([] (boost::contract::from) { + // Testing multiple failures so dtors must not throw multiple + // exceptions, just ignore failure and continue test program... + }); + + a_entry_static_inv = false; + b_entry_static_inv = false; + c_entry_static_inv = false; + a_entering_static_inv = b_entering_static_inv = c_entering_static_inv = + BOOST_PP_IIF(BOOST_CONTRACT_TEST_entry_inv, true, false); + { + a aa; + out.str(""); + } + ok.str(""); ok + #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS + << ok_a() // Test no a::static_inv so no failure here. + + << "b::static_inv" << std::endl // Test this failed (as all did)... + << "b::dtor::body" << std::endl + + << ok_c() // Test no c::static_inv so no failure here. + #else + << ok_a() + << ok_b() + << ok_c() + #endif + ; + BOOST_TEST(out.eq(ok.str())); + + #undef BOOST_CONTRACT_TEST_entry_inv + return boost::report_errors(); +} + diff --git a/src/boost/libs/contract/test/destructor/decl_entry_static_inv_none.cpp b/src/boost/libs/contract/test/destructor/decl_entry_static_inv_none.cpp new file mode 100644 index 000000000..acc7b6822 --- /dev/null +++ b/src/boost/libs/contract/test/destructor/decl_entry_static_inv_none.cpp @@ -0,0 +1,118 @@ + +// Copyright (C) 2008-2018 Lorenzo Caminiti +// Distributed under the Boost Software License, Version 1.0 (see accompanying +// file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt). +// See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html + +// Test all derived and base classes without entry static invariants. + +#define BOOST_CONTRACT_TEST_NO_A_STATIC_INV +#define BOOST_CONTRACT_TEST_NO_B_STATIC_INV +#define BOOST_CONTRACT_TEST_NO_C_STATIC_INV +#include "decl.hpp" + +#include <boost/preprocessor/control/iif.hpp> +#include <boost/detail/lightweight_test.hpp> +#include <sstream> + +int main() { + std::ostringstream ok; ok // Test nothing fails. + #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS + << "a::inv" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_OLDS + << "a::dtor::old" << std::endl + #endif + << "a::dtor::body" << std::endl + #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS + << "a::dtor::post" << std::endl + #endif + + #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS + << "b::inv" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_OLDS + << "b::dtor::old" << std::endl + #endif + << "b::dtor::body" << std::endl + #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS + << "b::dtor::post" << std::endl + #endif + + #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS + << "c::inv" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_OLDS + << "c::dtor::old" << std::endl + #endif + << "c::dtor::body" << std::endl + #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS + << "c::dtor::post" << std::endl + #endif + ; + + #ifdef BOOST_CONTRACT_NO_ENTRY_INVARIANTS + #define BOOST_CONTRACT_TEST_entry_inv 0 + #else + #define BOOST_CONTRACT_TEST_entry_inv 1 + #endif + + a_entry_static_inv = true; + b_entry_static_inv = true; + c_entry_static_inv = true; + a_entering_static_inv = b_entering_static_inv = c_entering_static_inv = + BOOST_PP_IIF(BOOST_CONTRACT_TEST_entry_inv, true, false); + { + a aa; + out.str(""); + } + BOOST_TEST(out.eq(ok.str())); + + a_entry_static_inv = false; + b_entry_static_inv = true; + c_entry_static_inv = true; + a_entering_static_inv = b_entering_static_inv = c_entering_static_inv = + BOOST_PP_IIF(BOOST_CONTRACT_TEST_entry_inv, true, false); + { + a aa; + out.str(""); + } + BOOST_TEST(out.eq(ok.str())); + + a_entry_static_inv = true; + b_entry_static_inv = false; + c_entry_static_inv = true; + a_entering_static_inv = b_entering_static_inv = c_entering_static_inv = + BOOST_PP_IIF(BOOST_CONTRACT_TEST_entry_inv, true, false); + { + a aa; + out.str(""); + } + BOOST_TEST(out.eq(ok.str())); + + a_entry_static_inv = true; + b_entry_static_inv = true; + c_entry_static_inv = false; + a_entering_static_inv = b_entering_static_inv = c_entering_static_inv = + BOOST_PP_IIF(BOOST_CONTRACT_TEST_entry_inv, true, false); + { + a aa; + out.str(""); + } + BOOST_TEST(out.eq(ok.str())); + + a_entry_static_inv = false; + b_entry_static_inv = false; + c_entry_static_inv = false; + a_entering_static_inv = b_entering_static_inv = c_entering_static_inv = + BOOST_PP_IIF(BOOST_CONTRACT_TEST_entry_inv, true, false); + { + a aa; + out.str(""); + } + BOOST_TEST(out.eq(ok.str())); + + #undef BOOST_CONTRACT_TEST_entry_inv + return boost::report_errors(); +} + diff --git a/src/boost/libs/contract/test/destructor/decl_exit_static_inv_all.cpp b/src/boost/libs/contract/test/destructor/decl_exit_static_inv_all.cpp new file mode 100644 index 000000000..4cb68fea3 --- /dev/null +++ b/src/boost/libs/contract/test/destructor/decl_exit_static_inv_all.cpp @@ -0,0 +1,222 @@ + +// Copyright (C) 2008-2018 Lorenzo Caminiti +// Distributed under the Boost Software License, Version 1.0 (see accompanying +// file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt). +// See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html + +// Test all derived and base classes with exit static invariants. + +#undef BOOST_CONTRACT_TEST_NO_A_STATIC_INV +#undef BOOST_CONTRACT_TEST_NO_B_STATIC_INV +#undef BOOST_CONTRACT_TEST_NO_C_STATIC_INV +#include "decl.hpp" + +#include <boost/preprocessor/control/iif.hpp> +#include <boost/detail/lightweight_test.hpp> +#include <sstream> +#include <string> + +std::string ok_a(bool failed = false) { + std::ostringstream ok; ok + #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS + << "a::static_inv" << std::endl + << "a::inv" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_OLDS + << "a::dtor::old" << std::endl + #endif + << "a::dtor::body" << std::endl + #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS + << "a::static_inv" << std::endl // This can fail. + #endif + #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS + << (!failed ? "a::dtor::post\n" : "") + #endif + ; + return ok.str(); +} + +enum checked { passed, failed, threw }; + +std::string ok_b(checked check = passed) { + std::ostringstream ok; ok + #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS + << "b::static_inv" << std::endl + << "b::inv" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_OLDS + << "b::dtor::old" << std::endl + #endif + << "b::dtor::body" << std::endl + #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS + << "b::static_inv" << std::endl // This can fail. + << (check == threw ? "b::inv\n" : "") + #endif + #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS + << (check == passed ? "b::dtor::post\n" : "") + #endif + ; + return ok.str(); +} + +std::string ok_c(checked check = passed) { + std::ostringstream ok; ok + #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS + << "c::static_inv" << std::endl + << "c::inv" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_OLDS + << "c::dtor::old" << std::endl + #endif + << "c::dtor::body" << std::endl + #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS + << "c::static_inv" << std::endl // This can fail. + << (check == threw ? "c::inv\n" : "") + #endif + #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS + << (check == passed ? "c::dtor::post\n" : "") + #endif + ; + return ok.str(); +} + +struct err {}; // Global decl so visible in MSVC10 lambdas. + +int main() { + std::ostringstream ok; + + #ifdef BOOST_CONTRACT_NO_ENTRY_INVARIANTS + #define BOOST_CONTRACT_TEST_entry_inv 0 + #else + #define BOOST_CONTRACT_TEST_entry_inv 1 + #endif + #ifdef BOOST_CONTRACT_NO_EXIT_INVARIANTS + #define BOOST_CONTRACT_TEST_exit_inv 0 + #else + #define BOOST_CONTRACT_TEST_exit_inv 1 + #endif + + a_exit_static_inv = true; + b_exit_static_inv = true; + c_exit_static_inv = true; + a_entering_static_inv = b_entering_static_inv = c_entering_static_inv = + BOOST_PP_IIF(BOOST_CONTRACT_TEST_entry_inv, true, false); + { + a aa; + out.str(""); + } + ok.str(""); ok // Test nothing failed. + << ok_a() + << ok_b() + << ok_c() + ; + BOOST_TEST(out.eq(ok.str())); + + boost::contract::set_exit_invariant_failure([&ok] (boost::contract::from) { + BOOST_TEST(out.eq(ok.str())); // Must check before dtor throws. + throw err(); // For testing only (as dtors should not throw otherwise). + }); + + a_exit_static_inv = false; + b_exit_static_inv = true; + c_exit_static_inv = true; + a_entering_static_inv = b_entering_static_inv = c_entering_static_inv = + BOOST_PP_IIF(BOOST_CONTRACT_TEST_entry_inv, true, false); + try { + { + a aa; + ok.str(""); ok + // Test a::static_inv failed... + << ok_a(BOOST_CONTRACT_TEST_exit_inv) + ; + out.str(""); + } + #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS + BOOST_TEST(false); + } catch(err const&) { + #endif + ok // ...then exec other dtors and check inv on throw (as dtor threw). + << ok_b(BOOST_CONTRACT_TEST_exit_inv ? threw : passed) + << ok_c(BOOST_CONTRACT_TEST_exit_inv ? threw : passed) + ; + BOOST_TEST(out.eq(ok.str())); + } catch(...) { BOOST_TEST(false); } + + a_exit_static_inv = true; + b_exit_static_inv = false; + c_exit_static_inv = true; + a_entering_static_inv = b_entering_static_inv = c_entering_static_inv = + BOOST_PP_IIF(BOOST_CONTRACT_TEST_entry_inv, true, false); + try { + { + a aa; + ok.str(""); ok + << ok_a() + // Test b::static_inv failed... + << ok_b(BOOST_CONTRACT_TEST_exit_inv ? failed : passed) + ; + out.str(""); + } + #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS + BOOST_TEST(false); + } catch(err const&) { + #endif + ok // ...then exec other dtors and check inv on throw (as dtor threw). + << ok_c(BOOST_CONTRACT_TEST_exit_inv ? threw : passed) + ; + BOOST_TEST(out.eq(ok.str())); + } catch(...) { BOOST_TEST(false); } + + a_exit_static_inv = true; + b_exit_static_inv = true; + c_exit_static_inv = false; + a_entering_static_inv = b_entering_static_inv = c_entering_static_inv = + BOOST_PP_IIF(BOOST_CONTRACT_TEST_entry_inv, true, false); + try { + { + a aa; + ok.str(""); ok + << ok_a() + << ok_b() + // Test exit c::static_inv failed. + << ok_c(BOOST_CONTRACT_TEST_exit_inv ? failed : passed) + ; + out.str(""); + } + #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS + BOOST_TEST(false); + } catch(err const&) { + #endif + // ... then exec other dtors and check inv on throw (as dtor threw). + BOOST_TEST(out.eq(ok.str())); + } catch(...) { BOOST_TEST(false); } + + boost::contract::set_exit_invariant_failure([] (boost::contract::from) { + // Testing multiple failures but dtors must not throw multiple except, + // just ignore failure and continue test program (for testing only). + }); + + a_exit_static_inv = false; + b_exit_static_inv = false; + c_exit_static_inv = false; + a_entering_static_inv = b_entering_static_inv = c_entering_static_inv = + BOOST_PP_IIF(BOOST_CONTRACT_TEST_entry_inv, true, false); + { + a aa; + out.str(""); + } + ok.str(""); ok + // Test exit a::static_inv failed (as all did). + << ok_a(BOOST_CONTRACT_TEST_exit_inv) + // Test exit b::static_inv failed (as all did). + << ok_b(BOOST_CONTRACT_TEST_exit_inv ? failed : passed) + // Test exit c::static_inv failed (as all did). + << ok_c(BOOST_CONTRACT_TEST_exit_inv ? failed : passed) + ; + BOOST_TEST(out.eq(ok.str())); + + #undef BOOST_CONTRACT_TEST_entry_inv + #undef BOOST_CONTRACT_TEST_exit_inv + return boost::report_errors(); +} + diff --git a/src/boost/libs/contract/test/destructor/decl_exit_static_inv_ends.cpp b/src/boost/libs/contract/test/destructor/decl_exit_static_inv_ends.cpp new file mode 100644 index 000000000..cbce75141 --- /dev/null +++ b/src/boost/libs/contract/test/destructor/decl_exit_static_inv_ends.cpp @@ -0,0 +1,211 @@ + +// Copyright (C) 2008-2018 Lorenzo Caminiti +// Distributed under the Boost Software License, Version 1.0 (see accompanying +// file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt). +// See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html + +// Test only derived and grandparent classes (ends) with exit static invariants. + +#undef BOOST_CONTRACT_TEST_NO_A_STATIC_INV +#define BOOST_CONTRACT_TEST_NO_B_STATIC_INV +#undef BOOST_CONTRACT_TEST_NO_C_STATIC_INV +#include "decl.hpp" + +#include <boost/preprocessor/control/iif.hpp> +#include <boost/detail/lightweight_test.hpp> +#include <sstream> +#include <string> + +std::string ok_a(bool failed = false) { + std::ostringstream ok; ok + #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS + << "a::static_inv" << std::endl + << "a::inv" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_OLDS + << "a::dtor::old" << std::endl + #endif + << "a::dtor::body" << std::endl + #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS + << "a::static_inv" << std::endl // This can fail. + #endif + #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS + << (!failed ? "a::dtor::post\n" : "") + #endif + ; + return ok.str(); +} + +std::string ok_b(bool threw = false) { + std::ostringstream ok; ok + #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS + << "b::inv" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_OLDS + << "b::dtor::old" << std::endl + #endif + << "b::dtor::body" << std::endl + #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS + << (threw ? "b::inv\n" : "") + #endif + #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS + << (!threw ? "b::dtor::post\n" : "") + #endif + ; + return ok.str(); +} + +enum checked { passed, failed, threw }; + +std::string ok_c(checked check = passed) { + std::ostringstream ok; ok + #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS + << "c::static_inv" << std::endl + << "c::inv" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_OLDS + << "c::dtor::old" << std::endl + #endif + << "c::dtor::body" << std::endl + #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS + << "c::static_inv" << std::endl // This can fail. + << (check == threw ? "c::inv\n" : "") + #endif + #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS + << (check == passed ? "c::dtor::post\n" : "") + #endif + ; + return ok.str(); +} + +struct err {}; // Global decl so visible in MSVC10 lambdas. + +int main() { + std::ostringstream ok; + + #ifdef BOOST_CONTRACT_NO_ENTRY_INVARIANTS + #define BOOST_CONTRACT_TEST_entry_inv 0 + #else + #define BOOST_CONTRACT_TEST_entry_inv 1 + #endif + #ifdef BOOST_CONTRACT_NO_EXIT_INVARIANTS + #define BOOST_CONTRACT_TEST_exit_inv 0 + #else + #define BOOST_CONTRACT_TEST_exit_inv 1 + #endif + + a_exit_static_inv = true; + b_exit_static_inv = true; + c_exit_static_inv = true; + a_entering_static_inv = b_entering_static_inv = c_entering_static_inv = + BOOST_PP_IIF(BOOST_CONTRACT_TEST_entry_inv, true, false); + { + a aa; + out.str(""); + } + ok.str(""); ok // Test nothing failed. + << ok_a() + << ok_b() + << ok_c() + ; + BOOST_TEST(out.eq(ok.str())); + + boost::contract::set_exit_invariant_failure([&ok] (boost::contract::from) { + BOOST_TEST(out.eq(ok.str())); // Must check before dtor throws. + throw err(); // For testing only (as dtors should not throw otherwise). + }); + + a_exit_static_inv = false; + b_exit_static_inv = true; + c_exit_static_inv = true; + a_entering_static_inv = b_entering_static_inv = c_entering_static_inv = + BOOST_PP_IIF(BOOST_CONTRACT_TEST_entry_inv, true, false); + try { + { + a aa; + ok.str(""); ok + // Test a::static_inv failed... + << ok_a(BOOST_CONTRACT_TEST_exit_inv) + ; + out.str(""); + } + #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS + BOOST_TEST(false); + } catch(err const&) { + #endif + ok // ...then exec other dtors and check inv on throw (as dtor threw). + << ok_b(BOOST_CONTRACT_TEST_exit_inv) + << ok_c(BOOST_CONTRACT_TEST_exit_inv ? threw : passed) + ; + BOOST_TEST(out.eq(ok.str())); + } catch(...) { BOOST_TEST(false); } + + a_exit_static_inv = true; + b_exit_static_inv = false; + c_exit_static_inv = true; + a_entering_static_inv = b_entering_static_inv = c_entering_static_inv = + BOOST_PP_IIF(BOOST_CONTRACT_TEST_entry_inv, true, false); + { + a aa; + out.str(""); + } + ok.str(""); ok + << ok_a() + << ok_b() // Test no exit b::static_inv so no failure here. + << ok_c() + ; + BOOST_TEST(out.eq(ok.str())); + + a_exit_static_inv = true; + b_exit_static_inv = true; + c_exit_static_inv = false; + a_entering_static_inv = b_entering_static_inv = c_entering_static_inv = + BOOST_PP_IIF(BOOST_CONTRACT_TEST_entry_inv, true, false); + try { + { + a aa; + ok.str(""); ok + << ok_a() + << ok_b() + // Test c::static_inv failed... + << ok_c(BOOST_CONTRACT_TEST_exit_inv ? failed : passed) + ; + out.str(""); + } + #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS + BOOST_TEST(false); + } catch(err const&) { + #endif + // ...then exec other dtors and check inv on throw (as dtor threw). + BOOST_TEST(out.eq(ok.str())); + } catch(...) { BOOST_TEST(false); } + + boost::contract::set_exit_invariant_failure([] (boost::contract::from) { + // Testing multiple failures so dtors must not throw multiple + // exceptions, just ignore failure and continue test program... + }); + + a_exit_static_inv = false; + b_exit_static_inv = false; + c_exit_static_inv = false; + a_entering_static_inv = b_entering_static_inv = c_entering_static_inv = + BOOST_PP_IIF(BOOST_CONTRACT_TEST_entry_inv, true, false); + { + a aa; + out.str(""); + } + ok.str(""); ok + // Test a::static_inv failed (as all did). + << ok_a(BOOST_CONTRACT_TEST_exit_inv) + // Test no exit b::static_inv so no failure here. + << ok_b() + // Test c::static_inv failed (as all did). + << ok_c(BOOST_CONTRACT_TEST_exit_inv ? failed : passed) + ; + BOOST_TEST(out.eq(ok.str())); + + #undef BOOST_CONTRACT_TEST_entry_inv + #undef BOOST_CONTRACT_TEST_exit_inv + return boost::report_errors(); +} + diff --git a/src/boost/libs/contract/test/destructor/decl_exit_static_inv_mid.cpp b/src/boost/libs/contract/test/destructor/decl_exit_static_inv_mid.cpp new file mode 100644 index 000000000..bd5cce643 --- /dev/null +++ b/src/boost/libs/contract/test/destructor/decl_exit_static_inv_mid.cpp @@ -0,0 +1,203 @@ + +// Copyright (C) 2008-2018 Lorenzo Caminiti +// Distributed under the Boost Software License, Version 1.0 (see accompanying +// file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt). +// See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html + +// Test only middle base class with exit static invariants. + +#define BOOST_CONTRACT_TEST_NO_A_STATIC_INV +#undef BOOST_CONTRACT_TEST_NO_B_STATIC_INV +#define BOOST_CONTRACT_TEST_NO_C_STATIC_INV +#include "decl.hpp" + +#include <boost/preprocessor/control/iif.hpp> +#include <boost/detail/lightweight_test.hpp> +#include <sstream> +#include <string> + +std::string ok_a() { + std::ostringstream ok; ok + #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS + << "a::inv" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_OLDS + << "a::dtor::old" << std::endl + #endif + << "a::dtor::body" << std::endl + #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS + << "a::dtor::post" << std::endl + #endif + ; + return ok.str(); +} + +std::string ok_b(bool failed = false) { + std::ostringstream ok; ok + #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS + << "b::static_inv" << std::endl + << "b::inv" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_OLDS + << "b::dtor::old" << std::endl + #endif + << "b::dtor::body" << std::endl + #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS + << "b::static_inv" << std::endl // This can fail. + #endif + #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS + << (!failed ? "b::dtor::post\n" : "") + #endif + ; + return ok.str(); +} + +std::string ok_c(bool threw = false) { + std::ostringstream ok; ok + #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS + << "c::inv" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_OLDS + << "c::dtor::old" << std::endl + #endif + << "c::dtor::body" << std::endl + #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS + << (threw ? "c::inv\n" : "") + #endif + #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS + << (!threw ? "c::dtor::post\n" : "") + #endif + ; + return ok.str(); +} + +struct err {}; // Global decl so visible in MSVC10 lambdas. + +int main() { + std::ostringstream ok; + + #ifdef BOOST_CONTRACT_NO_ENTRY_INVARIANTS + #define BOOST_CONTRACT_TEST_entry_inv 0 + #else + #define BOOST_CONTRACT_TEST_entry_inv 1 + #endif + #ifdef BOOST_CONTRACT_NO_EXIT_INVARIANTS + #define BOOST_CONTRACT_TEST_exit_inv 0 + #else + #define BOOST_CONTRACT_TEST_exit_inv 1 + #endif + + a_exit_static_inv = true; + b_exit_static_inv = true; + c_exit_static_inv = true; + a_entering_static_inv = b_entering_static_inv = c_entering_static_inv = + BOOST_PP_IIF(BOOST_CONTRACT_TEST_entry_inv, true, false); + { + a aa; + out.str(""); + } + ok.str(""); ok // Test nothing failed. + << ok_a() + << ok_b() + << ok_c() + ; + BOOST_TEST(out.eq(ok.str())); + + boost::contract::set_exit_invariant_failure([&ok] (boost::contract::from) { + BOOST_TEST(out.eq(ok.str())); // Must check before dtor throws. + throw err(); // For testing only (as dtors should not throw otherwise). + }); + + a_exit_static_inv = false; + b_exit_static_inv = true; + c_exit_static_inv = true; + a_entering_static_inv = b_entering_static_inv = c_entering_static_inv = + BOOST_PP_IIF(BOOST_CONTRACT_TEST_entry_inv, true, false); + try { + { + a aa; + ok.str(""); + out.str(""); + } + ok.str(""); ok + << ok_a() // Test no exit a::static_inv so no failure here. + << ok_b() + << ok_c() + ; + BOOST_TEST(out.eq(ok.str())); + } catch(...) { BOOST_TEST(false); } + + a_exit_static_inv = true; + b_exit_static_inv = false; + c_exit_static_inv = true; + a_entering_static_inv = b_entering_static_inv = c_entering_static_inv = + BOOST_PP_IIF(BOOST_CONTRACT_TEST_entry_inv, true, false); + try { + { + a aa; + ok.str(""); ok + << ok_a() + // Test exit b::static_inv failed... + << ok_b(BOOST_CONTRACT_TEST_exit_inv) + ; + out.str(""); + } + #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS + BOOST_TEST(false); + } catch(err const&) { + #endif + ok // ...then exec other dtors and check inv on throw (as dtor threw). + << ok_c(BOOST_CONTRACT_TEST_exit_inv) + ; + BOOST_TEST(out.eq(ok.str())); + } catch(...) { BOOST_TEST(false); } + + a_exit_static_inv = true; + b_exit_static_inv = true; + c_exit_static_inv = false; + a_entering_static_inv = b_entering_static_inv = c_entering_static_inv = + BOOST_PP_IIF(BOOST_CONTRACT_TEST_entry_inv, true, false); + try { + { + a aa; + ok.str(""); + out.str(""); + } + ok.str(""); ok + << ok_a() + << ok_b() + // Test no exit c::static_inv so no failure here. + << ok_c() + ; + BOOST_TEST(out.eq(ok.str())); + } catch(...) { BOOST_TEST(false); } + + boost::contract::set_exit_invariant_failure([] (boost::contract::from) { + // Testing multiple failures so dtors must not throw multiple except, + // just ignore failure and continue test program (for testing only). + }); + + a_exit_static_inv = false; + b_exit_static_inv = false; + c_exit_static_inv = false; + a_entering_static_inv = b_entering_static_inv = c_entering_static_inv = + BOOST_PP_IIF(BOOST_CONTRACT_TEST_entry_inv, true, false); + { + a aa; + out.str(""); + } + ok.str(""); ok + // Test no exit a::static_inv so no faliure here. + << ok_a() + // Test exit b::static_inv failed (as all did). + << ok_b(BOOST_CONTRACT_TEST_exit_inv) + // Test no exit c::static_inv so no failure here. + << ok_c() + ; + BOOST_TEST(out.eq(ok.str())); + + #undef BOOST_CONTRACT_TEST_entry_inv + #undef BOOST_CONTRACT_TEST_exit_inv + return boost::report_errors(); +} + diff --git a/src/boost/libs/contract/test/destructor/decl_exit_static_inv_none.cpp b/src/boost/libs/contract/test/destructor/decl_exit_static_inv_none.cpp new file mode 100644 index 000000000..0d572adbc --- /dev/null +++ b/src/boost/libs/contract/test/destructor/decl_exit_static_inv_none.cpp @@ -0,0 +1,118 @@ + +// Copyright (C) 2008-2018 Lorenzo Caminiti +// Distributed under the Boost Software License, Version 1.0 (see accompanying +// file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt). +// See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html + +// Test all derived and base classes without exit static invariants. + +#define BOOST_CONTRACT_TEST_NO_A_STATIC_INV +#define BOOST_CONTRACT_TEST_NO_B_STATIC_INV +#define BOOST_CONTRACT_TEST_NO_C_STATIC_INV +#include "decl.hpp" + +#include <boost/preprocessor/control/iif.hpp> +#include <boost/detail/lightweight_test.hpp> +#include <sstream> + +int main() { + std::ostringstream ok; ok // Test nothing fails. + #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS + << "a::inv" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_OLDS + << "a::dtor::old" << std::endl + #endif + << "a::dtor::body" << std::endl + #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS + << "a::dtor::post" << std::endl + #endif + + #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS + << "b::inv" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_OLDS + << "b::dtor::old" << std::endl + #endif + << "b::dtor::body" << std::endl + #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS + << "b::dtor::post" << std::endl + #endif + + #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS + << "c::inv" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_OLDS + << "c::dtor::old" << std::endl + #endif + << "c::dtor::body" << std::endl + #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS + << "c::dtor::post" << std::endl + #endif + ; + + #ifdef BOOST_CONTRACT_NO_ENTRY_INVARIANTS + #define BOOST_CONTRACT_TEST_entry_inv 0 + #else + #define BOOST_CONTRACT_TEST_entry_inv 1 + #endif + + a_exit_static_inv = true; + b_exit_static_inv = true; + c_exit_static_inv = true; + a_entering_static_inv = b_entering_static_inv = c_entering_static_inv = + BOOST_PP_IIF(BOOST_CONTRACT_TEST_entry_inv, true, false); + { + a aa; + out.str(""); + } + BOOST_TEST(out.eq(ok.str())); + + a_exit_static_inv = false; + b_exit_static_inv = true; + c_exit_static_inv = true; + a_entering_static_inv = b_entering_static_inv = c_entering_static_inv = + BOOST_PP_IIF(BOOST_CONTRACT_TEST_entry_inv, true, false); + { + a aa; + out.str(""); + } + BOOST_TEST(out.eq(ok.str())); + + a_exit_static_inv = true; + b_exit_static_inv = false; + c_exit_static_inv = true; + a_entering_static_inv = b_entering_static_inv = c_entering_static_inv = + BOOST_PP_IIF(BOOST_CONTRACT_TEST_entry_inv, true, false); + { + a aa; + out.str(""); + } + BOOST_TEST(out.eq(ok.str())); + + a_exit_static_inv = true; + b_exit_static_inv = true; + c_exit_static_inv = false; + a_entering_static_inv = b_entering_static_inv = c_entering_static_inv = + BOOST_PP_IIF(BOOST_CONTRACT_TEST_entry_inv, true, false); + { + a aa; + out.str(""); + } + BOOST_TEST(out.eq(ok.str())); + + a_exit_static_inv = false; + b_exit_static_inv = false; + c_exit_static_inv = false; + a_entering_static_inv = b_entering_static_inv = c_entering_static_inv = + BOOST_PP_IIF(BOOST_CONTRACT_TEST_entry_inv, true, false); + { + a aa; + out.str(""); + } + BOOST_TEST(out.eq(ok.str())); + + #undef BOOST_CONTRACT_TEST_entry_inv + return boost::report_errors(); +} + diff --git a/src/boost/libs/contract/test/destructor/decl_post_all.cpp b/src/boost/libs/contract/test/destructor/decl_post_all.cpp new file mode 100644 index 000000000..8617b4788 --- /dev/null +++ b/src/boost/libs/contract/test/destructor/decl_post_all.cpp @@ -0,0 +1,200 @@ + +// Copyright (C) 2008-2018 Lorenzo Caminiti +// Distributed under the Boost Software License, Version 1.0 (see accompanying +// file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt). +// See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html + +// Test all derived and base classes with postconditions. + +#undef BOOST_CONTRACT_TEST_NO_A_POST +#undef BOOST_CONTRACT_TEST_NO_B_POST +#undef BOOST_CONTRACT_TEST_NO_C_POST +#include "decl.hpp" + +#include <boost/detail/lightweight_test.hpp> +#include <sstream> +#include <string> + +std::string ok_a() { + std::ostringstream ok; ok + #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS + << "a::static_inv" << std::endl + << "a::inv" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_OLDS + << "a::dtor::old" << std::endl + #endif + << "a::dtor::body" << std::endl + #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS + << "a::static_inv" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS + << "a::dtor::post" << std::endl // This can fail. + #endif + ; + return ok.str(); +} + +std::string ok_b(bool threw = false) { + std::ostringstream ok; ok + #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS + << "b::static_inv" << std::endl + << "b::inv" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_OLDS + << "b::dtor::old" << std::endl + #endif + << "b::dtor::body" << std::endl + #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS + << "b::static_inv" << std::endl + << (threw ? "b::inv\n" : "") + #endif + #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS + << (!threw ? "b::dtor::post\n" : "") // This can fail. + #endif + ; + return ok.str(); +} + +std::string ok_c(bool threw = false) { + std::ostringstream ok; ok + #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS + << "c::static_inv" << std::endl + << "c::inv" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_OLDS + << "c::dtor::old" << std::endl + #endif + << "c::dtor::body" << std::endl + #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS + << "c::static_inv" << std::endl + << (threw ? "c::inv\n" : "") + #endif + #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS + << (!threw ? "c::dtor::post\n" : "") // This can fail. + #endif + ; + return ok.str(); +} + +struct err {}; // Global decl so visible in MSVC10 lambdas. + +int main() { + std::ostringstream ok; + + a_post = true; + b_post = true; + c_post = true; + { + a aa; + out.str(""); + } + ok.str(""); ok // Test nothing failed. + << ok_a() + << ok_b() + << ok_c() + ; + BOOST_TEST(out.eq(ok.str())); + + boost::contract::set_postcondition_failure([&ok] (boost::contract::from) { + BOOST_TEST(out.eq(ok.str())); // Must check before dtor throws... + throw err(); // for testing (as dtors should never throw anyways). + }); + + #ifdef BOOST_CONTRACT_NO_POSTCONDITIONS + #define BOOST_CONTRACT_TEST_post 0 + #else + #define BOOST_CONTRACT_TEST_post 1 + #endif + + a_post = false; + b_post = true; + c_post = true; + try { + { + a aa; + ok.str(""); ok + << ok_a() // Test a::dtor::post failed... + ; + out.str(""); + } + #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS + BOOST_TEST(false); + } catch(err const&) { + #endif + ok // ...then exec other dtors and check inv on throw (as dtor threw). + << ok_b(BOOST_CONTRACT_TEST_post) + << ok_c(BOOST_CONTRACT_TEST_post) + ; + BOOST_TEST(out.eq(ok.str())); + } catch(...) { BOOST_TEST(false); } + + a_post = true; + b_post = false; + c_post = true; + try { + { + a aa; + ok.str(""); ok + << ok_a() + << ok_b() // Test b::dtor::post failed... + ; + out.str(""); + } + #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS + BOOST_TEST(false); + } catch(err const&) { + #endif + ok // ...then exec other dtors and check inv on throw (as dtor threw). + << ok_c(BOOST_CONTRACT_TEST_post) + ; + BOOST_TEST(out.eq(ok.str())); + } catch(...) { BOOST_TEST(false); } + + a_post = true; + b_post = true; + c_post = false; + try { + { + a aa; + ok.str(""); ok + << ok_a() + << ok_b() + << ok_c() // Test c::dtor::post failed... + ; + out.str(""); + } + #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS + BOOST_TEST(false); + } catch(err const&) { + #endif + // ...then exec other dtors and check inv on throw (as dtor threw). + BOOST_TEST(out.eq(ok.str())); + } catch(...) { BOOST_TEST(false); } + + a_post = false; + b_post = false; + c_post = false; + try { + { + a aa; + ok.str(""); ok + << ok_a() // Test a::dtor::post failed... + ; + out.str(""); + } + #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS + BOOST_TEST(false); + } catch(err const&) { + #endif + ok // ...then exec other dtors and check inv on throw (as dtor threw). + << ok_b(BOOST_CONTRACT_TEST_post) + << ok_c(BOOST_CONTRACT_TEST_post) + ; + BOOST_TEST(out.eq(ok.str())); + } catch(...) { BOOST_TEST(false); } + + #undef BOOST_CONTRACT_TEST_post + return boost::report_errors(); +} + diff --git a/src/boost/libs/contract/test/destructor/decl_post_ends.cpp b/src/boost/libs/contract/test/destructor/decl_post_ends.cpp new file mode 100644 index 000000000..942d2ed9a --- /dev/null +++ b/src/boost/libs/contract/test/destructor/decl_post_ends.cpp @@ -0,0 +1,191 @@ + +// Copyright (C) 2008-2018 Lorenzo Caminiti +// Distributed under the Boost Software License, Version 1.0 (see accompanying +// file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt). +// See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html + +// Test only derived and grandparent classes (ends) with postconditions. + +#undef BOOST_CONTRACT_TEST_NO_A_POST +#define BOOST_CONTRACT_TEST_NO_B_POST +#undef BOOST_CONTRACT_TEST_NO_C_POST +#include "decl.hpp" + +#include <boost/detail/lightweight_test.hpp> +#include <sstream> +#include <string> + +std::string ok_a() { + std::ostringstream ok; ok + #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS + << "a::static_inv" << std::endl + << "a::inv" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_OLDS + << "a::dtor::old" << std::endl + #endif + << "a::dtor::body" << std::endl + #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS + << "a::static_inv" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS + << "a::dtor::post" << std::endl // This can fail. + #endif + ; + return ok.str(); +} + +std::string ok_b(bool threw = false) { + std::ostringstream ok; ok + #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS + << "b::static_inv" << std::endl + << "b::inv" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_OLDS + << "b::dtor::old" << std::endl + #endif + << "b::dtor::body" << std::endl + #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS + << "b::static_inv" << std::endl + << (threw ? "b::inv\n" : "") + #endif + ; + return ok.str(); +} + +std::string ok_c(bool threw = false) { + std::ostringstream ok; ok + #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS + << "c::static_inv" << std::endl + << "c::inv" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_OLDS + << "c::dtor::old" << std::endl + #endif + << "c::dtor::body" << std::endl + #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS + << "c::static_inv" << std::endl + << (threw ? "c::inv\n" : "") + #endif + #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS + << (!threw ? "c::dtor::post\n" : "") // This can fail. + #endif + ; + return ok.str(); +} + +struct err {}; // Global decl so visible in MSVC10 lambdas. + +int main() { + std::ostringstream ok; + + a_post = true; + b_post = true; + c_post = true; + { + a aa; + out.str(""); + } + ok.str(""); ok // Test nothing failed. + << ok_a() + << ok_b() + << ok_c() + ; + BOOST_TEST(out.eq(ok.str())); + + boost::contract::set_postcondition_failure([&ok] (boost::contract::from) { + BOOST_TEST(out.eq(ok.str())); // Must check before dtor throws... + throw err(); // ... for testing (as dtors should never throw anyways). + }); + + #ifdef BOOST_CONTRACT_NO_POSTCONDITIONS + #define BOOST_CONTRACT_TEST_post 0 + #else + #define BOOST_CONTRACT_TEST_post 1 + #endif + + a_post = false; + b_post = true; + c_post = true; + try { + { + a aa; + ok.str(""); ok + << ok_a() // Test a::dtor::post failed. + ; + out.str(""); + } + #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS + BOOST_TEST(false); + } catch(err const&) { + #endif + ok // ... then exec other dtors and check inv on throw (as dtor threw). + << ok_b(BOOST_CONTRACT_TEST_post) + << ok_c(BOOST_CONTRACT_TEST_post) + ; + BOOST_TEST(out.eq(ok.str())); + } catch(...) { BOOST_TEST(false); } + + a_post = true; + b_post = false; + c_post = true; + try { + { + a aa; + out.str(""); + } + ok.str(""); ok + << ok_a() + << ok_b() // Test no b::dtor::post so no failure here. + << ok_c() + ; + BOOST_TEST(out.eq(ok.str())); + } catch(...) { BOOST_TEST(false); } + + a_post = true; + b_post = true; + c_post = false; + try { + { + a aa; + ok.str(""); ok + << ok_a() + << ok_b() + << ok_c() // Test c::dtor::post failed. + ; + out.str(""); + } + #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS + BOOST_TEST(false); + } catch(err const&) { + #endif + // ... then exec other dtors and check inv on throw (as dtor threw). + BOOST_TEST(out.eq(ok.str())); + } catch(...) { BOOST_TEST(false); } + + a_post = false; + b_post = false; + c_post = false; + try { + { + a aa; + ok.str(""); ok + << ok_a() // Test a::dtor::post failed. + ; + out.str(""); + } + #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS + BOOST_TEST(false); + } catch(err const&) { + #endif + ok // ... then exec other dtors and check inv on throw (as dtor threw). + << ok_b(BOOST_CONTRACT_TEST_post) + << ok_c(BOOST_CONTRACT_TEST_post) + ; + BOOST_TEST(out.eq(ok.str())); + } catch(...) { BOOST_TEST(false); } + + #undef BOOST_CONTRACT_TEST_post + return boost::report_errors(); +} + diff --git a/src/boost/libs/contract/test/destructor/decl_post_mid.cpp b/src/boost/libs/contract/test/destructor/decl_post_mid.cpp new file mode 100644 index 000000000..54197b1ae --- /dev/null +++ b/src/boost/libs/contract/test/destructor/decl_post_mid.cpp @@ -0,0 +1,182 @@ + +// Copyright (C) 2008-2018 Lorenzo Caminiti +// Distributed under the Boost Software License, Version 1.0 (see accompanying +// file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt). +// See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html + +// Test only middle base class with postconditions. + +#define BOOST_CONTRACT_TEST_NO_A_POST +#undef BOOST_CONTRACT_TEST_NO_B_POST +#define BOOST_CONTRACT_TEST_NO_C_POST +#include "decl.hpp" + +#include <boost/detail/lightweight_test.hpp> +#include <sstream> +#include <string> + +std::string ok_a() { + std::ostringstream ok; ok + #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS + << "a::static_inv" << std::endl + << "a::inv" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_OLDS + << "a::dtor::old" << std::endl + #endif + << "a::dtor::body" << std::endl + #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS + << "a::static_inv" << std::endl + #endif + ; + return ok.str(); +} + +std::string ok_b() { + std::ostringstream ok; ok + #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS + << "b::static_inv" << std::endl + << "b::inv" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_OLDS + << "b::dtor::old" << std::endl + #endif + << "b::dtor::body" << std::endl + #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS + << "b::static_inv" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS + << "b::dtor::post" << std::endl // This can fail. + #endif + ; + return ok.str(); +} + +std::string ok_c(bool threw = false) { + std::ostringstream ok; ok + #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS + << "c::static_inv" << std::endl + << "c::inv" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_OLDS + << "c::dtor::old" << std::endl + #endif + << "c::dtor::body" << std::endl + #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS + << "c::static_inv" << std::endl + << (threw ? "c::inv\n" : "") + #endif + ; + return ok.str(); +} + +struct err {}; // Global decl so visible in MSVC10 lambdas. + +int main() { + std::ostringstream ok; + + a_post = true; + b_post = true; + c_post = true; + { + a aa; + out.str(""); + } + ok.str(""); ok // Test nothing failed. + << ok_a() + << ok_b() + << ok_c() + ; + BOOST_TEST(out.eq(ok.str())); + + boost::contract::set_postcondition_failure([&ok] (boost::contract::from) { + BOOST_TEST(out.eq(ok.str())); // Must check before dtor throws... + throw err(); // ... for testing (as dtors should never throw anyways). + }); + + a_post = false; + b_post = true; + c_post = true; + try { + { + a aa; + out.str(""); + } + ok.str(""); ok + << ok_a() // Test no a::dtor::post so no failure here. + << ok_b() + << ok_c() + ; + BOOST_TEST(out.eq(ok.str())); + } catch(...) { BOOST_TEST(false); } + + #ifdef BOOST_CONTRACT_NO_POSTCONDITIONS + #define BOOST_CONTRACT_TEST_post 0 + #else + #define BOOST_CONTRACT_TEST_post 1 + #endif + + a_post = true; + b_post = false; + c_post = true; + try { + { + a aa; + ok.str(""); ok + << ok_a() + << ok_b() // Test b::dtor::post failed. + ; + out.str(""); + } + #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS + BOOST_TEST(false); + } catch(err const&) { + #endif + ok // ... then exec other dtors and check inv on throw (as dtor threw). + << ok_c(BOOST_CONTRACT_TEST_post) + ; + BOOST_TEST(out.eq(ok.str())); + } catch(...) { BOOST_TEST(false); } + + a_post = true; + b_post = true; + c_post = false; + try { + { + a aa; + out.str(""); + } + ok.str(""); ok + << ok_a() + << ok_b() + << ok_c() // Test no c::dtor::post so no failure here. + ; + BOOST_TEST(out.eq(ok.str())); + } catch(...) { BOOST_TEST(false); } + + a_post = false; + b_post = false; + c_post = false; + try { + { + a aa; + ok.str(""); ok + << ok_a() + << ok_b() // Test b::dtor::post failed. + ; + out.str(""); + } + #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS + BOOST_TEST(false); + } catch(err const&) { + #endif + ok // ... then exec other dtors and check inv on throw (as dtor threw). + << ok_c(BOOST_CONTRACT_TEST_post) + ; + BOOST_TEST(out.eq(ok.str())); + } catch(...) { BOOST_TEST(false); } + + #undef BOOST_CONTRACT_TEST_post + return boost::report_errors(); +} + diff --git a/src/boost/libs/contract/test/destructor/decl_post_none.cpp b/src/boost/libs/contract/test/destructor/decl_post_none.cpp new file mode 100644 index 000000000..9b3eb4df1 --- /dev/null +++ b/src/boost/libs/contract/test/destructor/decl_post_none.cpp @@ -0,0 +1,103 @@ + +// Copyright (C) 2008-2018 Lorenzo Caminiti +// Distributed under the Boost Software License, Version 1.0 (see accompanying +// file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt). +// See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html + +// Test all derived and base classes without postconditions. + +#define BOOST_CONTRACT_TEST_NO_A_POST +#define BOOST_CONTRACT_TEST_NO_B_POST +#define BOOST_CONTRACT_TEST_NO_C_POST +#include "decl.hpp" + +#include <boost/detail/lightweight_test.hpp> +#include <sstream> + +int main() { + std::ostringstream ok; ok // Test nothing fails. + #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS + << "a::static_inv" << std::endl + << "a::inv" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_OLDS + << "a::dtor::old" << std::endl + #endif + << "a::dtor::body" << std::endl + #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS + << "a::static_inv" << std::endl + #endif + + #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS + << "b::static_inv" << std::endl + << "b::inv" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_OLDS + << "b::dtor::old" << std::endl + #endif + << "b::dtor::body" << std::endl + #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS + << "b::static_inv" << std::endl + #endif + + #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS + << "c::static_inv" << std::endl + << "c::inv" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_OLDS + << "c::dtor::old" << std::endl + #endif + << "c::dtor::body" << std::endl + #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS + << "c::static_inv" << std::endl + #endif + ; + + a_post = true; + b_post = true; + c_post = true; + { + a aa; + out.str(""); + } + BOOST_TEST(out.eq(ok.str())); + + a_post = false; + b_post = true; + c_post = true; + { + a aa; + out.str(""); + } + BOOST_TEST(out.eq(ok.str())); + + a_post = true; + b_post = false; + c_post = true; + { + a aa; + out.str(""); + } + BOOST_TEST(out.eq(ok.str())); + + a_post = true; + b_post = true; + c_post = false; + { + a aa; + out.str(""); + } + BOOST_TEST(out.eq(ok.str())); + + a_post = false; + b_post = false; + c_post = false; + { + a aa; + out.str(""); + } + BOOST_TEST(out.eq(ok.str())); + + return boost::report_errors(); +} + diff --git a/src/boost/libs/contract/test/destructor/ifdef.cpp b/src/boost/libs/contract/test/destructor/ifdef.cpp new file mode 100644 index 000000000..53c4c89dd --- /dev/null +++ b/src/boost/libs/contract/test/destructor/ifdef.cpp @@ -0,0 +1,111 @@ + +// Copyright (C) 2008-2018 Lorenzo Caminiti +// Distributed under the Boost Software License, Version 1.0 (see accompanying +// file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt). +// See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html + +// Test contract compilation on/off. + +#include "../detail/oteststream.hpp" +#include <boost/contract/core/config.hpp> +#ifndef BOOST_CONTRACT_NO_DESTRUCTORS + #include <boost/contract/destructor.hpp> + #include <boost/contract/check.hpp> + #include <boost/contract/old.hpp> +#endif +#include <boost/detail/lightweight_test.hpp> +#include <sstream> + +boost::contract::test::detail::oteststream out; + +struct b { + #ifndef BOOST_CONTRACT_NO_INVARIANTS + static void static_invariant() { out << "b::static_inv" << std::endl; } + void invariant() const { out << "b::inv" << std::endl; } + #endif + + virtual ~b() { + #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS + boost::contract::old_ptr<int> old_y = BOOST_CONTRACT_OLDOF(y); + #endif + #ifndef BOOST_CONTRACT_NO_DESTRUCTORS + boost::contract::check c = boost::contract::destructor(this) + #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS + .old([] { out << "b::dtor::old" << std::endl; }) + .postcondition([] { out << "b::dtor::post" << std::endl; }) + #endif + ; + #endif + out << "b::dtor::body" << std::endl; + } + + static int y; +}; +int b::y = 0; + +struct a : public b { + #ifndef BOOST_CONTRACT_NO_INVARIANTS + static void static_invariant() { out << "a::static_inv" << std::endl; } + void invariant() const { out << "a::inv" << std::endl; } + #endif + + virtual ~a() { + #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS + boost::contract::old_ptr<int> old_x = BOOST_CONTRACT_OLDOF(x); + #endif + #ifndef BOOST_CONTRACT_NO_DESTRUCTORS + boost::contract::check c = boost::contract::destructor(this) + #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS + .old([] { out << "a::dtor::old" << std::endl; }) + .postcondition([] { out << "a::dtor::post" << std::endl; }) + #endif + ; + #endif + out << "a::dtor::body" << std::endl; + } + + static int x; +}; +int a::x = 0; + +int main() { + std::ostringstream ok; + { + a aa; + out.str(""); + } + ok.str(""); ok + #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS + << "a::static_inv" << std::endl + << "a::inv" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS + << "a::dtor::old" << std::endl + #endif + << "a::dtor::body" << std::endl + #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS + << "a::static_inv" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS + << "a::dtor::post" << std::endl + #endif + + #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS + << "b::static_inv" << std::endl + << "b::inv" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS + << "b::dtor::old" << std::endl + #endif + << "b::dtor::body" << std::endl + #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS + << "b::static_inv" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS + << "b::dtor::post" << std::endl + #endif + ; + BOOST_TEST(out.eq(ok.str())); + return boost::report_errors(); +} + diff --git a/src/boost/libs/contract/test/destructor/ifdef_macro.cpp b/src/boost/libs/contract/test/destructor/ifdef_macro.cpp new file mode 100644 index 000000000..cc14b4694 --- /dev/null +++ b/src/boost/libs/contract/test/destructor/ifdef_macro.cpp @@ -0,0 +1,142 @@ + +// Copyright (C) 2008-2018 Lorenzo Caminiti +// Distributed under the Boost Software License, Version 1.0 (see accompanying +// file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt). +// See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html + +// Test contract compilation on/off (using macro interface). + +#include "../detail/oteststream.hpp" +#include "../detail/unprotected_commas.hpp" +#include <boost/contract/core/config.hpp> +#include <boost/contract_macro.hpp> +#include <boost/detail/lightweight_test.hpp> +#include <sstream> + +boost::contract::test::detail::oteststream out; + +struct b { + BOOST_CONTRACT_STATIC_INVARIANT({ + boost::contract::test::detail::unprotected_commas<void, void, void>:: + call(); + out << "b::static_inv" << std::endl; + }) + + BOOST_CONTRACT_INVARIANT({ + boost::contract::test::detail::unprotected_commas<void, void, void>:: + call(); + out << "b::inv" << std::endl; + }) + + virtual ~b() { + BOOST_CONTRACT_OLD_PTR( + boost::contract::test::detail::unprotected_commas<int, void, + void>::type1 + )( + old_y, + (boost::contract::test::detail::unprotected_commas<void, void, + void>::same(y)) + ); + BOOST_CONTRACT_DESTRUCTOR(boost::contract::test::detail:: + unprotected_commas<void, void, void>::same(this)) + BOOST_CONTRACT_OLD([] { + boost::contract::test::detail::unprotected_commas< + void, void, void>::call(); + out << "b::dtor::old" << std::endl; + }) + BOOST_CONTRACT_POSTCONDITION([] { + boost::contract::test::detail::unprotected_commas< + void, void, void>::call(); + out << "b::dtor::post" << std::endl; + }) + ; + out << "b::dtor::body" << std::endl; + } + + static int y; +}; +int b::y = 0; + +struct a : public b { + BOOST_CONTRACT_STATIC_INVARIANT({ + boost::contract::test::detail::unprotected_commas<void, void, void>:: + call(); + out << "a::static_inv" << std::endl; + }) + + BOOST_CONTRACT_INVARIANT({ + boost::contract::test::detail::unprotected_commas<void, void, void>:: + call(); + out << "a::inv" << std::endl; + }) + + virtual ~a() { + BOOST_CONTRACT_OLD_PTR( + boost::contract::test::detail::unprotected_commas<int, void, void>:: + type1 + )( + old_x, + (boost::contract::test::detail::unprotected_commas<void, void, + void>::same(x)) + ); + BOOST_CONTRACT_DESTRUCTOR(boost::contract::test::detail:: + unprotected_commas<void, void, void>::same(this)) + BOOST_CONTRACT_OLD([] { + boost::contract::test::detail::unprotected_commas< + void, void, void>::call(); + out << "a::dtor::old" << std::endl; + }) + BOOST_CONTRACT_POSTCONDITION([] { + boost::contract::test::detail::unprotected_commas< + void, void, void>::call(); + out << "a::dtor::post" << std::endl; + }) + ; + out << "a::dtor::body" << std::endl; + } + + static int x; +}; +int a::x = 0; + +int main() { + std::ostringstream ok; + { + a aa; + out.str(""); + } + ok.str(""); ok + #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS + << "a::static_inv" << std::endl + << "a::inv" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_OLDS + << "a::dtor::old" << std::endl + #endif + << "a::dtor::body" << std::endl + #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS + << "a::static_inv" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS + << "a::dtor::post" << std::endl + #endif + + #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS + << "b::static_inv" << std::endl + << "b::inv" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_OLDS + << "b::dtor::old" << std::endl + #endif + << "b::dtor::body" << std::endl + #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS + << "b::static_inv" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS + << "b::dtor::post" << std::endl + #endif + ; + BOOST_TEST(out.eq(ok.str())); + return boost::report_errors(); +} + diff --git a/src/boost/libs/contract/test/destructor/pre_error.cpp b/src/boost/libs/contract/test/destructor/pre_error.cpp new file mode 100644 index 000000000..49b49e799 --- /dev/null +++ b/src/boost/libs/contract/test/destructor/pre_error.cpp @@ -0,0 +1,24 @@ + +// Copyright (C) 2008-2018 Lorenzo Caminiti +// Distributed under the Boost Software License, Version 1.0 (see accompanying +// file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt). +// See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html + +// Test destructor cannot use `.precondition(...)`. + +#include <boost/contract/destructor.hpp> +#include <boost/contract/check.hpp> + +struct a { + ~a() { + boost::contract::check c = boost::contract::destructor(this) + .precondition([] {}) // Error (no dtor func arg so never pre). + ; + } +}; + +int main() { + a aa; + return 0; +} + diff --git a/src/boost/libs/contract/test/destructor/smoke.cpp b/src/boost/libs/contract/test/destructor/smoke.cpp new file mode 100644 index 000000000..d1a9e18af --- /dev/null +++ b/src/boost/libs/contract/test/destructor/smoke.cpp @@ -0,0 +1,306 @@ + +// Copyright (C) 2008-2018 Lorenzo Caminiti +// Distributed under the Boost Software License, Version 1.0 (see accompanying +// file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt). +// See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html + +// Test destructor subcontracting. + +#include "../detail/oteststream.hpp" +#include "../detail/counter.hpp" +#include <boost/contract/destructor.hpp> +#include <boost/contract/base_types.hpp> +#include <boost/contract/assert.hpp> +#include <boost/contract/old.hpp> +#include <boost/contract/check.hpp> +#include <boost/preprocessor/control/iif.hpp> +#include <boost/detail/lightweight_test.hpp> +#include <sstream> + +boost::contract::test::detail::oteststream out; + +template<char Id> +struct t { + static void static_invariant() { + out << Id << "::static_inv" << std::endl; + BOOST_CONTRACT_ASSERT(l.value >= 0); + } + + void invariant() const { + out << Id << "::inv" << std::endl; + BOOST_CONTRACT_ASSERT(k_ < 0); + } + + struct l_tag; + typedef boost::contract::test::detail::counter<l_tag, int> l_type; + static l_type l; + + explicit t() : k_(-1) { ++l.value; } + + virtual ~t() { + boost::contract::old_ptr<l_type> old_l; + boost::contract::check c = boost::contract::destructor(this) + .old([&] { + out << Id << "::dtor::old" << std::endl; + old_l = BOOST_CONTRACT_OLDOF(l_type::eval(l)); + }) + .postcondition([&old_l] { + out << Id << "::dtor::post" << std::endl; + BOOST_CONTRACT_ASSERT(t<Id>::l.value == old_l->value - 1); + }) + ; + out << Id << "::dtor::body" << std::endl; + --l.value; + } + +private: + int k_; +}; +template<char Id> typename t<Id>::l_type t<Id>::l; + +// 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<'p'>, private t<'q'>, public t<'e'> + : BASES +{ + typedef BOOST_CONTRACT_BASE_TYPES(BASES) base_types; + #undef BASES + + static void static_invariant() { + out << "c::static_inv" << std::endl; + BOOST_CONTRACT_ASSERT(m.value >= 0); + } + + void invariant() const { + out << "c::inv" << std::endl; + BOOST_CONTRACT_ASSERT(j_ < 0); + } + + struct m_tag; + typedef boost::contract::test::detail::counter<m_tag, int> m_type; + static m_type m; + + explicit c() : j_(-1) { ++m.value; } + + virtual ~c() { + boost::contract::old_ptr<m_type> old_m = + BOOST_CONTRACT_OLDOF(m_type::eval(m)); + boost::contract::check c = boost::contract::destructor(this) + .old([] { + out << "c::dtor::old" << std::endl; + // Test old-of assignment above instead. + }) + .postcondition([&old_m] { + out << "c::dtor::post" << std::endl; + BOOST_CONTRACT_ASSERT(c::m.value == old_m->value - 1); + }) + ; + out << "c::dtor::body" << std::endl; + --m.value; + } + +private: + int j_; +}; +c::m_type c::m; + +// Test not (fully) contracted base is not part of destructor subcontracting. +struct b { + static void static_invariant() { out << "b::static_inv" << std::endl; } + void invariant() const { out << "b::inv" << std::endl; } + + explicit b() {} + virtual ~b() {} // No contract. +}; + +struct a_n_tag; // Global decl so visible in MSVC10 lambdas. +typedef boost::contract::test::detail::counter<a_n_tag, int> a_n_type; + +// 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 + + static void static_invariant() { + out << "a::static_inv" << std::endl; + BOOST_CONTRACT_ASSERT(n.value >= 0); + } + + void invariant() const { + out << "a::inv" << std::endl; + BOOST_CONTRACT_ASSERT(i_ < 0); + } + + static a_n_type n; + + explicit a() : i_(-1) { + ++i_; --i_; // To avoid a warning when all contracts off. + ++n.value; + } + + virtual ~a() { + boost::contract::old_ptr<a_n_type> old_n; + boost::contract::check c = boost::contract::destructor(this) + .old([&] { + out << "a::dtor::old" << std::endl; + old_n = BOOST_CONTRACT_OLDOF(a_n_type::eval(n)); + }) + .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_type a::n; + +int main() { + std::ostringstream ok; + + { + a aa; + out.str(""); + } // Call aa's destructor. + ok.str(""); ok + #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS + << "a::static_inv" << std::endl + << "a::inv" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_OLDS + << "a::dtor::old" << std::endl + #endif + << "a::dtor::body" << std::endl + // Test static inv, but not const inv, checked after destructor body. + #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS + << "a::static_inv" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS + << "a::dtor::post" << std::endl + #endif + + #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS + << "c::static_inv" << std::endl + << "c::inv" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_OLDS + << "c::dtor::old" << std::endl + #endif + << "c::dtor::body" << std::endl + #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS + << "c::static_inv" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS + << "c::dtor::post" << std::endl + #endif + + #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS + << "e::static_inv" << std::endl + << "e::inv" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_OLDS + << "e::dtor::old" << std::endl + #endif + << "e::dtor::body" << std::endl + #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS + << "e::static_inv" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS + << "e::dtor::post" << std::endl + #endif + + // Test check also private bases (because part of C++ destruction). + #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS + << "q::static_inv" << std::endl + << "q::inv" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_OLDS + << "q::dtor::old" << std::endl + #endif + << "q::dtor::body" << std::endl + #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS + << "q::static_inv" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS + << "q::dtor::post" << std::endl + #endif + + // Test check also protected bases (because part of C++ destruction). + #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS + << "p::static_inv" << std::endl + << "p::inv" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_OLDS + << "p::dtor::old" << std::endl + #endif + << "p::dtor::body" << std::endl + #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS + << "p::static_inv" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS + << "p::dtor::post" << std::endl + #endif + + #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS + << "d::static_inv" << std::endl + << "d::inv" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_OLDS + << "d::dtor::old" << std::endl + #endif + << "d::dtor::body" << std::endl + #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS + << "d::static_inv" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS + << "d::dtor::post" << std::endl + #endif + ; + BOOST_TEST(out.eq(ok.str())); + + #ifndef BOOST_CONTRACT_NO_OLDS + #define BOOST_CONTRACT_TEST_old 1u + #else + #define BOOST_CONTRACT_TEST_old 0u + #endif + + // Followings destroy only copies (actual objects are static data members). + + BOOST_TEST_EQ(a_n_type::copies(), BOOST_CONTRACT_TEST_old); + BOOST_TEST_EQ(a_n_type::evals(), BOOST_CONTRACT_TEST_old); + BOOST_TEST_EQ(a_n_type::copies(), a_n_type::dtors()); // No leak. + + BOOST_TEST_EQ(c::m_type::copies(), BOOST_CONTRACT_TEST_old); + BOOST_TEST_EQ(c::m_type::evals(), BOOST_CONTRACT_TEST_old); + BOOST_TEST_EQ(c::m_type::copies(), c::m_type::dtors()); // No leak. + + BOOST_TEST_EQ(t<'d'>::l_type::copies(), BOOST_CONTRACT_TEST_old); + BOOST_TEST_EQ(t<'d'>::l_type::evals(), BOOST_CONTRACT_TEST_old); + BOOST_TEST_EQ(t<'d'>::l_type::copies(), t<'d'>::l_type::dtors()); // No leak + + BOOST_TEST_EQ(t<'p'>::l_type::copies(), BOOST_CONTRACT_TEST_old); + BOOST_TEST_EQ(t<'p'>::l_type::evals(), BOOST_CONTRACT_TEST_old); + BOOST_TEST_EQ(t<'p'>::l_type::copies(), t<'p'>::l_type::dtors()); // No leak + + BOOST_TEST_EQ(t<'q'>::l_type::copies(), BOOST_CONTRACT_TEST_old); + BOOST_TEST_EQ(t<'q'>::l_type::evals(), BOOST_CONTRACT_TEST_old); + BOOST_TEST_EQ(t<'q'>::l_type::copies(), t<'q'>::l_type::dtors()); // No leak + + BOOST_TEST_EQ(t<'e'>::l_type::copies(), BOOST_CONTRACT_TEST_old); + BOOST_TEST_EQ(t<'e'>::l_type::evals(), BOOST_CONTRACT_TEST_old); + BOOST_TEST_EQ(t<'e'>::l_type::copies(), t<'e'>::l_type::dtors()); // No leak + + #undef BOOST_CONTRACT_TEST_old + return boost::report_errors(); +} + diff --git a/src/boost/libs/contract/test/destructor/throwing_body.cpp b/src/boost/libs/contract/test/destructor/throwing_body.cpp new file mode 100644 index 000000000..f14612ed9 --- /dev/null +++ b/src/boost/libs/contract/test/destructor/throwing_body.cpp @@ -0,0 +1,144 @@ + +// Copyright (C) 2008-2018 Lorenzo Caminiti +// Distributed under the Boost Software License, Version 1.0 (see accompanying +// file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt). +// See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html + +// Test throw from destructor body (in middle branch of inheritance tree). + +#include "../detail/oteststream.hpp" +#include <boost/contract/destructor.hpp> +#include <boost/contract/base_types.hpp> +#include <boost/contract/check.hpp> +#include <boost/config.hpp> +#include <boost/detail/lightweight_test.hpp> +#include <sstream> + +boost::contract::test::detail::oteststream out; + +struct c { + static void static_invariant() { out << "c::static_inv" << std::endl; } + void invariant() const { out << "c::inv" << std::endl; } + + ~c() BOOST_NOEXCEPT_IF(false) { + boost::contract::check c = boost::contract::destructor(this) + .old([] { out << "c::dtor::old" << std::endl; }) + .postcondition([] { out << "c::dtor::post" << std::endl; }) + .except([] { out << "c::dtor::except" << std::endl; }) + ; + out << "c::dtor::body" << std::endl; + // Do not throw (from inheritance root). + } +}; + +struct b_err {}; // Global decl so visible in MSVC10 lambdas. + +struct b + #define BASES public c + : BASES +{ + typedef BOOST_CONTRACT_BASE_TYPES(BASES) base_types; + #undef BASES + + static void static_invariant() { out << "b::static_inv" << std::endl; } + void invariant() const { out << "b::inv" << std::endl; } + + ~b() BOOST_NOEXCEPT_IF(false) { + boost::contract::check c = boost::contract::destructor(this) + .old([] { out << "b::dtor::old" << std::endl; }) + .postcondition([] { out << "b::dtor::post" << std::endl; }) + .except([] { out << "b::dtor::except" << std::endl; }) + ; + out << "b::dtor::body" << std::endl; + throw b_err(); // Test body throw (from inheritance mid branch). + } +}; + +struct a + #define BASES public b + : BASES +{ + typedef BOOST_CONTRACT_BASE_TYPES(BASES) base_types; + #undef BASES + + static void static_invariant() { out << "a::static_inv" << std::endl; } + void invariant() const { out << "a::inv" << std::endl; } + + ~a() BOOST_NOEXCEPT_IF(false) { + boost::contract::check c = boost::contract::destructor(this) + .old([] { out << "a::dtor::old" << std::endl; }) + .postcondition([] { out << "a::dtor::post" << std::endl; }) + .except([] { out << "a::dtor::except" << std::endl; }) + ; + out << "a::dtor::body" << std::endl; + // Do not throw (from inheritance leaf). + } +}; + +int main() { + std::ostringstream ok; + + try { + { + a aa; + out.str(""); + } + BOOST_TEST(false); + } catch(b_err const&) { + ok.str(""); ok + #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS + << "a::static_inv" << std::endl + << "a::inv" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_OLDS + << "a::dtor::old" << std::endl + #endif + << "a::dtor::body" << std::endl + // Test a destructed (so only static_inv and post, but no inv). + #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS + << "a::static_inv" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS + << "a::dtor::post" << std::endl + #endif + + #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS + << "b::static_inv" << std::endl + << "b::inv" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_OLDS + << "b::dtor::old" << std::endl + #endif + << "b::dtor::body" << std::endl // Test this threw. + // Test b not destructed (so static_inv, inv, and except, no post). + #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS + << "b::static_inv" << std::endl + << "b::inv" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_EXCEPTS + << "b::dtor::except" << std::endl + #endif + + #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS + << "c::static_inv" << std::endl + << "c::inv" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_OLDS + << "c::dtor::old" << std::endl + #endif + << "c::dtor::body" << std::endl + // Test c not destructed (so static_inv, inv, and except, no post). + #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS + << "c::static_inv" << std::endl + << "c::inv" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_EXCEPTS + << "c::dtor::except" << std::endl + #endif + ; + BOOST_TEST(out.eq(ok.str())); + } catch(...) { BOOST_TEST(false); } + + return boost::report_errors(); +} + diff --git a/src/boost/libs/contract/test/destructor/throwing_old.cpp b/src/boost/libs/contract/test/destructor/throwing_old.cpp new file mode 100644 index 000000000..cdfc13bc1 --- /dev/null +++ b/src/boost/libs/contract/test/destructor/throwing_old.cpp @@ -0,0 +1,150 @@ + +// Copyright (C) 2008-2018 Lorenzo Caminiti +// Distributed under the Boost Software License, Version 1.0 (see accompanying +// file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt). +// See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html + +// Test throw from destructor .old() (in middle branch of inheritance tree). + +#include "../detail/oteststream.hpp" +#include <boost/contract/destructor.hpp> +#include <boost/contract/base_types.hpp> +#include <boost/contract/check.hpp> +#include <boost/config.hpp> +#include <boost/detail/lightweight_test.hpp> +#include <sstream> + +boost::contract::test::detail::oteststream out; + +struct c { + static void static_invariant() { out << "c::static_inv" << std::endl; } + void invariant() const { out << "c::inv" << std::endl; } + + ~c() BOOST_NOEXCEPT_IF(false) { + boost::contract::check c = boost::contract::destructor(this) + .old([] { out << "c::dtor::old" << std::endl; }) + .postcondition([] { out << "c::dtor::post" << std::endl; }) + .except([] { out << "c::dtor::except" << std::endl; }) + ; + out << "c::dtor::body" << std::endl; + // Do not throw (from inheritance root). + } +}; + +struct b_err {}; // Global decl so visible in MSVC10 lambdas. + +struct b + #define BASES public c + : BASES +{ + typedef BOOST_CONTRACT_BASE_TYPES(BASES) base_types; + #undef BASES + + static void static_invariant() { out << "b::static_inv" << std::endl; } + void invariant() const { out << "b::inv" << std::endl; } + + ~b() BOOST_NOEXCEPT_IF(false) { + boost::contract::check c = boost::contract::destructor(this) + .old([] { + out << "b::dtor::old" << std::endl; + throw b_err(); // Test this throws (from mid branch). + }) + .postcondition([] { out << "b::dtor::post" << std::endl; }) + .except([] { out << "b::dtor::except" << std::endl; }) + ; + out << "b::dtor::body" << std::endl; + } +}; + +struct a + #define BASES public b + : BASES +{ + typedef BOOST_CONTRACT_BASE_TYPES(BASES) base_types; + #undef BASES + + static void static_invariant() { out << "a::static_inv" << std::endl; } + void invariant() const { out << "a::inv" << std::endl; } + + ~a() BOOST_NOEXCEPT_IF(false) { + boost::contract::check c = boost::contract::destructor(this) + .old([] { out << "a::dtor::old" << std::endl; }) + .postcondition([] { out << "a::dtor::post" << std::endl; }) + .except([] { out << "a::dtor::except" << std::endl; }) + ; + out << "a::dtor::body" << std::endl; + // Do not throw (from inheritance leaf). + } +}; + +int main() { + std::ostringstream ok; + + boost::contract::set_old_failure([] (boost::contract::from) { throw; }); + + try { + { + a aa; + out.str(""); + } + #ifndef BOOST_CONTRACT_NO_OLDS + BOOST_TEST(false); + } catch(b_err const&) { + #endif + ok.str(""); ok + #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS + << "a::static_inv" << std::endl + << "a::inv" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_OLDS + << "a::dtor::old" << std::endl + #endif + << "a::dtor::body" << std::endl + #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS + // Test a destructed (so only static_inv and post, but no inv). + << "a::static_inv" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS + << "a::dtor::post" << std::endl + #endif + + #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS + << "b::static_inv" << std::endl + << "b::inv" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_OLDS + << "b::dtor::old" << std::endl // Test this threw. + #else + << "b::dtor::body" << std::endl + #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS + << "b::static_inv" << std::endl + #endif + #endif + + #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS + << "c::static_inv" << std::endl + << "c::inv" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_OLDS + << "c::dtor::old" << std::endl + #endif + << "c::dtor::body" << std::endl + #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS + << "c::static_inv" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_OLDS + // Test c not destructed (so both inv and except). + #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS + << "c::inv" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_EXCEPTS + << "c::dtor::except" << std::endl + #endif + #endif + ; + BOOST_TEST(out.eq(ok.str())); + } catch(...) { BOOST_TEST(false); } + + return boost::report_errors(); +} + diff --git a/src/boost/libs/contract/test/destructor/throwing_post.cpp b/src/boost/libs/contract/test/destructor/throwing_post.cpp new file mode 100644 index 000000000..831864932 --- /dev/null +++ b/src/boost/libs/contract/test/destructor/throwing_post.cpp @@ -0,0 +1,153 @@ + +// Copyright (C) 2008-2018 Lorenzo Caminiti +// Distributed under the Boost Software License, Version 1.0 (see accompanying +// file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt). +// See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html + +// Test throw from destructor .post() (in middle branch of inheritance tree). + +#include "../detail/oteststream.hpp" +#include <boost/contract/destructor.hpp> +#include <boost/contract/base_types.hpp> +#include <boost/contract/check.hpp> +#include <boost/config.hpp> +#include <boost/detail/lightweight_test.hpp> +#include <sstream> + +boost::contract::test::detail::oteststream out; + +struct c { + static void static_invariant() { out << "c::static_inv" << std::endl; } + void invariant() const { out << "c::inv" << std::endl; } + + ~c() BOOST_NOEXCEPT_IF(false) { + boost::contract::check c = boost::contract::destructor(this) + .old([] { out << "c::dtor::old" << std::endl; }) + .postcondition([] { out << "c::dtor::post" << std::endl; }) + .except([] { out << "c::dtor::except" << std::endl; }) + ; + out << "c::dtor::body" << std::endl; + // Do not throw (from inheritance root). + } +}; + +struct b_err {}; // Global decl so visible in MSVC10 lambdas. + +struct b + #define BASES public c + : BASES +{ + typedef BOOST_CONTRACT_BASE_TYPES(BASES) base_types; + #undef BASES + + static void static_invariant() { out << "b::static_inv" << std::endl; } + void invariant() const { out << "b::inv" << std::endl; } + + ~b() BOOST_NOEXCEPT_IF(false) { + boost::contract::check c = boost::contract::destructor(this) + .old([] { out << "b::dtor::old" << std::endl; }) + .postcondition([] { + out << "b::dtor::post" << std::endl; + throw b_err(); // Test this throws (from mid branch). + }) + .except([] { out << "b::dtor::except" << std::endl; }) + ; + out << "b::dtor::body" << std::endl; + } +}; + +struct a + #define BASES public b + : BASES +{ + typedef BOOST_CONTRACT_BASE_TYPES(BASES) base_types; + #undef BASES + + static void static_invariant() { out << "a::static_inv" << std::endl; } + void invariant() const { out << "a::inv" << std::endl; } + + ~a() BOOST_NOEXCEPT_IF(false) { + boost::contract::check c = boost::contract::destructor(this) + .old([] { out << "a::dtor::old" << std::endl; }) + .postcondition([] { out << "a::dtor::post" << std::endl; }) + .except([] { out << "a::dtor::except" << std::endl; }) + ; + out << "a::dtor::body" << std::endl; + // Do not throw (from inheritance leaf). + } +}; + +int main() { + std::ostringstream ok; + + boost::contract::set_postcondition_failure( + [] (boost::contract::from) { throw; }); + + try { + { + a aa; + out.str(""); + } + #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS + BOOST_TEST(false); + } catch(b_err const&) { + #endif + ok.str(""); ok + #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS + << "a::static_inv" << std::endl + << "a::inv" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_OLDS + << "a::dtor::old" << std::endl + #endif + << "a::dtor::body" << std::endl + #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS + // Test a destructed (so only static_inv and post, but no inv). + << "a::static_inv" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS + << "a::dtor::post" << std::endl + #endif + + #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS + << "b::static_inv" << std::endl + << "b::inv" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_OLDS + << "b::dtor::old" << std::endl + #endif + << "b::dtor::body" << std::endl + #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS + << "b::static_inv" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS + << "b::dtor::post" << std::endl // Test this threw. + #endif + + #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS + << "c::static_inv" << std::endl + << "c::inv" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_OLDS + << "c::dtor::old" << std::endl + #endif + << "c::dtor::body" << std::endl + #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS + << "c::static_inv" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS + // Test c not destructed (so both inv and except). + #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS + << "c::inv" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_EXCEPTS + << "c::dtor::except" << std::endl + #endif + #endif + ; + BOOST_TEST(out.eq(ok.str())); + } catch(...) { BOOST_TEST(false); } + + return boost::report_errors(); +} + diff --git a/src/boost/libs/contract/test/detail/counter.hpp b/src/boost/libs/contract/test/detail/counter.hpp new file mode 100644 index 000000000..ab40dfcdb --- /dev/null +++ b/src/boost/libs/contract/test/detail/counter.hpp @@ -0,0 +1,56 @@ + +#ifndef BOOST_CONTRACT_TEST_DETAIL_COUNTER_HPP_ +#define BOOST_CONTRACT_TEST_DETAIL_COUNTER_HPP_ + +// Copyright (C) 2008-2018 Lorenzo Caminiti +// Distributed under the Boost Software License, Version 1.0 (see accompanying +// file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt). +// See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html + +namespace boost { namespace contract { namespace test { namespace detail { + +// Helper to count copies and evaluations of type (e.g., for old values). +template<class Tag, typename T> +struct counter { + T value; + + counter() : value() { ++ctors_; } + static unsigned ctors() { return ctors_; } + + ~counter() { ++dtors_; } + static unsigned dtors() { return dtors_; } + + /* implicit */ counter(counter const& other) : value(other.value) { + ++ctor_copies_; + ++ctors_; + } + + counter& operator=(counter const& other) { + value = other.value; + ++op_copies_; + return *this; + } + + static unsigned copies() { return ctor_copies_ + op_copies_; } + + static counter const& eval(counter const& me) { ++me.evals_; return me; } + static unsigned evals() { return evals_; } + +private: + static unsigned ctors_; // Total constructions (including copies). + static unsigned dtors_; + static unsigned ctor_copies_; + static unsigned op_copies_; + static unsigned evals_; +}; + +template<class Tag, typename T> unsigned counter<Tag, T>::ctors_ = 0; +template<class Tag, typename T> unsigned counter<Tag, T>::dtors_ = 0; +template<class Tag, typename T> unsigned counter<Tag, T>::ctor_copies_ = 0; +template<class Tag, typename T> unsigned counter<Tag, T>::op_copies_ = 0; +template<class Tag, typename T> unsigned counter<Tag, T>::evals_ = 0; + +} } } } // namespace + +#endif // #include guard + diff --git a/src/boost/libs/contract/test/detail/oteststream.hpp b/src/boost/libs/contract/test/detail/oteststream.hpp new file mode 100644 index 000000000..5bf5a031c --- /dev/null +++ b/src/boost/libs/contract/test/detail/oteststream.hpp @@ -0,0 +1,82 @@ + +#ifndef BOOST_CONTRACT_TEST_DETAIL_OTESTSTREAM_HPP_ +#define BOOST_CONTRACT_TEST_DETAIL_OTESTSTREAM_HPP_ + +// Copyright (C) 2008-2018 Lorenzo Caminiti +// Distributed under the Boost Software License, Version 1.0 (see accompanying +// file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt). +// See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html + +#include <boost/iostreams/tee.hpp> +#include <boost/iostreams/stream.hpp> +#include <string> +#include <sstream> +#include <iostream> +#include <algorithm> + +namespace boost { namespace contract { namespace test { namespace detail { + +namespace oteststream_ { + struct oss_base { // Wrap oss data member for proper initialization order. + protected: + std::ostringstream oss_; + }; +} + +// Print to clog plus build internal string (using ostringstream) for checking. +struct oteststream : + private oteststream_::oss_base, + public boost::iostreams::stream<boost::iostreams::tee_device<std::ostream, + std::ostringstream> > +{ + oteststream() : + oteststream_::oss_base(), + boost::iostreams::stream<boost::iostreams::tee_device< + std::ostream, std::ostringstream> >( + boost::iostreams::tee_device<std::ostream, std::ostringstream>( + std::clog, oss_) + ) + {} + + std::string str() const { return oss_.str(); } + void str(std::string const& s) { oss_.str(s); } + + 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()) { + std::cout << std::endl; + std::cout << + "Error: Following strings differ at position " << i << + ", because '" << r[i] << "' != '" << s[i] << "':" << std::endl + ; + std::cout << std::endl; + std::cout + << r.substr(0, i) + << "(((" << r[i] << ")))" + // Extra () to avoid clashes with MSVC min macro. + << r.substr((std::min)(i + 1, r.size()), r.size()) + << std::endl + ; + std::cout << std::endl; + std::cout + << s.substr(0, i) + << "(((" << s[i] << ")))" + // Extra () to avoid clashes with MSVC min macro. + << s.substr((std::min)(i + 1, s.size()), s.size()) + << std::endl + ; + std::cout << std::endl; + return false; + } + return true; + } +}; + +} } } } // namespace + +#endif // #include guard + diff --git a/src/boost/libs/contract/test/detail/out.hpp b/src/boost/libs/contract/test/detail/out.hpp new file mode 100644 index 000000000..fd9cd4c54 --- /dev/null +++ b/src/boost/libs/contract/test/detail/out.hpp @@ -0,0 +1,23 @@ + +#ifndef BOOST_CONTRACT_TEST_DETAIL_OUT_HPP_ +#define BOOST_CONTRACT_TEST_DETAIL_OUT_HPP_ + +// Copyright (C) 2008-2018 Lorenzo Caminiti +// Distributed under the Boost Software License, Version 1.0 (see accompanying +// file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt). +// See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html + +// To declare test string functions across shared libraries. + +#include <string> + +namespace boost { namespace contract { namespace test { namespace detail { + +std::string BOOST_CONTRACT_TEST_DETAIL_OUT_DECLSPEC out(); + +void BOOST_CONTRACT_TEST_DETAIL_OUT_DECLSPEC out(std::string const& text); + +} } } } + +#endif // #include guard + diff --git a/src/boost/libs/contract/test/detail/out_inlined.hpp b/src/boost/libs/contract/test/detail/out_inlined.hpp new file mode 100644 index 000000000..954088f35 --- /dev/null +++ b/src/boost/libs/contract/test/detail/out_inlined.hpp @@ -0,0 +1,33 @@ + +#ifndef BOOST_CONTRACT_TEST_OUT_INLINED_HPP_ +#define BOOST_CONTRACT_TEST_OUT_INLINED_HPP_ + +// Copyright (C) 2008-2018 Lorenzo Caminiti +// Distributed under the Boost Software License, Version 1.0 (see accompanying +// file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt). +// See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html + +#include "out.hpp" +#include <iostream> + +namespace boost { namespace contract { namespace test { namespace detail { + +namespace out_ { + std::string out; +} + +std::string out() { return out_::out; } + +void out(std::string const& text) { + if(text == "") out_::out = ""; + else { + out_::out = out_::out + text; + std::clog << text; + std::clog.flush(); + } +} + +} } } } + +#endif // #include guard + diff --git a/src/boost/libs/contract/test/detail/unprotected_commas.hpp b/src/boost/libs/contract/test/detail/unprotected_commas.hpp new file mode 100644 index 000000000..c20dd4045 --- /dev/null +++ b/src/boost/libs/contract/test/detail/unprotected_commas.hpp @@ -0,0 +1,27 @@ + +#ifndef BOOST_CONTRACT_TEST_DETAIL_UNPROTECTED_COMMAS_HPP_ +#define BOOST_CONTRACT_TEST_DETAIL_UNPROTECTED_COMMAS_HPP_ + +// Copyright (C) 2008-2018 Lorenzo Caminiti +// Distributed under the Boost Software License, Version 1.0 (see accompanying +// file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt). +// See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html + +namespace boost { namespace contract { namespace test { namespace detail { + +// Used to test passing unprotected commas into macro parameters. +template<typename T1, typename Unused2, typename Unused3> +struct unprotected_commas { + typedef T1 type1; // For type macro parameters. + + static void call() {} // For code block macro parameters. + + // For value macro parameters. + template<typename U> static U& same(U& x) { return x; } + template<typename U> static U* same(U* x) { return x; } +}; + +} } } } // namespace + +#endif // #include guard + diff --git a/src/boost/libs/contract/test/disable/audit.cpp b/src/boost/libs/contract/test/disable/audit.cpp new file mode 100644 index 000000000..cb0765ea7 --- /dev/null +++ b/src/boost/libs/contract/test/disable/audit.cpp @@ -0,0 +1,11 @@ + +// Copyright (C) 2008-2018 Lorenzo Caminiti +// Distributed under the Boost Software License, Version 1.0 (see accompanying +// file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt). +// See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html + +#ifndef BOOST_CONTRACT_AUDITS + #error "build must define AUDITS" +#endif +#include "audit.hpp" + diff --git a/src/boost/libs/contract/test/disable/audit.hpp b/src/boost/libs/contract/test/disable/audit.hpp new file mode 100644 index 000000000..c2b2236cb --- /dev/null +++ b/src/boost/libs/contract/test/disable/audit.hpp @@ -0,0 +1,32 @@ + +// no #include guard + +// Copyright (C) 2008-2018 Lorenzo Caminiti +// Distributed under the Boost Software License, Version 1.0 (see accompanying +// file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt). +// See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html + +#include <boost/contract/assert.hpp> +#include <boost/contract/core/exception.hpp> +#include <boost/detail/lightweight_test.hpp> + +int main() { + bool threw = false; + try { + #ifdef BOOST_CONTRACT_TEST_ERROR + BOOST_CONTRACT_ASSERT_AUDIT( + BOOST_CONTRACT_TEST_ERROR_expected_undeclared_identifier); + #else + BOOST_CONTRACT_ASSERT_AUDIT(false); + #endif + } catch(boost::contract::assertion_failure const&) { threw = true; } + + #if defined(BOOST_CONTRACT_AUDITS) && !defined(BOOST_CONTRACT_NO_ALL) + BOOST_TEST(threw); + #else + BOOST_TEST(!threw); + #endif + + return boost::report_errors(); +} + diff --git a/src/boost/libs/contract/test/disable/audit_disabled.cpp b/src/boost/libs/contract/test/disable/audit_disabled.cpp new file mode 100644 index 000000000..18c6ad03f --- /dev/null +++ b/src/boost/libs/contract/test/disable/audit_disabled.cpp @@ -0,0 +1,8 @@ + +// Copyright (C) 2008-2018 Lorenzo Caminiti +// Distributed under the Boost Software License, Version 1.0 (see accompanying +// file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt). +// See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html + +#include "audit.hpp" + diff --git a/src/boost/libs/contract/test/disable/audit_disabled_error.cpp b/src/boost/libs/contract/test/disable/audit_disabled_error.cpp new file mode 100644 index 000000000..c58714dce --- /dev/null +++ b/src/boost/libs/contract/test/disable/audit_disabled_error.cpp @@ -0,0 +1,9 @@ + +// Copyright (C) 2008-2018 Lorenzo Caminiti +// Distributed under the Boost Software License, Version 1.0 (see accompanying +// file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt). +// See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html + +#define BOOST_CONTRACT_TEST_ERROR +#include "audit.hpp" + diff --git a/src/boost/libs/contract/test/disable/audit_error.cpp b/src/boost/libs/contract/test/disable/audit_error.cpp new file mode 100644 index 000000000..c58714dce --- /dev/null +++ b/src/boost/libs/contract/test/disable/audit_error.cpp @@ -0,0 +1,9 @@ + +// Copyright (C) 2008-2018 Lorenzo Caminiti +// Distributed under the Boost Software License, Version 1.0 (see accompanying +// file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt). +// See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html + +#define BOOST_CONTRACT_TEST_ERROR +#include "audit.hpp" + diff --git a/src/boost/libs/contract/test/disable/axiom.cpp b/src/boost/libs/contract/test/disable/axiom.cpp new file mode 100644 index 000000000..b24af7a4f --- /dev/null +++ b/src/boost/libs/contract/test/disable/axiom.cpp @@ -0,0 +1,8 @@ + +// Copyright (C) 2008-2018 Lorenzo Caminiti +// Distributed under the Boost Software License, Version 1.0 (see accompanying +// file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt). +// See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html + +#include "axiom.hpp" + diff --git a/src/boost/libs/contract/test/disable/axiom.hpp b/src/boost/libs/contract/test/disable/axiom.hpp new file mode 100644 index 000000000..df5231bb1 --- /dev/null +++ b/src/boost/libs/contract/test/disable/axiom.hpp @@ -0,0 +1,23 @@ + +// no #include guard + +// Copyright (C) 2008-2018 Lorenzo Caminiti +// Distributed under the Boost Software License, Version 1.0 (see accompanying +// file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt). +// See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html + +#include <boost/contract/assert.hpp> + +bool no_impl(); // Test func that cannot be impl in C++ sill OK in axioms. + +int main() { + #ifdef BOOST_CONTRACT_TEST_ERROR + BOOST_CONTRACT_ASSERT_AXIOM( + BOOST_CONRACT_TEST_ERROR_expected_undeclared_identifier); + #else + BOOST_CONTRACT_ASSERT_AXIOM(false); // Test always false, OK. + BOOST_CONTRACT_ASSERT_AXIOM(no_impl()); // Test no implementation, OK. + #endif + return 0; +} + diff --git a/src/boost/libs/contract/test/disable/axiom_error.cpp b/src/boost/libs/contract/test/disable/axiom_error.cpp new file mode 100644 index 000000000..a7c4c406d --- /dev/null +++ b/src/boost/libs/contract/test/disable/axiom_error.cpp @@ -0,0 +1,9 @@ + +// Copyright (C) 2008-2018 Lorenzo Caminiti +// Distributed under the Boost Software License, Version 1.0 (see accompanying +// file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt). +// See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html + +#define BOOST_CONTRACT_TEST_ERROR +#include "axiom.hpp" + diff --git a/src/boost/libs/contract/test/disable/lib_a.cpp b/src/boost/libs/contract/test/disable/lib_a.cpp new file mode 100644 index 000000000..a4f283de3 --- /dev/null +++ b/src/boost/libs/contract/test/disable/lib_a.cpp @@ -0,0 +1,14 @@ + +// Copyright (C) 2008-2018 Lorenzo Caminiti +// Distributed under the Boost Software License, Version 1.0 (see accompanying +// file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt). +// See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html + +#define BOOST_CONTRACT_TEST_LIB_A_SOURCE +#include "lib_a.hpp" +#include <boost/contract.hpp> // All headers so test ODR for entire lib. +#ifndef BOOST_CONTRACT_HEADER_ONLY + #include "lib_a_inlined.hpp" +#endif +#include "../detail/out_inlined.hpp" + diff --git a/src/boost/libs/contract/test/disable/lib_a.hpp b/src/boost/libs/contract/test/disable/lib_a.hpp new file mode 100644 index 000000000..7f26276ee --- /dev/null +++ b/src/boost/libs/contract/test/disable/lib_a.hpp @@ -0,0 +1,51 @@ + +#ifndef BOOST_CONTRACT_TEST_LIB_A_HPP_ +#define BOOST_CONTRACT_TEST_LIB_A_HPP_ + +// Copyright (C) 2008-2018 Lorenzo Caminiti +// Distributed under the Boost Software License, Version 1.0 (see accompanying +// file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt). +// See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html + +#include "../detail/counter.hpp" +#include <boost/contract.hpp> // All headers so test ODR for entire lib. +#include <boost/config.hpp> +#include <string> + +#ifdef BOOST_CONTRACT_TEST_LIB_A_DYN_LINK + #ifdef BOOST_CONTRACT_TEST_LIB_A_SOURCE + #define BOOST_CONTRACT_TEST_LIB_A_DECLSPEC BOOST_SYMBOL_EXPORT + #else + #define BOOST_CONTRACT_TEST_LIB_A_DECLSPEC BOOST_SYMBOL_IMPORT + #endif +#else + #define BOOST_CONTRACT_TEST_LIB_A_DECLSPEC /* nothing */ +#endif + +#define BOOST_CONTRACT_TEST_DETAIL_OUT_DECLSPEC \ + BOOST_CONTRACT_TEST_LIB_A_DECLSPEC +#include "../detail/out.hpp" + +struct BOOST_CONTRACT_TEST_LIB_A_DECLSPEC a { + static void static_invariant(); + void invariant() const; + + struct x_tag; + typedef boost::contract::test::detail::counter<x_tag, int> 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(); +}; + +#ifdef BOOST_CONTRACT_HEADER_ONLY + #include "lib_a_inlined.hpp" +#endif + +#endif // #include guard + diff --git a/src/boost/libs/contract/test/disable/lib_a_inlined.hpp b/src/boost/libs/contract/test/disable/lib_a_inlined.hpp new file mode 100644 index 000000000..f139bd2b2 --- /dev/null +++ b/src/boost/libs/contract/test/disable/lib_a_inlined.hpp @@ -0,0 +1,101 @@ + +#ifndef BOOST_CONTRACT_TEST_LIB_A_INLINED_HPP_ +#define BOOST_CONTRACT_TEST_LIB_A_INLINED_HPP_ + +// Copyright (C) 2008-2018 Lorenzo Caminiti +// Distributed under the Boost Software License, Version 1.0 (see accompanying +// file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt). +// See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html + +#include "lib_a.hpp" +#include <boost/contract.hpp> // All headers so test ODR for entire lib. + +#ifdef BOOST_CONTRACT_HEADER_ONLY + #define BOOST_CONTRACT_TEST_LIB_A_DECLINLINE inline +#else + #define BOOST_CONTRACT_TEST_LIB_A_DECLINLINE /* nothing */ +#endif + +BOOST_CONTRACT_TEST_LIB_A_DECLINLINE +void a::static_invariant() { + using boost::contract::test::detail::out; + out("a::static_inv\n"); +} + +BOOST_CONTRACT_TEST_LIB_A_DECLINLINE +void a::invariant() const { + using boost::contract::test::detail::out; + out("a::inv\n"); +} + +BOOST_CONTRACT_TEST_LIB_A_DECLINLINE +int a::f(x_type& x) { + using boost::contract::test::detail::out; + int result; + boost::contract::old_ptr<x_type> old_x = + BOOST_CONTRACT_OLDOF(x_type::eval(x)); + boost::contract::check c = boost::contract::public_function(this) + // Capturing [&] so out() visible in MSVC10 lambdas. + .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; +} + +BOOST_CONTRACT_TEST_LIB_A_DECLINLINE +void a::disable_pre_failure() { + using boost::contract::test::detail::out; + boost::contract::set_precondition_failure([] (boost::contract::from) + { out("a::pre_failure\n"); }); +} + +BOOST_CONTRACT_TEST_LIB_A_DECLINLINE +void a::disable_post_failure() { + using boost::contract::test::detail::out; + boost::contract::set_postcondition_failure([] (boost::contract::from) + { out("a::post_failure\n"); }); +} + +BOOST_CONTRACT_TEST_LIB_A_DECLINLINE +void a::disable_entry_inv_failure() { + using boost::contract::test::detail::out; + boost::contract::set_entry_invariant_failure([] (boost::contract::from) + { out("a::entry_inv_failure\n"); }); +} + +BOOST_CONTRACT_TEST_LIB_A_DECLINLINE +void a::disable_exit_inv_failure() { + using boost::contract::test::detail::out; + boost::contract::set_exit_invariant_failure([] (boost::contract::from) + { out("a::exit_inv_failure\n"); }); +} + +BOOST_CONTRACT_TEST_LIB_A_DECLINLINE +void a::disable_inv_failure() { + using boost::contract::test::detail::out; + boost::contract::set_invariant_failure([] (boost::contract::from) + { out("a::inv_failure\n"); }); +} + +BOOST_CONTRACT_TEST_LIB_A_DECLINLINE +void a::disable_failure() { + using boost::contract::test::detail::out; + boost::contract::set_precondition_failure( + boost::contract::set_postcondition_failure( + boost::contract::set_except_failure( + boost::contract::set_old_failure( + boost::contract::set_invariant_failure( + [] (boost::contract::from) { out("a::failure\n"); } + ))))); +} + +#endif // #include guard + diff --git a/src/boost/libs/contract/test/disable/lib_ab.hpp b/src/boost/libs/contract/test/disable/lib_ab.hpp new file mode 100644 index 000000000..f6aafdb31 --- /dev/null +++ b/src/boost/libs/contract/test/disable/lib_ab.hpp @@ -0,0 +1,164 @@ + +// Copyright (C) 2008-2018 Lorenzo Caminiti +// Distributed under the Boost Software License, Version 1.0 (see accompanying +// file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt). +// See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html + +#include "lib_a.hpp" +#include "lib_b.hpp" +#include "../detail/oteststream.hpp" +#include <boost/contract/core/exception.hpp> +#include <boost/contract/core/config.hpp> +#include <boost/detail/lightweight_test.hpp> +#include <sstream> +#include <string> + +std::string ok_f() { + std::ostringstream ok; ok + #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS + << "a::static_inv" << std::endl + << "a::inv" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_PRECONDITIONS + << "a::f::pre" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_OLDS + << "a::f::old" << std::endl + #endif + << "a::f::body" << std::endl + #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS + << "a::static_inv" << std::endl + << "a::inv" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS + << "a::f::post" << std::endl + #endif + ; + return ok.str(); +} + +int main() { + using boost::contract::test::detail::out; + std::ostringstream ok; + b bb; + + out(""); + bb.g(); + ok.str(""); ok + #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS + << "b::static_inv" << std::endl + << "b::inv" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_PRECONDITIONS + << "b::g::pre" << std::endl + #ifdef BOOST_CONTRACT_PRECONDITIONS_DISABLE_NO_ASSERTION + // 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 + #ifndef BOOST_CONTRACT_NO_OLDS + << "b::g::old" << std::endl + #endif + << "b::g::body" << std::endl + #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS + << "b::static_inv" << std::endl + << "b::inv" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS + << "b::g::post" << std::endl + // Test call while checking executes body (but no contracts). + << "a::f::body" << std::endl + #endif + ; + BOOST_TEST(boost::contract::test::detail::oteststream::eq(out(), ok.str())); + + // Test old values not copied for disabled contracts. + + #if defined(BOOST_CONTRACT_PRECONDITIONS_DISABLE_NO_ASSERTION) && \ + !defined(BOOST_CONTRACT_NO_PRECONDITIONS) && \ + !defined(BOOST_CONTRACT_NO_OLDS) + #define BOOST_CONTRACT_TEST_old 1u + #else + #define BOOST_CONTRACT_TEST_old 0u + #endif + + BOOST_TEST_EQ(a::x_type::copies(), BOOST_CONTRACT_TEST_old); + BOOST_TEST_EQ(a::x_type::evals(), BOOST_CONTRACT_TEST_old); + 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(boost::contract::test::detail::oteststream::eq(out(), 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(boost::contract::test::detail::oteststream::eq(out(), + "a::pre_failure\n")); + + a::disable_post_failure(); + out(""); + boost::contract::postcondition_failure(boost::contract::from()); + BOOST_TEST(boost::contract::test::detail::oteststream::eq(out(), + "a::post_failure\n")); + + a::disable_entry_inv_failure(); + out(""); + boost::contract::entry_invariant_failure(boost::contract::from()); + BOOST_TEST(boost::contract::test::detail::oteststream::eq(out(), + "a::entry_inv_failure\n")); + + a::disable_exit_inv_failure(); + out(""); + boost::contract::exit_invariant_failure(boost::contract::from()); + BOOST_TEST(boost::contract::test::detail::oteststream::eq(out(), + "a::exit_inv_failure\n")); + + a::disable_inv_failure(); + out(""); + boost::contract::entry_invariant_failure(boost::contract::from()); + BOOST_TEST(boost::contract::test::detail::oteststream::eq(out(), + "a::inv_failure\n")); + out(""); + boost::contract::exit_invariant_failure(boost::contract::from()); + BOOST_TEST(boost::contract::test::detail::oteststream::eq(out(), + "a::inv_failure\n")); + + a::disable_failure(); + out(""); + boost::contract::precondition_failure(boost::contract::from()); + BOOST_TEST(boost::contract::test::detail::oteststream::eq(out(), + "a::failure\n")); + out(""); + boost::contract::postcondition_failure(boost::contract::from()); + BOOST_TEST(boost::contract::test::detail::oteststream::eq(out(), + "a::failure\n")); + out(""); + boost::contract::entry_invariant_failure(boost::contract::from()); + BOOST_TEST(boost::contract::test::detail::oteststream::eq(out(), + "a::failure\n")); + out(""); + boost::contract::exit_invariant_failure(boost::contract::from()); + BOOST_TEST(boost::contract::test::detail::oteststream::eq(out(), + "a::failure\n")); + + // 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()); + + #undef BOOST_CONTRACT_TEST_old + return boost::report_errors(); +} + diff --git a/src/boost/libs/contract/test/disable/lib_b.cpp b/src/boost/libs/contract/test/disable/lib_b.cpp new file mode 100644 index 000000000..7d9a94a94 --- /dev/null +++ b/src/boost/libs/contract/test/disable/lib_b.cpp @@ -0,0 +1,9 @@ + +// Copyright (C) 2008-2018 Lorenzo Caminiti +// Distributed under the Boost Software License, Version 1.0 (see accompanying +// file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt). +// See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html + +#define BOOST_CONTRACT_TEST_LIB_B_SOURCE +#include "lib_b_inlined.hpp" + diff --git a/src/boost/libs/contract/test/disable/lib_b.hpp b/src/boost/libs/contract/test/disable/lib_b.hpp new file mode 100644 index 000000000..8cc34cbc3 --- /dev/null +++ b/src/boost/libs/contract/test/disable/lib_b.hpp @@ -0,0 +1,41 @@ + +#ifndef BOOST_CONTRACT_TEST_LIB_B_HPP_ +#define BOOST_CONTRACT_TEST_LIB_B_HPP_ + +// Copyright (C) 2008-2018 Lorenzo Caminiti +// Distributed under the Boost Software License, Version 1.0 (see accompanying +// file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt). +// See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html + +#include <boost/config.hpp> + +#ifdef BOOST_CONTRACT_TEST_LIB_B_DYN_LINK + #ifdef BOOST_CONTRACT_TEST_LIB_B_SOURCE + #define BOOST_CONTRACT_TEST_LIB_B_DECLSPEC BOOST_SYMBOL_EXPORT + #else + #define BOOST_CONTRACT_TEST_LIB_B_DECLSPEC BOOST_SYMBOL_IMPORT + #endif +#else + #define BOOST_CONTRACT_TEST_LIB_B_DECLSPEC /* nothing */ +#endif + +bool BOOST_CONTRACT_TEST_LIB_B_DECLSPEC call_f(); + +struct BOOST_CONTRACT_TEST_LIB_B_DECLSPEC 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/src/boost/libs/contract/test/disable/lib_b_inlined.hpp b/src/boost/libs/contract/test/disable/lib_b_inlined.hpp new file mode 100644 index 000000000..0a7bf5a9c --- /dev/null +++ b/src/boost/libs/contract/test/disable/lib_b_inlined.hpp @@ -0,0 +1,124 @@ + +#ifndef BOOST_CONTRACT_TEST_LIB_B_INLINED_HPP_ +#define BOOST_CONTRACT_TEST_LIB_B_INLINED_HPP_ + +// Copyright (C) 2008-2018 Lorenzo Caminiti +// Distributed under the Boost Software License, Version 1.0 (see accompanying +// file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt). +// See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html + +#include "lib_b.hpp" +#include "lib_a.hpp" +#include "../detail/oteststream.hpp" +#include <boost/contract.hpp> // All headers to test ODR for entire lib. + +bool call_f() { + a aa; + a::x_type x; x.value = -123; + return aa.f(x) == -123; +} + +void b::static_invariant() { + using boost::contract::test::detail::out; + out("b::static_inv\n"); +} + +void b::invariant() const { + using boost::contract::test::detail::out; + out("b::inv\n"); +} + +void b::g() { + using boost::contract::test::detail::out; + boost::contract::check 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() { + using boost::contract::test::detail::out; + a::disable_pre_failure(); + out(""); + boost::contract::precondition_failure(boost::contract::from()); + return boost::contract::test::detail::oteststream::eq(out(), + "a::pre_failure\n"); +} + +bool b::test_disable_post_failure() { + using boost::contract::test::detail::out; + a::disable_post_failure(); + out(""); + boost::contract::postcondition_failure(boost::contract::from()); + return boost::contract::test::detail::oteststream::eq(out(), + "a::post_failure\n"); +} + +bool b::test_disable_entry_inv_failure() { + using boost::contract::test::detail::out; + a::disable_entry_inv_failure(); + out(""); + boost::contract::entry_invariant_failure(boost::contract::from()); + return boost::contract::test::detail::oteststream::eq(out(), + "a::entry_inv_failure\n"); +} + +bool b::test_disable_exit_inv_failure() { + using boost::contract::test::detail::out; + a::disable_exit_inv_failure(); + out(""); + boost::contract::exit_invariant_failure(boost::contract::from()); + return boost::contract::test::detail::oteststream::eq(out(), + "a::exit_inv_failure\n"); +} + +bool b::test_disable_inv_failure() { + using boost::contract::test::detail::out; + + a::disable_inv_failure(); + out(""); + boost::contract::entry_invariant_failure(boost::contract::from()); + bool entry_inv = boost::contract::test::detail::oteststream::eq(out(), + "a::inv_failure\n"); + out(""); + boost::contract::exit_invariant_failure(boost::contract::from()); + bool exit_inv = boost::contract::test::detail::oteststream::eq(out(), + "a::inv_failure\n"); + + return entry_inv && exit_inv; +} + +bool b::test_disable_failure() { + using boost::contract::test::detail::out; + + a::disable_failure(); + out(""); + boost::contract::precondition_failure(boost::contract::from()); + bool pre = boost::contract::test::detail::oteststream::eq(out(), + "a::failure\n"); + out(""); + boost::contract::postcondition_failure(boost::contract::from()); + bool post = boost::contract::test::detail::oteststream::eq(out(), + "a::failure\n"); + out(""); + boost::contract::entry_invariant_failure(boost::contract::from()); + bool entry_inv = boost::contract::test::detail::oteststream::eq(out(), + "a::failure\n"); + out(""); + boost::contract::exit_invariant_failure(boost::contract::from()); + bool exit_inv = boost::contract::test::detail::oteststream::eq(out(), + "a::failure\n"); + + return pre && post && entry_inv && exit_inv; +} + +#endif // #include guard + diff --git a/src/boost/libs/contract/test/disable/lib_x.cpp b/src/boost/libs/contract/test/disable/lib_x.cpp new file mode 100644 index 000000000..e928b47e2 --- /dev/null +++ b/src/boost/libs/contract/test/disable/lib_x.cpp @@ -0,0 +1,29 @@ + +// Copyright (C) 2008-2018 Lorenzo Caminiti +// Distributed under the Boost Software License, Version 1.0 (see accompanying +// file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt). +// See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html + +// Force .cpp never check post/except. +#ifndef BOOST_CONTRACT_NO_POSTCONDITIONS + #error "build must define NO_POSTCONDITIONS" +#endif +#ifndef BOOST_CONTRACT_NO_EXCEPTS + #error "build must define NO_EXCEPTS" +#endif + +#define BOOST_CONTRACT_TEST_LIB_X_SOURCE +#include "lib_x.hpp" +#include <boost/contract.hpp> // All headers so test ODR for entire lib. +#include "../detail/out_inlined.hpp" + +void x() { + using boost::contract::test::detail::out; + boost::contract::check c = boost::contract::function() + .precondition([] { out("x::pre\n"); }) + .old([] { out("x::old\n"); }) + .postcondition([] { out("x::post\n"); }) + ; + out("x::body\n"); +} + diff --git a/src/boost/libs/contract/test/disable/lib_x.hpp b/src/boost/libs/contract/test/disable/lib_x.hpp new file mode 100644 index 000000000..e64a74ccd --- /dev/null +++ b/src/boost/libs/contract/test/disable/lib_x.hpp @@ -0,0 +1,30 @@ + +#ifndef BOOST_CONTRACT_TEST_LIB_X_HPP_ +#define BOOST_CONTRACT_TEST_LIB_X_HPP_ + +// Copyright (C) 2008-2018 Lorenzo Caminiti +// Distributed under the Boost Software License, Version 1.0 (see accompanying +// file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt). +// See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html + +#include <boost/config.hpp> +#include <string> + +#ifdef BOOST_CONTRACT_TEST_LIB_X_DYN_LINK + #ifdef BOOST_CONTRACT_TEST_LIB_X_SOURCE + #define BOOST_CONTRACT_TEST_LIB_X_DECLSPEC BOOST_SYMBOL_EXPORT + #else + #define BOOST_CONTRACT_TEST_LIB_X_DECLSPEC BOOST_SYMBOL_IMPORT + #endif +#else + #define BOOST_CONTRACT_TEST_LIB_X_DECLSPEC /* nothing */ +#endif + +#define BOOST_CONTRACT_TEST_DETAIL_OUT_DECLSPEC \ + BOOST_CONTRACT_TEST_LIB_X_DECLSPEC +#include "../detail/out.hpp" + +void BOOST_CONTRACT_TEST_LIB_X_DECLSPEC x(); + +#endif + diff --git a/src/boost/libs/contract/test/disable/lib_xy.hpp b/src/boost/libs/contract/test/disable/lib_xy.hpp new file mode 100644 index 000000000..0c52262e2 --- /dev/null +++ b/src/boost/libs/contract/test/disable/lib_xy.hpp @@ -0,0 +1,76 @@ + +// Copyright (C) 2008-2018 Lorenzo Caminiti +// Distributed under the Boost Software License, Version 1.0 (see accompanying +// file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt). +// See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html + +// Test contracts in .cpp compiled to never check post/except (but not in .hpp). + +#include "lib_x.hpp" +#include "lib_y.hpp" +#include "../detail/oteststream.hpp" +#include <boost/contract/function.hpp> +#include <boost/contract/check.hpp> +#include <boost/detail/lightweight_test.hpp> +#include <sstream> + +void f() { + using boost::contract::test::detail::out; + boost::contract::check c = boost::contract::function() + // Capturing [&] so out() visible in MSVC10 lambdas. + .precondition([&] { out("f::pre\n"); }) + .old([&] { out("f::old\n"); }) + .postcondition([&] { out("f::post\n"); }) + ; + out("f::body\n"); +} + +int main() { + using boost::contract::test::detail::out; + std::ostringstream ok; + + out(""); + f(); + ok.str(""); ok // Test normal (no lib) case. + #ifndef BOOST_CONTRACT_NO_PRECONDITIONS + << "f::pre" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_OLDS + << "f::old" << std::endl + #endif + << "f::body" << std::endl + #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS + << "f::post" << std::endl + #endif + ; + BOOST_TEST(boost::contract::test::detail::oteststream::eq(out(), ok.str())); + + out(""); + x(); + ok.str(""); ok // Test contracts in .cpp so no post (NO_POST in build file). + #ifndef BOOST_CONTRACT_NO_PRECONDITIONS + << "x::pre" << std::endl + #endif + << "x::body" << std::endl + ; + BOOST_TEST(boost::contract::test::detail::oteststream::eq(out(), ok.str())); + + out(""); + y(); + ok.str(""); ok // Test contracts in .hpp so post (NO_POST in build file). + #ifndef BOOST_CONTRACT_NO_PRECONDITIONS + << "y::pre" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_OLDS + << "y::old" << std::endl + #endif + << "y::body" << std::endl + #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS + << "y::post" << std::endl + #endif + ; + BOOST_TEST(boost::contract::test::detail::oteststream::eq(out(), ok.str())); + + return boost::report_errors(); +} + diff --git a/src/boost/libs/contract/test/disable/lib_y.cpp b/src/boost/libs/contract/test/disable/lib_y.cpp new file mode 100644 index 000000000..eade2541e --- /dev/null +++ b/src/boost/libs/contract/test/disable/lib_y.cpp @@ -0,0 +1,24 @@ + +// Copyright (C) 2008-2018 Lorenzo Caminiti +// Distributed under the Boost Software License, Version 1.0 (see accompanying +// file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt). +// See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html + +// Force .cpp never check post/except. +#ifndef BOOST_CONTRACT_NO_POSTCONDITIONS + #error "build must define NO_POSTCONDITIONS" +#endif +#ifndef BOOST_CONTRACT_NO_EXCEPTS + #error "build must define NO_EXCEPTS" +#endif + +#define BOOST_CONTRACT_TEST_LIB_Y_SOURCE +#include "lib_y.hpp" + +namespace lib_y_ { + void y_body() { + using boost::contract::test::detail::out; + out("y::body\n"); + } +} + diff --git a/src/boost/libs/contract/test/disable/lib_y.hpp b/src/boost/libs/contract/test/disable/lib_y.hpp new file mode 100644 index 000000000..f24440963 --- /dev/null +++ b/src/boost/libs/contract/test/disable/lib_y.hpp @@ -0,0 +1,40 @@ + +#ifndef BOOST_CONTRACT_TEST_LIB_Y_HPP_ +#define BOOST_CONTRACT_TEST_LIB_Y_HPP_ + +// Copyright (C) 2008-2018 Lorenzo Caminiti +// Distributed under the Boost Software License, Version 1.0 (see accompanying +// file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt). +// See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html + +#include "lib_x.hpp" +#include <boost/contract.hpp> // All headers so test ODR for entire lib. +#include <boost/config.hpp> + +#ifdef BOOST_CONTRACT_TEST_LIB_Y_DYN_LINK + #ifdef BOOST_CONTRACT_TEST_LIB_Y_SOURCE + #define BOOST_CONTRACT_TEST_LIB_Y_DECLSPEC BOOST_SYMBOL_EXPORT + #else + #define BOOST_CONTRACT_TEST_LIB_Y_DECLSPEC BOOST_SYMBOL_IMPORT + #endif +#else + #define BOOST_CONTRACT_TEST_LIB_Y_DECLSPEC /* nothing */ +#endif + +namespace lib_y_ { // Internal namepsace. + void BOOST_CONTRACT_TEST_LIB_Y_DECLSPEC y_body(); +} + +inline void y() { + using boost::contract::test::detail::out; + boost::contract::check c = boost::contract::function() + // Capturing [&] so out() visible in MSVC10 lambdas. + .precondition([&] { out("y::pre\n"); }) + .old([&] { out("y::old\n"); }) + .postcondition([&] { out("y::post\n"); }) + ; + lib_y_::y_body(); +} + +#endif + diff --git a/src/boost/libs/contract/test/disable/no_post_except_lib.cpp b/src/boost/libs/contract/test/disable/no_post_except_lib.cpp new file mode 100644 index 000000000..eaa52e38f --- /dev/null +++ b/src/boost/libs/contract/test/disable/no_post_except_lib.cpp @@ -0,0 +1,10 @@ + +// Copyright (C) 2008-2018 Lorenzo Caminiti +// Distributed under the Boost Software License, Version 1.0 (see accompanying +// file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt). +// See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html + +// Test contracts in .cpp compiled to never check post/except (but not in .hpp). + +#include "lib_xy.hpp" + diff --git a/src/boost/libs/contract/test/disable/no_post_except_unit.cpp b/src/boost/libs/contract/test/disable/no_post_except_unit.cpp new file mode 100644 index 000000000..c5db4a7ee --- /dev/null +++ b/src/boost/libs/contract/test/disable/no_post_except_unit.cpp @@ -0,0 +1,10 @@ + +// Copyright (C) 2008-2018 Lorenzo Caminiti +// Distributed under the Boost Software License, Version 1.0 (see accompanying +// file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt). +// See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html + +// Test .cpp never check post/except (in multiple compilation units). + +#include "lib_xy.hpp" + diff --git a/src/boost/libs/contract/test/disable/nothing_for_pre_prog.cpp b/src/boost/libs/contract/test/disable/nothing_for_pre_prog.cpp new file mode 100644 index 000000000..c8286f727 --- /dev/null +++ b/src/boost/libs/contract/test/disable/nothing_for_pre_prog.cpp @@ -0,0 +1,13 @@ + +// Copyright (C) 2008-2018 Lorenzo Caminiti +// Distributed under the Boost Software License, Version 1.0 (see accompanying +// file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt). +// See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html + +// Test pre disable no assertion (in programs, but same for libraries). + +#ifndef BOOST_CONTRACT_PRECONDITIONS_DISABLE_NO_ASSERTION + #error "build must define PRECONDITIONS_DISABLE_NO_ASSERTION" +#endif +#include "prog.hpp" + diff --git a/src/boost/libs/contract/test/disable/other_assertions_lib.cpp b/src/boost/libs/contract/test/disable/other_assertions_lib.cpp new file mode 100644 index 000000000..2e68b943c --- /dev/null +++ b/src/boost/libs/contract/test/disable/other_assertions_lib.cpp @@ -0,0 +1,10 @@ + +// Copyright (C) 2008-2018 Lorenzo Caminiti +// Distributed under the Boost Software License, Version 1.0 (see accompanying +// file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt). +// See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html + +// Test assertion checking disables other assertion checking (in libraries). + +#include "lib_ab.hpp" + diff --git a/src/boost/libs/contract/test/disable/other_assertions_prog.cpp b/src/boost/libs/contract/test/disable/other_assertions_prog.cpp new file mode 100644 index 000000000..b5fc359c0 --- /dev/null +++ b/src/boost/libs/contract/test/disable/other_assertions_prog.cpp @@ -0,0 +1,10 @@ + +// Copyright (C) 2008-2018 Lorenzo Caminiti +// Distributed under the Boost Software License, Version 1.0 (see accompanying +// file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt). +// See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html + +// Test assertion checking disables other assertion checking (in programs). + +#include "prog.hpp" + diff --git a/src/boost/libs/contract/test/disable/other_assertions_unit.cpp b/src/boost/libs/contract/test/disable/other_assertions_unit.cpp new file mode 100644 index 000000000..c1bdea41b --- /dev/null +++ b/src/boost/libs/contract/test/disable/other_assertions_unit.cpp @@ -0,0 +1,10 @@ + +// Copyright (C) 2008-2018 Lorenzo Caminiti +// Distributed under the Boost Software License, Version 1.0 (see accompanying +// file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt). +// See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html + +// Test assertions disables other assertions (in multiple compilation units). + +#include "lib_ab.hpp" + diff --git a/src/boost/libs/contract/test/disable/prog.hpp b/src/boost/libs/contract/test/disable/prog.hpp new file mode 100644 index 000000000..a20bb723b --- /dev/null +++ b/src/boost/libs/contract/test/disable/prog.hpp @@ -0,0 +1,13 @@ + +// Copyright (C) 2008-2018 Lorenzo Caminiti +// Distributed under the Boost Software License, Version 1.0 (see accompanying +// file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt). +// See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html + +#include "lib_a.hpp" +#include "lib_a_inlined.hpp" +#include "lib_b.hpp" +#include "lib_b_inlined.hpp" +#include "lib_ab.hpp" +#include "../detail/out_inlined.hpp" + diff --git a/src/boost/libs/contract/test/function/decl.hpp b/src/boost/libs/contract/test/function/decl.hpp new file mode 100644 index 000000000..360f7c5d6 --- /dev/null +++ b/src/boost/libs/contract/test/function/decl.hpp @@ -0,0 +1,40 @@ + +#ifndef BOOST_CONTRACT_TEST_FUNCTION_DECL_HPP_ +#define BOOST_CONTRACT_TEST_FUNCTION_DECL_HPP_ + +// Copyright (C) 2008-2018 Lorenzo Caminiti +// Distributed under the Boost Software License, Version 1.0 (see accompanying +// file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt). +// See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html + +// Test with and without pre and post declarations. + +#include "../detail/oteststream.hpp" +#include <boost/contract/function.hpp> +#include <boost/contract/check.hpp> +#include <boost/contract/assert.hpp> + +boost::contract::test::detail::oteststream out; + +bool f_pre = true, f_post = true; +void f() { + boost::contract::check c = boost::contract::function() + #ifndef BOOST_CONTRACT_TEST_NO_F_PRE + .precondition([] { + out << "f::pre" << std::endl; + BOOST_CONTRACT_ASSERT(f_pre); + }) + #endif + .old([] { out << "f::old" << std::endl; }) + #ifndef BOOST_CONTRACT_TEST_NO_F_POST + .postcondition([] { + out << "f::post" << std::endl; + BOOST_CONTRACT_ASSERT(f_post); + }) + #endif + ; + out << "f::body" << std::endl; +} + +#endif // #include guard + diff --git a/src/boost/libs/contract/test/function/decl_post_all.cpp b/src/boost/libs/contract/test/function/decl_post_all.cpp new file mode 100644 index 000000000..59dce860a --- /dev/null +++ b/src/boost/libs/contract/test/function/decl_post_all.cpp @@ -0,0 +1,64 @@ + +// Copyright (C) 2008-2018 Lorenzo Caminiti +// Distributed under the Boost Software License, Version 1.0 (see accompanying +// file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt). +// See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html + +// Test with postconditions. + +#undef BOOST_CONTRACT_TEST_NO_F_POST +#include "decl.hpp" + +#include <boost/detail/lightweight_test.hpp> +#include <sstream> +#include <string> + +std::string ok_f() { + std::ostringstream ok; ok + #ifndef BOOST_CONTRACT_NO_PRECONDITIONS + << "f::pre" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_OLDS + << "f::old" << std::endl + #endif + << "f::body" << std::endl + #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS + << "f::post" << std::endl // This can fail. + #endif + ; + return ok.str(); +} + +struct err {}; // Global decl so visible in MSVC10 lambdas. + +int main() { + std::ostringstream ok; + + f_post = true; + out.str(""); + f(); + ok.str(""); ok // Test nothing failed. + << ok_f() + ; + BOOST_TEST(out.eq(ok.str())); + + boost::contract::set_postcondition_failure( + [] (boost::contract::from) { throw err(); }); + + f_post = false; + out.str(""); + try { + f(); + #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS + BOOST_TEST(false); + } catch(err const&) { + #endif + ok.str(""); ok + << ok_f() // Test f::post failed. + ; + BOOST_TEST(out.eq(ok.str())); + } catch(...) { BOOST_TEST(false); } + + return boost::report_errors(); +} + diff --git a/src/boost/libs/contract/test/function/decl_post_none.cpp b/src/boost/libs/contract/test/function/decl_post_none.cpp new file mode 100644 index 000000000..514e98581 --- /dev/null +++ b/src/boost/libs/contract/test/function/decl_post_none.cpp @@ -0,0 +1,38 @@ + +// Copyright (C) 2008-2018 Lorenzo Caminiti +// Distributed under the Boost Software License, Version 1.0 (see accompanying +// file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt). +// See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html + +// Test without postconditions. + +#define BOOST_CONTRACT_TEST_NO_F_POST +#include "decl.hpp" + +#include <boost/detail/lightweight_test.hpp> +#include <sstream> + +int main() { + std::ostringstream ok; ok // Test nothing fails. + #ifndef BOOST_CONTRACT_NO_PRECONDITIONS + << "f::pre" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_OLDS + << "f::old" << std::endl + #endif + << "f::body" << std::endl + ; + + f_post = true; + out.str(""); + f(); + BOOST_TEST(out.eq(ok.str())); + + f_post = false; + out.str(""); + f(); + BOOST_TEST(out.eq(ok.str())); + + return boost::report_errors(); +} + diff --git a/src/boost/libs/contract/test/function/decl_pre_all.cpp b/src/boost/libs/contract/test/function/decl_pre_all.cpp new file mode 100644 index 000000000..1ff33a55b --- /dev/null +++ b/src/boost/libs/contract/test/function/decl_pre_all.cpp @@ -0,0 +1,73 @@ + +// Copyright (C) 2008-2018 Lorenzo Caminiti +// Distributed under the Boost Software License, Version 1.0 (see accompanying +// file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt). +// See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html + +// Test with preconditions. + +#undef BOOST_CONTRACT_TEST_NO_F_PRE +#include "decl.hpp" + +#include <boost/detail/lightweight_test.hpp> +#include <sstream> +#include <string> + +std::string ok_f(bool failed = false) { + std::ostringstream ok; ok << "" // Suppress a warning. + #ifndef BOOST_CONTRACT_NO_PRECONDITIONS + << "f::pre" << std::endl // Test no failure here. + #endif + ; + if(!failed) ok + #ifndef BOOST_CONTRACT_NO_OLDS + << "f::old" << std::endl + #endif + << "f::body" << std::endl + #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS + << "f::post" << std::endl + #endif + ; + return ok.str(); +} + +struct err {}; // Global decl so visible in MSVC10 lambdas. + +int main() { + std::ostringstream ok; + + f_pre = true; + out.str(""); + f(); + ok.str(""); ok + << ok_f() + ; + BOOST_TEST(out.eq(ok.str())); + + #ifdef BOOST_CONTRACT_NO_PRECONDITIONS + #define BOOST_CONTRACT_TEST_pre 0 + #else + #define BOOST_CONTRACT_TEST_pre 1 + #endif + + boost::contract::set_precondition_failure( + [] (boost::contract::from) { throw err(); }); + + f_pre = false; + out.str(""); + try { + f(); + #ifndef BOOST_CONTRACT_NO_PRECONDITIONS + BOOST_TEST(false); + } catch(err const&) { + #endif + ok.str(""); ok + << ok_f(BOOST_CONTRACT_TEST_pre) + ; + BOOST_TEST(out.eq(ok.str())); + } catch(...) { BOOST_TEST(false); } + + #undef BOOST_CONTRACT_TEST_pre + return boost::report_errors(); +} + diff --git a/src/boost/libs/contract/test/function/decl_pre_none.cpp b/src/boost/libs/contract/test/function/decl_pre_none.cpp new file mode 100644 index 000000000..a9c511322 --- /dev/null +++ b/src/boost/libs/contract/test/function/decl_pre_none.cpp @@ -0,0 +1,38 @@ + +// Copyright (C) 2008-2018 Lorenzo Caminiti +// Distributed under the Boost Software License, Version 1.0 (see accompanying +// file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt). +// See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html + +// Test without preconditions. + +#define BOOST_CONTRACT_TEST_NO_F_PRE +#include "decl.hpp" + +#include <boost/detail/lightweight_test.hpp> +#include <sstream> + +int main() { + std::ostringstream ok; ok // Test nothing fails. + #ifndef BOOST_CONTRACT_NO_OLDS + << "f::old" << std::endl + #endif + << "f::body" << std::endl + #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS + << "f::post" << std::endl + #endif + ; + + f_pre = true; + out.str(""); + f(); + BOOST_TEST(out.eq(ok.str())); + + f_pre = false; + out.str(""); + f(); + BOOST_TEST(out.eq(ok.str())); + + return boost::report_errors(); +} + diff --git a/src/boost/libs/contract/test/function/ifdef.cpp b/src/boost/libs/contract/test/function/ifdef.cpp new file mode 100644 index 000000000..fe9a1ceeb --- /dev/null +++ b/src/boost/libs/contract/test/function/ifdef.cpp @@ -0,0 +1,58 @@ + +// Copyright (C) 2008-2018 Lorenzo Caminiti +// Distributed under the Boost Software License, Version 1.0 (see accompanying +// file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt). +// See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html + +// Test contract compilation on/off. + +#include "../detail/oteststream.hpp" +#include <boost/contract/core/config.hpp> +#ifndef BOOST_CONTRACT_NO_FUNCTIONS + #include <boost/contract/function.hpp> + #include <boost/contract/check.hpp> + #include <boost/contract/old.hpp> +#endif +#include <boost/detail/lightweight_test.hpp> +#include <sstream> + +boost::contract::test::detail::oteststream out; + +void f(int x) { + #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS + boost::contract::old_ptr<int> old_x = BOOST_CONTRACT_OLDOF(x); + #endif + #ifndef BOOST_CONTRACT_NO_FUNCTIONS + boost::contract::check c = boost::contract::function() + #ifndef BOOST_CONTRACT_NO_PRECONDITIONS + .precondition([] { out << "f::pre" << std::endl; }) + #endif + #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS + .old([] { out << "f::old" << std::endl; }) + .postcondition([] { out << "f::post" << std::endl; }) + #endif + ; + #endif + out << "f::body" << std::endl; +} + +int main() { + std::ostringstream ok; + out.str(""); + f(123); + ok.str(""); ok + #ifndef BOOST_CONTRACT_NO_PRECONDITIONS + << "f::pre" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS + << "f::old" << std::endl + #endif + << "f::body" << std::endl + #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS + << "f::post" << std::endl + #endif + ; + BOOST_TEST(out.eq(ok.str())); + return boost::report_errors(); +} + diff --git a/src/boost/libs/contract/test/function/ifdef_macro.cpp b/src/boost/libs/contract/test/function/ifdef_macro.cpp new file mode 100644 index 000000000..ffd7e668d --- /dev/null +++ b/src/boost/libs/contract/test/function/ifdef_macro.cpp @@ -0,0 +1,95 @@ + +// Copyright (C) 2008-2018 Lorenzo Caminiti +// Distributed under the Boost Software License, Version 1.0 (see accompanying +// file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt). +// See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html + +// Test contract compilation on/off (including EXCEPT, using macro interface). + +#include "../detail/oteststream.hpp" +#include "../detail/unprotected_commas.hpp" +#include <boost/contract_macro.hpp> +#include <boost/detail/lightweight_test.hpp> +#include <sstream> + +boost::contract::test::detail::oteststream out; + +struct except_error {}; + +void f(int x) { + BOOST_CONTRACT_OLD_PTR( + boost::contract::test::detail::unprotected_commas<int, void, void>:: + type1 + )( + old_x, + (boost::contract::test::detail::unprotected_commas<void, void, void>:: + same(x)) + ); + BOOST_CONTRACT_FUNCTION() + BOOST_CONTRACT_PRECONDITION([] { + boost::contract::test::detail::unprotected_commas<void, void, void> + ::call(); + out << "f::pre" << std::endl; + }) + BOOST_CONTRACT_OLD([] { + boost::contract::test::detail::unprotected_commas<void, void, void> + ::call(); + out << "f::old" << std::endl; + }) + BOOST_CONTRACT_POSTCONDITION([] { + boost::contract::test::detail::unprotected_commas<void, void, void> + ::call(); + out << "f::post" << std::endl; + }) + BOOST_CONTRACT_EXCEPT([] { // Test EXCEPT macro (at least 1 time here). + boost::contract::test::detail::unprotected_commas<void, void, void> + ::call(); + out << "f::except" << std::endl; + }) + ; + out << "f::body" << std::endl; + if(x == -1) throw except_error(); +} + +int main() { + std::ostringstream ok; + + out.str(""); + f(123); + ok.str(""); ok + #ifndef BOOST_CONTRACT_NO_PRECONDITIONS + << "f::pre" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_OLDS + << "f::old" << std::endl + #endif + << "f::body" << std::endl + #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS + << "f::post" << std::endl + #endif + ; + BOOST_TEST(out.eq(ok.str())); + + boost::contract::set_except_failure([] (boost::contract::from) {}); + out.str(""); + try { + f(-1); // Test throw and EXCEPT macro (test only here... that's fine). + BOOST_TEST(false); + } catch(except_error const&) {} // OK. + ok.str(""); ok + #ifndef BOOST_CONTRACT_NO_PRECONDITIONS + << "f::pre" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_OLDS + << "f::old" << std::endl + #endif + << "f::body" << std::endl + #ifndef BOOST_CONTRACT_NO_EXCEPTS + << "f::except" << std::endl + #endif + ; + BOOST_TEST(out.eq(ok.str())); + + return boost::report_errors(); +} + diff --git a/src/boost/libs/contract/test/function/smoke.cpp b/src/boost/libs/contract/test/function/smoke.cpp new file mode 100644 index 000000000..a4a733fd7 --- /dev/null +++ b/src/boost/libs/contract/test/function/smoke.cpp @@ -0,0 +1,99 @@ + +// Copyright (C) 2008-2018 Lorenzo Caminiti +// Distributed under the Boost Software License, Version 1.0 (see accompanying +// file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt). +// See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html + +// Test free function contracts. + +#include "../detail/oteststream.hpp" +#include "../detail/counter.hpp" +#include <boost/contract/function.hpp> +#include <boost/contract/old.hpp> +#include <boost/contract/assert.hpp> +#include <boost/contract/check.hpp> +#include <boost/preprocessor/control/iif.hpp> +#include <boost/detail/lightweight_test.hpp> +#include <sstream> + +boost::contract::test::detail::oteststream out; + +struct x_tag; typedef boost::contract::test::detail::counter<x_tag, int> x_type; +struct y_tag; typedef boost::contract::test::detail::counter<y_tag, int> y_type; + +bool swap(x_type& x, y_type& y) { + bool result; + boost::contract::old_ptr<x_type> old_x = + BOOST_CONTRACT_OLDOF(x_type::eval(x)); + boost::contract::old_ptr<y_type> old_y; + boost::contract::check c = boost::contract::function() + .precondition([&] { + out << "swap::pre" << std::endl; + BOOST_CONTRACT_ASSERT(x.value != y.value); + }) + .old([&] { + out << "swap::old" << std::endl; + old_y = BOOST_CONTRACT_OLDOF(y_type::eval(y)); + }) + .postcondition([&] { + out << "swap::post" << std::endl; + BOOST_CONTRACT_ASSERT(x.value == old_y->value); + BOOST_CONTRACT_ASSERT(y.value == old_x->value); + BOOST_CONTRACT_ASSERT(result == (old_x->value != old_y->value)); + }) + ; + + out << "swap::body" << std::endl; + if(x.value == y.value) return result = false; + int save_x = x.value; + x.value = y.value; + y.value = save_x; + return result = true; +} + +int main() { + std::ostringstream ok; + + { + x_type x; x.value = 123; + y_type y; y.value = 456; + + out.str(""); + bool r = swap(x, y); + ok.str(""); ok + #ifndef BOOST_CONTRACT_NO_PRECONDITIONS + << "swap::pre" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_OLDS + << "swap::old" << std::endl + #endif + << "swap::body" << std::endl + #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS + << "swap::post" << std::endl + #endif + ; + BOOST_TEST(out.eq(ok.str())); + + BOOST_TEST(r); + BOOST_TEST_EQ(x.value, 456); + BOOST_TEST_EQ(y.value, 123); + } + + #ifndef BOOST_CONTRACT_NO_OLDS + #define BOOST_CONTRACT_TEST_old 1u + #else + #define BOOST_CONTRACT_TEST_old 0u + #endif + + BOOST_TEST_EQ(x_type::copies(), BOOST_CONTRACT_TEST_old); + BOOST_TEST_EQ(x_type::evals(), BOOST_CONTRACT_TEST_old); + BOOST_TEST_EQ(x_type::ctors(), x_type::dtors()); // No leak. + + BOOST_TEST_EQ(y_type::copies(), BOOST_CONTRACT_TEST_old); + BOOST_TEST_EQ(y_type::evals(), BOOST_CONTRACT_TEST_old); + BOOST_TEST_EQ(y_type::ctors(), y_type::dtors()); // No leak. + + #undef BOOST_CONTRACT_TEST_old + return boost::report_errors(); +} + diff --git a/src/boost/libs/contract/test/function/throwing_body.cpp b/src/boost/libs/contract/test/function/throwing_body.cpp new file mode 100644 index 000000000..7a64ba1de --- /dev/null +++ b/src/boost/libs/contract/test/function/throwing_body.cpp @@ -0,0 +1,55 @@ + +// Copyright (C) 2008-2018 Lorenzo Caminiti +// Distributed under the Boost Software License, Version 1.0 (see accompanying +// file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt). +// See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html + +// Test throw from free function body. + +#include "../detail/oteststream.hpp" +#include <boost/contract/function.hpp> +#include <boost/contract/check.hpp> +#include <boost/detail/lightweight_test.hpp> +#include <sstream> + +boost::contract::test::detail::oteststream out; + +struct err {}; // Global decl so visible in MSVC10 lambdas. + +void f() { + boost::contract::check c = boost::contract::function() + .precondition([] { out << "f::pre" << std::endl; }) + .old([] { out << "f::old" << std::endl; }) + .postcondition([] { out << "f::post" << std::endl; }) + .except([] { out << "f::except" << std::endl; }) + ; + out << "f::body" << std::endl; + throw err(); // Test body throws. +} + +int main() { + std::ostringstream ok; + + try { + out.str(""); + f(); + BOOST_TEST(false); + } catch(err const&) { + ok.str(""); ok + #ifndef BOOST_CONTRACT_NO_PRECONDITIONS + << "f::pre" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_OLDS + << "f::old" << std::endl + #endif + << "f::body" << std::endl // Test this threw. + #ifndef BOOST_CONTRACT_NO_EXCEPTS + << "f::except" << std::endl; + #endif + ; + BOOST_TEST(out.eq(ok.str())); + } catch(...) { BOOST_TEST(false); } + + return boost::report_errors(); +} + diff --git a/src/boost/libs/contract/test/function/throwing_old.cpp b/src/boost/libs/contract/test/function/throwing_old.cpp new file mode 100644 index 000000000..9bae86625 --- /dev/null +++ b/src/boost/libs/contract/test/function/throwing_old.cpp @@ -0,0 +1,59 @@ + +// Copyright (C) 2008-2018 Lorenzo Caminiti +// Distributed under the Boost Software License, Version 1.0 (see accompanying +// file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt). +// See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html + +// Test throw from free function .old(). + +#include "../detail/oteststream.hpp" +#include <boost/contract/function.hpp> +#include <boost/contract/check.hpp> +#include <boost/detail/lightweight_test.hpp> +#include <sstream> + +boost::contract::test::detail::oteststream out; + +struct err {}; // Global decl so visible in MSVC10 lambdas. + +void f() { + boost::contract::check c = boost::contract::function() + .precondition([] { out << "f::pre" << std::endl; }) + .old([] { + out << "f::old" << std::endl; + throw err(); // Test this throws. + }) + .postcondition([] { out << "f::post" << std::endl; }) + .except([] { out << "f::except" << std::endl; }) + ; + out << "f::body" << std::endl; +} + +int main() { + std::ostringstream ok; + + boost::contract::set_old_failure([] (boost::contract::from) { throw; }); + + try { + out.str(""); + f(); + #ifndef BOOST_CONTRACT_NO_OLDS + BOOST_TEST(false); + } catch(err const&) { + #endif + ok.str(""); ok + #ifndef BOOST_CONTRACT_NO_PRECONDITIONS + << "f::pre" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_OLDS + << "f::old" << std::endl // Test this threw. + #else + << "f::body" << std::endl + #endif + ; + BOOST_TEST(out.eq(ok.str())); + } catch(...) { BOOST_TEST(false); } + + return boost::report_errors(); +} + diff --git a/src/boost/libs/contract/test/function/throwing_post.cpp b/src/boost/libs/contract/test/function/throwing_post.cpp new file mode 100644 index 000000000..16d24813d --- /dev/null +++ b/src/boost/libs/contract/test/function/throwing_post.cpp @@ -0,0 +1,62 @@ + +// Copyright (C) 2008-2018 Lorenzo Caminiti +// Distributed under the Boost Software License, Version 1.0 (see accompanying +// file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt). +// See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html + +// Test throw from free function .post(). + +#include "../detail/oteststream.hpp" +#include <boost/contract/function.hpp> +#include <boost/contract/check.hpp> +#include <boost/detail/lightweight_test.hpp> +#include <sstream> + +boost::contract::test::detail::oteststream out; + +struct err {}; // Global decl so visible in MSVC10 lambdas. + +void f() { + boost::contract::check c = boost::contract::function() + .precondition([] { out << "f::pre" << std::endl; }) + .old([] { out << "f::old" << std::endl; }) + .postcondition([] { + out << "f::post" << std::endl; + throw err(); // Test this throws. + }) + .except([] { out << "f::except" << std::endl; }) + ; + out << "f::body" << std::endl; +} + +int main() { + std::ostringstream ok; + + boost::contract::set_postcondition_failure( + [] (boost::contract::from) { throw; }); + + try { + out.str(""); + f(); + #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS + BOOST_TEST(false); + } catch(err const&) { + #endif + ok.str(""); ok << "" // Suppress a warning. + #ifndef BOOST_CONTRACT_NO_PRECONDITIONS + << "f::pre" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_OLDS + << "f::old" << std::endl + #endif + << "f::body" << std::endl + #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS + << "f::post" << std::endl // Test this threw. + #endif + ; + BOOST_TEST(out.eq(ok.str())); + } catch(...) { BOOST_TEST(false); } + + return boost::report_errors(); +} + diff --git a/src/boost/libs/contract/test/function/throwing_pre.cpp b/src/boost/libs/contract/test/function/throwing_pre.cpp new file mode 100644 index 000000000..3f2669d09 --- /dev/null +++ b/src/boost/libs/contract/test/function/throwing_pre.cpp @@ -0,0 +1,63 @@ + +// Copyright (C) 2008-2018 Lorenzo Caminiti +// Distributed under the Boost Software License, Version 1.0 (see accompanying +// file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt). +// See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html + +// Test throw from free function .pre(). + +#include "../detail/oteststream.hpp" +#include <boost/contract/function.hpp> +#include <boost/contract/check.hpp> +#include <boost/detail/lightweight_test.hpp> +#include <sstream> + +boost::contract::test::detail::oteststream out; + +struct err {}; // Global decl so visible in MSVC10 lambdas. + +void f() { + boost::contract::check c = boost::contract::function() + .precondition([] { + out << "f::pre" << std::endl; + throw err(); // Test this throws. + }) + .old([] { out << "f::old" << std::endl; }) + .postcondition([] { out << "f::post" << std::endl; }) + .except([] { out << "f::except" << std::endl; }) + ; + out << "f::body" << std::endl; +} + +int main() { + std::ostringstream ok; + + boost::contract::set_precondition_failure( + [] (boost::contract::from) { throw; }); + + try { + out.str(""); + f(); + #ifndef BOOST_CONTRACT_NO_PRECONDITIONS + BOOST_TEST(false); + } catch(err const&) { + #endif + ok.str(""); ok + #ifndef BOOST_CONTRACT_NO_PRECONDITIONS + << "f::pre" << std::endl // Test this threw. + #else + #ifndef BOOST_CONTRACT_NO_OLDS + << "f::old" << std::endl + #endif + << "f::body" << std::endl + #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS + << "f::post" << std::endl + #endif + #endif + ; + BOOST_TEST(out.eq(ok.str())); + } catch(...) { BOOST_TEST(false); } + + return boost::report_errors(); +} + diff --git a/src/boost/libs/contract/test/invariant/decl.hpp b/src/boost/libs/contract/test/invariant/decl.hpp new file mode 100644 index 000000000..b4ae9a481 --- /dev/null +++ b/src/boost/libs/contract/test/invariant/decl.hpp @@ -0,0 +1,840 @@ + +// no #include guard + +// Copyright (C) 2008-2018 Lorenzo Caminiti +// Distributed under the Boost Software License, Version 1.0 (see accompanying +// file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt). +// See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html + +// Test with and without all invariants (static/cv/const-only) declarations. + +#include "../detail/oteststream.hpp" +#include <boost/contract/base_types.hpp> +#include <boost/contract/constructor.hpp> +#include <boost/contract/destructor.hpp> +#include <boost/contract/public_function.hpp> +#include <boost/contract/function.hpp> +#include <boost/contract/override.hpp> +#include <boost/contract/check.hpp> +#include <boost/contract/assert.hpp> +#include <boost/detail/lightweight_test.hpp> +#include <sstream> + +boost::contract::test::detail::oteststream out; + +struct b : private boost::contract::constructor_precondition<b> { + // Test also with no base_types. + + #ifdef BOOST_CONTRACT_TEST_STATIC_INV + static void static_invariant() { out << "b::static_inv" << std::endl; } + #endif + #ifdef BOOST_CONTRACT_TEST_CV_INV + void invariant() const volatile { out << "b::cv_inv" << std::endl; } + #endif + #ifdef BOOST_CONTRACT_TEST_CONST_INV + void invariant() const { out << "b::const_inv" << std::endl; } + #endif + + b() : boost::contract::constructor_precondition<b>([] { + out << "b::ctor::pre" << std::endl; + }) { + boost::contract::check c = boost::contract::constructor(this) + .old([] { out << "b::ctor::old" << std::endl; }) + .postcondition([] { out << "b::ctor::post" << std::endl; }) + ; + out << "b::ctor::body" << std::endl; + } + + virtual ~b() { + boost::contract::check c = boost::contract::destructor(this) + .old([] { out << "b::dtor::old" << std::endl; }) + .postcondition([] { out << "b::dtor::post" << std::endl; }) + ; + out << "b::dtor::body" << std::endl; + } + + virtual void f(char x, boost::contract::virtual_* v = 0) volatile { + boost::contract::check c = boost::contract::public_function(v, this) + .precondition([&] { + out << "b::f::volatile_pre" << std::endl; + BOOST_CONTRACT_ASSERT(x == 'b'); + }) + .old([] { out << "b::f::volatile_old" << std::endl; }) + .postcondition([] { out << "b::f::volatile_post" << std::endl; }) + ; + out << "b::f::volatile_body" << std::endl; + } + + virtual void f(char x, boost::contract::virtual_* v = 0) { + boost::contract::check c = boost::contract::public_function(v, this) + .precondition([&] { + out << "b::f::pre" << std::endl; + BOOST_CONTRACT_ASSERT(x == 'b'); + }) + .old([] { out << "b::f::old" << std::endl; }) + .postcondition([] { out << "b::f::post" << std::endl; }) + ; + out << "b::f::body" << std::endl; + } +}; + +struct a + #define BASES private boost::contract::constructor_precondition<a>, public b + : BASES +{ + typedef BOOST_CONTRACT_BASE_TYPES(BASES) base_types; + #undef BASES + + #ifdef BOOST_CONTRACT_TEST_STATIC_INV + static void static_invariant() { out << "a::static_inv" << std::endl; } + #endif + #ifdef BOOST_CONTRACT_TEST_CV_INV + void invariant() const volatile { out << "a::cv_inv" << std::endl; } + #endif + #ifdef BOOST_CONTRACT_TEST_CONST_INV + void invariant() const { out << "a::const_inv" << std::endl; } + #endif + + a() : boost::contract::constructor_precondition<a>([] { + out << "a::ctor::pre" << std::endl; + }) { + boost::contract::check c = boost::contract::constructor(this) + .old([] { out << "a::ctor::old" << std::endl; }) + .postcondition([] { out << "a::ctor::post" << std::endl; }) + ; + out << "a::ctor::body" << std::endl; + } + + virtual ~a() { + boost::contract::check c = boost::contract::destructor(this) + .old([] { out << "a::dtor::old" << std::endl; }) + .postcondition([] { out << "a::dtor::post" << std::endl; }) + ; + out << "a::dtor::body" << std::endl; + } + + virtual void f(char x, boost::contract::virtual_* v = 0) + volatile /* override */ { + boost::contract::check c = boost::contract::public_function< + override_f>( + v, + static_cast<void (a::*)(char x, boost::contract::virtual_*) + volatile>(&a::f), + this, x + ) + .precondition([&] { + out << "a::f::volatile_pre" << std::endl; + BOOST_CONTRACT_ASSERT(x == 'a'); + }) + .old([] { out << "a::f::volatile_old" << std::endl; }) + .postcondition([] { out << "a::f::volatile_post" << std::endl; }) + ; + out << "a::f::volatile_body" << std::endl; + } + + virtual void f(char x, boost::contract::virtual_* v = 0) /* override */ { + boost::contract::check c = boost::contract::public_function< + override_f>( + v, + static_cast<void (a::*)(char x, boost::contract::virtual_*)>(&a::f), + this, x + ) + .precondition([&] { + out << "a::f::pre" << std::endl; + BOOST_CONTRACT_ASSERT(x == 'a'); + }) + .old([] { out << "a::f::old" << std::endl; }) + .postcondition([] { out << "a::f::post" << std::endl; }) + ; + out << "a::f::body" << std::endl; + } + + static void s() { + boost::contract::check c = boost::contract::public_function<a>() + .precondition([] { out << "a::s::pre" << std::endl; }) + .old([] { out << "a::s::old" << std::endl; }) + .postcondition([] { out << "a::s::post" << std::endl; }) + ; + out << "a::s::body" << std::endl; + } + +protected: + void p() volatile { + boost::contract::check c = boost::contract::function() + .precondition([] { out << "a::p::volatile_pre" << std::endl; }) + .old([] { out << "a::p::volatile_old" << std::endl; }) + .postcondition([] { out << "a::p::volatile_post" << std::endl; }) + ; + out << "a::p::volatile_body" << std::endl; + } + + void p() { + boost::contract::check c = boost::contract::function() + .precondition([] { out << "a::p::pre" << std::endl; }) + .old([] { out << "a::p::old" << std::endl; }) + .postcondition([] { out << "a::p::post" << std::endl; }) + ; + out << "a::p::body" << std::endl; + } +public: + void call_p() volatile { p(); } + void call_p() { p(); } + +private: + void q() volatile { + boost::contract::check c = boost::contract::function() + .precondition([] { out << "a::q::volatile_pre" << std::endl; }) + .old([] { out << "a::q::volatile_old" << std::endl; }) + .postcondition([] { out << "a::q::volatile_post" << std::endl; }) + ; + out << "a::q::volatile_body" << std::endl; + } + + void q() { + boost::contract::check c = boost::contract::function() + .precondition([] { out << "a::q::pre" << std::endl; }) + .old([] { out << "a::q::old" << std::endl; }) + .postcondition([] { out << "a::q::post" << std::endl; }) + ; + out << "a::q::body" << std::endl; + } +public: + void call_q() volatile { q(); } + void call_q() { q(); } + + BOOST_CONTRACT_OVERRIDE(f) +}; + +int main() { + std::ostringstream ok; + + { // Test volatile call with bases. + out.str(""); + a volatile av; + ok.str(""); ok // Ctors always check const_inv (even if volatile). + #ifndef BOOST_CONTRACT_NO_PRECONDITIONS + << "a::ctor::pre" << std::endl + << "b::ctor::pre" << std::endl + #endif + + #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS + #ifdef BOOST_CONTRACT_TEST_STATIC_INV + << "b::static_inv" << std::endl + #endif + #endif + #ifndef BOOST_CONTRACT_NO_OLDS + << "b::ctor::old" << std::endl + #endif + << "b::ctor::body" << std::endl + #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS + #ifdef BOOST_CONTRACT_TEST_STATIC_INV + << "b::static_inv" << std::endl + #endif + #ifdef BOOST_CONTRACT_TEST_CV_INV + << "b::cv_inv" << std::endl + #endif + #ifdef BOOST_CONTRACT_TEST_CONST_INV + << "b::const_inv" << std::endl + #endif + #endif + #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS + << "b::ctor::post" << std::endl + #endif + + #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS + #ifdef BOOST_CONTRACT_TEST_STATIC_INV + << "a::static_inv" << std::endl + #endif + #endif + #ifndef BOOST_CONTRACT_NO_OLDS + << "a::ctor::old" << std::endl + #endif + << "a::ctor::body" << std::endl + #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS + #ifdef BOOST_CONTRACT_TEST_STATIC_INV + << "a::static_inv" << std::endl + #endif + #ifdef BOOST_CONTRACT_TEST_CV_INV + << "a::cv_inv" << std::endl + #endif + #ifdef BOOST_CONTRACT_TEST_CONST_INV + << "a::const_inv" << std::endl + #endif + #endif + #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS + << "a::ctor::post" << std::endl + #endif + ; + BOOST_TEST(out.eq(ok.str())); + + out.str(""); + av.f('a'); + ok.str(""); ok // Volatile checks static and cv (but not const) inv. + #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS + #ifdef BOOST_CONTRACT_TEST_STATIC_INV + << "b::static_inv" << std::endl + #endif + #ifdef BOOST_CONTRACT_TEST_CV_INV + << "b::cv_inv" << std::endl + #endif + #ifdef BOOST_CONTRACT_TEST_STATIC_INV + << "a::static_inv" << std::endl + #endif + #ifdef BOOST_CONTRACT_TEST_CV_INV + << "a::cv_inv" << std::endl + #endif + #endif + #ifndef BOOST_CONTRACT_NO_PRECONDITIONS + << "b::f::volatile_pre" << std::endl + << "a::f::volatile_pre" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_OLDS + << "b::f::volatile_old" << std::endl + << "a::f::volatile_old" << std::endl + #endif + << "a::f::volatile_body" << std::endl + #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS + #ifdef BOOST_CONTRACT_TEST_STATIC_INV + << "b::static_inv" << std::endl + #endif + #ifdef BOOST_CONTRACT_TEST_CV_INV + << "b::cv_inv" << std::endl + #endif + #ifdef BOOST_CONTRACT_TEST_STATIC_INV + << "a::static_inv" << std::endl + #endif + #ifdef BOOST_CONTRACT_TEST_CV_INV + << "a::cv_inv" << std::endl + #endif + #endif + #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS + << "b::f::volatile_old" << std::endl + << "b::f::volatile_post" << std::endl + << "a::f::volatile_post" << std::endl + #endif + ; + BOOST_TEST(out.eq(ok.str())); + + out.str(""); + av.s(); // Test static call. + ok.str(""); ok + #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS + #ifdef BOOST_CONTRACT_TEST_STATIC_INV + << "a::static_inv" << std::endl + #endif + #endif + #ifndef BOOST_CONTRACT_NO_PRECONDITIONS + << "a::s::pre" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_OLDS + << "a::s::old" << std::endl + #endif + << "a::s::body" << std::endl + #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS + #ifdef BOOST_CONTRACT_TEST_STATIC_INV + << "a::static_inv" << std::endl + #endif + #endif + #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS + << "a::s::post" << std::endl + #endif + ; + BOOST_TEST(out.eq(ok.str())); + + out.str(""); + av.call_p(); // Test (indirect) protected call. + ok.str(""); ok + #ifndef BOOST_CONTRACT_NO_PRECONDITIONS + << "a::p::volatile_pre" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_OLDS + << "a::p::volatile_old" << std::endl + #endif + << "a::p::volatile_body" << std::endl + #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS + << "a::p::volatile_post" << std::endl + #endif + ; + BOOST_TEST(out.eq(ok.str())); + + out.str(""); + av.call_q(); // Test (indirect) private call. + ok.str(""); ok + #ifndef BOOST_CONTRACT_NO_PRECONDITIONS + << "a::q::volatile_pre" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_OLDS + << "a::q::volatile_old" << std::endl + #endif + << "a::q::volatile_body" << std::endl + #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS + << "a::q::volatile_post" << std::endl + #endif + ; + BOOST_TEST(out.eq(ok.str())); + + out.str(""); + } // Call a's destructor. + ok.str(""); ok // Dtors always check const_inv (even if volatile). + #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS + #ifdef BOOST_CONTRACT_TEST_STATIC_INV + << "a::static_inv" << std::endl + #endif + #ifdef BOOST_CONTRACT_TEST_CV_INV + << "a::cv_inv" << std::endl + #endif + #ifdef BOOST_CONTRACT_TEST_CONST_INV + << "a::const_inv" << std::endl + #endif + #endif + #ifndef BOOST_CONTRACT_NO_OLDS + << "a::dtor::old" << std::endl + #endif + << "a::dtor::body" << std::endl + #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS + #ifdef BOOST_CONTRACT_TEST_STATIC_INV + << "a::static_inv" << std::endl + #endif + #endif + #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS + << "a::dtor::post" << std::endl + #endif + + #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS + #ifdef BOOST_CONTRACT_TEST_STATIC_INV + << "b::static_inv" << std::endl + #endif + #ifdef BOOST_CONTRACT_TEST_CV_INV + << "b::cv_inv" << std::endl + #endif + #ifdef BOOST_CONTRACT_TEST_CONST_INV + << "b::const_inv" << std::endl + #endif + #endif + #ifndef BOOST_CONTRACT_NO_OLDS + << "b::dtor::old" << std::endl + #endif + << "b::dtor::body" << std::endl + #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS + #ifdef BOOST_CONTRACT_TEST_STATIC_INV + << "b::static_inv" << std::endl + #endif + #endif + #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS + << "b::dtor::post" << std::endl + #endif + ; + BOOST_TEST(out.eq(ok.str())); + + { // Test non-volatile call with bases. + out.str(""); + a aa; + ok.str(""); ok // Ctors always check cv_inv (even if not volatile). + #ifndef BOOST_CONTRACT_NO_PRECONDITIONS + << "a::ctor::pre" << std::endl + << "b::ctor::pre" << std::endl + #endif + + #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS + #ifdef BOOST_CONTRACT_TEST_STATIC_INV + << "b::static_inv" << std::endl + #endif + #endif + #ifndef BOOST_CONTRACT_NO_OLDS + << "b::ctor::old" << std::endl + #endif + << "b::ctor::body" << std::endl + #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS + #ifdef BOOST_CONTRACT_TEST_STATIC_INV + << "b::static_inv" << std::endl + #endif + #ifdef BOOST_CONTRACT_TEST_CV_INV + << "b::cv_inv" << std::endl + #endif + #ifdef BOOST_CONTRACT_TEST_CONST_INV + << "b::const_inv" << std::endl + #endif + #endif + #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS + << "b::ctor::post" << std::endl + #endif + + #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS + #ifdef BOOST_CONTRACT_TEST_STATIC_INV + << "a::static_inv" << std::endl + #endif + #endif + #ifndef BOOST_CONTRACT_NO_OLDS + << "a::ctor::old" << std::endl + #endif + << "a::ctor::body" << std::endl + #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS + #ifdef BOOST_CONTRACT_TEST_STATIC_INV + << "a::static_inv" << std::endl + #endif + #ifdef BOOST_CONTRACT_TEST_CV_INV + << "a::cv_inv" << std::endl + #endif + #ifdef BOOST_CONTRACT_TEST_CONST_INV + << "a::const_inv" << std::endl + #endif + #endif + #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS + << "a::ctor::post" << std::endl + #endif + ; + BOOST_TEST(out.eq(ok.str())); + + out.str(""); + aa.f('a'); + ok.str(""); ok // Non-cv checks static and const (but not cv) inv. + #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS + #ifdef BOOST_CONTRACT_TEST_STATIC_INV + << "b::static_inv" << std::endl + #endif + #ifdef BOOST_CONTRACT_TEST_CONST_INV + << "b::const_inv" << std::endl + #endif + #ifdef BOOST_CONTRACT_TEST_STATIC_INV + << "a::static_inv" << std::endl + #endif + #ifdef BOOST_CONTRACT_TEST_CONST_INV + << "a::const_inv" << std::endl + #endif + #endif + #ifndef BOOST_CONTRACT_NO_PRECONDITIONS + << "b::f::pre" << std::endl + << "a::f::pre" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_OLDS + << "b::f::old" << std::endl + << "a::f::old" << std::endl + #endif + << "a::f::body" << std::endl + #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS + #ifdef BOOST_CONTRACT_TEST_STATIC_INV + << "b::static_inv" << std::endl + #endif + #ifdef BOOST_CONTRACT_TEST_CONST_INV + << "b::const_inv" << std::endl + #endif + #ifdef BOOST_CONTRACT_TEST_STATIC_INV + << "a::static_inv" << std::endl + #endif + #ifdef BOOST_CONTRACT_TEST_CONST_INV + << "a::const_inv" << std::endl + #endif + #endif + #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS + << "b::f::old" << std::endl + << "b::f::post" << std::endl + << "a::f::post" << std::endl + #endif + ; + BOOST_TEST(out.eq(ok.str())); + + out.str(""); + aa.s(); // Test static call. + ok.str(""); ok + #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS + #ifdef BOOST_CONTRACT_TEST_STATIC_INV + << "a::static_inv" << std::endl + #endif + #endif + #ifndef BOOST_CONTRACT_NO_PRECONDITIONS + << "a::s::pre" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_OLDS + << "a::s::old" << std::endl + #endif + << "a::s::body" << std::endl + #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS + #ifdef BOOST_CONTRACT_TEST_STATIC_INV + << "a::static_inv" << std::endl + #endif + #endif + #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS + << "a::s::post" << std::endl + #endif + ; + BOOST_TEST(out.eq(ok.str())); + + out.str(""); + aa.call_p(); // Test (indirect) protected call. + ok.str(""); ok + #ifndef BOOST_CONTRACT_NO_PRECONDITIONS + << "a::p::pre" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_OLDS + << "a::p::old" << std::endl + #endif + << "a::p::body" << std::endl + #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS + << "a::p::post" << std::endl + #endif + ; + BOOST_TEST(out.eq(ok.str())); + + out.str(""); + aa.call_q(); // Test (indirect) private call. + ok.str(""); ok + #ifndef BOOST_CONTRACT_NO_PRECONDITIONS + << "a::q::pre" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_OLDS + << "a::q::old" << std::endl + #endif + << "a::q::body" << std::endl + #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS + << "a::q::post" << std::endl + #endif + ; + BOOST_TEST(out.eq(ok.str())); + + out.str(""); + } // Call a's destructor. + ok.str(""); ok // Dtors always check cv_inv (even if not volatile). + #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS + #ifdef BOOST_CONTRACT_TEST_STATIC_INV + << "a::static_inv" << std::endl + #endif + #ifdef BOOST_CONTRACT_TEST_CV_INV + << "a::cv_inv" << std::endl + #endif + #ifdef BOOST_CONTRACT_TEST_CONST_INV + << "a::const_inv" << std::endl + #endif + #endif + #ifndef BOOST_CONTRACT_NO_OLDS + << "a::dtor::old" << std::endl + #endif + << "a::dtor::body" << std::endl + #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS + #ifdef BOOST_CONTRACT_TEST_STATIC_INV + << "a::static_inv" << std::endl + #endif + #endif + #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS + << "a::dtor::post" << std::endl + #endif + + #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS + #ifdef BOOST_CONTRACT_TEST_STATIC_INV + << "b::static_inv" << std::endl + #endif + #ifdef BOOST_CONTRACT_TEST_CV_INV + << "b::cv_inv" << std::endl + #endif + #ifdef BOOST_CONTRACT_TEST_CONST_INV + << "b::const_inv" << std::endl + #endif + #endif + #ifndef BOOST_CONTRACT_NO_OLDS + << "b::dtor::old" << std::endl + #endif + << "b::dtor::body" << std::endl + #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS + #ifdef BOOST_CONTRACT_TEST_STATIC_INV + << "b::static_inv" << std::endl + #endif + #endif + #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS + << "b::dtor::post" << std::endl + #endif + ; + BOOST_TEST(out.eq(ok.str())); + + + { // Test volatile call with no bases. + out.str(""); + b volatile bv; + ok.str(""); ok // Ctors always check const_inv (even if volatile). + #ifndef BOOST_CONTRACT_NO_PRECONDITIONS + << "b::ctor::pre" << std::endl + #endif + + #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS + #ifdef BOOST_CONTRACT_TEST_STATIC_INV + << "b::static_inv" << std::endl + #endif + #endif + #ifndef BOOST_CONTRACT_NO_OLDS + << "b::ctor::old" << std::endl + #endif + << "b::ctor::body" << std::endl + #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS + #ifdef BOOST_CONTRACT_TEST_STATIC_INV + << "b::static_inv" << std::endl + #endif + #ifdef BOOST_CONTRACT_TEST_CV_INV + << "b::cv_inv" << std::endl + #endif + #ifdef BOOST_CONTRACT_TEST_CONST_INV + << "b::const_inv" << std::endl + #endif + #endif + #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS + << "b::ctor::post" << std::endl + #endif + ; + BOOST_TEST(out.eq(ok.str())); + + out.str(""); + bv.f('b'); + ok.str(""); ok // Volatile checks static and cv (but not const) inv. + #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS + #ifdef BOOST_CONTRACT_TEST_STATIC_INV + << "b::static_inv" << std::endl + #endif + #ifdef BOOST_CONTRACT_TEST_CV_INV + << "b::cv_inv" << std::endl + #endif + #endif + #ifndef BOOST_CONTRACT_NO_PRECONDITIONS + << "b::f::volatile_pre" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_OLDS + << "b::f::volatile_old" << std::endl + #endif + << "b::f::volatile_body" << std::endl + #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS + #ifdef BOOST_CONTRACT_TEST_STATIC_INV + << "b::static_inv" << std::endl + #endif + #ifdef BOOST_CONTRACT_TEST_CV_INV + << "b::cv_inv" << std::endl + #endif + #endif + #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS + << "b::f::volatile_post" << std::endl + #endif + ; + BOOST_TEST(out.eq(ok.str())); + + out.str(""); + } // Call b's destructor. + ok.str(""); ok // Dtors always check const_inv (even if volatile). + #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS + #ifdef BOOST_CONTRACT_TEST_STATIC_INV + << "b::static_inv" << std::endl + #endif + #ifdef BOOST_CONTRACT_TEST_CV_INV + << "b::cv_inv" << std::endl + #endif + #ifdef BOOST_CONTRACT_TEST_CONST_INV + << "b::const_inv" << std::endl + #endif + #endif + #ifndef BOOST_CONTRACT_NO_OLDS + << "b::dtor::old" << std::endl + #endif + << "b::dtor::body" << std::endl + #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS + #ifdef BOOST_CONTRACT_TEST_STATIC_INV + << "b::static_inv" << std::endl + #endif + #endif + #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS + << "b::dtor::post" << std::endl + #endif + ; + BOOST_TEST(out.eq(ok.str())); + + { // Test non-volatile call with no bases. + out.str(""); + b bb; + ok.str(""); ok // Ctors always check cv_inv (even if not volatile). + #ifndef BOOST_CONTRACT_NO_PRECONDITIONS + << "b::ctor::pre" << std::endl + #endif + + #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS + #ifdef BOOST_CONTRACT_TEST_STATIC_INV + << "b::static_inv" << std::endl + #endif + #endif + #ifndef BOOST_CONTRACT_NO_OLDS + << "b::ctor::old" << std::endl + #endif + << "b::ctor::body" << std::endl + #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS + #ifdef BOOST_CONTRACT_TEST_STATIC_INV + << "b::static_inv" << std::endl + #endif + #ifdef BOOST_CONTRACT_TEST_CV_INV + << "b::cv_inv" << std::endl + #endif + #ifdef BOOST_CONTRACT_TEST_CONST_INV + << "b::const_inv" << std::endl + #endif + #endif + #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS + << "b::ctor::post" << std::endl + #endif + ; + BOOST_TEST(out.eq(ok.str())); + + out.str(""); + bb.f('b'); + ok.str(""); ok // Non-cv checks static and const (but not cv) inv. + #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS + #ifdef BOOST_CONTRACT_TEST_STATIC_INV + << "b::static_inv" << std::endl + #endif + #ifdef BOOST_CONTRACT_TEST_CONST_INV + << "b::const_inv" << std::endl + #endif + #endif + #ifndef BOOST_CONTRACT_NO_PRECONDITIONS + << "b::f::pre" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_OLDS + << "b::f::old" << std::endl + #endif + << "b::f::body" << std::endl + #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS + #ifdef BOOST_CONTRACT_TEST_STATIC_INV + << "b::static_inv" << std::endl + #endif + #ifdef BOOST_CONTRACT_TEST_CONST_INV + << "b::const_inv" << std::endl + #endif + #endif + #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS + << "b::f::post" << std::endl + #endif + ; + BOOST_TEST(out.eq(ok.str())); + + out.str(""); + } // Call b's destructor. + ok.str(""); ok // Dtors always check cv_inv (even if not volatile). + #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS + #ifdef BOOST_CONTRACT_TEST_STATIC_INV + << "b::static_inv" << std::endl + #endif + #ifdef BOOST_CONTRACT_TEST_CV_INV + << "b::cv_inv" << std::endl + #endif + #ifdef BOOST_CONTRACT_TEST_CONST_INV + << "b::const_inv" << std::endl + #endif + #endif + #ifndef BOOST_CONTRACT_NO_OLDS + << "b::dtor::old" << std::endl + #endif + << "b::dtor::body" << std::endl + #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS + #ifdef BOOST_CONTRACT_TEST_STATIC_INV + << "b::static_inv" << std::endl + #endif + #endif + #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS + << "b::dtor::post" << std::endl + #endif + ; + BOOST_TEST(out.eq(ok.str())); + + return boost::report_errors(); +} + diff --git a/src/boost/libs/contract/test/invariant/decl_const.cpp b/src/boost/libs/contract/test/invariant/decl_const.cpp new file mode 100644 index 000000000..b936449df --- /dev/null +++ b/src/boost/libs/contract/test/invariant/decl_const.cpp @@ -0,0 +1,13 @@ + +// Copyright (C) 2008-2018 Lorenzo Caminiti +// Distributed under the Boost Software License, Version 1.0 (see accompanying +// file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt). +// See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html + +// Test all invariants (static, cv, and const-only). + +#undef BOOST_CONTRACT_TEST_STATIC_INV +#undef BOOST_CONTRACT_TEST_CV_INV +#define BOOST_CONTRACT_TEST_CONST_INV +#include "decl.hpp" + diff --git a/src/boost/libs/contract/test/invariant/decl_cv.cpp b/src/boost/libs/contract/test/invariant/decl_cv.cpp new file mode 100644 index 000000000..5607dafbe --- /dev/null +++ b/src/boost/libs/contract/test/invariant/decl_cv.cpp @@ -0,0 +1,13 @@ + +// Copyright (C) 2008-2018 Lorenzo Caminiti +// Distributed under the Boost Software License, Version 1.0 (see accompanying +// file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt). +// See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html + +// Test all invariants (static, cv, and const-only). + +#undef BOOST_CONTRACT_TEST_STATIC_INV +#define BOOST_CONTRACT_TEST_CV_INV +#undef BOOST_CONTRACT_TEST_CONST_INV +#include "decl.hpp" + diff --git a/src/boost/libs/contract/test/invariant/decl_cv_const.cpp b/src/boost/libs/contract/test/invariant/decl_cv_const.cpp new file mode 100644 index 000000000..c762bbbcf --- /dev/null +++ b/src/boost/libs/contract/test/invariant/decl_cv_const.cpp @@ -0,0 +1,13 @@ + +// Copyright (C) 2008-2018 Lorenzo Caminiti +// Distributed under the Boost Software License, Version 1.0 (see accompanying +// file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt). +// See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html + +// Test all invariants (static, cv, and const-only). + +#undef BOOST_CONTRACT_TEST_STATIC_INV +#define BOOST_CONTRACT_TEST_CV_INV +#define BOOST_CONTRACT_TEST_CONST_INV +#include "decl.hpp" + diff --git a/src/boost/libs/contract/test/invariant/decl_nothing.cpp b/src/boost/libs/contract/test/invariant/decl_nothing.cpp new file mode 100644 index 000000000..ad89d1f1e --- /dev/null +++ b/src/boost/libs/contract/test/invariant/decl_nothing.cpp @@ -0,0 +1,13 @@ + +// Copyright (C) 2008-2018 Lorenzo Caminiti +// Distributed under the Boost Software License, Version 1.0 (see accompanying +// file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt). +// See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html + +// Test all invariants (static, cv, and const-only). + +#undef BOOST_CONTRACT_TEST_STATIC_INV +#undef BOOST_CONTRACT_TEST_CV_INV +#undef BOOST_CONTRACT_TEST_CONST_INV +#include "decl.hpp" + diff --git a/src/boost/libs/contract/test/invariant/decl_static.cpp b/src/boost/libs/contract/test/invariant/decl_static.cpp new file mode 100644 index 000000000..8db92edca --- /dev/null +++ b/src/boost/libs/contract/test/invariant/decl_static.cpp @@ -0,0 +1,13 @@ + +// Copyright (C) 2008-2018 Lorenzo Caminiti +// Distributed under the Boost Software License, Version 1.0 (see accompanying +// file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt). +// See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html + +// Test all invariants (static, cv, and const-only). + +#define BOOST_CONTRACT_TEST_STATIC_INV +#undef BOOST_CONTRACT_TEST_CV_INV +#undef BOOST_CONTRACT_TEST_CONST_INV +#include "decl.hpp" + diff --git a/src/boost/libs/contract/test/invariant/decl_static_const.cpp b/src/boost/libs/contract/test/invariant/decl_static_const.cpp new file mode 100644 index 000000000..7060c21c1 --- /dev/null +++ b/src/boost/libs/contract/test/invariant/decl_static_const.cpp @@ -0,0 +1,13 @@ + +// Copyright (C) 2008-2018 Lorenzo Caminiti +// Distributed under the Boost Software License, Version 1.0 (see accompanying +// file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt). +// See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html + +// Test all invariants (static, cv, and const-only). + +#define BOOST_CONTRACT_TEST_STATIC_INV +#undef BOOST_CONTRACT_TEST_CV_INV +#define BOOST_CONTRACT_TEST_CONST_INV +#include "decl.hpp" + diff --git a/src/boost/libs/contract/test/invariant/decl_static_cv.cpp b/src/boost/libs/contract/test/invariant/decl_static_cv.cpp new file mode 100644 index 000000000..a87be0f28 --- /dev/null +++ b/src/boost/libs/contract/test/invariant/decl_static_cv.cpp @@ -0,0 +1,13 @@ + +// Copyright (C) 2008-2018 Lorenzo Caminiti +// Distributed under the Boost Software License, Version 1.0 (see accompanying +// file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt). +// See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html + +// Test all invariants (static, cv, and const-only). + +#define BOOST_CONTRACT_TEST_STATIC_INV +#define BOOST_CONTRACT_TEST_CV_INV +#undef BOOST_CONTRACT_TEST_CONST_INV +#include "decl.hpp" + diff --git a/src/boost/libs/contract/test/invariant/decl_static_cv_const.cpp b/src/boost/libs/contract/test/invariant/decl_static_cv_const.cpp new file mode 100644 index 000000000..a4c977604 --- /dev/null +++ b/src/boost/libs/contract/test/invariant/decl_static_cv_const.cpp @@ -0,0 +1,13 @@ + +// Copyright (C) 2008-2018 Lorenzo Caminiti +// Distributed under the Boost Software License, Version 1.0 (see accompanying +// file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt). +// See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html + +// Test all invariants (static, cv, and const-only). + +#define BOOST_CONTRACT_TEST_STATIC_INV +#define BOOST_CONTRACT_TEST_CV_INV +#define BOOST_CONTRACT_TEST_CONST_INV +#include "decl.hpp" + diff --git a/src/boost/libs/contract/test/invariant/ifdef.cpp b/src/boost/libs/contract/test/invariant/ifdef.cpp new file mode 100644 index 000000000..16ebf75fd --- /dev/null +++ b/src/boost/libs/contract/test/invariant/ifdef.cpp @@ -0,0 +1,174 @@ + +// Copyright (C) 2008-2018 Lorenzo Caminiti +// Distributed under the Boost Software License, Version 1.0 (see accompanying +// file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt). +// See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html + +// Test invariant compilation on/off. + +#include "../detail/oteststream.hpp" +#include <boost/contract/constructor.hpp> +#include <boost/contract/destructor.hpp> +#include <boost/contract/public_function.hpp> +#include <boost/contract/check.hpp> +#include <boost/detail/lightweight_test.hpp> +#include <sstream> + +boost::contract::test::detail::oteststream out; + +class a { +public: + #ifndef BOOST_CONTRACT_NO_INVARIANTS + static void static_invariant() { + out << "a::static_inv" << std::endl; + } + + void invariant() const volatile { + out << "a::cv_inv" << std::endl; + } + + void invariant() const { + out << "a::const_inv" << std::endl; + } + #endif + + a() { // Test check both cv and const invariant (at exit if no throw). + #ifndef BOOST_CONTRACT_NO_CONSTRUCTORS + boost::contract::check c= boost::contract::constructor(this); + #endif + out << "a::ctor::body" << std::endl; + } + + ~a() { // Test check both cv and const invariant (at entry). + #ifndef BOOSTT_CONTRACT_NO_DESTRUCTORS + boost::contract::check c = boost::contract::destructor(this); + #endif + out << "a::dtor::body" << std::endl; + } + + void m() { // Test check const invariant (at entry and exit). + #ifndef BOOST_CONTRACT_NO_PUBLIC_FUNCTIONS + boost::contract::check c = boost::contract::public_function(this); + #endif + out << "a::m::body" << std::endl; + } + + void c() const { // Test check const invariant (at entry and exit). + #ifndef BOOST_CONTRACT_NO_PUBLIC_FUNCTIONS + boost::contract::check c = boost::contract::public_function(this); + #endif + out << "a::c::body" << std::endl; + } + + void v() volatile { // Test check cv invariant (at entry and exit). + #ifndef BOOST_CONTRACT_NO_PUBLIC_FUNCTIONS + boost::contract::check c = boost::contract::public_function(this); + #endif + out << "a::v::body" << std::endl; + } + + void cv() const volatile { // Test check cv invariant (at entry and exit). + #ifndef BOOST_CONTRACT_NO_PUBLIC_FUNCTIONS + boost::contract::check c = boost::contract::public_function(this); + #endif + out << "a::cv::body" << std::endl; + } +}; + +int main() { + std::ostringstream ok; + + { + out.str(""); + a aa; + ok.str(""); ok + #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS + << "a::static_inv" << std::endl + #endif + << "a::ctor::body" << std::endl + #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS + << "a::static_inv" << std::endl + << "a::cv_inv" << std::endl + << "a::const_inv" << std::endl + #endif + ; + BOOST_TEST(out.eq(ok.str())); + + out.str(""); + aa.m(); + ok.str(""); ok + #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS + << "a::static_inv" << std::endl + << "a::const_inv" << std::endl + #endif + << "a::m::body" << std::endl + #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS + << "a::static_inv" << std::endl + << "a::const_inv" << std::endl + #endif + ; + BOOST_TEST(out.eq(ok.str())); + + out.str(""); + aa.c(); + ok.str(""); ok + #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS + << "a::static_inv" << std::endl + << "a::const_inv" << std::endl + #endif + << "a::c::body" << std::endl + #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS + << "a::static_inv" << std::endl + << "a::const_inv" << std::endl + #endif + ; + BOOST_TEST(out.eq(ok.str())); + + out.str(""); + aa.v(); + ok.str(""); ok + #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS + << "a::static_inv" << std::endl + << "a::cv_inv" << std::endl + #endif + << "a::v::body" << std::endl + #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS + << "a::static_inv" << std::endl + << "a::cv_inv" << std::endl + #endif + ; + BOOST_TEST(out.eq(ok.str())); + + out.str(""); + aa.cv(); + ok.str(""); ok + #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS + << "a::static_inv" << std::endl + << "a::cv_inv" << std::endl + #endif + << "a::cv::body" << std::endl + #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS + << "a::static_inv" << std::endl + << "a::cv_inv" << std::endl + #endif + ; + BOOST_TEST(out.eq(ok.str())); + + out.str(""); + } // Call dtor. + ok.str(""); ok + #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS + << "a::static_inv" << std::endl + << "a::cv_inv" << std::endl + << "a::const_inv" << std::endl + #endif + << "a::dtor::body" << std::endl + #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS + << "a::static_inv" << std::endl + #endif + ; + BOOST_TEST(out.eq(ok.str())); + + return boost::report_errors(); +} + diff --git a/src/boost/libs/contract/test/invariant/ifdef_macro.cpp b/src/boost/libs/contract/test/invariant/ifdef_macro.cpp new file mode 100644 index 000000000..5955fa017 --- /dev/null +++ b/src/boost/libs/contract/test/invariant/ifdef_macro.cpp @@ -0,0 +1,170 @@ + +// Copyright (C) 2008-2018 Lorenzo Caminiti +// Distributed under the Boost Software License, Version 1.0 (see accompanying +// file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt). +// See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html + +// Test invariant compilation on/off (using macro interface). + +#include "../detail/oteststream.hpp" +#include "../detail/unprotected_commas.hpp" +#include <boost/contract_macro.hpp> +#include <boost/detail/lightweight_test.hpp> +#include <sstream> + +boost::contract::test::detail::oteststream out; + +class a { +public: + BOOST_CONTRACT_STATIC_INVARIANT({ + boost::contract::test::detail::unprotected_commas<void, void, void>:: + call(); + out << "a::static_inv" << std::endl; + }) + + BOOST_CONTRACT_INVARIANT_VOLATILE({ + boost::contract::test::detail::unprotected_commas<void, void, void>:: + call(); + out << "a::cv_inv" << std::endl; + }) + + BOOST_CONTRACT_INVARIANT({ + boost::contract::test::detail::unprotected_commas<void, void, void>:: + call(); + out << "a::const_inv" << std::endl; + }) + + a() { // Test check both cv and const invariant (at exit if no throw). + BOOST_CONTRACT_CONSTRUCTOR(boost::contract::test::detail:: + unprotected_commas<void, void, void>::same(this)); + out << "a::ctor::body" << std::endl; + } + + ~a() { // Test check both cv and const invariant (at entry). + BOOST_CONTRACT_DESTRUCTOR(boost::contract::test::detail:: + unprotected_commas<void, void, void>::same(this)); + out << "a::dtor::body" << std::endl; + } + + void m() { // Test check const invariant (at entry and exit). + BOOST_CONTRACT_PUBLIC_FUNCTION(boost::contract::test::detail:: + unprotected_commas<void, void, void>::same(this)); + out << "a::m::body" << std::endl; + } + + void c() const { // Test check const invariant (at entry and exit). + BOOST_CONTRACT_PUBLIC_FUNCTION(boost::contract::test::detail:: + unprotected_commas<void, void, void>::same(this)); + out << "a::c::body" << std::endl; + } + + void v() volatile { // Test check cv invariant (at entry and exit). + BOOST_CONTRACT_PUBLIC_FUNCTION(boost::contract::test::detail:: + unprotected_commas<void, void, void>::same(this)); + out << "a::v::body" << std::endl; + } + + void cv() const volatile { // Test check cv invariant (at entry and exit). + BOOST_CONTRACT_PUBLIC_FUNCTION(boost::contract::test::detail:: + unprotected_commas<void, void, void>::same(this)); + out << "a::cv::body" << std::endl; + } +}; + +int main() { + std::ostringstream ok; + + { + out.str(""); + a aa; + ok.str(""); ok + #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS + << "a::static_inv" << std::endl + #endif + << "a::ctor::body" << std::endl + #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS + << "a::static_inv" << std::endl + << "a::cv_inv" << std::endl + << "a::const_inv" << std::endl + #endif + ; + BOOST_TEST(out.eq(ok.str())); + + out.str(""); + aa.m(); + ok.str(""); ok + #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS + << "a::static_inv" << std::endl + << "a::const_inv" << std::endl + #endif + << "a::m::body" << std::endl + #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS + << "a::static_inv" << std::endl + << "a::const_inv" << std::endl + #endif + ; + BOOST_TEST(out.eq(ok.str())); + + out.str(""); + aa.c(); + ok.str(""); ok + #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS + << "a::static_inv" << std::endl + << "a::const_inv" << std::endl + #endif + << "a::c::body" << std::endl + #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS + << "a::static_inv" << std::endl + << "a::const_inv" << std::endl + #endif + ; + BOOST_TEST(out.eq(ok.str())); + + out.str(""); + aa.v(); + ok.str(""); ok + #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS + << "a::static_inv" << std::endl + << "a::cv_inv" << std::endl + #endif + << "a::v::body" << std::endl + #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS + << "a::static_inv" << std::endl + << "a::cv_inv" << std::endl + #endif + ; + BOOST_TEST(out.eq(ok.str())); + + out.str(""); + aa.cv(); + ok.str(""); ok + #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS + << "a::static_inv" << std::endl + << "a::cv_inv" << std::endl + #endif + << "a::cv::body" << std::endl + #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS + << "a::static_inv" << std::endl + << "a::cv_inv" << std::endl + #endif + ; + BOOST_TEST(out.eq(ok.str())); + + out.str(""); + } // Call dtor. + ok.str(""); ok + #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS + << "a::static_inv" << std::endl + << "a::cv_inv" << std::endl + << "a::const_inv" << std::endl + #endif + << "a::dtor::body" << std::endl + #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS + << "a::static_inv" << std::endl + #endif + ; + BOOST_TEST(out.eq(ok.str())); + + return boost::report_errors(); +} + diff --git a/src/boost/libs/contract/test/invariant/mutable.hpp b/src/boost/libs/contract/test/invariant/mutable.hpp new file mode 100644 index 000000000..0940bc987 --- /dev/null +++ b/src/boost/libs/contract/test/invariant/mutable.hpp @@ -0,0 +1,28 @@ + +// no #include guard + +// Copyright (C) 2008-2018 Lorenzo Caminiti +// Distributed under the Boost Software License, Version 1.0 (see accompanying +// file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt). +// See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html + +// Test error if non-static inv declared mutable (unless PERMISSIVE #defined). + +#include <boost/contract/public_function.hpp> +#include <boost/contract/check.hpp> + +struct a { + void invariant() {} + + void f() { + // Same for ctor and dtor (because they all use check_pre_post_inv). + boost::contract::check c = boost::contract::public_function(this); + } +}; + +int main() { + a aa; + aa.f(); + return 0; +} + diff --git a/src/boost/libs/contract/test/invariant/mutable_error.cpp b/src/boost/libs/contract/test/invariant/mutable_error.cpp new file mode 100644 index 000000000..97a267853 --- /dev/null +++ b/src/boost/libs/contract/test/invariant/mutable_error.cpp @@ -0,0 +1,14 @@ + +// Copyright (C) 2008-2018 Lorenzo Caminiti +// Distributed under the Boost Software License, Version 1.0 (see accompanying +// file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt). +// See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html + +// Test compiler error when invariant() not declared const. + +#undef BOOST_CONTRACT_PERMISSIVE +#include "mutable.hpp" +#ifdef BOOST_CONTRACT_NO_INVARIANTS + #error "Forcing error even when invariants not checked" +#endif + diff --git a/src/boost/libs/contract/test/invariant/mutable_permissive.cpp b/src/boost/libs/contract/test/invariant/mutable_permissive.cpp new file mode 100644 index 000000000..fb098ee1e --- /dev/null +++ b/src/boost/libs/contract/test/invariant/mutable_permissive.cpp @@ -0,0 +1,13 @@ + +// Copyright (C) 2008-2018 Lorenzo Caminiti +// Distributed under the Boost Software License, Version 1.0 (see accompanying +// file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt). +// See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html + +// Test no error if permissive even if invariant() not declared const. + +#ifndef BOOST_CONTRACT_PERMISSIVE + #error "build must define PERMISSIVE" +#endif +#include "mutable.hpp" + diff --git a/src/boost/libs/contract/test/invariant/static.hpp b/src/boost/libs/contract/test/invariant/static.hpp new file mode 100644 index 000000000..75e4da3f4 --- /dev/null +++ b/src/boost/libs/contract/test/invariant/static.hpp @@ -0,0 +1,28 @@ + +// no #include guard + +// Copyright (C) 2008-2018 Lorenzo Caminiti +// Distributed under the Boost Software License, Version 1.0 (see accompanying +// file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt). +// See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html + +// Test error if non-static inv declared static (unless PERMISSIVE #defined). + +#include <boost/contract/public_function.hpp> +#include <boost/contract/check.hpp> + +struct a { + static void invariant() {} + + void f() { + // Same for ctor and dtor (because they all use check_pre_post_inv). + boost::contract::check c = boost::contract::public_function(this); + } +}; + +int main() { + a aa; + aa.f(); + return 0; +} + diff --git a/src/boost/libs/contract/test/invariant/static_const.hpp b/src/boost/libs/contract/test/invariant/static_const.hpp new file mode 100644 index 000000000..ea2f99619 --- /dev/null +++ b/src/boost/libs/contract/test/invariant/static_const.hpp @@ -0,0 +1,28 @@ + +// no #include guard + +// Copyright (C) 2008-2018 Lorenzo Caminiti +// Distributed under the Boost Software License, Version 1.0 (see accompanying +// file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt). +// See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html + +// Test error if static inv declared const (unless PERMISSIVE #defined). + +#include <boost/contract/public_function.hpp> +#include <boost/contract/check.hpp> + +struct a { + void static_invariant() const {} + + void f() { + // Same for ctor and dtor (because they all use check_pre_post_inv). + boost::contract::check c = boost::contract::public_function(this); + } +}; + +int main() { + a aa; + aa.f(); + return 0; +} + diff --git a/src/boost/libs/contract/test/invariant/static_const_error.cpp b/src/boost/libs/contract/test/invariant/static_const_error.cpp new file mode 100644 index 000000000..e9ef5e668 --- /dev/null +++ b/src/boost/libs/contract/test/invariant/static_const_error.cpp @@ -0,0 +1,14 @@ + +// Copyright (C) 2008-2018 Lorenzo Caminiti +// Distributed under the Boost Software License, Version 1.0 (see accompanying +// file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt). +// See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html + +// Test error if static inv declared const. + +#undef BOOST_CONTRACT_PERMISSIVE +#include "static_const.hpp" +#ifdef BOOST_CONTRACT_NO_INVARIANTS + #error "Forcing error even when invariants not checked" +#endif + diff --git a/src/boost/libs/contract/test/invariant/static_const_permissive.cpp b/src/boost/libs/contract/test/invariant/static_const_permissive.cpp new file mode 100644 index 000000000..efe334071 --- /dev/null +++ b/src/boost/libs/contract/test/invariant/static_const_permissive.cpp @@ -0,0 +1,13 @@ + +// Copyright (C) 2008-2018 Lorenzo Caminiti +// Distributed under the Boost Software License, Version 1.0 (see accompanying +// file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt). +// See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html + +// Test no error if permissive even when static inv declared const. + +#ifndef BOOST_CONTRACT_PERMISSIVE + #error "build must define PERMISSIVE" +#endif +#include "static_const.hpp" + diff --git a/src/boost/libs/contract/test/invariant/static_cv.hpp b/src/boost/libs/contract/test/invariant/static_cv.hpp new file mode 100644 index 000000000..bca082e2a --- /dev/null +++ b/src/boost/libs/contract/test/invariant/static_cv.hpp @@ -0,0 +1,28 @@ + +// no #include guard + +// Copyright (C) 2008-2018 Lorenzo Caminiti +// Distributed under the Boost Software License, Version 1.0 (see accompanying +// file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt). +// See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html + +// Test error if static inv declared cv (unless PERMISSIVE #defined). + +#include <boost/contract/public_function.hpp> +#include <boost/contract/check.hpp> + +struct a { + void static_invariant() const volatile {} + + void f() { + // Same for ctor and dtor (because they all use check_pre_post_inv). + boost::contract::check c = boost::contract::public_function(this); + } +}; + +int main() { + a aa; + aa.f(); + return 0; +} + diff --git a/src/boost/libs/contract/test/invariant/static_cv_error.cpp b/src/boost/libs/contract/test/invariant/static_cv_error.cpp new file mode 100644 index 000000000..84f9ca0d5 --- /dev/null +++ b/src/boost/libs/contract/test/invariant/static_cv_error.cpp @@ -0,0 +1,14 @@ + +// Copyright (C) 2008-2018 Lorenzo Caminiti +// Distributed under the Boost Software License, Version 1.0 (see accompanying +// file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt). +// See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html + +// Test error if static inv declared cv. + +#undef BOOST_CONTRACT_PERMISSIVE +#include "static_cv.hpp" +#ifdef BOOST_CONTRACT_NO_INVARIANTS + #error "Forcing error even when invariants not checked" +#endif + diff --git a/src/boost/libs/contract/test/invariant/static_cv_permissive.cpp b/src/boost/libs/contract/test/invariant/static_cv_permissive.cpp new file mode 100644 index 000000000..9ffee38f6 --- /dev/null +++ b/src/boost/libs/contract/test/invariant/static_cv_permissive.cpp @@ -0,0 +1,13 @@ + +// Copyright (C) 2008-2018 Lorenzo Caminiti +// Distributed under the Boost Software License, Version 1.0 (see accompanying +// file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt). +// See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html + +// Test no error if permissive even when static inv declared cv. + +#ifndef BOOST_CONTRACT_PERMISSIVE + #error "build must define PERMISSIVE" +#endif +#include "static_cv.hpp" + diff --git a/src/boost/libs/contract/test/invariant/static_error.cpp b/src/boost/libs/contract/test/invariant/static_error.cpp new file mode 100644 index 000000000..eeaa85f2e --- /dev/null +++ b/src/boost/libs/contract/test/invariant/static_error.cpp @@ -0,0 +1,14 @@ + +// Copyright (C) 2008-2018 Lorenzo Caminiti +// Distributed under the Boost Software License, Version 1.0 (see accompanying +// file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt). +// See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html + +// Test compiler error if invariant() declared static. + +#undef BOOST_CONTRACT_PERMISSIVE +#include "static.hpp" +#ifdef BOOST_CONTRACT_NO_INVARIANTS + #error "Forcing error even when invariants not checked" +#endif + diff --git a/src/boost/libs/contract/test/invariant/static_mutable.hpp b/src/boost/libs/contract/test/invariant/static_mutable.hpp new file mode 100644 index 000000000..1cf1f4242 --- /dev/null +++ b/src/boost/libs/contract/test/invariant/static_mutable.hpp @@ -0,0 +1,28 @@ + +// no #include guard + +// Copyright (C) 2008-2018 Lorenzo Caminiti +// Distributed under the Boost Software License, Version 1.0 (see accompanying +// file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt). +// See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html + +// Test error if static inv declared mutable (unless PERMISSIVE #defined). + +#include <boost/contract/public_function.hpp> +#include <boost/contract/check.hpp> + +struct a { + void static_invariant() {} // Error (unless PERMISSIVE). + + void f() { + // Same for ctor and dtor (because they all use check_pre_post_inv). + boost::contract::check c = boost::contract::public_function(this); + } +}; + +int main() { + a aa; + aa.f(); + return 0; +} + diff --git a/src/boost/libs/contract/test/invariant/static_mutable_error.cpp b/src/boost/libs/contract/test/invariant/static_mutable_error.cpp new file mode 100644 index 000000000..0e45af436 --- /dev/null +++ b/src/boost/libs/contract/test/invariant/static_mutable_error.cpp @@ -0,0 +1,14 @@ + +// Copyright (C) 2008-2018 Lorenzo Caminiti +// Distributed under the Boost Software License, Version 1.0 (see accompanying +// file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt). +// See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html + +// Test error if static inv declared mutable. + +#undef BOOST_CONTRACT_PERMISSIVE +#include "static_mutable.hpp" +#ifdef BOOST_CONTRACT_NO_INVARIANTS + #error "Forcing error even when invariants not checked" +#endif + diff --git a/src/boost/libs/contract/test/invariant/static_mutable_permissive.cpp b/src/boost/libs/contract/test/invariant/static_mutable_permissive.cpp new file mode 100644 index 000000000..d6f6bcbba --- /dev/null +++ b/src/boost/libs/contract/test/invariant/static_mutable_permissive.cpp @@ -0,0 +1,13 @@ + +// Copyright (C) 2008-2018 Lorenzo Caminiti +// Distributed under the Boost Software License, Version 1.0 (see accompanying +// file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt). +// See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html + +// Test error if permissive even when static inv declared mutable. + +#ifndef BOOST_CONTRACT_PERMISSIVE + #error "build must define PERMISSIVE" +#endif +#include "static_mutable.hpp" + diff --git a/src/boost/libs/contract/test/invariant/static_permissive.cpp b/src/boost/libs/contract/test/invariant/static_permissive.cpp new file mode 100644 index 000000000..710240cbe --- /dev/null +++ b/src/boost/libs/contract/test/invariant/static_permissive.cpp @@ -0,0 +1,13 @@ + +// Copyright (C) 2008-2018 Lorenzo Caminiti +// Distributed under the Boost Software License, Version 1.0 (see accompanying +// file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt). +// See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html + +// Test no compiler error if permissive even when invariant() declared static. + +#ifndef BOOST_CONTRACT_PERMISSIVE + #error "build must define PERMISSIVE" +#endif +#include "static.hpp" + diff --git a/src/boost/libs/contract/test/invariant/static_volatile.hpp b/src/boost/libs/contract/test/invariant/static_volatile.hpp new file mode 100644 index 000000000..ba3bb351b --- /dev/null +++ b/src/boost/libs/contract/test/invariant/static_volatile.hpp @@ -0,0 +1,28 @@ + +// no #include guard + +// Copyright (C) 2008-2018 Lorenzo Caminiti +// Distributed under the Boost Software License, Version 1.0 (see accompanying +// file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt). +// See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html + +// Test error if static inv declared volatile (unless PERMISSIVE #defined). + +#include <boost/contract/public_function.hpp> +#include <boost/contract/check.hpp> + +struct a { + void static_invariant() volatile {} + + void f() { + // Same for ctor and dtor (because they all use check_pre_post_inv). + boost::contract::check c = boost::contract::public_function(this); + } +}; + +int main() { + a aa; + aa.f(); + return 0; +} + diff --git a/src/boost/libs/contract/test/invariant/static_volatile_error.cpp b/src/boost/libs/contract/test/invariant/static_volatile_error.cpp new file mode 100644 index 000000000..66cc9d2c9 --- /dev/null +++ b/src/boost/libs/contract/test/invariant/static_volatile_error.cpp @@ -0,0 +1,14 @@ + +// Copyright (C) 2008-2018 Lorenzo Caminiti +// Distributed under the Boost Software License, Version 1.0 (see accompanying +// file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt). +// See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html + +// Test error if static inv declared volatile. + +#undef BOOST_CONTRACT_PERMISSIVE +#include "static_volatile.hpp" +#ifdef BOOST_CONTRACT_NO_INVARIANTS + #error "Forcing error even when invariants not checked" +#endif + diff --git a/src/boost/libs/contract/test/invariant/static_volatile_permissive.cpp b/src/boost/libs/contract/test/invariant/static_volatile_permissive.cpp new file mode 100644 index 000000000..fd92e273c --- /dev/null +++ b/src/boost/libs/contract/test/invariant/static_volatile_permissive.cpp @@ -0,0 +1,13 @@ + +// Copyright (C) 2008-2018 Lorenzo Caminiti +// Distributed under the Boost Software License, Version 1.0 (see accompanying +// file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt). +// See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html + +// Test error if permissive even when static inv declared volatile. + +#ifndef BOOST_CONTRACT_PERMISSIVE + #error "build must define PERMISSIVE" +#endif +#include "static_volatile.hpp" + diff --git a/src/boost/libs/contract/test/invariant/volatile.hpp b/src/boost/libs/contract/test/invariant/volatile.hpp new file mode 100644 index 000000000..0e7ede02b --- /dev/null +++ b/src/boost/libs/contract/test/invariant/volatile.hpp @@ -0,0 +1,28 @@ + +// no #include guard + +// Copyright (C) 2008-2018 Lorenzo Caminiti +// Distributed under the Boost Software License, Version 1.0 (see accompanying +// file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt). +// See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html + +// Test error if non-static inv declared volatile (unless PERMISSIVE #defined). + +#include <boost/contract/public_function.hpp> +#include <boost/contract/check.hpp> + +struct a { + void invariant() volatile {} + + void f() { + // Same for ctor and dtor (because they all use check_pre_post_inv). + boost::contract::check c = boost::contract::public_function(this); + } +}; + +int main() { + a aa; + aa.f(); + return 0; +} + diff --git a/src/boost/libs/contract/test/invariant/volatile_error.cpp b/src/boost/libs/contract/test/invariant/volatile_error.cpp new file mode 100644 index 000000000..3372a35d6 --- /dev/null +++ b/src/boost/libs/contract/test/invariant/volatile_error.cpp @@ -0,0 +1,14 @@ + +// Copyright (C) 2008-2018 Lorenzo Caminiti +// Distributed under the Boost Software License, Version 1.0 (see accompanying +// file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt). +// See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html + +// Test error if non-static inv declared volatile. + +#undef BOOST_CONTRACT_PERMISSIVE +#include "volatile.hpp" +#ifdef BOOST_CONTRACT_NO_INVARIANTS + #error "Forcing error even when invariants not checked" +#endif + diff --git a/src/boost/libs/contract/test/invariant/volatile_permissive.cpp b/src/boost/libs/contract/test/invariant/volatile_permissive.cpp new file mode 100644 index 000000000..a3d1b987c --- /dev/null +++ b/src/boost/libs/contract/test/invariant/volatile_permissive.cpp @@ -0,0 +1,13 @@ + +// Copyright (C) 2008-2018 Lorenzo Caminiti +// Distributed under the Boost Software License, Version 1.0 (see accompanying +// file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt). +// See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html + +// Test no error if permissive even when non-static inv declared volatile. + +#ifndef BOOST_CONTRACT_PERMISSIVE + #error "build must define PERMISSIVE" +#endif +#include "volatile.hpp" + diff --git a/src/boost/libs/contract/test/old/auto.cpp b/src/boost/libs/contract/test/old/auto.cpp new file mode 100644 index 000000000..97dd87f7b --- /dev/null +++ b/src/boost/libs/contract/test/old/auto.cpp @@ -0,0 +1,38 @@ + +// Copyright (C) 2008-2018 Lorenzo Caminiti +// Distributed under the Boost Software License, Version 1.0 (see accompanying +// file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt). +// See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html + +// Test that OLD macro allows to use C++11 auto declarations. + +#include <boost/config.hpp> +#include <boost/contract/old.hpp> +#include <boost/type_traits.hpp> +#include <boost/static_assert.hpp> +#include <boost/detail/lightweight_test.hpp> + +int main() { + int x = -123; + auto old_x = BOOST_CONTRACT_OLDOF(x); + x = 123; + BOOST_STATIC_ASSERT((boost::is_same<decltype(old_x), + boost::contract::old_ptr<int> >::value)); + #ifndef BOOST_CONTRACT_NO_OLDS + BOOST_TEST_EQ(*old_x, -123); + #endif + BOOST_TEST_EQ(x, 123); + + boost::contract::virtual_* v = 0; + char y = 'j'; + auto old_y = BOOST_CONTRACT_OLDOF(v, y); + y = 'k'; + BOOST_STATIC_ASSERT((boost::is_same<decltype(old_y), + boost::contract::old_ptr<char> >::value)); + #ifndef BOOST_CONTRACT_NO_OLDS + BOOST_TEST_EQ(*old_y, 'j'); + #endif + BOOST_TEST_EQ(y, 'k'); + return boost::report_errors(); +} + diff --git a/src/boost/libs/contract/test/old/copyable_traits.cpp b/src/boost/libs/contract/test/old/copyable_traits.cpp new file mode 100644 index 000000000..3792c6fea --- /dev/null +++ b/src/boost/libs/contract/test/old/copyable_traits.cpp @@ -0,0 +1,108 @@ + +// Copyright (C) 2008-2018 Lorenzo Caminiti +// Distributed under the Boost Software License, Version 1.0 (see accompanying +// file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt). +// See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html + +// Test specializations of old value copy type traits. + +#include <boost/contract/old.hpp> +#include <boost/type_traits.hpp> +#include <boost/noncopyable.hpp> +#include <boost/detail/lightweight_test.hpp> +#include <cassert> + +template<typename T> +void f(T& x) { + // No OLDOF here so C++11 not required for this test. + boost::contract::old_ptr_if_copyable<T> old_x = boost::contract::make_old( + boost::contract::copy_old() ? x : boost::contract::null_old()); +} + +// Test copyable type but... +struct w { + w() {} + w(w const&) { BOOST_TEST(false); } // Test this doesn't get copied. +}; + +// ...never copy old values for type `w` (because its copy is too expensive). +namespace boost { namespace contract { + template<> + struct is_old_value_copyable<w> : boost::false_type {}; +} } // namespace + +// Test non-copyable type but... +struct p : private boost::noncopyable { // Non-copyable via Boost. + static bool copied; + p() : num_(new int(0)) {} + ~p() { delete num_; } +private: + int* num_; + friend struct boost::contract::old_value_copy<p>; +}; +bool p::copied = false; + +// ...still copy old values for type `p` (using a deep copy). +namespace boost { namespace contract { + template<> + struct old_value_copy<p> { + explicit old_value_copy(p const& old) { + *old_.num_ = *old.num_; // Deep copy pointed value. + p::copied = true; + } + + p const& old() const { return old_; } + + private: + p old_; + }; + + template<> + struct is_old_value_copyable<p> : boost::true_type {}; +} } // namespace + +// Non-copyable type so... +struct n { + n() {} +private: + n(n const&); // Non-copyable (but not via Boost). +}; + +// ...specialize `boost::is_copy_constructible` (no need for this on C++11). +namespace boost { namespace contract { + template<> + struct is_old_value_copyable<n> : boost::false_type {}; +} } // namespace + +int main() { + // NOTE: No test::detail::counter below because that is for copyable types. + + { + int x; // Test has copy ctor so copy olds. + f(x); + } + + { + w x; // Test has copy ctor but never copy olds (see TEST(...) above). + f(x); + } + + p::copied = false; + { + p x; // Test no copy ctor but still old copies. + f(x); + } + #ifndef BOOST_CONTRACT_NO_OLDS + BOOST_TEST(p::copied); + #else + BOOST_TEST(!p::copied); + #endif + + { + n x; // Test no copy ctor so no old copies. + f(x); + } + + return boost::report_errors(); +} + diff --git a/src/boost/libs/contract/test/old/if_copyable.cpp b/src/boost/libs/contract/test/old/if_copyable.cpp new file mode 100644 index 000000000..0c3738f33 --- /dev/null +++ b/src/boost/libs/contract/test/old/if_copyable.cpp @@ -0,0 +1,133 @@ + +// Copyright (C) 2008-2018 Lorenzo Caminiti +// Distributed under the Boost Software License, Version 1.0 (see accompanying +// file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt). +// See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html + +// Test old values of non-copyable types. + +#include "if_copyable.hpp" +#include <boost/contract/public_function.hpp> +#include <boost/contract/function.hpp> +#include <boost/contract/base_types.hpp> +#include <boost/contract/override.hpp> +#include <boost/contract/old.hpp> +#include <boost/contract/check.hpp> +#include <boost/contract/assert.hpp> +#include <boost/noncopyable.hpp> +#include <boost/detail/lightweight_test.hpp> + +unsigned old_checks; + +template<typename T> +struct b { + virtual void next(T& x, boost::contract::virtual_* v = 0) { + boost::contract::old_ptr_if_copyable<T> old_x = + BOOST_CONTRACT_OLDOF(v, x); + boost::contract::check c = boost::contract::public_function(v, this) + .postcondition([&] { + if(old_x) { + BOOST_CONTRACT_ASSERT(x == *old_x + T(1)); + ++old_checks; + } + }) + ; + ++x; + } + BOOST_CONTRACT_OVERRIDE(next) +}; + +template<typename T> +struct a + #define BASES public b<T> + : BASES +{ + typedef BOOST_CONTRACT_BASE_TYPES(BASES) base_types; + #undef BASES + + virtual void next(T& x, boost::contract::virtual_* v = 0) /* override */ { + boost::contract::old_ptr_if_copyable<T> old_x = + BOOST_CONTRACT_OLDOF(v, x); + boost::contract::check c = boost::contract::public_function< + override_next>(v, &a::next, this, x) + .postcondition([&] { + if(old_x) { + BOOST_CONTRACT_ASSERT(x == *old_x + T(1)); + ++old_checks; + } + }) + ; + ++x; + } + BOOST_CONTRACT_OVERRIDE(next) +}; + +template<typename T> +void next(T& x) { + boost::contract::old_ptr_if_copyable<T> old_x = BOOST_CONTRACT_OLDOF(x); + boost::contract::check c = boost::contract::function() + .postcondition([&] { + if(old_x) { + BOOST_CONTRACT_ASSERT(x == *old_x + T(1)); + ++old_checks; + } + }) + ; + ++x; +} + +int main() { + int i = 1; // Test built-in copyable type. + cp c(1); // Test custom copyable type. + ncp n(1); // Test non-copyable type. + + // Test free functions (old values without `v`). + + unsigned cnt = + #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS + 1 + #else + 0 + #endif + ; + + old_checks = 0; + next(i); + BOOST_TEST_EQ(old_checks, cnt); + + old_checks = 0; + next(c); + BOOST_TEST_EQ(old_checks, cnt); + + old_checks = 0; + next(n); + BOOST_TEST_EQ(old_checks, 0u); + + // Test virtual functions (old values with `v`). + + cnt = + #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS + 2 + #else + 0 + #endif + ; + + a<int> ai; + old_checks = 0; + ai.next(i); + BOOST_TEST_EQ(old_checks, cnt); + + a<cp> ac; + old_checks = 0; + ac.next(c); + BOOST_TEST_EQ(old_checks, cnt); + + a<ncp> an; + old_checks = 0; + an.next(n); + BOOST_TEST_EQ(old_checks, 0u); + + return boost::report_errors(); +} + diff --git a/src/boost/libs/contract/test/old/if_copyable.hpp b/src/boost/libs/contract/test/old/if_copyable.hpp new file mode 100644 index 000000000..6bb6c1f8b --- /dev/null +++ b/src/boost/libs/contract/test/old/if_copyable.hpp @@ -0,0 +1,45 @@ + +#ifndef BOOST_CONTRACT_TEST_IF_COPYABLE_HPP_ +#define BOOST_CONTRACT_TEST_IF_COPYABLE_HPP_ + +// Copyright (C) 2008-2018 Lorenzo Caminiti +// Distributed under the Boost Software License, Version 1.0 (see accompanying +// file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt). +// See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html + +// Test old values of non-copyable types. + +#define BOOST_CONTRACT_TEST_IF_COPYABLE_TYPE(class_) \ + public: \ + explicit class_(int value) : value_(value) {} \ + \ + friend class_& operator++(class_& me) { ++me.value_; return me; } \ + \ + friend bool operator>(class_ const& left, class_ const& right) { \ + return left.value_ > right.value_; \ + } \ + \ + friend bool operator==(class_ const& left, class_ const& right) { \ + return left.value_ == right.value_; \ + } \ + \ + friend class_ operator+(class_ const& left, class_ const& right) { \ + return class_(left.value_ + right.value_); \ + } \ + \ + private: \ + int value_; + +struct cp { // Copyable type. + BOOST_CONTRACT_TEST_IF_COPYABLE_TYPE(cp) +}; + +struct ncp { + BOOST_CONTRACT_TEST_IF_COPYABLE_TYPE(ncp) + +private: // Non (publicly) copyable type. + ncp(ncp const& other) : value_(other.value_) {} +}; + +#endif // #include guard + diff --git a/src/boost/libs/contract/test/old/if_copyable_error.cpp b/src/boost/libs/contract/test/old/if_copyable_error.cpp new file mode 100644 index 000000000..34b029732 --- /dev/null +++ b/src/boost/libs/contract/test/old/if_copyable_error.cpp @@ -0,0 +1,43 @@ + +// Copyright (C) 2008-2018 Lorenzo Caminiti +// Distributed under the Boost Software License, Version 1.0 (see accompanying +// file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt). +// See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html + +// Test forcing compiler error for old values of non-copyable types. + +#include "if_copyable.hpp" +#include <boost/contract/function.hpp> +#include <boost/contract/old.hpp> +#include <boost/contract/check.hpp> +#include <boost/contract/assert.hpp> +#include <boost/noncopyable.hpp> + + +template<typename T> +void next(T& x) { + boost::contract::old_ptr<T> old_x = BOOST_CONTRACT_OLDOF(x); + boost::contract::check c = boost::contract::function() + .postcondition([&] { + // No need to check `if(old_x) ...` here. + BOOST_CONTRACT_ASSERT(x == *old_x + T(1)); + #ifdef BOOST_CONTRACT_NO_ALL + #error "force error if no contracts (ASSERT expands to nothing)" + #endif + }) + ; + ++x; +} + +int main() { + int i = 1; // Test built-in copyable type. + cp c(1); // Test custom copyable type. + ncp n(1); // Test non-copyable type. + + next(i); // OK. + next(c); // OK. + next(n); // Error. + + return 0; +} + diff --git a/src/boost/libs/contract/test/old/if_copyable_macro.cpp b/src/boost/libs/contract/test/old/if_copyable_macro.cpp new file mode 100644 index 000000000..ac31961a7 --- /dev/null +++ b/src/boost/libs/contract/test/old/if_copyable_macro.cpp @@ -0,0 +1,172 @@ + +// Copyright (C) 2008-2018 Lorenzo Caminiti +// Distributed under the Boost Software License, Version 1.0 (see accompanying +// file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt). +// See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html + +// Test old values of non-copyable types (using macro interface). + +#include "if_copyable.hpp" +#include "../detail/unprotected_commas.hpp" +#include <boost/contract_macro.hpp> +#include <boost/noncopyable.hpp> +#include <boost/detail/lightweight_test.hpp> + +unsigned old_checks; + +template<typename T> +struct b { + virtual void next(T& x, boost::contract::virtual_* v = 0) { + BOOST_CONTRACT_OLD_PTR_IF_COPYABLE( + typename boost::contract::test::detail::unprotected_commas<T, void, + void>::type1 + )( + (boost::contract::test::detail::unprotected_commas<void, void, + void>::same(v)), + old_x, + (boost::contract::test::detail::unprotected_commas<void, void, + void>::same(x)) + ); + BOOST_CONTRACT_PUBLIC_FUNCTION( + boost::contract::test::detail::unprotected_commas<void, void, + void>::same(v), + boost::contract::test::detail::unprotected_commas<void, void, + void>::same(this) + ) + BOOST_CONTRACT_POSTCONDITION([&] { + boost::contract::test::detail::unprotected_commas< + void, void, void>::call(); + if(old_x) { + BOOST_CONTRACT_ASSERT(x == *old_x + T(1)); + ++old_checks; + } + }) + ; + ++x; + } + BOOST_CONTRACT_OVERRIDE(next) +}; + +template<typename T> +struct a + #define BASES public b<T> + : BASES +{ + typedef BOOST_CONTRACT_BASE_TYPES(BASES) base_types; + #undef BASES + + virtual void next(T& x, boost::contract::virtual_* v = 0) /* override */ { + BOOST_CONTRACT_OLD_PTR_IF_COPYABLE( + typename boost::contract::test::detail::unprotected_commas<T, void, + void>::type1 + )( + (boost::contract::test::detail::unprotected_commas<void, void, + void>::same(v)), + old_x, + (boost::contract::test::detail::unprotected_commas<void, void, + void>::same(x)) + ); + BOOST_CONTRACT_PUBLIC_FUNCTION_OVERRIDE( + typename boost::contract::test::detail::unprotected_commas< + override_next, void, void>::type1 + )( + boost::contract::test::detail::unprotected_commas<void, void, + void>::same(v), + &a::next, + boost::contract::test::detail::unprotected_commas<void, void, + void>::same(this), + boost::contract::test::detail::unprotected_commas<void, void, + void>::same(x) + ) + BOOST_CONTRACT_POSTCONDITION([&] { + boost::contract::test::detail::unprotected_commas< + void, void, void>::call(); + if(old_x) { + BOOST_CONTRACT_ASSERT(x == *old_x + T(1)); + ++old_checks; + } + }) + ; + ++x; + } + BOOST_CONTRACT_OVERRIDE(next) +}; + +template<typename T> +void next(T& x) { + BOOST_CONTRACT_OLD_PTR_IF_COPYABLE( + typename boost::contract::test::detail::unprotected_commas<T, void, + void>::type1 + )( + old_x, + (boost::contract::test::detail::unprotected_commas<void, void, + void>::same(x)) + ); + BOOST_CONTRACT_FUNCTION() + BOOST_CONTRACT_POSTCONDITION([&] { + boost::contract::test::detail::unprotected_commas<void, void, void> + ::call(); + if(old_x) { + BOOST_CONTRACT_ASSERT(x == *old_x + T(1)); + ++old_checks; + } + }) + ; + ++x; +} + +int main() { + int i = 1; // Test built-in copyable type. + cp c(1); // Test custom copyable type. + ncp n(1); // Test non-copyable type. + + // Test free functions (old values without `v`). + + unsigned cnt = + #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS + 1 + #else + 0 + #endif + ; + + old_checks = 0; + next(i); + BOOST_TEST_EQ(old_checks, cnt); + + old_checks = 0; + next(c); + BOOST_TEST_EQ(old_checks, cnt); + + old_checks = 0; + next(n); + BOOST_TEST_EQ(old_checks, 0u); + + // Test virtual functions (old values with `v`). + + cnt = + #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS + 2 + #else + 0 + #endif + ; + + a<int> ai; + old_checks = 0; + ai.next(i); + BOOST_TEST_EQ(old_checks, cnt); + + a<cp> ac; + old_checks = 0; + ac.next(c); + BOOST_TEST_EQ(old_checks, cnt); + + a<ncp> an; + old_checks = 0; + an.next(n); + BOOST_TEST_EQ(old_checks, 0u); + + return boost::report_errors(); +} + diff --git a/src/boost/libs/contract/test/old/no_macro.cpp b/src/boost/libs/contract/test/old/no_macro.cpp new file mode 100644 index 000000000..d715f6ecb --- /dev/null +++ b/src/boost/libs/contract/test/old/no_macro.cpp @@ -0,0 +1,9 @@ + +// Copyright (C) 2008-2018 Lorenzo Caminiti +// Distributed under the Boost Software License, Version 1.0 (see accompanying +// file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt). +// See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html + +#define BOOST_CONTRACT_TEST_OLD_PTR_TYPE boost::contract::old_ptr +#include "no_macro.hpp" + diff --git a/src/boost/libs/contract/test/old/no_macro.hpp b/src/boost/libs/contract/test/old/no_macro.hpp new file mode 100644 index 000000000..1e75ac444 --- /dev/null +++ b/src/boost/libs/contract/test/old/no_macro.hpp @@ -0,0 +1,190 @@ + +// Copyright (C) 2008-2018 Lorenzo Caminiti +// Distributed under the Boost Software License, Version 1.0 (see accompanying +// file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt). +// See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html + +// Test old values without BOOST_CONTRACT_OLD macro. + +#ifndef BOOST_CONTRACT_TEST_OLD_PTR_TYPE + #error "must define BOOST_CONTRACT_TEST_OLD_PTR_TYPE" +#endif + +#include "../detail/oteststream.hpp" +#include "../detail/counter.hpp" +#include <boost/contract/function.hpp> +#include <boost/contract/public_function.hpp> +#include <boost/contract/base_types.hpp> +#include <boost/contract/override.hpp> +#include <boost/contract/assert.hpp> +#include <boost/contract/old.hpp> +#include <boost/contract/check.hpp> +#include <boost/detail/lightweight_test.hpp> +#include <cassert> + +boost::contract::test::detail::oteststream out; + +struct i_tag; typedef boost::contract::test::detail::counter<i_tag, int> i_type; +struct j_tag; typedef boost::contract::test::detail::counter<j_tag, int> j_type; + +struct b { + virtual void swap(i_type& i, j_type& j, boost::contract::virtual_* v = 0); +}; + +void b::swap(i_type& i, j_type& j, boost::contract::virtual_* v) { + BOOST_CONTRACT_TEST_OLD_PTR_TYPE<i_type> old_i = boost::contract::make_old( + v, boost::contract::copy_old(v) ? + i_type::eval(i) + : + boost::contract::null_old() + ); + BOOST_CONTRACT_TEST_OLD_PTR_TYPE<j_type> old_j; + boost::contract::check c = boost::contract::public_function(v, this) + .precondition([&] { + out << "b::swap::pre" << std::endl; + BOOST_CONTRACT_ASSERT(i.value != j.value); + }) + .old([&] { + out << "b::swap::old" << std::endl; + old_j = boost::contract::make_old(v, boost::contract::copy_old(v) ? + j_type::eval(j) : boost::contract::null_old()); + }) + .postcondition([&] { + out << "b::swap::post" << std::endl; + BOOST_CONTRACT_ASSERT(i.value == old_j->value); + BOOST_CONTRACT_ASSERT(j.value == old_i->value); + }) + ; + assert(false); +} + +struct a + #define BASES public b + : BASES +{ + typedef BOOST_CONTRACT_BASE_TYPES(BASES) base_types; + #undef BASES + + void swap(i_type& i, j_type& j, boost::contract::virtual_* v = 0) + /* override */ { + boost::contract::check c = boost::contract::public_function< + override_swap>(v, &a::swap, this, i, j); + + out << "a::swap::body" << std::endl; + int t = i.value; + i.value = j.value; + j.value = t; + } + BOOST_CONTRACT_OVERRIDE(swap) +}; + +struct x_tag; +typedef boost::contract::test::detail::counter<x_tag, char> x_type; + +struct y_tag; +typedef boost::contract::test::detail::counter<y_tag, char> y_type; + +void swap(x_type& x, y_type& y) { + BOOST_CONTRACT_TEST_OLD_PTR_TYPE<x_type> old_x = boost::contract::make_old( + boost::contract::copy_old() ? + x_type::eval(x) + : + boost::contract::null_old() + ); + BOOST_CONTRACT_TEST_OLD_PTR_TYPE<y_type> old_y; + boost::contract::check c = boost::contract::function() + .precondition([&] { + out << "swap::pre" << std::endl; + BOOST_CONTRACT_ASSERT(x.value != y.value); + }) + .old([&] { + out << "swap::old" << std::endl; + old_y = boost::contract::make_old(boost::contract::copy_old() ? + y_type::eval(y) : boost::contract::null_old()); + }) + .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; + char t = x.value; + x.value = y.value; + y.value = t; +} + +int main() { + std::ostringstream ok; + + out.str(""); + x_type x; x.value = 'a'; + y_type y; y.value = 'b'; + swap(x, y); + + ok.str(""); ok + #ifndef BOOST_CONTRACT_NO_PRECONDITIONS + << "swap::pre" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_OLDS + << "swap::old" << std::endl + #endif + << "swap::body" << std::endl + #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS + << "swap::post" << std::endl + #endif + ; + BOOST_TEST(out.eq(ok.str())); + + #ifndef BOOST_CONTRACT_NO_OLDS + #define BOOST_CONTRACT_TEST_old 1u + #else + #define BOOST_CONTRACT_TEST_old 0u + #endif + + BOOST_TEST_EQ(x.value, 'b'); + BOOST_TEST_EQ(x.copies(), BOOST_CONTRACT_TEST_old); + BOOST_TEST_EQ(x.evals(), BOOST_CONTRACT_TEST_old); + BOOST_TEST_EQ(x.ctors(), x.dtors() + 1); // 1 for local var. + + BOOST_TEST_EQ(y.value, 'a'); + BOOST_TEST_EQ(y.copies(), BOOST_CONTRACT_TEST_old); + BOOST_TEST_EQ(y.evals(), BOOST_CONTRACT_TEST_old); + BOOST_TEST_EQ(y.ctors(), y.dtors() + 1); // 1 for local var. + + a aa; + i_type i; i.value = 1; + j_type j; j.value = 2; + out.str(""); + aa.swap(i, j); + + ok.str(""); ok + #ifndef BOOST_CONTRACT_NO_PRECONDITIONS + << "b::swap::pre" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_OLDS + << "b::swap::old" << std::endl + #endif + << "a::swap::body" << std::endl + #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS + << "b::swap::old" << std::endl + << "b::swap::post" << std::endl + #endif + ; + BOOST_TEST(out.eq(ok.str())); + + BOOST_TEST_EQ(i.value, 2); + BOOST_TEST_EQ(i.copies(), BOOST_CONTRACT_TEST_old); + BOOST_TEST_EQ(i.evals(), BOOST_CONTRACT_TEST_old); + BOOST_TEST_EQ(i.ctors(), i.dtors() + 1); // 1 for local var. + + BOOST_TEST_EQ(j.value, 1); + BOOST_TEST_EQ(j.copies(), BOOST_CONTRACT_TEST_old); + BOOST_TEST_EQ(j.evals(), BOOST_CONTRACT_TEST_old); + BOOST_TEST_EQ(j.ctors(), j.dtors() + 1); // 1 for local var. + + #undef BOOST_CONTRACT_TEST_old + return boost::report_errors(); +} + diff --git a/src/boost/libs/contract/test/old/no_macro_if_copyable.cpp b/src/boost/libs/contract/test/old/no_macro_if_copyable.cpp new file mode 100644 index 000000000..88c30c10a --- /dev/null +++ b/src/boost/libs/contract/test/old/no_macro_if_copyable.cpp @@ -0,0 +1,9 @@ + +// Copyright (C) 2008-2018 Lorenzo Caminiti +// Distributed under the Boost Software License, Version 1.0 (see accompanying +// file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt). +// See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html + +#define BOOST_CONTRACT_TEST_OLD_PTR_TYPE boost::contract::old_ptr_if_copyable +#include "no_macro.hpp" + diff --git a/src/boost/libs/contract/test/old/no_make_old_error.cpp b/src/boost/libs/contract/test/old/no_make_old_error.cpp new file mode 100644 index 000000000..7d517fa48 --- /dev/null +++ b/src/boost/libs/contract/test/old/no_make_old_error.cpp @@ -0,0 +1,9 @@ + +// Copyright (C) 2008-2018 Lorenzo Caminiti +// Distributed under the Boost Software License, Version 1.0 (see accompanying +// file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt). +// See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html + +#define BOOST_CONTRACT_TEST_OLD_PTR_TYPE boost::contract::old_ptr +#include "no_make_old_error.hpp" + diff --git a/src/boost/libs/contract/test/old/no_make_old_error.hpp b/src/boost/libs/contract/test/old/no_make_old_error.hpp new file mode 100644 index 000000000..d637fade9 --- /dev/null +++ b/src/boost/libs/contract/test/old/no_make_old_error.hpp @@ -0,0 +1,21 @@ + +// Copyright (C) 2008-2018 Lorenzo Caminiti +// Distributed under the Boost Software License, Version 1.0 (see accompanying +// file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt). +// See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html + +// Test error when make_old(...) not used by mistake. + +#ifndef BOOST_CONTRACT_TEST_OLD_PTR_TYPE + #error "must define BOOST_CONTRACT_TEST_OLD_PTR_TYPE" +#endif + +#include <boost/contract/old.hpp> + +int main() { + int x = 1; + BOOST_CONTRACT_TEST_OLD_PTR_TYPE<int> old_x = boost::contract::copy_old() ? + x : boost::contract::null_old(); // Error (missing make_old(...)). + return 0; +} + diff --git a/src/boost/libs/contract/test/old/no_make_old_if_copyable_error.cpp b/src/boost/libs/contract/test/old/no_make_old_if_copyable_error.cpp new file mode 100644 index 000000000..4800fe8bf --- /dev/null +++ b/src/boost/libs/contract/test/old/no_make_old_if_copyable_error.cpp @@ -0,0 +1,9 @@ + +// Copyright (C) 2008-2018 Lorenzo Caminiti +// Distributed under the Boost Software License, Version 1.0 (see accompanying +// file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt). +// See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html + +#define BOOST_CONTRACT_TEST_OLD_PTR_TYPE boost::contract::old_ptr_if_copyable +#include "no_make_old_error.hpp" + diff --git a/src/boost/libs/contract/test/public_function/access.cpp b/src/boost/libs/contract/test/public_function/access.cpp new file mode 100644 index 000000000..5e6167734 --- /dev/null +++ b/src/boost/libs/contract/test/public_function/access.cpp @@ -0,0 +1,136 @@ + +// Copyright (C) 2008-2018 Lorenzo Caminiti +// Distributed under the Boost Software License, Version 1.0 (see accompanying +// file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt). +// See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html + +// Test making all contract extra declarations (base types, inv, etc.) private. + +#include "../detail/oteststream.hpp" +#include <boost/contract/base_types.hpp> +#include <boost/contract/override.hpp> +#include <boost/contract/public_function.hpp> +#include <boost/contract/check.hpp> +#include <boost/contract/assert.hpp> +#include <boost/detail/lightweight_test.hpp> +#include <sstream> + +boost::contract::test::detail::oteststream out; + +class b { + friend class boost::contract::access; + + static void static_invariant() { out << "b::static_inv" << std::endl; } + void invariant() const { out << "b::inv" << std::endl; } + +public: + virtual void f(char ch, boost::contract::virtual_* v = 0) { + boost::contract::check c = boost::contract::public_function(v, this) + .precondition([&] { + out << "b::f::pre" << std::endl; + BOOST_CONTRACT_ASSERT(ch == 'b'); + }) + .old([] { out << "b::f::old" << std::endl; }) + .postcondition([] { out << "b::f::post" << std::endl; }) + ; + out << "b::f::body" << std::endl; + } +}; + +class a + #define BASES public b + : BASES +{ + friend class boost::contract::access; + + // Private base types. + typedef BOOST_CONTRACT_BASE_TYPES(BASES) base_types; + #undef BASES + + // Private invariants. + static void static_invariant() { out << "a::static_inv" << std::endl; } + void invariant() const { out << "a::inv" << std::endl; } + + // Private override (always possible even when access is not friend). + BOOST_CONTRACT_OVERRIDE(f) + +public: + virtual void f(char ch, boost::contract::virtual_* v = 0) /* override */ { + boost::contract::check c = boost::contract::public_function<override_f>( + v, &a::f, this, ch) + .precondition([&] { + out << "a::f::pre" << std::endl; + BOOST_CONTRACT_ASSERT(ch == 'a'); + }) + .old([] { out << "a::f::old" << std::endl; }) + .postcondition([] { out << "a::f::post" << std::endl; }) + ; + out << "a::f::body" << std::endl; + } +}; + +int main() { + std::ostringstream ok; + + a aa; + out.str(""); + aa.f('a'); + ok.str(""); ok + #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS + << "b::static_inv" << std::endl + << "b::inv" << std::endl + << "a::static_inv" << std::endl + << "a::inv" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_PRECONDITIONS + << "b::f::pre" << std::endl + << "a::f::pre" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_OLDS + << "b::f::old" << std::endl + << "a::f::old" << std::endl + #endif + << "a::f::body" << std::endl + #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS + << "b::static_inv" << std::endl + << "b::inv" << std::endl + << "a::static_inv" << std::endl + << "a::inv" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS + << "b::f::old" << std::endl + << "b::f::post" << std::endl + // No old call here because not a base object. + << "a::f::post" << std::endl + #endif + ; + BOOST_TEST(out.eq(ok.str())); + + b bb; + out.str(""); + bb.f('b'); + ok.str(""); ok + #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS + << "b::static_inv" << std::endl + << "b::inv" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_PRECONDITIONS + << "b::f::pre" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_OLDS + << "b::f::old" << std::endl + #endif + << "b::f::body" << std::endl + #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS + << "b::static_inv" << std::endl + << "b::inv" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS + << "b::f::post" << std::endl + #endif + ; + BOOST_TEST(out.eq(ok.str())); + + return boost::report_errors(); +} + diff --git a/src/boost/libs/contract/test/public_function/decl.hpp b/src/boost/libs/contract/test/public_function/decl.hpp new file mode 100644 index 000000000..9927587fa --- /dev/null +++ b/src/boost/libs/contract/test/public_function/decl.hpp @@ -0,0 +1,162 @@ + +#ifndef BOOST_CONTRACT_TEST_PUBLIC_FUNCTION_DECL_HPP_ +#define BOOST_CONTRACT_TEST_PUBLIC_FUNCTION_DECL_HPP_ + +// Copyright (C) 2008-2018 Lorenzo Caminiti +// Distributed under the Boost Software License, Version 1.0 (see accompanying +// file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt). +// See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html + +// Test with and without pre, post, and inv declarations. + +#include "../detail/oteststream.hpp" +#include <boost/contract/public_function.hpp> +#include <boost/contract/base_types.hpp> +#include <boost/contract/override.hpp> +#include <boost/contract/check.hpp> +#include <boost/contract/assert.hpp> + +boost::contract::test::detail::oteststream out; + +bool c_pre = true, c_post = true; +bool c_entering_static_inv = true, c_entry_static_inv = true, + c_exit_static_inv = true; +bool c_entering_inv = true, c_entry_inv = true, c_exit_inv = true; +struct c { + #ifndef BOOST_CONTRACT_TEST_NO_C_STATIC_INV + static void static_invariant() { + out << "c::static_inv" << std::endl; + if(c_entering_static_inv) BOOST_CONTRACT_ASSERT(c_entry_static_inv); + else BOOST_CONTRACT_ASSERT(c_exit_static_inv); + c_entering_static_inv = false; + } + #endif + #ifndef BOOST_CONTRACT_TEST_NO_C_INV + void invariant() const { + out << "c::inv" << std::endl; + if(c_entering_inv) BOOST_CONTRACT_ASSERT(c_entry_inv); + else BOOST_CONTRACT_ASSERT(c_exit_inv); + c_entering_inv = false; + } + #endif + + virtual void f(boost::contract::virtual_* v = 0) { + boost::contract::check c = boost::contract::public_function(v, this) + #ifndef BOOST_CONTRACT_TEST_NO_C_PRE + .precondition([] { + out << "c::f::pre" << std::endl; + BOOST_CONTRACT_ASSERT(c_pre); + }) + #endif + .old([] { out << "c::f::old" << std::endl; }) + #ifndef BOOST_CONTRACT_TEST_NO_C_POST + .postcondition([] { + out << "c::f::post" << std::endl; + BOOST_CONTRACT_ASSERT(c_post); + }) + #endif + ; + out << "c::f::body" << std::endl; + } +}; + +bool b_pre = true, b_post = true; +bool b_entering_static_inv = true, b_entry_static_inv = true, + b_exit_static_inv = true; +bool b_entering_inv = true, b_entry_inv = true, b_exit_inv = true; +struct b + #define BASES public c + : BASES +{ + typedef BOOST_CONTRACT_BASE_TYPES(BASES) base_types; + #undef BASES + + #ifndef BOOST_CONTRACT_TEST_NO_B_STATIC_INV + static void static_invariant() { + out << "b::static_inv" << std::endl; + if(b_entering_static_inv) BOOST_CONTRACT_ASSERT(b_entry_static_inv); + else BOOST_CONTRACT_ASSERT(b_exit_static_inv); + b_entering_static_inv = false; + } + #endif + #ifndef BOOST_CONTRACT_TEST_NO_B_INV + void invariant() const { + out << "b::inv" << std::endl; + if(b_entering_inv) BOOST_CONTRACT_ASSERT(b_entry_inv); + else BOOST_CONTRACT_ASSERT(b_exit_inv); + b_entering_inv = false; + } + #endif + + virtual void f(boost::contract::virtual_* v = 0) { + boost::contract::check c = boost::contract::public_function(v, this) + #ifndef BOOST_CONTRACT_TEST_NO_B_PRE + .precondition([] { + out << "b::f::pre" << std::endl; + BOOST_CONTRACT_ASSERT(b_pre); + }) + #endif + .old([] { out << "b::f::old" << std::endl; }) + #ifndef BOOST_CONTRACT_TEST_NO_B_POST + .postcondition([] { + out << "b::f::post" << std::endl; + BOOST_CONTRACT_ASSERT(b_post); + }) + #endif + ; + out << "a::f::body" << std::endl; + } +}; + +bool a_pre = true, a_post = true; +bool a_entering_static_inv = true, a_entry_static_inv = true, + a_exit_static_inv = true; +bool a_entering_inv = true, a_entry_inv = true, a_exit_inv = true; +struct a + #define BASES public b + : BASES +{ + typedef BOOST_CONTRACT_BASE_TYPES(BASES) base_types; + #undef BASES + + #ifndef BOOST_CONTRACT_TEST_NO_A_STATIC_INV + static void static_invariant() { + out << "a::static_inv" << std::endl; + if(a_entering_static_inv) BOOST_CONTRACT_ASSERT(a_entry_static_inv); + else BOOST_CONTRACT_ASSERT(a_exit_static_inv); + a_entering_static_inv = false; + } + #endif + #ifndef BOOST_CONTRACT_TEST_NO_A_INV + void invariant() const { + out << "a::inv" << std::endl; + if(a_entering_inv) BOOST_CONTRACT_ASSERT(a_entry_inv); + else BOOST_CONTRACT_ASSERT(a_exit_inv); + a_entering_inv = false; + } + #endif + + virtual void f(boost::contract::virtual_* v = 0) /* override */ { + boost::contract::check c = boost::contract::public_function<override_f>( + v, &a::f, this) + #ifndef BOOST_CONTRACT_TEST_NO_A_PRE + .precondition([] { + out << "a::f::pre" << std::endl; + BOOST_CONTRACT_ASSERT(a_pre); + }) + #endif + .old([] { out << "a::f::old" << std::endl; }) + #ifndef BOOST_CONTRACT_TEST_NO_A_POST + .postcondition([] { + out << "a::f::post" << std::endl; + BOOST_CONTRACT_ASSERT(a_post); + }) + #endif + ; + out << "a::f::body" << std::endl; + } + BOOST_CONTRACT_OVERRIDE(f) +}; + +#endif // #include guard + diff --git a/src/boost/libs/contract/test/public_function/decl_entry_inv_all.cpp b/src/boost/libs/contract/test/public_function/decl_entry_inv_all.cpp new file mode 100644 index 000000000..14f019136 --- /dev/null +++ b/src/boost/libs/contract/test/public_function/decl_entry_inv_all.cpp @@ -0,0 +1,185 @@ + +// Copyright (C) 2008-2018 Lorenzo Caminiti +// Distributed under the Boost Software License, Version 1.0 (see accompanying +// file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt). +// See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html + +// Test all derived and base classes with entry invariants. + +#undef BOOST_CONTRACT_TEST_NO_A_INV +#undef BOOST_CONTRACT_TEST_NO_B_INV +#undef BOOST_CONTRACT_TEST_NO_C_INV +#include "decl.hpp" + +#include <boost/preprocessor/control/iif.hpp> +#include <boost/detail/lightweight_test.hpp> +#include <sstream> +#include <string> + +std::string ok_end() { + std::ostringstream ok; ok + #ifndef BOOST_CONTRACT_NO_PRECONDITIONS + << "c::f::pre" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_OLDS + << "c::f::old" << std::endl + << "b::f::old" << std::endl + << "a::f::old" << std::endl + #endif + << "a::f::body" << std::endl + #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS + << "c::static_inv" << std::endl + << "c::inv" << std::endl + << "b::static_inv" << std::endl + << "b::inv" << std::endl + << "a::static_inv" << std::endl + << "a::inv" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS + << "c::f::old" << std::endl + << "c::f::post" << std::endl + << "b::f::old" << std::endl + << "b::f::post" << std::endl + << "a::f::post" << std::endl + #endif + ; + return ok.str(); +} + +struct err {}; // Global decl so visible in MSVC10 lambdas. + +int main() { + std::ostringstream ok; + + #ifdef BOOST_CONTRACT_NO_ENTRY_INVARIANTS + #define BOOST_CONTRACT_TEST_entry_inv 0 + #else + #define BOOST_CONTRACT_TEST_entry_inv 1 + #endif + + a aa; + + a_entry_inv = true; + b_entry_inv = true; + c_entry_inv = true; + a_entering_inv = b_entering_inv = c_entering_inv = + BOOST_PP_IIF(BOOST_CONTRACT_TEST_entry_inv, true, false); + out.str(""); + aa.f(); + ok.str(""); ok // Test nothing failed. + #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS + << "c::static_inv" << std::endl + << "c::inv" << std::endl + << "b::static_inv" << std::endl + << "b::inv" << std::endl + << "a::static_inv" << std::endl + << "a::inv" << std::endl + #endif + << ok_end() + ; + BOOST_TEST(out.eq(ok.str())); + + boost::contract::set_entry_invariant_failure( + [] (boost::contract::from) { throw err(); }); + + a_entry_inv = false; + b_entry_inv = true; + c_entry_inv = true; + a_entering_inv = b_entering_inv = c_entering_inv = + BOOST_PP_IIF(BOOST_CONTRACT_TEST_entry_inv, true, false); + out.str(""); + try { + aa.f(); + #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS + BOOST_TEST(false); + } catch(err const&) { + #endif + ok.str(""); ok + #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS + << "c::static_inv" << std::endl + << "c::inv" << std::endl + << "b::static_inv" << std::endl + << "b::inv" << std::endl + << "a::static_inv" << std::endl + << "a::inv" << std::endl // Test this failed. + #else + << ok_end() + #endif + ; + BOOST_TEST(out.eq(ok.str())); + } catch(...) { BOOST_TEST(false); } + + a_entry_inv = true; + b_entry_inv = false; + c_entry_inv = true; + a_entering_inv = b_entering_inv = c_entering_inv = + BOOST_PP_IIF(BOOST_CONTRACT_TEST_entry_inv, true, false); + out.str(""); + try { + aa.f(); + #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS + BOOST_TEST(false); + } catch(err const&) { + #endif + ok.str(""); ok + #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS + << "c::static_inv" << std::endl + << "c::inv" << std::endl + << "b::static_inv" << std::endl + << "b::inv" << std::endl // Test this failed. + #else + << ok_end() + #endif + ; + BOOST_TEST(out.eq(ok.str())); + } catch(...) { BOOST_TEST(false); } + + a_entry_inv = true; + b_entry_inv = true; + c_entry_inv = false; + a_entering_inv = b_entering_inv = c_entering_inv = + BOOST_PP_IIF(BOOST_CONTRACT_TEST_entry_inv, true, false); + out.str(""); + try { + aa.f(); + #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS + BOOST_TEST(false); + } catch(err const&) { + #endif + ok.str(""); ok + #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS + << "c::static_inv" << std::endl + << "c::inv" << std::endl // Test this failed. + #else + << ok_end() + #endif + ; + BOOST_TEST(out.eq(ok.str())); + } catch(...) { BOOST_TEST(false); } + + a_entry_inv = false; + b_entry_inv = false; + c_entry_inv = false; + a_entering_inv = b_entering_inv = c_entering_inv = + BOOST_PP_IIF(BOOST_CONTRACT_TEST_entry_inv, true, false); + out.str(""); + try { + aa.f(); + #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS + BOOST_TEST(false); + } catch(err const&) { + #endif + ok.str(""); ok + #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS + << "c::static_inv" << std::endl + << "c::inv" << std::endl // Test this failed (as all did). + #else + << ok_end() + #endif + ; + BOOST_TEST(out.eq(ok.str())); + } catch(...) { BOOST_TEST(false); } + + return boost::report_errors(); +} + diff --git a/src/boost/libs/contract/test/public_function/decl_entry_inv_ends.cpp b/src/boost/libs/contract/test/public_function/decl_entry_inv_ends.cpp new file mode 100644 index 000000000..21883ee03 --- /dev/null +++ b/src/boost/libs/contract/test/public_function/decl_entry_inv_ends.cpp @@ -0,0 +1,179 @@ + +// Copyright (C) 2008-2018 Lorenzo Caminiti +// Distributed under the Boost Software License, Version 1.0 (see accompanying +// file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt). +// See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html + +// Test only derived and grandparent classes (ends) with entry invariants. + +#undef BOOST_CONTRACT_TEST_NO_A_INV +#define BOOST_CONTRACT_TEST_NO_B_INV +#undef BOOST_CONTRACT_TEST_NO_C_INV +#include "decl.hpp" + +#include <boost/preprocessor/control/iif.hpp> +#include <boost/detail/lightweight_test.hpp> +#include <sstream> +#include <string> + +std::string ok_end() { + std::ostringstream ok; ok + #ifndef BOOST_CONTRACT_NO_PRECONDITIONS + << "c::f::pre" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_OLDS + << "c::f::old" << std::endl + << "b::f::old" << std::endl + << "a::f::old" << std::endl + #endif + << "a::f::body" << std::endl + #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS + << "c::static_inv" << std::endl + << "c::inv" << std::endl + << "b::static_inv" << std::endl + << "a::static_inv" << std::endl + << "a::inv" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS + << "c::f::old" << std::endl + << "c::f::post" << std::endl + << "b::f::old" << std::endl + << "b::f::post" << std::endl + << "a::f::post" << std::endl + #endif + ; + return ok.str(); +} + +struct err {}; // Global decl so visible in MSVC10 lambdas. + +int main() { + std::ostringstream ok; + + #ifdef BOOST_CONTRACT_NO_ENTRY_INVARIANTS + #define BOOST_CONTRACT_TEST_entry_inv 0 + #else + #define BOOST_CONTRACT_TEST_entry_inv 1 + #endif + + a aa; + + a_entry_inv = true; + b_entry_inv = true; + c_entry_inv = true; + a_entering_inv = b_entering_inv = c_entering_inv = + BOOST_PP_IIF(BOOST_CONTRACT_TEST_entry_inv, true, false); + out.str(""); + aa.f(); + ok.str(""); ok // Test nothing failed. + #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS + << "c::static_inv" << std::endl + << "c::inv" << std::endl + << "b::static_inv" << std::endl + << "a::static_inv" << std::endl + << "a::inv" << std::endl + #endif + << ok_end() + ; + BOOST_TEST(out.eq(ok.str())); + + boost::contract::set_entry_invariant_failure( + [] (boost::contract::from) { throw err(); }); + + a_entry_inv = false; + b_entry_inv = true; + c_entry_inv = true; + a_entering_inv = b_entering_inv = c_entering_inv = + BOOST_PP_IIF(BOOST_CONTRACT_TEST_entry_inv, true, false); + out.str(""); + try { + aa.f(); + #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS + BOOST_TEST(false); + } catch(err const&) { + #endif + ok.str(""); ok + #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS + << "c::static_inv" << std::endl + << "c::inv" << std::endl + << "b::static_inv" << std::endl + << "a::static_inv" << std::endl + << "a::inv" << std::endl // Test this failed. + #else + << ok_end() + #endif + ; + BOOST_TEST(out.eq(ok.str())); + } catch(...) { BOOST_TEST(false); } + + a_entry_inv = true; + b_entry_inv = false; + c_entry_inv = true; + a_entering_inv = b_entering_inv = c_entering_inv = + BOOST_PP_IIF(BOOST_CONTRACT_TEST_entry_inv, true, false); + out.str(""); + try { + aa.f(); + ok.str(""); ok + #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS + << "c::static_inv" << std::endl + << "c::inv" << std::endl + << "b::static_inv" << std::endl + << "a::static_inv" << std::endl + << "a::inv" << std::endl + #endif + << ok_end() + ; + BOOST_TEST(out.eq(ok.str())); + } catch(...) { BOOST_TEST(false); } + + a_entry_inv = true; + b_entry_inv = true; + c_entry_inv = false; + a_entering_inv = b_entering_inv = c_entering_inv = + BOOST_PP_IIF(BOOST_CONTRACT_TEST_entry_inv, true, false); + out.str(""); + try { + aa.f(); + #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS + BOOST_TEST(false); + } catch(err const&) { + #endif + ok.str(""); ok + #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS + << "c::static_inv" << std::endl + << "c::inv" << std::endl // Test this failed. + #else + << ok_end() + #endif + ; + BOOST_TEST(out.eq(ok.str())); + } catch(...) { BOOST_TEST(false); } + + a_entry_inv = false; + b_entry_inv = false; + c_entry_inv = false; + a_entering_inv = b_entering_inv = c_entering_inv = + BOOST_PP_IIF(BOOST_CONTRACT_TEST_entry_inv, true, false); + out.str(""); + try { + aa.f(); + #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS + BOOST_TEST(false); + } catch(err const&) { + #endif + ok.str(""); ok + #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS + << "c::static_inv" << std::endl + << "c::inv" << std::endl // Test this failed (as all did). + #else + << ok_end() + #endif + ; + BOOST_TEST(out.eq(ok.str())); + } catch(...) { BOOST_TEST(false); } + + #undef BOOST_CONTRACT_TEST_entry_inv + return boost::report_errors(); +} + diff --git a/src/boost/libs/contract/test/public_function/decl_entry_inv_mid.cpp b/src/boost/libs/contract/test/public_function/decl_entry_inv_mid.cpp new file mode 100644 index 000000000..1dd68516f --- /dev/null +++ b/src/boost/libs/contract/test/public_function/decl_entry_inv_mid.cpp @@ -0,0 +1,172 @@ + +// Copyright (C) 2008-2018 Lorenzo Caminiti +// Distributed under the Boost Software License, Version 1.0 (see accompanying +// file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt). +// See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html + +// Test only middle base class with entry invariants. + +#define BOOST_CONTRACT_TEST_NO_A_INV +#undef BOOST_CONTRACT_TEST_NO_B_INV +#define BOOST_CONTRACT_TEST_NO_C_INV +#include "decl.hpp" + +#include <boost/preprocessor/control/iif.hpp> +#include <boost/detail/lightweight_test.hpp> +#include <sstream> +#include <string> + +std::string ok_end() { + std::ostringstream ok; ok + #ifndef BOOST_CONTRACT_NO_PRECONDITIONS + << "c::f::pre" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_OLDS + << "c::f::old" << std::endl + << "b::f::old" << std::endl + << "a::f::old" << std::endl + #endif + << "a::f::body" << std::endl + #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS + << "c::static_inv" << std::endl + << "b::static_inv" << std::endl + << "b::inv" << std::endl + << "a::static_inv" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS + << "c::f::old" << std::endl + << "c::f::post" << std::endl + << "b::f::old" << std::endl + << "b::f::post" << std::endl + << "a::f::post" << std::endl + #endif + ; + return ok.str(); +} + +struct err {}; // Global decl so visible in MSVC10 lambdas. + +int main() { + std::ostringstream ok; + + #ifdef BOOST_CONTRACT_NO_ENTRY_INVARIANTS + #define BOOST_CONTRACT_TEST_entry_inv 0 + #else + #define BOOST_CONTRACT_TEST_entry_inv 1 + #endif + + a aa; + + a_entry_inv = true; + b_entry_inv = true; + c_entry_inv = true; + a_entering_inv = b_entering_inv = c_entering_inv = + BOOST_PP_IIF(BOOST_CONTRACT_TEST_entry_inv, true, false); + out.str(""); + aa.f(); + ok.str(""); ok // Test nothing failed. + #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS + << "c::static_inv" << std::endl + << "b::static_inv" << std::endl + << "b::inv" << std::endl + << "a::static_inv" << std::endl + #endif + << ok_end() + ; + BOOST_TEST(out.eq(ok.str())); + + boost::contract::set_entry_invariant_failure( + [] (boost::contract::from) { throw err(); }); + + a_entry_inv = false; + b_entry_inv = true; + c_entry_inv = true; + a_entering_inv = b_entering_inv = c_entering_inv = + BOOST_PP_IIF(BOOST_CONTRACT_TEST_entry_inv, true, false); + out.str(""); + try { + aa.f(); + ok.str(""); ok + #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS + << "c::static_inv" << std::endl + << "b::static_inv" << std::endl + << "b::inv" << std::endl + << "a::static_inv" << std::endl + #endif + << ok_end() + ; + BOOST_TEST(out.eq(ok.str())); + } catch(...) { BOOST_TEST(false); } + + a_entry_inv = true; + b_entry_inv = false; + c_entry_inv = true; + a_entering_inv = b_entering_inv = c_entering_inv = + BOOST_PP_IIF(BOOST_CONTRACT_TEST_entry_inv, true, false); + out.str(""); + try { + aa.f(); + #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS + BOOST_TEST(false); + } catch(err const&) { + #endif + ok.str(""); ok + #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS + << "c::static_inv" << std::endl + << "b::static_inv" << std::endl + << "b::inv" << std::endl // Test this fail. + #else + << ok_end() + #endif + ; + BOOST_TEST(out.eq(ok.str())); + } catch(...) { BOOST_TEST(false); } + + a_entry_inv = true; + b_entry_inv = true; + c_entry_inv = false; + a_entering_inv = b_entering_inv = c_entering_inv = + BOOST_PP_IIF(BOOST_CONTRACT_TEST_entry_inv, true, false); + out.str(""); + try { + aa.f(); + ok.str(""); ok + #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS + << "c::static_inv" << std::endl + << "b::static_inv" << std::endl + << "b::inv" << std::endl + << "a::static_inv" << std::endl + #endif + << ok_end() + ; + BOOST_TEST(out.eq(ok.str())); + } catch(...) { BOOST_TEST(false); } + + a_entry_inv = false; + b_entry_inv = false; + c_entry_inv = false; + a_entering_inv = b_entering_inv = c_entering_inv = + BOOST_PP_IIF(BOOST_CONTRACT_TEST_entry_inv, true, false); + out.str(""); + try { + aa.f(); + #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS + BOOST_TEST(false); + } catch(err const&) { + #endif + ok.str(""); ok + #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS + << "c::static_inv" << std::endl + << "b::static_inv" << std::endl + << "b::inv" << std::endl // Test this failed (as all did). + #else + << ok_end() + #endif + ; + BOOST_TEST(out.eq(ok.str())); + } catch(...) { BOOST_TEST(false); } + + #undef BOOST_CONTRACT_TEST_entry_inv + return boost::report_errors(); +} + diff --git a/src/boost/libs/contract/test/public_function/decl_entry_inv_none.cpp b/src/boost/libs/contract/test/public_function/decl_entry_inv_none.cpp new file mode 100644 index 000000000..e89b09a85 --- /dev/null +++ b/src/boost/libs/contract/test/public_function/decl_entry_inv_none.cpp @@ -0,0 +1,105 @@ + +// Copyright (C) 2008-2018 Lorenzo Caminiti +// Distributed under the Boost Software License, Version 1.0 (see accompanying +// file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt). +// See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html + +// Test all derived and base classes without entry invariants. + +#define BOOST_CONTRACT_TEST_NO_A_INV +#define BOOST_CONTRACT_TEST_NO_B_INV +#define BOOST_CONTRACT_TEST_NO_C_INV +#include "decl.hpp" + +#include <boost/preprocessor/control/iif.hpp> +#include <boost/detail/lightweight_test.hpp> +#include <sstream> + +int main() { + std::ostringstream ok; + ok.str(""); ok // Test nothing fails. + #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS + << "c::static_inv" << std::endl + << "b::static_inv" << std::endl + << "a::static_inv" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_PRECONDITIONS + << "c::f::pre" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_OLDS + << "c::f::old" << std::endl + << "b::f::old" << std::endl + << "a::f::old" << std::endl + #endif + << "a::f::body" << std::endl + #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS + << "c::static_inv" << std::endl + << "b::static_inv" << std::endl + << "a::static_inv" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS + << "c::f::old" << std::endl + << "c::f::post" << std::endl + << "b::f::old" << std::endl + << "b::f::post" << std::endl + << "a::f::post" << std::endl + #endif + ; + + #ifdef BOOST_CONTRACT_NO_ENTRY_INVARIANTS + #define BOOST_CONTRACT_TEST_entry_inv 0 + #else + #define BOOST_CONTRACT_TEST_entry_inv 1 + #endif + + a aa; + + a_entry_inv = true; + b_entry_inv = true; + c_entry_inv = true; + a_entering_inv = b_entering_inv = c_entering_inv = + BOOST_PP_IIF(BOOST_CONTRACT_TEST_entry_inv, true, false); + out.str(""); + aa.f(); + BOOST_TEST(out.eq(ok.str())); + + a_entry_inv = false; + b_entry_inv = true; + c_entry_inv = true; + a_entering_inv = b_entering_inv = c_entering_inv = + BOOST_PP_IIF(BOOST_CONTRACT_TEST_entry_inv, true, false); + out.str(""); + aa.f(); + BOOST_TEST(out.eq(ok.str())); + + a_entry_inv = true; + b_entry_inv = false; + c_entry_inv = true; + a_entering_inv = b_entering_inv = c_entering_inv = + BOOST_PP_IIF(BOOST_CONTRACT_TEST_entry_inv, true, false); + out.str(""); + aa.f(); + BOOST_TEST(out.eq(ok.str())); + + a_entry_inv = true; + b_entry_inv = true; + c_entry_inv = false; + a_entering_inv = b_entering_inv = c_entering_inv = + BOOST_PP_IIF(BOOST_CONTRACT_TEST_entry_inv, true, false); + out.str(""); + aa.f(); + BOOST_TEST(out.eq(ok.str())); + + a_entry_inv = false; + b_entry_inv = false; + c_entry_inv = false; + a_entering_inv = b_entering_inv = c_entering_inv = + BOOST_PP_IIF(BOOST_CONTRACT_TEST_entry_inv, true, false); + out.str(""); + aa.f(); + BOOST_TEST(out.eq(ok.str())); + + #undef BOOST_CONTRACT_TEST_entry_inv + return boost::report_errors(); +} + diff --git a/src/boost/libs/contract/test/public_function/decl_entry_static_inv_all.cpp b/src/boost/libs/contract/test/public_function/decl_entry_static_inv_all.cpp new file mode 100644 index 000000000..aad1a91d2 --- /dev/null +++ b/src/boost/libs/contract/test/public_function/decl_entry_static_inv_all.cpp @@ -0,0 +1,183 @@ + +// Copyright (C) 2008-2018 Lorenzo Caminiti +// Distributed under the Boost Software License, Version 1.0 (see accompanying +// file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt). +// See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html + +// Test all derived and base classes with entry static invariants. + +#undef BOOST_CONTRACT_TEST_NO_A_STATIC_INV +#undef BOOST_CONTRACT_TEST_NO_B_STATIC_INV +#undef BOOST_CONTRACT_TEST_NO_C_STATIC_INV +#include "decl.hpp" + +#include <boost/preprocessor/control/iif.hpp> +#include <boost/detail/lightweight_test.hpp> +#include <sstream> +#include <string> + +std::string ok_end() { + std::ostringstream ok; ok + #ifndef BOOST_CONTRACT_NO_PRECONDITIONS + << "c::f::pre" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_OLDS + << "c::f::old" << std::endl + << "b::f::old" << std::endl + << "a::f::old" << std::endl + #endif + << "a::f::body" << std::endl + #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS + << "c::static_inv" << std::endl + << "c::inv" << std::endl + << "b::static_inv" << std::endl + << "b::inv" << std::endl + << "a::static_inv" << std::endl + << "a::inv" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS + << "c::f::old" << std::endl + << "c::f::post" << std::endl + << "b::f::old" << std::endl + << "b::f::post" << std::endl + << "a::f::post" << std::endl + #endif + ; + return ok.str(); +} + +struct err {}; // Global decl so visible in MSVC10 lambdas. + +int main() { + std::ostringstream ok; + + #ifdef BOOST_CONTRACT_NO_ENTRY_INVARIANTS + #define BOOST_CONTRACT_TEST_entry_inv 0 + #else + #define BOOST_CONTRACT_TEST_entry_inv 1 + #endif + + a aa; + + a_entry_static_inv = true; + b_entry_static_inv = true; + c_entry_static_inv = true; + a_entering_static_inv = b_entering_static_inv = c_entering_static_inv = + BOOST_PP_IIF(BOOST_CONTRACT_TEST_entry_inv, true, false); + out.str(""); + aa.f(); + ok.str(""); ok // Test nothing failed. + #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS + << "c::static_inv" << std::endl + << "c::inv" << std::endl + << "b::static_inv" << std::endl + << "b::inv" << std::endl + << "a::static_inv" << std::endl + << "a::inv" << std::endl + #endif + << ok_end() + ; + BOOST_TEST(out.eq(ok.str())); + + boost::contract::set_entry_invariant_failure( + [] (boost::contract::from) { throw err(); }); + + a_entry_static_inv = false; + b_entry_static_inv = true; + c_entry_static_inv = true; + a_entering_static_inv = b_entering_static_inv = c_entering_static_inv = + BOOST_PP_IIF(BOOST_CONTRACT_TEST_entry_inv, true, false); + out.str(""); + try { + aa.f(); + #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS + BOOST_TEST(false); + } catch(err const&) { + #endif + ok.str(""); ok + #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS + << "c::static_inv" << std::endl + << "c::inv" << std::endl + << "b::static_inv" << std::endl + << "b::inv" << std::endl + << "a::static_inv" << std::endl // Test this failed. + #else + << ok_end() + #endif + ; + BOOST_TEST(out.eq(ok.str())); + } catch(...) { BOOST_TEST(false); } + + a_entry_static_inv = true; + b_entry_static_inv = false; + c_entry_static_inv = true; + a_entering_static_inv = b_entering_static_inv = c_entering_static_inv = + BOOST_PP_IIF(BOOST_CONTRACT_TEST_entry_inv, true, false); + out.str(""); + try { + aa.f(); + #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS + BOOST_TEST(false); + } catch(err const&) { + #endif + ok.str(""); ok + #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS + << "c::static_inv" << std::endl + << "c::inv" << std::endl + << "b::static_inv" << std::endl // Test this failed. + #else + << ok_end() + #endif + ; + BOOST_TEST(out.eq(ok.str())); + } catch(...) { BOOST_TEST(false); } + + a_entry_static_inv = true; + b_entry_static_inv = true; + c_entry_static_inv = false; + a_entering_static_inv = b_entering_static_inv = c_entering_static_inv = + BOOST_PP_IIF(BOOST_CONTRACT_TEST_entry_inv, true, false); + out.str(""); + try { + aa.f(); + #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS + BOOST_TEST(false); + } catch(err const&) { + #endif + ok.str(""); ok + #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS + << "c::static_inv" << std::endl // Test this failed. + #else + << ok_end() + #endif + ; + BOOST_TEST(out.eq(ok.str())); + } catch(...) { BOOST_TEST(false); } + + a_entry_static_inv = false; + b_entry_static_inv = false; + c_entry_static_inv = false; + a_entering_static_inv = b_entering_static_inv = c_entering_static_inv = + BOOST_PP_IIF(BOOST_CONTRACT_TEST_entry_inv, true, false); + out.str(""); + try { + aa.f(); + #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS + BOOST_TEST(false); + } catch(err const&) { + #endif + ok.str(""); ok + #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS + // Test this failed (as all did). + << "c::static_inv" << std::endl + #else + << ok_end() + #endif + ; + BOOST_TEST(out.eq(ok.str())); + } catch(...) { BOOST_TEST(false); } + + #undef BOOST_CONTRACT_TEST_entry_inv + return boost::report_errors(); +} + diff --git a/src/boost/libs/contract/test/public_function/decl_entry_static_inv_ends.cpp b/src/boost/libs/contract/test/public_function/decl_entry_static_inv_ends.cpp new file mode 100644 index 000000000..ade705ce3 --- /dev/null +++ b/src/boost/libs/contract/test/public_function/decl_entry_static_inv_ends.cpp @@ -0,0 +1,198 @@ + +// Copyright (C) 2008-2018 Lorenzo Caminiti +// Distributed under the Boost Software License, Version 1.0 (see accompanying +// file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt). +// See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html + +// Test only derived and grandparent classes (ends) with entry static inv. + +#undef BOOST_CONTRACT_TEST_NO_A_STATIC_INV +#define BOOST_CONTRACT_TEST_NO_B_STATIC_INV +#undef BOOST_CONTRACT_TEST_NO_C_STATIC_INV +#include "decl.hpp" + +#include <boost/preprocessor/control/iif.hpp> +#include <boost/detail/lightweight_test.hpp> +#include <sstream> +#include <string> + +std::string ok_end() { + std::ostringstream ok; ok + #ifndef BOOST_CONTRACT_NO_PRECONDITIONS + << "c::f::pre" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_OLDS + << "c::f::old" << std::endl + << "b::f::old" << std::endl + << "a::f::old" << std::endl + #endif + << "a::f::body" << std::endl + #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS + << "c::static_inv" << std::endl + << "c::inv" << std::endl + << "b::inv" << std::endl + << "a::static_inv" << std::endl + << "a::inv" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS + << "c::f::old" << std::endl + << "c::f::post" << std::endl + << "b::f::old" << std::endl + << "b::f::post" << std::endl + << "a::f::post" << std::endl + #endif + ; + return ok.str(); +} + +struct err {}; // Global decl so visible in MSVC10 lambdas. + +int main() { + std::ostringstream ok; + + #ifdef BOOST_CONTRACT_NO_ENTRY_INVARIANTS + #define BOOST_CONTRACT_TEST_entry_inv 0 + #else + #define BOOST_CONTRACT_TEST_entry_inv 1 + #endif + + a aa; + + a_entry_static_inv = true; + b_entry_static_inv = true; + c_entry_static_inv = true; + a_entering_static_inv = b_entering_static_inv = c_entering_static_inv = + BOOST_PP_IIF(BOOST_CONTRACT_TEST_entry_inv, true, false); + out.str(""); + aa.f(); + ok.str(""); ok + #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS + << "c::static_inv" << std::endl + << "c::inv" << std::endl + << "b::inv" << std::endl + << "a::static_inv" << std::endl + << "a::inv" << std::endl + #endif + << ok_end() + ; + BOOST_TEST(out.eq(ok.str())); + + boost::contract::set_entry_invariant_failure( + [] (boost::contract::from) { throw err(); }); + + a_entry_static_inv = false; + b_entry_static_inv = true; + c_entry_static_inv = true; + a_entering_static_inv = b_entering_static_inv = c_entering_static_inv = + BOOST_PP_IIF(BOOST_CONTRACT_TEST_entry_inv, true, false); + out.str(""); + try { + aa.f(); + #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS + BOOST_TEST(false); + } catch(err const&) { + #endif + ok.str(""); ok + #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS + << "c::static_inv" << std::endl + << "c::inv" << std::endl + << "b::inv" << std::endl + << "a::static_inv" << std::endl // Test this failed. + #else + << ok_end() + #endif + ; + BOOST_TEST(out.eq(ok.str())); + } catch(...) { BOOST_TEST(false); } + + a_entry_static_inv = true; + b_entry_static_inv = false; + c_entry_static_inv = true; + a_entering_static_inv = b_entering_static_inv = c_entering_static_inv =true; + out.str(""); + try { + aa.f(); + ok.str(""); ok + #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS + << "c::static_inv" << std::endl + << "c::inv" << std::endl + << "b::inv" << std::endl + << "a::static_inv" << std::endl + << "a::inv" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_PRECONDITIONS + << "c::f::pre" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_OLDS + << "c::f::old" << std::endl + << "b::f::old" << std::endl + << "a::f::old" << std::endl + #endif + << "a::f::body" << std::endl + #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS + << "c::static_inv" << std::endl + << "c::inv" << std::endl + << "b::inv" << std::endl + << "a::static_inv" << std::endl + << "a::inv" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS + << "c::f::old" << std::endl + << "c::f::post" << std::endl + << "b::f::old" << std::endl + << "b::f::post" << std::endl + << "a::f::post" << std::endl + #endif + ; + BOOST_TEST(out.eq(ok.str())); + } catch(...) { BOOST_TEST(false); } + + a_entry_static_inv = true; + b_entry_static_inv = true; + c_entry_static_inv = false; + a_entering_static_inv = b_entering_static_inv = c_entering_static_inv = + BOOST_PP_IIF(BOOST_CONTRACT_TEST_entry_inv, true, false); + out.str(""); + try { + aa.f(); + #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS + BOOST_TEST(false); + } catch(err const&) { + #endif + ok.str(""); ok + #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS + << "c::static_inv" << std::endl // Test this failed. + #else + << ok_end() + #endif + ; + BOOST_TEST(out.eq(ok.str())); + } catch(...) { BOOST_TEST(false); } + + a_entry_static_inv = false; + b_entry_static_inv = false; + c_entry_static_inv = false; + a_entering_static_inv = b_entering_static_inv = c_entering_static_inv = + BOOST_PP_IIF(BOOST_CONTRACT_TEST_entry_inv, true, false); + out.str(""); + try { + aa.f(); + #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS + BOOST_TEST(false); + } catch(err const&) { + #endif + ok.str(""); ok + #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS + // Test this failed (as all did). + << "c::static_inv" << std::endl + #else + << ok_end() + #endif + ; + BOOST_TEST(out.eq(ok.str())); + } catch(...) { BOOST_TEST(false); } + + #undef BOOST_CONTRACT_TEST_entry_inv + return boost::report_errors(); +} + diff --git a/src/boost/libs/contract/test/public_function/decl_entry_static_inv_mid.cpp b/src/boost/libs/contract/test/public_function/decl_entry_static_inv_mid.cpp new file mode 100644 index 000000000..d7cb7e9cc --- /dev/null +++ b/src/boost/libs/contract/test/public_function/decl_entry_static_inv_mid.cpp @@ -0,0 +1,169 @@ + +// Copyright (C) 2008-2018 Lorenzo Caminiti +// Distributed under the Boost Software License, Version 1.0 (see accompanying +// file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt). +// See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html + +// Test only middle base class with entry static invariants. + +#define BOOST_CONTRACT_TEST_NO_A_STATIC_INV +#undef BOOST_CONTRACT_TEST_NO_B_STATIC_INV +#define BOOST_CONTRACT_TEST_NO_C_STATIC_INV +#include "decl.hpp" + +#include <boost/preprocessor/control/iif.hpp> +#include <boost/detail/lightweight_test.hpp> +#include <sstream> +#include <string> + +std::string ok_end() { + std::ostringstream ok; ok + #ifndef BOOST_CONTRACT_NO_PRECONDITIONS + << "c::f::pre" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_OLDS + << "c::f::old" << std::endl + << "b::f::old" << std::endl + << "a::f::old" << std::endl + #endif + << "a::f::body" << std::endl + #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS + << "c::inv" << std::endl + << "b::static_inv" << std::endl + << "b::inv" << std::endl + << "a::inv" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS + << "c::f::old" << std::endl + << "c::f::post" << std::endl + << "b::f::old" << std::endl + << "b::f::post" << std::endl + << "a::f::post" << std::endl + #endif + ; + return ok.str(); +} + +struct err {}; // Global decl so visible in MSVC10 lambdas. + +int main() { + std::ostringstream ok; + + #ifdef BOOST_CONTRACT_NO_ENTRY_INVARIANTS + #define BOOST_CONTRACT_TEST_entry_inv 0 + #else + #define BOOST_CONTRACT_TEST_entry_inv 1 + #endif + + a aa; + + a_entry_static_inv = true; + b_entry_static_inv = true; + c_entry_static_inv = true; + a_entering_static_inv = b_entering_static_inv = c_entering_static_inv = + BOOST_PP_IIF(BOOST_CONTRACT_TEST_entry_inv, true, false); + out.str(""); + aa.f(); + ok.str(""); ok // Test nothing failed. + #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS + << "c::inv" << std::endl + << "b::static_inv" << std::endl + << "b::inv" << std::endl + << "a::inv" << std::endl + #endif + << ok_end() + ; + BOOST_TEST(out.eq(ok.str())); + + boost::contract::set_entry_invariant_failure( + [] (boost::contract::from) { throw err(); }); + + a_entry_static_inv = false; + b_entry_static_inv = true; + c_entry_static_inv = true; + a_entering_static_inv = b_entering_static_inv = c_entering_static_inv =true; + out.str(""); + try { + aa.f(); + ok.str(""); ok + #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS + << "c::inv" << std::endl + << "b::static_inv" << std::endl + << "b::inv" << std::endl + << "a::inv" << std::endl + #endif + << ok_end() + ; + BOOST_TEST(out.eq(ok.str())); + } catch(...) { BOOST_TEST(false); } + + a_entry_static_inv = true; + b_entry_static_inv = false; + c_entry_static_inv = true; + a_entering_static_inv = b_entering_static_inv = c_entering_static_inv = + BOOST_PP_IIF(BOOST_CONTRACT_TEST_entry_inv, true, false); + out.str(""); + try { + aa.f(); + #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS + BOOST_TEST(false); + } catch(err const&) { + #endif + ok.str(""); ok + #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS + << "c::inv" << std::endl + << "b::static_inv" << std::endl // Test this fail. + #else + << ok_end() + #endif + ; + BOOST_TEST(out.eq(ok.str())); + } catch(...) { BOOST_TEST(false); } + + a_entry_static_inv = true; + b_entry_static_inv = true; + c_entry_static_inv = false; + a_entering_static_inv = b_entering_static_inv = c_entering_static_inv =true; + out.str(""); + try { + aa.f(); + ok.str(""); ok + #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS + << "c::inv" << std::endl + << "b::static_inv" << std::endl + << "b::inv" << std::endl + << "a::inv" << std::endl + #endif + << ok_end() + ; + BOOST_TEST(out.eq(ok.str())); + } catch(...) { BOOST_TEST(false); } + + a_entry_static_inv = false; + b_entry_static_inv = false; + c_entry_static_inv = false; + a_entering_static_inv = b_entering_static_inv = c_entering_static_inv = + BOOST_PP_IIF(BOOST_CONTRACT_TEST_entry_inv, true, false); + out.str(""); + try { + aa.f(); + #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS + BOOST_TEST(false); + } catch(err const&) { + #endif + ok.str(""); ok + #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS + << "c::inv" << std::endl + // Test this failed (as all did). + << "b::static_inv" << std::endl + #else + << ok_end() + #endif + ; + BOOST_TEST(out.eq(ok.str())); + } catch(...) { BOOST_TEST(false); } + + #undef BOOST_CONTRACT_TEST_entry_inv + return boost::report_errors(); +} + diff --git a/src/boost/libs/contract/test/public_function/decl_entry_static_inv_none.cpp b/src/boost/libs/contract/test/public_function/decl_entry_static_inv_none.cpp new file mode 100644 index 000000000..87a97d607 --- /dev/null +++ b/src/boost/libs/contract/test/public_function/decl_entry_static_inv_none.cpp @@ -0,0 +1,104 @@ + +// Copyright (C) 2008-2018 Lorenzo Caminiti +// Distributed under the Boost Software License, Version 1.0 (see accompanying +// file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt). +// See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html + +// Test all derived and base classes without entry static invariants. + +#define BOOST_CONTRACT_TEST_NO_A_STATIC_INV +#define BOOST_CONTRACT_TEST_NO_B_STATIC_INV +#define BOOST_CONTRACT_TEST_NO_C_STATIC_INV +#include "decl.hpp" + +#include <boost/preprocessor/control/iif.hpp> +#include <boost/detail/lightweight_test.hpp> +#include <sstream> + +int main() { + std::ostringstream ok; ok // Test nothing fails. + #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS + << "c::inv" << std::endl + << "b::inv" << std::endl + << "a::inv" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_PRECONDITIONS + << "c::f::pre" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_OLDS + << "c::f::old" << std::endl + << "b::f::old" << std::endl + << "a::f::old" << std::endl + #endif + << "a::f::body" << std::endl + #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS + << "c::inv" << std::endl + << "b::inv" << std::endl + << "a::inv" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS + << "c::f::old" << std::endl + << "c::f::post" << std::endl + << "b::f::old" << std::endl + << "b::f::post" << std::endl + << "a::f::post" << std::endl + #endif + ; + + #ifdef BOOST_CONTRACT_NO_ENTRY_INVARIANTS + #define BOOST_CONTRACT_TEST_entry_inv 0 + #else + #define BOOST_CONTRACT_TEST_entry_inv 1 + #endif + + a aa; + + a_entry_static_inv = true; + b_entry_static_inv = true; + c_entry_static_inv = true; + a_entering_static_inv = b_entering_static_inv = c_entering_static_inv = + BOOST_PP_IIF(BOOST_CONTRACT_TEST_entry_inv, true, false); + out.str(""); + aa.f(); + BOOST_TEST(out.eq(ok.str())); + + a_entry_static_inv = false; + b_entry_static_inv = true; + c_entry_static_inv = true; + a_entering_static_inv = b_entering_static_inv = c_entering_static_inv = + BOOST_PP_IIF(BOOST_CONTRACT_TEST_entry_inv, true, false); + out.str(""); + aa.f(); + BOOST_TEST(out.eq(ok.str())); + + a_entry_static_inv = true; + b_entry_static_inv = false; + c_entry_static_inv = true; + a_entering_static_inv = b_entering_static_inv = c_entering_static_inv = + BOOST_PP_IIF(BOOST_CONTRACT_TEST_entry_inv, true, false); + out.str(""); + aa.f(); + BOOST_TEST(out.eq(ok.str())); + + a_entry_static_inv = true; + b_entry_static_inv = true; + c_entry_static_inv = false; + a_entering_static_inv = b_entering_static_inv = c_entering_static_inv = + BOOST_PP_IIF(BOOST_CONTRACT_TEST_entry_inv, true, false); + out.str(""); + aa.f(); + BOOST_TEST(out.eq(ok.str())); + + a_entry_static_inv = false; + b_entry_static_inv = false; + c_entry_static_inv = false; + a_entering_static_inv = b_entering_static_inv = c_entering_static_inv = + BOOST_PP_IIF(BOOST_CONTRACT_TEST_entry_inv, true, false); + out.str(""); + aa.f(); + BOOST_TEST(out.eq(ok.str())); + + #undef BOOST_CONTRACT_TEST_entry_inv + return boost::report_errors(); +} + diff --git a/src/boost/libs/contract/test/public_function/decl_exit_inv_all.cpp b/src/boost/libs/contract/test/public_function/decl_exit_inv_all.cpp new file mode 100644 index 000000000..ffbe647d4 --- /dev/null +++ b/src/boost/libs/contract/test/public_function/decl_exit_inv_all.cpp @@ -0,0 +1,196 @@ + +// Copyright (C) 2008-2018 Lorenzo Caminiti +// Distributed under the Boost Software License, Version 1.0 (see accompanying +// file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt). +// See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html + +// Test all derived and base classes with exit invariants. + +#undef BOOST_CONTRACT_TEST_NO_A_INV +#undef BOOST_CONTRACT_TEST_NO_B_INV +#undef BOOST_CONTRACT_TEST_NO_C_INV +#include "decl.hpp" + +#include <boost/preprocessor/control/iif.hpp> +#include <boost/detail/lightweight_test.hpp> +#include <sstream> +#include <string> + +std::string ok_begin() { + std::ostringstream ok; ok + #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS + << "c::static_inv" << std::endl + << "c::inv" << std::endl + << "b::static_inv" << std::endl + << "b::inv" << std::endl + << "a::static_inv" << std::endl + << "a::inv" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_PRECONDITIONS + << "c::f::pre" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_OLDS + << "c::f::old" << std::endl + << "b::f::old" << std::endl + << "a::f::old" << std::endl + #endif + << "a::f::body" << std::endl + ; + return ok.str(); +} + +std::string ok_end() { + std::ostringstream ok; ok << "" // Suppress a warning. + #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS + << "c::f::old" << std::endl + << "c::f::post" << std::endl + << "b::f::old" << std::endl + << "b::f::post" << std::endl + << "a::f::post" << std::endl + #endif + ; + return ok.str(); +} + +struct err {}; // Global decl so visible in MSVC10 lambdas. + +int main() { + std::ostringstream ok; + + #ifdef BOOST_CONTRACT_NO_ENTRY_INVARIANTS + #define BOOST_CONTRACT_TEST_entry_inv 0 + #else + #define BOOST_CONTRACT_TEST_entry_inv 1 + #endif + + a aa; + + a_exit_inv = true; + b_exit_inv = true; + c_exit_inv = true; + a_entering_inv = b_entering_inv = c_entering_inv = + BOOST_PP_IIF(BOOST_CONTRACT_TEST_entry_inv, true, false); + out.str(""); + aa.f(); + ok.str(""); ok // Test nothing failed. + << ok_begin() + #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS + << "c::static_inv" << std::endl + << "c::inv" << std::endl + << "b::static_inv" << std::endl + << "b::inv" << std::endl + << "a::static_inv" << std::endl + << "a::inv" << std::endl + #endif + << ok_end() + ; + BOOST_TEST(out.eq(ok.str())); + + boost::contract::set_exit_invariant_failure( + [] (boost::contract::from) { throw err(); }); + + a_exit_inv = false; + b_exit_inv = true; + c_exit_inv = true; + a_entering_inv = b_entering_inv = c_entering_inv = + BOOST_PP_IIF(BOOST_CONTRACT_TEST_entry_inv, true, false); + out.str(""); + try { + aa.f(); + #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS + BOOST_TEST(false); + } catch(err const&) { + #endif + ok.str(""); ok + << ok_begin() + #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS + << "c::static_inv" << std::endl + << "c::inv" << std::endl + << "b::static_inv" << std::endl + << "b::inv" << std::endl + << "a::static_inv" << std::endl + << "a::inv" << std::endl // Test this failed. + #elif !defined(BOOST_CONTRACT_NO_POSTCONDITIONS) + << ok_end() + #endif + ; + BOOST_TEST(out.eq(ok.str())); + } catch(...) { BOOST_TEST(false); } + + a_exit_inv = true; + b_exit_inv = false; + c_exit_inv = true; + a_entering_inv = b_entering_inv = c_entering_inv = + BOOST_PP_IIF(BOOST_CONTRACT_TEST_entry_inv, true, false); + out.str(""); + try { + aa.f(); + #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS + BOOST_TEST(false); + } catch(err const&) { + #endif + ok.str(""); ok + << ok_begin() + #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS + << "c::static_inv" << std::endl + << "c::inv" << std::endl + << "b::static_inv" << std::endl + << "b::inv" << std::endl // Test this failed. + #elif !defined(BOOST_CONTRACT_NO_POSTCONDITIONS) + << ok_end() + #endif + ; + BOOST_TEST(out.eq(ok.str())); + } catch(...) { BOOST_TEST(false); } + + a_exit_inv = true; + b_exit_inv = true; + c_exit_inv = false; + a_entering_inv = b_entering_inv = c_entering_inv = + BOOST_PP_IIF(BOOST_CONTRACT_TEST_entry_inv, true, false); + out.str(""); + try { + aa.f(); + #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS + BOOST_TEST(false); + } catch(err const&) { + #endif + ok.str(""); ok + << ok_begin() + #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS + << "c::static_inv" << std::endl + << "c::inv" << std::endl // Test this failed. + #elif !defined(BOOST_CONTRACT_NO_POSTCONDITIONS) + << ok_end() + #endif + ; + BOOST_TEST(out.eq(ok.str())); + } catch(...) { BOOST_TEST(false); } + + a_exit_inv = false; + b_exit_inv = false; + c_exit_inv = false; + a_entering_inv = b_entering_inv = c_entering_inv = + BOOST_PP_IIF(BOOST_CONTRACT_TEST_entry_inv, true, false); + out.str(""); + try { + aa.f(); + #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS + BOOST_TEST(false); + } catch(err const&) { + #endif + ok.str(""); ok + << ok_begin() + #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS + << "c::static_inv" << std::endl + << "c::inv" << std::endl // Test this failed (as all did). + #elif !defined(BOOST_CONTRACT_NO_POSTCONDITIONS) + << ok_end() + #endif + ; + BOOST_TEST(out.eq(ok.str())); + } catch(...) { BOOST_TEST(false); } + + return boost::report_errors(); +} + diff --git a/src/boost/libs/contract/test/public_function/decl_exit_inv_ends.cpp b/src/boost/libs/contract/test/public_function/decl_exit_inv_ends.cpp new file mode 100644 index 000000000..b5fd8d1eb --- /dev/null +++ b/src/boost/libs/contract/test/public_function/decl_exit_inv_ends.cpp @@ -0,0 +1,189 @@ + +// Copyright (C) 2008-2018 Lorenzo Caminiti +// Distributed under the Boost Software License, Version 1.0 (see accompanying +// file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt). +// See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html + +// Test only derived and grandparent classes (ends) with exit invariants. + +#undef BOOST_CONTRACT_TEST_NO_A_INV +#define BOOST_CONTRACT_TEST_NO_B_INV +#undef BOOST_CONTRACT_TEST_NO_C_INV +#include "decl.hpp" + +#include <boost/preprocessor/control/iif.hpp> +#include <boost/detail/lightweight_test.hpp> +#include <sstream> +#include <string> + +std::string ok_begin() { + std::ostringstream ok; ok + #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS + << "c::static_inv" << std::endl + << "c::inv" << std::endl + << "b::static_inv" << std::endl + << "a::static_inv" << std::endl + << "a::inv" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_PRECONDITIONS + << "c::f::pre" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_OLDS + << "c::f::old" << std::endl + << "b::f::old" << std::endl + << "a::f::old" << std::endl + #endif + << "a::f::body" << std::endl + ; + return ok.str(); +} + +std::string ok_end() { + std::ostringstream ok; ok << "" // Suppress a warning. + #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS + << "c::f::old" << std::endl + << "c::f::post" << std::endl + << "b::f::old" << std::endl + << "b::f::post" << std::endl + << "a::f::post" << std::endl + #endif + ; + return ok.str(); +} + +struct err {}; // Global decl so visible in MSVC10 lambdas. + +int main() { + std::ostringstream ok; + + #ifdef BOOST_CONTRACT_NO_ENTRY_INVARIANTS + #define BOOST_CONTRACT_TEST_entry_inv 0 + #else + #define BOOST_CONTRACT_TEST_entry_inv 1 + #endif + + a aa; + + a_exit_inv = true; + b_exit_inv = true; + c_exit_inv = true; + a_entering_inv = b_entering_inv = c_entering_inv = + BOOST_PP_IIF(BOOST_CONTRACT_TEST_entry_inv, true, false); + out.str(""); + aa.f(); + ok.str(""); ok // Test nothing failed. + << ok_begin() + #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS + << "c::static_inv" << std::endl + << "c::inv" << std::endl + << "b::static_inv" << std::endl + << "a::static_inv" << std::endl + << "a::inv" << std::endl + #endif + << ok_end() + ; + BOOST_TEST(out.eq(ok.str())); + + boost::contract::set_exit_invariant_failure( + [] (boost::contract::from) { throw err(); }); + + a_exit_inv = false; + b_exit_inv = true; + c_exit_inv = true; + a_entering_inv = b_entering_inv = c_entering_inv = + BOOST_PP_IIF(BOOST_CONTRACT_TEST_entry_inv, true, false); + out.str(""); + try { + aa.f(); + #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS + BOOST_TEST(false); + } catch(err const&) { + #endif + ok.str(""); ok + << ok_begin() + #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS + << "c::static_inv" << std::endl + << "c::inv" << std::endl + << "b::static_inv" << std::endl + << "a::static_inv" << std::endl + << "a::inv" << std::endl // Test this failed. + #elif !defined(BOOST_CONTRACT_NO_POSTCONDITIONS) + << ok_end() + #endif + ; + BOOST_TEST(out.eq(ok.str())); + } catch(...) { BOOST_TEST(false); } + + a_exit_inv = true; + b_exit_inv = false; + c_exit_inv = true; + a_entering_inv = b_entering_inv = c_entering_inv = + BOOST_PP_IIF(BOOST_CONTRACT_TEST_entry_inv, true, false); + out.str(""); + try { + aa.f(); + ok.str(""); ok + << ok_begin() + #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS + << "c::static_inv" << std::endl + << "c::inv" << std::endl + << "b::static_inv" << std::endl + << "a::static_inv" << std::endl + << "a::inv" << std::endl + #endif + << ok_end() + ; + BOOST_TEST(out.eq(ok.str())); + } catch(...) { BOOST_TEST(false); } + + a_exit_inv = true; + b_exit_inv = true; + c_exit_inv = false; + a_entering_inv = b_entering_inv = c_entering_inv = + BOOST_PP_IIF(BOOST_CONTRACT_TEST_entry_inv, true, false); + out.str(""); + try { + aa.f(); + #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS + BOOST_TEST(false); + } catch(err const&) { + #endif + ok.str(""); ok + << ok_begin() + #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS + << "c::static_inv" << std::endl + << "c::inv" << std::endl // Test this failed. + #elif !defined(BOOST_CONTRACT_NO_POSTCONDITIONS) + << ok_end() + #endif + ; + BOOST_TEST(out.eq(ok.str())); + } catch(...) { BOOST_TEST(false); } + + a_exit_inv = false; + b_exit_inv = false; + c_exit_inv = false; + a_entering_inv = b_entering_inv = c_entering_inv = + BOOST_PP_IIF(BOOST_CONTRACT_TEST_entry_inv, true, false); + out.str(""); + try { + aa.f(); + #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS + BOOST_TEST(false); + } catch(err const&) { + #endif + ok.str(""); ok + << ok_begin() + #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS + << "c::static_inv" << std::endl + << "c::inv" << std::endl // Test this failed (as all did). + #elif !defined(BOOST_CONTRACT_NO_POSTCONDITIONS) + << ok_end() + #endif + ; + BOOST_TEST(out.eq(ok.str())); + } catch(...) { BOOST_TEST(false); } + + return boost::report_errors(); +} + diff --git a/src/boost/libs/contract/test/public_function/decl_exit_inv_mid.cpp b/src/boost/libs/contract/test/public_function/decl_exit_inv_mid.cpp new file mode 100644 index 000000000..c07b299af --- /dev/null +++ b/src/boost/libs/contract/test/public_function/decl_exit_inv_mid.cpp @@ -0,0 +1,187 @@ + +// Copyright (C) 2008-2018 Lorenzo Caminiti +// Distributed under the Boost Software License, Version 1.0 (see accompanying +// file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt). +// See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html + +// Test only middle base class with exit invariants. + +#define BOOST_CONTRACT_TEST_NO_A_INV +#undef BOOST_CONTRACT_TEST_NO_B_INV +#define BOOST_CONTRACT_TEST_NO_C_INV +#include "decl.hpp" + +#include <boost/preprocessor/control/iif.hpp> +#include <boost/detail/lightweight_test.hpp> +#include <sstream> +#include <string> + +std::string ok_begin() { + std::ostringstream ok; ok + #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS + << "c::static_inv" << std::endl + << "b::static_inv" << std::endl + << "b::inv" << std::endl + << "a::static_inv" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_PRECONDITIONS + << "c::f::pre" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_OLDS + << "c::f::old" << std::endl + << "b::f::old" << std::endl + << "a::f::old" << std::endl + #endif + << "a::f::body" << std::endl + ; + return ok.str(); +} + +std::string ok_end() { + std::ostringstream ok; ok << "" // Suppress a warning. + #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS + << "c::f::old" << std::endl + << "c::f::post" << std::endl + << "b::f::old" << std::endl + << "b::f::post" << std::endl + << "a::f::post" << std::endl + #endif + ; + return ok.str(); +} + +struct err {}; // Global decl so visible in MSVC10 lambdas. + +int main() { + std::ostringstream ok; + + #ifdef BOOST_CONTRACT_NO_ENTRY_INVARIANTS + #define BOOST_CONTRACT_TEST_entry_inv 0 + #else + #define BOOST_CONTRACT_TEST_entry_inv 1 + #endif + + a aa; + + a_exit_inv = true; + b_exit_inv = true; + c_exit_inv = true; + a_entering_inv = b_entering_inv = c_entering_inv = + BOOST_PP_IIF(BOOST_CONTRACT_TEST_entry_inv, true, false); + out.str(""); + aa.f(); + ok.str(""); ok // Test nothing failed. + << ok_begin() + #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS + << "c::static_inv" << std::endl + << "b::static_inv" << std::endl + << "b::inv" << std::endl + << "a::static_inv" << std::endl + #endif + << ok_end() + ; + BOOST_TEST(out.eq(ok.str())); + + boost::contract::set_exit_invariant_failure( + [] (boost::contract::from) { throw err(); }); + + a_exit_inv = false; + b_exit_inv = true; + c_exit_inv = true; + a_entering_inv = b_entering_inv = c_entering_inv = + BOOST_PP_IIF(BOOST_CONTRACT_TEST_entry_inv, true, false); + out.str(""); + try { + aa.f(); + ok.str(""); ok + << ok_begin() + #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS + << "c::static_inv" << std::endl + << "b::static_inv" << std::endl + << "b::inv" << std::endl + << "a::static_inv" << std::endl + // Test no failure here. + #endif + #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS + << ok_end() + #endif + ; + BOOST_TEST(out.eq(ok.str())); + } catch(...) { BOOST_TEST(false); } + + a_exit_inv = true; + b_exit_inv = false; + c_exit_inv = true; + a_entering_inv = b_entering_inv = c_entering_inv = + BOOST_PP_IIF(BOOST_CONTRACT_TEST_entry_inv, true, false); + out.str(""); + try { + aa.f(); + #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS + BOOST_TEST(false); + } catch(err const&) { + #endif + ok.str(""); ok + << ok_begin() + #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS + << "c::static_inv" << std::endl + << "b::static_inv" << std::endl + << "b::inv" << std::endl // Test this failed. + #elif !defined(BOOST_CONTRACT_NO_POSTCONDITIONS) + << ok_end() + #endif + ; + BOOST_TEST(out.eq(ok.str())); + } catch(...) { BOOST_TEST(false); } + + a_exit_inv = true; + b_exit_inv = true; + c_exit_inv = false; + a_entering_inv = b_entering_inv = c_entering_inv = + BOOST_PP_IIF(BOOST_CONTRACT_TEST_entry_inv, true, false); + out.str(""); + try { + aa.f(); + ok.str(""); ok + << ok_begin() + #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS + << "c::static_inv" << std::endl + << "b::static_inv" << std::endl + << "b::inv" << std::endl + << "a::static_inv" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS + << ok_end() + #endif + ; + BOOST_TEST(out.eq(ok.str())); + } catch(...) { BOOST_TEST(false); } + + a_exit_inv = false; + b_exit_inv = false; + c_exit_inv = false; + a_entering_inv = b_entering_inv = c_entering_inv = + BOOST_PP_IIF(BOOST_CONTRACT_TEST_entry_inv, true, false); + out.str(""); + try { + aa.f(); + #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS + BOOST_TEST(false); + } catch(err const&) { + #endif + ok.str(""); ok + << ok_begin() + #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS + << "c::static_inv" << std::endl + << "b::static_inv" << std::endl + << "b::inv" << std::endl // Test this failed (as all did). + #elif !defined(BOOST_CONTRACT_NO_POSTCONDITIONS) + << ok_end() + #endif + ; + BOOST_TEST(out.eq(ok.str())); + } catch(...) { BOOST_TEST(false); } + + return boost::report_errors(); +} + diff --git a/src/boost/libs/contract/test/public_function/decl_exit_inv_none.cpp b/src/boost/libs/contract/test/public_function/decl_exit_inv_none.cpp new file mode 100644 index 000000000..5f7aa61c2 --- /dev/null +++ b/src/boost/libs/contract/test/public_function/decl_exit_inv_none.cpp @@ -0,0 +1,110 @@ + +// Copyright (C) 2008-2018 Lorenzo Caminiti +// Distributed under the Boost Software License, Version 1.0 (see accompanying +// file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt). +// See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html + +// Test all derived and base classes without exit invariants. + +#define BOOST_CONTRACT_TEST_NO_A_INV +#define BOOST_CONTRACT_TEST_NO_B_INV +#define BOOST_CONTRACT_TEST_NO_C_INV +#include "decl.hpp" + +#include <boost/preprocessor/control/iif.hpp> +#include <boost/detail/lightweight_test.hpp> +#include <sstream> + +struct err {}; // Global decl so visible in MSVC10 lambdas. + +int main() { + std::ostringstream ok; + ok.str(""); ok // Test nothing fails. + #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS + // No invariants. + << "c::static_inv" << std::endl + << "b::static_inv" << std::endl + << "a::static_inv" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_PRECONDITIONS + << "c::f::pre" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_OLDS + << "c::f::old" << std::endl + << "b::f::old" << std::endl + << "a::f::old" << std::endl + #endif + << "a::f::body" << std::endl + #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS + << "c::static_inv" << std::endl + << "b::static_inv" << std::endl + << "a::static_inv" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS + << "c::f::old" << std::endl + << "c::f::post" << std::endl + << "b::f::old" << std::endl + << "b::f::post" << std::endl + << "a::f::post" << std::endl + #endif + ; + + boost::contract::set_exit_invariant_failure( + [] (boost::contract::from) { throw err(); }); + + a aa; + + #ifdef BOOST_CONTRACT_NO_ENTRY_INVARIANTS + #define BOOST_CONTRACT_TEST_entry_inv 0 + #else + #define BOOST_CONTRACT_TEST_entry_inv 1 + #endif + + a_exit_inv = true; + b_exit_inv = true; + c_exit_inv = true; + a_entering_inv = b_entering_inv = c_entering_inv = + BOOST_PP_IIF(BOOST_CONTRACT_TEST_entry_inv, true, false); + out.str(""); + aa.f(); + BOOST_TEST(out.eq(ok.str())); + + a_exit_inv = false; + b_exit_inv = true; + c_exit_inv = true; + a_entering_inv = b_entering_inv = c_entering_inv = + BOOST_PP_IIF(BOOST_CONTRACT_TEST_entry_inv, true, false); + out.str(""); + aa.f(); + BOOST_TEST(out.eq(ok.str())); + + a_exit_inv = true; + b_exit_inv = false; + a_entering_inv = b_entering_inv = c_entering_inv = + BOOST_PP_IIF(BOOST_CONTRACT_TEST_entry_inv, true, false); + out.str(""); + aa.f(); + BOOST_TEST(out.eq(ok.str())); + + a_exit_inv = true; + b_exit_inv = true; + c_exit_inv = false; + a_entering_inv = b_entering_inv = c_entering_inv = + BOOST_PP_IIF(BOOST_CONTRACT_TEST_entry_inv, true, false); + out.str(""); + aa.f(); + BOOST_TEST(out.eq(ok.str())); + + a_exit_inv = false; + b_exit_inv = false; + c_exit_inv = false; + a_entering_inv = b_entering_inv = c_entering_inv = + BOOST_PP_IIF(BOOST_CONTRACT_TEST_entry_inv, true, false); + out.str(""); + aa.f(); + BOOST_TEST(out.eq(ok.str())); + + #undef BOOST_CONTRACT_TEST_entry_inv + return boost::report_errors(); +} + diff --git a/src/boost/libs/contract/test/public_function/decl_exit_static_inv_all.cpp b/src/boost/libs/contract/test/public_function/decl_exit_static_inv_all.cpp new file mode 100644 index 000000000..5547b2f36 --- /dev/null +++ b/src/boost/libs/contract/test/public_function/decl_exit_static_inv_all.cpp @@ -0,0 +1,195 @@ + +// Copyright (C) 2008-2018 Lorenzo Caminiti +// Distributed under the Boost Software License, Version 1.0 (see accompanying +// file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt). +// See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html + +// Test all derived and base classes with exit static invariants. + +#undef BOOST_CONTRACT_TEST_NO_A_STATIC_INV +#undef BOOST_CONTRACT_TEST_NO_B_STATIC_INV +#undef BOOST_CONTRACT_TEST_NO_C_STATIC_INV +#include "decl.hpp" + +#include <boost/preprocessor/control/iif.hpp> +#include <boost/detail/lightweight_test.hpp> +#include <sstream> +#include <string> + +std::string ok_begin() { + std::ostringstream ok; ok + #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS + << "c::static_inv" << std::endl + << "c::inv" << std::endl + << "b::static_inv" << std::endl + << "b::inv" << std::endl + << "a::static_inv" << std::endl + << "a::inv" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_PRECONDITIONS + << "c::f::pre" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_OLDS + << "c::f::old" << std::endl + << "b::f::old" << std::endl + << "a::f::old" << std::endl + #endif + << "a::f::body" << std::endl + ; + return ok.str(); +} + +std::string ok_end() { + std::ostringstream ok; ok << "" // Suppress a warning. + #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS + << "c::f::old" << std::endl + << "c::f::post" << std::endl + << "b::f::old" << std::endl + << "b::f::post" << std::endl + << "a::f::post" << std::endl + #endif + ; + return ok.str(); +} + +struct err {}; // Global decl so visible in MSVC10 lambdas. + +int main() { + std::ostringstream ok; + + #ifdef BOOST_CONTRACT_NO_ENTRY_INVARIANTS + #define BOOST_CONTRACT_TEST_entry_inv 0 + #else + #define BOOST_CONTRACT_TEST_entry_inv 1 + #endif + + a aa; + + a_exit_static_inv = true; + b_exit_static_inv = true; + c_exit_static_inv = true; + a_entering_static_inv = b_entering_static_inv = c_entering_static_inv = + BOOST_PP_IIF(BOOST_CONTRACT_TEST_entry_inv, true, false); + out.str(""); + aa.f(); + ok.str(""); ok // Test nothing failed. + << ok_begin() + #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS + << "c::static_inv" << std::endl + << "c::inv" << std::endl + << "b::static_inv" << std::endl + << "b::inv" << std::endl + << "a::static_inv" << std::endl + << "a::inv" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS + << ok_end() + #endif + ; + BOOST_TEST(out.eq(ok.str())); + + boost::contract::set_exit_invariant_failure( + [] (boost::contract::from) { throw err(); }); + + a_exit_static_inv = false; + b_exit_static_inv = true; + c_exit_static_inv = true; + a_entering_static_inv = b_entering_static_inv = c_entering_static_inv = + BOOST_PP_IIF(BOOST_CONTRACT_TEST_entry_inv, true, false); + out.str(""); + try { + aa.f(); + #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS + BOOST_TEST(false); + } catch(err const&) { + #endif + ok.str(""); ok + << ok_begin() + #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS + << "c::static_inv" << std::endl + << "c::inv" << std::endl + << "b::static_inv" << std::endl + << "b::inv" << std::endl + << "a::static_inv" << std::endl // Test this failed. + #elif !defined(BOOST_CONTRACT_NO_POSTCONDITIONS) + << ok_end() + #endif + ; + BOOST_TEST(out.eq(ok.str())); + } catch(...) { BOOST_TEST(false); } + + a_exit_static_inv = true; + b_exit_static_inv = false; + c_exit_static_inv = true; + a_entering_static_inv = b_entering_static_inv = c_entering_static_inv = + BOOST_PP_IIF(BOOST_CONTRACT_TEST_entry_inv, true, false); + out.str(""); + try { + aa.f(); + #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS + BOOST_TEST(false); + } catch(err const&) { + #endif + ok.str(""); ok + << ok_begin() + #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS + << "c::static_inv" << std::endl + << "c::inv" << std::endl + << "b::static_inv" << std::endl // Test this failed. + #elif !defined(BOOST_CONTRACT_NO_POSTCONDITIONS) + << ok_end() + #endif + ; + BOOST_TEST(out.eq(ok.str())); + } catch(...) { BOOST_TEST(false); } + + a_exit_static_inv = true; + b_exit_static_inv = true; + c_exit_static_inv = false; + a_entering_static_inv = b_entering_static_inv = c_entering_static_inv = + BOOST_PP_IIF(BOOST_CONTRACT_TEST_entry_inv, true, false); + out.str(""); + try { + aa.f(); + #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS + BOOST_TEST(false); + } catch(err const&) { + #endif + ok.str(""); ok + << ok_begin() + #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS + << "c::static_inv" << std::endl // Test this failed. + #elif !defined(BOOST_CONTRACT_NO_POSTCONDITIONS) + << ok_end() + #endif + ; + BOOST_TEST(out.eq(ok.str())); + } catch(...) { BOOST_TEST(false); } + + a_exit_static_inv = false; + b_exit_static_inv = false; + c_exit_static_inv = false; + a_entering_static_inv = b_entering_static_inv = c_entering_static_inv = + BOOST_PP_IIF(BOOST_CONTRACT_TEST_entry_inv, true, false); + out.str(""); + try { + aa.f(); + #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS + BOOST_TEST(false); + } catch(err const&) { + #endif + ok.str(""); ok + << ok_begin() + #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS + // Test this failed (as all did). + << "c::static_inv" << std::endl + #elif !defined(BOOST_CONTRACT_NO_POSTCONDITIONS) + << ok_end() + #endif + ; + BOOST_TEST(out.eq(ok.str())); + } catch(...) { BOOST_TEST(false); } + + return boost::report_errors(); +} + diff --git a/src/boost/libs/contract/test/public_function/decl_exit_static_inv_ends.cpp b/src/boost/libs/contract/test/public_function/decl_exit_static_inv_ends.cpp new file mode 100644 index 000000000..3853e346e --- /dev/null +++ b/src/boost/libs/contract/test/public_function/decl_exit_static_inv_ends.cpp @@ -0,0 +1,191 @@ + +// Copyright (C) 2008-2018 Lorenzo Caminiti +// Distributed under the Boost Software License, Version 1.0 (see accompanying +// file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt). +// See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html + +// Test only derived and grandparent classes (ends) with exit static invariants. + +#undef BOOST_CONTRACT_TEST_NO_A_STATIC_INV +#define BOOST_CONTRACT_TEST_NO_B_STATIC_INV +#undef BOOST_CONTRACT_TEST_NO_C_STATIC_INV +#include "decl.hpp" + +#include <boost/preprocessor/control/iif.hpp> +#include <boost/detail/lightweight_test.hpp> +#include <sstream> +#include <string> + +std::string ok_begin() { + std::ostringstream ok; ok + #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS + << "c::static_inv" << std::endl + << "c::inv" << std::endl + << "b::inv" << std::endl + << "a::static_inv" << std::endl + << "a::inv" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_PRECONDITIONS + << "c::f::pre" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_OLDS + << "c::f::old" << std::endl + << "b::f::old" << std::endl + << "a::f::old" << std::endl + #endif + << "a::f::body" << std::endl + ; + return ok.str(); +} + +std::string ok_end() { + std::ostringstream ok; ok << "" // Suppress a warning. + #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS + << "c::f::old" << std::endl + << "c::f::post" << std::endl + << "b::f::old" << std::endl + << "b::f::post" << std::endl + << "a::f::post" << std::endl + #endif + ; + return ok.str(); +} + +struct err {}; // Global decl so visible in MSVC10 lambdas. + +int main() { + std::ostringstream ok; + + #ifdef BOOST_CONTRACT_NO_ENTRY_INVARIANTS + #define BOOST_CONTRACT_TEST_entry_inv 0 + #else + #define BOOST_CONTRACT_TEST_entry_inv 1 + #endif + + a aa; + + a_exit_static_inv = true; + b_exit_static_inv = true; + c_exit_static_inv = true; + a_entering_static_inv = b_entering_static_inv = c_entering_static_inv = + BOOST_PP_IIF(BOOST_CONTRACT_TEST_entry_inv, true, false); + out.str(""); + aa.f(); + ok.str(""); ok // Test nothing failed. + << ok_begin() + #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS + << "c::static_inv" << std::endl + << "c::inv" << std::endl + << "b::inv" << std::endl + << "a::static_inv" << std::endl + << "a::inv" << std::endl + #endif + << ok_end() + ; + BOOST_TEST(out.eq(ok.str())); + + boost::contract::set_exit_invariant_failure( + [] (boost::contract::from) { throw err(); }); + + a_exit_static_inv = false; + b_exit_static_inv = true; + c_exit_static_inv = true; + a_entering_static_inv = b_entering_static_inv = c_entering_static_inv = + BOOST_PP_IIF(BOOST_CONTRACT_TEST_entry_inv, true, false); + out.str(""); + try { + aa.f(); + #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS + BOOST_TEST(false); + } catch(err const&) { + #endif + ok.str(""); ok + << ok_begin() + #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS + << "c::static_inv" << std::endl + << "c::inv" << std::endl + << "b::inv" << std::endl + << "a::static_inv" << std::endl // Test this failed. + #elif !defined(BOOST_CONTRACT_NO_POSTCONDITIONS) + << ok_end() + #endif + ; + BOOST_TEST(out.eq(ok.str())); + } catch(...) { BOOST_TEST(false); } + + a_exit_static_inv = true; + b_exit_static_inv = false; + c_exit_static_inv = true; + a_entering_static_inv = b_entering_static_inv = c_entering_static_inv = + BOOST_PP_IIF(BOOST_CONTRACT_TEST_entry_inv, true, false); + out.str(""); + try { + aa.f(); + ok.str(""); ok + << ok_begin() + #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS + << "c::static_inv" << std::endl + << "c::inv" << std::endl + // Test no failure here. + << "b::inv" << std::endl + << "a::static_inv" << std::endl + << "a::inv" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS + << ok_end() + #endif + ; + BOOST_TEST(out.eq(ok.str())); + } catch(...) { BOOST_TEST(false); } + + a_exit_static_inv = true; + b_exit_static_inv = true; + c_exit_static_inv = false; + a_entering_static_inv = b_entering_static_inv = c_entering_static_inv = + BOOST_PP_IIF(BOOST_CONTRACT_TEST_entry_inv, true, false); + out.str(""); + try { + aa.f(); + #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS + BOOST_TEST(false); + } catch(err const&) { + #endif + ok.str(""); ok + << ok_begin() + #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS + << "c::static_inv" << std::endl // Test this failed. + #elif !defined(BOOST_CONTRACT_NO_POSTCONDITIONS) + << ok_end() + #endif + ; + BOOST_TEST(out.eq(ok.str())); + } catch(...) { BOOST_TEST(false); } + + a_exit_static_inv = false; + b_exit_static_inv = false; + c_exit_static_inv = false; + a_entering_static_inv = b_entering_static_inv = c_entering_static_inv = + BOOST_PP_IIF(BOOST_CONTRACT_TEST_entry_inv, true, false); + out.str(""); + try { + aa.f(); + #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS + BOOST_TEST(false); + } catch(err const&) { + #endif + ok.str(""); ok + << ok_begin() + #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS + // Test this failed (as all did). + << "c::static_inv" << std::endl + #elif !defined(BOOST_CONTRACT_NO_POSTCONDITIONS) + << ok_end() + #endif + ; + BOOST_TEST(out.eq(ok.str())); + } catch(...) { BOOST_TEST(false); } + + #undef BOOST_CONTRACT_TEST_entry_inv + return boost::report_errors(); +} + diff --git a/src/boost/libs/contract/test/public_function/decl_exit_static_inv_mid.cpp b/src/boost/libs/contract/test/public_function/decl_exit_static_inv_mid.cpp new file mode 100644 index 000000000..c723ddf7d --- /dev/null +++ b/src/boost/libs/contract/test/public_function/decl_exit_static_inv_mid.cpp @@ -0,0 +1,190 @@ + +// Copyright (C) 2008-2018 Lorenzo Caminiti +// Distributed under the Boost Software License, Version 1.0 (see accompanying +// file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt). +// See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html + +// Test only middle base class with exit static invariants. + +#define BOOST_CONTRACT_TEST_NO_A_STATIC_INV +#undef BOOST_CONTRACT_TEST_NO_B_STATIC_INV +#define BOOST_CONTRACT_TEST_NO_C_STATIC_INV +#include "decl.hpp" + +#include <boost/preprocessor/control/iif.hpp> +#include <boost/detail/lightweight_test.hpp> +#include <sstream> +#include <string> + +std::string ok_begin() { + std::ostringstream ok; ok + #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS + << "c::inv" << std::endl + << "b::static_inv" << std::endl + << "b::inv" << std::endl + << "a::inv" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_PRECONDITIONS + << "c::f::pre" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_OLDS + << "c::f::old" << std::endl + << "b::f::old" << std::endl + << "a::f::old" << std::endl + #endif + << "a::f::body" << std::endl + ; + return ok.str(); +} + +std::string ok_end() { + std::ostringstream ok; ok << "" // Suppress a warning. + #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS + << "c::f::old" << std::endl + << "c::f::post" << std::endl + << "b::f::old" << std::endl + << "b::f::post" << std::endl + << "a::f::post" << std::endl + #endif + ; + return ok.str(); +} + +struct err {}; // Global decl so visible in MSVC10 lambdas. + +int main() { + std::ostringstream ok; + + #ifdef BOOST_CONTRACT_NO_ENTRY_INVARIANTS + #define BOOST_CONTRACT_TEST_entry_inv 0 + #else + #define BOOST_CONTRACT_TEST_entry_inv 1 + #endif + + a aa; + + a_exit_static_inv = true; + b_exit_static_inv = true; + c_exit_static_inv = true; + a_entering_static_inv = b_entering_static_inv = c_entering_static_inv = + BOOST_PP_IIF(BOOST_CONTRACT_TEST_entry_inv, true, false); + out.str(""); + aa.f(); + ok.str(""); ok // Test nothing failed. + << ok_begin() + #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS + << "c::inv" << std::endl + << "b::static_inv" << std::endl + << "b::inv" << std::endl + << "a::inv" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS + << ok_end() + #endif + ; + BOOST_TEST(out.eq(ok.str())); + + boost::contract::set_exit_invariant_failure( + [] (boost::contract::from) { throw err(); }); + + a_exit_static_inv = false; + b_exit_static_inv = true; + c_exit_static_inv = true; + a_entering_static_inv = b_entering_static_inv = c_entering_static_inv = + BOOST_PP_IIF(BOOST_CONTRACT_TEST_entry_inv, true, false); + out.str(""); + try { + aa.f(); + ok.str(""); ok + << ok_begin() + #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS + << "c::inv" << std::endl + << "b::static_inv" << std::endl + << "b::inv" << std::endl + // Test no failure here. + << "a::inv" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS + << ok_end() + #endif + ; + BOOST_TEST(out.eq(ok.str())); + } catch(...) { BOOST_TEST(false); } + + a_exit_static_inv = true; + b_exit_static_inv = false; + c_exit_static_inv = true; + a_entering_static_inv = b_entering_static_inv = c_entering_static_inv = + BOOST_PP_IIF(BOOST_CONTRACT_TEST_entry_inv, true, false); + out.str(""); + try { + aa.f(); + #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS + BOOST_TEST(false); + } catch(err const&) { + #endif + ok.str(""); ok + << ok_begin() + #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS + << "c::inv" << std::endl + << "b::static_inv" << std::endl // Test this failed. + #elif !defined(BOOST_CONTRACT_NO_POSTCONDITIONS) + << ok_end() + #endif + ; + BOOST_TEST(out.eq(ok.str())); + } catch(...) { BOOST_TEST(false); } + + a_exit_static_inv = true; + b_exit_static_inv = true; + c_exit_static_inv = false; + a_entering_static_inv = b_entering_static_inv = c_entering_static_inv = + BOOST_PP_IIF(BOOST_CONTRACT_TEST_entry_inv, true, false); + out.str(""); + try { + aa.f(); + ok.str(""); ok + << ok_begin() + #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS + << "c::inv" << std::endl + // Test no failure here. + << "b::static_inv" << std::endl + << "b::inv" << std::endl + << "a::inv" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS + << ok_end() + #endif + ; + BOOST_TEST(out.eq(ok.str())); + } catch(...) { BOOST_TEST(false); } + + a_exit_static_inv = false; + b_exit_static_inv = false; + c_exit_static_inv = false; + a_entering_static_inv = b_entering_static_inv = c_entering_static_inv = + BOOST_PP_IIF(BOOST_CONTRACT_TEST_entry_inv, true, false); + out.str(""); + try { + aa.f(); + #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS + BOOST_TEST(false); + } catch(err const&) { + #endif + ok.str(""); ok + << ok_begin() + #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS + << "c::inv" << std::endl + // Test this failed (as all did). + << "b::static_inv" << std::endl + #elif !defined(BOOST_CONTRACT_NO_POSTCONDITIONS) + << ok_end() + #endif + ; + BOOST_TEST(out.eq(ok.str())); + } catch(...) { BOOST_TEST(false); } + + #undef BOOST_CONTRACT_TEST_entry_inv + return boost::report_errors(); +} + diff --git a/src/boost/libs/contract/test/public_function/decl_exit_static_inv_none.cpp b/src/boost/libs/contract/test/public_function/decl_exit_static_inv_none.cpp new file mode 100644 index 000000000..65c78ca7a --- /dev/null +++ b/src/boost/libs/contract/test/public_function/decl_exit_static_inv_none.cpp @@ -0,0 +1,110 @@ + +// Copyright (C) 2008-2018 Lorenzo Caminiti +// Distributed under the Boost Software License, Version 1.0 (see accompanying +// file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt). +// See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html + +// Test all derived and base classes without exit static invariants. + +#define BOOST_CONTRACT_TEST_NO_A_STATIC_INV +#define BOOST_CONTRACT_TEST_NO_B_STATIC_INV +#define BOOST_CONTRACT_TEST_NO_C_STATIC_INV +#include "decl.hpp" + +#include <boost/preprocessor/control/iif.hpp> +#include <boost/detail/lightweight_test.hpp> +#include <sstream> + +struct err {}; // Global decl so visible in MSVC10 lambdas. + +int main() { + std::ostringstream ok; ok // Test nothing fails. + #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS + // No static invariants. + << "c::inv" << std::endl + << "b::inv" << std::endl + << "a::inv" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_PRECONDITIONS + << "c::f::pre" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_OLDS + << "c::f::old" << std::endl + << "b::f::old" << std::endl + << "a::f::old" << std::endl + #endif + << "a::f::body" << std::endl + #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS + << "c::inv" << std::endl + << "b::inv" << std::endl + << "a::inv" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS + << "c::f::old" << std::endl + << "c::f::post" << std::endl + << "b::f::old" << std::endl + << "b::f::post" << std::endl + << "a::f::post" << std::endl + #endif + ; + + boost::contract::set_exit_invariant_failure( + [] (boost::contract::from) { throw err(); }); + + #ifdef BOOST_CONTRACT_NO_ENTRY_INVARIANTS + #define BOOST_CONTRACT_TEST_entry_inv 0 + #else + #define BOOST_CONTRACT_TEST_entry_inv 1 + #endif + + a aa; + + a_exit_static_inv = true; + b_exit_static_inv = true; + c_exit_static_inv = true; + a_entering_static_inv = b_entering_static_inv = c_entering_static_inv = + BOOST_PP_IIF(BOOST_CONTRACT_TEST_entry_inv, true, false); + out.str(""); + aa.f(); + BOOST_TEST(out.eq(ok.str())); + + a_exit_static_inv = false; + b_exit_static_inv = true; + c_exit_static_inv = true; + a_entering_static_inv = b_entering_static_inv = c_entering_static_inv = + BOOST_PP_IIF(BOOST_CONTRACT_TEST_entry_inv, true, false); + out.str(""); + aa.f(); + BOOST_TEST(out.eq(ok.str())); + + a_exit_static_inv = true; + b_exit_static_inv = false; + c_exit_static_inv = true; + a_entering_static_inv = b_entering_static_inv = c_entering_static_inv = + BOOST_PP_IIF(BOOST_CONTRACT_TEST_entry_inv, true, false); + out.str(""); + aa.f(); + BOOST_TEST(out.eq(ok.str())); + + a_exit_static_inv = true; + b_exit_static_inv = true; + c_exit_static_inv = false; + a_entering_static_inv = b_entering_static_inv = c_entering_static_inv = + BOOST_PP_IIF(BOOST_CONTRACT_TEST_entry_inv, true, false); + out.str(""); + aa.f(); + BOOST_TEST(out.eq(ok.str())); + + a_exit_static_inv = false; + b_exit_static_inv = false; + c_exit_static_inv = false; + a_entering_static_inv = b_entering_static_inv = c_entering_static_inv = + BOOST_PP_IIF(BOOST_CONTRACT_TEST_entry_inv, true, false); + out.str(""); + aa.f(); + BOOST_TEST(out.eq(ok.str())); + + #undef BOOST_CONTRACT_TEST_entry_inv + return boost::report_errors(); +} + diff --git a/src/boost/libs/contract/test/public_function/decl_post_all.cpp b/src/boost/libs/contract/test/public_function/decl_post_all.cpp new file mode 100644 index 000000000..18c52873b --- /dev/null +++ b/src/boost/libs/contract/test/public_function/decl_post_all.cpp @@ -0,0 +1,163 @@ + +// Copyright (C) 2008-2018 Lorenzo Caminiti +// Distributed under the Boost Software License, Version 1.0 (see accompanying +// file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt). +// See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html + +// Test all derived and base classes with postconditions. + +#undef BOOST_CONTRACT_TEST_NO_A_POST +#undef BOOST_CONTRACT_TEST_NO_B_POST +#undef BOOST_CONTRACT_TEST_NO_C_POST +#include "decl.hpp" + +#include <boost/detail/lightweight_test.hpp> +#include <sstream> +#include <string> + +std::string ok_begin() { + std::ostringstream ok; ok + #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS + << "c::static_inv" << std::endl + << "c::inv" << std::endl + << "b::static_inv" << std::endl + << "b::inv" << std::endl + << "a::static_inv" << std::endl + << "a::inv" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_PRECONDITIONS + << "c::f::pre" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_OLDS + << "c::f::old" << std::endl + << "b::f::old" << std::endl + << "a::f::old" << std::endl + #endif + << "a::f::body" << std::endl + #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS + << "c::static_inv" << std::endl + << "c::inv" << std::endl + << "b::static_inv" << std::endl + << "b::inv" << std::endl + << "a::static_inv" << std::endl + << "a::inv" << std::endl + #endif + ; + return ok.str(); +} + +struct err {}; // Global decl so visible in MSVC10 lambdas. + +int main() { + std::ostringstream ok; + + a aa; + + a_post = true; + b_post = true; + c_post = true; + out.str(""); + aa.f(); + ok.str(""); ok // Test nothing failed. + << ok_begin() + #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS + << "c::f::old" << std::endl + << "c::f::post" << std::endl + << "b::f::old" << std::endl + << "b::f::post" << std::endl + << "a::f::post" << std::endl + #endif + ; + BOOST_TEST(out.eq(ok.str())); + + boost::contract::set_postcondition_failure( + [] (boost::contract::from) { throw err(); }); + + a_post = false; + b_post = true; + c_post = true; + out.str(""); + try { + aa.f(); + #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS + BOOST_TEST(false); + } catch(err const&) { + #endif + ok.str(""); ok + << ok_begin() + #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS + << "c::f::old" << std::endl + << "c::f::post" << std::endl + << "b::f::old" << std::endl + << "b::f::post" << std::endl + << "a::f::post" << std::endl // Test this failed. + #endif + ; + BOOST_TEST(out.eq(ok.str())); + } catch(...) { BOOST_TEST(false); } + + a_post = true; + b_post = false; + c_post = true; + out.str(""); + try { + aa.f(); + #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS + BOOST_TEST(false); + } catch(err const&) { + #endif + ok.str(""); ok + << ok_begin() + #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS + << "c::f::old" << std::endl + << "c::f::post" << std::endl + << "b::f::old" << std::endl + << "b::f::post" << std::endl // Test this failed. + #endif + ; + BOOST_TEST(out.eq(ok.str())); + } catch(...) { BOOST_TEST(false); } + + a_post = true; + b_post = true; + c_post = false; + out.str(""); + try { + aa.f(); + #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS + BOOST_TEST(false); + } catch(err const&) { + #endif + ok.str(""); ok + << ok_begin() + #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS + << "c::f::old" << std::endl + << "c::f::post" << std::endl // Test this failed. + #endif + ; + BOOST_TEST(out.eq(ok.str())); + } catch(...) { BOOST_TEST(false); } + + a_post = false; + b_post = false; + c_post = false; + out.str(""); + try { + aa.f(); + #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS + BOOST_TEST(false); + } catch(err const&) { + #endif + ok.str(""); ok + << ok_begin() + #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS + << "c::f::old" << std::endl + << "c::f::post" << std::endl // Test this failed (as all did). + #endif + ; + BOOST_TEST(out.eq(ok.str())); + } catch(...) { BOOST_TEST(false); } + + return boost::report_errors(); +} + diff --git a/src/boost/libs/contract/test/public_function/decl_post_ends.cpp b/src/boost/libs/contract/test/public_function/decl_post_ends.cpp new file mode 100644 index 000000000..6785aa8a0 --- /dev/null +++ b/src/boost/libs/contract/test/public_function/decl_post_ends.cpp @@ -0,0 +1,158 @@ + +// Copyright (C) 2008-2018 Lorenzo Caminiti +// Distributed under the Boost Software License, Version 1.0 (see accompanying +// file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt). +// See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html + +// Test only derived and grandparent classes (ends) with postconditions. + +#undef BOOST_CONTRACT_TEST_NO_A_POST +#define BOOST_CONTRACT_TEST_NO_B_POST +#undef BOOST_CONTRACT_TEST_NO_C_POST +#include "decl.hpp" + +#include <boost/detail/lightweight_test.hpp> +#include <sstream> +#include <string> + +std::string ok_begin() { + std::ostringstream ok; ok + #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS + << "c::static_inv" << std::endl + << "c::inv" << std::endl + << "b::static_inv" << std::endl + << "b::inv" << std::endl + << "a::static_inv" << std::endl + << "a::inv" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_PRECONDITIONS + << "c::f::pre" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_OLDS + << "c::f::old" << std::endl + << "b::f::old" << std::endl + << "a::f::old" << std::endl + #endif + << "a::f::body" << std::endl + #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS + << "c::static_inv" << std::endl + << "c::inv" << std::endl + << "b::static_inv" << std::endl + << "b::inv" << std::endl + << "a::static_inv" << std::endl + << "a::inv" << std::endl + #endif + ; + return ok.str(); +} + +struct err {}; // Global decl so visible in MSVC10 lambdas. + +int main() { + std::ostringstream ok; + + a aa; + + a_post = true; + b_post = true; + c_post = true; + out.str(""); + aa.f(); + ok.str(""); ok // Test nothing failed. + << ok_begin() + #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS + << "c::f::old" << std::endl + << "c::f::post" << std::endl + << "b::f::old" << std::endl + << "a::f::post" << std::endl + #endif + ; + BOOST_TEST(out.eq(ok.str())); + + boost::contract::set_postcondition_failure( + [] (boost::contract::from) { throw err(); }); + + a_post = false; + b_post = true; + c_post = true; + out.str(""); + try { + aa.f(); + #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS + BOOST_TEST(false); + } catch(err const&) { + #endif + ok.str(""); ok + << ok_begin() + #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS + << "c::f::old" << std::endl + << "c::f::post" << std::endl + << "b::f::old" << std::endl + << "a::f::post" << std::endl // Test this failed. + #endif + ; + BOOST_TEST(out.eq(ok.str())); + } catch(...) { BOOST_TEST(false); } + + a_post = true; + b_post = false; + c_post = true; + out.str(""); + try { + aa.f(); + ok.str(""); ok + << ok_begin() + #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS + << "c::f::old" << std::endl + << "c::f::post" << std::endl + << "b::f::old" << std::endl + // Test no failure here. + << "a::f::post" << std::endl + #endif + ; + BOOST_TEST(out.eq(ok.str())); + } catch(...) { BOOST_TEST(false); } + + a_post = true; + b_post = true; + c_post = false; + out.str(""); + try { + aa.f(); + #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS + BOOST_TEST(false); + } catch(err const&) { + #endif + ok.str(""); ok + << ok_begin() + #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS + << "c::f::old" << std::endl + << "c::f::post" << std::endl // Test this failed. + #endif + ; + BOOST_TEST(out.eq(ok.str())); + } catch(...) { BOOST_TEST(false); } + + a_post = false; + b_post = false; + c_post = false; + out.str(""); + try { + aa.f(); + #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS + BOOST_TEST(false); + } catch(err const&) { + #endif + ok.str(""); ok + << ok_begin() + #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS + << "c::f::old" << std::endl + << "c::f::post" << std::endl // Test this failed (as all did). + #endif + ; + BOOST_TEST(out.eq(ok.str())); + } catch(...) { BOOST_TEST(false); } + + return boost::report_errors(); +} + diff --git a/src/boost/libs/contract/test/public_function/decl_post_mid.cpp b/src/boost/libs/contract/test/public_function/decl_post_mid.cpp new file mode 100644 index 000000000..eaa71b166 --- /dev/null +++ b/src/boost/libs/contract/test/public_function/decl_post_mid.cpp @@ -0,0 +1,154 @@ + +// Copyright (C) 2008-2018 Lorenzo Caminiti +// Distributed under the Boost Software License, Version 1.0 (see accompanying +// file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt). +// See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html + +// Test only middle base class with postconditions. + +#define BOOST_CONTRACT_TEST_NO_A_POST +#undef BOOST_CONTRACT_TEST_NO_B_POST +#define BOOST_CONTRACT_TEST_NO_C_POST +#include "decl.hpp" + +#include <boost/detail/lightweight_test.hpp> +#include <sstream> +#include <string> + +std::string ok_begin() { + std::ostringstream ok; ok + #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS + << "c::static_inv" << std::endl + << "c::inv" << std::endl + << "b::static_inv" << std::endl + << "b::inv" << std::endl + << "a::static_inv" << std::endl + << "a::inv" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_PRECONDITIONS + << "c::f::pre" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_OLDS + << "c::f::old" << std::endl + << "b::f::old" << std::endl + << "a::f::old" << std::endl + #endif + << "a::f::body" << std::endl + #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS + << "c::static_inv" << std::endl + << "c::inv" << std::endl + << "b::static_inv" << std::endl + << "b::inv" << std::endl + << "a::static_inv" << std::endl + << "a::inv" << std::endl + #endif + ; + return ok.str(); +} + +struct err {}; // Global decl so visible in MSVC10 lambdas. + +int main() { + std::ostringstream ok; + + a aa; + + a_post = true; + b_post = true; + c_post = true; + out.str(""); + aa.f(); + ok.str(""); ok // Test nothing failed. + << ok_begin() + #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS + << "c::f::old" << std::endl + << "b::f::old" << std::endl + << "b::f::post" << std::endl + #endif + ; + BOOST_TEST(out.eq(ok.str())); + + boost::contract::set_postcondition_failure( + [] (boost::contract::from) { throw err(); }); + + a_post = false; + b_post = true; + c_post = true; + out.str(""); + try { + aa.f(); + ok.str(""); ok + << ok_begin() + #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS + << "c::f::old" << std::endl + << "b::f::old" << std::endl + << "b::f::post" << std::endl + // Test no failure here. + #endif + ; + BOOST_TEST(out.eq(ok.str())); + } catch(...) { BOOST_TEST(false); } + + a_post = true; + b_post = false; + c_post = true; + out.str(""); + try { + aa.f(); + #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS + BOOST_TEST(false); + } catch(err const&) { + #endif + ok.str(""); ok + << ok_begin() + #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS + << "c::f::old" << std::endl + << "b::f::old" << std::endl + << "b::f::post" << std::endl // Test this failed. + #endif + ; + BOOST_TEST(out.eq(ok.str())); + } catch(...) { BOOST_TEST(false); } + + a_post = true; + b_post = true; + c_post = false; + out.str(""); + try { + aa.f(); + ok.str(""); ok + << ok_begin() + #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS + << "c::f::old" << std::endl + // Test no failure here. + << "b::f::old" << std::endl + << "b::f::post" << std::endl + #endif + ; + BOOST_TEST(out.eq(ok.str())); + } catch(...) { BOOST_TEST(false); } + + a_post = false; + b_post = false; + c_post = false; + out.str(""); + try { + aa.f(); + #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS + BOOST_TEST(false); + } catch(err const&) { + #endif + ok.str(""); ok + << ok_begin() + #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS + << "c::f::old" << std::endl + << "b::f::old" << std::endl + << "b::f::post" << std::endl // Test this failed (as all did). + #endif + ; + BOOST_TEST(out.eq(ok.str())); + } catch(...) { BOOST_TEST(false); } + + return boost::report_errors(); +} + diff --git a/src/boost/libs/contract/test/public_function/decl_post_none.cpp b/src/boost/libs/contract/test/public_function/decl_post_none.cpp new file mode 100644 index 000000000..26a424949 --- /dev/null +++ b/src/boost/libs/contract/test/public_function/decl_post_none.cpp @@ -0,0 +1,90 @@ + +// Copyright (C) 2008-2018 Lorenzo Caminiti +// Distributed under the Boost Software License, Version 1.0 (see accompanying +// file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt). +// See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html + +// Test all derived and base classes without postconditions. + +#define BOOST_CONTRACT_TEST_NO_A_POST +#define BOOST_CONTRACT_TEST_NO_B_POST +#define BOOST_CONTRACT_TEST_NO_C_POST +#include "decl.hpp" + +#include <boost/detail/lightweight_test.hpp> +#include <sstream> + +int main() { + std::ostringstream ok; ok // Test nothing fails. + #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS + << "c::static_inv" << std::endl + << "c::inv" << std::endl + << "b::static_inv" << std::endl + << "b::inv" << std::endl + << "a::static_inv" << std::endl + << "a::inv" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_PRECONDITIONS + << "c::f::pre" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_OLDS + << "c::f::old" << std::endl + << "b::f::old" << std::endl + << "a::f::old" << std::endl + #endif + << "a::f::body" << std::endl + #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS + << "c::static_inv" << std::endl + << "c::inv" << std::endl + << "b::static_inv" << std::endl + << "b::inv" << std::endl + << "a::static_inv" << std::endl + << "a::inv" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS + // No postconditions. + << "c::f::old" << std::endl + << "b::f::old" << std::endl + #endif + ; + + a aa; + + a_post = true; + b_post = true; + c_post = true; + out.str(""); + aa.f(); + BOOST_TEST(out.eq(ok.str())); + + a_post = false; + b_post = true; + c_post = true; + out.str(""); + aa.f(); + BOOST_TEST(out.eq(ok.str())); + + a_post = true; + b_post = false; + c_post = true; + out.str(""); + aa.f(); + BOOST_TEST(out.eq(ok.str())); + + a_post = true; + b_post = true; + c_post = false; + out.str(""); + aa.f(); + BOOST_TEST(out.eq(ok.str())); + + a_post = false; + b_post = false; + c_post = false; + out.str(""); + aa.f(); + BOOST_TEST(out.eq(ok.str())); + + return boost::report_errors(); +} + diff --git a/src/boost/libs/contract/test/public_function/decl_pre_all.cpp b/src/boost/libs/contract/test/public_function/decl_pre_all.cpp new file mode 100644 index 000000000..fb8600fb2 --- /dev/null +++ b/src/boost/libs/contract/test/public_function/decl_pre_all.cpp @@ -0,0 +1,154 @@ + +// Copyright (C) 2008-2018 Lorenzo Caminiti +// Distributed under the Boost Software License, Version 1.0 (see accompanying +// file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt). +// See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html + +// Test all derived and base classes with preconditions. + +#undef BOOST_CONTRACT_TEST_NO_A_PRE +#undef BOOST_CONTRACT_TEST_NO_B_PRE +#undef BOOST_CONTRACT_TEST_NO_C_PRE +#include "decl.hpp" + +#include <boost/detail/lightweight_test.hpp> +#include <sstream> +#include <string> + +std::string ok_begin() { + std::ostringstream ok; ok << "" // Suppress a warning. + #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS + << "c::static_inv" << std::endl + << "c::inv" << std::endl + << "b::static_inv" << std::endl + << "b::inv" << std::endl + << "a::static_inv" << std::endl + << "a::inv" << std::endl + #endif + ; + return ok.str(); +} + +std::string ok_end() { + std::ostringstream ok; ok + #ifndef BOOST_CONTRACT_NO_OLDS + << "c::f::old" << std::endl + << "b::f::old" << std::endl + << "a::f::old" << std::endl + #endif + << "a::f::body" << std::endl + #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS + << "c::static_inv" << std::endl + << "c::inv" << std::endl + << "b::static_inv" << std::endl + << "b::inv" << std::endl + << "a::static_inv" << std::endl + << "a::inv" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS + << "c::f::old" << std::endl // Old only if post (or except) run. + << "c::f::post" << std::endl + << "b::f::old" << std::endl + << "b::f::post" << std::endl + << "a::f::post" << std::endl + #endif + ; + return ok.str(); +} + +struct err {}; // Global decl so visible in MSVC10 lambdas. + +int main() { + std::ostringstream ok; + + a aa; + + a_pre = true; + b_pre = true; + c_pre = true; + out.str(""); + aa.f(); + ok.str(""); ok + << ok_begin() + #ifndef BOOST_CONTRACT_NO_PRECONDITIONS + << "c::f::pre" << std::endl // Test only c::f::pre checked. + #endif + << ok_end() + ; + BOOST_TEST(out.eq(ok.str())); + + a_pre = true; + b_pre = false; + c_pre = false; + out.str(""); + aa.f(); + ok.str(""); ok + << ok_begin() + #ifndef BOOST_CONTRACT_NO_PRECONDITIONS + << "c::f::pre" << std::endl + << "b::f::pre" << std::endl + << "a::f::pre" << std::endl // Test all pre checked. + #endif + << ok_end() + ; + BOOST_TEST(out.eq(ok.str())); + + a_pre = false; + b_pre = true; + c_pre = false; + out.str(""); + aa.f(); + ok.str(""); ok + << ok_begin() + #ifndef BOOST_CONTRACT_NO_PRECONDITIONS + << "c::f::pre" << std::endl + << "b::f::pre" << std::endl + // Test only a::f::pre not checked. + #endif + << ok_end() + ; + BOOST_TEST(out.eq(ok.str())); + + a_pre = false; + b_pre = false; + c_pre = true; + out.str(""); + aa.f(); + ok.str(""); ok + << ok_begin() + #ifndef BOOST_CONTRACT_NO_PRECONDITIONS + << "c::f::pre" << std::endl // Test only c::f::pre checked. + #endif + << ok_end() + ; + BOOST_TEST(out.eq(ok.str())); + + boost::contract::set_precondition_failure( + [] (boost::contract::from) { throw err(); }); + + a_pre = false; + b_pre = false; + c_pre = false; + out.str(""); + try { + aa.f(); + #ifndef BOOST_CONTRACT_NO_PRECONDITIONS + BOOST_TEST(false); + } catch(err const&) { + #endif + ok.str(""); ok + << ok_begin() + #ifndef BOOST_CONTRACT_NO_PRECONDITIONS + << "c::f::pre" << std::endl + << "b::f::pre" << std::endl + << "a::f::pre" << std::endl // Test all pre checked and failed. + #else + << ok_end() + #endif + ; + BOOST_TEST(out.eq(ok.str())); + } catch(...) { BOOST_TEST(false); } + + return boost::report_errors(); +} + diff --git a/src/boost/libs/contract/test/public_function/decl_pre_ends.cpp b/src/boost/libs/contract/test/public_function/decl_pre_ends.cpp new file mode 100644 index 000000000..dc6b19587 --- /dev/null +++ b/src/boost/libs/contract/test/public_function/decl_pre_ends.cpp @@ -0,0 +1,159 @@ + +// Copyright (C) 2008-2018 Lorenzo Caminiti +// Distributed under the Boost Software License, Version 1.0 (see accompanying +// file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt). +// See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html + +// Test only derived and grandparent classes (ends) with preconditions. + +#undef BOOST_CONTRACT_TEST_NO_A_PRE +#define BOOST_CONTRACT_TEST_NO_B_PRE +#undef BOOST_CONTRACT_TEST_NO_C_PRE +#include "decl.hpp" + +#include <boost/detail/lightweight_test.hpp> +#include <sstream> +#include <string> + +std::string ok_begin() { + std::ostringstream ok; ok << "" // Suppress a warning. + #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS + << "c::static_inv" << std::endl + << "c::inv" << std::endl + << "b::static_inv" << std::endl + << "b::inv" << std::endl + << "a::static_inv" << std::endl + << "a::inv" << std::endl + #endif + ; + return ok.str(); +} + +std::string ok_end() { + std::ostringstream ok; ok + #ifndef BOOST_CONTRACT_NO_OLDS + << "c::f::old" << std::endl + << "b::f::old" << std::endl + << "a::f::old" << std::endl + #endif + << "a::f::body" << std::endl + #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS + << "c::static_inv" << std::endl + << "c::inv" << std::endl + << "b::static_inv" << std::endl + << "b::inv" << std::endl + << "a::static_inv" << std::endl + << "a::inv" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS + << "c::f::old" << std::endl // Old only if post (or except) run. + << "c::f::post" << std::endl + << "b::f::old" << std::endl + << "b::f::post" << std::endl + << "a::f::post" << std::endl + #endif + ; + return ok.str(); +} + +struct err {}; // Global decl so visible in MSVC10 lambdas. + +int main() { + std::ostringstream ok; + + a aa; + + a_pre = true; + b_pre = true; + c_pre = true; + out.str(""); + aa.f(); + ok.str(""); ok // Test nothing failed. + << ok_begin() + #ifndef BOOST_CONTRACT_NO_PRECONDITIONS + << "c::f::pre" << std::endl // Test only c pre checked. + #endif + << ok_end() + ; + BOOST_TEST(out.eq(ok.str())); + + a_pre = true; + b_pre = false; + c_pre = false; + out.str(""); + aa.f(); + ok.str(""); ok + << ok_begin() + #ifndef BOOST_CONTRACT_NO_PRECONDITIONS + << "c::f::pre" << std::endl + // Test b's pre not checked. + << "a::f::pre" << std::endl + #endif + << ok_end() + ; + BOOST_TEST(out.eq(ok.str())); + + a_pre = false; + b_pre = false; + c_pre = true; + out.str(""); + aa.f(); + ok.str(""); ok + << ok_begin() + #ifndef BOOST_CONTRACT_NO_PRECONDITIONS + << "c::f::pre" << std::endl // Test only c pre checked. + #endif + << ok_end() + ; + BOOST_TEST(out.eq(ok.str())); + + boost::contract::set_precondition_failure( + [] (boost::contract::from) { throw err(); }); + + a_pre = false; + b_pre = true; + c_pre = false; + out.str(""); + try { + aa.f(); + #ifndef BOOST_CONTRACT_NO_PRECONDITIONS + BOOST_TEST(false); + } catch(err const&) { + #endif + ok.str(""); ok + << ok_begin() + #ifndef BOOST_CONTRACT_NO_PRECONDITIONS + << "c::f::pre" << std::endl + << "a::f::pre" << std::endl // Only ends pre checked and failed. + #else + << ok_end() + #endif + ; + BOOST_TEST(out.eq(ok.str())); + } catch(...) { BOOST_TEST(false); } + + a_pre = false; + b_pre = false; + c_pre = false; + out.str(""); + try { + aa.f(); + #ifndef BOOST_CONTRACT_NO_PRECONDITIONS + BOOST_TEST(false); + } catch(err const&) { + #endif + ok.str(""); ok + << ok_begin() + #ifndef BOOST_CONTRACT_NO_PRECONDITIONS + << "c::f::pre" << std::endl + << "a::f::pre" << std::endl // Only ends pre checked and failed. + #else + << ok_end() + #endif + ; + BOOST_TEST(out.eq(ok.str())); + } catch(...) { BOOST_TEST(false); } + + return boost::report_errors(); +} + diff --git a/src/boost/libs/contract/test/public_function/decl_pre_mid.cpp b/src/boost/libs/contract/test/public_function/decl_pre_mid.cpp new file mode 100644 index 000000000..f0939ca82 --- /dev/null +++ b/src/boost/libs/contract/test/public_function/decl_pre_mid.cpp @@ -0,0 +1,166 @@ + +// Copyright (C) 2008-2018 Lorenzo Caminiti +// Distributed under the Boost Software License, Version 1.0 (see accompanying +// file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt). +// See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html + +// Test only middle base class with preconditions. + +#define BOOST_CONTRACT_TEST_NO_A_PRE +#undef BOOST_CONTRACT_TEST_NO_B_PRE +#define BOOST_CONTRACT_TEST_NO_C_PRE +#include "decl.hpp" + +#include <boost/detail/lightweight_test.hpp> +#include <sstream> +#include <string> + +std::string ok_begin() { + std::ostringstream ok; ok << "" // Suppress a warning. + #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS + << "c::static_inv" << std::endl + << "c::inv" << std::endl + << "b::static_inv" << std::endl + << "b::inv" << std::endl + << "a::static_inv" << std::endl + << "a::inv" << std::endl + #endif + ; + return ok.str(); +} + +std::string ok_end() { + std::ostringstream ok; ok + #ifndef BOOST_CONTRACT_NO_OLDS + << "c::f::old" << std::endl + << "b::f::old" << std::endl + << "a::f::old" << std::endl + #endif + << "a::f::body" << std::endl + #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS + << "c::static_inv" << std::endl + << "c::inv" << std::endl + << "b::static_inv" << std::endl + << "b::inv" << std::endl + << "a::static_inv" << std::endl + << "a::inv" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS + << "c::f::old" << std::endl // Old only if post (or except) run. + << "c::f::post" << std::endl + << "b::f::old" << std::endl + << "b::f::post" << std::endl + << "a::f::post" << std::endl + #endif + ; + return ok.str(); +} + +struct err {}; // Global decl so visible in MSVC10 lambdas. + +int main() { + std::ostringstream ok; + + a aa; + + a_pre = true; + b_pre = true; + c_pre = true; + out.str(""); + aa.f(); + ok.str(""); ok // Test nothing failed. + << ok_begin() + #ifndef BOOST_CONTRACT_NO_PRECONDITIONS + << "b::f::pre" << std::endl + #endif + << ok_end() + ; + BOOST_TEST(out.eq(ok.str())); + + a_pre = false; + b_pre = true; + c_pre = false; + out.str(""); + aa.f(); + ok.str(""); ok + << ok_begin() + #ifndef BOOST_CONTRACT_NO_PRECONDITIONS + // Test only middle pre checked and no fail. + << "b::f::pre" << std::endl + #endif + << ok_end() + ; + BOOST_TEST(out.eq(ok.str())); + + boost::contract::set_precondition_failure( + [] (boost::contract::from) { throw err(); }); + + a_pre = true; + b_pre = false; + c_pre = false; + out.str(""); + try { + aa.f(); + #ifndef BOOST_CONTRACT_NO_PRECONDITIONS + BOOST_TEST(false); + } catch(err const&) { + #endif + ok.str(""); ok + << ok_begin() + #ifndef BOOST_CONTRACT_NO_PRECONDITIONS + // Test only middle pre checked and failed. + << "b::f::pre" << std::endl + #else + << ok_end() + #endif + ; + BOOST_TEST(out.eq(ok.str())); + } catch(...) { BOOST_TEST(false); } + + a_pre = false; + b_pre = false; + c_pre = true; + out.str(""); + try { + aa.f(); + #ifndef BOOST_CONTRACT_NO_PRECONDITIONS + BOOST_TEST(false); + } catch(err const&) { + #endif + ok.str(""); ok + << ok_begin() + #ifndef BOOST_CONTRACT_NO_PRECONDITIONS + // Test only middle pre checked and failed. + << "b::f::pre" << std::endl + #else + << ok_end() + #endif + ; + BOOST_TEST(out.eq(ok.str())); + } catch(...) { BOOST_TEST(false); } + + a_pre = false; + b_pre = false; + c_pre = false; + out.str(""); + try { + aa.f(); + #ifndef BOOST_CONTRACT_NO_PRECONDITIONS + BOOST_TEST(false); + } catch(err const&) { + #endif + ok.str(""); ok + << ok_begin() + #ifndef BOOST_CONTRACT_NO_PRECONDITIONS + // Test only middle pre checked and failed. + << "b::f::pre" << std::endl + #else + << ok_end() + #endif + ; + BOOST_TEST(out.eq(ok.str())); + } catch(...) { BOOST_TEST(false); } + + return boost::report_errors(); +} + diff --git a/src/boost/libs/contract/test/public_function/decl_pre_none.cpp b/src/boost/libs/contract/test/public_function/decl_pre_none.cpp new file mode 100644 index 000000000..71ace3e4d --- /dev/null +++ b/src/boost/libs/contract/test/public_function/decl_pre_none.cpp @@ -0,0 +1,90 @@ + +// Copyright (C) 2008-2018 Lorenzo Caminiti +// Distributed under the Boost Software License, Version 1.0 (see accompanying +// file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt). +// See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html + +// Test all derived and base classes without preconditions. + +#define BOOST_CONTRACT_TEST_NO_A_PRE +#define BOOST_CONTRACT_TEST_NO_B_PRE +#define BOOST_CONTRACT_TEST_NO_C_PRE +#include "decl.hpp" + +#include <boost/detail/lightweight_test.hpp> +#include <sstream> + +int main() { + std::ostringstream ok; ok // Test nothing fails. + #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS + << "c::static_inv" << std::endl + << "c::inv" << std::endl + << "b::static_inv" << std::endl + << "b::inv" << std::endl + << "a::static_inv" << std::endl + << "a::inv" << std::endl + #endif + // No preconditions here. + #ifndef BOOST_CONTRACT_NO_OLDS + << "c::f::old" << std::endl + << "b::f::old" << std::endl + << "a::f::old" << std::endl + #endif + << "a::f::body" << std::endl + #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS + << "c::static_inv" << std::endl + << "c::inv" << std::endl + << "b::static_inv" << std::endl + << "b::inv" << std::endl + << "a::static_inv" << std::endl + << "a::inv" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS + << "c::f::old" << std::endl // Old only if post (or except) run. + << "c::f::post" << std::endl + << "b::f::old" << std::endl + << "b::f::post" << std::endl + << "a::f::post" << std::endl + #endif + ; + + a aa; + + a_pre = true; + b_pre = true; + c_pre = true; + out.str(""); + aa.f(); + BOOST_TEST(out.eq(ok.str())); + + a_pre = true; + b_pre = false; + c_pre = false; + out.str(""); + aa.f(); + BOOST_TEST(out.eq(ok.str())); + + a_pre = false; + b_pre = true; + c_pre = false; + out.str(""); + aa.f(); + BOOST_TEST(out.eq(ok.str())); + + a_pre = false; + b_pre = false; + c_pre = true; + out.str(""); + aa.f(); + BOOST_TEST(out.eq(ok.str())); + + a_pre = false; + b_pre = false; + c_pre = false; + out.str(""); + aa.f(); + BOOST_TEST(out.eq(ok.str())); + + return boost::report_errors(); +} + diff --git a/src/boost/libs/contract/test/public_function/friend.cpp b/src/boost/libs/contract/test/public_function/friend.cpp new file mode 100644 index 000000000..d5fc63595 --- /dev/null +++ b/src/boost/libs/contract/test/public_function/friend.cpp @@ -0,0 +1,107 @@ + +// Copyright (C) 2008-2018 Lorenzo Caminiti +// Distributed under the Boost Software License, Version 1.0 (see accompanying +// file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt). +// See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html + +// Test friend functions (also forcing them to check invariants). + +#include "../detail/oteststream.hpp" +#include <boost/contract/public_function.hpp> +#include <boost/contract/function.hpp> +#include <boost/contract/check.hpp> +#include <boost/contract/assert.hpp> +#include <boost/detail/lightweight_test.hpp> +#include <sstream> + +boost::contract::test::detail::oteststream out; + +class y; +class z; + +class x { +public: + void invariant() const { + out << "x::inv" << std::endl; + BOOST_CONTRACT_ASSERT(get() >= 0); + } + + x() : value_(0) {} + int get() const { return value_; } + + friend void f(x&, y&, int value); + +private: + int value_; +}; + +class y { +public: + void invariant() const { + out << "y::inv" << std::endl; + BOOST_CONTRACT_ASSERT(get() >= 0); + } + + y() : value_(0) {} + int get() const { return value_; } + + friend void f(x&, y&, int value); + +private: + int value_; +}; + +void f(x& a, y& b, int value) { + boost::contract::check post = boost::contract::function() + .postcondition([&] { + out << "f::post" << std::endl; + BOOST_CONTRACT_ASSERT(a.get() == value); + BOOST_CONTRACT_ASSERT(b.get() == value); + }) + ; + boost::contract::check inv_b = boost::contract::public_function(&b); + boost::contract::check inv_a = boost::contract::public_function(&a); + boost::contract::check pre = boost::contract::function() + .precondition([&] { + out << "f::pre" << std::endl; + BOOST_CONTRACT_ASSERT(value > 0); + }) + ; + + out << "f::body" << std::endl; + a.value_ = b.value_ = value; +} + +int main() { + std::ostringstream ok; + + x a; + y b; + + out.str(""); + f(a, b, 123); + ok.str(""); ok + #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS + << "y::inv" << std::endl + << "x::inv" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_PRECONDITIONS + << "f::pre" << std::endl + #endif + << "f::body" << std::endl + #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS + << "x::inv" << std::endl + << "y::inv" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS + << "f::post" << std::endl + #endif + ; + BOOST_TEST(out.eq(ok.str())); + + BOOST_TEST_EQ(a.get(), 123); + BOOST_TEST_EQ(b.get(), 123); + + return boost::report_errors(); +} + diff --git a/src/boost/libs/contract/test/public_function/ifdef.cpp b/src/boost/libs/contract/test/public_function/ifdef.cpp new file mode 100644 index 000000000..2ab7d3ac0 --- /dev/null +++ b/src/boost/libs/contract/test/public_function/ifdef.cpp @@ -0,0 +1,122 @@ + +// Copyright (C) 2008-2018 Lorenzo Caminiti +// Distributed under the Boost Software License, Version 1.0 (see accompanying +// file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt). +// See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html + +// Test contract compilation on/off. + +#include "../detail/oteststream.hpp" +#include <boost/contract/core/config.hpp> +#include <boost/contract/core/virtual.hpp> +#ifndef BOOST_CONTRACT_NO_PUBLIC_FUNCTIONS + #include <boost/contract/public_function.hpp> + #include <boost/contract/base_types.hpp> + #include <boost/contract/override.hpp> + #include <boost/contract/check.hpp> + #include <boost/contract/old.hpp> +#endif +#include <boost/detail/lightweight_test.hpp> +#include <sstream> + +boost::contract::test::detail::oteststream out; + +struct b { + #ifndef BOOST_CONTRACT_NO_INVARIANTS + static void static_invariant() { out << "b::static_inv" << std::endl; } + void invariant() const { out << "b::inv" << std::endl; } + #endif + + virtual void f(int x, boost::contract::virtual_* v = 0) = 0; +}; + +void b::f(int x, boost::contract::virtual_* v) { + #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS + boost::contract::old_ptr<int> old_x = BOOST_CONTRACT_OLDOF(v, x); + #endif + #ifndef BOOST_CONTRACT_NO_PUBLIC_FUNCTIONS + boost::contract::check c = boost::contract::public_function(v, this) + #ifndef BOOST_CONTRACT_NO_PRECONDITIONS + .precondition([] { out << "b::f::pre" << std::endl; }) + #endif + #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS + .old([] { out << "b::f::old" << std::endl; }) + .postcondition([] { out << "b::f::post" << std::endl; }) + #endif + ; + #endif + out << "b::f::body" << std::endl; +} + +struct a + #define BASES public b + : BASES +{ + #ifndef BOOST_CONTRACT_NO_PUBLIC_FUNCTIONS + typedef BOOST_CONTRACT_BASE_TYPES(BASES) base_types; + BOOST_CONTRACT_OVERRIDE(f) + #endif + + #ifndef BOOST_CONTRACT_NO_INVARIANTS + static void static_invariant() { out << "a::static_inv" << std::endl; } + void invariant() const { out << "a::inv" << std::endl; } + #endif + + virtual void f(int x, boost::contract::virtual_* v = 0) { + #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS + boost::contract::old_ptr<int> old_x = BOOST_CONTRACT_OLDOF(v, x); + #endif + #ifndef BOOST_CONTRACT_NO_PUBLIC_FUNCTIONS + boost::contract::check c = boost::contract::public_function< + override_f>(v, &a::f, this, x) + #ifndef BOOST_CONTRACT_NO_PRECONDITIONS + .precondition([] { out << "a::f::pre" << std::endl; }) + #endif + #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS + .old([] { out << "a::f::old" << std::endl; }) + .postcondition([] { out << "a::f::post" << std::endl; }) + #endif + ; + #endif + out << "a::f::body" << std::endl; + } +}; + +int main() { + std::ostringstream ok; + + a aa; + out.str(""); + aa.f(123); + ok.str(""); ok + #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS + << "b::static_inv" << std::endl + << "b::inv" << std::endl + << "a::static_inv" << std::endl + << "a::inv" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_PRECONDITIONS + << "b::f::pre" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS + << "b::f::old" << std::endl + << "a::f::old" << std::endl + #endif + << "a::f::body" << std::endl + #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS + << "b::static_inv" << std::endl + << "b::inv" << std::endl + << "a::static_inv" << std::endl + << "a::inv" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS + << "b::f::old" << std::endl + << "b::f::post" << std::endl + << "a::f::post" << std::endl + #endif + ; + BOOST_TEST(out.eq(ok.str())); + + return boost::report_errors(); +} + diff --git a/src/boost/libs/contract/test/public_function/ifdef_macro.cpp b/src/boost/libs/contract/test/public_function/ifdef_macro.cpp new file mode 100644 index 000000000..ab552de7c --- /dev/null +++ b/src/boost/libs/contract/test/public_function/ifdef_macro.cpp @@ -0,0 +1,171 @@ + +// Copyright (C) 2008-2018 Lorenzo Caminiti +// Distributed under the Boost Software License, Version 1.0 (see accompanying +// file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt). +// See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html + +// Test contract compilation on/off (using macro interface). + +#include "../detail/oteststream.hpp" +#include "../detail/unprotected_commas.hpp" +#include <boost/contract/core/config.hpp> +#include <boost/contract/core/virtual.hpp> +#include <boost/contract_macro.hpp> +#include <boost/detail/lightweight_test.hpp> +#include <sstream> + +boost::contract::test::detail::oteststream out; + +struct b { + BOOST_CONTRACT_STATIC_INVARIANT({ + boost::contract::test::detail::unprotected_commas<void, void, void>:: + call(); + out << "b::static_inv" << std::endl; + }) + + BOOST_CONTRACT_INVARIANT({ + boost::contract::test::detail::unprotected_commas<void, void, void>:: + call(); + out << "b::inv" << std::endl; + }) + + virtual void f(int x, boost::contract::virtual_* v = 0) = 0; +}; + +void b::f(int x, boost::contract::virtual_* v) { + BOOST_CONTRACT_OLD_PTR( + boost::contract::test::detail::unprotected_commas<int, void, void>:: + type1 + )( + (boost::contract::test::detail::unprotected_commas<void, void, void>:: + same(v)), + old_x, + (boost::contract::test::detail::unprotected_commas<void, void, void>:: + same(x)) + ); + BOOST_CONTRACT_PUBLIC_FUNCTION( + boost::contract::test::detail::unprotected_commas<void, void, void>:: + same(v), + boost::contract::test::detail::unprotected_commas<void, void, void>:: + same(this) + ) + BOOST_CONTRACT_PRECONDITION([] { + boost::contract::test::detail::unprotected_commas< + void, void, void>::call(); + out << "b::f::pre" << std::endl; + }) + BOOST_CONTRACT_OLD([] { + boost::contract::test::detail::unprotected_commas< + void, void, void>::call(); + out << "b::f::old" << std::endl; + }) + BOOST_CONTRACT_POSTCONDITION([] { + boost::contract::test::detail::unprotected_commas< + void, void, void>::call(); + out << "b::f::post" << std::endl; + }) + ; + out << "b::f::body" << std::endl; +} + +struct a + #define BASES public boost::contract::test::detail::unprotected_commas< \ + b, void, void>::type1 + : BASES +{ + typedef BOOST_CONTRACT_BASE_TYPES(BASES) base_types; + BOOST_CONTRACT_OVERRIDE(f) + + BOOST_CONTRACT_STATIC_INVARIANT({ + boost::contract::test::detail::unprotected_commas<void, void, void>:: + call(); + out << "a::static_inv" << std::endl; + }) + + BOOST_CONTRACT_INVARIANT({ + boost::contract::test::detail::unprotected_commas<void, void, void>:: + call(); + out << "a::inv" << std::endl; + }) + + virtual void f(int x, boost::contract::virtual_* v = 0) { + BOOST_CONTRACT_OLD_PTR( + boost::contract::test::detail::unprotected_commas<int, void, void>:: + type1 + )( + (boost::contract::test::detail::unprotected_commas<void, void, + void>::same(v)), + old_x, + (boost::contract::test::detail::unprotected_commas<void, void, + void>::same(x)) + ); + BOOST_CONTRACT_PUBLIC_FUNCTION_OVERRIDE( + boost::contract::test::detail::unprotected_commas<override_f, void, + void>::type1 + )( + boost::contract::test::detail::unprotected_commas<void, void, void> + ::same(v), + &a::f, + boost::contract::test::detail::unprotected_commas<void, void, void> + ::same(this), + boost::contract::test::detail::unprotected_commas<void, void, void> + ::same(x) + ) + BOOST_CONTRACT_PRECONDITION([] { + boost::contract::test::detail::unprotected_commas< + void, void, void>::call(); + out << "a::f::pre" << std::endl; + }) + BOOST_CONTRACT_OLD([] { + boost::contract::test::detail::unprotected_commas< + void, void, void>::call(); + out << "a::f::old" << std::endl; + }) + BOOST_CONTRACT_POSTCONDITION([] { + boost::contract::test::detail::unprotected_commas< + void, void, void>::call(); + out << "a::f::post" << std::endl; + }) + ; + out << "a::f::body" << std::endl; + } +}; + +int main() { + std::ostringstream ok; + + a aa; + out.str(""); + aa.f(123); + ok.str(""); ok + #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS + << "b::static_inv" << std::endl + << "b::inv" << std::endl + << "a::static_inv" << std::endl + << "a::inv" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_PRECONDITIONS + << "b::f::pre" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_OLDS + << "b::f::old" << std::endl + << "a::f::old" << std::endl + #endif + << "a::f::body" << std::endl + #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS + << "b::static_inv" << std::endl + << "b::inv" << std::endl + << "a::static_inv" << std::endl + << "a::inv" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS + << "b::f::old" << std::endl // Called by post (so under NO_POST). + << "b::f::post" << std::endl + << "a::f::post" << std::endl + #endif + ; + BOOST_TEST(out.eq(ok.str())); + + return boost::report_errors(); +} + diff --git a/src/boost/libs/contract/test/public_function/max_args.cpp b/src/boost/libs/contract/test/public_function/max_args.cpp new file mode 100644 index 000000000..d01e8281f --- /dev/null +++ b/src/boost/libs/contract/test/public_function/max_args.cpp @@ -0,0 +1,10 @@ + +// Copyright (C) 2008-2018 Lorenzo Caminiti +// Distributed under the Boost Software License, Version 1.0 (see accompanying +// file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt). +// See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html + +// Test with default max argument number (leave MAX_ARGS #undef). + +#include "max_args.hpp" + diff --git a/src/boost/libs/contract/test/public_function/max_args.hpp b/src/boost/libs/contract/test/public_function/max_args.hpp new file mode 100644 index 000000000..210f730d1 --- /dev/null +++ b/src/boost/libs/contract/test/public_function/max_args.hpp @@ -0,0 +1,209 @@ + +// Copyright (C) 2008-2018 Lorenzo Caminiti +// Distributed under the Boost Software License, Version 1.0 (see accompanying +// file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt). +// See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html + +// Test max argument number for public function (with and without result). + +#include "../detail/oteststream.hpp" +#include <boost/contract/public_function.hpp> +#include <boost/contract/check.hpp> +#include <boost/contract/base_types.hpp> +#include <boost/contract/override.hpp> +#include <boost/preprocessor/repetition/repeat.hpp> +#include <boost/preprocessor/arithmetic/inc.hpp> +#include <boost/preprocessor/control/expr_iif.hpp> +#include <boost/preprocessor/cat.hpp> +#include <boost/preprocessor/stringize.hpp> +#include <boost/config.hpp> +#include <boost/detail/lightweight_test.hpp> +#include <sstream> + +boost::contract::test::detail::oteststream out; + +#if defined(BOOST_GCC) + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored "-Wunused-parameter" // aN from macros. +#elif defined(BOOST_CLANG) + #pragma clang diagnostic push + #pragma clang diagnostic ignored "-Wunused-parameter" // aN from macros. +#endif + +#define BOOST_CONTRACT_TEST_MAX_ARGS_PARAM_COMMA_(z, n, unused) \ + int BOOST_PP_CAT(a, n) , + +#define BOOST_CONTRACT_TEST_MAX_ARGS_COMMA_ARG_(z, n, unused) \ + , BOOST_PP_CAT(a, n) + +#define BOOST_CONTRACT_TEST_MAX_ARGS_N_(z, n, unused) \ + n + +struct b { + static void static_invariant() { out << "b::static_inv" << std::endl; } + void invariant() const { out << "b::inv" << std::endl; } + + #define BOOST_CONTRACT_TEST_MAX_ARGS_B_F_(z, n, unused) \ + virtual int BOOST_PP_CAT(f, n)( \ + BOOST_PP_REPEAT_ ## z( \ + n, BOOST_CONTRACT_TEST_MAX_ARGS_PARAM_COMMA_, ~) \ + boost::contract::virtual_* v = 0 \ + ) { \ + int result = 0; \ + boost::contract::check c = boost::contract::public_function( \ + v, result, this) \ + .precondition([] { \ + out << "b::" << BOOST_PP_STRINGIZE(BOOST_PP_CAT(f, n)) << \ + "::pre" << std::endl; \ + }) \ + .old([] { \ + out << "b::" << BOOST_PP_STRINGIZE(BOOST_PP_CAT(f, n)) << \ + "::old" << std::endl; \ + }) \ + .postcondition([] (int result) { \ + out << "b::" << BOOST_PP_STRINGIZE(BOOST_PP_CAT(f, n)) << \ + "::post" << std::endl; \ + }) \ + ; \ + out << "b::" << BOOST_PP_STRINGIZE(BOOST_PP_CAT(f, n)) << \ + "::body" << std::endl; \ + return result; \ + } + + BOOST_PP_REPEAT(BOOST_PP_INC(BOOST_CONTRACT_MAX_ARGS), + BOOST_CONTRACT_TEST_MAX_ARGS_B_F_, ~) +}; + +struct a + #define BASES public b + : BASES +{ + typedef BOOST_CONTRACT_BASE_TYPES(BASES) base_types; + #undef BASES + + static void static_invariant() { out << "a::static_inv" << std::endl; } + void invariant() const { out << "a::inv" << std::endl; } + + #define BOOST_CONTRACT_TEST_MAX_ARGS_A_F_(z, n, unused) \ + int BOOST_PP_CAT(f, n)( \ + BOOST_PP_REPEAT_ ## z( \ + n, BOOST_CONTRACT_TEST_MAX_ARGS_PARAM_COMMA_, ~) \ + boost::contract::virtual_* v = 0 \ + ) /* override */ { \ + int result = 0; \ + boost::contract::check c = boost::contract::public_function< \ + BOOST_PP_CAT(override_, BOOST_PP_CAT(f, n)) \ + >( \ + v, result, &a::BOOST_PP_CAT(f, n), this \ + BOOST_PP_REPEAT_ ## z( \ + n, BOOST_CONTRACT_TEST_MAX_ARGS_COMMA_ARG_, ~) \ + ) \ + .precondition([] { \ + out << "a::" << BOOST_PP_STRINGIZE(BOOST_PP_CAT(f, n)) << \ + "::pre" << std::endl; \ + }) \ + .old([] { \ + out << "a::" << BOOST_PP_STRINGIZE(BOOST_PP_CAT(f, n)) << \ + "::old" << std::endl; \ + }) \ + .postcondition([] (int result) { \ + out << "a::" << BOOST_PP_STRINGIZE(BOOST_PP_CAT(f, n)) << \ + "::post" << std::endl; \ + }) \ + ; \ + out << "a::" << BOOST_PP_STRINGIZE(BOOST_PP_CAT(f, n)) << \ + "::body" << std::endl; \ + return result; \ + } \ + BOOST_CONTRACT_OVERRIDE(BOOST_PP_CAT(f, n)) + + BOOST_PP_REPEAT(BOOST_PP_INC(BOOST_CONTRACT_MAX_ARGS), + BOOST_CONTRACT_TEST_MAX_ARGS_A_F_, ~) +}; + +#if defined(BOOST_GCC) + #pragma GCC diagnostic pop +#elif defined(BOOST_CLANG) + #pragma clang diagnostic pop +#endif + +int main() { + std::ostringstream ok; + a aa; + + #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS + #define BOOST_CONTRACT_TEST_entry_inv 1 + #else + #define BOOST_CONTRACT_TEST_entry_inv 0 + #endif + #ifndef BOOST_CONTRACT_NO_PRECONDITIONS + #define BOOST_CONTRACT_TEST_pre 1 + #else + #define BOOST_CONTRACT_TEST_pre 0 + #endif + #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS + #define BOOST_CONTRACT_TEST_exit_inv 1 + #else + #define BOOST_CONTRACT_TEST_exit_inv 0 + #endif + #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS + #define BOOST_CONTRACT_TEST_post 1 + #else + #define BOOST_CONTRACT_TEST_post 0 + #endif + #ifndef BOOST_CONTRACT_NO_OLDS + #define BOOST_CONTRACT_TEST_old 1 + #else + #define BOOST_CONTRACT_TEST_old 0 + #endif + + #define BOOST_CONTRACT_TEST_MAX_ARGS_TEST_(z, n, unused) \ + out.str(""); \ + aa.BOOST_PP_CAT(f, n)(BOOST_PP_ENUM_ ## z( \ + n, BOOST_CONTRACT_TEST_MAX_ARGS_N_, ~)); \ + ok.str(""); ok \ + BOOST_PP_EXPR_IIF(BOOST_CONTRACT_TEST_entry_inv, \ + << "b::static_inv\n" \ + << "b::inv\n"\ + << "a::static_inv\n" \ + << "a::inv\n" \ + ) \ + BOOST_PP_EXPR_IIF(BOOST_CONTRACT_TEST_pre, \ + << "b::" << BOOST_PP_STRINGIZE(BOOST_PP_CAT(f, n)) << \ + "::pre\n" \ + ) \ + BOOST_PP_EXPR_IIF(BOOST_CONTRACT_TEST_old, \ + << "b::" << BOOST_PP_STRINGIZE(BOOST_PP_CAT(f, n)) << \ + "::old\n" \ + << "a::" << BOOST_PP_STRINGIZE(BOOST_PP_CAT(f, n)) << \ + "::old\n" \ + ) \ + << "a::" << BOOST_PP_STRINGIZE(BOOST_PP_CAT(f, n)) << "::body\n" \ + BOOST_PP_EXPR_IIF(BOOST_CONTRACT_TEST_exit_inv, \ + << "b::static_inv\n" \ + << "b::inv\n"\ + << "a::static_inv\n" \ + << "a::inv\n" \ + ) \ + BOOST_PP_EXPR_IIF(BOOST_CONTRACT_TEST_post, \ + << "b::" << BOOST_PP_STRINGIZE(BOOST_PP_CAT(f, n)) << \ + "::old\n" \ + << "b::" << BOOST_PP_STRINGIZE(BOOST_PP_CAT(f, n)) << \ + "::post\n" \ + << "a::" << BOOST_PP_STRINGIZE(BOOST_PP_CAT(f, n)) << \ + "::post\n" \ + ) \ + ; \ + BOOST_TEST(out.eq(ok.str())); + + BOOST_PP_REPEAT(BOOST_PP_INC(BOOST_CONTRACT_MAX_ARGS), + BOOST_CONTRACT_TEST_MAX_ARGS_TEST_, ~) + + #undef BOOST_CONTRACT_TEST_entry_inv + #undef BOOST_CONTRACT_TEST_pre + #undef BOOST_CONTRACT_TEST_exit_inv + #undef BOOST_CONTRACT_TEST_post + #undef BOOST_CONTRACT_TEST_old + return boost::report_errors(); +} + diff --git a/src/boost/libs/contract/test/public_function/max_args0.cpp b/src/boost/libs/contract/test/public_function/max_args0.cpp new file mode 100644 index 000000000..5f6a40629 --- /dev/null +++ b/src/boost/libs/contract/test/public_function/max_args0.cpp @@ -0,0 +1,13 @@ + +// Copyright (C) 2008-2018 Lorenzo Caminiti +// Distributed under the Boost Software License, Version 1.0 (see accompanying +// file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt). +// See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html + +// Test with max argument number set to 0. + +#if !defined(BOOST_CONTRACT_MAX_ARGS) || BOOST_CONTRACT_MAX_ARGS != 0 + #error "build must define MAX_ARGS=0" +#endif +#include "max_args.hpp" + diff --git a/src/boost/libs/contract/test/public_function/max_args0_no_tva.cpp b/src/boost/libs/contract/test/public_function/max_args0_no_tva.cpp new file mode 100644 index 000000000..c2b24b929 --- /dev/null +++ b/src/boost/libs/contract/test/public_function/max_args0_no_tva.cpp @@ -0,0 +1,16 @@ + +// Copyright (C) 2008-2018 Lorenzo Caminiti +// Distributed under the Boost Software License, Version 1.0 (see accompanying +// file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt). +// See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html + +// Test with max argument number set to 0 and no variadic templates. + +#ifndef BOOST_NO_CXX11_VARIADIC_TEMPLATES + #error "build must define BOOST_NO_CXX11_VARIADIC_TEMPLATES" +#endif +#if !defined(BOOST_CONTRACT_MAX_ARGS) || BOOST_CONTRACT_MAX_ARGS != 0 + #error "build must define MAX_ARGS=0" +#endif +#include "max_args.hpp" + diff --git a/src/boost/libs/contract/test/public_function/max_args1.cpp b/src/boost/libs/contract/test/public_function/max_args1.cpp new file mode 100644 index 000000000..eea520267 --- /dev/null +++ b/src/boost/libs/contract/test/public_function/max_args1.cpp @@ -0,0 +1,13 @@ + +// Copyright (C) 2008-2018 Lorenzo Caminiti +// Distributed under the Boost Software License, Version 1.0 (see accompanying +// file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt). +// See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html + +// Test with max argument number set to 1. + +#if !defined(BOOST_CONTRACT_MAX_ARGS) || BOOST_CONTRACT_MAX_ARGS != 1 + #error "build must define MAX_ARGS=1" +#endif +#include "max_args.hpp" + diff --git a/src/boost/libs/contract/test/public_function/max_args1_no_tva.cpp b/src/boost/libs/contract/test/public_function/max_args1_no_tva.cpp new file mode 100644 index 000000000..303fc3ed5 --- /dev/null +++ b/src/boost/libs/contract/test/public_function/max_args1_no_tva.cpp @@ -0,0 +1,16 @@ + +// Copyright (C) 2008-2018 Lorenzo Caminiti +// Distributed under the Boost Software License, Version 1.0 (see accompanying +// file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt). +// See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html + +// Test with max argument number set to 1 and no variadic templates. + +#ifndef BOOST_NO_CXX11_VARIADIC_TEMPLATES + #error "build must define BOOST_NO_CXX11_VARIADIC_TEMPLATES" +#endif +#if !defined(BOOST_CONTRACT_MAX_ARGS) || BOOST_CONTRACT_MAX_ARGS != 1 + #error "build must define MAX_ARGS=1" +#endif +#include "max_args.hpp" + diff --git a/src/boost/libs/contract/test/public_function/max_args2.cpp b/src/boost/libs/contract/test/public_function/max_args2.cpp new file mode 100644 index 000000000..771fcc1c1 --- /dev/null +++ b/src/boost/libs/contract/test/public_function/max_args2.cpp @@ -0,0 +1,13 @@ + +// Copyright (C) 2008-2018 Lorenzo Caminiti +// Distributed under the Boost Software License, Version 1.0 (see accompanying +// file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt). +// See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html + +// Test with max argument number set to 2. + +#if !defined(BOOST_CONTRACT_MAX_ARGS) || BOOST_CONTRACT_MAX_ARGS != 2 + #error "build must define MAX_ARGS=2" +#endif +#include "max_args.hpp" + diff --git a/src/boost/libs/contract/test/public_function/max_args2_no_tva.cpp b/src/boost/libs/contract/test/public_function/max_args2_no_tva.cpp new file mode 100644 index 000000000..4ddf0bce8 --- /dev/null +++ b/src/boost/libs/contract/test/public_function/max_args2_no_tva.cpp @@ -0,0 +1,16 @@ + +// Copyright (C) 2008-2018 Lorenzo Caminiti +// Distributed under the Boost Software License, Version 1.0 (see accompanying +// file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt). +// See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html + +// Test with max argument number set to 2 and no variadic templates. + +#ifndef BOOST_NO_CXX11_VARIADIC_TEMPLATES + #error "build must define BOOST_NO_CXX11_VARIADIC_TEMPLATES" +#endif +#if !defined(BOOST_CONTRACT_MAX_ARGS) || BOOST_CONTRACT_MAX_ARGS != 2 + #error "build must define MAX_ARGS=2" +#endif +#include "max_args.hpp" + diff --git a/src/boost/libs/contract/test/public_function/max_args_no_tva.cpp b/src/boost/libs/contract/test/public_function/max_args_no_tva.cpp new file mode 100644 index 000000000..e0e1c5580 --- /dev/null +++ b/src/boost/libs/contract/test/public_function/max_args_no_tva.cpp @@ -0,0 +1,13 @@ + +// Copyright (C) 2008-2018 Lorenzo Caminiti +// Distributed under the Boost Software License, Version 1.0 (see accompanying +// file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt). +// See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html + +// Test with default max arg number (leave MAX_ARGS #undef) and no variadic tpl. + +#ifndef BOOST_NO_CXX11_VARIADIC_TEMPLATES + #error "build must define BOOST_NO_CXX11_VARIADIC_TEMPLATES" +#endif +#include "max_args.hpp" + diff --git a/src/boost/libs/contract/test/public_function/max_bases.cpp b/src/boost/libs/contract/test/public_function/max_bases.cpp new file mode 100644 index 000000000..4d8d1a8a9 --- /dev/null +++ b/src/boost/libs/contract/test/public_function/max_bases.cpp @@ -0,0 +1,59 @@ + +// Copyright (C) 2008-2018 Lorenzo Caminiti +// Distributed under the Boost Software License, Version 1.0 (see accompanying +// file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt). +// See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html + +// Test with max possible number of bases. + +#include <boost/contract/public_function.hpp> +#include <boost/contract/base_types.hpp> +#include <boost/contract/check.hpp> +#include <boost/contract/override.hpp> +#include <boost/preprocessor/repetition/repeat.hpp> +#include <boost/preprocessor/repetition/enum.hpp> +#include <boost/preprocessor/cat.hpp> + +// Limited by max size of current impl of Boost.MPL vector. +#ifndef BOOST_CONTRACT_TEST_CONFIG_MAX_BASES + #define BOOST_CONTRACT_TEST_CONFIG_MAX_BASES 20 +#endif + +#define BOOST_CONTRACT_TEST_base_decl(z, n, unused) \ + struct BOOST_PP_CAT(b, n) { \ + virtual void f(boost::contract::virtual_* v = 0) { \ + boost::contract::check c = boost::contract::public_function( \ + v, this); \ + } \ + }; + +BOOST_PP_REPEAT(BOOST_CONTRACT_TEST_CONFIG_MAX_BASES, + BOOST_CONTRACT_TEST_base_decl, ~) + +#define BOOST_CONTRACT_TEST_public_base(z, n, unused) public BOOST_PP_CAT(b, n) + +struct a + #define BASES \ + BOOST_PP_ENUM(BOOST_CONTRACT_TEST_CONFIG_MAX_BASES, \ + BOOST_CONTRACT_TEST_public_base, ~) + : BASES +{ + typedef BOOST_CONTRACT_BASE_TYPES(BASES) base_types; + #undef BASES + + void f(boost::contract::virtual_* v = 0) /* override */ { + boost::contract::check c = boost::contract::public_function<override_f>( + v, &a::f, this); + } + BOOST_CONTRACT_OVERRIDE(f) +}; + +int main() { + a aa; + aa.f(); + return 0; +} + +#undef BOOST_CONTRACT_TEST_base_decl +#undef BOOST_CONTRACT_TEST_public_base + diff --git a/src/boost/libs/contract/test/public_function/old_virtual.cpp b/src/boost/libs/contract/test/public_function/old_virtual.cpp new file mode 100644 index 000000000..ed6dcebd3 --- /dev/null +++ b/src/boost/libs/contract/test/public_function/old_virtual.cpp @@ -0,0 +1,214 @@ + +// Copyright (C) 2008-2018 Lorenzo Caminiti +// Distributed under the Boost Software License, Version 1.0 (see accompanying +// file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt). +// See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html + +// Test old inits/ftors and of mixed types up inheritance tree. + +#include "../detail/oteststream.hpp" +#include <boost/contract/public_function.hpp> +#include <boost/contract/base_types.hpp> +#include <boost/contract/assert.hpp> +#include <boost/contract/old.hpp> +#include <boost/contract/check.hpp> +#include <boost/contract/override.hpp> +#include <boost/lexical_cast.hpp> +#include <boost/detail/lightweight_test.hpp> +#include <sstream> +#include <string> + +boost::contract::test::detail::oteststream out; + +struct num { + static num make(int i) { // Test no ctor (not even explicit) but for copy. + num n; + n.value(i); + return n; + } + + num(num const& other) : value_(other.value_) {} + + void value(int i) { value_ = boost::lexical_cast<std::string>(i); } + int value() const { return boost::lexical_cast<int>(value_); } + + num operator+(int left) { + num n; + n.value(value() + left); + return n; + } + +private: + num() {} // Test no visible default ctor (only copy ctor). + num& operator=(num const&); // Test no copy operator (only copy ctor). + + std::string value_; // Test this size-of != from other old type `int` below. +}; + +struct c { + virtual void f(int& i, num& n, boost::contract::virtual_* v = 0) { + boost::contract::old_ptr<int> old_a = BOOST_CONTRACT_OLDOF(v, i + 1); + boost::contract::old_ptr<num> old_b = BOOST_CONTRACT_OLDOF(v, n + 2); + boost::contract::old_ptr<int> old_x; + boost::contract::old_ptr<num> old_y; + boost::contract::check c = boost::contract::public_function(v, this) + .old([&] { + out << "c::f::old" << std::endl; + old_x = BOOST_CONTRACT_OLDOF(v, i + 3); + old_y = BOOST_CONTRACT_OLDOF(v, n + 4); + }) + .postcondition([&] { + out << "c::f::post" << std::endl; + BOOST_CONTRACT_ASSERT(*old_a == n.value() + 1); + BOOST_CONTRACT_ASSERT(old_b->value() == i + 2); + BOOST_CONTRACT_ASSERT(*old_x == n.value() + 3); + BOOST_CONTRACT_ASSERT(old_y->value() == i + 4); + }) + ; + out << "c::f::body" << std::endl; + int tmp = i; + i = n.value(); + n.value(tmp); + } +}; + +struct b + #define BASES public c + : BASES +{ + typedef BOOST_CONTRACT_BASE_TYPES(BASES) base_types; + #undef BASES + + virtual void f(int& i, num& n, boost::contract::virtual_* v = 0) + /* override */ { + boost::contract::old_ptr<int> old_a = BOOST_CONTRACT_OLDOF(v, i + 1); + boost::contract::old_ptr<num> old_b = BOOST_CONTRACT_OLDOF(v, n + 2); + boost::contract::old_ptr<int> old_x; + boost::contract::old_ptr<num> old_y; + boost::contract::check c = boost::contract::public_function< + override_f>(v, &c::f, this, i, n) + .old([&] { + out << "b::f::old" << std::endl; + old_x = BOOST_CONTRACT_OLDOF(v, i + 3); + old_y = BOOST_CONTRACT_OLDOF(v, n + 4); + }) + .postcondition([&] { + out << "b::f::post" << std::endl; + BOOST_CONTRACT_ASSERT(*old_a == n.value() + 1); + BOOST_CONTRACT_ASSERT(old_b->value() == i + 2); + BOOST_CONTRACT_ASSERT(*old_x == n.value() + 3); + BOOST_CONTRACT_ASSERT(old_y->value() == i + 4); + }) + ; + out << "b::f::body" << std::endl; + int tmp = i; + i = n.value(); + n.value(tmp); + } + BOOST_CONTRACT_OVERRIDE(f) +}; + +struct a + #define BASES public b + : BASES +{ + typedef BOOST_CONTRACT_BASE_TYPES(BASES) base_types; + #undef BASES + + virtual void f(int& i, num& n, boost::contract::virtual_* v = 0) + /* override */ { + boost::contract::old_ptr<int> old_a = BOOST_CONTRACT_OLDOF(v, i + 1); + boost::contract::old_ptr<num> old_b = BOOST_CONTRACT_OLDOF(v, n + 2); + boost::contract::old_ptr<int> old_x; + boost::contract::old_ptr<num> old_y; + boost::contract::check c = boost::contract::public_function< + override_f>(v, &c::f, this, i, n) + .old([&] { + out << "a::f::old" << std::endl; + old_x = BOOST_CONTRACT_OLDOF(v, i + 3); + old_y = BOOST_CONTRACT_OLDOF(v, n + 4); + }) + .postcondition([&] { + out << "a::f::post" << std::endl; + BOOST_CONTRACT_ASSERT(*old_a == n.value() + 1); + BOOST_CONTRACT_ASSERT(old_b->value() == i + 2); + BOOST_CONTRACT_ASSERT(*old_x == n.value() + 3); + BOOST_CONTRACT_ASSERT(old_y->value() == i + 4); + }) + ; + out << "a::f::body" << std::endl; + int tmp = i; + i = n.value(); + n.value(tmp); + } + BOOST_CONTRACT_OVERRIDE(f) +}; + +int main() { + std::ostringstream ok; + int i = 0; + num n = num::make(0); + + i = 123; + n.value(-123); + a aa; // Test virtual call with 2 bases. + out.str(""); + aa.f(i, n); + ok.str(""); ok + #ifndef BOOST_CONTRACT_NO_OLDS + << "c::f::old" << std::endl + << "b::f::old" << std::endl + << "a::f::old" << std::endl + #endif + << "a::f::body" << std::endl + #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS + << "c::f::old" << std::endl + << "c::f::post" << std::endl + << "b::f::old" << std::endl + << "b::f::post" << std::endl + // No old call here because not a base object. + << "a::f::post" << std::endl + #endif + ; + BOOST_TEST(out.eq(ok.str())); + + i = 456; + n.value(-456); + b bb; // Test virtual call with 1 base. + out.str(""); + bb.f(i, n); + ok.str(""); ok + #ifndef BOOST_CONTRACT_NO_OLDS + << "c::f::old" << std::endl + << "b::f::old" << std::endl + #endif + << "b::f::body" << std::endl + #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS + << "c::f::old" << std::endl + << "c::f::post" << std::endl + // No old call here because not a base object. + << "b::f::post" << std::endl + #endif + ; + BOOST_TEST(out.eq(ok.str())); + + i = 789; + n.value(-789); + c cc; // Test virtual call with no bases. + out.str(""); + cc.f(i, n); + ok.str(""); ok + #ifndef BOOST_CONTRACT_NO_OLDS + << "c::f::old" << std::endl + #endif + << "c::f::body" << std::endl + #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS + // No old call here because not a base object. + << "c::f::post" << std::endl + #endif + ; + BOOST_TEST(out.eq(ok.str())); + + return boost::report_errors(); +} + diff --git a/src/boost/libs/contract/test/public_function/overload.cpp b/src/boost/libs/contract/test/public_function/overload.cpp new file mode 100644 index 000000000..64101d265 --- /dev/null +++ b/src/boost/libs/contract/test/public_function/overload.cpp @@ -0,0 +1,10 @@ + +// Copyright (C) 2008-2018 Lorenzo Caminiti +// Distributed under the Boost Software License, Version 1.0 (see accompanying +// file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt). +// See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html + +// Test public function overloads (with variadic templates if supported). + +#include "overload.hpp" + diff --git a/src/boost/libs/contract/test/public_function/overload.hpp b/src/boost/libs/contract/test/public_function/overload.hpp new file mode 100644 index 000000000..46abdd56a --- /dev/null +++ b/src/boost/libs/contract/test/public_function/overload.hpp @@ -0,0 +1,343 @@ + +// Copyright (C) 2008-2018 Lorenzo Caminiti +// Distributed under the Boost Software License, Version 1.0 (see accompanying +// file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt). +// See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html + +// Test public function overloads. + +#include "../detail/oteststream.hpp" +#include <boost/contract/public_function.hpp> +#include <boost/contract/base_types.hpp> +#include <boost/contract/override.hpp> +#include <boost/contract/check.hpp> +#include <boost/detail/lightweight_test.hpp> +#include <sstream> +#include <string> + +boost::contract::test::detail::oteststream out; + +struct b { + static void static_invariant() { out << "b::static_inv" << std::endl; } + void invariant() const { out << "b::inv" << std::endl; } + + virtual void f(int /* x */, boost::contract::virtual_* v = 0) { + boost::contract::check c = boost::contract::public_function(v, this) + .precondition([] { out << "b::f(int)::pre" << std::endl; }) + .old([] { out << "b::f(int)::old" << std::endl; }) + .postcondition([] { out << "b::f(int)::post" << std::endl; }) + ; + out << "b::f(int)::body" << std::endl; + } + + virtual void f(char const* /* x */, boost::contract::virtual_* v = 0) { + boost::contract::check c = boost::contract::public_function(v, this) + .precondition([] { out << "b::f(char const*)::pre" << std::endl; }) + .old([] { out << "b::f(char const*)::old" << std::endl; }) + .postcondition( + [] { out << "b::f(char const*)::post" << std::endl; }) + ; + out << "b::f(char const*)::body" << std::endl; + } + + virtual void f(int /* x */, int /* y */, boost::contract::virtual_* v = 0) { + boost::contract::check c = boost::contract::public_function(v, this) + .precondition([] { out << "b::f(int, int)::pre" << std::endl; }) + .old([] { out << "b::f(int, int)::old" << std::endl; }) + .postcondition([] { out << "b::f(int, int)::post" << std::endl; }) + ; + out << "b::f(int, int)::body" << std::endl; + } + + virtual void f(boost::contract::virtual_* v = 0) { + boost::contract::check c = boost::contract::public_function(v, this) + .precondition([] { out << "b::f()::pre" << std::endl; }) + .old([] { out << "b::f()::old" << std::endl; }) + .postcondition([] { out << "b::f()::post" << std::endl; }) + ; + out << "b::f()::body" << std::endl; + } + + void f(int /* x */[2][3], boost::contract::virtual_* v = 0) { + boost::contract::check c = boost::contract::public_function(v, this) + .precondition([] { out << "b::f(int[2][3])::pre" << std::endl; }) + .old([] { out << "b::f(int[2][3])::old" << std::endl; }) + .postcondition([] { out << "b::f(int[2][3])::post" << std::endl; }) + ; + out << "b::f(int[2][3])::body" << std::endl; + } + + void f(void (* /* x */)(int), boost::contract::virtual_* v = 0) { + boost::contract::check c = boost::contract::public_function(v, this) + .precondition( + [] { out << "b::f(void (*)(int))::pre" << std::endl; }) + .old( + [] { out << "b::f(void (*)(int))::old" << std::endl; }) + .postcondition( + [] { out << "b::f(void (*)(int))::post" << std::endl; }) + ; + out << "b::f(void (*)(int))::body" << std::endl; + } +}; + +struct a + #define BASES public b + : BASES +{ + typedef BOOST_CONTRACT_BASE_TYPES(BASES) base_types; + #undef BASES + + static void static_invariant() { out << "a::static_inv" << std::endl; } + void invariant() const { out << "a::inv" << std::endl; } + + void f(int x, boost::contract::virtual_* v = 0) /* override */ { + boost::contract::check c = boost::contract::public_function<override_f>( + v, + static_cast<void (a::*)(int, boost::contract::virtual_*)>(&a::f), + this, x + ) + .precondition([] { out << "a::f(int)::pre" << std::endl; }) + .old([] { out << "a::f(int)::old" << std::endl; }) + .postcondition([] { out << "a::f(int)::post" << std::endl; }) + ; + out << "a::f(int)::body" << std::endl; + } + + // Test overload via argument type. + void f(char const* x, boost::contract::virtual_* v = 0) /* override */ { + boost::contract::check c = boost::contract::public_function<override_f>( + v, + static_cast<void (a::*)(char const*, boost::contract::virtual_*)>( + &a::f), + this, x + ) + .precondition([] { out << "a::f(char const*)::pre" << std::endl; }) + .old([] { out << "a::f(char const*)::old" << std::endl; }) + .postcondition( + [] { out << "a::f(char const*)::post" << std::endl; }) + ; + out << "a::f(char const*)::body" << std::endl; + } + + // Test overload via argument count. + void f(int x, int y, boost::contract::virtual_* v = 0) /* override */ { + boost::contract::check c = boost::contract::public_function<override_f>( + v, + static_cast<void (a::*)(int, int, boost::contract::virtual_*)>( + &a::f), + this, x, y + ) + .precondition([] { out << "a::f(int, int)::pre" << std::endl; }) + .old([] { out << "a::f(int, int)::old" << std::endl; }) + .postcondition([] { out << "a::f(int, int)::post" << std::endl; }) + ; + out << "a::f(int, int)::body" << std::endl; + } + + // Test overload via template argument type. + template<typename T> + void f(T /* x */) { // Template cannot be virtual (or override) in C++. + boost::contract::check c = boost::contract::public_function(this) + .precondition([] { out << "a::f(T)::pre" << std::endl; }) + .old([] { out << "a::f(T)::old" << std::endl; }) + .postcondition([] { out << "a::f(T)::post" << std::endl; }) + ; + out << "a::f(T)::body" << std::endl; + } + + // Test no overload ambiguity in public_function called by these two cases. + + // NOTE: In *all* other cases, public_function is always called with a + // different number of arguments so there cannot be ambiguity either + // (0 args for static, 1 arg for non-virtual, 2 or 3 args for virtual, + // >= 3 for override, so only in cases below of 3 args for virtual and 3 + // for override there could be ambiguity but there is not because of + // presence or absence of override_... template parameter). + + typedef void (a::* f0_ptr)(boost::contract::virtual_*); + + void f(boost::contract::virtual_* v = 0) /* override */ { + f0_ptr f0 = static_cast<f0_ptr>(&a::f); + // Test this and public_function call in func below both take same 3 + // args but they are ambiguous because of presence override_f. + boost::contract::check c = boost::contract::public_function<override_f>( + v, f0, this) + .precondition([] { out << "a::f()::pre" << std::endl; }) + .old([] { out << "a::f()::old" << std::endl; }) + .postcondition([] { out << "a::f()::post" << std::endl; }) + ; + out << "a::f()::body" << std::endl; + } + + virtual f0_ptr f(bool /* x */, boost::contract::virtual_* v = 0) + /* not an override */ { + f0_ptr f0 = static_cast<f0_ptr>(&a::f); + // Test this and public_function call in func above both take same 3 + // args but they are ambiguous because of lack of override_f. + boost::contract::check c = boost::contract::public_function( + v, f0, this) + .precondition([] { out << "a::f(bool)::pre" << std::endl; }) + .old([] { out << "a::f(bool)::old" << std::endl; }) + .postcondition([] (f0_ptr const&) { + out << "a::f(bool)::post" << std::endl; }) + ; + out << "a::f(bool)::body" << std::endl; + return f0; + } + + // Test overload with array parameter. + void f(int x[2][3], boost::contract::virtual_* v = 0) /* override */ { + boost::contract::check c = boost::contract::public_function<override_f>( + v, + static_cast<void (a::*)(int[2][3], boost::contract::virtual_*)>( + &a::f), + this, x + ) + .precondition([] { out << "a::f(int[2][3])::pre" << std::endl; }) + .old([] { out << "a::f(int[2][3])::old" << std::endl; }) + .postcondition([] { out << "a::f(int[2][3])::post" << std::endl; }) + ; + out << "a::f(int[2][3])::body" << std::endl; + } + + // Test overload with function pointer parameter. + void f(void (*x)(int), boost::contract::virtual_* v = 0) /* override */ { + boost::contract::check c = boost::contract::public_function<override_f>( + v, + static_cast<void (a::*)(void (*)(int), boost::contract::virtual_*)>( + &a::f), + this, x + ) + .precondition( + [] { out << "a::f(void (*)(int))::pre" << std::endl; }) + .old( + [] { out << "a::f(void (*)(int))::old" << std::endl; }) + .postcondition( + [] { out << "a::f(void (*)(int))::post" << std::endl; }) + ; + out << "a::f(void (*)(int))::body" << std::endl; + } + + BOOST_CONTRACT_OVERRIDE(f) +}; + +void g(int) {} + +std::string ok_args(std::string const& args) { + std::ostringstream ok; ok + #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS + << "b::static_inv" << std::endl + << "b::inv" << std::endl + << "a::static_inv" << std::endl + << "a::inv" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_PRECONDITIONS + << "b::f(" << args << ")::pre" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_OLDS + << "b::f(" << args << ")::old" << std::endl + << "a::f(" << args << ")::old" << std::endl + #endif + << "a::f(" << args << ")::body" << std::endl + #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS + << "b::static_inv" << std::endl + << "b::inv" << std::endl + << "a::static_inv" << std::endl + << "a::inv" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS + << "b::f(" << args << ")::old" << std::endl + << "b::f(" << args << ")::post" << std::endl + << "a::f(" << args << ")::post" << std::endl + #endif + ; + return ok.str(); +} + +int main() { + std::ostringstream ok; + a aa; + + out.str(""); + aa.f(123); + ok.str(""); ok << ok_args("int"); + BOOST_TEST(out.eq(ok.str())); + + out.str(""); + aa.f("abc"); + ok.str(""); ok << ok_args("char const*"); + BOOST_TEST(out.eq(ok.str())); + + out.str(""); + aa.f(123, 456); + ok.str(""); ok << ok_args("int, int"); + BOOST_TEST(out.eq(ok.str())); + + out.str(""); + struct {} zz; + aa.f(zz); // Call template (so no override because no virtual). + ok.str(""); ok + #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS + << "a::static_inv" << std::endl + << "a::inv" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_PRECONDITIONS + << "a::f(T)::pre" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_OLDS + << "a::f(T)::old" << std::endl + #endif + << "a::f(T)::body" << std::endl + #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS + << "a::static_inv" << std::endl + << "a::inv" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS + << "a::f(T)::post" << std::endl + #endif + ; + BOOST_TEST(out.eq(ok.str())); + + out.str(""); + aa.f(); + ok.str(""); ok << ok_args(""); + BOOST_TEST(out.eq(ok.str())); + + out.str(""); + aa.f(true); // This does not override (public_function ambiguity testing). + ok.str(""); ok + #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS + << "a::static_inv" << std::endl + << "a::inv" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_PRECONDITIONS + << "a::f(bool)::pre" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_OLDS + << "a::f(bool)::old" << std::endl + #endif + << "a::f(bool)::body" << std::endl + #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS + << "a::static_inv" << std::endl + << "a::inv" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS + << "a::f(bool)::post" << std::endl + #endif + ; + BOOST_TEST(out.eq(ok.str())); + + out.str(""); + int i[2][3]; + aa.f(i); + ok.str(""); ok << ok_args("int[2][3]"); + BOOST_TEST(out.eq(ok.str())); + + out.str(""); + aa.f(&g); + ok.str(""); ok << ok_args("void (*)(int)"); + BOOST_TEST(out.eq(ok.str())); + + return boost::report_errors(); +} + diff --git a/src/boost/libs/contract/test/public_function/overload_no_tva.cpp b/src/boost/libs/contract/test/public_function/overload_no_tva.cpp new file mode 100644 index 000000000..328d4efe6 --- /dev/null +++ b/src/boost/libs/contract/test/public_function/overload_no_tva.cpp @@ -0,0 +1,13 @@ + +// Copyright (C) 2008-2018 Lorenzo Caminiti +// Distributed under the Boost Software License, Version 1.0 (see accompanying +// file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt). +// See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html + +// Test public function overloads (always without variadic templates). + +#ifndef BOOST_NO_CXX11_VARIADIC_TEMPLATES + #error "build must define BOOST_NO_CXX11_VARIADIC_TEMPLATES" +#endif +#include "overload.hpp" + diff --git a/src/boost/libs/contract/test/public_function/override.hpp b/src/boost/libs/contract/test/public_function/override.hpp new file mode 100644 index 000000000..c25757a4c --- /dev/null +++ b/src/boost/libs/contract/test/public_function/override.hpp @@ -0,0 +1,41 @@ + +// no #include guard + +// Copyright (C) 2008-2018 Lorenzo Caminiti +// Distributed under the Boost Software License, Version 1.0 (see accompanying +// file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt). +// See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html + +// Test error if override func does not actually override (unless PERMISSIVE). + +#include <boost/contract/public_function.hpp> +#include <boost/contract/base_types.hpp> +#include <boost/contract/override.hpp> +#include <boost/contract/check.hpp> + +struct b { + virtual void g(boost::contract::virtual_* v = 0) { + boost::contract::check c = boost::contract::public_function(v, this); + } +}; + +struct a + #define BASES public b + : BASES +{ + typedef BOOST_CONTRACT_BASE_TYPES(BASES) base_types; + #undef BASES + + virtual void f(boost::contract::virtual_* v = 0) /* override */ { + boost::contract::check c = boost::contract::public_function< + override_f>(v, &a::f, this); + } + BOOST_CONTRACT_OVERRIDE(f) +}; + +int main() { + a aa; + aa.f(); + return 0; +} + diff --git a/src/boost/libs/contract/test/public_function/override_error.cpp b/src/boost/libs/contract/test/public_function/override_error.cpp new file mode 100644 index 000000000..1dd233ab4 --- /dev/null +++ b/src/boost/libs/contract/test/public_function/override_error.cpp @@ -0,0 +1,14 @@ + +// Copyright (C) 2008-2018 Lorenzo Caminiti +// Distributed under the Boost Software License, Version 1.0 (see accompanying +// file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt). +// See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html + +// Test error if override func does not actually override. + +#undef BOOST_CONTRACT_PERMISSIVE +#include "override.hpp" +#ifdef BOOST_CONTRACT_NO_PUBLIC_FUNCTIONS + #error "Forcing error even when public functions not checked" +#endif + diff --git a/src/boost/libs/contract/test/public_function/override_permissive.cpp b/src/boost/libs/contract/test/public_function/override_permissive.cpp new file mode 100644 index 000000000..e3a2be5ba --- /dev/null +++ b/src/boost/libs/contract/test/public_function/override_permissive.cpp @@ -0,0 +1,13 @@ + +// Copyright (C) 2008-2018 Lorenzo Caminiti +// Distributed under the Boost Software License, Version 1.0 (see accompanying +// file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt). +// See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html + +// Test no error if permissive even when override f does not actually override. + +#ifndef BOOST_CONTRACT_PERMISSIVE + #error "build must define PERMISSIVE" +#endif +#include "override.hpp" + diff --git a/src/boost/libs/contract/test/public_function/protected.cpp b/src/boost/libs/contract/test/public_function/protected.cpp new file mode 100644 index 000000000..8ec7e7d79 --- /dev/null +++ b/src/boost/libs/contract/test/public_function/protected.cpp @@ -0,0 +1,88 @@ + +// Copyright (C) 2008-2018 Lorenzo Caminiti +// Distributed under the Boost Software License, Version 1.0 (see accompanying +// file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt). +// See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html + +// Test overriding function never overrides protected function contract. + +#include "../detail/oteststream.hpp" +#include <boost/contract/function.hpp> +#include <boost/contract/public_function.hpp> +#include <boost/contract/base_types.hpp> +#include <boost/contract/check.hpp> +#include <boost/detail/lightweight_test.hpp> +#include <sstream> + +boost::contract::test::detail::oteststream out; + +struct b { + static void static_invariant() { out << "b::static_inv" << std::endl; } + void invariant() const { out << "b::inv" << std::endl; } + +protected: + // NOTE: This is the correct way of programming contracts for overridden + // protected and overriding public functions: Both must use virtual_ + // (otherwise C++ won't override because mismatching parameters), but + // overridden protected does not use public_function. + virtual void f(boost::contract::virtual_* /* v */ = 0) { + boost::contract::check c = boost::contract::function() + .precondition([] { out << "b::f::pre" << std::endl; }) + .old([] { out << "b::f::old" << std::endl; }) + .postcondition([] { out << "b::f::post" << std::endl; }) + ; + out << "b::f::body" << std::endl; + } +}; +struct a + #define BASES public b + : BASES +{ + typedef BOOST_CONTRACT_BASE_TYPES(BASES) base_types; + #undef BASES + + static void static_invariant() { out << "a::static_inv" << std::endl; } + void invariant() const { out << "a::inv" << std::endl; } + + void f(boost::contract::virtual_* v = 0) /* not override */ { + // C++ func a::f overrides b::f, but contracts don't (so no override_f). + boost::contract::check c = boost::contract::public_function(v, this) + .precondition([] { out << "a::f::pre" << std::endl; }) + .old([] { out << "a::f::old" << std::endl; }) + .postcondition([] { out << "a::f::post" << std::endl; }) + ; + out << "a::f::body" << std::endl; + } +}; + +int main() { + std::ostringstream ok; + + a aa; + out.str(""); + aa.f(); + ok.str(""); ok + #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS + << "a::static_inv" << std::endl + << "a::inv" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_PRECONDITIONS + << "a::f::pre" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_OLDS + << "a::f::old" << std::endl + #endif + << "a::f::body" << std::endl + #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS + << "a::static_inv" << std::endl + << "a::inv" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS + << "a::f::post" << std::endl + #endif + ; + BOOST_TEST(out.eq(ok.str())); + + return boost::report_errors(); +} + diff --git a/src/boost/libs/contract/test/public_function/protected_error.cpp b/src/boost/libs/contract/test/public_function/protected_error.cpp new file mode 100644 index 000000000..f7e01d2fe --- /dev/null +++ b/src/boost/libs/contract/test/public_function/protected_error.cpp @@ -0,0 +1,52 @@ + +// Copyright (C) 2008-2018 Lorenzo Caminiti +// Distributed under the Boost Software License, Version 1.0 (see accompanying +// file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt). +// See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html + +// Test a public function contract cannot override from a protected one. + +#include <boost/contract/public_function.hpp> +#include <boost/contract/base_types.hpp> +#include <boost/contract/override.hpp> +#include <boost/contract/check.hpp> + +struct b { +protected: + virtual void f(boost::contract::virtual_* v = 0) { + boost::contract::check c = boost::contract::public_function(v, this); + } + + friend class boost::contract::access; // Test this cannot prevent error. +}; + +struct a + #define BASES public b + : BASES +{ + typedef BOOST_CONTRACT_BASE_TYPES(BASES) base_types; + #undef BASES + + void f(boost::contract::virtual_* v = 0) /* override */ { + boost::contract::check c = boost::contract::public_function<override_f>( + v, &a::f, this); // Error (override cannot access b::f). + #ifdef BOOST_CONTRACT_NO_PUBLIC_FUNCTIONS + #error "Forcing error even when public functions not checked" + #endif + } + + // Correctly, GCC and CLang cannot even see b::f as part of overloaded bases + // because it is protected. MSVC also fails compilation but only when + // override_f below tries to call b::f (because it is protected so it cannot + // be seen from within override_f). + BOOST_CONTRACT_OVERRIDE(f) + + friend class boost::contract::access; // Test this cannot prevent error. +}; + +int main() { + a aa; + aa.f(); + return 0; +} + diff --git a/src/boost/libs/contract/test/public_function/smoke.cpp b/src/boost/libs/contract/test/public_function/smoke.cpp new file mode 100644 index 000000000..7463d047e --- /dev/null +++ b/src/boost/libs/contract/test/public_function/smoke.cpp @@ -0,0 +1,104 @@ + +// Copyright (C) 2008-2018 Lorenzo Caminiti +// Distributed under the Boost Software License, Version 1.0 (see accompanying +// file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt). +// See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html + +// Test public member function subcontracting. + +#include "smoke.hpp" +#include <boost/preprocessor/control/iif.hpp> +#include <boost/detail/lightweight_test.hpp> +#include <sstream> + +int main() { + std::ostringstream ok; + + a aa; // Test call to derived out-most leaf. + s_type s; s.value = "A"; + out.str(""); + result_type& r = aa.f(s); + + ok.str(""); ok + #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS + << "d::static_inv" << std::endl + << "d::inv" << std::endl + << "e::static_inv" << std::endl + << "e::inv" << std::endl + << "c::static_inv" << std::endl + << "c::inv" << std::endl + << "a::static_inv" << std::endl + << "a::inv" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_PRECONDITIONS + << "d::f::pre" << std::endl + << "e::f::pre" << std::endl + << "c::f::pre" << std::endl + << "a::f::pre" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_OLDS + << "d::f::old" << std::endl + << "e::f::old" << std::endl + << "c::f::old" << std::endl + << "a::f::old" << std::endl + #endif + << "a::f::body" << std::endl + #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS + << "d::static_inv" << std::endl + << "d::inv" << std::endl + << "e::static_inv" << std::endl + << "e::inv" << std::endl + << "c::static_inv" << std::endl + << "c::inv" << std::endl + << "a::static_inv" << std::endl + << "a::inv" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS + << "d::f::old" << std::endl + << "d::f::post" << std::endl + << "e::f::old" << std::endl + << "e::f::post" << std::endl + << "c::f::old" << std::endl + << "c::f::post" << std::endl + // No old call here because not a base object. + << "a::f::post" << std::endl + #endif + ; + BOOST_TEST(out.eq(ok.str())); + + #ifndef BOOST_CONTRACT_NO_OLDS + #define BOOST_CONTRACT_TEST_old 1u + #else + #define BOOST_CONTRACT_TEST_old 0u + #endif + + BOOST_TEST_EQ(r.value, "A"); + BOOST_TEST_EQ(s.value, "acde"); + BOOST_TEST_EQ(s.copies(), BOOST_CONTRACT_TEST_old * 4); + BOOST_TEST_EQ(s.evals(), BOOST_CONTRACT_TEST_old * 4); + 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_CONTRACT_TEST_old); + BOOST_TEST_EQ(aa.x.evals(), BOOST_CONTRACT_TEST_old); + 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_CONTRACT_TEST_old); + BOOST_TEST_EQ(aa.y.evals(), BOOST_CONTRACT_TEST_old); + 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_CONTRACT_TEST_old); + BOOST_TEST_EQ(aa.t<'d'>::z.evals(), BOOST_CONTRACT_TEST_old); + 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_CONTRACT_TEST_old); + BOOST_TEST_EQ(aa.t<'e'>::z.evals(), BOOST_CONTRACT_TEST_old); + BOOST_TEST_EQ(aa.t<'e'>::z.ctors(), aa.t<'e'>::z.dtors() + 1); // 1 member. + + #undef BOOST_CONTRACT_TEST_old + return boost::report_errors(); +} + diff --git a/src/boost/libs/contract/test/public_function/smoke.hpp b/src/boost/libs/contract/test/public_function/smoke.hpp new file mode 100644 index 000000000..8ebec1bd1 --- /dev/null +++ b/src/boost/libs/contract/test/public_function/smoke.hpp @@ -0,0 +1,278 @@ + +#ifndef BOOST_CONTRACT_TEST_PUBLIC_FUNCTION_CONTRACTS_HPP_ +#define BOOST_CONTRACT_TEST_PUBLIC_FUNCTION_CONTRACTS_HPP_ + +// Copyright (C) 2008-2018 Lorenzo Caminiti +// Distributed under the Boost Software License, Version 1.0 (see accompanying +// file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt). +// See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html + +// Test public member function subcontracting (also with old and return values). + +#include "../detail/oteststream.hpp" +#include "../detail/counter.hpp" +#include <boost/contract/public_function.hpp> +#include <boost/contract/base_types.hpp> +#include <boost/contract/assert.hpp> +#include <boost/contract/old.hpp> +#include <boost/contract/check.hpp> +#include <boost/contract/override.hpp> +#include <boost/config.hpp> +#include <string> + +boost::contract::test::detail::oteststream out; + +struct s_tag; +typedef boost::contract::test::detail::counter<s_tag, std::string> s_type; + +struct except_error {}; + +struct result_type { + std::string value; + explicit result_type(std::string const& s) : value(s) {} + +private: // Test non-copyable and non-default-constructible result. + result_type(); + result_type(result_type const&); + result_type& operator=(result_type const&); +}; + +// Test base without additional bases and pure virtual. +template<char Id> +struct t { + static void static_invariant() { out << Id << "::static_inv" << std::endl; } + + void invariant() const { + out << Id << "::inv" << std::endl; + BOOST_CONTRACT_ASSERT(z.value != ""); + } + + struct z_tag; + typedef boost::contract::test::detail::counter<z_tag, std::string> z_type; + z_type z; + + t() { z.value.push_back(Id); } + + virtual result_type& f(s_type& s, boost::contract::virtual_* v = 0) = 0; +}; + +template<char Id> // Requires: Only pass lower case Id so it'll never be 'X'. +result_type& t<Id>::f(s_type& s, boost::contract::virtual_* v) { + std::ostringstream r; r << "none-" << Id; + static result_type result(r.str()); + boost::contract::old_ptr<z_type> old_z = + BOOST_CONTRACT_OLDOF(v, z_type::eval(z)); + boost::contract::old_ptr<s_type> old_s; + boost::contract::check c = boost::contract::public_function(v, result, this) + .precondition([&] { + out << Id << "::f::pre" << std::endl; + BOOST_CONTRACT_ASSERT(s.value[0] == Id || s.value[0] == 'X'); + }) + .old([&] { + out << Id << "::f::old" << std::endl; + old_s = BOOST_CONTRACT_OLDOF(v, s_type::eval(s)); + }) + .postcondition([&] (result_type const& result) { + out << Id << "::f::post" << std::endl; + BOOST_CONTRACT_ASSERT(z.value == old_z->value + old_s->value); + BOOST_CONTRACT_ASSERT(s.value.find(old_z->value) != + std::string::npos); + BOOST_CONTRACT_ASSERT(result.value == old_s->value); + }) + .except([&] { + out << Id << "::f::except" << std::endl; + BOOST_CONTRACT_ASSERT(z.value == old_z->value); + BOOST_CONTRACT_ASSERT(s.value == old_s->value); + }) + ; + out << "t<" << Id << ">::f::body" << std::endl; + if(s.value == "X") throw except_error(); + return result; +} + +// Test base with other bases, multiple inheritance, and no subcontracting from +// protected and private bases (even if fully contracted). +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 + + static void static_invariant() { out << "c::static_inv" << std::endl; } + + void invariant() const { + out << "c::inv" << std::endl; + BOOST_CONTRACT_ASSERT(y.value != ""); + } + + struct y_tag; + typedef boost::contract::test::detail::counter<y_tag, std::string> y_type; + y_type y; + + c() { y.value = "c"; } + + virtual result_type& f(s_type& s, boost::contract::virtual_* v = 0) + /* override */ { + static result_type result("none-c"); + boost::contract::old_ptr<y_type> old_y = + BOOST_CONTRACT_OLDOF(v, y_type::eval(y)); + boost::contract::old_ptr<s_type> old_s; + boost::contract::check c = boost::contract::public_function< + override_f>(v, result, &c::f, this, s) + .precondition([&] { + out << "c::f::pre" << std::endl; + BOOST_CONTRACT_ASSERT(s.value == "C" || s.value == "X"); + }) + .old([&] { + out << "c::f::old" << std::endl; + old_s = BOOST_CONTRACT_OLDOF(v, s_type::eval(s)); + }) + .postcondition([&] (result_type const& result) { + out << "c::f::post" << std::endl; + BOOST_CONTRACT_ASSERT(y.value == old_y->value + old_s->value); + BOOST_CONTRACT_ASSERT(s.value.find(old_y->value) != + std::string::npos); + BOOST_CONTRACT_ASSERT(result.value == old_s->value); + }) + .except([&] { + out << "c::f::except" << std::endl; + BOOST_CONTRACT_ASSERT(y.value == old_y->value); + BOOST_CONTRACT_ASSERT(s.value == old_s->value); + }) + ; + + out << "c::f::body" << std::endl; + if(s.value == "X") throw except_error(); + std::string save_s = s.value; + + std::string save = y.value; + y.value += save_s; + s.value = save; + + save = t<'d'>::z.value; + t<'d'>::z.value += save_s; + s.value += save; + + save = t<'e'>::z.value; + t<'e'>::z.value += save_s; + s.value += save; + + result.value = save_s; + return result; + } + BOOST_CONTRACT_OVERRIDE(f) +}; + +// Test no subcontracting from not (fully) contracted base. +struct b { + static void static_invariant() { out << "b::static_inv" << std::endl; } + void invariant() const { out << "b::inv" << std::endl; } + + virtual ~b() {} + + // No contract (no virtual_ so this is not actually overridden by a::f). + virtual result_type& f(s_type& s) { + static result_type result("none-b"); + out << "b::f::body" << std::endl; + result.value = s.value; + return result; + } +}; + +// Test public function 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 + + static void static_invariant() { out << "a::static_inv" << std::endl; } + + void invariant() const { + out << "a::inv" << std::endl; + BOOST_CONTRACT_ASSERT(x.value != ""); + } + + struct x_tag; + typedef boost::contract::test::detail::counter<x_tag, std::string> x_type; + x_type x; + + a() { x.value = "a"; } + + #if defined(BOOST_GCC) + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored "-Woverloaded-virtual" // For a::f. + #elif defined(BOOST_CLANG) + #pragma clang diagnostic push + #pragma clang diagnostic ignored "-Woverloaded-virtual" // For a::f. + #endif + + // Must use virtual_ even if no longer decl virtual for correct overloading. + // NOTE: This intentionally hides but does not override `b::f` (it overrides + // `c::f` instead). This generates warnings on some compilers (Clang, etc.). + result_type& f(s_type& s, boost::contract::virtual_* v = 0) + /* override */ { + static result_type result("none-a"); + boost::contract::old_ptr<x_type> old_x = + BOOST_CONTRACT_OLDOF(v, x_type::eval(x)); + boost::contract::old_ptr<s_type> old_s; + boost::contract::check c = boost::contract::public_function< + override_f>(v, result, &a::f, this, s) + .precondition([&] { + out << "a::f::pre" << std::endl; + BOOST_CONTRACT_ASSERT(s.value == "A" || s.value == "X"); + }) + .old([&] { + out << "a::f::old" << std::endl; + old_s = BOOST_CONTRACT_OLDOF(v, s_type::eval(s)); + }) + .postcondition([&] (result_type const& result) { + out << "a::f::post" << std::endl; + BOOST_CONTRACT_ASSERT(x.value == old_x->value + old_s->value); + BOOST_CONTRACT_ASSERT(s.value.find(old_x->value) != + std::string::npos); + BOOST_CONTRACT_ASSERT(result.value == old_s->value); + }) + .except([&] { + out << "a::f::except" << std::endl; + BOOST_CONTRACT_ASSERT(x.value == old_x->value); + BOOST_CONTRACT_ASSERT(s.value == old_s->value); + }) + ; + + out << "a::f::body" << std::endl; + if(s.value == "X") throw except_error(); + std::string save_s = s.value; + + std::string save = x.value; + x.value += save_s; + s.value = save; + + save = y.value; + y.value += save_s; + s.value += save; + + save = t<'d'>::z.value; + t<'d'>::z.value += save_s; + s.value += save; + + save = t<'e'>::z.value; + t<'e'>::z.value += save_s; + s.value += save; + + result.value = save_s; + return result; + } + BOOST_CONTRACT_OVERRIDE(f) + + #if defined(BOOST_GCC) + #pragma GCC diagnostic pop + #elif defined(BOOST_CLANG) + #pragma clang diagnostic pop + #endif +}; + +#endif // #include guard + diff --git a/src/boost/libs/contract/test/public_function/static.cpp b/src/boost/libs/contract/test/public_function/static.cpp new file mode 100644 index 000000000..010c965f0 --- /dev/null +++ b/src/boost/libs/contract/test/public_function/static.cpp @@ -0,0 +1,82 @@ + +// Copyright (C) 2008-2018 Lorenzo Caminiti +// Distributed under the Boost Software License, Version 1.0 (see accompanying +// file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt). +// See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html + +// Test public static member function contracts. + +#include "../detail/oteststream.hpp" +#include <boost/contract/base_types.hpp> +#include <boost/contract/public_function.hpp> +#include <boost/contract/check.hpp> +#include <boost/detail/lightweight_test.hpp> +#include <sstream> + +boost::contract::test::detail::oteststream out; + +struct b { + static void static_invariant() { out << "b::static_inv" << std::endl; } + void invariant() const { out << "b::inv" << std::endl; } + + static void f() { + boost::contract::check c = boost::contract::public_function<b>() + .precondition([] { out << "b::f::pre" << std::endl; }) + .old([] { out << "b::f::old" << std::endl; }) + .postcondition([] { out << "b::f::post" << std::endl; }) + ; + out << "b::f::body" << std::endl; + } +}; + +struct a + #define BASES public b + : BASES +{ + typedef BOOST_CONTRACT_BASE_TYPES(BASES) base_types; + #undef BASES + + static void static_invariant() { out << "a::static_inv" << std::endl; } + void invariant() const { out << "a::inv" << std::endl; } + + static void f() { + boost::contract::check c = boost::contract::public_function<a>() + .precondition([] { out << "a::f::pre" << std::endl; }) + .old([] { out << "a::f::old" << std::endl; }) + .postcondition([] { out << "a::f::post" << std::endl; }) + ; + out << "a::f::body" << std::endl; + } +}; + +int main() { + std::ostringstream ok; + + out.str(""); + a::f(); + ok.str(""); ok + // Static so no object thus only static inv, plus never virtual so subst + // principle does not apply and no subcontracting. + #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS + << "a::static_inv" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_PRECONDITIONS + << "a::f::pre" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_OLDS + << "a::f::old" << std::endl + #endif + << "a::f::body" << std::endl + #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS + << "a::static_inv" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS + // No old call here because not base object. + << "a::f::post" << std::endl + #endif + ; + BOOST_TEST(out.eq(ok.str())); + + return boost::report_errors(); +} + diff --git a/src/boost/libs/contract/test/public_function/static_ifdef.cpp b/src/boost/libs/contract/test/public_function/static_ifdef.cpp new file mode 100644 index 000000000..032129504 --- /dev/null +++ b/src/boost/libs/contract/test/public_function/static_ifdef.cpp @@ -0,0 +1,74 @@ + +// Copyright (C) 2008-2018 Lorenzo Caminiti +// Distributed under the Boost Software License, Version 1.0 (see accompanying +// file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt). +// See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html + +// Test public static member function contract compilation on/off. + +#include "../detail/oteststream.hpp" +#include <boost/contract/core/config.hpp> +#ifndef BOOST_CONTRACT_NO_PUBLIC_FUNCTIONS + #include <boost/contract/public_function.hpp> + #include <boost/contract/check.hpp> + #include <boost/contract/old.hpp> +#endif +#include <boost/detail/lightweight_test.hpp> +#include <sstream> + +boost::contract::test::detail::oteststream out; + +struct a { + #ifndef BOOST_CONTRACT_NO_INVARIANTS + static void static_invariant() { out << "a::static_inv" << std::endl; } + void invariant() const { out << "a::inv" << std::endl; } + #endif + + static void f(int x) { + #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS + boost::contract::old_ptr<int> old_x = BOOST_CONTRACT_OLDOF(x); + #endif + #ifndef BOOST_CONTRACT_NO_PUBLIC_FUNCTIONS + boost::contract::check c = boost::contract::public_function<a>() + #ifndef BOOST_CONTRACT_NO_PRECONDITIONS + .precondition([] { out << "a::f::pre" << std::endl; }) + #endif + #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS + .old([] { out << "a::f::old" << std::endl; }) + .postcondition([] { out << "a::f::post" << std::endl; }) + #endif + ; + #endif + out << "a::f::body" << std::endl; + } +}; + +int main() { + std::ostringstream ok; + + out.str(""); + a::f(123); + ok.str(""); ok + #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS + << "a::static_inv" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_PRECONDITIONS + << "a::f::pre" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS + << "a::f::old" << std::endl + #endif + << "a::f::body" << std::endl + // Test no post (but still static inv) because body threw. + #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS + << "a::static_inv" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS + << "a::f::post" << std::endl + #endif + ; + BOOST_TEST(out.eq(ok.str())); + + return boost::report_errors(); +} + diff --git a/src/boost/libs/contract/test/public_function/static_ifdef_macro.cpp b/src/boost/libs/contract/test/public_function/static_ifdef_macro.cpp new file mode 100644 index 000000000..9f03cf215 --- /dev/null +++ b/src/boost/libs/contract/test/public_function/static_ifdef_macro.cpp @@ -0,0 +1,90 @@ + +// Copyright (C) 2008-2018 Lorenzo Caminiti +// Distributed under the Boost Software License, Version 1.0 (see accompanying +// file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt). +// See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html + +// Test public static member function contract compilation on/off (w/ macros). + +#include "../detail/oteststream.hpp" +#include "../detail/unprotected_commas.hpp" +#include <boost/contract/core/config.hpp> +#include <boost/contract_macro.hpp> +#include <boost/detail/lightweight_test.hpp> +#include <sstream> + +boost::contract::test::detail::oteststream out; + +struct a { + BOOST_CONTRACT_STATIC_INVARIANT({ + boost::contract::test::detail::unprotected_commas<void, void, void>:: + call(); + out << "a::static_inv" << std::endl; + }) + + BOOST_CONTRACT_INVARIANT({ + boost::contract::test::detail::unprotected_commas<void, void, void>:: + call(); + out << "a::inv" << std::endl; + }) + + static void f(int x) { + BOOST_CONTRACT_OLD_PTR( + boost::contract::test::detail::unprotected_commas<int, void, void>:: + type1 + )( + old_x, + (boost::contract::test::detail::unprotected_commas<void, void, + void>::same(x)) + ); + BOOST_CONTRACT_STATIC_PUBLIC_FUNCTION(boost::contract::test::detail:: + unprotected_commas<a, void, void>::type1) + BOOST_CONTRACT_PRECONDITION([] { + boost::contract::test::detail::unprotected_commas< + void, void, void>::call(); + out << "a::f::pre" << std::endl; + }) + BOOST_CONTRACT_OLD([] { + boost::contract::test::detail::unprotected_commas< + void, void, void>::call(); + out << "a::f::old" << std::endl; + }) + BOOST_CONTRACT_POSTCONDITION([] { + boost::contract::test::detail::unprotected_commas< + void, void, void>::call(); + out << "a::f::post" << std::endl; + }) + ; + out << "a::f::body" << std::endl; + } +}; + +int main() { + std::ostringstream ok; + + out.str(""); + a::f(123); + ok.str(""); ok + #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS + << "a::static_inv" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_PRECONDITIONS + << "a::f::pre" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_OLDS + << "a::f::old" << std::endl + #endif + << "a::f::body" << std::endl + // Test no post (but still static inv) because body threw. + #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS + << "a::static_inv" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS + << "a::f::post" << std::endl + #endif + ; + BOOST_TEST(out.eq(ok.str())); + + return boost::report_errors(); +} + diff --git a/src/boost/libs/contract/test/public_function/static_throwing_body.cpp b/src/boost/libs/contract/test/public_function/static_throwing_body.cpp new file mode 100644 index 000000000..37c0354f6 --- /dev/null +++ b/src/boost/libs/contract/test/public_function/static_throwing_body.cpp @@ -0,0 +1,67 @@ + +// Copyright (C) 2008-2018 Lorenzo Caminiti +// Distributed under the Boost Software License, Version 1.0 (see accompanying +// file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt). +// See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html + +// Test public static member function throwing. + +#include "../detail/oteststream.hpp" +#include <boost/contract/public_function.hpp> +#include <boost/contract/check.hpp> +#include <boost/detail/lightweight_test.hpp> +#include <sstream> + +boost::contract::test::detail::oteststream out; + +struct a_err {}; // Global decl so visible in MSVC10 lambdas. + +struct a { + static void static_invariant() { out << "a::static_inv" << std::endl; } + void invariant() const { out << "a::inv" << std::endl; } + + static void f() { + boost::contract::check c = boost::contract::public_function<a>() + .precondition([] { out << "a::f::pre" << std::endl; }) + .old([] { out << "a::f::old" << std::endl; }) + .postcondition([] { out << "a::f::post" << std::endl; }) + .except([] { out << "a::f::except" << std::endl; }) + ; + out << "a::f::body" << std::endl; + throw a_err(); // Test this throws. + } +}; + +int main() { + std::ostringstream ok; + + try { + out.str(""); + a::f(); + BOOST_TEST(false); + } catch(a_err const&) { + ok.str(""); ok + #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS + << "a::static_inv" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_PRECONDITIONS + << "a::f::pre" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_OLDS + << "a::f::old" << std::endl + #endif + << "a::f::body" << std::endl // Test this threw. + // Test no post (but still static inv) because body threw. + #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS + << "a::static_inv" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_EXCEPTS + << "a::f::except" << std::endl + #endif + ; + BOOST_TEST(out.eq(ok.str())); + } catch(...) { BOOST_TEST(false); } + + return boost::report_errors(); +} + diff --git a/src/boost/libs/contract/test/public_function/static_throwing_old.cpp b/src/boost/libs/contract/test/public_function/static_throwing_old.cpp new file mode 100644 index 000000000..04e963596 --- /dev/null +++ b/src/boost/libs/contract/test/public_function/static_throwing_old.cpp @@ -0,0 +1,71 @@ + +// Copyright (C) 2008-2018 Lorenzo Caminiti +// Distributed under the Boost Software License, Version 1.0 (see accompanying +// file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt). +// See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html + +// Test throw from public static member function .old(). + +#include "../detail/oteststream.hpp" +#include <boost/contract/public_function.hpp> +#include <boost/contract/check.hpp> +#include <boost/detail/lightweight_test.hpp> +#include <sstream> + +boost::contract::test::detail::oteststream out; + +struct a_err {}; // Global decl so visible in MSVC10 lambdas. + +struct a { + static void static_invariant() { out << "a::static_inv" << std::endl; } + void invariant() const { out << "a::inv" << std::endl; } + + static void f() { + boost::contract::check c = boost::contract::public_function<a>() + .precondition([] { out << "a::f::pre" << std::endl; }) + .old([] { + out << "a::f::old" << std::endl; + throw a_err(); // Test this throws. + }) + .postcondition([] { out << "a::f::post" << std::endl; }) + .except([] { out << "a::f::except" << std::endl; }) + ; + out << "a::f::body" << std::endl; + } +}; + +int main() { + std::ostringstream ok; + + boost::contract::set_old_failure([] (boost::contract::from) { throw; }); + + try { + out.str(""); + a::f(); + #ifndef BOOST_CONTRACT_NO_OLDS + BOOST_TEST(false); + } catch(a_err const&) { + #endif + ok.str(""); ok + #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS + << "a::static_inv" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_PRECONDITIONS + << "a::f::pre" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_OLDS + << "a::f::old" << std::endl // Test this threw. + #else + << "a::f::body" << std::endl + // Test no post (but still static inv) because .old() threw. + #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS + << "a::static_inv" << std::endl + #endif + #endif + ; + BOOST_TEST(out.eq(ok.str())); + } catch(...) { BOOST_TEST(false); } + + return boost::report_errors(); +} + diff --git a/src/boost/libs/contract/test/public_function/static_throwing_post.cpp b/src/boost/libs/contract/test/public_function/static_throwing_post.cpp new file mode 100644 index 000000000..b8414f8af --- /dev/null +++ b/src/boost/libs/contract/test/public_function/static_throwing_post.cpp @@ -0,0 +1,73 @@ + +// Copyright (C) 2008-2018 Lorenzo Caminiti +// Distributed under the Boost Software License, Version 1.0 (see accompanying +// file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt). +// See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html + +// Test throw from public static member function .post(). + +#include "../detail/oteststream.hpp" +#include <boost/contract/public_function.hpp> +#include <boost/contract/check.hpp> +#include <boost/detail/lightweight_test.hpp> +#include <sstream> + +boost::contract::test::detail::oteststream out; + +struct a_err {}; // Global decl so visible in MSVC10 lambdas. + +struct a { + static void static_invariant() { out << "a::static_inv" << std::endl; } + void invariant() const { out << "a::inv" << std::endl; } + + static void f() { + boost::contract::check c = boost::contract::public_function<a>() + .precondition([] { out << "a::f::pre" << std::endl; }) + .old([] { out << "a::f::old" << std::endl; }) + .postcondition([] { + out << "a::f::post" << std::endl; + throw a_err(); // Test this throws. + }) + .except([] { out << "a::f::except" << std::endl; }) + ; + out << "a::f::body" << std::endl; + } +}; + +int main() { + std::ostringstream ok; + + boost::contract::set_postcondition_failure( + [] (boost::contract::from) { throw; }); + + try { + out.str(""); + a::f(); + #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS + BOOST_TEST(false); + } catch(a_err const&) { + #endif + ok.str(""); ok + #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS + << "a::static_inv" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_PRECONDITIONS + << "a::f::pre" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_OLDS + << "a::f::old" << std::endl + #endif + << "a::f::body" << std::endl + #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS + << "a::static_inv" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS + << "a::f::post" << std::endl // Test this threw. + #endif + ; + BOOST_TEST(out.eq(ok.str())); + } catch(...) { BOOST_TEST(false); } + + return boost::report_errors(); +} + diff --git a/src/boost/libs/contract/test/public_function/static_throwing_pre.cpp b/src/boost/libs/contract/test/public_function/static_throwing_pre.cpp new file mode 100644 index 000000000..79c38af01 --- /dev/null +++ b/src/boost/libs/contract/test/public_function/static_throwing_pre.cpp @@ -0,0 +1,74 @@ + +// Copyright (C) 2008-2018 Lorenzo Caminiti +// Distributed under the Boost Software License, Version 1.0 (see accompanying +// file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt). +// See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html + +// Test throw from public static member function .pre(). + +#include "../detail/oteststream.hpp" +#include <boost/contract/public_function.hpp> +#include <boost/contract/check.hpp> +#include <boost/detail/lightweight_test.hpp> +#include <sstream> + +boost::contract::test::detail::oteststream out; + +struct a_err {}; // Global decl so visible in MSVC10 lambdas. + +struct a { + static void static_invariant() { out << "a::static_inv" << std::endl; } + void invariant() const { out << "a::inv" << std::endl; } + + static void f() { + boost::contract::check c = boost::contract::public_function<a>() + .precondition([] { + out << "a::f::pre" << std::endl; + throw a_err(); // Test this throws. + }) + .old([] { out << "a::f::old" << std::endl; }) + .postcondition([] { out << "a::f::post" << std::endl; }) + .except([] { out << "a::f::except" << std::endl; }) + ; + out << "a::f::body" << std::endl; + } +}; + +int main() { + std::ostringstream ok; + + boost::contract::set_precondition_failure( + [] (boost::contract::from) { throw; }); + + try { + out.str(""); + a::f(); + #ifndef BOOST_CONTRACT_NO_PRECONDITIONS + BOOST_TEST(false); + } catch(a_err const&) { + #endif + ok.str(""); ok + #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS + << "a::static_inv" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_PRECONDITIONS + << "a::f::pre" << std::endl // Test this threw. + #else + #ifndef BOOST_CONTRACT_NO_OLDS + << "a::f::old" << std::endl + #endif + << "a::f::body" << std::endl + #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS + << "a::static_inv" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS + << "a::f::post" << std::endl + #endif + #endif + ; + BOOST_TEST(out.eq(ok.str())); + } catch(...) { BOOST_TEST(false); } + + return boost::report_errors(); +} + diff --git a/src/boost/libs/contract/test/public_function/throwing_body.cpp b/src/boost/libs/contract/test/public_function/throwing_body.cpp new file mode 100644 index 000000000..40684a5a5 --- /dev/null +++ b/src/boost/libs/contract/test/public_function/throwing_body.cpp @@ -0,0 +1,106 @@ + +// Copyright (C) 2008-2018 Lorenzo Caminiti +// Distributed under the Boost Software License, Version 1.0 (see accompanying +// file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt). +// See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html + +// Test public member function body throws with subcontracting. + +#include "smoke.hpp" +#include <boost/optional.hpp> +#include <boost/preprocessor/control/iif.hpp> +#include <boost/detail/lightweight_test.hpp> +#include <sstream> + +int main() { + std::ostringstream ok; + + a aa; // Test call to derived out-most leaf. + s_type s; s.value = "X"; // So body will throw. + out.str(""); + boost::optional<result_type&> r; + try { + r = aa.f(s); + BOOST_TEST(false); + } catch(except_error const&) { + ok.str(""); ok + #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS + << "d::static_inv" << std::endl + << "d::inv" << std::endl + << "e::static_inv" << std::endl + << "e::inv" << std::endl + << "c::static_inv" << std::endl + << "c::inv" << std::endl + << "a::static_inv" << std::endl + << "a::inv" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_PRECONDITIONS + << "d::f::pre" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_OLDS + << "d::f::old" << std::endl + << "e::f::old" << std::endl + << "c::f::old" << std::endl + << "a::f::old" << std::endl + #endif + << "a::f::body" << std::endl + #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS + << "d::static_inv" << std::endl + << "d::inv" << std::endl + << "e::static_inv" << std::endl + << "e::inv" << std::endl + << "c::static_inv" << std::endl + << "c::inv" << std::endl + << "a::static_inv" << std::endl + << "a::inv" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_EXCEPTS + << "d::f::old" << std::endl + << "d::f::except" << std::endl + << "e::f::old" << std::endl + << "e::f::except" << std::endl + << "c::f::old" << std::endl + << "c::f::except" << std::endl + // No old call here because not a base object. + << "a::f::except" << std::endl + #endif + ; + BOOST_TEST(out.eq(ok.str())); + + #ifndef BOOST_CONTRACT_NO_OLDS + #define BOOST_CONTRACT_TEST_old 1u + #else + #define BOOST_CONTRACT_TEST_old 0u + #endif + + BOOST_TEST(!r); // Boost.Optional result not init (as body threw). + BOOST_TEST_EQ(s.value, "X"); + BOOST_TEST_EQ(s.copies(), BOOST_CONTRACT_TEST_old * 4); + BOOST_TEST_EQ(s.evals(), BOOST_CONTRACT_TEST_old * 4); + BOOST_TEST_EQ(s.ctors(), s.dtors() + 1); // 1 for local var. + + BOOST_TEST_EQ(aa.x.value, "a"); + BOOST_TEST_EQ(aa.x.copies(), BOOST_CONTRACT_TEST_old); + BOOST_TEST_EQ(aa.x.evals(), BOOST_CONTRACT_TEST_old); + BOOST_TEST_EQ(aa.x.ctors(), aa.x.dtors() + 1); // 1 for member var. + + BOOST_TEST_EQ(aa.y.value, "c"); + BOOST_TEST_EQ(aa.y.copies(), BOOST_CONTRACT_TEST_old); + BOOST_TEST_EQ(aa.y.evals(), BOOST_CONTRACT_TEST_old); + BOOST_TEST_EQ(aa.y.ctors(), aa.y.dtors() + 1); // 1 for member var. + + BOOST_TEST_EQ(aa.t<'d'>::z.value, "d"); + BOOST_TEST_EQ(aa.t<'d'>::z.copies(), BOOST_CONTRACT_TEST_old); + BOOST_TEST_EQ(aa.t<'d'>::z.evals(), BOOST_CONTRACT_TEST_old); + BOOST_TEST_EQ(aa.t<'d'>::z.ctors(), aa.t<'d'>::z.dtors() + 1); // 1 mem. + + BOOST_TEST_EQ(aa.t<'e'>::z.value, "e"); + BOOST_TEST_EQ(aa.t<'e'>::z.copies(), BOOST_CONTRACT_TEST_old); + BOOST_TEST_EQ(aa.t<'e'>::z.evals(), BOOST_CONTRACT_TEST_old); + BOOST_TEST_EQ(aa.t<'e'>::z.ctors(), aa.t<'e'>::z.dtors() + 1); // 1 mem. + + #undef BOOST_CONTRACT_TEST_old + } + return boost::report_errors(); +} + diff --git a/src/boost/libs/contract/test/public_function/throwing_body_virtual.cpp b/src/boost/libs/contract/test/public_function/throwing_body_virtual.cpp new file mode 100644 index 000000000..57d9acdd7 --- /dev/null +++ b/src/boost/libs/contract/test/public_function/throwing_body_virtual.cpp @@ -0,0 +1,108 @@ + +// Copyright (C) 2008-2018 Lorenzo Caminiti +// Distributed under the Boost Software License, Version 1.0 (see accompanying +// file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt). +// See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html + +// Test virtual public member function body throws with subcontracting. + +#include "smoke.hpp" +#include <boost/optional.hpp> +#include <boost/preprocessor/control/iif.hpp> +#include <boost/detail/lightweight_test.hpp> +#include <sstream> + +int main() { + std::ostringstream ok; + + a aa; // Test call to derived out-most leaf. + c& ca = aa; // Test polymorphic virtual call (via reference to base c). + s_type s; s.value = "X"; // So body will throw. + out.str(""); + boost::optional<result_type&> r; + try { + r = ca.f(s); + BOOST_TEST(false); + } catch(except_error const&) { + ok.str(""); ok + #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS + << "d::static_inv" << std::endl + << "d::inv" << std::endl + << "e::static_inv" << std::endl + << "e::inv" << std::endl + << "c::static_inv" << std::endl + << "c::inv" << std::endl + << "a::static_inv" << std::endl + << "a::inv" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_PRECONDITIONS + << "d::f::pre" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_OLDS + << "d::f::old" << std::endl + << "e::f::old" << std::endl + << "c::f::old" << std::endl + << "a::f::old" << std::endl + #endif + << "a::f::body" << std::endl + #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS + << "d::static_inv" << std::endl + << "d::inv" << std::endl + << "e::static_inv" << std::endl + << "e::inv" << std::endl + << "c::static_inv" << std::endl + << "c::inv" << std::endl + << "a::static_inv" << std::endl + << "a::inv" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_EXCEPTS + << "d::f::old" << std::endl + << "d::f::except" << std::endl + << "e::f::old" << std::endl + << "e::f::except" << std::endl + << "c::f::old" << std::endl + << "c::f::except" << std::endl + // No old call here because not a base object. + << "a::f::except" << std::endl + #endif + ; + BOOST_TEST(out.eq(ok.str())); + + #ifndef BOOST_CONTRACT_NO_OLDS + #define BOOST_CONTRACT_TEST_old 1u + #else + #define BOOST_CONTRACT_TEST_old 0u + #endif + + BOOST_TEST(!r); // Boost.Optional result not init (as body threw). + BOOST_TEST_EQ(s.value, "X"); + BOOST_TEST_EQ(s.copies(), BOOST_CONTRACT_TEST_old * 4); + BOOST_TEST_EQ(s.evals(), BOOST_CONTRACT_TEST_old * 4); + BOOST_TEST_EQ(s.ctors(), s.dtors() + 1); // 1 for local var. + + // Cannot access x via ca, but only via aa. + BOOST_TEST_EQ(aa.x.value, "a"); + BOOST_TEST_EQ(aa.x.copies(), BOOST_CONTRACT_TEST_old); + BOOST_TEST_EQ(aa.x.evals(), BOOST_CONTRACT_TEST_old); + BOOST_TEST_EQ(aa.x.ctors(), aa.x.dtors() + 1); // 1 for member var. + + BOOST_TEST_EQ(ca.y.value, "c"); + BOOST_TEST_EQ(ca.y.copies(), BOOST_CONTRACT_TEST_old); + BOOST_TEST_EQ(ca.y.evals(), BOOST_CONTRACT_TEST_old); + BOOST_TEST_EQ(ca.y.ctors(), aa.y.dtors() + 1); // 1 for member var. + + BOOST_TEST_EQ(ca.t<'d'>::z.value, "d"); + BOOST_TEST_EQ(ca.t<'d'>::z.copies(), BOOST_CONTRACT_TEST_old); + BOOST_TEST_EQ(ca.t<'d'>::z.evals(), BOOST_CONTRACT_TEST_old); + BOOST_TEST_EQ(ca.t<'d'>::z.ctors(), aa.t<'d'>::z.dtors() + 1); // 1 mem. + + BOOST_TEST_EQ(ca.t<'e'>::z.value, "e"); + BOOST_TEST_EQ(ca.t<'e'>::z.copies(), BOOST_CONTRACT_TEST_old); + BOOST_TEST_EQ(ca.t<'e'>::z.evals(), BOOST_CONTRACT_TEST_old); + BOOST_TEST_EQ(ca.t<'e'>::z.ctors(), aa.t<'e'>::z.dtors() + 1); // 1 mem. + + #undef BOOST_CONTRACT_TEST_old + } + return boost::report_errors(); +} + diff --git a/src/boost/libs/contract/test/public_function/throwing_body_virtual_branch.cpp b/src/boost/libs/contract/test/public_function/throwing_body_virtual_branch.cpp new file mode 100644 index 000000000..dccc18d32 --- /dev/null +++ b/src/boost/libs/contract/test/public_function/throwing_body_virtual_branch.cpp @@ -0,0 +1,94 @@ + +// Copyright (C) 2008-2018 Lorenzo Caminiti +// Distributed under the Boost Software License, Version 1.0 (see accompanying +// file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt). +// See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html + +// Test virt pub func body throws with subcontr from middle of inheritance tree. + +#include "smoke.hpp" +#include <boost/optional.hpp> +#include <boost/preprocessor/control/iif.hpp> +#include <boost/detail/lightweight_test.hpp> +#include <sstream> + +int main() { + std::ostringstream ok; + + c cc; // Test call to class at mid- inheritance tree (as base with bases). + s_type s; s.value = "X"; // So body will throw. + out.str(""); + boost::optional<result_type&> r; + try { + r = cc.f(s); + BOOST_TEST(false); + } catch(except_error const&) { + ok.str(""); ok + #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS + << "d::static_inv" << std::endl + << "d::inv" << std::endl + << "e::static_inv" << std::endl + << "e::inv" << std::endl + << "c::static_inv" << std::endl + << "c::inv" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_PRECONDITIONS + << "d::f::pre" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_OLDS + << "d::f::old" << std::endl + << "e::f::old" << std::endl + << "c::f::old" << std::endl + #endif + << "c::f::body" << std::endl + #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS + << "d::static_inv" << std::endl + << "d::inv" << std::endl + << "e::static_inv" << std::endl + << "e::inv" << std::endl + << "c::static_inv" << std::endl + << "c::inv" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_EXCEPTS + << "d::f::old" << std::endl + << "d::f::except" << std::endl + << "e::f::old" << std::endl + << "e::f::except" << std::endl + // No old call here because not a base object. + << "c::f::except" << std::endl + #endif + ; + BOOST_TEST(out.eq(ok.str())); + + #ifndef BOOST_CONTRACT_NO_OLDS + #define BOOST_CONTRACT_TEST_old 1u + #else + #define BOOST_CONTRACT_TEST_old 0u + #endif + + BOOST_TEST(!r); // Boost.Optional result not init (as body threw). + BOOST_TEST_EQ(s.value, "X"); + BOOST_TEST_EQ(s.copies(), BOOST_CONTRACT_TEST_old * 3); + BOOST_TEST_EQ(s.evals(), BOOST_CONTRACT_TEST_old * 3); + BOOST_TEST_EQ(s.ctors(), s.dtors() + 1); // 1 for local var. + + BOOST_TEST_EQ(cc.y.value, "c"); + BOOST_TEST_EQ(cc.y.copies(), BOOST_CONTRACT_TEST_old); + BOOST_TEST_EQ(cc.y.evals(), BOOST_CONTRACT_TEST_old); + BOOST_TEST_EQ(cc.y.ctors(), cc.y.dtors() + 1); // 1 for member var. + + BOOST_TEST_EQ(cc.t<'d'>::z.value, "d"); + BOOST_TEST_EQ(cc.t<'d'>::z.copies(), BOOST_CONTRACT_TEST_old); + BOOST_TEST_EQ(cc.t<'d'>::z.evals(), BOOST_CONTRACT_TEST_old); + BOOST_TEST_EQ(cc.t<'d'>::z.ctors(), cc.t<'d'>::z.dtors() + 1); // 1 mem. + + BOOST_TEST_EQ(cc.t<'e'>::z.value, "e"); + BOOST_TEST_EQ(cc.t<'e'>::z.copies(), BOOST_CONTRACT_TEST_old); + BOOST_TEST_EQ(cc.t<'e'>::z.evals(), BOOST_CONTRACT_TEST_old); + BOOST_TEST_EQ(cc.t<'e'>::z.ctors(), cc.t<'e'>::z.dtors() + 1); // 1 mem. + + #undef BOOST_CONTRACT_TEST_old + } + return boost::report_errors(); +} + diff --git a/src/boost/libs/contract/test/public_function/throwing_old.cpp b/src/boost/libs/contract/test/public_function/throwing_old.cpp new file mode 100644 index 000000000..aec127fa0 --- /dev/null +++ b/src/boost/libs/contract/test/public_function/throwing_old.cpp @@ -0,0 +1,149 @@ + +// Copyright (C) 2008-2018 Lorenzo Caminiti +// Distributed under the Boost Software License, Version 1.0 (see accompanying +// file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt). +// See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html + +// Test throw from public function (derived and bases) .old(). + +#include "../detail/oteststream.hpp" +#include <boost/contract/public_function.hpp> +#include <boost/contract/assert.hpp> +#include <boost/contract/base_types.hpp> +#include <boost/contract/override.hpp> +#include <boost/contract/check.hpp> +#include <boost/detail/lightweight_test.hpp> +#include <sstream> + +boost::contract::test::detail::oteststream out; + +struct c_err {}; // Global decl so visible in MSVC10 lambdas. + +struct c { + static void static_invariant() { out << "c::static_inv" << std::endl; } + void invariant() const { out << "c::inv" << std::endl; } + + virtual void f(boost::contract::virtual_* v = 0) { + boost::contract::check c = boost::contract::public_function(v, this) + .precondition([] { + out << "c::f::pre" << std::endl; + BOOST_CONTRACT_ASSERT(false); // To check derived pre. + }) + .old([] { + out << "c::f::old" << std::endl; + throw c_err(); // Test this throws. + }) + .postcondition([] { out << "c::f::post" << std::endl; }) + .except([] { out << "c::f::except" << std::endl; }) + ; + out << "c::f::body" << std::endl; + } +}; + +struct b_err {}; // Global decl so visible in MSVC10 lambdas. + +struct b + #define BASES public c + : BASES +{ + typedef BOOST_CONTRACT_BASE_TYPES(BASES) base_types; + #undef BASES + + static void static_invariant() { out << "b::static_inv" << std::endl; } + void invariant() const { out << "b::inv" << std::endl; } + + virtual void f(boost::contract::virtual_* v = 0) /* override */ { + boost::contract::check c = boost::contract::public_function<override_f>( + v, &b::f, this) + .precondition([] { + out << "b::f::pre" << std::endl; + BOOST_CONTRACT_ASSERT(false); // To check derived pre. + }) + .old([] { + out << "b::f::old" << std::endl; + throw b_err(); // Test this throws. + }) + .postcondition([] { out << "b::f::post" << std::endl; }) + .except([] { out << "b::f::except" << std::endl; }) + ; + out << "b::f::body" << std::endl; + } + BOOST_CONTRACT_OVERRIDE(f) +}; + +struct a_err {}; // Global decl so visible in MSVC10 lambdas. + +struct a + #define BASES public b + : BASES +{ + typedef BOOST_CONTRACT_BASE_TYPES(BASES) base_types; + #undef BASES + + static void static_invariant() { out << "a::static_inv" << std::endl; } + void invariant() const { out << "a::inv" << std::endl; } + + void f(boost::contract::virtual_* v = 0) /* override */ { + boost::contract::check c = boost::contract::public_function<override_f>( + v, &a::f, this) + .precondition([] { out << "a::f::pre" << std::endl; }) + .old([] { + out << "a::f::old" << std::endl; + throw a_err(); // Test this throws. + }) + .postcondition([] { out << "a::f::post" << std::endl; }) + .except([] { out << "a::f::except" << std::endl; }) + ; + out << "a::f::body" << std::endl; + } + BOOST_CONTRACT_OVERRIDE(f) +}; + +int main() { + std::ostringstream ok; + + boost::contract::set_old_failure([] (boost::contract::from) { throw; }); + + a aa; + b& ba = aa; // Test as virtual call via polymorphism. + try { + out.str(""); + ba.f(); + #ifndef BOOST_CONTRACT_NO_OLDS + BOOST_TEST(false); + } catch(c_err const&) { + #endif + ok.str(""); ok + #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS + << "c::static_inv" << std::endl + << "c::inv" << std::endl + << "b::static_inv" << std::endl + << "b::inv" << std::endl + << "a::static_inv" << std::endl + << "a::inv" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_PRECONDITIONS + << "c::f::pre" << std::endl + << "b::f::pre" << std::endl + << "a::f::pre" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_OLDS + << "c::f::old" << std::endl // Test this threw. + #else + << "a::f::body" << std::endl + #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS + << "c::static_inv" << std::endl + << "c::inv" << std::endl + << "b::static_inv" << std::endl + << "b::inv" << std::endl + << "a::static_inv" << std::endl + << "a::inv" << std::endl + #endif + #endif + ; + BOOST_TEST(out.eq(ok.str())); + } catch(...) { BOOST_TEST(false); } + + return boost::report_errors(); +} + diff --git a/src/boost/libs/contract/test/public_function/throwing_post.cpp b/src/boost/libs/contract/test/public_function/throwing_post.cpp new file mode 100644 index 000000000..038b09547 --- /dev/null +++ b/src/boost/libs/contract/test/public_function/throwing_post.cpp @@ -0,0 +1,157 @@ + +// Copyright (C) 2008-2018 Lorenzo Caminiti +// Distributed under the Boost Software License, Version 1.0 (see accompanying +// file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt). +// See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html + +// Test throw from public function (derived and bases) .post(). + +#include "../detail/oteststream.hpp" +#include <boost/contract/public_function.hpp> +#include <boost/contract/assert.hpp> +#include <boost/contract/base_types.hpp> +#include <boost/contract/override.hpp> +#include <boost/contract/check.hpp> +#include <boost/detail/lightweight_test.hpp> +#include <sstream> + +boost::contract::test::detail::oteststream out; + +struct c_err {}; // Global decl so visible in MSVC10 lambdas. + +struct c { + static void static_invariant() { out << "c::static_inv" << std::endl; } + void invariant() const { out << "c::inv" << std::endl; } + + virtual void f(boost::contract::virtual_* v = 0) { + boost::contract::check c = boost::contract::public_function(v, this) + .precondition([] { + out << "c::f::pre" << std::endl; + BOOST_CONTRACT_ASSERT(false); // To check derived pre. + }) + .old([] { out << "c::f::old" << std::endl; }) + .postcondition([] { + out << "c::f::post" << std::endl; + // Test derived will throw. + }) + .except([] { out << "c::f::except" << std::endl; }) + ; + out << "c::f::body" << std::endl; + } +}; + +struct b_err {}; // Global decl so visible in MSVC10 lambdas. + +struct b + #define BASES public c + : BASES +{ + typedef BOOST_CONTRACT_BASE_TYPES(BASES) base_types; + #undef BASES + + static void static_invariant() { out << "b::static_inv" << std::endl; } + void invariant() const { out << "b::inv" << std::endl; } + + virtual void f(boost::contract::virtual_* v = 0) /* override */ { + boost::contract::check c = boost::contract::public_function<override_f>( + v, &b::f, this) + .precondition([] { + out << "b::f::pre" << std::endl; + BOOST_CONTRACT_ASSERT(false); // To check derived pre. + }) + .old([] { out << "b::f::old" << std::endl; }) + .postcondition([] { + out << "b::f::post" << std::endl; + throw b_err(); // Test this (both derived and base) throws. + }) + .except([] { out << "b::f::except" << std::endl; }) + ; + out << "b::f::body" << std::endl; + } + BOOST_CONTRACT_OVERRIDE(f) +}; + +struct a_err {}; // Global decl so visible in MSVC10 lambdas. + +struct a + #define BASES public b + : BASES +{ + typedef BOOST_CONTRACT_BASE_TYPES(BASES) base_types; + #undef BASES + + static void static_invariant() { out << "a::static_inv" << std::endl; } + void invariant() const { out << "a::inv" << std::endl; } + + void f(boost::contract::virtual_* v = 0) /* override */ { + boost::contract::check c = boost::contract::public_function<override_f>( + v, &a::f, this) + .precondition([] { out << "a::f::pre" << std::endl; }) + .old([] { out << "a::f::old" << std::endl; }) + .postcondition([] { + out << "a::f::post" << std::endl; + throw a_err(); // Test base already threw. + }) + .except([] { out << "a::f::except" << std::endl; }) + ; + out << "a::f::body" << std::endl; + } + BOOST_CONTRACT_OVERRIDE(f) +}; + +int main() { + std::ostringstream ok; + + boost::contract::set_postcondition_failure( + [] (boost::contract::from) { throw; }); + + a aa; + b& ba = aa; // Test as virtual call via polymorphism. + try { + out.str(""); + ba.f(); + #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS + BOOST_TEST(false); + } catch(b_err const&) { + #endif + ok.str(""); ok + #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS + << "c::static_inv" << std::endl + << "c::inv" << std::endl + << "b::static_inv" << std::endl + << "b::inv" << std::endl + << "a::static_inv" << std::endl + << "a::inv" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_PRECONDITIONS + << "c::f::pre" << std::endl + << "b::f::pre" << std::endl + << "a::f::pre" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_OLDS + << "c::f::old" << std::endl + << "b::f::old" << std::endl + << "a::f::old" << std::endl + #endif + << "a::f::body" << std::endl + #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS + << "c::static_inv" << std::endl + << "c::inv" << std::endl + << "b::static_inv" << std::endl + << "b::inv" << std::endl + << "a::static_inv" << std::endl + << "a::inv" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS + << "c::f::old" << std::endl + << "c::f::post" << std::endl + << "b::f::old" << std::endl + << "b::f::post" << std::endl // Test this threw. + #endif + ; + BOOST_TEST(out.eq(ok.str())); + } catch(...) { BOOST_TEST(false); } + + return boost::report_errors(); +} + diff --git a/src/boost/libs/contract/test/public_function/throwing_pre.cpp b/src/boost/libs/contract/test/public_function/throwing_pre.cpp new file mode 100644 index 000000000..23729121f --- /dev/null +++ b/src/boost/libs/contract/test/public_function/throwing_pre.cpp @@ -0,0 +1,154 @@ + +// Copyright (C) 2008-2018 Lorenzo Caminiti +// Distributed under the Boost Software License, Version 1.0 (see accompanying +// file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt). +// See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html + +// Test throw from public function (derived and bases) .pre(). + +#include "../detail/oteststream.hpp" +#include <boost/contract/public_function.hpp> +#include <boost/contract/assert.hpp> +#include <boost/contract/base_types.hpp> +#include <boost/contract/override.hpp> +#include <boost/contract/check.hpp> +#include <boost/detail/lightweight_test.hpp> +#include <sstream> + +boost::contract::test::detail::oteststream out; + +struct c_err {}; // Global decl so visible in MSVC10 lambdas. + +struct c { + static void static_invariant() { out << "c::static_inv" << std::endl; } + void invariant() const { out << "c::inv" << std::endl; } + + virtual void f(boost::contract::virtual_* v = 0) { + boost::contract::check c = boost::contract::public_function(v, this) + .precondition([] { + out << "c::f::pre" << std::endl; + BOOST_CONTRACT_ASSERT(false); // To check derived pre. + }) + .old([] { out << "c::f::old" << std::endl; }) + .postcondition([] { out << "c::f::post" << std::endl; }) + .except([] { out << "c::f::except" << std::endl; }) + ; + out << "c::f::body" << std::endl; + } +}; + +struct b_err {}; // Global decl so visible in MSVC10 lambdas. + +struct b + #define BASES public c + : BASES +{ + typedef BOOST_CONTRACT_BASE_TYPES(BASES) base_types; + #undef BASES + + static void static_invariant() { out << "b::static_inv" << std::endl; } + void invariant() const { out << "b::inv" << std::endl; } + + virtual void f(boost::contract::virtual_* v = 0) /* override */ { + boost::contract::check c = boost::contract::public_function<override_f>( + v, &b::f, this) + .precondition([] { + out << "b::f::pre" << std::endl; + BOOST_CONTRACT_ASSERT(false); // To check derived pre. + }) + .old([] { out << "b::f::old" << std::endl; }) + .postcondition([] { out << "b::f::post" << std::endl; }) + .except([] { out << "b::f::except" << std::endl; }) + ; + out << "b::f::body" << std::endl; + } + BOOST_CONTRACT_OVERRIDE(f) +}; + +struct a_err {}; // Global decl so visible in MSVC10 lambdas. + +struct a + #define BASES public b + : BASES +{ + typedef BOOST_CONTRACT_BASE_TYPES(BASES) base_types; + #undef BASES + + static void static_invariant() { out << "a::static_inv" << std::endl; } + void invariant() const { out << "a::inv" << std::endl; } + + void f(boost::contract::virtual_* v = 0) /* override */ { + boost::contract::check c = boost::contract::public_function<override_f>( + v, &a::f, this) + .precondition([] { + out << "a::f::pre" << std::endl; + throw a_err(); // Test this throws. + }) + .old([] { out << "a::f::old" << std::endl; }) + .postcondition([] { out << "a::f::post" << std::endl; }) + .except([] { out << "a::f::except" << std::endl; }) + ; + out << "a::f::body" << std::endl; + } + BOOST_CONTRACT_OVERRIDE(f) +}; + +int main() { + std::ostringstream ok; + + boost::contract::set_precondition_failure( + [] (boost::contract::from) { throw; }); + + a aa; + b& ba = aa; // Test as virtual call via polymorphism. + try { + out.str(""); + ba.f(); + #ifndef BOOST_CONTRACT_NO_PRECONDITIONS + BOOST_TEST(false); + } catch(a_err const&) { + #endif + ok.str(""); ok + #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS + << "c::static_inv" << std::endl + << "c::inv" << std::endl + << "b::static_inv" << std::endl + << "b::inv" << std::endl + << "a::static_inv" << std::endl + << "a::inv" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_PRECONDITIONS + << "c::f::pre" << std::endl + << "b::f::pre" << std::endl + << "a::f::pre" << std::endl // Test this threw. + #else + #ifndef BOOST_CONTRACT_NO_OLDS + << "c::f::old" << std::endl + << "b::f::old" << std::endl + << "a::f::old" << std::endl + #endif + << "a::f::body" << std::endl + #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS + << "c::static_inv" << std::endl + << "c::inv" << std::endl + << "b::static_inv" << std::endl + << "b::inv" << std::endl + << "a::static_inv" << std::endl + << "a::inv" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS + << "c::f::old" << std::endl + << "c::f::post" << std::endl + << "b::f::old" << std::endl + << "b::f::post" << std::endl + // No old call here because not a base object. + << "a::f::post" << std::endl + #endif + #endif + ; + BOOST_TEST(out.eq(ok.str())); + } catch(...) { BOOST_TEST(false); } + + return boost::report_errors(); +} + diff --git a/src/boost/libs/contract/test/public_function/virtual.cpp b/src/boost/libs/contract/test/public_function/virtual.cpp new file mode 100644 index 000000000..766182ae4 --- /dev/null +++ b/src/boost/libs/contract/test/public_function/virtual.cpp @@ -0,0 +1,106 @@ + +// Copyright (C) 2008-2018 Lorenzo Caminiti +// Distributed under the Boost Software License, Version 1.0 (see accompanying +// file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt). +// See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html + +// Test public function subcontracting via virtual functions. + +#include "smoke.hpp" +#include <boost/preprocessor/control/iif.hpp> +#include <boost/detail/lightweight_test.hpp> +#include <sstream> + +int main() { + std::ostringstream ok; + + a aa; + c& ca = aa; // Test polymorphic virtual call (via reference to base c). + s_type s; s.value = "A"; + out.str(""); + result_type& r = ca.f(s); + + ok.str(""); ok + #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS + << "d::static_inv" << std::endl + << "d::inv" << std::endl + << "e::static_inv" << std::endl + << "e::inv" << std::endl + << "c::static_inv" << std::endl + << "c::inv" << std::endl + << "a::static_inv" << std::endl + << "a::inv" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_PRECONDITIONS + << "d::f::pre" << std::endl + << "e::f::pre" << std::endl + << "c::f::pre" << std::endl + << "a::f::pre" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_OLDS + << "d::f::old" << std::endl + << "e::f::old" << std::endl + << "c::f::old" << std::endl + << "a::f::old" << std::endl + #endif + << "a::f::body" << std::endl + #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS + << "d::static_inv" << std::endl + << "d::inv" << std::endl + << "e::static_inv" << std::endl + << "e::inv" << std::endl + << "c::static_inv" << std::endl + << "c::inv" << std::endl + << "a::static_inv" << std::endl + << "a::inv" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS + << "d::f::old" << std::endl + << "d::f::post" << std::endl + << "e::f::old" << std::endl + << "e::f::post" << std::endl + << "c::f::old" << std::endl + << "c::f::post" << std::endl + // No old call here because not a base object. + << "a::f::post" << std::endl + #endif + ; + BOOST_TEST(out.eq(ok.str())); + + #ifndef BOOST_CONTRACT_NO_OLDS + #define BOOST_CONTRACT_TEST_old 1u + #else + #define BOOST_CONTRACT_TEST_old 0u + #endif + + BOOST_TEST_EQ(r.value, "A"); + BOOST_TEST_EQ(s.value, "acde"); + BOOST_TEST_EQ(s.copies(), BOOST_CONTRACT_TEST_old * 4); + BOOST_TEST_EQ(s.evals(), BOOST_CONTRACT_TEST_old * 4); + BOOST_TEST_EQ(s.ctors(), s.dtors() + 1); // 1 local var. + + // Cannot access x via ca, but only via aa. + BOOST_TEST_EQ(aa.x.value, "aA"); + BOOST_TEST_EQ(aa.x.copies(), BOOST_CONTRACT_TEST_old); + BOOST_TEST_EQ(aa.x.evals(), BOOST_CONTRACT_TEST_old); + BOOST_TEST_EQ(aa.x.ctors(), aa.x.dtors() + 1); // 1 data member. + + BOOST_TEST_EQ(ca.y.value, "cA"); + BOOST_TEST_EQ(ca.y.copies(), BOOST_CONTRACT_TEST_old); + BOOST_TEST_EQ(ca.y.evals(), BOOST_CONTRACT_TEST_old); + BOOST_TEST_EQ(ca.y.ctors(), ca.y.dtors() + 1); // 1 data member. + + BOOST_TEST_EQ(ca.t<'d'>::z.value, "dA"); + BOOST_TEST_EQ(ca.t<'d'>::z.copies(), BOOST_CONTRACT_TEST_old); + BOOST_TEST_EQ(ca.t<'d'>::z.evals(), BOOST_CONTRACT_TEST_old); + BOOST_TEST_EQ(ca.t<'d'>::z.ctors(), ca.t<'d'>::z.dtors() + 1); // 1 member. + + BOOST_TEST_EQ(ca.t<'e'>::z.value, "eA"); + BOOST_TEST_EQ(ca.t<'e'>::z.copies(), BOOST_CONTRACT_TEST_old); + BOOST_TEST_EQ(ca.t<'e'>::z.evals(), BOOST_CONTRACT_TEST_old); + BOOST_TEST_EQ(ca.t<'e'>::z.ctors(), ca.t<'e'>::z.dtors() + 1); // 1 member. + + #undef BOOST_CONTRACT_TEST_old + return boost::report_errors(); +} + diff --git a/src/boost/libs/contract/test/public_function/virtual_access.cpp b/src/boost/libs/contract/test/public_function/virtual_access.cpp new file mode 100644 index 000000000..a83296a97 --- /dev/null +++ b/src/boost/libs/contract/test/public_function/virtual_access.cpp @@ -0,0 +1,220 @@ + +// Copyright (C) 2008-2018 Lorenzo Caminiti +// Distributed under the Boost Software License, Version 1.0 (see accompanying +// file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt). +// See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html + +// Test overrides with mixed access level from (single) base. + +#include "../detail/oteststream.hpp" +#include <boost/contract/public_function.hpp> +#include <boost/contract/function.hpp> +#include <boost/contract/base_types.hpp> +#include <boost/contract/override.hpp> +#include <boost/contract/check.hpp> +#include <boost/detail/lightweight_test.hpp> +#include <sstream> + +boost::contract::test::detail::oteststream out; + +struct b { // Test all access levels (public, protected, and private). + friend void call(b& me) { // Test polymorphic calls (object by &). + me.f(); + me.g(); + me.h(); + } + + static void statci_inv() { out << "b::static_inv" << std::endl; } + void invariant() const { out << "b::inv" << std::endl; } + + virtual void f(boost::contract::virtual_* v = 0) { + boost::contract::check c = boost::contract::public_function(v, this) + .precondition([] { out << "b::f::pre" << std::endl; }) + .old([] { out << "b::f::old" << std::endl; }) + .postcondition([] { out << "b::f::post" << std::endl; }) + ; + out << "b::f::body" << std::endl; + } + + // NOTE: Both protected and private virtual members must declare + // extra `virtual_* = 0` parameter (otherwise they cannot be overridden in + // derived classes with contracts because C++ uses also default parameters + // to match signature of overriding functions). + +protected: + virtual void g(boost::contract::virtual_* /* v */= 0) { + boost::contract::check c = boost::contract::function() + .precondition([] { out << "b::g::pre" << std::endl; }) + .old([] { out << "b::g::old" << std::endl; }) + .postcondition([] { out << "b::g::post" << std::endl; }) + ; + out << "b::g::body" << std::endl; + } + +private: + virtual void h(boost::contract::virtual_* /* v */ = 0) { + boost::contract::check c = boost::contract::function() + .precondition([] { out << "b::h::pre" << std::endl; }) + .old([] { out << "b::h::old" << std::endl; }) + .postcondition([] { out << "b::h::post" << std::endl; }) + ; + out << "b::h::body" << std::endl; + } +}; + +struct a // Test overrides with mixed access levels from base. + #define BASES public b + : BASES +{ + typedef BOOST_CONTRACT_BASE_TYPES(BASES) base_types; + #undef BASES + + static void statci_inv() { out << "a::static_inv" << std::endl; } + void invariant() const { out << "a::inv" << std::endl; } + + virtual void f(boost::contract::virtual_* v = 0) /* override */ { + boost::contract::check c = boost::contract::public_function<override_f>( + v, &a::f, this) + .precondition([] { out << "a::f::pre" << std::endl; }) + .old([] { out << "a::f::old" << std::endl; }) + .postcondition([] { out << "a::f::post" << std::endl; }) + ; + out << "a::f::body" << std::endl; + } + BOOST_CONTRACT_OVERRIDES(f) + + // Following do not override public members so no `override_...` param and + // they do not actually subcontract. + + virtual void g(boost::contract::virtual_* v = 0) /* override */ { + boost::contract::check c = boost::contract::public_function(v, this) + .precondition([] { out << "a::g::pre" << std::endl; }) + .old([] { out << "a::g::old" << std::endl; }) + .postcondition([] { out << "a::g::post" << std::endl; }) + ; + out << "a::g::body" << std::endl; + } + + virtual void h(boost::contract::virtual_* v = 0) /* override */ { + boost::contract::check c = boost::contract::public_function(v, this) + .precondition([] { out << "a::h::pre" << std::endl; }) + .old([] { out << "a::h::old" << std::endl; }) + .postcondition([] { out << "a::h::post" << std::endl; }) + ; + out << "a::h::body" << std::endl; + } +}; + +int main() { + std::ostringstream ok; + + b bb; + out.str(""); + call(bb); + ok.str(""); ok + #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS + << "b::inv" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_PRECONDITIONS + << "b::f::pre" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_OLDS + << "b::f::old" << std::endl + #endif + << "b::f::body" << std::endl + #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS + << "b::inv" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS + << "b::f::post" << std::endl + #endif + + #ifndef BOOST_CONTRACT_NO_PRECONDITIONS + << "b::g::pre" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_OLDS + << "b::g::old" << std::endl + #endif + << "b::g::body" << std::endl + #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS + << "b::g::post" << std::endl + #endif + + #ifndef BOOST_CONTRACT_NO_PRECONDITIONS + << "b::h::pre" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_OLDS + << "b::h::old" << std::endl + #endif + << "b::h::body" << std::endl + #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS + << "b::h::post" << std::endl + #endif + ; + BOOST_TEST(out.eq(ok.str())); + + a aa; + out.str(""); + call(aa); + ok.str(""); ok + #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS + << "b::inv" << std::endl + << "a::inv" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_PRECONDITIONS + << "b::f::pre" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_OLDS + << "b::f::old" << std::endl + << "a::f::old" << std::endl + #endif + << "a::f::body" << std::endl + #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS + << "b::inv" << std::endl + << "a::inv" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS + << "b::f::old" << std::endl + << "b::f::post" << std::endl + << "a::f::post" << std::endl + #endif + + #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS + << "a::inv" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_PRECONDITIONS + << "a::g::pre" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_OLDS + << "a::g::old" << std::endl + #endif + << "a::g::body" << std::endl + #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS + << "a::inv" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS + << "a::g::post" << std::endl + #endif + + #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS + << "a::inv" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_PRECONDITIONS + << "a::h::pre" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_OLDS + << "a::h::old" << std::endl + #endif + << "a::h::body" << std::endl + #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS + << "a::inv" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS + << "a::h::post" << std::endl + #endif + ; + BOOST_TEST(out.eq(ok.str())); + + return boost::report_errors(); +} + diff --git a/src/boost/libs/contract/test/public_function/virtual_access_multi.cpp b/src/boost/libs/contract/test/public_function/virtual_access_multi.cpp new file mode 100644 index 000000000..70bebad44 --- /dev/null +++ b/src/boost/libs/contract/test/public_function/virtual_access_multi.cpp @@ -0,0 +1,283 @@ + +// Copyright (C) 2008-2018 Lorenzo Caminiti +// Distributed under the Boost Software License, Version 1.0 (see accompanying +// file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt). +// See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html + +// Test overrides with mixed access levels from different (multiple) bases. + +#include <boost/config.hpp> +#ifdef BOOST_MSVC + +// WARNING: MSVC (at least up to VS 2015) gives a compile-time error if SFINAE +// cannot introspect a member because of its private or protected access level. +// That is incorrect, SFINAE should fail in these cases without generating +// compile-time errors like GCC and CLang do. Therefore, currently it is not +// possible to override a member that is public in one base but private or +// protected in other base using this library on MSVC (that can be done instead +// using this library on GCC or CLang). +int main() { return 0; } // This test trivially passes on MSVC. + +#else + +#include "../detail/oteststream.hpp" +#include <boost/contract/public_function.hpp> +#include <boost/contract/function.hpp> +#include <boost/contract/base_types.hpp> +#include <boost/contract/override.hpp> +#include <boost/contract/check.hpp> +#include <boost/detail/lightweight_test.hpp> +#include <sstream> + +boost::contract::test::detail::oteststream out; + +struct c { // Test public access different from base `b`'s access below. + static void statci_inv() { out << "c::static_inv" << std::endl; } + void invariant() const { out << "c::inv" << std::endl; } + + virtual void f(boost::contract::virtual_* v = 0) { + boost::contract::check c = boost::contract::public_function(v, this) + .precondition([] { out << "c::f::pre" << std::endl; }) + .old([] { out << "c::f::old" << std::endl; }) + .postcondition([] { out << "c::f::post" << std::endl; }) + ; + out << "c::f::body" << std::endl; + } + + virtual void g(boost::contract::virtual_* v = 0) { + boost::contract::check c = boost::contract::public_function(v, this) + .precondition([] { out << "c::g::pre" << std::endl; }) + .old([] { out << "c::g::old" << std::endl; }) + .postcondition([] { out << "c::g::post" << std::endl; }) + ; + out << "c::g::body" << std::endl; + } + + virtual void h(boost::contract::virtual_* v = 0) { + boost::contract::check c = boost::contract::public_function(v, this) + .precondition([] { out << "c::h::pre" << std::endl; }) + .old([] { out << "c::h::old" << std::endl; }) + .postcondition([] { out << "c::h::post" << std::endl; }) + ; + out << "c::h::body" << std::endl; + } +}; + +struct b { // Test all access levels (public, protected, and private). + friend void call(b& me) { // Test polymorphic calls (object by &). + me.f(); + me.g(); + me.h(); + } + + static void statci_inv() { out << "b::static_inv" << std::endl; } + void invariant() const { out << "b::inv" << std::endl; } + + virtual void f(boost::contract::virtual_* v = 0) { + boost::contract::check c = boost::contract::public_function(v, this) + .precondition([] { out << "b::f::pre" << std::endl; }) + .old([] { out << "b::f::old" << std::endl; }) + .postcondition([] { out << "b::f::post" << std::endl; }) + ; + out << "b::f::body" << std::endl; + } + + // NOTE: Both protected and private virtual members must declare + // extra `virtual_* = 0` parameter (otherwise they cannot be overridden in + // derived classes with contracts because C++ uses also default parameters + // to match signature of overriding functions). + +protected: + virtual void g(boost::contract::virtual_* /* v */ = 0) { + boost::contract::check c = boost::contract::function() + .precondition([] { out << "b::g::pre" << std::endl; }) + .old([] { out << "b::g::old" << std::endl; }) + .postcondition([] { out << "b::g::post" << std::endl; }) + ; + out << "b::g::body" << std::endl; + } + +private: + virtual void h(boost::contract::virtual_* /* v */ = 0) { + boost::contract::check c = boost::contract::function() + .precondition([] { out << "b::h::pre" << std::endl; }) + .old([] { out << "b::h::old" << std::endl; }) + .postcondition([] { out << "b::h::post" << std::endl; }) + ; + out << "b::h::body" << std::endl; + } +}; + +struct a // Test overrides with mixed access levels from different bases. + #define BASES public b, public c + : BASES +{ + typedef BOOST_CONTRACT_BASE_TYPES(BASES) base_types; + #undef BASES + + static void statci_inv() { out << "a::static_inv" << std::endl; } + void invariant() const { out << "a::inv" << std::endl; } + + virtual void f(boost::contract::virtual_* v = 0) /* override */ { + boost::contract::check c = boost::contract::public_function<override_f>( + v, &a::f, this) + .precondition([] { out << "a::f::pre" << std::endl; }) + .old([] { out << "a::f::old" << std::endl; }) + .postcondition([] { out << "a::f::post" << std::endl; }) + ; + out << "a::f::body" << std::endl; + } + + virtual void g(boost::contract::virtual_* v = 0) /* override */ { + boost::contract::check c = boost::contract::public_function<override_g>( + v, &a::g, this) + .precondition([] { out << "a::g::pre" << std::endl; }) + .old([] { out << "a::g::old" << std::endl; }) + .postcondition([] { out << "a::g::post" << std::endl; }) + ; + out << "a::g::body" << std::endl; + } + + virtual void h(boost::contract::virtual_* v = 0) /* override */ { + boost::contract::check c = boost::contract::public_function<override_h>( + v, &a::h, this) + .precondition([] { out << "a::h::pre" << std::endl; }) + .old([] { out << "a::h::old" << std::endl; }) + .postcondition([] { out << "a::h::post" << std::endl; }) + ; + out << "a::h::body" << std::endl; + } + + BOOST_CONTRACT_OVERRIDES(f, g, h) +}; + +int main() { + std::ostringstream ok; + + b bb; + out.str(""); + call(bb); + ok.str(""); ok + #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS + << "b::inv" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_PRECONDITIONS + << "b::f::pre" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_OLDS + << "b::f::old" << std::endl + #endif + << "b::f::body" << std::endl + #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS + << "b::inv" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS + << "b::f::post" << std::endl + #endif + + #ifndef BOOST_CONTRACT_NO_PRECONDITIONS + << "b::g::pre" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_OLDS + << "b::g::old" << std::endl + #endif + << "b::g::body" << std::endl + #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS + << "b::g::post" << std::endl + #endif + + #ifndef BOOST_CONTRACT_NO_PRECONDITIONS + << "b::h::pre" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_OLDS + << "b::h::old" << std::endl + #endif + << "b::h::body" << std::endl + #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS + << "b::h::post" << std::endl + #endif + ; + BOOST_TEST(out.eq(ok.str())); + + a aa; + out.str(""); + call(aa); + ok.str(""); ok + #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS + << "b::inv" << std::endl + << "c::inv" << std::endl + << "a::inv" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_PRECONDITIONS + << "b::f::pre" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_OLDS + << "b::f::old" << std::endl + << "c::f::old" << std::endl + << "a::f::old" << std::endl + #endif + << "a::f::body" << std::endl + #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS + << "b::inv" << std::endl + << "c::inv" << std::endl + << "a::inv" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS + << "b::f::old" << std::endl + << "b::f::post" << std::endl + << "c::f::old" << std::endl + << "c::f::post" << std::endl + << "a::f::post" << std::endl + #endif + + #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS + << "c::inv" << std::endl + << "a::inv" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_PRECONDITIONS + << "c::g::pre" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_OLDS + << "c::g::old" << std::endl + << "a::g::old" << std::endl + #endif + << "a::g::body" << std::endl + #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS + << "c::inv" << std::endl + << "a::inv" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS + << "c::g::old" << std::endl + << "c::g::post" << std::endl + << "a::g::post" << std::endl + #endif + + #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS + << "c::inv" << std::endl + << "a::inv" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_PRECONDITIONS + << "c::h::pre" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_OLDS + << "c::h::old" << std::endl + << "a::h::old" << std::endl + #endif + << "a::h::body" << std::endl + #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS + << "c::inv" << std::endl + << "a::inv" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS + << "c::h::old" << std::endl + << "c::h::post" << std::endl + << "a::h::post" << std::endl + #endif + ; + BOOST_TEST(out.eq(ok.str())); + + return boost::report_errors(); +} + +#endif // MSVC + diff --git a/src/boost/libs/contract/test/public_function/virtual_branch.cpp b/src/boost/libs/contract/test/public_function/virtual_branch.cpp new file mode 100644 index 000000000..b3c473517 --- /dev/null +++ b/src/boost/libs/contract/test/public_function/virtual_branch.cpp @@ -0,0 +1,90 @@ + +// Copyright (C) 2008-2018 Lorenzo Caminiti +// Distributed under the Boost Software License, Version 1.0 (see accompanying +// file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt). +// See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html + +// Test public function subcontracting from middle branch of inheritance tree. + +#include "smoke.hpp" +#include <boost/detail/lightweight_test.hpp> +#include <sstream> + +int main() { + std::ostringstream ok; + + c cc; // Test call to class at mid- inheritance tree (a base with bases). + s_type s; s.value = "C"; + out.str(""); + result_type& r = cc.f(s); + + ok.str(""); ok + #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS + << "d::static_inv" << std::endl + << "d::inv" << std::endl + << "e::static_inv" << std::endl + << "e::inv" << std::endl + << "c::static_inv" << std::endl + << "c::inv" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_PRECONDITIONS + << "d::f::pre" << std::endl + << "e::f::pre" << std::endl + << "c::f::pre" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_OLDS + << "d::f::old" << std::endl + << "e::f::old" << std::endl + << "c::f::old" << std::endl + #endif + << "c::f::body" << std::endl + #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS + << "d::static_inv" << std::endl + << "d::inv" << std::endl + << "e::static_inv" << std::endl + << "e::inv" << std::endl + << "c::static_inv" << std::endl + << "c::inv" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS + << "d::f::old" << std::endl + << "d::f::post" << std::endl + << "e::f::old" << std::endl + << "e::f::post" << std::endl + // No old call here because not a base object. + << "c::f::post" << std::endl + #endif + ; + BOOST_TEST(out.eq(ok.str())); + + #ifndef BOOST_CONTRACT_NO_OLDS + #define BOOST_CONTRACT_TEST_old 1u + #else + #define BOOST_CONTRACT_TEST_old 0u + #endif + + BOOST_TEST_EQ(r.value, "C"); + BOOST_TEST_EQ(s.value, "cde"); + BOOST_TEST_EQ(s.copies(), BOOST_CONTRACT_TEST_old * 3); + BOOST_TEST_EQ(s.evals(), BOOST_CONTRACT_TEST_old * 3); + BOOST_TEST_EQ(s.ctors(), s.dtors() + 1); // 1 local var. + + BOOST_TEST_EQ(cc.y.value, "cC"); + BOOST_TEST_EQ(cc.y.copies(), BOOST_CONTRACT_TEST_old); + BOOST_TEST_EQ(cc.y.evals(), BOOST_CONTRACT_TEST_old); + BOOST_TEST_EQ(cc.y.ctors(), cc.y.dtors() + 1); // 1 data member. + + BOOST_TEST_EQ(cc.t<'d'>::z.value, "dC"); + BOOST_TEST_EQ(cc.t<'d'>::z.copies(), BOOST_CONTRACT_TEST_old); + BOOST_TEST_EQ(cc.t<'d'>::z.evals(), BOOST_CONTRACT_TEST_old); + BOOST_TEST_EQ(cc.t<'d'>::z.ctors(), cc.t<'d'>::z.dtors() + 1); // 1 member. + + BOOST_TEST_EQ(cc.t<'e'>::z.value, "eC"); + BOOST_TEST_EQ(cc.t<'e'>::z.copies(), BOOST_CONTRACT_TEST_old); + BOOST_TEST_EQ(cc.t<'e'>::z.evals(), BOOST_CONTRACT_TEST_old); + BOOST_TEST_EQ(cc.t<'e'>::z.ctors(), cc.t<'e'>::z.dtors() + 1); // 1 member. + + #undef BOOST_CONTRACT_TEST_old + return boost::report_errors(); +} + diff --git a/src/boost/libs/contract/test/public_function/virtual_sparse.cpp b/src/boost/libs/contract/test/public_function/virtual_sparse.cpp new file mode 100644 index 000000000..09d76d6f2 --- /dev/null +++ b/src/boost/libs/contract/test/public_function/virtual_sparse.cpp @@ -0,0 +1,418 @@ + +// Copyright (C) 2008-2018 Lorenzo Caminiti +// Distributed under the Boost Software License, Version 1.0 (see accompanying +// file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt). +// See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html + +// Test subcontracting with sparse and complex inheritance graph. + +#include "../detail/oteststream.hpp" +#include <boost/contract/public_function.hpp> +#include <boost/contract/assert.hpp> +#include <boost/contract/check.hpp> +#include <boost/contract/override.hpp> +#include <boost/contract/base_types.hpp> +#include <boost/detail/lightweight_test.hpp> +#include <sstream> + +boost::contract::test::detail::oteststream out; + +struct j { + static void static_invariant() { out << "j::static_inv" << std::endl; } + void invariant() const { out << "j::inv" << std::endl; } + + virtual void f(char ch, boost::contract::virtual_* v = 0) { + boost::contract::check c = boost::contract::public_function(v, this) + .precondition([&] { + out << "j::f::pre" << std::endl; + BOOST_CONTRACT_ASSERT(ch == 'j'); + }) + .old([] { out << "j::f::old" << std::endl; }) + .postcondition([] { out << "j::f::post" << std::endl; }) + ; + out << "j::f::body" << std::endl; + } +}; + +struct i { + static void static_invariant() { out << "i::static_inv" << std::endl; } + void invariant() const { out << "i::inv" << std::endl; } + + virtual void f(char ch, boost::contract::virtual_* v = 0) { + boost::contract::check c = boost::contract::public_function(v, this) + .precondition([&] { + out << "i::f::pre" << std::endl; + BOOST_CONTRACT_ASSERT(ch == 'i'); + }) + .old([] { out << "i::f::old" << std::endl; }) + .postcondition([] { out << "i::f::post" << std::endl; }) + ; + out << "i::f::body" << std::endl; + } +}; + +struct k {}; + +struct h + #define BASES public j + : BASES +{ + typedef BOOST_CONTRACT_BASE_TYPES(BASES) base_types; + #undef BASES + + static void static_invariant() { out << "h::static_inv" << std::endl; } + void invariant() const { out << "h::inv" << std::endl; } + + virtual void f(char ch, boost::contract::virtual_* v = 0) /* override */ { + boost::contract::check c = boost::contract::public_function< + override_f>(v, &h::f, this, ch) + .precondition([&] { + out << "h::f::pre" << std::endl; + BOOST_CONTRACT_ASSERT(ch == 'h'); + }) + .old([] { out << "h::f::old" << std::endl; }) + .postcondition([] { out << "h::f::post" << std::endl; }) + ; + out << "h::f::body" << std::endl; + } + BOOST_CONTRACT_OVERRIDE(f) +}; + +struct e + #define BASES public virtual i + : BASES +{ + typedef BOOST_CONTRACT_BASE_TYPES(BASES) base_types; + #undef BASES + + static void static_invariant() { out << "e::static_inv" << std::endl; } + void invariant() const { out << "e::inv" << std::endl; } + + virtual void f(char ch, boost::contract::virtual_* v = 0) /* override */ { + boost::contract::check c = boost::contract::public_function< + override_f>(v, &e::f, this, ch) + .precondition([&] { + out << "e::f::pre" << std::endl; + BOOST_CONTRACT_ASSERT(ch == 'e'); + }) + .old([] { out << "e::f::old" << std::endl; }) + .postcondition([] { out << "e::f::post" << std::endl; }) + ; + out << "e::f::body" << std::endl; + } + BOOST_CONTRACT_OVERRIDE(f) +}; + +struct d + #define BASES public k, virtual public i + : BASES +{ + typedef BOOST_CONTRACT_BASE_TYPES(BASES) base_types; + #undef BASES + + static void static_invariant() { out << "d::static_inv" << std::endl; } + void invariant() const { out << "d::inv" << std::endl; } +}; + +struct c { + static void static_invariant() { out << "c::static_inv" << std::endl; } + void invariant() const { out << "c::inv" << std::endl; } + + virtual void f(char ch, boost::contract::virtual_* v = 0) { + boost::contract::check c = boost::contract::public_function(v, this) + .precondition([&] { + out << "c::f::pre" << std::endl; + BOOST_CONTRACT_ASSERT(ch == 'c'); + }) + .old([] { out << "c::f::old" << std::endl; }) + .postcondition([] { out << "c::f::post" << std::endl; }) + ; + out << "c::f::body" << std::endl; + } +}; + +struct b + #define BASES public c, public d + : BASES +{ + typedef BOOST_CONTRACT_BASE_TYPES(BASES) base_types; + #undef BASES + + static void static_invariant() { out << "b::static_inv" << std::endl; } + void invariant() const { out << "b::inv" << std::endl; } +}; + +struct x {}; +struct y {}; +struct z {}; + +struct a + #define BASES public b, public x, public e, protected y, public h, \ + private z + : BASES +{ + typedef BOOST_CONTRACT_BASE_TYPES(BASES) base_types; + #undef BASES + + static void static_invariant() { out << "a::static_inv" << std::endl; } + void invariant() const { out << "a::inv" << std::endl; } + + virtual void f(char ch, boost::contract::virtual_* v = 0) /* override */ { + boost::contract::check c = boost::contract::public_function< + override_f>(v, &a::f, this, ch) + .precondition([&] { + out << "a::f::pre" << std::endl; + BOOST_CONTRACT_ASSERT(ch == 'a'); + }) + .old([] { out << "a::f::old" << std::endl; }) + .postcondition([] { out << "a::f::post" << std::endl; }) + ; + out << "a::f::body" << std::endl; + } + BOOST_CONTRACT_OVERRIDE(f) +}; + +int main() { + std::ostringstream ok; + + a aa; + out.str(""); + aa.f('a'); + ok.str(""); ok + #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS + << "c::static_inv" << std::endl + << "c::inv" << std::endl + << "i::static_inv" << std::endl + << "i::inv" << std::endl + << "e::static_inv" << std::endl + << "e::inv" << std::endl + << "j::static_inv" << std::endl + << "j::inv" << std::endl + << "h::static_inv" << std::endl + << "h::inv" << std::endl + << "a::static_inv" << std::endl + << "a::inv" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_PRECONDITIONS + << "c::f::pre" << std::endl + << "i::f::pre" << std::endl + << "e::f::pre" << std::endl + << "j::f::pre" << std::endl + << "h::f::pre" << std::endl + << "a::f::pre" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_OLDS + << "c::f::old" << std::endl + << "i::f::old" << std::endl + << "e::f::old" << std::endl + << "j::f::old" << std::endl + << "h::f::old" << std::endl + << "a::f::old" << std::endl + #endif + << "a::f::body" << std::endl + #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS + << "c::static_inv" << std::endl + << "c::inv" << std::endl + << "i::static_inv" << std::endl + << "i::inv" << std::endl + << "e::static_inv" << std::endl + << "e::inv" << std::endl + << "j::static_inv" << std::endl + << "j::inv" << std::endl + << "h::static_inv" << std::endl + << "h::inv" << std::endl + << "a::static_inv" << std::endl + << "a::inv" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS + << "c::f::old" << std::endl + << "c::f::post" << std::endl + << "i::f::old" << std::endl + << "i::f::post" << std::endl + << "e::f::old" << std::endl + << "e::f::post" << std::endl + << "j::f::old" << std::endl + << "j::f::post" << std::endl + << "h::f::old" << std::endl + << "h::f::post" << std::endl + // No old call here because not a base object. + << "a::f::post" << std::endl + #endif + ; + BOOST_TEST(out.eq(ok.str())); + + c cc; + out.str(""); + cc.f('c'); + ok.str(""); ok + #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS + << "c::static_inv" << std::endl + << "c::inv" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_PRECONDITIONS + << "c::f::pre" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_OLDS + << "c::f::old" << std::endl + #endif + << "c::f::body" << std::endl + #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS + << "c::static_inv" << std::endl + << "c::inv" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS + // No old call here because not a base object. + << "c::f::post" << std::endl + #endif + ; + BOOST_TEST(out.eq(ok.str())); + + d dd; + out.str(""); + dd.f('i'); // d's f inherited from i. + ok.str(""); ok + #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS + << "i::static_inv" << std::endl + << "i::inv" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_PRECONDITIONS + << "i::f::pre" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_OLDS + << "i::f::old" << std::endl + #endif + << "i::f::body" << std::endl + #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS + << "i::static_inv" << std::endl + << "i::inv" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS + // No old call here because not a base object. + << "i::f::post" << std::endl + #endif + ; + BOOST_TEST(out.eq(ok.str())); + + e ee; + out.str(""); + ee.f('e'); + ok.str(""); ok + #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS + << "i::static_inv" << std::endl + << "i::inv" << std::endl + << "e::static_inv" << std::endl + << "e::inv" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_PRECONDITIONS + << "i::f::pre" << std::endl + << "e::f::pre" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_OLDS + << "i::f::old" << std::endl + << "e::f::old" << std::endl + #endif + << "e::f::body" << std::endl + #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS + << "i::static_inv" << std::endl + << "i::inv" << std::endl + << "e::static_inv" << std::endl + << "e::inv" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS + << "i::f::old" << std::endl + << "i::f::post" << std::endl + // No old call here because not a base object. + << "e::f::post" << std::endl + #endif + ; + BOOST_TEST(out.eq(ok.str())); + + i ii; + out.str(""); + ii.f('i'); + ok.str(""); ok + #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS + << "i::static_inv" << std::endl + << "i::inv" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_PRECONDITIONS + << "i::f::pre" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_OLDS + << "i::f::old" << std::endl + #endif + << "i::f::body" << std::endl + #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS + << "i::static_inv" << std::endl + << "i::inv" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS + // No old call here because not a base object. + << "i::f::post" << std::endl + #endif + ; + BOOST_TEST(out.eq(ok.str())); + + h hh; + out.str(""); + hh.f('h'); + ok.str(""); ok + #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS + << "j::static_inv" << std::endl + << "j::inv" << std::endl + << "h::static_inv" << std::endl + << "h::inv" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_PRECONDITIONS + << "j::f::pre" << std::endl + << "h::f::pre" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_OLDS + << "j::f::old" << std::endl + << "h::f::old" << std::endl + #endif + << "h::f::body" << std::endl + #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS + << "j::static_inv" << std::endl + << "j::inv" << std::endl + << "h::static_inv" << std::endl + << "h::inv" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS + << "j::f::old" << std::endl + << "j::f::post" << std::endl + // No old call here because not a base object. + << "h::f::post" << std::endl + #endif + ; + BOOST_TEST(out.eq(ok.str())); + + j jj; + out.str(""); + jj.f('j'); + ok.str(""); ok + #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS + << "j::static_inv" << std::endl + << "j::inv" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_PRECONDITIONS + << "j::f::pre" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_OLDS + << "j::f::old" << std::endl + #endif + << "j::f::body" << std::endl + #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS + << "j::static_inv" << std::endl + << "j::inv" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS + // No old call here because not a base object. + << "j::f::post" << std::endl + #endif + ; + BOOST_TEST(out.eq(ok.str())); + + return boost::report_errors(); +} + diff --git a/src/boost/libs/contract/test/result/mixed_optional.cpp b/src/boost/libs/contract/test/result/mixed_optional.cpp new file mode 100644 index 000000000..c2002007a --- /dev/null +++ b/src/boost/libs/contract/test/result/mixed_optional.cpp @@ -0,0 +1,10 @@ + +// Copyright (C) 2008-2018 Lorenzo Caminiti +// Distributed under the Boost Software License, Version 1.0 (see accompanying +// file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt). +// See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html + +// Test base and derived classes mixing boost::optional and non- result types. + +#include "mixed_optional.hpp" + diff --git a/src/boost/libs/contract/test/result/mixed_optional.hpp b/src/boost/libs/contract/test/result/mixed_optional.hpp new file mode 100644 index 000000000..425941f1a --- /dev/null +++ b/src/boost/libs/contract/test/result/mixed_optional.hpp @@ -0,0 +1,410 @@ + +// no #include guard + +// Copyright (C) 2008-2018 Lorenzo Caminiti +// Distributed under the Boost Software License, Version 1.0 (see accompanying +// file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt). +// See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html + +// Test base and derived classes mixing boost::optional and non- result types. + +#include "../detail/oteststream.hpp" +#include "../detail/counter.hpp" +#include <boost/contract/base_types.hpp> +#include <boost/contract/public_function.hpp> +#include <boost/contract/override.hpp> +#include <boost/contract/check.hpp> +#include <boost/contract/assert.hpp> +#include <boost/optional.hpp> +#include <boost/detail/lightweight_test.hpp> +#include <boost/config.hpp> +#include <sstream> +#include <cassert> + +boost::contract::test::detail::oteststream out; + +struct ch_tag; +typedef boost::contract::test::detail::counter<ch_tag, char> ch_type; + +#ifdef BOOST_CONTRACT_TEST_REF // Test with result types by reference. + #define BOOST_CONTRACT_TEST_CH_TYPE ch_type& + #define BOOST_CONTRACT_TEST_CH_INIT = ch_init + ch_type ch_init; + unsigned const ch_extras = 2; // 1 local and 1 global var. +#else // Test with result types by value. + #define BOOST_CONTRACT_TEST_CH_TYPE ch_type + #define BOOST_CONTRACT_TEST_CH_INIT /* nothing */ + unsigned const ch_extras = 1; // 1 for local var (no global var). +#endif + +bool tested_d_copies = false; +struct d { + static void static_invariant() { out << "d::static_inv" << std::endl; } + void invariant() const { out << "d::inv" << std::endl; } + + virtual BOOST_CONTRACT_TEST_CH_TYPE f( + ch_type& ch, boost::contract::virtual_* v = 0) { + unsigned const old_ch_copies = ch_type::copies(); + boost::optional<BOOST_CONTRACT_TEST_CH_TYPE> result; + boost::contract::check c = boost::contract::public_function( + v, result, this) + .precondition([&] { + out << "d::f::pre" << std::endl; + BOOST_CONTRACT_ASSERT(ch.value == 'd'); + }) + .old([] { out << "d::f::old" << std::endl; }) + .postcondition([&] (boost::optional<ch_type const&> const& result) { + out << "d::f::post" << std::endl; + BOOST_CONTRACT_ASSERT(result->value == ch.value); + }) + ; + BOOST_TEST_EQ(ch_type::copies(), old_ch_copies); + tested_d_copies = true; + + out << "d::f::body" << std::endl; + return *(result = ch); + } +}; + +bool tested_c_copies = false; +struct c + #define BASES public d + : BASES +{ + typedef BOOST_CONTRACT_BASE_TYPES(BASES) base_types; + #undef BASES + + static void static_invariant() { out << "c::static_inv" << std::endl; } + void invariant() const { out << "c::inv" << std::endl; } + + virtual BOOST_CONTRACT_TEST_CH_TYPE f( + ch_type& ch, boost::contract::virtual_* v = 0) /* override */ { + unsigned const old_ch_copies = ch_type::copies(); + boost::optional<BOOST_CONTRACT_TEST_CH_TYPE> result; + boost::contract::check c = boost::contract::public_function<override_f>( + v, result, &c::f, this, ch) + .precondition([&] { + out << "c::f::pre" << std::endl; + BOOST_CONTRACT_ASSERT(ch.value == 'c'); + }) + .old([] { out << "c::f::old" << std::endl; }) + .postcondition([&] (boost::optional<ch_type const&> const& result) { + out << "c::f::post" << std::endl; + BOOST_CONTRACT_ASSERT(result->value == ch.value); + }) + ; + BOOST_TEST_EQ(ch_type::copies(), old_ch_copies); + tested_c_copies = true; + + out << "c::f::body" << std::endl; + return *(result = ch); + } + BOOST_CONTRACT_OVERRIDE(f) +}; + +bool tested_b_copies = false; +struct b + #define BASES public c + : BASES +{ + typedef BOOST_CONTRACT_BASE_TYPES(BASES) base_types; + #undef BASES + + static void static_invariant() { out << "b::static_inv" << std::endl; } + void invariant() const { out << "b::inv" << std::endl; } + + virtual BOOST_CONTRACT_TEST_CH_TYPE f( + ch_type& ch, boost::contract::virtual_* v = 0) /* override */ { + unsigned const old_ch_copies = ch_type::copies(); + BOOST_CONTRACT_TEST_CH_TYPE result BOOST_CONTRACT_TEST_CH_INIT; + boost::contract::check c = boost::contract::public_function<override_f>( + v, result, &b::f, this, ch) + .precondition([&] { + out << "b::f::pre" << std::endl; + BOOST_CONTRACT_ASSERT(ch.value == 'b'); + }) + .old([] { out << "b::f::old" << std::endl; }) + .postcondition([&] (ch_type const& result) { + out << "b::f::post" << std::endl; + BOOST_CONTRACT_ASSERT(result.value == ch.value); + }) + ; + BOOST_TEST_EQ(ch_type::copies(), old_ch_copies); + tested_b_copies = true; + + out << "b::f::body" << std::endl; + return result = ch; + } + BOOST_CONTRACT_OVERRIDE(f) +}; + +bool tested_a_copies = false; +struct a + #define BASES public b + : BASES +{ + typedef BOOST_CONTRACT_BASE_TYPES(BASES) base_types; + #undef BASES + + static void static_invariant() { out << "a::static_inv" << std::endl; } + void invariant() const { out << "a::inv" << std::endl; } + + virtual BOOST_CONTRACT_TEST_CH_TYPE f( + ch_type& ch, boost::contract::virtual_* v = 0) /* override */ { + unsigned const old_ch_copies = ch_type::copies(); + boost::optional<BOOST_CONTRACT_TEST_CH_TYPE> result; + boost::contract::check c = boost::contract::public_function<override_f>( + v, result, &a::f, this, ch) + .precondition([&] { + out << "a::f::pre" << std::endl; + BOOST_CONTRACT_ASSERT(ch.value == 'a'); + }) + .old([] { out << "a::f::old" << std::endl; }) + .postcondition([&] (boost::optional<ch_type const&> const& result) { + out << "a::f::post" << std::endl; + BOOST_CONTRACT_ASSERT(result->value == ch.value); + }) + ; + BOOST_TEST_EQ(ch_type::copies(), old_ch_copies); + tested_a_copies = true; + + out << "a::f::body" << std::endl; + return *(result = ch); + } + BOOST_CONTRACT_OVERRIDE(f) +}; + +bool tested_e_copies = false; +struct e + #define BASES public b + : BASES +{ + typedef BOOST_CONTRACT_BASE_TYPES(BASES) base_types; + #undef BASES + + static void static_invariant() { out << "e::static_inv" << std::endl; } + void invariant() const { out << "e::inv" << std::endl; } + + virtual BOOST_CONTRACT_TEST_CH_TYPE f( + ch_type& ch, boost::contract::virtual_* v = 0) /* override */ { + unsigned const old_ch_copies = ch_type::copies(); + BOOST_CONTRACT_TEST_CH_TYPE result BOOST_CONTRACT_TEST_CH_INIT; + boost::contract::check c = boost::contract::public_function<override_f>( + v, result, &e::f, this, ch) + .precondition([&] { + out << "e::f::pre" << std::endl; + BOOST_CONTRACT_ASSERT(ch.value == 'e'); + }) + .old([] { out << "e::f::old" << std::endl; }) + .postcondition([&] (ch_type const& result) { + out << "e::f::post" << std::endl; + BOOST_CONTRACT_ASSERT(result.value == ch.value); + }) + ; + BOOST_TEST_EQ(ch_type::copies(), old_ch_copies); + tested_e_copies = true; + + out << "e::f::body" << std::endl; + return result = ch; + } + BOOST_CONTRACT_OVERRIDE(f) +}; + +int main() { + std::ostringstream ok; + ch_type ch; + #ifdef BOOST_CONTRACT_TEST_REF + ch_init.value = '\0'; + #endif + + // Test optional in overriding a::f and non-optional in overridden b::f. + a aa; + ch.value = 'a'; + out.str(""); + aa.f(ch); + ok.str(""); ok + #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS + << "d::static_inv" << std::endl + << "d::inv" << std::endl + << "c::static_inv" << std::endl + << "c::inv" << std::endl + << "b::static_inv" << std::endl + << "b::inv" << std::endl + << "a::static_inv" << std::endl + << "a::inv" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_PRECONDITIONS + << "d::f::pre" << std::endl + << "c::f::pre" << std::endl + << "b::f::pre" << std::endl + << "a::f::pre" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_OLDS + << "d::f::old" << std::endl + << "c::f::old" << std::endl + << "b::f::old" << std::endl + << "a::f::old" << std::endl + #endif + << "a::f::body" << std::endl + #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS + << "d::static_inv" << std::endl + << "d::inv" << std::endl + << "c::static_inv" << std::endl + << "c::inv" << std::endl + << "b::static_inv" << std::endl + << "b::inv" << std::endl + << "a::static_inv" << std::endl + << "a::inv" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS + << "d::f::old" << std::endl + << "d::f::post" << std::endl + << "c::f::old" << std::endl + << "c::f::post" << std::endl + << "b::f::old" << std::endl + << "b::f::post" << std::endl + << "a::f::post" << std::endl + #endif + ; + BOOST_TEST(out.eq(ok.str())); + BOOST_TEST(tested_a_copies); + BOOST_TEST_EQ(ch_type::ctors(), ch_type::dtors() + ch_extras); + + // Test non-optional in overriding b::f and optional in overridden c::f. + b bb; + ch.value = 'b'; + out.str(""); + bb.f(ch); + ok.str(""); ok + #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS + << "d::static_inv" << std::endl + << "d::inv" << std::endl + << "c::static_inv" << std::endl + << "c::inv" << std::endl + << "b::static_inv" << std::endl + << "b::inv" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_PRECONDITIONS + << "d::f::pre" << std::endl + << "c::f::pre" << std::endl + << "b::f::pre" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_OLDS + << "d::f::old" << std::endl + << "c::f::old" << std::endl + << "b::f::old" << std::endl + #endif + << "b::f::body" << std::endl + #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS + << "d::static_inv" << std::endl + << "d::inv" << std::endl + << "c::static_inv" << std::endl + << "c::inv" << std::endl + << "b::static_inv" << std::endl + << "b::inv" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS + << "d::f::old" << std::endl + << "d::f::post" << std::endl + << "c::f::old" << std::endl + << "c::f::post" << std::endl + << "b::f::post" << std::endl + #endif + ; + BOOST_TEST(out.eq(ok.str())); + BOOST_TEST(tested_b_copies); + BOOST_TEST_EQ(ch_type::ctors(), ch_type::dtors() + ch_extras); + + // Test optional in both overriding c::f and overridden d::f. + c cc; + ch.value = 'c'; + out.str(""); + cc.f(ch); + ok.str(""); ok + #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS + << "d::static_inv" << std::endl + << "d::inv" << std::endl + << "c::static_inv" << std::endl + << "c::inv" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_PRECONDITIONS + << "d::f::pre" << std::endl + << "c::f::pre" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_OLDS + << "d::f::old" << std::endl + << "c::f::old" << std::endl + #endif + << "c::f::body" << std::endl + #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS + << "d::static_inv" << std::endl + << "d::inv" << std::endl + << "c::static_inv" << std::endl + << "c::inv" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS + << "d::f::old" << std::endl + << "d::f::post" << std::endl + << "c::f::post" << std::endl + #endif + ; + BOOST_TEST(out.eq(ok.str())); + BOOST_TEST(tested_c_copies); + BOOST_TEST_EQ(ch_type::ctors(), ch_type::dtors() + ch_extras); + + // Test non-optional in both overriding c::f and overridden d::f. + e ee; + ch.value = 'e'; + out.str(""); + ee.f(ch); + ok.str(""); ok + #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS + << "d::static_inv" << std::endl + << "d::inv" << std::endl + << "c::static_inv" << std::endl + << "c::inv" << std::endl + << "b::static_inv" << std::endl + << "b::inv" << std::endl + << "e::static_inv" << std::endl + << "e::inv" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_PRECONDITIONS + << "d::f::pre" << std::endl + << "c::f::pre" << std::endl + << "b::f::pre" << std::endl + << "e::f::pre" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_OLDS + << "d::f::old" << std::endl + << "c::f::old" << std::endl + << "b::f::old" << std::endl + << "e::f::old" << std::endl + #endif + << "e::f::body" << std::endl + #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS + << "d::static_inv" << std::endl + << "d::inv" << std::endl + << "c::static_inv" << std::endl + << "c::inv" << std::endl + << "b::static_inv" << std::endl + << "b::inv" << std::endl + << "e::static_inv" << std::endl + << "e::inv" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS + << "d::f::old" << std::endl + << "d::f::post" << std::endl + << "c::f::old" << std::endl + << "c::f::post" << std::endl + << "b::f::old" << std::endl + << "b::f::post" << std::endl + << "e::f::post" << std::endl + #endif + ; + BOOST_TEST(out.eq(ok.str())); + BOOST_TEST(tested_e_copies); + BOOST_TEST_EQ(ch_type::ctors(), ch_type::dtors() + ch_extras); + + return boost::report_errors(); +} + diff --git a/src/boost/libs/contract/test/result/mixed_optional_ref.cpp b/src/boost/libs/contract/test/result/mixed_optional_ref.cpp new file mode 100644 index 000000000..e7b2acc96 --- /dev/null +++ b/src/boost/libs/contract/test/result/mixed_optional_ref.cpp @@ -0,0 +1,11 @@ + +// Copyright (C) 2008-2018 Lorenzo Caminiti +// Distributed under the Boost Software License, Version 1.0 (see accompanying +// file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt). +// See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html + +// Test base and derived classes mixing boost::optional and non- result by ref. + +#define BOOST_CONTRACT_TEST_REF +#include "mixed_optional.hpp" + diff --git a/src/boost/libs/contract/test/result/type_mismatch_error.cpp b/src/boost/libs/contract/test/result/type_mismatch_error.cpp new file mode 100644 index 000000000..3e6180bdb --- /dev/null +++ b/src/boost/libs/contract/test/result/type_mismatch_error.cpp @@ -0,0 +1,50 @@ + +// Copyright (C) 2008-2018 Lorenzo Caminiti +// Distributed under the Boost Software License, Version 1.0 (see accompanying +// file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt). +// See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html + +// Test override public function error on result type mismatch. + +#include <boost/contract/public_function.hpp> +#include <boost/contract/override.hpp> +#include <boost/contract/base_types.hpp> +#include <boost/contract/check.hpp> + +struct b { + virtual int f(boost::contract::virtual_* v = 0) { + // Unfortunately, this cannot be made to error at compile-time because + // in this case public_function does not that &b::f as param (but this + // will error at run-time on a virtual call via a derived class). + char result; + boost::contract::check c = boost::contract::public_function( + v, result, this); + return result; + } +}; + +struct a + #define BASES public b + : BASES +{ + typedef BOOST_CONTRACT_BASE_TYPES(BASES) base_types; + #undef BASES + + virtual int f(boost::contract::virtual_* v = 0) /* override */ { + char result; + boost::contract::check c = boost::contract::public_function<override_f>( + v, result, &a::f, this); // Error (result time mismatch). + #ifdef BOOST_CONTRACT_NO_PUBLIC_FUNCTIONS + #error "Forcing error even when public functions not checked" + #endif + return result; + } + BOOST_CONTRACT_OVERRIDE(f) +}; + +int main() { + a aa; + aa.f(); + return 0; +} + diff --git a/src/boost/libs/contract/test/specify/auto_error.cpp b/src/boost/libs/contract/test/specify/auto_error.cpp new file mode 100644 index 000000000..04990649f --- /dev/null +++ b/src/boost/libs/contract/test/specify/auto_error.cpp @@ -0,0 +1,24 @@ + +// Copyright (C) 2008-2018 Lorenzo Caminiti +// Distributed under the Boost Software License, Version 1.0 (see accompanying +// file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt). +// See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html + +// Test auto error (for free func, but same for all contracts). + +#include <boost/config.hpp> +// Not just __cplusplus to detect C++17 as MSVC defines it correctly sometimes. +#if (defined(__cplusplus) && __cplusplus >= 201703L) || \ + !defined(BOOST_NO_CXX17_IF_CONSTEXPR) + #error "C++17 copy elision invalidates test so forcing expected failure" +#else + +#include <boost/contract/function.hpp> + +int main() { + auto c = boost::contract::function(); // Error (can't use auto). + return 0; +} + +#endif + diff --git a/src/boost/libs/contract/test/specify/auto_pre_error.cpp b/src/boost/libs/contract/test/specify/auto_pre_error.cpp new file mode 100644 index 000000000..1a5b7f606 --- /dev/null +++ b/src/boost/libs/contract/test/specify/auto_pre_error.cpp @@ -0,0 +1,26 @@ + +// Copyright (C) 2008-2018 Lorenzo Caminiti +// Distributed under the Boost Software License, Version 1.0 (see accompanying +// file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt). +// See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html + +// Test auto error after pre (for free func, but same for all contracts). + +#include <boost/config.hpp> +// Not just __cplusplus to detect C++17 as MSVC defines it correctly sometimes. +#if (defined(__cplusplus) && __cplusplus >= 201703L) || \ + !defined(BOOST_NO_CXX17_IF_CONSTEXPR) + #error "C++17 copy elision invalidates test so forcing expected failure" +#else + +#include <boost/contract/function.hpp> + +int main() { + auto c = boost::contract::function() // Error (can't use auto). + .precondition([] {}) + ; + return 0; +} + +#endif + diff --git a/src/boost/libs/contract/test/specify/auto_pre_old_error.cpp b/src/boost/libs/contract/test/specify/auto_pre_old_error.cpp new file mode 100644 index 000000000..6c3187699 --- /dev/null +++ b/src/boost/libs/contract/test/specify/auto_pre_old_error.cpp @@ -0,0 +1,27 @@ + +// Copyright (C) 2008-2018 Lorenzo Caminiti +// Distributed under the Boost Software License, Version 1.0 (see accompanying +// file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt). +// See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html + +// Test auto error after old (for free func, but same for all contracts). + +#include <boost/config.hpp> +// Not just __cplusplus to detect C++17 as MSVC defines it correctly sometimes. +#if (defined(__cplusplus) && __cplusplus >= 201703L) || \ + !defined(BOOST_NO_CXX17_IF_CONSTEXPR) + #error "C++17 copy elision invalidates test so forcing expected failure" +#else + +#include <boost/contract/function.hpp> + +int main() { + auto c = boost::contract::function() // Error (can't use auto). + .precondition([] {}) + .old([] {}) + ; + return 0; +} + +#endif + diff --git a/src/boost/libs/contract/test/specify/auto_pre_old_post_error.cpp b/src/boost/libs/contract/test/specify/auto_pre_old_post_error.cpp new file mode 100644 index 000000000..6d0302ffd --- /dev/null +++ b/src/boost/libs/contract/test/specify/auto_pre_old_post_error.cpp @@ -0,0 +1,28 @@ + +// Copyright (C) 2008-2018 Lorenzo Caminiti +// Distributed under the Boost Software License, Version 1.0 (see accompanying +// file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt). +// See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html + +// Test auto error after post (for free func, but same for all contracts). + +#include <boost/config.hpp> +// Not just __cplusplus to detect C++17 as MSVC defines it correctly sometimes. +#if (defined(__cplusplus) && __cplusplus >= 201703L) || \ + !defined(BOOST_NO_CXX17_IF_CONSTEXPR) + #error "C++17 copy elision invalidates test so forcing expected failure" +#else + +#include <boost/contract/function.hpp> + +int main() { + auto c = boost::contract::function() // Error (can't use auto). + .precondition([] {}) + .old([] {}) + .postcondition([] {}) + ; + return 0; +} + +#endif + diff --git a/src/boost/libs/contract/test/specify/auto_pre_old_post_except_error.cpp b/src/boost/libs/contract/test/specify/auto_pre_old_post_except_error.cpp new file mode 100644 index 000000000..c51d32953 --- /dev/null +++ b/src/boost/libs/contract/test/specify/auto_pre_old_post_except_error.cpp @@ -0,0 +1,29 @@ + +// Copyright (C) 2008-2018 Lorenzo Caminiti +// Distributed under the Boost Software License, Version 1.0 (see accompanying +// file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt). +// See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html + +// Test auto error after except (for free func, but same for all contracts). + +#include <boost/config.hpp> +// Not just __cplusplus to detect C++17 as MSVC defines it correctly sometimes. +#if (defined(__cplusplus) && __cplusplus >= 201703L) || \ + !defined(BOOST_NO_CXX17_IF_CONSTEXPR) + #error "C++17 copy elision invalidates test so forcing expected failure" +#else + +#include <boost/contract/function.hpp> + +int main() { + auto c = boost::contract::function() // Error (can't use auto). + .precondition([] {}) + .old([] {}) + .postcondition([] {}) + .except([] {}) + ; + return 0; +} + +#endif + diff --git a/src/boost/libs/contract/test/specify/except.cpp b/src/boost/libs/contract/test/specify/except.cpp new file mode 100644 index 000000000..791ba1148 --- /dev/null +++ b/src/boost/libs/contract/test/specify/except.cpp @@ -0,0 +1,37 @@ + +// Copyright (C) 2008-2018 Lorenzo Caminiti +// Distributed under the Boost Software License, Version 1.0 (see accompanying +// file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt). +// See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html + +// Test specifying except, no pre, old, or post (same if not free func). + +#include "../detail/oteststream.hpp" +#include <boost/contract/function.hpp> +#include <boost/contract/check.hpp> +#include <boost/detail/lightweight_test.hpp> +#include <sstream> + +boost::contract::test::detail::oteststream out; + +void f() { + boost::contract::check c = boost::contract::function() + .except([] { out << "f::except" << std::endl; }) + ; + 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/src/boost/libs/contract/test/specify/except_old_error.cpp b/src/boost/libs/contract/test/specify/except_old_error.cpp new file mode 100644 index 000000000..ea865e842 --- /dev/null +++ b/src/boost/libs/contract/test/specify/except_old_error.cpp @@ -0,0 +1,23 @@ + +// Copyright (C) 2008-2018 Lorenzo Caminiti +// Distributed under the Boost Software License, Version 1.0 (see accompanying +// file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt). +// See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html + +// Test old after except error (same if not free func). + +#include <boost/contract/function.hpp> +#include <boost/contract/check.hpp> + +void f() { + boost::contract::check c = boost::contract::function() + .except([] {}) + .old([] {}) // Error (old after except). + ; +} + +int main() { + f(); + return 0; +} + diff --git a/src/boost/libs/contract/test/specify/except_post_error.cpp b/src/boost/libs/contract/test/specify/except_post_error.cpp new file mode 100644 index 000000000..5b9ef354b --- /dev/null +++ b/src/boost/libs/contract/test/specify/except_post_error.cpp @@ -0,0 +1,23 @@ + +// Copyright (C) 2008-2018 Lorenzo Caminiti +// Distributed under the Boost Software License, Version 1.0 (see accompanying +// file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt). +// See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html + +// Test post after except error (same if not free func). + +#include <boost/contract/function.hpp> +#include <boost/contract/check.hpp> + +void f() { + boost::contract::check c = boost::contract::function() + .except([] {}) + .postcondition([] {}) // Error (post after except). + ; +} + +int main() { + f(); + return 0; +} + diff --git a/src/boost/libs/contract/test/specify/except_pre_error.cpp b/src/boost/libs/contract/test/specify/except_pre_error.cpp new file mode 100644 index 000000000..3b6906621 --- /dev/null +++ b/src/boost/libs/contract/test/specify/except_pre_error.cpp @@ -0,0 +1,23 @@ + +// Copyright (C) 2008-2018 Lorenzo Caminiti +// Distributed under the Boost Software License, Version 1.0 (see accompanying +// file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt). +// See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html + +// Test pre after except error (same if not free func). + +#include <boost/contract/function.hpp> +#include <boost/contract/check.hpp> + +void f() { + boost::contract::check c = boost::contract::function() + .except([] {}) + .precondition([] {}) // Error (pre after except). + ; +} + +int main() { + f(); + return 0; +} + diff --git a/src/boost/libs/contract/test/specify/missing_check.cpp b/src/boost/libs/contract/test/specify/missing_check.cpp new file mode 100644 index 000000000..7e6f01c0d --- /dev/null +++ b/src/boost/libs/contract/test/specify/missing_check.cpp @@ -0,0 +1,43 @@ + +// Copyright (C) 2008-2018 Lorenzo Caminiti +// Distributed under the Boost Software License, Version 1.0 (see accompanying +// file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt). +// See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html + +// Test missing contract check declaration gives run-time error. + +struct err {}; +#ifndef BOOST_CONTRACT_ON_MISSING_CHECK_DECL + #error "build must define ON_MISSING_CHECK_DECL=`{ throw err(); }`" +#endif + +#include <boost/contract/function.hpp> +#include <boost/contract/check.hpp> +#include <boost/detail/lightweight_test.hpp> + +int main() { + boost::contract::check c = boost::contract::function() // Test this is OK. + .precondition([] {}) + .old([] {}) + .postcondition([] {}) + ; + + try { + boost::contract::function() // Test no `check c = ...` errors. + .precondition([] {}) + .old([] {}) + .postcondition([] {}) + ; + #if !defined(BOOST_CONTRACT_NO_PRECONDITIONS) || \ + !defined(BOOST_CONTRACT_NO_POSTCONDITIONS) || \ + !defined(BOOST_CONTRACT_NO_INVARIANTS) + BOOST_TEST(false); // Error, must throw. + #endif + } catch(err const&) { + // OK, threw as expected. + } catch(...) { + BOOST_TEST(false); // Error, unexpected throw. + } + return boost::report_errors(); +} + diff --git a/src/boost/libs/contract/test/specify/nothing.cpp b/src/boost/libs/contract/test/specify/nothing.cpp new file mode 100644 index 000000000..b14a7c0c6 --- /dev/null +++ b/src/boost/libs/contract/test/specify/nothing.cpp @@ -0,0 +1,32 @@ + +// Copyright (C) 2008-2018 Lorenzo Caminiti +// Distributed under the Boost Software License, Version 1.0 (see accompanying +// file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt). +// See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html + +// Test no pre or post (for free func, but same for all contracts). + +#include "../detail/oteststream.hpp" +#include <boost/contract/function.hpp> +#include <boost/contract/check.hpp> +#include <boost/detail/lightweight_test.hpp> +#include <sstream> + +boost::contract::test::detail::oteststream out; + +void f() { + boost::contract::check c = boost::contract::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/src/boost/libs/contract/test/specify/old.cpp b/src/boost/libs/contract/test/specify/old.cpp new file mode 100644 index 000000000..a064d5f98 --- /dev/null +++ b/src/boost/libs/contract/test/specify/old.cpp @@ -0,0 +1,39 @@ + +// Copyright (C) 2008-2018 Lorenzo Caminiti +// Distributed under the Boost Software License, Version 1.0 (see accompanying +// file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt). +// See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html + +// Test specifying old, no pre, post, or except (same if not free func). + +#include "../detail/oteststream.hpp" +#include <boost/contract/function.hpp> +#include <boost/contract/check.hpp> +#include <boost/detail/lightweight_test.hpp> +#include <sstream> + +boost::contract::test::detail::oteststream out; + +void f() { + boost::contract::check c = boost::contract::function() + .old([] { out << "f::old" << std::endl; }) + ; + out << "f::body" << std::endl; +} + +int main() { + std::ostringstream ok; + + out.str(""); + f(); + ok.str(""); ok + #ifndef BOOST_CONTRACT_NO_OLDS + << "f::old" << std::endl + #endif + << "f::body" << std::endl + ; + BOOST_TEST(out.eq(ok.str())); + + return boost::report_errors(); +} + diff --git a/src/boost/libs/contract/test/specify/old_except.cpp b/src/boost/libs/contract/test/specify/old_except.cpp new file mode 100644 index 000000000..31af80668 --- /dev/null +++ b/src/boost/libs/contract/test/specify/old_except.cpp @@ -0,0 +1,41 @@ + +// Copyright (C) 2008-2018 Lorenzo Caminiti +// Distributed under the Boost Software License, Version 1.0 (see accompanying +// file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt). +// See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html + +// Test specifying old and except, no pre or post (same if not free func). + +#include "../detail/oteststream.hpp" +#include <boost/contract/function.hpp> +#include <boost/contract/check.hpp> +#include <boost/detail/lightweight_test.hpp> +#include <sstream> + +boost::contract::test::detail::oteststream out; + +void f() { + boost::contract::check c = boost::contract::function() + .old([] { out << "f::old" << std::endl; }) + .except([] { out << "f::except" << std::endl; }) + ; + out << "f::body" << std::endl; +} + +int main() { + std::ostringstream ok; + + out.str(""); + f(); + ok.str(""); + ok + #ifndef BOOST_CONTRACT_NO_OLDS + << "f::old" << std::endl + #endif + << "f::body" << std::endl + ; + BOOST_TEST(out.eq(ok.str())); + + return boost::report_errors(); +} + diff --git a/src/boost/libs/contract/test/specify/old_post.cpp b/src/boost/libs/contract/test/specify/old_post.cpp new file mode 100644 index 000000000..97f3eb02c --- /dev/null +++ b/src/boost/libs/contract/test/specify/old_post.cpp @@ -0,0 +1,44 @@ + +// Copyright (C) 2008-2018 Lorenzo Caminiti +// Distributed under the Boost Software License, Version 1.0 (see accompanying +// file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt). +// See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html + +// Test specifying old and post, no pre or except (same if not free func). + +#include "../detail/oteststream.hpp" +#include <boost/contract/function.hpp> +#include <boost/contract/check.hpp> +#include <boost/detail/lightweight_test.hpp> +#include <sstream> + +boost::contract::test::detail::oteststream out; + +void f() { + boost::contract::check c = boost::contract::function() + .old([] { out << "f::old" << std::endl; }) + .postcondition([] { out << "f::post" << std::endl; }) + ; + out << "f::body" << std::endl; +} + +int main() { + std::ostringstream ok; + + out.str(""); + f(); + ok.str(""); + ok + #ifndef BOOST_CONTRACT_NO_OLDS + << "f::old" << std::endl + #endif + << "f::body" << std::endl + #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS + << "f::post" << std::endl + #endif + ; + BOOST_TEST(out.eq(ok.str())); + + return boost::report_errors(); +} + diff --git a/src/boost/libs/contract/test/specify/old_post_except.cpp b/src/boost/libs/contract/test/specify/old_post_except.cpp new file mode 100644 index 000000000..36259e60f --- /dev/null +++ b/src/boost/libs/contract/test/specify/old_post_except.cpp @@ -0,0 +1,45 @@ + +// Copyright (C) 2008-2018 Lorenzo Caminiti +// Distributed under the Boost Software License, Version 1.0 (see accompanying +// file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt). +// See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html + +// Test specifying old, post, and except, not pre (same if not free func). + +#include "../detail/oteststream.hpp" +#include <boost/contract/function.hpp> +#include <boost/contract/check.hpp> +#include <boost/detail/lightweight_test.hpp> +#include <sstream> + +boost::contract::test::detail::oteststream out; + +void f() { + boost::contract::check c = boost::contract::function() + .old([] { out << "f::old" << std::endl; }) + .postcondition([] { out << "f::post" << std::endl; }) + .except([] { out << "f::except" << std::endl; }) + ; + out << "f::body" << std::endl; +} + +int main() { + std::ostringstream ok; + + out.str(""); + f(); + ok.str(""); + ok + #ifndef BOOST_CONTRACT_NO_OLDS + << "f::old" << std::endl + #endif + << "f::body" << std::endl + #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS + << "f::post" << std::endl + #endif + ; + BOOST_TEST(out.eq(ok.str())); + + return boost::report_errors(); +} + diff --git a/src/boost/libs/contract/test/specify/old_pre_error.cpp b/src/boost/libs/contract/test/specify/old_pre_error.cpp new file mode 100644 index 000000000..9d9548ce4 --- /dev/null +++ b/src/boost/libs/contract/test/specify/old_pre_error.cpp @@ -0,0 +1,23 @@ + +// Copyright (C) 2008-2018 Lorenzo Caminiti +// Distributed under the Boost Software License, Version 1.0 (see accompanying +// file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt). +// See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html + +// Test pre after old error (same if not free func). + +#include <boost/contract/function.hpp> +#include <boost/contract/check.hpp> + +void f() { + boost::contract::check c = boost::contract::function() + .old([] {}) + .precondition([] {}) // Error (pre after old). + ; +} + +int main() { + f(); + return 0; +} + diff --git a/src/boost/libs/contract/test/specify/post.cpp b/src/boost/libs/contract/test/specify/post.cpp new file mode 100644 index 000000000..4930c238a --- /dev/null +++ b/src/boost/libs/contract/test/specify/post.cpp @@ -0,0 +1,39 @@ + +// Copyright (C) 2008-2018 Lorenzo Caminiti +// Distributed under the Boost Software License, Version 1.0 (see accompanying +// file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt). +// See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html + +// Test specifying post, no pre, old, or except (same if not free func). + +#include "../detail/oteststream.hpp" +#include <boost/contract/function.hpp> +#include <boost/contract/check.hpp> +#include <boost/detail/lightweight_test.hpp> +#include <sstream> + +boost::contract::test::detail::oteststream out; + +void f() { + boost::contract::check c = boost::contract::function() + .postcondition([] { out << "f::post" << std::endl; }) + ; + out << "f::body" << std::endl; +} + +int main() { + std::ostringstream ok; + + out.str(""); + f(); + ok.str(""); ok + << "f::body" << std::endl + #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS + << "f::post" << std::endl + #endif + ; + BOOST_TEST(out.eq(ok.str())); + + return boost::report_errors(); +} + diff --git a/src/boost/libs/contract/test/specify/post_except.cpp b/src/boost/libs/contract/test/specify/post_except.cpp new file mode 100644 index 000000000..115ab6ef8 --- /dev/null +++ b/src/boost/libs/contract/test/specify/post_except.cpp @@ -0,0 +1,41 @@ + +// Copyright (C) 2008-2018 Lorenzo Caminiti +// Distributed under the Boost Software License, Version 1.0 (see accompanying +// file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt). +// See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html + +// Test specifying post and except, no pre or old (same if not free func). + +#include "../detail/oteststream.hpp" +#include <boost/contract/function.hpp> +#include <boost/contract/check.hpp> +#include <boost/detail/lightweight_test.hpp> +#include <sstream> + +boost::contract::test::detail::oteststream out; + +void f() { + boost::contract::check c = boost::contract::function() + .postcondition([] { out << "f::post" << std::endl; }) + .except([] { out << "f::except" << std::endl; }) + ; + out << "f::body" << std::endl; +} + +int main() { + std::ostringstream ok; + + out.str(""); + f(); + ok.str(""); + ok + << "f::body" << std::endl + #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS + << "f::post" << std::endl + #endif + ; + BOOST_TEST(out.eq(ok.str())); + + return boost::report_errors(); +} + diff --git a/src/boost/libs/contract/test/specify/post_old_error.cpp b/src/boost/libs/contract/test/specify/post_old_error.cpp new file mode 100644 index 000000000..7a3361a72 --- /dev/null +++ b/src/boost/libs/contract/test/specify/post_old_error.cpp @@ -0,0 +1,23 @@ + +// Copyright (C) 2008-2018 Lorenzo Caminiti +// Distributed under the Boost Software License, Version 1.0 (see accompanying +// file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt). +// See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html + +// Test old after post error (same if not free func). + +#include <boost/contract/function.hpp> +#include <boost/contract/check.hpp> + +void f() { + boost::contract::check c = boost::contract::function() + .postcondition([] {}) + .old([] {}) // Error (old after post). + ; +} + +int main() { + f(); + return 0; +} + diff --git a/src/boost/libs/contract/test/specify/post_pre_error.cpp b/src/boost/libs/contract/test/specify/post_pre_error.cpp new file mode 100644 index 000000000..3e50b5338 --- /dev/null +++ b/src/boost/libs/contract/test/specify/post_pre_error.cpp @@ -0,0 +1,23 @@ + +// Copyright (C) 2008-2018 Lorenzo Caminiti +// Distributed under the Boost Software License, Version 1.0 (see accompanying +// file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt). +// See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html + +// Test pre after post error (same if not free func). + +#include <boost/contract/function.hpp> +#include <boost/contract/check.hpp> + +void f() { + boost::contract::check c = boost::contract::function() + .postcondition([] {}) + .precondition([] {}) // Error (pre after post). + ; +} + +int main() { + f(); + return 0; +} + diff --git a/src/boost/libs/contract/test/specify/pre.cpp b/src/boost/libs/contract/test/specify/pre.cpp new file mode 100644 index 000000000..4c02acd2b --- /dev/null +++ b/src/boost/libs/contract/test/specify/pre.cpp @@ -0,0 +1,39 @@ + +// Copyright (C) 2008-2018 Lorenzo Caminiti +// Distributed under the Boost Software License, Version 1.0 (see accompanying +// file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt). +// See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html + +// Test specifying pre, no old, post, or except (same if not free func). + +#include "../detail/oteststream.hpp" +#include <boost/contract/function.hpp> +#include <boost/contract/check.hpp> +#include <boost/detail/lightweight_test.hpp> +#include <sstream> + +boost::contract::test::detail::oteststream out; + +void f() { + boost::contract::check c = boost::contract::function() + .precondition([] { out << "f::pre" << std::endl; }) + ; + out << "f::body" << std::endl; +} + +int main() { + std::ostringstream ok; + + out.str(""); + f(); + ok.str(""); ok + #ifndef BOOST_CONTRACT_NO_PRECONDITIONS + << "f::pre" << std::endl + #endif + << "f::body" << std::endl + ; + BOOST_TEST(out.eq(ok.str())); + + return boost::report_errors(); +} + diff --git a/src/boost/libs/contract/test/specify/pre_except.cpp b/src/boost/libs/contract/test/specify/pre_except.cpp new file mode 100644 index 000000000..1e7095ce5 --- /dev/null +++ b/src/boost/libs/contract/test/specify/pre_except.cpp @@ -0,0 +1,41 @@ + +// Copyright (C) 2008-2018 Lorenzo Caminiti +// Distributed under the Boost Software License, Version 1.0 (see accompanying +// file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt). +// See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html + +// Test specifying pre and except, no old or post (same if not free func). + +#include "../detail/oteststream.hpp" +#include <boost/contract/function.hpp> +#include <boost/contract/check.hpp> +#include <boost/detail/lightweight_test.hpp> +#include <sstream> + +boost::contract::test::detail::oteststream out; + +void f() { + boost::contract::check c = boost::contract::function() + .precondition([] { out << "f::pre" << std::endl; }) + .except([] { out << "f::except" << std::endl; }) + ; + out << "f::body" << std::endl; +} + +int main() { + std::ostringstream ok; + + out.str(""); + f(); + ok.str(""); + ok + #ifndef BOOST_CONTRACT_NO_PRECONDITIONS + << "f::pre" << std::endl + #endif + << "f::body" << std::endl + ; + BOOST_TEST(out.eq(ok.str())); + + return boost::report_errors(); +} + diff --git a/src/boost/libs/contract/test/specify/pre_old.cpp b/src/boost/libs/contract/test/specify/pre_old.cpp new file mode 100644 index 000000000..8c1cc763b --- /dev/null +++ b/src/boost/libs/contract/test/specify/pre_old.cpp @@ -0,0 +1,44 @@ + +// Copyright (C) 2008-2018 Lorenzo Caminiti +// Distributed under the Boost Software License, Version 1.0 (see accompanying +// file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt). +// See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html + +// Test specifying pre and old, no post or except (same if not free func). + +#include "../detail/oteststream.hpp" +#include <boost/contract/function.hpp> +#include <boost/contract/check.hpp> +#include <boost/detail/lightweight_test.hpp> +#include <sstream> + +boost::contract::test::detail::oteststream out; + +void f() { + boost::contract::check c = boost::contract::function() + .precondition([] { out << "f::pre" << std::endl; }) + .old([] { out << "f::old" << std::endl; }) + ; + out << "f::body" << std::endl; +} + +int main() { + std::ostringstream ok; + + out.str(""); + f(); + ok.str(""); + ok + #ifndef BOOST_CONTRACT_NO_PRECONDITIONS + << "f::pre" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_OLDS + << "f::old" << std::endl + #endif + << "f::body" << std::endl + ; + BOOST_TEST(out.eq(ok.str())); + + return boost::report_errors(); +} + diff --git a/src/boost/libs/contract/test/specify/pre_old_except.cpp b/src/boost/libs/contract/test/specify/pre_old_except.cpp new file mode 100644 index 000000000..99de5bc29 --- /dev/null +++ b/src/boost/libs/contract/test/specify/pre_old_except.cpp @@ -0,0 +1,45 @@ + +// Copyright (C) 2008-2018 Lorenzo Caminiti +// Distributed under the Boost Software License, Version 1.0 (see accompanying +// file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt). +// See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html + +// Test specify pre, old, and except, no post (same if not free func). + +#include "../detail/oteststream.hpp" +#include <boost/contract/function.hpp> +#include <boost/contract/check.hpp> +#include <boost/detail/lightweight_test.hpp> +#include <sstream> + +boost::contract::test::detail::oteststream out; + +void f() { + boost::contract::check c = boost::contract::function() + .precondition([] { out << "f::pre" << std::endl; }) + .old([] { out << "f::old" << std::endl; }) + .except([] { out << "f::except" << std::endl; }) + ; + out << "f::body" << std::endl; +} + +int main() { + std::ostringstream ok; + + out.str(""); + f(); + ok.str(""); + ok + #ifndef BOOST_CONTRACT_NO_PRECONDITIONS + << "f::pre" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_OLDS + << "f::old" << std::endl + #endif + << "f::body" << std::endl + ; + BOOST_TEST(out.eq(ok.str())); + + return boost::report_errors(); +} + diff --git a/src/boost/libs/contract/test/specify/pre_old_post.cpp b/src/boost/libs/contract/test/specify/pre_old_post.cpp new file mode 100644 index 000000000..0ea576f29 --- /dev/null +++ b/src/boost/libs/contract/test/specify/pre_old_post.cpp @@ -0,0 +1,48 @@ + +// Copyright (C) 2008-2018 Lorenzo Caminiti +// Distributed under the Boost Software License, Version 1.0 (see accompanying +// file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt). +// See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html + +// Test specifying pre, old, and post, no except (same if not free func). + +#include "../detail/oteststream.hpp" +#include <boost/contract/function.hpp> +#include <boost/contract/check.hpp> +#include <boost/detail/lightweight_test.hpp> +#include <sstream> + +boost::contract::test::detail::oteststream out; + +void f() { + boost::contract::check c = boost::contract::function() + .precondition([] { out << "f::pre" << std::endl; }) + .old([] { out << "f::old" << std::endl; }) + .postcondition([] { out << "f::post" << std::endl; }) + ; + out << "f::body" << std::endl; +} + +int main() { + std::ostringstream ok; + + out.str(""); + f(); + ok.str(""); + ok + #ifndef BOOST_CONTRACT_NO_PRECONDITIONS + << "f::pre" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_OLDS + << "f::old" << std::endl + #endif + << "f::body" << std::endl + #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS + << "f::post" << std::endl + #endif + ; + BOOST_TEST(out.eq(ok.str())); + + return boost::report_errors(); +} + diff --git a/src/boost/libs/contract/test/specify/pre_old_post_except.cpp b/src/boost/libs/contract/test/specify/pre_old_post_except.cpp new file mode 100644 index 000000000..b69929066 --- /dev/null +++ b/src/boost/libs/contract/test/specify/pre_old_post_except.cpp @@ -0,0 +1,49 @@ + +// Copyright (C) 2008-2018 Lorenzo Caminiti +// Distributed under the Boost Software License, Version 1.0 (see accompanying +// file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt). +// See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html + +// Test specifying pre, old, post, and except (same if not free func). + +#include "../detail/oteststream.hpp" +#include <boost/contract/function.hpp> +#include <boost/contract/check.hpp> +#include <boost/detail/lightweight_test.hpp> +#include <sstream> + +boost::contract::test::detail::oteststream out; + +void f() { + boost::contract::check c = boost::contract::function() + .precondition([] { out << "f::pre" << std::endl; }) + .old([] { out << "f::old" << std::endl; }) + .postcondition([] { out << "f::post" << std::endl; }) + .except([] { out << "f::except" << std::endl; }) + ; + out << "f::body" << std::endl; +} + +int main() { + std::ostringstream ok; + + out.str(""); + f(); + ok.str(""); + ok + #ifndef BOOST_CONTRACT_NO_PRECONDITIONS + << "f::pre" << std::endl + #endif + #ifndef BOOST_CONTRACT_NO_OLDS + << "f::old" << std::endl + #endif + << "f::body" << std::endl + #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS + << "f::post" << std::endl + #endif + ; + BOOST_TEST(out.eq(ok.str())); + + return boost::report_errors(); +} + diff --git a/src/boost/libs/contract/test/specify/pre_post.cpp b/src/boost/libs/contract/test/specify/pre_post.cpp new file mode 100644 index 000000000..ecedebf54 --- /dev/null +++ b/src/boost/libs/contract/test/specify/pre_post.cpp @@ -0,0 +1,44 @@ + +// Copyright (C) 2008-2018 Lorenzo Caminiti +// Distributed under the Boost Software License, Version 1.0 (see accompanying +// file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt). +// See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html + +// Test specifying pre and post, no old or except (same if not free func). + +#include "../detail/oteststream.hpp" +#include <boost/contract/function.hpp> +#include <boost/contract/check.hpp> +#include <boost/detail/lightweight_test.hpp> +#include <sstream> + +boost::contract::test::detail::oteststream out; + +void f() { + boost::contract::check c = boost::contract::function() + .precondition([] { out << "f::pre" << std::endl; }) + .postcondition([] { out << "f::post" << std::endl; }) + ; + out << "f::body" << std::endl; +} + +int main() { + std::ostringstream ok; + + out.str(""); + f(); + ok.str(""); + ok + #ifndef BOOST_CONTRACT_NO_PRECONDITIONS + << "f::pre" << std::endl + #endif + << "f::body" << std::endl + #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS + << "f::post" << std::endl + #endif + ; + BOOST_TEST(out.eq(ok.str())); + + return boost::report_errors(); +} + diff --git a/src/boost/libs/contract/test/specify/pre_post_except.cpp b/src/boost/libs/contract/test/specify/pre_post_except.cpp new file mode 100644 index 000000000..1b22e2ec4 --- /dev/null +++ b/src/boost/libs/contract/test/specify/pre_post_except.cpp @@ -0,0 +1,45 @@ + +// Copyright (C) 2008-2018 Lorenzo Caminiti +// Distributed under the Boost Software License, Version 1.0 (see accompanying +// file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt). +// See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html + +// Test specify pre, post, and except, no old (same if not free func). + +#include "../detail/oteststream.hpp" +#include <boost/contract/function.hpp> +#include <boost/contract/check.hpp> +#include <boost/detail/lightweight_test.hpp> +#include <sstream> + +boost::contract::test::detail::oteststream out; + +void f() { + boost::contract::check c = boost::contract::function() + .precondition([] { out << "f::pre" << std::endl; }) + .postcondition([] { out << "f::post" << std::endl; }) + .except([] { out << "f::except" << std::endl; }) + ; + out << "f::body" << std::endl; +} + +int main() { + std::ostringstream ok; + + out.str(""); + f(); + ok.str(""); + ok + #ifndef BOOST_CONTRACT_NO_PRECONDITIONS + << "f::pre" << std::endl + #endif + << "f::body" << std::endl + #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS + << "f::post" << std::endl + #endif + ; + BOOST_TEST(out.eq(ok.str())); + + return boost::report_errors(); +} + |