use tempfile::NamedTempFile;
use crate::Error;
use crate::config::tls::TlsConfig;
#[test]
fn test_tls_config_default_values() {
let config = TlsConfig::default();
assert!(!config.enable_tls);
assert!(!config.generate_self_signed_certificates);
assert!(!config.enable_mtls);
let result = config.validate();
assert!(
result.is_ok(),
"Default config should validate when TLS is disabled"
);
assert_eq!(
config.certificate_authority_root_path,
"/etc/ssl/certs/ca.pem"
);
assert_eq!(config.server_certificate_path, "./certs/server.pem");
assert_eq!(config.server_private_key_path, "./certs/server.key");
assert_eq!(
config.client_certificate_authority_root_path,
"/etc/ssl/certs/ca.pem"
);
}
#[test]
fn test_validate_tls_disabled_should_succeed() {
let config = TlsConfig {
enable_tls: false,
..Default::default()
};
let result = config.validate();
assert!(
result.is_ok(),
"Validation should succeed when TLS is disabled"
);
}
#[test]
fn test_validate_mtls_without_tls_should_fail() {
let invalid_config = TlsConfig {
enable_tls: false, enable_mtls: true, ..Default::default()
};
assert!(
invalid_config.enable_mtls && !invalid_config.enable_tls,
"Config should have mTLS enabled but TLS disabled"
);
let result = invalid_config.validate();
assert!(
result.is_err(),
"Validation should fail when mTLS is enabled without TLS"
);
let error = result.unwrap_err();
assert!(matches!(error, Error::Config(_)));
assert!(error.to_string().contains("mTLS requires enable_tls to be true"));
}
#[test]
fn test_validate_self_signed_with_cert_paths_should_fail() {
let config = TlsConfig {
enable_tls: true,
generate_self_signed_certificates: true,
server_certificate_path: "./certs/existing.pem".to_string(),
server_private_key_path: "./certs/existing.key".to_string(),
..Default::default()
};
let result = config.validate();
assert!(
result.is_err(),
"Validation should fail when self-signed is enabled with certificate paths"
);
let error = result.unwrap_err();
assert!(matches!(error, Error::Config(_)));
assert!(
error.to_string().contains(
"Cannot specify certificate paths with generate_self_signed_certificates=true"
)
);
}
#[test]
fn test_validate_self_signed_without_paths_should_succeed() {
let config = TlsConfig {
enable_tls: true,
generate_self_signed_certificates: true,
server_certificate_path: String::new(),
server_private_key_path: String::new(),
..Default::default()
};
let result = config.validate();
assert!(
result.is_ok(),
"Validation should succeed when self-signed is enabled without certificate paths"
);
}
#[test]
fn test_validate_missing_server_certificate_should_fail() {
let config = TlsConfig {
enable_tls: true,
generate_self_signed_certificates: false,
server_certificate_path: "/nonexistent/server.pem".to_string(),
..Default::default()
};
let result = config.validate();
assert!(
result.is_err(),
"Validation should fail when server certificate is missing"
);
let error = result.unwrap_err();
assert!(matches!(error, Error::Config(_)));
assert!(error.to_string().contains("server certificate file"));
assert!(error.to_string().contains("not found"));
}
#[test]
fn test_validate_missing_server_private_key_should_fail() {
let cert_file = NamedTempFile::new().unwrap();
let config = TlsConfig {
enable_tls: true,
generate_self_signed_certificates: false,
server_private_key_path: "/nonexistent/server.key".to_string(),
server_certificate_path: cert_file.path().to_string_lossy().to_string(),
..Default::default()
};
let result = config.validate();
assert!(
result.is_err(),
"Validation should fail when server private key is missing"
);
let error = result.unwrap_err();
assert!(matches!(error, Error::Config(_)));
let error_str = error.to_string();
assert!(error_str.contains("not found"));
assert!(
error_str.contains("server.key")
|| error_str.contains("/nonexistent")
|| error_str.contains("server private key")
);
}
#[test]
fn test_validate_missing_ca_certificate_should_fail() {
let cert_file = NamedTempFile::new().unwrap();
let key_file = NamedTempFile::new().unwrap();
let config = TlsConfig {
enable_tls: true,
generate_self_signed_certificates: false,
certificate_authority_root_path: "/nonexistent/ca.pem".to_string(),
server_certificate_path: cert_file.path().to_string_lossy().to_string(),
server_private_key_path: key_file.path().to_string_lossy().to_string(),
..Default::default()
};
let result = config.validate();
assert!(
result.is_err(),
"Validation should fail when CA certificate is missing"
);
let error = result.unwrap_err();
assert!(matches!(error, Error::Config(_)));
let error_str = error.to_string();
assert!(error_str.contains("not found"));
assert!(
error_str.contains("ca.pem")
|| error_str.contains("/nonexistent")
|| error_str.contains("CA certificate")
);
}
#[test]
fn test_validate_mtls_missing_client_ca_should_fail() {
let cert_file = NamedTempFile::new().unwrap();
let key_file = NamedTempFile::new().unwrap();
let ca_file = NamedTempFile::new().unwrap();
let config = TlsConfig {
enable_tls: true,
enable_mtls: true,
generate_self_signed_certificates: false,
client_certificate_authority_root_path: "/nonexistent/client-ca.pem".to_string(),
server_certificate_path: cert_file.path().to_string_lossy().to_string(),
server_private_key_path: key_file.path().to_string_lossy().to_string(),
certificate_authority_root_path: ca_file.path().to_string_lossy().to_string(),
};
let result = config.validate();
assert!(
result.is_err(),
"Validation should fail when client CA certificate is missing for mTLS"
);
let error = result.unwrap_err();
assert!(matches!(error, Error::Config(_)));
let error_str = error.to_string();
assert!(error_str.contains("not found"));
assert!(
error_str.contains("client-ca.pem")
|| error_str.contains("/nonexistent")
|| error_str.contains("client CA certificate")
);
}
#[test]
fn test_validate_mtls_with_valid_client_ca_should_succeed() {
let cert_file = NamedTempFile::new().unwrap();
let key_file = NamedTempFile::new().unwrap();
let ca_file = NamedTempFile::new().unwrap();
let client_ca_file = NamedTempFile::new().unwrap();
let config = TlsConfig {
enable_tls: true,
enable_mtls: true,
generate_self_signed_certificates: false,
server_certificate_path: cert_file.path().to_string_lossy().to_string(),
server_private_key_path: key_file.path().to_string_lossy().to_string(),
certificate_authority_root_path: ca_file.path().to_string_lossy().to_string(),
client_certificate_authority_root_path: client_ca_file.path().to_string_lossy().to_string(),
};
let result = config.validate();
assert!(
result.is_ok(),
"Validation should succeed with valid certificate files for mTLS"
);
}
#[test]
fn test_validate_tls_with_valid_files_should_succeed() {
let cert_file = NamedTempFile::new().unwrap();
let key_file = NamedTempFile::new().unwrap();
let ca_file = NamedTempFile::new().unwrap();
let config = TlsConfig {
enable_tls: true,
generate_self_signed_certificates: false,
server_certificate_path: cert_file.path().to_string_lossy().to_string(),
server_private_key_path: key_file.path().to_string_lossy().to_string(),
certificate_authority_root_path: ca_file.path().to_string_lossy().to_string(),
..Default::default()
};
let result = config.validate();
assert!(
result.is_ok(),
"Validation should succeed with valid certificate files"
);
}
#[test]
#[cfg(unix)]
fn test_validate_key_file_secure_permissions_should_succeed() {
let key_file = NamedTempFile::new().unwrap();
let config = TlsConfig {
enable_tls: true,
generate_self_signed_certificates: false,
server_private_key_path: key_file.path().to_string_lossy().to_string(),
server_certificate_path: key_file.path().to_string_lossy().to_string(),
certificate_authority_root_path: key_file.path().to_string_lossy().to_string(),
..Default::default()
};
let result = config.validate();
assert!(
result.is_ok(),
"Validation should succeed with existing files (permissions are not checked in test mode)"
);
}
#[test]
fn test_validate_cert_file_unreadable_should_fail() {
let config = TlsConfig {
enable_tls: true,
generate_self_signed_certificates: false,
server_certificate_path: "/nonexistent/unreadable.pem".to_string(),
..Default::default()
};
let result = config.validate();
assert!(
result.is_err(),
"Validation should fail for non-existent certificate file"
);
let error = result.unwrap_err();
assert!(matches!(error, Error::Config(_)));
assert!(error.to_string().contains("not found"));
}
#[test]
fn test_validate_complete_mtls_config_should_succeed() {
let server_cert = NamedTempFile::new().unwrap();
let server_key = NamedTempFile::new().unwrap();
let ca_cert = NamedTempFile::new().unwrap();
let client_ca_cert = NamedTempFile::new().unwrap();
let config = TlsConfig {
enable_tls: true,
enable_mtls: true,
generate_self_signed_certificates: false,
server_certificate_path: server_cert.path().to_string_lossy().to_string(),
server_private_key_path: server_key.path().to_string_lossy().to_string(),
certificate_authority_root_path: ca_cert.path().to_string_lossy().to_string(),
client_certificate_authority_root_path: client_ca_cert.path().to_string_lossy().to_string(),
};
let result = config.validate();
assert!(
result.is_ok(),
"Complete mTLS configuration should validate successfully"
);
}
#[test]
fn test_validate_partial_tls_config_should_fail() {
let server_cert = NamedTempFile::new().unwrap();
let config = TlsConfig {
enable_tls: true,
generate_self_signed_certificates: false,
server_certificate_path: server_cert.path().to_string_lossy().to_string(),
..Default::default()
};
let result = config.validate();
assert!(
result.is_err(),
"Partial TLS configuration should fail validation"
);
let error = result.unwrap_err();
assert!(matches!(error, Error::Config(_)));
}
#[test]
fn test_validate_empty_paths_with_self_signed_should_succeed() {
let config = TlsConfig {
enable_tls: true,
generate_self_signed_certificates: true,
server_certificate_path: String::new(),
server_private_key_path: String::new(),
certificate_authority_root_path: String::new(),
client_certificate_authority_root_path: String::new(),
..Default::default()
};
let result = config.validate();
assert!(
result.is_ok(),
"Empty paths with self-signed generation should succeed"
);
}