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