/*
 *  Copyright 2016 The WebRTC Project Authors. All rights reserved.
 *
 *  Use of this source code is governed by a BSD-style license
 *  that can be found in the LICENSE file in the root of the source
 *  tree. An additional intellectual property rights grant can be found
 *  in the file PATENTS.  All contributing project authors may
 *  be found in the AUTHORS file in the root of the source tree.
 */

#include "webrtc/p2p/quic/quictransportchannel.h"

#include <memory>
#include <set>
#include <string>
#include <vector>

#include "webrtc/base/gunit.h"
#include "webrtc/base/sslidentity.h"
#include "webrtc/p2p/base/faketransportcontroller.h"

using cricket::ConnectionRole;
using cricket::IceRole;
using cricket::QuicTransportChannel;
using cricket::ReliableQuicStream;
using cricket::TransportChannel;
using cricket::TransportDescription;

// Timeout in milliseconds for asynchronous operations in unit tests.
static const int kTimeoutMs = 1000;

// Export keying material parameters.
static const char kExporterLabel[] = "label";
static const uint8_t kExporterContext[] = "context";
static const size_t kExporterContextLength = sizeof(kExporterContext);
static const size_t kOutputKeyLength = 20;

// Packet size for SRTP.
static const size_t kPacketSize = 100;

// Indicates ICE channel has no write error.
static const int kNoWriteError = 0;

// ICE parameters.
static const char kIceUfrag[] = "TESTICEUFRAG0001";
static const char kIcePwd[] = "TESTICEPWD00000000000001";

// QUIC packet parameters.
static const net::IPAddress kIpAddress(0, 0, 0, 0);
static const net::IPEndPoint kIpEndpoint(kIpAddress, 0);

// Detects incoming RTP packets.
static bool IsRtpLeadByte(uint8_t b) {
  return (b & 0xC0) == 0x80;
}

// Maps SSL role to ICE connection role. The peer with a client role is assumed
// to be the one who initiates the connection.
static ConnectionRole SslRoleToConnectionRole(rtc::SSLRole ssl_role) {
  return (ssl_role == rtc::SSL_CLIENT) ? cricket::CONNECTIONROLE_ACTIVE
                                       : cricket::CONNECTIONROLE_PASSIVE;
}

// Allows cricket::FakeTransportChannel to simulate write blocked
// and write error states.
// TODO(mikescarlett): Add this functionality to cricket::FakeTransportChannel.
class FailableTransportChannel : public cricket::FakeTransportChannel {
 public:
  FailableTransportChannel(const std::string& name, int component)
      : cricket::FakeTransportChannel(name, component), error_(kNoWriteError) {}
  int GetError() override { return error_; }
  void SetError(int error) { error_ = error; }
  int SendPacket(const char* data,
                 size_t len,
                 const rtc::PacketOptions& options,
                 int flags) override {
    if (error_ == kNoWriteError) {
      return cricket::FakeTransportChannel::SendPacket(data, len, options,
                                                       flags);
    }
    return -1;
  }

 private:
  int error_;
};

// Peer who establishes a handshake using a QuicTransportChannel, which wraps
// a FailableTransportChannel to simulate network connectivity and ICE
// negotiation.
class QuicTestPeer : public sigslot::has_slots<> {
 public:
  explicit QuicTestPeer(const std::string& name)
      : name_(name),
        bytes_sent_(0),
        ice_channel_(new FailableTransportChannel(name_, 0)),
        quic_channel_(ice_channel_),
        incoming_stream_count_(0) {
    quic_channel_.SignalReadPacket.connect(
        this, &QuicTestPeer::OnTransportChannelReadPacket);
    quic_channel_.SignalIncomingStream.connect(this,
                                               &QuicTestPeer::OnIncomingStream);
    quic_channel_.SignalClosed.connect(this, &QuicTestPeer::OnClosed);
    ice_channel_->SetAsync(true);
    rtc::scoped_refptr<rtc::RTCCertificate> local_cert =
        rtc::RTCCertificate::Create(std::unique_ptr<rtc::SSLIdentity>(
            rtc::SSLIdentity::Generate(name_, rtc::KT_DEFAULT)));
    quic_channel_.SetLocalCertificate(local_cert);
    local_fingerprint_.reset(CreateFingerprint(local_cert.get()));
  }

  // Connects |ice_channel_| to that of the other peer.
  void Connect(QuicTestPeer* other_peer) {
    ice_channel_->SetDestination(other_peer->ice_channel_);
  }

