use crate::bucket::Bucket;
use crate::error::Error;
use crate::node::{Address, Center, Node};
use std::sync::{Arc, Mutex};
pub struct Table {
root: Element,
center: Center,
}
#[derive(Clone)]
pub struct Safe {
table: Arc<Mutex<Table>>,
center: Center,
}
#[derive(Clone, Debug)]
struct Property {
lower: u8,
upper: u8,
}
#[derive(Clone, Debug)]
enum Element {
Split(Split, Property),
Leaf(Bucket, Property),
}
#[derive(Clone, Debug)]
struct Split {
near: Box<Element>,
far: Box<Element>,
}
impl Table {
pub fn new(limit: usize, center: Center) -> Self {
Table {
root: Element::Leaf(
Bucket::new(limit),
Property {
lower: 0,
upper: 255,
},
),
center,
}
}
pub fn try_add(&mut self, node: Node) -> Result<(), Error> {
self.root.try_add(node, &self.center)
}
pub fn add(&mut self, node: Node) {
if &node.address != &self.center.public {
match self.find_mut(&node.address) {
Some(found) => {
found.link = node.link;
}
None => {
self.root.add(node, &self.center);
}
}
}
}
pub fn remove(&mut self, address: &Address) -> Result<(), Error> {
self.root.remove(address, &self.center)
}
pub fn find(&self, address: &Address) -> Option<&Node> {
self.root.find(address, &self.center)
}
pub fn find_mut(&mut self, address: &Address) -> Option<&mut Node> {
self.root.find_mut(address, &self.center)
}
pub fn get(&self, address: &Address, limit: usize) -> Vec<&Node> {
self.root.get(address, &self.center, limit)
}
pub fn get_copy(&self, address: &Address, limit: usize) -> Vec<Node> {
let mut nodes = Vec::new();
let refs = self.get(address, limit);
for n in refs {
nodes.push(n.clone());
}
return nodes;
}
pub fn capacity(&self) -> usize {
self.root.capacity()
}
pub fn status(&mut self, address: &Address, status: bool) {
match self.root.find_mut(address, &self.center) {
Some(node) => node.update(status),
None => (),
}
}
pub fn len(&self) -> usize {
self.root.len()
}
pub fn export(&self) -> Vec<u8> {
let mut data = Vec::new();
let nodes = self.get(&self.center.public, self.len());
for n in nodes {
data.append(&mut n.as_bytes().to_vec());
}
let center = Node::new(self.center.public.clone(), Some(self.center.link.clone()));
data.append(&mut center.as_bytes());
return data;
}
pub fn should_be_local(&self, address: &Address) -> bool {
if address == &self.center.public {
return true;
}
let nodes = self.get(address, 1);
if let Some(node) = nodes.first() {
let d1 = address ^ &node.address;
let d2 = address ^ &self.center.public;
d1 >= d2
} else {
true
}
}
pub fn center(&self) -> Address {
self.center.public.clone()
}
}
impl Safe {
pub fn new(limit: usize, center: Center) -> Self {
Self {
table: Arc::new(Mutex::new(Table::new(limit, center.clone()))),
center: center,
}
}
pub fn try_add(&self, node: Node) -> Result<(), Error> {
let mut table = self.table.lock().unwrap();
(*table).try_add(node)
}
pub fn add(&self, node: Node) {
let mut table = self.table.lock().unwrap();
(*table).add(node);
}
pub fn remove(&self, address: &Address) -> Result<(), Error> {
let mut table = self.table.lock().unwrap();
(*table).remove(address)
}
pub fn get_copy(&self, address: &Address, limit: usize) -> Vec<Node> {
let table = self.table.lock().unwrap();
(*table).get_copy(address, limit)
}
pub fn capacity(&self) -> usize {
let table = self.table.lock().unwrap();
(*table).capacity()
}
pub fn status(&self, address: &Address, status: bool) {
let mut table = self.table.lock().unwrap();
(*table).status(address, status);
}
pub fn len(&self) -> usize {
let table = self.table.lock().unwrap();
(*table).len()
}
pub fn export(&self) -> Vec<u8> {
let table = self.table.lock().unwrap();
(*table).export()
}
pub fn should_be_local(&self, address: &Address) -> bool {
let table = self.table.lock().unwrap();
(*table).should_be_local(address)
}
pub fn center(&self) -> Address {
self.center.public.clone()
}
}
impl Element {
fn try_add(&mut self, node: Node, center: &Center) -> Result<(), Error> {
match self {
Self::Split(s, p) => {
if !p.in_range(&node.address, ¢er) {
return Err(Error::Invalid(String::from("not in range")));
}
if p.is_near() {
s.try_add(node, center)
} else {
s.add(node, center);
Ok(())
}
}
Self::Leaf(b, p) => {
if !p.in_range(&node.address, ¢er) {
return Err(Error::Invalid(String::from("not in range")));
}
b.try_add(node)
}
}
}
fn add(&mut self, node: Node, center: &Center) {
match self {
Self::Split(s, _) => s.add(node, center),
Self::Leaf(b, p) => {
if p.is_near() {
match b.try_add(node.clone()) {
Ok(()) => return,
Err(_) => {
*self = self.clone().split(center).unwrap();
self.add(node, center);
}
}
} else {
b.add(node)
}
}
}
}
fn remove(&mut self, address: &Address, center: &Center) -> Result<(), Error> {
if let None = self.find(address, center) {
return Err(Error::Unknown);
}
match self {
Self::Split(s, _) => {
if s.is_final() {
let _ = s.remove(address, center);
if (s.capacity() / 2) > s.len() {
if let Ok(e) = s.collapse() {
*self = e;
} else {
return Err(Error::Unknown);
}
}
} else {
s.remove(address, center)?;
}
}
Self::Leaf(b, _) => {
b.remove(address)?;
}
}
Ok(())
}
fn split(self, center: &Center) -> Option<Self> {
match self {
Self::Split(_, _) => return None,
Self::Leaf(b, p) => {
if p.lower != 0 {
return None;
}
let (near, far) = b.split(center, p.upper);
let (near_p, far_p) = p.split();
let split = Split {
near: Box::new(Self::Leaf(near, near_p)),
far: Box::new(Self::Leaf(far, far_p)),
};
Some(Self::Split(split, p))
}
}
}
fn find(&self, search: &Address, center: &Center) -> Option<&Node> {
if !self.in_range(search, center) {
return None;
}
match self {
Self::Split(s, _) => s.find(search, center),
Self::Leaf(b, _) => b.find(search),
}
}
fn find_mut(&mut self, search: &Address, center: &Center) -> Option<&mut Node> {
if !self.in_range(search, center) {
return None;
}
match self {
Self::Split(s, _) => s.find_mut(search, center),
Self::Leaf(b, _) => b.find_mut(search),
}
}
fn get(&self, target: &Address, center: &Center, limit: usize) -> Vec<&Node> {
match self {
Self::Split(s, _) => s.get(target, center, limit),
Self::Leaf(b, _) => b.get(limit),
}
}
fn len(&self) -> usize {
match self {
Self::Split(s, _) => s.len(),
Self::Leaf(b, _) => b.len(),
}
}
fn capacity(&self) -> usize {
let mut sum = 0;
match self {
Self::Split(s, _) => sum += s.capacity(),
Self::Leaf(b, _) => sum += b.capacity(),
}
return sum;
}
fn in_range(&self, address: &Address, center: &Center) -> bool {
match self {
Self::Split(_, p) => p.in_range(&address, center),
Self::Leaf(_, p) => p.in_range(&address, center),
}
}
fn is_leaf(&self) -> bool {
match self {
Self::Split(_, _) => false,
Self::Leaf(_, _) => true,
}
}
}
impl Split {
fn try_add(&mut self, node: Node, center: &Center) -> Result<(), Error> {
if self.near.in_range(&node.address, center) {
self.near.try_add(node, center)
} else {
self.far.try_add(node, center)
}
}
fn add(&mut self, node: Node, center: &Center) {
if self.near.in_range(&node.address, center) {
self.near.add(node, center)
} else {
self.far.add(node, center)
}
}
fn find(&self, search: &Address, center: &Center) -> Option<&Node> {
if self.near.in_range(search, center) {
self.near.find(search, center)
} else {
self.far.find(search, center)
}
}
fn find_mut(&mut self, search: &Address, center: &Center) -> Option<&mut Node> {
if self.near.in_range(search, center) {
self.near.find_mut(search, center)
} else {
self.far.find_mut(search, center)
}
}
fn get(&self, target: &Address, center: &Center, limit: usize) -> Vec<&Node> {
let mut nodes = Vec::new();
if self.near.in_range(&target, ¢er) {
nodes.append(&mut self.near.get(target, center, limit));
if nodes.len() >= limit {
nodes.truncate(limit);
return nodes;
} else {
nodes.append(&mut self.far.get(target, center, limit));
nodes.truncate(limit);
return nodes;
}
} else {
nodes.append(&mut self.far.get(target, center, limit));
if nodes.len() >= limit {
nodes.truncate(limit);
return nodes;
} else {
nodes.append(&mut self.near.get(target, center, limit));
nodes.truncate(limit);
return nodes;
}
}
}
fn remove(&mut self, address: &Address, center: &Center) -> Result<(), Error> {
if self.near.in_range(address, center) {
self.near.remove(address, center)
} else {
self.far.remove(address, center)
}
}
fn collapse(&self) -> Result<Element, Error> {
let mut nodes = Vec::new();
let lower;
let upper;
let limit;
if let Element::Leaf(b, p) = &*self.near {
nodes.append(&mut b.get(b.capacity()));
lower = p.lower;
limit = b.capacity();
} else {
return Err(Error::Unknown);
}
if let Element::Leaf(b, p) = &*self.far {
nodes.append(&mut b.get(b.capacity()));
upper = p.upper;
} else {
return Err(Error::Unknown);
}
if nodes.len() > limit {
return Err(Error::Unknown);
}
let mut bucket = Bucket::new(limit);
for i in nodes.into_iter() {
bucket.add(i.clone());
}
let prop = Property { lower, upper };
Ok(Element::Leaf(bucket, prop))
}
fn len(&self) -> usize {
let mut length = self.far.len();
match &*self.near {
Element::Leaf(b, _) => length += b.len(),
Element::Split(s, _) => length += s.len(),
}
return length;
}
fn capacity(&self) -> usize {
let mut sum = self.near.capacity();
sum += self.far.capacity();
return sum;
}
fn is_final(&self) -> bool {
self.near.is_leaf() && self.far.is_leaf()
}
}
impl Property {
fn in_range(&self, address: &Address, center: &Center) -> bool {
let index = (address.clone() ^ center.public.clone())[0];
self.lower <= index && self.upper > index
}
fn split(&self) -> (Self, Self) {
let lower = Self {
lower: self.lower,
upper: self.upper / 2,
};
let upper = Self {
lower: (self.upper / 2) + 1,
upper: self.upper,
};
(lower, upper)
}
fn is_near(&self) -> bool {
self.lower == 0
}
}
#[cfg(test)]
mod tests {
use super::*;
use sodiumoxide::crypto::box_::curve25519xsalsa20poly1305::SecretKey;
#[test]
fn test_full_duplicate() {
let b = gen_bucket();
let p = Property {
lower: 0,
upper: 255,
};
let mut elem = Element::Leaf(b, p);
let center = gen_center();
for i in 0..40 {
elem.add(gen_node(&i.to_string()), ¢er);
}
assert_eq!(elem.len(), 40);
for i in 0..40 {
let _ = elem.add(gen_node(&i.to_string()), ¢er);
}
assert_eq!(elem.len(), 40);
}
#[test]
fn test_full_stress() {
let b = gen_bucket();
let p = Property {
lower: 0,
upper: 255,
};
let mut elem = Element::Leaf(b, p);
let center = gen_center();
for i in 0..1000 {
elem.add(gen_node(&i.to_string()), ¢er);
}
for i in 100..1100 {
let _ = elem.remove(&gen_node(&i.to_string()).address, ¢er);
}
for i in 0..1000 {
elem.add(gen_node(&i.to_string()), ¢er);
}
for i in 100..1100 {
let _ = elem.remove(&gen_node(&i.to_string()).address, ¢er);
}
let a = elem.len() <= elem.capacity();
assert_eq!(a, true);
}
#[test]
fn test_capacity_get() {
let b = gen_bucket();
let p = Property {
lower: 0,
upper: 255,
};
let mut elem = Element::Leaf(b, p);
let center = gen_center();
for i in 0..1000 {
elem.add(gen_node(&i.to_string()), ¢er);
}
let nodes = elem.get(¢er.public, ¢er, elem.len());
assert_eq!(nodes.len(), elem.len());
}
#[test]
fn test_property_in_range() {
let p = Property {
lower: 0,
upper: 255,
};
let node = gen_node_near();
let center = gen_center_near();
assert_eq!(p.in_range(&node.address, ¢er), true);
assert_eq!((node.address ^ center.public)[0], 0);
}
#[test]
fn test_property_split_root() {
let p = Property {
lower: 0,
upper: 255,
};
let (l, u) = p.split();
assert_eq!(l.lower, 0);
assert_eq!(l.upper, 127);
assert_eq!(u.lower, 128);
assert_eq!(u.upper, 255);
}
#[test]
fn test_property_split_lower() {
let p = Property {
lower: 0,
upper: 63,
};
let (l, u) = p.split();
assert_eq!(l.lower, 0);
assert_eq!(l.upper, 31);
assert_eq!(u.lower, 32);
assert_eq!(u.upper, 63);
}
#[test]
fn test_property_near() {
let p = Property {
lower: 0,
upper: 63,
};
let (l, u) = p.split();
assert_eq!(l.is_near(), true);
assert_eq!(u.is_near(), false);
}
#[test]
fn test_element_try_add() {
let bucket = Bucket::new(1);
let prop = Property {
lower: 0,
upper: 63,
};
let mut elem = Element::Leaf(bucket, prop);
let node = gen_node_near();
let center = gen_center_near();
elem.add(node, ¢er);
let node = gen_node_far();
let s = elem.try_add(node, ¢er);
assert_eq!(s.is_err(), true);
}
#[test]
fn test_element_split_root() {
let prop = Property {
lower: 0,
upper: 255,
};
let buck = gen_bucket();
let elem = Element::Leaf(buck, prop);
let center = gen_center();
let split = elem.split(¢er).unwrap();
match split {
Element::Split(s, p) => {
assert_eq!(p.upper, 255);
assert_eq!(s.len(), 3);
assert_eq!(s.near.as_ref().len(), 2);
}
Element::Leaf(_, _) => assert_eq!("invalid split", ""),
}
}
#[test]
fn test_element_split_far() {
let prop = Property {
lower: 128,
upper: 255,
};
let buck = gen_bucket();
let elem = Element::Leaf(buck, prop);
let center = gen_center();
let split = elem.split(¢er).is_none();
assert_eq!(split, true);
}
#[test]
fn test_element_add_to_leaf() {
let bucket = gen_bucket();
let prop = Property {
lower: 0,
upper: 255,
};
let mut elem = Element::Leaf(bucket, prop);
let node = gen_node("added");
let center = gen_center();
elem.add(node, ¢er);
assert_eq!(elem.len(), 4);
}
#[test]
fn test_element_split() {
let bucket = Bucket::new(1);
let prop = Property {
lower: 0,
upper: 255,
};
let mut elem = Element::Leaf(bucket, prop);
let center = gen_center_near();
let node = gen_node_near();
elem.add(node, ¢er);
let node = gen_node_far();
elem.add(node, ¢er);
assert_eq!(elem.len(), 2);
match elem {
Element::Split(s, _) => {
assert_eq!(s.len(), 2);
assert_eq!(s.near.len(), 1);
assert_eq!(s.far.len(), 1);
}
Element::Leaf(_, _) => assert_eq!("split failed", ""),
}
}
#[test]
fn test_element_split_near() {
let bucket = Bucket::new(1);
let prop = Property {
lower: 0,
upper: 255,
};
let mut elem = Element::Leaf(bucket, prop);
let center = gen_center_near();
let node = gen_node_near();
elem.add(node, ¢er);
let node = gen_node_near();
elem.add(node, ¢er);
assert_eq!(elem.len(), 1);
match elem {
Element::Split(s, _) => {
assert_eq!(s.len(), 1);
assert_eq!(s.near.len(), 1);
assert_eq!(s.far.len(), 0);
}
Element::Leaf(_, _) => assert_eq!("split failed", ""),
}
}
#[test]
fn test_element_find_top() {
let bucket = Bucket::new(20);
let prop = Property {
lower: 0,
upper: 255,
};
let mut elem = Element::Leaf(bucket, prop);
let center = gen_center_near();
let node = gen_node("searching");
let searching = node.address.clone();
elem.add(node, ¢er);
assert_eq!(elem.len(), 1);
let node = elem.find(&searching, ¢er).unwrap();
assert_eq!(node.address, searching);
}
#[test]
fn test_element_find_deep() {
let split = Split {
near: Box::new(Element::Split(
Split {
near: Box::new(Element::Leaf(
Bucket::new(20),
Property {
lower: 0,
upper: 63,
},
)),
far: Box::new(Element::Leaf(
Bucket::new(20),
Property {
lower: 64,
upper: 127,
},
)),
},
Property {
lower: 0,
upper: 127,
},
)),
far: Box::new(Element::Leaf(
Bucket::new(20),
Property {
lower: 128,
upper: 255,
},
)),
};
let props = Property {
lower: 0,
upper: 255,
};
let mut elem = Element::Split(split, props);
let center = gen_center_near();
let node = gen_node("searching");
let searching = node.address.clone();
elem.add(node, ¢er);
assert_eq!(elem.len(), 1);
let node = elem.find(&searching, ¢er).unwrap();
assert_eq!(node.address, searching);
}
#[test]
fn test_element_get_top() {
let bucket = Bucket::new(20);
let prop = Property {
lower: 0,
upper: 255,
};
let mut elem = Element::Leaf(bucket, prop);
let center = gen_center_near();
let node = gen_node("searching");
elem.add(node, ¢er);
let node = gen_node("random");
elem.add(node, ¢er);
let node = gen_node("string");
elem.add(node, ¢er);
let node = gen_node("actaeon");
elem.add(node, ¢er);
let node = gen_node("data");
elem.add(node, ¢er);
let target = gen_node("target").address;
let targets = elem.get(&target, ¢er, 5);
assert_eq!(targets.len(), 5);
}
#[test]
fn test_element_get_empty() {
let bucket = Bucket::new(20);
let prop = Property {
lower: 0,
upper: 255,
};
let elem = Element::Leaf(bucket, prop);
let center = gen_center_near();
let target = gen_node("target").address;
let targets = elem.get(&target, ¢er, 5);
assert_eq!(targets.len(), 0);
}
#[test]
fn test_element_get_deep() {
let split = Split {
near: Box::new(Element::Split(
Split {
near: Box::new(Element::Leaf(
Bucket::new(20),
Property {
lower: 0,
upper: 63,
},
)),
far: Box::new(Element::Leaf(
Bucket::new(20),
Property {
lower: 64,
upper: 127,
},
)),
},
Property {
lower: 0,
upper: 127,
},
)),
far: Box::new(Element::Leaf(
Bucket::new(20),
Property {
lower: 128,
upper: 255,
},
)),
};
let props = Property {
lower: 0,
upper: 255,
};
let mut elem = Element::Split(split, props);
let center = gen_center_near();
let node = gen_node("searching");
elem.add(node, ¢er);
let node = gen_node("random");
elem.add(node, ¢er);
let node = gen_node("string");
elem.add(node, ¢er);
let node = gen_node("actaeon");
elem.add(node, ¢er);
let node = gen_node("data");
elem.add(node, ¢er);
let node = gen_node("searching2");
elem.add(node, ¢er);
let node = gen_node("random2");
elem.add(node, ¢er);
let node = gen_node("string2");
elem.add(node, ¢er);
let node = gen_node("actaeon2");
elem.add(node, ¢er);
let node = gen_node("maybe use a loop for this?");
elem.add(node, ¢er);
let target = gen_node("target").address;
let targets = elem.get(&target, ¢er, 5);
assert_eq!(targets.len(), 5);
}
#[test]
fn test_element_remove_root() {
let bucket = Bucket::new(20);
let prop = Property {
lower: 0,
upper: 255,
};
let mut elem = Element::Leaf(bucket, prop);
let center = gen_center();
let node = gen_node("test");
elem.add(node, ¢er);
assert_eq!(elem.len(), 1);
let node = gen_node("test");
let _ = elem.remove(&node.address, ¢er);
assert_eq!(elem.len(), 0);
}
#[test]
fn test_element_remove_deep() {
let split = Split {
near: Box::new(Element::Split(
Split {
near: Box::new(Element::Leaf(
Bucket::new(20),
Property {
lower: 0,
upper: 63,
},
)),
far: Box::new(Element::Leaf(
Bucket::new(20),
Property {
lower: 64,
upper: 127,
},
)),
},
Property {
lower: 0,
upper: 127,
},
)),
far: Box::new(Element::Leaf(
Bucket::new(20),
Property {
lower: 128,
upper: 255,
},
)),
};
let props = Property {
lower: 0,
upper: 255,
};
let mut elem = Element::Split(split, props);
let center = gen_center_near();
let node = gen_node("searching");
elem.add(node, ¢er);
let node = gen_node("random");
elem.add(node, ¢er);
let node = gen_node("string");
elem.add(node, ¢er);
let node = gen_node("actaeon");
elem.add(node, ¢er);
let node = gen_node("data");
elem.add(node, ¢er);
let node = gen_node("searching2");
elem.add(node, ¢er);
let node = gen_node("random2");
elem.add(node, ¢er);
let node = gen_node("string2");
elem.add(node, ¢er);
let node = gen_node("actaeon2");
elem.add(node, ¢er);
let node = gen_node("maybe use a loop for this?");
elem.add(node, ¢er);
let target = gen_node("random");
assert_eq!(elem.len(), 10);
let _ = elem.remove(&target.address, ¢er);
assert_eq!(elem.len(), 9);
}
#[test]
fn test_element_remove_collaps() {
let split = Split {
near: Box::new(Element::Split(
Split {
near: Box::new(Element::Leaf(
Bucket::new(20),
Property {
lower: 0,
upper: 63,
},
)),
far: Box::new(Element::Leaf(
Bucket::new(20),
Property {
lower: 64,
upper: 127,
},
)),
},
Property {
lower: 0,
upper: 127,
},
)),
far: Box::new(Element::Leaf(
Bucket::new(20),
Property {
lower: 128,
upper: 255,
},
)),
};
let props = Property {
lower: 0,
upper: 255,
};
let mut elem = Element::Split(split, props);
let center = gen_center_near();
for i in 0..40 {
elem.add(gen_node(&i.to_string()), ¢er);
}
assert_eq!(elem.len(), 40);
for i in 0..40 {
let _ = elem.remove(&gen_node(&i.to_string()).address, ¢er);
}
assert_eq!(elem.len(), 0);
if let Element::Leaf(b, _) = elem {
assert_eq!(b.len(), 0);
}
}
#[test]
fn test_split_add_near_top() {
let mut split = gen_split();
let node = gen_node_near();
let center = gen_center_near();
split.add(node, ¢er);
assert_eq!(split.len(), 1);
assert_eq!(split.near.len(), 1);
assert_eq!(split.far.len(), 0);
}
#[test]
fn test_split_add_far_top() {
let mut split = gen_split();
let node = gen_node_far();
let center = gen_center_near();
let a = (node.address.clone() ^ center.public.clone())[0];
split.add(node, ¢er);
assert_eq!(split.len(), 1);
assert_eq!(a, 255);
assert_eq!(split.far.len(), 1);
}
#[test]
fn test_split_add_deep() {
let mut split = Split {
near: Box::new(Element::Split(
Split {
near: Box::new(Element::Leaf(
Bucket::new(20),
Property {
lower: 0,
upper: 63,
},
)),
far: Box::new(Element::Leaf(
Bucket::new(20),
Property {
lower: 64,
upper: 127,
},
)),
},
Property {
lower: 0,
upper: 127,
},
)),
far: Box::new(Element::Leaf(
Bucket::new(20),
Property {
lower: 128,
upper: 255,
},
)),
};
assert_eq!(split.len(), 0);
let center = gen_center_near();
let node = gen_node_near();
split.add(node, ¢er);
assert_eq!(split.len(), 1);
assert_eq!(split.near.as_ref().len(), 1);
assert_eq!(split.far.as_ref().len(), 0);
let node = gen_node_far();
split.add(node, ¢er);
assert_eq!(split.len(), 2);
assert_eq!(split.near.as_ref().len(), 1);
assert_eq!(split.far.as_ref().len(), 1);
}
#[test]
fn test_split_in_range() {
let split = gen_split();
let center = gen_center_near();
let node = gen_node_near();
assert_eq!(split.near.in_range(&node.address, ¢er), true);
}
#[test]
fn test_split_collaps_working() {
let mut split = gen_split();
let center = gen_center_near();
let node = gen_node("first");
split.add(node, ¢er);
let node = gen_node("second");
split.add(node, ¢er);
let node = gen_node_far();
split.add(node, ¢er);
let node = gen_node_near();
split.add(node, ¢er);
assert_eq!(split.len(), 4);
let e = split.collapse().unwrap();
assert_eq!(e.len(), 4);
}
#[test]
fn test_split_in_range_far() {
let split = gen_split();
let center = gen_center_near();
let node = gen_node_far();
assert_eq!(split.near.in_range(&node.address, ¢er), false);
}
#[test]
fn test_should_be_local_manual() {
let center = gen_center_near();
let address = gen_node_near().address;
let nodes = vec![
gen_node("first"),
gen_node("second"),
gen_node("third"),
gen_node("fourth"),
gen_node("fifth"),
];
let mut addrs: Vec<Address> = nodes.iter().map(|x| x.address.clone()).collect();
addrs.push(address.clone());
addrs.sort_by(|a, b| {
let left = (a.clone() ^ center.public.clone())[0];
let right = (b.clone() ^ center.public.clone())[0];
left.partial_cmp(&right).unwrap()
});
let index = addrs.iter().position(|e| e == ¢er.public);
let res = match index {
Some(i) => i <= 3,
None => false,
};
assert_eq!(res, true);
}
#[test]
fn test_safe_multi() {
let center = gen_center();
let safe = Safe::new(10, center);
let inner = safe.clone();
std::thread::spawn(move || {
let node = gen_node("first");
inner.add(node);
});
std::thread::sleep(std::time::Duration::from_millis(42));
assert_eq!(safe.len(), 1);
}
#[test]
fn test_safe_random() {
let center = gen_center();
let safe = Safe::new(100, center);
let inner = safe.clone();
std::thread::spawn(move || {
for i in 0..100 {
inner.add(gen_node(&i.to_string()))
}
});
std::thread::sleep(std::time::Duration::from_millis(42));
assert_eq!(safe.len(), 100);
}
fn gen_split() -> Split {
let near = Bucket::new(20);
let np = Property {
lower: 0,
upper: 127,
};
let near = Element::Leaf(near, np);
let far = Bucket::new(20);
let fp = Property {
lower: 128,
upper: 255,
};
let far = Element::Leaf(far, fp);
Split {
near: Box::new(near),
far: Box::new(far),
}
}
fn gen_bucket() -> Bucket {
let mut root = Bucket::new(20);
root.add(gen_node("first"));
root.add(gen_node("second"));
root.add(gen_node("another"));
root
}
fn gen_node(s: &str) -> Node {
Node::new(Address::generate(s), None)
}
fn gen_node_near() -> Node {
let addr = Address::from_bytes([0; 32]);
Node::new(addr, None)
}
fn gen_node_far() -> Node {
let addr = Address::from_bytes([255; 32]);
Node::new(addr, None)
}
fn gen_center() -> Center {
let mut b = [0; 32];
b[0] = 42;
let s = SecretKey::from_slice(&b).unwrap();
Center::new(s, String::from(""), 8080)
}
fn gen_center_near() -> Center {
let secret = [0; 32];
let secret = SecretKey::from_slice(&secret).unwrap();
let public = [0; 32];
let b = [0; 32];
let s = SecretKey::from_slice(&b).unwrap();
let base = Center::new(s, String::from(""), 8080);
Center {
secret,
public: Address::from_bytes(public),
..base
}
}
}