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