  // Disconnects |ice_channel_|.
  void Disconnect() { ice_channel_->SetDestination(nullptr); }

  // Generates ICE credentials and passes them to |quic_channel_|.
  void SetIceParameters(IceRole local_ice_role,
                        ConnectionRole local_connection_role,
                        ConnectionRole remote_connection_role,
                        rtc::SSLFingerprint* remote_fingerprint) {
    quic_channel_.SetIceRole(local_ice_role);
    quic_channel_.SetIceTiebreaker(
        (local_ice_role == cricket::ICEROLE_CONTROLLING) ? 1 : 2);

    TransportDescription local_desc(
        std::vector<std::string>(), kIceUfrag, kIcePwd, cricket::ICEMODE_FULL,
        local_connection_role, local_fingerprint_.get());
    TransportDescription remote_desc(
        std::vector<std::string>(), kIceUfrag, kIcePwd, cricket::ICEMODE_FULL,
        remote_connection_role, remote_fingerprint);

    quic_channel_.SetIceParameters(local_desc.GetIceParameters());
    quic_channel_.SetRemoteIceParameters(remote_desc.GetIceParameters());
  }

  // Creates fingerprint from certificate.
  rtc::SSLFingerprint* CreateFingerprint(rtc::RTCCertificate* cert) {
    std::string digest_algorithm;
    bool get_digest_algorithm =
        cert->ssl_certificate().GetSignatureDigestAlgorithm(&digest_algorithm);
    if (!get_digest_algorithm || digest_algorithm.empty()) {
      return nullptr;
    }
    std::unique_ptr<rtc::SSLFingerprint> fingerprint(
        rtc::SSLFingerprint::Create(digest_algorithm, cert->identity()));
    if (digest_algorithm != rtc::DIGEST_SHA_256) {
      return nullptr;
    }
    return fingerprint.release();
  }

  // Sends SRTP packet to the other peer via |quic_channel_|.
  int SendSrtpPacket() {
    char packet[kPacketSize];
    packet[0] = 0x80;  // Make the packet header look like RTP.
    int rv = quic_channel_.SendPacket(
        &packet[0], kPacketSize, rtc::PacketOptions(), cricket::PF_SRTP_BYPASS);
    bytes_sent_ += rv;
    return rv;
  }

  // Sends a non-SRTP packet with the PF_SRTP_BYPASS flag via |quic_channel_|.
  int SendInvalidSrtpPacket() {
    char packet[kPacketSize];
    // Fill the packet with 0 to form an invalid SRTP packet.
    memset(packet, 0, kPacketSize);
    return quic_channel_.SendPacket(
        &packet[0], kPacketSize, rtc::PacketOptions(), cricket::PF_SRTP_BYPASS);
  }

  // Sends an RTP packet to the other peer via |quic_channel_|, without the SRTP
  // bypass flag.
  int SendRtpPacket() {
    char packet[kPacketSize];
    packet[0] = 0x80;  // Make the packet header look like RTP.
    return quic_channel_.SendPacket(&packet[0], kPacketSize,
                                    rtc::PacketOptions(), 0);
  }

  void ClearBytesSent() { bytes_sent_ = 0; }

  void ClearBytesReceived() { bytes_received_ = 0; }

  void SetWriteError(int error) { ice_channel_->SetError(error); }

  size_t bytes_received() const { return bytes_received_; }

  size_t bytes_sent() const { return bytes_sent_; }

  FailableTransportChannel* ice_channel() { return ice_channel_; }

  QuicTransportChannel* quic_channel() { return &quic_channel_; }

  std::unique_ptr<rtc::SSLFingerprint>& local_fingerprint() {
    return local_fingerprint_;
  }

  ReliableQuicStream* incoming_quic_stream() { return incoming_quic_stream_; }

  size_t incoming_stream_count() const { return incoming_stream_count_; }

  bool signal_closed_emitted() const { return signal_closed_emitted_; }

 private:
  // QuicTransportChannel callbacks.
  void OnTransportChannelReadPacket(TransportChannel* channel,
                                    const char* data,
                                    size_t size,
                                    const rtc::PacketTime& packet_time,
                                    int flags) {
    bytes_received_ += size;
    // Only SRTP packets should have the bypass flag set.
    int expected_flags = IsRtpLeadByte(data[0]) ? cricket::PF_SRTP_BYPASS : 0;
    ASSERT_EQ(expected_flags, flags);
  }
  void OnIncomingStream(ReliableQuicStream* stream) {
    incoming_quic_stream_ = stream;
    ++incoming_stream_count_;
  }
  void OnClosed() { signal_closed_emitted_ = true; }

