use {
hash_iter::{BuildHashIterHasher, DoubleHashBuilder, DoubleHashHasher, HashIterHasher},
xxhash_rust::xxh3::Xxh3Builder,
};
#[test]
fn default_config() {
{
let hasher = DoubleHashHasher::<u64, _, _>::new();
let hashes = hasher.hash_iter(&"hello", 3).collect::<Vec<_>>();
assert_eq!(hashes, vec![
10179864958193109059,
16936771314159985077,
5246933596417309481
]);
}
{
let builder = DoubleHashBuilder::<u64>::new();
let hasher = builder.build_hash_iter_hasher();
let hashes = hasher.hash_iter(&"hello", 3).collect::<Vec<_>>();
assert_eq!(hashes, vec![
10179864958193109059,
16936771314159985077,
5246933596417309481
]);
}
}
#[test]
fn custom_config() {
let hasher = DoubleHashBuilder::<u64>::new()
.with_seed1(12345)
.with_seed2(67890)
.with_n(u64::MAX)
.build_hash_iter_hasher();
let hashes = hasher.hash_iter(&"hello", 3).collect::<Vec<_>>();
assert_eq!(hashes, vec![
10179864958193109059,
16936771314159985077,
5246933596417309481
]);
}
#[test]
fn custom_hash_builders() {
let hasher = DoubleHashHasher::<u64, _, _>::with_hash_builders(
Xxh3Builder::new().with_seed(12345),
Xxh3Builder::new().with_seed(67890),
u64::MAX,
);
let hashes = hasher.hash_iter(&"hello", 3).collect::<Vec<_>>();
assert_eq!(hashes, vec![
10179864958193109059,
16936771314159985077,
5246933596417309481
]);
}
#[test]
fn use_as_struct_field() {
{
struct Foo {
hasher: DoubleHashHasher<u64, Xxh3Builder, Xxh3Builder>,
}
impl Foo {
fn new() -> Self {
Self {
hasher: DoubleHashHasher::<u64, _, _>::new(),
}
}
fn hash(&self, key: u64, count: usize) -> Vec<u64> {
self.hasher.hash_iter(&key, count).collect()
}
}
let foo = Foo::new();
let hashes = foo.hash(42, 3);
assert_eq!(hashes, vec![
2604207548944960858,
14475308512507584086,
7899665402360655700
]);
}
{
struct Foo {
hasher: DoubleHashHasher<u64, Xxh3Builder, Xxh3Builder>,
}
impl Foo {
fn new() -> Self {
Self {
hasher: DoubleHashHasher::<u64, _, _>::new(),
}
}
fn hash(&self, key: u64, count: usize) -> Vec<u64> {
self.hasher.hash_iter(&key, count).collect()
}
}
let foo = Foo::new();
let hashes = foo.hash(42, 3);
assert_eq!(hashes, vec![
2604207548944960858,
14475308512507584086,
7899665402360655700
]);
}
}
#[test]
fn modular_arithmetic_overflow_regression() {
use hash_iter::Hashes;
let hash1: u64 = u64::MAX - 100; let hash2: u64 = u64::MAX - 50; let n: u64 = 1000;
let k: u64 = 3;
let mut iter = Hashes::<u64>::new(hash1, hash2, n, k);
let first = iter.next();
assert_eq!(first, Some(515), "First hash should be hash1 % n = 515");
let second = iter.next();
assert_eq!(
second,
Some(80),
"If you see 465, the implementation is using wrapping_add incorrectly."
);
let third = iter.next();
assert_eq!(third, Some(646), "Third hash should be 646");
assert_eq!(
iter.next(),
None,
"Iterator should be exhausted after k iterations"
);
}
#[test]
fn clone_iterator_checkpoint() {
use hash_iter::Hashes;
let hash1: u64 = 12345;
let hash2: u64 = 67890;
let n: u64 = 10000;
let k: u64 = 5;
let iter = Hashes::<u64>::new(hash1, hash2, n, k);
let clone_at_start = iter.clone();
let original_values: Vec<_> = iter.collect();
let cloned_values: Vec<_> = clone_at_start.collect();
assert_eq!(
original_values, cloned_values,
"Clone at start should produce identical sequence"
);
assert_eq!(original_values.len(), 5, "Should produce 5 values");
let mut iter = Hashes::<u64>::new(hash1, hash2, n, k);
let _first = iter.next();
let _second = iter.next();
let checkpoint = iter.clone();
let remaining_original: Vec<_> = iter.collect();
let remaining_checkpoint: Vec<_> = checkpoint.collect();
assert_eq!(
remaining_original, remaining_checkpoint,
"Clone mid-iteration should produce identical remaining sequence"
);
assert_eq!(
remaining_original.len(),
3,
"Should have 3 remaining values after consuming 2"
);
let mut iter1 = Hashes::<u64>::new(hash1, hash2, n, k);
let mut iter2 = iter1.clone();
let val1_from_iter1 = iter1.next();
let val1_from_iter2 = iter2.next();
assert_eq!(
val1_from_iter1, val1_from_iter2,
"First values should match"
);
iter1.next();
iter1.next();
let val2_from_iter2 = iter2.next();
let mut fresh = Hashes::<u64>::new(hash1, hash2, n, k);
fresh.next();
let val2_from_fresh = fresh.next();
assert_eq!(
val2_from_iter2, val2_from_fresh,
"Cloned iterator should be independent of original"
);
let iter = Hashes::<u64>::new(hash1, hash2, n, 3);
let copy_of_iter = iter;
let from_original: Vec<_> = iter.collect();
let from_copy: Vec<_> = copy_of_iter.collect();
assert_eq!(
from_original, from_copy,
"Copy should work the same as Clone for iterator state"
);
let mut iter = Hashes::<u64>::new(hash1, hash2, n, 10);
let checkpoint_0 = iter.clone();
iter.next();
iter.next();
let checkpoint_2 = iter.clone();
iter.next();
iter.next();
let checkpoint_4 = iter.clone();
assert_eq!(checkpoint_0.count(), 10, "Checkpoint at position 0");
assert_eq!(checkpoint_2.count(), 8, "Checkpoint at position 2");
assert_eq!(checkpoint_4.count(), 6, "Checkpoint at position 4");
}
#[test]
fn test_u32_type() {
let hasher = DoubleHashBuilder::<u32>::new().build_hash_iter_hasher();
let hashes: Vec<u32> = hasher.hash_iter(&"test", 20).collect();
assert_eq!(hashes.len(), 20);
for &hash in &hashes {
assert!(hash <= u32::MAX);
}
}
#[test]
fn test_u64_type() {
let hasher = DoubleHashBuilder::<u64>::new().build_hash_iter_hasher();
let hashes: Vec<u64> = hasher.hash_iter(&"test", 20).collect();
assert_eq!(hashes.len(), 20);
for &hash in &hashes {
assert!(hash <= u64::MAX);
}
}
#[test]
fn test_u128_type() {
let hasher = DoubleHashBuilder::<u128>::new().build_hash_iter_hasher();
let hashes: Vec<u128> = hasher.hash_iter(&"test", 15).collect();
assert_eq!(hashes.len(), 15);
for &hash in &hashes {
assert!(hash <= u128::MAX);
}
}
#[test]
fn test_u32_with_custom_seeds() {
let hasher = DoubleHashBuilder::<u32>::new()
.with_seed1(11111)
.with_seed2(22222)
.build_hash_iter_hasher();
let hashes: Vec<u32> = hasher.hash_iter(&"custom_seeds", 10).collect();
assert_eq!(hashes.len(), 10);
let hashes2: Vec<u32> = hasher.hash_iter(&"custom_seeds", 10).collect();
assert_eq!(hashes, hashes2);
}
#[test]
fn test_different_types_produce_different_results() {
let key = "same_key";
let count = 10;
let hasher_u32 = DoubleHashBuilder::<u32>::new()
.with_n(1000)
.build_hash_iter_hasher();
let hasher_u64 = DoubleHashBuilder::<u64>::new()
.with_n(1000)
.build_hash_iter_hasher();
let hashes_u32: Vec<u32> = hasher_u32.hash_iter(&key, count).collect();
let hashes_u64: Vec<u64> = hasher_u64.hash_iter(&key, count).collect();
assert_eq!(hashes_u32.len(), count);
assert_eq!(hashes_u64.len(), count);
for &hash in &hashes_u32 {
assert!(hash < 1000);
}
for &hash in &hashes_u64 {
assert!(hash < 1000);
}
assert_ne!(hashes_u32[0] as u64, hashes_u64[0]);
}
#[test]
fn test_custom_hash_builders_with_u32() {
use xxhash_rust::xxh3::Xxh3Builder;
let hasher = DoubleHashHasher::<u32, _, _>::with_hash_builders(
Xxh3Builder::new().with_seed(42),
Xxh3Builder::new().with_seed(84),
u32::MAX,
);
let hashes: Vec<u32> = hasher.hash_iter(&"custom_builder", 8).collect();
assert_eq!(hashes.len(), 8);
let hashes2: Vec<u32> = hasher.hash_iter(&"custom_builder", 8).collect();
assert_eq!(hashes, hashes2);
}