xref: /aosp_15_r20/external/pigweed/pw_assert/docs.rst (revision 61c4878ac05f98d0ceed94b57d316916de578985)
1.. _module-pw_assert:
2
3=========
4pw_assert
5=========
6.. pigweed-module::
7   :name: pw_assert
8
9--------
10Overview
11--------
12Pigweed's assert module enables applications to check preconditions, triggering
13a crash if the condition is not met. Consistent use of asserts is one aspect of
14defensive programming that can lead to more reliable and less buggy code.
15
16The assert API facilitates flexible crash handling through Pigweed's facade
17mechanism. The API is designed to enable features like:
18
19- Optional ancillary printf-style messages along assertions
20- Capturing actual values of binary operator assertions like ``a < b``
21- Compatibility with pw_tokenizer for reduced binary code size
22
23The ``pw_assert`` API provides three classes of macros:
24
25- **PW_CRASH(format, ...)** - Trigger a crash with a message.
26- **PW_CHECK(condition[, format, ...])** - Assert a condition, optionally with
27  a message.
28- **PW_CHECK_<type>_<cmp>(a, b[, fmt, ...])** - Assert that the expression ``a
29  <cmp> b`` is true, optionally with a message.
30- **PW_ASSERT(condition)** - Header- and constexpr-safe assert.
31
32.. tip::
33
34  All of the ``CHECK`` macros optionally support a message with additional
35  arguments, to assist in debugging when an assert triggers:
36
37  .. code-block:: cpp
38
39     PW_CHECK_INT_LE(ItemCount(), 100);
40     PW_CHECK_INT_LE(ItemCount(), 100, "System state: %s", GetStateStr());
41
42  To ensure compatibility with :ref:`module-pw_assert_log` and
43  :ref:`module-pw_log_tokenized`, the message must be a string literal.
44
45Example
46=======
47
48.. code-block:: cpp
49
50   #include "pw_assert/check.h"
51
52   int main() {
53     bool sensor_running = StartSensor(&msg);
54     PW_CHECK(sensor_running, "Sensor failed to start; code: %s", msg);
55
56     int temperature_c = ReadSensorCelcius();
57     PW_CHECK_INT_LE(temperature_c, 100,
58                     "System is way out of heat spec; state=%s",
59                     ReadSensorStateString());
60   }
61
62.. tip::
63
64  All macros have both a ``CHECK`` and ``DCHECK`` variant. The ``CHECK``
65  variant is always enabled, even in production. Generally, we advise making
66  most asserts ``CHECK`` rather than ``DCHECK``, unless there is a critical
67  performance or code size reason to use ``DCHECK``.
68
69  .. code-block:: cpp
70
71     // This assert is always enabled, even in production.
72     PW_CHECK_INT_LE(ItemCount(), 100);
73
74     // This assert is enabled based on ``PW_ASSERT_ENABLE_DEBUG``.
75     // The functions ItemCount() and GetStateStr() are never called.
76     PW_DCHECK_INT_LE(ItemCount(), 100, "System state: %s", GetStateStr());
77
78.. tip::
79
80  Use ``PW_ASSERT`` from ``pw_assert/assert.h`` for asserts in headers or
81  asserting in ``constexpr`` contexts.
82
83Structure of Assert Modules
84===========================
85The module is split into two components:
86
871. The **facade** (this module) which is only a macro interface layer, and
88   performs the actual checks for the conditions.
892. The **backend**, provided elsewhere, that handles the consequences of an
90   assert failing. Example backends include ``pw_assert_basic``, which prints a
91   useful message and either quits the application (on host) or hangs in a
92   while loop (on device). In the future, there will be a tokenized assert
93   backend. This is also where application or product specific crash handling
94   would go.
95
96.. mermaid::
97
98  graph LR
99    facade --> backend
100
101See the Backend API section below for more details.
102
103----------
104Facade API
105----------
106The below functions describe the assert API functions that applications should
107invoke to assert. These macros are found in the ``pw_assert/check.h`` header.
108
109.. cpp:function:: PW_CRASH(format, ...)
110
111  Trigger a crash with a message. Replaces LOG_FATAL() in other systems. Can
112  include a message with format arguments; for example:
113
114  .. code-block:: cpp
115
116     PW_CRASH("Unexpected: frobnitz in state: %s", frobnitz_state);
117
118  Note: ``PW_CRASH`` is the equivalent of ``LOG_FATAL`` in other systems, where
119  a device crash is triggered with a message. In Pigweed, logging and
120  crashing/asserting are separated. There is a ``LOG_CRITICAL`` level in the
121  logging module, but it does not have side effects; for ``LOG_FATAL``, instead
122  use this macro (``PW_CRASH``).
123
124.. cpp:function:: PW_CHECK(condition)
125.. cpp:function:: PW_CHECK(condition, format, ...)
126.. cpp:function:: PW_DCHECK(condition)
127.. cpp:function:: PW_DCHECK(condition, format, ...)
128
129  Assert that a condition is true, optionally including a message with
130  arguments to report if the codition is false.
131
132  The ``DCHECK`` variants only run if ``PW_ASSERT_ENABLE_DEBUG`` is enabled;
133  otherwise, the entire statement is removed (and the expression not evaluated).
134
135  Example:
136
137  .. code-block:: cpp
138
139     PW_CHECK(StartTurbines());
140     PW_CHECK(StartWarpDrive(), "Oddly warp drive couldn't start; ruh-roh!");
141     PW_CHECK(RunSelfTest(), "Failure in self test; try %d", TestAttempts());
142
143  .. attention::
144
145    Don't use use ``PW_CHECK`` for binary comparisons or status checks!
146
147    Instead, use the ``PW_CHECK_<TYPE>_<OP>`` macros. These macros enable
148    capturing the value of the operands, and also tokenizing them if using a
149    tokenizing assert backend. For example, if ``x`` and ``b`` are integers,
150    use instead ``PW_CHECK_INT_LT(x, b)``.
151
152    Additionally, use ``PW_CHECK_OK(status)`` when checking for an OK status,
153    since it enables showing a human-readable status string rather than an
154    integer (e.g. ``status == RESOURCE_EXHAUSTED`` instead of ``status == 5``.
155    This works with any expression convertible to ``pw::Status``, including
156    ``pw::StatusWithString`` and ``pw::Result<T>``.
157
158    +------------------------------------+-------------------------------------+
159    | **Do NOT do this**                 | **Do this instead**                 |
160    +------------------------------------+-------------------------------------+
161    | ``PW_CHECK(a_int < b_int)``        | ``PW_CHECK_INT_LT(a_int, b_int)``   |
162    +------------------------------------+-------------------------------------+
163    | ``PW_CHECK(a_ptr <= b_ptr)``       | ``PW_CHECK_PTR_LE(a_ptr, b_ptr)``   |
164    +------------------------------------+-------------------------------------+
165    | ``PW_CHECK(Temp() <= 10.0)``       | ``PW_CHECK_FLOAT_EXACT_LE(``        |
166    |                                    | ``    Temp(), 10.0)``               |
167    +------------------------------------+-------------------------------------+
168    | ``PW_CHECK(Foo() == OkStatus())``  | ``PW_CHECK_OK(Foo())``              |
169    +------------------------------------+-------------------------------------+
170
171.. cpp:function:: PW_CHECK_NOTNULL(ptr)
172.. cpp:function:: PW_CHECK_NOTNULL(ptr, format, ...)
173.. cpp:function:: PW_DCHECK_NOTNULL(ptr)
174.. cpp:function:: PW_DCHECK_NOTNULL(ptr, format, ...)
175
176  Assert that the given pointer is not ``NULL``, optionally including a message
177  with arguments to report if the pointer is ``NULL``.
178
179  The ``DCHECK`` variants only run if ``PW_ASSERT_ENABLE_DEBUG`` is enabled;
180  otherwise, the entire statement is removed (and the expression not evaluated).
181
182  .. code-block:: cpp
183
184     Foo* foo = GetTheFoo()
185     PW_CHECK_NOTNULL(foo);
186
187     Bar* bar = GetSomeBar();
188     PW_CHECK_NOTNULL(bar, "Weirdly got NULL bar; state: %d", MyState());
189
190.. cpp:function:: PW_CHECK_TYPE_OP(a, b)
191.. cpp:function:: PW_CHECK_TYPE_OP(a, b, format, ...)
192.. cpp:function:: PW_DCHECK_TYPE_OP(a, b)
193.. cpp:function:: PW_DCHECK_TYPE_OP(a, b, format, ...)
194
195  Asserts that ``a OP b`` is true, where ``a`` and ``b`` are converted to
196  ``TYPE``; with ``OP`` and ``TYPE`` described below.
197
198  If present, the optional format message is reported on failure. Depending on
199  the backend, values of ``a`` and ``b`` will also be reported.
200
201  The ``DCHECK`` variants only run if ``PW_ASSERT_ENABLE_DEBUG`` is enabled;
202  otherwise, the entire statement is removed (and the expression not evaluated).
203
204  Example, with no message:
205
206  .. code-block:: cpp
207
208     PW_CHECK_INT_LE(CurrentTemperature(), 100);
209     PW_CHECK_INT_LE(ItemCount(), 100);
210
211  Example, with an included message and arguments:
212
213  .. code-block:: cpp
214
215     PW_CHECK_FLOAT_EXACT_GE(BatteryVoltage(), 3.2,
216                             "System state=%s", SysState());
217
218  Below is the full list of binary comparison assert macros, along with the
219  type specifier. The specifier is irrelevant to application authors but is
220  needed for backend implementers.
221
222  +-------------------------+--------------+-----------+-----------------------+
223  | Macro                   | a, b type    | condition | a, b format specifier |
224  +-------------------------+--------------+-----------+-----------------------+
225  | PW_CHECK_INT_LE         | int          | a <= b    | %d                    |
226  +-------------------------+--------------+-----------+-----------------------+
227  | PW_CHECK_INT_LT         | int          | a <  b    | %d                    |
228  +-------------------------+--------------+-----------+-----------------------+
229  | PW_CHECK_INT_GE         | int          | a >= b    | %d                    |
230  +-------------------------+--------------+-----------+-----------------------+
231  | PW_CHECK_INT_GT         | int          | a >  b    | %d                    |
232  +-------------------------+--------------+-----------+-----------------------+
233  | PW_CHECK_INT_EQ         | int          | a == b    | %d                    |
234  +-------------------------+--------------+-----------+-----------------------+
235  | PW_CHECK_INT_NE         | int          | a != b    | %d                    |
236  +-------------------------+--------------+-----------+-----------------------+
237  | PW_CHECK_UINT_LE        | unsigned int | a <= b    | %u                    |
238  +-------------------------+--------------+-----------+-----------------------+
239  | PW_CHECK_UINT_LT        | unsigned int | a <  b    | %u                    |
240  +-------------------------+--------------+-----------+-----------------------+
241  | PW_CHECK_UINT_GE        | unsigned int | a >= b    | %u                    |
242  +-------------------------+--------------+-----------+-----------------------+
243  | PW_CHECK_UINT_GT        | unsigned int | a >  b    | %u                    |
244  +-------------------------+--------------+-----------+-----------------------+
245  | PW_CHECK_UINT_EQ        | unsigned int | a == b    | %u                    |
246  +-------------------------+--------------+-----------+-----------------------+
247  | PW_CHECK_UINT_NE        | unsigned int | a != b    | %u                    |
248  +-------------------------+--------------+-----------+-----------------------+
249  | PW_CHECK_PTR_LE         | void*        | a <= b    | %p                    |
250  +-------------------------+--------------+-----------+-----------------------+
251  | PW_CHECK_PTR_LT         | void*        | a <  b    | %p                    |
252  +-------------------------+--------------+-----------+-----------------------+
253  | PW_CHECK_PTR_GE         | void*        | a >= b    | %p                    |
254  +-------------------------+--------------+-----------+-----------------------+
255  | PW_CHECK_PTR_GT         | void*        | a >  b    | %p                    |
256  +-------------------------+--------------+-----------+-----------------------+
257  | PW_CHECK_PTR_EQ         | void*        | a == b    | %p                    |
258  +-------------------------+--------------+-----------+-----------------------+
259  | PW_CHECK_PTR_NE         | void*        | a != b    | %p                    |
260  +-------------------------+--------------+-----------+-----------------------+
261  | PW_CHECK_FLOAT_EXACT_LE | float        | a <= b    | %f                    |
262  +-------------------------+--------------+-----------+-----------------------+
263  | PW_CHECK_FLOAT_EXACT_LT | float        | a <  b    | %f                    |
264  +-------------------------+--------------+-----------+-----------------------+
265  | PW_CHECK_FLOAT_EXACT_GE | float        | a >= b    | %f                    |
266  +-------------------------+--------------+-----------+-----------------------+
267  | PW_CHECK_FLOAT_EXACT_GT | float        | a >  b    | %f                    |
268  +-------------------------+--------------+-----------+-----------------------+
269  | PW_CHECK_FLOAT_EXACT_EQ | float        | a == b    | %f                    |
270  +-------------------------+--------------+-----------+-----------------------+
271  | PW_CHECK_FLOAT_EXACT_NE | float        | a != b    | %f                    |
272  +-------------------------+--------------+-----------+-----------------------+
273
274  The above ``CHECK_*_*()`` are also available in DCHECK variants, which will
275  only evaluate their arguments and trigger if the ``PW_ASSERT_ENABLE_DEBUG``
276  macro is enabled.
277
278  +--------------------------+--------------+-----------+----------------------+
279  | Macro                    | a, b type    | condition | a, b format          |
280  |                          |              |           | specifier            |
281  +--------------------------+--------------+-----------+----------------------+
282  | PW_DCHECK_INT_LE         | int          | a <= b    | %d                   |
283  +--------------------------+--------------+-----------+----------------------+
284  | PW_DCHECK_INT_LT         | int          | a <  b    | %d                   |
285  +--------------------------+--------------+-----------+----------------------+
286  | PW_DCHECK_INT_GE         | int          | a >= b    | %d                   |
287  +--------------------------+--------------+-----------+----------------------+
288  | PW_DCHECK_INT_GT         | int          | a >  b    | %d                   |
289  +--------------------------+--------------+-----------+----------------------+
290  | PW_DCHECK_INT_EQ         | int          | a == b    | %d                   |
291  +--------------------------+--------------+-----------+----------------------+
292  | PW_DCHECK_INT_NE         | int          | a != b    | %d                   |
293  +--------------------------+--------------+-----------+----------------------+
294  | PW_DCHECK_UINT_LE        | unsigned int | a <= b    | %u                   |
295  +--------------------------+--------------+-----------+----------------------+
296  | PW_DCHECK_UINT_LT        | unsigned int | a <  b    | %u                   |
297  +--------------------------+--------------+-----------+----------------------+
298  | PW_DCHECK_UINT_GE        | unsigned int | a >= b    | %u                   |
299  +--------------------------+--------------+-----------+----------------------+
300  | PW_DCHECK_UINT_GT        | unsigned int | a >  b    | %u                   |
301  +--------------------------+--------------+-----------+----------------------+
302  | PW_DCHECK_UINT_EQ        | unsigned int | a == b    | %u                   |
303  +--------------------------+--------------+-----------+----------------------+
304  | PW_DCHECK_UINT_NE        | unsigned int | a != b    | %u                   |
305  +--------------------------+--------------+-----------+----------------------+
306  | PW_DCHECK_PTR_LE         | void*        | a <= b    | %p                   |
307  +--------------------------+--------------+-----------+----------------------+
308  | PW_DCHECK_PTR_LT         | void*        | a <  b    | %p                   |
309  +--------------------------+--------------+-----------+----------------------+
310  | PW_DCHECK_PTR_GE         | void*        | a >= b    | %p                   |
311  +--------------------------+--------------+-----------+----------------------+
312  | PW_DCHECK_PTR_GT         | void*        | a >  b    | %p                   |
313  +--------------------------+--------------+-----------+----------------------+
314  | PW_DCHECK_PTR_EQ         | void*        | a == b    | %p                   |
315  +--------------------------+--------------+-----------+----------------------+
316  | PW_DCHECK_PTR_NE         | void*        | a != b    | %p                   |
317  +--------------------------+--------------+-----------+----------------------+
318  | PW_DCHECK_FLOAT_EXACT_LE | float        | a <= b    | %f                   |
319  +--------------------------+--------------+-----------+----------------------+
320  | PW_DCHECK_FLOAT_EXACT_LT | float        | a <  b    | %f                   |
321  +--------------------------+--------------+-----------+----------------------+
322  | PW_DCHECK_FLOAT_EXACT_GE | float        | a >= b    | %f                   |
323  +--------------------------+--------------+-----------+----------------------+
324  | PW_DCHECK_FLOAT_EXACT_GT | float        | a >  b    | %f                   |
325  +--------------------------+--------------+-----------+----------------------+
326  | PW_DCHECK_FLOAT_EXACT_EQ | float        | a == b    | %f                   |
327  +--------------------------+--------------+-----------+----------------------+
328  | PW_DCHECK_FLOAT_EXACT_NE | float        | a != b    | %f                   |
329  +--------------------------+--------------+-----------+----------------------+
330
331.. attention::
332
333  For float, proper comparator checks which take floating point
334  precision and ergo error accumulation into account are not provided on
335  purpose as this comes with some complexity and requires application
336  specific tolerances in terms of Units of Least Precision (ULP). Instead,
337  carefully consider how floating point precision and error impact the data
338  they are bounding and whether checks are appropriate.
339
340.. cpp:function:: PW_CHECK_FLOAT_NEAR(a, b, abs_tolerance)
341.. cpp:function:: PW_CHECK_FLOAT_NEAR(a, b, abs_tolerance, format, ...)
342.. cpp:function:: PW_DCHECK_FLOAT_NEAR(a, b, abs_tolerance)
343.. cpp:function:: PW_DCHECK_FLOAT_NEAR(a, b, abs_tolerance, format, ...)
344
345  Asserts that ``(a >= b - abs_tolerance) && (a <= b + abs_tolerance)`` is true,
346  where ``a``, ``b``, and ``abs_tolerance`` are converted to ``float``.
347
348  .. note::
349    This also asserts that ``abs_tolerance >= 0``.
350
351  The ``DCHECK`` variants only run if ``PW_ASSERT_ENABLE_DEBUG`` is enabled;
352  otherwise, the entire statement is removed (and the expression not evaluated).
353
354  Example, with no message:
355
356  .. code-block:: cpp
357
358     PW_CHECK_FLOAT_NEAR(cos(0.0f), 1, 0.001);
359
360  Example, with an included message and arguments:
361
362  .. code-block:: cpp
363
364     PW_CHECK_FLOAT_NEAR(FirstOperation(), RedundantOperation(), 0.1,
365                         "System state=%s", SysState());
366
367.. cpp:function:: PW_CHECK_OK(status)
368.. cpp:function:: PW_CHECK_OK(status, format, ...)
369.. cpp:function:: PW_DCHECK_OK(status)
370.. cpp:function:: PW_DCHECK_OK(status, format, ...)
371
372  Assert that ``status`` evaluates to ``pw::OkStatus()`` (in C++) or
373  ``PW_STATUS_OK`` (in C). Optionally include a message with arguments to
374  report.
375
376  ``status`` can be a ``pw::Status``, or (in C++ only) any expression
377  convertible to ``pw::Status``, including ``pw::StatusWithString`` and
378  ``pw::Result<T>``.
379
380  The ``DCHECK`` variants only run if ``PW_ASSERT_ENABLE_DEBUG`` is defined;
381  otherwise, the entire statement is removed (and the expression not evaluated).
382
383  .. code-block:: cpp
384
385     pw::Status operation_status = DoSomeOperation();
386     PW_CHECK_OK(operation_status);
387
388     // Any expression that evaluates to a pw::Status or pw_Status works.
389     PW_CHECK_OK(DoTheThing(), "System state: %s", SystemState());
390
391     // pw::Result<T> works.
392     pw::Result<int> result = GetSomething();
393     PW_CHECK_OK(result);
394
395     // C works too.
396     pw_Status c_status = DoMoreThings();
397     PW_CHECK_OK(c_status, "System state: %s", SystemState());
398
399  .. note::
400
401    Using ``PW_CHECK_OK(status)`` instead of ``PW_CHECK(status == OkStatus())``
402    enables displaying an error message with a string version of the error
403    code; for example ``status == RESOURCE_EXHAUSTED`` instead of ``status ==
404    5``.
405
406``%`` in conditions
407===================
408``PW_CHECK`` conditions cannot contain the ``%`` character (e.g. from the
409modulus operator), since it may be interpreted as a printf-style format
410specifier. Some backends (:ref:`module-pw_assert_tokenized` in particular) may
411include the condition in the format string as a size optimization.
412Unintentionally introducing an extra %-style argument could lead to problems, so
413``pw_assert`` prevents this.
414
415Using a % in a ``PW_CHECK`` condition causes errors like the following:
416
417.. code-block:: none
418
419   ../pw_assert/public/pw_assert/internal/check_impl.h:237:7: note: expanded from macro '_PW_CHECK_BINARY_ARG_HANDLER'
420     237 |       arg_a_str arg_b_str); /* cannot use '%' here; call mod via a function */ \
421
422To avoid errors like this, do not use ``%`` in ``PW_CHECK`` conditions. Modulus
423can be moved to a separate statement outside of the ``PW_CHECK`` or invoked via
424a function or `std::modulus
425<https://en.cppreference.com/w/cpp/utility/functional/modulus>`_.
426
427This restriction may be removed in the future (`b/235149326
428<https://issues.pigweed.dev/issues/235149326>`_)
429
430.. _module-pw_assert-assert-api:
431
432----------
433Assert API
434----------
435The normal ``PW_CHECK_*`` and ``PW_DCHECK_*`` family of macros are intended to
436provide rich debug information, like the file, line number, value of operands
437in boolean comparisons, and more. However, this comes at a cost: these macros
438depend directly on the backend headers, and may perform complicated call-site
439transformations like tokenization.
440
441There are several issues with the normal ``PW_CHECK_*`` suite of macros:
442
4431. ``PW_CHECK_*`` in headers can cause ODR violations in the case of tokenized
444   asserts, due to differing module choices.
4452. ``PW_CHECK_*`` is not constexpr-safe.
4463. ``PW_CHECK_*`` can cause code bloat with some backends; this is the tradeoff
447   to get rich assert information.
4484. ``PW_CHECK_*`` can trigger circular dependencies when asserts are used from
449   low-level contexts, like in ``<span>``.
450
451**PW_ASSERT** solves all of the above problems: No risk of ODR violations, are
452constexpr safe, and have a tiny call site footprint; and there is no header
453dependency on the backend preventing circular include issues.  However, there
454are **no format messages, no captured line number, no captured file, no captured
455expression, or anything other than a binary indication of failure**.
456
457Example
458=======
459
460.. code-block:: cpp
461
462   // This example demonstrates asserting in a header.
463
464   #include "pw_assert/assert.h"
465
466   class InlinedSubsystem {
467    public:
468     void DoSomething() {
469       // GOOD: No problem; PW_ASSERT is fine to inline and place in a header.
470       PW_ASSERT(IsEnabled());
471     }
472     void DoSomethingElse() {
473       // BAD: Generally avoid using PW_DCHECK() or PW_CHECK in headers. If you
474       // want rich asserts or logs, move the function into the .cc file, and
475       // then use PW_CHECK there.
476       PW_DCHECK(IsEnabled());  // DON'T DO THIS
477     }
478   };
479
480PW_ASSERT API Reference
481=======================
482.. cpp:function:: PW_ASSERT(condition)
483
484  A header- and constexpr-safe version of ``PW_CHECK()``.
485
486  If the given condition is false, crash the system. Otherwise, do nothing.
487  The condition is guaranteed to be evaluated. This assert implementation is
488  guaranteed to be constexpr-safe.
489
490.. cpp:function:: PW_DASSERT(condition)
491
492  A header- and constexpr-safe version of ``PW_DCHECK()``.
493
494  Same as ``PW_ASSERT()``, except that if ``PW_ASSERT_ENABLE_DEBUG == 0``, the
495  assert is disabled and condition is not evaluated.
496
497.. cpp:function:: PW_ASSERT_OK(expression)
498
499  A header- and constexpr-safe version of ``PW_CHECK_OK()``.
500
501  If the given expression is not `OK`, crash the system. Otherwise, do nothing.
502  The condition is guarenteed to be evaluated.
503
504.. attention::
505
506  Unlike the ``PW_CHECK_*()`` suite of macros, ``PW_ASSERT()`` and
507  ``PW_DASSERT()`` capture no rich information like line numbers, the file,
508  expression arguments, or the stringified expression. Use these macros **only
509  when absolutely necessary**---in headers, constexpr contexts, or in rare cases
510  where the call site overhead of a full PW_CHECK must be avoided.
511
512  Use ``PW_CHECK_*()`` whenever possible.
513
514PW_ASSERT API Backend
515=====================
516The ``PW_ASSERT`` API ultimately calls the C function
517``pw_assert_HandleFailure()``, which must be provided by the ``pw_assert``
518backend. The ``pw_assert_HandleFailure()`` function must not return.
519
520.. _module-pw_assert-circular-deps:
521
522Avoiding Circular Dependencies With ``PW_ASSERT``
523=================================================
524Because asserts are so widely used, including in low-level libraries, it is
525common for the ``pw_assert`` backend to cause circular dependencies. Because of
526this, assert backends may avoid declaring explicit dependencies, instead relying
527on include paths to access header files.
528
529GN
530--
531In GN, the ``pw_assert`` backend's full implementation with true dependencies is
532made available through the ``$dir_pw_assert:impl`` group. When
533``pw_assert_BACKEND`` is set, ``$dir_pw_assert:impl`` must be listed in the
534``pw_build_LINK_DEPS`` variable. See :ref:`module-pw_build-link-deps`.
535
536In the ``pw_assert``, the backend's full implementation is placed in the
537``$pw_assert_BACKEND.impl`` target. ``$dir_pw_assert:impl`` depends on this
538backend target. The ``$pw_assert_BACKEND.impl`` target may be an empty group if
539the backend target can use its dependencies directly without causing circular
540dependencies.
541
542In order to break dependency cycles, the ``pw_assert_BACKEND`` target may need
543to directly provide dependencies through include paths only, rather than GN
544``public_deps``. In this case, GN header checking can be disabled with
545``check_includes = false``.
546
547Bazel
548-----
549In Bazel, assert backends may break dependency cycles by placing the full
550implementation in an ``impl`` target, like ``//pw_assert_basic:impl`` or
551``//pw_assert_tokenized:impl``. The ``//pw_assert:backend_impl`` label flag
552should be set to the ``impl`` target required by the assert backend used by the
553platform.
554
555You must add a dependency on the ``@pigweed//pw_assert:backend_impl`` target to
556any binary using ``pw_assert``.
557
558See :ref:`docs-build_system-bazel_link-extra-lib` for a general discussion of
559cyclic dependencies in low-level libraries in Bazel.
560
561.. _module-pw_assert-backend_api:
562
563-----------
564Backend API
565-----------
566The backend controls what to do in the case of an assertion failure. In the
567most basic cases, the backend could display the assertion failure on something
568like sys_io and halt in a while loop waiting for a debugger. In other cases,
569the backend could store crash details like the current thread's stack to flash.
570
571This facade module (``pw_assert``) does not provide a backend. See
572:ref:`module-pw_assert_basic` for a basic implementation.
573
574.. attention::
575
576  The facade macros (``PW_CRASH`` and related) are expected to behave like they
577  have the ``[[noreturn]]`` attribute set. This implies that the backend handler
578  functions, ``PW_HANDLE_*`` defined by the backend, must not return.
579
580  In other words, the device must reboot.
581
582The backend must provide the header
583
584``pw_assert_backend/check_backend.h``
585
586and that header must define the following macros:
587
588.. cpp:function:: PW_HANDLE_CRASH(message, ...)
589
590  Trigger a system crash or halt, and if possible, deliver the specified
591  message and arguments to the user or developer.
592
593.. cpp:function:: PW_HANDLE_ASSERT_FAILURE(condition_str, message, ...)
594
595  Trigger a system crash or halt, and if possible, deliver the condition string
596  (indicating what expression was false) and the message with format arguments,
597  to the user or developer.
598
599  This macro is invoked from the ``PW_CHECK`` facade macro if condition is
600  false.
601
602.. cpp:function:: PW_HANDLE_ASSERT_BINARY_COMPARE_FAILURE( \
603    a_str, a_val, op_str, b_str, b_val, type_fmt, message, ...)
604
605  Trigger a system crash or halt for a failed binary comparison assert (e.g.
606  any of the ``PW_CHECK_<type>_<op>`` macros). The handler should combine the
607  assert components into a useful message for the user; though in some cases
608  this may not be possible.
609
610  Consider the following example:
611
612  .. code-block:: cpp
613
614     int temp = 16;
615     int max_temp = 15;
616     PW_CHECK_INT_LE(temp, MAX_TEMP, "Got too hot; state: %s", GetSystemState());
617
618  In this block, the assert will trigger, which will cause the facade to invoke
619  the handler macro. Below is the meaning of the arguments, referencing to the
620  example:
621
622  - ``a_str`` - Stringified first operand. In the example: ``"temp"``.
623  - ``a_val`` - The value of the first operand. In the example: ``16``.
624  - ``op_str`` - The string version of the operator. In the example: "<=".
625  - ``b_str`` - Stringified second operand. In the example: ``"max_temp"``.
626  - ``b_val`` - The value of the second operand. In the example: ``15``.
627  - ``type_fmt`` - The format code for the type. In the example: ``"%d"``.
628  - ``message, ...`` - A formatted message to go with the assert. In the
629    example: ``"Got too hot; state: %s", "ON_FIRE"``.
630
631  .. tip::
632
633    See :ref:`module-pw_assert_basic` for one way to combine these arguments
634    into a meaningful error message.
635
636Additionally, the backend must provide a link-time function for the
637``PW_ASSERT`` assert handler. This does not need to appear in the backend
638header, but instead is in a ``.cc`` file.
639
640.. cpp:function:: pw_assert_HandleFailure()
641
642  Handle a low-level crash. This crash entry happens through
643  ``pw_assert/assert.h``. In this crash handler, there is no access to line,
644  file, expression, or other rich assert information. Backends should do
645  something reasonable in this case; typically, capturing the stack is useful.
646
647Backend Build Targets
648=====================
649In GN, the backend must provide a ``pw_assert.impl`` build target in the same
650directory as the backend target. If the main backend target's dependencies would
651cause dependency cycles, the actual backend implementation with its full
652dependencies is placed in the ``pw_assert.impl`` target. If this is not
653necessary, ``pw_assert.impl`` can be an empty group. Circular dependencies are a
654common problem with ``pw_assert`` because it is so widely used. See
655:ref:`module-pw_assert-circular-deps`.
656
657Macro-based PW_ASSERT()/PW_DASSERT() backend
658============================================
659The pw_assert API is being re-assessed to provide more helpful information in
660contexts where ``PW_CHECK_*()`` macros cannot be used. A first step towards this
661is providing a macro-based backend API for the ``PW_ASSERT()`` and
662``PW_DASSERT()`` macros.
663
664.. warning::
665  This part of ``pw_assert``'s API is transitional, and any project-specific
666  reliance on any of the API mentioned here will likely experience breakages.
667  In particular, ``PW_ASSERT_HANDLE_FAILURE`` and ``PW_HANDLE_ASSERT_FAILURE``
668  are extremely confusingly similar and are NOT interchangeable.
669
670A macro-based backend for the ``PW_ASSERT()`` macros must provide the following
671macro in a header at ``pw_assert_backend/assert_backend.h``.
672
673.. cpp:function:: PW_ASSERT_HANDLE_FAILURE(expression)
674
675  Handle a low-level crash. This crash entry happens through
676  ``pw_assert/assert.h``. Backends must ensure their implementation is safe for
677  usage in headers, constexpr contexts, and templates. This macro should expand
678  to an expression that does not return.
679
680Similar to the ``PW_CHECK_*()`` facade, the header backend that provides an
681expansion for the ``PW_ASSERT_HANDLE_FAILURE()`` macro can be controlled in the
682GN build using the ``pw_assert_LITE_BACKEND`` build argument. In addition to
683the header-based target at ``${pw_assert_LITE_BACKEND}``, a source set at
684``${pw_assert_LITE_BACKEND}.impl`` is also required as a way to reduce the
685impact of :ref:`circular dependencies <module-pw_assert-circular-deps>`.
686
687--------------------------
688Frequently Asked Questions
689--------------------------
690
691When should DCHECK_* be used instead of CHECK_* and vice versa?
692===============================================================
693There is no hard and fast rule for when to use one or the other.
694
695In theory, ``DCHECK_*`` macros should never be used and all the asserts should
696remain active in production. In practice, **assert statements come at a binary
697size and runtime cost**, even when using extensions like a tokenized assert
698backend that strips the stringified assert expression from the binary. Each
699assert is **at least a branch with a function call**; depending on the assert
700backend, that function call may take several arguments (like the message, the
701file line number, the module, etc). These function calls can take 10-20 bytes
702or more of ROM each. Thus, there is a balance to be struct between ``DCHECK_*``
703and ``CHECK_*``.
704
705Pigweed uses these conventions to decide between ``CHECK_*`` and ``DCHECK_*``:
706
707- **Prefer to use CHECK_* at public API boundaries** of modules, where an
708  invalid value is a clear programmer bug. In certain cases use ``DCHECK_*`` to
709  keep binary size small when in production; for example, in modules with a
710  large public API surface, or modules with many inlined functions in headers.
711- **Avoid using CHECK_* macros in headers.** It is still OK to use ``CHECK_*``
712  macros in headers, but carefully consider the cost, since inlined use of the
713  ``CHECK_*`` macros in headers will expand to the full assert cost for every
714  translation unit that includes the header and calls the function with the
715  ``CHECK_*`` instance. ``DCHECK_*`` macros are are better, but even they come
716  at a cost, since it is preferable to be able to compile a binary in debug
717  mode for as long as possible on the road to production.
718- **Prefer to use DCHECK_* variants for internal asserts** that attempt to
719  catch module-author level programming errors. For example, use DCHECKs to
720  verify internal function preconditions, or other invariants that should
721  always be true but will likely never fire in production. In some cases using
722  ``CHECK_*`` macros for internal consistency checking can make sense, if the
723  runtime cost is low and there are only a couple of instances.
724
725.. tip::
726
727  **Do not return error status codes for obvious API misuse**
728
729  Returning an error code may **mask the earliest sign of a bug** because
730  notifying the developer of the problem depends on correct propagation of the
731  error to upper levels of the system. Instead, prefer to use the ``CHECK_*``
732  or ``DCHECK_*`` macros to ensure a prompt termination and warning to the
733  developer.
734
735  **Error status codes should be reserved for system misbehaviour or expected
736  exceptional cases**, like a sensor is not yet ready, or a storage subsystem
737  is full when writing. Doing ``CHECK_*`` assertions in those cases would be a
738  mistake; so use error codes in those cases instead.
739
740How should objects be asserted against or compared?
741===================================================
742Unfortunately, there is no native mechanism for this, and instead the way to
743assert object states or comparisons is with the normal ``PW_CHECK_*`` macros
744that operate on booleans, ints, and floats.
745
746This is due to the requirement of supporting C and also tokenization. It may be
747possible support rich object comparisons by defining a convention for
748stringifying objects; however, this hasn't been added yet. Additionally, such a
749mechanism would not work well with tokenization. In particular, it would
750require runtime stringifying arguments and rendering them with ``%s``, which
751leads to binary bloat even with tokenization. So it is likely that a rich
752object assert API won't be added.
753
754Why was the assert facade designed this way?
755============================================
756The Pigweed assert API was designed taking into account the needs of several
757past projects the team members were involved with. Based on those experiences,
758the following were key requirements for the API:
759
7601. **C compatibility** - Since asserts are typically invoked from arbitrary
761   contexts, including from vendor or third party code, the assert system must
762   have a C-compatible API. Some API functions working only in C++ is
763   acceptable, as long as the key functions work in C.
7642. **Capturing both expressions and values** - Since asserts can trigger in
765   ways that are not repeatable, it is important to capture rich diagnostic
766   information to help identifying the root cause of the fault. For asserts,
767   this means including the failing expression text, and optionally also
768   capturing failing expression values. For example, instead of capturing an
769   error with the expression (``x < y``), capturing an error with the
770   expression and values(``x < y, with x = 10, y = 0``).
7713. **Tokenization compatible** - It's important that the assert expressions
772   support tokenization; both the expression itself (e.g. ``a < b``) and the
773   message attached to the expression. For example: ``PW_CHECK(ItWorks(), "Ruh
774   roh: %d", some_int)``.
7754. **Customizable assert handling** - Most products need to support custom
776   handling of asserts. In some cases, an assert might trigger printing out
777   details to a UART; in other cases, it might trigger saving a log entry to
778   flash. The assert system must support this customization.
779
780The combination of #1, #2, and #3 led to the structure of the API. In
781particular, the need to support tokenized asserts and the need to support
782capturing values led to the choice of having ``PW_CHECK_INT_LE(a, b)`` instead
783of ``PW_CHECK(a <= b)``. Needing to support tokenization is what drove the
784facade & backend arrangement, since the backend must provide the raw macros for
785asserting in that case, rather than terminating at a C-style API.
786
787Why isn't there a ``PW_CHECK_LE``? Why is the type (e.g. ``INT``) needed?
788=========================================================================
789The problem with asserts like ``PW_CHECK_LE(a, b)`` instead of
790``PW_CHECK_INT_LE(a, b)`` or ``PW_CHECK_FLOAT_EXACT_LE(a, b)`` is that to
791capture the arguments with the tokenizer, we need to know the types. Using the
792preprocessor, it is impossible to dispatch based on the types of ``a`` and
793``b``, so unfortunately having a separate macro for each of the types commonly
794asserted on is necessary.
795
796----------------------------
797Module Configuration Options
798----------------------------
799The following configurations can be adjusted via compile-time configuration of
800this module, see the
801:ref:`module documentation <module-structure-compile-time-configuration>` for
802more details.
803
804.. c:macro:: PW_ASSERT_ENABLE_DEBUG
805
806  Controls whether ``DCHECK`` and ``DASSERT`` are enabled.
807
808  This defaults to being disabled if ``NDEBUG`` is defined, else it is enabled
809  by default.
810
811.. c:macro:: PW_ASSERT_CAPTURE_VALUES
812
813  Controls whether the evaluated values of a CHECK statement are captured as
814  arguments to the final string. Disabling this will reduce code size at CHECK
815  callsites, but slightly reduces debugability.
816
817  This defaults to enabled.
818
819-------------
820Compatibility
821-------------
822The facade is compatible with both C and C++.
823
824---------------------------------------
825C Standard Library `assert` Replacement
826---------------------------------------
827An optional replacement of the C standard Library's `assert` macro is provided
828through the `libc_assert` target which fully implements replacement `assert.h`
829and `cassert` headers using `PW_ASSERT`. While this is effective for porting
830external code to microcontrollers, we do not advise embedded projects use the
831`assert` macro unless absolutely necessary.
832
833----------------
834Roadmap & Status
835----------------
836The Pigweed assert subsystem consiststs of several modules that work in
837coordination. This module is the facade (API), then a number of backends are
838available to handle assert failures. Products can also define their own
839backends. In some cases, the backends will have backends (like
840``pw_log_tokenized``).
841
842Below is a brief summary of what modules are ready for use:
843
844Available Assert Backends
845=========================
846See :ref:`module-pw_assert-backends`.
847
848Missing Functionality
849=====================
850- **Stack traces** - Pigweed doesn't have a reliable stack walker, which makes
851  displaying a stack trace on crash harder. We plan to add this eventually.
852- **Snapshot integration** - Pigweed doesn't yet have a rich system state
853  capture system that can capture state like number of tasks, available memory,
854  and so on. Snapshot facilities are the obvious ones to run inside an assert
855  handler. It'll happen someday.
856
857.. toctree::
858   :maxdepth: 1
859
860   Backends <backends>
861