spdy_proxy_client_socket_unittest.cc revision eb525c5499e34cc9c4b825d6d9e75bb07cc06ace
1// Copyright (c) 2012 The Chromium Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4 5#include "net/spdy/spdy_proxy_client_socket.h" 6 7#include "base/bind.h" 8#include "base/bind_helpers.h" 9#include "base/strings/utf_string_conversions.h" 10#include "net/base/address_list.h" 11#include "net/base/capturing_net_log.h" 12#include "net/base/net_log.h" 13#include "net/base/net_log_unittest.h" 14#include "net/base/test_completion_callback.h" 15#include "net/base/winsock_init.h" 16#include "net/dns/mock_host_resolver.h" 17#include "net/http/http_response_headers.h" 18#include "net/http/http_response_info.h" 19#include "net/socket/client_socket_factory.h" 20#include "net/socket/next_proto.h" 21#include "net/socket/socket_test_util.h" 22#include "net/socket/tcp_client_socket.h" 23#include "net/spdy/buffered_spdy_framer.h" 24#include "net/spdy/spdy_http_utils.h" 25#include "net/spdy/spdy_protocol.h" 26#include "net/spdy/spdy_session_pool.h" 27#include "net/spdy/spdy_test_util_common.h" 28#include "testing/gtest/include/gtest/gtest.h" 29#include "testing/platform_test.h" 30 31//----------------------------------------------------------------------------- 32 33namespace { 34 35static const char kRequestUrl[] = "https://www.google.com/"; 36static const char kOriginHost[] = "www.google.com"; 37static const int kOriginPort = 443; 38static const char kOriginHostPort[] = "www.google.com:443"; 39static const char kProxyUrl[] = "https://myproxy:6121/"; 40static const char kProxyHost[] = "myproxy"; 41static const int kProxyPort = 6121; 42static const char kUserAgent[] = "Mozilla/1.0"; 43 44static const int kStreamId = 1; 45 46static const char kMsg1[] = "\0hello!\xff"; 47static const int kLen1 = 8; 48static const char kMsg2[] = "\00012345678\0"; 49static const int kLen2 = 10; 50static const char kMsg3[] = "bye!"; 51static const int kLen3 = 4; 52static const char kMsg33[] = "bye!bye!"; 53static const int kLen33 = kLen3 + kLen3; 54static const char kMsg333[] = "bye!bye!bye!"; 55static const int kLen333 = kLen3 + kLen3 + kLen3; 56 57static const char kRedirectUrl[] = "https://example.com/"; 58 59} // anonymous namespace 60 61namespace net { 62 63class SpdyProxyClientSocketTest 64 : public PlatformTest, 65 public testing::WithParamInterface<NextProto> { 66 public: 67 SpdyProxyClientSocketTest(); 68 69 virtual void TearDown(); 70 71 protected: 72 void Initialize(MockRead* reads, size_t reads_count, MockWrite* writes, 73 size_t writes_count); 74 SpdyFrame* ConstructConnectRequestFrame(); 75 SpdyFrame* ConstructConnectAuthRequestFrame(); 76 SpdyFrame* ConstructConnectReplyFrame(); 77 SpdyFrame* ConstructConnectAuthReplyFrame(); 78 SpdyFrame* ConstructConnectRedirectReplyFrame(); 79 SpdyFrame* ConstructConnectErrorReplyFrame(); 80 SpdyFrame* ConstructBodyFrame(const char* data, int length); 81 scoped_refptr<IOBufferWithSize> CreateBuffer(const char* data, int size); 82 void AssertConnectSucceeds(); 83 void AssertConnectFails(int result); 84 void AssertConnectionEstablished(); 85 void AssertSyncReadEquals(const char* data, int len); 86 void AssertAsyncReadEquals(const char* data, int len); 87 void AssertReadStarts(const char* data, int len); 88 void AssertReadReturns(const char* data, int len); 89 void AssertAsyncWriteSucceeds(const char* data, int len); 90 void AssertWriteReturns(const char* data, int len, int rv); 91 void AssertWriteLength(int len); 92 void AssertAsyncWriteWithReadsSucceeds(const char* data, int len, 93 int num_reads); 94 95 void AddAuthToCache() { 96 const base::string16 kFoo(ASCIIToUTF16("foo")); 97 const base::string16 kBar(ASCIIToUTF16("bar")); 98 session_->http_auth_cache()->Add(GURL(kProxyUrl), 99 "MyRealm1", 100 HttpAuth::AUTH_SCHEME_BASIC, 101 "Basic realm=MyRealm1", 102 AuthCredentials(kFoo, kBar), 103 "/"); 104 } 105 106 void Run(int steps) { 107 data_->StopAfter(steps); 108 data_->Run(); 109 } 110 111 SpdyTestUtil spdy_util_; 112 scoped_ptr<SpdyProxyClientSocket> sock_; 113 TestCompletionCallback read_callback_; 114 TestCompletionCallback write_callback_; 115 scoped_ptr<DeterministicSocketData> data_; 116 CapturingBoundNetLog net_log_; 117 118 private: 119 scoped_refptr<HttpNetworkSession> session_; 120 scoped_refptr<IOBuffer> read_buf_; 121 SpdySessionDependencies session_deps_; 122 MockConnect connect_data_; 123 scoped_refptr<SpdySession> spdy_session_; 124 BufferedSpdyFramer framer_; 125 126 std::string user_agent_; 127 GURL url_; 128 HostPortPair proxy_host_port_; 129 HostPortPair endpoint_host_port_pair_; 130 ProxyServer proxy_; 131 SpdySessionKey endpoint_spdy_session_key_; 132 scoped_refptr<TransportSocketParams> transport_params_; 133 134 DISALLOW_COPY_AND_ASSIGN(SpdyProxyClientSocketTest); 135}; 136 137INSTANTIATE_TEST_CASE_P( 138 NextProto, 139 SpdyProxyClientSocketTest, 140 testing::Values(kProtoSPDY2, kProtoSPDY3, kProtoSPDY31, kProtoSPDY4a2)); 141 142SpdyProxyClientSocketTest::SpdyProxyClientSocketTest() 143 : spdy_util_(GetParam()), 144 session_(NULL), 145 read_buf_(NULL), 146 session_deps_(GetParam()), 147 connect_data_(SYNCHRONOUS, OK), 148 spdy_session_(NULL), 149 framer_(spdy_util_.spdy_version(), false), 150 user_agent_(kUserAgent), 151 url_(kRequestUrl), 152 proxy_host_port_(kProxyHost, kProxyPort), 153 endpoint_host_port_pair_(kOriginHost, kOriginPort), 154 proxy_(ProxyServer::SCHEME_HTTPS, proxy_host_port_), 155 endpoint_spdy_session_key_(endpoint_host_port_pair_, 156 proxy_, 157 kPrivacyModeDisabled), 158 transport_params_(new TransportSocketParams(proxy_host_port_, 159 LOWEST, 160 false, 161 false, 162 OnHostResolutionCallback())) { 163 session_deps_.net_log = net_log_.bound().net_log(); 164} 165 166void SpdyProxyClientSocketTest::TearDown() { 167 sock_.reset(NULL); 168 if (session_.get() != NULL) 169 session_->spdy_session_pool()->CloseAllSessions(); 170 171 // Empty the current queue. 172 base::MessageLoop::current()->RunUntilIdle(); 173 PlatformTest::TearDown(); 174} 175 176void SpdyProxyClientSocketTest::Initialize(MockRead* reads, 177 size_t reads_count, 178 MockWrite* writes, 179 size_t writes_count) { 180 data_.reset(new DeterministicSocketData(reads, reads_count, 181 writes, writes_count)); 182 data_->set_connect_data(connect_data_); 183 data_->SetStop(2); 184 185 session_deps_.deterministic_socket_factory->AddSocketDataProvider( 186 data_.get()); 187 session_deps_.host_resolver->set_synchronous_mode(true); 188 189 session_ = SpdySessionDependencies::SpdyCreateSessionDeterministic( 190 &session_deps_); 191 192 // Creates a new spdy session. 193 spdy_session_ = 194 session_->spdy_session_pool()->Get(endpoint_spdy_session_key_, 195 net_log_.bound()); 196 197 // Perform the TCP connect. 198 scoped_ptr<ClientSocketHandle> connection(new ClientSocketHandle); 199 EXPECT_EQ(OK, 200 connection->Init(endpoint_host_port_pair_.ToString(), 201 transport_params_, LOWEST, CompletionCallback(), 202 session_->GetTransportSocketPool( 203 HttpNetworkSession::NORMAL_SOCKET_POOL), 204 net_log_.bound())); 205 spdy_session_->InitializeWithSocket(connection.release(), false, OK); 206 207 // Create the SPDY Stream. 208 base::WeakPtr<SpdyStream> spdy_stream( 209 CreateStreamSynchronously( 210 SPDY_BIDIRECTIONAL_STREAM, spdy_session_, url_, LOWEST, 211 net_log_.bound())); 212 ASSERT_TRUE(spdy_stream.get() != NULL); 213 214 // Create the SpdyProxyClientSocket. 215 sock_.reset( 216 new SpdyProxyClientSocket(spdy_stream, user_agent_, 217 endpoint_host_port_pair_, url_, 218 proxy_host_port_, net_log_.bound(), 219 session_->http_auth_cache(), 220 session_->http_auth_handler_factory())); 221} 222 223scoped_refptr<IOBufferWithSize> SpdyProxyClientSocketTest::CreateBuffer( 224 const char* data, int size) { 225 scoped_refptr<IOBufferWithSize> buf(new IOBufferWithSize(size)); 226 memcpy(buf->data(), data, size); 227 return buf; 228} 229 230void SpdyProxyClientSocketTest::AssertConnectSucceeds() { 231 ASSERT_EQ(ERR_IO_PENDING, sock_->Connect(read_callback_.callback())); 232 data_->Run(); 233 ASSERT_EQ(OK, read_callback_.WaitForResult()); 234} 235 236void SpdyProxyClientSocketTest::AssertConnectFails(int result) { 237 ASSERT_EQ(ERR_IO_PENDING, sock_->Connect(read_callback_.callback())); 238 data_->Run(); 239 ASSERT_EQ(result, read_callback_.WaitForResult()); 240} 241 242void SpdyProxyClientSocketTest::AssertConnectionEstablished() { 243 const HttpResponseInfo* response = sock_->GetConnectResponseInfo(); 244 ASSERT_TRUE(response != NULL); 245 ASSERT_EQ(200, response->headers->response_code()); 246 ASSERT_EQ("Connection Established", response->headers->GetStatusText()); 247} 248 249void SpdyProxyClientSocketTest::AssertSyncReadEquals(const char* data, 250 int len) { 251 scoped_refptr<IOBuffer> buf(new IOBuffer(len)); 252 ASSERT_EQ(len, sock_->Read(buf.get(), len, CompletionCallback())); 253 ASSERT_EQ(std::string(data, len), std::string(buf->data(), len)); 254 ASSERT_TRUE(sock_->IsConnected()); 255} 256 257void SpdyProxyClientSocketTest::AssertAsyncReadEquals(const char* data, 258 int len) { 259 data_->StopAfter(1); 260 // Issue the read, which will be completed asynchronously 261 scoped_refptr<IOBuffer> buf(new IOBuffer(len)); 262 ASSERT_EQ(ERR_IO_PENDING, 263 sock_->Read(buf.get(), len, read_callback_.callback())); 264 EXPECT_TRUE(sock_->IsConnected()); 265 data_->Run(); 266 267 EXPECT_TRUE(sock_->IsConnected()); 268 269 // Now the read will return 270 EXPECT_EQ(len, read_callback_.WaitForResult()); 271 ASSERT_EQ(std::string(data, len), std::string(buf->data(), len)); 272} 273 274void SpdyProxyClientSocketTest::AssertReadStarts(const char* data, 275 int len) { 276 data_->StopAfter(1); 277 // Issue the read, which will be completed asynchronously 278 read_buf_ = new IOBuffer(len); 279 ASSERT_EQ(ERR_IO_PENDING, 280 sock_->Read(read_buf_.get(), len, read_callback_.callback())); 281 EXPECT_TRUE(sock_->IsConnected()); 282} 283 284void SpdyProxyClientSocketTest::AssertReadReturns(const char* data, 285 int len) { 286 EXPECT_TRUE(sock_->IsConnected()); 287 288 // Now the read will return 289 EXPECT_EQ(len, read_callback_.WaitForResult()); 290 ASSERT_EQ(std::string(data, len), std::string(read_buf_->data(), len)); 291} 292 293void SpdyProxyClientSocketTest::AssertAsyncWriteSucceeds(const char* data, 294 int len) { 295 AssertWriteReturns(data, len, ERR_IO_PENDING); 296 data_->RunFor(1); 297 AssertWriteLength(len); 298} 299 300void SpdyProxyClientSocketTest::AssertWriteReturns(const char* data, 301 int len, 302 int rv) { 303 scoped_refptr<IOBufferWithSize> buf(CreateBuffer(data, len)); 304 EXPECT_EQ(rv, 305 sock_->Write(buf.get(), buf->size(), write_callback_.callback())); 306} 307 308void SpdyProxyClientSocketTest::AssertWriteLength(int len) { 309 EXPECT_EQ(len, write_callback_.WaitForResult()); 310} 311 312void SpdyProxyClientSocketTest::AssertAsyncWriteWithReadsSucceeds( 313 const char* data, int len, int num_reads) { 314 scoped_refptr<IOBufferWithSize> buf(CreateBuffer(data, len)); 315 316 EXPECT_EQ(ERR_IO_PENDING, 317 sock_->Write(buf.get(), buf->size(), write_callback_.callback())); 318 319 for (int i = 0; i < num_reads; i++) { 320 Run(1); 321 AssertSyncReadEquals(kMsg2, kLen2); 322 } 323 324 write_callback_.WaitForResult(); 325} 326 327// Constructs a standard SPDY SYN_STREAM frame for a CONNECT request. 328SpdyFrame* 329SpdyProxyClientSocketTest::ConstructConnectRequestFrame() { 330 const SpdyHeaderInfo kSynStartHeader = { 331 SYN_STREAM, 332 kStreamId, 333 0, 334 net::ConvertRequestPriorityToSpdyPriority( 335 LOWEST, spdy_util_.spdy_version()), 336 0, 337 CONTROL_FLAG_NONE, 338 false, 339 RST_STREAM_INVALID, 340 NULL, 341 0, 342 DATA_FLAG_NONE 343 }; 344 bool spdy2 = spdy_util_.is_spdy2(); 345 const char* const kConnectHeaders[] = { 346 spdy2 ? "method" : ":method", "CONNECT", 347 spdy2 ? "url" : ":path", kOriginHostPort, 348 spdy2 ? "host" : ":host", kOriginHost, 349 "user-agent", kUserAgent, 350 spdy2 ? "version" : ":version", "HTTP/1.1", 351 }; 352 return spdy_util_.ConstructSpdyFrame( 353 kSynStartHeader, NULL, 0, kConnectHeaders, arraysize(kConnectHeaders)/2); 354} 355 356// Constructs a SPDY SYN_STREAM frame for a CONNECT request which includes 357// Proxy-Authorization headers. 358SpdyFrame* 359SpdyProxyClientSocketTest::ConstructConnectAuthRequestFrame() { 360 const SpdyHeaderInfo kSynStartHeader = { 361 SYN_STREAM, 362 kStreamId, 363 0, 364 net::ConvertRequestPriorityToSpdyPriority( 365 LOWEST, spdy_util_.spdy_version()), 366 0, 367 CONTROL_FLAG_NONE, 368 false, 369 RST_STREAM_INVALID, 370 NULL, 371 0, 372 DATA_FLAG_NONE 373 }; 374 bool spdy2 = spdy_util_.is_spdy2(); 375 const char* const kConnectHeaders[] = { 376 spdy2 ? "method" : ":method", "CONNECT", 377 spdy2 ? "url" : ":path", kOriginHostPort, 378 spdy2 ? "host" : ":host", kOriginHost, 379 "user-agent", kUserAgent, 380 spdy2 ? "version" : ":version", "HTTP/1.1", 381 "proxy-authorization", "Basic Zm9vOmJhcg==", 382 }; 383 return spdy_util_.ConstructSpdyFrame( 384 kSynStartHeader, NULL, 0, kConnectHeaders, arraysize(kConnectHeaders)/2); 385} 386 387// Constructs a standard SPDY SYN_REPLY frame to match the SPDY CONNECT. 388SpdyFrame* SpdyProxyClientSocketTest::ConstructConnectReplyFrame() { 389 bool spdy2 = spdy_util_.is_spdy2(); 390 const char* const kStandardReplyHeaders[] = { 391 spdy2 ? "status" : ":status", "200 Connection Established", 392 spdy2 ? "version" : ":version", "HTTP/1.1" 393 }; 394 return spdy_util_.ConstructSpdyControlFrame(NULL, 395 0, 396 false, 397 kStreamId, 398 LOWEST, 399 SYN_REPLY, 400 CONTROL_FLAG_NONE, 401 kStandardReplyHeaders, 402 arraysize(kStandardReplyHeaders), 403 0); 404} 405 406// Constructs a standard SPDY SYN_REPLY frame to match the SPDY CONNECT. 407SpdyFrame* 408SpdyProxyClientSocketTest::ConstructConnectAuthReplyFrame() { 409 bool spdy2 = spdy_util_.is_spdy2(); 410 411 const char* const kStandardReplyHeaders[] = { 412 spdy2 ? "status" : ":status", "407 Proxy Authentication Required", 413 spdy2 ? "version" : ":version", "HTTP/1.1", 414 "proxy-authenticate", "Basic realm=\"MyRealm1\"", 415 }; 416 417 return spdy_util_.ConstructSpdyControlFrame(NULL, 418 0, 419 false, 420 kStreamId, 421 LOWEST, 422 SYN_REPLY, 423 CONTROL_FLAG_NONE, 424 kStandardReplyHeaders, 425 arraysize(kStandardReplyHeaders), 426 0); 427} 428 429// Constructs a SPDY SYN_REPLY frame with an HTTP 302 redirect. 430SpdyFrame* 431SpdyProxyClientSocketTest::ConstructConnectRedirectReplyFrame() { 432 bool spdy2 = spdy_util_.is_spdy2(); 433 434 const char* const kStandardReplyHeaders[] = { 435 spdy2 ? "status" : ":status", "302 Found", 436 spdy2 ? "version" : ":version", "HTTP/1.1", 437 "location", kRedirectUrl, 438 "set-cookie", "foo=bar" 439 }; 440 441 return spdy_util_.ConstructSpdyControlFrame(NULL, 442 0, 443 false, 444 kStreamId, 445 LOWEST, 446 SYN_REPLY, 447 CONTROL_FLAG_NONE, 448 kStandardReplyHeaders, 449 arraysize(kStandardReplyHeaders), 450 0); 451} 452 453// Constructs a SPDY SYN_REPLY frame with an HTTP 500 error. 454SpdyFrame* 455SpdyProxyClientSocketTest::ConstructConnectErrorReplyFrame() { 456 bool spdy2 = spdy_util_.is_spdy2(); 457 458 const char* const kStandardReplyHeaders[] = { 459 spdy2 ? "status" : ":status", "500 Internal Server Error", 460 spdy2 ? "version" : ":version", "HTTP/1.1", 461 }; 462 463 return spdy_util_.ConstructSpdyControlFrame(NULL, 464 0, 465 false, 466 kStreamId, 467 LOWEST, 468 SYN_REPLY, 469 CONTROL_FLAG_NONE, 470 kStandardReplyHeaders, 471 arraysize(kStandardReplyHeaders), 472 0); 473} 474 475SpdyFrame* SpdyProxyClientSocketTest::ConstructBodyFrame( 476 const char* data, 477 int length) { 478 return framer_.CreateDataFrame(kStreamId, data, length, DATA_FLAG_NONE); 479} 480 481// ----------- Connect 482 483TEST_P(SpdyProxyClientSocketTest, ConnectSendsCorrectRequest) { 484 scoped_ptr<SpdyFrame> conn(ConstructConnectRequestFrame()); 485 MockWrite writes[] = { 486 CreateMockWrite(*conn, 0, SYNCHRONOUS), 487 }; 488 489 scoped_ptr<SpdyFrame> resp(ConstructConnectReplyFrame()); 490 MockRead reads[] = { 491 CreateMockRead(*resp, 1, ASYNC), 492 MockRead(ASYNC, 0, 2), // EOF 493 }; 494 495 Initialize(reads, arraysize(reads), writes, arraysize(writes)); 496 497 ASSERT_FALSE(sock_->IsConnected()); 498 499 AssertConnectSucceeds(); 500 501 AssertConnectionEstablished(); 502} 503 504TEST_P(SpdyProxyClientSocketTest, ConnectWithAuthRequested) { 505 scoped_ptr<SpdyFrame> conn(ConstructConnectRequestFrame()); 506 MockWrite writes[] = { 507 CreateMockWrite(*conn, 0, SYNCHRONOUS), 508 }; 509 510 scoped_ptr<SpdyFrame> resp(ConstructConnectAuthReplyFrame()); 511 MockRead reads[] = { 512 CreateMockRead(*resp, 1, ASYNC), 513 MockRead(ASYNC, 0, 2), // EOF 514 }; 515 516 Initialize(reads, arraysize(reads), writes, arraysize(writes)); 517 518 AssertConnectFails(ERR_PROXY_AUTH_REQUESTED); 519 520 const HttpResponseInfo* response = sock_->GetConnectResponseInfo(); 521 ASSERT_TRUE(response != NULL); 522 ASSERT_EQ(407, response->headers->response_code()); 523 ASSERT_EQ("Proxy Authentication Required", 524 response->headers->GetStatusText()); 525} 526 527TEST_P(SpdyProxyClientSocketTest, ConnectWithAuthCredentials) { 528 scoped_ptr<SpdyFrame> conn(ConstructConnectAuthRequestFrame()); 529 MockWrite writes[] = { 530 CreateMockWrite(*conn, 0, SYNCHRONOUS), 531 }; 532 533 scoped_ptr<SpdyFrame> resp(ConstructConnectReplyFrame()); 534 MockRead reads[] = { 535 CreateMockRead(*resp, 1, ASYNC), 536 MockRead(ASYNC, 0, 2), // EOF 537 }; 538 539 Initialize(reads, arraysize(reads), writes, arraysize(writes)); 540 AddAuthToCache(); 541 542 AssertConnectSucceeds(); 543 544 AssertConnectionEstablished(); 545} 546 547TEST_P(SpdyProxyClientSocketTest, ConnectRedirects) { 548 scoped_ptr<SpdyFrame> conn(ConstructConnectRequestFrame()); 549 MockWrite writes[] = { 550 CreateMockWrite(*conn, 0, SYNCHRONOUS), 551 }; 552 553 scoped_ptr<SpdyFrame> resp(ConstructConnectRedirectReplyFrame()); 554 MockRead reads[] = { 555 CreateMockRead(*resp, 1, ASYNC), 556 MockRead(ASYNC, 0, 2), // EOF 557 }; 558 559 Initialize(reads, arraysize(reads), writes, arraysize(writes)); 560 561 AssertConnectFails(ERR_HTTPS_PROXY_TUNNEL_RESPONSE); 562 563 const HttpResponseInfo* response = sock_->GetConnectResponseInfo(); 564 ASSERT_TRUE(response != NULL); 565 566 const HttpResponseHeaders* headers = response->headers.get(); 567 ASSERT_EQ(302, headers->response_code()); 568 ASSERT_FALSE(headers->HasHeader("set-cookie")); 569 ASSERT_TRUE(headers->HasHeaderValue("content-length", "0")); 570 571 std::string location; 572 ASSERT_TRUE(headers->IsRedirect(&location)); 573 ASSERT_EQ(location, kRedirectUrl); 574} 575 576TEST_P(SpdyProxyClientSocketTest, ConnectFails) { 577 scoped_ptr<SpdyFrame> conn(ConstructConnectRequestFrame()); 578 MockWrite writes[] = { 579 CreateMockWrite(*conn, 0, SYNCHRONOUS), 580 }; 581 582 scoped_ptr<SpdyFrame> resp(ConstructConnectReplyFrame()); 583 MockRead reads[] = { 584 MockRead(ASYNC, 0, 1), // EOF 585 }; 586 587 Initialize(reads, arraysize(reads), writes, arraysize(writes)); 588 589 ASSERT_FALSE(sock_->IsConnected()); 590 591 AssertConnectFails(ERR_CONNECTION_CLOSED); 592 593 ASSERT_FALSE(sock_->IsConnected()); 594} 595 596// ----------- WasEverUsed 597 598TEST_P(SpdyProxyClientSocketTest, WasEverUsedReturnsCorrectValues) { 599 scoped_ptr<SpdyFrame> conn(ConstructConnectRequestFrame()); 600 MockWrite writes[] = { 601 CreateMockWrite(*conn, 0, SYNCHRONOUS), 602 }; 603 604 scoped_ptr<SpdyFrame> resp(ConstructConnectReplyFrame()); 605 MockRead reads[] = { 606 CreateMockRead(*resp, 1, ASYNC), 607 MockRead(ASYNC, 0, 2), // EOF 608 }; 609 610 Initialize(reads, arraysize(reads), writes, arraysize(writes)); 611 612 EXPECT_FALSE(sock_->WasEverUsed()); 613 AssertConnectSucceeds(); 614 EXPECT_TRUE(sock_->WasEverUsed()); 615 sock_->Disconnect(); 616 EXPECT_TRUE(sock_->WasEverUsed()); 617} 618 619// ----------- GetPeerAddress 620 621TEST_P(SpdyProxyClientSocketTest, GetPeerAddressReturnsCorrectValues) { 622 scoped_ptr<SpdyFrame> conn(ConstructConnectRequestFrame()); 623 MockWrite writes[] = { 624 CreateMockWrite(*conn, 0, SYNCHRONOUS), 625 }; 626 627 scoped_ptr<SpdyFrame> resp(ConstructConnectReplyFrame()); 628 MockRead reads[] = { 629 CreateMockRead(*resp, 1, ASYNC), 630 MockRead(ASYNC, 0, 2), // EOF 631 }; 632 633 Initialize(reads, arraysize(reads), writes, arraysize(writes)); 634 635 net::IPEndPoint addr; 636 EXPECT_EQ(ERR_SOCKET_NOT_CONNECTED, sock_->GetPeerAddress(&addr)); 637 638 AssertConnectSucceeds(); 639 EXPECT_TRUE(sock_->IsConnected()); 640 EXPECT_EQ(OK, sock_->GetPeerAddress(&addr)); 641 642 Run(1); 643 644 EXPECT_FALSE(sock_->IsConnected()); 645 EXPECT_EQ(ERR_SOCKET_NOT_CONNECTED, sock_->GetPeerAddress(&addr)); 646 647 sock_->Disconnect(); 648 649 EXPECT_EQ(ERR_SOCKET_NOT_CONNECTED, sock_->GetPeerAddress(&addr)); 650} 651 652// ----------- Write 653 654TEST_P(SpdyProxyClientSocketTest, WriteSendsDataInDataFrame) { 655 scoped_ptr<SpdyFrame> conn(ConstructConnectRequestFrame()); 656 scoped_ptr<SpdyFrame> msg1(ConstructBodyFrame(kMsg1, kLen1)); 657 scoped_ptr<SpdyFrame> msg2(ConstructBodyFrame(kMsg2, kLen2)); 658 MockWrite writes[] = { 659 CreateMockWrite(*conn, 0, SYNCHRONOUS), 660 CreateMockWrite(*msg1, 2, SYNCHRONOUS), 661 CreateMockWrite(*msg2, 3, SYNCHRONOUS), 662 }; 663 664 scoped_ptr<SpdyFrame> resp(ConstructConnectReplyFrame()); 665 MockRead reads[] = { 666 CreateMockRead(*resp, 1, ASYNC), 667 MockRead(ASYNC, 0, 4), // EOF 668 }; 669 670 Initialize(reads, arraysize(reads), writes, arraysize(writes)); 671 672 AssertConnectSucceeds(); 673 674 AssertAsyncWriteSucceeds(kMsg1, kLen1); 675 AssertAsyncWriteSucceeds(kMsg2, kLen2); 676} 677 678TEST_P(SpdyProxyClientSocketTest, WriteSplitsLargeDataIntoMultipleFrames) { 679 std::string chunk_data(kMaxSpdyFrameChunkSize, 'x'); 680 scoped_ptr<SpdyFrame> conn(ConstructConnectRequestFrame()); 681 scoped_ptr<SpdyFrame> chunk(ConstructBodyFrame(chunk_data.data(), 682 chunk_data.length())); 683 MockWrite writes[] = { 684 CreateMockWrite(*conn, 0, SYNCHRONOUS), 685 CreateMockWrite(*chunk, 2, SYNCHRONOUS), 686 CreateMockWrite(*chunk, 3, SYNCHRONOUS), 687 CreateMockWrite(*chunk, 4, SYNCHRONOUS) 688 }; 689 690 scoped_ptr<SpdyFrame> resp(ConstructConnectReplyFrame()); 691 MockRead reads[] = { 692 CreateMockRead(*resp, 1, ASYNC), 693 MockRead(ASYNC, 0, 5), // EOF 694 }; 695 696 Initialize(reads, arraysize(reads), writes, arraysize(writes)); 697 698 AssertConnectSucceeds(); 699 700 std::string big_data(kMaxSpdyFrameChunkSize * 3, 'x'); 701 scoped_refptr<IOBufferWithSize> buf(CreateBuffer(big_data.data(), 702 big_data.length())); 703 704 EXPECT_EQ(ERR_IO_PENDING, 705 sock_->Write(buf.get(), buf->size(), write_callback_.callback())); 706 data_->RunFor(3); 707 708 EXPECT_EQ(buf->size(), write_callback_.WaitForResult()); 709} 710 711// ----------- Read 712 713TEST_P(SpdyProxyClientSocketTest, ReadReadsDataInDataFrame) { 714 scoped_ptr<SpdyFrame> conn(ConstructConnectRequestFrame()); 715 MockWrite writes[] = { 716 CreateMockWrite(*conn, 0, SYNCHRONOUS), 717 }; 718 719 scoped_ptr<SpdyFrame> resp(ConstructConnectReplyFrame()); 720 scoped_ptr<SpdyFrame> msg1(ConstructBodyFrame(kMsg1, kLen1)); 721 MockRead reads[] = { 722 CreateMockRead(*resp, 1, ASYNC), 723 CreateMockRead(*msg1, 2, ASYNC), 724 MockRead(ASYNC, 0, 3), // EOF 725 }; 726 727 Initialize(reads, arraysize(reads), writes, arraysize(writes)); 728 729 AssertConnectSucceeds(); 730 731 Run(1); // SpdySession consumes the next read and sends it to 732 // sock_ to be buffered. 733 AssertSyncReadEquals(kMsg1, kLen1); 734} 735 736TEST_P(SpdyProxyClientSocketTest, ReadDataFromBufferedFrames) { 737 scoped_ptr<SpdyFrame> conn(ConstructConnectRequestFrame()); 738 MockWrite writes[] = { 739 CreateMockWrite(*conn, 0, SYNCHRONOUS), 740 }; 741 742 scoped_ptr<SpdyFrame> resp(ConstructConnectReplyFrame()); 743 scoped_ptr<SpdyFrame> msg1(ConstructBodyFrame(kMsg1, kLen1)); 744 scoped_ptr<SpdyFrame> msg2(ConstructBodyFrame(kMsg2, kLen2)); 745 MockRead reads[] = { 746 CreateMockRead(*resp, 1, ASYNC), 747 CreateMockRead(*msg1, 2, ASYNC), 748 CreateMockRead(*msg2, 3, ASYNC), 749 MockRead(ASYNC, 0, 4), // EOF 750 }; 751 752 Initialize(reads, arraysize(reads), writes, arraysize(writes)); 753 754 AssertConnectSucceeds(); 755 756 Run(1); // SpdySession consumes the next read and sends it to 757 // sock_ to be buffered. 758 AssertSyncReadEquals(kMsg1, kLen1); 759 Run(1); // SpdySession consumes the next read and sends it to 760 // sock_ to be buffered. 761 AssertSyncReadEquals(kMsg2, kLen2); 762} 763 764TEST_P(SpdyProxyClientSocketTest, ReadDataMultipleBufferedFrames) { 765 scoped_ptr<SpdyFrame> conn(ConstructConnectRequestFrame()); 766 MockWrite writes[] = { 767 CreateMockWrite(*conn, 0, SYNCHRONOUS), 768 }; 769 770 scoped_ptr<SpdyFrame> resp(ConstructConnectReplyFrame()); 771 scoped_ptr<SpdyFrame> msg1(ConstructBodyFrame(kMsg1, kLen1)); 772 scoped_ptr<SpdyFrame> msg2(ConstructBodyFrame(kMsg2, kLen2)); 773 MockRead reads[] = { 774 CreateMockRead(*resp, 1, ASYNC), 775 CreateMockRead(*msg1, 2, ASYNC), 776 CreateMockRead(*msg2, 3, ASYNC), 777 MockRead(ASYNC, 0, 4), // EOF 778 }; 779 780 Initialize(reads, arraysize(reads), writes, arraysize(writes)); 781 782 AssertConnectSucceeds(); 783 784 Run(2); // SpdySession consumes the next two reads and sends then to 785 // sock_ to be buffered. 786 AssertSyncReadEquals(kMsg1, kLen1); 787 AssertSyncReadEquals(kMsg2, kLen2); 788} 789 790TEST_P(SpdyProxyClientSocketTest, 791 LargeReadWillMergeDataFromDifferentFrames) { 792 scoped_ptr<SpdyFrame> conn(ConstructConnectRequestFrame()); 793 MockWrite writes[] = { 794 CreateMockWrite(*conn, 0, SYNCHRONOUS), 795 }; 796 797 scoped_ptr<SpdyFrame> resp(ConstructConnectReplyFrame()); 798 scoped_ptr<SpdyFrame> msg1(ConstructBodyFrame(kMsg1, kLen1)); 799 scoped_ptr<SpdyFrame> msg3(ConstructBodyFrame(kMsg3, kLen3)); 800 MockRead reads[] = { 801 CreateMockRead(*resp, 1, ASYNC), 802 CreateMockRead(*msg3, 2, ASYNC), 803 CreateMockRead(*msg3, 3, ASYNC), 804 MockRead(ASYNC, 0, 4), // EOF 805 }; 806 807 Initialize(reads, arraysize(reads), writes, arraysize(writes)); 808 809 AssertConnectSucceeds(); 810 811 Run(2); // SpdySession consumes the next two reads and sends then to 812 // sock_ to be buffered. 813 // The payload from two data frames, each with kMsg3 will be combined 814 // together into a single read(). 815 AssertSyncReadEquals(kMsg33, kLen33); 816} 817 818TEST_P(SpdyProxyClientSocketTest, MultipleShortReadsThenMoreRead) { 819 scoped_ptr<SpdyFrame> conn(ConstructConnectRequestFrame()); 820 MockWrite writes[] = { 821 CreateMockWrite(*conn, 0, SYNCHRONOUS), 822 }; 823 824 scoped_ptr<SpdyFrame> resp(ConstructConnectReplyFrame()); 825 scoped_ptr<SpdyFrame> msg1(ConstructBodyFrame(kMsg1, kLen1)); 826 scoped_ptr<SpdyFrame> msg3(ConstructBodyFrame(kMsg3, kLen3)); 827 scoped_ptr<SpdyFrame> msg2(ConstructBodyFrame(kMsg2, kLen2)); 828 MockRead reads[] = { 829 CreateMockRead(*resp, 1, ASYNC), 830 CreateMockRead(*msg1, 2, ASYNC), 831 CreateMockRead(*msg3, 3, ASYNC), 832 CreateMockRead(*msg3, 4, ASYNC), 833 CreateMockRead(*msg2, 5, ASYNC), 834 MockRead(ASYNC, 0, 6), // EOF 835 }; 836 837 Initialize(reads, arraysize(reads), writes, arraysize(writes)); 838 839 AssertConnectSucceeds(); 840 841 Run(4); // SpdySession consumes the next four reads and sends then to 842 // sock_ to be buffered. 843 AssertSyncReadEquals(kMsg1, kLen1); 844 // The payload from two data frames, each with kMsg3 will be combined 845 // together into a single read(). 846 AssertSyncReadEquals(kMsg33, kLen33); 847 AssertSyncReadEquals(kMsg2, kLen2); 848} 849 850TEST_P(SpdyProxyClientSocketTest, ReadWillSplitDataFromLargeFrame) { 851 scoped_ptr<SpdyFrame> conn(ConstructConnectRequestFrame()); 852 MockWrite writes[] = { 853 CreateMockWrite(*conn, 0, SYNCHRONOUS), 854 }; 855 856 scoped_ptr<SpdyFrame> resp(ConstructConnectReplyFrame()); 857 scoped_ptr<SpdyFrame> msg1(ConstructBodyFrame(kMsg1, kLen1)); 858 scoped_ptr<SpdyFrame> msg33(ConstructBodyFrame(kMsg33, kLen33)); 859 scoped_ptr<SpdyFrame> msg2(ConstructBodyFrame(kMsg2, kLen2)); 860 MockRead reads[] = { 861 CreateMockRead(*resp, 1, ASYNC), 862 CreateMockRead(*msg1, 2, ASYNC), 863 CreateMockRead(*msg33, 3, ASYNC), 864 MockRead(ASYNC, 0, 4), // EOF 865 }; 866 867 Initialize(reads, arraysize(reads), writes, arraysize(writes)); 868 869 AssertConnectSucceeds(); 870 871 Run(2); // SpdySession consumes the next two reads and sends then to 872 // sock_ to be buffered. 873 AssertSyncReadEquals(kMsg1, kLen1); 874 // The payload from the single large data frame will be read across 875 // two different reads. 876 AssertSyncReadEquals(kMsg3, kLen3); 877 AssertSyncReadEquals(kMsg3, kLen3); 878} 879 880TEST_P(SpdyProxyClientSocketTest, MultipleReadsFromSameLargeFrame) { 881 scoped_ptr<SpdyFrame> conn(ConstructConnectRequestFrame()); 882 MockWrite writes[] = { 883 CreateMockWrite(*conn, 0, SYNCHRONOUS), 884 }; 885 886 scoped_ptr<SpdyFrame> resp(ConstructConnectReplyFrame()); 887 scoped_ptr<SpdyFrame> msg333(ConstructBodyFrame(kMsg333, kLen333)); 888 MockRead reads[] = { 889 CreateMockRead(*resp, 1, ASYNC), 890 CreateMockRead(*msg333, 2, ASYNC), 891 MockRead(ASYNC, 0, 3), // EOF 892 }; 893 894 Initialize(reads, arraysize(reads), writes, arraysize(writes)); 895 896 AssertConnectSucceeds(); 897 898 Run(1); // SpdySession consumes the next read and sends it to 899 // sock_ to be buffered. 900 // The payload from the single large data frame will be read across 901 // two different reads. 902 AssertSyncReadEquals(kMsg33, kLen33); 903 904 // Now attempt to do a read of more data than remains buffered 905 scoped_refptr<IOBuffer> buf(new IOBuffer(kLen33)); 906 ASSERT_EQ(kLen3, sock_->Read(buf.get(), kLen33, read_callback_.callback())); 907 ASSERT_EQ(std::string(kMsg3, kLen3), std::string(buf->data(), kLen3)); 908 ASSERT_TRUE(sock_->IsConnected()); 909} 910 911TEST_P(SpdyProxyClientSocketTest, ReadAuthResponseBody) { 912 scoped_ptr<SpdyFrame> conn(ConstructConnectRequestFrame()); 913 MockWrite writes[] = { 914 CreateMockWrite(*conn, 0, SYNCHRONOUS), 915 }; 916 917 scoped_ptr<SpdyFrame> resp(ConstructConnectAuthReplyFrame()); 918 scoped_ptr<SpdyFrame> msg1(ConstructBodyFrame(kMsg1, kLen1)); 919 scoped_ptr<SpdyFrame> msg2(ConstructBodyFrame(kMsg2, kLen2)); 920 MockRead reads[] = { 921 CreateMockRead(*resp, 1, ASYNC), 922 CreateMockRead(*msg1, 2, ASYNC), 923 CreateMockRead(*msg2, 3, ASYNC), 924 MockRead(ASYNC, 0, 4), // EOF 925 }; 926 927 Initialize(reads, arraysize(reads), writes, arraysize(writes)); 928 929 AssertConnectFails(ERR_PROXY_AUTH_REQUESTED); 930 931 Run(2); // SpdySession consumes the next two reads and sends then to 932 // sock_ to be buffered. 933 AssertSyncReadEquals(kMsg1, kLen1); 934 AssertSyncReadEquals(kMsg2, kLen2); 935} 936 937TEST_P(SpdyProxyClientSocketTest, ReadErrorResponseBody) { 938 scoped_ptr<SpdyFrame> conn(ConstructConnectRequestFrame()); 939 MockWrite writes[] = { 940 CreateMockWrite(*conn, 0, SYNCHRONOUS), 941 }; 942 943 scoped_ptr<SpdyFrame> resp(ConstructConnectErrorReplyFrame()); 944 scoped_ptr<SpdyFrame> msg1(ConstructBodyFrame(kMsg1, kLen1)); 945 scoped_ptr<SpdyFrame> msg2(ConstructBodyFrame(kMsg2, kLen2)); 946 MockRead reads[] = { 947 CreateMockRead(*resp, 1, ASYNC), 948 CreateMockRead(*msg1, 2, ASYNC), 949 CreateMockRead(*msg2, 3, ASYNC), 950 MockRead(ASYNC, 0, 4), // EOF 951 }; 952 953 Initialize(reads, arraysize(reads), writes, arraysize(writes)); 954 955 AssertConnectFails(ERR_TUNNEL_CONNECTION_FAILED); 956} 957 958// ----------- Reads and Writes 959 960TEST_P(SpdyProxyClientSocketTest, AsyncReadAroundWrite) { 961 scoped_ptr<SpdyFrame> conn(ConstructConnectRequestFrame()); 962 scoped_ptr<SpdyFrame> msg2(ConstructBodyFrame(kMsg2, kLen2)); 963 MockWrite writes[] = { 964 CreateMockWrite(*conn, 0, SYNCHRONOUS), 965 CreateMockWrite(*msg2, 3, SYNCHRONOUS), 966 }; 967 968 scoped_ptr<SpdyFrame> resp(ConstructConnectReplyFrame()); 969 scoped_ptr<SpdyFrame> msg1(ConstructBodyFrame(kMsg1, kLen1)); 970 scoped_ptr<SpdyFrame> msg3(ConstructBodyFrame(kMsg3, kLen3)); 971 MockRead reads[] = { 972 CreateMockRead(*resp, 1, ASYNC), 973 CreateMockRead(*msg1, 2, ASYNC), // sync read 974 CreateMockRead(*msg3, 4, ASYNC), // async read 975 MockRead(ASYNC, 0, 5), // EOF 976 }; 977 978 Initialize(reads, arraysize(reads), writes, arraysize(writes)); 979 980 AssertConnectSucceeds(); 981 982 Run(1); 983 AssertSyncReadEquals(kMsg1, kLen1); 984 985 AssertReadStarts(kMsg3, kLen3); 986 // Read should block until after the write succeeds 987 988 AssertAsyncWriteSucceeds(kMsg2, kLen2); // Runs 1 step 989 990 ASSERT_FALSE(read_callback_.have_result()); 991 Run(1); 992 // Now the read will return 993 AssertReadReturns(kMsg3, kLen3); 994} 995 996TEST_P(SpdyProxyClientSocketTest, AsyncWriteAroundReads) { 997 scoped_ptr<SpdyFrame> conn(ConstructConnectRequestFrame()); 998 scoped_ptr<SpdyFrame> msg2(ConstructBodyFrame(kMsg2, kLen2)); 999 MockWrite writes[] = { 1000 CreateMockWrite(*conn, 0, SYNCHRONOUS), 1001 CreateMockWrite(*msg2, 4, ASYNC), 1002 }; 1003 1004 scoped_ptr<SpdyFrame> resp(ConstructConnectReplyFrame()); 1005 scoped_ptr<SpdyFrame> msg1(ConstructBodyFrame(kMsg1, kLen1)); 1006 scoped_ptr<SpdyFrame> msg3(ConstructBodyFrame(kMsg3, kLen3)); 1007 MockRead reads[] = { 1008 CreateMockRead(*resp, 1, ASYNC), 1009 CreateMockRead(*msg1, 2, ASYNC), 1010 CreateMockRead(*msg3, 3, ASYNC), 1011 MockRead(ASYNC, 0, 5), // EOF 1012 }; 1013 1014 Initialize(reads, arraysize(reads), writes, arraysize(writes)); 1015 1016 AssertConnectSucceeds(); 1017 1018 Run(1); 1019 AssertSyncReadEquals(kMsg1, kLen1); 1020 // Write should block until the read completes 1021 AssertWriteReturns(kMsg2, kLen2, ERR_IO_PENDING); 1022 1023 AssertAsyncReadEquals(kMsg3, kLen3); 1024 1025 ASSERT_FALSE(write_callback_.have_result()); 1026 1027 // Now the write will complete 1028 Run(1); 1029 AssertWriteLength(kLen2); 1030} 1031 1032// ----------- Reading/Writing on Closed socket 1033 1034// Reading from an already closed socket should return 0 1035TEST_P(SpdyProxyClientSocketTest, ReadOnClosedSocketReturnsZero) { 1036 scoped_ptr<SpdyFrame> conn(ConstructConnectRequestFrame()); 1037 MockWrite writes[] = { 1038 CreateMockWrite(*conn, 0, SYNCHRONOUS), 1039 }; 1040 1041 scoped_ptr<SpdyFrame> resp(ConstructConnectReplyFrame()); 1042 MockRead reads[] = { 1043 CreateMockRead(*resp, 1, ASYNC), 1044 MockRead(ASYNC, 0, 2), // EOF 1045 }; 1046 1047 Initialize(reads, arraysize(reads), writes, arraysize(writes)); 1048 1049 AssertConnectSucceeds(); 1050 1051 Run(1); 1052 1053 ASSERT_FALSE(sock_->IsConnected()); 1054 ASSERT_EQ(0, sock_->Read(NULL, 1, CompletionCallback())); 1055 ASSERT_EQ(0, sock_->Read(NULL, 1, CompletionCallback())); 1056 ASSERT_EQ(0, sock_->Read(NULL, 1, CompletionCallback())); 1057 ASSERT_FALSE(sock_->IsConnectedAndIdle()); 1058} 1059 1060// Read pending when socket is closed should return 0 1061TEST_P(SpdyProxyClientSocketTest, PendingReadOnCloseReturnsZero) { 1062 scoped_ptr<SpdyFrame> conn(ConstructConnectRequestFrame()); 1063 MockWrite writes[] = { 1064 CreateMockWrite(*conn, 0, SYNCHRONOUS), 1065 }; 1066 1067 scoped_ptr<SpdyFrame> resp(ConstructConnectReplyFrame()); 1068 MockRead reads[] = { 1069 CreateMockRead(*resp, 1, ASYNC), 1070 MockRead(ASYNC, 0, 2), // EOF 1071 }; 1072 1073 Initialize(reads, arraysize(reads), writes, arraysize(writes)); 1074 1075 AssertConnectSucceeds(); 1076 1077 AssertReadStarts(kMsg1, kLen1); 1078 1079 Run(1); 1080 1081 ASSERT_EQ(0, read_callback_.WaitForResult()); 1082} 1083 1084// Reading from a disconnected socket is an error 1085TEST_P(SpdyProxyClientSocketTest, 1086 ReadOnDisconnectSocketReturnsNotConnected) { 1087 scoped_ptr<SpdyFrame> conn(ConstructConnectRequestFrame()); 1088 MockWrite writes[] = { 1089 CreateMockWrite(*conn, 0, SYNCHRONOUS), 1090 }; 1091 1092 scoped_ptr<SpdyFrame> resp(ConstructConnectReplyFrame()); 1093 MockRead reads[] = { 1094 CreateMockRead(*resp, 1, ASYNC), 1095 MockRead(ASYNC, 0, 2), // EOF 1096 }; 1097 1098 Initialize(reads, arraysize(reads), writes, arraysize(writes)); 1099 1100 AssertConnectSucceeds(); 1101 1102 sock_->Disconnect(); 1103 1104 ASSERT_EQ(ERR_SOCKET_NOT_CONNECTED, 1105 sock_->Read(NULL, 1, CompletionCallback())); 1106} 1107 1108// Reading buffered data from an already closed socket should return 1109// buffered data, then 0. 1110TEST_P(SpdyProxyClientSocketTest, ReadOnClosedSocketReturnsBufferedData) { 1111 scoped_ptr<SpdyFrame> conn(ConstructConnectRequestFrame()); 1112 MockWrite writes[] = { 1113 CreateMockWrite(*conn, 0, SYNCHRONOUS), 1114 }; 1115 1116 scoped_ptr<SpdyFrame> resp(ConstructConnectReplyFrame()); 1117 scoped_ptr<SpdyFrame> msg1(ConstructBodyFrame(kMsg1, kLen1)); 1118 MockRead reads[] = { 1119 CreateMockRead(*resp, 1, ASYNC), 1120 CreateMockRead(*msg1, 2, ASYNC), 1121 MockRead(ASYNC, 0, 3), // EOF 1122 }; 1123 1124 Initialize(reads, arraysize(reads), writes, arraysize(writes)); 1125 1126 AssertConnectSucceeds(); 1127 1128 Run(2); 1129 1130 ASSERT_FALSE(sock_->IsConnected()); 1131 scoped_refptr<IOBuffer> buf(new IOBuffer(kLen1)); 1132 ASSERT_EQ(kLen1, sock_->Read(buf.get(), kLen1, CompletionCallback())); 1133 ASSERT_EQ(std::string(kMsg1, kLen1), std::string(buf->data(), kLen1)); 1134 1135 ASSERT_EQ(0, sock_->Read(NULL, 1, CompletionCallback())); 1136 ASSERT_EQ(0, sock_->Read(NULL, 1, CompletionCallback())); 1137 sock_->Disconnect(); 1138 ASSERT_EQ(ERR_SOCKET_NOT_CONNECTED, 1139 sock_->Read(NULL, 1, CompletionCallback())); 1140} 1141 1142// Calling Write() on a closed socket is an error 1143TEST_P(SpdyProxyClientSocketTest, WriteOnClosedStream) { 1144 scoped_ptr<SpdyFrame> conn(ConstructConnectRequestFrame()); 1145 MockWrite writes[] = { 1146 CreateMockWrite(*conn, 0, SYNCHRONOUS), 1147 }; 1148 1149 scoped_ptr<SpdyFrame> resp(ConstructConnectReplyFrame()); 1150 scoped_ptr<SpdyFrame> msg1(ConstructBodyFrame(kMsg1, kLen1)); 1151 MockRead reads[] = { 1152 CreateMockRead(*resp, 1, ASYNC), 1153 MockRead(ASYNC, 0, 2), // EOF 1154 }; 1155 1156 Initialize(reads, arraysize(reads), writes, arraysize(writes)); 1157 1158 AssertConnectSucceeds(); 1159 1160 Run(1); // Read EOF which will close the stream 1161 scoped_refptr<IOBufferWithSize> buf(CreateBuffer(kMsg1, kLen1)); 1162 EXPECT_EQ(ERR_SOCKET_NOT_CONNECTED, 1163 sock_->Write(buf.get(), buf->size(), CompletionCallback())); 1164} 1165 1166// Calling Write() on a disconnected socket is an error 1167TEST_P(SpdyProxyClientSocketTest, WriteOnDisconnectedSocket) { 1168 scoped_ptr<SpdyFrame> conn(ConstructConnectRequestFrame()); 1169 MockWrite writes[] = { 1170 CreateMockWrite(*conn, 0, SYNCHRONOUS), 1171 }; 1172 1173 scoped_ptr<SpdyFrame> resp(ConstructConnectReplyFrame()); 1174 scoped_ptr<SpdyFrame> msg1(ConstructBodyFrame(kMsg1, kLen1)); 1175 MockRead reads[] = { 1176 CreateMockRead(*resp, 1, ASYNC), 1177 MockRead(ASYNC, 0, 2), // EOF 1178 }; 1179 1180 Initialize(reads, arraysize(reads), writes, arraysize(writes)); 1181 1182 AssertConnectSucceeds(); 1183 1184 sock_->Disconnect(); 1185 1186 scoped_refptr<IOBufferWithSize> buf(CreateBuffer(kMsg1, kLen1)); 1187 EXPECT_EQ(ERR_SOCKET_NOT_CONNECTED, 1188 sock_->Write(buf.get(), buf->size(), CompletionCallback())); 1189} 1190 1191// If the socket is closed with a pending Write(), the callback 1192// should be called with ERR_CONNECTION_CLOSED. 1193TEST_P(SpdyProxyClientSocketTest, WritePendingOnClose) { 1194 scoped_ptr<SpdyFrame> conn(ConstructConnectRequestFrame()); 1195 MockWrite writes[] = { 1196 CreateMockWrite(*conn, 0, SYNCHRONOUS), 1197 MockWrite(ASYNC, ERR_IO_PENDING, 2), 1198 }; 1199 1200 scoped_ptr<SpdyFrame> resp(ConstructConnectReplyFrame()); 1201 MockRead reads[] = { 1202 CreateMockRead(*resp, 1, ASYNC), 1203 MockRead(ASYNC, 0, 3), // EOF 1204 }; 1205 1206 Initialize(reads, arraysize(reads), writes, arraysize(writes)); 1207 1208 AssertConnectSucceeds(); 1209 1210 EXPECT_TRUE(sock_->IsConnected()); 1211 1212 scoped_refptr<IOBufferWithSize> buf(CreateBuffer(kMsg1, kLen1)); 1213 EXPECT_EQ(ERR_IO_PENDING, 1214 sock_->Write(buf.get(), buf->size(), write_callback_.callback())); 1215 1216 Run(1); 1217 1218 EXPECT_EQ(ERR_CONNECTION_CLOSED, write_callback_.WaitForResult()); 1219} 1220 1221// If the socket is Disconnected with a pending Write(), the callback 1222// should not be called. 1223TEST_P(SpdyProxyClientSocketTest, DisconnectWithWritePending) { 1224 scoped_ptr<SpdyFrame> conn(ConstructConnectRequestFrame()); 1225 MockWrite writes[] = { 1226 CreateMockWrite(*conn, 0, SYNCHRONOUS), 1227 MockWrite(SYNCHRONOUS, 0, 2), // EOF 1228 }; 1229 1230 scoped_ptr<SpdyFrame> resp(ConstructConnectReplyFrame()); 1231 MockRead reads[] = { 1232 CreateMockRead(*resp, 1, ASYNC), 1233 MockRead(ASYNC, 0, 3), // EOF 1234 }; 1235 1236 Initialize(reads, arraysize(reads), writes, arraysize(writes)); 1237 1238 AssertConnectSucceeds(); 1239 1240 EXPECT_TRUE(sock_->IsConnected()); 1241 1242 scoped_refptr<IOBufferWithSize> buf(CreateBuffer(kMsg1, kLen1)); 1243 EXPECT_EQ(ERR_IO_PENDING, 1244 sock_->Write(buf.get(), buf->size(), write_callback_.callback())); 1245 1246 sock_->Disconnect(); 1247 1248 EXPECT_FALSE(sock_->IsConnected()); 1249 EXPECT_FALSE(write_callback_.have_result()); 1250} 1251 1252// If the socket is Disconnected with a pending Read(), the callback 1253// should not be called. 1254TEST_P(SpdyProxyClientSocketTest, DisconnectWithReadPending) { 1255 scoped_ptr<SpdyFrame> conn(ConstructConnectRequestFrame()); 1256 MockWrite writes[] = { 1257 CreateMockWrite(*conn, 0, SYNCHRONOUS), 1258 }; 1259 1260 scoped_ptr<SpdyFrame> resp(ConstructConnectReplyFrame()); 1261 MockRead reads[] = { 1262 CreateMockRead(*resp, 1, ASYNC), 1263 MockRead(ASYNC, 0, 2), // EOF 1264 }; 1265 1266 Initialize(reads, arraysize(reads), writes, arraysize(writes)); 1267 1268 AssertConnectSucceeds(); 1269 1270 EXPECT_TRUE(sock_->IsConnected()); 1271 1272 scoped_refptr<IOBuffer> buf(new IOBuffer(kLen1)); 1273 ASSERT_EQ(ERR_IO_PENDING, 1274 sock_->Read(buf.get(), kLen1, read_callback_.callback())); 1275 1276 sock_->Disconnect(); 1277 1278 EXPECT_FALSE(sock_->IsConnected()); 1279 EXPECT_FALSE(read_callback_.have_result()); 1280} 1281 1282// If the socket is Reset when both a read and write are pending, 1283// both should be called back. 1284TEST_P(SpdyProxyClientSocketTest, RstWithReadAndWritePending) { 1285 scoped_ptr<SpdyFrame> conn(ConstructConnectRequestFrame()); 1286 MockWrite writes[] = { 1287 CreateMockWrite(*conn, 0, SYNCHRONOUS), 1288 MockWrite(ASYNC, ERR_IO_PENDING, 2), 1289 }; 1290 1291 scoped_ptr<SpdyFrame> resp(ConstructConnectReplyFrame()); 1292 scoped_ptr<SpdyFrame> rst( 1293 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_CANCEL)); 1294 MockRead reads[] = { 1295 CreateMockRead(*resp, 1, ASYNC), 1296 CreateMockRead(*rst, 3, ASYNC), 1297 }; 1298 1299 Initialize(reads, arraysize(reads), writes, arraysize(writes)); 1300 1301 AssertConnectSucceeds(); 1302 1303 EXPECT_TRUE(sock_->IsConnected()); 1304 1305 scoped_refptr<IOBuffer> read_buf(new IOBuffer(kLen1)); 1306 ASSERT_EQ(ERR_IO_PENDING, 1307 sock_->Read(read_buf.get(), kLen1, read_callback_.callback())); 1308 1309 scoped_refptr<IOBufferWithSize> write_buf(CreateBuffer(kMsg1, kLen1)); 1310 EXPECT_EQ( 1311 ERR_IO_PENDING, 1312 sock_->Write( 1313 write_buf.get(), write_buf->size(), write_callback_.callback())); 1314 1315 Run(2); 1316 1317 EXPECT_TRUE(sock_.get()); 1318 EXPECT_TRUE(read_callback_.have_result()); 1319 EXPECT_TRUE(write_callback_.have_result()); 1320} 1321 1322// Makes sure the proxy client socket's source gets the expected NetLog events 1323// and only the expected NetLog events (No SpdySession events). 1324TEST_P(SpdyProxyClientSocketTest, NetLog) { 1325 scoped_ptr<SpdyFrame> conn(ConstructConnectRequestFrame()); 1326 MockWrite writes[] = { 1327 CreateMockWrite(*conn, 0, SYNCHRONOUS), 1328 }; 1329 1330 scoped_ptr<SpdyFrame> resp(ConstructConnectReplyFrame()); 1331 scoped_ptr<SpdyFrame> msg1(ConstructBodyFrame(kMsg1, kLen1)); 1332 MockRead reads[] = { 1333 CreateMockRead(*resp, 1, ASYNC), 1334 CreateMockRead(*msg1, 2, ASYNC), 1335 MockRead(ASYNC, 0, 3), // EOF 1336 }; 1337 1338 Initialize(reads, arraysize(reads), writes, arraysize(writes)); 1339 1340 AssertConnectSucceeds(); 1341 1342 Run(1); // SpdySession consumes the next read and sends it to 1343 // sock_ to be buffered. 1344 AssertSyncReadEquals(kMsg1, kLen1); 1345 1346 NetLog::Source sock_source = sock_->NetLog().source(); 1347 sock_.reset(); 1348 1349 CapturingNetLog::CapturedEntryList entry_list; 1350 net_log_.GetEntriesForSource(sock_source, &entry_list); 1351 1352 ASSERT_EQ(entry_list.size(), 10u); 1353 EXPECT_TRUE(LogContainsBeginEvent(entry_list, 0, NetLog::TYPE_SOCKET_ALIVE)); 1354 EXPECT_TRUE(LogContainsEvent(entry_list, 1, 1355 NetLog::TYPE_SPDY_PROXY_CLIENT_SESSION, 1356 NetLog::PHASE_NONE)); 1357 EXPECT_TRUE(LogContainsBeginEvent(entry_list, 2, 1358 NetLog::TYPE_HTTP_TRANSACTION_TUNNEL_SEND_REQUEST)); 1359 EXPECT_TRUE(LogContainsEvent(entry_list, 3, 1360 NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS, 1361 NetLog::PHASE_NONE)); 1362 EXPECT_TRUE(LogContainsEndEvent(entry_list, 4, 1363 NetLog::TYPE_HTTP_TRANSACTION_TUNNEL_SEND_REQUEST)); 1364 EXPECT_TRUE(LogContainsBeginEvent(entry_list, 5, 1365 NetLog::TYPE_HTTP_TRANSACTION_TUNNEL_READ_HEADERS)); 1366 EXPECT_TRUE(LogContainsEvent(entry_list, 6, 1367 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS, 1368 NetLog::PHASE_NONE)); 1369 EXPECT_TRUE(LogContainsEndEvent(entry_list, 7, 1370 NetLog::TYPE_HTTP_TRANSACTION_TUNNEL_READ_HEADERS)); 1371 EXPECT_TRUE(LogContainsEvent(entry_list, 8, 1372 NetLog::TYPE_SOCKET_BYTES_RECEIVED, 1373 NetLog::PHASE_NONE)); 1374 EXPECT_TRUE(LogContainsEndEvent(entry_list, 9, NetLog::TYPE_SOCKET_ALIVE)); 1375} 1376 1377// CompletionCallback that causes the SpdyProxyClientSocket to be 1378// deleted when Run is invoked. 1379class DeleteSockCallback : public TestCompletionCallbackBase { 1380 public: 1381 explicit DeleteSockCallback(scoped_ptr<SpdyProxyClientSocket>* sock) 1382 : sock_(sock), 1383 callback_(base::Bind(&DeleteSockCallback::OnComplete, 1384 base::Unretained(this))) { 1385 } 1386 1387 virtual ~DeleteSockCallback() { 1388 } 1389 1390 const CompletionCallback& callback() const { return callback_; } 1391 1392 private: 1393 void OnComplete(int result) { 1394 sock_->reset(NULL); 1395 SetResult(result); 1396 } 1397 1398 scoped_ptr<SpdyProxyClientSocket>* sock_; 1399 CompletionCallback callback_; 1400 1401 DISALLOW_COPY_AND_ASSIGN(DeleteSockCallback); 1402}; 1403 1404// If the socket is Reset when both a read and write are pending, and the 1405// read callback causes the socket to be deleted, the write callback should 1406// not be called. 1407TEST_P(SpdyProxyClientSocketTest, RstWithReadAndWritePendingDelete) { 1408 scoped_ptr<SpdyFrame> conn(ConstructConnectRequestFrame()); 1409 MockWrite writes[] = { 1410 CreateMockWrite(*conn, 0, SYNCHRONOUS), 1411 MockWrite(ASYNC, ERR_IO_PENDING, 2), 1412 }; 1413 1414 scoped_ptr<SpdyFrame> resp(ConstructConnectReplyFrame()); 1415 scoped_ptr<SpdyFrame> rst( 1416 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_CANCEL)); 1417 MockRead reads[] = { 1418 CreateMockRead(*resp, 1, ASYNC), 1419 CreateMockRead(*rst, 3, ASYNC), 1420 }; 1421 1422 Initialize(reads, arraysize(reads), writes, arraysize(writes)); 1423 1424 AssertConnectSucceeds(); 1425 1426 EXPECT_TRUE(sock_->IsConnected()); 1427 1428 DeleteSockCallback read_callback(&sock_); 1429 1430 scoped_refptr<IOBuffer> read_buf(new IOBuffer(kLen1)); 1431 ASSERT_EQ(ERR_IO_PENDING, 1432 sock_->Read(read_buf.get(), kLen1, read_callback.callback())); 1433 1434 scoped_refptr<IOBufferWithSize> write_buf(CreateBuffer(kMsg1, kLen1)); 1435 EXPECT_EQ( 1436 ERR_IO_PENDING, 1437 sock_->Write( 1438 write_buf.get(), write_buf->size(), write_callback_.callback())); 1439 1440 Run(2); 1441 1442 EXPECT_FALSE(sock_.get()); 1443 EXPECT_TRUE(read_callback.have_result()); 1444 EXPECT_FALSE(write_callback_.have_result()); 1445} 1446 1447} // namespace net 1448