use blazehash::algorithm::Algorithm;
use std::str::FromStr;
#[test]
fn parse_blake3() {
let algo = Algorithm::from_str("blake3").unwrap();
assert_eq!(algo, Algorithm::Blake3);
}
#[test]
fn parse_sha256() {
let algo = Algorithm::from_str("sha256").unwrap();
assert_eq!(algo, Algorithm::Sha256);
let algo2 = Algorithm::from_str("sha-256").unwrap();
assert_eq!(algo2, Algorithm::Sha256);
}
#[test]
fn parse_sha1() {
let algo = Algorithm::from_str("sha1").unwrap();
assert_eq!(algo, Algorithm::Sha1);
let algo2 = Algorithm::from_str("sha-1").unwrap();
assert_eq!(algo2, Algorithm::Sha1);
}
#[test]
fn parse_md5() {
let algo = Algorithm::from_str("md5").unwrap();
assert_eq!(algo, Algorithm::Md5);
}
#[test]
fn parse_sha512() {
let algo = Algorithm::from_str("sha512").unwrap();
assert_eq!(algo, Algorithm::Sha512);
}
#[test]
fn parse_sha3_256() {
let algo = Algorithm::from_str("sha3-256").unwrap();
assert_eq!(algo, Algorithm::Sha3_256);
}
#[test]
fn parse_tiger() {
let algo = Algorithm::from_str("tiger").unwrap();
assert_eq!(algo, Algorithm::Tiger);
}
#[test]
fn parse_whirlpool() {
let algo = Algorithm::from_str("whirlpool").unwrap();
assert_eq!(algo, Algorithm::Whirlpool);
}
#[test]
fn parse_invalid_algorithm() {
assert!(Algorithm::from_str("xxhash").is_err());
}
#[test]
fn algorithm_display_roundtrips() {
for algo in Algorithm::all() {
let s = algo.to_string();
let parsed = Algorithm::from_str(&s).unwrap();
assert_eq!(*algo, parsed);
}
}
#[test]
fn default_algorithm_is_blake3() {
assert_eq!(Algorithm::default(), Algorithm::Blake3);
}
use blazehash::algorithm::hash_bytes;
#[test]
fn hash_bytes_blake3_known_vector() {
let hash = hash_bytes(Algorithm::Blake3, b"hello world");
assert_eq!(
hash,
"d74981efa70a0c880b8d8c1985d075dbcbf679b99a5f9914e5aaf96b831a9e24"
);
}
#[test]
fn hash_bytes_sha256_known_vector() {
let hash = hash_bytes(Algorithm::Sha256, b"hello world");
assert_eq!(
hash,
"b94d27b9934d3e08a52e52d7da7dabfac484efe37a5380ee9088f7ace2efcde9"
);
}
#[test]
fn hash_bytes_md5_known_vector() {
let hash = hash_bytes(Algorithm::Md5, b"hello world");
assert_eq!(hash, "5eb63bbbe01eeed093cb22bb8f5acdc3");
}
#[test]
fn hash_bytes_sha1_known_vector() {
let hash = hash_bytes(Algorithm::Sha1, b"hello world");
assert_eq!(hash, "2aae6c35c94fcfb415dbe95f408b9ce91ee846ed");
}
#[test]
fn hash_bytes_sha512_known_vector() {
let hash = hash_bytes(Algorithm::Sha512, b"hello world");
assert_eq!(hash, "309ecc489c12d6eb4cc40f50c902f2b4d0ed77ee511a7c7a9bcd3ca86d4cd86f989dd35bc5ff499670da34255b45b0cfd830e81f605dcf7dc5542e93ae9cd76f");
}
#[test]
fn hash_bytes_empty_input() {
for algo in Algorithm::all() {
let hash = hash_bytes(*algo, b"");
assert!(!hash.is_empty(), "empty hash for {algo:?}");
}
}
#[test]
fn hash_bytes_sha3_256_known_vector() {
let hash = hash_bytes(Algorithm::Sha3_256, b"hello world");
assert_eq!(
hash,
"644bcc7e564373040999aac89e7622f3ca71fba1d972fd94a31c3bfbf24e3938"
);
}
#[test]
fn hash_bytes_tiger_known_vector() {
let hash = hash_bytes(Algorithm::Tiger, b"hello world");
assert!(!hash.is_empty());
assert_eq!(hash.len(), 48); }
#[test]
fn hash_bytes_whirlpool_known_vector() {
let hash = hash_bytes(Algorithm::Whirlpool, b"hello world");
assert!(!hash.is_empty());
assert_eq!(hash.len(), 128); }
#[test]
fn parse_algorithm_case_insensitive() {
assert_eq!(Algorithm::from_str("BLAKE3").unwrap(), Algorithm::Blake3);
assert_eq!(Algorithm::from_str("SHA256").unwrap(), Algorithm::Sha256);
assert_eq!(Algorithm::from_str("Sha-256").unwrap(), Algorithm::Sha256);
assert_eq!(Algorithm::from_str("MD5").unwrap(), Algorithm::Md5);
assert_eq!(
Algorithm::from_str("SHA3-256").unwrap(),
Algorithm::Sha3_256
);
assert_eq!(
Algorithm::from_str("SHA3_256").unwrap(),
Algorithm::Sha3_256
);
assert_eq!(Algorithm::from_str("TIGER").unwrap(), Algorithm::Tiger);
assert_eq!(
Algorithm::from_str("WHIRLPOOL").unwrap(),
Algorithm::Whirlpool
);
assert_eq!(Algorithm::from_str("SHA512").unwrap(), Algorithm::Sha512);
assert_eq!(Algorithm::from_str("SHA-1").unwrap(), Algorithm::Sha1);
}
#[test]
fn parse_algorithm_error_message_contains_name() {
let err = Algorithm::from_str("xxhash").unwrap_err();
assert!(err.to_string().contains("xxhash"));
}
#[test]
fn hashdeep_name_matches_display() {
for algo in Algorithm::all() {
assert_eq!(algo.hashdeep_name(), &algo.to_string());
}
}
#[test]
fn algorithm_all_returns_all_variants() {
let all = Algorithm::all();
assert_eq!(all.len(), 8);
let mut seen = std::collections::HashSet::new();
for algo in all {
assert!(seen.insert(algo));
}
}
#[test]
fn test_ssdeep_from_str() {
use std::str::FromStr;
assert_eq!(Algorithm::from_str("ssdeep").unwrap(), Algorithm::Ssdeep);
assert_eq!(Algorithm::from_str("SSDEEP").unwrap(), Algorithm::Ssdeep);
}
#[test]
fn test_tlsh_from_str() {
use std::str::FromStr;
assert_eq!(Algorithm::from_str("tlsh").unwrap(), Algorithm::Tlsh);
assert_eq!(Algorithm::from_str("TLSH").unwrap(), Algorithm::Tlsh);
}
#[test]
fn test_ssdeep_is_fuzzy() {
assert!(Algorithm::Ssdeep.is_fuzzy());
assert!(Algorithm::Tlsh.is_fuzzy());
assert!(!Algorithm::Blake3.is_fuzzy());
assert!(!Algorithm::Sha256.is_fuzzy());
}
#[test]
fn test_fuzzy_not_in_all() {
let all = Algorithm::all();
assert!(!all.contains(&Algorithm::Ssdeep));
assert!(!all.contains(&Algorithm::Tlsh));
}
#[test]
fn test_ssdeep_hashdeep_name() {
assert_eq!(Algorithm::Ssdeep.hashdeep_name(), "ssdeep");
assert_eq!(Algorithm::Tlsh.hashdeep_name(), "tlsh");
}
#[test]
fn test_crc32c_known_vector() {
let result = hash_bytes(Algorithm::Crc32c, b"hello world");
assert_eq!(result, "c99465aa"); }
#[test]
fn test_xxh3_known_vector() {
let result = hash_bytes(Algorithm::Xxh3, b"");
assert_eq!(result.len(), 32); }
#[test]
fn test_crc32c_is_non_cryptographic() {
assert!(Algorithm::Crc32c.is_non_cryptographic());
assert!(Algorithm::Xxh3.is_non_cryptographic());
assert!(!Algorithm::Blake3.is_non_cryptographic());
}
#[test]
fn test_crc32c_not_in_all() {
let all = Algorithm::all();
assert!(!all.contains(&Algorithm::Crc32c));
assert!(!all.contains(&Algorithm::Xxh3));
}
#[test]
fn test_crc32c_parse_from_str() {
assert_eq!("crc32c".parse::<Algorithm>().unwrap(), Algorithm::Crc32c);
assert_eq!("xxh3".parse::<Algorithm>().unwrap(), Algorithm::Xxh3);
}
#[test]
fn test_shake128_known_vector() {
let result = hash_bytes(Algorithm::Shake128, b"");
assert_eq!(result.len(), 64); assert_eq!(&result[..8], "7f9c2ba4"); }
#[test]
fn test_shake256_known_vector() {
let result = hash_bytes(Algorithm::Shake256, b"");
assert_eq!(result.len(), 128); assert_eq!(&result[..8], "46b9dd2b"); }
#[test]
fn test_shake128_not_fuzzy_not_non_crypto() {
assert!(!Algorithm::Shake128.is_fuzzy());
assert!(!Algorithm::Shake128.is_non_cryptographic());
assert!(!Algorithm::Shake256.is_fuzzy());
assert!(!Algorithm::Shake256.is_non_cryptographic());
}
#[test]
fn test_shake_parse_from_str() {
assert_eq!(
"shake128".parse::<Algorithm>().unwrap(),
Algorithm::Shake128
);
assert_eq!(
"shake256".parse::<Algorithm>().unwrap(),
Algorithm::Shake256
);
}
#[test]
fn blake2b_parses_from_str() {
assert!("blake2b".parse::<Algorithm>().is_ok());
}
#[test]
fn blake2b_hash_bytes_length() {
let h = hash_bytes(Algorithm::Blake2b, b"abc");
assert_eq!(h.len(), 128, "blake2b output should be 128 hex chars");
}
#[test]
fn blake2b_hash_bytes_nonempty_hex() {
let h = hash_bytes(Algorithm::Blake2b, b"");
assert!(!h.is_empty());
assert!(h.chars().all(|c| c.is_ascii_hexdigit()));
}
#[test]
fn blake2s_parses_from_str() {
assert!("blake2s".parse::<Algorithm>().is_ok());
}
#[test]
fn blake2s_hash_bytes_length() {
let h = hash_bytes(Algorithm::Blake2s, b"abc");
assert_eq!(h.len(), 64, "blake2s output should be 64 hex chars");
}
#[test]
fn sm3_parses_from_str() {
assert!("sm3".parse::<Algorithm>().is_ok());
}
#[test]
fn sm3_hash_bytes_length() {
let h = hash_bytes(Algorithm::Sm3, b"abc");
assert_eq!(h.len(), 64, "sm3 output should be 64 hex chars");
}
#[test]
fn streebog256_parses_from_str() {
assert!("streebog256".parse::<Algorithm>().is_ok());
}
#[test]
fn streebog256_hash_bytes_length() {
let h = hash_bytes(Algorithm::Streebog256, b"abc");
assert_eq!(h.len(), 64, "streebog256 output should be 64 hex chars");
}
#[test]
fn streebog512_parses_from_str() {
assert!("streebog512".parse::<Algorithm>().is_ok());
}
#[test]
fn streebog512_hash_bytes_length() {
let h = hash_bytes(Algorithm::Streebog512, b"abc");
assert_eq!(h.len(), 128, "streebog512 output should be 128 hex chars");
}
#[test]
fn ripemd160_parses_from_str() {
assert!("ripemd160".parse::<Algorithm>().is_ok());
}
#[test]
fn ripemd160_hash_bytes_length() {
let h = hash_bytes(Algorithm::Ripemd160, b"abc");
assert_eq!(h.len(), 40, "ripemd160 output should be 40 hex chars");
}
#[test]
fn sha512_256_parses_from_str() {
assert!("sha512-256".parse::<Algorithm>().is_ok());
}
#[test]
fn sha512_256_hash_bytes_length() {
let h = hash_bytes(Algorithm::Sha512_256, b"abc");
assert_eq!(h.len(), 64, "sha512-256 output should be 64 hex chars");
}
#[test]
fn sha512_224_parses_from_str() {
assert!("sha512-224".parse::<Algorithm>().is_ok());
}
#[test]
fn sha512_224_hash_bytes_length() {
let h = hash_bytes(Algorithm::Sha512_224, b"abc");
assert_eq!(h.len(), 56, "sha512-224 output should be 56 hex chars");
}
#[test]
fn k12_parses_from_str() {
assert!("k12".parse::<Algorithm>().is_ok());
}
#[test]
fn k12_parses_alias() {
assert!("kangaroo12".parse::<Algorithm>().is_ok());
}
#[test]
fn k12_hash_bytes_length() {
let h = hash_bytes(Algorithm::K12, b"abc");
assert_eq!(h.len(), 64, "k12 output should be 64 hex chars");
}
#[test]
fn adler32_parses_from_str() {
assert!("adler32".parse::<Algorithm>().is_ok());
}
#[test]
fn adler32_hash_bytes_length() {
let h = hash_bytes(Algorithm::Adler32, b"abc");
assert_eq!(h.len(), 8, "adler32 output should be 8 hex chars");
}
#[test]
fn adler32_is_non_cryptographic() {
assert!(Algorithm::Adler32.is_non_cryptographic());
}
#[test]
fn crc64_parses_from_str() {
assert!("crc64".parse::<Algorithm>().is_ok());
}
#[test]
fn crc64_hash_bytes_length() {
let h = hash_bytes(Algorithm::Crc64, b"abc");
assert_eq!(h.len(), 16, "crc64 output should be 16 hex chars");
}
#[test]
fn crc64_is_non_cryptographic() {
assert!(Algorithm::Crc64.is_non_cryptographic());
}
use blazehash::digest_wrappers::{
Adler32Digest, Crc32cDigest, Crc64Digest, K12Fixed,
Shake128Fixed, Shake256Fixed, Xxh3Digest,
};
use digest::Digest;
#[test]
fn shake128_wrapper_matches_hash_bytes() {
let data = b"shake128 wrapper test";
let wrapper = hex::encode(Shake128Fixed::digest(data));
let direct = hash_bytes(Algorithm::Shake128, data);
assert_eq!(wrapper, direct, "Shake128Fixed must match hash_bytes");
}
#[test]
fn shake256_wrapper_matches_hash_bytes() {
let data = b"shake256 wrapper test";
let wrapper = hex::encode(Shake256Fixed::digest(data));
let direct = hash_bytes(Algorithm::Shake256, data);
assert_eq!(wrapper, direct, "Shake256Fixed must match hash_bytes");
}
#[test]
fn k12_wrapper_matches_hash_bytes() {
let data = b"k12 wrapper test";
let wrapper = hex::encode(K12Fixed::digest(data));
let direct = hash_bytes(Algorithm::K12, data);
assert_eq!(wrapper, direct, "K12Fixed must match hash_bytes");
}
#[test]
fn crc32c_wrapper_matches_hash_bytes() {
let data = b"crc32c wrapper test";
let wrapper = hex::encode(Crc32cDigest::digest(data));
let direct = hash_bytes(Algorithm::Crc32c, data);
assert_eq!(wrapper, direct, "Crc32cDigest must match hash_bytes");
}
#[test]
fn crc64_wrapper_matches_hash_bytes() {
let data = b"crc64 wrapper test";
let wrapper = hex::encode(Crc64Digest::digest(data));
let direct = hash_bytes(Algorithm::Crc64, data);
assert_eq!(wrapper, direct, "Crc64Digest must match hash_bytes");
}
#[test]
fn adler32_wrapper_matches_hash_bytes() {
let data = b"adler32 wrapper test";
let wrapper = hex::encode(Adler32Digest::digest(data));
let direct = hash_bytes(Algorithm::Adler32, data);
assert_eq!(wrapper, direct, "Adler32Digest must match hash_bytes");
}
#[test]
fn xxh3_wrapper_matches_hash_bytes() {
let data = b"xxh3 wrapper test";
let wrapper = hex::encode(Xxh3Digest::digest(data));
let direct = hash_bytes(Algorithm::Xxh3, data);
assert_eq!(wrapper, direct, "Xxh3Digest must match hash_bytes");
}
#[test]
fn shake128_wrapper_incremental_matches_oneshot() {
let part1: &[u8] = b"hello ";
let part2: &[u8] = b"world";
let mut all = part1.to_vec();
all.extend_from_slice(part2);
let oneshot = hex::encode(Shake128Fixed::digest(all.as_slice()));
let mut h = Shake128Fixed::new();
Digest::update(&mut h, part1);
Digest::update(&mut h, part2);
let incremental = hex::encode(h.finalize());
assert_eq!(incremental, oneshot, "incremental must equal one-shot for Shake128");
}
#[test]
fn crc32c_wrapper_incremental_matches_oneshot() {
let part1: &[u8] = b"hello ";
let part2: &[u8] = b"world";
let mut all = part1.to_vec();
all.extend_from_slice(part2);
let oneshot = hex::encode(Crc32cDigest::digest(all.as_slice()));
let mut h = Crc32cDigest::new();
Digest::update(&mut h, part1);
Digest::update(&mut h, part2);
let incremental = hex::encode(h.finalize());
assert_eq!(incremental, oneshot, "incremental must equal one-shot for Crc32c");
}