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/net_errors.h"
10 #include "net/base/test_completion_callback.h"
11 #include "net/base/upload_bytes_element_reader.h"
12 #include "net/base/upload_data_stream.h"
13 #include "net/http/http_response_headers.h"
14 #include "net/http/transport_security_state.h"
15 #include "net/quic/congestion_control/receive_algorithm_interface.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 false /* is_server */,
72 void SetSendAlgorithm(SendAlgorithmInterface
* send_algorithm
) {
73 QuicConnectionPeer::SetSendAlgorithm(this, send_algorithm
);
76 void SetReceiveAlgorithm(ReceiveAlgorithmInterface
* receive_algorithm
) {
77 QuicConnectionPeer::SetReceiveAlgorithm(this, receive_algorithm
);
81 class TestReceiveAlgorithm
: public ReceiveAlgorithmInterface
{
83 virtual bool GenerateCongestionFeedback(
84 QuicCongestionFeedbackFrame
* /*congestion_feedback*/) {
88 MOCK_METHOD3(RecordIncomingPacket
,
89 void(QuicByteCount
, QuicPacketSequenceNumber
, QuicTime
));
92 // Subclass of QuicHttpStream that closes itself when the first piece of data
94 class AutoClosingStream
: public QuicHttpStream
{
96 explicit AutoClosingStream(const base::WeakPtr
<QuicClientSession
>& session
)
97 : QuicHttpStream(session
) {
100 virtual int OnDataReceived(const char* data
, int length
) OVERRIDE
{
106 class TestPacketWriterFactory
: public QuicConnection::PacketWriterFactory
{
108 explicit TestPacketWriterFactory(DatagramClientSocket
* socket
)
110 virtual ~TestPacketWriterFactory() {}
112 virtual QuicPacketWriter
* Create(QuicConnection
* connection
) const OVERRIDE
{
113 return new QuicDefaultPacketWriter(socket_
);
117 DatagramClientSocket
* socket_
;
122 class QuicHttpStreamPeer
{
124 static QuicReliableClientStream
* GetQuicReliableClientStream(
125 QuicHttpStream
* stream
) {
126 return stream
->stream_
;
130 class QuicHttpStreamTest
: public ::testing::TestWithParam
<QuicVersion
> {
132 static const bool kFin
= true;
133 static const bool kIncludeVersion
= true;
134 static const bool kIncludeCongestionFeedback
= true;
136 // Holds a packet to be written to the wire, and the IO mode that should
137 // be used by the mock socket when performing the write.
138 struct PacketToWrite
{
139 PacketToWrite(IoMode mode
, QuicEncryptedPacket
* packet
)
144 QuicEncryptedPacket
* packet
;
148 : net_log_(BoundNetLog()),
149 use_closing_stream_(false),
150 read_buffer_(new IOBufferWithSize(4096)),
152 stream_id_(kClientDataStreamId1
),
153 maker_(GetParam(), connection_id_
, &clock_
),
154 random_generator_(0) {
156 CHECK(ParseIPLiteralToNumber("192.0.2.33", &ip
));
157 peer_addr_
= IPEndPoint(ip
, 443);
158 self_addr_
= IPEndPoint(ip
, 8435);
159 clock_
.AdvanceTime(QuicTime::Delta::FromMilliseconds(20));
162 ~QuicHttpStreamTest() {
163 session_
->CloseSessionOnError(ERR_ABORTED
);
164 for (size_t i
= 0; i
< writes_
.size(); i
++) {
165 delete writes_
[i
].packet
;
169 // Adds a packet to the list of expected writes.
170 void AddWrite(scoped_ptr
<QuicEncryptedPacket
> packet
) {
171 writes_
.push_back(PacketToWrite(SYNCHRONOUS
, packet
.release()));
174 // Returns the packet to be written at position |pos|.
175 QuicEncryptedPacket
* GetWrite(size_t pos
) {
176 return writes_
[pos
].packet
;
180 return socket_data_
->at_read_eof() && socket_data_
->at_write_eof();
183 void ProcessPacket(scoped_ptr
<QuicEncryptedPacket
> packet
) {
184 connection_
->ProcessUdpPacket(self_addr_
, peer_addr_
, *packet
);
187 // Configures the test fixture to use the list of expected writes.
189 mock_writes_
.reset(new MockWrite
[writes_
.size()]);
190 for (size_t i
= 0; i
< writes_
.size(); i
++) {
191 mock_writes_
[i
] = MockWrite(writes_
[i
].mode
,
192 writes_
[i
].packet
->data(),
193 writes_
[i
].packet
->length());
196 socket_data_
.reset(new StaticSocketDataProvider(NULL
, 0, mock_writes_
.get(),
199 MockUDPClientSocket
* socket
= new MockUDPClientSocket(socket_data_
.get(),
201 socket
->Connect(peer_addr_
);
202 runner_
= new TestTaskRunner(&clock_
);
203 send_algorithm_
= new MockSendAlgorithm();
204 receive_algorithm_
= new TestReceiveAlgorithm();
205 EXPECT_CALL(*receive_algorithm_
, RecordIncomingPacket(_
, _
, _
)).
207 EXPECT_CALL(*send_algorithm_
,
208 OnPacketSent(_
, _
, _
, _
, _
)).WillRepeatedly(Return(true));
209 EXPECT_CALL(*send_algorithm_
, RetransmissionDelay()).WillRepeatedly(
210 Return(QuicTime::Delta::Zero()));
211 EXPECT_CALL(*send_algorithm_
, GetCongestionWindow()).WillRepeatedly(
212 Return(kMaxPacketSize
));
213 EXPECT_CALL(*send_algorithm_
, TimeUntilSend(_
, _
, _
)).
214 WillRepeatedly(Return(QuicTime::Delta::Zero()));
215 EXPECT_CALL(*send_algorithm_
, BandwidthEstimate()).WillRepeatedly(
216 Return(QuicBandwidth::Zero()));
217 EXPECT_CALL(*send_algorithm_
, SetFromConfig(_
, _
)).Times(AnyNumber());
218 helper_
.reset(new QuicConnectionHelper(runner_
.get(), &clock_
,
219 &random_generator_
));
220 TestPacketWriterFactory
writer_factory(socket
);
221 connection_
= new TestQuicConnection(SupportedVersions(GetParam()),
222 connection_id_
, peer_addr_
,
223 helper_
.get(), writer_factory
);
224 connection_
->set_visitor(&visitor_
);
225 connection_
->SetSendAlgorithm(send_algorithm_
);
226 connection_
->SetReceiveAlgorithm(receive_algorithm_
);
227 crypto_config_
.SetDefaults();
229 new QuicClientSession(connection_
,
230 scoped_ptr
<DatagramClientSocket
>(socket
),
232 &transport_security_state_
,
233 make_scoped_ptr((QuicServerInfo
*)NULL
),
235 base::MessageLoop::current()->
236 message_loop_proxy().get(),
238 session_
->InitializeSession(QuicServerId(kServerHostname
, kServerPort
,
239 false, PRIVACY_MODE_DISABLED
),
241 &crypto_client_stream_factory_
);
242 session_
->GetCryptoStream()->CryptoConnect();
243 EXPECT_TRUE(session_
->IsCryptoHandshakeConfirmed());
244 stream_
.reset(use_closing_stream_
?
245 new AutoClosingStream(session_
->GetWeakPtr()) :
246 new QuicHttpStream(session_
->GetWeakPtr()));
249 void SetRequest(const std::string
& method
,
250 const std::string
& path
,
251 RequestPriority priority
) {
252 request_headers_
= maker_
.GetRequestHeaders(method
, "http", path
);
255 void SetResponse(const std::string
& status
, const std::string
& body
) {
256 response_headers_
= maker_
.GetResponseHeaders(status
);
257 response_data_
= body
;
260 scoped_ptr
<QuicEncryptedPacket
> ConstructDataPacket(
261 QuicPacketSequenceNumber sequence_number
,
262 bool should_include_version
,
264 QuicStreamOffset offset
,
265 base::StringPiece data
) {
266 return maker_
.MakeDataPacket(
267 sequence_number
, stream_id_
, should_include_version
, fin
, offset
, data
);
270 scoped_ptr
<QuicEncryptedPacket
> ConstructRequestHeadersPacket(
271 QuicPacketSequenceNumber sequence_number
,
273 return maker_
.MakeRequestHeadersPacket(
274 sequence_number
, stream_id_
, kIncludeVersion
, fin
, request_headers_
);
277 scoped_ptr
<QuicEncryptedPacket
> ConstructResponseHeadersPacket(
278 QuicPacketSequenceNumber sequence_number
,
280 return maker_
.MakeResponseHeadersPacket(
281 sequence_number
, stream_id_
, !kIncludeVersion
, fin
, response_headers_
);
284 scoped_ptr
<QuicEncryptedPacket
> ConstructRstStreamPacket(
285 QuicPacketSequenceNumber sequence_number
) {
286 return maker_
.MakeRstPacket(
287 sequence_number
, true, stream_id_
,
288 AdjustErrorForVersion(QUIC_RST_FLOW_CONTROL_ACCOUNTING
, GetParam()));
291 scoped_ptr
<QuicEncryptedPacket
> ConstructAckAndRstStreamPacket(
292 QuicPacketSequenceNumber sequence_number
) {
293 return maker_
.MakeAckAndRstPacket(
294 sequence_number
, !kIncludeVersion
, stream_id_
, QUIC_STREAM_CANCELLED
,
295 2, 1, !kIncludeCongestionFeedback
);
298 scoped_ptr
<QuicEncryptedPacket
> ConstructAckPacket(
299 QuicPacketSequenceNumber sequence_number
,
300 QuicPacketSequenceNumber largest_received
,
301 QuicPacketSequenceNumber least_unacked
) {
302 return maker_
.MakeAckPacket(sequence_number
, largest_received
,
303 least_unacked
, !kIncludeCongestionFeedback
);
306 BoundNetLog net_log_
;
307 bool use_closing_stream_
;
308 MockSendAlgorithm
* send_algorithm_
;
309 TestReceiveAlgorithm
* receive_algorithm_
;
310 scoped_refptr
<TestTaskRunner
> runner_
;
311 scoped_ptr
<MockWrite
[]> mock_writes_
;
313 TestQuicConnection
* connection_
;
314 scoped_ptr
<QuicConnectionHelper
> helper_
;
315 testing::StrictMock
<MockConnectionVisitor
> visitor_
;
316 scoped_ptr
<QuicHttpStream
> stream_
;
317 TransportSecurityState transport_security_state_
;
318 scoped_ptr
<QuicClientSession
> session_
;
319 QuicCryptoClientConfig crypto_config_
;
320 TestCompletionCallback callback_
;
321 HttpRequestInfo request_
;
322 HttpRequestHeaders headers_
;
323 HttpResponseInfo response_
;
324 scoped_refptr
<IOBufferWithSize
> read_buffer_
;
325 SpdyHeaderBlock request_headers_
;
326 SpdyHeaderBlock response_headers_
;
327 std::string request_data_
;
328 std::string response_data_
;
331 const QuicConnectionId connection_id_
;
332 const QuicStreamId stream_id_
;
333 QuicTestPacketMaker maker_
;
334 IPEndPoint self_addr_
;
335 IPEndPoint peer_addr_
;
336 MockRandom random_generator_
;
337 MockCryptoClientStreamFactory crypto_client_stream_factory_
;
338 scoped_ptr
<StaticSocketDataProvider
> socket_data_
;
339 std::vector
<PacketToWrite
> writes_
;
342 INSTANTIATE_TEST_CASE_P(Version
, QuicHttpStreamTest
,
343 ::testing::ValuesIn(QuicSupportedVersions()));
345 TEST_P(QuicHttpStreamTest
, RenewStreamForAuth
) {
347 EXPECT_EQ(NULL
, stream_
->RenewStreamForAuth());
350 TEST_P(QuicHttpStreamTest
, CanFindEndOfResponse
) {
352 EXPECT_TRUE(stream_
->CanFindEndOfResponse());
355 TEST_P(QuicHttpStreamTest
, IsConnectionReusable
) {
357 EXPECT_FALSE(stream_
->IsConnectionReusable());
360 TEST_P(QuicHttpStreamTest
, GetRequest
) {
361 SetRequest("GET", "/", DEFAULT_PRIORITY
);
362 AddWrite(ConstructRequestHeadersPacket(1, kFin
));
365 request_
.method
= "GET";
366 request_
.url
= GURL("http://www.google.com/");
368 EXPECT_EQ(OK
, stream_
->InitializeStream(&request_
, DEFAULT_PRIORITY
,
369 net_log_
, callback_
.callback()));
370 EXPECT_EQ(OK
, stream_
->SendRequest(headers_
, &response_
,
371 callback_
.callback()));
374 ProcessPacket(ConstructAckPacket(1, 0, 0));
376 EXPECT_EQ(ERR_IO_PENDING
,
377 stream_
->ReadResponseHeaders(callback_
.callback()));
379 SetResponse("404 Not Found", std::string());
380 ProcessPacket(ConstructResponseHeadersPacket(2, kFin
));
382 // Now that the headers have been processed, the callback will return.
383 EXPECT_EQ(OK
, callback_
.WaitForResult());
384 ASSERT_TRUE(response_
.headers
.get());
385 EXPECT_EQ(404, response_
.headers
->response_code());
386 EXPECT_TRUE(response_
.headers
->HasHeaderValue("Content-Type", "text/plain"));
387 EXPECT_FALSE(response_
.response_time
.is_null());
388 EXPECT_FALSE(response_
.request_time
.is_null());
390 // There is no body, so this should return immediately.
391 EXPECT_EQ(0, stream_
->ReadResponseBody(read_buffer_
.get(),
392 read_buffer_
->size(),
393 callback_
.callback()));
394 EXPECT_TRUE(stream_
->IsResponseBodyComplete());
395 EXPECT_TRUE(AtEof());
398 // Regression test for http://crbug.com/288128
399 TEST_P(QuicHttpStreamTest
, GetRequestLargeResponse
) {
400 SetRequest("GET", "/", DEFAULT_PRIORITY
);
401 AddWrite(ConstructRequestHeadersPacket(1, kFin
));
404 request_
.method
= "GET";
405 request_
.url
= GURL("http://www.google.com/");
407 EXPECT_EQ(OK
, stream_
->InitializeStream(&request_
, DEFAULT_PRIORITY
,
408 net_log_
, callback_
.callback()));
409 EXPECT_EQ(OK
, stream_
->SendRequest(headers_
, &response_
,
410 callback_
.callback()));
413 ProcessPacket(ConstructAckPacket(1, 0, 0));
415 EXPECT_EQ(ERR_IO_PENDING
,
416 stream_
->ReadResponseHeaders(callback_
.callback()));
418 SpdyHeaderBlock headers
;
419 headers
[":status"] = "200 OK";
420 headers
[":version"] = "HTTP/1.1";
421 headers
["content-type"] = "text/plain";
422 headers
["big6"] = std::string(10000, 'x'); // Lots of x's.
424 std::string response
= SpdyUtils::SerializeUncompressedHeaders(headers
);
425 EXPECT_LT(4096u, response
.length());
426 stream_
->OnDataReceived(response
.data(), response
.length());
427 stream_
->OnClose(QUIC_NO_ERROR
);
429 // Now that the headers have been processed, the callback will return.
430 EXPECT_EQ(OK
, callback_
.WaitForResult());
431 ASSERT_TRUE(response_
.headers
.get());
432 EXPECT_EQ(200, response_
.headers
->response_code());
433 EXPECT_TRUE(response_
.headers
->HasHeaderValue("Content-Type", "text/plain"));
435 // There is no body, so this should return immediately.
436 EXPECT_EQ(0, stream_
->ReadResponseBody(read_buffer_
.get(),
437 read_buffer_
->size(),
438 callback_
.callback()));
439 EXPECT_TRUE(stream_
->IsResponseBodyComplete());
440 EXPECT_TRUE(AtEof());
443 // Regression test for http://crbug.com/409101
444 TEST_P(QuicHttpStreamTest
, SessionClosedBeforeSendRequest
) {
445 SetRequest("GET", "/", DEFAULT_PRIORITY
);
448 request_
.method
= "GET";
449 request_
.url
= GURL("http://www.google.com/");
451 EXPECT_EQ(OK
, stream_
->InitializeStream(&request_
, DEFAULT_PRIORITY
,
452 net_log_
, callback_
.callback()));
454 session_
->connection()->CloseConnection(QUIC_NO_ERROR
, true);
456 EXPECT_EQ(ERR_CONNECTION_CLOSED
,
457 stream_
->SendRequest(headers_
, &response_
,
458 callback_
.callback()));
461 // Regression test for http://crbug.com/409871
462 TEST_P(QuicHttpStreamTest
, SessionClosedBeforeReadResponseHeaders
) {
463 SetRequest("GET", "/", DEFAULT_PRIORITY
);
464 AddWrite(ConstructRequestHeadersPacket(1, kFin
));
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()));
481 TEST_P(QuicHttpStreamTest
, SendPostRequest
) {
482 SetRequest("POST", "/", DEFAULT_PRIORITY
);
483 AddWrite(ConstructRequestHeadersPacket(1, !kFin
));
484 AddWrite(ConstructDataPacket(2, kIncludeVersion
, kFin
, 0, kUploadData
));
485 AddWrite(ConstructAckPacket(3, 3, 1));
489 ScopedVector
<UploadElementReader
> element_readers
;
490 element_readers
.push_back(
491 new UploadBytesElementReader(kUploadData
, strlen(kUploadData
)));
492 UploadDataStream
upload_data_stream(element_readers
.Pass(), 0);
493 request_
.method
= "POST";
494 request_
.url
= GURL("http://www.google.com/");
495 request_
.upload_data_stream
= &upload_data_stream
;
496 ASSERT_EQ(OK
, request_
.upload_data_stream
->Init(CompletionCallback()));
498 EXPECT_EQ(OK
, stream_
->InitializeStream(&request_
, DEFAULT_PRIORITY
,
499 net_log_
, callback_
.callback()));
500 EXPECT_EQ(OK
, stream_
->SendRequest(headers_
, &response_
,
501 callback_
.callback()));
503 // Ack both packets in the request.
504 ProcessPacket(ConstructAckPacket(1, 0, 0));
506 // Send the response headers (but not the body).
507 SetResponse("200 OK", std::string());
508 ProcessPacket(ConstructResponseHeadersPacket(2, !kFin
));
510 // Since the headers have already arrived, this should return immediately.
511 EXPECT_EQ(OK
, stream_
->ReadResponseHeaders(callback_
.callback()));
512 ASSERT_TRUE(response_
.headers
.get());
513 EXPECT_EQ(200, response_
.headers
->response_code());
514 EXPECT_TRUE(response_
.headers
->HasHeaderValue("Content-Type", "text/plain"));
516 // Send the response body.
517 const char kResponseBody
[] = "Hello world!";
518 ProcessPacket(ConstructDataPacket(3, false, kFin
, 0, kResponseBody
));
519 // Since the body has already arrived, this should return immediately.
520 EXPECT_EQ(static_cast<int>(strlen(kResponseBody
)),
521 stream_
->ReadResponseBody(read_buffer_
.get(), read_buffer_
->size(),
522 callback_
.callback()));
524 EXPECT_TRUE(stream_
->IsResponseBodyComplete());
525 EXPECT_TRUE(AtEof());
528 TEST_P(QuicHttpStreamTest
, SendChunkedPostRequest
) {
529 SetRequest("POST", "/", DEFAULT_PRIORITY
);
530 size_t chunk_size
= strlen(kUploadData
);
531 AddWrite(ConstructRequestHeadersPacket(1, !kFin
));
532 AddWrite(ConstructDataPacket(2, kIncludeVersion
, !kFin
, 0, kUploadData
));
533 AddWrite(ConstructDataPacket(3, kIncludeVersion
, kFin
, chunk_size
,
535 AddWrite(ConstructAckPacket(4, 3, 1));
538 UploadDataStream
upload_data_stream(UploadDataStream::CHUNKED
, 0);
539 upload_data_stream
.AppendChunk(kUploadData
, chunk_size
, false);
541 request_
.method
= "POST";
542 request_
.url
= GURL("http://www.google.com/");
543 request_
.upload_data_stream
= &upload_data_stream
;
544 ASSERT_EQ(OK
, request_
.upload_data_stream
->Init(CompletionCallback()));
546 ASSERT_EQ(OK
, stream_
->InitializeStream(&request_
, DEFAULT_PRIORITY
,
547 net_log_
, callback_
.callback()));
548 ASSERT_EQ(ERR_IO_PENDING
, stream_
->SendRequest(headers_
, &response_
,
549 callback_
.callback()));
551 upload_data_stream
.AppendChunk(kUploadData
, chunk_size
, true);
553 // Ack both packets in the request.
554 ProcessPacket(ConstructAckPacket(1, 0, 0));
556 // Send the response headers (but not the body).
557 SetResponse("200 OK", std::string());
558 ProcessPacket(ConstructResponseHeadersPacket(2, !kFin
));
560 // Since the headers have already arrived, this should return immediately.
561 ASSERT_EQ(OK
, stream_
->ReadResponseHeaders(callback_
.callback()));
562 ASSERT_TRUE(response_
.headers
.get());
563 EXPECT_EQ(200, response_
.headers
->response_code());
564 EXPECT_TRUE(response_
.headers
->HasHeaderValue("Content-Type", "text/plain"));
566 // Send the response body.
567 const char kResponseBody
[] = "Hello world!";
568 ProcessPacket(ConstructDataPacket(3, false, kFin
, response_data_
.length(),
571 // Since the body has already arrived, this should return immediately.
572 ASSERT_EQ(static_cast<int>(strlen(kResponseBody
)),
573 stream_
->ReadResponseBody(read_buffer_
.get(), read_buffer_
->size(),
574 callback_
.callback()));
576 EXPECT_TRUE(stream_
->IsResponseBodyComplete());
577 EXPECT_TRUE(AtEof());
580 TEST_P(QuicHttpStreamTest
, SendChunkedPostRequestWithFinalEmptyDataPacket
) {
581 SetRequest("POST", "/", DEFAULT_PRIORITY
);
582 size_t chunk_size
= strlen(kUploadData
);
583 AddWrite(ConstructRequestHeadersPacket(1, !kFin
));
584 AddWrite(ConstructDataPacket(2, kIncludeVersion
, !kFin
, 0, kUploadData
));
585 AddWrite(ConstructDataPacket(3, kIncludeVersion
, kFin
, chunk_size
, ""));
586 AddWrite(ConstructAckPacket(4, 3, 1));
589 UploadDataStream
upload_data_stream(UploadDataStream::CHUNKED
, 0);
590 upload_data_stream
.AppendChunk(kUploadData
, chunk_size
, false);
592 request_
.method
= "POST";
593 request_
.url
= GURL("http://www.google.com/");
594 request_
.upload_data_stream
= &upload_data_stream
;
595 ASSERT_EQ(OK
, request_
.upload_data_stream
->Init(CompletionCallback()));
597 ASSERT_EQ(OK
, stream_
->InitializeStream(&request_
, DEFAULT_PRIORITY
,
598 net_log_
, callback_
.callback()));
599 ASSERT_EQ(ERR_IO_PENDING
, stream_
->SendRequest(headers_
, &response_
,
600 callback_
.callback()));
602 upload_data_stream
.AppendChunk(NULL
, 0, true);
604 ProcessPacket(ConstructAckPacket(1, 0, 0));
606 // Send the response headers (but not the body).
607 SetResponse("200 OK", std::string());
608 ProcessPacket(ConstructResponseHeadersPacket(2, !kFin
));
610 // Since the headers have already arrived, this should return immediately.
611 ASSERT_EQ(OK
, stream_
->ReadResponseHeaders(callback_
.callback()));
612 ASSERT_TRUE(response_
.headers
.get());
613 EXPECT_EQ(200, response_
.headers
->response_code());
614 EXPECT_TRUE(response_
.headers
->HasHeaderValue("Content-Type", "text/plain"));
616 // Send the response body.
617 const char kResponseBody
[] = "Hello world!";
618 ProcessPacket(ConstructDataPacket(3, false, kFin
, response_data_
.length(),
621 // Since the body has already arrived, this should return immediately.
622 ASSERT_EQ(static_cast<int>(strlen(kResponseBody
)),
623 stream_
->ReadResponseBody(read_buffer_
.get(), read_buffer_
->size(),
624 callback_
.callback()));
626 EXPECT_TRUE(stream_
->IsResponseBodyComplete());
627 EXPECT_TRUE(AtEof());
630 TEST_P(QuicHttpStreamTest
, SendChunkedPostRequestWithOneEmptyDataPacket
) {
631 SetRequest("POST", "/", DEFAULT_PRIORITY
);
632 AddWrite(ConstructRequestHeadersPacket(1, !kFin
));
633 AddWrite(ConstructDataPacket(2, kIncludeVersion
, kFin
, 0, ""));
634 AddWrite(ConstructAckPacket(3, 3, 1));
637 UploadDataStream
upload_data_stream(UploadDataStream::CHUNKED
, 0);
639 request_
.method
= "POST";
640 request_
.url
= GURL("http://www.google.com/");
641 request_
.upload_data_stream
= &upload_data_stream
;
642 ASSERT_EQ(OK
, request_
.upload_data_stream
->Init(CompletionCallback()));
644 ASSERT_EQ(OK
, stream_
->InitializeStream(&request_
, DEFAULT_PRIORITY
,
645 net_log_
, callback_
.callback()));
646 ASSERT_EQ(ERR_IO_PENDING
, stream_
->SendRequest(headers_
, &response_
,
647 callback_
.callback()));
649 upload_data_stream
.AppendChunk(NULL
, 0, true);
651 ProcessPacket(ConstructAckPacket(1, 0, 0));
653 // Send the response headers (but not the body).
654 SetResponse("200 OK", std::string());
655 ProcessPacket(ConstructResponseHeadersPacket(2, !kFin
));
657 // Since the headers have already arrived, this should return immediately.
658 ASSERT_EQ(OK
, stream_
->ReadResponseHeaders(callback_
.callback()));
659 ASSERT_TRUE(response_
.headers
.get());
660 EXPECT_EQ(200, response_
.headers
->response_code());
661 EXPECT_TRUE(response_
.headers
->HasHeaderValue("Content-Type", "text/plain"));
663 // Send the response body.
664 const char kResponseBody
[] = "Hello world!";
665 ProcessPacket(ConstructDataPacket(3, false, kFin
, response_data_
.length(),
668 // Since the body has already arrived, this should return immediately.
669 ASSERT_EQ(static_cast<int>(strlen(kResponseBody
)),
670 stream_
->ReadResponseBody(read_buffer_
.get(), read_buffer_
->size(),
671 callback_
.callback()));
673 EXPECT_TRUE(stream_
->IsResponseBodyComplete());
674 EXPECT_TRUE(AtEof());
677 TEST_P(QuicHttpStreamTest
, DestroyedEarly
) {
678 SetRequest("GET", "/", DEFAULT_PRIORITY
);
679 AddWrite(ConstructRequestHeadersPacket(1, kFin
));
680 AddWrite(ConstructAckAndRstStreamPacket(2));
681 use_closing_stream_
= true;
684 request_
.method
= "GET";
685 request_
.url
= GURL("http://www.google.com/");
687 EXPECT_EQ(OK
, stream_
->InitializeStream(&request_
, DEFAULT_PRIORITY
,
688 net_log_
, callback_
.callback()));
689 EXPECT_EQ(OK
, stream_
->SendRequest(headers_
, &response_
,
690 callback_
.callback()));
693 ProcessPacket(ConstructAckPacket(1, 0, 0));
694 EXPECT_EQ(ERR_IO_PENDING
,
695 stream_
->ReadResponseHeaders(callback_
.callback()));
697 // Send the response with a body.
698 SetResponse("404 OK", "hello world!");
699 // In the course of processing this packet, the QuicHttpStream close itself.
700 ProcessPacket(ConstructResponseHeadersPacket(2, kFin
));
702 EXPECT_TRUE(AtEof());
705 TEST_P(QuicHttpStreamTest
, Priority
) {
706 SetRequest("GET", "/", MEDIUM
);
707 AddWrite(ConstructRequestHeadersPacket(1, kFin
));
708 AddWrite(ConstructAckAndRstStreamPacket(2));
709 use_closing_stream_
= true;
712 request_
.method
= "GET";
713 request_
.url
= GURL("http://www.google.com/");
715 EXPECT_EQ(OK
, stream_
->InitializeStream(&request_
, MEDIUM
,
716 net_log_
, callback_
.callback()));
718 // Check that priority is highest.
719 QuicReliableClientStream
* reliable_stream
=
720 QuicHttpStreamPeer::GetQuicReliableClientStream(stream_
.get());
721 DCHECK(reliable_stream
);
722 DCHECK_EQ(QuicWriteBlockedList::kHighestPriority
,
723 reliable_stream
->EffectivePriority());
725 EXPECT_EQ(OK
, stream_
->SendRequest(headers_
, &response_
,
726 callback_
.callback()));
728 // Check that priority has now dropped back to MEDIUM.
729 DCHECK_EQ(MEDIUM
, ConvertQuicPriorityToRequestPriority(
730 reliable_stream
->EffectivePriority()));
733 ProcessPacket(ConstructAckPacket(1, 0, 0));
734 EXPECT_EQ(ERR_IO_PENDING
,
735 stream_
->ReadResponseHeaders(callback_
.callback()));
737 // Send the response with a body.
738 SetResponse("404 OK", "hello world!");
739 // In the course of processing this packet, the QuicHttpStream close itself.
740 ProcessPacket(ConstructResponseHeadersPacket(2, kFin
));
742 EXPECT_TRUE(AtEof());
745 // Regression test for http://crbug.com/294870
746 TEST_P(QuicHttpStreamTest
, CheckPriorityWithNoDelegate
) {
747 SetRequest("GET", "/", MEDIUM
);
748 use_closing_stream_
= true;
750 AddWrite(ConstructRstStreamPacket(1));
754 request_
.method
= "GET";
755 request_
.url
= GURL("http://www.google.com/");
757 EXPECT_EQ(OK
, stream_
->InitializeStream(&request_
, MEDIUM
,
758 net_log_
, callback_
.callback()));
760 // Check that priority is highest.
761 QuicReliableClientStream
* reliable_stream
=
762 QuicHttpStreamPeer::GetQuicReliableClientStream(stream_
.get());
763 DCHECK(reliable_stream
);
764 QuicReliableClientStream::Delegate
* delegate
= reliable_stream
->GetDelegate();
766 DCHECK_EQ(QuicWriteBlockedList::kHighestPriority
,
767 reliable_stream
->EffectivePriority());
769 // Set Delegate to NULL and make sure EffectivePriority returns highest
771 reliable_stream
->SetDelegate(NULL
);
772 DCHECK_EQ(QuicWriteBlockedList::kHighestPriority
,
773 reliable_stream
->EffectivePriority());
774 reliable_stream
->SetDelegate(delegate
);