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/quic/congestion_control/receive_algorithm_interface.h"
15 #include "net/quic/congestion_control/send_algorithm_interface.h"
16 #include "net/quic/crypto/crypto_protocol.h"
17 #include "net/quic/crypto/quic_decrypter.h"
18 #include "net/quic/crypto/quic_encrypter.h"
19 #include "net/quic/crypto/quic_server_info.h"
20 #include "net/quic/quic_client_session.h"
21 #include "net/quic/quic_connection.h"
22 #include "net/quic/quic_connection_helper.h"
23 #include "net/quic/quic_default_packet_writer.h"
24 #include "net/quic/quic_http_utils.h"
25 #include "net/quic/quic_reliable_client_stream.h"
26 #include "net/quic/quic_write_blocked_list.h"
27 #include "net/quic/spdy_utils.h"
28 #include "net/quic/test_tools/mock_clock.h"
29 #include "net/quic/test_tools/mock_crypto_client_stream_factory.h"
30 #include "net/quic/test_tools/mock_random.h"
31 #include "net/quic/test_tools/quic_connection_peer.h"
32 #include "net/quic/test_tools/quic_test_packet_maker.h"
33 #include "net/quic/test_tools/quic_test_utils.h"
34 #include "net/quic/test_tools/test_task_runner.h"
35 #include "net/socket/socket_test_util.h"
36 #include "net/spdy/spdy_frame_builder.h"
37 #include "net/spdy/spdy_framer.h"
38 #include "net/spdy/spdy_http_utils.h"
39 #include "net/spdy/spdy_protocol.h"
40 #include "testing/gmock/include/gmock/gmock.h"
41 #include "testing/gtest/include/gtest/gtest.h"
44 using testing::AnyNumber
;
45 using testing::Return
;
51 const char kUploadData
[] = "hello world!";
52 const char kServerHostname
[] = "www.google.com";
53 const uint16 kServerPort
= 80;
55 class TestQuicConnection
: public QuicConnection
{
57 TestQuicConnection(const QuicVersionVector
& versions
,
58 QuicConnectionId connection_id
,
60 QuicConnectionHelper
* helper
,
61 QuicPacketWriter
* writer
)
62 : QuicConnection(connection_id
,
66 false /* owns_writer */,
67 false /* is_server */,
71 void SetSendAlgorithm(SendAlgorithmInterface
* send_algorithm
) {
72 QuicConnectionPeer::SetSendAlgorithm(this, send_algorithm
);
75 void SetReceiveAlgorithm(ReceiveAlgorithmInterface
* receive_algorithm
) {
76 QuicConnectionPeer::SetReceiveAlgorithm(this, receive_algorithm
);
80 class TestReceiveAlgorithm
: public ReceiveAlgorithmInterface
{
82 virtual bool GenerateCongestionFeedback(
83 QuicCongestionFeedbackFrame
* /*congestion_feedback*/) {
87 MOCK_METHOD3(RecordIncomingPacket
,
88 void(QuicByteCount
, QuicPacketSequenceNumber
, QuicTime
));
91 // Subclass of QuicHttpStream that closes itself when the first piece of data
93 class AutoClosingStream
: public QuicHttpStream
{
95 explicit AutoClosingStream(const base::WeakPtr
<QuicClientSession
>& session
)
96 : QuicHttpStream(session
) {
99 virtual int OnDataReceived(const char* data
, int length
) OVERRIDE
{
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_
),
139 random_generator_(0) {
141 CHECK(ParseIPLiteralToNumber("192.0.2.33", &ip
));
142 peer_addr_
= IPEndPoint(ip
, 443);
143 self_addr_
= IPEndPoint(ip
, 8435);
146 ~QuicHttpStreamTest() {
147 session_
->CloseSessionOnError(ERR_ABORTED
);
148 for (size_t i
= 0; i
< writes_
.size(); i
++) {
149 delete writes_
[i
].packet
;
153 // Adds a packet to the list of expected writes.
154 void AddWrite(scoped_ptr
<QuicEncryptedPacket
> packet
) {
155 writes_
.push_back(PacketToWrite(SYNCHRONOUS
, packet
.release()));
158 // Returns the packet to be written at position |pos|.
159 QuicEncryptedPacket
* GetWrite(size_t pos
) {
160 return writes_
[pos
].packet
;
164 return socket_data_
->at_read_eof() && socket_data_
->at_write_eof();
167 void ProcessPacket(scoped_ptr
<QuicEncryptedPacket
> packet
) {
168 connection_
->ProcessUdpPacket(self_addr_
, peer_addr_
, *packet
);
171 // Configures the test fixture to use the list of expected writes.
173 mock_writes_
.reset(new MockWrite
[writes_
.size()]);
174 for (size_t i
= 0; i
< writes_
.size(); i
++) {
175 mock_writes_
[i
] = MockWrite(writes_
[i
].mode
,
176 writes_
[i
].packet
->data(),
177 writes_
[i
].packet
->length());
180 socket_data_
.reset(new StaticSocketDataProvider(NULL
, 0, mock_writes_
.get(),
183 MockUDPClientSocket
* socket
= new MockUDPClientSocket(socket_data_
.get(),
185 socket
->Connect(peer_addr_
);
186 runner_
= new TestTaskRunner(&clock_
);
187 send_algorithm_
= new MockSendAlgorithm();
188 receive_algorithm_
= new TestReceiveAlgorithm();
189 EXPECT_CALL(*receive_algorithm_
, RecordIncomingPacket(_
, _
, _
)).
191 EXPECT_CALL(*send_algorithm_
,
192 OnPacketSent(_
, _
, _
, _
, _
)).WillRepeatedly(Return(true));
193 EXPECT_CALL(*send_algorithm_
, RetransmissionDelay()).WillRepeatedly(
194 Return(QuicTime::Delta::Zero()));
195 EXPECT_CALL(*send_algorithm_
, GetCongestionWindow()).WillRepeatedly(
196 Return(kMaxPacketSize
));
197 EXPECT_CALL(*send_algorithm_
, TimeUntilSend(_
, _
, _
)).
198 WillRepeatedly(Return(QuicTime::Delta::Zero()));
199 EXPECT_CALL(*send_algorithm_
, BandwidthEstimate()).WillRepeatedly(
200 Return(QuicBandwidth::Zero()));
201 EXPECT_CALL(*send_algorithm_
, SetFromConfig(_
, _
)).Times(AnyNumber());
202 helper_
.reset(new QuicConnectionHelper(runner_
.get(), &clock_
,
203 &random_generator_
));
204 writer_
.reset(new QuicDefaultPacketWriter(socket
));
205 connection_
= new TestQuicConnection(SupportedVersions(GetParam()),
206 connection_id_
, peer_addr_
,
207 helper_
.get(), writer_
.get());
208 connection_
->set_visitor(&visitor_
);
209 connection_
->SetSendAlgorithm(send_algorithm_
);
210 connection_
->SetReceiveAlgorithm(receive_algorithm_
);
211 crypto_config_
.SetDefaults();
213 new QuicClientSession(connection_
,
214 scoped_ptr
<DatagramClientSocket
>(socket
),
215 writer_
.Pass(), NULL
,
216 &crypto_client_stream_factory_
,
217 make_scoped_ptr((QuicServerInfo
*)NULL
),
218 QuicServerId(kServerHostname
, kServerPort
,
219 false, PRIVACY_MODE_DISABLED
),
220 DefaultQuicConfig(), &crypto_config_
,
221 base::MessageLoop::current()->
222 message_loop_proxy().get(),
224 session_
->InitializeSession();
225 session_
->GetCryptoStream()->CryptoConnect();
226 EXPECT_TRUE(session_
->IsCryptoHandshakeConfirmed());
227 stream_
.reset(use_closing_stream_
?
228 new AutoClosingStream(session_
->GetWeakPtr()) :
229 new QuicHttpStream(session_
->GetWeakPtr()));
230 clock_
.AdvanceTime(QuicTime::Delta::FromMilliseconds(20));
233 void SetRequest(const std::string
& method
,
234 const std::string
& path
,
235 RequestPriority priority
) {
236 request_headers_
= maker_
.GetRequestHeaders(method
, "http", path
);
239 void SetResponse(const std::string
& status
, const std::string
& body
) {
240 response_headers_
= maker_
.GetResponseHeaders(status
);
241 response_data_
= body
;
244 scoped_ptr
<QuicEncryptedPacket
> ConstructDataPacket(
245 QuicPacketSequenceNumber sequence_number
,
246 bool should_include_version
,
248 QuicStreamOffset offset
,
249 base::StringPiece data
) {
250 return maker_
.MakeDataPacket(
251 sequence_number
, stream_id_
, should_include_version
, fin
, offset
, data
);
254 scoped_ptr
<QuicEncryptedPacket
> ConstructRequestHeadersPacket(
255 QuicPacketSequenceNumber sequence_number
,
257 return maker_
.MakeRequestHeadersPacket(
258 sequence_number
, stream_id_
, kIncludeVersion
, fin
, request_headers_
);
261 scoped_ptr
<QuicEncryptedPacket
> ConstructResponseHeadersPacket(
262 QuicPacketSequenceNumber sequence_number
,
264 return maker_
.MakeResponseHeadersPacket(
265 sequence_number
, stream_id_
, !kIncludeVersion
, fin
, response_headers_
);
268 scoped_ptr
<QuicEncryptedPacket
> ConstructRstStreamPacket(
269 QuicPacketSequenceNumber sequence_number
) {
270 return maker_
.MakeRstPacket(
271 sequence_number
, true, stream_id_
,
272 AdjustErrorForVersion(QUIC_RST_FLOW_CONTROL_ACCOUNTING
, GetParam()));
275 scoped_ptr
<QuicEncryptedPacket
> ConstructAckAndRstStreamPacket(
276 QuicPacketSequenceNumber sequence_number
) {
277 return maker_
.MakeAckAndRstPacket(
278 sequence_number
, !kIncludeVersion
, stream_id_
, QUIC_STREAM_CANCELLED
,
279 2, 1, !kIncludeCongestionFeedback
);
282 scoped_ptr
<QuicEncryptedPacket
> ConstructAckPacket(
283 QuicPacketSequenceNumber sequence_number
,
284 QuicPacketSequenceNumber largest_received
,
285 QuicPacketSequenceNumber least_unacked
) {
286 return maker_
.MakeAckPacket(sequence_number
, largest_received
,
287 least_unacked
, !kIncludeCongestionFeedback
);
290 BoundNetLog net_log_
;
291 bool use_closing_stream_
;
292 MockSendAlgorithm
* send_algorithm_
;
293 TestReceiveAlgorithm
* receive_algorithm_
;
294 scoped_refptr
<TestTaskRunner
> runner_
;
295 scoped_ptr
<MockWrite
[]> mock_writes_
;
297 TestQuicConnection
* connection_
;
298 scoped_ptr
<QuicConnectionHelper
> helper_
;
299 testing::StrictMock
<MockConnectionVisitor
> visitor_
;
300 scoped_ptr
<QuicHttpStream
> stream_
;
301 scoped_ptr
<QuicDefaultPacketWriter
> writer_
;
302 scoped_ptr
<QuicClientSession
> session_
;
303 QuicCryptoClientConfig crypto_config_
;
304 TestCompletionCallback callback_
;
305 HttpRequestInfo request_
;
306 HttpRequestHeaders headers_
;
307 HttpResponseInfo response_
;
308 scoped_refptr
<IOBufferWithSize
> read_buffer_
;
309 SpdyHeaderBlock request_headers_
;
310 SpdyHeaderBlock response_headers_
;
311 std::string request_data_
;
312 std::string response_data_
;
315 const QuicConnectionId connection_id_
;
316 const QuicStreamId stream_id_
;
317 QuicTestPacketMaker maker_
;
318 IPEndPoint self_addr_
;
319 IPEndPoint peer_addr_
;
320 MockRandom random_generator_
;
321 MockCryptoClientStreamFactory crypto_client_stream_factory_
;
322 scoped_ptr
<StaticSocketDataProvider
> socket_data_
;
323 std::vector
<PacketToWrite
> writes_
;
326 INSTANTIATE_TEST_CASE_P(Version
, QuicHttpStreamTest
,
327 ::testing::ValuesIn(QuicSupportedVersions()));
329 TEST_P(QuicHttpStreamTest
, RenewStreamForAuth
) {
331 EXPECT_EQ(NULL
, stream_
->RenewStreamForAuth());
334 TEST_P(QuicHttpStreamTest
, CanFindEndOfResponse
) {
336 EXPECT_TRUE(stream_
->CanFindEndOfResponse());
339 TEST_P(QuicHttpStreamTest
, IsConnectionReusable
) {
341 EXPECT_FALSE(stream_
->IsConnectionReusable());
344 TEST_P(QuicHttpStreamTest
, GetRequest
) {
345 SetRequest("GET", "/", DEFAULT_PRIORITY
);
346 AddWrite(ConstructRequestHeadersPacket(1, kFin
));
349 request_
.method
= "GET";
350 request_
.url
= GURL("http://www.google.com/");
352 EXPECT_EQ(OK
, stream_
->InitializeStream(&request_
, DEFAULT_PRIORITY
,
353 net_log_
, callback_
.callback()));
354 EXPECT_EQ(OK
, stream_
->SendRequest(headers_
, &response_
,
355 callback_
.callback()));
358 ProcessPacket(ConstructAckPacket(1, 0, 0));
360 EXPECT_EQ(ERR_IO_PENDING
,
361 stream_
->ReadResponseHeaders(callback_
.callback()));
363 SetResponse("404 Not Found", std::string());
364 ProcessPacket(ConstructResponseHeadersPacket(2, kFin
));
366 // Now that the headers have been processed, the callback will return.
367 EXPECT_EQ(OK
, callback_
.WaitForResult());
368 ASSERT_TRUE(response_
.headers
.get());
369 EXPECT_EQ(404, response_
.headers
->response_code());
370 EXPECT_TRUE(response_
.headers
->HasHeaderValue("Content-Type", "text/plain"));
371 EXPECT_FALSE(response_
.response_time
.is_null());
372 EXPECT_FALSE(response_
.request_time
.is_null());
374 // There is no body, so this should return immediately.
375 EXPECT_EQ(0, stream_
->ReadResponseBody(read_buffer_
.get(),
376 read_buffer_
->size(),
377 callback_
.callback()));
378 EXPECT_TRUE(stream_
->IsResponseBodyComplete());
379 EXPECT_TRUE(AtEof());
382 // Regression test for http://crbug.com/288128
383 TEST_P(QuicHttpStreamTest
, GetRequestLargeResponse
) {
384 SetRequest("GET", "/", DEFAULT_PRIORITY
);
385 AddWrite(ConstructRequestHeadersPacket(1, kFin
));
388 request_
.method
= "GET";
389 request_
.url
= GURL("http://www.google.com/");
391 EXPECT_EQ(OK
, stream_
->InitializeStream(&request_
, DEFAULT_PRIORITY
,
392 net_log_
, callback_
.callback()));
393 EXPECT_EQ(OK
, stream_
->SendRequest(headers_
, &response_
,
394 callback_
.callback()));
397 ProcessPacket(ConstructAckPacket(1, 0, 0));
399 EXPECT_EQ(ERR_IO_PENDING
,
400 stream_
->ReadResponseHeaders(callback_
.callback()));
402 SpdyHeaderBlock headers
;
403 headers
[":status"] = "200 OK";
404 headers
[":version"] = "HTTP/1.1";
405 headers
["content-type"] = "text/plain";
406 headers
["big6"] = std::string(10000, 'x'); // Lots of x's.
408 std::string response
= SpdyUtils::SerializeUncompressedHeaders(headers
);
409 EXPECT_LT(4096u, response
.length());
410 stream_
->OnDataReceived(response
.data(), response
.length());
411 stream_
->OnClose(QUIC_NO_ERROR
);
413 // Now that the headers have been processed, the callback will return.
414 EXPECT_EQ(OK
, callback_
.WaitForResult());
415 ASSERT_TRUE(response_
.headers
.get());
416 EXPECT_EQ(200, response_
.headers
->response_code());
417 EXPECT_TRUE(response_
.headers
->HasHeaderValue("Content-Type", "text/plain"));
419 // There is no body, so this should return immediately.
420 EXPECT_EQ(0, stream_
->ReadResponseBody(read_buffer_
.get(),
421 read_buffer_
->size(),
422 callback_
.callback()));
423 EXPECT_TRUE(stream_
->IsResponseBodyComplete());
424 EXPECT_TRUE(AtEof());
427 TEST_P(QuicHttpStreamTest
, SendPostRequest
) {
428 SetRequest("POST", "/", DEFAULT_PRIORITY
);
429 AddWrite(ConstructRequestHeadersPacket(1, !kFin
));
430 AddWrite(ConstructDataPacket(2, kIncludeVersion
, kFin
, 0, kUploadData
));
431 AddWrite(ConstructAckPacket(3, 3, 1));
435 ScopedVector
<UploadElementReader
> element_readers
;
436 element_readers
.push_back(
437 new UploadBytesElementReader(kUploadData
, strlen(kUploadData
)));
438 UploadDataStream
upload_data_stream(element_readers
.Pass(), 0);
439 request_
.method
= "POST";
440 request_
.url
= GURL("http://www.google.com/");
441 request_
.upload_data_stream
= &upload_data_stream
;
442 ASSERT_EQ(OK
, request_
.upload_data_stream
->Init(CompletionCallback()));
444 EXPECT_EQ(OK
, stream_
->InitializeStream(&request_
, DEFAULT_PRIORITY
,
445 net_log_
, callback_
.callback()));
446 EXPECT_EQ(OK
, stream_
->SendRequest(headers_
, &response_
,
447 callback_
.callback()));
449 // Ack both packets in the request.
450 ProcessPacket(ConstructAckPacket(1, 0, 0));
452 // Send the response headers (but not the body).
453 SetResponse("200 OK", std::string());
454 ProcessPacket(ConstructResponseHeadersPacket(2, !kFin
));
456 // Since the headers have already arrived, this should return immediately.
457 EXPECT_EQ(OK
, stream_
->ReadResponseHeaders(callback_
.callback()));
458 ASSERT_TRUE(response_
.headers
.get());
459 EXPECT_EQ(200, response_
.headers
->response_code());
460 EXPECT_TRUE(response_
.headers
->HasHeaderValue("Content-Type", "text/plain"));
462 // Send the response body.
463 const char kResponseBody
[] = "Hello world!";
464 ProcessPacket(ConstructDataPacket(3, false, kFin
, 0, kResponseBody
));
465 // Since the body has already arrived, this should return immediately.
466 EXPECT_EQ(static_cast<int>(strlen(kResponseBody
)),
467 stream_
->ReadResponseBody(read_buffer_
.get(), read_buffer_
->size(),
468 callback_
.callback()));
470 EXPECT_TRUE(stream_
->IsResponseBodyComplete());
471 EXPECT_TRUE(AtEof());
474 TEST_P(QuicHttpStreamTest
, SendChunkedPostRequest
) {
475 SetRequest("POST", "/", DEFAULT_PRIORITY
);
476 size_t chunk_size
= strlen(kUploadData
);
477 AddWrite(ConstructRequestHeadersPacket(1, !kFin
));
478 AddWrite(ConstructDataPacket(2, kIncludeVersion
, !kFin
, 0, kUploadData
));
479 AddWrite(ConstructDataPacket(3, kIncludeVersion
, kFin
, chunk_size
,
481 AddWrite(ConstructAckPacket(4, 3, 1));
484 UploadDataStream
upload_data_stream(UploadDataStream::CHUNKED
, 0);
485 upload_data_stream
.AppendChunk(kUploadData
, chunk_size
, false);
487 request_
.method
= "POST";
488 request_
.url
= GURL("http://www.google.com/");
489 request_
.upload_data_stream
= &upload_data_stream
;
490 ASSERT_EQ(OK
, request_
.upload_data_stream
->Init(CompletionCallback()));
492 ASSERT_EQ(OK
, stream_
->InitializeStream(&request_
, DEFAULT_PRIORITY
,
493 net_log_
, callback_
.callback()));
494 ASSERT_EQ(ERR_IO_PENDING
, stream_
->SendRequest(headers_
, &response_
,
495 callback_
.callback()));
497 upload_data_stream
.AppendChunk(kUploadData
, chunk_size
, true);
499 // Ack both packets in the request.
500 ProcessPacket(ConstructAckPacket(1, 0, 0));
502 // Send the response headers (but not the body).
503 SetResponse("200 OK", std::string());
504 ProcessPacket(ConstructResponseHeadersPacket(2, !kFin
));
506 // Since the headers have already arrived, this should return immediately.
507 ASSERT_EQ(OK
, stream_
->ReadResponseHeaders(callback_
.callback()));
508 ASSERT_TRUE(response_
.headers
.get());
509 EXPECT_EQ(200, response_
.headers
->response_code());
510 EXPECT_TRUE(response_
.headers
->HasHeaderValue("Content-Type", "text/plain"));
512 // Send the response body.
513 const char kResponseBody
[] = "Hello world!";
514 ProcessPacket(ConstructDataPacket(3, false, kFin
, response_data_
.length(),
517 // Since the body has already arrived, this should return immediately.
518 ASSERT_EQ(static_cast<int>(strlen(kResponseBody
)),
519 stream_
->ReadResponseBody(read_buffer_
.get(), read_buffer_
->size(),
520 callback_
.callback()));
522 EXPECT_TRUE(stream_
->IsResponseBodyComplete());
523 EXPECT_TRUE(AtEof());
526 TEST_P(QuicHttpStreamTest
, DestroyedEarly
) {
527 SetRequest("GET", "/", DEFAULT_PRIORITY
);
528 AddWrite(ConstructRequestHeadersPacket(1, kFin
));
529 AddWrite(ConstructAckAndRstStreamPacket(2));
530 use_closing_stream_
= true;
533 request_
.method
= "GET";
534 request_
.url
= GURL("http://www.google.com/");
536 EXPECT_EQ(OK
, stream_
->InitializeStream(&request_
, DEFAULT_PRIORITY
,
537 net_log_
, callback_
.callback()));
538 EXPECT_EQ(OK
, stream_
->SendRequest(headers_
, &response_
,
539 callback_
.callback()));
542 ProcessPacket(ConstructAckPacket(1, 0, 0));
543 EXPECT_EQ(ERR_IO_PENDING
,
544 stream_
->ReadResponseHeaders(callback_
.callback()));
546 // Send the response with a body.
547 SetResponse("404 OK", "hello world!");
548 // In the course of processing this packet, the QuicHttpStream close itself.
549 ProcessPacket(ConstructResponseHeadersPacket(2, kFin
));
551 EXPECT_TRUE(AtEof());
554 TEST_P(QuicHttpStreamTest
, Priority
) {
555 SetRequest("GET", "/", MEDIUM
);
556 AddWrite(ConstructRequestHeadersPacket(1, kFin
));
557 AddWrite(ConstructAckAndRstStreamPacket(2));
558 use_closing_stream_
= true;
561 request_
.method
= "GET";
562 request_
.url
= GURL("http://www.google.com/");
564 EXPECT_EQ(OK
, stream_
->InitializeStream(&request_
, MEDIUM
,
565 net_log_
, callback_
.callback()));
567 // Check that priority is highest.
568 QuicReliableClientStream
* reliable_stream
=
569 QuicHttpStreamPeer::GetQuicReliableClientStream(stream_
.get());
570 DCHECK(reliable_stream
);
571 DCHECK_EQ(QuicWriteBlockedList::kHighestPriority
,
572 reliable_stream
->EffectivePriority());
574 EXPECT_EQ(OK
, stream_
->SendRequest(headers_
, &response_
,
575 callback_
.callback()));
577 // Check that priority has now dropped back to MEDIUM.
578 DCHECK_EQ(MEDIUM
, ConvertQuicPriorityToRequestPriority(
579 reliable_stream
->EffectivePriority()));
582 ProcessPacket(ConstructAckPacket(1, 0, 0));
583 EXPECT_EQ(ERR_IO_PENDING
,
584 stream_
->ReadResponseHeaders(callback_
.callback()));
586 // Send the response with a body.
587 SetResponse("404 OK", "hello world!");
588 // In the course of processing this packet, the QuicHttpStream close itself.
589 ProcessPacket(ConstructResponseHeadersPacket(2, kFin
));
591 EXPECT_TRUE(AtEof());
594 // Regression test for http://crbug.com/294870
595 TEST_P(QuicHttpStreamTest
, CheckPriorityWithNoDelegate
) {
596 SetRequest("GET", "/", MEDIUM
);
597 use_closing_stream_
= true;
599 AddWrite(ConstructRstStreamPacket(1));
603 request_
.method
= "GET";
604 request_
.url
= GURL("http://www.google.com/");
606 EXPECT_EQ(OK
, stream_
->InitializeStream(&request_
, MEDIUM
,
607 net_log_
, callback_
.callback()));
609 // Check that priority is highest.
610 QuicReliableClientStream
* reliable_stream
=
611 QuicHttpStreamPeer::GetQuicReliableClientStream(stream_
.get());
612 DCHECK(reliable_stream
);
613 QuicReliableClientStream::Delegate
* delegate
= reliable_stream
->GetDelegate();
615 DCHECK_EQ(QuicWriteBlockedList::kHighestPriority
,
616 reliable_stream
->EffectivePriority());
618 // Set Delegate to NULL and make sure EffectivePriority returns highest
620 reliable_stream
->SetDelegate(NULL
);
621 DCHECK_EQ(QuicWriteBlockedList::kHighestPriority
,
622 reliable_stream
->EffectivePriority());
623 reliable_stream
->SetDelegate(delegate
);