#![cfg(test)]
use clock_hash::{DomainTag, clockhash256, clockhash256_domain, clockhash256_with_domain, tags};
#[test]
fn test_empty_string() {
let hash = clockhash256(b"");
assert_eq!(hash.len(), 32);
let hash2 = clockhash256(b"");
assert_eq!(hash, hash2);
}
#[test]
fn test_abc() {
let hash = clockhash256(b"abc");
assert_eq!(hash.len(), 32);
let hash2 = clockhash256(b"abc");
assert_eq!(hash, hash2);
let empty_hash = clockhash256(b"");
assert_ne!(hash, empty_hash);
}
#[test]
fn test_large_zeroes() {
let data = [0u8; 10000];
let hash = clockhash256(&data);
assert_eq!(hash.len(), 32);
let hash2 = clockhash256(&data);
assert_eq!(hash, hash2);
}
#[test]
fn test_domain_separation() {
let data = b"test data";
let hash_block = clockhash256_domain(tags::CLK_BLOCK, data);
let hash_tx = clockhash256_domain(tags::CLK_TX, data);
let hash_merkle = clockhash256_domain(tags::CLK_MERKLE, data);
let hash_nonce = clockhash256_domain(tags::CLK_NONCE, data);
let hash_rng = clockhash256_domain(tags::CLK_RNG, data);
let hash_raw = clockhash256(data);
assert_ne!(hash_block, hash_tx);
assert_ne!(hash_block, hash_merkle);
assert_ne!(hash_block, hash_nonce);
assert_ne!(hash_block, hash_rng);
assert_ne!(hash_block, hash_raw);
assert_ne!(hash_tx, hash_merkle);
assert_ne!(hash_tx, hash_nonce);
assert_ne!(hash_tx, hash_rng);
assert_ne!(hash_tx, hash_raw);
}
#[test]
fn test_domain_tag_enum() {
let data = b"test";
let hash_block = clockhash256_with_domain(DomainTag::Block, data);
let hash_tx = clockhash256_with_domain(DomainTag::Transaction, data);
let hash_merkle = clockhash256_with_domain(DomainTag::Merkle, data);
let hash_nonce = clockhash256_with_domain(DomainTag::Nonce, data);
let hash_rng = clockhash256_with_domain(DomainTag::Rng, data);
assert_ne!(hash_block, hash_tx);
assert_ne!(hash_block, hash_merkle);
assert_ne!(hash_block, hash_nonce);
assert_ne!(hash_block, hash_rng);
assert_ne!(hash_tx, hash_merkle);
assert_ne!(hash_tx, hash_nonce);
assert_ne!(hash_tx, hash_rng);
}
#[test]
fn test_avalanche_property() {
let data1 = [0u8; 100];
let mut data2 = data1;
data2[50] ^= 1;
let hash1 = clockhash256(&data1);
let hash2 = clockhash256(&data2);
assert_ne!(hash1, hash2);
let mut diff_bits = 0;
for i in 0..32 {
diff_bits += (hash1[i] ^ hash2[i]).count_ones();
}
assert!(
diff_bits >= 100 && diff_bits <= 156,
"Avalanche property: expected ~128 bits different, got {}",
diff_bits
);
}
#[test]
fn test_incremental_vs_oneshot() {
use clock_hash::ClockHasher;
let data = b"hello, world! This is a test message.";
let hash1 = clockhash256(data);
let mut hasher = ClockHasher::new();
hasher.update(data);
let hash2 = hasher.finalize();
assert_eq!(hash1, hash2);
}
#[test]
fn test_incremental_multiple_updates() {
use clock_hash::ClockHasher;
let data1 = b"hello";
let data2 = b", ";
let data3 = b"world";
let mut hasher1 = ClockHasher::new();
hasher1.update(data1);
hasher1.update(data2);
hasher1.update(data3);
let hash1 = hasher1.finalize();
let mut combined = [0u8; 12];
combined[0..5].copy_from_slice(data1);
combined[5..7].copy_from_slice(data2);
combined[7..12].copy_from_slice(data3);
let hash2 = clockhash256(&combined);
assert_eq!(hash1, hash2);
}
#[test]
fn test_deterministic() {
let data = b"deterministic test data";
let hash1 = clockhash256(data);
let hash2 = clockhash256(data);
let hash3 = clockhash256(data);
assert_eq!(hash1, hash2);
assert_eq!(hash2, hash3);
}
#[test]
fn test_various_sizes() {
for &size in &[0, 1, 15, 16, 17, 127, 128, 129, 255, 256, 1000] {
let mut data = [0xAAu8; 1000];
let hash = clockhash256(&data[..size]);
assert_eq!(hash.len(), 32, "Hash should be 32 bytes for size {}", size);
}
}