1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
use chrono::{DateTime, Utc};
use std::sync::OnceLock;
use std::time::Duration;
use super::{ArtificialClockConfig, ClockController, ClockHandle, ClockSleep, ClockTimeout};
struct GlobalState {
handle: ClockHandle,
controller: Option<ClockController>,
}
static GLOBAL: OnceLock<GlobalState> = OnceLock::new();
/// Global clock access - like `Utc::now()` but testable.
pub struct Clock;
impl Clock {
/// Get current time from the global clock.
///
/// Lazily initializes to realtime if not already set.
pub fn now() -> DateTime<Utc> {
Self::handle().now()
}
/// Get the current date (without time component).
///
/// Lazily initializes to realtime if not already set.
pub fn today() -> chrono::NaiveDate {
Self::handle().today()
}
/// Sleep using the global clock.
pub fn sleep(duration: Duration) -> ClockSleep {
Self::handle().sleep(duration)
}
/// Timeout using the global clock.
pub fn timeout<F: std::future::Future>(duration: Duration, future: F) -> ClockTimeout<F> {
Self::handle().timeout(duration, future)
}
/// Get a reference to the global clock handle.
pub fn handle() -> &'static ClockHandle {
&GLOBAL
.get_or_init(|| GlobalState {
handle: ClockHandle::realtime(),
controller: None,
})
.handle
}
/// Install an artificial clock globally.
///
/// - If not initialized: installs artificial clock, returns controller
/// - If already artificial: returns existing controller (idempotent)
/// - If already realtime: panics
///
/// Must be called before any `Clock::now()` calls if you want artificial time.
pub fn install_artificial(config: ArtificialClockConfig) -> ClockController {
// Check if already initialized
if let Some(state) = GLOBAL.get() {
return state
.controller
.clone()
.expect("Cannot install artificial clock: realtime clock already initialized");
}
// Try to initialize
let (handle, ctrl) = ClockHandle::artificial(config);
match GLOBAL.set(GlobalState {
handle,
controller: Some(ctrl.clone()),
}) {
Ok(()) => ctrl,
Err(_) => {
// Race: someone else initialized between our check and set
GLOBAL
.get()
.unwrap()
.controller
.clone()
.expect("Cannot install artificial clock: realtime clock already initialized")
}
}
}
/// Check if an artificial clock is installed.
pub fn is_artificial() -> bool {
GLOBAL
.get()
.map(|s| s.controller.is_some())
.unwrap_or(false)
}
/// Get the current artificial time, if an artificial clock is installed
/// and hasn't transitioned to realtime.
///
/// Returns:
/// - `None` if no clock is initialized (doesn't initialize one)
/// - `None` for realtime clocks
/// - `None` for artificial clocks that have transitioned to realtime
/// - `Some(time)` for artificial clocks that are still artificial
pub fn artificial_now() -> Option<DateTime<Utc>> {
GLOBAL.get().and_then(|s| s.handle.artificial_now())
}
}