spdy_session_unittest.cc revision 7dbb3d5cf0c15f500944d211057644d6a2f37371
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 read completion 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(ERR_CONNECTION_CLOSED, 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(ERR_CONNECTION_CLOSED, 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 read completion 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 read completion 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 read completion task. 1709 base::MessageLoop::current()->RunUntilIdle(); 1710 1711 session->CloseSessionOnError(ERR_ABORTED, std::string()); 1712} 1713 1714// Test that SpdySession::DoReadLoop reads data from the socket 1715// without yielding. This test makes 32k - 1 bytes of data available 1716// on the socket for reading. It then verifies that it has read all 1717// the available data without yielding. 1718TEST_P(SpdySessionTest, ReadDataWithoutYielding) { 1719 MockConnect connect_data(SYNCHRONOUS, OK); 1720 BufferedSpdyFramer framer(spdy_util_.spdy_version(), false); 1721 1722 scoped_ptr<SpdyFrame> req1( 1723 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, MEDIUM, true)); 1724 MockWrite writes[] = { 1725 CreateMockWrite(*req1, 0), 1726 }; 1727 1728 // Build buffer of size kMaxReadBytesWithoutYielding / 4 1729 // (-spdy_data_frame_size). 1730 ASSERT_EQ(32 * 1024, kMaxReadBytesWithoutYielding); 1731 const int kPayloadSize = 1732 kMaxReadBytesWithoutYielding / 4 - framer.GetControlFrameHeaderSize(); 1733 TestDataStream test_stream; 1734 scoped_refptr<net::IOBuffer> payload(new net::IOBuffer(kPayloadSize)); 1735 char* payload_data = payload->data(); 1736 test_stream.GetBytes(payload_data, kPayloadSize); 1737 1738 scoped_ptr<SpdyFrame> partial_data_frame( 1739 framer.CreateDataFrame(1, payload_data, kPayloadSize, DATA_FLAG_NONE)); 1740 scoped_ptr<SpdyFrame> finish_data_frame( 1741 framer.CreateDataFrame(1, payload_data, kPayloadSize - 1, DATA_FLAG_FIN)); 1742 1743 scoped_ptr<SpdyFrame> resp1(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1)); 1744 1745 // Write 1 byte less than kMaxReadBytes to check that DoRead reads up to 32k 1746 // bytes. 1747 MockRead reads[] = { 1748 CreateMockRead(*resp1, 1), 1749 CreateMockRead(*partial_data_frame, 2), 1750 CreateMockRead(*partial_data_frame, 3, SYNCHRONOUS), 1751 CreateMockRead(*partial_data_frame, 4, SYNCHRONOUS), 1752 CreateMockRead(*finish_data_frame, 5, SYNCHRONOUS), 1753 MockRead(ASYNC, 0, 6) // EOF 1754 }; 1755 1756 // Create SpdySession and SpdyStream and send the request. 1757 DeterministicSocketData data(reads, arraysize(reads), 1758 writes, arraysize(writes)); 1759 data.set_connect_data(connect_data); 1760 session_deps_.host_resolver->set_synchronous_mode(true); 1761 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data); 1762 1763 SSLSocketDataProvider ssl(SYNCHRONOUS, OK); 1764 session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl); 1765 1766 CreateDeterministicNetworkSession(); 1767 1768 scoped_refptr<SpdySession> session = 1769 CreateInsecureSpdySession(http_session_, key_, BoundNetLog()); 1770 1771 GURL url1("http://www.google.com"); 1772 base::WeakPtr<SpdyStream> spdy_stream1 = 1773 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM, 1774 session, url1, MEDIUM, BoundNetLog()); 1775 ASSERT_TRUE(spdy_stream1.get() != NULL); 1776 EXPECT_EQ(0u, spdy_stream1->stream_id()); 1777 test::StreamDelegateDoNothing delegate1(spdy_stream1); 1778 spdy_stream1->SetDelegate(&delegate1); 1779 1780 scoped_ptr<SpdyHeaderBlock> headers1( 1781 spdy_util_.ConstructGetHeaderBlock(url1.spec())); 1782 spdy_stream1->SendRequestHeaders(headers1.Pass(), NO_MORE_DATA_TO_SEND); 1783 EXPECT_TRUE(spdy_stream1->HasUrl()); 1784 1785 // Set up the TaskObserver to verify SpdySession::DoReadLoop doesn't 1786 // post a task. 1787 SpdySessionTestTaskObserver observer("spdy_session.cc", "DoReadLoop"); 1788 1789 // Run until 1st read. 1790 EXPECT_EQ(0u, delegate1.stream_id()); 1791 data.RunFor(2); 1792 EXPECT_EQ(1u, delegate1.stream_id()); 1793 EXPECT_EQ(0u, observer.executed_count()); 1794 1795 // Read all the data and verify SpdySession::DoReadLoop has not 1796 // posted a task. 1797 data.RunFor(4); 1798 EXPECT_EQ(NULL, spdy_stream1.get()); 1799 1800 // Verify task observer's executed_count is zero, which indicates DoRead read 1801 // all the available data. 1802 EXPECT_EQ(0u, observer.executed_count()); 1803 EXPECT_TRUE(data.at_write_eof()); 1804 EXPECT_TRUE(data.at_read_eof()); 1805} 1806 1807// Test that SpdySession::DoReadLoop yields while reading the 1808// data. This test makes 32k + 1 bytes of data available on the socket 1809// for reading. It then verifies that DoRead has yielded even though 1810// there is data available for it to read (i.e, socket()->Read didn't 1811// return ERR_IO_PENDING during socket reads). 1812TEST_P(SpdySessionTest, TestYieldingDuringReadData) { 1813 MockConnect connect_data(SYNCHRONOUS, OK); 1814 BufferedSpdyFramer framer(spdy_util_.spdy_version(), false); 1815 1816 scoped_ptr<SpdyFrame> req1( 1817 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, MEDIUM, true)); 1818 MockWrite writes[] = { 1819 CreateMockWrite(*req1, 0), 1820 }; 1821 1822 // Build buffer of size kMaxReadBytesWithoutYielding / 4 1823 // (-spdy_data_frame_size). 1824 ASSERT_EQ(32 * 1024, kMaxReadBytesWithoutYielding); 1825 const int kPayloadSize = 1826 kMaxReadBytesWithoutYielding / 4 - framer.GetControlFrameHeaderSize(); 1827 TestDataStream test_stream; 1828 scoped_refptr<net::IOBuffer> payload(new net::IOBuffer(kPayloadSize)); 1829 char* payload_data = payload->data(); 1830 test_stream.GetBytes(payload_data, kPayloadSize); 1831 1832 scoped_ptr<SpdyFrame> partial_data_frame( 1833 framer.CreateDataFrame(1, payload_data, kPayloadSize, DATA_FLAG_NONE)); 1834 scoped_ptr<SpdyFrame> finish_data_frame( 1835 framer.CreateDataFrame(1, "h", 1, DATA_FLAG_FIN)); 1836 1837 scoped_ptr<SpdyFrame> resp1(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1)); 1838 1839 // Write 1 byte more than kMaxReadBytes to check that DoRead yields. 1840 MockRead reads[] = { 1841 CreateMockRead(*resp1, 1), 1842 CreateMockRead(*partial_data_frame, 2), 1843 CreateMockRead(*partial_data_frame, 3, SYNCHRONOUS), 1844 CreateMockRead(*partial_data_frame, 4, SYNCHRONOUS), 1845 CreateMockRead(*partial_data_frame, 5, SYNCHRONOUS), 1846 CreateMockRead(*finish_data_frame, 6, SYNCHRONOUS), 1847 MockRead(ASYNC, 0, 7) // EOF 1848 }; 1849 1850 // Create SpdySession and SpdyStream and send the request. 1851 DeterministicSocketData data(reads, arraysize(reads), 1852 writes, arraysize(writes)); 1853 data.set_connect_data(connect_data); 1854 session_deps_.host_resolver->set_synchronous_mode(true); 1855 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data); 1856 1857 SSLSocketDataProvider ssl(SYNCHRONOUS, OK); 1858 session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl); 1859 1860 CreateDeterministicNetworkSession(); 1861 1862 scoped_refptr<SpdySession> session = 1863 CreateInsecureSpdySession(http_session_, key_, BoundNetLog()); 1864 1865 GURL url1("http://www.google.com"); 1866 base::WeakPtr<SpdyStream> spdy_stream1 = 1867 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM, 1868 session, url1, MEDIUM, BoundNetLog()); 1869 ASSERT_TRUE(spdy_stream1.get() != NULL); 1870 EXPECT_EQ(0u, spdy_stream1->stream_id()); 1871 test::StreamDelegateDoNothing delegate1(spdy_stream1); 1872 spdy_stream1->SetDelegate(&delegate1); 1873 1874 scoped_ptr<SpdyHeaderBlock> headers1( 1875 spdy_util_.ConstructGetHeaderBlock(url1.spec())); 1876 spdy_stream1->SendRequestHeaders(headers1.Pass(), NO_MORE_DATA_TO_SEND); 1877 EXPECT_TRUE(spdy_stream1->HasUrl()); 1878 1879 // Set up the TaskObserver to verify SpdySession::DoReadLoop posts a 1880 // task. 1881 SpdySessionTestTaskObserver observer("spdy_session.cc", "DoReadLoop"); 1882 1883 // Run until 1st read. 1884 EXPECT_EQ(0u, delegate1.stream_id()); 1885 data.RunFor(2); 1886 EXPECT_EQ(1u, delegate1.stream_id()); 1887 EXPECT_EQ(0u, observer.executed_count()); 1888 1889 // Read all the data and verify SpdySession::DoReadLoop has posted a 1890 // task. 1891 data.RunFor(6); 1892 EXPECT_EQ(NULL, spdy_stream1.get()); 1893 1894 // Verify task observer's executed_count is 1, which indicates DoRead has 1895 // posted only one task and thus yielded though there is data available for it 1896 // to read. 1897 EXPECT_EQ(1u, observer.executed_count()); 1898 EXPECT_TRUE(data.at_write_eof()); 1899 EXPECT_TRUE(data.at_read_eof()); 1900} 1901 1902// Test that SpdySession::DoReadLoop() tests interactions of yielding 1903// + async, by doing the following MockReads. 1904// 1905// MockRead of SYNCHRONOUS 8K, SYNCHRONOUS 8K, SYNCHRONOUS 8K, SYNCHRONOUS 2K 1906// ASYNC 8K, SYNCHRONOUS 8K, SYNCHRONOUS 8K, SYNCHRONOUS 8K, SYNCHRONOUS 2K. 1907// 1908// The above reads 26K synchronously. Since that is less that 32K, we 1909// will attempt to read again. However, that DoRead() will return 1910// ERR_IO_PENDING (because of async read), so DoReadLoop() will 1911// yield. When we come back, DoRead() will read the results from the 1912// async read, and rest of the data synchronously. 1913TEST_P(SpdySessionTest, TestYieldingDuringAsyncReadData) { 1914 MockConnect connect_data(SYNCHRONOUS, OK); 1915 BufferedSpdyFramer framer(spdy_util_.spdy_version(), false); 1916 1917 scoped_ptr<SpdyFrame> req1( 1918 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, MEDIUM, true)); 1919 MockWrite writes[] = { 1920 CreateMockWrite(*req1, 0), 1921 }; 1922 1923 // Build buffer of size kMaxReadBytesWithoutYielding / 4 1924 // (-spdy_data_frame_size). 1925 ASSERT_EQ(32 * 1024, kMaxReadBytesWithoutYielding); 1926 TestDataStream test_stream; 1927 const int kEightKPayloadSize = 1928 kMaxReadBytesWithoutYielding / 4 - framer.GetControlFrameHeaderSize(); 1929 scoped_refptr<net::IOBuffer> eightk_payload( 1930 new net::IOBuffer(kEightKPayloadSize)); 1931 char* eightk_payload_data = eightk_payload->data(); 1932 test_stream.GetBytes(eightk_payload_data, kEightKPayloadSize); 1933 1934 // Build buffer of 2k size. 1935 TestDataStream test_stream2; 1936 const int kTwoKPayloadSize = kEightKPayloadSize - 6 * 1024; 1937 scoped_refptr<net::IOBuffer> twok_payload( 1938 new net::IOBuffer(kTwoKPayloadSize)); 1939 char* twok_payload_data = twok_payload->data(); 1940 test_stream2.GetBytes(twok_payload_data, kTwoKPayloadSize); 1941 1942 scoped_ptr<SpdyFrame> eightk_data_frame(framer.CreateDataFrame( 1943 1, eightk_payload_data, kEightKPayloadSize, DATA_FLAG_NONE)); 1944 scoped_ptr<SpdyFrame> twok_data_frame(framer.CreateDataFrame( 1945 1, twok_payload_data, kTwoKPayloadSize, DATA_FLAG_NONE)); 1946 scoped_ptr<SpdyFrame> finish_data_frame(framer.CreateDataFrame( 1947 1, "h", 1, DATA_FLAG_FIN)); 1948 1949 scoped_ptr<SpdyFrame> resp1(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1)); 1950 1951 MockRead reads[] = { 1952 CreateMockRead(*resp1, 1), 1953 CreateMockRead(*eightk_data_frame, 2), 1954 CreateMockRead(*eightk_data_frame, 3, SYNCHRONOUS), 1955 CreateMockRead(*eightk_data_frame, 4, SYNCHRONOUS), 1956 CreateMockRead(*twok_data_frame, 5, SYNCHRONOUS), 1957 CreateMockRead(*eightk_data_frame, 6, ASYNC), 1958 CreateMockRead(*eightk_data_frame, 7, SYNCHRONOUS), 1959 CreateMockRead(*eightk_data_frame, 8, SYNCHRONOUS), 1960 CreateMockRead(*eightk_data_frame, 9, SYNCHRONOUS), 1961 CreateMockRead(*twok_data_frame, 10, SYNCHRONOUS), 1962 CreateMockRead(*finish_data_frame, 11, SYNCHRONOUS), 1963 MockRead(ASYNC, 0, 12) // EOF 1964 }; 1965 1966 // Create SpdySession and SpdyStream and send the request. 1967 DeterministicSocketData data(reads, arraysize(reads), 1968 writes, arraysize(writes)); 1969 data.set_connect_data(connect_data); 1970 session_deps_.host_resolver->set_synchronous_mode(true); 1971 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data); 1972 1973 SSLSocketDataProvider ssl(SYNCHRONOUS, OK); 1974 session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl); 1975 1976 CreateDeterministicNetworkSession(); 1977 1978 scoped_refptr<SpdySession> session = 1979 CreateInsecureSpdySession(http_session_, key_, BoundNetLog()); 1980 1981 GURL url1("http://www.google.com"); 1982 base::WeakPtr<SpdyStream> spdy_stream1 = 1983 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM, 1984 session, url1, MEDIUM, BoundNetLog()); 1985 ASSERT_TRUE(spdy_stream1.get() != NULL); 1986 EXPECT_EQ(0u, spdy_stream1->stream_id()); 1987 test::StreamDelegateDoNothing delegate1(spdy_stream1); 1988 spdy_stream1->SetDelegate(&delegate1); 1989 1990 scoped_ptr<SpdyHeaderBlock> headers1( 1991 spdy_util_.ConstructGetHeaderBlock(url1.spec())); 1992 spdy_stream1->SendRequestHeaders(headers1.Pass(), NO_MORE_DATA_TO_SEND); 1993 EXPECT_TRUE(spdy_stream1->HasUrl()); 1994 1995 // Set up the TaskObserver to monitor SpdySession::DoReadLoop 1996 // posting of tasks. 1997 SpdySessionTestTaskObserver observer("spdy_session.cc", "DoReadLoop"); 1998 1999 // Run until 1st read. 2000 EXPECT_EQ(0u, delegate1.stream_id()); 2001 data.RunFor(2); 2002 EXPECT_EQ(1u, delegate1.stream_id()); 2003 EXPECT_EQ(0u, observer.executed_count()); 2004 2005 // Read all the data and verify SpdySession::DoReadLoop has posted a 2006 // task. 2007 data.RunFor(12); 2008 EXPECT_EQ(NULL, spdy_stream1.get()); 2009 2010 // Verify task observer's executed_count is 1, which indicates DoRead has 2011 // posted only one task and thus yielded though there is data available for 2012 // it to read. 2013 EXPECT_EQ(1u, observer.executed_count()); 2014 EXPECT_TRUE(data.at_write_eof()); 2015 EXPECT_TRUE(data.at_read_eof()); 2016} 2017 2018// Send a GoAway frame when SpdySession is in DoReadLoop. If 2019// scoped_refptr to <SpdySession> is deleted from 2020// SpdySession::DoReadLoop(), we get a crash because GoAway could 2021// delete the SpdySession from the SpdySessionPool and the last 2022// reference to SpdySession. 2023TEST_P(SpdySessionTest, GoAwayWhileInDoReadLoop) { 2024 MockConnect connect_data(SYNCHRONOUS, OK); 2025 BufferedSpdyFramer framer(spdy_util_.spdy_version(), false); 2026 2027 scoped_ptr<SpdyFrame> req1( 2028 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, MEDIUM, true)); 2029 MockWrite writes[] = { 2030 CreateMockWrite(*req1, 0), 2031 }; 2032 2033 scoped_ptr<SpdyFrame> resp1(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1)); 2034 scoped_ptr<SpdyFrame> body1(spdy_util_.ConstructSpdyBodyFrame(1, true)); 2035 scoped_ptr<SpdyFrame> goaway(spdy_util_.ConstructSpdyGoAway()); 2036 2037 MockRead reads[] = { 2038 CreateMockRead(*resp1, 1), 2039 CreateMockRead(*body1, 2), 2040 CreateMockRead(*goaway, 3), 2041 MockRead(ASYNC, 0, 4) // EOF 2042 }; 2043 2044 // Create SpdySession and SpdyStream and send the request. 2045 DeterministicSocketData data(reads, arraysize(reads), 2046 writes, arraysize(writes)); 2047 data.set_connect_data(connect_data); 2048 session_deps_.host_resolver->set_synchronous_mode(true); 2049 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data); 2050 2051 SSLSocketDataProvider ssl(SYNCHRONOUS, OK); 2052 session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl); 2053 2054 CreateDeterministicNetworkSession(); 2055 2056 scoped_refptr<SpdySession> session = 2057 CreateInsecureSpdySession(http_session_, key_, BoundNetLog()); 2058 2059 GURL url1("http://www.google.com"); 2060 base::WeakPtr<SpdyStream> spdy_stream1 = 2061 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM, 2062 session, url1, MEDIUM, BoundNetLog()); 2063 test::StreamDelegateDoNothing delegate1(spdy_stream1); 2064 spdy_stream1->SetDelegate(&delegate1); 2065 session = NULL; 2066 ASSERT_TRUE(spdy_stream1.get() != NULL); 2067 EXPECT_EQ(0u, spdy_stream1->stream_id()); 2068 2069 scoped_ptr<SpdyHeaderBlock> headers1( 2070 spdy_util_.ConstructGetHeaderBlock(url1.spec())); 2071 spdy_stream1->SendRequestHeaders(headers1.Pass(), NO_MORE_DATA_TO_SEND); 2072 EXPECT_TRUE(spdy_stream1->HasUrl()); 2073 2074 // Run until 1st read. 2075 EXPECT_EQ(0u, spdy_stream1->stream_id()); 2076 data.RunFor(1); 2077 EXPECT_EQ(1u, spdy_stream1->stream_id()); 2078 2079 // Only references to SpdySession are held by DoReadLoop and 2080 // SpdySessionPool. If DoReadLoop doesn't hold the reference, we get a 2081 // crash if SpdySession is deleted from the SpdySessionPool. 2082 2083 // Run until GoAway. 2084 data.RunFor(4); 2085 EXPECT_EQ(NULL, spdy_stream1.get()); 2086 EXPECT_TRUE(data.at_write_eof()); 2087 EXPECT_TRUE(data.at_read_eof()); 2088} 2089 2090// Within this framework, a SpdySession should be initialized with 2091// flow control disabled for protocol version 2, with flow control 2092// enabled only for streams for protocol version 3, and with flow 2093// control enabled for streams and sessions for higher versions. 2094TEST_P(SpdySessionTest, ProtocolNegotiation) { 2095 session_deps_.host_resolver->set_synchronous_mode(true); 2096 2097 MockConnect connect_data(SYNCHRONOUS, OK); 2098 MockRead reads[] = { 2099 MockRead(SYNCHRONOUS, 0, 0) // EOF 2100 }; 2101 StaticSocketDataProvider data(reads, arraysize(reads), NULL, 0); 2102 data.set_connect_data(connect_data); 2103 session_deps_.socket_factory->AddSocketDataProvider(&data); 2104 2105 CreateNetworkSession(); 2106 scoped_refptr<SpdySession> session = 2107 CreateFakeSpdySession(spdy_session_pool_, key_); 2108 2109 EXPECT_EQ(spdy_util_.spdy_version(), 2110 session->buffered_spdy_framer_->protocol_version()); 2111 if (GetParam() == kProtoSPDY2) { 2112 EXPECT_EQ(SpdySession::FLOW_CONTROL_NONE, session->flow_control_state()); 2113 EXPECT_EQ(0, session->session_send_window_size_); 2114 EXPECT_EQ(0, session->session_recv_window_size_); 2115 } else if (GetParam() == kProtoSPDY3) { 2116 EXPECT_EQ(SpdySession::FLOW_CONTROL_STREAM, session->flow_control_state()); 2117 EXPECT_EQ(0, session->session_send_window_size_); 2118 EXPECT_EQ(0, session->session_recv_window_size_); 2119 } else { 2120 EXPECT_EQ(SpdySession::FLOW_CONTROL_STREAM_AND_SESSION, 2121 session->flow_control_state()); 2122 EXPECT_EQ(kSpdySessionInitialWindowSize, 2123 session->session_send_window_size_); 2124 EXPECT_EQ(kSpdySessionInitialWindowSize, 2125 session->session_recv_window_size_); 2126 } 2127 EXPECT_EQ(0, session->session_unacked_recv_window_bytes_); 2128} 2129 2130// Tests the case of a non-SPDY request closing an idle SPDY session when no 2131// pointers to the idle session are currently held. 2132TEST_P(SpdySessionTest, CloseOneIdleConnection) { 2133 ClientSocketPoolManager::set_max_sockets_per_group( 2134 HttpNetworkSession::NORMAL_SOCKET_POOL, 1); 2135 ClientSocketPoolManager::set_max_sockets_per_pool( 2136 HttpNetworkSession::NORMAL_SOCKET_POOL, 1); 2137 2138 MockConnect connect_data(SYNCHRONOUS, OK); 2139 MockRead reads[] = { 2140 MockRead(SYNCHRONOUS, ERR_IO_PENDING) // Stall forever. 2141 }; 2142 StaticSocketDataProvider data(reads, arraysize(reads), NULL, 0); 2143 data.set_connect_data(connect_data); 2144 session_deps_.socket_factory->AddSocketDataProvider(&data); 2145 session_deps_.socket_factory->AddSocketDataProvider(&data); 2146 2147 CreateNetworkSession(); 2148 2149 TransportClientSocketPool* pool = 2150 http_session_->GetTransportSocketPool( 2151 HttpNetworkSession::NORMAL_SOCKET_POOL); 2152 2153 // Create an idle SPDY session. 2154 SpdySessionKey key1(HostPortPair("1.com", 80), ProxyServer::Direct(), 2155 kPrivacyModeDisabled); 2156 scoped_refptr<SpdySession> session1 = 2157 CreateInsecureSpdySession(http_session_, key1, BoundNetLog()); 2158 EXPECT_FALSE(pool->IsStalled()); 2159 // Release the pointer to the session so it can be closed. 2160 session1 = NULL; 2161 2162 // Trying to create a new connection should cause the pool to be stalled, and 2163 // post a task asynchronously to try and close the session. 2164 TestCompletionCallback callback2; 2165 HostPortPair host_port2("2.com", 80); 2166 scoped_refptr<TransportSocketParams> params2( 2167 new TransportSocketParams(host_port2, DEFAULT_PRIORITY, false, false, 2168 OnHostResolutionCallback())); 2169 scoped_ptr<ClientSocketHandle> connection2(new ClientSocketHandle); 2170 EXPECT_EQ(ERR_IO_PENDING, 2171 connection2->Init(host_port2.ToString(), params2, DEFAULT_PRIORITY, 2172 callback2.callback(), pool, BoundNetLog())); 2173 EXPECT_TRUE(pool->IsStalled()); 2174 2175 // The socket pool should close the connection asynchronously and establish a 2176 // new connection. 2177 EXPECT_EQ(OK, callback2.WaitForResult()); 2178 EXPECT_FALSE(pool->IsStalled()); 2179} 2180 2181// Tests the case of a non-SPDY request closing an idle SPDY session when no 2182// pointers to the idle session are currently held, in the case the SPDY session 2183// has an alias. 2184TEST_P(SpdySessionTest, CloseOneIdleConnectionWithAlias) { 2185 ClientSocketPoolManager::set_max_sockets_per_group( 2186 HttpNetworkSession::NORMAL_SOCKET_POOL, 1); 2187 ClientSocketPoolManager::set_max_sockets_per_pool( 2188 HttpNetworkSession::NORMAL_SOCKET_POOL, 1); 2189 2190 MockConnect connect_data(SYNCHRONOUS, OK); 2191 MockRead reads[] = { 2192 MockRead(SYNCHRONOUS, ERR_IO_PENDING) // Stall forever. 2193 }; 2194 StaticSocketDataProvider data(reads, arraysize(reads), NULL, 0); 2195 data.set_connect_data(connect_data); 2196 session_deps_.socket_factory->AddSocketDataProvider(&data); 2197 session_deps_.socket_factory->AddSocketDataProvider(&data); 2198 2199 session_deps_.host_resolver->set_synchronous_mode(true); 2200 session_deps_.host_resolver->rules()->AddIPLiteralRule( 2201 "1.com", "192.168.0.2", std::string()); 2202 session_deps_.host_resolver->rules()->AddIPLiteralRule( 2203 "2.com", "192.168.0.2", std::string()); 2204 // Not strictly needed. 2205 session_deps_.host_resolver->rules()->AddIPLiteralRule( 2206 "3.com", "192.168.0.3", std::string()); 2207 2208 CreateNetworkSession(); 2209 2210 TransportClientSocketPool* pool = 2211 http_session_->GetTransportSocketPool( 2212 HttpNetworkSession::NORMAL_SOCKET_POOL); 2213 2214 // Create an idle SPDY session. 2215 SpdySessionKey key1(HostPortPair("1.com", 80), ProxyServer::Direct(), 2216 kPrivacyModeDisabled); 2217 scoped_refptr<SpdySession> session1 = 2218 CreateInsecureSpdySession(http_session_, key1, BoundNetLog()); 2219 EXPECT_FALSE(pool->IsStalled()); 2220 2221 // Set up an alias for the idle SPDY session, increasing its ref count to 2. 2222 SpdySessionKey key2(HostPortPair("2.com", 80), ProxyServer::Direct(), 2223 kPrivacyModeDisabled); 2224 HostResolver::RequestInfo info(key2.host_port_pair()); 2225 AddressList addresses; 2226 // Pre-populate the DNS cache, since a synchronous resolution is required in 2227 // order to create the alias. 2228 session_deps_.host_resolver->Resolve( 2229 info, &addresses, CompletionCallback(), NULL, BoundNetLog()); 2230 // Get a session for |key2|, which should return the session created earlier. 2231 scoped_refptr<SpdySession> session2 = 2232 spdy_session_pool_->FindAvailableSession(key2, BoundNetLog()); 2233 ASSERT_EQ(session1.get(), session2.get()); 2234 EXPECT_FALSE(pool->IsStalled()); 2235 2236 // Release both the pointers to the session so it can be closed. 2237 session1 = NULL; 2238 session2 = NULL; 2239 2240 // Trying to create a new connection should cause the pool to be stalled, and 2241 // post a task asynchronously to try and close the session. 2242 TestCompletionCallback callback3; 2243 HostPortPair host_port3("3.com", 80); 2244 scoped_refptr<TransportSocketParams> params3( 2245 new TransportSocketParams(host_port3, DEFAULT_PRIORITY, false, false, 2246 OnHostResolutionCallback())); 2247 scoped_ptr<ClientSocketHandle> connection3(new ClientSocketHandle); 2248 EXPECT_EQ(ERR_IO_PENDING, 2249 connection3->Init(host_port3.ToString(), params3, DEFAULT_PRIORITY, 2250 callback3.callback(), pool, BoundNetLog())); 2251 EXPECT_TRUE(pool->IsStalled()); 2252 2253 // The socket pool should close the connection asynchronously and establish a 2254 // new connection. 2255 EXPECT_EQ(OK, callback3.WaitForResult()); 2256 EXPECT_FALSE(pool->IsStalled()); 2257} 2258 2259// Tests the case of a non-SPDY request closing an idle SPDY session when a 2260// pointer to the idle session is still held. 2261TEST_P(SpdySessionTest, CloseOneIdleConnectionSessionStillHeld) { 2262 ClientSocketPoolManager::set_max_sockets_per_group( 2263 HttpNetworkSession::NORMAL_SOCKET_POOL, 1); 2264 ClientSocketPoolManager::set_max_sockets_per_pool( 2265 HttpNetworkSession::NORMAL_SOCKET_POOL, 1); 2266 2267 MockConnect connect_data(SYNCHRONOUS, OK); 2268 MockRead reads[] = { 2269 MockRead(SYNCHRONOUS, ERR_IO_PENDING) // Stall forever. 2270 }; 2271 StaticSocketDataProvider data(reads, arraysize(reads), NULL, 0); 2272 data.set_connect_data(connect_data); 2273 session_deps_.socket_factory->AddSocketDataProvider(&data); 2274 session_deps_.socket_factory->AddSocketDataProvider(&data); 2275 2276 CreateNetworkSession(); 2277 2278 TransportClientSocketPool* pool = 2279 http_session_->GetTransportSocketPool( 2280 HttpNetworkSession::NORMAL_SOCKET_POOL); 2281 2282 // Create an idle SPDY session. 2283 SpdySessionKey key1(HostPortPair("1.com", 80), ProxyServer::Direct(), 2284 kPrivacyModeDisabled); 2285 scoped_refptr<SpdySession> session1 = 2286 CreateInsecureSpdySession(http_session_, key1, BoundNetLog()); 2287 EXPECT_FALSE(pool->IsStalled()); 2288 2289 // Trying to create a new connection should cause the pool to be stalled, and 2290 // post a task asynchronously to try and close the session. 2291 TestCompletionCallback callback2; 2292 HostPortPair host_port2("2.com", 80); 2293 scoped_refptr<TransportSocketParams> params2( 2294 new TransportSocketParams(host_port2, DEFAULT_PRIORITY, false, false, 2295 OnHostResolutionCallback())); 2296 scoped_ptr<ClientSocketHandle> connection2(new ClientSocketHandle); 2297 EXPECT_EQ(ERR_IO_PENDING, 2298 connection2->Init(host_port2.ToString(), params2, DEFAULT_PRIORITY, 2299 callback2.callback(), pool, BoundNetLog())); 2300 EXPECT_TRUE(pool->IsStalled()); 2301 2302 // Running the message loop should cause the session to prepare to be closed, 2303 // but since there's still an outstanding reference, it should not be closed 2304 // yet. 2305 base::RunLoop().RunUntilIdle(); 2306 EXPECT_TRUE(pool->IsStalled()); 2307 EXPECT_FALSE(callback2.have_result()); 2308 2309 // Release the pointer to the session so it can be closed. 2310 session1 = NULL; 2311 EXPECT_EQ(OK, callback2.WaitForResult()); 2312 EXPECT_FALSE(pool->IsStalled()); 2313} 2314 2315// Tests that a non-SPDY request can't close a SPDY session that's currently in 2316// use. 2317TEST_P(SpdySessionTest, CloseOneIdleConnectionFailsWhenSessionInUse) { 2318 ClientSocketPoolManager::set_max_sockets_per_group( 2319 HttpNetworkSession::NORMAL_SOCKET_POOL, 1); 2320 ClientSocketPoolManager::set_max_sockets_per_pool( 2321 HttpNetworkSession::NORMAL_SOCKET_POOL, 1); 2322 2323 MockConnect connect_data(SYNCHRONOUS, OK); 2324 MockRead reads[] = { 2325 MockRead(SYNCHRONOUS, ERR_IO_PENDING) // Stall forever. 2326 }; 2327 scoped_ptr<SpdyFrame> req1( 2328 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true)); 2329 scoped_ptr<SpdyFrame> cancel1( 2330 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_CANCEL)); 2331 MockWrite writes[] = { 2332 CreateMockWrite(*req1, 1), 2333 CreateMockWrite(*cancel1, 1), 2334 }; 2335 StaticSocketDataProvider data(reads, arraysize(reads), 2336 writes, arraysize(writes)); 2337 data.set_connect_data(connect_data); 2338 session_deps_.socket_factory->AddSocketDataProvider(&data); 2339 2340 CreateNetworkSession(); 2341 2342 TransportClientSocketPool* pool = 2343 http_session_->GetTransportSocketPool( 2344 HttpNetworkSession::NORMAL_SOCKET_POOL); 2345 2346 // Create a SPDY session. 2347 GURL url1("http://www.google.com"); 2348 SpdySessionKey key1(HostPortPair(url1.host(), 80), 2349 ProxyServer::Direct(), kPrivacyModeDisabled); 2350 scoped_refptr<SpdySession> session1 = 2351 CreateInsecureSpdySession(http_session_, key1, BoundNetLog()); 2352 EXPECT_FALSE(pool->IsStalled()); 2353 2354 // Create a stream using the session, and send a request. 2355 2356 TestCompletionCallback callback1; 2357 base::WeakPtr<SpdyStream> spdy_stream1 = 2358 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM, 2359 session1, url1, DEFAULT_PRIORITY, 2360 BoundNetLog()); 2361 ASSERT_TRUE(spdy_stream1.get()); 2362 test::StreamDelegateDoNothing delegate1(spdy_stream1); 2363 spdy_stream1->SetDelegate(&delegate1); 2364 2365 scoped_ptr<SpdyHeaderBlock> headers1( 2366 spdy_util_.ConstructGetHeaderBlock(url1.spec())); 2367 EXPECT_EQ(ERR_IO_PENDING, 2368 spdy_stream1->SendRequestHeaders( 2369 headers1.Pass(), NO_MORE_DATA_TO_SEND)); 2370 EXPECT_TRUE(spdy_stream1->HasUrl()); 2371 2372 base::MessageLoop::current()->RunUntilIdle(); 2373 2374 // Release the session, so holding onto a pointer here does not affect 2375 // anything. 2376 session1 = NULL; 2377 2378 // Trying to create a new connection should cause the pool to be stalled, and 2379 // post a task asynchronously to try and close the session. 2380 TestCompletionCallback callback2; 2381 HostPortPair host_port2("2.com", 80); 2382 scoped_refptr<TransportSocketParams> params2( 2383 new TransportSocketParams(host_port2, DEFAULT_PRIORITY, false, false, 2384 OnHostResolutionCallback())); 2385 scoped_ptr<ClientSocketHandle> connection2(new ClientSocketHandle); 2386 EXPECT_EQ(ERR_IO_PENDING, 2387 connection2->Init(host_port2.ToString(), params2, DEFAULT_PRIORITY, 2388 callback2.callback(), pool, BoundNetLog())); 2389 EXPECT_TRUE(pool->IsStalled()); 2390 2391 // Running the message loop should cause the socket pool to ask the SPDY 2392 // session to close an idle socket, but since the socket is in use, nothing 2393 // happens. 2394 base::RunLoop().RunUntilIdle(); 2395 EXPECT_TRUE(pool->IsStalled()); 2396 EXPECT_FALSE(callback2.have_result()); 2397 2398 // Cancelling the request should still not release the session's socket, 2399 // since the session is still kept alive by the SpdySessionPool. 2400 ASSERT_TRUE(spdy_stream1.get()); 2401 spdy_stream1->Cancel(); 2402 base::RunLoop().RunUntilIdle(); 2403 EXPECT_TRUE(pool->IsStalled()); 2404 EXPECT_FALSE(callback2.have_result()); 2405} 2406 2407// Verify that SpdySessionKey and therefore SpdySession is different when 2408// privacy mode is enabled or disabled. 2409TEST_P(SpdySessionTest, SpdySessionKeyPrivacyMode) { 2410 CreateDeterministicNetworkSession(); 2411 2412 HostPortPair host_port_pair("www.google.com", 443); 2413 SpdySessionKey key_privacy_enabled(host_port_pair, ProxyServer::Direct(), 2414 kPrivacyModeEnabled); 2415 SpdySessionKey key_privacy_disabled(host_port_pair, ProxyServer::Direct(), 2416 kPrivacyModeDisabled); 2417 2418 EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_privacy_enabled)); 2419 EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_privacy_disabled)); 2420 2421 // Add SpdySession with PrivacyMode Enabled to the pool. 2422 scoped_refptr<SpdySession> session_privacy_enabled = 2423 CreateFakeSpdySession(spdy_session_pool_, key_privacy_enabled); 2424 2425 EXPECT_TRUE(HasSpdySession(spdy_session_pool_, key_privacy_enabled)); 2426 EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_privacy_disabled)); 2427 2428 // Add SpdySession with PrivacyMode Disabled to the pool. 2429 scoped_refptr<SpdySession> session_privacy_disabled = 2430 CreateFakeSpdySession(spdy_session_pool_, key_privacy_disabled); 2431 2432 EXPECT_TRUE(HasSpdySession(spdy_session_pool_, key_privacy_enabled)); 2433 EXPECT_TRUE(HasSpdySession(spdy_session_pool_, key_privacy_disabled)); 2434 2435 session_privacy_enabled->CloseSessionOnError(ERR_ABORTED, std::string()); 2436 EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_privacy_enabled)); 2437 EXPECT_TRUE(HasSpdySession(spdy_session_pool_, key_privacy_disabled)); 2438 2439 session_privacy_disabled->CloseSessionOnError(ERR_ABORTED, std::string()); 2440 EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_privacy_enabled)); 2441 EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_privacy_disabled)); 2442} 2443 2444// The tests below are only for SPDY/3 and above. 2445 2446TEST_P(SpdySessionTest, SendCredentials) { 2447 if (GetParam() < kProtoSPDY3) 2448 return; 2449 2450 MockConnect connect_data(SYNCHRONOUS, OK); 2451 MockRead reads[] = { 2452 MockRead(SYNCHRONOUS, ERR_IO_PENDING) // Stall forever. 2453 }; 2454 SettingsMap settings; 2455 scoped_ptr<SpdyFrame> settings_frame( 2456 spdy_util_.ConstructSpdySettings(settings)); 2457 MockWrite writes[] = { 2458 CreateMockWrite(*settings_frame), 2459 }; 2460 StaticSocketDataProvider data(reads, arraysize(reads), 2461 writes, arraysize(writes)); 2462 data.set_connect_data(connect_data); 2463 session_deps_.socket_factory->AddSocketDataProvider(&data); 2464 2465 SSLSocketDataProvider ssl(SYNCHRONOUS, OK); 2466 ssl.channel_id_sent = true; 2467 ssl.protocol_negotiated = GetParam(); 2468 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl); 2469 2470 CreateNetworkSession(); 2471 2472 const GURL kTestUrl("https://www.foo.com"); 2473 HostPortPair test_host_port_pair(kTestUrl.host(), 443); 2474 SpdySessionKey key(test_host_port_pair, ProxyServer::Direct(), 2475 kPrivacyModeDisabled); 2476 2477 scoped_refptr<SpdySession> session = 2478 CreateSecureSpdySession(http_session_, key, BoundNetLog()); 2479 2480 EXPECT_TRUE(session->NeedsCredentials()); 2481 2482 // Flush the read completion task. 2483 base::MessageLoop::current()->RunUntilIdle(); 2484 2485 session->CloseSessionOnError(ERR_ABORTED, std::string()); 2486 EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key)); 2487} 2488 2489TEST_P(SpdySessionTest, UpdateStreamsSendWindowSize) { 2490 if (GetParam() < kProtoSPDY3) 2491 return; 2492 2493 // Set SETTINGS_INITIAL_WINDOW_SIZE to a small number so that WINDOW_UPDATE 2494 // gets sent. 2495 SettingsMap new_settings; 2496 int32 window_size = 1; 2497 new_settings[SETTINGS_INITIAL_WINDOW_SIZE] = 2498 SettingsFlagsAndValue(SETTINGS_FLAG_NONE, window_size); 2499 2500 // Set up the socket so we read a SETTINGS frame that sets 2501 // INITIAL_WINDOW_SIZE. 2502 MockConnect connect_data(SYNCHRONOUS, OK); 2503 scoped_ptr<SpdyFrame> settings_frame( 2504 spdy_util_.ConstructSpdySettings(new_settings)); 2505 MockRead reads[] = { 2506 CreateMockRead(*settings_frame, 0), 2507 MockRead(ASYNC, 0, 1) // EOF 2508 }; 2509 2510 session_deps_.host_resolver->set_synchronous_mode(true); 2511 2512 scoped_ptr<DeterministicSocketData> data( 2513 new DeterministicSocketData(reads, arraysize(reads), NULL, 0)); 2514 data->set_connect_data(connect_data); 2515 session_deps_.deterministic_socket_factory->AddSocketDataProvider(data.get()); 2516 2517 SSLSocketDataProvider ssl(SYNCHRONOUS, OK); 2518 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl); 2519 2520 CreateDeterministicNetworkSession(); 2521 2522 scoped_refptr<SpdySession> session = 2523 CreateInsecureSpdySession(http_session_, key_, BoundNetLog()); 2524 base::WeakPtr<SpdyStream> spdy_stream1 = 2525 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM, 2526 session, test_url_, MEDIUM, BoundNetLog()); 2527 ASSERT_TRUE(spdy_stream1.get() != NULL); 2528 TestCompletionCallback callback1; 2529 EXPECT_NE(spdy_stream1->send_window_size(), window_size); 2530 2531 data->RunFor(1); // Process the SETTINGS frame, but not the EOF 2532 base::MessageLoop::current()->RunUntilIdle(); 2533 EXPECT_EQ(session->stream_initial_send_window_size(), window_size); 2534 EXPECT_EQ(spdy_stream1->send_window_size(), window_size); 2535 2536 // Release the first one, this will allow the second to be created. 2537 spdy_stream1->Cancel(); 2538 EXPECT_EQ(NULL, spdy_stream1.get()); 2539 2540 base::WeakPtr<SpdyStream> spdy_stream2 = 2541 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM, 2542 session, test_url_, MEDIUM, BoundNetLog()); 2543 ASSERT_TRUE(spdy_stream2.get() != NULL); 2544 EXPECT_EQ(spdy_stream2->send_window_size(), window_size); 2545 spdy_stream2->Cancel(); 2546 EXPECT_EQ(NULL, spdy_stream2.get()); 2547} 2548 2549// The tests below are only for SPDY/3.1 and above. 2550 2551// SpdySession::{Increase,Decrease}RecvWindowSize should properly 2552// adjust the session receive window size for SPDY 3.1 and higher. In 2553// addition, SpdySession::IncreaseRecvWindowSize should trigger 2554// sending a WINDOW_UPDATE frame for a large enough delta. 2555TEST_P(SpdySessionTest, AdjustRecvWindowSize) { 2556 if (GetParam() < kProtoSPDY31) 2557 return; 2558 2559 session_deps_.host_resolver->set_synchronous_mode(true); 2560 2561 const int32 delta_window_size = 100; 2562 2563 MockConnect connect_data(SYNCHRONOUS, OK); 2564 MockRead reads[] = { 2565 MockRead(ASYNC, 0, 1) // EOF 2566 }; 2567 scoped_ptr<SpdyFrame> window_update( 2568 spdy_util_.ConstructSpdyWindowUpdate( 2569 kSessionFlowControlStreamId, 2570 kSpdySessionInitialWindowSize + delta_window_size)); 2571 MockWrite writes[] = { 2572 CreateMockWrite(*window_update, 0), 2573 }; 2574 DeterministicSocketData data(reads, arraysize(reads), 2575 writes, arraysize(writes)); 2576 data.set_connect_data(connect_data); 2577 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data); 2578 2579 SSLSocketDataProvider ssl(SYNCHRONOUS, OK); 2580 session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl); 2581 2582 CreateDeterministicNetworkSession(); 2583 scoped_refptr<SpdySession> session = 2584 CreateInsecureSpdySession(http_session_, key_, BoundNetLog()); 2585 EXPECT_EQ(SpdySession::FLOW_CONTROL_STREAM_AND_SESSION, 2586 session->flow_control_state()); 2587 2588 EXPECT_EQ(kSpdySessionInitialWindowSize, session->session_recv_window_size_); 2589 EXPECT_EQ(0, session->session_unacked_recv_window_bytes_); 2590 2591 session->IncreaseRecvWindowSize(delta_window_size); 2592 EXPECT_EQ(kSpdySessionInitialWindowSize + delta_window_size, 2593 session->session_recv_window_size_); 2594 EXPECT_EQ(delta_window_size, session->session_unacked_recv_window_bytes_); 2595 2596 // Should trigger sending a WINDOW_UPDATE frame. 2597 session->IncreaseRecvWindowSize(kSpdySessionInitialWindowSize); 2598 EXPECT_EQ(kSpdySessionInitialWindowSize + delta_window_size + 2599 kSpdySessionInitialWindowSize, 2600 session->session_recv_window_size_); 2601 EXPECT_EQ(0, session->session_unacked_recv_window_bytes_); 2602 2603 data.RunFor(1); 2604 2605 session->DecreaseRecvWindowSize( 2606 kSpdySessionInitialWindowSize + delta_window_size + 2607 kSpdySessionInitialWindowSize); 2608 EXPECT_EQ(0, session->session_recv_window_size_); 2609 EXPECT_EQ(0, session->session_unacked_recv_window_bytes_); 2610} 2611 2612// SpdySession::{Increase,Decrease}SendWindowSize should properly 2613// adjust the session send window size when the "enable_spdy_31" flag 2614// is set. 2615TEST_P(SpdySessionTest, AdjustSendWindowSize) { 2616 if (GetParam() < kProtoSPDY31) 2617 return; 2618 2619 session_deps_.host_resolver->set_synchronous_mode(true); 2620 2621 MockConnect connect_data(SYNCHRONOUS, OK); 2622 MockRead reads[] = { 2623 MockRead(SYNCHRONOUS, 0, 0) // EOF 2624 }; 2625 StaticSocketDataProvider data(reads, arraysize(reads), NULL, 0); 2626 data.set_connect_data(connect_data); 2627 session_deps_.socket_factory->AddSocketDataProvider(&data); 2628 2629 CreateNetworkSession(); 2630 scoped_refptr<SpdySession> session = 2631 CreateFakeSpdySession(spdy_session_pool_, key_); 2632 EXPECT_EQ(SpdySession::FLOW_CONTROL_STREAM_AND_SESSION, 2633 session->flow_control_state()); 2634 2635 const int32 delta_window_size = 100; 2636 2637 EXPECT_EQ(kSpdySessionInitialWindowSize, session->session_send_window_size_); 2638 2639 session->IncreaseSendWindowSize(delta_window_size); 2640 EXPECT_EQ(kSpdySessionInitialWindowSize + delta_window_size, 2641 session->session_send_window_size_); 2642 2643 session->DecreaseSendWindowSize(delta_window_size); 2644 EXPECT_EQ(kSpdySessionInitialWindowSize, session->session_send_window_size_); 2645} 2646 2647// Incoming data for an inactive stream should not cause the session 2648// receive window size to decrease. 2649TEST_P(SpdySessionTest, SessionFlowControlInactiveStream) { 2650 if (GetParam() < kProtoSPDY31) 2651 return; 2652 2653 session_deps_.host_resolver->set_synchronous_mode(true); 2654 2655 MockConnect connect_data(SYNCHRONOUS, OK); 2656 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyBodyFrame(1, false)); 2657 MockRead reads[] = { 2658 CreateMockRead(*resp, 0), 2659 MockRead(ASYNC, 0, 1) // EOF 2660 }; 2661 DeterministicSocketData data(reads, arraysize(reads), NULL, 0); 2662 data.set_connect_data(connect_data); 2663 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data); 2664 2665 SSLSocketDataProvider ssl(SYNCHRONOUS, OK); 2666 session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl); 2667 2668 CreateDeterministicNetworkSession(); 2669 scoped_refptr<SpdySession> session = 2670 CreateInsecureSpdySession(http_session_, key_, BoundNetLog()); 2671 EXPECT_EQ(SpdySession::FLOW_CONTROL_STREAM_AND_SESSION, 2672 session->flow_control_state()); 2673 2674 EXPECT_EQ(kSpdySessionInitialWindowSize, session->session_recv_window_size_); 2675 EXPECT_EQ(0, session->session_unacked_recv_window_bytes_); 2676 2677 data.RunFor(2); 2678 2679 EXPECT_EQ(kSpdySessionInitialWindowSize, session->session_recv_window_size_); 2680 EXPECT_EQ(0, session->session_unacked_recv_window_bytes_); 2681} 2682 2683// A delegate that drops any received data. 2684class DropReceivedDataDelegate : public test::StreamDelegateSendImmediate { 2685 public: 2686 DropReceivedDataDelegate(const base::WeakPtr<SpdyStream>& stream, 2687 base::StringPiece data) 2688 : StreamDelegateSendImmediate(stream, data) {} 2689 2690 virtual ~DropReceivedDataDelegate() {} 2691 2692 // Drop any received data. 2693 virtual void OnDataReceived(scoped_ptr<SpdyBuffer> buffer) OVERRIDE {} 2694}; 2695 2696// Send data back and forth but use a delegate that drops its received 2697// data. The receive window should still increase to its original 2698// value, i.e. we shouldn't "leak" receive window bytes. 2699TEST_P(SpdySessionTest, SessionFlowControlNoReceiveLeaks) { 2700 if (GetParam() < kProtoSPDY31) 2701 return; 2702 2703 const char kStreamUrl[] = "http://www.google.com/"; 2704 2705 const int32 msg_data_size = 100; 2706 const std::string msg_data(msg_data_size, 'a'); 2707 2708 MockConnect connect_data(SYNCHRONOUS, OK); 2709 2710 scoped_ptr<SpdyFrame> req( 2711 spdy_util_.ConstructSpdyPost( 2712 kStreamUrl, 1, msg_data_size, MEDIUM, NULL, 0)); 2713 scoped_ptr<SpdyFrame> msg( 2714 spdy_util_.ConstructSpdyBodyFrame( 2715 1, msg_data.data(), msg_data_size, false)); 2716 MockWrite writes[] = { 2717 CreateMockWrite(*req, 0), 2718 CreateMockWrite(*msg, 2), 2719 }; 2720 2721 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1)); 2722 scoped_ptr<SpdyFrame> echo( 2723 spdy_util_.ConstructSpdyBodyFrame( 2724 1, msg_data.data(), msg_data_size, false)); 2725 scoped_ptr<SpdyFrame> window_update( 2726 spdy_util_.ConstructSpdyWindowUpdate( 2727 kSessionFlowControlStreamId, msg_data_size)); 2728 MockRead reads[] = { 2729 CreateMockRead(*resp, 1), 2730 CreateMockRead(*echo, 3), 2731 MockRead(ASYNC, 0, 4) // EOF 2732 }; 2733 2734 // Create SpdySession and SpdyStream and send the request. 2735 DeterministicSocketData data(reads, arraysize(reads), 2736 writes, arraysize(writes)); 2737 data.set_connect_data(connect_data); 2738 session_deps_.host_resolver->set_synchronous_mode(true); 2739 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data); 2740 2741 SSLSocketDataProvider ssl(SYNCHRONOUS, OK); 2742 session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl); 2743 2744 CreateDeterministicNetworkSession(); 2745 2746 scoped_refptr<SpdySession> session = 2747 CreateInsecureSpdySession(http_session_, key_, BoundNetLog()); 2748 2749 GURL url(kStreamUrl); 2750 base::WeakPtr<SpdyStream> stream = 2751 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM, 2752 session, url, MEDIUM, BoundNetLog()); 2753 ASSERT_TRUE(stream.get() != NULL); 2754 EXPECT_EQ(0u, stream->stream_id()); 2755 2756 DropReceivedDataDelegate delegate(stream, msg_data); 2757 stream->SetDelegate(&delegate); 2758 2759 scoped_ptr<SpdyHeaderBlock> headers( 2760 spdy_util_.ConstructPostHeaderBlock(url.spec(), msg_data_size)); 2761 EXPECT_EQ(ERR_IO_PENDING, 2762 stream->SendRequestHeaders(headers.Pass(), MORE_DATA_TO_SEND)); 2763 EXPECT_TRUE(stream->HasUrl()); 2764 2765 EXPECT_EQ(kSpdySessionInitialWindowSize, session->session_recv_window_size_); 2766 EXPECT_EQ(0, session->session_unacked_recv_window_bytes_); 2767 2768 data.RunFor(4); 2769 2770 EXPECT_TRUE(data.at_write_eof()); 2771 EXPECT_TRUE(data.at_read_eof()); 2772 2773 EXPECT_EQ(kSpdySessionInitialWindowSize, session->session_recv_window_size_); 2774 EXPECT_EQ(msg_data_size, session->session_unacked_recv_window_bytes_); 2775 2776 stream->Close(); 2777 EXPECT_EQ(NULL, stream.get()); 2778 2779 EXPECT_EQ(OK, delegate.WaitForClose()); 2780 2781 EXPECT_EQ(kSpdySessionInitialWindowSize, session->session_recv_window_size_); 2782 EXPECT_EQ(msg_data_size, session->session_unacked_recv_window_bytes_); 2783} 2784 2785// Send data back and forth but close the stream before its data frame 2786// can be written to the socket. The send window should then increase 2787// to its original value, i.e. we shouldn't "leak" send window bytes. 2788TEST_P(SpdySessionTest, SessionFlowControlNoSendLeaks) { 2789 if (GetParam() < kProtoSPDY31) 2790 return; 2791 2792 const char kStreamUrl[] = "http://www.google.com/"; 2793 2794 const int32 msg_data_size = 100; 2795 const std::string msg_data(msg_data_size, 'a'); 2796 2797 MockConnect connect_data(SYNCHRONOUS, OK); 2798 2799 scoped_ptr<SpdyFrame> req( 2800 spdy_util_.ConstructSpdyPost( 2801 kStreamUrl, 1, msg_data_size, MEDIUM, NULL, 0)); 2802 MockWrite writes[] = { 2803 CreateMockWrite(*req, 0), 2804 }; 2805 2806 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1)); 2807 MockRead reads[] = { 2808 CreateMockRead(*resp, 1), 2809 MockRead(ASYNC, 0, 2) // EOF 2810 }; 2811 2812 // Create SpdySession and SpdyStream and send the request. 2813 DeterministicSocketData data(reads, arraysize(reads), 2814 writes, arraysize(writes)); 2815 data.set_connect_data(connect_data); 2816 session_deps_.host_resolver->set_synchronous_mode(true); 2817 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data); 2818 2819 SSLSocketDataProvider ssl(SYNCHRONOUS, OK); 2820 session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl); 2821 2822 CreateDeterministicNetworkSession(); 2823 2824 scoped_refptr<SpdySession> session = 2825 CreateInsecureSpdySession(http_session_, key_, BoundNetLog()); 2826 2827 GURL url(kStreamUrl); 2828 base::WeakPtr<SpdyStream> stream = 2829 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM, 2830 session, url, MEDIUM, BoundNetLog()); 2831 ASSERT_TRUE(stream.get() != NULL); 2832 EXPECT_EQ(0u, stream->stream_id()); 2833 2834 test::StreamDelegateSendImmediate delegate(stream, msg_data); 2835 stream->SetDelegate(&delegate); 2836 2837 scoped_ptr<SpdyHeaderBlock> headers( 2838 spdy_util_.ConstructPostHeaderBlock(url.spec(), msg_data_size)); 2839 EXPECT_EQ(ERR_IO_PENDING, 2840 stream->SendRequestHeaders(headers.Pass(), MORE_DATA_TO_SEND)); 2841 EXPECT_TRUE(stream->HasUrl()); 2842 2843 EXPECT_EQ(kSpdySessionInitialWindowSize, session->session_send_window_size_); 2844 2845 data.RunFor(1); 2846 2847 EXPECT_EQ(kSpdySessionInitialWindowSize, session->session_send_window_size_); 2848 2849 data.RunFor(1); 2850 2851 EXPECT_TRUE(data.at_write_eof()); 2852 EXPECT_TRUE(data.at_read_eof()); 2853 2854 EXPECT_EQ(kSpdySessionInitialWindowSize - msg_data_size, 2855 session->session_send_window_size_); 2856 2857 // Closing the stream should increase the session's send window. 2858 stream->Close(); 2859 EXPECT_EQ(NULL, stream.get()); 2860 2861 EXPECT_EQ(kSpdySessionInitialWindowSize, session->session_send_window_size_); 2862 2863 EXPECT_EQ(OK, delegate.WaitForClose()); 2864} 2865 2866// Send data back and forth; the send and receive windows should 2867// change appropriately. 2868TEST_P(SpdySessionTest, SessionFlowControlEndToEnd) { 2869 if (GetParam() < kProtoSPDY31) 2870 return; 2871 2872 const char kStreamUrl[] = "http://www.google.com/"; 2873 2874 const int32 msg_data_size = 100; 2875 const std::string msg_data(msg_data_size, 'a'); 2876 2877 MockConnect connect_data(SYNCHRONOUS, OK); 2878 2879 scoped_ptr<SpdyFrame> req( 2880 spdy_util_.ConstructSpdyPost( 2881 kStreamUrl, 1, msg_data_size, MEDIUM, NULL, 0)); 2882 scoped_ptr<SpdyFrame> msg( 2883 spdy_util_.ConstructSpdyBodyFrame( 2884 1, msg_data.data(), msg_data_size, false)); 2885 MockWrite writes[] = { 2886 CreateMockWrite(*req, 0), 2887 CreateMockWrite(*msg, 2), 2888 }; 2889 2890 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1)); 2891 scoped_ptr<SpdyFrame> echo( 2892 spdy_util_.ConstructSpdyBodyFrame( 2893 1, msg_data.data(), msg_data_size, false)); 2894 scoped_ptr<SpdyFrame> window_update( 2895 spdy_util_.ConstructSpdyWindowUpdate( 2896 kSessionFlowControlStreamId, msg_data_size)); 2897 MockRead reads[] = { 2898 CreateMockRead(*resp, 1), 2899 CreateMockRead(*echo, 3), 2900 CreateMockRead(*window_update, 4), 2901 MockRead(ASYNC, 0, 5) // EOF 2902 }; 2903 2904 // Create SpdySession and SpdyStream and send the request. 2905 DeterministicSocketData data(reads, arraysize(reads), 2906 writes, arraysize(writes)); 2907 data.set_connect_data(connect_data); 2908 session_deps_.host_resolver->set_synchronous_mode(true); 2909 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data); 2910 2911 SSLSocketDataProvider ssl(SYNCHRONOUS, OK); 2912 session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl); 2913 2914 CreateDeterministicNetworkSession(); 2915 2916 scoped_refptr<SpdySession> session = 2917 CreateInsecureSpdySession(http_session_, key_, BoundNetLog()); 2918 2919 GURL url(kStreamUrl); 2920 base::WeakPtr<SpdyStream> stream = 2921 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM, 2922 session, url, MEDIUM, BoundNetLog()); 2923 ASSERT_TRUE(stream.get() != NULL); 2924 EXPECT_EQ(0u, stream->stream_id()); 2925 2926 test::StreamDelegateSendImmediate delegate(stream, msg_data); 2927 stream->SetDelegate(&delegate); 2928 2929 scoped_ptr<SpdyHeaderBlock> headers( 2930 spdy_util_.ConstructPostHeaderBlock(url.spec(), msg_data_size)); 2931 EXPECT_EQ(ERR_IO_PENDING, 2932 stream->SendRequestHeaders(headers.Pass(), MORE_DATA_TO_SEND)); 2933 EXPECT_TRUE(stream->HasUrl()); 2934 2935 EXPECT_EQ(kSpdySessionInitialWindowSize, session->session_send_window_size_); 2936 EXPECT_EQ(kSpdySessionInitialWindowSize, session->session_recv_window_size_); 2937 EXPECT_EQ(0, session->session_unacked_recv_window_bytes_); 2938 2939 data.RunFor(1); 2940 2941 EXPECT_EQ(kSpdySessionInitialWindowSize, session->session_send_window_size_); 2942 EXPECT_EQ(kSpdySessionInitialWindowSize, session->session_recv_window_size_); 2943 EXPECT_EQ(0, session->session_unacked_recv_window_bytes_); 2944 2945 data.RunFor(1); 2946 2947 EXPECT_EQ(kSpdySessionInitialWindowSize - msg_data_size, 2948 session->session_send_window_size_); 2949 EXPECT_EQ(kSpdySessionInitialWindowSize, session->session_recv_window_size_); 2950 EXPECT_EQ(0, session->session_unacked_recv_window_bytes_); 2951 2952 data.RunFor(1); 2953 2954 EXPECT_EQ(kSpdySessionInitialWindowSize - msg_data_size, 2955 session->session_send_window_size_); 2956 EXPECT_EQ(kSpdySessionInitialWindowSize, session->session_recv_window_size_); 2957 EXPECT_EQ(0, session->session_unacked_recv_window_bytes_); 2958 2959 data.RunFor(1); 2960 2961 EXPECT_EQ(kSpdySessionInitialWindowSize - msg_data_size, 2962 session->session_send_window_size_); 2963 EXPECT_EQ(kSpdySessionInitialWindowSize - msg_data_size, 2964 session->session_recv_window_size_); 2965 EXPECT_EQ(0, session->session_unacked_recv_window_bytes_); 2966 2967 data.RunFor(1); 2968 2969 EXPECT_EQ(kSpdySessionInitialWindowSize, session->session_send_window_size_); 2970 EXPECT_EQ(kSpdySessionInitialWindowSize - msg_data_size, 2971 session->session_recv_window_size_); 2972 EXPECT_EQ(0, session->session_unacked_recv_window_bytes_); 2973 2974 EXPECT_TRUE(data.at_write_eof()); 2975 EXPECT_TRUE(data.at_read_eof()); 2976 2977 EXPECT_EQ(msg_data, delegate.TakeReceivedData()); 2978 2979 // Draining the delegate's read queue should increase the session's 2980 // receive window. 2981 EXPECT_EQ(kSpdySessionInitialWindowSize, session->session_send_window_size_); 2982 EXPECT_EQ(kSpdySessionInitialWindowSize, session->session_recv_window_size_); 2983 EXPECT_EQ(msg_data_size, session->session_unacked_recv_window_bytes_); 2984 2985 stream->Close(); 2986 EXPECT_EQ(NULL, stream.get()); 2987 2988 EXPECT_EQ(OK, delegate.WaitForClose()); 2989 2990 EXPECT_EQ(kSpdySessionInitialWindowSize, session->session_send_window_size_); 2991 EXPECT_EQ(kSpdySessionInitialWindowSize, session->session_recv_window_size_); 2992 EXPECT_EQ(msg_data_size, session->session_unacked_recv_window_bytes_); 2993} 2994 2995// Given a stall function and an unstall function, runs a test to make 2996// sure that a stream resumes after unstall. 2997void SpdySessionTest::RunResumeAfterUnstallTest( 2998 const base::Callback<void(SpdySession*, SpdyStream*)>& stall_function, 2999 const base::Callback<void(SpdySession*, SpdyStream*, int32)>& 3000 unstall_function) { 3001 const char kStreamUrl[] = "http://www.google.com/"; 3002 GURL url(kStreamUrl); 3003 3004 session_deps_.host_resolver->set_synchronous_mode(true); 3005 3006 scoped_ptr<SpdyFrame> req( 3007 spdy_util_.ConstructSpdyPost( 3008 kStreamUrl, 1, kBodyDataSize, LOWEST, NULL, 0)); 3009 scoped_ptr<SpdyFrame> body( 3010 spdy_util_.ConstructSpdyBodyFrame(1, kBodyData, kBodyDataSize, true)); 3011 MockWrite writes[] = { 3012 CreateMockWrite(*req, 0), 3013 CreateMockWrite(*body, 1), 3014 }; 3015 3016 scoped_ptr<SpdyFrame> resp( 3017 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1)); 3018 scoped_ptr<SpdyFrame> echo( 3019 spdy_util_.ConstructSpdyBodyFrame(1, kBodyData, kBodyDataSize, false)); 3020 MockRead reads[] = { 3021 CreateMockRead(*resp, 2), 3022 MockRead(ASYNC, 0, 0, 3), // EOF 3023 }; 3024 3025 DeterministicSocketData data(reads, arraysize(reads), 3026 writes, arraysize(writes)); 3027 MockConnect connect_data(SYNCHRONOUS, OK); 3028 data.set_connect_data(connect_data); 3029 3030 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data); 3031 3032 CreateDeterministicNetworkSession(); 3033 scoped_refptr<SpdySession> session = 3034 CreateInsecureSpdySession(http_session_, key_, BoundNetLog()); 3035 EXPECT_EQ(SpdySession::FLOW_CONTROL_STREAM_AND_SESSION, 3036 session->flow_control_state()); 3037 3038 base::WeakPtr<SpdyStream> stream = 3039 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM, 3040 session, url, LOWEST, BoundNetLog()); 3041 ASSERT_TRUE(stream.get() != NULL); 3042 3043 test::StreamDelegateWithBody delegate(stream, kBodyDataStringPiece); 3044 stream->SetDelegate(&delegate); 3045 3046 EXPECT_FALSE(stream->HasUrl()); 3047 EXPECT_FALSE(stream->send_stalled_by_flow_control()); 3048 3049 scoped_ptr<SpdyHeaderBlock> headers( 3050 spdy_util_.ConstructPostHeaderBlock(kStreamUrl, kBodyDataSize)); 3051 EXPECT_EQ(ERR_IO_PENDING, 3052 stream->SendRequestHeaders(headers.Pass(), MORE_DATA_TO_SEND)); 3053 EXPECT_TRUE(stream->HasUrl()); 3054 EXPECT_EQ(kStreamUrl, stream->GetUrl().spec()); 3055 3056 stall_function.Run(session.get(), stream.get()); 3057 3058 data.RunFor(1); 3059 3060 EXPECT_TRUE(stream->send_stalled_by_flow_control()); 3061 3062 unstall_function.Run(session.get(), stream.get(), kBodyDataSize); 3063 3064 EXPECT_FALSE(stream->send_stalled_by_flow_control()); 3065 3066 data.RunFor(3); 3067 3068 EXPECT_EQ(ERR_CONNECTION_CLOSED, delegate.WaitForClose()); 3069 3070 EXPECT_TRUE(delegate.send_headers_completed()); 3071 EXPECT_EQ("200", delegate.GetResponseHeaderValue(":status")); 3072 EXPECT_EQ("HTTP/1.1", delegate.GetResponseHeaderValue(":version")); 3073 EXPECT_EQ(std::string(), delegate.TakeReceivedData()); 3074 EXPECT_TRUE(data.at_write_eof()); 3075} 3076 3077// Run the resume-after-unstall test with all possible stall and 3078// unstall sequences. 3079 3080TEST_P(SpdySessionTest, ResumeAfterUnstallSession) { 3081 if (GetParam() < kProtoSPDY31) 3082 return; 3083 3084 RunResumeAfterUnstallTest( 3085 base::Bind(&SpdySessionTest::StallSessionOnly, 3086 base::Unretained(this)), 3087 base::Bind(&SpdySessionTest::UnstallSessionOnly, 3088 base::Unretained(this))); 3089} 3090 3091// Equivalent to 3092// SpdyStreamTest.ResumeAfterSendWindowSizeIncrease. 3093TEST_P(SpdySessionTest, ResumeAfterUnstallStream) { 3094 if (GetParam() < kProtoSPDY31) 3095 return; 3096 3097 RunResumeAfterUnstallTest( 3098 base::Bind(&SpdySessionTest::StallStreamOnly, 3099 base::Unretained(this)), 3100 base::Bind(&SpdySessionTest::UnstallStreamOnly, 3101 base::Unretained(this))); 3102} 3103 3104TEST_P(SpdySessionTest, StallSessionStreamResumeAfterUnstallSessionStream) { 3105 if (GetParam() < kProtoSPDY31) 3106 return; 3107 3108 RunResumeAfterUnstallTest( 3109 base::Bind(&SpdySessionTest::StallSessionStream, 3110 base::Unretained(this)), 3111 base::Bind(&SpdySessionTest::UnstallSessionStream, 3112 base::Unretained(this))); 3113} 3114 3115TEST_P(SpdySessionTest, StallStreamSessionResumeAfterUnstallSessionStream) { 3116 if (GetParam() < kProtoSPDY31) 3117 return; 3118 3119 RunResumeAfterUnstallTest( 3120 base::Bind(&SpdySessionTest::StallStreamSession, 3121 base::Unretained(this)), 3122 base::Bind(&SpdySessionTest::UnstallSessionStream, 3123 base::Unretained(this))); 3124} 3125 3126TEST_P(SpdySessionTest, StallStreamSessionResumeAfterUnstallStreamSession) { 3127 if (GetParam() < kProtoSPDY31) 3128 return; 3129 3130 RunResumeAfterUnstallTest( 3131 base::Bind(&SpdySessionTest::StallStreamSession, 3132 base::Unretained(this)), 3133 base::Bind(&SpdySessionTest::UnstallStreamSession, 3134 base::Unretained(this))); 3135} 3136 3137TEST_P(SpdySessionTest, StallSessionStreamResumeAfterUnstallStreamSession) { 3138 if (GetParam() < kProtoSPDY31) 3139 return; 3140 3141 RunResumeAfterUnstallTest( 3142 base::Bind(&SpdySessionTest::StallSessionStream, 3143 base::Unretained(this)), 3144 base::Bind(&SpdySessionTest::UnstallStreamSession, 3145 base::Unretained(this))); 3146} 3147 3148// Cause a stall by reducing the flow control send window to 0. The 3149// streams should resume in priority order when that window is then 3150// increased. 3151TEST_P(SpdySessionTest, ResumeByPriorityAfterSendWindowSizeIncrease) { 3152 if (GetParam() < kProtoSPDY31) 3153 return; 3154 3155 const char kStreamUrl[] = "http://www.google.com/"; 3156 GURL url(kStreamUrl); 3157 3158 session_deps_.host_resolver->set_synchronous_mode(true); 3159 3160 scoped_ptr<SpdyFrame> req1( 3161 spdy_util_.ConstructSpdyPost( 3162 kStreamUrl, 1, kBodyDataSize, LOWEST, NULL, 0)); 3163 scoped_ptr<SpdyFrame> req2( 3164 spdy_util_.ConstructSpdyPost( 3165 kStreamUrl, 3, kBodyDataSize, MEDIUM, NULL, 0)); 3166 scoped_ptr<SpdyFrame> body1( 3167 spdy_util_.ConstructSpdyBodyFrame(1, kBodyData, kBodyDataSize, true)); 3168 scoped_ptr<SpdyFrame> body2( 3169 spdy_util_.ConstructSpdyBodyFrame(3, kBodyData, kBodyDataSize, true)); 3170 MockWrite writes[] = { 3171 CreateMockWrite(*req1, 0), 3172 CreateMockWrite(*req2, 1), 3173 CreateMockWrite(*body2, 2), 3174 CreateMockWrite(*body1, 3), 3175 }; 3176 3177 scoped_ptr<SpdyFrame> resp1(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1)); 3178 scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3)); 3179 MockRead reads[] = { 3180 CreateMockRead(*resp1, 4), 3181 CreateMockRead(*resp2, 5), 3182 MockRead(ASYNC, 0, 0, 6), // EOF 3183 }; 3184 3185 DeterministicSocketData data(reads, arraysize(reads), 3186 writes, arraysize(writes)); 3187 MockConnect connect_data(SYNCHRONOUS, OK); 3188 data.set_connect_data(connect_data); 3189 3190 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data); 3191 3192 CreateDeterministicNetworkSession(); 3193 scoped_refptr<SpdySession> session = 3194 CreateInsecureSpdySession(http_session_, key_, BoundNetLog()); 3195 EXPECT_EQ(SpdySession::FLOW_CONTROL_STREAM_AND_SESSION, 3196 session->flow_control_state()); 3197 3198 base::WeakPtr<SpdyStream> stream1 = 3199 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM, 3200 session, url, LOWEST, BoundNetLog()); 3201 ASSERT_TRUE(stream1.get() != NULL); 3202 3203 test::StreamDelegateWithBody delegate1(stream1, kBodyDataStringPiece); 3204 stream1->SetDelegate(&delegate1); 3205 3206 EXPECT_FALSE(stream1->HasUrl()); 3207 3208 base::WeakPtr<SpdyStream> stream2 = 3209 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM, 3210 session, url, MEDIUM, BoundNetLog()); 3211 ASSERT_TRUE(stream2.get() != NULL); 3212 3213 test::StreamDelegateWithBody delegate2(stream2, kBodyDataStringPiece); 3214 stream2->SetDelegate(&delegate2); 3215 3216 EXPECT_FALSE(stream2->HasUrl()); 3217 3218 EXPECT_FALSE(stream1->send_stalled_by_flow_control()); 3219 EXPECT_FALSE(stream2->send_stalled_by_flow_control()); 3220 3221 StallSessionSend(session.get()); 3222 3223 scoped_ptr<SpdyHeaderBlock> headers1( 3224 spdy_util_.ConstructPostHeaderBlock(kStreamUrl, kBodyDataSize)); 3225 EXPECT_EQ(ERR_IO_PENDING, 3226 stream1->SendRequestHeaders(headers1.Pass(), MORE_DATA_TO_SEND)); 3227 EXPECT_TRUE(stream1->HasUrl()); 3228 EXPECT_EQ(kStreamUrl, stream1->GetUrl().spec()); 3229 3230 data.RunFor(1); 3231 EXPECT_EQ(1u, stream1->stream_id()); 3232 EXPECT_TRUE(stream1->send_stalled_by_flow_control()); 3233 3234 scoped_ptr<SpdyHeaderBlock> headers2( 3235 spdy_util_.ConstructPostHeaderBlock(kStreamUrl, kBodyDataSize)); 3236 EXPECT_EQ(ERR_IO_PENDING, 3237 stream2->SendRequestHeaders(headers2.Pass(), MORE_DATA_TO_SEND)); 3238 EXPECT_TRUE(stream2->HasUrl()); 3239 EXPECT_EQ(kStreamUrl, stream2->GetUrl().spec()); 3240 3241 data.RunFor(1); 3242 EXPECT_EQ(3u, stream2->stream_id()); 3243 EXPECT_TRUE(stream2->send_stalled_by_flow_control()); 3244 3245 // This should unstall only stream2. 3246 UnstallSessionSend(session.get(), kBodyDataSize); 3247 3248 EXPECT_TRUE(stream1->send_stalled_by_flow_control()); 3249 EXPECT_FALSE(stream2->send_stalled_by_flow_control()); 3250 3251 data.RunFor(1); 3252 3253 EXPECT_TRUE(stream1->send_stalled_by_flow_control()); 3254 EXPECT_FALSE(stream2->send_stalled_by_flow_control()); 3255 3256 // This should then unstall stream1. 3257 UnstallSessionSend(session.get(), kBodyDataSize); 3258 3259 EXPECT_FALSE(stream1->send_stalled_by_flow_control()); 3260 EXPECT_FALSE(stream2->send_stalled_by_flow_control()); 3261 3262 data.RunFor(4); 3263 3264 EXPECT_EQ(ERR_CONNECTION_CLOSED, delegate1.WaitForClose()); 3265 EXPECT_EQ(ERR_CONNECTION_CLOSED, delegate2.WaitForClose()); 3266 3267 EXPECT_TRUE(delegate1.send_headers_completed()); 3268 EXPECT_EQ("200", delegate1.GetResponseHeaderValue(":status")); 3269 EXPECT_EQ("HTTP/1.1", delegate1.GetResponseHeaderValue(":version")); 3270 EXPECT_EQ(std::string(), delegate1.TakeReceivedData()); 3271 3272 EXPECT_TRUE(delegate2.send_headers_completed()); 3273 EXPECT_EQ("200", delegate2.GetResponseHeaderValue(":status")); 3274 EXPECT_EQ("HTTP/1.1", delegate2.GetResponseHeaderValue(":version")); 3275 EXPECT_EQ(std::string(), delegate2.TakeReceivedData()); 3276 3277 EXPECT_TRUE(data.at_write_eof()); 3278} 3279 3280// Delegate that closes a given stream after sending its body. 3281class StreamClosingDelegate : public test::StreamDelegateWithBody { 3282 public: 3283 StreamClosingDelegate(const base::WeakPtr<SpdyStream>& stream, 3284 base::StringPiece data) 3285 : StreamDelegateWithBody(stream, data) {} 3286 3287 virtual ~StreamClosingDelegate() {} 3288 3289 void set_stream_to_close(const base::WeakPtr<SpdyStream>& stream_to_close) { 3290 stream_to_close_ = stream_to_close; 3291 } 3292 3293 virtual void OnDataSent() OVERRIDE { 3294 test::StreamDelegateWithBody::OnDataSent(); 3295 if (stream_to_close_.get()) { 3296 stream_to_close_->Close(); 3297 EXPECT_EQ(NULL, stream_to_close_.get()); 3298 } 3299 } 3300 3301 private: 3302 base::WeakPtr<SpdyStream> stream_to_close_; 3303}; 3304 3305// Cause a stall by reducing the flow control send window to 3306// 0. Unstalling the session should properly handle deleted streams. 3307TEST_P(SpdySessionTest, SendWindowSizeIncreaseWithDeletedStreams) { 3308 if (GetParam() < kProtoSPDY31) 3309 return; 3310 3311 const char kStreamUrl[] = "http://www.google.com/"; 3312 GURL url(kStreamUrl); 3313 3314 session_deps_.host_resolver->set_synchronous_mode(true); 3315 3316 scoped_ptr<SpdyFrame> req1( 3317 spdy_util_.ConstructSpdyPost( 3318 kStreamUrl, 1, kBodyDataSize, LOWEST, NULL, 0)); 3319 scoped_ptr<SpdyFrame> req2( 3320 spdy_util_.ConstructSpdyPost( 3321 kStreamUrl, 3, kBodyDataSize, LOWEST, NULL, 0)); 3322 scoped_ptr<SpdyFrame> req3( 3323 spdy_util_.ConstructSpdyPost( 3324 kStreamUrl, 5, kBodyDataSize, LOWEST, NULL, 0)); 3325 scoped_ptr<SpdyFrame> body2( 3326 spdy_util_.ConstructSpdyBodyFrame(3, kBodyData, kBodyDataSize, true)); 3327 MockWrite writes[] = { 3328 CreateMockWrite(*req1, 0), 3329 CreateMockWrite(*req2, 1), 3330 CreateMockWrite(*req3, 2), 3331 CreateMockWrite(*body2, 3), 3332 }; 3333 3334 scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3)); 3335 MockRead reads[] = { 3336 CreateMockRead(*resp2, 4), 3337 MockRead(ASYNC, 0, 0, 5), // EOF 3338 }; 3339 3340 DeterministicSocketData data(reads, arraysize(reads), 3341 writes, arraysize(writes)); 3342 MockConnect connect_data(SYNCHRONOUS, OK); 3343 data.set_connect_data(connect_data); 3344 3345 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data); 3346 3347 CreateDeterministicNetworkSession(); 3348 scoped_refptr<SpdySession> session = 3349 CreateInsecureSpdySession(http_session_, key_, BoundNetLog()); 3350 EXPECT_EQ(SpdySession::FLOW_CONTROL_STREAM_AND_SESSION, 3351 session->flow_control_state()); 3352 3353 base::WeakPtr<SpdyStream> stream1 = 3354 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM, 3355 session, url, LOWEST, BoundNetLog()); 3356 ASSERT_TRUE(stream1.get() != NULL); 3357 3358 test::StreamDelegateWithBody delegate1(stream1, kBodyDataStringPiece); 3359 stream1->SetDelegate(&delegate1); 3360 3361 EXPECT_FALSE(stream1->HasUrl()); 3362 3363 base::WeakPtr<SpdyStream> stream2 = 3364 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM, 3365 session, url, LOWEST, BoundNetLog()); 3366 ASSERT_TRUE(stream2.get() != NULL); 3367 3368 StreamClosingDelegate delegate2(stream2, kBodyDataStringPiece); 3369 stream2->SetDelegate(&delegate2); 3370 3371 EXPECT_FALSE(stream2->HasUrl()); 3372 3373 base::WeakPtr<SpdyStream> stream3 = 3374 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM, 3375 session, url, LOWEST, BoundNetLog()); 3376 ASSERT_TRUE(stream3.get() != NULL); 3377 3378 test::StreamDelegateWithBody delegate3(stream3, kBodyDataStringPiece); 3379 stream3->SetDelegate(&delegate3); 3380 3381 EXPECT_FALSE(stream3->HasUrl()); 3382 3383 EXPECT_FALSE(stream1->send_stalled_by_flow_control()); 3384 EXPECT_FALSE(stream2->send_stalled_by_flow_control()); 3385 EXPECT_FALSE(stream3->send_stalled_by_flow_control()); 3386 3387 StallSessionSend(session.get()); 3388 3389 scoped_ptr<SpdyHeaderBlock> headers1( 3390 spdy_util_.ConstructPostHeaderBlock(kStreamUrl, kBodyDataSize)); 3391 EXPECT_EQ(ERR_IO_PENDING, 3392 stream1->SendRequestHeaders(headers1.Pass(), MORE_DATA_TO_SEND)); 3393 EXPECT_TRUE(stream1->HasUrl()); 3394 EXPECT_EQ(kStreamUrl, stream1->GetUrl().spec()); 3395 3396 data.RunFor(1); 3397 EXPECT_EQ(1u, stream1->stream_id()); 3398 EXPECT_TRUE(stream1->send_stalled_by_flow_control()); 3399 3400 scoped_ptr<SpdyHeaderBlock> headers2( 3401 spdy_util_.ConstructPostHeaderBlock(kStreamUrl, kBodyDataSize)); 3402 EXPECT_EQ(ERR_IO_PENDING, 3403 stream2->SendRequestHeaders(headers2.Pass(), MORE_DATA_TO_SEND)); 3404 EXPECT_TRUE(stream2->HasUrl()); 3405 EXPECT_EQ(kStreamUrl, stream2->GetUrl().spec()); 3406 3407 data.RunFor(1); 3408 EXPECT_EQ(3u, stream2->stream_id()); 3409 EXPECT_TRUE(stream2->send_stalled_by_flow_control()); 3410 3411 scoped_ptr<SpdyHeaderBlock> headers3( 3412 spdy_util_.ConstructPostHeaderBlock(kStreamUrl, kBodyDataSize)); 3413 EXPECT_EQ(ERR_IO_PENDING, 3414 stream3->SendRequestHeaders(headers3.Pass(), MORE_DATA_TO_SEND)); 3415 EXPECT_TRUE(stream3->HasUrl()); 3416 EXPECT_EQ(kStreamUrl, stream3->GetUrl().spec()); 3417 3418 data.RunFor(1); 3419 EXPECT_EQ(5u, stream3->stream_id()); 3420 EXPECT_TRUE(stream3->send_stalled_by_flow_control()); 3421 3422 SpdyStreamId stream_id1 = stream1->stream_id(); 3423 SpdyStreamId stream_id2 = stream2->stream_id(); 3424 SpdyStreamId stream_id3 = stream3->stream_id(); 3425 3426 // Close stream1 preemptively. 3427 session->CloseActiveStream(stream_id1, ERR_CONNECTION_CLOSED); 3428 EXPECT_EQ(NULL, stream1.get()); 3429 3430 EXPECT_FALSE(session->IsStreamActive(stream_id1)); 3431 EXPECT_TRUE(session->IsStreamActive(stream_id2)); 3432 EXPECT_TRUE(session->IsStreamActive(stream_id3)); 3433 3434 // Unstall stream2, which should then close stream3. 3435 delegate2.set_stream_to_close(stream3); 3436 UnstallSessionSend(session.get(), kBodyDataSize); 3437 3438 data.RunFor(1); 3439 EXPECT_EQ(NULL, stream3.get()); 3440 3441 EXPECT_FALSE(stream2->send_stalled_by_flow_control()); 3442 EXPECT_FALSE(session->IsStreamActive(stream_id1)); 3443 EXPECT_TRUE(session->IsStreamActive(stream_id2)); 3444 EXPECT_FALSE(session->IsStreamActive(stream_id3)); 3445 3446 data.RunFor(2); 3447 EXPECT_EQ(NULL, stream2.get()); 3448 3449 EXPECT_EQ(ERR_CONNECTION_CLOSED, delegate1.WaitForClose()); 3450 EXPECT_EQ(ERR_CONNECTION_CLOSED, delegate2.WaitForClose()); 3451 EXPECT_EQ(OK, delegate3.WaitForClose()); 3452 3453 EXPECT_TRUE(delegate1.send_headers_completed()); 3454 EXPECT_EQ(std::string(), delegate1.TakeReceivedData()); 3455 3456 EXPECT_TRUE(delegate2.send_headers_completed()); 3457 EXPECT_EQ("200", delegate2.GetResponseHeaderValue(":status")); 3458 EXPECT_EQ("HTTP/1.1", delegate2.GetResponseHeaderValue(":version")); 3459 EXPECT_EQ(std::string(), delegate2.TakeReceivedData()); 3460 3461 EXPECT_TRUE(delegate3.send_headers_completed()); 3462 EXPECT_EQ(std::string(), delegate3.TakeReceivedData()); 3463 3464 EXPECT_TRUE(data.at_write_eof()); 3465} 3466 3467// Cause a stall by reducing the flow control send window to 3468// 0. Unstalling the session should properly handle the session itself 3469// being closed. 3470TEST_P(SpdySessionTest, SendWindowSizeIncreaseWithDeletedSession) { 3471 if (GetParam() < kProtoSPDY31) 3472 return; 3473 3474 const char kStreamUrl[] = "http://www.google.com/"; 3475 GURL url(kStreamUrl); 3476 3477 session_deps_.host_resolver->set_synchronous_mode(true); 3478 3479 scoped_ptr<SpdyFrame> req1( 3480 spdy_util_.ConstructSpdyPost( 3481 kStreamUrl, 1, kBodyDataSize, LOWEST, NULL, 0)); 3482 scoped_ptr<SpdyFrame> req2( 3483 spdy_util_.ConstructSpdyPost( 3484 kStreamUrl, 3, kBodyDataSize, LOWEST, NULL, 0)); 3485 scoped_ptr<SpdyFrame> body1( 3486 spdy_util_.ConstructSpdyBodyFrame(1, kBodyData, kBodyDataSize, false)); 3487 MockWrite writes[] = { 3488 CreateMockWrite(*req1, 0), 3489 CreateMockWrite(*req2, 1), 3490 }; 3491 3492 MockRead reads[] = { 3493 MockRead(ASYNC, 0, 0, 2), // EOF 3494 }; 3495 3496 DeterministicSocketData data(reads, arraysize(reads), 3497 writes, arraysize(writes)); 3498 MockConnect connect_data(SYNCHRONOUS, OK); 3499 data.set_connect_data(connect_data); 3500 3501 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data); 3502 3503 CreateDeterministicNetworkSession(); 3504 scoped_refptr<SpdySession> session = 3505 CreateInsecureSpdySession(http_session_, key_, BoundNetLog()); 3506 EXPECT_EQ(SpdySession::FLOW_CONTROL_STREAM_AND_SESSION, 3507 session->flow_control_state()); 3508 3509 base::WeakPtr<SpdyStream> stream1 = 3510 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM, 3511 session, url, LOWEST, BoundNetLog()); 3512 ASSERT_TRUE(stream1.get() != NULL); 3513 3514 test::StreamDelegateWithBody delegate1(stream1, kBodyDataStringPiece); 3515 stream1->SetDelegate(&delegate1); 3516 3517 EXPECT_FALSE(stream1->HasUrl()); 3518 3519 base::WeakPtr<SpdyStream> stream2 = 3520 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM, 3521 session, url, LOWEST, BoundNetLog()); 3522 ASSERT_TRUE(stream2.get() != NULL); 3523 3524 test::StreamDelegateWithBody delegate2(stream2, kBodyDataStringPiece); 3525 stream2->SetDelegate(&delegate2); 3526 3527 EXPECT_FALSE(stream2->HasUrl()); 3528 3529 EXPECT_FALSE(stream1->send_stalled_by_flow_control()); 3530 EXPECT_FALSE(stream2->send_stalled_by_flow_control()); 3531 3532 StallSessionSend(session.get()); 3533 3534 scoped_ptr<SpdyHeaderBlock> headers1( 3535 spdy_util_.ConstructPostHeaderBlock(kStreamUrl, kBodyDataSize)); 3536 EXPECT_EQ(ERR_IO_PENDING, 3537 stream1->SendRequestHeaders(headers1.Pass(), MORE_DATA_TO_SEND)); 3538 EXPECT_TRUE(stream1->HasUrl()); 3539 EXPECT_EQ(kStreamUrl, stream1->GetUrl().spec()); 3540 3541 data.RunFor(1); 3542 EXPECT_EQ(1u, stream1->stream_id()); 3543 EXPECT_TRUE(stream1->send_stalled_by_flow_control()); 3544 3545 scoped_ptr<SpdyHeaderBlock> headers2( 3546 spdy_util_.ConstructPostHeaderBlock(kStreamUrl, kBodyDataSize)); 3547 EXPECT_EQ(ERR_IO_PENDING, 3548 stream2->SendRequestHeaders(headers2.Pass(), MORE_DATA_TO_SEND)); 3549 EXPECT_TRUE(stream2->HasUrl()); 3550 EXPECT_EQ(kStreamUrl, stream2->GetUrl().spec()); 3551 3552 data.RunFor(1); 3553 EXPECT_EQ(3u, stream2->stream_id()); 3554 EXPECT_TRUE(stream2->send_stalled_by_flow_control()); 3555 3556 EXPECT_TRUE(HasSpdySession(spdy_session_pool_, key_)); 3557 3558 // Unstall stream1. 3559 UnstallSessionSend(session.get(), kBodyDataSize); 3560 3561 // Close the session (since we can't do it from within the delegate 3562 // method, since it's in the stream's loop). 3563 session->CloseSessionOnError(ERR_CONNECTION_CLOSED, "Closing session"); 3564 session = NULL; 3565 3566 EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_)); 3567 3568 EXPECT_EQ(ERR_CONNECTION_CLOSED, delegate1.WaitForClose()); 3569 EXPECT_EQ(ERR_CONNECTION_CLOSED, delegate2.WaitForClose()); 3570 3571 EXPECT_TRUE(delegate1.send_headers_completed()); 3572 EXPECT_EQ(std::string(), delegate1.TakeReceivedData()); 3573 3574 EXPECT_TRUE(delegate2.send_headers_completed()); 3575 EXPECT_EQ(std::string(), delegate2.TakeReceivedData()); 3576 3577 EXPECT_TRUE(data.at_write_eof()); 3578} 3579 3580} // namespace net 3581