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