/* * Copyright 2010-2016 Nest Labs Inc. All Rights Reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */ /** * @file * This file defines macros and interfaces for performing both * compile- and run-time assertion checking and run-time * exception handling. * * Where exception-handing is concerned, the format of the macros * are inspired by those found in Mac OS Classic and, later, Mac * OS X. These, in turn, were inspired by "Living In an * Exceptional World" by Sean Parent (develop, The Apple * Technical Journal, Issue 11, August/September 1992) * * for the methodology behind these error handling and assertion * macros. * */ /** * @mainpage notitle * * @section introduction Introduction * * This package defines macros and interfaces for performing both * compile- and run-time assertion checking and run-time exception * handling. * * Where exception-handing is concerned, the format of the macros are * inspired by those found in Mac OS Classic and, later, Mac OS * X. These, in turn, were inspired by "Living In an Exceptional * World" by Sean Parent (develop, The Apple Technical Journal, Issue * 11, August/September 1992). See: * * http://www.mactech.com/articles/develop/issue_11/Parent_final.html * * for the methodology behind these error handling and assertion * macros. * * @section overview Overview * * The interfaces in this package come in two interface modalities: * *
*
[Run-time](@ref run-time)
*
Interfaces that dynamically check a logical assertion and * alter run-time execution on assertion firing.
*
[Compile-time](@ref compile-time)
*
Interfaces that statically check a logical assertion and * terminate compile-time execution on assertion firing.
*
* * @subsection run-time Run-time * * The [run-time modality interfaces](@ref run-time-interfaces) in * this package come in three families: * *
*
[Assertion](@ref run-time-assertions)
*
Similar to the traditional C Standard Library * [assert()](http://pubs.opengroup.org/onlinepubs/009695399/functions/assert.html).
* *
[Precondition](@ref preconditions)
*
Designed to be placed at the head of an interface or * method to check incoming parameters and return on * assertion failure.
* *
[Exception](@ref exceptions)
*
Designed to jump to a local label on assertion failure * to support the method of error and exception handling that * advocates a single function or method return site and, by * extension, consolidated points of exception and error * handling as well as resource clean-up.
*
* * There are several styles of interfaces within each family and * several potential variants within each style, all of which are * summarized below and are described in detail in the following * sections. * * @subsection compile-time Compile-time * * The [compile-time modality interfaces](@ref compile-time-interfaces) * in this package are simpler and come in a single family with a * couple of variants. * * @section run-time-interfaces Run-time Interfaces * * @subsection triggers Behavior Triggers * * Unlike the traditional C Standard Library * [assert()](http://pubs.opengroup.org/onlinepubs/009695399/functions/assert.html) * or other assertion checking packages, this package offers the * ability to enable and customize one or more of a few triggers that * run when an assertion fires, including: * * * [Abort](@ref abort-behavior) * * [Backtrace](@ref backtrace-behavior) * * [Log](@ref log-behavior) * * [Trap](@ref trap-behavior) * * @subsubsection abort-behavior Abort * * The abort behavior trigger allows, on an assertion firing, to * execute a trigger that terminates overall program or system * execution. * * Note, however, the abort behavior trigger is only available in * some styles of the [assertion-family](@ref run-time-assertions) of * interfaces. * * Please see #NL_ASSERT_ABORT() and @ref customization for more * information about this behavior trigger. * * @subsubsection backtrace-behavior Backtrace * * The backtrace behavior trigger allows, on an assertion firing, to * execute a trigger that generates a stack backtrace. * * This style of assertion is available, when configured, on all * interface families. * * Please see #NL_ASSERT_BACKTRACE() and @ref customization for more * information about this behavior trigger. * * @subsubsection log-behavior Log * * The log behavior trigger allows, on an assertion firing, to * execute a trigger that logs a message summarizing the assertion * that fired. * * This style of assertion is available, when configured, on all * interface families. * * Please see #NL_ASSERT_LOG() and @ref customization for more * information about this behavior trigger. * * @subsubsection trap-behavior Trap * * The log behavior trigger allows, on an assertion firing, to * execute a trigger that generates a debugger trap or exception. * * This style of assertion is available, when configured, on all * interface families. * * Please see #NL_ASSERT_TRAP() and @ref customization for more * information about this behavior trigger. * * @subsection run-time-assertions Assertion Interfaces * * The assertion interfaces are similar to the traditional C * Standard Library * [assert()](http://pubs.opengroup.org/onlinepubs/009695399/functions/assert.html). * * These interfaces include the following styles: * * * [Assert](@ref run-time-assert) * * [Abort](@ref run-time-abort) * * [Check](@ref run-time-check) * * [Verify](@ref run-time-verify) * * The following table summarizes the relationship and features among * the styles: * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
StyleBehaviorsAvailability
AbortBacktraceLogTrapNon-productionProduction
AssertNon-productionNon-productionNon-productionX
AbortXXXXX
CheckNon-productionNon-productionNon-productionX
VerifyXXNon-productionXX
* * @note The above described behaviors are only in effect when * #NL_ASSERT_USE_FLAGS_DEFAULT to 1. See @ref customization * for more information on configuring and customizing the * trigger behaviors. * * @subsubsection run-time-assert Assert * * These assertions are identical to the traditional C Standard * Library-style assertion (see * [assert()](http://pubs.opengroup.org/onlinepubs/009695399/functions/assert.html)) * except that side-effects, if any, in the asserted expression will be * produced even when the assertion is made inactive, as in production build * configurations, by setting #NL_ASSERT_PRODUCTION to true. * * Like the C Standard Library assertion, a trigger of this style of * assertion interface will invoke #NL_ASSERT_ABORT(). * * @subsubsection run-time-abort Abort * * These assertions are identical to the @ref run-time-assert style * assertions; however, they are active in __both__ non-production * __and__ production build configurations. * * A trigger of this style of assertion interface will invoke #NL_ASSERT_ABORT(). * * @subsubsection run-time-check Check * * These assertions are similar to the @ref run-time-assert style; however, * this style __does not__ abort. Normal program flow and execution * will continue past this assertion. * * Side-effects, if any, in the asserted expression will be produced even when * the assertion is made inactive, as in production build configurations, by * setting #NL_ASSERT_PRODUCTION to true. * * @subsubsection run-time-verify Verify * * These assertions are similar to the @ref run-time-abort style; however, * this style __does not__ abort. Normal program flow and execution * will continue past this assertion. * * These are active in __both__ non-production __and__ production * build configurations. * * @subsection preconditions Precondition Interfaces * * These assertions are designed to be placed at the head of an * interface or method to check incoming parameters. * * These assertions implicitly return, either void or a specified * value for non-void interfaces or methods. * * @note This family of interfaces may be in violation of your site's * or project's coding style and best practices by virtue of its * implicit return. If so, please consider using the * [exception-style](@ref exceptions) interfaces instead. * * The following table summarizes the features for this family of interfaces: * * * * * * * * * * * * * * * * * * * * * * * * *
StyleBehaviorsAvailability
AbortBacktraceLogTrapNon-productionProduction
PreconditionXXXX
* * @note The above described behaviors are only in effect when * #NL_ASSERT_USE_FLAGS_DEFAULT to 1. See @ref customization * for more information on configuring and customizing the * trigger behaviors. * * @subsection exceptions Exception Interfaces * * This family of interfaces is designed to support the method of * error and exception handling that advocates a single function or * method return site and, by extension, consolidated points of * exception and error handling as well as resource clean-up. * * A general example usage of this family of interfaces is: * * @code * int Bar(uint8_t **aBuffer, const Foo *aParameter) * { * const size_t size = 1024; * int retval = 0; * * nlREQUIRE(aBuffer != NULL, exit, retval = -EINVAL); * * *aBuffer = (uint8_t *)malloc(size); * nlREQUIRE(*aBuffer != NULL, exit, retval = -ENOMEM); * * memset(*aBuffer, 0, size); * * exit: * return retval; * } * @endcode * * As shown in the example, this family checks for the specified * condition, which is expected to commonly be true, and branches to * the specified label if the condition is false. * * * [Expect](@ref expect) * * [Desire](@ref desire) * * [Require](@ref require) * * This family of interfaces are all identical across the styles and * all styles support an identical set of variants. The only * difference among them is the default configured trigger action * behavior, as summarized in the table below: * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
StyleBehaviorsAvailability
BacktraceLogTrapNon-productionProduction
ExpectXX
DesireNon-productionXX
RequireXXNon-productionXX
* * @note The above described behaviors are only in effect when * #NL_ASSERT_USE_FLAGS_DEFAULT to 1. See @ref customization * for more information on configuring and customizing the * trigger behaviors. * * @subsubsection expect Expect * * These assertions are designed to be placed anywhere an exceptional * condition might occur where handling needs to locally jump to * error-handling code. * * These checks are always present and do nothing beyond branching to * the named exception label. Consequently, they are simply mnemonics * or syntactic sugar. * * This style of check should be used where either true or false * evaluation of the assertion expression are equally likely since * there is no default configured trigger behavior. * * __Anticipated Assertion Firing Frequency:__ Frequent * * @subsubsection desire Desire * * These are identical to the @ref expect style checks; except for * their non-production and production configured behavior. * * This style of check should be used where false evaluation of the * assertion expression is expected to be occasional. * * __Anticipated Assertion Firing Frequency:__ Occasional * * @subsubsection require Require * * These are identical to the @ref expect style checks; except for * their non-production and production configured behavior. * * This style of check should be used where false evaluation of the * assertion expression is expected to be rare. * * __Anticipated Assertion Firing Frequency:__ Rare * * @subsection variants Variants * * The three families of run-time interface are available in one of several * variants, as summarized below. <STYLE> may be replaced with one of (see [Run-time Availability](@ref run-time-availability) for details): * * * ASSERT * * ABORT * * CHECK * * VERIFY * * PRECONDITION * * EXPECT * * DESIRE * * REQUIRE * * to form an actual interface name. * * | Interface Variant | Description | * |:---------------------------------------------- |:------------------------------------------------------------------------------------------------------------ | * | nl<STYLE> | Base variant; execute the check. | * | nl<STYLE>\_ACTION | Execute the base check and execute the action if the check fails. | * | nl<STYLE>\_PRINT | Execute the base check and print the descriptive string if the check fails. | * | nl<STYLE>\_ACTION_PRINT | Execute the base check and both execute the action and print the descriptive string if the check fails. | * | nl<STYLE>\_SUCCESS | Adds a check against zero (0) as the logical condition to assert. | * | nl<STYLE>\_SUCCESS_ACTION | Execute the success check and execute the action if the check fails. | * | nl<STYLE>\_SUCCESS_PRINT | Execute the success check and print the descriptive string if the check fails. | * | nl<STYLE>\_SUCCESS_ACTION_PRINT | Execute the success check and both execute the action and print the descriptive string if the check fails. | * | nlN<STYLE> | Inverts the logical sense of the base check; execute the check. | * | nlN<STYLE>\_ACTION | Execute the inversion check and execute the action if the check fails. | * | nlN<STYLE>\_PRINT | Execute the inversion check and print the descriptive string if the check fails. | * | nlN<STYLE>\_ACTION_PRINT | Execute the inversion check and both execute the action and print the descriptive string if the check fails. | * * @section run-time-availability Run-time Availability * * The following table indicates the availability of the run-time interface * variants for each style. * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
Interface VariantStyle
AssertAbortCheckVerifyPreconditionExpectDesireRequire
nl<STYLE>XXXXXXXX
nl<STYLE>\_ACTIONXXXXXXXX
nl<STYLE>\_PRINTXXXXXX
nl<STYLE>\_ACTION_PRINTXXX
nl<STYLE>\_SUCCESSXXXXXX
nl<STYLE>\_SUCCESS_ACTIONXXXXXX
nl<STYLE>\_SUCCESS_PRINTXXXXXX
nl<STYLE>\_SUCCESS_ACTION_PRINTXXX
nlN<STYLE>XXXXXX
nlN<STYLE>\_ACTIONXXXXXX
nlN<STYLE>\_PRINTXXXXXX
nlN<STYLE>\_ACTION_PRINTXXX
* * @section customization Customization * * The Nest Labs Assertion library is designed "out of the box" to * provide a high degree of utility. However, there are a number of * aspects that can be tuned on a per-module, -project, or -site basis * to customize the appearance and behavior through user-definable * attributes via the C preprocessor. * * @subsection userattrs User-definable Attributes * * The following attributes may be defined by the user before * the nlassert.h header is included by the preprocessor, overriding * the default behavior: * * * #NL_ASSERT_PRODUCTION * * #NL_ASSERT_PREFIX_STRING * * #NL_ASSERT_COMPONENT_STRING * * #NL_ASSERT_FILE * * #NL_ASSERT_ABORT * * #NL_ASSERT_BACKTRACE * * #NL_ASSERT_LOG * * #NL_ASSERT_TRAP * * Without any customization, all of the interface styles are set to * use __no__ trigger behaviors (i.e. #NL_ASSERT_FLAG_NONE). However, a * set of default trigger behaviors (as documented in the tables * above) may be enabled by setting #NL_ASSERT_USE_FLAGS_DEFAULT to 1 * before nlassert.h is included by the preprocessor. * * Otherwise, the following attributes may be overridden, customizing * the trigger behavior of each assertion interface family for both * non-production and production configurations: * * * #NL_ASSERT_EXPECT_FLAGS * * * #NL_ASSERT_CHECK_NONPRODUCTION_FLAGS * * #NL_ASSERT_VERIFY_NONPRODUCTION_FLAGS * * #NL_ASSERT_ASSERT_NONPRODUCTION_FLAGS * * #NL_ASSERT_ABORT_NONPRODUCTION_FLAGS * * #NL_ASSERT_DESIRE_NONPRODUCTION_FLAGS * * #NL_ASSERT_REQUIRE_NONPRODUCTION_FLAGS * * #NL_ASSERT_PRECONDITION_NONPRODUCTION_FLAGS * * * #NL_ASSERT_VERIFY_PRODUCTION_FLAGS * * #NL_ASSERT_ABORT_PRODUCTION_FLAGS * * #NL_ASSERT_DESIRE_PRODUCTION_FLAGS * * #NL_ASSERT_REQUIRE_PRODUCTION_FLAGS * * #NL_ASSERT_PRECONDITION_PRODUCTION_FLAGS * * @section compile-time-interfaces Compile-time Interfaces * * The compile-time interfaces are a limited subset of their run-time * counterparts. Rather than altering run-time execution on assertion * firing against a dynamically-checked run-time condition, these * interfaces terminate compilation against a statically-checked * compile-time condition. * * @subsection compile-time-assertions Assertion Interfaces * * These interfaces have only one style: * * * [Assert](@ref compile-time-assert) * * * * * * * * * * * * * * * *
StyleAvailability
Non-productionProduction
AssertXX
* * @subsubsection compile-time-assert Assert * * These assertions are active in __both__ non-production * __and__ production build configurations. This behavior * is unconventional with respect to the [run-time assert-style assertions](@ref run-time-assert) * but very conventional with respect to the similar * C11/C++11 static-assertion standards. * * @subsection compile-time-variants Variants * * The compile-time interfaces are available in two variants: * * | Interface Variant | Description | * |:---------------------------------------------- |:------------------------------------------------------------------------------------------------------------ | * | nlSTATIC\_ASSERT | Base variant; execute the check. | * | nlSTATIC\_ASSERT\_PRINT | Execute the base check with a descriptive string. Note, this string is not actually emitted in any meaningful way. It serves to simply comment or annotate the assertion and to provide interface parallelism with the run-time assertion interfaces. | * * @section compile-time-availability Compile-time Availability * * The following table indicates the availability of the compile-time interface * variants. * * * * * * * * * * * * * * * * * * * * *
Interface VariantAvailability
Non-ProductionProduction
nlSTATIC\_ASSERTXX
nlSTATIC\_ASSERT\_PRINTXX
* * @section compatibility Standard C Library Compatibility * * This package also provides an ISO/IEC 9899:1999-, C89-, and * C99-compatible Standard C Library header (via assert.h) and * assertion interface definition (assert()), implemented atop Nest * Labs assertion checking and runtime exception interfaces such that * consistent platform and system capabilities, behavior, and output * may be implemented and enforced across the two interfaces. * * Systems wishing to use this compatibility header and interface in * lieu of their Standard C Library header of the same name should * ensure that their toolchain is configured to either ignore or * deprioritize standard search paths while placing the directory this * header is contained in among the preferred header search paths. * */ #ifndef NLCORE_NLASSERT_H #define NLCORE_NLASSERT_H #include #include #include /** * @name Behavioral Control Flags * * @brief * These flags are used to influence the behavior of the various * classes and styles of assertion macros. * * @{ * */ /** * @def NL_ASSERT_FLAG_NONE * * @brief * Perform no actions when an assertion expression evaluates to * false. * * @sa #NL_ASSERT_FLAG_BACKTRACE * @sa #NL_ASSERT_FLAG_LOG * @sa #NL_ASSERT_FLAG_TRAP * */ #define NL_ASSERT_FLAG_NONE 0x00000000 /** * @def NL_ASSERT_FLAG_BACKTRACE * * @brief * Invoke #NL_ASSERT_BACKTRACE() when an assertion expression * evaluates to false. * * @note For the *_ACTION*-style assertion variants, * #NL_ASSERT_BACKTRACE() is a pre-action trigger and will run * before the specified action. * * @sa #NL_ASSERT_FLAG_NONE * @sa #NL_ASSERT_FLAG_LOG * @sa #NL_ASSERT_FLAG_TRAP * * @sa #NL_ASSERT_BACKTRACE * */ #define NL_ASSERT_FLAG_BACKTRACE 0x00000001 /** * @def NL_ASSERT_FLAG_LOG * * @brief * Invoke #NL_ASSERT_LOG() when an assertion expression evaluates * to false. * * @note For the *_ACTION*-style assertion variants, * #NL_ASSERT_LOG() is a pre-action trigger and will run * before the specified action. * * @sa #NL_ASSERT_FLAG_NONE * @sa #NL_ASSERT_FLAG_BACKTRACE * @sa #NL_ASSERT_FLAG_TRAP * * @sa #NL_ASSERT_LOG * */ #define NL_ASSERT_FLAG_LOG 0x00000002 /** * @def NL_ASSERT_FLAG_TRAP * * @brief * Invoke #NL_ASSERT_TRAP() when an assertion expression evaluates * to false. * * @note For the *_ACTION*-style assertion variants, * #NL_ASSERT_TRAP() is a post-action trigger and will run * after the specified action. * * @sa #NL_ASSERT_FLAG_NONE * @sa #NL_ASSERT_FLAG_BACKTRACE * @sa #NL_ASSERT_FLAG_LOG * * @sa #NL_ASSERT_TRAP * */ #define NL_ASSERT_FLAG_TRAP 0x00000004 /** * @} * */ /** * @def NL_ASSERT_USE_FLAGS_DEFAULT * * @brief * Enable (1) or disable (0) use of the default trigger behavior flags. * * This enables or disables the use of the default trigger behavior * flags as specified by: * * * #NL_ASSERT_EXPECT_FLAGS_DEFAULT * * * #NL_ASSERT_CHECK_NONPRODUCTION_FLAGS_DEFAULT * * #NL_ASSERT_VERIFY_NONPRODUCTION_FLAGS_DEFAULT * * #NL_ASSERT_ASSERT_NONPRODUCTION_FLAGS_DEFAULT * * #NL_ASSERT_ABORT_NONPRODUCTION_FLAGS_DEFAULT * * #NL_ASSERT_DESIRE_NONPRODUCTION_FLAGS_DEFAULT * * #NL_ASSERT_REQUIRE_NONPRODUCTION_FLAGS_DEFAULT * * #NL_ASSERT_PRECONDITION_NONPRODUCTION_FLAGS_DEFAULT * * * #NL_ASSERT_VERIFY_PRODUCTION_FLAGS_DEFAULT * * #NL_ASSERT_ABORT_PRODUCTION_FLAGS_DEFAULT * * #NL_ASSERT_DESIRE_PRODUCTION_FLAGS_DEFAULT * * #NL_ASSERT_REQUIRE_PRODUCTION_FLAGS_DEFAULT * * #NL_ASSERT_PRECONDITION_PRODUCTION_FLAGS_DEFAULT * * Setting this to 1, effectively does the following: * * @code * #define NL_ASSERT_