Skip to main content

reifydb_runtime/context/clock/
mod.rs

1// SPDX-License-Identifier: Apache-2.0
2// Copyright (c) 2026 ReifyDB
3
4#[cfg(any(reifydb_target = "host", reifydb_dst))]
5mod host;
6#[cfg(reifydb_target = "wasi")]
7mod wasi;
8#[cfg(reifydb_target = "wasm")]
9mod wasm;
10
11#[cfg(any(reifydb_target = "host", reifydb_dst))]
12pub use host::{Clock, Instant, MockClock};
13use reifydb_value::{clock::ClockNow, value::datetime::DateTime};
14#[cfg(reifydb_target = "wasi")]
15pub use wasi::{Clock, Instant, MockClock};
16#[cfg(reifydb_target = "wasm")]
17pub use wasm::{Clock, Instant, MockClock};
18
19impl ClockNow for Clock {
20	fn now(&self) -> DateTime {
21		Clock::now(self)
22	}
23}
24
25#[cfg(test)]
26mod tests {
27	#[cfg(all(reifydb_target = "host", not(reifydb_dst)))]
28	use std::thread;
29
30	use super::*;
31
32	#[test]
33	fn test_real_clock() {
34		let clock = Clock::Real;
35		let t1 = clock.now().to_millis();
36		// Busy work rather than a sleep; the assertion only requires the clock not to go
37		// backwards, so it holds whether or not a millisecond actually elapsed.
38		let mut sum = 0;
39		for i in 0..10000 {
40			sum += i;
41		}
42		let t2 = clock.now().to_millis();
43		assert!(t2 >= t1, "Time should not go backwards");
44		let _ = sum;
45	}
46
47	#[test]
48	fn test_mock_clock_initial() {
49		let mock = MockClock::from_millis(1000);
50		let clock = Clock::Mock(mock);
51
52		assert_eq!(clock.now().to_millis(), 1000);
53		assert_eq!(clock.now().to_micros(), 1_000_000);
54		assert_eq!(clock.now().to_nanos(), 1_000_000_000);
55	}
56
57	#[test]
58	fn test_mock_clock_set() {
59		let mock = MockClock::from_millis(0);
60		mock.set_millis(5000);
61
62		assert_eq!(mock.now().to_millis(), 5000);
63
64		mock.set_micros(6_000_000);
65		assert_eq!(mock.now().to_millis(), 6000);
66	}
67
68	#[test]
69	fn test_mock_clock_advance() {
70		let mock = MockClock::from_millis(1000);
71		let clock = Clock::Mock(mock.clone());
72
73		assert_eq!(clock.now().to_millis(), 1000);
74
75		mock.advance_millis(500);
76		assert_eq!(clock.now().to_millis(), 1500);
77
78		mock.advance_micros(500_000);
79		assert_eq!(clock.now().to_millis(), 2000);
80
81		mock.advance_nanos(500_000_000);
82		assert_eq!(clock.now().to_millis(), 2500);
83	}
84
85	#[cfg(all(reifydb_target = "host", not(reifydb_dst)))]
86	#[test]
87	fn test_mock_clock_thread_safe() {
88		let mock = MockClock::from_millis(1000);
89		let mock_clone = mock.clone();
90
91		let handle = thread::spawn(move || {
92			mock_clone.advance_millis(500);
93			mock_clone.now().to_millis()
94		});
95
96		let result = handle.join().unwrap();
97		assert_eq!(result, 1500);
98		assert_eq!(mock.now().to_millis(), 1500);
99	}
100
101	#[test]
102	fn test_nanosecond_precision() {
103		let mock = MockClock::new(1_234_567_890_123_456_789);
104		let clock = Clock::Mock(mock);
105
106		assert_eq!(clock.now().to_nanos(), 1_234_567_890_123_456_789);
107		assert_eq!(clock.now().to_micros(), 1_234_567_890_123_456);
108		assert_eq!(clock.now().to_millis(), 1_234_567_890_123);
109		assert_eq!(clock.now().to_epoch_secs(), 1_234_567_890);
110	}
111}