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/core/stream_traits.hpp>
13 #include <boost/beast/_experimental/unit_test/suite.hpp>
14 #include <boost/beast/core/error.hpp>
15 #include <boost/beast/_experimental/test/stream.hpp>
16 #include <boost/beast/core/string.hpp>
17 #include <boost/asio/io_context.hpp>
18 #include <boost/asio/ip/tcp.hpp>
19 #include <boost/asio/write.hpp>
25 class stream_traits_test
26 : public beast::unit_test::suite
36 std::size_t write_some(T
const&)
42 std::size_t write_some(T
const&, boost::system::error_code
&)
69 ! detail::has_next_layer
<without
>::value
);
72 detail::has_next_layer
<with
<without
>>::value
);
75 detail::has_next_layer
<with
<with
<without
>>>::value
);
82 BEAST_EXPECT(&get_lowest_layer(w
) == &w
);
86 BEAST_EXPECT(&get_lowest_layer(w
) == &w
);
90 BEAST_EXPECT(&get_lowest_layer(w
) == &w
.t
);
93 with
<without
> const w
{};
94 BEAST_EXPECT(&get_lowest_layer(w
) == &w
.t
);
97 with
<with
<without
>> w
{};
98 BEAST_EXPECT(&get_lowest_layer(w
) == &w
.t
.t
);
101 with
<with
<without
>> const w
{};
102 BEAST_EXPECT(&get_lowest_layer(w
) == &w
.t
.t
);
105 with
<with
<with
<without
>>> w
{};
106 BEAST_EXPECT(&get_lowest_layer(w
) == &w
.t
.t
.t
);
109 with
<with
<with
<without
>>> const w
{};
110 BEAST_EXPECT(&get_lowest_layer(w
) == &w
.t
.t
.t
);
114 //--------------------------------------------------------------------------
117 This code implements a <em>SyncWriteStream</em> wrapper which calls
118 `std::terminate` upon any error.
120 template <class NextLayer
>
123 NextLayer next_layer_
;
126 static_assert(is_sync_write_stream
<NextLayer
>::value
,
127 "SyncWriteStream type requirements not met");
129 template<class... Args
>
131 write_stream(Args
&&... args
)
132 : next_layer_(std::forward
<Args
>(args
)...)
136 NextLayer
& next_layer() noexcept
141 NextLayer
const& next_layer() const noexcept
146 template<class ConstBufferSequence
>
148 write_some(ConstBufferSequence
const& buffers
)
151 auto const bytes_transferred
= next_layer_
.write_some(buffers
, ec
);
154 return bytes_transferred
;
157 template<class ConstBufferSequence
>
159 write_some(ConstBufferSequence
const& buffers
, error_code
& ec
)
161 auto const bytes_transferred
= next_layer_
.write_some(buffers
, ec
);
164 return bytes_transferred
;
169 testGetLowestLayerJavadoc()
171 write_stream
<without
> s
;
173 is_sync_write_stream
<without
>::value
);
174 BOOST_STATIC_ASSERT(std::is_same
<
175 decltype(get_lowest_layer(s
)), without
&>::value
);
178 BEAST_EXPECT(static_cast<
179 std::size_t(type::*)(net::const_buffer
)>(
180 &type::write_some
<net::const_buffer
>));
184 //--------------------------------------------------------------------------
192 testExecutorTypeJavadoc()
196 //--------------------------------------------------------------------------
198 struct sync_read_stream
200 template<class MutableBufferSequence
>
201 std::size_t read_some(MutableBufferSequence
const&);
202 template<class MutableBufferSequence
>
203 std::size_t read_some(MutableBufferSequence
const&, error_code
& ec
);
206 struct sync_write_stream
208 template<class ConstBufferSequence
>
209 std::size_t write_some(ConstBufferSequence
const&);
210 template<class ConstBufferSequence
>
211 std::size_t write_some(ConstBufferSequence
const&, error_code
&);
214 struct async_read_stream
216 net::io_context::executor_type
get_executor() noexcept
;
217 template<class MutableBufferSequence
, BOOST_BEAST_ASYNC_TPARAM2 ReadHandler
>
218 void async_read_some(MutableBufferSequence
const&, ReadHandler
&&);
221 struct async_write_stream
223 net::io_context::executor_type
get_executor() noexcept
;
224 template<class ConstBufferSequence
, BOOST_BEAST_ASYNC_TPARAM2 WriteHandler
>
225 void async_write_some(ConstBufferSequence
const&, WriteHandler
&&);
228 struct sync_stream
: sync_read_stream
, sync_write_stream
232 struct async_stream
: async_read_stream
, async_write_stream
234 net::io_context::executor_type
get_executor() noexcept
;
235 template<class MutableBufferSequence
, BOOST_BEAST_ASYNC_TPARAM2 ReadHandler
>
236 void async_read_some(MutableBufferSequence
const&, ReadHandler
&&);
237 template<class ConstBufferSequence
, BOOST_BEAST_ASYNC_TPARAM2 WriteHandler
>
238 void async_write_some(ConstBufferSequence
const&, WriteHandler
&&);
241 BOOST_STATIC_ASSERT(is_sync_read_stream
<sync_read_stream
>::value
);
242 BOOST_STATIC_ASSERT(is_sync_read_stream
<sync_stream
>::value
);
243 BOOST_STATIC_ASSERT(is_sync_write_stream
<sync_write_stream
>::value
);
244 BOOST_STATIC_ASSERT(is_sync_write_stream
<sync_stream
>::value
);
245 BOOST_STATIC_ASSERT(is_sync_stream
<sync_stream
>::value
);
247 BOOST_STATIC_ASSERT(! is_sync_read_stream
<sync_write_stream
>::value
);
248 BOOST_STATIC_ASSERT(! is_sync_write_stream
<sync_read_stream
>::value
);
249 BOOST_STATIC_ASSERT(! is_sync_stream
<async_stream
>::value
);
251 BOOST_STATIC_ASSERT(has_get_executor
<async_read_stream
>::value
);
252 BOOST_STATIC_ASSERT(has_get_executor
<async_write_stream
>::value
);
253 BOOST_STATIC_ASSERT(has_get_executor
<async_stream
>::value
);
255 BOOST_STATIC_ASSERT(! has_get_executor
<sync_read_stream
>::value
);
256 BOOST_STATIC_ASSERT(! has_get_executor
<sync_write_stream
>::value
);
257 BOOST_STATIC_ASSERT(! has_get_executor
<sync_stream
>::value
);
259 BOOST_STATIC_ASSERT(is_async_read_stream
<async_read_stream
>::value
);
260 BOOST_STATIC_ASSERT(is_async_read_stream
<async_stream
>::value
);
261 #if BOOST_WORKAROUND(BOOST_MSVC, < 1910)
262 BOOST_STATIC_ASSERT(is_async_write_stream
<net::ip::tcp::socket
>::value
);
264 BOOST_STATIC_ASSERT(is_async_write_stream
<async_write_stream
>::value
);
266 BOOST_STATIC_ASSERT(is_async_write_stream
<async_stream
>::value
);
267 BOOST_STATIC_ASSERT(is_async_stream
<async_stream
>::value
);
269 BOOST_STATIC_ASSERT(! is_async_write_stream
<async_read_stream
>::value
);
270 BOOST_STATIC_ASSERT(! is_async_read_stream
<async_write_stream
>::value
);
271 BOOST_STATIC_ASSERT(! is_async_stream
<sync_stream
>::value
);
273 //--------------------------------------------------------------------------
283 : t(std::forward
<U
>(u
))
298 net::ip::tcp::socket
sock(ioc
);
299 sock
.open(net::ip::tcp::v4());
300 BEAST_EXPECT(sock
.is_open());
301 close_socket(get_lowest_layer(sock
));
302 BEAST_EXPECT(! sock
.is_open());
305 using type
= layer
<net::ip::tcp::socket
>;
307 layer
.next_layer().open(net::ip::tcp::v4());
308 BEAST_EXPECT(layer
.next_layer().is_open());
309 BOOST_STATIC_ASSERT(detail::has_next_layer
<type
>::value
);
310 BOOST_STATIC_ASSERT((std::is_same
<
311 typename
std::decay
<decltype(get_lowest_layer(layer
))>::type
,
312 lowest_layer_type
<decltype(layer
)>>::value
));
313 BOOST_STATIC_ASSERT(std::is_same
<net::ip::tcp::socket
&,
314 decltype(get_lowest_layer(layer
))>::value
);
315 BOOST_STATIC_ASSERT(std::is_same
<net::ip::tcp::socket
,
316 lowest_layer_type
<decltype(layer
)>>::value
);
317 close_socket(get_lowest_layer(layer
));
318 BEAST_EXPECT(! layer
.next_layer().is_open());
321 test::stream
ts(ioc
);
326 //--------------------------------------------------------------------------
328 template <class WriteStream
>
329 void hello_and_close (WriteStream
& stream
)
331 net::write(stream
, net::const_buffer("Hello, world!", 13));
332 close_socket(get_lowest_layer(stream
));
337 net::ip::tcp::socket sock_
;
340 my_socket(net::io_context
& ioc
)
345 friend void beast_close_socket(my_socket
& s
)
356 BEAST_EXPECT(&stream_traits_test::template hello_and_close
<net::ip::tcp::socket
>);
364 //--------------------------------------------------------------------------
369 testGetLowestLayer();
370 testGetLowestLayerJavadoc();
372 testExecutorTypeJavadoc();
378 BEAST_DEFINE_TESTSUITE(beast
,core
,stream_traits
);