#include "../test.h"
#include <panda/encode/base64.h>
#define TEST(name) TEST_CASE("deflate-frames: " name, "[deflate-frames]")
string default_handshake () {
return "GET /?encoding=text HTTP/1.1\r\n"
"Host: dev.crazypanda.ru:4680\r\n"
"Connection: Upgrade\r\n"
"Pragma: no-cache\r\n"
"Cache-Control: no-cache\r\n"
"Upgrade: websocket\r\n"
"Origin: http://www.websocket.org\r\n"
"Sec-WebSocket-Version: 13\r\n"
"User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.87 Safari/537.36\r\n"
"Accept-Encoding: gzip, deflate, sdch\r\n"
"Accept-Language: ru-RU,ru;q=0.8,en-US;q=0.6,en;q=0.4\r\n"
"Cookie: _ga=GA1.2.1700804447.1456741171\r\n"
"Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n"
"Sec-WebSocket-Extensions: permessage-deflate\r\n"
"\r\n";
}
struct MyParser : ServerParser {
MyParser (string msg = default_handshake()) {
accept(msg);
accept_response();
if (!established()) throw "should not happen";
}
};
TEST("empty payload frame") {
auto bin = MyParser().start_message(DeflateFlag::YES).send("", IsFinal::YES);
CHECK_BINFRAME(bin).final().rsv1().opcode(Opcode::BINARY).payload(bin.substr(2)).binlen(2+1); // 2 header + 1 bytes empty zlib frame
}
TEST("small server2client frame (rfc7692 'Hello' sample)") {
std::vector<string_view> payload = {"H", "e", "l", "l", "o"}; // must be <= 125
string bin;
SECTION("single mode") {
bin = MyParser().start_message(Opcode::TEXT, DeflateFlag::YES).send(join(payload), IsFinal::YES);
}
SECTION("it mode") {
bin = MyParser().start_message(Opcode::TEXT, DeflateFlag::YES).send(payload.begin(), payload.end(), IsFinal::YES);
}
auto deflate_payload = bin.substr(2);
CHECK(encode::encode_base64(deflate_payload) == "8kjNyckHAA");
CHECK_BINFRAME(bin).final().rsv1().opcode(Opcode::TEXT).payload(deflate_payload).binlen(9);
}
TEST("big (1923 b) server2client frame") {
std::vector<string_view> payload(1923, "0");
string bin;
SECTION("single mode") {
bin = MyParser().start_message(DeflateFlag::YES).send(join(payload), IsFinal::YES);
}
SECTION("it mode") {
bin = MyParser().start_message(DeflateFlag::YES).send(payload.begin(), payload.end(), IsFinal::YES);
}
auto deflate_payload = bin.substr(2);
CHECK(encode::encode_base64(deflate_payload) == "MjAYBaNgFIyCUTAKRsEAAAAA");
CHECK_BINFRAME(bin).final().rsv1().opcode(Opcode::BINARY).payload(deflate_payload).binlen(20);
}
TEST("big (108 kb) server2client frame") {
std::vector<string_view> payload(1024 * 108, "0");
string bin;
SECTION("single mode") {
bin = MyParser().start_message(DeflateFlag::YES).send(join(payload), IsFinal::YES);
}
SECTION("it mode") {
bin = MyParser().start_message(DeflateFlag::YES).send(payload.begin(), payload.end(), IsFinal::YES);
}
auto deflate_payload = bin.substr(4);
CHECK_BINFRAME(bin).final().rsv1().opcode(Opcode::BINARY).payload(deflate_payload).binlen(130);
}
TEST("big (1 mb) server2client frame") {
std::vector<string_view> payload(1024 * 1024, "0");
string bin;
SECTION("single mode") {
bin = MyParser().start_message(DeflateFlag::YES).send(join(payload), IsFinal::YES);
}
SECTION("it mode") {
bin = MyParser().start_message(DeflateFlag::YES).send(payload.begin(), payload.end(), IsFinal::YES);
}
auto deflate_payload = bin.substr(4);
CHECK_BINFRAME(bin).final().rsv1().opcode(Opcode::BINARY).payload(deflate_payload).binlen(1038);
}
TEST("2 messages in a sequence (different due to context takeover)") {
std::vector<string_view> payload(100, "0123456789");
SECTION("as single lines") {
MyParser p;
auto bin1 = p.start_message(DeflateFlag::YES).send(join(payload), IsFinal::YES);
auto bin2 = p.start_message(DeflateFlag::YES).send(join(payload), IsFinal::YES);
CHECK(bin1.length() > bin2.length());
}
SECTION("as iterators") {
MyParser p;
auto bin1 = p.start_message(DeflateFlag::YES).send(payload.begin(), payload.end(), IsFinal::YES);
auto bin2 = p.start_message(DeflateFlag::YES).send(payload.begin(), payload.end(), IsFinal::YES);
CHECK(bin1.length() > bin2.length());
}
}
TEST("no context takeover") {
string handshake = "GET /?encoding=text HTTP/1.1\r\n"
"Host: dev.crazypanda.ru:4680\r\n"
"Connection: Upgrade\r\n"
"Upgrade: websocket\r\n"
"Sec-WebSocket-Version: 13\r\n"
"User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.87 Safari/537.36\r\n"
"Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n"
"Sec-WebSocket-Extensions: permessage-deflate; client_no_context_takeover; server_no_context_takeover\r\n"
"\r\n";
MyParser p(handshake);
auto payload = repeat("0123456789", 100);
auto bin1 = p.start_message(DeflateFlag::YES).send(payload, IsFinal::YES);
auto bin2 = p.start_message(DeflateFlag::YES).send(payload, IsFinal::YES);
CHECK((bin1 == bin2));
}