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 void PopulateConnectRequestIR(SpdySynStreamIR* syn_ir); 75 void PopulateConnectReplyIR(SpdySynReplyIR* reply_ir, const char* status); 76 SpdyFrame* ConstructConnectRequestFrame(); 77 SpdyFrame* ConstructConnectAuthRequestFrame(); 78 SpdyFrame* ConstructConnectReplyFrame(); 79 SpdyFrame* ConstructConnectAuthReplyFrame(); 80 SpdyFrame* ConstructConnectRedirectReplyFrame(); 81 SpdyFrame* ConstructConnectErrorReplyFrame(); 82 SpdyFrame* ConstructBodyFrame(const char* data, int length); 83 scoped_refptr<IOBufferWithSize> CreateBuffer(const char* data, int size); 84 void AssertConnectSucceeds(); 85 void AssertConnectFails(int result); 86 void AssertConnectionEstablished(); 87 void AssertSyncReadEquals(const char* data, int len); 88 void AssertAsyncReadEquals(const char* data, int len); 89 void AssertReadStarts(const char* data, int len); 90 void AssertReadReturns(const char* data, int len); 91 void AssertAsyncWriteSucceeds(const char* data, int len); 92 void AssertWriteReturns(const char* data, int len, int rv); 93 void AssertWriteLength(int len); 94 void AssertAsyncWriteWithReadsSucceeds(const char* data, int len, 95 int num_reads); 96 97 void AddAuthToCache() { 98 const base::string16 kFoo(base::ASCIIToUTF16("foo")); 99 const base::string16 kBar(base::ASCIIToUTF16("bar")); 100 session_->http_auth_cache()->Add(GURL(kProxyUrl), 101 "MyRealm1", 102 HttpAuth::AUTH_SCHEME_BASIC, 103 "Basic realm=MyRealm1", 104 AuthCredentials(kFoo, kBar), 105 "/"); 106 } 107 108 void Run(int steps) { 109 data_->StopAfter(steps); 110 data_->Run(); 111 } 112 113 void CloseSpdySession(net::Error error, const std::string& description) { 114 spdy_session_->CloseSessionOnError(error, description); 115 } 116 117 SpdyTestUtil spdy_util_; 118 scoped_ptr<SpdyProxyClientSocket> sock_; 119 TestCompletionCallback read_callback_; 120 TestCompletionCallback write_callback_; 121 scoped_ptr<DeterministicSocketData> data_; 122 CapturingBoundNetLog net_log_; 123 124 private: 125 scoped_refptr<HttpNetworkSession> session_; 126 scoped_refptr<IOBuffer> read_buf_; 127 SpdySessionDependencies session_deps_; 128 MockConnect connect_data_; 129 base::WeakPtr<SpdySession> spdy_session_; 130 BufferedSpdyFramer framer_; 131 132 std::string user_agent_; 133 GURL url_; 134 HostPortPair proxy_host_port_; 135 HostPortPair endpoint_host_port_pair_; 136 ProxyServer proxy_; 137 SpdySessionKey endpoint_spdy_session_key_; 138 139 DISALLOW_COPY_AND_ASSIGN(SpdyProxyClientSocketTest); 140 }; 141 142 INSTANTIATE_TEST_CASE_P( 143 NextProto, 144 SpdyProxyClientSocketTest, 145 testing::Values(kProtoDeprecatedSPDY2, 146 kProtoSPDY3, kProtoSPDY31, kProtoSPDY4)); 147 148 SpdyProxyClientSocketTest::SpdyProxyClientSocketTest() 149 : spdy_util_(GetParam()), 150 session_(NULL), 151 read_buf_(NULL), 152 session_deps_(GetParam()), 153 connect_data_(SYNCHRONOUS, OK), 154 framer_(spdy_util_.spdy_version(), false), 155 user_agent_(kUserAgent), 156 url_(kRequestUrl), 157 proxy_host_port_(kProxyHost, kProxyPort), 158 endpoint_host_port_pair_(kOriginHost, kOriginPort), 159 proxy_(ProxyServer::SCHEME_HTTPS, proxy_host_port_), 160 endpoint_spdy_session_key_(endpoint_host_port_pair_, 161 proxy_, 162 PRIVACY_MODE_DISABLED) { 163 session_deps_.net_log = net_log_.bound().net_log(); 164 } 165 166 void SpdyProxyClientSocketTest::TearDown() { 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 } 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 void SpdyProxyClientSocketTest::PopulateConnectRequestIR( 314 SpdySynStreamIR* syn_ir) { 315 spdy_util_.SetPriority(LOWEST, syn_ir); 316 syn_ir->SetHeader(spdy_util_.GetMethodKey(), "CONNECT"); 317 syn_ir->SetHeader(spdy_util_.GetPathKey(), kOriginHostPort); 318 syn_ir->SetHeader(spdy_util_.GetHostKey(), kOriginHost); 319 syn_ir->SetHeader("user-agent", kUserAgent); 320 spdy_util_.MaybeAddVersionHeader(syn_ir); 321 } 322 323 void SpdyProxyClientSocketTest::PopulateConnectReplyIR(SpdySynReplyIR* reply_ir, 324 const char* status) { 325 reply_ir->SetHeader(spdy_util_.GetStatusKey(), status); 326 spdy_util_.MaybeAddVersionHeader(reply_ir); 327 } 328 329 // Constructs a standard SPDY SYN_STREAM frame for a CONNECT request. 330 SpdyFrame* 331 SpdyProxyClientSocketTest::ConstructConnectRequestFrame() { 332 SpdySynStreamIR syn_ir(kStreamId); 333 PopulateConnectRequestIR(&syn_ir); 334 return spdy_util_.CreateFramer(false)->SerializeFrame(syn_ir); 335 } 336 337 // Constructs a SPDY SYN_STREAM frame for a CONNECT request which includes 338 // Proxy-Authorization headers. 339 SpdyFrame* SpdyProxyClientSocketTest::ConstructConnectAuthRequestFrame() { 340 SpdySynStreamIR syn_ir(kStreamId); 341 PopulateConnectRequestIR(&syn_ir); 342 syn_ir.SetHeader("proxy-authorization", "Basic Zm9vOmJhcg=="); 343 return spdy_util_.CreateFramer(false)->SerializeFrame(syn_ir); 344 } 345 346 // Constructs a standard SPDY SYN_REPLY frame to match the SPDY CONNECT. 347 SpdyFrame* SpdyProxyClientSocketTest::ConstructConnectReplyFrame() { 348 SpdySynReplyIR reply_ir(kStreamId); 349 PopulateConnectReplyIR(&reply_ir, "200"); 350 return spdy_util_.CreateFramer(false)->SerializeFrame(reply_ir); 351 } 352 353 // Constructs a standard SPDY SYN_REPLY frame to match the SPDY CONNECT, 354 // including Proxy-Authenticate headers. 355 SpdyFrame* SpdyProxyClientSocketTest::ConstructConnectAuthReplyFrame() { 356 SpdySynReplyIR reply_ir(kStreamId); 357 PopulateConnectReplyIR(&reply_ir, "407"); 358 reply_ir.SetHeader("proxy-authenticate", "Basic realm=\"MyRealm1\""); 359 return framer_.SerializeFrame(reply_ir); 360 } 361 362 // Constructs a SPDY SYN_REPLY frame with an HTTP 302 redirect. 363 SpdyFrame* SpdyProxyClientSocketTest::ConstructConnectRedirectReplyFrame() { 364 SpdySynReplyIR reply_ir(kStreamId); 365 PopulateConnectReplyIR(&reply_ir, "302"); 366 reply_ir.SetHeader("location", kRedirectUrl); 367 reply_ir.SetHeader("set-cookie", "foo=bar"); 368 return framer_.SerializeFrame(reply_ir); 369 } 370 371 // Constructs a SPDY SYN_REPLY frame with an HTTP 500 error. 372 SpdyFrame* SpdyProxyClientSocketTest::ConstructConnectErrorReplyFrame() { 373 SpdySynReplyIR reply_ir(kStreamId); 374 PopulateConnectReplyIR(&reply_ir, "500"); 375 return framer_.SerializeFrame(reply_ir); 376 } 377 378 SpdyFrame* SpdyProxyClientSocketTest::ConstructBodyFrame( 379 const char* data, 380 int length) { 381 return framer_.CreateDataFrame(kStreamId, data, length, DATA_FLAG_NONE); 382 } 383 384 // ----------- Connect 385 386 TEST_P(SpdyProxyClientSocketTest, ConnectSendsCorrectRequest) { 387 scoped_ptr<SpdyFrame> conn(ConstructConnectRequestFrame()); 388 MockWrite writes[] = { 389 CreateMockWrite(*conn, 0, SYNCHRONOUS), 390 }; 391 392 scoped_ptr<SpdyFrame> resp(ConstructConnectReplyFrame()); 393 MockRead reads[] = { 394 CreateMockRead(*resp, 1, ASYNC), 395 MockRead(ASYNC, 0, 2), // EOF 396 }; 397 398 Initialize(reads, arraysize(reads), writes, arraysize(writes)); 399 400 ASSERT_FALSE(sock_->IsConnected()); 401 402 AssertConnectSucceeds(); 403 404 AssertConnectionEstablished(); 405 } 406 407 TEST_P(SpdyProxyClientSocketTest, ConnectWithAuthRequested) { 408 scoped_ptr<SpdyFrame> conn(ConstructConnectRequestFrame()); 409 MockWrite writes[] = { 410 CreateMockWrite(*conn, 0, SYNCHRONOUS), 411 }; 412 413 scoped_ptr<SpdyFrame> resp(ConstructConnectAuthReplyFrame()); 414 MockRead reads[] = { 415 CreateMockRead(*resp, 1, ASYNC), 416 MockRead(ASYNC, 0, 2), // EOF 417 }; 418 419 Initialize(reads, arraysize(reads), writes, arraysize(writes)); 420 421 AssertConnectFails(ERR_PROXY_AUTH_REQUESTED); 422 423 const HttpResponseInfo* response = sock_->GetConnectResponseInfo(); 424 ASSERT_TRUE(response != NULL); 425 ASSERT_EQ(407, response->headers->response_code()); 426 } 427 428 TEST_P(SpdyProxyClientSocketTest, ConnectWithAuthCredentials) { 429 scoped_ptr<SpdyFrame> conn(ConstructConnectAuthRequestFrame()); 430 MockWrite writes[] = { 431 CreateMockWrite(*conn, 0, SYNCHRONOUS), 432 }; 433 434 scoped_ptr<SpdyFrame> resp(ConstructConnectReplyFrame()); 435 MockRead reads[] = { 436 CreateMockRead(*resp, 1, ASYNC), 437 MockRead(ASYNC, 0, 2), // EOF 438 }; 439 440 Initialize(reads, arraysize(reads), writes, arraysize(writes)); 441 AddAuthToCache(); 442 443 AssertConnectSucceeds(); 444 445 AssertConnectionEstablished(); 446 } 447 448 TEST_P(SpdyProxyClientSocketTest, ConnectRedirects) { 449 scoped_ptr<SpdyFrame> conn(ConstructConnectRequestFrame()); 450 scoped_ptr<SpdyFrame> rst( 451 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_CANCEL)); 452 MockWrite writes[] = { 453 CreateMockWrite(*conn, 0, SYNCHRONOUS), CreateMockWrite(*rst, 2), 454 }; 455 456 scoped_ptr<SpdyFrame> resp(ConstructConnectRedirectReplyFrame()); 457 MockRead reads[] = { 458 CreateMockRead(*resp, 1, ASYNC), MockRead(ASYNC, 0, 3), // EOF 459 }; 460 461 Initialize(reads, arraysize(reads), writes, arraysize(writes)); 462 463 AssertConnectFails(ERR_HTTPS_PROXY_TUNNEL_RESPONSE); 464 465 const HttpResponseInfo* response = sock_->GetConnectResponseInfo(); 466 ASSERT_TRUE(response != NULL); 467 468 const HttpResponseHeaders* headers = response->headers.get(); 469 ASSERT_EQ(302, headers->response_code()); 470 ASSERT_FALSE(headers->HasHeader("set-cookie")); 471 ASSERT_TRUE(headers->HasHeaderValue("content-length", "0")); 472 473 std::string location; 474 ASSERT_TRUE(headers->IsRedirect(&location)); 475 ASSERT_EQ(location, kRedirectUrl); 476 477 // Let the RST_STREAM write while |rst| is in-scope. 478 base::MessageLoop::current()->RunUntilIdle(); 479 } 480 481 TEST_P(SpdyProxyClientSocketTest, ConnectFails) { 482 scoped_ptr<SpdyFrame> conn(ConstructConnectRequestFrame()); 483 MockWrite writes[] = { 484 CreateMockWrite(*conn, 0, SYNCHRONOUS), 485 }; 486 487 scoped_ptr<SpdyFrame> resp(ConstructConnectReplyFrame()); 488 MockRead reads[] = { 489 MockRead(ASYNC, 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_P(SpdyProxyClientSocketTest, WasEverUsedReturnsCorrectValues) { 504 scoped_ptr<SpdyFrame> conn(ConstructConnectRequestFrame()); 505 scoped_ptr<SpdyFrame> rst( 506 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_CANCEL)); 507 MockWrite writes[] = { 508 CreateMockWrite(*conn, 0, SYNCHRONOUS), CreateMockWrite(*rst, 2), 509 }; 510 511 scoped_ptr<SpdyFrame> resp(ConstructConnectReplyFrame()); 512 MockRead reads[] = { 513 CreateMockRead(*resp, 1, ASYNC), MockRead(ASYNC, 0, 3), // EOF 514 }; 515 516 Initialize(reads, arraysize(reads), writes, arraysize(writes)); 517 518 EXPECT_FALSE(sock_->WasEverUsed()); 519 AssertConnectSucceeds(); 520 EXPECT_TRUE(sock_->WasEverUsed()); 521 sock_->Disconnect(); 522 EXPECT_TRUE(sock_->WasEverUsed()); 523 524 // Let the RST_STREAM write while |rst| is in-scope. 525 base::MessageLoop::current()->RunUntilIdle(); 526 } 527 528 // ----------- GetPeerAddress 529 530 TEST_P(SpdyProxyClientSocketTest, GetPeerAddressReturnsCorrectValues) { 531 scoped_ptr<SpdyFrame> conn(ConstructConnectRequestFrame()); 532 MockWrite writes[] = { 533 CreateMockWrite(*conn, 0, SYNCHRONOUS), 534 }; 535 536 scoped_ptr<SpdyFrame> resp(ConstructConnectReplyFrame()); 537 MockRead reads[] = { 538 CreateMockRead(*resp, 1, ASYNC), 539 MockRead(ASYNC, 0, 2), // EOF 540 }; 541 542 Initialize(reads, arraysize(reads), writes, arraysize(writes)); 543 544 net::IPEndPoint addr; 545 EXPECT_EQ(ERR_SOCKET_NOT_CONNECTED, sock_->GetPeerAddress(&addr)); 546 547 AssertConnectSucceeds(); 548 EXPECT_TRUE(sock_->IsConnected()); 549 EXPECT_EQ(OK, sock_->GetPeerAddress(&addr)); 550 551 Run(1); 552 553 EXPECT_FALSE(sock_->IsConnected()); 554 EXPECT_EQ(ERR_SOCKET_NOT_CONNECTED, sock_->GetPeerAddress(&addr)); 555 556 sock_->Disconnect(); 557 558 EXPECT_EQ(ERR_SOCKET_NOT_CONNECTED, sock_->GetPeerAddress(&addr)); 559 } 560 561 // ----------- Write 562 563 TEST_P(SpdyProxyClientSocketTest, WriteSendsDataInDataFrame) { 564 scoped_ptr<SpdyFrame> conn(ConstructConnectRequestFrame()); 565 scoped_ptr<SpdyFrame> msg1(ConstructBodyFrame(kMsg1, kLen1)); 566 scoped_ptr<SpdyFrame> msg2(ConstructBodyFrame(kMsg2, kLen2)); 567 MockWrite writes[] = { 568 CreateMockWrite(*conn, 0, SYNCHRONOUS), 569 CreateMockWrite(*msg1, 2, SYNCHRONOUS), 570 CreateMockWrite(*msg2, 3, SYNCHRONOUS), 571 }; 572 573 scoped_ptr<SpdyFrame> resp(ConstructConnectReplyFrame()); 574 MockRead reads[] = { 575 CreateMockRead(*resp, 1, ASYNC), 576 MockRead(ASYNC, 0, 4), // EOF 577 }; 578 579 Initialize(reads, arraysize(reads), writes, arraysize(writes)); 580 581 AssertConnectSucceeds(); 582 583 AssertAsyncWriteSucceeds(kMsg1, kLen1); 584 AssertAsyncWriteSucceeds(kMsg2, kLen2); 585 } 586 587 TEST_P(SpdyProxyClientSocketTest, WriteSplitsLargeDataIntoMultipleFrames) { 588 std::string chunk_data(kMaxSpdyFrameChunkSize, 'x'); 589 scoped_ptr<SpdyFrame> conn(ConstructConnectRequestFrame()); 590 scoped_ptr<SpdyFrame> chunk(ConstructBodyFrame(chunk_data.data(), 591 chunk_data.length())); 592 MockWrite writes[] = { 593 CreateMockWrite(*conn, 0, SYNCHRONOUS), 594 CreateMockWrite(*chunk, 2, SYNCHRONOUS), 595 CreateMockWrite(*chunk, 3, SYNCHRONOUS), 596 CreateMockWrite(*chunk, 4, SYNCHRONOUS) 597 }; 598 599 scoped_ptr<SpdyFrame> resp(ConstructConnectReplyFrame()); 600 MockRead reads[] = { 601 CreateMockRead(*resp, 1, ASYNC), 602 MockRead(ASYNC, 0, 5), // EOF 603 }; 604 605 Initialize(reads, arraysize(reads), writes, arraysize(writes)); 606 607 AssertConnectSucceeds(); 608 609 std::string big_data(kMaxSpdyFrameChunkSize * 3, 'x'); 610 scoped_refptr<IOBufferWithSize> buf(CreateBuffer(big_data.data(), 611 big_data.length())); 612 613 EXPECT_EQ(ERR_IO_PENDING, 614 sock_->Write(buf.get(), buf->size(), write_callback_.callback())); 615 data_->RunFor(3); 616 617 EXPECT_EQ(buf->size(), write_callback_.WaitForResult()); 618 } 619 620 // ----------- Read 621 622 TEST_P(SpdyProxyClientSocketTest, ReadReadsDataInDataFrame) { 623 scoped_ptr<SpdyFrame> conn(ConstructConnectRequestFrame()); 624 MockWrite writes[] = { 625 CreateMockWrite(*conn, 0, SYNCHRONOUS), 626 }; 627 628 scoped_ptr<SpdyFrame> resp(ConstructConnectReplyFrame()); 629 scoped_ptr<SpdyFrame> msg1(ConstructBodyFrame(kMsg1, kLen1)); 630 MockRead reads[] = { 631 CreateMockRead(*resp, 1, ASYNC), 632 CreateMockRead(*msg1, 2, ASYNC), 633 MockRead(ASYNC, 0, 3), // EOF 634 }; 635 636 Initialize(reads, arraysize(reads), writes, arraysize(writes)); 637 638 AssertConnectSucceeds(); 639 640 Run(1); // SpdySession consumes the next read and sends it to 641 // sock_ to be buffered. 642 AssertSyncReadEquals(kMsg1, kLen1); 643 } 644 645 TEST_P(SpdyProxyClientSocketTest, ReadDataFromBufferedFrames) { 646 scoped_ptr<SpdyFrame> conn(ConstructConnectRequestFrame()); 647 MockWrite writes[] = { 648 CreateMockWrite(*conn, 0, SYNCHRONOUS), 649 }; 650 651 scoped_ptr<SpdyFrame> resp(ConstructConnectReplyFrame()); 652 scoped_ptr<SpdyFrame> msg1(ConstructBodyFrame(kMsg1, kLen1)); 653 scoped_ptr<SpdyFrame> msg2(ConstructBodyFrame(kMsg2, kLen2)); 654 MockRead reads[] = { 655 CreateMockRead(*resp, 1, ASYNC), 656 CreateMockRead(*msg1, 2, ASYNC), 657 CreateMockRead(*msg2, 3, ASYNC), 658 MockRead(ASYNC, 0, 4), // EOF 659 }; 660 661 Initialize(reads, arraysize(reads), writes, arraysize(writes)); 662 663 AssertConnectSucceeds(); 664 665 Run(1); // SpdySession consumes the next read and sends it to 666 // sock_ to be buffered. 667 AssertSyncReadEquals(kMsg1, kLen1); 668 Run(1); // SpdySession consumes the next read and sends it to 669 // sock_ to be buffered. 670 AssertSyncReadEquals(kMsg2, kLen2); 671 } 672 673 TEST_P(SpdyProxyClientSocketTest, ReadDataMultipleBufferedFrames) { 674 scoped_ptr<SpdyFrame> conn(ConstructConnectRequestFrame()); 675 MockWrite writes[] = { 676 CreateMockWrite(*conn, 0, SYNCHRONOUS), 677 }; 678 679 scoped_ptr<SpdyFrame> resp(ConstructConnectReplyFrame()); 680 scoped_ptr<SpdyFrame> msg1(ConstructBodyFrame(kMsg1, kLen1)); 681 scoped_ptr<SpdyFrame> msg2(ConstructBodyFrame(kMsg2, kLen2)); 682 MockRead reads[] = { 683 CreateMockRead(*resp, 1, ASYNC), 684 CreateMockRead(*msg1, 2, ASYNC), 685 CreateMockRead(*msg2, 3, ASYNC), 686 MockRead(ASYNC, 0, 4), // EOF 687 }; 688 689 Initialize(reads, arraysize(reads), writes, arraysize(writes)); 690 691 AssertConnectSucceeds(); 692 693 Run(2); // SpdySession consumes the next two reads and sends then to 694 // sock_ to be buffered. 695 AssertSyncReadEquals(kMsg1, kLen1); 696 AssertSyncReadEquals(kMsg2, kLen2); 697 } 698 699 TEST_P(SpdyProxyClientSocketTest, 700 LargeReadWillMergeDataFromDifferentFrames) { 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 scoped_ptr<SpdyFrame> msg3(ConstructBodyFrame(kMsg3, kLen3)); 709 MockRead reads[] = { 710 CreateMockRead(*resp, 1, ASYNC), 711 CreateMockRead(*msg3, 2, ASYNC), 712 CreateMockRead(*msg3, 3, ASYNC), 713 MockRead(ASYNC, 0, 4), // EOF 714 }; 715 716 Initialize(reads, arraysize(reads), writes, arraysize(writes)); 717 718 AssertConnectSucceeds(); 719 720 Run(2); // SpdySession consumes the next two reads and sends then to 721 // sock_ to be buffered. 722 // The payload from two data frames, each with kMsg3 will be combined 723 // together into a single read(). 724 AssertSyncReadEquals(kMsg33, kLen33); 725 } 726 727 TEST_P(SpdyProxyClientSocketTest, MultipleShortReadsThenMoreRead) { 728 scoped_ptr<SpdyFrame> conn(ConstructConnectRequestFrame()); 729 MockWrite writes[] = { 730 CreateMockWrite(*conn, 0, SYNCHRONOUS), 731 }; 732 733 scoped_ptr<SpdyFrame> resp(ConstructConnectReplyFrame()); 734 scoped_ptr<SpdyFrame> msg1(ConstructBodyFrame(kMsg1, kLen1)); 735 scoped_ptr<SpdyFrame> msg3(ConstructBodyFrame(kMsg3, kLen3)); 736 scoped_ptr<SpdyFrame> msg2(ConstructBodyFrame(kMsg2, kLen2)); 737 MockRead reads[] = { 738 CreateMockRead(*resp, 1, ASYNC), 739 CreateMockRead(*msg1, 2, ASYNC), 740 CreateMockRead(*msg3, 3, ASYNC), 741 CreateMockRead(*msg3, 4, ASYNC), 742 CreateMockRead(*msg2, 5, ASYNC), 743 MockRead(ASYNC, 0, 6), // EOF 744 }; 745 746 Initialize(reads, arraysize(reads), writes, arraysize(writes)); 747 748 AssertConnectSucceeds(); 749 750 Run(4); // SpdySession consumes the next four reads and sends then to 751 // sock_ to be buffered. 752 AssertSyncReadEquals(kMsg1, kLen1); 753 // The payload from two data frames, each with kMsg3 will be combined 754 // together into a single read(). 755 AssertSyncReadEquals(kMsg33, kLen33); 756 AssertSyncReadEquals(kMsg2, kLen2); 757 } 758 759 TEST_P(SpdyProxyClientSocketTest, ReadWillSplitDataFromLargeFrame) { 760 scoped_ptr<SpdyFrame> conn(ConstructConnectRequestFrame()); 761 MockWrite writes[] = { 762 CreateMockWrite(*conn, 0, SYNCHRONOUS), 763 }; 764 765 scoped_ptr<SpdyFrame> resp(ConstructConnectReplyFrame()); 766 scoped_ptr<SpdyFrame> msg1(ConstructBodyFrame(kMsg1, kLen1)); 767 scoped_ptr<SpdyFrame> msg33(ConstructBodyFrame(kMsg33, kLen33)); 768 scoped_ptr<SpdyFrame> msg2(ConstructBodyFrame(kMsg2, kLen2)); 769 MockRead reads[] = { 770 CreateMockRead(*resp, 1, ASYNC), 771 CreateMockRead(*msg1, 2, ASYNC), 772 CreateMockRead(*msg33, 3, ASYNC), 773 MockRead(ASYNC, 0, 4), // EOF 774 }; 775 776 Initialize(reads, arraysize(reads), writes, arraysize(writes)); 777 778 AssertConnectSucceeds(); 779 780 Run(2); // SpdySession consumes the next two reads and sends then to 781 // sock_ to be buffered. 782 AssertSyncReadEquals(kMsg1, kLen1); 783 // The payload from the single large data frame will be read across 784 // two different reads. 785 AssertSyncReadEquals(kMsg3, kLen3); 786 AssertSyncReadEquals(kMsg3, kLen3); 787 } 788 789 TEST_P(SpdyProxyClientSocketTest, MultipleReadsFromSameLargeFrame) { 790 scoped_ptr<SpdyFrame> conn(ConstructConnectRequestFrame()); 791 MockWrite writes[] = { 792 CreateMockWrite(*conn, 0, SYNCHRONOUS), 793 }; 794 795 scoped_ptr<SpdyFrame> resp(ConstructConnectReplyFrame()); 796 scoped_ptr<SpdyFrame> msg333(ConstructBodyFrame(kMsg333, kLen333)); 797 MockRead reads[] = { 798 CreateMockRead(*resp, 1, ASYNC), 799 CreateMockRead(*msg333, 2, ASYNC), 800 MockRead(ASYNC, 0, 3), // EOF 801 }; 802 803 Initialize(reads, arraysize(reads), writes, arraysize(writes)); 804 805 AssertConnectSucceeds(); 806 807 Run(1); // SpdySession consumes the next read and sends it to 808 // sock_ to be buffered. 809 // The payload from the single large data frame will be read across 810 // two different reads. 811 AssertSyncReadEquals(kMsg33, kLen33); 812 813 // Now attempt to do a read of more data than remains buffered 814 scoped_refptr<IOBuffer> buf(new IOBuffer(kLen33)); 815 ASSERT_EQ(kLen3, sock_->Read(buf.get(), kLen33, read_callback_.callback())); 816 ASSERT_EQ(std::string(kMsg3, kLen3), std::string(buf->data(), kLen3)); 817 ASSERT_TRUE(sock_->IsConnected()); 818 } 819 820 TEST_P(SpdyProxyClientSocketTest, ReadAuthResponseBody) { 821 scoped_ptr<SpdyFrame> conn(ConstructConnectRequestFrame()); 822 MockWrite writes[] = { 823 CreateMockWrite(*conn, 0, SYNCHRONOUS), 824 }; 825 826 scoped_ptr<SpdyFrame> resp(ConstructConnectAuthReplyFrame()); 827 scoped_ptr<SpdyFrame> msg1(ConstructBodyFrame(kMsg1, kLen1)); 828 scoped_ptr<SpdyFrame> msg2(ConstructBodyFrame(kMsg2, kLen2)); 829 MockRead reads[] = { 830 CreateMockRead(*resp, 1, ASYNC), 831 CreateMockRead(*msg1, 2, ASYNC), 832 CreateMockRead(*msg2, 3, ASYNC), 833 MockRead(ASYNC, 0, 4), // EOF 834 }; 835 836 Initialize(reads, arraysize(reads), writes, arraysize(writes)); 837 838 AssertConnectFails(ERR_PROXY_AUTH_REQUESTED); 839 840 Run(2); // SpdySession consumes the next two reads and sends then to 841 // sock_ to be buffered. 842 AssertSyncReadEquals(kMsg1, kLen1); 843 AssertSyncReadEquals(kMsg2, kLen2); 844 } 845 846 TEST_P(SpdyProxyClientSocketTest, ReadErrorResponseBody) { 847 scoped_ptr<SpdyFrame> conn(ConstructConnectRequestFrame()); 848 MockWrite writes[] = { 849 CreateMockWrite(*conn, 0, SYNCHRONOUS), 850 }; 851 852 scoped_ptr<SpdyFrame> resp(ConstructConnectErrorReplyFrame()); 853 scoped_ptr<SpdyFrame> msg1(ConstructBodyFrame(kMsg1, kLen1)); 854 scoped_ptr<SpdyFrame> msg2(ConstructBodyFrame(kMsg2, kLen2)); 855 MockRead reads[] = { 856 CreateMockRead(*resp, 1, ASYNC), 857 CreateMockRead(*msg1, 2, ASYNC), 858 CreateMockRead(*msg2, 3, ASYNC), 859 MockRead(ASYNC, 0, 4), // EOF 860 }; 861 862 Initialize(reads, arraysize(reads), writes, arraysize(writes)); 863 864 AssertConnectFails(ERR_TUNNEL_CONNECTION_FAILED); 865 } 866 867 // ----------- Reads and Writes 868 869 TEST_P(SpdyProxyClientSocketTest, AsyncReadAroundWrite) { 870 scoped_ptr<SpdyFrame> conn(ConstructConnectRequestFrame()); 871 scoped_ptr<SpdyFrame> msg2(ConstructBodyFrame(kMsg2, kLen2)); 872 MockWrite writes[] = { 873 CreateMockWrite(*conn, 0, SYNCHRONOUS), 874 CreateMockWrite(*msg2, 3, SYNCHRONOUS), 875 }; 876 877 scoped_ptr<SpdyFrame> resp(ConstructConnectReplyFrame()); 878 scoped_ptr<SpdyFrame> msg1(ConstructBodyFrame(kMsg1, kLen1)); 879 scoped_ptr<SpdyFrame> msg3(ConstructBodyFrame(kMsg3, kLen3)); 880 MockRead reads[] = { 881 CreateMockRead(*resp, 1, ASYNC), 882 CreateMockRead(*msg1, 2, ASYNC), // sync read 883 CreateMockRead(*msg3, 4, ASYNC), // async read 884 MockRead(ASYNC, 0, 5), // EOF 885 }; 886 887 Initialize(reads, arraysize(reads), writes, arraysize(writes)); 888 889 AssertConnectSucceeds(); 890 891 Run(1); 892 AssertSyncReadEquals(kMsg1, kLen1); 893 894 AssertReadStarts(kMsg3, kLen3); 895 // Read should block until after the write succeeds 896 897 AssertAsyncWriteSucceeds(kMsg2, kLen2); // Runs 1 step 898 899 ASSERT_FALSE(read_callback_.have_result()); 900 Run(1); 901 // Now the read will return 902 AssertReadReturns(kMsg3, kLen3); 903 } 904 905 TEST_P(SpdyProxyClientSocketTest, AsyncWriteAroundReads) { 906 scoped_ptr<SpdyFrame> conn(ConstructConnectRequestFrame()); 907 scoped_ptr<SpdyFrame> msg2(ConstructBodyFrame(kMsg2, kLen2)); 908 MockWrite writes[] = { 909 CreateMockWrite(*conn, 0, SYNCHRONOUS), 910 CreateMockWrite(*msg2, 4, ASYNC), 911 }; 912 913 scoped_ptr<SpdyFrame> resp(ConstructConnectReplyFrame()); 914 scoped_ptr<SpdyFrame> msg1(ConstructBodyFrame(kMsg1, kLen1)); 915 scoped_ptr<SpdyFrame> msg3(ConstructBodyFrame(kMsg3, kLen3)); 916 MockRead reads[] = { 917 CreateMockRead(*resp, 1, ASYNC), 918 CreateMockRead(*msg1, 2, ASYNC), 919 CreateMockRead(*msg3, 3, ASYNC), 920 MockRead(ASYNC, 0, 5), // EOF 921 }; 922 923 Initialize(reads, arraysize(reads), writes, arraysize(writes)); 924 925 AssertConnectSucceeds(); 926 927 Run(1); 928 AssertSyncReadEquals(kMsg1, kLen1); 929 // Write should block until the read completes 930 AssertWriteReturns(kMsg2, kLen2, ERR_IO_PENDING); 931 932 AssertAsyncReadEquals(kMsg3, kLen3); 933 934 ASSERT_FALSE(write_callback_.have_result()); 935 936 // Now the write will complete 937 Run(1); 938 AssertWriteLength(kLen2); 939 } 940 941 // ----------- Reading/Writing on Closed socket 942 943 // Reading from an already closed socket should return 0 944 TEST_P(SpdyProxyClientSocketTest, ReadOnClosedSocketReturnsZero) { 945 scoped_ptr<SpdyFrame> conn(ConstructConnectRequestFrame()); 946 MockWrite writes[] = { 947 CreateMockWrite(*conn, 0, SYNCHRONOUS), 948 }; 949 950 scoped_ptr<SpdyFrame> resp(ConstructConnectReplyFrame()); 951 MockRead reads[] = { 952 CreateMockRead(*resp, 1, ASYNC), 953 MockRead(ASYNC, 0, 2), // EOF 954 }; 955 956 Initialize(reads, arraysize(reads), writes, arraysize(writes)); 957 958 AssertConnectSucceeds(); 959 960 Run(1); 961 962 ASSERT_FALSE(sock_->IsConnected()); 963 ASSERT_EQ(0, sock_->Read(NULL, 1, CompletionCallback())); 964 ASSERT_EQ(0, sock_->Read(NULL, 1, CompletionCallback())); 965 ASSERT_EQ(0, sock_->Read(NULL, 1, CompletionCallback())); 966 ASSERT_FALSE(sock_->IsConnectedAndIdle()); 967 } 968 969 // Read pending when socket is closed should return 0 970 TEST_P(SpdyProxyClientSocketTest, PendingReadOnCloseReturnsZero) { 971 scoped_ptr<SpdyFrame> conn(ConstructConnectRequestFrame()); 972 MockWrite writes[] = { 973 CreateMockWrite(*conn, 0, SYNCHRONOUS), 974 }; 975 976 scoped_ptr<SpdyFrame> resp(ConstructConnectReplyFrame()); 977 MockRead reads[] = { 978 CreateMockRead(*resp, 1, ASYNC), 979 MockRead(ASYNC, 0, 2), // EOF 980 }; 981 982 Initialize(reads, arraysize(reads), writes, arraysize(writes)); 983 984 AssertConnectSucceeds(); 985 986 AssertReadStarts(kMsg1, kLen1); 987 988 Run(1); 989 990 ASSERT_EQ(0, read_callback_.WaitForResult()); 991 } 992 993 // Reading from a disconnected socket is an error 994 TEST_P(SpdyProxyClientSocketTest, 995 ReadOnDisconnectSocketReturnsNotConnected) { 996 scoped_ptr<SpdyFrame> conn(ConstructConnectRequestFrame()); 997 scoped_ptr<SpdyFrame> rst( 998 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_CANCEL)); 999 MockWrite writes[] = { 1000 CreateMockWrite(*conn, 0, SYNCHRONOUS), CreateMockWrite(*rst, 2), 1001 }; 1002 1003 scoped_ptr<SpdyFrame> resp(ConstructConnectReplyFrame()); 1004 MockRead reads[] = { 1005 CreateMockRead(*resp, 1, ASYNC), MockRead(ASYNC, 0, 3), // EOF 1006 }; 1007 1008 Initialize(reads, arraysize(reads), writes, arraysize(writes)); 1009 1010 AssertConnectSucceeds(); 1011 1012 sock_->Disconnect(); 1013 1014 ASSERT_EQ(ERR_SOCKET_NOT_CONNECTED, 1015 sock_->Read(NULL, 1, CompletionCallback())); 1016 1017 // Let the RST_STREAM write while |rst| is in-scope. 1018 base::MessageLoop::current()->RunUntilIdle(); 1019 } 1020 1021 // Reading buffered data from an already closed socket should return 1022 // buffered data, then 0. 1023 TEST_P(SpdyProxyClientSocketTest, ReadOnClosedSocketReturnsBufferedData) { 1024 scoped_ptr<SpdyFrame> conn(ConstructConnectRequestFrame()); 1025 MockWrite writes[] = { 1026 CreateMockWrite(*conn, 0, SYNCHRONOUS), 1027 }; 1028 1029 scoped_ptr<SpdyFrame> resp(ConstructConnectReplyFrame()); 1030 scoped_ptr<SpdyFrame> msg1(ConstructBodyFrame(kMsg1, kLen1)); 1031 MockRead reads[] = { 1032 CreateMockRead(*resp, 1, ASYNC), 1033 CreateMockRead(*msg1, 2, ASYNC), 1034 MockRead(ASYNC, 0, 3), // EOF 1035 }; 1036 1037 Initialize(reads, arraysize(reads), writes, arraysize(writes)); 1038 1039 AssertConnectSucceeds(); 1040 1041 Run(2); 1042 1043 ASSERT_FALSE(sock_->IsConnected()); 1044 scoped_refptr<IOBuffer> buf(new IOBuffer(kLen1)); 1045 ASSERT_EQ(kLen1, sock_->Read(buf.get(), kLen1, CompletionCallback())); 1046 ASSERT_EQ(std::string(kMsg1, kLen1), std::string(buf->data(), kLen1)); 1047 1048 ASSERT_EQ(0, sock_->Read(NULL, 1, CompletionCallback())); 1049 ASSERT_EQ(0, sock_->Read(NULL, 1, CompletionCallback())); 1050 sock_->Disconnect(); 1051 ASSERT_EQ(ERR_SOCKET_NOT_CONNECTED, 1052 sock_->Read(NULL, 1, CompletionCallback())); 1053 } 1054 1055 // Calling Write() on a closed socket is an error 1056 TEST_P(SpdyProxyClientSocketTest, WriteOnClosedStream) { 1057 scoped_ptr<SpdyFrame> conn(ConstructConnectRequestFrame()); 1058 MockWrite writes[] = { 1059 CreateMockWrite(*conn, 0, SYNCHRONOUS), 1060 }; 1061 1062 scoped_ptr<SpdyFrame> resp(ConstructConnectReplyFrame()); 1063 scoped_ptr<SpdyFrame> msg1(ConstructBodyFrame(kMsg1, kLen1)); 1064 MockRead reads[] = { 1065 CreateMockRead(*resp, 1, ASYNC), 1066 MockRead(ASYNC, 0, 2), // EOF 1067 }; 1068 1069 Initialize(reads, arraysize(reads), writes, arraysize(writes)); 1070 1071 AssertConnectSucceeds(); 1072 1073 Run(1); // Read EOF which will close the stream 1074 scoped_refptr<IOBufferWithSize> buf(CreateBuffer(kMsg1, kLen1)); 1075 EXPECT_EQ(ERR_SOCKET_NOT_CONNECTED, 1076 sock_->Write(buf.get(), buf->size(), CompletionCallback())); 1077 } 1078 1079 // Calling Write() on a disconnected socket is an error 1080 TEST_P(SpdyProxyClientSocketTest, WriteOnDisconnectedSocket) { 1081 scoped_ptr<SpdyFrame> conn(ConstructConnectRequestFrame()); 1082 scoped_ptr<SpdyFrame> rst( 1083 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_CANCEL)); 1084 MockWrite writes[] = { 1085 CreateMockWrite(*conn, 0, SYNCHRONOUS), CreateMockWrite(*rst, 2), 1086 }; 1087 1088 scoped_ptr<SpdyFrame> resp(ConstructConnectReplyFrame()); 1089 scoped_ptr<SpdyFrame> msg1(ConstructBodyFrame(kMsg1, kLen1)); 1090 MockRead reads[] = { 1091 CreateMockRead(*resp, 1, ASYNC), MockRead(ASYNC, 0, 3), // EOF 1092 }; 1093 1094 Initialize(reads, arraysize(reads), writes, arraysize(writes)); 1095 1096 AssertConnectSucceeds(); 1097 1098 sock_->Disconnect(); 1099 1100 scoped_refptr<IOBufferWithSize> buf(CreateBuffer(kMsg1, kLen1)); 1101 EXPECT_EQ(ERR_SOCKET_NOT_CONNECTED, 1102 sock_->Write(buf.get(), buf->size(), CompletionCallback())); 1103 1104 // Let the RST_STREAM write while |rst| is in-scope. 1105 base::MessageLoop::current()->RunUntilIdle(); 1106 } 1107 1108 // If the socket is closed with a pending Write(), the callback 1109 // should be called with ERR_CONNECTION_CLOSED. 1110 TEST_P(SpdyProxyClientSocketTest, WritePendingOnClose) { 1111 scoped_ptr<SpdyFrame> conn(ConstructConnectRequestFrame()); 1112 MockWrite writes[] = { 1113 CreateMockWrite(*conn, 0, SYNCHRONOUS), 1114 MockWrite(ASYNC, ERR_ABORTED, 2), 1115 }; 1116 1117 scoped_ptr<SpdyFrame> resp(ConstructConnectReplyFrame()); 1118 MockRead reads[] = { 1119 CreateMockRead(*resp, 1, ASYNC), 1120 MockRead(ASYNC, 0, 3), // EOF 1121 }; 1122 1123 Initialize(reads, arraysize(reads), writes, arraysize(writes)); 1124 1125 AssertConnectSucceeds(); 1126 1127 EXPECT_TRUE(sock_->IsConnected()); 1128 1129 scoped_refptr<IOBufferWithSize> buf(CreateBuffer(kMsg1, kLen1)); 1130 EXPECT_EQ(ERR_IO_PENDING, 1131 sock_->Write(buf.get(), buf->size(), write_callback_.callback())); 1132 1133 CloseSpdySession(ERR_ABORTED, std::string()); 1134 1135 EXPECT_EQ(ERR_CONNECTION_CLOSED, write_callback_.WaitForResult()); 1136 } 1137 1138 // If the socket is Disconnected with a pending Write(), the callback 1139 // should not be called. 1140 TEST_P(SpdyProxyClientSocketTest, DisconnectWithWritePending) { 1141 scoped_ptr<SpdyFrame> conn(ConstructConnectRequestFrame()); 1142 scoped_ptr<SpdyFrame> rst( 1143 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_CANCEL)); 1144 MockWrite writes[] = { 1145 CreateMockWrite(*conn, 0, SYNCHRONOUS), CreateMockWrite(*rst, 2), 1146 MockWrite(SYNCHRONOUS, 0, 3), // EOF 1147 }; 1148 1149 scoped_ptr<SpdyFrame> resp(ConstructConnectReplyFrame()); 1150 MockRead reads[] = { 1151 CreateMockRead(*resp, 1, ASYNC), MockRead(ASYNC, 0, 4), // EOF 1152 }; 1153 1154 Initialize(reads, arraysize(reads), writes, arraysize(writes)); 1155 1156 AssertConnectSucceeds(); 1157 1158 EXPECT_TRUE(sock_->IsConnected()); 1159 1160 scoped_refptr<IOBufferWithSize> buf(CreateBuffer(kMsg1, kLen1)); 1161 EXPECT_EQ(ERR_IO_PENDING, 1162 sock_->Write(buf.get(), buf->size(), write_callback_.callback())); 1163 1164 sock_->Disconnect(); 1165 1166 EXPECT_FALSE(sock_->IsConnected()); 1167 EXPECT_FALSE(write_callback_.have_result()); 1168 1169 // Let the RST_STREAM write while |rst| is in-scope. 1170 base::MessageLoop::current()->RunUntilIdle(); 1171 } 1172 1173 // If the socket is Disconnected with a pending Read(), the callback 1174 // should not be called. 1175 TEST_P(SpdyProxyClientSocketTest, DisconnectWithReadPending) { 1176 scoped_ptr<SpdyFrame> conn(ConstructConnectRequestFrame()); 1177 scoped_ptr<SpdyFrame> rst( 1178 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_CANCEL)); 1179 MockWrite writes[] = { 1180 CreateMockWrite(*conn, 0, SYNCHRONOUS), CreateMockWrite(*rst, 2), 1181 }; 1182 1183 scoped_ptr<SpdyFrame> resp(ConstructConnectReplyFrame()); 1184 MockRead reads[] = { 1185 CreateMockRead(*resp, 1, ASYNC), MockRead(ASYNC, 0, 3), // EOF 1186 }; 1187 1188 Initialize(reads, arraysize(reads), writes, arraysize(writes)); 1189 1190 AssertConnectSucceeds(); 1191 1192 EXPECT_TRUE(sock_->IsConnected()); 1193 1194 scoped_refptr<IOBuffer> buf(new IOBuffer(kLen1)); 1195 ASSERT_EQ(ERR_IO_PENDING, 1196 sock_->Read(buf.get(), kLen1, read_callback_.callback())); 1197 1198 sock_->Disconnect(); 1199 1200 EXPECT_FALSE(sock_->IsConnected()); 1201 EXPECT_FALSE(read_callback_.have_result()); 1202 1203 // Let the RST_STREAM write while |rst| is in-scope. 1204 base::MessageLoop::current()->RunUntilIdle(); 1205 } 1206 1207 // If the socket is Reset when both a read and write are pending, 1208 // both should be called back. 1209 TEST_P(SpdyProxyClientSocketTest, RstWithReadAndWritePending) { 1210 scoped_ptr<SpdyFrame> conn(ConstructConnectRequestFrame()); 1211 MockWrite writes[] = { 1212 CreateMockWrite(*conn, 0, SYNCHRONOUS), 1213 MockWrite(ASYNC, ERR_ABORTED, 3), 1214 }; 1215 1216 scoped_ptr<SpdyFrame> resp(ConstructConnectReplyFrame()); 1217 scoped_ptr<SpdyFrame> rst( 1218 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_CANCEL)); 1219 MockRead reads[] = { 1220 CreateMockRead(*resp, 1, ASYNC), 1221 CreateMockRead(*rst, 2, ASYNC), 1222 MockRead(ASYNC, 0, 4) // EOF 1223 }; 1224 1225 Initialize(reads, arraysize(reads), writes, arraysize(writes)); 1226 1227 AssertConnectSucceeds(); 1228 1229 EXPECT_TRUE(sock_->IsConnected()); 1230 1231 scoped_refptr<IOBuffer> read_buf(new IOBuffer(kLen1)); 1232 ASSERT_EQ(ERR_IO_PENDING, 1233 sock_->Read(read_buf.get(), kLen1, read_callback_.callback())); 1234 1235 scoped_refptr<IOBufferWithSize> write_buf(CreateBuffer(kMsg1, kLen1)); 1236 EXPECT_EQ( 1237 ERR_IO_PENDING, 1238 sock_->Write( 1239 write_buf.get(), write_buf->size(), write_callback_.callback())); 1240 1241 Run(2); 1242 1243 EXPECT_TRUE(sock_.get()); 1244 EXPECT_TRUE(read_callback_.have_result()); 1245 EXPECT_TRUE(write_callback_.have_result()); 1246 1247 // Let the RST_STREAM write while |rst| is in-scope. 1248 base::MessageLoop::current()->RunUntilIdle(); 1249 } 1250 1251 // Makes sure the proxy client socket's source gets the expected NetLog events 1252 // and only the expected NetLog events (No SpdySession events). 1253 TEST_P(SpdyProxyClientSocketTest, NetLog) { 1254 scoped_ptr<SpdyFrame> conn(ConstructConnectRequestFrame()); 1255 scoped_ptr<SpdyFrame> rst( 1256 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_CANCEL)); 1257 MockWrite writes[] = { 1258 CreateMockWrite(*conn, 0, SYNCHRONOUS), CreateMockWrite(*rst, 3), 1259 }; 1260 1261 scoped_ptr<SpdyFrame> resp(ConstructConnectReplyFrame()); 1262 scoped_ptr<SpdyFrame> msg1(ConstructBodyFrame(kMsg1, kLen1)); 1263 MockRead reads[] = { 1264 CreateMockRead(*resp, 1, ASYNC), CreateMockRead(*msg1, 2, ASYNC), 1265 MockRead(ASYNC, 0, 4), // EOF 1266 }; 1267 1268 Initialize(reads, arraysize(reads), writes, arraysize(writes)); 1269 1270 AssertConnectSucceeds(); 1271 1272 Run(1); // SpdySession consumes the next read and sends it to 1273 // sock_ to be buffered. 1274 AssertSyncReadEquals(kMsg1, kLen1); 1275 1276 NetLog::Source sock_source = sock_->NetLog().source(); 1277 sock_.reset(); 1278 1279 CapturingNetLog::CapturedEntryList entry_list; 1280 net_log_.GetEntriesForSource(sock_source, &entry_list); 1281 1282 ASSERT_EQ(entry_list.size(), 10u); 1283 EXPECT_TRUE(LogContainsBeginEvent(entry_list, 0, NetLog::TYPE_SOCKET_ALIVE)); 1284 EXPECT_TRUE(LogContainsEvent(entry_list, 1, 1285 NetLog::TYPE_SPDY_PROXY_CLIENT_SESSION, 1286 NetLog::PHASE_NONE)); 1287 EXPECT_TRUE(LogContainsBeginEvent(entry_list, 2, 1288 NetLog::TYPE_HTTP_TRANSACTION_TUNNEL_SEND_REQUEST)); 1289 EXPECT_TRUE(LogContainsEvent(entry_list, 3, 1290 NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS, 1291 NetLog::PHASE_NONE)); 1292 EXPECT_TRUE(LogContainsEndEvent(entry_list, 4, 1293 NetLog::TYPE_HTTP_TRANSACTION_TUNNEL_SEND_REQUEST)); 1294 EXPECT_TRUE(LogContainsBeginEvent(entry_list, 5, 1295 NetLog::TYPE_HTTP_TRANSACTION_TUNNEL_READ_HEADERS)); 1296 EXPECT_TRUE(LogContainsEvent(entry_list, 6, 1297 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS, 1298 NetLog::PHASE_NONE)); 1299 EXPECT_TRUE(LogContainsEndEvent(entry_list, 7, 1300 NetLog::TYPE_HTTP_TRANSACTION_TUNNEL_READ_HEADERS)); 1301 EXPECT_TRUE(LogContainsEvent(entry_list, 8, 1302 NetLog::TYPE_SOCKET_BYTES_RECEIVED, 1303 NetLog::PHASE_NONE)); 1304 EXPECT_TRUE(LogContainsEndEvent(entry_list, 9, NetLog::TYPE_SOCKET_ALIVE)); 1305 1306 // Let the RST_STREAM write while |rst| is in-scope. 1307 base::MessageLoop::current()->RunUntilIdle(); 1308 } 1309 1310 // CompletionCallback that causes the SpdyProxyClientSocket to be 1311 // deleted when Run is invoked. 1312 class DeleteSockCallback : public TestCompletionCallbackBase { 1313 public: 1314 explicit DeleteSockCallback(scoped_ptr<SpdyProxyClientSocket>* sock) 1315 : sock_(sock), 1316 callback_(base::Bind(&DeleteSockCallback::OnComplete, 1317 base::Unretained(this))) { 1318 } 1319 1320 virtual ~DeleteSockCallback() { 1321 } 1322 1323 const CompletionCallback& callback() const { return callback_; } 1324 1325 private: 1326 void OnComplete(int result) { 1327 sock_->reset(NULL); 1328 SetResult(result); 1329 } 1330 1331 scoped_ptr<SpdyProxyClientSocket>* sock_; 1332 CompletionCallback callback_; 1333 1334 DISALLOW_COPY_AND_ASSIGN(DeleteSockCallback); 1335 }; 1336 1337 // If the socket is Reset when both a read and write are pending, and the 1338 // read callback causes the socket to be deleted, the write callback should 1339 // not be called. 1340 TEST_P(SpdyProxyClientSocketTest, RstWithReadAndWritePendingDelete) { 1341 scoped_ptr<SpdyFrame> conn(ConstructConnectRequestFrame()); 1342 MockWrite writes[] = { 1343 CreateMockWrite(*conn, 0, SYNCHRONOUS), 1344 MockWrite(ASYNC, ERR_ABORTED, 3), 1345 }; 1346 1347 scoped_ptr<SpdyFrame> resp(ConstructConnectReplyFrame()); 1348 scoped_ptr<SpdyFrame> rst( 1349 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_CANCEL)); 1350 MockRead reads[] = { 1351 CreateMockRead(*resp, 1, ASYNC), 1352 CreateMockRead(*rst, 2, ASYNC), 1353 MockRead(ASYNC, 0, 4), // EOF 1354 }; 1355 1356 Initialize(reads, arraysize(reads), writes, arraysize(writes)); 1357 1358 AssertConnectSucceeds(); 1359 1360 EXPECT_TRUE(sock_->IsConnected()); 1361 1362 DeleteSockCallback read_callback(&sock_); 1363 1364 scoped_refptr<IOBuffer> read_buf(new IOBuffer(kLen1)); 1365 ASSERT_EQ(ERR_IO_PENDING, 1366 sock_->Read(read_buf.get(), kLen1, read_callback.callback())); 1367 1368 scoped_refptr<IOBufferWithSize> write_buf(CreateBuffer(kMsg1, kLen1)); 1369 EXPECT_EQ( 1370 ERR_IO_PENDING, 1371 sock_->Write( 1372 write_buf.get(), write_buf->size(), write_callback_.callback())); 1373 1374 Run(1); 1375 1376 EXPECT_FALSE(sock_.get()); 1377 EXPECT_TRUE(read_callback.have_result()); 1378 EXPECT_FALSE(write_callback_.have_result()); 1379 1380 // Let the RST_STREAM write while |rst| is in-scope. 1381 base::MessageLoop::current()->RunUntilIdle(); 1382 } 1383 1384 } // namespace net 1385