# This file is dual licensed under the terms of the Apache License, Version
# 2.0, and the BSD License. See the LICENSE file in the root of this repository
# for complete details.

from __future__ import absolute_import, division, print_function

import datetime

import pytest

import pytz

from cryptography import x509
from cryptography.hazmat.backends.interfaces import X509Backend


class TestRevokedCertificateBuilder(object):
    def test_serial_number_must_be_integer(self):
        with pytest.raises(TypeError):
            x509.RevokedCertificateBuilder().serial_number("notanx509name")

    def test_serial_number_must_be_non_negative(self):
        with pytest.raises(ValueError):
            x509.RevokedCertificateBuilder().serial_number(-1)

    def test_serial_number_must_be_positive(self):
        with pytest.raises(ValueError):
            x509.RevokedCertificateBuilder().serial_number(0)

    @pytest.mark.requires_backend_interface(interface=X509Backend)
    def test_minimal_serial_number(self, backend):
        revocation_date = datetime.datetime(2002, 1, 1, 12, 1)
        builder = x509.RevokedCertificateBuilder().serial_number(
            1
        ).revocation_date(
            revocation_date
        )

        revoked_certificate = builder.build(backend)
        assert revoked_certificate.serial_number == 1

    @pytest.mark.requires_backend_interface(interface=X509Backend)
    def test_biggest_serial_number(self, backend):
        revocation_date = datetime.datetime(2002, 1, 1, 12, 1)
        builder = x509.RevokedCertificateBuilder().serial_number(
            (1 << 159) - 1
        ).revocation_date(
            revocation_date
        )

        revoked_certificate = builder.build(backend)
        assert revoked_certificate.serial_number == (1 << 159) - 1

    def test_serial_number_must_be_less_than_160_bits_long(self):
        with pytest.raises(ValueError):
            x509.RevokedCertificateBuilder().serial_number(1 << 159)

    def test_set_serial_number_twice(self):
        builder = x509.RevokedCertificateBuilder().serial_number(3)
        with pytest.raises(ValueError):
            builder.serial_number(4)

    @pytest.mark.requires_backend_interface(interface=X509Backend)
    def test_aware_revocation_date(self, backend):
        time = datetime.datetime(2012, 1, 16, 22, 43)
        tz = pytz.timezone("US/Pacific")
        time = tz.localize(time)
        utc_time = datetime.datetime(2012, 1, 17, 6, 43)
        serial_number = 333
        builder = x509.RevokedCertificateBuilder().serial_number(
            serial_number
        ).revocation_date(
            time
        )

        revoked_certificate = builder.build(backend)
        assert revoked_certificate.revocation_date == utc_time

    def test_revocation_date_invalid(self):
        with pytest.raises(TypeError):
            x509.RevokedCertificateBuilder().revocation_date("notadatetime")

    def test_revocation_date_before_1950(self):
        with pytest.raises(ValueError):
            x509.RevokedCertificateBuilder().revocation_date(
                datetime.datetime(1940, 8, 10)
            )

    def test_set_revocation_date_twice(self):
        builder = x509.RevokedCertificateBuilder().revocation_date(
            datetime.datetime(2002, 1, 1, 12, 1)
        )
        with pytest.raises(ValueError):
            builder.revocation_date(datetime.datetime(2002, 1, 1, 12, 1))

    def test_add_extension_checks_for_duplicates(self):
        builder = x509.RevokedCertificateBuilder().add_extension(
            x509.CRLReason(x509.ReasonFlags.ca_compromise), False
        )

        with pytest.raises(ValueError):
            builder.add_extension(
                x509.CRLReason(x509.ReasonFlags.ca_compromise), False
            )

    def test_add_invalid_extension(self):
        with pytest.raises(TypeError):
            x509.RevokedCertificateBuilder().add_extension(
                "notanextension", False
            )

    @pytest.mark.requires_backend_interface(interface=X509Backend)
    def test_no_serial_number(self, backend):
        builder = x509.RevokedCertificateBuilder().revocation_date(
            datetime.datetime(2002, 1, 1, 12, 1)
        )

        with pytest.raises(ValueError):
            builder.build(backend)

    @pytest.mark.requires_backend_interface(interface=X509Backend)
    def test_no_revocation_date(self, backend):
        builder = x509.RevokedCertificateBuilder().serial_number(3)

        with pytest.raises(ValueError):
            builder.build(backend)

    @pytest.mark.requires_backend_interface(interface=X509Backend)
    def test_create_revoked(self, backend):
        serial_number = 333
        revocation_date = datetime.datetime(2002, 1, 1, 12, 1)
        builder = x509.RevokedCertificateBuilder().serial_number(
            serial_number
        ).revocation_date(
            revocation_date
        )

        revoked_certificate = builder.build(backend)
        assert revoked_certificate.serial_number == serial_number
        assert revoked_certificate.revocation_date == revocation_date
        assert len(revoked_certificate.extensions) == 0

    @pytest.mark.parametrize(
        "extension",
        [
            x509.InvalidityDate(datetime.datetime(2015, 1, 1, 0, 0)),
            x509.CRLReason(x509.ReasonFlags.ca_compromise),
            x509.CertificateIssuer([
                x509.DNSName(u"cryptography.io"),
            ])
        ]
    )
    @pytest.mark.requires_backend_interface(interface=X509Backend)
    def test_add_extensions(self, backend, extension):
        serial_number = 333
        revocation_date = datetime.datetime(2002, 1, 1, 12, 1)
        builder = x509.RevokedCertificateBuilder().serial_number(
            serial_number
        ).revocation_date(
            revocation_date
        ).add_extension(
            extension, False
        )

        revoked_certificate = builder.build(backend)
        assert revoked_certificate.serial_number == serial_number
        assert revoked_certificate.revocation_date == revocation_date
        assert len(revoked_certificate.extensions) == 1
        ext = revoked_certificate.extensions.get_extension_for_class(
            type(extension)
        )
        assert ext.critical is False
        assert ext.value == extension

    @pytest.mark.requires_backend_interface(interface=X509Backend)
    def test_add_multiple_extensions(self, backend):
        serial_number = 333
        revocation_date = datetime.datetime(2002, 1, 1, 12, 1)
        invalidity_date = x509.InvalidityDate(
            datetime.datetime(2015, 1, 1, 0, 0)
        )
        certificate_issuer = x509.CertificateIssuer([
            x509.DNSName(u"cryptography.io"),
        ])
        crl_reason = x509.CRLReason(x509.ReasonFlags.aa_compromise)
        builder = x509.RevokedCertificateBuilder().serial_number(
            serial_number
        ).revocation_date(
            revocation_date
        ).add_extension(
            invalidity_date, True
        ).add_extension(
            crl_reason, True
        ).add_extension(
            certificate_issuer, True
        )

        revoked_certificate = builder.build(backend)
        assert len(revoked_certificate.extensions) == 3
        for ext_data in [invalidity_date, certificate_issuer, crl_reason]:
            ext = revoked_certificate.extensions.get_extension_for_class(
                type(ext_data)
            )
            assert ext.critical is True
            assert ext.value == ext_data
