use super::*;
#[test]
fn test_evaluate_parent_picks_smallest_root() {
let my_node = make_node_addr(5);
let mut state = TreeState::new(my_node);
let peer3 = make_node_addr(3);
let peer7 = make_node_addr(7);
state.update_peer(
ParentDeclaration::new(peer3, make_node_addr(1), 1, 1000),
make_coords(&[3, 1]),
);
state.update_peer(
ParentDeclaration::new(peer7, make_node_addr(2), 1, 1000),
make_coords(&[7, 2]),
);
let result = state.evaluate_parent(&HashMap::new());
assert_eq!(result, Some(peer3));
}
#[test]
fn test_evaluate_parent_prefers_shallowest_depth() {
let my_node = make_node_addr(5);
let mut state = TreeState::new(my_node);
let peer1 = make_node_addr(1);
let peer2 = make_node_addr(2);
let root = make_node_addr(0);
state.update_peer(
ParentDeclaration::new(peer1, root, 1, 1000),
make_coords(&[1, 0]),
);
state.update_peer(
ParentDeclaration::new(peer2, make_node_addr(3), 1, 1000),
make_coords(&[2, 3, 4, 0]),
);
let result = state.evaluate_parent(&HashMap::new());
assert_eq!(result, Some(peer1));
}
#[test]
fn test_evaluate_parent_stays_root_when_smallest() {
let my_node = make_node_addr(0);
let mut state = TreeState::new(my_node);
let peer1 = make_node_addr(1);
state.update_peer(
ParentDeclaration::new(peer1, my_node, 1, 1000),
make_coords(&[1, 0]),
);
assert_eq!(state.evaluate_parent(&HashMap::new()), None);
}
#[test]
fn test_evaluate_parent_no_switch_when_already_best() {
let my_node = make_node_addr(5);
let mut state = TreeState::new(my_node);
let peer1 = make_node_addr(1);
let root = make_node_addr(0);
state.update_peer(
ParentDeclaration::new(peer1, root, 1, 1000),
make_coords(&[1, 0]),
);
state.set_parent(peer1, 1, 1000);
state.recompute_coords();
assert_eq!(state.evaluate_parent(&HashMap::new()), None);
}
#[test]
fn test_evaluate_parent_no_peers() {
let my_node = make_node_addr(5);
let state = TreeState::new(my_node);
assert_eq!(state.evaluate_parent(&HashMap::new()), None);
}
#[test]
fn test_evaluate_parent_depth_threshold() {
let my_node = make_node_addr(5);
let mut state = TreeState::new(my_node);
let peer2 = make_node_addr(2);
let peer3 = make_node_addr(3);
let root = make_node_addr(0);
state.update_peer(
ParentDeclaration::new(peer2, make_node_addr(6), 1, 1000),
make_coords(&[2, 6, 7, 0]),
);
state.set_parent(peer2, 1, 1000);
state.recompute_coords();
assert_eq!(state.my_coords().depth(), 4);
state.update_peer(
ParentDeclaration::new(peer3, root, 1, 1000),
make_coords(&[3, 0]),
);
let result = state.evaluate_parent(&HashMap::new());
assert_eq!(result, Some(peer3));
}
#[test]
fn test_evaluate_parent_rejects_loop_candidate() {
let my_node = make_node_addr(5);
let mut state = TreeState::new(my_node);
let peer1 = make_node_addr(1);
let _root = make_node_addr(0);
state.update_peer(
ParentDeclaration::new(peer1, my_node, 1, 1000),
make_coords(&[1, 5, 0]),
);
assert_eq!(state.evaluate_parent(&HashMap::new()), None);
}
#[test]
fn test_evaluate_parent_picks_loop_free_over_loopy() {
let my_node = make_node_addr(5);
let mut state = TreeState::new(my_node);
let peer1 = make_node_addr(1);
let peer2 = make_node_addr(2);
let _root = make_node_addr(0);
state.update_peer(
ParentDeclaration::new(peer1, my_node, 1, 1000),
make_coords(&[1, 5, 0]),
);
state.update_peer(
ParentDeclaration::new(peer2, make_node_addr(3), 1, 1000),
make_coords(&[2, 3, 4, 0]),
);
let result = state.evaluate_parent(&HashMap::new());
assert_eq!(result, Some(peer2));
}
#[test]
fn test_handle_parent_lost_finds_alternative() {
let my_node = make_node_addr(5);
let mut state = TreeState::new(my_node);
let peer1 = make_node_addr(1);
let peer2 = make_node_addr(2);
let root = make_node_addr(0);
state.update_peer(
ParentDeclaration::new(peer1, root, 1, 1000),
make_coords(&[1, 0]),
);
state.update_peer(
ParentDeclaration::new(peer2, root, 1, 1000),
make_coords(&[2, 0]),
);
state.set_parent(peer1, 1, 1000);
state.recompute_coords();
state.remove_peer(&peer1);
let changed = state.handle_parent_lost(&HashMap::new());
assert!(changed);
assert_eq!(state.my_declaration().parent_id(), &peer2);
assert!(!state.is_root());
}
#[test]
fn test_handle_parent_lost_becomes_root_when_self_smaller_than_remaining() {
let my_node = make_node_addr(1); let mut state = TreeState::new(my_node);
let smaller = make_node_addr(0);
let bigger1 = make_node_addr(2);
let bigger2 = make_node_addr(3);
state.update_peer(
ParentDeclaration::self_root(smaller, 1, 1000),
make_coords(&[0]),
);
state.update_peer(
ParentDeclaration::self_root(bigger1, 1, 1000),
make_coords(&[2]),
);
state.update_peer(
ParentDeclaration::self_root(bigger2, 1, 1000),
make_coords(&[3]),
);
state.set_parent(smaller, 2, 2000);
state.recompute_coords();
assert_eq!(state.my_coords().entries().len(), 2);
assert_eq!(state.root(), &smaller);
state.remove_peer(&smaller);
let changed = state.handle_parent_lost(&HashMap::new());
assert!(changed);
assert!(
state.is_root(),
"must self-root when no smaller peer remains"
);
assert_eq!(state.root(), &my_node);
assert_eq!(state.my_coords().entries().len(), 1);
let entries = state.my_coords().entries();
let min = entries.iter().map(|e| e.node_addr).min().unwrap();
assert_eq!(*state.my_coords().root_id(), min);
}
#[test]
fn test_recompute_coords_demotes_when_self_smaller_than_parent_root() {
let my_node = make_node_addr(5);
let mut state = TreeState::new(my_node);
let bigger_peer = make_node_addr(7);
state.update_peer(
ParentDeclaration::self_root(bigger_peer, 1, 1000),
make_coords(&[7]),
);
state.set_parent(bigger_peer, 2, 2000);
state.recompute_coords();
assert!(state.is_root(), "recompute_coords demoted to self-root");
assert_eq!(state.root(), &my_node);
assert_eq!(state.my_coords().entries().len(), 1);
let entries = state.my_coords().entries();
let min = entries.iter().map(|e| e.node_addr).min().unwrap();
assert_eq!(*state.my_coords().root_id(), min);
}
#[test]
fn test_handle_parent_lost_becomes_root() {
let my_node = make_node_addr(5);
let mut state = TreeState::new(my_node);
let peer1 = make_node_addr(1);
let root = make_node_addr(0);
state.update_peer(
ParentDeclaration::new(peer1, root, 1, 1000),
make_coords(&[1, 0]),
);
state.set_parent(peer1, 1, 1000);
state.recompute_coords();
let seq_before = state.my_declaration().sequence();
state.remove_peer(&peer1);
let changed = state.handle_parent_lost(&HashMap::new());
assert!(changed);
assert!(state.is_root());
assert!(state.my_declaration().sequence() > seq_before);
assert_eq!(state.root(), &my_node);
}