forked from boostorg/beast
websocket read tests
This commit is contained in:
1 parent
142b785119
commit
df7b068fa7
9 files changed
+552
-357
No files matched your search
@@ -27,12 +27,18 @@ public:
|
||||
pmd.client_enable = false;
|
||||
pmd.server_enable = false;
|
||||
|
||||
// normal close
|
||||
// close
|
||||
doTest(pmd, [&](ws_type& ws)
|
||||
{
|
||||
w.close(ws, {});
|
||||
});
|
||||
|
||||
// close with code
|
||||
doTest(pmd, [&](ws_type& ws)
|
||||
{
|
||||
w.close(ws, close_code::going_away);
|
||||
});
|
||||
|
||||
// double close
|
||||
{
|
||||
echo_server es{log};
|
||||
|
||||
@@ -37,10 +37,10 @@ public:
|
||||
|
||||
void run() override
|
||||
{
|
||||
check("beast.websocket", error::closed);
|
||||
check("beast.websocket", error::failed);
|
||||
check("beast.websocket", error::handshake_failed);
|
||||
check("beast.websocket", error::buffer_overflow);
|
||||
check("boost.beast.websocket", error::closed);
|
||||
check("boost.beast.websocket", error::failed);
|
||||
check("boost.beast.websocket", error::handshake_failed);
|
||||
check("boost.beast.websocket", error::buffer_overflow);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -19,18 +19,287 @@ namespace websocket {
|
||||
class stream_read_test : public websocket_test_suite
|
||||
{
|
||||
public:
|
||||
template<class Wrap>
|
||||
void
|
||||
doReadTest(
|
||||
Wrap const& w,
|
||||
ws_type& ws,
|
||||
close_code code)
|
||||
{
|
||||
try
|
||||
{
|
||||
multi_buffer b;
|
||||
w.read(ws, b);
|
||||
fail("", __FILE__, __LINE__);
|
||||
}
|
||||
catch(system_error const& se)
|
||||
{
|
||||
if(se.code() != error::closed)
|
||||
throw;
|
||||
BEAST_EXPECT(
|
||||
ws.reason().code == code);
|
||||
}
|
||||
}
|
||||
|
||||
template<class Wrap>
|
||||
void
|
||||
doFailTest(
|
||||
Wrap const& w,
|
||||
ws_type& ws,
|
||||
error_code ev)
|
||||
{
|
||||
try
|
||||
{
|
||||
multi_buffer b;
|
||||
w.read(ws, b);
|
||||
fail("", __FILE__, __LINE__);
|
||||
}
|
||||
catch(system_error const& se)
|
||||
{
|
||||
if(se.code() != ev)
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
template<class Wrap>
|
||||
void
|
||||
doTestRead(Wrap const& w)
|
||||
{
|
||||
using boost::asio::buffer;
|
||||
|
||||
permessage_deflate pmd;
|
||||
pmd.client_enable = false;
|
||||
pmd.server_enable = false;
|
||||
|
||||
// Read close frames
|
||||
// empty, fragmented message
|
||||
doTest(pmd, [&](ws_type& ws)
|
||||
{
|
||||
// VFALCO What about asynchronous??
|
||||
ws.next_layer().append(
|
||||
string_view(
|
||||
"\x01\x00" "\x80\x00", 4));
|
||||
multi_buffer b;
|
||||
w.read(ws, b);
|
||||
BEAST_EXPECT(b.size() == 0);
|
||||
});
|
||||
|
||||
// two part message
|
||||
// this triggers "fill the read buffer first"
|
||||
doTest(pmd, [&](ws_type& ws)
|
||||
{
|
||||
w.write_raw(ws, sbuf(
|
||||
"\x01\x81\xff\xff\xff\xff"));
|
||||
w.write_raw(ws, sbuf(
|
||||
"\xd5"));
|
||||
w.write_raw(ws, sbuf(
|
||||
"\x80\x81\xff\xff\xff\xff\xd5"));
|
||||
multi_buffer b;
|
||||
w.read(ws, b);
|
||||
BEAST_EXPECT(to_string(b.data()) == "**");
|
||||
});
|
||||
|
||||
// ping
|
||||
doTest(pmd, [&](ws_type& ws)
|
||||
{
|
||||
put(ws.next_layer().buffer(), cbuf(
|
||||
0x89, 0x00));
|
||||
bool invoked = false;
|
||||
auto cb = [&](frame_type kind, string_view)
|
||||
{
|
||||
BEAST_EXPECT(! invoked);
|
||||
BEAST_EXPECT(kind == frame_type::ping);
|
||||
invoked = true;
|
||||
};
|
||||
ws.control_callback(cb);
|
||||
w.write(ws, sbuf("Hello"));
|
||||
multi_buffer b;
|
||||
w.read(ws, b);
|
||||
BEAST_EXPECT(invoked);
|
||||
BEAST_EXPECT(ws.got_text());
|
||||
BEAST_EXPECT(to_string(b.data()) == "Hello");
|
||||
});
|
||||
|
||||
// ping
|
||||
doTest(pmd, [&](ws_type& ws)
|
||||
{
|
||||
put(ws.next_layer().buffer(), cbuf(
|
||||
0x88, 0x00));
|
||||
bool invoked = false;
|
||||
auto cb = [&](frame_type kind, string_view)
|
||||
{
|
||||
BEAST_EXPECT(! invoked);
|
||||
BEAST_EXPECT(kind == frame_type::close);
|
||||
invoked = true;
|
||||
};
|
||||
ws.control_callback(cb);
|
||||
w.write(ws, sbuf("Hello"));
|
||||
doReadTest(w, ws, close_code::none);
|
||||
});
|
||||
|
||||
// ping then message
|
||||
doTest(pmd, [&](ws_type& ws)
|
||||
{
|
||||
bool once = false;
|
||||
auto cb =
|
||||
[&](frame_type kind, string_view s)
|
||||
{
|
||||
BEAST_EXPECT(kind == frame_type::pong);
|
||||
BEAST_EXPECT(! once);
|
||||
once = true;
|
||||
BEAST_EXPECT(s == "");
|
||||
};
|
||||
ws.control_callback(cb);
|
||||
w.ping(ws, "");
|
||||
ws.binary(true);
|
||||
w.write(ws, sbuf("Hello"));
|
||||
multi_buffer b;
|
||||
w.read(ws, b);
|
||||
BEAST_EXPECT(once);
|
||||
BEAST_EXPECT(ws.got_binary());
|
||||
BEAST_EXPECT(to_string(b.data()) == "Hello");
|
||||
});
|
||||
|
||||
// ping then fragmented message
|
||||
doTest(pmd, [&](ws_type& ws)
|
||||
{
|
||||
bool once = false;
|
||||
auto cb =
|
||||
[&](frame_type kind, string_view s)
|
||||
{
|
||||
BEAST_EXPECT(kind == frame_type::pong);
|
||||
BEAST_EXPECT(! once);
|
||||
once = true;
|
||||
BEAST_EXPECT(s == "payload");
|
||||
};
|
||||
ws.control_callback(cb);
|
||||
ws.ping("payload");
|
||||
w.write_some(ws, false, sbuf("Hello, "));
|
||||
w.write_some(ws, false, sbuf(""));
|
||||
w.write_some(ws, true, sbuf("World!"));
|
||||
multi_buffer b;
|
||||
w.read(ws, b);
|
||||
BEAST_EXPECT(once);
|
||||
BEAST_EXPECT(to_string(b.data()) == "Hello, World!");
|
||||
});
|
||||
|
||||
// already closed
|
||||
doTest(pmd, [&](ws_type& ws)
|
||||
{
|
||||
w.close(ws, {});
|
||||
multi_buffer b;
|
||||
doFailTest(w, ws,
|
||||
boost::asio::error::operation_aborted);
|
||||
});
|
||||
|
||||
// buffer overflow
|
||||
doTest(pmd, [&](ws_type& ws)
|
||||
{
|
||||
std::string const s = "Hello, world!";
|
||||
ws.auto_fragment(false);
|
||||
ws.binary(false);
|
||||
w.write(ws, buffer(s));
|
||||
try
|
||||
{
|
||||
multi_buffer b(3);
|
||||
w.read(ws, b);
|
||||
fail("", __FILE__, __LINE__);
|
||||
}
|
||||
catch(system_error const& se)
|
||||
{
|
||||
if(se.code() != error::buffer_overflow)
|
||||
throw;
|
||||
}
|
||||
});
|
||||
|
||||
// bad utf8, big
|
||||
doTest(pmd, [&](ws_type& ws)
|
||||
{
|
||||
auto const s = std::string(2000, '*') +
|
||||
random_string();
|
||||
ws.text(true);
|
||||
w.write(ws, buffer(s));
|
||||
doReadTest(w, ws, close_code::bad_payload);
|
||||
});
|
||||
|
||||
// invalid fixed frame header
|
||||
doTest(pmd, [&](ws_type& ws)
|
||||
{
|
||||
w.write_raw(ws, cbuf(
|
||||
0x8f, 0x80, 0xff, 0xff, 0xff, 0xff));
|
||||
doReadTest(w, ws, close_code::protocol_error);
|
||||
});
|
||||
|
||||
// receive bad close
|
||||
doTest(pmd, [&](ws_type& ws)
|
||||
{
|
||||
put(ws.next_layer().buffer(), cbuf(
|
||||
0x88, 0x02, 0x03, 0xed));
|
||||
doFailTest(w, ws, error::failed);
|
||||
});
|
||||
|
||||
// expected cont
|
||||
doTest(pmd, [&](ws_type& ws)
|
||||
{
|
||||
w.write_some(ws, false, boost::asio::null_buffers{});
|
||||
w.write_raw(ws, cbuf(
|
||||
0x81, 0x80, 0xff, 0xff, 0xff, 0xff));
|
||||
doReadTest(w, ws, close_code::protocol_error);
|
||||
});
|
||||
|
||||
// message size above 2^64
|
||||
doTest(pmd, [&](ws_type& ws)
|
||||
{
|
||||
w.write_some(ws, false, sbuf("*"));
|
||||
w.write_raw(ws, cbuf(
|
||||
0x80, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff));
|
||||
doReadTest(w, ws, close_code::too_big);
|
||||
});
|
||||
|
||||
// message size exceeds max
|
||||
doTest(pmd, [&](ws_type& ws)
|
||||
{
|
||||
ws.read_message_max(1);
|
||||
w.write(ws, sbuf("**"));
|
||||
doFailTest(w, ws, error::failed);
|
||||
});
|
||||
|
||||
// unexpected cont
|
||||
doTest(pmd, [&](ws_type& ws)
|
||||
{
|
||||
w.write_raw(ws, cbuf(
|
||||
0x80, 0x80, 0xff, 0xff, 0xff, 0xff));
|
||||
doReadTest(w, ws, close_code::protocol_error);
|
||||
});
|
||||
|
||||
// bad utf8
|
||||
doTest(pmd, [&](ws_type& ws)
|
||||
{
|
||||
put(ws.next_layer().buffer(), cbuf(
|
||||
0x81, 0x06, 0x03, 0xea, 0xf0, 0x28, 0x8c, 0xbc));
|
||||
doFailTest(w, ws, error::failed);
|
||||
});
|
||||
|
||||
// incomplete utf8
|
||||
doTest(pmd, [&](ws_type& ws)
|
||||
{
|
||||
std::string const s =
|
||||
"Hello, world!" "\xc0";
|
||||
w.write(ws, buffer(s));
|
||||
doReadTest(w, ws, close_code::bad_payload);
|
||||
});
|
||||
|
||||
// incomplete utf8, big
|
||||
doTest(pmd, [&](ws_type& ws)
|
||||
{
|
||||
std::string const s =
|
||||
random_string() +
|
||||
"Hello, world!" "\xc0";
|
||||
w.write(ws, buffer(s));
|
||||
doReadTest(w, ws, close_code::bad_payload);
|
||||
});
|
||||
|
||||
// close frames
|
||||
{
|
||||
auto const check =
|
||||
[&](error_code ev, string_view s)
|
||||
{
|
||||
@@ -71,8 +340,24 @@ public:
|
||||
"\x88\x06\xfc\x15utf8");
|
||||
}
|
||||
|
||||
//
|
||||
// permessage-deflate
|
||||
//
|
||||
|
||||
pmd.client_enable = true;
|
||||
pmd.server_enable = true;
|
||||
pmd.client_max_window_bits = 9;
|
||||
pmd.server_max_window_bits = 9;
|
||||
pmd.compLevel = 1;
|
||||
|
||||
// message size limit
|
||||
doTest(pmd, [&](ws_type& ws)
|
||||
{
|
||||
std::string const s = std::string(128, '*');
|
||||
w.write(ws, buffer(s));
|
||||
ws.read_message_max(32);
|
||||
doFailTest(w, ws, error::failed);
|
||||
});
|
||||
|
||||
// invalid inflate block
|
||||
doTest(pmd, [&](ws_type& ws)
|
||||
@@ -99,18 +384,136 @@ public:
|
||||
throw;
|
||||
}
|
||||
});
|
||||
|
||||
// no_context_takeover
|
||||
pmd.server_no_context_takeover = true;
|
||||
doTest(pmd, [&](ws_type& ws)
|
||||
{
|
||||
auto const& s = random_string();
|
||||
ws.binary(true);
|
||||
w.write(ws, buffer(s));
|
||||
multi_buffer b;
|
||||
w.read(ws, b);
|
||||
BEAST_EXPECT(to_string(b.data()) == s);
|
||||
});
|
||||
pmd.client_no_context_takeover = false;
|
||||
}
|
||||
|
||||
template<class Wrap>
|
||||
void
|
||||
doTestRead(
|
||||
permessage_deflate const& pmd,
|
||||
Wrap const& w)
|
||||
{
|
||||
using boost::asio::buffer;
|
||||
|
||||
// message
|
||||
doTest(pmd, [&](ws_type& ws)
|
||||
{
|
||||
std::string const s = "Hello, world!";
|
||||
ws.auto_fragment(false);
|
||||
ws.binary(false);
|
||||
w.write(ws, buffer(s));
|
||||
multi_buffer b;
|
||||
w.read(ws, b);
|
||||
BEAST_EXPECT(ws.got_text());
|
||||
BEAST_EXPECT(to_string(b.data()) == s);
|
||||
});
|
||||
|
||||
// empty message
|
||||
doTest(pmd, [&](ws_type& ws)
|
||||
{
|
||||
std::string const s = "";
|
||||
ws.text(true);
|
||||
w.write(ws, buffer(s));
|
||||
multi_buffer b;
|
||||
w.read(ws, b);
|
||||
BEAST_EXPECT(ws.got_text());
|
||||
BEAST_EXPECT(to_string(b.data()) == s);
|
||||
});
|
||||
|
||||
// partial message
|
||||
doTest(pmd, [&](ws_type& ws)
|
||||
{
|
||||
std::string const s = "Hello";
|
||||
w.write(ws, buffer(s));
|
||||
char buf[3];
|
||||
auto const bytes_written =
|
||||
w.read_some(ws, buffer(buf, sizeof(buf)));
|
||||
BEAST_EXPECT(bytes_written > 0);
|
||||
BEAST_EXPECT(
|
||||
string_view(buf, 3).substr(0, bytes_written) ==
|
||||
s.substr(0, bytes_written));
|
||||
});
|
||||
|
||||
// partial message, dynamic buffer
|
||||
doTest(pmd, [&](ws_type& ws)
|
||||
{
|
||||
std::string const s = "Hello, world!";
|
||||
w.write(ws, buffer(s));
|
||||
multi_buffer b;
|
||||
auto bytes_written =
|
||||
w.read_some(ws, 3, b);
|
||||
BEAST_EXPECT(bytes_written > 0);
|
||||
BEAST_EXPECT(to_string(b.data()) ==
|
||||
s.substr(0, b.size()));
|
||||
w.read_some(ws, 256, b);
|
||||
BEAST_EXPECT(to_string(b.data()) == s);
|
||||
});
|
||||
|
||||
// big message
|
||||
doTest(pmd, [&](ws_type& ws)
|
||||
{
|
||||
auto const& s = random_string();
|
||||
ws.binary(true);
|
||||
w.write(ws, buffer(s));
|
||||
multi_buffer b;
|
||||
w.read(ws, b);
|
||||
BEAST_EXPECT(to_string(b.data()) == s);
|
||||
});
|
||||
|
||||
// message, bad utf8
|
||||
doTest(pmd, [&](ws_type& ws)
|
||||
{
|
||||
std::string const s = "\x03\xea\xf0\x28\x8c\xbc";
|
||||
ws.auto_fragment(false);
|
||||
ws.text(true);
|
||||
w.write(ws, buffer(s));
|
||||
doReadTest(w, ws, close_code::bad_payload);
|
||||
});
|
||||
}
|
||||
|
||||
void
|
||||
testRead()
|
||||
{
|
||||
doTestRead(SyncClient{});
|
||||
using boost::asio::buffer;
|
||||
|
||||
doTestRead(SyncClient{});
|
||||
yield_to([&](yield_context yield)
|
||||
{
|
||||
doTestRead(AsyncClient{yield});
|
||||
});
|
||||
|
||||
permessage_deflate pmd;
|
||||
pmd.client_enable = false;
|
||||
pmd.server_enable = false;
|
||||
doTestRead(pmd, SyncClient{});
|
||||
yield_to([&](yield_context yield)
|
||||
{
|
||||
doTestRead(pmd, AsyncClient{yield});
|
||||
});
|
||||
|
||||
pmd.client_enable = true;
|
||||
pmd.server_enable = true;
|
||||
pmd.client_max_window_bits = 9;
|
||||
pmd.server_max_window_bits = 9;
|
||||
pmd.compLevel = 1;
|
||||
doTestRead(pmd, SyncClient{});
|
||||
yield_to([&](yield_context yield)
|
||||
{
|
||||
doTestRead(pmd, AsyncClient{yield});
|
||||
});
|
||||
|
||||
// Read close frames
|
||||
{
|
||||
auto const check =
|
||||
@@ -144,6 +547,39 @@ public:
|
||||
check(error::closed,
|
||||
"\x88\x06\xfc\x15utf8");
|
||||
}
|
||||
|
||||
// suspend on write
|
||||
{
|
||||
echo_server es{log};
|
||||
error_code ec;
|
||||
boost::asio::io_service ios;
|
||||
stream<test::stream> ws{ios};
|
||||
ws.next_layer().connect(es.stream());
|
||||
ws.handshake("localhost", "/", ec);
|
||||
BEAST_EXPECTS(! ec, ec.message());
|
||||
// insert a ping
|
||||
ws.next_layer().append(string_view(
|
||||
"\x89\x00", 2));
|
||||
std::size_t count = 0;
|
||||
multi_buffer b;
|
||||
std::string const s = "Hello, world";
|
||||
ws.async_read(b,
|
||||
[&](error_code ec, std::size_t)
|
||||
{
|
||||
++count;
|
||||
BEAST_EXPECTS(! ec, ec.message());
|
||||
BEAST_EXPECT(to_string(b.data()) == s);
|
||||
});
|
||||
ws.async_write(buffer(s),
|
||||
[&](error_code ec)
|
||||
{
|
||||
++count;
|
||||
BEAST_EXPECTS(! ec, ec.message());
|
||||
});
|
||||
BEAST_EXPECT(ws.wr_block_);
|
||||
ios.run();
|
||||
BEAST_EXPECT(count == 2);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
|
||||
@@ -47,102 +47,6 @@ public:
|
||||
{
|
||||
using boost::asio::buffer;
|
||||
|
||||
// send empty message
|
||||
doTest(pmd, [&](ws_type& ws)
|
||||
{
|
||||
ws.text(true);
|
||||
w.write(ws, boost::asio::null_buffers{});
|
||||
multi_buffer b;
|
||||
w.read(ws, b);
|
||||
BEAST_EXPECT(ws.got_text());
|
||||
BEAST_EXPECT(b.size() == 0);
|
||||
});
|
||||
|
||||
// send message
|
||||
doTest(pmd, [&](ws_type& ws)
|
||||
{
|
||||
ws.auto_fragment(false);
|
||||
ws.binary(false);
|
||||
w.write(ws, sbuf("Hello"));
|
||||
multi_buffer b;
|
||||
w.read(ws, b);
|
||||
BEAST_EXPECT(ws.got_text());
|
||||
BEAST_EXPECT(to_string(b.data()) == "Hello");
|
||||
});
|
||||
|
||||
// read_some
|
||||
doTest(pmd, [&](ws_type& ws)
|
||||
{
|
||||
w.write(ws, sbuf("Hello"));
|
||||
char buf[10];
|
||||
auto const bytes_written =
|
||||
w.read_some(ws, buffer(buf, sizeof(buf)));
|
||||
BEAST_EXPECT(bytes_written > 0);
|
||||
buf[bytes_written] = 0;
|
||||
BEAST_EXPECT(
|
||||
string_view(buf).substr(0, bytes_written) ==
|
||||
string_view("Hello").substr(0, bytes_written));
|
||||
});
|
||||
|
||||
// close, no payload
|
||||
doTest(pmd, [&](ws_type& ws)
|
||||
{
|
||||
w.close(ws, {});
|
||||
});
|
||||
|
||||
// close with code
|
||||
doTest(pmd, [&](ws_type& ws)
|
||||
{
|
||||
w.close(ws, close_code::going_away);
|
||||
});
|
||||
|
||||
// send ping and message
|
||||
doTest(pmd, [&](ws_type& ws)
|
||||
{
|
||||
bool once = false;
|
||||
auto cb =
|
||||
[&](frame_type kind, string_view s)
|
||||
{
|
||||
BEAST_EXPECT(kind == frame_type::pong);
|
||||
BEAST_EXPECT(! once);
|
||||
once = true;
|
||||
BEAST_EXPECT(s == "");
|
||||
};
|
||||
ws.control_callback(cb);
|
||||
w.ping(ws, "");
|
||||
ws.binary(true);
|
||||
w.write(ws, sbuf("Hello"));
|
||||
multi_buffer b;
|
||||
w.read(ws, b);
|
||||
BEAST_EXPECT(once);
|
||||
BEAST_EXPECT(ws.got_binary());
|
||||
BEAST_EXPECT(to_string(b.data()) == "Hello");
|
||||
});
|
||||
|
||||
// send ping and fragmented message
|
||||
doTest(pmd, [&](ws_type& ws)
|
||||
{
|
||||
bool once = false;
|
||||
auto cb =
|
||||
[&](frame_type kind, string_view s)
|
||||
{
|
||||
BEAST_EXPECT(kind == frame_type::pong);
|
||||
BEAST_EXPECT(! once);
|
||||
once = true;
|
||||
BEAST_EXPECT(s == "payload");
|
||||
};
|
||||
ws.control_callback(cb);
|
||||
ws.ping("payload");
|
||||
w.write_some(ws, false, sbuf("Hello, "));
|
||||
w.write_some(ws, false, sbuf(""));
|
||||
w.write_some(ws, true, sbuf("World!"));
|
||||
multi_buffer b;
|
||||
w.read(ws, b);
|
||||
BEAST_EXPECT(once);
|
||||
BEAST_EXPECT(to_string(b.data()) == "Hello, World!");
|
||||
ws.control_callback();
|
||||
});
|
||||
|
||||
// send pong
|
||||
doTest(pmd, [&](ws_type& ws)
|
||||
{
|
||||
@@ -170,109 +74,6 @@ public:
|
||||
w.read(ws, b);
|
||||
BEAST_EXPECT(to_string(b.data()) == s);
|
||||
});
|
||||
|
||||
// unexpected cont
|
||||
doTest(pmd, [&](ws_type& ws)
|
||||
{
|
||||
w.write_raw(ws, cbuf(
|
||||
0x80, 0x80, 0xff, 0xff, 0xff, 0xff));
|
||||
doCloseTest(w, ws, close_code::protocol_error);
|
||||
});
|
||||
|
||||
// invalid fixed frame header
|
||||
doTest(pmd, [&](ws_type& ws)
|
||||
{
|
||||
w.write_raw(ws, cbuf(
|
||||
0x8f, 0x80, 0xff, 0xff, 0xff, 0xff));
|
||||
doCloseTest(w, ws, close_code::protocol_error);
|
||||
});
|
||||
|
||||
if(! pmd.client_enable)
|
||||
{
|
||||
// expected cont
|
||||
doTest(pmd, [&](ws_type& ws)
|
||||
{
|
||||
w.write_some(ws, false, boost::asio::null_buffers{});
|
||||
w.write_raw(ws, cbuf(
|
||||
0x81, 0x80, 0xff, 0xff, 0xff, 0xff));
|
||||
doCloseTest(w, ws, close_code::protocol_error);
|
||||
});
|
||||
|
||||
// message size above 2^64
|
||||
doTest(pmd, [&](ws_type& ws)
|
||||
{
|
||||
w.write_some(ws, false, cbuf(0x00));
|
||||
w.write_raw(ws, cbuf(
|
||||
0x80, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff));
|
||||
doCloseTest(w, ws, close_code::too_big);
|
||||
});
|
||||
|
||||
/*
|
||||
// message size exceeds max
|
||||
doTest(pmd, [&](ws_type& ws)
|
||||
{
|
||||
// VFALCO This was never implemented correctly
|
||||
ws.read_message_max(1);
|
||||
w.write(ws, cbuf(0x81, 0x02, '*', '*'));
|
||||
doCloseTest(w, ws, close_code::too_big);
|
||||
});
|
||||
*/
|
||||
}
|
||||
|
||||
// receive ping
|
||||
doTest(pmd, [&](ws_type& ws)
|
||||
{
|
||||
put(ws.next_layer().buffer(), cbuf(
|
||||
0x89, 0x00));
|
||||
bool invoked = false;
|
||||
auto cb = [&](frame_type kind, string_view)
|
||||
{
|
||||
BEAST_EXPECT(! invoked);
|
||||
BEAST_EXPECT(kind == frame_type::ping);
|
||||
invoked = true;
|
||||
};
|
||||
ws.control_callback(cb);
|
||||
w.write(ws, sbuf("Hello"));
|
||||
multi_buffer b;
|
||||
w.read(ws, b);
|
||||
BEAST_EXPECT(invoked);
|
||||
BEAST_EXPECT(ws.got_text());
|
||||
BEAST_EXPECT(to_string(b.data()) == "Hello");
|
||||
});
|
||||
|
||||
// receive ping
|
||||
doTest(pmd, [&](ws_type& ws)
|
||||
{
|
||||
put(ws.next_layer().buffer(), cbuf(
|
||||
0x88, 0x00));
|
||||
bool invoked = false;
|
||||
auto cb = [&](frame_type kind, string_view)
|
||||
{
|
||||
BEAST_EXPECT(! invoked);
|
||||
BEAST_EXPECT(kind == frame_type::close);
|
||||
invoked = true;
|
||||
};
|
||||
ws.control_callback(cb);
|
||||
w.write(ws, sbuf("Hello"));
|
||||
doCloseTest(w, ws, close_code::none);
|
||||
});
|
||||
|
||||
// receive bad utf8
|
||||
doTest(pmd, [&](ws_type& ws)
|
||||
{
|
||||
put(ws.next_layer().buffer(), cbuf(
|
||||
0x81, 0x06, 0x03, 0xea, 0xf0, 0x28, 0x8c, 0xbc));
|
||||
doFailTest(w, ws, error::failed);
|
||||
});
|
||||
|
||||
// receive bad close
|
||||
doTest(pmd, [&](ws_type& ws)
|
||||
{
|
||||
put(ws.next_layer().buffer(), cbuf(
|
||||
0x88, 0x02, 0x03, 0xed));
|
||||
doFailTest(w, ws, error::failed);
|
||||
});
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
@@ -303,6 +104,7 @@ public:
|
||||
|
||||
testOptions();
|
||||
|
||||
#if 0
|
||||
auto const testStream =
|
||||
[this](permessage_deflate const& pmd)
|
||||
{
|
||||
@@ -336,6 +138,7 @@ public:
|
||||
pmd.compLevel = 1;
|
||||
pmd.memLevel = 1;
|
||||
testStream(pmd);
|
||||
#endif
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -70,8 +70,9 @@ public:
|
||||
, ws_(ts_)
|
||||
{
|
||||
permessage_deflate pmd;
|
||||
pmd.client_enable = true;
|
||||
pmd.server_enable = true;
|
||||
pmd.server_max_window_bits = 9;
|
||||
pmd.compLevel = 1;
|
||||
ws_.set_option(pmd);
|
||||
|
||||
switch(k)
|
||||
@@ -238,48 +239,6 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
template<class Wrap>
|
||||
void
|
||||
doCloseTest(
|
||||
Wrap const& w,
|
||||
ws_type& ws,
|
||||
close_code code)
|
||||
{
|
||||
try
|
||||
{
|
||||
multi_buffer b;
|
||||
w.read(ws, b);
|
||||
fail("", __FILE__, __LINE__);
|
||||
}
|
||||
catch(system_error const& se)
|
||||
{
|
||||
if(se.code() != error::closed)
|
||||
throw;
|
||||
BEAST_EXPECT(
|
||||
ws.reason().code == code);
|
||||
}
|
||||
}
|
||||
|
||||
template<class Wrap>
|
||||
void
|
||||
doFailTest(
|
||||
Wrap const& w,
|
||||
ws_type& ws,
|
||||
error_code ev)
|
||||
{
|
||||
try
|
||||
{
|
||||
multi_buffer b;
|
||||
w.read(ws, b);
|
||||
fail("", __FILE__, __LINE__);
|
||||
}
|
||||
catch(system_error const& se)
|
||||
{
|
||||
if(se.code() != ev)
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
template<class Test>
|
||||
void
|
||||
doTestLoop(Test const& f)
|
||||
|
||||
@@ -23,10 +23,36 @@ public:
|
||||
void
|
||||
doTestWrite(Wrap const& w)
|
||||
{
|
||||
using boost::asio::buffer;
|
||||
|
||||
permessage_deflate pmd;
|
||||
pmd.client_enable = false;
|
||||
pmd.server_enable = false;
|
||||
|
||||
// message
|
||||
doTest(pmd, [&](ws_type& ws)
|
||||
{
|
||||
ws.auto_fragment(false);
|
||||
ws.binary(false);
|
||||
std::string const s = "Hello, world!";
|
||||
w.write(ws, buffer(s));
|
||||
multi_buffer b;
|
||||
w.read(ws, b);
|
||||
BEAST_EXPECT(ws.got_text());
|
||||
BEAST_EXPECT(to_string(b.data()) == s);
|
||||
});
|
||||
|
||||
// empty message
|
||||
doTest(pmd, [&](ws_type& ws)
|
||||
{
|
||||
ws.text(true);
|
||||
w.write(ws, boost::asio::null_buffers{});
|
||||
multi_buffer b;
|
||||
w.read(ws, b);
|
||||
BEAST_EXPECT(ws.got_text());
|
||||
BEAST_EXPECT(b.size() == 0);
|
||||
});
|
||||
|
||||
// continuation
|
||||
doTest(pmd, [&](ws_type& ws)
|
||||
{
|
||||
@@ -34,8 +60,8 @@ public:
|
||||
std::size_t const chop = 3;
|
||||
BOOST_ASSERT(chop < s.size());
|
||||
w.write_some(ws, false,
|
||||
boost::asio::buffer(s.data(), chop));
|
||||
w.write_some(ws, true, boost::asio::buffer(
|
||||
buffer(s.data(), chop));
|
||||
w.write_some(ws, true, buffer(
|
||||
s.data() + chop, s.size() - chop));
|
||||
flat_buffer b;
|
||||
w.read(ws, b);
|
||||
@@ -47,7 +73,7 @@ public:
|
||||
{
|
||||
ws.auto_fragment(false);
|
||||
std::string const s = "Hello";
|
||||
w.write(ws, boost::asio::buffer(s));
|
||||
w.write(ws, buffer(s));
|
||||
flat_buffer b;
|
||||
w.read(ws, b);
|
||||
BEAST_EXPECT(to_string(b.data()) == s);
|
||||
@@ -59,7 +85,7 @@ public:
|
||||
ws.auto_fragment(false);
|
||||
ws.write_buffer_size(16);
|
||||
std::string const s(32, '*');
|
||||
w.write(ws, boost::asio::buffer(s));
|
||||
w.write(ws, buffer(s));
|
||||
flat_buffer b;
|
||||
w.read(ws, b);
|
||||
BEAST_EXPECT(to_string(b.data()) == s);
|
||||
@@ -70,7 +96,7 @@ public:
|
||||
{
|
||||
ws.auto_fragment(true);
|
||||
std::string const s(16384, '*');
|
||||
w.write(ws, boost::asio::buffer(s));
|
||||
w.write(ws, buffer(s));
|
||||
flat_buffer b;
|
||||
w.read(ws, b);
|
||||
BEAST_EXPECT(to_string(b.data()) == s);
|
||||
@@ -88,7 +114,7 @@ public:
|
||||
w.accept(ws);
|
||||
ws.auto_fragment(false);
|
||||
std::string const s = "Hello";
|
||||
w.write(ws, boost::asio::buffer(s));
|
||||
w.write(ws, buffer(s));
|
||||
flat_buffer b;
|
||||
w.read(ws, b);
|
||||
BEAST_EXPECT(to_string(b.data()) == s);
|
||||
@@ -114,7 +140,7 @@ public:
|
||||
w.accept(ws);
|
||||
ws.auto_fragment(true);
|
||||
std::string const s(16384, '*');
|
||||
w.write(ws, boost::asio::buffer(s));
|
||||
w.write(ws, buffer(s));
|
||||
flat_buffer b;
|
||||
w.read(ws, b);
|
||||
BEAST_EXPECT(to_string(b.data()) == s);
|
||||
@@ -130,13 +156,14 @@ public:
|
||||
|
||||
pmd.client_enable = true;
|
||||
pmd.server_enable = true;
|
||||
pmd.compLevel = 1;
|
||||
|
||||
// deflate
|
||||
doTest(pmd, [&](ws_type& ws)
|
||||
{
|
||||
auto const& s = random_string();
|
||||
ws.binary(true);
|
||||
w.write(ws, boost::asio::buffer(s));
|
||||
w.write(ws, buffer(s));
|
||||
flat_buffer b;
|
||||
w.read(ws, b);
|
||||
BEAST_EXPECT(to_string(b.data()) == s);
|
||||
@@ -151,8 +178,8 @@ public:
|
||||
// This call should produce no
|
||||
// output due to compression latency.
|
||||
w.write_some(ws, false,
|
||||
boost::asio::buffer(s.data(), chop));
|
||||
w.write_some(ws, true, boost::asio::buffer(
|
||||
buffer(s.data(), chop));
|
||||
w.write_some(ws, true, buffer(
|
||||
s.data() + chop, s.size() - chop));
|
||||
flat_buffer b;
|
||||
w.read(ws, b);
|
||||
@@ -165,7 +192,7 @@ public:
|
||||
{
|
||||
auto const& s = random_string();
|
||||
ws.binary(true);
|
||||
w.write(ws, boost::asio::buffer(s));
|
||||
w.write(ws, buffer(s));
|
||||
flat_buffer b;
|
||||
w.read(ws, b);
|
||||
BEAST_EXPECT(to_string(b.data()) == s);
|
||||
@@ -175,6 +202,8 @@ public:
|
||||
void
|
||||
testWrite()
|
||||
{
|
||||
using boost::asio::buffer;
|
||||
|
||||
doTestWrite(SyncClient{});
|
||||
|
||||
yield_to([&](yield_context yield)
|
||||
@@ -249,7 +278,7 @@ public:
|
||||
std::size_t count = 0;
|
||||
std::string const s(16384, '*');
|
||||
ws.auto_fragment(true);
|
||||
ws.async_write(boost::asio::buffer(s),
|
||||
ws.async_write(buffer(s),
|
||||
[&](error_code ec)
|
||||
{
|
||||
++count;
|
||||
@@ -295,7 +324,7 @@ public:
|
||||
std::size_t count = 0;
|
||||
std::string const s(16384, '*');
|
||||
ws.auto_fragment(true);
|
||||
ws.async_write(boost::asio::buffer(s),
|
||||
ws.async_write(buffer(s),
|
||||
[&](error_code ec)
|
||||
{
|
||||
++count;
|
||||
@@ -338,6 +367,7 @@ public:
|
||||
{
|
||||
permessage_deflate pmd;
|
||||
pmd.client_enable = true;
|
||||
pmd.compLevel = 1;
|
||||
ws.set_option(pmd);
|
||||
}
|
||||
ws.next_layer().connect(es.stream());
|
||||
@@ -346,7 +376,7 @@ public:
|
||||
std::size_t count = 0;
|
||||
auto const& s = random_string();
|
||||
ws.binary(true);
|
||||
ws.async_write(boost::asio::buffer(s),
|
||||
ws.async_write(buffer(s),
|
||||
[&](error_code ec)
|
||||
{
|
||||
++count;
|
||||
|
||||
Reference in new issue
Block a user