forked from boostorg/beast
Parser concept, fixes:
A new concept Parser is introduced with routines to read from a stream into the parser. This solves a problem with the old read interface where messages must be default constructible and move assignable. Parser fixes: * Fix detect invalid reason-phrase octets * Fix write_eof to set the 'complete' state on success * Fix consider parse complete if eof received on empty body WebSocket: * Increase coverage
This commit is contained in:
1 parent
8921da91b8
commit
2a8de0fd6b
28 files changed
+1536
-701
No files matched your search
@@ -7,6 +7,7 @@ GroupSources(test/core "/")
|
||||
add_executable (core-tests
|
||||
${BEAST_INCLUDES}
|
||||
../../extras/beast/unit_test/main.cpp
|
||||
buffer_test.hpp
|
||||
async_completion.cpp
|
||||
basic_streambuf.cpp
|
||||
bind_handler.cpp
|
||||
|
||||
+103
-56
@@ -8,6 +8,7 @@
|
||||
// Test that header file is self-contained.
|
||||
#include <beast/core/basic_streambuf.hpp>
|
||||
|
||||
#include "buffer_test.hpp"
|
||||
#include <beast/core/streambuf.hpp>
|
||||
#include <beast/core/to_string.hpp>
|
||||
#include <beast/unit_test/suite.hpp>
|
||||
@@ -148,6 +149,24 @@ public:
|
||||
return to_string(sb1.data()) == to_string(sb2.data());
|
||||
}
|
||||
|
||||
template<class ConstBufferSequence>
|
||||
void
|
||||
expect_size(std::size_t n, ConstBufferSequence const& buffers)
|
||||
{
|
||||
expect(test::size_pre(buffers) == n);
|
||||
expect(test::size_post(buffers) == n);
|
||||
expect(test::size_rev_pre(buffers) == n);
|
||||
expect(test::size_rev_post(buffers) == n);
|
||||
}
|
||||
|
||||
template<class U, class V>
|
||||
static
|
||||
void
|
||||
self_assign(U& u, V&& v)
|
||||
{
|
||||
u = std::forward<V>(v);
|
||||
}
|
||||
|
||||
void testSpecialMembers()
|
||||
{
|
||||
using boost::asio::buffer;
|
||||
@@ -177,19 +196,31 @@ public:
|
||||
{
|
||||
streambuf sb2(std::move(sb));
|
||||
expect(to_string(sb2.data()) == s);
|
||||
expect(buffer_size(sb.data()) == 0);
|
||||
expect_size(0, sb.data());
|
||||
sb = std::move(sb2);
|
||||
expect(to_string(sb.data()) == s);
|
||||
expect(buffer_size(sb2.data()) == 0);
|
||||
expect_size(0, sb2.data());
|
||||
}
|
||||
sb = sb;
|
||||
sb = std::move(sb);
|
||||
self_assign(sb, sb);
|
||||
expect(to_string(sb.data()) == s);
|
||||
self_assign(sb, std::move(sb));
|
||||
expect(to_string(sb.data()) == s);
|
||||
}
|
||||
}}}
|
||||
try
|
||||
{
|
||||
streambuf sb0(0);
|
||||
fail();
|
||||
}
|
||||
catch(std::exception const&)
|
||||
{
|
||||
pass();
|
||||
}
|
||||
}
|
||||
|
||||
void testAllocator()
|
||||
{
|
||||
// VFALCO This needs work
|
||||
{
|
||||
using alloc_type =
|
||||
test_allocator<char, false, false, false, false>;
|
||||
@@ -206,7 +237,6 @@ public:
|
||||
sb_type sb2(sb);
|
||||
expect(sb2.get_allocator().id() == 2);
|
||||
sb_type sb3(sb, alloc_type{});
|
||||
//expect(sb3.get_allocator().id() == 3);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -223,21 +253,9 @@ public:
|
||||
{
|
||||
streambuf sb(2);
|
||||
sb.prepare(2);
|
||||
{
|
||||
auto const bs = sb.prepare(5);
|
||||
expect(std::distance(
|
||||
bs.begin(), bs.end()) == 2);
|
||||
}
|
||||
{
|
||||
auto const bs = sb.prepare(8);
|
||||
expect(std::distance(
|
||||
bs.begin(), bs.end()) == 3);
|
||||
}
|
||||
{
|
||||
auto const bs = sb.prepare(4);
|
||||
expect(std::distance(
|
||||
bs.begin(), bs.end()) == 2);
|
||||
}
|
||||
expect(test::buffer_count(sb.prepare(5)) == 2);
|
||||
expect(test::buffer_count(sb.prepare(8)) == 3);
|
||||
expect(test::buffer_count(sb.prepare(4)) == 2);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -248,10 +266,21 @@ public:
|
||||
sb.prepare(2);
|
||||
sb.prepare(5);
|
||||
sb.commit(1);
|
||||
expect(buffer_size(sb.data()) == 1);
|
||||
expect_size(1, sb.data());
|
||||
}
|
||||
|
||||
void testStreambuf()
|
||||
void testConsume()
|
||||
{
|
||||
using boost::asio::buffer_size;
|
||||
streambuf sb(1);
|
||||
expect_size(5, sb.prepare(5));
|
||||
sb.commit(3);
|
||||
expect_size(3, sb.data());
|
||||
sb.consume(1);
|
||||
expect_size(2, sb.data());
|
||||
}
|
||||
|
||||
void testMatrix()
|
||||
{
|
||||
using boost::asio::buffer;
|
||||
using boost::asio::buffer_cast;
|
||||
@@ -354,41 +383,11 @@ public:
|
||||
sb.commit(1);
|
||||
sb.prepare(2);
|
||||
sb.commit(2);
|
||||
expect(buffer_size(sb.data()) == 3);
|
||||
expect_size(3, sb.data());
|
||||
sb.prepare(1);
|
||||
expect(buffer_size(sb.prepare(3)) == 3);
|
||||
expect(read_size_helper(sb, 3) == 3);
|
||||
expect_size(3, sb.prepare(3));
|
||||
sb.commit(2);
|
||||
try
|
||||
{
|
||||
streambuf sb0(0);
|
||||
fail();
|
||||
}
|
||||
catch(std::exception const&)
|
||||
{
|
||||
pass();
|
||||
}
|
||||
std::size_t n;
|
||||
n = 0;
|
||||
for(auto it = sb.data().begin();
|
||||
it != sb.data().end(); it++)
|
||||
++n;
|
||||
expect(n == 4);
|
||||
n = 0;
|
||||
for(auto it = sb.data().begin();
|
||||
it != sb.data().end(); ++it)
|
||||
++n;
|
||||
expect(n == 4);
|
||||
n = 0;
|
||||
for(auto it = sb.data().end();
|
||||
it != sb.data().begin(); it--)
|
||||
++n;
|
||||
expect(n == 4);
|
||||
n = 0;
|
||||
for(auto it = sb.data().end();
|
||||
it != sb.data().begin(); --it)
|
||||
++n;
|
||||
expect(n == 4);
|
||||
expect(test::buffer_count(sb.data()) == 4);
|
||||
}
|
||||
|
||||
void testOutputStream()
|
||||
@@ -398,15 +397,63 @@ public:
|
||||
expect(to_string(sb.data()) == "x");
|
||||
}
|
||||
|
||||
void testReadSizeHelper()
|
||||
{
|
||||
using boost::asio::buffer_size;
|
||||
{
|
||||
streambuf sb(10);
|
||||
expect(read_size_helper(sb, 0) == 0);
|
||||
expect(read_size_helper(sb, 1) == 1);
|
||||
expect(read_size_helper(sb, 10) == 10);
|
||||
expect(read_size_helper(sb, 20) == 20);
|
||||
expect(read_size_helper(sb, 1000) == 512);
|
||||
sb.prepare(3);
|
||||
sb.commit(3);
|
||||
expect(read_size_helper(sb, 10) == 7);
|
||||
expect(read_size_helper(sb, 1000) == 7);
|
||||
}
|
||||
{
|
||||
streambuf sb(1000);
|
||||
expect(read_size_helper(sb, 0) == 0);
|
||||
expect(read_size_helper(sb, 1) == 1);
|
||||
expect(read_size_helper(sb, 1000) == 1000);
|
||||
expect(read_size_helper(sb, 2000) == 1000);
|
||||
sb.prepare(3);
|
||||
expect(read_size_helper(sb, 0) == 0);
|
||||
expect(read_size_helper(sb, 1) == 1);
|
||||
expect(read_size_helper(sb, 1000) == 1000);
|
||||
expect(read_size_helper(sb, 2000) == 1000);
|
||||
sb.commit(3);
|
||||
expect(read_size_helper(sb, 0) == 0);
|
||||
expect(read_size_helper(sb, 1) == 1);
|
||||
expect(read_size_helper(sb, 1000) == 997);
|
||||
expect(read_size_helper(sb, 2000) == 997);
|
||||
sb.consume(2);
|
||||
expect(read_size_helper(sb, 0) == 0);
|
||||
expect(read_size_helper(sb, 1) == 1);
|
||||
expect(read_size_helper(sb, 1000) == 997);
|
||||
expect(read_size_helper(sb, 2000) == 997);
|
||||
}
|
||||
{
|
||||
streambuf sb(2);
|
||||
expect(test::buffer_count(sb.prepare(2)) == 1);
|
||||
expect(test::buffer_count(sb.prepare(3)) == 2);
|
||||
expect(buffer_size(sb.prepare(5)) == 5);
|
||||
expect(read_size_helper(sb, 10) == 6);
|
||||
}
|
||||
}
|
||||
|
||||
void run() override
|
||||
{
|
||||
testSpecialMembers();
|
||||
testAllocator();
|
||||
testPrepare();
|
||||
testCommit();
|
||||
testStreambuf();
|
||||
testConsume();
|
||||
testMatrix();
|
||||
testIterators();
|
||||
testOutputStream();
|
||||
testReadSizeHelper();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -116,7 +116,8 @@ public:
|
||||
|
||||
try
|
||||
{
|
||||
expect((buffer_size(*bs.end()) == 0, false));
|
||||
buffer_size(*bs.end());
|
||||
fail();
|
||||
}
|
||||
catch(std::exception const&)
|
||||
{
|
||||
|
||||
@@ -0,0 +1,89 @@
|
||||
//
|
||||
// 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)
|
||||
//
|
||||
|
||||
#ifndef BEAST_TEST_BUFFER_TEST_HPP
|
||||
#define BEAST_TEST_BUFFER_TEST_HPP
|
||||
|
||||
#include <beast/core/buffer_concepts.hpp>
|
||||
#include <boost/asio/buffer.hpp>
|
||||
#include <algorithm>
|
||||
#include <type_traits>
|
||||
|
||||
namespace beast {
|
||||
namespace test {
|
||||
|
||||
template<class ConstBufferSequence>
|
||||
typename std::enable_if<
|
||||
is_ConstBufferSequence<ConstBufferSequence>::value,
|
||||
std::size_t>::type
|
||||
buffer_count(ConstBufferSequence const& buffers)
|
||||
{
|
||||
return std::distance(buffers.begin(), buffers.end());
|
||||
}
|
||||
|
||||
template<class ConstBufferSequence>
|
||||
typename std::enable_if<
|
||||
is_ConstBufferSequence<ConstBufferSequence>::value,
|
||||
std::size_t>::type
|
||||
size_pre(ConstBufferSequence const& buffers)
|
||||
{
|
||||
std::size_t n = 0;
|
||||
for(auto it = buffers.begin(); it != buffers.end(); ++it)
|
||||
{
|
||||
typename ConstBufferSequence::const_iterator it0(std::move(it));
|
||||
typename ConstBufferSequence::const_iterator it1(it0);
|
||||
typename ConstBufferSequence::const_iterator it2;
|
||||
it2 = it1;
|
||||
n += boost::asio::buffer_size(*it2);
|
||||
it = std::move(it2);
|
||||
}
|
||||
return n;
|
||||
}
|
||||
|
||||
template<class ConstBufferSequence>
|
||||
typename std::enable_if<
|
||||
is_ConstBufferSequence<ConstBufferSequence>::value,
|
||||
std::size_t>::type
|
||||
size_post(ConstBufferSequence const& buffers)
|
||||
{
|
||||
std::size_t n = 0;
|
||||
for(auto it = buffers.begin(); it != buffers.end(); it++)
|
||||
n += boost::asio::buffer_size(*it);
|
||||
return n;
|
||||
}
|
||||
|
||||
template<class ConstBufferSequence>
|
||||
typename std::enable_if<
|
||||
is_ConstBufferSequence<ConstBufferSequence>::value,
|
||||
std::size_t>::type
|
||||
size_rev_pre(ConstBufferSequence const& buffers)
|
||||
{
|
||||
std::size_t n = 0;
|
||||
for(auto it = buffers.end(); it != buffers.begin();)
|
||||
n += boost::asio::buffer_size(*--it);
|
||||
return n;
|
||||
}
|
||||
|
||||
template<class ConstBufferSequence>
|
||||
typename std::enable_if<
|
||||
is_ConstBufferSequence<ConstBufferSequence>::value,
|
||||
std::size_t>::type
|
||||
size_rev_post(ConstBufferSequence const& buffers)
|
||||
{
|
||||
std::size_t n = 0;
|
||||
for(auto it = buffers.end(); it != buffers.begin();)
|
||||
{
|
||||
it--;
|
||||
n += boost::asio::buffer_size(*it);
|
||||
}
|
||||
return n;
|
||||
}
|
||||
|
||||
} // test
|
||||
} // beast
|
||||
|
||||
#endif
|
||||
@@ -8,6 +8,8 @@
|
||||
// Test that header file is self-contained.
|
||||
#include <beast/core/consuming_buffers.hpp>
|
||||
|
||||
#include "buffer_test.hpp"
|
||||
#include <beast/core/to_string.hpp>
|
||||
#include <beast/unit_test/suite.hpp>
|
||||
#include <boost/asio/buffer.hpp>
|
||||
#include <string>
|
||||
@@ -17,22 +19,25 @@ namespace beast {
|
||||
class consuming_buffers_test : public beast::unit_test::suite
|
||||
{
|
||||
public:
|
||||
template<class ConstBufferSequence>
|
||||
template<class Buffers1, class Buffers2>
|
||||
static
|
||||
std::string
|
||||
to_string(ConstBufferSequence const& bs)
|
||||
bool
|
||||
eq(Buffers1 const& lhs, Buffers2 const& rhs)
|
||||
{
|
||||
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;
|
||||
return to_string(lhs) == to_string(rhs);
|
||||
}
|
||||
|
||||
void testBuffers()
|
||||
template<class ConstBufferSequence>
|
||||
void
|
||||
expect_size(std::size_t n, ConstBufferSequence const& buffers)
|
||||
{
|
||||
expect(test::size_pre(buffers) == n);
|
||||
expect(test::size_post(buffers) == n);
|
||||
expect(test::size_rev_pre(buffers) == n);
|
||||
expect(test::size_rev_post(buffers) == n);
|
||||
}
|
||||
|
||||
void testMatrix()
|
||||
{
|
||||
using boost::asio::buffer;
|
||||
using boost::asio::const_buffer;
|
||||
@@ -54,16 +59,23 @@ public:
|
||||
const_buffer{&buf[i+j], k}}};
|
||||
consuming_buffers<decltype(bs)> cb(bs);
|
||||
expect(to_string(cb) == s);
|
||||
expect_size(s.size(), cb);
|
||||
cb.consume(0);
|
||||
expect(eq(cb, consumed_buffers(bs, 0)));
|
||||
expect(to_string(cb) == s);
|
||||
expect_size(s.size(), cb);
|
||||
cb.consume(x);
|
||||
expect(to_string(cb) == s.substr(x));
|
||||
expect(eq(cb, consumed_buffers(bs, x)));
|
||||
cb.consume(y);
|
||||
expect(to_string(cb) == s.substr(x+y));
|
||||
expect(eq(cb, consumed_buffers(bs, x+y)));
|
||||
cb.consume(z);
|
||||
expect(to_string(cb) == "");
|
||||
expect(eq(cb, consumed_buffers(bs, x+y+z)));
|
||||
cb.consume(1);
|
||||
expect(to_string(cb) == "");
|
||||
expect(eq(cb, consumed_buffers(bs, x+y+z)));
|
||||
}
|
||||
}}}}
|
||||
}
|
||||
@@ -94,7 +106,7 @@ public:
|
||||
|
||||
void run() override
|
||||
{
|
||||
testBuffers();
|
||||
testMatrix();
|
||||
testNullBuffers();
|
||||
testIterator();
|
||||
}
|
||||
|
||||
@@ -33,20 +33,20 @@ public:
|
||||
return s;
|
||||
}
|
||||
|
||||
void testBuffers()
|
||||
template<class BufferType>
|
||||
void testMatrix()
|
||||
{
|
||||
using boost::asio::buffer_size;
|
||||
using boost::asio::const_buffer;
|
||||
std::string const s = "Hello, world";
|
||||
std::string 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}}};
|
||||
std::array<BufferType, 3> bs{{
|
||||
BufferType{&s[0], x},
|
||||
BufferType{&s[x], y},
|
||||
BufferType{&s[x+y], z}}};
|
||||
for(std::size_t i = 0; i <= s.size() + 1; ++i)
|
||||
{
|
||||
auto pb = prepare_buffers(i, bs);
|
||||
@@ -104,7 +104,8 @@ public:
|
||||
|
||||
void run() override
|
||||
{
|
||||
testBuffers();
|
||||
testMatrix<boost::asio::const_buffer>();
|
||||
testMatrix<boost::asio::mutable_buffer>();
|
||||
testNullBuffers();
|
||||
testIterator();
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user