1 /* 2 restinio 3 */ 4 5 #include <catch2/catch.hpp> 6 7 #include <restinio/all.hpp> 8 9 #include <test/common/utest_logger.hpp> 10 #include <test/common/pub.hpp> 11 12 namespace test 13 { 14 15 class test_extra_data_factory_t 16 { 17 struct ctor_dtor_monitors_t 18 { 19 std::atomic<int> m_constructors{0}; 20 std::atomic<int> m_destructors{0}; 21 }; 22 23 std::atomic<int> m_index_counter{0}; 24 25 ctor_dtor_monitors_t m_ctor_dtor_monitors; 26 27 public: 28 class data_t 29 { 30 ctor_dtor_monitors_t & m_monitors; 31 32 public: data_t(ctor_dtor_monitors_t & monitors,int index)33 data_t( 34 ctor_dtor_monitors_t & monitors, 35 int index ) 36 : m_monitors{ monitors } 37 , m_index{ index } 38 { 39 ++m_monitors.m_constructors; 40 } ~data_t()41 ~data_t() 42 { 43 ++m_monitors.m_destructors; 44 } 45 46 int m_index; 47 }; 48 49 void make_within(restinio::extra_data_buffer_t<data_t> buffer)50 make_within( restinio::extra_data_buffer_t<data_t> buffer ) noexcept 51 { 52 new(buffer.get()) data_t{ m_ctor_dtor_monitors, ++m_index_counter }; 53 } 54 55 RESTINIO_NODISCARD 56 int current_value()57 current_value() noexcept 58 { 59 return m_index_counter.load( std::memory_order_acquire ); 60 } 61 62 RESTINIO_NODISCARD 63 int constructors_called()64 constructors_called() noexcept 65 { 66 return m_ctor_dtor_monitors.m_constructors.load( std::memory_order_acquire ); 67 } 68 69 RESTINIO_NODISCARD 70 int destructors_called()71 destructors_called() noexcept 72 { 73 return m_ctor_dtor_monitors.m_destructors.load( std::memory_order_acquire ); 74 } 75 }; 76 77 struct test_traits_t : public restinio::traits_t< 78 restinio::asio_timer_manager_t, utest_logger_t > 79 { 80 using extra_data_factory_t = test_extra_data_factory_t; 81 }; 82 83 } /* namespace test */ 84 85 TEST_CASE( "remote_endpoint extraction" , "[remote_endpoint]" ) 86 { 87 using namespace test; 88 89 using http_server_t = restinio::http_server_t< test_traits_t >; 90 91 std::string endpoint_value; 92 int index_value; 93 94 auto extra_data_factory = std::make_shared< test_extra_data_factory_t >(); 95 96 http_server_t http_server{ 97 restinio::own_io_context(), __anoncb17e20c0102( )98 [&endpoint_value, &index_value, extra_data_factory]( auto & settings ){ 99 settings 100 .port( utest_default_port() ) 101 .address( "127.0.0.1" ) 102 .extra_data_factory( extra_data_factory ) 103 .request_handler( 104 [&endpoint_value, &index_value]( auto req ){ 105 endpoint_value = fmt::format( "{}", req->remote_endpoint() ); 106 index_value = req->extra_data().m_index; 107 108 req->create_response() 109 .append_header( "Server", "RESTinio utest server" ) 110 .append_header_date_field() 111 .append_header( "Content-Type", "text/plain; charset=utf-8" ) 112 .set_body( 113 restinio::const_buffer( req->header().method().c_str() ) ) 114 .done(); 115 116 return restinio::request_accepted(); 117 } ); 118 } }; 119 120 other_work_thread_for_server_t<http_server_t> other_thread(http_server); 121 other_thread.run(); 122 123 std::string response; 124 const char * request_str = 125 "GET / HTTP/1.1\r\n" 126 "Host: 127.0.0.1\r\n" 127 "User-Agent: unit-test\r\n" 128 "Accept: */*\r\n" 129 "Connection: close\r\n" 130 "\r\n"; 131 132 REQUIRE_NOTHROW( response = do_request( request_str ) ); 133 134 REQUIRE_THAT( response, Catch::Matchers::EndsWith( "GET" ) ); 135 136 other_thread.stop_and_join(); 137 138 REQUIRE( !endpoint_value.empty() ); 139 REQUIRE( 0 != extra_data_factory->current_value() ); 140 REQUIRE( 1 == extra_data_factory->constructors_called() ); 141 REQUIRE( 1 == extra_data_factory->destructors_called() ); 142 REQUIRE( 1 == index_value ); 143 } 144 145