use std::io::Write;
use std::path::Path;
use modde_core::hash::{hash_file_sha256, hash_file_xxhash, verify_sha256, verify_xxhash};
use tempfile::NamedTempFile;
fn create_temp_file(content: &[u8]) -> NamedTempFile {
let mut f = NamedTempFile::new().unwrap();
f.write_all(content).unwrap();
f
}
#[tokio::test]
async fn test_xxhash_binary_content() {
let data: Vec<u8> = (0..=255u8).collect();
let f = create_temp_file(&data);
let hash = hash_file_xxhash(f.path()).await.unwrap();
let hash2 = hash_file_xxhash(f.path()).await.unwrap();
assert_eq!(hash, hash2);
assert_ne!(hash, 0);
}
#[tokio::test]
async fn test_xxhash_single_byte() {
let f = create_temp_file(&[0x42]);
let hash = hash_file_xxhash(f.path()).await.unwrap();
assert_ne!(hash, 0);
}
#[tokio::test]
async fn test_xxhash_single_null_byte() {
let f = create_temp_file(&[0x00]);
let hash = hash_file_xxhash(f.path()).await.unwrap();
let empty = create_temp_file(b"");
let empty_hash = hash_file_xxhash(empty.path()).await.unwrap();
assert_ne!(hash, empty_hash);
}
#[tokio::test]
async fn test_xxhash_verify_immediately_after_hash() {
let f = create_temp_file(b"verify me");
let hash = hash_file_xxhash(f.path()).await.unwrap();
verify_xxhash(f.path(), hash).await.unwrap();
}
#[tokio::test]
async fn test_xxhash_verify_wrong_hash_error_message() {
let f = create_temp_file(b"test content");
let result = verify_xxhash(f.path(), 12345).await;
assert!(result.is_err());
let err = format!("{}", result.unwrap_err());
assert!(
err.contains("hash mismatch"),
"expected hash mismatch error, got: {err}"
);
}
#[tokio::test]
async fn test_sha256_binary_content() {
let data: Vec<u8> = (0..=255u8).collect();
let f = create_temp_file(&data);
let hash = hash_file_sha256(f.path()).await.unwrap();
assert_eq!(hash.len(), 64); }
#[tokio::test]
async fn test_sha256_large_file_streaming() {
let data = vec![0xCDu8; 5 * 1024 * 1024];
let f = create_temp_file(&data);
let hash = hash_file_sha256(f.path()).await.unwrap();
assert_eq!(hash.len(), 64);
let hash2 = hash_file_sha256(f.path()).await.unwrap();
assert_eq!(hash, hash2);
}
#[tokio::test]
async fn test_sha256_verify_immediately_after_hash() {
let f = create_temp_file(b"sha256 test data");
let hash = hash_file_sha256(f.path()).await.unwrap();
verify_sha256(f.path(), &hash).await.unwrap();
}
#[tokio::test]
async fn test_sha256_verify_wrong_hash_error_message() {
let f = create_temp_file(b"test");
let result = verify_sha256(
f.path(),
"0000000000000000000000000000000000000000000000000000000000000000",
)
.await;
assert!(result.is_err());
let err = format!("{}", result.unwrap_err());
assert!(
err.contains("hash mismatch"),
"expected hash mismatch, got: {err}"
);
}
#[tokio::test]
async fn test_sha256_case_sensitive_hex() {
let f = create_temp_file(b"case test");
let hash = hash_file_sha256(f.path()).await.unwrap();
assert_eq!(hash, hash.to_lowercase());
}
#[tokio::test]
async fn test_different_algorithms_different_hashes_same_content() {
let f = create_temp_file(b"hello algorithms");
let xxhash = hash_file_xxhash(f.path()).await.unwrap();
let sha256 = hash_file_sha256(f.path()).await.unwrap();
assert_ne!(xxhash, 0);
assert_eq!(sha256.len(), 64);
}
#[tokio::test]
async fn test_both_algorithms_fail_on_nonexistent() {
let bad_path = Path::new("/tmp/nonexistent_modde_hash_test_file");
assert!(hash_file_xxhash(bad_path).await.is_err());
assert!(hash_file_sha256(bad_path).await.is_err());
}
#[tokio::test]
async fn test_both_algorithms_handle_just_newline() {
let f = create_temp_file(b"\n");
let xxhash = hash_file_xxhash(f.path()).await.unwrap();
let sha256 = hash_file_sha256(f.path()).await.unwrap();
assert_ne!(xxhash, 0);
assert_eq!(sha256.len(), 64);
}
#[tokio::test]
async fn test_xxhash_mismatch_includes_path() {
let f = create_temp_file(b"mismatch test");
let result = verify_xxhash(f.path(), 0).await;
let err = format!("{}", result.unwrap_err());
assert!(
err.contains(f.path().to_str().unwrap()),
"error should contain path: {err}"
);
}
#[tokio::test]
async fn test_sha256_mismatch_includes_path() {
let f = create_temp_file(b"mismatch sha256");
let result = verify_sha256(f.path(), "bad_hash").await;
let err = format!("{}", result.unwrap_err());
assert!(
err.contains(f.path().to_str().unwrap()),
"error should contain path: {err}"
);
}