| OLD | NEW |
| 1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2013 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "net/websockets/websocket_stream.h" | 5 #include "net/websockets/websocket_stream.h" |
| 6 | 6 |
| 7 #include <algorithm> | 7 #include <algorithm> |
| 8 #include <string> | 8 #include <string> |
| 9 #include <utility> | 9 #include <utility> |
| 10 #include <vector> | 10 #include <vector> |
| (...skipping 182 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 193 public: | 193 public: |
| 194 // Performs a standard connect, with the value of the Sec-WebSocket-Extensions | 194 // Performs a standard connect, with the value of the Sec-WebSocket-Extensions |
| 195 // header in the response set to |extensions_header_value|. Runs the event | 195 // header in the response set to |extensions_header_value|. Runs the event |
| 196 // loop to allow the connect to complete. | 196 // loop to allow the connect to complete. |
| 197 void CreateAndConnectWithExtensions( | 197 void CreateAndConnectWithExtensions( |
| 198 const std::string& extensions_header_value) { | 198 const std::string& extensions_header_value) { |
| 199 CreateAndConnectStandard( | 199 CreateAndConnectStandard( |
| 200 "ws://localhost/testing_path", | 200 "ws://localhost/testing_path", |
| 201 "/testing_path", | 201 "/testing_path", |
| 202 NoSubProtocols(), | 202 NoSubProtocols(), |
| 203 "http://localhost/", | 203 "http://localhost", |
| 204 "", | 204 "", |
| 205 "Sec-WebSocket-Extensions: " + extensions_header_value + "\r\n"); | 205 "Sec-WebSocket-Extensions: " + extensions_header_value + "\r\n"); |
| 206 RunUntilIdle(); | 206 RunUntilIdle(); |
| 207 } | 207 } |
| 208 }; | 208 }; |
| 209 | 209 |
| 210 // Confirm that the basic case works as expected. | 210 // Confirm that the basic case works as expected. |
| 211 TEST_F(WebSocketStreamCreateTest, SimpleSuccess) { | 211 TEST_F(WebSocketStreamCreateTest, SimpleSuccess) { |
| 212 CreateAndConnectStandard( | 212 CreateAndConnectStandard( |
| 213 "ws://localhost/", "/", NoSubProtocols(), "http://localhost/", "", ""); | 213 "ws://localhost/", "/", NoSubProtocols(), "http://localhost", "", ""); |
| 214 EXPECT_FALSE(request_info_); | 214 EXPECT_FALSE(request_info_); |
| 215 EXPECT_FALSE(response_info_); | 215 EXPECT_FALSE(response_info_); |
| 216 RunUntilIdle(); | 216 RunUntilIdle(); |
| 217 EXPECT_FALSE(has_failed()); | 217 EXPECT_FALSE(has_failed()); |
| 218 EXPECT_TRUE(stream_); | 218 EXPECT_TRUE(stream_); |
| 219 EXPECT_TRUE(request_info_); | 219 EXPECT_TRUE(request_info_); |
| 220 EXPECT_TRUE(response_info_); | 220 EXPECT_TRUE(response_info_); |
| 221 } | 221 } |
| 222 | 222 |
| 223 TEST_F(WebSocketStreamCreateTest, HandshakeInfo) { | 223 TEST_F(WebSocketStreamCreateTest, HandshakeInfo) { |
| 224 static const char kResponse[] = | 224 static const char kResponse[] = |
| 225 "HTTP/1.1 101 Switching Protocols\r\n" | 225 "HTTP/1.1 101 Switching Protocols\r\n" |
| 226 "Upgrade: websocket\r\n" | 226 "Upgrade: websocket\r\n" |
| 227 "Connection: Upgrade\r\n" | 227 "Connection: Upgrade\r\n" |
| 228 "Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=\r\n" | 228 "Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=\r\n" |
| 229 "foo: bar, baz\r\n" | 229 "foo: bar, baz\r\n" |
| 230 "hoge: fuga\r\n" | 230 "hoge: fuga\r\n" |
| 231 "hoge: piyo\r\n" | 231 "hoge: piyo\r\n" |
| 232 "\r\n"; | 232 "\r\n"; |
| 233 | 233 |
| 234 CreateAndConnectCustomResponse( | 234 CreateAndConnectCustomResponse( |
| 235 "ws://localhost/", | 235 "ws://localhost/", |
| 236 "/", | 236 "/", |
| 237 NoSubProtocols(), | 237 NoSubProtocols(), |
| 238 "http://localhost/", | 238 "http://localhost:8080", |
| 239 "", | 239 "", |
| 240 kResponse); | 240 kResponse); |
| 241 EXPECT_FALSE(request_info_); | 241 EXPECT_FALSE(request_info_); |
| 242 EXPECT_FALSE(response_info_); | 242 EXPECT_FALSE(response_info_); |
| 243 RunUntilIdle(); | 243 RunUntilIdle(); |
| 244 EXPECT_TRUE(stream_); | 244 EXPECT_TRUE(stream_); |
| 245 ASSERT_TRUE(request_info_); | 245 ASSERT_TRUE(request_info_); |
| 246 ASSERT_TRUE(response_info_); | 246 ASSERT_TRUE(response_info_); |
| 247 std::vector<HeaderKeyValuePair> request_headers = | 247 std::vector<HeaderKeyValuePair> request_headers = |
| 248 ToVector(request_info_->headers); | 248 ToVector(request_info_->headers); |
| 249 // We examine the contents of request_info_ and response_info_ | 249 // We examine the contents of request_info_ and response_info_ |
| 250 // mainly only in this test case. | 250 // mainly only in this test case. |
| 251 EXPECT_EQ(GURL("ws://localhost/"), request_info_->url); | 251 EXPECT_EQ(GURL("ws://localhost/"), request_info_->url); |
| 252 EXPECT_EQ(GURL("ws://localhost/"), response_info_->url); | 252 EXPECT_EQ(GURL("ws://localhost/"), response_info_->url); |
| 253 EXPECT_EQ(101, response_info_->status_code); | 253 EXPECT_EQ(101, response_info_->status_code); |
| 254 EXPECT_EQ("Switching Protocols", response_info_->status_text); | 254 EXPECT_EQ("Switching Protocols", response_info_->status_text); |
| 255 ASSERT_EQ(12u, request_headers.size()); | 255 ASSERT_EQ(12u, request_headers.size()); |
| 256 EXPECT_EQ(HeaderKeyValuePair("Host", "localhost"), request_headers[0]); | 256 EXPECT_EQ(HeaderKeyValuePair("Host", "localhost"), request_headers[0]); |
| 257 EXPECT_EQ(HeaderKeyValuePair("Connection", "Upgrade"), request_headers[1]); | 257 EXPECT_EQ(HeaderKeyValuePair("Connection", "Upgrade"), request_headers[1]); |
| 258 EXPECT_EQ(HeaderKeyValuePair("Pragma", "no-cache"), request_headers[2]); | 258 EXPECT_EQ(HeaderKeyValuePair("Pragma", "no-cache"), request_headers[2]); |
| 259 EXPECT_EQ(HeaderKeyValuePair("Cache-Control", "no-cache"), | 259 EXPECT_EQ(HeaderKeyValuePair("Cache-Control", "no-cache"), |
| 260 request_headers[3]); | 260 request_headers[3]); |
| 261 EXPECT_EQ(HeaderKeyValuePair("Upgrade", "websocket"), request_headers[4]); | 261 EXPECT_EQ(HeaderKeyValuePair("Upgrade", "websocket"), request_headers[4]); |
| 262 EXPECT_EQ(HeaderKeyValuePair("Origin", "http://localhost/"), | 262 EXPECT_EQ(HeaderKeyValuePair("Origin", "http://localhost:8080"), |
| 263 request_headers[5]); | 263 request_headers[5]); |
| 264 EXPECT_EQ(HeaderKeyValuePair("Sec-WebSocket-Version", "13"), | 264 EXPECT_EQ(HeaderKeyValuePair("Sec-WebSocket-Version", "13"), |
| 265 request_headers[6]); | 265 request_headers[6]); |
| 266 EXPECT_EQ(HeaderKeyValuePair("User-Agent", ""), request_headers[7]); | 266 EXPECT_EQ(HeaderKeyValuePair("User-Agent", ""), request_headers[7]); |
| 267 EXPECT_EQ(HeaderKeyValuePair("Accept-Encoding", "gzip,deflate"), | 267 EXPECT_EQ(HeaderKeyValuePair("Accept-Encoding", "gzip,deflate"), |
| 268 request_headers[8]); | 268 request_headers[8]); |
| 269 EXPECT_EQ(HeaderKeyValuePair("Accept-Language", "en-us,fr"), | 269 EXPECT_EQ(HeaderKeyValuePair("Accept-Language", "en-us,fr"), |
| 270 request_headers[9]); | 270 request_headers[9]); |
| 271 EXPECT_EQ("Sec-WebSocket-Key", request_headers[10].first); | 271 EXPECT_EQ("Sec-WebSocket-Key", request_headers[10].first); |
| 272 EXPECT_EQ(HeaderKeyValuePair("Sec-WebSocket-Extensions", | 272 EXPECT_EQ(HeaderKeyValuePair("Sec-WebSocket-Extensions", |
| (...skipping 10 matching lines...) Expand all Loading... |
| 283 EXPECT_EQ("Sec-WebSocket-Accept", response_headers[1].first); | 283 EXPECT_EQ("Sec-WebSocket-Accept", response_headers[1].first); |
| 284 EXPECT_EQ(HeaderKeyValuePair("Upgrade", "websocket"), response_headers[2]); | 284 EXPECT_EQ(HeaderKeyValuePair("Upgrade", "websocket"), response_headers[2]); |
| 285 EXPECT_EQ(HeaderKeyValuePair("foo", "bar, baz"), response_headers[3]); | 285 EXPECT_EQ(HeaderKeyValuePair("foo", "bar, baz"), response_headers[3]); |
| 286 EXPECT_EQ(HeaderKeyValuePair("hoge", "fuga"), response_headers[4]); | 286 EXPECT_EQ(HeaderKeyValuePair("hoge", "fuga"), response_headers[4]); |
| 287 EXPECT_EQ(HeaderKeyValuePair("hoge", "piyo"), response_headers[5]); | 287 EXPECT_EQ(HeaderKeyValuePair("hoge", "piyo"), response_headers[5]); |
| 288 } | 288 } |
| 289 | 289 |
| 290 // Confirm that the stream isn't established until the message loop runs. | 290 // Confirm that the stream isn't established until the message loop runs. |
| 291 TEST_F(WebSocketStreamCreateTest, NeedsToRunLoop) { | 291 TEST_F(WebSocketStreamCreateTest, NeedsToRunLoop) { |
| 292 CreateAndConnectStandard( | 292 CreateAndConnectStandard( |
| 293 "ws://localhost/", "/", NoSubProtocols(), "http://localhost/", "", ""); | 293 "ws://localhost/", "/", NoSubProtocols(), "http://localhost", "", ""); |
| 294 EXPECT_FALSE(has_failed()); | 294 EXPECT_FALSE(has_failed()); |
| 295 EXPECT_FALSE(stream_); | 295 EXPECT_FALSE(stream_); |
| 296 } | 296 } |
| 297 | 297 |
| 298 // Check the path is used. | 298 // Check the path is used. |
| 299 TEST_F(WebSocketStreamCreateTest, PathIsUsed) { | 299 TEST_F(WebSocketStreamCreateTest, PathIsUsed) { |
| 300 CreateAndConnectStandard("ws://localhost/testing_path", | 300 CreateAndConnectStandard("ws://localhost/testing_path", |
| 301 "/testing_path", | 301 "/testing_path", |
| 302 NoSubProtocols(), | 302 NoSubProtocols(), |
| 303 "http://localhost/", | 303 "http://localhost", |
| 304 "", | 304 "", |
| 305 ""); | 305 ""); |
| 306 RunUntilIdle(); | 306 RunUntilIdle(); |
| 307 EXPECT_FALSE(has_failed()); | 307 EXPECT_FALSE(has_failed()); |
| 308 EXPECT_TRUE(stream_); | 308 EXPECT_TRUE(stream_); |
| 309 } | 309 } |
| 310 | 310 |
| 311 // Check that the origin is used. | 311 // Check that the origin is used. |
| 312 TEST_F(WebSocketStreamCreateTest, OriginIsUsed) { | 312 TEST_F(WebSocketStreamCreateTest, OriginIsUsed) { |
| 313 CreateAndConnectStandard("ws://localhost/testing_path", | 313 CreateAndConnectStandard("ws://localhost/testing_path", |
| 314 "/testing_path", | 314 "/testing_path", |
| 315 NoSubProtocols(), | 315 NoSubProtocols(), |
| 316 "http://google.com/", | 316 "http://google.com", |
| 317 "", | 317 "", |
| 318 ""); | 318 ""); |
| 319 RunUntilIdle(); | 319 RunUntilIdle(); |
| 320 EXPECT_FALSE(has_failed()); | 320 EXPECT_FALSE(has_failed()); |
| 321 EXPECT_TRUE(stream_); | 321 EXPECT_TRUE(stream_); |
| 322 } | 322 } |
| 323 | 323 |
| 324 // Check that sub-protocols are sent and parsed. | 324 // Check that sub-protocols are sent and parsed. |
| 325 TEST_F(WebSocketStreamCreateTest, SubProtocolIsUsed) { | 325 TEST_F(WebSocketStreamCreateTest, SubProtocolIsUsed) { |
| 326 std::vector<std::string> sub_protocols; | 326 std::vector<std::string> sub_protocols; |
| 327 sub_protocols.push_back("chatv11.chromium.org"); | 327 sub_protocols.push_back("chatv11.chromium.org"); |
| 328 sub_protocols.push_back("chatv20.chromium.org"); | 328 sub_protocols.push_back("chatv20.chromium.org"); |
| 329 CreateAndConnectStandard("ws://localhost/testing_path", | 329 CreateAndConnectStandard("ws://localhost/testing_path", |
| 330 "/testing_path", | 330 "/testing_path", |
| 331 sub_protocols, | 331 sub_protocols, |
| 332 "http://google.com/", | 332 "http://google.com", |
| 333 "Sec-WebSocket-Protocol: chatv11.chromium.org, " | 333 "Sec-WebSocket-Protocol: chatv11.chromium.org, " |
| 334 "chatv20.chromium.org\r\n", | 334 "chatv20.chromium.org\r\n", |
| 335 "Sec-WebSocket-Protocol: chatv20.chromium.org\r\n"); | 335 "Sec-WebSocket-Protocol: chatv20.chromium.org\r\n"); |
| 336 RunUntilIdle(); | 336 RunUntilIdle(); |
| 337 EXPECT_TRUE(stream_); | 337 EXPECT_TRUE(stream_); |
| 338 EXPECT_FALSE(has_failed()); | 338 EXPECT_FALSE(has_failed()); |
| 339 EXPECT_EQ("chatv20.chromium.org", stream_->GetSubProtocol()); | 339 EXPECT_EQ("chatv20.chromium.org", stream_->GetSubProtocol()); |
| 340 } | 340 } |
| 341 | 341 |
| 342 // Unsolicited sub-protocols are rejected. | 342 // Unsolicited sub-protocols are rejected. |
| 343 TEST_F(WebSocketStreamCreateTest, UnsolicitedSubProtocol) { | 343 TEST_F(WebSocketStreamCreateTest, UnsolicitedSubProtocol) { |
| 344 CreateAndConnectStandard("ws://localhost/testing_path", | 344 CreateAndConnectStandard("ws://localhost/testing_path", |
| 345 "/testing_path", | 345 "/testing_path", |
| 346 NoSubProtocols(), | 346 NoSubProtocols(), |
| 347 "http://google.com/", | 347 "http://google.com", |
| 348 "", | 348 "", |
| 349 "Sec-WebSocket-Protocol: chatv20.chromium.org\r\n"); | 349 "Sec-WebSocket-Protocol: chatv20.chromium.org\r\n"); |
| 350 RunUntilIdle(); | 350 RunUntilIdle(); |
| 351 EXPECT_FALSE(stream_); | 351 EXPECT_FALSE(stream_); |
| 352 EXPECT_TRUE(has_failed()); | 352 EXPECT_TRUE(has_failed()); |
| 353 EXPECT_EQ("Error during WebSocket handshake: " | 353 EXPECT_EQ("Error during WebSocket handshake: " |
| 354 "Response must not include 'Sec-WebSocket-Protocol' header " | 354 "Response must not include 'Sec-WebSocket-Protocol' header " |
| 355 "if not present in request: chatv20.chromium.org", | 355 "if not present in request: chatv20.chromium.org", |
| 356 failure_message()); | 356 failure_message()); |
| 357 } | 357 } |
| 358 | 358 |
| 359 // Missing sub-protocol response is rejected. | 359 // Missing sub-protocol response is rejected. |
| 360 TEST_F(WebSocketStreamCreateTest, UnacceptedSubProtocol) { | 360 TEST_F(WebSocketStreamCreateTest, UnacceptedSubProtocol) { |
| 361 std::vector<std::string> sub_protocols; | 361 std::vector<std::string> sub_protocols; |
| 362 sub_protocols.push_back("chat.example.com"); | 362 sub_protocols.push_back("chat.example.com"); |
| 363 CreateAndConnectStandard("ws://localhost/testing_path", | 363 CreateAndConnectStandard("ws://localhost/testing_path", |
| 364 "/testing_path", | 364 "/testing_path", |
| 365 sub_protocols, | 365 sub_protocols, |
| 366 "http://localhost/", | 366 "http://localhost", |
| 367 "Sec-WebSocket-Protocol: chat.example.com\r\n", | 367 "Sec-WebSocket-Protocol: chat.example.com\r\n", |
| 368 ""); | 368 ""); |
| 369 RunUntilIdle(); | 369 RunUntilIdle(); |
| 370 EXPECT_FALSE(stream_); | 370 EXPECT_FALSE(stream_); |
| 371 EXPECT_TRUE(has_failed()); | 371 EXPECT_TRUE(has_failed()); |
| 372 EXPECT_EQ("Error during WebSocket handshake: " | 372 EXPECT_EQ("Error during WebSocket handshake: " |
| 373 "Sent non-empty 'Sec-WebSocket-Protocol' header " | 373 "Sent non-empty 'Sec-WebSocket-Protocol' header " |
| 374 "but no response was received", | 374 "but no response was received", |
| 375 failure_message()); | 375 failure_message()); |
| 376 } | 376 } |
| 377 | 377 |
| 378 // Only one sub-protocol can be accepted. | 378 // Only one sub-protocol can be accepted. |
| 379 TEST_F(WebSocketStreamCreateTest, MultipleSubProtocolsInResponse) { | 379 TEST_F(WebSocketStreamCreateTest, MultipleSubProtocolsInResponse) { |
| 380 std::vector<std::string> sub_protocols; | 380 std::vector<std::string> sub_protocols; |
| 381 sub_protocols.push_back("chatv11.chromium.org"); | 381 sub_protocols.push_back("chatv11.chromium.org"); |
| 382 sub_protocols.push_back("chatv20.chromium.org"); | 382 sub_protocols.push_back("chatv20.chromium.org"); |
| 383 CreateAndConnectStandard("ws://localhost/testing_path", | 383 CreateAndConnectStandard("ws://localhost/testing_path", |
| 384 "/testing_path", | 384 "/testing_path", |
| 385 sub_protocols, | 385 sub_protocols, |
| 386 "http://google.com/", | 386 "http://google.com", |
| 387 "Sec-WebSocket-Protocol: chatv11.chromium.org, " | 387 "Sec-WebSocket-Protocol: chatv11.chromium.org, " |
| 388 "chatv20.chromium.org\r\n", | 388 "chatv20.chromium.org\r\n", |
| 389 "Sec-WebSocket-Protocol: chatv11.chromium.org, " | 389 "Sec-WebSocket-Protocol: chatv11.chromium.org, " |
| 390 "chatv20.chromium.org\r\n"); | 390 "chatv20.chromium.org\r\n"); |
| 391 RunUntilIdle(); | 391 RunUntilIdle(); |
| 392 EXPECT_FALSE(stream_); | 392 EXPECT_FALSE(stream_); |
| 393 EXPECT_TRUE(has_failed()); | 393 EXPECT_TRUE(has_failed()); |
| 394 EXPECT_EQ("Error during WebSocket handshake: " | 394 EXPECT_EQ("Error during WebSocket handshake: " |
| 395 "'Sec-WebSocket-Protocol' header must not appear " | 395 "'Sec-WebSocket-Protocol' header must not appear " |
| 396 "more than once in a response", | 396 "more than once in a response", |
| 397 failure_message()); | 397 failure_message()); |
| 398 } | 398 } |
| 399 | 399 |
| 400 // Unmatched sub-protocol should be rejected. | 400 // Unmatched sub-protocol should be rejected. |
| 401 TEST_F(WebSocketStreamCreateTest, UnmatchedSubProtocolInResponse) { | 401 TEST_F(WebSocketStreamCreateTest, UnmatchedSubProtocolInResponse) { |
| 402 std::vector<std::string> sub_protocols; | 402 std::vector<std::string> sub_protocols; |
| 403 sub_protocols.push_back("chatv11.chromium.org"); | 403 sub_protocols.push_back("chatv11.chromium.org"); |
| 404 sub_protocols.push_back("chatv20.chromium.org"); | 404 sub_protocols.push_back("chatv20.chromium.org"); |
| 405 CreateAndConnectStandard("ws://localhost/testing_path", | 405 CreateAndConnectStandard("ws://localhost/testing_path", |
| 406 "/testing_path", | 406 "/testing_path", |
| 407 sub_protocols, | 407 sub_protocols, |
| 408 "http://google.com/", | 408 "http://google.com", |
| 409 "Sec-WebSocket-Protocol: chatv11.chromium.org, " | 409 "Sec-WebSocket-Protocol: chatv11.chromium.org, " |
| 410 "chatv20.chromium.org\r\n", | 410 "chatv20.chromium.org\r\n", |
| 411 "Sec-WebSocket-Protocol: chatv21.chromium.org\r\n"); | 411 "Sec-WebSocket-Protocol: chatv21.chromium.org\r\n"); |
| 412 RunUntilIdle(); | 412 RunUntilIdle(); |
| 413 EXPECT_FALSE(stream_); | 413 EXPECT_FALSE(stream_); |
| 414 EXPECT_TRUE(has_failed()); | 414 EXPECT_TRUE(has_failed()); |
| 415 EXPECT_EQ("Error during WebSocket handshake: " | 415 EXPECT_EQ("Error during WebSocket handshake: " |
| 416 "'Sec-WebSocket-Protocol' header value 'chatv21.chromium.org' " | 416 "'Sec-WebSocket-Protocol' header value 'chatv21.chromium.org' " |
| 417 "in response does not match any of sent values", | 417 "in response does not match any of sent values", |
| 418 failure_message()); | 418 failure_message()); |
| (...skipping 16 matching lines...) Expand all Loading... |
| 435 EXPECT_FALSE(has_failed()); | 435 EXPECT_FALSE(has_failed()); |
| 436 } | 436 } |
| 437 | 437 |
| 438 // Verify that incoming messages are actually decompressed with | 438 // Verify that incoming messages are actually decompressed with |
| 439 // permessage-deflate enabled. | 439 // permessage-deflate enabled. |
| 440 TEST_F(WebSocketStreamCreateExtensionTest, PerMessageDeflateInflates) { | 440 TEST_F(WebSocketStreamCreateExtensionTest, PerMessageDeflateInflates) { |
| 441 CreateAndConnectCustomResponse( | 441 CreateAndConnectCustomResponse( |
| 442 "ws://localhost/testing_path", | 442 "ws://localhost/testing_path", |
| 443 "/testing_path", | 443 "/testing_path", |
| 444 NoSubProtocols(), | 444 NoSubProtocols(), |
| 445 "http://localhost/", | 445 "http://localhost", |
| 446 "", | 446 "", |
| 447 WebSocketStandardResponse( | 447 WebSocketStandardResponse( |
| 448 "Sec-WebSocket-Extensions: permessage-deflate\r\n") + | 448 "Sec-WebSocket-Extensions: permessage-deflate\r\n") + |
| 449 std::string( | 449 std::string( |
| 450 "\xc1\x07" // WebSocket header (FIN + RSV1, Text payload 7 bytes) | 450 "\xc1\x07" // WebSocket header (FIN + RSV1, Text payload 7 bytes) |
| 451 "\xf2\x48\xcd\xc9\xc9\x07\x00", // "Hello" DEFLATE compressed | 451 "\xf2\x48\xcd\xc9\xc9\x07\x00", // "Hello" DEFLATE compressed |
| 452 9)); | 452 9)); |
| 453 RunUntilIdle(); | 453 RunUntilIdle(); |
| 454 | 454 |
| 455 ASSERT_TRUE(stream_); | 455 ASSERT_TRUE(stream_); |
| (...skipping 164 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 620 // TODO(ricea): Check that WebSocketDeflateStream is initialised with the | 620 // TODO(ricea): Check that WebSocketDeflateStream is initialised with the |
| 621 // arguments from the server. This is difficult because the data written to the | 621 // arguments from the server. This is difficult because the data written to the |
| 622 // socket is randomly masked. | 622 // socket is randomly masked. |
| 623 | 623 |
| 624 // Additional Sec-WebSocket-Accept headers should be rejected. | 624 // Additional Sec-WebSocket-Accept headers should be rejected. |
| 625 TEST_F(WebSocketStreamCreateTest, DoubleAccept) { | 625 TEST_F(WebSocketStreamCreateTest, DoubleAccept) { |
| 626 CreateAndConnectStandard( | 626 CreateAndConnectStandard( |
| 627 "ws://localhost/", | 627 "ws://localhost/", |
| 628 "/", | 628 "/", |
| 629 NoSubProtocols(), | 629 NoSubProtocols(), |
| 630 "http://localhost/", | 630 "http://localhost", |
| 631 "", | 631 "", |
| 632 "Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=\r\n"); | 632 "Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=\r\n"); |
| 633 RunUntilIdle(); | 633 RunUntilIdle(); |
| 634 EXPECT_FALSE(stream_); | 634 EXPECT_FALSE(stream_); |
| 635 EXPECT_TRUE(has_failed()); | 635 EXPECT_TRUE(has_failed()); |
| 636 EXPECT_EQ("Error during WebSocket handshake: " | 636 EXPECT_EQ("Error during WebSocket handshake: " |
| 637 "'Sec-WebSocket-Accept' header must not appear " | 637 "'Sec-WebSocket-Accept' header must not appear " |
| 638 "more than once in a response", | 638 "more than once in a response", |
| 639 failure_message()); | 639 failure_message()); |
| 640 } | 640 } |
| 641 | 641 |
| 642 // Response code 200 must be rejected. | 642 // Response code 200 must be rejected. |
| 643 TEST_F(WebSocketStreamCreateTest, InvalidStatusCode) { | 643 TEST_F(WebSocketStreamCreateTest, InvalidStatusCode) { |
| 644 static const char kInvalidStatusCodeResponse[] = | 644 static const char kInvalidStatusCodeResponse[] = |
| 645 "HTTP/1.1 200 OK\r\n" | 645 "HTTP/1.1 200 OK\r\n" |
| 646 "Upgrade: websocket\r\n" | 646 "Upgrade: websocket\r\n" |
| 647 "Connection: Upgrade\r\n" | 647 "Connection: Upgrade\r\n" |
| 648 "Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=\r\n" | 648 "Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=\r\n" |
| 649 "\r\n"; | 649 "\r\n"; |
| 650 CreateAndConnectCustomResponse("ws://localhost/", | 650 CreateAndConnectCustomResponse("ws://localhost/", |
| 651 "/", | 651 "/", |
| 652 NoSubProtocols(), | 652 NoSubProtocols(), |
| 653 "http://localhost/", | 653 "http://localhost", |
| 654 "", | 654 "", |
| 655 kInvalidStatusCodeResponse); | 655 kInvalidStatusCodeResponse); |
| 656 RunUntilIdle(); | 656 RunUntilIdle(); |
| 657 EXPECT_TRUE(has_failed()); | 657 EXPECT_TRUE(has_failed()); |
| 658 EXPECT_EQ("Error during WebSocket handshake: Unexpected response code: 200", | 658 EXPECT_EQ("Error during WebSocket handshake: Unexpected response code: 200", |
| 659 failure_message()); | 659 failure_message()); |
| 660 } | 660 } |
| 661 | 661 |
| 662 // Redirects are not followed (according to the WHATWG WebSocket API, which | 662 // Redirects are not followed (according to the WHATWG WebSocket API, which |
| 663 // overrides RFC6455 for browser applications). | 663 // overrides RFC6455 for browser applications). |
| 664 TEST_F(WebSocketStreamCreateTest, RedirectsRejected) { | 664 TEST_F(WebSocketStreamCreateTest, RedirectsRejected) { |
| 665 static const char kRedirectResponse[] = | 665 static const char kRedirectResponse[] = |
| 666 "HTTP/1.1 302 Moved Temporarily\r\n" | 666 "HTTP/1.1 302 Moved Temporarily\r\n" |
| 667 "Content-Type: text/html\r\n" | 667 "Content-Type: text/html\r\n" |
| 668 "Content-Length: 34\r\n" | 668 "Content-Length: 34\r\n" |
| 669 "Connection: keep-alive\r\n" | 669 "Connection: keep-alive\r\n" |
| 670 "Location: ws://localhost/other\r\n" | 670 "Location: ws://localhost/other\r\n" |
| 671 "\r\n" | 671 "\r\n" |
| 672 "<title>Moved</title><h1>Moved</h1>"; | 672 "<title>Moved</title><h1>Moved</h1>"; |
| 673 CreateAndConnectCustomResponse("ws://localhost/", | 673 CreateAndConnectCustomResponse("ws://localhost/", |
| 674 "/", | 674 "/", |
| 675 NoSubProtocols(), | 675 NoSubProtocols(), |
| 676 "http://localhost/", | 676 "http://localhost", |
| 677 "", | 677 "", |
| 678 kRedirectResponse); | 678 kRedirectResponse); |
| 679 RunUntilIdle(); | 679 RunUntilIdle(); |
| 680 EXPECT_TRUE(has_failed()); | 680 EXPECT_TRUE(has_failed()); |
| 681 EXPECT_EQ("Error during WebSocket handshake: Unexpected response code: 302", | 681 EXPECT_EQ("Error during WebSocket handshake: Unexpected response code: 302", |
| 682 failure_message()); | 682 failure_message()); |
| 683 } | 683 } |
| 684 | 684 |
| 685 // Malformed responses should be rejected. HttpStreamParser will accept just | 685 // Malformed responses should be rejected. HttpStreamParser will accept just |
| 686 // about any garbage in the middle of the headers. To make it give up, the junk | 686 // about any garbage in the middle of the headers. To make it give up, the junk |
| 687 // has to be at the start of the response. Even then, it just gets treated as an | 687 // has to be at the start of the response. Even then, it just gets treated as an |
| 688 // HTTP/0.9 response. | 688 // HTTP/0.9 response. |
| 689 TEST_F(WebSocketStreamCreateTest, MalformedResponse) { | 689 TEST_F(WebSocketStreamCreateTest, MalformedResponse) { |
| 690 static const char kMalformedResponse[] = | 690 static const char kMalformedResponse[] = |
| 691 "220 mx.google.com ESMTP\r\n" | 691 "220 mx.google.com ESMTP\r\n" |
| 692 "HTTP/1.1 101 OK\r\n" | 692 "HTTP/1.1 101 OK\r\n" |
| 693 "Upgrade: websocket\r\n" | 693 "Upgrade: websocket\r\n" |
| 694 "Connection: Upgrade\r\n" | 694 "Connection: Upgrade\r\n" |
| 695 "Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=\r\n" | 695 "Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=\r\n" |
| 696 "\r\n"; | 696 "\r\n"; |
| 697 CreateAndConnectCustomResponse("ws://localhost/", | 697 CreateAndConnectCustomResponse("ws://localhost/", |
| 698 "/", | 698 "/", |
| 699 NoSubProtocols(), | 699 NoSubProtocols(), |
| 700 "http://localhost/", | 700 "http://localhost", |
| 701 "", | 701 "", |
| 702 kMalformedResponse); | 702 kMalformedResponse); |
| 703 RunUntilIdle(); | 703 RunUntilIdle(); |
| 704 EXPECT_TRUE(has_failed()); | 704 EXPECT_TRUE(has_failed()); |
| 705 EXPECT_EQ("Error during WebSocket handshake: Unexpected response code: 200", | 705 EXPECT_EQ("Error during WebSocket handshake: Unexpected response code: 200", |
| 706 failure_message()); | 706 failure_message()); |
| 707 } | 707 } |
| 708 | 708 |
| 709 // Upgrade header must be present. | 709 // Upgrade header must be present. |
| 710 TEST_F(WebSocketStreamCreateTest, MissingUpgradeHeader) { | 710 TEST_F(WebSocketStreamCreateTest, MissingUpgradeHeader) { |
| 711 static const char kMissingUpgradeResponse[] = | 711 static const char kMissingUpgradeResponse[] = |
| 712 "HTTP/1.1 101 Switching Protocols\r\n" | 712 "HTTP/1.1 101 Switching Protocols\r\n" |
| 713 "Connection: Upgrade\r\n" | 713 "Connection: Upgrade\r\n" |
| 714 "Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=\r\n" | 714 "Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=\r\n" |
| 715 "\r\n"; | 715 "\r\n"; |
| 716 CreateAndConnectCustomResponse("ws://localhost/", | 716 CreateAndConnectCustomResponse("ws://localhost/", |
| 717 "/", | 717 "/", |
| 718 NoSubProtocols(), | 718 NoSubProtocols(), |
| 719 "http://localhost/", | 719 "http://localhost", |
| 720 "", | 720 "", |
| 721 kMissingUpgradeResponse); | 721 kMissingUpgradeResponse); |
| 722 RunUntilIdle(); | 722 RunUntilIdle(); |
| 723 EXPECT_TRUE(has_failed()); | 723 EXPECT_TRUE(has_failed()); |
| 724 EXPECT_EQ("Error during WebSocket handshake: 'Upgrade' header is missing", | 724 EXPECT_EQ("Error during WebSocket handshake: 'Upgrade' header is missing", |
| 725 failure_message()); | 725 failure_message()); |
| 726 } | 726 } |
| 727 | 727 |
| 728 // There must only be one upgrade header. | 728 // There must only be one upgrade header. |
| 729 TEST_F(WebSocketStreamCreateTest, DoubleUpgradeHeader) { | 729 TEST_F(WebSocketStreamCreateTest, DoubleUpgradeHeader) { |
| 730 CreateAndConnectStandard( | 730 CreateAndConnectStandard( |
| 731 "ws://localhost/", | 731 "ws://localhost/", |
| 732 "/", | 732 "/", |
| 733 NoSubProtocols(), | 733 NoSubProtocols(), |
| 734 "http://localhost/", | 734 "http://localhost", |
| 735 "", "Upgrade: HTTP/2.0\r\n"); | 735 "", "Upgrade: HTTP/2.0\r\n"); |
| 736 RunUntilIdle(); | 736 RunUntilIdle(); |
| 737 EXPECT_TRUE(has_failed()); | 737 EXPECT_TRUE(has_failed()); |
| 738 EXPECT_EQ("Error during WebSocket handshake: " | 738 EXPECT_EQ("Error during WebSocket handshake: " |
| 739 "'Upgrade' header must not appear more than once in a response", | 739 "'Upgrade' header must not appear more than once in a response", |
| 740 failure_message()); | 740 failure_message()); |
| 741 } | 741 } |
| 742 | 742 |
| 743 // There must only be one correct upgrade header. | 743 // There must only be one correct upgrade header. |
| 744 TEST_F(WebSocketStreamCreateTest, IncorrectUpgradeHeader) { | 744 TEST_F(WebSocketStreamCreateTest, IncorrectUpgradeHeader) { |
| 745 static const char kMissingUpgradeResponse[] = | 745 static const char kMissingUpgradeResponse[] = |
| 746 "HTTP/1.1 101 Switching Protocols\r\n" | 746 "HTTP/1.1 101 Switching Protocols\r\n" |
| 747 "Connection: Upgrade\r\n" | 747 "Connection: Upgrade\r\n" |
| 748 "Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=\r\n" | 748 "Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=\r\n" |
| 749 "Upgrade: hogefuga\r\n" | 749 "Upgrade: hogefuga\r\n" |
| 750 "\r\n"; | 750 "\r\n"; |
| 751 CreateAndConnectCustomResponse("ws://localhost/", | 751 CreateAndConnectCustomResponse("ws://localhost/", |
| 752 "/", | 752 "/", |
| 753 NoSubProtocols(), | 753 NoSubProtocols(), |
| 754 "http://localhost/", | 754 "http://localhost", |
| 755 "", | 755 "", |
| 756 kMissingUpgradeResponse); | 756 kMissingUpgradeResponse); |
| 757 RunUntilIdle(); | 757 RunUntilIdle(); |
| 758 EXPECT_TRUE(has_failed()); | 758 EXPECT_TRUE(has_failed()); |
| 759 EXPECT_EQ("Error during WebSocket handshake: " | 759 EXPECT_EQ("Error during WebSocket handshake: " |
| 760 "'Upgrade' header value is not 'WebSocket': hogefuga", | 760 "'Upgrade' header value is not 'WebSocket': hogefuga", |
| 761 failure_message()); | 761 failure_message()); |
| 762 } | 762 } |
| 763 | 763 |
| 764 // Connection header must be present. | 764 // Connection header must be present. |
| 765 TEST_F(WebSocketStreamCreateTest, MissingConnectionHeader) { | 765 TEST_F(WebSocketStreamCreateTest, MissingConnectionHeader) { |
| 766 static const char kMissingConnectionResponse[] = | 766 static const char kMissingConnectionResponse[] = |
| 767 "HTTP/1.1 101 Switching Protocols\r\n" | 767 "HTTP/1.1 101 Switching Protocols\r\n" |
| 768 "Upgrade: websocket\r\n" | 768 "Upgrade: websocket\r\n" |
| 769 "Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=\r\n" | 769 "Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=\r\n" |
| 770 "\r\n"; | 770 "\r\n"; |
| 771 CreateAndConnectCustomResponse("ws://localhost/", | 771 CreateAndConnectCustomResponse("ws://localhost/", |
| 772 "/", | 772 "/", |
| 773 NoSubProtocols(), | 773 NoSubProtocols(), |
| 774 "http://localhost/", | 774 "http://localhost", |
| 775 "", | 775 "", |
| 776 kMissingConnectionResponse); | 776 kMissingConnectionResponse); |
| 777 RunUntilIdle(); | 777 RunUntilIdle(); |
| 778 EXPECT_TRUE(has_failed()); | 778 EXPECT_TRUE(has_failed()); |
| 779 EXPECT_EQ("Error during WebSocket handshake: " | 779 EXPECT_EQ("Error during WebSocket handshake: " |
| 780 "'Connection' header is missing", | 780 "'Connection' header is missing", |
| 781 failure_message()); | 781 failure_message()); |
| 782 } | 782 } |
| 783 | 783 |
| 784 // Connection header must contain "Upgrade". | 784 // Connection header must contain "Upgrade". |
| 785 TEST_F(WebSocketStreamCreateTest, IncorrectConnectionHeader) { | 785 TEST_F(WebSocketStreamCreateTest, IncorrectConnectionHeader) { |
| 786 static const char kMissingConnectionResponse[] = | 786 static const char kMissingConnectionResponse[] = |
| 787 "HTTP/1.1 101 Switching Protocols\r\n" | 787 "HTTP/1.1 101 Switching Protocols\r\n" |
| 788 "Upgrade: websocket\r\n" | 788 "Upgrade: websocket\r\n" |
| 789 "Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=\r\n" | 789 "Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=\r\n" |
| 790 "Connection: hogefuga\r\n" | 790 "Connection: hogefuga\r\n" |
| 791 "\r\n"; | 791 "\r\n"; |
| 792 CreateAndConnectCustomResponse("ws://localhost/", | 792 CreateAndConnectCustomResponse("ws://localhost/", |
| 793 "/", | 793 "/", |
| 794 NoSubProtocols(), | 794 NoSubProtocols(), |
| 795 "http://localhost/", | 795 "http://localhost", |
| 796 "", | 796 "", |
| 797 kMissingConnectionResponse); | 797 kMissingConnectionResponse); |
| 798 RunUntilIdle(); | 798 RunUntilIdle(); |
| 799 EXPECT_TRUE(has_failed()); | 799 EXPECT_TRUE(has_failed()); |
| 800 EXPECT_EQ("Error during WebSocket handshake: " | 800 EXPECT_EQ("Error during WebSocket handshake: " |
| 801 "'Connection' header value must contain 'Upgrade'", | 801 "'Connection' header value must contain 'Upgrade'", |
| 802 failure_message()); | 802 failure_message()); |
| 803 } | 803 } |
| 804 | 804 |
| 805 // Connection header is permitted to contain other tokens. | 805 // Connection header is permitted to contain other tokens. |
| 806 TEST_F(WebSocketStreamCreateTest, AdditionalTokenInConnectionHeader) { | 806 TEST_F(WebSocketStreamCreateTest, AdditionalTokenInConnectionHeader) { |
| 807 static const char kAdditionalConnectionTokenResponse[] = | 807 static const char kAdditionalConnectionTokenResponse[] = |
| 808 "HTTP/1.1 101 Switching Protocols\r\n" | 808 "HTTP/1.1 101 Switching Protocols\r\n" |
| 809 "Upgrade: websocket\r\n" | 809 "Upgrade: websocket\r\n" |
| 810 "Connection: Upgrade, Keep-Alive\r\n" | 810 "Connection: Upgrade, Keep-Alive\r\n" |
| 811 "Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=\r\n" | 811 "Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=\r\n" |
| 812 "\r\n"; | 812 "\r\n"; |
| 813 CreateAndConnectCustomResponse("ws://localhost/", | 813 CreateAndConnectCustomResponse("ws://localhost/", |
| 814 "/", | 814 "/", |
| 815 NoSubProtocols(), | 815 NoSubProtocols(), |
| 816 "http://localhost/", | 816 "http://localhost", |
| 817 "", | 817 "", |
| 818 kAdditionalConnectionTokenResponse); | 818 kAdditionalConnectionTokenResponse); |
| 819 RunUntilIdle(); | 819 RunUntilIdle(); |
| 820 EXPECT_FALSE(has_failed()); | 820 EXPECT_FALSE(has_failed()); |
| 821 EXPECT_TRUE(stream_); | 821 EXPECT_TRUE(stream_); |
| 822 } | 822 } |
| 823 | 823 |
| 824 // Sec-WebSocket-Accept header must be present. | 824 // Sec-WebSocket-Accept header must be present. |
| 825 TEST_F(WebSocketStreamCreateTest, MissingSecWebSocketAccept) { | 825 TEST_F(WebSocketStreamCreateTest, MissingSecWebSocketAccept) { |
| 826 static const char kMissingAcceptResponse[] = | 826 static const char kMissingAcceptResponse[] = |
| 827 "HTTP/1.1 101 Switching Protocols\r\n" | 827 "HTTP/1.1 101 Switching Protocols\r\n" |
| 828 "Upgrade: websocket\r\n" | 828 "Upgrade: websocket\r\n" |
| 829 "Connection: Upgrade\r\n" | 829 "Connection: Upgrade\r\n" |
| 830 "\r\n"; | 830 "\r\n"; |
| 831 CreateAndConnectCustomResponse("ws://localhost/", | 831 CreateAndConnectCustomResponse("ws://localhost/", |
| 832 "/", | 832 "/", |
| 833 NoSubProtocols(), | 833 NoSubProtocols(), |
| 834 "http://localhost/", | 834 "http://localhost", |
| 835 "", | 835 "", |
| 836 kMissingAcceptResponse); | 836 kMissingAcceptResponse); |
| 837 RunUntilIdle(); | 837 RunUntilIdle(); |
| 838 EXPECT_TRUE(has_failed()); | 838 EXPECT_TRUE(has_failed()); |
| 839 EXPECT_EQ("Error during WebSocket handshake: " | 839 EXPECT_EQ("Error during WebSocket handshake: " |
| 840 "'Sec-WebSocket-Accept' header is missing", | 840 "'Sec-WebSocket-Accept' header is missing", |
| 841 failure_message()); | 841 failure_message()); |
| 842 } | 842 } |
| 843 | 843 |
| 844 // Sec-WebSocket-Accept header must match the key that was sent. | 844 // Sec-WebSocket-Accept header must match the key that was sent. |
| 845 TEST_F(WebSocketStreamCreateTest, WrongSecWebSocketAccept) { | 845 TEST_F(WebSocketStreamCreateTest, WrongSecWebSocketAccept) { |
| 846 static const char kIncorrectAcceptResponse[] = | 846 static const char kIncorrectAcceptResponse[] = |
| 847 "HTTP/1.1 101 Switching Protocols\r\n" | 847 "HTTP/1.1 101 Switching Protocols\r\n" |
| 848 "Upgrade: websocket\r\n" | 848 "Upgrade: websocket\r\n" |
| 849 "Connection: Upgrade\r\n" | 849 "Connection: Upgrade\r\n" |
| 850 "Sec-WebSocket-Accept: x/byyPZ2tOFvJCGkkugcKvqhhPk=\r\n" | 850 "Sec-WebSocket-Accept: x/byyPZ2tOFvJCGkkugcKvqhhPk=\r\n" |
| 851 "\r\n"; | 851 "\r\n"; |
| 852 CreateAndConnectCustomResponse("ws://localhost/", | 852 CreateAndConnectCustomResponse("ws://localhost/", |
| 853 "/", | 853 "/", |
| 854 NoSubProtocols(), | 854 NoSubProtocols(), |
| 855 "http://localhost/", | 855 "http://localhost", |
| 856 "", | 856 "", |
| 857 kIncorrectAcceptResponse); | 857 kIncorrectAcceptResponse); |
| 858 RunUntilIdle(); | 858 RunUntilIdle(); |
| 859 EXPECT_TRUE(has_failed()); | 859 EXPECT_TRUE(has_failed()); |
| 860 EXPECT_EQ("Error during WebSocket handshake: " | 860 EXPECT_EQ("Error during WebSocket handshake: " |
| 861 "Incorrect 'Sec-WebSocket-Accept' header value", | 861 "Incorrect 'Sec-WebSocket-Accept' header value", |
| 862 failure_message()); | 862 failure_message()); |
| 863 } | 863 } |
| 864 | 864 |
| 865 // Cancellation works. | 865 // Cancellation works. |
| 866 TEST_F(WebSocketStreamCreateTest, Cancellation) { | 866 TEST_F(WebSocketStreamCreateTest, Cancellation) { |
| 867 CreateAndConnectStandard( | 867 CreateAndConnectStandard( |
| 868 "ws://localhost/", "/", NoSubProtocols(), "http://localhost/", "", ""); | 868 "ws://localhost/", "/", NoSubProtocols(), "http://localhost", "", ""); |
| 869 stream_request_.reset(); | 869 stream_request_.reset(); |
| 870 RunUntilIdle(); | 870 RunUntilIdle(); |
| 871 EXPECT_FALSE(has_failed()); | 871 EXPECT_FALSE(has_failed()); |
| 872 EXPECT_FALSE(stream_); | 872 EXPECT_FALSE(stream_); |
| 873 EXPECT_FALSE(request_info_); | 873 EXPECT_FALSE(request_info_); |
| 874 EXPECT_FALSE(response_info_); | 874 EXPECT_FALSE(response_info_); |
| 875 } | 875 } |
| 876 | 876 |
| 877 // Connect failure must look just like negotiation failure. | 877 // Connect failure must look just like negotiation failure. |
| 878 TEST_F(WebSocketStreamCreateTest, ConnectionFailure) { | 878 TEST_F(WebSocketStreamCreateTest, ConnectionFailure) { |
| 879 scoped_ptr<DeterministicSocketData> socket_data( | 879 scoped_ptr<DeterministicSocketData> socket_data( |
| 880 new DeterministicSocketData(NULL, 0, NULL, 0)); | 880 new DeterministicSocketData(NULL, 0, NULL, 0)); |
| 881 socket_data->set_connect_data( | 881 socket_data->set_connect_data( |
| 882 MockConnect(SYNCHRONOUS, ERR_CONNECTION_REFUSED)); | 882 MockConnect(SYNCHRONOUS, ERR_CONNECTION_REFUSED)); |
| 883 CreateAndConnectRawExpectations("ws://localhost/", NoSubProtocols(), | 883 CreateAndConnectRawExpectations("ws://localhost/", NoSubProtocols(), |
| 884 "http://localhost/", socket_data.Pass()); | 884 "http://localhost", socket_data.Pass()); |
| 885 RunUntilIdle(); | 885 RunUntilIdle(); |
| 886 EXPECT_TRUE(has_failed()); | 886 EXPECT_TRUE(has_failed()); |
| 887 EXPECT_EQ("Error in connection establishment: net::ERR_CONNECTION_REFUSED", | 887 EXPECT_EQ("Error in connection establishment: net::ERR_CONNECTION_REFUSED", |
| 888 failure_message()); | 888 failure_message()); |
| 889 EXPECT_FALSE(request_info_); | 889 EXPECT_FALSE(request_info_); |
| 890 EXPECT_FALSE(response_info_); | 890 EXPECT_FALSE(response_info_); |
| 891 } | 891 } |
| 892 | 892 |
| 893 // Connect timeout must look just like any other failure. | 893 // Connect timeout must look just like any other failure. |
| 894 TEST_F(WebSocketStreamCreateTest, ConnectionTimeout) { | 894 TEST_F(WebSocketStreamCreateTest, ConnectionTimeout) { |
| 895 scoped_ptr<DeterministicSocketData> socket_data( | 895 scoped_ptr<DeterministicSocketData> socket_data( |
| 896 new DeterministicSocketData(NULL, 0, NULL, 0)); | 896 new DeterministicSocketData(NULL, 0, NULL, 0)); |
| 897 socket_data->set_connect_data( | 897 socket_data->set_connect_data( |
| 898 MockConnect(ASYNC, ERR_CONNECTION_TIMED_OUT)); | 898 MockConnect(ASYNC, ERR_CONNECTION_TIMED_OUT)); |
| 899 CreateAndConnectRawExpectations("ws://localhost/", NoSubProtocols(), | 899 CreateAndConnectRawExpectations("ws://localhost/", NoSubProtocols(), |
| 900 "http://localhost/", socket_data.Pass()); | 900 "http://localhost/", socket_data.Pass()); |
| 901 RunUntilIdle(); | 901 RunUntilIdle(); |
| 902 EXPECT_TRUE(has_failed()); | 902 EXPECT_TRUE(has_failed()); |
| 903 EXPECT_EQ("Error in connection establishment: net::ERR_CONNECTION_TIMED_OUT", | 903 EXPECT_EQ("Error in connection establishment: net::ERR_CONNECTION_TIMED_OUT", |
| 904 failure_message()); | 904 failure_message()); |
| 905 } | 905 } |
| 906 | 906 |
| 907 // Cancellation during connect works. | 907 // Cancellation during connect works. |
| 908 TEST_F(WebSocketStreamCreateTest, CancellationDuringConnect) { | 908 TEST_F(WebSocketStreamCreateTest, CancellationDuringConnect) { |
| 909 scoped_ptr<DeterministicSocketData> socket_data( | 909 scoped_ptr<DeterministicSocketData> socket_data( |
| 910 new DeterministicSocketData(NULL, 0, NULL, 0)); | 910 new DeterministicSocketData(NULL, 0, NULL, 0)); |
| 911 socket_data->set_connect_data(MockConnect(SYNCHRONOUS, ERR_IO_PENDING)); | 911 socket_data->set_connect_data(MockConnect(SYNCHRONOUS, ERR_IO_PENDING)); |
| 912 CreateAndConnectRawExpectations("ws://localhost/", | 912 CreateAndConnectRawExpectations("ws://localhost/", |
| 913 NoSubProtocols(), | 913 NoSubProtocols(), |
| 914 "http://localhost/", | 914 "http://localhost", |
| 915 socket_data.Pass()); | 915 socket_data.Pass()); |
| 916 stream_request_.reset(); | 916 stream_request_.reset(); |
| 917 RunUntilIdle(); | 917 RunUntilIdle(); |
| 918 EXPECT_FALSE(has_failed()); | 918 EXPECT_FALSE(has_failed()); |
| 919 EXPECT_FALSE(stream_); | 919 EXPECT_FALSE(stream_); |
| 920 } | 920 } |
| 921 | 921 |
| 922 // Cancellation during write of the request headers works. | 922 // Cancellation during write of the request headers works. |
| 923 TEST_F(WebSocketStreamCreateTest, CancellationDuringWrite) { | 923 TEST_F(WebSocketStreamCreateTest, CancellationDuringWrite) { |
| 924 // We seem to need at least two operations in order to use SetStop(). | 924 // We seem to need at least two operations in order to use SetStop(). |
| 925 MockWrite writes[] = {MockWrite(ASYNC, 0, "GET / HTTP/"), | 925 MockWrite writes[] = {MockWrite(ASYNC, 0, "GET / HTTP/"), |
| 926 MockWrite(ASYNC, 1, "1.1\r\n")}; | 926 MockWrite(ASYNC, 1, "1.1\r\n")}; |
| 927 // We keep a copy of the pointer so that we can call RunFor() on it later. | 927 // We keep a copy of the pointer so that we can call RunFor() on it later. |
| 928 DeterministicSocketData* socket_data( | 928 DeterministicSocketData* socket_data( |
| 929 new DeterministicSocketData(NULL, 0, writes, arraysize(writes))); | 929 new DeterministicSocketData(NULL, 0, writes, arraysize(writes))); |
| 930 socket_data->set_connect_data(MockConnect(SYNCHRONOUS, OK)); | 930 socket_data->set_connect_data(MockConnect(SYNCHRONOUS, OK)); |
| 931 socket_data->SetStop(1); | 931 socket_data->SetStop(1); |
| 932 CreateAndConnectRawExpectations("ws://localhost/", | 932 CreateAndConnectRawExpectations("ws://localhost/", |
| 933 NoSubProtocols(), | 933 NoSubProtocols(), |
| 934 "http://localhost/", | 934 "http://localhost", |
| 935 make_scoped_ptr(socket_data)); | 935 make_scoped_ptr(socket_data)); |
| 936 socket_data->Run(); | 936 socket_data->Run(); |
| 937 stream_request_.reset(); | 937 stream_request_.reset(); |
| 938 RunUntilIdle(); | 938 RunUntilIdle(); |
| 939 EXPECT_FALSE(has_failed()); | 939 EXPECT_FALSE(has_failed()); |
| 940 EXPECT_FALSE(stream_); | 940 EXPECT_FALSE(stream_); |
| 941 EXPECT_TRUE(request_info_); | 941 EXPECT_TRUE(request_info_); |
| 942 EXPECT_FALSE(response_info_); | 942 EXPECT_FALSE(response_info_); |
| 943 } | 943 } |
| 944 | 944 |
| 945 // Cancellation during read of the response headers works. | 945 // Cancellation during read of the response headers works. |
| 946 TEST_F(WebSocketStreamCreateTest, CancellationDuringRead) { | 946 TEST_F(WebSocketStreamCreateTest, CancellationDuringRead) { |
| 947 std::string request = WebSocketStandardRequest("/", "http://localhost/", ""); | 947 std::string request = WebSocketStandardRequest("/", "http://localhost", ""); |
| 948 MockWrite writes[] = {MockWrite(ASYNC, 0, request.c_str())}; | 948 MockWrite writes[] = {MockWrite(ASYNC, 0, request.c_str())}; |
| 949 MockRead reads[] = { | 949 MockRead reads[] = { |
| 950 MockRead(ASYNC, 1, "HTTP/1.1 101 Switching Protocols\r\nUpgr"), | 950 MockRead(ASYNC, 1, "HTTP/1.1 101 Switching Protocols\r\nUpgr"), |
| 951 }; | 951 }; |
| 952 DeterministicSocketData* socket_data(new DeterministicSocketData( | 952 DeterministicSocketData* socket_data(new DeterministicSocketData( |
| 953 reads, arraysize(reads), writes, arraysize(writes))); | 953 reads, arraysize(reads), writes, arraysize(writes))); |
| 954 socket_data->set_connect_data(MockConnect(SYNCHRONOUS, OK)); | 954 socket_data->set_connect_data(MockConnect(SYNCHRONOUS, OK)); |
| 955 socket_data->SetStop(1); | 955 socket_data->SetStop(1); |
| 956 CreateAndConnectRawExpectations("ws://localhost/", | 956 CreateAndConnectRawExpectations("ws://localhost/", |
| 957 NoSubProtocols(), | 957 NoSubProtocols(), |
| 958 "http://localhost/", | 958 "http://localhost", |
| 959 make_scoped_ptr(socket_data)); | 959 make_scoped_ptr(socket_data)); |
| 960 socket_data->Run(); | 960 socket_data->Run(); |
| 961 stream_request_.reset(); | 961 stream_request_.reset(); |
| 962 RunUntilIdle(); | 962 RunUntilIdle(); |
| 963 EXPECT_FALSE(has_failed()); | 963 EXPECT_FALSE(has_failed()); |
| 964 EXPECT_FALSE(stream_); | 964 EXPECT_FALSE(stream_); |
| 965 EXPECT_TRUE(request_info_); | 965 EXPECT_TRUE(request_info_); |
| 966 EXPECT_FALSE(response_info_); | 966 EXPECT_FALSE(response_info_); |
| 967 } | 967 } |
| 968 | 968 |
| 969 // Over-size response headers (> 256KB) should not cause a crash. This is a | 969 // Over-size response headers (> 256KB) should not cause a crash. This is a |
| 970 // regression test for crbug.com/339456. It is based on the layout test | 970 // regression test for crbug.com/339456. It is based on the layout test |
| 971 // "cookie-flood.html". | 971 // "cookie-flood.html". |
| 972 TEST_F(WebSocketStreamCreateTest, VeryLargeResponseHeaders) { | 972 TEST_F(WebSocketStreamCreateTest, VeryLargeResponseHeaders) { |
| 973 std::string set_cookie_headers; | 973 std::string set_cookie_headers; |
| 974 set_cookie_headers.reserve(45 * 10000); | 974 set_cookie_headers.reserve(45 * 10000); |
| 975 for (int i = 0; i < 10000; ++i) { | 975 for (int i = 0; i < 10000; ++i) { |
| 976 set_cookie_headers += | 976 set_cookie_headers += |
| 977 base::StringPrintf("Set-Cookie: WK-websocket-test-flood-%d=1\r\n", i); | 977 base::StringPrintf("Set-Cookie: WK-websocket-test-flood-%d=1\r\n", i); |
| 978 } | 978 } |
| 979 CreateAndConnectStandard("ws://localhost/", "/", NoSubProtocols(), | 979 CreateAndConnectStandard("ws://localhost/", "/", NoSubProtocols(), |
| 980 "http://localhost/", "", set_cookie_headers); | 980 "http://localhost", "", set_cookie_headers); |
| 981 RunUntilIdle(); | 981 RunUntilIdle(); |
| 982 EXPECT_TRUE(has_failed()); | 982 EXPECT_TRUE(has_failed()); |
| 983 EXPECT_FALSE(response_info_); | 983 EXPECT_FALSE(response_info_); |
| 984 } | 984 } |
| 985 | 985 |
| 986 // If the remote host closes the connection without sending headers, we should | 986 // If the remote host closes the connection without sending headers, we should |
| 987 // log the console message "Connection closed before receiving a handshake | 987 // log the console message "Connection closed before receiving a handshake |
| 988 // response". | 988 // response". |
| 989 TEST_F(WebSocketStreamCreateTest, NoResponse) { | 989 TEST_F(WebSocketStreamCreateTest, NoResponse) { |
| 990 std::string request = WebSocketStandardRequest("/", "http://localhost/", ""); | 990 std::string request = WebSocketStandardRequest("/", "http://localhost", ""); |
| 991 MockWrite writes[] = {MockWrite(ASYNC, request.data(), request.size(), 0)}; | 991 MockWrite writes[] = {MockWrite(ASYNC, request.data(), request.size(), 0)}; |
| 992 MockRead reads[] = {MockRead(ASYNC, 0, 1)}; | 992 MockRead reads[] = {MockRead(ASYNC, 0, 1)}; |
| 993 DeterministicSocketData* socket_data(new DeterministicSocketData( | 993 DeterministicSocketData* socket_data(new DeterministicSocketData( |
| 994 reads, arraysize(reads), writes, arraysize(writes))); | 994 reads, arraysize(reads), writes, arraysize(writes))); |
| 995 socket_data->set_connect_data(MockConnect(SYNCHRONOUS, OK)); | 995 socket_data->set_connect_data(MockConnect(SYNCHRONOUS, OK)); |
| 996 CreateAndConnectRawExpectations("ws://localhost/", | 996 CreateAndConnectRawExpectations("ws://localhost/", |
| 997 NoSubProtocols(), | 997 NoSubProtocols(), |
| 998 "http://localhost/", | 998 "http://localhost", |
| 999 make_scoped_ptr(socket_data)); | 999 make_scoped_ptr(socket_data)); |
| 1000 socket_data->RunFor(2); | 1000 socket_data->RunFor(2); |
| 1001 EXPECT_TRUE(has_failed()); | 1001 EXPECT_TRUE(has_failed()); |
| 1002 EXPECT_FALSE(stream_); | 1002 EXPECT_FALSE(stream_); |
| 1003 EXPECT_FALSE(response_info_); | 1003 EXPECT_FALSE(response_info_); |
| 1004 EXPECT_EQ("Connection closed before receiving a handshake response", | 1004 EXPECT_EQ("Connection closed before receiving a handshake response", |
| 1005 failure_message()); | 1005 failure_message()); |
| 1006 } | 1006 } |
| 1007 | 1007 |
| 1008 } // namespace | 1008 } // namespace |
| 1009 } // namespace net | 1009 } // namespace net |
| OLD | NEW |