]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/libs/beast/test/beast/core/stream_traits.cpp
import new upstream nautilus stable release 14.2.8
[ceph.git] / ceph / src / boost / libs / beast / test / beast / core / stream_traits.cpp
1 //
2 // Copyright (c) 2016-2019 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/core/stream_traits.hpp>
12
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>
20 #include <utility>
21
22 namespace boost {
23 namespace beast {
24
25 class stream_traits_test
26 : public beast::unit_test::suite
27 {
28 public:
29 struct without
30 {
31 int dummy = 0;
32
33 without() = default;
34
35 template<class T>
36 std::size_t write_some(T const&)
37 {
38 return 0;
39 }
40
41 template<class T>
42 std::size_t write_some(T const&, boost::system::error_code&)
43 {
44 return 0;
45 }
46 };
47
48 template<class T>
49 struct with
50 {
51 T t;
52
53 with() = default;
54
55 T&
56 next_layer()
57 {
58 return t;
59 }
60
61 T const&
62 next_layer() const
63 {
64 return t;
65 }
66 };
67
68 BOOST_STATIC_ASSERT(
69 ! detail::has_next_layer<without>::value);
70
71 BOOST_STATIC_ASSERT(
72 detail::has_next_layer<with<without>>::value);
73
74 BOOST_STATIC_ASSERT(
75 detail::has_next_layer<with<with<without>>>::value);
76
77 void
78 testGetLowestLayer()
79 {
80 {
81 without w{};
82 BEAST_EXPECT(&get_lowest_layer(w) == &w);
83 }
84 {
85 without const w{};
86 BEAST_EXPECT(&get_lowest_layer(w) == &w);
87 }
88 {
89 with<without> w{};
90 BEAST_EXPECT(&get_lowest_layer(w) == &w.t);
91 }
92 {
93 with<without> const w{};
94 BEAST_EXPECT(&get_lowest_layer(w) == &w.t);
95 }
96 {
97 with<with<without>> w{};
98 BEAST_EXPECT(&get_lowest_layer(w) == &w.t.t);
99 }
100 {
101 with<with<without>> const w{};
102 BEAST_EXPECT(&get_lowest_layer(w) == &w.t.t);
103 }
104 {
105 with<with<with<without>>> w{};
106 BEAST_EXPECT(&get_lowest_layer(w) == &w.t.t.t);
107 }
108 {
109 with<with<with<without>>> const w{};
110 BEAST_EXPECT(&get_lowest_layer(w) == &w.t.t.t);
111 }
112 }
113
114 //--------------------------------------------------------------------------
115 /*
116 @par Example
117 This code implements a <em>SyncWriteStream</em> wrapper which calls
118 `std::terminate` upon any error.
119 */
120 template <class NextLayer>
121 class write_stream
122 {
123 NextLayer next_layer_;
124
125 public:
126 static_assert(is_sync_write_stream<NextLayer>::value,
127 "SyncWriteStream type requirements not met");
128
129 template<class... Args>
130 explicit
131 write_stream(Args&&... args)
132 : next_layer_(std::forward<Args>(args)...)
133 {
134 }
135
136 NextLayer& next_layer() noexcept
137 {
138 return next_layer_;
139 }
140
141 NextLayer const& next_layer() const noexcept
142 {
143 return next_layer_;
144 }
145
146 template<class ConstBufferSequence>
147 std::size_t
148 write_some(ConstBufferSequence const& buffers)
149 {
150 error_code ec;
151 auto const bytes_transferred = next_layer_.write_some(buffers, ec);
152 if(ec)
153 std::terminate();
154 return bytes_transferred;
155 }
156
157 template<class ConstBufferSequence>
158 std::size_t
159 write_some(ConstBufferSequence const& buffers, error_code& ec)
160 {
161 auto const bytes_transferred = next_layer_.write_some(buffers, ec);
162 if(ec)
163 std::terminate();
164 return bytes_transferred;
165 }
166 };
167
168 void
169 testGetLowestLayerJavadoc()
170 {
171 write_stream<without> s;
172 BOOST_STATIC_ASSERT(
173 is_sync_write_stream<without>::value);
174 BOOST_STATIC_ASSERT(std::is_same<
175 decltype(get_lowest_layer(s)), without&>::value);
176
177 #if 0
178 BEAST_EXPECT(static_cast<
179 std::size_t(type::*)(net::const_buffer)>(
180 &type::write_some<net::const_buffer>));
181 #endif
182 }
183
184 //--------------------------------------------------------------------------
185
186 void
187 testExecutorType()
188 {
189 }
190
191 void
192 testExecutorTypeJavadoc()
193 {
194 }
195
196 //--------------------------------------------------------------------------
197
198 struct sync_read_stream
199 {
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);
204 };
205
206 struct sync_write_stream
207 {
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&);
212 };
213
214 struct async_read_stream
215 {
216 net::io_context::executor_type get_executor() noexcept;
217 template<class MutableBufferSequence, class ReadHandler>
218 void async_read_some(MutableBufferSequence const&, ReadHandler&&);
219 };
220
221 struct async_write_stream
222 {
223 net::io_context::executor_type get_executor() noexcept;
224 template<class ConstBufferSequence, class WriteHandler>
225 void async_write_some(ConstBufferSequence const&, WriteHandler&&);
226 };
227
228 struct sync_stream : sync_read_stream, sync_write_stream
229 {
230 };
231
232 struct async_stream : async_read_stream, async_write_stream
233 {
234 net::io_context::executor_type get_executor() noexcept;
235 template<class MutableBufferSequence, class ReadHandler>
236 void async_read_some(MutableBufferSequence const&, ReadHandler&&);
237 template<class ConstBufferSequence, class WriteHandler>
238 void async_write_some(ConstBufferSequence const&, WriteHandler&&);
239 };
240
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);
246
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);
250
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);
254
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);
258
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);
263 #else
264 BOOST_STATIC_ASSERT(is_async_write_stream<async_write_stream>::value);
265 #endif
266 BOOST_STATIC_ASSERT(is_async_write_stream<async_stream>::value);
267 BOOST_STATIC_ASSERT(is_async_stream<async_stream>::value);
268
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);
272
273 //--------------------------------------------------------------------------
274
275 template<class T>
276 struct layer
277 {
278 T t;
279
280 template<class U>
281 explicit
282 layer(U&& u)
283 : t(std::forward<U>(u))
284 {
285 }
286
287 T& next_layer()
288 {
289 return t;
290 }
291 };
292
293 void
294 testClose()
295 {
296 net::io_context ioc;
297 {
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());
303 }
304 {
305 using type = layer<net::ip::tcp::socket>;
306 type layer(ioc);
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());
319 }
320 {
321 test::stream ts(ioc);
322 close_socket(ts);
323 }
324 }
325
326 //--------------------------------------------------------------------------
327
328 template <class WriteStream>
329 void hello_and_close (WriteStream& stream)
330 {
331 net::write(stream, net::const_buffer("Hello, world!", 13));
332 close_socket(get_lowest_layer(stream));
333 }
334
335 class my_socket
336 {
337 net::ip::tcp::socket sock_;
338
339 public:
340 my_socket(net::io_context& ioc)
341 : sock_(ioc)
342 {
343 }
344
345 friend void beast_close_socket(my_socket& s)
346 {
347 error_code ec;
348 s.sock_.close(ec);
349 // ignore the error
350 }
351 };
352
353 void
354 testCloseJavadoc()
355 {
356 BEAST_EXPECT(&stream_traits_test::template hello_and_close<net::ip::tcp::socket>);
357 {
358 net::io_context ioc;
359 my_socket s(ioc);
360 close_socket(s);
361 }
362 }
363
364 //--------------------------------------------------------------------------
365
366 void
367 run() override
368 {
369 testGetLowestLayer();
370 testGetLowestLayerJavadoc();
371 testExecutorType();
372 testExecutorTypeJavadoc();
373 testClose();
374 testCloseJavadoc();
375 }
376 };
377
378 BEAST_DEFINE_TESTSUITE(beast,core,stream_traits);
379
380 } // beast
381 } // boost