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 "net/base/chunked_upload_data_stream.h"
10 #include "net/base/elements_upload_data_stream.h"
11 #include "net/base/net_errors.h"
12 #include "net/base/test_completion_callback.h"
13 #include "net/base/upload_bytes_element_reader.h"
14 #include "net/http/http_response_headers.h"
15 #include "net/http/transport_security_state.h"
16 #include "net/quic/congestion_control/send_algorithm_interface.h"
17 #include "net/quic/crypto/crypto_protocol.h"
18 #include "net/quic/crypto/quic_decrypter.h"
19 #include "net/quic/crypto/quic_encrypter.h"
20 #include "net/quic/crypto/quic_server_info.h"
21 #include "net/quic/quic_client_session.h"
22 #include "net/quic/quic_connection.h"
23 #include "net/quic/quic_connection_helper.h"
24 #include "net/quic/quic_default_packet_writer.h"
25 #include "net/quic/quic_http_utils.h"
26 #include "net/quic/quic_reliable_client_stream.h"
27 #include "net/quic/quic_write_blocked_list.h"
28 #include "net/quic/spdy_utils.h"
29 #include "net/quic/test_tools/mock_clock.h"
30 #include "net/quic/test_tools/mock_crypto_client_stream_factory.h"
31 #include "net/quic/test_tools/mock_random.h"
32 #include "net/quic/test_tools/quic_connection_peer.h"
33 #include "net/quic/test_tools/quic_test_packet_maker.h"
34 #include "net/quic/test_tools/quic_test_utils.h"
35 #include "net/quic/test_tools/test_task_runner.h"
36 #include "net/socket/socket_test_util.h"
37 #include "net/spdy/spdy_frame_builder.h"
38 #include "net/spdy/spdy_framer.h"
39 #include "net/spdy/spdy_http_utils.h"
40 #include "net/spdy/spdy_protocol.h"
41 #include "testing/gmock/include/gmock/gmock.h"
42 #include "testing/gtest/include/gtest/gtest.h"
45 using testing::AnyNumber
;
46 using testing::Return
;
52 const char kUploadData
[] = "Really nifty data!";
53 const char kServerHostname
[] = "www.google.com";
54 const uint16 kServerPort
= 80;
56 class TestQuicConnection
: public QuicConnection
{
58 TestQuicConnection(const QuicVersionVector
& versions
,
59 QuicConnectionId connection_id
,
61 QuicConnectionHelper
* helper
,
62 const QuicConnection::PacketWriterFactory
& writer_factory
)
63 : QuicConnection(connection_id
,
67 true /* owns_writer */,
68 Perspective::IS_CLIENT
,
69 false /* is_secure */,
72 void SetSendAlgorithm(SendAlgorithmInterface
* send_algorithm
) {
73 QuicConnectionPeer::SetSendAlgorithm(this, send_algorithm
);
77 // Subclass of QuicHttpStream that closes itself when the first piece of data
79 class AutoClosingStream
: public QuicHttpStream
{
81 explicit AutoClosingStream(const base::WeakPtr
<QuicClientSession
>& session
)
82 : QuicHttpStream(session
) {
85 int OnDataReceived(const char* data
, int length
) override
{
91 class TestPacketWriterFactory
: public QuicConnection::PacketWriterFactory
{
93 explicit TestPacketWriterFactory(DatagramClientSocket
* socket
)
95 ~TestPacketWriterFactory() override
{}
97 QuicPacketWriter
* Create(QuicConnection
* connection
) const override
{
98 return new QuicDefaultPacketWriter(socket_
);
102 DatagramClientSocket
* socket_
;
107 class QuicHttpStreamPeer
{
109 static QuicReliableClientStream
* GetQuicReliableClientStream(
110 QuicHttpStream
* stream
) {
111 return stream
->stream_
;
115 class QuicHttpStreamTest
: public ::testing::TestWithParam
<QuicVersion
> {
117 static const bool kFin
= true;
118 static const bool kIncludeVersion
= true;
119 static const bool kIncludeCongestionFeedback
= true;
121 // Holds a packet to be written to the wire, and the IO mode that should
122 // be used by the mock socket when performing the write.
123 struct PacketToWrite
{
124 PacketToWrite(IoMode mode
, QuicEncryptedPacket
* packet
)
129 QuicEncryptedPacket
* packet
;
133 : net_log_(BoundNetLog()),
134 use_closing_stream_(false),
135 read_buffer_(new IOBufferWithSize(4096)),
137 stream_id_(kClientDataStreamId1
),
138 maker_(GetParam(), connection_id_
, &clock_
),
139 random_generator_(0) {
141 CHECK(ParseIPLiteralToNumber("192.0.2.33", &ip
));
142 peer_addr_
= IPEndPoint(ip
, 443);
143 self_addr_
= IPEndPoint(ip
, 8435);
144 clock_
.AdvanceTime(QuicTime::Delta::FromMilliseconds(20));
147 ~QuicHttpStreamTest() {
148 session_
->CloseSessionOnError(ERR_ABORTED
, QUIC_INTERNAL_ERROR
);
149 for (size_t i
= 0; i
< writes_
.size(); i
++) {
150 delete writes_
[i
].packet
;
154 // Adds a packet to the list of expected writes.
155 void AddWrite(scoped_ptr
<QuicEncryptedPacket
> packet
) {
156 writes_
.push_back(PacketToWrite(SYNCHRONOUS
, packet
.release()));
159 // Returns the packet to be written at position |pos|.
160 QuicEncryptedPacket
* GetWrite(size_t pos
) {
161 return writes_
[pos
].packet
;
165 return socket_data_
->at_read_eof() && socket_data_
->at_write_eof();
168 void ProcessPacket(scoped_ptr
<QuicEncryptedPacket
> packet
) {
169 connection_
->ProcessUdpPacket(self_addr_
, peer_addr_
, *packet
);
172 // Configures the test fixture to use the list of expected writes.
174 mock_writes_
.reset(new MockWrite
[writes_
.size()]);
175 for (size_t i
= 0; i
< writes_
.size(); i
++) {
176 mock_writes_
[i
] = MockWrite(writes_
[i
].mode
,
177 writes_
[i
].packet
->data(),
178 writes_
[i
].packet
->length());
181 socket_data_
.reset(new StaticSocketDataProvider(
182 nullptr, 0, mock_writes_
.get(), writes_
.size()));
184 MockUDPClientSocket
* socket
= new MockUDPClientSocket(socket_data_
.get(),
186 socket
->Connect(peer_addr_
);
187 runner_
= new TestTaskRunner(&clock_
);
188 send_algorithm_
= new MockSendAlgorithm();
189 EXPECT_CALL(*send_algorithm_
,
190 OnPacketSent(_
, _
, _
, _
, _
)).WillRepeatedly(Return(true));
191 EXPECT_CALL(*send_algorithm_
, RetransmissionDelay()).WillRepeatedly(
192 Return(QuicTime::Delta::Zero()));
193 EXPECT_CALL(*send_algorithm_
, GetCongestionWindow()).WillRepeatedly(
194 Return(kMaxPacketSize
));
195 EXPECT_CALL(*send_algorithm_
, TimeUntilSend(_
, _
, _
)).
196 WillRepeatedly(Return(QuicTime::Delta::Zero()));
197 EXPECT_CALL(*send_algorithm_
, BandwidthEstimate()).WillRepeatedly(
198 Return(QuicBandwidth::Zero()));
199 EXPECT_CALL(*send_algorithm_
, SetFromConfig(_
, _
)).Times(AnyNumber());
200 helper_
.reset(new QuicConnectionHelper(runner_
.get(), &clock_
,
201 &random_generator_
));
202 TestPacketWriterFactory
writer_factory(socket
);
203 connection_
= new TestQuicConnection(SupportedVersions(GetParam()),
204 connection_id_
, peer_addr_
,
205 helper_
.get(), writer_factory
);
206 connection_
->set_visitor(&visitor_
);
207 connection_
->SetSendAlgorithm(send_algorithm_
);
208 session_
.reset(new QuicClientSession(
209 connection_
, scoped_ptr
<DatagramClientSocket
>(socket
), nullptr,
210 &transport_security_state_
, make_scoped_ptr((QuicServerInfo
*)nullptr),
211 DefaultQuicConfig(), "CONNECTION_UNKNOWN", base::TimeTicks::Now(),
212 base::MessageLoop::current()->message_loop_proxy().get(), nullptr));
213 session_
->InitializeSession(QuicServerId(kServerHostname
, kServerPort
,
215 PRIVACY_MODE_DISABLED
),
217 &crypto_client_stream_factory_
);
218 session_
->GetCryptoStream()->CryptoConnect();
219 EXPECT_TRUE(session_
->IsCryptoHandshakeConfirmed());
220 stream_
.reset(use_closing_stream_
?
221 new AutoClosingStream(session_
->GetWeakPtr()) :
222 new QuicHttpStream(session_
->GetWeakPtr()));
225 void SetRequest(const std::string
& method
,
226 const std::string
& path
,
227 RequestPriority priority
) {
228 request_headers_
= maker_
.GetRequestHeaders(method
, "http", path
);
231 void SetResponse(const std::string
& status
, const std::string
& body
) {
232 response_headers_
= maker_
.GetResponseHeaders(status
);
233 response_data_
= body
;
236 scoped_ptr
<QuicEncryptedPacket
> ConstructDataPacket(
237 QuicPacketSequenceNumber sequence_number
,
238 bool should_include_version
,
240 QuicStreamOffset offset
,
241 base::StringPiece data
) {
242 return maker_
.MakeDataPacket(sequence_number
, stream_id_
,
243 should_include_version
, fin
, offset
, data
);
246 scoped_ptr
<QuicEncryptedPacket
> ConstructRequestHeadersPacket(
247 QuicPacketSequenceNumber sequence_number
,
249 RequestPriority request_priority
) {
250 QuicPriority priority
=
251 ConvertRequestPriorityToQuicPriority(request_priority
);
252 return maker_
.MakeRequestHeadersPacket(sequence_number
, stream_id_
,
253 kIncludeVersion
, fin
, priority
,
257 scoped_ptr
<QuicEncryptedPacket
> ConstructResponseHeadersPacket(
258 QuicPacketSequenceNumber sequence_number
,
260 return maker_
.MakeResponseHeadersPacket(
261 sequence_number
, stream_id_
, !kIncludeVersion
, fin
, response_headers_
);
264 scoped_ptr
<QuicEncryptedPacket
> ConstructRstStreamPacket(
265 QuicPacketSequenceNumber sequence_number
) {
266 return maker_
.MakeRstPacket(
267 sequence_number
, true, stream_id_
,
268 AdjustErrorForVersion(QUIC_RST_ACKNOWLEDGEMENT
, GetParam()));
271 scoped_ptr
<QuicEncryptedPacket
> ConstructAckAndRstStreamPacket(
272 QuicPacketSequenceNumber sequence_number
) {
273 return maker_
.MakeAckAndRstPacket(
274 sequence_number
, !kIncludeVersion
, stream_id_
, QUIC_STREAM_CANCELLED
,
275 2, 1, !kIncludeCongestionFeedback
);
278 scoped_ptr
<QuicEncryptedPacket
> ConstructAckPacket(
279 QuicPacketSequenceNumber sequence_number
,
280 QuicPacketSequenceNumber largest_received
,
281 QuicPacketSequenceNumber least_unacked
) {
282 return maker_
.MakeAckPacket(sequence_number
, largest_received
,
283 least_unacked
, !kIncludeCongestionFeedback
);
286 BoundNetLog net_log_
;
287 bool use_closing_stream_
;
288 MockSendAlgorithm
* send_algorithm_
;
289 scoped_refptr
<TestTaskRunner
> runner_
;
290 scoped_ptr
<MockWrite
[]> mock_writes_
;
292 TestQuicConnection
* connection_
;
293 scoped_ptr
<QuicConnectionHelper
> helper_
;
294 testing::StrictMock
<MockConnectionVisitor
> visitor_
;
295 scoped_ptr
<QuicHttpStream
> stream_
;
296 TransportSecurityState transport_security_state_
;
297 scoped_ptr
<QuicClientSession
> session_
;
298 QuicCryptoClientConfig crypto_config_
;
299 TestCompletionCallback callback_
;
300 HttpRequestInfo request_
;
301 HttpRequestHeaders headers_
;
302 HttpResponseInfo response_
;
303 scoped_refptr
<IOBufferWithSize
> read_buffer_
;
304 SpdyHeaderBlock request_headers_
;
305 SpdyHeaderBlock response_headers_
;
306 std::string request_data_
;
307 std::string response_data_
;
310 const QuicConnectionId connection_id_
;
311 const QuicStreamId stream_id_
;
312 QuicTestPacketMaker maker_
;
313 IPEndPoint self_addr_
;
314 IPEndPoint peer_addr_
;
315 MockRandom random_generator_
;
316 MockCryptoClientStreamFactory crypto_client_stream_factory_
;
317 scoped_ptr
<StaticSocketDataProvider
> socket_data_
;
318 std::vector
<PacketToWrite
> writes_
;
321 INSTANTIATE_TEST_CASE_P(Version
, QuicHttpStreamTest
,
322 ::testing::ValuesIn(QuicSupportedVersions()));
324 TEST_P(QuicHttpStreamTest
, RenewStreamForAuth
) {
326 EXPECT_EQ(nullptr, stream_
->RenewStreamForAuth());
329 TEST_P(QuicHttpStreamTest
, CanFindEndOfResponse
) {
331 EXPECT_TRUE(stream_
->CanFindEndOfResponse());
334 TEST_P(QuicHttpStreamTest
, IsConnectionReusable
) {
336 EXPECT_FALSE(stream_
->IsConnectionReusable());
339 TEST_P(QuicHttpStreamTest
, GetRequest
) {
340 SetRequest("GET", "/", DEFAULT_PRIORITY
);
341 AddWrite(ConstructRequestHeadersPacket(1, kFin
, DEFAULT_PRIORITY
));
344 request_
.method
= "GET";
345 request_
.url
= GURL("http://www.google.com/");
347 EXPECT_EQ(OK
, stream_
->InitializeStream(&request_
, DEFAULT_PRIORITY
,
348 net_log_
, callback_
.callback()));
349 EXPECT_EQ(OK
, stream_
->SendRequest(headers_
, &response_
,
350 callback_
.callback()));
353 ProcessPacket(ConstructAckPacket(1, 0, 0));
355 EXPECT_EQ(ERR_IO_PENDING
,
356 stream_
->ReadResponseHeaders(callback_
.callback()));
358 SetResponse("404 Not Found", std::string());
359 ProcessPacket(ConstructResponseHeadersPacket(2, kFin
));
361 // Now that the headers have been processed, the callback will return.
362 EXPECT_EQ(OK
, callback_
.WaitForResult());
363 ASSERT_TRUE(response_
.headers
.get());
364 EXPECT_EQ(404, response_
.headers
->response_code());
365 EXPECT_TRUE(response_
.headers
->HasHeaderValue("Content-Type", "text/plain"));
366 EXPECT_FALSE(response_
.response_time
.is_null());
367 EXPECT_FALSE(response_
.request_time
.is_null());
369 // There is no body, so this should return immediately.
370 EXPECT_EQ(0, stream_
->ReadResponseBody(read_buffer_
.get(),
371 read_buffer_
->size(),
372 callback_
.callback()));
373 EXPECT_TRUE(stream_
->IsResponseBodyComplete());
374 EXPECT_TRUE(AtEof());
377 // Regression test for http://crbug.com/288128
378 TEST_P(QuicHttpStreamTest
, GetRequestLargeResponse
) {
379 SetRequest("GET", "/", DEFAULT_PRIORITY
);
380 AddWrite(ConstructRequestHeadersPacket(1, kFin
, DEFAULT_PRIORITY
));
383 request_
.method
= "GET";
384 request_
.url
= GURL("http://www.google.com/");
386 EXPECT_EQ(OK
, stream_
->InitializeStream(&request_
, DEFAULT_PRIORITY
,
387 net_log_
, callback_
.callback()));
388 EXPECT_EQ(OK
, stream_
->SendRequest(headers_
, &response_
,
389 callback_
.callback()));
392 ProcessPacket(ConstructAckPacket(1, 0, 0));
394 EXPECT_EQ(ERR_IO_PENDING
,
395 stream_
->ReadResponseHeaders(callback_
.callback()));
397 SpdyHeaderBlock headers
;
398 headers
[":status"] = "200 OK";
399 headers
[":version"] = "HTTP/1.1";
400 headers
["content-type"] = "text/plain";
401 headers
["big6"] = std::string(10000, 'x'); // Lots of x's.
403 std::string response
= SpdyUtils::SerializeUncompressedHeaders(headers
);
404 EXPECT_LT(4096u, response
.length());
405 stream_
->OnDataReceived(response
.data(), response
.length());
406 stream_
->OnClose(QUIC_NO_ERROR
);
408 // Now that the headers have been processed, the callback will return.
409 EXPECT_EQ(OK
, callback_
.WaitForResult());
410 ASSERT_TRUE(response_
.headers
.get());
411 EXPECT_EQ(200, response_
.headers
->response_code());
412 EXPECT_TRUE(response_
.headers
->HasHeaderValue("Content-Type", "text/plain"));
414 // There is no body, so this should return immediately.
415 EXPECT_EQ(0, stream_
->ReadResponseBody(read_buffer_
.get(),
416 read_buffer_
->size(),
417 callback_
.callback()));
418 EXPECT_TRUE(stream_
->IsResponseBodyComplete());
419 EXPECT_TRUE(AtEof());
422 // Regression test for http://crbug.com/409101
423 TEST_P(QuicHttpStreamTest
, SessionClosedBeforeSendRequest
) {
424 SetRequest("GET", "/", DEFAULT_PRIORITY
);
427 request_
.method
= "GET";
428 request_
.url
= GURL("http://www.google.com/");
430 EXPECT_EQ(OK
, stream_
->InitializeStream(&request_
, DEFAULT_PRIORITY
,
431 net_log_
, callback_
.callback()));
433 session_
->connection()->CloseConnection(QUIC_NO_ERROR
, true);
435 EXPECT_EQ(ERR_CONNECTION_CLOSED
,
436 stream_
->SendRequest(headers_
, &response_
,
437 callback_
.callback()));
440 // Regression test for http://crbug.com/409871
441 TEST_P(QuicHttpStreamTest
, SessionClosedBeforeReadResponseHeaders
) {
442 SetRequest("GET", "/", DEFAULT_PRIORITY
);
443 AddWrite(ConstructRequestHeadersPacket(1, kFin
, 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 EXPECT_EQ(OK
, stream_
->SendRequest(headers_
, &response_
,
453 callback_
.callback()));
455 session_
->connection()->CloseConnection(QUIC_NO_ERROR
, true);
457 EXPECT_NE(OK
, stream_
->ReadResponseHeaders(callback_
.callback()));
460 TEST_P(QuicHttpStreamTest
, SendPostRequest
) {
461 SetRequest("POST", "/", DEFAULT_PRIORITY
);
462 AddWrite(ConstructRequestHeadersPacket(1, !kFin
, DEFAULT_PRIORITY
));
463 AddWrite(ConstructDataPacket(2, kIncludeVersion
, kFin
, 0, kUploadData
));
464 AddWrite(ConstructAckPacket(3, 3, 1));
468 ScopedVector
<UploadElementReader
> element_readers
;
469 element_readers
.push_back(
470 new UploadBytesElementReader(kUploadData
, strlen(kUploadData
)));
471 ElementsUploadDataStream
upload_data_stream(element_readers
.Pass(), 0);
472 request_
.method
= "POST";
473 request_
.url
= GURL("http://www.google.com/");
474 request_
.upload_data_stream
= &upload_data_stream
;
475 ASSERT_EQ(OK
, request_
.upload_data_stream
->Init(CompletionCallback()));
477 EXPECT_EQ(OK
, stream_
->InitializeStream(&request_
, DEFAULT_PRIORITY
,
478 net_log_
, callback_
.callback()));
479 EXPECT_EQ(OK
, stream_
->SendRequest(headers_
, &response_
,
480 callback_
.callback()));
482 // Ack both packets in the request.
483 ProcessPacket(ConstructAckPacket(1, 0, 0));
485 // Send the response headers (but not the body).
486 SetResponse("200 OK", std::string());
487 ProcessPacket(ConstructResponseHeadersPacket(2, !kFin
));
489 // Since the headers have already arrived, this should return immediately.
490 EXPECT_EQ(OK
, stream_
->ReadResponseHeaders(callback_
.callback()));
491 ASSERT_TRUE(response_
.headers
.get());
492 EXPECT_EQ(200, response_
.headers
->response_code());
493 EXPECT_TRUE(response_
.headers
->HasHeaderValue("Content-Type", "text/plain"));
495 // Send the response body.
496 const char kResponseBody
[] = "Hello world!";
497 ProcessPacket(ConstructDataPacket(3, false, kFin
, 0, kResponseBody
));
498 // Since the body has already arrived, this should return immediately.
499 EXPECT_EQ(static_cast<int>(strlen(kResponseBody
)),
500 stream_
->ReadResponseBody(read_buffer_
.get(), read_buffer_
->size(),
501 callback_
.callback()));
503 EXPECT_TRUE(stream_
->IsResponseBodyComplete());
504 EXPECT_TRUE(AtEof());
507 TEST_P(QuicHttpStreamTest
, SendChunkedPostRequest
) {
508 SetRequest("POST", "/", DEFAULT_PRIORITY
);
509 size_t chunk_size
= strlen(kUploadData
);
510 AddWrite(ConstructRequestHeadersPacket(1, !kFin
, DEFAULT_PRIORITY
));
511 AddWrite(ConstructDataPacket(2, kIncludeVersion
, !kFin
, 0, kUploadData
));
512 AddWrite(ConstructDataPacket(3, kIncludeVersion
, kFin
, chunk_size
,
514 AddWrite(ConstructAckPacket(4, 3, 1));
517 ChunkedUploadDataStream
upload_data_stream(0);
518 upload_data_stream
.AppendData(kUploadData
, chunk_size
, false);
520 request_
.method
= "POST";
521 request_
.url
= GURL("http://www.google.com/");
522 request_
.upload_data_stream
= &upload_data_stream
;
523 ASSERT_EQ(OK
, request_
.upload_data_stream
->Init(
524 TestCompletionCallback().callback()));
526 ASSERT_EQ(OK
, stream_
->InitializeStream(&request_
, DEFAULT_PRIORITY
,
527 net_log_
, callback_
.callback()));
528 ASSERT_EQ(ERR_IO_PENDING
, stream_
->SendRequest(headers_
, &response_
,
529 callback_
.callback()));
531 upload_data_stream
.AppendData(kUploadData
, chunk_size
, true);
533 // Ack both packets in the request.
534 ProcessPacket(ConstructAckPacket(1, 0, 0));
536 // Send the response headers (but not the body).
537 SetResponse("200 OK", std::string());
538 ProcessPacket(ConstructResponseHeadersPacket(2, !kFin
));
540 // Since the headers have already arrived, this should return immediately.
541 ASSERT_EQ(OK
, stream_
->ReadResponseHeaders(callback_
.callback()));
542 ASSERT_TRUE(response_
.headers
.get());
543 EXPECT_EQ(200, response_
.headers
->response_code());
544 EXPECT_TRUE(response_
.headers
->HasHeaderValue("Content-Type", "text/plain"));
546 // Send the response body.
547 const char kResponseBody
[] = "Hello world!";
548 ProcessPacket(ConstructDataPacket(3, false, kFin
, response_data_
.length(),
551 // Since the body has already arrived, this should return immediately.
552 ASSERT_EQ(static_cast<int>(strlen(kResponseBody
)),
553 stream_
->ReadResponseBody(read_buffer_
.get(), read_buffer_
->size(),
554 callback_
.callback()));
556 EXPECT_TRUE(stream_
->IsResponseBodyComplete());
557 EXPECT_TRUE(AtEof());
560 TEST_P(QuicHttpStreamTest
, SendChunkedPostRequestWithFinalEmptyDataPacket
) {
561 SetRequest("POST", "/", DEFAULT_PRIORITY
);
562 size_t chunk_size
= strlen(kUploadData
);
563 AddWrite(ConstructRequestHeadersPacket(1, !kFin
, DEFAULT_PRIORITY
));
564 AddWrite(ConstructDataPacket(2, kIncludeVersion
, !kFin
, 0, kUploadData
));
565 AddWrite(ConstructDataPacket(3, kIncludeVersion
, kFin
, chunk_size
, ""));
566 AddWrite(ConstructAckPacket(4, 3, 1));
569 ChunkedUploadDataStream
upload_data_stream(0);
570 upload_data_stream
.AppendData(kUploadData
, chunk_size
, false);
572 request_
.method
= "POST";
573 request_
.url
= GURL("http://www.google.com/");
574 request_
.upload_data_stream
= &upload_data_stream
;
575 ASSERT_EQ(OK
, request_
.upload_data_stream
->Init(
576 TestCompletionCallback().callback()));
578 ASSERT_EQ(OK
, stream_
->InitializeStream(&request_
, DEFAULT_PRIORITY
,
579 net_log_
, callback_
.callback()));
580 ASSERT_EQ(ERR_IO_PENDING
, stream_
->SendRequest(headers_
, &response_
,
581 callback_
.callback()));
583 upload_data_stream
.AppendData(nullptr, 0, true);
585 ProcessPacket(ConstructAckPacket(1, 0, 0));
587 // Send the response headers (but not the body).
588 SetResponse("200 OK", std::string());
589 ProcessPacket(ConstructResponseHeadersPacket(2, !kFin
));
591 // Since the headers have already arrived, this should return immediately.
592 ASSERT_EQ(OK
, stream_
->ReadResponseHeaders(callback_
.callback()));
593 ASSERT_TRUE(response_
.headers
.get());
594 EXPECT_EQ(200, response_
.headers
->response_code());
595 EXPECT_TRUE(response_
.headers
->HasHeaderValue("Content-Type", "text/plain"));
597 // Send the response body.
598 const char kResponseBody
[] = "Hello world!";
599 ProcessPacket(ConstructDataPacket(3, false, kFin
, response_data_
.length(),
602 // Since the body has already arrived, this should return immediately.
603 ASSERT_EQ(static_cast<int>(strlen(kResponseBody
)),
604 stream_
->ReadResponseBody(read_buffer_
.get(), read_buffer_
->size(),
605 callback_
.callback()));
607 EXPECT_TRUE(stream_
->IsResponseBodyComplete());
608 EXPECT_TRUE(AtEof());
611 TEST_P(QuicHttpStreamTest
, SendChunkedPostRequestWithOneEmptyDataPacket
) {
612 SetRequest("POST", "/", DEFAULT_PRIORITY
);
613 AddWrite(ConstructRequestHeadersPacket(1, !kFin
, DEFAULT_PRIORITY
));
614 AddWrite(ConstructDataPacket(2, kIncludeVersion
, kFin
, 0, ""));
615 AddWrite(ConstructAckPacket(3, 3, 1));
618 ChunkedUploadDataStream
upload_data_stream(0);
620 request_
.method
= "POST";
621 request_
.url
= GURL("http://www.google.com/");
622 request_
.upload_data_stream
= &upload_data_stream
;
623 ASSERT_EQ(OK
, request_
.upload_data_stream
->Init(
624 TestCompletionCallback().callback()));
626 ASSERT_EQ(OK
, stream_
->InitializeStream(&request_
, DEFAULT_PRIORITY
,
627 net_log_
, callback_
.callback()));
628 ASSERT_EQ(ERR_IO_PENDING
, stream_
->SendRequest(headers_
, &response_
,
629 callback_
.callback()));
631 upload_data_stream
.AppendData(nullptr, 0, true);
633 ProcessPacket(ConstructAckPacket(1, 0, 0));
635 // Send the response headers (but not the body).
636 SetResponse("200 OK", std::string());
637 ProcessPacket(ConstructResponseHeadersPacket(2, !kFin
));
639 // Since the headers have already arrived, this should return immediately.
640 ASSERT_EQ(OK
, stream_
->ReadResponseHeaders(callback_
.callback()));
641 ASSERT_TRUE(response_
.headers
.get());
642 EXPECT_EQ(200, response_
.headers
->response_code());
643 EXPECT_TRUE(response_
.headers
->HasHeaderValue("Content-Type", "text/plain"));
645 // Send the response body.
646 const char kResponseBody
[] = "Hello world!";
647 ProcessPacket(ConstructDataPacket(3, false, kFin
, response_data_
.length(),
650 // Since the body has already arrived, this should return immediately.
651 ASSERT_EQ(static_cast<int>(strlen(kResponseBody
)),
652 stream_
->ReadResponseBody(read_buffer_
.get(), read_buffer_
->size(),
653 callback_
.callback()));
655 EXPECT_TRUE(stream_
->IsResponseBodyComplete());
656 EXPECT_TRUE(AtEof());
659 TEST_P(QuicHttpStreamTest
, DestroyedEarly
) {
660 SetRequest("GET", "/", DEFAULT_PRIORITY
);
661 AddWrite(ConstructRequestHeadersPacket(1, kFin
, DEFAULT_PRIORITY
));
662 AddWrite(ConstructAckAndRstStreamPacket(2));
663 use_closing_stream_
= true;
666 request_
.method
= "GET";
667 request_
.url
= GURL("http://www.google.com/");
669 EXPECT_EQ(OK
, stream_
->InitializeStream(&request_
, DEFAULT_PRIORITY
,
670 net_log_
, callback_
.callback()));
671 EXPECT_EQ(OK
, stream_
->SendRequest(headers_
, &response_
,
672 callback_
.callback()));
675 ProcessPacket(ConstructAckPacket(1, 0, 0));
676 EXPECT_EQ(ERR_IO_PENDING
,
677 stream_
->ReadResponseHeaders(callback_
.callback()));
679 // Send the response with a body.
680 SetResponse("404 OK", "hello world!");
681 // In the course of processing this packet, the QuicHttpStream close itself.
682 ProcessPacket(ConstructResponseHeadersPacket(2, kFin
));
684 EXPECT_TRUE(AtEof());
687 TEST_P(QuicHttpStreamTest
, Priority
) {
688 SetRequest("GET", "/", MEDIUM
);
689 AddWrite(ConstructRequestHeadersPacket(1, kFin
, MEDIUM
));
690 AddWrite(ConstructAckAndRstStreamPacket(2));
691 use_closing_stream_
= true;
694 request_
.method
= "GET";
695 request_
.url
= GURL("http://www.google.com/");
697 EXPECT_EQ(OK
, stream_
->InitializeStream(&request_
, MEDIUM
,
698 net_log_
, callback_
.callback()));
700 // Check that priority is highest.
701 QuicReliableClientStream
* reliable_stream
=
702 QuicHttpStreamPeer::GetQuicReliableClientStream(stream_
.get());
703 DCHECK(reliable_stream
);
704 DCHECK_EQ(QuicWriteBlockedList::kHighestPriority
,
705 reliable_stream
->EffectivePriority());
707 EXPECT_EQ(OK
, stream_
->SendRequest(headers_
, &response_
,
708 callback_
.callback()));
710 // Check that priority has now dropped back to MEDIUM.
711 DCHECK_EQ(MEDIUM
, ConvertQuicPriorityToRequestPriority(
712 reliable_stream
->EffectivePriority()));
715 ProcessPacket(ConstructAckPacket(1, 0, 0));
716 EXPECT_EQ(ERR_IO_PENDING
,
717 stream_
->ReadResponseHeaders(callback_
.callback()));
719 // Send the response with a body.
720 SetResponse("404 OK", "hello world!");
721 // In the course of processing this packet, the QuicHttpStream close itself.
722 ProcessPacket(ConstructResponseHeadersPacket(2, kFin
));
724 EXPECT_TRUE(AtEof());
727 // Regression test for http://crbug.com/294870
728 TEST_P(QuicHttpStreamTest
, CheckPriorityWithNoDelegate
) {
729 SetRequest("GET", "/", MEDIUM
);
730 use_closing_stream_
= true;
732 AddWrite(ConstructRstStreamPacket(1));
736 request_
.method
= "GET";
737 request_
.url
= GURL("http://www.google.com/");
739 EXPECT_EQ(OK
, stream_
->InitializeStream(&request_
, MEDIUM
,
740 net_log_
, callback_
.callback()));
742 // Check that priority is highest.
743 QuicReliableClientStream
* reliable_stream
=
744 QuicHttpStreamPeer::GetQuicReliableClientStream(stream_
.get());
745 DCHECK(reliable_stream
);
746 QuicReliableClientStream::Delegate
* delegate
= reliable_stream
->GetDelegate();
748 DCHECK_EQ(QuicWriteBlockedList::kHighestPriority
,
749 reliable_stream
->EffectivePriority());
751 // Set Delegate to nullptr and make sure EffectivePriority returns highest
753 reliable_stream
->SetDelegate(nullptr);
754 DCHECK_EQ(QuicWriteBlockedList::kHighestPriority
,
755 reliable_stream
->EffectivePriority());
756 reliable_stream
->SetDelegate(delegate
);