Simple mechanism for contract specification and enforcement
Description
Autoware should have a standard practice for specification and enforcement of contracts between functions. This issue is to discuss what that practice could look like and how it might be implemented.
Specification points to discuss:
- How to integrate contract specification into current documentation
- This may be as simple as adding a statement to the 'Assumptions' section of design docs that a certain assumption is enforced via contract
- The practice should be able to be integrated directly with general requirements specification and traceability in the project.
- See: Doorstop proposal and Doorstop example
- This probably achievable through comment tags in the code(?)
Implementation proposal:
- The practice should be as compatible as possible with the C++20 contracts proposals
- Create a contract library within each package. For each function in the package for which a contract will be enforced the library should have:
- Exactly one function of the same signature that checks pre-conditions
- This function would act as a container for all
expects
checks in a C++20 contract
- This function would act as a container for all
- Exactly one function of the same signature that checks post-conditions
- This function would act as a container for all
ensures
checks in a C++20 contract
- This function would act as a container for all
- Zero or more functions that check invariants
- These functions would correspond 1-to-1 with
assert
checks in a C++20 contract
- These functions would correspond 1-to-1 with
- All pre-/post- and invariant checks should be non-throwing and marked
noexcept
- All pre-/post- and invariant checks should have the same return type
- (What should the naming convention be for these functions?)
- Exactly one function of the same signature that checks pre-conditions
- Create a global 'contracts' package that contains:
- Design documentation around contract handling with tutorials and pointers to examples
- A "contract return type" to be used by all condition checks:
- It should contain information about whether the check passed or failed and, on failure, human interpretable information about why it failed. (Ideally it should be similar to the proposed
std::contract_violation
type.) - It should be castable to a boolean value true/false (pass/fail)
- It should contain information about whether the check passed or failed and, on failure, human interpretable information about why it failed. (Ideally it should be similar to the proposed
- A "violation handler" class that can be used to respond to failed condition checks.
- In Autoware's current error handling scheme, this would probably throw an exception for any contract check that returns false. In the future this could also send a signal some kind of system health monitor.
- It should be possible to classify checks (as in C++20 proposal):
-
default
: These low-cost checks that can be run online during normal system operation. -
audit
: These higher-cost checks that should only be run during testing/validation.
-
- It should be possible to choose which types of checks are run at compile time (as in C++20 proposal):
-
off
: Do not run any contract enforcement -
default
: Only run checks marked asdefault
-
audit
: Rundefault
andaudit
checks
-
Definition of Done
-
Choose a node to act as an initial trial actually using contracts. -
Reach sufficient consensus that contracts can be implemented for the chosen initial node
Other
- #522 (closed) Has some utilities that will be useful for contract enforcement
Edited by Jeffrey Kane Johnson