use super::*;
fn vars_below(vtree: &Vtree, node: VtreeIdx) -> Vec<u32> {
let mut out = leaves_under(vtree, node);
out.sort_unstable();
out
}
#[test]
fn lca_of_two_leaves_is_the_node_whose_subtrees_separate_them() {
let vtree = Vtree::balanced(4);
let leaf = |var: u32| vtree.leaf_of(VarId(var));
let parent = |node: VtreeIdx| vtree.node(node).parent().expect("not the root");
let left_half = parent(leaf(0));
let right_half = parent(leaf(2));
assert_ne!(
left_half, right_half,
"the fixture puts v0 and v2 in different halves",
);
for node in vtree.bottomup() {
assert_eq!(vtree.lca(node, node), node, "a node meets itself at itself");
}
assert_eq!(vtree.lca(leaf(0), leaf(1)), left_half, "siblings");
assert_eq!(vtree.lca(leaf(2), leaf(3)), right_half, "siblings");
assert_eq!(vtree.lca(leaf(0), left_half), left_half);
assert_eq!(vtree.lca(left_half, leaf(0)), left_half);
assert_eq!(vtree.lca(leaf(0), vtree.root()), vtree.root());
for a in [leaf(0), leaf(1)] {
for b in [leaf(2), leaf(3)] {
assert_eq!(vtree.lca(a, b), vtree.root());
assert_eq!(vtree.lca(b, a), vtree.root());
}
}
}
#[test]
fn lca_still_answers_correctly_after_a_rotation_has_reordered_the_topo() {
let mut rotated = Vtree::linear(4);
let root = rotated.root();
rotate::rotate_left(&mut rotated, root).expect("the root's right child is internal");
let fresh = Vtree::balanced(4);
assert!(
rotated.same_tree(&fresh),
"the rotation must reach the balanced shape",
);
for (a, b) in [(0u32, 1u32), (2, 3), (0, 2), (1, 3), (0, 3), (1, 2)] {
let in_rotated = rotated.lca(rotated.leaf_of(VarId(a)), rotated.leaf_of(VarId(b)));
let in_fresh = fresh.lca(fresh.leaf_of(VarId(a)), fresh.leaf_of(VarId(b)));
assert_eq!(
vars_below(&rotated, in_rotated),
vars_below(&fresh, in_fresh),
"v{a} and v{b} must meet at the same node of the same tree",
);
}
}