Skip to main content

ddd_toolkit_core/adapter/
clock.rs

1use crate::port::clock::Clock;
2
3/// A [`Clock`] backed by [`chrono::Utc::now`].
4#[derive(Debug, Clone, Copy, Default)]
5pub struct SystemClock;
6
7impl Clock for SystemClock {
8    fn now(&self) -> chrono::DateTime<chrono::Utc> {
9        chrono::Utc::now()
10    }
11}
12
13#[cfg(test)]
14mod test {
15    use super::*;
16
17    // Wall-clock time (chrono::Utc::now(), which SystemClock wraps) is not
18    // guaranteed monotonic: NTP slew/step corrections can move it backward
19    // between two calls. Assert closeness to a reference instant instead of
20    // strict before/after ordering, so the test isn't flaky under clock
21    // adjustments while still catching a grossly wrong (e.g. fixed/mocked)
22    // implementation.
23    fn assert_close_to_now(
24        now: chrono::DateTime<chrono::Utc>,
25        reference: chrono::DateTime<chrono::Utc>,
26    ) {
27        let diff = (now - reference).num_milliseconds().abs();
28        assert!(
29            diff < 5_000,
30            "expected {now} to be within 5s of {reference}, was {diff}ms apart"
31        );
32    }
33
34    #[test]
35    fn now_returns_time_close_to_wall_clock() {
36        let reference = chrono::Utc::now();
37        let now = SystemClock.now();
38
39        assert_close_to_now(now, reference);
40    }
41
42    #[test]
43    fn now_via_dyn_clock_trait_object_returns_time() {
44        let clock: Box<dyn Clock> = Box::new(SystemClock);
45
46        let reference = chrono::Utc::now();
47        let now = clock.now();
48
49        assert_close_to_now(now, reference);
50    }
51
52    #[test]
53    fn debug_formats_struct_name() {
54        assert_eq!(format!("{:?}", SystemClock), "SystemClock");
55    }
56
57    #[test]
58    fn copy_and_clone_produce_usable_instances() {
59        let original = SystemClock;
60        let copied = original;
61        #[allow(clippy::clone_on_copy)]
62        let cloned = original.clone();
63
64        let reference = chrono::Utc::now();
65        let now_copied = copied.now();
66        let now_cloned = cloned.now();
67
68        assert_close_to_now(now_copied, reference);
69        assert_close_to_now(now_cloned, reference);
70    }
71
72    #[test]
73    fn default_constructs_usable_system_clock() {
74        #[allow(clippy::default_constructed_unit_structs)]
75        let clock = SystemClock::default();
76
77        let reference = chrono::Utc::now();
78        let now = clock.now();
79
80        assert_close_to_now(now, reference);
81    }
82
83    #[test]
84    fn system_clock_is_send_and_sync() {
85        fn assert_send_sync<T: Send + Sync>() {}
86
87        assert_send_sync::<SystemClock>();
88    }
89}