LCOV - code coverage report
Current view: top level - src/test - coinscachepair_tests.cpp (source / functions) Coverage Total Hit
Test: total_coverage.info Lines: 99.2 % 132 131
Test Date: 2024-11-04 05:10:19 Functions: 100.0 % 9 9
Branches: 51.2 % 518 265

             Branch data     Line data    Source code
       1                 :             : // Copyright (c) 2024-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 <coins.h>
       6                 :             : 
       7                 :             : #include <boost/test/unit_test.hpp>
       8                 :             : 
       9                 :             : #include <list>
      10                 :             : 
      11                 :             : BOOST_AUTO_TEST_SUITE(coinscachepair_tests)
      12                 :             : 
      13                 :             : static constexpr auto NUM_NODES{4};
      14                 :             : 
      15                 :           3 : std::list<CoinsCachePair> CreatePairs(CoinsCachePair& sentinel)
      16                 :             : {
      17                 :           3 :     std::list<CoinsCachePair> nodes;
      18         [ +  + ]:          15 :     for (auto i{0}; i < NUM_NODES; ++i) {
      19         [ +  - ]:          12 :         nodes.emplace_back();
      20                 :             : 
      21                 :          12 :         auto node{std::prev(nodes.end())};
      22                 :          12 :         node->second.AddFlags(CCoinsCacheEntry::DIRTY, *node, sentinel);
      23                 :             : 
      24   [ +  -  +  - ]:          12 :         BOOST_CHECK_EQUAL(node->second.GetFlags(), CCoinsCacheEntry::DIRTY);
      25   [ +  -  +  - ]:          12 :         BOOST_CHECK_EQUAL(node->second.Next(), &sentinel);
      26   [ +  -  +  - ]:          12 :         BOOST_CHECK_EQUAL(sentinel.second.Prev(), &(*node));
      27                 :             : 
      28         [ +  + ]:          12 :         if (i > 0) {
      29   [ +  -  +  - ]:           9 :             BOOST_CHECK_EQUAL(std::prev(node)->second.Next(), &(*node));
      30   [ +  -  +  - ]:           9 :             BOOST_CHECK_EQUAL(node->second.Prev(), &(*std::prev(node)));
      31                 :             :         }
      32                 :             :     }
      33                 :           3 :     return nodes;
      34                 :           0 : }
      35                 :             : 
      36   [ +  -  +  -  :           7 : BOOST_AUTO_TEST_CASE(linked_list_iteration)
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
                      - ]
      37                 :             : {
      38                 :           1 :     CoinsCachePair sentinel;
      39                 :           1 :     sentinel.second.SelfRef(sentinel);
      40         [ +  - ]:           1 :     auto nodes{CreatePairs(sentinel)};
      41                 :             : 
      42                 :             :     // Check iterating through pairs is identical to iterating through a list
      43                 :           1 :     auto node{sentinel.second.Next()};
      44         [ +  + ]:           5 :     for (const auto& expected : nodes) {
      45   [ +  -  +  - ]:           4 :         BOOST_CHECK_EQUAL(&expected, node);
      46                 :           4 :         node = node->second.Next();
      47                 :             :     }
      48   [ +  -  +  - ]:           1 :     BOOST_CHECK_EQUAL(node, &sentinel);
      49                 :             : 
      50                 :             :     // Check iterating through pairs is identical to iterating through a list
      51                 :             :     // Clear the flags during iteration
      52                 :           1 :     node = sentinel.second.Next();
      53         [ +  + ]:           5 :     for (const auto& expected : nodes) {
      54   [ +  -  +  - ]:           4 :         BOOST_CHECK_EQUAL(&expected, node);
      55                 :           4 :         auto next = node->second.Next();
      56         [ +  - ]:           4 :         node->second.ClearFlags();
      57                 :           4 :         node = next;
      58                 :             :     }
      59   [ +  -  +  - ]:           1 :     BOOST_CHECK_EQUAL(node, &sentinel);
      60                 :             :     // Check that sentinel's next and prev are itself
      61   [ +  -  +  - ]:           1 :     BOOST_CHECK_EQUAL(sentinel.second.Next(), &sentinel);
      62   [ +  -  +  - ]:           1 :     BOOST_CHECK_EQUAL(sentinel.second.Prev(), &sentinel);
      63                 :             : 
      64                 :             :     // Delete the nodes from the list to make sure there are no dangling pointers
      65         [ +  + ]:           5 :     for (auto it{nodes.begin()}; it != nodes.end(); it = nodes.erase(it)) {
      66   [ +  -  +  - ]:           4 :         BOOST_CHECK_EQUAL(it->second.GetFlags(), 0);
      67                 :             :     }
      68                 :           1 : }
      69                 :             : 
      70   [ +  -  +  -  :           7 : BOOST_AUTO_TEST_CASE(linked_list_iterate_erase)
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
                      - ]
      71                 :             : {
      72                 :           1 :     CoinsCachePair sentinel;
      73                 :           1 :     sentinel.second.SelfRef(sentinel);
      74         [ +  - ]:           1 :     auto nodes{CreatePairs(sentinel)};
      75                 :             : 
      76                 :             :     // Check iterating through pairs is identical to iterating through a list
      77                 :             :     // Erase the nodes as we iterate through, but don't clear flags
      78                 :             :     // The flags will be cleared by the CCoinsCacheEntry's destructor
      79                 :           1 :     auto node{sentinel.second.Next()};
      80         [ +  + ]:           5 :     for (auto expected{nodes.begin()}; expected != nodes.end(); expected = nodes.erase(expected)) {
      81   [ +  -  +  - ]:           4 :         BOOST_CHECK_EQUAL(&(*expected), node);
      82                 :           4 :         node = node->second.Next();
      83                 :             :     }
      84   [ +  -  +  - ]:           1 :     BOOST_CHECK_EQUAL(node, &sentinel);
      85                 :             : 
      86                 :             :     // Check that sentinel's next and prev are itself
      87   [ +  -  +  - ]:           1 :     BOOST_CHECK_EQUAL(sentinel.second.Next(), &sentinel);
      88   [ +  -  +  - ]:           1 :     BOOST_CHECK_EQUAL(sentinel.second.Prev(), &sentinel);
      89                 :           1 : }
      90                 :             : 
      91   [ +  -  +  -  :           7 : BOOST_AUTO_TEST_CASE(linked_list_random_deletion)
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
                      - ]
      92                 :             : {
      93                 :           1 :     CoinsCachePair sentinel;
      94                 :           1 :     sentinel.second.SelfRef(sentinel);
      95         [ +  - ]:           1 :     auto nodes{CreatePairs(sentinel)};
      96                 :             : 
      97                 :             :     // Create linked list sentinel->n1->n2->n3->n4->sentinel
      98                 :           1 :     auto n1{nodes.begin()};
      99                 :           1 :     auto n2{std::next(n1)};
     100                 :           1 :     auto n3{std::next(n2)};
     101                 :           1 :     auto n4{std::next(n3)};
     102                 :             : 
     103                 :             :     // Delete n2
     104                 :             :     // sentinel->n1->n3->n4->sentinel
     105                 :           1 :     nodes.erase(n2);
     106                 :             :     // Check that n1 now points to n3, and n3 still points to n4
     107                 :             :     // Also check that flags were not altered
     108   [ +  -  +  - ]:           1 :     BOOST_CHECK_EQUAL(n1->second.GetFlags(), CCoinsCacheEntry::DIRTY);
     109   [ +  -  +  - ]:           1 :     BOOST_CHECK_EQUAL(n1->second.Next(), &(*n3));
     110   [ +  -  +  - ]:           1 :     BOOST_CHECK_EQUAL(n3->second.GetFlags(), CCoinsCacheEntry::DIRTY);
     111   [ +  -  +  - ]:           1 :     BOOST_CHECK_EQUAL(n3->second.Next(), &(*n4));
     112   [ +  -  +  - ]:           1 :     BOOST_CHECK_EQUAL(n3->second.Prev(), &(*n1));
     113                 :             : 
     114                 :             :     // Delete n1
     115                 :             :     // sentinel->n3->n4->sentinel
     116                 :           1 :     nodes.erase(n1);
     117                 :             :     // Check that sentinel now points to n3, and n3 still points to n4
     118                 :             :     // Also check that flags were not altered
     119   [ +  -  +  - ]:           1 :     BOOST_CHECK_EQUAL(n3->second.GetFlags(), CCoinsCacheEntry::DIRTY);
     120   [ +  -  +  - ]:           1 :     BOOST_CHECK_EQUAL(sentinel.second.Next(), &(*n3));
     121   [ +  -  +  - ]:           1 :     BOOST_CHECK_EQUAL(n3->second.Next(), &(*n4));
     122   [ +  -  +  - ]:           1 :     BOOST_CHECK_EQUAL(n3->second.Prev(), &sentinel);
     123                 :             : 
     124                 :             :     // Delete n4
     125                 :             :     // sentinel->n3->sentinel
     126                 :           1 :     nodes.erase(n4);
     127                 :             :     // Check that sentinel still points to n3, and n3 points to sentinel
     128                 :             :     // Also check that flags were not altered
     129   [ +  -  +  - ]:           1 :     BOOST_CHECK_EQUAL(n3->second.GetFlags(), CCoinsCacheEntry::DIRTY);
     130   [ +  -  +  - ]:           1 :     BOOST_CHECK_EQUAL(sentinel.second.Next(), &(*n3));
     131   [ +  -  +  - ]:           1 :     BOOST_CHECK_EQUAL(n3->second.Next(), &sentinel);
     132   [ +  -  +  - ]:           1 :     BOOST_CHECK_EQUAL(sentinel.second.Prev(), &(*n3));
     133                 :             : 
     134                 :             :     // Delete n3
     135                 :             :     // sentinel->sentinel
     136                 :           1 :     nodes.erase(n3);
     137                 :             :     // Check that sentinel's next and prev are itself
     138   [ +  -  +  - ]:           1 :     BOOST_CHECK_EQUAL(sentinel.second.Next(), &sentinel);
     139   [ +  -  +  - ]:           1 :     BOOST_CHECK_EQUAL(sentinel.second.Prev(), &sentinel);
     140                 :           1 : }
     141                 :             : 
     142   [ +  -  +  -  :           7 : BOOST_AUTO_TEST_CASE(linked_list_add_flags)
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
                      - ]
     143                 :             : {
     144                 :           1 :     CoinsCachePair sentinel;
     145                 :           1 :     sentinel.second.SelfRef(sentinel);
     146                 :           1 :     CoinsCachePair n1;
     147                 :           1 :     CoinsCachePair n2;
     148                 :             : 
     149                 :             :     // Check that adding 0 flag has no effect
     150                 :           1 :     n1.second.AddFlags(0, n1, sentinel);
     151   [ +  -  +  - ]:           1 :     BOOST_CHECK_EQUAL(n1.second.GetFlags(), 0);
     152   [ +  -  +  - ]:           1 :     BOOST_CHECK_EQUAL(sentinel.second.Next(), &sentinel);
     153   [ +  -  +  - ]:           1 :     BOOST_CHECK_EQUAL(sentinel.second.Prev(), &sentinel);
     154                 :             : 
     155                 :             :     // Check that adding DIRTY flag inserts it into linked list and sets flags
     156                 :           1 :     n1.second.AddFlags(CCoinsCacheEntry::DIRTY, n1, sentinel);
     157   [ +  -  +  - ]:           1 :     BOOST_CHECK_EQUAL(n1.second.GetFlags(), CCoinsCacheEntry::DIRTY);
     158   [ +  -  +  - ]:           1 :     BOOST_CHECK_EQUAL(n1.second.Next(), &sentinel);
     159   [ +  -  +  - ]:           1 :     BOOST_CHECK_EQUAL(n1.second.Prev(), &sentinel);
     160   [ +  -  +  - ]:           1 :     BOOST_CHECK_EQUAL(sentinel.second.Next(), &n1);
     161   [ +  -  +  - ]:           1 :     BOOST_CHECK_EQUAL(sentinel.second.Prev(), &n1);
     162                 :             : 
     163                 :             :     // Check that adding FRESH flag on new node inserts it after n1
     164                 :           1 :     n2.second.AddFlags(CCoinsCacheEntry::FRESH, n2, sentinel);
     165   [ +  -  +  - ]:           1 :     BOOST_CHECK_EQUAL(n2.second.GetFlags(), CCoinsCacheEntry::FRESH);
     166   [ +  -  +  - ]:           1 :     BOOST_CHECK_EQUAL(n2.second.Next(), &sentinel);
     167   [ +  -  +  - ]:           1 :     BOOST_CHECK_EQUAL(n2.second.Prev(), &n1);
     168   [ +  -  +  - ]:           1 :     BOOST_CHECK_EQUAL(n1.second.Next(), &n2);
     169   [ +  -  +  - ]:           1 :     BOOST_CHECK_EQUAL(sentinel.second.Prev(), &n2);
     170                 :             : 
     171                 :             :     // Check that adding 0 flag has no effect, and doesn't change position
     172                 :           1 :     n1.second.AddFlags(0, n1, sentinel);
     173   [ +  -  +  - ]:           1 :     BOOST_CHECK_EQUAL(n1.second.GetFlags(), CCoinsCacheEntry::DIRTY);
     174   [ +  -  +  - ]:           1 :     BOOST_CHECK_EQUAL(n1.second.Next(), &n2);
     175   [ +  -  +  - ]:           1 :     BOOST_CHECK_EQUAL(n1.second.Prev(), &sentinel);
     176   [ +  -  +  - ]:           1 :     BOOST_CHECK_EQUAL(sentinel.second.Next(), &n1);
     177   [ +  -  +  - ]:           1 :     BOOST_CHECK_EQUAL(n2.second.Prev(), &n1);
     178                 :             : 
     179                 :             :     // Check that we can add extra flags, but they don't change our position
     180                 :           1 :     n1.second.AddFlags(CCoinsCacheEntry::FRESH, n1, sentinel);
     181   [ +  -  +  - ]:           1 :     BOOST_CHECK_EQUAL(n1.second.GetFlags(), CCoinsCacheEntry::DIRTY | CCoinsCacheEntry::FRESH);
     182   [ +  -  +  - ]:           1 :     BOOST_CHECK_EQUAL(n1.second.Next(), &n2);
     183   [ +  -  +  - ]:           1 :     BOOST_CHECK_EQUAL(n1.second.Prev(), &sentinel);
     184   [ +  -  +  - ]:           1 :     BOOST_CHECK_EQUAL(sentinel.second.Next(), &n1);
     185   [ +  -  +  - ]:           1 :     BOOST_CHECK_EQUAL(n2.second.Prev(), &n1);
     186                 :             : 
     187                 :             :     // Check that we can clear flags then re-add them
     188         [ +  - ]:           1 :     n1.second.ClearFlags();
     189   [ +  -  +  - ]:           1 :     BOOST_CHECK_EQUAL(n1.second.GetFlags(), 0);
     190   [ +  -  +  - ]:           1 :     BOOST_CHECK_EQUAL(sentinel.second.Next(), &n2);
     191   [ +  -  +  - ]:           1 :     BOOST_CHECK_EQUAL(sentinel.second.Prev(), &n2);
     192   [ +  -  +  - ]:           1 :     BOOST_CHECK_EQUAL(n2.second.Next(), &sentinel);
     193   [ +  -  +  - ]:           1 :     BOOST_CHECK_EQUAL(n2.second.Prev(), &sentinel);
     194                 :             : 
     195                 :             :     // Check that calling `ClearFlags` with 0 flags has no effect
     196         [ -  + ]:           1 :     n1.second.ClearFlags();
     197   [ +  -  +  - ]:           1 :     BOOST_CHECK_EQUAL(n1.second.GetFlags(), 0);
     198   [ +  -  +  - ]:           1 :     BOOST_CHECK_EQUAL(sentinel.second.Next(), &n2);
     199   [ +  -  +  - ]:           1 :     BOOST_CHECK_EQUAL(sentinel.second.Prev(), &n2);
     200   [ +  -  +  - ]:           1 :     BOOST_CHECK_EQUAL(n2.second.Next(), &sentinel);
     201   [ +  -  +  - ]:           1 :     BOOST_CHECK_EQUAL(n2.second.Prev(), &sentinel);
     202                 :             : 
     203                 :             :     // Adding 0 still has no effect
     204                 :           1 :     n1.second.AddFlags(0, n1, sentinel);
     205   [ +  -  +  - ]:           1 :     BOOST_CHECK_EQUAL(sentinel.second.Next(), &n2);
     206   [ +  -  +  - ]:           1 :     BOOST_CHECK_EQUAL(sentinel.second.Prev(), &n2);
     207   [ +  -  +  - ]:           1 :     BOOST_CHECK_EQUAL(n2.second.Next(), &sentinel);
     208   [ +  -  +  - ]:           1 :     BOOST_CHECK_EQUAL(n2.second.Prev(), &sentinel);
     209                 :             : 
     210                 :             :     // But adding DIRTY re-inserts it after n2
     211                 :           1 :     n1.second.AddFlags(CCoinsCacheEntry::DIRTY, n1, sentinel);
     212   [ +  -  +  - ]:           1 :     BOOST_CHECK_EQUAL(n1.second.GetFlags(), CCoinsCacheEntry::DIRTY);
     213   [ +  -  +  - ]:           1 :     BOOST_CHECK_EQUAL(n2.second.Next(), &n1);
     214   [ +  -  +  - ]:           1 :     BOOST_CHECK_EQUAL(n1.second.Prev(), &n2);
     215   [ +  -  +  - ]:           1 :     BOOST_CHECK_EQUAL(n1.second.Next(), &sentinel);
     216   [ +  -  +  - ]:           1 :     BOOST_CHECK_EQUAL(sentinel.second.Prev(), &n1);
     217                 :           1 : }
     218                 :             : 
     219                 :             : BOOST_AUTO_TEST_SUITE_END()
        

Generated by: LCOV version 2.0-1