/*
 *  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 "p2p/quic/quictransport.h"

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

#include "rtc_base/gunit.h"
#include "rtc_base/rtccertificate.h"
#include "rtc_base/sslidentity.h"

using cricket::TransportChannelImpl;
using cricket::QuicTransport;
using cricket::Transport;
using cricket::TransportDescription;

static const char kIceUfrag1[] = "TESTICEUFRAG0001";
static const char kIcePwd1[] = "TESTICEPWD00000000000001";

static const char kIceUfrag2[] = "TESTICEUFRAG0002";
static const char kIcePwd2[] = "TESTICEPWD00000000000002";

static rtc::scoped_refptr<rtc::RTCCertificate> CreateCertificate(
    std::string name) {
  return rtc::RTCCertificate::Create(std::unique_ptr<rtc::SSLIdentity>(
      rtc::SSLIdentity::Generate(name, rtc::KT_DEFAULT)));
}

static std::unique_ptr<rtc::SSLFingerprint> CreateFingerprint(
    rtc::RTCCertificate* cert) {
  std::string digest_algorithm;
  cert->ssl_certificate().GetSignatureDigestAlgorithm(&digest_algorithm);
  return std::unique_ptr<rtc::SSLFingerprint>(
      rtc::SSLFingerprint::Create(digest_algorithm, cert->identity()));
}

class QuicTransportTest : public testing::Test {
 public:
  QuicTransportTest() : transport_("testing", nullptr, nullptr) {}

  void SetTransportDescription(cricket::ConnectionRole local_role,
                               cricket::ConnectionRole remote_role,
                               cricket::ContentAction local_action,
                               cricket::ContentAction remote_action,
                               rtc::SSLRole expected_ssl_role) {
    TransportChannelImpl* channel = transport_.CreateChannel(1);
    ASSERT_NE(nullptr, channel);

    rtc::scoped_refptr<rtc::RTCCertificate> local_certificate(
        CreateCertificate("local"));
    ASSERT_NE(nullptr, local_certificate);
    transport_.SetLocalCertificate(local_certificate);

    std::unique_ptr<rtc::SSLFingerprint> local_fingerprint =
        CreateFingerprint(local_certificate.get());
    ASSERT_NE(nullptr, local_fingerprint);
    TransportDescription local_desc(std::vector<std::string>(), kIceUfrag1,
                                    kIcePwd1, cricket::ICEMODE_FULL, local_role,
                                    local_fingerprint.get());
    ASSERT_TRUE(transport_.SetLocalTransportDescription(local_desc,
                                                        local_action, nullptr));
    // The certificate is applied to QuicTransportChannel when the local
    // description is set.
    rtc::scoped_refptr<rtc::RTCCertificate> channel_local_certificate =
        channel->GetLocalCertificate();
    ASSERT_NE(nullptr, channel_local_certificate);
    EXPECT_EQ(local_certificate, channel_local_certificate);
    std::unique_ptr<rtc::SSLFingerprint> remote_fingerprint =
        CreateFingerprint(CreateCertificate("remote").get());
    // NegotiateTransportDescription was not called yet. The SSL role should
    // not be set and neither should the remote fingerprint.
    std::unique_ptr<rtc::SSLRole> role(new rtc::SSLRole());
    EXPECT_FALSE(channel->GetSslRole(role.get()));
    // Setting the remote description should set the SSL role.
    ASSERT_NE(nullptr, remote_fingerprint);
    TransportDescription remote_desc(std::vector<std::string>(), kIceUfrag2,
                                     kIcePwd2, cricket::ICEMODE_FULL,
                                     remote_role, remote_fingerprint.get());
    ASSERT_TRUE(transport_.SetRemoteTransportDescription(
        remote_desc, remote_action, nullptr));
    ASSERT_TRUE(channel->GetSslRole(role.get()));
    // SSL role should be client because the remote description is an ANSWER.
    EXPECT_EQ(expected_ssl_role, *role);
  }

 protected:
  QuicTransport transport_;
};

// Test setting the local certificate.
TEST_F(QuicTransportTest, SetLocalCertificate) {
  rtc::scoped_refptr<rtc::RTCCertificate> local_certificate(
      CreateCertificate("local"));
  ASSERT_NE(nullptr, local_certificate);
  rtc::scoped_refptr<rtc::RTCCertificate> transport_local_certificate;
  EXPECT_FALSE(transport_.GetLocalCertificate(&transport_local_certificate));
  transport_.SetLocalCertificate(local_certificate);
  ASSERT_TRUE(transport_.GetLocalCertificate(&transport_local_certificate));
  ASSERT_NE(nullptr, transport_local_certificate);
  EXPECT_EQ(local_certificate, transport_local_certificate);
}

// Test setting the ICE role.
TEST_F(QuicTransportTest, SetIceRole) {
  TransportChannelImpl* channel1 = transport_.CreateChannel(1);
  ASSERT_NE(nullptr, channel1);
  transport_.SetIceRole(cricket::ICEROLE_CONTROLLING);
  EXPECT_EQ(cricket::ICEROLE_CONTROLLING, transport_.ice_role());
  TransportChannelImpl* channel2 = transport_.CreateChannel(2);
  ASSERT_NE(nullptr, channel2);
  EXPECT_EQ(cricket::ICEROLE_CONTROLLING, channel1->GetIceRole());
  EXPECT_EQ(cricket::ICEROLE_CONTROLLING, channel2->GetIceRole());
}

// Test setting the ICE tie breaker.
TEST_F(QuicTransportTest, SetIceTiebreaker) {
  transport_.SetIceTiebreaker(1u);
  EXPECT_EQ(1u, transport_.IceTiebreaker());
}

// Test setting the local and remote descriptions for a SSL client.
TEST_F(QuicTransportTest, SetLocalAndRemoteTransportDescriptionClient) {
  SetTransportDescription(cricket::CONNECTIONROLE_ACTPASS,
                          cricket::CONNECTIONROLE_PASSIVE, cricket::CA_OFFER,
                          cricket::CA_ANSWER, rtc::SSL_CLIENT);
}

// Test setting the local and remote descriptions for a SSL server.
TEST_F(QuicTransportTest, SetLocalAndRemoteTransportDescriptionServer) {
  SetTransportDescription(cricket::CONNECTIONROLE_ACTPASS,
                          cricket::CONNECTIONROLE_ACTIVE, cricket::CA_OFFER,
                          cricket::CA_ANSWER, rtc::SSL_SERVER);
}

// Test creation and destruction of channels.
TEST_F(QuicTransportTest, CreateAndDestroyChannels) {
  TransportChannelImpl* channel1 = transport_.CreateChannel(1);
  ASSERT_NE(nullptr, channel1);
  EXPECT_TRUE(transport_.HasChannel(1));
  EXPECT_EQ(channel1, transport_.GetChannel(1));
  TransportChannelImpl* channel2 = transport_.CreateChannel(2);
  ASSERT_NE(nullptr, channel2);
  EXPECT_TRUE(transport_.HasChannel(2));
  EXPECT_EQ(channel2, transport_.GetChannel(2));
  transport_.DestroyChannel(1);
  EXPECT_FALSE(transport_.HasChannel(1));
  EXPECT_EQ(nullptr, transport_.GetChannel(1));
  transport_.DestroyChannel(2);
  EXPECT_FALSE(transport_.HasChannel(2));
  EXPECT_EQ(nullptr, transport_.GetChannel(2));
}
