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
//! Injectable time source for the respawn-backoff logic in [`super::respawn`].
//!
//! Production always uses [`SystemClock`]; tests use [`FakeClock`] to
//! advance time deterministically instead of sleeping in real time.
use std::time::Instant;
/// A source of the current instant, abstracting over [`Instant::now`] so
/// respawn-backoff tests can advance time deterministically instead of
/// sleeping in real time.
pub(super) trait Clock: std::fmt::Debug + Send + Sync {
/// The current instant, per this clock's notion of time.
fn now(&self) -> Instant;
}
/// Production [`Clock`]: delegates directly to [`Instant::now`].
#[derive(Debug, Clone, Copy, Default)]
pub(super) struct SystemClock;
impl Clock for SystemClock {
fn now(&self) -> Instant {
Instant::now()
}
}
/// Test-only [`Clock`] with a settable, advanceable [`Instant`], so
/// respawn-backoff tests can assert on elapsed-time behavior without
/// sleeping in real time.
#[cfg(test)]
#[derive(Debug)]
pub(super) struct FakeClock {
now: std::sync::Mutex<Instant>,
}
#[cfg(test)]
impl FakeClock {
/// A `FakeClock` initialized to the current real instant.
pub(super) fn new() -> Self {
Self {
now: std::sync::Mutex::new(Instant::now()),
}
}
/// Advance this clock's reported time by `duration`.
pub(super) fn advance(&self, duration: std::time::Duration) {
let mut now = crate::util::lock_std(&self.now);
*now += duration;
}
}
#[cfg(test)]
impl Clock for FakeClock {
fn now(&self) -> Instant {
*crate::util::lock_std(&self.now)
}
}