// Copyright 2023 Daniel McCarney.
//
// Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
// copyright notice and this permission notice appear in all copies.
//
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHORS DISCLAIM ALL WARRANTIES
// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR
// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.

#![cfg(any(feature = "ring", feature = "aws-lc-rs"))]

use core::time::Duration;

use pki_types::{CertificateDer, SignatureVerificationAlgorithm, UnixTime};
use webpki::{
    KeyUsage, RevocationCheckDepth, RevocationOptions, RevocationOptionsBuilder,
    UnknownStatusPolicy, anchor_from_trusted_cert,
};

static ALGS: &[&dyn SignatureVerificationAlgorithm] = &[
    #[cfg(feature = "ring")]
    webpki::ring::ECDSA_P256_SHA256,
    #[cfg(feature = "aws-lc-rs")]
    webpki::aws_lc_rs::ECDSA_P256_SHA256,
];

fn check_cert(
    ee: &[u8],
    intermediates: &[&[u8]],
    ca: &[u8],
    revocation: Option<RevocationOptions>,
) -> Result<(), webpki::Error> {
    let ca = CertificateDer::from(ca);
    let anchors = &[anchor_from_trusted_cert(&ca).unwrap()];
    let ee = CertificateDer::from(ee);
    let cert = webpki::EndEntityCert::try_from(&ee).unwrap();
    let time = UnixTime::since_unix_epoch(Duration::from_secs(0x1fed_f00d));
    let intermediates = intermediates
        .iter()
        .map(|cert| CertificateDer::from(*cert))
        .collect::<Vec<_>>();

    cert.verify_for_usage(
        ALGS,
        anchors,
        &intermediates,
        time,
        KeyUsage::client_auth(),
        revocation,
        None,
    )
    .map(|_| ())
}

// DO NOT EDIT BELOW: generated by tests/generate.py

#[test]
fn no_crls_test() {
    let ee = include_bytes!("client_auth_revocation/no_ku_chain.ee.der");
    let intermediates = &[
        include_bytes!("client_auth_revocation/no_ku_chain.int.a.ca.der").as_slice(),
        include_bytes!("client_auth_revocation/no_ku_chain.int.b.ca.der").as_slice(),
    ];
    let ca = include_bytes!("client_auth_revocation/no_ku_chain.root.ca.der");
    let revocation = None;
    assert_eq!(check_cert(ee, intermediates, ca, revocation), Ok(()));
}

#[cfg(feature = "alloc")]
#[test]
fn no_crls_test_owned() {
    let ee = include_bytes!("client_auth_revocation/no_ku_chain.ee.der");
    let intermediates = &[
        include_bytes!("client_auth_revocation/no_ku_chain.int.a.ca.der").as_slice(),
        include_bytes!("client_auth_revocation/no_ku_chain.int.b.ca.der").as_slice(),
    ];
    let ca = include_bytes!("client_auth_revocation/no_ku_chain.root.ca.der");
    let revocation = None;
    assert_eq!(check_cert(ee, intermediates, ca, revocation), Ok(()));
}

#[test]
fn no_relevant_crl_ee_depth_allow_unknown() {
    let ee = include_bytes!("client_auth_revocation/no_ku_chain.ee.der");
    let intermediates = &[
        include_bytes!("client_auth_revocation/no_ku_chain.int.a.ca.der").as_slice(),
        include_bytes!("client_auth_revocation/no_ku_chain.int.b.ca.der").as_slice(),
    ];
    let ca = include_bytes!("client_auth_revocation/no_ku_chain.root.ca.der");

    let crls = &[&webpki::CertRevocationList::Borrowed(
        webpki::BorrowedCertRevocationList::from_der(
            include_bytes!("client_auth_revocation/no_relevant_crl_ee_depth_allow_unknown.crl.der")
                .as_slice(),
        )
        .unwrap(),
    )];
    let builder = RevocationOptionsBuilder::new(crls).unwrap();

    let builder = builder.with_depth(RevocationCheckDepth::EndEntity);

    let builder = builder.with_status_policy(UnknownStatusPolicy::Allow);
    let revocation = Some(builder.build());
    assert_eq!(check_cert(ee, intermediates, ca, revocation), Ok(()));
}

#[cfg(feature = "alloc")]
#[test]
fn no_relevant_crl_ee_depth_allow_unknown_owned() {
    let ee = include_bytes!("client_auth_revocation/no_ku_chain.ee.der");
    let intermediates = &[
        include_bytes!("client_auth_revocation/no_ku_chain.int.a.ca.der").as_slice(),
        include_bytes!("client_auth_revocation/no_ku_chain.int.b.ca.der").as_slice(),
    ];
    let ca = include_bytes!("client_auth_revocation/no_ku_chain.root.ca.der");

    let crls = &[&webpki::CertRevocationList::Owned(
        webpki::OwnedCertRevocationList::from_der(
            include_bytes!("client_auth_revocation/no_relevant_crl_ee_depth_allow_unknown.crl.der")
                .as_slice(),
        )
        .unwrap(),
    )];
    let builder = RevocationOptionsBuilder::new(crls).unwrap();

    let builder = builder.with_depth(RevocationCheckDepth::EndEntity);

    let builder = builder.with_status_policy(UnknownStatusPolicy::Allow);
    let revocation = Some(builder.build());
    assert_eq!(check_cert(ee, intermediates, ca, revocation), Ok(()));
}

#[test]
fn no_relevant_crl_ee_depth_forbid_unknown() {
    let ee = include_bytes!("client_auth_revocation/no_ku_chain.ee.der");
    let intermediates = &[
        include_bytes!("client_auth_revocation/no_ku_chain.int.a.ca.der").as_slice(),
        include_bytes!("client_auth_revocation/no_ku_chain.int.b.ca.der").as_slice(),
    ];
    let ca = include_bytes!("client_auth_revocation/no_ku_chain.root.ca.der");

    let crls = &[&webpki::CertRevocationList::Borrowed(
        webpki::BorrowedCertRevocationList::from_der(
            include_bytes!(
                "client_auth_revocation/no_relevant_crl_ee_depth_forbid_unknown.crl.der"
            )
            .as_slice(),
        )
        .unwrap(),
    )];
    let builder = RevocationOptionsBuilder::new(crls).unwrap();

    let builder = builder.with_depth(RevocationCheckDepth::EndEntity);
    let revocation = Some(builder.build());
    assert_eq!(
        check_cert(ee, intermediates, ca, revocation),
        Err(webpki::Error::UnknownRevocationStatus)
    );
}

#[cfg(feature = "alloc")]
#[test]
fn no_relevant_crl_ee_depth_forbid_unknown_owned() {
    let ee = include_bytes!("client_auth_revocation/no_ku_chain.ee.der");
    let intermediates = &[
        include_bytes!("client_auth_revocation/no_ku_chain.int.a.ca.der").as_slice(),
        include_bytes!("client_auth_revocation/no_ku_chain.int.b.ca.der").as_slice(),
    ];
    let ca = include_bytes!("client_auth_revocation/no_ku_chain.root.ca.der");

    let crls = &[&webpki::CertRevocationList::Owned(
        webpki::OwnedCertRevocationList::from_der(
            include_bytes!(
                "client_auth_revocation/no_relevant_crl_ee_depth_forbid_unknown.crl.der"
            )
            .as_slice(),
        )
        .unwrap(),
    )];
    let builder = RevocationOptionsBuilder::new(crls).unwrap();

    let builder = builder.with_depth(RevocationCheckDepth::EndEntity);
    let revocation = Some(builder.build());
    assert_eq!(
        check_cert(ee, intermediates, ca, revocation),
        Err(webpki::Error::UnknownRevocationStatus)
    );
}

#[test]
fn ee_not_revoked_ee_depth() {
    let ee = include_bytes!("client_auth_revocation/no_ku_chain.ee.der");
    let intermediates = &[
        include_bytes!("client_auth_revocation/no_ku_chain.int.a.ca.der").as_slice(),
        include_bytes!("client_auth_revocation/no_ku_chain.int.b.ca.der").as_slice(),
    ];
    let ca = include_bytes!("client_auth_revocation/no_ku_chain.root.ca.der");

    let crls = &[&webpki::CertRevocationList::Borrowed(
        webpki::BorrowedCertRevocationList::from_der(
            include_bytes!("client_auth_revocation/ee_not_revoked_ee_depth.crl.der").as_slice(),
        )
        .unwrap(),
    )];
    let builder = RevocationOptionsBuilder::new(crls).unwrap();

    let builder = builder.with_depth(RevocationCheckDepth::EndEntity);

    let builder = builder.with_status_policy(UnknownStatusPolicy::Allow);
    let revocation = Some(builder.build());
    assert_eq!(check_cert(ee, intermediates, ca, revocation), Ok(()));
}

