1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #include "net/spdy/spdy_proxy_client_socket.h" 6 7 #include "base/utf_string_conversions.h" 8 #include "net/base/address_list.h" 9 #include "net/base/net_log.h" 10 #include "net/base/net_log_unittest.h" 11 #include "net/base/mock_host_resolver.h" 12 #include "net/base/test_completion_callback.h" 13 #include "net/base/winsock_init.h" 14 #include "net/http/http_response_info.h" 15 #include "net/http/http_response_headers.h" 16 #include "net/socket/client_socket_factory.h" 17 #include "net/socket/tcp_client_socket.h" 18 #include "net/socket/socket_test_util.h" 19 #include "net/spdy/spdy_http_utils.h" 20 #include "net/spdy/spdy_protocol.h" 21 #include "net/spdy/spdy_session_pool.h" 22 #include "net/spdy/spdy_test_util.h" 23 #include "testing/platform_test.h" 24 #include "testing/gtest/include/gtest/gtest.h" 25 26 //----------------------------------------------------------------------------- 27 28 namespace { 29 30 static const char kUrl[] = "https://www.google.com/"; 31 static const char kOriginHost[] = "www.google.com"; 32 static const int kOriginPort = 443; 33 static const char kOriginHostPort[] = "www.google.com:443"; 34 static const char kProxyUrl[] = "http://myproxy:6121/"; 35 static const char kProxyHost[] = "myproxy"; 36 static const int kProxyPort = 6121; 37 static const char kUserAgent[] = "Mozilla/1.0"; 38 39 static const int kStreamId = 1; 40 41 static const char kMsg1[] = "\0hello!\xff"; 42 static const int kLen1 = 8; 43 static const char kMsg2[] = "\012345678\0"; 44 static const int kLen2 = 10; 45 static const char kMsg3[] = "bye!"; 46 static const int kLen3 = 4; 47 static const char kMsg33[] = "bye!bye!"; 48 static const int kLen33 = kLen3 + kLen3; 49 static const char kMsg333[] = "bye!bye!bye!"; 50 static const int kLen333 = kLen3 + kLen3 + kLen3; 51 52 } // anonymous namespace 53 54 namespace net { 55 56 class SpdyProxyClientSocketTest : public PlatformTest { 57 public: 58 SpdyProxyClientSocketTest(); 59 60 virtual void TearDown(); 61 62 protected: 63 void Initialize(MockRead* reads, size_t reads_count, MockWrite* writes, 64 size_t writes_count); 65 spdy::SpdyFrame* ConstructConnectRequestFrame(); 66 spdy::SpdyFrame* ConstructConnectAuthRequestFrame(); 67 spdy::SpdyFrame* ConstructConnectReplyFrame(); 68 spdy::SpdyFrame* ConstructConnectAuthReplyFrame(); 69 spdy::SpdyFrame* ConstructConnectErrorReplyFrame(); 70 spdy::SpdyFrame* ConstructBodyFrame(const char* data, int length); 71 scoped_refptr<IOBufferWithSize> CreateBuffer(const char* data, int size); 72 void AssertConnectSucceeds(); 73 void AssertConnectFails(int result); 74 void AssertConnectionEstablished(); 75 void AssertSyncReadEquals(const char* data, int len); 76 void AssertAsyncReadEquals(const char* data, int len); 77 void AssertReadStarts(const char* data, int len); 78 void AssertReadReturns(const char* data, int len); 79 void AssertAsyncWriteSucceeds(const char* data, int len); 80 void AssertWriteReturns(const char* data, int len, int rv); 81 void AssertWriteLength(int len); 82 void AssertAsyncWriteWithReadsSucceeds(const char* data, int len, 83 int num_reads); 84 85 void AddAuthToCache() { 86 const string16 kFoo(ASCIIToUTF16("foo")); 87 const string16 kBar(ASCIIToUTF16("bar")); 88 session_->http_auth_cache()->Add(GURL(kProxyUrl), 89 "MyRealm1", 90 HttpAuth::AUTH_SCHEME_BASIC, 91 "Basic realm=MyRealm1", 92 kFoo, 93 kBar, 94 "/"); 95 } 96 97 void Run(int steps) { 98 data_->StopAfter(steps); 99 data_->Run(); 100 } 101 102 scoped_ptr<SpdyProxyClientSocket> sock_; 103 TestCompletionCallback read_callback_; 104 TestCompletionCallback write_callback_; 105 scoped_refptr<DeterministicSocketData> data_; 106 107 private: 108 scoped_refptr<HttpNetworkSession> session_; 109 scoped_refptr<IOBuffer> read_buf_; 110 SpdySessionDependencies session_deps_; 111 MockConnect connect_data_; 112 scoped_refptr<SpdySession> spdy_session_; 113 scoped_refptr<SpdyStream> spdy_stream_; 114 spdy::SpdyFramer framer_; 115 116 std::string user_agent_; 117 GURL url_; 118 HostPortPair proxy_host_port_; 119 HostPortPair endpoint_host_port_pair_; 120 ProxyServer proxy_; 121 HostPortProxyPair endpoint_host_port_proxy_pair_; 122 scoped_refptr<TransportSocketParams> transport_params_; 123 124 DISALLOW_COPY_AND_ASSIGN(SpdyProxyClientSocketTest); 125 }; 126 127 SpdyProxyClientSocketTest::SpdyProxyClientSocketTest() 128 : sock_(NULL), 129 read_callback_(), 130 write_callback_(), 131 data_(NULL), 132 session_(NULL), 133 read_buf_(NULL), 134 session_deps_(), 135 connect_data_(false, OK), 136 spdy_session_(NULL), 137 spdy_stream_(NULL), 138 framer_(), 139 user_agent_(kUserAgent), 140 url_(kUrl), 141 proxy_host_port_(kProxyHost, kProxyPort), 142 endpoint_host_port_pair_(kOriginHost, kOriginPort), 143 proxy_(ProxyServer::SCHEME_HTTPS, proxy_host_port_), 144 endpoint_host_port_proxy_pair_(endpoint_host_port_pair_, proxy_), 145 transport_params_(new TransportSocketParams(proxy_host_port_, 146 LOWEST, 147 url_, 148 false, 149 false)) { 150 } 151 152 void SpdyProxyClientSocketTest::TearDown() { 153 if (session_ != NULL) 154 session_->spdy_session_pool()->CloseAllSessions(); 155 156 spdy::SpdyFramer::set_enable_compression_default(true); 157 // Empty the current queue. 158 MessageLoop::current()->RunAllPending(); 159 PlatformTest::TearDown(); 160 } 161 162 void SpdyProxyClientSocketTest::Initialize(MockRead* reads, 163 size_t reads_count, 164 MockWrite* writes, 165 size_t writes_count) { 166 data_ = new DeterministicSocketData(reads, reads_count, writes, writes_count); 167 data_->set_connect_data(connect_data_); 168 data_->SetStop(2); 169 170 session_deps_.deterministic_socket_factory->AddSocketDataProvider( 171 data_.get()); 172 session_deps_.host_resolver->set_synchronous_mode(true); 173 174 session_ = SpdySessionDependencies::SpdyCreateSessionDeterministic( 175 &session_deps_); 176 SpdySession::SetSSLMode(false); 177 spdy::SpdyFramer::set_enable_compression_default(false); 178 179 // Creates a new spdy session 180 spdy_session_ = 181 session_->spdy_session_pool()->Get(endpoint_host_port_proxy_pair_, 182 BoundNetLog()); 183 184 // Perform the TCP connect 185 scoped_ptr<ClientSocketHandle> connection(new ClientSocketHandle); 186 EXPECT_EQ(OK, 187 connection->Init(endpoint_host_port_pair_.ToString(), 188 transport_params_, 189 LOWEST, NULL, session_->transport_socket_pool(), 190 BoundNetLog())); 191 spdy_session_->InitializeWithSocket(connection.release(), false, OK); 192 193 // Create the SPDY Stream 194 ASSERT_EQ( 195 OK, 196 spdy_session_->CreateStream(url_, LOWEST, &spdy_stream_, BoundNetLog(), 197 NULL)); 198 199 // Create the SpdyProxyClientSocket 200 sock_.reset( 201 new SpdyProxyClientSocket(spdy_stream_, user_agent_, 202 endpoint_host_port_pair_, url_, 203 proxy_host_port_, session_->http_auth_cache(), 204 session_->http_auth_handler_factory())); 205 } 206 207 scoped_refptr<IOBufferWithSize> SpdyProxyClientSocketTest::CreateBuffer( 208 const char* data, int size) { 209 scoped_refptr<IOBufferWithSize> buf(new IOBufferWithSize(size)); 210 memcpy(buf->data(), data, size); 211 return buf; 212 } 213 214 void SpdyProxyClientSocketTest::AssertConnectSucceeds() { 215 ASSERT_EQ(ERR_IO_PENDING, sock_->Connect(&read_callback_)); 216 data_->Run(); 217 ASSERT_EQ(OK, read_callback_.WaitForResult()); 218 } 219 220 void SpdyProxyClientSocketTest::AssertConnectFails(int result) { 221 ASSERT_EQ(ERR_IO_PENDING, sock_->Connect(&read_callback_)); 222 data_->Run(); 223 ASSERT_EQ(result, read_callback_.WaitForResult()); 224 } 225 226 void SpdyProxyClientSocketTest::AssertConnectionEstablished() { 227 const HttpResponseInfo* response = sock_->GetConnectResponseInfo(); 228 ASSERT_TRUE(response != NULL); 229 ASSERT_EQ(200, response->headers->response_code()); 230 ASSERT_EQ("Connection Established", response->headers->GetStatusText()); 231 } 232 233 void SpdyProxyClientSocketTest::AssertSyncReadEquals(const char* data, 234 int len) { 235 scoped_refptr<IOBuffer> buf(new IOBuffer(len)); 236 ASSERT_EQ(len, sock_->Read(buf, len, NULL)); 237 ASSERT_EQ(std::string(data, len), std::string(buf->data(), len)); 238 ASSERT_TRUE(sock_->IsConnected()); 239 } 240 241 void SpdyProxyClientSocketTest::AssertAsyncReadEquals(const char* data, 242 int len) { 243 data_->StopAfter(1); 244 // Issue the read, which will be completed asynchronously 245 scoped_refptr<IOBuffer> buf(new IOBuffer(len)); 246 ASSERT_EQ(ERR_IO_PENDING, sock_->Read(buf, len, &read_callback_)); 247 EXPECT_TRUE(sock_->IsConnected()); 248 data_->Run(); 249 250 EXPECT_TRUE(sock_->IsConnected()); 251 252 // Now the read will return 253 EXPECT_EQ(len, read_callback_.WaitForResult()); 254 ASSERT_EQ(std::string(data, len), std::string(buf->data(), len)); 255 } 256 257 void SpdyProxyClientSocketTest::AssertReadStarts(const char* data, int len) { 258 data_->StopAfter(1); 259 // Issue the read, which will be completed asynchronously 260 read_buf_ = new IOBuffer(len); 261 ASSERT_EQ(ERR_IO_PENDING, sock_->Read(read_buf_, len, &read_callback_)); 262 EXPECT_TRUE(sock_->IsConnected()); 263 } 264 265 void SpdyProxyClientSocketTest::AssertReadReturns(const char* data, int len) { 266 EXPECT_TRUE(sock_->IsConnected()); 267 268 // Now the read will return 269 EXPECT_EQ(len, read_callback_.WaitForResult()); 270 ASSERT_EQ(std::string(data, len), std::string(read_buf_->data(), len)); 271 } 272 273 void SpdyProxyClientSocketTest::AssertAsyncWriteSucceeds(const char* data, 274 int len) { 275 AssertWriteReturns(data, len, ERR_IO_PENDING); 276 data_->RunFor(1); 277 AssertWriteLength(len); 278 } 279 280 void SpdyProxyClientSocketTest::AssertWriteReturns(const char* data, int len, 281 int rv) { 282 scoped_refptr<IOBufferWithSize> buf(CreateBuffer(data, len)); 283 EXPECT_EQ(rv, sock_->Write(buf, buf->size(), &write_callback_)); 284 } 285 286 void SpdyProxyClientSocketTest::AssertWriteLength(int len) { 287 EXPECT_EQ(len, write_callback_.WaitForResult()); 288 } 289 290 void SpdyProxyClientSocketTest::AssertAsyncWriteWithReadsSucceeds( 291 const char* data, int len, int num_reads) { 292 scoped_refptr<IOBufferWithSize> buf(CreateBuffer(data, len)); 293 294 EXPECT_EQ(ERR_IO_PENDING, sock_->Write(buf, buf->size(), &write_callback_)); 295 296 for (int i = 0; i < num_reads; i++) { 297 Run(1); 298 AssertSyncReadEquals(kMsg2, kLen2); 299 } 300 301 write_callback_.WaitForResult(); 302 } 303 304 // Constructs a standard SPDY SYN_STREAM frame for a CONNECT request. 305 spdy::SpdyFrame* SpdyProxyClientSocketTest::ConstructConnectRequestFrame() { 306 const SpdyHeaderInfo kSynStartHeader = { 307 spdy::SYN_STREAM, 308 kStreamId, 309 0, 310 net::ConvertRequestPriorityToSpdyPriority(LOWEST), 311 spdy::CONTROL_FLAG_NONE, 312 false, 313 spdy::INVALID, 314 NULL, 315 0, 316 spdy::DATA_FLAG_NONE 317 }; 318 const char* const kConnectHeaders[] = { 319 "method", "CONNECT", 320 "url", kOriginHostPort, 321 "host", kOriginHost, 322 "user-agent", kUserAgent, 323 "version", "HTTP/1.1", 324 }; 325 return ConstructSpdyPacket( 326 kSynStartHeader, NULL, 0, kConnectHeaders, arraysize(kConnectHeaders)/2); 327 } 328 329 // Constructs a SPDY SYN_STREAM frame for a CONNECT request which includes 330 // Proxy-Authorization headers. 331 spdy::SpdyFrame* SpdyProxyClientSocketTest::ConstructConnectAuthRequestFrame() { 332 const SpdyHeaderInfo kSynStartHeader = { 333 spdy::SYN_STREAM, 334 kStreamId, 335 0, 336 net::ConvertRequestPriorityToSpdyPriority(LOWEST), 337 spdy::CONTROL_FLAG_NONE, 338 false, 339 spdy::INVALID, 340 NULL, 341 0, 342 spdy::DATA_FLAG_NONE 343 }; 344 const char* const kConnectHeaders[] = { 345 "method", "CONNECT", 346 "url", kOriginHostPort, 347 "host", kOriginHost, 348 "user-agent", kUserAgent, 349 "version", "HTTP/1.1", 350 "proxy-authorization", "Basic Zm9vOmJhcg==", 351 }; 352 return ConstructSpdyPacket( 353 kSynStartHeader, NULL, 0, kConnectHeaders, arraysize(kConnectHeaders)/2); 354 } 355 356 // Constructs a standard SPDY SYN_REPLY frame to match the SPDY CONNECT. 357 spdy::SpdyFrame* SpdyProxyClientSocketTest::ConstructConnectReplyFrame() { 358 const char* const kStandardReplyHeaders[] = { 359 "status", "200 Connection Established", 360 "version", "HTTP/1.1" 361 }; 362 return ConstructSpdyControlFrame(NULL, 363 0, 364 false, 365 kStreamId, 366 LOWEST, 367 spdy::SYN_REPLY, 368 spdy::CONTROL_FLAG_NONE, 369 kStandardReplyHeaders, 370 arraysize(kStandardReplyHeaders)); 371 } 372 373 // Constructs a standard SPDY SYN_REPLY frame to match the SPDY CONNECT. 374 spdy::SpdyFrame* SpdyProxyClientSocketTest::ConstructConnectAuthReplyFrame() { 375 const char* const kStandardReplyHeaders[] = { 376 "status", "407 Proxy Authentication Required", 377 "version", "HTTP/1.1", 378 "proxy-authenticate", "Basic realm=\"MyRealm1\"", 379 }; 380 381 return ConstructSpdyControlFrame(NULL, 382 0, 383 false, 384 kStreamId, 385 LOWEST, 386 spdy::SYN_REPLY, 387 spdy::CONTROL_FLAG_NONE, 388 kStandardReplyHeaders, 389 arraysize(kStandardReplyHeaders)); 390 } 391 392 // Constructs a SPDY SYN_REPLY frame with an HTTP 500 error. 393 spdy::SpdyFrame* SpdyProxyClientSocketTest::ConstructConnectErrorReplyFrame() { 394 const char* const kStandardReplyHeaders[] = { 395 "status", "500 Internal Server Error", 396 "version", "HTTP/1.1", 397 }; 398 399 return ConstructSpdyControlFrame(NULL, 400 0, 401 false, 402 kStreamId, 403 LOWEST, 404 spdy::SYN_REPLY, 405 spdy::CONTROL_FLAG_NONE, 406 kStandardReplyHeaders, 407 arraysize(kStandardReplyHeaders)); 408 } 409 410 spdy::SpdyFrame* SpdyProxyClientSocketTest::ConstructBodyFrame(const char* data, 411 int length) { 412 return framer_.CreateDataFrame(kStreamId, data, length, spdy::DATA_FLAG_NONE); 413 } 414 415 // ----------- Connect 416 417 TEST_F(SpdyProxyClientSocketTest, ConnectSendsCorrectRequest) { 418 scoped_ptr<spdy::SpdyFrame> conn(ConstructConnectRequestFrame()); 419 MockWrite writes[] = { 420 CreateMockWrite(*conn, 0, false), 421 }; 422 423 scoped_ptr<spdy::SpdyFrame> resp(ConstructConnectReplyFrame()); 424 MockRead reads[] = { 425 CreateMockRead(*resp, 1, true), 426 MockRead(true, 0, 3), // EOF 427 }; 428 429 Initialize(reads, arraysize(reads), writes, arraysize(writes)); 430 431 ASSERT_FALSE(sock_->IsConnected()); 432 433 AssertConnectSucceeds(); 434 435 AssertConnectionEstablished(); 436 } 437 438 TEST_F(SpdyProxyClientSocketTest, ConnectWithAuthRequested) { 439 scoped_ptr<spdy::SpdyFrame> conn(ConstructConnectRequestFrame()); 440 MockWrite writes[] = { 441 CreateMockWrite(*conn, 0, false), 442 }; 443 444 scoped_ptr<spdy::SpdyFrame> resp(ConstructConnectAuthReplyFrame()); 445 MockRead reads[] = { 446 CreateMockRead(*resp, 1, true), 447 MockRead(true, 0, 3), // EOF 448 }; 449 450 Initialize(reads, arraysize(reads), writes, arraysize(writes)); 451 452 AssertConnectFails(ERR_TUNNEL_CONNECTION_FAILED); 453 454 const HttpResponseInfo* response = sock_->GetConnectResponseInfo(); 455 ASSERT_TRUE(response != NULL); 456 ASSERT_EQ(407, response->headers->response_code()); 457 ASSERT_EQ("Proxy Authentication Required", 458 response->headers->GetStatusText()); 459 } 460 461 TEST_F(SpdyProxyClientSocketTest, ConnectWithAuthCredentials) { 462 scoped_ptr<spdy::SpdyFrame> conn(ConstructConnectAuthRequestFrame()); 463 MockWrite writes[] = { 464 CreateMockWrite(*conn, 0, false), 465 }; 466 467 scoped_ptr<spdy::SpdyFrame> resp(ConstructConnectReplyFrame()); 468 MockRead reads[] = { 469 CreateMockRead(*resp, 1, true), 470 MockRead(true, 0, 3), // EOF 471 }; 472 473 Initialize(reads, arraysize(reads), writes, arraysize(writes)); 474 AddAuthToCache(); 475 476 AssertConnectSucceeds(); 477 478 AssertConnectionEstablished(); 479 } 480 481 TEST_F(SpdyProxyClientSocketTest, ConnectFails) { 482 scoped_ptr<spdy::SpdyFrame> conn(ConstructConnectRequestFrame()); 483 MockWrite writes[] = { 484 CreateMockWrite(*conn, 0, false), 485 }; 486 487 scoped_ptr<spdy::SpdyFrame> resp(ConstructConnectReplyFrame()); 488 MockRead reads[] = { 489 MockRead(true, 0, 1), // EOF 490 }; 491 492 Initialize(reads, arraysize(reads), writes, arraysize(writes)); 493 494 ASSERT_FALSE(sock_->IsConnected()); 495 496 AssertConnectFails(ERR_CONNECTION_CLOSED); 497 498 ASSERT_FALSE(sock_->IsConnected()); 499 } 500 501 // ----------- WasEverUsed 502 503 TEST_F(SpdyProxyClientSocketTest, WasEverUsedReturnsCorrectValues) { 504 scoped_ptr<spdy::SpdyFrame> conn(ConstructConnectRequestFrame()); 505 MockWrite writes[] = { 506 CreateMockWrite(*conn, 0, false), 507 }; 508 509 scoped_ptr<spdy::SpdyFrame> resp(ConstructConnectReplyFrame()); 510 MockRead reads[] = { 511 CreateMockRead(*resp, 1, true), 512 MockRead(true, 0, 2), // EOF 513 }; 514 515 Initialize(reads, arraysize(reads), writes, arraysize(writes)); 516 517 EXPECT_FALSE(sock_->WasEverUsed()); 518 AssertConnectSucceeds(); 519 EXPECT_TRUE(sock_->WasEverUsed()); 520 sock_->Disconnect(); 521 EXPECT_TRUE(sock_->WasEverUsed()); 522 } 523 524 // ----------- GetPeerAddress 525 526 TEST_F(SpdyProxyClientSocketTest, GetPeerAddressReturnsCorrectValues) { 527 scoped_ptr<spdy::SpdyFrame> conn(ConstructConnectRequestFrame()); 528 MockWrite writes[] = { 529 CreateMockWrite(*conn, 0, false), 530 }; 531 532 scoped_ptr<spdy::SpdyFrame> resp(ConstructConnectReplyFrame()); 533 MockRead reads[] = { 534 CreateMockRead(*resp, 1, true), 535 MockRead(true, 0, 2), // EOF 536 }; 537 538 Initialize(reads, arraysize(reads), writes, arraysize(writes)); 539 540 net::AddressList addr; 541 EXPECT_EQ(ERR_SOCKET_NOT_CONNECTED, sock_->GetPeerAddress(&addr)); 542 543 AssertConnectSucceeds(); 544 EXPECT_TRUE(sock_->IsConnected()); 545 EXPECT_EQ(OK, sock_->GetPeerAddress(&addr)); 546 547 sock_->Disconnect(); 548 EXPECT_EQ(ERR_SOCKET_NOT_CONNECTED, sock_->GetPeerAddress(&addr)); 549 } 550 551 // ----------- Write 552 553 TEST_F(SpdyProxyClientSocketTest, WriteSendsDataInDataFrame) { 554 scoped_ptr<spdy::SpdyFrame> conn(ConstructConnectRequestFrame()); 555 scoped_ptr<spdy::SpdyFrame> msg1(ConstructBodyFrame(kMsg1, kLen1)); 556 scoped_ptr<spdy::SpdyFrame> msg2(ConstructBodyFrame(kMsg2, kLen2)); 557 MockWrite writes[] = { 558 CreateMockWrite(*conn, 0, false), 559 CreateMockWrite(*msg1, 2, false), 560 CreateMockWrite(*msg2, 3, false), 561 }; 562 563 scoped_ptr<spdy::SpdyFrame> resp(ConstructConnectReplyFrame()); 564 MockRead reads[] = { 565 CreateMockRead(*resp, 1, true), 566 MockRead(true, 0, 4), // EOF 567 }; 568 569 Initialize(reads, arraysize(reads), writes, arraysize(writes)); 570 571 AssertConnectSucceeds(); 572 573 AssertAsyncWriteSucceeds(kMsg1, kLen1); 574 AssertAsyncWriteSucceeds(kMsg2, kLen2); 575 } 576 577 TEST_F(SpdyProxyClientSocketTest, WriteSplitsLargeDataIntoMultipleFrames) { 578 std::string chunk_data(kMaxSpdyFrameChunkSize, 'x'); 579 scoped_ptr<spdy::SpdyFrame> conn(ConstructConnectRequestFrame()); 580 scoped_ptr<spdy::SpdyFrame> chunk(ConstructBodyFrame(chunk_data.data(), 581 chunk_data.length())); 582 MockWrite writes[] = { 583 CreateMockWrite(*conn, 0, false), 584 CreateMockWrite(*chunk, 2, false), 585 CreateMockWrite(*chunk, 3, false), 586 CreateMockWrite(*chunk, 4, false) 587 }; 588 589 scoped_ptr<spdy::SpdyFrame> resp(ConstructConnectReplyFrame()); 590 MockRead reads[] = { 591 CreateMockRead(*resp, 1, true), 592 MockRead(true, 0, 5), // EOF 593 }; 594 595 Initialize(reads, arraysize(reads), writes, arraysize(writes)); 596 597 AssertConnectSucceeds(); 598 599 std::string big_data(kMaxSpdyFrameChunkSize * 3, 'x'); 600 scoped_refptr<IOBufferWithSize> buf(CreateBuffer(big_data.data(), 601 big_data.length())); 602 603 EXPECT_EQ(ERR_IO_PENDING, sock_->Write(buf, buf->size(), &write_callback_)); 604 data_->RunFor(3); 605 606 EXPECT_EQ(buf->size(), write_callback_.WaitForResult()); 607 } 608 609 // ----------- Read 610 611 TEST_F(SpdyProxyClientSocketTest, ReadReadsDataInDataFrame) { 612 scoped_ptr<spdy::SpdyFrame> conn(ConstructConnectRequestFrame()); 613 MockWrite writes[] = { 614 CreateMockWrite(*conn, 0, false), 615 }; 616 617 scoped_ptr<spdy::SpdyFrame> resp(ConstructConnectReplyFrame()); 618 scoped_ptr<spdy::SpdyFrame> msg1(ConstructBodyFrame(kMsg1, kLen1)); 619 MockRead reads[] = { 620 CreateMockRead(*resp, 1, true), 621 CreateMockRead(*msg1, 2, true), 622 MockRead(true, 0, 3), // EOF 623 }; 624 625 Initialize(reads, arraysize(reads), writes, arraysize(writes)); 626 627 AssertConnectSucceeds(); 628 629 Run(1); // SpdySession consumes the next read and sends it to 630 // sock_ to be buffered. 631 AssertSyncReadEquals(kMsg1, kLen1); 632 } 633 634 TEST_F(SpdyProxyClientSocketTest, ReadDataFromBufferedFrames) { 635 scoped_ptr<spdy::SpdyFrame> conn(ConstructConnectRequestFrame()); 636 MockWrite writes[] = { 637 CreateMockWrite(*conn, 0, false), 638 }; 639 640 scoped_ptr<spdy::SpdyFrame> resp(ConstructConnectReplyFrame()); 641 scoped_ptr<spdy::SpdyFrame> msg1(ConstructBodyFrame(kMsg1, kLen1)); 642 scoped_ptr<spdy::SpdyFrame> msg2(ConstructBodyFrame(kMsg2, kLen2)); 643 MockRead reads[] = { 644 CreateMockRead(*resp, 1, true), 645 CreateMockRead(*msg1, 2, true), 646 CreateMockRead(*msg2, 3, true), 647 MockRead(true, 0, 4), // EOF 648 }; 649 650 Initialize(reads, arraysize(reads), writes, arraysize(writes)); 651 652 AssertConnectSucceeds(); 653 654 Run(1); // SpdySession consumes the next read and sends it to 655 // sock_ to be buffered. 656 AssertSyncReadEquals(kMsg1, kLen1); 657 Run(1); // SpdySession consumes the next read and sends it to 658 // sock_ to be buffered. 659 AssertSyncReadEquals(kMsg2, kLen2); 660 } 661 662 TEST_F(SpdyProxyClientSocketTest, ReadDataMultipleBufferedFrames) { 663 scoped_ptr<spdy::SpdyFrame> conn(ConstructConnectRequestFrame()); 664 MockWrite writes[] = { 665 CreateMockWrite(*conn, 0, false), 666 }; 667 668 scoped_ptr<spdy::SpdyFrame> resp(ConstructConnectReplyFrame()); 669 scoped_ptr<spdy::SpdyFrame> msg1(ConstructBodyFrame(kMsg1, kLen1)); 670 scoped_ptr<spdy::SpdyFrame> msg2(ConstructBodyFrame(kMsg2, kLen2)); 671 MockRead reads[] = { 672 CreateMockRead(*resp, 1, true), 673 CreateMockRead(*msg1, 2, true), 674 CreateMockRead(*msg2, 3, true), 675 MockRead(true, 0, 4), // EOF 676 }; 677 678 Initialize(reads, arraysize(reads), writes, arraysize(writes)); 679 680 AssertConnectSucceeds(); 681 682 Run(2); // SpdySession consumes the next two reads and sends then to 683 // sock_ to be buffered. 684 AssertSyncReadEquals(kMsg1, kLen1); 685 AssertSyncReadEquals(kMsg2, kLen2); 686 } 687 688 TEST_F(SpdyProxyClientSocketTest, LargeReadWillMergeDataFromDifferentFrames) { 689 scoped_ptr<spdy::SpdyFrame> conn(ConstructConnectRequestFrame()); 690 MockWrite writes[] = { 691 CreateMockWrite(*conn, 0, false), 692 }; 693 694 scoped_ptr<spdy::SpdyFrame> resp(ConstructConnectReplyFrame()); 695 scoped_ptr<spdy::SpdyFrame> msg1(ConstructBodyFrame(kMsg1, kLen1)); 696 scoped_ptr<spdy::SpdyFrame> msg3(ConstructBodyFrame(kMsg3, kLen3)); 697 MockRead reads[] = { 698 CreateMockRead(*resp, 1, true), 699 CreateMockRead(*msg3, 2, true), 700 CreateMockRead(*msg3, 3, true), 701 MockRead(true, 0, 4), // EOF 702 }; 703 704 Initialize(reads, arraysize(reads), writes, arraysize(writes)); 705 706 AssertConnectSucceeds(); 707 708 Run(2); // SpdySession consumes the next two reads and sends then to 709 // sock_ to be buffered. 710 // The payload from two data frames, each with kMsg3 will be combined 711 // together into a single read(). 712 AssertSyncReadEquals(kMsg33, kLen33); 713 } 714 715 TEST_F(SpdyProxyClientSocketTest, MultipleShortReadsThenMoreRead) { 716 scoped_ptr<spdy::SpdyFrame> conn(ConstructConnectRequestFrame()); 717 MockWrite writes[] = { 718 CreateMockWrite(*conn, 0, false), 719 }; 720 721 scoped_ptr<spdy::SpdyFrame> resp(ConstructConnectReplyFrame()); 722 scoped_ptr<spdy::SpdyFrame> msg1(ConstructBodyFrame(kMsg1, kLen1)); 723 scoped_ptr<spdy::SpdyFrame> msg3(ConstructBodyFrame(kMsg3, kLen3)); 724 scoped_ptr<spdy::SpdyFrame> msg2(ConstructBodyFrame(kMsg2, kLen2)); 725 MockRead reads[] = { 726 CreateMockRead(*resp, 1, true), 727 CreateMockRead(*msg1, 2, true), 728 CreateMockRead(*msg3, 3, true), 729 CreateMockRead(*msg3, 4, true), 730 CreateMockRead(*msg2, 5, true), 731 MockRead(true, 0, 6), // EOF 732 }; 733 734 Initialize(reads, arraysize(reads), writes, arraysize(writes)); 735 736 AssertConnectSucceeds(); 737 738 Run(4); // SpdySession consumes the next four reads and sends then to 739 // sock_ to be buffered. 740 AssertSyncReadEquals(kMsg1, kLen1); 741 // The payload from two data frames, each with kMsg3 will be combined 742 // together into a single read(). 743 AssertSyncReadEquals(kMsg33, kLen33); 744 AssertSyncReadEquals(kMsg2, kLen2); 745 } 746 747 TEST_F(SpdyProxyClientSocketTest, ReadWillSplitDataFromLargeFrame) { 748 scoped_ptr<spdy::SpdyFrame> conn(ConstructConnectRequestFrame()); 749 MockWrite writes[] = { 750 CreateMockWrite(*conn, 0, false), 751 }; 752 753 scoped_ptr<spdy::SpdyFrame> resp(ConstructConnectReplyFrame()); 754 scoped_ptr<spdy::SpdyFrame> msg1(ConstructBodyFrame(kMsg1, kLen1)); 755 scoped_ptr<spdy::SpdyFrame> msg33(ConstructBodyFrame(kMsg33, kLen33)); 756 scoped_ptr<spdy::SpdyFrame> msg2(ConstructBodyFrame(kMsg2, kLen2)); 757 MockRead reads[] = { 758 CreateMockRead(*resp, 1, true), 759 CreateMockRead(*msg1, 2, true), 760 CreateMockRead(*msg33, 3, true), 761 MockRead(true, 0, 4), // EOF 762 }; 763 764 Initialize(reads, arraysize(reads), writes, arraysize(writes)); 765 766 AssertConnectSucceeds(); 767 768 Run(2); // SpdySession consumes the next two reads and sends then to 769 // sock_ to be buffered. 770 AssertSyncReadEquals(kMsg1, kLen1); 771 // The payload from the single large data frame will be read across 772 // two different reads. 773 AssertSyncReadEquals(kMsg3, kLen3); 774 AssertSyncReadEquals(kMsg3, kLen3); 775 } 776 777 TEST_F(SpdyProxyClientSocketTest, MultipleReadsFromSameLargeFrame) { 778 scoped_ptr<spdy::SpdyFrame> conn(ConstructConnectRequestFrame()); 779 MockWrite writes[] = { 780 CreateMockWrite(*conn, 0, false), 781 }; 782 783 scoped_ptr<spdy::SpdyFrame> resp(ConstructConnectReplyFrame()); 784 scoped_ptr<spdy::SpdyFrame> msg333(ConstructBodyFrame(kMsg333, kLen333)); 785 MockRead reads[] = { 786 CreateMockRead(*resp, 1, true), 787 CreateMockRead(*msg333, 2, true), 788 MockRead(true, 0, 3), // EOF 789 }; 790 791 Initialize(reads, arraysize(reads), writes, arraysize(writes)); 792 793 AssertConnectSucceeds(); 794 795 Run(1); // SpdySession consumes the next read and sends it to 796 // sock_ to be buffered. 797 // The payload from the single large data frame will be read across 798 // two different reads. 799 AssertSyncReadEquals(kMsg33, kLen33); 800 801 // Now attempt to do a read of more data than remains buffered 802 scoped_refptr<IOBuffer> buf(new IOBuffer(kLen33)); 803 ASSERT_EQ(kLen3, sock_->Read(buf, kLen33, &read_callback_)); 804 ASSERT_EQ(std::string(kMsg3, kLen3), std::string(buf->data(), kLen3)); 805 ASSERT_TRUE(sock_->IsConnected()); 806 } 807 808 TEST_F(SpdyProxyClientSocketTest, ReadAuthResponseBody) { 809 scoped_ptr<spdy::SpdyFrame> conn(ConstructConnectRequestFrame()); 810 MockWrite writes[] = { 811 CreateMockWrite(*conn, 0, false), 812 }; 813 814 scoped_ptr<spdy::SpdyFrame> resp(ConstructConnectAuthReplyFrame()); 815 scoped_ptr<spdy::SpdyFrame> msg1(ConstructBodyFrame(kMsg1, kLen1)); 816 scoped_ptr<spdy::SpdyFrame> msg2(ConstructBodyFrame(kMsg2, kLen2)); 817 MockRead reads[] = { 818 CreateMockRead(*resp, 1, true), 819 CreateMockRead(*msg1, 2, true), 820 CreateMockRead(*msg2, 3, true), 821 MockRead(true, 0, 4), // EOF 822 }; 823 824 Initialize(reads, arraysize(reads), writes, arraysize(writes)); 825 826 AssertConnectFails(ERR_TUNNEL_CONNECTION_FAILED); 827 828 Run(2); // SpdySession consumes the next two reads and sends then to 829 // sock_ to be buffered. 830 AssertSyncReadEquals(kMsg1, kLen1); 831 AssertSyncReadEquals(kMsg2, kLen2); 832 } 833 834 TEST_F(SpdyProxyClientSocketTest, ReadErrorResponseBody) { 835 scoped_ptr<spdy::SpdyFrame> conn(ConstructConnectRequestFrame()); 836 MockWrite writes[] = { 837 CreateMockWrite(*conn, 0, false), 838 }; 839 840 scoped_ptr<spdy::SpdyFrame> resp(ConstructConnectErrorReplyFrame()); 841 scoped_ptr<spdy::SpdyFrame> msg1(ConstructBodyFrame(kMsg1, kLen1)); 842 scoped_ptr<spdy::SpdyFrame> msg2(ConstructBodyFrame(kMsg2, kLen2)); 843 MockRead reads[] = { 844 CreateMockRead(*resp, 1, true), 845 CreateMockRead(*msg1, 2, true), 846 CreateMockRead(*msg2, 3, true), 847 MockRead(true, 0, 4), // EOF 848 }; 849 850 Initialize(reads, arraysize(reads), writes, arraysize(writes)); 851 852 AssertConnectFails(ERR_HTTPS_PROXY_TUNNEL_RESPONSE); 853 854 Run(2); // SpdySession consumes the next two reads and sends then to 855 // sock_ to be buffered. 856 EXPECT_EQ(ERR_SOCKET_NOT_CONNECTED, sock_->Read(NULL, 1, NULL)); 857 scoped_refptr<IOBuffer> buf(new IOBuffer(kLen1 + kLen2)); 858 scoped_ptr<HttpStream> stream(sock_->CreateConnectResponseStream()); 859 stream->ReadResponseBody(buf, kLen1 + kLen2, &read_callback_); 860 } 861 862 // ----------- Reads and Writes 863 864 TEST_F(SpdyProxyClientSocketTest, AsyncReadAroundWrite) { 865 scoped_ptr<spdy::SpdyFrame> conn(ConstructConnectRequestFrame()); 866 scoped_ptr<spdy::SpdyFrame> msg2(ConstructBodyFrame(kMsg2, kLen2)); 867 MockWrite writes[] = { 868 CreateMockWrite(*conn, 0, false), 869 CreateMockWrite(*msg2, 3, false), 870 }; 871 872 scoped_ptr<spdy::SpdyFrame> resp(ConstructConnectReplyFrame()); 873 scoped_ptr<spdy::SpdyFrame> msg1(ConstructBodyFrame(kMsg1, kLen1)); 874 scoped_ptr<spdy::SpdyFrame> msg3(ConstructBodyFrame(kMsg3, kLen3)); 875 MockRead reads[] = { 876 CreateMockRead(*resp, 1, true), 877 CreateMockRead(*msg1, 2, true), // sync read 878 CreateMockRead(*msg3, 4, true), // async read 879 MockRead(true, 0, 5), // EOF 880 }; 881 882 Initialize(reads, arraysize(reads), writes, arraysize(writes)); 883 884 AssertConnectSucceeds(); 885 886 Run(1); 887 AssertSyncReadEquals(kMsg1, kLen1); 888 889 AssertReadStarts(kMsg3, kLen3); 890 // Read should block until after the write succeeds 891 892 AssertAsyncWriteSucceeds(kMsg2, kLen2); // Runs 1 step 893 894 ASSERT_FALSE(read_callback_.have_result()); 895 Run(1); 896 // Now the read will return 897 AssertReadReturns(kMsg3, kLen3); 898 } 899 900 TEST_F(SpdyProxyClientSocketTest, AsyncWriteAroundReads) { 901 scoped_ptr<spdy::SpdyFrame> conn(ConstructConnectRequestFrame()); 902 scoped_ptr<spdy::SpdyFrame> msg2(ConstructBodyFrame(kMsg2, kLen2)); 903 MockWrite writes[] = { 904 CreateMockWrite(*conn, 0, false), 905 CreateMockWrite(*msg2, 4, true), 906 }; 907 908 scoped_ptr<spdy::SpdyFrame> resp(ConstructConnectReplyFrame()); 909 scoped_ptr<spdy::SpdyFrame> msg1(ConstructBodyFrame(kMsg1, kLen1)); 910 scoped_ptr<spdy::SpdyFrame> msg3(ConstructBodyFrame(kMsg3, kLen3)); 911 MockRead reads[] = { 912 CreateMockRead(*resp, 1, true), 913 CreateMockRead(*msg1, 2, true), 914 CreateMockRead(*msg3, 3, true), 915 MockRead(true, 0, 5), // EOF 916 }; 917 918 Initialize(reads, arraysize(reads), writes, arraysize(writes)); 919 920 AssertConnectSucceeds(); 921 922 Run(1); 923 AssertSyncReadEquals(kMsg1, kLen1); 924 // Write should block until the read completes 925 AssertWriteReturns(kMsg2, kLen2, ERR_IO_PENDING); 926 927 AssertAsyncReadEquals(kMsg3, kLen3); 928 929 ASSERT_FALSE(write_callback_.have_result()); 930 931 // Now the write will complete 932 Run(1); 933 AssertWriteLength(kLen2); 934 } 935 936 // ----------- Reading/Writing on Closed socket 937 938 // Reading from an already closed socket should return 0 939 TEST_F(SpdyProxyClientSocketTest, ReadOnClosedSocketReturnsZero) { 940 scoped_ptr<spdy::SpdyFrame> conn(ConstructConnectRequestFrame()); 941 MockWrite writes[] = { 942 CreateMockWrite(*conn, 0, false), 943 }; 944 945 scoped_ptr<spdy::SpdyFrame> resp(ConstructConnectReplyFrame()); 946 MockRead reads[] = { 947 CreateMockRead(*resp, 1, true), 948 MockRead(true, 0, 2), // EOF 949 }; 950 951 Initialize(reads, arraysize(reads), writes, arraysize(writes)); 952 953 AssertConnectSucceeds(); 954 955 Run(1); 956 957 ASSERT_EQ(0, sock_->Read(NULL, 1, NULL)); 958 ASSERT_EQ(ERR_CONNECTION_CLOSED, sock_->Read(NULL, 1, NULL)); 959 ASSERT_EQ(ERR_CONNECTION_CLOSED, sock_->Read(NULL, 1, NULL)); 960 } 961 962 // Read pending when socket is closed should return 0 963 TEST_F(SpdyProxyClientSocketTest, PendingReadOnCloseReturnsZero) { 964 scoped_ptr<spdy::SpdyFrame> conn(ConstructConnectRequestFrame()); 965 MockWrite writes[] = { 966 CreateMockWrite(*conn, 0, false), 967 }; 968 969 scoped_ptr<spdy::SpdyFrame> resp(ConstructConnectReplyFrame()); 970 MockRead reads[] = { 971 CreateMockRead(*resp, 1, true), 972 MockRead(true, 0, 2), // EOF 973 }; 974 975 Initialize(reads, arraysize(reads), writes, arraysize(writes)); 976 977 AssertConnectSucceeds(); 978 979 AssertReadStarts(kMsg1, kLen1); 980 981 Run(1); 982 983 ASSERT_EQ(0, read_callback_.WaitForResult()); 984 } 985 986 // Reading from a disconnected socket is an error 987 TEST_F(SpdyProxyClientSocketTest, ReadOnDisconnectSocketReturnsNotConnected) { 988 scoped_ptr<spdy::SpdyFrame> conn(ConstructConnectRequestFrame()); 989 MockWrite writes[] = { 990 CreateMockWrite(*conn, 0, false), 991 }; 992 993 scoped_ptr<spdy::SpdyFrame> resp(ConstructConnectReplyFrame()); 994 MockRead reads[] = { 995 CreateMockRead(*resp, 1, true), 996 MockRead(true, 0, 2), // EOF 997 }; 998 999 Initialize(reads, arraysize(reads), writes, arraysize(writes)); 1000 1001 AssertConnectSucceeds(); 1002 1003 sock_->Disconnect(); 1004 1005 ASSERT_EQ(ERR_SOCKET_NOT_CONNECTED, sock_->Read(NULL, 1, NULL)); 1006 } 1007 1008 // Reading buffered data from an already closed socket should return 1009 // buffered data, then 0. 1010 TEST_F(SpdyProxyClientSocketTest, ReadOnClosedSocketReturnsBufferedData) { 1011 scoped_ptr<spdy::SpdyFrame> conn(ConstructConnectRequestFrame()); 1012 MockWrite writes[] = { 1013 CreateMockWrite(*conn, 0, false), 1014 }; 1015 1016 scoped_ptr<spdy::SpdyFrame> resp(ConstructConnectReplyFrame()); 1017 scoped_ptr<spdy::SpdyFrame> msg1(ConstructBodyFrame(kMsg1, kLen1)); 1018 MockRead reads[] = { 1019 CreateMockRead(*resp, 1, true), 1020 CreateMockRead(*msg1, 2, true), 1021 MockRead(true, 0, 3), // EOF 1022 }; 1023 1024 Initialize(reads, arraysize(reads), writes, arraysize(writes)); 1025 1026 AssertConnectSucceeds(); 1027 1028 Run(2); 1029 1030 AssertSyncReadEquals(kMsg1, kLen1); 1031 ASSERT_EQ(0, sock_->Read(NULL, 1, NULL)); 1032 ASSERT_EQ(ERR_CONNECTION_CLOSED, sock_->Read(NULL, 1, NULL)); 1033 // Verify that read *still* returns ERR_CONNECTION_CLOSED 1034 ASSERT_EQ(ERR_CONNECTION_CLOSED, sock_->Read(NULL, 1, NULL)); 1035 } 1036 1037 // Calling Write() on a closed socket is an error 1038 TEST_F(SpdyProxyClientSocketTest, WriteOnClosedStream) { 1039 scoped_ptr<spdy::SpdyFrame> conn(ConstructConnectRequestFrame()); 1040 MockWrite writes[] = { 1041 CreateMockWrite(*conn, 0, false), 1042 }; 1043 1044 scoped_ptr<spdy::SpdyFrame> resp(ConstructConnectReplyFrame()); 1045 scoped_ptr<spdy::SpdyFrame> msg1(ConstructBodyFrame(kMsg1, kLen1)); 1046 MockRead reads[] = { 1047 CreateMockRead(*resp, 1, true), 1048 MockRead(true, 0, 2), // EOF 1049 }; 1050 1051 Initialize(reads, arraysize(reads), writes, arraysize(writes)); 1052 1053 AssertConnectSucceeds(); 1054 1055 Run(1); // Read EOF which will close the stream 1056 scoped_refptr<IOBufferWithSize> buf(CreateBuffer(kMsg1, kLen1)); 1057 EXPECT_EQ(ERR_CONNECTION_CLOSED, sock_->Write(buf, buf->size(), NULL)); 1058 } 1059 1060 // Calling Write() on a disconnected socket is an error 1061 TEST_F(SpdyProxyClientSocketTest, WriteOnDisconnectedSocket) { 1062 scoped_ptr<spdy::SpdyFrame> conn(ConstructConnectRequestFrame()); 1063 MockWrite writes[] = { 1064 CreateMockWrite(*conn, 0, false), 1065 }; 1066 1067 scoped_ptr<spdy::SpdyFrame> resp(ConstructConnectReplyFrame()); 1068 scoped_ptr<spdy::SpdyFrame> msg1(ConstructBodyFrame(kMsg1, kLen1)); 1069 MockRead reads[] = { 1070 CreateMockRead(*resp, 1, true), 1071 MockRead(true, 0, 2), // EOF 1072 }; 1073 1074 Initialize(reads, arraysize(reads), writes, arraysize(writes)); 1075 1076 AssertConnectSucceeds(); 1077 1078 sock_->Disconnect(); 1079 1080 scoped_refptr<IOBufferWithSize> buf(CreateBuffer(kMsg1, kLen1)); 1081 EXPECT_EQ(ERR_SOCKET_NOT_CONNECTED, sock_->Write(buf, buf->size(), NULL)); 1082 } 1083 1084 // If the socket is closed with a pending Write(), the callback 1085 // should be called with ERR_CONNECTION_CLOSED. 1086 TEST_F(SpdyProxyClientSocketTest, WritePendingOnClose) { 1087 scoped_ptr<spdy::SpdyFrame> conn(ConstructConnectRequestFrame()); 1088 MockWrite writes[] = { 1089 CreateMockWrite(*conn, 0, false), 1090 MockWrite(true, ERR_IO_PENDING, 2), 1091 }; 1092 1093 scoped_ptr<spdy::SpdyFrame> resp(ConstructConnectReplyFrame()); 1094 MockRead reads[] = { 1095 CreateMockRead(*resp, 1, true), 1096 MockRead(true, 0, 3), // EOF 1097 }; 1098 1099 Initialize(reads, arraysize(reads), writes, arraysize(writes)); 1100 1101 AssertConnectSucceeds(); 1102 1103 EXPECT_TRUE(sock_->IsConnected()); 1104 1105 scoped_refptr<IOBufferWithSize> buf(CreateBuffer(kMsg1, kLen1)); 1106 EXPECT_EQ(ERR_IO_PENDING, sock_->Write(buf, buf->size(), &write_callback_)); 1107 1108 Run(1); 1109 1110 EXPECT_EQ(ERR_CONNECTION_CLOSED, write_callback_.WaitForResult()); 1111 } 1112 1113 // If the socket is Disconnected with a pending Write(), the callback 1114 // should not be called. 1115 TEST_F(SpdyProxyClientSocketTest, DisconnectWithWritePending) { 1116 scoped_ptr<spdy::SpdyFrame> conn(ConstructConnectRequestFrame()); 1117 MockWrite writes[] = { 1118 CreateMockWrite(*conn, 0, false), 1119 MockWrite(false, 0, 2), // EOF 1120 }; 1121 1122 scoped_ptr<spdy::SpdyFrame> resp(ConstructConnectReplyFrame()); 1123 MockRead reads[] = { 1124 CreateMockRead(*resp, 1, true), 1125 MockRead(true, 0, 3), // EOF 1126 }; 1127 1128 Initialize(reads, arraysize(reads), writes, arraysize(writes)); 1129 1130 AssertConnectSucceeds(); 1131 1132 EXPECT_TRUE(sock_->IsConnected()); 1133 1134 scoped_refptr<IOBufferWithSize> buf(CreateBuffer(kMsg1, kLen1)); 1135 EXPECT_EQ(ERR_IO_PENDING, sock_->Write(buf, buf->size(), &write_callback_)); 1136 1137 sock_->Disconnect(); 1138 1139 EXPECT_FALSE(sock_->IsConnected()); 1140 EXPECT_FALSE(write_callback_.have_result()); 1141 } 1142 1143 // If the socket is Disconnected with a pending Read(), the callback 1144 // should not be called. 1145 TEST_F(SpdyProxyClientSocketTest, DisconnectWithReadPending) { 1146 scoped_ptr<spdy::SpdyFrame> conn(ConstructConnectRequestFrame()); 1147 MockWrite writes[] = { 1148 CreateMockWrite(*conn, 0, false), 1149 }; 1150 1151 scoped_ptr<spdy::SpdyFrame> resp(ConstructConnectReplyFrame()); 1152 MockRead reads[] = { 1153 CreateMockRead(*resp, 1, true), 1154 MockRead(true, 0, 2), // EOF 1155 }; 1156 1157 Initialize(reads, arraysize(reads), writes, arraysize(writes)); 1158 1159 AssertConnectSucceeds(); 1160 1161 EXPECT_TRUE(sock_->IsConnected()); 1162 1163 scoped_refptr<IOBuffer> buf(new IOBuffer(kLen1)); 1164 ASSERT_EQ(ERR_IO_PENDING, sock_->Read(buf, kLen1, &read_callback_)); 1165 1166 sock_->Disconnect(); 1167 1168 EXPECT_FALSE(sock_->IsConnected()); 1169 EXPECT_FALSE(read_callback_.have_result()); 1170 } 1171 1172 } // namespace net 1173