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}