#[cfg(feature = "alloc")]
#[test]
fn ee_not_revoked_ee_depth_owned() {
    let ee = include_bytes!("client_auth_revocation/no_ku_chain.ee.der");
    let intermediates = &[
        include_bytes!("client_auth_revocation/no_ku_chain.int.a.ca.der").as_slice(),
        include_bytes!("client_auth_revocation/no_ku_chain.int.b.ca.der").as_slice(),
    ];
    let ca = include_bytes!("client_auth_revocation/no_ku_chain.root.ca.der");

    let crls = &[&webpki::CertRevocationList::Owned(
        webpki::OwnedCertRevocationList::from_der(
            include_bytes!("client_auth_revocation/ee_not_revoked_ee_depth.crl.der").as_slice(),
        )
        .unwrap(),
    )];
    let builder = RevocationOptionsBuilder::new(crls).unwrap();

    let builder = builder.with_depth(RevocationCheckDepth::EndEntity);

    let builder = builder.with_status_policy(UnknownStatusPolicy::Allow);
    let revocation = Some(builder.build());
    assert_eq!(check_cert(ee, intermediates, ca, revocation), Ok(()));
}

#[test]
fn ee_not_revoked_chain_depth() {
    let ee = include_bytes!("client_auth_revocation/no_ku_chain.ee.der");
    let intermediates = &[
        include_bytes!("client_auth_revocation/no_ku_chain.int.a.ca.der").as_slice(),
        include_bytes!("client_auth_revocation/no_ku_chain.int.b.ca.der").as_slice(),
    ];
    let ca = include_bytes!("client_auth_revocation/no_ku_chain.root.ca.der");

    let crls = &[&webpki::CertRevocationList::Borrowed(
        webpki::BorrowedCertRevocationList::from_der(
            include_bytes!("client_auth_revocation/ee_not_revoked_chain_depth.crl.der").as_slice(),
        )
        .unwrap(),
    )];
    let builder = RevocationOptionsBuilder::new(crls).unwrap();

    let builder = builder.with_status_policy(UnknownStatusPolicy::Allow);
    let revocation = Some(builder.build());
    assert_eq!(check_cert(ee, intermediates, ca, revocation), Ok(()));
}

#[cfg(feature = "alloc")]
#[test]
fn ee_not_revoked_chain_depth_owned() {
    let ee = include_bytes!("client_auth_revocation/no_ku_chain.ee.der");
    let intermediates = &[
        include_bytes!("client_auth_revocation/no_ku_chain.int.a.ca.der").as_slice(),
        include_bytes!("client_auth_revocation/no_ku_chain.int.b.ca.der").as_slice(),
    ];
    let ca = include_bytes!("client_auth_revocation/no_ku_chain.root.ca.der");

    let crls = &[&webpki::CertRevocationList::Owned(
        webpki::OwnedCertRevocationList::from_der(
            include_bytes!("client_auth_revocation/ee_not_revoked_chain_depth.crl.der").as_slice(),
        )
        .unwrap(),
    )];
    let builder = RevocationOptionsBuilder::new(crls).unwrap();

    let builder = builder.with_status_policy(UnknownStatusPolicy::Allow);
    let revocation = Some(builder.build());
    assert_eq!(check_cert(ee, intermediates, ca, revocation), Ok(()));
}

#[test]
fn ee_revoked_badsig_ee_depth() {
    let ee = include_bytes!("client_auth_revocation/no_ku_chain.ee.der");
    let intermediates = &[
        include_bytes!("client_auth_revocation/no_ku_chain.int.a.ca.der").as_slice(),
        include_bytes!("client_auth_revocation/no_ku_chain.int.b.ca.der").as_slice(),
    ];
    let ca = include_bytes!("client_auth_revocation/no_ku_chain.root.ca.der");

    let crls = &[&webpki::CertRevocationList::Borrowed(
        webpki::BorrowedCertRevocationList::from_der(
            include_bytes!("client_auth_revocation/ee_revoked_badsig_ee_depth.crl.der").as_slice(),
        )
        .unwrap(),
    )];
    let builder = RevocationOptionsBuilder::new(crls).unwrap();

    let builder = builder.with_depth(RevocationCheckDepth::EndEntity);

    let builder = builder.with_status_policy(UnknownStatusPolicy::Allow);
    let revocation = Some(builder.build());
    assert_eq!(
        check_cert(ee, intermediates, ca, revocation),
        Err(webpki::Error::InvalidCrlSignatureForPublicKey)
    );
}

#[cfg(feature = "alloc")]
#[test]
fn ee_revoked_badsig_ee_depth_owned() {
    let ee = include_bytes!("client_auth_revocation/no_ku_chain.ee.der");
    let intermediates = &[
        include_bytes!("client_auth_revocation/no_ku_chain.int.a.ca.der").as_slice(),
        include_bytes!("client_auth_revocation/no_ku_chain.int.b.ca.der").as_slice(),
    ];
    let ca = include_bytes!("client_auth_revocation/no_ku_chain.root.ca.der");

    let crls = &[&webpki::CertRevocationList::Owned(
        webpki::OwnedCertRevocationList::from_der(
            include_bytes!("client_auth_revocation/ee_revoked_badsig_ee_depth.crl.der").as_slice(),
        )
        .unwrap(),
    )];
    let builder = RevocationOptionsBuilder::new(crls).unwrap();

    let builder = builder.with_depth(RevocationCheckDepth::EndEntity);

    let builder = builder.with_status_policy(UnknownStatusPolicy::Allow);
    let revocation = Some(builder.build());
    assert_eq!(
        check_cert(ee, intermediates, ca, revocation),
        Err(webpki::Error::InvalidCrlSignatureForPublicKey)
    );
}

#[test]
fn ee_revoked_wrong_ku_ee_depth() {
    let ee = include_bytes!("client_auth_revocation/no_crl_ku_chain.ee.der");
    let intermediates = &[
        include_bytes!("client_auth_revocation/no_crl_ku_chain.int.a.ca.der").as_slice(),
        include_bytes!("client_auth_revocation/no_crl_ku_chain.int.b.ca.der").as_slice(),
    ];
    let ca = include_bytes!("client_auth_revocation/no_crl_ku_chain.root.ca.der");

    let crls = &[&webpki::CertRevocationList::Borrowed(
        webpki::BorrowedCertRevocationList::from_der(
            include_bytes!("client_auth_revocation/ee_revoked_wrong_ku_ee_depth.crl.der")
                .as_slice(),
        )
        .unwrap(),
    )];
    let builder = RevocationOptionsBuilder::new(crls).unwrap();

    let builder = builder.with_depth(RevocationCheckDepth::EndEntity);

    let builder = builder.with_status_policy(UnknownStatusPolicy::Allow);
    let revocation = Some(builder.build());
    assert_eq!(
        check_cert(ee, intermediates, ca, revocation),
        Err(webpki::Error::IssuerNotCrlSigner)
    );
}

#[cfg(feature = "alloc")]
#[test]
fn ee_revoked_wrong_ku_ee_depth_owned() {
    let ee = include_bytes!("client_auth_revocation/no_crl_ku_chain.ee.der");
    let intermediates = &[
        include_bytes!("client_auth_revocation/no_crl_ku_chain.int.a.ca.der").as_slice(),
        include_bytes!("client_auth_revocation/no_crl_ku_chain.int.b.ca.der").as_slice(),
    ];
    let ca = include_bytes!("client_auth_revocation/no_crl_ku_chain.root.ca.der");

    let crls = &[&webpki::CertRevocationList::Owned(
        webpki::OwnedCertRevocationList::from_der(
            include_bytes!("client_auth_revocation/ee_revoked_wrong_ku_ee_depth.crl.der")
                .as_slice(),
        )
        .unwrap(),
    )];
    let builder = RevocationOptionsBuilder::new(crls).unwrap();

    let builder = builder.with_depth(RevocationCheckDepth::EndEntity);

    let builder = builder.with_status_policy(UnknownStatusPolicy::Allow);
    let revocation = Some(builder.build());
    assert_eq!(
        check_cert(ee, intermediates, ca, revocation),
        Err(webpki::Error::IssuerNotCrlSigner)
    );
}

#[test]
fn ee_not_revoked_wrong_ku_ee_depth() {
    let ee = include_bytes!("client_auth_revocation/no_crl_ku_chain.ee.der");
    let intermediates = &[
        include_bytes!("client_auth_revocation/no_crl_ku_chain.int.a.ca.der").as_slice(),
        include_bytes!("client_auth_revocation/no_crl_ku_chain.int.b.ca.der").as_slice(),
    ];
    let ca = include_bytes!("client_auth_revocation/no_crl_ku_chain.root.ca.der");

    let crls = &[&webpki::CertRevocationList::Borrowed(
        webpki::BorrowedCertRevocationList::from_der(
            include_bytes!("client_auth_revocation/ee_not_revoked_wrong_ku_ee_depth.crl.der")
                .as_slice(),
        )
        .unwrap(),
    )];
    let builder = RevocationOptionsBuilder::new(crls).unwrap();

    let builder = builder.with_depth(RevocationCheckDepth::EndEntity);

    let builder = builder.with_status_policy(UnknownStatusPolicy::Allow);
    let revocation = Some(builder.build());
    assert_eq!(
        check_cert(ee, intermediates, ca, revocation),
        Err(webpki::Error::IssuerNotCrlSigner)
    );
}

