OLD | NEW |
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 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_job.h" | 5 #include "net/websockets/websocket_job.h" |
6 | 6 |
7 #include <string> | 7 #include <string> |
8 #include <vector> | 8 #include <vector> |
9 | 9 |
10 #include "base/memory/ref_counted.h" | 10 #include "base/memory/ref_counted.h" |
11 #include "base/string_split.h" | 11 #include "base/string_split.h" |
12 #include "base/string_util.h" | 12 #include "base/string_util.h" |
13 #include "googleurl/src/gurl.h" | 13 #include "googleurl/src/gurl.h" |
14 #include "net/base/completion_callback.h" | 14 #include "net/base/completion_callback.h" |
15 #include "net/base/cookie_store.h" | 15 #include "net/base/cookie_store.h" |
16 #include "net/base/mock_host_resolver.h" | 16 #include "net/base/mock_host_resolver.h" |
17 #include "net/base/net_errors.h" | 17 #include "net/base/net_errors.h" |
18 #include "net/base/ssl_config_service.h" | 18 #include "net/base/ssl_config_service.h" |
19 #include "net/base/sys_addrinfo.h" | 19 #include "net/base/sys_addrinfo.h" |
20 #include "net/base/test_completion_callback.h" | 20 #include "net/base/test_completion_callback.h" |
21 #include "net/base/transport_security_state.h" | 21 #include "net/base/transport_security_state.h" |
| 22 #include "net/http/http_transaction_factory.h" |
22 #include "net/proxy/proxy_service.h" | 23 #include "net/proxy/proxy_service.h" |
23 #include "net/socket/socket_test_util.h" | 24 #include "net/socket/socket_test_util.h" |
24 #include "net/socket_stream/socket_stream.h" | 25 #include "net/socket_stream/socket_stream.h" |
| 26 #include "net/spdy/spdy_session.h" |
| 27 #include "net/spdy/spdy_test_util.h" |
| 28 #include "net/spdy/spdy_websocket_test_util.h" |
25 #include "net/url_request/url_request_context.h" | 29 #include "net/url_request/url_request_context.h" |
26 #include "net/websockets/websocket_throttle.h" | 30 #include "net/websockets/websocket_throttle.h" |
27 #include "testing/gtest/include/gtest/gtest.h" | 31 #include "testing/gtest/include/gtest/gtest.h" |
28 #include "testing/gmock/include/gmock/gmock.h" | 32 #include "testing/gmock/include/gmock/gmock.h" |
29 #include "testing/platform_test.h" | 33 #include "testing/platform_test.h" |
30 | 34 |
31 namespace { | 35 namespace { |
32 | 36 |
33 class MockSocketStream : public net::SocketStream { | 37 class MockSocketStream : public net::SocketStream { |
34 public: | 38 public: |
(...skipping 156 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
191 transport_security_state_->EnableHost("upgrademe.com", state); | 195 transport_security_state_->EnableHost("upgrademe.com", state); |
192 } | 196 } |
193 | 197 |
194 private: | 198 private: |
195 friend class base::RefCountedThreadSafe<MockURLRequestContext>; | 199 friend class base::RefCountedThreadSafe<MockURLRequestContext>; |
196 virtual ~MockURLRequestContext() {} | 200 virtual ~MockURLRequestContext() {} |
197 | 201 |
198 scoped_refptr<net::TransportSecurityState> transport_security_state_; | 202 scoped_refptr<net::TransportSecurityState> transport_security_state_; |
199 }; | 203 }; |
200 | 204 |
| 205 class MockHttpTransactionFactory : public net::HttpTransactionFactory { |
| 206 public: |
| 207 MockHttpTransactionFactory(scoped_refptr<net::OrderedSocketData>& data) { |
| 208 data_ = data; |
| 209 net::MockConnect connect_data(false, net::OK); |
| 210 data_->set_connect_data(connect_data); |
| 211 session_deps_.reset(new net::SpdySessionDependencies); |
| 212 session_deps_->socket_factory->AddSocketDataProvider(data_.get()); |
| 213 http_session_ = |
| 214 net::SpdySessionDependencies::SpdyCreateSession(session_deps_.get()); |
| 215 host_port_pair_.set_host("example.com"); |
| 216 host_port_pair_.set_port(80); |
| 217 host_port_proxy_pair_.first = host_port_pair_; |
| 218 host_port_proxy_pair_.second = net::ProxyServer::Direct(); |
| 219 net::SpdySessionPool* spdy_session_pool = |
| 220 http_session_->spdy_session_pool(); |
| 221 DCHECK(spdy_session_pool); |
| 222 EXPECT_FALSE(spdy_session_pool->HasSession(host_port_proxy_pair_)); |
| 223 session_ = |
| 224 spdy_session_pool->Get(host_port_proxy_pair_, net::BoundNetLog()); |
| 225 EXPECT_TRUE(spdy_session_pool->HasSession(host_port_proxy_pair_)); |
| 226 |
| 227 transport_params_ = new net::TransportSocketParams(host_port_pair_, |
| 228 net::MEDIUM, |
| 229 GURL(), |
| 230 false, |
| 231 false); |
| 232 net::ClientSocketHandle* connection = new net::ClientSocketHandle; |
| 233 EXPECT_EQ(net::OK, connection->Init(host_port_pair_.ToString(), |
| 234 transport_params_, |
| 235 net::MEDIUM, |
| 236 NULL, |
| 237 http_session_->transport_socket_pool(), |
| 238 net::BoundNetLog())); |
| 239 EXPECT_EQ(net::OK, |
| 240 session_->InitializeWithSocket(connection, false, net::OK)); |
| 241 } |
| 242 virtual int CreateTransaction(scoped_ptr<net::HttpTransaction>* trans) { |
| 243 NOTREACHED(); |
| 244 return net::ERR_UNEXPECTED; |
| 245 } |
| 246 virtual net::HttpCache* GetCache() { |
| 247 NOTREACHED(); |
| 248 return NULL; |
| 249 } |
| 250 virtual net::HttpNetworkSession* GetSession() { |
| 251 return http_session_.get(); |
| 252 } |
| 253 private: |
| 254 scoped_refptr<net::OrderedSocketData> data_; |
| 255 scoped_ptr<net::SpdySessionDependencies> session_deps_; |
| 256 scoped_refptr<net::HttpNetworkSession> http_session_; |
| 257 scoped_refptr<net::TransportSocketParams> transport_params_; |
| 258 scoped_refptr<net::SpdySession> session_; |
| 259 net::HostPortPair host_port_pair_; |
| 260 net::HostPortProxyPair host_port_proxy_pair_; |
| 261 }; |
| 262 |
201 } | 263 } |
202 | 264 |
203 namespace net { | 265 namespace net { |
204 | 266 |
205 class WebSocketJobTest : public PlatformTest { | 267 class WebSocketJobTest : public PlatformTest { |
206 public: | 268 public: |
207 virtual void SetUp() { | 269 virtual void SetUp() { |
| 270 spdy::SpdyFramer::set_enable_compression_default(false); |
208 stream_type_ = STREAM_INVALID; | 271 stream_type_ = STREAM_INVALID; |
209 cookie_store_ = new MockCookieStore; | 272 cookie_store_ = new MockCookieStore; |
210 context_ = new MockURLRequestContext(cookie_store_.get()); | 273 context_ = new MockURLRequestContext(cookie_store_.get()); |
211 } | 274 } |
212 virtual void TearDown() { | 275 virtual void TearDown() { |
213 cookie_store_ = NULL; | 276 cookie_store_ = NULL; |
214 context_ = NULL; | 277 context_ = NULL; |
215 websocket_ = NULL; | 278 websocket_ = NULL; |
216 socket_ = NULL; | 279 socket_ = NULL; |
217 } | 280 } |
(...skipping 14 matching lines...) Expand all Loading... |
232 protected: | 295 protected: |
233 enum StreamType { | 296 enum StreamType { |
234 STREAM_INVALID, | 297 STREAM_INVALID, |
235 STREAM_MOCK_SOCKET, | 298 STREAM_MOCK_SOCKET, |
236 STREAM_SOCKET, | 299 STREAM_SOCKET, |
237 STREAM_SPDY_WEBSOCKET, | 300 STREAM_SPDY_WEBSOCKET, |
238 }; | 301 }; |
239 void InitWebSocketJob(const GURL& url, | 302 void InitWebSocketJob(const GURL& url, |
240 MockSocketStreamDelegate* delegate, | 303 MockSocketStreamDelegate* delegate, |
241 StreamType stream_type) { | 304 StreamType stream_type) { |
| 305 DCHECK_NE(STREAM_INVALID, stream_type); |
242 stream_type_ = stream_type; | 306 stream_type_ = stream_type; |
243 websocket_ = new WebSocketJob(delegate); | 307 websocket_ = new WebSocketJob(delegate); |
244 | 308 |
245 if (stream_type == STREAM_SOCKET || | 309 if (stream_type == STREAM_MOCK_SOCKET) |
246 stream_type == STREAM_SPDY_WEBSOCKET) { | 310 socket_ = new MockSocketStream(url, websocket_.get()); |
| 311 |
| 312 if (stream_type == STREAM_SOCKET || stream_type == STREAM_SPDY_WEBSOCKET) { |
| 313 if (stream_type == STREAM_SPDY_WEBSOCKET) { |
| 314 http_factory_.reset(new MockHttpTransactionFactory(data_)); |
| 315 context_->set_http_transaction_factory(http_factory_.get()); |
| 316 } |
| 317 |
247 ssl_config_service_ = new MockSSLConfigService(); | 318 ssl_config_service_ = new MockSSLConfigService(); |
248 context_->set_ssl_config_service(ssl_config_service_); | 319 context_->set_ssl_config_service(ssl_config_service_); |
249 proxy_service_.reset(net::ProxyService::CreateDirect()); | 320 proxy_service_.reset(net::ProxyService::CreateDirect()); |
250 context_->set_proxy_service(proxy_service_.get()); | 321 context_->set_proxy_service(proxy_service_.get()); |
251 host_resolver_.reset(new net::MockHostResolver); | 322 host_resolver_.reset(new net::MockHostResolver); |
252 context_->set_host_resolver(host_resolver_.get()); | 323 context_->set_host_resolver(host_resolver_.get()); |
| 324 |
| 325 socket_ = new SocketStream(url, websocket_.get()); |
| 326 socket_factory_.reset(new MockClientSocketFactory); |
| 327 DCHECK(data_.get()); |
| 328 socket_factory_->AddSocketDataProvider(data_.get()); |
| 329 socket_->SetClientSocketFactory(socket_factory_.get()); |
253 } | 330 } |
254 | 331 |
255 switch (stream_type) { | |
256 case STREAM_INVALID: | |
257 NOTREACHED(); | |
258 break; | |
259 case STREAM_MOCK_SOCKET: | |
260 socket_ = new MockSocketStream(url, websocket_.get()); | |
261 break; | |
262 case STREAM_SOCKET: | |
263 socket_ = new SocketStream(url, websocket_.get()); | |
264 socket_factory_.reset(new MockClientSocketFactory); | |
265 DCHECK(data_.get()); | |
266 socket_factory_->AddSocketDataProvider(data_.get()); | |
267 socket_->SetClientSocketFactory(socket_factory_.get()); | |
268 break; | |
269 case STREAM_SPDY_WEBSOCKET: | |
270 // TODO(toyoshim): Support SpdyWebSocketStream. | |
271 break; | |
272 } | |
273 websocket_->InitSocketStream(socket_.get()); | 332 websocket_->InitSocketStream(socket_.get()); |
274 websocket_->set_context(context_.get()); | 333 websocket_->set_context(context_.get()); |
275 struct addrinfo addr; | 334 struct addrinfo addr; |
276 memset(&addr, 0, sizeof(struct addrinfo)); | 335 memset(&addr, 0, sizeof(struct addrinfo)); |
277 addr.ai_family = AF_INET; | 336 addr.ai_family = AF_INET; |
278 addr.ai_addrlen = sizeof(struct sockaddr_in); | 337 addr.ai_addrlen = sizeof(struct sockaddr_in); |
279 struct sockaddr_in sa_in; | 338 struct sockaddr_in sa_in; |
280 memset(&sa_in, 0, sizeof(struct sockaddr_in)); | 339 memset(&sa_in, 0, sizeof(struct sockaddr_in)); |
281 memcpy(&sa_in.sin_addr, "\x7f\0\0\1", 4); | 340 memcpy(&sa_in.sin_addr, "\x7f\0\0\1", 4); |
282 addr.ai_addr = reinterpret_cast<sockaddr*>(&sa_in); | 341 addr.ai_addr = reinterpret_cast<sockaddr*>(&sa_in); |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
317 return delegate->received_data(); | 376 return delegate->received_data(); |
318 } | 377 } |
319 | 378 |
320 void TestSimpleHandshake(); | 379 void TestSimpleHandshake(); |
321 void TestSlowHandshake(); | 380 void TestSlowHandshake(); |
322 void TestHandshakeWithCookie(); | 381 void TestHandshakeWithCookie(); |
323 void TestHandshakeWithCookieButNotAllowed(); | 382 void TestHandshakeWithCookieButNotAllowed(); |
324 void TestHSTSUpgrade(); | 383 void TestHSTSUpgrade(); |
325 void TestInvalidSendData(); | 384 void TestInvalidSendData(); |
326 void TestConnectByWebSocket(); | 385 void TestConnectByWebSocket(); |
| 386 void TestConnectBySpdy(bool use_spdy); |
327 | 387 |
328 StreamType stream_type_; | 388 StreamType stream_type_; |
329 scoped_refptr<MockCookieStore> cookie_store_; | 389 scoped_refptr<MockCookieStore> cookie_store_; |
330 scoped_refptr<MockURLRequestContext> context_; | 390 scoped_refptr<MockURLRequestContext> context_; |
331 scoped_refptr<WebSocketJob> websocket_; | 391 scoped_refptr<WebSocketJob> websocket_; |
332 scoped_refptr<SocketStream> socket_; | 392 scoped_refptr<SocketStream> socket_; |
333 scoped_ptr<MockClientSocketFactory> socket_factory_; | 393 scoped_ptr<MockClientSocketFactory> socket_factory_; |
334 scoped_refptr<OrderedSocketData> data_; | 394 scoped_refptr<OrderedSocketData> data_; |
335 TestCompletionCallback sync_callback_; | 395 TestCompletionCallback sync_callback_; |
336 scoped_refptr<MockSSLConfigService> ssl_config_service_; | 396 scoped_refptr<MockSSLConfigService> ssl_config_service_; |
337 scoped_ptr<net::ProxyService> proxy_service_; | 397 scoped_ptr<net::ProxyService> proxy_service_; |
338 scoped_ptr<net::MockHostResolver> host_resolver_; | 398 scoped_ptr<net::MockHostResolver> host_resolver_; |
| 399 scoped_ptr<MockHttpTransactionFactory> http_factory_; |
339 | 400 |
340 static const char kHandshakeRequestWithoutCookie[]; | 401 static const char kHandshakeRequestWithoutCookie[]; |
341 static const char kHandshakeRequestWithCookie[]; | 402 static const char kHandshakeRequestWithCookie[]; |
342 static const char kHandshakeRequestWithFilteredCookie[]; | 403 static const char kHandshakeRequestWithFilteredCookie[]; |
343 static const char kHandshakeResponseWithoutCookie[]; | 404 static const char kHandshakeResponseWithoutCookie[]; |
344 static const char kHandshakeResponseWithCookie[]; | 405 static const char kHandshakeResponseWithCookie[]; |
345 static const char kDataHello[]; | 406 static const char kDataHello[]; |
346 static const char kDataWorld[]; | 407 static const char kDataWorld[]; |
| 408 static const char* const kHandshakeRequestForSpdy[]; |
| 409 static const char* const kHandshakeResponseForSpdy[]; |
347 static const size_t kHandshakeRequestWithoutCookieLength; | 410 static const size_t kHandshakeRequestWithoutCookieLength; |
348 static const size_t kHandshakeRequestWithCookieLength; | 411 static const size_t kHandshakeRequestWithCookieLength; |
349 static const size_t kHandshakeRequestWithFilteredCookieLength; | 412 static const size_t kHandshakeRequestWithFilteredCookieLength; |
350 static const size_t kHandshakeResponseWithoutCookieLength; | 413 static const size_t kHandshakeResponseWithoutCookieLength; |
351 static const size_t kHandshakeResponseWithCookieLength; | 414 static const size_t kHandshakeResponseWithCookieLength; |
352 static const size_t kDataHelloLength; | 415 static const size_t kDataHelloLength; |
353 static const size_t kDataWorldLength; | 416 static const size_t kDataWorldLength; |
354 }; | 417 }; |
355 | 418 |
356 const char WebSocketJobTest::kHandshakeRequestWithoutCookie[] = | 419 const char WebSocketJobTest::kHandshakeRequestWithoutCookie[] = |
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
409 "Sec-WebSocket-Location: ws://example.com/demo\r\n" | 472 "Sec-WebSocket-Location: ws://example.com/demo\r\n" |
410 "Sec-WebSocket-Protocol: sample\r\n" | 473 "Sec-WebSocket-Protocol: sample\r\n" |
411 "Set-Cookie: CR-set-test=1\r\n" | 474 "Set-Cookie: CR-set-test=1\r\n" |
412 "\r\n" | 475 "\r\n" |
413 "8jKS'y:G*Co,Wxa-"; | 476 "8jKS'y:G*Co,Wxa-"; |
414 | 477 |
415 const char WebSocketJobTest::kDataHello[] = "Hello, "; | 478 const char WebSocketJobTest::kDataHello[] = "Hello, "; |
416 | 479 |
417 const char WebSocketJobTest::kDataWorld[] = "World!\n"; | 480 const char WebSocketJobTest::kDataWorld[] = "World!\n"; |
418 | 481 |
| 482 // TODO(toyoshim): I should clarify which WebSocket headers for handshake must |
| 483 // be exported to SPDY SYN_STREAM and SYN_REPLY. |
| 484 // Because it depends on HyBi versions, just define it as follow for now. |
| 485 const char* const WebSocketJobTest::kHandshakeRequestForSpdy[] = { |
| 486 "host", "example.com", |
| 487 "origin", "http://example.com", |
| 488 "sec-websocket-protocol", "sample", |
| 489 "url", "ws://example.com/demo" |
| 490 }; |
| 491 |
| 492 const char* const WebSocketJobTest::kHandshakeResponseForSpdy[] = { |
| 493 "sec-websocket-origin", "http://example.com", |
| 494 "sec-websocket-location", "ws://example.com/demo", |
| 495 "sec-websocket-protocol", "sample", |
| 496 }; |
| 497 |
419 const size_t WebSocketJobTest::kHandshakeRequestWithoutCookieLength = | 498 const size_t WebSocketJobTest::kHandshakeRequestWithoutCookieLength = |
420 arraysize(kHandshakeRequestWithoutCookie) - 1; | 499 arraysize(kHandshakeRequestWithoutCookie) - 1; |
421 const size_t WebSocketJobTest::kHandshakeRequestWithCookieLength = | 500 const size_t WebSocketJobTest::kHandshakeRequestWithCookieLength = |
422 arraysize(kHandshakeRequestWithCookie) - 1; | 501 arraysize(kHandshakeRequestWithCookie) - 1; |
423 const size_t WebSocketJobTest::kHandshakeRequestWithFilteredCookieLength = | 502 const size_t WebSocketJobTest::kHandshakeRequestWithFilteredCookieLength = |
424 arraysize(kHandshakeRequestWithFilteredCookie) - 1; | 503 arraysize(kHandshakeRequestWithFilteredCookie) - 1; |
425 const size_t WebSocketJobTest::kHandshakeResponseWithoutCookieLength = | 504 const size_t WebSocketJobTest::kHandshakeResponseWithoutCookieLength = |
426 arraysize(kHandshakeResponseWithoutCookie) - 1; | 505 arraysize(kHandshakeResponseWithoutCookie) - 1; |
427 const size_t WebSocketJobTest::kHandshakeResponseWithCookieLength = | 506 const size_t WebSocketJobTest::kHandshakeResponseWithCookieLength = |
428 arraysize(kHandshakeResponseWithCookie) - 1; | 507 arraysize(kHandshakeResponseWithCookie) - 1; |
(...skipping 188 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
617 EXPECT_EQ(WebSocketJob::CONNECTING, GetWebSocketJobState()); | 696 EXPECT_EQ(WebSocketJob::CONNECTING, GetWebSocketJobState()); |
618 CloseWebSocketJob(); | 697 CloseWebSocketJob(); |
619 } | 698 } |
620 | 699 |
621 // Following tests verify cooperation between WebSocketJob and SocketStream. | 700 // Following tests verify cooperation between WebSocketJob and SocketStream. |
622 // Other former tests use MockSocketStream as SocketStream, so we could not | 701 // Other former tests use MockSocketStream as SocketStream, so we could not |
623 // check SocketStream behavior. | 702 // check SocketStream behavior. |
624 // OrderedSocketData provide socket level verifiation by checking out-going | 703 // OrderedSocketData provide socket level verifiation by checking out-going |
625 // packets in comparison with the MockWrite array and emulating in-coming | 704 // packets in comparison with the MockWrite array and emulating in-coming |
626 // packets with MockRead array. | 705 // packets with MockRead array. |
627 // TODO(toyoshim): Add tests which verify protocol switch and ERR_IO_PENDING. | |
628 | 706 |
629 void WebSocketJobTest::TestConnectByWebSocket() { | 707 void WebSocketJobTest::TestConnectByWebSocket() { |
630 // This is a test for verifying cooperation between WebSocketJob and | 708 // This is a test for verifying cooperation between WebSocketJob and |
631 // SocketStream in basic situation. | 709 // SocketStream in basic situation. |
632 MockWrite writes[] = { | 710 MockWrite writes[] = { |
633 MockWrite(true, | 711 MockWrite(true, |
634 kHandshakeRequestWithoutCookie, | 712 kHandshakeRequestWithoutCookie, |
635 kHandshakeRequestWithoutCookieLength, | 713 kHandshakeRequestWithoutCookieLength, |
636 1), | 714 1), |
637 MockWrite(true, | 715 MockWrite(true, |
638 kDataHello, | 716 kDataHello, |
639 kDataHelloLength, | 717 kDataHelloLength, |
640 3) | 718 3) |
641 }; | 719 }; |
642 MockRead reads[] = { | 720 MockRead reads[] = { |
643 MockRead(true, | 721 MockRead(true, |
644 kHandshakeResponseWithoutCookie, | 722 kHandshakeResponseWithoutCookie, |
645 kHandshakeResponseWithoutCookieLength, | 723 kHandshakeResponseWithoutCookieLength, |
646 2), | 724 2), |
647 MockRead(true, | 725 MockRead(true, |
648 kDataWorld, | 726 kDataWorld, |
649 kDataWorldLength, | 727 kDataWorldLength, |
650 4), | 728 4), |
651 MockRead(false, 0, 5) // EOF | 729 MockRead(false, 0, 5) // EOF |
652 }; | 730 }; |
653 data_ = (new OrderedSocketData( | 731 data_ = new OrderedSocketData( |
654 reads, arraysize(reads), writes, arraysize(writes))); | 732 reads, arraysize(reads), writes, arraysize(writes)); |
655 | 733 |
656 GURL url("ws://example.com/demo"); | 734 GURL url("ws://example.com/demo"); |
657 MockSocketStreamDelegate delegate; | 735 MockSocketStreamDelegate delegate; |
658 WebSocketJobTest* test = this; | 736 WebSocketJobTest* test = this; |
659 delegate.SetOnConnected( | 737 delegate.SetOnConnected( |
660 NewCallback(test, &WebSocketJobTest::DoSendRequest)); | 738 NewCallback(test, &WebSocketJobTest::DoSendRequest)); |
661 delegate.SetOnReceivedData( | 739 delegate.SetOnReceivedData( |
662 NewCallback(test, &WebSocketJobTest::DoSendData)); | 740 NewCallback(test, &WebSocketJobTest::DoSendData)); |
663 delegate.SetOnClose( | 741 delegate.SetOnClose( |
664 NewCallback(test, &WebSocketJobTest::DoSync)); | 742 NewCallback(test, &WebSocketJobTest::DoSync)); |
665 InitWebSocketJob(url, &delegate, STREAM_SOCKET); | 743 InitWebSocketJob(url, &delegate, STREAM_SOCKET); |
666 | 744 |
667 websocket_->Connect(); | 745 websocket_->Connect(); |
668 EXPECT_EQ(OK, WaitForResult()); | 746 EXPECT_EQ(OK, WaitForResult()); |
669 EXPECT_TRUE(data_->at_read_eof()); | 747 EXPECT_TRUE(data_->at_read_eof()); |
670 EXPECT_TRUE(data_->at_write_eof()); | 748 EXPECT_TRUE(data_->at_write_eof()); |
671 EXPECT_EQ(WebSocketJob::CLOSED, GetWebSocketJobState()); | 749 EXPECT_EQ(WebSocketJob::CLOSED, GetWebSocketJobState()); |
672 } | 750 } |
673 | 751 |
| 752 void WebSocketJobTest::TestConnectBySpdy(bool use_spdy) { |
| 753 // This is a test for verifying cooperation between WebSocketJob and |
| 754 // SocketStream in the situation we have SPDY session to the server. |
| 755 MockWrite writes_websocket[] = { |
| 756 MockWrite(true, |
| 757 kHandshakeRequestWithoutCookie, |
| 758 kHandshakeRequestWithoutCookieLength, |
| 759 1), |
| 760 MockWrite(true, |
| 761 kDataHello, |
| 762 kDataHelloLength, |
| 763 3) |
| 764 }; |
| 765 MockRead reads_websocket[] = { |
| 766 MockRead(true, |
| 767 kHandshakeResponseWithoutCookie, |
| 768 kHandshakeResponseWithoutCookieLength, |
| 769 2), |
| 770 MockRead(true, |
| 771 kDataWorld, |
| 772 kDataWorldLength, |
| 773 4), |
| 774 MockRead(false, 0, 5) // EOF |
| 775 }; |
| 776 |
| 777 const spdy::SpdyStreamId kStreamId = 1; |
| 778 scoped_ptr<spdy::SpdyFrame> request_frame( |
| 779 ConstructSpdyWebSocketHandshakeRequestFrame( |
| 780 kHandshakeRequestForSpdy, |
| 781 arraysize(kHandshakeRequestForSpdy) / 2, |
| 782 kStreamId, |
| 783 MEDIUM)); |
| 784 scoped_ptr<spdy::SpdyFrame> response_frame( |
| 785 ConstructSpdyWebSocketHandshakeResponseFrame( |
| 786 kHandshakeResponseForSpdy, |
| 787 arraysize(kHandshakeResponseForSpdy) / 2, |
| 788 kStreamId, |
| 789 MEDIUM)); |
| 790 scoped_ptr<spdy::SpdyFrame> data_hello_frame( |
| 791 ConstructSpdyWebSocketDataFrame( |
| 792 kDataHello, |
| 793 kDataHelloLength, |
| 794 kStreamId, |
| 795 false)); |
| 796 scoped_ptr<spdy::SpdyFrame> data_world_frame( |
| 797 ConstructSpdyWebSocketDataFrame( |
| 798 kDataWorld, |
| 799 kDataWorldLength, |
| 800 kStreamId, |
| 801 false)); |
| 802 MockWrite writes_spdy[] = { |
| 803 CreateMockWrite(*request_frame.get(), 1), |
| 804 CreateMockWrite(*data_hello_frame.get(), 3), |
| 805 }; |
| 806 MockRead reads_spdy[] = { |
| 807 CreateMockRead(*response_frame.get(), 2), |
| 808 CreateMockRead(*data_world_frame.get(), 4), |
| 809 MockRead(false, 0, 5) // EOF |
| 810 }; |
| 811 |
| 812 if (use_spdy) |
| 813 data_ = new OrderedSocketData( |
| 814 reads_spdy, arraysize(reads_spdy), |
| 815 writes_spdy, arraysize(writes_spdy)); |
| 816 else |
| 817 data_ = new OrderedSocketData( |
| 818 reads_websocket, arraysize(reads_websocket), |
| 819 writes_websocket, arraysize(writes_websocket)); |
| 820 |
| 821 GURL url("ws://example.com/demo"); |
| 822 MockSocketStreamDelegate delegate; |
| 823 WebSocketJobTest* test = this; |
| 824 delegate.SetOnConnected( |
| 825 NewCallback(test, &WebSocketJobTest::DoSendRequest)); |
| 826 delegate.SetOnReceivedData( |
| 827 NewCallback(test, &WebSocketJobTest::DoSendData)); |
| 828 delegate.SetOnClose( |
| 829 NewCallback(test, &WebSocketJobTest::DoSync)); |
| 830 InitWebSocketJob(url, &delegate, STREAM_SPDY_WEBSOCKET); |
| 831 |
| 832 websocket_->Connect(); |
| 833 EXPECT_EQ(OK, WaitForResult()); |
| 834 |
| 835 EXPECT_TRUE(data_->at_read_eof()); |
| 836 EXPECT_TRUE(data_->at_write_eof()); |
| 837 EXPECT_EQ(WebSocketJob::CLOSED, GetWebSocketJobState()); |
| 838 } |
| 839 |
674 // Execute tests in both spdy-disabled mode and spdy-enabled mode. | 840 // Execute tests in both spdy-disabled mode and spdy-enabled mode. |
675 TEST_F(WebSocketJobTest, SimpleHandshake) { | 841 TEST_F(WebSocketJobTest, SimpleHandshake) { |
676 WebSocketJob::set_websocket_over_spdy_enabled(false); | 842 WebSocketJob::set_websocket_over_spdy_enabled(false); |
677 TestSimpleHandshake(); | 843 TestSimpleHandshake(); |
678 } | 844 } |
679 | 845 |
680 TEST_F(WebSocketJobTest, SlowHandshake) { | 846 TEST_F(WebSocketJobTest, SlowHandshake) { |
681 WebSocketJob::set_websocket_over_spdy_enabled(false); | 847 WebSocketJob::set_websocket_over_spdy_enabled(false); |
682 TestSlowHandshake(); | 848 TestSlowHandshake(); |
683 } | 849 } |
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
735 TEST_F(WebSocketJobTest, ConnectByWebSocket) { | 901 TEST_F(WebSocketJobTest, ConnectByWebSocket) { |
736 WebSocketJob::set_websocket_over_spdy_enabled(false); | 902 WebSocketJob::set_websocket_over_spdy_enabled(false); |
737 TestConnectByWebSocket(); | 903 TestConnectByWebSocket(); |
738 } | 904 } |
739 | 905 |
740 TEST_F(WebSocketJobTest, ConnectByWebSocketSpdyEnabled) { | 906 TEST_F(WebSocketJobTest, ConnectByWebSocketSpdyEnabled) { |
741 WebSocketJob::set_websocket_over_spdy_enabled(true); | 907 WebSocketJob::set_websocket_over_spdy_enabled(true); |
742 TestConnectByWebSocket(); | 908 TestConnectByWebSocket(); |
743 } | 909 } |
744 | 910 |
| 911 TEST_F(WebSocketJobTest, ConnectBySpdy) { |
| 912 WebSocketJob::set_websocket_over_spdy_enabled(false); |
| 913 TestConnectBySpdy(false); |
| 914 } |
| 915 |
| 916 TEST_F(WebSocketJobTest, ConnectBySpdySpdyEnabled) { |
| 917 WebSocketJob::set_websocket_over_spdy_enabled(true); |
| 918 TestConnectBySpdy(true); |
| 919 } |
| 920 |
| 921 // TODO(toyoshim): Add tests to verify throttling, SPDY stream limitation. |
| 922 // TODO(toyoshim,yutak): Add tests to verify closing handshake. |
| 923 |
745 } // namespace net | 924 } // namespace net |
OLD | NEW |