dncurrency/nano/core_test/socket.cpp
Wesley Shillingford f8158fc03c
Remove compiler warnings (incl from third party headers) (#2072)
* Remove compiler warnings

* Fix new warnings in test

* Remove new msvc warnings
2019-07-12 17:28:21 +01:00

140 lines
4.6 KiB
C++

#include <nano/core_test/testutil.hpp>
#include <nano/node/socket.hpp>
#include <nano/node/testing.hpp>
#include <gtest/gtest.h>
#include <boost/thread.hpp>
using namespace std::chrono_literals;
TEST (socket, concurrent_writes)
{
nano::inactive_node inactivenode;
auto node = inactivenode.node;
// This gives more realistic execution than using system#poll, allowing writes to
// queue up and drain concurrently.
nano::thread_runner runner (node->io_ctx, 1);
constexpr size_t max_connections = 4;
constexpr size_t client_count = max_connections;
constexpr size_t message_count = 4;
constexpr size_t total_message_count = client_count * message_count;
// We're expecting client_count*4 messages
nano::util::counted_completion read_count_completion (total_message_count);
std::function<void(std::shared_ptr<nano::socket>)> reader = [&read_count_completion, &total_message_count, &reader](std::shared_ptr<nano::socket> socket_a) {
auto buff (std::make_shared<std::vector<uint8_t>> ());
buff->resize (1);
#ifndef _WIN32
#pragma GCC diagnostic push
#if defined(__has_warning)
#if __has_warning("-Wunused-lambda-capture")
/** total_message_count is constexpr and a capture isn't needed. However, removing it fails to compile on VS2017 due to a known compiler bug. */
#pragma GCC diagnostic ignored "-Wunused-lambda-capture"
#endif
#endif
#endif
socket_a->async_read (buff, 1, [&read_count_completion, &reader, &total_message_count, socket_a, buff](boost::system::error_code const & ec, size_t size_a) {
if (!ec)
{
if (read_count_completion.increment () < total_message_count)
{
reader (socket_a);
}
}
else if (ec != boost::asio::error::eof)
{
std::cerr << "async_read: " << ec.message () << std::endl;
}
});
#ifndef _WIN32
#pragma GCC diagnostic pop
#endif
};
boost::asio::ip::tcp::endpoint endpoint (boost::asio::ip::address_v4::any (), 25000);
auto server_socket (std::make_shared<nano::server_socket> (node, endpoint, max_connections, nano::socket::concurrency::multi_writer));
boost::system::error_code ec;
server_socket->start (ec);
ASSERT_FALSE (ec);
std::vector<std::shared_ptr<nano::socket>> connections;
// On every new connection, start reading data
server_socket->on_connection ([&connections, &reader](std::shared_ptr<nano::socket> new_connection, boost::system::error_code const & ec_a) {
if (ec_a)
{
std::cerr << "on_connection: " << ec_a.message () << std::endl;
}
else
{
connections.push_back (new_connection);
reader (new_connection);
}
// Keep accepting connections
return true;
});
nano::util::counted_completion connection_count_completion (client_count);
std::vector<std::shared_ptr<nano::socket>> clients;
for (unsigned i = 0; i < client_count; i++)
{
auto client (std::make_shared<nano::socket> (node, boost::none, nano::socket::concurrency::multi_writer));
clients.push_back (client);
client->async_connect (boost::asio::ip::tcp::endpoint (boost::asio::ip::address_v4::loopback (), 25000),
[&connection_count_completion](boost::system::error_code const & ec_a) {
if (ec_a)
{
std::cerr << "async_connect: " << ec_a.message () << std::endl;
}
else
{
connection_count_completion.increment ();
}
});
}
ASSERT_FALSE (connection_count_completion.await_count_for (10s));
// Execute overlapping writes from multiple threads
auto client (clients[0]);
std::vector<std::thread> client_threads;
for (int i = 0; i < client_count; i++)
{
#ifndef _WIN32
#pragma GCC diagnostic push
#if defined(__has_warning)
#if __has_warning("-Wunused-lambda-capture")
/** total_message_count is constexpr and a capture isn't needed. However, removing it fails to compile on VS2017 due to a known compiler bug. */
#pragma GCC diagnostic ignored "-Wunused-lambda-capture"
#endif
#endif
#endif
client_threads.emplace_back ([&client, &message_count]() {
for (int i = 0; i < message_count; i++)
{
auto buff (std::make_shared<std::vector<uint8_t>> ());
buff->push_back ('A' + i);
client->async_write (buff);
}
});
#ifndef _WIN32
#pragma GCC diagnostic pop
#endif
}
ASSERT_FALSE (read_count_completion.await_count_for (10s));
node->stop ();
runner.stop_event_processing ();
runner.join ();
ASSERT_EQ (node->stats.count (nano::stat::type::tcp, nano::stat::detail::tcp_accept_success, nano::stat::dir::in), client_count);
// We may exhaust max connections and have some tcp accept failures, but no more than the client count
ASSERT_LT (node->stats.count (nano::stat::type::tcp, nano::stat::detail::tcp_accept_failure, nano::stat::dir::in), client_count);
for (auto & t : client_threads)
{
t.join ();
}
}