use simulation::distribution::sim::{ run_simulation_with_nodes, DistributionSimConfig, SimAction, }; #[test] fn debug_tombstone_propagation() { let config = DistributionSimConfig { name: "debug-tombstone".into(), num_nodes: 5, num_rounds: 80, ticks_per_round: 3, actors_per_node: 0, action_schedule: vec![ (5, SimAction::RegisterName { node_idx: 0, name: "svc".into() }), ], kill_schedule: vec![(15, 0)], ..DistributionSimConfig::default() }; let (trace, nodes) = run_simulation_with_nodes(config); // Check snapshots at various rounds for round_idx in [4, 9, 14, 19, 24, 39, 59, 79] { if round_idx < trace.snapshots_per_round.len() { let snaps = &trace.snapshots_per_round[round_idx]; let reg_sizes: Vec = snaps.iter().map(|(_, s)| s.registry_size).collect(); let tomb_counts: Vec = snaps.iter().map(|(_, s)| s.registry_tombstone_count).collect(); let alive: Vec = snaps.iter().map(|(_, s)| s.is_alive).collect(); let members: Vec = snaps.iter().map(|(_, s)| s.member_count).collect(); eprintln!("Round {}: alive={alive:?} members={members:?} registry={reg_sizes:?} tombstones={tomb_counts:?}", round_idx + 1); } } // Check membership change events let dead_events: Vec<_> = trace.events.iter() .filter(|e| matches!(&e.kind, simulation::distribution::trace::DistributionEventKind::MembershipChanged { new_state, .. } if new_state == "Dead")) .collect(); eprintln!("Dead events: {}", dead_events.len()); for e in &dead_events { if let simulation::distribution::trace::DistributionEventKind::MembershipChanged { target, new_state } = &e.kind { eprintln!(" tick={} node={} declared {target} as {new_state}", e.tick, e.node_name); } } // Check final nodes' resolve_name for (i, node) in nodes.iter().enumerate() { match node { Some(n) => { let res = n.resolve_name("svc"); eprintln!("Node {i}: resolve_name('svc') = {res:?}, registry_size={}, tombstones={}", n.registry().len(), n.registry().tombstone_count()); } None => eprintln!("Node {i}: DEAD"), } } }