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:
Vinnie Falco
2017-07-20 08:12:06 -07:00
parent 00d8ed71fd
commit a59329ff8e
17 changed files with 649 additions and 122 deletions
+2
View File
@@ -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 :
+107 -1
View File
@@ -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();
+47
View File
@@ -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
+20
View File
@@ -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
+38 -4
View File
@@ -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 = "*";
+56
View File
@@ -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();
}
};
+15 -8
View File
@@ -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");
+2
View File
@@ -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
View 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
View 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
+42
View File
@@ -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