mirror of
https://github.com/bitcoin/bitcoin.git
synced 2026-07-17 10:17:09 +02:00
Currently, all test cases using TestChain100Setup or a derived class like BuildChainTestingSetup are using mocktime by default due to the SetMockTime call in the TestChain100Setup ctor. This is confusing, because test cases using mocktime explicitly seem to imply that before they set the mocktime, real time was used. E.g. index_reorg_crash claimed in a comment to "Enable mock time". Fix this issue by adding a FakeNodeClock m_clock field to TestChain100Setup. Then, use the m_clock instead of explicit calls to SetMockTime or to a (now) shadowing local FakeNodeClock variable.
107 lines
4.0 KiB
C++
107 lines
4.0 KiB
C++
// Copyright (c) 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 <test/util/setup_common.h>
|
|
#include <test/util/time.h>
|
|
#include <validation.h>
|
|
#include <validationinterface.h>
|
|
|
|
#include <boost/test/unit_test.hpp>
|
|
|
|
using kernel::ChainstateRole;
|
|
|
|
// Taken from validation.cpp
|
|
static constexpr auto DATABASE_WRITE_INTERVAL_MIN{50min};
|
|
static constexpr auto DATABASE_WRITE_INTERVAL_MAX{70min};
|
|
|
|
BOOST_AUTO_TEST_SUITE(chainstate_write_tests)
|
|
|
|
BOOST_FIXTURE_TEST_CASE(chainstate_write_interval, TestingSetup)
|
|
{
|
|
struct TestSubscriber final : CValidationInterface {
|
|
bool m_did_flush{false};
|
|
void ChainStateFlushed(const ChainstateRole&, const CBlockLocator&) override
|
|
{
|
|
m_did_flush = true;
|
|
}
|
|
};
|
|
|
|
const auto sub{std::make_shared<TestSubscriber>()};
|
|
m_node.validation_signals->RegisterSharedValidationInterface(sub);
|
|
auto& chainstate{Assert(m_node.chainman)->ActiveChainstate()};
|
|
BlockValidationState state_dummy{};
|
|
FakeNodeClock clock{};
|
|
|
|
// The first periodic flush sets m_next_write and does not flush
|
|
chainstate.FlushStateToDisk(state_dummy, FlushStateMode::PERIODIC);
|
|
m_node.validation_signals->SyncWithValidationInterfaceQueue();
|
|
BOOST_CHECK(!sub->m_did_flush);
|
|
|
|
// The periodic flush interval is between 50 and 70 minutes (inclusive)
|
|
clock += DATABASE_WRITE_INTERVAL_MIN - 1min;
|
|
chainstate.FlushStateToDisk(state_dummy, FlushStateMode::PERIODIC);
|
|
m_node.validation_signals->SyncWithValidationInterfaceQueue();
|
|
BOOST_CHECK(!sub->m_did_flush);
|
|
|
|
clock += DATABASE_WRITE_INTERVAL_MAX;
|
|
chainstate.FlushStateToDisk(state_dummy, FlushStateMode::PERIODIC);
|
|
m_node.validation_signals->SyncWithValidationInterfaceQueue();
|
|
BOOST_CHECK(sub->m_did_flush);
|
|
}
|
|
|
|
// Test that we do PERIODIC flushes inside ActivateBestChain.
|
|
// This is necessary for reindex-chainstate to be able to periodically flush
|
|
// before reaching chain tip.
|
|
BOOST_FIXTURE_TEST_CASE(write_during_multiblock_activation, TestChain100Setup)
|
|
{
|
|
struct TestSubscriber final : CValidationInterface
|
|
{
|
|
const CBlockIndex* m_tip{nullptr};
|
|
const CBlockIndex* m_flushed_at_block{nullptr};
|
|
void ChainStateFlushed(const ChainstateRole&, const CBlockLocator&) override
|
|
{
|
|
m_flushed_at_block = m_tip;
|
|
}
|
|
void UpdatedBlockTip(const CBlockIndex* block_index, const CBlockIndex*, bool) override {
|
|
m_tip = block_index;
|
|
}
|
|
};
|
|
|
|
auto& chainstate{Assert(m_node.chainman)->ActiveChainstate()};
|
|
BlockValidationState state_dummy{};
|
|
|
|
// Pop two blocks from the tip
|
|
const CBlockIndex* tip{chainstate.m_chain.Tip()};
|
|
CBlockIndex* second_from_tip{tip->pprev};
|
|
|
|
{
|
|
LOCK2(m_node.chainman->GetMutex(), chainstate.MempoolMutex());
|
|
chainstate.DisconnectTip(state_dummy, nullptr);
|
|
chainstate.DisconnectTip(state_dummy, nullptr);
|
|
}
|
|
|
|
BOOST_CHECK_EQUAL(second_from_tip->pprev, chainstate.m_chain.Tip());
|
|
|
|
// Set m_next_write to current time
|
|
chainstate.FlushStateToDisk(state_dummy, FlushStateMode::FORCE_FLUSH);
|
|
m_node.validation_signals->SyncWithValidationInterfaceQueue();
|
|
// The periodic flush interval is between 50 and 70 minutes (inclusive)
|
|
// The next call to a PERIODIC write will flush
|
|
m_clock += DATABASE_WRITE_INTERVAL_MAX;
|
|
|
|
const auto sub{std::make_shared<TestSubscriber>()};
|
|
m_node.validation_signals->RegisterSharedValidationInterface(sub);
|
|
|
|
// ActivateBestChain back to tip
|
|
chainstate.ActivateBestChain(state_dummy, nullptr);
|
|
BOOST_CHECK_EQUAL(tip, chainstate.m_chain.Tip());
|
|
// Check that we flushed inside ActivateBestChain while we were at the
|
|
// second block from tip, since FlushStateToDisk is called with PERIODIC
|
|
// inside the outer loop.
|
|
m_node.validation_signals->SyncWithValidationInterfaceQueue();
|
|
BOOST_CHECK_EQUAL(sub->m_flushed_at_block, second_from_tip);
|
|
}
|
|
|
|
BOOST_AUTO_TEST_SUITE_END()
|