]>
git.proxmox.com Git - ceph.git/blob - ceph/src/boost/libs/beast/test/beast/websocket/ping.cpp
2 // Copyright (c) 2016-2019 Vinnie Falco (vinnie dot falco at gmail dot com)
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)
7 // Official repository: https://github.com/boostorg/beast
10 // Test that header file is self-contained.
11 #include <boost/beast/websocket/stream.hpp>
13 #include <boost/beast/_experimental/test/tcp.hpp>
17 #include <boost/asio/ip/tcp.hpp>
18 #include <boost/asio/io_context.hpp>
19 #include <boost/asio/strand.hpp>
21 #if BOOST_ASIO_HAS_CO_AWAIT
22 #include <boost/asio/use_awaitable.hpp>
29 class ping_test
: public websocket_test_suite
34 doTestPing(Wrap
const& w
)
36 permessage_deflate pmd
;
37 pmd
.client_enable
= false;
38 pmd
.server_enable
= false;
41 doTest(pmd
, [&](ws_type
& ws
)
47 doTest(pmd
, [&](ws_type
& ws
)
52 // ping, already closed
55 stream
<test::stream
> ws
{ioc_
};
56 ws
.next_layer().connect(es
.stream());
57 ws
.handshake("localhost", "/");
62 fail("", __FILE__
, __LINE__
);
64 catch(system_error
const& se
)
67 se
.code() == net::error::operation_aborted
,
72 // pong, already closed
75 stream
<test::stream
> ws
{ioc_
};
76 ws
.next_layer().connect(es
.stream());
77 ws
.handshake("localhost", "/");
82 fail("", __FILE__
, __LINE__
);
84 catch(system_error
const& se
)
87 se
.code() == net::error::operation_aborted
,
96 doTestPing(SyncClient
{});
98 yield_to([&](yield_context yield
)
100 doTestPing(AsyncClient
{yield
});
108 doFailLoop([&](test::fail_count
& fc
)
112 stream
<test::stream
> ws
{ioc
, fc
};
113 ws
.next_layer().connect(es
.stream());
114 ws
.handshake("localhost", "/");
115 std::size_t count
= 0;
116 ws
.async_write(sbuf("Hello, world"),
117 [&](error_code ec
, std::size_t n
)
121 BOOST_THROW_EXCEPTION(
123 BEAST_EXPECT(n
== 12);
125 BEAST_EXPECT(ws
.impl_
->wr_block
.is_locked());
126 BEAST_EXPECT(count
== 0);
132 BOOST_THROW_EXCEPTION(
135 BEAST_EXPECT(count
== 0);
137 BEAST_EXPECT(count
== 2);
141 doFailLoop([&](test::fail_count
& fc
)
145 stream
<test::stream
> ws
{ioc
, fc
};
146 ws
.next_layer().connect(es
.stream());
147 ws
.handshake("localhost", "/");
148 std::size_t count
= 0;
154 BOOST_THROW_EXCEPTION(
157 BEAST_EXPECT(ws
.impl_
->wr_block
.is_locked());
158 BEAST_EXPECT(count
== 0);
163 if(ec
!= net::error::operation_aborted
)
164 BOOST_THROW_EXCEPTION(
167 BEAST_EXPECT(count
== 0);
169 BEAST_EXPECT(count
== 2);
172 // suspend on read ping + message
173 doFailLoop([&](test::fail_count
& fc
)
177 stream
<test::stream
> ws
{ioc
, fc
};
178 ws
.next_layer().connect(es
.stream());
179 ws
.handshake("localhost", "/");
180 // add a ping and message to the input
181 ws
.next_layer().append(string_view
{
182 "\x89\x00" "\x81\x01*", 5});
183 std::size_t count
= 0;
186 [&](error_code ec
, std::size_t)
190 BOOST_THROW_EXCEPTION(
193 while(! ws
.impl_
->wr_block
.is_locked())
196 if(! BEAST_EXPECT(! ioc
.stopped()))
199 BEAST_EXPECT(count
== 0);
205 BOOST_THROW_EXCEPTION(
208 BEAST_EXPECT(count
== 0);
210 BEAST_EXPECT(count
== 2);
213 // suspend on read bad message
214 doFailLoop([&](test::fail_count
& fc
)
218 stream
<test::stream
> ws
{ioc
, fc
};
219 ws
.next_layer().connect(es
.stream());
220 ws
.handshake("localhost", "/");
221 // add an invalid frame to the input
222 ws
.next_layer().append(string_view
{
225 std::size_t count
= 0;
228 [&](error_code ec
, std::size_t)
231 if(ec
!= error::bad_control_fragment
)
232 BOOST_THROW_EXCEPTION(
235 while(! ws
.impl_
->wr_block
.is_locked())
238 if(! BEAST_EXPECT(! ioc
.stopped()))
241 BEAST_EXPECT(count
== 0);
246 if(ec
!= net::error::operation_aborted
)
247 BOOST_THROW_EXCEPTION(
250 BEAST_EXPECT(count
== 0);
252 BEAST_EXPECT(count
== 2);
255 // suspend on read close #1
256 doFailLoop([&](test::fail_count
& fc
)
260 stream
<test::stream
> ws
{ioc
, fc
};
261 ws
.next_layer().connect(es
.stream());
262 ws
.handshake("localhost", "/");
263 // add a close frame to the input
264 ws
.next_layer().append(string_view
{
266 std::size_t count
= 0;
269 [&](error_code ec
, std::size_t)
272 if(ec
!= error::closed
)
273 BOOST_THROW_EXCEPTION(
276 while(! ws
.impl_
->wr_block
.is_locked())
279 if(! BEAST_EXPECT(! ioc
.stopped()))
282 BEAST_EXPECT(count
== 0);
287 if(ec
!= net::error::operation_aborted
)
288 BOOST_THROW_EXCEPTION(
291 BEAST_EXPECT(count
== 0);
293 BEAST_EXPECT(count
== 2);
296 // suspend on read close #2
297 doFailLoop([&](test::fail_count
& fc
)
299 echo_server es
{log
, kind::async
};
301 stream
<test::stream
> ws
{ioc
, fc
};
302 ws
.next_layer().connect(es
.stream());
303 ws
.handshake("localhost", "/");
304 // Cause close to be received
306 std::size_t count
= 0;
309 [&](error_code ec
, std::size_t)
312 if(ec
!= error::closed
)
313 BOOST_THROW_EXCEPTION(
316 while(! ws
.impl_
->wr_block
.is_locked())
319 if(! BEAST_EXPECT(! ioc
.stopped()))
322 BEAST_EXPECT(count
== 0);
327 if(ec
!= net::error::operation_aborted
)
328 BOOST_THROW_EXCEPTION(
331 BEAST_EXPECT(count
== 0);
333 BEAST_EXPECT(count
== 2);
336 // don't ping on close
337 doFailLoop([&](test::fail_count
& fc
)
342 stream
<test::stream
> ws
{ioc
, fc
};
343 ws
.next_layer().connect(es
.stream());
344 ws
.handshake("localhost", "/");
345 std::size_t count
= 0;
346 ws
.async_write(sbuf("*"),
347 [&](error_code ec
, std::size_t n
)
351 BOOST_THROW_EXCEPTION(
353 BEAST_EXPECT(n
== 1);
355 BEAST_EXPECT(ws
.impl_
->wr_block
.is_locked());
360 if(ec
!= net::error::operation_aborted
)
361 BOOST_THROW_EXCEPTION(
369 BOOST_THROW_EXCEPTION(
373 BEAST_EXPECT(count
== 3);
379 net::basic_stream_socket
<
381 net::any_io_executor
>;
383 stream
<socket_type
> ws1(ioc
);
384 stream
<socket_type
> ws2(ioc
);
385 ws1
.set_option(stream_base::timeout
{
387 std::chrono::seconds(0),
392 ws1
.async_handshake("localhost", "/",
394 ws2
.async_accept([](error_code
){});
398 auto mb
= b1
.prepare(65536);
399 std::memset(mb
.data(), 0, mb
.size());
401 ws1
.async_write(b1
.data(),
402 [&](error_code
, std::size_t){});
404 ws1
.impl_
->wr_block
.is_locked());
405 ws1
.async_read_some(net::mutable_buffer
{},
406 [&](error_code
, std::size_t){});
411 [&](error_code
, std::size_t){});
417 echo_server es
{log
, kind::async
};
419 stream
<test::stream
> ws
{ioc
};
420 ws
.next_layer().connect(es
.stream());
421 ws
.handshake("localhost", "/");
423 // Cause close to be received
427 std::size_t count
= 0;
428 // Read a close frame.
429 // Sends a close frame, blocking writes.
431 [&](error_code ec
, std::size_t)
433 // Read should complete with error::closed
435 BEAST_EXPECTS(ec
== error::closed
,
438 if(! BEAST_EXPECT(run_until(ioc
, 100,
439 [&]{ return ws
.impl_
->wr_close
; })))
442 ws
.async_ping("payload",
445 // Pings after a close are aborted
447 BEAST_EXPECTS(ec
== net::
448 error::operation_aborted
,
450 // Subsequent calls to close are aborted
455 BEAST_EXPECTS(ec
== net::
456 error::operation_aborted
,
460 static std::size_t constexpr limit
= 100;
462 for(n
= 0; n
< limit
; ++n
)
468 BEAST_EXPECT(n
< limit
);
477 stream
<test::stream
> ws
{ioc
};
478 ws
.async_ping({}, move_only_handler
{});
481 struct copyable_handler
483 template<class... Args
>
485 operator()(Args
&&...) const
490 #if BOOST_ASIO_HAS_CO_AWAIT
491 void testAwaitableCompiles(
492 stream
<test::stream
>& s
,
495 static_assert(std::is_same_v
<
496 net::awaitable
<void>, decltype(
497 s
.async_ping(pdat
, net::use_awaitable
))>);
499 static_assert(std::is_same_v
<
500 net::awaitable
<void>, decltype(
501 s
.async_pong(pdat
, net::use_awaitable
))>);
511 #if BOOST_ASIO_HAS_CO_AWAIT
512 boost::ignore_unused(&ping_test::testAwaitableCompiles
);
517 BEAST_DEFINE_TESTSUITE(beast
,websocket
,ping
);