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