1#[cfg(msim)]
5pub use msim::*;
6
7#[cfg(msim)]
8use std::hash::Hasher;
9
10use std::sync::atomic::{AtomicUsize, Ordering};
11
12pub use ::rand as rand_crate;
14pub use anemo;
15pub use anemo_tower;
16pub use fastcrypto;
17pub use lru;
18pub use move_package;
19pub use mysten_network;
20pub use sui_framework;
21pub use sui_move_build;
22pub use sui_types;
23pub use telemetry_subscribers;
24pub use tempfile;
25pub use tower;
26
27#[cfg(msim)]
28pub mod configs {
29 use msim::*;
30 use std::collections::HashMap;
31 use std::ops::Range;
32 use std::time::Duration;
33
34 use tracing::info;
35
36 fn ms_to_dur(range: Range<u64>) -> Range<Duration> {
37 Duration::from_millis(range.start)..Duration::from_millis(range.end)
38 }
39
40 pub fn constant_latency_ms(latency: u64) -> SimConfig {
42 uniform_latency_ms(latency..(latency + 1))
43 }
44
45 pub fn uniform_latency_ms(range: Range<u64>) -> SimConfig {
47 let range = ms_to_dur(range);
48 SimConfig {
49 net: NetworkConfig {
50 latency: LatencyConfig {
51 default_latency: LatencyDistribution::uniform(range),
52 ..Default::default()
53 },
54 ..Default::default()
55 },
56 }
57 }
58
59 pub fn bimodal_latency_ms(
61 baseline: Range<u64>,
63 degraded: Range<u64>,
65 degraded_freq: f64,
67 ) -> SimConfig {
68 let baseline = ms_to_dur(baseline);
69 let degraded = ms_to_dur(degraded);
70 SimConfig {
71 net: NetworkConfig {
72 latency: LatencyConfig {
73 default_latency: LatencyDistribution::bimodal(
74 baseline,
75 degraded,
76 degraded_freq,
77 ),
78 ..Default::default()
79 },
80 ..Default::default()
81 },
82 }
83 }
84
85 pub fn env_config(
87 default: SimConfig,
89 env_configs: impl IntoIterator<Item = (&'static str, SimConfig)>,
92 ) -> SimConfig {
93 let mut env_configs = HashMap::<&'static str, SimConfig>::from_iter(env_configs);
94 if let Some(env) = std::env::var("SUI_SIM_CONFIG").ok() {
95 if let Some(cfg) = env_configs.remove(env.as_str()) {
96 info!("Using test config for SUI_SIM_CONFIG={}", env);
97 cfg
98 } else {
99 panic!(
100 "No config found for SUI_SIM_CONFIG={}. Available configs are: {:?}",
101 env,
102 env_configs.keys()
103 );
104 }
105 } else {
106 info!("Using default test config");
107 default
108 }
109 }
110}
111
112thread_local! {
113 static NODE_COUNT: AtomicUsize = const { AtomicUsize::new(0) };
114}
115
116pub struct NodeLeakDetector(());
117
118impl NodeLeakDetector {
119 pub fn new() -> Self {
120 NODE_COUNT.with(|c| c.fetch_add(1, Ordering::SeqCst));
121 Self(())
122 }
123
124 pub fn get_current_node_count() -> usize {
125 NODE_COUNT.with(|c| c.load(Ordering::SeqCst))
126 }
127}
128
129impl Default for NodeLeakDetector {
130 fn default() -> Self {
131 Self::new()
132 }
133}
134
135impl Drop for NodeLeakDetector {
136 fn drop(&mut self) {
137 NODE_COUNT.with(|c| c.fetch_sub(1, Ordering::SeqCst));
138 }
139}
140
141#[cfg(not(msim))]
142#[macro_export]
143macro_rules! return_if_killed {
144 () => {};
145}
146
147#[cfg(msim)]
148pub fn current_simnode_id() -> msim::task::NodeId {
149 msim::runtime::NodeHandle::current().id()
150}
151
152pub fn has_mainnet_protocol_config_override() -> bool {
153 use sui_types::{digests::ChainIdentifier, supported_protocol_versions::Chain};
154
155 ChainIdentifier::default().chain() == Chain::Mainnet
156}
157
158#[cfg(msim)]
159pub mod random {
160 use super::*;
161
162 use rand_crate::{Rng, SeedableRng, rngs::SmallRng, thread_rng};
163 use serde::Serialize;
164 use std::cell::RefCell;
165 use std::collections::HashSet;
166 use std::hash::Hash;
167
168 pub fn deterministic_probability<T: Hash>(value: T, chance: f32) -> bool {
171 thread_local! {
172 static SEED: u64 = thread_rng().r#gen();
175 }
176
177 chance
178 > SEED.with(|seed| {
179 let mut hasher = std::collections::hash_map::DefaultHasher::new();
180 seed.hash(&mut hasher);
181 value.hash(&mut hasher);
182 let mut rng = SmallRng::seed_from_u64(hasher.finish());
183 rng.gen_range(0.0..1.0)
184 })
185 }
186
187 pub fn deterministic_probability_once<T: Hash + Serialize>(value: T, chance: f32) -> bool {
190 thread_local! {
191 static FAILING_VALUES: RefCell<HashSet<(msim::task::NodeId, Vec<u8>)>> = RefCell::new(HashSet::new());
192 }
193
194 let bytes = bcs::to_bytes(&value).unwrap();
195 let key = (current_simnode_id(), bytes);
196
197 FAILING_VALUES.with(|failing_values| {
198 let mut failing_values = failing_values.borrow_mut();
199 if failing_values.contains(&key) {
200 false
201 } else if deterministic_probability(value, chance) {
202 failing_values.insert(key);
203 true
204 } else {
205 false
206 }
207 })
208 }
209}