Move Network test helper from util crate into text crate

This way, `util` does not depend on `clock`.

Co-Authored-By: Nathan Sobo <nathan@zed.dev>
This commit is contained in:
Max Brunsfeld 2022-03-04 13:32:28 -08:00
parent 9b8c782609
commit 28bacabc4e
6 changed files with 75 additions and 74 deletions

View File

@ -11,8 +11,9 @@ use std::{
rc::Rc,
time::{Duration, Instant},
};
use text::network::Network;
use unindent::Unindent as _;
use util::{post_inc, test::Network};
use util::post_inc;
#[cfg(test)]
#[ctor::ctor]

View File

@ -0,0 +1,69 @@
use clock::ReplicaId;
pub struct Network<T: Clone, R: rand::Rng> {
inboxes: std::collections::BTreeMap<ReplicaId, Vec<Envelope<T>>>,
all_messages: Vec<T>,
rng: R,
}
#[derive(Clone)]
struct Envelope<T: Clone> {
message: T,
}
impl<T: Clone, R: rand::Rng> Network<T, R> {
pub fn new(rng: R) -> Self {
Network {
inboxes: Default::default(),
all_messages: Vec::new(),
rng,
}
}
pub fn add_peer(&mut self, id: ReplicaId) {
self.inboxes.insert(id, Vec::new());
}
pub fn replicate(&mut self, old_replica_id: ReplicaId, new_replica_id: ReplicaId) {
self.inboxes
.insert(new_replica_id, self.inboxes[&old_replica_id].clone());
}
pub fn is_idle(&self) -> bool {
self.inboxes.values().all(|i| i.is_empty())
}
pub fn broadcast(&mut self, sender: ReplicaId, messages: Vec<T>) {
for (replica, inbox) in self.inboxes.iter_mut() {
if *replica != sender {
for message in &messages {
// Insert one or more duplicates of this message, potentially *before* the previous
// message sent by this peer to simulate out-of-order delivery.
for _ in 0..self.rng.gen_range(1..4) {
let insertion_index = self.rng.gen_range(0..inbox.len() + 1);
inbox.insert(
insertion_index,
Envelope {
message: message.clone(),
},
);
}
}
}
}
self.all_messages.extend(messages);
}
pub fn has_unreceived(&self, receiver: ReplicaId) -> bool {
!self.inboxes[&receiver].is_empty()
}
pub fn receive(&mut self, receiver: ReplicaId) -> Vec<T> {
let inbox = self.inboxes.get_mut(&receiver).unwrap();
let count = self.rng.gen_range(0..inbox.len() + 1);
inbox
.drain(0..count)
.map(|envelope| envelope.message)
.collect()
}
}

View File

@ -1,4 +1,4 @@
use super::*;
use super::{network::Network, *};
use clock::ReplicaId;
use rand::prelude::*;
use std::{
@ -7,7 +7,6 @@ use std::{
iter::Iterator,
time::{Duration, Instant},
};
use util::test::Network;
#[cfg(test)]
#[ctor::ctor]

View File

@ -1,5 +1,7 @@
mod anchor;
pub mod locator;
#[cfg(any(test, feature = "test-support"))]
pub mod network;
pub mod operation_queue;
mod patch;
mod point;

View File

@ -7,10 +7,9 @@ edition = "2021"
doctest = false
[features]
test-support = ["clock", "rand", "serde_json", "tempdir"]
test-support = ["rand", "serde_json", "tempdir"]
[dependencies]
clock = { path = "../clock", optional = true }
anyhow = "1.0.38"
futures = "0.3"
log = "0.4"

View File

@ -1,75 +1,6 @@
use clock::ReplicaId;
use std::path::{Path, PathBuf};
use tempdir::TempDir;
#[derive(Clone)]
struct Envelope<T: Clone> {
message: T,
}
pub struct Network<T: Clone, R: rand::Rng> {
inboxes: std::collections::BTreeMap<ReplicaId, Vec<Envelope<T>>>,
all_messages: Vec<T>,
rng: R,
}
impl<T: Clone, R: rand::Rng> Network<T, R> {
pub fn new(rng: R) -> Self {
Network {
inboxes: Default::default(),
all_messages: Vec::new(),
rng,
}
}
pub fn add_peer(&mut self, id: ReplicaId) {
self.inboxes.insert(id, Vec::new());
}
pub fn replicate(&mut self, old_replica_id: ReplicaId, new_replica_id: ReplicaId) {
self.inboxes
.insert(new_replica_id, self.inboxes[&old_replica_id].clone());
}
pub fn is_idle(&self) -> bool {
self.inboxes.values().all(|i| i.is_empty())
}
pub fn broadcast(&mut self, sender: ReplicaId, messages: Vec<T>) {
for (replica, inbox) in self.inboxes.iter_mut() {
if *replica != sender {
for message in &messages {
// Insert one or more duplicates of this message, potentially *before* the previous
// message sent by this peer to simulate out-of-order delivery.
for _ in 0..self.rng.gen_range(1..4) {
let insertion_index = self.rng.gen_range(0..inbox.len() + 1);
inbox.insert(
insertion_index,
Envelope {
message: message.clone(),
},
);
}
}
}
}
self.all_messages.extend(messages);
}
pub fn has_unreceived(&self, receiver: ReplicaId) -> bool {
!self.inboxes[&receiver].is_empty()
}
pub fn receive(&mut self, receiver: ReplicaId) -> Vec<T> {
let inbox = self.inboxes.get_mut(&receiver).unwrap();
let count = self.rng.gen_range(0..inbox.len() + 1);
inbox
.drain(0..count)
.map(|envelope| envelope.message)
.collect()
}
}
pub fn temp_tree(tree: serde_json::Value) -> TempDir {
let dir = TempDir::new("").unwrap();
write_tree(dir.path(), tree);