• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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
457Since ``PW_ASSERT`` can be used in ``constexpr`` functions, assertions may fail
458during compilation. For example, the following code fails to compile due to a
459``PW_ASSERT`` in a constant expression:
460
461.. literalinclude:: assert_test.cc
462   :language: cpp
463   :linenos:
464   :start-after: pw_assert-constexpr-example
465   :end-before: pw_assert-constexpr-example
466
467The compiler reports the failed assertion as follows:
468
469.. code-block:: none
470
471   example.cc:6:15: error: constexpr variable 'kResult' must be initialized by a constant expression
472       6 | constexpr int kResult = DivideEvenNumberBy2(11);  // This fails the PW_ASSERT!
473         |               ^         ~~~~~~~~~~~~~~~~~~~~~~~
474   example.cc:2:3: note: non-constexpr function 'PW_ASSERT_failed_in_constant_expression_' cannot be used in a constant expression
475       2 |   PW_ASSERT(value % 2 == 0);  // value must be even!
476         |   ^
477   ../pw_assert/public/pw_assert/assert.h:33:7: note: expanded from macro 'PW_ASSERT'
478      33 |       PW_ASSERT_failed_in_constant_expression_(); \
479         |       ^
480   example.cc:6:25: note: in call to 'DivideEvenNumberBy2(11)'
481       6 | constexpr int kResult = DivideEvenNumberBy2(11);  // This fails the PW_ASSERT!
482         |                         ^~~~~~~~~~~~~~~~~~~~~~~
483   ../pw_assert/public/pw_assert/assert.h:88:20: note: declared here
484      88 | static inline void PW_ASSERT_failed_in_constant_expression_(void) {}
485
486Example
487=======
488
489.. code-block:: cpp
490
491   // This example demonstrates asserting in a header.
492
493   #include "pw_assert/assert.h"
494
495   class InlinedSubsystem {
496    public:
497     void DoSomething() {
498       // GOOD: No problem; PW_ASSERT is fine to inline and place in a header.
499       PW_ASSERT(IsEnabled());
500     }
501     void DoSomethingElse() {
502       // BAD: Generally avoid using PW_DCHECK() or PW_CHECK in headers. If you
503       // want rich asserts or logs, move the function into the .cc file, and
504       // then use PW_CHECK there.
505       PW_DCHECK(IsEnabled());  // DON'T DO THIS
506     }
507   };
508
509PW_ASSERT API Reference
510=======================
511.. cpp:function:: PW_ASSERT(condition)
512
513  A header- and constexpr-safe version of ``PW_CHECK()``.
514
515  If the given condition is false, crash the system. Otherwise, do nothing.
516  The condition is guaranteed to be evaluated. This assert implementation is
517  guaranteed to be constexpr-safe.
518
519.. cpp:function:: PW_DASSERT(condition)
520
521  A header- and constexpr-safe version of ``PW_DCHECK()``.
522
523  Same as ``PW_ASSERT()``, except that if ``PW_ASSERT_ENABLE_DEBUG == 0``, the
524  assert is disabled and condition is not evaluated.
525
526.. cpp:function:: PW_ASSERT_OK(expression)
527
528  A header- and constexpr-safe version of ``PW_CHECK_OK()``.
529
530  If the given expression is not `OK`, crash the system. Otherwise, do nothing.
531  The condition is guarenteed to be evaluated.
532
533.. attention::
534
535  Unlike the ``PW_CHECK_*()`` suite of macros, ``PW_ASSERT()`` and
536  ``PW_DASSERT()`` capture no rich information like line numbers, the file,
537  expression arguments, or the stringified expression. Use these macros **only
538  when absolutely necessary**---in headers, constexpr contexts, or in rare cases
539  where the call site overhead of a full PW_CHECK must be avoided.
540
541  Use ``PW_CHECK_*()`` whenever possible.
542
543PW_ASSERT API Backend
544=====================
545The ``PW_ASSERT`` API ultimately calls the C function
546``pw_assert_HandleFailure()``, which must be provided by the ``pw_assert``
547backend. The ``pw_assert_HandleFailure()`` function must not return.
548
549.. _module-pw_assert-circular-deps:
550
551Avoiding Circular Dependencies With ``PW_ASSERT``
552=================================================
553Because asserts are so widely used, including in low-level libraries, it is
554common for the ``pw_assert`` backend to cause circular dependencies. Because of
555this, assert backends may avoid declaring explicit dependencies, instead relying
556on include paths to access header files.
557
558GN
559--
560In GN, the ``pw_assert`` backend's full implementation with true dependencies is
561made available through the ``$dir_pw_assert:impl`` group. When
562``pw_assert_BACKEND`` is set, ``$dir_pw_assert:impl`` must be listed in the
563``pw_build_LINK_DEPS`` variable. See :ref:`module-pw_build-link-deps`.
564
565In the ``pw_assert``, the backend's full implementation is placed in the
566``$pw_assert_BACKEND.impl`` target. ``$dir_pw_assert:impl`` depends on this
567backend target. The ``$pw_assert_BACKEND.impl`` target may be an empty group if
568the backend target can use its dependencies directly without causing circular
569dependencies.
570
571In order to break dependency cycles, the ``pw_assert_BACKEND`` target may need
572to directly provide dependencies through include paths only, rather than GN
573``public_deps``. In this case, GN header checking can be disabled with
574``check_includes = false``.
575
576Bazel
577-----
578In Bazel, assert backends may break dependency cycles by placing the full
579implementation in an ``impl`` target, like ``//pw_assert_basic:impl`` or
580``//pw_assert_tokenized:impl``. The ``//pw_assert:backend_impl`` label flag
581should be set to the ``impl`` target required by the assert backend used by the
582platform.
583
584You must add a dependency on the ``@pigweed//pw_assert:backend_impl`` target to
585any binary using ``pw_assert``.
586
587See :ref:`docs-build_system-bazel_link-extra-lib` for a general discussion of
588cyclic dependencies in low-level libraries in Bazel.
589
590.. _module-pw_assert-backend_api:
591
592-----------
593Backend API
594-----------
595The backend controls what to do in the case of an assertion failure. In the
596most basic cases, the backend could display the assertion failure on something
597like sys_io and halt in a while loop waiting for a debugger. In other cases,
598the backend could store crash details like the current thread's stack to flash.
599
600This facade module (``pw_assert``) does not provide a backend. See
601:ref:`module-pw_assert_basic` for a basic implementation.
602
603.. attention::
604
605  The facade macros (``PW_CRASH`` and related) are expected to behave like they
606  have the ``[[noreturn]]`` attribute set. This implies that the backend handler
607  functions, ``PW_HANDLE_*`` defined by the backend, must not return.
608
609  In other words, the device must reboot.
610
611The backend must provide the header
612
613``pw_assert_backend/check_backend.h``
614
615and that header must define the following macros:
616
617.. cpp:function:: PW_HANDLE_CRASH(message, ...)
618
619  Trigger a system crash or halt, and if possible, deliver the specified
620  message and arguments to the user or developer.
621
622.. cpp:function:: PW_HANDLE_ASSERT_FAILURE(condition_str, message, ...)
623
624  Trigger a system crash or halt, and if possible, deliver the condition string
625  (indicating what expression was false) and the message with format arguments,
626  to the user or developer.
627
628  This macro is invoked from the ``PW_CHECK`` facade macro if condition is
629  false.
630
631.. cpp:function:: PW_HANDLE_ASSERT_BINARY_COMPARE_FAILURE( \
632    a_str, a_val, op_str, b_str, b_val, type_fmt, message, ...)
633
634  Trigger a system crash or halt for a failed binary comparison assert (e.g.
635  any of the ``PW_CHECK_<type>_<op>`` macros). The handler should combine the
636  assert components into a useful message for the user; though in some cases
637  this may not be possible.
638
639  Consider the following example:
640
641  .. code-block:: cpp
642
643     int temp = 16;
644     int max_temp = 15;
645     PW_CHECK_INT_LE(temp, MAX_TEMP, "Got too hot; state: %s", GetSystemState());
646
647  In this block, the assert will trigger, which will cause the facade to invoke
648  the handler macro. Below is the meaning of the arguments, referencing to the
649  example:
650
651  - ``a_str`` - Stringified first operand. In the example: ``"temp"``.
652  - ``a_val`` - The value of the first operand. In the example: ``16``.
653  - ``op_str`` - The string version of the operator. In the example: "<=".
654  - ``b_str`` - Stringified second operand. In the example: ``"max_temp"``.
655  - ``b_val`` - The value of the second operand. In the example: ``15``.
656  - ``type_fmt`` - The format code for the type. In the example: ``"%d"``.
657  - ``message, ...`` - A formatted message to go with the assert. In the
658    example: ``"Got too hot; state: %s", "ON_FIRE"``.
659
660  .. tip::
661
662    See :ref:`module-pw_assert_basic` for one way to combine these arguments
663    into a meaningful error message.
664
665Additionally, the backend must provide a link-time function for the
666``PW_ASSERT`` assert handler. This does not need to appear in the backend
667header, but instead is in a ``.cc`` file.
668
669.. cpp:function:: pw_assert_HandleFailure()
670
671  Handle a low-level crash. This crash entry happens through
672  ``pw_assert/assert.h``. In this crash handler, there is no access to line,
673  file, expression, or other rich assert information. Backends should do
674  something reasonable in this case; typically, capturing the stack is useful.
675
676Backend Build Targets
677=====================
678In GN, the backend must provide a ``pw_assert.impl`` build target in the same
679directory as the backend target. If the main backend target's dependencies would
680cause dependency cycles, the actual backend implementation with its full
681dependencies is placed in the ``pw_assert.impl`` target. If this is not
682necessary, ``pw_assert.impl`` can be an empty group. Circular dependencies are a
683common problem with ``pw_assert`` because it is so widely used. See
684:ref:`module-pw_assert-circular-deps`.
685
686Macro-based PW_ASSERT()/PW_DASSERT() backend
687============================================
688The pw_assert API is being re-assessed to provide more helpful information in
689contexts where ``PW_CHECK_*()`` macros cannot be used. A first step towards this
690is providing a macro-based backend API for the ``PW_ASSERT()`` and
691``PW_DASSERT()`` macros.
692
693.. warning::
694  This part of ``pw_assert``'s API is transitional, and any project-specific
695  reliance on any of the API mentioned here will likely experience breakages.
696  In particular, ``PW_ASSERT_HANDLE_FAILURE`` and ``PW_HANDLE_ASSERT_FAILURE``
697  are extremely confusingly similar and are NOT interchangeable.
698
699A macro-based backend for the ``PW_ASSERT()`` macros must provide the following
700macro in a header at ``pw_assert_backend/assert_backend.h``.
701
702.. cpp:function:: PW_ASSERT_HANDLE_FAILURE(expression)
703
704  Handle a low-level crash. This crash entry happens through
705  ``pw_assert/assert.h``. Backends must ensure their implementation is safe for
706  usage in headers, constexpr contexts, and templates. This macro should expand
707  to an expression that does not return.
708
709Similar to the ``PW_CHECK_*()`` facade, the header backend that provides an
710expansion for the ``PW_ASSERT_HANDLE_FAILURE()`` macro can be controlled in the
711GN build using the ``pw_assert_LITE_BACKEND`` build argument. In addition to
712the header-based target at ``${pw_assert_LITE_BACKEND}``, a source set at
713``${pw_assert_LITE_BACKEND}.impl`` is also required as a way to reduce the
714impact of :ref:`circular dependencies <module-pw_assert-circular-deps>`.
715
716--------------------------
717Frequently Asked Questions
718--------------------------
719
720When should DCHECK_* be used instead of CHECK_* and vice versa?
721===============================================================
722There is no hard and fast rule for when to use one or the other.
723
724In theory, ``DCHECK_*`` macros should never be used and all the asserts should
725remain active in production. In practice, **assert statements come at a binary
726size and runtime cost**, even when using extensions like a tokenized assert
727backend that strips the stringified assert expression from the binary. Each
728assert is **at least a branch with a function call**; depending on the assert
729backend, that function call may take several arguments (like the message, the
730file line number, the module, etc). These function calls can take 10-20 bytes
731or more of ROM each. Thus, there is a balance to be struct between ``DCHECK_*``
732and ``CHECK_*``.
733
734Pigweed uses these conventions to decide between ``CHECK_*`` and ``DCHECK_*``:
735
736- **Prefer to use CHECK_* at public API boundaries** of modules, where an
737  invalid value is a clear programmer bug. In certain cases use ``DCHECK_*`` to
738  keep binary size small when in production; for example, in modules with a
739  large public API surface, or modules with many inlined functions in headers.
740- **Avoid using CHECK_* macros in headers.** It is still OK to use ``CHECK_*``
741  macros in headers, but carefully consider the cost, since inlined use of the
742  ``CHECK_*`` macros in headers will expand to the full assert cost for every
743  translation unit that includes the header and calls the function with the
744  ``CHECK_*`` instance. ``DCHECK_*`` macros are are better, but even they come
745  at a cost, since it is preferable to be able to compile a binary in debug
746  mode for as long as possible on the road to production.
747- **Prefer to use DCHECK_* variants for internal asserts** that attempt to
748  catch module-author level programming errors. For example, use DCHECKs to
749  verify internal function preconditions, or other invariants that should
750  always be true but will likely never fire in production. In some cases using
751  ``CHECK_*`` macros for internal consistency checking can make sense, if the
752  runtime cost is low and there are only a couple of instances.
753
754.. tip::
755
756  **Do not return error status codes for obvious API misuse**
757
758  Returning an error code may **mask the earliest sign of a bug** because
759  notifying the developer of the problem depends on correct propagation of the
760  error to upper levels of the system. Instead, prefer to use the ``CHECK_*``
761  or ``DCHECK_*`` macros to ensure a prompt termination and warning to the
762  developer.
763
764  **Error status codes should be reserved for system misbehaviour or expected
765  exceptional cases**, like a sensor is not yet ready, or a storage subsystem
766  is full when writing. Doing ``CHECK_*`` assertions in those cases would be a
767  mistake; so use error codes in those cases instead.
768
769How should objects be asserted against or compared?
770===================================================
771Unfortunately, there is no native mechanism for this, and instead the way to
772assert object states or comparisons is with the normal ``PW_CHECK_*`` macros
773that operate on booleans, ints, and floats.
774
775This is due to the requirement of supporting C and also tokenization. It may be
776possible support rich object comparisons by defining a convention for
777stringifying objects; however, this hasn't been added yet. Additionally, such a
778mechanism would not work well with tokenization. In particular, it would
779require runtime stringifying arguments and rendering them with ``%s``, which
780leads to binary bloat even with tokenization. So it is likely that a rich
781object assert API won't be added.
782
783Why was the assert facade designed this way?
784============================================
785The Pigweed assert API was designed taking into account the needs of several
786past projects the team members were involved with. Based on those experiences,
787the following were key requirements for the API:
788
7891. **C compatibility** - Since asserts are typically invoked from arbitrary
790   contexts, including from vendor or third party code, the assert system must
791   have a C-compatible API. Some API functions working only in C++ is
792   acceptable, as long as the key functions work in C.
7932. **Capturing both expressions and values** - Since asserts can trigger in
794   ways that are not repeatable, it is important to capture rich diagnostic
795   information to help identifying the root cause of the fault. For asserts,
796   this means including the failing expression text, and optionally also
797   capturing failing expression values. For example, instead of capturing an
798   error with the expression (``x < y``), capturing an error with the
799   expression and values(``x < y, with x = 10, y = 0``).
8003. **Tokenization compatible** - It's important that the assert expressions
801   support tokenization; both the expression itself (e.g. ``a < b``) and the
802   message attached to the expression. For example: ``PW_CHECK(ItWorks(), "Ruh
803   roh: %d", some_int)``.
8044. **Customizable assert handling** - Most products need to support custom
805   handling of asserts. In some cases, an assert might trigger printing out
806   details to a UART; in other cases, it might trigger saving a log entry to
807   flash. The assert system must support this customization.
808
809The combination of #1, #2, and #3 led to the structure of the API. In
810particular, the need to support tokenized asserts and the need to support
811capturing values led to the choice of having ``PW_CHECK_INT_LE(a, b)`` instead
812of ``PW_CHECK(a <= b)``. Needing to support tokenization is what drove the
813facade & backend arrangement, since the backend must provide the raw macros for
814asserting in that case, rather than terminating at a C-style API.
815
816Why isn't there a ``PW_CHECK_LE``? Why is the type (e.g. ``INT``) needed?
817=========================================================================
818The problem with asserts like ``PW_CHECK_LE(a, b)`` instead of
819``PW_CHECK_INT_LE(a, b)`` or ``PW_CHECK_FLOAT_EXACT_LE(a, b)`` is that to
820capture the arguments with the tokenizer, we need to know the types. Using the
821preprocessor, it is impossible to dispatch based on the types of ``a`` and
822``b``, so unfortunately having a separate macro for each of the types commonly
823asserted on is necessary.
824
825----------------------------
826Module Configuration Options
827----------------------------
828The following configurations can be adjusted via compile-time configuration of
829this module, see the
830:ref:`module documentation <module-structure-compile-time-configuration>` for
831more details.
832
833.. c:macro:: PW_ASSERT_ENABLE_DEBUG
834
835  Controls whether ``DCHECK`` and ``DASSERT`` are enabled.
836
837  This defaults to being disabled if ``NDEBUG`` is defined, else it is enabled
838  by default.
839
840.. c:macro:: PW_ASSERT_CAPTURE_VALUES
841
842  Controls whether the evaluated values of a CHECK statement are captured as
843  arguments to the final string. Disabling this will reduce code size at CHECK
844  callsites, but slightly reduces debugability.
845
846  This defaults to enabled.
847
848-------------
849Compatibility
850-------------
851The facade is compatible with both C and C++.
852
853---------------------------------------
854C Standard Library `assert` Replacement
855---------------------------------------
856An optional replacement of the C standard Library's `assert` macro is provided
857through the `libc_assert` target which fully implements replacement `assert.h`
858and `cassert` headers using `PW_ASSERT`. While this is effective for porting
859external code to microcontrollers, we do not advise embedded projects use the
860`assert` macro unless absolutely necessary.
861
862----------------
863Roadmap & Status
864----------------
865The Pigweed assert subsystem consiststs of several modules that work in
866coordination. This module is the facade (API), then a number of backends are
867available to handle assert failures. Products can also define their own
868backends. In some cases, the backends will have backends (like
869``pw_log_tokenized``).
870
871Below is a brief summary of what modules are ready for use:
872
873Available Assert Backends
874=========================
875See :ref:`module-pw_assert-backends`.
876
877Missing Functionality
878=====================
879- **Stack traces** - Pigweed doesn't have a reliable stack walker, which makes
880  displaying a stack trace on crash harder. We plan to add this eventually.
881- **Snapshot integration** - Pigweed doesn't yet have a rich system state
882  capture system that can capture state like number of tasks, available memory,
883  and so on. Snapshot facilities are the obvious ones to run inside an assert
884  handler. It'll happen someday.
885
886.. toctree::
887   :maxdepth: 1
888
889   backends
890