LCOV - code coverage report
Current view: top level - src/test/fuzz/util - reachability.cpp (source / functions) Coverage Total Hit
Test: fuzz_coverage.info Lines: 84.3 % 51 43
Test Date: 2026-11-03 06:39:55 Functions: 100.0 % 7 7
Branches: 48.3 % 58 28

             Branch data     Line data    Source code
       1                 :             : // Copyright (c) 2026-present 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                 :             : #include <sync.h>
       6                 :             : #include <test/fuzz/util/reachability.h>
       7                 :             : #include <util/check.h>
       8                 :             : 
       9                 :             : #include <compare>
      10                 :             : #include <cstdint>
      11                 :             : #include <cstdio>
      12                 :             : #include <cstdlib>
      13                 :             : #include <iostream>
      14                 :             : #include <map>
      15                 :             : #include <string>
      16                 :             : #include <string_view>
      17                 :             : 
      18                 :             : namespace {
      19                 :             : struct GoalId {
      20                 :             :     std::string_view file_name;
      21                 :       96660 :     std::uint_least32_t line;
      22                 :       84728 :     std::uint_least32_t column;
      23                 :             : 
      24                 :       96660 :     auto operator<=>(const GoalId&) const = default;
           [ -  +  +  +  
          +  +  +  +  -  
             +  -  -  -  
                      + ]
      25                 :             : };
      26                 :             : 
      27                 :          17 : struct GoalState {
      28                 :             :     std::string message;
      29                 :             :     bool reached{false};
      30                 :             : 
      31                 :          17 :     explicit GoalState(std::string_view message) : message{message} {}
      32                 :             : };
      33                 :             : 
      34                 :             : class ReachabilityTracker
      35                 :             : {
      36                 :             : public:
      37                 :         238 :     ReachabilityTracker()
      38                 :         238 :     {
      39                 :         238 :         const char* enforce{std::getenv("FUZZ_ENFORCE_REACHABILITY")};
      40   [ -  +  -  - ]:         238 :         if (!enforce || std::string_view{enforce} == "0") return;
      41         [ #  # ]:           0 :         if (std::string_view{enforce} == "1") {
      42                 :           0 :             m_enforce = true;
      43                 :           0 :             return;
      44                 :             :         }
      45         [ #  # ]:           0 :         std::fputs("FUZZ_ENFORCE_REACHABILITY must be 0 or 1.\n", stderr);
      46                 :           0 :         std::abort();
      47                 :           0 :     }
      48                 :             : 
      49                 :         238 :     ~ReachabilityTracker()
      50                 :             :     {
      51                 :         238 :         LOCK(m_mutex);
      52                 :         238 :         bool all_reached{true};
      53   [ -  +  +  + ]:         255 :         for (const auto& [id, goal] : m_goals) {
      54                 :          17 :             std::cerr << (goal.reached ? "PASS" : "FAIL") << " reachability goal \""
      55   [ -  +  -  + ]:          34 :                       << goal.message << "\" at " << id.file_name << ':' << id.line << ':' << id.column << '\n';
      56                 :          17 :             all_reached &= goal.reached;
      57                 :             :         }
      58   [ -  +  -  - ]:         238 :         if (m_enforce && !all_reached) {
      59                 :           0 :             std::cerr.flush();
      60                 :           0 :             std::_Exit(EXIT_FAILURE);
      61                 :             :         }
      62                 :         238 :     }
      63                 :             : 
      64                 :          17 :     void Register(const ReachabilityGoal& goal) EXCLUSIVE_LOCKS_REQUIRED(!m_mutex)
      65                 :             :     {
      66                 :          17 :         const GoalId id{
      67                 :             :             .file_name = goal.location.file_name(),
      68         [ +  - ]:          17 :             .line = goal.location.line(),
      69                 :          34 :             .column = goal.location.column(),
      70   [ +  -  +  -  :          51 :         };
                   +  - ]
      71                 :          17 :         LOCK(m_mutex);
      72         [ +  - ]:          17 :         const bool inserted{m_goals.try_emplace(id, goal.message).second};
      73         [ +  - ]:          17 :         Assert(inserted);
      74                 :          17 :     }
      75                 :             : 
      76                 :       42364 :     void Observe(bool reached, const ReachabilityGoal& goal) EXCLUSIVE_LOCKS_REQUIRED(!m_mutex)
      77                 :             :     {
      78                 :       42364 :         const GoalId id{
      79                 :             :             .file_name = goal.location.file_name(),
      80         [ +  - ]:       42364 :             .line = goal.location.line(),
      81                 :       84728 :             .column = goal.location.column(),
      82   [ +  -  +  -  :      127092 :         };
                   +  - ]
      83                 :       42364 :         LOCK(m_mutex);
      84                 :       42364 :         const auto it{m_goals.find(id)};
      85         [ +  - ]:       42364 :         Assert(it != m_goals.end());
      86         [ +  - ]:       42364 :         it->second.reached |= reached;
      87                 :       42364 :     }
      88                 :             : 
      89                 :             : private:
      90                 :             :     Mutex m_mutex;
      91                 :             :     std::map<GoalId, GoalState> m_goals GUARDED_BY(m_mutex);
      92                 :             :     bool m_enforce{false};
      93                 :             : };
      94                 :             : 
      95                 :             : ReachabilityTracker g_reachability_tracker;
      96                 :             : } // namespace
      97                 :             : 
      98                 :          17 : void RegisterReachabilityGoal(const ReachabilityGoal& goal)
      99                 :             : {
     100                 :          17 :     g_reachability_tracker.Register(goal);
     101                 :          17 : }
     102                 :             : 
     103                 :       42364 : void ObserveReachabilityGoal(bool reached, const ReachabilityGoal& goal)
     104                 :             : {
     105                 :       42364 :     g_reachability_tracker.Observe(reached, goal);
     106                 :       42364 : }
        

Generated by: LCOV version 2.5.0-full