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/flat_stream.hpp>
12 
13 #include "stream_tests.hpp"
14 
15 #include <boost/beast/_experimental/unit_test/suite.hpp>
16 #include <boost/beast/_experimental/test/stream.hpp>
17 #include <boost/beast/core/role.hpp>
18 #include <initializer_list>
19 #include <vector>
20 
21 namespace boost {
22 namespace beast {
23 
24 class flat_stream_test : public unit_test::suite
25 {
26 public:
27     void
testMembers()28     testMembers()
29     {
30         net::io_context ioc;
31 
32         test_sync_stream<flat_stream<test::stream>>();
33 
34         test_async_stream<flat_stream<test::stream>>();
35 
36         // read/write
37 
38         {
39             error_code ec;
40             flat_stream<test::stream> s(ioc);
41             {
42                 // VFALCO Hack to make test stream code = eof
43                 test::stream ts(ioc);
44                 s.next_layer().connect(ts);
45             }
46             char buf[1];
47             net::mutable_buffer m1 = net::buffer(buf);
48 
49             BEAST_EXPECT(s.read_some(net::mutable_buffer{}) == 0);
50             BEAST_EXPECT(s.read_some(net::mutable_buffer{}, ec) == 0);
51             BEAST_EXPECTS(! ec, ec.message());
52 
53             try
54             {
55                 s.read_some(m1);
56                 BEAST_FAIL();
57             }
58             catch(std::exception const&)
59             {
60                 BEAST_PASS();
61             }
62             catch(...)
63             {
64                 BEAST_FAIL();
65             }
66 
67             BEAST_EXPECT(s.write_some(net::const_buffer{}) == 0);
68             BEAST_EXPECT(s.write_some(net::const_buffer{}, ec) == 0);
69             BEAST_EXPECTS(! ec, ec.message());
70 
71             try
72             {
73                 s.write_some(m1);
74                 BEAST_FAIL();
75             }
76             catch(std::exception const&)
77             {
78                 BEAST_PASS();
79             }
80             catch(...)
81             {
82                 BEAST_FAIL();
83             }
84 
85             bool invoked;
86 
87             invoked = false;
88             s.async_read_some(net::mutable_buffer{},
89                 [&](error_code ec, std::size_t)
90                 {
91                     invoked = true;
92                     BEAST_EXPECTS(! ec, ec.message());
93                 });
94             ioc.run();
95             ioc.restart();
96             BEAST_EXPECT(invoked);
97 
98             invoked = false;
99             s.async_write_some(net::const_buffer{},
100                 [&](error_code ec, std::size_t)
101                 {
102                     invoked = true;
103                     BEAST_EXPECTS(! ec, ec.message());
104                 });
105             ioc.run();
106             ioc.restart();
107             BEAST_EXPECT(invoked);
108         }
109 
110         // stack_write_some
111 
112         {
113             char b[detail::flat_stream_base::max_size];
114             std::array<net::const_buffer, 3> bs;
115             bs[0] = net::const_buffer(b, 100);
116             bs[1] = net::const_buffer(b + 100, 200);
117             bs[2] = net::const_buffer(b + 100 + 200, 300);
118             BEAST_EXPECT(buffer_bytes(bs) <=
119                 detail::flat_stream_base::max_stack);
120             flat_stream<test::stream> s(ioc);
121             error_code ec;
122             s.write_some(bs, ec);
123         }
124 
125         // write_some
126 
127         {
128             char b[detail::flat_stream_base::max_size];
129             std::array<net::const_buffer, 2> bs;
130             bs[0] = net::const_buffer(b,
131                 detail::flat_stream_base::max_stack);
132             bs[1] = net::const_buffer(b + bs[0].size(), 1024);
133             BEAST_EXPECT(buffer_bytes(bs) <=
134                 detail::flat_stream_base::max_size);
135             flat_stream<test::stream> s(ioc);
136             error_code ec;
137             s.write_some(bs, ec);
138         }
139 
140         // async_write_some
141 
142         {
143             char b[detail::flat_stream_base::max_size];
144             std::array<net::const_buffer, 2> bs;
145             bs[0] = net::const_buffer(b,
146                 detail::flat_stream_base::max_stack);
147             bs[1] = net::const_buffer(b + bs[0].size(), 1024);
148             BEAST_EXPECT(buffer_bytes(bs) <=
149                 detail::flat_stream_base::max_size);
150             flat_stream<test::stream> s(ioc);
151             s.async_write_some(bs,
152                 [](error_code, std::size_t)
153                 {
154                 });
155         }
156 
157         // teardown
158 
159         {
160             test::stream ts(ioc);
161             flat_stream<test::stream> s(ioc);
162             ts.connect(s.next_layer());
163             error_code ec;
164             teardown(role_type::client, s, ec);
165         }
166 
167         {
168             test::stream ts(ioc);
169             flat_stream<test::stream> s(ioc);
170             ts.connect(s.next_layer());
171             async_teardown(role_type::client, s,
172                 [](error_code)
173                 {
174                 });
175         }
176     }
177 
178     void
testSplit()179     testSplit()
180     {
181         auto const check =
182             [&](
183                 std::initializer_list<int> v0,
184                 std::size_t limit,
185                 unsigned long count,
186                 bool copy)
187             {
188                 std::vector<net::const_buffer> v;
189                 v.reserve(v0.size());
190                 for(auto const n : v0)
191                     v.emplace_back("", n);
192                 auto const result =
193                     boost::beast::detail::flat_stream_base::flatten(v, limit);
194                 BEAST_EXPECT(result.size == count);
195                 BEAST_EXPECT(result.flatten == copy);
196                 return result;
197             };
198         check({},           1,    0, false);
199         check({1,2},        1,    1, false);
200         check({1,2},        2,    1, false);
201         check({1,2},        3,    3, true);
202         check({1,2},        4,    3, true);
203         check({1,2,3},      1,    1, false);
204         check({1,2,3},      2,    1, false);
205         check({1,2,3},      3,    3, true);
206         check({1,2,3},      4,    3, true);
207         check({1,2,3},      7,    6, true);
208         check({1,2,3,4},    3,    3, true);
209     }
210 
211     void
run()212     run() override
213     {
214         testMembers();
215         testSplit();
216     }
217 };
218 
219 BEAST_DEFINE_TESTSUITE(beast,core,flat_stream);
220 
221 } // beast
222 } // boost
223