LCOV - code coverage report
Current view: top level - src/util - check.h (source / functions) Hit Total Coverage
Test: fuzz_coverage.info Lines: 7 10 70.0 %
Date: 2023-10-05 15:40:34 Functions: 40 64 62.5 %
Branches: 19 50 38.0 %

           Branch data     Line data    Source code
       1                 :            : // Copyright (c) 2019-2022 The Bitcoin Core developers
       2                 :            : // Distributed under the MIT software license, see the accompanying
       3                 :            : // file COPYING or http://www.opensource.org/licenses/mit-license.php.
       4                 :            : 
       5                 :            : #ifndef BITCOIN_UTIL_CHECK_H
       6                 :            : #define BITCOIN_UTIL_CHECK_H
       7                 :            : 
       8                 :            : #include <attributes.h>
       9                 :            : 
      10                 :            : #include <stdexcept>
      11                 :            : #include <string>
      12                 :            : #include <string_view>
      13                 :            : #include <utility>
      14                 :            : 
      15                 :            : std::string StrFormatInternalBug(std::string_view msg, std::string_view file, int line, std::string_view func);
      16                 :            : 
      17                 :            : class NonFatalCheckError : public std::runtime_error
      18                 :            : {
      19                 :            : public:
      20                 :            :     NonFatalCheckError(std::string_view msg, std::string_view file, int line, std::string_view func);
      21                 :            : };
      22                 :            : 
      23                 :            : #define STR_INTERNAL_BUG(msg) StrFormatInternalBug((msg), __FILE__, __LINE__, __func__)
      24                 :            : 
      25                 :            : /** Helper for CHECK_NONFATAL() */
      26                 :            : template <typename T>
      27                 :     197881 : T&& inline_check_non_fatal(LIFETIMEBOUND T&& val, const char* file, int line, const char* func, const char* assertion)
      28                 :            : {
      29   [ +  +  +  -  :     197881 :     if (!val) {
          +  +  +  -  #  
                      # ]
      30   [ +  -  #  #  :         65 :         throw NonFatalCheckError{assertion, file, line, func};
          +  -  #  #  #  
                      # ]
      31                 :            :     }
      32                 :     197816 :     return std::forward<T>(val);
      33                 :          0 : }
      34                 :            : 
      35                 :            : /**
      36                 :            :  * Identity function. Throw a NonFatalCheckError when the condition evaluates to false
      37                 :            :  *
      38                 :            :  * This should only be used
      39                 :            :  * - where the condition is assumed to be true, not for error handling or validating user input
      40                 :            :  * - where a failure to fulfill the condition is recoverable and does not abort the program
      41                 :            :  *
      42                 :            :  * For example in RPC code, where it is undesirable to crash the whole program, this can be generally used to replace
      43                 :            :  * asserts or recoverable logic errors. A NonFatalCheckError in RPC code is caught and passed as a string to the RPC
      44                 :            :  * caller, which can then report the issue to the developers.
      45                 :            :  */
      46                 :            : #define CHECK_NONFATAL(condition) \
      47                 :            :     inline_check_non_fatal(condition, __FILE__, __LINE__, __func__, #condition)
      48                 :            : 
      49                 :            : #if defined(NDEBUG)
      50                 :            : #error "Cannot compile without assertions!"
      51                 :            : #endif
      52                 :            : 
      53                 :            : /** Helper for Assert() */
      54                 :            : void assertion_fail(std::string_view file, int line, std::string_view func, std::string_view assertion);
      55                 :            : 
      56                 :            : /** Helper for Assert()/Assume() */
      57                 :            : template <bool IS_ASSERT, typename T>
      58                 :   90987620 : T&& inline_assertion_check(LIFETIMEBOUND T&& val, [[maybe_unused]] const char* file, [[maybe_unused]] int line, [[maybe_unused]] const char* func, [[maybe_unused]] const char* assertion)
      59                 :            : {
      60                 :            :     if constexpr (IS_ASSERT
      61                 :            : #ifdef ABORT_ON_FAILED_ASSUME
      62                 :            :                   || true
      63                 :            : #endif
      64                 :            :     ) {
      65   [ +  +  +  +  :   90987620 :         if (!val) {
          +  +  +  -  #  
          #  #  #  #  #  
          -  +  #  #  #  
          #  #  #  #  #  
          -  +  +  -  +  
                      - ]
      66                 :          0 :             assertion_fail(file, line, func, assertion);
      67                 :          0 :         }
      68                 :            :     }
      69                 :   90987620 :     return std::forward<T>(val);
      70                 :            : }
      71                 :            : 
      72                 :            : /** Identity function. Abort if the value compares equal to zero */
      73                 :            : #define Assert(val) inline_assertion_check<true>(val, __FILE__, __LINE__, __func__, #val)
      74                 :            : 
      75                 :            : /**
      76                 :            :  * Assume is the identity function.
      77                 :            :  *
      78                 :            :  * - Should be used to run non-fatal checks. In debug builds it behaves like
      79                 :            :  *   Assert()/assert() to notify developers and testers about non-fatal errors.
      80                 :            :  *   In production it doesn't warn or log anything.
      81                 :            :  * - For fatal errors, use Assert().
      82                 :            :  * - For non-fatal errors in interactive sessions (e.g. RPC or command line
      83                 :            :  *   interfaces), CHECK_NONFATAL() might be more appropriate.
      84                 :            :  */
      85                 :            : #define Assume(val) inline_assertion_check<false>(val, __FILE__, __LINE__, __func__, #val)
      86                 :            : 
      87                 :            : /**
      88                 :            :  * NONFATAL_UNREACHABLE() is a macro that is used to mark unreachable code. It throws a NonFatalCheckError.
      89                 :            :  */
      90                 :            : #define NONFATAL_UNREACHABLE()                                        \
      91                 :            :     throw NonFatalCheckError(                                         \
      92                 :            :         "Unreachable code reached (non-fatal)", __FILE__, __LINE__, __func__)
      93                 :            : 
      94                 :            : #endif // BITCOIN_UTIL_CHECK_H

Generated by: LCOV version 1.14