Skip to content

Commit

Permalink
docs: update documentation
Browse files Browse the repository at this point in the history
  • Loading branch information
abdes committed Jul 14, 2023
1 parent e123836 commit c31717c
Show file tree
Hide file tree
Showing 4 changed files with 182 additions and 49 deletions.
27 changes: 25 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,29 @@ the implementation of
Additionally, optional helpers for unit testing contracts without the need for
death tests are provided as a separate library.

Examples of usage include:
```c++
// The simplest contract
ASAP_EXPECT(x !=0);

// Expect
ASAP_EXPECT(x > 0, "should not be > 0 but I got " << x);

// Assert
ASAP_ASSERT(x > 0, "should not be > 0 but I got " << x);

// Assert that some code branch is unreachable, e.g. after a fully covered
// switch / case statement.
ASAP_ASSERT_UNREACHABLE("should never reach here")

// Assert with complex expression (note the true at the start to avoid starting
// the expression with parenthesis), assertion failure message and a return
// value in case of the assertion failure and the violation handler does not
// abort; also to keep the compiler happy with the return statement.
ASAP_ENSURE(true && ((0<x) || (x == -1)), "failed", Result::kFailed);

```
For a full documentation of what is available refer to the
[project docs](https://asap-projects.github.io/asap-contract/).
Expand All @@ -48,8 +71,8 @@ We have detailed guides for setting up an efficient development environment, the
development process, project structure, etc. Take a look at the available guides
[here](https://abdes.github.io/asap/asap_master/html/).
In addition to that, specific documentation for the command line parser, its
usage and APIs, are provided in the project GitHub Pages site
In addition to that, specific documentation for the contract checking module,
its usage and APIs, are provided in the project GitHub Pages site
[here](https://asap-projects.github.io/asap-contract/asap_contract_master/html/).
## Getting Started
Expand Down
196 changes: 149 additions & 47 deletions contract/include/contract/contract.h
Original file line number Diff line number Diff line change
Expand Up @@ -135,17 +135,6 @@ ASAP_CONTRACT_API auto GetViolationHandler() -> ViolationHandler&;

// --- Default mode macros -----------------------------------------------------

/*!
* \brief Defines a precondition.
*
* A precondition describes the function's expectation of its arguments and/or
* the state of other objects upon entry into the function and is usually placed
* at the start of a function body.
*
* \note The prediction is ignored if the contract checking build mode is `OFF`.
*
* \param cond an expression, that specifies the predicate of the contract.
*/
#define ASAP_EX_3_(condition, message, return_value) \
ASAP_EX_CHECK_(ASAP_CONTRACT_MODE_DEFAULT_, condition, message, return_value)
#define ASAP_EX_2_(condition, message) ASAP_EX_3_(condition, message, )
Expand All @@ -157,18 +146,40 @@ ASAP_CONTRACT_API auto GetViolationHandler() -> ViolationHandler&;
#define ASAP_EX_SELECT_(...) \
ASAP_EX_BY_ARG_COUNT_(ASAP_EX_NO_ARG_EXPANDER_ __VA_ARGS__())
#define ASAP_EXPECT(...) ASAP_EX_SELECT_(__VA_ARGS__)(__VA_ARGS__)

/*!
* Defines a post-condition.
* \def ASAP_EXPECT
*
* A post-condition is a condition that a function should ensure for the return
* value and/or the state of objects upon exit from the function and is usually
* placed immediately before returning control to the caller of the function.
* \brief Defines a precondition.
*
* \note The post-condition is ignored if the contract checking build mode is
* `OFF`.
* A precondition describes the function's expectation of its arguments and/or
* the state of other objects upon entry into the function and is usually placed
* at the start of a function body.
*
* The macro can be invoked in multiple forms depending on whether a detailed
* failure message needs to be printed when the condition fails and whether the
* assertion is in a function that returns a value or not.
*
* The accompanying message is sent to an output stream before being printed to
* the standard error output. Therefore, it is possible to chain multiple
* message chunks using the `<<` operator.
*
* \code{.cpp}
ASAP_EXPECT(cond,
"failed, was expecting: " << expected << " but got: " << actual)
* \endcode
*
* The default handler aborts when an assertion fails, but it can be customized
* not to do so. The macro always has a return statement, and therefore, if it
* is located in a function that requires a return value, such value can be
* specified in the macro. This is not needed if the function does not return a
* value.
*
* \param cond an expression, that specifies the predicate of the contract.
* \code{.cpp}
* ASAP_EXPECT(cond, "failed, and will return a default value",
* Result:kDefault);
* \endcode
*
* \note The prediction is ignored if the contract checking build mode is `OFF`.
*/
#define ASAP_EN_3_(condition, message, return_value) \
ASAP_EN_CHECK_(ASAP_CONTRACT_MODE_DEFAULT_, condition, message, return_value)
Expand All @@ -183,14 +194,39 @@ ASAP_CONTRACT_API auto GetViolationHandler() -> ViolationHandler&;
#define ASAP_ENSURE(...) ASAP_EN_CHOOSE_(__VA_ARGS__)(__VA_ARGS__)

/*!
* \brief Defines an assertion.
* \def ASAP_ENSURE
* \brief Defines a post-condition.
*
* An assertion is a condition that should be satisfied where it appears in a
* function body and can be placed anywhere within the body of a function.
* A post-condition is a condition that a function should ensure for the return
* value and/or the state of objects upon exit from the function and is usually
* placed immediately before returning control to the caller of the function.
*
* \note The assertion is ignored if the contract checking build mode is `OFF`.
* The macro can be invoked in multiple forms depending on whether a detailed
* failure message needs to be printed when the condition fails and whether the
* assertion is in a function that returns a value or not.
*
* The accompanying message is sent to an output stream before being printed to
* the standard error output. Therefore, it is possible to chain multiple
* message chunks using the `<<` operator.
*
* \param cond an expression, that specifies the predicate of the contract.
* \code{.cpp}
* ASAP_ENSURE(cond, "failed, was supposed to be: " << expected << " but is: "
* << actual)
* \endcode
*
* The default handler aborts when an assertion fails, but it can be customized
* not to do so. The macro always has a return statement, and therefore, if it
* is located in a function that requires a return value, such value can be
* specified in the macro. This is not needed if the function does not return a
* value.
*
* \code{.cpp}
* ASAP_ENSURE(cond, "failed, and will return a default value",
* Result:kDefault);
* \endcode
*
* \note The post-condition is ignored if the contract checking build mode is
* `OFF`.
*/
#define ASAP_A_3_(condition, message, return_value) \
ASAP_A_CHECK_(ASAP_CONTRACT_MODE_DEFAULT_, condition, message, return_value)
Expand All @@ -205,16 +241,39 @@ ASAP_CONTRACT_API auto GetViolationHandler() -> ViolationHandler&;
#define ASAP_ASSERT(...) ASAP_A_CHOOSE_(__VA_ARGS__)(__VA_ARGS__)

/*!
* \brief Defines a constexpr assertion macro.
* \def ASAP_ASSERT
* \brief Defines an assertion.
*
* In a `constexpr` context, if the condition fails, the code fails to compile.
* In a non-`constexpr` context, if the condition fails, message is printed to
* error output and the application aborts.
* An assertion is a condition that should be satisfied where it appears in a
* function body and can be placed anywhere within the body of a function.
*
* \note The assertion is ignored if the contract checking build mode is `OFF`.
* The macro can be invoked in multiple forms depending on whether a detailed
* failure message needs to be printed when the condition fails and whether the
* assertion is in a function that returns a value or not.
*
* The accompanying message is sent to an output stream before being printed to
* the standard error output. Therefore, it is possible to chain multiple
* message chunks using the `<<` operator.
*
* \param cond an expression, that specifies the predicate of the contract.
* \code{.cpp}
* ASAP_ASSERT(cond, "failed, was supposed to be: " << expected << " but is: "
* << actual)
* \endcode
*
* The default handler aborts when an assertion fails, but it can be customized
* not to do so. The macro always has a return statement, and therefore, if it
* is located in a function that requires a return value, such value can be
* specified in the macro. This is not needed if the function does not return a
* value.
*
* \code{.cpp}
* ASAP_ASSERT(cond, "failed, and will return a default value",
* Result:kDefault);
* \endcode
*
* \note The assertion is ignored if the contract checking build mode is `OFF`.
*/

#define ASAP_C_A_2_(condition, message) \
ASAP_C_A_CHECK_(ASAP_C_A_MODE_DEFAULT_, condition, message)
#define ASAP_C_A_1_(condition) ASAP_C_A_2_(condition, )
Expand All @@ -225,16 +284,30 @@ ASAP_CONTRACT_API auto GetViolationHandler() -> ViolationHandler&;
#define ASAP_C_A_CHOOSE_(...) \
ASAP_C_A_BY_ARG_COUNT_(ASAP_C_A_NO_ARG_EXPANDER_ __VA_ARGS__())
#define ASAP_CONSTEXPR_ASSERT(...) ASAP_C_A_CHOOSE_(__VA_ARGS__)(__VA_ARGS__)

/*!
* \brief Defines an assertion macro for unreachable code.
* \def ASAP_CONSTEXPR_ASSERT
* \brief Defines a constexpr assertion macro.
*
* If code marked with this macro is reached, `message` is printed to error
* output and the application aborts.
* In a `constexpr` context, if the condition fails, the code fails to compile.
* In a non-`constexpr` context, if the condition fails, message is printed to
* error output and the application aborts.
*
* \note The assertion is ignored if the contract checking build mode is `OFF`.
* The macro can be invoked in multiple forms depending on whether a detailed
* failure message needs to be printed when the condition fails and whether the
* assertion is in a function that returns a value or not.
*
* \param cond an expression, that specifies the predicate of the contract.
* The accompanying message is sent to an output stream before being printed to
* the standard error output. Therefore, it is possible to chain multiple
* message chunks using the `<<` operator.
*
* \code{.cpp}
* constexpr int divide(int a, int b)
* {
* return ASAP_CONSTEXPR_ASSERT(b, "divide(): can't divide by zero"), a / b;
* }
* \endcode
*
* \note The assertion is ignored if the contract checking build mode is `OFF`.
*/

#define ASAP_A_U_1_(message) ASAP_A_U_CHECK_(ASAP_A_U_MODE_DEFAULT_, message)
Expand All @@ -245,6 +318,26 @@ ASAP_CONTRACT_API auto GetViolationHandler() -> ViolationHandler&;
#define ASAP_A_U_SELECT_(...) \
ASAP_A_U_BY_ARG_COUNT_(ASAP_A_U_NO_ARG_EXPANDER_ __VA_ARGS__())
#define ASAP_ASSERT_UNREACHABLE(...) ASAP_A_U_SELECT_(__VA_ARGS__)(__VA_ARGS__)
/*!
* \def ASAP_ASSERT_UNREACHABLE
* \brief Defines an assertion macro for unreachable code.
*
* If code marked with this macro is reached, `message` is printed to error
* output and the application aborts.
*
* \code{.cpp}
* void Unreachable(int value)
* {
* if (value == 5) {
* value += 2;
* (void)value;
* }
* ASAP_ASSERT_UNREACHABLE("unreachable code")
* }
* \endcode
*
* \note The assertion is ignored if the contract checking build mode is `OFF`.
*/

// --- Audit mode macros -------------------------------------------------------

Expand All @@ -258,7 +351,10 @@ ASAP_CONTRACT_API auto GetViolationHandler() -> ViolationHandler&;
* \note The precondition is enforced only if the contract checking build mode
* is `AUDIT`.
*
* \param cond an expression, that specifies the predicate of the contract.
* \param condition an expression, that specifies the predicate of the contract.
* \param message an optional description message.
* \param return_value an optional return value if the macro is in function that
* requires one.
*/
#define ASAP_EXPECT_AUDIT(condition, message, return_value) \
ASAP_EX_CHECK_(ASAP_CONTRACT_MODE_AUDIT_, condition, message, return_value)
Expand All @@ -273,7 +369,10 @@ ASAP_CONTRACT_API auto GetViolationHandler() -> ViolationHandler&;
* \note The post-condition is enforced only if the contract checking build mode
* is `AUDIT`.
*
* \param cond an expression, that specifies the predicate of the contract.
* \param condition an expression, that specifies the predicate of the contract.
* \param message an optional description message.
* \param return_value an optional return value if the macro is in function that
* requires one.
*/
#define ASAP_ENSURE_AUDIT(condition, message, return_value) \
ASAP_EN_CHECK_(ASAP_CONTRACT_MODE_AUDIT_, condition, message, return_value)
Expand All @@ -287,7 +386,10 @@ ASAP_CONTRACT_API auto GetViolationHandler() -> ViolationHandler&;
* \note The assertion is enforced only if the contract checking build mode is
* `AUDIT`.
*
* \param cond an expression, that specifies the predicate of the contract.
* \param condition an expression, that specifies the predicate of the contract.
* \param message an optional description message.
* \param return_value an optional return value if the macro is in function that
* requires one.
*/
#define ASAP_ASSERT_AUDIT(condition, message, return_value) \
ASAP_A_CHECK_(ASAP_CONTRACT_MODE_AUDIT_, condition, message, return_value)
Expand All @@ -296,16 +398,16 @@ ASAP_CONTRACT_API auto GetViolationHandler() -> ViolationHandler&;
// Internal macros
// -----------------------------------------------------------------------------

#define ASAP_SELECT_4_(_f1, _f2, _f3, _f4, ...) _f4
#define ASAP_COMPOSE_4_(args) ASAP_SELECT_4_ args
#define ASAP_SELECT_3_(_f1, _f2, _f3, ...) _f3
#define ASAP_COMPOSE_3_(args) ASAP_SELECT_3_ args
#define ASAP_SELECT_2_(_f1, _f2, ...) _f2
#define ASAP_COMPOSE_2_(args) ASAP_SELECT_2_ args

// Exclude internal macros from doxygen documentation
// Exclude all internal macros from doxygen documentation
#if !defined(DOXYGEN_DOCUMENTATION_BUILD)

# define ASAP_SELECT_4_(_f1, _f2, _f3, _f4, ...) _f4
# define ASAP_COMPOSE_4_(args) ASAP_SELECT_4_ args
# define ASAP_SELECT_3_(_f1, _f2, _f3, ...) _f3
# define ASAP_COMPOSE_3_(args) ASAP_SELECT_3_ args
# define ASAP_SELECT_2_(_f1, _f2, ...) _f2
# define ASAP_COMPOSE_2_(args) ASAP_SELECT_2_ args

/* Helper macros */
# define ASAP_EX_CHECK_(check, condition, message, return_value) \
check(ASAP_CONTRACT_TYPE_EXPECT_, condition, message, return_value)
Expand Down
3 changes: 3 additions & 0 deletions doc/contract-ut/api/contract-ut.rst
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,13 @@ Google Test (other frameworks can be easily added) that do not require the use
of death tests.

.. doxygendefine:: CHECK_VIOLATES_CONTRACT
:project: asap_contract-ut

.. doxygendefine:: EXPECT_VIOLATES_CONTRACT
:project: asap_contract-ut

.. doxygendefine:: ASSERT_VIOLATES_CONTRACT
:project: asap_contract-ut

Example
=======
Expand Down
5 changes: 5 additions & 0 deletions doc/contract/api/contract.rst
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,11 @@ Default mode macros

.. doxygendefine:: ASAP_ASSERT

.. doxygendefine:: ASAP_CONSTEXPR_ASSERT

.. doxygendefine:: ASAP_ASSERT_UNREACHABLE


Audit mode macros
-------------------

Expand Down

0 comments on commit c31717c

Please sign in to comment.