moonpool_sim/providers/
time.rs1use async_trait::async_trait;
4use std::time::Duration;
5
6use moonpool_core::{TimeError, 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) -> Result<(), TimeError> {
26 let sleep_future = self.sim.sleep(duration).map_err(|_| TimeError::Shutdown)?;
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) -> Result<T, TimeError>
43 where
44 F: std::future::Future<Output = T>,
45 {
46 let sleep_future = self.sim.sleep(duration).map_err(|_| TimeError::Shutdown)?;
47
48 tokio::select! {
51 result = future => Ok(result),
52 _ = sleep_future => Err(TimeError::Elapsed),
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_eq!(result, Ok(42));
80 }
81
82 #[test]
83 fn test_sim_time_provider_with_simulation() {
84 let sim = SimWorld::new();
85 let time_provider = SimTimeProvider::new(sim.downgrade());
86
87 let now = time_provider.now();
89 assert_eq!(now, Duration::ZERO);
90
91 let timer = time_provider.timer();
93 assert!(timer >= now);
94 assert!(timer <= now + Duration::from_millis(100));
96 }
97
98 #[test]
99 fn test_clock_drift_bounds() {
100 let sim = SimWorld::new();
101 let time_provider = SimTimeProvider::new(sim.downgrade());
102
103 for _ in 0..100 {
105 let now = time_provider.now();
106 let timer = time_provider.timer();
107
108 assert!(timer >= now, "timer ({:?}) < now ({:?})", timer, now);
110
111 assert!(
113 timer <= now + Duration::from_millis(100),
114 "timer ({:?}) > now + 100ms ({:?})",
115 timer,
116 now + Duration::from_millis(100)
117 );
118 }
119 }
120}