Comment out tests for better IDE experience, add some comments

This commit is contained in:
folex 2020-03-16 16:54:53 +03:00
parent 96cd509c60
commit 65bb4f2b7d
2 changed files with 419 additions and 415 deletions

View File

@ -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(_,_) -> _)
} // }
} // }

View File

@ -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(_,_,_) -> _);
} // }
} // }