Adding yfriedman@ as owner for the enhanced_bookmarks component.
[chromium-blink-merge.git] / net / quic / quic_http_stream_test.cc
blob5e46258f2cbce5d46a4b131e3722ffcf0fdd7451
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"
7 #include <vector>
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"
43 using testing::_;
44 using testing::AnyNumber;
45 using testing::Return;
47 namespace net {
48 namespace test {
49 namespace {
51 const char kUploadData[] = "hello world!";
52 const char kServerHostname[] = "www.google.com";
53 const uint16 kServerPort = 80;
55 class TestQuicConnection : public QuicConnection {
56 public:
57 TestQuicConnection(const QuicVersionVector& versions,
58 QuicConnectionId connection_id,
59 IPEndPoint address,
60 QuicConnectionHelper* helper,
61 QuicPacketWriter* writer)
62 : QuicConnection(connection_id,
63 address,
64 helper,
65 writer,
66 false /* owns_writer */,
67 false /* is_server */,
68 versions) {
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 {
81 public:
82 virtual bool GenerateCongestionFeedback(
83 QuicCongestionFeedbackFrame* /*congestion_feedback*/) {
84 return false;
87 MOCK_METHOD3(RecordIncomingPacket,
88 void(QuicByteCount, QuicPacketSequenceNumber, QuicTime));
91 // Subclass of QuicHttpStream that closes itself when the first piece of data
92 // is received.
93 class AutoClosingStream : public QuicHttpStream {
94 public:
95 explicit AutoClosingStream(const base::WeakPtr<QuicClientSession>& session)
96 : QuicHttpStream(session) {
99 virtual int OnDataReceived(const char* data, int length) OVERRIDE {
100 Close(false);
101 return OK;
105 } // namespace
107 class QuicHttpStreamPeer {
108 public:
109 static QuicReliableClientStream* GetQuicReliableClientStream(
110 QuicHttpStream* stream) {
111 return stream->stream_;
115 class QuicHttpStreamTest : public ::testing::TestWithParam<QuicVersion> {
116 protected:
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)
125 : mode(mode),
126 packet(packet) {
128 IoMode mode;
129 QuicEncryptedPacket* packet;
132 QuicHttpStreamTest()
133 : net_log_(BoundNetLog()),
134 use_closing_stream_(false),
135 read_buffer_(new IOBufferWithSize(4096)),
136 connection_id_(2),
137 stream_id_(kClientDataStreamId1),
138 maker_(GetParam(), connection_id_),
139 random_generator_(0) {
140 IPAddressNumber ip;
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;
163 bool AtEof() {
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.
172 void Initialize() {
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(),
181 writes_.size()));
183 MockUDPClientSocket* socket = new MockUDPClientSocket(socket_data_.get(),
184 net_log_.net_log());
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(_, _, _)).
190 Times(AnyNumber());
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();
212 session_.reset(
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(),
223 NULL));
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,
247 bool fin,
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,
256 bool fin) {
257 return maker_.MakeRequestHeadersPacket(
258 sequence_number, stream_id_, kIncludeVersion, fin, request_headers_);
261 scoped_ptr<QuicEncryptedPacket> ConstructResponseHeadersPacket(
262 QuicPacketSequenceNumber sequence_number,
263 bool fin) {
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_;
296 MockClock clock_;
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_;
314 private:
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) {
330 Initialize();
331 EXPECT_EQ(NULL, stream_->RenewStreamForAuth());
334 TEST_P(QuicHttpStreamTest, CanFindEndOfResponse) {
335 Initialize();
336 EXPECT_TRUE(stream_->CanFindEndOfResponse());
339 TEST_P(QuicHttpStreamTest, IsConnectionReusable) {
340 Initialize();
341 EXPECT_FALSE(stream_->IsConnectionReusable());
344 TEST_P(QuicHttpStreamTest, GetRequest) {
345 SetRequest("GET", "/", DEFAULT_PRIORITY);
346 AddWrite(ConstructRequestHeadersPacket(1, kFin));
347 Initialize();
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()));
357 // Ack the request.
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));
386 Initialize();
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()));
396 // Ack the request.
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));
433 Initialize();
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,
480 kUploadData));
481 AddWrite(ConstructAckPacket(4, 3, 1));
482 Initialize();
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(),
515 kResponseBody));
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;
531 Initialize();
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()));
541 // Ack the request.
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;
559 Initialize();
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()));
581 // Ack the request.
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));
601 Initialize();
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();
614 DCHECK(delegate);
615 DCHECK_EQ(QuicWriteBlockedList::kHighestPriority,
616 reliable_stream->EffectivePriority());
618 // Set Delegate to NULL and make sure EffectivePriority returns highest
619 // priority.
620 reliable_stream->SetDelegate(NULL);
621 DCHECK_EQ(QuicWriteBlockedList::kHighestPriority,
622 reliable_stream->EffectivePriority());
623 reliable_stream->SetDelegate(delegate);
626 } // namespace test
627 } // namespace net