Commit f81216be authored by Samir Halilcevic's avatar Samir Halilcevic

Refactor test cases and unify mock socket app

parent 4f20d587
......@@ -6,7 +6,7 @@
#include "caf/detail/rfc6455.hpp"
#include "caf/test/dsl.hpp"
#include "net-test.hpp"
#include "caf/byte_buffer.hpp"
#include "caf/span.hpp"
......@@ -39,259 +39,259 @@ struct fixture {
} // namespace
CAF_TEST_FIXTURE_SCOPE(rfc6455_tests, fixture)
BEGIN_FIXTURE_SCOPE(fixture)
CAF_TEST(masking) {
TEST_CASE("masking") {
auto key = uint32_t{0xDEADC0DE};
auto data = bytes({0x12, 0x34, 0x45, 0x67, 0x89, 0x9A});
auto masked_data = data;
CAF_MESSAGE("masking XORs the repeated key to data");
MESSAGE("masking XORs the repeated key to data");
impl::mask_data(key, masked_data);
CAF_CHECK_EQUAL(masked_data, bytes({
0x12 ^ 0xDE,
0x34 ^ 0xAD,
0x45 ^ 0xC0,
0x67 ^ 0xDE,
0x89 ^ 0xDE,
0x9A ^ 0xAD,
}));
CAF_MESSAGE("masking masked data again gives the original data");
CHECK_EQ(masked_data, bytes({
0x12 ^ 0xDE,
0x34 ^ 0xAD,
0x45 ^ 0xC0,
0x67 ^ 0xDE,
0x89 ^ 0xDE,
0x9A ^ 0xAD,
}));
MESSAGE("masking masked data again gives the original data");
impl::mask_data(key, masked_data);
CAF_CHECK_EQUAL(masked_data, data);
CHECK_EQ(masked_data, data);
}
CAF_TEST(no mask key and no data) {
std::vector<uint8_t> data{};
TEST_CASE("no mask key and no data") {
std::vector<uint8_t> data;
byte_buffer out;
impl::assemble_frame(impl::binary_frame, 0, as_bytes(make_span(data)), out);
CAF_CHECK_EQUAL(out, bytes({
0x82, // FIN + binary frame opcode
0x00, // data size = 0
}));
CHECK_EQ(out, bytes({
0x82, // FIN + binary frame opcode
0x00, // data size = 0
}));
impl::header hdr;
CAF_CHECK_EQUAL(impl::decode_header(out, hdr), 2);
CAF_CHECK_EQUAL(hdr.fin, true);
CAF_CHECK_EQUAL(hdr.mask_key, 0u);
CAF_CHECK_EQUAL(hdr.opcode, impl::binary_frame);
CAF_CHECK_EQUAL(hdr.payload_len, data.size());
CHECK_EQ(impl::decode_header(out, hdr), 2);
CHECK_EQ(hdr.fin, true);
CHECK_EQ(hdr.mask_key, 0u);
CHECK_EQ(hdr.opcode, impl::binary_frame);
CHECK_EQ(hdr.payload_len, data.size());
}
CAF_TEST(valid mask key and no data) {
std::vector<uint8_t> data{};
TEST_CASE("valid mask key and no data") {
std::vector<uint8_t> data;
byte_buffer out;
impl::assemble_frame(impl::binary_frame, 0xDEADC0DE,
as_bytes(make_span(data)), out);
CAF_CHECK_EQUAL(out, bytes({
0x82, // FIN + binary frame opcode
0x80, // MASKED + data size = 0
0xDE, 0xAD, 0xC0, 0xDE, // mask key,
}));
CHECK_EQ(out, bytes({
0x82, // FIN + binary frame opcode
0x80, // MASKED + data size = 0
0xDE, 0xAD, 0xC0, 0xDE, // mask key,
}));
impl::header hdr;
CAF_CHECK_EQUAL(impl::decode_header(out, hdr), 6);
CAF_CHECK_EQUAL(hdr.fin, true);
CAF_CHECK_EQUAL(hdr.mask_key, 0xDEADC0DEu);
CAF_CHECK_EQUAL(hdr.opcode, impl::binary_frame);
CAF_CHECK_EQUAL(hdr.payload_len, data.size());
CHECK_EQ(impl::decode_header(out, hdr), 6);
CHECK_EQ(hdr.fin, true);
CHECK_EQ(hdr.mask_key, 0xDEADC0DE);
CHECK_EQ(hdr.opcode, impl::binary_frame);
CHECK_EQ(hdr.payload_len, data.size());
}
CAF_TEST(no mask key plus small data) {
TEST_CASE("no mask key plus small data") {
std::vector<uint8_t> data{0x12, 0x34, 0x45, 0x67};
byte_buffer out;
impl::assemble_frame(impl::binary_frame, 0, as_bytes(make_span(data)), out);
CAF_CHECK_EQUAL(out, bytes({
0x82, // FIN + binary frame opcode
0x04, // data size = 4
0x12, 0x34, 0x45, 0x67, // masked data
}));
CHECK_EQ(out, bytes({
0x82, // FIN + binary frame opcode
0x04, // data size = 4
0x12, 0x34, 0x45, 0x67, // masked data
}));
impl::header hdr;
CAF_CHECK_EQUAL(impl::decode_header(out, hdr), 2);
CAF_CHECK_EQUAL(hdr.fin, true);
CAF_CHECK_EQUAL(hdr.mask_key, 0u);
CAF_CHECK_EQUAL(hdr.opcode, impl::binary_frame);
CAF_CHECK_EQUAL(hdr.payload_len, data.size());
CHECK_EQ(impl::decode_header(out, hdr), 2);
CHECK_EQ(hdr.fin, true);
CHECK_EQ(hdr.mask_key, 0u);
CHECK_EQ(hdr.opcode, impl::binary_frame);
CHECK_EQ(hdr.payload_len, data.size());
}
CAF_TEST(valid mask key plus small data) {
TEST_CASE("valid mask key plus small data") {
std::vector<uint8_t> data{0x12, 0x34, 0x45, 0x67};
byte_buffer out;
impl::assemble_frame(impl::binary_frame, 0xDEADC0DE,
as_bytes(make_span(data)), out);
CAF_CHECK_EQUAL(out, bytes({
0x82, // FIN + binary frame opcode
0x84, // MASKED + data size = 4
0xDE, 0xAD, 0xC0, 0xDE, // mask key,
0x12, 0x34, 0x45, 0x67, // masked data
}));
CHECK_EQ(out, bytes({
0x82, // FIN + binary frame opcode
0x84, // MASKED + data size = 4
0xDE, 0xAD, 0xC0, 0xDE, // mask key,
0x12, 0x34, 0x45, 0x67, // masked data
}));
impl::header hdr;
CAF_CHECK_EQUAL(impl::decode_header(out, hdr), 6);
CAF_CHECK_EQUAL(hdr.fin, true);
CAF_CHECK_EQUAL(hdr.mask_key, 0xDEADC0DEu);
CAF_CHECK_EQUAL(hdr.opcode, impl::binary_frame);
CAF_CHECK_EQUAL(hdr.payload_len, data.size());
CHECK_EQ(impl::decode_header(out, hdr), 6);
CHECK_EQ(hdr.fin, true);
CHECK_EQ(hdr.mask_key, 0xDEADC0DE);
CHECK_EQ(hdr.opcode, impl::binary_frame);
CHECK_EQ(hdr.payload_len, data.size());
}
CAF_TEST(no mask key plus upper bound on small data) {
TEST_CASE("no mask key plus upper bound on small data") {
std::vector<uint8_t> data;
data.resize(125, 0xFF);
byte_buffer out;
impl::assemble_frame(impl::binary_frame, 0, as_bytes(make_span(data)), out);
CAF_CHECK_EQUAL(take(out, 6), bytes({
0x82, // FIN + binary frame opcode
0x7D, // data size = 125
0xFF, 0xFF, 0xFF, 0xFF, // masked data
}));
CHECK_EQ(take(out, 6), bytes({
0x82, // FIN + binary frame opcode
0x7D, // data size = 125
0xFF, 0xFF, 0xFF, 0xFF, // masked data
}));
impl::header hdr;
CAF_CHECK_EQUAL(impl::decode_header(out, hdr), 2);
CAF_CHECK_EQUAL(hdr.fin, true);
CAF_CHECK_EQUAL(hdr.mask_key, 0u);
CAF_CHECK_EQUAL(hdr.opcode, impl::binary_frame);
CAF_CHECK_EQUAL(hdr.payload_len, data.size());
CHECK_EQ(impl::decode_header(out, hdr), 2);
CHECK_EQ(hdr.fin, true);
CHECK_EQ(hdr.mask_key, 0u);
CHECK_EQ(hdr.opcode, impl::binary_frame);
CHECK_EQ(hdr.payload_len, data.size());
}
CAF_TEST(valid mask key plus upper bound on small data) {
TEST_CASE("valid mask key plus upper bound on small data") {
std::vector<uint8_t> data;
data.resize(125, 0xFF);
byte_buffer out;
impl::assemble_frame(impl::binary_frame, 0xDEADC0DE,
as_bytes(make_span(data)), out);
CAF_CHECK_EQUAL(take(out, 10), bytes({
0x82, // FIN + binary frame opcode
0xFD, // MASKED + data size = 125
0xDE, 0xAD, 0xC0, 0xDE, // mask key,
0xFF, 0xFF, 0xFF, 0xFF, // masked data
}));
CHECK_EQ(take(out, 10), bytes({
0x82, // FIN + binary frame opcode
0xFD, // MASKED + data size = 125
0xDE, 0xAD, 0xC0, 0xDE, // mask key,
0xFF, 0xFF, 0xFF, 0xFF, // masked data
}));
impl::header hdr;
CAF_CHECK_EQUAL(impl::decode_header(out, hdr), 6);
CAF_CHECK_EQUAL(hdr.fin, true);
CAF_CHECK_EQUAL(hdr.mask_key, 0xDEADC0DEu);
CAF_CHECK_EQUAL(hdr.opcode, impl::binary_frame);
CAF_CHECK_EQUAL(hdr.payload_len, data.size());
CHECK_EQ(impl::decode_header(out, hdr), 6);
CHECK_EQ(hdr.fin, true);
CHECK_EQ(hdr.mask_key, 0xDEADC0DE);
CHECK_EQ(hdr.opcode, impl::binary_frame);
CHECK_EQ(hdr.payload_len, data.size());
}
CAF_TEST(no mask key plus medium data) {
TEST_CASE("no mask key plus medium data") {
std::vector<uint8_t> data;
data.insert(data.end(), 126, 0xFF);
data.resize(126, 0xFF);
byte_buffer out;
impl::assemble_frame(impl::binary_frame, 0, as_bytes(make_span(data)), out);
CAF_CHECK_EQUAL(take(out, 8),
bytes({
0x82, // FIN + binary frame opcode
0x7E, // 126 -> uint16 size
0x00, 0x7E, // data size = 126
0xFF, 0xFF, 0xFF, 0xFF, // first 4 masked bytes
}));
CHECK_EQ(take(out, 8),
bytes({
0x82, // FIN + binary frame opcode
0x7E, // 126 -> uint16 size
0x00, 0x7E, // data size = 126
0xFF, 0xFF, 0xFF, 0xFF, // first 4 masked bytes
}));
impl::header hdr;
CAF_CHECK_EQUAL(impl::decode_header(out, hdr), 4);
CAF_CHECK_EQUAL(hdr.fin, true);
CAF_CHECK_EQUAL(hdr.mask_key, 0u);
CAF_CHECK_EQUAL(hdr.opcode, impl::binary_frame);
CAF_CHECK_EQUAL(hdr.payload_len, data.size());
CHECK_EQ(impl::decode_header(out, hdr), 4);
CHECK_EQ(hdr.fin, true);
CHECK_EQ(hdr.mask_key, 0u);
CHECK_EQ(hdr.opcode, impl::binary_frame);
CHECK_EQ(hdr.payload_len, data.size());
}
CAF_TEST(valid mask key plus medium data) {
TEST_CASE("valid mask key plus medium data") {
std::vector<uint8_t> data;
data.insert(data.end(), 126, 0xFF);
data.resize(126, 0xFF);
byte_buffer out;
impl::assemble_frame(impl::binary_frame, 0xDEADC0DE,
as_bytes(make_span(data)), out);
CAF_CHECK_EQUAL(take(out, 12),
bytes({
0x82, // FIN + binary frame opcode
0xFE, // MASKED + 126 -> uint16 size
0x00, 0x7E, // data size = 126
0xDE, 0xAD, 0xC0, 0xDE, // mask key,
0xFF, 0xFF, 0xFF, 0xFF, // first 4 masked bytes
}));
CHECK_EQ(take(out, 12),
bytes({
0x82, // FIN + binary frame opcode
0xFE, // MASKED + 126 -> uint16 size
0x00, 0x7E, // data size = 126
0xDE, 0xAD, 0xC0, 0xDE, // mask key,
0xFF, 0xFF, 0xFF, 0xFF, // first 4 masked bytes
}));
impl::header hdr;
CAF_CHECK_EQUAL(impl::decode_header(out, hdr), 8);
CAF_CHECK_EQUAL(hdr.fin, true);
CAF_CHECK_EQUAL(hdr.mask_key, 0xDEADC0DEu);
CAF_CHECK_EQUAL(hdr.opcode, impl::binary_frame);
CAF_CHECK_EQUAL(hdr.payload_len, data.size());
CHECK_EQ(impl::decode_header(out, hdr), 8);
CHECK_EQ(hdr.fin, true);
CHECK_EQ(hdr.mask_key, 0xDEADC0DE);
CHECK_EQ(hdr.opcode, impl::binary_frame);
CHECK_EQ(hdr.payload_len, data.size());
}
CAF_TEST(no mask key plus upper bound on medium data) {
TEST_CASE("no mask key plus upper bound on medium data") {
std::vector<uint8_t> data;
data.insert(data.end(), 65535, 0xFF);
data.resize(65535, 0xFF);
byte_buffer out;
impl::assemble_frame(impl::binary_frame, 0, as_bytes(make_span(data)), out);
CAF_CHECK_EQUAL(take(out, 8),
bytes({
0x82, // FIN + binary frame opcode
0x7E, // 126 -> uint16 size
0xFF, 0xFF, // data size = 65535
0xFF, 0xFF, 0xFF, 0xFF, // first 4 masked bytes
}));
CHECK_EQ(take(out, 8),
bytes({
0x82, // FIN + binary frame opcode
0x7E, // 126 -> uint16 size
0xFF, 0xFF, // data size = 65535
0xFF, 0xFF, 0xFF, 0xFF, // first 4 masked bytes
}));
impl::header hdr;
CAF_CHECK_EQUAL(impl::decode_header(out, hdr), 4);
CAF_CHECK_EQUAL(hdr.fin, true);
CAF_CHECK_EQUAL(hdr.mask_key, 0u);
CAF_CHECK_EQUAL(hdr.opcode, impl::binary_frame);
CAF_CHECK_EQUAL(hdr.payload_len, data.size());
CHECK_EQ(impl::decode_header(out, hdr), 4);
CHECK_EQ(hdr.fin, true);
CHECK_EQ(hdr.mask_key, 0u);
CHECK_EQ(hdr.opcode, impl::binary_frame);
CHECK_EQ(hdr.payload_len, data.size());
}
CAF_TEST(valid mask key plus upper bound on medium data) {
TEST_CASE("valid mask key plus upper bound on medium data") {
std::vector<uint8_t> data;
data.insert(data.end(), 65535, 0xFF);
data.resize(65535, 0xFF);
byte_buffer out;
impl::assemble_frame(impl::binary_frame, 0xDEADC0DE,
as_bytes(make_span(data)), out);
CAF_CHECK_EQUAL(take(out, 12),
bytes({
0x82, // FIN + binary frame opcode
0xFE, // 126 -> uint16 size
0xFF, 0xFF, // data size = 65535
0xDE, 0xAD, 0xC0, 0xDE, // mask key,
0xFF, 0xFF, 0xFF, 0xFF, // first 4 masked bytes
}));
CHECK_EQ(take(out, 12),
bytes({
0x82, // FIN + binary frame opcode
0xFE, // 126 -> uint16 size
0xFF, 0xFF, // data size = 65535
0xDE, 0xAD, 0xC0, 0xDE, // mask key,
0xFF, 0xFF, 0xFF, 0xFF, // first 4 masked bytes
}));
impl::header hdr;
CAF_CHECK_EQUAL(impl::decode_header(out, hdr), 8);
CAF_CHECK_EQUAL(hdr.fin, true);
CAF_CHECK_EQUAL(hdr.mask_key, 0xDEADC0DEu);
CAF_CHECK_EQUAL(hdr.opcode, impl::binary_frame);
CAF_CHECK_EQUAL(hdr.payload_len, data.size());
CHECK_EQ(impl::decode_header(out, hdr), 8);
CHECK_EQ(hdr.fin, true);
CHECK_EQ(hdr.mask_key, 0xDEADC0DE);
CHECK_EQ(hdr.opcode, impl::binary_frame);
CHECK_EQ(hdr.payload_len, data.size());
}
CAF_TEST(no mask key plus large data) {
TEST_CASE("no mask key plus large data") {
std::vector<uint8_t> data;
data.insert(data.end(), 65536, 0xFF);
data.resize(65536, 0xFF);
byte_buffer out;
impl::assemble_frame(impl::binary_frame, 0, as_bytes(make_span(data)), out);
CAF_CHECK_EQUAL(take(out, 14),
bytes({
0x82, // FIN + binary frame opcode
0x7F, // 127 -> uint64 size
0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, // 65536
0xFF, 0xFF, 0xFF, 0xFF, // first 4 masked bytes
}));
CHECK_EQ(take(out, 14),
bytes({
0x82, // FIN + binary frame opcode
0x7F, // 127 -> uint64 size
0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, // 65536
0xFF, 0xFF, 0xFF, 0xFF, // first 4 masked bytes
}));
impl::header hdr;
CAF_CHECK_EQUAL(impl::decode_header(out, hdr), 10);
CAF_CHECK_EQUAL(hdr.fin, true);
CAF_CHECK_EQUAL(hdr.mask_key, 0u);
CAF_CHECK_EQUAL(hdr.opcode, impl::binary_frame);
CAF_CHECK_EQUAL(hdr.payload_len, data.size());
CHECK_EQ(impl::decode_header(out, hdr), 10);
CHECK_EQ(hdr.fin, true);
CHECK_EQ(hdr.mask_key, 0u);
CHECK_EQ(hdr.opcode, impl::binary_frame);
CHECK_EQ(hdr.payload_len, data.size());
}
CAF_TEST(valid mask key plus large data) {
TEST_CASE("valid mask key plus large data") {
std::vector<uint8_t> data;
data.insert(data.end(), 65536, 0xFF);
data.resize(65536, 0xFF);
byte_buffer out;
impl::assemble_frame(impl::binary_frame, 0xDEADC0DE,
as_bytes(make_span(data)), out);
CAF_CHECK_EQUAL(take(out, 18),
bytes({
0x82, // FIN + binary frame opcode
0xFF, // MASKED + 127 -> uint64 size
0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, // 65536
0xDE, 0xAD, 0xC0, 0xDE, // mask key,
0xFF, 0xFF, 0xFF, 0xFF, // first 4 masked bytes
}));
CHECK_EQ(take(out, 18),
bytes({
0x82, // FIN + binary frame opcode
0xFF, // MASKED + 127 -> uint64 size
0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, // 65536
0xDE, 0xAD, 0xC0, 0xDE, // mask key,
0xFF, 0xFF, 0xFF, 0xFF, // first 4 masked bytes
}));
impl::header hdr;
CAF_CHECK_EQUAL(impl::decode_header(out, hdr), 14);
CAF_CHECK_EQUAL(hdr.fin, true);
CAF_CHECK_EQUAL(hdr.mask_key, 0xDEADC0DEu);
CAF_CHECK_EQUAL(hdr.opcode, impl::binary_frame);
CAF_CHECK_EQUAL(hdr.payload_len, data.size());
CHECK_EQ(impl::decode_header(out, hdr), 14);
CHECK_EQ(hdr.fin, true);
CHECK_EQ(hdr.mask_key, 0xDEADC0DE);
CHECK_EQ(hdr.opcode, impl::binary_frame);
CHECK_EQ(hdr.payload_len, data.size());
}
CAF_TEST_FIXTURE_SCOPE_END()
END_FIXTURE_SCOPE()
......@@ -118,6 +118,59 @@ ptrdiff_t mock_stream_transport::handle_input() {
return result;
}
// -- mock_web_socket_app ------------------------------------------------------
mock_web_socket_app::mock_web_socket_app(bool behave_as_server)
: behave_as_server(behave_as_server) {
// nop
}
caf::error mock_web_socket_app::start(caf::net::web_socket::lower_layer* ll) {
down = ll;
if (behave_as_server)
down->request_messages();
return caf::none;
}
caf::error
mock_web_socket_app::accept(const caf::net::http::request_header& hdr) {
// Store the request information in cfg to evaluate them later.
auto& ws = cfg["web-socket"].as_dictionary();
put(ws, "method", to_rfc_string(hdr.method()));
put(ws, "path", std::string{hdr.path()});
put(ws, "query", hdr.query());
put(ws, "fragment", hdr.fragment());
put(ws, "http-version", hdr.version());
if (hdr.num_fields() > 0) {
auto& fields = ws["fields"].as_dictionary();
hdr.for_each_field([&fields](auto key, auto val) {
put(fields, std::string{key}, std::string{val});
});
}
return caf::none;
}
void mock_web_socket_app::abort(const caf::error& reason) {
if (expect_abort_) {
has_aborted = true;
err = reason;
expect_abort_ = false;
down->shutdown(reason);
} else {
CAF_FAIL("app::abort called: " << reason);
}
}
ptrdiff_t mock_web_socket_app::consume_text(std::string_view text) {
text_input.insert(text_input.end(), text.begin(), text.end());
return static_cast<ptrdiff_t>(text.size());
}
ptrdiff_t mock_web_socket_app::consume_binary(caf::byte_span bytes) {
binary_input.insert(binary_input.end(), bytes.begin(), bytes.end());
return static_cast<ptrdiff_t>(bytes.size());
}
// -- barrier ------------------------------------------------------------------
void barrier::arrive_and_wait() {
......
......@@ -5,6 +5,7 @@
#include "caf/net/octet_stream/upper_layer.hpp"
#include "caf/net/receive_policy.hpp"
#include "caf/net/socket.hpp"
#include "caf/net/web_socket/server.hpp"
#include "caf/settings.hpp"
#include "caf/span.hpp"
#include "caf/string_view.hpp"
......@@ -105,6 +106,63 @@ private:
caf::net::multiplexer* mpx_;
};
class mock_web_socket_app : public caf::net::web_socket::upper_layer::server {
public:
// -- constructor ------------------------------------------------------------
mock_web_socket_app(bool behave_as_server);
// -- factories --------------------------------------------------------------
static auto make(bool behave_as_server = false) {
return std::make_unique<mock_web_socket_app>(behave_as_server);
}
// -- initialization ---------------------------------------------------------
caf::error start(caf::net::web_socket::lower_layer* ll) override;
// -- implementation ---------------------------------------------------------
caf::error accept(const caf::net::http::request_header& hdr) override;
void prepare_send() override {
// nop
}
bool done_sending() override {
return true;
}
void abort(const caf::error& reason) override;
ptrdiff_t consume_text(std::string_view text) override;
ptrdiff_t consume_binary(caf::byte_span bytes) override;
void expect_abort() {
expect_abort_ = true;
}
// -- member variables -------------------------------------------------------
std::string text_input;
caf::byte_buffer binary_input;
caf::net::web_socket::lower_layer* down = nullptr;
caf::settings cfg;
bool behave_as_server = false;
caf::error err;
bool has_aborted = false;
bool expect_abort_ = false;
};
// Drop-in replacement for std::barrier (based on the TS API as of 2020).
class barrier {
public:
......
......@@ -14,43 +14,6 @@ namespace {
using svec = std::vector<std::string>;
class app_t : public net::web_socket::upper_layer {
public:
static auto make() {
return std::make_unique<app_t>();
}
std::string text_input;
caf::byte_buffer binary_input;
error start(net::web_socket::lower_layer*) override {
return none;
}
void prepare_send() override {
// nop
}
bool done_sending() override {
return true;
}
void abort(const error& reason) override {
CAF_FAIL("app::abort called: " << reason);
}
ptrdiff_t consume_text(std::string_view text) override {
text_input.insert(text_input.end(), text.begin(), text.end());
return static_cast<ptrdiff_t>(text.size());
}
ptrdiff_t consume_binary(byte_span bytes) override {
binary_input.insert(binary_input.end(), bytes.begin(), bytes.end());
return static_cast<ptrdiff_t>(bytes.size());
}
};
constexpr std::string_view key = "the sample nonce";
constexpr std::string_view http_request
......@@ -93,7 +56,7 @@ auto make_handshake() {
SCENARIO("the client performs the WebSocket handshake on startup") {
GIVEN("valid WebSocket handshake data") {
WHEN("starting a WebSocket client") {
auto app = app_t::make();
auto app = mock_web_socket_app::make();
auto ws = net::web_socket::client::make(make_handshake(), std::move(app));
auto uut = mock_stream_transport::make(std::move(ws));
THEN("the client sends its HTTP request when initializing it") {
......
......@@ -13,59 +13,13 @@ using namespace std::literals;
namespace {
class app_t : public net::web_socket::upper_layer {
public:
static auto make() {
return std::make_unique<app_t>();
}
std::string text_input;
caf::byte_buffer binary_input;
error err;
bool aborted = false;
net::web_socket::lower_layer* down = nullptr;
error start(net::web_socket::lower_layer* ll) override {
down = ll;
return none;
}
void prepare_send() override {
// nop
}
bool done_sending() override {
return true;
}
void abort(const error& reason) override {
aborted = true;
err = reason;
down->shutdown(reason);
}
ptrdiff_t consume_text(std::string_view text) override {
text_input.insert(text_input.end(), text.begin(), text.end());
return static_cast<ptrdiff_t>(text.size());
}
ptrdiff_t consume_binary(byte_span bytes) override {
binary_input.insert(binary_input.end(), bytes.begin(), bytes.end());
return static_cast<ptrdiff_t>(bytes.size());
}
};
struct fixture {
app_t* app;
mock_web_socket_app* app;
net::web_socket::framing* uut;
std::unique_ptr<mock_stream_transport> transport;
fixture() {
auto app_layer = app_t::make();
auto app_layer = mock_web_socket_app::make();
app = app_layer.get();
auto uut_layer
= net::web_socket::framing::make_server(std::move(app_layer));
......@@ -152,8 +106,9 @@ SCENARIO("the client sends an invalid ping that closes the connection") {
ping_frame);
transport->push(ping_frame);
THEN("the server aborts the application") {
app->expect_abort();
CHECK_EQ(transport->handle_input(), 0);
CHECK(app->aborted);
CHECK(app->has_aborted);
CHECK_EQ(app->err, sec::protocol_error);
MESSAGE("Aborted with: " << app->err);
}
......
......@@ -20,67 +20,10 @@ namespace {
using svec = std::vector<std::string>;
class app_t : public net::web_socket::upper_layer::server {
public:
std::string text_input;
byte_buffer binary_input;
settings cfg;
static auto make() {
return std::make_unique<app_t>();
}
error start(net::web_socket::lower_layer* down) override {
down->request_messages();
return none;
}
error accept(const net::http::request_header& hdr) override {
// Store the request information in cfg to evaluate them later.
auto& ws = cfg["web-socket"].as_dictionary();
put(ws, "method", to_rfc_string(hdr.method()));
put(ws, "path", std::string{hdr.path()});
put(ws, "query", hdr.query());
put(ws, "fragment", hdr.fragment());
put(ws, "http-version", hdr.version());
if (hdr.num_fields() > 0) {
auto& fields = ws["fields"].as_dictionary();
hdr.for_each_field([&fields](auto key, auto val) {
put(fields, std::string{key}, std::string{val});
});
}
return none;
}
void prepare_send() override {
// nop
}
bool done_sending() override {
return true;
}
void abort(const error& reason) override {
CAF_FAIL("app::abort called: " << reason);
}
ptrdiff_t consume_text(std::string_view text) override {
text_input.insert(text_input.end(), text.begin(), text.end());
return static_cast<ptrdiff_t>(text.size());
}
ptrdiff_t consume_binary(byte_span bytes) override {
binary_input.insert(binary_input.end(), bytes.begin(), bytes.end());
return static_cast<ptrdiff_t>(bytes.size());
}
};
struct fixture {
fixture() {
using namespace caf::net;
auto app_ptr = app_t::make();
auto app_ptr = mock_web_socket_app::make(/*behave_as_server=*/true);
app = app_ptr.get();
auto ws_ptr = net::web_socket::server::make(std::move(app_ptr));
transport = mock_stream_transport::make(std::move(ws_ptr));
......@@ -126,7 +69,7 @@ struct fixture {
std::unique_ptr<mock_stream_transport> transport;
app_t* app;
mock_web_socket_app* app;
std::minstd_rand rng;
};
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment