]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/libs/beast/test/beast/websocket/ping.cpp
update sources to v12.2.3
[ceph.git] / ceph / src / boost / libs / beast / test / beast / websocket / ping.cpp
1 //
2 // Copyright (w) 2016-2017 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 "test.hpp"
14
15 namespace boost {
16 namespace beast {
17 namespace websocket {
18
19 class ping_test : public websocket_test_suite
20 {
21 public:
22 template<class Wrap>
23 void
24 doTestPing(Wrap const& w)
25 {
26 permessage_deflate pmd;
27 pmd.client_enable = false;
28 pmd.server_enable = false;
29
30 // ping
31 doTest(pmd, [&](ws_type& ws)
32 {
33 w.ping(ws, {});
34 });
35
36 // pong
37 doTest(pmd, [&](ws_type& ws)
38 {
39 w.pong(ws, {});
40 });
41
42 // ping, already closed
43 {
44 echo_server es{log};
45 stream<test::stream> ws{ioc_};
46 ws.next_layer().connect(es.stream());
47 ws.handshake("localhost", "/");
48 ws.close({});
49 try
50 {
51 w.ping(ws, {});
52 fail("", __FILE__, __LINE__);
53 }
54 catch(system_error const& se)
55 {
56 BEAST_EXPECTS(
57 se.code() == boost::asio::error::operation_aborted,
58 se.code().message());
59 }
60 }
61
62 // pong, already closed
63 {
64 echo_server es{log};
65 stream<test::stream> ws{ioc_};
66 ws.next_layer().connect(es.stream());
67 ws.handshake("localhost", "/");
68 ws.close({});
69 try
70 {
71 w.pong(ws, {});
72 fail("", __FILE__, __LINE__);
73 }
74 catch(system_error const& se)
75 {
76 BEAST_EXPECTS(
77 se.code() == boost::asio::error::operation_aborted,
78 se.code().message());
79 }
80 }
81 }
82
83 void
84 testPing()
85 {
86 doTestPing(SyncClient{});
87
88 yield_to([&](yield_context yield)
89 {
90 doTestPing(AsyncClient{yield});
91 });
92 }
93
94 void
95 testSuspend()
96 {
97 // suspend on write
98 doFailLoop([&](test::fail_counter& fc)
99 {
100 echo_server es{log};
101 boost::asio::io_context ioc;
102 stream<test::stream> ws{ioc, fc};
103 ws.next_layer().connect(es.stream());
104 ws.handshake("localhost", "/");
105 std::size_t count = 0;
106 ws.async_write(sbuf("Hello, world"),
107 [&](error_code ec, std::size_t n)
108 {
109 ++count;
110 if(ec)
111 BOOST_THROW_EXCEPTION(
112 system_error{ec});
113 BEAST_EXPECT(n == 12);
114 });
115 BEAST_EXPECT(ws.wr_block_);
116 BEAST_EXPECT(count == 0);
117 ws.async_ping({},
118 [&](error_code ec)
119 {
120 ++count;
121 if(ec)
122 BOOST_THROW_EXCEPTION(
123 system_error{ec});
124 });
125 BEAST_EXPECT(count == 0);
126 ioc.run();
127 BEAST_EXPECT(count == 2);
128 });
129
130 // suspend on close
131 doFailLoop([&](test::fail_counter& fc)
132 {
133 echo_server es{log};
134 boost::asio::io_context ioc;
135 stream<test::stream> ws{ioc, fc};
136 ws.next_layer().connect(es.stream());
137 ws.handshake("localhost", "/");
138 std::size_t count = 0;
139 ws.async_close({},
140 [&](error_code ec)
141 {
142 ++count;
143 if(ec)
144 BOOST_THROW_EXCEPTION(
145 system_error{ec});
146 });
147 BEAST_EXPECT(ws.wr_block_);
148 BEAST_EXPECT(count == 0);
149 ws.async_ping({},
150 [&](error_code ec)
151 {
152 ++count;
153 if(ec != boost::asio::error::operation_aborted)
154 BOOST_THROW_EXCEPTION(
155 system_error{ec});
156 });
157 BEAST_EXPECT(count == 0);
158 ioc.run();
159 BEAST_EXPECT(count == 2);
160 });
161
162 // suspend on read ping + message
163 doFailLoop([&](test::fail_counter& fc)
164 {
165 echo_server es{log};
166 boost::asio::io_context ioc;
167 stream<test::stream> ws{ioc, fc};
168 ws.next_layer().connect(es.stream());
169 ws.handshake("localhost", "/");
170 // add a ping and message to the input
171 ws.next_layer().append(string_view{
172 "\x89\x00" "\x81\x01*", 5});
173 std::size_t count = 0;
174 multi_buffer b;
175 ws.async_read(b,
176 [&](error_code ec, std::size_t)
177 {
178 ++count;
179 if(ec)
180 BOOST_THROW_EXCEPTION(
181 system_error{ec});
182 });
183 while(! ws.wr_block_)
184 {
185 ioc.run_one();
186 if(! BEAST_EXPECT(! ioc.stopped()))
187 break;
188 }
189 BEAST_EXPECT(count == 0);
190 ws.async_ping({},
191 [&](error_code ec)
192 {
193 ++count;
194 if(ec)
195 BOOST_THROW_EXCEPTION(
196 system_error{ec});
197 });
198 BEAST_EXPECT(count == 0);
199 ioc.run();
200 BEAST_EXPECT(count == 2);
201 });
202
203 // suspend on read bad message
204 doFailLoop([&](test::fail_counter& fc)
205 {
206 echo_server es{log};
207 boost::asio::io_context ioc;
208 stream<test::stream> ws{ioc, fc};
209 ws.next_layer().connect(es.stream());
210 ws.handshake("localhost", "/");
211 // add an invalid frame to the input
212 ws.next_layer().append(string_view{
213 "\x09\x00", 2});
214
215 std::size_t count = 0;
216 multi_buffer b;
217 ws.async_read(b,
218 [&](error_code ec, std::size_t)
219 {
220 ++count;
221 if(ec != error::failed)
222 BOOST_THROW_EXCEPTION(
223 system_error{ec});
224 });
225 while(! ws.wr_block_)
226 {
227 ioc.run_one();
228 if(! BEAST_EXPECT(! ioc.stopped()))
229 break;
230 }
231 BEAST_EXPECT(count == 0);
232 ws.async_ping({},
233 [&](error_code ec)
234 {
235 ++count;
236 if(ec != boost::asio::error::operation_aborted)
237 BOOST_THROW_EXCEPTION(
238 system_error{ec});
239 });
240 BEAST_EXPECT(count == 0);
241 ioc.run();
242 BEAST_EXPECT(count == 2);
243 });
244
245 // suspend on read close #1
246 doFailLoop([&](test::fail_counter& fc)
247 {
248 echo_server es{log};
249 boost::asio::io_context ioc;
250 stream<test::stream> ws{ioc, fc};
251 ws.next_layer().connect(es.stream());
252 ws.handshake("localhost", "/");
253 // add a close frame to the input
254 ws.next_layer().append(string_view{
255 "\x88\x00", 2});
256 std::size_t count = 0;
257 multi_buffer b;
258 ws.async_read(b,
259 [&](error_code ec, std::size_t)
260 {
261 ++count;
262 if(ec != error::closed)
263 BOOST_THROW_EXCEPTION(
264 system_error{ec});
265 });
266 while(! ws.wr_block_)
267 {
268 ioc.run_one();
269 if(! BEAST_EXPECT(! ioc.stopped()))
270 break;
271 }
272 BEAST_EXPECT(count == 0);
273 ws.async_ping({},
274 [&](error_code ec)
275 {
276 ++count;
277 if(ec != boost::asio::error::operation_aborted)
278 BOOST_THROW_EXCEPTION(
279 system_error{ec});
280 });
281 BEAST_EXPECT(count == 0);
282 ioc.run();
283 BEAST_EXPECT(count == 2);
284 });
285
286 // suspend on read close #2
287 doFailLoop([&](test::fail_counter& fc)
288 {
289 echo_server es{log, kind::async};
290 boost::asio::io_context ioc;
291 stream<test::stream> ws{ioc, fc};
292 ws.next_layer().connect(es.stream());
293 ws.handshake("localhost", "/");
294 // Cause close to be received
295 es.async_close();
296 std::size_t count = 0;
297 multi_buffer b;
298 ws.async_read(b,
299 [&](error_code ec, std::size_t)
300 {
301 ++count;
302 if(ec != error::closed)
303 BOOST_THROW_EXCEPTION(
304 system_error{ec});
305 });
306 while(! ws.wr_block_)
307 {
308 ioc.run_one();
309 if(! BEAST_EXPECT(! ioc.stopped()))
310 break;
311 }
312 BEAST_EXPECT(count == 0);
313 ws.async_ping({},
314 [&](error_code ec)
315 {
316 ++count;
317 if(ec != boost::asio::error::operation_aborted)
318 BOOST_THROW_EXCEPTION(
319 system_error{ec});
320 });
321 BEAST_EXPECT(count == 0);
322 ioc.run();
323 BEAST_EXPECT(count == 2);
324 });
325
326 // don't ping on close
327 doFailLoop([&](test::fail_counter& fc)
328 {
329 echo_server es{log};
330 error_code ec;
331 boost::asio::io_context ioc;
332 stream<test::stream> ws{ioc, fc};
333 ws.next_layer().connect(es.stream());
334 ws.handshake("localhost", "/");
335 std::size_t count = 0;
336 ws.async_write(sbuf("*"),
337 [&](error_code ec, std::size_t n)
338 {
339 ++count;
340 if(ec)
341 BOOST_THROW_EXCEPTION(
342 system_error{ec});
343 BEAST_EXPECT(n == 1);
344 });
345 BEAST_EXPECT(ws.wr_block_);
346 ws.async_ping("",
347 [&](error_code ec)
348 {
349 ++count;
350 if(ec != boost::asio::error::operation_aborted)
351 BOOST_THROW_EXCEPTION(
352 system_error{ec});
353 });
354 ws.async_close({},
355 [&](error_code)
356 {
357 ++count;
358 if(ec)
359 BOOST_THROW_EXCEPTION(
360 system_error{ec});
361 });
362 ioc.run();
363 BEAST_EXPECT(count == 3);
364 });
365
366 {
367 echo_server es{log, kind::async};
368 boost::asio::io_context ioc;
369 stream<test::stream> ws{ioc};
370 ws.next_layer().connect(es.stream());
371 ws.handshake("localhost", "/");
372
373 // Cause close to be received
374 es.async_close();
375
376 multi_buffer b;
377 std::size_t count = 0;
378 // Read a close frame.
379 // Sends a close frame, blocking writes.
380 ws.async_read(b,
381 [&](error_code ec, std::size_t)
382 {
383 // Read should complete with error::closed
384 ++count;
385 BEAST_EXPECTS(ec == error::closed,
386 ec.message());
387 // Pings after a close are aborted
388 ws.async_ping("",
389 [&](error_code ec)
390 {
391 ++count;
392 BEAST_EXPECTS(ec == boost::asio::
393 error::operation_aborted,
394 ec.message());
395 });
396 });
397 if(! BEAST_EXPECT(run_until(ioc, 100,
398 [&]{ return ws.wr_close_; })))
399 return;
400 // Try to ping
401 ws.async_ping("payload",
402 [&](error_code ec)
403 {
404 // Pings after a close are aborted
405 ++count;
406 BEAST_EXPECTS(ec == boost::asio::
407 error::operation_aborted,
408 ec.message());
409 // Subsequent calls to close are aborted
410 ws.async_close({},
411 [&](error_code ec)
412 {
413 ++count;
414 BEAST_EXPECTS(ec == boost::asio::
415 error::operation_aborted,
416 ec.message());
417 });
418 });
419 static std::size_t constexpr limit = 100;
420 std::size_t n;
421 for(n = 0; n < limit; ++n)
422 {
423 if(count >= 4)
424 break;
425 ioc.run_one();
426 }
427 BEAST_EXPECT(n < limit);
428 ioc.run();
429 }
430 }
431
432 void
433 testContHook()
434 {
435 struct handler
436 {
437 void operator()(error_code) {}
438 };
439
440 stream<test::stream> ws{ioc_};
441 stream<test::stream>::ping_op<handler> op{
442 handler{}, ws, detail::opcode::ping, {}};
443 using boost::asio::asio_handler_is_continuation;
444 asio_handler_is_continuation(&op);
445 }
446
447 void
448 run() override
449 {
450 testPing();
451 testSuspend();
452 testContHook();
453 }
454 };
455
456 BEAST_DEFINE_TESTSUITE(beast,websocket,ping);
457
458 } // websocket
459 } // beast
460 } // boost