LCOV - code coverage report
Current view: top level - src/test - disconnected_transactions.cpp (source / functions) Coverage Total Hit
Test: total_coverage.info Lines: 100.0 % 45 45
Test Date: 2024-07-07 05:05:19 Functions: 100.0 % 2 2
Branches: 48.8 % 170 83

             Branch data     Line data    Source code
       1                 :             : // Copyright (c) 2023 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 <boost/test/unit_test.hpp>
       6                 :             : #include <core_memusage.h>
       7                 :             : #include <kernel/disconnected_transactions.h>
       8                 :             : #include <test/util/setup_common.h>
       9                 :             : 
      10                 :             : BOOST_FIXTURE_TEST_SUITE(disconnected_transactions, TestChain100Setup)
      11                 :             : 
      12                 :             : //! Tests that DisconnectedBlockTransactions limits its own memory properly
      13   [ +  -  +  -  :           7 : BOOST_AUTO_TEST_CASE(disconnectpool_memory_limits)
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
                      - ]
      14                 :             : {
      15                 :             :     // Use the coinbase transactions from TestChain100Setup. It doesn't matter whether these
      16                 :             :     // transactions would realistically be in a block together, they just need distinct txids and
      17                 :             :     // uniform size for this test to work.
      18                 :           1 :     std::vector<CTransactionRef> block_vtx(m_coinbase_txns);
      19   [ +  -  +  - ]:           1 :     BOOST_CHECK_EQUAL(block_vtx.size(), 100);
      20                 :             : 
      21                 :             :     // Roughly estimate sizes to sanity check that DisconnectedBlockTransactions::DynamicMemoryUsage
      22                 :             :     // is within an expected range.
      23                 :             : 
      24                 :             :     // Overhead for the hashmap depends on number of buckets
      25         [ +  - ]:           1 :     std::unordered_map<uint256, CTransaction*, SaltedTxidHasher> temp_map;
      26         [ +  - ]:           1 :     temp_map.reserve(1);
      27         [ +  - ]:           1 :     const size_t MAP_1{memusage::DynamicUsage(temp_map)};
      28         [ +  - ]:           1 :     temp_map.reserve(100);
      29         [ +  - ]:           1 :     const size_t MAP_100{memusage::DynamicUsage(temp_map)};
      30                 :             : 
      31                 :           1 :     const size_t TX_USAGE{RecursiveDynamicUsage(block_vtx.front())};
      32         [ +  + ]:         101 :     for (const auto& tx : block_vtx)
      33   [ +  -  +  - ]:         100 :         BOOST_CHECK_EQUAL(RecursiveDynamicUsage(tx), TX_USAGE);
      34                 :             : 
      35                 :             :     // Our overall formula is unordered map overhead + usage per entry.
      36                 :             :     // Implementations may vary, but we're trying to guess the usage of data structures.
      37                 :           1 :     const size_t ENTRY_USAGE_ESTIMATE{
      38                 :           1 :         TX_USAGE
      39                 :             :         // list entry: 2 pointers (next pointer and prev pointer) + element itself
      40                 :           1 :         + memusage::MallocUsage((2 * sizeof(void*)) + sizeof(decltype(block_vtx)::value_type))
      41                 :             :         // unordered map: 1 pointer for the hashtable + key and value
      42                 :           1 :         + memusage::MallocUsage(sizeof(void*) + sizeof(decltype(temp_map)::key_type)
      43                 :           1 :                                 + sizeof(decltype(temp_map)::value_type))};
      44                 :             : 
      45                 :             :     // DisconnectedBlockTransactions that's just big enough for 1 transaction.
      46                 :           1 :     {
      47         [ +  - ]:           1 :         DisconnectedBlockTransactions disconnectpool{MAP_1 + ENTRY_USAGE_ESTIMATE};
      48                 :             :         // Add just 2 (and not all 100) transactions to keep the unordered map's hashtable overhead
      49                 :             :         // to a minimum and avoid all (instead of all but 1) transactions getting evicted.
      50   [ +  -  +  -  :           5 :         std::vector<CTransactionRef> two_txns({block_vtx.at(0), block_vtx.at(1)});
          +  -  +  +  +  
             -  -  -  -  
                      - ]
      51         [ +  - ]:           1 :         auto evicted_txns{disconnectpool.AddTransactionsFromBlock(two_txns)};
      52   [ +  -  +  -  :           2 :         BOOST_CHECK(disconnectpool.DynamicMemoryUsage() <= MAP_1 + ENTRY_USAGE_ESTIMATE);
             +  -  +  - ]
      53                 :             : 
      54                 :             :         // Only 1 transaction can be kept
      55   [ +  -  +  - ]:           1 :         BOOST_CHECK_EQUAL(1, evicted_txns.size());
      56                 :             :         // Transactions are added from back to front and eviction is FIFO.
      57   [ +  -  +  -  :           1 :         BOOST_CHECK_EQUAL(block_vtx.at(1), evicted_txns.front());
                   +  - ]
      58                 :             : 
      59         [ +  - ]:           1 :         disconnectpool.clear();
      60                 :           1 :     }
      61                 :             : 
      62                 :             :     // DisconnectedBlockTransactions with a comfortable maximum memory usage so that nothing is evicted.
      63                 :             :     // Record usage so we can check size limiting in the next test.
      64                 :           1 :     size_t usage_full{0};
      65                 :           1 :     {
      66                 :           1 :         const size_t USAGE_100_OVERESTIMATE{MAP_100 + ENTRY_USAGE_ESTIMATE * 100};
      67         [ +  - ]:           1 :         DisconnectedBlockTransactions disconnectpool{USAGE_100_OVERESTIMATE};
      68         [ +  - ]:           1 :         auto evicted_txns{disconnectpool.AddTransactionsFromBlock(block_vtx)};
      69   [ +  -  +  - ]:           1 :         BOOST_CHECK_EQUAL(evicted_txns.size(), 0);
      70   [ +  -  +  -  :           2 :         BOOST_CHECK(disconnectpool.DynamicMemoryUsage() <= USAGE_100_OVERESTIMATE);
             +  -  +  - ]
      71                 :             : 
      72         [ +  - ]:           1 :         usage_full = disconnectpool.DynamicMemoryUsage();
      73                 :             : 
      74         [ +  - ]:           1 :         disconnectpool.clear();
      75                 :           1 :     }
      76                 :             : 
      77                 :             :     // DisconnectedBlockTransactions that's just a little too small for all of the transactions.
      78                 :           1 :     {
      79                 :           1 :         const size_t MAX_MEMUSAGE_99{usage_full - sizeof(void*)};
      80         [ +  - ]:           1 :         DisconnectedBlockTransactions disconnectpool{MAX_MEMUSAGE_99};
      81         [ +  - ]:           1 :         auto evicted_txns{disconnectpool.AddTransactionsFromBlock(block_vtx)};
      82   [ +  -  +  -  :           2 :         BOOST_CHECK(disconnectpool.DynamicMemoryUsage() <= MAX_MEMUSAGE_99);
             +  -  +  - ]
      83                 :             : 
      84                 :             :         // Only 1 transaction needed to be evicted
      85   [ +  -  +  - ]:           1 :         BOOST_CHECK_EQUAL(1, evicted_txns.size());
      86                 :             : 
      87                 :             :         // Transactions are added from back to front and eviction is FIFO.
      88                 :             :         // The last transaction of block_vtx should be the first to be evicted.
      89   [ +  -  +  - ]:           1 :         BOOST_CHECK_EQUAL(block_vtx.back(), evicted_txns.front());
      90                 :             : 
      91         [ +  - ]:           1 :         disconnectpool.clear();
      92                 :           1 :     }
      93   [ +  -  +  -  :           4 : }
          -  +  -  -  -  
                      - ]
      94                 :             : 
      95                 :             : BOOST_AUTO_TEST_SUITE_END()
        

Generated by: LCOV version 2.0-1