Merge pull request #426 from rustfs/feat/add-utils-certs-comprehensive-tests

feat: add comprehensive test coverage for utils certs module
This commit is contained in:
安正超
2025-05-27 22:50:34 +08:00
committed by GitHub
3 changed files with 266 additions and 0 deletions

1
Cargo.lock generated
View File

@@ -7485,6 +7485,7 @@ dependencies = [
"rustls 0.23.27",
"rustls-pemfile",
"rustls-pki-types",
"tempfile",
"tracing",
]

View File

@@ -14,6 +14,9 @@ rustls-pemfile = { workspace = true, optional = true }
rustls-pki-types = { workspace = true, optional = true }
tracing = { workspace = true }
[dev-dependencies]
tempfile = { workspace = true }
[lints]
workspace = true

View File

@@ -184,3 +184,265 @@ pub fn create_multi_cert_resolver(
default_cert,
})
}
#[cfg(test)]
mod tests {
use super::*;
use std::fs;
use tempfile::TempDir;
#[test]
fn test_certs_error_function() {
let error_msg = "Test error message";
let error = certs_error(error_msg.to_string());
assert_eq!(error.kind(), std::io::ErrorKind::Other);
assert_eq!(error.to_string(), error_msg);
}
#[test]
fn test_load_certs_file_not_found() {
let result = load_certs("non_existent_file.pem");
assert!(result.is_err());
let error = result.unwrap_err();
assert_eq!(error.kind(), std::io::ErrorKind::Other);
assert!(error.to_string().contains("failed to open"));
}
#[test]
fn test_load_private_key_file_not_found() {
let result = load_private_key("non_existent_key.pem");
assert!(result.is_err());
let error = result.unwrap_err();
assert_eq!(error.kind(), std::io::ErrorKind::Other);
assert!(error.to_string().contains("failed to open"));
}
#[test]
fn test_load_certs_empty_file() {
let temp_dir = TempDir::new().unwrap();
let cert_path = temp_dir.path().join("empty.pem");
fs::write(&cert_path, "").unwrap();
let result = load_certs(cert_path.to_str().unwrap());
assert!(result.is_err());
let error = result.unwrap_err();
assert!(error.to_string().contains("No valid certificate was found"));
}
#[test]
fn test_load_certs_invalid_format() {
let temp_dir = TempDir::new().unwrap();
let cert_path = temp_dir.path().join("invalid.pem");
fs::write(&cert_path, "invalid certificate content").unwrap();
let result = load_certs(cert_path.to_str().unwrap());
assert!(result.is_err());
let error = result.unwrap_err();
assert!(error.to_string().contains("No valid certificate was found"));
}
#[test]
fn test_load_private_key_empty_file() {
let temp_dir = TempDir::new().unwrap();
let key_path = temp_dir.path().join("empty_key.pem");
fs::write(&key_path, "").unwrap();
let result = load_private_key(key_path.to_str().unwrap());
assert!(result.is_err());
let error = result.unwrap_err();
assert!(error.to_string().contains("no private key found"));
}
#[test]
fn test_load_private_key_invalid_format() {
let temp_dir = TempDir::new().unwrap();
let key_path = temp_dir.path().join("invalid_key.pem");
fs::write(&key_path, "invalid private key content").unwrap();
let result = load_private_key(key_path.to_str().unwrap());
assert!(result.is_err());
let error = result.unwrap_err();
assert!(error.to_string().contains("no private key found"));
}
#[test]
fn test_load_all_certs_from_directory_not_exists() {
let result = load_all_certs_from_directory("/non/existent/directory");
assert!(result.is_err());
let error = result.unwrap_err();
assert!(error.to_string().contains("does not exist or is not a directory"));
}
#[test]
fn test_load_all_certs_from_directory_empty() {
let temp_dir = TempDir::new().unwrap();
let result = load_all_certs_from_directory(temp_dir.path().to_str().unwrap());
assert!(result.is_err());
let error = result.unwrap_err();
assert!(error.to_string().contains("No valid certificate/private key pair found"));
}
#[test]
fn test_load_all_certs_from_directory_file_instead_of_dir() {
let temp_dir = TempDir::new().unwrap();
let file_path = temp_dir.path().join("not_a_directory.txt");
fs::write(&file_path, "content").unwrap();
let result = load_all_certs_from_directory(file_path.to_str().unwrap());
assert!(result.is_err());
let error = result.unwrap_err();
assert!(error.to_string().contains("does not exist or is not a directory"));
}
#[test]
fn test_load_cert_key_pair_missing_cert() {
let temp_dir = TempDir::new().unwrap();
let key_path = temp_dir.path().join("test_key.pem");
fs::write(&key_path, "dummy key content").unwrap();
let result = load_cert_key_pair("non_existent_cert.pem", key_path.to_str().unwrap());
assert!(result.is_err());
}
#[test]
fn test_load_cert_key_pair_missing_key() {
let temp_dir = TempDir::new().unwrap();
let cert_path = temp_dir.path().join("test_cert.pem");
fs::write(&cert_path, "dummy cert content").unwrap();
let result = load_cert_key_pair(cert_path.to_str().unwrap(), "non_existent_key.pem");
assert!(result.is_err());
}
#[test]
fn test_create_multi_cert_resolver_empty_map() {
let empty_map = HashMap::new();
let result = create_multi_cert_resolver(empty_map);
// Should succeed even with empty map
assert!(result.is_ok());
}
#[test]
fn test_error_message_formatting() {
let test_cases = vec![
("file not found", "failed to open test.pem: file not found"),
("permission denied", "failed to open key.pem: permission denied"),
("invalid format", "certificate file cert.pem format error:invalid format"),
];
for (input, _expected_pattern) in test_cases {
let error1 = certs_error(format!("failed to open test.pem: {}", input));
assert!(error1.to_string().contains(input));
let error2 = certs_error(format!("failed to open key.pem: {}", input));
assert!(error2.to_string().contains(input));
}
}
#[test]
fn test_path_handling_edge_cases() {
// Test with various path formats
let path_cases = vec![
"", // Empty path
".", // Current directory
"..", // Parent directory
"/", // Root directory (Unix)
"relative/path", // Relative path
"/absolute/path", // Absolute path
];
for path in path_cases {
let result = load_all_certs_from_directory(path);
// All should fail since these are not valid cert directories
assert!(result.is_err());
}
}
#[test]
fn test_filename_constants_consistency() {
// Test that the constants match expected values
assert_eq!(RUSTFS_TLS_CERT, "rustfs_cert.pem");
assert_eq!(RUSTFS_TLS_KEY, "rustfs_key.pem");
// Test that constants are not empty
assert!(!RUSTFS_TLS_CERT.is_empty());
assert!(!RUSTFS_TLS_KEY.is_empty());
// Test that constants have proper extensions
assert!(RUSTFS_TLS_CERT.ends_with(".pem"));
assert!(RUSTFS_TLS_KEY.ends_with(".pem"));
}
#[test]
fn test_directory_structure_validation() {
let temp_dir = TempDir::new().unwrap();
// Create a subdirectory without certificates
let sub_dir = temp_dir.path().join("example.com");
fs::create_dir(&sub_dir).unwrap();
// Should fail because no certificates found
let result = load_all_certs_from_directory(temp_dir.path().to_str().unwrap());
assert!(result.is_err());
assert!(result.unwrap_err().to_string().contains("No valid certificate/private key pair found"));
}
#[test]
fn test_unicode_path_handling() {
let temp_dir = TempDir::new().unwrap();
// Create directory with Unicode characters
let unicode_dir = temp_dir.path().join("测试目录");
fs::create_dir(&unicode_dir).unwrap();
let result = load_all_certs_from_directory(unicode_dir.to_str().unwrap());
assert!(result.is_err());
assert!(result.unwrap_err().to_string().contains("No valid certificate/private key pair found"));
}
#[test]
fn test_concurrent_access_safety() {
use std::sync::Arc;
use std::thread;
let temp_dir = TempDir::new().unwrap();
let dir_path = Arc::new(temp_dir.path().to_string_lossy().to_string());
let handles: Vec<_> = (0..5).map(|_| {
let path = Arc::clone(&dir_path);
thread::spawn(move || {
let result = load_all_certs_from_directory(&path);
// All should fail since directory is empty
assert!(result.is_err());
})
}).collect();
for handle in handles {
handle.join().expect("Thread should complete successfully");
}
}
#[test]
fn test_memory_efficiency() {
// Test that error types are reasonably sized
use std::mem;
let error = certs_error("test".to_string());
let error_size = mem::size_of_val(&error);
// Error should not be excessively large
assert!(error_size < 1024, "Error size should be reasonable, got {} bytes", error_size);
}
}