aboutsummaryrefslogtreecommitdiffstats
path: root/src/simtest
diff options
context:
space:
mode:
authortv <tv@krebsco.de>2026-11-03 01:19:05 +0100
committertv <tv@krebsco.de>2026-11-03 01:19:05 +0100
commitc12ce1a67e387474d17419bb252211bf04b2e443 (patch)
tree61157a186b9a7c884859e53e8cdea3155e92ded5 /src/simtest
parent72d05e54de4a051148578d8445ad4527550052ff (diff)
always announce new heads
Diffstat (limited to 'src/simtest')
-rw-r--r--src/simtest/relay.rs53
1 files changed, 53 insertions, 0 deletions
diff --git a/src/simtest/relay.rs b/src/simtest/relay.rs
index 9b016b8..dadeed3 100644
--- a/src/simtest/relay.rs
+++ b/src/simtest/relay.rs
@@ -64,3 +64,56 @@ async fn changes_reach_members_the_writer_cant_reach_at_once() {
.await;
}
}
+
+/// One transport, a full mesh by the member list, but the writer x reaches b alone (as
+/// one behind NAT may): what x writes reaches c through b, at once, though the member
+/// list makes c x's neighbour too.
+#[tokio::test(flavor = "multi_thread", worker_threads = 4)]
+async fn changes_reach_members_the_writer_fails_to_reach_at_once() {
+ let keepalive = Duration::from_secs(5);
+ let slow = move |config: &mut crate::node::NodeConfig| {
+ config.timing = Timing::new(keepalive, SYNC_REPLY_TIMEOUT, DELIVERY_LIMIT);
+ };
+ let sim = Sim::with_identity(63);
+ // Nothing between x and c, either way.
+ 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_with("b", &["sim"], &[], Start::Genesis, slow);
+ let c = sim.start_on_with("c", &["sim"], &["b"], Start::Join, slow);
+ let x = sim.start_on_with("x", &["sim"], &["b"], Start::Join, slow);
+ sim.wait_ready(&[&b, &c, &x], SOON).await;
+ let (c_id, x_id) = (c.local_id().to_owned(), x.local_id().to_owned());
+ {
+ let (b, c_id, x_id) = (&b, c_id.clone(), x_id.clone());
+ sim.wait_until(
+ "b knows its neighbours, a full mesh, x and c among them",
+ SOON,
+ move || {
+ let (c_id, x_id) = (c_id.clone(), x_id.clone());
+ async move {
+ topology::view_known(b)
+ && topology::is_full_mesh(b)
+ && topology::is_neighbour(b, &c_id)
+ && topology::is_neighbour(b, &x_id)
+ }
+ },
+ )
+ .await;
+ }
+ sim.wait_converged(&[&b, &c, &x], SOON).await;
+
+ write(&x, "y", json!(1)).await;
+ {
+ let c = &c;
+ sim.wait_until(
+ "c has x's write within a second",
+ Duration::from_secs(1),
+ move || async move { read(c, "y").await == Some(json!(1)) },
+ )
+ .await;
+ }
+}