async_time_mock_core/
timer.rs1use crate::time_handler_guard::TimeHandlerFinished;
2use crate::TimeHandlerGuard;
3use event_listener::{Event, EventListener};
4use pin_project_lite::pin_project;
5use std::future::Future;
6use std::pin::Pin;
7use std::task::{ready, Context, Poll};
8
9pub(crate) struct Timer {
10 trigger: Event,
11 handler_finished_waiter: TimeHandlerFinished,
12}
13
14impl Timer {
15 pub(crate) fn new() -> (Self, TimerListener) {
16 let (handler_guard, handler_finished_waiter) = TimeHandlerGuard::new();
17 let trigger = Event::new();
18 let listener = trigger.listen();
19 (
20 Self {
21 trigger,
22 handler_finished_waiter,
23 },
24 TimerListener {
25 listener,
26 handler_guard: Some(handler_guard),
27 },
28 )
29 }
30
31 pub(crate) fn trigger(self) -> TimeHandlerFinished {
32 let Self {
33 trigger,
34 handler_finished_waiter,
35 } = self;
36 trigger.notify(1);
37 handler_finished_waiter
38 }
39}
40
41pin_project! {
42 #[derive(Debug)]
43 pub struct TimerListener {
44 #[pin]
45 listener: EventListener,
46 handler_guard: Option<TimeHandlerGuard>,
47 }
48}
49
50impl Future for TimerListener {
51 type Output = TimeHandlerGuard;
52
53 fn poll(self: Pin<&mut Self>, context: &mut Context<'_>) -> Poll<Self::Output> {
54 let this = self.project();
55
56 ready!(this.listener.poll(context));
57
58 match this.handler_guard.take() {
59 Some(handler_guard) => Poll::Ready(handler_guard),
60 None => Poll::Pending,
61 }
62 }
63}
64
65#[cfg(test)]
66mod test {
67 use super::*;
68 use futures_lite::future::poll_once;
69 use std::pin::pin;
70
71 #[tokio::test]
72 async fn timer_should_trigger_timer_listener() {
73 let (timer, listener) = Timer::new();
74
75 let mut listener = pin!(listener);
76 assert!(
77 poll_once(listener.as_mut()).await.is_none(),
78 "Future should have been pending before the timer is triggered",
79 );
80 let _ = timer.trigger();
81
82 assert!(
83 poll_once(listener.as_mut()).await.is_some(),
84 "Future should have been ready after timer was triggered"
85 );
86 }
87
88 #[tokio::test]
89 async fn time_handler_finished_should_be_triggered_by_time_handler_completion() {
90 let (timer, listener) = Timer::new();
91
92 let time_handler_finished = timer.trigger();
93 let time_handler_guard = listener.await;
94
95 let mut waiter = pin!(time_handler_finished.wait());
96 assert!(
97 poll_once(waiter.as_mut()).await.is_none(),
98 "Future should have been pending before the time handler is finished (guard dropped)",
99 );
100
101 drop(time_handler_guard);
102 assert!(
103 poll_once(waiter.as_mut()).await.is_some(),
104 "Future should have been ready after the time handler is finished (guard dropped)",
105 );
106 }
107}