Refactor static_buffer:

* Improve tests and coverage
* Add static_buffer_base::clear
* Use BOOST_BEAST_DECL
This commit is contained in:
Vinnie Falco
2018-12-19 20:59:20 -08:00
parent 0006ab3b2b
commit 321af29d25
6 changed files with 106 additions and 205 deletions
+57 -155
View File
@@ -24,27 +24,17 @@
namespace boost {
namespace beast {
BOOST_STATIC_ASSERT(
net::is_dynamic_buffer<static_buffer_base>::value);
class static_buffer_test : public beast::unit_test::suite
{
public:
BOOST_STATIC_ASSERT(
net::is_dynamic_buffer<
is_mutable_dynamic_buffer<
static_buffer<13>>::value);
BOOST_STATIC_ASSERT(
is_mutable_dynamic_buffer<
static_buffer_base>::value);
BOOST_STATIC_ASSERT(
net::is_const_buffer_sequence<
static_buffer_base::const_buffers_type>::value);
BOOST_STATIC_ASSERT(
net::is_mutable_buffer_sequence<
static_buffer_base::mutable_data_type>::value);
BOOST_STATIC_ASSERT(
net::is_mutable_buffer_sequence<
static_buffer_base::mutable_buffers_type>::value);
BOOST_STATIC_ASSERT(std::is_convertible<
static_buffer_base::mutable_data_type,
static_buffer_base::const_buffers_type>::value);
#if ! defined( BOOST_LIBSTDCXX_VERSION ) || BOOST_LIBSTDCXX_VERSION >= 50000
# ifndef BOOST_ASIO_ENABLE_BUFFER_DEBUGGING
BOOST_STATIC_ASSERT(std::is_trivially_copyable<
@@ -54,147 +44,18 @@ public:
# endif
#endif
template<class DynamicBuffer>
void
testMutableData()
testDynamicBuffer()
{
DynamicBuffer b;
DynamicBuffer const& cb = b;
ostream(b) << "Hello";
BOOST_STATIC_ASSERT(
net::is_const_buffer_sequence<
decltype(cb.data())>::value &&
! net::is_mutable_buffer_sequence<
decltype(cb.data())>::value);
BOOST_STATIC_ASSERT(
net::is_const_buffer_sequence<
decltype(cb.cdata())>::value &&
! net::is_mutable_buffer_sequence<
decltype(cb.cdata())>::value);
BOOST_STATIC_ASSERT(
net::is_mutable_buffer_sequence<
decltype(b.data())>::value);
std::for_each(
net::buffers_iterator<decltype(b.data())>::begin(b.data()),
net::buffers_iterator<decltype(b.data())>::end(b.data()),
[](char& c)
{
c = static_cast<char>(std::toupper(c));
});
BEAST_EXPECT(buffers_to_string(b.data()) == "HELLO");
BEAST_EXPECT(buffers_to_string(b.cdata()) == "HELLO");
static_buffer<13> b;
test_dynamic_buffer(*this, b);
}
void
testStaticBuffer()
testMembers()
{
using net::buffer;
using net::buffer_size;
char buf[12];
std::string const s = "Hello, world";
BEAST_EXPECT(s.size() == sizeof(buf));
for(std::size_t i = 1; i < 4; ++i) {
for(std::size_t j = 1; j < 4; ++j) {
for(std::size_t x = 1; x < 4; ++x) {
for(std::size_t y = 1; y < 4; ++y) {
for(std::size_t t = 1; t < 4; ++ t) {
for(std::size_t u = 1; u < 4; ++ u) {
std::size_t z = sizeof(buf) - (x + y);
std::size_t v = sizeof(buf) - (t + u);
{
std::memset(buf, 0, sizeof(buf));
static_buffer<sizeof(buf)> ba;
{
auto d = ba.prepare(z);
BEAST_EXPECT(buffer_size(d) == z);
}
{
auto d = ba.prepare(0);
BEAST_EXPECT(buffer_size(d) == 0);
}
{
auto d = ba.prepare(y);
BEAST_EXPECT(buffer_size(d) == y);
}
{
auto d = ba.prepare(x);
BEAST_EXPECT(buffer_size(d) == x);
ba.commit(buffer_copy(d, buffer(s.data(), x)));
}
BEAST_EXPECT(ba.size() == x);
BEAST_EXPECT(buffer_size(ba.data()) == ba.size());
{
auto d = ba.prepare(x);
BEAST_EXPECT(buffer_size(d) == x);
}
{
auto d = ba.prepare(0);
BEAST_EXPECT(buffer_size(d) == 0);
}
{
auto d = ba.prepare(z);
BEAST_EXPECT(buffer_size(d) == z);
}
{
auto d = ba.prepare(y);
BEAST_EXPECT(buffer_size(d) == y);
ba.commit(buffer_copy(d, buffer(s.data()+x, y)));
}
ba.commit(1);
BEAST_EXPECT(ba.size() == x + y);
BEAST_EXPECT(buffer_size(ba.data()) == ba.size());
{
auto d = ba.prepare(x);
BEAST_EXPECT(buffer_size(d) == x);
}
{
auto d = ba.prepare(y);
BEAST_EXPECT(buffer_size(d) == y);
}
{
auto d = ba.prepare(0);
BEAST_EXPECT(buffer_size(d) == 0);
}
{
auto d = ba.prepare(z);
BEAST_EXPECT(buffer_size(d) == z);
ba.commit(buffer_copy(d, buffer(s.data()+x+y, z)));
}
ba.commit(2);
BEAST_EXPECT(ba.size() == x + y + z);
BEAST_EXPECT(buffer_size(ba.data()) == ba.size());
BEAST_EXPECT(buffers_to_string(ba.data()) == s);
ba.consume(t);
{
auto d = ba.prepare(0);
BEAST_EXPECT(buffer_size(d) == 0);
}
BEAST_EXPECT(buffers_to_string(ba.data()) == s.substr(t, std::string::npos));
ba.consume(u);
BEAST_EXPECT(buffers_to_string(ba.data()) == s.substr(t + u, std::string::npos));
ba.consume(v);
BEAST_EXPECT(buffers_to_string(ba.data()) == "");
ba.consume(1);
{
auto d = ba.prepare(0);
BEAST_EXPECT(buffer_size(d) == 0);
}
try
{
ba.prepare(ba.capacity() - ba.size() + 1);
fail();
}
catch(...)
{
pass();
}
}
}}}}}}
}
void
testBuffer()
{
string_view const s = "Hello, world!";
// static_buffer_base
@@ -203,8 +64,9 @@ public:
static_buffer_base b{buf, sizeof(buf)};
ostream(b) << s;
BEAST_EXPECT(buffers_to_string(b.data()) == s);
b.consume(b.size());
BEAST_EXPECT(buffers_to_string(b.data()) == "");
b.clear();
BEAST_EXPECT(b.size() == 0);
BEAST_EXPECT(buffer_size(b.data()) == 0);
}
// static_buffer
@@ -277,13 +139,53 @@ public:
}
(b.base());
}
// This exercises the wrap-around cases
// for the circular buffer representation
{
static_buffer<5> b;
{
auto const mb = b.prepare(5);
BEAST_EXPECT(buffers_length(mb) == 1);
}
b.commit(4);
BEAST_EXPECT(buffers_length(b.data()) == 1);
BEAST_EXPECT(buffers_length(b.cdata()) == 1);
b.consume(3);
{
auto const mb = b.prepare(3);
BEAST_EXPECT(buffers_length(mb) == 2);
auto it1 = mb.begin();
auto it2 = std::next(it1);
BEAST_EXPECT(
net::const_buffer(*it1).data() >
net::const_buffer(*it2).data());
}
b.commit(2);
{
auto const mb = b.data();
auto it1 = mb.begin();
auto it2 = std::next(it1);
BEAST_EXPECT(
net::const_buffer(*it1).data() >
net::const_buffer(*it2).data());
}
{
auto const cb = b.cdata();
auto it1 = cb.begin();
auto it2 = std::next(it1);
BEAST_EXPECT(
net::const_buffer(*it1).data() >
net::const_buffer(*it2).data());
}
}
}
void run() override
void
run() override
{
testBuffer();
testStaticBuffer();
testMutableData<static_buffer<32>>();
testDynamicBuffer();
testMembers();
}
};