  std::string name_;                      // Channel name.
  size_t bytes_sent_;                     // Bytes sent by QUIC channel.
  size_t bytes_received_;                 // Bytes received by QUIC channel.
  FailableTransportChannel* ice_channel_;  // Simulates an ICE channel.
  QuicTransportChannel quic_channel_;     // QUIC channel to test.
  std::unique_ptr<rtc::SSLFingerprint> local_fingerprint_;
  ReliableQuicStream* incoming_quic_stream_ = nullptr;
  size_t incoming_stream_count_;
  bool signal_closed_emitted_ = false;
};

class QuicTransportChannelTest : public testing::Test {
 public:
  QuicTransportChannelTest() : peer1_("P1"), peer2_("P2") {}

  // Performs negotiation before QUIC handshake, then connects the fake
  // transport channels of each peer. As a side effect, the QUIC channels
  // start sending handshake messages. |peer1_| has a client role and |peer2_|
  // has server role in the QUIC handshake.
  void Connect() {
    SetIceAndCryptoParameters(rtc::SSL_CLIENT, rtc::SSL_SERVER);
    peer1_.Connect(&peer2_);
  }

  // Disconnects the fake transport channels.
  void Disconnect() {
    peer1_.Disconnect();
    peer2_.Disconnect();
  }

  // Sets up ICE parameters and exchanges fingerprints before QUIC handshake.
  void SetIceAndCryptoParameters(rtc::SSLRole peer1_ssl_role,
                                 rtc::SSLRole peer2_ssl_role) {
    peer1_.quic_channel()->SetSslRole(peer1_ssl_role);
    peer2_.quic_channel()->SetSslRole(peer2_ssl_role);

    std::unique_ptr<rtc::SSLFingerprint>& peer1_fingerprint =
        peer1_.local_fingerprint();
    std::unique_ptr<rtc::SSLFingerprint>& peer2_fingerprint =
        peer2_.local_fingerprint();

    peer1_.quic_channel()->SetRemoteFingerprint(
        peer2_fingerprint->algorithm,
        reinterpret_cast<const uint8_t*>(peer2_fingerprint->digest.data()),
        peer2_fingerprint->digest.size());
    peer2_.quic_channel()->SetRemoteFingerprint(
        peer1_fingerprint->algorithm,
        reinterpret_cast<const uint8_t*>(peer1_fingerprint->digest.data()),
        peer1_fingerprint->digest.size());

    ConnectionRole peer1_connection_role =
        SslRoleToConnectionRole(peer1_ssl_role);
    ConnectionRole peer2_connection_role =
        SslRoleToConnectionRole(peer2_ssl_role);

    peer1_.SetIceParameters(cricket::ICEROLE_CONTROLLED, peer1_connection_role,
                            peer2_connection_role, peer2_fingerprint.get());
    peer2_.SetIceParameters(cricket::ICEROLE_CONTROLLING, peer2_connection_role,
                            peer1_connection_role, peer1_fingerprint.get());
  }

  // Checks if QUIC handshake is done.
  bool quic_connected() {
    return peer1_.quic_channel()->quic_state() ==
               cricket::QUIC_TRANSPORT_CONNECTED &&
           peer2_.quic_channel()->quic_state() ==
               cricket::QUIC_TRANSPORT_CONNECTED;
  }

  // Checks if QUIC channels are writable.
  bool quic_writable() {
    return peer1_.quic_channel()->writable() &&
           peer2_.quic_channel()->writable();
  }

 protected:
  // QUIC peer with a client role, who initiates the QUIC handshake.
  QuicTestPeer peer1_;
  // QUIC peer with a server role, who responds to the client peer.
  QuicTestPeer peer2_;
};

// Test that the QUIC channel passes ICE parameters to the underlying ICE
// channel.
TEST_F(QuicTransportChannelTest, ChannelSetupIce) {
  SetIceAndCryptoParameters(rtc::SSL_CLIENT, rtc::SSL_SERVER);
  FailableTransportChannel* channel1 = peer1_.ice_channel();
  FailableTransportChannel* channel2 = peer2_.ice_channel();
  EXPECT_EQ(cricket::ICEROLE_CONTROLLED, channel1->GetIceRole());
  EXPECT_EQ(2u, channel1->IceTiebreaker());
  EXPECT_EQ(kIceUfrag, channel1->ice_ufrag());
  EXPECT_EQ(kIcePwd, channel1->ice_pwd());
  EXPECT_EQ(cricket::ICEROLE_CONTROLLING, channel2->GetIceRole());
  EXPECT_EQ(1u, channel2->IceTiebreaker());
}

