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[] = "hello world!";
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 QuicPacketWriter* writer)
63 : QuicConnection(connection_id,
67 false /* 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 {
108 class QuicHttpStreamPeer {
110 static QuicReliableClientStream* GetQuicReliableClientStream(
111 QuicHttpStream* stream) {
112 return stream->stream_;
116 class QuicHttpStreamTest : public ::testing::TestWithParam<QuicVersion> {
118 static const bool kFin = true;
119 static const bool kIncludeVersion = true;
120 static const bool kIncludeCongestionFeedback = true;
122 // Holds a packet to be written to the wire, and the IO mode that should
123 // be used by the mock socket when performing the write.
124 struct PacketToWrite {
125 PacketToWrite(IoMode mode, QuicEncryptedPacket* packet)
130 QuicEncryptedPacket* packet;
134 : net_log_(BoundNetLog()),
135 use_closing_stream_(false),
136 read_buffer_(new IOBufferWithSize(4096)),
138 stream_id_(kClientDataStreamId1),
139 maker_(GetParam(), connection_id_),
140 random_generator_(0) {
142 CHECK(ParseIPLiteralToNumber("192.0.2.33", &ip));
143 peer_addr_ = IPEndPoint(ip, 443);
144 self_addr_ = IPEndPoint(ip, 8435);
147 ~QuicHttpStreamTest() {
148 session_->CloseSessionOnError(ERR_ABORTED);
149 for (size_t i = 0; i < writes_.size(); i++) {
150 delete writes_[i].packet;
154 // Adds a packet to the list of expected writes.
155 void AddWrite(scoped_ptr<QuicEncryptedPacket> packet) {
156 writes_.push_back(PacketToWrite(SYNCHRONOUS, packet.release()));
159 // Returns the packet to be written at position |pos|.
160 QuicEncryptedPacket* GetWrite(size_t pos) {
161 return writes_[pos].packet;
165 return socket_data_->at_read_eof() && socket_data_->at_write_eof();
168 void ProcessPacket(scoped_ptr<QuicEncryptedPacket> packet) {
169 connection_->ProcessUdpPacket(self_addr_, peer_addr_, *packet);
172 // Configures the test fixture to use the list of expected writes.
174 mock_writes_.reset(new MockWrite[writes_.size()]);
175 for (size_t i = 0; i < writes_.size(); i++) {
176 mock_writes_[i] = MockWrite(writes_[i].mode,
177 writes_[i].packet->data(),
178 writes_[i].packet->length());
181 socket_data_.reset(new StaticSocketDataProvider(NULL, 0, mock_writes_.get(),
184 MockUDPClientSocket* socket = new MockUDPClientSocket(socket_data_.get(),
186 socket->Connect(peer_addr_);
187 runner_ = new TestTaskRunner(&clock_);
188 send_algorithm_ = new MockSendAlgorithm();
189 receive_algorithm_ = new TestReceiveAlgorithm();
190 EXPECT_CALL(*receive_algorithm_, RecordIncomingPacket(_, _, _)).
192 EXPECT_CALL(*send_algorithm_,
193 OnPacketSent(_, _, _, _, _)).WillRepeatedly(Return(true));
194 EXPECT_CALL(*send_algorithm_, RetransmissionDelay()).WillRepeatedly(
195 Return(QuicTime::Delta::Zero()));
196 EXPECT_CALL(*send_algorithm_, GetCongestionWindow()).WillRepeatedly(
197 Return(kMaxPacketSize));
198 EXPECT_CALL(*send_algorithm_, TimeUntilSend(_, _, _)).
199 WillRepeatedly(Return(QuicTime::Delta::Zero()));
200 EXPECT_CALL(*send_algorithm_, BandwidthEstimate()).WillRepeatedly(
201 Return(QuicBandwidth::Zero()));
202 EXPECT_CALL(*send_algorithm_, SetFromConfig(_, _)).Times(AnyNumber());
203 helper_.reset(new QuicConnectionHelper(runner_.get(), &clock_,
204 &random_generator_));
205 writer_.reset(new QuicDefaultPacketWriter(socket));
206 connection_ = new TestQuicConnection(SupportedVersions(GetParam()),
207 connection_id_, peer_addr_,
208 helper_.get(), writer_.get());
209 connection_->set_visitor(&visitor_);
210 connection_->SetSendAlgorithm(send_algorithm_);
211 connection_->SetReceiveAlgorithm(receive_algorithm_);
212 crypto_config_.SetDefaults();
214 new QuicClientSession(connection_,
215 scoped_ptr<DatagramClientSocket>(socket),
216 writer_.Pass(), NULL,
217 &crypto_client_stream_factory_,
218 &transport_security_state_,
219 make_scoped_ptr((QuicServerInfo*)NULL),
220 QuicServerId(kServerHostname, kServerPort,
221 false, PRIVACY_MODE_DISABLED),
222 DefaultQuicConfig(), &crypto_config_,
223 base::MessageLoop::current()->
224 message_loop_proxy().get(),
226 session_->InitializeSession();
227 session_->GetCryptoStream()->CryptoConnect();
228 EXPECT_TRUE(session_->IsCryptoHandshakeConfirmed());
229 stream_.reset(use_closing_stream_ ?
230 new AutoClosingStream(session_->GetWeakPtr()) :
231 new QuicHttpStream(session_->GetWeakPtr()));
232 clock_.AdvanceTime(QuicTime::Delta::FromMilliseconds(20));
235 void SetRequest(const std::string& method,
236 const std::string& path,
237 RequestPriority priority) {
238 request_headers_ = maker_.GetRequestHeaders(method, "http", path);
241 void SetResponse(const std::string& status, const std::string& body) {
242 response_headers_ = maker_.GetResponseHeaders(status);
243 response_data_ = body;
246 scoped_ptr<QuicEncryptedPacket> ConstructDataPacket(
247 QuicPacketSequenceNumber sequence_number,
248 bool should_include_version,
250 QuicStreamOffset offset,
251 base::StringPiece data) {
252 return maker_.MakeDataPacket(
253 sequence_number, stream_id_, should_include_version, fin, offset, data);
256 scoped_ptr<QuicEncryptedPacket> ConstructRequestHeadersPacket(
257 QuicPacketSequenceNumber sequence_number,
259 return maker_.MakeRequestHeadersPacket(
260 sequence_number, stream_id_, kIncludeVersion, fin, request_headers_);
263 scoped_ptr<QuicEncryptedPacket> ConstructResponseHeadersPacket(
264 QuicPacketSequenceNumber sequence_number,
266 return maker_.MakeResponseHeadersPacket(
267 sequence_number, stream_id_, !kIncludeVersion, fin, response_headers_);
270 scoped_ptr<QuicEncryptedPacket> ConstructRstStreamPacket(
271 QuicPacketSequenceNumber sequence_number) {
272 return maker_.MakeRstPacket(
273 sequence_number, true, stream_id_,
274 AdjustErrorForVersion(QUIC_RST_FLOW_CONTROL_ACCOUNTING, GetParam()));
277 scoped_ptr<QuicEncryptedPacket> ConstructAckAndRstStreamPacket(
278 QuicPacketSequenceNumber sequence_number) {
279 return maker_.MakeAckAndRstPacket(
280 sequence_number, !kIncludeVersion, stream_id_, QUIC_STREAM_CANCELLED,
281 2, 1, !kIncludeCongestionFeedback);
284 scoped_ptr<QuicEncryptedPacket> ConstructAckPacket(
285 QuicPacketSequenceNumber sequence_number,
286 QuicPacketSequenceNumber largest_received,
287 QuicPacketSequenceNumber least_unacked) {
288 return maker_.MakeAckPacket(sequence_number, largest_received,
289 least_unacked, !kIncludeCongestionFeedback);
292 BoundNetLog net_log_;
293 bool use_closing_stream_;
294 MockSendAlgorithm* send_algorithm_;
295 TestReceiveAlgorithm* receive_algorithm_;
296 scoped_refptr<TestTaskRunner> runner_;
297 scoped_ptr<MockWrite[]> mock_writes_;
299 TestQuicConnection* connection_;
300 scoped_ptr<QuicConnectionHelper> helper_;
301 testing::StrictMock<MockConnectionVisitor> visitor_;
302 scoped_ptr<QuicHttpStream> stream_;
303 scoped_ptr<QuicDefaultPacketWriter> writer_;
304 TransportSecurityState transport_security_state_;
305 scoped_ptr<QuicClientSession> session_;
306 QuicCryptoClientConfig crypto_config_;
307 TestCompletionCallback callback_;
308 HttpRequestInfo request_;
309 HttpRequestHeaders headers_;
310 HttpResponseInfo response_;
311 scoped_refptr<IOBufferWithSize> read_buffer_;
312 SpdyHeaderBlock request_headers_;
313 SpdyHeaderBlock response_headers_;
314 std::string request_data_;
315 std::string response_data_;
318 const QuicConnectionId connection_id_;
319 const QuicStreamId stream_id_;
320 QuicTestPacketMaker maker_;
321 IPEndPoint self_addr_;
322 IPEndPoint peer_addr_;
323 MockRandom random_generator_;
324 MockCryptoClientStreamFactory crypto_client_stream_factory_;
325 scoped_ptr<StaticSocketDataProvider> socket_data_;
326 std::vector<PacketToWrite> writes_;
329 INSTANTIATE_TEST_CASE_P(Version, QuicHttpStreamTest,
330 ::testing::ValuesIn(QuicSupportedVersions()));
332 TEST_P(QuicHttpStreamTest, RenewStreamForAuth) {
334 EXPECT_EQ(NULL, stream_->RenewStreamForAuth());
337 TEST_P(QuicHttpStreamTest, CanFindEndOfResponse) {
339 EXPECT_TRUE(stream_->CanFindEndOfResponse());
342 TEST_P(QuicHttpStreamTest, IsConnectionReusable) {
344 EXPECT_FALSE(stream_->IsConnectionReusable());
347 TEST_P(QuicHttpStreamTest, GetRequest) {
348 SetRequest("GET", "/", DEFAULT_PRIORITY);
349 AddWrite(ConstructRequestHeadersPacket(1, kFin));
352 request_.method = "GET";
353 request_.url = GURL("http://www.google.com/");
355 EXPECT_EQ(OK, stream_->InitializeStream(&request_, DEFAULT_PRIORITY,
356 net_log_, callback_.callback()));
357 EXPECT_EQ(OK, stream_->SendRequest(headers_, &response_,
358 callback_.callback()));
361 ProcessPacket(ConstructAckPacket(1, 0, 0));
363 EXPECT_EQ(ERR_IO_PENDING,
364 stream_->ReadResponseHeaders(callback_.callback()));
366 SetResponse("404 Not Found", std::string());
367 ProcessPacket(ConstructResponseHeadersPacket(2, kFin));
369 // Now that the headers have been processed, the callback will return.
370 EXPECT_EQ(OK, callback_.WaitForResult());
371 ASSERT_TRUE(response_.headers.get());
372 EXPECT_EQ(404, response_.headers->response_code());
373 EXPECT_TRUE(response_.headers->HasHeaderValue("Content-Type", "text/plain"));
374 EXPECT_FALSE(response_.response_time.is_null());
375 EXPECT_FALSE(response_.request_time.is_null());
377 // There is no body, so this should return immediately.
378 EXPECT_EQ(0, stream_->ReadResponseBody(read_buffer_.get(),
379 read_buffer_->size(),
380 callback_.callback()));
381 EXPECT_TRUE(stream_->IsResponseBodyComplete());
382 EXPECT_TRUE(AtEof());
385 // Regression test for http://crbug.com/288128
386 TEST_P(QuicHttpStreamTest, GetRequestLargeResponse) {
387 SetRequest("GET", "/", DEFAULT_PRIORITY);
388 AddWrite(ConstructRequestHeadersPacket(1, kFin));
391 request_.method = "GET";
392 request_.url = GURL("http://www.google.com/");
394 EXPECT_EQ(OK, stream_->InitializeStream(&request_, DEFAULT_PRIORITY,
395 net_log_, callback_.callback()));
396 EXPECT_EQ(OK, stream_->SendRequest(headers_, &response_,
397 callback_.callback()));
400 ProcessPacket(ConstructAckPacket(1, 0, 0));
402 EXPECT_EQ(ERR_IO_PENDING,
403 stream_->ReadResponseHeaders(callback_.callback()));
405 SpdyHeaderBlock headers;
406 headers[":status"] = "200 OK";
407 headers[":version"] = "HTTP/1.1";
408 headers["content-type"] = "text/plain";
409 headers["big6"] = std::string(10000, 'x'); // Lots of x's.
411 std::string response = SpdyUtils::SerializeUncompressedHeaders(headers);
412 EXPECT_LT(4096u, response.length());
413 stream_->OnDataReceived(response.data(), response.length());
414 stream_->OnClose(QUIC_NO_ERROR);
416 // Now that the headers have been processed, the callback will return.
417 EXPECT_EQ(OK, callback_.WaitForResult());
418 ASSERT_TRUE(response_.headers.get());
419 EXPECT_EQ(200, response_.headers->response_code());
420 EXPECT_TRUE(response_.headers->HasHeaderValue("Content-Type", "text/plain"));
422 // There is no body, so this should return immediately.
423 EXPECT_EQ(0, stream_->ReadResponseBody(read_buffer_.get(),
424 read_buffer_->size(),
425 callback_.callback()));
426 EXPECT_TRUE(stream_->IsResponseBodyComplete());
427 EXPECT_TRUE(AtEof());
430 TEST_P(QuicHttpStreamTest, SendPostRequest) {
431 SetRequest("POST", "/", DEFAULT_PRIORITY);
432 AddWrite(ConstructRequestHeadersPacket(1, !kFin));
433 AddWrite(ConstructDataPacket(2, kIncludeVersion, kFin, 0, kUploadData));
434 AddWrite(ConstructAckPacket(3, 3, 1));
438 ScopedVector<UploadElementReader> element_readers;
439 element_readers.push_back(
440 new UploadBytesElementReader(kUploadData, strlen(kUploadData)));
441 UploadDataStream upload_data_stream(element_readers.Pass(), 0);
442 request_.method = "POST";
443 request_.url = GURL("http://www.google.com/");
444 request_.upload_data_stream = &upload_data_stream;
445 ASSERT_EQ(OK, request_.upload_data_stream->Init(CompletionCallback()));
447 EXPECT_EQ(OK, stream_->InitializeStream(&request_, DEFAULT_PRIORITY,
448 net_log_, callback_.callback()));
449 EXPECT_EQ(OK, stream_->SendRequest(headers_, &response_,
450 callback_.callback()));
452 // Ack both packets in the request.
453 ProcessPacket(ConstructAckPacket(1, 0, 0));
455 // Send the response headers (but not the body).
456 SetResponse("200 OK", std::string());
457 ProcessPacket(ConstructResponseHeadersPacket(2, !kFin));
459 // Since the headers have already arrived, this should return immediately.
460 EXPECT_EQ(OK, stream_->ReadResponseHeaders(callback_.callback()));
461 ASSERT_TRUE(response_.headers.get());
462 EXPECT_EQ(200, response_.headers->response_code());
463 EXPECT_TRUE(response_.headers->HasHeaderValue("Content-Type", "text/plain"));
465 // Send the response body.
466 const char kResponseBody[] = "Hello world!";
467 ProcessPacket(ConstructDataPacket(3, false, kFin, 0, kResponseBody));
468 // Since the body has already arrived, this should return immediately.
469 EXPECT_EQ(static_cast<int>(strlen(kResponseBody)),
470 stream_->ReadResponseBody(read_buffer_.get(), read_buffer_->size(),
471 callback_.callback()));
473 EXPECT_TRUE(stream_->IsResponseBodyComplete());
474 EXPECT_TRUE(AtEof());
477 TEST_P(QuicHttpStreamTest, SendChunkedPostRequest) {
478 SetRequest("POST", "/", DEFAULT_PRIORITY);
479 size_t chunk_size = strlen(kUploadData);
480 AddWrite(ConstructRequestHeadersPacket(1, !kFin));
481 AddWrite(ConstructDataPacket(2, kIncludeVersion, !kFin, 0, kUploadData));
482 AddWrite(ConstructDataPacket(3, kIncludeVersion, kFin, chunk_size,
484 AddWrite(ConstructAckPacket(4, 3, 1));
487 UploadDataStream upload_data_stream(UploadDataStream::CHUNKED, 0);
488 upload_data_stream.AppendChunk(kUploadData, chunk_size, false);
490 request_.method = "POST";
491 request_.url = GURL("http://www.google.com/");
492 request_.upload_data_stream = &upload_data_stream;
493 ASSERT_EQ(OK, request_.upload_data_stream->Init(CompletionCallback()));
495 ASSERT_EQ(OK, stream_->InitializeStream(&request_, DEFAULT_PRIORITY,
496 net_log_, callback_.callback()));
497 ASSERT_EQ(ERR_IO_PENDING, stream_->SendRequest(headers_, &response_,
498 callback_.callback()));
500 upload_data_stream.AppendChunk(kUploadData, chunk_size, true);
502 // Ack both packets in the request.
503 ProcessPacket(ConstructAckPacket(1, 0, 0));
505 // Send the response headers (but not the body).
506 SetResponse("200 OK", std::string());
507 ProcessPacket(ConstructResponseHeadersPacket(2, !kFin));
509 // Since the headers have already arrived, this should return immediately.
510 ASSERT_EQ(OK, stream_->ReadResponseHeaders(callback_.callback()));
511 ASSERT_TRUE(response_.headers.get());
512 EXPECT_EQ(200, response_.headers->response_code());
513 EXPECT_TRUE(response_.headers->HasHeaderValue("Content-Type", "text/plain"));
515 // Send the response body.
516 const char kResponseBody[] = "Hello world!";
517 ProcessPacket(ConstructDataPacket(3, false, kFin, response_data_.length(),
520 // Since the body has already arrived, this should return immediately.
521 ASSERT_EQ(static_cast<int>(strlen(kResponseBody)),
522 stream_->ReadResponseBody(read_buffer_.get(), read_buffer_->size(),
523 callback_.callback()));
525 EXPECT_TRUE(stream_->IsResponseBodyComplete());
526 EXPECT_TRUE(AtEof());
529 TEST_P(QuicHttpStreamTest, DestroyedEarly) {
530 SetRequest("GET", "/", DEFAULT_PRIORITY);
531 AddWrite(ConstructRequestHeadersPacket(1, kFin));
532 AddWrite(ConstructAckAndRstStreamPacket(2));
533 use_closing_stream_ = true;
536 request_.method = "GET";
537 request_.url = GURL("http://www.google.com/");
539 EXPECT_EQ(OK, stream_->InitializeStream(&request_, DEFAULT_PRIORITY,
540 net_log_, callback_.callback()));
541 EXPECT_EQ(OK, stream_->SendRequest(headers_, &response_,
542 callback_.callback()));
545 ProcessPacket(ConstructAckPacket(1, 0, 0));
546 EXPECT_EQ(ERR_IO_PENDING,
547 stream_->ReadResponseHeaders(callback_.callback()));
549 // Send the response with a body.
550 SetResponse("404 OK", "hello world!");
551 // In the course of processing this packet, the QuicHttpStream close itself.
552 ProcessPacket(ConstructResponseHeadersPacket(2, kFin));
554 EXPECT_TRUE(AtEof());
557 TEST_P(QuicHttpStreamTest, Priority) {
558 SetRequest("GET", "/", MEDIUM);
559 AddWrite(ConstructRequestHeadersPacket(1, kFin));
560 AddWrite(ConstructAckAndRstStreamPacket(2));
561 use_closing_stream_ = true;
564 request_.method = "GET";
565 request_.url = GURL("http://www.google.com/");
567 EXPECT_EQ(OK, stream_->InitializeStream(&request_, MEDIUM,
568 net_log_, callback_.callback()));
570 // Check that priority is highest.
571 QuicReliableClientStream* reliable_stream =
572 QuicHttpStreamPeer::GetQuicReliableClientStream(stream_.get());
573 DCHECK(reliable_stream);
574 DCHECK_EQ(QuicWriteBlockedList::kHighestPriority,
575 reliable_stream->EffectivePriority());
577 EXPECT_EQ(OK, stream_->SendRequest(headers_, &response_,
578 callback_.callback()));
580 // Check that priority has now dropped back to MEDIUM.
581 DCHECK_EQ(MEDIUM, ConvertQuicPriorityToRequestPriority(
582 reliable_stream->EffectivePriority()));
585 ProcessPacket(ConstructAckPacket(1, 0, 0));
586 EXPECT_EQ(ERR_IO_PENDING,
587 stream_->ReadResponseHeaders(callback_.callback()));
589 // Send the response with a body.
590 SetResponse("404 OK", "hello world!");
591 // In the course of processing this packet, the QuicHttpStream close itself.
592 ProcessPacket(ConstructResponseHeadersPacket(2, kFin));
594 EXPECT_TRUE(AtEof());
597 // Regression test for http://crbug.com/294870
598 TEST_P(QuicHttpStreamTest, CheckPriorityWithNoDelegate) {
599 SetRequest("GET", "/", MEDIUM);
600 use_closing_stream_ = true;
602 AddWrite(ConstructRstStreamPacket(1));
606 request_.method = "GET";
607 request_.url = GURL("http://www.google.com/");
609 EXPECT_EQ(OK, stream_->InitializeStream(&request_, MEDIUM,
610 net_log_, callback_.callback()));
612 // Check that priority is highest.
613 QuicReliableClientStream* reliable_stream =
614 QuicHttpStreamPeer::GetQuicReliableClientStream(stream_.get());
615 DCHECK(reliable_stream);
616 QuicReliableClientStream::Delegate* delegate = reliable_stream->GetDelegate();
618 DCHECK_EQ(QuicWriteBlockedList::kHighestPriority,
619 reliable_stream->EffectivePriority());
621 // Set Delegate to NULL and make sure EffectivePriority returns highest
623 reliable_stream->SetDelegate(NULL);
624 DCHECK_EQ(QuicWriteBlockedList::kHighestPriority,
625 reliable_stream->EffectivePriority());
626 reliable_stream->SetDelegate(delegate);