use super::{check_executor, check_rrf, check_stable_hash};
use crate::fusion::FusionStrategy;
use crate::{hash_edge_id, hash_id};
use proptest::prelude::*;
fn reference_rrf(inputs: Vec<Vec<(u64, f32)>>, k: u32) -> Vec<(u64, f32)> {
FusionStrategy::RRF { k }.fuse(inputs).unwrap_or_default()
}
proptest! {
#![proptest_config(ProptestConfig::with_cases(100))]
#[test]
fn prop_hash_divergence_detected(mask in 1_u64..=u64::MAX) {
prop_assert!(check_stable_hash(hash_id).is_empty());
let perturbed = |s: &str| hash_id(s) ^ mask;
let divergences = check_stable_hash(perturbed);
prop_assert!(!divergences.is_empty());
let first = &divergences[0];
prop_assert!(!first.case.is_empty());
prop_assert_ne!(&first.expected, &first.actual);
}
#[test]
fn prop_executor_divergence_detected(delta in 1_u64..=u64::MAX) {
prop_assert!(check_executor(hash_edge_id).is_empty());
let perturbed = |source: u64, target: u64, label: &str| {
hash_edge_id(source, target, label).wrapping_add(delta)
};
let divergences = check_executor(perturbed);
prop_assert!(!divergences.is_empty());
let first = &divergences[0];
prop_assert!(!first.case.is_empty());
prop_assert_ne!(&first.expected, &first.actual);
}
#[test]
fn prop_rrf_divergence_detected(id_delta in 1_u64..=u64::MAX) {
prop_assert!(check_rrf(reference_rrf).is_empty());
let perturbed = |inputs: Vec<Vec<(u64, f32)>>, k: u32| {
reference_rrf(inputs, k)
.into_iter()
.map(|(id, score)| (id.wrapping_add(id_delta), score))
.collect::<Vec<_>>()
};
let divergences = check_rrf(perturbed);
prop_assert!(!divergences.is_empty());
let first = &divergences[0];
prop_assert!(!first.case.is_empty());
prop_assert_ne!(&first.expected, &first.actual);
}
}