Electroneum
epee_boosted_tcp_server.cpp
Go to the documentation of this file.
1 // Copyrights(c) 2017-2021, The Electroneum Project
2 // Copyrights(c) 2014-2019, The Monero Project
3 //
4 // All rights reserved.
5 //
6 // Redistribution and use in source and binary forms, with or without modification, are
7 // permitted provided that the following conditions are met:
8 //
9 // 1. Redistributions of source code must retain the above copyright notice, this list of
10 // conditions and the following disclaimer.
11 //
12 // 2. Redistributions in binary form must reproduce the above copyright notice, this list
13 // of conditions and the following disclaimer in the documentation and/or other
14 // materials provided with the distribution.
15 //
16 // 3. Neither the name of the copyright holder nor the names of its contributors may be
17 // used to endorse or promote products derived from this software without specific
18 // prior written permission.
19 //
20 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
21 // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
22 // MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
23 // THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
25 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
27 // STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
28 // THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 //
30 // Parts of this file are originally copyright (c) 2012-2013 The Cryptonote developers
31 
32 #include <boost/chrono/chrono.hpp>
33 #include <boost/thread/condition_variable.hpp>
34 #include <boost/thread/mutex.hpp>
35 
36 #include "gtest/gtest.h"
37 
38 #include "include_base_utils.h"
39 #include "string_tools.h"
41 
42 namespace
43 {
44  const uint32_t test_server_port = 5626;
45  const std::string test_server_host("127.0.0.1");
46 
47  struct test_connection_context : public epee::net_utils::connection_context_base
48  {
49  };
50 
51  struct test_protocol_handler_config
52  {
53  };
54 
55  struct test_protocol_handler
56  {
57  typedef test_connection_context connection_context;
58  typedef test_protocol_handler_config config_type;
59 
60  test_protocol_handler(epee::net_utils::i_service_endpoint* /*psnd_hndlr*/, config_type& /*config*/, connection_context& /*conn_context*/)
61  {
62  }
63 
64  void after_init_connection()
65  {
66  }
67 
68  void handle_qued_callback()
69  {
70  }
71 
72  bool release_protocol()
73  {
74  return true;
75  }
76 
77  bool handle_recv(const void* /*data*/, size_t /*size*/)
78  {
79  return false;
80  }
81  };
82 
84 }
85 
86 TEST(boosted_tcp_server, worker_threads_are_exception_resistant)
87 {
88  test_tcp_server srv(epee::net_utils::e_connection_type_RPC); // RPC disables network limit for unit tests
89  ASSERT_TRUE(srv.init_server(test_server_port, test_server_host));
90 
91  boost::mutex mtx;
92  boost::condition_variable cond;
93  int counter = 0;
94 
95  auto counter_incrementer = [&counter, &cond, &mtx]()
96  {
97  boost::unique_lock<boost::mutex> lock(mtx);
98  ++counter;
99  if (4 <= counter)
100  {
101  cond.notify_one();
102  }
103  };
104 
105  // 2 theads, but 4 exceptions
106  ASSERT_TRUE(srv.run_server(2, false));
107  ASSERT_TRUE(srv.async_call([&counter_incrementer]() { counter_incrementer(); throw std::runtime_error("test 1"); }));
108  ASSERT_TRUE(srv.async_call([&counter_incrementer]() { counter_incrementer(); throw std::string("test 2"); }));
109  ASSERT_TRUE(srv.async_call([&counter_incrementer]() { counter_incrementer(); throw "test 3"; }));
110  ASSERT_TRUE(srv.async_call([&counter_incrementer]() { counter_incrementer(); throw 4; }));
111 
112  {
113  boost::unique_lock<boost::mutex> lock(mtx);
114  ASSERT_NE(boost::cv_status::timeout, cond.wait_for(lock, boost::chrono::seconds(5)));
115  ASSERT_EQ(4, counter);
116  }
117 
118  // Check if threads are alive
119  counter = 0;
120  //auto counter_incrementer = [&counter]() { counter.fetch_add(1); epee::misc_utils::sleep_no_w(counter.load() * 10); };
121  ASSERT_TRUE(srv.async_call(counter_incrementer));
122  ASSERT_TRUE(srv.async_call(counter_incrementer));
123  ASSERT_TRUE(srv.async_call(counter_incrementer));
124  ASSERT_TRUE(srv.async_call(counter_incrementer));
125 
126  {
127  boost::unique_lock<boost::mutex> lock(mtx);
128  ASSERT_NE(boost::cv_status::timeout, cond.wait_for(lock, boost::chrono::seconds(5)));
129  ASSERT_EQ(4, counter);
130  }
131 
132  srv.send_stop_signal();
133  ASSERT_TRUE(srv.timed_wait_server_stop(5 * 1000));
134  ASSERT_TRUE(srv.deinit_server());
135 }
::std::string string
Definition: gtest-port.h:1097
epee::net_utils::boosted_tcp_server< test_levin_protocol_handler > test_tcp_server
#define ASSERT_EQ(val1, val2)
Definition: gtest.h:1956
unsigned int uint32_t
Definition: stdint.h:126
the connection templated-class for one peer connection
TEST(boosted_tcp_server, worker_threads_are_exception_resistant)
#define ASSERT_TRUE(condition)
Definition: gtest.h:1865
#define ASSERT_NE(val1, val2)
Definition: gtest.h:1960