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