Upstream version 7.36.149.0
[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/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"
42
43 using testing::_;
44 using testing::AnyNumber;
45 using testing::Return;
46
47 namespace net {
48 namespace test {
49 namespace {
50
51 const char kUploadData[] = "hello world!";
52 const char kServerHostname[] = "www.google.com";
53 const uint16 kServerPort = 80;
54
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, address, helper, writer, false,
63                        versions, kInitialFlowControlWindowForTest) {
64   }
65
66   void SetSendAlgorithm(SendAlgorithmInterface* send_algorithm) {
67     QuicConnectionPeer::SetSendAlgorithm(this, send_algorithm);
68   }
69
70   void SetReceiveAlgorithm(ReceiveAlgorithmInterface* receive_algorithm) {
71     QuicConnectionPeer::SetReceiveAlgorithm(this, receive_algorithm);
72   }
73 };
74
75 class TestReceiveAlgorithm : public ReceiveAlgorithmInterface {
76  public:
77   virtual bool GenerateCongestionFeedback(
78       QuicCongestionFeedbackFrame* /*congestion_feedback*/) {
79     return false;
80   }
81
82   MOCK_METHOD3(RecordIncomingPacket,
83                void(QuicByteCount, QuicPacketSequenceNumber, QuicTime));
84 };
85
86 // Subclass of QuicHttpStream that closes itself when the first piece of data
87 // is received.
88 class AutoClosingStream : public QuicHttpStream {
89  public:
90   explicit AutoClosingStream(const base::WeakPtr<QuicClientSession>& session)
91       : QuicHttpStream(session) {
92   }
93
94   virtual int OnDataReceived(const char* data, int length) OVERRIDE {
95     Close(false);
96     return OK;
97   }
98 };
99
100 }  // namespace
101
102 class QuicHttpStreamPeer {
103  public:
104   static QuicReliableClientStream* GetQuicReliableClientStream(
105       QuicHttpStream* stream) {
106     return stream->stream_;
107   }
108 };
109
110 class QuicHttpStreamTest : public ::testing::TestWithParam<QuicVersion> {
111  protected:
112   static const bool kFin = true;
113   static const bool kIncludeVersion = true;
114   static const bool kIncludeCongestionFeedback = true;
115
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)
120         : mode(mode),
121           packet(packet) {
122     }
123     IoMode mode;
124     QuicEncryptedPacket* packet;
125   };
126
127   QuicHttpStreamTest()
128       : net_log_(BoundNetLog()),
129         use_closing_stream_(false),
130         read_buffer_(new IOBufferWithSize(4096)),
131         connection_id_(2),
132         stream_id_(5),
133         maker_(GetParam(), connection_id_),
134         random_generator_(0) {
135     IPAddressNumber ip;
136     CHECK(ParseIPLiteralToNumber("192.0.2.33", &ip));
137     peer_addr_ = IPEndPoint(ip, 443);
138     self_addr_ = IPEndPoint(ip, 8435);
139   }
140
141   ~QuicHttpStreamTest() {
142     session_->CloseSessionOnError(ERR_ABORTED);
143     for (size_t i = 0; i < writes_.size(); i++) {
144       delete writes_[i].packet;
145     }
146   }
147
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()));
151   }
152
153   // Returns the packet to be written at position |pos|.
154   QuicEncryptedPacket* GetWrite(size_t pos) {
155     return writes_[pos].packet;
156   }
157
158   bool AtEof() {
159     return socket_data_->at_read_eof() && socket_data_->at_write_eof();
160   }
161
162   void ProcessPacket(scoped_ptr<QuicEncryptedPacket> packet) {
163     connection_->ProcessUdpPacket(self_addr_, peer_addr_, *packet);
164   }
165
166   // Configures the test fixture to use the list of expected writes.
167   void Initialize() {
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());
173     };
174
175     socket_data_.reset(new StaticSocketDataProvider(NULL, 0, mock_writes_.get(),
176                                                     writes_.size()));
177
178     MockUDPClientSocket* socket = new MockUDPClientSocket(socket_data_.get(),
179                                                           net_log_.net_log());
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(_, _, _)).
185         Times(AnyNumber());
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();
207     session_.reset(
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));
222   }
223
224   void SetRequest(const std::string& method,
225                   const std::string& path,
226                   RequestPriority priority) {
227     request_headers_ = maker_.GetRequestHeaders(method, "http", path);
228   }
229
230   void SetResponse(const std::string& status, const std::string& body) {
231     response_headers_ = maker_.GetResponseHeaders(status);
232     response_data_ = body;
233   }
234
235   scoped_ptr<QuicEncryptedPacket> ConstructDataPacket(
236       QuicPacketSequenceNumber sequence_number,
237       bool should_include_version,
238       bool fin,
239       QuicStreamOffset offset,
240       base::StringPiece data) {
241     return maker_.MakeDataPacket(
242         sequence_number, stream_id_, should_include_version, fin, offset, data);
243   }
244
245   scoped_ptr<QuicEncryptedPacket> ConstructRequestHeadersPacket(
246       QuicPacketSequenceNumber sequence_number,
247       bool fin) {
248     return maker_.MakeRequestHeadersPacket(
249         sequence_number, stream_id_, kIncludeVersion, fin, request_headers_);
250   }
251
252   scoped_ptr<QuicEncryptedPacket> ConstructResponseHeadersPacket(
253       QuicPacketSequenceNumber sequence_number,
254       bool fin) {
255     return maker_.MakeResponseHeadersPacket(
256         sequence_number, stream_id_, !kIncludeVersion, fin, response_headers_);
257   }
258
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()));
264   }
265
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);
271   }
272
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);
279   }
280
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_;
287   MockClock clock_;
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_;
304
305  private:
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_;
315 };
316
317 INSTANTIATE_TEST_CASE_P(Version, QuicHttpStreamTest,
318                         ::testing::ValuesIn(QuicSupportedVersions()));
319
320 TEST_P(QuicHttpStreamTest, RenewStreamForAuth) {
321   Initialize();
322   EXPECT_EQ(NULL, stream_->RenewStreamForAuth());
323 }
324
325 TEST_P(QuicHttpStreamTest, CanFindEndOfResponse) {
326   Initialize();
327   EXPECT_TRUE(stream_->CanFindEndOfResponse());
328 }
329
330 TEST_P(QuicHttpStreamTest, IsConnectionReusable) {
331   Initialize();
332   EXPECT_FALSE(stream_->IsConnectionReusable());
333 }
334
335 TEST_P(QuicHttpStreamTest, GetRequest) {
336   SetRequest("GET", "/", DEFAULT_PRIORITY);
337   AddWrite(ConstructRequestHeadersPacket(1, kFin));
338   Initialize();
339
340   request_.method = "GET";
341   request_.url = GURL("http://www.google.com/");
342
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());
348
349   // Ack the request.
350   ProcessPacket(ConstructAckPacket(1, 0, 0));
351
352   EXPECT_EQ(ERR_IO_PENDING,
353             stream_->ReadResponseHeaders(callback_.callback()));
354
355   SetResponse("404 Not Found", std::string());
356   ProcessPacket(ConstructResponseHeadersPacket(2, kFin));
357
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"));
363
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());
370 }
371
372 // Regression test for http://crbug.com/288128
373 TEST_P(QuicHttpStreamTest, GetRequestLargeResponse) {
374   SetRequest("GET", "/", DEFAULT_PRIORITY);
375   AddWrite(ConstructRequestHeadersPacket(1, kFin));
376   Initialize();
377
378   request_.method = "GET";
379   request_.url = GURL("http://www.google.com/");
380
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());
386
387   // Ack the request.
388   ProcessPacket(ConstructAckPacket(1, 0, 0));
389
390   EXPECT_EQ(ERR_IO_PENDING,
391             stream_->ReadResponseHeaders(callback_.callback()));
392
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.
398
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);
403
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"));
409
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());
416 }
417
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));
423
424   Initialize();
425
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()));
434
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());
440
441   // Ack both packets in the request.
442   ProcessPacket(ConstructAckPacket(1, 0, 0));
443
444   // Send the response headers (but not the body).
445   SetResponse("200 OK", std::string());
446   ProcessPacket(ConstructResponseHeadersPacket(2, !kFin));
447
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"));
453
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()));
461
462   EXPECT_TRUE(stream_->IsResponseBodyComplete());
463   EXPECT_TRUE(AtEof());
464 }
465
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,
472                                kUploadData));
473   AddWrite(ConstructAckPacket(4, 3, 1));
474   Initialize();
475
476   UploadDataStream upload_data_stream(UploadDataStream::CHUNKED, 0);
477   upload_data_stream.AppendChunk(kUploadData, chunk_size, false);
478
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()));
483
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());
489
490   upload_data_stream.AppendChunk(kUploadData, chunk_size, true);
491
492   // Ack both packets in the request.
493   ProcessPacket(ConstructAckPacket(1, 0, 0));
494
495   // Send the response headers (but not the body).
496   SetResponse("200 OK", std::string());
497   ProcessPacket(ConstructResponseHeadersPacket(2, !kFin));
498
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"));
504
505   // Send the response body.
506   const char kResponseBody[] = "Hello world!";
507   ProcessPacket(ConstructDataPacket(3, false, kFin, response_data_.length(),
508                                     kResponseBody));
509
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()));
514
515   EXPECT_TRUE(stream_->IsResponseBodyComplete());
516   EXPECT_TRUE(AtEof());
517 }
518
519 TEST_P(QuicHttpStreamTest, DestroyedEarly) {
520   SetRequest("GET", "/", DEFAULT_PRIORITY);
521   AddWrite(ConstructRequestHeadersPacket(1, kFin));
522   AddWrite(ConstructAckAndRstStreamPacket(2));
523   use_closing_stream_ = true;
524   Initialize();
525
526   request_.method = "GET";
527   request_.url = GURL("http://www.google.com/");
528
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());
534
535   // Ack the request.
536   ProcessPacket(ConstructAckPacket(1, 0, 0));
537   EXPECT_EQ(ERR_IO_PENDING,
538             stream_->ReadResponseHeaders(callback_.callback()));
539
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));
544
545   EXPECT_TRUE(AtEof());
546 }
547
548 TEST_P(QuicHttpStreamTest, Priority) {
549   SetRequest("GET", "/", MEDIUM);
550   AddWrite(ConstructRequestHeadersPacket(1, kFin));
551   AddWrite(ConstructAckAndRstStreamPacket(2));
552   use_closing_stream_ = true;
553   Initialize();
554
555   request_.method = "GET";
556   request_.url = GURL("http://www.google.com/");
557
558   EXPECT_EQ(OK, stream_->InitializeStream(&request_, MEDIUM,
559                                           net_log_, callback_.callback()));
560
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());
567
568   EXPECT_EQ(OK, stream_->SendRequest(headers_, &response_,
569                                      callback_.callback()));
570   EXPECT_EQ(&response_, stream_->GetResponseInfo());
571
572   // Check that priority has now dropped back to MEDIUM.
573   DCHECK_EQ(MEDIUM, ConvertQuicPriorityToRequestPriority(
574       reliable_stream->EffectivePriority()));
575
576   // Ack the request.
577   ProcessPacket(ConstructAckPacket(1, 0, 0));
578   EXPECT_EQ(ERR_IO_PENDING,
579             stream_->ReadResponseHeaders(callback_.callback()));
580
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));
585
586   EXPECT_TRUE(AtEof());
587 }
588
589 // Regression test for http://crbug.com/294870
590 TEST_P(QuicHttpStreamTest, CheckPriorityWithNoDelegate) {
591   SetRequest("GET", "/", MEDIUM);
592   use_closing_stream_ = true;
593
594   AddWrite(ConstructRstStreamPacket(1));
595
596   Initialize();
597
598   request_.method = "GET";
599   request_.url = GURL("http://www.google.com/");
600
601   EXPECT_EQ(OK, stream_->InitializeStream(&request_, MEDIUM,
602                                           net_log_, callback_.callback()));
603
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();
609   DCHECK(delegate);
610   DCHECK_EQ(QuicWriteBlockedList::kHighestPriority,
611             reliable_stream->EffectivePriority());
612
613   // Set Delegate to NULL and make sure EffectivePriority returns highest
614   // priority.
615   reliable_stream->SetDelegate(NULL);
616   DCHECK_EQ(QuicWriteBlockedList::kHighestPriority,
617             reliable_stream->EffectivePriority());
618   reliable_stream->SetDelegate(delegate);
619 }
620
621 }  // namespace test
622 }  // namespace net