#[cfg(feature = "alloc")]
#[test]
fn ee_not_revoked_wrong_ku_ee_depth_owned() {
    let ee = include_bytes!("client_auth_revocation/no_crl_ku_chain.ee.der");
    let intermediates = &[
        include_bytes!("client_auth_revocation/no_crl_ku_chain.int.a.ca.der").as_slice(),
        include_bytes!("client_auth_revocation/no_crl_ku_chain.int.b.ca.der").as_slice(),
    ];
    let ca = include_bytes!("client_auth_revocation/no_crl_ku_chain.root.ca.der");

    let crls = &[&webpki::CertRevocationList::Owned(
        webpki::OwnedCertRevocationList::from_der(
            include_bytes!("client_auth_revocation/ee_not_revoked_wrong_ku_ee_depth.crl.der")
                .as_slice(),
        )
        .unwrap(),
    )];
    let builder = RevocationOptionsBuilder::new(crls).unwrap();

    let builder = builder.with_depth(RevocationCheckDepth::EndEntity);

    let builder = builder.with_status_policy(UnknownStatusPolicy::Allow);
    let revocation = Some(builder.build());
    assert_eq!(
        check_cert(ee, intermediates, ca, revocation),
        Err(webpki::Error::IssuerNotCrlSigner)
    );
}

#[test]
fn ee_revoked_no_ku_ee_depth() {
    let ee = include_bytes!("client_auth_revocation/no_ku_chain.ee.der");
    let intermediates = &[
        include_bytes!("client_auth_revocation/no_ku_chain.int.a.ca.der").as_slice(),
        include_bytes!("client_auth_revocation/no_ku_chain.int.b.ca.der").as_slice(),
    ];
    let ca = include_bytes!("client_auth_revocation/no_ku_chain.root.ca.der");

    let crls = &[&webpki::CertRevocationList::Borrowed(
        webpki::BorrowedCertRevocationList::from_der(
            include_bytes!("client_auth_revocation/ee_revoked_no_ku_ee_depth.crl.der").as_slice(),
        )
        .unwrap(),
    )];
    let builder = RevocationOptionsBuilder::new(crls).unwrap();

    let builder = builder.with_depth(RevocationCheckDepth::EndEntity);

    let builder = builder.with_status_policy(UnknownStatusPolicy::Allow);
    let revocation = Some(builder.build());
    assert_eq!(
        check_cert(ee, intermediates, ca, revocation),
        Err(webpki::Error::CertRevoked)
    );
}

#[cfg(feature = "alloc")]
#[test]
fn ee_revoked_no_ku_ee_depth_owned() {
    let ee = include_bytes!("client_auth_revocation/no_ku_chain.ee.der");
    let intermediates = &[
        include_bytes!("client_auth_revocation/no_ku_chain.int.a.ca.der").as_slice(),
        include_bytes!("client_auth_revocation/no_ku_chain.int.b.ca.der").as_slice(),
    ];
    let ca = include_bytes!("client_auth_revocation/no_ku_chain.root.ca.der");

    let crls = &[&webpki::CertRevocationList::Owned(
        webpki::OwnedCertRevocationList::from_der(
            include_bytes!("client_auth_revocation/ee_revoked_no_ku_ee_depth.crl.der").as_slice(),
        )
        .unwrap(),
    )];
    let builder = RevocationOptionsBuilder::new(crls).unwrap();

    let builder = builder.with_depth(RevocationCheckDepth::EndEntity);

    let builder = builder.with_status_policy(UnknownStatusPolicy::Allow);
    let revocation = Some(builder.build());
    assert_eq!(
        check_cert(ee, intermediates, ca, revocation),
        Err(webpki::Error::CertRevoked)
    );
}

#[test]
fn ee_revoked_crl_ku_ee_depth() {
    let ee = include_bytes!("client_auth_revocation/ku_chain.ee.der");
    let intermediates = &[
        include_bytes!("client_auth_revocation/ku_chain.int.a.ca.der").as_slice(),
        include_bytes!("client_auth_revocation/ku_chain.int.b.ca.der").as_slice(),
    ];
    let ca = include_bytes!("client_auth_revocation/ku_chain.root.ca.der");

    let crls = &[&webpki::CertRevocationList::Borrowed(
        webpki::BorrowedCertRevocationList::from_der(
            include_bytes!("client_auth_revocation/ee_revoked_crl_ku_ee_depth.crl.der").as_slice(),
        )
        .unwrap(),
    )];
    let builder = RevocationOptionsBuilder::new(crls).unwrap();

    let builder = builder.with_depth(RevocationCheckDepth::EndEntity);

    let builder = builder.with_status_policy(UnknownStatusPolicy::Allow);
    let revocation = Some(builder.build());
    assert_eq!(
        check_cert(ee, intermediates, ca, revocation),
        Err(webpki::Error::CertRevoked)
    );
}

#[cfg(feature = "alloc")]
#[test]
fn ee_revoked_crl_ku_ee_depth_owned() {
    let ee = include_bytes!("client_auth_revocation/ku_chain.ee.der");
    let intermediates = &[
        include_bytes!("client_auth_revocation/ku_chain.int.a.ca.der").as_slice(),
        include_bytes!("client_auth_revocation/ku_chain.int.b.ca.der").as_slice(),
    ];
    let ca = include_bytes!("client_auth_revocation/ku_chain.root.ca.der");

    let crls = &[&webpki::CertRevocationList::Owned(
        webpki::OwnedCertRevocationList::from_der(
            include_bytes!("client_auth_revocation/ee_revoked_crl_ku_ee_depth.crl.der").as_slice(),
        )
        .unwrap(),
    )];
    let builder = RevocationOptionsBuilder::new(crls).unwrap();

    let builder = builder.with_depth(RevocationCheckDepth::EndEntity);

    let builder = builder.with_status_policy(UnknownStatusPolicy::Allow);
    let revocation = Some(builder.build());
    assert_eq!(
        check_cert(ee, intermediates, ca, revocation),
        Err(webpki::Error::CertRevoked)
    );
}

#[test]
fn no_crls_test_chain_depth() {
    let ee = include_bytes!("client_auth_revocation/no_ku_chain.ee.der");
    let intermediates = &[
        include_bytes!("client_auth_revocation/no_ku_chain.int.a.ca.der").as_slice(),
        include_bytes!("client_auth_revocation/no_ku_chain.int.b.ca.der").as_slice(),
    ];
    let ca = include_bytes!("client_auth_revocation/no_ku_chain.root.ca.der");
    let revocation = None;
    assert_eq!(check_cert(ee, intermediates, ca, revocation), Ok(()));
}

#[cfg(feature = "alloc")]
#[test]
fn no_crls_test_chain_depth_owned() {
    let ee = include_bytes!("client_auth_revocation/no_ku_chain.ee.der");
    let intermediates = &[
        include_bytes!("client_auth_revocation/no_ku_chain.int.a.ca.der").as_slice(),
        include_bytes!("client_auth_revocation/no_ku_chain.int.b.ca.der").as_slice(),
    ];
    let ca = include_bytes!("client_auth_revocation/no_ku_chain.root.ca.der");
    let revocation = None;
    assert_eq!(check_cert(ee, intermediates, ca, revocation), Ok(()));
}

#[test]
fn no_relevant_crl_chain_depth_allow_unknown() {
    let ee = include_bytes!("client_auth_revocation/no_ku_chain.ee.der");
    let intermediates = &[
        include_bytes!("client_auth_revocation/no_ku_chain.int.a.ca.der").as_slice(),
        include_bytes!("client_auth_revocation/no_ku_chain.int.b.ca.der").as_slice(),
    ];
    let ca = include_bytes!("client_auth_revocation/no_ku_chain.root.ca.der");

    let crls = &[&webpki::CertRevocationList::Borrowed(
        webpki::BorrowedCertRevocationList::from_der(
            include_bytes!(
                "client_auth_revocation/no_relevant_crl_chain_depth_allow_unknown.crl.der"
            )
            .as_slice(),
        )
        .unwrap(),
    )];
    let builder = RevocationOptionsBuilder::new(crls).unwrap();

    let builder = builder.with_status_policy(UnknownStatusPolicy::Allow);
    let revocation = Some(builder.build());
    assert_eq!(check_cert(ee, intermediates, ca, revocation), Ok(()));
}

#[cfg(feature = "alloc")]
#[test]
fn no_relevant_crl_chain_depth_allow_unknown_owned() {
    let ee = include_bytes!("client_auth_revocation/no_ku_chain.ee.der");
    let intermediates = &[
        include_bytes!("client_auth_revocation/no_ku_chain.int.a.ca.der").as_slice(),
        include_bytes!("client_auth_revocation/no_ku_chain.int.b.ca.der").as_slice(),
    ];
    let ca = include_bytes!("client_auth_revocation/no_ku_chain.root.ca.der");

    let crls = &[&webpki::CertRevocationList::Owned(
        webpki::OwnedCertRevocationList::from_der(
            include_bytes!(
                "client_auth_revocation/no_relevant_crl_chain_depth_allow_unknown.crl.der"
            )
            .as_slice(),
        )
        .unwrap(),
    )];
    let builder = RevocationOptionsBuilder::new(crls).unwrap();

    let builder = builder.with_status_policy(UnknownStatusPolicy::Allow);
    let revocation = Some(builder.build());
    assert_eq!(check_cert(ee, intermediates, ca, revocation), Ok(()));
}

