| Index: net/quic/chromium/quic_chromium_client_stream_test.cc
|
| diff --git a/net/quic/chromium/quic_chromium_client_stream_test.cc b/net/quic/chromium/quic_chromium_client_stream_test.cc
|
| index 30587d05b42d2c82096f5a32ebc596153f8ce9f0..41e0ca5e535016f62910e950d781efdba22c24f5 100644
|
| --- a/net/quic/chromium/quic_chromium_client_stream_test.cc
|
| +++ b/net/quic/chromium/quic_chromium_client_stream_test.cc
|
| @@ -365,6 +365,17 @@ TEST_P(QuicChromiumClientStreamTest, OnTrailers) {
|
| .WillOnce(testing::InvokeWithoutArgs([&run_loop]() { run_loop.Quit(); }));
|
|
|
| run_loop.Run();
|
| +
|
| + // OnDataAvailable callback should follow trailers notification.
|
| + base::RunLoop run_loop3;
|
| + EXPECT_CALL(delegate_, OnDataAvailable())
|
| + .Times(1)
|
| + .WillOnce(testing::DoAll(
|
| + testing::Invoke(CreateFunctor(&QuicChromiumClientStreamTest::ReadData,
|
| + base::Unretained(this), StringPiece())),
|
| + testing::InvokeWithoutArgs([&run_loop3]() { run_loop3.Quit(); })));
|
| + run_loop3.Run();
|
| +
|
| // Make sure kFinalOffsetHeaderKey is gone from the delivered actual trailers.
|
| trailers.erase(kFinalOffsetHeaderKey);
|
| EXPECT_EQ(trailers, delegate_.headers_);
|
| @@ -425,6 +436,16 @@ TEST_P(QuicChromiumClientStreamTest, MarkTrailersConsumedWhenNotifyDelegate) {
|
|
|
| run_loop2.Run();
|
|
|
| + // OnDataAvailable callback should follow trailers notification.
|
| + base::RunLoop run_loop3;
|
| + EXPECT_CALL(delegate_, OnDataAvailable())
|
| + .Times(1)
|
| + .WillOnce(testing::DoAll(
|
| + testing::Invoke(CreateFunctor(&QuicChromiumClientStreamTest::ReadData,
|
| + base::Unretained(this), StringPiece())),
|
| + testing::InvokeWithoutArgs([&run_loop3]() { run_loop3.Quit(); })));
|
| + run_loop3.Run();
|
| +
|
| // Make sure the stream is properly closed since trailers and data are all
|
| // consumed.
|
| EXPECT_TRUE(stream_->IsDoneReading());
|
| @@ -436,6 +457,84 @@ TEST_P(QuicChromiumClientStreamTest, MarkTrailersConsumedWhenNotifyDelegate) {
|
| EXPECT_CALL(delegate_, OnClose());
|
| }
|
|
|
| +// Test that if Read() is called after response body is read and after trailers
|
| +// are received but not yet delivered, Read() will return ERR_IO_PENDING instead
|
| +// of 0 (EOF).
|
| +TEST_P(QuicChromiumClientStreamTest, ReadAfterTrailersReceivedButNotDelivered) {
|
| + InitializeHeaders();
|
| + std::string uncompressed_headers =
|
| + SpdyUtils::SerializeUncompressedHeaders(headers_);
|
| + stream_->OnStreamHeaders(uncompressed_headers);
|
| + stream_->OnStreamHeadersComplete(false, uncompressed_headers.length());
|
| +
|
| + EXPECT_CALL(delegate_,
|
| + OnHeadersAvailableMock(_, uncompressed_headers.length()));
|
| + base::RunLoop().RunUntilIdle();
|
| + EXPECT_EQ(headers_, delegate_.headers_);
|
| + EXPECT_TRUE(stream_->decompressed_headers().empty());
|
| +
|
| + const char data[] = "hello world!";
|
| + stream_->OnStreamFrame(QuicStreamFrame(kTestStreamId, /*fin=*/false,
|
| + /*offset=*/0, data));
|
| +
|
| + base::RunLoop run_loop;
|
| + EXPECT_CALL(delegate_, OnDataAvailable())
|
| + .Times(1)
|
| + .WillOnce(testing::DoAll(
|
| + testing::Invoke(CreateFunctor(
|
| + &QuicChromiumClientStreamTest::ReadData, base::Unretained(this),
|
| + StringPiece(data, arraysize(data) - 1))),
|
| + testing::Invoke([&run_loop]() { run_loop.Quit(); })));
|
| +
|
| + // Wait for the read to complete.
|
| + run_loop.Run();
|
| +
|
| + // Deliver trailers. Delegate notification is posted asynchronously.
|
| + SpdyHeaderBlock trailers;
|
| + trailers["bar"] = "foo";
|
| + trailers[kFinalOffsetHeaderKey] = base::IntToString(strlen(data));
|
| + std::string uncompressed_trailers =
|
| + SpdyUtils::SerializeUncompressedHeaders(trailers);
|
| +
|
| + stream_->OnStreamHeaders(uncompressed_trailers);
|
| + stream_->OnStreamHeadersComplete(true, uncompressed_trailers.length());
|
| +
|
| + // Read again, it return ERR_IO_PENDING.
|
| + scoped_refptr<IOBuffer> buffer(new IOBuffer(1));
|
| + EXPECT_THAT(stream_->Read(buffer.get(), 1), ERR_IO_PENDING);
|
| +
|
| + // Trailers are not delivered
|
| + EXPECT_FALSE(stream_->IsDoneReading());
|
| +
|
| + base::RunLoop run_loop2;
|
| + EXPECT_CALL(delegate_,
|
| + OnHeadersAvailableMock(_, uncompressed_trailers.length()))
|
| + .WillOnce(
|
| + testing::InvokeWithoutArgs([&run_loop2]() { run_loop2.Quit(); }));
|
| +
|
| + run_loop2.Run();
|
| +
|
| + base::RunLoop run_loop3;
|
| + // OnDataAvailable() should follow right after and Read() will return 0.
|
| + EXPECT_CALL(delegate_, OnDataAvailable())
|
| + .WillOnce(testing::DoAll(
|
| + testing::Invoke(CreateFunctor(&QuicChromiumClientStreamTest::ReadData,
|
| + base::Unretained(this), StringPiece())),
|
| + testing::Invoke([&run_loop3]() { run_loop3.Quit(); })));
|
| + run_loop3.Run();
|
| +
|
| + // Make sure the stream is properly closed since trailers and data are all
|
| + // consumed.
|
| + EXPECT_TRUE(stream_->IsDoneReading());
|
| +
|
| + // Make sure kFinalOffsetHeaderKey is gone from the delivered actual trailers.
|
| + trailers.erase(kFinalOffsetHeaderKey);
|
| + EXPECT_EQ(trailers, delegate_.headers_);
|
| +
|
| + base::RunLoop().RunUntilIdle();
|
| + EXPECT_CALL(delegate_, OnClose());
|
| +}
|
| +
|
| TEST_P(QuicChromiumClientStreamTest, WriteStreamData) {
|
| EXPECT_CALL(delegate_, OnClose());
|
|
|
|
|