moonpool_sim/providers/
time.rs1use async_trait::async_trait;
4use std::time::Duration;
5
6use moonpool_core::{SimulationResult, TimeProvider};
7
8use crate::sim::WeakSimWorld;
9
10#[derive(Debug, Clone)]
12pub struct SimTimeProvider {
13 sim: WeakSimWorld,
14}
15
16impl SimTimeProvider {
17 pub fn new(sim: WeakSimWorld) -> Self {
19 Self { sim }
20 }
21}
22
23#[async_trait(?Send)]
24impl TimeProvider for SimTimeProvider {
25 async fn sleep(&self, duration: Duration) -> SimulationResult<()> {
26 let sleep_future = self.sim.sleep(duration)?;
27 let _ = sleep_future.await;
28 Ok(())
29 }
30
31 fn now(&self) -> Duration {
32 self.sim.now().unwrap_or(Duration::ZERO)
34 }
35
36 fn timer(&self) -> Duration {
37 self.sim.timer().unwrap_or(Duration::ZERO)
40 }
41
42 async fn timeout<F, T>(&self, duration: Duration, future: F) -> SimulationResult<Result<T, ()>>
43 where
44 F: std::future::Future<Output = T>,
45 {
46 let sleep_future = self.sim.sleep(duration)?;
47
48 tokio::select! {
51 result = future => Ok(Ok(result)),
52 _ = sleep_future => Ok(Err(())),
53 }
54 }
55}
56
57#[cfg(test)]
58mod tests {
59 use super::*;
60 use crate::sim::SimWorld;
61
62 #[tokio::test]
63 async fn test_sim_time_provider_basic() {
64 let sim = SimWorld::new();
65 let time_provider = SimTimeProvider::new(sim.downgrade());
66
67 let now = time_provider.now();
69 assert_eq!(now, Duration::ZERO);
70
71 let timer = time_provider.timer();
73 assert!(timer >= now);
74
75 let result = time_provider
77 .timeout(Duration::from_millis(100), async { 42 })
78 .await;
79 assert!(result.is_ok());
80 assert_eq!(result.expect("timeout should complete"), Ok(42));
81 }
82
83 #[test]
84 fn test_sim_time_provider_with_simulation() {
85 let sim = SimWorld::new();
86 let time_provider = SimTimeProvider::new(sim.downgrade());
87
88 let now = time_provider.now();
90 assert_eq!(now, Duration::ZERO);
91
92 let timer = time_provider.timer();
94 assert!(timer >= now);
95 assert!(timer <= now + Duration::from_millis(100));
97 }
98
99 #[test]
100 fn test_clock_drift_bounds() {
101 let sim = SimWorld::new();
102 let time_provider = SimTimeProvider::new(sim.downgrade());
103
104 for _ in 0..100 {
106 let now = time_provider.now();
107 let timer = time_provider.timer();
108
109 assert!(timer >= now, "timer ({:?}) < now ({:?})", timer, now);
111
112 assert!(
114 timer <= now + Duration::from_millis(100),
115 "timer ({:?}) > now + 100ms ({:?})",
116 timer,
117 now + Duration::from_millis(100)
118 );
119 }
120 }
121}