1use std::sync::{Arc, Mutex};
2use std::time::Duration;
3
4use crate::clock::Source;
5use crate::{Clock, Instant, Result, unpoisoned};
6
7#[derive(Clone, Debug)]
8pub struct TestClock {
9 time: Arc<Mutex<Instant>>,
10}
11
12impl TestClock {
13 #[must_use]
14 pub fn starting_at(start: impl Into<Instant>) -> Self {
15 Self {
16 time: Arc::new(Mutex::new(start.into())),
17 }
18 }
19
20 #[must_use]
21 pub fn clock(&self) -> Clock {
22 Clock {
23 source: Source::Test(Arc::clone(&self.time)),
24 }
25 }
26
27 pub fn advance(&self, by: Duration) -> Result<()> {
28 let mut time = unpoisoned::lock(&self.time);
29 *time = time.checked_add(by)?;
30 Ok(())
31 }
32}
33
34#[cfg(test)]
35mod tests {
36 use jiff::Timestamp;
37
38 use super::*;
39
40 #[test]
41 fn a_test_clock_moves_only_when_advanced() {
42 let start = Timestamp::from_second(1_700_000_000).unwrap();
43 let test_clock = TestClock::starting_at(start);
44 let clock = test_clock.clock();
45
46 assert_eq!(clock.now().timestamp(), start);
47 test_clock.advance(Duration::from_secs(90)).unwrap();
48 assert_eq!(
49 clock.now().timestamp(),
50 start.checked_add(Duration::from_secs(90)).unwrap()
51 );
52 }
53}