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"
11 #include "base/thread_task_runner_handle.h"
12 #include "net/base/chunked_upload_data_stream.h"
13 #include "net/base/elements_upload_data_stream.h"
14 #include "net/base/net_errors.h"
15 #include "net/base/test_completion_callback.h"
16 #include "net/base/upload_bytes_element_reader.h"
17 #include "net/http/http_response_headers.h"
18 #include "net/http/transport_security_state.h"
19 #include "net/quic/congestion_control/send_algorithm_interface.h"
20 #include "net/quic/crypto/crypto_protocol.h"
21 #include "net/quic/crypto/quic_decrypter.h"
22 #include "net/quic/crypto/quic_encrypter.h"
23 #include "net/quic/crypto/quic_server_info.h"
24 #include "net/quic/quic_chromium_client_session.h"
25 #include "net/quic/quic_connection.h"
26 #include "net/quic/quic_connection_helper.h"
27 #include "net/quic/quic_default_packet_writer.h"
28 #include "net/quic/quic_flags.h"
29 #include "net/quic/quic_http_utils.h"
30 #include "net/quic/quic_reliable_client_stream.h"
31 #include "net/quic/quic_write_blocked_list.h"
32 #include "net/quic/spdy_utils.h"
33 #include "net/quic/test_tools/mock_clock.h"
34 #include "net/quic/test_tools/mock_crypto_client_stream_factory.h"
35 #include "net/quic/test_tools/mock_random.h"
36 #include "net/quic/test_tools/quic_connection_peer.h"
37 #include "net/quic/test_tools/quic_test_packet_maker.h"
38 #include "net/quic/test_tools/quic_test_utils.h"
39 #include "net/quic/test_tools/test_task_runner.h"
40 #include "net/socket/socket_test_util.h"
41 #include "net/spdy/spdy_frame_builder.h"
42 #include "net/spdy/spdy_framer.h"
43 #include "net/spdy/spdy_http_utils.h"
44 #include "net/spdy/spdy_protocol.h"
45 #include "testing/gmock/include/gmock/gmock.h"
46 #include "testing/gtest/include/gtest/gtest.h"
49 using testing::AnyNumber
;
50 using testing::Return
;
56 const char kUploadData
[] = "Really nifty data!";
57 const char kDefaultServerHostName
[] = "www.google.com";
58 const uint16 kDefaultServerPort
= 80;
60 class TestQuicConnection
: public QuicConnection
{
62 TestQuicConnection(const QuicVersionVector
& versions
,
63 QuicConnectionId connection_id
,
65 QuicConnectionHelper
* helper
,
66 const QuicConnection::PacketWriterFactory
& writer_factory
)
67 : QuicConnection(connection_id
,
71 true /* owns_writer */,
72 Perspective::IS_CLIENT
,
73 false /* is_secure */,
76 void SetSendAlgorithm(SendAlgorithmInterface
* send_algorithm
) {
77 QuicConnectionPeer::SetSendAlgorithm(this, send_algorithm
);
81 // Subclass of QuicHttpStream that closes itself when the first piece of data
83 class AutoClosingStream
: public QuicHttpStream
{
85 explicit AutoClosingStream(
86 const base::WeakPtr
<QuicChromiumClientSession
>& session
)
87 : QuicHttpStream(session
) {}
89 void OnHeadersAvailable(const SpdyHeaderBlock
& headers
) override
{
93 void OnDataAvailable() override
{ Close(false); }
96 class TestPacketWriterFactory
: public QuicConnection::PacketWriterFactory
{
98 explicit TestPacketWriterFactory(DatagramClientSocket
* socket
)
100 ~TestPacketWriterFactory() override
{}
102 QuicPacketWriter
* Create(QuicConnection
* connection
) const override
{
103 return new QuicDefaultPacketWriter(socket_
);
107 DatagramClientSocket
* socket_
;
112 class QuicHttpStreamPeer
{
114 static QuicReliableClientStream
* GetQuicReliableClientStream(
115 QuicHttpStream
* stream
) {
116 return stream
->stream_
;
120 class QuicHttpStreamTest
: public ::testing::TestWithParam
<QuicVersion
> {
122 static const bool kFin
= true;
123 static const bool kIncludeVersion
= true;
124 static const bool kIncludeCongestionFeedback
= true;
126 // Holds a packet to be written to the wire, and the IO mode that should
127 // be used by the mock socket when performing the write.
128 struct PacketToWrite
{
129 PacketToWrite(IoMode mode
, QuicEncryptedPacket
* packet
)
134 QuicEncryptedPacket
* packet
;
138 : net_log_(BoundNetLog()),
139 use_closing_stream_(false),
140 read_buffer_(new IOBufferWithSize(4096)),
142 stream_id_(kClientDataStreamId1
),
143 maker_(GetParam(), connection_id_
, &clock_
, kDefaultServerHostName
),
144 random_generator_(0) {
146 CHECK(ParseIPLiteralToNumber("192.0.2.33", &ip
));
147 peer_addr_
= IPEndPoint(ip
, 443);
148 self_addr_
= IPEndPoint(ip
, 8435);
149 clock_
.AdvanceTime(QuicTime::Delta::FromMilliseconds(20));
152 ~QuicHttpStreamTest() {
153 session_
->CloseSessionOnError(ERR_ABORTED
, QUIC_INTERNAL_ERROR
);
154 for (size_t i
= 0; i
< writes_
.size(); i
++) {
155 delete writes_
[i
].packet
;
159 // Adds a packet to the list of expected writes.
160 void AddWrite(scoped_ptr
<QuicEncryptedPacket
> packet
) {
161 writes_
.push_back(PacketToWrite(SYNCHRONOUS
, packet
.release()));
164 // Returns the packet to be written at position |pos|.
165 QuicEncryptedPacket
* GetWrite(size_t pos
) {
166 return writes_
[pos
].packet
;
170 return socket_data_
->AllReadDataConsumed() &&
171 socket_data_
->AllWriteDataConsumed();
174 void ProcessPacket(scoped_ptr
<QuicEncryptedPacket
> packet
) {
175 connection_
->ProcessUdpPacket(self_addr_
, peer_addr_
, *packet
);
178 // Configures the test fixture to use the list of expected writes.
180 mock_writes_
.reset(new MockWrite
[writes_
.size()]);
181 for (size_t i
= 0; i
< writes_
.size(); i
++) {
182 mock_writes_
[i
] = MockWrite(writes_
[i
].mode
,
183 writes_
[i
].packet
->data(),
184 writes_
[i
].packet
->length());
187 socket_data_
.reset(new StaticSocketDataProvider(
188 nullptr, 0, mock_writes_
.get(), writes_
.size()));
190 MockUDPClientSocket
* socket
= new MockUDPClientSocket(socket_data_
.get(),
192 socket
->Connect(peer_addr_
);
193 runner_
= new TestTaskRunner(&clock_
);
194 send_algorithm_
= new MockSendAlgorithm();
195 EXPECT_CALL(*send_algorithm_
, InRecovery()).WillRepeatedly(Return(false));
196 EXPECT_CALL(*send_algorithm_
, InSlowStart()).WillRepeatedly(Return(false));
197 EXPECT_CALL(*send_algorithm_
,
198 OnPacketSent(_
, _
, _
, _
, _
)).WillRepeatedly(Return(true));
199 EXPECT_CALL(*send_algorithm_
, RetransmissionDelay())
200 .WillRepeatedly(Return(QuicTime::Delta::Zero()));
201 EXPECT_CALL(*send_algorithm_
, GetCongestionWindow())
202 .WillRepeatedly(Return(kMaxPacketSize
));
203 EXPECT_CALL(*send_algorithm_
, PacingRate())
204 .WillRepeatedly(Return(QuicBandwidth::Zero()));
205 EXPECT_CALL(*send_algorithm_
, TimeUntilSend(_
, _
, _
))
206 .WillRepeatedly(Return(QuicTime::Delta::Zero()));
207 EXPECT_CALL(*send_algorithm_
, BandwidthEstimate())
208 .WillRepeatedly(Return(QuicBandwidth::Zero()));
209 EXPECT_CALL(*send_algorithm_
, SetFromConfig(_
, _
)).Times(AnyNumber());
210 helper_
.reset(new QuicConnectionHelper(runner_
.get(), &clock_
,
211 &random_generator_
));
212 TestPacketWriterFactory
writer_factory(socket
);
213 connection_
= new TestQuicConnection(SupportedVersions(GetParam()),
214 connection_id_
, peer_addr_
,
215 helper_
.get(), writer_factory
);
216 connection_
->set_visitor(&visitor_
);
217 connection_
->SetSendAlgorithm(send_algorithm_
);
218 session_
.reset(new QuicChromiumClientSession(
219 connection_
, scoped_ptr
<DatagramClientSocket
>(socket
),
220 /*stream_factory=*/nullptr, &crypto_client_stream_factory_
,
221 &transport_security_state_
, make_scoped_ptr((QuicServerInfo
*)nullptr),
222 QuicServerId(kDefaultServerHostName
, kDefaultServerPort
,
223 /*is_secure=*/false, PRIVACY_MODE_DISABLED
),
224 /*cert_verify_flags=*/0, DefaultQuicConfig(), &crypto_config_
,
225 "CONNECTION_UNKNOWN", base::TimeTicks::Now(),
226 base::ThreadTaskRunnerHandle::Get().get(), nullptr));
227 session_
->Initialize();
228 session_
->GetCryptoStream()->CryptoConnect();
229 EXPECT_TRUE(session_
->IsCryptoHandshakeConfirmed());
230 stream_
.reset(use_closing_stream_
?
231 new AutoClosingStream(session_
->GetWeakPtr()) :
232 new QuicHttpStream(session_
->GetWeakPtr()));
235 void SetRequest(const std::string
& method
,
236 const std::string
& path
,
237 RequestPriority priority
) {
238 request_headers_
= maker_
.GetRequestHeaders(method
, "http", path
);
241 void SetResponse(const std::string
& status
, const std::string
& body
) {
242 response_headers_
= maker_
.GetResponseHeaders(status
);
243 response_data_
= body
;
246 scoped_ptr
<QuicEncryptedPacket
> ConstructDataPacket(
247 QuicPacketNumber packet_number
,
248 bool should_include_version
,
250 QuicStreamOffset offset
,
251 base::StringPiece data
) {
252 return maker_
.MakeDataPacket(packet_number
, stream_id_
,
253 should_include_version
, fin
, offset
, data
);
256 scoped_ptr
<QuicEncryptedPacket
> ConstructRequestHeadersPacket(
257 QuicPacketNumber packet_number
,
259 RequestPriority request_priority
) {
260 QuicPriority priority
=
261 ConvertRequestPriorityToQuicPriority(request_priority
);
262 return maker_
.MakeRequestHeadersPacket(packet_number
, stream_id_
,
263 kIncludeVersion
, fin
, priority
,
267 scoped_ptr
<QuicEncryptedPacket
> ConstructResponseHeadersPacket(
268 QuicPacketNumber packet_number
,
270 return maker_
.MakeResponseHeadersPacket(
271 packet_number
, stream_id_
, !kIncludeVersion
, fin
, response_headers_
);
274 scoped_ptr
<QuicEncryptedPacket
> ConstructRstStreamPacket(
275 QuicPacketNumber packet_number
) {
276 return maker_
.MakeRstPacket(
277 packet_number
, true, stream_id_
,
278 AdjustErrorForVersion(QUIC_RST_ACKNOWLEDGEMENT
, GetParam()));
281 scoped_ptr
<QuicEncryptedPacket
> ConstructRstStreamCancelledPacket(
282 QuicPacketNumber packet_number
) {
283 return maker_
.MakeRstPacket(packet_number
, !kIncludeVersion
, stream_id_
,
284 QUIC_STREAM_CANCELLED
);
287 scoped_ptr
<QuicEncryptedPacket
> ConstructAckAndRstStreamPacket(
288 QuicPacketNumber packet_number
) {
289 return maker_
.MakeAckAndRstPacket(packet_number
, !kIncludeVersion
,
290 stream_id_
, QUIC_STREAM_CANCELLED
, 2, 1,
291 !kIncludeCongestionFeedback
);
294 scoped_ptr
<QuicEncryptedPacket
> ConstructAckPacket(
295 QuicPacketNumber packet_number
,
296 QuicPacketNumber largest_received
,
297 QuicPacketNumber least_unacked
) {
298 return maker_
.MakeAckPacket(packet_number
, largest_received
, least_unacked
,
299 !kIncludeCongestionFeedback
);
302 BoundNetLog net_log_
;
303 bool use_closing_stream_
;
304 MockSendAlgorithm
* send_algorithm_
;
305 scoped_refptr
<TestTaskRunner
> runner_
;
306 scoped_ptr
<MockWrite
[]> mock_writes_
;
308 TestQuicConnection
* connection_
;
309 scoped_ptr
<QuicConnectionHelper
> helper_
;
310 testing::StrictMock
<MockConnectionVisitor
> visitor_
;
311 scoped_ptr
<QuicHttpStream
> stream_
;
312 TransportSecurityState transport_security_state_
;
313 scoped_ptr
<QuicChromiumClientSession
> session_
;
314 QuicCryptoClientConfig crypto_config_
;
315 TestCompletionCallback callback_
;
316 HttpRequestInfo request_
;
317 HttpRequestHeaders headers_
;
318 HttpResponseInfo response_
;
319 scoped_refptr
<IOBufferWithSize
> read_buffer_
;
320 SpdyHeaderBlock request_headers_
;
321 SpdyHeaderBlock response_headers_
;
322 std::string request_data_
;
323 std::string response_data_
;
326 const QuicConnectionId connection_id_
;
327 const QuicStreamId stream_id_
;
328 QuicTestPacketMaker maker_
;
329 IPEndPoint self_addr_
;
330 IPEndPoint peer_addr_
;
331 MockRandom random_generator_
;
332 MockCryptoClientStreamFactory crypto_client_stream_factory_
;
333 scoped_ptr
<StaticSocketDataProvider
> socket_data_
;
334 std::vector
<PacketToWrite
> writes_
;
337 INSTANTIATE_TEST_CASE_P(Version
, QuicHttpStreamTest
,
338 ::testing::ValuesIn(QuicSupportedVersions()));
340 TEST_P(QuicHttpStreamTest
, RenewStreamForAuth
) {
342 EXPECT_EQ(nullptr, stream_
->RenewStreamForAuth());
345 TEST_P(QuicHttpStreamTest
, CanReuseConnection
) {
347 EXPECT_FALSE(stream_
->CanReuseConnection());
350 TEST_P(QuicHttpStreamTest
, GetRequest
) {
351 SetRequest("GET", "/", DEFAULT_PRIORITY
);
352 AddWrite(ConstructRequestHeadersPacket(1, kFin
, DEFAULT_PRIORITY
));
355 request_
.method
= "GET";
356 request_
.url
= GURL("http://www.google.com/");
358 EXPECT_EQ(OK
, stream_
->InitializeStream(&request_
, DEFAULT_PRIORITY
,
359 net_log_
, callback_
.callback()));
360 EXPECT_EQ(OK
, stream_
->SendRequest(headers_
, &response_
,
361 callback_
.callback()));
364 ProcessPacket(ConstructAckPacket(1, 0, 0));
366 EXPECT_EQ(ERR_IO_PENDING
,
367 stream_
->ReadResponseHeaders(callback_
.callback()));
369 SetResponse("404 Not Found", std::string());
370 ProcessPacket(ConstructResponseHeadersPacket(2, kFin
));
372 // Now that the headers have been processed, the callback will return.
373 EXPECT_EQ(OK
, callback_
.WaitForResult());
374 ASSERT_TRUE(response_
.headers
.get());
375 EXPECT_EQ(404, response_
.headers
->response_code());
376 EXPECT_TRUE(response_
.headers
->HasHeaderValue("Content-Type", "text/plain"));
377 EXPECT_FALSE(response_
.response_time
.is_null());
378 EXPECT_FALSE(response_
.request_time
.is_null());
380 // There is no body, so this should return immediately.
381 EXPECT_EQ(0, stream_
->ReadResponseBody(read_buffer_
.get(),
382 read_buffer_
->size(),
383 callback_
.callback()));
384 EXPECT_TRUE(stream_
->IsResponseBodyComplete());
385 EXPECT_TRUE(AtEof());
387 // QuicHttpStream::GetTotalSent/ReceivedBytes currently only includes the
389 EXPECT_EQ(0, stream_
->GetTotalSentBytes());
390 EXPECT_EQ(0, stream_
->GetTotalReceivedBytes());
393 // Regression test for http://crbug.com/288128
394 TEST_P(QuicHttpStreamTest
, GetRequestLargeResponse
) {
395 SetRequest("GET", "/", DEFAULT_PRIORITY
);
396 AddWrite(ConstructRequestHeadersPacket(1, kFin
, DEFAULT_PRIORITY
));
399 request_
.method
= "GET";
400 request_
.url
= GURL("http://www.google.com/");
402 EXPECT_EQ(OK
, stream_
->InitializeStream(&request_
, DEFAULT_PRIORITY
,
403 net_log_
, callback_
.callback()));
404 EXPECT_EQ(OK
, stream_
->SendRequest(headers_
, &response_
,
405 callback_
.callback()));
408 ProcessPacket(ConstructAckPacket(1, 0, 0));
410 EXPECT_EQ(ERR_IO_PENDING
,
411 stream_
->ReadResponseHeaders(callback_
.callback()));
413 SpdyHeaderBlock headers
;
414 headers
[":status"] = "200 OK";
415 headers
[":version"] = "HTTP/1.1";
416 headers
["content-type"] = "text/plain";
417 headers
["big6"] = std::string(1000, 'x'); // Lots of x's.
419 response_headers_
= headers
;
420 ProcessPacket(ConstructResponseHeadersPacket(2, kFin
));
422 // Now that the headers have been processed, the callback will return.
423 EXPECT_EQ(OK
, callback_
.WaitForResult());
424 ASSERT_TRUE(response_
.headers
.get());
425 EXPECT_EQ(200, response_
.headers
->response_code());
426 EXPECT_TRUE(response_
.headers
->HasHeaderValue("Content-Type", "text/plain"));
428 // There is no body, so this should return immediately.
429 EXPECT_EQ(0, stream_
->ReadResponseBody(read_buffer_
.get(),
430 read_buffer_
->size(),
431 callback_
.callback()));
432 EXPECT_TRUE(stream_
->IsResponseBodyComplete());
433 EXPECT_TRUE(AtEof());
435 // QuicHttpStream::GetTotalSent/ReceivedBytes currently only includes the
437 EXPECT_EQ(0, stream_
->GetTotalSentBytes());
438 EXPECT_EQ(0, stream_
->GetTotalReceivedBytes());
441 // Regression test for http://crbug.com/409101
442 TEST_P(QuicHttpStreamTest
, SessionClosedBeforeSendRequest
) {
443 SetRequest("GET", "/", DEFAULT_PRIORITY
);
446 request_
.method
= "GET";
447 request_
.url
= GURL("http://www.google.com/");
449 EXPECT_EQ(OK
, stream_
->InitializeStream(&request_
, DEFAULT_PRIORITY
,
450 net_log_
, callback_
.callback()));
452 session_
->connection()->CloseConnection(QUIC_NO_ERROR
, true);
454 EXPECT_EQ(ERR_CONNECTION_CLOSED
,
455 stream_
->SendRequest(headers_
, &response_
,
456 callback_
.callback()));
458 EXPECT_EQ(0, stream_
->GetTotalSentBytes());
459 EXPECT_EQ(0, stream_
->GetTotalReceivedBytes());
462 // Regression test for http://crbug.com/409871
463 TEST_P(QuicHttpStreamTest
, SessionClosedBeforeReadResponseHeaders
) {
464 SetRequest("GET", "/", DEFAULT_PRIORITY
);
465 AddWrite(ConstructRequestHeadersPacket(1, kFin
, DEFAULT_PRIORITY
));
468 request_
.method
= "GET";
469 request_
.url
= GURL("http://www.google.com/");
471 EXPECT_EQ(OK
, stream_
->InitializeStream(&request_
, DEFAULT_PRIORITY
,
472 net_log_
, callback_
.callback()));
474 EXPECT_EQ(OK
, stream_
->SendRequest(headers_
, &response_
,
475 callback_
.callback()));
477 session_
->connection()->CloseConnection(QUIC_NO_ERROR
, true);
479 EXPECT_NE(OK
, stream_
->ReadResponseHeaders(callback_
.callback()));
481 // QuicHttpStream::GetTotalSent/ReceivedBytes currently only includes the
483 EXPECT_EQ(0, stream_
->GetTotalSentBytes());
484 EXPECT_EQ(0, stream_
->GetTotalReceivedBytes());
487 TEST_P(QuicHttpStreamTest
, SendPostRequest
) {
488 SetRequest("POST", "/", DEFAULT_PRIORITY
);
489 AddWrite(ConstructRequestHeadersPacket(1, !kFin
, DEFAULT_PRIORITY
));
490 AddWrite(ConstructDataPacket(2, kIncludeVersion
, kFin
, 0, kUploadData
));
491 AddWrite(ConstructAckPacket(3, 3, 1));
495 ScopedVector
<UploadElementReader
> element_readers
;
496 element_readers
.push_back(
497 new UploadBytesElementReader(kUploadData
, strlen(kUploadData
)));
498 ElementsUploadDataStream
upload_data_stream(element_readers
.Pass(), 0);
499 request_
.method
= "POST";
500 request_
.url
= GURL("http://www.google.com/");
501 request_
.upload_data_stream
= &upload_data_stream
;
502 ASSERT_EQ(OK
, request_
.upload_data_stream
->Init(CompletionCallback()));
504 EXPECT_EQ(OK
, stream_
->InitializeStream(&request_
, DEFAULT_PRIORITY
,
505 net_log_
, callback_
.callback()));
506 EXPECT_EQ(OK
, stream_
->SendRequest(headers_
, &response_
,
507 callback_
.callback()));
509 // Ack both packets in the request.
510 ProcessPacket(ConstructAckPacket(1, 0, 0));
512 // Send the response headers (but not the body).
513 SetResponse("200 OK", std::string());
514 ProcessPacket(ConstructResponseHeadersPacket(2, !kFin
));
516 // The headers have arrived, but they are delivered asynchronously.
517 EXPECT_EQ(ERR_IO_PENDING
, stream_
->ReadResponseHeaders(callback_
.callback()));
518 EXPECT_EQ(OK
, callback_
.WaitForResult());
519 ASSERT_TRUE(response_
.headers
.get());
520 EXPECT_EQ(200, response_
.headers
->response_code());
521 EXPECT_TRUE(response_
.headers
->HasHeaderValue("Content-Type", "text/plain"));
523 // Send the response body.
524 const char kResponseBody
[] = "Hello world!";
525 ProcessPacket(ConstructDataPacket(3, false, kFin
, 0, kResponseBody
));
526 // Since the body has already arrived, this should return immediately.
527 EXPECT_EQ(static_cast<int>(strlen(kResponseBody
)),
528 stream_
->ReadResponseBody(read_buffer_
.get(), read_buffer_
->size(),
529 callback_
.callback()));
531 EXPECT_TRUE(stream_
->IsResponseBodyComplete());
532 EXPECT_TRUE(AtEof());
534 // QuicHttpStream::GetTotalSent/ReceivedBytes currently only includes the
536 EXPECT_EQ(static_cast<int64_t>(strlen(kUploadData
)),
537 stream_
->GetTotalSentBytes());
538 EXPECT_EQ(static_cast<int64_t>(strlen(kResponseBody
)),
539 stream_
->GetTotalReceivedBytes());
542 TEST_P(QuicHttpStreamTest
, SendChunkedPostRequest
) {
543 SetRequest("POST", "/", DEFAULT_PRIORITY
);
544 size_t chunk_size
= strlen(kUploadData
);
545 AddWrite(ConstructRequestHeadersPacket(1, !kFin
, DEFAULT_PRIORITY
));
546 AddWrite(ConstructDataPacket(2, kIncludeVersion
, !kFin
, 0, kUploadData
));
547 AddWrite(ConstructDataPacket(3, kIncludeVersion
, kFin
, chunk_size
,
549 AddWrite(ConstructAckPacket(4, 3, 1));
552 ChunkedUploadDataStream
upload_data_stream(0);
553 upload_data_stream
.AppendData(kUploadData
, chunk_size
, false);
555 request_
.method
= "POST";
556 request_
.url
= GURL("http://www.google.com/");
557 request_
.upload_data_stream
= &upload_data_stream
;
558 ASSERT_EQ(OK
, request_
.upload_data_stream
->Init(
559 TestCompletionCallback().callback()));
561 ASSERT_EQ(OK
, stream_
->InitializeStream(&request_
, DEFAULT_PRIORITY
,
562 net_log_
, callback_
.callback()));
563 ASSERT_EQ(ERR_IO_PENDING
, stream_
->SendRequest(headers_
, &response_
,
564 callback_
.callback()));
566 upload_data_stream
.AppendData(kUploadData
, chunk_size
, true);
567 EXPECT_EQ(OK
, callback_
.WaitForResult());
569 // Ack both packets in the request.
570 ProcessPacket(ConstructAckPacket(1, 0, 0));
572 // Send the response headers (but not the body).
573 SetResponse("200 OK", std::string());
574 ProcessPacket(ConstructResponseHeadersPacket(2, !kFin
));
576 // The headers have arrived, but they are delivered asynchronously
577 EXPECT_EQ(ERR_IO_PENDING
, stream_
->ReadResponseHeaders(callback_
.callback()));
578 EXPECT_EQ(OK
, callback_
.WaitForResult());
579 ASSERT_TRUE(response_
.headers
.get());
580 EXPECT_EQ(200, response_
.headers
->response_code());
581 EXPECT_TRUE(response_
.headers
->HasHeaderValue("Content-Type", "text/plain"));
583 // Send the response body.
584 const char kResponseBody
[] = "Hello world!";
585 ProcessPacket(ConstructDataPacket(3, false, kFin
, response_data_
.length(),
588 // Since the body has already arrived, this should return immediately.
589 ASSERT_EQ(static_cast<int>(strlen(kResponseBody
)),
590 stream_
->ReadResponseBody(read_buffer_
.get(), read_buffer_
->size(),
591 callback_
.callback()));
593 EXPECT_TRUE(stream_
->IsResponseBodyComplete());
594 EXPECT_TRUE(AtEof());
596 // QuicHttpStream::GetTotalSent/ReceivedBytes currently only includes the
598 EXPECT_EQ(static_cast<int64_t>(strlen(kUploadData
) * 2),
599 stream_
->GetTotalSentBytes());
600 EXPECT_EQ(static_cast<int64_t>(strlen(kResponseBody
)),
601 stream_
->GetTotalReceivedBytes());
604 TEST_P(QuicHttpStreamTest
, SendChunkedPostRequestWithFinalEmptyDataPacket
) {
605 SetRequest("POST", "/", DEFAULT_PRIORITY
);
606 size_t chunk_size
= strlen(kUploadData
);
607 AddWrite(ConstructRequestHeadersPacket(1, !kFin
, DEFAULT_PRIORITY
));
608 AddWrite(ConstructDataPacket(2, kIncludeVersion
, !kFin
, 0, kUploadData
));
609 AddWrite(ConstructDataPacket(3, kIncludeVersion
, kFin
, chunk_size
, ""));
610 AddWrite(ConstructAckPacket(4, 3, 1));
613 ChunkedUploadDataStream
upload_data_stream(0);
614 upload_data_stream
.AppendData(kUploadData
, chunk_size
, false);
616 request_
.method
= "POST";
617 request_
.url
= GURL("http://www.google.com/");
618 request_
.upload_data_stream
= &upload_data_stream
;
619 ASSERT_EQ(OK
, request_
.upload_data_stream
->Init(
620 TestCompletionCallback().callback()));
622 ASSERT_EQ(OK
, stream_
->InitializeStream(&request_
, DEFAULT_PRIORITY
,
623 net_log_
, callback_
.callback()));
624 ASSERT_EQ(ERR_IO_PENDING
, stream_
->SendRequest(headers_
, &response_
,
625 callback_
.callback()));
627 upload_data_stream
.AppendData(nullptr, 0, true);
628 EXPECT_EQ(OK
, callback_
.WaitForResult());
630 ProcessPacket(ConstructAckPacket(1, 0, 0));
632 // Send the response headers (but not the body).
633 SetResponse("200 OK", std::string());
634 ProcessPacket(ConstructResponseHeadersPacket(2, !kFin
));
636 // The headers have arrived, but they are delivered asynchronously
637 EXPECT_EQ(ERR_IO_PENDING
, stream_
->ReadResponseHeaders(callback_
.callback()));
638 EXPECT_EQ(OK
, callback_
.WaitForResult());
639 ASSERT_TRUE(response_
.headers
.get());
640 EXPECT_EQ(200, response_
.headers
->response_code());
641 EXPECT_TRUE(response_
.headers
->HasHeaderValue("Content-Type", "text/plain"));
643 // Send the response body.
644 const char kResponseBody
[] = "Hello world!";
645 ProcessPacket(ConstructDataPacket(3, false, kFin
, response_data_
.length(),
648 // The body has arrived, but it is delivered asynchronously
649 ASSERT_EQ(static_cast<int>(strlen(kResponseBody
)),
650 stream_
->ReadResponseBody(read_buffer_
.get(), read_buffer_
->size(),
651 callback_
.callback()));
652 EXPECT_TRUE(stream_
->IsResponseBodyComplete());
653 EXPECT_TRUE(AtEof());
655 // QuicHttpStream::GetTotalSent/ReceivedBytes currently only includes the
657 EXPECT_EQ(static_cast<int64_t>(strlen(kUploadData
)),
658 stream_
->GetTotalSentBytes());
659 EXPECT_EQ(static_cast<int64_t>(strlen(kResponseBody
)),
660 stream_
->GetTotalReceivedBytes());
663 TEST_P(QuicHttpStreamTest
, SendChunkedPostRequestWithOneEmptyDataPacket
) {
664 SetRequest("POST", "/", DEFAULT_PRIORITY
);
665 AddWrite(ConstructRequestHeadersPacket(1, !kFin
, DEFAULT_PRIORITY
));
666 AddWrite(ConstructDataPacket(2, kIncludeVersion
, kFin
, 0, ""));
667 AddWrite(ConstructAckPacket(3, 3, 1));
670 ChunkedUploadDataStream
upload_data_stream(0);
672 request_
.method
= "POST";
673 request_
.url
= GURL("http://www.google.com/");
674 request_
.upload_data_stream
= &upload_data_stream
;
675 ASSERT_EQ(OK
, request_
.upload_data_stream
->Init(
676 TestCompletionCallback().callback()));
678 ASSERT_EQ(OK
, stream_
->InitializeStream(&request_
, DEFAULT_PRIORITY
,
679 net_log_
, callback_
.callback()));
680 ASSERT_EQ(ERR_IO_PENDING
, stream_
->SendRequest(headers_
, &response_
,
681 callback_
.callback()));
683 upload_data_stream
.AppendData(nullptr, 0, true);
684 EXPECT_EQ(OK
, callback_
.WaitForResult());
686 ProcessPacket(ConstructAckPacket(1, 0, 0));
688 // Send the response headers (but not the body).
689 SetResponse("200 OK", std::string());
690 ProcessPacket(ConstructResponseHeadersPacket(2, !kFin
));
692 // The headers have arrived, but they are delivered asynchronously
693 EXPECT_EQ(ERR_IO_PENDING
, stream_
->ReadResponseHeaders(callback_
.callback()));
694 EXPECT_EQ(OK
, callback_
.WaitForResult());
695 ASSERT_TRUE(response_
.headers
.get());
696 EXPECT_EQ(200, response_
.headers
->response_code());
697 EXPECT_TRUE(response_
.headers
->HasHeaderValue("Content-Type", "text/plain"));
699 // Send the response body.
700 const char kResponseBody
[] = "Hello world!";
701 ProcessPacket(ConstructDataPacket(3, false, kFin
, response_data_
.length(),
704 // The body has arrived, but it is delivered asynchronously
705 ASSERT_EQ(static_cast<int>(strlen(kResponseBody
)),
706 stream_
->ReadResponseBody(read_buffer_
.get(), read_buffer_
->size(),
707 callback_
.callback()));
709 EXPECT_TRUE(stream_
->IsResponseBodyComplete());
710 EXPECT_TRUE(AtEof());
712 // QuicHttpStream::GetTotalSent/ReceivedBytes currently only includes the
714 EXPECT_EQ(0, stream_
->GetTotalSentBytes());
715 EXPECT_EQ(static_cast<int64_t>(strlen(kResponseBody
)),
716 stream_
->GetTotalReceivedBytes());
719 TEST_P(QuicHttpStreamTest
, DestroyedEarly
) {
720 SetRequest("GET", "/", DEFAULT_PRIORITY
);
721 AddWrite(ConstructRequestHeadersPacket(1, kFin
, DEFAULT_PRIORITY
));
722 if (!FLAGS_quic_process_frames_inline
) {
723 AddWrite(ConstructRstStreamCancelledPacket(2));
725 AddWrite(ConstructAckAndRstStreamPacket(2));
727 use_closing_stream_
= true;
730 request_
.method
= "GET";
731 request_
.url
= GURL("http://www.google.com/");
733 EXPECT_EQ(OK
, stream_
->InitializeStream(&request_
, DEFAULT_PRIORITY
,
734 net_log_
, callback_
.callback()));
735 EXPECT_EQ(OK
, stream_
->SendRequest(headers_
, &response_
,
736 callback_
.callback()));
739 ProcessPacket(ConstructAckPacket(1, 0, 0));
740 EXPECT_EQ(ERR_IO_PENDING
,
741 stream_
->ReadResponseHeaders(callback_
.callback()));
743 // Send the response with a body.
744 SetResponse("404 OK", "hello world!");
745 // In the course of processing this packet, the QuicHttpStream close itself.
746 ProcessPacket(ConstructResponseHeadersPacket(2, kFin
));
748 base::MessageLoop::current()->RunUntilIdle();
750 EXPECT_TRUE(AtEof());
752 // QuicHttpStream::GetTotalSent/ReceivedBytes currently only includes the
754 EXPECT_EQ(0, stream_
->GetTotalSentBytes());
755 EXPECT_EQ(0, stream_
->GetTotalReceivedBytes());
758 TEST_P(QuicHttpStreamTest
, Priority
) {
759 SetRequest("GET", "/", MEDIUM
);
760 AddWrite(ConstructRequestHeadersPacket(1, kFin
, MEDIUM
));
761 if (!FLAGS_quic_process_frames_inline
) {
762 AddWrite(ConstructRstStreamCancelledPacket(2));
764 AddWrite(ConstructAckAndRstStreamPacket(2));
766 use_closing_stream_
= true;
769 request_
.method
= "GET";
770 request_
.url
= GURL("http://www.google.com/");
772 EXPECT_EQ(OK
, stream_
->InitializeStream(&request_
, MEDIUM
,
773 net_log_
, callback_
.callback()));
775 // Check that priority is highest.
776 QuicReliableClientStream
* reliable_stream
=
777 QuicHttpStreamPeer::GetQuicReliableClientStream(stream_
.get());
778 DCHECK(reliable_stream
);
779 DCHECK_EQ(QuicWriteBlockedList::kHighestPriority
,
780 reliable_stream
->EffectivePriority());
782 EXPECT_EQ(OK
, stream_
->SendRequest(headers_
, &response_
,
783 callback_
.callback()));
785 // Check that priority has now dropped back to MEDIUM.
786 DCHECK_EQ(MEDIUM
, ConvertQuicPriorityToRequestPriority(
787 reliable_stream
->EffectivePriority()));
790 ProcessPacket(ConstructAckPacket(1, 0, 0));
791 EXPECT_EQ(ERR_IO_PENDING
,
792 stream_
->ReadResponseHeaders(callback_
.callback()));
794 // Send the response with a body.
795 SetResponse("404 OK", "hello world!");
796 // In the course of processing this packet, the QuicHttpStream close itself.
797 ProcessPacket(ConstructResponseHeadersPacket(2, kFin
));
799 base::MessageLoop::current()->RunUntilIdle();
801 EXPECT_TRUE(AtEof());
803 // QuicHttpStream::GetTotalSent/ReceivedBytes currently only includes the
805 EXPECT_EQ(0, stream_
->GetTotalSentBytes());
806 EXPECT_EQ(0, stream_
->GetTotalReceivedBytes());
809 // Regression test for http://crbug.com/294870
810 TEST_P(QuicHttpStreamTest
, CheckPriorityWithNoDelegate
) {
811 SetRequest("GET", "/", MEDIUM
);
812 use_closing_stream_
= true;
814 AddWrite(ConstructRstStreamPacket(1));
818 request_
.method
= "GET";
819 request_
.url
= GURL("http://www.google.com/");
821 EXPECT_EQ(OK
, stream_
->InitializeStream(&request_
, MEDIUM
,
822 net_log_
, callback_
.callback()));
824 // Check that priority is highest.
825 QuicReliableClientStream
* reliable_stream
=
826 QuicHttpStreamPeer::GetQuicReliableClientStream(stream_
.get());
827 DCHECK(reliable_stream
);
828 QuicReliableClientStream::Delegate
* delegate
= reliable_stream
->GetDelegate();
830 DCHECK_EQ(QuicWriteBlockedList::kHighestPriority
,
831 reliable_stream
->EffectivePriority());
833 // Set Delegate to nullptr and make sure EffectivePriority returns highest
835 reliable_stream
->SetDelegate(nullptr);
836 DCHECK_EQ(QuicWriteBlockedList::kHighestPriority
,
837 reliable_stream
->EffectivePriority());
838 reliable_stream
->SetDelegate(delegate
);
840 // QuicHttpStream::GetTotalSent/ReceivedBytes currently only includes the
842 EXPECT_EQ(0, stream_
->GetTotalSentBytes());
843 EXPECT_EQ(0, stream_
->GetTotalReceivedBytes());