quic_http_stream_test.cc revision 5d1f7b1de12d16ceb2c938c56701a3e8bfa558f7
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/quic_client_session.h"
20#include "net/quic/quic_connection.h"
21#include "net/quic/quic_connection_helper.h"
22#include "net/quic/quic_default_packet_writer.h"
23#include "net/quic/quic_http_utils.h"
24#include "net/quic/quic_reliable_client_stream.h"
25#include "net/quic/quic_write_blocked_list.h"
26#include "net/quic/spdy_utils.h"
27#include "net/quic/test_tools/mock_clock.h"
28#include "net/quic/test_tools/mock_crypto_client_stream_factory.h"
29#include "net/quic/test_tools/mock_random.h"
30#include "net/quic/test_tools/quic_connection_peer.h"
31#include "net/quic/test_tools/quic_test_packet_maker.h"
32#include "net/quic/test_tools/quic_test_utils.h"
33#include "net/quic/test_tools/test_task_runner.h"
34#include "net/socket/socket_test_util.h"
35#include "net/spdy/spdy_frame_builder.h"
36#include "net/spdy/spdy_framer.h"
37#include "net/spdy/spdy_http_utils.h"
38#include "net/spdy/spdy_protocol.h"
39#include "testing/gmock/include/gmock/gmock.h"
40#include "testing/gtest/include/gtest/gtest.h"
41
42using testing::_;
43using testing::AnyNumber;
44using testing::Return;
45
46namespace net {
47namespace test {
48namespace {
49
50const char kUploadData[] = "hello world!";
51
52class TestQuicConnection : public QuicConnection {
53 public:
54  TestQuicConnection(const QuicVersionVector& versions,
55                     QuicGuid guid,
56                     IPEndPoint address,
57                     QuicConnectionHelper* helper,
58                     QuicPacketWriter* writer)
59      : QuicConnection(guid, address, helper, writer, false, versions) {
60  }
61
62  void SetSendAlgorithm(SendAlgorithmInterface* send_algorithm) {
63    QuicConnectionPeer::SetSendAlgorithm(this, send_algorithm);
64  }
65
66  void SetReceiveAlgorithm(ReceiveAlgorithmInterface* receive_algorithm) {
67    QuicConnectionPeer::SetReceiveAlgorithm(this, receive_algorithm);
68  }
69};
70
71class TestReceiveAlgorithm : public ReceiveAlgorithmInterface {
72 public:
73  virtual bool GenerateCongestionFeedback(
74      QuicCongestionFeedbackFrame* /*congestion_feedback*/) {
75    return false;
76  }
77
78  MOCK_METHOD3(RecordIncomingPacket,
79               void(QuicByteCount, QuicPacketSequenceNumber, QuicTime));
80};
81
82// Subclass of QuicHttpStream that closes itself when the first piece of data
83// is received.
84class AutoClosingStream : public QuicHttpStream {
85 public:
86  explicit AutoClosingStream(const base::WeakPtr<QuicClientSession>& session)
87      : QuicHttpStream(session) {
88  }
89
90  virtual int OnDataReceived(const char* data, int length) OVERRIDE {
91    Close(false);
92    return OK;
93  }
94};
95
96}  // namespace
97
98class QuicHttpStreamPeer {
99 public:
100  static QuicReliableClientStream* GetQuicReliableClientStream(
101      QuicHttpStream* stream) {
102    return stream->stream_;
103  }
104};
105
106class QuicHttpStreamTest : public ::testing::TestWithParam<QuicVersion> {
107 protected:
108  static const bool kFin = true;
109  static const bool kIncludeVersion = true;
110  static const bool kIncludeCongestionFeedback = true;
111
112  // Holds a packet to be written to the wire, and the IO mode that should
113  // be used by the mock socket when performing the write.
114  struct PacketToWrite {
115    PacketToWrite(IoMode mode, QuicEncryptedPacket* packet)
116        : mode(mode),
117          packet(packet) {
118    }
119    IoMode mode;
120    QuicEncryptedPacket* packet;
121  };
122
123  QuicHttpStreamTest()
124      : net_log_(BoundNetLog()),
125        use_closing_stream_(false),
126        read_buffer_(new IOBufferWithSize(4096)),
127        guid_(2),
128        stream_id_(GetParam() > QUIC_VERSION_12 ? 5 : 3),
129        maker_(GetParam(), guid_),
130        random_generator_(0) {
131    IPAddressNumber ip;
132    CHECK(ParseIPLiteralToNumber("192.0.2.33", &ip));
133    peer_addr_ = IPEndPoint(ip, 443);
134    self_addr_ = IPEndPoint(ip, 8435);
135  }
136
137  ~QuicHttpStreamTest() {
138    session_->CloseSessionOnError(ERR_ABORTED);
139    for (size_t i = 0; i < writes_.size(); i++) {
140      delete writes_[i].packet;
141    }
142  }
143
144  // Adds a packet to the list of expected writes.
145  void AddWrite(scoped_ptr<QuicEncryptedPacket> packet) {
146    writes_.push_back(PacketToWrite(SYNCHRONOUS, packet.release()));
147  }
148
149  // Returns the packet to be written at position |pos|.
150  QuicEncryptedPacket* GetWrite(size_t pos) {
151    return writes_[pos].packet;
152  }
153
154  bool AtEof() {
155    return socket_data_->at_read_eof() && socket_data_->at_write_eof();
156  }
157
158  void ProcessPacket(scoped_ptr<QuicEncryptedPacket> packet) {
159    connection_->ProcessUdpPacket(self_addr_, peer_addr_, *packet);
160  }
161
162  // Configures the test fixture to use the list of expected writes.
163  void Initialize() {
164    mock_writes_.reset(new MockWrite[writes_.size()]);
165    for (size_t i = 0; i < writes_.size(); i++) {
166      mock_writes_[i] = MockWrite(writes_[i].mode,
167                                  writes_[i].packet->data(),
168                                  writes_[i].packet->length());
169    };
170
171    socket_data_.reset(new StaticSocketDataProvider(NULL, 0, mock_writes_.get(),
172                                                    writes_.size()));
173
174    MockUDPClientSocket* socket = new MockUDPClientSocket(socket_data_.get(),
175                                                          net_log_.net_log());
176    socket->Connect(peer_addr_);
177    runner_ = new TestTaskRunner(&clock_);
178    send_algorithm_ = new MockSendAlgorithm();
179    receive_algorithm_ = new TestReceiveAlgorithm();
180    EXPECT_CALL(*receive_algorithm_, RecordIncomingPacket(_, _, _)).
181        Times(AnyNumber());
182    EXPECT_CALL(*send_algorithm_,
183                OnPacketSent(_, _, _, _, _)).WillRepeatedly(Return(true));
184    EXPECT_CALL(*send_algorithm_, RetransmissionDelay()).WillRepeatedly(
185        Return(QuicTime::Delta::Zero()));
186    EXPECT_CALL(*send_algorithm_, TimeUntilSend(_, _, _, _)).
187        WillRepeatedly(Return(QuicTime::Delta::Zero()));
188    EXPECT_CALL(*send_algorithm_, SmoothedRtt()).WillRepeatedly(
189        Return(QuicTime::Delta::Zero()));
190    EXPECT_CALL(*send_algorithm_, BandwidthEstimate()).WillRepeatedly(
191        Return(QuicBandwidth::Zero()));
192    EXPECT_CALL(*send_algorithm_, SetFromConfig(_, _)).Times(AnyNumber());
193    helper_.reset(new QuicConnectionHelper(runner_.get(), &clock_,
194                                           &random_generator_));
195    writer_.reset(new QuicDefaultPacketWriter(socket));
196    connection_ = new TestQuicConnection(SupportedVersions(GetParam()), guid_,
197                                         peer_addr_, helper_.get(),
198                                         writer_.get());
199    connection_->set_visitor(&visitor_);
200    connection_->SetSendAlgorithm(send_algorithm_);
201    connection_->SetReceiveAlgorithm(receive_algorithm_);
202    crypto_config_.SetDefaults();
203    session_.reset(
204        new QuicClientSession(connection_,
205                              scoped_ptr<DatagramClientSocket>(socket),
206                              writer_.Pass(), NULL,
207                              &crypto_client_stream_factory_,
208                              "www.google.com", DefaultQuicConfig(),
209                              &crypto_config_, NULL));
210    session_->GetCryptoStream()->CryptoConnect();
211    EXPECT_TRUE(session_->IsCryptoHandshakeConfirmed());
212    stream_.reset(use_closing_stream_ ?
213                  new AutoClosingStream(session_->GetWeakPtr()) :
214                  new QuicHttpStream(session_->GetWeakPtr()));
215  }
216
217  void SetRequest(const std::string& method,
218                  const std::string& path,
219                  RequestPriority priority) {
220    request_headers_ = maker_.GetRequestHeaders(method, "http", path);
221    request_data_ = GetParam() > QUIC_VERSION_12 ? "" :
222        SerializeHeaderBlock(request_headers_, true, priority);
223  }
224
225  void SetResponse(const std::string& status, const std::string& body) {
226    response_headers_ = maker_.GetResponseHeaders(status);
227    if (GetParam() > QUIC_VERSION_12) {
228      response_data_ = body;
229    } else {
230      response_data_ =
231          SerializeHeaderBlock(response_headers_, false, DEFAULT_PRIORITY) +
232          body;
233    }
234  }
235
236  scoped_ptr<QuicEncryptedPacket> ConstructDataPacket(
237      QuicPacketSequenceNumber sequence_number,
238      bool should_include_version,
239      bool fin,
240      QuicStreamOffset offset,
241      base::StringPiece data) {
242    return maker_.MakeDataPacket(
243        sequence_number, stream_id_, should_include_version, fin, offset, data);
244  }
245
246  scoped_ptr<QuicEncryptedPacket> ConstructRequestHeadersPacket(
247      QuicPacketSequenceNumber sequence_number,
248      bool fin) {
249    return maker_.MakeRequestHeadersPacket(
250        sequence_number, stream_id_, kIncludeVersion, fin, request_headers_);
251  }
252
253  scoped_ptr<QuicEncryptedPacket> ConstructResponseHeadersPacket(
254      QuicPacketSequenceNumber sequence_number,
255      bool fin) {
256    return maker_.MakeResponseHeadersPacket(
257        sequence_number, stream_id_, !kIncludeVersion, fin, response_headers_);
258  }
259
260  scoped_ptr<QuicEncryptedPacket> ConstructRstStreamPacket(
261      QuicPacketSequenceNumber sequence_number) {
262    return maker_.MakeRstPacket(
263        sequence_number, true, stream_id_, QUIC_STREAM_NO_ERROR);
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        1, 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  std::string SerializeHeaderBlock(const SpdyHeaderBlock& headers,
307                                   bool write_priority,
308                                   RequestPriority priority) {
309    QuicSpdyCompressor compressor;
310    if (write_priority) {
311      return compressor.CompressHeadersWithPriority(
312          ConvertRequestPriorityToQuicPriority(priority), headers);
313    }
314    return compressor.CompressHeaders(headers);
315  }
316
317  const QuicGuid guid_;
318  const QuicStreamId stream_id_;
319  QuicTestPacketMaker maker_;
320  IPEndPoint self_addr_;
321  IPEndPoint peer_addr_;
322  MockRandom random_generator_;
323  MockCryptoClientStreamFactory crypto_client_stream_factory_;
324  scoped_ptr<StaticSocketDataProvider> socket_data_;
325  std::vector<PacketToWrite> writes_;
326};
327
328INSTANTIATE_TEST_CASE_P(Version, QuicHttpStreamTest,
329                        ::testing::ValuesIn(QuicSupportedVersions()));
330
331TEST_P(QuicHttpStreamTest, RenewStreamForAuth) {
332  Initialize();
333  EXPECT_EQ(NULL, stream_->RenewStreamForAuth());
334}
335
336TEST_P(QuicHttpStreamTest, CanFindEndOfResponse) {
337  Initialize();
338  EXPECT_TRUE(stream_->CanFindEndOfResponse());
339}
340
341TEST_P(QuicHttpStreamTest, IsConnectionReusable) {
342  Initialize();
343  EXPECT_FALSE(stream_->IsConnectionReusable());
344}
345
346TEST_P(QuicHttpStreamTest, GetRequest) {
347  SetRequest("GET", "/", DEFAULT_PRIORITY);
348  if (GetParam() > QUIC_VERSION_12) {
349    AddWrite(ConstructRequestHeadersPacket(1, kFin));
350  } else {
351    AddWrite(ConstructDataPacket(1, kIncludeVersion, kFin, 0, request_data_));
352  }
353  Initialize();
354
355  request_.method = "GET";
356  request_.url = GURL("http://www.google.com/");
357
358  EXPECT_EQ(OK, stream_->InitializeStream(&request_, DEFAULT_PRIORITY,
359                                          net_log_, callback_.callback()));
360  EXPECT_EQ(OK, stream_->SendRequest(headers_, &response_,
361                                     callback_.callback()));
362  EXPECT_EQ(&response_, stream_->GetResponseInfo());
363
364  // Ack the request.
365  ProcessPacket(ConstructAckPacket(1, 0, 0));
366
367  EXPECT_EQ(ERR_IO_PENDING,
368            stream_->ReadResponseHeaders(callback_.callback()));
369
370  SetResponse("404 Not Found", std::string());
371  if (GetParam() > QUIC_VERSION_12) {
372    ProcessPacket(ConstructResponseHeadersPacket(2, kFin));
373  } else {
374    ProcessPacket(ConstructDataPacket(2, false, kFin, 0, response_data_));
375  }
376
377  // Now that the headers have been processed, the callback will return.
378  EXPECT_EQ(OK, callback_.WaitForResult());
379  ASSERT_TRUE(response_.headers.get());
380  EXPECT_EQ(404, response_.headers->response_code());
381  EXPECT_TRUE(response_.headers->HasHeaderValue("Content-Type", "text/plain"));
382
383  // There is no body, so this should return immediately.
384  EXPECT_EQ(0, stream_->ReadResponseBody(read_buffer_.get(),
385                                         read_buffer_->size(),
386                                         callback_.callback()));
387  EXPECT_TRUE(stream_->IsResponseBodyComplete());
388  EXPECT_TRUE(AtEof());
389}
390
391// Regression test for http://crbug.com/288128
392TEST_P(QuicHttpStreamTest, GetRequestLargeResponse) {
393  SetRequest("GET", "/", DEFAULT_PRIORITY);
394  if (GetParam() > QUIC_VERSION_12) {
395    AddWrite(ConstructRequestHeadersPacket(1, kFin));
396  } else {
397    AddWrite(ConstructDataPacket(1, kIncludeVersion, kFin, 0, request_data_));
398  }
399  Initialize();
400
401  request_.method = "GET";
402  request_.url = GURL("http://www.google.com/");
403
404  EXPECT_EQ(OK, stream_->InitializeStream(&request_, DEFAULT_PRIORITY,
405                                          net_log_, callback_.callback()));
406  EXPECT_EQ(OK, stream_->SendRequest(headers_, &response_,
407                                     callback_.callback()));
408  EXPECT_EQ(&response_, stream_->GetResponseInfo());
409
410  // Ack the request.
411  ProcessPacket(ConstructAckPacket(1, 0, 0));
412
413  EXPECT_EQ(ERR_IO_PENDING,
414            stream_->ReadResponseHeaders(callback_.callback()));
415
416  SpdyHeaderBlock headers;
417  headers[":status"] = "200 OK";
418  headers[":version"] = "HTTP/1.1";
419  headers["content-type"] = "text/plain";
420  headers["big6"] = std::string(10000, 'x');  // Lots of x's.
421
422  std::string response = SpdyUtils::SerializeUncompressedHeaders(headers);
423  EXPECT_LT(4096u, response.length());
424  stream_->OnDataReceived(response.data(), response.length());
425  stream_->OnClose(QUIC_NO_ERROR);
426
427  // Now that the headers have been processed, the callback will return.
428  EXPECT_EQ(OK, callback_.WaitForResult());
429  ASSERT_TRUE(response_.headers.get());
430  EXPECT_EQ(200, response_.headers->response_code());
431  EXPECT_TRUE(response_.headers->HasHeaderValue("Content-Type", "text/plain"));
432
433  // There is no body, so this should return immediately.
434  EXPECT_EQ(0, stream_->ReadResponseBody(read_buffer_.get(),
435                                         read_buffer_->size(),
436                                         callback_.callback()));
437  EXPECT_TRUE(stream_->IsResponseBodyComplete());
438  EXPECT_TRUE(AtEof());
439}
440
441TEST_P(QuicHttpStreamTest, GetRequestFullResponseInSinglePacket) {
442  SetRequest("GET", "/", DEFAULT_PRIORITY);
443  AddWrite(ConstructDataPacket(1, kIncludeVersion, kFin, 0, request_data_));
444  Initialize();
445
446  if (GetParam() > QUIC_VERSION_12) {
447    // we can't put the request and response into a single frame.
448    return;
449  }
450
451  request_.method = "GET";
452  request_.url = GURL("http://www.google.com/");
453
454  EXPECT_EQ(OK, stream_->InitializeStream(&request_, DEFAULT_PRIORITY,
455                                          net_log_, callback_.callback()));
456  EXPECT_EQ(OK, stream_->SendRequest(headers_, &response_,
457                                     callback_.callback()));
458  EXPECT_EQ(&response_, stream_->GetResponseInfo());
459
460  // Ack the request.
461  ProcessPacket(ConstructAckPacket(1, 0, 0));
462
463  EXPECT_EQ(ERR_IO_PENDING,
464            stream_->ReadResponseHeaders(callback_.callback()));
465
466  // Send the response with a body.
467  SetResponse("200 OK", "hello world!");
468  ProcessPacket(ConstructDataPacket(2, false, kFin, 0, response_data_));
469
470  // Now that the headers have been processed, the callback will return.
471  EXPECT_EQ(OK, callback_.WaitForResult());
472  ASSERT_TRUE(response_.headers.get());
473  EXPECT_EQ(200, response_.headers->response_code());
474  EXPECT_TRUE(response_.headers->HasHeaderValue("Content-Type", "text/plain"));
475
476  // There is no body, so this should return immediately.
477  // Since the body has already arrived, this should return immediately.
478  EXPECT_EQ(12, stream_->ReadResponseBody(read_buffer_.get(),
479                                          read_buffer_->size(),
480                                          callback_.callback()));
481  EXPECT_TRUE(stream_->IsResponseBodyComplete());
482  EXPECT_TRUE(AtEof());
483}
484
485TEST_P(QuicHttpStreamTest, SendPostRequest) {
486  SetRequest("POST", "/", DEFAULT_PRIORITY);
487  if (GetParam() > QUIC_VERSION_12) {
488    AddWrite(ConstructRequestHeadersPacket(1, !kFin));
489    AddWrite(ConstructDataPacket(2, kIncludeVersion, kFin, 0, kUploadData));
490  } else {
491    AddWrite(ConstructDataPacket(1, kIncludeVersion, !kFin, 0, request_data_));
492    AddWrite(ConstructDataPacket(2, kIncludeVersion, kFin,
493                                 request_data_.length(), kUploadData));
494  }
495  AddWrite(ConstructAckPacket(3, 3, 1));
496
497  Initialize();
498
499  ScopedVector<UploadElementReader> element_readers;
500  element_readers.push_back(
501      new UploadBytesElementReader(kUploadData, strlen(kUploadData)));
502  UploadDataStream upload_data_stream(element_readers.Pass(), 0);
503  request_.method = "POST";
504  request_.url = GURL("http://www.google.com/");
505  request_.upload_data_stream = &upload_data_stream;
506  ASSERT_EQ(OK, request_.upload_data_stream->Init(CompletionCallback()));
507
508  EXPECT_EQ(OK, stream_->InitializeStream(&request_, DEFAULT_PRIORITY,
509                                          net_log_, callback_.callback()));
510  EXPECT_EQ(OK, stream_->SendRequest(headers_, &response_,
511                                     callback_.callback()));
512  EXPECT_EQ(&response_, stream_->GetResponseInfo());
513
514  // Ack both packets in the request.
515  ProcessPacket(ConstructAckPacket(1, 0, 0));
516
517  // Send the response headers (but not the body).
518  SetResponse("200 OK", std::string());
519  if (GetParam() > QUIC_VERSION_12) {
520    ProcessPacket(ConstructResponseHeadersPacket(2, !kFin));
521  } else {
522    ProcessPacket(ConstructDataPacket(2, false, !kFin, 0, response_data_));
523  }
524
525  // Since the headers have already arrived, this should return immediately.
526  EXPECT_EQ(OK, stream_->ReadResponseHeaders(callback_.callback()));
527  ASSERT_TRUE(response_.headers.get());
528  EXPECT_EQ(200, response_.headers->response_code());
529  EXPECT_TRUE(response_.headers->HasHeaderValue("Content-Type", "text/plain"));
530
531  // Send the response body.
532  const char kResponseBody[] = "Hello world!";
533  if (GetParam() > QUIC_VERSION_12) {
534    ProcessPacket(ConstructDataPacket(3, false, kFin, 0, kResponseBody));
535  } else {
536    ProcessPacket(ConstructDataPacket(3, false, kFin, response_data_.length(),
537                                      kResponseBody));
538  }
539  // Since the body has already arrived, this should return immediately.
540  EXPECT_EQ(static_cast<int>(strlen(kResponseBody)),
541            stream_->ReadResponseBody(read_buffer_.get(), read_buffer_->size(),
542                                      callback_.callback()));
543
544  EXPECT_TRUE(stream_->IsResponseBodyComplete());
545  EXPECT_TRUE(AtEof());
546}
547
548TEST_P(QuicHttpStreamTest, SendChunkedPostRequest) {
549  SetRequest("POST", "/", DEFAULT_PRIORITY);
550  size_t chunk_size = strlen(kUploadData);
551  if (GetParam() > QUIC_VERSION_12) {
552    AddWrite(ConstructRequestHeadersPacket(1, !kFin));
553    AddWrite(ConstructDataPacket(2, kIncludeVersion, !kFin, 0, kUploadData));
554    AddWrite(ConstructDataPacket(3, kIncludeVersion, kFin, chunk_size,
555                                 kUploadData));
556  } else {
557    AddWrite(ConstructDataPacket(1, kIncludeVersion, !kFin, 0, request_data_));
558    AddWrite(ConstructDataPacket(2, kIncludeVersion, !kFin,
559                                 request_data_.length(), kUploadData));
560    AddWrite(ConstructDataPacket(3, kIncludeVersion, kFin,
561                                 request_data_.length() + chunk_size,
562                                 kUploadData));
563  }
564  AddWrite(ConstructAckPacket(4, 3, 1));
565  Initialize();
566
567  UploadDataStream upload_data_stream(UploadDataStream::CHUNKED, 0);
568  upload_data_stream.AppendChunk(kUploadData, chunk_size, false);
569
570  request_.method = "POST";
571  request_.url = GURL("http://www.google.com/");
572  request_.upload_data_stream = &upload_data_stream;
573  ASSERT_EQ(OK, request_.upload_data_stream->Init(CompletionCallback()));
574
575  ASSERT_EQ(OK, stream_->InitializeStream(&request_, DEFAULT_PRIORITY,
576                                          net_log_, callback_.callback()));
577  ASSERT_EQ(ERR_IO_PENDING, stream_->SendRequest(headers_, &response_,
578                                                 callback_.callback()));
579  EXPECT_EQ(&response_, stream_->GetResponseInfo());
580
581  upload_data_stream.AppendChunk(kUploadData, chunk_size, true);
582
583  // Ack both packets in the request.
584  ProcessPacket(ConstructAckPacket(1, 0, 0));
585
586  // Send the response headers (but not the body).
587  SetResponse("200 OK", std::string());
588  if (GetParam() > QUIC_VERSION_12) {
589    ProcessPacket(ConstructResponseHeadersPacket(2, !kFin));
590  } else {
591    ProcessPacket(ConstructDataPacket(2, false, !kFin, 0, response_data_));
592  }
593
594  // Since the headers have already arrived, this should return immediately.
595  ASSERT_EQ(OK, stream_->ReadResponseHeaders(callback_.callback()));
596  ASSERT_TRUE(response_.headers.get());
597  EXPECT_EQ(200, response_.headers->response_code());
598  EXPECT_TRUE(response_.headers->HasHeaderValue("Content-Type", "text/plain"));
599
600  // Send the response body.
601  const char kResponseBody[] = "Hello world!";
602  ProcessPacket(ConstructDataPacket(3, false, kFin, response_data_.length(),
603                                    kResponseBody));
604
605  // Since the body has already arrived, this should return immediately.
606  ASSERT_EQ(static_cast<int>(strlen(kResponseBody)),
607            stream_->ReadResponseBody(read_buffer_.get(), read_buffer_->size(),
608                                      callback_.callback()));
609
610  EXPECT_TRUE(stream_->IsResponseBodyComplete());
611  EXPECT_TRUE(AtEof());
612}
613
614TEST_P(QuicHttpStreamTest, DestroyedEarly) {
615  SetRequest("GET", "/", DEFAULT_PRIORITY);
616  if (GetParam() > QUIC_VERSION_12) {
617    AddWrite(ConstructRequestHeadersPacket(1, kFin));
618  } else {
619    AddWrite(ConstructDataPacket(1, kIncludeVersion, kFin, 0, request_data_));
620  }
621  AddWrite(ConstructAckAndRstStreamPacket(2));
622  use_closing_stream_ = true;
623  Initialize();
624
625  request_.method = "GET";
626  request_.url = GURL("http://www.google.com/");
627
628  EXPECT_EQ(OK, stream_->InitializeStream(&request_, DEFAULT_PRIORITY,
629                                          net_log_, callback_.callback()));
630  EXPECT_EQ(OK, stream_->SendRequest(headers_, &response_,
631                                     callback_.callback()));
632  EXPECT_EQ(&response_, stream_->GetResponseInfo());
633
634  // Ack the request.
635  ProcessPacket(ConstructAckPacket(1, 0, 0));
636  EXPECT_EQ(ERR_IO_PENDING,
637            stream_->ReadResponseHeaders(callback_.callback()));
638
639  // Send the response with a body.
640  SetResponse("404 OK", "hello world!");
641  // In the course of processing this packet, the QuicHttpStream close itself.
642  if (GetParam() > QUIC_VERSION_12) {
643    ProcessPacket(ConstructResponseHeadersPacket(2, kFin));
644  } else {
645    ProcessPacket(ConstructDataPacket(2, false, kFin, 0, response_data_));
646  }
647
648  EXPECT_TRUE(AtEof());
649}
650
651TEST_P(QuicHttpStreamTest, Priority) {
652  SetRequest("GET", "/", MEDIUM);
653  if (GetParam() > QUIC_VERSION_12) {
654    AddWrite(ConstructRequestHeadersPacket(1, kFin));
655  } else {
656    AddWrite(ConstructDataPacket(1, kIncludeVersion, kFin, 0, request_data_));
657  }
658  AddWrite(ConstructAckAndRstStreamPacket(2));
659  use_closing_stream_ = true;
660  Initialize();
661
662  request_.method = "GET";
663  request_.url = GURL("http://www.google.com/");
664
665  EXPECT_EQ(OK, stream_->InitializeStream(&request_, MEDIUM,
666                                          net_log_, callback_.callback()));
667
668  // Check that priority is highest.
669  QuicReliableClientStream* reliable_stream =
670      QuicHttpStreamPeer::GetQuicReliableClientStream(stream_.get());
671  DCHECK(reliable_stream);
672  DCHECK_EQ(QuicWriteBlockedList::kHighestPriority,
673            reliable_stream->EffectivePriority());
674
675  EXPECT_EQ(OK, stream_->SendRequest(headers_, &response_,
676                                     callback_.callback()));
677  EXPECT_EQ(&response_, stream_->GetResponseInfo());
678
679  // Check that priority has now dropped back to MEDIUM.
680  DCHECK_EQ(MEDIUM, ConvertQuicPriorityToRequestPriority(
681      reliable_stream->EffectivePriority()));
682
683  // Ack the request.
684  ProcessPacket(ConstructAckPacket(1, 0, 0));
685  EXPECT_EQ(ERR_IO_PENDING,
686            stream_->ReadResponseHeaders(callback_.callback()));
687
688  // Send the response with a body.
689  SetResponse("404 OK", "hello world!");
690  // In the course of processing this packet, the QuicHttpStream close itself.
691  if (GetParam() > QUIC_VERSION_12) {
692    ProcessPacket(ConstructResponseHeadersPacket(2, kFin));
693  } else {
694    ProcessPacket(ConstructDataPacket(2, !kIncludeVersion, kFin, 0,
695                                      response_data_));
696  }
697
698  EXPECT_TRUE(AtEof());
699}
700
701// Regression test for http://crbug.com/294870
702TEST_P(QuicHttpStreamTest, CheckPriorityWithNoDelegate) {
703  SetRequest("GET", "/", MEDIUM);
704  use_closing_stream_ = true;
705
706  if (GetParam() > QUIC_VERSION_13) {
707    AddWrite(ConstructRstStreamPacket(1));
708  }
709
710  Initialize();
711
712  request_.method = "GET";
713  request_.url = GURL("http://www.google.com/");
714
715  EXPECT_EQ(OK, stream_->InitializeStream(&request_, MEDIUM,
716                                          net_log_, callback_.callback()));
717
718  // Check that priority is highest.
719  QuicReliableClientStream* reliable_stream =
720      QuicHttpStreamPeer::GetQuicReliableClientStream(stream_.get());
721  DCHECK(reliable_stream);
722  QuicReliableClientStream::Delegate* delegate = reliable_stream->GetDelegate();
723  DCHECK(delegate);
724  DCHECK_EQ(QuicWriteBlockedList::kHighestPriority,
725            reliable_stream->EffectivePriority());
726
727  // Set Delegate to NULL and make sure EffectivePriority returns highest
728  // priority.
729  reliable_stream->SetDelegate(NULL);
730  DCHECK_EQ(QuicWriteBlockedList::kHighestPriority,
731            reliable_stream->EffectivePriority());
732  reliable_stream->SetDelegate(delegate);
733}
734
735TEST_P(QuicHttpStreamTest, DontCompressHeadersWhenNotWritable) {
736  SetRequest("GET", "/", MEDIUM);
737  AddWrite(ConstructDataPacket(1, kIncludeVersion, kFin, 0, request_data_));
738  Initialize();
739
740  if (GetParam() > QUIC_VERSION_12) {
741    // The behavior tested here is obsolete.
742    return;
743  }
744  request_.method = "GET";
745  request_.url = GURL("http://www.google.com/");
746
747  EXPECT_CALL(*send_algorithm_, TimeUntilSend(_, _, _, _)).
748      WillRepeatedly(Return(QuicTime::Delta::Infinite()));
749  EXPECT_EQ(OK, stream_->InitializeStream(&request_, MEDIUM,
750                                          net_log_, callback_.callback()));
751  EXPECT_EQ(ERR_IO_PENDING, stream_->SendRequest(headers_, &response_,
752                                                 callback_.callback()));
753
754  // Verify that the headers have not been compressed and buffered in
755  // the stream.
756  QuicReliableClientStream* reliable_stream =
757      QuicHttpStreamPeer::GetQuicReliableClientStream(stream_.get());
758  EXPECT_FALSE(reliable_stream->HasBufferedData());
759  EXPECT_FALSE(AtEof());
760
761  EXPECT_CALL(*send_algorithm_, TimeUntilSend(_, _, _, _)).
762      WillRepeatedly(Return(QuicTime::Delta::Zero()));
763
764  // Data should flush out now.
765  connection_->OnCanWrite();
766  EXPECT_FALSE(reliable_stream->HasBufferedData());
767  EXPECT_TRUE(AtEof());
768}
769
770}  // namespace test
771}  // namespace net
772