actionqueue_core/time/
clock.rs1pub trait Clock: Send + Sync {
15 fn now(&self) -> u64;
17}
18
19#[derive(Debug, Clone, Copy, Default)]
24pub struct SystemClock;
25
26impl Clock for SystemClock {
27 fn now(&self) -> u64 {
34 std::time::SystemTime::now()
35 .duration_since(std::time::UNIX_EPOCH)
36 .expect("system time before Unix epoch")
37 .as_secs()
38 }
39}
40
41impl SystemClock {
42 pub fn now_system_time(&self) -> std::time::SystemTime {
44 std::time::SystemTime::now()
45 }
46}
47
48#[derive(Debug, Clone)]
53pub struct MockClock {
54 current_time: u64,
56}
57
58impl MockClock {
59 pub fn new(current_time: u64) -> Self {
61 Self { current_time }
62 }
63
64 pub fn with_system_time() -> Self {
71 Self::new(
72 std::time::SystemTime::now()
73 .duration_since(std::time::UNIX_EPOCH)
74 .expect("system time before Unix epoch")
75 .as_secs(),
76 )
77 }
78
79 pub fn advance_by(&mut self, seconds: u64) {
81 self.current_time = self.current_time.saturating_add(seconds);
82 }
83
84 pub fn set(&mut self, time: u64) {
86 self.current_time = time;
87 }
88
89 pub fn now_system_time(&self) -> std::time::SystemTime {
91 std::time::SystemTime::UNIX_EPOCH
92 .checked_add(std::time::Duration::from_secs(self.current_time))
93 .expect("time overflow")
94 }
95}
96
97impl Default for MockClock {
98 fn default() -> Self {
99 Self::with_system_time()
100 }
101}
102
103impl Clock for MockClock {
104 fn now(&self) -> u64 {
105 self.current_time
106 }
107}
108
109pub type SharedClock = std::sync::Arc<dyn Clock>;
111
112#[cfg(test)]
113mod tests {
114 use super::*;
115
116 #[test]
117 fn system_clock_returns_monotonically_increasing_time() {
118 let clock = SystemClock;
119 let time1 = clock.now();
120 let time2 = clock.now();
121 assert!(time2 >= time1);
122 }
123
124 #[test]
125 fn mock_clock_can_be_initialized() {
126 let clock = MockClock::new(1000);
127 assert_eq!(clock.now(), 1000);
128 }
129
130 #[test]
131 fn mock_clock_can_be_advanced() {
132 let mut clock = MockClock::new(1000);
133 clock.advance_by(100);
134 assert_eq!(clock.now(), 1100);
135 }
136
137 #[test]
138 fn mock_clock_can_be_set() {
139 let mut clock = MockClock::new(1000);
140 clock.set(2000);
141 assert_eq!(clock.now(), 2000);
142 }
143
144 #[test]
145 fn mock_clock_system_time_conversion() {
146 let clock = MockClock::new(1000);
147 let system_time = clock.now_system_time();
148 let duration = system_time.duration_since(std::time::UNIX_EPOCH).expect("time overflow");
149 assert_eq!(duration.as_secs(), 1000);
150 }
151}