summaryrefslogtreecommitdiffstats
path: root/src/simtest
diff options
context:
space:
mode:
Diffstat (limited to 'src/simtest')
-rw-r--r--src/simtest/identity.rs46
-rw-r--r--src/simtest/mod.rs1
2 files changed, 46 insertions, 1 deletions
diff --git a/src/simtest/identity.rs b/src/simtest/identity.rs
index a33783f..9859d0e 100644
--- a/src/simtest/identity.rs
+++ b/src/simtest/identity.rs
@@ -2,6 +2,7 @@
//! through addresses (seeds, HELLO_REPLYs, the member list), and believed only once a
//! node proved itself at an address.
+use std::sync::Arc;
use std::time::Duration;
use serde_json::json;
@@ -12,7 +13,8 @@ use crate::state::AppState;
use crate::swarm::bootstrap::Start;
use crate::swarm::members;
use crate::transport::identity::{WHO_LABEL, signed};
-use crate::transport::{HeadsSummary, IdentityProof, Keepalive, ParsedMessage};
+use crate::transport::sim::SimNet;
+use crate::transport::{HeadsSummary, IdentityProof, Keepalive, ParsedMessage, Transport};
const SOON: Duration = Duration::from_secs(20);
@@ -126,3 +128,45 @@ async fn a_proof_holds_only_at_its_address() {
// Known by its node ID, not by its address.
assert!(a.get_peer_state("ghost").await.is_none());
}
+
+/// A swarm across two transports: a only on the first, c only on the second, b on both.
+/// a and c never reach each other, and still share everything through b.
+#[tokio::test(flavor = "multi_thread", worker_threads = 4)]
+async fn nodes_on_both_transports_carry_the_others() {
+ let sim = Sim::with_identity(54);
+ let second = SimNet::new(55);
+ let a = sim.start("a", &[], Start::Genesis);
+ let b = sim.start_with("b", &["a"], Start::Join, |config| {
+ let identity = config.identity.as_mut().unwrap();
+ let transport: Arc<dyn Transport> = second.transport("b");
+ identity.more.push(("other", transport));
+ });
+ let c = sim.start_with("c", &["other:b"], Start::Join, |config| {
+ config.transport = second.transport("c");
+ config.identity.as_mut().unwrap().scheme = "other";
+ });
+ sim.wait_ready(&[&a, &b, &c], SOON).await;
+ assert_eq!(b.transport.local_addresses(), ["sim:b", "other:b"]);
+
+ write(&c, "from/c", json!("c")).await;
+ write(&a, "from/a", json!("a")).await;
+ sim.wait_converged(&[&a, &b, &c], SOON).await;
+ assert_eq!(read(&a, "from/c").await, Some(json!("c")));
+ assert_eq!(read(&c, "from/a").await, Some(json!("a")));
+
+ // The member list says where c is, on a transport a doesn't have.
+ let c_id = c.local_id().to_owned();
+ let a_ref = &a;
+ sim.wait_until("a knows c's entry", SOON, move || {
+ let c_id = c_id.clone();
+ async move {
+ let replica = a_ref.doc.read().await;
+ members::addresses(&replica.doc, &c_id) == ["other:c"]
+ }
+ })
+ .await;
+ assert!(!a.transport.can_reach(c.local_id()));
+ assert!(!c.transport.can_reach(a.local_id()));
+ assert!(a.transport.can_reach(b.local_id()));
+ assert!(c.transport.can_reach(b.local_id()));
+}
diff --git a/src/simtest/mod.rs b/src/simtest/mod.rs
index 4d7374a..be2dc7b 100644
--- a/src/simtest/mod.rs
+++ b/src/simtest/mod.rs
@@ -94,6 +94,7 @@ impl Sim {
identity: self.identity.then(|| IdentityConfig {
key: Arc::new(sim_key(id)),
scheme: "sim",
+ more: Vec::new(),
}),
initial_epoch: Epoch::GENESIS,
initial_doc: AutoCommit::new(),