mirror of
https://github.com/boostorg/beast.git
synced 2025-07-31 21:34:46 +02:00
Improvements to code coverage:
More tests and test cases are added to bring up the percentage of library code covered by tests.
This commit is contained in:
1
TODO.txt
1
TODO.txt
@@ -55,3 +55,4 @@ HTTP:
|
|||||||
* Make empty_body write-only, remove reader nested type
|
* Make empty_body write-only, remove reader nested type
|
||||||
* Add concepts WritableBody ReadableBody with type checks,
|
* Add concepts WritableBody ReadableBody with type checks,
|
||||||
check them in read and write functions
|
check them in read and write functions
|
||||||
|
* Branch prediction hints in parser
|
||||||
|
@@ -228,12 +228,6 @@ prepare(message_v1<isRequest, Body, Headers>& msg,
|
|||||||
msg.headers["Connection"], "upgrade"))
|
msg.headers["Connection"], "upgrade"))
|
||||||
throw std::invalid_argument(
|
throw std::invalid_argument(
|
||||||
"invalid version for Connection: upgrade");
|
"invalid version for Connection: upgrade");
|
||||||
|
|
||||||
// rfc7230 3.3.2
|
|
||||||
if(msg.headers.exists("Content-Length") &&
|
|
||||||
msg.headers.exists("Transfer-Encoding"))
|
|
||||||
throw std::invalid_argument(
|
|
||||||
"Content-Length and Transfer-Encoding cannot be combined");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} // http
|
} // http
|
||||||
|
@@ -39,22 +39,11 @@ write_firstline(Streambuf& streambuf,
|
|||||||
write(streambuf, msg.method);
|
write(streambuf, msg.method);
|
||||||
write(streambuf, " ");
|
write(streambuf, " ");
|
||||||
write(streambuf, msg.url);
|
write(streambuf, msg.url);
|
||||||
switch(msg.version)
|
|
||||||
{
|
|
||||||
case 10:
|
|
||||||
write(streambuf, " HTTP/1.0\r\n");
|
|
||||||
break;
|
|
||||||
case 11:
|
|
||||||
write(streambuf, " HTTP/1.1\r\n");
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
write(streambuf, " HTTP/");
|
write(streambuf, " HTTP/");
|
||||||
write(streambuf, msg.version / 10);
|
write(streambuf, msg.version / 10);
|
||||||
write(streambuf, ".");
|
write(streambuf, ".");
|
||||||
write(streambuf, msg.version % 10);
|
write(streambuf, msg.version % 10);
|
||||||
write(streambuf, "\r\n");
|
write(streambuf, "\r\n");
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class Streambuf, class Body, class Headers>
|
template<class Streambuf, class Body, class Headers>
|
||||||
@@ -62,22 +51,11 @@ void
|
|||||||
write_firstline(Streambuf& streambuf,
|
write_firstline(Streambuf& streambuf,
|
||||||
message_v1<false, Body, Headers> const& msg)
|
message_v1<false, Body, Headers> const& msg)
|
||||||
{
|
{
|
||||||
switch(msg.version)
|
write(streambuf, "HTTP/");
|
||||||
{
|
|
||||||
case 10:
|
|
||||||
write(streambuf, "HTTP/1.0 ");
|
|
||||||
break;
|
|
||||||
case 11:
|
|
||||||
write(streambuf, "HTTP/1.1 ");
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
write(streambuf, " HTTP/");
|
|
||||||
write(streambuf, msg.version / 10);
|
write(streambuf, msg.version / 10);
|
||||||
write(streambuf, ".");
|
write(streambuf, ".");
|
||||||
write(streambuf, msg.version % 10);
|
write(streambuf, msg.version % 10);
|
||||||
write(streambuf, " ");
|
write(streambuf, " ");
|
||||||
break;
|
|
||||||
}
|
|
||||||
write(streambuf, msg.status);
|
write(streambuf, msg.status);
|
||||||
write(streambuf, " ");
|
write(streambuf, " ");
|
||||||
write(streambuf, msg.reason);
|
write(streambuf, msg.reason);
|
||||||
|
@@ -1,21 +1,9 @@
|
|||||||
//------------------------------------------------------------------------------
|
//
|
||||||
/*
|
// Copyright (c) 2013-2016 Vinnie Falco (vinnie dot falco at gmail dot com)
|
||||||
This file is part of Beast: https://github.com/vinniefalco/Beast
|
//
|
||||||
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.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)
|
||||||
Permission to use, copy, modify, and/or distribute this software for any
|
//
|
||||||
purpose with or without fee is hereby granted, provided that the above
|
|
||||||
copyright notice and this permission notice appear in all copies.
|
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
|
||||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
|
||||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
|
||||||
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
|
||||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
|
||||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
|
||||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
|
||||||
*/
|
|
||||||
//==============================================================================
|
|
||||||
|
|
||||||
#ifndef BEAST_WEBSOCKET_DETAIL_DEBUG_HPP
|
#ifndef BEAST_WEBSOCKET_DETAIL_DEBUG_HPP
|
||||||
#define BEAST_WEBSOCKET_DETAIL_DEBUG_HPP
|
#define BEAST_WEBSOCKET_DETAIL_DEBUG_HPP
|
||||||
|
@@ -119,6 +119,12 @@ write(Streambuf& sb, frame_header const& fh)
|
|||||||
std::size_t n;
|
std::size_t n;
|
||||||
std::uint8_t b[14];
|
std::uint8_t b[14];
|
||||||
b[0] = (fh.fin ? 0x80 : 0x00) | static_cast<std::uint8_t>(fh.op);
|
b[0] = (fh.fin ? 0x80 : 0x00) | static_cast<std::uint8_t>(fh.op);
|
||||||
|
if(fh.rsv1)
|
||||||
|
b[0] |= 0x40;
|
||||||
|
if(fh.rsv2)
|
||||||
|
b[0] |= 0x20;
|
||||||
|
if(fh.rsv3)
|
||||||
|
b[0] |= 0x10;
|
||||||
b[1] = fh.mask ? 0x80 : 0x00;
|
b[1] = fh.mask ? 0x80 : 0x00;
|
||||||
if (fh.len <= 125)
|
if (fh.len <= 125)
|
||||||
{
|
{
|
||||||
@@ -196,13 +202,6 @@ read_fh1(frame_header& fh, Streambuf& sb,
|
|||||||
code = close_code::protocol_error;
|
code = close_code::protocol_error;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
// invalid opcode
|
|
||||||
// (only in locally generated headers)
|
|
||||||
if(! is_valid(fh.op))
|
|
||||||
{
|
|
||||||
code = close_code::protocol_error;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
// fragmented control message
|
// fragmented control message
|
||||||
if(is_control(fh.op) && ! fh.fin)
|
if(is_control(fh.op) && ! fh.fin)
|
||||||
{
|
{
|
||||||
@@ -243,13 +242,7 @@ read_fh2(frame_header& fh, Streambuf& sb,
|
|||||||
std::uint8_t b[2];
|
std::uint8_t b[2];
|
||||||
assert(buffer_size(sb.data()) >= sizeof(b));
|
assert(buffer_size(sb.data()) >= sizeof(b));
|
||||||
sb.consume(buffer_copy(buffer(b), sb.data()));
|
sb.consume(buffer_copy(buffer(b), sb.data()));
|
||||||
#if 0
|
|
||||||
// Causes strict-aliasing warning in gcc
|
|
||||||
fh.len = reinterpret_cast<
|
|
||||||
big_uint16_buf_t const*>(&b[0])->value();
|
|
||||||
#else
|
|
||||||
fh.len = big_uint16_to_native(&b[0]);
|
fh.len = big_uint16_to_native(&b[0]);
|
||||||
#endif
|
|
||||||
// length not canonical
|
// length not canonical
|
||||||
if(fh.len < 126)
|
if(fh.len < 126)
|
||||||
{
|
{
|
||||||
@@ -263,13 +256,7 @@ read_fh2(frame_header& fh, Streambuf& sb,
|
|||||||
std::uint8_t b[8];
|
std::uint8_t b[8];
|
||||||
assert(buffer_size(sb.data()) >= sizeof(b));
|
assert(buffer_size(sb.data()) >= sizeof(b));
|
||||||
sb.consume(buffer_copy(buffer(b), sb.data()));
|
sb.consume(buffer_copy(buffer(b), sb.data()));
|
||||||
#if 0
|
|
||||||
// Causes strict-aliasing warning in gcc
|
|
||||||
fh.len = reinterpret_cast<
|
|
||||||
big_uint64_buf_t const*>(&b[0])->value();
|
|
||||||
#else
|
|
||||||
fh.len = big_uint64_to_native(&b[0]);
|
fh.len = big_uint64_to_native(&b[0]);
|
||||||
#endif
|
|
||||||
// length not canonical
|
// length not canonical
|
||||||
if(fh.len < 65536)
|
if(fh.len < 65536)
|
||||||
{
|
{
|
||||||
@@ -284,13 +271,12 @@ read_fh2(frame_header& fh, Streambuf& sb,
|
|||||||
std::uint8_t b[4];
|
std::uint8_t b[4];
|
||||||
assert(buffer_size(sb.data()) >= sizeof(b));
|
assert(buffer_size(sb.data()) >= sizeof(b));
|
||||||
sb.consume(buffer_copy(buffer(b), sb.data()));
|
sb.consume(buffer_copy(buffer(b), sb.data()));
|
||||||
#if 0
|
|
||||||
// Causes strict-aliasing warning in gcc
|
|
||||||
fh.key = reinterpret_cast<
|
|
||||||
little_uint32_buf_t const*>(&b[0])->value();
|
|
||||||
#else
|
|
||||||
fh.key = little_uint32_to_native(&b[0]);
|
fh.key = little_uint32_to_native(&b[0]);
|
||||||
#endif
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// initialize this otherwise operator== breaks
|
||||||
|
fh.key = 0;
|
||||||
}
|
}
|
||||||
code = close_code::none;
|
code = close_code::none;
|
||||||
}
|
}
|
||||||
|
@@ -1,24 +1,12 @@
|
|||||||
//------------------------------------------------------------------------------
|
//
|
||||||
/*
|
// Copyright (c) 2013-2016 Vinnie Falco (vinnie dot falco at gmail dot com)
|
||||||
This file is part of Beast: https://github.com/vinniefalco/Beast
|
//
|
||||||
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.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)
|
||||||
|
//
|
||||||
|
|
||||||
Permission to use, copy, modify, and/or distribute this software for any
|
#ifndef BEAST_WEBSOCKET_DETAIL_MASK_HPP
|
||||||
purpose with or without fee is hereby granted, provided that the above
|
#define BEAST_WEBSOCKET_DETAIL_MASK_HPP
|
||||||
copyright notice and this permission notice appear in all copies.
|
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
|
||||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
|
||||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
|
||||||
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
|
||||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
|
||||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
|
||||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
|
||||||
*/
|
|
||||||
//==============================================================================
|
|
||||||
|
|
||||||
#ifndef BEAST_WEBSOCKETDETAIL_MASKGEN_HPP
|
|
||||||
#define BEAST_WEBSOCKETDETAIL_MASKGEN_HPP
|
|
||||||
|
|
||||||
#include <boost/asio/buffer.hpp>
|
#include <boost/asio/buffer.hpp>
|
||||||
#include <array>
|
#include <array>
|
||||||
@@ -33,13 +21,14 @@ namespace detail {
|
|||||||
|
|
||||||
// Pseudo-random source of mask keys
|
// Pseudo-random source of mask keys
|
||||||
//
|
//
|
||||||
template<class = void>
|
template<class Generator>
|
||||||
class maskgen_t
|
class maskgen_t
|
||||||
{
|
{
|
||||||
std::mt19937 g_;
|
Generator g_;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
using result_type = typename std::mt19937::result_type;
|
using result_type =
|
||||||
|
typename Generator::result_type;
|
||||||
|
|
||||||
maskgen_t();
|
maskgen_t();
|
||||||
|
|
||||||
@@ -50,15 +39,15 @@ public:
|
|||||||
rekey();
|
rekey();
|
||||||
};
|
};
|
||||||
|
|
||||||
template<class _>
|
template<class Generator>
|
||||||
maskgen_t<_>::maskgen_t()
|
maskgen_t<Generator>::maskgen_t()
|
||||||
{
|
{
|
||||||
rekey();
|
rekey();
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class _>
|
template<class Generator>
|
||||||
auto
|
auto
|
||||||
maskgen_t<_>::operator()() noexcept ->
|
maskgen_t<Generator>::operator()() noexcept ->
|
||||||
result_type
|
result_type
|
||||||
{
|
{
|
||||||
for(;;)
|
for(;;)
|
||||||
@@ -78,7 +67,7 @@ maskgen_t<_>::rekey()
|
|||||||
g_.seed(ss);
|
g_.seed(ss);
|
||||||
}
|
}
|
||||||
|
|
||||||
using maskgen = maskgen_t<>;
|
using maskgen = maskgen_t<std::mt19937>;
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
@@ -73,6 +73,8 @@ unit-test websocket-tests :
|
|||||||
websocket/stream.cpp
|
websocket/stream.cpp
|
||||||
websocket/teardown.cpp
|
websocket/teardown.cpp
|
||||||
websocket/utf8_checker.cpp
|
websocket/utf8_checker.cpp
|
||||||
|
websocket/detail/frame.cpp
|
||||||
|
websocket/detail/mask.cpp
|
||||||
;
|
;
|
||||||
|
|
||||||
exe websocket-echo :
|
exe websocket-echo :
|
||||||
|
@@ -10,7 +10,6 @@
|
|||||||
|
|
||||||
#include "message_fuzz.hpp"
|
#include "message_fuzz.hpp"
|
||||||
|
|
||||||
#include <beast/error.hpp>
|
|
||||||
#include <beast/streambuf.hpp>
|
#include <beast/streambuf.hpp>
|
||||||
#include <beast/write_streambuf.hpp>
|
#include <beast/write_streambuf.hpp>
|
||||||
#include <beast/http/rfc2616.hpp>
|
#include <beast/http/rfc2616.hpp>
|
||||||
@@ -102,6 +101,68 @@ public:
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template<bool isRequest>
|
||||||
|
struct cb_fail
|
||||||
|
: public basic_parser_v1<isRequest, cb_fail<isRequest>>
|
||||||
|
|
||||||
|
{
|
||||||
|
std::size_t n_;
|
||||||
|
|
||||||
|
void fail(error_code& ec)
|
||||||
|
{
|
||||||
|
if(n_ > 0)
|
||||||
|
--n_;
|
||||||
|
if(! n_)
|
||||||
|
ec = boost::system::errc::make_error_code(
|
||||||
|
boost::system::errc::invalid_argument);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
friend class basic_parser_v1<isRequest, cb_checker<isRequest>>;
|
||||||
|
|
||||||
|
void on_method(boost::string_ref const&, error_code& ec)
|
||||||
|
{
|
||||||
|
fail(ec);
|
||||||
|
}
|
||||||
|
void on_uri(boost::string_ref const&, error_code& ec)
|
||||||
|
{
|
||||||
|
fail(ec);
|
||||||
|
}
|
||||||
|
void on_reason(boost::string_ref const&, error_code& ec)
|
||||||
|
{
|
||||||
|
fail(ec);
|
||||||
|
}
|
||||||
|
void on_request(error_code& ec)
|
||||||
|
{
|
||||||
|
fail(ec);
|
||||||
|
}
|
||||||
|
void on_response(error_code& ec)
|
||||||
|
{
|
||||||
|
fail(ec);
|
||||||
|
}
|
||||||
|
void on_field(boost::string_ref const&, error_code& ec)
|
||||||
|
{
|
||||||
|
fail(ec);
|
||||||
|
}
|
||||||
|
void on_value(boost::string_ref const&, error_code& ec)
|
||||||
|
{
|
||||||
|
fail(ec);
|
||||||
|
}
|
||||||
|
int on_headers(error_code& ec)
|
||||||
|
{
|
||||||
|
fail(ec);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
void on_body(boost::string_ref const&, error_code& ec)
|
||||||
|
{
|
||||||
|
fail(ec);
|
||||||
|
}
|
||||||
|
void on_complete(error_code& ec)
|
||||||
|
{
|
||||||
|
fail(ec);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
//--------------------------------------------------------------------------
|
//--------------------------------------------------------------------------
|
||||||
|
|
||||||
static
|
static
|
||||||
@@ -177,6 +238,50 @@ public:
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
void
|
||||||
|
testFail()
|
||||||
|
{
|
||||||
|
using boost::asio::buffer;
|
||||||
|
{
|
||||||
|
std::string const s =
|
||||||
|
"GET / HTTP/1.1\r\n"
|
||||||
|
"User-Agent: test\r\n"
|
||||||
|
"Content-Length: 1\r\n"
|
||||||
|
"\r\n"
|
||||||
|
"*";
|
||||||
|
static std::size_t constexpr limit = 100;
|
||||||
|
std::size_t n = 1;
|
||||||
|
for(; n < limit; ++n)
|
||||||
|
{
|
||||||
|
error_code ec;
|
||||||
|
basic_parser_v1<true, cb_fail<true>> p;
|
||||||
|
p.write(buffer(s), ec);
|
||||||
|
if(! ec)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
expect(n < limit);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
std::string const s =
|
||||||
|
"HTTP/1.1 200 OK\r\n"
|
||||||
|
"Server: test\r\n"
|
||||||
|
"Content-Length: 1\r\n"
|
||||||
|
"\r\n"
|
||||||
|
"*";
|
||||||
|
static std::size_t constexpr limit = 100;
|
||||||
|
std::size_t n = 1;
|
||||||
|
for(; n < limit; ++n)
|
||||||
|
{
|
||||||
|
error_code ec;
|
||||||
|
basic_parser_v1<false, cb_fail<false>> p;
|
||||||
|
p.write(buffer(s), ec);
|
||||||
|
if(! ec)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
expect(n < limit);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
testCallbacks()
|
testCallbacks()
|
||||||
{
|
{
|
||||||
@@ -647,6 +752,7 @@ public:
|
|||||||
|
|
||||||
void run() override
|
void run() override
|
||||||
{
|
{
|
||||||
|
testFail();
|
||||||
testCallbacks();
|
testCallbacks();
|
||||||
testVersion();
|
testVersion();
|
||||||
testFlags();
|
testFlags();
|
||||||
|
@@ -7,3 +7,50 @@
|
|||||||
|
|
||||||
// Test that header file is self-contained.
|
// Test that header file is self-contained.
|
||||||
#include <beast/http/parse_error.hpp>
|
#include <beast/http/parse_error.hpp>
|
||||||
|
|
||||||
|
#include <beast/unit_test/suite.hpp>
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
namespace beast {
|
||||||
|
namespace http {
|
||||||
|
|
||||||
|
class parse_error_test : public unit_test::suite
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
void check(char const* name, parse_error ev)
|
||||||
|
{
|
||||||
|
auto const ec = make_error_code(ev);
|
||||||
|
expect(std::string{ec.category().name()} == name);
|
||||||
|
expect(! ec.message().empty());
|
||||||
|
expect(std::addressof(ec.category()) ==
|
||||||
|
std::addressof(get_parse_error_category()));
|
||||||
|
expect(get_parse_error_category().equivalent(static_cast<int>(ev),
|
||||||
|
ec.category().default_error_condition(static_cast<int>(ev))));
|
||||||
|
expect(get_parse_error_category().equivalent(
|
||||||
|
ec, static_cast<int>(ev)));
|
||||||
|
}
|
||||||
|
|
||||||
|
void run() override
|
||||||
|
{
|
||||||
|
check("http", parse_error::connection_closed);
|
||||||
|
check("http", parse_error::bad_method);
|
||||||
|
check("http", parse_error::bad_uri);
|
||||||
|
check("http", parse_error::bad_version);
|
||||||
|
check("http", parse_error::bad_crlf);
|
||||||
|
check("http", parse_error::bad_request);
|
||||||
|
check("http", parse_error::bad_status_code);
|
||||||
|
check("http", parse_error::bad_status);
|
||||||
|
check("http", parse_error::bad_field);
|
||||||
|
check("http", parse_error::bad_value);
|
||||||
|
check("http", parse_error::bad_content_length);
|
||||||
|
check("http", parse_error::illegal_content_length);
|
||||||
|
check("http", parse_error::bad_on_headers_rv);
|
||||||
|
check("http", parse_error::invalid_chunk_size);
|
||||||
|
check("http", parse_error::short_read);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
BEAST_DEFINE_TESTSUITE(parse_error,http,beast);
|
||||||
|
|
||||||
|
} // http
|
||||||
|
} // beast
|
||||||
|
@@ -7,3 +7,23 @@
|
|||||||
|
|
||||||
// Test that header file is self-contained.
|
// Test that header file is self-contained.
|
||||||
#include <beast/http/reason.hpp>
|
#include <beast/http/reason.hpp>
|
||||||
|
|
||||||
|
#include <beast/unit_test/suite.hpp>
|
||||||
|
|
||||||
|
namespace beast {
|
||||||
|
namespace http {
|
||||||
|
|
||||||
|
class reason_test : public unit_test::suite
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
void run() override
|
||||||
|
{
|
||||||
|
for(int i = 1; i <= 999; ++i)
|
||||||
|
expect(reason_string(i) != nullptr);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
BEAST_DEFINE_TESTSUITE(reason,http,beast);
|
||||||
|
|
||||||
|
} // http
|
||||||
|
} // beast
|
||||||
|
@@ -56,7 +56,7 @@ public:
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
struct test_Body
|
struct fail_body
|
||||||
{
|
{
|
||||||
using value_type = std::string;
|
using value_type = std::string;
|
||||||
|
|
||||||
@@ -67,7 +67,41 @@ public:
|
|||||||
public:
|
public:
|
||||||
template<bool isRequest, class Allocator>
|
template<bool isRequest, class Allocator>
|
||||||
explicit
|
explicit
|
||||||
writer(message<isRequest, test_Body, Allocator> const& msg)
|
writer(message<isRequest, fail_body, Allocator> const& msg)
|
||||||
|
: body_(msg.body)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
init(error_code& ec)
|
||||||
|
{
|
||||||
|
ec = boost::system::errc::make_error_code(
|
||||||
|
boost::system::errc::errc_t::invalid_argument);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class Write>
|
||||||
|
boost::tribool
|
||||||
|
operator()(resume_context&&, error_code&, Write&& write)
|
||||||
|
{
|
||||||
|
write(boost::asio::buffer(body_));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
struct test_body
|
||||||
|
{
|
||||||
|
using value_type = std::string;
|
||||||
|
|
||||||
|
class writer
|
||||||
|
{
|
||||||
|
std::size_t pos_ = 0;
|
||||||
|
value_type const& body_;
|
||||||
|
|
||||||
|
public:
|
||||||
|
template<bool isRequest, class Allocator>
|
||||||
|
explicit
|
||||||
|
writer(message<isRequest, test_body, Allocator> const& msg)
|
||||||
: body_(msg.body)
|
: body_(msg.body)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
@@ -148,7 +182,7 @@ public:
|
|||||||
}
|
}
|
||||||
// no content-length HTTP/1.0
|
// no content-length HTTP/1.0
|
||||||
{
|
{
|
||||||
message_v1<true, test_Body, headers> m{{
|
message_v1<true, test_body, headers> m{{
|
||||||
"GET", "/", 10}};
|
"GET", "/", 10}};
|
||||||
m.headers.insert("User-Agent", "test");
|
m.headers.insert("User-Agent", "test");
|
||||||
m.body = "*";
|
m.body = "*";
|
||||||
@@ -214,7 +248,7 @@ public:
|
|||||||
}
|
}
|
||||||
// no content-length HTTP/1.1
|
// no content-length HTTP/1.1
|
||||||
{
|
{
|
||||||
message_v1<true, test_Body, headers> m{{
|
message_v1<true, test_body, headers> m{{
|
||||||
"GET", "/", 11}};
|
"GET", "/", 11}};
|
||||||
m.headers.insert("User-Agent", "test");
|
m.headers.insert("User-Agent", "test");
|
||||||
m.body = "*";
|
m.body = "*";
|
||||||
|
@@ -139,9 +139,65 @@ public:
|
|||||||
}}}}}}
|
}}}}}}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void testIterators()
|
||||||
|
{
|
||||||
|
static_streambuf_n<2> ba;
|
||||||
|
{
|
||||||
|
auto mb = ba.prepare(2);
|
||||||
|
std::size_t n;
|
||||||
|
n = 0;
|
||||||
|
for(auto it = mb.begin();
|
||||||
|
it != mb.end(); it++)
|
||||||
|
++n;
|
||||||
|
expect(n == 1);
|
||||||
|
mb = ba.prepare(2);
|
||||||
|
n = 0;
|
||||||
|
for(auto it = mb.begin();
|
||||||
|
it != mb.end(); ++it)
|
||||||
|
++n;
|
||||||
|
expect(n == 1);
|
||||||
|
mb = ba.prepare(2);
|
||||||
|
n = 0;
|
||||||
|
for(auto it = mb.end();
|
||||||
|
it != mb.begin(); it--)
|
||||||
|
++n;
|
||||||
|
expect(n == 1);
|
||||||
|
mb = ba.prepare(2);
|
||||||
|
n = 0;
|
||||||
|
for(auto it = mb.end();
|
||||||
|
it != mb.begin(); --it)
|
||||||
|
++n;
|
||||||
|
expect(n == 1);
|
||||||
|
}
|
||||||
|
ba.prepare(2);
|
||||||
|
ba.commit(1);
|
||||||
|
std::size_t n;
|
||||||
|
n = 0;
|
||||||
|
for(auto it = ba.data().begin();
|
||||||
|
it != ba.data().end(); it++)
|
||||||
|
++n;
|
||||||
|
expect(n == 1);
|
||||||
|
n = 0;
|
||||||
|
for(auto it = ba.data().begin();
|
||||||
|
it != ba.data().end(); ++it)
|
||||||
|
++n;
|
||||||
|
expect(n == 1);
|
||||||
|
n = 0;
|
||||||
|
for(auto it = ba.data().end();
|
||||||
|
it != ba.data().begin(); it--)
|
||||||
|
++n;
|
||||||
|
expect(n == 1);
|
||||||
|
n = 0;
|
||||||
|
for(auto it = ba.data().end();
|
||||||
|
it != ba.data().begin(); --it)
|
||||||
|
++n;
|
||||||
|
expect(n == 1);
|
||||||
|
}
|
||||||
|
|
||||||
void run() override
|
void run() override
|
||||||
{
|
{
|
||||||
testStaticStreambuf();
|
testStaticStreambuf();
|
||||||
|
testIterators();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@@ -154,14 +154,6 @@ public:
|
|||||||
{
|
{
|
||||||
pass();
|
pass();
|
||||||
}
|
}
|
||||||
s1 = "1";
|
|
||||||
s2 = "2";
|
|
||||||
expect(s1.compare(s2) < 0);
|
|
||||||
expect(s2.compare(s1) > 0);
|
|
||||||
expect(s1 < "10");
|
|
||||||
expect(s2 > "1");
|
|
||||||
expect("10" > s1);
|
|
||||||
expect("1" < s2);
|
|
||||||
}
|
}
|
||||||
pass();
|
pass();
|
||||||
}
|
}
|
||||||
@@ -170,6 +162,21 @@ public:
|
|||||||
{
|
{
|
||||||
using str1 = static_string<1>;
|
using str1 = static_string<1>;
|
||||||
using str2 = static_string<2>;
|
using str2 = static_string<2>;
|
||||||
|
{
|
||||||
|
str1 s1;
|
||||||
|
str2 s2;
|
||||||
|
s1 = "1";
|
||||||
|
s2 = "22";
|
||||||
|
expect(s1.compare(s2) < 0);
|
||||||
|
expect(s2.compare(s1) > 0);
|
||||||
|
expect(s1 < "10");
|
||||||
|
expect(s2 > "1");
|
||||||
|
expect("10" > s1);
|
||||||
|
expect("1" < s2);
|
||||||
|
expect(s1 < "20");
|
||||||
|
expect(s2 > "1");
|
||||||
|
expect(s2 > "2");
|
||||||
|
}
|
||||||
{
|
{
|
||||||
str2 s1("x");
|
str2 s1("x");
|
||||||
str2 s2("x");
|
str2 s2("x");
|
||||||
|
@@ -15,6 +15,8 @@ add_executable (websocket-tests
|
|||||||
stream.cpp
|
stream.cpp
|
||||||
teardown.cpp
|
teardown.cpp
|
||||||
utf8_checker.cpp
|
utf8_checker.cpp
|
||||||
|
detail/frame.cpp
|
||||||
|
detail/mask.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
if (NOT WIN32)
|
if (NOT WIN32)
|
||||||
|
227
test/websocket/detail/frame.cpp
Normal file
227
test/websocket/detail/frame.cpp
Normal file
@@ -0,0 +1,227 @@
|
|||||||
|
//
|
||||||
|
// 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)
|
||||||
|
//
|
||||||
|
|
||||||
|
#include <beast/websocket/detail/frame.hpp>
|
||||||
|
#include <beast/unit_test/suite.hpp>
|
||||||
|
#include <initializer_list>
|
||||||
|
#include <climits>
|
||||||
|
|
||||||
|
namespace beast {
|
||||||
|
namespace websocket {
|
||||||
|
namespace detail {
|
||||||
|
|
||||||
|
static
|
||||||
|
bool
|
||||||
|
operator==(frame_header const& lhs, frame_header const& rhs)
|
||||||
|
{
|
||||||
|
return
|
||||||
|
lhs.op == rhs.op &&
|
||||||
|
lhs.fin == rhs.fin &&
|
||||||
|
lhs.mask == rhs.mask &&
|
||||||
|
lhs.rsv1 == rhs.rsv1 &&
|
||||||
|
lhs.rsv2 == rhs.rsv2 &&
|
||||||
|
lhs.rsv3 == rhs.rsv3 &&
|
||||||
|
lhs.len == rhs.len &&
|
||||||
|
lhs.key == rhs.key;
|
||||||
|
}
|
||||||
|
|
||||||
|
class frame_test : public beast::unit_test::suite
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
void testValidOpcode()
|
||||||
|
{
|
||||||
|
expect(! is_valid(0));
|
||||||
|
expect(! is_valid(1));
|
||||||
|
expect(! is_valid(999));
|
||||||
|
expect(! is_valid(1004));
|
||||||
|
expect(! is_valid(1005));
|
||||||
|
expect(! is_valid(1006));
|
||||||
|
expect(! is_valid(1016));
|
||||||
|
expect(! is_valid(2000));
|
||||||
|
expect(! is_valid(2999));
|
||||||
|
expect(is_valid(3000));
|
||||||
|
expect(is_valid(4000));
|
||||||
|
expect(is_valid(5000));
|
||||||
|
}
|
||||||
|
|
||||||
|
struct test_fh : frame_header
|
||||||
|
{
|
||||||
|
test_fh()
|
||||||
|
{
|
||||||
|
op = opcode::text;
|
||||||
|
fin = false;
|
||||||
|
mask = false;
|
||||||
|
rsv1 = false;
|
||||||
|
rsv2 = false;
|
||||||
|
rsv3 = false;
|
||||||
|
len = 0;
|
||||||
|
key = 0;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
void testFrameHeader()
|
||||||
|
{
|
||||||
|
// good frame headers
|
||||||
|
{
|
||||||
|
role_type role = role_type::client;
|
||||||
|
|
||||||
|
auto check =
|
||||||
|
[&](frame_header const& fh)
|
||||||
|
{
|
||||||
|
fh_streambuf sb;
|
||||||
|
write(sb, fh);
|
||||||
|
frame_header fh1;
|
||||||
|
close_code::value code;
|
||||||
|
auto const n = read_fh1(
|
||||||
|
fh1, sb, role, code);
|
||||||
|
if(! expect(! code))
|
||||||
|
return;
|
||||||
|
if(! expect(sb.size() == n))
|
||||||
|
return;
|
||||||
|
read_fh2(fh1, sb, role, code);
|
||||||
|
if(! expect(! code))
|
||||||
|
return;
|
||||||
|
if(! expect(sb.size() == 0))
|
||||||
|
return;
|
||||||
|
expect(fh1 == fh);
|
||||||
|
};
|
||||||
|
|
||||||
|
test_fh fh;
|
||||||
|
|
||||||
|
check(fh);
|
||||||
|
|
||||||
|
role = role_type::server;
|
||||||
|
fh.mask = true;
|
||||||
|
fh.key = 1;
|
||||||
|
check(fh);
|
||||||
|
|
||||||
|
fh.len = 1;
|
||||||
|
check(fh);
|
||||||
|
|
||||||
|
fh.len = 126;
|
||||||
|
check(fh);
|
||||||
|
|
||||||
|
fh.len = 65535;
|
||||||
|
check(fh);
|
||||||
|
|
||||||
|
fh.len = 65536;
|
||||||
|
check(fh);
|
||||||
|
|
||||||
|
fh.len = std::numeric_limits<std::uint64_t>::max();
|
||||||
|
check(fh);
|
||||||
|
}
|
||||||
|
|
||||||
|
// bad frame headers
|
||||||
|
{
|
||||||
|
role_type role = role_type::client;
|
||||||
|
|
||||||
|
auto check =
|
||||||
|
[&](frame_header const& fh)
|
||||||
|
{
|
||||||
|
fh_streambuf sb;
|
||||||
|
write(sb, fh);
|
||||||
|
frame_header fh1;
|
||||||
|
close_code::value code;
|
||||||
|
auto const n = read_fh1(
|
||||||
|
fh1, sb, role, code);
|
||||||
|
if(code)
|
||||||
|
{
|
||||||
|
pass();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if(! expect(sb.size() == n))
|
||||||
|
return;
|
||||||
|
read_fh2(fh1, sb, role, code);
|
||||||
|
if(! expect(code))
|
||||||
|
return;
|
||||||
|
if(! expect(sb.size() == 0))
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
|
||||||
|
test_fh fh;
|
||||||
|
|
||||||
|
fh.op = opcode::close;
|
||||||
|
fh.fin = true;
|
||||||
|
fh.len = 126;
|
||||||
|
check(fh);
|
||||||
|
fh.len = 0;
|
||||||
|
|
||||||
|
fh.rsv1 = true;
|
||||||
|
check(fh);
|
||||||
|
fh.rsv1 = false;
|
||||||
|
|
||||||
|
fh.op = opcode::rsv3;
|
||||||
|
check(fh);
|
||||||
|
fh.op = opcode::text;
|
||||||
|
|
||||||
|
fh.op = opcode::ping;
|
||||||
|
fh.fin = false;
|
||||||
|
check(fh);
|
||||||
|
fh.fin = true;
|
||||||
|
|
||||||
|
fh.mask = true;
|
||||||
|
check(fh);
|
||||||
|
|
||||||
|
role = role_type::server;
|
||||||
|
fh.mask = false;
|
||||||
|
check(fh);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void bad(std::initializer_list<std::uint8_t> bs)
|
||||||
|
{
|
||||||
|
using boost::asio::buffer;
|
||||||
|
using boost::asio::buffer_copy;
|
||||||
|
static role_type constexpr role =
|
||||||
|
role_type::client;
|
||||||
|
std::vector<std::uint8_t> v{bs};
|
||||||
|
fh_streambuf sb;
|
||||||
|
sb.commit(buffer_copy(
|
||||||
|
sb.prepare(v.size()), buffer(v)));
|
||||||
|
frame_header fh;
|
||||||
|
close_code::value code;
|
||||||
|
auto const n = read_fh1(fh, sb, role, code);
|
||||||
|
if(code)
|
||||||
|
{
|
||||||
|
pass();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if(! expect(sb.size() == n))
|
||||||
|
return;
|
||||||
|
read_fh2(fh, sb, role, code);
|
||||||
|
if(! expect(code))
|
||||||
|
return;
|
||||||
|
if(! expect(sb.size() == 0))
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
void testBadFrameHeaders()
|
||||||
|
{
|
||||||
|
// bad frame headers
|
||||||
|
//
|
||||||
|
// can't be created by the library
|
||||||
|
// so we produce them manually.
|
||||||
|
|
||||||
|
bad({0, 126, 0, 125});
|
||||||
|
bad({0, 127, 0, 0, 0, 0, 0, 0, 255, 255});
|
||||||
|
}
|
||||||
|
|
||||||
|
void run() override
|
||||||
|
{
|
||||||
|
testValidOpcode();
|
||||||
|
testFrameHeader();
|
||||||
|
testBadFrameHeaders();
|
||||||
|
pass();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
BEAST_DEFINE_TESTSUITE(frame,websocket,beast);
|
||||||
|
|
||||||
|
} // detail
|
||||||
|
} // websocket
|
||||||
|
} // beast
|
||||||
|
|
48
test/websocket/detail/mask.cpp
Normal file
48
test/websocket/detail/mask.cpp
Normal file
@@ -0,0 +1,48 @@
|
|||||||
|
//
|
||||||
|
// 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)
|
||||||
|
//
|
||||||
|
|
||||||
|
#include <beast/websocket/detail/mask.hpp>
|
||||||
|
#include <beast/unit_test/suite.hpp>
|
||||||
|
|
||||||
|
namespace beast {
|
||||||
|
namespace websocket {
|
||||||
|
namespace detail {
|
||||||
|
|
||||||
|
class mask_test : public beast::unit_test::suite
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
struct test_generator
|
||||||
|
{
|
||||||
|
using result_type = std::uint32_t;
|
||||||
|
|
||||||
|
result_type n = 0;
|
||||||
|
|
||||||
|
void
|
||||||
|
seed(std::seed_seq const&)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
std::uint32_t
|
||||||
|
operator()()
|
||||||
|
{
|
||||||
|
return n++;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
void run() override
|
||||||
|
{
|
||||||
|
maskgen_t<test_generator> mg;
|
||||||
|
expect(mg() != 0);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
BEAST_DEFINE_TESTSUITE(mask,websocket,beast);
|
||||||
|
|
||||||
|
} // detail
|
||||||
|
} // websocket
|
||||||
|
} // beast
|
||||||
|
|
@@ -7,3 +7,45 @@
|
|||||||
|
|
||||||
// Test that header file is self-contained.
|
// Test that header file is self-contained.
|
||||||
#include <beast/websocket/error.hpp>
|
#include <beast/websocket/error.hpp>
|
||||||
|
|
||||||
|
#include <beast/unit_test/suite.hpp>
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
namespace beast {
|
||||||
|
namespace websocket {
|
||||||
|
|
||||||
|
class error_test : public unit_test::suite
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
void check(char const* name, error ev)
|
||||||
|
{
|
||||||
|
auto const ec = make_error_code(ev);
|
||||||
|
expect(std::string{ec.category().name()} == name);
|
||||||
|
expect(! ec.message().empty());
|
||||||
|
expect(std::addressof(ec.category()) ==
|
||||||
|
std::addressof(detail::get_error_category()));
|
||||||
|
expect(detail::get_error_category().equivalent(static_cast<int>(ev),
|
||||||
|
ec.category().default_error_condition(static_cast<int>(ev))));
|
||||||
|
expect(detail::get_error_category().equivalent(
|
||||||
|
ec, static_cast<int>(ev)));
|
||||||
|
}
|
||||||
|
|
||||||
|
void run() override
|
||||||
|
{
|
||||||
|
check("websocket", error::closed);
|
||||||
|
check("websocket", error::failed);
|
||||||
|
check("websocket", error::handshake_failed);
|
||||||
|
check("websocket", error::keep_alive);
|
||||||
|
check("websocket", error::response_malformed);
|
||||||
|
check("websocket", error::response_failed);
|
||||||
|
check("websocket", error::response_denied);
|
||||||
|
check("websocket", error::request_malformed);
|
||||||
|
check("websocket", error::request_invalid);
|
||||||
|
check("websocket", error::request_denied);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
BEAST_DEFINE_TESTSUITE(error,websocket,beast);
|
||||||
|
|
||||||
|
} // http
|
||||||
|
} // beast
|
||||||
|
Reference in New Issue
Block a user