1 2 // Copyright (c) 2016-2019 Vinnie Falco (vinnie dot falco at gmail dot com) 3 // 4 // Distributed under the Boost Software License, Version 1.0. (See accompanying 5 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 6 // 7 // Official repository: https://github.com/boostorg/beast 8 // 9 10 // Test that header file is self-contained. 11 #include <boost/beast/websocket/stream.hpp> 12 13 #include <boost/beast/_experimental/test/stream.hpp> 14 #include <boost/beast/_experimental/test/tcp.hpp> 15 #include <boost/beast/_experimental/unit_test/suite.hpp> 16 #include <boost/beast/core/flat_buffer.hpp> 17 #include <boost/asio/ip/tcp.hpp> 18 #include <boost/asio/detached.hpp> 19 20 namespace boost { 21 namespace beast { 22 namespace websocket { 23 24 struct timer_test : unit_test::suite 25 { 26 using tcp = boost::asio::ip::tcp; 27 28 void testIdlePingboost::beast::websocket::timer_test29 testIdlePing() 30 { 31 net::io_context ioc; 32 33 // idle ping, no timeout 34 35 { 36 stream<tcp::socket> ws1(ioc); 37 stream<tcp::socket> ws2(ioc); 38 test::connect(ws1.next_layer(), ws2.next_layer()); 39 ws1.async_accept(test::success_handler()); 40 ws2.async_handshake("test", "/", test::success_handler()); 41 test::run(ioc); 42 43 ws2.set_option(stream_base::timeout{ 44 stream_base::none(), 45 std::chrono::milliseconds(100), 46 true}); 47 flat_buffer b1; 48 flat_buffer b2; 49 bool received = false; 50 ws1.control_callback( 51 [&received](frame_type ft, string_view) 52 { 53 received = true; 54 BEAST_EXPECT(ft == frame_type::ping); 55 }); 56 ws1.async_read(b1, test::fail_handler( 57 net::error::operation_aborted)); 58 ws2.async_read(b2, test::fail_handler( 59 net::error::operation_aborted)); 60 test::run_for(ioc, std::chrono::milliseconds(500)); 61 BEAST_EXPECT(received); 62 } 63 64 test::run(ioc); 65 66 // idle ping, timeout 67 68 { 69 stream<tcp::socket> ws1(ioc); 70 stream<tcp::socket> ws2(ioc); 71 test::connect(ws1.next_layer(), ws2.next_layer()); 72 ws1.async_accept(test::success_handler()); 73 ws2.async_handshake("test", "/", test::success_handler()); 74 test::run(ioc); 75 76 ws2.set_option(stream_base::timeout{ 77 stream_base::none(), 78 std::chrono::milliseconds(50), 79 true}); 80 flat_buffer b; 81 ws2.async_read(b, 82 test::fail_handler(beast::error::timeout)); 83 test::run(ioc); 84 } 85 86 test::run(ioc); 87 } 88 89 // https://github.com/boostorg/beast/issues/1729 90 void testIssue1729boost::beast::websocket::timer_test91 testIssue1729() 92 { 93 { 94 net::io_context ioc; 95 stream<tcp::socket> ws1(ioc); 96 stream<tcp::socket> ws2(ioc); 97 test::connect(ws1.next_layer(), ws2.next_layer()); 98 99 ws1.set_option(websocket::stream_base::timeout{ 100 std::chrono::milliseconds(50), 101 websocket::stream_base::none(), 102 false}); 103 104 ws1.async_accept(net::detached); 105 ws2.async_handshake( 106 "localhost", "/", net::detached); 107 ioc.run(); 108 ioc.restart(); 109 110 flat_buffer b; 111 error_code ec1, ec2; 112 ws1.async_close({}, 113 [&ec2](error_code ec) 114 { 115 ec2 = ec; 116 }); 117 ioc.run(); 118 BEAST_EXPECT( 119 ec1 == beast::error::timeout || 120 ec2 == beast::error::timeout); 121 } 122 { 123 net::io_context ioc; 124 stream<tcp::socket> ws1(ioc); 125 stream<tcp::socket> ws2(ioc); 126 test::connect(ws1.next_layer(), ws2.next_layer()); 127 128 ws1.set_option(websocket::stream_base::timeout{ 129 std::chrono::milliseconds(50), 130 websocket::stream_base::none(), 131 false}); 132 133 ws1.async_accept(net::detached); 134 ws2.async_handshake( 135 "localhost", "/", net::detached); 136 ioc.run(); 137 ioc.restart(); 138 139 flat_buffer b; 140 error_code ec1, ec2; 141 ws1.async_read(b, 142 [&ec1](error_code ec, std::size_t) 143 { 144 ec1 = ec; 145 }); 146 ws1.async_close({}, 147 [&ec2](error_code ec) 148 { 149 ec2 = ec; 150 }); 151 ioc.run(); 152 BEAST_EXPECT( 153 ec1 == beast::error::timeout || 154 ec2 == beast::error::timeout); 155 } 156 } 157 158 // https://github.com/boostorg/beast/issues/1729#issuecomment-540481056 159 void testCloseWhileReadboost::beast::websocket::timer_test160 testCloseWhileRead() 161 { 162 net::io_context ioc; 163 stream<tcp::socket> ws1(ioc); 164 stream<tcp::socket> ws2(ioc); 165 test::connect(ws1.next_layer(), ws2.next_layer()); 166 167 ws1.set_option(websocket::stream_base::timeout{ 168 std::chrono::milliseconds(50), 169 websocket::stream_base::none(), 170 false}); 171 172 ws1.async_accept(net::detached); 173 ws2.async_handshake( 174 "localhost", "/", net::detached); 175 ioc.run(); 176 ioc.restart(); 177 178 flat_buffer b; 179 ws1.async_read(b, test::fail_handler( 180 beast::error::timeout)); 181 ws1.async_close({}, test::fail_handler( 182 net::error::operation_aborted)); 183 ioc.run(); 184 } 185 186 void runboost::beast::websocket::timer_test187 run() override 188 { 189 testIdlePing(); 190 testIssue1729(); 191 testCloseWhileRead(); 192 } 193 }; 194 195 BEAST_DEFINE_TESTSUITE(beast,websocket,timer); 196 197 } // websocket 198 } // beast 199 } // boost 200