steid

@jamesgill /

1//! Clock adapters.
2//!
3//! Two implementations, as every port gets: the real one, and the one that makes a use
4//! case testable without waiting.
5
6use std::time::{Duration, SystemTime};
7
8use crate::application::port::Clock;
9
10/// The system clock. The only implementation the running application uses.
11#[derive(Debug, Clone, Copy, Default)]
12pub struct SystemClock;
13
14impl Clock for SystemClock {
15 fn now(&self) -> SystemTime {
16 SystemTime::now()
17 }
18}
19
20/// A clock that always answers the same instant.
21///
22/// Enough for every test there is today: what they assert is that a recorded time is
23/// *the one the clock said*, not that two reads differ. A clock that advanced on each
24/// read would make those assertions depend on how many times the use case happened to
25/// look, which is exactly the coupling the port exists to avoid.
26#[derive(Debug, Clone, Copy)]
27pub struct FixedClock(SystemTime);
28
29impl FixedClock {
30 pub fn new(at: SystemTime) -> Self {
31 Self(at)
32 }
33
34 /// A fixed clock at a round number of seconds after the epoch, for a test that only
35 /// needs *a* time and would rather not spell one out.
36 pub fn at_epoch_plus(seconds: u64) -> Self {
37 Self(SystemTime::UNIX_EPOCH + Duration::from_secs(seconds))
38 }
39}
40
41impl Clock for FixedClock {
42 fn now(&self) -> SystemTime {
43 self.0
44 }
45}
46
47#[cfg(test)]
48mod tests {
49 use super::*;
50
51 #[test]
52 fn a_fixed_clock_does_not_move() {
53 let clock = FixedClock::at_epoch_plus(1_700_000_000);
54 assert_eq!(clock.now(), clock.now());
55 assert_eq!(
56 clock.now(),
57 SystemTime::UNIX_EPOCH + Duration::from_secs(1_700_000_000)
58 );
59 }
60
61 #[test]
62 fn the_system_clock_moves_forward() {
63 let before = SystemClock.now();
64 assert!(SystemClock.now() >= before);
65 }
66}