feat: distribution simulation tests #34
1 changed files with 70 additions and 0 deletions
|
|
@ -484,3 +484,73 @@ fn large_cluster_registry_converges() {
|
|||
result.actual
|
||||
);
|
||||
}
|
||||
|
||||
// ────────────────────────────────────────────────────────────────────────────
|
||||
// 10. Three-way partition: cluster splits into 3 groups, heals, converges
|
||||
// ────────────────────────────────────────────────────────────────────────────
|
||||
|
||||
#[test]
|
||||
fn three_way_partition_heals_and_converges() {
|
||||
// Given: 9 nodes split into 3 groups {0,1,2}, {3,4,5}, {6,7,8}.
|
||||
// Each group registers a name during the partition. After healing,
|
||||
// all 9 nodes should converge on all 3 names.
|
||||
let config = DistributionSimConfig {
|
||||
name: "three-way-partition".into(),
|
||||
num_nodes: 9,
|
||||
num_rounds: 140,
|
||||
ticks_per_round: 3,
|
||||
actors_per_node: 0,
|
||||
network_faults: vec![
|
||||
// Partition A vs B
|
||||
NetworkFault::Partition {
|
||||
round: 10,
|
||||
partition: Partition {
|
||||
side_a: vec![0, 1, 2],
|
||||
side_b: vec![3, 4, 5, 6, 7, 8],
|
||||
asymmetric: false,
|
||||
},
|
||||
},
|
||||
// Partition B vs C (stacks with the above: now 3 groups isolated)
|
||||
NetworkFault::Partition {
|
||||
round: 10,
|
||||
partition: Partition {
|
||||
side_a: vec![3, 4, 5],
|
||||
side_b: vec![6, 7, 8],
|
||||
asymmetric: false,
|
||||
},
|
||||
},
|
||||
NetworkFault::Heal { round: 60 },
|
||||
],
|
||||
action_schedule: vec![
|
||||
(20, SimAction::RegisterName { node_idx: 0, name: "group-a-svc".into() }),
|
||||
(20, SimAction::RegisterName { node_idx: 3, name: "group-b-svc".into() }),
|
||||
(20, SimAction::RegisterName { node_idx: 6, name: "group-c-svc".into() }),
|
||||
],
|
||||
swim: distribution::swim::probe::SwimConfig {
|
||||
probe_interval: 1,
|
||||
probe_timeout: 3,
|
||||
indirect_probes: 1,
|
||||
// Must exceed partition duration (50 rounds × 3 ticks = 150 ticks)
|
||||
suspicion_timeout: 200,
|
||||
dead_reprobe_interval: 10,
|
||||
},
|
||||
..DistributionSimConfig::default()
|
||||
};
|
||||
|
||||
let (_trace, nodes) = run_simulation_with_nodes(config);
|
||||
|
||||
let alive_count = nodes.iter().filter(|n| n.is_some()).count();
|
||||
assert_eq!(alive_count, 9, "all 9 nodes should survive the three-way partition");
|
||||
|
||||
// After healing + gossip, all 3 names should be resolvable from every node
|
||||
for (i, node) in nodes.iter().enumerate() {
|
||||
if let Some(node) = node {
|
||||
for name in &["group-a-svc", "group-b-svc", "group-c-svc"] {
|
||||
assert!(
|
||||
node.resolve_name(name).is_some(),
|
||||
"node {i} should resolve '{name}' after three-way partition heals"
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue