diff options
Diffstat (limited to 'src/simtest/reach.rs')
| -rw-r--r-- | src/simtest/reach.rs | 52 |
1 files changed, 52 insertions, 0 deletions
diff --git a/src/simtest/reach.rs b/src/simtest/reach.rs new file mode 100644 index 0000000..b38db87 --- /dev/null +++ b/src/simtest/reach.rs @@ -0,0 +1,52 @@ +//! Whom neighbours reach (`swarm::reach`): told in STATUSes, as measured. + +use std::time::Duration; + +use super::Sim; +use crate::state::AppState; +use crate::swarm::bootstrap::Start; +use crate::swarm::{reach, topology}; + +const SOON: Duration = Duration::from_secs(30); + +/// Whether `node` reaches `member`, as `node` measured and told it. +fn reaches(node: &AppState, member: &AppState) -> bool { + reach::published(node).contains(&topology::pair_key(member.local_id())) +} + +/// Whether `node` heard from `neighbour` that it reaches `member`. +async fn heard(node: &AppState, neighbour: &AppState, member: &AppState) -> bool { + let Some(peer_state) = node.get_peer_state(neighbour.local_id()).await else { + return false; + }; + let said = peer_state.lock().await.reaches.clone(); + reach::of(node, said.as_ref()) + .is_some_and(|keys| keys.contains(&topology::pair_key(member.local_id()))) +} + +/// x, b and c on one net, all members of one full mesh, but nothing passes between x +/// and c: b reaches both and says so; c learns from b that b reaches x, which c itself +/// doesn't. +#[tokio::test(flavor = "multi_thread", worker_threads = 4)] +async fn neighbours_tell_whom_they_reach() { + let sim = Sim::with_identity(66); + 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); + sim.wait_until( + "c heard from b that b reaches x, and c doesn't reach x", + SOON, + move || async move { + reaches(b, x) && reaches(b, c) && !reaches(c, x) && heard(c, b, x).await + }, + ) + .await; +} |
