From 5c96698de2c1d239985f3c0672b41f29a95ca13c Mon Sep 17 00:00:00 2001 From: tv Date: Tue, 3 Nov 2026 01:54:10 +0100 Subject: swarm: links by whom we reach --- src/simtest/links.rs | 48 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 48 insertions(+) (limited to 'src/simtest') diff --git a/src/simtest/links.rs b/src/simtest/links.rs index 44836bd..17c7ced 100644 --- a/src/simtest/links.rs +++ b/src/simtest/links.rs @@ -103,3 +103,51 @@ async fn links_are_relayed_to_members_out_of_reach() { .await; } } + +/// a, b and c all on `sim`, but nothing passes between a and c (as behind NAT): once a +/// judges c unreachable, it asks c's links through b, though it has c's address. +#[tokio::test(flavor = "multi_thread", worker_threads = 4)] +async fn links_are_relayed_to_members_that_dont_answer() { + let sim = Sim::with_identity(64); + let cut = crate::transport::sim::LinkParams { + loss: 1.0, + ..Default::default() + }; + sim.net.set_link("a", "c", cut.clone()); + sim.net.set_link("c", "a", cut); + let b = sim.start_on("b", &["sim"], &[], Start::Genesis); + let a = sim.start_on("a", &["sim"], &["b"], Start::Join); + let c = sim.start_on("c", &["sim"], &["b"], Start::Join); + sim.wait_ready(&[&a, &b, &c], SOON).await; + let (b_id, c_id) = (b.local_id().to_owned(), c.local_id().to_owned()); + { + let (a, c_id) = (&a, c_id.clone()); + sim.wait_until( + "a knows c, and that it doesn't answer", + SOON * 3, + move || { + let c_id = c_id.clone(); + async move { + let listed = members::members(&a.doc.read().await.doc).contains(&c_id); + listed && a.transport.can_reach(&c_id) && !topology::reaches(a, &c_id).await + } + }, + ) + .await; + } + links::ask_all( + &a, + vec![b_id.clone(), c_id.clone()], + Duration::from_secs(10), + ) + .await; + { + let (a, b_id, c_id) = (&a, b_id.clone(), c_id.clone()); + sim.wait_until("a has c's links, relayed by b", SOON, move || { + let (b_id, c_id) = (b_id.clone(), c_id.clone()); + async move { has_links(a, &c_id, &b_id) } + }) + .await; + } + assert!(!c.links.subscribers().contains(&a.local_id().to_owned())); +} -- cgit v1.3.1