//
-// Copyright (w) 2016-2017 Vinnie Falco (vinnie dot falco at gmail dot com)
+// Copyright (c) 2016-2019 Vinnie Falco (vinnie dot falco at gmail dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
// Test that header file is self-contained.
#include <boost/beast/websocket/stream.hpp>
+#include <boost/beast/_experimental/test/stream.hpp>
+#include <boost/beast/_experimental/test/tcp.hpp>
#include "test.hpp"
-#include <boost/asio/io_service.hpp>
+#include <boost/asio/io_context.hpp>
#include <boost/asio/strand.hpp>
namespace boost {
catch(system_error const& se)
{
BEAST_EXPECTS(
- se.code() == boost::asio::error::operation_aborted,
+ se.code() == net::error::operation_aborted,
se.code().message());
}
}
}
void
- testSuspend()
+ testTimeout()
{
- using boost::asio::buffer;
+ using tcp = net::ip::tcp;
+
+ net::io_context ioc;
+
+ // success
+
+ {
+ stream<tcp::socket> ws1(ioc);
+ stream<tcp::socket> ws2(ioc);
+ test::connect(ws1.next_layer(), ws2.next_layer());
+ ws1.async_handshake("test", "/", test::success_handler());
+ ws2.async_accept(test::success_handler());
+ test::run(ioc);
+
+ ws1.async_close({}, test::success_handler());
+ ws2.async_close({}, test::success_handler());
+ test::run(ioc);
+ }
+
+ {
+ stream<test::stream> ws1(ioc);
+ stream<test::stream> ws2(ioc);
+ test::connect(ws1.next_layer(), ws2.next_layer());
+ ws1.async_handshake("test", "/", test::success_handler());
+ ws2.async_accept(test::success_handler());
+ test::run(ioc);
+
+ ws1.async_close({}, test::success_handler());
+ ws2.async_close({}, test::success_handler());
+ test::run(ioc);
+ }
+
+ // success, timeout enabled
+
+ {
+ stream<tcp::socket> ws1(ioc);
+ stream<tcp::socket> ws2(ioc);
+ test::connect(ws1.next_layer(), ws2.next_layer());
+ ws1.async_handshake("test", "/", test::success_handler());
+ ws2.async_accept(test::success_handler());
+ test::run(ioc);
+
+ ws1.set_option(stream_base::timeout{
+ std::chrono::milliseconds(50),
+ stream_base::none(),
+ false});
+ ws1.async_close({}, test::success_handler());
+ ws2.async_close({}, test::success_handler());
+ test::run(ioc);
+ }
+
+ {
+ stream<test::stream> ws1(ioc);
+ stream<test::stream> ws2(ioc);
+ test::connect(ws1.next_layer(), ws2.next_layer());
+ ws1.async_handshake("test", "/", test::success_handler());
+ ws2.async_accept(test::success_handler());
+ test::run(ioc);
+
+ ws1.set_option(stream_base::timeout{
+ std::chrono::milliseconds(50),
+ stream_base::none(),
+ false});
+ ws1.async_close({}, test::success_handler());
+ ws2.async_close({}, test::success_handler());
+ test::run(ioc);
+ }
+ // timeout
+
+ {
+ stream<tcp::socket> ws1(ioc);
+ stream<tcp::socket> ws2(ioc);
+ test::connect(ws1.next_layer(), ws2.next_layer());
+ ws1.async_handshake("test", "/", test::success_handler());
+ ws2.async_accept(test::success_handler());
+ test::run(ioc);
+
+ ws1.set_option(stream_base::timeout{
+ std::chrono::milliseconds(50),
+ stream_base::none(),
+ false});
+ ws1.async_close({}, test::fail_handler(
+ beast::error::timeout));
+ test::run(ioc);
+ }
+
+ {
+ stream<test::stream> ws1(ioc);
+ stream<test::stream> ws2(ioc);
+ test::connect(ws1.next_layer(), ws2.next_layer());
+ ws1.async_handshake("test", "/", test::success_handler());
+ ws2.async_accept(test::success_handler());
+ test::run(ioc);
+
+ ws1.set_option(stream_base::timeout{
+ std::chrono::milliseconds(50),
+ stream_base::none(),
+ false});
+ ws1.async_close({}, test::fail_handler(
+ beast::error::timeout));
+ test::run(ioc);
+ }
+ }
+
+ void
+ testSuspend()
+ {
// suspend on ping
- doFailLoop([&](test::fail_counter& fc)
+ doFailLoop([&](test::fail_count& fc)
{
echo_server es{log};
- boost::asio::io_context ioc;
+ net::io_context ioc;
stream<test::stream> ws{ioc, fc};
ws.next_layer().connect(es.stream());
ws.handshake("localhost", "/");
BOOST_THROW_EXCEPTION(
system_error{ec});
});
- BEAST_EXPECT(ws.wr_block_.is_locked());
+ BEAST_EXPECT(ws.impl_->wr_block.is_locked());
BEAST_EXPECT(count == 0);
ws.async_close({},
[&](error_code ec)
});
// suspend on write
- doFailLoop([&](test::fail_counter& fc)
+ doFailLoop([&](test::fail_count& fc)
{
echo_server es{log};
- boost::asio::io_context ioc;
+ net::io_context ioc;
stream<test::stream> ws{ioc, fc};
ws.next_layer().connect(es.stream());
ws.handshake("localhost", "/");
system_error{ec});
BEAST_EXPECT(n == 1);
});
- BEAST_EXPECT(ws.wr_block_.is_locked());
+ BEAST_EXPECT(ws.impl_->wr_block.is_locked());
BEAST_EXPECT(count == 0);
ws.async_close({},
[&](error_code ec)
});
// suspend on read ping + message
- doFailLoop([&](test::fail_counter& fc)
+ doFailLoop([&](test::fail_count& fc)
{
echo_server es{log};
- boost::asio::io_context ioc;
+ multi_buffer b;
+ net::io_context ioc;
stream<test::stream> ws{ioc, fc};
ws.next_layer().connect(es.stream());
ws.handshake("localhost", "/");
ws.next_layer().append(string_view{
"\x89\x00" "\x81\x01*", 5});
std::size_t count = 0;
- multi_buffer b;
ws.async_read(b,
[&](error_code ec, std::size_t)
{
BOOST_THROW_EXCEPTION(
system_error{ec});
});
- while(! ws.wr_block_.is_locked())
+ while(! ws.impl_->wr_block.is_locked())
{
ioc.run_one();
if(! BEAST_EXPECT(! ioc.stopped()))
});
// suspend on read bad message
- doFailLoop([&](test::fail_counter& fc)
+ doFailLoop([&](test::fail_count& fc)
{
echo_server es{log};
- boost::asio::io_context ioc;
+ multi_buffer b;
+ net::io_context ioc;
stream<test::stream> ws{ioc, fc};
ws.next_layer().connect(es.stream());
ws.handshake("localhost", "/");
ws.next_layer().append(string_view{
"\x09\x00", 2});
std::size_t count = 0;
- multi_buffer b;
ws.async_read(b,
[&](error_code ec, std::size_t)
{
system_error{ec});
BEAST_EXPECT(++count == 1);
});
- while(! ws.wr_block_.is_locked())
+ while(! ws.impl_->wr_block.is_locked())
{
ioc.run_one();
if(! BEAST_EXPECT(! ioc.stopped()))
ws.async_close({},
[&](error_code ec)
{
- if(ec != boost::asio::error::operation_aborted)
+ if(ec != net::error::operation_aborted)
BOOST_THROW_EXCEPTION(
system_error{ec});
BEAST_EXPECT(++count == 2);
});
// suspend on read close #1
- doFailLoop([&](test::fail_counter& fc)
+ doFailLoop([&](test::fail_count& fc)
{
echo_server es{log};
- boost::asio::io_context ioc;
+ multi_buffer b;
+ net::io_context ioc;
stream<test::stream> ws{ioc, fc};
ws.next_layer().connect(es.stream());
ws.handshake("localhost", "/");
ws.next_layer().append(string_view{
"\x88\x00", 2});
std::size_t count = 0;
- multi_buffer b;
ws.async_read(b,
[&](error_code ec, std::size_t)
{
system_error{ec});
BEAST_EXPECT(++count == 1);
});
- while(! ws.wr_block_.is_locked())
+ while(! ws.impl_->wr_block.is_locked())
{
ioc.run_one();
if(! BEAST_EXPECT(! ioc.stopped()))
ws.async_close({},
[&](error_code ec)
{
- if(ec != boost::asio::error::operation_aborted)
+ if(ec != net::error::operation_aborted)
BOOST_THROW_EXCEPTION(
system_error{ec});
BEAST_EXPECT(++count == 2);
});
// teardown on received close
- doFailLoop([&](test::fail_counter& fc)
+ doFailLoop([&](test::fail_count& fc)
{
echo_server es{log};
- boost::asio::io_context ioc;
+ std::string const s = "Hello, world!";
+ multi_buffer b;
+ net::io_context ioc;
stream<test::stream> ws{ioc, fc};
ws.next_layer().connect(es.stream());
ws.handshake("localhost", "/");
ws.next_layer().append(string_view{
"\x88\x00", 2});
std::size_t count = 0;
- std::string const s = "Hello, world!";
- ws.async_write(buffer(s),
+ ws.async_write(net::buffer(s),
[&](error_code ec, std::size_t n)
{
if(ec)
BEAST_EXPECT(n == s.size());
BEAST_EXPECT(++count == 1);
});
- multi_buffer b;
ws.async_read(b,
[&](error_code ec, std::size_t)
{
- if(ec != boost::asio::error::operation_aborted)
+ if(ec != net::error::operation_aborted)
BOOST_THROW_EXCEPTION(
system_error{ec});
BEAST_EXPECT(++count == 3);
});
// check for deadlock
- doFailLoop([&](test::fail_counter& fc)
+ doFailLoop([&](test::fail_count& fc)
{
echo_server es{log};
- boost::asio::io_context ioc;
+ multi_buffer b;
+ std::string const s = "Hello, world!";
+ net::io_context ioc;
stream<test::stream> ws{ioc, fc};
ws.next_layer().connect(es.stream());
ws.handshake("localhost", "/");
ws.next_layer().append(string_view{
"\x89\x00", 2});
std::size_t count = 0;
- multi_buffer b;
- std::string const s = "Hello, world!";
- ws.async_write(buffer(s),
+ ws.async_write(net::buffer(s),
[&](error_code ec, std::size_t n)
{
if(ec)
ws.async_read(b,
[&](error_code ec, std::size_t)
{
- if(ec != boost::asio::error::operation_aborted)
+ if(ec != net::error::operation_aborted)
BOOST_THROW_EXCEPTION(
system_error{ec});
BEAST_EXPECT(++count == 3);
});
- BEAST_EXPECT(ws.rd_block_.is_locked());
+ BEAST_EXPECT(ws.impl_->rd_block.is_locked());
ws.async_close({},
[&](error_code ec)
{
BEAST_EXPECT(++count == 2);
});
BEAST_EXPECT(ws.is_open());
- BEAST_EXPECT(ws.wr_block_.is_locked());
+ BEAST_EXPECT(ws.impl_->wr_block.is_locked());
BEAST_EXPECT(count == 0);
ioc.run();
BEAST_EXPECT(count == 3);
});
// Four-way: close, read, write, ping
- doFailLoop([&](test::fail_counter& fc)
+ doFailLoop([&](test::fail_count& fc)
{
echo_server es{log};
- boost::asio::io_context ioc;
+ std::string const s = "Hello, world!";
+ multi_buffer b;
+ net::io_context ioc;
stream<test::stream> ws{ioc, fc};
ws.next_layer().connect(es.stream());
ws.handshake("localhost", "/");
std::size_t count = 0;
- std::string const s = "Hello, world!";
- multi_buffer b;
ws.async_close({},
[&](error_code ec)
{
ws.async_read(b,
[&](error_code ec, std::size_t)
{
- if(ec != boost::asio::error::operation_aborted)
+ if(ec != net::error::operation_aborted)
BOOST_THROW_EXCEPTION(
system_error{ec});
++count;
});
- ws.async_write(buffer(s),
+ ws.async_write(net::buffer(s),
[&](error_code ec, std::size_t)
{
- if(ec != boost::asio::error::operation_aborted)
+ if(ec != net::error::operation_aborted)
BOOST_THROW_EXCEPTION(
system_error{ec});
++count;
ws.async_ping({},
[&](error_code ec)
{
- if(ec != boost::asio::error::operation_aborted)
+ if(ec != net::error::operation_aborted)
BOOST_THROW_EXCEPTION(
system_error{ec});
++count;
});
// Four-way: read, write, ping, close
- doFailLoop([&](test::fail_counter& fc)
+ doFailLoop([&](test::fail_count& fc)
{
echo_server es{log};
- boost::asio::io_context ioc;
+ multi_buffer b;
+ std::string const s = "Hello, world!";
+ net::io_context ioc;
stream<test::stream> ws{ioc, fc};
ws.next_layer().connect(es.stream());
ws.handshake("localhost", "/");
std::size_t count = 0;
- std::string const s = "Hello, world!";
- multi_buffer b;
ws.async_read(b,
[&](error_code ec, std::size_t)
{
- if(ec && ec != boost::asio::error::operation_aborted)
+ if(ec && ec != net::error::operation_aborted)
{
BEAST_EXPECTS(ec, ec.message());
BOOST_THROW_EXCEPTION(
system_error{ec});
}
if(! ec)
- BEAST_EXPECT(to_string(b.data()) == s);
+ BEAST_EXPECT(buffers_to_string(b.data()) == s);
++count;
if(count == 4)
BEAST_EXPECT(
- ec == boost::asio::error::operation_aborted);
+ ec == net::error::operation_aborted);
});
- ws.async_write(buffer(s),
+ ws.async_write(net::buffer(s),
[&](error_code ec, std::size_t n)
{
if(ec)
ws.async_ping({},
[&](error_code ec)
{
- if(ec != boost::asio::error::operation_aborted)
+ if(ec != net::error::operation_aborted)
{
BEAST_EXPECTS(ec, ec.message());
BOOST_THROW_EXCEPTION(
});
// Four-way: ping, read, write, close
- doFailLoop([&](test::fail_counter& fc)
+ doFailLoop([&](test::fail_count& fc)
{
echo_server es{log};
- boost::asio::io_context ioc;
+ multi_buffer b;
+ std::string const s = "Hello, world!";
+ net::io_context ioc;
stream<test::stream> ws{ioc, fc};
ws.next_layer().connect(es.stream());
ws.handshake("localhost", "/");
std::size_t count = 0;
- std::string const s = "Hello, world!";
- multi_buffer b;
ws.async_ping({},
[&](error_code ec)
{
ws.async_read(b,
[&](error_code ec, std::size_t)
{
- if(ec != boost::asio::error::operation_aborted)
+ if(ec != net::error::operation_aborted)
BOOST_THROW_EXCEPTION(
system_error{ec});
++count;
});
- ws.async_write(buffer(s),
+ ws.async_write(net::buffer(s),
[&](error_code ec, std::size_t)
{
- if(ec != boost::asio::error::operation_aborted)
+ if(ec != net::error::operation_aborted)
BOOST_THROW_EXCEPTION(
system_error{ec});
++count;
});
}
- void
- testContHook()
- {
- struct handler
- {
- void operator()(error_code) {}
- };
-
- stream<test::stream> ws{ioc_};
- stream<test::stream>::close_op<handler> op{
- handler{}, ws, {}};
- using boost::asio::asio_handler_is_continuation;
- asio_handler_is_continuation(&op);
- }
-
void
testMoveOnly()
{
- boost::asio::io_context ioc;
+ net::io_context ioc;
stream<test::stream> ws{ioc};
ws.async_close({}, move_only_handler{});
}
}
};
- void
- testAsioHandlerInvoke()
- {
- // make sure things compile, also can set a
- // breakpoint in asio_handler_invoke to make sure
- // it is instantiated.
- boost::asio::io_context ioc;
- boost::asio::io_service::strand s{ioc};
- stream<test::stream> ws{ioc};
- ws.async_close({}, s.wrap(copyable_handler{}));
- }
-
void
run() override
{
testClose();
+ testTimeout();
testSuspend();
- testContHook();
testMoveOnly();
- testAsioHandlerInvoke();
}
};