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