diff --git a/CHANGELOG.md b/CHANGELOG.md index ba709f93..16c5ae14 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,9 @@ +Version 54: + +* static_buffer coverage + +-------------------------------------------------------------------------------- + Version 53: * Fix basic_parser::maybe_flatten diff --git a/include/beast/core/detail/read_size_helper.hpp b/include/beast/core/detail/read_size_helper.hpp index 92f9aa8d..433ba38d 100644 --- a/include/beast/core/detail/read_size_helper.hpp +++ b/include/beast/core/detail/read_size_helper.hpp @@ -44,9 +44,7 @@ read_size_helper( BOOST_ASSERT(max_size >= 1); auto const size = buffer.size(); auto const limit = buffer.max_size() - size; - if(limit <= 0) - BOOST_THROW_EXCEPTION(std::length_error{ - "dynamic buffer overflow"}); + BOOST_ASSERT(size <= buffer.max_size()); return std::min( std::max(512, buffer.capacity() - size), std::min(max_size, limit)); diff --git a/include/beast/core/impl/static_buffer.ipp b/include/beast/core/impl/static_buffer.ipp index 9f7b7265..13652ca5 100644 --- a/include/beast/core/impl/static_buffer.ipp +++ b/include/beast/core/impl/static_buffer.ipp @@ -76,7 +76,7 @@ prepare_impl(std::size_t n) -> auto const len = size(); if(n > capacity() - len) BOOST_THROW_EXCEPTION(std::length_error{ - "static_buffer overflow"}); + "buffer overflow"}); if(len > 0) std::memmove(begin_, in_, len); in_ = begin_; @@ -99,6 +99,31 @@ consume_impl(std::size_t n) in_ += n; } +//------------------------------------------------------------------------------ + +template +static_buffer_n:: +static_buffer_n(static_buffer_n const& other) + : static_buffer(buf_, N) +{ + using boost::asio::buffer_copy; + this->commit(buffer_copy( + this->prepare(other.size()), other.data())); +} + +template +auto +static_buffer_n:: +operator=(static_buffer_n const& other) -> + static_buffer_n& +{ + using boost::asio::buffer_copy; + this->consume(this->size()); + this->commit(buffer_copy( + this->prepare(other.size()), other.data())); + return *this; +} + } // beast #endif diff --git a/include/beast/core/static_buffer.hpp b/include/beast/core/static_buffer.hpp index dd9f5958..1f86c336 100644 --- a/include/beast/core/static_buffer.hpp +++ b/include/beast/core/static_buffer.hpp @@ -10,6 +10,8 @@ #include #include +#include +#include #include namespace beast { @@ -37,6 +39,9 @@ class static_buffer char* last_; char* end_; + static_buffer(static_buffer const& other) = delete; + static_buffer& operator=(static_buffer const&) = delete; + public: /// The type used to represent the input sequence as a list of buffers. using const_buffers_type = boost::asio::const_buffers_1; @@ -44,12 +49,6 @@ public: /// The type used to represent the output sequence as a list of buffers. using mutable_buffers_type = boost::asio::mutable_buffers_1; - static_buffer( - static_buffer const& other) noexcept = delete; - - static_buffer& operator=( - static_buffer const&) noexcept = delete; - /** Constructor. This creates a dynamic buffer using the provided storage area. @@ -185,17 +184,31 @@ class static_buffer_n : public static_buffer char buf_[N]; public: - /// Copy constructor (disallowed). - static_buffer_n(static_buffer_n const&) = delete; + /// Copy constructor + static_buffer_n(static_buffer_n const&); - /// Copy assignment (disallowed). - static_buffer_n& operator=(static_buffer_n const&) = delete; + /// Copy assignment + static_buffer_n& operator=(static_buffer_n const&); /// Construct a static buffer. static_buffer_n() : static_buffer(buf_, N) { } + + /// Returns the @ref static_buffer portion of this object + static_buffer& + base() + { + return *this; + } + + /// Returns the @ref static_buffer portion of this object + static_buffer const& + base() const + { + return *this; + } }; } // beast diff --git a/test/core/async_result.cpp b/test/core/async_result.cpp index e3b72ae5..1aca1cbe 100644 --- a/test/core/async_result.cpp +++ b/test/core/async_result.cpp @@ -7,3 +7,32 @@ // Test that header file is self-contained. #include + +#include +#include +#include + +namespace beast { +namespace { + +struct handler +{ + void operator()(beast::error_code, std::size_t) const; +}; + +static_assert(detail::is_invocable< + typename async_result::completion_handler_type, + void(error_code, std::size_t)>::value, ""); + +static_assert(std::is_same::return_type>::value, ""); + +static_assert(std::is_constructible< + async_result, + typename async_result::completion_handler_type&>::value, ""); + +} // (anon-ns) +} // beast diff --git a/test/core/buffer_test.hpp b/test/core/buffer_test.hpp index 11df5f0d..2aac00ed 100644 --- a/test/core/buffer_test.hpp +++ b/test/core/buffer_test.hpp @@ -8,16 +8,43 @@ #ifndef BEAST_TEST_BUFFER_TEST_HPP #define BEAST_TEST_BUFFER_TEST_HPP +#include #include #include #include #include #include +#include #include namespace beast { namespace test { +template +typename std::enable_if< + is_const_buffer_sequence::value, +std::string>::type +to_string(ConstBufferSequence const& bs) +{ + using boost::asio::buffer_cast; + using boost::asio::buffer_size; + std::string s; + s.reserve(buffer_size(bs)); + for(auto const& b : bs) + s.append(buffer_cast(b), + buffer_size(b)); + return s; +} + +template +void +write_buffer(DynamicBuffer& b, string_view s) +{ + b.commit(boost::asio::buffer_copy( + b.prepare(s.size()), boost::asio::buffer( + s.data(), s.size()))); +} + template typename std::enable_if< is_const_buffer_sequence::value, @@ -101,6 +128,8 @@ namespace has_read_size_helper }; } +//------------------------------------------------------------------------------ + // Make sure read_size_helper works template inline @@ -109,6 +138,7 @@ check_read_size_helper() { static_assert(is_dynamic_buffer::value, "DynamicBuffer requirements not met "); + static_assert(has_read_size_helper::trait::value, "Missing read_size_helper for dynamic buffer"); } diff --git a/test/core/static_buffer.cpp b/test/core/static_buffer.cpp index 8e54f1c0..bebbfa10 100644 --- a/test/core/static_buffer.cpp +++ b/test/core/static_buffer.cpp @@ -9,33 +9,25 @@ #include #include "buffer_test.hpp" + +#include +#include #include -#include #include namespace beast { +static_assert( + is_dynamic_buffer::value, + "DynamicBuffer requirements not met"); + class static_buffer_test : public beast::unit_test::suite { public: - template - static - std::string - to_string(ConstBufferSequence const& bs) - { - using boost::asio::buffer_cast; - using boost::asio::buffer_size; - std::string s; - s.reserve(buffer_size(bs)); - for(auto const& b : bs) - s.append(buffer_cast(b), - buffer_size(b)); - return s; - } - void testStaticBuffer() { + using namespace test; using boost::asio::buffer; using boost::asio::buffer_cast; using boost::asio::buffer_size; @@ -142,15 +134,100 @@ public: } void - testReadSizeHelper() + testBuffer() { + using namespace test; + string_view const s = "Hello, world!"; + + // static_buffer + { + char buf[64]; + static_buffer b{buf, sizeof(buf)}; + ostream(b) << s; + BEAST_EXPECT(to_string(b.data()) == s); + b.consume(b.size()); + BEAST_EXPECT(to_string(b.data()) == ""); + } + + // static_buffer_n + { + static_buffer_n<64> b1; + BEAST_EXPECT(b1.size() == 0); + BEAST_EXPECT(b1.max_size() == 64); + BEAST_EXPECT(b1.capacity() == 64); + ostream(b1) << s; + BEAST_EXPECT(to_string(b1.data()) == s); + { + static_buffer_n<64> b2{b1}; + BEAST_EXPECT(to_string(b2.data()) == s); + b2.consume(7); + BEAST_EXPECT(to_string(b2.data()) == s.substr(7)); + } + { + static_buffer_n<64> b2; + b2 = b1; + BEAST_EXPECT(to_string(b2.data()) == s); + b2.consume(7); + BEAST_EXPECT(to_string(b2.data()) == s.substr(7)); + } + } + + // cause memmove + { + static_buffer_n<10> b; + write_buffer(b, "12345"); + b.consume(3); + write_buffer(b, "67890123"); + BEAST_EXPECT(to_string(b.data()) == "4567890123"); + try + { + b.prepare(1); + fail("", __FILE__, __LINE__); + } + catch(std::length_error const&) + { + pass(); + } + } + + // read_size_helper + { + using detail::read_size_helper; + static_buffer_n<10> b; + BEAST_EXPECT(read_size_helper(b, 512) == 10); + b.prepare(4); + b.commit(4); + BEAST_EXPECT(read_size_helper(b, 512) == 6); + b.consume(2); + BEAST_EXPECT(read_size_helper(b, 512) == 8); + b.prepare(8); + b.commit(8); + BEAST_EXPECT(read_size_helper(b, 512) == 0); + } + + // base + { + static_buffer_n<10> b; + [&](static_buffer& b) + { + BEAST_EXPECT(b.max_size() == b.capacity()); + } + (b.base()); + + [&](static_buffer const&) + { + BEAST_EXPECT(b.max_size() == b.capacity()); + } + (b.base()); + } } void run() override { test::check_read_size_helper>(); - testStaticBuffer(); + testBuffer(); + //testStaticBuffer(); } };