diff --git a/crates/tick/src/clock.rs b/crates/tick/src/clock.rs index c28642c51..c925d4f2c 100644 --- a/crates/tick/src/clock.rs +++ b/crates/tick/src/clock.rs @@ -632,6 +632,8 @@ mod tests { let precise_clock = Clock::new_system_frozen(); let fast_clock = precise_clock.clone().with_fast_instant(true); + assert!(!precise_clock.simple_clock().uses_fast_instant()); + assert!(fast_clock.simple_clock().uses_fast_instant()); _ = precise_clock.instant(); _ = fast_clock.instant(); } diff --git a/crates/tick/src/clock_control.rs b/crates/tick/src/clock_control.rs index b69aefbe3..9a571ecdd 100644 --- a/crates/tick/src/clock_control.rs +++ b/crates/tick/src/clock_control.rs @@ -749,6 +749,58 @@ mod tests { assert_eq!(control.timers_len(), 0); } + #[test] + fn manual_advance_evaluates_auto_advance_timers() { + let mut state = State { + auto_advance_timers: true, + ..State::default() + }; + let start = state.instant; + state.timers.register(start + Duration::from_secs(2), Waker::noop().clone()); + + state.advance(Duration::from_secs(1), TimeFlow::Forward); + + assert_eq!(state.instant.saturating_duration_since(start), Duration::from_secs(2)); + assert_eq!(state.timers.len(), 0); + } + + #[test] + fn auto_advanced_timer_consumes_limit() { + let control = ClockControl::new() + .auto_advance_timers(true) + .auto_advance(Duration::from_secs(1)) + .auto_advance_limit(Duration::from_secs(2)); + let clock = control.to_clock(); + let start = clock.instant(); + + control.register_timer(start + Duration::from_secs(2), Waker::noop().clone()); + let after_timer = clock.instant(); + let after_limit = clock.instant(); + + assert_eq!(after_timer.saturating_duration_since(start), Duration::from_secs(2)); + assert_eq!(after_limit, after_timer); + } + + #[test] + fn advance_time_fires_ready_timers() { + let mut state = State::default(); + state.timers.register(state.instant + Duration::from_secs(1), Waker::noop().clone()); + + state.advance_time(Duration::from_secs(1), TimeFlow::Forward); + + assert_eq!(state.timers.len(), 0); + } + + #[test] + fn zero_advance_does_not_evaluate_timers() { + let mut state = State::default(); + state.timers.register(state.instant, Waker::noop().clone()); + + state.advance_time(Duration::ZERO, TimeFlow::Forward); + + assert_eq!(state.timers.len(), 1); + } + #[test] fn auto_advance_limit() { let control = ClockControl::new() diff --git a/crates/tick/src/delay.rs b/crates/tick/src/delay.rs index c06345809..f64a5fe53 100644 --- a/crates/tick/src/delay.rs +++ b/crates/tick/src/delay.rs @@ -211,6 +211,20 @@ mod tests { assert!(delay.current_timer.is_none()); } + #[test] + fn overflowing_reregistration_clears_existing_timer() { + let clock = Clock::new_system_frozen(); + let mut delay = Delay::new(&clock, Duration::from_millis(1)); + let waker = Waker::noop(); + assert_eq!(delay.register_timer(waker), Poll::Pending); + assert!(delay.current_timer.is_some()); + + delay.duration = Duration::MAX; + assert_eq!(delay.register_timer(waker), Poll::Pending); + + assert_eq!(delay.current_timer, None); + } + #[test] fn ready_without_advancing_timers_ensure_timer_unregistered() { let clock = Clock::new_system_frozen(); diff --git a/crates/tick/src/fast_instant.rs b/crates/tick/src/fast_instant.rs index 956355e7c..a00f67461 100644 --- a/crates/tick/src/fast_instant.rs +++ b/crates/tick/src/fast_instant.rs @@ -123,6 +123,6 @@ mod tests { #[test] fn platform_time_can_be_read() { - _ = platform_time(); + assert_ne!(platform_time(), Duration::ZERO); } } diff --git a/crates/tick/src/periodic_timer.rs b/crates/tick/src/periodic_timer.rs index 055557778..322045188 100644 --- a/crates/tick/src/periodic_timer.rs +++ b/crates/tick/src/periodic_timer.rs @@ -225,6 +225,18 @@ mod tests { assert_eq!(poll_timer(&mut timer), Poll::Ready(Some(()))); } + #[test] + fn timer_fires_at_exact_deadline() { + let control = ClockControl::new(); + let clock = control.to_clock(); + let mut timer = PeriodicTimer::new(&clock, Duration::from_millis(1)); + + assert_eq!(poll_timer(&mut timer), Poll::Pending); + control.advance(Duration::from_millis(1)); + + assert_eq!(poll_timer(&mut timer), Poll::Ready(Some(()))); + } + #[test] fn first_poll_next_should_be_pending() { let clock = Clock::new_frozen(); diff --git a/crates/tick/src/simple_clock.rs b/crates/tick/src/simple_clock.rs index e9674e229..37e7a9903 100644 --- a/crates/tick/src/simple_clock.rs +++ b/crates/tick/src/simple_clock.rs @@ -101,6 +101,11 @@ impl SimpleClock { } } + #[cfg(test)] + pub(crate) const fn uses_fast_instant(&self) -> bool { + matches!(self.0, TimeKind::SystemFast) + } + /// Creates a new frozen `SimpleClock`. /// /// This is a convenience method equivalent to calling `ClockControl::new().to_simple_clock()`. diff --git a/crates/tick/src/state.rs b/crates/tick/src/state.rs index 14e75af3e..ec64c2d36 100644 --- a/crates/tick/src/state.rs +++ b/crates/tick/src/state.rs @@ -145,4 +145,16 @@ mod tests { fn clock_state_send_and_sync() { static_assertions::assert_impl_all!(ClockState: Send, Sync); } + + #[test] + fn shared_timer_uniqueness_tracks_clones() { + let timers = SynchronizedTimers::new_shared(); + assert!(timers.is_unique()); + + let clone = timers.clone(); + assert!(!timers.is_unique()); + + drop(clone); + assert!(timers.is_unique()); + } } diff --git a/crates/tick/src/timers.rs b/crates/tick/src/timers.rs index 6a37b25ba..c88212830 100644 --- a/crates/tick/src/timers.rs +++ b/crates/tick/src/timers.rs @@ -153,6 +153,30 @@ mod tests { assert_eq!(timers.len(), 0); } + #[test] + fn timer_discriminators_are_sequential() { + let mut timers = Timers::default(); + let when = Instant::now(); + + let first = timers.register(when, Waker::noop().clone()); + let second = timers.register(when, Waker::noop().clone()); + + assert_eq!(first.discriminator, 1); + assert_eq!(second.discriminator, 2); + } + + #[test] + fn timer_one_nanosecond_after_now_stays_pending() { + let mut timers = Timers::default(); + let now = Instant::now(); + let next = now + Duration::from_nanos(1); + let key = TimerKey::new(next, 0); + timers.wakers.insert(key, Waker::noop().clone()); + + assert_eq!(timers.advance_timers(now), Some(next)); + assert!(timers.contains(key)); + } + #[test] fn advance_timers_ensure_order() { let mut timers = Timers::default();