Chromium Code Reviews| Index: net/spdy/bidirectional_stream_spdy_impl_unittest.cc |
| diff --git a/net/spdy/bidirectional_stream_spdy_impl_unittest.cc b/net/spdy/bidirectional_stream_spdy_impl_unittest.cc |
| index bee61f0a6f61274370fe9ec218a9fdcd53232d72..086c1eae63a2ca211b8193ab457ced42dde0d641 100644 |
| --- a/net/spdy/bidirectional_stream_spdy_impl_unittest.cc |
| +++ b/net/spdy/bidirectional_stream_spdy_impl_unittest.cc |
| @@ -432,4 +432,70 @@ TEST_F(BidirectionalStreamSpdyImplTest, SendDataAfterStreamFailed) { |
| delegate->GetTotalReceivedBytes()); |
| } |
| +// Tests that when received RST_STREAM with NO_ERROR, BidirectionalStream does |
| +// not crash when processing pending writes. See crbug.com/650438. |
| +TEST_F(BidirectionalStreamSpdyImplTest, RstWithNoErrorBeforeSendIsComplete) { |
|
kapishnikov
2016/10/31 17:21:47
We need a similar test for SendvData
xunjieli
2016/10/31 18:42:19
Done.
|
| + SpdySerializedFrame req(spdy_util_.ConstructSpdyPost( |
| + kDefaultUrl, 1, kBodyDataSize * 3, LOW, nullptr, 0)); |
| + MockWrite writes[] = {CreateMockWrite(req, 0)}; |
| + |
| + SpdySerializedFrame resp(spdy_util_.ConstructSpdyPostReply(nullptr, 0)); |
| + SpdySerializedFrame rst( |
| + spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_NO_ERROR)); |
| + MockRead reads[] = {CreateMockRead(resp, 1), |
| + MockRead(ASYNC, ERR_IO_PENDING, 2), // Force a pause. |
| + CreateMockRead(rst, 3), MockRead(ASYNC, 0, 4)}; |
| + |
| + InitSession(reads, arraysize(reads), writes, arraysize(writes)); |
| + |
| + BidirectionalStreamRequestInfo request_info; |
| + request_info.method = "POST"; |
| + request_info.url = default_url_; |
| + request_info.extra_headers.SetHeader(net::HttpRequestHeaders::kContentLength, |
| + base::SizeTToString(kBodyDataSize * 3)); |
| + |
| + scoped_refptr<IOBuffer> read_buffer(new IOBuffer(kReadBufferSize)); |
| + std::unique_ptr<TestDelegateBase> delegate( |
| + new TestDelegateBase(session_, read_buffer.get(), kReadBufferSize)); |
| + delegate->SetRunUntilCompletion(true); |
| + delegate->Start(&request_info, net_log_.bound()); |
| + sequenced_data_->RunUntilPaused(); |
| + // Make a write pending before receiving RST_STREAM. |
| + scoped_refptr<StringIOBuffer> write_buffer( |
| + new StringIOBuffer(std::string(kBodyData, kBodyDataSize))); |
| + delegate->SendData(write_buffer.get(), write_buffer->size(), false); |
| + sequenced_data_->Resume(); |
| + base::RunLoop().RunUntilIdle(); |
| + |
| + // Make sure OnClose() without an error completes any pending write(). |
| + EXPECT_EQ(1, delegate->on_data_sent_count()); |
| + EXPECT_FALSE(delegate->on_failed_called()); |
| + |
| + for (size_t i = 0; i < 3; i++) { |
| + delegate->SendData(write_buffer.get(), write_buffer->size(), i == 2); |
| + base::RunLoop().RunUntilIdle(); |
| + } |
| + delegate->WaitUntilCompletion(); |
| + LoadTimingInfo load_timing_info; |
| + EXPECT_TRUE(delegate->GetLoadTimingInfo(&load_timing_info)); |
| + TestLoadTimingNotReused(load_timing_info); |
| + |
| + EXPECT_THAT(delegate->error(), IsError(OK)); |
| + EXPECT_EQ(1, delegate->on_data_read_count()); |
| + EXPECT_EQ(4, delegate->on_data_sent_count()); |
| + EXPECT_EQ(kProtoHTTP2, delegate->GetProtocol()); |
| + EXPECT_EQ(CountWriteBytes(writes, 1), delegate->GetTotalSentBytes()); |
| + // Should not count RST stream. |
| + EXPECT_EQ(CountReadBytes(reads, arraysize(reads) - 2), |
| + delegate->GetTotalReceivedBytes()); |
| + |
| + // Now call SendData again should produce an error because end of stream flag |
| + // has been written. |
| + delegate->SendData(write_buffer.get(), write_buffer->size(), true); |
| + base::RunLoop().RunUntilIdle(); |
| + EXPECT_THAT(delegate->error(), IsError(ERR_UNEXPECTED)); |
| + EXPECT_TRUE(delegate->on_failed_called()); |
| + EXPECT_EQ(4, delegate->on_data_sent_count()); |
| +} |
| + |
| } // namespace net |