Skip to main content

torrust_clock/clock/
mod.rs

1use std::time::Duration;
2
3use self::stopped::StoppedClock;
4use self::working::WorkingClock;
5use crate::DurationSinceUnixEpoch;
6
7pub mod stopped;
8pub mod working;
9
10/// A generic structure that represents a clock.
11///
12/// It can be either the working clock (production) or the stopped clock
13/// (testing). It implements the `Time` trait, which gives you the current time.
14#[derive(Debug)]
15pub struct Clock<T> {
16    clock: std::marker::PhantomData<T>,
17}
18
19/// The working clock. It returns the current time.
20pub type Working = Clock<WorkingClock>;
21/// The stopped clock. It returns always the same fixed time.
22pub type Stopped = Clock<StoppedClock>;
23
24/// Trait for types that can be used as a timestamp clock.
25pub trait Time: Sized {
26    fn now() -> DurationSinceUnixEpoch;
27
28    fn dbg_clock_type() -> String;
29
30    #[must_use]
31    fn now_add(add_time: &Duration) -> Option<DurationSinceUnixEpoch> {
32        Self::now().checked_add(*add_time)
33    }
34    #[must_use]
35    fn now_sub(sub_time: &Duration) -> Option<DurationSinceUnixEpoch> {
36        Self::now().checked_sub(*sub_time)
37    }
38}
39
40#[cfg(test)]
41mod tests {
42    use std::any::TypeId;
43    use std::time::Duration;
44
45    use crate::CurrentClock;
46    use crate::clock::{self, Stopped, Time, Working};
47
48    #[test]
49    fn it_should_be_the_stopped_clock_as_default_when_testing() {
50        // We are testing, so we should default to the fixed time.
51        assert_eq!(TypeId::of::<Stopped>(), TypeId::of::<CurrentClock>());
52        assert_eq!(Stopped::now(), CurrentClock::now());
53    }
54
55    #[test]
56    fn it_should_have_different_times() {
57        assert_ne!(TypeId::of::<clock::Stopped>(), TypeId::of::<Working>());
58        assert_ne!(Stopped::now(), Working::now());
59    }
60
61    #[test]
62    fn it_should_use_stopped_time_for_testing() {
63        assert_eq!(CurrentClock::dbg_clock_type(), "Stopped".to_owned());
64
65        let time = CurrentClock::now();
66        std::thread::sleep(Duration::from_millis(50));
67        let time_2 = CurrentClock::now();
68
69        assert_eq!(time, time_2);
70    }
71}