mirror of
https://github.com/fluencelabs/rust-libp2p
synced 2025-05-19 06:01:19 +00:00
Comment out tests for better IDE experience, add some comments
This commit is contained in:
parent
96cd509c60
commit
65bb4f2b7d
@ -475,189 +475,189 @@ where
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
// mod tests {
|
||||||
use super::*;
|
// use super::*;
|
||||||
use libp2p_core::PeerId;
|
// use libp2p_core::PeerId;
|
||||||
use quickcheck::*;
|
// use quickcheck::*;
|
||||||
use rand::Rng;
|
// use rand::Rng;
|
||||||
|
//
|
||||||
type TestTable = KBucketsTable<KeyBytes, ()>;
|
// type TestTable = KBucketsTable<KeyBytes, ()>;
|
||||||
|
//
|
||||||
impl Arbitrary for TestTable {
|
// impl Arbitrary for TestTable {
|
||||||
fn arbitrary<G: Gen>(g: &mut G) -> TestTable {
|
// fn arbitrary<G: Gen>(g: &mut G) -> TestTable {
|
||||||
let local_key = Key::from(PeerId::random());
|
// let local_key = Key::from(PeerId::random());
|
||||||
let timeout = Duration::from_secs(g.gen_range(1, 360));
|
// let timeout = Duration::from_secs(g.gen_range(1, 360));
|
||||||
let mut table = TestTable::new(local_key.clone().into(), timeout);
|
// let mut table = TestTable::new(local_key.clone().into(), timeout);
|
||||||
let mut num_total = g.gen_range(0, 100);
|
// let mut num_total = g.gen_range(0, 100);
|
||||||
for (i, b) in &mut table.buckets.iter_mut().enumerate().rev() {
|
// for (i, b) in &mut table.buckets.iter_mut().enumerate().rev() {
|
||||||
let ix = BucketIndex(i);
|
// let ix = BucketIndex(i);
|
||||||
let num = g.gen_range(0, usize::min(K_VALUE.get(), num_total) + 1);
|
// let num = g.gen_range(0, usize::min(K_VALUE.get(), num_total) + 1);
|
||||||
num_total -= num;
|
// num_total -= num;
|
||||||
for _ in 0 .. num {
|
// for _ in 0 .. num {
|
||||||
let distance = ix.rand_distance(g);
|
// let distance = ix.rand_distance(g);
|
||||||
let key = local_key.for_distance(distance);
|
// let key = local_key.for_distance(distance);
|
||||||
let node = Node { key: key.clone(), value: () };
|
// let node = Node { key: key.clone(), value: () };
|
||||||
let status = NodeStatus::arbitrary(g);
|
// let status = NodeStatus::arbitrary(g);
|
||||||
match b.insert(node, status) {
|
// match b.insert(node, status) {
|
||||||
InsertResult::Inserted => {}
|
// InsertResult::Inserted => {}
|
||||||
_ => panic!()
|
// _ => panic!()
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
table
|
// table
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
#[test]
|
// #[test]
|
||||||
fn rand_distance() {
|
// fn rand_distance() {
|
||||||
fn prop(ix: u8) -> bool {
|
// fn prop(ix: u8) -> bool {
|
||||||
let d = BucketIndex(ix as usize).rand_distance(&mut rand::thread_rng());
|
// let d = BucketIndex(ix as usize).rand_distance(&mut rand::thread_rng());
|
||||||
let n = U256::from(<[u8; 32]>::from(d.0));
|
// let n = U256::from(<[u8; 32]>::from(d.0));
|
||||||
let b = U256::from(2);
|
// let b = U256::from(2);
|
||||||
let e = U256::from(ix);
|
// let e = U256::from(ix);
|
||||||
let lower = b.pow(e);
|
// let lower = b.pow(e);
|
||||||
let upper = b.pow(e + U256::from(1)) - U256::from(1);
|
// let upper = b.pow(e + U256::from(1)) - U256::from(1);
|
||||||
lower <= n && n <= upper
|
// lower <= n && n <= upper
|
||||||
}
|
// }
|
||||||
quickcheck(prop as fn(_) -> _);
|
// quickcheck(prop as fn(_) -> _);
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
#[test]
|
// #[test]
|
||||||
fn entry_inserted() {
|
// fn entry_inserted() {
|
||||||
let local_key = Key::from(PeerId::random());
|
// let local_key = Key::from(PeerId::random());
|
||||||
let other_id = Key::from(PeerId::random());
|
// let other_id = Key::from(PeerId::random());
|
||||||
|
//
|
||||||
let mut table = KBucketsTable::<_, ()>::new(local_key, Duration::from_secs(5));
|
// let mut table = KBucketsTable::<_, ()>::new(local_key, Duration::from_secs(5));
|
||||||
if let Entry::Absent(entry) = table.entry(&other_id) {
|
// if let Entry::Absent(entry) = table.entry(&other_id) {
|
||||||
match entry.insert((), NodeStatus::Connected) {
|
// match entry.insert((), NodeStatus::Connected) {
|
||||||
InsertResult::Inserted => (),
|
// InsertResult::Inserted => (),
|
||||||
_ => panic!()
|
// _ => panic!()
|
||||||
}
|
// }
|
||||||
} else {
|
// } else {
|
||||||
panic!()
|
// panic!()
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
let res = table.closest_keys(&other_id).collect::<Vec<_>>();
|
// let res = table.closest_keys(&other_id).collect::<Vec<_>>();
|
||||||
assert_eq!(res.len(), 1);
|
// assert_eq!(res.len(), 1);
|
||||||
assert_eq!(res[0], other_id);
|
// assert_eq!(res[0], other_id);
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
#[test]
|
// #[test]
|
||||||
fn entry_self() {
|
// fn entry_self() {
|
||||||
let local_key = Key::from(PeerId::random());
|
// let local_key = Key::from(PeerId::random());
|
||||||
let mut table = KBucketsTable::<_, ()>::new(local_key.clone(), Duration::from_secs(5));
|
// let mut table = KBucketsTable::<_, ()>::new(local_key.clone(), Duration::from_secs(5));
|
||||||
match table.entry(&local_key) {
|
// match table.entry(&local_key) {
|
||||||
Entry::SelfEntry => (),
|
// Entry::SelfEntry => (),
|
||||||
_ => panic!(),
|
// _ => panic!(),
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
#[test]
|
// #[test]
|
||||||
fn closest() {
|
// fn closest() {
|
||||||
let local_key = Key::from(PeerId::random());
|
// let local_key = Key::from(PeerId::random());
|
||||||
let mut table = KBucketsTable::<_, ()>::new(local_key, Duration::from_secs(5));
|
// let mut table = KBucketsTable::<_, ()>::new(local_key, Duration::from_secs(5));
|
||||||
let mut count = 0;
|
// let mut count = 0;
|
||||||
loop {
|
// loop {
|
||||||
if count == 100 { break; }
|
// if count == 100 { break; }
|
||||||
let key = Key::from(PeerId::random());
|
// let key = Key::from(PeerId::random());
|
||||||
if let Entry::Absent(e) = table.entry(&key) {
|
// if let Entry::Absent(e) = table.entry(&key) {
|
||||||
match e.insert((), NodeStatus::Connected) {
|
// match e.insert((), NodeStatus::Connected) {
|
||||||
InsertResult::Inserted => count += 1,
|
// InsertResult::Inserted => count += 1,
|
||||||
_ => continue,
|
// _ => continue,
|
||||||
}
|
// }
|
||||||
} else {
|
// } else {
|
||||||
panic!("entry exists")
|
// panic!("entry exists")
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
let mut expected_keys: Vec<_> = table.buckets
|
// let mut expected_keys: Vec<_> = table.buckets
|
||||||
.iter()
|
// .iter()
|
||||||
.flat_map(|t| t.iter().map(|(n,_)| n.key.clone()))
|
// .flat_map(|t| t.iter().map(|(n,_)| n.key.clone()))
|
||||||
.collect();
|
// .collect();
|
||||||
|
//
|
||||||
for _ in 0 .. 10 {
|
// for _ in 0 .. 10 {
|
||||||
let target_key = Key::from(PeerId::random());
|
// let target_key = Key::from(PeerId::random());
|
||||||
let keys = table.closest_keys(&target_key).collect::<Vec<_>>();
|
// let keys = table.closest_keys(&target_key).collect::<Vec<_>>();
|
||||||
// The list of keys is expected to match the result of a full-table scan.
|
// // The list of keys is expected to match the result of a full-table scan.
|
||||||
expected_keys.sort_by_key(|k| k.distance(&target_key));
|
// expected_keys.sort_by_key(|k| k.distance(&target_key));
|
||||||
assert_eq!(keys, expected_keys);
|
// assert_eq!(keys, expected_keys);
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
#[test]
|
// #[test]
|
||||||
fn applied_pending() {
|
// fn applied_pending() {
|
||||||
let local_key = Key::from(PeerId::random());
|
// let local_key = Key::from(PeerId::random());
|
||||||
let mut table = KBucketsTable::<_, ()>::new(local_key.clone(), Duration::from_millis(1));
|
// let mut table = KBucketsTable::<_, ()>::new(local_key.clone(), Duration::from_millis(1));
|
||||||
let expected_applied;
|
// let expected_applied;
|
||||||
let full_bucket_index;
|
// let full_bucket_index;
|
||||||
loop {
|
// loop {
|
||||||
let key = Key::from(PeerId::random());
|
// let key = Key::from(PeerId::random());
|
||||||
if let Entry::Absent(e) = table.entry(&key) {
|
// if let Entry::Absent(e) = table.entry(&key) {
|
||||||
match e.insert((), NodeStatus::Disconnected) {
|
// match e.insert((), NodeStatus::Disconnected) {
|
||||||
InsertResult::Full => {
|
// InsertResult::Full => {
|
||||||
if let Entry::Absent(e) = table.entry(&key) {
|
// if let Entry::Absent(e) = table.entry(&key) {
|
||||||
match e.insert((), NodeStatus::Connected) {
|
// match e.insert((), NodeStatus::Connected) {
|
||||||
InsertResult::Pending { disconnected } => {
|
// InsertResult::Pending { disconnected } => {
|
||||||
expected_applied = AppliedPending {
|
// expected_applied = AppliedPending {
|
||||||
inserted: Node { key: key.clone(), value: () },
|
// inserted: Node { key: key.clone(), value: () },
|
||||||
evicted: Some(Node { key: disconnected, value: () })
|
// evicted: Some(Node { key: disconnected, value: () })
|
||||||
};
|
// };
|
||||||
full_bucket_index = BucketIndex::new(&key.distance(&local_key));
|
// full_bucket_index = BucketIndex::new(&key.distance(&local_key));
|
||||||
break
|
// break
|
||||||
},
|
// },
|
||||||
_ => panic!()
|
// _ => panic!()
|
||||||
}
|
// }
|
||||||
} else {
|
// } else {
|
||||||
panic!()
|
// panic!()
|
||||||
}
|
// }
|
||||||
},
|
// },
|
||||||
_ => continue,
|
// _ => continue,
|
||||||
}
|
// }
|
||||||
} else {
|
// } else {
|
||||||
panic!("entry exists")
|
// panic!("entry exists")
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
// Expire the timeout for the pending entry on the full bucket.`
|
// // Expire the timeout for the pending entry on the full bucket.`
|
||||||
let full_bucket = &mut table.buckets[full_bucket_index.unwrap().get()];
|
// let full_bucket = &mut table.buckets[full_bucket_index.unwrap().get()];
|
||||||
let elapsed = Instant::now() - Duration::from_secs(1);
|
// let elapsed = Instant::now() - Duration::from_secs(1);
|
||||||
full_bucket.pending_mut().unwrap().set_ready_at(elapsed);
|
// full_bucket.pending_mut().unwrap().set_ready_at(elapsed);
|
||||||
|
//
|
||||||
match table.entry(&expected_applied.inserted.key) {
|
// match table.entry(&expected_applied.inserted.key) {
|
||||||
Entry::Present(_, NodeStatus::Connected) => {}
|
// Entry::Present(_, NodeStatus::Connected) => {}
|
||||||
x => panic!("Unexpected entry: {:?}", x)
|
// x => panic!("Unexpected entry: {:?}", x)
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
match table.entry(&expected_applied.evicted.as_ref().unwrap().key) {
|
// match table.entry(&expected_applied.evicted.as_ref().unwrap().key) {
|
||||||
Entry::Absent(_) => {}
|
// Entry::Absent(_) => {}
|
||||||
x => panic!("Unexpected entry: {:?}", x)
|
// x => panic!("Unexpected entry: {:?}", x)
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
assert_eq!(Some(expected_applied), table.take_applied_pending());
|
// assert_eq!(Some(expected_applied), table.take_applied_pending());
|
||||||
assert_eq!(None, table.take_applied_pending());
|
// assert_eq!(None, table.take_applied_pending());
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
#[test]
|
// #[test]
|
||||||
fn count_nodes_between() {
|
// fn count_nodes_between() {
|
||||||
fn prop(mut table: TestTable, target: Key<PeerId>) -> bool {
|
// fn prop(mut table: TestTable, target: Key<PeerId>) -> bool {
|
||||||
let num_to_target = table.count_nodes_between(&target);
|
// let num_to_target = table.count_nodes_between(&target);
|
||||||
let distance = table.local_key.distance(&target);
|
// let distance = table.local_key.distance(&target);
|
||||||
let base2 = U256::from(2);
|
// let base2 = U256::from(2);
|
||||||
let mut iter = ClosestBucketsIter::new(distance);
|
// let mut iter = ClosestBucketsIter::new(distance);
|
||||||
iter.all(|i| {
|
// iter.all(|i| {
|
||||||
// Flip the distance bit related to the bucket.
|
// // Flip the distance bit related to the bucket.
|
||||||
let d = Distance(distance.0 ^ (base2.pow(U256::from(i.get()))));
|
// let d = Distance(distance.0 ^ (base2.pow(U256::from(i.get()))));
|
||||||
let k = table.local_key.for_distance(d);
|
// let k = table.local_key.for_distance(d);
|
||||||
if distance.0.bit(i.get()) {
|
// if distance.0.bit(i.get()) {
|
||||||
// Bit flip `1` -> `0`, the key must be closer than `target`.
|
// // Bit flip `1` -> `0`, the key must be closer than `target`.
|
||||||
d < distance && table.count_nodes_between(&k) <= num_to_target
|
// d < distance && table.count_nodes_between(&k) <= num_to_target
|
||||||
} else {
|
// } else {
|
||||||
// Bit flip `0` -> `1`, the key must be farther than `target`.
|
// // Bit flip `0` -> `1`, the key must be farther than `target`.
|
||||||
d > distance && table.count_nodes_between(&k) >= num_to_target
|
// d > distance && table.count_nodes_between(&k) >= num_to_target
|
||||||
}
|
// }
|
||||||
})
|
// })
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
QuickCheck::new().tests(10).quickcheck(prop as fn(_,_) -> _)
|
// QuickCheck::new().tests(10).quickcheck(prop as fn(_,_) -> _)
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
@ -324,6 +324,7 @@ where
|
|||||||
match status {
|
match status {
|
||||||
NodeStatus::Connected => {
|
NodeStatus::Connected => {
|
||||||
if self.nodes.is_full() {
|
if self.nodes.is_full() {
|
||||||
|
// All nodes are connected OR there is already a pending node
|
||||||
if self.first_connected_pos == Some(0) || self.pending.is_some() {
|
if self.first_connected_pos == Some(0) || self.pending.is_some() {
|
||||||
return InsertResult::Full
|
return InsertResult::Full
|
||||||
} else {
|
} else {
|
||||||
@ -338,6 +339,7 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
let pos = self.nodes.len();
|
let pos = self.nodes.len();
|
||||||
|
// If there were no previously connected nodes – set mark to the last one
|
||||||
self.first_connected_pos = self.first_connected_pos.or(Some(pos));
|
self.first_connected_pos = self.first_connected_pos.or(Some(pos));
|
||||||
self.nodes.push(node);
|
self.nodes.push(node);
|
||||||
InsertResult::Inserted
|
InsertResult::Inserted
|
||||||
@ -346,10 +348,12 @@ where
|
|||||||
if self.nodes.is_full() {
|
if self.nodes.is_full() {
|
||||||
return InsertResult::Full
|
return InsertResult::Full
|
||||||
}
|
}
|
||||||
|
// There are some connected nodes
|
||||||
if let Some(ref mut p) = self.first_connected_pos {
|
if let Some(ref mut p) = self.first_connected_pos {
|
||||||
self.nodes.insert(*p, node);
|
self.nodes.insert(*p, node);
|
||||||
|
// Lower the mark of connected nodes
|
||||||
*p += 1;
|
*p += 1;
|
||||||
} else {
|
} else { // There are no connected nodes
|
||||||
self.nodes.push(node);
|
self.nodes.push(node);
|
||||||
}
|
}
|
||||||
InsertResult::Inserted
|
InsertResult::Inserted
|
||||||
@ -401,231 +405,231 @@ where
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
// mod tests {
|
||||||
use libp2p_core::PeerId;
|
// use libp2p_core::PeerId;
|
||||||
use rand::Rng;
|
// use rand::Rng;
|
||||||
use std::collections::VecDeque;
|
// use std::collections::VecDeque;
|
||||||
use super::*;
|
// use super::*;
|
||||||
use quickcheck::*;
|
// use quickcheck::*;
|
||||||
|
//
|
||||||
impl Arbitrary for KBucket<Key<PeerId>, ()> {
|
// impl Arbitrary for KBucket<Key<PeerId>, ()> {
|
||||||
fn arbitrary<G: Gen>(g: &mut G) -> KBucket<Key<PeerId>, ()> {
|
// fn arbitrary<G: Gen>(g: &mut G) -> KBucket<Key<PeerId>, ()> {
|
||||||
let timeout = Duration::from_secs(g.gen_range(1, g.size() as u64));
|
// let timeout = Duration::from_secs(g.gen_range(1, g.size() as u64));
|
||||||
let mut bucket = KBucket::<Key<PeerId>, ()>::new(timeout);
|
// let mut bucket = KBucket::<Key<PeerId>, ()>::new(timeout);
|
||||||
let num_nodes = g.gen_range(1, K_VALUE.get() + 1);
|
// let num_nodes = g.gen_range(1, K_VALUE.get() + 1);
|
||||||
for _ in 0 .. num_nodes {
|
// for _ in 0 .. num_nodes {
|
||||||
let key = Key::new(PeerId::random());
|
// let key = Key::new(PeerId::random());
|
||||||
let node = Node { key: key.clone(), value: () };
|
// let node = Node { key: key.clone(), value: () };
|
||||||
let status = NodeStatus::arbitrary(g);
|
// let status = NodeStatus::arbitrary(g);
|
||||||
match bucket.insert(node, status) {
|
// match bucket.insert(node, status) {
|
||||||
InsertResult::Inserted => {}
|
// InsertResult::Inserted => {}
|
||||||
_ => panic!()
|
// _ => panic!()
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
bucket
|
// bucket
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
impl Arbitrary for NodeStatus {
|
// impl Arbitrary for NodeStatus {
|
||||||
fn arbitrary<G: Gen>(g: &mut G) -> NodeStatus {
|
// fn arbitrary<G: Gen>(g: &mut G) -> NodeStatus {
|
||||||
if g.gen() {
|
// if g.gen() {
|
||||||
NodeStatus::Connected
|
// NodeStatus::Connected
|
||||||
} else {
|
// } else {
|
||||||
NodeStatus::Disconnected
|
// NodeStatus::Disconnected
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
impl Arbitrary for Position {
|
// impl Arbitrary for Position {
|
||||||
fn arbitrary<G: Gen>(g: &mut G) -> Position {
|
// fn arbitrary<G: Gen>(g: &mut G) -> Position {
|
||||||
Position(g.gen_range(0, K_VALUE.get()))
|
// Position(g.gen_range(0, K_VALUE.get()))
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
// Fill a bucket with random nodes with the given status.
|
// // Fill a bucket with random nodes with the given status.
|
||||||
fn fill_bucket(bucket: &mut KBucket<Key<PeerId>, ()>, status: NodeStatus) {
|
// fn fill_bucket(bucket: &mut KBucket<Key<PeerId>, ()>, status: NodeStatus) {
|
||||||
let num_entries_start = bucket.num_entries();
|
// let num_entries_start = bucket.num_entries();
|
||||||
for i in 0 .. K_VALUE.get() - num_entries_start {
|
// for i in 0 .. K_VALUE.get() - num_entries_start {
|
||||||
let key = Key::new(PeerId::random());
|
// let key = Key::new(PeerId::random());
|
||||||
let node = Node { key, value: () };
|
// let node = Node { key, value: () };
|
||||||
assert_eq!(InsertResult::Inserted, bucket.insert(node, status));
|
// assert_eq!(InsertResult::Inserted, bucket.insert(node, status));
|
||||||
assert_eq!(bucket.num_entries(), num_entries_start + i + 1);
|
// assert_eq!(bucket.num_entries(), num_entries_start + i + 1);
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
#[test]
|
// #[test]
|
||||||
fn ordering() {
|
// fn ordering() {
|
||||||
fn prop(status: Vec<NodeStatus>) -> bool {
|
// fn prop(status: Vec<NodeStatus>) -> bool {
|
||||||
let mut bucket = KBucket::<Key<PeerId>, ()>::new(Duration::from_secs(1));
|
// let mut bucket = KBucket::<Key<PeerId>, ()>::new(Duration::from_secs(1));
|
||||||
|
//
|
||||||
// The expected lists of connected and disconnected nodes.
|
// // The expected lists of connected and disconnected nodes.
|
||||||
let mut connected = VecDeque::new();
|
// let mut connected = VecDeque::new();
|
||||||
let mut disconnected = VecDeque::new();
|
// let mut disconnected = VecDeque::new();
|
||||||
|
//
|
||||||
// Fill the bucket, thereby populating the expected lists in insertion order.
|
// // Fill the bucket, thereby populating the expected lists in insertion order.
|
||||||
for status in status {
|
// for status in status {
|
||||||
let key = Key::new(PeerId::random());
|
// let key = Key::new(PeerId::random());
|
||||||
let node = Node { key: key.clone(), value: () };
|
// let node = Node { key: key.clone(), value: () };
|
||||||
let full = bucket.num_entries() == K_VALUE.get();
|
// let full = bucket.num_entries() == K_VALUE.get();
|
||||||
match bucket.insert(node, status) {
|
// match bucket.insert(node, status) {
|
||||||
InsertResult::Inserted => {
|
// InsertResult::Inserted => {
|
||||||
let vec = match status {
|
// let vec = match status {
|
||||||
NodeStatus::Connected => &mut connected,
|
// NodeStatus::Connected => &mut connected,
|
||||||
NodeStatus::Disconnected => &mut disconnected
|
// NodeStatus::Disconnected => &mut disconnected
|
||||||
};
|
// };
|
||||||
if full {
|
// if full {
|
||||||
vec.pop_front();
|
// vec.pop_front();
|
||||||
}
|
// }
|
||||||
vec.push_back((status, key.clone()));
|
// vec.push_back((status, key.clone()));
|
||||||
}
|
// }
|
||||||
_ => {}
|
// _ => {}
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
// Get all nodes from the bucket, together with their status.
|
// // Get all nodes from the bucket, together with their status.
|
||||||
let mut nodes = bucket.iter()
|
// let mut nodes = bucket.iter()
|
||||||
.map(|(n, s)| (s, n.key.clone()))
|
// .map(|(n, s)| (s, n.key.clone()))
|
||||||
.collect::<Vec<_>>();
|
// .collect::<Vec<_>>();
|
||||||
|
//
|
||||||
// Split the list of nodes at the first connected node.
|
// // Split the list of nodes at the first connected node.
|
||||||
let first_connected_pos = nodes.iter().position(|(s,_)| *s == NodeStatus::Connected);
|
// let first_connected_pos = nodes.iter().position(|(s,_)| *s == NodeStatus::Connected);
|
||||||
assert_eq!(bucket.first_connected_pos, first_connected_pos);
|
// assert_eq!(bucket.first_connected_pos, first_connected_pos);
|
||||||
let tail = first_connected_pos.map_or(Vec::new(), |p| nodes.split_off(p));
|
// let tail = first_connected_pos.map_or(Vec::new(), |p| nodes.split_off(p));
|
||||||
|
//
|
||||||
// All nodes before the first connected node must be disconnected and
|
// // All nodes before the first connected node must be disconnected and
|
||||||
// in insertion order. Similarly, all remaining nodes must be connected
|
// // in insertion order. Similarly, all remaining nodes must be connected
|
||||||
// and in insertion order.
|
// // and in insertion order.
|
||||||
nodes == Vec::from(disconnected)
|
// nodes == Vec::from(disconnected)
|
||||||
&&
|
// &&
|
||||||
tail == Vec::from(connected)
|
// tail == Vec::from(connected)
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
quickcheck(prop as fn(_) -> _);
|
// quickcheck(prop as fn(_) -> _);
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
#[test]
|
// #[test]
|
||||||
fn full_bucket() {
|
// fn full_bucket() {
|
||||||
let mut bucket = KBucket::<Key<PeerId>, ()>::new(Duration::from_secs(1));
|
// let mut bucket = KBucket::<Key<PeerId>, ()>::new(Duration::from_secs(1));
|
||||||
|
//
|
||||||
// Fill the bucket with disconnected nodes.
|
// // Fill the bucket with disconnected nodes.
|
||||||
fill_bucket(&mut bucket, NodeStatus::Disconnected);
|
// fill_bucket(&mut bucket, NodeStatus::Disconnected);
|
||||||
|
//
|
||||||
// Trying to insert another disconnected node fails.
|
// // Trying to insert another disconnected node fails.
|
||||||
let key = Key::new(PeerId::random());
|
// let key = Key::new(PeerId::random());
|
||||||
let node = Node { key, value: () };
|
// let node = Node { key, value: () };
|
||||||
match bucket.insert(node, NodeStatus::Disconnected) {
|
// match bucket.insert(node, NodeStatus::Disconnected) {
|
||||||
InsertResult::Full => {},
|
// InsertResult::Full => {},
|
||||||
x => panic!("{:?}", x)
|
// x => panic!("{:?}", x)
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
// One-by-one fill the bucket with connected nodes, replacing the disconnected ones.
|
// // One-by-one fill the bucket with connected nodes, replacing the disconnected ones.
|
||||||
for i in 0 .. K_VALUE.get() {
|
// for i in 0 .. K_VALUE.get() {
|
||||||
let (first, first_status) = bucket.iter().next().unwrap();
|
// let (first, first_status) = bucket.iter().next().unwrap();
|
||||||
let first_disconnected = first.clone();
|
// let first_disconnected = first.clone();
|
||||||
assert_eq!(first_status, NodeStatus::Disconnected);
|
// assert_eq!(first_status, NodeStatus::Disconnected);
|
||||||
|
//
|
||||||
// Add a connected node, which is expected to be pending, scheduled to
|
// // Add a connected node, which is expected to be pending, scheduled to
|
||||||
// replace the first (i.e. least-recently connected) node.
|
// // replace the first (i.e. least-recently connected) node.
|
||||||
let key = Key::new(PeerId::random());
|
// let key = Key::new(PeerId::random());
|
||||||
let node = Node { key: key.clone(), value: () };
|
// let node = Node { key: key.clone(), value: () };
|
||||||
match bucket.insert(node.clone(), NodeStatus::Connected) {
|
// match bucket.insert(node.clone(), NodeStatus::Connected) {
|
||||||
InsertResult::Pending { disconnected } =>
|
// InsertResult::Pending { disconnected } =>
|
||||||
assert_eq!(disconnected, first_disconnected.key),
|
// assert_eq!(disconnected, first_disconnected.key),
|
||||||
x => panic!("{:?}", x)
|
// x => panic!("{:?}", x)
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
// Trying to insert another connected node fails.
|
// // Trying to insert another connected node fails.
|
||||||
match bucket.insert(node.clone(), NodeStatus::Connected) {
|
// match bucket.insert(node.clone(), NodeStatus::Connected) {
|
||||||
InsertResult::Full => {},
|
// InsertResult::Full => {},
|
||||||
x => panic!("{:?}", x)
|
// x => panic!("{:?}", x)
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
assert!(bucket.pending().is_some());
|
// assert!(bucket.pending().is_some());
|
||||||
|
//
|
||||||
// Apply the pending node.
|
// // Apply the pending node.
|
||||||
let pending = bucket.pending_mut().expect("No pending node.");
|
// let pending = bucket.pending_mut().expect("No pending node.");
|
||||||
pending.set_ready_at(Instant::now() - Duration::from_secs(1));
|
// pending.set_ready_at(Instant::now() - Duration::from_secs(1));
|
||||||
let result = bucket.apply_pending();
|
// let result = bucket.apply_pending();
|
||||||
assert_eq!(result, Some(AppliedPending {
|
// assert_eq!(result, Some(AppliedPending {
|
||||||
inserted: node.clone(),
|
// inserted: node.clone(),
|
||||||
evicted: Some(first_disconnected)
|
// evicted: Some(first_disconnected)
|
||||||
}));
|
// }));
|
||||||
assert_eq!(Some((&node, NodeStatus::Connected)), bucket.iter().last());
|
// assert_eq!(Some((&node, NodeStatus::Connected)), bucket.iter().last());
|
||||||
assert!(bucket.pending().is_none());
|
// assert!(bucket.pending().is_none());
|
||||||
assert_eq!(Some(K_VALUE.get() - (i + 1)), bucket.first_connected_pos);
|
// assert_eq!(Some(K_VALUE.get() - (i + 1)), bucket.first_connected_pos);
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
assert!(bucket.pending().is_none());
|
// assert!(bucket.pending().is_none());
|
||||||
assert_eq!(K_VALUE.get(), bucket.num_entries());
|
// assert_eq!(K_VALUE.get(), bucket.num_entries());
|
||||||
|
//
|
||||||
// Trying to insert another connected node fails.
|
// // Trying to insert another connected node fails.
|
||||||
let key = Key::new(PeerId::random());
|
// let key = Key::new(PeerId::random());
|
||||||
let node = Node { key, value: () };
|
// let node = Node { key, value: () };
|
||||||
match bucket.insert(node, NodeStatus::Connected) {
|
// match bucket.insert(node, NodeStatus::Connected) {
|
||||||
InsertResult::Full => {},
|
// InsertResult::Full => {},
|
||||||
x => panic!("{:?}", x)
|
// x => panic!("{:?}", x)
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
#[test]
|
// #[test]
|
||||||
fn full_bucket_discard_pending() {
|
// fn full_bucket_discard_pending() {
|
||||||
let mut bucket = KBucket::<Key<PeerId>, ()>::new(Duration::from_secs(1));
|
// let mut bucket = KBucket::<Key<PeerId>, ()>::new(Duration::from_secs(1));
|
||||||
fill_bucket(&mut bucket, NodeStatus::Disconnected);
|
// fill_bucket(&mut bucket, NodeStatus::Disconnected);
|
||||||
let (first, _) = bucket.iter().next().unwrap();
|
// let (first, _) = bucket.iter().next().unwrap();
|
||||||
let first_disconnected = first.clone();
|
// let first_disconnected = first.clone();
|
||||||
|
//
|
||||||
// Add a connected pending node.
|
// // Add a connected pending node.
|
||||||
let key = Key::new(PeerId::random());
|
// let key = Key::new(PeerId::random());
|
||||||
let node = Node { key: key.clone(), value: () };
|
// let node = Node { key: key.clone(), value: () };
|
||||||
if let InsertResult::Pending { disconnected } = bucket.insert(node, NodeStatus::Connected) {
|
// if let InsertResult::Pending { disconnected } = bucket.insert(node, NodeStatus::Connected) {
|
||||||
assert_eq!(&disconnected, &first_disconnected.key);
|
// assert_eq!(&disconnected, &first_disconnected.key);
|
||||||
} else {
|
// } else {
|
||||||
panic!()
|
// panic!()
|
||||||
}
|
// }
|
||||||
assert!(bucket.pending().is_some());
|
// assert!(bucket.pending().is_some());
|
||||||
|
//
|
||||||
// Update the status of the first disconnected node to be connected.
|
// // Update the status of the first disconnected node to be connected.
|
||||||
bucket.update(&first_disconnected.key, NodeStatus::Connected);
|
// bucket.update(&first_disconnected.key, NodeStatus::Connected);
|
||||||
|
//
|
||||||
// The pending node has been discarded.
|
// // The pending node has been discarded.
|
||||||
assert!(bucket.pending().is_none());
|
// assert!(bucket.pending().is_none());
|
||||||
assert!(bucket.iter().all(|(n,_)| &n.key != &key));
|
// assert!(bucket.iter().all(|(n,_)| &n.key != &key));
|
||||||
|
//
|
||||||
// The initially disconnected node is now the most-recently connected.
|
// // The initially disconnected node is now the most-recently connected.
|
||||||
assert_eq!(Some((&first_disconnected, NodeStatus::Connected)), bucket.iter().last());
|
// assert_eq!(Some((&first_disconnected, NodeStatus::Connected)), bucket.iter().last());
|
||||||
assert_eq!(bucket.position(&first_disconnected.key).map(|p| p.0), bucket.first_connected_pos);
|
// assert_eq!(bucket.position(&first_disconnected.key).map(|p| p.0), bucket.first_connected_pos);
|
||||||
assert_eq!(1, bucket.num_connected());
|
// assert_eq!(1, bucket.num_connected());
|
||||||
assert_eq!(K_VALUE.get() - 1, bucket.num_disconnected());
|
// assert_eq!(K_VALUE.get() - 1, bucket.num_disconnected());
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
|
//
|
||||||
#[test]
|
// #[test]
|
||||||
fn bucket_update() {
|
// fn bucket_update() {
|
||||||
fn prop(mut bucket: KBucket<Key<PeerId>, ()>, pos: Position, status: NodeStatus) -> bool {
|
// fn prop(mut bucket: KBucket<Key<PeerId>, ()>, pos: Position, status: NodeStatus) -> bool {
|
||||||
let num_nodes = bucket.num_entries();
|
// let num_nodes = bucket.num_entries();
|
||||||
|
//
|
||||||
// Capture position and key of the random node to update.
|
// // Capture position and key of the random node to update.
|
||||||
let pos = pos.0 % num_nodes;
|
// let pos = pos.0 % num_nodes;
|
||||||
let key = bucket.nodes[pos].key.clone();
|
// let key = bucket.nodes[pos].key.clone();
|
||||||
|
//
|
||||||
// Record the (ordered) list of status of all nodes in the bucket.
|
// // Record the (ordered) list of status of all nodes in the bucket.
|
||||||
let mut expected = bucket.iter().map(|(n,s)| (n.key.clone(), s)).collect::<Vec<_>>();
|
// let mut expected = bucket.iter().map(|(n,s)| (n.key.clone(), s)).collect::<Vec<_>>();
|
||||||
|
//
|
||||||
// Update the node in the bucket.
|
// // Update the node in the bucket.
|
||||||
bucket.update(&key, status);
|
// bucket.update(&key, status);
|
||||||
|
//
|
||||||
// Check that the bucket now contains the node with the new status,
|
// // Check that the bucket now contains the node with the new status,
|
||||||
// preserving the status and relative order of all other nodes.
|
// // preserving the status and relative order of all other nodes.
|
||||||
let expected_pos = match status {
|
// let expected_pos = match status {
|
||||||
NodeStatus::Connected => num_nodes - 1,
|
// NodeStatus::Connected => num_nodes - 1,
|
||||||
NodeStatus::Disconnected => bucket.first_connected_pos.unwrap_or(num_nodes) - 1
|
// NodeStatus::Disconnected => bucket.first_connected_pos.unwrap_or(num_nodes) - 1
|
||||||
};
|
// };
|
||||||
expected.remove(pos);
|
// expected.remove(pos);
|
||||||
expected.insert(expected_pos, (key.clone(), status));
|
// expected.insert(expected_pos, (key.clone(), status));
|
||||||
let actual = bucket.iter().map(|(n,s)| (n.key.clone(), s)).collect::<Vec<_>>();
|
// let actual = bucket.iter().map(|(n,s)| (n.key.clone(), s)).collect::<Vec<_>>();
|
||||||
expected == actual
|
// expected == actual
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
quickcheck(prop as fn(_,_,_) -> _);
|
// quickcheck(prop as fn(_,_,_) -> _);
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
Loading…
x
Reference in New Issue
Block a user