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