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)]
mod tests {
use super::*;
use libp2p_core::PeerId;
use quickcheck::*;
use rand::Rng;
type TestTable = KBucketsTable<KeyBytes, ()>;
impl Arbitrary for TestTable {
fn arbitrary<G: Gen>(g: &mut G) -> TestTable {
let local_key = Key::from(PeerId::random());
let timeout = Duration::from_secs(g.gen_range(1, 360));
let mut table = TestTable::new(local_key.clone().into(), timeout);
let mut num_total = g.gen_range(0, 100);
for (i, b) in &mut table.buckets.iter_mut().enumerate().rev() {
let ix = BucketIndex(i);
let num = g.gen_range(0, usize::min(K_VALUE.get(), num_total) + 1);
num_total -= num;
for _ in 0 .. num {
let distance = ix.rand_distance(g);
let key = local_key.for_distance(distance);
let node = Node { key: key.clone(), value: () };
let status = NodeStatus::arbitrary(g);
match b.insert(node, status) {
InsertResult::Inserted => {}
_ => panic!()
}
}
}
table
}
}
#[test]
fn rand_distance() {
fn prop(ix: u8) -> bool {
let d = BucketIndex(ix as usize).rand_distance(&mut rand::thread_rng());
let n = U256::from(<[u8; 32]>::from(d.0));
let b = U256::from(2);
let e = U256::from(ix);
let lower = b.pow(e);
let upper = b.pow(e + U256::from(1)) - U256::from(1);
lower <= n && n <= upper
}
quickcheck(prop as fn(_) -> _);
}
#[test]
fn entry_inserted() {
let local_key = Key::from(PeerId::random());
let other_id = Key::from(PeerId::random());
let mut table = KBucketsTable::<_, ()>::new(local_key, Duration::from_secs(5));
if let Entry::Absent(entry) = table.entry(&other_id) {
match entry.insert((), NodeStatus::Connected) {
InsertResult::Inserted => (),
_ => panic!()
}
} else {
panic!()
}
let res = table.closest_keys(&other_id).collect::<Vec<_>>();
assert_eq!(res.len(), 1);
assert_eq!(res[0], other_id);
}
#[test]
fn entry_self() {
let local_key = Key::from(PeerId::random());
let mut table = KBucketsTable::<_, ()>::new(local_key.clone(), Duration::from_secs(5));
match table.entry(&local_key) {
Entry::SelfEntry => (),
_ => panic!(),
}
}
#[test]
fn closest() {
let local_key = Key::from(PeerId::random());
let mut table = KBucketsTable::<_, ()>::new(local_key, Duration::from_secs(5));
let mut count = 0;
loop {
if count == 100 { break; }
let key = Key::from(PeerId::random());
if let Entry::Absent(e) = table.entry(&key) {
match e.insert((), NodeStatus::Connected) {
InsertResult::Inserted => count += 1,
_ => continue,
}
} else {
panic!("entry exists")
}
}
let mut expected_keys: Vec<_> = table.buckets
.iter()
.flat_map(|t| t.iter().map(|(n,_)| n.key.clone()))
.collect();
for _ in 0 .. 10 {
let target_key = Key::from(PeerId::random());
let keys = table.closest_keys(&target_key).collect::<Vec<_>>();
// 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));
assert_eq!(keys, expected_keys);
}
}
#[test]
fn applied_pending() {
let local_key = Key::from(PeerId::random());
let mut table = KBucketsTable::<_, ()>::new(local_key.clone(), Duration::from_millis(1));
let expected_applied;
let full_bucket_index;
loop {
let key = Key::from(PeerId::random());
if let Entry::Absent(e) = table.entry(&key) {
match e.insert((), NodeStatus::Disconnected) {
InsertResult::Full => {
if let Entry::Absent(e) = table.entry(&key) {
match e.insert((), NodeStatus::Connected) {
InsertResult::Pending { disconnected } => {
expected_applied = AppliedPending {
inserted: Node { key: key.clone(), value: () },
evicted: Some(Node { key: disconnected, value: () })
};
full_bucket_index = BucketIndex::new(&key.distance(&local_key));
break
},
_ => panic!()
}
} else {
panic!()
}
},
_ => continue,
}
} else {
panic!("entry exists")
}
}
// Expire the timeout for the pending entry on the full bucket.`
let full_bucket = &mut table.buckets[full_bucket_index.unwrap().get()];
let elapsed = Instant::now() - Duration::from_secs(1);
full_bucket.pending_mut().unwrap().set_ready_at(elapsed);
match table.entry(&expected_applied.inserted.key) {
Entry::Present(_, NodeStatus::Connected) => {}
x => panic!("Unexpected entry: {:?}", x)
}
match table.entry(&expected_applied.evicted.as_ref().unwrap().key) {
Entry::Absent(_) => {}
x => panic!("Unexpected entry: {:?}", x)
}
assert_eq!(Some(expected_applied), table.take_applied_pending());
assert_eq!(None, table.take_applied_pending());
}
#[test]
fn count_nodes_between() {
fn prop(mut table: TestTable, target: Key<PeerId>) -> bool {
let num_to_target = table.count_nodes_between(&target);
let distance = table.local_key.distance(&target);
let base2 = U256::from(2);
let mut iter = ClosestBucketsIter::new(distance);
iter.all(|i| {
// Flip the distance bit related to the bucket.
let d = Distance(distance.0 ^ (base2.pow(U256::from(i.get()))));
let k = table.local_key.for_distance(d);
if distance.0.bit(i.get()) {
// Bit flip `1` -> `0`, the key must be closer than `target`.
d < distance && table.count_nodes_between(&k) <= num_to_target
} else {
// Bit flip `0` -> `1`, the key must be farther than `target`.
d > distance && table.count_nodes_between(&k) >= num_to_target
}
})
}
QuickCheck::new().tests(10).quickcheck(prop as fn(_,_) -> _)
}
}
// mod tests {
// use super::*;
// use libp2p_core::PeerId;
// use quickcheck::*;
// use rand::Rng;
//
// type TestTable = KBucketsTable<KeyBytes, ()>;
//
// impl Arbitrary for TestTable {
// fn arbitrary<G: Gen>(g: &mut G) -> TestTable {
// let local_key = Key::from(PeerId::random());
// let timeout = Duration::from_secs(g.gen_range(1, 360));
// let mut table = TestTable::new(local_key.clone().into(), timeout);
// let mut num_total = g.gen_range(0, 100);
// for (i, b) in &mut table.buckets.iter_mut().enumerate().rev() {
// let ix = BucketIndex(i);
// let num = g.gen_range(0, usize::min(K_VALUE.get(), num_total) + 1);
// num_total -= num;
// for _ in 0 .. num {
// let distance = ix.rand_distance(g);
// let key = local_key.for_distance(distance);
// let node = Node { key: key.clone(), value: () };
// let status = NodeStatus::arbitrary(g);
// match b.insert(node, status) {
// InsertResult::Inserted => {}
// _ => panic!()
// }
// }
// }
// table
// }
// }
//
// #[test]
// fn rand_distance() {
// fn prop(ix: u8) -> bool {
// let d = BucketIndex(ix as usize).rand_distance(&mut rand::thread_rng());
// let n = U256::from(<[u8; 32]>::from(d.0));
// let b = U256::from(2);
// let e = U256::from(ix);
// let lower = b.pow(e);
// let upper = b.pow(e + U256::from(1)) - U256::from(1);
// lower <= n && n <= upper
// }
// quickcheck(prop as fn(_) -> _);
// }
//
// #[test]
// fn entry_inserted() {
// let local_key = Key::from(PeerId::random());
// let other_id = Key::from(PeerId::random());
//
// let mut table = KBucketsTable::<_, ()>::new(local_key, Duration::from_secs(5));
// if let Entry::Absent(entry) = table.entry(&other_id) {
// match entry.insert((), NodeStatus::Connected) {
// InsertResult::Inserted => (),
// _ => panic!()
// }
// } else {
// panic!()
// }
//
// let res = table.closest_keys(&other_id).collect::<Vec<_>>();
// assert_eq!(res.len(), 1);
// assert_eq!(res[0], other_id);
// }
//
// #[test]
// fn entry_self() {
// let local_key = Key::from(PeerId::random());
// let mut table = KBucketsTable::<_, ()>::new(local_key.clone(), Duration::from_secs(5));
// match table.entry(&local_key) {
// Entry::SelfEntry => (),
// _ => panic!(),
// }
// }
//
// #[test]
// fn closest() {
// let local_key = Key::from(PeerId::random());
// let mut table = KBucketsTable::<_, ()>::new(local_key, Duration::from_secs(5));
// let mut count = 0;
// loop {
// if count == 100 { break; }
// let key = Key::from(PeerId::random());
// if let Entry::Absent(e) = table.entry(&key) {
// match e.insert((), NodeStatus::Connected) {
// InsertResult::Inserted => count += 1,
// _ => continue,
// }
// } else {
// panic!("entry exists")
// }
// }
//
// let mut expected_keys: Vec<_> = table.buckets
// .iter()
// .flat_map(|t| t.iter().map(|(n,_)| n.key.clone()))
// .collect();
//
// for _ in 0 .. 10 {
// let target_key = Key::from(PeerId::random());
// let keys = table.closest_keys(&target_key).collect::<Vec<_>>();
// // 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));
// assert_eq!(keys, expected_keys);
// }
// }
//
// #[test]
// fn applied_pending() {
// let local_key = Key::from(PeerId::random());
// let mut table = KBucketsTable::<_, ()>::new(local_key.clone(), Duration::from_millis(1));
// let expected_applied;
// let full_bucket_index;
// loop {
// let key = Key::from(PeerId::random());
// if let Entry::Absent(e) = table.entry(&key) {
// match e.insert((), NodeStatus::Disconnected) {
// InsertResult::Full => {
// if let Entry::Absent(e) = table.entry(&key) {
// match e.insert((), NodeStatus::Connected) {
// InsertResult::Pending { disconnected } => {
// expected_applied = AppliedPending {
// inserted: Node { key: key.clone(), value: () },
// evicted: Some(Node { key: disconnected, value: () })
// };
// full_bucket_index = BucketIndex::new(&key.distance(&local_key));
// break
// },
// _ => panic!()
// }
// } else {
// panic!()
// }
// },
// _ => continue,
// }
// } else {
// panic!("entry exists")
// }
// }
//
// // Expire the timeout for the pending entry on the full bucket.`
// let full_bucket = &mut table.buckets[full_bucket_index.unwrap().get()];
// let elapsed = Instant::now() - Duration::from_secs(1);
// full_bucket.pending_mut().unwrap().set_ready_at(elapsed);
//
// match table.entry(&expected_applied.inserted.key) {
// Entry::Present(_, NodeStatus::Connected) => {}
// x => panic!("Unexpected entry: {:?}", x)
// }
//
// match table.entry(&expected_applied.evicted.as_ref().unwrap().key) {
// Entry::Absent(_) => {}
// x => panic!("Unexpected entry: {:?}", x)
// }
//
// assert_eq!(Some(expected_applied), table.take_applied_pending());
// assert_eq!(None, table.take_applied_pending());
// }
//
// #[test]
// fn count_nodes_between() {
// fn prop(mut table: TestTable, target: Key<PeerId>) -> bool {
// let num_to_target = table.count_nodes_between(&target);
// let distance = table.local_key.distance(&target);
// let base2 = U256::from(2);
// let mut iter = ClosestBucketsIter::new(distance);
// iter.all(|i| {
// // Flip the distance bit related to the bucket.
// let d = Distance(distance.0 ^ (base2.pow(U256::from(i.get()))));
// let k = table.local_key.for_distance(d);
// if distance.0.bit(i.get()) {
// // Bit flip `1` -> `0`, the key must be closer than `target`.
// d < distance && table.count_nodes_between(&k) <= num_to_target
// } else {
// // Bit flip `0` -> `1`, the key must be farther than `target`.
// d > distance && table.count_nodes_between(&k) >= num_to_target
// }
// })
// }
//
// QuickCheck::new().tests(10).quickcheck(prop as fn(_,_) -> _)
// }
// }

