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/buffers_cat.hpp>
12
13#include "test_buffer.hpp"
14
15#include <boost/beast/_experimental/unit_test/suite.hpp>
16#include <boost/beast/core/buffer_traits.hpp>
17#include <boost/beast/core/buffers_prefix.hpp>
18#include <boost/beast/core/buffers_suffix.hpp>
19#include <boost/asio/buffer.hpp>
20#include <boost/asio/streambuf.hpp>
21#include <iterator>
22#include <list>
23#include <type_traits>
24#include <vector>
25
26namespace boost {
27namespace beast {
28
29class buffers_cat_test : public unit_test::suite
30{
31public:
32 void
33 testDefaultIterators()
34 {
35 // default ctor is one past the end
36 char c[2] = {};
37 auto bs = buffers_cat(
38 b1: net::const_buffer(&c[0], 1),
39 bn: net::const_buffer(&c[1], 1));
40 decltype(bs)::const_iterator it;
41 decltype(bs)::const_iterator it2;
42 BEAST_EXPECT(it == it2);
43 BEAST_EXPECT(it2 == it);
44 it = bs.end();
45 it2 = bs.end();
46 BEAST_EXPECT(it == it2);
47 BEAST_EXPECT(it2 == it);
48 decltype(bs)::const_iterator it3(it2);
49 BEAST_EXPECT(it3 == it2);
50 it = bs.begin();
51 BEAST_EXPECT(it != it3);
52 it = it3;
53 BEAST_EXPECT(it == it3);
54
55 // dereferencing default iterator should throw
56 try
57 {
58 it = {};
59 (void)*it;
60 fail();
61 }
62 catch(std::logic_error const&)
63 {
64 pass();
65 }
66 catch(...)
67 {
68 fail();
69 }
70 }
71
72 void
73 testBufferSequence()
74 {
75 string_view s = "Hello, world!";
76 net::const_buffer b1(s.data(), 6);
77 net::const_buffer b2(
78 s.data() + b1.size(), s.size() - b1.size());
79 test_buffer_sequence(buffers: buffers_cat(b1, bn: b2));
80 }
81
82 template<class F>
83 void
84 checkException(F&& f)
85 {
86 try
87 {
88 f();
89 fail(reason: "missing exception", __FILE__, __LINE__);
90 }
91 catch(std::logic_error const&)
92 {
93 pass();
94 }
95 catch(...)
96 {
97 fail(reason: "wrong exception", __FILE__, __LINE__);
98 }
99 }
100
101 void
102 testExceptions()
103 {
104 net::const_buffer b1{"He", 2};
105 net::const_buffer b2{"llo,", 4};
106 net::const_buffer b3{" world!", 7};
107
108 auto const b = beast::buffers_cat(b1, bn: b2, bn: b3);
109 using type = decltype(b);
110
111 // Dereferencing a default-constructed iterator
112 checkException(
113 f: []
114 {
115 (void)*(type::const_iterator{});
116 });
117
118 // Incrementing a default-constructed iterator
119 checkException(
120 f: []
121 {
122 ++(type::const_iterator{});
123 });
124
125 // Decrementing a default-constructed iterator
126 checkException(
127 f: []
128 {
129 --(type::const_iterator{});
130 });
131
132 // Decrementing an iterator to the beginning
133 checkException(
134 f: [&b]
135 {
136 --b.begin();
137 });
138
139 // Dereferencing an iterator to the end
140 checkException(
141 f: [&b]
142 {
143 *b.end();
144 });
145
146 // Incrementing an iterator to the end
147 checkException(
148 f: [&b]
149 {
150 ++b.end();
151 });
152 }
153
154 void
155 testEmpty()
156 {
157 struct empty_sequence
158 {
159 using value_type = net::const_buffer;
160 using const_iterator = value_type const*;
161
162 const_iterator
163 begin() const noexcept
164 {
165 return &v_;
166 }
167
168 const_iterator
169 end() const noexcept
170 {
171 return begin();
172 }
173
174 private:
175 value_type v_;
176 };
177
178 {
179 net::const_buffer b0{};
180 net::const_buffer b1{"He", 2};
181 net::const_buffer b2{"llo,", 4};
182 net::const_buffer b3{" world!", 7};
183
184 {
185 auto const b = beast::buffers_cat(b1: b0, bn: b0);
186 BEAST_EXPECT(buffer_bytes(b) == 0);
187 BEAST_EXPECT(buffers_length(b) == 0);
188 }
189 {
190 auto const b = beast::buffers_cat(b1: b0, bn: b0, bn: b0, bn: b0);
191 BEAST_EXPECT(buffer_bytes(b) == 0);
192 BEAST_EXPECT(buffers_length(b) == 0);
193 }
194 {
195 auto const b = beast::buffers_cat(b1, bn: b2, bn: b3);
196 BEAST_EXPECT(beast::buffers_to_string(b) == "Hello, world!");
197 BEAST_EXPECT(buffers_length(b) == 3);
198 test_buffer_sequence(buffers: b);
199 }
200 {
201 auto const b = beast::buffers_cat(b1: b0, bn: b1, bn: b2, bn: b3);
202 BEAST_EXPECT(beast::buffers_to_string(b) == "Hello, world!");
203 BEAST_EXPECT(buffers_length(b) == 3);
204 test_buffer_sequence(buffers: b);
205 }
206 {
207 auto const b = beast::buffers_cat(b1, bn: b0, bn: b2, bn: b3);
208 BEAST_EXPECT(beast::buffers_to_string(b) == "Hello, world!");
209 BEAST_EXPECT(buffers_length(b) == 3);
210 test_buffer_sequence(buffers: b);
211 }
212 {
213 auto const b = beast::buffers_cat(b1, bn: b2, bn: b0, bn: b3);
214 BEAST_EXPECT(beast::buffers_to_string(b) == "Hello, world!");
215 BEAST_EXPECT(buffers_length(b) == 3);
216 test_buffer_sequence(buffers: b);
217 }
218 {
219 auto const b = beast::buffers_cat(b1, bn: b2, bn: b3, bn: b0);
220 BEAST_EXPECT(beast::buffers_to_string(b) == "Hello, world!");
221 BEAST_EXPECT(buffers_length(b) == 3);
222 test_buffer_sequence(buffers: b);
223 }
224 }
225
226 {
227 auto e1 = net::const_buffer{};
228 auto b1 = std::array<net::const_buffer, 3>{._M_elems: {
229 e1,
230 net::const_buffer{"He", 2},
231 net::const_buffer{"l", 1} }};
232 auto b2 = std::array<net::const_buffer, 3>{._M_elems: {
233 net::const_buffer{"lo", 2},
234 e1,
235 net::const_buffer{", ", 2} }};
236 auto b3 = std::array<net::const_buffer, 3>{._M_elems: {
237 net::const_buffer{"w", 1},
238 net::const_buffer{"orld!", 5},
239 e1 }};
240 {
241 auto const b = beast::buffers_cat(
242 b1: e1, bn: b1, bn: e1, bn: b2, bn: e1, bn: b3, bn: e1);
243 BEAST_EXPECT(beast::buffers_to_string(b) == "Hello, world!");
244 BEAST_EXPECT(buffers_length(b) == 6);
245 }
246 }
247
248 {
249 auto e1 = net::const_buffer{};
250 auto e2 = empty_sequence{};
251 auto b1 = std::array<net::const_buffer, 3>{._M_elems: {
252 e1,
253 net::const_buffer{"He", 2},
254 net::const_buffer{"l", 1} }};
255 auto b2 = std::array<net::const_buffer, 3>{._M_elems: {
256 net::const_buffer{"lo", 2},
257 e1,
258 net::const_buffer{", ", 2} }};
259 auto b3 = std::array<net::const_buffer, 3>{._M_elems: {
260 net::const_buffer{"w", 1},
261 net::const_buffer{"orld!", 5},
262 e1 }};
263 {
264 auto const b = beast::buffers_cat(
265 b1: e2, bn: b1, bn: e2, bn: b2, bn: e2, bn: b3, bn: e2);
266 BEAST_EXPECT(beast::buffers_to_string(b) == "Hello, world!");
267 BEAST_EXPECT(buffers_length(b) == 6);
268 }
269 }
270 }
271
272 void
273 testGccWarning1()
274 {
275 char out[64];
276 std::array<net::const_buffer, 2> buffers{
277 ._M_elems: {net::buffer(data: "Hello, "), net::buffer(data: "world!")}};
278 std::size_t i = 3;
279 buffers_suffix<std::array<net::const_buffer, 2>> cb(buffers);
280 cb.consume(amount: i);
281 net::buffer_copy(
282 target: net::buffer(data&: out),
283 source: buffers_cat(b1: cb, bn: cb));
284 }
285
286 // VFALCO Some version of g++ incorrectly complain about
287 // uninitialized values when buffers_cat and
288 // buffers_prefix and/or buffers_suffix are used
289 // together.
290 void
291 testGccWarning2()
292 {
293 char out[64];
294 net::const_buffer buffers("Hello, world!", 13);
295 std::size_t i = 3;
296 buffers_suffix<net::const_buffer> cb{buffers};
297 cb.consume(amount: i);
298 net::buffer_copy(
299 target: net::buffer(data&: out),
300 source: buffers_cat(b1: buffers_prefix(size: i, buffers), bn: cb));
301 }
302
303 void
304 testSingleBuffer()
305 {
306 char c[1] = {};
307 auto b = net::const_buffer(c, 1);
308 auto bs = buffers_cat(b1: net::const_buffer(c, 1));
309 auto first = net::buffer_sequence_begin(c&: bs);
310 auto last = net::buffer_sequence_end(c&: bs);
311 BOOST_ASSERT(first != last);
312 BEAST_EXPECT(std::distance(first, last) == 1);
313 net::const_buffer b2(*first);
314 BEAST_EXPECT(b.data() == b2.data());
315 BEAST_EXPECT(b.size() == b2.size());
316 }
317
318 void run() override
319 {
320 testDefaultIterators();
321 testBufferSequence();
322 testExceptions();
323 testEmpty();
324 testGccWarning1();
325 testGccWarning2();
326 testSingleBuffer();
327 }
328};
329
330BEAST_DEFINE_TESTSUITE(beast,core,buffers_cat);
331
332} // beast
333} // boost
334

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