spdy_session_unittest.cc revision 7d4cd473f85ac64c3747c96c277f9e506a0d2246
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_session.h" 6 7#include "base/bind.h" 8#include "base/callback.h" 9#include "base/memory/scoped_ptr.h" 10#include "base/run_loop.h" 11#include "net/base/io_buffer.h" 12#include "net/base/ip_endpoint.h" 13#include "net/base/net_log_unittest.h" 14#include "net/base/request_priority.h" 15#include "net/base/test_data_directory.h" 16#include "net/base/test_data_stream.h" 17#include "net/dns/host_cache.h" 18#include "net/socket/client_socket_pool_manager.h" 19#include "net/socket/next_proto.h" 20#include "net/socket/socket_test_util.h" 21#include "net/spdy/spdy_http_utils.h" 22#include "net/spdy/spdy_session_pool.h" 23#include "net/spdy/spdy_session_test_util.h" 24#include "net/spdy/spdy_stream.h" 25#include "net/spdy/spdy_stream_test_util.h" 26#include "net/spdy/spdy_test_util_common.h" 27#include "net/spdy/spdy_test_utils.h" 28#include "net/test/cert_test_util.h" 29#include "testing/platform_test.h" 30 31namespace net { 32 33namespace { 34 35static const char kTestUrl[] = "http://www.example.org/"; 36static const char kTestHost[] = "www.example.org"; 37static const int kTestPort = 80; 38 39const char kBodyData[] = "Body data"; 40const size_t kBodyDataSize = arraysize(kBodyData); 41const base::StringPiece kBodyDataStringPiece(kBodyData, kBodyDataSize); 42 43static int g_delta_seconds = 0; 44base::TimeTicks TheNearFuture() { 45 return base::TimeTicks::Now() + base::TimeDelta::FromSeconds(g_delta_seconds); 46} 47 48} // namespace 49 50class SpdySessionTest : public PlatformTest, 51 public ::testing::WithParamInterface<NextProto> { 52 public: 53 // Functions used with RunResumeAfterUnstallTest(). 54 55 void StallSessionOnly(SpdySession* session, SpdyStream* stream) { 56 StallSessionSend(session); 57 } 58 59 void StallStreamOnly(SpdySession* session, SpdyStream* stream) { 60 StallStreamSend(stream); 61 } 62 63 void StallSessionStream(SpdySession* session, SpdyStream* stream) { 64 StallSessionSend(session); 65 StallStreamSend(stream); 66 } 67 68 void StallStreamSession(SpdySession* session, SpdyStream* stream) { 69 StallStreamSend(stream); 70 StallSessionSend(session); 71 } 72 73 void UnstallSessionOnly(SpdySession* session, 74 SpdyStream* stream, 75 int32 delta_window_size) { 76 UnstallSessionSend(session, delta_window_size); 77 } 78 79 void UnstallStreamOnly(SpdySession* session, 80 SpdyStream* stream, 81 int32 delta_window_size) { 82 UnstallStreamSend(stream, delta_window_size); 83 } 84 85 void UnstallSessionStream(SpdySession* session, 86 SpdyStream* stream, 87 int32 delta_window_size) { 88 UnstallSessionSend(session, delta_window_size); 89 UnstallStreamSend(stream, delta_window_size); 90 } 91 92 void UnstallStreamSession(SpdySession* session, 93 SpdyStream* stream, 94 int32 delta_window_size) { 95 UnstallStreamSend(stream, delta_window_size); 96 UnstallSessionSend(session, delta_window_size); 97 } 98 99 protected: 100 SpdySessionTest() 101 : old_max_group_sockets_(ClientSocketPoolManager::max_sockets_per_group( 102 HttpNetworkSession::NORMAL_SOCKET_POOL)), 103 old_max_pool_sockets_(ClientSocketPoolManager::max_sockets_per_pool( 104 HttpNetworkSession::NORMAL_SOCKET_POOL)), 105 spdy_util_(GetParam()), 106 session_deps_(GetParam()), 107 spdy_session_pool_(NULL), 108 test_url_(kTestUrl), 109 test_host_port_pair_(kTestHost, kTestPort), 110 key_(test_host_port_pair_, ProxyServer::Direct(), 111 kPrivacyModeDisabled) { 112 } 113 114 virtual ~SpdySessionTest() { 115 // Important to restore the per-pool limit first, since the pool limit must 116 // always be greater than group limit, and the tests reduce both limits. 117 ClientSocketPoolManager::set_max_sockets_per_pool( 118 HttpNetworkSession::NORMAL_SOCKET_POOL, old_max_pool_sockets_); 119 ClientSocketPoolManager::set_max_sockets_per_group( 120 HttpNetworkSession::NORMAL_SOCKET_POOL, old_max_group_sockets_); 121 } 122 123 virtual void SetUp() OVERRIDE { 124 g_delta_seconds = 0; 125 } 126 127 void CreateDeterministicNetworkSession() { 128 http_session_ = 129 SpdySessionDependencies::SpdyCreateSessionDeterministic(&session_deps_); 130 spdy_session_pool_ = http_session_->spdy_session_pool(); 131 } 132 133 void CreateNetworkSession() { 134 http_session_ = 135 SpdySessionDependencies::SpdyCreateSession(&session_deps_); 136 spdy_session_pool_ = http_session_->spdy_session_pool(); 137 } 138 139 scoped_refptr<SpdySession> GetSession(const SpdySessionKey& key) { 140 EXPECT_FALSE(spdy_session_pool_->HasSession(key)); 141 scoped_refptr<SpdySession> session = 142 spdy_session_pool_->Get(key, BoundNetLog()); 143 EXPECT_TRUE(spdy_session_pool_->HasSession(key)); 144 return session; 145 } 146 147 // Creates an initialized session to |key_|. 148 scoped_refptr<SpdySession> CreateInitializedSession() { 149 scoped_refptr<SpdySession> session = GetSession(key_); 150 EXPECT_EQ( 151 OK, 152 InitializeSession( 153 http_session_.get(), session.get(), test_host_port_pair_)); 154 return session; 155 } 156 157 net::Error InitializeSession(HttpNetworkSession* http_session, 158 SpdySession* session, 159 const HostPortPair& host_port_pair) { 160 transport_params_ = new TransportSocketParams( 161 host_port_pair, MEDIUM, false, false, OnHostResolutionCallback()); 162 163 scoped_ptr<ClientSocketHandle> connection(new ClientSocketHandle); 164 EXPECT_EQ(OK, connection->Init(host_port_pair.ToString(), 165 transport_params_, MEDIUM, 166 CompletionCallback(), 167 http_session->GetTransportSocketPool( 168 HttpNetworkSession::NORMAL_SOCKET_POOL), 169 BoundNetLog())); 170 return session->InitializeWithSocket(connection.release(), false, OK); 171 } 172 173 void StallSessionSend(SpdySession* session) { 174 // Reduce the send window size to 0 to stall. 175 while (session->session_send_window_size_ > 0) { 176 session->DecreaseSendWindowSize( 177 std::min(kMaxSpdyFrameChunkSize, session->session_send_window_size_)); 178 } 179 } 180 181 void UnstallSessionSend(SpdySession* session, int32 delta_window_size) { 182 session->IncreaseSendWindowSize(delta_window_size); 183 } 184 185 void StallStreamSend(SpdyStream* stream) { 186 // Reduce the send window size to 0 to stall. 187 while (stream->send_window_size() > 0) { 188 stream->DecreaseSendWindowSize( 189 std::min(kMaxSpdyFrameChunkSize, stream->send_window_size())); 190 } 191 } 192 193 void UnstallStreamSend(SpdyStream* stream, int32 delta_window_size) { 194 stream->IncreaseSendWindowSize(delta_window_size); 195 } 196 197 void RunResumeAfterUnstallTest( 198 const base::Callback<void(SpdySession*, SpdyStream*)>& stall_fn, 199 const base::Callback<void(SpdySession*, SpdyStream*, int32)>& 200 unstall_function); 201 202 // Original socket limits. Some tests set these. Safest to always restore 203 // them once each test has been run. 204 int old_max_group_sockets_; 205 int old_max_pool_sockets_; 206 207 SpdyTestUtil spdy_util_; 208 scoped_refptr<TransportSocketParams> transport_params_; 209 SpdySessionDependencies session_deps_; 210 scoped_refptr<HttpNetworkSession> http_session_; 211 SpdySessionPool* spdy_session_pool_; 212 GURL test_url_; 213 HostPortPair test_host_port_pair_; 214 SpdySessionKey key_; 215}; 216 217INSTANTIATE_TEST_CASE_P( 218 NextProto, 219 SpdySessionTest, 220 testing::Values(kProtoSPDY2, kProtoSPDY3, kProtoSPDY31, kProtoSPDY4a2)); 221 222// TODO(akalin): Don't early-exit in the tests below for values > 223// kProtoSPDY3. 224 225TEST_P(SpdySessionTest, GoAway) { 226 if (GetParam() > kProtoSPDY3) 227 return; 228 229 session_deps_.host_resolver->set_synchronous_mode(true); 230 231 MockConnect connect_data(SYNCHRONOUS, OK); 232 scoped_ptr<SpdyFrame> goaway(spdy_util_.ConstructSpdyGoAway(1)); 233 MockRead reads[] = { 234 CreateMockRead(*goaway, 2), 235 MockRead(ASYNC, 0, 3) // EOF 236 }; 237 scoped_ptr<SpdyFrame> req1( 238 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, MEDIUM, true)); 239 scoped_ptr<SpdyFrame> req2( 240 spdy_util_.ConstructSpdyGet(NULL, 0, false, 3, MEDIUM, true)); 241 MockWrite writes[] = { 242 CreateMockWrite(*req1, 0), 243 CreateMockWrite(*req2, 1), 244 }; 245 DeterministicSocketData data(reads, arraysize(reads), 246 writes, arraysize(writes)); 247 data.set_connect_data(connect_data); 248 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data); 249 250 SSLSocketDataProvider ssl(SYNCHRONOUS, OK); 251 session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl); 252 253 CreateDeterministicNetworkSession(); 254 255 scoped_refptr<SpdySession> session = CreateInitializedSession(); 256 257 EXPECT_EQ(spdy_util_.spdy_version(), session->GetProtocolVersion()); 258 259 GURL url("http://www.google.com"); 260 base::WeakPtr<SpdyStream> spdy_stream1 = 261 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM, 262 session, url, MEDIUM, BoundNetLog()); 263 test::StreamDelegateDoNothing delegate1(spdy_stream1); 264 spdy_stream1->SetDelegate(&delegate1); 265 266 base::WeakPtr<SpdyStream> spdy_stream2 = 267 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM, 268 session, url, MEDIUM, BoundNetLog()); 269 test::StreamDelegateDoNothing delegate2(spdy_stream2); 270 spdy_stream2->SetDelegate(&delegate2); 271 272 scoped_ptr<SpdyHeaderBlock> headers( 273 spdy_util_.ConstructGetHeaderBlock(url.spec())); 274 scoped_ptr<SpdyHeaderBlock> headers2(new SpdyHeaderBlock(*headers)); 275 276 spdy_stream1->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND); 277 EXPECT_TRUE(spdy_stream1->HasUrl()); 278 spdy_stream2->SendRequestHeaders(headers2.Pass(), NO_MORE_DATA_TO_SEND); 279 EXPECT_TRUE(spdy_stream2->HasUrl()); 280 281 data.RunFor(2); 282 283 EXPECT_EQ(1u, spdy_stream1->stream_id()); 284 EXPECT_EQ(3u, spdy_stream2->stream_id()); 285 286 EXPECT_TRUE(spdy_session_pool_->HasSession(key_)); 287 288 // Read and process the GOAWAY frame. 289 data.RunFor(1); 290 291 EXPECT_FALSE(spdy_session_pool_->HasSession(key_)); 292 293 EXPECT_TRUE(session->IsStreamActive(1)); 294 EXPECT_FALSE(session->IsStreamActive(3)); 295 296 scoped_refptr<SpdySession> session2 = GetSession(key_); 297 298 spdy_stream1->Close(); 299 EXPECT_EQ(NULL, spdy_stream1.get()); 300 301 // Delete the first session. 302 session = NULL; 303 304 // Delete the second session. 305 spdy_session_pool_->Remove(session2); 306 session2 = NULL; 307 EXPECT_EQ(NULL, spdy_stream2.get()); 308} 309 310TEST_P(SpdySessionTest, ClientPing) { 311 if (GetParam() > kProtoSPDY3) 312 return; 313 314 session_deps_.enable_ping = true; 315 session_deps_.host_resolver->set_synchronous_mode(true); 316 317 MockConnect connect_data(SYNCHRONOUS, OK); 318 scoped_ptr<SpdyFrame> read_ping(spdy_util_.ConstructSpdyPing(1)); 319 MockRead reads[] = { 320 CreateMockRead(*read_ping), 321 MockRead(SYNCHRONOUS, 0, 0) // EOF 322 }; 323 scoped_ptr<SpdyFrame> write_ping(spdy_util_.ConstructSpdyPing(1)); 324 MockWrite writes[] = { 325 CreateMockWrite(*write_ping), 326 }; 327 StaticSocketDataProvider data( 328 reads, arraysize(reads), writes, arraysize(writes)); 329 data.set_connect_data(connect_data); 330 session_deps_.socket_factory->AddSocketDataProvider(&data); 331 332 SSLSocketDataProvider ssl(SYNCHRONOUS, OK); 333 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl); 334 335 CreateNetworkSession(); 336 337 scoped_refptr<SpdySession> session = CreateInitializedSession(); 338 339 base::WeakPtr<SpdyStream> spdy_stream1 = 340 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM, 341 session, test_url_, MEDIUM, BoundNetLog()); 342 ASSERT_TRUE(spdy_stream1.get() != NULL); 343 test::StreamDelegateSendImmediate delegate(spdy_stream1, NULL); 344 spdy_stream1->SetDelegate(&delegate); 345 346 base::TimeTicks before_ping_time = base::TimeTicks::Now(); 347 348 session->set_connection_at_risk_of_loss_time( 349 base::TimeDelta::FromSeconds(-1)); 350 session->set_hung_interval(base::TimeDelta::FromMilliseconds(50)); 351 352 session->SendPrefacePingIfNoneInFlight(); 353 354 EXPECT_EQ(ERR_CONNECTION_CLOSED, delegate.WaitForClose()); 355 356 session->CheckPingStatus(before_ping_time); 357 358 EXPECT_EQ(0, session->pings_in_flight()); 359 EXPECT_GE(session->next_ping_id(), static_cast<uint32>(1)); 360 EXPECT_FALSE(session->check_ping_status_pending()); 361 EXPECT_GE(session->last_activity_time(), before_ping_time); 362 363 EXPECT_FALSE(spdy_session_pool_->HasSession(key_)); 364 365 // Delete the first session. 366 session = NULL; 367} 368 369TEST_P(SpdySessionTest, ServerPing) { 370 if (GetParam() > kProtoSPDY3) 371 return; 372 373 session_deps_.host_resolver->set_synchronous_mode(true); 374 375 MockConnect connect_data(SYNCHRONOUS, OK); 376 scoped_ptr<SpdyFrame> read_ping(spdy_util_.ConstructSpdyPing(2)); 377 MockRead reads[] = { 378 CreateMockRead(*read_ping), 379 MockRead(SYNCHRONOUS, 0, 0) // EOF 380 }; 381 scoped_ptr<SpdyFrame> write_ping(spdy_util_.ConstructSpdyPing(2)); 382 MockWrite writes[] = { 383 CreateMockWrite(*write_ping), 384 }; 385 StaticSocketDataProvider data( 386 reads, arraysize(reads), writes, arraysize(writes)); 387 data.set_connect_data(connect_data); 388 session_deps_.socket_factory->AddSocketDataProvider(&data); 389 390 SSLSocketDataProvider ssl(SYNCHRONOUS, OK); 391 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl); 392 393 CreateNetworkSession(); 394 395 scoped_refptr<SpdySession> session = CreateInitializedSession(); 396 397 base::WeakPtr<SpdyStream> spdy_stream1 = 398 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM, 399 session, test_url_, MEDIUM, BoundNetLog()); 400 ASSERT_TRUE(spdy_stream1.get() != NULL); 401 test::StreamDelegateSendImmediate delegate(spdy_stream1, NULL); 402 spdy_stream1->SetDelegate(&delegate); 403 404 // Flush the SpdySession::OnReadComplete() task. 405 base::MessageLoop::current()->RunUntilIdle(); 406 407 EXPECT_FALSE(spdy_session_pool_->HasSession(key_)); 408 409 // Delete the session. 410 session = NULL; 411 EXPECT_EQ(NULL, spdy_stream1.get()); 412} 413 414TEST_P(SpdySessionTest, DeleteExpiredPushStreams) { 415 if (GetParam() > kProtoSPDY3) 416 return; 417 418 session_deps_.host_resolver->set_synchronous_mode(true); 419 420 SSLSocketDataProvider ssl(SYNCHRONOUS, OK); 421 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl); 422 session_deps_.time_func = TheNearFuture; 423 424 CreateNetworkSession(); 425 426 scoped_refptr<SpdySession> session = GetSession(key_); 427 428 session->buffered_spdy_framer_.reset( 429 new BufferedSpdyFramer(spdy_util_.spdy_version(), false)); 430 431 // Create the associated stream and add to active streams. 432 scoped_ptr<SpdyHeaderBlock> request_headers( 433 spdy_util_.ConstructGetHeaderBlock("http://www.google.com/")); 434 435 scoped_ptr<SpdyStream> stream(new SpdyStream(SPDY_REQUEST_RESPONSE_STREAM, 436 session.get(), 437 std::string(), 438 DEFAULT_PRIORITY, 439 kSpdyStreamInitialWindowSize, 440 kSpdyStreamInitialWindowSize, 441 session->net_log_)); 442 stream->SendRequestHeaders(request_headers.Pass(), NO_MORE_DATA_TO_SEND); 443 SpdyStream* stream_ptr = stream.get(); 444 session->InsertCreatedStream(stream.Pass()); 445 stream = session->ActivateCreatedStream(stream_ptr); 446 session->InsertActivatedStream(stream.Pass()); 447 448 SpdyHeaderBlock headers; 449 spdy_util_.AddUrlToHeaderBlock("http://www.google.com/a.dat", &headers); 450 session->OnSynStream(2, 1, 0, 0, true, false, headers); 451 452 // Verify that there is one unclaimed push stream. 453 EXPECT_EQ(1u, session->num_unclaimed_pushed_streams()); 454 SpdySession::PushedStreamMap::iterator iter = 455 session->unclaimed_pushed_streams_.find("http://www.google.com/a.dat"); 456 EXPECT_TRUE(session->unclaimed_pushed_streams_.end() != iter); 457 458 // Shift time. 459 g_delta_seconds = 301; 460 461 spdy_util_.AddUrlToHeaderBlock("http://www.google.com/b.dat", &headers); 462 session->OnSynStream(4, 1, 0, 0, true, false, headers); 463 464 // Verify that the second pushed stream evicted the first pushed stream. 465 EXPECT_EQ(1u, session->num_unclaimed_pushed_streams()); 466 iter = session->unclaimed_pushed_streams_.find("http://www.google.com/b.dat"); 467 EXPECT_TRUE(session->unclaimed_pushed_streams_.end() != iter); 468 469 // Delete the session. 470 session = NULL; 471} 472 473TEST_P(SpdySessionTest, FailedPing) { 474 if (GetParam() > kProtoSPDY3) 475 return; 476 477 session_deps_.host_resolver->set_synchronous_mode(true); 478 479 MockConnect connect_data(SYNCHRONOUS, OK); 480 scoped_ptr<SpdyFrame> read_ping(spdy_util_.ConstructSpdyPing(1)); 481 MockRead reads[] = { 482 CreateMockRead(*read_ping), 483 MockRead(SYNCHRONOUS, 0, 0) // EOF 484 }; 485 scoped_ptr<SpdyFrame> write_ping(spdy_util_.ConstructSpdyPing(1)); 486 MockWrite writes[] = { 487 CreateMockWrite(*write_ping), 488 }; 489 StaticSocketDataProvider data( 490 reads, arraysize(reads), writes, arraysize(writes)); 491 data.set_connect_data(connect_data); 492 session_deps_.socket_factory->AddSocketDataProvider(&data); 493 494 SSLSocketDataProvider ssl(SYNCHRONOUS, OK); 495 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl); 496 497 CreateNetworkSession(); 498 499 scoped_refptr<SpdySession> session = CreateInitializedSession(); 500 501 base::WeakPtr<SpdyStream> spdy_stream1 = 502 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM, 503 session, test_url_, MEDIUM, BoundNetLog()); 504 ASSERT_TRUE(spdy_stream1.get() != NULL); 505 test::StreamDelegateSendImmediate delegate(spdy_stream1, NULL); 506 spdy_stream1->SetDelegate(&delegate); 507 508 session->set_connection_at_risk_of_loss_time(base::TimeDelta::FromSeconds(0)); 509 session->set_hung_interval(base::TimeDelta::FromSeconds(0)); 510 511 // Send a PING frame. 512 session->WritePingFrame(1); 513 EXPECT_LT(0, session->pings_in_flight()); 514 EXPECT_GE(session->next_ping_id(), static_cast<uint32>(1)); 515 EXPECT_TRUE(session->check_ping_status_pending()); 516 517 // Assert session is not closed. 518 EXPECT_FALSE(session->IsClosed()); 519 EXPECT_LT(0u, session->num_active_streams() + session->num_created_streams()); 520 EXPECT_TRUE(spdy_session_pool_->HasSession(key_)); 521 522 // We set last time we have received any data in 1 sec less than now. 523 // CheckPingStatus will trigger timeout because hung interval is zero. 524 base::TimeTicks now = base::TimeTicks::Now(); 525 session->last_activity_time_ = now - base::TimeDelta::FromSeconds(1); 526 session->CheckPingStatus(now); 527 528 EXPECT_TRUE(session->IsClosed()); 529 EXPECT_EQ(0u, session->num_active_streams()); 530 EXPECT_EQ(0u, session->num_unclaimed_pushed_streams()); 531 EXPECT_FALSE(spdy_session_pool_->HasSession(key_)); 532 533 // Delete the first session. 534 session = NULL; 535 EXPECT_EQ(NULL, spdy_stream1.get()); 536} 537 538TEST_P(SpdySessionTest, CloseIdleSessions) { 539 if (GetParam() > kProtoSPDY3) 540 return; 541 542 MockConnect connect_data(SYNCHRONOUS, OK); 543 MockRead reads[] = { 544 MockRead(ASYNC, 0, 0) // EOF 545 }; 546 547 StaticSocketDataProvider data(reads, arraysize(reads), NULL, 0); 548 data.set_connect_data(connect_data); 549 session_deps_.socket_factory->AddSocketDataProvider(&data); 550 551 CreateNetworkSession(); 552 553 // Set up session 1 554 const std::string kTestHost1("http://www.a.com"); 555 HostPortPair test_host_port_pair1(kTestHost1, 80); 556 SpdySessionKey key1(test_host_port_pair1, ProxyServer::Direct(), 557 kPrivacyModeDisabled); 558 scoped_refptr<SpdySession> session1 = GetSession(key1); 559 EXPECT_EQ( 560 OK, 561 InitializeSession( 562 http_session_.get(), session1.get(), test_host_port_pair1)); 563 GURL url1(kTestHost1); 564 base::WeakPtr<SpdyStream> spdy_stream1 = 565 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM, 566 session1, url1, MEDIUM, BoundNetLog()); 567 ASSERT_TRUE(spdy_stream1.get() != NULL); 568 569 // Set up session 2 570 session_deps_.socket_factory->AddSocketDataProvider(&data); 571 const std::string kTestHost2("http://www.b.com"); 572 HostPortPair test_host_port_pair2(kTestHost2, 80); 573 SpdySessionKey key2(test_host_port_pair2, ProxyServer::Direct(), 574 kPrivacyModeDisabled); 575 scoped_refptr<SpdySession> session2 = GetSession(key2); 576 EXPECT_EQ( 577 OK, 578 InitializeSession( 579 http_session_.get(), session2.get(), test_host_port_pair2)); 580 GURL url2(kTestHost2); 581 base::WeakPtr<SpdyStream> spdy_stream2 = 582 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM, 583 session2, url2, MEDIUM, BoundNetLog()); 584 ASSERT_TRUE(spdy_stream2.get() != NULL); 585 586 // Set up session 3 587 session_deps_.socket_factory->AddSocketDataProvider(&data); 588 const std::string kTestHost3("http://www.c.com"); 589 HostPortPair test_host_port_pair3(kTestHost3, 80); 590 SpdySessionKey key3(test_host_port_pair3, ProxyServer::Direct(), 591 kPrivacyModeDisabled); 592 scoped_refptr<SpdySession> session3 = GetSession(key3); 593 EXPECT_EQ( 594 OK, 595 InitializeSession( 596 http_session_.get(), session3.get(), test_host_port_pair3)); 597 GURL url3(kTestHost3); 598 base::WeakPtr<SpdyStream> spdy_stream3 = 599 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM, 600 session3, url3, MEDIUM, BoundNetLog()); 601 ASSERT_TRUE(spdy_stream3.get() != NULL); 602 603 // All sessions are active and not closed 604 EXPECT_TRUE(session1->is_active()); 605 EXPECT_FALSE(session1->IsClosed()); 606 EXPECT_TRUE(session2->is_active()); 607 EXPECT_FALSE(session2->IsClosed()); 608 EXPECT_TRUE(session3->is_active()); 609 EXPECT_FALSE(session3->IsClosed()); 610 611 // Should not do anything, all are active 612 spdy_session_pool_->CloseIdleSessions(); 613 EXPECT_TRUE(session1->is_active()); 614 EXPECT_FALSE(session1->IsClosed()); 615 EXPECT_TRUE(session2->is_active()); 616 EXPECT_FALSE(session2->IsClosed()); 617 EXPECT_TRUE(session3->is_active()); 618 EXPECT_FALSE(session3->IsClosed()); 619 620 // Make sessions 1 and 3 inactive, but keep them open. 621 // Session 2 still open and active 622 session1->CloseCreatedStream(spdy_stream1, OK); 623 EXPECT_EQ(NULL, spdy_stream1.get()); 624 session3->CloseCreatedStream(spdy_stream3, OK); 625 EXPECT_EQ(NULL, spdy_stream3.get()); 626 EXPECT_FALSE(session1->is_active()); 627 EXPECT_FALSE(session1->IsClosed()); 628 EXPECT_TRUE(session2->is_active()); 629 EXPECT_FALSE(session2->IsClosed()); 630 EXPECT_FALSE(session3->is_active()); 631 EXPECT_FALSE(session3->IsClosed()); 632 633 // Should close session 1 and 3, 2 should be left open 634 spdy_session_pool_->CloseIdleSessions(); 635 EXPECT_FALSE(session1->is_active()); 636 EXPECT_TRUE(session1->IsClosed()); 637 EXPECT_TRUE(session2->is_active()); 638 EXPECT_FALSE(session2->IsClosed()); 639 EXPECT_FALSE(session3->is_active()); 640 EXPECT_TRUE(session3->IsClosed()); 641 642 // Should not do anything 643 spdy_session_pool_->CloseIdleSessions(); 644 EXPECT_TRUE(session2->is_active()); 645 EXPECT_FALSE(session2->IsClosed()); 646 647 // Make 2 not active 648 session2->CloseCreatedStream(spdy_stream2, OK); 649 EXPECT_EQ(NULL, spdy_stream2.get()); 650 EXPECT_FALSE(session2->is_active()); 651 EXPECT_FALSE(session2->IsClosed()); 652 653 // This should close session 2 654 spdy_session_pool_->CloseIdleSessions(); 655 EXPECT_FALSE(session2->is_active()); 656 EXPECT_TRUE(session2->IsClosed()); 657} 658 659// Start with max concurrent streams set to 1. Request two streams. Receive a 660// settings frame setting max concurrent streams to 2. Have the callback 661// release the stream, which releases its reference (the last) to the session. 662// Make sure nothing blows up. 663// http://crbug.com/57331 664TEST_P(SpdySessionTest, OnSettings) { 665 if (GetParam() > kProtoSPDY3) 666 return; 667 668 session_deps_.host_resolver->set_synchronous_mode(true); 669 670 SettingsMap new_settings; 671 const SpdySettingsIds kSpdySettingsIds1 = SETTINGS_MAX_CONCURRENT_STREAMS; 672 const uint32 max_concurrent_streams = 2; 673 new_settings[kSpdySettingsIds1] = 674 SettingsFlagsAndValue(SETTINGS_FLAG_NONE, max_concurrent_streams); 675 676 // Set up the socket so we read a SETTINGS frame that raises max concurrent 677 // streams to 2. 678 MockConnect connect_data(SYNCHRONOUS, OK); 679 scoped_ptr<SpdyFrame> settings_frame( 680 spdy_util_.ConstructSpdySettings(new_settings)); 681 MockRead reads[] = { 682 CreateMockRead(*settings_frame), 683 MockRead(SYNCHRONOUS, 0, 0) // EOF 684 }; 685 686 StaticSocketDataProvider data(reads, arraysize(reads), NULL, 0); 687 data.set_connect_data(connect_data); 688 session_deps_.socket_factory->AddSocketDataProvider(&data); 689 690 SSLSocketDataProvider ssl(SYNCHRONOUS, OK); 691 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl); 692 693 CreateNetworkSession(); 694 695 // Initialize the SpdySetting with 1 max concurrent streams. 696 spdy_session_pool_->http_server_properties()->SetSpdySetting( 697 test_host_port_pair_, 698 kSpdySettingsIds1, 699 SETTINGS_FLAG_PLEASE_PERSIST, 700 1); 701 702 scoped_refptr<SpdySession> session = CreateInitializedSession(); 703 704 // Create 2 streams. First will succeed. Second will be pending. 705 base::WeakPtr<SpdyStream> spdy_stream1 = 706 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM, 707 session, test_url_, MEDIUM, BoundNetLog()); 708 ASSERT_TRUE(spdy_stream1.get() != NULL); 709 710 StreamReleaserCallback stream_releaser; 711 SpdyStreamRequest request; 712 ASSERT_EQ(ERR_IO_PENDING, 713 request.StartRequest( 714 SPDY_BIDIRECTIONAL_STREAM, session, test_url_, MEDIUM, 715 BoundNetLog(), 716 stream_releaser.MakeCallback(&request))); 717 session = NULL; 718 719 EXPECT_EQ(OK, stream_releaser.WaitForResult()); 720} 721 722// Start with max concurrent streams set to 1 (that is persisted). Receive a 723// settings frame setting max concurrent streams to 2 and which also clears the 724// persisted data. Verify that persisted data is correct. 725TEST_P(SpdySessionTest, ClearSettings) { 726 if (GetParam() > kProtoSPDY3) 727 return; 728 729 session_deps_.host_resolver->set_synchronous_mode(true); 730 731 SettingsMap new_settings; 732 const SpdySettingsIds kSpdySettingsIds1 = SETTINGS_MAX_CONCURRENT_STREAMS; 733 const uint32 max_concurrent_streams = 2; 734 new_settings[kSpdySettingsIds1] = 735 SettingsFlagsAndValue(SETTINGS_FLAG_NONE, max_concurrent_streams); 736 737 // Set up the socket so we read a SETTINGS frame that raises max concurrent 738 // streams to 2 and clears previously persisted data. 739 MockConnect connect_data(SYNCHRONOUS, OK); 740 scoped_ptr<SpdyFrame> settings_frame( 741 spdy_util_.ConstructSpdySettings(new_settings)); 742 uint8 flags = SETTINGS_FLAG_CLEAR_PREVIOUSLY_PERSISTED_SETTINGS; 743 test::SetFrameFlags(settings_frame.get(), flags, SPDY3); 744 MockRead reads[] = { 745 CreateMockRead(*settings_frame), 746 MockRead(SYNCHRONOUS, 0, 0) // EOF 747 }; 748 749 StaticSocketDataProvider data(reads, arraysize(reads), NULL, 0); 750 data.set_connect_data(connect_data); 751 session_deps_.socket_factory->AddSocketDataProvider(&data); 752 753 SSLSocketDataProvider ssl(SYNCHRONOUS, OK); 754 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl); 755 756 CreateNetworkSession(); 757 758 // Initialize the SpdySetting with 1 max concurrent streams. 759 spdy_session_pool_->http_server_properties()->SetSpdySetting( 760 test_host_port_pair_, 761 kSpdySettingsIds1, 762 SETTINGS_FLAG_PLEASE_PERSIST, 763 1); 764 765 EXPECT_EQ(1u, spdy_session_pool_->http_server_properties()->GetSpdySettings( 766 test_host_port_pair_).size()); 767 768 scoped_refptr<SpdySession> session = CreateInitializedSession(); 769 770 // Create 2 streams. First will succeed. Second will be pending. 771 base::WeakPtr<SpdyStream> spdy_stream1 = 772 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM, 773 session, test_url_, MEDIUM, BoundNetLog()); 774 ASSERT_TRUE(spdy_stream1.get() != NULL); 775 776 StreamReleaserCallback stream_releaser; 777 778 SpdyStreamRequest request; 779 ASSERT_EQ(ERR_IO_PENDING, 780 request.StartRequest( 781 SPDY_BIDIRECTIONAL_STREAM, session, test_url_, MEDIUM, 782 BoundNetLog(), 783 stream_releaser.MakeCallback(&request))); 784 785 EXPECT_EQ(OK, stream_releaser.WaitForResult()); 786 787 // Make sure that persisted data is cleared. 788 EXPECT_EQ(0u, spdy_session_pool_->http_server_properties()->GetSpdySettings( 789 test_host_port_pair_).size()); 790 791 // Make sure session's max_concurrent_streams is 2. 792 EXPECT_EQ(2u, session->max_concurrent_streams()); 793 794 session = NULL; 795} 796 797// Start with max concurrent streams set to 1. Request two streams. When the 798// first completes, have the callback close itself, which should trigger the 799// second stream creation. Then cancel that one immediately. Don't crash. 800// http://crbug.com/63532 801TEST_P(SpdySessionTest, CancelPendingCreateStream) { 802 if (GetParam() > kProtoSPDY3) 803 return; 804 805 session_deps_.host_resolver->set_synchronous_mode(true); 806 807 MockRead reads[] = { 808 MockRead(SYNCHRONOUS, ERR_IO_PENDING) // Stall forever. 809 }; 810 811 StaticSocketDataProvider data(reads, arraysize(reads), NULL, 0); 812 MockConnect connect_data(SYNCHRONOUS, OK); 813 814 data.set_connect_data(connect_data); 815 session_deps_.socket_factory->AddSocketDataProvider(&data); 816 817 SSLSocketDataProvider ssl(SYNCHRONOUS, OK); 818 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl); 819 820 CreateNetworkSession(); 821 822 // Initialize the SpdySetting with 1 max concurrent streams. 823 spdy_session_pool_->http_server_properties()->SetSpdySetting( 824 test_host_port_pair_, 825 SETTINGS_MAX_CONCURRENT_STREAMS, 826 SETTINGS_FLAG_PLEASE_PERSIST, 827 1); 828 829 scoped_refptr<SpdySession> session = CreateInitializedSession(); 830 831 // Create 2 streams. First will succeed. Second will be pending. 832 base::WeakPtr<SpdyStream> spdy_stream1 = 833 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM, 834 session, test_url_, MEDIUM, BoundNetLog()); 835 ASSERT_TRUE(spdy_stream1.get() != NULL); 836 837 // Use scoped_ptr to let us invalidate the memory when we want to, to trigger 838 // a valgrind error if the callback is invoked when it's not supposed to be. 839 scoped_ptr<TestCompletionCallback> callback(new TestCompletionCallback); 840 841 SpdyStreamRequest request; 842 ASSERT_EQ(ERR_IO_PENDING, 843 request.StartRequest( 844 SPDY_BIDIRECTIONAL_STREAM, session, test_url_, MEDIUM, 845 BoundNetLog(), 846 callback->callback())); 847 848 // Release the first one, this will allow the second to be created. 849 spdy_stream1->Cancel(); 850 EXPECT_EQ(NULL, spdy_stream1.get()); 851 852 request.CancelRequest(); 853 callback.reset(); 854 855 // Should not crash when running the pending callback. 856 base::MessageLoop::current()->RunUntilIdle(); 857} 858 859TEST_P(SpdySessionTest, SendInitialSettingsOnNewSession) { 860 if (GetParam() > kProtoSPDY3) 861 return; 862 863 session_deps_.host_resolver->set_synchronous_mode(true); 864 865 MockRead reads[] = { 866 MockRead(SYNCHRONOUS, ERR_IO_PENDING) // Stall forever. 867 }; 868 869 SettingsMap settings; 870 const SpdySettingsIds kSpdySettingsIds1 = SETTINGS_MAX_CONCURRENT_STREAMS; 871 const SpdySettingsIds kSpdySettingsIds2 = SETTINGS_INITIAL_WINDOW_SIZE; 872 const uint32 kInitialRecvWindowSize = 10 * 1024 * 1024; 873 settings[kSpdySettingsIds1] = 874 SettingsFlagsAndValue(SETTINGS_FLAG_NONE, kMaxConcurrentPushedStreams); 875 if (spdy_util_.spdy_version() >= SPDY3) { 876 settings[kSpdySettingsIds2] = 877 SettingsFlagsAndValue(SETTINGS_FLAG_NONE, kInitialRecvWindowSize); 878 } 879 MockConnect connect_data(SYNCHRONOUS, OK); 880 scoped_ptr<SpdyFrame> settings_frame( 881 spdy_util_.ConstructSpdySettings(settings)); 882 MockWrite writes[] = { 883 CreateMockWrite(*settings_frame), 884 }; 885 session_deps_.stream_initial_recv_window_size = kInitialRecvWindowSize; 886 887 StaticSocketDataProvider data( 888 reads, arraysize(reads), writes, arraysize(writes)); 889 data.set_connect_data(connect_data); 890 session_deps_.socket_factory->AddSocketDataProvider(&data); 891 892 SSLSocketDataProvider ssl(SYNCHRONOUS, OK); 893 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl); 894 895 CreateNetworkSession(); 896 897 SpdySessionPoolPeer pool_peer(spdy_session_pool_); 898 pool_peer.EnableSendingInitialSettings(true); 899 900 scoped_refptr<SpdySession> session = CreateInitializedSession(); 901 902 base::MessageLoop::current()->RunUntilIdle(); 903 EXPECT_TRUE(data.at_write_eof()); 904} 905 906TEST_P(SpdySessionTest, SendSettingsOnNewSession) { 907 if (GetParam() > kProtoSPDY3) 908 return; 909 910 session_deps_.host_resolver->set_synchronous_mode(true); 911 912 MockRead reads[] = { 913 MockRead(SYNCHRONOUS, ERR_IO_PENDING) // Stall forever. 914 }; 915 916 // Create the bogus setting that we want to verify is sent out. 917 // Note that it will be marked as SETTINGS_FLAG_PERSISTED when sent out. But 918 // to persist it into the HttpServerProperties, we need to mark as 919 // SETTINGS_FLAG_PLEASE_PERSIST. 920 SettingsMap settings; 921 const SpdySettingsIds kSpdySettingsIds1 = SETTINGS_UPLOAD_BANDWIDTH; 922 const uint32 kBogusSettingValue = 0xCDCD; 923 settings[kSpdySettingsIds1] = 924 SettingsFlagsAndValue(SETTINGS_FLAG_PERSISTED, kBogusSettingValue); 925 MockConnect connect_data(SYNCHRONOUS, OK); 926 scoped_ptr<SpdyFrame> settings_frame( 927 spdy_util_.ConstructSpdySettings(settings)); 928 MockWrite writes[] = { 929 CreateMockWrite(*settings_frame), 930 }; 931 932 StaticSocketDataProvider data( 933 reads, arraysize(reads), writes, arraysize(writes)); 934 data.set_connect_data(connect_data); 935 session_deps_.socket_factory->AddSocketDataProvider(&data); 936 937 SSLSocketDataProvider ssl(SYNCHRONOUS, OK); 938 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl); 939 940 CreateNetworkSession(); 941 942 spdy_session_pool_->http_server_properties()->SetSpdySetting( 943 test_host_port_pair_, 944 kSpdySettingsIds1, 945 SETTINGS_FLAG_PLEASE_PERSIST, 946 kBogusSettingValue); 947 948 scoped_refptr<SpdySession> session = CreateInitializedSession(); 949 950 base::MessageLoop::current()->RunUntilIdle(); 951 EXPECT_TRUE(data.at_write_eof()); 952} 953 954namespace { 955 956// Specifies the style for closing the connection. 957enum SpdyPoolCloseSessionsType { 958 SPDY_POOL_CLOSE_SESSIONS_MANUALLY, 959 SPDY_POOL_CLOSE_CURRENT_SESSIONS, 960 SPDY_POOL_CLOSE_IDLE_SESSIONS, 961}; 962 963// Initialize the SpdySession with socket. 964void IPPoolingInitializedSession( 965 const std::string& group_name, 966 const scoped_refptr<TransportSocketParams>& transport_params, 967 HttpNetworkSession* http_session, 968 SpdySession* session) { 969 scoped_ptr<ClientSocketHandle> connection(new ClientSocketHandle); 970 EXPECT_EQ(OK, connection->Init(group_name, 971 transport_params, MEDIUM, CompletionCallback(), 972 http_session->GetTransportSocketPool( 973 HttpNetworkSession::NORMAL_SOCKET_POOL), 974 BoundNetLog())); 975 EXPECT_EQ(OK, session->InitializeWithSocket(connection.release(), false, OK)); 976} 977 978// This test has three variants, one for each style of closing the connection. 979// If |clean_via_close_current_sessions| is SPDY_POOL_CLOSE_SESSIONS_MANUALLY, 980// the sessions are closed manually, calling SpdySessionPool::Remove() directly. 981// If |clean_via_close_current_sessions| is SPDY_POOL_CLOSE_CURRENT_SESSIONS, 982// sessions are closed with SpdySessionPool::CloseCurrentSessions(). 983// If |clean_via_close_current_sessions| is SPDY_POOL_CLOSE_IDLE_SESSIONS, 984// sessions are closed with SpdySessionPool::CloseIdleSessions(). 985void IPPoolingTest(NextProto next_proto, 986 SpdyPoolCloseSessionsType close_sessions_type) { 987 const int kTestPort = 80; 988 struct TestHosts { 989 std::string url; 990 std::string name; 991 std::string iplist; 992 SpdySessionKey key; 993 AddressList addresses; 994 } test_hosts[] = { 995 { "http:://www.foo.com", 996 "www.foo.com", 997 "192.0.2.33,192.168.0.1,192.168.0.5" 998 }, 999 { "http://js.foo.com", 1000 "js.foo.com", 1001 "192.168.0.2,192.168.0.3,192.168.0.5,192.0.2.33" 1002 }, 1003 { "http://images.foo.com", 1004 "images.foo.com", 1005 "192.168.0.4,192.168.0.3" 1006 }, 1007 }; 1008 1009 SpdySessionDependencies session_deps(next_proto); 1010 session_deps.host_resolver->set_synchronous_mode(true); 1011 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(test_hosts); i++) { 1012 session_deps.host_resolver->rules()->AddIPLiteralRule( 1013 test_hosts[i].name, test_hosts[i].iplist, std::string()); 1014 1015 // This test requires that the HostResolver cache be populated. Normal 1016 // code would have done this already, but we do it manually. 1017 HostResolver::RequestInfo info(HostPortPair(test_hosts[i].name, kTestPort)); 1018 session_deps.host_resolver->Resolve( 1019 info, &test_hosts[i].addresses, CompletionCallback(), NULL, 1020 BoundNetLog()); 1021 1022 // Setup a SpdySessionKey 1023 test_hosts[i].key = SpdySessionKey( 1024 HostPortPair(test_hosts[i].name, kTestPort), ProxyServer::Direct(), 1025 kPrivacyModeDisabled); 1026 } 1027 1028 MockConnect connect_data(SYNCHRONOUS, OK); 1029 MockRead reads[] = { 1030 MockRead(SYNCHRONOUS, ERR_IO_PENDING) // Stall forever. 1031 }; 1032 1033 StaticSocketDataProvider data(reads, arraysize(reads), NULL, 0); 1034 data.set_connect_data(connect_data); 1035 session_deps.socket_factory->AddSocketDataProvider(&data); 1036 1037 SSLSocketDataProvider ssl(SYNCHRONOUS, OK); 1038 session_deps.socket_factory->AddSSLSocketDataProvider(&ssl); 1039 1040 scoped_refptr<HttpNetworkSession> http_session( 1041 SpdySessionDependencies::SpdyCreateSession(&session_deps)); 1042 1043 // Setup the first session to the first host. 1044 SpdySessionPool* spdy_session_pool(http_session->spdy_session_pool()); 1045 EXPECT_FALSE(spdy_session_pool->HasSession(test_hosts[0].key)); 1046 scoped_refptr<SpdySession> session = 1047 spdy_session_pool->Get(test_hosts[0].key, BoundNetLog()); 1048 EXPECT_TRUE(spdy_session_pool->HasSession(test_hosts[0].key)); 1049 1050 HostPortPair test_host_port_pair(test_hosts[0].name, kTestPort); 1051 1052 // Initialize session for the first host. 1053 scoped_refptr<TransportSocketParams> transport_params( 1054 new TransportSocketParams(test_host_port_pair, 1055 MEDIUM, 1056 false, 1057 false, 1058 OnHostResolutionCallback())); 1059 IPPoolingInitializedSession(test_host_port_pair.ToString(), 1060 transport_params, 1061 http_session.get(), 1062 session.get()); 1063 1064 // TODO(rtenneti): MockClientSocket::GetPeerAddress return's 0 as the port 1065 // number. Fix it to return port 80 and then use GetPeerAddress to AddAlias. 1066 SpdySessionPoolPeer pool_peer(spdy_session_pool); 1067 pool_peer.AddAlias(test_hosts[0].addresses.front(), test_hosts[0].key); 1068 1069 // Flush the SpdySession::OnReadComplete() task. 1070 base::MessageLoop::current()->RunUntilIdle(); 1071 1072 // The third host has no overlap with the first, so it can't pool IPs. 1073 EXPECT_FALSE(spdy_session_pool->HasSession(test_hosts[2].key)); 1074 1075 // The second host overlaps with the first, and should IP pool. 1076 EXPECT_TRUE(spdy_session_pool->HasSession(test_hosts[1].key)); 1077 1078 // Verify that the second host, through a proxy, won't share the IP. 1079 SpdySessionKey proxy_key(test_hosts[1].key.host_port_pair(), 1080 ProxyServer::FromPacString("HTTP http://proxy.foo.com/"), 1081 kPrivacyModeDisabled); 1082 EXPECT_FALSE(spdy_session_pool->HasSession(proxy_key)); 1083 1084 // Overlap between 2 and 3 does is not transitive to 1. 1085 EXPECT_FALSE(spdy_session_pool->HasSession(test_hosts[2].key)); 1086 1087 // Create a new session to host 2. 1088 scoped_refptr<SpdySession> session2 = 1089 spdy_session_pool->Get(test_hosts[2].key, BoundNetLog()); 1090 1091 // Verify that we have sessions for everything. 1092 EXPECT_TRUE(spdy_session_pool->HasSession(test_hosts[0].key)); 1093 EXPECT_TRUE(spdy_session_pool->HasSession(test_hosts[1].key)); 1094 EXPECT_TRUE(spdy_session_pool->HasSession(test_hosts[2].key)); 1095 1096 // Initialize session for host 2. 1097 session_deps.socket_factory->AddSocketDataProvider(&data); 1098 IPPoolingInitializedSession(test_hosts[2].key.host_port_pair().ToString(), 1099 transport_params, 1100 http_session.get(), 1101 session2.get()); 1102 1103 // Grab the session to host 1 and verify that it is the same session 1104 // we got with host 0, and that is a different than host 2's session. 1105 scoped_refptr<SpdySession> session1 = 1106 spdy_session_pool->Get(test_hosts[1].key, BoundNetLog()); 1107 EXPECT_EQ(session.get(), session1.get()); 1108 EXPECT_NE(session2.get(), session1.get()); 1109 1110 // Initialize session for host 1. 1111 session_deps.socket_factory->AddSocketDataProvider(&data); 1112 IPPoolingInitializedSession(test_hosts[2].key.host_port_pair().ToString(), 1113 transport_params, 1114 http_session.get(), 1115 session2.get()); 1116 1117 // Remove the aliases and observe that we still have a session for host1. 1118 pool_peer.RemoveAliases(test_hosts[0].key); 1119 pool_peer.RemoveAliases(test_hosts[1].key); 1120 EXPECT_TRUE(spdy_session_pool->HasSession(test_hosts[1].key)); 1121 1122 // Expire the host cache 1123 session_deps.host_resolver->GetHostCache()->clear(); 1124 EXPECT_TRUE(spdy_session_pool->HasSession(test_hosts[1].key)); 1125 1126 // Cleanup the sessions. 1127 switch (close_sessions_type) { 1128 case SPDY_POOL_CLOSE_SESSIONS_MANUALLY: 1129 spdy_session_pool->Remove(session); 1130 session = NULL; 1131 spdy_session_pool->Remove(session2); 1132 session2 = NULL; 1133 break; 1134 case SPDY_POOL_CLOSE_CURRENT_SESSIONS: 1135 spdy_session_pool->CloseCurrentSessions(net::ERR_ABORTED); 1136 break; 1137 case SPDY_POOL_CLOSE_IDLE_SESSIONS: 1138 GURL url(test_hosts[0].url); 1139 base::WeakPtr<SpdyStream> spdy_stream = 1140 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM, 1141 session, url, MEDIUM, BoundNetLog()); 1142 GURL url1(test_hosts[1].url); 1143 base::WeakPtr<SpdyStream> spdy_stream1 = 1144 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM, 1145 session1, url1, MEDIUM, BoundNetLog()); 1146 GURL url2(test_hosts[2].url); 1147 base::WeakPtr<SpdyStream> spdy_stream2 = 1148 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM, 1149 session2, url2, MEDIUM, BoundNetLog()); 1150 1151 // Close streams to make spdy_session and spdy_session1 inactive. 1152 session->CloseCreatedStream(spdy_stream, OK); 1153 EXPECT_EQ(NULL, spdy_stream.get()); 1154 session1->CloseCreatedStream(spdy_stream1, OK); 1155 EXPECT_EQ(NULL, spdy_stream1.get()); 1156 1157 // Check spdy_session and spdy_session1 are not closed. 1158 EXPECT_FALSE(session->is_active()); 1159 EXPECT_FALSE(session->IsClosed()); 1160 EXPECT_FALSE(session1->is_active()); 1161 EXPECT_FALSE(session1->IsClosed()); 1162 EXPECT_TRUE(session2->is_active()); 1163 EXPECT_FALSE(session2->IsClosed()); 1164 1165 // Test that calling CloseIdleSessions, does not cause a crash. 1166 // http://crbug.com/181400 1167 spdy_session_pool->CloseIdleSessions(); 1168 1169 // Verify spdy_session and spdy_session1 are closed. 1170 EXPECT_FALSE(session->is_active()); 1171 EXPECT_TRUE(session->IsClosed()); 1172 EXPECT_FALSE(session1->is_active()); 1173 EXPECT_TRUE(session1->IsClosed()); 1174 EXPECT_TRUE(session2->is_active()); 1175 EXPECT_FALSE(session2->IsClosed()); 1176 1177 spdy_stream2->Cancel(); 1178 EXPECT_EQ(NULL, spdy_stream.get()); 1179 EXPECT_EQ(NULL, spdy_stream1.get()); 1180 EXPECT_EQ(NULL, spdy_stream2.get()); 1181 spdy_session_pool->Remove(session2); 1182 session2 = NULL; 1183 break; 1184 } 1185 1186 // Verify that the map is all cleaned up. 1187 EXPECT_FALSE(spdy_session_pool->HasSession(test_hosts[0].key)); 1188 EXPECT_FALSE(spdy_session_pool->HasSession(test_hosts[1].key)); 1189 EXPECT_FALSE(spdy_session_pool->HasSession(test_hosts[2].key)); 1190} 1191 1192} // namespace 1193 1194TEST_P(SpdySessionTest, IPPooling) { 1195 IPPoolingTest(GetParam(), SPDY_POOL_CLOSE_SESSIONS_MANUALLY); 1196} 1197 1198TEST_P(SpdySessionTest, IPPoolingCloseCurrentSessions) { 1199 IPPoolingTest(GetParam(), SPDY_POOL_CLOSE_CURRENT_SESSIONS); 1200} 1201 1202TEST_P(SpdySessionTest, IPPoolingCloseIdleSessions) { 1203 IPPoolingTest(GetParam(), SPDY_POOL_CLOSE_IDLE_SESSIONS); 1204} 1205 1206TEST_P(SpdySessionTest, ClearSettingsStorageOnIPAddressChanged) { 1207 if (GetParam() > kProtoSPDY3) 1208 return; 1209 1210 CreateNetworkSession(); 1211 1212 HttpServerProperties* test_http_server_properties = 1213 spdy_session_pool_->http_server_properties(); 1214 SettingsFlagsAndValue flags_and_value1(SETTINGS_FLAG_PLEASE_PERSIST, 2); 1215 test_http_server_properties->SetSpdySetting( 1216 test_host_port_pair_, 1217 SETTINGS_MAX_CONCURRENT_STREAMS, 1218 SETTINGS_FLAG_PLEASE_PERSIST, 1219 2); 1220 EXPECT_NE(0u, test_http_server_properties->GetSpdySettings( 1221 test_host_port_pair_).size()); 1222 spdy_session_pool_->OnIPAddressChanged(); 1223 EXPECT_EQ(0u, test_http_server_properties->GetSpdySettings( 1224 test_host_port_pair_).size()); 1225} 1226 1227TEST_P(SpdySessionTest, Initialize) { 1228 if (GetParam() > kProtoSPDY3) 1229 return; 1230 1231 CapturingBoundNetLog log; 1232 session_deps_.net_log = log.bound().net_log(); 1233 session_deps_.host_resolver->set_synchronous_mode(true); 1234 1235 MockConnect connect_data(SYNCHRONOUS, OK); 1236 MockRead reads[] = { 1237 MockRead(ASYNC, 0, 0) // EOF 1238 }; 1239 1240 StaticSocketDataProvider data(reads, arraysize(reads), NULL, 0); 1241 data.set_connect_data(connect_data); 1242 session_deps_.socket_factory->AddSocketDataProvider(&data); 1243 1244 SSLSocketDataProvider ssl(SYNCHRONOUS, OK); 1245 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl); 1246 1247 CreateNetworkSession(); 1248 1249 scoped_refptr<SpdySession> session = 1250 spdy_session_pool_->Get(key_, log.bound()); 1251 EXPECT_TRUE(spdy_session_pool_->HasSession(key_)); 1252 1253 EXPECT_EQ(OK, 1254 InitializeSession( 1255 http_session_.get(), session.get(), test_host_port_pair_)); 1256 1257 // Flush the SpdySession::OnReadComplete() task. 1258 base::MessageLoop::current()->RunUntilIdle(); 1259 1260 net::CapturingNetLog::CapturedEntryList entries; 1261 log.GetEntries(&entries); 1262 EXPECT_LT(0u, entries.size()); 1263 1264 // Check that we logged TYPE_SPDY_SESSION_INITIALIZED correctly. 1265 int pos = net::ExpectLogContainsSomewhere( 1266 entries, 0, 1267 net::NetLog::TYPE_SPDY_SESSION_INITIALIZED, 1268 net::NetLog::PHASE_NONE); 1269 EXPECT_LT(0, pos); 1270 1271 CapturingNetLog::CapturedEntry entry = entries[pos]; 1272 NetLog::Source socket_source; 1273 EXPECT_TRUE(NetLog::Source::FromEventParameters(entry.params.get(), 1274 &socket_source)); 1275 EXPECT_TRUE(socket_source.IsValid()); 1276 EXPECT_NE(log.bound().source().id, socket_source.id); 1277} 1278 1279TEST_P(SpdySessionTest, CloseSessionOnError) { 1280 if (GetParam() > kProtoSPDY3) 1281 return; 1282 1283 session_deps_.host_resolver->set_synchronous_mode(true); 1284 1285 MockConnect connect_data(SYNCHRONOUS, OK); 1286 scoped_ptr<SpdyFrame> goaway(spdy_util_.ConstructSpdyGoAway()); 1287 MockRead reads[] = { 1288 CreateMockRead(*goaway), 1289 MockRead(SYNCHRONOUS, 0, 0) // EOF 1290 }; 1291 1292 StaticSocketDataProvider data(reads, arraysize(reads), NULL, 0); 1293 data.set_connect_data(connect_data); 1294 session_deps_.socket_factory->AddSocketDataProvider(&data); 1295 1296 SSLSocketDataProvider ssl(SYNCHRONOUS, OK); 1297 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl); 1298 1299 CreateNetworkSession(); 1300 1301 CapturingBoundNetLog log; 1302 scoped_refptr<SpdySession> session = 1303 spdy_session_pool_->Get(key_, log.bound()); 1304 EXPECT_TRUE(spdy_session_pool_->HasSession(key_)); 1305 1306 EXPECT_EQ(OK, 1307 InitializeSession( 1308 http_session_.get(), session.get(), test_host_port_pair_)); 1309 1310 // Flush the SpdySession::OnReadComplete() task. 1311 base::MessageLoop::current()->RunUntilIdle(); 1312 1313 EXPECT_FALSE(spdy_session_pool_->HasSession(key_)); 1314 1315 // Check that the NetLog was filled reasonably. 1316 net::CapturingNetLog::CapturedEntryList entries; 1317 log.GetEntries(&entries); 1318 EXPECT_LT(0u, entries.size()); 1319 1320 // Check that we logged SPDY_SESSION_CLOSE correctly. 1321 int pos = net::ExpectLogContainsSomewhere( 1322 entries, 0, 1323 net::NetLog::TYPE_SPDY_SESSION_CLOSE, 1324 net::NetLog::PHASE_NONE); 1325 1326 CapturingNetLog::CapturedEntry entry = entries[pos]; 1327 int error_code = 0; 1328 ASSERT_TRUE(entry.GetNetErrorCode(&error_code)); 1329 EXPECT_EQ(ERR_CONNECTION_CLOSED, error_code); 1330} 1331 1332TEST_P(SpdySessionTest, OutOfOrderSynStreams) { 1333 if (GetParam() > kProtoSPDY3) 1334 return; 1335 1336 // Construct the request. 1337 MockConnect connect_data(SYNCHRONOUS, OK); 1338 scoped_ptr<SpdyFrame> req1( 1339 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, HIGHEST, true)); 1340 scoped_ptr<SpdyFrame> req2( 1341 spdy_util_.ConstructSpdyGet(NULL, 0, false, 3, LOWEST, true)); 1342 MockWrite writes[] = { 1343 CreateMockWrite(*req1, 2), 1344 CreateMockWrite(*req2, 1), 1345 }; 1346 1347 scoped_ptr<SpdyFrame> resp1(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1)); 1348 scoped_ptr<SpdyFrame> body1(spdy_util_.ConstructSpdyBodyFrame(1, true)); 1349 scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3)); 1350 scoped_ptr<SpdyFrame> body2(spdy_util_.ConstructSpdyBodyFrame(3, true)); 1351 MockRead reads[] = { 1352 CreateMockRead(*resp1, 3), 1353 CreateMockRead(*body1, 4), 1354 CreateMockRead(*resp2, 5), 1355 CreateMockRead(*body2, 6), 1356 MockRead(ASYNC, 0, 7) // EOF 1357 }; 1358 1359 session_deps_.host_resolver->set_synchronous_mode(true); 1360 1361 StaticSocketDataProvider data(reads, arraysize(reads), 1362 writes, arraysize(writes)); 1363 data.set_connect_data(connect_data); 1364 session_deps_.socket_factory->AddSocketDataProvider(&data); 1365 1366 SSLSocketDataProvider ssl(SYNCHRONOUS, OK); 1367 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl); 1368 1369 CreateNetworkSession(); 1370 1371 scoped_refptr<SpdySession> session = CreateInitializedSession(); 1372 1373 GURL url("http://www.google.com"); 1374 1375 base::WeakPtr<SpdyStream> spdy_stream1 = 1376 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM, 1377 session, url, LOWEST, BoundNetLog()); 1378 ASSERT_TRUE(spdy_stream1.get() != NULL); 1379 EXPECT_EQ(0u, spdy_stream1->stream_id()); 1380 test::StreamDelegateDoNothing delegate1(spdy_stream1); 1381 spdy_stream1->SetDelegate(&delegate1); 1382 1383 base::WeakPtr<SpdyStream> spdy_stream2 = 1384 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM, 1385 session, url, HIGHEST, BoundNetLog()); 1386 ASSERT_TRUE(spdy_stream2.get() != NULL); 1387 EXPECT_EQ(0u, spdy_stream2->stream_id()); 1388 test::StreamDelegateDoNothing delegate2(spdy_stream2); 1389 spdy_stream2->SetDelegate(&delegate2); 1390 1391 scoped_ptr<SpdyHeaderBlock> headers( 1392 spdy_util_.ConstructGetHeaderBlock(url.spec())); 1393 spdy_stream1->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND); 1394 EXPECT_TRUE(spdy_stream1->HasUrl()); 1395 1396 scoped_ptr<SpdyHeaderBlock> headers2( 1397 spdy_util_.ConstructGetHeaderBlock(url.spec())); 1398 spdy_stream2->SendRequestHeaders(headers2.Pass(), NO_MORE_DATA_TO_SEND); 1399 EXPECT_TRUE(spdy_stream2->HasUrl()); 1400 1401 base::MessageLoop::current()->RunUntilIdle(); 1402 1403 EXPECT_EQ(NULL, spdy_stream1.get()); 1404 EXPECT_EQ(NULL, spdy_stream2.get()); 1405 EXPECT_EQ(3u, delegate1.stream_id()); 1406 EXPECT_EQ(1u, delegate2.stream_id()); 1407} 1408 1409TEST_P(SpdySessionTest, CancelStream) { 1410 if (GetParam() > kProtoSPDY3) 1411 return; 1412 1413 MockConnect connect_data(SYNCHRONOUS, OK); 1414 // Request 1, at HIGHEST priority, will be cancelled before it writes data. 1415 // Request 2, at LOWEST priority, will be a full request and will be id 1. 1416 scoped_ptr<SpdyFrame> req2( 1417 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true)); 1418 MockWrite writes[] = { 1419 CreateMockWrite(*req2, 0), 1420 }; 1421 1422 scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1)); 1423 scoped_ptr<SpdyFrame> body2(spdy_util_.ConstructSpdyBodyFrame(1, true)); 1424 MockRead reads[] = { 1425 CreateMockRead(*resp2, 1), 1426 CreateMockRead(*body2, 2), 1427 MockRead(ASYNC, 0, 3) // EOF 1428 }; 1429 1430 session_deps_.host_resolver->set_synchronous_mode(true); 1431 1432 DeterministicSocketData data(reads, arraysize(reads), 1433 writes, arraysize(writes)); 1434 data.set_connect_data(connect_data); 1435 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data); 1436 1437 SSLSocketDataProvider ssl(SYNCHRONOUS, OK); 1438 session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl); 1439 1440 CreateDeterministicNetworkSession(); 1441 1442 scoped_refptr<SpdySession> session = CreateInitializedSession(); 1443 1444 GURL url1("http://www.google.com"); 1445 base::WeakPtr<SpdyStream> spdy_stream1 = 1446 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM, 1447 session, url1, HIGHEST, BoundNetLog()); 1448 ASSERT_TRUE(spdy_stream1.get() != NULL); 1449 EXPECT_EQ(0u, spdy_stream1->stream_id()); 1450 test::StreamDelegateDoNothing delegate1(spdy_stream1); 1451 spdy_stream1->SetDelegate(&delegate1); 1452 1453 GURL url2("http://www.google.com"); 1454 base::WeakPtr<SpdyStream> spdy_stream2 = 1455 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM, 1456 session, url2, LOWEST, BoundNetLog()); 1457 ASSERT_TRUE(spdy_stream2.get() != NULL); 1458 EXPECT_EQ(0u, spdy_stream2->stream_id()); 1459 test::StreamDelegateDoNothing delegate2(spdy_stream2); 1460 spdy_stream2->SetDelegate(&delegate2); 1461 1462 scoped_ptr<SpdyHeaderBlock> headers( 1463 spdy_util_.ConstructGetHeaderBlock(url1.spec())); 1464 spdy_stream1->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND); 1465 EXPECT_TRUE(spdy_stream1->HasUrl()); 1466 1467 scoped_ptr<SpdyHeaderBlock> headers2( 1468 spdy_util_.ConstructGetHeaderBlock(url2.spec())); 1469 spdy_stream2->SendRequestHeaders(headers2.Pass(), NO_MORE_DATA_TO_SEND); 1470 EXPECT_TRUE(spdy_stream2->HasUrl()); 1471 1472 EXPECT_EQ(0u, spdy_stream1->stream_id()); 1473 1474 spdy_stream1->Cancel(); 1475 EXPECT_EQ(NULL, spdy_stream1.get()); 1476 1477 EXPECT_EQ(0u, delegate1.stream_id()); 1478 1479 data.RunFor(1); 1480 1481 EXPECT_EQ(0u, delegate1.stream_id()); 1482 EXPECT_EQ(1u, delegate2.stream_id()); 1483 1484 spdy_stream2->Cancel(); 1485 EXPECT_EQ(NULL, spdy_stream2.get()); 1486} 1487 1488TEST_P(SpdySessionTest, CloseSessionWithTwoCreatedStreams) { 1489 if (GetParam() > kProtoSPDY3) 1490 return; 1491 1492 session_deps_.host_resolver->set_synchronous_mode(true); 1493 1494 // Test that if a sesion is closed with two created streams pending, 1495 // it does not crash. http://crbug.com/139518 1496 MockConnect connect_data(SYNCHRONOUS, OK); 1497 1498 // No actual data will be sent. 1499 MockWrite writes[] = { 1500 MockWrite(ASYNC, 0, 1) // EOF 1501 }; 1502 1503 MockRead reads[] = { 1504 MockRead(ASYNC, 0, 0) // EOF 1505 }; 1506 DeterministicSocketData data(reads, arraysize(reads), 1507 writes, arraysize(writes)); 1508 data.set_connect_data(connect_data); 1509 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data); 1510 1511 SSLSocketDataProvider ssl(SYNCHRONOUS, OK); 1512 session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl); 1513 1514 CreateDeterministicNetworkSession(); 1515 1516 scoped_refptr<SpdySession> session = CreateInitializedSession(); 1517 1518 GURL url1("http://www.google.com"); 1519 base::WeakPtr<SpdyStream> spdy_stream1 = 1520 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM, 1521 session, url1, HIGHEST, BoundNetLog()); 1522 ASSERT_TRUE(spdy_stream1.get() != NULL); 1523 EXPECT_EQ(0u, spdy_stream1->stream_id()); 1524 1525 GURL url2("http://www.google.com"); 1526 base::WeakPtr<SpdyStream> spdy_stream2 = 1527 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM, 1528 session, url2, LOWEST, BoundNetLog()); 1529 ASSERT_TRUE(spdy_stream2.get() != NULL); 1530 EXPECT_EQ(0u, spdy_stream2->stream_id()); 1531 1532 test::StreamDelegateDoNothing delegate1(spdy_stream1); 1533 spdy_stream1->SetDelegate(&delegate1); 1534 1535 test::StreamDelegateDoNothing delegate2(spdy_stream2); 1536 spdy_stream2->SetDelegate(&delegate2); 1537 1538 scoped_ptr<SpdyHeaderBlock> headers( 1539 spdy_util_.ConstructGetHeaderBlock(url1.spec())); 1540 spdy_stream1->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND); 1541 EXPECT_TRUE(spdy_stream1->HasUrl()); 1542 1543 scoped_ptr<SpdyHeaderBlock> headers2( 1544 spdy_util_.ConstructGetHeaderBlock(url2.spec())); 1545 spdy_stream2->SendRequestHeaders(headers2.Pass(), NO_MORE_DATA_TO_SEND); 1546 EXPECT_TRUE(spdy_stream2->HasUrl()); 1547 1548 // Ensure that the streams have not yet been activated and assigned an id. 1549 EXPECT_EQ(0u, spdy_stream1->stream_id()); 1550 EXPECT_EQ(0u, spdy_stream2->stream_id()); 1551 1552 // Ensure we don't crash while closing the session. 1553 session->CloseSessionOnError(ERR_ABORTED, true, std::string()); 1554 1555 EXPECT_EQ(NULL, spdy_stream1.get()); 1556 EXPECT_EQ(NULL, spdy_stream2.get()); 1557 1558 EXPECT_TRUE(delegate1.StreamIsClosed()); 1559 EXPECT_TRUE(delegate2.StreamIsClosed()); 1560 1561 session = NULL; 1562} 1563 1564TEST_P(SpdySessionTest, VerifyDomainAuthentication) { 1565 if (GetParam() > kProtoSPDY3) 1566 return; 1567 1568 session_deps_.host_resolver->set_synchronous_mode(true); 1569 1570 MockConnect connect_data(SYNCHRONOUS, OK); 1571 1572 // No actual data will be sent. 1573 MockWrite writes[] = { 1574 MockWrite(ASYNC, 0, 1) // EOF 1575 }; 1576 1577 MockRead reads[] = { 1578 MockRead(ASYNC, 0, 0) // EOF 1579 }; 1580 DeterministicSocketData data(reads, arraysize(reads), 1581 writes, arraysize(writes)); 1582 data.set_connect_data(connect_data); 1583 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data); 1584 1585 // Load a cert that is valid for: 1586 // www.example.org 1587 // mail.example.org 1588 // www.example.com 1589 base::FilePath certs_dir = GetTestCertsDirectory(); 1590 scoped_refptr<X509Certificate> test_cert( 1591 ImportCertFromFile(certs_dir, "spdy_pooling.pem")); 1592 ASSERT_NE(static_cast<X509Certificate*>(NULL), test_cert); 1593 1594 SSLSocketDataProvider ssl(SYNCHRONOUS, OK); 1595 ssl.cert = test_cert; 1596 session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl); 1597 1598 CreateDeterministicNetworkSession(); 1599 1600 scoped_refptr<SpdySession> session = GetSession(key_); 1601 1602 SSLConfig ssl_config; 1603 scoped_refptr<TransportSocketParams> transport_params( 1604 new TransportSocketParams(test_host_port_pair_, 1605 MEDIUM, 1606 false, 1607 false, 1608 OnHostResolutionCallback())); 1609 scoped_refptr<SOCKSSocketParams> socks_params; 1610 scoped_refptr<HttpProxySocketParams> http_proxy_params; 1611 scoped_refptr<SSLSocketParams> ssl_params( 1612 new SSLSocketParams(transport_params, 1613 socks_params, 1614 http_proxy_params, 1615 ProxyServer::SCHEME_DIRECT, 1616 test_host_port_pair_, 1617 ssl_config, 1618 0, 1619 false, 1620 false)); 1621 scoped_ptr<ClientSocketHandle> connection(new ClientSocketHandle); 1622 EXPECT_EQ(OK, connection->Init(test_host_port_pair_.ToString(), 1623 ssl_params, MEDIUM, CompletionCallback(), 1624 http_session_->GetSSLSocketPool( 1625 HttpNetworkSession::NORMAL_SOCKET_POOL), 1626 BoundNetLog())); 1627 1628 EXPECT_EQ(OK, session->InitializeWithSocket(connection.release(), false, OK)); 1629 EXPECT_TRUE(session->VerifyDomainAuthentication("www.example.org")); 1630 EXPECT_TRUE(session->VerifyDomainAuthentication("mail.example.org")); 1631 EXPECT_TRUE(session->VerifyDomainAuthentication("mail.example.com")); 1632 EXPECT_FALSE(session->VerifyDomainAuthentication("mail.google.com")); 1633} 1634 1635TEST_P(SpdySessionTest, ConnectionPooledWithTlsChannelId) { 1636 if (GetParam() > kProtoSPDY3) 1637 return; 1638 1639 session_deps_.host_resolver->set_synchronous_mode(true); 1640 1641 MockConnect connect_data(SYNCHRONOUS, OK); 1642 1643 // No actual data will be sent. 1644 MockWrite writes[] = { 1645 MockWrite(ASYNC, 0, 1) // EOF 1646 }; 1647 1648 MockRead reads[] = { 1649 MockRead(ASYNC, 0, 0) // EOF 1650 }; 1651 DeterministicSocketData data(reads, arraysize(reads), 1652 writes, arraysize(writes)); 1653 data.set_connect_data(connect_data); 1654 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data); 1655 1656 // Load a cert that is valid for: 1657 // www.example.org 1658 // mail.example.org 1659 // www.example.com 1660 base::FilePath certs_dir = GetTestCertsDirectory(); 1661 scoped_refptr<X509Certificate> test_cert( 1662 ImportCertFromFile(certs_dir, "spdy_pooling.pem")); 1663 ASSERT_NE(static_cast<X509Certificate*>(NULL), test_cert); 1664 1665 SSLSocketDataProvider ssl(SYNCHRONOUS, OK); 1666 ssl.channel_id_sent = true; 1667 ssl.cert = test_cert; 1668 session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl); 1669 1670 CreateDeterministicNetworkSession(); 1671 1672 scoped_refptr<SpdySession> session = GetSession(key_); 1673 1674 SSLConfig ssl_config; 1675 scoped_refptr<TransportSocketParams> transport_params( 1676 new TransportSocketParams(test_host_port_pair_, 1677 MEDIUM, 1678 false, 1679 false, 1680 OnHostResolutionCallback())); 1681 scoped_refptr<SOCKSSocketParams> socks_params; 1682 scoped_refptr<HttpProxySocketParams> http_proxy_params; 1683 scoped_refptr<SSLSocketParams> ssl_params( 1684 new SSLSocketParams(transport_params, 1685 socks_params, 1686 http_proxy_params, 1687 ProxyServer::SCHEME_DIRECT, 1688 test_host_port_pair_, 1689 ssl_config, 1690 0, 1691 false, 1692 false)); 1693 scoped_ptr<ClientSocketHandle> connection(new ClientSocketHandle); 1694 EXPECT_EQ(OK, connection->Init(test_host_port_pair_.ToString(), 1695 ssl_params, MEDIUM, CompletionCallback(), 1696 http_session_->GetSSLSocketPool( 1697 HttpNetworkSession::NORMAL_SOCKET_POOL), 1698 BoundNetLog())); 1699 1700 EXPECT_EQ(OK, session->InitializeWithSocket(connection.release(), false, OK)); 1701 EXPECT_TRUE(session->VerifyDomainAuthentication("www.example.org")); 1702 EXPECT_TRUE(session->VerifyDomainAuthentication("mail.example.org")); 1703 EXPECT_FALSE(session->VerifyDomainAuthentication("mail.example.com")); 1704 EXPECT_FALSE(session->VerifyDomainAuthentication("mail.google.com")); 1705} 1706 1707TEST_P(SpdySessionTest, CloseTwoStalledCreateStream) { 1708 if (GetParam() > kProtoSPDY3) 1709 return; 1710 1711 // TODO(rtenneti): Define a helper class/methods and move the common code in 1712 // this file. 1713 MockConnect connect_data(SYNCHRONOUS, OK); 1714 1715 SettingsMap new_settings; 1716 const SpdySettingsIds kSpdySettingsIds1 = SETTINGS_MAX_CONCURRENT_STREAMS; 1717 const uint32 max_concurrent_streams = 1; 1718 new_settings[kSpdySettingsIds1] = 1719 SettingsFlagsAndValue(SETTINGS_FLAG_NONE, max_concurrent_streams); 1720 1721 scoped_ptr<SpdyFrame> req1( 1722 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true)); 1723 scoped_ptr<SpdyFrame> req2( 1724 spdy_util_.ConstructSpdyGet(NULL, 0, false, 3, LOWEST, true)); 1725 scoped_ptr<SpdyFrame> req3( 1726 spdy_util_.ConstructSpdyGet(NULL, 0, false, 5, LOWEST, true)); 1727 MockWrite writes[] = { 1728 CreateMockWrite(*req1, 1), 1729 CreateMockWrite(*req2, 4), 1730 CreateMockWrite(*req3, 7), 1731 }; 1732 1733 // Set up the socket so we read a SETTINGS frame that sets max concurrent 1734 // streams to 1. 1735 scoped_ptr<SpdyFrame> settings_frame( 1736 spdy_util_.ConstructSpdySettings(new_settings)); 1737 1738 scoped_ptr<SpdyFrame> resp1(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1)); 1739 scoped_ptr<SpdyFrame> body1(spdy_util_.ConstructSpdyBodyFrame(1, true)); 1740 1741 scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3)); 1742 scoped_ptr<SpdyFrame> body2(spdy_util_.ConstructSpdyBodyFrame(3, true)); 1743 1744 scoped_ptr<SpdyFrame> resp3(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 5)); 1745 scoped_ptr<SpdyFrame> body3(spdy_util_.ConstructSpdyBodyFrame(5, true)); 1746 1747 MockRead reads[] = { 1748 CreateMockRead(*settings_frame), 1749 CreateMockRead(*resp1, 2), 1750 CreateMockRead(*body1, 3), 1751 CreateMockRead(*resp2, 5), 1752 CreateMockRead(*body2, 6), 1753 CreateMockRead(*resp3, 8), 1754 CreateMockRead(*body3, 9), 1755 MockRead(ASYNC, 0, 10) // EOF 1756 }; 1757 1758 DeterministicSocketData data(reads, arraysize(reads), 1759 writes, arraysize(writes)); 1760 data.set_connect_data(connect_data); 1761 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data); 1762 1763 SSLSocketDataProvider ssl(SYNCHRONOUS, OK); 1764 session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl); 1765 1766 CreateDeterministicNetworkSession(); 1767 1768 scoped_refptr<SpdySession> session = CreateInitializedSession(); 1769 1770 // Read the settings frame. 1771 data.RunFor(1); 1772 1773 GURL url1("http://www.google.com"); 1774 base::WeakPtr<SpdyStream> spdy_stream1 = 1775 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM, 1776 session, url1, LOWEST, BoundNetLog()); 1777 ASSERT_TRUE(spdy_stream1.get() != NULL); 1778 EXPECT_EQ(0u, spdy_stream1->stream_id()); 1779 test::StreamDelegateDoNothing delegate1(spdy_stream1); 1780 spdy_stream1->SetDelegate(&delegate1); 1781 1782 TestCompletionCallback callback2; 1783 GURL url2("http://www.google.com"); 1784 SpdyStreamRequest request2; 1785 ASSERT_EQ(ERR_IO_PENDING, 1786 request2.StartRequest( 1787 SPDY_REQUEST_RESPONSE_STREAM, 1788 session, url2, LOWEST, BoundNetLog(), callback2.callback())); 1789 1790 TestCompletionCallback callback3; 1791 GURL url3("http://www.google.com"); 1792 SpdyStreamRequest request3; 1793 ASSERT_EQ(ERR_IO_PENDING, 1794 request3.StartRequest( 1795 SPDY_REQUEST_RESPONSE_STREAM, 1796 session, url3, LOWEST, BoundNetLog(), callback3.callback())); 1797 1798 EXPECT_EQ(1u, session->num_active_streams() + session->num_created_streams()); 1799 EXPECT_EQ(2u, session->pending_create_stream_queues(LOWEST)); 1800 1801 scoped_ptr<SpdyHeaderBlock> headers( 1802 spdy_util_.ConstructGetHeaderBlock(url1.spec())); 1803 spdy_stream1->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND); 1804 EXPECT_TRUE(spdy_stream1->HasUrl()); 1805 1806 // Run until 1st stream is closed and 2nd one is opened. 1807 EXPECT_EQ(0u, delegate1.stream_id()); 1808 data.RunFor(3); 1809 // Pump loop for SpdySession::ProcessPendingStreamRequests(). 1810 base::MessageLoop::current()->RunUntilIdle(); 1811 EXPECT_EQ(NULL, spdy_stream1.get()); 1812 EXPECT_EQ(1u, delegate1.stream_id()); 1813 EXPECT_EQ(2u, session->num_active_streams() + session->num_created_streams()); 1814 EXPECT_EQ(0u, session->pending_create_stream_queues(LOWEST)); 1815 1816 base::WeakPtr<SpdyStream> stream2 = request2.ReleaseStream(); 1817 test::StreamDelegateDoNothing delegate2(stream2); 1818 stream2->SetDelegate(&delegate2); 1819 scoped_ptr<SpdyHeaderBlock> headers2( 1820 spdy_util_.ConstructGetHeaderBlock(url2.spec())); 1821 stream2->SendRequestHeaders(headers2.Pass(), NO_MORE_DATA_TO_SEND); 1822 EXPECT_TRUE(stream2->HasUrl()); 1823 1824 // Run until 2nd stream is closed. 1825 EXPECT_EQ(0u, delegate2.stream_id()); 1826 data.RunFor(3); 1827 EXPECT_EQ(NULL, stream2.get()); 1828 EXPECT_EQ(3u, delegate2.stream_id()); 1829 EXPECT_EQ(1u, session->num_active_streams() + session->num_created_streams()); 1830 EXPECT_EQ(0u, session->pending_create_stream_queues(LOWEST)); 1831 1832 base::WeakPtr<SpdyStream> stream3 = request3.ReleaseStream(); 1833 test::StreamDelegateDoNothing delegate3(stream3); 1834 stream3->SetDelegate(&delegate3); 1835 scoped_ptr<SpdyHeaderBlock> headers3( 1836 spdy_util_.ConstructGetHeaderBlock(url3.spec())); 1837 stream3->SendRequestHeaders(headers3.Pass(), NO_MORE_DATA_TO_SEND); 1838 EXPECT_TRUE(stream3->HasUrl()); 1839 1840 EXPECT_EQ(0u, delegate3.stream_id()); 1841 data.RunFor(4); 1842 EXPECT_EQ(NULL, stream3.get()); 1843 EXPECT_EQ(5u, delegate3.stream_id()); 1844 EXPECT_EQ(0u, session->num_active_streams() + session->num_created_streams()); 1845 EXPECT_EQ(0u, session->pending_create_stream_queues(LOWEST)); 1846} 1847 1848TEST_P(SpdySessionTest, CancelTwoStalledCreateStream) { 1849 if (GetParam() > kProtoSPDY3) 1850 return; 1851 1852 session_deps_.host_resolver->set_synchronous_mode(true); 1853 1854 MockRead reads[] = { 1855 MockRead(SYNCHRONOUS, ERR_IO_PENDING) // Stall forever. 1856 }; 1857 1858 StaticSocketDataProvider data(reads, arraysize(reads), NULL, 0); 1859 MockConnect connect_data(SYNCHRONOUS, OK); 1860 1861 data.set_connect_data(connect_data); 1862 session_deps_.socket_factory->AddSocketDataProvider(&data); 1863 1864 SSLSocketDataProvider ssl(SYNCHRONOUS, OK); 1865 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl); 1866 1867 CreateNetworkSession(); 1868 1869 // Initialize the SpdySetting with 1 max concurrent streams. 1870 spdy_session_pool_->http_server_properties()->SetSpdySetting( 1871 test_host_port_pair_, 1872 SETTINGS_MAX_CONCURRENT_STREAMS, 1873 SETTINGS_FLAG_PLEASE_PERSIST, 1874 1); 1875 1876 scoped_refptr<SpdySession> session = CreateInitializedSession(); 1877 1878 GURL url1("http://www.google.com"); 1879 base::WeakPtr<SpdyStream> spdy_stream1 = 1880 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM, 1881 session, url1, LOWEST, BoundNetLog()); 1882 ASSERT_TRUE(spdy_stream1.get() != NULL); 1883 EXPECT_EQ(0u, spdy_stream1->stream_id()); 1884 1885 TestCompletionCallback callback2; 1886 GURL url2("http://www.google.com"); 1887 SpdyStreamRequest request2; 1888 ASSERT_EQ(ERR_IO_PENDING, 1889 request2.StartRequest( 1890 SPDY_BIDIRECTIONAL_STREAM, session, url2, LOWEST, BoundNetLog(), 1891 callback2.callback())); 1892 1893 TestCompletionCallback callback3; 1894 GURL url3("http://www.google.com"); 1895 SpdyStreamRequest request3; 1896 ASSERT_EQ(ERR_IO_PENDING, 1897 request3.StartRequest( 1898 SPDY_BIDIRECTIONAL_STREAM, session, url3, LOWEST, BoundNetLog(), 1899 callback3.callback())); 1900 1901 EXPECT_EQ(1u, session->num_active_streams() + session->num_created_streams()); 1902 EXPECT_EQ(2u, session->pending_create_stream_queues(LOWEST)); 1903 1904 // Cancel the first stream, this will allow the second stream to be created. 1905 EXPECT_TRUE(spdy_stream1.get() != NULL); 1906 spdy_stream1->Cancel(); 1907 EXPECT_EQ(NULL, spdy_stream1.get()); 1908 1909 callback2.WaitForResult(); 1910 EXPECT_EQ(2u, session->num_active_streams() + session->num_created_streams()); 1911 EXPECT_EQ(0u, session->pending_create_stream_queues(LOWEST)); 1912 1913 // Cancel the second stream, this will allow the third stream to be created. 1914 base::WeakPtr<SpdyStream> spdy_stream2 = request2.ReleaseStream(); 1915 spdy_stream2->Cancel(); 1916 EXPECT_EQ(NULL, spdy_stream2.get()); 1917 EXPECT_EQ(1u, session->num_active_streams() + session->num_created_streams()); 1918 EXPECT_EQ(0u, session->pending_create_stream_queues(LOWEST)); 1919 1920 // Cancel the third stream. 1921 base::WeakPtr<SpdyStream> spdy_stream3 = request3.ReleaseStream(); 1922 spdy_stream3->Cancel(); 1923 EXPECT_EQ(NULL, spdy_stream3.get()); 1924 EXPECT_EQ(0u, session->num_active_streams() + session->num_created_streams()); 1925 EXPECT_EQ(0u, session->pending_create_stream_queues(LOWEST)); 1926} 1927 1928TEST_P(SpdySessionTest, NeedsCredentials) { 1929 if (GetParam() > kProtoSPDY3) 1930 return; 1931 1932 MockConnect connect_data(SYNCHRONOUS, OK); 1933 MockRead reads[] = { 1934 MockRead(SYNCHRONOUS, ERR_IO_PENDING) // Stall forever. 1935 }; 1936 StaticSocketDataProvider data(reads, arraysize(reads), NULL, 0); 1937 data.set_connect_data(connect_data); 1938 session_deps_.socket_factory->AddSocketDataProvider(&data); 1939 1940 SSLSocketDataProvider ssl(SYNCHRONOUS, OK); 1941 ssl.channel_id_sent = true; 1942 ssl.protocol_negotiated = GetParam(); 1943 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl); 1944 1945 CreateNetworkSession(); 1946 1947 const GURL url("https://www.foo.com"); 1948 HostPortPair test_host_port_pair(url.host(), 443); 1949 SpdySessionKey key(test_host_port_pair, ProxyServer::Direct(), 1950 kPrivacyModeDisabled); 1951 1952 scoped_refptr<SpdySession> session = GetSession(key); 1953 1954 SSLConfig ssl_config; 1955 scoped_refptr<TransportSocketParams> transport_params( 1956 new TransportSocketParams(test_host_port_pair, 1957 MEDIUM, 1958 false, 1959 false, 1960 OnHostResolutionCallback())); 1961 scoped_refptr<SOCKSSocketParams> socks_params; 1962 scoped_refptr<HttpProxySocketParams> http_proxy_params; 1963 scoped_refptr<SSLSocketParams> ssl_params( 1964 new SSLSocketParams(transport_params, 1965 socks_params, 1966 http_proxy_params, 1967 ProxyServer::SCHEME_DIRECT, 1968 test_host_port_pair, 1969 ssl_config, 1970 0, 1971 false, 1972 false)); 1973 scoped_ptr<ClientSocketHandle> connection(new ClientSocketHandle); 1974 EXPECT_EQ(OK, connection->Init(test_host_port_pair.ToString(), 1975 ssl_params, MEDIUM, CompletionCallback(), 1976 http_session_->GetSSLSocketPool( 1977 HttpNetworkSession::NORMAL_SOCKET_POOL), 1978 BoundNetLog())); 1979 1980 EXPECT_EQ(OK, session->InitializeWithSocket(connection.release(), true, OK)); 1981 1982 EXPECT_EQ(spdy_util_.spdy_version() >= SPDY3, session->NeedsCredentials()); 1983 1984 // Flush the SpdySession::OnReadComplete() task. 1985 base::MessageLoop::current()->RunUntilIdle(); 1986 1987 spdy_session_pool_->Remove(session); 1988} 1989 1990TEST_P(SpdySessionTest, SendCredentials) { 1991 if (GetParam() > kProtoSPDY3) 1992 return; 1993 1994 MockConnect connect_data(SYNCHRONOUS, OK); 1995 MockRead reads[] = { 1996 MockRead(SYNCHRONOUS, ERR_IO_PENDING) // Stall forever. 1997 }; 1998 SettingsMap settings; 1999 scoped_ptr<SpdyFrame> settings_frame( 2000 spdy_util_.ConstructSpdySettings(settings)); 2001 MockWrite writes[] = { 2002 CreateMockWrite(*settings_frame), 2003 }; 2004 StaticSocketDataProvider data(reads, arraysize(reads), 2005 writes, arraysize(writes)); 2006 data.set_connect_data(connect_data); 2007 session_deps_.socket_factory->AddSocketDataProvider(&data); 2008 2009 SSLSocketDataProvider ssl(SYNCHRONOUS, OK); 2010 ssl.channel_id_sent = true; 2011 ssl.protocol_negotiated = kProtoSPDY3; 2012 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl); 2013 2014 CreateNetworkSession(); 2015 2016 const GURL kTestUrl("https://www.foo.com"); 2017 HostPortPair test_host_port_pair(kTestUrl.host(), 443); 2018 SpdySessionKey key(test_host_port_pair, ProxyServer::Direct(), 2019 kPrivacyModeDisabled); 2020 2021 scoped_refptr<SpdySession> session = GetSession(key); 2022 2023 SSLConfig ssl_config; 2024 scoped_refptr<TransportSocketParams> transport_params( 2025 new TransportSocketParams(test_host_port_pair, 2026 MEDIUM, 2027 false, 2028 false, 2029 OnHostResolutionCallback())); 2030 scoped_refptr<SOCKSSocketParams> socks_params; 2031 scoped_refptr<HttpProxySocketParams> http_proxy_params; 2032 scoped_refptr<SSLSocketParams> ssl_params( 2033 new SSLSocketParams(transport_params, 2034 socks_params, 2035 http_proxy_params, 2036 ProxyServer::SCHEME_DIRECT, 2037 test_host_port_pair, 2038 ssl_config, 2039 0, 2040 false, 2041 false)); 2042 scoped_ptr<ClientSocketHandle> connection(new ClientSocketHandle); 2043 EXPECT_EQ(OK, connection->Init(test_host_port_pair.ToString(), 2044 ssl_params, MEDIUM, CompletionCallback(), 2045 http_session_->GetSSLSocketPool( 2046 HttpNetworkSession::NORMAL_SOCKET_POOL), 2047 BoundNetLog())); 2048 2049 EXPECT_EQ(OK, session->InitializeWithSocket(connection.release(), true, OK)); 2050 EXPECT_TRUE(session->NeedsCredentials()); 2051 2052 // Flush the SpdySession::OnReadComplete() task. 2053 base::MessageLoop::current()->RunUntilIdle(); 2054 2055 spdy_session_pool_->Remove(session); 2056 EXPECT_FALSE(spdy_session_pool_->HasSession(key)); 2057} 2058 2059TEST_P(SpdySessionTest, UpdateStreamsSendWindowSize) { 2060 if (GetParam() != kProtoSPDY3) 2061 return; 2062 2063 // Set SETTINGS_INITIAL_WINDOW_SIZE to a small number so that WINDOW_UPDATE 2064 // gets sent. 2065 SettingsMap new_settings; 2066 int32 window_size = 1; 2067 new_settings[SETTINGS_INITIAL_WINDOW_SIZE] = 2068 SettingsFlagsAndValue(SETTINGS_FLAG_NONE, window_size); 2069 2070 // Set up the socket so we read a SETTINGS frame that sets 2071 // INITIAL_WINDOW_SIZE. 2072 MockConnect connect_data(SYNCHRONOUS, OK); 2073 scoped_ptr<SpdyFrame> settings_frame( 2074 spdy_util_.ConstructSpdySettings(new_settings)); 2075 MockRead reads[] = { 2076 CreateMockRead(*settings_frame, 0), 2077 MockRead(ASYNC, 0, 1) // EOF 2078 }; 2079 2080 session_deps_.host_resolver->set_synchronous_mode(true); 2081 2082 scoped_ptr<DeterministicSocketData> data( 2083 new DeterministicSocketData(reads, arraysize(reads), NULL, 0)); 2084 data->set_connect_data(connect_data); 2085 session_deps_.deterministic_socket_factory->AddSocketDataProvider(data.get()); 2086 2087 SSLSocketDataProvider ssl(SYNCHRONOUS, OK); 2088 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl); 2089 2090 CreateDeterministicNetworkSession(); 2091 2092 scoped_refptr<SpdySession> session = CreateInitializedSession(); 2093 base::WeakPtr<SpdyStream> spdy_stream1 = 2094 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM, 2095 session, test_url_, MEDIUM, BoundNetLog()); 2096 ASSERT_TRUE(spdy_stream1.get() != NULL); 2097 TestCompletionCallback callback1; 2098 EXPECT_NE(spdy_stream1->send_window_size(), window_size); 2099 2100 data->RunFor(1); // Process the SETTINGS frame, but not the EOF 2101 base::MessageLoop::current()->RunUntilIdle(); 2102 EXPECT_EQ(session->stream_initial_send_window_size(), window_size); 2103 EXPECT_EQ(spdy_stream1->send_window_size(), window_size); 2104 2105 // Release the first one, this will allow the second to be created. 2106 spdy_stream1->Cancel(); 2107 EXPECT_EQ(NULL, spdy_stream1.get()); 2108 2109 base::WeakPtr<SpdyStream> spdy_stream2 = 2110 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM, 2111 session, test_url_, MEDIUM, BoundNetLog()); 2112 ASSERT_TRUE(spdy_stream2.get() != NULL); 2113 EXPECT_EQ(spdy_stream2->send_window_size(), window_size); 2114 spdy_stream2->Cancel(); 2115 EXPECT_EQ(NULL, spdy_stream2.get()); 2116} 2117 2118// Test that SpdySession::DoRead reads data from the socket without yielding. 2119// This test makes 32k - 1 bytes of data available on the socket for reading. It 2120// then verifies that it has read all the available data without yielding. 2121TEST_P(SpdySessionTest, ReadDataWithoutYielding) { 2122 if (GetParam() > kProtoSPDY3) 2123 return; 2124 2125 MockConnect connect_data(SYNCHRONOUS, OK); 2126 BufferedSpdyFramer framer(spdy_util_.spdy_version(), false); 2127 2128 scoped_ptr<SpdyFrame> req1( 2129 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, MEDIUM, true)); 2130 MockWrite writes[] = { 2131 CreateMockWrite(*req1, 0), 2132 }; 2133 2134 // Build buffer of size kMaxReadBytes / 4 (-spdy_data_frame_size). 2135 ASSERT_EQ(32 * 1024, kMaxReadBytes); 2136 const int kPayloadSize = 2137 kMaxReadBytes / 4 - framer.GetControlFrameHeaderSize(); 2138 TestDataStream test_stream; 2139 scoped_refptr<net::IOBuffer> payload(new net::IOBuffer(kPayloadSize)); 2140 char* payload_data = payload->data(); 2141 test_stream.GetBytes(payload_data, kPayloadSize); 2142 2143 scoped_ptr<SpdyFrame> partial_data_frame( 2144 framer.CreateDataFrame(1, payload_data, kPayloadSize, DATA_FLAG_NONE)); 2145 scoped_ptr<SpdyFrame> finish_data_frame( 2146 framer.CreateDataFrame(1, payload_data, kPayloadSize - 1, DATA_FLAG_FIN)); 2147 2148 scoped_ptr<SpdyFrame> resp1(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1)); 2149 2150 // Write 1 byte less than kMaxReadBytes to check that DoRead reads up to 32k 2151 // bytes. 2152 MockRead reads[] = { 2153 CreateMockRead(*resp1, 1), 2154 CreateMockRead(*partial_data_frame, 2), 2155 CreateMockRead(*partial_data_frame, 3, SYNCHRONOUS), 2156 CreateMockRead(*partial_data_frame, 4, SYNCHRONOUS), 2157 CreateMockRead(*finish_data_frame, 5, SYNCHRONOUS), 2158 MockRead(ASYNC, 0, 6) // EOF 2159 }; 2160 2161 // Create SpdySession and SpdyStream and send the request. 2162 DeterministicSocketData data(reads, arraysize(reads), 2163 writes, arraysize(writes)); 2164 data.set_connect_data(connect_data); 2165 session_deps_.host_resolver->set_synchronous_mode(true); 2166 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data); 2167 2168 SSLSocketDataProvider ssl(SYNCHRONOUS, OK); 2169 session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl); 2170 2171 CreateDeterministicNetworkSession(); 2172 2173 scoped_refptr<SpdySession> session = CreateInitializedSession(); 2174 2175 GURL url1("http://www.google.com"); 2176 base::WeakPtr<SpdyStream> spdy_stream1 = 2177 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM, 2178 session, url1, MEDIUM, BoundNetLog()); 2179 ASSERT_TRUE(spdy_stream1.get() != NULL); 2180 EXPECT_EQ(0u, spdy_stream1->stream_id()); 2181 test::StreamDelegateDoNothing delegate1(spdy_stream1); 2182 spdy_stream1->SetDelegate(&delegate1); 2183 2184 scoped_ptr<SpdyHeaderBlock> headers1( 2185 spdy_util_.ConstructGetHeaderBlock(url1.spec())); 2186 spdy_stream1->SendRequestHeaders(headers1.Pass(), NO_MORE_DATA_TO_SEND); 2187 EXPECT_TRUE(spdy_stream1->HasUrl()); 2188 2189 // Set up the TaskObserver to verify SpdySession::DoRead doesn't post a task. 2190 SpdySessionTestTaskObserver observer("spdy_session.cc", "DoRead"); 2191 2192 // Run until 1st read. 2193 EXPECT_EQ(0u, delegate1.stream_id()); 2194 data.RunFor(2); 2195 EXPECT_EQ(1u, delegate1.stream_id()); 2196 EXPECT_EQ(0u, observer.executed_count()); 2197 2198 // Read all the data and verify SpdySession::DoRead has not posted a task. 2199 data.RunFor(4); 2200 EXPECT_EQ(NULL, spdy_stream1.get()); 2201 2202 // Verify task observer's executed_count is zero, which indicates DoRead read 2203 // all the available data. 2204 EXPECT_EQ(0u, observer.executed_count()); 2205 EXPECT_TRUE(data.at_write_eof()); 2206 EXPECT_TRUE(data.at_read_eof()); 2207} 2208 2209// Test that SpdySession::DoRead yields while reading the data. This test makes 2210// 32k + 1 bytes of data available on the socket for reading. It then verifies 2211// that DoRead has yielded even though there is data available for it to read 2212// (i.e, socket()->Read didn't return ERR_IO_PENDING during socket reads). 2213TEST_P(SpdySessionTest, TestYieldingDuringReadData) { 2214 if (GetParam() > kProtoSPDY3) 2215 return; 2216 2217 MockConnect connect_data(SYNCHRONOUS, OK); 2218 BufferedSpdyFramer framer(spdy_util_.spdy_version(), false); 2219 2220 scoped_ptr<SpdyFrame> req1( 2221 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, MEDIUM, true)); 2222 MockWrite writes[] = { 2223 CreateMockWrite(*req1, 0), 2224 }; 2225 2226 // Build buffer of size kMaxReadBytes / 4 (-spdy_data_frame_size). 2227 ASSERT_EQ(32 * 1024, kMaxReadBytes); 2228 const int kPayloadSize = 2229 kMaxReadBytes / 4 - framer.GetControlFrameHeaderSize(); 2230 TestDataStream test_stream; 2231 scoped_refptr<net::IOBuffer> payload(new net::IOBuffer(kPayloadSize)); 2232 char* payload_data = payload->data(); 2233 test_stream.GetBytes(payload_data, kPayloadSize); 2234 2235 scoped_ptr<SpdyFrame> partial_data_frame( 2236 framer.CreateDataFrame(1, payload_data, kPayloadSize, DATA_FLAG_NONE)); 2237 scoped_ptr<SpdyFrame> finish_data_frame( 2238 framer.CreateDataFrame(1, "h", 1, DATA_FLAG_FIN)); 2239 2240 scoped_ptr<SpdyFrame> resp1(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1)); 2241 2242 // Write 1 byte more than kMaxReadBytes to check that DoRead yields. 2243 MockRead reads[] = { 2244 CreateMockRead(*resp1, 1), 2245 CreateMockRead(*partial_data_frame, 2), 2246 CreateMockRead(*partial_data_frame, 3, SYNCHRONOUS), 2247 CreateMockRead(*partial_data_frame, 4, SYNCHRONOUS), 2248 CreateMockRead(*partial_data_frame, 5, SYNCHRONOUS), 2249 CreateMockRead(*finish_data_frame, 6, SYNCHRONOUS), 2250 MockRead(ASYNC, 0, 7) // EOF 2251 }; 2252 2253 // Create SpdySession and SpdyStream and send the request. 2254 DeterministicSocketData data(reads, arraysize(reads), 2255 writes, arraysize(writes)); 2256 data.set_connect_data(connect_data); 2257 session_deps_.host_resolver->set_synchronous_mode(true); 2258 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data); 2259 2260 SSLSocketDataProvider ssl(SYNCHRONOUS, OK); 2261 session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl); 2262 2263 CreateDeterministicNetworkSession(); 2264 2265 scoped_refptr<SpdySession> session = CreateInitializedSession(); 2266 2267 GURL url1("http://www.google.com"); 2268 base::WeakPtr<SpdyStream> spdy_stream1 = 2269 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM, 2270 session, url1, MEDIUM, BoundNetLog()); 2271 ASSERT_TRUE(spdy_stream1.get() != NULL); 2272 EXPECT_EQ(0u, spdy_stream1->stream_id()); 2273 test::StreamDelegateDoNothing delegate1(spdy_stream1); 2274 spdy_stream1->SetDelegate(&delegate1); 2275 2276 scoped_ptr<SpdyHeaderBlock> headers1( 2277 spdy_util_.ConstructGetHeaderBlock(url1.spec())); 2278 spdy_stream1->SendRequestHeaders(headers1.Pass(), NO_MORE_DATA_TO_SEND); 2279 EXPECT_TRUE(spdy_stream1->HasUrl()); 2280 2281 // Set up the TaskObserver to verify SpdySession::DoRead posts a task. 2282 SpdySessionTestTaskObserver observer("spdy_session.cc", "DoRead"); 2283 2284 // Run until 1st read. 2285 EXPECT_EQ(0u, delegate1.stream_id()); 2286 data.RunFor(2); 2287 EXPECT_EQ(1u, delegate1.stream_id()); 2288 EXPECT_EQ(0u, observer.executed_count()); 2289 2290 // Read all the data and verify SpdySession::DoRead has posted a task. 2291 data.RunFor(6); 2292 EXPECT_EQ(NULL, spdy_stream1.get()); 2293 2294 // Verify task observer's executed_count is 1, which indicates DoRead has 2295 // posted only one task and thus yielded though there is data available for it 2296 // to read. 2297 EXPECT_EQ(1u, observer.executed_count()); 2298 EXPECT_TRUE(data.at_write_eof()); 2299 EXPECT_TRUE(data.at_read_eof()); 2300} 2301 2302// Test that SpdySession::DoRead() tests interactions of yielding + async, 2303// by doing the following MockReads. 2304// 2305// MockRead of SYNCHRONOUS 8K, SYNCHRONOUS 8K, SYNCHRONOUS 8K, SYNCHRONOUS 2K 2306// ASYNC 8K, SYNCHRONOUS 8K, SYNCHRONOUS 8K, SYNCHRONOUS 8K, SYNCHRONOUS 2K. 2307// 2308// The above reads 26K synchronously. Since that is less that 32K, we will 2309// attempt to read again. However, that DoRead() will return ERR_IO_PENDING 2310// (because of async read), so DoRead() will yield. When we come back, DoRead() 2311// will read the results from the async read, and rest of the data 2312// synchronously. 2313TEST_P(SpdySessionTest, TestYieldingDuringAsyncReadData) { 2314 if (GetParam() > kProtoSPDY3) 2315 return; 2316 2317 MockConnect connect_data(SYNCHRONOUS, OK); 2318 BufferedSpdyFramer framer(spdy_util_.spdy_version(), false); 2319 2320 scoped_ptr<SpdyFrame> req1( 2321 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, MEDIUM, true)); 2322 MockWrite writes[] = { 2323 CreateMockWrite(*req1, 0), 2324 }; 2325 2326 // Build buffer of size kMaxReadBytes / 4 (-spdy_data_frame_size). 2327 ASSERT_EQ(32 * 1024, kMaxReadBytes); 2328 TestDataStream test_stream; 2329 const int kEightKPayloadSize = 2330 kMaxReadBytes / 4 - framer.GetControlFrameHeaderSize(); 2331 scoped_refptr<net::IOBuffer> eightk_payload( 2332 new net::IOBuffer(kEightKPayloadSize)); 2333 char* eightk_payload_data = eightk_payload->data(); 2334 test_stream.GetBytes(eightk_payload_data, kEightKPayloadSize); 2335 2336 // Build buffer of 2k size. 2337 TestDataStream test_stream2; 2338 const int kTwoKPayloadSize = kEightKPayloadSize - 6 * 1024; 2339 scoped_refptr<net::IOBuffer> twok_payload( 2340 new net::IOBuffer(kTwoKPayloadSize)); 2341 char* twok_payload_data = twok_payload->data(); 2342 test_stream2.GetBytes(twok_payload_data, kTwoKPayloadSize); 2343 2344 scoped_ptr<SpdyFrame> eightk_data_frame(framer.CreateDataFrame( 2345 1, eightk_payload_data, kEightKPayloadSize, DATA_FLAG_NONE)); 2346 scoped_ptr<SpdyFrame> twok_data_frame(framer.CreateDataFrame( 2347 1, twok_payload_data, kTwoKPayloadSize, DATA_FLAG_NONE)); 2348 scoped_ptr<SpdyFrame> finish_data_frame(framer.CreateDataFrame( 2349 1, "h", 1, DATA_FLAG_FIN)); 2350 2351 scoped_ptr<SpdyFrame> resp1(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1)); 2352 2353 MockRead reads[] = { 2354 CreateMockRead(*resp1, 1), 2355 CreateMockRead(*eightk_data_frame, 2), 2356 CreateMockRead(*eightk_data_frame, 3, SYNCHRONOUS), 2357 CreateMockRead(*eightk_data_frame, 4, SYNCHRONOUS), 2358 CreateMockRead(*twok_data_frame, 5, SYNCHRONOUS), 2359 CreateMockRead(*eightk_data_frame, 6, ASYNC), 2360 CreateMockRead(*eightk_data_frame, 7, SYNCHRONOUS), 2361 CreateMockRead(*eightk_data_frame, 8, SYNCHRONOUS), 2362 CreateMockRead(*eightk_data_frame, 9, SYNCHRONOUS), 2363 CreateMockRead(*twok_data_frame, 10, SYNCHRONOUS), 2364 CreateMockRead(*finish_data_frame, 11, SYNCHRONOUS), 2365 MockRead(ASYNC, 0, 12) // EOF 2366 }; 2367 2368 // Create SpdySession and SpdyStream and send the request. 2369 DeterministicSocketData data(reads, arraysize(reads), 2370 writes, arraysize(writes)); 2371 data.set_connect_data(connect_data); 2372 session_deps_.host_resolver->set_synchronous_mode(true); 2373 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data); 2374 2375 SSLSocketDataProvider ssl(SYNCHRONOUS, OK); 2376 session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl); 2377 2378 CreateDeterministicNetworkSession(); 2379 2380 scoped_refptr<SpdySession> session = CreateInitializedSession(); 2381 2382 GURL url1("http://www.google.com"); 2383 base::WeakPtr<SpdyStream> spdy_stream1 = 2384 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM, 2385 session, url1, MEDIUM, BoundNetLog()); 2386 ASSERT_TRUE(spdy_stream1.get() != NULL); 2387 EXPECT_EQ(0u, spdy_stream1->stream_id()); 2388 test::StreamDelegateDoNothing delegate1(spdy_stream1); 2389 spdy_stream1->SetDelegate(&delegate1); 2390 2391 scoped_ptr<SpdyHeaderBlock> headers1( 2392 spdy_util_.ConstructGetHeaderBlock(url1.spec())); 2393 spdy_stream1->SendRequestHeaders(headers1.Pass(), NO_MORE_DATA_TO_SEND); 2394 EXPECT_TRUE(spdy_stream1->HasUrl()); 2395 2396 // Set up the TaskObserver to monitor SpdySession::DoRead posting of tasks. 2397 SpdySessionTestTaskObserver observer("spdy_session.cc", "DoRead"); 2398 2399 // Run until 1st read. 2400 EXPECT_EQ(0u, delegate1.stream_id()); 2401 data.RunFor(2); 2402 EXPECT_EQ(1u, delegate1.stream_id()); 2403 EXPECT_EQ(0u, observer.executed_count()); 2404 2405 // Read all the data and verify SpdySession::DoRead has posted a task. 2406 data.RunFor(12); 2407 EXPECT_EQ(NULL, spdy_stream1.get()); 2408 2409 // Verify task observer's executed_count is 1, which indicates DoRead has 2410 // posted only one task and thus yielded though there is data available for 2411 // it to read. 2412 EXPECT_EQ(1u, observer.executed_count()); 2413 EXPECT_TRUE(data.at_write_eof()); 2414 EXPECT_TRUE(data.at_read_eof()); 2415} 2416 2417// Send a GoAway frame when SpdySession is in DoLoop. If scoped_refptr to 2418// <SpdySession> is deleted from SpdySession::DoLoop(), we get a crash because 2419// GoAway could delete the SpdySession from the SpdySessionPool and the last 2420// reference to SpdySession. 2421TEST_P(SpdySessionTest, GoAwayWhileInDoLoop) { 2422 if (GetParam() > kProtoSPDY3) 2423 return; 2424 2425 MockConnect connect_data(SYNCHRONOUS, OK); 2426 BufferedSpdyFramer framer(spdy_util_.spdy_version(), false); 2427 2428 scoped_ptr<SpdyFrame> req1( 2429 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, MEDIUM, true)); 2430 MockWrite writes[] = { 2431 CreateMockWrite(*req1, 0), 2432 }; 2433 2434 scoped_ptr<SpdyFrame> resp1(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1)); 2435 scoped_ptr<SpdyFrame> body1(spdy_util_.ConstructSpdyBodyFrame(1, true)); 2436 scoped_ptr<SpdyFrame> goaway(spdy_util_.ConstructSpdyGoAway()); 2437 2438 MockRead reads[] = { 2439 CreateMockRead(*resp1, 1), 2440 CreateMockRead(*body1, 2), 2441 CreateMockRead(*goaway, 3), 2442 MockRead(ASYNC, 0, 4) // EOF 2443 }; 2444 2445 // Create SpdySession and SpdyStream and send the request. 2446 DeterministicSocketData data(reads, arraysize(reads), 2447 writes, arraysize(writes)); 2448 data.set_connect_data(connect_data); 2449 session_deps_.host_resolver->set_synchronous_mode(true); 2450 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data); 2451 2452 SSLSocketDataProvider ssl(SYNCHRONOUS, OK); 2453 session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl); 2454 2455 CreateDeterministicNetworkSession(); 2456 2457 scoped_refptr<SpdySession> session = CreateInitializedSession(); 2458 2459 GURL url1("http://www.google.com"); 2460 base::WeakPtr<SpdyStream> spdy_stream1 = 2461 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM, 2462 session, url1, MEDIUM, BoundNetLog()); 2463 test::StreamDelegateDoNothing delegate1(spdy_stream1); 2464 spdy_stream1->SetDelegate(&delegate1); 2465 session = NULL; 2466 ASSERT_TRUE(spdy_stream1.get() != NULL); 2467 EXPECT_EQ(0u, spdy_stream1->stream_id()); 2468 2469 scoped_ptr<SpdyHeaderBlock> headers1( 2470 spdy_util_.ConstructGetHeaderBlock(url1.spec())); 2471 spdy_stream1->SendRequestHeaders(headers1.Pass(), NO_MORE_DATA_TO_SEND); 2472 EXPECT_TRUE(spdy_stream1->HasUrl()); 2473 2474 // Run until 1st read. 2475 EXPECT_EQ(0u, spdy_stream1->stream_id()); 2476 data.RunFor(1); 2477 EXPECT_EQ(1u, spdy_stream1->stream_id()); 2478 2479 // Only references to SpdySession are held by DoLoop and 2480 // SpdySessionPool. If DoLoop doesn't hold the reference, we get a 2481 // crash if SpdySession is deleted from the SpdySessionPool. 2482 2483 // Run until GoAway. 2484 data.RunFor(4); 2485 EXPECT_EQ(NULL, spdy_stream1.get()); 2486 EXPECT_TRUE(data.at_write_eof()); 2487 EXPECT_TRUE(data.at_read_eof()); 2488} 2489 2490// Within this framework, a SpdySession should be initialized with 2491// flow control disabled for protocol version 2, with flow control 2492// enabled only for streams for protocol version 3, and with flow 2493// control enabled for streams and sessions for higher versions. 2494TEST_P(SpdySessionTest, ProtocolNegotiation) { 2495 session_deps_.host_resolver->set_synchronous_mode(true); 2496 2497 MockConnect connect_data(SYNCHRONOUS, OK); 2498 MockRead reads[] = { 2499 MockRead(SYNCHRONOUS, 0, 0) // EOF 2500 }; 2501 StaticSocketDataProvider data(reads, arraysize(reads), NULL, 0); 2502 data.set_connect_data(connect_data); 2503 session_deps_.socket_factory->AddSocketDataProvider(&data); 2504 2505 CreateNetworkSession(); 2506 scoped_refptr<SpdySession> session = GetSession(key_); 2507 2508 EXPECT_EQ(SpdySession::FLOW_CONTROL_NONE, session->flow_control_state()); 2509 EXPECT_TRUE(session->buffered_spdy_framer_ == NULL); 2510 EXPECT_EQ(0, session->session_send_window_size_); 2511 EXPECT_EQ(0, session->session_recv_window_size_); 2512 EXPECT_EQ(0, session->session_unacked_recv_window_bytes_); 2513 2514 InitializeSession( 2515 http_session_.get(), session.get(), test_host_port_pair_); 2516 2517 EXPECT_EQ(spdy_util_.spdy_version(), 2518 session->buffered_spdy_framer_->protocol_version()); 2519 if (GetParam() == kProtoSPDY2) { 2520 EXPECT_EQ(SpdySession::FLOW_CONTROL_NONE, session->flow_control_state()); 2521 EXPECT_EQ(0, session->session_send_window_size_); 2522 EXPECT_EQ(0, session->session_recv_window_size_); 2523 } else if (GetParam() == kProtoSPDY3) { 2524 EXPECT_EQ(SpdySession::FLOW_CONTROL_STREAM, session->flow_control_state()); 2525 EXPECT_EQ(0, session->session_send_window_size_); 2526 EXPECT_EQ(0, session->session_recv_window_size_); 2527 } else { 2528 EXPECT_EQ(SpdySession::FLOW_CONTROL_STREAM_AND_SESSION, 2529 session->flow_control_state()); 2530 EXPECT_EQ(kSpdySessionInitialWindowSize, 2531 session->session_send_window_size_); 2532 EXPECT_EQ(kDefaultInitialRecvWindowSize, 2533 session->session_recv_window_size_); 2534 } 2535 EXPECT_EQ(0, session->session_unacked_recv_window_bytes_); 2536} 2537 2538// SpdySession::{Increase,Decrease}RecvWindowSize should properly 2539// adjust the session receive window size when the "enable_spdy_31" 2540// flag is set. In addition, SpdySession::IncreaseRecvWindowSize 2541// should trigger sending a WINDOW_UPDATE frame for a large enough 2542// delta. 2543TEST_P(SpdySessionTest, AdjustRecvWindowSize) { 2544 if (GetParam() < kProtoSPDY31) 2545 return; 2546 2547 session_deps_.host_resolver->set_synchronous_mode(true); 2548 2549 const int32 delta_window_size = 100; 2550 2551 MockConnect connect_data(SYNCHRONOUS, OK); 2552 MockRead reads[] = { 2553 MockRead(ASYNC, 0, 2) // EOF 2554 }; 2555 scoped_ptr<SpdyFrame> initial_window_update( 2556 spdy_util_.ConstructSpdyWindowUpdate( 2557 kSessionFlowControlStreamId, 2558 kDefaultInitialRecvWindowSize - kSpdySessionInitialWindowSize)); 2559 scoped_ptr<SpdyFrame> window_update( 2560 spdy_util_.ConstructSpdyWindowUpdate( 2561 kSessionFlowControlStreamId, 2562 kSpdySessionInitialWindowSize + delta_window_size)); 2563 MockWrite writes[] = { 2564 CreateMockWrite(*initial_window_update, 0), 2565 CreateMockWrite(*window_update, 1), 2566 }; 2567 DeterministicSocketData data(reads, arraysize(reads), 2568 writes, arraysize(writes)); 2569 data.set_connect_data(connect_data); 2570 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data); 2571 2572 SSLSocketDataProvider ssl(SYNCHRONOUS, OK); 2573 session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl); 2574 2575 CreateDeterministicNetworkSession(); 2576 scoped_refptr<SpdySession> session = GetSession(key_); 2577 InitializeSession( 2578 http_session_.get(), session.get(), test_host_port_pair_); 2579 EXPECT_EQ(SpdySession::FLOW_CONTROL_STREAM_AND_SESSION, 2580 session->flow_control_state()); 2581 2582 EXPECT_EQ(kDefaultInitialRecvWindowSize, session->session_recv_window_size_); 2583 EXPECT_EQ(0, session->session_unacked_recv_window_bytes_); 2584 2585 session->IncreaseRecvWindowSize(delta_window_size); 2586 EXPECT_EQ(kDefaultInitialRecvWindowSize + delta_window_size, 2587 session->session_recv_window_size_); 2588 EXPECT_EQ(delta_window_size, session->session_unacked_recv_window_bytes_); 2589 2590 // Should trigger sending a WINDOW_UPDATE frame. 2591 session->IncreaseRecvWindowSize(kSpdySessionInitialWindowSize); 2592 EXPECT_EQ(kDefaultInitialRecvWindowSize + delta_window_size + 2593 kSpdySessionInitialWindowSize, 2594 session->session_recv_window_size_); 2595 EXPECT_EQ(0, session->session_unacked_recv_window_bytes_); 2596 2597 data.RunFor(2); 2598 2599 session->DecreaseRecvWindowSize( 2600 kDefaultInitialRecvWindowSize + delta_window_size + 2601 kSpdySessionInitialWindowSize); 2602 EXPECT_EQ(0, session->session_recv_window_size_); 2603 EXPECT_EQ(0, session->session_unacked_recv_window_bytes_); 2604} 2605 2606// SpdySession::{Increase,Decrease}SendWindowSize should properly 2607// adjust the session send window size when the "enable_spdy_31" flag 2608// is set. 2609TEST_P(SpdySessionTest, AdjustSendWindowSize) { 2610 if (GetParam() < kProtoSPDY31) 2611 return; 2612 2613 session_deps_.host_resolver->set_synchronous_mode(true); 2614 2615 MockConnect connect_data(SYNCHRONOUS, OK); 2616 MockRead reads[] = { 2617 MockRead(SYNCHRONOUS, 0, 0) // EOF 2618 }; 2619 StaticSocketDataProvider data(reads, arraysize(reads), NULL, 0); 2620 data.set_connect_data(connect_data); 2621 session_deps_.socket_factory->AddSocketDataProvider(&data); 2622 2623 CreateNetworkSession(); 2624 scoped_refptr<SpdySession> session = GetSession(key_); 2625 InitializeSession( 2626 http_session_.get(), session.get(), test_host_port_pair_); 2627 EXPECT_EQ(SpdySession::FLOW_CONTROL_STREAM_AND_SESSION, 2628 session->flow_control_state()); 2629 2630 const int32 delta_window_size = 100; 2631 2632 EXPECT_EQ(kSpdySessionInitialWindowSize, session->session_send_window_size_); 2633 2634 session->IncreaseSendWindowSize(delta_window_size); 2635 EXPECT_EQ(kSpdySessionInitialWindowSize + delta_window_size, 2636 session->session_send_window_size_); 2637 2638 session->DecreaseSendWindowSize(delta_window_size); 2639 EXPECT_EQ(kSpdySessionInitialWindowSize, session->session_send_window_size_); 2640} 2641 2642// Incoming data for an inactive stream should not cause the session 2643// receive window size to decrease. 2644TEST_P(SpdySessionTest, SessionFlowControlInactiveStream) { 2645 if (GetParam() < kProtoSPDY31) 2646 return; 2647 2648 session_deps_.host_resolver->set_synchronous_mode(true); 2649 2650 MockConnect connect_data(SYNCHRONOUS, OK); 2651 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyBodyFrame(1, false)); 2652 MockRead reads[] = { 2653 CreateMockRead(*resp, 1), 2654 MockRead(ASYNC, 0, 2) // EOF 2655 }; 2656 scoped_ptr<SpdyFrame> initial_window_update( 2657 spdy_util_.ConstructSpdyWindowUpdate( 2658 kSessionFlowControlStreamId, 2659 kDefaultInitialRecvWindowSize - kSpdySessionInitialWindowSize)); 2660 MockWrite writes[] = { 2661 CreateMockWrite(*initial_window_update, 0), 2662 }; 2663 DeterministicSocketData data(reads, arraysize(reads), 2664 writes, arraysize(writes)); 2665 data.set_connect_data(connect_data); 2666 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data); 2667 2668 SSLSocketDataProvider ssl(SYNCHRONOUS, OK); 2669 session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl); 2670 2671 CreateDeterministicNetworkSession(); 2672 scoped_refptr<SpdySession> session = GetSession(key_); 2673 InitializeSession( 2674 http_session_.get(), session.get(), test_host_port_pair_); 2675 EXPECT_EQ(SpdySession::FLOW_CONTROL_STREAM_AND_SESSION, 2676 session->flow_control_state()); 2677 2678 EXPECT_EQ(kDefaultInitialRecvWindowSize, session->session_recv_window_size_); 2679 EXPECT_EQ(0, session->session_unacked_recv_window_bytes_); 2680 2681 data.RunFor(3); 2682 2683 EXPECT_EQ(kDefaultInitialRecvWindowSize, session->session_recv_window_size_); 2684 EXPECT_EQ(0, session->session_unacked_recv_window_bytes_); 2685} 2686 2687// A delegate that drops any received data. 2688class DropReceivedDataDelegate : public test::StreamDelegateSendImmediate { 2689 public: 2690 DropReceivedDataDelegate(const base::WeakPtr<SpdyStream>& stream, 2691 base::StringPiece data) 2692 : StreamDelegateSendImmediate(stream, data) {} 2693 2694 virtual ~DropReceivedDataDelegate() {} 2695 2696 // Drop any received data. 2697 virtual int OnDataReceived(scoped_ptr<SpdyBuffer> buffer) OVERRIDE { 2698 return OK; 2699 } 2700}; 2701 2702// Send data back and forth but use a delegate that drops its received 2703// data. The receive window should still increase to its original 2704// value, i.e. we shouldn't "leak" receive window bytes. 2705TEST_P(SpdySessionTest, SessionFlowControlNoReceiveLeaks) { 2706 if (GetParam() < kProtoSPDY31) 2707 return; 2708 2709 const char kStreamUrl[] = "http://www.google.com/"; 2710 2711 const int32 msg_data_size = 100; 2712 const std::string msg_data(msg_data_size, 'a'); 2713 2714 MockConnect connect_data(SYNCHRONOUS, OK); 2715 2716 scoped_ptr<SpdyFrame> initial_window_update( 2717 spdy_util_.ConstructSpdyWindowUpdate( 2718 kSessionFlowControlStreamId, 2719 kDefaultInitialRecvWindowSize - kSpdySessionInitialWindowSize)); 2720 scoped_ptr<SpdyFrame> req( 2721 spdy_util_.ConstructSpdyPost( 2722 kStreamUrl, 1, msg_data_size, MEDIUM, NULL, 0)); 2723 scoped_ptr<SpdyFrame> msg( 2724 spdy_util_.ConstructSpdyBodyFrame( 2725 1, msg_data.data(), msg_data_size, false)); 2726 MockWrite writes[] = { 2727 CreateMockWrite(*initial_window_update, 0), 2728 CreateMockWrite(*req, 1), 2729 CreateMockWrite(*msg, 3), 2730 }; 2731 2732 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1)); 2733 scoped_ptr<SpdyFrame> echo( 2734 spdy_util_.ConstructSpdyBodyFrame( 2735 1, msg_data.data(), msg_data_size, false)); 2736 scoped_ptr<SpdyFrame> window_update( 2737 spdy_util_.ConstructSpdyWindowUpdate( 2738 kSessionFlowControlStreamId, msg_data_size)); 2739 MockRead reads[] = { 2740 CreateMockRead(*resp, 2), 2741 CreateMockRead(*echo, 4), 2742 MockRead(ASYNC, 0, 5) // EOF 2743 }; 2744 2745 // Create SpdySession and SpdyStream and send the request. 2746 DeterministicSocketData data(reads, arraysize(reads), 2747 writes, arraysize(writes)); 2748 data.set_connect_data(connect_data); 2749 session_deps_.host_resolver->set_synchronous_mode(true); 2750 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data); 2751 2752 SSLSocketDataProvider ssl(SYNCHRONOUS, OK); 2753 session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl); 2754 2755 CreateDeterministicNetworkSession(); 2756 2757 scoped_refptr<SpdySession> session = CreateInitializedSession(); 2758 2759 GURL url(kStreamUrl); 2760 base::WeakPtr<SpdyStream> stream = 2761 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM, 2762 session, url, MEDIUM, BoundNetLog()); 2763 ASSERT_TRUE(stream.get() != NULL); 2764 EXPECT_EQ(0u, stream->stream_id()); 2765 2766 DropReceivedDataDelegate delegate(stream, msg_data); 2767 stream->SetDelegate(&delegate); 2768 2769 scoped_ptr<SpdyHeaderBlock> headers( 2770 spdy_util_.ConstructPostHeaderBlock(url.spec(), msg_data_size)); 2771 EXPECT_EQ(ERR_IO_PENDING, 2772 stream->SendRequestHeaders(headers.Pass(), MORE_DATA_TO_SEND)); 2773 EXPECT_TRUE(stream->HasUrl()); 2774 2775 EXPECT_EQ(kDefaultInitialRecvWindowSize, session->session_recv_window_size_); 2776 EXPECT_EQ(0, session->session_unacked_recv_window_bytes_); 2777 2778 data.RunFor(5); 2779 2780 EXPECT_TRUE(data.at_write_eof()); 2781 EXPECT_TRUE(data.at_read_eof()); 2782 2783 EXPECT_EQ(kDefaultInitialRecvWindowSize, session->session_recv_window_size_); 2784 EXPECT_EQ(msg_data_size, session->session_unacked_recv_window_bytes_); 2785 2786 stream->Close(); 2787 EXPECT_EQ(NULL, stream.get()); 2788 2789 EXPECT_EQ(OK, delegate.WaitForClose()); 2790 2791 EXPECT_EQ(kDefaultInitialRecvWindowSize, session->session_recv_window_size_); 2792 EXPECT_EQ(msg_data_size, session->session_unacked_recv_window_bytes_); 2793} 2794 2795// Send data back and forth but close the stream before its data frame 2796// can be written to the socket. The send window should then increase 2797// to its original value, i.e. we shouldn't "leak" send window bytes. 2798TEST_P(SpdySessionTest, SessionFlowControlNoSendLeaks) { 2799 if (GetParam() < kProtoSPDY31) 2800 return; 2801 2802 const char kStreamUrl[] = "http://www.google.com/"; 2803 2804 const int32 msg_data_size = 100; 2805 const std::string msg_data(msg_data_size, 'a'); 2806 2807 MockConnect connect_data(SYNCHRONOUS, OK); 2808 2809 scoped_ptr<SpdyFrame> initial_window_update( 2810 spdy_util_.ConstructSpdyWindowUpdate( 2811 kSessionFlowControlStreamId, 2812 kDefaultInitialRecvWindowSize - kSpdySessionInitialWindowSize)); 2813 scoped_ptr<SpdyFrame> req( 2814 spdy_util_.ConstructSpdyPost( 2815 kStreamUrl, 1, msg_data_size, MEDIUM, NULL, 0)); 2816 MockWrite writes[] = { 2817 CreateMockWrite(*initial_window_update, 0), 2818 CreateMockWrite(*req, 1), 2819 }; 2820 2821 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1)); 2822 MockRead reads[] = { 2823 CreateMockRead(*resp, 2), 2824 MockRead(ASYNC, 0, 3) // EOF 2825 }; 2826 2827 // Create SpdySession and SpdyStream and send the request. 2828 DeterministicSocketData data(reads, arraysize(reads), 2829 writes, arraysize(writes)); 2830 data.set_connect_data(connect_data); 2831 session_deps_.host_resolver->set_synchronous_mode(true); 2832 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data); 2833 2834 SSLSocketDataProvider ssl(SYNCHRONOUS, OK); 2835 session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl); 2836 2837 CreateDeterministicNetworkSession(); 2838 2839 scoped_refptr<SpdySession> session = CreateInitializedSession(); 2840 2841 GURL url(kStreamUrl); 2842 base::WeakPtr<SpdyStream> stream = 2843 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM, 2844 session, url, MEDIUM, BoundNetLog()); 2845 ASSERT_TRUE(stream.get() != NULL); 2846 EXPECT_EQ(0u, stream->stream_id()); 2847 2848 test::StreamDelegateSendImmediate delegate(stream, msg_data); 2849 stream->SetDelegate(&delegate); 2850 2851 scoped_ptr<SpdyHeaderBlock> headers( 2852 spdy_util_.ConstructPostHeaderBlock(url.spec(), msg_data_size)); 2853 EXPECT_EQ(ERR_IO_PENDING, 2854 stream->SendRequestHeaders(headers.Pass(), MORE_DATA_TO_SEND)); 2855 EXPECT_TRUE(stream->HasUrl()); 2856 2857 EXPECT_EQ(kSpdySessionInitialWindowSize, session->session_send_window_size_); 2858 2859 data.RunFor(2); 2860 2861 EXPECT_EQ(kSpdySessionInitialWindowSize, session->session_send_window_size_); 2862 2863 data.RunFor(1); 2864 2865 EXPECT_TRUE(data.at_write_eof()); 2866 EXPECT_TRUE(data.at_read_eof()); 2867 2868 EXPECT_EQ(kSpdySessionInitialWindowSize - msg_data_size, 2869 session->session_send_window_size_); 2870 2871 // Closing the stream should increase the session's send window. 2872 stream->Close(); 2873 EXPECT_EQ(NULL, stream.get()); 2874 2875 EXPECT_EQ(kSpdySessionInitialWindowSize, session->session_send_window_size_); 2876 2877 EXPECT_EQ(OK, delegate.WaitForClose()); 2878} 2879 2880// Send data back and forth; the send and receive windows should 2881// change appropriately. 2882TEST_P(SpdySessionTest, SessionFlowControlEndToEnd) { 2883 if (GetParam() < kProtoSPDY31) 2884 return; 2885 2886 const char kStreamUrl[] = "http://www.google.com/"; 2887 2888 const int32 msg_data_size = 100; 2889 const std::string msg_data(msg_data_size, 'a'); 2890 2891 MockConnect connect_data(SYNCHRONOUS, OK); 2892 2893 scoped_ptr<SpdyFrame> initial_window_update( 2894 spdy_util_.ConstructSpdyWindowUpdate( 2895 kSessionFlowControlStreamId, 2896 kDefaultInitialRecvWindowSize - kSpdySessionInitialWindowSize)); 2897 scoped_ptr<SpdyFrame> req( 2898 spdy_util_.ConstructSpdyPost( 2899 kStreamUrl, 1, msg_data_size, MEDIUM, NULL, 0)); 2900 scoped_ptr<SpdyFrame> msg( 2901 spdy_util_.ConstructSpdyBodyFrame( 2902 1, msg_data.data(), msg_data_size, false)); 2903 MockWrite writes[] = { 2904 CreateMockWrite(*initial_window_update, 0), 2905 CreateMockWrite(*req, 1), 2906 CreateMockWrite(*msg, 3), 2907 }; 2908 2909 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1)); 2910 scoped_ptr<SpdyFrame> echo( 2911 spdy_util_.ConstructSpdyBodyFrame( 2912 1, msg_data.data(), msg_data_size, false)); 2913 scoped_ptr<SpdyFrame> window_update( 2914 spdy_util_.ConstructSpdyWindowUpdate( 2915 kSessionFlowControlStreamId, msg_data_size)); 2916 MockRead reads[] = { 2917 CreateMockRead(*resp, 2), 2918 CreateMockRead(*echo, 4), 2919 CreateMockRead(*window_update, 5), 2920 MockRead(ASYNC, 0, 6) // EOF 2921 }; 2922 2923 // Create SpdySession and SpdyStream and send the request. 2924 DeterministicSocketData data(reads, arraysize(reads), 2925 writes, arraysize(writes)); 2926 data.set_connect_data(connect_data); 2927 session_deps_.host_resolver->set_synchronous_mode(true); 2928 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data); 2929 2930 SSLSocketDataProvider ssl(SYNCHRONOUS, OK); 2931 session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl); 2932 2933 CreateDeterministicNetworkSession(); 2934 2935 scoped_refptr<SpdySession> session = CreateInitializedSession(); 2936 2937 GURL url(kStreamUrl); 2938 base::WeakPtr<SpdyStream> stream = 2939 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM, 2940 session, url, MEDIUM, BoundNetLog()); 2941 ASSERT_TRUE(stream.get() != NULL); 2942 EXPECT_EQ(0u, stream->stream_id()); 2943 2944 test::StreamDelegateSendImmediate delegate(stream, msg_data); 2945 stream->SetDelegate(&delegate); 2946 2947 scoped_ptr<SpdyHeaderBlock> headers( 2948 spdy_util_.ConstructPostHeaderBlock(url.spec(), msg_data_size)); 2949 EXPECT_EQ(ERR_IO_PENDING, 2950 stream->SendRequestHeaders(headers.Pass(), MORE_DATA_TO_SEND)); 2951 EXPECT_TRUE(stream->HasUrl()); 2952 2953 EXPECT_EQ(kSpdySessionInitialWindowSize, session->session_send_window_size_); 2954 EXPECT_EQ(kDefaultInitialRecvWindowSize, session->session_recv_window_size_); 2955 EXPECT_EQ(0, session->session_unacked_recv_window_bytes_); 2956 2957 data.RunFor(2); 2958 2959 EXPECT_EQ(kSpdySessionInitialWindowSize, session->session_send_window_size_); 2960 EXPECT_EQ(kDefaultInitialRecvWindowSize, session->session_recv_window_size_); 2961 EXPECT_EQ(0, session->session_unacked_recv_window_bytes_); 2962 2963 data.RunFor(1); 2964 2965 EXPECT_EQ(kSpdySessionInitialWindowSize - msg_data_size, 2966 session->session_send_window_size_); 2967 EXPECT_EQ(kDefaultInitialRecvWindowSize, session->session_recv_window_size_); 2968 EXPECT_EQ(0, session->session_unacked_recv_window_bytes_); 2969 2970 data.RunFor(1); 2971 2972 EXPECT_EQ(kSpdySessionInitialWindowSize - msg_data_size, 2973 session->session_send_window_size_); 2974 EXPECT_EQ(kDefaultInitialRecvWindowSize, session->session_recv_window_size_); 2975 EXPECT_EQ(0, session->session_unacked_recv_window_bytes_); 2976 2977 data.RunFor(1); 2978 2979 EXPECT_EQ(kSpdySessionInitialWindowSize - msg_data_size, 2980 session->session_send_window_size_); 2981 EXPECT_EQ(kDefaultInitialRecvWindowSize - msg_data_size, 2982 session->session_recv_window_size_); 2983 EXPECT_EQ(0, session->session_unacked_recv_window_bytes_); 2984 2985 data.RunFor(1); 2986 2987 EXPECT_EQ(kSpdySessionInitialWindowSize, session->session_send_window_size_); 2988 EXPECT_EQ(kDefaultInitialRecvWindowSize - msg_data_size, 2989 session->session_recv_window_size_); 2990 EXPECT_EQ(0, session->session_unacked_recv_window_bytes_); 2991 2992 EXPECT_TRUE(data.at_write_eof()); 2993 EXPECT_TRUE(data.at_read_eof()); 2994 2995 EXPECT_EQ(msg_data, delegate.TakeReceivedData()); 2996 2997 // Draining the delegate's read queue should increase the session's 2998 // receive window. 2999 EXPECT_EQ(kSpdySessionInitialWindowSize, session->session_send_window_size_); 3000 EXPECT_EQ(kDefaultInitialRecvWindowSize, session->session_recv_window_size_); 3001 EXPECT_EQ(msg_data_size, session->session_unacked_recv_window_bytes_); 3002 3003 stream->Close(); 3004 EXPECT_EQ(NULL, stream.get()); 3005 3006 EXPECT_EQ(OK, delegate.WaitForClose()); 3007 3008 EXPECT_EQ(kSpdySessionInitialWindowSize, session->session_send_window_size_); 3009 EXPECT_EQ(kDefaultInitialRecvWindowSize, session->session_recv_window_size_); 3010 EXPECT_EQ(msg_data_size, session->session_unacked_recv_window_bytes_); 3011} 3012 3013// Given a stall function and an unstall function, runs a test to make 3014// sure that a stream resumes after unstall. 3015void SpdySessionTest::RunResumeAfterUnstallTest( 3016 const base::Callback<void(SpdySession*, SpdyStream*)>& stall_fn, 3017 const base::Callback<void(SpdySession*, SpdyStream*, int32)>& 3018 unstall_function) { 3019 const char kStreamUrl[] = "http://www.google.com/"; 3020 GURL url(kStreamUrl); 3021 3022 session_deps_.host_resolver->set_synchronous_mode(true); 3023 3024 scoped_ptr<SpdyFrame> initial_window_update( 3025 spdy_util_.ConstructSpdyWindowUpdate( 3026 kSessionFlowControlStreamId, 3027 kDefaultInitialRecvWindowSize - kSpdySessionInitialWindowSize)); 3028 scoped_ptr<SpdyFrame> req( 3029 spdy_util_.ConstructSpdyPost( 3030 kStreamUrl, 1, kBodyDataSize, LOWEST, NULL, 0)); 3031 scoped_ptr<SpdyFrame> body( 3032 spdy_util_.ConstructSpdyBodyFrame(1, kBodyData, kBodyDataSize, true)); 3033 MockWrite writes[] = { 3034 CreateMockWrite(*initial_window_update, 0), 3035 CreateMockWrite(*req, 1), 3036 CreateMockWrite(*body, 2), 3037 }; 3038 3039 scoped_ptr<SpdyFrame> resp( 3040 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1)); 3041 scoped_ptr<SpdyFrame> echo( 3042 spdy_util_.ConstructSpdyBodyFrame(1, kBodyData, kBodyDataSize, false)); 3043 MockRead reads[] = { 3044 CreateMockRead(*resp, 3), 3045 MockRead(ASYNC, 0, 0, 4), // EOF 3046 }; 3047 3048 DeterministicSocketData data(reads, arraysize(reads), 3049 writes, arraysize(writes)); 3050 MockConnect connect_data(SYNCHRONOUS, OK); 3051 data.set_connect_data(connect_data); 3052 3053 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data); 3054 3055 CreateDeterministicNetworkSession(); 3056 scoped_refptr<SpdySession> session = GetSession(key_); 3057 InitializeSession( 3058 http_session_.get(), session.get(), test_host_port_pair_); 3059 EXPECT_EQ(SpdySession::FLOW_CONTROL_STREAM_AND_SESSION, 3060 session->flow_control_state()); 3061 3062 base::WeakPtr<SpdyStream> stream = 3063 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM, 3064 session, url, LOWEST, BoundNetLog()); 3065 ASSERT_TRUE(stream.get() != NULL); 3066 3067 test::StreamDelegateWithBody delegate(stream, kBodyDataStringPiece); 3068 stream->SetDelegate(&delegate); 3069 3070 EXPECT_FALSE(stream->HasUrl()); 3071 EXPECT_FALSE(stream->send_stalled_by_flow_control()); 3072 3073 scoped_ptr<SpdyHeaderBlock> headers( 3074 spdy_util_.ConstructPostHeaderBlock(kStreamUrl, kBodyDataSize)); 3075 EXPECT_EQ(ERR_IO_PENDING, 3076 stream->SendRequestHeaders(headers.Pass(), MORE_DATA_TO_SEND)); 3077 EXPECT_TRUE(stream->HasUrl()); 3078 EXPECT_EQ(kStreamUrl, stream->GetUrl().spec()); 3079 3080 stall_fn.Run(session.get(), stream.get()); 3081 3082 data.RunFor(2); 3083 3084 EXPECT_TRUE(stream->send_stalled_by_flow_control()); 3085 3086 unstall_function.Run(session.get(), stream.get(), kBodyDataSize); 3087 3088 EXPECT_FALSE(stream->send_stalled_by_flow_control()); 3089 3090 data.RunFor(3); 3091 3092 EXPECT_EQ(ERR_CONNECTION_CLOSED, delegate.WaitForClose()); 3093 3094 EXPECT_TRUE(delegate.send_headers_completed()); 3095 EXPECT_EQ("200", delegate.GetResponseHeaderValue(":status")); 3096 EXPECT_EQ("HTTP/1.1", delegate.GetResponseHeaderValue(":version")); 3097 EXPECT_EQ(std::string(), delegate.TakeReceivedData()); 3098 EXPECT_TRUE(data.at_write_eof()); 3099} 3100 3101// Run the resume-after-unstall test with all possible stall and 3102// unstall sequences. 3103 3104TEST_P(SpdySessionTest, ResumeAfterUnstallSession) { 3105 if (GetParam() < kProtoSPDY31) 3106 return; 3107 3108 RunResumeAfterUnstallTest( 3109 base::Bind(&SpdySessionTest::StallSessionOnly, 3110 base::Unretained(this)), 3111 base::Bind(&SpdySessionTest::UnstallSessionOnly, 3112 base::Unretained(this))); 3113} 3114 3115// Equivalent to 3116// SpdyStreamTest.ResumeAfterSendWindowSizeIncrease. 3117TEST_P(SpdySessionTest, ResumeAfterUnstallStream) { 3118 if (GetParam() < kProtoSPDY31) 3119 return; 3120 3121 RunResumeAfterUnstallTest( 3122 base::Bind(&SpdySessionTest::StallStreamOnly, 3123 base::Unretained(this)), 3124 base::Bind(&SpdySessionTest::UnstallStreamOnly, 3125 base::Unretained(this))); 3126} 3127 3128TEST_P(SpdySessionTest, StallSessionStreamResumeAfterUnstallSessionStream) { 3129 if (GetParam() < kProtoSPDY31) 3130 return; 3131 3132 RunResumeAfterUnstallTest( 3133 base::Bind(&SpdySessionTest::StallSessionStream, 3134 base::Unretained(this)), 3135 base::Bind(&SpdySessionTest::UnstallSessionStream, 3136 base::Unretained(this))); 3137} 3138 3139TEST_P(SpdySessionTest, StallStreamSessionResumeAfterUnstallSessionStream) { 3140 if (GetParam() < kProtoSPDY31) 3141 return; 3142 3143 RunResumeAfterUnstallTest( 3144 base::Bind(&SpdySessionTest::StallStreamSession, 3145 base::Unretained(this)), 3146 base::Bind(&SpdySessionTest::UnstallSessionStream, 3147 base::Unretained(this))); 3148} 3149 3150TEST_P(SpdySessionTest, StallStreamSessionResumeAfterUnstallStreamSession) { 3151 if (GetParam() < kProtoSPDY31) 3152 return; 3153 3154 RunResumeAfterUnstallTest( 3155 base::Bind(&SpdySessionTest::StallStreamSession, 3156 base::Unretained(this)), 3157 base::Bind(&SpdySessionTest::UnstallStreamSession, 3158 base::Unretained(this))); 3159} 3160 3161TEST_P(SpdySessionTest, StallSessionStreamResumeAfterUnstallStreamSession) { 3162 if (GetParam() < kProtoSPDY31) 3163 return; 3164 3165 RunResumeAfterUnstallTest( 3166 base::Bind(&SpdySessionTest::StallSessionStream, 3167 base::Unretained(this)), 3168 base::Bind(&SpdySessionTest::UnstallStreamSession, 3169 base::Unretained(this))); 3170} 3171 3172// Cause a stall by reducing the flow control send window to 0. The 3173// streams should resume in priority order when that window is then 3174// increased. 3175TEST_P(SpdySessionTest, ResumeByPriorityAfterSendWindowSizeIncrease) { 3176 if (GetParam() < kProtoSPDY31) 3177 return; 3178 3179 const char kStreamUrl[] = "http://www.google.com/"; 3180 GURL url(kStreamUrl); 3181 3182 session_deps_.host_resolver->set_synchronous_mode(true); 3183 3184 scoped_ptr<SpdyFrame> initial_window_update( 3185 spdy_util_.ConstructSpdyWindowUpdate( 3186 kSessionFlowControlStreamId, 3187 kDefaultInitialRecvWindowSize - kSpdySessionInitialWindowSize)); 3188 scoped_ptr<SpdyFrame> req1( 3189 spdy_util_.ConstructSpdyPost( 3190 kStreamUrl, 1, kBodyDataSize, LOWEST, NULL, 0)); 3191 scoped_ptr<SpdyFrame> req2( 3192 spdy_util_.ConstructSpdyPost( 3193 kStreamUrl, 3, kBodyDataSize, MEDIUM, NULL, 0)); 3194 scoped_ptr<SpdyFrame> body1( 3195 spdy_util_.ConstructSpdyBodyFrame(1, kBodyData, kBodyDataSize, true)); 3196 scoped_ptr<SpdyFrame> body2( 3197 spdy_util_.ConstructSpdyBodyFrame(3, kBodyData, kBodyDataSize, true)); 3198 MockWrite writes[] = { 3199 CreateMockWrite(*initial_window_update, 0), 3200 CreateMockWrite(*req1, 1), 3201 CreateMockWrite(*req2, 2), 3202 CreateMockWrite(*body2, 3), 3203 CreateMockWrite(*body1, 4), 3204 }; 3205 3206 scoped_ptr<SpdyFrame> resp1(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1)); 3207 scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3)); 3208 MockRead reads[] = { 3209 CreateMockRead(*resp1, 5), 3210 CreateMockRead(*resp2, 6), 3211 MockRead(ASYNC, 0, 0, 7), // EOF 3212 }; 3213 3214 DeterministicSocketData data(reads, arraysize(reads), 3215 writes, arraysize(writes)); 3216 MockConnect connect_data(SYNCHRONOUS, OK); 3217 data.set_connect_data(connect_data); 3218 3219 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data); 3220 3221 CreateDeterministicNetworkSession(); 3222 scoped_refptr<SpdySession> session = GetSession(key_); 3223 InitializeSession( 3224 http_session_.get(), session.get(), test_host_port_pair_); 3225 EXPECT_EQ(SpdySession::FLOW_CONTROL_STREAM_AND_SESSION, 3226 session->flow_control_state()); 3227 3228 base::WeakPtr<SpdyStream> stream1 = 3229 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM, 3230 session, url, LOWEST, BoundNetLog()); 3231 ASSERT_TRUE(stream1.get() != NULL); 3232 3233 test::StreamDelegateWithBody delegate1(stream1, kBodyDataStringPiece); 3234 stream1->SetDelegate(&delegate1); 3235 3236 EXPECT_FALSE(stream1->HasUrl()); 3237 3238 base::WeakPtr<SpdyStream> stream2 = 3239 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM, 3240 session, url, MEDIUM, BoundNetLog()); 3241 ASSERT_TRUE(stream2.get() != NULL); 3242 3243 test::StreamDelegateWithBody delegate2(stream2, kBodyDataStringPiece); 3244 stream2->SetDelegate(&delegate2); 3245 3246 EXPECT_FALSE(stream2->HasUrl()); 3247 3248 EXPECT_FALSE(stream1->send_stalled_by_flow_control()); 3249 EXPECT_FALSE(stream2->send_stalled_by_flow_control()); 3250 3251 StallSessionSend(session.get()); 3252 3253 scoped_ptr<SpdyHeaderBlock> headers1( 3254 spdy_util_.ConstructPostHeaderBlock(kStreamUrl, kBodyDataSize)); 3255 EXPECT_EQ(ERR_IO_PENDING, 3256 stream1->SendRequestHeaders(headers1.Pass(), MORE_DATA_TO_SEND)); 3257 EXPECT_TRUE(stream1->HasUrl()); 3258 EXPECT_EQ(kStreamUrl, stream1->GetUrl().spec()); 3259 3260 data.RunFor(2); 3261 EXPECT_EQ(1u, stream1->stream_id()); 3262 EXPECT_TRUE(stream1->send_stalled_by_flow_control()); 3263 3264 scoped_ptr<SpdyHeaderBlock> headers2( 3265 spdy_util_.ConstructPostHeaderBlock(kStreamUrl, kBodyDataSize)); 3266 EXPECT_EQ(ERR_IO_PENDING, 3267 stream2->SendRequestHeaders(headers2.Pass(), MORE_DATA_TO_SEND)); 3268 EXPECT_TRUE(stream2->HasUrl()); 3269 EXPECT_EQ(kStreamUrl, stream2->GetUrl().spec()); 3270 3271 data.RunFor(1); 3272 EXPECT_EQ(3u, stream2->stream_id()); 3273 EXPECT_TRUE(stream2->send_stalled_by_flow_control()); 3274 3275 // This should unstall only stream2. 3276 UnstallSessionSend(session.get(), kBodyDataSize); 3277 3278 EXPECT_TRUE(stream1->send_stalled_by_flow_control()); 3279 EXPECT_FALSE(stream2->send_stalled_by_flow_control()); 3280 3281 data.RunFor(1); 3282 3283 EXPECT_TRUE(stream1->send_stalled_by_flow_control()); 3284 EXPECT_FALSE(stream2->send_stalled_by_flow_control()); 3285 3286 // This should then unstall stream1. 3287 UnstallSessionSend(session.get(), kBodyDataSize); 3288 3289 EXPECT_FALSE(stream1->send_stalled_by_flow_control()); 3290 EXPECT_FALSE(stream2->send_stalled_by_flow_control()); 3291 3292 data.RunFor(4); 3293 3294 EXPECT_EQ(ERR_CONNECTION_CLOSED, delegate1.WaitForClose()); 3295 EXPECT_EQ(ERR_CONNECTION_CLOSED, delegate2.WaitForClose()); 3296 3297 EXPECT_TRUE(delegate1.send_headers_completed()); 3298 EXPECT_EQ("200", delegate1.GetResponseHeaderValue(":status")); 3299 EXPECT_EQ("HTTP/1.1", delegate1.GetResponseHeaderValue(":version")); 3300 EXPECT_EQ(std::string(), delegate1.TakeReceivedData()); 3301 3302 EXPECT_TRUE(delegate2.send_headers_completed()); 3303 EXPECT_EQ("200", delegate2.GetResponseHeaderValue(":status")); 3304 EXPECT_EQ("HTTP/1.1", delegate2.GetResponseHeaderValue(":version")); 3305 EXPECT_EQ(std::string(), delegate2.TakeReceivedData()); 3306 3307 EXPECT_TRUE(data.at_write_eof()); 3308} 3309 3310// Delegate that closes a given stream after sending its body. 3311class StreamClosingDelegate : public test::StreamDelegateWithBody { 3312 public: 3313 StreamClosingDelegate(const base::WeakPtr<SpdyStream>& stream, 3314 base::StringPiece data) 3315 : StreamDelegateWithBody(stream, data) {} 3316 3317 virtual ~StreamClosingDelegate() {} 3318 3319 void set_stream_to_close(const base::WeakPtr<SpdyStream>& stream_to_close) { 3320 stream_to_close_ = stream_to_close; 3321 } 3322 3323 virtual void OnDataSent() OVERRIDE { 3324 test::StreamDelegateWithBody::OnDataSent(); 3325 if (stream_to_close_.get()) { 3326 stream_to_close_->Close(); 3327 EXPECT_EQ(NULL, stream_to_close_.get()); 3328 } 3329 } 3330 3331 private: 3332 base::WeakPtr<SpdyStream> stream_to_close_; 3333}; 3334 3335// Cause a stall by reducing the flow control send window to 3336// 0. Unstalling the session should properly handle deleted streams. 3337TEST_P(SpdySessionTest, SendWindowSizeIncreaseWithDeletedStreams) { 3338 if (GetParam() < kProtoSPDY31) 3339 return; 3340 3341 const char kStreamUrl[] = "http://www.google.com/"; 3342 GURL url(kStreamUrl); 3343 3344 session_deps_.host_resolver->set_synchronous_mode(true); 3345 3346 scoped_ptr<SpdyFrame> initial_window_update( 3347 spdy_util_.ConstructSpdyWindowUpdate( 3348 kSessionFlowControlStreamId, 3349 kDefaultInitialRecvWindowSize - kSpdySessionInitialWindowSize)); 3350 scoped_ptr<SpdyFrame> req1( 3351 spdy_util_.ConstructSpdyPost( 3352 kStreamUrl, 1, kBodyDataSize, LOWEST, NULL, 0)); 3353 scoped_ptr<SpdyFrame> req2( 3354 spdy_util_.ConstructSpdyPost( 3355 kStreamUrl, 3, kBodyDataSize, LOWEST, NULL, 0)); 3356 scoped_ptr<SpdyFrame> req3( 3357 spdy_util_.ConstructSpdyPost( 3358 kStreamUrl, 5, kBodyDataSize, LOWEST, NULL, 0)); 3359 scoped_ptr<SpdyFrame> body2( 3360 spdy_util_.ConstructSpdyBodyFrame(3, kBodyData, kBodyDataSize, true)); 3361 MockWrite writes[] = { 3362 CreateMockWrite(*initial_window_update, 0), 3363 CreateMockWrite(*req1, 1), 3364 CreateMockWrite(*req2, 2), 3365 CreateMockWrite(*req3, 3), 3366 CreateMockWrite(*body2, 4), 3367 }; 3368 3369 scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3)); 3370 MockRead reads[] = { 3371 CreateMockRead(*resp2, 5), 3372 MockRead(ASYNC, 0, 0, 6), // EOF 3373 }; 3374 3375 DeterministicSocketData data(reads, arraysize(reads), 3376 writes, arraysize(writes)); 3377 MockConnect connect_data(SYNCHRONOUS, OK); 3378 data.set_connect_data(connect_data); 3379 3380 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data); 3381 3382 CreateDeterministicNetworkSession(); 3383 scoped_refptr<SpdySession> session = GetSession(key_); 3384 InitializeSession( 3385 http_session_.get(), session.get(), test_host_port_pair_); 3386 EXPECT_EQ(SpdySession::FLOW_CONTROL_STREAM_AND_SESSION, 3387 session->flow_control_state()); 3388 3389 base::WeakPtr<SpdyStream> stream1 = 3390 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM, 3391 session, url, LOWEST, BoundNetLog()); 3392 ASSERT_TRUE(stream1.get() != NULL); 3393 3394 test::StreamDelegateWithBody delegate1(stream1, kBodyDataStringPiece); 3395 stream1->SetDelegate(&delegate1); 3396 3397 EXPECT_FALSE(stream1->HasUrl()); 3398 3399 base::WeakPtr<SpdyStream> stream2 = 3400 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM, 3401 session, url, LOWEST, BoundNetLog()); 3402 ASSERT_TRUE(stream2.get() != NULL); 3403 3404 StreamClosingDelegate delegate2(stream2, kBodyDataStringPiece); 3405 stream2->SetDelegate(&delegate2); 3406 3407 EXPECT_FALSE(stream2->HasUrl()); 3408 3409 base::WeakPtr<SpdyStream> stream3 = 3410 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM, 3411 session, url, LOWEST, BoundNetLog()); 3412 ASSERT_TRUE(stream3.get() != NULL); 3413 3414 test::StreamDelegateWithBody delegate3(stream3, kBodyDataStringPiece); 3415 stream3->SetDelegate(&delegate3); 3416 3417 EXPECT_FALSE(stream3->HasUrl()); 3418 3419 EXPECT_FALSE(stream1->send_stalled_by_flow_control()); 3420 EXPECT_FALSE(stream2->send_stalled_by_flow_control()); 3421 EXPECT_FALSE(stream3->send_stalled_by_flow_control()); 3422 3423 StallSessionSend(session.get()); 3424 3425 scoped_ptr<SpdyHeaderBlock> headers1( 3426 spdy_util_.ConstructPostHeaderBlock(kStreamUrl, kBodyDataSize)); 3427 EXPECT_EQ(ERR_IO_PENDING, 3428 stream1->SendRequestHeaders(headers1.Pass(), MORE_DATA_TO_SEND)); 3429 EXPECT_TRUE(stream1->HasUrl()); 3430 EXPECT_EQ(kStreamUrl, stream1->GetUrl().spec()); 3431 3432 data.RunFor(2); 3433 EXPECT_EQ(1u, stream1->stream_id()); 3434 EXPECT_TRUE(stream1->send_stalled_by_flow_control()); 3435 3436 scoped_ptr<SpdyHeaderBlock> headers2( 3437 spdy_util_.ConstructPostHeaderBlock(kStreamUrl, kBodyDataSize)); 3438 EXPECT_EQ(ERR_IO_PENDING, 3439 stream2->SendRequestHeaders(headers2.Pass(), MORE_DATA_TO_SEND)); 3440 EXPECT_TRUE(stream2->HasUrl()); 3441 EXPECT_EQ(kStreamUrl, stream2->GetUrl().spec()); 3442 3443 data.RunFor(1); 3444 EXPECT_EQ(3u, stream2->stream_id()); 3445 EXPECT_TRUE(stream2->send_stalled_by_flow_control()); 3446 3447 scoped_ptr<SpdyHeaderBlock> headers3( 3448 spdy_util_.ConstructPostHeaderBlock(kStreamUrl, kBodyDataSize)); 3449 EXPECT_EQ(ERR_IO_PENDING, 3450 stream3->SendRequestHeaders(headers3.Pass(), MORE_DATA_TO_SEND)); 3451 EXPECT_TRUE(stream3->HasUrl()); 3452 EXPECT_EQ(kStreamUrl, stream3->GetUrl().spec()); 3453 3454 data.RunFor(1); 3455 EXPECT_EQ(5u, stream3->stream_id()); 3456 EXPECT_TRUE(stream3->send_stalled_by_flow_control()); 3457 3458 SpdyStreamId stream_id1 = stream1->stream_id(); 3459 SpdyStreamId stream_id2 = stream2->stream_id(); 3460 SpdyStreamId stream_id3 = stream3->stream_id(); 3461 3462 // Close stream1 preemptively. 3463 session->CloseActiveStream(stream_id1, ERR_CONNECTION_CLOSED); 3464 EXPECT_EQ(NULL, stream1.get()); 3465 3466 EXPECT_FALSE(session->IsStreamActive(stream_id1)); 3467 EXPECT_TRUE(session->IsStreamActive(stream_id2)); 3468 EXPECT_TRUE(session->IsStreamActive(stream_id3)); 3469 3470 // Unstall stream2, which should then close stream3. 3471 delegate2.set_stream_to_close(stream3); 3472 UnstallSessionSend(session.get(), kBodyDataSize); 3473 3474 data.RunFor(1); 3475 EXPECT_EQ(NULL, stream3.get()); 3476 3477 EXPECT_FALSE(stream2->send_stalled_by_flow_control()); 3478 EXPECT_FALSE(session->IsStreamActive(stream_id1)); 3479 EXPECT_TRUE(session->IsStreamActive(stream_id2)); 3480 EXPECT_FALSE(session->IsStreamActive(stream_id3)); 3481 3482 data.RunFor(2); 3483 EXPECT_EQ(NULL, stream2.get()); 3484 3485 EXPECT_EQ(ERR_CONNECTION_CLOSED, delegate1.WaitForClose()); 3486 EXPECT_EQ(ERR_CONNECTION_CLOSED, delegate2.WaitForClose()); 3487 EXPECT_EQ(OK, delegate3.WaitForClose()); 3488 3489 EXPECT_TRUE(delegate1.send_headers_completed()); 3490 EXPECT_EQ(std::string(), delegate1.TakeReceivedData()); 3491 3492 EXPECT_TRUE(delegate2.send_headers_completed()); 3493 EXPECT_EQ("200", delegate2.GetResponseHeaderValue(":status")); 3494 EXPECT_EQ("HTTP/1.1", delegate2.GetResponseHeaderValue(":version")); 3495 EXPECT_EQ(std::string(), delegate2.TakeReceivedData()); 3496 3497 EXPECT_TRUE(delegate3.send_headers_completed()); 3498 EXPECT_EQ(std::string(), delegate3.TakeReceivedData()); 3499 3500 EXPECT_TRUE(data.at_write_eof()); 3501} 3502 3503// Cause a stall by reducing the flow control send window to 3504// 0. Unstalling the session should properly handle the session itself 3505// being closed. 3506TEST_P(SpdySessionTest, SendWindowSizeIncreaseWithDeletedSession) { 3507 if (GetParam() < kProtoSPDY31) 3508 return; 3509 3510 const char kStreamUrl[] = "http://www.google.com/"; 3511 GURL url(kStreamUrl); 3512 3513 session_deps_.host_resolver->set_synchronous_mode(true); 3514 3515 scoped_ptr<SpdyFrame> initial_window_update( 3516 spdy_util_.ConstructSpdyWindowUpdate( 3517 kSessionFlowControlStreamId, 3518 kDefaultInitialRecvWindowSize - kSpdySessionInitialWindowSize)); 3519 scoped_ptr<SpdyFrame> req1( 3520 spdy_util_.ConstructSpdyPost( 3521 kStreamUrl, 1, kBodyDataSize, LOWEST, NULL, 0)); 3522 scoped_ptr<SpdyFrame> req2( 3523 spdy_util_.ConstructSpdyPost( 3524 kStreamUrl, 3, kBodyDataSize, LOWEST, NULL, 0)); 3525 scoped_ptr<SpdyFrame> body1( 3526 spdy_util_.ConstructSpdyBodyFrame(1, kBodyData, kBodyDataSize, false)); 3527 MockWrite writes[] = { 3528 CreateMockWrite(*initial_window_update, 0), 3529 CreateMockWrite(*req1, 1), 3530 CreateMockWrite(*req2, 2), 3531 }; 3532 3533 MockRead reads[] = { 3534 MockRead(ASYNC, 0, 0, 3), // EOF 3535 }; 3536 3537 DeterministicSocketData data(reads, arraysize(reads), 3538 writes, arraysize(writes)); 3539 MockConnect connect_data(SYNCHRONOUS, OK); 3540 data.set_connect_data(connect_data); 3541 3542 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data); 3543 3544 CreateDeterministicNetworkSession(); 3545 scoped_refptr<SpdySession> session = GetSession(key_); 3546 InitializeSession( 3547 http_session_.get(), session.get(), test_host_port_pair_); 3548 EXPECT_EQ(SpdySession::FLOW_CONTROL_STREAM_AND_SESSION, 3549 session->flow_control_state()); 3550 3551 base::WeakPtr<SpdyStream> stream1 = 3552 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM, 3553 session, url, LOWEST, BoundNetLog()); 3554 ASSERT_TRUE(stream1.get() != NULL); 3555 3556 test::StreamDelegateWithBody delegate1(stream1, kBodyDataStringPiece); 3557 stream1->SetDelegate(&delegate1); 3558 3559 EXPECT_FALSE(stream1->HasUrl()); 3560 3561 base::WeakPtr<SpdyStream> stream2 = 3562 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM, 3563 session, url, LOWEST, BoundNetLog()); 3564 ASSERT_TRUE(stream2.get() != NULL); 3565 3566 test::StreamDelegateWithBody delegate2(stream2, kBodyDataStringPiece); 3567 stream2->SetDelegate(&delegate2); 3568 3569 EXPECT_FALSE(stream2->HasUrl()); 3570 3571 EXPECT_FALSE(stream1->send_stalled_by_flow_control()); 3572 EXPECT_FALSE(stream2->send_stalled_by_flow_control()); 3573 3574 StallSessionSend(session.get()); 3575 3576 scoped_ptr<SpdyHeaderBlock> headers1( 3577 spdy_util_.ConstructPostHeaderBlock(kStreamUrl, kBodyDataSize)); 3578 EXPECT_EQ(ERR_IO_PENDING, 3579 stream1->SendRequestHeaders(headers1.Pass(), MORE_DATA_TO_SEND)); 3580 EXPECT_TRUE(stream1->HasUrl()); 3581 EXPECT_EQ(kStreamUrl, stream1->GetUrl().spec()); 3582 3583 data.RunFor(2); 3584 EXPECT_EQ(1u, stream1->stream_id()); 3585 EXPECT_TRUE(stream1->send_stalled_by_flow_control()); 3586 3587 scoped_ptr<SpdyHeaderBlock> headers2( 3588 spdy_util_.ConstructPostHeaderBlock(kStreamUrl, kBodyDataSize)); 3589 EXPECT_EQ(ERR_IO_PENDING, 3590 stream2->SendRequestHeaders(headers2.Pass(), MORE_DATA_TO_SEND)); 3591 EXPECT_TRUE(stream2->HasUrl()); 3592 EXPECT_EQ(kStreamUrl, stream2->GetUrl().spec()); 3593 3594 data.RunFor(1); 3595 EXPECT_EQ(3u, stream2->stream_id()); 3596 EXPECT_TRUE(stream2->send_stalled_by_flow_control()); 3597 3598 EXPECT_TRUE(spdy_session_pool_->HasSession(key_)); 3599 3600 // Unstall stream1. 3601 UnstallSessionSend(session.get(), kBodyDataSize); 3602 3603 // Close the session (since we can't do it from within the delegate 3604 // method, since it's in the stream's loop). 3605 session->CloseSessionOnError(ERR_CONNECTION_CLOSED, true, "Closing session"); 3606 session = NULL; 3607 3608 EXPECT_FALSE(spdy_session_pool_->HasSession(key_)); 3609 3610 EXPECT_EQ(ERR_CONNECTION_CLOSED, delegate1.WaitForClose()); 3611 EXPECT_EQ(ERR_CONNECTION_CLOSED, delegate2.WaitForClose()); 3612 3613 EXPECT_TRUE(delegate1.send_headers_completed()); 3614 EXPECT_EQ(std::string(), delegate1.TakeReceivedData()); 3615 3616 EXPECT_TRUE(delegate2.send_headers_completed()); 3617 EXPECT_EQ(std::string(), delegate2.TakeReceivedData()); 3618 3619 EXPECT_TRUE(data.at_write_eof()); 3620} 3621 3622// Tests the case of a non-SPDY request closing an idle SPDY session when no 3623// pointers to the idle session are currently held. 3624TEST_P(SpdySessionTest, CloseOneIdleConnection) { 3625 if (GetParam() > kProtoSPDY3) 3626 return; 3627 3628 ClientSocketPoolManager::set_max_sockets_per_group( 3629 HttpNetworkSession::NORMAL_SOCKET_POOL, 1); 3630 ClientSocketPoolManager::set_max_sockets_per_pool( 3631 HttpNetworkSession::NORMAL_SOCKET_POOL, 1); 3632 3633 MockConnect connect_data(SYNCHRONOUS, OK); 3634 MockRead reads[] = { 3635 MockRead(SYNCHRONOUS, ERR_IO_PENDING) // Stall forever. 3636 }; 3637 StaticSocketDataProvider data(reads, arraysize(reads), NULL, 0); 3638 data.set_connect_data(connect_data); 3639 session_deps_.socket_factory->AddSocketDataProvider(&data); 3640 session_deps_.socket_factory->AddSocketDataProvider(&data); 3641 3642 CreateNetworkSession(); 3643 3644 TransportClientSocketPool* pool = 3645 http_session_->GetTransportSocketPool( 3646 HttpNetworkSession::NORMAL_SOCKET_POOL); 3647 3648 // Create an idle SPDY session. 3649 SpdySessionKey key1(HostPortPair("1.com", 80), ProxyServer::Direct(), 3650 kPrivacyModeDisabled); 3651 scoped_refptr<SpdySession> session1 = GetSession(key1); 3652 EXPECT_EQ( 3653 OK, 3654 InitializeSession(http_session_.get(), session1.get(), 3655 key1.host_port_pair())); 3656 EXPECT_FALSE(pool->IsStalled()); 3657 // Release the pointer to the session so it can be closed. 3658 session1 = NULL; 3659 3660 // Trying to create a new connection should cause the pool to be stalled, and 3661 // post a task asynchronously to try and close the session. 3662 TestCompletionCallback callback2; 3663 HostPortPair host_port2("2.com", 80); 3664 scoped_refptr<TransportSocketParams> params2( 3665 new TransportSocketParams(host_port2, DEFAULT_PRIORITY, false, false, 3666 OnHostResolutionCallback())); 3667 scoped_ptr<ClientSocketHandle> connection2(new ClientSocketHandle); 3668 EXPECT_EQ(ERR_IO_PENDING, 3669 connection2->Init(host_port2.ToString(), params2, DEFAULT_PRIORITY, 3670 callback2.callback(), pool, BoundNetLog())); 3671 EXPECT_TRUE(pool->IsStalled()); 3672 3673 // The socket pool should close the connection asynchronously and establish a 3674 // new connection. 3675 EXPECT_EQ(OK, callback2.WaitForResult()); 3676 EXPECT_FALSE(pool->IsStalled()); 3677} 3678 3679// Tests the case of a non-SPDY request closing an idle SPDY session when no 3680// pointers to the idle session are currently held, in the case the SPDY session 3681// has an alias. 3682TEST_P(SpdySessionTest, CloseOneIdleConnectionWithAlias) { 3683 if (GetParam() > kProtoSPDY3) 3684 return; 3685 3686 ClientSocketPoolManager::set_max_sockets_per_group( 3687 HttpNetworkSession::NORMAL_SOCKET_POOL, 1); 3688 ClientSocketPoolManager::set_max_sockets_per_pool( 3689 HttpNetworkSession::NORMAL_SOCKET_POOL, 1); 3690 3691 MockConnect connect_data(SYNCHRONOUS, OK); 3692 MockRead reads[] = { 3693 MockRead(SYNCHRONOUS, ERR_IO_PENDING) // Stall forever. 3694 }; 3695 StaticSocketDataProvider data(reads, arraysize(reads), NULL, 0); 3696 data.set_connect_data(connect_data); 3697 session_deps_.socket_factory->AddSocketDataProvider(&data); 3698 session_deps_.socket_factory->AddSocketDataProvider(&data); 3699 3700 session_deps_.host_resolver->set_synchronous_mode(true); 3701 session_deps_.host_resolver->rules()->AddIPLiteralRule( 3702 "1.com", "192.168.0.2", std::string()); 3703 session_deps_.host_resolver->rules()->AddIPLiteralRule( 3704 "2.com", "192.168.0.2", std::string()); 3705 // Not strictly needed. 3706 session_deps_.host_resolver->rules()->AddIPLiteralRule( 3707 "3.com", "192.168.0.3", std::string()); 3708 3709 CreateNetworkSession(); 3710 3711 TransportClientSocketPool* pool = 3712 http_session_->GetTransportSocketPool( 3713 HttpNetworkSession::NORMAL_SOCKET_POOL); 3714 3715 // Create an idle SPDY session. 3716 SpdySessionKey key1(HostPortPair("1.com", 80), ProxyServer::Direct(), 3717 kPrivacyModeDisabled); 3718 scoped_refptr<SpdySession> session1 = GetSession(key1); 3719 EXPECT_EQ( 3720 OK, 3721 InitializeSession(http_session_.get(), session1.get(), 3722 key1.host_port_pair())); 3723 EXPECT_FALSE(pool->IsStalled()); 3724 3725 // Set up an alias for the idle SPDY session, increasing its ref count to 2. 3726 SpdySessionKey key2(HostPortPair("2.com", 80), ProxyServer::Direct(), 3727 kPrivacyModeDisabled); 3728 SpdySessionPoolPeer pool_peer(spdy_session_pool_); 3729 HostResolver::RequestInfo info(key2.host_port_pair()); 3730 AddressList addresses; 3731 // Pre-populate the DNS cache, since a synchronous resolution is required in 3732 // order to create the alias. 3733 session_deps_.host_resolver->Resolve( 3734 info, &addresses, CompletionCallback(), NULL, BoundNetLog()); 3735 // Add the alias for the first session's key. Has to be done manually since 3736 // the usual process is bypassed. 3737 pool_peer.AddAlias(addresses.front(), key1); 3738 // Get a session for |key2|, which should return the session created earlier. 3739 scoped_refptr<SpdySession> session2 = 3740 spdy_session_pool_->Get(key2, BoundNetLog()); 3741 ASSERT_EQ(session1.get(), session2.get()); 3742 EXPECT_FALSE(pool->IsStalled()); 3743 3744 // Release both the pointers to the session so it can be closed. 3745 session1 = NULL; 3746 session2 = NULL; 3747 3748 // Trying to create a new connection should cause the pool to be stalled, and 3749 // post a task asynchronously to try and close the session. 3750 TestCompletionCallback callback3; 3751 HostPortPair host_port3("3.com", 80); 3752 scoped_refptr<TransportSocketParams> params3( 3753 new TransportSocketParams(host_port3, DEFAULT_PRIORITY, false, false, 3754 OnHostResolutionCallback())); 3755 scoped_ptr<ClientSocketHandle> connection3(new ClientSocketHandle); 3756 EXPECT_EQ(ERR_IO_PENDING, 3757 connection3->Init(host_port3.ToString(), params3, DEFAULT_PRIORITY, 3758 callback3.callback(), pool, BoundNetLog())); 3759 EXPECT_TRUE(pool->IsStalled()); 3760 3761 // The socket pool should close the connection asynchronously and establish a 3762 // new connection. 3763 EXPECT_EQ(OK, callback3.WaitForResult()); 3764 EXPECT_FALSE(pool->IsStalled()); 3765} 3766 3767// Tests the case of a non-SPDY request closing an idle SPDY session when a 3768// pointer to the idle session is still held. 3769TEST_P(SpdySessionTest, CloseOneIdleConnectionSessionStillHeld) { 3770 if (GetParam() > kProtoSPDY3) 3771 return; 3772 3773 ClientSocketPoolManager::set_max_sockets_per_group( 3774 HttpNetworkSession::NORMAL_SOCKET_POOL, 1); 3775 ClientSocketPoolManager::set_max_sockets_per_pool( 3776 HttpNetworkSession::NORMAL_SOCKET_POOL, 1); 3777 3778 MockConnect connect_data(SYNCHRONOUS, OK); 3779 MockRead reads[] = { 3780 MockRead(SYNCHRONOUS, ERR_IO_PENDING) // Stall forever. 3781 }; 3782 StaticSocketDataProvider data(reads, arraysize(reads), NULL, 0); 3783 data.set_connect_data(connect_data); 3784 session_deps_.socket_factory->AddSocketDataProvider(&data); 3785 session_deps_.socket_factory->AddSocketDataProvider(&data); 3786 3787 CreateNetworkSession(); 3788 3789 TransportClientSocketPool* pool = 3790 http_session_->GetTransportSocketPool( 3791 HttpNetworkSession::NORMAL_SOCKET_POOL); 3792 3793 // Create an idle SPDY session. 3794 SpdySessionKey key1(HostPortPair("1.com", 80), ProxyServer::Direct(), 3795 kPrivacyModeDisabled); 3796 scoped_refptr<SpdySession> session1 = GetSession(key1); 3797 EXPECT_EQ( 3798 OK, 3799 InitializeSession(http_session_.get(), session1.get(), 3800 key1.host_port_pair())); 3801 EXPECT_FALSE(pool->IsStalled()); 3802 3803 // Trying to create a new connection should cause the pool to be stalled, and 3804 // post a task asynchronously to try and close the session. 3805 TestCompletionCallback callback2; 3806 HostPortPair host_port2("2.com", 80); 3807 scoped_refptr<TransportSocketParams> params2( 3808 new TransportSocketParams(host_port2, DEFAULT_PRIORITY, false, false, 3809 OnHostResolutionCallback())); 3810 scoped_ptr<ClientSocketHandle> connection2(new ClientSocketHandle); 3811 EXPECT_EQ(ERR_IO_PENDING, 3812 connection2->Init(host_port2.ToString(), params2, DEFAULT_PRIORITY, 3813 callback2.callback(), pool, BoundNetLog())); 3814 EXPECT_TRUE(pool->IsStalled()); 3815 3816 // Running the message loop should cause the session to prepare to be closed, 3817 // but since there's still an outstanding reference, it should not be closed 3818 // yet. 3819 base::RunLoop().RunUntilIdle(); 3820 EXPECT_TRUE(pool->IsStalled()); 3821 EXPECT_FALSE(callback2.have_result()); 3822 3823 // Release the pointer to the session so it can be closed. 3824 session1 = NULL; 3825 EXPECT_EQ(OK, callback2.WaitForResult()); 3826 EXPECT_FALSE(pool->IsStalled()); 3827} 3828 3829// Tests that a non-SPDY request can't close a SPDY session that's currently in 3830// use. 3831TEST_P(SpdySessionTest, CloseOneIdleConnectionFailsWhenSessionInUse) { 3832 if (GetParam() > kProtoSPDY3) 3833 return; 3834 3835 ClientSocketPoolManager::set_max_sockets_per_group( 3836 HttpNetworkSession::NORMAL_SOCKET_POOL, 1); 3837 ClientSocketPoolManager::set_max_sockets_per_pool( 3838 HttpNetworkSession::NORMAL_SOCKET_POOL, 1); 3839 3840 MockConnect connect_data(SYNCHRONOUS, OK); 3841 MockRead reads[] = { 3842 MockRead(SYNCHRONOUS, ERR_IO_PENDING) // Stall forever. 3843 }; 3844 scoped_ptr<SpdyFrame> req1( 3845 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true)); 3846 scoped_ptr<SpdyFrame> cancel1( 3847 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_CANCEL)); 3848 MockWrite writes[] = { 3849 CreateMockWrite(*req1, 1), 3850 CreateMockWrite(*cancel1, 1), 3851 }; 3852 StaticSocketDataProvider data(reads, arraysize(reads), 3853 writes, arraysize(writes)); 3854 data.set_connect_data(connect_data); 3855 session_deps_.socket_factory->AddSocketDataProvider(&data); 3856 3857 CreateNetworkSession(); 3858 3859 TransportClientSocketPool* pool = 3860 http_session_->GetTransportSocketPool( 3861 HttpNetworkSession::NORMAL_SOCKET_POOL); 3862 3863 // Create a SPDY session. 3864 GURL url1("http://www.google.com"); 3865 SpdySessionKey key1(HostPortPair(url1.host(), 80), 3866 ProxyServer::Direct(), kPrivacyModeDisabled); 3867 scoped_refptr<SpdySession> session1 = GetSession(key1); 3868 EXPECT_EQ( 3869 OK, 3870 InitializeSession(http_session_.get(), session1.get(), 3871 key1.host_port_pair())); 3872 EXPECT_FALSE(pool->IsStalled()); 3873 3874 // Create a stream using the session, and send a request. 3875 3876 TestCompletionCallback callback1; 3877 base::WeakPtr<SpdyStream> spdy_stream1 = 3878 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM, 3879 session1, url1, DEFAULT_PRIORITY, 3880 BoundNetLog()); 3881 ASSERT_TRUE(spdy_stream1.get()); 3882 test::StreamDelegateDoNothing delegate1(spdy_stream1); 3883 spdy_stream1->SetDelegate(&delegate1); 3884 3885 scoped_ptr<SpdyHeaderBlock> headers1( 3886 spdy_util_.ConstructGetHeaderBlock(url1.spec())); 3887 EXPECT_EQ(ERR_IO_PENDING, 3888 spdy_stream1->SendRequestHeaders( 3889 headers1.Pass(), NO_MORE_DATA_TO_SEND)); 3890 EXPECT_TRUE(spdy_stream1->HasUrl()); 3891 3892 base::MessageLoop::current()->RunUntilIdle(); 3893 3894 // Release the session, so holding onto a pointer here does not affect 3895 // anything. 3896 session1 = NULL; 3897 3898 // Trying to create a new connection should cause the pool to be stalled, and 3899 // post a task asynchronously to try and close the session. 3900 TestCompletionCallback callback2; 3901 HostPortPair host_port2("2.com", 80); 3902 scoped_refptr<TransportSocketParams> params2( 3903 new TransportSocketParams(host_port2, DEFAULT_PRIORITY, false, false, 3904 OnHostResolutionCallback())); 3905 scoped_ptr<ClientSocketHandle> connection2(new ClientSocketHandle); 3906 EXPECT_EQ(ERR_IO_PENDING, 3907 connection2->Init(host_port2.ToString(), params2, DEFAULT_PRIORITY, 3908 callback2.callback(), pool, BoundNetLog())); 3909 EXPECT_TRUE(pool->IsStalled()); 3910 3911 // Running the message loop should cause the socket pool to ask the SPDY 3912 // session to close an idle socket, but since the socket is in use, nothing 3913 // happens. 3914 base::RunLoop().RunUntilIdle(); 3915 EXPECT_TRUE(pool->IsStalled()); 3916 EXPECT_FALSE(callback2.have_result()); 3917 3918 // Cancelling the request should still not release the session's socket, 3919 // since the session is still kept alive by the SpdySessionPool. 3920 ASSERT_TRUE(spdy_stream1.get()); 3921 spdy_stream1->Cancel(); 3922 base::RunLoop().RunUntilIdle(); 3923 EXPECT_TRUE(pool->IsStalled()); 3924 EXPECT_FALSE(callback2.have_result()); 3925} 3926 3927// Verify that SpdySessionKey and therefore SpdySession is different when 3928// privacy mode is enabled or disabled. 3929TEST_P(SpdySessionTest, SpdySessionKeyPrivacyMode) { 3930 CreateDeterministicNetworkSession(); 3931 3932 HostPortPair host_port_pair("www.google.com", 443); 3933 SpdySessionKey key_privacy_enabled(host_port_pair, ProxyServer::Direct(), 3934 kPrivacyModeEnabled); 3935 SpdySessionKey key_privacy_disabled(host_port_pair, ProxyServer::Direct(), 3936 kPrivacyModeDisabled); 3937 3938 EXPECT_FALSE(spdy_session_pool_->HasSession(key_privacy_enabled)); 3939 EXPECT_FALSE(spdy_session_pool_->HasSession(key_privacy_disabled)); 3940 3941 // Add SpdySession with PrivacyMode Enabled to the pool. 3942 scoped_refptr<SpdySession> session_privacy_enabled = 3943 spdy_session_pool_->Get(key_privacy_enabled, BoundNetLog()); 3944 3945 EXPECT_TRUE(spdy_session_pool_->HasSession(key_privacy_enabled)); 3946 EXPECT_FALSE(spdy_session_pool_->HasSession(key_privacy_disabled)); 3947 3948 // Add SpdySession with PrivacyMode Disabled to the pool. 3949 scoped_refptr<SpdySession> session_privacy_disabled = 3950 spdy_session_pool_->Get(key_privacy_disabled, BoundNetLog()); 3951 3952 EXPECT_TRUE(spdy_session_pool_->HasSession(key_privacy_enabled)); 3953 EXPECT_TRUE(spdy_session_pool_->HasSession(key_privacy_disabled)); 3954 3955 spdy_session_pool_->Remove(session_privacy_enabled); 3956 EXPECT_FALSE(spdy_session_pool_->HasSession(key_privacy_enabled)); 3957 EXPECT_TRUE(spdy_session_pool_->HasSession(key_privacy_disabled)); 3958 3959 spdy_session_pool_->Remove(session_privacy_disabled); 3960 EXPECT_FALSE(spdy_session_pool_->HasSession(key_privacy_enabled)); 3961 EXPECT_FALSE(spdy_session_pool_->HasSession(key_privacy_disabled)); 3962} 3963 3964} // namespace net 3965