// Test that export keying material generates identical keys for both peers
// after the QUIC handshake.
TEST_F(QuicTransportChannelTest, ExportKeyingMaterial) {
  Connect();
  ASSERT_TRUE_WAIT(quic_connected(), kTimeoutMs);
  uint8_t key1[kOutputKeyLength];
  uint8_t key2[kOutputKeyLength];

  bool from_success = peer1_.quic_channel()->ExportKeyingMaterial(
      kExporterLabel, kExporterContext, kExporterContextLength, true, key1,
      kOutputKeyLength);
  ASSERT_TRUE(from_success);
  bool to_success = peer2_.quic_channel()->ExportKeyingMaterial(
      kExporterLabel, kExporterContext, kExporterContextLength, true, key2,
      kOutputKeyLength);
  ASSERT_TRUE(to_success);

  EXPECT_EQ(0, memcmp(key1, key2, sizeof(key1)));
}

// Test that the QUIC channel is not writable before the QUIC handshake.
TEST_F(QuicTransportChannelTest, NotWritableBeforeHandshake) {
  Connect();
  EXPECT_FALSE(quic_writable());
  Disconnect();
  EXPECT_FALSE(quic_writable());
  Connect();
  EXPECT_FALSE(quic_writable());
}

// Test that once handshake begins, QUIC is not writable until its completion.
TEST_F(QuicTransportChannelTest, QuicHandshake) {
  Connect();
  EXPECT_FALSE(quic_writable());
  ASSERT_TRUE_WAIT(quic_connected(), kTimeoutMs);
  EXPECT_TRUE(quic_writable());
}

// Test that Non-SRTP data is not sent using SendPacket(), regardless of QUIC
// channel state.
TEST_F(QuicTransportChannelTest, TransferNonSrtp) {
  // Send data before ICE channel is connected.
  peer1_.ClearBytesSent();
  peer2_.ClearBytesReceived();
  ASSERT_EQ(-1, peer1_.SendRtpPacket());
  EXPECT_EQ(0u, peer1_.bytes_sent());
  // Send data after ICE channel is connected, before QUIC handshake.
  Connect();
  peer1_.ClearBytesSent();
  peer2_.ClearBytesReceived();
  ASSERT_EQ(-1, peer1_.SendRtpPacket());
  EXPECT_EQ(0u, peer1_.bytes_sent());
  // Send data after QUIC handshake.
  ASSERT_TRUE_WAIT(quic_connected(), kTimeoutMs);
  peer1_.ClearBytesSent();
  peer2_.ClearBytesReceived();
  ASSERT_EQ(-1, peer1_.SendRtpPacket());
  EXPECT_EQ(0u, peer1_.bytes_sent());
}

// Test that SRTP data is always be sent, regardless of QUIC channel state, when
// the ICE channel is connected.
TEST_F(QuicTransportChannelTest, TransferSrtp) {
  // Send data after ICE channel is connected, before QUIC handshake.
  Connect();
  peer1_.ClearBytesSent();
  peer2_.ClearBytesReceived();
  ASSERT_EQ(kPacketSize, static_cast<size_t>(peer1_.SendSrtpPacket()));
  EXPECT_EQ_WAIT(kPacketSize, peer2_.bytes_received(), kTimeoutMs);
  EXPECT_EQ(kPacketSize, peer1_.bytes_sent());
  ASSERT_TRUE_WAIT(quic_connected(), kTimeoutMs);
  // Send data after QUIC handshake.
  peer1_.ClearBytesSent();
  peer2_.ClearBytesReceived();
  ASSERT_EQ(kPacketSize, static_cast<size_t>(peer1_.SendSrtpPacket()));
  EXPECT_EQ_WAIT(kPacketSize, peer2_.bytes_received(), kTimeoutMs);
  EXPECT_EQ(kPacketSize, peer1_.bytes_sent());
}

