blob: c181416cdac33cafc9411edfd276db6882ba7916 [file] [log] [blame]
.. _chapter-pw-assert:
.. default-domain:: cpp
.. highlight:: cpp
=========
pw_assert
=========
--------
Overview
--------
Pigweed's assert module provides facilities for applications to check
preconditions. The module is split into two components:
1. The facade (this module) which is only a macro interface layer
2. The backend, provided elsewhere, that implements the low level checks
All behaviour is controlled by the backend.
The ``pw_assert`` public API provides three classes of macros:
+-----------------------------------------+--------------------------------+
| PW_CRASH(format, ...) | Trigger a crash with a message |
+-----------------------------------------+--------------------------------+
| PW_CHECK(condition[, format, ...]) | Assert a condition, optionally |
| | with a message |
+-----------------------------------------+--------------------------------+
| PW_CHECK_<type>_<cmp>(a, b[, fmt, ...]) | Assert that the expression |
| | ``a <cmp> b`` is true, |
| | optionally with a message. |
+-----------------------------------------+--------------------------------+
.. tip::
All of the assert macros optionally support a message with additional
arguments, to assist in debugging when an assert triggers:
.. code-block:: cpp
PW_CHECK_INT_LE(ItemCount(), 100);
PW_CHECK_INT_LE(ItemCount(), 100, "System state: %s", GetStateStr());
Compatibility
-------------
The facade is compatible with C and C++.
Example
-------
.. code-block:: cpp
#include "pw_assert/assert.h"
int main() {
bool sensor_running = StartSensor(&msg);
PW_CHECK(sensor_running, "Sensor failed to start; code: %s", msg);
int temperature_c = ReadSensorCelcius();
PW_CHECK_INT_LE(temperature_c, 100,
"System is way out of heat spec; state=%s",
ReadSensorStateString());
}
---------------------------
Assert facade API reference
---------------------------
The below functions describe the assert API functions that applications should
invoke to assert.
.. cpp:function:: PW_CRASH(format, ...)
Trigger a crash with a message. Replaces LOG_FATAL() in other systems. Can
include a message with format arguments; for example:
.. code-block:: cpp
PW_CRASH("Unexpected: frobnitz in state: %s", frobnitz_state);
Note: ``PW_CRASH`` is the equivalent of ``LOG_FATAL`` in other systems, where
a device crash is triggered with a message. In Pigweed, logging and
crashing/asserting are separated. There is a ``LOG_CRITICAL`` level in the
logging module, but it does not have side effects; for ``LOG_FATAL``, instead
use this macro (``PW_CRASH``).
.. cpp:function:: PW_CHECK(condition)
.. cpp:function:: PW_CHECK(condition, format, ...)
Assert that a condition is true, optionally including a message with
arguments to report if the codition is false.
.. code-block:: cpp
PW_CHECK(StartTurbines());
PW_CHECK(StartWarpDrive(), "Oddly warp drive couldn't start; ruh-roh!");
.. cpp:function:: PW_CHECK_TYPE_OP(a, b)
.. cpp:function:: PW_CHECK_TYPE_OP(a, b, format, ...)
Asserts that ``a OP b`` is true, where ``a`` and ``b`` are converted to
``TYPE``; with ``OP`` and ``TYPE`` described below.
If present, the optional format message is reported on failure. Depending on
the backend, values of ``a`` and ``b`` will also be reported.
Example, with no message:
.. code-block:: cpp
PW_CHECK_INT_LE(CurrentTemperature(), 100);
PW_CHECK_INT_LE(ItemCount(), 100);
Example, with an included message and arguments:
.. code-block:: cpp
PW_CHECK_FLOAT_GE(BatteryVoltage(), 3.2, "System state=%s", SysState());
Below is the full list of binary comparison assert macros, along with the
type specifier. The specifier is irrelevant to application authors but is
needed for backend implementers.
+-------------------+--------------+-----------+-----------------------+
| Macro | a, b type | condition | a, b format specifier |
+-------------------+--------------+-----------+-----------------------+
| PW_CHECK_INT_LE | int | a <= b | %d |
+-------------------+--------------+-----------+-----------------------+
| PW_CHECK_INT_LT | int | a < b | %d |
+-------------------+--------------+-----------+-----------------------+
| PW_CHECK_INT_GE | int | a >= b | %d |
+-------------------+--------------+-----------+-----------------------+
| PW_CHECK_INT_GT | int | a > b | %d |
+-------------------+--------------+-----------+-----------------------+
| PW_CHECK_INT_EQ | int | a == b | %d |
+-------------------+--------------+-----------+-----------------------+
| PW_CHECK_UINT_LE | unsigned int | a <= b | %u |
+-------------------+--------------+-----------+-----------------------+
| PW_CHECK_UINT_LT | unsigned int | a < b | %u |
+-------------------+--------------+-----------+-----------------------+
| PW_CHECK_UINT_GE | unsigned int | a >= b | %u |
+-------------------+--------------+-----------+-----------------------+
| PW_CHECK_UINT_GT | unsigned int | a > b | %u |
+-------------------+--------------+-----------+-----------------------+
| PW_CHECK_UINT_EQ | unsigned int | a == b | %u |
+-------------------+--------------+-----------+-----------------------+
| PW_CHECK_FLOAT_LE | float | a <= b | %f |
+-------------------+--------------+-----------+-----------------------+
| PW_CHECK_FLOAT_LT | float | a < b | %f |
+-------------------+--------------+-----------+-----------------------+
| PW_CHECK_FLOAT_GE | float | a >= b | %f |
+-------------------+--------------+-----------+-----------------------+
| PW_CHECK_FLOAT_GT | float | a > b | %f |
+-------------------+--------------+-----------+-----------------------+
| PW_CHECK_FLOAT_EQ | float | a == b | %f |
+-------------------+--------------+-----------+-----------------------+
----------------------------
Assert backend API reference
----------------------------
The backend controls what to do in the case of an assertion failure. In the
most basic cases, the backend could display the assertion failure on something
like sys_io and halt in a while loop waiting for a debugger. In other cases,
the backend could store crash details like the current thread's stack to flash.
This module does not provide a backend; see ``pw_assert_basic`` for a basic
implementation (which we do not advise using in production).
Here are the macros the backend must provide:
.. cpp:function:: PW_HANDLE_CRASH(message, ...)
The backend should trigger a system crash or halt, and if possible, deliver
the specified message and arguments to the user or developer.
.. cpp:function:: PW_HANDLE_ASSERT_FAILURE(condition_str, message, ...)
This macro is invoked from ``PW_CHECK`` if condition is false. The
application should crash with the given message and specified format
arguments, and may optionally include the stringified condition provided in
``condition_str``.
.. cpp:function:: PW_HANDLE_ASSERT_BINARY_COMPARE_FAILURE( \
a_str, a_val, op_str, b_str, b_val, type_fmt, message, ...)
This macro is invoked from the ``PW_CHECK_*_*`` macros if the condition
``a_val op b_val`` is false. The facade API macros have already evaluated and
stringified the arguments, so the backend is free to report the details as
needed.
The backend is expected to report the failure to the user or developer in a
useful way, potentially capturing the string and values of the binary
comparison operands.