// Copyright 2016 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "net/quic/bidirectional_stream_quic_impl.h"

#include <memory>
#include <utility>

#include "base/memory/ptr_util.h"
#include "base/memory/raw_ptr.h"
#include "base/run_loop.h"
#include "base/strings/strcat.h"
#include "base/strings/string_number_conversions.h"
#include "base/task/single_thread_task_runner.h"
#include "base/time/default_tick_clock.h"
#include "base/time/time.h"
#include "base/timer/timer.h"
#include "net/base/completion_once_callback.h"
#include "net/base/connection_endpoint_metadata.h"
#include "net/base/ip_address.h"
#include "net/base/load_timing_info.h"
#include "net/base/load_timing_info_test_util.h"
#include "net/base/net_errors.h"
#include "net/base/network_anonymization_key.h"
#include "net/base/privacy_mode.h"
#include "net/base/proxy_chain.h"
#include "net/base/session_usage.h"
#include "net/dns/public/host_resolver_results.h"
#include "net/dns/public/secure_dns_policy.h"
#include "net/http/bidirectional_stream_request_info.h"
#include "net/http/transport_security_state.h"
#include "net/log/net_log.h"
#include "net/log/net_log_event_type.h"
#include "net/log/test_net_log.h"
#include "net/log/test_net_log_util.h"
#include "net/quic/address_utils.h"
#include "net/quic/mock_crypto_client_stream_factory.h"
#include "net/quic/quic_chromium_alarm_factory.h"
#include "net/quic/quic_chromium_connection_helper.h"
#include "net/quic/quic_chromium_packet_reader.h"
#include "net/quic/quic_chromium_packet_writer.h"
#include "net/quic/quic_context.h"
#include "net/quic/quic_crypto_client_config_handle.h"
#include "net/quic/quic_http_utils.h"
#include "net/quic/quic_server_info.h"
#include "net/quic/quic_session_alias_key.h"
#include "net/quic/quic_session_key.h"
#include "net/quic/quic_session_pool.h"
#include "net/quic/quic_test_packet_maker.h"
#include "net/quic/quic_test_packet_printer.h"
#include "net/quic/test_quic_crypto_client_config_handle.h"
#include "net/quic/test_task_runner.h"
#include "net/socket/socket_test_util.h"
#include "net/ssl/ssl_config_service_defaults.h"
#include "net/test/gtest_util.h"
#include "net/test/test_with_task_environment.h"
#include "net/third_party/quiche/src/quiche/common/http/http_header_block.h"
#include "net/third_party/quiche/src/quiche/common/quiche_text_utils.h"
#include "net/third_party/quiche/src/quiche/quic/core/crypto/crypto_protocol.h"
#include "net/third_party/quiche/src/quiche/quic/core/crypto/quic_decrypter.h"
#include "net/third_party/quiche/src/quiche/quic/core/crypto/quic_encrypter.h"
#include "net/third_party/quiche/src/quiche/quic/core/http/spdy_utils.h"
#include "net/third_party/quiche/src/quiche/quic/core/quic_connection.h"
#include "net/third_party/quiche/src/quiche/quic/test_tools/crypto_test_utils.h"
#include "net/third_party/quiche/src/quiche/quic/test_tools/mock_clock.h"
#include "net/third_party/quiche/src/quiche/quic/test_tools/mock_connection_id_generator.h"
#include "net/third_party/quiche/src/quiche/quic/test_tools/mock_random.h"
#include "net/third_party/quiche/src/quiche/quic/test_tools/qpack/qpack_test_utils.h"
#include "net/third_party/quiche/src/quiche/quic/test_tools/quic_connection_peer.h"
#include "net/third_party/quiche/src/quiche/quic/test_tools/quic_session_peer.h"
#include "net/third_party/quiche/src/quiche/quic/test_tools/quic_spdy_session_peer.h"
#include "net/third_party/quiche/src/quiche/quic/test_tools/quic_test_utils.h"
#include "net/traffic_annotation/network_traffic_annotation_test_helper.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "url/scheme_host_port.h"
#include "url/url_constants.h"

namespace net::test {

namespace {

const char kUploadData[] = "Really nifty data!";
const char kDefaultServerHostName[] = "www.google.com";
const uint16_t kDefaultServerPort = 80;
// Size of the buffer to be allocated for each read.
const size_t kReadBufferSize = 4096;

enum DelegateMethod {
  kOnStreamReady,
  kOnHeadersReceived,
  kOnTrailersReceived,
  kOnDataRead,
  kOnDataSent,
  kOnFailed
};

class TestDelegateBase : public BidirectionalStreamImpl::Delegate {
 public:
  TestDelegateBase(IOBuffer* read_buf, int read_buf_len)
      : TestDelegateBase(read_buf,
                         read_buf_len,
                         std::make_unique<base::OneShotTimer>()) {}

  TestDelegateBase(IOBuffer* read_buf,
                   int read_buf_len,
                   std::unique_ptr<base::OneShotTimer> timer)
      : read_buf_(read_buf),
        read_buf_len_(read_buf_len),
        timer_(std::move(timer)) {
    loop_ = std::make_unique<base::RunLoop>();
  }

  TestDelegateBase(const TestDelegateBase&) = delete;
  TestDelegateBase& operator=(const TestDelegateBase&) = delete;

  ~TestDelegateBase() override = default;

  void OnStreamReady(bool request_headers_sent) override {
    CHECK(!is_ready_);
    CHECK(!on_failed_called_);
    EXPECT_EQ(send_request_headers_automatically_, request_headers_sent);
    CHECK(!not_expect_callback_);
    is_ready_ = true;
    loop_->Quit();
  }

  void OnHeadersReceived(
      const quiche::HttpHeaderBlock& response_headers) override {
    CHECK(!on_failed_called_);
    CHECK(!not_expect_callback_);

    response_headers_ = response_headers.Clone();
    loop_->Quit();
  }

  void OnDataRead(int bytes_read) override {
    CHECK(!on_failed_called_);
    CHECK(!not_expect_callback_);
    CHECK(!callback_.is_null());

    // If read EOF, make sure this callback is after trailers callback.
    if (bytes_read == 0) {
      EXPECT_TRUE(!trailers_expected_ || trailers_received_);
    }
    ++on_data_read_count_;
    CHECK_GE(bytes_read, OK);
    data_received_.append(read_buf_->data(), bytes_read);
    std::move(callback_).Run(bytes_read);
  }

  void OnDataSent() override {
    CHECK(!on_failed_called_);
    CHECK(!not_expect_callback_);

    ++on_data_sent_count_;
    loop_->Quit();
  }

  void OnTrailersReceived(const quiche::HttpHeaderBlock& trailers) override {
    CHECK(!on_failed_called_);
    CHECK(!not_expect_callback_);

    trailers_received_ = true;
    trailers_ = trailers.Clone();
    loop_->Quit();
  }

  void OnFailed(int error) override {
    CHECK(!on_failed_called_);
    CHECK(!not_expect_callback_);
    CHECK_EQ(OK, error_);
    CHECK_NE(OK, error);

    on_failed_called_ = true;
    error_ = error;
    loop_->Quit();
  }

  void Start(const BidirectionalStreamRequestInfo* request_info,
             const NetLogWithSource& net_log,
             std::unique_ptr<QuicChromiumClientSession::Handle> session) {
    not_expect_callback_ = true;
    stream_ = std::make_unique<BidirectionalStreamQuicImpl>(std::move(session));
    stream_->Start(request_info, net_log, send_request_headers_automatically_,
                   this, nullptr, TRAFFIC_ANNOTATION_FOR_TESTS);
    not_expect_callback_ = false;
  }

  void SendRequestHeaders() {
    not_expect_callback_ = true;
    stream_->SendRequestHeaders();
    not_expect_callback_ = false;
  }

  void SendData(const scoped_refptr<IOBuffer>& data,
                int length,
                bool end_of_stream) {
    SendvData({data}, {length}, end_of_stream);
  }

  void SendvData(const std::vector<scoped_refptr<IOBuffer>>& data,
                 const std::vector<int>& lengths,
                 bool end_of_stream) {
    not_expect_callback_ = true;
    stream_->SendvData(data, lengths, end_of_stream);
    not_expect_callback_ = false;
  }

  // Waits until next Delegate callback.
  void WaitUntilNextCallback(DelegateMethod method) {
    ASSERT_FALSE(on_failed_called_);
    bool is_ready = is_ready_;
    bool headers_received = !response_headers_.empty();
    bool trailers_received = trailers_received_;
    int on_data_read_count = on_data_read_count_;
    int on_data_sent_count = on_data_sent_count_;

    loop_->Run();
    loop_ = std::make_unique<base::RunLoop>();

    EXPECT_EQ(method == kOnFailed, on_failed_called_);
    EXPECT_EQ(is_ready || (method == kOnStreamReady), is_ready_);
    EXPECT_EQ(headers_received || (method == kOnHeadersReceived),
              !response_headers_.empty());
    EXPECT_EQ(trailers_received || (method == kOnTrailersReceived),
              trailers_received_);
    EXPECT_EQ(on_data_read_count + (method == kOnDataRead ? 1 : 0),
              on_data_read_count_);
    EXPECT_EQ(on_data_sent_count + (method == kOnDataSent ? 1 : 0),
              on_data_sent_count_);
  }

  // Calls ReadData on the |stream_| and updates |data_received_|.
  int ReadData(CompletionOnceCallback callback) {
    not_expect_callback_ = true;
    int rv = stream_->ReadData(read_buf_.get(), read_buf_len_);
    not_expect_callback_ = false;
    if (rv > 0) {
      data_received_.append(read_buf_->data(), rv);
    }
    if (rv == ERR_IO_PENDING) {
      callback_ = std::move(callback);
    }
    return rv;
  }

  NextProto GetProtocol() const {
    if (stream_) {
      return stream_->GetProtocol();
    }
    return next_proto_;
  }

  int64_t GetTotalReceivedBytes() const {
    if (stream_) {
      return stream_->GetTotalReceivedBytes();
    }
    return received_bytes_;
  }

  int64_t GetTotalSentBytes() const {
    if (stream_) {
      return stream_->GetTotalSentBytes();
    }
    return sent_bytes_;
  }

  bool GetLoadTimingInfo(LoadTimingInfo* load_timing_info) {
    if (stream_) {
      return stream_->GetLoadTimingInfo(load_timing_info);
    }
    *load_timing_info = load_timing_info_;
    return has_load_timing_info_;
  }

  void DoNotSendRequestHeadersAutomatically() {
    send_request_headers_automatically_ = false;
  }

  // Deletes |stream_|.
  void DeleteStream() {
    next_proto_ = stream_->GetProtocol();
    received_bytes_ = stream_->GetTotalReceivedBytes();
    sent_bytes_ = stream_->GetTotalSentBytes();
    has_load_timing_info_ = stream_->GetLoadTimingInfo(&load_timing_info_);
    stream_.reset();
  }

  void set_trailers_expected(bool trailers_expected) {
    trailers_expected_ = trailers_expected;
  }
  // Const getters for internal states.
  const std::string& data_received() const { return data_received_; }
  int error() const { return error_; }
  const quiche::HttpHeaderBlock& response_headers() const {
    return response_headers_;
  }
  const quiche::HttpHeaderBlock& trailers() const { return trailers_; }
  int on_data_read_count() const { return on_data_read_count_; }
  int on_data_sent_count() const { return on_data_sent_count_; }
  bool on_failed_called() const { return on_failed_called_; }
  bool is_ready() const { return is_ready_; }

 protected:
  // Quits |loop_|.
  void QuitLoop() { loop_->Quit(); }

 private:
  std::unique_ptr<BidirectionalStreamQuicImpl> stream_;
  scoped_refptr<IOBuffer> read_buf_;
  int read_buf_len_;
  std::unique_ptr<base::OneShotTimer> timer_;
  std::string data_received_;
  std::unique_ptr<base::RunLoop> loop_;
  quiche::HttpHeaderBlock response_headers_;
  quiche::HttpHeaderBlock trailers_;
  NextProto next_proto_ = NextProto::kProtoUnknown;
  int64_t received_bytes_ = 0;
  int64_t sent_bytes_ = 0;
  bool has_load_timing_info_ = false;
  LoadTimingInfo load_timing_info_;
  int error_ = OK;
  int on_data_read_count_ = 0;
  int on_data_sent_count_ = 0;
  // This is to ensure that delegate callback is not invoked synchronously when
  // calling into |stream_|.
  bool not_expect_callback_ = false;
  bool on_failed_called_ = false;
  CompletionOnceCallback callback_;
  bool send_request_headers_automatically_ = true;
  bool is_ready_ = false;
  bool trailers_expected_ = false;
  bool trailers_received_ = false;
};

// A delegate that deletes the stream in a particular callback.
class DeleteStreamDelegate : public TestDelegateBase {
 public:
  // Specifies in which callback the stream can be deleted.
  enum Phase {
    ON_STREAM_READY,
    ON_HEADERS_RECEIVED,
    ON_DATA_READ,
    ON_TRAILERS_RECEIVED,
    ON_FAILED,
  };

  DeleteStreamDelegate(IOBuffer* buf, int buf_len, Phase phase)
      : TestDelegateBase(buf, buf_len), phase_(phase) {}