#[test]
fn no_relevant_crl_chain_depth_forbid_unknown() {
    let ee = include_bytes!("client_auth_revocation/no_ku_chain.ee.der");
    let intermediates = &[
        include_bytes!("client_auth_revocation/no_ku_chain.int.a.ca.der").as_slice(),
        include_bytes!("client_auth_revocation/no_ku_chain.int.b.ca.der").as_slice(),
    ];
    let ca = include_bytes!("client_auth_revocation/no_ku_chain.root.ca.der");

    let crls = &[&webpki::CertRevocationList::Borrowed(
        webpki::BorrowedCertRevocationList::from_der(
            include_bytes!(
                "client_auth_revocation/no_relevant_crl_chain_depth_forbid_unknown.crl.der"
            )
            .as_slice(),
        )
        .unwrap(),
    )];
    let builder = RevocationOptionsBuilder::new(crls).unwrap();
    let revocation = Some(builder.build());
    assert_eq!(
        check_cert(ee, intermediates, ca, revocation),
        Err(webpki::Error::UnknownRevocationStatus)
    );
}

#[cfg(feature = "alloc")]
#[test]
fn no_relevant_crl_chain_depth_forbid_unknown_owned() {
    let ee = include_bytes!("client_auth_revocation/no_ku_chain.ee.der");
    let intermediates = &[
        include_bytes!("client_auth_revocation/no_ku_chain.int.a.ca.der").as_slice(),
        include_bytes!("client_auth_revocation/no_ku_chain.int.b.ca.der").as_slice(),
    ];
    let ca = include_bytes!("client_auth_revocation/no_ku_chain.root.ca.der");

    let crls = &[&webpki::CertRevocationList::Owned(
        webpki::OwnedCertRevocationList::from_der(
            include_bytes!(
                "client_auth_revocation/no_relevant_crl_chain_depth_forbid_unknown.crl.der"
            )
            .as_slice(),
        )
        .unwrap(),
    )];
    let builder = RevocationOptionsBuilder::new(crls).unwrap();
    let revocation = Some(builder.build());
    assert_eq!(
        check_cert(ee, intermediates, ca, revocation),
        Err(webpki::Error::UnknownRevocationStatus)
    );
}

#[test]
fn int_not_revoked_chain_depth() {
    let ee = include_bytes!("client_auth_revocation/no_ku_chain.ee.der");
    let intermediates = &[
        include_bytes!("client_auth_revocation/no_ku_chain.int.a.ca.der").as_slice(),
        include_bytes!("client_auth_revocation/no_ku_chain.int.b.ca.der").as_slice(),
    ];
    let ca = include_bytes!("client_auth_revocation/no_ku_chain.root.ca.der");

    let crls = &[&webpki::CertRevocationList::Borrowed(
        webpki::BorrowedCertRevocationList::from_der(
            include_bytes!("client_auth_revocation/int_not_revoked_chain_depth.crl.der").as_slice(),
        )
        .unwrap(),
    )];
    let builder = RevocationOptionsBuilder::new(crls).unwrap();

    let builder = builder.with_status_policy(UnknownStatusPolicy::Allow);
    let revocation = Some(builder.build());
    assert_eq!(check_cert(ee, intermediates, ca, revocation), Ok(()));
}

#[cfg(feature = "alloc")]
#[test]
fn int_not_revoked_chain_depth_owned() {
    let ee = include_bytes!("client_auth_revocation/no_ku_chain.ee.der");
    let intermediates = &[
        include_bytes!("client_auth_revocation/no_ku_chain.int.a.ca.der").as_slice(),
        include_bytes!("client_auth_revocation/no_ku_chain.int.b.ca.der").as_slice(),
    ];
    let ca = include_bytes!("client_auth_revocation/no_ku_chain.root.ca.der");

    let crls = &[&webpki::CertRevocationList::Owned(
        webpki::OwnedCertRevocationList::from_der(
            include_bytes!("client_auth_revocation/int_not_revoked_chain_depth.crl.der").as_slice(),
        )
        .unwrap(),
    )];
    let builder = RevocationOptionsBuilder::new(crls).unwrap();

    let builder = builder.with_status_policy(UnknownStatusPolicy::Allow);
    let revocation = Some(builder.build());
    assert_eq!(check_cert(ee, intermediates, ca, revocation), Ok(()));
}

#[test]
fn int_not_revoked_chain_depth_forbid_unknown() {
    let ee = include_bytes!("client_auth_revocation/no_ku_chain.ee.der");
    let intermediates = &[
        include_bytes!("client_auth_revocation/no_ku_chain.int.a.ca.der").as_slice(),
        include_bytes!("client_auth_revocation/no_ku_chain.int.b.ca.der").as_slice(),
    ];
    let ca = include_bytes!("client_auth_revocation/no_ku_chain.root.ca.der");

    let crls = &[
        &webpki::CertRevocationList::Borrowed(
            webpki::BorrowedCertRevocationList::from_der(
                include_bytes!(
                    "client_auth_revocation/int_not_revoked_chain_depth_forbid_unknown_ee.crl.der"
                )
                .as_slice(),
            )
            .unwrap(),
        ),
        &webpki::CertRevocationList::Borrowed(
            webpki::BorrowedCertRevocationList::from_der(
                include_bytes!(
                    "client_auth_revocation/int_not_revoked_chain_depth_forbid_unknown.crl.der"
                )
                .as_slice(),
            )
            .unwrap(),
        ),
        &webpki::CertRevocationList::Borrowed(
            webpki::BorrowedCertRevocationList::from_der(
                include_bytes!(
                    "client_auth_revocation/int_not_revoked_chain_depth_forbid_unknown_b.crl.der"
                )
                .as_slice(),
            )
            .unwrap(),
        ),
    ];
    let builder = RevocationOptionsBuilder::new(crls).unwrap();
    let revocation = Some(builder.build());
    assert_eq!(check_cert(ee, intermediates, ca, revocation), Ok(()));
}

#[cfg(feature = "alloc")]
#[test]
fn int_not_revoked_chain_depth_forbid_unknown_owned() {
    let ee = include_bytes!("client_auth_revocation/no_ku_chain.ee.der");
    let intermediates = &[
        include_bytes!("client_auth_revocation/no_ku_chain.int.a.ca.der").as_slice(),
        include_bytes!("client_auth_revocation/no_ku_chain.int.b.ca.der").as_slice(),
    ];
    let ca = include_bytes!("client_auth_revocation/no_ku_chain.root.ca.der");

    let crls = &[
        &webpki::CertRevocationList::Owned(
            webpki::OwnedCertRevocationList::from_der(
                include_bytes!(
                    "client_auth_revocation/int_not_revoked_chain_depth_forbid_unknown_ee.crl.der"
                )
                .as_slice(),
            )
            .unwrap(),
        ),
        &webpki::CertRevocationList::Owned(
            webpki::OwnedCertRevocationList::from_der(
                include_bytes!(
                    "client_auth_revocation/int_not_revoked_chain_depth_forbid_unknown.crl.der"
                )
                .as_slice(),
            )
            .unwrap(),
        ),
        &webpki::CertRevocationList::Owned(
            webpki::OwnedCertRevocationList::from_der(
                include_bytes!(
                    "client_auth_revocation/int_not_revoked_chain_depth_forbid_unknown_b.crl.der"
                )
                .as_slice(),
            )
            .unwrap(),
        ),
    ];
    let builder = RevocationOptionsBuilder::new(crls).unwrap();
    let revocation = Some(builder.build());
    assert_eq!(check_cert(ee, intermediates, ca, revocation), Ok(()));
}

#[test]
fn int_revoked_badsig_chain_depth() {
    let ee = include_bytes!("client_auth_revocation/no_ku_chain.ee.der");
    let intermediates = &[
        include_bytes!("client_auth_revocation/no_ku_chain.int.a.ca.der").as_slice(),
        include_bytes!("client_auth_revocation/no_ku_chain.int.b.ca.der").as_slice(),
    ];
    let ca = include_bytes!("client_auth_revocation/no_ku_chain.root.ca.der");

    let crls = &[&webpki::CertRevocationList::Borrowed(
        webpki::BorrowedCertRevocationList::from_der(
            include_bytes!("client_auth_revocation/int_revoked_badsig_chain_depth.crl.der")
                .as_slice(),
        )
        .unwrap(),
    )];
    let builder = RevocationOptionsBuilder::new(crls).unwrap();

    let builder = builder.with_status_policy(UnknownStatusPolicy::Allow);
    let revocation = Some(builder.build());
    assert_eq!(
        check_cert(ee, intermediates, ca, revocation),
        Err(webpki::Error::InvalidCrlSignatureForPublicKey)
    );
}

