1use std::sync::atomic::{AtomicU64, Ordering};
11use std::sync::Arc;
12use std::time::{SystemTime, UNIX_EPOCH};
13
14pub trait Clock: Send + Sync + std::fmt::Debug {
16 fn now(&self) -> u64;
17}
18
19pub type SharedClock = Arc<dyn Clock + Send + Sync>;
21
22#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
24pub struct SystemClock;
25
26impl Clock for SystemClock {
27 fn now(&self) -> u64 {
28 SystemTime::now()
31 .duration_since(UNIX_EPOCH)
32 .map(|d| d.as_secs())
33 .unwrap_or(0)
34 }
35}
36
37#[derive(Clone, Debug)]
39pub struct MockClock {
40 now: Arc<AtomicU64>,
41}
42
43impl MockClock {
44 pub fn new(now: u64) -> Self {
45 Self {
46 now: Arc::new(AtomicU64::new(now)),
47 }
48 }
49
50 pub fn set_now(&self, now: u64) {
52 self.now.store(now, Ordering::Relaxed);
53 }
54
55 pub fn advance(&self, secs: u64) {
57 self.now.fetch_add(secs, Ordering::Relaxed);
58 }
59
60 pub fn peek(&self) -> u64 {
62 self.now.load(Ordering::Relaxed)
63 }
64}
65
66impl Clock for MockClock {
67 fn now(&self) -> u64 {
68 self.peek()
69 }
70}
71
72#[cfg(test)]
73mod tests {
74 use super::*;
75
76 #[test]
77 fn mock_clock_set_and_advance() {
78 let c = MockClock::new(1000);
79 assert_eq!(c.peek(), 1000);
80 c.advance(50);
81 assert_eq!(c.peek(), 1050);
82 c.set_now(2000);
83 assert_eq!(c.peek(), 2000);
84 let shared: SharedClock = Arc::new(c.clone());
86 assert_eq!(shared.now(), 2000);
87 }
88
89 #[test]
90 fn mock_clock_clone_shares_state() {
91 let c = MockClock::new(1);
92 let d = c.clone();
93 c.set_now(99);
94 assert_eq!(d.peek(), 99);
95 }
96
97 #[test]
98 fn system_clock_returns_unix_seconds() {
99 let now = SystemClock.now();
100 assert!(now > 1_700_000_000, "SystemClock 应返回 Unix 秒,得到 {now}");
102 }
103}