32 #include <boost/thread/mutex.hpp> 33 #include <boost/thread/thread.hpp> 35 #include "gtest/gtest.h" 54 test_levin_commands_handler()
62 m_invoke_counter.inc();
63 boost::unique_lock<boost::mutex> lock(m_mutex);
64 m_last_command = command;
66 buff_out = m_invoke_out_buf;
72 m_notify_counter.inc();
73 boost::unique_lock<boost::mutex> lock(m_mutex);
74 m_last_command = command;
81 m_callback_counter.inc();
87 m_new_connection_counter.inc();
93 m_close_connection_counter.inc();
97 size_t invoke_counter()
const {
return m_invoke_counter.get(); }
98 size_t notify_counter()
const {
return m_notify_counter.get(); }
99 size_t callback_counter()
const {
return m_callback_counter.get(); }
100 size_t new_connection_counter()
const {
return m_new_connection_counter.get(); }
101 size_t close_connection_counter()
const {
return m_close_connection_counter.get(); }
103 int return_code()
const {
return m_return_code; }
104 void return_code(
int v) { m_return_code = v; }
106 const std::string& invoke_out_buf()
const {
return m_invoke_out_buf; }
107 void invoke_out_buf(
const std::string& v) { m_invoke_out_buf = v; }
109 int last_command()
const {
return m_last_command; }
110 const std::string& last_in_buf()
const {
return m_last_in_buf; }
119 boost::mutex m_mutex;
132 : m_io_service(io_service)
133 , m_protocol_handler(this, protocol_config, m_context)
134 , m_send_return(
true)
140 ASSERT_TRUE(m_protocol_handler.after_init_connection());
144 virtual bool do_send(
const void* ptr,
size_t cb)
147 m_send_counter.inc();
148 boost::unique_lock<boost::mutex> lock(m_mutex);
149 m_last_send_data.append(reinterpret_cast<const char*>(ptr), cb);
150 return m_send_return;
153 virtual bool close() {
return true; }
154 virtual bool send_done() {
return true; }
155 virtual bool call_run_once_service_io() { std::cout <<
"test_connection::call_run_once_service_io()" << std::endl;
return true; }
156 virtual bool request_callback() { std::cout <<
"test_connection::request_callback()" << std::endl;
return true; }
157 virtual boost::asio::io_service&
get_io_service() { std::cout <<
"test_connection::get_io_service()" << std::endl;
return m_io_service; }
158 virtual bool add_ref() { std::cout <<
"test_connection::add_ref()" << std::endl;
return true; }
159 virtual bool release() { std::cout <<
"test_connection::release()" << std::endl;
return true; }
161 size_t send_counter()
const {
return m_send_counter.get(); }
163 const std::string& last_send_data()
const {
return m_last_send_data; }
164 void reset_last_send_data() { boost::unique_lock<boost::mutex> lock(m_mutex); m_last_send_data.clear(); }
166 bool send_return()
const {
return m_send_return; }
167 void send_return(
bool v) { m_send_return = v; }
173 boost::asio::io_service& m_io_service;
174 test_levin_connection_context m_context;
177 boost::mutex m_mutex;
187 const static uint64_t invoke_timeout = 5 * 1000;
188 const static size_t max_packet_size = 10 * 1024 * 1024;
190 typedef std::unique_ptr<test_connection> test_connection_ptr;
192 async_protocol_handler_test():
193 m_pcommands_handler(new test_levin_commands_handler()),
194 m_commands_handler(*m_pcommands_handler)
197 m_handler_config.m_invoke_timeout = invoke_timeout;
198 m_handler_config.m_max_packet_size = max_packet_size;
206 test_connection_ptr create_connection(
bool start =
true)
208 test_connection_ptr conn(
new test_connection(m_io_service, m_handler_config));
217 boost::asio::io_service m_io_service;
219 test_levin_commands_handler *m_pcommands_handler, &m_commands_handler;
222 class positive_test_connection_to_levin_protocol_handler_calls :
public async_protocol_handler_test
226 class test_levin_protocol_handler__hanle_recv_with_invalid_data :
public async_protocol_handler_test
229 static const int expected_command = 5615871;
230 static const int expected_return_code = 782546;
232 test_levin_protocol_handler__hanle_recv_with_invalid_data()
233 : m_expected_invoke_out_buf(512,
'y')
239 async_protocol_handler_test::SetUp();
241 m_conn = create_connection();
243 m_in_data.assign(256,
't');
246 m_req_head.m_cb = m_in_data.size();
247 m_req_head.m_have_to_return_data =
true;
248 m_req_head.m_command = expected_command;
249 m_req_head.m_return_code =
LEVIN_OK;
253 m_commands_handler.return_code(expected_return_code);
254 m_commands_handler.invoke_out_buf(m_expected_invoke_out_buf);
260 m_buf.assign(reinterpret_cast<const char*>(&m_req_head),
sizeof(m_req_head));
265 test_connection_ptr m_conn;
273 TEST_F(positive_test_connection_to_levin_protocol_handler_calls, new_handler_is_not_initialized)
275 test_connection_ptr conn = create_connection(
false);
276 ASSERT_FALSE(conn->m_protocol_handler.m_connection_initialized);
277 ASSERT_EQ(0, m_handler_config.get_connections_count());
278 ASSERT_EQ(0, m_commands_handler.new_connection_counter());
280 ASSERT_EQ(0, m_handler_config.get_connections_count());
281 ASSERT_EQ(0, m_commands_handler.close_connection_counter());
284 TEST_F(positive_test_connection_to_levin_protocol_handler_calls, handler_initialization_and_destruction_is_correct)
286 test_connection_ptr conn = create_connection();
287 ASSERT_TRUE(conn->m_protocol_handler.m_connection_initialized);
288 ASSERT_EQ(1, m_handler_config.get_connections_count());
289 ASSERT_EQ(1, m_commands_handler.new_connection_counter());
291 ASSERT_EQ(0, m_handler_config.get_connections_count());
292 ASSERT_EQ(1, m_commands_handler.close_connection_counter());
295 TEST_F(positive_test_connection_to_levin_protocol_handler_calls, concurent_handler_initialization_and_destruction_is_correct)
297 const size_t connection_count = 10000;
298 auto create_and_destroy_connections = [
this]()
300 std::vector<test_connection_ptr> connections(connection_count);
301 for (
size_t i = 0; i < connection_count; ++i)
303 connections[i] = create_connection();
306 for (
size_t i = 0; i < connection_count; ++i)
308 connections[i].reset();
312 const size_t thread_count = boost::thread::hardware_concurrency();
313 std::vector<boost::thread> threads(thread_count);
314 for (boost::thread& th : threads)
316 th = boost::thread(create_and_destroy_connections);
319 for (boost::thread& th : threads)
324 ASSERT_EQ(0, m_handler_config.get_connections_count());
325 ASSERT_EQ(connection_count * thread_count, m_commands_handler.new_connection_counter());
326 ASSERT_EQ(connection_count * thread_count, m_commands_handler.close_connection_counter());
329 TEST_F(positive_test_connection_to_levin_protocol_handler_calls, handler_processes_handle_read_as_invoke)
332 const int expected_command = 2634981;
333 const int expected_return_code = 6732;
336 test_connection_ptr conn = create_connection();
342 req_head.
m_cb = in_data.size();
348 std::string buf(reinterpret_cast<const char*>(&req_head),
sizeof(req_head));
351 m_commands_handler.invoke_out_buf(expected_out_data);
352 m_commands_handler.return_code(expected_return_code);
362 ASSERT_EQ(1, m_commands_handler.invoke_counter());
363 ASSERT_EQ(0, m_commands_handler.notify_counter());
364 ASSERT_EQ(expected_command, m_commands_handler.last_command());
365 ASSERT_EQ(in_data, m_commands_handler.last_in_buf());
372 ASSERT_LT(
sizeof(resp_head), send_data.size());
373 std::string out_data = send_data.substr(
sizeof(resp_head));
386 TEST_F(positive_test_connection_to_levin_protocol_handler_calls, handler_processes_handle_read_as_notify)
389 const int expected_command = 4673261;
391 test_connection_ptr conn = create_connection();
397 req_head.
m_cb = in_data.size();
403 std::string buf(reinterpret_cast<const char*>(&req_head),
sizeof(req_head));
410 ASSERT_EQ(1, m_commands_handler.notify_counter());
411 ASSERT_EQ(0, m_commands_handler.invoke_counter());
412 ASSERT_EQ(expected_command, m_commands_handler.last_command());
413 ASSERT_EQ(in_data, m_commands_handler.last_in_buf());
418 TEST_F(positive_test_connection_to_levin_protocol_handler_calls, handler_processes_qued_callback)
420 test_connection_ptr conn = create_connection();
422 conn->m_protocol_handler.handle_qued_callback();
423 conn->m_protocol_handler.handle_qued_callback();
424 conn->m_protocol_handler.handle_qued_callback();
426 ASSERT_EQ(3, m_commands_handler.callback_counter());
429 TEST_F(test_levin_protocol_handler__hanle_recv_with_invalid_data, handles_big_packet_1)
432 ASSERT_FALSE(m_conn->m_protocol_handler.handle_recv(
buf.data(), max_packet_size + 1));
435 TEST_F(test_levin_protocol_handler__hanle_recv_with_invalid_data, handles_big_packet_2)
438 const size_t first_packet_size =
sizeof(m_req_head) - 1;
440 m_buf.resize(first_packet_size);
441 ASSERT_TRUE(m_conn->m_protocol_handler.handle_recv(m_buf.data(), m_buf.size()));
443 ASSERT_FALSE(m_conn->m_protocol_handler.handle_recv(m_buf.data(), max_packet_size - m_buf.size() + 1));
446 TEST_F(test_levin_protocol_handler__hanle_recv_with_invalid_data, handles_invalid_signature_for_full_header)
451 ASSERT_FALSE(m_conn->m_protocol_handler.handle_recv(m_buf.data(), m_buf.size()));
454 TEST_F(test_levin_protocol_handler__hanle_recv_with_invalid_data, handles_invalid_signature_for_partial_header)
458 m_buf.resize(
sizeof(m_req_head.m_signature));
460 ASSERT_FALSE(m_conn->m_protocol_handler.handle_recv(m_buf.data(), m_buf.size()));
463 TEST_F(test_levin_protocol_handler__hanle_recv_with_invalid_data, handles_big_cb)
465 m_req_head.m_cb = max_packet_size + 1;
468 ASSERT_FALSE(m_conn->m_protocol_handler.handle_recv(m_buf.data(), m_buf.size()));
471 TEST_F(test_levin_protocol_handler__hanle_recv_with_invalid_data, does_not_handle_data_after_close)
476 ASSERT_FALSE(m_conn->m_protocol_handler.handle_recv(m_buf.data(), m_buf.size()));
479 TEST_F(test_levin_protocol_handler__hanle_recv_with_invalid_data, handles_network_error)
483 m_conn->send_return(
false);
484 ASSERT_FALSE(m_conn->m_protocol_handler.handle_recv(m_buf.data(), m_buf.size()));
487 TEST_F(test_levin_protocol_handler__hanle_recv_with_invalid_data, handles_chunked_header)
491 size_t buf1_size =
sizeof(m_req_head) / 2;
497 ASSERT_TRUE(m_conn->m_protocol_handler.handle_recv(buf1.data(), buf1.size()));
498 ASSERT_EQ(0, m_commands_handler.invoke_counter());
500 ASSERT_TRUE(m_conn->m_protocol_handler.handle_recv(buf2.data(), buf2.size()));
501 ASSERT_EQ(1, m_commands_handler.invoke_counter());
505 TEST_F(test_levin_protocol_handler__hanle_recv_with_invalid_data, handles_chunked_body)
509 size_t buf1_size =
sizeof(m_req_head) + (m_buf.size() -
sizeof(m_req_head)) / 2;
515 ASSERT_TRUE(m_conn->m_protocol_handler.handle_recv(buf1.data(), buf1.size()));
516 ASSERT_EQ(0, m_commands_handler.invoke_counter());
518 ASSERT_TRUE(m_conn->m_protocol_handler.handle_recv(buf2.data(), buf2.size()));
519 ASSERT_EQ(1, m_commands_handler.invoke_counter());
522 TEST_F(test_levin_protocol_handler__hanle_recv_with_invalid_data, handles_two_requests_at_once)
527 ASSERT_TRUE(m_conn->m_protocol_handler.handle_recv(m_buf.data(), m_buf.size()));
528 ASSERT_EQ(2, m_commands_handler.invoke_counter());
531 TEST_F(test_levin_protocol_handler__hanle_recv_with_invalid_data, handles_unexpected_response)
536 ASSERT_FALSE(m_conn->m_protocol_handler.handle_recv(m_buf.data(), m_buf.size()));
epee::net_utils::connection< test_levin_protocol_handler > test_connection
uint32_t m_protocol_version
#define LEVIN_PACKET_REQUEST
#define LEVIN_PACKET_RESPONSE
TEST_F(positive_test_connection_to_levin_protocol_handler_calls, new_handler_is_not_initialized)
Non-owning sequence of data. Does not deep copy.
virtual int invoke(int command, const epee::span< const uint8_t > in_buff, std::string &buff_out, t_connection_context &context)=0
#define ASSERT_FALSE(condition)
constexpr std::size_t size() const noexcept
#define ASSERT_EQ(val1, val2)
virtual int notify(int command, const epee::span< const uint8_t > in_buff, t_connection_context &context)=0
virtual void callback(t_connection_context &context)
epee::levin::async_protocol_handler_config< test_connection_context > test_levin_protocol_handler_config
unsigned __int64 uint64_t
std::unique_ptr< void, terminate > context
Unique ZMQ context handle, calls zmq_term on destruction.
virtual boost::asio::io_service & get_io_service()=0
bool m_have_to_return_data
#define ASSERT_LT(val1, val2)
epee::levin::async_protocol_handler< test_connection_context > test_levin_protocol_handler
#define ASSERT_TRUE(condition)
virtual bool call_run_once_service_io()=0
#define LEVIN_PROTOCOL_VER_1
virtual void on_connection_new(t_connection_context &context)
virtual bool send_done()=0
virtual bool request_callback()=0
virtual bool do_send(const void *ptr, size_t cb)=0
#define ASSERT_LE(val1, val2)
virtual void on_connection_close(t_connection_context &context)
constexpr pointer data() const noexcept