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