// Test that invalid SRTP (non-SRTP data with
// PF_SRTP_BYPASS flag) fails to send with return value -1.
TEST_F(QuicTransportChannelTest, TransferInvalidSrtp) {
  peer1_.ClearBytesSent();
  peer2_.ClearBytesReceived();
  EXPECT_EQ(-1, peer1_.SendInvalidSrtpPacket());
  EXPECT_EQ(0u, peer2_.bytes_received());
  Connect();
  peer1_.ClearBytesSent();
  peer2_.ClearBytesReceived();
  EXPECT_EQ(-1, peer1_.SendInvalidSrtpPacket());
  EXPECT_EQ(0u, peer2_.bytes_received());
}

// Test that QuicTransportChannel::WritePacket blocks when the ICE
// channel is not writable, and otherwise succeeds.
TEST_F(QuicTransportChannelTest, QuicWritePacket) {
  peer1_.ice_channel()->SetDestination(peer2_.ice_channel());
  std::string packet = "FAKEQUICPACKET";

  // QUIC should be write blocked when the ICE channel is not writable.
  peer1_.ice_channel()->SetWritable(false);
  EXPECT_TRUE(peer1_.quic_channel()->IsWriteBlocked());
  net::WriteResult write_blocked_result = peer1_.quic_channel()->WritePacket(
      packet.data(), packet.size(), kIpAddress, kIpEndpoint, nullptr);
  EXPECT_EQ(net::WRITE_STATUS_BLOCKED, write_blocked_result.status);
  EXPECT_EQ(EWOULDBLOCK, write_blocked_result.error_code);

  // QUIC should ignore errors when the ICE channel is writable.
  peer1_.ice_channel()->SetWritable(true);
  EXPECT_FALSE(peer1_.quic_channel()->IsWriteBlocked());
  peer1_.SetWriteError(EWOULDBLOCK);
  net::WriteResult ignore_error_result = peer1_.quic_channel()->WritePacket(
      packet.data(), packet.size(), kIpAddress, kIpEndpoint, nullptr);
  EXPECT_EQ(net::WRITE_STATUS_OK, ignore_error_result.status);
  EXPECT_EQ(0, ignore_error_result.bytes_written);

  peer1_.SetWriteError(kNoWriteError);
  net::WriteResult no_error_result = peer1_.quic_channel()->WritePacket(
      packet.data(), packet.size(), kIpAddress, kIpEndpoint, nullptr);
  EXPECT_EQ(net::WRITE_STATUS_OK, no_error_result.status);
  EXPECT_EQ(static_cast<int>(packet.size()), no_error_result.bytes_written);
}

// Test that SSL roles can be reversed before QUIC handshake.
TEST_F(QuicTransportChannelTest, QuicRoleReversalBeforeQuic) {
  EXPECT_TRUE(peer1_.quic_channel()->SetSslRole(rtc::SSL_SERVER));
  EXPECT_TRUE(peer1_.quic_channel()->SetSslRole(rtc::SSL_CLIENT));
  EXPECT_TRUE(peer1_.quic_channel()->SetSslRole(rtc::SSL_SERVER));
}

// Test that SSL roles cannot be reversed after the QUIC handshake. SetSslRole
// returns true if the current SSL role equals the proposed SSL role.
TEST_F(QuicTransportChannelTest, QuicRoleReversalAfterQuic) {
  Connect();
  ASSERT_TRUE_WAIT(quic_connected(), kTimeoutMs);
  EXPECT_FALSE(peer1_.quic_channel()->SetSslRole(rtc::SSL_SERVER));
  EXPECT_TRUE(peer1_.quic_channel()->SetSslRole(rtc::SSL_CLIENT));
  EXPECT_FALSE(peer2_.quic_channel()->SetSslRole(rtc::SSL_CLIENT));
  EXPECT_TRUE(peer2_.quic_channel()->SetSslRole(rtc::SSL_SERVER));
}

// Set the SSL role, then test that GetSslRole returns the same value.
TEST_F(QuicTransportChannelTest, SetGetSslRole) {
  ASSERT_TRUE(peer1_.quic_channel()->SetSslRole(rtc::SSL_SERVER));
  std::unique_ptr<rtc::SSLRole> role(new rtc::SSLRole());
  ASSERT_TRUE(peer1_.quic_channel()->GetSslRole(role.get()));
  EXPECT_EQ(rtc::SSL_SERVER, *role);
}

