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

#include <memory>

#include "absl/types/optional.h"
#include "rtc_base/checks.h"
#include "rtc_base/gunit.h"
#include "rtc_base/logging.h"
#include "rtc_base/refcountedobject.h"
#include "rtc_base/thread.h"

namespace rtc {

class RTCCertificateGeneratorFixture : public RTCCertificateGeneratorCallback {
 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()));
  }
  ~RTCCertificateGeneratorFixture() override {}

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

  void OnSuccess(const scoped_refptr<RTCCertificate>& certificate) override {
    RTC_CHECK(signaling_thread_->IsCurrent());
    RTC_CHECK(certificate);
    certificate_ = certificate;
    generate_async_completed_ = true;
  }
  void OnFailure() override {
    RTC_CHECK(signaling_thread_->IsCurrent());
    certificate_ = nullptr;
    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:
  RTCCertificateGeneratorTest()
      : fixture_(new RefCountedObject<RTCCertificateGeneratorFixture>()) {}

 protected:
  static const int kGenerationTimeoutMs = 10000;

  scoped_refptr<RTCCertificateGeneratorFixture> fixture_;
};

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

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

TEST_F(RTCCertificateGeneratorTest, GenerateAsyncECDSA) {
  EXPECT_FALSE(fixture_->certificate());
  fixture_->generator()->GenerateCertificateAsync(KeyParams::ECDSA(),
                                                  absl::nullopt, fixture_);
  // 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_TRUE_WAIT(fixture_->GenerateAsyncCompleted(), kGenerationTimeoutMs);
  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(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(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 + 1000);
}

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

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

  fixture_->generator()->GenerateCertificateAsync(invalid_params, absl::nullopt,
                                                  fixture_);
  EXPECT_TRUE_WAIT(fixture_->GenerateAsyncCompleted(), kGenerationTimeoutMs);
  EXPECT_FALSE(fixture_->certificate());
}

}  // namespace rtc
