forked from boostorg/beast
Beast.Asio:
New classes:
class async_completion:
Helper class for implementing asynchronous initiation functions.
See n3964:
Library Foundations for Asynchronous Operations, Revision 1
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n3964.pdf
class basic_streambuf:
Meets the requirements of Streambuf.
class buffered_readstream:
Buffers a ReadStream with a ConstBufferSequence.
class consuming_buffers:
Adapts a BufferSequence which wraps the underlying buffer
sequence and presents fewer bytes, with the retained bytes
occurring at the end of the sequence.
class handler_alloc:
A C++ Allocator the uses asio handler allocation hooks.
class static_streambuf:
An implementation of the Streambuf concept that uses a
fixed size buffer with size determined at compile-time.
class streambuf_readstream:
Buffers a ReadStream with a Streambuf.
New functions:
append_buffers()
Returns a new BufferSequence which efficiently concatenates
two or more buffer sequences together.
prepare_buffers()
Shortens a buffer sequence. The bytes excluded are at the
end of the underlying buffer sequence.
boost::asio::read_until()
A copy of boost::asio::read_until overloads, modified to work
with a beast::asio::basic_streambuf.
Debugging:
buffers_to_string()
Convert a ConstBufferSequence to a human readable string
suitable for diagnostics.
type_check.h:
Metafunctions for checking asio concepts:
AsyncReadStream, AsyncWriteStream
SyncReadStream, SyncWriteStream
ConstBufferSequence, MutableBufferSequence
Streambuf
Handler
Changes:
* All symbols moved up a namespace level.
* streambuf provides all move and copy special members,
behavior of moved from objects is well-defined.
Fixes:
* Fix basic_streambuf iterator category.
This commit is contained in:
@@ -0,0 +1,29 @@
|
||||
#
|
||||
# Copyright (c) 2013-2016 Vinnie Falco (vinnie dot falco at gmail dot com)
|
||||
#
|
||||
# Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
# file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
#
|
||||
|
||||
import os ;
|
||||
|
||||
path-constant main : ../../beast/unit_test/src/main.cpp ;
|
||||
|
||||
unit-test all :
|
||||
append_buffers.cpp
|
||||
asio.cpp
|
||||
async_completion.cpp
|
||||
basic_streambuf.cpp
|
||||
bind_handler.cpp
|
||||
buffers_adapter.cpp
|
||||
buffers_debug.cpp
|
||||
consuming_buffers.cpp
|
||||
handler_alloc.cpp
|
||||
placeholders.cpp
|
||||
prepare_buffers.cpp
|
||||
static_streambuf.cpp
|
||||
streambuf.cpp
|
||||
streambuf_readstream.cpp
|
||||
type_check.cpp
|
||||
$(main)
|
||||
;
|
||||
@@ -0,0 +1,76 @@
|
||||
//
|
||||
// Copyright (c) 2013-2016 Vinnie Falco (vinnie dot falco at gmail dot com)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
|
||||
// Test that header file is self-contained.
|
||||
#include <beast/asio/append_buffers.h>
|
||||
|
||||
#include <beast/unit_test/suite.h>
|
||||
#include <boost/asio/buffer.hpp>
|
||||
#include <boost/asio/streambuf.hpp>
|
||||
#include <iterator>
|
||||
#include <list>
|
||||
#include <vector>
|
||||
|
||||
namespace beast {
|
||||
namespace asio {
|
||||
namespace test {
|
||||
|
||||
class append_buffers_test : public unit_test::suite
|
||||
{
|
||||
public:
|
||||
|
||||
void testAppendBuffers()
|
||||
{
|
||||
using boost::asio::buffer_size;
|
||||
using boost::asio::const_buffer;
|
||||
char buf[10];
|
||||
std::list<const_buffer> b1;
|
||||
std::vector<const_buffer> b2{
|
||||
const_buffer{buf+0, 1},
|
||||
const_buffer{buf+1, 2}};
|
||||
std::list<const_buffer> b3;
|
||||
std::array<const_buffer, 3> b4{{
|
||||
const_buffer{buf+3, 1},
|
||||
const_buffer{buf+4, 2},
|
||||
const_buffer{buf+6, 3}}};
|
||||
std::list<const_buffer> b5{
|
||||
const_buffer{buf+9, 1}};
|
||||
std::list<const_buffer> b6;
|
||||
auto bs = append_buffers(
|
||||
b1, b2, b3, b4, b5, b6);
|
||||
expect(buffer_size(bs) == 10);
|
||||
std::vector<const_buffer> v;
|
||||
for(auto iter = std::make_reverse_iterator(bs.end());
|
||||
iter != std::make_reverse_iterator(bs.begin()); ++iter)
|
||||
v.emplace_back(*iter);
|
||||
expect(buffer_size(bs) == 10);
|
||||
decltype(bs) bs2(bs);
|
||||
auto bs3(std::move(bs));
|
||||
bs = bs2;
|
||||
bs3 = std::move(bs2);
|
||||
{
|
||||
boost::asio::streambuf sb1, sb2;
|
||||
expect(buffer_size(append_buffers(
|
||||
sb1.prepare(5), sb2.prepare(7))) == 12);
|
||||
sb1.commit(5);
|
||||
sb2.commit(7);
|
||||
expect(buffer_size(append_buffers(
|
||||
sb1.data(), sb2.data())) == 12);
|
||||
}
|
||||
}
|
||||
|
||||
void run() override
|
||||
{
|
||||
testAppendBuffers();
|
||||
}
|
||||
};
|
||||
|
||||
BEAST_DEFINE_TESTSUITE(append_buffers,asio,beast);
|
||||
|
||||
} // test
|
||||
} // asio
|
||||
} // beast
|
||||
@@ -0,0 +1,9 @@
|
||||
//
|
||||
// Copyright (c) 2013-2016 Vinnie Falco (vinnie dot falco at gmail dot com)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
|
||||
// Test that header file is self-contained.
|
||||
#include <beast/asio.h>
|
||||
@@ -0,0 +1,9 @@
|
||||
//
|
||||
// Copyright (c) 2013-2016 Vinnie Falco (vinnie dot falco at gmail dot com)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
|
||||
// Test that header file is self-contained.
|
||||
#include <beast/asio/async_completion.h>
|
||||
@@ -0,0 +1,9 @@
|
||||
//
|
||||
// Copyright (c) 2013-2016 Vinnie Falco (vinnie dot falco at gmail dot com)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
|
||||
// Test that header file is self-contained.
|
||||
#include <beast/asio/basic_streambuf.h>
|
||||
@@ -0,0 +1,11 @@
|
||||
//
|
||||
// Copyright (c) 2013-2016 Vinnie Falco (vinnie dot falco at gmail dot com)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
|
||||
// Test that header file is self-contained.
|
||||
#include <beast/asio/bind_handler.h>
|
||||
|
||||
#include <beast/asio/src/test/beast_asio_bind_handler_test.cpp>
|
||||
@@ -0,0 +1,124 @@
|
||||
//
|
||||
// Copyright (c) 2013-2016 Vinnie Falco (vinnie dot falco at gmail dot com)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
|
||||
// Test that header file is self-contained.
|
||||
#include <beast/asio/buffers_adapter.h>
|
||||
|
||||
#include <beast/unit_test/suite.h>
|
||||
#include <boost/asio/buffer.hpp>
|
||||
#include <boost/asio/streambuf.hpp>
|
||||
#include <iterator>
|
||||
|
||||
namespace beast {
|
||||
namespace asio {
|
||||
namespace test {
|
||||
|
||||
class buffers_adapter_test : public unit_test::suite
|
||||
{
|
||||
public:
|
||||
template<class ConstBufferSequence>
|
||||
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<char const*>(b),
|
||||
buffer_size(b));
|
||||
return s;
|
||||
}
|
||||
|
||||
void testBuffersAdapter()
|
||||
{
|
||||
using boost::asio::buffer;
|
||||
using boost::asio::buffer_cast;
|
||||
using boost::asio::buffer_size;
|
||||
using boost::asio::const_buffer;
|
||||
using boost::asio::mutable_buffer;
|
||||
char buf[12];
|
||||
std::string const s = "Hello, world";
|
||||
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 k = sizeof(buf) - (i + j);
|
||||
std::size_t z = sizeof(buf) - (x + y);
|
||||
std::size_t v = sizeof(buf) - (t + u);
|
||||
{
|
||||
std::memset(buf, 0, sizeof(buf));
|
||||
std::array<mutable_buffer, 3> bs{{
|
||||
mutable_buffer{&buf[0], i},
|
||||
mutable_buffer{&buf[i], j},
|
||||
mutable_buffer{&buf[i+j], k}}};
|
||||
buffers_adapter<decltype(bs)> ba(std::move(bs));
|
||||
expect(ba.max_size() == sizeof(buf));
|
||||
decltype(ba)::mutable_buffers_type d;
|
||||
d = ba.prepare(z); expect(buffer_size(d) == z);
|
||||
d = ba.prepare(0); expect(buffer_size(d) == 0);
|
||||
d = ba.prepare(y); expect(buffer_size(d) == y);
|
||||
d = ba.prepare(x); expect(buffer_size(d) == x);
|
||||
ba.commit(buffer_copy(d, buffer(s.data(), x)));
|
||||
expect(ba.size() == x);
|
||||
expect(ba.max_size() == sizeof(buf) - x);
|
||||
expect(buffer_size(ba.data()) == ba.size());
|
||||
d = ba.prepare(x); expect(buffer_size(d) == x);
|
||||
d = ba.prepare(0); expect(buffer_size(d) == 0);
|
||||
d = ba.prepare(z); expect(buffer_size(d) == z);
|
||||
d = ba.prepare(y); expect(buffer_size(d) == y);
|
||||
ba.commit(buffer_copy(d, buffer(s.data()+x, y)));
|
||||
ba.commit(1);
|
||||
expect(ba.size() == x + y);
|
||||
expect(ba.max_size() == sizeof(buf) - (x + y));
|
||||
expect(buffer_size(ba.data()) == ba.size());
|
||||
d = ba.prepare(x); expect(buffer_size(d) == x);
|
||||
d = ba.prepare(y); expect(buffer_size(d) == y);
|
||||
d = ba.prepare(0); expect(buffer_size(d) == 0);
|
||||
d = ba.prepare(z); expect(buffer_size(d) == z);
|
||||
ba.commit(buffer_copy(d, buffer(s.data()+x+y, z)));
|
||||
ba.commit(2);
|
||||
expect(ba.size() == x + y + z);
|
||||
expect(ba.max_size() == 0);
|
||||
expect(buffer_size(ba.data()) == ba.size());
|
||||
expect(to_string(ba.data()) == s);
|
||||
ba.consume(t);
|
||||
d = ba.prepare(0); expect(buffer_size(d) == 0);
|
||||
expect(to_string(ba.data()) == s.substr(t, std::string::npos));
|
||||
ba.consume(u);
|
||||
expect(to_string(ba.data()) == s.substr(t + u, std::string::npos));
|
||||
ba.consume(v);
|
||||
expect(to_string(ba.data()) == "");
|
||||
ba.consume(1);
|
||||
d = ba.prepare(0); expect(buffer_size(d) == 0);
|
||||
try
|
||||
{
|
||||
ba.prepare(1);
|
||||
fail();
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
pass();
|
||||
}
|
||||
}
|
||||
}}}}}}
|
||||
}
|
||||
void run() override
|
||||
{
|
||||
testBuffersAdapter();
|
||||
}
|
||||
};
|
||||
|
||||
BEAST_DEFINE_TESTSUITE(buffers_adapter,asio,beast);
|
||||
|
||||
} // test
|
||||
} // asio
|
||||
} // beast
|
||||
@@ -0,0 +1,9 @@
|
||||
//
|
||||
// Copyright (c) 2013-2016 Vinnie Falco (vinnie dot falco at gmail dot com)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
|
||||
// Test that header file is self-contained.
|
||||
#include <beast/asio/buffers_debug.h>
|
||||
@@ -0,0 +1,97 @@
|
||||
//
|
||||
// Copyright (c) 2013-2016 Vinnie Falco (vinnie dot falco at gmail dot com)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
|
||||
// Test that header file is self-contained.
|
||||
#include <beast/asio/consuming_buffers.h>
|
||||
|
||||
#include <beast/unit_test/suite.h>
|
||||
#include <boost/asio/buffer.hpp>
|
||||
#include <string>
|
||||
|
||||
namespace beast {
|
||||
namespace asio {
|
||||
namespace test {
|
||||
|
||||
class consuming_buffers_test : public unit_test::suite
|
||||
{
|
||||
public:
|
||||
template<class ConstBufferSequence>
|
||||
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<char const*>(b),
|
||||
buffer_size(b));
|
||||
return s;
|
||||
}
|
||||
|
||||
void testBuffers()
|
||||
{
|
||||
using boost::asio::buffer;
|
||||
using boost::asio::const_buffer;
|
||||
char buf[12];
|
||||
std::string const s = "Hello, world";
|
||||
expect(s.size() == sizeof(buf));
|
||||
buffer_copy(buffer(buf), buffer(s));
|
||||
expect(to_string(buffer(buf)) == s);
|
||||
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) {
|
||||
std::size_t k = sizeof(buf) - (i + j);
|
||||
std::size_t z = sizeof(buf) - (x + y);
|
||||
{
|
||||
std::array<const_buffer, 3> bs{{
|
||||
const_buffer{&buf[0], i},
|
||||
const_buffer{&buf[i], j},
|
||||
const_buffer{&buf[i+j], k}}};
|
||||
consuming_buffers<decltype(bs)> cb(bs);
|
||||
expect(to_string(cb) == s);
|
||||
cb.consume(0);
|
||||
expect(to_string(cb) == s);
|
||||
cb.consume(x);
|
||||
expect(to_string(cb) == s.substr(x));
|
||||
cb.consume(y);
|
||||
expect(to_string(cb) == s.substr(x+y));
|
||||
cb.consume(z);
|
||||
expect(to_string(cb) == "");
|
||||
cb.consume(1);
|
||||
expect(to_string(cb) == "");
|
||||
}
|
||||
}}}}
|
||||
}
|
||||
|
||||
void testNullBuffers()
|
||||
{
|
||||
using boost::asio::buffer_copy;
|
||||
using boost::asio::buffer_size;
|
||||
using boost::asio::null_buffers;
|
||||
consuming_buffers<null_buffers> cb(
|
||||
null_buffers{});
|
||||
expect(buffer_size(cb) == 0);
|
||||
consuming_buffers<null_buffers> cb2(
|
||||
null_buffers{});
|
||||
expect(buffer_copy(cb2, cb) == 0);
|
||||
}
|
||||
|
||||
void run() override
|
||||
{
|
||||
testBuffers();
|
||||
testNullBuffers();
|
||||
}
|
||||
};
|
||||
|
||||
BEAST_DEFINE_TESTSUITE(consuming_buffers,asio,beast);
|
||||
|
||||
} // test
|
||||
} // asio
|
||||
} // beast
|
||||
@@ -0,0 +1,9 @@
|
||||
//
|
||||
// Copyright (c) 2013-2016 Vinnie Falco (vinnie dot falco at gmail dot com)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
|
||||
// Test that header file is self-contained.
|
||||
#include <beast/asio/handler_alloc.h>
|
||||
@@ -0,0 +1,9 @@
|
||||
//
|
||||
// Copyright (c) 2013-2016 Vinnie Falco (vinnie dot falco at gmail dot com)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
|
||||
// Test that header file is self-contained.
|
||||
#include <beast/asio/placeholders.h>
|
||||
@@ -0,0 +1,103 @@
|
||||
//
|
||||
// Copyright (c) 2013-2016 Vinnie Falco (vinnie dot falco at gmail dot com)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
|
||||
// Test that header file is self-contained.
|
||||
#include <beast/asio/prepare_buffers.h>
|
||||
|
||||
#include <beast/asio/consuming_buffers.h>
|
||||
#include <beast/unit_test/suite.h>
|
||||
#include <boost/asio/buffer.hpp>
|
||||
#include <string>
|
||||
|
||||
namespace beast {
|
||||
namespace asio {
|
||||
namespace test {
|
||||
|
||||
class prepare_buffers_test : public unit_test::suite
|
||||
{
|
||||
public:
|
||||
template<class ConstBufferSequence>
|
||||
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<char const*>(b),
|
||||
buffer_size(b));
|
||||
return s;
|
||||
}
|
||||
|
||||
void testBuffers()
|
||||
{
|
||||
using boost::asio::buffer_size;
|
||||
using boost::asio::const_buffer;
|
||||
std::string const s = "Hello, world";
|
||||
expect(s.size() == 12);
|
||||
for(std::size_t x = 1; x < 4; ++x) {
|
||||
for(std::size_t y = 1; y < 4; ++y) {
|
||||
std::size_t z = s.size() - (x + y);
|
||||
{
|
||||
std::array<const_buffer, 3> bs{{
|
||||
const_buffer{&s[0], x},
|
||||
const_buffer{&s[x], y},
|
||||
const_buffer{&s[x+y], z}}};
|
||||
for(std::size_t i = 0; i <= s.size() + 1; ++i)
|
||||
{
|
||||
auto pb = prepare_buffers(i, bs);
|
||||
expect(to_string(pb) == s.substr(0, i));
|
||||
auto pb2 = pb;
|
||||
expect(to_string(pb2) == to_string(pb));
|
||||
pb = prepare_buffers(0, bs);
|
||||
pb2 = pb;
|
||||
expect(buffer_size(pb2) == 0);
|
||||
pb2 = prepare_buffers(i, bs);
|
||||
expect(to_string(pb2) == s.substr(0, i));
|
||||
}
|
||||
}
|
||||
}}
|
||||
}
|
||||
|
||||
void testNullBuffers()
|
||||
{
|
||||
using boost::asio::buffer_copy;
|
||||
using boost::asio::buffer_size;
|
||||
using boost::asio::null_buffers;
|
||||
auto pb0 = prepare_buffers(0, null_buffers{});
|
||||
expect(buffer_size(pb0) == 0);
|
||||
auto pb1 = prepare_buffers(1, null_buffers{});
|
||||
expect(buffer_size(pb1) == 0);
|
||||
expect(buffer_copy(pb0, pb1) == 0);
|
||||
|
||||
using pb_type = decltype(pb0);
|
||||
consuming_buffers<pb_type> cb(pb0);
|
||||
expect(buffer_size(cb) == 0);
|
||||
expect(buffer_copy(cb, pb1) == 0);
|
||||
cb.consume(1);
|
||||
expect(buffer_size(cb) == 0);
|
||||
expect(buffer_copy(cb, pb1) == 0);
|
||||
|
||||
auto pbc = prepare_buffers(2, cb);
|
||||
expect(buffer_size(pbc) == 0);
|
||||
expect(buffer_copy(pbc, cb) == 0);
|
||||
}
|
||||
|
||||
void run() override
|
||||
{
|
||||
testBuffers();
|
||||
testNullBuffers();
|
||||
}
|
||||
};
|
||||
|
||||
BEAST_DEFINE_TESTSUITE(prepare_buffers,asio,beast);
|
||||
|
||||
} // test
|
||||
} // asio
|
||||
} // beast
|
||||
@@ -0,0 +1,113 @@
|
||||
//
|
||||
// Copyright (c) 2013-2016 Vinnie Falco (vinnie dot falco at gmail dot com)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
|
||||
// Test that header file is self-contained.
|
||||
#include <beast/asio/static_streambuf.h>
|
||||
|
||||
#include <beast/unit_test/suite.h>
|
||||
#include <boost/asio/buffer.hpp>
|
||||
#include <string>
|
||||
|
||||
namespace beast {
|
||||
namespace asio {
|
||||
namespace test {
|
||||
|
||||
class static_streambuf_test : public unit_test::suite
|
||||
{
|
||||
public:
|
||||
template<class ConstBufferSequence>
|
||||
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<char const*>(b),
|
||||
buffer_size(b));
|
||||
return s;
|
||||
}
|
||||
|
||||
void testStaticStreambuf()
|
||||
{
|
||||
using boost::asio::buffer;
|
||||
using boost::asio::buffer_cast;
|
||||
using boost::asio::buffer_size;
|
||||
char buf[12];
|
||||
std::string const s = "Hello, world";
|
||||
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_streambuf_n<sizeof(buf)> ba;
|
||||
decltype(ba)::mutable_buffers_type d;
|
||||
d = ba.prepare(z); expect(buffer_size(d) == z);
|
||||
d = ba.prepare(0); expect(buffer_size(d) == 0);
|
||||
d = ba.prepare(y); expect(buffer_size(d) == y);
|
||||
d = ba.prepare(x); expect(buffer_size(d) == x);
|
||||
ba.commit(buffer_copy(d, buffer(s.data(), x)));
|
||||
expect(ba.size() == x);
|
||||
expect(buffer_size(ba.data()) == ba.size());
|
||||
d = ba.prepare(x); expect(buffer_size(d) == x);
|
||||
d = ba.prepare(0); expect(buffer_size(d) == 0);
|
||||
d = ba.prepare(z); expect(buffer_size(d) == z);
|
||||
d = ba.prepare(y); expect(buffer_size(d) == y);
|
||||
ba.commit(buffer_copy(d, buffer(s.data()+x, y)));
|
||||
ba.commit(1);
|
||||
expect(ba.size() == x + y);
|
||||
expect(buffer_size(ba.data()) == ba.size());
|
||||
d = ba.prepare(x); expect(buffer_size(d) == x);
|
||||
d = ba.prepare(y); expect(buffer_size(d) == y);
|
||||
d = ba.prepare(0); expect(buffer_size(d) == 0);
|
||||
d = ba.prepare(z); expect(buffer_size(d) == z);
|
||||
ba.commit(buffer_copy(d, buffer(s.data()+x+y, z)));
|
||||
ba.commit(2);
|
||||
expect(ba.size() == x + y + z);
|
||||
expect(buffer_size(ba.data()) == ba.size());
|
||||
expect(to_string(ba.data()) == s);
|
||||
ba.consume(t);
|
||||
d = ba.prepare(0); expect(buffer_size(d) == 0);
|
||||
expect(to_string(ba.data()) == s.substr(t, std::string::npos));
|
||||
ba.consume(u);
|
||||
expect(to_string(ba.data()) == s.substr(t + u, std::string::npos));
|
||||
ba.consume(v);
|
||||
expect(to_string(ba.data()) == "");
|
||||
ba.consume(1);
|
||||
d = ba.prepare(0); expect(buffer_size(d) == 0);
|
||||
try
|
||||
{
|
||||
ba.prepare(1);
|
||||
fail();
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
pass();
|
||||
}
|
||||
}
|
||||
}}}}}}
|
||||
}
|
||||
|
||||
void run() override
|
||||
{
|
||||
testStaticStreambuf();
|
||||
}
|
||||
};
|
||||
|
||||
BEAST_DEFINE_TESTSUITE(static_streambuf,asio,beast);
|
||||
|
||||
} // test
|
||||
} // asio
|
||||
} // beast
|
||||
@@ -0,0 +1,296 @@
|
||||
//
|
||||
// Copyright (c) 2013-2016 Vinnie Falco (vinnie dot falco at gmail dot com)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
|
||||
// Test that header file is self-contained.
|
||||
#include <beast/asio/streambuf.h>
|
||||
|
||||
#include <beast/unit_test/suite.h>
|
||||
#include <boost/asio/buffer.hpp>
|
||||
#include <atomic>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
|
||||
namespace beast {
|
||||
namespace asio {
|
||||
namespace test {
|
||||
|
||||
struct test_allocator_info
|
||||
{
|
||||
std::size_t ncopy = 0;
|
||||
std::size_t nmove = 0;
|
||||
std::size_t nselect = 0;
|
||||
};
|
||||
|
||||
template<class T,
|
||||
bool Assign, bool Move, bool Swap, bool Select>
|
||||
class test_allocator;
|
||||
|
||||
template<class T,
|
||||
bool Assign, bool Move, bool Swap, bool Select>
|
||||
struct test_allocator_base
|
||||
{
|
||||
};
|
||||
|
||||
template<class T,
|
||||
bool Assign, bool Move, bool Swap>
|
||||
struct test_allocator_base<T, Assign, Move, Swap, true>
|
||||
{
|
||||
static
|
||||
test_allocator<T, Assign, Move, Swap, true>
|
||||
select_on_container_copy_construction(
|
||||
test_allocator<T, Assign, Move, Swap, true> const& a)
|
||||
{
|
||||
return test_allocator<T, Assign, Move, Swap, true>{};
|
||||
}
|
||||
};
|
||||
|
||||
template<class T,
|
||||
bool Assign, bool Move, bool Swap, bool Select>
|
||||
class test_allocator : public test_allocator_base<
|
||||
T, Assign, Move, Swap, Select>
|
||||
{
|
||||
std::size_t id_;
|
||||
std::shared_ptr<test_allocator_info> info_;
|
||||
|
||||
template<class, bool, bool, bool, bool>
|
||||
friend class test_allocator;
|
||||
|
||||
public:
|
||||
using value_type = T;
|
||||
using propagate_on_container_copy_assignment =
|
||||
std::integral_constant<bool, Assign>;
|
||||
using propagate_on_container_move_assignment =
|
||||
std::integral_constant<bool, Move>;
|
||||
using propagate_on_container_swap =
|
||||
std::integral_constant<bool, Swap>;
|
||||
|
||||
template<class U>
|
||||
struct rebind
|
||||
{
|
||||
using other = test_allocator<
|
||||
U, Assign, Move, Swap, Select>;
|
||||
};
|
||||
|
||||
test_allocator()
|
||||
: id_([]
|
||||
{
|
||||
static std::atomic<
|
||||
std::size_t> sid(0);
|
||||
return ++sid;
|
||||
}())
|
||||
, info_(std::make_shared<test_allocator_info>())
|
||||
{
|
||||
}
|
||||
|
||||
test_allocator(test_allocator const& u) noexcept
|
||||
: id_(u.id_)
|
||||
, info_(u.info_)
|
||||
{
|
||||
++info_->ncopy;
|
||||
}
|
||||
|
||||
template<class U>
|
||||
test_allocator(test_allocator<
|
||||
U, Assign, Move, Swap, Select> const& u) noexcept
|
||||
: id_(u.id_)
|
||||
, info_(u.info_)
|
||||
{
|
||||
++info_->ncopy;
|
||||
}
|
||||
|
||||
test_allocator(test_allocator&& t)
|
||||
: id_(t.id_)
|
||||
, info_(t.info_)
|
||||
{
|
||||
++info_->nmove;
|
||||
}
|
||||
|
||||
value_type*
|
||||
allocate(std::size_t n)
|
||||
{
|
||||
return static_cast<value_type*>(
|
||||
::operator new (n*sizeof(value_type)));
|
||||
}
|
||||
|
||||
void
|
||||
deallocate(value_type* p, std::size_t) noexcept
|
||||
{
|
||||
::operator delete(p);
|
||||
}
|
||||
|
||||
std::size_t
|
||||
id() const
|
||||
{
|
||||
return id_;
|
||||
}
|
||||
|
||||
test_allocator_info const*
|
||||
operator->() const
|
||||
{
|
||||
return info_.get();
|
||||
}
|
||||
};
|
||||
|
||||
class streambuf_test : public unit_test::suite
|
||||
{
|
||||
public:
|
||||
template<class ConstBufferSequence>
|
||||
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<char const*>(b),
|
||||
buffer_size(b));
|
||||
return s;
|
||||
}
|
||||
|
||||
void testStreambuf()
|
||||
{
|
||||
using boost::asio::buffer;
|
||||
using boost::asio::buffer_cast;
|
||||
using boost::asio::buffer_size;
|
||||
std::string const s = "Hello, world";
|
||||
expect(s.size() == 12);
|
||||
for(std::size_t i = 1; i < 12; ++i) {
|
||||
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 = s.size() - (x + y);
|
||||
std::size_t v = s.size() - (t + u);
|
||||
{
|
||||
streambuf sb(i);
|
||||
decltype(sb)::mutable_buffers_type d;
|
||||
d = sb.prepare(z); expect(buffer_size(d) == z);
|
||||
d = sb.prepare(0); expect(buffer_size(d) == 0);
|
||||
d = sb.prepare(y); expect(buffer_size(d) == y);
|
||||
d = sb.prepare(x); expect(buffer_size(d) == x);
|
||||
sb.commit(buffer_copy(d, buffer(s.data(), x)));
|
||||
expect(sb.size() == x);
|
||||
expect(buffer_size(sb.data()) == sb.size());
|
||||
d = sb.prepare(x); expect(buffer_size(d) == x);
|
||||
d = sb.prepare(0); expect(buffer_size(d) == 0);
|
||||
d = sb.prepare(z); expect(buffer_size(d) == z);
|
||||
d = sb.prepare(y); expect(buffer_size(d) == y);
|
||||
sb.commit(buffer_copy(d, buffer(s.data()+x, y)));
|
||||
sb.commit(1);
|
||||
expect(sb.size() == x + y);
|
||||
expect(buffer_size(sb.data()) == sb.size());
|
||||
d = sb.prepare(x); expect(buffer_size(d) == x);
|
||||
d = sb.prepare(y); expect(buffer_size(d) == y);
|
||||
d = sb.prepare(0); expect(buffer_size(d) == 0);
|
||||
d = sb.prepare(z); expect(buffer_size(d) == z);
|
||||
sb.commit(buffer_copy(d, buffer(s.data()+x+y, z)));
|
||||
sb.commit(2);
|
||||
expect(sb.size() == x + y + z);
|
||||
expect(buffer_size(sb.data()) == sb.size());
|
||||
expect(to_string(sb.data()) == s);
|
||||
sb.consume(t);
|
||||
d = sb.prepare(0); expect(buffer_size(d) == 0);
|
||||
expect(to_string(sb.data()) == s.substr(t, std::string::npos));
|
||||
sb.consume(u);
|
||||
expect(to_string(sb.data()) == s.substr(t + u, std::string::npos));
|
||||
sb.consume(v);
|
||||
expect(to_string(sb.data()) == "");
|
||||
sb.consume(1);
|
||||
d = sb.prepare(0); expect(buffer_size(d) == 0);
|
||||
}
|
||||
}}}}}
|
||||
}
|
||||
|
||||
template<class Alloc1, class Alloc2>
|
||||
static
|
||||
bool
|
||||
eq(basic_streambuf<Alloc1> const& sb1,
|
||||
basic_streambuf<Alloc2> const& sb2)
|
||||
{
|
||||
return to_string(sb1.data()) == to_string(sb2.data());
|
||||
}
|
||||
|
||||
void testSpecial()
|
||||
{
|
||||
using boost::asio::buffer;
|
||||
using boost::asio::buffer_cast;
|
||||
using boost::asio::buffer_size;
|
||||
std::string const s = "Hello, world";
|
||||
expect(s.size() == 12);
|
||||
for(std::size_t i = 1; i < 12; ++i) {
|
||||
for(std::size_t x = 1; x < 4; ++x) {
|
||||
for(std::size_t y = 1; y < 4; ++y) {
|
||||
std::size_t z = s.size() - (x + y);
|
||||
{
|
||||
streambuf sb(i);
|
||||
sb.commit(buffer_copy(sb.prepare(x), buffer(s.data(), x)));
|
||||
sb.commit(buffer_copy(sb.prepare(y), buffer(s.data()+x, y)));
|
||||
sb.commit(buffer_copy(sb.prepare(z), buffer(s.data()+x+y, z)));
|
||||
expect(to_string(sb.data()) == s);
|
||||
{
|
||||
streambuf sb2(sb);
|
||||
expect(eq(sb, sb2));
|
||||
}
|
||||
{
|
||||
streambuf sb2;
|
||||
sb2 = sb;
|
||||
expect(eq(sb, sb2));
|
||||
}
|
||||
{
|
||||
streambuf sb2(std::move(sb));
|
||||
expect(to_string(sb2.data()) == s);
|
||||
expect(buffer_size(sb.data()) == 0);
|
||||
sb = std::move(sb2);
|
||||
expect(to_string(sb.data()) == s);
|
||||
expect(buffer_size(sb2.data()) == 0);
|
||||
}
|
||||
}
|
||||
}}}
|
||||
}
|
||||
|
||||
void testAllocator()
|
||||
{
|
||||
{
|
||||
using alloc_type =
|
||||
test_allocator<char, false, false, false, false>;
|
||||
using sb_type = basic_streambuf<alloc_type>;
|
||||
sb_type sb;
|
||||
expect(sb.get_allocator().id() == 1);
|
||||
}
|
||||
{
|
||||
using alloc_type =
|
||||
test_allocator<char, false, false, false, false>;
|
||||
using sb_type = basic_streambuf<alloc_type>;
|
||||
sb_type sb;
|
||||
expect(sb.get_allocator().id() == 2);
|
||||
sb_type sb2(sb);
|
||||
expect(sb2.get_allocator().id() == 2);
|
||||
sb_type sb3(sb, alloc_type{});
|
||||
//expect(sb3.get_allocator().id() == 3);
|
||||
}
|
||||
{
|
||||
using alloc_type =
|
||||
test_allocator<char, false, false, false, false>;
|
||||
using sb_type = basic_streambuf<alloc_type>;
|
||||
}
|
||||
}
|
||||
|
||||
void run() override
|
||||
{
|
||||
testStreambuf();
|
||||
testSpecial();
|
||||
testAllocator();
|
||||
}
|
||||
};
|
||||
|
||||
BEAST_DEFINE_TESTSUITE(streambuf,asio,beast);
|
||||
|
||||
} // test
|
||||
} // asio
|
||||
} // beast
|
||||
@@ -0,0 +1,9 @@
|
||||
//
|
||||
// Copyright (c) 2013-2016 Vinnie Falco (vinnie dot falco at gmail dot com)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
|
||||
// Test that header file is self-contained.
|
||||
#include <beast/asio/streambuf_readstream.h>
|
||||
@@ -0,0 +1,9 @@
|
||||
//
|
||||
// Copyright (c) 2013-2016 Vinnie Falco (vinnie dot falco at gmail dot com)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
|
||||
// Test that header file is self-contained.
|
||||
#include <beast/asio/temp_buffer.h>
|
||||
@@ -0,0 +1,9 @@
|
||||
//
|
||||
// Copyright (c) 2013-2016 Vinnie Falco (vinnie dot falco at gmail dot com)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
|
||||
// Test that header file is self-contained.
|
||||
#include <beast/asio/type_check.h>
|
||||
Reference in New Issue
Block a user