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.
5 #include "net/quic/quic_http_stream.h"
9 #include "base/thread_task_runner_handle.h"
10 #include "net/base/chunked_upload_data_stream.h"
11 #include "net/base/elements_upload_data_stream.h"
12 #include "net/base/net_errors.h"
13 #include "net/base/test_completion_callback.h"
14 #include "net/base/upload_bytes_element_reader.h"
15 #include "net/http/http_response_headers.h"
16 #include "net/http/transport_security_state.h"
17 #include "net/quic/congestion_control/send_algorithm_interface.h"
18 #include "net/quic/crypto/crypto_protocol.h"
19 #include "net/quic/crypto/quic_decrypter.h"
20 #include "net/quic/crypto/quic_encrypter.h"
21 #include "net/quic/crypto/quic_server_info.h"
22 #include "net/quic/quic_chromium_client_session.h"
23 #include "net/quic/quic_connection.h"
24 #include "net/quic/quic_connection_helper.h"
25 #include "net/quic/quic_default_packet_writer.h"
26 #include "net/quic/quic_flags.h"
27 #include "net/quic/quic_http_utils.h"
28 #include "net/quic/quic_reliable_client_stream.h"
29 #include "net/quic/quic_write_blocked_list.h"
30 #include "net/quic/spdy_utils.h"
31 #include "net/quic/test_tools/mock_clock.h"
32 #include "net/quic/test_tools/mock_crypto_client_stream_factory.h"
33 #include "net/quic/test_tools/mock_random.h"
34 #include "net/quic/test_tools/quic_connection_peer.h"
35 #include "net/quic/test_tools/quic_test_packet_maker.h"
36 #include "net/quic/test_tools/quic_test_utils.h"
37 #include "net/quic/test_tools/test_task_runner.h"
38 #include "net/socket/socket_test_util.h"
39 #include "net/spdy/spdy_frame_builder.h"
40 #include "net/spdy/spdy_framer.h"
41 #include "net/spdy/spdy_http_utils.h"
42 #include "net/spdy/spdy_protocol.h"
43 #include "testing/gmock/include/gmock/gmock.h"
44 #include "testing/gtest/include/gtest/gtest.h"
47 using testing::AnyNumber
;
48 using testing::Return
;
54 const char kUploadData
[] = "Really nifty data!";
55 const char kDefaultServerHostName
[] = "www.google.com";
56 const uint16 kDefaultServerPort
= 80;
58 class TestQuicConnection
: public QuicConnection
{
60 TestQuicConnection(const QuicVersionVector
& versions
,
61 QuicConnectionId connection_id
,
63 QuicConnectionHelper
* helper
,
64 const QuicConnection::PacketWriterFactory
& writer_factory
)
65 : QuicConnection(connection_id
,
69 true /* owns_writer */,
70 Perspective::IS_CLIENT
,
71 false /* is_secure */,
74 void SetSendAlgorithm(SendAlgorithmInterface
* send_algorithm
) {
75 QuicConnectionPeer::SetSendAlgorithm(this, send_algorithm
);
79 // Subclass of QuicHttpStream that closes itself when the first piece of data
81 class AutoClosingStream
: public QuicHttpStream
{
83 explicit AutoClosingStream(
84 const base::WeakPtr
<QuicChromiumClientSession
>& session
)
85 : QuicHttpStream(session
) {}
87 void OnHeadersAvailable(StringPiece headers
) override
{ Close(false); }
89 int OnDataReceived(const char* data
, int length
) override
{
95 class TestPacketWriterFactory
: public QuicConnection::PacketWriterFactory
{
97 explicit TestPacketWriterFactory(DatagramClientSocket
* socket
)
99 ~TestPacketWriterFactory() override
{}
101 QuicPacketWriter
* Create(QuicConnection
* connection
) const override
{
102 return new QuicDefaultPacketWriter(socket_
);
106 DatagramClientSocket
* socket_
;
111 class QuicHttpStreamPeer
{
113 static QuicReliableClientStream
* GetQuicReliableClientStream(
114 QuicHttpStream
* stream
) {
115 return stream
->stream_
;
119 class QuicHttpStreamTest
: public ::testing::TestWithParam
<QuicVersion
> {
121 static const bool kFin
= true;
122 static const bool kIncludeVersion
= true;
123 static const bool kIncludeCongestionFeedback
= true;
125 // Holds a packet to be written to the wire, and the IO mode that should
126 // be used by the mock socket when performing the write.
127 struct PacketToWrite
{
128 PacketToWrite(IoMode mode
, QuicEncryptedPacket
* packet
)
133 QuicEncryptedPacket
* packet
;
137 : net_log_(BoundNetLog()),
138 use_closing_stream_(false),
139 read_buffer_(new IOBufferWithSize(4096)),
141 stream_id_(kClientDataStreamId1
),
142 maker_(GetParam(), connection_id_
, &clock_
, kDefaultServerHostName
),
143 random_generator_(0) {
145 CHECK(ParseIPLiteralToNumber("192.0.2.33", &ip
));
146 peer_addr_
= IPEndPoint(ip
, 443);
147 self_addr_
= IPEndPoint(ip
, 8435);
148 clock_
.AdvanceTime(QuicTime::Delta::FromMilliseconds(20));
151 ~QuicHttpStreamTest() {
152 session_
->CloseSessionOnError(ERR_ABORTED
, QUIC_INTERNAL_ERROR
);
153 for (size_t i
= 0; i
< writes_
.size(); i
++) {
154 delete writes_
[i
].packet
;
158 // Adds a packet to the list of expected writes.
159 void AddWrite(scoped_ptr
<QuicEncryptedPacket
> packet
) {
160 writes_
.push_back(PacketToWrite(SYNCHRONOUS
, packet
.release()));
163 // Returns the packet to be written at position |pos|.
164 QuicEncryptedPacket
* GetWrite(size_t pos
) {
165 return writes_
[pos
].packet
;
169 return socket_data_
->AllReadDataConsumed() &&
170 socket_data_
->AllWriteDataConsumed();
173 void ProcessPacket(scoped_ptr
<QuicEncryptedPacket
> packet
) {
174 connection_
->ProcessUdpPacket(self_addr_
, peer_addr_
, *packet
);
177 // Configures the test fixture to use the list of expected writes.
179 mock_writes_
.reset(new MockWrite
[writes_
.size()]);
180 for (size_t i
= 0; i
< writes_
.size(); i
++) {
181 mock_writes_
[i
] = MockWrite(writes_
[i
].mode
,
182 writes_
[i
].packet
->data(),
183 writes_
[i
].packet
->length());
186 socket_data_
.reset(new StaticSocketDataProvider(
187 nullptr, 0, mock_writes_
.get(), writes_
.size()));
189 MockUDPClientSocket
* socket
= new MockUDPClientSocket(socket_data_
.get(),
191 socket
->Connect(peer_addr_
);
192 runner_
= new TestTaskRunner(&clock_
);
193 send_algorithm_
= new MockSendAlgorithm();
194 EXPECT_CALL(*send_algorithm_
, InRecovery()).WillRepeatedly(Return(false));
195 EXPECT_CALL(*send_algorithm_
, InSlowStart()).WillRepeatedly(Return(false));
196 EXPECT_CALL(*send_algorithm_
,
197 OnPacketSent(_
, _
, _
, _
, _
)).WillRepeatedly(Return(true));
198 EXPECT_CALL(*send_algorithm_
, RetransmissionDelay()).WillRepeatedly(
199 Return(QuicTime::Delta::Zero()));
200 EXPECT_CALL(*send_algorithm_
, GetCongestionWindow()).WillRepeatedly(
201 Return(kMaxPacketSize
));
202 EXPECT_CALL(*send_algorithm_
, TimeUntilSend(_
, _
, _
)).
203 WillRepeatedly(Return(QuicTime::Delta::Zero()));
204 EXPECT_CALL(*send_algorithm_
, BandwidthEstimate()).WillRepeatedly(
205 Return(QuicBandwidth::Zero()));
206 EXPECT_CALL(*send_algorithm_
, SetFromConfig(_
, _
)).Times(AnyNumber());
207 helper_
.reset(new QuicConnectionHelper(runner_
.get(), &clock_
,
208 &random_generator_
));
209 TestPacketWriterFactory
writer_factory(socket
);
210 connection_
= new TestQuicConnection(SupportedVersions(GetParam()),
211 connection_id_
, peer_addr_
,
212 helper_
.get(), writer_factory
);
213 connection_
->set_visitor(&visitor_
);
214 connection_
->SetSendAlgorithm(send_algorithm_
);
215 session_
.reset(new QuicChromiumClientSession(
216 connection_
, scoped_ptr
<DatagramClientSocket
>(socket
),
217 /*stream_factory=*/nullptr, &crypto_client_stream_factory_
,
218 &transport_security_state_
, make_scoped_ptr((QuicServerInfo
*)nullptr),
219 QuicServerId(kDefaultServerHostName
, kDefaultServerPort
,
220 /*is_secure=*/false, PRIVACY_MODE_DISABLED
),
221 /*cert_verify_flags=*/0, DefaultQuicConfig(), &crypto_config_
,
222 "CONNECTION_UNKNOWN", base::TimeTicks::Now(),
223 base::ThreadTaskRunnerHandle::Get().get(), nullptr));
224 session_
->Initialize();
225 session_
->GetCryptoStream()->CryptoConnect();
226 EXPECT_TRUE(session_
->IsCryptoHandshakeConfirmed());
227 stream_
.reset(use_closing_stream_
?
228 new AutoClosingStream(session_
->GetWeakPtr()) :
229 new QuicHttpStream(session_
->GetWeakPtr()));
232 void SetRequest(const std::string
& method
,
233 const std::string
& path
,
234 RequestPriority priority
) {
235 request_headers_
= maker_
.GetRequestHeaders(method
, "http", path
);
238 void SetResponse(const std::string
& status
, const std::string
& body
) {
239 response_headers_
= maker_
.GetResponseHeaders(status
);
240 response_data_
= body
;
243 scoped_ptr
<QuicEncryptedPacket
> ConstructDataPacket(
244 QuicPacketSequenceNumber sequence_number
,
245 bool should_include_version
,
247 QuicStreamOffset offset
,
248 base::StringPiece data
) {
249 return maker_
.MakeDataPacket(sequence_number
, stream_id_
,
250 should_include_version
, fin
, offset
, data
);
253 scoped_ptr
<QuicEncryptedPacket
> ConstructRequestHeadersPacket(
254 QuicPacketSequenceNumber sequence_number
,
256 RequestPriority request_priority
) {
257 QuicPriority priority
=
258 ConvertRequestPriorityToQuicPriority(request_priority
);
259 return maker_
.MakeRequestHeadersPacket(sequence_number
, stream_id_
,
260 kIncludeVersion
, fin
, priority
,
264 scoped_ptr
<QuicEncryptedPacket
> ConstructResponseHeadersPacket(
265 QuicPacketSequenceNumber sequence_number
,
267 return maker_
.MakeResponseHeadersPacket(
268 sequence_number
, stream_id_
, !kIncludeVersion
, fin
, response_headers_
);
271 scoped_ptr
<QuicEncryptedPacket
> ConstructRstStreamPacket(
272 QuicPacketSequenceNumber sequence_number
) {
273 return maker_
.MakeRstPacket(
274 sequence_number
, true, stream_id_
,
275 AdjustErrorForVersion(QUIC_RST_ACKNOWLEDGEMENT
, GetParam()));
278 scoped_ptr
<QuicEncryptedPacket
> ConstructRstStreamCancelledPacket(
279 QuicPacketSequenceNumber sequence_number
) {
280 return maker_
.MakeRstPacket(sequence_number
, !kIncludeVersion
, stream_id_
,
281 QUIC_STREAM_CANCELLED
);
284 scoped_ptr
<QuicEncryptedPacket
> ConstructAckAndRstStreamPacket(
285 QuicPacketSequenceNumber sequence_number
) {
286 return maker_
.MakeAckAndRstPacket(
287 sequence_number
, !kIncludeVersion
, stream_id_
, QUIC_STREAM_CANCELLED
,
288 2, 1, !kIncludeCongestionFeedback
);
291 scoped_ptr
<QuicEncryptedPacket
> ConstructAckPacket(
292 QuicPacketSequenceNumber sequence_number
,
293 QuicPacketSequenceNumber largest_received
,
294 QuicPacketSequenceNumber least_unacked
) {
295 return maker_
.MakeAckPacket(sequence_number
, largest_received
,
296 least_unacked
, !kIncludeCongestionFeedback
);
299 BoundNetLog net_log_
;
300 bool use_closing_stream_
;
301 MockSendAlgorithm
* send_algorithm_
;
302 scoped_refptr
<TestTaskRunner
> runner_
;
303 scoped_ptr
<MockWrite
[]> mock_writes_
;
305 TestQuicConnection
* connection_
;
306 scoped_ptr
<QuicConnectionHelper
> helper_
;
307 testing::StrictMock
<MockConnectionVisitor
> visitor_
;
308 scoped_ptr
<QuicHttpStream
> stream_
;
309 TransportSecurityState transport_security_state_
;
310 scoped_ptr
<QuicChromiumClientSession
> session_
;
311 QuicCryptoClientConfig crypto_config_
;
312 TestCompletionCallback callback_
;
313 HttpRequestInfo request_
;
314 HttpRequestHeaders headers_
;
315 HttpResponseInfo response_
;
316 scoped_refptr
<IOBufferWithSize
> read_buffer_
;
317 SpdyHeaderBlock request_headers_
;
318 SpdyHeaderBlock response_headers_
;
319 std::string request_data_
;
320 std::string response_data_
;
323 const QuicConnectionId connection_id_
;
324 const QuicStreamId stream_id_
;
325 QuicTestPacketMaker maker_
;
326 IPEndPoint self_addr_
;
327 IPEndPoint peer_addr_
;
328 MockRandom random_generator_
;
329 MockCryptoClientStreamFactory crypto_client_stream_factory_
;
330 scoped_ptr
<StaticSocketDataProvider
> socket_data_
;
331 std::vector
<PacketToWrite
> writes_
;
334 INSTANTIATE_TEST_CASE_P(Version
, QuicHttpStreamTest
,
335 ::testing::ValuesIn(QuicSupportedVersions()));
337 TEST_P(QuicHttpStreamTest
, RenewStreamForAuth
) {
339 EXPECT_EQ(nullptr, stream_
->RenewStreamForAuth());
342 TEST_P(QuicHttpStreamTest
, CanFindEndOfResponse
) {
344 EXPECT_TRUE(stream_
->CanFindEndOfResponse());
347 TEST_P(QuicHttpStreamTest
, IsConnectionReusable
) {
349 EXPECT_FALSE(stream_
->IsConnectionReusable());
352 TEST_P(QuicHttpStreamTest
, GetRequest
) {
353 SetRequest("GET", "/", DEFAULT_PRIORITY
);
354 AddWrite(ConstructRequestHeadersPacket(1, kFin
, DEFAULT_PRIORITY
));
357 request_
.method
= "GET";
358 request_
.url
= GURL("http://www.google.com/");
360 EXPECT_EQ(OK
, stream_
->InitializeStream(&request_
, DEFAULT_PRIORITY
,
361 net_log_
, callback_
.callback()));
362 EXPECT_EQ(OK
, stream_
->SendRequest(headers_
, &response_
,
363 callback_
.callback()));
366 ProcessPacket(ConstructAckPacket(1, 0, 0));
368 EXPECT_EQ(ERR_IO_PENDING
,
369 stream_
->ReadResponseHeaders(callback_
.callback()));
371 SetResponse("404 Not Found", std::string());
372 ProcessPacket(ConstructResponseHeadersPacket(2, kFin
));
374 // Now that the headers have been processed, the callback will return.
375 EXPECT_EQ(OK
, callback_
.WaitForResult());
376 ASSERT_TRUE(response_
.headers
.get());
377 EXPECT_EQ(404, response_
.headers
->response_code());
378 EXPECT_TRUE(response_
.headers
->HasHeaderValue("Content-Type", "text/plain"));
379 EXPECT_FALSE(response_
.response_time
.is_null());
380 EXPECT_FALSE(response_
.request_time
.is_null());
382 // There is no body, so this should return immediately.
383 EXPECT_EQ(0, stream_
->ReadResponseBody(read_buffer_
.get(),
384 read_buffer_
->size(),
385 callback_
.callback()));
386 EXPECT_TRUE(stream_
->IsResponseBodyComplete());
387 EXPECT_TRUE(AtEof());
390 // Regression test for http://crbug.com/288128
391 TEST_P(QuicHttpStreamTest
, GetRequestLargeResponse
) {
392 SetRequest("GET", "/", DEFAULT_PRIORITY
);
393 AddWrite(ConstructRequestHeadersPacket(1, kFin
, DEFAULT_PRIORITY
));
396 request_
.method
= "GET";
397 request_
.url
= GURL("http://www.google.com/");
399 EXPECT_EQ(OK
, stream_
->InitializeStream(&request_
, DEFAULT_PRIORITY
,
400 net_log_
, callback_
.callback()));
401 EXPECT_EQ(OK
, stream_
->SendRequest(headers_
, &response_
,
402 callback_
.callback()));
405 ProcessPacket(ConstructAckPacket(1, 0, 0));
407 EXPECT_EQ(ERR_IO_PENDING
,
408 stream_
->ReadResponseHeaders(callback_
.callback()));
410 SpdyHeaderBlock headers
;
411 headers
[":status"] = "200 OK";
412 headers
[":version"] = "HTTP/1.1";
413 headers
["content-type"] = "text/plain";
414 headers
["big6"] = std::string(1000, 'x'); // Lots of x's.
416 response_headers_
= headers
;
417 ProcessPacket(ConstructResponseHeadersPacket(2, kFin
));
419 // Now that the headers have been processed, the callback will return.
420 EXPECT_EQ(OK
, callback_
.WaitForResult());
421 ASSERT_TRUE(response_
.headers
.get());
422 EXPECT_EQ(200, response_
.headers
->response_code());
423 EXPECT_TRUE(response_
.headers
->HasHeaderValue("Content-Type", "text/plain"));
425 // There is no body, so this should return immediately.
426 EXPECT_EQ(0, stream_
->ReadResponseBody(read_buffer_
.get(),
427 read_buffer_
->size(),
428 callback_
.callback()));
429 EXPECT_TRUE(stream_
->IsResponseBodyComplete());
430 EXPECT_TRUE(AtEof());
433 // Regression test for http://crbug.com/409101
434 TEST_P(QuicHttpStreamTest
, SessionClosedBeforeSendRequest
) {
435 SetRequest("GET", "/", DEFAULT_PRIORITY
);
438 request_
.method
= "GET";
439 request_
.url
= GURL("http://www.google.com/");
441 EXPECT_EQ(OK
, stream_
->InitializeStream(&request_
, DEFAULT_PRIORITY
,
442 net_log_
, callback_
.callback()));
444 session_
->connection()->CloseConnection(QUIC_NO_ERROR
, true);
446 EXPECT_EQ(ERR_CONNECTION_CLOSED
,
447 stream_
->SendRequest(headers_
, &response_
,
448 callback_
.callback()));
451 // Regression test for http://crbug.com/409871
452 TEST_P(QuicHttpStreamTest
, SessionClosedBeforeReadResponseHeaders
) {
453 SetRequest("GET", "/", DEFAULT_PRIORITY
);
454 AddWrite(ConstructRequestHeadersPacket(1, kFin
, DEFAULT_PRIORITY
));
457 request_
.method
= "GET";
458 request_
.url
= GURL("http://www.google.com/");
460 EXPECT_EQ(OK
, stream_
->InitializeStream(&request_
, DEFAULT_PRIORITY
,
461 net_log_
, callback_
.callback()));
463 EXPECT_EQ(OK
, stream_
->SendRequest(headers_
, &response_
,
464 callback_
.callback()));
466 session_
->connection()->CloseConnection(QUIC_NO_ERROR
, true);
468 EXPECT_NE(OK
, stream_
->ReadResponseHeaders(callback_
.callback()));
471 TEST_P(QuicHttpStreamTest
, SendPostRequest
) {
472 SetRequest("POST", "/", DEFAULT_PRIORITY
);
473 AddWrite(ConstructRequestHeadersPacket(1, !kFin
, DEFAULT_PRIORITY
));
474 AddWrite(ConstructDataPacket(2, kIncludeVersion
, kFin
, 0, kUploadData
));
475 AddWrite(ConstructAckPacket(3, 3, 1));
479 ScopedVector
<UploadElementReader
> element_readers
;
480 element_readers
.push_back(
481 new UploadBytesElementReader(kUploadData
, strlen(kUploadData
)));
482 ElementsUploadDataStream
upload_data_stream(element_readers
.Pass(), 0);
483 request_
.method
= "POST";
484 request_
.url
= GURL("http://www.google.com/");
485 request_
.upload_data_stream
= &upload_data_stream
;
486 ASSERT_EQ(OK
, request_
.upload_data_stream
->Init(CompletionCallback()));
488 EXPECT_EQ(OK
, stream_
->InitializeStream(&request_
, DEFAULT_PRIORITY
,
489 net_log_
, callback_
.callback()));
490 EXPECT_EQ(OK
, stream_
->SendRequest(headers_
, &response_
,
491 callback_
.callback()));
493 // Ack both packets in the request.
494 ProcessPacket(ConstructAckPacket(1, 0, 0));
496 // Send the response headers (but not the body).
497 SetResponse("200 OK", std::string());
498 ProcessPacket(ConstructResponseHeadersPacket(2, !kFin
));
500 // Since the headers have already arrived, this should return immediately.
501 EXPECT_EQ(OK
, stream_
->ReadResponseHeaders(callback_
.callback()));
502 ASSERT_TRUE(response_
.headers
.get());
503 EXPECT_EQ(200, response_
.headers
->response_code());
504 EXPECT_TRUE(response_
.headers
->HasHeaderValue("Content-Type", "text/plain"));
506 // Send the response body.
507 const char kResponseBody
[] = "Hello world!";
508 ProcessPacket(ConstructDataPacket(3, false, kFin
, 0, kResponseBody
));
509 // Since the body has already arrived, this should return immediately.
510 EXPECT_EQ(static_cast<int>(strlen(kResponseBody
)),
511 stream_
->ReadResponseBody(read_buffer_
.get(), read_buffer_
->size(),
512 callback_
.callback()));
514 EXPECT_TRUE(stream_
->IsResponseBodyComplete());
515 EXPECT_TRUE(AtEof());
518 TEST_P(QuicHttpStreamTest
, SendChunkedPostRequest
) {
519 SetRequest("POST", "/", DEFAULT_PRIORITY
);
520 size_t chunk_size
= strlen(kUploadData
);
521 AddWrite(ConstructRequestHeadersPacket(1, !kFin
, DEFAULT_PRIORITY
));
522 AddWrite(ConstructDataPacket(2, kIncludeVersion
, !kFin
, 0, kUploadData
));
523 AddWrite(ConstructDataPacket(3, kIncludeVersion
, kFin
, chunk_size
,
525 AddWrite(ConstructAckPacket(4, 3, 1));
528 ChunkedUploadDataStream
upload_data_stream(0);
529 upload_data_stream
.AppendData(kUploadData
, chunk_size
, false);
531 request_
.method
= "POST";
532 request_
.url
= GURL("http://www.google.com/");
533 request_
.upload_data_stream
= &upload_data_stream
;
534 ASSERT_EQ(OK
, request_
.upload_data_stream
->Init(
535 TestCompletionCallback().callback()));
537 ASSERT_EQ(OK
, stream_
->InitializeStream(&request_
, DEFAULT_PRIORITY
,
538 net_log_
, callback_
.callback()));
539 ASSERT_EQ(ERR_IO_PENDING
, stream_
->SendRequest(headers_
, &response_
,
540 callback_
.callback()));
542 upload_data_stream
.AppendData(kUploadData
, chunk_size
, true);
544 // Ack both packets in the request.
545 ProcessPacket(ConstructAckPacket(1, 0, 0));
547 // Send the response headers (but not the body).
548 SetResponse("200 OK", std::string());
549 ProcessPacket(ConstructResponseHeadersPacket(2, !kFin
));
551 // Since the headers have already arrived, this should return immediately.
552 ASSERT_EQ(OK
, stream_
->ReadResponseHeaders(callback_
.callback()));
553 ASSERT_TRUE(response_
.headers
.get());
554 EXPECT_EQ(200, response_
.headers
->response_code());
555 EXPECT_TRUE(response_
.headers
->HasHeaderValue("Content-Type", "text/plain"));
557 // Send the response body.
558 const char kResponseBody
[] = "Hello world!";
559 ProcessPacket(ConstructDataPacket(3, false, kFin
, response_data_
.length(),
562 // Since the body has already arrived, this should return immediately.
563 ASSERT_EQ(static_cast<int>(strlen(kResponseBody
)),
564 stream_
->ReadResponseBody(read_buffer_
.get(), read_buffer_
->size(),
565 callback_
.callback()));
567 EXPECT_TRUE(stream_
->IsResponseBodyComplete());
568 EXPECT_TRUE(AtEof());
571 TEST_P(QuicHttpStreamTest
, SendChunkedPostRequestWithFinalEmptyDataPacket
) {
572 SetRequest("POST", "/", DEFAULT_PRIORITY
);
573 size_t chunk_size
= strlen(kUploadData
);
574 AddWrite(ConstructRequestHeadersPacket(1, !kFin
, DEFAULT_PRIORITY
));
575 AddWrite(ConstructDataPacket(2, kIncludeVersion
, !kFin
, 0, kUploadData
));
576 AddWrite(ConstructDataPacket(3, kIncludeVersion
, kFin
, chunk_size
, ""));
577 AddWrite(ConstructAckPacket(4, 3, 1));
580 ChunkedUploadDataStream
upload_data_stream(0);
581 upload_data_stream
.AppendData(kUploadData
, chunk_size
, false);
583 request_
.method
= "POST";
584 request_
.url
= GURL("http://www.google.com/");
585 request_
.upload_data_stream
= &upload_data_stream
;
586 ASSERT_EQ(OK
, request_
.upload_data_stream
->Init(
587 TestCompletionCallback().callback()));
589 ASSERT_EQ(OK
, stream_
->InitializeStream(&request_
, DEFAULT_PRIORITY
,
590 net_log_
, callback_
.callback()));
591 ASSERT_EQ(ERR_IO_PENDING
, stream_
->SendRequest(headers_
, &response_
,
592 callback_
.callback()));
594 upload_data_stream
.AppendData(nullptr, 0, true);
596 ProcessPacket(ConstructAckPacket(1, 0, 0));
598 // Send the response headers (but not the body).
599 SetResponse("200 OK", std::string());
600 ProcessPacket(ConstructResponseHeadersPacket(2, !kFin
));
602 // Since the headers have already arrived, this should return immediately.
603 ASSERT_EQ(OK
, stream_
->ReadResponseHeaders(callback_
.callback()));
604 ASSERT_TRUE(response_
.headers
.get());
605 EXPECT_EQ(200, response_
.headers
->response_code());
606 EXPECT_TRUE(response_
.headers
->HasHeaderValue("Content-Type", "text/plain"));
608 // Send the response body.
609 const char kResponseBody
[] = "Hello world!";
610 ProcessPacket(ConstructDataPacket(3, false, kFin
, response_data_
.length(),
613 // Since the body has already arrived, this should return immediately.
614 ASSERT_EQ(static_cast<int>(strlen(kResponseBody
)),
615 stream_
->ReadResponseBody(read_buffer_
.get(), read_buffer_
->size(),
616 callback_
.callback()));
618 EXPECT_TRUE(stream_
->IsResponseBodyComplete());
619 EXPECT_TRUE(AtEof());
622 TEST_P(QuicHttpStreamTest
, SendChunkedPostRequestWithOneEmptyDataPacket
) {
623 SetRequest("POST", "/", DEFAULT_PRIORITY
);
624 AddWrite(ConstructRequestHeadersPacket(1, !kFin
, DEFAULT_PRIORITY
));
625 AddWrite(ConstructDataPacket(2, kIncludeVersion
, kFin
, 0, ""));
626 AddWrite(ConstructAckPacket(3, 3, 1));
629 ChunkedUploadDataStream
upload_data_stream(0);
631 request_
.method
= "POST";
632 request_
.url
= GURL("http://www.google.com/");
633 request_
.upload_data_stream
= &upload_data_stream
;
634 ASSERT_EQ(OK
, request_
.upload_data_stream
->Init(
635 TestCompletionCallback().callback()));
637 ASSERT_EQ(OK
, stream_
->InitializeStream(&request_
, DEFAULT_PRIORITY
,
638 net_log_
, callback_
.callback()));
639 ASSERT_EQ(ERR_IO_PENDING
, stream_
->SendRequest(headers_
, &response_
,
640 callback_
.callback()));
642 upload_data_stream
.AppendData(nullptr, 0, true);
644 ProcessPacket(ConstructAckPacket(1, 0, 0));
646 // Send the response headers (but not the body).
647 SetResponse("200 OK", std::string());
648 ProcessPacket(ConstructResponseHeadersPacket(2, !kFin
));
650 // Since the headers have already arrived, this should return immediately.
651 ASSERT_EQ(OK
, stream_
->ReadResponseHeaders(callback_
.callback()));
652 ASSERT_TRUE(response_
.headers
.get());
653 EXPECT_EQ(200, response_
.headers
->response_code());
654 EXPECT_TRUE(response_
.headers
->HasHeaderValue("Content-Type", "text/plain"));
656 // Send the response body.
657 const char kResponseBody
[] = "Hello world!";
658 ProcessPacket(ConstructDataPacket(3, false, kFin
, response_data_
.length(),
661 // Since the body has already arrived, this should return immediately.
662 ASSERT_EQ(static_cast<int>(strlen(kResponseBody
)),
663 stream_
->ReadResponseBody(read_buffer_
.get(), read_buffer_
->size(),
664 callback_
.callback()));
666 EXPECT_TRUE(stream_
->IsResponseBodyComplete());
667 EXPECT_TRUE(AtEof());
670 TEST_P(QuicHttpStreamTest
, DestroyedEarly
) {
671 SetRequest("GET", "/", DEFAULT_PRIORITY
);
672 AddWrite(ConstructRequestHeadersPacket(1, kFin
, DEFAULT_PRIORITY
));
673 if (FLAGS_quic_process_frames_inline
) {
674 AddWrite(ConstructRstStreamCancelledPacket(2));
676 AddWrite(ConstructAckAndRstStreamPacket(2));
678 use_closing_stream_
= true;
681 request_
.method
= "GET";
682 request_
.url
= GURL("http://www.google.com/");
684 EXPECT_EQ(OK
, stream_
->InitializeStream(&request_
, DEFAULT_PRIORITY
,
685 net_log_
, callback_
.callback()));
686 EXPECT_EQ(OK
, stream_
->SendRequest(headers_
, &response_
,
687 callback_
.callback()));
690 ProcessPacket(ConstructAckPacket(1, 0, 0));
691 EXPECT_EQ(ERR_IO_PENDING
,
692 stream_
->ReadResponseHeaders(callback_
.callback()));
694 // Send the response with a body.
695 SetResponse("404 OK", "hello world!");
696 // In the course of processing this packet, the QuicHttpStream close itself.
697 ProcessPacket(ConstructResponseHeadersPacket(2, kFin
));
699 EXPECT_TRUE(AtEof());
702 TEST_P(QuicHttpStreamTest
, Priority
) {
703 SetRequest("GET", "/", MEDIUM
);
704 AddWrite(ConstructRequestHeadersPacket(1, kFin
, MEDIUM
));
705 if (FLAGS_quic_process_frames_inline
) {
706 AddWrite(ConstructRstStreamCancelledPacket(2));
708 AddWrite(ConstructAckAndRstStreamPacket(2));
710 use_closing_stream_
= true;
713 request_
.method
= "GET";
714 request_
.url
= GURL("http://www.google.com/");
716 EXPECT_EQ(OK
, stream_
->InitializeStream(&request_
, MEDIUM
,
717 net_log_
, callback_
.callback()));
719 // Check that priority is highest.
720 QuicReliableClientStream
* reliable_stream
=
721 QuicHttpStreamPeer::GetQuicReliableClientStream(stream_
.get());
722 DCHECK(reliable_stream
);
723 DCHECK_EQ(QuicWriteBlockedList::kHighestPriority
,
724 reliable_stream
->EffectivePriority());
726 EXPECT_EQ(OK
, stream_
->SendRequest(headers_
, &response_
,
727 callback_
.callback()));
729 // Check that priority has now dropped back to MEDIUM.
730 DCHECK_EQ(MEDIUM
, ConvertQuicPriorityToRequestPriority(
731 reliable_stream
->EffectivePriority()));
734 ProcessPacket(ConstructAckPacket(1, 0, 0));
735 EXPECT_EQ(ERR_IO_PENDING
,
736 stream_
->ReadResponseHeaders(callback_
.callback()));
738 // Send the response with a body.
739 SetResponse("404 OK", "hello world!");
740 // In the course of processing this packet, the QuicHttpStream close itself.
741 ProcessPacket(ConstructResponseHeadersPacket(2, kFin
));
743 EXPECT_TRUE(AtEof());
746 // Regression test for http://crbug.com/294870
747 TEST_P(QuicHttpStreamTest
, CheckPriorityWithNoDelegate
) {
748 SetRequest("GET", "/", MEDIUM
);
749 use_closing_stream_
= true;
751 AddWrite(ConstructRstStreamPacket(1));
755 request_
.method
= "GET";
756 request_
.url
= GURL("http://www.google.com/");
758 EXPECT_EQ(OK
, stream_
->InitializeStream(&request_
, MEDIUM
,
759 net_log_
, callback_
.callback()));
761 // Check that priority is highest.
762 QuicReliableClientStream
* reliable_stream
=
763 QuicHttpStreamPeer::GetQuicReliableClientStream(stream_
.get());
764 DCHECK(reliable_stream
);
765 QuicReliableClientStream::Delegate
* delegate
= reliable_stream
->GetDelegate();
767 DCHECK_EQ(QuicWriteBlockedList::kHighestPriority
,
768 reliable_stream
->EffectivePriority());
770 // Set Delegate to nullptr and make sure EffectivePriority returns highest
772 reliable_stream
->SetDelegate(nullptr);
773 DCHECK_EQ(QuicWriteBlockedList::kHighestPriority
,
774 reliable_stream
->EffectivePriority());
775 reliable_stream
->SetDelegate(delegate
);