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, address, helper, writer, false,
63 versions, kInitialFlowControlWindowForTest) {
66 void SetSendAlgorithm(SendAlgorithmInterface* send_algorithm) {
67 QuicConnectionPeer::SetSendAlgorithm(this, send_algorithm);
70 void SetReceiveAlgorithm(ReceiveAlgorithmInterface* receive_algorithm) {
71 QuicConnectionPeer::SetReceiveAlgorithm(this, receive_algorithm);
75 class TestReceiveAlgorithm : public ReceiveAlgorithmInterface {
77 virtual bool GenerateCongestionFeedback(
78 QuicCongestionFeedbackFrame* /*congestion_feedback*/) {
82 MOCK_METHOD3(RecordIncomingPacket,
83 void(QuicByteCount, QuicPacketSequenceNumber, QuicTime));
86 // Subclass of QuicHttpStream that closes itself when the first piece of data
88 class AutoClosingStream : public QuicHttpStream {
90 explicit AutoClosingStream(const base::WeakPtr<QuicClientSession>& session)
91 : QuicHttpStream(session) {
94 virtual int OnDataReceived(const char* data, int length) OVERRIDE {
102 class QuicHttpStreamPeer {
104 static QuicReliableClientStream* GetQuicReliableClientStream(
105 QuicHttpStream* stream) {
106 return stream->stream_;
110 class QuicHttpStreamTest : public ::testing::TestWithParam<QuicVersion> {
112 static const bool kFin = true;
113 static const bool kIncludeVersion = true;
114 static const bool kIncludeCongestionFeedback = true;
116 // Holds a packet to be written to the wire, and the IO mode that should
117 // be used by the mock socket when performing the write.
118 struct PacketToWrite {
119 PacketToWrite(IoMode mode, QuicEncryptedPacket* packet)
124 QuicEncryptedPacket* packet;
128 : net_log_(BoundNetLog()),
129 use_closing_stream_(false),
130 read_buffer_(new IOBufferWithSize(4096)),
133 maker_(GetParam(), connection_id_),
134 random_generator_(0) {
136 CHECK(ParseIPLiteralToNumber("192.0.2.33", &ip));
137 peer_addr_ = IPEndPoint(ip, 443);
138 self_addr_ = IPEndPoint(ip, 8435);
141 ~QuicHttpStreamTest() {
142 session_->CloseSessionOnError(ERR_ABORTED);
143 for (size_t i = 0; i < writes_.size(); i++) {
144 delete writes_[i].packet;
148 // Adds a packet to the list of expected writes.
149 void AddWrite(scoped_ptr<QuicEncryptedPacket> packet) {
150 writes_.push_back(PacketToWrite(SYNCHRONOUS, packet.release()));
153 // Returns the packet to be written at position |pos|.
154 QuicEncryptedPacket* GetWrite(size_t pos) {
155 return writes_[pos].packet;
159 return socket_data_->at_read_eof() && socket_data_->at_write_eof();
162 void ProcessPacket(scoped_ptr<QuicEncryptedPacket> packet) {
163 connection_->ProcessUdpPacket(self_addr_, peer_addr_, *packet);
166 // Configures the test fixture to use the list of expected writes.
168 mock_writes_.reset(new MockWrite[writes_.size()]);
169 for (size_t i = 0; i < writes_.size(); i++) {
170 mock_writes_[i] = MockWrite(writes_[i].mode,
171 writes_[i].packet->data(),
172 writes_[i].packet->length());
175 socket_data_.reset(new StaticSocketDataProvider(NULL, 0, mock_writes_.get(),
178 MockUDPClientSocket* socket = new MockUDPClientSocket(socket_data_.get(),
180 socket->Connect(peer_addr_);
181 runner_ = new TestTaskRunner(&clock_);
182 send_algorithm_ = new MockSendAlgorithm();
183 receive_algorithm_ = new TestReceiveAlgorithm();
184 EXPECT_CALL(*receive_algorithm_, RecordIncomingPacket(_, _, _)).
186 EXPECT_CALL(*send_algorithm_,
187 OnPacketSent(_, _, _, _, _)).WillRepeatedly(Return(true));
188 EXPECT_CALL(*send_algorithm_, RetransmissionDelay()).WillRepeatedly(
189 Return(QuicTime::Delta::Zero()));
190 EXPECT_CALL(*send_algorithm_, GetCongestionWindow()).WillRepeatedly(
191 Return(kMaxPacketSize));
192 EXPECT_CALL(*send_algorithm_, TimeUntilSend(_, _, _)).
193 WillRepeatedly(Return(QuicTime::Delta::Zero()));
194 EXPECT_CALL(*send_algorithm_, BandwidthEstimate()).WillRepeatedly(
195 Return(QuicBandwidth::Zero()));
196 EXPECT_CALL(*send_algorithm_, SetFromConfig(_, _)).Times(AnyNumber());
197 helper_.reset(new QuicConnectionHelper(runner_.get(), &clock_,
198 &random_generator_));
199 writer_.reset(new QuicDefaultPacketWriter(socket));
200 connection_ = new TestQuicConnection(SupportedVersions(GetParam()),
201 connection_id_, peer_addr_,
202 helper_.get(), writer_.get());
203 connection_->set_visitor(&visitor_);
204 connection_->SetSendAlgorithm(send_algorithm_);
205 connection_->SetReceiveAlgorithm(receive_algorithm_);
206 crypto_config_.SetDefaults();
208 new QuicClientSession(connection_,
209 scoped_ptr<DatagramClientSocket>(socket),
210 writer_.Pass(), NULL,
211 &crypto_client_stream_factory_,
212 make_scoped_ptr((QuicServerInfo*)NULL),
213 QuicServerId(kServerHostname, kServerPort,
214 false, PRIVACY_MODE_DISABLED),
215 DefaultQuicConfig(), &crypto_config_, NULL));
216 session_->GetCryptoStream()->CryptoConnect();
217 EXPECT_TRUE(session_->IsCryptoHandshakeConfirmed());
218 stream_.reset(use_closing_stream_ ?
219 new AutoClosingStream(session_->GetWeakPtr()) :
220 new QuicHttpStream(session_->GetWeakPtr()));
221 clock_.AdvanceTime(QuicTime::Delta::FromMilliseconds(20));
224 void SetRequest(const std::string& method,
225 const std::string& path,
226 RequestPriority priority) {
227 request_headers_ = maker_.GetRequestHeaders(method, "http", path);
230 void SetResponse(const std::string& status, const std::string& body) {
231 response_headers_ = maker_.GetResponseHeaders(status);
232 response_data_ = body;
235 scoped_ptr<QuicEncryptedPacket> ConstructDataPacket(
236 QuicPacketSequenceNumber sequence_number,
237 bool should_include_version,
239 QuicStreamOffset offset,
240 base::StringPiece data) {
241 return maker_.MakeDataPacket(
242 sequence_number, stream_id_, should_include_version, fin, offset, data);
245 scoped_ptr<QuicEncryptedPacket> ConstructRequestHeadersPacket(
246 QuicPacketSequenceNumber sequence_number,
248 return maker_.MakeRequestHeadersPacket(
249 sequence_number, stream_id_, kIncludeVersion, fin, request_headers_);
252 scoped_ptr<QuicEncryptedPacket> ConstructResponseHeadersPacket(
253 QuicPacketSequenceNumber sequence_number,
255 return maker_.MakeResponseHeadersPacket(
256 sequence_number, stream_id_, !kIncludeVersion, fin, response_headers_);
259 scoped_ptr<QuicEncryptedPacket> ConstructRstStreamPacket(
260 QuicPacketSequenceNumber sequence_number) {
261 return maker_.MakeRstPacket(
262 sequence_number, true, stream_id_,
263 AdjustErrorForVersion(QUIC_RST_FLOW_CONTROL_ACCOUNTING, GetParam()));
266 scoped_ptr<QuicEncryptedPacket> ConstructAckAndRstStreamPacket(
267 QuicPacketSequenceNumber sequence_number) {
268 return maker_.MakeAckAndRstPacket(
269 sequence_number, !kIncludeVersion, stream_id_, QUIC_STREAM_CANCELLED,
270 2, 1, !kIncludeCongestionFeedback);
273 scoped_ptr<QuicEncryptedPacket> ConstructAckPacket(
274 QuicPacketSequenceNumber sequence_number,
275 QuicPacketSequenceNumber largest_received,
276 QuicPacketSequenceNumber least_unacked) {
277 return maker_.MakeAckPacket(sequence_number, largest_received,
278 least_unacked, !kIncludeCongestionFeedback);
281 BoundNetLog net_log_;
282 bool use_closing_stream_;
283 MockSendAlgorithm* send_algorithm_;
284 TestReceiveAlgorithm* receive_algorithm_;
285 scoped_refptr<TestTaskRunner> runner_;
286 scoped_ptr<MockWrite[]> mock_writes_;
288 TestQuicConnection* connection_;
289 scoped_ptr<QuicConnectionHelper> helper_;
290 testing::StrictMock<MockConnectionVisitor> visitor_;
291 scoped_ptr<QuicHttpStream> stream_;
292 scoped_ptr<QuicDefaultPacketWriter> writer_;
293 scoped_ptr<QuicClientSession> session_;
294 QuicCryptoClientConfig crypto_config_;
295 TestCompletionCallback callback_;
296 HttpRequestInfo request_;
297 HttpRequestHeaders headers_;
298 HttpResponseInfo response_;
299 scoped_refptr<IOBufferWithSize> read_buffer_;
300 SpdyHeaderBlock request_headers_;
301 SpdyHeaderBlock response_headers_;
302 std::string request_data_;
303 std::string response_data_;
306 const QuicConnectionId connection_id_;
307 const QuicStreamId stream_id_;
308 QuicTestPacketMaker maker_;
309 IPEndPoint self_addr_;
310 IPEndPoint peer_addr_;
311 MockRandom random_generator_;
312 MockCryptoClientStreamFactory crypto_client_stream_factory_;
313 scoped_ptr<StaticSocketDataProvider> socket_data_;
314 std::vector<PacketToWrite> writes_;
317 INSTANTIATE_TEST_CASE_P(Version, QuicHttpStreamTest,
318 ::testing::ValuesIn(QuicSupportedVersions()));
320 TEST_P(QuicHttpStreamTest, RenewStreamForAuth) {
322 EXPECT_EQ(NULL, stream_->RenewStreamForAuth());
325 TEST_P(QuicHttpStreamTest, CanFindEndOfResponse) {
327 EXPECT_TRUE(stream_->CanFindEndOfResponse());
330 TEST_P(QuicHttpStreamTest, IsConnectionReusable) {
332 EXPECT_FALSE(stream_->IsConnectionReusable());
335 TEST_P(QuicHttpStreamTest, GetRequest) {
336 SetRequest("GET", "/", DEFAULT_PRIORITY);
337 AddWrite(ConstructRequestHeadersPacket(1, kFin));
340 request_.method = "GET";
341 request_.url = GURL("http://www.google.com/");
343 EXPECT_EQ(OK, stream_->InitializeStream(&request_, DEFAULT_PRIORITY,
344 net_log_, callback_.callback()));
345 EXPECT_EQ(OK, stream_->SendRequest(headers_, &response_,
346 callback_.callback()));
347 EXPECT_EQ(&response_, stream_->GetResponseInfo());
350 ProcessPacket(ConstructAckPacket(1, 0, 0));
352 EXPECT_EQ(ERR_IO_PENDING,
353 stream_->ReadResponseHeaders(callback_.callback()));
355 SetResponse("404 Not Found", std::string());
356 ProcessPacket(ConstructResponseHeadersPacket(2, kFin));
358 // Now that the headers have been processed, the callback will return.
359 EXPECT_EQ(OK, callback_.WaitForResult());
360 ASSERT_TRUE(response_.headers.get());
361 EXPECT_EQ(404, response_.headers->response_code());
362 EXPECT_TRUE(response_.headers->HasHeaderValue("Content-Type", "text/plain"));
364 // There is no body, so this should return immediately.
365 EXPECT_EQ(0, stream_->ReadResponseBody(read_buffer_.get(),
366 read_buffer_->size(),
367 callback_.callback()));
368 EXPECT_TRUE(stream_->IsResponseBodyComplete());
369 EXPECT_TRUE(AtEof());
372 // Regression test for http://crbug.com/288128
373 TEST_P(QuicHttpStreamTest, GetRequestLargeResponse) {
374 SetRequest("GET", "/", DEFAULT_PRIORITY);
375 AddWrite(ConstructRequestHeadersPacket(1, kFin));
378 request_.method = "GET";
379 request_.url = GURL("http://www.google.com/");
381 EXPECT_EQ(OK, stream_->InitializeStream(&request_, DEFAULT_PRIORITY,
382 net_log_, callback_.callback()));
383 EXPECT_EQ(OK, stream_->SendRequest(headers_, &response_,
384 callback_.callback()));
385 EXPECT_EQ(&response_, stream_->GetResponseInfo());
388 ProcessPacket(ConstructAckPacket(1, 0, 0));
390 EXPECT_EQ(ERR_IO_PENDING,
391 stream_->ReadResponseHeaders(callback_.callback()));
393 SpdyHeaderBlock headers;
394 headers[":status"] = "200 OK";
395 headers[":version"] = "HTTP/1.1";
396 headers["content-type"] = "text/plain";
397 headers["big6"] = std::string(10000, 'x'); // Lots of x's.
399 std::string response = SpdyUtils::SerializeUncompressedHeaders(headers);
400 EXPECT_LT(4096u, response.length());
401 stream_->OnDataReceived(response.data(), response.length());
402 stream_->OnClose(QUIC_NO_ERROR);
404 // Now that the headers have been processed, the callback will return.
405 EXPECT_EQ(OK, callback_.WaitForResult());
406 ASSERT_TRUE(response_.headers.get());
407 EXPECT_EQ(200, response_.headers->response_code());
408 EXPECT_TRUE(response_.headers->HasHeaderValue("Content-Type", "text/plain"));
410 // There is no body, so this should return immediately.
411 EXPECT_EQ(0, stream_->ReadResponseBody(read_buffer_.get(),
412 read_buffer_->size(),
413 callback_.callback()));
414 EXPECT_TRUE(stream_->IsResponseBodyComplete());
415 EXPECT_TRUE(AtEof());
418 TEST_P(QuicHttpStreamTest, SendPostRequest) {
419 SetRequest("POST", "/", DEFAULT_PRIORITY);
420 AddWrite(ConstructRequestHeadersPacket(1, !kFin));
421 AddWrite(ConstructDataPacket(2, kIncludeVersion, kFin, 0, kUploadData));
422 AddWrite(ConstructAckPacket(3, 3, 1));
426 ScopedVector<UploadElementReader> element_readers;
427 element_readers.push_back(
428 new UploadBytesElementReader(kUploadData, strlen(kUploadData)));
429 UploadDataStream upload_data_stream(element_readers.Pass(), 0);
430 request_.method = "POST";
431 request_.url = GURL("http://www.google.com/");
432 request_.upload_data_stream = &upload_data_stream;
433 ASSERT_EQ(OK, request_.upload_data_stream->Init(CompletionCallback()));
435 EXPECT_EQ(OK, stream_->InitializeStream(&request_, DEFAULT_PRIORITY,
436 net_log_, callback_.callback()));
437 EXPECT_EQ(OK, stream_->SendRequest(headers_, &response_,
438 callback_.callback()));
439 EXPECT_EQ(&response_, stream_->GetResponseInfo());
441 // Ack both packets in the request.
442 ProcessPacket(ConstructAckPacket(1, 0, 0));
444 // Send the response headers (but not the body).
445 SetResponse("200 OK", std::string());
446 ProcessPacket(ConstructResponseHeadersPacket(2, !kFin));
448 // Since the headers have already arrived, this should return immediately.
449 EXPECT_EQ(OK, stream_->ReadResponseHeaders(callback_.callback()));
450 ASSERT_TRUE(response_.headers.get());
451 EXPECT_EQ(200, response_.headers->response_code());
452 EXPECT_TRUE(response_.headers->HasHeaderValue("Content-Type", "text/plain"));
454 // Send the response body.
455 const char kResponseBody[] = "Hello world!";
456 ProcessPacket(ConstructDataPacket(3, false, kFin, 0, kResponseBody));
457 // Since the body has already arrived, this should return immediately.
458 EXPECT_EQ(static_cast<int>(strlen(kResponseBody)),
459 stream_->ReadResponseBody(read_buffer_.get(), read_buffer_->size(),
460 callback_.callback()));
462 EXPECT_TRUE(stream_->IsResponseBodyComplete());
463 EXPECT_TRUE(AtEof());
466 TEST_P(QuicHttpStreamTest, SendChunkedPostRequest) {
467 SetRequest("POST", "/", DEFAULT_PRIORITY);
468 size_t chunk_size = strlen(kUploadData);
469 AddWrite(ConstructRequestHeadersPacket(1, !kFin));
470 AddWrite(ConstructDataPacket(2, kIncludeVersion, !kFin, 0, kUploadData));
471 AddWrite(ConstructDataPacket(3, kIncludeVersion, kFin, chunk_size,
473 AddWrite(ConstructAckPacket(4, 3, 1));
476 UploadDataStream upload_data_stream(UploadDataStream::CHUNKED, 0);
477 upload_data_stream.AppendChunk(kUploadData, chunk_size, false);
479 request_.method = "POST";
480 request_.url = GURL("http://www.google.com/");
481 request_.upload_data_stream = &upload_data_stream;
482 ASSERT_EQ(OK, request_.upload_data_stream->Init(CompletionCallback()));
484 ASSERT_EQ(OK, stream_->InitializeStream(&request_, DEFAULT_PRIORITY,
485 net_log_, callback_.callback()));
486 ASSERT_EQ(ERR_IO_PENDING, stream_->SendRequest(headers_, &response_,
487 callback_.callback()));
488 EXPECT_EQ(&response_, stream_->GetResponseInfo());
490 upload_data_stream.AppendChunk(kUploadData, chunk_size, true);
492 // Ack both packets in the request.
493 ProcessPacket(ConstructAckPacket(1, 0, 0));
495 // Send the response headers (but not the body).
496 SetResponse("200 OK", std::string());
497 ProcessPacket(ConstructResponseHeadersPacket(2, !kFin));
499 // Since the headers have already arrived, this should return immediately.
500 ASSERT_EQ(OK, stream_->ReadResponseHeaders(callback_.callback()));
501 ASSERT_TRUE(response_.headers.get());
502 EXPECT_EQ(200, response_.headers->response_code());
503 EXPECT_TRUE(response_.headers->HasHeaderValue("Content-Type", "text/plain"));
505 // Send the response body.
506 const char kResponseBody[] = "Hello world!";
507 ProcessPacket(ConstructDataPacket(3, false, kFin, response_data_.length(),
510 // Since the body has already arrived, this should return immediately.
511 ASSERT_EQ(static_cast<int>(strlen(kResponseBody)),
512 stream_->ReadResponseBody(read_buffer_.get(), read_buffer_->size(),
513 callback_.callback()));
515 EXPECT_TRUE(stream_->IsResponseBodyComplete());
516 EXPECT_TRUE(AtEof());
519 TEST_P(QuicHttpStreamTest, DestroyedEarly) {
520 SetRequest("GET", "/", DEFAULT_PRIORITY);
521 AddWrite(ConstructRequestHeadersPacket(1, kFin));
522 AddWrite(ConstructAckAndRstStreamPacket(2));
523 use_closing_stream_ = true;
526 request_.method = "GET";
527 request_.url = GURL("http://www.google.com/");
529 EXPECT_EQ(OK, stream_->InitializeStream(&request_, DEFAULT_PRIORITY,
530 net_log_, callback_.callback()));
531 EXPECT_EQ(OK, stream_->SendRequest(headers_, &response_,
532 callback_.callback()));
533 EXPECT_EQ(&response_, stream_->GetResponseInfo());
536 ProcessPacket(ConstructAckPacket(1, 0, 0));
537 EXPECT_EQ(ERR_IO_PENDING,
538 stream_->ReadResponseHeaders(callback_.callback()));
540 // Send the response with a body.
541 SetResponse("404 OK", "hello world!");
542 // In the course of processing this packet, the QuicHttpStream close itself.
543 ProcessPacket(ConstructResponseHeadersPacket(2, kFin));
545 EXPECT_TRUE(AtEof());
548 TEST_P(QuicHttpStreamTest, Priority) {
549 SetRequest("GET", "/", MEDIUM);
550 AddWrite(ConstructRequestHeadersPacket(1, kFin));
551 AddWrite(ConstructAckAndRstStreamPacket(2));
552 use_closing_stream_ = true;
555 request_.method = "GET";
556 request_.url = GURL("http://www.google.com/");
558 EXPECT_EQ(OK, stream_->InitializeStream(&request_, MEDIUM,
559 net_log_, callback_.callback()));
561 // Check that priority is highest.
562 QuicReliableClientStream* reliable_stream =
563 QuicHttpStreamPeer::GetQuicReliableClientStream(stream_.get());
564 DCHECK(reliable_stream);
565 DCHECK_EQ(QuicWriteBlockedList::kHighestPriority,
566 reliable_stream->EffectivePriority());
568 EXPECT_EQ(OK, stream_->SendRequest(headers_, &response_,
569 callback_.callback()));
570 EXPECT_EQ(&response_, stream_->GetResponseInfo());
572 // Check that priority has now dropped back to MEDIUM.
573 DCHECK_EQ(MEDIUM, ConvertQuicPriorityToRequestPriority(
574 reliable_stream->EffectivePriority()));
577 ProcessPacket(ConstructAckPacket(1, 0, 0));
578 EXPECT_EQ(ERR_IO_PENDING,
579 stream_->ReadResponseHeaders(callback_.callback()));
581 // Send the response with a body.
582 SetResponse("404 OK", "hello world!");
583 // In the course of processing this packet, the QuicHttpStream close itself.
584 ProcessPacket(ConstructResponseHeadersPacket(2, kFin));
586 EXPECT_TRUE(AtEof());
589 // Regression test for http://crbug.com/294870
590 TEST_P(QuicHttpStreamTest, CheckPriorityWithNoDelegate) {
591 SetRequest("GET", "/", MEDIUM);
592 use_closing_stream_ = true;
594 AddWrite(ConstructRstStreamPacket(1));
598 request_.method = "GET";
599 request_.url = GURL("http://www.google.com/");
601 EXPECT_EQ(OK, stream_->InitializeStream(&request_, MEDIUM,
602 net_log_, callback_.callback()));
604 // Check that priority is highest.
605 QuicReliableClientStream* reliable_stream =
606 QuicHttpStreamPeer::GetQuicReliableClientStream(stream_.get());
607 DCHECK(reliable_stream);
608 QuicReliableClientStream::Delegate* delegate = reliable_stream->GetDelegate();
610 DCHECK_EQ(QuicWriteBlockedList::kHighestPriority,
611 reliable_stream->EffectivePriority());
613 // Set Delegate to NULL and make sure EffectivePriority returns highest
615 reliable_stream->SetDelegate(NULL);
616 DCHECK_EQ(QuicWriteBlockedList::kHighestPriority,
617 reliable_stream->EffectivePriority());
618 reliable_stream->SetDelegate(delegate);