1use std::time::{Duration, SystemTime};
8
9pub trait Clock: Send + Sync {
24 fn now(&self) -> SystemTime;
26}
27
28#[derive(Debug, Clone, Copy, Default)]
33pub struct SystemClock;
34
35impl Clock for SystemClock {
36 fn now(&self) -> SystemTime {
37 SystemTime::now()
38 }
39}
40
41pub trait Sleeper: Send + Sync {
58 fn sleep(&self, duration: Duration) -> impl std::future::Future<Output = ()> + Send;
60}
61
62#[derive(Debug, Clone, Copy, Default)]
67pub struct TokioSleeper;
68
69impl Sleeper for TokioSleeper {
70 async fn sleep(&self, duration: Duration) {
71 tokio::time::sleep(duration).await;
72 }
73}
74
75#[derive(Debug, Clone, Copy, Default)]
79pub struct InstantSleeper;
80
81impl Sleeper for InstantSleeper {
82 async fn sleep(&self, _duration: Duration) {
83 }
85}
86
87#[cfg(test)]
88mod tests {
89 use super::*;
90 use std::sync::atomic::{AtomicU64, Ordering};
91 use std::time::Duration;
92
93 struct MockClock {
95 secs: AtomicU64,
97 }
98
99 impl MockClock {
100 fn new(initial_secs: u64) -> Self {
101 Self {
102 secs: AtomicU64::new(initial_secs),
103 }
104 }
105
106 fn advance(&self, secs: u64) {
107 self.secs.fetch_add(secs, Ordering::SeqCst);
108 }
109 }
110
111 impl Clock for MockClock {
112 fn now(&self) -> SystemTime {
113 SystemTime::UNIX_EPOCH + Duration::from_secs(self.secs.load(Ordering::SeqCst))
114 }
115 }
116
117 #[test]
118 fn system_clock_returns_current_time() {
119 let clock = SystemClock;
120 let before = SystemTime::now();
121 let result = clock.now();
122 let after = SystemTime::now();
123
124 assert!(result >= before);
125 assert!(result <= after);
126 }
127
128 #[test]
129 fn system_clock_is_send_sync() {
130 fn assert_send_sync<T: Send + Sync>() {}
131 assert_send_sync::<SystemClock>();
132 }
133
134 fn assert_default<T: Default>() {}
135
136 #[test]
137 fn system_clock_is_default() {
138 assert_default::<SystemClock>();
139 }
140
141 #[test]
142 fn system_clock_is_copy() {
143 let clock1 = SystemClock;
144 let clock2 = clock1;
145 let _ = clock1.now();
147 let _ = clock2.now();
148 }
149
150 #[test]
151 fn mock_clock_returns_controlled_time() {
152 let clock = MockClock::new(1_000_000);
153 let expected = SystemTime::UNIX_EPOCH + Duration::from_secs(1_000_000);
154
155 assert_eq!(clock.now(), expected);
156 }
157
158 #[test]
159 fn mock_clock_can_advance() {
160 let clock = MockClock::new(0);
161
162 assert_eq!(clock.now(), SystemTime::UNIX_EPOCH);
163
164 clock.advance(100);
165 assert_eq!(
166 clock.now(),
167 SystemTime::UNIX_EPOCH + Duration::from_secs(100)
168 );
169
170 clock.advance(50);
171 assert_eq!(
172 clock.now(),
173 SystemTime::UNIX_EPOCH + Duration::from_secs(150)
174 );
175 }
176
177 #[test]
178 fn mock_clock_is_send_sync() {
179 fn assert_send_sync<T: Send + Sync>() {}
180 assert_send_sync::<MockClock>();
181 }
182
183 #[tokio::test]
186 async fn tokio_sleeper_completes() {
187 let sleeper = TokioSleeper;
188 sleeper.sleep(Duration::from_millis(1)).await;
190 }
191
192 #[test]
193 fn tokio_sleeper_is_send_sync() {
194 fn assert_send_sync<T: Send + Sync>() {}
195 assert_send_sync::<TokioSleeper>();
196 }
197
198 #[test]
199 fn tokio_sleeper_is_default() {
200 assert_default::<TokioSleeper>();
201 }
202
203 #[test]
204 fn tokio_sleeper_is_copy() {
205 let sleeper1 = TokioSleeper;
206 let sleeper2 = sleeper1;
207 let _ = sleeper1;
209 let _ = sleeper2;
210 }
211
212 #[tokio::test]
213 async fn instant_sleeper_returns_immediately() {
214 let sleeper = InstantSleeper;
215 let start = std::time::Instant::now();
216 sleeper.sleep(Duration::from_secs(1000)).await;
217 assert!(start.elapsed() < Duration::from_millis(100));
219 }
220
221 #[test]
222 fn instant_sleeper_is_send_sync() {
223 fn assert_send_sync<T: Send + Sync>() {}
224 assert_send_sync::<InstantSleeper>();
225 }
226
227 #[test]
228 fn instant_sleeper_is_default() {
229 assert_default::<InstantSleeper>();
230 }
231
232 #[test]
233 fn instant_sleeper_is_copy() {
234 let sleeper1 = InstantSleeper;
235 let sleeper2 = sleeper1;
236 let _ = sleeper1;
238 let _ = sleeper2;
239 }
240}