use nodedb_vector::DistanceMetric;
use nodedb_vector::hnsw::{HnswIndex, HnswParams};
const LAYER_CAP: usize = 16;
#[test]
fn random_layer_never_exceeds_cap_under_normal_inserts() {
let mut idx = HnswIndex::with_seed(
4,
HnswParams {
m: 16,
m0: 32,
ef_construction: 64,
metric: DistanceMetric::L2,
},
1,
);
for i in 0..5_000u32 {
let v = vec![
(i as f32).sin(),
(i as f32).cos(),
((i * 3) as f32).sin(),
((i * 7) as f32).cos(),
];
idx.insert(v).unwrap();
}
assert!(
idx.max_layer() <= LAYER_CAP,
"max_layer grew to {} (cap = {LAYER_CAP}); one pathological random_layer \
draw promoted the index and will slow every subsequent search",
idx.max_layer()
);
}
#[test]
fn random_layer_capped_with_adversarial_seed() {
for seed in [1u64, 2, 3, 7, 13, 42, 123, 9_999, 1_000_003] {
let mut idx = HnswIndex::with_seed(
2,
HnswParams {
m: 2, m0: 4,
ef_construction: 32,
metric: DistanceMetric::L2,
},
seed,
);
for i in 0..2_000u32 {
idx.insert(vec![i as f32, 0.0]).unwrap();
}
assert!(
idx.max_layer() <= LAYER_CAP,
"seed={seed}: max_layer reached {} (cap = {LAYER_CAP}) — \
random_layer has no upper bound",
idx.max_layer()
);
}
}