aboutsummaryrefslogtreecommitdiffstats
path: root/src/simtest/mod.rs
diff options
context:
space:
mode:
authortv <tv@krebsco.de>2026-11-02 23:31:25 +0100
committertv <tv@krebsco.de>2026-11-02 23:31:25 +0100
commit6d66ebdb6d38e7a9b891fb05d5c9c1ca933ceb21 (patch)
tree8b338fd8f34c2cb3adad5c9e7d3aba9d8fc1e1b3 /src/simtest/mod.rs
parent0c096a524531c180798f0712bb7100f0b7557f76 (diff)
add links relay test
Diffstat (limited to 'src/simtest/mod.rs')
-rw-r--r--src/simtest/mod.rs62
1 files changed, 61 insertions, 1 deletions
diff --git a/src/simtest/mod.rs b/src/simtest/mod.rs
index a79bd2b..76583de 100644
--- a/src/simtest/mod.rs
+++ b/src/simtest/mod.rs
@@ -11,6 +11,7 @@
mod deltas;
mod identity;
+mod links;
mod remakes;
mod soak;
mod timing;
@@ -47,7 +48,14 @@ pub(crate) const SOON: Duration = Duration::from_secs(10);
/// A simulated swarm: the net and the nodes started on it.
pub(crate) struct Sim {
+ /// The net of the transport `sim`, every node's but those started on others
+ /// (`start_on`).
pub(crate) net: SimNet,
+ /// Further nets, by the scheme of their transport: nodes on different nets can't
+ /// reach each other, as nodes on different transports (one on Tor alone, one on
+ /// libp2p alone) can't. Made when first used.
+ nets: std::sync::Mutex<std::collections::HashMap<&'static str, SimNet>>,
+ seed: u64,
/// Nodes under the identity layer (`transport::identity`), named by node IDs; else
/// by their names on the net.
identity: bool,
@@ -60,6 +68,8 @@ impl Sim {
init_logging();
Self {
net: SimNet::new(seed),
+ nets: Default::default(),
+ seed,
identity: false,
nodes: Default::default(),
}
@@ -99,8 +109,58 @@ impl Sim {
start: Start,
adjust: impl FnOnce(&mut NodeConfig),
) -> AppState {
+ self.start_node(id, self.net.transport(id), seeds, start, adjust)
+ }
+
+ /// [`start`](Self::start) under the identity layer, on the nets of `schemes`
+ /// instead of `sim`'s alone (the first preferred): it reaches only nodes on one of
+ /// them. Seeds by name are resolved on the first.
+ pub(crate) fn start_on(
+ &self,
+ id: &str,
+ schemes: &[&'static str],
+ seeds: &[&str],
+ start: Start,
+ ) -> AppState {
+ assert!(
+ self.identity,
+ "transports by scheme need the identity layer"
+ );
+ let mut transports = schemes.iter().map(|scheme| {
+ let transport: Arc<dyn crate::transport::Transport> =
+ self.net_for(scheme).transport(id);
+ (*scheme, transport)
+ });
+ let (scheme, first) = transports.next().expect("a transport at least");
+ let more: Vec<_> = transports.collect();
+ let key = Arc::new(sim_key(id));
+ self.start_node(id, first, seeds, start, move |config| {
+ config.identity = Some(IdentityConfig { key, scheme, more });
+ })
+ }
+
+ /// The net of the transport `scheme`.
+ pub(crate) fn net_for(&self, scheme: &'static str) -> SimNet {
+ if scheme == "sim" {
+ return self.net.clone();
+ }
+ let mut nets = self.nets.lock().unwrap();
+ let index = nets.len() as u64 + 1;
+ nets.entry(scheme)
+ .or_insert_with(|| SimNet::new(self.seed.wrapping_add(index)))
+ .clone()
+ }
+
+ fn start_node(
+ &self,
+ id: &str,
+ transport: Arc<dyn crate::transport::Transport>,
+ seeds: &[&str],
+ start: Start,
+ adjust: impl FnOnce(&mut NodeConfig),
+ ) -> AppState {
let mut config = NodeConfig {
- transport: self.net.transport(id),
+ transport,
identity: self.identity.then(|| IdentityConfig {
key: Arc::new(sim_key(id)),
scheme: "sim",