Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(228)

Unified Diff: net/websockets/websocket_handshake_unittest.cc

Issue 1108002: Implement new websocket handshake based on draft-hixie-thewebsocketprotocol-76 (Closed)
Patch Set: fix for review comments Created 10 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « net/websockets/websocket_handshake_draft75_unittest.cc ('k') | net/websockets/websocket_unittest.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: net/websockets/websocket_handshake_unittest.cc
diff --git a/net/websockets/websocket_handshake_unittest.cc b/net/websockets/websocket_handshake_unittest.cc
index beae8059ae8ff673f24a540a7d1f83c171c3ea1c..f68855404aa37fa0a585deb635993fdff88ebb19 100644
--- a/net/websockets/websocket_handshake_unittest.cc
+++ b/net/websockets/websocket_handshake_unittest.cc
@@ -6,6 +6,7 @@
#include <vector>
#include "base/scoped_ptr.h"
+#include "base/string_util.h"
#include "net/websockets/websocket_handshake.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "testing/gmock/include/gmock/gmock.h"
@@ -13,100 +14,216 @@
namespace net {
-TEST(WebSocketHandshakeTest, Connect) {
+class WebSocketHandshakeTest : public testing::Test {
+ public:
+ static void SetUpParameter(WebSocketHandshake* handshake,
+ uint32 number_1, uint32 number_2,
+ const std::string& key_1, const std::string& key_2,
+ const std::string& key_3) {
+ WebSocketHandshake::Parameter* parameter =
+ new WebSocketHandshake::Parameter;
+ parameter->number_1_ = number_1;
+ parameter->number_2_ = number_2;
+ parameter->key_1_ = key_1;
+ parameter->key_2_ = key_2;
+ parameter->key_3_ = key_3;
+ handshake->parameter_.reset(parameter);
+ }
+
+ static void ExpectHeaderEquals(const std::string& expected,
+ const std::string& actual) {
+ std::vector<std::string> expected_lines;
+ Tokenize(expected, "\r\n", &expected_lines);
+ std::vector<std::string> actual_lines;
+ Tokenize(actual, "\r\n", &actual_lines);
+ // Request lines.
+ EXPECT_EQ(expected_lines[0], actual_lines[0]);
+
+ std::vector<std::string> expected_headers;
+ for (size_t i = 1; i < expected_lines.size(); i++) {
+ // Finish at first CRLF CRLF. Note that /key_3/ might include CRLF.
+ if (expected_lines[i] == "")
+ break;
+ expected_headers.push_back(expected_lines[i]);
+ }
+ sort(expected_headers.begin(), expected_headers.end());
+
+ std::vector<std::string> actual_headers;
+ for (size_t i = 1; i < actual_lines.size(); i++) {
+ // Finish at first CRLF CRLF. Note that /key_3/ might include CRLF.
+ if (actual_lines[i] == "")
+ break;
+ actual_headers.push_back(actual_lines[i]);
+ }
+ sort(actual_headers.begin(), actual_headers.end());
+
+ EXPECT_EQ(expected_headers.size(), actual_headers.size())
+ << "expected:" << expected
+ << "\nactual:" << actual;
+ for (size_t i = 0; i < expected_headers.size(); i++) {
+ EXPECT_EQ(expected_headers[i], actual_headers[i]);
+ }
+ }
+
+ static void ExpectHandshakeMessageEquals(const std::string& expected,
+ const std::string& actual) {
+ // Headers.
+ ExpectHeaderEquals(expected, actual);
+ // Compare tailing \r\n\r\n<key3> (4 + 8 bytes).
+ ASSERT_GT(expected.size(), 12U);
+ const char* expected_key3 = expected.data() + expected.size() - 12;
+ EXPECT_GT(actual.size(), 12U);
+ if (actual.size() <= 12U)
+ return;
+ const char* actual_key3 = actual.data() + actual.size() - 12;
+ EXPECT_TRUE(memcmp(expected_key3, actual_key3, 12) == 0)
+ << "expected_key3:" << DumpKey(expected_key3, 12)
+ << ", actual_key3:" << DumpKey(actual_key3, 12);
+ }
+
+ static std::string DumpKey(const char* buf, int len) {
+ std::string s;
+ for (int i = 0; i < len; i++) {
+ if (isprint(buf[i]))
+ s += StringPrintf("%c", buf[i]);
+ else
+ s += StringPrintf("\\x%02x", buf[i]);
+ }
+ return s;
+ }
+
+ static std::string GetResourceName(WebSocketHandshake* handshake) {
+ return handshake->GetResourceName();
+ }
+ static std::string GetHostFieldValue(WebSocketHandshake* handshake) {
+ return handshake->GetHostFieldValue();
+ }
+ static std::string GetOriginFieldValue(WebSocketHandshake* handshake) {
+ return handshake->GetOriginFieldValue();
+ }
+};
+
+
+TEST_F(WebSocketHandshakeTest, Connect) {
const std::string kExpectedClientHandshakeMessage =
"GET /demo HTTP/1.1\r\n"
"Upgrade: WebSocket\r\n"
"Connection: Upgrade\r\n"
"Host: example.com\r\n"
"Origin: http://example.com\r\n"
- "WebSocket-Protocol: sample\r\n"
- "\r\n";
+ "Sec-WebSocket-Protocol: sample\r\n"
+ "Sec-WebSocket-Key1: 388P O503D&ul7 {K%gX( %7 15\r\n"
+ "Sec-WebSocket-Key2: 1 N ?|k UT0or 3o 4 I97N 5-S3O 31\r\n"
+ "\r\n"
+ "\x47\x30\x22\x2D\x5A\x3F\x47\x58";
scoped_ptr<WebSocketHandshake> handshake(
new WebSocketHandshake(GURL("ws://example.com/demo"),
"http://example.com",
"ws://example.com/demo",
"sample"));
+ SetUpParameter(handshake.get(), 777007543U, 114997259U,
+ "388P O503D&ul7 {K%gX( %7 15",
+ "1 N ?|k UT0or 3o 4 I97N 5-S3O 31",
+ std::string("\x47\x30\x22\x2D\x5A\x3F\x47\x58", 8));
EXPECT_EQ(WebSocketHandshake::MODE_INCOMPLETE, handshake->mode());
- EXPECT_EQ(kExpectedClientHandshakeMessage,
- handshake->CreateClientHandshakeMessage());
+ ExpectHandshakeMessageEquals(
+ kExpectedClientHandshakeMessage,
+ handshake->CreateClientHandshakeMessage());
- const char kResponse[] = "HTTP/1.1 101 Web Socket Protocol Handshake\r\n"
+ const char kResponse[] = "HTTP/1.1 101 WebSocket Protocol Handshake\r\n"
"Upgrade: WebSocket\r\n"
"Connection: Upgrade\r\n"
- "WebSocket-Origin: http://example.com\r\n"
- "WebSocket-Location: ws://example.com/demo\r\n"
- "WebSocket-Protocol: sample\r\n"
- "\r\n";
+ "Sec-WebSocket-Origin: http://example.com\r\n"
+ "Sec-WebSocket-Location: ws://example.com/demo\r\n"
+ "Sec-WebSocket-Protocol: sample\r\n"
+ "\r\n"
+ "\x30\x73\x74\x33\x52\x6C\x26\x71\x2D\x32\x5A\x55\x5E\x77\x65\x75";
+ std::vector<std::string> response_lines;
+ SplitStringDontTrim(kResponse, '\n', &response_lines);
EXPECT_EQ(WebSocketHandshake::MODE_INCOMPLETE, handshake->mode());
// too short
EXPECT_EQ(-1, handshake->ReadServerHandshake(kResponse, 16));
EXPECT_EQ(WebSocketHandshake::MODE_INCOMPLETE, handshake->mode());
+
// only status line
+ std::string response = response_lines[0];
EXPECT_EQ(-1, handshake->ReadServerHandshake(
- kResponse,
- WebSocketHandshake::kServerHandshakeHeaderLength));
- EXPECT_EQ(WebSocketHandshake::MODE_NORMAL, handshake->mode());
+ response.data(), response.size()));
+ EXPECT_EQ(WebSocketHandshake::MODE_INCOMPLETE, handshake->mode());
// by upgrade header
+ response += response_lines[1];
EXPECT_EQ(-1, handshake->ReadServerHandshake(
- kResponse,
- WebSocketHandshake::kServerHandshakeHeaderLength +
- WebSocketHandshake::kUpgradeHeaderLength));
- EXPECT_EQ(WebSocketHandshake::MODE_NORMAL, handshake->mode());
+ response.data(), response.size()));
+ EXPECT_EQ(WebSocketHandshake::MODE_INCOMPLETE, handshake->mode());
// by connection header
+ response += response_lines[2];
EXPECT_EQ(-1, handshake->ReadServerHandshake(
- kResponse,
- WebSocketHandshake::kServerHandshakeHeaderLength +
- WebSocketHandshake::kUpgradeHeaderLength +
- WebSocketHandshake::kConnectionHeaderLength));
- EXPECT_EQ(WebSocketHandshake::MODE_NORMAL, handshake->mode());
+ response.data(), response.size()));
+ EXPECT_EQ(WebSocketHandshake::MODE_INCOMPLETE, handshake->mode());
+ response += response_lines[3]; // Sec-WebSocket-Origin
+ response += response_lines[4]; // Sec-WebSocket-Location
+ response += response_lines[5]; // Sec-WebSocket-Protocol
EXPECT_EQ(-1, handshake->ReadServerHandshake(
- kResponse, sizeof(kResponse) - 2));
- EXPECT_EQ(WebSocketHandshake::MODE_NORMAL, handshake->mode());
+ response.data(), response.size()));
+ EXPECT_EQ(WebSocketHandshake::MODE_INCOMPLETE, handshake->mode());
- int handshake_length = strlen(kResponse);
+ response += response_lines[6]; // \r\n
+ EXPECT_EQ(-1, handshake->ReadServerHandshake(
+ response.data(), response.size()));
+ EXPECT_EQ(WebSocketHandshake::MODE_INCOMPLETE, handshake->mode());
+
+ int handshake_length = sizeof(kResponse) - 1; // -1 for terminating \0
EXPECT_EQ(handshake_length, handshake->ReadServerHandshake(
- kResponse, sizeof(kResponse) - 1)); // -1 for terminating \0
+ kResponse, handshake_length)); // -1 for terminating \0
EXPECT_EQ(WebSocketHandshake::MODE_CONNECTED, handshake->mode());
}
-TEST(WebSocketHandshakeTest, ServerSentData) {
+TEST_F(WebSocketHandshakeTest, ServerSentData) {
const std::string kExpectedClientHandshakeMessage =
"GET /demo HTTP/1.1\r\n"
"Upgrade: WebSocket\r\n"
"Connection: Upgrade\r\n"
"Host: example.com\r\n"
"Origin: http://example.com\r\n"
- "WebSocket-Protocol: sample\r\n"
- "\r\n";
+ "Sec-WebSocket-Protocol: sample\r\n"
+ "Sec-WebSocket-Key1: 388P O503D&ul7 {K%gX( %7 15\r\n"
+ "Sec-WebSocket-Key2: 1 N ?|k UT0or 3o 4 I97N 5-S3O 31\r\n"
+ "\r\n"
+ "\x47\x30\x22\x2D\x5A\x3F\x47\x58";
scoped_ptr<WebSocketHandshake> handshake(
new WebSocketHandshake(GURL("ws://example.com/demo"),
"http://example.com",
"ws://example.com/demo",
"sample"));
+ SetUpParameter(handshake.get(), 777007543U, 114997259U,
+ "388P O503D&ul7 {K%gX( %7 15",
+ "1 N ?|k UT0or 3o 4 I97N 5-S3O 31",
+ std::string("\x47\x30\x22\x2D\x5A\x3F\x47\x58", 8));
EXPECT_EQ(WebSocketHandshake::MODE_INCOMPLETE, handshake->mode());
- EXPECT_EQ(kExpectedClientHandshakeMessage,
- handshake->CreateClientHandshakeMessage());
+ ExpectHandshakeMessageEquals(
+ kExpectedClientHandshakeMessage,
+ handshake->CreateClientHandshakeMessage());
- const char kResponse[] ="HTTP/1.1 101 Web Socket Protocol Handshake\r\n"
+ const char kResponse[] = "HTTP/1.1 101 WebSocket Protocol Handshake\r\n"
"Upgrade: WebSocket\r\n"
"Connection: Upgrade\r\n"
- "WebSocket-Origin: http://example.com\r\n"
- "WebSocket-Location: ws://example.com/demo\r\n"
- "WebSocket-Protocol: sample\r\n"
+ "Sec-WebSocket-Origin: http://example.com\r\n"
+ "Sec-WebSocket-Location: ws://example.com/demo\r\n"
+ "Sec-WebSocket-Protocol: sample\r\n"
"\r\n"
+ "\x30\x73\x74\x33\x52\x6C\x26\x71\x2D\x32\x5A\x55\x5E\x77\x65\x75"
"\0Hello\xff";
- int handshake_length = strlen(kResponse);
+ int handshake_length = strlen(kResponse); // key3 doesn't contain \0.
EXPECT_EQ(handshake_length, handshake->ReadServerHandshake(
kResponse, sizeof(kResponse) - 1)); // -1 for terminating \0
EXPECT_EQ(WebSocketHandshake::MODE_CONNECTED, handshake->mode());
}
-TEST(WebSocketHandshakeTest, is_secure_false) {
+TEST_F(WebSocketHandshakeTest, is_secure_false) {
scoped_ptr<WebSocketHandshake> handshake(
new WebSocketHandshake(GURL("ws://example.com/demo"),
"http://example.com",
@@ -115,7 +232,7 @@ TEST(WebSocketHandshakeTest, is_secure_false) {
EXPECT_FALSE(handshake->is_secure());
}
-TEST(WebSocketHandshakeTest, is_secure_true) {
+TEST_F(WebSocketHandshakeTest, is_secure_true) {
// wss:// is secure.
scoped_ptr<WebSocketHandshake> handshake(
new WebSocketHandshake(GURL("wss://example.com/demo"),
@@ -125,80 +242,59 @@ TEST(WebSocketHandshakeTest, is_secure_true) {
EXPECT_TRUE(handshake->is_secure());
}
-TEST(WebSocketHandshakeTest, CreateClientHandshakeMessage_Simple) {
- scoped_ptr<WebSocketHandshake> handshake(
- new WebSocketHandshake(GURL("ws://example.com/demo"),
- "http://example.com",
- "ws://example.com/demo",
- "sample"));
- EXPECT_EQ("GET /demo HTTP/1.1\r\n"
- "Upgrade: WebSocket\r\n"
- "Connection: Upgrade\r\n"
- "Host: example.com\r\n"
- "Origin: http://example.com\r\n"
- "WebSocket-Protocol: sample\r\n"
- "\r\n",
- handshake->CreateClientHandshakeMessage());
-}
-
-TEST(WebSocketHandshakeTest, CreateClientHandshakeMessage_PathAndQuery) {
+TEST_F(WebSocketHandshakeTest, CreateClientHandshakeMessage_ResourceName) {
scoped_ptr<WebSocketHandshake> handshake(
new WebSocketHandshake(GURL("ws://example.com/Test?q=xxx&p=%20"),
"http://example.com",
"ws://example.com/demo",
"sample"));
// Path and query should be preserved as-is.
- EXPECT_THAT(handshake->CreateClientHandshakeMessage(),
- testing::HasSubstr("GET /Test?q=xxx&p=%20 HTTP/1.1\r\n"));
+ EXPECT_EQ("/Test?q=xxx&p=%20", GetResourceName(handshake.get()));
}
-TEST(WebSocketHandshakeTest, CreateClientHandshakeMessage_Host) {
+TEST_F(WebSocketHandshakeTest, CreateClientHandshakeMessage_Host) {
scoped_ptr<WebSocketHandshake> handshake(
new WebSocketHandshake(GURL("ws://Example.Com/demo"),
"http://Example.Com",
"ws://Example.Com/demo",
"sample"));
// Host should be lowercased
- EXPECT_THAT(handshake->CreateClientHandshakeMessage(),
- testing::HasSubstr("Host: example.com\r\n"));
- EXPECT_THAT(handshake->CreateClientHandshakeMessage(),
- testing::HasSubstr("Origin: http://example.com\r\n"));
+ EXPECT_EQ("example.com", GetHostFieldValue(handshake.get()));
+ EXPECT_EQ("http://example.com", GetOriginFieldValue(handshake.get()));
}
-TEST(WebSocketHandshakeTest, CreateClientHandshakeMessage_TrimPort80) {
+TEST_F(WebSocketHandshakeTest, CreateClientHandshakeMessage_TrimPort80) {
scoped_ptr<WebSocketHandshake> handshake(
new WebSocketHandshake(GURL("ws://example.com:80/demo"),
"http://example.com",
"ws://example.com/demo",
"sample"));
// :80 should be trimmed as it's the default port for ws://.
- EXPECT_THAT(handshake->CreateClientHandshakeMessage(),
- testing::HasSubstr("Host: example.com\r\n"));
+ EXPECT_EQ("example.com", GetHostFieldValue(handshake.get()));
}
-TEST(WebSocketHandshakeTest, CreateClientHandshakeMessage_TrimPort443) {
+TEST_F(WebSocketHandshakeTest, CreateClientHandshakeMessage_TrimPort443) {
scoped_ptr<WebSocketHandshake> handshake(
new WebSocketHandshake(GURL("wss://example.com:443/demo"),
"http://example.com",
"wss://example.com/demo",
"sample"));
// :443 should be trimmed as it's the default port for wss://.
- EXPECT_THAT(handshake->CreateClientHandshakeMessage(),
- testing::HasSubstr("Host: example.com\r\n"));
+ EXPECT_EQ("example.com", GetHostFieldValue(handshake.get()));
}
-TEST(WebSocketHandshakeTest, CreateClientHandshakeMessage_NonDefaultPortForWs) {
+TEST_F(WebSocketHandshakeTest,
+ CreateClientHandshakeMessage_NonDefaultPortForWs) {
scoped_ptr<WebSocketHandshake> handshake(
new WebSocketHandshake(GURL("ws://example.com:8080/demo"),
"http://example.com",
"wss://example.com/demo",
"sample"));
// :8080 should be preserved as it's not the default port for ws://.
- EXPECT_THAT(handshake->CreateClientHandshakeMessage(),
- testing::HasSubstr("Host: example.com:8080\r\n"));
+ EXPECT_EQ("example.com:8080", GetHostFieldValue(handshake.get()));
}
-TEST(WebSocketHandshakeTest,
+TEST_F(WebSocketHandshakeTest,
CreateClientHandshakeMessage_NonDefaultPortForWss) {
scoped_ptr<WebSocketHandshake> handshake(
new WebSocketHandshake(GURL("wss://example.com:4443/demo"),
@@ -206,30 +302,27 @@ TEST(WebSocketHandshakeTest,
"wss://example.com/demo",
"sample"));
// :4443 should be preserved as it's not the default port for wss://.
- EXPECT_THAT(handshake->CreateClientHandshakeMessage(),
- testing::HasSubstr("Host: example.com:4443\r\n"));
+ EXPECT_EQ("example.com:4443", GetHostFieldValue(handshake.get()));
}
-TEST(WebSocketHandshakeTest, CreateClientHandshakeMessage_WsBut443) {
+TEST_F(WebSocketHandshakeTest, CreateClientHandshakeMessage_WsBut443) {
scoped_ptr<WebSocketHandshake> handshake(
new WebSocketHandshake(GURL("ws://example.com:443/demo"),
"http://example.com",
"ws://example.com/demo",
"sample"));
// :443 should be preserved as it's not the default port for ws://.
- EXPECT_THAT(handshake->CreateClientHandshakeMessage(),
- testing::HasSubstr("Host: example.com:443\r\n"));
+ EXPECT_EQ("example.com:443", GetHostFieldValue(handshake.get()));
}
-TEST(WebSocketHandshakeTest, CreateClientHandshakeMessage_WssBut80) {
+TEST_F(WebSocketHandshakeTest, CreateClientHandshakeMessage_WssBut80) {
scoped_ptr<WebSocketHandshake> handshake(
new WebSocketHandshake(GURL("wss://example.com:80/demo"),
"http://example.com",
"wss://example.com/demo",
"sample"));
// :80 should be preserved as it's not the default port for wss://.
- EXPECT_THAT(handshake->CreateClientHandshakeMessage(),
- testing::HasSubstr("Host: example.com:80\r\n"));
+ EXPECT_EQ("example.com:80", GetHostFieldValue(handshake.get()));
}
} // namespace net
« no previous file with comments | « net/websockets/websocket_handshake_draft75_unittest.cc ('k') | net/websockets/websocket_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698