  DeleteStreamDelegate(const DeleteStreamDelegate&) = delete;
  DeleteStreamDelegate& operator=(const DeleteStreamDelegate&) = delete;

  ~DeleteStreamDelegate() override = default;

  void OnStreamReady(bool request_headers_sent) override {
    TestDelegateBase::OnStreamReady(request_headers_sent);
    if (phase_ == ON_STREAM_READY) {
      DeleteStream();
    }
  }

  void OnHeadersReceived(
      const quiche::HttpHeaderBlock& response_headers) override {
    // Make a copy of |response_headers| before the stream is deleted, since
    // the headers are owned by the stream.
    quiche::HttpHeaderBlock headers_copy = response_headers.Clone();
    if (phase_ == ON_HEADERS_RECEIVED) {
      DeleteStream();
    }
    TestDelegateBase::OnHeadersReceived(headers_copy);
  }

  void OnDataSent() override { NOTREACHED(); }

  void OnDataRead(int bytes_read) override {
    DCHECK_NE(ON_HEADERS_RECEIVED, phase_);
    if (phase_ == ON_DATA_READ) {
      DeleteStream();
    }
    TestDelegateBase::OnDataRead(bytes_read);
  }

  void OnTrailersReceived(const quiche::HttpHeaderBlock& trailers) override {
    DCHECK_NE(ON_HEADERS_RECEIVED, phase_);
    DCHECK_NE(ON_DATA_READ, phase_);
    // Make a copy of |response_headers| before the stream is deleted, since
    // the headers are owned by the stream.
    quiche::HttpHeaderBlock trailers_copy = trailers.Clone();
    if (phase_ == ON_TRAILERS_RECEIVED) {
      DeleteStream();
    }
    TestDelegateBase::OnTrailersReceived(trailers_copy);
  }

  void OnFailed(int error) override {
    DCHECK_EQ(ON_FAILED, phase_);
    DeleteStream();
    TestDelegateBase::OnFailed(error);
  }

