stratus/
utils.rs

1use std::time::Duration;
2
3use tokio::time::Instant;
4
5/// Amount of bytes in one GB (technically, GiB).
6pub const GIGABYTE: usize = 1024 * 1024 * 1024;
7
8pub fn calculate_tps_and_bpm(duration: Duration, transaction_count: usize, block_count: usize) -> (f64, f64) {
9    let seconds_elapsed = duration.as_secs_f64() + f64::EPSILON;
10    let tps = transaction_count as f64 / seconds_elapsed;
11    let blocks_per_minute = block_count as f64 / (seconds_elapsed / 60.0);
12    (tps, blocks_per_minute)
13}
14
15pub fn calculate_tps(duration: Duration, transaction_count: usize) -> f64 {
16    let seconds_elapsed = duration.as_secs_f64() + f64::EPSILON;
17    transaction_count as f64 / seconds_elapsed
18}
19
20pub struct DropTimer {
21    instant: Instant,
22    scope_name: &'static str,
23}
24
25impl DropTimer {
26    pub fn start(scope_name: &'static str) -> Self {
27        Self {
28            instant: Instant::now(),
29            scope_name,
30        }
31    }
32}
33
34impl Drop for DropTimer {
35    fn drop(&mut self) {
36        tracing::info!(ran_for = ?self.instant.elapsed(), "Timer: '{}' finished", self.scope_name);
37    }
38}
39
40#[cfg(test)]
41pub mod test_utils {
42    use alloy_primitives::Uint;
43    use anyhow::Context;
44    use fake::Dummy;
45    use fake::Fake;
46    use fake::Faker;
47    use glob::glob;
48    use rand::SeedableRng;
49    use rand::rngs::SmallRng;
50
51    fn generate_rng() -> rand::rngs::SmallRng {
52        use std::time::SystemTime;
53        use std::time::UNIX_EPOCH;
54
55        use rand::SeedableRng;
56        let now = SystemTime::now().duration_since(UNIX_EPOCH).expect("Failed to get system time").as_secs();
57        rand::rngs::SmallRng::seed_from_u64(now)
58    }
59
60    fn deterministic_rng() -> SmallRng {
61        SeedableRng::seed_from_u64(0)
62    }
63
64    /// Fake the first `size` values of type `T` using the default seed.
65    ///
66    /// Multiple calls of this (for the same `T` and `size`) will return the same list.
67    pub fn fake_list<T: fake::Dummy<Faker>>(size: usize) -> Vec<T> {
68        let mut rng = deterministic_rng();
69        (0..size).map(|_| Faker.fake_with_rng::<T, _>(&mut rng)).collect()
70    }
71
72    /// Fake the first `T` value in the default seed.
73    ///
74    /// Multiple calls of this (for the same `T`) will return the same value.
75    pub fn fake_first<T: fake::Dummy<Faker>>() -> T {
76        let mut rng = deterministic_rng();
77        Faker.fake_with_rng::<T, _>(&mut rng)
78    }
79
80    pub fn glob_to_string_paths(pattern: impl AsRef<str>) -> anyhow::Result<Vec<String>> {
81        let pattern = pattern.as_ref();
82
83        let iter = glob(pattern).with_context(|| format!("failed to parse glob pattern: {pattern}"))?;
84        let mut paths = vec![];
85
86        for entry in iter {
87            let entry = entry.with_context(|| format!("failed to read glob entry with pattern: {pattern}"))?;
88            let path = entry.to_str().with_context(|| format!("failed to convert path to string: {entry:?}"))?;
89            paths.push(path.to_owned());
90        }
91
92        Ok(paths)
93    }
94
95    pub fn fake_option<T: Dummy<Faker>>() -> Option<T> {
96        let mut rng = generate_rng();
97        Some(Faker.fake_with_rng::<T, _>(&mut rng))
98    }
99
100    pub fn fake_option_uint<const N: usize, const L: usize>() -> Option<Uint<N, L>> {
101        let mut rng = generate_rng();
102        Some(Uint::random_with(&mut rng))
103    }
104
105    pub fn fake_uint<const N: usize, const L: usize>() -> Uint<N, L> {
106        let mut rng = generate_rng();
107        Uint::random_with(&mut rng)
108    }
109}