Add coinstatsindex_unclean_shutdown test
This commit is contained in:
1 parent
eb6cc05da3
commit
691d45fdc8
4 files changed
+69
-7
No files matched your search
@@ -2,8 +2,10 @@
|
|||||||
// Distributed under the MIT software license, see the accompanying
|
// Distributed under the MIT software license, see the accompanying
|
||||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||||
|
|
||||||
|
#include <chainparams.h>
|
||||||
#include <index/coinstatsindex.h>
|
#include <index/coinstatsindex.h>
|
||||||
#include <test/util/setup_common.h>
|
#include <test/util/setup_common.h>
|
||||||
|
#include <test/util/validation.h>
|
||||||
#include <util/time.h>
|
#include <util/time.h>
|
||||||
#include <validation.h>
|
#include <validation.h>
|
||||||
|
|
||||||
@@ -16,6 +18,17 @@ using node::CoinStatsHashType;
|
|||||||
|
|
||||||
BOOST_AUTO_TEST_SUITE(coinstatsindex_tests)
|
BOOST_AUTO_TEST_SUITE(coinstatsindex_tests)
|
||||||
|
|
||||||
|
static void IndexWaitSynced(BaseIndex& index)
|
||||||
|
{
|
||||||
|
// Allow the CoinStatsIndex to catch up with the block index that is syncing
|
||||||
|
// in a background thread.
|
||||||
|
const auto timeout = GetTime<std::chrono::seconds>() + 120s;
|
||||||
|
while (!index.BlockUntilSyncedToCurrentChain()) {
|
||||||
|
BOOST_REQUIRE(timeout > GetTime<std::chrono::milliseconds>());
|
||||||
|
UninterruptibleSleep(100ms);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
BOOST_FIXTURE_TEST_CASE(coinstatsindex_initial_sync, TestChain100Setup)
|
BOOST_FIXTURE_TEST_CASE(coinstatsindex_initial_sync, TestChain100Setup)
|
||||||
{
|
{
|
||||||
CoinStatsIndex coin_stats_index{1 << 20, true};
|
CoinStatsIndex coin_stats_index{1 << 20, true};
|
||||||
@@ -36,13 +49,7 @@ BOOST_FIXTURE_TEST_CASE(coinstatsindex_initial_sync, TestChain100Setup)
|
|||||||
|
|
||||||
BOOST_REQUIRE(coin_stats_index.Start(m_node.chainman->ActiveChainstate()));
|
BOOST_REQUIRE(coin_stats_index.Start(m_node.chainman->ActiveChainstate()));
|
||||||
|
|
||||||
// Allow the CoinStatsIndex to catch up with the block index that is syncing
|
IndexWaitSynced(coin_stats_index);
|
||||||
// in a background thread.
|
|
||||||
const auto timeout = GetTime<std::chrono::seconds>() + 120s;
|
|
||||||
while (!coin_stats_index.BlockUntilSyncedToCurrentChain()) {
|
|
||||||
BOOST_REQUIRE(timeout > GetTime<std::chrono::milliseconds>());
|
|
||||||
UninterruptibleSleep(100ms);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check that CoinStatsIndex works for genesis block.
|
// Check that CoinStatsIndex works for genesis block.
|
||||||
const CBlockIndex* genesis_block_index;
|
const CBlockIndex* genesis_block_index;
|
||||||
@@ -78,4 +85,44 @@ BOOST_FIXTURE_TEST_CASE(coinstatsindex_initial_sync, TestChain100Setup)
|
|||||||
// Rest of shutdown sequence and destructors happen in ~TestingSetup()
|
// Rest of shutdown sequence and destructors happen in ~TestingSetup()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Test shutdown between BlockConnected and ChainStateFlushed notifications,
|
||||||
|
// make sure index is not corrupted and is able to reload.
|
||||||
|
BOOST_FIXTURE_TEST_CASE(coinstatsindex_unclean_shutdown, TestChain100Setup)
|
||||||
|
{
|
||||||
|
CChainState& chainstate = Assert(m_node.chainman)->ActiveChainstate();
|
||||||
|
const CChainParams& params = Params();
|
||||||
|
{
|
||||||
|
CoinStatsIndex index{1 << 20};
|
||||||
|
BOOST_REQUIRE(index.Start(chainstate));
|
||||||
|
IndexWaitSynced(index);
|
||||||
|
std::shared_ptr<const CBlock> new_block;
|
||||||
|
CBlockIndex* new_block_index = nullptr;
|
||||||
|
{
|
||||||
|
const CScript script_pub_key{CScript() << ToByteVector(coinbaseKey.GetPubKey()) << OP_CHECKSIG};
|
||||||
|
const CBlock block = this->CreateBlock({}, script_pub_key, chainstate);
|
||||||
|
|
||||||
|
new_block = std::make_shared<CBlock>(block);
|
||||||
|
|
||||||
|
LOCK(cs_main);
|
||||||
|
BlockValidationState state;
|
||||||
|
BOOST_CHECK(CheckBlock(block, state, params.GetConsensus()));
|
||||||
|
BOOST_CHECK(chainstate.AcceptBlock(new_block, state, &new_block_index, true, nullptr, nullptr));
|
||||||
|
CCoinsViewCache view(&chainstate.CoinsTip());
|
||||||
|
BOOST_CHECK(chainstate.ConnectBlock(block, state, new_block_index, view));
|
||||||
|
}
|
||||||
|
// Send block connected notification, then stop the index without
|
||||||
|
// sending a chainstate flushed notification. Prior to #24138, this
|
||||||
|
// would cause the index to be corrupted and fail to reload.
|
||||||
|
ValidationInterfaceTest::BlockConnected(index, new_block, new_block_index);
|
||||||
|
index.Stop();
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
CoinStatsIndex index{1 << 20};
|
||||||
|
// Make sure the index can be loaded.
|
||||||
|
BOOST_REQUIRE(index.Start(chainstate));
|
||||||
|
index.Stop();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
BOOST_AUTO_TEST_SUITE_END()
|
BOOST_AUTO_TEST_SUITE_END()
|
||||||
@@ -7,6 +7,7 @@
|
|||||||
#include <util/check.h>
|
#include <util/check.h>
|
||||||
#include <util/time.h>
|
#include <util/time.h>
|
||||||
#include <validation.h>
|
#include <validation.h>
|
||||||
|
#include <validationinterface.h>
|
||||||
|
|
||||||
void TestChainState::ResetIbd()
|
void TestChainState::ResetIbd()
|
||||||
{
|
{
|
||||||
@@ -20,3 +21,8 @@ void TestChainState::JumpOutOfIbd()
|
|||||||
m_cached_finished_ibd = true;
|
m_cached_finished_ibd = true;
|
||||||
Assert(!IsInitialBlockDownload());
|
Assert(!IsInitialBlockDownload());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ValidationInterfaceTest::BlockConnected(CValidationInterface& obj, const std::shared_ptr<const CBlock>& block, const CBlockIndex* pindex)
|
||||||
|
{
|
||||||
|
obj.BlockConnected(block, pindex);
|
||||||
|
}
|
||||||
@@ -7,6 +7,8 @@
|
|||||||
|
|
||||||
#include <validation.h>
|
#include <validation.h>
|
||||||
|
|
||||||
|
class CValidationInterface;
|
||||||
|
|
||||||
struct TestChainState : public CChainState {
|
struct TestChainState : public CChainState {
|
||||||
/** Reset the ibd cache to its initial state */
|
/** Reset the ibd cache to its initial state */
|
||||||
void ResetIbd();
|
void ResetIbd();
|
||||||
@@ -14,4 +16,10 @@ struct TestChainState : public CChainState {
|
|||||||
void JumpOutOfIbd();
|
void JumpOutOfIbd();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class ValidationInterfaceTest
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
static void BlockConnected(CValidationInterface& obj, const std::shared_ptr<const CBlock>& block, const CBlockIndex* pindex);
|
||||||
|
};
|
||||||
|
|
||||||
#endif // BITCOIN_TEST_UTIL_VALIDATION_H
|
#endif // BITCOIN_TEST_UTIL_VALIDATION_H
|
||||||
@@ -174,6 +174,7 @@ protected:
|
|||||||
* has been received and connected to the headers tree, though not validated yet */
|
* has been received and connected to the headers tree, though not validated yet */
|
||||||
virtual void NewPoWValidBlock(const CBlockIndex *pindex, const std::shared_ptr<const CBlock>& block) {};
|
virtual void NewPoWValidBlock(const CBlockIndex *pindex, const std::shared_ptr<const CBlock>& block) {};
|
||||||
friend class CMainSignals;
|
friend class CMainSignals;
|
||||||
|
friend class ValidationInterfaceTest;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct MainSignalsInstance;
|
struct MainSignalsInstance;
|
||||||
|
|||||||
Reference in new issue
Block a user