1#![warn(rust_2018_idioms)]
2#![cfg(feature = "full")]
3
4use tokio::time::*;
5
6use std::sync::mpsc;
7
8#[cfg(all(feature = "rt-multi-thread", not(target_os = "wasi")))] // Wasi doesn't support threads
9#[test]
10fn timer_with_threaded_runtime() {
11 use tokio::runtime::Runtime;
12
13 let rt = Runtime::new().unwrap();
14 let (tx, rx) = mpsc::channel();
15
16 rt.spawn(async move {
17 let when = Instant::now() + Duration::from_millis(10);
18
19 sleep_until(when).await;
20 assert!(Instant::now() >= when);
21
22 tx.send(()).unwrap();
23 });
24
25 rx.recv().unwrap();
26}
27
28#[test]
29fn timer_with_current_thread_scheduler() {
30 use tokio::runtime::Builder;
31
32 let rt = Builder::new_current_thread().enable_all().build().unwrap();
33 let (tx, rx) = mpsc::channel();
34
35 rt.block_on(async move {
36 let when = Instant::now() + Duration::from_millis(10);
37
38 sleep_until(when).await;
39 assert!(Instant::now() >= when);
40
41 tx.send(()).unwrap();
42 });
43
44 rx.recv().unwrap();
45}
46
47#[tokio::test]
48async fn starving() {
49 use std::future::Future;
50 use std::pin::Pin;
51 use std::task::{Context, Poll};
52
53 struct Starve<T: Future<Output = ()> + Unpin>(T, u64);
54
55 impl<T: Future<Output = ()> + Unpin> Future for Starve<T> {
56 type Output = u64;
57
58 fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<u64> {
59 if Pin::new(&mut self.0).poll(cx).is_ready() {
60 return Poll::Ready(self.1);
61 }
62
63 self.1 += 1;
64
65 cx.waker().wake_by_ref();
66
67 Poll::Pending
68 }
69 }
70
71 let when = Instant::now() + Duration::from_millis(10);
72 let starve = Starve(Box::pin(sleep_until(when)), 0);
73
74 starve.await;
75 assert!(Instant::now() >= when);
76}
77
78#[tokio::test]
79async fn timeout_value() {
80 use tokio::sync::oneshot;
81
82 let (_tx, rx) = oneshot::channel::<()>();
83
84 let now = Instant::now();
85 let dur = Duration::from_millis(10);
86
87 let res = timeout(dur, rx).await;
88 assert!(res.is_err());
89 assert!(Instant::now() >= now + dur);
90}
91