Skip to main content

lenso_test/
clock.rs

1//! Test-only wall-clock projection from deterministic virtual time.
2
3use std::time::SystemTime;
4
5use crate::simulator::TestSimulator;
6
7/// An explicit wall-clock projection of one [`TestSimulator`]'s virtual time.
8///
9/// Production code must supply its own clock. This type is intentionally not
10/// installed into a Driver or selected from a Plan; a test passes it only to a
11/// test-support seam that explicitly accepts a clock.
12#[derive(Clone, Debug)]
13pub struct TestWallClock {
14    simulator: TestSimulator,
15    epoch: SystemTime,
16}
17
18impl TestWallClock {
19    pub(crate) fn new(simulator: TestSimulator, epoch: SystemTime) -> Self {
20        Self { simulator, epoch }
21    }
22
23    /// Returns the explicitly configured instant at virtual instant zero.
24    pub const fn epoch(&self) -> SystemTime {
25        self.epoch
26    }
27
28    /// Returns the current wall-clock instant derived from virtual time.
29    ///
30    /// `None` means the explicit epoch plus virtual duration is out of range;
31    /// this method never consults the host wall clock.
32    pub fn now(&self) -> Option<SystemTime> {
33        self.epoch.checked_add(self.simulator.now())
34    }
35}
36
37impl TestSimulator {
38    /// Projects this simulator's virtual monotonic clock onto a chosen epoch.
39    ///
40    /// The supplied epoch is part of the test scenario, not Host configuration
41    /// or production security policy.
42    pub fn wall_clock(&self, epoch: SystemTime) -> TestWallClock {
43        TestWallClock::new(self.clone(), epoch)
44    }
45}
46
47#[cfg(test)]
48mod tests {
49    use std::time::Duration;
50
51    use super::*;
52
53    #[test]
54    fn wall_clock_advances_only_with_its_simulator() {
55        let simulator = TestSimulator::new();
56        let epoch = SystemTime::UNIX_EPOCH + Duration::from_secs(1_700_000_000);
57        let clock = simulator.wall_clock(epoch);
58
59        assert_eq!(clock.epoch(), epoch);
60        assert_eq!(clock.now(), Some(epoch));
61        simulator.advance(Duration::from_millis(250));
62        assert_eq!(clock.now(), Some(epoch + Duration::from_millis(250)),);
63    }
64}