 private:
  // Indicates in which callback the delegate should cancel or delete the
  // stream.
  Phase phase_;
};

}  // namespace

class BidirectionalStreamQuicImplTest
    : public ::testing::TestWithParam<quic::ParsedQuicVersion>,
      public WithTaskEnvironment {
 protected:
  static const bool kFin = true;

  // Holds a packet to be written to the wire, and the IO mode that should
  // be used by the mock socket when performing the write.
  struct PacketToWrite {
    PacketToWrite(IoMode mode, quic::QuicReceivedPacket* packet)
        : mode(mode), packet(packet) {}
    PacketToWrite(IoMode mode, int rv) : mode(mode), packet(nullptr), rv(rv) {}
    IoMode mode;
    raw_ptr<quic::QuicReceivedPacket, DanglingUntriaged> packet;
    int rv;
  };

  BidirectionalStreamQuicImplTest()
      : version_(GetParam()),
        crypto_config_(
            quic::test::crypto_test_utils::ProofVerifierForTesting()),
        read_buffer_(base::MakeRefCounted<IOBufferWithSize>(4096)),
        connection_id_(quic::test::TestConnectionId(2)),
        stream_id_(GetNthClientInitiatedBidirectionalStreamId(0)),
        client_maker_(version_,
                      connection_id_,
                      &clock_,
                      kDefaultServerHostName,
                      quic::Perspective::IS_CLIENT),
        server_maker_(version_,
                      connection_id_,
                      &clock_,
                      kDefaultServerHostName,
                      quic::Perspective::IS_SERVER,
                      false),
        printer_(version_),
        destination_(url::kHttpsScheme,
                     kDefaultServerHostName,
                     kDefaultServerPort) {
    quic::QuicEnableVersion(version_);
    FLAGS_quic_enable_http3_grease_randomness = false;
    IPAddress ip(192, 0, 2, 33);
    peer_addr_ = IPEndPoint(ip, 443);
    self_addr_ = IPEndPoint(ip, 8435);
    clock_.AdvanceTime(quic::QuicTime::Delta::FromMilliseconds(20));
  }

  ~BidirectionalStreamQuicImplTest() override {
    if (session_) {
      session_->CloseSessionOnError(
          ERR_ABORTED, quic::QUIC_INTERNAL_ERROR,
          quic::ConnectionCloseBehavior::SILENT_CLOSE);
    }
    for (auto& write : writes_) {
      delete write.packet;
    }
  }

  void TearDown() override {
    if (socket_data_) {
      EXPECT_TRUE(socket_data_->AllReadDataConsumed());
      EXPECT_TRUE(socket_data_->AllWriteDataConsumed());
    }
  }

  // Adds a packet to the list of expected writes.
  void AddWrite(std::unique_ptr<quic::QuicReceivedPacket> packet) {
    writes_.emplace_back(SYNCHRONOUS, packet.release());
  }

  // Adds a write error to the list of expected writes.
  void AddWriteError(IoMode mode, int rv) { writes_.emplace_back(mode, rv); }

  void ProcessPacket(std::unique_ptr<quic::QuicReceivedPacket> packet) {
    connection_->ProcessUdpPacket(ToQuicSocketAddress(self_addr_),
                                  ToQuicSocketAddress(peer_addr_), *packet);
  }

  // Configures the test fixture to use the list of expected writes.
  void Initialize() {
    crypto_client_stream_factory_.set_handshake_mode(
        MockCryptoClientStream::ZERO_RTT);
    mock_writes_.resize(writes_.size());
    for (size_t i = 0; i < writes_.size(); i++) {
      if (writes_[i].packet == nullptr) {
        mock_writes_[i] = MockWrite(writes_[i].mode, writes_[i].rv, i);
      } else {
        mock_writes_[i] =
            MockWrite(writes_[i].mode, writes_[i].packet->AsStringPiece());
      }
    }

    socket_data_ = std::make_unique<StaticSocketDataProvider>(
        base::span<MockRead>(), mock_writes_);
    socket_data_->set_printer(&printer_);

    auto socket = std::make_unique<MockUDPClientSocket>(socket_data_.get(),
                                                        NetLog::Get());
    socket->Connect(peer_addr_);
    runner_ = base::MakeRefCounted<TestTaskRunner>(&clock_);
    helper_ = std::make_unique<QuicChromiumConnectionHelper>(
        &clock_, &random_generator_);
    alarm_factory_ =
        std::make_unique<QuicChromiumAlarmFactory>(runner_.get(), &clock_);
    connection_ = new quic::QuicConnection(
        connection_id_, quic::QuicSocketAddress(),
        ToQuicSocketAddress(peer_addr_), helper_.get(), alarm_factory_.get(),
        new QuicChromiumPacketWriter(socket.get(), runner_.get()),
        true /* owns_writer */, quic::Perspective::IS_CLIENT,
        quic::test::SupportedVersions(version_), connection_id_generator_);
    if (connection_->version().KnowsWhichDecrypterToUse()) {
      connection_->InstallDecrypter(
          quic::ENCRYPTION_FORWARD_SECURE,
          std::make_unique<quic::test::StrictTaggingDecrypter>(
              quic::ENCRYPTION_FORWARD_SECURE));
    }
    base::TimeTicks dns_end = base::TimeTicks::Now();
    base::TimeTicks dns_start = dns_end - base::Milliseconds(1);

    session_ = std::make_unique<QuicChromiumClientSession>(
        connection_, std::move(socket),
        /*stream_factory=*/nullptr, &crypto_client_stream_factory_, &clock_,
        &transport_security_state_, &ssl_config_service_,
        base::WrapUnique(static_cast<QuicServerInfo*>(nullptr)),
        QuicSessionAliasKey(
            url::SchemeHostPort(),
            QuicSessionKey(
                kDefaultServerHostName, kDefaultServerPort,
                PRIVACY_MODE_DISABLED, ProxyChain::Direct(),
                SessionUsage::kDestination, SocketTag(),
                NetworkAnonymizationKey(), SecureDnsPolicy::kAllow,
                /*require_dns_https_alpn=*/false,
                /*disable_cert_verification_network_fetches=*/false)),
        /*require_confirmation=*/false,
        /*migrate_session_early_v2=*/false,
        /*migrate_session_on_network_change_v2=*/false,
        /*default_network=*/handles::kInvalidNetworkHandle,
        quic::QuicTime::Delta::FromMilliseconds(
            kDefaultRetransmittableOnWireTimeout.InMilliseconds()),
        /*migrate_idle_session=*/false, /*allow_port_migration=*/false,
        kDefaultIdleSessionMigrationPeriod, /*multi_port_probing_interval=*/0,
        kMaxTimeOnNonDefaultNetwork,
        kMaxMigrationsToNonDefaultNetworkOnWriteError,
        kMaxMigrationsToNonDefaultNetworkOnPathDegrading,
        kQuicYieldAfterPacketsRead,
        quic::QuicTime::Delta::FromMilliseconds(
            kQuicYieldAfterDurationMilliseconds),
        /*cert_verify_flags=*/0, quic::test::DefaultQuicConfig(),
        std::make_unique<TestQuicCryptoClientConfigHandle>(&crypto_config_),
        "CONNECTION_UNKNOWN", dns_start, dns_end,
        base::DefaultTickClock::GetInstance(),
        base::SingleThreadTaskRunner::GetCurrentDefault().get(),
        /*socket_performance_watcher=*/nullptr, ConnectionEndpointMetadata(),
        /*enable_origin_frame=*/true, /*server_preferred_address=*/true,
        MultiplexedSessionCreationInitiator::kUnknown,
        NetLogWithSource::Make(NetLogSourceType::NONE));
    session_->Initialize();

    // Blackhole QPACK decoder stream instead of constructing mock writes.
    session_->qpack_decoder()->set_qpack_stream_sender_delegate(
        &noop_qpack_stream_sender_delegate_);

    TestCompletionCallback callback;
    session_->CryptoConnect(callback.callback());
    EXPECT_TRUE(session_->IsEncryptionEstablished());
  }

  void ConfirmHandshake() {
    crypto_client_stream_factory_.last_stream()
        ->NotifySessionOneRttKeyAvailable();
  }

  void SetRequest(const std::string& method,
                  const std::string& path,
                  RequestPriority priority) {
    request_headers_ = client_maker_.GetRequestHeaders(method, "http", path);
  }

  quiche::HttpHeaderBlock ConstructResponseHeaders(
      const std::string& response_code) {
    return server_maker_.GetResponseHeaders(response_code);
  }

  std::unique_ptr<quic::QuicReceivedPacket> ConstructServerDataPacket(
      uint64_t packet_number,
      bool fin,
      std::string_view data) {
    std::unique_ptr<quic::QuicReceivedPacket> packet(
        server_maker_.Packet(packet_number)
            .AddStreamFrame(stream_id_, fin, data)
            .Build());
    DVLOG(2) << "packet(" << packet_number << "): " << std::endl
             << quiche::QuicheTextUtils::HexDump(packet->AsStringPiece());
    return packet;
  }

  std::unique_ptr<quic::QuicReceivedPacket> ConstructClientDataPacket(
      bool fin,
      std::string_view data) {
    return client_maker_.Packet(++packet_number_)
        .AddStreamFrame(stream_id_, fin, data)
        .Build();
  }

  std::unique_ptr<quic::QuicReceivedPacket> ConstructRequestHeadersPacket(
      bool fin,
      RequestPriority request_priority,
      size_t* spdy_headers_frame_length) {
    return ConstructRequestHeadersPacketInner(stream_id_, fin, request_priority,
                                              spdy_headers_frame_length);
  }

  std::unique_ptr<quic::QuicReceivedPacket> ConstructRequestHeadersPacketInner(
      quic::QuicStreamId stream_id,
      bool fin,
      RequestPriority request_priority,
      size_t* spdy_headers_frame_length) {
    spdy::SpdyPriority priority =
        ConvertRequestPriorityToQuicPriority(request_priority);
    std::unique_ptr<quic::QuicReceivedPacket> packet(
        client_maker_.MakeRequestHeadersPacket(
            ++packet_number_, stream_id, fin, priority,
            std::move(request_headers_), spdy_headers_frame_length));
    DVLOG(2) << "packet(" << packet_number_ << "): " << std::endl
             << quiche::QuicheTextUtils::HexDump(packet->AsStringPiece());
    return packet;
  }

  std::unique_ptr<quic::QuicReceivedPacket>
  ConstructRequestHeadersAndMultipleDataFramesPacket(
      bool fin,
      RequestPriority request_priority,
      size_t* spdy_headers_frame_length,
      const std::vector<std::string>& data) {
    spdy::SpdyPriority priority =
        ConvertRequestPriorityToQuicPriority(request_priority);
    std::unique_ptr<quic::QuicReceivedPacket> packet(
        client_maker_.MakeRequestHeadersAndMultipleDataFramesPacket(
            ++packet_number_, stream_id_, fin, priority,
            std::move(request_headers_), spdy_headers_frame_length, data));
    DVLOG(2) << "packet(" << packet_number_ << "): " << std::endl
             << quiche::QuicheTextUtils::HexDump(packet->AsStringPiece());
    return packet;
  }

  std::unique_ptr<quic::QuicReceivedPacket> ConstructResponseHeadersPacket(
      uint64_t packet_number,
      bool fin,
      quiche::HttpHeaderBlock response_headers,
      size_t* spdy_headers_frame_length) {
    return ConstructResponseHeadersPacketInner(packet_number, stream_id_, fin,
                                               std::move(response_headers),
                                               spdy_headers_frame_length);
  }

  std::unique_ptr<quic::QuicReceivedPacket> ConstructResponseHeadersPacketInner(
      uint64_t packet_number,
      quic::QuicStreamId stream_id,
      bool fin,
      quiche::HttpHeaderBlock response_headers,
      size_t* spdy_headers_frame_length) {
    return server_maker_.MakeResponseHeadersPacket(
        packet_number, stream_id, fin, std::move(response_headers),
        spdy_headers_frame_length);
  }

  std::unique_ptr<quic::QuicReceivedPacket> ConstructResponseTrailersPacket(
      uint64_t packet_number,
      bool fin,
      quiche::HttpHeaderBlock trailers,
      size_t* spdy_headers_frame_length) {
    return server_maker_.MakeResponseHeadersPacket(packet_number, stream_id_,
                                                   fin, std::move(trailers),
                                                   spdy_headers_frame_length);
  }

  std::unique_ptr<quic::QuicReceivedPacket> ConstructClientRstStreamPacket() {
    return ConstructRstStreamCancelledPacket(++packet_number_, &client_maker_);
  }

  std::unique_ptr<quic::QuicReceivedPacket> ConstructServerRstStreamPacket(
      uint64_t packet_number) {
    return ConstructRstStreamCancelledPacket(packet_number, &server_maker_);
  }

  std::unique_ptr<quic::QuicReceivedPacket>
  ConstructClientEarlyRstStreamPacket() {
    return ConstructRstStreamCancelledPacket(++packet_number_, &client_maker_);
  }

  std::unique_ptr<quic::QuicReceivedPacket> ConstructRstStreamCancelledPacket(
      uint64_t packet_number,
      QuicTestPacketMaker* maker) {
    std::unique_ptr<quic::QuicReceivedPacket> packet(
        client_maker_.Packet(packet_number)
            .AddStopSendingFrame(stream_id_, quic::QUIC_STREAM_CANCELLED)
            .AddRstStreamFrame(stream_id_, quic::QUIC_STREAM_CANCELLED)
            .Build());
    DVLOG(2) << "packet(" << packet_number << "): " << std::endl
             << quiche::QuicheTextUtils::HexDump(packet->AsStringPiece());
    return packet;
  }

  std::unique_ptr<quic::QuicReceivedPacket>
  ConstructClientAckAndRstStreamPacket(uint64_t largest_received,
                                       uint64_t smallest_received) {
    return client_maker_.Packet(++packet_number_)
        .AddAckFrame(/*first_received=*/1, largest_received, smallest_received)
        .AddStopSendingFrame(stream_id_, quic::QUIC_STREAM_CANCELLED)
        .AddRstStreamFrame(stream_id_, quic::QUIC_STREAM_CANCELLED)
        .Build();
  }

  std::unique_ptr<quic::QuicReceivedPacket> ConstructAckAndDataPacket(
      uint64_t packet_number,
      uint64_t largest_received,
      uint64_t smallest_received,
      bool fin,
      std::string_view data,
      QuicTestPacketMaker* maker) {
    std::unique_ptr<quic::QuicReceivedPacket> packet(
        maker->Packet(packet_number)
            .AddAckFrame(/*first_received=*/1, largest_received,
                         smallest_received)
            .AddStreamFrame(stream_id_, fin, data)
            .Build());
    DVLOG(2) << "packet(" << packet_number << "): " << std::endl
             << quiche::QuicheTextUtils::HexDump(packet->AsStringPiece());
    return packet;
  }

  std::unique_ptr<quic::QuicReceivedPacket> ConstructClientAckPacket(
      uint64_t largest_received,
      uint64_t smallest_received) {
    return client_maker_.Packet(++packet_number_)
        .AddAckFrame(1, largest_received, smallest_received)
        .Build();
  }

  std::unique_ptr<quic::QuicReceivedPacket> ConstructServerAckPacket(
      uint64_t packet_number,
      uint64_t largest_received,
      uint64_t smallest_received,
      uint64_t least_unacked) {
    return server_maker_.Packet(packet_number)
        .AddAckFrame(largest_received, smallest_received, least_unacked)
        .Build();
  }

  std::unique_ptr<quic::QuicReceivedPacket> ConstructInitialSettingsPacket() {
    return client_maker_.MakeInitialSettingsPacket(++packet_number_);
  }

  void ExpectLoadTimingValid(const LoadTimingInfo& load_timing_info,
                             bool session_reused) {
    EXPECT_EQ(session_reused, load_timing_info.socket_reused);

    if (session_reused) {
      ExpectConnectTimingHasNoTimes(load_timing_info.connect_timing);
    } else {
      ExpectConnectTimingHasTimes(
          load_timing_info.connect_timing,
          CONNECT_TIMING_HAS_SSL_TIMES | CONNECT_TIMING_HAS_DNS_TIMES);
    }
    ExpectLoadTimingHasOnlyConnectionTimes(load_timing_info);
  }

  const RecordingNetLogObserver& net_log_observer() const {
    return net_log_observer_;
  }

  const NetLogWithSource& net_log_with_source() const {
    return net_log_with_source_;
  }

  QuicChromiumClientSession* session() const { return session_.get(); }

  quic::QuicStreamId GetNthClientInitiatedBidirectionalStreamId(int n) {
    return quic::test::GetNthClientInitiatedBidirectionalStreamId(
        version_.transport_version, n);
  }

  std::string ConstructDataHeader(size_t body_len) {
    quiche::QuicheBuffer buffer = quic::HttpEncoder::SerializeDataFrameHeader(
        body_len, quiche::SimpleBufferAllocator::Get());
    return std::string(buffer.data(), buffer.size());
  }

 protected:
  quic::test::QuicFlagSaver saver_;
  const quic::ParsedQuicVersion version_;
  RecordingNetLogObserver net_log_observer_;
  NetLogWithSource net_log_with_source_{
      NetLogWithSource::Make(NetLogSourceType::NONE)};
  scoped_refptr<TestTaskRunner> runner_;
  std::vector<MockWrite> mock_writes_;
  quic::MockClock clock_;
  raw_ptr<quic::QuicConnection, DanglingUntriaged> connection_;
  std::unique_ptr<QuicChromiumConnectionHelper> helper_;
  std::unique_ptr<QuicChromiumAlarmFactory> alarm_factory_;
  TransportSecurityState transport_security_state_;
  SSLConfigServiceDefaults ssl_config_service_;
  std::unique_ptr<QuicChromiumClientSession> session_;
  quic::QuicCryptoClientConfig crypto_config_;
  HttpRequestHeaders headers_;
  HttpResponseInfo response_;
  scoped_refptr<IOBufferWithSize> read_buffer_;
  quiche::HttpHeaderBlock request_headers_;
  const quic::QuicConnectionId connection_id_;
  const quic::QuicStreamId stream_id_;
  QuicTestPacketMaker client_maker_;
  uint64_t packet_number_ = 0;
  QuicTestPacketMaker server_maker_;
  IPEndPoint self_addr_;
  IPEndPoint peer_addr_;
  quic::test::MockRandom random_generator_{0};
  QuicPacketPrinter printer_;
  MockCryptoClientStreamFactory crypto_client_stream_factory_;
  std::unique_ptr<StaticSocketDataProvider> socket_data_;
  std::vector<PacketToWrite> writes_;
  url::SchemeHostPort destination_;
  quic::test::MockConnectionIdGenerator connection_id_generator_;
  quic::test::NoopQpackStreamSenderDelegate noop_qpack_stream_sender_delegate_;
};

INSTANTIATE_TEST_SUITE_P(Version,
                         BidirectionalStreamQuicImplTest,
                         ::testing::ValuesIn(AllSupportedQuicVersions()),
                         ::testing::PrintToStringParamName());

TEST_P(BidirectionalStreamQuicImplTest, GetRequest) {
  SetRequest("GET", "/", DEFAULT_PRIORITY);
  size_t spdy_request_headers_frame_length;
  client_maker_.SetEncryptionLevel(quic::ENCRYPTION_ZERO_RTT);
  AddWrite(ConstructInitialSettingsPacket());
  AddWrite(ConstructRequestHeadersPacketInner(
      GetNthClientInitiatedBidirectionalStreamId(0), kFin, DEFAULT_PRIORITY,
      &spdy_request_headers_frame_length));
  client_maker_.SetEncryptionLevel(quic::ENCRYPTION_FORWARD_SECURE);
  AddWrite(ConstructClientAckPacket(3, 1));

  Initialize();

  BidirectionalStreamRequestInfo request;
  request.method = "GET";
  request.url = GURL("http://www.google.com/");
  request.end_stream_on_headers = true;
  request.priority = DEFAULT_PRIORITY;

  auto read_buffer = base::MakeRefCounted<IOBufferWithSize>(kReadBufferSize);
  auto delegate =
      std::make_unique<TestDelegateBase>(read_buffer.get(), kReadBufferSize);
  delegate->set_trailers_expected(true);
  delegate->Start(&request, net_log_with_source(),
                  session()->CreateHandle(destination_));
  delegate->WaitUntilNextCallback(kOnStreamReady);
  ConfirmHandshake();

  // Server acks the request.
  ProcessPacket(ConstructServerAckPacket(1, 1, 1, 1));

  // Server sends the response headers.
  quiche::HttpHeaderBlock response_headers = ConstructResponseHeaders("200");

  size_t spdy_response_headers_frame_length;
  ProcessPacket(
      ConstructResponseHeadersPacket(2, !kFin, std::move(response_headers),
                                     &spdy_response_headers_frame_length));

  delegate->WaitUntilNextCallback(kOnHeadersReceived);
  LoadTimingInfo load_timing_info;
  EXPECT_TRUE(delegate->GetLoadTimingInfo(&load_timing_info));
  ExpectLoadTimingValid(load_timing_info, /*session_reused=*/false);
  TestCompletionCallback cb;
  int rv = delegate->ReadData(cb.callback());
  EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
  EXPECT_EQ("200", delegate->response_headers().find(":status")->second);
  const char kResponseBody[] = "Hello world!";
  // Server sends data.
  std::string header = ConstructDataHeader(strlen(kResponseBody));
  ProcessPacket(ConstructServerDataPacket(3, !kFin, header + kResponseBody));
  EXPECT_EQ(12, cb.WaitForResult());

  EXPECT_EQ(std::string(kResponseBody), delegate->data_received());
  TestCompletionCallback cb2;
  EXPECT_THAT(delegate->ReadData(cb2.callback()), IsError(ERR_IO_PENDING));

  quiche::HttpHeaderBlock trailers;
  size_t spdy_trailers_frame_length;
  trailers["foo"] = "bar";
  // Server sends trailers.
  ProcessPacket(ConstructResponseTrailersPacket(4, kFin, trailers.Clone(),
                                                &spdy_trailers_frame_length));

  delegate->WaitUntilNextCallback(kOnTrailersReceived);
  EXPECT_THAT(cb2.WaitForResult(), IsOk());
  EXPECT_EQ(trailers, delegate->trailers());

  EXPECT_THAT(delegate->ReadData(cb2.callback()), IsOk());
  base::RunLoop().RunUntilIdle();

  EXPECT_EQ(2, delegate->on_data_read_count());
  EXPECT_EQ(0, delegate->on_data_sent_count());
  EXPECT_EQ(NextProto::kProtoQUIC, delegate->GetProtocol());
  EXPECT_EQ(static_cast<int64_t>(spdy_request_headers_frame_length),
            delegate->GetTotalSentBytes());
  EXPECT_EQ(static_cast<int64_t>(spdy_response_headers_frame_length +
                                 strlen(kResponseBody) + header.length() +
                                 spdy_trailers_frame_length),
            delegate->GetTotalReceivedBytes());
  // Check that NetLog was filled as expected.
  auto entries = net_log_observer().GetEntries();
  size_t pos = ExpectLogContainsSomewhere(
      entries, /*min_offset=*/0,
      NetLogEventType::QUIC_CHROMIUM_CLIENT_STREAM_SEND_REQUEST_HEADERS,
      NetLogEventPhase::NONE);
  pos = ExpectLogContainsSomewhere(
      entries, /*min_offset=*/pos,
      NetLogEventType::QUIC_CHROMIUM_CLIENT_STREAM_SEND_REQUEST_HEADERS,
      NetLogEventPhase::NONE);
  ExpectLogContainsSomewhere(
      entries, /*min_offset=*/pos,
      NetLogEventType::QUIC_CHROMIUM_CLIENT_STREAM_SEND_REQUEST_HEADERS,
      NetLogEventPhase::NONE);
}

TEST_P(BidirectionalStreamQuicImplTest, LoadTimingTwoRequests) {
  SetRequest("GET", "/", DEFAULT_PRIORITY);
  client_maker_.SetEncryptionLevel(quic::ENCRYPTION_ZERO_RTT);
  AddWrite(ConstructInitialSettingsPacket());
  AddWrite(ConstructRequestHeadersPacketInner(
      GetNthClientInitiatedBidirectionalStreamId(0), kFin, DEFAULT_PRIORITY,
      nullptr));
  // SetRequest() again for second request as |request_headers_| was moved.
  SetRequest("GET", "/", DEFAULT_PRIORITY);
  AddWrite(ConstructRequestHeadersPacketInner(
      GetNthClientInitiatedBidirectionalStreamId(1), kFin, DEFAULT_PRIORITY,
      nullptr));
  client_maker_.SetEncryptionLevel(quic::ENCRYPTION_FORWARD_SECURE);
  AddWrite(ConstructClientAckPacket(3, 1));
  Initialize();

  BidirectionalStreamRequestInfo request;
  request.method = "GET";
  request.url = GURL("http://www.google.com/");
  request.end_stream_on_headers = true;
  request.priority = DEFAULT_PRIORITY;

  // Start first request.
  auto read_buffer = base::MakeRefCounted<IOBufferWithSize>(kReadBufferSize);
  auto delegate =
      std::make_unique<TestDelegateBase>(read_buffer.get(), kReadBufferSize);
  delegate->Start(&request, net_log_with_source(),
                  session()->CreateHandle(destination_));

  // Start second request.
  auto read_buffer2 = base::MakeRefCounted<IOBufferWithSize>(kReadBufferSize);
  auto delegate2 =
      std::make_unique<TestDelegateBase>(read_buffer2.get(), kReadBufferSize);
  delegate2->Start(&request, net_log_with_source(),
                   session()->CreateHandle(destination_));

  delegate->WaitUntilNextCallback(kOnStreamReady);
  delegate2->WaitUntilNextCallback(kOnStreamReady);

  ConfirmHandshake();
  // Server acks the request.
  ProcessPacket(ConstructServerAckPacket(1, 1, 1, 1));

  // Server sends the response headers.
  ProcessPacket(ConstructResponseHeadersPacketInner(
      2, GetNthClientInitiatedBidirectionalStreamId(0), kFin,
      ConstructResponseHeaders("200"), nullptr));

  ProcessPacket(ConstructResponseHeadersPacketInner(
      3, GetNthClientInitiatedBidirectionalStreamId(1), kFin,
      ConstructResponseHeaders("200"), nullptr));

  delegate->WaitUntilNextCallback(kOnHeadersReceived);
  delegate2->WaitUntilNextCallback(kOnHeadersReceived);

  LoadTimingInfo load_timing_info;
  EXPECT_TRUE(delegate->GetLoadTimingInfo(&load_timing_info));
  LoadTimingInfo load_timing_info2;
  EXPECT_TRUE(delegate2->GetLoadTimingInfo(&load_timing_info2));
  ExpectLoadTimingValid(load_timing_info, /*session_reused=*/false);
  ExpectLoadTimingValid(load_timing_info2, /*session_reused=*/true);
  EXPECT_EQ("200", delegate->response_headers().find(":status")->second);
  EXPECT_EQ("200", delegate2->response_headers().find(":status")->second);
  // No response body. ReadData() should return OK synchronously.
  TestCompletionCallback dummy_callback;
  EXPECT_EQ(OK, delegate->ReadData(dummy_callback.callback()));
  EXPECT_EQ(OK, delegate2->ReadData(dummy_callback.callback()));
}

// Tests that when request headers are not delayed, only data buffers are
// coalesced.
TEST_P(BidirectionalStreamQuicImplTest, CoalesceDataBuffersNotHeadersFrame) {
  SetRequest("POST", "/", DEFAULT_PRIORITY);
  size_t spdy_request_headers_frame_length;
  client_maker_.SetEncryptionLevel(quic::ENCRYPTION_ZERO_RTT);
  AddWrite(ConstructInitialSettingsPacket());
  client_maker_.SetEncryptionLevel(quic::ENCRYPTION_FORWARD_SECURE);
  const std::string kBody1 = "here are some data";
  const std::string kBody2 = "data keep coming";
  std::string header = ConstructDataHeader(kBody1.length());
  std::string header2 = ConstructDataHeader(kBody2.length());
  std::vector<std::string> two_writes = {kBody1, kBody2};
  AddWrite(ConstructRequestHeadersPacketInner(
      GetNthClientInitiatedBidirectionalStreamId(0), !kFin, DEFAULT_PRIORITY,
      &spdy_request_headers_frame_length));
  AddWrite(
      ConstructClientDataPacket(!kFin, header + kBody1 + header2 + kBody2));

  // Ack server's data packet.
  AddWrite(ConstructClientAckPacket(3, 1));
  const std::string kBody3 = "hello there";
  const std::string kBody4 = "another piece of small data";
  const std::string kBody5 = "really small";
  std::string header3 = ConstructDataHeader(kBody3.length());
  std::string header4 = ConstructDataHeader(kBody4.length());
  std::string header5 = ConstructDataHeader(kBody5.length());
  AddWrite(ConstructClientDataPacket(
      kFin, header3 + kBody3 + header4 + kBody4 + header5 + kBody5));

  Initialize();

  BidirectionalStreamRequestInfo request;
  request.method = "POST";
  request.url = GURL("http://www.google.com/");
  request.end_stream_on_headers = false;
  request.priority = DEFAULT_PRIORITY;

  auto read_buffer = base::MakeRefCounted<IOBufferWithSize>(kReadBufferSize);
  auto delegate =
      std::make_unique<TestDelegateBase>(read_buffer.get(), kReadBufferSize);
  delegate->DoNotSendRequestHeadersAutomatically();
  delegate->Start(&request, net_log_with_source(),
                  session()->CreateHandle(destination_));
  EXPECT_FALSE(delegate->is_ready());
  ConfirmHandshake();
  delegate->WaitUntilNextCallback(kOnStreamReady);
  EXPECT_TRUE(delegate->is_ready());

  // Sends request headers separately, which causes them to be sent in a
  // separate packet.
  delegate->SendRequestHeaders();
  // Send a Data packet.
  scoped_refptr<StringIOBuffer> buf1 =
      base::MakeRefCounted<StringIOBuffer>(kBody1);
  scoped_refptr<StringIOBuffer> buf2 =
      base::MakeRefCounted<StringIOBuffer>(kBody2);

  std::vector<int> lengths = {buf1->size(), buf2->size()};
  delegate->SendvData({buf1, buf2}, lengths, !kFin);
  delegate->WaitUntilNextCallback(kOnDataSent);

  // Server acks the request.
  ProcessPacket(ConstructServerAckPacket(1, 1, 1, 1));

  // Server sends the response headers.
  quiche::HttpHeaderBlock response_headers = ConstructResponseHeaders("200");
  size_t spdy_response_headers_frame_length;
  ProcessPacket(
      ConstructResponseHeadersPacket(2, !kFin, std::move(response_headers),
                                     &spdy_response_headers_frame_length));

  delegate->WaitUntilNextCallback(kOnHeadersReceived);
  TestCompletionCallback cb;
  int rv = delegate->ReadData(cb.callback());
  EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
  EXPECT_EQ("200", delegate->response_headers().find(":status")->second);
  const char kResponseBody[] = "Hello world!";
  std::string header6 = ConstructDataHeader(strlen(kResponseBody));
  // Server sends data.
  ProcessPacket(ConstructServerDataPacket(3, !kFin, header6 + kResponseBody));

  EXPECT_EQ(static_cast<int>(strlen(kResponseBody)), cb.WaitForResult());

  // Send a second Data packet.
  scoped_refptr<StringIOBuffer> buf3 =
      base::MakeRefCounted<StringIOBuffer>(kBody3);
  scoped_refptr<StringIOBuffer> buf4 =
      base::MakeRefCounted<StringIOBuffer>(kBody4);
  scoped_refptr<StringIOBuffer> buf5 =
      base::MakeRefCounted<StringIOBuffer>(kBody5);

  delegate->SendvData({buf3, buf4, buf5},
                      {buf3->size(), buf4->size(), buf5->size()}, kFin);
  delegate->WaitUntilNextCallback(kOnDataSent);

  size_t spdy_trailers_frame_length;
  quiche::HttpHeaderBlock trailers;
  trailers["foo"] = "bar";
  // Server sends trailers.
  ProcessPacket(ConstructResponseTrailersPacket(4, kFin, trailers.Clone(),
                                                &spdy_trailers_frame_length));

  delegate->WaitUntilNextCallback(kOnTrailersReceived);
  EXPECT_EQ(trailers, delegate->trailers());
  EXPECT_THAT(delegate->ReadData(cb.callback()), IsOk());

  EXPECT_EQ(1, delegate->on_data_read_count());
  EXPECT_EQ(2, delegate->on_data_sent_count());
  EXPECT_EQ(NextProto::kProtoQUIC, delegate->GetProtocol());
  EXPECT_EQ(static_cast<int64_t>(
                spdy_request_headers_frame_length + kBody1.length() +
                kBody2.length() + kBody3.length() + kBody4.length() +
                kBody5.length() + header.length() + header2.length() +
                header3.length() + header4.length() + header5.length()),
            delegate->GetTotalSentBytes());
  EXPECT_EQ(static_cast<int64_t>(spdy_response_headers_frame_length +
                                 strlen(kResponseBody) + header6.length() +
                                 spdy_trailers_frame_length),
            delegate->GetTotalReceivedBytes());
}

// Tests that when request headers are delayed, SendData triggers coalescing of
// request headers with data buffers.
TEST_P(BidirectionalStreamQuicImplTest,
       SendDataCoalesceDataBufferAndHeaderFrame) {
  SetRequest("POST", "/", DEFAULT_PRIORITY);
  size_t spdy_request_headers_frame_length;
  client_maker_.SetEncryptionLevel(quic::ENCRYPTION_ZERO_RTT);
  AddWrite(ConstructInitialSettingsPacket());
  client_maker_.SetEncryptionLevel(quic::ENCRYPTION_FORWARD_SECURE);
  const char kBody1[] = "here are some data";
  std::string header = ConstructDataHeader(strlen(kBody1));
  AddWrite(ConstructRequestHeadersAndMultipleDataFramesPacket(
      !kFin, DEFAULT_PRIORITY, &spdy_request_headers_frame_length,
      {header, kBody1}));

  // Ack server's data packet.
  AddWrite(ConstructClientAckPacket(3, 1));
  const char kBody2[] = "really small";
  std::string header2 = ConstructDataHeader(strlen(kBody2));
  AddWrite(ConstructClientDataPacket(kFin, header2 + std::string(kBody2)));

  Initialize();

  BidirectionalStreamRequestInfo request;
  request.method = "POST";
  request.url = GURL("http://www.google.com/");
  request.end_stream_on_headers = false;
  request.priority = DEFAULT_PRIORITY;

  auto read_buffer = base::MakeRefCounted<IOBufferWithSize>(kReadBufferSize);
  auto delegate =
      std::make_unique<TestDelegateBase>(read_buffer.get(), kReadBufferSize);
  delegate->DoNotSendRequestHeadersAutomatically();
  delegate->Start(&request, net_log_with_source(),
                  session()->CreateHandle(destination_));
  ConfirmHandshake();
  delegate->WaitUntilNextCallback(kOnStreamReady);

  // Send a Data packet.
  scoped_refptr<StringIOBuffer> buf1 =
      base::MakeRefCounted<StringIOBuffer>(kBody1);

  delegate->SendData(buf1, buf1->size(), false);
  delegate->WaitUntilNextCallback(kOnDataSent);

  // Server acks the request.
  ProcessPacket(ConstructServerAckPacket(1, 1, 1, 1));

  // Server sends the response headers.
  quiche::HttpHeaderBlock response_headers = ConstructResponseHeaders("200");
  size_t spdy_response_headers_frame_length;
  ProcessPacket(
      ConstructResponseHeadersPacket(2, !kFin, std::move(response_headers),
                                     &spdy_response_headers_frame_length));

  delegate->WaitUntilNextCallback(kOnHeadersReceived);
  TestCompletionCallback cb;
  int rv = delegate->ReadData(cb.callback());
  EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
  EXPECT_EQ("200", delegate->response_headers().find(":status")->second);
  const char kResponseBody[] = "Hello world!";
  // Server sends data.
  std::string header3 = ConstructDataHeader(strlen(kResponseBody));
  ProcessPacket(ConstructServerDataPacket(3, !kFin, header3 + kResponseBody));

  EXPECT_EQ(static_cast<int>(strlen(kResponseBody)), cb.WaitForResult());

  // Send a second Data packet.
  scoped_refptr<StringIOBuffer> buf2 =
      base::MakeRefCounted<StringIOBuffer>(kBody2);

  delegate->SendData(buf2, buf2->size(), true);
  delegate->WaitUntilNextCallback(kOnDataSent);

  size_t spdy_trailers_frame_length;
  quiche::HttpHeaderBlock trailers;
  trailers["foo"] = "bar";
  // Server sends trailers.
  ProcessPacket(ConstructResponseTrailersPacket(4, kFin, trailers.Clone(),
                                                &spdy_trailers_frame_length));

  delegate->WaitUntilNextCallback(kOnTrailersReceived);
  EXPECT_EQ(trailers, delegate->trailers());
  EXPECT_THAT(delegate->ReadData(cb.callback()), IsOk());

  EXPECT_EQ(1, delegate->on_data_read_count());
  EXPECT_EQ(2, delegate->on_data_sent_count());
  EXPECT_EQ(NextProto::kProtoQUIC, delegate->GetProtocol());
  EXPECT_EQ(
      static_cast<int64_t>(spdy_request_headers_frame_length + strlen(kBody1) +
                           strlen(kBody2) + header.length() + header2.length()),
      delegate->GetTotalSentBytes());
  EXPECT_EQ(static_cast<int64_t>(spdy_response_headers_frame_length +
                                 strlen(kResponseBody) + header3.length() +
                                 spdy_trailers_frame_length),
            delegate->GetTotalReceivedBytes());
}

// Tests that when request headers are delayed, SendvData triggers coalescing of
// request headers with data buffers.
TEST_P(BidirectionalStreamQuicImplTest,
       SendvDataCoalesceDataBuffersAndHeaderFrame) {
  SetRequest("POST", "/", DEFAULT_PRIORITY);
  size_t spdy_request_headers_frame_length;
  client_maker_.SetEncryptionLevel(quic::ENCRYPTION_ZERO_RTT);
  AddWrite(ConstructInitialSettingsPacket());
  client_maker_.SetEncryptionLevel(quic::ENCRYPTION_FORWARD_SECURE);
  const std::string kBody1 = "here are some data";
  const std::string kBody2 = "data keep coming";
  std::string header = ConstructDataHeader(kBody1.length());
  std::string header2 = ConstructDataHeader(kBody2.length());

  AddWrite(ConstructRequestHeadersAndMultipleDataFramesPacket(
      !kFin, DEFAULT_PRIORITY, &spdy_request_headers_frame_length,
      {header + kBody1 + header2 + kBody2}));

  // Ack server's data packet.
  AddWrite(ConstructClientAckPacket(3, 1));
  const std::string kBody3 = "hello there";
  const std::string kBody4 = "another piece of small data";
  const std::string kBody5 = "really small";
  std::string header3 = ConstructDataHeader(kBody3.length());
  std::string header4 = ConstructDataHeader(kBody4.length());
  std::string header5 = ConstructDataHeader(kBody5.length());
  AddWrite(ConstructClientDataPacket(
      kFin, header3 + kBody3 + header4 + kBody4 + header5 + kBody5));

  Initialize();

  BidirectionalStreamRequestInfo request;
  request.method = "POST";
  request.url = GURL("http://www.google.com/");
  request.end_stream_on_headers = false;
  request.priority = DEFAULT_PRIORITY;

  auto read_buffer = base::MakeRefCounted<IOBufferWithSize>(kReadBufferSize);
  auto delegate =
      std::make_unique<TestDelegateBase>(read_buffer.get(), kReadBufferSize);
  delegate->DoNotSendRequestHeadersAutomatically();
  delegate->Start(&request, net_log_with_source(),
                  session()->CreateHandle(destination_));
  ConfirmHandshake();
  delegate->WaitUntilNextCallback(kOnStreamReady);

  // Send a Data packet.
  scoped_refptr<StringIOBuffer> buf1 =
      base::MakeRefCounted<StringIOBuffer>(kBody1);
  scoped_refptr<StringIOBuffer> buf2 =
      base::MakeRefCounted<StringIOBuffer>(kBody2);

  std::vector<int> lengths = {buf1->size(), buf2->size()};
  delegate->SendvData({buf1, buf2}, lengths, !kFin);
  delegate->WaitUntilNextCallback(kOnDataSent);

  // Server acks the request.
  ProcessPacket(ConstructServerAckPacket(1, 1, 1, 1));

  // Server sends the response headers.
  quiche::HttpHeaderBlock response_headers = ConstructResponseHeaders("200");
  size_t spdy_response_headers_frame_length;
  ProcessPacket(
      ConstructResponseHeadersPacket(2, !kFin, std::move(response_headers),
                                     &spdy_response_headers_frame_length));

  delegate->WaitUntilNextCallback(kOnHeadersReceived);
  TestCompletionCallback cb;
  int rv = delegate->ReadData(cb.callback());
  EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
  EXPECT_EQ("200", delegate->response_headers().find(":status")->second);
  const char kResponseBody[] = "Hello world!";
  std::string header6 = ConstructDataHeader(strlen(kResponseBody));
  // Server sends data.
  ProcessPacket(ConstructServerDataPacket(3, !kFin, header6 + kResponseBody));

  EXPECT_EQ(static_cast<int>(strlen(kResponseBody)), cb.WaitForResult());

  // Send a second Data packet.
  scoped_refptr<StringIOBuffer> buf3 =
      base::MakeRefCounted<StringIOBuffer>(kBody3);
  scoped_refptr<StringIOBuffer> buf4 =
      base::MakeRefCounted<StringIOBuffer>(kBody4);
  scoped_refptr<StringIOBuffer> buf5 =
      base::MakeRefCounted<StringIOBuffer>(kBody5);

  delegate->SendvData({buf3, buf4, buf5},
                      {buf3->size(), buf4->size(), buf5->size()}, kFin);
  delegate->WaitUntilNextCallback(kOnDataSent);

  size_t spdy_trailers_frame_length;
  quiche::HttpHeaderBlock trailers;
  trailers["foo"] = "bar";
  // Server sends trailers.
  ProcessPacket(ConstructResponseTrailersPacket(4, kFin, trailers.Clone(),
                                                &spdy_trailers_frame_length));

  delegate->WaitUntilNextCallback(kOnTrailersReceived);
  EXPECT_EQ(trailers, delegate->trailers());
  EXPECT_THAT(delegate->ReadData(cb.callback()), IsOk());

  EXPECT_EQ(1, delegate->on_data_read_count());
  EXPECT_EQ(2, delegate->on_data_sent_count());
  EXPECT_EQ(NextProto::kProtoQUIC, delegate->GetProtocol());
  EXPECT_EQ(static_cast<int64_t>(
                spdy_request_headers_frame_length + kBody1.length() +
                kBody2.length() + kBody3.length() + kBody4.length() +
                kBody5.length() + header.length() + header2.length() +
                header3.length() + header4.length() + header5.length()),
            delegate->GetTotalSentBytes());
  EXPECT_EQ(static_cast<int64_t>(spdy_response_headers_frame_length +
                                 strlen(kResponseBody) + header6.length() +
                                 spdy_trailers_frame_length),
            delegate->GetTotalReceivedBytes());
}

// Tests that when request headers are delayed and SendData triggers the
// headers to be sent, if that write fails the stream does not crash.
TEST_P(BidirectionalStreamQuicImplTest,
       SendDataWriteErrorCoalesceDataBufferAndHeaderFrame) {
  client_maker_.SetEncryptionLevel(quic::ENCRYPTION_ZERO_RTT);
  AddWrite(ConstructInitialSettingsPacket());
  AddWriteError(SYNCHRONOUS, ERR_CONNECTION_REFUSED);

  Initialize();

  BidirectionalStreamRequestInfo request;
  request.method = "POST";
  request.url = GURL("http://www.google.com/");
  request.end_stream_on_headers = false;
  request.priority = DEFAULT_PRIORITY;
  request.extra_headers.SetHeader("cookie", std::string(2048, 'A'));

  auto read_buffer = base::MakeRefCounted<IOBufferWithSize>(kReadBufferSize);
  auto delegate = std::make_unique<DeleteStreamDelegate>(
      read_buffer.get(), kReadBufferSize, DeleteStreamDelegate::ON_FAILED);
  delegate->DoNotSendRequestHeadersAutomatically();
  delegate->Start(&request, net_log_with_source(),
                  session()->CreateHandle(destination_));
  ConfirmHandshake();
  delegate->WaitUntilNextCallback(kOnStreamReady);

  // Attempt to send the headers and data.
  const char kBody1[] = "here are some data";
  scoped_refptr<StringIOBuffer> buf1 =
      base::MakeRefCounted<StringIOBuffer>(kBody1);
  delegate->SendData(buf1, buf1->size(), !kFin);

  delegate->WaitUntilNextCallback(kOnFailed);
}

// Tests that when request headers are delayed and SendvData triggers the
// headers to be sent, if that write fails the stream does not crash.
TEST_P(BidirectionalStreamQuicImplTest,
       SendvDataWriteErrorCoalesceDataBufferAndHeaderFrame) {
  client_maker_.SetEncryptionLevel(quic::ENCRYPTION_ZERO_RTT);
  AddWrite(ConstructInitialSettingsPacket());
  AddWriteError(SYNCHRONOUS, ERR_CONNECTION_REFUSED);

  Initialize();

  BidirectionalStreamRequestInfo request;
  request.method = "POST";
  request.url = GURL("http://www.google.com/");
  request.end_stream_on_headers = false;
  request.priority = DEFAULT_PRIORITY;
  request.extra_headers.SetHeader("cookie", std::string(2048, 'A'));

  auto read_buffer = base::MakeRefCounted<IOBufferWithSize>(kReadBufferSize);
  auto delegate = std::make_unique<DeleteStreamDelegate>(
      read_buffer.get(), kReadBufferSize, DeleteStreamDelegate::ON_FAILED);
  delegate->DoNotSendRequestHeadersAutomatically();
  delegate->Start(&request, net_log_with_source(),
                  session()->CreateHandle(destination_));
  ConfirmHandshake();
  delegate->WaitUntilNextCallback(kOnStreamReady);

  // Attempt to send the headers and data.
  const char kBody1[] = "here are some data";
  const char kBody2[] = "data keep coming";
  scoped_refptr<StringIOBuffer> buf1 =
      base::MakeRefCounted<StringIOBuffer>(kBody1);
  scoped_refptr<StringIOBuffer> buf2 =
      base::MakeRefCounted<StringIOBuffer>(kBody2);
  std::vector<int> lengths = {buf1->size(), buf2->size()};
  delegate->SendvData({buf1, buf2}, lengths, !kFin);

  delegate->WaitUntilNextCallback(kOnFailed);
}

TEST_P(BidirectionalStreamQuicImplTest, PostRequest) {
  SetRequest("POST", "/", DEFAULT_PRIORITY);
  size_t spdy_request_headers_frame_length;
  client_maker_.SetEncryptionLevel(quic::ENCRYPTION_ZERO_RTT);
  AddWrite(ConstructInitialSettingsPacket());
  client_maker_.SetEncryptionLevel(quic::ENCRYPTION_FORWARD_SECURE);
  AddWrite(ConstructRequestHeadersPacketInner(
      GetNthClientInitiatedBidirectionalStreamId(0), !kFin, DEFAULT_PRIORITY,
      &spdy_request_headers_frame_length));
  std::string header = ConstructDataHeader(strlen(kUploadData));
  AddWrite(ConstructClientDataPacket(kFin, header + std::string(kUploadData)));

  AddWrite(ConstructClientAckPacket(3, 1));

  Initialize();

  BidirectionalStreamRequestInfo request;
  request.method = "POST";
  request.url = GURL("http://www.google.com/");
  request.end_stream_on_headers = false;
  request.priority = DEFAULT_PRIORITY;

  auto read_buffer = base::MakeRefCounted<IOBufferWithSize>(kReadBufferSize);
  auto delegate =
      std::make_unique<TestDelegateBase>(read_buffer.get(), kReadBufferSize);
  delegate->Start(&request, net_log_with_source(),
                  session()->CreateHandle(destination_));
  ConfirmHandshake();
  delegate->WaitUntilNextCallback(kOnStreamReady);

  // Send a DATA frame.
  scoped_refptr<StringIOBuffer> buf =
      base::MakeRefCounted<StringIOBuffer>(kUploadData);

  delegate->SendData(buf, buf->size(), true);
  delegate->WaitUntilNextCallback(kOnDataSent);

  // Server acks the request.
  ProcessPacket(ConstructServerAckPacket(1, 1, 1, 1));

  // Server sends the response headers.
  quiche::HttpHeaderBlock response_headers = ConstructResponseHeaders("200");
  size_t spdy_response_headers_frame_length;
  ProcessPacket(
      ConstructResponseHeadersPacket(2, !kFin, std::move(response_headers),
                                     &spdy_response_headers_frame_length));

  delegate->WaitUntilNextCallback(kOnHeadersReceived);
  TestCompletionCallback cb;
  int rv = delegate->ReadData(cb.callback());
  EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
  EXPECT_EQ("200", delegate->response_headers().find(":status")->second);
  const char kResponseBody[] = "Hello world!";
  std::string header2 = ConstructDataHeader(strlen(kResponseBody));
  // Server sends data.
  ProcessPacket(ConstructServerDataPacket(3, !kFin, header2 + kResponseBody));

  EXPECT_EQ(static_cast<int>(strlen(kResponseBody)), cb.WaitForResult());

  size_t spdy_trailers_frame_length;
  quiche::HttpHeaderBlock trailers;
  trailers["foo"] = "bar";
  // Server sends trailers.
  ProcessPacket(ConstructResponseTrailersPacket(4, kFin, trailers.Clone(),
                                                &spdy_trailers_frame_length));

  delegate->WaitUntilNextCallback(kOnTrailersReceived);
  EXPECT_EQ(trailers, delegate->trailers());
  EXPECT_THAT(delegate->ReadData(cb.callback()), IsOk());

  EXPECT_EQ(1, delegate->on_data_read_count());
  EXPECT_EQ(1, delegate->on_data_sent_count());
  EXPECT_EQ(NextProto::kProtoQUIC, delegate->GetProtocol());
  EXPECT_EQ(static_cast<int64_t>(spdy_request_headers_frame_length +
                                 strlen(kUploadData) + header.length()),
            delegate->GetTotalSentBytes());
  EXPECT_EQ(static_cast<int64_t>(spdy_response_headers_frame_length +
                                 strlen(kResponseBody) + header2.length() +
                                 spdy_trailers_frame_length),
            delegate->GetTotalReceivedBytes());
}

TEST_P(BidirectionalStreamQuicImplTest, EarlyDataOverrideRequest) {
  SetRequest("PUT", "/", DEFAULT_PRIORITY);
  size_t spdy_request_headers_frame_length;
  client_maker_.SetEncryptionLevel(quic::ENCRYPTION_ZERO_RTT);
  AddWrite(ConstructInitialSettingsPacket());
  AddWrite(ConstructRequestHeadersPacketInner(
      GetNthClientInitiatedBidirectionalStreamId(0), kFin, DEFAULT_PRIORITY,
      &spdy_request_headers_frame_length));
  client_maker_.SetEncryptionLevel(quic::ENCRYPTION_FORWARD_SECURE);
  AddWrite(ConstructClientAckPacket(3, 1));

  Initialize();

  BidirectionalStreamRequestInfo request;
  request.method = "PUT";
  request.allow_early_data_override = true;
  request.url = GURL("http://www.google.com/");
  request.end_stream_on_headers = true;
  request.priority = DEFAULT_PRIORITY;

  auto read_buffer = base::MakeRefCounted<IOBufferWithSize>(kReadBufferSize);
  auto delegate =
      std::make_unique<TestDelegateBase>(read_buffer.get(), kReadBufferSize);
  delegate->set_trailers_expected(true);
  delegate->Start(&request, net_log_with_source(),
                  session()->CreateHandle(destination_));
  delegate->WaitUntilNextCallback(kOnStreamReady);
  ConfirmHandshake();

  // Server acks the request.
  ProcessPacket(ConstructServerAckPacket(1, 1, 1, 1));

  // Server sends the response headers.
  quiche::HttpHeaderBlock response_headers = ConstructResponseHeaders("200");

  size_t spdy_response_headers_frame_length;
  ProcessPacket(
      ConstructResponseHeadersPacket(2, !kFin, std::move(response_headers),
                                     &spdy_response_headers_frame_length));

  delegate->WaitUntilNextCallback(kOnHeadersReceived);
  LoadTimingInfo load_timing_info;
  EXPECT_TRUE(delegate->GetLoadTimingInfo(&load_timing_info));
  ExpectLoadTimingValid(load_timing_info, /*session_reused=*/false);
  TestCompletionCallback cb;
  int rv = delegate->ReadData(cb.callback());
  EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
  EXPECT_EQ("200", delegate->response_headers().find(":status")->second);
  const char kResponseBody[] = "Hello world!";
  // Server sends data.
  std::string header = ConstructDataHeader(strlen(kResponseBody));
  ProcessPacket(ConstructServerDataPacket(3, !kFin, header + kResponseBody));
  EXPECT_EQ(12, cb.WaitForResult());

  EXPECT_EQ(std::string(kResponseBody), delegate->data_received());
  TestCompletionCallback cb2;
  EXPECT_THAT(delegate->ReadData(cb2.callback()), IsError(ERR_IO_PENDING));

  quiche::HttpHeaderBlock trailers;
  size_t spdy_trailers_frame_length;
  trailers["foo"] = "bar";
  // Server sends trailers.
  ProcessPacket(ConstructResponseTrailersPacket(4, kFin, trailers.Clone(),
                                                &spdy_trailers_frame_length));

  delegate->WaitUntilNextCallback(kOnTrailersReceived);
  EXPECT_THAT(cb2.WaitForResult(), IsOk());
  EXPECT_EQ(trailers, delegate->trailers());

  EXPECT_THAT(delegate->ReadData(cb2.callback()), IsOk());
  base::RunLoop().RunUntilIdle();

  EXPECT_EQ(2, delegate->on_data_read_count());
  EXPECT_EQ(0, delegate->on_data_sent_count());
  EXPECT_EQ(NextProto::kProtoQUIC, delegate->GetProtocol());
  EXPECT_EQ(static_cast<int64_t>(spdy_request_headers_frame_length),
            delegate->GetTotalSentBytes());
  EXPECT_EQ(static_cast<int64_t>(spdy_response_headers_frame_length +
                                 strlen(kResponseBody) + header.length() +
                                 spdy_trailers_frame_length),
            delegate->GetTotalReceivedBytes());
  // Check that NetLog was filled as expected.
  auto entries = net_log_observer().GetEntries();
  size_t pos = ExpectLogContainsSomewhere(
      entries, /*min_offset=*/0,
      NetLogEventType::QUIC_CHROMIUM_CLIENT_STREAM_SEND_REQUEST_HEADERS,
      NetLogEventPhase::NONE);
  pos = ExpectLogContainsSomewhere(
      entries, /*min_offset=*/pos,
      NetLogEventType::QUIC_CHROMIUM_CLIENT_STREAM_SEND_REQUEST_HEADERS,
      NetLogEventPhase::NONE);
  ExpectLogContainsSomewhere(
      entries, /*min_offset=*/pos,
      NetLogEventType::QUIC_CHROMIUM_CLIENT_STREAM_SEND_REQUEST_HEADERS,
      NetLogEventPhase::NONE);
}

TEST_P(BidirectionalStreamQuicImplTest, InterleaveReadDataAndSendData) {
  SetRequest("POST", "/", DEFAULT_PRIORITY);
  size_t spdy_request_headers_frame_length;
  client_maker_.SetEncryptionLevel(quic::ENCRYPTION_ZERO_RTT);
  AddWrite(ConstructInitialSettingsPacket());
  client_maker_.SetEncryptionLevel(quic::ENCRYPTION_FORWARD_SECURE);
  AddWrite(ConstructRequestHeadersPacketInner(
      GetNthClientInitiatedBidirectionalStreamId(0), !kFin, DEFAULT_PRIORITY,
      &spdy_request_headers_frame_length));

  std::string header = ConstructDataHeader(strlen(kUploadData));
  AddWrite(ConstructAckAndDataPacket(++packet_number_, 2, 1, !kFin,
                                     header + std::string(kUploadData),
                                     &client_maker_));
  AddWrite(ConstructAckAndDataPacket(++packet_number_, 3, 3, kFin,
                                     header + std::string(kUploadData),
                                     &client_maker_));
  Initialize();

  BidirectionalStreamRequestInfo request;
  request.method = "POST";
  request.url = GURL("http://www.google.com/");
  request.end_stream_on_headers = false;
  request.priority = DEFAULT_PRIORITY;

  auto read_buffer = base::MakeRefCounted<IOBufferWithSize>(kReadBufferSize);
  auto delegate =
      std::make_unique<TestDelegateBase>(read_buffer.get(), kReadBufferSize);
  delegate->Start(&request, net_log_with_source(),
                  session()->CreateHandle(destination_));
  ConfirmHandshake();
  delegate->WaitUntilNextCallback(kOnStreamReady);

  // Server acks the request.
  ProcessPacket(ConstructServerAckPacket(1, 1, 1, 1));

  // Server sends the response headers.
  quiche::HttpHeaderBlock response_headers = ConstructResponseHeaders("200");
  size_t spdy_response_headers_frame_length;
  ProcessPacket(
      ConstructResponseHeadersPacket(2, !kFin, std::move(response_headers),
                                     &spdy_response_headers_frame_length));

  delegate->WaitUntilNextCallback(kOnHeadersReceived);
  EXPECT_EQ("200", delegate->response_headers().find(":status")->second);

  // Client sends a data packet.
  scoped_refptr<StringIOBuffer> buf =
      base::MakeRefCounted<StringIOBuffer>(kUploadData);

  delegate->SendData(buf, buf->size(), false);
  delegate->WaitUntilNextCallback(kOnDataSent);

  TestCompletionCallback cb;
  int rv = delegate->ReadData(cb.callback());
  EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
  const char kResponseBody[] = "Hello world!";

  std::string header2 = ConstructDataHeader(strlen(kResponseBody));
  // Server sends a data packet
  int server_ack = 2;
  ProcessPacket(ConstructAckAndDataPacket(
      3, server_ack++, 1, !kFin, header2 + kResponseBody, &server_maker_));

  EXPECT_EQ(static_cast<int64_t>(strlen(kResponseBody)), cb.WaitForResult());
  EXPECT_EQ(std::string(kResponseBody), delegate->data_received());

  // Client sends a data packet.
  delegate->SendData(buf, buf->size(), true);
  delegate->WaitUntilNextCallback(kOnDataSent);

  TestCompletionCallback cb2;
  rv = delegate->ReadData(cb2.callback());
  EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
  ProcessPacket(ConstructAckAndDataPacket(4, server_ack++, 1, kFin,

                                          header2 + kResponseBody,
                                          &server_maker_));

  EXPECT_EQ(static_cast<int64_t>(strlen(kResponseBody)), cb2.WaitForResult());

  std::string expected_body(kResponseBody);
  expected_body.append(kResponseBody);
  EXPECT_EQ(expected_body, delegate->data_received());

  EXPECT_THAT(delegate->ReadData(cb.callback()), IsOk());
  EXPECT_EQ(2, delegate->on_data_read_count());
  EXPECT_EQ(2, delegate->on_data_sent_count());
  EXPECT_EQ(NextProto::kProtoQUIC, delegate->GetProtocol());
  EXPECT_EQ(static_cast<int64_t>(spdy_request_headers_frame_length +
                                 2 * strlen(kUploadData) + 2 * header.length()),
            delegate->GetTotalSentBytes());
  EXPECT_EQ(
      static_cast<int64_t>(spdy_response_headers_frame_length +
                           2 * strlen(kResponseBody) + 2 * header2.length()),
      delegate->GetTotalReceivedBytes());
}

TEST_P(BidirectionalStreamQuicImplTest, ServerSendsRstAfterHeaders) {
  SetRequest("GET", "/", DEFAULT_PRIORITY);
  size_t spdy_request_headers_frame_length;
  client_maker_.SetEncryptionLevel(quic::ENCRYPTION_ZERO_RTT);
  AddWrite(ConstructInitialSettingsPacket());
  AddWrite(ConstructRequestHeadersPacketInner(
      GetNthClientInitiatedBidirectionalStreamId(0), kFin, DEFAULT_PRIORITY,
      &spdy_request_headers_frame_length));
  client_maker_.SetEncryptionLevel(quic::ENCRYPTION_FORWARD_SECURE);
  Initialize();

  BidirectionalStreamRequestInfo request;
  request.method = "GET";
  request.url = GURL("http://www.google.com/");
  request.end_stream_on_headers = true;
  request.priority = DEFAULT_PRIORITY;

  auto read_buffer = base::MakeRefCounted<IOBufferWithSize>(kReadBufferSize);
  auto delegate =
      std::make_unique<TestDelegateBase>(read_buffer.get(), kReadBufferSize);
  delegate->Start(&request, net_log_with_source(),
                  session()->CreateHandle(destination_));
  delegate->WaitUntilNextCallback(kOnStreamReady);
  ConfirmHandshake();

  // Server sends a Rst. Since the stream has sent fin, the rst is one way in
  // IETF QUIC.
  ProcessPacket(
      server_maker_.Packet(1)
          .AddRstStreamFrame(GetNthClientInitiatedBidirectionalStreamId(0),
                             quic::QUIC_STREAM_CANCELLED)
          .Build());

  delegate->WaitUntilNextCallback(kOnFailed);

  TestCompletionCallback cb;
  EXPECT_THAT(delegate->ReadData(cb.callback()),
              IsError(ERR_QUIC_PROTOCOL_ERROR));

  base::RunLoop().RunUntilIdle();

  EXPECT_THAT(delegate->error(), IsError(ERR_QUIC_PROTOCOL_ERROR));
  EXPECT_EQ(0, delegate->on_data_read_count());
  EXPECT_EQ(0, delegate->on_data_sent_count());
  EXPECT_EQ(static_cast<int64_t>(spdy_request_headers_frame_length),
            delegate->GetTotalSentBytes());
  EXPECT_EQ(0, delegate->GetTotalReceivedBytes());
}

TEST_P(BidirectionalStreamQuicImplTest, ServerSendsRstAfterReadData) {
  SetRequest("GET", "/", DEFAULT_PRIORITY);
  size_t spdy_request_headers_frame_length;
  client_maker_.SetEncryptionLevel(quic::ENCRYPTION_ZERO_RTT);
  AddWrite(ConstructInitialSettingsPacket());
  AddWrite(ConstructRequestHeadersPacketInner(
      GetNthClientInitiatedBidirectionalStreamId(0), kFin, DEFAULT_PRIORITY,
      &spdy_request_headers_frame_length));
  client_maker_.SetEncryptionLevel(quic::ENCRYPTION_FORWARD_SECURE);
  // Why does QUIC ack Rst? Is this expected?
  AddWrite(ConstructClientAckPacket(3, 1));

  Initialize();

  BidirectionalStreamRequestInfo request;
  request.method = "GET";
  request.url = GURL("http://www.google.com/");
  request.end_stream_on_headers = true;
  request.priority = DEFAULT_PRIORITY;

  auto read_buffer = base::MakeRefCounted<IOBufferWithSize>(kReadBufferSize);
  auto delegate =
      std::make_unique<TestDelegateBase>(read_buffer.get(), kReadBufferSize);
  delegate->Start(&request, net_log_with_source(),
                  session()->CreateHandle(destination_));
  delegate->WaitUntilNextCallback(kOnStreamReady);
  ConfirmHandshake();

  // Server acks the request.
  ProcessPacket(ConstructServerAckPacket(1, 1, 1, 1));

  // Server sends the response headers.
  quiche::HttpHeaderBlock response_headers = ConstructResponseHeaders("200");

  size_t spdy_response_headers_frame_length;
  ProcessPacket(
      ConstructResponseHeadersPacket(2, !kFin, std::move(response_headers),
                                     &spdy_response_headers_frame_length));

  delegate->WaitUntilNextCallback(kOnHeadersReceived);
  EXPECT_EQ("200", delegate->response_headers().find(":status")->second);

  TestCompletionCallback cb;
  int rv = delegate->ReadData(cb.callback());
  EXPECT_THAT(rv, IsError(ERR_IO_PENDING));

  // Server sends a Rst. Since the stream has sent fin, the rst is one way in
  // IETF QUIC.
  ProcessPacket(
      server_maker_.Packet(3)
          .AddRstStreamFrame(GetNthClientInitiatedBidirectionalStreamId(0),
                             quic::QUIC_STREAM_CANCELLED)
          .Build());

  delegate->WaitUntilNextCallback(kOnFailed);

  EXPECT_THAT(delegate->ReadData(cb.callback()),
              IsError(ERR_QUIC_PROTOCOL_ERROR));
  EXPECT_THAT(delegate->error(), IsError(ERR_QUIC_PROTOCOL_ERROR));
  EXPECT_EQ(0, delegate->on_data_read_count());
  EXPECT_EQ(0, delegate->on_data_sent_count());
  EXPECT_EQ(static_cast<int64_t>(spdy_request_headers_frame_length),
            delegate->GetTotalSentBytes());
  EXPECT_EQ(static_cast<int64_t>(spdy_response_headers_frame_length),
            delegate->GetTotalReceivedBytes());
}

TEST_P(BidirectionalStreamQuicImplTest, SessionClosedBeforeReadData) {
  SetRequest("POST", "/", DEFAULT_PRIORITY);
  size_t spdy_request_headers_frame_length;
  client_maker_.SetEncryptionLevel(quic::ENCRYPTION_ZERO_RTT);
  AddWrite(ConstructInitialSettingsPacket());
  client_maker_.SetEncryptionLevel(quic::ENCRYPTION_FORWARD_SECURE);
  AddWrite(ConstructRequestHeadersPacketInner(
      GetNthClientInitiatedBidirectionalStreamId(0), !kFin, DEFAULT_PRIORITY,
      &spdy_request_headers_frame_length));
  Initialize();

  BidirectionalStreamRequestInfo request;
  request.method = "POST";
  request.url = GURL("http://www.google.com/");
  request.end_stream_on_headers = false;
  request.priority = DEFAULT_PRIORITY;

  auto read_buffer = base::MakeRefCounted<IOBufferWithSize>(kReadBufferSize);
  auto delegate =
      std::make_unique<TestDelegateBase>(read_buffer.get(), kReadBufferSize);
  delegate->Start(&request, net_log_with_source(),
                  session()->CreateHandle(destination_));
  ConfirmHandshake();
  delegate->WaitUntilNextCallback(kOnStreamReady);

  // Server acks the request.
  ProcessPacket(ConstructServerAckPacket(1, 1, 1, 1));

  // Server sends the response headers.
  quiche::HttpHeaderBlock response_headers = ConstructResponseHeaders("200");

  size_t spdy_response_headers_frame_length;
  ProcessPacket(
      ConstructResponseHeadersPacket(2, !kFin, std::move(response_headers),
                                     &spdy_response_headers_frame_length));

  delegate->WaitUntilNextCallback(kOnHeadersReceived);
  TestCompletionCallback cb;
  int rv = delegate->ReadData(cb.callback());
  EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
  session()->connection()->CloseConnection(
      quic::QUIC_NO_ERROR, "test", quic::ConnectionCloseBehavior::SILENT_CLOSE);
  delegate->WaitUntilNextCallback(kOnFailed);

  // Try to send data after OnFailed(), should not get called back.
  scoped_refptr<StringIOBuffer> buf =
      base::MakeRefCounted<StringIOBuffer>(kUploadData);
  delegate->SendData(buf, buf->size(), false);

  EXPECT_THAT(delegate->ReadData(cb.callback()),
              IsError(ERR_QUIC_PROTOCOL_ERROR));
  EXPECT_THAT(delegate->error(), IsError(ERR_QUIC_PROTOCOL_ERROR));
  EXPECT_EQ(0, delegate->on_data_read_count());
  EXPECT_EQ(0, delegate->on_data_sent_count());
  EXPECT_EQ(NextProto::kProtoQUIC, delegate->GetProtocol());
  EXPECT_EQ(static_cast<int64_t>(spdy_request_headers_frame_length),
            delegate->GetTotalSentBytes());
  EXPECT_EQ(static_cast<int64_t>(spdy_response_headers_frame_length),
            delegate->GetTotalReceivedBytes());
}

TEST_P(BidirectionalStreamQuicImplTest, SessionClosedBeforeStartConfirmed) {
  SetRequest("POST", "/", DEFAULT_PRIORITY);
  Initialize();

  BidirectionalStreamRequestInfo request;
  request.method = "POST";
  request.url = GURL("http://www.google.com/");
  request.end_stream_on_headers = false;
  request.priority = DEFAULT_PRIORITY;

  ConfirmHandshake();
  session()->connection()->CloseConnection(
      quic::QUIC_NO_ERROR, "test", quic::ConnectionCloseBehavior::SILENT_CLOSE);

  auto read_buffer = base::MakeRefCounted<IOBufferWithSize>(kReadBufferSize);
  auto delegate =
      std::make_unique<TestDelegateBase>(read_buffer.get(), kReadBufferSize);
  delegate->Start(&request, net_log_with_source(),
                  session()->CreateHandle(destination_));
  delegate->WaitUntilNextCallback(kOnFailed);
  EXPECT_TRUE(delegate->on_failed_called());
  EXPECT_THAT(delegate->error(), IsError(ERR_CONNECTION_CLOSED));
}

TEST_P(BidirectionalStreamQuicImplTest, SessionClosedBeforeStartNotConfirmed) {
  SetRequest("POST", "/", DEFAULT_PRIORITY);
  Initialize();

  session()->connection()->CloseConnection(
      quic::QUIC_NO_ERROR, "test", quic::ConnectionCloseBehavior::SILENT_CLOSE);

  BidirectionalStreamRequestInfo request;
  request.method = "POST";
  request.url = GURL("http://www.google.com/");
  request.end_stream_on_headers = false;
  request.priority = DEFAULT_PRIORITY;

  auto read_buffer = base::MakeRefCounted<IOBufferWithSize>(kReadBufferSize);
  auto delegate =
      std::make_unique<TestDelegateBase>(read_buffer.get(), kReadBufferSize);
  delegate->Start(&request, net_log_with_source(),
                  session()->CreateHandle(destination_));
  delegate->WaitUntilNextCallback(kOnFailed);
  EXPECT_TRUE(delegate->on_failed_called());
  EXPECT_THAT(delegate->error(), IsError(ERR_QUIC_HANDSHAKE_FAILED));
}

TEST_P(BidirectionalStreamQuicImplTest, SessionCloseDuringOnStreamReady) {
  SetRequest("POST", "/", DEFAULT_PRIORITY);
  client_maker_.SetEncryptionLevel(quic::ENCRYPTION_ZERO_RTT);
  AddWrite(ConstructInitialSettingsPacket());
  AddWriteError(SYNCHRONOUS, ERR_CONNECTION_REFUSED);

  Initialize();

  BidirectionalStreamRequestInfo request;
  request.method = "POST";
  request.url = GURL("http://www.google.com/");
  request.end_stream_on_headers = false;
  request.priority = DEFAULT_PRIORITY;

  auto read_buffer = base::MakeRefCounted<IOBufferWithSize>(kReadBufferSize);
  auto delegate = std::make_unique<DeleteStreamDelegate>(
      read_buffer.get(), kReadBufferSize, DeleteStreamDelegate::ON_FAILED);
  delegate->Start(&request, net_log_with_source(),
                  session()->CreateHandle(destination_));
  ConfirmHandshake();
  delegate->WaitUntilNextCallback(kOnFailed);

  EXPECT_EQ(0, delegate->on_data_read_count());
  EXPECT_EQ(0, delegate->on_data_sent_count());
}

TEST_P(BidirectionalStreamQuicImplTest, DeleteStreamDuringOnStreamReady) {
  SetRequest("POST", "/", DEFAULT_PRIORITY);
  size_t spdy_request_headers_frame_length;
  client_maker_.SetEncryptionLevel(quic::ENCRYPTION_ZERO_RTT);
  AddWrite(ConstructInitialSettingsPacket());
  client_maker_.SetEncryptionLevel(quic::ENCRYPTION_FORWARD_SECURE);
  AddWrite(ConstructRequestHeadersPacketInner(
      GetNthClientInitiatedBidirectionalStreamId(0), !kFin, DEFAULT_PRIORITY,
      &spdy_request_headers_frame_length));
  AddWrite(ConstructClientEarlyRstStreamPacket());

  Initialize();

  BidirectionalStreamRequestInfo request;
  request.method = "POST";
  request.url = GURL("http://www.google.com/");
  request.end_stream_on_headers = false;
  request.priority = DEFAULT_PRIORITY;

  auto read_buffer = base::MakeRefCounted<IOBufferWithSize>(kReadBufferSize);
  auto delegate = std::make_unique<DeleteStreamDelegate>(
      read_buffer.get(), kReadBufferSize,
      DeleteStreamDelegate::ON_STREAM_READY);
  delegate->Start(&request, net_log_with_source(),
                  session()->CreateHandle(destination_));
  ConfirmHandshake();
  delegate->WaitUntilNextCallback(kOnStreamReady);

  EXPECT_EQ(0, delegate->on_data_read_count());
  EXPECT_EQ(0, delegate->on_data_sent_count());
}

TEST_P(BidirectionalStreamQuicImplTest, DeleteStreamAfterReadData) {
  SetRequest("POST", "/", DEFAULT_PRIORITY);
  size_t spdy_request_headers_frame_length;
  client_maker_.SetEncryptionLevel(quic::ENCRYPTION_ZERO_RTT);
  AddWrite(ConstructInitialSettingsPacket());
  client_maker_.SetEncryptionLevel(quic::ENCRYPTION_FORWARD_SECURE);
  AddWrite(ConstructRequestHeadersPacketInner(
      GetNthClientInitiatedBidirectionalStreamId(0), !kFin, DEFAULT_PRIORITY,
      &spdy_request_headers_frame_length));
  AddWrite(ConstructClientAckAndRstStreamPacket(2, 1));

  Initialize();

  BidirectionalStreamRequestInfo request;
  request.method = "POST";
  request.url = GURL("http://www.google.com/");
  request.end_stream_on_headers = false;
  request.priority = DEFAULT_PRIORITY;

  auto read_buffer = base::MakeRefCounted<IOBufferWithSize>(kReadBufferSize);
  auto delegate =
      std::make_unique<TestDelegateBase>(read_buffer.get(), kReadBufferSize);
  delegate->Start(&request, net_log_with_source(),
                  session()->CreateHandle(destination_));
  ConfirmHandshake();
  delegate->WaitUntilNextCallback(kOnStreamReady);

  // Server acks the request.
  ProcessPacket(ConstructServerAckPacket(1, 1, 1, 1));

  // Server sends the response headers.
  quiche::HttpHeaderBlock response_headers = ConstructResponseHeaders("200");
  size_t spdy_response_headers_frame_length;
  ProcessPacket(
      ConstructResponseHeadersPacket(2, !kFin, std::move(response_headers),
                                     &spdy_response_headers_frame_length));

  delegate->WaitUntilNextCallback(kOnHeadersReceived);
  EXPECT_EQ("200", delegate->response_headers().find(":status")->second);

  // Cancel the stream after ReadData returns ERR_IO_PENDING.
  TestCompletionCallback cb;
  EXPECT_THAT(delegate->ReadData(cb.callback()), IsError(ERR_IO_PENDING));
  delegate->DeleteStream();

  base::RunLoop().RunUntilIdle();

  EXPECT_EQ(0, delegate->on_data_read_count());
  EXPECT_EQ(0, delegate->on_data_sent_count());
  EXPECT_EQ(NextProto::kProtoQUIC, delegate->GetProtocol());
  EXPECT_EQ(static_cast<int64_t>(spdy_request_headers_frame_length),
            delegate->GetTotalSentBytes());
  EXPECT_EQ(static_cast<int64_t>(spdy_response_headers_frame_length),
            delegate->GetTotalReceivedBytes());
}

TEST_P(BidirectionalStreamQuicImplTest, DeleteStreamDuringOnHeadersReceived) {
  SetRequest("POST", "/", DEFAULT_PRIORITY);
  size_t spdy_request_headers_frame_length;
  client_maker_.SetEncryptionLevel(quic::ENCRYPTION_ZERO_RTT);
  AddWrite(ConstructInitialSettingsPacket());
  client_maker_.SetEncryptionLevel(quic::ENCRYPTION_FORWARD_SECURE);
  AddWrite(ConstructRequestHeadersPacketInner(
      GetNthClientInitiatedBidirectionalStreamId(0), !kFin, DEFAULT_PRIORITY,
      &spdy_request_headers_frame_length));
  AddWrite(ConstructClientAckAndRstStreamPacket(2, 1));

  Initialize();

  BidirectionalStreamRequestInfo request;
  request.method = "POST";
  request.url = GURL("http://www.google.com/");
  request.end_stream_on_headers = false;
  request.priority = DEFAULT_PRIORITY;

  auto read_buffer = base::MakeRefCounted<IOBufferWithSize>(kReadBufferSize);
  auto delegate = std::make_unique<DeleteStreamDelegate>(
      read_buffer.get(), kReadBufferSize,
      DeleteStreamDelegate::ON_HEADERS_RECEIVED);
  delegate->Start(&request, net_log_with_source(),
                  session()->CreateHandle(destination_));
  ConfirmHandshake();
  delegate->WaitUntilNextCallback(kOnStreamReady);

  // Server acks the request.
  ProcessPacket(ConstructServerAckPacket(1, 1, 1, 1));

  // Server sends the response headers.
  quiche::HttpHeaderBlock response_headers = ConstructResponseHeaders("200");

  size_t spdy_response_headers_frame_length;
  ProcessPacket(
      ConstructResponseHeadersPacket(2, !kFin, std::move(response_headers),
                                     &spdy_response_headers_frame_length));

  delegate->WaitUntilNextCallback(kOnHeadersReceived);
  EXPECT_EQ("200", delegate->response_headers().find(":status")->second);

  base::RunLoop().RunUntilIdle();

  EXPECT_EQ(0, delegate->on_data_read_count());
  EXPECT_EQ(0, delegate->on_data_sent_count());
}

TEST_P(BidirectionalStreamQuicImplTest, DeleteStreamDuringOnDataRead) {
  SetRequest("POST", "/", DEFAULT_PRIORITY);
  size_t spdy_request_headers_frame_length;
  client_maker_.SetEncryptionLevel(quic::ENCRYPTION_ZERO_RTT);
  AddWrite(ConstructInitialSettingsPacket());
  client_maker_.SetEncryptionLevel(quic::ENCRYPTION_FORWARD_SECURE);
  AddWrite(ConstructRequestHeadersPacketInner(
      GetNthClientInitiatedBidirectionalStreamId(0), !kFin, DEFAULT_PRIORITY,
      &spdy_request_headers_frame_length));
  AddWrite(ConstructClientAckPacket(3, 1));
  AddWrite(ConstructClientRstStreamPacket());

  Initialize();

  BidirectionalStreamRequestInfo request;
  request.method = "POST";
  request.url = GURL("http://www.google.com/");
  request.end_stream_on_headers = false;
  request.priority = DEFAULT_PRIORITY;

  auto read_buffer = base::MakeRefCounted<IOBufferWithSize>(kReadBufferSize);
  auto delegate = std::make_unique<DeleteStreamDelegate>(
      read_buffer.get(), kReadBufferSize, DeleteStreamDelegate::ON_DATA_READ);
  delegate->Start(&request, net_log_with_source(),
                  session()->CreateHandle(destination_));
  ConfirmHandshake();
  delegate->WaitUntilNextCallback(kOnStreamReady);

  // Server acks the request.
  ProcessPacket(ConstructServerAckPacket(1, 1, 1, 1));

  // Server sends the response headers.
  quiche::HttpHeaderBlock response_headers = ConstructResponseHeaders("200");

  size_t spdy_response_headers_frame_length;
  ProcessPacket(
      ConstructResponseHeadersPacket(2, !kFin, std::move(response_headers),
                                     &spdy_response_headers_frame_length));

  delegate->WaitUntilNextCallback(kOnHeadersReceived);

  EXPECT_EQ("200", delegate->response_headers().find(":status")->second);

  TestCompletionCallback cb;
  int rv = delegate->ReadData(cb.callback());
  EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
  const char kResponseBody[] = "Hello world!";
  std::string header = ConstructDataHeader(strlen(kResponseBody));
  // Server sends data.
  ProcessPacket(ConstructServerDataPacket(3, !kFin, header + kResponseBody));
  EXPECT_EQ(static_cast<int64_t>(strlen(kResponseBody)), cb.WaitForResult());

  base::RunLoop().RunUntilIdle();

  EXPECT_EQ(1, delegate->on_data_read_count());
  EXPECT_EQ(0, delegate->on_data_sent_count());
}

TEST_P(BidirectionalStreamQuicImplTest, AsyncFinRead) {
  const char kBody[] = "here is some data";
  SetRequest("POST", "/", DEFAULT_PRIORITY);
  size_t spdy_request_headers_frame_length;
  client_maker_.SetEncryptionLevel(quic::ENCRYPTION_ZERO_RTT);
  AddWrite(ConstructInitialSettingsPacket());
  client_maker_.SetEncryptionLevel(quic::ENCRYPTION_FORWARD_SECURE);
  AddWrite(ConstructRequestHeadersPacketInner(
      GetNthClientInitiatedBidirectionalStreamId(0), !kFin, DEFAULT_PRIORITY,
      &spdy_request_headers_frame_length));
  std::string header = ConstructDataHeader(strlen(kBody));
  AddWrite(ConstructClientDataPacket(kFin, header + kBody));
  AddWrite(ConstructClientAckPacket(3, 1));

  Initialize();

  BidirectionalStreamRequestInfo request;
  request.method = "POST";
  request.url = GURL("http://www.google.com/");
  request.end_stream_on_headers = false;
  request.priority = DEFAULT_PRIORITY;

  auto read_buffer = base::MakeRefCounted<IOBufferWithSize>(kReadBufferSize);
  auto delegate =
      std::make_unique<TestDelegateBase>(read_buffer.get(), kReadBufferSize);

  delegate->Start(&request, net_log_with_source(),
                  session()->CreateHandle(destination_));
  ConfirmHandshake();
  delegate->WaitUntilNextCallback(kOnStreamReady);

  // Send a Data packet with fin set.
  scoped_refptr<StringIOBuffer> buf1 =
      base::MakeRefCounted<StringIOBuffer>(kBody);
  delegate->SendData(buf1, buf1->size(), /*fin*/ true);
  delegate->WaitUntilNextCallback(kOnDataSent);

  // Server acks the request.
  ProcessPacket(ConstructServerAckPacket(1, 1, 1, 1));

  // Server sends the response headers.
  quiche::HttpHeaderBlock response_headers = ConstructResponseHeaders("200");

  size_t spdy_response_headers_frame_length;
  ProcessPacket(
      ConstructResponseHeadersPacket(2, !kFin, std::move(response_headers),
                                     &spdy_response_headers_frame_length));

  delegate->WaitUntilNextCallback(kOnHeadersReceived);

  EXPECT_EQ("200", delegate->response_headers().find(":status")->second);

  // Read the body, which will complete asynchronously.
  TestCompletionCallback cb;
  int rv = delegate->ReadData(cb.callback());
  EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
  const char kResponseBody[] = "Hello world!";
  std::string header2 = ConstructDataHeader(strlen(kResponseBody));

  // Server sends data with the fin set, which should result in the stream
  // being closed and hence no RST_STREAM will be sent.
  ProcessPacket(ConstructServerDataPacket(3, kFin, header2 + kResponseBody));
  EXPECT_EQ(static_cast<int64_t>(strlen(kResponseBody)), cb.WaitForResult());

  base::RunLoop().RunUntilIdle();

  EXPECT_EQ(1, delegate->on_data_read_count());
  EXPECT_EQ(1, delegate->on_data_sent_count());
}

TEST_P(BidirectionalStreamQuicImplTest, DeleteStreamDuringOnTrailersReceived) {
  SetRequest("GET", "/", DEFAULT_PRIORITY);
  size_t spdy_request_headers_frame_length;
  client_maker_.SetEncryptionLevel(quic::ENCRYPTION_ZERO_RTT);
  AddWrite(ConstructInitialSettingsPacket());
  client_maker_.SetEncryptionLevel(quic::ENCRYPTION_FORWARD_SECURE);
  AddWrite(ConstructRequestHeadersPacket(kFin, DEFAULT_PRIORITY,
                                         &spdy_request_headers_frame_length));
  AddWrite(ConstructClientAckPacket(3, 1));  // Ack the data packet
  AddWrite(ConstructClientAckAndRstStreamPacket(4, 4));

  Initialize();

  BidirectionalStreamRequestInfo request;
  request.method = "GET";
  request.url = GURL("http://www.google.com/");
  request.end_stream_on_headers = true;
  request.priority = DEFAULT_PRIORITY;

  auto read_buffer = base::MakeRefCounted<IOBufferWithSize>(kReadBufferSize);
  auto delegate = std::make_unique<DeleteStreamDelegate>(
      read_buffer.get(), kReadBufferSize,
      DeleteStreamDelegate::ON_TRAILERS_RECEIVED);
  delegate->Start(&request, net_log_with_source(),
                  session()->CreateHandle(destination_));
  ConfirmHandshake();
  delegate->WaitUntilNextCallback(kOnStreamReady);

  // Server acks the request.
  ProcessPacket(ConstructServerAckPacket(1, 1, 1, 1));

  // Server sends the response headers.
  quiche::HttpHeaderBlock response_headers = ConstructResponseHeaders("200");

  size_t spdy_response_headers_frame_length;
  ProcessPacket(
      ConstructResponseHeadersPacket(2, !kFin, std::move(response_headers),
                                     &spdy_response_headers_frame_length));

  delegate->WaitUntilNextCallback(kOnHeadersReceived);

  EXPECT_EQ("200", delegate->response_headers().find(":status")->second);

  TestCompletionCallback cb;
  int rv = delegate->ReadData(cb.callback());
  EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
  const char kResponseBody[] = "Hello world!";

  // Server sends data.
  std::string header = ConstructDataHeader(strlen(kResponseBody));
  ProcessPacket(ConstructServerDataPacket(3, !kFin, header + kResponseBody));

  EXPECT_EQ(static_cast<int64_t>(strlen(kResponseBody)), cb.WaitForResult());
  EXPECT_EQ(std::string(kResponseBody), delegate->data_received());

  size_t spdy_trailers_frame_length;
  quiche::HttpHeaderBlock trailers;
  trailers["foo"] = "bar";
  // Server sends trailers.
  ProcessPacket(ConstructResponseTrailersPacket(4, kFin, trailers.Clone(),
                                                &spdy_trailers_frame_length));

  delegate->WaitUntilNextCallback(kOnTrailersReceived);
  EXPECT_EQ(trailers, delegate->trailers());

  base::RunLoop().RunUntilIdle();

  EXPECT_EQ(1, delegate->on_data_read_count());
  EXPECT_EQ(0, delegate->on_data_sent_count());
}

// Tests that if QuicChromiumClientSession is closed after
// BidirectionalStreamQuicImpl::OnStreamReady() but before
// QuicChromiumClientSession::Handle::ReleaseStream() is called, there is no
// crash. Regression test for crbug.com/754823.
TEST_P(BidirectionalStreamQuicImplTest, ReleaseStreamFails) {
  SetRequest("GET", "/", DEFAULT_PRIORITY);
  Initialize();

  ConfirmHandshake();

  BidirectionalStreamRequestInfo request;
  request.method = "GET";
  request.url = GURL("http://www.google.com/");
  request.end_stream_on_headers = true;
  request.priority = DEFAULT_PRIORITY;

  auto read_buffer = base::MakeRefCounted<IOBufferWithSize>(kReadBufferSize);
  auto delegate =
      std::make_unique<TestDelegateBase>(read_buffer.get(), kReadBufferSize);
  delegate->set_trailers_expected(true);
  // QuicChromiumClientSession::Handle::RequestStream() returns OK synchronously
  // because Initialize() has established a Session.
  delegate->Start(&request, net_log_with_source(),
                  session()->CreateHandle(destination_));
  // Now closes the underlying session.
  session_->CloseSessionOnError(ERR_ABORTED, quic::QUIC_INTERNAL_ERROR,
                                quic::ConnectionCloseBehavior::SILENT_CLOSE);
  delegate->WaitUntilNextCallback(kOnFailed);

  EXPECT_THAT(delegate->error(), IsError(ERR_CONNECTION_CLOSED));
}

}  // namespace net::test
