From 88dcf22abff266fd86b50838a41a0233dfd560af Mon Sep 17 00:00:00 2001 From: glozow Date: Thu, 7 Sep 2023 08:40:34 +0100 Subject: [PATCH] [test] DisconnectedBlockTransactions::DynamicMemoryUsage --- src/Makefile.test.include | 1 + src/test/disconnected_transactions.cpp | 94 ++++++++++++++++++++++++++ 2 files changed, 95 insertions(+) create mode 100644 src/test/disconnected_transactions.cpp diff --git a/src/Makefile.test.include b/src/Makefile.test.include index 5dc20d4fab9fa0..578101022be629 100644 --- a/src/Makefile.test.include +++ b/src/Makefile.test.include @@ -92,6 +92,7 @@ BITCOIN_TESTS =\ test/dbwrapper_tests.cpp \ test/denialofservice_tests.cpp \ test/descriptor_tests.cpp \ + test/disconnected_transactions.cpp \ test/flatfile_tests.cpp \ test/fs_tests.cpp \ test/getarg_tests.cpp \ diff --git a/src/test/disconnected_transactions.cpp b/src/test/disconnected_transactions.cpp new file mode 100644 index 00000000000000..71c9c40386b99b --- /dev/null +++ b/src/test/disconnected_transactions.cpp @@ -0,0 +1,94 @@ +// Copyright (c) 2023 The Bitcoin Core developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// +#include +#include + +#include + +BOOST_FIXTURE_TEST_SUITE(disconnected_transactions, TestChain100Setup) + +//! Tests that DisconnectedBlockTransactions limits its own memory properly +BOOST_AUTO_TEST_CASE(disconnectpool_memory_limits) +{ + // Use the coinbase transactions from TestChain100Setup. It doesn't matter whether these + // transactions would realistically be in a block together, they just need distinct txids for + // this test to work. + std::vector block_vtx(m_coinbase_txns); + + size_t usage_full{0}; + // DisconnectedBlockTransactions with a comfortable maximum memory usage s.t. nothing is evicted. + { + DisconnectedBlockTransactions disconnectpool{MAX_DISCONNECTED_TX_POOL_SIZE * 1000}; + auto evicted_txns = disconnectpool.AddTransactionsFromBlock(block_vtx); + BOOST_CHECK_EQUAL(evicted_txns.size(), 0); + BOOST_CHECK(disconnectpool.DynamicMemoryUsage() <= MAX_DISCONNECTED_TX_POOL_SIZE * 1000); + + usage_full = disconnectpool.DynamicMemoryUsage(); + + disconnectpool.clear(); + } + + // DisconnectedBlockTransactions that's just a little too small for all of the transactions. + { + const size_t MAX_MEMUSAGE_99{usage_full - sizeof(void*)}; + DisconnectedBlockTransactions disconnectpool{MAX_MEMUSAGE_99}; + auto evicted_txns = disconnectpool.AddTransactionsFromBlock(block_vtx); + BOOST_CHECK(disconnectpool.DynamicMemoryUsage() <= MAX_MEMUSAGE_99); + + // Only 1 transaction needed to be evicted + BOOST_CHECK_EQUAL(1, evicted_txns.size()); + + // Transactions are added from back to front and eviction is FIFO. + // The last transaction of block_vtx should be the first to be evicted. + BOOST_CHECK_EQUAL(block_vtx.back(), evicted_txns.front()); + + disconnectpool.clear(); + } +} + +//! Sanity checks for DisconnectedBlockTransactions::DynamicMemoryUsage. +BOOST_AUTO_TEST_CASE(disconnectpool_memusage) +{ + if (sizeof(void*) != 8) { + BOOST_TEST_MESSAGE("Exiting DisconnectedBlockTransactions memusage tests early due to unsupported arch"); + } + + // Use the coinbase transactions from TestChain100Setup as they all have the same size and it + // doesn't matter whether these transactions would realistically be in a block together. They + // just need distinct txids for this test to work. + std::vector block_vtx(m_coinbase_txns); + + // Sanity check the sizes are as expected. If setup_common changes the size of coinbase + // transactions, update COINBASE_TX_USAGE. + const size_t COINBASE_TX_USAGE{640}; + BOOST_CHECK_EQUAL(block_vtx.size(), 100); + for (const auto& tx : block_vtx) { + BOOST_CHECK_EQUAL(RecursiveDynamicUsage(tx), COINBASE_TX_USAGE); + } + + // Test DisconnectedBlockTransactions::DynamicMemoryUsage() for 100 transactions + const size_t EXPECTED_USAGE_100{77648}; + { + const size_t MAX_MEMUSAGE_100{EXPECTED_USAGE_100}; + DisconnectedBlockTransactions disconnectpool{MAX_MEMUSAGE_100}; + auto evicted_txns = disconnectpool.AddTransactionsFromBlock(block_vtx); + BOOST_CHECK_EQUAL(evicted_txns.size(), 0); + BOOST_CHECK_EQUAL(disconnectpool.DynamicMemoryUsage(), EXPECTED_USAGE_100); + disconnectpool.clear(); + } + + // Test DisconnectedBlockTransactions::DynamicMemoryUsage() for 1 transaction + const size_t EXPECTED_USAGE_1{800}; + { + const size_t MAX_MEMUSAGE_100{EXPECTED_USAGE_100}; + DisconnectedBlockTransactions disconnectpool{MAX_MEMUSAGE_100}; + auto evicted_txns = disconnectpool.AddTransactionsFromBlock({block_vtx.front()}); + BOOST_CHECK_EQUAL(evicted_txns.size(), 0); + BOOST_CHECK_EQUAL(disconnectpool.DynamicMemoryUsage(), EXPECTED_USAGE_1); + disconnectpool.clear(); + } +} + +BOOST_AUTO_TEST_SUITE_END()