#[cfg(test)]
mod tests {
use anyhow::Result;
use crate::code::Code;
use crate::code::similarity::SimilaritySketch;
fn widest_container(code: &Code) -> Vec<usize> {
let metadata = code.metadata.ast_metadata.as_ref().expect("parsed");
let mut best: Vec<usize> = Vec::new();
for info in metadata.node_info.values() {
if info.children.len() > best.len() {
best = info.children.clone();
}
}
best.sort_by_key(|c| metadata.node_info[c].start_byte);
best
}
fn sketches(code: &Code, ids: &[usize]) -> Vec<SimilaritySketch> {
let metadata = code.metadata.ast_metadata.as_ref().expect("parsed");
ids.iter()
.map(|id| metadata.node_to_similarity_sketch[id].clone())
.collect()
}
fn kinds(code: &Code, ids: &[usize]) -> Vec<String> {
let metadata = code.metadata.ast_metadata.as_ref().expect("parsed");
ids.iter()
.map(|id| metadata.node_info[id].kind.clone())
.collect()
}
fn load(name: &str) -> Result<(Vec<SimilaritySketch>, Vec<SimilaritySketch>, Vec<String>)> {
let pairs = crate::test::helper::handmade_test_code_pairs_for(&[name])?;
let (before, after) = &**pairs.get(name).expect("fixture present");
let (bc, ac) = (widest_container(before), widest_container(after));
let names = kinds(before, &bc);
Ok((sketches(before, &bc), sketches(after, &ac), names))
}
#[test]
fn sketch_recovers_a_permutation_of_near_identical_yaml_urls() -> Result<()> {
let (before, after, kinds) = load("yaml-draios-sysdig-string-url-change")?;
let expected: Vec<(usize, usize)> = vec![(1, 3), (3, 9), (5, 1), (7, 5), (9, 11), (11, 7)];
for (b, a) in expected {
assert_eq!(kinds[b], "flow_node", "fixture shape changed at index {b}");
let scores: Vec<f32> = after.iter().map(|s| before[b].jaccard(s)).collect();
let best = scores
.iter()
.enumerate()
.max_by(|x, y| x.1.total_cmp(y.1))
.map(|(i, _)| i)
.expect("non-empty");
assert_eq!(
best, a,
"before[{b}] should be most similar to after[{a}], got {best}: {scores:?}"
);
assert_eq!(scores[a], 1.0, "true counterparts are byte-identical here");
let runner_up = scores
.iter()
.enumerate()
.filter(|(i, _)| *i != a)
.map(|(_, s)| *s)
.fold(0.0f32, f32::max);
assert!(
runner_up < 0.5,
"before[{b}]'s runner-up scored {runner_up}, too close to call"
);
}
Ok(())
}
#[test]
fn sketch_grades_the_near_miss_the_equality_hashes_call_different() -> Result<()> {
let (before, after, kinds) = load("css-wordpress-reformat")?;
assert_eq!(kinds[1], "declaration", "fixture shape changed");
let near_miss = before[3].jaccard(&after[2]);
assert!(
(0.5..1.0).contains(&near_miss),
"near-miss declarations scored {near_miss}, wanted clearly-similar-but-not-equal"
);
let unrelated = before[1].jaccard(&after[2]);
assert!(
unrelated < near_miss * 0.5,
"unrelated declaration scored {unrelated} against a near-miss of {near_miss}"
);
Ok(())
}
}