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