View File

@ -324,6 +324,7 @@ where
match status {
NodeStatus::Connected => {
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() {
return InsertResult::Full
} else {
@ -338,6 +339,7 @@ where
}
}
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.nodes.push(node);
InsertResult::Inserted
@ -346,10 +348,12 @@ where
if self.nodes.is_full() {
return InsertResult::Full
}
// There are some connected nodes
if let Some(ref mut p) = self.first_connected_pos {
self.nodes.insert(*p, node);
// Lower the mark of connected nodes
*p += 1;
} else {
} else { // There are no connected nodes
self.nodes.push(node);
}
InsertResult::Inserted
@ -401,231 +405,231 @@ where
}
#[cfg(test)]
mod tests {
use libp2p_core::PeerId;
use rand::Rng;
use std::collections::VecDeque;
use super::*;
use quickcheck::*;
impl Arbitrary for 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 mut bucket = KBucket::<Key<PeerId>, ()>::new(timeout);
let num_nodes = g.gen_range(1, K_VALUE.get() + 1);
for _ in 0 .. num_nodes {
let key = Key::new(PeerId::random());
let node = Node { key: key.clone(), value: () };
let status = NodeStatus::arbitrary(g);
match bucket.insert(node, status) {
InsertResult::Inserted => {}
_ => panic!()
}
}
bucket
}
}
impl Arbitrary for NodeStatus {
fn arbitrary<G: Gen>(g: &mut G) -> NodeStatus {
if g.gen() {
NodeStatus::Connected
} else {
NodeStatus::Disconnected
}
}
}
impl Arbitrary for Position {
fn arbitrary<G: Gen>(g: &mut G) -> Position {
Position(g.gen_range(0, K_VALUE.get()))
}
}
// Fill a bucket with random nodes with the given status.
fn fill_bucket(bucket: &mut KBucket<Key<PeerId>, ()>, status: NodeStatus) {
let num_entries_start = bucket.num_entries();
for i in 0 .. K_VALUE.get() - num_entries_start {
let key = Key::new(PeerId::random());
let node = Node { key, value: () };
assert_eq!(InsertResult::Inserted, bucket.insert(node, status));
assert_eq!(bucket.num_entries(), num_entries_start + i + 1);
}
}
#[test]
fn ordering() {
fn prop(status: Vec<NodeStatus>) -> bool {
let mut bucket = KBucket::<Key<PeerId>, ()>::new(Duration::from_secs(1));
// The expected lists of connected and disconnected nodes.
let mut connected = VecDeque::new();
let mut disconnected = VecDeque::new();
// Fill the bucket, thereby populating the expected lists in insertion order.
for status in status {
let key = Key::new(PeerId::random());
let node = Node { key: key.clone(), value: () };
let full = bucket.num_entries() == K_VALUE.get();
match bucket.insert(node, status) {
InsertResult::Inserted => {
let vec = match status {
NodeStatus::Connected => &mut connected,
NodeStatus::Disconnected => &mut disconnected
};
if full {
vec.pop_front();
}
vec.push_back((status, key.clone()));
}
_ => {}
}
}
// Get all nodes from the bucket, together with their status.
let mut nodes = bucket.iter()
.map(|(n, s)| (s, n.key.clone()))
.collect::<Vec<_>>();
// Split the list of nodes at the first connected node.
let first_connected_pos = nodes.iter().position(|(s,_)| *s == NodeStatus::Connected);
assert_eq!(bucket.first_connected_pos, first_connected_pos);
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
// in insertion order. Similarly, all remaining nodes must be connected
// and in insertion order.
nodes == Vec::from(disconnected)
&&
tail == Vec::from(connected)
}
quickcheck(prop as fn(_) -> _);
}
#[test]
fn full_bucket() {
let mut bucket = KBucket::<Key<PeerId>, ()>::new(Duration::from_secs(1));
// Fill the bucket with disconnected nodes.
fill_bucket(&mut bucket, NodeStatus::Disconnected);
// Trying to insert another disconnected node fails.
let key = Key::new(PeerId::random());
let node = Node { key, value: () };
match bucket.insert(node, NodeStatus::Disconnected) {
InsertResult::Full => {},
x => panic!("{:?}", x)
}
// One-by-one fill the bucket with connected nodes, replacing the disconnected ones.
for i in 0 .. K_VALUE.get() {
let (first, first_status) = bucket.iter().next().unwrap();
let first_disconnected = first.clone();
assert_eq!(first_status, NodeStatus::Disconnected);
// Add a connected node, which is expected to be pending, scheduled to
// replace the first (i.e. least-recently connected) node.
let key = Key::new(PeerId::random());
let node = Node { key: key.clone(), value: () };
match bucket.insert(node.clone(), NodeStatus::Connected) {
InsertResult::Pending { disconnected } =>
assert_eq!(disconnected, first_disconnected.key),
x => panic!("{:?}", x)
}
// Trying to insert another connected node fails.
match bucket.insert(node.clone(), NodeStatus::Connected) {
InsertResult::Full => {},
x => panic!("{:?}", x)
}
assert!(bucket.pending().is_some());
// Apply the pending node.
let pending = bucket.pending_mut().expect("No pending node.");
pending.set_ready_at(Instant::now() - Duration::from_secs(1));
let result = bucket.apply_pending();
assert_eq!(result, Some(AppliedPending {
inserted: node.clone(),
evicted: Some(first_disconnected)
}));
assert_eq!(Some((&node, NodeStatus::Connected)), bucket.iter().last());
assert!(bucket.pending().is_none());
assert_eq!(Some(K_VALUE.get() - (i + 1)), bucket.first_connected_pos);
}
assert!(bucket.pending().is_none());
assert_eq!(K_VALUE.get(), bucket.num_entries());
// Trying to insert another connected node fails.
let key = Key::new(PeerId::random());
let node = Node { key, value: () };
match bucket.insert(node, NodeStatus::Connected) {
InsertResult::Full => {},
x => panic!("{:?}", x)
}
}
#[test]
fn full_bucket_discard_pending() {
let mut bucket = KBucket::<Key<PeerId>, ()>::new(Duration::from_secs(1));
fill_bucket(&mut bucket, NodeStatus::Disconnected);
let (first, _) = bucket.iter().next().unwrap();
let first_disconnected = first.clone();
// Add a connected pending node.
let key = Key::new(PeerId::random());
let node = Node { key: key.clone(), value: () };
if let InsertResult::Pending { disconnected } = bucket.insert(node, NodeStatus::Connected) {
assert_eq!(&disconnected, &first_disconnected.key);
} else {
panic!()
}
assert!(bucket.pending().is_some());
// Update the status of the first disconnected node to be connected.
bucket.update(&first_disconnected.key, NodeStatus::Connected);
// The pending node has been discarded.
assert!(bucket.pending().is_none());
assert!(bucket.iter().all(|(n,_)| &n.key != &key));
// The initially disconnected node is now the most-recently connected.
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!(1, bucket.num_connected());
assert_eq!(K_VALUE.get() - 1, bucket.num_disconnected());
}
#[test]
fn bucket_update() {
fn prop(mut bucket: KBucket<Key<PeerId>, ()>, pos: Position, status: NodeStatus) -> bool {
let num_nodes = bucket.num_entries();
// Capture position and key of the random node to update.
let pos = pos.0 % num_nodes;
let key = bucket.nodes[pos].key.clone();
// 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<_>>();
// Update the node in the bucket.
bucket.update(&key, status);
// Check that the bucket now contains the node with the new status,
// preserving the status and relative order of all other nodes.
let expected_pos = match status {
NodeStatus::Connected => num_nodes - 1,
NodeStatus::Disconnected => bucket.first_connected_pos.unwrap_or(num_nodes) - 1
};
expected.remove(pos);
expected.insert(expected_pos, (key.clone(), status));
let actual = bucket.iter().map(|(n,s)| (n.key.clone(), s)).collect::<Vec<_>>();
expected == actual
}
quickcheck(prop as fn(_,_,_) -> _);
}
}
// mod tests {
// use libp2p_core::PeerId;
// use rand::Rng;
// use std::collections::VecDeque;
// use super::*;
// use quickcheck::*;
//
// impl Arbitrary for 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 mut bucket = KBucket::<Key<PeerId>, ()>::new(timeout);
// let num_nodes = g.gen_range(1, K_VALUE.get() + 1);
// for _ in 0 .. num_nodes {
// let key = Key::new(PeerId::random());
// let node = Node { key: key.clone(), value: () };
// let status = NodeStatus::arbitrary(g);
// match bucket.insert(node, status) {
// InsertResult::Inserted => {}
// _ => panic!()
// }
// }
// bucket
// }
// }
//
// impl Arbitrary for NodeStatus {
// fn arbitrary<G: Gen>(g: &mut G) -> NodeStatus {
// if g.gen() {
// NodeStatus::Connected
// } else {
// NodeStatus::Disconnected
// }
// }
// }
//
// impl Arbitrary for Position {
// fn arbitrary<G: Gen>(g: &mut G) -> Position {
// Position(g.gen_range(0, K_VALUE.get()))
// }
// }
//
// // Fill a bucket with random nodes with the given status.
// fn fill_bucket(bucket: &mut KBucket<Key<PeerId>, ()>, status: NodeStatus) {
// let num_entries_start = bucket.num_entries();
// for i in 0 .. K_VALUE.get() - num_entries_start {
// let key = Key::new(PeerId::random());
// let node = Node { key, value: () };
// assert_eq!(InsertResult::Inserted, bucket.insert(node, status));
// assert_eq!(bucket.num_entries(), num_entries_start + i + 1);
// }
// }
//
// #[test]
// fn ordering() {
// fn prop(status: Vec<NodeStatus>) -> bool {
// let mut bucket = KBucket::<Key<PeerId>, ()>::new(Duration::from_secs(1));
//
// // The expected lists of connected and disconnected nodes.
// let mut connected = VecDeque::new();
// let mut disconnected = VecDeque::new();
//
// // Fill the bucket, thereby populating the expected lists in insertion order.
// for status in status {
// let key = Key::new(PeerId::random());
// let node = Node { key: key.clone(), value: () };
// let full = bucket.num_entries() == K_VALUE.get();
// match bucket.insert(node, status) {
// InsertResult::Inserted => {
// let vec = match status {
// NodeStatus::Connected => &mut connected,
// NodeStatus::Disconnected => &mut disconnected
// };
// if full {
// vec.pop_front();
// }
// vec.push_back((status, key.clone()));
// }
// _ => {}
// }
// }
//
// // Get all nodes from the bucket, together with their status.
// let mut nodes = bucket.iter()
// .map(|(n, s)| (s, n.key.clone()))
// .collect::<Vec<_>>();
//
// // Split the list of nodes at the first connected node.
// let first_connected_pos = nodes.iter().position(|(s,_)| *s == NodeStatus::Connected);
// assert_eq!(bucket.first_connected_pos, first_connected_pos);
// 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
// // in insertion order. Similarly, all remaining nodes must be connected
// // and in insertion order.
// nodes == Vec::from(disconnected)
// &&
// tail == Vec::from(connected)
// }
//
// quickcheck(prop as fn(_) -> _);
// }
//
// #[test]
// fn full_bucket() {
// let mut bucket = KBucket::<Key<PeerId>, ()>::new(Duration::from_secs(1));
//
// // Fill the bucket with disconnected nodes.
// fill_bucket(&mut bucket, NodeStatus::Disconnected);
//
// // Trying to insert another disconnected node fails.
// let key = Key::new(PeerId::random());
// let node = Node { key, value: () };
// match bucket.insert(node, NodeStatus::Disconnected) {
// InsertResult::Full => {},
// x => panic!("{:?}", x)
// }
//
// // One-by-one fill the bucket with connected nodes, replacing the disconnected ones.
// for i in 0 .. K_VALUE.get() {
// let (first, first_status) = bucket.iter().next().unwrap();
// let first_disconnected = first.clone();
// assert_eq!(first_status, NodeStatus::Disconnected);
//
// // Add a connected node, which is expected to be pending, scheduled to
// // replace the first (i.e. least-recently connected) node.
// let key = Key::new(PeerId::random());
// let node = Node { key: key.clone(), value: () };
// match bucket.insert(node.clone(), NodeStatus::Connected) {
// InsertResult::Pending { disconnected } =>
// assert_eq!(disconnected, first_disconnected.key),
// x => panic!("{:?}", x)
// }
//
// // Trying to insert another connected node fails.
// match bucket.insert(node.clone(), NodeStatus::Connected) {
// InsertResult::Full => {},
// x => panic!("{:?}", x)
// }
//
// assert!(bucket.pending().is_some());
//
// // Apply the pending node.
// let pending = bucket.pending_mut().expect("No pending node.");
// pending.set_ready_at(Instant::now() - Duration::from_secs(1));
// let result = bucket.apply_pending();
// assert_eq!(result, Some(AppliedPending {
// inserted: node.clone(),
// evicted: Some(first_disconnected)
// }));
// assert_eq!(Some((&node, NodeStatus::Connected)), bucket.iter().last());
// assert!(bucket.pending().is_none());
// assert_eq!(Some(K_VALUE.get() - (i + 1)), bucket.first_connected_pos);
// }
//
// assert!(bucket.pending().is_none());
// assert_eq!(K_VALUE.get(), bucket.num_entries());
//
// // Trying to insert another connected node fails.
// let key = Key::new(PeerId::random());
// let node = Node { key, value: () };
// match bucket.insert(node, NodeStatus::Connected) {
// InsertResult::Full => {},
// x => panic!("{:?}", x)
// }
// }
//
// #[test]
// fn full_bucket_discard_pending() {
// let mut bucket = KBucket::<Key<PeerId>, ()>::new(Duration::from_secs(1));
// fill_bucket(&mut bucket, NodeStatus::Disconnected);
// let (first, _) = bucket.iter().next().unwrap();
// let first_disconnected = first.clone();
//
// // Add a connected pending node.
// let key = Key::new(PeerId::random());
// let node = Node { key: key.clone(), value: () };
// if let InsertResult::Pending { disconnected } = bucket.insert(node, NodeStatus::Connected) {
// assert_eq!(&disconnected, &first_disconnected.key);
// } else {
// panic!()
// }
// assert!(bucket.pending().is_some());
//
// // Update the status of the first disconnected node to be connected.
// bucket.update(&first_disconnected.key, NodeStatus::Connected);
//
// // The pending node has been discarded.
// assert!(bucket.pending().is_none());
// assert!(bucket.iter().all(|(n,_)| &n.key != &key));
//
// // The initially disconnected node is now the most-recently connected.
// 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!(1, bucket.num_connected());
// assert_eq!(K_VALUE.get() - 1, bucket.num_disconnected());
// }
//
//
// #[test]
// fn bucket_update() {
// fn prop(mut bucket: KBucket<Key<PeerId>, ()>, pos: Position, status: NodeStatus) -> bool {
// let num_nodes = bucket.num_entries();
//
// // Capture position and key of the random node to update.
// let pos = pos.0 % num_nodes;
// let key = bucket.nodes[pos].key.clone();
//
// // 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<_>>();
//
// // Update the node in the bucket.
// bucket.update(&key, status);
//
// // Check that the bucket now contains the node with the new status,
// // preserving the status and relative order of all other nodes.
// let expected_pos = match status {
// NodeStatus::Connected => num_nodes - 1,
// NodeStatus::Disconnected => bucket.first_connected_pos.unwrap_or(num_nodes) - 1
// };
// expected.remove(pos);
// expected.insert(expected_pos, (key.clone(), status));
// let actual = bucket.iter().map(|(n,s)| (n.key.clone(), s)).collect::<Vec<_>>();
// expected == actual
// }
//
// quickcheck(prop as fn(_,_,_) -> _);
// }
// }