#[cfg(feature = "alloc")]
#[test]
fn int_revoked_badsig_chain_depth_owned() {
    let ee = include_bytes!("client_auth_revocation/no_ku_chain.ee.der");
    let intermediates = &[
        include_bytes!("client_auth_revocation/no_ku_chain.int.a.ca.der").as_slice(),
        include_bytes!("client_auth_revocation/no_ku_chain.int.b.ca.der").as_slice(),
    ];
    let ca = include_bytes!("client_auth_revocation/no_ku_chain.root.ca.der");

    let crls = &[&webpki::CertRevocationList::Owned(
        webpki::OwnedCertRevocationList::from_der(
            include_bytes!("client_auth_revocation/int_revoked_badsig_chain_depth.crl.der")
                .as_slice(),
        )
        .unwrap(),
    )];
    let builder = RevocationOptionsBuilder::new(crls).unwrap();

    let builder = builder.with_status_policy(UnknownStatusPolicy::Allow);
    let revocation = Some(builder.build());
    assert_eq!(
        check_cert(ee, intermediates, ca, revocation),
        Err(webpki::Error::InvalidCrlSignatureForPublicKey)
    );
}

#[test]
fn int_revoked_wrong_ku_chain_depth() {
    let ee = include_bytes!("client_auth_revocation/no_crl_ku_chain.ee.der");
    let intermediates = &[
        include_bytes!("client_auth_revocation/no_crl_ku_chain.int.a.ca.der").as_slice(),
        include_bytes!("client_auth_revocation/no_crl_ku_chain.int.b.ca.der").as_slice(),
    ];
    let ca = include_bytes!("client_auth_revocation/no_crl_ku_chain.root.ca.der");

    let crls = &[&webpki::CertRevocationList::Borrowed(
        webpki::BorrowedCertRevocationList::from_der(
            include_bytes!("client_auth_revocation/int_revoked_wrong_ku_chain_depth.crl.der")
                .as_slice(),
        )
        .unwrap(),
    )];
    let builder = RevocationOptionsBuilder::new(crls).unwrap();

    let builder = builder.with_status_policy(UnknownStatusPolicy::Allow);
    let revocation = Some(builder.build());
    assert_eq!(
        check_cert(ee, intermediates, ca, revocation),
        Err(webpki::Error::IssuerNotCrlSigner)
    );
}

#[cfg(feature = "alloc")]
#[test]
fn int_revoked_wrong_ku_chain_depth_owned() {
    let ee = include_bytes!("client_auth_revocation/no_crl_ku_chain.ee.der");
    let intermediates = &[
        include_bytes!("client_auth_revocation/no_crl_ku_chain.int.a.ca.der").as_slice(),
        include_bytes!("client_auth_revocation/no_crl_ku_chain.int.b.ca.der").as_slice(),
    ];
    let ca = include_bytes!("client_auth_revocation/no_crl_ku_chain.root.ca.der");

    let crls = &[&webpki::CertRevocationList::Owned(
        webpki::OwnedCertRevocationList::from_der(
            include_bytes!("client_auth_revocation/int_revoked_wrong_ku_chain_depth.crl.der")
                .as_slice(),
        )
        .unwrap(),
    )];
    let builder = RevocationOptionsBuilder::new(crls).unwrap();

    let builder = builder.with_status_policy(UnknownStatusPolicy::Allow);
    let revocation = Some(builder.build());
    assert_eq!(
        check_cert(ee, intermediates, ca, revocation),
        Err(webpki::Error::IssuerNotCrlSigner)
    );
}

#[test]
fn ee_revoked_chain_depth() {
    let ee = include_bytes!("client_auth_revocation/no_ku_chain.ee.der");
    let intermediates = &[
        include_bytes!("client_auth_revocation/no_ku_chain.int.a.ca.der").as_slice(),
        include_bytes!("client_auth_revocation/no_ku_chain.int.b.ca.der").as_slice(),
    ];
    let ca = include_bytes!("client_auth_revocation/no_ku_chain.root.ca.der");

    let crls = &[&webpki::CertRevocationList::Borrowed(
        webpki::BorrowedCertRevocationList::from_der(
            include_bytes!("client_auth_revocation/ee_revoked_chain_depth.crl.der").as_slice(),
        )
        .unwrap(),
    )];
    let builder = RevocationOptionsBuilder::new(crls).unwrap();

    let builder = builder.with_status_policy(UnknownStatusPolicy::Allow);
    let revocation = Some(builder.build());
    assert_eq!(
        check_cert(ee, intermediates, ca, revocation),
        Err(webpki::Error::CertRevoked)
    );
}

#[cfg(feature = "alloc")]
#[test]
fn ee_revoked_chain_depth_owned() {
    let ee = include_bytes!("client_auth_revocation/no_ku_chain.ee.der");
    let intermediates = &[
        include_bytes!("client_auth_revocation/no_ku_chain.int.a.ca.der").as_slice(),
        include_bytes!("client_auth_revocation/no_ku_chain.int.b.ca.der").as_slice(),
    ];
    let ca = include_bytes!("client_auth_revocation/no_ku_chain.root.ca.der");

    let crls = &[&webpki::CertRevocationList::Owned(
        webpki::OwnedCertRevocationList::from_der(
            include_bytes!("client_auth_revocation/ee_revoked_chain_depth.crl.der").as_slice(),
        )
        .unwrap(),
    )];
    let builder = RevocationOptionsBuilder::new(crls).unwrap();

    let builder = builder.with_status_policy(UnknownStatusPolicy::Allow);
    let revocation = Some(builder.build());
    assert_eq!(
        check_cert(ee, intermediates, ca, revocation),
        Err(webpki::Error::CertRevoked)
    );
}

#[test]
fn int_revoked_no_ku_chain_depth() {
    let ee = include_bytes!("client_auth_revocation/no_ku_chain.ee.der");
    let intermediates = &[
        include_bytes!("client_auth_revocation/no_ku_chain.int.a.ca.der").as_slice(),
        include_bytes!("client_auth_revocation/no_ku_chain.int.b.ca.der").as_slice(),
    ];
    let ca = include_bytes!("client_auth_revocation/no_ku_chain.root.ca.der");

    let crls = &[&webpki::CertRevocationList::Borrowed(
        webpki::BorrowedCertRevocationList::from_der(
            include_bytes!("client_auth_revocation/int_revoked_no_ku_chain_depth.crl.der")
                .as_slice(),
        )
        .unwrap(),
    )];
    let builder = RevocationOptionsBuilder::new(crls).unwrap();

    let builder = builder.with_status_policy(UnknownStatusPolicy::Allow);
    let revocation = Some(builder.build());
    assert_eq!(
        check_cert(ee, intermediates, ca, revocation),
        Err(webpki::Error::CertRevoked)
    );
}

#[cfg(feature = "alloc")]
#[test]
fn int_revoked_no_ku_chain_depth_owned() {
    let ee = include_bytes!("client_auth_revocation/no_ku_chain.ee.der");
    let intermediates = &[
        include_bytes!("client_auth_revocation/no_ku_chain.int.a.ca.der").as_slice(),
        include_bytes!("client_auth_revocation/no_ku_chain.int.b.ca.der").as_slice(),
    ];
    let ca = include_bytes!("client_auth_revocation/no_ku_chain.root.ca.der");

    let crls = &[&webpki::CertRevocationList::Owned(
        webpki::OwnedCertRevocationList::from_der(
            include_bytes!("client_auth_revocation/int_revoked_no_ku_chain_depth.crl.der")
                .as_slice(),
        )
        .unwrap(),
    )];
    let builder = RevocationOptionsBuilder::new(crls).unwrap();

    let builder = builder.with_status_policy(UnknownStatusPolicy::Allow);
    let revocation = Some(builder.build());
    assert_eq!(
        check_cert(ee, intermediates, ca, revocation),
        Err(webpki::Error::CertRevoked)
    );
}

#[test]
fn int_revoked_crl_ku_chain_depth() {
    let ee = include_bytes!("client_auth_revocation/ku_chain.ee.der");
    let intermediates = &[
        include_bytes!("client_auth_revocation/ku_chain.int.a.ca.der").as_slice(),
        include_bytes!("client_auth_revocation/ku_chain.int.b.ca.der").as_slice(),
    ];
    let ca = include_bytes!("client_auth_revocation/ku_chain.root.ca.der");

    let crls = &[&webpki::CertRevocationList::Borrowed(
        webpki::BorrowedCertRevocationList::from_der(
            include_bytes!("client_auth_revocation/int_revoked_crl_ku_chain_depth.crl.der")
                .as_slice(),
        )
        .unwrap(),
    )];
    let builder = RevocationOptionsBuilder::new(crls).unwrap();

    let builder = builder.with_status_policy(UnknownStatusPolicy::Allow);
    let revocation = Some(builder.build());
    assert_eq!(
        check_cert(ee, intermediates, ca, revocation),
        Err(webpki::Error::CertRevoked)
    );
}

