| Index: net/quic/bidirectional_stream_quic_impl_unittest.cc
|
| diff --git a/net/quic/bidirectional_stream_quic_impl_unittest.cc b/net/quic/bidirectional_stream_quic_impl_unittest.cc
|
| index 3afdb479a7ce672047e82b43de48376412a553af..cd237885a4ac08f4e6eec95c88fd86a88a2c1103 100644
|
| --- a/net/quic/bidirectional_stream_quic_impl_unittest.cc
|
| +++ b/net/quic/bidirectional_stream_quic_impl_unittest.cc
|
| @@ -71,13 +71,14 @@ class TestDelegateBase : public BidirectionalStreamImpl::Delegate {
|
| error_(OK),
|
| on_data_read_count_(0),
|
| on_data_sent_count_(0),
|
| - not_expect_callback_(false) {
|
| + not_expect_callback_(false),
|
| + disable_auto_flush_(false) {
|
| loop_.reset(new base::RunLoop);
|
| }
|
|
|
| ~TestDelegateBase() override {}
|
|
|
| - void OnHeadersSent() override {
|
| + void OnStreamReady() override {
|
| CHECK(!not_expect_callback_);
|
| loop_->Quit();
|
| }
|
| @@ -126,7 +127,8 @@ class TestDelegateBase : public BidirectionalStreamImpl::Delegate {
|
| const BoundNetLog& net_log,
|
| const base::WeakPtr<QuicChromiumClientSession> session) {
|
| stream_job_.reset(new BidirectionalStreamQuicImpl(session));
|
| - stream_job_->Start(request_info, net_log, this, nullptr);
|
| + stream_job_->Start(request_info, net_log, disable_auto_flush_, this,
|
| + nullptr);
|
| }
|
|
|
| void SendData(IOBuffer* data, int length, bool end_of_stream) {
|
| @@ -135,6 +137,14 @@ class TestDelegateBase : public BidirectionalStreamImpl::Delegate {
|
| not_expect_callback_ = false;
|
| }
|
|
|
| + void SendvData(const std::vector<IOBuffer*>& data,
|
| + const std::vector<int>& lengths,
|
| + bool end_of_stream) {
|
| + not_expect_callback_ = true;
|
| + stream_job_->SendvData(data, lengths, end_of_stream);
|
| + not_expect_callback_ = false;
|
| + }
|
| +
|
| // Waits until next Delegate callback.
|
| void WaitUntilNextCallback() {
|
| loop_->Run();
|
| @@ -164,6 +174,8 @@ class TestDelegateBase : public BidirectionalStreamImpl::Delegate {
|
|
|
| int64_t GetTotalSentBytes() const { return stream_job_->GetTotalSentBytes(); }
|
|
|
| + void DisableAutoFlush() { disable_auto_flush_ = true; }
|
| +
|
| // Const getters for internal states.
|
| const std::string& data_received() const { return data_received_; }
|
| int error() const { return error_; }
|
| @@ -195,6 +207,7 @@ class TestDelegateBase : public BidirectionalStreamImpl::Delegate {
|
| // calling into |stream_|.
|
| bool not_expect_callback_;
|
| CompletionCallback callback_;
|
| + bool disable_auto_flush_;
|
|
|
| DISALLOW_COPY_AND_ASSIGN(TestDelegateBase);
|
| };
|
| @@ -373,6 +386,20 @@ class BidirectionalStreamQuicImplTest
|
| << QuicUtils::StringToHexASCIIDump(packet->AsStringPiece());
|
| return packet;
|
| }
|
| + // Construct a data packet with multiple data frames
|
| + scoped_ptr<QuicReceivedPacket> ConstructMultipleDataFramesPacket(
|
| + QuicPacketNumber packet_number,
|
| + bool should_include_version,
|
| + bool fin,
|
| + QuicStreamOffset offset,
|
| + const std::vector<std::string>& data_writes) {
|
| + scoped_ptr<QuicReceivedPacket> packet(maker_.MakeMultipleDataFramesPacket(
|
| + packet_number, stream_id_, should_include_version, fin, offset,
|
| + data_writes));
|
| + DVLOG(2) << "packet(" << packet_number << "): " << std::endl
|
| + << QuicUtils::StringToHexASCIIDump(packet->AsStringPiece());
|
| + return packet;
|
| + }
|
|
|
| scoped_ptr<QuicReceivedPacket> ConstructRequestHeadersPacket(
|
| QuicPacketNumber packet_number,
|
| @@ -386,6 +413,24 @@ class BidirectionalStreamQuicImplTest
|
| request_headers_, spdy_headers_frame_length);
|
| }
|
|
|
| + scoped_ptr<QuicReceivedPacket>
|
| + ConstructRequestHeadersAndMultipleDataFramesPacket(
|
| + QuicPacketNumber packet_number,
|
| + bool fin,
|
| + RequestPriority request_priority,
|
| + size_t* spdy_headers_frame_length,
|
| + const std::vector<std::string>& data) {
|
| + SpdyPriority priority =
|
| + ConvertRequestPriorityToQuicPriority(request_priority);
|
| + scoped_ptr<QuicReceivedPacket> packet(
|
| + maker_.MakeRequestHeadersAndMultipleDataFramesPacket(
|
| + packet_number, stream_id_, kIncludeVersion, fin, priority,
|
| + request_headers_, spdy_headers_frame_length, data));
|
| + DVLOG(2) << "packet(" << packet_number << "): " << std::endl
|
| + << QuicUtils::StringToHexASCIIDump(packet->AsStringPiece());
|
| + return packet;
|
| + }
|
| +
|
| scoped_ptr<QuicReceivedPacket> ConstructResponseHeadersPacket(
|
| QuicPacketNumber packet_number,
|
| bool fin,
|
| @@ -512,7 +557,7 @@ TEST_P(BidirectionalStreamQuicImplTest, GetRequest) {
|
| scoped_ptr<TestDelegateBase> delegate(
|
| new TestDelegateBase(read_buffer.get(), kReadBufferSize));
|
| delegate->Start(&request, net_log().bound(), session()->GetWeakPtr());
|
| - delegate->WaitUntilNextCallback(); // OnHeadersSent
|
| + delegate->WaitUntilNextCallback(); // OnStreamReady
|
|
|
| // Server acks the request.
|
| ProcessPacket(ConstructAckPacket(1, 0, 0));
|
| @@ -583,6 +628,108 @@ TEST_P(BidirectionalStreamQuicImplTest, GetRequest) {
|
| NetLog::PHASE_NONE);
|
| }
|
|
|
| +TEST_P(BidirectionalStreamQuicImplTest, CoalesceSmallBuffers) {
|
| + SetRequest("POST", "/", DEFAULT_PRIORITY);
|
| + size_t spdy_request_headers_frame_length;
|
| +
|
| + const char kBody1[] = "here are some data";
|
| + const char kBody2[] = "data keep coming";
|
| + std::vector<std::string> two_writes = {kBody1, kBody2};
|
| + AddWrite(ConstructRequestHeadersAndMultipleDataFramesPacket(
|
| + 1, !kFin, DEFAULT_PRIORITY, &spdy_request_headers_frame_length,
|
| + two_writes));
|
| + // Ack server's data packet.
|
| + AddWrite(ConstructAckPacket(2, 3, 1));
|
| + const char kBody3[] = "hello there";
|
| + const char kBody4[] = "another piece of small data";
|
| + const char kBody5[] = "really small";
|
| + QuicStreamOffset data_offset = strlen(kBody1) + strlen(kBody2);
|
| + AddWrite(ConstructMultipleDataFramesPacket(
|
| + 3, !kIncludeVersion, kFin, data_offset, {kBody3, kBody4, kBody5}));
|
| +
|
| + Initialize();
|
| +
|
| + BidirectionalStreamRequestInfo request;
|
| + request.method = "POST";
|
| + request.url = GURL("http://www.google.com/");
|
| + request.end_stream_on_headers = false;
|
| + request.priority = DEFAULT_PRIORITY;
|
| +
|
| + scoped_refptr<IOBuffer> read_buffer(new IOBuffer(kReadBufferSize));
|
| + scoped_ptr<TestDelegateBase> delegate(
|
| + new TestDelegateBase(read_buffer.get(), kReadBufferSize));
|
| + delegate->DisableAutoFlush();
|
| + delegate->Start(&request, net_log().bound(), session()->GetWeakPtr());
|
| + delegate->WaitUntilNextCallback(); // OnStreamReady
|
| +
|
| + // Send a Data packet.
|
| + scoped_refptr<StringIOBuffer> buf1(new StringIOBuffer(kBody1));
|
| + scoped_refptr<StringIOBuffer> buf2(new StringIOBuffer(kBody2));
|
| +
|
| + std::vector<IOBuffer*> buffers = {buf1.get(), buf2.get()};
|
| + std::vector<int> lengths = {buf1->size(), buf2->size()};
|
| + delegate->SendvData(buffers, lengths, !kFin);
|
| + delegate->WaitUntilNextCallback(); // OnDataSent
|
| +
|
| + // Server acks the request.
|
| + ProcessPacket(ConstructAckPacket(1, 0, 0));
|
| +
|
| + // Server sends the response headers.
|
| + SpdyHeaderBlock response_headers = ConstructResponseHeaders("200");
|
| + size_t spdy_response_headers_frame_length;
|
| + QuicStreamOffset offset = 0;
|
| + ProcessPacket(ConstructResponseHeadersPacket(
|
| + 2, !kFin, response_headers, &spdy_response_headers_frame_length,
|
| + &offset));
|
| +
|
| + delegate->WaitUntilNextCallback(); // OnHeadersReceived
|
| + TestCompletionCallback cb;
|
| + int rv = delegate->ReadData(cb.callback());
|
| + EXPECT_EQ(ERR_IO_PENDING, rv);
|
| + EXPECT_EQ("200", delegate->response_headers().find(":status")->second);
|
| + const char kResponseBody[] = "Hello world!";
|
| + // Server sends data.
|
| + ProcessPacket(
|
| + ConstructDataPacket(3, !kIncludeVersion, !kFin, 0, kResponseBody));
|
| +
|
| + EXPECT_EQ(static_cast<int>(strlen(kResponseBody)), cb.WaitForResult());
|
| +
|
| + // Send a second Data packet.
|
| + scoped_refptr<StringIOBuffer> buf3(new StringIOBuffer(kBody3));
|
| + scoped_refptr<StringIOBuffer> buf4(new StringIOBuffer(kBody4));
|
| + scoped_refptr<StringIOBuffer> buf5(new StringIOBuffer(kBody5));
|
| +
|
| + delegate->SendvData({buf3.get(), buf4.get(), buf5.get()},
|
| + {buf3->size(), buf4->size(), buf5->size()}, kFin);
|
| + delegate->WaitUntilNextCallback(); // OnDataSent
|
| +
|
| + size_t spdy_trailers_frame_length;
|
| + SpdyHeaderBlock trailers;
|
| + trailers["foo"] = "bar";
|
| + trailers[kFinalOffsetHeaderKey] = base::IntToString(strlen(kResponseBody));
|
| + // Server sends trailers.
|
| + ProcessPacket(ConstructResponseTrailersPacket(
|
| + 4, kFin, trailers, &spdy_trailers_frame_length, &offset));
|
| +
|
| + delegate->WaitUntilNextCallback(); // OnTrailersReceived
|
| + trailers.erase(kFinalOffsetHeaderKey);
|
| + EXPECT_EQ(trailers, delegate->trailers());
|
| + EXPECT_EQ(OK, delegate->ReadData(cb.callback()));
|
| +
|
| + EXPECT_EQ(1, delegate->on_data_read_count());
|
| + EXPECT_EQ(2, delegate->on_data_sent_count());
|
| + EXPECT_EQ(kProtoQUIC1SPDY3, delegate->GetProtocol());
|
| + EXPECT_EQ(
|
| + static_cast<int64_t>(spdy_request_headers_frame_length + strlen(kBody1) +
|
| + strlen(kBody2) + strlen(kBody3) + strlen(kBody4) +
|
| + strlen(kBody5)),
|
| + delegate->GetTotalSentBytes());
|
| + EXPECT_EQ(
|
| + static_cast<int64_t>(spdy_response_headers_frame_length +
|
| + strlen(kResponseBody) + spdy_trailers_frame_length),
|
| + delegate->GetTotalReceivedBytes());
|
| +}
|
| +
|
| TEST_P(BidirectionalStreamQuicImplTest, PostRequest) {
|
| SetRequest("POST", "/", DEFAULT_PRIORITY);
|
| size_t spdy_request_headers_frame_length;
|
| @@ -603,7 +750,7 @@ TEST_P(BidirectionalStreamQuicImplTest, PostRequest) {
|
| scoped_ptr<TestDelegateBase> delegate(
|
| new TestDelegateBase(read_buffer.get(), kReadBufferSize));
|
| delegate->Start(&request, net_log().bound(), session()->GetWeakPtr());
|
| - delegate->WaitUntilNextCallback(); // OnHeadersSent
|
| + delegate->WaitUntilNextCallback(); // OnStreamReady
|
|
|
| // Send a DATA frame.
|
| scoped_refptr<StringIOBuffer> buf(new StringIOBuffer(kUploadData));
|
| @@ -680,7 +827,7 @@ TEST_P(BidirectionalStreamQuicImplTest, InterleaveReadDataAndSendData) {
|
| scoped_ptr<TestDelegateBase> delegate(
|
| new TestDelegateBase(read_buffer.get(), kReadBufferSize));
|
| delegate->Start(&request, net_log().bound(), session()->GetWeakPtr());
|
| - delegate->WaitUntilNextCallback(); // OnHeadersSent
|
| + delegate->WaitUntilNextCallback(); // OnStreamReady
|
|
|
| // Server acks the request.
|
| ProcessPacket(ConstructAckPacket(1, 0, 0));
|
| @@ -757,7 +904,7 @@ TEST_P(BidirectionalStreamQuicImplTest, ServerSendsRstAfterHeaders) {
|
| scoped_ptr<TestDelegateBase> delegate(
|
| new TestDelegateBase(read_buffer.get(), kReadBufferSize));
|
| delegate->Start(&request, net_log().bound(), session()->GetWeakPtr());
|
| - delegate->WaitUntilNextCallback(); // OnHeadersSent
|
| + delegate->WaitUntilNextCallback(); // OnStreamReady
|
|
|
| // Server sends a Rst.
|
| ProcessPacket(ConstructRstStreamPacket(1));
|
| @@ -796,7 +943,7 @@ TEST_P(BidirectionalStreamQuicImplTest, ServerSendsRstAfterReadData) {
|
| scoped_ptr<TestDelegateBase> delegate(
|
| new TestDelegateBase(read_buffer.get(), kReadBufferSize));
|
| delegate->Start(&request, net_log().bound(), session()->GetWeakPtr());
|
| - delegate->WaitUntilNextCallback(); // OnHeadersSent
|
| + delegate->WaitUntilNextCallback(); // OnStreamReady
|
|
|
| // Server acks the request.
|
| ProcessPacket(ConstructAckPacket(1, 0, 0));
|
| @@ -853,7 +1000,7 @@ TEST_P(BidirectionalStreamQuicImplTest, CancelStreamAfterSendData) {
|
| scoped_ptr<TestDelegateBase> delegate(
|
| new TestDelegateBase(read_buffer.get(), kReadBufferSize));
|
| delegate->Start(&request, net_log().bound(), session()->GetWeakPtr());
|
| - delegate->WaitUntilNextCallback(); // OnHeadersSent
|
| + delegate->WaitUntilNextCallback(); // OnStreamReady
|
|
|
| // Server acks the request.
|
| ProcessPacket(ConstructAckPacket(1, 0, 0));
|
| @@ -903,7 +1050,7 @@ TEST_P(BidirectionalStreamQuicImplTest, SessionClosedBeforeReadData) {
|
| scoped_ptr<TestDelegateBase> delegate(
|
| new TestDelegateBase(read_buffer.get(), kReadBufferSize));
|
| delegate->Start(&request, net_log().bound(), session()->GetWeakPtr());
|
| - delegate->WaitUntilNextCallback(); // OnHeadersSent
|
| + delegate->WaitUntilNextCallback(); // OnStreamReady
|
|
|
| // Server acks the request.
|
| ProcessPacket(ConstructAckPacket(1, 0, 0));
|
| @@ -957,7 +1104,7 @@ TEST_P(BidirectionalStreamQuicImplTest, CancelStreamAfterReadData) {
|
| scoped_ptr<TestDelegateBase> delegate(
|
| new TestDelegateBase(read_buffer.get(), kReadBufferSize));
|
| delegate->Start(&request, net_log().bound(), session()->GetWeakPtr());
|
| - delegate->WaitUntilNextCallback(); // OnHeadersSent
|
| + delegate->WaitUntilNextCallback(); // OnStreamReady
|
|
|
| // Server acks the request.
|
| ProcessPacket(ConstructAckPacket(1, 0, 0));
|
| @@ -1007,7 +1154,7 @@ TEST_P(BidirectionalStreamQuicImplTest, DeleteStreamDuringOnHeadersReceived) {
|
| read_buffer.get(), kReadBufferSize,
|
| DeleteStreamDelegate::ON_HEADERS_RECEIVED, true));
|
| delegate->Start(&request, net_log().bound(), session()->GetWeakPtr());
|
| - delegate->WaitUntilNextCallback(); // OnHeadersSent
|
| + delegate->WaitUntilNextCallback(); // OnStreamReady
|
|
|
| // Server acks the request.
|
| ProcessPacket(ConstructAckPacket(1, 0, 0));
|
| @@ -1050,7 +1197,7 @@ TEST_P(BidirectionalStreamQuicImplTest, DeleteStreamDuringOnDataRead) {
|
| new DeleteStreamDelegate(read_buffer.get(), kReadBufferSize,
|
| DeleteStreamDelegate::ON_DATA_READ, true));
|
| delegate->Start(&request, net_log().bound(), session()->GetWeakPtr());
|
| - delegate->WaitUntilNextCallback(); // OnHeadersSent
|
| + delegate->WaitUntilNextCallback(); // OnStreamReady
|
|
|
| // Server acks the request.
|
| ProcessPacket(ConstructAckPacket(1, 0, 0));
|
| @@ -1102,7 +1249,7 @@ TEST_P(BidirectionalStreamQuicImplTest, DeleteStreamDuringOnTrailersReceived) {
|
| read_buffer.get(), kReadBufferSize,
|
| DeleteStreamDelegate::ON_TRAILERS_RECEIVED, true));
|
| delegate->Start(&request, net_log().bound(), session()->GetWeakPtr());
|
| - delegate->WaitUntilNextCallback(); // OnHeadersSent
|
| + delegate->WaitUntilNextCallback(); // OnStreamReady
|
|
|
| // Server acks the request.
|
| ProcessPacket(ConstructAckPacket(1, 0, 0));
|
|
|