| Index: net/spdy/spdy_session_unittest.cc
|
| diff --git a/net/spdy/spdy_session_unittest.cc b/net/spdy/spdy_session_unittest.cc
|
| index 95c8fd98b74427d79720f7554d868cb6e0e6e9a4..dda8d949b23068c723ed83602d70fae1c51c6324 100644
|
| --- a/net/spdy/spdy_session_unittest.cc
|
| +++ b/net/spdy/spdy_session_unittest.cc
|
| @@ -1132,6 +1132,112 @@ TEST_P(SpdySessionTest, StreamIdSpaceExhausted) {
|
| EXPECT_FALSE(session_);
|
| }
|
|
|
| +// Regression test for https://crbug.com/481009.
|
| +TEST_P(SpdySessionTest, MaxConcurrentStreamsZero) {
|
| + session_deps_.host_resolver->set_synchronous_mode(true);
|
| +
|
| + int seq = 0;
|
| + std::vector<MockRead> reads;
|
| +
|
| + // Receive SETTINGS frame that sets max_concurrent_streams to zero.
|
| + SettingsMap settings_zero;
|
| + settings_zero[SETTINGS_MAX_CONCURRENT_STREAMS] =
|
| + SettingsFlagsAndValue(SETTINGS_FLAG_NONE, 0);
|
| + scoped_ptr<SpdyFrame> settings_frame_zero(
|
| + spdy_util_.ConstructSpdySettings(settings_zero));
|
| + reads.push_back(CreateMockRead(*settings_frame_zero, seq++));
|
| +
|
| + // Acknowledge it.
|
| + std::vector<MockWrite> writes;
|
| + scoped_ptr<SpdyFrame> settings_ack0;
|
| + if (GetProtocol() == kProtoHTTP2) {
|
| + settings_ack0.reset(spdy_util_.ConstructSpdySettingsAck());
|
| + writes.push_back(CreateMockWrite(*settings_ack0, seq++));
|
| + }
|
| +
|
| + // Pause.
|
| + reads.push_back(MockRead(ASYNC, ERR_IO_PENDING, seq++));
|
| +
|
| + // Receive SETTINGS frame that sets max_concurrent_streams to one.
|
| + SettingsMap settings_one;
|
| + settings_one[SETTINGS_MAX_CONCURRENT_STREAMS] =
|
| + SettingsFlagsAndValue(SETTINGS_FLAG_NONE, 1);
|
| + scoped_ptr<SpdyFrame> settings_frame_one(
|
| + spdy_util_.ConstructSpdySettings(settings_one));
|
| + reads.push_back(CreateMockRead(*settings_frame_one, seq++));
|
| +
|
| + // Acknowledge it.
|
| + scoped_ptr<SpdyFrame> settings_ack1;
|
| + if (GetProtocol() == kProtoHTTP2) {
|
| + settings_ack1.reset(spdy_util_.ConstructSpdySettingsAck());
|
| + writes.push_back(CreateMockWrite(*settings_ack1, seq++));
|
| + }
|
| +
|
| + // Request and response.
|
| + scoped_ptr<SpdyFrame> req(
|
| + spdy_util_.ConstructSpdyGet(nullptr, 0, false, 1, MEDIUM, true));
|
| + writes.push_back(CreateMockWrite(*req, seq++));
|
| +
|
| + scoped_ptr<SpdyFrame> resp(
|
| + spdy_util_.ConstructSpdyGetSynReply(nullptr, 0, 1));
|
| + reads.push_back(CreateMockRead(*resp, seq++));
|
| +
|
| + scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
|
| + reads.push_back(CreateMockRead(*body, seq++));
|
| +
|
| + reads.push_back(MockRead(ASYNC, 0, seq++));
|
| +
|
| + SequencedSocketData data(reads.data(), reads.size(), writes.data(),
|
| + writes.size());
|
| + session_deps_.socket_factory->AddSocketDataProvider(&data);
|
| +
|
| + // Create session.
|
| + CreateNetworkSession();
|
| + CreateInsecureSpdySession();
|
| +
|
| + // Receive SETTINGS frame that sets max_concurrent_streams to zero.
|
| + base::RunLoop().RunUntilIdle();
|
| + EXPECT_EQ(0u, session_->max_concurrent_streams_);
|
| +
|
| + // Start request.
|
| + SpdyStreamRequest request;
|
| + TestCompletionCallback callback;
|
| + int rv =
|
| + request.StartRequest(SPDY_REQUEST_RESPONSE_STREAM, session_, test_url_,
|
| + MEDIUM, BoundNetLog(), callback.callback());
|
| + EXPECT_EQ(ERR_IO_PENDING, rv);
|
| +
|
| + // Stream is stalled.
|
| + EXPECT_EQ(1u, session_->pending_create_stream_queue_size(MEDIUM));
|
| + EXPECT_EQ(0u, session_->num_created_streams());
|
| +
|
| + // Receive SETTINGS frame that sets max_concurrent_streams to one.
|
| + data.Resume();
|
| + base::RunLoop().RunUntilIdle();
|
| + EXPECT_EQ(1u, session_->max_concurrent_streams_);
|
| +
|
| + // Stream is created.
|
| + EXPECT_EQ(0u, session_->pending_create_stream_queue_size(MEDIUM));
|
| + EXPECT_EQ(1u, session_->num_created_streams());
|
| +
|
| + EXPECT_EQ(OK, callback.WaitForResult());
|
| +
|
| + // Send request.
|
| + base::WeakPtr<SpdyStream> stream = request.ReleaseStream();
|
| + test::StreamDelegateDoNothing delegate(stream);
|
| + stream->SetDelegate(&delegate);
|
| + scoped_ptr<SpdyHeaderBlock> headers(
|
| + spdy_util_.ConstructGetHeaderBlock(kDefaultURL));
|
| + stream->SendRequestHeaders(std::move(headers), NO_MORE_DATA_TO_SEND);
|
| + EXPECT_TRUE(stream->HasUrlFromHeaders());
|
| +
|
| + EXPECT_EQ(OK, delegate.WaitForClose());
|
| + EXPECT_EQ("hello!", delegate.TakeReceivedData());
|
| +
|
| + // Session is destroyed.
|
| + EXPECT_FALSE(session_);
|
| +}
|
| +
|
| // Verifies that an unstalled pending stream creation racing with a new stream
|
| // creation doesn't violate the maximum stream concurrency. Regression test for
|
| // crbug.com/373858.
|
| @@ -1459,7 +1565,7 @@ TEST_P(SpdySessionTest, ClearSettings) {
|
|
|
| // Make sure session's max_concurrent_streams is correct.
|
| EXPECT_EQ(kInitialMaxConcurrentStreams + 1,
|
| - session_->max_concurrent_streams());
|
| + session_->max_concurrent_streams_);
|
|
|
| data.Resume();
|
| base::RunLoop().RunUntilIdle();
|
|
|