Monorepo for Tangled
tangled.org
1use std::num::NonZeroUsize;
2use std::time::Duration;
3
4use bobbin_ingest::DisconnectKind;
5use bobbin_sim::workloads::{SlingshotFlap, SlingshotFlapConfig};
6use bobbin_sim::{Sim, SimConfig, SimOutcome};
7use tokio::runtime::Builder as TokioBuilder;
8
9#[test]
10fn slingshot_flap_resumes_via_replay_after_pong_timeout() {
11 let cfg = SlingshotFlapConfig {
12 cross_did_stars: 5000,
13 normal_latency_ms: 2,
14 brownout_start_ms: 0,
15 brownout_duration_ms: 60_000,
16 brownout_latency_ms: 200,
17 brownout_enabled: true,
18 hydrant_send_timeout_ms: 30_000,
19 hydrant_frame_pace_us: 1_000,
20 omit_target_repos: false,
21 emit_live_promotion_frame: false,
22 };
23 let mut sim_config = SimConfig::new(7);
24 sim_config.parallelism = NonZeroUsize::new(4).unwrap();
25 sim_config.max_virtual_runtime = Duration::from_secs(600);
26 sim_config.warming_buffer_enabled = false;
27
28 let workload = Box::new(SlingshotFlap::new(cfg.clone()));
29 let runtime = TokioBuilder::new_current_thread()
30 .enable_all()
31 .start_paused(true)
32 .build()
33 .expect("build current_thread runtime");
34 let report = runtime.block_on(Sim::new(sim_config, workload).run());
35
36 let total_frames = (cfg.cross_did_stars as u64) * 2;
37
38 assert_eq!(
39 report.outcome,
40 SimOutcome::Passed,
41 "expected eventual recovery via replay after disconnect, got {:?} reason={:?}",
42 report.outcome,
43 report.failure_reason,
44 );
45 assert_eq!(
46 report.events_processed, total_frames,
47 "expected all {total_frames} frames processed after reconnect, got {}",
48 report.events_processed,
49 );
50 assert!(
51 report.disconnect_count >= 1,
52 "expected at least one disconnect during sustained brownout, got {}",
53 report.disconnect_count,
54 );
55 let last = report
56 .last_disconnect
57 .as_ref()
58 .expect("last_disconnect populated when disconnect_count > 0");
59 assert_eq!(
60 last.kind,
61 DisconnectKind::PongTimeout,
62 "expected PongTimeout under sustained brownout (paced upstream + N=4 + 200ms slingshot RTT), got {:?}: {}",
63 last.kind,
64 last.message,
65 );
66 assert!(
67 last.last_cursor.raw() > 0 && last.last_cursor.raw() < total_frames,
68 "expected disconnect mid-stream, got last_cursor={}",
69 last.last_cursor.raw(),
70 );
71}