/*
 *  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 "rtc_base/rtc_certificate_generator.h"

#include <cstdint>
#include <memory>
#include <optional>
#include <utility>

#include "api/scoped_refptr.h"
#include "api/test/rtc_error_matchers.h"
#include "api/units/time_delta.h"
#include "rtc_base/checks.h"
#include "rtc_base/rtc_certificate.h"
#include "rtc_base/ssl_identity.h"
#include "rtc_base/thread.h"
#include "test/gmock.h"
#include "test/gtest.h"
#include "test/wait_until.h"

namespace webrtc {

class RTCCertificateGeneratorFixture {
 public:
  RTCCertificateGeneratorFixture()
      : signaling_thread_(Thread::Current()),
        worker_thread_(Thread::Create()),
        generate_async_completed_(false) {
    RTC_CHECK(signaling_thread_);
    RTC_CHECK(worker_thread_->Start());
    generator_.reset(
        new RTCCertificateGenerator(signaling_thread_, worker_thread_.get()));
  }

  RTCCertificateGenerator* generator() const { return generator_.get(); }
  RTCCertificate* certificate() const { return certificate_.get(); }

  RTCCertificateGeneratorInterface::Callback OnGenerated() {
    return [this](scoped_refptr<RTCCertificate> certificate) mutable {
      RTC_CHECK(signaling_thread_->IsCurrent());
      certificate_ = std::move(certificate);
      generate_async_completed_ = true;
    };
  }

  bool GenerateAsyncCompleted() {
    RTC_CHECK(signaling_thread_->IsCurrent());
    if (generate_async_completed_) {
      // Reset flag so that future generation requests are not considered done.
      generate_async_completed_ = false;
      return true;
    }
    return false;
  }

 protected:
  Thread* const signaling_thread_;
  std::unique_ptr<Thread> worker_thread_;
  std::unique_ptr<RTCCertificateGenerator> generator_;
  scoped_refptr<RTCCertificate> certificate_;
  bool generate_async_completed_;
};

class RTCCertificateGeneratorTest : public ::testing::Test {
 public:
 protected:
  static constexpr TimeDelta kGenerationTimeoutMs = TimeDelta::Millis(10000);

  AutoThread main_thread_;
  RTCCertificateGeneratorFixture fixture_;
};

TEST_F(RTCCertificateGeneratorTest, GenerateECDSA) {
  EXPECT_TRUE(RTCCertificateGenerator::GenerateCertificate(
      rtc::KeyParams::ECDSA(), std::nullopt));
}

TEST_F(RTCCertificateGeneratorTest, GenerateRSA) {
  EXPECT_TRUE(RTCCertificateGenerator::GenerateCertificate(
      rtc::KeyParams::RSA(), std::nullopt));
}

TEST_F(RTCCertificateGeneratorTest, GenerateAsyncECDSA) {
  EXPECT_FALSE(fixture_.certificate());
  fixture_.generator()->GenerateCertificateAsync(
      rtc::KeyParams::ECDSA(), std::nullopt, fixture_.OnGenerated());
  // Until generation has completed, the certificate is null. Since this is an
  // async call, generation must not have completed until we process messages
  // posted to this thread (which is done by `EXPECT_TRUE_WAIT`).
  EXPECT_FALSE(fixture_.GenerateAsyncCompleted());
  EXPECT_FALSE(fixture_.certificate());
  EXPECT_THAT(
      webrtc::WaitUntil([&] { return fixture_.GenerateAsyncCompleted(); },
                        ::testing::IsTrue(), {.timeout = kGenerationTimeoutMs}),
      webrtc::IsRtcOk());
  EXPECT_TRUE(fixture_.certificate());
}

TEST_F(RTCCertificateGeneratorTest, GenerateWithExpires) {
  // By generating two certificates with different expiration we can compare the
  // two expiration times relative to each other without knowing the current
  // time relative to epoch, 1970-01-01T00:00:00Z. This verifies that the
  // expiration parameter is correctly used relative to the generator's clock,
  // but does not verify that this clock is relative to epoch.

  // Generate a certificate that expires immediately.
  scoped_refptr<RTCCertificate> cert_a =
      RTCCertificateGenerator::GenerateCertificate(rtc::KeyParams::ECDSA(), 0);
  EXPECT_TRUE(cert_a);

  // Generate a certificate that expires in one minute.
  const uint64_t kExpiresMs = 60000;
  scoped_refptr<RTCCertificate> cert_b =
      RTCCertificateGenerator::GenerateCertificate(rtc::KeyParams::ECDSA(),
                                                   kExpiresMs);
  EXPECT_TRUE(cert_b);

  // Verify that `cert_b` expires approximately `kExpiresMs` after `cert_a`
  // (allowing a +/- 1 second plus maximum generation time difference).
  EXPECT_GT(cert_b->Expires(), cert_a->Expires());
  uint64_t expires_diff = cert_b->Expires() - cert_a->Expires();
  EXPECT_GE(expires_diff, kExpiresMs);
  EXPECT_LE(expires_diff, kExpiresMs + 2 * kGenerationTimeoutMs.ms() + 1000);
}

TEST_F(RTCCertificateGeneratorTest, GenerateWithInvalidParamsShouldFail) {
  rtc::KeyParams invalid_params = rtc::KeyParams::RSA(0, 0);
  EXPECT_FALSE(invalid_params.IsValid());

  EXPECT_FALSE(RTCCertificateGenerator::GenerateCertificate(invalid_params,
                                                            std::nullopt));

  fixture_.generator()->GenerateCertificateAsync(invalid_params, std::nullopt,
                                                 fixture_.OnGenerated());
  EXPECT_THAT(
      webrtc::WaitUntil([&] { return fixture_.GenerateAsyncCompleted(); },
                        ::testing::IsTrue(), {.timeout = kGenerationTimeoutMs}),
      webrtc::IsRtcOk());
  EXPECT_FALSE(fixture_.certificate());
}

}  // namespace webrtc
