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_http_utils.h"
29 #include "net/quic/quic_reliable_client_stream.h"
30 #include "net/quic/quic_write_blocked_list.h"
31 #include "net/quic/spdy_utils.h"
32 #include "net/quic/test_tools/mock_clock.h"
33 #include "net/quic/test_tools/mock_crypto_client_stream_factory.h"
34 #include "net/quic/test_tools/mock_random.h"
35 #include "net/quic/test_tools/quic_connection_peer.h"
36 #include "net/quic/test_tools/quic_test_packet_maker.h"
37 #include "net/quic/test_tools/quic_test_utils.h"
38 #include "net/quic/test_tools/test_task_runner.h"
39 #include "net/socket/socket_test_util.h"
40 #include "net/spdy/spdy_frame_builder.h"
41 #include "net/spdy/spdy_framer.h"
42 #include "net/spdy/spdy_http_utils.h"
43 #include "net/spdy/spdy_protocol.h"
44 #include "testing/gmock/include/gmock/gmock.h"
45 #include "testing/gtest/include/gtest/gtest.h"
48 using testing::AnyNumber
;
49 using testing::Return
;
55 const char kUploadData
[] = "Really nifty data!";
56 const char kDefaultServerHostName
[] = "www.google.com";
57 const uint16 kDefaultServerPort
= 80;
59 class TestQuicConnection
: public QuicConnection
{
61 TestQuicConnection(const QuicVersionVector
& versions
,
62 QuicConnectionId connection_id
,
64 QuicConnectionHelper
* helper
,
65 const QuicConnection::PacketWriterFactory
& writer_factory
)
66 : QuicConnection(connection_id
,
70 true /* owns_writer */,
71 Perspective::IS_CLIENT
,
72 false /* is_secure */,
75 void SetSendAlgorithm(SendAlgorithmInterface
* send_algorithm
) {
76 QuicConnectionPeer::SetSendAlgorithm(this, send_algorithm
);
80 // Subclass of QuicHttpStream that closes itself when the first piece of data
82 class AutoClosingStream
: public QuicHttpStream
{
84 explicit AutoClosingStream(
85 const base::WeakPtr
<QuicChromiumClientSession
>& session
)
86 : QuicHttpStream(session
) {}
88 void OnHeadersAvailable(const SpdyHeaderBlock
& headers
) override
{
92 void OnDataAvailable() override
{ Close(false); }
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())
199 .WillRepeatedly(Return(QuicTime::Delta::Zero()));
200 EXPECT_CALL(*send_algorithm_
, GetCongestionWindow())
201 .WillRepeatedly(Return(kMaxPacketSize
));
202 EXPECT_CALL(*send_algorithm_
, PacingRate())
203 .WillRepeatedly(Return(QuicBandwidth::Zero()));
204 EXPECT_CALL(*send_algorithm_
, TimeUntilSend(_
, _
, _
))
205 .WillRepeatedly(Return(QuicTime::Delta::Zero()));
206 EXPECT_CALL(*send_algorithm_
, BandwidthEstimate())
207 .WillRepeatedly(Return(QuicBandwidth::Zero()));
208 EXPECT_CALL(*send_algorithm_
, SetFromConfig(_
, _
)).Times(AnyNumber());
209 helper_
.reset(new QuicConnectionHelper(runner_
.get(), &clock_
,
210 &random_generator_
));
211 TestPacketWriterFactory
writer_factory(socket
);
212 connection_
= new TestQuicConnection(SupportedVersions(GetParam()),
213 connection_id_
, peer_addr_
,
214 helper_
.get(), writer_factory
);
215 connection_
->set_visitor(&visitor_
);
216 connection_
->SetSendAlgorithm(send_algorithm_
);
217 session_
.reset(new QuicChromiumClientSession(
218 connection_
, scoped_ptr
<DatagramClientSocket
>(socket
),
219 /*stream_factory=*/nullptr, &crypto_client_stream_factory_
,
220 &transport_security_state_
, make_scoped_ptr((QuicServerInfo
*)nullptr),
221 QuicServerId(kDefaultServerHostName
, kDefaultServerPort
,
222 /*is_secure=*/false, PRIVACY_MODE_DISABLED
),
223 /*cert_verify_flags=*/0, DefaultQuicConfig(), &crypto_config_
,
224 "CONNECTION_UNKNOWN", base::TimeTicks::Now(),
225 base::ThreadTaskRunnerHandle::Get().get(), nullptr));
226 session_
->Initialize();
227 session_
->GetCryptoStream()->CryptoConnect();
228 EXPECT_TRUE(session_
->IsCryptoHandshakeConfirmed());
229 stream_
.reset(use_closing_stream_
?
230 new AutoClosingStream(session_
->GetWeakPtr()) :
231 new QuicHttpStream(session_
->GetWeakPtr()));
234 void SetRequest(const std::string
& method
,
235 const std::string
& path
,
236 RequestPriority priority
) {
237 request_headers_
= maker_
.GetRequestHeaders(method
, "http", path
);
240 void SetResponse(const std::string
& status
, const std::string
& body
) {
241 response_headers_
= maker_
.GetResponseHeaders(status
);
242 response_data_
= body
;
245 scoped_ptr
<QuicEncryptedPacket
> ConstructDataPacket(
246 QuicPacketNumber packet_number
,
247 bool should_include_version
,
249 QuicStreamOffset offset
,
250 base::StringPiece data
) {
251 return maker_
.MakeDataPacket(packet_number
, stream_id_
,
252 should_include_version
, fin
, offset
, data
);
255 scoped_ptr
<QuicEncryptedPacket
> ConstructRequestHeadersPacket(
256 QuicPacketNumber packet_number
,
258 RequestPriority request_priority
) {
259 QuicPriority priority
=
260 ConvertRequestPriorityToQuicPriority(request_priority
);
261 return maker_
.MakeRequestHeadersPacket(packet_number
, stream_id_
,
262 kIncludeVersion
, fin
, priority
,
266 scoped_ptr
<QuicEncryptedPacket
> ConstructResponseHeadersPacket(
267 QuicPacketNumber packet_number
,
269 return maker_
.MakeResponseHeadersPacket(
270 packet_number
, stream_id_
, !kIncludeVersion
, fin
, response_headers_
);
273 scoped_ptr
<QuicEncryptedPacket
> ConstructRstStreamPacket(
274 QuicPacketNumber packet_number
) {
275 return maker_
.MakeRstPacket(
276 packet_number
, true, stream_id_
,
277 AdjustErrorForVersion(QUIC_RST_ACKNOWLEDGEMENT
, GetParam()));
280 scoped_ptr
<QuicEncryptedPacket
> ConstructRstStreamCancelledPacket(
281 QuicPacketNumber packet_number
) {
282 return maker_
.MakeRstPacket(packet_number
, !kIncludeVersion
, stream_id_
,
283 QUIC_STREAM_CANCELLED
);
286 scoped_ptr
<QuicEncryptedPacket
> ConstructAckAndRstStreamPacket(
287 QuicPacketNumber packet_number
) {
288 return maker_
.MakeAckAndRstPacket(packet_number
, !kIncludeVersion
,
289 stream_id_
, QUIC_STREAM_CANCELLED
, 2, 1,
290 !kIncludeCongestionFeedback
);
293 scoped_ptr
<QuicEncryptedPacket
> ConstructAckPacket(
294 QuicPacketNumber packet_number
,
295 QuicPacketNumber largest_received
,
296 QuicPacketNumber least_unacked
) {
297 return maker_
.MakeAckPacket(packet_number
, largest_received
, least_unacked
,
298 !kIncludeCongestionFeedback
);
301 BoundNetLog net_log_
;
302 bool use_closing_stream_
;
303 MockSendAlgorithm
* send_algorithm_
;
304 scoped_refptr
<TestTaskRunner
> runner_
;
305 scoped_ptr
<MockWrite
[]> mock_writes_
;
307 TestQuicConnection
* connection_
;
308 scoped_ptr
<QuicConnectionHelper
> helper_
;
309 testing::StrictMock
<MockConnectionVisitor
> visitor_
;
310 scoped_ptr
<QuicHttpStream
> stream_
;
311 TransportSecurityState transport_security_state_
;
312 scoped_ptr
<QuicChromiumClientSession
> session_
;
313 QuicCryptoClientConfig crypto_config_
;
314 TestCompletionCallback callback_
;
315 HttpRequestInfo request_
;
316 HttpRequestHeaders headers_
;
317 HttpResponseInfo response_
;
318 scoped_refptr
<IOBufferWithSize
> read_buffer_
;
319 SpdyHeaderBlock request_headers_
;
320 SpdyHeaderBlock response_headers_
;
321 std::string request_data_
;
322 std::string response_data_
;
325 const QuicConnectionId connection_id_
;
326 const QuicStreamId stream_id_
;
327 QuicTestPacketMaker maker_
;
328 IPEndPoint self_addr_
;
329 IPEndPoint peer_addr_
;
330 MockRandom random_generator_
;
331 MockCryptoClientStreamFactory crypto_client_stream_factory_
;
332 scoped_ptr
<StaticSocketDataProvider
> socket_data_
;
333 std::vector
<PacketToWrite
> writes_
;
336 INSTANTIATE_TEST_CASE_P(Version
, QuicHttpStreamTest
,
337 ::testing::ValuesIn(QuicSupportedVersions()));
339 TEST_P(QuicHttpStreamTest
, RenewStreamForAuth
) {
341 EXPECT_EQ(nullptr, stream_
->RenewStreamForAuth());
344 TEST_P(QuicHttpStreamTest
, CanReuseConnection
) {
346 EXPECT_FALSE(stream_
->CanReuseConnection());
349 TEST_P(QuicHttpStreamTest
, GetRequest
) {
350 SetRequest("GET", "/", DEFAULT_PRIORITY
);
351 AddWrite(ConstructRequestHeadersPacket(1, kFin
, DEFAULT_PRIORITY
));
354 request_
.method
= "GET";
355 request_
.url
= GURL("http://www.google.com/");
357 EXPECT_EQ(OK
, stream_
->InitializeStream(&request_
, DEFAULT_PRIORITY
,
358 net_log_
, callback_
.callback()));
359 EXPECT_EQ(OK
, stream_
->SendRequest(headers_
, &response_
,
360 callback_
.callback()));
363 ProcessPacket(ConstructAckPacket(1, 0, 0));
365 EXPECT_EQ(ERR_IO_PENDING
,
366 stream_
->ReadResponseHeaders(callback_
.callback()));
368 SetResponse("404 Not Found", std::string());
369 ProcessPacket(ConstructResponseHeadersPacket(2, kFin
));
371 // Now that the headers have been processed, the callback will return.
372 EXPECT_EQ(OK
, callback_
.WaitForResult());
373 ASSERT_TRUE(response_
.headers
.get());
374 EXPECT_EQ(404, response_
.headers
->response_code());
375 EXPECT_TRUE(response_
.headers
->HasHeaderValue("Content-Type", "text/plain"));
376 EXPECT_FALSE(response_
.response_time
.is_null());
377 EXPECT_FALSE(response_
.request_time
.is_null());
379 // There is no body, so this should return immediately.
380 EXPECT_EQ(0, stream_
->ReadResponseBody(read_buffer_
.get(),
381 read_buffer_
->size(),
382 callback_
.callback()));
383 EXPECT_TRUE(stream_
->IsResponseBodyComplete());
384 EXPECT_TRUE(AtEof());
386 // QuicHttpStream::GetTotalSent/ReceivedBytes currently only includes the
388 EXPECT_EQ(0, stream_
->GetTotalSentBytes());
389 EXPECT_EQ(0, stream_
->GetTotalReceivedBytes());
392 // Regression test for http://crbug.com/288128
393 TEST_P(QuicHttpStreamTest
, GetRequestLargeResponse
) {
394 SetRequest("GET", "/", DEFAULT_PRIORITY
);
395 AddWrite(ConstructRequestHeadersPacket(1, kFin
, DEFAULT_PRIORITY
));
398 request_
.method
= "GET";
399 request_
.url
= GURL("http://www.google.com/");
401 EXPECT_EQ(OK
, stream_
->InitializeStream(&request_
, DEFAULT_PRIORITY
,
402 net_log_
, callback_
.callback()));
403 EXPECT_EQ(OK
, stream_
->SendRequest(headers_
, &response_
,
404 callback_
.callback()));
407 ProcessPacket(ConstructAckPacket(1, 0, 0));
409 EXPECT_EQ(ERR_IO_PENDING
,
410 stream_
->ReadResponseHeaders(callback_
.callback()));
412 SpdyHeaderBlock headers
;
413 headers
[":status"] = "200 OK";
414 headers
[":version"] = "HTTP/1.1";
415 headers
["content-type"] = "text/plain";
416 headers
["big6"] = std::string(1000, 'x'); // Lots of x's.
418 response_headers_
= headers
;
419 ProcessPacket(ConstructResponseHeadersPacket(2, kFin
));
421 // Now that the headers have been processed, the callback will return.
422 EXPECT_EQ(OK
, callback_
.WaitForResult());
423 ASSERT_TRUE(response_
.headers
.get());
424 EXPECT_EQ(200, response_
.headers
->response_code());
425 EXPECT_TRUE(response_
.headers
->HasHeaderValue("Content-Type", "text/plain"));
427 // There is no body, so this should return immediately.
428 EXPECT_EQ(0, stream_
->ReadResponseBody(read_buffer_
.get(),
429 read_buffer_
->size(),
430 callback_
.callback()));
431 EXPECT_TRUE(stream_
->IsResponseBodyComplete());
432 EXPECT_TRUE(AtEof());
434 // QuicHttpStream::GetTotalSent/ReceivedBytes currently only includes the
436 EXPECT_EQ(0, stream_
->GetTotalSentBytes());
437 EXPECT_EQ(0, stream_
->GetTotalReceivedBytes());
440 // Regression test for http://crbug.com/409101
441 TEST_P(QuicHttpStreamTest
, SessionClosedBeforeSendRequest
) {
442 SetRequest("GET", "/", DEFAULT_PRIORITY
);
445 request_
.method
= "GET";
446 request_
.url
= GURL("http://www.google.com/");
448 EXPECT_EQ(OK
, stream_
->InitializeStream(&request_
, DEFAULT_PRIORITY
,
449 net_log_
, callback_
.callback()));
451 session_
->connection()->CloseConnection(QUIC_NO_ERROR
, true);
453 EXPECT_EQ(ERR_CONNECTION_CLOSED
,
454 stream_
->SendRequest(headers_
, &response_
,
455 callback_
.callback()));
457 EXPECT_EQ(0, stream_
->GetTotalSentBytes());
458 EXPECT_EQ(0, stream_
->GetTotalReceivedBytes());
461 // Regression test for http://crbug.com/409871
462 TEST_P(QuicHttpStreamTest
, SessionClosedBeforeReadResponseHeaders
) {
463 SetRequest("GET", "/", DEFAULT_PRIORITY
);
464 AddWrite(ConstructRequestHeadersPacket(1, kFin
, DEFAULT_PRIORITY
));
467 request_
.method
= "GET";
468 request_
.url
= GURL("http://www.google.com/");
470 EXPECT_EQ(OK
, stream_
->InitializeStream(&request_
, DEFAULT_PRIORITY
,
471 net_log_
, callback_
.callback()));
473 EXPECT_EQ(OK
, stream_
->SendRequest(headers_
, &response_
,
474 callback_
.callback()));
476 session_
->connection()->CloseConnection(QUIC_NO_ERROR
, true);
478 EXPECT_NE(OK
, stream_
->ReadResponseHeaders(callback_
.callback()));
480 // QuicHttpStream::GetTotalSent/ReceivedBytes currently only includes the
482 EXPECT_EQ(0, stream_
->GetTotalSentBytes());
483 EXPECT_EQ(0, stream_
->GetTotalReceivedBytes());
486 TEST_P(QuicHttpStreamTest
, SendPostRequest
) {
487 SetRequest("POST", "/", DEFAULT_PRIORITY
);
488 AddWrite(ConstructRequestHeadersPacket(1, !kFin
, DEFAULT_PRIORITY
));
489 AddWrite(ConstructDataPacket(2, kIncludeVersion
, kFin
, 0, kUploadData
));
490 AddWrite(ConstructAckPacket(3, 3, 1));
494 ScopedVector
<UploadElementReader
> element_readers
;
495 element_readers
.push_back(
496 new UploadBytesElementReader(kUploadData
, strlen(kUploadData
)));
497 ElementsUploadDataStream
upload_data_stream(element_readers
.Pass(), 0);
498 request_
.method
= "POST";
499 request_
.url
= GURL("http://www.google.com/");
500 request_
.upload_data_stream
= &upload_data_stream
;
501 ASSERT_EQ(OK
, request_
.upload_data_stream
->Init(CompletionCallback()));
503 EXPECT_EQ(OK
, stream_
->InitializeStream(&request_
, DEFAULT_PRIORITY
,
504 net_log_
, callback_
.callback()));
505 EXPECT_EQ(OK
, stream_
->SendRequest(headers_
, &response_
,
506 callback_
.callback()));
508 // Ack both packets in the request.
509 ProcessPacket(ConstructAckPacket(1, 0, 0));
511 // Send the response headers (but not the body).
512 SetResponse("200 OK", std::string());
513 ProcessPacket(ConstructResponseHeadersPacket(2, !kFin
));
515 // The headers have arrived, but they are delivered asynchronously.
516 EXPECT_EQ(ERR_IO_PENDING
, stream_
->ReadResponseHeaders(callback_
.callback()));
517 EXPECT_EQ(OK
, callback_
.WaitForResult());
518 ASSERT_TRUE(response_
.headers
.get());
519 EXPECT_EQ(200, response_
.headers
->response_code());
520 EXPECT_TRUE(response_
.headers
->HasHeaderValue("Content-Type", "text/plain"));
522 // Send the response body.
523 const char kResponseBody
[] = "Hello world!";
524 ProcessPacket(ConstructDataPacket(3, false, kFin
, 0, kResponseBody
));
525 // Since the body has already arrived, this should return immediately.
526 EXPECT_EQ(static_cast<int>(strlen(kResponseBody
)),
527 stream_
->ReadResponseBody(read_buffer_
.get(), read_buffer_
->size(),
528 callback_
.callback()));
530 EXPECT_TRUE(stream_
->IsResponseBodyComplete());
531 EXPECT_TRUE(AtEof());
533 // QuicHttpStream::GetTotalSent/ReceivedBytes currently only includes the
535 EXPECT_EQ(static_cast<int64_t>(strlen(kUploadData
)),
536 stream_
->GetTotalSentBytes());
537 EXPECT_EQ(static_cast<int64_t>(strlen(kResponseBody
)),
538 stream_
->GetTotalReceivedBytes());
541 TEST_P(QuicHttpStreamTest
, SendChunkedPostRequest
) {
542 SetRequest("POST", "/", DEFAULT_PRIORITY
);
543 size_t chunk_size
= strlen(kUploadData
);
544 AddWrite(ConstructRequestHeadersPacket(1, !kFin
, DEFAULT_PRIORITY
));
545 AddWrite(ConstructDataPacket(2, kIncludeVersion
, !kFin
, 0, kUploadData
));
546 AddWrite(ConstructDataPacket(3, kIncludeVersion
, kFin
, chunk_size
,
548 AddWrite(ConstructAckPacket(4, 3, 1));
551 ChunkedUploadDataStream
upload_data_stream(0);
552 upload_data_stream
.AppendData(kUploadData
, chunk_size
, false);
554 request_
.method
= "POST";
555 request_
.url
= GURL("http://www.google.com/");
556 request_
.upload_data_stream
= &upload_data_stream
;
557 ASSERT_EQ(OK
, request_
.upload_data_stream
->Init(
558 TestCompletionCallback().callback()));
560 ASSERT_EQ(OK
, stream_
->InitializeStream(&request_
, DEFAULT_PRIORITY
,
561 net_log_
, callback_
.callback()));
562 ASSERT_EQ(ERR_IO_PENDING
, stream_
->SendRequest(headers_
, &response_
,
563 callback_
.callback()));
565 upload_data_stream
.AppendData(kUploadData
, chunk_size
, true);
566 EXPECT_EQ(OK
, callback_
.WaitForResult());
568 // Ack both packets in the request.
569 ProcessPacket(ConstructAckPacket(1, 0, 0));
571 // Send the response headers (but not the body).
572 SetResponse("200 OK", std::string());
573 ProcessPacket(ConstructResponseHeadersPacket(2, !kFin
));
575 // The headers have arrived, but they are delivered asynchronously
576 EXPECT_EQ(ERR_IO_PENDING
, stream_
->ReadResponseHeaders(callback_
.callback()));
577 EXPECT_EQ(OK
, callback_
.WaitForResult());
578 ASSERT_TRUE(response_
.headers
.get());
579 EXPECT_EQ(200, response_
.headers
->response_code());
580 EXPECT_TRUE(response_
.headers
->HasHeaderValue("Content-Type", "text/plain"));
582 // Send the response body.
583 const char kResponseBody
[] = "Hello world!";
584 ProcessPacket(ConstructDataPacket(3, false, kFin
, response_data_
.length(),
587 // Since the body has already arrived, this should return immediately.
588 ASSERT_EQ(static_cast<int>(strlen(kResponseBody
)),
589 stream_
->ReadResponseBody(read_buffer_
.get(), read_buffer_
->size(),
590 callback_
.callback()));
592 EXPECT_TRUE(stream_
->IsResponseBodyComplete());
593 EXPECT_TRUE(AtEof());
595 // QuicHttpStream::GetTotalSent/ReceivedBytes currently only includes the
597 EXPECT_EQ(static_cast<int64_t>(strlen(kUploadData
) * 2),
598 stream_
->GetTotalSentBytes());
599 EXPECT_EQ(static_cast<int64_t>(strlen(kResponseBody
)),
600 stream_
->GetTotalReceivedBytes());
603 TEST_P(QuicHttpStreamTest
, SendChunkedPostRequestWithFinalEmptyDataPacket
) {
604 SetRequest("POST", "/", DEFAULT_PRIORITY
);
605 size_t chunk_size
= strlen(kUploadData
);
606 AddWrite(ConstructRequestHeadersPacket(1, !kFin
, DEFAULT_PRIORITY
));
607 AddWrite(ConstructDataPacket(2, kIncludeVersion
, !kFin
, 0, kUploadData
));
608 AddWrite(ConstructDataPacket(3, kIncludeVersion
, kFin
, chunk_size
, ""));
609 AddWrite(ConstructAckPacket(4, 3, 1));
612 ChunkedUploadDataStream
upload_data_stream(0);
613 upload_data_stream
.AppendData(kUploadData
, chunk_size
, false);
615 request_
.method
= "POST";
616 request_
.url
= GURL("http://www.google.com/");
617 request_
.upload_data_stream
= &upload_data_stream
;
618 ASSERT_EQ(OK
, request_
.upload_data_stream
->Init(
619 TestCompletionCallback().callback()));
621 ASSERT_EQ(OK
, stream_
->InitializeStream(&request_
, DEFAULT_PRIORITY
,
622 net_log_
, callback_
.callback()));
623 ASSERT_EQ(ERR_IO_PENDING
, stream_
->SendRequest(headers_
, &response_
,
624 callback_
.callback()));
626 upload_data_stream
.AppendData(nullptr, 0, true);
627 EXPECT_EQ(OK
, callback_
.WaitForResult());
629 ProcessPacket(ConstructAckPacket(1, 0, 0));
631 // Send the response headers (but not the body).
632 SetResponse("200 OK", std::string());
633 ProcessPacket(ConstructResponseHeadersPacket(2, !kFin
));
635 // The headers have arrived, but they are delivered asynchronously
636 EXPECT_EQ(ERR_IO_PENDING
, stream_
->ReadResponseHeaders(callback_
.callback()));
637 EXPECT_EQ(OK
, callback_
.WaitForResult());
638 ASSERT_TRUE(response_
.headers
.get());
639 EXPECT_EQ(200, response_
.headers
->response_code());
640 EXPECT_TRUE(response_
.headers
->HasHeaderValue("Content-Type", "text/plain"));
642 // Send the response body.
643 const char kResponseBody
[] = "Hello world!";
644 ProcessPacket(ConstructDataPacket(3, false, kFin
, response_data_
.length(),
647 // The body has arrived, but it is delivered asynchronously
648 ASSERT_EQ(static_cast<int>(strlen(kResponseBody
)),
649 stream_
->ReadResponseBody(read_buffer_
.get(), read_buffer_
->size(),
650 callback_
.callback()));
651 EXPECT_TRUE(stream_
->IsResponseBodyComplete());
652 EXPECT_TRUE(AtEof());
654 // QuicHttpStream::GetTotalSent/ReceivedBytes currently only includes the
656 EXPECT_EQ(static_cast<int64_t>(strlen(kUploadData
)),
657 stream_
->GetTotalSentBytes());
658 EXPECT_EQ(static_cast<int64_t>(strlen(kResponseBody
)),
659 stream_
->GetTotalReceivedBytes());
662 TEST_P(QuicHttpStreamTest
, SendChunkedPostRequestWithOneEmptyDataPacket
) {
663 SetRequest("POST", "/", DEFAULT_PRIORITY
);
664 AddWrite(ConstructRequestHeadersPacket(1, !kFin
, DEFAULT_PRIORITY
));
665 AddWrite(ConstructDataPacket(2, kIncludeVersion
, kFin
, 0, ""));
666 AddWrite(ConstructAckPacket(3, 3, 1));
669 ChunkedUploadDataStream
upload_data_stream(0);
671 request_
.method
= "POST";
672 request_
.url
= GURL("http://www.google.com/");
673 request_
.upload_data_stream
= &upload_data_stream
;
674 ASSERT_EQ(OK
, request_
.upload_data_stream
->Init(
675 TestCompletionCallback().callback()));
677 ASSERT_EQ(OK
, stream_
->InitializeStream(&request_
, DEFAULT_PRIORITY
,
678 net_log_
, callback_
.callback()));
679 ASSERT_EQ(ERR_IO_PENDING
, stream_
->SendRequest(headers_
, &response_
,
680 callback_
.callback()));
682 upload_data_stream
.AppendData(nullptr, 0, true);
683 EXPECT_EQ(OK
, callback_
.WaitForResult());
685 ProcessPacket(ConstructAckPacket(1, 0, 0));
687 // Send the response headers (but not the body).
688 SetResponse("200 OK", std::string());
689 ProcessPacket(ConstructResponseHeadersPacket(2, !kFin
));
691 // The headers have arrived, but they are delivered asynchronously
692 EXPECT_EQ(ERR_IO_PENDING
, stream_
->ReadResponseHeaders(callback_
.callback()));
693 EXPECT_EQ(OK
, callback_
.WaitForResult());
694 ASSERT_TRUE(response_
.headers
.get());
695 EXPECT_EQ(200, response_
.headers
->response_code());
696 EXPECT_TRUE(response_
.headers
->HasHeaderValue("Content-Type", "text/plain"));
698 // Send the response body.
699 const char kResponseBody
[] = "Hello world!";
700 ProcessPacket(ConstructDataPacket(3, false, kFin
, response_data_
.length(),
703 // The body has arrived, but it is delivered asynchronously
704 ASSERT_EQ(static_cast<int>(strlen(kResponseBody
)),
705 stream_
->ReadResponseBody(read_buffer_
.get(), read_buffer_
->size(),
706 callback_
.callback()));
708 EXPECT_TRUE(stream_
->IsResponseBodyComplete());
709 EXPECT_TRUE(AtEof());
711 // QuicHttpStream::GetTotalSent/ReceivedBytes currently only includes the
713 EXPECT_EQ(0, stream_
->GetTotalSentBytes());
714 EXPECT_EQ(static_cast<int64_t>(strlen(kResponseBody
)),
715 stream_
->GetTotalReceivedBytes());
718 TEST_P(QuicHttpStreamTest
, DestroyedEarly
) {
719 SetRequest("GET", "/", DEFAULT_PRIORITY
);
720 AddWrite(ConstructRequestHeadersPacket(1, kFin
, DEFAULT_PRIORITY
));
721 AddWrite(ConstructAckAndRstStreamPacket(2));
722 use_closing_stream_
= true;
725 request_
.method
= "GET";
726 request_
.url
= GURL("http://www.google.com/");
728 EXPECT_EQ(OK
, stream_
->InitializeStream(&request_
, DEFAULT_PRIORITY
,
729 net_log_
, callback_
.callback()));
730 EXPECT_EQ(OK
, stream_
->SendRequest(headers_
, &response_
,
731 callback_
.callback()));
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 base::MessageLoop::current()->RunUntilIdle();
745 EXPECT_TRUE(AtEof());
747 // QuicHttpStream::GetTotalSent/ReceivedBytes currently only includes the
749 EXPECT_EQ(0, stream_
->GetTotalSentBytes());
750 EXPECT_EQ(0, stream_
->GetTotalReceivedBytes());
753 TEST_P(QuicHttpStreamTest
, Priority
) {
754 SetRequest("GET", "/", MEDIUM
);
755 AddWrite(ConstructRequestHeadersPacket(1, kFin
, MEDIUM
));
756 AddWrite(ConstructAckAndRstStreamPacket(2));
757 use_closing_stream_
= true;
760 request_
.method
= "GET";
761 request_
.url
= GURL("http://www.google.com/");
763 EXPECT_EQ(OK
, stream_
->InitializeStream(&request_
, MEDIUM
,
764 net_log_
, callback_
.callback()));
766 // Check that priority is highest.
767 QuicReliableClientStream
* reliable_stream
=
768 QuicHttpStreamPeer::GetQuicReliableClientStream(stream_
.get());
769 DCHECK(reliable_stream
);
770 DCHECK_EQ(QuicWriteBlockedList::kHighestPriority
,
771 reliable_stream
->EffectivePriority());
773 EXPECT_EQ(OK
, stream_
->SendRequest(headers_
, &response_
,
774 callback_
.callback()));
776 // Check that priority has now dropped back to MEDIUM.
777 DCHECK_EQ(MEDIUM
, ConvertQuicPriorityToRequestPriority(
778 reliable_stream
->EffectivePriority()));
781 ProcessPacket(ConstructAckPacket(1, 0, 0));
782 EXPECT_EQ(ERR_IO_PENDING
,
783 stream_
->ReadResponseHeaders(callback_
.callback()));
785 // Send the response with a body.
786 SetResponse("404 OK", "hello world!");
787 // In the course of processing this packet, the QuicHttpStream close itself.
788 ProcessPacket(ConstructResponseHeadersPacket(2, kFin
));
790 base::MessageLoop::current()->RunUntilIdle();
792 EXPECT_TRUE(AtEof());
794 // QuicHttpStream::GetTotalSent/ReceivedBytes currently only includes the
796 EXPECT_EQ(0, stream_
->GetTotalSentBytes());
797 EXPECT_EQ(0, stream_
->GetTotalReceivedBytes());
800 // Regression test for http://crbug.com/294870
801 TEST_P(QuicHttpStreamTest
, CheckPriorityWithNoDelegate
) {
802 SetRequest("GET", "/", MEDIUM
);
803 use_closing_stream_
= true;
805 AddWrite(ConstructRstStreamPacket(1));
809 request_
.method
= "GET";
810 request_
.url
= GURL("http://www.google.com/");
812 EXPECT_EQ(OK
, stream_
->InitializeStream(&request_
, MEDIUM
,
813 net_log_
, callback_
.callback()));
815 // Check that priority is highest.
816 QuicReliableClientStream
* reliable_stream
=
817 QuicHttpStreamPeer::GetQuicReliableClientStream(stream_
.get());
818 DCHECK(reliable_stream
);
819 QuicReliableClientStream::Delegate
* delegate
= reliable_stream
->GetDelegate();
821 DCHECK_EQ(QuicWriteBlockedList::kHighestPriority
,
822 reliable_stream
->EffectivePriority());
824 // Set Delegate to nullptr and make sure EffectivePriority returns highest
826 reliable_stream
->SetDelegate(nullptr);
827 DCHECK_EQ(QuicWriteBlockedList::kHighestPriority
,
828 reliable_stream
->EffectivePriority());
829 reliable_stream
->SetDelegate(delegate
);
831 // QuicHttpStream::GetTotalSent/ReceivedBytes currently only includes the
833 EXPECT_EQ(0, stream_
->GetTotalSentBytes());
834 EXPECT_EQ(0, stream_
->GetTotalReceivedBytes());