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
20namespace boost {
21namespace beast {
22namespace websocket {
23
24struct timer_test : unit_test::suite
25{
26 using tcp = boost::asio::ip::tcp;
27
28 void
29 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(s1&: ws1.next_layer(), s2&: ws2.next_layer());
39 ws1.async_accept(handler: test::success_handler());
40 ws2.async_handshake(host: "test", target: "/", handler: test::success_handler());
41 test::run(ioc);
42
43 ws2.set_option(stream_base::timeout{
44 .handshake_timeout: stream_base::none(),
45 .idle_timeout: std::chrono::milliseconds(200),
46 .keep_alive_pings: true});
47 flat_buffer b1;
48 flat_buffer b2;
49 bool received = false;
50 ws1.control_callback(
51 cb: [&received](frame_type ft, string_view)
52 {
53 received = true;
54 BEAST_EXPECT(ft == frame_type::ping);
55 });
56 ws1.async_read(buffer&: b1, handler: test::fail_handler(
57 ec: net::error::operation_aborted));
58 ws2.async_read(buffer&: b2, handler: test::fail_handler(
59 ec: net::error::operation_aborted));
60 test::run_for(ioc, elapsed: 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(s1&: ws1.next_layer(), s2&: ws2.next_layer());
72 ws1.async_accept(handler: test::success_handler());
73 ws2.async_handshake(host: "test", target: "/", handler: test::success_handler());
74 test::run(ioc);
75
76 ws2.set_option(stream_base::timeout{
77 .handshake_timeout: stream_base::none(),
78 .idle_timeout: std::chrono::milliseconds(50),
79 .keep_alive_pings: true});
80 flat_buffer b;
81 ws2.async_read(buffer&: b,
82 handler: test::fail_handler(ec: 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
91 testIssue1729()
92 {
93 {
94 net::io_context ioc;
95 stream<tcp::socket> ws1(ioc);
96 stream<tcp::socket> ws2(ioc);
97 test::connect(s1&: ws1.next_layer(), s2&: ws2.next_layer());
98
99 ws1.set_option(websocket::stream_base::timeout{
100 .handshake_timeout: std::chrono::milliseconds(50),
101 .idle_timeout: websocket::stream_base::none(),
102 .keep_alive_pings: false});
103
104 ws1.async_accept(handler: net::detached);
105 ws2.async_handshake(
106 host: "localhost", target: "/", handler: net::detached);
107 ioc.run();
108 ioc.restart();
109
110 flat_buffer b;
111 error_code ec2;
112 ws1.async_close(cr: {},
113 handler: [&ec2](error_code ec)
114 {
115 ec2 = ec;
116 });
117 ioc.run();
118 BEAST_EXPECTS(
119 ec2 == beast::error::timeout ||
120 ec2 == net::error::operation_aborted,
121 ec2.message());
122 }
123 {
124 net::io_context ioc;
125 stream<tcp::socket> ws1(ioc);
126 stream<tcp::socket> ws2(ioc);
127 test::connect(s1&: ws1.next_layer(), s2&: ws2.next_layer());
128
129 ws1.set_option(websocket::stream_base::timeout{
130 .handshake_timeout: std::chrono::milliseconds(50),
131 .idle_timeout: websocket::stream_base::none(),
132 .keep_alive_pings: false});
133
134 ws1.async_accept(handler: net::detached);
135 ws2.async_handshake(
136 host: "localhost", target: "/", handler: net::detached);
137 ioc.run();
138 ioc.restart();
139
140 flat_buffer b;
141 error_code ec1, ec2;
142 ws1.async_read(buffer&: b,
143 handler: [&ec1](error_code ec, std::size_t)
144 {
145 ec1 = ec;
146 });
147 ws1.async_close(cr: {},
148 handler: [&ec2](error_code ec)
149 {
150 ec2 = ec;
151 });
152 ioc.run();
153 BEAST_EXPECT(
154 ec1 == beast::error::timeout ||
155 ec2 == beast::error::timeout);
156 }
157 }
158
159 // https://github.com/boostorg/beast/issues/1729#issuecomment-540481056
160 void
161 testCloseWhileRead()
162 {
163 net::io_context ioc;
164 stream<tcp::socket> ws1(ioc);
165 stream<tcp::socket> ws2(ioc);
166 test::connect(s1&: ws1.next_layer(), s2&: ws2.next_layer());
167
168 ws1.set_option(websocket::stream_base::timeout{
169 .handshake_timeout: std::chrono::milliseconds(50),
170 .idle_timeout: websocket::stream_base::none(),
171 .keep_alive_pings: false});
172
173 ws1.async_accept(handler: net::detached);
174 ws2.async_handshake(
175 host: "localhost", target: "/", handler: net::detached);
176 ioc.run();
177 ioc.restart();
178
179 flat_buffer b;
180 ws1.async_read(buffer&: b, handler: test::fail_handler(
181 ec: beast::error::timeout));
182 ws1.async_close(cr: {}, handler: test::fail_handler(
183 ec: net::error::operation_aborted));
184 ioc.run();
185 }
186
187 void
188 run() override
189 {
190 testIssue1729();
191 testIdlePing();
192 testCloseWhileRead();
193 }
194};
195
196BEAST_DEFINE_TESTSUITE(beast,websocket,timer);
197
198} // websocket
199} // beast
200} // boost
201

source code of boost/libs/beast/test/beast/websocket/timer.cpp