Files
boost_beast/test/beast/websocket/stream.cpp
T

347 lines
9.9 KiB
C++
Raw Normal View History

2016-04-30 13:00:33 -04:00
//
2017-08-21 14:45:58 -07:00
// Copyright (w) 2016-2017 Vinnie Falco (vinnie dot falco at gmail dot com)
2016-04-30 13:00:33 -04:00
//
// 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)
//
2017-07-20 13:40:34 -07:00
// Official repository: https://github.com/boostorg/beast
//
2016-04-30 13:00:33 -04:00
// Test that header file is self-contained.
2017-07-20 13:40:34 -07:00
#include <boost/beast/websocket/stream.hpp>
2016-04-30 13:00:33 -04:00
2017-08-24 06:21:30 -07:00
#include "test.hpp"
2016-04-30 13:00:33 -04:00
2017-07-20 13:40:34 -07:00
namespace boost {
2016-04-30 13:00:33 -04:00
namespace beast {
namespace websocket {
2017-08-24 06:21:30 -07:00
class stream_test : public websocket_test_suite
2016-04-30 13:00:33 -04:00
{
public:
2017-08-22 18:08:56 -07:00
void
testOptions()
{
2017-08-24 06:21:30 -07:00
stream<test::stream> ws(ios_);
2017-08-22 18:08:56 -07:00
ws.auto_fragment(true);
ws.write_buffer_size(2048);
ws.binary(false);
ws.read_message_max(1 * 1024 * 1024);
try
{
ws.write_buffer_size(7);
fail();
}
catch(std::exception const&)
{
pass();
2016-05-04 17:27:50 -04:00
}
}
//--------------------------------------------------------------------------
2016-10-24 18:41:25 -04:00
2017-08-21 14:45:58 -07:00
template<class Wrap>
2016-10-24 18:41:25 -04:00
void
2017-08-22 18:08:56 -07:00
doTestStream(Wrap const& w,
2017-08-21 14:45:58 -07:00
permessage_deflate const& pmd)
2016-10-24 18:41:25 -04:00
{
using boost::asio::buffer;
// send empty message
2017-08-21 14:45:58 -07:00
doTest(pmd, [&](ws_type& ws)
2016-10-24 18:41:25 -04:00
{
ws.text(true);
2017-08-21 14:45:58 -07:00
w.write(ws, boost::asio::null_buffers{});
multi_buffer b;
2017-08-21 14:45:58 -07:00
w.read(ws, b);
BEAST_EXPECT(ws.got_text());
BEAST_EXPECT(b.size() == 0);
});
// send message
2017-08-21 14:45:58 -07:00
doTest(pmd, [&](ws_type& ws)
{
ws.auto_fragment(false);
ws.binary(false);
2017-08-21 14:45:58 -07:00
w.write(ws, sbuf("Hello"));
multi_buffer b;
2017-08-21 14:45:58 -07:00
w.read(ws, b);
BEAST_EXPECT(ws.got_text());
BEAST_EXPECT(to_string(b.data()) == "Hello");
});
// read_some
2017-08-21 14:45:58 -07:00
doTest(pmd, [&](ws_type& ws)
{
2017-08-21 14:45:58 -07:00
w.write(ws, sbuf("Hello"));
char buf[10];
auto const bytes_written =
2017-08-21 14:45:58 -07:00
w.read_some(ws, buffer(buf, sizeof(buf)));
2017-08-12 15:03:39 -07:00
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
2017-08-21 14:45:58 -07:00
doTest(pmd, [&](ws_type& ws)
{
2017-08-21 14:45:58 -07:00
w.close(ws, {});
});
// close with code
2017-08-21 14:45:58 -07:00
doTest(pmd, [&](ws_type& ws)
{
2017-08-21 14:45:58 -07:00
w.close(ws, close_code::going_away);
});
// send ping and message
2017-08-21 14:45:58 -07:00
doTest(pmd, [&](ws_type& ws)
{
bool once = false;
auto cb =
[&](frame_type kind, string_view s)
2016-10-24 18:41:25 -04:00
{
BEAST_EXPECT(kind == frame_type::pong);
BEAST_EXPECT(! once);
once = true;
BEAST_EXPECT(s == "");
2016-10-24 18:41:25 -04:00
};
ws.control_callback(cb);
2017-08-21 14:45:58 -07:00
w.ping(ws, "");
ws.binary(true);
2017-08-21 14:45:58 -07:00
w.write(ws, sbuf("Hello"));
multi_buffer b;
2017-08-21 14:45:58 -07:00
w.read(ws, b);
BEAST_EXPECT(once);
BEAST_EXPECT(ws.got_binary());
BEAST_EXPECT(to_string(b.data()) == "Hello");
});
// send ping and fragmented message
2017-08-21 14:45:58 -07:00
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");
2017-08-21 14:45:58 -07:00
w.write_some(ws, false, sbuf("Hello, "));
w.write_some(ws, false, sbuf(""));
w.write_some(ws, true, sbuf("World!"));
multi_buffer b;
2017-08-21 14:45:58 -07:00
w.read(ws, b);
BEAST_EXPECT(once);
BEAST_EXPECT(to_string(b.data()) == "Hello, World!");
ws.control_callback();
});
// send pong
2017-08-21 14:45:58 -07:00
doTest(pmd, [&](ws_type& ws)
{
2017-08-21 14:45:58 -07:00
w.pong(ws, "");
});
// send auto fragmented message
2017-08-21 14:45:58 -07:00
doTest(pmd, [&](ws_type& ws)
{
ws.auto_fragment(true);
ws.write_buffer_size(8);
2017-08-21 14:45:58 -07:00
w.write(ws, sbuf("Now is the time for all good men"));
multi_buffer b;
2017-08-21 14:45:58 -07:00
w.read(ws, b);
BEAST_EXPECT(to_string(b.data()) == "Now is the time for all good men");
});
// send message with write buffer limit
2017-08-21 14:45:58 -07:00
doTest(pmd, [&](ws_type& ws)
{
std::string s(2000, '*');
ws.write_buffer_size(1200);
2017-08-21 14:45:58 -07:00
w.write(ws, buffer(s.data(), s.size()));
multi_buffer b;
2017-08-21 14:45:58 -07:00
w.read(ws, b);
BEAST_EXPECT(to_string(b.data()) == s);
});
// unexpected cont
2017-08-21 14:45:58 -07:00
doTest(pmd, [&](ws_type& ws)
{
2017-08-21 14:45:58 -07:00
w.write_raw(ws, cbuf(
0x80, 0x80, 0xff, 0xff, 0xff, 0xff));
2017-08-21 14:45:58 -07:00
doCloseTest(w, ws, close_code::protocol_error);
});
// invalid fixed frame header
2017-08-21 14:45:58 -07:00
doTest(pmd, [&](ws_type& ws)
{
2017-08-21 14:45:58 -07:00
w.write_raw(ws, cbuf(
0x8f, 0x80, 0xff, 0xff, 0xff, 0xff));
2017-08-21 14:45:58 -07:00
doCloseTest(w, ws, close_code::protocol_error);
});
if(! pmd.client_enable)
{
// expected cont
2017-08-21 14:45:58 -07:00
doTest(pmd, [&](ws_type& ws)
2016-10-24 18:41:25 -04:00
{
2017-08-21 14:45:58 -07:00
w.write_some(ws, false, boost::asio::null_buffers{});
w.write_raw(ws, cbuf(
0x81, 0x80, 0xff, 0xff, 0xff, 0xff));
2017-08-21 14:45:58 -07:00
doCloseTest(w, ws, close_code::protocol_error);
});
2016-10-24 18:41:25 -04:00
// message size above 2^64
2017-08-21 14:45:58 -07:00
doTest(pmd, [&](ws_type& ws)
2016-10-24 18:41:25 -04:00
{
2017-08-21 14:45:58 -07:00
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));
2017-08-21 14:45:58 -07:00
doCloseTest(w, ws, close_code::too_big);
});
/*
// message size exceeds max
2017-08-21 14:45:58 -07:00
doTest(pmd, [&](ws_type& ws)
{
// VFALCO This was never implemented correctly
ws.read_message_max(1);
2017-08-21 14:45:58 -07:00
w.write(ws, cbuf(0x81, 0x02, '*', '*'));
doCloseTest(w, ws, close_code::too_big);
});
*/
2016-10-24 18:41:25 -04:00
}
// receive ping
2017-08-21 14:45:58 -07:00
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);
2017-08-21 14:45:58 -07:00
w.write(ws, sbuf("Hello"));
multi_buffer b;
2017-08-21 14:45:58 -07:00
w.read(ws, b);
BEAST_EXPECT(invoked);
BEAST_EXPECT(ws.got_text());
BEAST_EXPECT(to_string(b.data()) == "Hello");
});
// receive ping
2017-08-21 14:45:58 -07:00
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);
2017-08-21 14:45:58 -07:00
w.write(ws, sbuf("Hello"));
doCloseTest(w, ws, close_code::none);
});
// receive bad utf8
2017-08-21 14:45:58 -07:00
doTest(pmd, [&](ws_type& ws)
{
put(ws.next_layer().buffer(), cbuf(
0x81, 0x06, 0x03, 0xea, 0xf0, 0x28, 0x8c, 0xbc));
2017-08-21 14:45:58 -07:00
doFailTest(w, ws, error::failed);
});
// receive bad close
2017-08-21 14:45:58 -07:00
doTest(pmd, [&](ws_type& ws)
{
put(ws.next_layer().buffer(), cbuf(
0x88, 0x02, 0x03, 0xed));
2017-08-21 14:45:58 -07:00
doFailTest(w, ws, error::failed);
});
2016-10-24 18:41:25 -04:00
}
//--------------------------------------------------------------------------
2017-07-29 17:47:04 -07:00
2017-06-07 17:41:27 -07:00
void
run() override
2016-04-30 13:00:33 -04:00
{
2017-05-23 12:33:31 -07:00
BOOST_STATIC_ASSERT(std::is_constructible<
2017-08-24 06:21:30 -07:00
stream<test::stream>, boost::asio::io_service&>::value);
2016-05-07 17:06:46 -04:00
2017-05-23 12:33:31 -07:00
BOOST_STATIC_ASSERT(std::is_move_constructible<
2017-08-24 06:21:30 -07:00
stream<test::stream>>::value);
2016-04-30 13:00:33 -04:00
2017-05-23 12:33:31 -07:00
BOOST_STATIC_ASSERT(std::is_move_assignable<
2017-08-24 06:21:30 -07:00
stream<test::stream>>::value);
2016-04-30 13:00:33 -04:00
2017-05-23 12:33:31 -07:00
BOOST_STATIC_ASSERT(std::is_constructible<
2017-08-24 06:21:30 -07:00
stream<test::stream&>, test::stream&>::value);
2016-05-15 16:22:25 -04:00
2017-05-23 12:33:31 -07:00
BOOST_STATIC_ASSERT(std::is_move_constructible<
2017-08-24 06:21:30 -07:00
stream<test::stream&>>::value);
2016-05-15 16:22:25 -04:00
2017-05-23 12:33:31 -07:00
BOOST_STATIC_ASSERT(! std::is_move_assignable<
2017-08-24 06:21:30 -07:00
stream<test::stream&>>::value);
2016-04-30 13:00:33 -04:00
2016-06-10 15:48:39 -04:00
log << "sizeof(websocket::stream) == " <<
2017-08-16 19:25:02 -07:00
sizeof(websocket::stream<test::stream&>) << std::endl;
2016-10-24 18:41:25 -04:00
testOptions();
2017-08-22 18:08:56 -07:00
auto const testStream =
[this](permessage_deflate const& pmd)
2016-10-24 18:41:25 -04:00
{
2017-08-22 18:08:56 -07:00
doTestStream(SyncClient{}, pmd);
2017-08-21 14:45:58 -07:00
2017-08-12 15:03:39 -07:00
yield_to(
[&](yield_context yield)
{
2017-08-22 18:08:56 -07:00
doTestStream(AsyncClient{yield}, pmd);
});
2016-10-24 18:41:25 -04:00
};
2017-08-22 18:08:56 -07:00
permessage_deflate pmd;
2016-10-24 18:41:25 -04:00
pmd.client_enable = false;
pmd.server_enable = false;
2017-08-22 18:08:56 -07:00
testStream(pmd);
2016-10-24 18:41:25 -04:00
pmd.client_enable = true;
pmd.server_enable = true;
pmd.client_max_window_bits = 10;
pmd.client_no_context_takeover = false;
2017-07-31 18:48:22 -07:00
pmd.compLevel = 1;
pmd.memLevel = 1;
2017-08-22 18:08:56 -07:00
testStream(pmd);
2016-10-24 18:41:25 -04:00
pmd.client_enable = true;
pmd.server_enable = true;
pmd.client_max_window_bits = 10;
pmd.client_no_context_takeover = true;
2017-07-31 18:48:22 -07:00
pmd.compLevel = 1;
pmd.memLevel = 1;
2017-08-22 18:08:56 -07:00
testStream(pmd);
2016-04-30 13:00:33 -04:00
}
};
2017-08-01 17:01:57 -07:00
BEAST_DEFINE_TESTSUITE(beast,websocket,stream);
2016-04-30 13:00:33 -04:00
} // websocket
} // beast
2017-07-20 13:40:34 -07:00
} // boost