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 #ifndef BOOST_BEAST_TEST_BUFFER_HPP
11 #define BOOST_BEAST_TEST_BUFFER_HPP
13 #include <boost/beast/core/detail/config.hpp>
14 #include <boost/beast/_experimental/unit_test/suite.hpp>
15 #include <boost/beast/core/buffer_traits.hpp>
16 #include <boost/beast/core/buffers_to_string.hpp>
17 #include <boost/beast/core/string.hpp>
18 #include <boost/beast/core/detail/type_traits.hpp>
19 #include <boost/asio/buffer.hpp>
20 #include <boost/assert.hpp>
23 #include <type_traits>
28 /** A MutableBufferSequence for tests, where length is always 3.
32 net::mutable_buffer b_[3];
35 using value_type = net::mutable_buffer;
36 using const_iterator = net::mutable_buffer const*;
39 buffers_triple const&) = default;
41 buffers_triple& operator=(
42 buffers_triple const&) = default;
44 buffers_triple(char* data, std::size_t size)
46 b_[0] = {data, size/6};
50 b_[1] = {data, 2*size/5};
56 BOOST_ASSERT(b_[0].size() > 0);
57 BOOST_ASSERT(b_[1].size() > 0);
58 BOOST_ASSERT(b_[2].size() > 0);
62 operator==(buffers_triple const& rhs) const noexcept
65 b_[0].data() == rhs.b_[0].data() &&
66 b_[0].size() == rhs.b_[0].size() &&
67 b_[1].data() == rhs.b_[1].data() &&
68 b_[1].size() == rhs.b_[1].size() &&
69 b_[2].data() == rhs.b_[2].data() &&
70 b_[2].size() == rhs.b_[2].size();
74 operator!=(buffers_triple const& rhs) const noexcept
76 return !(*this == rhs);
80 begin() const noexcept
92 template<class ConstBufferSequence>
95 ConstBufferSequence const& buffers)
98 net::buffer_sequence_begin(buffers),
99 net::buffer_sequence_end(buffers));
102 //------------------------------------------------------------------------------
106 template<class MutableBufferSequence>
107 void test_mutable_buffers(
108 MutableBufferSequence const&,
113 template<class MutableBufferSequence>
114 void test_mutable_buffers(
115 MutableBufferSequence const& b,
118 string_view src = "Hello, world!";
119 BOOST_ASSERT(buffer_bytes(b) <= src.size());
120 if(src.size() > buffer_bytes(b))
121 src = {src.data(), buffer_bytes(b)};
122 net::buffer_copy(b, net::const_buffer(
123 src.data(), src.size()));
124 BEAST_EXPECT(beast::buffers_to_string(b) == src);
129 /** Test an instance of a constant or mutable buffer sequence.
131 template<class ConstBufferSequence>
133 test_buffer_sequence(
134 ConstBufferSequence const& buffers)
137 net::is_const_buffer_sequence<
138 ConstBufferSequence>::value);
140 using iterator = decltype(
141 net::buffer_sequence_begin(buffers));
142 BEAST_EXPECT(sizeof(iterator) > 0);
144 auto const size = buffer_bytes(buffers);
145 BEAST_EXPECT(size > 0 );
148 auto const length = std::distance(
149 net::buffer_sequence_begin(buffers),
150 net::buffer_sequence_end(buffers));
151 BEAST_EXPECT(length > 0);
153 net::buffer_sequence_begin(buffers) !=
154 net::buffer_sequence_end(buffers));
157 ConstBufferSequence b1(buffers);
158 BEAST_EXPECT(buffer_bytes(b1) == size);
161 ConstBufferSequence b2(buffers);
163 BEAST_EXPECT(buffer_bytes(b2) == size);
170 net::buffer_sequence_begin(buffers);
172 net::buffer_sequence_end(buffers);
173 BEAST_EXPECT(it1 == it2);
174 BEAST_EXPECT(it1 != it3);
175 BEAST_EXPECT(it3 != it1);
176 BEAST_EXPECT(it1 != it4);
177 BEAST_EXPECT(it4 != it1);
183 net::buffer_sequence_begin(buffers);
185 net::buffer_sequence_end(buffers);
192 for(it = first; n--; ++it)
193 m += buffer_bytes(*it);
194 BEAST_EXPECT(it == last);
195 BEAST_EXPECT(m == size);
200 for(it = first; n--;)
201 m += buffer_bytes(*it++);
202 BEAST_EXPECT(it == last);
203 BEAST_EXPECT(m == size);
209 m += buffer_bytes(*--it);
210 BEAST_EXPECT(it == first);
211 BEAST_EXPECT(m == size);
219 m += buffer_bytes(*it);
221 BEAST_EXPECT(it == first);
222 BEAST_EXPECT(m == size);
225 detail::test_mutable_buffers(buffers,
226 buffers_type<ConstBufferSequence>{});
229 //------------------------------------------------------------------------------
231 /** Metafunction to determine if a type meets the requirements of MutableDynamicBuffer_v0
234 // VFALCO This trait needs tests
235 template<class T, class = void>
236 struct is_mutable_dynamic_buffer
242 struct is_mutable_dynamic_buffer<T, detail::void_t<decltype(
243 std::declval<typename T::const_buffers_type&>() =
244 std::declval<T const&>().data(),
245 std::declval<typename T::const_buffers_type&>() =
246 std::declval<T&>().cdata(),
247 std::declval<typename T::mutable_buffers_type&>() =
248 std::declval<T&>().data()
249 ) > > : net::is_dynamic_buffer_v1<T>
256 template<class MutableBufferSequence>
259 MutableBufferSequence const& buffers,
263 net::buffer_sequence_end(buffers);
264 for(auto it = net::buffer_sequence_begin(buffers);
267 net::mutable_buffer b(*it);
269 static_cast<char*>(b.data()),
270 static_cast<char*>(b.data()) + b.size(), c);
274 template<class MutableDynamicBuffer_v0>
276 test_mutable_dynamic_buffer(
277 MutableDynamicBuffer_v0 const&,
282 template<class MutableDynamicBuffer_v0>
284 test_mutable_dynamic_buffer(
285 MutableDynamicBuffer_v0 const& b0,
289 net::is_mutable_buffer_sequence<typename
290 MutableDynamicBuffer_v0::mutable_buffers_type>::value);
294 typename MutableDynamicBuffer_v0::mutable_buffers_type,
295 typename MutableDynamicBuffer_v0::const_buffers_type>::value);
297 string_view src = "Hello, world!";
298 if(src.size() > b0.max_size())
299 src = {src.data(), b0.max_size()};
301 // modify readable bytes
303 MutableDynamicBuffer_v0 b(b0);
304 auto const mb = b.prepare(src.size());
305 BEAST_EXPECT(buffer_bytes(mb) == src.size());
306 buffers_fill(mb, '*');
307 b.commit(src.size());
308 BEAST_EXPECT(b.size() == src.size());
310 beast::buffers_to_string(b.data()) ==
311 std::string(src.size(), '*'));
313 beast::buffers_to_string(b.cdata()) ==
314 std::string(src.size(), '*'));
315 auto const n = net::buffer_copy(
316 b.data(), net::const_buffer(
317 src.data(), src.size()));
318 BEAST_EXPECT(n == src.size());
320 beast::buffers_to_string(b.data()) == src);
322 beast::buffers_to_string(b.cdata()) == src);
325 // mutable to const sequence conversion
327 MutableDynamicBuffer_v0 b(b0);
328 b.commit(net::buffer_copy(
329 b.prepare(src.size()),
330 net::const_buffer(src.data(), src.size())));
332 auto cb = static_cast<
333 MutableDynamicBuffer_v0 const&>(b).data();
334 auto cbc = b.cdata();
336 beast::buffers_to_string(b.data()) == src);
338 beast::buffers_to_string(b.cdata()) == src);
339 beast::test_buffer_sequence(cb);
340 beast::test_buffer_sequence(cbc);
341 beast::test_buffer_sequence(mb);
343 decltype(mb) mb2(mb);
345 decltype(cb) cb2(cb);
347 decltype(cbc) cbc2(cbc);
351 decltype(cb) cb2(mb);
352 decltype(cbc) cbc2(mb);
361 /** Test an instance of a dynamic buffer or mutable dynamic buffer.
363 template<class DynamicBuffer_v0>
366 DynamicBuffer_v0 const& b0)
369 net::is_dynamic_buffer_v1<DynamicBuffer_v0>::value);
372 net::is_const_buffer_sequence<typename
373 DynamicBuffer_v0::const_buffers_type>::value);
376 net::is_mutable_buffer_sequence<typename
377 DynamicBuffer_v0::mutable_buffers_type>::value);
379 BEAST_EXPECT(b0.size() == 0);
380 BEAST_EXPECT(buffer_bytes(b0.data()) == 0);
384 string_view src = "Hello, world!";
386 DynamicBuffer_v0 b1(b0);
387 auto const mb = b1.prepare(src.size());
388 b1.commit(net::buffer_copy(mb,
389 net::const_buffer(src.data(), src.size())));
393 DynamicBuffer_v0 b2(b1);
394 BEAST_EXPECT(b2.size() == b1.size());
396 buffers_to_string(b1.data()) ==
397 buffers_to_string(b2.data()));
399 // https://github.com/boostorg/beast/issues/1621
401 DynamicBuffer_v0 b3(b2);
402 BEAST_EXPECT(b3.size() == b2.size());
404 buffers_to_string(b2.data()) ==
405 buffers_to_string(b3.data()));
410 DynamicBuffer_v0 b2(b1);
411 DynamicBuffer_v0 b3(std::move(b2));
412 BEAST_EXPECT(b3.size() == b1.size());
414 buffers_to_string(b3.data()) ==
415 buffers_to_string(b1.data()));
420 DynamicBuffer_v0 b2(b0);
422 BEAST_EXPECT(b2.size() == b1.size());
424 buffers_to_string(b1.data()) ==
425 buffers_to_string(b2.data()));
429 BEAST_EXPECT(b2.size() == b1.size());
431 buffers_to_string(b2.data()) ==
432 buffers_to_string(b1.data()));
434 // https://github.com/boostorg/beast/issues/1621
436 DynamicBuffer_v0 b3(b2);
437 BEAST_EXPECT(b3.size() == b2.size());
439 buffers_to_string(b2.data()) ==
440 buffers_to_string(b3.data()));
446 DynamicBuffer_v0 b2(b1);
447 DynamicBuffer_v0 b3(b0);
449 BEAST_EXPECT(b3.size() == b1.size());
451 buffers_to_string(b3.data()) ==
452 buffers_to_string(b1.data()));
456 BEAST_EXPECT(b3.size() == b1.size());
458 buffers_to_string(b3.data()) ==
459 buffers_to_string(b1.data()));
464 DynamicBuffer_v0 b2(b1);
465 DynamicBuffer_v0 b3(b0);
466 BEAST_EXPECT(b2.size() == b1.size());
467 BEAST_EXPECT(b3.size() == b0.size());
470 BEAST_EXPECT(b2.size() == b0.size());
471 BEAST_EXPECT(b3.size() == b1.size());
473 buffers_to_string(b3.data()) ==
474 buffers_to_string(b1.data()));
480 DynamicBuffer_v0 b(b0);
482 BEAST_EXPECT(b.size() == 0);
483 BEAST_EXPECT(buffer_bytes(b.prepare(0)) == 0);
485 BEAST_EXPECT(b.size() == 0);
487 BEAST_EXPECT(b.size() == 0);
488 b.commit(b.max_size() + 1);
489 BEAST_EXPECT(b.size() == 0);
491 BEAST_EXPECT(b.size() == 0);
493 BEAST_EXPECT(b.size() == 0);
494 b.consume(b.max_size() + 1);
495 BEAST_EXPECT(b.size() == 0);
500 DynamicBuffer_v0 b(b0);
502 b.max_size() + 1 > b.max_size()))
506 b.prepare(b.max_size() + 1);
509 catch(std::length_error const&)
520 // setup source buffer
522 unsigned char k0 = 0;
523 string_view src(buf, sizeof(buf));
524 if(src.size() > b0.max_size())
525 src = {src.data(), b0.max_size()};
526 BEAST_EXPECT(b0.max_size() >= src.size());
527 BEAST_EXPECT(b0.size() == 0);
528 BEAST_EXPECT(buffer_bytes(b0.data()) == 0);
529 auto const make_new_src =
533 for(std::size_t i = 0; i < src.size(); ++i)
537 // readable / writable buffer sequence tests
540 DynamicBuffer_v0 b(b0);
542 auto const mb = b.prepare(src.size());
543 BEAST_EXPECT(buffer_bytes(mb) == src.size());
544 beast::test_buffer_sequence(mb);
545 b.commit(net::buffer_copy(mb,
546 net::const_buffer(src.data(), src.size())));
548 buffer_bytes(bc.data()) == src.size());
549 beast::test_buffer_sequence(bc.data());
556 for(std::size_t h = 1; h <= src.size(); ++h)
558 string_view in(src.data(), h);
559 for(std::size_t i = 1; i <= in.size(); ++i) {
560 for(std::size_t j = 1; j <= i + 1; ++j) {
561 for(std::size_t k = 1; k <= in.size(); ++k) {
565 DynamicBuffer_v0 b(b0);
567 net::const_buffer cb(in.data(), in.size());
570 auto const mb = b.prepare(
571 std::min<std::size_t>(i,
572 b.max_size() - b.size()));
573 auto const n = net::buffer_copy(mb,
574 net::const_buffer(cb.data(),
575 std::min<std::size_t>(j, cb.size())));
579 BEAST_EXPECT(b.size() == in.size());
581 buffer_bytes(bc.data()) == in.size());
582 BEAST_EXPECT(beast::buffers_to_string(
586 BEAST_EXPECT(buffer_bytes(bc.data()) == 0);
591 // MutableDynamicBuffer_v0 refinement
592 detail::test_mutable_dynamic_buffer(b0,
593 is_mutable_dynamic_buffer<DynamicBuffer_v0>{});