From 76af4167669d9f243a1ad223462b67d3638df368 Mon Sep 17 00:00:00 2001 From: The-EDev Date: Mon, 9 Nov 2020 04:47:41 +0300 Subject: [PATCH] added websocket unit test --- tests/unittest.cpp | 134 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 134 insertions(+) diff --git a/tests/unittest.cpp b/tests/unittest.cpp index 730623807..7b4b35978 100644 --- a/tests/unittest.cpp +++ b/tests/unittest.cpp @@ -1371,3 +1371,137 @@ TEST_CASE("stream_response") }); runTest.join(); } + +TEST_CASE("websocket") +{ + static std::string http_message = "GET /ws HTTP/1.1\r\nConnection: keep-alive, Upgrade\r\nupgrade: websocket\r\nSec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\nSec-WebSocket-Version: 13\r\n\r\n"; + + static bool connected{false}; + + SimpleApp app; + + CROW_ROUTE(app, "/ws").websocket() + .onopen([&](websocket::connection&){ + connected = true; + CROW_LOG_INFO << "Connected websocket and value is " << connected; + }) + .onmessage([&](websocket::connection& conn, const std::string& message, bool isbin){ + CROW_LOG_INFO << "Message is \"" << message << '\"'; + if (!isbin && message == "PINGME") + conn.send_ping(""); + else if (!isbin && message == "Hello") + conn.send_text("Hello back"); + else if (isbin && message == "Hello bin") + conn.send_binary("Hello back bin"); + }) + .onclose([&](websocket::connection&, const std::string&){ + CROW_LOG_INFO << "Closing websocket"; + }); + + app.validate(); + + auto _ = async(launch::async, + [&] { app.bindaddr(LOCALHOST_ADDRESS).port(45451).run(); }); + app.wait_for_server_start(); + asio::io_service is; + + asio::ip::tcp::socket c(is); + c.connect(asio::ip::tcp::endpoint( + asio::ip::address::from_string(LOCALHOST_ADDRESS), 45451)); + + + char buf[2048]; + + //----------Handshake---------- + { + std::fill_n (buf, 2048, 0); + c.send(asio::buffer(http_message)); + + c.receive(asio::buffer(buf, 2048)); + std::this_thread::sleep_for(std::chrono::milliseconds(5)); + CHECK(connected); + } + //----------Pong---------- + { + std::fill_n (buf, 2048, 0); + char ping_message[2]("\x89"); + + c.send(asio::buffer(ping_message, 2)); + c.receive(asio::buffer(buf, 2048)); + std::this_thread::sleep_for(std::chrono::milliseconds(5)); + CHECK((int)(unsigned char)buf[0] == 0x8A); + } + //----------Ping---------- + { + std::fill_n (buf, 2048, 0); + char not_ping_message[2+6+1]("\x81\x06" + "PINGME"); + + c.send(asio::buffer(not_ping_message, 8)); + c.receive(asio::buffer(buf, 2048)); + std::this_thread::sleep_for(std::chrono::milliseconds(5)); + CHECK((int)(unsigned char)buf[0] == 0x89); + } + //----------Text---------- + { + std::fill_n (buf, 2048, 0); + char text_message[2+5+1]("\x81\x05" + "Hello"); + + c.send(asio::buffer(text_message, 7)); + c.receive(asio::buffer(buf, 2048)); + std::this_thread::sleep_for(std::chrono::milliseconds(5)); + std::string checkstring(std::string(buf).substr(0, 12)); + CHECK(checkstring == "\x81\x0AHello back"); + } + //----------Binary---------- + { + std::fill_n (buf, 2048, 0); + char bin_message[2+9+1]("\x82\x09" + "Hello bin"); + + c.send(asio::buffer(bin_message, 11)); + c.receive(asio::buffer(buf, 2048)); + std::this_thread::sleep_for(std::chrono::milliseconds(5)); + std::string checkstring2(std::string(buf).substr(0, 16)); + CHECK(checkstring2 == "\x82\x0EHello back bin"); + } + //----------Masked Text---------- + { + std::fill_n (buf, 2048, 0); + char text_masked_message[2+4+5+1]("\x81\x85" + "\x67\xc6\x69\x73" + "\x2f\xa3\x05\x1f\x08"); + + c.send(asio::buffer(text_masked_message, 11)); + c.receive(asio::buffer(buf, 2048)); + std::this_thread::sleep_for(std::chrono::milliseconds(5)); + std::string checkstring3(std::string(buf).substr(0, 12)); + CHECK(checkstring3 == "\x81\x0AHello back"); + } + //----------Masked Binary---------- + { + std::fill_n (buf, 2048, 0); + char bin_masked_message[2+4+9+1]("\x82\x89" + "\x67\xc6\x69\x73" + "\x2f\xa3\x05\x1f\x08\xe6\x0b\x1a\x09"); + + c.send(asio::buffer(bin_masked_message, 15)); + c.receive(asio::buffer(buf, 2048)); + std::this_thread::sleep_for(std::chrono::milliseconds(5)); + std::string checkstring4(std::string(buf).substr(0, 16)); + CHECK(checkstring4 == "\x82\x0EHello back bin"); + } + //----------Close---------- + { + std::fill_n (buf, 2048, 0); + char close_message[10]("\x88"); //I do not know why, but the websocket code does not read this unless it's longer than 4 or so bytes + + c.send(asio::buffer(close_message, 10)); + c.receive(asio::buffer(buf, 2048)); + std::this_thread::sleep_for(std::chrono::milliseconds(5)); + CHECK((int)(unsigned char)buf[0] == 0x88); + } + + app.stop(); +}