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