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