#[cfg(feature = "alloc")]
#[test]
fn int_revoked_crl_ku_chain_depth_owned() {
    let ee = include_bytes!("client_auth_revocation/ku_chain.ee.der");
    let intermediates = &[
        include_bytes!("client_auth_revocation/ku_chain.int.a.ca.der").as_slice(),
        include_bytes!("client_auth_revocation/ku_chain.int.b.ca.der").as_slice(),
    ];
    let ca = include_bytes!("client_auth_revocation/ku_chain.root.ca.der");

    let crls = &[&webpki::CertRevocationList::Owned(
        webpki::OwnedCertRevocationList::from_der(
            include_bytes!("client_auth_revocation/int_revoked_crl_ku_chain_depth.crl.der")
                .as_slice(),
        )
        .unwrap(),
    )];
    let builder = RevocationOptionsBuilder::new(crls).unwrap();

    let builder = builder.with_status_policy(UnknownStatusPolicy::Allow);
    let revocation = Some(builder.build());
    assert_eq!(
        check_cert(ee, intermediates, ca, revocation),
        Err(webpki::Error::CertRevoked)
    );
}

#[test]
fn ee_with_top_bit_set_serial_revoked() {
    let ee = include_bytes!("client_auth_revocation/ku_chain.topbit.ee.der");
    let intermediates = &[
        include_bytes!("client_auth_revocation/ku_chain.int.a.ca.der").as_slice(),
        include_bytes!("client_auth_revocation/ku_chain.int.b.ca.der").as_slice(),
    ];
    let ca = include_bytes!("client_auth_revocation/ku_chain.root.ca.der");

    let crls = &[&webpki::CertRevocationList::Borrowed(
        webpki::BorrowedCertRevocationList::from_der(
            include_bytes!("client_auth_revocation/ee_with_top_bit_set_serial_revoked.crl.der")
                .as_slice(),
        )
        .unwrap(),
    )];
    let builder = RevocationOptionsBuilder::new(crls).unwrap();

    let builder = builder.with_status_policy(UnknownStatusPolicy::Allow);
    let revocation = Some(builder.build());
    assert_eq!(
        check_cert(ee, intermediates, ca, revocation),
        Err(webpki::Error::CertRevoked)
    );
}

#[cfg(feature = "alloc")]
#[test]
fn ee_with_top_bit_set_serial_revoked_owned() {
    let ee = include_bytes!("client_auth_revocation/ku_chain.topbit.ee.der");
    let intermediates = &[
        include_bytes!("client_auth_revocation/ku_chain.int.a.ca.der").as_slice(),
        include_bytes!("client_auth_revocation/ku_chain.int.b.ca.der").as_slice(),
    ];
    let ca = include_bytes!("client_auth_revocation/ku_chain.root.ca.der");

    let crls = &[&webpki::CertRevocationList::Owned(
        webpki::OwnedCertRevocationList::from_der(
            include_bytes!("client_auth_revocation/ee_with_top_bit_set_serial_revoked.crl.der")
                .as_slice(),
        )
        .unwrap(),
    )];
    let builder = RevocationOptionsBuilder::new(crls).unwrap();

    let builder = builder.with_status_policy(UnknownStatusPolicy::Allow);
    let revocation = Some(builder.build());
    assert_eq!(
        check_cert(ee, intermediates, ca, revocation),
        Err(webpki::Error::CertRevoked)
    );
}

#[test]
fn ee_no_dp_crl_idp() {
    let ee = include_bytes!("client_auth_revocation/no_ku_chain.ee.der");
    let intermediates = &[
        include_bytes!("client_auth_revocation/no_ku_chain.int.a.ca.der").as_slice(),
        include_bytes!("client_auth_revocation/no_ku_chain.int.b.ca.der").as_slice(),
    ];
    let ca = include_bytes!("client_auth_revocation/no_ku_chain.root.ca.der");

    let crls = &[&webpki::CertRevocationList::Borrowed(
        webpki::BorrowedCertRevocationList::from_der(
            include_bytes!("client_auth_revocation/ee_no_dp_crl_idp.crl.der").as_slice(),
        )
        .unwrap(),
    )];
    let builder = RevocationOptionsBuilder::new(crls).unwrap();

    let builder = builder.with_depth(RevocationCheckDepth::EndEntity);
    let revocation = Some(builder.build());
    assert_eq!(check_cert(ee, intermediates, ca, revocation), Ok(()));
}

#[cfg(feature = "alloc")]
#[test]
fn ee_no_dp_crl_idp_owned() {
    let ee = include_bytes!("client_auth_revocation/no_ku_chain.ee.der");
    let intermediates = &[
        include_bytes!("client_auth_revocation/no_ku_chain.int.a.ca.der").as_slice(),
        include_bytes!("client_auth_revocation/no_ku_chain.int.b.ca.der").as_slice(),
    ];
    let ca = include_bytes!("client_auth_revocation/no_ku_chain.root.ca.der");

    let crls = &[&webpki::CertRevocationList::Owned(
        webpki::OwnedCertRevocationList::from_der(
            include_bytes!("client_auth_revocation/ee_no_dp_crl_idp.crl.der").as_slice(),
        )
        .unwrap(),
    )];
    let builder = RevocationOptionsBuilder::new(crls).unwrap();

    let builder = builder.with_depth(RevocationCheckDepth::EndEntity);
    let revocation = Some(builder.build());
    assert_eq!(check_cert(ee, intermediates, ca, revocation), Ok(()));
}

#[test]
fn ee_not_revoked_crl_no_idp() {
    let ee = include_bytes!("client_auth_revocation/dp_chain.ee.der");
    let intermediates = &[
        include_bytes!("client_auth_revocation/dp_chain.int.a.ca.der").as_slice(),
        include_bytes!("client_auth_revocation/dp_chain.int.b.ca.der").as_slice(),
    ];
    let ca = include_bytes!("client_auth_revocation/dp_chain.root.ca.der");

    let crls = &[&webpki::CertRevocationList::Borrowed(
        webpki::BorrowedCertRevocationList::from_der(
            include_bytes!("client_auth_revocation/ee_not_revoked_crl_no_idp.crl.der").as_slice(),
        )
        .unwrap(),
    )];
    let builder = RevocationOptionsBuilder::new(crls).unwrap();

    let builder = builder.with_depth(RevocationCheckDepth::EndEntity);
    let revocation = Some(builder.build());
    assert_eq!(check_cert(ee, intermediates, ca, revocation), Ok(()));
}

#[cfg(feature = "alloc")]
#[test]
fn ee_not_revoked_crl_no_idp_owned() {
    let ee = include_bytes!("client_auth_revocation/dp_chain.ee.der");
    let intermediates = &[
        include_bytes!("client_auth_revocation/dp_chain.int.a.ca.der").as_slice(),
        include_bytes!("client_auth_revocation/dp_chain.int.b.ca.der").as_slice(),
    ];
    let ca = include_bytes!("client_auth_revocation/dp_chain.root.ca.der");

    let crls = &[&webpki::CertRevocationList::Owned(
        webpki::OwnedCertRevocationList::from_der(
            include_bytes!("client_auth_revocation/ee_not_revoked_crl_no_idp.crl.der").as_slice(),
        )
        .unwrap(),
    )];
    let builder = RevocationOptionsBuilder::new(crls).unwrap();

    let builder = builder.with_depth(RevocationCheckDepth::EndEntity);
    let revocation = Some(builder.build());
    assert_eq!(check_cert(ee, intermediates, ca, revocation), Ok(()));
}

#[test]
fn ee_revoked_crl_no_idp() {
    let ee = include_bytes!("client_auth_revocation/dp_chain.ee.der");
    let intermediates = &[
        include_bytes!("client_auth_revocation/dp_chain.int.a.ca.der").as_slice(),
        include_bytes!("client_auth_revocation/dp_chain.int.b.ca.der").as_slice(),
    ];
    let ca = include_bytes!("client_auth_revocation/dp_chain.root.ca.der");

    let crls = &[&webpki::CertRevocationList::Borrowed(
        webpki::BorrowedCertRevocationList::from_der(
            include_bytes!("client_auth_revocation/ee_revoked_crl_no_idp.crl.der").as_slice(),
        )
        .unwrap(),
    )];
    let builder = RevocationOptionsBuilder::new(crls).unwrap();

    let builder = builder.with_depth(RevocationCheckDepth::EndEntity);
    let revocation = Some(builder.build());
    assert_eq!(
        check_cert(ee, intermediates, ca, revocation),
        Err(webpki::Error::CertRevoked)
    );
}

#[cfg(feature = "alloc")]
#[test]
fn ee_revoked_crl_no_idp_owned() {
    let ee = include_bytes!("client_auth_revocation/dp_chain.ee.der");
    let intermediates = &[
        include_bytes!("client_auth_revocation/dp_chain.int.a.ca.der").as_slice(),
        include_bytes!("client_auth_revocation/dp_chain.int.b.ca.der").as_slice(),
    ];
    let ca = include_bytes!("client_auth_revocation/dp_chain.root.ca.der");

    let crls = &[&webpki::CertRevocationList::Owned(
        webpki::OwnedCertRevocationList::from_der(
            include_bytes!("client_auth_revocation/ee_revoked_crl_no_idp.crl.der").as_slice(),
        )
        .unwrap(),
    )];
    let builder = RevocationOptionsBuilder::new(crls).unwrap();

    let builder = builder.with_depth(RevocationCheckDepth::EndEntity);
    let revocation = Some(builder.build());
    assert_eq!(
        check_cert(ee, intermediates, ca, revocation),
        Err(webpki::Error::CertRevoked)
    );
}

