Branch data Line data Source code
1 : : // Copyright (c) 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 <test/util/setup_common.h>
6 : : #include <validation.h>
7 : : #include <validationinterface.h>
8 : :
9 : : #include <boost/test/unit_test.hpp>
10 : :
11 : : // Taken from validation.cpp
12 : : static constexpr auto DATABASE_WRITE_INTERVAL_MIN{50min};
13 : : static constexpr auto DATABASE_WRITE_INTERVAL_MAX{70min};
14 : :
15 : : BOOST_AUTO_TEST_SUITE(chainstate_write_tests)
16 : :
17 [ + - + - : 7 : BOOST_FIXTURE_TEST_CASE(chainstate_write_interval, TestingSetup)
+ - + - -
+ + - + -
+ - + - +
- + - - +
+ - + - +
- + - + -
+ - - + +
- + - + -
+ - + - +
- + - - +
+ - + - +
- + - + -
+ - - + +
- ]
18 : : {
19 : 2 : struct TestSubscriber final : CValidationInterface {
20 : : bool m_did_flush{false};
21 : 1 : void ChainStateFlushed(ChainstateRole, const CBlockLocator&) override
22 : : {
23 : 1 : m_did_flush = true;
24 : 1 : }
25 : : };
26 : :
27 : 1 : const auto sub{std::make_shared<TestSubscriber>()};
28 [ + - + - ]: 2 : m_node.validation_signals->RegisterSharedValidationInterface(sub);
29 [ - + + - ]: 1 : auto& chainstate{Assert(m_node.chainman)->ActiveChainstate()};
30 [ + - ]: 1 : BlockValidationState state_dummy{};
31 : :
32 : : // The first periodic flush sets m_next_write and does not flush
33 [ + - ]: 1 : chainstate.FlushStateToDisk(state_dummy, FlushStateMode::PERIODIC);
34 [ + - ]: 1 : m_node.validation_signals->SyncWithValidationInterfaceQueue();
35 [ + - + - ]: 2 : BOOST_CHECK(!sub->m_did_flush);
36 : :
37 : : // The periodic flush interval is between 50 and 70 minutes (inclusive)
38 [ + - ]: 1 : SetMockTime(GetTime<std::chrono::minutes>() + DATABASE_WRITE_INTERVAL_MIN - 1min);
39 [ + - ]: 1 : chainstate.FlushStateToDisk(state_dummy, FlushStateMode::PERIODIC);
40 [ + - ]: 1 : m_node.validation_signals->SyncWithValidationInterfaceQueue();
41 [ + - + - ]: 2 : BOOST_CHECK(!sub->m_did_flush);
42 : :
43 [ + - ]: 1 : SetMockTime(GetTime<std::chrono::minutes>() + DATABASE_WRITE_INTERVAL_MAX);
44 [ + - ]: 1 : chainstate.FlushStateToDisk(state_dummy, FlushStateMode::PERIODIC);
45 [ + - ]: 1 : m_node.validation_signals->SyncWithValidationInterfaceQueue();
46 [ + - + - ]: 2 : BOOST_CHECK(sub->m_did_flush);
47 [ + - ]: 2 : }
48 : :
49 : : // Test that we do PERIODIC flushes inside ActivateBestChain.
50 : : // This is necessary for reindex-chainstate to be able to periodically flush
51 : : // before reaching chain tip.
52 [ + - + - : 7 : BOOST_FIXTURE_TEST_CASE(write_during_multiblock_activation, TestChain100Setup)
+ - + - -
+ + - + -
+ - + - +
- + - - +
+ - + - +
- + - + -
+ - - + +
- + - + -
+ - + - +
- + - - +
+ - + - +
- + - + -
+ - - + +
- ]
53 : : {
54 : 2 : struct TestSubscriber final : CValidationInterface
55 : : {
56 : : const CBlockIndex* m_tip{nullptr};
57 : : const CBlockIndex* m_flushed_at_block{nullptr};
58 : 1 : void ChainStateFlushed(ChainstateRole, const CBlockLocator&) override
59 : : {
60 : 1 : m_flushed_at_block = m_tip;
61 : 1 : }
62 : 2 : void UpdatedBlockTip(const CBlockIndex* block_index, const CBlockIndex*, bool) override {
63 : 2 : m_tip = block_index;
64 : 2 : }
65 : : };
66 : :
67 [ - + ]: 1 : auto& chainstate{Assert(m_node.chainman)->ActiveChainstate()};
68 [ - + ]: 1 : BlockValidationState state_dummy{};
69 : :
70 : : // Pop two blocks from the tip
71 [ - + ]: 1 : const CBlockIndex* tip{chainstate.m_chain.Tip()};
72 : 1 : CBlockIndex* second_from_tip{tip->pprev};
73 : :
74 : 1 : {
75 [ + - + - : 2 : LOCK2(m_node.chainman->GetMutex(), chainstate.MempoolMutex());
+ - ]
76 [ + - ]: 1 : chainstate.DisconnectTip(state_dummy, nullptr);
77 [ + - ]: 1 : chainstate.DisconnectTip(state_dummy, nullptr);
78 [ + - ]: 1 : }
79 : :
80 [ + - - + : 2 : BOOST_CHECK_EQUAL(second_from_tip->pprev, chainstate.m_chain.Tip());
+ - ]
81 : :
82 : : // Set m_next_write to current time
83 [ + - ]: 1 : chainstate.FlushStateToDisk(state_dummy, FlushStateMode::ALWAYS);
84 [ + - ]: 1 : m_node.validation_signals->SyncWithValidationInterfaceQueue();
85 : : // The periodic flush interval is between 50 and 70 minutes (inclusive)
86 : : // The next call to a PERIODIC write will flush
87 [ + - + - ]: 1 : SetMockTime(GetMockTime() + DATABASE_WRITE_INTERVAL_MAX);
88 : :
89 [ + - ]: 1 : const auto sub{std::make_shared<TestSubscriber>()};
90 [ + - + - ]: 2 : m_node.validation_signals->RegisterSharedValidationInterface(sub);
91 : :
92 : : // ActivateBestChain back to tip
93 [ + - ]: 1 : chainstate.ActivateBestChain(state_dummy, nullptr);
94 [ + - - + : 2 : BOOST_CHECK_EQUAL(tip, chainstate.m_chain.Tip());
+ - ]
95 : : // Check that we flushed inside ActivateBestChain while we were at the
96 : : // second block from tip, since FlushStateToDisk is called with PERIODIC
97 : : // inside the outer loop.
98 [ + - ]: 1 : m_node.validation_signals->SyncWithValidationInterfaceQueue();
99 [ + - + - : 1 : BOOST_CHECK_EQUAL(sub->m_flushed_at_block, second_from_tip);
+ - ]
100 : 2 : }
101 : :
102 : : BOOST_AUTO_TEST_SUITE_END()
|