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/buffered_read_stream.hpp>
12
13#include <boost/beast/core/multi_buffer.hpp>
14#include <boost/beast/_experimental/test/stream.hpp>
15#include <boost/beast/_experimental/unit_test/suite.hpp>
16#include <boost/beast/core/bind_handler.hpp>
17#include <boost/beast/test/yield_to.hpp>
18#include <boost/asio/buffer.hpp>
19#include <boost/asio/execution.hpp>
20#include <boost/asio/io_context.hpp>
21#include <boost/asio/any_io_executor.hpp>
22#include <boost/asio/read.hpp>
23#include <boost/asio/strand.hpp>
24#include <boost/optional.hpp>
25#if BOOST_ASIO_HAS_CO_AWAIT
26#include <boost/asio/use_awaitable.hpp>
27#endif
28
29namespace boost {
30namespace beast {
31
32class buffered_read_stream_test
33 : public unit_test::suite
34 , public test::enable_yield_to
35{
36 using self = buffered_read_stream_test;
37
38public:
39 void testSpecialMembers()
40 {
41 net::io_context ioc;
42 {
43 buffered_read_stream<test::stream, multi_buffer> srs(ioc);
44 buffered_read_stream<test::stream, multi_buffer> srs2(std::move(srs));
45 srs = std::move(srs2);
46#if defined(BOOST_ASIO_USE_TS_EXECUTOR_AS_DEFAULT)
47 BEAST_EXPECT(&srs.get_executor().context() == &ioc);
48 BEAST_EXPECT(
49 &srs.get_executor().context() ==
50 &srs2.get_executor().context());
51#else
52 BEAST_EXPECT(&net::query(srs.get_executor(), net::execution::context) == &ioc);
53 BEAST_EXPECT(
54 &net::query(srs.get_executor(), net::execution::context) ==
55 &net::query(srs2.get_executor(), net::execution::context));
56#endif
57 }
58 {
59 test::stream ts{ioc};
60 buffered_read_stream<test::stream&, multi_buffer> srs(ts);
61 }
62 }
63
64 struct loop : std::enable_shared_from_this<loop>
65 {
66 static std::size_t constexpr limit = 100;
67 std::string s_;
68 std::size_t n_ = 0;
69 std::size_t cap_;
70 unit_test::suite& suite_;
71 net::io_context& ioc_;
72 boost::optional<test::stream> ts_;
73 boost::optional<test::fail_count> fc_;
74 boost::optional<buffered_read_stream<
75 test::stream&, multi_buffer>> brs_;
76
77 loop(
78 unit_test::suite& suite,
79 net::io_context& ioc,
80 std::size_t cap)
81 : cap_(cap)
82 , suite_(suite)
83 , ioc_(ioc)
84 {
85 }
86
87 void
88 run()
89 {
90 do_read();
91 }
92
93 void
94 on_read(error_code ec, std::size_t)
95 {
96 if(! ec)
97 {
98 suite_.expect(shouldBeTrue: s_ ==
99 "Hello, world!", __FILE__, __LINE__);
100 return;
101 }
102 ++n_;
103 if(! suite_.expect(shouldBeTrue: n_ < limit, __FILE__, __LINE__))
104 return;
105 s_.clear();
106 do_read();
107 }
108
109 void
110 do_read()
111 {
112 s_.resize(n: 13);
113 fc_.emplace(args&: n_);
114 ts_.emplace(args&: ioc_, args&: *fc_, args: ", world!");
115 brs_.emplace(args&: *ts_);
116 brs_->buffer().commit(n: net::buffer_copy(
117 target: brs_->buffer().prepare(n: 5), source: net::buffer(data: "Hello", max_size_in_bytes: 5)));
118 net::async_read(s&: *brs_,
119 buffers: net::buffer(data: &s_[0], size_in_bytes: s_.size()),
120 token: bind_front_handler(
121 handler: &loop::on_read,
122 args: shared_from_this()));
123 }
124 };
125
126 void
127 testAsyncLoop()
128 {
129 std::make_shared<loop>(*this, ioc_, 0)->run();
130 std::make_shared<loop>(*this, ioc_, 3)->run();
131 }
132
133 void testRead(yield_context do_yield)
134 {
135 static std::size_t constexpr limit = 100;
136 std::size_t n;
137 std::string s;
138 s.resize(n: 13);
139
140 for(n = 0; n < limit; ++n)
141 {
142 test::fail_count fc{n};
143 test::stream ts(ioc_, fc, ", world!");
144 buffered_read_stream<
145 test::stream&, multi_buffer> srs(ts);
146 srs.buffer().commit(n: net::buffer_copy(
147 target: srs.buffer().prepare(n: 5), source: net::buffer(data: "Hello", max_size_in_bytes: 5)));
148 error_code ec = test::error::test_failure;
149 net::read(s&: srs, buffers: net::buffer(data: &s[0], size_in_bytes: s.size()), ec);
150 if(! ec)
151 {
152 BEAST_EXPECT(s == "Hello, world!");
153 break;
154 }
155 }
156 BEAST_EXPECT(n < limit);
157
158 for(n = 0; n < limit; ++n)
159 {
160 test::fail_count fc{n};
161 test::stream ts(ioc_, fc, ", world!");
162 buffered_read_stream<
163 test::stream&, multi_buffer> srs(ts);
164 srs.capacity(size: 3);
165 srs.buffer().commit(n: net::buffer_copy(
166 target: srs.buffer().prepare(n: 5), source: net::buffer(data: "Hello", max_size_in_bytes: 5)));
167 error_code ec = test::error::test_failure;
168 net::read(s&: srs, buffers: net::buffer(data: &s[0], size_in_bytes: s.size()), ec);
169 if(! ec)
170 {
171 BEAST_EXPECT(s == "Hello, world!");
172 break;
173 }
174 }
175 BEAST_EXPECT(n < limit);
176
177 for(n = 0; n < limit; ++n)
178 {
179 test::fail_count fc{n};
180 test::stream ts(ioc_, fc, ", world!");
181 buffered_read_stream<
182 test::stream&, multi_buffer> srs(ts);
183 srs.buffer().commit(n: net::buffer_copy(
184 target: srs.buffer().prepare(n: 5), source: net::buffer(data: "Hello", max_size_in_bytes: 5)));
185 error_code ec = test::error::test_failure;
186 net::async_read(
187 srs, net::buffer(data: &s[0], size_in_bytes: s.size()), do_yield[ec]);
188 if(! ec)
189 {
190 BEAST_EXPECT(s == "Hello, world!");
191 break;
192 }
193 }
194 BEAST_EXPECT(n < limit);
195
196 for(n = 0; n < limit; ++n)
197 {
198 test::fail_count fc{n};
199 test::stream ts(ioc_, fc, ", world!");
200 buffered_read_stream<
201 test::stream&, multi_buffer> srs(ts);
202 srs.capacity(size: 3);
203 srs.buffer().commit(n: net::buffer_copy(
204 target: srs.buffer().prepare(n: 5), source: net::buffer(data: "Hello", max_size_in_bytes: 5)));
205 error_code ec = test::error::test_failure;
206 net::async_read(
207 srs, net::buffer(data: &s[0], size_in_bytes: s.size()), do_yield[ec]);
208 if(! ec)
209 {
210 BEAST_EXPECT(s == "Hello, world!");
211 break;
212 }
213 }
214 BEAST_EXPECT(n < limit);
215 }
216
217 struct copyable_handler
218 {
219 template<class... Args>
220 void
221 operator()(Args&&...) const
222 {
223 }
224 };
225
226#if BOOST_ASIO_HAS_CO_AWAIT
227 void testAwaitableCompiles(
228 buffered_read_stream<test::stream, flat_buffer>& stream,
229 net::mutable_buffer rxbuf,
230 net::const_buffer txbuf)
231 {
232 static_assert(std::is_same_v<
233 net::awaitable<std::size_t>, decltype(
234 stream.async_read_some(rxbuf, net::use_awaitable))>);
235
236 static_assert(std::is_same_v<
237 net::awaitable<std::size_t>, decltype(
238 stream.async_write_some(txbuf, net::use_awaitable))>);
239 }
240#endif
241
242 void run() override
243 {
244 testSpecialMembers();
245
246 yield_to([&](yield_context yield)
247 {
248 testRead(yield);
249 });
250 testAsyncLoop();
251
252#if BOOST_ASIO_HAS_CO_AWAIT
253 boost::ignore_unused(&buffered_read_stream_test::testAwaitableCompiles);
254#endif
255 }
256};
257
258BEAST_DEFINE_TESTSUITE(beast,core,buffered_read_stream);
259
260} // beast
261} // boost
262

source code of boost/libs/beast/test/beast/core/buffered_read_stream.cpp