mirror of
https://github.com/boostorg/beast.git
synced 2025-07-30 04:47:29 +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
|
||||
* Add concepts WritableBody ReadableBody with type checks,
|
||||
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"))
|
||||
throw std::invalid_argument(
|
||||
"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
|
||||
|
@ -39,22 +39,11 @@ write_firstline(Streambuf& streambuf,
|
||||
write(streambuf, msg.method);
|
||||
write(streambuf, " ");
|
||||
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, msg.version / 10);
|
||||
write(streambuf, ".");
|
||||
write(streambuf, msg.version % 10);
|
||||
write(streambuf, "\r\n");
|
||||
break;
|
||||
}
|
||||
write(streambuf, " HTTP/");
|
||||
write(streambuf, msg.version / 10);
|
||||
write(streambuf, ".");
|
||||
write(streambuf, msg.version % 10);
|
||||
write(streambuf, "\r\n");
|
||||
}
|
||||
|
||||
template<class Streambuf, class Body, class Headers>
|
||||
@ -62,22 +51,11 @@ void
|
||||
write_firstline(Streambuf& streambuf,
|
||||
message_v1<false, Body, Headers> const& msg)
|
||||
{
|
||||
switch(msg.version)
|
||||
{
|
||||
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, ".");
|
||||
write(streambuf, msg.version % 10);
|
||||
write(streambuf, " ");
|
||||
break;
|
||||
}
|
||||
write(streambuf, "HTTP/");
|
||||
write(streambuf, msg.version / 10);
|
||||
write(streambuf, ".");
|
||||
write(streambuf, msg.version % 10);
|
||||
write(streambuf, " ");
|
||||
write(streambuf, msg.status);
|
||||
write(streambuf, " ");
|
||||
write(streambuf, msg.reason);
|
||||
|
@ -1,21 +1,9 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of Beast: https://github.com/vinniefalco/Beast
|
||||
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
|
||||
|
||||
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.
|
||||
*/
|
||||
//==============================================================================
|
||||
//
|
||||
// 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_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::uint8_t b[14];
|
||||
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;
|
||||
if (fh.len <= 125)
|
||||
{
|
||||
@ -196,13 +202,6 @@ read_fh1(frame_header& fh, Streambuf& sb,
|
||||
code = close_code::protocol_error;
|
||||
return 0;
|
||||
}
|
||||
// invalid opcode
|
||||
// (only in locally generated headers)
|
||||
if(! is_valid(fh.op))
|
||||
{
|
||||
code = close_code::protocol_error;
|
||||
return 0;
|
||||
}
|
||||
// fragmented control message
|
||||
if(is_control(fh.op) && ! fh.fin)
|
||||
{
|
||||
@ -243,13 +242,7 @@ read_fh2(frame_header& fh, Streambuf& sb,
|
||||
std::uint8_t b[2];
|
||||
assert(buffer_size(sb.data()) >= sizeof(b));
|
||||
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]);
|
||||
#endif
|
||||
// length not canonical
|
||||
if(fh.len < 126)
|
||||
{
|
||||
@ -263,13 +256,7 @@ read_fh2(frame_header& fh, Streambuf& sb,
|
||||
std::uint8_t b[8];
|
||||
assert(buffer_size(sb.data()) >= sizeof(b));
|
||||
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]);
|
||||
#endif
|
||||
// length not canonical
|
||||
if(fh.len < 65536)
|
||||
{
|
||||
@ -284,13 +271,12 @@ read_fh2(frame_header& fh, Streambuf& sb,
|
||||
std::uint8_t b[4];
|
||||
assert(buffer_size(sb.data()) >= sizeof(b));
|
||||
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]);
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
// initialize this otherwise operator== breaks
|
||||
fh.key = 0;
|
||||
}
|
||||
code = close_code::none;
|
||||
}
|
||||
|
@ -1,24 +1,12 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of Beast: https://github.com/vinniefalco/Beast
|
||||
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
|
||||
//
|
||||
// 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)
|
||||
//
|
||||
|
||||
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_WEBSOCKETDETAIL_MASKGEN_HPP
|
||||
#define BEAST_WEBSOCKETDETAIL_MASKGEN_HPP
|
||||
#ifndef BEAST_WEBSOCKET_DETAIL_MASK_HPP
|
||||
#define BEAST_WEBSOCKET_DETAIL_MASK_HPP
|
||||
|
||||
#include <boost/asio/buffer.hpp>
|
||||
#include <array>
|
||||
@ -33,13 +21,14 @@ namespace detail {
|
||||
|
||||
// Pseudo-random source of mask keys
|
||||
//
|
||||
template<class = void>
|
||||
template<class Generator>
|
||||
class maskgen_t
|
||||
{
|
||||
std::mt19937 g_;
|
||||
Generator g_;
|
||||
|
||||
public:
|
||||
using result_type = typename std::mt19937::result_type;
|
||||
using result_type =
|
||||
typename Generator::result_type;
|
||||
|
||||
maskgen_t();
|
||||
|
||||
@ -50,15 +39,15 @@ public:
|
||||
rekey();
|
||||
};
|
||||
|
||||
template<class _>
|
||||
maskgen_t<_>::maskgen_t()
|
||||
template<class Generator>
|
||||
maskgen_t<Generator>::maskgen_t()
|
||||
{
|
||||
rekey();
|
||||
}
|
||||
|
||||
template<class _>
|
||||
template<class Generator>
|
||||
auto
|
||||
maskgen_t<_>::operator()() noexcept ->
|
||||
maskgen_t<Generator>::operator()() noexcept ->
|
||||
result_type
|
||||
{
|
||||
for(;;)
|
||||
@ -78,7 +67,7 @@ maskgen_t<_>::rekey()
|
||||
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/teardown.cpp
|
||||
websocket/utf8_checker.cpp
|
||||
websocket/detail/frame.cpp
|
||||
websocket/detail/mask.cpp
|
||||
;
|
||||
|
||||
exe websocket-echo :
|
||||
|
@ -10,7 +10,6 @@
|
||||
|
||||
#include "message_fuzz.hpp"
|
||||
|
||||
#include <beast/error.hpp>
|
||||
#include <beast/streambuf.hpp>
|
||||
#include <beast/write_streambuf.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
|
||||
@ -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
|
||||
testCallbacks()
|
||||
{
|
||||
@ -647,6 +752,7 @@ public:
|
||||
|
||||
void run() override
|
||||
{
|
||||
testFail();
|
||||
testCallbacks();
|
||||
testVersion();
|
||||
testFlags();
|
||||
|
@ -7,3 +7,50 @@
|
||||
|
||||
// Test that header file is self-contained.
|
||||
#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.
|
||||
#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;
|
||||
|
||||
@ -67,7 +67,41 @@ public:
|
||||
public:
|
||||
template<bool isRequest, class Allocator>
|
||||
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)
|
||||
{
|
||||
}
|
||||
@ -148,7 +182,7 @@ public:
|
||||
}
|
||||
// no content-length HTTP/1.0
|
||||
{
|
||||
message_v1<true, test_Body, headers> m{{
|
||||
message_v1<true, test_body, headers> m{{
|
||||
"GET", "/", 10}};
|
||||
m.headers.insert("User-Agent", "test");
|
||||
m.body = "*";
|
||||
@ -214,7 +248,7 @@ public:
|
||||
}
|
||||
// no content-length HTTP/1.1
|
||||
{
|
||||
message_v1<true, test_Body, headers> m{{
|
||||
message_v1<true, test_body, headers> m{{
|
||||
"GET", "/", 11}};
|
||||
m.headers.insert("User-Agent", "test");
|
||||
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
|
||||
{
|
||||
testStaticStreambuf();
|
||||
testIterators();
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -154,14 +154,6 @@ public:
|
||||
{
|
||||
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();
|
||||
}
|
||||
@ -170,6 +162,21 @@ public:
|
||||
{
|
||||
using str1 = static_string<1>;
|
||||
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 s2("x");
|
||||
|
@ -15,6 +15,8 @@ add_executable (websocket-tests
|
||||
stream.cpp
|
||||
teardown.cpp
|
||||
utf8_checker.cpp
|
||||
detail/frame.cpp
|
||||
detail/mask.cpp
|
||||
)
|
||||
|
||||
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.
|
||||
#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