mod common;
use common::get_test_lock;
use std::env;
use std::net::IpAddr;
use tempfile::TempDir;
#[test]
fn test_validate_ip_v4() {
let _lock = get_test_lock();
let ip: IpAddr = "192.168.1.1".parse().unwrap();
let result = fastcert::cert::validate_ip_address(&ip);
assert!(result.is_ok(), "Should accept valid IPv4");
}
#[test]
fn test_validate_ip_v6() {
let _lock = get_test_lock();
let ip: IpAddr = "::1".parse().unwrap();
let result = fastcert::cert::validate_ip_address(&ip);
assert!(result.is_ok(), "Should accept valid IPv6");
}
#[test]
fn test_validate_ip_v6_full() {
let _lock = get_test_lock();
let ip: IpAddr = "2001:0db8:85a3:0000:0000:8a2e:0370:7334".parse().unwrap();
let result = fastcert::cert::validate_ip_address(&ip);
assert!(result.is_ok(), "Should accept full IPv6");
}
#[test]
fn test_validate_email_valid() {
let _lock = get_test_lock();
let result = fastcert::cert::validate_email_address("user@example.com");
assert!(result.is_ok(), "Should accept valid email");
}
#[test]
fn test_validate_email_with_plus() {
let _lock = get_test_lock();
let result = fastcert::cert::validate_email_address("user+tag@example.com");
assert!(result.is_ok(), "Should accept email with plus");
}
#[test]
fn test_validate_email_subdomain() {
let _lock = get_test_lock();
let result = fastcert::cert::validate_email_address("user@sub.example.com");
assert!(result.is_ok(), "Should accept email with subdomain");
}
#[test]
fn test_validate_uri_https() {
let _lock = get_test_lock();
let result = fastcert::cert::validate_uri("https://example.com");
assert!(result.is_ok(), "Should accept HTTPS URI");
}
#[test]
fn test_validate_uri_http() {
let _lock = get_test_lock();
let result = fastcert::cert::validate_uri("http://example.com");
assert!(result.is_ok(), "Should accept HTTP URI");
}
#[test]
fn test_validate_uri_with_path() {
let _lock = get_test_lock();
let result = fastcert::cert::validate_uri("https://example.com/path/to/resource");
assert!(result.is_ok(), "Should accept URI with path");
}
#[test]
fn test_validate_uri_with_query() {
let _lock = get_test_lock();
let result = fastcert::cert::validate_uri("https://example.com?query=value");
assert!(result.is_ok(), "Should accept URI with query");
}
#[test]
fn test_validate_uri_with_port() {
let _lock = get_test_lock();
let result = fastcert::cert::validate_uri("https://example.com:8443");
assert!(result.is_ok(), "Should accept URI with port");
}
#[test]
fn test_validate_hostname_simple() {
let _lock = get_test_lock();
let result = fastcert::cert::validate_hostname("example");
assert!(result.is_ok(), "Should accept simple hostname");
}
#[test]
fn test_validate_hostname_fqdn() {
let _lock = get_test_lock();
let result = fastcert::cert::validate_hostname("example.com");
assert!(result.is_ok(), "Should accept FQDN");
}
#[test]
fn test_validate_hostname_subdomain() {
let _lock = get_test_lock();
let result = fastcert::cert::validate_hostname("sub.example.com");
assert!(result.is_ok(), "Should accept subdomain");
}
#[test]
fn test_validate_hostname_with_hyphen() {
let _lock = get_test_lock();
let result = fastcert::cert::validate_hostname("my-domain.com");
assert!(result.is_ok(), "Should accept hostname with hyphen");
}
#[test]
fn test_validate_hostname_with_numbers() {
let _lock = get_test_lock();
let result = fastcert::cert::validate_hostname("example123.com");
assert!(result.is_ok(), "Should accept hostname with numbers");
}
#[test]
fn test_validate_wildcard_basic() {
let _lock = get_test_lock();
let result = fastcert::cert::validate_wildcard_depth("*.example.com");
assert!(result.is_ok(), "Should accept single wildcard");
}
#[test]
fn test_validate_wildcard_subdomain() {
let _lock = get_test_lock();
let result = fastcert::cert::validate_wildcard_depth("*.sub.example.com");
assert!(result.is_ok(), "Should accept wildcard with subdomain");
}
#[test]
fn test_build_san_list_single_domain() {
let _lock = get_test_lock();
let hosts = vec!["example.com".to_string()];
let result = fastcert::cert::build_san_list(&hosts);
assert!(result.is_ok(), "Should build SAN list for single domain");
assert_eq!(result.unwrap().len(), 1, "Should have 1 SAN");
}
#[test]
fn test_build_san_list_multiple() {
let _lock = get_test_lock();
let hosts = vec![
"example.com".to_string(),
"192.168.1.1".to_string(),
"user@example.com".to_string(),
];
let result = fastcert::cert::build_san_list(&hosts);
assert!(result.is_ok(), "Should build SAN list for mixed types");
assert_eq!(result.unwrap().len(), 3, "Should have 3 SANs");
}
#[test]
fn test_build_san_list_ipv6() {
let _lock = get_test_lock();
let hosts = vec!["::1".to_string(), "2001:db8::1".to_string()];
let result = fastcert::cert::build_san_list(&hosts);
assert!(result.is_ok(), "Should build SAN list for IPv6");
assert_eq!(result.unwrap().len(), 2, "Should have 2 IPv6 SANs");
}
#[test]
fn test_create_cert_params() {
let _lock = get_test_lock();
let hosts = vec!["example.com".to_string()];
let result = fastcert::cert::create_cert_params(&hosts);
assert!(result.is_ok(), "Should create cert params");
}
#[test]
fn test_create_cert_params_multiple() {
let _lock = get_test_lock();
let hosts = vec![
"example.com".to_string(),
"localhost".to_string(),
"127.0.0.1".to_string(),
];
let result = fastcert::cert::create_cert_params(&hosts);
assert!(
result.is_ok(),
"Should create cert params for multiple hosts"
);
}
#[test]
fn test_format_expiration_date() {
let _lock = get_test_lock();
use time::OffsetDateTime;
let expiration = OffsetDateTime::now_utc() + time::Duration::days(825);
let formatted = fastcert::cert::format_expiration_date(expiration);
assert!(!formatted.is_empty(), "Should format expiration date");
}
#[test]
fn test_cert_to_pem() {
let _lock = get_test_lock();
let cert_der = vec![0x30, 0x82, 0x01, 0x00]; let pem = fastcert::cert::cert_to_pem(&cert_der);
assert!(pem.contains("BEGIN CERTIFICATE"), "Should have PEM header");
assert!(pem.contains("END CERTIFICATE"), "Should have PEM footer");
}
#[test]
fn test_domain_to_unicode_ascii() {
let _lock = get_test_lock();
let result = fastcert::cert::domain_to_unicode("example.com");
assert_eq!(result, "example.com", "ASCII should pass through");
}
#[test]
fn test_cert_chain_validation() {
let _lock = get_test_lock();
let temp_dir = TempDir::new().unwrap();
unsafe {
env::set_var("CAROOT", temp_dir.path().to_str().unwrap());
}
let hosts = vec!["chain-test.local".to_string()];
let cert_file = temp_dir.path().join("chain.pem");
let key_file = temp_dir.path().join("chain-key.pem");
fastcert::cert::generate_certificate(
&hosts,
Some(cert_file.to_str().unwrap()),
Some(key_file.to_str().unwrap()),
None,
false,
false,
false,
)
.unwrap();
let cert_pem = std::fs::read_to_string(&cert_file).unwrap();
let ca_pem = std::fs::read_to_string(temp_dir.path().join("rootCA.pem")).unwrap();
let cert_parsed = pem::parse(&cert_pem).unwrap();
let ca_parsed = pem::parse(&ca_pem).unwrap();
let result = fastcert::cert::validate_cert_chain(cert_parsed.contents(), ca_parsed.contents());
assert!(result.is_ok(), "Certificate chain should be valid");
unsafe {
env::remove_var("CAROOT");
}
}
#[test]
fn test_generate_file_names_single() {
let _lock = get_test_lock();
use fastcert::cert::CertificateConfig;
let config = CertificateConfig {
hosts: vec!["example.com".to_string()],
cert_file: None,
key_file: None,
p12_file: None,
client_cert: false,
use_ecdsa: false,
pkcs12: false,
};
let (cert, _key, _) = fastcert::cert::generate_file_names(&config);
assert!(
cert.to_str().unwrap().contains("example.com"),
"Cert file should contain domain"
);
}
#[test]
fn test_generate_file_names_multiple() {
let _lock = get_test_lock();
use fastcert::cert::CertificateConfig;
let config = CertificateConfig {
hosts: vec![
"example.com".to_string(),
"localhost".to_string(),
"127.0.0.1".to_string(),
],
cert_file: None,
key_file: None,
p12_file: None,
client_cert: false,
use_ecdsa: false,
pkcs12: false,
};
let (cert, _key, _) = fastcert::cert::generate_file_names(&config);
assert!(
cert.to_str().unwrap().contains("+"),
"Cert file should indicate multiple hosts"
);
}
#[test]
fn test_generate_file_names_wildcard() {
let _lock = get_test_lock();
use fastcert::cert::CertificateConfig;
let config = CertificateConfig {
hosts: vec!["*.example.com".to_string()],
cert_file: None,
key_file: None,
p12_file: None,
client_cert: false,
use_ecdsa: false,
pkcs12: false,
};
let (cert, _, _) = fastcert::cert::generate_file_names(&config);
assert!(
cert.to_str().unwrap().contains("_wildcard"),
"Cert file should indicate wildcard"
);
}
#[test]
fn test_certificate_with_client_auth() {
let _lock = get_test_lock();
let temp_dir = TempDir::new().unwrap();
unsafe {
env::set_var("CAROOT", temp_dir.path().to_str().unwrap());
}
let hosts = vec!["client@example.com".to_string()];
let cert_file = temp_dir.path().join("client-auth.pem");
let key_file = temp_dir.path().join("client-auth-key.pem");
let result = fastcert::cert::generate_certificate(
&hosts,
Some(cert_file.to_str().unwrap()),
Some(key_file.to_str().unwrap()),
None,
true, false,
false,
);
assert!(result.is_ok(), "Should generate client cert");
unsafe {
env::remove_var("CAROOT");
}
}
#[test]
fn test_certificate_with_ecdsa() {
let _lock = get_test_lock();
let temp_dir = TempDir::new().unwrap();
unsafe {
env::set_var("CAROOT", temp_dir.path().to_str().unwrap());
}
let hosts = vec!["ecdsa.local".to_string()];
let cert_file = temp_dir.path().join("ecdsa-cert.pem");
let key_file = temp_dir.path().join("ecdsa-key.pem");
let result = fastcert::cert::generate_certificate(
&hosts,
Some(cert_file.to_str().unwrap()),
Some(key_file.to_str().unwrap()),
None,
false,
true, false,
);
assert!(result.is_ok(), "Should generate ECDSA cert");
unsafe {
env::remove_var("CAROOT");
}
}