From b6e65dd8b6a42c634e89540beb5ce7bcfb52f44a Mon Sep 17 00:00:00 2001 From: Guilherme Lawless Date: Fri, 13 Mar 2020 12:18:58 +0000 Subject: [PATCH] Fix node.aggressive_flooding (#2656) * Fix node.aggressive_flooding This test was resorting to bootstrapping as backup when it should fail instead. Now the test has bootstrap disabled, and the fix was to locally process the genesis chain in each node, ensuring all representatives will be able to connect the last blocks. With a sanitizer, less nodes are used because the repcrawler timings can remove one or more representatives during the test, making it fail. Disabling aggressive flooding in blockprocessor::process_live makes the test fail, as expected. Also did some cleanup using ASSERT_TIMELY. * Also decrease number of nodes and change timings under valgrind --- nano/core_test/node.cpp | 61 +++++++++++++++++++++++++---------------- 1 file changed, 37 insertions(+), 24 deletions(-) diff --git a/nano/core_test/node.cpp b/nano/core_test/node.cpp index ca2511b4..222307b2 100644 --- a/nano/core_test/node.cpp +++ b/nano/core_test/node.cpp @@ -3631,36 +3631,61 @@ TEST (node, bandwidth_limiter) } // Tests that local blocks are flooded to all principal representatives +// Sanitizers or running within valgrind use different timings and number of nodes TEST (node, aggressive_flooding) { nano::system system; nano::node_flags node_flags; node_flags.disable_request_loop = true; node_flags.disable_block_processor_republishing = true; + node_flags.disable_bootstrap_bulk_push_client = true; + node_flags.disable_bootstrap_bulk_pull_server = true; + node_flags.disable_bootstrap_listener = true; + node_flags.disable_lazy_bootstrap = true; + node_flags.disable_legacy_bootstrap = true; + node_flags.disable_wallet_bootstrap = true; auto & node1 (*system.add_node (node_flags)); auto & wallet1 (*system.wallet (0)); wallet1.insert_adhoc (nano::test_genesis_key.prv); - std::array, std::shared_ptr>, 5> nodes_wallets{}; + std::vector, std::shared_ptr>> nodes_wallets; + bool const sanitizer_or_valgrind (is_sanitizer_build || nano::running_within_valgrind ()); + nodes_wallets.resize (!sanitizer_or_valgrind ? 5 : 3); + std::generate (nodes_wallets.begin (), nodes_wallets.end (), [&system, node_flags]() { - nano::node_config node_config; - node_config.peering_port = nano::get_available_port (); + nano::node_config node_config (nano::get_available_port (), system.logging); auto node (system.add_node (node_config, node_flags)); return std::make_pair (node, system.wallet (system.nodes.size () - 1)); }); + + // This test is only valid if a non-aggressive flood would not reach every peer + ASSERT_TIMELY (5s, node1.network.size () == nodes_wallets.size ()); + ASSERT_LT (node1.network.fanout (), nodes_wallets.size ()); + + // Send a large amount to create a principal representative in each node auto large_amount = (nano::genesis_amount / 2) / nodes_wallets.size (); + std::vector> genesis_blocks; for (auto & node_wallet : nodes_wallets) { nano::keypair keypair; node_wallet.second->store.representative_set (node_wallet.first->wallets.tx_begin_write (), keypair.pub); node_wallet.second->insert_adhoc (keypair.prv); - wallet1.send_action (nano::test_genesis_key.pub, keypair.pub, large_amount); + auto block (wallet1.send_action (nano::test_genesis_key.pub, keypair.pub, large_amount)); + genesis_blocks.push_back (block); } - // Wait until all nodes have a representative - system.deadline_set (!is_sanitizer_build ? 5s : 15s); - while (node1.rep_crawler.principal_representatives ().size () != nodes_wallets.size ()) + + // Ensure all nodes have the full genesis chain + for (auto & node_wallet : nodes_wallets) { - ASSERT_NO_ERROR (system.poll ()); + for (auto const & block : genesis_blocks) + { + node_wallet.first->process (*block); + } + ASSERT_EQ (node1.latest (nano::test_genesis_key.pub), node_wallet.first->latest (nano::test_genesis_key.pub)); } + + // Wait until the main node sees all representatives + ASSERT_TIMELY (!sanitizer_or_valgrind ? 10s : 40s, node1.rep_crawler.principal_representatives ().size () == nodes_wallets.size ()); + // Generate blocks and ensure they are sent to all representatives nano::block_builder builder; std::shared_ptr block{}; @@ -3685,27 +3710,15 @@ TEST (node, aggressive_flooding) }); }; - system.deadline_set (!is_sanitizer_build ? 3s : 10s); - while (!all_have_block (block->hash ())) - { - ASSERT_NO_ERROR (system.poll ()); - } + ASSERT_TIMELY (!sanitizer_or_valgrind ? 5s : 25s, all_have_block (block->hash ())); // Do the same for a wallet block auto wallet_block = wallet1.send_sync (nano::test_genesis_key.pub, nano::test_genesis_key.pub, 10); - system.deadline_set (!is_sanitizer_build ? 3s : 10s); - while (!all_have_block (wallet_block)) - { - ASSERT_NO_ERROR (system.poll ()); - } + ASSERT_TIMELY (!sanitizer_or_valgrind ? 5s : 25s, all_have_block (wallet_block)); - // Wait until the main node has all blocks: genesis + (send+open) for each representative + 2 local blocks + // All blocks: genesis + (send+open) for each representative + 2 local blocks // The main node only sees all blocks if other nodes are flooding their PR's open block to all other PRs - system.deadline_set (5s); - while (node1.ledger.cache.block_count < 1 + 2 * nodes_wallets.size () + 2) - { - ASSERT_NO_ERROR (system.poll ()); - } + ASSERT_EQ (1 + 2 * nodes_wallets.size () + 2, node1.ledger.cache.block_count); } TEST (active_difficulty, recalculate_work)