blob: 41ea1ca07c7665a34bb40fb540e5b521784df2c7 [file] [log] [blame]
Wyatt Heplerf9fb90f2020-09-30 18:59:33 -07001.. _module-pw_assert:
Keir Mierle3cee8792020-01-22 17:08:13 -08002
Keir Mierleec9bf1b2020-03-03 10:27:01 -08003=========
Keir Mierle3cee8792020-01-22 17:08:13 -08004pw_assert
Keir Mierleec9bf1b2020-03-03 10:27:01 -08005=========
6
7--------
8Overview
9--------
Keir Mierle481d8292020-07-31 01:10:05 -070010Pigweed's assert module enables applications to check preconditions, triggering
11a crash if the condition is not met. Consistent use of asserts is one aspect of
12defensive programming that can lead to more reliable and less buggy code.
Keir Mierle3cee8792020-01-22 17:08:13 -080013
Keir Mierle481d8292020-07-31 01:10:05 -070014The assert API facilitates flexible crash handling through Pigweed's facade
Shiva Rajagopal9e516562021-05-11 17:04:15 -070015mechanism. The API is designed to enable features like:
Keir Mierle3cee8792020-01-22 17:08:13 -080016
Keir Mierle481d8292020-07-31 01:10:05 -070017- Optional ancillary printf-style messages along assertions
18- Capturing actual values of binary operator assertions like ``a < b``
19- Compatibility with pw_tokenizer for reduced binary code size
Keir Mierleec9bf1b2020-03-03 10:27:01 -080020
Keir Mierle481d8292020-07-31 01:10:05 -070021The ``pw_assert`` API provides three classes of macros:
Keir Mierleec9bf1b2020-03-03 10:27:01 -080022
Keir Mierle481d8292020-07-31 01:10:05 -070023- **PW_CRASH(format, ...)** - Trigger a crash with a message.
24- **PW_CHECK(condition[, format, ...])** - Assert a condition, optionally with
25 a message.
26- **PW_CHECK_<type>_<cmp>(a, b[, fmt, ...])** - Assert that the expression ``a
27 <cmp> b`` is true, optionally with a message.
Wyatt Heplera59998f2021-03-19 14:35:10 -070028- **PW_ASSERT(condition)** - Header- and constexpr-safe assert.
Keir Mierleec9bf1b2020-03-03 10:27:01 -080029
30.. tip::
Keir Mierleb9b88162020-04-15 20:43:09 -070031
Wyatt Heplera59998f2021-03-19 14:35:10 -070032 All of the ``CHECK`` macros optionally support a message with additional
Keir Mierleec9bf1b2020-03-03 10:27:01 -080033 arguments, to assist in debugging when an assert triggers:
34
35 .. code-block:: cpp
36
37 PW_CHECK_INT_LE(ItemCount(), 100);
38 PW_CHECK_INT_LE(ItemCount(), 100, "System state: %s", GetStateStr());
39
Keir Mierleec9bf1b2020-03-03 10:27:01 -080040Example
Erik Gilling40915502021-11-12 17:16:48 +000041=======
Keir Mierle3cee8792020-01-22 17:08:13 -080042
43.. code-block:: cpp
44
Wyatt Heplera59998f2021-03-19 14:35:10 -070045 #include "pw_assert/check.h"
Keir Mierle3cee8792020-01-22 17:08:13 -080046
47 int main() {
48 bool sensor_running = StartSensor(&msg);
49 PW_CHECK(sensor_running, "Sensor failed to start; code: %s", msg);
Keir Mierleec9bf1b2020-03-03 10:27:01 -080050
51 int temperature_c = ReadSensorCelcius();
52 PW_CHECK_INT_LE(temperature_c, 100,
53 "System is way out of heat spec; state=%s",
54 ReadSensorStateString());
Keir Mierle3cee8792020-01-22 17:08:13 -080055 }
56
Keir Mierleb9b88162020-04-15 20:43:09 -070057.. tip::
58
59 All macros have both a ``CHECK`` and ``DCHECK`` variant. The ``CHECK``
60 variant is always enabled, even in production. Generally, we advise making
61 most asserts ``CHECK`` rather than ``DCHECK``, unless there is a critical
62 performance or code size reason to use ``DCHECK``.
63
64 .. code-block:: cpp
65
66 // This assert is always enabled, even in production.
67 PW_CHECK_INT_LE(ItemCount(), 100);
68
Ewout van Bekkum2aff88e2021-11-12 15:36:57 -080069 // This assert is enabled based on ``PW_ASSERT_ENABLE_DEBUG``.
Keir Mierleb9b88162020-04-15 20:43:09 -070070 // The functions ItemCount() and GetStateStr() are never called.
71 PW_DCHECK_INT_LE(ItemCount(), 100, "System state: %s", GetStateStr());
Keir Mierleec9bf1b2020-03-03 10:27:01 -080072
Keir Mierle854adec2020-09-03 14:07:19 -070073.. tip::
74
Wyatt Heplera59998f2021-03-19 14:35:10 -070075 Use ``PW_ASSERT`` from ``pw_assert/assert.h`` for asserts in headers or
Keir Mierle854adec2020-09-03 14:07:19 -070076 asserting in ``constexpr`` contexts.
77
Erik Gilling40915502021-11-12 17:16:48 +000078Structure of Assert Modules
79===========================
Keir Mierle481d8292020-07-31 01:10:05 -070080The module is split into two components:
81
821. The **facade** (this module) which is only a macro interface layer, and
83 performs the actual checks for the conditions.
842. The **backend**, provided elsewhere, that handles the consequences of an
85 assert failing. Example backends include ``pw_assert_basic``, which prints a
86 useful message and either quits the application (on host) or hangs in a
87 while loop (on device). In the future, there will be a tokenized assert
88 backend. This is also where application or product specific crash handling
89 would go.
90
Wyatt Hepler1d221242021-09-07 15:42:21 -070091.. mermaid::
Wyatt Hepler79ea2cf2021-09-07 13:24:26 -070092
Wyatt Hepler1d221242021-09-07 15:42:21 -070093 graph LR
94 facade --> backend
Keir Mierle481d8292020-07-31 01:10:05 -070095
96See the Backend API section below for more details.
97
Keir Mierle854adec2020-09-03 14:07:19 -070098----------
99Facade API
100----------
Keir Mierleec9bf1b2020-03-03 10:27:01 -0800101The below functions describe the assert API functions that applications should
Wyatt Heplera59998f2021-03-19 14:35:10 -0700102invoke to assert. These macros are found in the ``pw_assert/check.h`` header.
Keir Mierleec9bf1b2020-03-03 10:27:01 -0800103
104.. cpp:function:: PW_CRASH(format, ...)
105
106 Trigger a crash with a message. Replaces LOG_FATAL() in other systems. Can
107 include a message with format arguments; for example:
108
109 .. code-block:: cpp
110
111 PW_CRASH("Unexpected: frobnitz in state: %s", frobnitz_state);
112
113 Note: ``PW_CRASH`` is the equivalent of ``LOG_FATAL`` in other systems, where
114 a device crash is triggered with a message. In Pigweed, logging and
115 crashing/asserting are separated. There is a ``LOG_CRITICAL`` level in the
116 logging module, but it does not have side effects; for ``LOG_FATAL``, instead
117 use this macro (``PW_CRASH``).
118
119.. cpp:function:: PW_CHECK(condition)
120.. cpp:function:: PW_CHECK(condition, format, ...)
Keir Mierleb9b88162020-04-15 20:43:09 -0700121.. cpp:function:: PW_DCHECK(condition)
122.. cpp:function:: PW_DCHECK(condition, format, ...)
Keir Mierleec9bf1b2020-03-03 10:27:01 -0800123
124 Assert that a condition is true, optionally including a message with
125 arguments to report if the codition is false.
126
Ewout van Bekkum2aff88e2021-11-12 15:36:57 -0800127 The ``DCHECK`` variants only run if ``PW_ASSERT_ENABLE_DEBUG`` is enabled;
128 otherwise, the entire statement is removed (and the expression not evaluated).
Keir Mierleb9b88162020-04-15 20:43:09 -0700129
Keir Mierlec1cb12d2020-06-01 11:59:41 -0700130 Example:
131
Keir Mierleec9bf1b2020-03-03 10:27:01 -0800132 .. code-block:: cpp
133
134 PW_CHECK(StartTurbines());
135 PW_CHECK(StartWarpDrive(), "Oddly warp drive couldn't start; ruh-roh!");
Keir Mierlec1cb12d2020-06-01 11:59:41 -0700136 PW_CHECK(RunSelfTest(), "Failure in self test; try %d", TestAttempts());
137
138 .. attention::
139
Keir Mierle0fa7f7d2020-05-07 12:34:00 -0700140 Don't use use ``PW_CHECK`` for binary comparisons or status checks!
Keir Mierlec1cb12d2020-06-01 11:59:41 -0700141
142 Instead, use the ``PW_CHECK_<TYPE>_<OP>`` macros. These macros enable
143 capturing the value of the operands, and also tokenizing them if using a
144 tokenizing assert backend. For example, if ``x`` and ``b`` are integers,
145 use instead ``PW_CHECK_INT_LT(x, b)``.
146
Wyatt Hepler1b3da3a2021-01-07 13:26:57 -0800147 Additionally, use ``PW_CHECK_OK(status)`` when checking for an OK status,
148 since it enables showing a human-readable status string rather than an
149 integer (e.g. ``status == RESOURCE_EXHAUSTED`` instead of ``status == 5``.
Keir Mierle0fa7f7d2020-05-07 12:34:00 -0700150
151 +------------------------------------+-------------------------------------+
152 | **Do NOT do this** | **Do this instead** |
153 +------------------------------------+-------------------------------------+
154 | ``PW_CHECK(a_int < b_int)`` | ``PW_CHECK_INT_LT(a_int, b_int)`` |
155 +------------------------------------+-------------------------------------+
156 | ``PW_CHECK(a_ptr <= b_ptr)`` | ``PW_CHECK_PTR_LE(a_ptr, b_ptr)`` |
157 +------------------------------------+-------------------------------------+
Ewout van Bekkum9e97cfd2020-07-16 13:57:24 -0700158 | ``PW_CHECK(Temp() <= 10.0)`` | ``PW_CHECK_FLOAT_EXACT_LE(`` |
159 | | `` Temp(), 10.0)`` |
Keir Mierle0fa7f7d2020-05-07 12:34:00 -0700160 +------------------------------------+-------------------------------------+
Wyatt Hepler1b3da3a2021-01-07 13:26:57 -0800161 | ``PW_CHECK(Foo() == OkStatus())`` | ``PW_CHECK_OK(Foo())`` |
Keir Mierle0fa7f7d2020-05-07 12:34:00 -0700162 +------------------------------------+-------------------------------------+
Keir Mierleec9bf1b2020-03-03 10:27:01 -0800163
Keir Mierlefa8f89d2020-04-15 16:20:02 -0700164.. cpp:function:: PW_CHECK_NOTNULL(ptr)
165.. cpp:function:: PW_CHECK_NOTNULL(ptr, format, ...)
Keir Mierleb9b88162020-04-15 20:43:09 -0700166.. cpp:function:: PW_DCHECK_NOTNULL(ptr)
167.. cpp:function:: PW_DCHECK_NOTNULL(ptr, format, ...)
Keir Mierlefa8f89d2020-04-15 16:20:02 -0700168
169 Assert that the given pointer is not ``NULL``, optionally including a message
170 with arguments to report if the pointer is ``NULL``.
171
Ewout van Bekkum2aff88e2021-11-12 15:36:57 -0800172 The ``DCHECK`` variants only run if ``PW_ASSERT_ENABLE_DEBUG`` is enabled;
173 otherwise, the entire statement is removed (and the expression not evaluated).
Keir Mierleb9b88162020-04-15 20:43:09 -0700174
Keir Mierlefa8f89d2020-04-15 16:20:02 -0700175 .. code-block:: cpp
176
177 Foo* foo = GetTheFoo()
178 PW_CHECK_NOTNULL(foo);
179
Keir Mierle0fa7f7d2020-05-07 12:34:00 -0700180 Bar* bar = GetSomeBar();
Keir Mierlefa8f89d2020-04-15 16:20:02 -0700181 PW_CHECK_NOTNULL(bar, "Weirdly got NULL bar; state: %d", MyState());
182
Keir Mierleec9bf1b2020-03-03 10:27:01 -0800183.. cpp:function:: PW_CHECK_TYPE_OP(a, b)
184.. cpp:function:: PW_CHECK_TYPE_OP(a, b, format, ...)
Keir Mierleb9b88162020-04-15 20:43:09 -0700185.. cpp:function:: PW_DCHECK_TYPE_OP(a, b)
186.. cpp:function:: PW_DCHECK_TYPE_OP(a, b, format, ...)
Keir Mierleec9bf1b2020-03-03 10:27:01 -0800187
188 Asserts that ``a OP b`` is true, where ``a`` and ``b`` are converted to
189 ``TYPE``; with ``OP`` and ``TYPE`` described below.
190
191 If present, the optional format message is reported on failure. Depending on
192 the backend, values of ``a`` and ``b`` will also be reported.
193
Ewout van Bekkum2aff88e2021-11-12 15:36:57 -0800194 The ``DCHECK`` variants only run if ``PW_ASSERT_ENABLE_DEBUG`` is enabled;
195 otherwise, the entire statement is removed (and the expression not evaluated).
Keir Mierleb9b88162020-04-15 20:43:09 -0700196
Keir Mierleec9bf1b2020-03-03 10:27:01 -0800197 Example, with no message:
198
199 .. code-block:: cpp
200
201 PW_CHECK_INT_LE(CurrentTemperature(), 100);
202 PW_CHECK_INT_LE(ItemCount(), 100);
203
204 Example, with an included message and arguments:
205
206 .. code-block:: cpp
207
Ewout van Bekkum9e97cfd2020-07-16 13:57:24 -0700208 PW_CHECK_FLOAT_EXACT_GE(BatteryVoltage(), 3.2,
209 "System state=%s", SysState());
Keir Mierleec9bf1b2020-03-03 10:27:01 -0800210
211 Below is the full list of binary comparison assert macros, along with the
212 type specifier. The specifier is irrelevant to application authors but is
213 needed for backend implementers.
214
Ewout van Bekkum9e97cfd2020-07-16 13:57:24 -0700215 +-------------------------+--------------+-----------+-----------------------+
216 | Macro | a, b type | condition | a, b format specifier |
217 +-------------------------+--------------+-----------+-----------------------+
218 | PW_CHECK_INT_LE | int | a <= b | %d |
219 +-------------------------+--------------+-----------+-----------------------+
220 | PW_CHECK_INT_LT | int | a < b | %d |
221 +-------------------------+--------------+-----------+-----------------------+
222 | PW_CHECK_INT_GE | int | a >= b | %d |
223 +-------------------------+--------------+-----------+-----------------------+
224 | PW_CHECK_INT_GT | int | a > b | %d |
225 +-------------------------+--------------+-----------+-----------------------+
226 | PW_CHECK_INT_EQ | int | a == b | %d |
227 +-------------------------+--------------+-----------+-----------------------+
228 | PW_CHECK_INT_NE | int | a != b | %d |
229 +-------------------------+--------------+-----------+-----------------------+
230 | PW_CHECK_UINT_LE | unsigned int | a <= b | %u |
231 +-------------------------+--------------+-----------+-----------------------+
232 | PW_CHECK_UINT_LT | unsigned int | a < b | %u |
233 +-------------------------+--------------+-----------+-----------------------+
234 | PW_CHECK_UINT_GE | unsigned int | a >= b | %u |
235 +-------------------------+--------------+-----------+-----------------------+
236 | PW_CHECK_UINT_GT | unsigned int | a > b | %u |
237 +-------------------------+--------------+-----------+-----------------------+
238 | PW_CHECK_UINT_EQ | unsigned int | a == b | %u |
239 +-------------------------+--------------+-----------+-----------------------+
240 | PW_CHECK_UINT_NE | unsigned int | a != b | %u |
241 +-------------------------+--------------+-----------+-----------------------+
242 | PW_CHECK_PTR_LE | void* | a <= b | %p |
243 +-------------------------+--------------+-----------+-----------------------+
244 | PW_CHECK_PTR_LT | void* | a < b | %p |
245 +-------------------------+--------------+-----------+-----------------------+
246 | PW_CHECK_PTR_GE | void* | a >= b | %p |
247 +-------------------------+--------------+-----------+-----------------------+
248 | PW_CHECK_PTR_GT | void* | a > b | %p |
249 +-------------------------+--------------+-----------+-----------------------+
250 | PW_CHECK_PTR_EQ | void* | a == b | %p |
251 +-------------------------+--------------+-----------+-----------------------+
252 | PW_CHECK_PTR_NE | void* | a != b | %p |
253 +-------------------------+--------------+-----------+-----------------------+
254 | PW_CHECK_FLOAT_EXACT_LE | float | a <= b | %f |
255 +-------------------------+--------------+-----------+-----------------------+
256 | PW_CHECK_FLOAT_EXACT_LT | float | a < b | %f |
257 +-------------------------+--------------+-----------+-----------------------+
258 | PW_CHECK_FLOAT_EXACT_GE | float | a >= b | %f |
259 +-------------------------+--------------+-----------+-----------------------+
260 | PW_CHECK_FLOAT_EXACT_GT | float | a > b | %f |
261 +-------------------------+--------------+-----------+-----------------------+
262 | PW_CHECK_FLOAT_EXACT_EQ | float | a == b | %f |
263 +-------------------------+--------------+-----------+-----------------------+
264 | PW_CHECK_FLOAT_EXACT_NE | float | a != b | %f |
265 +-------------------------+--------------+-----------+-----------------------+
Keir Mierleec9bf1b2020-03-03 10:27:01 -0800266
Keir Mierleb9b88162020-04-15 20:43:09 -0700267 The above ``CHECK_*_*()`` are also available in DCHECK variants, which will
Ewout van Bekkum2aff88e2021-11-12 15:36:57 -0800268 only evaluate their arguments and trigger if the ``PW_ASSERT_ENABLE_DEBUG``
269 macro is enabled.
Keir Mierleb9b88162020-04-15 20:43:09 -0700270
Ewout van Bekkum9e97cfd2020-07-16 13:57:24 -0700271 +--------------------------+--------------+-----------+----------------------+
272 | Macro | a, b type | condition | a, b format |
273 | | | | specifier |
274 +--------------------------+--------------+-----------+----------------------+
275 | PW_DCHECK_INT_LE | int | a <= b | %d |
276 +--------------------------+--------------+-----------+----------------------+
277 | PW_DCHECK_INT_LT | int | a < b | %d |
278 +--------------------------+--------------+-----------+----------------------+
279 | PW_DCHECK_INT_GE | int | a >= b | %d |
280 +--------------------------+--------------+-----------+----------------------+
281 | PW_DCHECK_INT_GT | int | a > b | %d |
282 +--------------------------+--------------+-----------+----------------------+
283 | PW_DCHECK_INT_EQ | int | a == b | %d |
284 +--------------------------+--------------+-----------+----------------------+
285 | PW_DCHECK_INT_NE | int | a != b | %d |
286 +--------------------------+--------------+-----------+----------------------+
287 | PW_DCHECK_UINT_LE | unsigned int | a <= b | %u |
288 +--------------------------+--------------+-----------+----------------------+
289 | PW_DCHECK_UINT_LT | unsigned int | a < b | %u |
290 +--------------------------+--------------+-----------+----------------------+
291 | PW_DCHECK_UINT_GE | unsigned int | a >= b | %u |
292 +--------------------------+--------------+-----------+----------------------+
293 | PW_DCHECK_UINT_GT | unsigned int | a > b | %u |
294 +--------------------------+--------------+-----------+----------------------+
295 | PW_DCHECK_UINT_EQ | unsigned int | a == b | %u |
296 +--------------------------+--------------+-----------+----------------------+
297 | PW_DCHECK_UINT_NE | unsigned int | a != b | %u |
298 +--------------------------+--------------+-----------+----------------------+
299 | PW_DCHECK_PTR_LE | void* | a <= b | %p |
300 +--------------------------+--------------+-----------+----------------------+
301 | PW_DCHECK_PTR_LT | void* | a < b | %p |
302 +--------------------------+--------------+-----------+----------------------+
303 | PW_DCHECK_PTR_GE | void* | a >= b | %p |
304 +--------------------------+--------------+-----------+----------------------+
305 | PW_DCHECK_PTR_GT | void* | a > b | %p |
306 +--------------------------+--------------+-----------+----------------------+
307 | PW_DCHECK_PTR_EQ | void* | a == b | %p |
308 +--------------------------+--------------+-----------+----------------------+
309 | PW_DCHECK_PTR_NE | void* | a != b | %p |
310 +--------------------------+--------------+-----------+----------------------+
311 | PW_DCHECK_FLOAT_EXACT_LE | float | a <= b | %f |
312 +--------------------------+--------------+-----------+----------------------+
313 | PW_DCHECK_FLOAT_EXACT_LT | float | a < b | %f |
314 +--------------------------+--------------+-----------+----------------------+
315 | PW_DCHECK_FLOAT_EXACT_GE | float | a >= b | %f |
316 +--------------------------+--------------+-----------+----------------------+
317 | PW_DCHECK_FLOAT_EXACT_GT | float | a > b | %f |
318 +--------------------------+--------------+-----------+----------------------+
319 | PW_DCHECK_FLOAT_EXACT_EQ | float | a == b | %f |
320 +--------------------------+--------------+-----------+----------------------+
321 | PW_DCHECK_FLOAT_EXACT_NE | float | a != b | %f |
322 +--------------------------+--------------+-----------+----------------------+
323
324.. attention::
325
326 For float, proper comparator checks which take floating point
327 precision and ergo error accumulation into account are not provided on
328 purpose as this comes with some complexity and requires application
329 specific tolerances in terms of Units of Least Precision (ULP). Instead,
330 we recommend developers carefully consider how floating point precision and
331 error impact the data they are bounding and whether checks are appropriate.
332
333.. cpp:function:: PW_CHECK_FLOAT_NEAR(a, b, abs_tolerance)
334.. cpp:function:: PW_CHECK_FLOAT_NEAR(a, b, abs_tolerance, format, ...)
335.. cpp:function:: PW_DCHECK_FLOAT_NEAR(a, b, abs_tolerance)
336.. cpp:function:: PW_DCHECK_FLOAT_NEAR(a, b, abs_tolerance, format, ...)
337
338 Asserts that ``(a >= b - abs_tolerance) && (a <= b + abs_tolerance)`` is true,
339 where ``a``, ``b``, and ``abs_tolerance`` are converted to ``float``.
340
341 .. note::
342 This also asserts that ``abs_tolerance >= 0``.
343
Ewout van Bekkum2aff88e2021-11-12 15:36:57 -0800344 The ``DCHECK`` variants only run if ``PW_ASSERT_ENABLE_DEBUG`` is enabled;
345 otherwise, the entire statement is removed (and the expression not evaluated).
Ewout van Bekkum9e97cfd2020-07-16 13:57:24 -0700346
347 Example, with no message:
348
349 .. code-block:: cpp
350
351 PW_CHECK_FLOAT_NEAR(cos(0.0f), 1, 0.001);
352
353 Example, with an included message and arguments:
354
355 .. code-block:: cpp
356
357 PW_CHECK_FLOAT_NEAR(FirstOperation(), RedundantOperation(), 0.1,
358 "System state=%s", SysState());
Keir Mierleb9b88162020-04-15 20:43:09 -0700359
Keir Mierle0fa7f7d2020-05-07 12:34:00 -0700360.. cpp:function:: PW_CHECK_OK(status)
361.. cpp:function:: PW_CHECK_OK(status, format, ...)
362.. cpp:function:: PW_DCHECK_OK(status)
363.. cpp:function:: PW_DCHECK_OK(status, format, ...)
364
Wyatt Hepler1b3da3a2021-01-07 13:26:57 -0800365 Assert that ``status`` evaluates to ``pw::OkStatus()`` (in C++) or
Keir Mierle0fa7f7d2020-05-07 12:34:00 -0700366 ``PW_STATUS_OK`` (in C). Optionally include a message with arguments to
367 report.
368
Ewout van Bekkum2aff88e2021-11-12 15:36:57 -0800369 The ``DCHECK`` variants only run if ``PW_ASSERT_ENABLE_DEBUG`` is defined;
370 otherwise, the entire statement is removed (and the expression not evaluated).
Keir Mierle0fa7f7d2020-05-07 12:34:00 -0700371
372 .. code-block:: cpp
373
374 pw::Status operation_status = DoSomeOperation();
375 PW_CHECK_OK(operation_status);
376
377 // Any expression that evaluates to a pw::Status or pw_Status works.
378 PW_CHECK_OK(DoTheThing(), "System state: %s", SystemState());
379
380 // C works too.
381 pw_Status c_status = DoMoreThings();
382 PW_CHECK_OK(c_status, "System state: %s", SystemState());
383
384 .. note::
385
Wyatt Hepler1b3da3a2021-01-07 13:26:57 -0800386 Using ``PW_CHECK_OK(status)`` instead of ``PW_CHECK(status == OkStatus())``
Keir Mierle0fa7f7d2020-05-07 12:34:00 -0700387 enables displaying an error message with a string version of the error
388 code; for example ``status == RESOURCE_EXHAUSTED`` instead of ``status ==
389 5``.
390
Erik Gilling703abad2021-11-09 11:54:44 -0800391.. _module-pw_assert-assert-api:
392
Wyatt Heplera59998f2021-03-19 14:35:10 -0700393----------
394Assert API
395----------
Keir Mierle854adec2020-09-03 14:07:19 -0700396The normal ``PW_CHECK_*`` and ``PW_DCHECK_*`` family of macros are intended to
397provide rich debug information, like the file, line number, value of operands
398in boolean comparisons, and more. However, this comes at a cost: these macros
399depend directly on the backend headers, and may perform complicated call-site
400transformations like tokenization.
401
402There are several issues with the normal ``PW_CHECK_*`` suite of macros:
403
4041. ``PW_CHECK_*`` in headers can cause ODR violations in the case of tokenized
405 asserts, due to differing module choices.
4062. ``PW_CHECK_*`` is not constexpr-safe.
4073. ``PW_CHECK_*`` can cause code bloat with some backends; this is the tradeoff
408 to get rich assert information.
4094. ``PW_CHECK_*`` can trigger circular dependencies when asserts are used from
410 low-level contexts, like in ``<span>``.
411
Wyatt Heplera59998f2021-03-19 14:35:10 -0700412**PW_ASSERT** solves all of the above problems: No risk of ODR violations, are
413constexpr safe, and have a tiny call site footprint; and there is no header
414dependency on the backend preventing circular include issues. However, there
415are **no format messages, no captured line number, no captured file, no captured
416expression, or anything other than a binary indication of failure**.
Keir Mierle854adec2020-09-03 14:07:19 -0700417
418Example
Erik Gilling40915502021-11-12 17:16:48 +0000419=======
Keir Mierle854adec2020-09-03 14:07:19 -0700420
421.. code-block:: cpp
422
423 // This example demonstrates asserting in a header.
424
Wyatt Heplera59998f2021-03-19 14:35:10 -0700425 #include "pw_assert/assert.h"
Keir Mierle854adec2020-09-03 14:07:19 -0700426
427 class InlinedSubsystem {
428 public:
429 void DoSomething() {
430 // GOOD: No problem; PW_ASSERT is fine to inline and place in a header.
431 PW_ASSERT(IsEnabled());
432 }
433 void DoSomethingElse() {
434 // BAD: Generally avoid using PW_DCHECK() or PW_CHECK in headers. If you
435 // want rich asserts or logs, move the function into the .cc file, and
436 // then use PW_CHECK there.
437 PW_DCHECK(IsEnabled()); // DON'T DO THIS
438 }
439 };
440
Erik Gilling40915502021-11-12 17:16:48 +0000441PW_ASSERT API Reference
442=======================
Keir Mierle854adec2020-09-03 14:07:19 -0700443.. cpp:function:: PW_ASSERT(condition)
444
445 A header- and constexpr-safe version of ``PW_CHECK()``.
446
447 If the given condition is false, crash the system. Otherwise, do nothing.
448 The condition is guaranteed to be evaluated. This assert implementation is
449 guaranteed to be constexpr-safe.
450
451.. cpp:function:: PW_DASSERT(condition)
452
453 A header- and constexpr-safe version of ``PW_DCHECK()``.
454
Ewout van Bekkum2aff88e2021-11-12 15:36:57 -0800455 Same as ``PW_ASSERT()``, except that if ``PW_ASSERT_ENABLE_DEBUG == 0``, the
Keir Mierle854adec2020-09-03 14:07:19 -0700456 assert is disabled and condition is not evaluated.
457
458.. attention::
459
460 Unlike the ``PW_CHECK_*()`` suite of macros, ``PW_ASSERT()`` and
461 ``PW_DASSERT()`` capture no rich information like line numbers, the file,
462 expression arguments, or the stringified expression. Use these macros **only
Alexei Frolov5a0450d2020-10-28 21:10:47 -0700463 when absolutely necessary**---in headers, constexpr contexts, or in rare cases
Keir Mierle854adec2020-09-03 14:07:19 -0700464 where the call site overhead of a full PW_CHECK must be avoided.
465
466 Use ``PW_CHECK_*()`` whenever possible.
467
Erik Gilling40915502021-11-12 17:16:48 +0000468PW_ASSERT API Backend
469=====================
Wyatt Heplera59998f2021-03-19 14:35:10 -0700470The ``PW_ASSERT`` API ultimately calls the C function
471``pw_assert_HandleFailure()``, which must be provided by the ``pw_assert``
Wyatt Hepler66064662021-05-03 09:15:40 -0700472backend. The ``pw_assert_HandleFailure()`` function must not return.
Keir Mierle854adec2020-09-03 14:07:19 -0700473
Wyatt Hepler8bd4fb02021-05-03 15:30:58 -0700474.. _module-pw_assert-circular-deps:
475
Erik Gilling40915502021-11-12 17:16:48 +0000476Avoiding Circular Dependencies With ``PW_ASSERT``
477=================================================
Wyatt Hepler3d0e3152021-04-29 17:08:31 -0700478Because asserts are so widely used, including in low-level libraries, it is
Wyatt Hepler8bd4fb02021-05-03 15:30:58 -0700479common for the ``pw_assert`` backend to cause circular dependencies. Because of
480this, assert backends may avoid declaring explicit dependencies, instead relying
481on include paths to access header files.
Wyatt Hepler3d0e3152021-04-29 17:08:31 -0700482
Wyatt Hepler61663222021-05-06 10:57:43 -0700483In GN, the ``pw_assert`` backend's full implementation with true dependencies is
484made available through the ``$dir_pw_assert:impl`` group. When
485``pw_assert_BACKEND`` is set, ``$dir_pw_assert:impl`` must be listed in the
486``pw_build_LINK_DEPS`` variable. See :ref:`module-pw_build-link-deps`.
Wyatt Hepler8bd4fb02021-05-03 15:30:58 -0700487
Wyatt Hepler61663222021-05-06 10:57:43 -0700488In the ``pw_assert``, the backend's full implementation is placed in the
489``$pw_assert_BACKEND.impl`` target. ``$dir_pw_assert:impl`` depends on this
490backend target. The ``$pw_assert_BACKEND.impl`` target may be an empty group if
491the backend target can use its dependencies directly without causing circular
492dependencies.
493
494In order to break dependency cycles, the ``pw_assert_BACKEND`` target may need
495to directly provide dependencies through include paths only, rather than GN
496``public_deps``. In this case, GN header checking can be disabled with
497``check_includes = false``.
Wyatt Hepler3d0e3152021-04-29 17:08:31 -0700498
Armando Montanez179aa8e2021-03-10 11:46:35 -0800499.. _module-pw_assert-backend_api:
500
Keir Mierle854adec2020-09-03 14:07:19 -0700501-----------
502Backend API
503-----------
Keir Mierleec9bf1b2020-03-03 10:27:01 -0800504The backend controls what to do in the case of an assertion failure. In the
505most basic cases, the backend could display the assertion failure on something
506like sys_io and halt in a while loop waiting for a debugger. In other cases,
507the backend could store crash details like the current thread's stack to flash.
508
Keir Mierlec1cb12d2020-06-01 11:59:41 -0700509This facade module (``pw_assert``) does not provide a backend. See
Wyatt Heplerf9fb90f2020-09-30 18:59:33 -0700510:ref:`module-pw_assert_basic` for a basic implementation.
Keir Mierleec9bf1b2020-03-03 10:27:01 -0800511
Keir Mierle49f8e7e2020-07-30 17:57:30 -0700512.. attention::
513
514 The facade macros (``PW_CRASH`` and related) are expected to behave like they
Wyatt Hepler3d0e3152021-04-29 17:08:31 -0700515 have the ``[[noreturn]]`` attribute set. This implies that the backend handler
516 functions, ``PW_HANDLE_*`` defined by the backend, must not return.
Keir Mierle49f8e7e2020-07-30 17:57:30 -0700517
518 In other words, the device must reboot.
519
Keir Mierlec1cb12d2020-06-01 11:59:41 -0700520The backend must provide the header
521
522``pw_assert_backend/backend.h``
523
524and that header must define the following macros:
Keir Mierleec9bf1b2020-03-03 10:27:01 -0800525
526.. cpp:function:: PW_HANDLE_CRASH(message, ...)
527
Keir Mierlec1cb12d2020-06-01 11:59:41 -0700528 Trigger a system crash or halt, and if possible, deliver the specified
529 message and arguments to the user or developer.
Keir Mierleec9bf1b2020-03-03 10:27:01 -0800530
531.. cpp:function:: PW_HANDLE_ASSERT_FAILURE(condition_str, message, ...)
532
Keir Mierlec1cb12d2020-06-01 11:59:41 -0700533 Trigger a system crash or halt, and if possible, deliver the condition string
534 (indicating what expression was false) and the message with format arguments,
535 to the user or developer.
536
537 This macro is invoked from the ``PW_CHECK`` facade macro if condition is
538 false.
Keir Mierleec9bf1b2020-03-03 10:27:01 -0800539
540.. cpp:function:: PW_HANDLE_ASSERT_BINARY_COMPARE_FAILURE( \
541 a_str, a_val, op_str, b_str, b_val, type_fmt, message, ...)
542
Keir Mierlec1cb12d2020-06-01 11:59:41 -0700543 Trigger a system crash or halt for a failed binary comparison assert (e.g.
544 any of the ``PW_CHECK_<type>_<op>`` macros). The handler should combine the
545 assert components into a useful message for the user; though in some cases
546 this may not be possible.
Keir Mierleec9bf1b2020-03-03 10:27:01 -0800547
Keir Mierlec1cb12d2020-06-01 11:59:41 -0700548 Consider the following example:
549
550 .. code-block:: cpp
551
552 int temp = 16;
553 int max_temp = 15;
554 PW_CHECK_INT_LE(temp, MAX_TEMP, "Got too hot; state: %s", GetSystemState());
555
556 In this block, the assert will trigger, which will cause the facade to invoke
557 the handler macro. Below is the meaning of the arguments, referencing to the
558 example:
559
560 - ``a_str`` - Stringified first operand. In the example: ``"temp"``.
561 - ``a_val`` - The value of the first operand. In the example: ``16``.
562 - ``op_str`` - The string version of the operator. In the example: "<=".
563 - ``b_str`` - Stringified second operand. In the example: ``"max_temp"``.
564 - ``b_val`` - The value of the second operand. In the example: ``15``.
565 - ``type_fmt`` - The format code for the type. In the example: ``"%d"``.
566 - ``message, ...`` - A formatted message to go with the assert. In the
567 example: ``"Got too hot; state: %s", "ON_FIRE"``.
568
569 .. tip::
570
Wyatt Heplerf9fb90f2020-09-30 18:59:33 -0700571 See :ref:`module-pw_assert_basic` for one way to combine these arguments
Keir Mierlec1cb12d2020-06-01 11:59:41 -0700572 into a meaningful error message.
573
Wyatt Heplera59998f2021-03-19 14:35:10 -0700574Additionally, the backend must provide a link-time function for the
575``PW_ASSERT`` assert handler. This does not need to appear in the backend
576header, but instead is in a ``.cc`` file.
Keir Mierle854adec2020-09-03 14:07:19 -0700577
578.. cpp:function:: pw_assert_HandleFailure()
579
580 Handle a low-level crash. This crash entry happens through
Wyatt Heplera59998f2021-03-19 14:35:10 -0700581 ``pw_assert/assert.h``. In this crash handler, there is no access to line,
Keir Mierle854adec2020-09-03 14:07:19 -0700582 file, expression, or other rich assert information. Backends should do
583 something reasonable in this case; typically, capturing the stack is useful.
584
Erik Gilling40915502021-11-12 17:16:48 +0000585Backend Build Targets
586=====================
Wyatt Hepler61663222021-05-06 10:57:43 -0700587In GN, the backend must provide a ``pw_assert.impl`` build target in the same
588directory as the backend target. If the main backend target's dependencies would
589cause dependency cycles, the actual backend implementation with its full
590dependencies is placed in the ``pw_assert.impl`` target. If this is not
591necessary, ``pw_assert.impl`` can be an empty group. Circular dependencies are a
592common problem with ``pw_assert`` because it is so widely used. See
593:ref:`module-pw_assert-circular-deps`.
Wyatt Hepler8bd4fb02021-05-03 15:30:58 -0700594
Keir Mierle49f8e7e2020-07-30 17:57:30 -0700595--------------------------
Erik Gilling40915502021-11-12 17:16:48 +0000596Frequently Asked Questions
Keir Mierle49f8e7e2020-07-30 17:57:30 -0700597--------------------------
Keir Mierlec1cb12d2020-06-01 11:59:41 -0700598
Keir Mierle3f356722020-07-31 00:43:43 -0700599When should DCHECK_* be used instead of CHECK_* and vice versa?
Erik Gilling40915502021-11-12 17:16:48 +0000600===============================================================
Keir Mierle3f356722020-07-31 00:43:43 -0700601There is no hard and fast rule for when to use one or the other.
602
603In theory, ``DCHECK_*`` macros should never be used and all the asserts should
604remain active in production. In practice, **assert statements come at a binary
605size and runtime cost**, even when using extensions like a tokenized assert
606backend that strips the stringified assert expression from the binary. Each
607assert is **at least a branch with a function call**; depending on the assert
608backend, that function call may take several arguments (like the message, the
609file line number, the module, etc). These function calls can take 10-20 bytes
610or more of ROM each. Thus, there is a balance to be struct between ``DCHECK_*``
611and ``CHECK_*``.
612
613Pigweed uses these conventions to decide between ``CHECK_*`` and ``DCHECK_*``:
614
615- **Prefer to use CHECK_* at public API boundaries** of modules, where an
616 invalid value is a clear programmer bug. In certain cases use ``DCHECK_*`` to
617 keep binary size small when in production; for example, in modules with a
618 large public API surface, or modules with many inlined functions in headers.
619- **Avoid using CHECK_* macros in headers.** It is still OK to use ``CHECK_*``
620 macros in headers, but carefully consider the cost, since inlined use of the
621 ``CHECK_*`` macros in headers will expand to the full assert cost for every
622 translation unit that includes the header and calls the function with the
623 ``CHECK_*`` instance. ``DCHECK_*`` macros are are better, but even they come
624 at a cost, since it is preferable to be able to compile a binary in debug
625 mode for as long as possible on the road to production.
626- **Prefer to use DCHECK_* variants for internal asserts** that attempt to
627 catch module-author level programming errors. For example, use DCHECKs to
628 verify internal function preconditions, or other invariants that should
629 always be true but will likely never fire in production. In some cases using
630 ``CHECK_*`` macros for internal consistency checking can make sense, if the
631 runtime cost is low and there are only a couple of instances.
632
633.. tip::
634
Keir Mierle481d8292020-07-31 01:10:05 -0700635 **Do not return error status codes for obvious API misuse**
Keir Mierle3f356722020-07-31 00:43:43 -0700636
Keir Mierle77d3cbd2020-08-03 21:14:38 -0700637 Returning an error code may **mask the earliest sign of a bug** because
638 notifying the developer of the problem depends on correct propagation of the
639 error to upper levels of the system. Instead, prefer to use the ``CHECK_*``
640 or ``DCHECK_*`` macros to ensure a prompt termination and warning to the
641 developer.
Keir Mierle3f356722020-07-31 00:43:43 -0700642
Keir Mierle77d3cbd2020-08-03 21:14:38 -0700643 **Error status codes should be reserved for system misbehaviour or expected
644 exceptional cases**, like a sensor is not yet ready, or a storage subsystem
645 is full when writing. Doing ``CHECK_*`` assertions in those cases would be a
Keir Mierle3f356722020-07-31 00:43:43 -0700646 mistake; so use error codes in those cases instead.
647
Keir Mierle49f8e7e2020-07-30 17:57:30 -0700648How should objects be asserted against or compared?
Erik Gilling40915502021-11-12 17:16:48 +0000649===================================================
Shiva Rajagopal9e516562021-05-11 17:04:15 -0700650Unfortunately, there is no native mechanism for this, and instead the way to
Keir Mierle49f8e7e2020-07-30 17:57:30 -0700651assert object states or comparisons is with the normal ``PW_CHECK_*`` macros
652that operate on booleans, ints, and floats.
Keir Mierlec1cb12d2020-06-01 11:59:41 -0700653
Keir Mierle49f8e7e2020-07-30 17:57:30 -0700654This is due to the requirement of supporting C and also tokenization. It may be
Shiva Rajagopal9e516562021-05-11 17:04:15 -0700655possible support rich object comparisons by defining a convention for
Keir Mierle49f8e7e2020-07-30 17:57:30 -0700656stringifying objects; however, this hasn't been added yet. Additionally, such a
657mechanism would not work well with tokenization. In particular, it would
658require runtime stringifying arguments and rendering them with ``%s``, which
659leads to binary bloat even with tokenization. So it is likely that a rich
660object assert API won't be added.
661
662Why was the assert facade designed this way?
Erik Gilling40915502021-11-12 17:16:48 +0000663============================================
Keir Mierle49f8e7e2020-07-30 17:57:30 -0700664The Pigweed assert API was designed taking into account the needs of several
665past projects the team members were involved with. Based on those experiences,
666the following were key requirements for the API:
667
6681. **C compatibility** - Since asserts are typically invoked from arbitrary
669 contexts, including from vendor or third party code, the assert system must
670 have a C-compatible API. Some API functions working only in C++ is
671 acceptable, as long as the key functions work in C.
6722. **Capturing both expressions and values** - Since asserts can trigger in
673 ways that are not repeatable, it is important to capture rich diagnostic
674 information to help identifying the root cause of the fault. For asserts,
675 this means including the failing expression text, and optionally also
676 capturing failing expression values. For example, instead of capturing an
677 error with the expression (``x < y``), capturing an error with the
678 expression and values(``x < y, with x = 10, y = 0``).
6793. **Tokenization compatible** - It's important that the assert expressions
680 support tokenization; both the expression itself (e.g. ``a < b``) and the
681 message attached to the expression. For example: ``PW_CHECK(ItWorks(), "Ruh
682 roh: %d", some_int)``.
6834. **Customizable assert handling** - Most products need to support custom
684 handling of asserts. In some cases, an assert might trigger printing out
685 details to a UART; in other cases, it might trigger saving a log entry to
686 flash. The assert system must support this customization.
687
688The combination of #1, #2, and #3 led to the structure of the API. In
689particular, the need to support tokenized asserts and the need to support
690capturing values led to the choice of having ``PW_CHECK_INT_LE(a, b)`` instead
691of ``PW_CHECK(a <= b)``. Needing to support tokenization is what drove the
692facade & backend arrangement, since the backend must provide the raw macros for
693asserting in that case, rather than terminating at a C-style API.
694
695Why isn't there a ``PW_CHECK_LE``? Why is the type (e.g. ``INT``) needed?
Erik Gilling40915502021-11-12 17:16:48 +0000696=========================================================================
Keir Mierle49f8e7e2020-07-30 17:57:30 -0700697The problem with asserts like ``PW_CHECK_LE(a, b)`` instead of
698``PW_CHECK_INT_LE(a, b)`` or ``PW_CHECK_FLOAT_EXACT_LE(a, b)`` is that to
699capture the arguments with the tokenizer, we need to know the types. Using the
700preprocessor, it is impossible to dispatch based on the types of ``a`` and
701``b``, so unfortunately having a separate macro for each of the types commonly
702asserted on is necessary.
Keir Mierlec1cb12d2020-06-01 11:59:41 -0700703
Ewout van Bekkum2aff88e2021-11-12 15:36:57 -0800704----------------------------
705Module Configuration Options
706----------------------------
707The following configurations can be adjusted via compile-time configuration of
708this module, see the
709:ref:`module documentation <module-structure-compile-time-configuration>` for
710more details.
711
712.. c:macro:: PW_ASSERT_ENABLE_DEBUG
713
714 Controls whether ``DCHECK`` and ``DASSERT`` are enabled.
715
716 This defaults to being disabled if ``NDEBUG`` is defined, else it is enabled
717 by default.
718
Keir Mierlec1cb12d2020-06-01 11:59:41 -0700719-------------
720Compatibility
721-------------
Keir Mierle77d3cbd2020-08-03 21:14:38 -0700722The facade is compatible with both C and C++.
723
724----------------
725Roadmap & Status
726----------------
Keir Mierle77d3cbd2020-08-03 21:14:38 -0700727The Pigweed assert subsystem consiststs of several modules that work in
Keir Mierle854adec2020-09-03 14:07:19 -0700728coordination. This module is the facade (API), then a number of backends are
729available to handle assert failures. Products can also define their own
730backends. In some cases, the backends will have backends (like
731``pw_log_tokenized``).
Keir Mierle77d3cbd2020-08-03 21:14:38 -0700732
Keir Mierle854adec2020-09-03 14:07:19 -0700733Below is a brief summary of what modules are ready for use:
Keir Mierle77d3cbd2020-08-03 21:14:38 -0700734
Erik Gilling40915502021-11-12 17:16:48 +0000735Available Assert Backends
736=========================
Keir Mierle77d3cbd2020-08-03 21:14:38 -0700737- ``pw_assert`` - **Stable** - The assert facade (this module). This module is
738 stable, and in production use. The documentation is comprehensive and covers
739 the functionality. There are (a) tests for the facade macro processing logic,
740 using a fake assert backend; and (b) compile tests to verify that the
741 selected backend compiles with all supported assert constructions and types.
742- ``pw_assert_basic`` - **Stable** - The assert basic module is a simple assert
743 handler that displays the failed assert line and the values of captured
744 arguments. Output is directed to ``pw_sys_io``. This module is a great
745 ready-to-roll module when bringing up a system, but is likely not the best
746 choice for production.
Keir Mierle854adec2020-09-03 14:07:19 -0700747- ``pw_assert_log`` - **Stable** - This assert backend redirects to logging,
748 but with a logging flag set that indicates an assert failure. This is our
749 advised approach to get **tokenized asserts**--by using tokenized logging,
750 then using the ``pw_assert_log`` backend.
Keir Mierle77d3cbd2020-08-03 21:14:38 -0700751
Keir Mierle854adec2020-09-03 14:07:19 -0700752Note: If one desires a null assert module (where asserts are removed), use
753``pw_assert_log`` in combination with ``pw_log_null``. This will direct asserts
754to logs, then the logs are removed due to the null backend.
Keir Mierle77d3cbd2020-08-03 21:14:38 -0700755
Erik Gilling40915502021-11-12 17:16:48 +0000756Missing Functionality
757=====================
Keir Mierle77d3cbd2020-08-03 21:14:38 -0700758- **Stack traces** - Pigweed doesn't have a reliable stack walker, which makes
759 displaying a stack trace on crash harder. We plan to add this eventually.
760- **Snapshot integration** - Pigweed doesn't yet have a rich system state
761 capture system that can capture state like number of tasks, available memory,
762 and so on. Snapshot facilities are the obvious ones to run inside an assert
763 handler. It'll happen someday.