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

Side by Side Diff: net/websockets/websocket_stream_test.cc

Issue 143913003: Add construction of WebSocketDeflateStream (Closed) Base URL: http://git.chromium.org/chromium/src.git@master
Patch Set: Rebase and add DCHECK() for extension params. Created 6 years, 10 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 unified diff | Download patch
OLDNEW
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>
11 11
12 #include "base/memory/scoped_vector.h"
12 #include "base/run_loop.h" 13 #include "base/run_loop.h"
13 #include "net/base/net_errors.h" 14 #include "net/base/net_errors.h"
14 #include "net/http/http_request_headers.h" 15 #include "net/http/http_request_headers.h"
15 #include "net/http/http_response_headers.h" 16 #include "net/http/http_response_headers.h"
16 #include "net/socket/client_socket_handle.h" 17 #include "net/socket/client_socket_handle.h"
17 #include "net/socket/socket_test_util.h" 18 #include "net/socket/socket_test_util.h"
18 #include "net/url_request/url_request_test_util.h" 19 #include "net/url_request/url_request_test_util.h"
19 #include "net/websockets/websocket_basic_handshake_stream.h" 20 #include "net/websockets/websocket_basic_handshake_stream.h"
21 #include "net/websockets/websocket_frame.h"
20 #include "net/websockets/websocket_handshake_request_info.h" 22 #include "net/websockets/websocket_handshake_request_info.h"
21 #include "net/websockets/websocket_handshake_response_info.h" 23 #include "net/websockets/websocket_handshake_response_info.h"
22 #include "net/websockets/websocket_handshake_stream_create_helper.h" 24 #include "net/websockets/websocket_handshake_stream_create_helper.h"
23 #include "net/websockets/websocket_test_util.h" 25 #include "net/websockets/websocket_test_util.h"
24 #include "testing/gtest/include/gtest/gtest.h" 26 #include "testing/gtest/include/gtest/gtest.h"
25 #include "url/gurl.h" 27 #include "url/gurl.h"
26 28
27 namespace net { 29 namespace net {
28 namespace { 30 namespace {
29 31
(...skipping 147 matching lines...) Expand 10 before | Expand all | Expand 10 after
177 scoped_ptr<WebSocketStreamRequest> stream_request_; 179 scoped_ptr<WebSocketStreamRequest> stream_request_;
178 // Only set if the connection succeeded. 180 // Only set if the connection succeeded.
179 scoped_ptr<WebSocketStream> stream_; 181 scoped_ptr<WebSocketStream> stream_;
180 // Only set if the connection failed. 182 // Only set if the connection failed.
181 std::string failure_message_; 183 std::string failure_message_;
182 bool has_failed_; 184 bool has_failed_;
183 scoped_ptr<WebSocketHandshakeRequestInfo> request_info_; 185 scoped_ptr<WebSocketHandshakeRequestInfo> request_info_;
184 scoped_ptr<WebSocketHandshakeResponseInfo> response_info_; 186 scoped_ptr<WebSocketHandshakeResponseInfo> response_info_;
185 }; 187 };
186 188
189 // There are enough tests of the Sec-WebSocket-Extensions header that they
190 // deserve their own test fixture.
191 class WebSocketStreamCreateExtensionTest : public WebSocketStreamCreateTest {
192 public:
193 // Performs a standard connect, with the value of the Sec-WebSocket-Extensions
194 // header in the response set to |extensions_header_value|. Runs the event
195 // loop to allow the connect to complete.
196 void CreateAndConnectWithExtensions(
197 const std::string& extensions_header_value) {
198 CreateAndConnectStandard(
199 "ws://localhost/testing_path",
200 "/testing_path",
201 NoSubProtocols(),
202 "http://localhost/",
203 "",
204 "Sec-WebSocket-Extensions: " + extensions_header_value + "\r\n");
205 RunUntilIdle();
206 }
207 };
208
187 // Confirm that the basic case works as expected. 209 // Confirm that the basic case works as expected.
188 TEST_F(WebSocketStreamCreateTest, SimpleSuccess) { 210 TEST_F(WebSocketStreamCreateTest, SimpleSuccess) {
189 CreateAndConnectStandard( 211 CreateAndConnectStandard(
190 "ws://localhost/", "/", NoSubProtocols(), "http://localhost/", "", ""); 212 "ws://localhost/", "/", NoSubProtocols(), "http://localhost/", "", "");
191 EXPECT_FALSE(request_info_); 213 EXPECT_FALSE(request_info_);
192 EXPECT_FALSE(response_info_); 214 EXPECT_FALSE(response_info_);
193 RunUntilIdle(); 215 RunUntilIdle();
194 EXPECT_FALSE(has_failed()); 216 EXPECT_FALSE(has_failed());
195 EXPECT_TRUE(stream_); 217 EXPECT_TRUE(stream_);
196 EXPECT_TRUE(request_info_); 218 EXPECT_TRUE(request_info_);
(...skipping 25 matching lines...) Expand all
222 ASSERT_TRUE(request_info_); 244 ASSERT_TRUE(request_info_);
223 ASSERT_TRUE(response_info_); 245 ASSERT_TRUE(response_info_);
224 std::vector<HeaderKeyValuePair> request_headers = 246 std::vector<HeaderKeyValuePair> request_headers =
225 ToVector(request_info_->headers); 247 ToVector(request_info_->headers);
226 // We examine the contents of request_info_ and response_info_ 248 // We examine the contents of request_info_ and response_info_
227 // mainly only in this test case. 249 // mainly only in this test case.
228 EXPECT_EQ(GURL("ws://localhost/"), request_info_->url); 250 EXPECT_EQ(GURL("ws://localhost/"), request_info_->url);
229 EXPECT_EQ(GURL("ws://localhost/"), response_info_->url); 251 EXPECT_EQ(GURL("ws://localhost/"), response_info_->url);
230 EXPECT_EQ(101, response_info_->status_code); 252 EXPECT_EQ(101, response_info_->status_code);
231 EXPECT_EQ("Switching Protocols", response_info_->status_text); 253 EXPECT_EQ("Switching Protocols", response_info_->status_text);
232 EXPECT_EQ(9u, request_headers.size()); 254 EXPECT_EQ(10u, request_headers.size());
233 EXPECT_EQ(HeaderKeyValuePair("Host", "localhost"), request_headers[0]); 255 EXPECT_EQ(HeaderKeyValuePair("Host", "localhost"), request_headers[0]);
234 EXPECT_EQ(HeaderKeyValuePair("Connection", "Upgrade"), request_headers[1]); 256 EXPECT_EQ(HeaderKeyValuePair("Connection", "Upgrade"), request_headers[1]);
235 EXPECT_EQ(HeaderKeyValuePair("Upgrade", "websocket"), request_headers[2]); 257 EXPECT_EQ(HeaderKeyValuePair("Upgrade", "websocket"), request_headers[2]);
236 EXPECT_EQ(HeaderKeyValuePair("Origin", "http://localhost/"), 258 EXPECT_EQ(HeaderKeyValuePair("Origin", "http://localhost/"),
237 request_headers[3]); 259 request_headers[3]);
238 EXPECT_EQ(HeaderKeyValuePair("Sec-WebSocket-Version", "13"), 260 EXPECT_EQ(HeaderKeyValuePair("Sec-WebSocket-Version", "13"),
239 request_headers[4]); 261 request_headers[4]);
240 EXPECT_EQ(HeaderKeyValuePair("User-Agent", ""), request_headers[5]); 262 EXPECT_EQ(HeaderKeyValuePair("User-Agent", ""), request_headers[5]);
241 EXPECT_EQ(HeaderKeyValuePair("Accept-Encoding", "gzip,deflate"), 263 EXPECT_EQ(HeaderKeyValuePair("Accept-Encoding", "gzip,deflate"),
242 request_headers[6]); 264 request_headers[6]);
243 EXPECT_EQ(HeaderKeyValuePair("Accept-Language", "en-us,fr"), 265 EXPECT_EQ(HeaderKeyValuePair("Accept-Language", "en-us,fr"),
244 request_headers[7]); 266 request_headers[7]);
245 EXPECT_EQ("Sec-WebSocket-Key", request_headers[8].first); 267 EXPECT_EQ("Sec-WebSocket-Key", request_headers[8].first);
268 EXPECT_EQ(HeaderKeyValuePair("Sec-WebSocket-Extensions",
269 "permessage-deflate; client_max_window_bits"),
270 request_headers[9]);
246 271
247 std::vector<HeaderKeyValuePair> response_headers = 272 std::vector<HeaderKeyValuePair> response_headers =
248 ToVector(*response_info_->headers); 273 ToVector(*response_info_->headers);
249 ASSERT_EQ(6u, response_headers.size()); 274 ASSERT_EQ(6u, response_headers.size());
250 // Sort the headers for ease of verification. 275 // Sort the headers for ease of verification.
251 std::sort(response_headers.begin(), response_headers.end()); 276 std::sort(response_headers.begin(), response_headers.end());
252 277
253 EXPECT_EQ(HeaderKeyValuePair("Connection", "Upgrade"), response_headers[0]); 278 EXPECT_EQ(HeaderKeyValuePair("Connection", "Upgrade"), response_headers[0]);
254 EXPECT_EQ("Sec-WebSocket-Accept", response_headers[1].first); 279 EXPECT_EQ("Sec-WebSocket-Accept", response_headers[1].first);
255 EXPECT_EQ(HeaderKeyValuePair("Upgrade", "websocket"), response_headers[2]); 280 EXPECT_EQ(HeaderKeyValuePair("Upgrade", "websocket"), response_headers[2]);
(...skipping 126 matching lines...) Expand 10 before | Expand all | Expand 10 after
382 "Sec-WebSocket-Protocol: chatv21.chromium.org\r\n"); 407 "Sec-WebSocket-Protocol: chatv21.chromium.org\r\n");
383 RunUntilIdle(); 408 RunUntilIdle();
384 EXPECT_FALSE(stream_); 409 EXPECT_FALSE(stream_);
385 EXPECT_TRUE(has_failed()); 410 EXPECT_TRUE(has_failed());
386 EXPECT_EQ("Error during WebSocket handshake: " 411 EXPECT_EQ("Error during WebSocket handshake: "
387 "'Sec-WebSocket-Protocol' header value 'chatv21.chromium.org' " 412 "'Sec-WebSocket-Protocol' header value 'chatv21.chromium.org' "
388 "in response does not match any of sent values", 413 "in response does not match any of sent values",
389 failure_message()); 414 failure_message());
390 } 415 }
391 416
417 // permessage-deflate extension basic success case.
418 TEST_F(WebSocketStreamCreateExtensionTest, PerMessageDeflateSuccess) {
419 CreateAndConnectWithExtensions("permessage-deflate");
420 EXPECT_TRUE(stream_);
421 EXPECT_FALSE(has_failed());
422 }
423
424 // permessage-deflate extensions success with all parameters.
425 TEST_F(WebSocketStreamCreateExtensionTest, PerMessageDeflateParamsSuccess) {
426 CreateAndConnectWithExtensions(
427 "permessage-deflate; client_no_context_takeover; "
428 "server_max_window_bits=11; client_max_window_bits=13; "
429 "server_no_context_takeover");
430 EXPECT_TRUE(stream_);
431 EXPECT_FALSE(has_failed());
432 }
433
434 // Verify that incoming messages are actually decompressed with
435 // permessage-deflate enabled.
436 TEST_F(WebSocketStreamCreateExtensionTest, PerMessageDeflateInflates) {
437 CreateAndConnectCustomResponse(
438 "ws://localhost/testing_path",
439 "/testing_path",
440 NoSubProtocols(),
441 "http://localhost/",
442 "",
443 WebSocketStandardResponse(
444 "Sec-WebSocket-Extensions: permessage-deflate\r\n") +
445 std::string(
446 "\xc1\x07" // WebSocket header (FIN + RSV1, Text payload 7 bytes)
447 "\xf2\x48\xcd\xc9\xc9\x07\x00", // "Hello" DEFLATE compressed
448 9));
449 RunUntilIdle();
450
451 ASSERT_TRUE(stream_);
452 ScopedVector<WebSocketFrame> frames;
453 CompletionCallback callback;
454 ASSERT_EQ(OK, stream_->ReadFrames(&frames, callback));
455 ASSERT_EQ(1U, frames.size());
456 ASSERT_EQ(5U, frames[0]->header.payload_length);
457 EXPECT_EQ("Hello", std::string(frames[0]->data->data(), 5));
458 }
459
392 // Unknown extension in the response is rejected 460 // Unknown extension in the response is rejected
393 TEST_F(WebSocketStreamCreateTest, UnknownExtension) { 461 TEST_F(WebSocketStreamCreateExtensionTest, UnknownExtension) {
394 CreateAndConnectStandard("ws://localhost/testing_path", 462 CreateAndConnectWithExtensions("x-unknown-extension");
395 "/testing_path",
396 NoSubProtocols(),
397 "http://localhost/",
398 "",
399 "Sec-WebSocket-Extensions: x-unknown-extension\r\n");
400 RunUntilIdle();
401 EXPECT_FALSE(stream_); 463 EXPECT_FALSE(stream_);
402 EXPECT_TRUE(has_failed()); 464 EXPECT_TRUE(has_failed());
403 EXPECT_EQ("Error during WebSocket handshake: " 465 EXPECT_EQ("Error during WebSocket handshake: "
404 "Found an unsupported extension 'x-unknown-extension' " 466 "Found an unsupported extension 'x-unknown-extension' "
405 "in 'Sec-WebSocket-Extensions' header", 467 "in 'Sec-WebSocket-Extensions' header",
406 failure_message()); 468 failure_message());
407 } 469 }
408 470
471 // Malformed extensions are rejected (this file does not cover all possible
472 // parse failures, as the parser is covered thoroughly by its own unit tests).
473 TEST_F(WebSocketStreamCreateExtensionTest, MalformedExtension) {
474 CreateAndConnectWithExtensions(";");
475 EXPECT_FALSE(stream_);
476 EXPECT_TRUE(has_failed());
477 EXPECT_EQ(
478 "Error during WebSocket handshake: 'Sec-WebSocket-Extensions' header "
479 "value is rejected by the parser: ;",
480 failure_message());
481 }
482
483 // The permessage-deflate extension may only be specified once.
484 TEST_F(WebSocketStreamCreateExtensionTest, OnlyOnePerMessageDeflateAllowed) {
485 CreateAndConnectWithExtensions(
486 "permessage-deflate, permessage-deflate; client_max_window_bits=10");
487 EXPECT_FALSE(stream_);
488 EXPECT_TRUE(has_failed());
489 EXPECT_EQ(
490 "Error during WebSocket handshake: Received duplicate permessage-deflate "
491 "response",
492 failure_message());
493 }
494
495 // permessage-deflate parameters may not be duplicated.
496 TEST_F(WebSocketStreamCreateExtensionTest, NoDuplicateParameters) {
497 CreateAndConnectWithExtensions(
498 "permessage-deflate; client_no_context_takeover; "
499 "client_no_context_takeover");
500 EXPECT_FALSE(stream_);
501 EXPECT_TRUE(has_failed());
502 EXPECT_EQ(
503 "Error during WebSocket handshake: Received duplicate permessage-deflate "
504 "extension parameter client_no_context_takeover",
505 failure_message());
506 }
507
508 // permessage-deflate parameters must start with "client_" or "server_"
509 TEST_F(WebSocketStreamCreateExtensionTest, BadParameterPrefix) {
510 CreateAndConnectWithExtensions(
511 "permessage-deflate; absurd_no_context_takeover");
512 EXPECT_FALSE(stream_);
513 EXPECT_TRUE(has_failed());
514 EXPECT_EQ(
515 "Error during WebSocket handshake: Received an unexpected "
516 "permessage-deflate extension parameter",
517 failure_message());
518 }
519
520 // permessage-deflate parameters must be either *_no_context_takeover or
521 // *_max_window_bits
522 TEST_F(WebSocketStreamCreateExtensionTest, BadParameterSuffix) {
523 CreateAndConnectWithExtensions(
524 "permessage-deflate; client_max_content_bits=5");
525 EXPECT_FALSE(stream_);
526 EXPECT_TRUE(has_failed());
527 EXPECT_EQ(
528 "Error during WebSocket handshake: Received an unexpected "
529 "permessage-deflate extension parameter",
530 failure_message());
531 }
532
533 // *_no_context_takeover parameters must not have an argument
534 TEST_F(WebSocketStreamCreateExtensionTest, BadParameterValue) {
535 CreateAndConnectWithExtensions(
536 "permessage-deflate; client_no_context_takeover=true");
537 EXPECT_FALSE(stream_);
538 EXPECT_TRUE(has_failed());
539 EXPECT_EQ(
540 "Error during WebSocket handshake: Received invalid "
541 "client_no_context_takeover parameter",
542 failure_message());
543 }
544
545 // *_max_window_bits must have an argument
546 TEST_F(WebSocketStreamCreateExtensionTest, NoMaxWindowBitsArgument) {
547 CreateAndConnectWithExtensions("permessage-deflate; client_max_window_bits");
548 EXPECT_FALSE(stream_);
549 EXPECT_TRUE(has_failed());
550 EXPECT_EQ(
551 "Error during WebSocket handshake: client_max_window_bits must have "
552 "value",
553 failure_message());
554 }
555
556 // *_max_window_bits must be an integer
557 TEST_F(WebSocketStreamCreateExtensionTest, MaxWindowBitsValueInteger) {
558 CreateAndConnectWithExtensions(
559 "permessage-deflate; server_max_window_bits=banana");
560 EXPECT_FALSE(stream_);
561 EXPECT_TRUE(has_failed());
562 EXPECT_EQ(
563 "Error during WebSocket handshake: Received invalid "
564 "server_max_window_bits parameter",
565 failure_message());
566 }
567
568 // *_max_window_bits must be >= 8
569 TEST_F(WebSocketStreamCreateExtensionTest, MaxWindowBitsValueTooSmall) {
570 CreateAndConnectWithExtensions(
571 "permessage-deflate; server_max_window_bits=7");
572 EXPECT_FALSE(stream_);
573 EXPECT_TRUE(has_failed());
574 EXPECT_EQ(
575 "Error during WebSocket handshake: Received invalid "
576 "server_max_window_bits parameter",
577 failure_message());
578 }
579
580 // *_max_window_bits must be <= 15
581 TEST_F(WebSocketStreamCreateExtensionTest, MaxWindowBitsValueTooBig) {
582 CreateAndConnectWithExtensions(
583 "permessage-deflate; client_max_window_bits=16");
584 EXPECT_FALSE(stream_);
585 EXPECT_TRUE(has_failed());
586 EXPECT_EQ(
587 "Error during WebSocket handshake: Received invalid "
588 "client_max_window_bits parameter",
589 failure_message());
590 }
591
592 // *_max_window_bits must not start with 0
593 TEST_F(WebSocketStreamCreateExtensionTest, MaxWindowBitsValueStartsWithZero) {
594 CreateAndConnectWithExtensions(
595 "permessage-deflate; client_max_window_bits=08");
596 EXPECT_FALSE(stream_);
597 EXPECT_TRUE(has_failed());
598 EXPECT_EQ(
599 "Error during WebSocket handshake: Received invalid "
600 "client_max_window_bits parameter",
601 failure_message());
602 }
603
604 // *_max_window_bits must not start with +
605 TEST_F(WebSocketStreamCreateExtensionTest, MaxWindowBitsValueStartsWithPlus) {
606 CreateAndConnectWithExtensions(
607 "permessage-deflate; server_max_window_bits=+9");
608 EXPECT_FALSE(stream_);
609 EXPECT_TRUE(has_failed());
610 EXPECT_EQ(
611 "Error during WebSocket handshake: Received invalid "
612 "server_max_window_bits parameter",
613 failure_message());
614 }
615
616 // TODO(ricea): Check that WebSocketDeflateStream is initialised with the
617 // arguments from the server. This is difficult because the data written to the
618 // socket is randomly masked.
619
409 // Additional Sec-WebSocket-Accept headers should be rejected. 620 // Additional Sec-WebSocket-Accept headers should be rejected.
410 TEST_F(WebSocketStreamCreateTest, DoubleAccept) { 621 TEST_F(WebSocketStreamCreateTest, DoubleAccept) {
411 CreateAndConnectStandard( 622 CreateAndConnectStandard(
412 "ws://localhost/", 623 "ws://localhost/",
413 "/", 624 "/",
414 NoSubProtocols(), 625 NoSubProtocols(),
415 "http://localhost/", 626 "http://localhost/",
416 "", 627 "",
417 "Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=\r\n"); 628 "Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=\r\n");
418 RunUntilIdle(); 629 RunUntilIdle();
(...skipping 324 matching lines...) Expand 10 before | Expand all | Expand 10 after
743 stream_request_.reset(); 954 stream_request_.reset();
744 RunUntilIdle(); 955 RunUntilIdle();
745 EXPECT_FALSE(has_failed()); 956 EXPECT_FALSE(has_failed());
746 EXPECT_FALSE(stream_); 957 EXPECT_FALSE(stream_);
747 EXPECT_TRUE(request_info_); 958 EXPECT_TRUE(request_info_);
748 EXPECT_FALSE(response_info_); 959 EXPECT_FALSE(response_info_);
749 } 960 }
750 961
751 } // namespace 962 } // namespace
752 } // namespace net 963 } // namespace net
OLDNEW
« no previous file with comments | « net/websockets/websocket_handshake_stream_create_helper_test.cc ('k') | net/websockets/websocket_test_util.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698