| // Copyright 2014 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "net/server/web_socket_encoder.h" |
| |
| #include "net/websockets/websocket_deflate_parameters.h" |
| #include "net/websockets/websocket_extension.h" |
| #include "testing/gtest/include/gtest/gtest.h" |
| |
| namespace net { |
| |
| TEST(WebSocketEncoderHandshakeTest, EmptyRequestShouldBeRejected) { |
| WebSocketDeflateParameters params; |
| std::unique_ptr<WebSocketEncoder> server = |
| WebSocketEncoder::CreateServer("", ¶ms); |
| |
| EXPECT_FALSE(server); |
| } |
| |
| TEST(WebSocketEncoderHandshakeTest, |
| CreateServerWithoutClientMaxWindowBitsParameter) { |
| WebSocketDeflateParameters params; |
| std::unique_ptr<WebSocketEncoder> server = |
| WebSocketEncoder::CreateServer("permessage-deflate", ¶ms); |
| |
| ASSERT_TRUE(server); |
| EXPECT_TRUE(server->deflate_enabled()); |
| EXPECT_EQ("permessage-deflate", params.AsExtension().ToString()); |
| } |
| |
| TEST(WebSocketEncoderHandshakeTest, |
| CreateServerWithServerNoContextTakeoverParameter) { |
| WebSocketDeflateParameters params; |
| std::unique_ptr<WebSocketEncoder> server = WebSocketEncoder::CreateServer( |
| "permessage-deflate; server_no_context_takeover", ¶ms); |
| ASSERT_TRUE(server); |
| EXPECT_TRUE(server->deflate_enabled()); |
| EXPECT_EQ("permessage-deflate; server_no_context_takeover", |
| params.AsExtension().ToString()); |
| } |
| |
| TEST(WebSocketEncoderHandshakeTest, FirstExtensionShouldBeChosen) { |
| WebSocketDeflateParameters params; |
| std::unique_ptr<WebSocketEncoder> server = WebSocketEncoder::CreateServer( |
| "permessage-deflate; server_no_context_takeover," |
| "permessage-deflate; server_max_window_bits=15", |
| ¶ms); |
| |
| ASSERT_TRUE(server); |
| EXPECT_TRUE(server->deflate_enabled()); |
| EXPECT_EQ("permessage-deflate; server_no_context_takeover", |
| params.AsExtension().ToString()); |
| } |
| |
| TEST(WebSocketEncoderHandshakeTest, FirstValidExtensionShouldBeChosen) { |
| WebSocketDeflateParameters params; |
| std::unique_ptr<WebSocketEncoder> server = WebSocketEncoder::CreateServer( |
| "permessage-deflate; Xserver_no_context_takeover," |
| "permessage-deflate; server_max_window_bits=15", |
| ¶ms); |
| |
| ASSERT_TRUE(server); |
| EXPECT_TRUE(server->deflate_enabled()); |
| EXPECT_EQ("permessage-deflate; server_max_window_bits=15", |
| params.AsExtension().ToString()); |
| } |
| |
| TEST(WebSocketEncoderHandshakeTest, AllExtensionsAreUnknownOrMalformed) { |
| WebSocketDeflateParameters params; |
| std::unique_ptr<WebSocketEncoder> server = |
| WebSocketEncoder::CreateServer("unknown, permessage-deflate; x", ¶ms); |
| |
| ASSERT_TRUE(server); |
| EXPECT_FALSE(server->deflate_enabled()); |
| } |
| |
| class WebSocketEncoderTest : public testing::Test { |
| public: |
| WebSocketEncoderTest() = default; |
| |
| void SetUp() override { |
| std::string response_extensions; |
| server_ = WebSocketEncoder::CreateServer(); |
| EXPECT_EQ(std::string(), response_extensions); |
| client_ = WebSocketEncoder::CreateClient(""); |
| } |
| |
| protected: |
| std::unique_ptr<WebSocketEncoder> server_; |
| std::unique_ptr<WebSocketEncoder> client_; |
| }; |
| |
| class WebSocketEncoderCompressionTest : public WebSocketEncoderTest { |
| public: |
| WebSocketEncoderCompressionTest() : WebSocketEncoderTest() {} |
| |
| void SetUp() override { |
| WebSocketDeflateParameters params; |
| server_ = WebSocketEncoder::CreateServer( |
| "permessage-deflate; client_max_window_bits", ¶ms); |
| ASSERT_TRUE(server_); |
| EXPECT_TRUE(server_->deflate_enabled()); |
| EXPECT_EQ("permessage-deflate; client_max_window_bits=15", |
| params.AsExtension().ToString()); |
| client_ = WebSocketEncoder::CreateClient(params.AsExtension().ToString()); |
| } |
| }; |
| |
| TEST_F(WebSocketEncoderTest, DeflateDisabledEncoder) { |
| std::unique_ptr<WebSocketEncoder> server = WebSocketEncoder::CreateServer(); |
| std::unique_ptr<WebSocketEncoder> client = WebSocketEncoder::CreateClient(""); |
| |
| ASSERT_TRUE(server); |
| ASSERT_TRUE(client); |
| |
| EXPECT_FALSE(server->deflate_enabled()); |
| EXPECT_FALSE(client->deflate_enabled()); |
| } |
| |
| TEST_F(WebSocketEncoderTest, ClientToServer) { |
| std::string frame("ClientToServer"); |
| int mask = 123456; |
| std::string encoded; |
| int bytes_consumed; |
| std::string decoded; |
| |
| client_->EncodeFrame(frame, mask, &encoded); |
| EXPECT_EQ(WebSocket::FRAME_OK, |
| server_->DecodeFrame(encoded, &bytes_consumed, &decoded)); |
| EXPECT_EQ(frame, decoded); |
| EXPECT_EQ((int)encoded.length(), bytes_consumed); |
| |
| std::string partial = encoded.substr(0, encoded.length() - 2); |
| EXPECT_EQ(WebSocket::FRAME_INCOMPLETE, |
| server_->DecodeFrame(partial, &bytes_consumed, &decoded)); |
| |
| std::string extra = encoded + "more stuff"; |
| EXPECT_EQ(WebSocket::FRAME_OK, |
| server_->DecodeFrame(extra, &bytes_consumed, &decoded)); |
| EXPECT_EQ(frame, decoded); |
| EXPECT_EQ((int)encoded.length(), bytes_consumed); |
| |
| EXPECT_EQ( |
| WebSocket::FRAME_ERROR, |
| server_->DecodeFrame(std::string("abcde"), &bytes_consumed, &decoded)); |
| } |
| |
| TEST_F(WebSocketEncoderTest, ServerToClient) { |
| std::string frame("ServerToClient"); |
| int mask = 0; |
| std::string encoded; |
| int bytes_consumed; |
| std::string decoded; |
| |
| server_->EncodeFrame(frame, mask, &encoded); |
| EXPECT_EQ(WebSocket::FRAME_OK, |
| client_->DecodeFrame(encoded, &bytes_consumed, &decoded)); |
| EXPECT_EQ(frame, decoded); |
| EXPECT_EQ((int)encoded.length(), bytes_consumed); |
| |
| std::string partial = encoded.substr(0, encoded.length() - 2); |
| EXPECT_EQ(WebSocket::FRAME_INCOMPLETE, |
| client_->DecodeFrame(partial, &bytes_consumed, &decoded)); |
| |
| std::string extra = encoded + "more stuff"; |
| EXPECT_EQ(WebSocket::FRAME_OK, |
| client_->DecodeFrame(extra, &bytes_consumed, &decoded)); |
| EXPECT_EQ(frame, decoded); |
| EXPECT_EQ((int)encoded.length(), bytes_consumed); |
| |
| EXPECT_EQ( |
| WebSocket::FRAME_ERROR, |
| client_->DecodeFrame(std::string("abcde"), &bytes_consumed, &decoded)); |
| } |
| |
| TEST_F(WebSocketEncoderCompressionTest, ClientToServer) { |
| std::string frame("CompressionCompressionCompressionCompression"); |
| int mask = 654321; |
| std::string encoded; |
| int bytes_consumed; |
| std::string decoded; |
| |
| client_->EncodeFrame(frame, mask, &encoded); |
| EXPECT_LT(encoded.length(), frame.length()); |
| EXPECT_EQ(WebSocket::FRAME_OK, |
| server_->DecodeFrame(encoded, &bytes_consumed, &decoded)); |
| EXPECT_EQ(frame, decoded); |
| EXPECT_EQ((int)encoded.length(), bytes_consumed); |
| } |
| |
| TEST_F(WebSocketEncoderCompressionTest, ServerToClient) { |
| std::string frame("CompressionCompressionCompressionCompression"); |
| int mask = 0; |
| std::string encoded; |
| int bytes_consumed; |
| std::string decoded; |
| |
| server_->EncodeFrame(frame, mask, &encoded); |
| EXPECT_LT(encoded.length(), frame.length()); |
| EXPECT_EQ(WebSocket::FRAME_OK, |
| client_->DecodeFrame(encoded, &bytes_consumed, &decoded)); |
| EXPECT_EQ(frame, decoded); |
| EXPECT_EQ((int)encoded.length(), bytes_consumed); |
| } |
| |
| TEST_F(WebSocketEncoderCompressionTest, LongFrame) { |
| int length = 1000000; |
| std::string temp; |
| temp.reserve(length); |
| for (int i = 0; i < length; ++i) |
| temp += (char)('a' + (i % 26)); |
| |
| std::string frame; |
| frame.reserve(length); |
| for (int i = 0; i < length; ++i) { |
| int64_t j = i; |
| frame += temp.data()[(j * j) % length]; |
| } |
| |
| int mask = 0; |
| std::string encoded; |
| int bytes_consumed; |
| std::string decoded; |
| |
| server_->EncodeFrame(frame, mask, &encoded); |
| EXPECT_LT(encoded.length(), frame.length()); |
| EXPECT_EQ(WebSocket::FRAME_OK, |
| client_->DecodeFrame(encoded, &bytes_consumed, &decoded)); |
| EXPECT_EQ(frame, decoded); |
| EXPECT_EQ((int)encoded.length(), bytes_consumed); |
| } |
| |
| } // namespace net |