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