From f9d7c76a6824e92f3432a104fc4f29454660af05 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Piotr=20Wo=CC=81jcik?= <3044353+pwojcikdev@users.noreply.github.com> Date: Tue, 7 Jan 2025 16:15:27 +0100 Subject: [PATCH] Tests --- nano/core_test/bootstrap.cpp | 56 +++++++++++++++--- nano/node/node.cpp | 10 ++++ nano/node/node.hpp | 4 +- nano/rpc_test/rpc.cpp | 108 +++++++++++++++++++++++++++++++++++ 4 files changed, 168 insertions(+), 10 deletions(-) diff --git a/nano/core_test/bootstrap.cpp b/nano/core_test/bootstrap.cpp index 8d866031b0..b2c17a6744 100644 --- a/nano/core_test/bootstrap.cpp +++ b/nano/core_test/bootstrap.cpp @@ -270,18 +270,12 @@ TEST (bootstrap, trace_base) .sign (key.prv, key.pub) .work (*system.work.generate (key.pub)) .build (); - // std::cerr << "Genesis key: " << nano::dev::genesis_key.pub.to_account () << std::endl; - // std::cerr << "Key: " << key.pub.to_account () << std::endl; - // std::cerr << "Genesis: " << nano::dev::genesis->hash ().to_string () << std::endl; - // std::cerr << "send1: " << send1->hash ().to_string () << std::endl; - // std::cerr << "receive1: " << receive1->hash ().to_string () << std::endl; auto & node1 = *system.add_node (); - // std::cerr << "--------------- Start ---------------\n"; + ASSERT_EQ (nano::block_status::progress, node0.process (send1)); ASSERT_EQ (nano::block_status::progress, node0.process (receive1)); + ASSERT_EQ (node1.ledger.any.receivable_end (), node1.ledger.any.receivable_upper_bound (node1.ledger.tx_begin_read (), key.pub, 0)); - // std::cerr << "node0: " << node0.network.endpoint () << std::endl; - // std::cerr << "node1: " << node1.network.endpoint () << std::endl; ASSERT_TIMELY (10s, node1.block (receive1->hash ()) != nullptr); } @@ -573,4 +567,48 @@ TEST (bootstrap, frontier_scan_cannot_prioritize) })); } -// TODO: Test bootstrap.reset () \ No newline at end of file +/* + * Tests that bootstrap.reset() properly recovers when called during an ongoing bootstrap + * This mimics node restart behaviour so this also ensures that the bootstrap is able to recover from a node restart + */ +TEST (bootstrap, reset) +{ + nano::test::system system; + + // Test configuration + int const chain_count = 10; + int const blocks_per_chain = 5; + + nano::node_config config; + // Disable election activation + config.backlog_scan.enable = false; + config.priority_scheduler.enable = false; + config.optimistic_scheduler.enable = false; + config.hinted_scheduler.enable = false; + // Add request limits to slow down bootstrap + config.bootstrap.rate_limit = 30; + + // Start server node + auto & node_server = *system.add_node (config); + + // Create multiple chains of blocks + auto chains = nano::test::setup_chains (system, node_server, chain_count, blocks_per_chain); + + int const total_blocks = node_server.block_count (); + int const halfway_blocks = total_blocks / 2; + + // Start client node and begin bootstrap + auto & node_client = *system.add_node (config); + ASSERT_LE (node_client.block_count (), halfway_blocks); // Should not be synced yet + + // Wait until bootstrap has started and processed some blocks but not all + // Target approximately halfway through + ASSERT_TIMELY (15s, node_client.block_count () >= halfway_blocks); + ASSERT_LT (node_client.block_count (), total_blocks); + + // Reset bootstrap halfway through the process + node_client.bootstrap.reset (); + + // Bootstrap should automatically restart and eventually sync all blocks + ASSERT_TIMELY_EQ (30s, node_client.block_count (), total_blocks); +} \ No newline at end of file diff --git a/nano/node/node.cpp b/nano/node/node.cpp index b6838515fa..96847d1c37 100644 --- a/nano/node/node.cpp +++ b/nano/node/node.cpp @@ -1105,6 +1105,16 @@ void nano::node::bootstrap_block (const nano::block_hash & hash) } } +uint64_t nano::node::block_count () const +{ + return ledger.block_count (); +} + +uint64_t nano::node::cemented_count () const +{ + return ledger.cemented_count (); +} + nano::account nano::node::get_node_id () const { return node_id.pub; diff --git a/nano/node/node.hpp b/nano/node/node.hpp index fc6581829a..6b58ff1548 100644 --- a/nano/node/node.hpp +++ b/nano/node/node.hpp @@ -77,11 +77,13 @@ class node final : public std::enable_shared_from_this void add_initial_peers (); void start_election (std::shared_ptr const & block); bool block_confirmed (nano::block_hash const &); - // This function may spuriously return false after returning true until the database transaction is refreshed bool block_confirmed_or_being_confirmed (nano::secure::transaction const &, nano::block_hash const &); bool block_confirmed_or_being_confirmed (nano::block_hash const &); + uint64_t block_count () const; + uint64_t cemented_count () const; + void do_rpc_callback (boost::asio::ip::tcp::resolver::iterator i_a, std::string const &, uint16_t, std::shared_ptr const &, std::shared_ptr const &, std::shared_ptr const &); bool online () const; bool init_error () const; diff --git a/nano/rpc_test/rpc.cpp b/nano/rpc_test/rpc.cpp index 82c9837d5b..f3a2e50644 100644 --- a/nano/rpc_test/rpc.cpp +++ b/nano/rpc_test/rpc.cpp @@ -6876,3 +6876,111 @@ TEST (rpc, election_statistics) ASSERT_LT (response.get ("max_election_age"), 5000); ASSERT_LT (response.get ("average_election_age"), 5000); } + +TEST (rpc, bootstrap_priorities) +{ + nano::test::system system; + + // Test configuration + int const chain_count = 5; + int const blocks_per_chain = 2; + + nano::node_config config; + config.bootstrap.rate_limit = 10; // Add request limits to slow down bootstrap + + // Start server node + auto & node_server = *system.add_node (config); + + // Create multiple chains of blocks + auto chains = nano::test::setup_chains (system, node_server, chain_count, blocks_per_chain); + + int const total_blocks = node_server.block_count (); + int const halfway_blocks = total_blocks / 2; + + // Start client node to observe bootstrap + auto node = add_ipc_enabled_node (system); + auto const rpc_ctx = add_rpc (system, node); + + // Wait until bootstrap has started and processed some blocks but not all + // Target approximately halfway through + ASSERT_TIMELY (15s, node->block_count () >= halfway_blocks); + + boost::property_tree::ptree request; + request.put ("action", "bootstrap_priorities"); + auto response = wait_response (system, rpc_ctx, request); + + ASSERT_TRUE (response.get_child_optional ("priorities")); + ASSERT_TRUE (response.get_child_optional ("blocking")); + ASSERT_FALSE (response.get_child_optional ("priorities").value ().empty ()); +} + +TEST (rpc, bootstrap_reset) +{ + nano::test::system system; + + // Test configuration + int const chain_count = 5; + int const blocks_per_chain = 2; + + nano::node_config config; + config.bootstrap.rate_limit = 10; // Add request limits to slow down bootstrap + + // Start server node + auto & node_server = *system.add_node (config); + + // Create multiple chains of blocks + auto chains = nano::test::setup_chains (system, node_server, chain_count, blocks_per_chain); + + int const total_blocks = node_server.block_count (); + int const halfway_blocks = total_blocks / 2; + + // Start client node to observe bootstrap + auto node = add_ipc_enabled_node (system); + auto const rpc_ctx = add_rpc (system, node); + + // Wait until bootstrap has started and processed some blocks but not all + // Target approximately halfway through + ASSERT_TIMELY (15s, node->block_count () >= halfway_blocks); + + boost::property_tree::ptree request; + request.put ("action", "bootstrap_reset"); + auto response = wait_response (system, rpc_ctx, request); + + ASSERT_TRUE (response.get ("success").empty ()); +} + +TEST (rpc, bootstrap_status) +{ + nano::test::system system; + + // Test configuration + int const chain_count = 5; + int const blocks_per_chain = 2; + + nano::node_config config; + config.bootstrap.rate_limit = 10; // Add request limits to slow down bootstrap + + // Start server node + auto & node_server = *system.add_node (config); + + // Create multiple chains of blocks + auto chains = nano::test::setup_chains (system, node_server, chain_count, blocks_per_chain); + + int const total_blocks = node_server.block_count (); + int const halfway_blocks = total_blocks / 2; + + // Start client node to observe bootstrap + auto node = add_ipc_enabled_node (system); + auto const rpc_ctx = add_rpc (system, node); + + // Wait until bootstrap has started and processed some blocks but not all + // Target approximately halfway through + ASSERT_TIMELY (15s, node->block_count () >= halfway_blocks); + + boost::property_tree::ptree request; + request.put ("action", "bootstrap_status"); + auto response = wait_response (system, rpc_ctx, request); + + ASSERT_GT (response.get ("priorities"), 0); + ASSERT_EQ (response.get ("blocking"), 0); +} \ No newline at end of file