use {mpchash::HashRing, rand::random, std::ops::Deref};
#[derive(Hash, Clone, Copy, Debug, Eq, PartialEq, Ord, PartialOrd)]
struct Node {
id: u64,
}
impl Node {
fn random() -> Self {
Self { id: random() }
}
}
#[test]
fn add_node() {
let ring = HashRing::new();
let num_nodes = 10;
let mut nodes = Vec::with_capacity(num_nodes);
for i in 0..num_nodes {
nodes.insert(i, Node { id: i as u64 });
ring.add(nodes[i]);
}
let num_keys = 1000;
for i in 0..num_keys {
let node = ring.node(&i).unwrap();
assert!(nodes.contains(&node));
}
}
#[test]
fn remove_node() {
let ring = HashRing::new();
let node1 = Node::random();
let node2 = Node::random();
ring.add(node1);
ring.add(node2);
assert_eq!(ring.len(), 2);
ring.remove(&node1);
assert_eq!(ring.len(), 1);
assert_eq!(ring.node(&0).as_deref(), Some(&node2));
}
#[test]
fn duplicate_peer() {
let ring = HashRing::new();
let node = Node::random();
ring.add(node);
ring.add(node);
assert_eq!(ring.len(), 1);
assert_eq!(ring.node(&0).as_deref(), Some(&node));
}
#[test]
fn walkthrough() {
#[derive(Hash, Debug, PartialEq, Clone, Copy)]
struct MyNode(u64);
let ring = HashRing::new();
(1..=5).for_each(|i| {
ring.add(MyNode(i));
});
let key = "hello world";
let token = ring.node(&key).expect("empty ring");
assert_eq!(token.position(), 1242564280540428107);
assert_eq!(token.node(), &MyNode(2));
let tokens = ring.replicas(&key, 3);
assert_eq!(tokens, vec![&MyNode(1), &MyNode(2), &MyNode(3)]);
let tokens = ring.replicas(&key, 3);
assert_eq!(tokens.iter().map(|e| e.node()).collect::<Vec<_>>(), vec![
&MyNode(1),
&MyNode(2),
&MyNode(3)
]);
assert_eq!(tokens.iter().map(Deref::deref).collect::<Vec<_>>(), vec![
&MyNode(1),
&MyNode(2),
&MyNode(3)
]);
let ranges = ring.intervals(&token).expect("empty ring");
assert_eq!(ranges.len(), 1);
assert_eq!(ranges[0].start, ring.position(&MyNode(1)));
assert_eq!(ranges[0].end, ring.position(&token.node()));
ring.remove(&MyNode(2));
let token = ring.node(&key).expect("empty ring");
assert_eq!(token.node(), &MyNode(4));
let tokens = ring.replicas(&key, 3);
assert_eq!(tokens, vec![&MyNode(1), &MyNode(3), &MyNode(4)]);
}