use horon_engine::{SemanticOutlier, Store};
use g_math::fixed_point::FixedPoint;
fn coords(vals: &[f64]) -> Vec<u8> {
let mut out = vec![0u8; 16 * 16];
for &v in vals {
out.extend_from_slice(&FixedPoint::from_f64(v).raw().to_le_bytes());
}
out
}
fn store_with_planted_outlier() -> Store {
let store = Store::new();
store.put_data_only("/courses", b"parent").unwrap();
for i in 0..30 {
let key = format!("/courses/c{:02}", i);
store.put_data_only(&key, b"x").unwrap();
let dx = (i % 5) as f64 * 0.01;
let dy = (i / 5) as f64 * 0.01;
store.set_semantic(&key, coords(&[0.5 + dx, 0.5 + dy])).unwrap();
}
store.put_data_only("/courses/dementie", b"x").unwrap();
store.set_semantic("/courses/dementie", coords(&[9.0, 9.0])).unwrap();
store
}
#[test]
fn find_similar_equals_neighbors_semantic() {
let store = store_with_planted_outlier();
let a = store.find_similar("/courses/c07", 5, 16..18).unwrap();
let b = store.neighbors_semantic("/courses/c07", 5, 16..18).unwrap();
assert_eq!(a, b);
assert_eq!(a.len(), 5);
assert!(a.iter().all(|(k, _)| k != "/courses/c07"), "self must be excluded");
}
#[test]
fn find_outliers_flags_the_planted_anomaly() {
let store = store_with_planted_outlier();
let outliers = store.find_outliers("/courses", FixedPoint::from_f64(2.0), 16..18).unwrap();
assert!(!outliers.is_empty(), "the planted outlier must be found");
let top: &SemanticOutlier = &outliers[0];
assert_eq!(top.key, "/courses/dementie");
assert!(top.z_score.to_f64() > 2.0);
assert!(
top.nearest_peer.starts_with("/courses/c"),
"nearest peer must come from the cluster: {}",
top.nearest_peer
);
assert!(top.nearest_distance.to_f64() > 5.0, "even its best match is far away");
assert!(
outliers.iter().all(|o| o.key == "/courses/dementie"),
"cluster members wrongly flagged: {:?}",
outliers
);
}
#[test]
fn outlier_statistics_respect_the_prefix_boundary() {
let store = store_with_planted_outlier();
store.put_data_only("/venues", b"parent").unwrap();
for i in 0..20 {
let key = format!("/venues/v{:02}", i);
store.put_data_only(&key, b"x").unwrap();
store.set_semantic(&key, coords(&[100.0 + i as f64, 100.0])).unwrap();
}
let outliers = store.find_outliers("/courses", FixedPoint::from_f64(2.0), 16..18).unwrap();
assert_eq!(outliers.len(), 1);
assert_eq!(outliers[0].key, "/courses/dementie");
assert!(
outliers[0].nearest_peer.starts_with("/courses/"),
"peer from outside the prefix population: {}",
outliers[0].nearest_peer
);
}
#[test]
fn small_and_uniform_populations_yield_no_outliers() {
let store = Store::new();
store.put_data_only("/few", b"parent").unwrap();
for i in 0..3 {
let key = format!("/few/n{}", i);
store.put_data_only(&key, b"x").unwrap();
store.set_semantic(&key, coords(&[i as f64 * 50.0, 0.0])).unwrap();
}
assert!(store.find_outliers("/few", FixedPoint::from_f64(2.0), 16..18).unwrap().is_empty());
store.put_data_only("/same", b"parent").unwrap();
for i in 0..10 {
let key = format!("/same/n{}", i);
store.put_data_only(&key, b"x").unwrap();
store.set_semantic(&key, coords(&[1.0, 1.0])).unwrap();
}
assert!(store.find_outliers("/same", FixedPoint::from_f64(2.0), 16..18).unwrap().is_empty());
}
#[test]
fn find_outliers_rejects_bad_thresholds() {
let store = store_with_planted_outlier();
assert!(store.find_outliers("/courses", FixedPoint::from_int(0), 16..18).is_err());
assert!(store.find_outliers("/courses", FixedPoint::from_int(-1), 16..18).is_err());
assert!(store.find_outliers("/courses", FixedPoint::from_raw(-1), 16..18).is_err());
}