Skip to main content

metrique_timesource/
fakes.rs

1// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
2// SPDX-License-Identifier: Apache-2.0
3
4use std::{
5    sync::{Arc, Mutex},
6    time::{Duration, Instant, SystemTime},
7};
8
9use crate::Time;
10
11/// Simple static timesource that will always return the same time
12#[derive(Debug)]
13pub struct StaticTimeSource {
14    now: SystemTime,
15    now_instant: Instant,
16}
17
18impl StaticTimeSource {
19    /// Create a new StaticTimeSource that always returns the given time
20    ///
21    /// # Arguments
22    ///
23    /// * `time` - The SystemTime that this source will always return
24    ///
25    /// # Returns
26    ///
27    /// A new StaticTimeSource initialized with the given time
28    ///
29    /// # Examples
30    ///
31    /// ```
32    /// use metrique_timesource::{TimeSource, fakes::StaticTimeSource};
33    /// use std::time::UNIX_EPOCH;
34    ///
35    /// let static_time = StaticTimeSource::at_time(UNIX_EPOCH);
36    /// let ts = TimeSource::custom(static_time);
37    /// assert_eq!(ts.system_time(), UNIX_EPOCH);
38    /// ```
39    pub fn at_time(time: impl Into<SystemTime>) -> Self {
40        Self {
41            now: time.into(),
42            now_instant: Instant::now(),
43        }
44    }
45}
46
47impl Time for StaticTimeSource {
48    fn now(&self) -> SystemTime {
49        self.now
50    }
51
52    fn instant(&self) -> Instant {
53        self.now_instant
54    }
55}
56
57/// Dummy timesource that is loaded with one time,
58/// but you can clone it and further modify the time and elapsed Instant duration
59/// via a shared handle
60#[derive(Debug, Clone)]
61pub struct ManuallyAdvancedTimeSource(Arc<Mutex<StaticTimeSource>>);
62
63impl ManuallyAdvancedTimeSource {
64    /// Create a new ManuallyAdvancedTimeSource that is started with the given time.
65    ///
66    /// You can subsequently call [`Self::update_time`] to modify the loaded time.
67    ///
68    /// # Arguments
69    ///
70    /// * `time` - The SystemTime that this source will initially return
71    ///
72    /// # Returns
73    ///
74    /// A new ManuallyAdvancedTimeSource initialized with the given time
75    ///
76    /// # Examples
77    ///
78    /// ```
79    /// use metrique_timesource::{TimeSource, fakes::ManuallyAdvancedTimeSource};
80    /// use std::time::UNIX_EPOCH;
81    ///
82    /// let dummy_time = ManuallyAdvancedTimeSource::at_time(UNIX_EPOCH);
83    /// let ts = TimeSource::custom(dummy_time);
84    /// assert_eq!(ts.system_time(), UNIX_EPOCH);
85    /// ```
86    pub fn at_time(time: impl Into<SystemTime>) -> Self {
87        let ts = StaticTimeSource::at_time(time);
88        Self(Arc::from(Mutex::from(ts)))
89    }
90
91    /// Update the SystemTime loaded into the ManuallyAdvancedTimeSource.
92    ///
93    /// # Examples
94    ///
95    /// ```
96    /// use metrique_timesource::{TimeSource, fakes::ManuallyAdvancedTimeSource};
97    /// use std::time::{Duration, UNIX_EPOCH};
98    ///
99    /// // initial time is UNIX_EPOCH
100    /// let dummy_time = ManuallyAdvancedTimeSource::at_time(UNIX_EPOCH);
101    /// let ts = TimeSource::custom(dummy_time.clone());
102    /// assert_eq!(ts.system_time(), UNIX_EPOCH);
103    ///
104    /// let new_timestamp = UNIX_EPOCH + Duration::from_secs(100);
105    /// dummy_time.update_time(new_timestamp);
106    /// assert_eq!(ts.system_time(), new_timestamp);
107    /// ```
108    pub fn update_time(&self, time: impl Into<SystemTime>) {
109        let mut guard = self.0.lock().unwrap();
110        guard.now = time.into();
111    }
112
113    /// Update the Instant loaded into the ManuallyAdvancedTimeSource by
114    /// moving it forward by a duration.
115    ///
116    /// # Examples
117    ///
118    /// ```
119    /// use metrique_timesource::{TimeSource, fakes::ManuallyAdvancedTimeSource};
120    /// use std::time::{Duration, UNIX_EPOCH};
121    ///
122    /// // initial time is UNIX_EPOCH
123    /// let dummy_time = ManuallyAdvancedTimeSource::at_time(UNIX_EPOCH);
124    /// let ts = TimeSource::custom(dummy_time.clone());
125    /// let instant = ts.instant();
126    ///
127    /// let elapsed = Duration::from_secs(100);
128    /// dummy_time.update_instant(elapsed);
129    /// assert_eq!(instant.elapsed(), elapsed);
130    /// ```
131    pub fn update_instant(&self, elapsed: Duration) {
132        let mut guard = self.0.lock().unwrap();
133        guard.now_instant += elapsed;
134    }
135}
136
137impl Time for ManuallyAdvancedTimeSource {
138    fn now(&self) -> SystemTime {
139        self.0.lock().unwrap().now
140    }
141
142    fn instant(&self) -> Instant {
143        self.0.lock().unwrap().now_instant
144    }
145}