#[test]
fn ee_crl_mismatched_idp_unknown_status() {
    let ee = include_bytes!("client_auth_revocation/dp_chain.ee.der");
    let intermediates = &[
        include_bytes!("client_auth_revocation/dp_chain.int.a.ca.der").as_slice(),
        include_bytes!("client_auth_revocation/dp_chain.int.b.ca.der").as_slice(),
    ];
    let ca = include_bytes!("client_auth_revocation/dp_chain.root.ca.der");

    let crls = &[&webpki::CertRevocationList::Borrowed(
        webpki::BorrowedCertRevocationList::from_der(
            include_bytes!("client_auth_revocation/ee_crl_mismatched_idp_unknown_status.crl.der")
                .as_slice(),
        )
        .unwrap(),
    )];
    let builder = RevocationOptionsBuilder::new(crls).unwrap();

    let builder = builder.with_depth(RevocationCheckDepth::EndEntity);
    let revocation = Some(builder.build());
    assert_eq!(
        check_cert(ee, intermediates, ca, revocation),
        Err(webpki::Error::UnknownRevocationStatus)
    );
}

#[cfg(feature = "alloc")]
#[test]
fn ee_crl_mismatched_idp_unknown_status_owned() {
    let ee = include_bytes!("client_auth_revocation/dp_chain.ee.der");
    let intermediates = &[
        include_bytes!("client_auth_revocation/dp_chain.int.a.ca.der").as_slice(),
        include_bytes!("client_auth_revocation/dp_chain.int.b.ca.der").as_slice(),
    ];
    let ca = include_bytes!("client_auth_revocation/dp_chain.root.ca.der");

    let crls = &[&webpki::CertRevocationList::Owned(
        webpki::OwnedCertRevocationList::from_der(
            include_bytes!("client_auth_revocation/ee_crl_mismatched_idp_unknown_status.crl.der")
                .as_slice(),
        )
        .unwrap(),
    )];
    let builder = RevocationOptionsBuilder::new(crls).unwrap();

    let builder = builder.with_depth(RevocationCheckDepth::EndEntity);
    let revocation = Some(builder.build());
    assert_eq!(
        check_cert(ee, intermediates, ca, revocation),
        Err(webpki::Error::UnknownRevocationStatus)
    );
}

#[test]
fn ee_indirect_dp_unknown_status() {
    let ee = include_bytes!("client_auth_revocation/indirect_dp_chain.ee.der");
    let intermediates = &[
        include_bytes!("client_auth_revocation/indirect_dp_chain.int.a.ca.der").as_slice(),
        include_bytes!("client_auth_revocation/indirect_dp_chain.int.b.ca.der").as_slice(),
    ];
    let ca = include_bytes!("client_auth_revocation/indirect_dp_chain.root.ca.der");

    let crls = &[&webpki::CertRevocationList::Borrowed(
        webpki::BorrowedCertRevocationList::from_der(
            include_bytes!("client_auth_revocation/ee_indirect_dp_unknown_status.crl.der")
                .as_slice(),
        )
        .unwrap(),
    )];
    let builder = RevocationOptionsBuilder::new(crls).unwrap();

    let builder = builder.with_depth(RevocationCheckDepth::EndEntity);
    let revocation = Some(builder.build());
    assert_eq!(
        check_cert(ee, intermediates, ca, revocation),
        Err(webpki::Error::UnknownRevocationStatus)
    );
}

#[cfg(feature = "alloc")]
#[test]
fn ee_indirect_dp_unknown_status_owned() {
    let ee = include_bytes!("client_auth_revocation/indirect_dp_chain.ee.der");
    let intermediates = &[
        include_bytes!("client_auth_revocation/indirect_dp_chain.int.a.ca.der").as_slice(),
        include_bytes!("client_auth_revocation/indirect_dp_chain.int.b.ca.der").as_slice(),
    ];
    let ca = include_bytes!("client_auth_revocation/indirect_dp_chain.root.ca.der");

    let crls = &[&webpki::CertRevocationList::Owned(
        webpki::OwnedCertRevocationList::from_der(
            include_bytes!("client_auth_revocation/ee_indirect_dp_unknown_status.crl.der")
                .as_slice(),
        )
        .unwrap(),
    )];
    let builder = RevocationOptionsBuilder::new(crls).unwrap();

    let builder = builder.with_depth(RevocationCheckDepth::EndEntity);
    let revocation = Some(builder.build());
    assert_eq!(
        check_cert(ee, intermediates, ca, revocation),
        Err(webpki::Error::UnknownRevocationStatus)
    );
}

#[test]
fn ee_reasons_dp_unknown_status() {
    let ee = include_bytes!("client_auth_revocation/reasons_dp_chain.ee.der");
    let intermediates = &[
        include_bytes!("client_auth_revocation/reasons_dp_chain.int.a.ca.der").as_slice(),
        include_bytes!("client_auth_revocation/reasons_dp_chain.int.b.ca.der").as_slice(),
    ];
    let ca = include_bytes!("client_auth_revocation/reasons_dp_chain.root.ca.der");

    let crls = &[&webpki::CertRevocationList::Borrowed(
        webpki::BorrowedCertRevocationList::from_der(
            include_bytes!("client_auth_revocation/ee_reasons_dp_unknown_status.crl.der")
                .as_slice(),
        )
        .unwrap(),
    )];
    let builder = RevocationOptionsBuilder::new(crls).unwrap();

    let builder = builder.with_depth(RevocationCheckDepth::EndEntity);
    let revocation = Some(builder.build());
    assert_eq!(
        check_cert(ee, intermediates, ca, revocation),
        Err(webpki::Error::UnknownRevocationStatus)
    );
}

#[cfg(feature = "alloc")]
#[test]
fn ee_reasons_dp_unknown_status_owned() {
    let ee = include_bytes!("client_auth_revocation/reasons_dp_chain.ee.der");
    let intermediates = &[
        include_bytes!("client_auth_revocation/reasons_dp_chain.int.a.ca.der").as_slice(),
        include_bytes!("client_auth_revocation/reasons_dp_chain.int.b.ca.der").as_slice(),
    ];
    let ca = include_bytes!("client_auth_revocation/reasons_dp_chain.root.ca.der");

    let crls = &[&webpki::CertRevocationList::Owned(
        webpki::OwnedCertRevocationList::from_der(
            include_bytes!("client_auth_revocation/ee_reasons_dp_unknown_status.crl.der")
                .as_slice(),
        )
        .unwrap(),
    )];
    let builder = RevocationOptionsBuilder::new(crls).unwrap();

    let builder = builder.with_depth(RevocationCheckDepth::EndEntity);
    let revocation = Some(builder.build());
    assert_eq!(
        check_cert(ee, intermediates, ca, revocation),
        Err(webpki::Error::UnknownRevocationStatus)
    );
}

#[test]
fn ee_nofullname_dp_unknown_status() {
    let ee = include_bytes!("client_auth_revocation/nofullname_dp_chain.ee.der");
    let intermediates = &[
        include_bytes!("client_auth_revocation/nofullname_dp_chain.int.a.ca.der").as_slice(),
        include_bytes!("client_auth_revocation/nofullname_dp_chain.int.b.ca.der").as_slice(),
    ];
    let ca = include_bytes!("client_auth_revocation/nofullname_dp_chain.root.ca.der");

    let crls = &[&webpki::CertRevocationList::Borrowed(
        webpki::BorrowedCertRevocationList::from_der(
            include_bytes!("client_auth_revocation/ee_nofullname_dp_unknown_status.crl.der")
                .as_slice(),
        )
        .unwrap(),
    )];
    let builder = RevocationOptionsBuilder::new(crls).unwrap();

    let builder = builder.with_depth(RevocationCheckDepth::EndEntity);
    let revocation = Some(builder.build());
    assert_eq!(
        check_cert(ee, intermediates, ca, revocation),
        Err(webpki::Error::UnknownRevocationStatus)
    );
}

#[cfg(feature = "alloc")]
#[test]
fn ee_nofullname_dp_unknown_status_owned() {
    let ee = include_bytes!("client_auth_revocation/nofullname_dp_chain.ee.der");
    let intermediates = &[
        include_bytes!("client_auth_revocation/nofullname_dp_chain.int.a.ca.der").as_slice(),
        include_bytes!("client_auth_revocation/nofullname_dp_chain.int.b.ca.der").as_slice(),
    ];
    let ca = include_bytes!("client_auth_revocation/nofullname_dp_chain.root.ca.der");

    let crls = &[&webpki::CertRevocationList::Owned(
        webpki::OwnedCertRevocationList::from_der(
            include_bytes!("client_auth_revocation/ee_nofullname_dp_unknown_status.crl.der")
                .as_slice(),
        )
        .unwrap(),
    )];
    let builder = RevocationOptionsBuilder::new(crls).unwrap();

    let builder = builder.with_depth(RevocationCheckDepth::EndEntity);
    let revocation = Some(builder.build());
    assert_eq!(
        check_cert(ee, intermediates, ca, revocation),
        Err(webpki::Error::UnknownRevocationStatus)
    );
}

