diff options
Diffstat (limited to 'tests/unit_tests/epee_boosted_tcp_server.cpp')
-rw-r--r-- | tests/unit_tests/epee_boosted_tcp_server.cpp | 109 |
1 files changed, 109 insertions, 0 deletions
diff --git a/tests/unit_tests/epee_boosted_tcp_server.cpp b/tests/unit_tests/epee_boosted_tcp_server.cpp new file mode 100644 index 000000000..1e606163d --- /dev/null +++ b/tests/unit_tests/epee_boosted_tcp_server.cpp @@ -0,0 +1,109 @@ +// Copyright (c) 2012-2013 The Cryptonote developers +// Distributed under the MIT/X11 software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#include <condition_variable> +#include <chrono> +#include <mutex> +#include <thread> + +#include "gtest/gtest.h" + +#include "include_base_utils.h" +#include "string_tools.h" +#include "net/abstract_tcp_server2.h" + +namespace +{ + const uint32_t test_server_port = 5626; + const std::string test_server_host("127.0.0.1"); + + struct test_connection_context : public epee::net_utils::connection_context_base + { + }; + + struct test_protocol_handler_config + { + }; + + struct test_protocol_handler + { + typedef test_connection_context connection_context; + typedef test_protocol_handler_config config_type; + + test_protocol_handler(epee::net_utils::i_service_endpoint* /*psnd_hndlr*/, config_type& /*config*/, connection_context& /*conn_context*/) + { + } + + void after_init_connection() + { + } + + void handle_qued_callback() + { + } + + bool release_protocol() + { + return true; + } + + bool handle_recv(const void* /*data*/, size_t /*size*/) + { + return false; + } + }; + + typedef epee::net_utils::boosted_tcp_server<test_protocol_handler> test_tcp_server; +} + +TEST(boosted_tcp_server, worker_threads_are_exception_resistant) +{ + test_tcp_server srv; + ASSERT_TRUE(srv.init_server(test_server_port, test_server_host)); + + std::mutex mtx; + std::condition_variable cond; + int counter = 0; + + auto counter_incrementer = [&counter, &cond, &mtx]() + { + std::unique_lock<std::mutex> lock(mtx); + ++counter; + if (4 <= counter) + { + cond.notify_one(); + } + }; + + // 2 theads, but 4 exceptions + ASSERT_TRUE(srv.run_server(2, false)); + ASSERT_TRUE(srv.async_call([&counter_incrementer]() { counter_incrementer(); throw std::runtime_error("test 1"); })); + ASSERT_TRUE(srv.async_call([&counter_incrementer]() { counter_incrementer(); throw std::string("test 2"); })); + ASSERT_TRUE(srv.async_call([&counter_incrementer]() { counter_incrementer(); throw "test 3"; })); + ASSERT_TRUE(srv.async_call([&counter_incrementer]() { counter_incrementer(); throw 4; })); + + { + std::unique_lock<std::mutex> lock(mtx); + ASSERT_NE(std::cv_status::timeout, cond.wait_for(lock, std::chrono::seconds(5))); + ASSERT_EQ(4, counter); + } + + // Check if threads are alive + counter = 0; + //auto counter_incrementer = [&counter]() { counter.fetch_add(1); epee::misc_utils::sleep_no_w(counter.load() * 10); }; + ASSERT_TRUE(srv.async_call(counter_incrementer)); + ASSERT_TRUE(srv.async_call(counter_incrementer)); + ASSERT_TRUE(srv.async_call(counter_incrementer)); + ASSERT_TRUE(srv.async_call(counter_incrementer)); + + { + std::unique_lock<std::mutex> lock(mtx); + ASSERT_NE(std::cv_status::timeout, cond.wait_for(lock, std::chrono::seconds(5))); + ASSERT_EQ(4, counter); + } + + srv.send_stop_signal(); + ASSERT_TRUE(srv.timed_wait_server_stop(5 * 1000)); + ASSERT_TRUE(srv.deinit_server()); +} |