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