use std::{cell::RefCell, time::Duration};
std::thread_local! {
static TIME: RefCell<Duration> = const { RefCell::new(Duration::ZERO) };
static SYSTEM_TIME: RefCell<Duration> = const { RefCell::new(Duration::ZERO) };
}
fn with_time(d: impl Fn(&mut Duration)) {
TIME.with(|t| d(&mut t.borrow_mut()));
}
fn get_time() -> Duration {
TIME.with(|t| *t.borrow())
}
fn with_system_time(d: impl Fn(&mut Duration)) {
SYSTEM_TIME.with(|t| d(&mut t.borrow_mut()));
}
fn get_system_time() -> Duration {
SYSTEM_TIME.with(|t| *t.borrow())
}
crate::macros::define_mock_clock! {
true;
}
crate::macros::define_instant! {
MockClock::time;
true;
}
crate::macros::define_system_time! {
MockClock::system_time;
true;
}
crate::macros::define_instant_tests!({});
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn is_thread_local() {
assert!(MockClock::is_thread_local());
assert!(Instant::now().is_thread_local());
assert!(SystemTime::now().is_thread_local());
}
#[test]
fn thread_locality() {
MockClock::set_time(Duration::ZERO);
let start = Instant::now();
let handles = [
std::thread::spawn(move || {
let start = Instant::now();
MockClock::advance(Duration::from_secs(3));
assert_eq!(start.elapsed(), Duration::from_secs(3));
}),
std::thread::spawn(move || {
let start = Instant::now();
MockClock::advance(Duration::from_secs(30));
assert_eq!(start.elapsed(), Duration::from_secs(30));
}),
];
MockClock::advance(Duration::from_secs(10));
assert_eq!(start.elapsed(), Duration::from_secs(10));
for handle in handles {
handle.join().unwrap();
}
}
}