prism3_clock/
controllable_clock.rs

1/*******************************************************************************
2 *
3 *    Copyright (c) 2025.
4 *    3-Prism Co. Ltd.
5 *
6 *    All rights reserved.
7 *
8 ******************************************************************************/
9//! Controllable clock trait for testing.
10//!
11//! This module defines the [`ControllableClock`] trait, which extends
12//! [`Clock`] to provide methods for controlling the clock's time. This is
13//! primarily useful for testing scenarios.
14//!
15//! # Author
16//!
17//! Haixing Hu
18
19use crate::Clock;
20use chrono::{DateTime, Duration, Utc};
21
22/// A trait representing a clock that can be controlled.
23///
24/// This trait extends [`Clock`] to provide methods for manually setting and
25/// advancing the clock's time. It's primarily designed for testing scenarios
26/// where you need precise control over time.
27///
28/// # Warning
29///
30/// This trait should only be used in testing code, not in production code.
31///
32/// # Examples
33///
34/// ```
35/// use prism3_clock::{Clock, ControllableClock, MockClock};
36/// use chrono::{DateTime, Duration, Utc};
37///
38/// let clock = MockClock::new();
39///
40/// // Set to a specific time
41/// let fixed_time = DateTime::parse_from_rfc3339(
42///     "2024-01-01T00:00:00Z"
43/// ).unwrap().with_timezone(&Utc);
44/// clock.set_time(fixed_time);
45///
46/// assert_eq!(clock.time(), fixed_time);
47///
48/// // Advance by 1 hour
49/// clock.add_duration(Duration::hours(1));
50/// assert_eq!(
51///     clock.time(),
52///     fixed_time + Duration::hours(1)
53/// );
54/// ```
55///
56/// # Author
57///
58/// Haixing Hu
59pub trait ControllableClock: Clock {
60    /// Sets the clock to a specific time.
61    ///
62    /// # Arguments
63    ///
64    /// * `instant` - The time to set the clock to (UTC).
65    ///
66    /// # Examples
67    ///
68    /// ```
69    /// use prism3_clock::{Clock, ControllableClock, MockClock};
70    /// use chrono::{DateTime, Utc};
71    ///
72    /// let clock = MockClock::new();
73    /// let time = DateTime::parse_from_rfc3339(
74    ///     "2024-01-01T00:00:00Z"
75    /// ).unwrap().with_timezone(&Utc);
76    ///
77    /// clock.set_time(time);
78    /// assert_eq!(clock.time(), time);
79    /// ```
80    fn set_time(&self, instant: DateTime<Utc>);
81
82    /// Advances the clock by the specified duration.
83    ///
84    /// # Arguments
85    ///
86    /// * `duration` - The duration to advance the clock by.
87    ///
88    /// # Examples
89    ///
90    /// ```
91    /// use prism3_clock::{Clock, ControllableClock, MockClock};
92    /// use chrono::Duration;
93    ///
94    /// let clock = MockClock::new();
95    /// let before = clock.time();
96    ///
97    /// clock.add_duration(Duration::hours(1));
98    ///
99    /// let after = clock.time();
100    /// assert_eq!(after - before, Duration::hours(1));
101    /// ```
102    fn add_duration(&self, duration: Duration);
103
104    /// Resets the clock to its initial state.
105    ///
106    /// The exact behavior of this method depends on the implementation. For
107    /// [`MockClock`](crate::MockClock), it resets to the time when the clock
108    /// was created.
109    ///
110    /// # Examples
111    ///
112    /// ```
113    /// use prism3_clock::{Clock, ControllableClock, MockClock};
114    /// use chrono::Duration;
115    ///
116    /// let clock = MockClock::new();
117    /// let initial = clock.time();
118    ///
119    /// clock.add_duration(Duration::hours(1));
120    /// clock.reset();
121    ///
122    /// // After reset, time should be close to initial time
123    /// let diff = (clock.time() - initial).num_milliseconds().abs();
124    /// assert!(diff < 100); // Allow small difference
125    /// ```
126    fn reset(&self);
127}