From 944f6b6e1d9a5dd7c20bba111799aa68b68e14d2 Mon Sep 17 00:00:00 2001 From: Guilherme Lawless Date: Mon, 2 Nov 2020 16:07:55 +0000 Subject: [PATCH] Translate some tests with UDP functionality to TCP (#2972) Test `network.last_contacted` was failing due to not setting `last_packet_received` in TCP channels, added this behavior though it's only used for tests at the moment. Does not touch tests specific to UDP: - network.send_insufficient_work_udp - network.replace_port - network.send_node_id_handshake - node.connect_after_junk - node_flags.disable_udp - telemetry.remove_peer_different_genesis_udp Some tests have UDP functionality that can also be removed in the future: - network.duplicate_detection - node.rep_remove --- nano/core_test/network.cpp | 64 +++++++++++---------------- nano/core_test/node.cpp | 78 ++++++++++++++------------------- nano/node/transport/tcp.cpp | 4 ++ nano/slow_test/node.cpp | 4 +- nano/test_common/CMakeLists.txt | 2 + nano/test_common/network.cpp | 43 ++++++++++++++++++ nano/test_common/network.hpp | 20 +++++++++ 7 files changed, 131 insertions(+), 84 deletions(-) create mode 100644 nano/test_common/network.cpp create mode 100644 nano/test_common/network.hpp diff --git a/nano/core_test/network.cpp b/nano/core_test/network.cpp index ee16b481..5ebb07d6 100644 --- a/nano/core_test/network.cpp +++ b/nano/core_test/network.cpp @@ -1,5 +1,6 @@ #include #include +#include #include #include @@ -111,12 +112,7 @@ TEST (network, send_node_id_handshake_tcp) auto initial_node1 (node1->stats.count (nano::stat::type::message, nano::stat::detail::node_id_handshake, nano::stat::dir::in)); auto initial_keepalive (node0->stats.count (nano::stat::type::message, nano::stat::detail::keepalive, nano::stat::dir::in)); std::weak_ptr node_w (node0); - node0->network.tcp_channels.start_tcp (node1->network.endpoint (), [node_w](std::shared_ptr channel_a) { - if (auto node_l = node_w.lock ()) - { - node_l->network.send_keepalive (channel_a); - } - }); + node0->network.tcp_channels.start_tcp (node1->network.endpoint (), nano::keepalive_tcp_callback (*node1)); ASSERT_EQ (0, node0->network.size ()); ASSERT_EQ (0, node1->network.size ()); ASSERT_TIMELY (10s, node0->stats.count (nano::stat::type::message, nano::stat::detail::node_id_handshake, nano::stat::dir::in) >= initial + 2); @@ -136,58 +132,46 @@ TEST (network, send_node_id_handshake_tcp) TEST (network, last_contacted) { - nano::system system; - nano::node_flags node_flags; - node_flags.disable_udp = false; - auto node0 = system.add_node (node_flags); + nano::system system (1); + auto node0 = system.nodes[0]; ASSERT_EQ (0, node0->network.size ()); - auto node1 (std::make_shared (system.io_ctx, nano::get_available_port (), nano::unique_path (), system.alarm, system.logging, system.work, node_flags)); + auto node1 (std::make_shared (system.io_ctx, nano::get_available_port (), nano::unique_path (), system.alarm, system.logging, system.work)); node1->start (); system.nodes.push_back (node1); - auto channel1 (std::make_shared (node1->network.udp_channels, nano::endpoint (boost::asio::ip::address_v6::loopback (), system.nodes.front ()->network.endpoint ().port ()), node1->network_params.protocol.protocol_version)); - node1->network.send_keepalive (channel1); - - // Wait until the handshake is complete - ASSERT_TIMELY (10s, node0->network.size () == 1); - ASSERT_EQ (node0->network.size (), 1); - - auto channel2 (node0->network.udp_channels.channel (nano::endpoint (boost::asio::ip::address_v6::loopback (), node1->network.endpoint ().port ()))); + auto channel1 = nano::establish_tcp (system, *node1, node0->network.endpoint ()); + ASSERT_NE (nullptr, channel1); + ASSERT_TIMELY (3s, node0->network.size () == 1); + auto channel2 = node0->network.tcp_channels.find_node_id (node1->node_id.pub); ASSERT_NE (nullptr, channel2); // Make sure last_contact gets updated on receiving a non-handshake message auto timestamp_before_keepalive = channel2->get_last_packet_received (); + auto keepalive_count = node0->stats.count (nano::stat::type::message, nano::stat::detail::keepalive, nano::stat::dir::in); node1->network.send_keepalive (channel1); - ASSERT_TIMELY (10s, node0->stats.count (nano::stat::type::message, nano::stat::detail::keepalive, nano::stat::dir::in) >= 2); + ASSERT_TIMELY (3s, node0->stats.count (nano::stat::type::message, nano::stat::detail::keepalive, nano::stat::dir::in) > keepalive_count); ASSERT_EQ (node0->network.size (), 1); auto timestamp_after_keepalive = channel2->get_last_packet_received (); ASSERT_GT (timestamp_after_keepalive, timestamp_before_keepalive); - - node1->stop (); } TEST (network, multi_keepalive) { - nano::system system; - nano::node_flags node_flags; - node_flags.disable_udp = false; - auto node0 = system.add_node (node_flags); + nano::system system (1); + auto node0 = system.nodes[0]; ASSERT_EQ (0, node0->network.size ()); - auto node1 (std::make_shared (system.io_ctx, nano::get_available_port (), nano::unique_path (), system.alarm, system.logging, system.work, node_flags)); + auto node1 (std::make_shared (system.io_ctx, nano::get_available_port (), nano::unique_path (), system.alarm, system.logging, system.work)); ASSERT_FALSE (node1->init_error ()); node1->start (); system.nodes.push_back (node1); ASSERT_EQ (0, node1->network.size ()); - auto channel1 (std::make_shared (node1->network.udp_channels, node0->network.endpoint (), node1->network_params.protocol.protocol_version)); - node1->network.send_keepalive (channel1); - ASSERT_EQ (0, node1->network.size ()); ASSERT_EQ (0, node0->network.size ()); - ASSERT_TIMELY (10s, node0->network.size () == 1); - auto node2 = system.add_node (node_flags); + node1->network.tcp_channels.start_tcp (node0->network.endpoint (), nano::keepalive_tcp_callback (*node1)); + ASSERT_TIMELY (10s, node0->network.size () == 1 && node0->stats.count (nano::stat::type::message, nano::stat::detail::keepalive) >= 1); + auto node2 (std::make_shared (system.io_ctx, nano::get_available_port (), nano::unique_path (), system.alarm, system.logging, system.work)); ASSERT_FALSE (node2->init_error ()); - auto channel2 (std::make_shared (node2->network.udp_channels, node0->network.endpoint (), node2->network_params.protocol.protocol_version)); - node2->network.send_keepalive (channel2); - ASSERT_TIMELY (10s, node1->network.size () == 2 && node0->network.size () == 2 && node2->network.size () == 2); - node1->stop (); - node2->stop (); + node2->start (); + system.nodes.push_back (node2); + node2->network.tcp_channels.start_tcp (node0->network.endpoint (), nano::keepalive_tcp_callback (*node2)); + ASSERT_TIMELY (10s, node1->network.size () == 2 && node0->network.size () == 2 && node2->network.size () == 2 && node0->stats.count (nano::stat::type::message, nano::stat::detail::keepalive) >= 2); } TEST (network, send_discarded_publish) @@ -911,7 +895,11 @@ TEST (network, duplicate_revert_publish) nano::uint128_t digest; ASSERT_FALSE (node.network.publish_filter.apply (bytes.data (), bytes.size (), &digest)); ASSERT_TRUE (node.network.publish_filter.apply (bytes.data (), bytes.size ())); - auto channel (std::make_shared (node.network.udp_channels, node.network.endpoint (), node.network_params.protocol.protocol_version)); + auto other_node (std::make_shared (system.io_ctx, nano::get_available_port (), nano::unique_path (), system.alarm, system.logging, system.work)); + other_node->start (); + system.nodes.push_back (other_node); + auto channel = nano::establish_tcp (system, *other_node, node.network.endpoint ()); + ASSERT_NE (nullptr, channel); ASSERT_EQ (0, publish.digest); node.network.process_message (publish, channel); ASSERT_TRUE (node.network.publish_filter.apply (bytes.data (), bytes.size ())); diff --git a/nano/core_test/node.cpp b/nano/core_test/node.cpp index 6780d783..6941762e 100644 --- a/nano/core_test/node.cpp +++ b/nano/core_test/node.cpp @@ -2,6 +2,7 @@ #include #include #include +#include #include #include @@ -240,10 +241,8 @@ TEST (node, quick_confirm) TEST (node, node_receive_quorum) { - nano::system system; - nano::node_flags node_flags; - node_flags.disable_udp = false; - auto & node1 = *system.add_node (node_flags); + nano::system system (1); + auto & node1 = *system.nodes[0]; nano::keypair key; nano::block_hash previous (node1.latest (nano::dev_genesis_key.pub)); system.wallet (0)->insert_adhoc (key.prv); @@ -263,12 +262,11 @@ TEST (node, node_receive_quorum) ASSERT_EQ (1, election->votes ().size ()); nano::system system2; - system2.add_node (node_flags); + system2.add_node (); system2.wallet (0)->insert_adhoc (nano::dev_genesis_key.prv); ASSERT_TRUE (node1.balance (key.pub).is_zero ()); - auto channel (std::make_shared (node1.network.udp_channels, system2.nodes[0]->network.endpoint (), node1.network_params.protocol.protocol_version)); - node1.network.send_keepalive (channel); + node1.network.tcp_channels.start_tcp (system2.nodes[0]->network.endpoint (), nano::keepalive_tcp_callback (node1)); while (node1.balance (key.pub).is_zero ()) { ASSERT_NO_ERROR (system.poll ()); @@ -284,7 +282,6 @@ TEST (node, auto_bootstrap) nano::node_flags node_flags; node_flags.disable_bootstrap_bulk_push_client = true; node_flags.disable_lazy_bootstrap = true; - node_flags.disable_udp = false; auto node0 = system.add_node (config, node_flags); nano::keypair key2; system.wallet (0)->insert_adhoc (nano::dev_genesis_key.prv); @@ -294,10 +291,9 @@ TEST (node, auto_bootstrap) ASSERT_TIMELY (10s, node0->balance (key2.pub) == node0->config.receive_minimum.number ()); auto node1 (std::make_shared (system.io_ctx, nano::get_available_port (), nano::unique_path (), system.alarm, system.logging, system.work, node_flags)); ASSERT_FALSE (node1->init_error ()); - auto channel (std::make_shared (node1->network.udp_channels, node0->network.endpoint (), node1->network_params.protocol.protocol_version)); - node1->network.send_keepalive (channel); node1->start (); system.nodes.push_back (node1); + ASSERT_NE (nullptr, nano::establish_tcp (system, *node1, node0->network.endpoint ())); ASSERT_TIMELY (10s, node1->bootstrap_initiator.in_progress ()); ASSERT_TIMELY (10s, node1->balance (key2.pub) == node0->config.receive_minimum.number ()); ASSERT_TIMELY (10s, !node1->bootstrap_initiator.in_progress ()); @@ -318,7 +314,6 @@ TEST (node, auto_bootstrap_reverse) nano::node_flags node_flags; node_flags.disable_bootstrap_bulk_push_client = true; node_flags.disable_lazy_bootstrap = true; - node_flags.disable_udp = false; auto node0 = system.add_node (config, node_flags); nano::keypair key2; system.wallet (0)->insert_adhoc (nano::dev_genesis_key.prv); @@ -326,12 +321,10 @@ TEST (node, auto_bootstrap_reverse) auto node1 (std::make_shared (system.io_ctx, nano::get_available_port (), nano::unique_path (), system.alarm, system.logging, system.work, node_flags)); ASSERT_FALSE (node1->init_error ()); ASSERT_NE (nullptr, system.wallet (0)->send_action (nano::dev_genesis_key.pub, key2.pub, node0->config.receive_minimum.number ())); - auto channel (std::make_shared (node0->network.udp_channels, node1->network.endpoint (), node0->network_params.protocol.protocol_version)); - node0->network.send_keepalive (channel); node1->start (); system.nodes.push_back (node1); + ASSERT_NE (nullptr, nano::establish_tcp (system, *node0, node1->network.endpoint ())); ASSERT_TIMELY (10s, node1->balance (key2.pub) == node0->config.receive_minimum.number ()); - node1->stop (); } TEST (node, receive_gap) @@ -1313,7 +1306,6 @@ TEST (node, fork_bootstrap_flip) nano::node_flags node_flags; node_flags.disable_bootstrap_bulk_push_client = true; node_flags.disable_lazy_bootstrap = true; - node_flags.disable_udp = false; auto & node1 (*system0.add_node (config0, node_flags)); nano::node_config config1 (nano::get_available_port (), system1.logging); config1.frontiers_confirmation = nano::frontiers_confirmation_mode::disabled; @@ -1346,14 +1338,6 @@ TEST (node, fork_bootstrap_flip) auto transaction (node2.store.tx_begin_read ()); ASSERT_TRUE (node2.store.block_exists (transaction, send2->hash ())); } - auto channel (std::make_shared (node1.network.udp_channels, node2.network.endpoint (), node2.network_params.protocol.protocol_version)); - node1.network.send_keepalive (channel); - system1.deadline_set (50s); - while (node2.network.empty ()) - { - ASSERT_NO_ERROR (system0.poll ()); - ASSERT_NO_ERROR (system1.poll ()); - } node2.bootstrap_initiator.bootstrap (node1.network.endpoint ()); auto again (true); system1.deadline_set (50s); @@ -1546,8 +1530,9 @@ TEST (node, fork_no_vote_quorum) nano::vectorstream stream (buffer); confirm.serialize (stream, false); } - nano::transport::channel_udp channel (node2.network.udp_channels, node3.network.endpoint (), node1.network_params.protocol.protocol_version); - channel.send_buffer (nano::shared_const_buffer (std::move (buffer))); + auto channel = node2.network.find_node_id (node3.node_id.pub); + ASSERT_NE (nullptr, channel); + channel->send_buffer (nano::shared_const_buffer (std::move (buffer))); ASSERT_TIMELY (10s, node3.stats.count (nano::stat::type::message, nano::stat::detail::confirm_ack, nano::stat::dir::in) >= 3); ASSERT_TRUE (node1.latest (nano::dev_genesis_key.pub) == send1.hash ()); ASSERT_TRUE (node2.latest (nano::dev_genesis_key.pub) == send1.hash ()); @@ -2105,8 +2090,17 @@ TEST (node, rep_list) TEST (node, rep_weight) { - nano::system system (1); - auto & node (*system.nodes[0]); + nano::system system; + auto add_node = [&system] { + auto node = std::make_shared (system.io_ctx, nano::get_available_port (), nano::unique_path (), system.alarm, system.logging, system.work); + node->start (); + system.nodes.push_back (node); + return node; + }; + auto & node = *add_node (); + auto & node1 = *add_node (); + auto & node2 = *add_node (); + auto & node3 = *add_node (); nano::genesis genesis; nano::keypair keypair1; nano::keypair keypair2; @@ -2160,33 +2154,29 @@ TEST (node, rep_weight) ASSERT_EQ (nano::process_result::progress, node.ledger.process (transaction, *block3).code); ASSERT_EQ (nano::process_result::progress, node.ledger.process (transaction, *block4).code); } - node.network.udp_channels.insert (nano::endpoint (boost::asio::ip::address_v6::loopback (), nano::get_available_port ()), 0); ASSERT_TRUE (node.rep_crawler.representatives (1).empty ()); - nano::endpoint endpoint0 (boost::asio::ip::address_v6::loopback (), nano::get_available_port ()); - nano::endpoint endpoint1 (boost::asio::ip::address_v6::loopback (), nano::get_available_port ()); - nano::endpoint endpoint2 (boost::asio::ip::address_v6::loopback (), nano::get_available_port ()); - std::shared_ptr channel0 (std::make_shared (node.network.udp_channels, endpoint0, node.network_params.protocol.protocol_version)); - std::shared_ptr channel1 (std::make_shared (node.network.udp_channels, endpoint1, node.network_params.protocol.protocol_version)); - std::shared_ptr channel2 (std::make_shared (node.network.udp_channels, endpoint2, node.network_params.protocol.protocol_version)); - node.network.udp_channels.insert (endpoint0, node.network_params.protocol.protocol_version); - node.network.udp_channels.insert (endpoint1, node.network_params.protocol.protocol_version); - node.network.udp_channels.insert (endpoint2, node.network_params.protocol.protocol_version); + std::shared_ptr channel1 = nano::establish_tcp (system, node, node1.network.endpoint ()); + ASSERT_NE (nullptr, channel1); + std::shared_ptr channel2 = nano::establish_tcp (system, node, node2.network.endpoint ()); + ASSERT_NE (nullptr, channel2); + std::shared_ptr channel3 = nano::establish_tcp (system, node, node3.network.endpoint ()); + ASSERT_NE (nullptr, channel3); auto vote0 = std::make_shared (nano::dev_genesis_key.pub, nano::dev_genesis_key.prv, 0, genesis.open); auto vote1 = std::make_shared (keypair1.pub, keypair1.prv, 0, genesis.open); auto vote2 = std::make_shared (keypair2.pub, keypair2.prv, 0, genesis.open); - node.rep_crawler.response (channel0, vote0); - node.rep_crawler.response (channel1, vote1); - node.rep_crawler.response (channel2, vote2); + node.rep_crawler.response (channel1, vote0); + node.rep_crawler.response (channel2, vote1); + node.rep_crawler.response (channel3, vote2); ASSERT_TIMELY (5s, node.rep_crawler.representative_count () == 2); // Make sure we get the rep with the most weight first auto reps (node.rep_crawler.representatives (1)); ASSERT_EQ (1, reps.size ()); ASSERT_EQ (node.balance (nano::dev_genesis_key.pub), reps[0].weight.number ()); ASSERT_EQ (nano::dev_genesis_key.pub, reps[0].account); - ASSERT_EQ (*channel0, reps[0].channel_ref ()); - ASSERT_TRUE (node.rep_crawler.is_pr (*channel0)); - ASSERT_FALSE (node.rep_crawler.is_pr (*channel1)); - ASSERT_TRUE (node.rep_crawler.is_pr (*channel2)); + ASSERT_EQ (*channel1, reps[0].channel_ref ()); + ASSERT_TRUE (node.rep_crawler.is_pr (*channel1)); + ASSERT_FALSE (node.rep_crawler.is_pr (*channel2)); + ASSERT_TRUE (node.rep_crawler.is_pr (*channel3)); } TEST (node, rep_remove) diff --git a/nano/node/transport/tcp.cpp b/nano/node/transport/tcp.cpp index 9a0351e1..44cf59f3 100644 --- a/nano/node/transport/tcp.cpp +++ b/nano/node/transport/tcp.cpp @@ -329,6 +329,10 @@ void nano::transport::tcp_channels::process_message (nano::message const & messa } } } + if (channel) + { + channel->set_last_packet_received (std::chrono::steady_clock::now ()); + } } } diff --git a/nano/slow_test/node.cpp b/nano/slow_test/node.cpp index b4d7fcbd..c7968805 100644 --- a/nano/slow_test/node.cpp +++ b/nano/slow_test/node.cpp @@ -3,6 +3,7 @@ #include #include #include +#include #include #include @@ -64,13 +65,12 @@ TEST (system, receive_while_synchronizing) nano::keypair key; auto node1 (std::make_shared (system.io_ctx, nano::get_available_port (), nano::unique_path (), system.alarm, system.logging, system.work)); ASSERT_FALSE (node1->init_error ()); - auto channel (std::make_shared (node1->network.udp_channels, system.nodes[0]->network.endpoint (), node1->network_params.protocol.protocol_version)); - node1->network.send_keepalive (channel); auto wallet (node1->wallets.create (1)); wallet->insert_adhoc (nano::dev_genesis_key.prv); // For voting ASSERT_EQ (key.pub, wallet->insert_adhoc (key.prv)); node1->start (); system.nodes.push_back (node1); + ASSERT_NE (nullptr, nano::establish_tcp (system, *node1, node->network.endpoint ())); system.alarm.add (std::chrono::steady_clock::now () + std::chrono::milliseconds (200), ([&system, &key]() { auto hash (system.wallet (0)->send_sync (nano::dev_genesis_key.pub, key.pub, system.nodes[0]->config.receive_minimum.number ())); auto transaction (system.nodes[0]->store.tx_begin_read ()); diff --git a/nano/test_common/CMakeLists.txt b/nano/test_common/CMakeLists.txt index afd7596c..058ce733 100644 --- a/nano/test_common/CMakeLists.txt +++ b/nano/test_common/CMakeLists.txt @@ -1,4 +1,6 @@ add_library (test_common + network.hpp + network.cpp telemetry.hpp telemetry.cpp testutil.hpp diff --git a/nano/test_common/network.cpp b/nano/test_common/network.cpp new file mode 100644 index 00000000..1b546c7c --- /dev/null +++ b/nano/test_common/network.cpp @@ -0,0 +1,43 @@ +#include +#include +#include +#include + +#include + +#include +#include + +std::shared_ptr nano::establish_tcp (nano::system & system, nano::node & node, nano::endpoint const & endpoint) +{ + using namespace std::chrono_literals; + debug_assert (node.network.endpoint () != endpoint && "Establishing TCP to self is not allowed"); + + std::shared_ptr result; + debug_assert (!node.flags.disable_tcp_realtime); + std::promise> promise; + auto callback = [&promise](std::shared_ptr channel_a) { promise.set_value (channel_a); }; + auto future = promise.get_future (); + node.network.tcp_channels.start_tcp (endpoint, callback); + auto error = system.poll_until_true (2s, [&future] { return future.wait_for (0s) == std::future_status::ready; }); + if (!error) + { + auto channel = future.get (); + EXPECT_NE (nullptr, channel); + if (channel) + { + result = node.network.tcp_channels.find_channel (channel->get_tcp_endpoint ()); + } + } + return result; +} + +std::function channel_a)> nano::keepalive_tcp_callback (nano::node & node_a) +{ + return [node_w = std::weak_ptr (node_a.shared ())](std::shared_ptr channel_a) { + if (auto node_l = node_w.lock ()) + { + node_l->network.send_keepalive (channel_a); + }; + }; +} diff --git a/nano/test_common/network.hpp b/nano/test_common/network.hpp new file mode 100644 index 00000000..fc9aaccc --- /dev/null +++ b/nano/test_common/network.hpp @@ -0,0 +1,20 @@ +#pragma once + +#include + +namespace nano +{ +class node; +class system; + +namespace transport +{ + class channel_tcp; +} + +/** Waits until a TCP connection is established and returns the TCP channel on success*/ +std::shared_ptr establish_tcp (nano::system &, nano::node &, nano::endpoint const &); + +/** Returns a callback to be used for start_tcp to send a keepalive*/ +std::function channel_a)> keepalive_tcp_callback (nano::node &); +}