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