#[test]
fn ee_dp_idp_match() {
    let ee = include_bytes!("client_auth_revocation/dp_chain.ee.der");
    let intermediates = &[
        include_bytes!("client_auth_revocation/dp_chain.int.a.ca.der").as_slice(),
        include_bytes!("client_auth_revocation/dp_chain.int.b.ca.der").as_slice(),
    ];
    let ca = include_bytes!("client_auth_revocation/dp_chain.root.ca.der");

    let crls = &[&webpki::CertRevocationList::Borrowed(
        webpki::BorrowedCertRevocationList::from_der(
            include_bytes!("client_auth_revocation/ee_dp_idp_match.crl.der").as_slice(),
        )
        .unwrap(),
    )];
    let builder = RevocationOptionsBuilder::new(crls).unwrap();

    let builder = builder.with_depth(RevocationCheckDepth::EndEntity);
    let revocation = Some(builder.build());
    assert_eq!(check_cert(ee, intermediates, ca, revocation), Ok(()));
}

#[cfg(feature = "alloc")]
#[test]
fn ee_dp_idp_match_owned() {
    let ee = include_bytes!("client_auth_revocation/dp_chain.ee.der");
    let intermediates = &[
        include_bytes!("client_auth_revocation/dp_chain.int.a.ca.der").as_slice(),
        include_bytes!("client_auth_revocation/dp_chain.int.b.ca.der").as_slice(),
    ];
    let ca = include_bytes!("client_auth_revocation/dp_chain.root.ca.der");

    let crls = &[&webpki::CertRevocationList::Owned(
        webpki::OwnedCertRevocationList::from_der(
            include_bytes!("client_auth_revocation/ee_dp_idp_match.crl.der").as_slice(),
        )
        .unwrap(),
    )];
    let builder = RevocationOptionsBuilder::new(crls).unwrap();

    let builder = builder.with_depth(RevocationCheckDepth::EndEntity);
    let revocation = Some(builder.build());
    assert_eq!(check_cert(ee, intermediates, ca, revocation), Ok(()));
}

#[test]
fn ee_dp_invalid() {
    let ee = include_bytes!("client_auth_revocation/invalid_dp_chain.ee.der");
    let intermediates = &[
        include_bytes!("client_auth_revocation/invalid_dp_chain.int.a.ca.der").as_slice(),
        include_bytes!("client_auth_revocation/invalid_dp_chain.int.b.ca.der").as_slice(),
    ];
    let ca = include_bytes!("client_auth_revocation/invalid_dp_chain.root.ca.der");

    let crls = &[&webpki::CertRevocationList::Borrowed(
        webpki::BorrowedCertRevocationList::from_der(
            include_bytes!("client_auth_revocation/ee_dp_invalid.crl.der").as_slice(),
        )
        .unwrap(),
    )];
    let builder = RevocationOptionsBuilder::new(crls).unwrap();

    let builder = builder.with_depth(RevocationCheckDepth::EndEntity);
    let revocation = Some(builder.build());
    assert_eq!(
        check_cert(ee, intermediates, ca, revocation),
        Err(webpki::Error::UnknownRevocationStatus)
    );
}

#[cfg(feature = "alloc")]
#[test]
fn ee_dp_invalid_owned() {
    let ee = include_bytes!("client_auth_revocation/invalid_dp_chain.ee.der");
    let intermediates = &[
        include_bytes!("client_auth_revocation/invalid_dp_chain.int.a.ca.der").as_slice(),
        include_bytes!("client_auth_revocation/invalid_dp_chain.int.b.ca.der").as_slice(),
    ];
    let ca = include_bytes!("client_auth_revocation/invalid_dp_chain.root.ca.der");

    let crls = &[&webpki::CertRevocationList::Owned(
        webpki::OwnedCertRevocationList::from_der(
            include_bytes!("client_auth_revocation/ee_dp_invalid.crl.der").as_slice(),
        )
        .unwrap(),
    )];
    let builder = RevocationOptionsBuilder::new(crls).unwrap();

    let builder = builder.with_depth(RevocationCheckDepth::EndEntity);
    let revocation = Some(builder.build());
    assert_eq!(
        check_cert(ee, intermediates, ca, revocation),
        Err(webpki::Error::UnknownRevocationStatus)
    );
}

#[test]
fn expired_crl_ignore_expiration() {
    let ee = include_bytes!("client_auth_revocation/no_ku_chain.ee.der");
    let intermediates = &[
        include_bytes!("client_auth_revocation/no_ku_chain.int.a.ca.der").as_slice(),
        include_bytes!("client_auth_revocation/no_ku_chain.int.b.ca.der").as_slice(),
    ];
    let ca = include_bytes!("client_auth_revocation/no_ku_chain.root.ca.der");

    let crls = &[&webpki::CertRevocationList::Borrowed(
        webpki::BorrowedCertRevocationList::from_der(
            include_bytes!("client_auth_revocation/expired_crl_ignore_expiration.crl.der")
                .as_slice(),
        )
        .unwrap(),
    )];
    let builder = RevocationOptionsBuilder::new(crls).unwrap();

    let builder = builder.with_status_policy(UnknownStatusPolicy::Allow);
    let revocation = Some(builder.build());
    assert_eq!(check_cert(ee, intermediates, ca, revocation), Ok(()));
}

#[cfg(feature = "alloc")]
#[test]
fn expired_crl_ignore_expiration_owned() {
    let ee = include_bytes!("client_auth_revocation/no_ku_chain.ee.der");
    let intermediates = &[
        include_bytes!("client_auth_revocation/no_ku_chain.int.a.ca.der").as_slice(),
        include_bytes!("client_auth_revocation/no_ku_chain.int.b.ca.der").as_slice(),
    ];
    let ca = include_bytes!("client_auth_revocation/no_ku_chain.root.ca.der");

    let crls = &[&webpki::CertRevocationList::Owned(
        webpki::OwnedCertRevocationList::from_der(
            include_bytes!("client_auth_revocation/expired_crl_ignore_expiration.crl.der")
                .as_slice(),
        )
        .unwrap(),
    )];
    let builder = RevocationOptionsBuilder::new(crls).unwrap();

    let builder = builder.with_status_policy(UnknownStatusPolicy::Allow);
    let revocation = Some(builder.build());
    assert_eq!(check_cert(ee, intermediates, ca, revocation), Ok(()));
}

#[test]
fn expired_crl_enforce_expiration() {
    let ee = include_bytes!("client_auth_revocation/no_ku_chain.ee.der");
    let intermediates = &[
        include_bytes!("client_auth_revocation/no_ku_chain.int.a.ca.der").as_slice(),
        include_bytes!("client_auth_revocation/no_ku_chain.int.b.ca.der").as_slice(),
    ];
    let ca = include_bytes!("client_auth_revocation/no_ku_chain.root.ca.der");

    let crls = &[&webpki::CertRevocationList::Borrowed(
        webpki::BorrowedCertRevocationList::from_der(
            include_bytes!("client_auth_revocation/expired_crl_enforce_expiration.crl.der")
                .as_slice(),
        )
        .unwrap(),
    )];
    let builder = RevocationOptionsBuilder::new(crls).unwrap();

    let builder = builder.with_status_policy(UnknownStatusPolicy::Allow);

    let builder = builder.with_expiration_policy(webpki::ExpirationPolicy::Enforce);
    let revocation = Some(builder.build());
    assert_eq!(
        check_cert(ee, intermediates, ca, revocation),
        Err(webpki::Error::CrlExpired {
            time: UnixTime::since_unix_epoch(Duration::from_secs(0x1fed_f00d)),
            next_update: UnixTime::since_unix_epoch(Duration::from_secs(0x1fed_f00d - 10)),
        })
    );
}

#[cfg(feature = "alloc")]
#[test]
fn expired_crl_enforce_expiration_owned() {
    let ee = include_bytes!("client_auth_revocation/no_ku_chain.ee.der");
    let intermediates = &[
        include_bytes!("client_auth_revocation/no_ku_chain.int.a.ca.der").as_slice(),
        include_bytes!("client_auth_revocation/no_ku_chain.int.b.ca.der").as_slice(),
    ];
    let ca = include_bytes!("client_auth_revocation/no_ku_chain.root.ca.der");

    let crls = &[&webpki::CertRevocationList::Owned(
        webpki::OwnedCertRevocationList::from_der(
            include_bytes!("client_auth_revocation/expired_crl_enforce_expiration.crl.der")
                .as_slice(),
        )
        .unwrap(),
    )];
    let builder = RevocationOptionsBuilder::new(crls).unwrap();

    let builder = builder.with_status_policy(UnknownStatusPolicy::Allow);

    let builder = builder.with_expiration_policy(webpki::ExpirationPolicy::Enforce);
    let revocation = Some(builder.build());
    assert_eq!(
        check_cert(ee, intermediates, ca, revocation),
        Err(webpki::Error::CrlExpired {
            time: UnixTime::since_unix_epoch(Duration::from_secs(0x1fed_f00d)),
            next_update: UnixTime::since_unix_epoch(Duration::from_secs(0x1fed_f00d - 10)),
        })
    );
}
