aboutsummaryrefslogtreecommitdiffstats
path: root/src/simtest
diff options
context:
space:
mode:
Diffstat (limited to 'src/simtest')
-rw-r--r--src/simtest/reach.rs44
1 files changed, 42 insertions, 2 deletions
diff --git a/src/simtest/reach.rs b/src/simtest/reach.rs
index b38db87..2c188cf 100644
--- a/src/simtest/reach.rs
+++ b/src/simtest/reach.rs
@@ -1,11 +1,12 @@
-//! Whom neighbours reach (`swarm::reach`): told in STATUSes, as measured.
+//! Whom neighbours reach (`swarm::reach`): told in STATUSes, as measured; and the
+//! writers' trees built on it (`swarm::tree`).
use std::time::Duration;
use super::Sim;
use crate::state::AppState;
use crate::swarm::bootstrap::Start;
-use crate::swarm::{reach, topology};
+use crate::swarm::{reach, topology, tree};
const SOON: Duration = Duration::from_secs(30);
@@ -50,3 +51,42 @@ async fn neighbours_tell_whom_they_reach() {
)
.await;
}
+
+/// The same three: in x's tree (`swarm::tree`), c can't take x as its parent (it
+/// doesn't reach it), so it takes b, which comes before it if c comes later by pair
+/// key; else c has no parent and gets x's changes from announcements. Either way x's
+/// only child is b, and nobody but b passes x's changes to c.
+#[tokio::test(flavor = "multi_thread", worker_threads = 4)]
+async fn writer_trees_go_around_links_down() {
+ let sim = Sim::with_identity(67);
+ let cut = crate::transport::sim::LinkParams {
+ loss: 1.0,
+ ..Default::default()
+ };
+ sim.net.set_link("x", "c", cut.clone());
+ sim.net.set_link("c", "x", cut);
+ let b = sim.start_on("b", &["sim"], &[], Start::Genesis);
+ let c = sim.start_on("c", &["sim"], &["b"], Start::Join);
+ let x = sim.start_on("x", &["sim"], &["b"], Start::Join);
+ sim.wait_ready(&[&b, &c, &x], SOON).await;
+ let (b, c, x) = (&b, &c, &x);
+ let writer = topology::pair_key(x.local_id());
+ let c_after_b = topology::pair_key(c.local_id()) > topology::pair_key(b.local_id());
+ sim.wait_until(
+ "x's tree: b under x, and c under b if c comes after it",
+ SOON,
+ move || async move {
+ let of_x = tree::children(x, writer).await;
+ let of_b = tree::children(b, writer).await;
+ heard(c, b, x).await
+ && of_x == [b.local_id().to_owned()]
+ && of_b
+ == if c_after_b {
+ vec![c.local_id().to_owned()]
+ } else {
+ Vec::new()
+ }
+ },
+ )
+ .await;
+}