932f566d4a525c7efbc299e83188c6fc7177028a
[platform/framework/web/crosswalk.git] / src / net / quic / quic_http_stream_test.cc
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.
4
5 #include "net/quic/quic_http_stream.h"
6
7 #include <vector>
8
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"
43
44 using testing::_;
45 using testing::AnyNumber;
46 using testing::Return;
47
48 namespace net {
49 namespace test {
50 namespace {
51
52 const char kUploadData[] = "hello world!";
53 const char kServerHostname[] = "www.google.com";
54 const uint16 kServerPort = 80;
55
56 class TestQuicConnection : public QuicConnection {
57  public:
58   TestQuicConnection(const QuicVersionVector& versions,
59                      QuicConnectionId connection_id,
60                      IPEndPoint address,
61                      QuicConnectionHelper* helper,
62                      QuicPacketWriter* writer)
63       : QuicConnection(connection_id,
64                        address,
65                        helper,
66                        writer,
67                        false  /* owns_writer */,
68                        false  /* is_server */,
69                        versions) {
70   }
71
72   void SetSendAlgorithm(SendAlgorithmInterface* send_algorithm) {
73     QuicConnectionPeer::SetSendAlgorithm(this, send_algorithm);
74   }
75
76   void SetReceiveAlgorithm(ReceiveAlgorithmInterface* receive_algorithm) {
77     QuicConnectionPeer::SetReceiveAlgorithm(this, receive_algorithm);
78   }
79 };
80
81 class TestReceiveAlgorithm : public ReceiveAlgorithmInterface {
82  public:
83   virtual bool GenerateCongestionFeedback(
84       QuicCongestionFeedbackFrame* /*congestion_feedback*/) {
85     return false;
86   }
87
88   MOCK_METHOD3(RecordIncomingPacket,
89                void(QuicByteCount, QuicPacketSequenceNumber, QuicTime));
90 };
91
92 // Subclass of QuicHttpStream that closes itself when the first piece of data
93 // is received.
94 class AutoClosingStream : public QuicHttpStream {
95  public:
96   explicit AutoClosingStream(const base::WeakPtr<QuicClientSession>& session)
97       : QuicHttpStream(session) {
98   }
99
100   virtual int OnDataReceived(const char* data, int length) OVERRIDE {
101     Close(false);
102     return OK;
103   }
104 };
105
106 }  // namespace
107
108 class QuicHttpStreamPeer {
109  public:
110   static QuicReliableClientStream* GetQuicReliableClientStream(
111       QuicHttpStream* stream) {
112     return stream->stream_;
113   }
114 };
115
116 class QuicHttpStreamTest : public ::testing::TestWithParam<QuicVersion> {
117  protected:
118   static const bool kFin = true;
119   static const bool kIncludeVersion = true;
120   static const bool kIncludeCongestionFeedback = true;
121
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)
126         : mode(mode),
127           packet(packet) {
128     }
129     IoMode mode;
130     QuicEncryptedPacket* packet;
131   };
132
133   QuicHttpStreamTest()
134       : net_log_(BoundNetLog()),
135         use_closing_stream_(false),
136         read_buffer_(new IOBufferWithSize(4096)),
137         connection_id_(2),
138         stream_id_(kClientDataStreamId1),
139         maker_(GetParam(), connection_id_),
140         random_generator_(0) {
141     IPAddressNumber ip;
142     CHECK(ParseIPLiteralToNumber("192.0.2.33", &ip));
143     peer_addr_ = IPEndPoint(ip, 443);
144     self_addr_ = IPEndPoint(ip, 8435);
145   }
146
147   ~QuicHttpStreamTest() {
148     session_->CloseSessionOnError(ERR_ABORTED);
149     for (size_t i = 0; i < writes_.size(); i++) {
150       delete writes_[i].packet;
151     }
152   }
153
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()));
157   }
158
159   // Returns the packet to be written at position |pos|.
160   QuicEncryptedPacket* GetWrite(size_t pos) {
161     return writes_[pos].packet;
162   }
163
164   bool AtEof() {
165     return socket_data_->at_read_eof() && socket_data_->at_write_eof();
166   }
167
168   void ProcessPacket(scoped_ptr<QuicEncryptedPacket> packet) {
169     connection_->ProcessUdpPacket(self_addr_, peer_addr_, *packet);
170   }
171
172   // Configures the test fixture to use the list of expected writes.
173   void Initialize() {
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());
179     };
180
181     socket_data_.reset(new StaticSocketDataProvider(NULL, 0, mock_writes_.get(),
182                                                     writes_.size()));
183
184     MockUDPClientSocket* socket = new MockUDPClientSocket(socket_data_.get(),
185                                                           net_log_.net_log());
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(_, _, _)).
191         Times(AnyNumber());
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();
213     session_.reset(
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(),
225                               NULL));
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));
233   }
234
235   void SetRequest(const std::string& method,
236                   const std::string& path,
237                   RequestPriority priority) {
238     request_headers_ = maker_.GetRequestHeaders(method, "http", path);
239   }
240
241   void SetResponse(const std::string& status, const std::string& body) {
242     response_headers_ = maker_.GetResponseHeaders(status);
243     response_data_ = body;
244   }
245
246   scoped_ptr<QuicEncryptedPacket> ConstructDataPacket(
247       QuicPacketSequenceNumber sequence_number,
248       bool should_include_version,
249       bool fin,
250       QuicStreamOffset offset,
251       base::StringPiece data) {
252     return maker_.MakeDataPacket(
253         sequence_number, stream_id_, should_include_version, fin, offset, data);
254   }
255
256   scoped_ptr<QuicEncryptedPacket> ConstructRequestHeadersPacket(
257       QuicPacketSequenceNumber sequence_number,
258       bool fin) {
259     return maker_.MakeRequestHeadersPacket(
260         sequence_number, stream_id_, kIncludeVersion, fin, request_headers_);
261   }
262
263   scoped_ptr<QuicEncryptedPacket> ConstructResponseHeadersPacket(
264       QuicPacketSequenceNumber sequence_number,
265       bool fin) {
266     return maker_.MakeResponseHeadersPacket(
267         sequence_number, stream_id_, !kIncludeVersion, fin, response_headers_);
268   }
269
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()));
275   }
276
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);
282   }
283
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);
290   }
291
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_;
298   MockClock clock_;
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_;
316
317  private:
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_;
327 };
328
329 INSTANTIATE_TEST_CASE_P(Version, QuicHttpStreamTest,
330                         ::testing::ValuesIn(QuicSupportedVersions()));
331
332 TEST_P(QuicHttpStreamTest, RenewStreamForAuth) {
333   Initialize();
334   EXPECT_EQ(NULL, stream_->RenewStreamForAuth());
335 }
336
337 TEST_P(QuicHttpStreamTest, CanFindEndOfResponse) {
338   Initialize();
339   EXPECT_TRUE(stream_->CanFindEndOfResponse());
340 }
341
342 TEST_P(QuicHttpStreamTest, IsConnectionReusable) {
343   Initialize();
344   EXPECT_FALSE(stream_->IsConnectionReusable());
345 }
346
347 TEST_P(QuicHttpStreamTest, GetRequest) {
348   SetRequest("GET", "/", DEFAULT_PRIORITY);
349   AddWrite(ConstructRequestHeadersPacket(1, kFin));
350   Initialize();
351
352   request_.method = "GET";
353   request_.url = GURL("http://www.google.com/");
354
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()));
359
360   // Ack the request.
361   ProcessPacket(ConstructAckPacket(1, 0, 0));
362
363   EXPECT_EQ(ERR_IO_PENDING,
364             stream_->ReadResponseHeaders(callback_.callback()));
365
366   SetResponse("404 Not Found", std::string());
367   ProcessPacket(ConstructResponseHeadersPacket(2, kFin));
368
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());
376
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());
383 }
384
385 // Regression test for http://crbug.com/288128
386 TEST_P(QuicHttpStreamTest, GetRequestLargeResponse) {
387   SetRequest("GET", "/", DEFAULT_PRIORITY);
388   AddWrite(ConstructRequestHeadersPacket(1, kFin));
389   Initialize();
390
391   request_.method = "GET";
392   request_.url = GURL("http://www.google.com/");
393
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()));
398
399   // Ack the request.
400   ProcessPacket(ConstructAckPacket(1, 0, 0));
401
402   EXPECT_EQ(ERR_IO_PENDING,
403             stream_->ReadResponseHeaders(callback_.callback()));
404
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.
410
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);
415
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"));
421
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());
428 }
429
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));
435
436   Initialize();
437
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()));
446
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()));
451
452   // Ack both packets in the request.
453   ProcessPacket(ConstructAckPacket(1, 0, 0));
454
455   // Send the response headers (but not the body).
456   SetResponse("200 OK", std::string());
457   ProcessPacket(ConstructResponseHeadersPacket(2, !kFin));
458
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"));
464
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()));
472
473   EXPECT_TRUE(stream_->IsResponseBodyComplete());
474   EXPECT_TRUE(AtEof());
475 }
476
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,
483                                kUploadData));
484   AddWrite(ConstructAckPacket(4, 3, 1));
485   Initialize();
486
487   UploadDataStream upload_data_stream(UploadDataStream::CHUNKED, 0);
488   upload_data_stream.AppendChunk(kUploadData, chunk_size, false);
489
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()));
494
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()));
499
500   upload_data_stream.AppendChunk(kUploadData, chunk_size, true);
501
502   // Ack both packets in the request.
503   ProcessPacket(ConstructAckPacket(1, 0, 0));
504
505   // Send the response headers (but not the body).
506   SetResponse("200 OK", std::string());
507   ProcessPacket(ConstructResponseHeadersPacket(2, !kFin));
508
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"));
514
515   // Send the response body.
516   const char kResponseBody[] = "Hello world!";
517   ProcessPacket(ConstructDataPacket(3, false, kFin, response_data_.length(),
518                                     kResponseBody));
519
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()));
524
525   EXPECT_TRUE(stream_->IsResponseBodyComplete());
526   EXPECT_TRUE(AtEof());
527 }
528
529 TEST_P(QuicHttpStreamTest, DestroyedEarly) {
530   SetRequest("GET", "/", DEFAULT_PRIORITY);
531   AddWrite(ConstructRequestHeadersPacket(1, kFin));
532   AddWrite(ConstructAckAndRstStreamPacket(2));
533   use_closing_stream_ = true;
534   Initialize();
535
536   request_.method = "GET";
537   request_.url = GURL("http://www.google.com/");
538
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()));
543
544   // Ack the request.
545   ProcessPacket(ConstructAckPacket(1, 0, 0));
546   EXPECT_EQ(ERR_IO_PENDING,
547             stream_->ReadResponseHeaders(callback_.callback()));
548
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));
553
554   EXPECT_TRUE(AtEof());
555 }
556
557 TEST_P(QuicHttpStreamTest, Priority) {
558   SetRequest("GET", "/", MEDIUM);
559   AddWrite(ConstructRequestHeadersPacket(1, kFin));
560   AddWrite(ConstructAckAndRstStreamPacket(2));
561   use_closing_stream_ = true;
562   Initialize();
563
564   request_.method = "GET";
565   request_.url = GURL("http://www.google.com/");
566
567   EXPECT_EQ(OK, stream_->InitializeStream(&request_, MEDIUM,
568                                           net_log_, callback_.callback()));
569
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());
576
577   EXPECT_EQ(OK, stream_->SendRequest(headers_, &response_,
578                                      callback_.callback()));
579
580   // Check that priority has now dropped back to MEDIUM.
581   DCHECK_EQ(MEDIUM, ConvertQuicPriorityToRequestPriority(
582       reliable_stream->EffectivePriority()));
583
584   // Ack the request.
585   ProcessPacket(ConstructAckPacket(1, 0, 0));
586   EXPECT_EQ(ERR_IO_PENDING,
587             stream_->ReadResponseHeaders(callback_.callback()));
588
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));
593
594   EXPECT_TRUE(AtEof());
595 }
596
597 // Regression test for http://crbug.com/294870
598 TEST_P(QuicHttpStreamTest, CheckPriorityWithNoDelegate) {
599   SetRequest("GET", "/", MEDIUM);
600   use_closing_stream_ = true;
601
602   AddWrite(ConstructRstStreamPacket(1));
603
604   Initialize();
605
606   request_.method = "GET";
607   request_.url = GURL("http://www.google.com/");
608
609   EXPECT_EQ(OK, stream_->InitializeStream(&request_, MEDIUM,
610                                           net_log_, callback_.callback()));
611
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();
617   DCHECK(delegate);
618   DCHECK_EQ(QuicWriteBlockedList::kHighestPriority,
619             reliable_stream->EffectivePriority());
620
621   // Set Delegate to NULL and make sure EffectivePriority returns highest
622   // priority.
623   reliable_stream->SetDelegate(NULL);
624   DCHECK_EQ(QuicWriteBlockedList::kHighestPriority,
625             reliable_stream->EffectivePriority());
626   reliable_stream->SetDelegate(delegate);
627 }
628
629 }  // namespace test
630 }  // namespace net