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
This commit is contained in:
Guilherme Lawless 2020-11-02 16:07:55 +00:00 committed by GitHub
commit 944f6b6e1d
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 131 additions and 84 deletions

View file

@ -1,5 +1,6 @@
#include <nano/node/testing.hpp>
#include <nano/node/transport/udp.hpp>
#include <nano/test_common/network.hpp>
#include <nano/test_common/testutil.hpp>
#include <gtest/gtest.h>
@ -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<nano::node> node_w (node0);
node0->network.tcp_channels.start_tcp (node1->network.endpoint (), [node_w](std::shared_ptr<nano::transport::channel> 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<nano::node> (system.io_ctx, nano::get_available_port (), nano::unique_path (), system.alarm, system.logging, system.work, node_flags));
auto node1 (std::make_shared<nano::node> (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<nano::transport::channel_udp> (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<nano::node> (system.io_ctx, nano::get_available_port (), nano::unique_path (), system.alarm, system.logging, system.work, node_flags));
auto node1 (std::make_shared<nano::node> (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<nano::transport::channel_udp> (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<nano::node> (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<nano::transport::channel_udp> (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<nano::transport::channel_udp> (node.network.udp_channels, node.network.endpoint (), node.network_params.protocol.protocol_version));
auto other_node (std::make_shared<nano::node> (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 ()));

View file

@ -2,6 +2,7 @@
#include <nano/node/election.hpp>
#include <nano/node/testing.hpp>
#include <nano/node/transport/udp.hpp>
#include <nano/test_common/network.hpp>
#include <nano/test_common/testutil.hpp>
#include <gtest/gtest.h>
@ -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<nano::transport::channel_udp> (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<nano::node> (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<nano::transport::channel_udp> (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<nano::node> (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<nano::transport::channel_udp> (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<nano::transport::channel_udp> (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<nano::node> (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<nano::transport::channel> channel0 (std::make_shared<nano::transport::channel_udp> (node.network.udp_channels, endpoint0, node.network_params.protocol.protocol_version));
std::shared_ptr<nano::transport::channel> channel1 (std::make_shared<nano::transport::channel_udp> (node.network.udp_channels, endpoint1, node.network_params.protocol.protocol_version));
std::shared_ptr<nano::transport::channel> channel2 (std::make_shared<nano::transport::channel_udp> (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<nano::transport::channel> channel1 = nano::establish_tcp (system, node, node1.network.endpoint ());
ASSERT_NE (nullptr, channel1);
std::shared_ptr<nano::transport::channel> channel2 = nano::establish_tcp (system, node, node2.network.endpoint ());
ASSERT_NE (nullptr, channel2);
std::shared_ptr<nano::transport::channel> channel3 = nano::establish_tcp (system, node, node3.network.endpoint ());
ASSERT_NE (nullptr, channel3);
auto vote0 = std::make_shared<nano::vote> (nano::dev_genesis_key.pub, nano::dev_genesis_key.prv, 0, genesis.open);
auto vote1 = std::make_shared<nano::vote> (keypair1.pub, keypair1.prv, 0, genesis.open);
auto vote2 = std::make_shared<nano::vote> (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)

View file

@ -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 ());
}
}
}

View file

@ -3,6 +3,7 @@
#include <nano/node/election.hpp>
#include <nano/node/testing.hpp>
#include <nano/node/transport/udp.hpp>
#include <nano/test_common/network.hpp>
#include <nano/test_common/testutil.hpp>
#include <gtest/gtest.h>
@ -64,13 +65,12 @@ TEST (system, receive_while_synchronizing)
nano::keypair key;
auto node1 (std::make_shared<nano::node> (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<nano::transport::channel_udp> (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 ());

View file

@ -1,4 +1,6 @@
add_library (test_common
network.hpp
network.cpp
telemetry.hpp
telemetry.cpp
testutil.hpp

View file

@ -0,0 +1,43 @@
#include <nano/node/node.hpp>
#include <nano/node/testing.hpp>
#include <nano/test_common/network.hpp>
#include <nano/test_common/testutil.hpp>
#include <gtest/gtest.h>
#include <chrono>
#include <future>
std::shared_ptr<nano::transport::channel_tcp> 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<nano::transport::channel_tcp> result;
debug_assert (!node.flags.disable_tcp_realtime);
std::promise<std::shared_ptr<nano::transport::channel>> promise;
auto callback = [&promise](std::shared_ptr<nano::transport::channel> 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<void(std::shared_ptr<nano::transport::channel> channel_a)> nano::keepalive_tcp_callback (nano::node & node_a)
{
return [node_w = std::weak_ptr<nano::node> (node_a.shared ())](std::shared_ptr<nano::transport::channel> channel_a) {
if (auto node_l = node_w.lock ())
{
node_l->network.send_keepalive (channel_a);
};
};
}

View file

@ -0,0 +1,20 @@
#pragma once
#include <nano/node/common.hpp>
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<nano::transport::channel_tcp> establish_tcp (nano::system &, nano::node &, nano::endpoint const &);
/** Returns a callback to be used for start_tcp to send a keepalive*/
std::function<void(std::shared_ptr<nano::transport::channel> channel_a)> keepalive_tcp_callback (nano::node &);
}