Keir Mierle | 3cee879 | 2020-01-22 17:08:13 -0800 | [diff] [blame] | 1 | .. _chapter-pw-assert: |
| 2 | |
| 3 | .. default-domain:: cpp |
| 4 | |
| 5 | .. highlight:: cpp |
| 6 | |
Keir Mierle | ec9bf1b | 2020-03-03 10:27:01 -0800 | [diff] [blame] | 7 | ========= |
Keir Mierle | 3cee879 | 2020-01-22 17:08:13 -0800 | [diff] [blame] | 8 | pw_assert |
Keir Mierle | ec9bf1b | 2020-03-03 10:27:01 -0800 | [diff] [blame] | 9 | ========= |
| 10 | |
| 11 | -------- |
| 12 | Overview |
| 13 | -------- |
Keir Mierle | 3cee879 | 2020-01-22 17:08:13 -0800 | [diff] [blame] | 14 | Pigweed's assert module provides facilities for applications to check |
Keir Mierle | ec9bf1b | 2020-03-03 10:27:01 -0800 | [diff] [blame] | 15 | preconditions. The module is split into two components: |
Keir Mierle | 3cee879 | 2020-01-22 17:08:13 -0800 | [diff] [blame] | 16 | |
| 17 | 1. The facade (this module) which is only a macro interface layer |
| 18 | 2. The backend, provided elsewhere, that implements the low level checks |
| 19 | |
Keir Mierle | ec9bf1b | 2020-03-03 10:27:01 -0800 | [diff] [blame] | 20 | All behaviour is controlled by the backend. |
| 21 | |
| 22 | The ``pw_assert`` public API provides three classes of macros: |
| 23 | |
| 24 | +-----------------------------------------+--------------------------------+ |
| 25 | | PW_CRASH(format, ...) | Trigger a crash with a message | |
| 26 | +-----------------------------------------+--------------------------------+ |
| 27 | | PW_CHECK(condition[, format, ...]) | Assert a condition, optionally | |
| 28 | | | with a message | |
| 29 | +-----------------------------------------+--------------------------------+ |
| 30 | | PW_CHECK_<type>_<cmp>(a, b[, fmt, ...]) | Assert that the expression | |
| 31 | | | ``a <cmp> b`` is true, | |
| 32 | | | optionally with a message. | |
| 33 | +-----------------------------------------+--------------------------------+ |
| 34 | |
| 35 | .. tip:: |
| 36 | All of the assert macros optionally support a message with additional |
| 37 | arguments, to assist in debugging when an assert triggers: |
| 38 | |
| 39 | .. code-block:: cpp |
| 40 | |
| 41 | PW_CHECK_INT_LE(ItemCount(), 100); |
| 42 | PW_CHECK_INT_LE(ItemCount(), 100, "System state: %s", GetStateStr()); |
| 43 | |
| 44 | Compatibility |
| 45 | ------------- |
| 46 | The facade is compatible with C and C++. |
| 47 | |
| 48 | Example |
| 49 | ------- |
Keir Mierle | 3cee879 | 2020-01-22 17:08:13 -0800 | [diff] [blame] | 50 | |
| 51 | .. code-block:: cpp |
| 52 | |
| 53 | #include "pw_assert/assert.h" |
| 54 | |
| 55 | int main() { |
| 56 | bool sensor_running = StartSensor(&msg); |
| 57 | PW_CHECK(sensor_running, "Sensor failed to start; code: %s", msg); |
Keir Mierle | ec9bf1b | 2020-03-03 10:27:01 -0800 | [diff] [blame] | 58 | |
| 59 | int temperature_c = ReadSensorCelcius(); |
| 60 | PW_CHECK_INT_LE(temperature_c, 100, |
| 61 | "System is way out of heat spec; state=%s", |
| 62 | ReadSensorStateString()); |
Keir Mierle | 3cee879 | 2020-01-22 17:08:13 -0800 | [diff] [blame] | 63 | } |
| 64 | |
Keir Mierle | ec9bf1b | 2020-03-03 10:27:01 -0800 | [diff] [blame] | 65 | |
| 66 | --------------------------- |
| 67 | Assert facade API reference |
| 68 | --------------------------- |
| 69 | |
| 70 | The below functions describe the assert API functions that applications should |
| 71 | invoke to assert. |
| 72 | |
| 73 | .. cpp:function:: PW_CRASH(format, ...) |
| 74 | |
| 75 | Trigger a crash with a message. Replaces LOG_FATAL() in other systems. Can |
| 76 | include a message with format arguments; for example: |
| 77 | |
| 78 | .. code-block:: cpp |
| 79 | |
| 80 | PW_CRASH("Unexpected: frobnitz in state: %s", frobnitz_state); |
| 81 | |
| 82 | Note: ``PW_CRASH`` is the equivalent of ``LOG_FATAL`` in other systems, where |
| 83 | a device crash is triggered with a message. In Pigweed, logging and |
| 84 | crashing/asserting are separated. There is a ``LOG_CRITICAL`` level in the |
| 85 | logging module, but it does not have side effects; for ``LOG_FATAL``, instead |
| 86 | use this macro (``PW_CRASH``). |
| 87 | |
| 88 | .. cpp:function:: PW_CHECK(condition) |
| 89 | .. cpp:function:: PW_CHECK(condition, format, ...) |
| 90 | |
| 91 | Assert that a condition is true, optionally including a message with |
| 92 | arguments to report if the codition is false. |
| 93 | |
| 94 | .. code-block:: cpp |
| 95 | |
| 96 | PW_CHECK(StartTurbines()); |
| 97 | PW_CHECK(StartWarpDrive(), "Oddly warp drive couldn't start; ruh-roh!"); |
| 98 | |
| 99 | .. cpp:function:: PW_CHECK_TYPE_OP(a, b) |
| 100 | .. cpp:function:: PW_CHECK_TYPE_OP(a, b, format, ...) |
| 101 | |
| 102 | Asserts that ``a OP b`` is true, where ``a`` and ``b`` are converted to |
| 103 | ``TYPE``; with ``OP`` and ``TYPE`` described below. |
| 104 | |
| 105 | If present, the optional format message is reported on failure. Depending on |
| 106 | the backend, values of ``a`` and ``b`` will also be reported. |
| 107 | |
| 108 | Example, with no message: |
| 109 | |
| 110 | .. code-block:: cpp |
| 111 | |
| 112 | PW_CHECK_INT_LE(CurrentTemperature(), 100); |
| 113 | PW_CHECK_INT_LE(ItemCount(), 100); |
| 114 | |
| 115 | Example, with an included message and arguments: |
| 116 | |
| 117 | .. code-block:: cpp |
| 118 | |
| 119 | PW_CHECK_FLOAT_GE(BatteryVoltage(), 3.2, "System state=%s", SysState()); |
| 120 | |
| 121 | Below is the full list of binary comparison assert macros, along with the |
| 122 | type specifier. The specifier is irrelevant to application authors but is |
| 123 | needed for backend implementers. |
| 124 | |
| 125 | +-------------------+--------------+-----------+-----------------------+ |
| 126 | | Macro | a, b type | condition | a, b format specifier | |
| 127 | +-------------------+--------------+-----------+-----------------------+ |
| 128 | | PW_CHECK_INT_LE | int | a <= b | %d | |
| 129 | +-------------------+--------------+-----------+-----------------------+ |
| 130 | | PW_CHECK_INT_LT | int | a < b | %d | |
| 131 | +-------------------+--------------+-----------+-----------------------+ |
| 132 | | PW_CHECK_INT_GE | int | a >= b | %d | |
| 133 | +-------------------+--------------+-----------+-----------------------+ |
| 134 | | PW_CHECK_INT_GT | int | a > b | %d | |
| 135 | +-------------------+--------------+-----------+-----------------------+ |
| 136 | | PW_CHECK_INT_EQ | int | a == b | %d | |
| 137 | +-------------------+--------------+-----------+-----------------------+ |
| 138 | | PW_CHECK_UINT_LE | unsigned int | a <= b | %u | |
| 139 | +-------------------+--------------+-----------+-----------------------+ |
| 140 | | PW_CHECK_UINT_LT | unsigned int | a < b | %u | |
| 141 | +-------------------+--------------+-----------+-----------------------+ |
| 142 | | PW_CHECK_UINT_GE | unsigned int | a >= b | %u | |
| 143 | +-------------------+--------------+-----------+-----------------------+ |
| 144 | | PW_CHECK_UINT_GT | unsigned int | a > b | %u | |
| 145 | +-------------------+--------------+-----------+-----------------------+ |
| 146 | | PW_CHECK_UINT_EQ | unsigned int | a == b | %u | |
| 147 | +-------------------+--------------+-----------+-----------------------+ |
| 148 | | PW_CHECK_FLOAT_LE | float | a <= b | %f | |
| 149 | +-------------------+--------------+-----------+-----------------------+ |
| 150 | | PW_CHECK_FLOAT_LT | float | a < b | %f | |
| 151 | +-------------------+--------------+-----------+-----------------------+ |
| 152 | | PW_CHECK_FLOAT_GE | float | a >= b | %f | |
| 153 | +-------------------+--------------+-----------+-----------------------+ |
| 154 | | PW_CHECK_FLOAT_GT | float | a > b | %f | |
| 155 | +-------------------+--------------+-----------+-----------------------+ |
| 156 | | PW_CHECK_FLOAT_EQ | float | a == b | %f | |
| 157 | +-------------------+--------------+-----------+-----------------------+ |
| 158 | |
| 159 | ---------------------------- |
| 160 | Assert backend API reference |
| 161 | ---------------------------- |
| 162 | |
| 163 | The backend controls what to do in the case of an assertion failure. In the |
| 164 | most basic cases, the backend could display the assertion failure on something |
| 165 | like sys_io and halt in a while loop waiting for a debugger. In other cases, |
| 166 | the backend could store crash details like the current thread's stack to flash. |
| 167 | |
| 168 | This module does not provide a backend; see ``pw_assert_basic`` for a basic |
| 169 | implementation (which we do not advise using in production). |
| 170 | |
| 171 | Here are the macros the backend must provide: |
| 172 | |
| 173 | .. cpp:function:: PW_HANDLE_CRASH(message, ...) |
| 174 | |
| 175 | The backend should trigger a system crash or halt, and if possible, deliver |
| 176 | the specified message and arguments to the user or developer. |
| 177 | |
| 178 | .. cpp:function:: PW_HANDLE_ASSERT_FAILURE(condition_str, message, ...) |
| 179 | |
| 180 | This macro is invoked from ``PW_CHECK`` if condition is false. The |
| 181 | application should crash with the given message and specified format |
| 182 | arguments, and may optionally include the stringified condition provided in |
| 183 | ``condition_str``. |
| 184 | |
| 185 | .. cpp:function:: PW_HANDLE_ASSERT_BINARY_COMPARE_FAILURE( \ |
| 186 | a_str, a_val, op_str, b_str, b_val, type_fmt, message, ...) |
| 187 | |
| 188 | This macro is invoked from the ``PW_CHECK_*_*`` macros if the condition |
| 189 | ``a_val op b_val`` is false. The facade API macros have already evaluated and |
| 190 | stringified the arguments, so the backend is free to report the details as |
| 191 | needed. |
| 192 | |
| 193 | The backend is expected to report the failure to the user or developer in a |
| 194 | useful way, potentially capturing the string and values of the binary |
| 195 | comparison operands. |