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 we recommend developers carefully consider how floating point precision and 334 error impact the data 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.. _module-pw_assert-assert-api: 395 396---------- 397Assert API 398---------- 399The normal ``PW_CHECK_*`` and ``PW_DCHECK_*`` family of macros are intended to 400provide rich debug information, like the file, line number, value of operands 401in boolean comparisons, and more. However, this comes at a cost: these macros 402depend directly on the backend headers, and may perform complicated call-site 403transformations like tokenization. 404 405There are several issues with the normal ``PW_CHECK_*`` suite of macros: 406 4071. ``PW_CHECK_*`` in headers can cause ODR violations in the case of tokenized 408 asserts, due to differing module choices. 4092. ``PW_CHECK_*`` is not constexpr-safe. 4103. ``PW_CHECK_*`` can cause code bloat with some backends; this is the tradeoff 411 to get rich assert information. 4124. ``PW_CHECK_*`` can trigger circular dependencies when asserts are used from 413 low-level contexts, like in ``<span>``. 414 415**PW_ASSERT** solves all of the above problems: No risk of ODR violations, are 416constexpr safe, and have a tiny call site footprint; and there is no header 417dependency on the backend preventing circular include issues. However, there 418are **no format messages, no captured line number, no captured file, no captured 419expression, or anything other than a binary indication of failure**. 420 421Example 422======= 423 424.. code-block:: cpp 425 426 // This example demonstrates asserting in a header. 427 428 #include "pw_assert/assert.h" 429 430 class InlinedSubsystem { 431 public: 432 void DoSomething() { 433 // GOOD: No problem; PW_ASSERT is fine to inline and place in a header. 434 PW_ASSERT(IsEnabled()); 435 } 436 void DoSomethingElse() { 437 // BAD: Generally avoid using PW_DCHECK() or PW_CHECK in headers. If you 438 // want rich asserts or logs, move the function into the .cc file, and 439 // then use PW_CHECK there. 440 PW_DCHECK(IsEnabled()); // DON'T DO THIS 441 } 442 }; 443 444PW_ASSERT API Reference 445======================= 446.. cpp:function:: PW_ASSERT(condition) 447 448 A header- and constexpr-safe version of ``PW_CHECK()``. 449 450 If the given condition is false, crash the system. Otherwise, do nothing. 451 The condition is guaranteed to be evaluated. This assert implementation is 452 guaranteed to be constexpr-safe. 453 454.. cpp:function:: PW_DASSERT(condition) 455 456 A header- and constexpr-safe version of ``PW_DCHECK()``. 457 458 Same as ``PW_ASSERT()``, except that if ``PW_ASSERT_ENABLE_DEBUG == 0``, the 459 assert is disabled and condition is not evaluated. 460 461.. attention:: 462 463 Unlike the ``PW_CHECK_*()`` suite of macros, ``PW_ASSERT()`` and 464 ``PW_DASSERT()`` capture no rich information like line numbers, the file, 465 expression arguments, or the stringified expression. Use these macros **only 466 when absolutely necessary**---in headers, constexpr contexts, or in rare cases 467 where the call site overhead of a full PW_CHECK must be avoided. 468 469 Use ``PW_CHECK_*()`` whenever possible. 470 471PW_ASSERT API Backend 472===================== 473The ``PW_ASSERT`` API ultimately calls the C function 474``pw_assert_HandleFailure()``, which must be provided by the ``pw_assert`` 475backend. The ``pw_assert_HandleFailure()`` function must not return. 476 477.. _module-pw_assert-circular-deps: 478 479Avoiding Circular Dependencies With ``PW_ASSERT`` 480================================================= 481Because asserts are so widely used, including in low-level libraries, it is 482common for the ``pw_assert`` backend to cause circular dependencies. Because of 483this, assert backends may avoid declaring explicit dependencies, instead relying 484on include paths to access header files. 485 486In GN, the ``pw_assert`` backend's full implementation with true dependencies is 487made available through the ``$dir_pw_assert:impl`` group. When 488``pw_assert_BACKEND`` is set, ``$dir_pw_assert:impl`` must be listed in the 489``pw_build_LINK_DEPS`` variable. See :ref:`module-pw_build-link-deps`. 490 491In the ``pw_assert``, the backend's full implementation is placed in the 492``$pw_assert_BACKEND.impl`` target. ``$dir_pw_assert:impl`` depends on this 493backend target. The ``$pw_assert_BACKEND.impl`` target may be an empty group if 494the backend target can use its dependencies directly without causing circular 495dependencies. 496 497In order to break dependency cycles, the ``pw_assert_BACKEND`` target may need 498to directly provide dependencies through include paths only, rather than GN 499``public_deps``. In this case, GN header checking can be disabled with 500``check_includes = false``. 501 502.. _module-pw_assert-backend_api: 503 504----------- 505Backend API 506----------- 507The backend controls what to do in the case of an assertion failure. In the 508most basic cases, the backend could display the assertion failure on something 509like sys_io and halt in a while loop waiting for a debugger. In other cases, 510the backend could store crash details like the current thread's stack to flash. 511 512This facade module (``pw_assert``) does not provide a backend. See 513:ref:`module-pw_assert_basic` for a basic implementation. 514 515.. attention:: 516 517 The facade macros (``PW_CRASH`` and related) are expected to behave like they 518 have the ``[[noreturn]]`` attribute set. This implies that the backend handler 519 functions, ``PW_HANDLE_*`` defined by the backend, must not return. 520 521 In other words, the device must reboot. 522 523The backend must provide the header 524 525``pw_assert_backend/backend.h`` 526 527and that header must define the following macros: 528 529.. cpp:function:: PW_HANDLE_CRASH(message, ...) 530 531 Trigger a system crash or halt, and if possible, deliver the specified 532 message and arguments to the user or developer. 533 534.. cpp:function:: PW_HANDLE_ASSERT_FAILURE(condition_str, message, ...) 535 536 Trigger a system crash or halt, and if possible, deliver the condition string 537 (indicating what expression was false) and the message with format arguments, 538 to the user or developer. 539 540 This macro is invoked from the ``PW_CHECK`` facade macro if condition is 541 false. 542 543.. cpp:function:: PW_HANDLE_ASSERT_BINARY_COMPARE_FAILURE( \ 544 a_str, a_val, op_str, b_str, b_val, type_fmt, message, ...) 545 546 Trigger a system crash or halt for a failed binary comparison assert (e.g. 547 any of the ``PW_CHECK_<type>_<op>`` macros). The handler should combine the 548 assert components into a useful message for the user; though in some cases 549 this may not be possible. 550 551 Consider the following example: 552 553 .. code-block:: cpp 554 555 int temp = 16; 556 int max_temp = 15; 557 PW_CHECK_INT_LE(temp, MAX_TEMP, "Got too hot; state: %s", GetSystemState()); 558 559 In this block, the assert will trigger, which will cause the facade to invoke 560 the handler macro. Below is the meaning of the arguments, referencing to the 561 example: 562 563 - ``a_str`` - Stringified first operand. In the example: ``"temp"``. 564 - ``a_val`` - The value of the first operand. In the example: ``16``. 565 - ``op_str`` - The string version of the operator. In the example: "<=". 566 - ``b_str`` - Stringified second operand. In the example: ``"max_temp"``. 567 - ``b_val`` - The value of the second operand. In the example: ``15``. 568 - ``type_fmt`` - The format code for the type. In the example: ``"%d"``. 569 - ``message, ...`` - A formatted message to go with the assert. In the 570 example: ``"Got too hot; state: %s", "ON_FIRE"``. 571 572 .. tip:: 573 574 See :ref:`module-pw_assert_basic` for one way to combine these arguments 575 into a meaningful error message. 576 577Additionally, the backend must provide a link-time function for the 578``PW_ASSERT`` assert handler. This does not need to appear in the backend 579header, but instead is in a ``.cc`` file. 580 581.. cpp:function:: pw_assert_HandleFailure() 582 583 Handle a low-level crash. This crash entry happens through 584 ``pw_assert/assert.h``. In this crash handler, there is no access to line, 585 file, expression, or other rich assert information. Backends should do 586 something reasonable in this case; typically, capturing the stack is useful. 587 588Backend Build Targets 589===================== 590In GN, the backend must provide a ``pw_assert.impl`` build target in the same 591directory as the backend target. If the main backend target's dependencies would 592cause dependency cycles, the actual backend implementation with its full 593dependencies is placed in the ``pw_assert.impl`` target. If this is not 594necessary, ``pw_assert.impl`` can be an empty group. Circular dependencies are a 595common problem with ``pw_assert`` because it is so widely used. See 596:ref:`module-pw_assert-circular-deps`. 597 598Macro-based PW_ASSERT()/PW_DASSERT() backend 599============================================ 600The pw_assert API is being re-assessed to provide more helpful information in 601contexts where ``PW_CHECK_*()`` macros cannot be used. A first step towards this 602is providing a macro-based backend API for the ``PW_ASSERT()`` and 603``PW_DASSERT()`` macros. 604 605.. warning:: 606 This part of ``pw_assert``'s API is transitional, and any project-specific 607 reliance on any of the API mentioned here will likely experience breakages. 608 In particular, ``PW_ASSERT_HANDLE_FAILURE`` and ``PW_HANDLE_ASSERT_FAILURE`` 609 are extremely confusingly similar and are NOT interchangeable. 610 611A macro-based backend for the ``PW_ASSERT()`` macros must provide the following 612macro in a header at ``pw_assert_backend/assert_lite_backend.h``. 613 614.. cpp:function:: PW_ASSERT_HANDLE_FAILURE(expression) 615 616 Handle a low-level crash. This crash entry happens through 617 ``pw_assert/assert.h``. Backends must ensure their implementation is safe for 618 usage in headers, constexpr contexts, and templates. This macro should expand 619 to an expression that does not return. 620 621Similar to the ``PW_CHECK_*()`` facade, the header backend that provides an 622expansion for the ``PW_ASSERT_HANDLE_FAILURE()`` macro can be controlled in the 623GN build using the ``pw_assert_LITE_BACKEND`` build argument. In addition to 624the header-based target at ``${pw_assert_LITE_BACKEND}``, a source set at 625``${pw_assert_LITE_BACKEND}.impl`` is also required as a way to reduce the 626impact of :ref:`circular dependencies <module-pw_assert-circular-deps>`. 627 628-------------------------- 629Frequently Asked Questions 630-------------------------- 631 632When should DCHECK_* be used instead of CHECK_* and vice versa? 633=============================================================== 634There is no hard and fast rule for when to use one or the other. 635 636In theory, ``DCHECK_*`` macros should never be used and all the asserts should 637remain active in production. In practice, **assert statements come at a binary 638size and runtime cost**, even when using extensions like a tokenized assert 639backend that strips the stringified assert expression from the binary. Each 640assert is **at least a branch with a function call**; depending on the assert 641backend, that function call may take several arguments (like the message, the 642file line number, the module, etc). These function calls can take 10-20 bytes 643or more of ROM each. Thus, there is a balance to be struct between ``DCHECK_*`` 644and ``CHECK_*``. 645 646Pigweed uses these conventions to decide between ``CHECK_*`` and ``DCHECK_*``: 647 648- **Prefer to use CHECK_* at public API boundaries** of modules, where an 649 invalid value is a clear programmer bug. In certain cases use ``DCHECK_*`` to 650 keep binary size small when in production; for example, in modules with a 651 large public API surface, or modules with many inlined functions in headers. 652- **Avoid using CHECK_* macros in headers.** It is still OK to use ``CHECK_*`` 653 macros in headers, but carefully consider the cost, since inlined use of the 654 ``CHECK_*`` macros in headers will expand to the full assert cost for every 655 translation unit that includes the header and calls the function with the 656 ``CHECK_*`` instance. ``DCHECK_*`` macros are are better, but even they come 657 at a cost, since it is preferable to be able to compile a binary in debug 658 mode for as long as possible on the road to production. 659- **Prefer to use DCHECK_* variants for internal asserts** that attempt to 660 catch module-author level programming errors. For example, use DCHECKs to 661 verify internal function preconditions, or other invariants that should 662 always be true but will likely never fire in production. In some cases using 663 ``CHECK_*`` macros for internal consistency checking can make sense, if the 664 runtime cost is low and there are only a couple of instances. 665 666.. tip:: 667 668 **Do not return error status codes for obvious API misuse** 669 670 Returning an error code may **mask the earliest sign of a bug** because 671 notifying the developer of the problem depends on correct propagation of the 672 error to upper levels of the system. Instead, prefer to use the ``CHECK_*`` 673 or ``DCHECK_*`` macros to ensure a prompt termination and warning to the 674 developer. 675 676 **Error status codes should be reserved for system misbehaviour or expected 677 exceptional cases**, like a sensor is not yet ready, or a storage subsystem 678 is full when writing. Doing ``CHECK_*`` assertions in those cases would be a 679 mistake; so use error codes in those cases instead. 680 681How should objects be asserted against or compared? 682=================================================== 683Unfortunately, there is no native mechanism for this, and instead the way to 684assert object states or comparisons is with the normal ``PW_CHECK_*`` macros 685that operate on booleans, ints, and floats. 686 687This is due to the requirement of supporting C and also tokenization. It may be 688possible support rich object comparisons by defining a convention for 689stringifying objects; however, this hasn't been added yet. Additionally, such a 690mechanism would not work well with tokenization. In particular, it would 691require runtime stringifying arguments and rendering them with ``%s``, which 692leads to binary bloat even with tokenization. So it is likely that a rich 693object assert API won't be added. 694 695Why was the assert facade designed this way? 696============================================ 697The Pigweed assert API was designed taking into account the needs of several 698past projects the team members were involved with. Based on those experiences, 699the following were key requirements for the API: 700 7011. **C compatibility** - Since asserts are typically invoked from arbitrary 702 contexts, including from vendor or third party code, the assert system must 703 have a C-compatible API. Some API functions working only in C++ is 704 acceptable, as long as the key functions work in C. 7052. **Capturing both expressions and values** - Since asserts can trigger in 706 ways that are not repeatable, it is important to capture rich diagnostic 707 information to help identifying the root cause of the fault. For asserts, 708 this means including the failing expression text, and optionally also 709 capturing failing expression values. For example, instead of capturing an 710 error with the expression (``x < y``), capturing an error with the 711 expression and values(``x < y, with x = 10, y = 0``). 7123. **Tokenization compatible** - It's important that the assert expressions 713 support tokenization; both the expression itself (e.g. ``a < b``) and the 714 message attached to the expression. For example: ``PW_CHECK(ItWorks(), "Ruh 715 roh: %d", some_int)``. 7164. **Customizable assert handling** - Most products need to support custom 717 handling of asserts. In some cases, an assert might trigger printing out 718 details to a UART; in other cases, it might trigger saving a log entry to 719 flash. The assert system must support this customization. 720 721The combination of #1, #2, and #3 led to the structure of the API. In 722particular, the need to support tokenized asserts and the need to support 723capturing values led to the choice of having ``PW_CHECK_INT_LE(a, b)`` instead 724of ``PW_CHECK(a <= b)``. Needing to support tokenization is what drove the 725facade & backend arrangement, since the backend must provide the raw macros for 726asserting in that case, rather than terminating at a C-style API. 727 728Why isn't there a ``PW_CHECK_LE``? Why is the type (e.g. ``INT``) needed? 729========================================================================= 730The problem with asserts like ``PW_CHECK_LE(a, b)`` instead of 731``PW_CHECK_INT_LE(a, b)`` or ``PW_CHECK_FLOAT_EXACT_LE(a, b)`` is that to 732capture the arguments with the tokenizer, we need to know the types. Using the 733preprocessor, it is impossible to dispatch based on the types of ``a`` and 734``b``, so unfortunately having a separate macro for each of the types commonly 735asserted on is necessary. 736 737---------------------------- 738Module Configuration Options 739---------------------------- 740The following configurations can be adjusted via compile-time configuration of 741this module, see the 742:ref:`module documentation <module-structure-compile-time-configuration>` for 743more details. 744 745.. c:macro:: PW_ASSERT_ENABLE_DEBUG 746 747 Controls whether ``DCHECK`` and ``DASSERT`` are enabled. 748 749 This defaults to being disabled if ``NDEBUG`` is defined, else it is enabled 750 by default. 751 752.. c:macro:: PW_ASSERT_CAPTURE_VALUES 753 754 Controls whether the evaluated values of a CHECK statement are captured as 755 arguments to the final string. Disabling this will reduce code size at CHECK 756 callsites, but slightly reduces debugability. 757 758 This defaults to enabled. 759 760------------- 761Compatibility 762------------- 763The facade is compatible with both C and C++. 764 765---------------- 766Roadmap & Status 767---------------- 768The Pigweed assert subsystem consiststs of several modules that work in 769coordination. This module is the facade (API), then a number of backends are 770available to handle assert failures. Products can also define their own 771backends. In some cases, the backends will have backends (like 772``pw_log_tokenized``). 773 774Below is a brief summary of what modules are ready for use: 775 776Available Assert Backends 777========================= 778- ``pw_assert`` - **Stable** - The assert facade (this module). This module is 779 stable, and in production use. The documentation is comprehensive and covers 780 the functionality. There are (a) tests for the facade macro processing logic, 781 using a fake assert backend; and (b) compile tests to verify that the 782 selected backend compiles with all supported assert constructions and types. 783- ``pw_assert_basic`` - **Stable** - The assert basic module is a simple assert 784 handler that displays the failed assert line and the values of captured 785 arguments. Output is directed to ``pw_sys_io``. This module is a great 786 ready-to-roll module when bringing up a system, but is likely not the best 787 choice for production. 788- ``pw_assert_log`` - **Stable** - This assert backend redirects to logging, 789 but with a logging flag set that indicates an assert failure. This is our 790 advised approach to get **tokenized asserts**--by using tokenized logging, 791 then using the ``pw_assert_log`` backend. 792 793Note: If one desires a null assert module (where asserts are removed), use 794``pw_assert_log`` in combination with ``pw_log_null``. This will direct asserts 795to logs, then the logs are removed due to the null backend. 796 797Missing Functionality 798===================== 799- **Stack traces** - Pigweed doesn't have a reliable stack walker, which makes 800 displaying a stack trace on crash harder. We plan to add this eventually. 801- **Snapshot integration** - Pigweed doesn't yet have a rich system state 802 capture system that can capture state like number of tasks, available memory, 803 and so on. Snapshot facilities are the obvious ones to run inside an assert 804 handler. It'll happen someday. 805