// bsls_preconditions.h -*-C++-*- #ifndef INCLUDED_BSLS_PRECONDITIONS #define INCLUDED_BSLS_PRECONDITIONS #include <bsls_ident.h> BSLS_IDENT("$Id: $") //@PURPOSE: Provide macros for use in fuzz testing narrow contract functions. // //@CLASSES: // bsls::PreconditionsHandler: for begin/end callback management functions // //@MACROS: // BSLS_PRECONDITIONS_BEGIN: mark the start of function preconditions // BSLS_PRECONDITIONS_END: mark the end of function preconditions // //@SEE_ALSO: bsls_fuzztest // //@DESCRIPTION: This component provides macros, 'BSLS_PRECONDITIONS_BEGIN' and // 'BSLS_PRECONDITIONS_END', to facilitate fuzz testing narrow contract // functions. When fuzz testing is not enabled, the macros expand to nothing. // When fuzz testing is enabled, the macros invoke a dynamic handler function // via 'bsls::PreconditionsHandler'. // // 'BSLS_PRECONDITIONS_BEGIN' is used as a marker to identify where // precondition checks are begun, while 'BSLS_PRECONDITIONS_END' is used as a // marker to identify where precondition checks are complete. These macros // should always be used as a pair, and always at the very beginning of a // function, surrounding the function preconditions. // ///Usage ///----- // Since the macros contained in this component are intended to be used in // conjunction with the macros defined in 'bsls_fuzztest', this test driver // contains only the simplest USAGE EXAMPLE. See the USAGE EXAMPLE in // {'bsls_fuzztest'} for a fuller treatment. // // The following example shows the use of 'BSLS_PRECONDITIONS_BEGIN' and // 'BSLS_PRECONDITIONS_END' in the definition of a narrow contract function. // These macros are to be placed around the function precondition checks, // immediately before and after. //.. // double mySqrt(double x) // // Return the square root of the specified 'x'. The behavior is // // undefined unless 'x >= 0'. // { // BSLS_PRECONDITIONS_BEGIN(); // BSLS_ASSERT(0 <= x); // BSLS_PRECONDITIONS_END(); // return sqrt(x); // } //.. // In a fuzz-enabled build, we would invoke this function inside the fuzz loop // with 'BSLS_FUZZTEST_EVALUATE'. #include <bsls_assert.h> #include <bsls_atomicoperations.h> // 'AtomicTypes' #include <bsls_consteval.h> #include <bsls_pointercastutil.h> // ================= // Macro Definitions // ================= #define BSLS_PRECONDITIONS_BEGIN_IMP() do { \ bsls::PreconditionsHandler::invokeBeginHandler(); \ } while (false) #define BSLS_PRECONDITIONS_END_IMP() do { \ bsls::PreconditionsHandler::invokeEndHandler(); \ } while (false) #if defined(BDE_ACTIVATE_FUZZ_TESTING) && \ defined(BSLS_CONSTEVAL_IS_CONSTANT_EVALUATED_IS_ACTIVE) #define BSLS_PRECONDITIONS_BEGIN() do { \ if (!BSLS_CONSTEVAL_IS_CONSTANT_EVALUATED) { \ BSLS_PRECONDITIONS_BEGIN_IMP(); \ } \ } while (false) #define BSLS_PRECONDITIONS_END() do { \ if (!BSLS_CONSTEVAL_IS_CONSTANT_EVALUATED) { \ BSLS_PRECONDITIONS_END_IMP(); \ } \ } while (false) #else // fuzzing not enabled or 'consteval' not active #define BSLS_PRECONDITIONS_BEGIN() do {} while(false) #define BSLS_PRECONDITIONS_END() do {} while(false) #endif namespace BloombergLP { namespace bsls { // =========================== // class PreconditionsHandler // =========================== class PreconditionsHandler { // This utility class maintains pointers containing the addresses of // functions invoked by the 'BSLS_PRECONDITIONS_BEGIN' and // 'BSLS_PRECONDITIONS_END' macros, and provides methods to // manipulate and utilize those functions. private: // CLASS DATA static AtomicOperations::AtomicTypes::Pointer s_beginHandler; // begin handler function static AtomicOperations::AtomicTypes::Pointer s_endHandler; // end handler function public: // TYPES typedef void (*PreconditionHandlerType)(); // 'PreconditionHandlerType' is an alias for a pointer to a function // returning 'void' and taking no parameters. // CLASS METHODS static PreconditionHandlerType getBeginHandler(); // Return the previously installed 's_beginHandler'. static PreconditionHandlerType getEndHandler(); // Return the previously installed 's_endHandler'. static void installHandlers(PreconditionHandlerType beginHandler, PreconditionHandlerType endHandler); // Store the specified 'beginHandler' and 'endHandler' function // pointers to the 'static' member variables. static void invokeBeginHandler(); // Invoke the previously installed 's_beginHandler' function. static void invokeEndHandler(); // Invoke the previously installed 's_endHandler' function. static void noOpHandler(); // Do nothing. }; } // close package namespace } // close enterprise namespace #endif // ---------------------------------------------------------------------------- // Copyright 2021 Bloomberg Finance L.P. // // 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. // ----------------------------- END-OF-FILE ----------------------------------