Files
boost_beast/test/beast/core/stream_socket.cpp
T

280 lines
6.8 KiB
C++
Raw Normal View History

2018-07-28 12:01:15 -07:00
//
// Copyright (c) 2018 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)
//
// Official repository: https://github.com/boostorg/beast
//
// Test that header file is self-contained.
2018-12-20 08:51:43 -08:00
#include <boost/beast/core/stream_socket.hpp>
2018-07-28 12:01:15 -07:00
2018-11-11 14:07:55 -08:00
#include <boost/beast/_experimental/unit_test/suite.hpp>
2018-12-20 08:51:43 -08:00
#include <boost/beast/test/yield_to.hpp>
2018-07-28 12:01:15 -07:00
#include <boost/asio/ip/tcp.hpp>
2018-12-20 08:51:43 -08:00
#include <array>
2018-07-28 12:01:15 -07:00
#include <thread>
namespace boost {
namespace beast {
2018-12-20 08:51:43 -08:00
class stream_socket_test
2018-07-28 12:01:15 -07:00
: public beast::unit_test::suite
, public test::enable_yield_to
{
public:
class server
{
std::ostream& log_;
2018-11-30 14:58:38 -08:00
net::io_context ioc_;
net::ip::tcp::acceptor acceptor_;
net::ip::tcp::socket socket_;
2018-07-28 12:01:15 -07:00
std::thread t_;
void
fail(error_code ec, string_view what)
{
2018-11-30 14:58:38 -08:00
if(ec != net::error::operation_aborted)
2018-07-28 12:01:15 -07:00
log_ << what << ": " << ec.message() << "\n";
}
public:
server(
2018-11-30 14:58:38 -08:00
net::ip::tcp::endpoint ep,
2018-07-28 12:01:15 -07:00
std::ostream& log)
: log_(log)
, ioc_(1)
, acceptor_(ioc_)
, socket_(ioc_)
{
boost::system::error_code ec;
acceptor_.open(ep.protocol(), ec);
if(ec)
{
fail(ec, "open");
return;
}
acceptor_.set_option(
2018-11-30 14:58:38 -08:00
net::socket_base::reuse_address(true), ec);
2018-07-28 12:01:15 -07:00
if(ec)
{
fail(ec, "set_option");
return;
}
acceptor_.bind(ep, ec);
if(ec)
{
fail(ec, "bind");
return;
}
acceptor_.listen(
2018-11-30 14:58:38 -08:00
net::socket_base::max_listen_connections, ec);
2018-07-28 12:01:15 -07:00
if(ec)
{
fail(ec, "listen");
return;
}
acceptor_.async_accept(socket_,
[this](error_code ec){ this->on_accept(ec); });
t_ = std::thread([this]{ ioc_.run(); });
}
~server()
{
ioc_.stop();
t_.join();
}
private:
class session
: public std::enable_shared_from_this<session>
{
2018-11-30 14:58:38 -08:00
net::ip::tcp::socket socket_;
2018-07-28 12:01:15 -07:00
public:
session(
2018-11-30 14:58:38 -08:00
net::ip::tcp::socket sock,
2018-11-22 20:49:30 -08:00
std::ostream&)
2018-07-28 12:01:15 -07:00
: socket_(std::move(sock))
{
}
void
run()
{
socket_.async_wait(
2018-11-30 14:58:38 -08:00
net::socket_base::wait_read,
2018-07-28 12:01:15 -07:00
std::bind(
&session::on_read,
shared_from_this(),
std::placeholders::_1));
}
protected:
void
on_read(error_code ec)
{
boost::ignore_unused(ec);
}
};
void
on_accept(error_code ec)
{
if(! acceptor_.is_open())
return;
if(ec)
fail(ec, "accept");
else
std::make_shared<session>(
std::move(socket_), log_)->run();
acceptor_.async_accept(socket_,
2018-11-23 18:14:03 -08:00
[this](error_code ec)
{
this->on_accept(ec);
});
2018-07-28 12:01:15 -07:00
}
};
void
testAsync()
{
2018-11-30 14:58:38 -08:00
net::ip::tcp::endpoint ep(
net::ip::make_address("127.0.0.1"), 8080);
2018-07-28 12:01:15 -07:00
server srv(ep, log);
{
2018-11-30 14:58:38 -08:00
net::io_context ioc;
2018-12-20 08:51:43 -08:00
stream_socket s(ioc);
2018-07-28 12:01:15 -07:00
s.next_layer().connect(ep);
char buf[32];
2018-12-20 08:51:43 -08:00
error_code ec;
s.expires_after(std::chrono::seconds(1));
2018-11-30 14:58:38 -08:00
s.async_read_some(net::buffer(buf),
2018-12-20 08:51:43 -08:00
[&ec](error_code ec_, std::size_t)
2018-07-28 12:01:15 -07:00
{
2018-12-20 08:51:43 -08:00
ec = ec_;
2018-07-28 12:01:15 -07:00
});
ioc.run();
2018-12-20 08:51:43 -08:00
BEAST_EXPECTS(
ec == error::timeout, ec.message());
}
}
void
testConnect()
{
using es_t =
std::array<net::ip::tcp::endpoint, 2>;
{
net::io_context ioc;
stream_socket s(ioc);
beast::async_connect(s, es_t{},
[](error_code, es_t::value_type)
{
});
}
{
net::io_context ioc;
stream_socket s(ioc);
beast::async_connect(s, es_t{},
[](error_code, es_t::value_type)
{
return true;
},
[](error_code, es_t::value_type)
{
});
}
{
es_t es;
net::io_context ioc;
stream_socket s(ioc);
beast::async_connect(s, es.begin(), es.end(),
[](error_code, es_t::iterator)
{
});
}
{
es_t es;
net::io_context ioc;
stream_socket s(ioc);
beast::async_connect(s, es.begin(), es.end(),
[](error_code, es_t::value_type)
{
return true;
},
[](error_code, es_t::iterator)
{
});
}
pass();
}
void callConnects()
{
using es_t =
std::array<net::ip::tcp::endpoint, 2>;
{
net::io_context ioc;
stream_socket s(ioc);
async_connect(s, es_t{},
[](error_code, es_t::value_type)
{
});
}
{
net::io_context ioc;
stream_socket s(ioc);
async_connect(s, es_t{},
[](error_code, es_t::value_type)
{
return true;
},
[](error_code, es_t::value_type)
{
});
}
{
es_t es;
net::io_context ioc;
stream_socket s(ioc);
async_connect(s, es.begin(), es.end(),
[](error_code, es_t::iterator)
{
});
}
{
es_t es;
net::io_context ioc;
stream_socket s(ioc);
async_connect(s, es.begin(), es.end(),
[](error_code, es_t::value_type)
{
return true;
},
[](error_code, es_t::iterator)
{
});
2018-07-28 12:01:15 -07:00
}
}
void
run()
{
testAsync();
2018-12-20 08:51:43 -08:00
testConnect();
2018-07-28 12:01:15 -07:00
}
};
2018-12-20 08:51:43 -08:00
BEAST_DEFINE_TESTSUITE(beast,core,stream_socket);
2018-07-28 12:01:15 -07:00
} // beast
} // boost