aboutsummaryrefslogtreecommitdiffstats
path: root/src/simtest
diff options
context:
space:
mode:
Diffstat (limited to 'src/simtest')
-rw-r--r--src/simtest/links.rs48
1 files changed, 48 insertions, 0 deletions
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()));
+}