12a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
22a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
32a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// found in the LICENSE file.
42a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
52a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "net/quic/quic_http_stream.h"
62a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
72a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include <vector>
82a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
92a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "net/base/net_errors.h"
102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "net/base/test_completion_callback.h"
112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "net/base/upload_bytes_element_reader.h"
122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "net/base/upload_data_stream.h"
132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "net/http/http_response_headers.h"
1403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)#include "net/http/transport_security_state.h"
152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "net/quic/congestion_control/receive_algorithm_interface.h"
162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "net/quic/congestion_control/send_algorithm_interface.h"
172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "net/quic/crypto/crypto_protocol.h"
182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "net/quic/crypto/quic_decrypter.h"
192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "net/quic/crypto/quic_encrypter.h"
20a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "net/quic/crypto/quic_server_info.h"
212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "net/quic/quic_client_session.h"
222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "net/quic/quic_connection.h"
232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "net/quic/quic_connection_helper.h"
241e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)#include "net/quic/quic_default_packet_writer.h"
25d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)#include "net/quic/quic_http_utils.h"
26d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)#include "net/quic/quic_reliable_client_stream.h"
275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "net/quic/quic_write_blocked_list.h"
2858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#include "net/quic/spdy_utils.h"
292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "net/quic/test_tools/mock_clock.h"
302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "net/quic/test_tools/mock_crypto_client_stream_factory.h"
312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "net/quic/test_tools/mock_random.h"
322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "net/quic/test_tools/quic_connection_peer.h"
335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "net/quic/test_tools/quic_test_packet_maker.h"
342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "net/quic/test_tools/quic_test_utils.h"
352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "net/quic/test_tools/test_task_runner.h"
362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "net/socket/socket_test_util.h"
372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "net/spdy/spdy_frame_builder.h"
382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "net/spdy/spdy_framer.h"
392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "net/spdy/spdy_http_utils.h"
402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "net/spdy/spdy_protocol.h"
412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "testing/gmock/include/gmock/gmock.h"
422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "testing/gtest/include/gtest/gtest.h"
432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)using testing::_;
45424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)using testing::AnyNumber;
46424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)using testing::Return;
472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace net {
492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace test {
502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace {
512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)const char kUploadData[] = "Really nifty data!";
53a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)const char kServerHostname[] = "www.google.com";
54a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)const uint16 kServerPort = 80;
552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)class TestQuicConnection : public QuicConnection {
572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) public:
585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  TestQuicConnection(const QuicVersionVector& versions,
59a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                     QuicConnectionId connection_id,
602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                     IPEndPoint address,
611e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)                     QuicConnectionHelper* helper,
6203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)                     const QuicConnection::PacketWriterFactory& writer_factory)
635f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      : QuicConnection(connection_id,
645f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                       address,
655f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                       helper,
6603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)                       writer_factory,
6703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)                       true  /* owns_writer */,
685f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                       false  /* is_server */,
69cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                       versions) {
702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  void SetSendAlgorithm(SendAlgorithmInterface* send_algorithm) {
732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    QuicConnectionPeer::SetSendAlgorithm(this, send_algorithm);
742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  void SetReceiveAlgorithm(ReceiveAlgorithmInterface* receive_algorithm) {
772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    QuicConnectionPeer::SetReceiveAlgorithm(this, receive_algorithm);
782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)};
802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)class TestReceiveAlgorithm : public ReceiveAlgorithmInterface {
822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) public:
835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  virtual bool GenerateCongestionFeedback(
845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      QuicCongestionFeedbackFrame* /*congestion_feedback*/) {
855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return false;
862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  MOCK_METHOD3(RecordIncomingPacket,
895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)               void(QuicByteCount, QuicPacketSequenceNumber, QuicTime));
902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)};
912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Subclass of QuicHttpStream that closes itself when the first piece of data
932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// is received.
942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)class AutoClosingStream : public QuicHttpStream {
952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) public:
96a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  explicit AutoClosingStream(const base::WeakPtr<QuicClientSession>& session)
97a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      : QuicHttpStream(session) {
982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual int OnDataReceived(const char* data, int length) OVERRIDE {
1012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    Close(false);
1022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return OK;
1032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)};
1052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
10603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)class TestPacketWriterFactory : public QuicConnection::PacketWriterFactory {
10703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) public:
10803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  explicit TestPacketWriterFactory(DatagramClientSocket* socket)
10903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      : socket_(socket) {}
11003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  virtual ~TestPacketWriterFactory() {}
11103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
11203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  virtual QuicPacketWriter* Create(QuicConnection* connection) const OVERRIDE {
11303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    return new QuicDefaultPacketWriter(socket_);
11403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  }
11503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
11603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) private:
11703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  DatagramClientSocket* socket_;
11803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)};
11903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
1202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}  // namespace
1212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
122d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)class QuicHttpStreamPeer {
123d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) public:
124d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  static QuicReliableClientStream* GetQuicReliableClientStream(
125d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      QuicHttpStream* stream) {
126d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    return stream->stream_;
127d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  }
128d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)};
129d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
1305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)class QuicHttpStreamTest : public ::testing::TestWithParam<QuicVersion> {
1312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) protected:
1325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  static const bool kFin = true;
1335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  static const bool kIncludeVersion = true;
1345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  static const bool kIncludeCongestionFeedback = true;
1355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Holds a packet to be written to the wire, and the IO mode that should
1372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // be used by the mock socket when performing the write.
1382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  struct PacketToWrite {
1392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    PacketToWrite(IoMode mode, QuicEncryptedPacket* packet)
1402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        : mode(mode),
1412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          packet(packet) {
1422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
1432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    IoMode mode;
1442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    QuicEncryptedPacket* packet;
1452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  };
1462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  QuicHttpStreamTest()
1482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      : net_log_(BoundNetLog()),
1492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        use_closing_stream_(false),
1502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        read_buffer_(new IOBufferWithSize(4096)),
151a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)        connection_id_(2),
152cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        stream_id_(kClientDataStreamId1),
1531320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        maker_(GetParam(), connection_id_, &clock_),
1545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        random_generator_(0) {
1552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    IPAddressNumber ip;
1562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    CHECK(ParseIPLiteralToNumber("192.0.2.33", &ip));
1572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    peer_addr_ = IPEndPoint(ip, 443);
1582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    self_addr_ = IPEndPoint(ip, 8435);
1591320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    clock_.AdvanceTime(QuicTime::Delta::FromMilliseconds(20));
1602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ~QuicHttpStreamTest() {
1638bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    session_->CloseSessionOnError(ERR_ABORTED);
1642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    for (size_t i = 0; i < writes_.size(); i++) {
1652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      delete writes_[i].packet;
1662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
1672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Adds a packet to the list of expected writes.
1705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  void AddWrite(scoped_ptr<QuicEncryptedPacket> packet) {
1715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    writes_.push_back(PacketToWrite(SYNCHRONOUS, packet.release()));
1722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Returns the packet to be written at position |pos|.
1752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  QuicEncryptedPacket* GetWrite(size_t pos) {
1762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return writes_[pos].packet;
1772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  bool AtEof() {
1802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return socket_data_->at_read_eof() && socket_data_->at_write_eof();
1812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  void ProcessPacket(scoped_ptr<QuicEncryptedPacket> packet) {
1845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    connection_->ProcessUdpPacket(self_addr_, peer_addr_, *packet);
1852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Configures the test fixture to use the list of expected writes.
1882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  void Initialize() {
1892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    mock_writes_.reset(new MockWrite[writes_.size()]);
1902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    for (size_t i = 0; i < writes_.size(); i++) {
1912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      mock_writes_[i] = MockWrite(writes_[i].mode,
1922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                  writes_[i].packet->data(),
1932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                  writes_[i].packet->length());
1942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    };
1952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    socket_data_.reset(new StaticSocketDataProvider(NULL, 0, mock_writes_.get(),
1972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                                    writes_.size()));
1982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    MockUDPClientSocket* socket = new MockUDPClientSocket(socket_data_.get(),
2002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                                          net_log_.net_log());
2012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    socket->Connect(peer_addr_);
2022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    runner_ = new TestTaskRunner(&clock_);
2032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    send_algorithm_ = new MockSendAlgorithm();
2045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    receive_algorithm_ = new TestReceiveAlgorithm();
2055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    EXPECT_CALL(*receive_algorithm_, RecordIncomingPacket(_, _, _)).
206424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)        Times(AnyNumber());
20768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    EXPECT_CALL(*send_algorithm_,
208010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)                OnPacketSent(_, _, _, _, _)).WillRepeatedly(Return(true));
209558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch    EXPECT_CALL(*send_algorithm_, RetransmissionDelay()).WillRepeatedly(
210424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)        Return(QuicTime::Delta::Zero()));
2115c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    EXPECT_CALL(*send_algorithm_, GetCongestionWindow()).WillRepeatedly(
2125c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu        Return(kMaxPacketSize));
213010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    EXPECT_CALL(*send_algorithm_, TimeUntilSend(_, _, _)).
214424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)        WillRepeatedly(Return(QuicTime::Delta::Zero()));
2153551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    EXPECT_CALL(*send_algorithm_, BandwidthEstimate()).WillRepeatedly(
216424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)        Return(QuicBandwidth::Zero()));
2170f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)    EXPECT_CALL(*send_algorithm_, SetFromConfig(_, _)).Times(AnyNumber());
2181e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    helper_.reset(new QuicConnectionHelper(runner_.get(), &clock_,
2191e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)                                           &random_generator_));
22003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    TestPacketWriterFactory writer_factory(socket);
221a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    connection_ = new TestQuicConnection(SupportedVersions(GetParam()),
222a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                         connection_id_, peer_addr_,
22303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)                                         helper_.get(), writer_factory);
2242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    connection_->set_visitor(&visitor_);
2252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    connection_->SetSendAlgorithm(send_algorithm_);
2262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    connection_->SetReceiveAlgorithm(receive_algorithm_);
227c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    crypto_config_.SetDefaults();
2283551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    session_.reset(
2293551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)        new QuicClientSession(connection_,
2301e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)                              scoped_ptr<DatagramClientSocket>(socket),
23103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)                              NULL,
23203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)                              &transport_security_state_,
23323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)                              make_scoped_ptr((QuicServerInfo*)NULL),
2341320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                              DefaultQuicConfig(),
23546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)                              base::MessageLoop::current()->
23646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)                                  message_loop_proxy().get(),
237cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                              NULL));
2381320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    session_->InitializeSession(QuicServerId(kServerHostname, kServerPort,
2391320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                                             false, PRIVACY_MODE_DISABLED),
2401320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                                &crypto_config_,
2411320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                                &crypto_client_stream_factory_);
2422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    session_->GetCryptoStream()->CryptoConnect();
243c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    EXPECT_TRUE(session_->IsCryptoHandshakeConfirmed());
2442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    stream_.reset(use_closing_stream_ ?
245a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                  new AutoClosingStream(session_->GetWeakPtr()) :
246a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                  new QuicHttpStream(session_->GetWeakPtr()));
2472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
2482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  void SetRequest(const std::string& method,
2505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                  const std::string& path,
2515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                  RequestPriority priority) {
2525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    request_headers_ = maker_.GetRequestHeaders(method, "http", path);
2532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
2542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  void SetResponse(const std::string& status, const std::string& body) {
2565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    response_headers_ = maker_.GetResponseHeaders(status);
257a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    response_data_ = body;
2582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
2592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  scoped_ptr<QuicEncryptedPacket> ConstructDataPacket(
2612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      QuicPacketSequenceNumber sequence_number,
2622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      bool should_include_version,
2632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      bool fin,
2642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      QuicStreamOffset offset,
2652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      base::StringPiece data) {
2665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return maker_.MakeDataPacket(
2675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        sequence_number, stream_id_, should_include_version, fin, offset, data);
2682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
2692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  scoped_ptr<QuicEncryptedPacket> ConstructRequestHeadersPacket(
2715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      QuicPacketSequenceNumber sequence_number,
2725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      bool fin) {
2735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return maker_.MakeRequestHeadersPacket(
2745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        sequence_number, stream_id_, kIncludeVersion, fin, request_headers_);
275424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  }
276424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
2775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  scoped_ptr<QuicEncryptedPacket> ConstructResponseHeadersPacket(
2782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      QuicPacketSequenceNumber sequence_number,
2795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      bool fin) {
2805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return maker_.MakeResponseHeadersPacket(
2815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        sequence_number, stream_id_, !kIncludeVersion, fin, response_headers_);
2825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
2832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  scoped_ptr<QuicEncryptedPacket> ConstructRstStreamPacket(
2855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      QuicPacketSequenceNumber sequence_number) {
2865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return maker_.MakeRstPacket(
2870529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch        sequence_number, true, stream_id_,
2880529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch        AdjustErrorForVersion(QUIC_RST_FLOW_CONTROL_ACCOUNTING, GetParam()));
2895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
2902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  scoped_ptr<QuicEncryptedPacket> ConstructAckAndRstStreamPacket(
2925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      QuicPacketSequenceNumber sequence_number) {
2935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return maker_.MakeAckAndRstPacket(
2945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        sequence_number, !kIncludeVersion, stream_id_, QUIC_STREAM_CANCELLED,
2955c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu        2, 1, !kIncludeCongestionFeedback);
2962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
2972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  scoped_ptr<QuicEncryptedPacket> ConstructAckPacket(
2992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      QuicPacketSequenceNumber sequence_number,
3005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      QuicPacketSequenceNumber largest_received,
3015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      QuicPacketSequenceNumber least_unacked) {
3025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return maker_.MakeAckPacket(sequence_number, largest_received,
3035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                least_unacked, !kIncludeCongestionFeedback);
3042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
3052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  BoundNetLog net_log_;
3072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  bool use_closing_stream_;
3082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  MockSendAlgorithm* send_algorithm_;
3092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  TestReceiveAlgorithm* receive_algorithm_;
3102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_refptr<TestTaskRunner> runner_;
311c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  scoped_ptr<MockWrite[]> mock_writes_;
3122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  MockClock clock_;
3132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  TestQuicConnection* connection_;
3141e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  scoped_ptr<QuicConnectionHelper> helper_;
3152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  testing::StrictMock<MockConnectionVisitor> visitor_;
3162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<QuicHttpStream> stream_;
31703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  TransportSecurityState transport_security_state_;
3182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<QuicClientSession> session_;
319c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  QuicCryptoClientConfig crypto_config_;
3202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  TestCompletionCallback callback_;
3212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  HttpRequestInfo request_;
3222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  HttpRequestHeaders headers_;
3232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  HttpResponseInfo response_;
3242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_refptr<IOBufferWithSize> read_buffer_;
3255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  SpdyHeaderBlock request_headers_;
3265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  SpdyHeaderBlock response_headers_;
3272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  std::string request_data_;
3282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  std::string response_data_;
3292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) private:
331a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  const QuicConnectionId connection_id_;
3325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  const QuicStreamId stream_id_;
3335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  QuicTestPacketMaker maker_;
3342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  IPEndPoint self_addr_;
3352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  IPEndPoint peer_addr_;
3365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  MockRandom random_generator_;
3372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  MockCryptoClientStreamFactory crypto_client_stream_factory_;
3382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<StaticSocketDataProvider> socket_data_;
3392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  std::vector<PacketToWrite> writes_;
3402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)};
3412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)INSTANTIATE_TEST_CASE_P(Version, QuicHttpStreamTest,
3435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                        ::testing::ValuesIn(QuicSupportedVersions()));
3445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
3455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)TEST_P(QuicHttpStreamTest, RenewStreamForAuth) {
3462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  Initialize();
3472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(NULL, stream_->RenewStreamForAuth());
3482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)TEST_P(QuicHttpStreamTest, CanFindEndOfResponse) {
3512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  Initialize();
3522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_TRUE(stream_->CanFindEndOfResponse());
3532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)TEST_P(QuicHttpStreamTest, IsConnectionReusable) {
3562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  Initialize();
3572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_FALSE(stream_->IsConnectionReusable());
3582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)TEST_P(QuicHttpStreamTest, GetRequest) {
3615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  SetRequest("GET", "/", DEFAULT_PRIORITY);
362a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  AddWrite(ConstructRequestHeadersPacket(1, kFin));
3632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  Initialize();
3642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  request_.method = "GET";
3662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  request_.url = GURL("http://www.google.com/");
3672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(OK, stream_->InitializeStream(&request_, DEFAULT_PRIORITY,
3692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                          net_log_, callback_.callback()));
3702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(OK, stream_->SendRequest(headers_, &response_,
3712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                     callback_.callback()));
3722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Ack the request.
3745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  ProcessPacket(ConstructAckPacket(1, 0, 0));
3752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(ERR_IO_PENDING,
3772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            stream_->ReadResponseHeaders(callback_.callback()));
3782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  SetResponse("404 Not Found", std::string());
380a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  ProcessPacket(ConstructResponseHeadersPacket(2, kFin));
3812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Now that the headers have been processed, the callback will return.
3832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(OK, callback_.WaitForResult());
3847d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  ASSERT_TRUE(response_.headers.get());
3852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(404, response_.headers->response_code());
3862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_TRUE(response_.headers->HasHeaderValue("Content-Type", "text/plain"));
387116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  EXPECT_FALSE(response_.response_time.is_null());
388116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  EXPECT_FALSE(response_.request_time.is_null());
3892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // There is no body, so this should return immediately.
3912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(0, stream_->ReadResponseBody(read_buffer_.get(),
3922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                         read_buffer_->size(),
3932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                         callback_.callback()));
39458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  EXPECT_TRUE(stream_->IsResponseBodyComplete());
39558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  EXPECT_TRUE(AtEof());
39658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)}
39758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
39858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)// Regression test for http://crbug.com/288128
3995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)TEST_P(QuicHttpStreamTest, GetRequestLargeResponse) {
4005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  SetRequest("GET", "/", DEFAULT_PRIORITY);
401a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  AddWrite(ConstructRequestHeadersPacket(1, kFin));
40258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  Initialize();
40358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
40458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  request_.method = "GET";
40558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  request_.url = GURL("http://www.google.com/");
40658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
40758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  EXPECT_EQ(OK, stream_->InitializeStream(&request_, DEFAULT_PRIORITY,
40858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)                                          net_log_, callback_.callback()));
40958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  EXPECT_EQ(OK, stream_->SendRequest(headers_, &response_,
41058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)                                     callback_.callback()));
41158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
41258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // Ack the request.
4135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  ProcessPacket(ConstructAckPacket(1, 0, 0));
41458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
41558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  EXPECT_EQ(ERR_IO_PENDING,
41658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)            stream_->ReadResponseHeaders(callback_.callback()));
41758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
41858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  SpdyHeaderBlock headers;
41958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  headers[":status"] = "200 OK";
42058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  headers[":version"] = "HTTP/1.1";
42158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  headers["content-type"] = "text/plain";
42258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  headers["big6"] = std::string(10000, 'x');  // Lots of x's.
42358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
42458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  std::string response = SpdyUtils::SerializeUncompressedHeaders(headers);
42558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  EXPECT_LT(4096u, response.length());
42658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  stream_->OnDataReceived(response.data(), response.length());
42758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  stream_->OnClose(QUIC_NO_ERROR);
42858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
42958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // Now that the headers have been processed, the callback will return.
43058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  EXPECT_EQ(OK, callback_.WaitForResult());
43158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  ASSERT_TRUE(response_.headers.get());
43258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  EXPECT_EQ(200, response_.headers->response_code());
43358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  EXPECT_TRUE(response_.headers->HasHeaderValue("Content-Type", "text/plain"));
43458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
43558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // There is no body, so this should return immediately.
43658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  EXPECT_EQ(0, stream_->ReadResponseBody(read_buffer_.get(),
43758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)                                         read_buffer_->size(),
43858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)                                         callback_.callback()));
4392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_TRUE(stream_->IsResponseBodyComplete());
4402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_TRUE(AtEof());
4412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
4422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4431320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// Regression test for http://crbug.com/409101
4441320f92c476a1ad9d19dba2a48c72b75566198e9Primiano TucciTEST_P(QuicHttpStreamTest, SessionClosedBeforeSendRequest) {
4451320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  SetRequest("GET", "/", DEFAULT_PRIORITY);
4461320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  Initialize();
4471320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
4481320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  request_.method = "GET";
4491320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  request_.url = GURL("http://www.google.com/");
4501320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
4511320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  EXPECT_EQ(OK, stream_->InitializeStream(&request_, DEFAULT_PRIORITY,
4521320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                                          net_log_, callback_.callback()));
4531320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
4541320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  session_->connection()->CloseConnection(QUIC_NO_ERROR, true);
4551320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
4561320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  EXPECT_EQ(ERR_CONNECTION_CLOSED,
4571320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci            stream_->SendRequest(headers_, &response_,
4581320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                                 callback_.callback()));
4591320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci}
4601320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
4611320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// Regression test for http://crbug.com/409871
4621320f92c476a1ad9d19dba2a48c72b75566198e9Primiano TucciTEST_P(QuicHttpStreamTest, SessionClosedBeforeReadResponseHeaders) {
4631320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  SetRequest("GET", "/", DEFAULT_PRIORITY);
4641320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  AddWrite(ConstructRequestHeadersPacket(1, kFin));
4651320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  Initialize();
4661320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
4671320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  request_.method = "GET";
4681320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  request_.url = GURL("http://www.google.com/");
4691320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
4701320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  EXPECT_EQ(OK, stream_->InitializeStream(&request_, DEFAULT_PRIORITY,
4711320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                                          net_log_, callback_.callback()));
4721320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
4731320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  EXPECT_EQ(OK, stream_->SendRequest(headers_, &response_,
4741320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                                     callback_.callback()));
4751320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
4761320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  session_->connection()->CloseConnection(QUIC_NO_ERROR, true);
4771320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
4781320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  EXPECT_NE(OK, stream_->ReadResponseHeaders(callback_.callback()));
4791320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci}
4801320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
4815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)TEST_P(QuicHttpStreamTest, SendPostRequest) {
4825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  SetRequest("POST", "/", DEFAULT_PRIORITY);
483a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  AddWrite(ConstructRequestHeadersPacket(1, !kFin));
484a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  AddWrite(ConstructDataPacket(2, kIncludeVersion, kFin, 0, kUploadData));
4855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  AddWrite(ConstructAckPacket(3, 3, 1));
4862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  Initialize();
4882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ScopedVector<UploadElementReader> element_readers;
4902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  element_readers.push_back(
4912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      new UploadBytesElementReader(kUploadData, strlen(kUploadData)));
49268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  UploadDataStream upload_data_stream(element_readers.Pass(), 0);
4932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  request_.method = "POST";
4942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  request_.url = GURL("http://www.google.com/");
4952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  request_.upload_data_stream = &upload_data_stream;
4962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ASSERT_EQ(OK, request_.upload_data_stream->Init(CompletionCallback()));
4972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(OK, stream_->InitializeStream(&request_, DEFAULT_PRIORITY,
4992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                          net_log_, callback_.callback()));
5002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(OK, stream_->SendRequest(headers_, &response_,
5012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                     callback_.callback()));
5022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Ack both packets in the request.
5045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  ProcessPacket(ConstructAckPacket(1, 0, 0));
5052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Send the response headers (but not the body).
5075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  SetResponse("200 OK", std::string());
508a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  ProcessPacket(ConstructResponseHeadersPacket(2, !kFin));
5092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Since the headers have already arrived, this should return immediately.
5112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(OK, stream_->ReadResponseHeaders(callback_.callback()));
5127d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  ASSERT_TRUE(response_.headers.get());
5132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(200, response_.headers->response_code());
5142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_TRUE(response_.headers->HasHeaderValue("Content-Type", "text/plain"));
5152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Send the response body.
5172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const char kResponseBody[] = "Hello world!";
518a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  ProcessPacket(ConstructDataPacket(3, false, kFin, 0, kResponseBody));
5192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Since the body has already arrived, this should return immediately.
5202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(static_cast<int>(strlen(kResponseBody)),
5212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            stream_->ReadResponseBody(read_buffer_.get(), read_buffer_->size(),
5222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                      callback_.callback()));
5232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_TRUE(stream_->IsResponseBodyComplete());
5252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_TRUE(AtEof());
5262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
5272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)TEST_P(QuicHttpStreamTest, SendChunkedPostRequest) {
5295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  SetRequest("POST", "/", DEFAULT_PRIORITY);
5302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  size_t chunk_size = strlen(kUploadData);
531a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  AddWrite(ConstructRequestHeadersPacket(1, !kFin));
532a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  AddWrite(ConstructDataPacket(2, kIncludeVersion, !kFin, 0, kUploadData));
533a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  AddWrite(ConstructDataPacket(3, kIncludeVersion, kFin, chunk_size,
534a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                               kUploadData));
5355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  AddWrite(ConstructAckPacket(4, 3, 1));
5362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  Initialize();
5372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  UploadDataStream upload_data_stream(UploadDataStream::CHUNKED, 0);
5392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  upload_data_stream.AppendChunk(kUploadData, chunk_size, false);
5402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  request_.method = "POST";
5422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  request_.url = GURL("http://www.google.com/");
5432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  request_.upload_data_stream = &upload_data_stream;
5442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ASSERT_EQ(OK, request_.upload_data_stream->Init(CompletionCallback()));
5452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ASSERT_EQ(OK, stream_->InitializeStream(&request_, DEFAULT_PRIORITY,
5472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                          net_log_, callback_.callback()));
5482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ASSERT_EQ(ERR_IO_PENDING, stream_->SendRequest(headers_, &response_,
5492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                                 callback_.callback()));
5502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  upload_data_stream.AppendChunk(kUploadData, chunk_size, true);
5522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Ack both packets in the request.
5545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  ProcessPacket(ConstructAckPacket(1, 0, 0));
5552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Send the response headers (but not the body).
5575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  SetResponse("200 OK", std::string());
558a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  ProcessPacket(ConstructResponseHeadersPacket(2, !kFin));
5592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Since the headers have already arrived, this should return immediately.
5612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ASSERT_EQ(OK, stream_->ReadResponseHeaders(callback_.callback()));
5627d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  ASSERT_TRUE(response_.headers.get());
5632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(200, response_.headers->response_code());
5642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_TRUE(response_.headers->HasHeaderValue("Content-Type", "text/plain"));
56503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
56603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  // Send the response body.
56703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  const char kResponseBody[] = "Hello world!";
56803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  ProcessPacket(ConstructDataPacket(3, false, kFin, response_data_.length(),
56903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)                                    kResponseBody));
57003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
57103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  // Since the body has already arrived, this should return immediately.
57203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  ASSERT_EQ(static_cast<int>(strlen(kResponseBody)),
57303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)            stream_->ReadResponseBody(read_buffer_.get(), read_buffer_->size(),
57403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)                                      callback_.callback()));
57503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
57603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  EXPECT_TRUE(stream_->IsResponseBodyComplete());
57703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  EXPECT_TRUE(AtEof());
57803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)}
57903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
58003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)TEST_P(QuicHttpStreamTest, SendChunkedPostRequestWithFinalEmptyDataPacket) {
58103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  SetRequest("POST", "/", DEFAULT_PRIORITY);
58203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  size_t chunk_size = strlen(kUploadData);
58303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  AddWrite(ConstructRequestHeadersPacket(1, !kFin));
58403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  AddWrite(ConstructDataPacket(2, kIncludeVersion, !kFin, 0, kUploadData));
58503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  AddWrite(ConstructDataPacket(3, kIncludeVersion, kFin, chunk_size, ""));
58603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  AddWrite(ConstructAckPacket(4, 3, 1));
58703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  Initialize();
58803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
58903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  UploadDataStream upload_data_stream(UploadDataStream::CHUNKED, 0);
59003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  upload_data_stream.AppendChunk(kUploadData, chunk_size, false);
59103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
59203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  request_.method = "POST";
59303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  request_.url = GURL("http://www.google.com/");
59403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  request_.upload_data_stream = &upload_data_stream;
59503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  ASSERT_EQ(OK, request_.upload_data_stream->Init(CompletionCallback()));
59603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
59703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  ASSERT_EQ(OK, stream_->InitializeStream(&request_, DEFAULT_PRIORITY,
59803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)                                          net_log_, callback_.callback()));
59903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  ASSERT_EQ(ERR_IO_PENDING, stream_->SendRequest(headers_, &response_,
60003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)                                                 callback_.callback()));
60103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
60203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  upload_data_stream.AppendChunk(NULL, 0, true);
60303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
60403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  ProcessPacket(ConstructAckPacket(1, 0, 0));
60503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
60603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  // Send the response headers (but not the body).
60703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  SetResponse("200 OK", std::string());
60803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  ProcessPacket(ConstructResponseHeadersPacket(2, !kFin));
60903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
61003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  // Since the headers have already arrived, this should return immediately.
61103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  ASSERT_EQ(OK, stream_->ReadResponseHeaders(callback_.callback()));
61203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  ASSERT_TRUE(response_.headers.get());
61303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  EXPECT_EQ(200, response_.headers->response_code());
61403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  EXPECT_TRUE(response_.headers->HasHeaderValue("Content-Type", "text/plain"));
61503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
61603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  // Send the response body.
61703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  const char kResponseBody[] = "Hello world!";
61803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  ProcessPacket(ConstructDataPacket(3, false, kFin, response_data_.length(),
61903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)                                    kResponseBody));
62003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
62103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  // Since the body has already arrived, this should return immediately.
62203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  ASSERT_EQ(static_cast<int>(strlen(kResponseBody)),
62303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)            stream_->ReadResponseBody(read_buffer_.get(), read_buffer_->size(),
62403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)                                      callback_.callback()));
62503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
62603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  EXPECT_TRUE(stream_->IsResponseBodyComplete());
62703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  EXPECT_TRUE(AtEof());
62803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)}
62903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
63003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)TEST_P(QuicHttpStreamTest, SendChunkedPostRequestWithOneEmptyDataPacket) {
63103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  SetRequest("POST", "/", DEFAULT_PRIORITY);
63203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  AddWrite(ConstructRequestHeadersPacket(1, !kFin));
63303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  AddWrite(ConstructDataPacket(2, kIncludeVersion, kFin, 0, ""));
63403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  AddWrite(ConstructAckPacket(3, 3, 1));
63503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  Initialize();
63603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
63703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  UploadDataStream upload_data_stream(UploadDataStream::CHUNKED, 0);
63803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
63903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  request_.method = "POST";
64003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  request_.url = GURL("http://www.google.com/");
64103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  request_.upload_data_stream = &upload_data_stream;
64203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  ASSERT_EQ(OK, request_.upload_data_stream->Init(CompletionCallback()));
64303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
64403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  ASSERT_EQ(OK, stream_->InitializeStream(&request_, DEFAULT_PRIORITY,
64503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)                                          net_log_, callback_.callback()));
64603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  ASSERT_EQ(ERR_IO_PENDING, stream_->SendRequest(headers_, &response_,
64703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)                                                 callback_.callback()));
64803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
64903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  upload_data_stream.AppendChunk(NULL, 0, true);
65003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
65103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  ProcessPacket(ConstructAckPacket(1, 0, 0));
65203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
65303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  // Send the response headers (but not the body).
65403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  SetResponse("200 OK", std::string());
65503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  ProcessPacket(ConstructResponseHeadersPacket(2, !kFin));
65603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
65703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  // Since the headers have already arrived, this should return immediately.
65803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  ASSERT_EQ(OK, stream_->ReadResponseHeaders(callback_.callback()));
65903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  ASSERT_TRUE(response_.headers.get());
66003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  EXPECT_EQ(200, response_.headers->response_code());
66103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  EXPECT_TRUE(response_.headers->HasHeaderValue("Content-Type", "text/plain"));
6622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Send the response body.
6642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const char kResponseBody[] = "Hello world!";
6655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  ProcessPacket(ConstructDataPacket(3, false, kFin, response_data_.length(),
6665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                    kResponseBody));
6672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Since the body has already arrived, this should return immediately.
6692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ASSERT_EQ(static_cast<int>(strlen(kResponseBody)),
6702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            stream_->ReadResponseBody(read_buffer_.get(), read_buffer_->size(),
6712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                      callback_.callback()));
6722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_TRUE(stream_->IsResponseBodyComplete());
6742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_TRUE(AtEof());
6752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
6762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)TEST_P(QuicHttpStreamTest, DestroyedEarly) {
6785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  SetRequest("GET", "/", DEFAULT_PRIORITY);
679a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  AddWrite(ConstructRequestHeadersPacket(1, kFin));
6805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  AddWrite(ConstructAckAndRstStreamPacket(2));
6812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  use_closing_stream_ = true;
6822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  Initialize();
6832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  request_.method = "GET";
6852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  request_.url = GURL("http://www.google.com/");
6862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(OK, stream_->InitializeStream(&request_, DEFAULT_PRIORITY,
6882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                          net_log_, callback_.callback()));
6892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(OK, stream_->SendRequest(headers_, &response_,
690d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)                                     callback_.callback()));
691d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
692d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  // Ack the request.
6935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  ProcessPacket(ConstructAckPacket(1, 0, 0));
694d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  EXPECT_EQ(ERR_IO_PENDING,
695d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)            stream_->ReadResponseHeaders(callback_.callback()));
696d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
697d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  // Send the response with a body.
6985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  SetResponse("404 OK", "hello world!");
699d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  // In the course of processing this packet, the QuicHttpStream close itself.
700a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  ProcessPacket(ConstructResponseHeadersPacket(2, kFin));
701d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
702d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  EXPECT_TRUE(AtEof());
703d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)}
704d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
7055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)TEST_P(QuicHttpStreamTest, Priority) {
7065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  SetRequest("GET", "/", MEDIUM);
707a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  AddWrite(ConstructRequestHeadersPacket(1, kFin));
7085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  AddWrite(ConstructAckAndRstStreamPacket(2));
709d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  use_closing_stream_ = true;
710d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  Initialize();
711d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
712d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  request_.method = "GET";
713d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  request_.url = GURL("http://www.google.com/");
714d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
715d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  EXPECT_EQ(OK, stream_->InitializeStream(&request_, MEDIUM,
716d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)                                          net_log_, callback_.callback()));
717d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
718d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  // Check that priority is highest.
719d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  QuicReliableClientStream* reliable_stream =
720d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      QuicHttpStreamPeer::GetQuicReliableClientStream(stream_.get());
721d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  DCHECK(reliable_stream);
7225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  DCHECK_EQ(QuicWriteBlockedList::kHighestPriority,
723d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)            reliable_stream->EffectivePriority());
724d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
725d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  EXPECT_EQ(OK, stream_->SendRequest(headers_, &response_,
726d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)                                     callback_.callback()));
7272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
728d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  // Check that priority has now dropped back to MEDIUM.
729d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  DCHECK_EQ(MEDIUM, ConvertQuicPriorityToRequestPriority(
730d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      reliable_stream->EffectivePriority()));
731d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
7322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Ack the request.
7335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  ProcessPacket(ConstructAckPacket(1, 0, 0));
7342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(ERR_IO_PENDING,
7352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            stream_->ReadResponseHeaders(callback_.callback()));
7362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
7372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Send the response with a body.
7385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  SetResponse("404 OK", "hello world!");
7392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // In the course of processing this packet, the QuicHttpStream close itself.
740a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  ProcessPacket(ConstructResponseHeadersPacket(2, kFin));
7412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
7422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_TRUE(AtEof());
7432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
7442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
74568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)// Regression test for http://crbug.com/294870
7465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)TEST_P(QuicHttpStreamTest, CheckPriorityWithNoDelegate) {
7475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  SetRequest("GET", "/", MEDIUM);
74868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  use_closing_stream_ = true;
7495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
7505c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  AddWrite(ConstructRstStreamPacket(1));
7515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
75268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  Initialize();
75368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
75468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  request_.method = "GET";
75568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  request_.url = GURL("http://www.google.com/");
75668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
75768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  EXPECT_EQ(OK, stream_->InitializeStream(&request_, MEDIUM,
75868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)                                          net_log_, callback_.callback()));
75968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
76068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  // Check that priority is highest.
76168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  QuicReliableClientStream* reliable_stream =
76268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      QuicHttpStreamPeer::GetQuicReliableClientStream(stream_.get());
76368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  DCHECK(reliable_stream);
76468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  QuicReliableClientStream::Delegate* delegate = reliable_stream->GetDelegate();
76568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  DCHECK(delegate);
7665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  DCHECK_EQ(QuicWriteBlockedList::kHighestPriority,
76768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)            reliable_stream->EffectivePriority());
76868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
76968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  // Set Delegate to NULL and make sure EffectivePriority returns highest
77068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  // priority.
77168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  reliable_stream->SetDelegate(NULL);
7725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  DCHECK_EQ(QuicWriteBlockedList::kHighestPriority,
77368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)            reliable_stream->EffectivePriority());
77468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  reliable_stream->SetDelegate(delegate);
77568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)}
77668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
7772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}  // namespace test
7782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}  // namespace net
779