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_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_http_utils.h"
27 #include "net/quic/quic_reliable_client_stream.h"
28 #include "net/quic/quic_write_blocked_list.h"
29 #include "net/quic/spdy_utils.h"
30 #include "net/quic/test_tools/mock_clock.h"
31 #include "net/quic/test_tools/mock_crypto_client_stream_factory.h"
32 #include "net/quic/test_tools/mock_random.h"
33 #include "net/quic/test_tools/quic_connection_peer.h"
34 #include "net/quic/test_tools/quic_test_packet_maker.h"
35 #include "net/quic/test_tools/quic_test_utils.h"
36 #include "net/quic/test_tools/test_task_runner.h"
37 #include "net/socket/socket_test_util.h"
38 #include "net/spdy/spdy_frame_builder.h"
39 #include "net/spdy/spdy_framer.h"
40 #include "net/spdy/spdy_http_utils.h"
41 #include "net/spdy/spdy_protocol.h"
42 #include "testing/gmock/include/gmock/gmock.h"
43 #include "testing/gtest/include/gtest/gtest.h"
46 using testing::AnyNumber
;
47 using testing::Return
;
53 const char kUploadData
[] = "Really nifty data!";
54 const char kDefaultServerHostName
[] = "www.google.com";
55 const uint16 kDefaultServerPort
= 80;
57 class TestQuicConnection
: public QuicConnection
{
59 TestQuicConnection(const QuicVersionVector
& versions
,
60 QuicConnectionId connection_id
,
62 QuicConnectionHelper
* helper
,
63 const QuicConnection::PacketWriterFactory
& writer_factory
)
64 : QuicConnection(connection_id
,
68 true /* owns_writer */,
69 Perspective::IS_CLIENT
,
70 false /* is_secure */,
73 void SetSendAlgorithm(SendAlgorithmInterface
* send_algorithm
) {
74 QuicConnectionPeer::SetSendAlgorithm(this, send_algorithm
);
78 // Subclass of QuicHttpStream that closes itself when the first piece of data
80 class AutoClosingStream
: public QuicHttpStream
{
82 explicit AutoClosingStream(const base::WeakPtr
<QuicClientSession
>& session
)
83 : QuicHttpStream(session
) {
86 int OnDataReceived(const char* data
, int length
) override
{
92 class TestPacketWriterFactory
: public QuicConnection::PacketWriterFactory
{
94 explicit TestPacketWriterFactory(DatagramClientSocket
* socket
)
96 ~TestPacketWriterFactory() override
{}
98 QuicPacketWriter
* Create(QuicConnection
* connection
) const override
{
99 return new QuicDefaultPacketWriter(socket_
);
103 DatagramClientSocket
* socket_
;
108 class QuicHttpStreamPeer
{
110 static QuicReliableClientStream
* GetQuicReliableClientStream(
111 QuicHttpStream
* stream
) {
112 return stream
->stream_
;
116 class QuicHttpStreamTest
: public ::testing::TestWithParam
<QuicVersion
> {
118 static const bool kFin
= true;
119 static const bool kIncludeVersion
= true;
120 static const bool kIncludeCongestionFeedback
= true;
122 // Holds a packet to be written to the wire, and the IO mode that should
123 // be used by the mock socket when performing the write.
124 struct PacketToWrite
{
125 PacketToWrite(IoMode mode
, QuicEncryptedPacket
* packet
)
130 QuicEncryptedPacket
* packet
;
134 : net_log_(BoundNetLog()),
135 use_closing_stream_(false),
136 read_buffer_(new IOBufferWithSize(4096)),
138 stream_id_(kClientDataStreamId1
),
139 maker_(GetParam(), connection_id_
, &clock_
, kDefaultServerHostName
),
140 random_generator_(0) {
142 CHECK(ParseIPLiteralToNumber("192.0.2.33", &ip
));
143 peer_addr_
= IPEndPoint(ip
, 443);
144 self_addr_
= IPEndPoint(ip
, 8435);
145 clock_
.AdvanceTime(QuicTime::Delta::FromMilliseconds(20));
148 ~QuicHttpStreamTest() {
149 session_
->CloseSessionOnError(ERR_ABORTED
, QUIC_INTERNAL_ERROR
);
150 for (size_t i
= 0; i
< writes_
.size(); i
++) {
151 delete writes_
[i
].packet
;
155 // Adds a packet to the list of expected writes.
156 void AddWrite(scoped_ptr
<QuicEncryptedPacket
> packet
) {
157 writes_
.push_back(PacketToWrite(SYNCHRONOUS
, packet
.release()));
160 // Returns the packet to be written at position |pos|.
161 QuicEncryptedPacket
* GetWrite(size_t pos
) {
162 return writes_
[pos
].packet
;
166 return socket_data_
->AllReadDataConsumed() &&
167 socket_data_
->AllWriteDataConsumed();
170 void ProcessPacket(scoped_ptr
<QuicEncryptedPacket
> packet
) {
171 connection_
->ProcessUdpPacket(self_addr_
, peer_addr_
, *packet
);
174 // Configures the test fixture to use the list of expected writes.
176 mock_writes_
.reset(new MockWrite
[writes_
.size()]);
177 for (size_t i
= 0; i
< writes_
.size(); i
++) {
178 mock_writes_
[i
] = MockWrite(writes_
[i
].mode
,
179 writes_
[i
].packet
->data(),
180 writes_
[i
].packet
->length());
183 socket_data_
.reset(new StaticSocketDataProvider(
184 nullptr, 0, mock_writes_
.get(), writes_
.size()));
186 MockUDPClientSocket
* socket
= new MockUDPClientSocket(socket_data_
.get(),
188 socket
->Connect(peer_addr_
);
189 runner_
= new TestTaskRunner(&clock_
);
190 send_algorithm_
= new MockSendAlgorithm();
191 EXPECT_CALL(*send_algorithm_
,
192 OnPacketSent(_
, _
, _
, _
, _
)).WillRepeatedly(Return(true));
193 EXPECT_CALL(*send_algorithm_
, RetransmissionDelay()).WillRepeatedly(
194 Return(QuicTime::Delta::Zero()));
195 EXPECT_CALL(*send_algorithm_
, GetCongestionWindow()).WillRepeatedly(
196 Return(kMaxPacketSize
));
197 EXPECT_CALL(*send_algorithm_
, TimeUntilSend(_
, _
, _
)).
198 WillRepeatedly(Return(QuicTime::Delta::Zero()));
199 EXPECT_CALL(*send_algorithm_
, BandwidthEstimate()).WillRepeatedly(
200 Return(QuicBandwidth::Zero()));
201 EXPECT_CALL(*send_algorithm_
, SetFromConfig(_
, _
)).Times(AnyNumber());
202 helper_
.reset(new QuicConnectionHelper(runner_
.get(), &clock_
,
203 &random_generator_
));
204 TestPacketWriterFactory
writer_factory(socket
);
205 connection_
= new TestQuicConnection(SupportedVersions(GetParam()),
206 connection_id_
, peer_addr_
,
207 helper_
.get(), writer_factory
);
208 connection_
->set_visitor(&visitor_
);
209 connection_
->SetSendAlgorithm(send_algorithm_
);
210 session_
.reset(new QuicClientSession(
211 connection_
, scoped_ptr
<DatagramClientSocket
>(socket
),
212 /*stream_factory=*/nullptr, &crypto_client_stream_factory_
,
213 &transport_security_state_
, make_scoped_ptr((QuicServerInfo
*)nullptr),
214 QuicServerId(kDefaultServerHostName
, kDefaultServerPort
,
215 /*is_secure=*/false, PRIVACY_MODE_DISABLED
),
216 /*cert_verify_flags=*/0, DefaultQuicConfig(), &crypto_config_
,
217 "CONNECTION_UNKNOWN", base::TimeTicks::Now(),
218 base::ThreadTaskRunnerHandle::Get().get(), nullptr));
219 session_
->Initialize();
220 session_
->GetCryptoStream()->CryptoConnect();
221 EXPECT_TRUE(session_
->IsCryptoHandshakeConfirmed());
222 stream_
.reset(use_closing_stream_
?
223 new AutoClosingStream(session_
->GetWeakPtr()) :
224 new QuicHttpStream(session_
->GetWeakPtr()));
227 void SetRequest(const std::string
& method
,
228 const std::string
& path
,
229 RequestPriority priority
) {
230 request_headers_
= maker_
.GetRequestHeaders(method
, "http", path
);
233 void SetResponse(const std::string
& status
, const std::string
& body
) {
234 response_headers_
= maker_
.GetResponseHeaders(status
);
235 response_data_
= body
;
238 scoped_ptr
<QuicEncryptedPacket
> ConstructDataPacket(
239 QuicPacketSequenceNumber sequence_number
,
240 bool should_include_version
,
242 QuicStreamOffset offset
,
243 base::StringPiece data
) {
244 return maker_
.MakeDataPacket(sequence_number
, stream_id_
,
245 should_include_version
, fin
, offset
, data
);
248 scoped_ptr
<QuicEncryptedPacket
> ConstructRequestHeadersPacket(
249 QuicPacketSequenceNumber sequence_number
,
251 RequestPriority request_priority
) {
252 QuicPriority priority
=
253 ConvertRequestPriorityToQuicPriority(request_priority
);
254 return maker_
.MakeRequestHeadersPacket(sequence_number
, stream_id_
,
255 kIncludeVersion
, fin
, priority
,
259 scoped_ptr
<QuicEncryptedPacket
> ConstructResponseHeadersPacket(
260 QuicPacketSequenceNumber sequence_number
,
262 return maker_
.MakeResponseHeadersPacket(
263 sequence_number
, stream_id_
, !kIncludeVersion
, fin
, response_headers_
);
266 scoped_ptr
<QuicEncryptedPacket
> ConstructRstStreamPacket(
267 QuicPacketSequenceNumber sequence_number
) {
268 return maker_
.MakeRstPacket(
269 sequence_number
, true, stream_id_
,
270 AdjustErrorForVersion(QUIC_RST_ACKNOWLEDGEMENT
, GetParam()));
273 scoped_ptr
<QuicEncryptedPacket
> ConstructAckAndRstStreamPacket(
274 QuicPacketSequenceNumber sequence_number
) {
275 return maker_
.MakeAckAndRstPacket(
276 sequence_number
, !kIncludeVersion
, stream_id_
, QUIC_STREAM_CANCELLED
,
277 2, 1, !kIncludeCongestionFeedback
);
280 scoped_ptr
<QuicEncryptedPacket
> ConstructAckPacket(
281 QuicPacketSequenceNumber sequence_number
,
282 QuicPacketSequenceNumber largest_received
,
283 QuicPacketSequenceNumber least_unacked
) {
284 return maker_
.MakeAckPacket(sequence_number
, largest_received
,
285 least_unacked
, !kIncludeCongestionFeedback
);
288 BoundNetLog net_log_
;
289 bool use_closing_stream_
;
290 MockSendAlgorithm
* send_algorithm_
;
291 scoped_refptr
<TestTaskRunner
> runner_
;
292 scoped_ptr
<MockWrite
[]> mock_writes_
;
294 TestQuicConnection
* connection_
;
295 scoped_ptr
<QuicConnectionHelper
> helper_
;
296 testing::StrictMock
<MockConnectionVisitor
> visitor_
;
297 scoped_ptr
<QuicHttpStream
> stream_
;
298 TransportSecurityState transport_security_state_
;
299 scoped_ptr
<QuicClientSession
> session_
;
300 QuicCryptoClientConfig crypto_config_
;
301 TestCompletionCallback callback_
;
302 HttpRequestInfo request_
;
303 HttpRequestHeaders headers_
;
304 HttpResponseInfo response_
;
305 scoped_refptr
<IOBufferWithSize
> read_buffer_
;
306 SpdyHeaderBlock request_headers_
;
307 SpdyHeaderBlock response_headers_
;
308 std::string request_data_
;
309 std::string response_data_
;
312 const QuicConnectionId connection_id_
;
313 const QuicStreamId stream_id_
;
314 QuicTestPacketMaker maker_
;
315 IPEndPoint self_addr_
;
316 IPEndPoint peer_addr_
;
317 MockRandom random_generator_
;
318 MockCryptoClientStreamFactory crypto_client_stream_factory_
;
319 scoped_ptr
<StaticSocketDataProvider
> socket_data_
;
320 std::vector
<PacketToWrite
> writes_
;
323 INSTANTIATE_TEST_CASE_P(Version
, QuicHttpStreamTest
,
324 ::testing::ValuesIn(QuicSupportedVersions()));
326 TEST_P(QuicHttpStreamTest
, RenewStreamForAuth
) {
328 EXPECT_EQ(nullptr, stream_
->RenewStreamForAuth());
331 TEST_P(QuicHttpStreamTest
, CanFindEndOfResponse
) {
333 EXPECT_TRUE(stream_
->CanFindEndOfResponse());
336 TEST_P(QuicHttpStreamTest
, IsConnectionReusable
) {
338 EXPECT_FALSE(stream_
->IsConnectionReusable());
341 TEST_P(QuicHttpStreamTest
, GetRequest
) {
342 SetRequest("GET", "/", DEFAULT_PRIORITY
);
343 AddWrite(ConstructRequestHeadersPacket(1, kFin
, DEFAULT_PRIORITY
));
346 request_
.method
= "GET";
347 request_
.url
= GURL("http://www.google.com/");
349 EXPECT_EQ(OK
, stream_
->InitializeStream(&request_
, DEFAULT_PRIORITY
,
350 net_log_
, callback_
.callback()));
351 EXPECT_EQ(OK
, stream_
->SendRequest(headers_
, &response_
,
352 callback_
.callback()));
355 ProcessPacket(ConstructAckPacket(1, 0, 0));
357 EXPECT_EQ(ERR_IO_PENDING
,
358 stream_
->ReadResponseHeaders(callback_
.callback()));
360 SetResponse("404 Not Found", std::string());
361 ProcessPacket(ConstructResponseHeadersPacket(2, kFin
));
363 // Now that the headers have been processed, the callback will return.
364 EXPECT_EQ(OK
, callback_
.WaitForResult());
365 ASSERT_TRUE(response_
.headers
.get());
366 EXPECT_EQ(404, response_
.headers
->response_code());
367 EXPECT_TRUE(response_
.headers
->HasHeaderValue("Content-Type", "text/plain"));
368 EXPECT_FALSE(response_
.response_time
.is_null());
369 EXPECT_FALSE(response_
.request_time
.is_null());
371 // There is no body, so this should return immediately.
372 EXPECT_EQ(0, stream_
->ReadResponseBody(read_buffer_
.get(),
373 read_buffer_
->size(),
374 callback_
.callback()));
375 EXPECT_TRUE(stream_
->IsResponseBodyComplete());
376 EXPECT_TRUE(AtEof());
379 // Regression test for http://crbug.com/288128
380 TEST_P(QuicHttpStreamTest
, GetRequestLargeResponse
) {
381 SetRequest("GET", "/", DEFAULT_PRIORITY
);
382 AddWrite(ConstructRequestHeadersPacket(1, kFin
, DEFAULT_PRIORITY
));
385 request_
.method
= "GET";
386 request_
.url
= GURL("http://www.google.com/");
388 EXPECT_EQ(OK
, stream_
->InitializeStream(&request_
, DEFAULT_PRIORITY
,
389 net_log_
, callback_
.callback()));
390 EXPECT_EQ(OK
, stream_
->SendRequest(headers_
, &response_
,
391 callback_
.callback()));
394 ProcessPacket(ConstructAckPacket(1, 0, 0));
396 EXPECT_EQ(ERR_IO_PENDING
,
397 stream_
->ReadResponseHeaders(callback_
.callback()));
399 SpdyHeaderBlock headers
;
400 headers
[":status"] = "200 OK";
401 headers
[":version"] = "HTTP/1.1";
402 headers
["content-type"] = "text/plain";
403 headers
["big6"] = std::string(10000, 'x'); // Lots of x's.
405 std::string response
=
406 SpdyUtils::SerializeUncompressedHeaders(headers
, GetParam());
407 EXPECT_LT(4096u, response
.length());
408 stream_
->OnDataReceived(response
.data(), response
.length());
409 stream_
->OnClose(QUIC_NO_ERROR
);
411 // Now that the headers have been processed, the callback will return.
412 EXPECT_EQ(OK
, callback_
.WaitForResult());
413 ASSERT_TRUE(response_
.headers
.get());
414 EXPECT_EQ(200, response_
.headers
->response_code());
415 EXPECT_TRUE(response_
.headers
->HasHeaderValue("Content-Type", "text/plain"));
417 // There is no body, so this should return immediately.
418 EXPECT_EQ(0, stream_
->ReadResponseBody(read_buffer_
.get(),
419 read_buffer_
->size(),
420 callback_
.callback()));
421 EXPECT_TRUE(stream_
->IsResponseBodyComplete());
422 EXPECT_TRUE(AtEof());
425 // Regression test for http://crbug.com/409101
426 TEST_P(QuicHttpStreamTest
, SessionClosedBeforeSendRequest
) {
427 SetRequest("GET", "/", DEFAULT_PRIORITY
);
430 request_
.method
= "GET";
431 request_
.url
= GURL("http://www.google.com/");
433 EXPECT_EQ(OK
, stream_
->InitializeStream(&request_
, DEFAULT_PRIORITY
,
434 net_log_
, callback_
.callback()));
436 session_
->connection()->CloseConnection(QUIC_NO_ERROR
, true);
438 EXPECT_EQ(ERR_CONNECTION_CLOSED
,
439 stream_
->SendRequest(headers_
, &response_
,
440 callback_
.callback()));
443 // Regression test for http://crbug.com/409871
444 TEST_P(QuicHttpStreamTest
, SessionClosedBeforeReadResponseHeaders
) {
445 SetRequest("GET", "/", DEFAULT_PRIORITY
);
446 AddWrite(ConstructRequestHeadersPacket(1, kFin
, DEFAULT_PRIORITY
));
449 request_
.method
= "GET";
450 request_
.url
= GURL("http://www.google.com/");
452 EXPECT_EQ(OK
, stream_
->InitializeStream(&request_
, DEFAULT_PRIORITY
,
453 net_log_
, callback_
.callback()));
455 EXPECT_EQ(OK
, stream_
->SendRequest(headers_
, &response_
,
456 callback_
.callback()));
458 session_
->connection()->CloseConnection(QUIC_NO_ERROR
, true);
460 EXPECT_NE(OK
, stream_
->ReadResponseHeaders(callback_
.callback()));
463 TEST_P(QuicHttpStreamTest
, SendPostRequest
) {
464 SetRequest("POST", "/", DEFAULT_PRIORITY
);
465 AddWrite(ConstructRequestHeadersPacket(1, !kFin
, DEFAULT_PRIORITY
));
466 AddWrite(ConstructDataPacket(2, kIncludeVersion
, kFin
, 0, kUploadData
));
467 AddWrite(ConstructAckPacket(3, 3, 1));
471 ScopedVector
<UploadElementReader
> element_readers
;
472 element_readers
.push_back(
473 new UploadBytesElementReader(kUploadData
, strlen(kUploadData
)));
474 ElementsUploadDataStream
upload_data_stream(element_readers
.Pass(), 0);
475 request_
.method
= "POST";
476 request_
.url
= GURL("http://www.google.com/");
477 request_
.upload_data_stream
= &upload_data_stream
;
478 ASSERT_EQ(OK
, request_
.upload_data_stream
->Init(CompletionCallback()));
480 EXPECT_EQ(OK
, stream_
->InitializeStream(&request_
, DEFAULT_PRIORITY
,
481 net_log_
, callback_
.callback()));
482 EXPECT_EQ(OK
, stream_
->SendRequest(headers_
, &response_
,
483 callback_
.callback()));
485 // Ack both packets in the request.
486 ProcessPacket(ConstructAckPacket(1, 0, 0));
488 // Send the response headers (but not the body).
489 SetResponse("200 OK", std::string());
490 ProcessPacket(ConstructResponseHeadersPacket(2, !kFin
));
492 // Since the headers have already arrived, this should return immediately.
493 EXPECT_EQ(OK
, stream_
->ReadResponseHeaders(callback_
.callback()));
494 ASSERT_TRUE(response_
.headers
.get());
495 EXPECT_EQ(200, response_
.headers
->response_code());
496 EXPECT_TRUE(response_
.headers
->HasHeaderValue("Content-Type", "text/plain"));
498 // Send the response body.
499 const char kResponseBody
[] = "Hello world!";
500 ProcessPacket(ConstructDataPacket(3, false, kFin
, 0, kResponseBody
));
501 // Since the body has already arrived, this should return immediately.
502 EXPECT_EQ(static_cast<int>(strlen(kResponseBody
)),
503 stream_
->ReadResponseBody(read_buffer_
.get(), read_buffer_
->size(),
504 callback_
.callback()));
506 EXPECT_TRUE(stream_
->IsResponseBodyComplete());
507 EXPECT_TRUE(AtEof());
510 TEST_P(QuicHttpStreamTest
, SendChunkedPostRequest
) {
511 SetRequest("POST", "/", DEFAULT_PRIORITY
);
512 size_t chunk_size
= strlen(kUploadData
);
513 AddWrite(ConstructRequestHeadersPacket(1, !kFin
, DEFAULT_PRIORITY
));
514 AddWrite(ConstructDataPacket(2, kIncludeVersion
, !kFin
, 0, kUploadData
));
515 AddWrite(ConstructDataPacket(3, kIncludeVersion
, kFin
, chunk_size
,
517 AddWrite(ConstructAckPacket(4, 3, 1));
520 ChunkedUploadDataStream
upload_data_stream(0);
521 upload_data_stream
.AppendData(kUploadData
, chunk_size
, false);
523 request_
.method
= "POST";
524 request_
.url
= GURL("http://www.google.com/");
525 request_
.upload_data_stream
= &upload_data_stream
;
526 ASSERT_EQ(OK
, request_
.upload_data_stream
->Init(
527 TestCompletionCallback().callback()));
529 ASSERT_EQ(OK
, stream_
->InitializeStream(&request_
, DEFAULT_PRIORITY
,
530 net_log_
, callback_
.callback()));
531 ASSERT_EQ(ERR_IO_PENDING
, stream_
->SendRequest(headers_
, &response_
,
532 callback_
.callback()));
534 upload_data_stream
.AppendData(kUploadData
, chunk_size
, true);
536 // Ack both packets in the request.
537 ProcessPacket(ConstructAckPacket(1, 0, 0));
539 // Send the response headers (but not the body).
540 SetResponse("200 OK", std::string());
541 ProcessPacket(ConstructResponseHeadersPacket(2, !kFin
));
543 // Since the headers have already arrived, this should return immediately.
544 ASSERT_EQ(OK
, stream_
->ReadResponseHeaders(callback_
.callback()));
545 ASSERT_TRUE(response_
.headers
.get());
546 EXPECT_EQ(200, response_
.headers
->response_code());
547 EXPECT_TRUE(response_
.headers
->HasHeaderValue("Content-Type", "text/plain"));
549 // Send the response body.
550 const char kResponseBody
[] = "Hello world!";
551 ProcessPacket(ConstructDataPacket(3, false, kFin
, response_data_
.length(),
554 // Since the body has already arrived, this should return immediately.
555 ASSERT_EQ(static_cast<int>(strlen(kResponseBody
)),
556 stream_
->ReadResponseBody(read_buffer_
.get(), read_buffer_
->size(),
557 callback_
.callback()));
559 EXPECT_TRUE(stream_
->IsResponseBodyComplete());
560 EXPECT_TRUE(AtEof());
563 TEST_P(QuicHttpStreamTest
, SendChunkedPostRequestWithFinalEmptyDataPacket
) {
564 SetRequest("POST", "/", DEFAULT_PRIORITY
);
565 size_t chunk_size
= strlen(kUploadData
);
566 AddWrite(ConstructRequestHeadersPacket(1, !kFin
, DEFAULT_PRIORITY
));
567 AddWrite(ConstructDataPacket(2, kIncludeVersion
, !kFin
, 0, kUploadData
));
568 AddWrite(ConstructDataPacket(3, kIncludeVersion
, kFin
, chunk_size
, ""));
569 AddWrite(ConstructAckPacket(4, 3, 1));
572 ChunkedUploadDataStream
upload_data_stream(0);
573 upload_data_stream
.AppendData(kUploadData
, chunk_size
, false);
575 request_
.method
= "POST";
576 request_
.url
= GURL("http://www.google.com/");
577 request_
.upload_data_stream
= &upload_data_stream
;
578 ASSERT_EQ(OK
, request_
.upload_data_stream
->Init(
579 TestCompletionCallback().callback()));
581 ASSERT_EQ(OK
, stream_
->InitializeStream(&request_
, DEFAULT_PRIORITY
,
582 net_log_
, callback_
.callback()));
583 ASSERT_EQ(ERR_IO_PENDING
, stream_
->SendRequest(headers_
, &response_
,
584 callback_
.callback()));
586 upload_data_stream
.AppendData(nullptr, 0, true);
588 ProcessPacket(ConstructAckPacket(1, 0, 0));
590 // Send the response headers (but not the body).
591 SetResponse("200 OK", std::string());
592 ProcessPacket(ConstructResponseHeadersPacket(2, !kFin
));
594 // Since the headers have already arrived, this should return immediately.
595 ASSERT_EQ(OK
, stream_
->ReadResponseHeaders(callback_
.callback()));
596 ASSERT_TRUE(response_
.headers
.get());
597 EXPECT_EQ(200, response_
.headers
->response_code());
598 EXPECT_TRUE(response_
.headers
->HasHeaderValue("Content-Type", "text/plain"));
600 // Send the response body.
601 const char kResponseBody
[] = "Hello world!";
602 ProcessPacket(ConstructDataPacket(3, false, kFin
, response_data_
.length(),
605 // Since the body has already arrived, this should return immediately.
606 ASSERT_EQ(static_cast<int>(strlen(kResponseBody
)),
607 stream_
->ReadResponseBody(read_buffer_
.get(), read_buffer_
->size(),
608 callback_
.callback()));
610 EXPECT_TRUE(stream_
->IsResponseBodyComplete());
611 EXPECT_TRUE(AtEof());
614 TEST_P(QuicHttpStreamTest
, SendChunkedPostRequestWithOneEmptyDataPacket
) {
615 SetRequest("POST", "/", DEFAULT_PRIORITY
);
616 AddWrite(ConstructRequestHeadersPacket(1, !kFin
, DEFAULT_PRIORITY
));
617 AddWrite(ConstructDataPacket(2, kIncludeVersion
, kFin
, 0, ""));
618 AddWrite(ConstructAckPacket(3, 3, 1));
621 ChunkedUploadDataStream
upload_data_stream(0);
623 request_
.method
= "POST";
624 request_
.url
= GURL("http://www.google.com/");
625 request_
.upload_data_stream
= &upload_data_stream
;
626 ASSERT_EQ(OK
, request_
.upload_data_stream
->Init(
627 TestCompletionCallback().callback()));
629 ASSERT_EQ(OK
, stream_
->InitializeStream(&request_
, DEFAULT_PRIORITY
,
630 net_log_
, callback_
.callback()));
631 ASSERT_EQ(ERR_IO_PENDING
, stream_
->SendRequest(headers_
, &response_
,
632 callback_
.callback()));
634 upload_data_stream
.AppendData(nullptr, 0, true);
636 ProcessPacket(ConstructAckPacket(1, 0, 0));
638 // Send the response headers (but not the body).
639 SetResponse("200 OK", std::string());
640 ProcessPacket(ConstructResponseHeadersPacket(2, !kFin
));
642 // Since the headers have already arrived, this should return immediately.
643 ASSERT_EQ(OK
, stream_
->ReadResponseHeaders(callback_
.callback()));
644 ASSERT_TRUE(response_
.headers
.get());
645 EXPECT_EQ(200, response_
.headers
->response_code());
646 EXPECT_TRUE(response_
.headers
->HasHeaderValue("Content-Type", "text/plain"));
648 // Send the response body.
649 const char kResponseBody
[] = "Hello world!";
650 ProcessPacket(ConstructDataPacket(3, false, kFin
, response_data_
.length(),
653 // Since the body has already arrived, this should return immediately.
654 ASSERT_EQ(static_cast<int>(strlen(kResponseBody
)),
655 stream_
->ReadResponseBody(read_buffer_
.get(), read_buffer_
->size(),
656 callback_
.callback()));
658 EXPECT_TRUE(stream_
->IsResponseBodyComplete());
659 EXPECT_TRUE(AtEof());
662 TEST_P(QuicHttpStreamTest
, DestroyedEarly
) {
663 SetRequest("GET", "/", DEFAULT_PRIORITY
);
664 AddWrite(ConstructRequestHeadersPacket(1, kFin
, DEFAULT_PRIORITY
));
665 AddWrite(ConstructAckAndRstStreamPacket(2));
666 use_closing_stream_
= true;
669 request_
.method
= "GET";
670 request_
.url
= GURL("http://www.google.com/");
672 EXPECT_EQ(OK
, stream_
->InitializeStream(&request_
, DEFAULT_PRIORITY
,
673 net_log_
, callback_
.callback()));
674 EXPECT_EQ(OK
, stream_
->SendRequest(headers_
, &response_
,
675 callback_
.callback()));
678 ProcessPacket(ConstructAckPacket(1, 0, 0));
679 EXPECT_EQ(ERR_IO_PENDING
,
680 stream_
->ReadResponseHeaders(callback_
.callback()));
682 // Send the response with a body.
683 SetResponse("404 OK", "hello world!");
684 // In the course of processing this packet, the QuicHttpStream close itself.
685 ProcessPacket(ConstructResponseHeadersPacket(2, kFin
));
687 EXPECT_TRUE(AtEof());
690 TEST_P(QuicHttpStreamTest
, Priority
) {
691 SetRequest("GET", "/", MEDIUM
);
692 AddWrite(ConstructRequestHeadersPacket(1, kFin
, MEDIUM
));
693 AddWrite(ConstructAckAndRstStreamPacket(2));
694 use_closing_stream_
= true;
697 request_
.method
= "GET";
698 request_
.url
= GURL("http://www.google.com/");
700 EXPECT_EQ(OK
, stream_
->InitializeStream(&request_
, MEDIUM
,
701 net_log_
, callback_
.callback()));
703 // Check that priority is highest.
704 QuicReliableClientStream
* reliable_stream
=
705 QuicHttpStreamPeer::GetQuicReliableClientStream(stream_
.get());
706 DCHECK(reliable_stream
);
707 DCHECK_EQ(QuicWriteBlockedList::kHighestPriority
,
708 reliable_stream
->EffectivePriority());
710 EXPECT_EQ(OK
, stream_
->SendRequest(headers_
, &response_
,
711 callback_
.callback()));
713 // Check that priority has now dropped back to MEDIUM.
714 DCHECK_EQ(MEDIUM
, ConvertQuicPriorityToRequestPriority(
715 reliable_stream
->EffectivePriority()));
718 ProcessPacket(ConstructAckPacket(1, 0, 0));
719 EXPECT_EQ(ERR_IO_PENDING
,
720 stream_
->ReadResponseHeaders(callback_
.callback()));
722 // Send the response with a body.
723 SetResponse("404 OK", "hello world!");
724 // In the course of processing this packet, the QuicHttpStream close itself.
725 ProcessPacket(ConstructResponseHeadersPacket(2, kFin
));
727 EXPECT_TRUE(AtEof());
730 // Regression test for http://crbug.com/294870
731 TEST_P(QuicHttpStreamTest
, CheckPriorityWithNoDelegate
) {
732 SetRequest("GET", "/", MEDIUM
);
733 use_closing_stream_
= true;
735 AddWrite(ConstructRstStreamPacket(1));
739 request_
.method
= "GET";
740 request_
.url
= GURL("http://www.google.com/");
742 EXPECT_EQ(OK
, stream_
->InitializeStream(&request_
, MEDIUM
,
743 net_log_
, callback_
.callback()));
745 // Check that priority is highest.
746 QuicReliableClientStream
* reliable_stream
=
747 QuicHttpStreamPeer::GetQuicReliableClientStream(stream_
.get());
748 DCHECK(reliable_stream
);
749 QuicReliableClientStream::Delegate
* delegate
= reliable_stream
->GetDelegate();
751 DCHECK_EQ(QuicWriteBlockedList::kHighestPriority
,
752 reliable_stream
->EffectivePriority());
754 // Set Delegate to nullptr and make sure EffectivePriority returns highest
756 reliable_stream
->SetDelegate(nullptr);
757 DCHECK_EQ(QuicWriteBlockedList::kHighestPriority
,
758 reliable_stream
->EffectivePriority());
759 reliable_stream
->SetDelegate(delegate
);