// Test that after the QUIC handshake is complete, the QUIC handshake remains
// confirmed even if the ICE channel reconnects.
TEST_F(QuicTransportChannelTest, HandshakeConfirmedAfterReconnect) {
  Connect();
  ASSERT_TRUE_WAIT(quic_connected(), kTimeoutMs);
  Disconnect();
  EXPECT_TRUE(quic_connected());
  Connect();
  EXPECT_TRUE(quic_connected());
}

// Test that if the ICE channel becomes receiving after the QUIC channel is
// connected, then the QUIC channel becomes receiving.
TEST_F(QuicTransportChannelTest, IceReceivingAfterConnected) {
  Connect();
  ASSERT_TRUE_WAIT(quic_connected(), kTimeoutMs);
  ASSERT_FALSE(peer1_.ice_channel()->receiving());
  EXPECT_FALSE(peer1_.quic_channel()->receiving());
  peer1_.ice_channel()->SetReceiving(true);
  EXPECT_TRUE(peer1_.quic_channel()->receiving());
}

// Test that if the ICE channel becomes receiving before the QUIC channel is
// connected, then the QUIC channel becomes receiving.
TEST_F(QuicTransportChannelTest, IceReceivingBeforeConnected) {
  Connect();
  peer1_.ice_channel()->SetReceiving(true);
  ASSERT_TRUE(peer1_.ice_channel()->receiving());
  ASSERT_TRUE_WAIT(quic_connected(), kTimeoutMs);
  EXPECT_TRUE(peer1_.quic_channel()->receiving());
}

// Test that when peer 1 creates an outgoing stream, peer 2 creates an incoming
// QUIC stream with the same ID and fires OnIncomingStream.
TEST_F(QuicTransportChannelTest, CreateOutgoingAndIncomingQuicStream) {
  Connect();
  EXPECT_EQ(nullptr, peer1_.quic_channel()->CreateQuicStream());
  ASSERT_TRUE_WAIT(quic_connected(), kTimeoutMs);
  ReliableQuicStream* stream = peer1_.quic_channel()->CreateQuicStream();
  ASSERT_NE(nullptr, stream);
  stream->Write("Hi", 2);
  EXPECT_TRUE_WAIT(peer2_.incoming_quic_stream() != nullptr, kTimeoutMs);
  EXPECT_EQ(stream->id(), peer2_.incoming_quic_stream()->id());
}

// Test that if the QuicTransportChannel is unwritable, then all outgoing QUIC
// streams can send data once the QuicTransprotChannel becomes writable again.
TEST_F(QuicTransportChannelTest, OutgoingQuicStreamSendsDataAfterReconnect) {
  Connect();
  ASSERT_TRUE_WAIT(quic_connected(), kTimeoutMs);
  ReliableQuicStream* stream1 = peer1_.quic_channel()->CreateQuicStream();
  ASSERT_NE(nullptr, stream1);
  ReliableQuicStream* stream2 = peer1_.quic_channel()->CreateQuicStream();
  ASSERT_NE(nullptr, stream2);

  peer1_.ice_channel()->SetWritable(false);
  stream1->Write("First", 5);
  EXPECT_EQ(5u, stream1->queued_data_bytes());
  stream2->Write("Second", 6);
  EXPECT_EQ(6u, stream2->queued_data_bytes());
  EXPECT_EQ(0u, peer2_.incoming_stream_count());

  peer1_.ice_channel()->SetWritable(true);
  EXPECT_EQ_WAIT(0u, stream1->queued_data_bytes(), kTimeoutMs);
  EXPECT_EQ_WAIT(0u, stream2->queued_data_bytes(), kTimeoutMs);
  EXPECT_EQ_WAIT(2u, peer2_.incoming_stream_count(), kTimeoutMs);
}

// Test that SignalClosed is emitted when the QuicConnection closes.
TEST_F(QuicTransportChannelTest, SignalClosedEmitted) {
  Connect();
  ASSERT_TRUE_WAIT(quic_connected(), kTimeoutMs);
  ASSERT_FALSE(peer1_.signal_closed_emitted());
  ReliableQuicStream* stream = peer1_.quic_channel()->CreateQuicStream();
  ASSERT_NE(nullptr, stream);
  stream->CloseConnectionWithDetails(net::QuicErrorCode::QUIC_NO_ERROR,
                                     "Closing QUIC for testing");
  EXPECT_TRUE(peer1_.signal_closed_emitted());
  EXPECT_TRUE_WAIT(peer2_.signal_closed_emitted(), kTimeoutMs);
}
