| 1 | #![warn (rust_2018_idioms)] |
| 2 | #![cfg (feature = "full" )] |
| 3 | |
| 4 | use tokio::time::*; |
| 5 | |
| 6 | use std::sync::mpsc; |
| 7 | |
| 8 | #[cfg (all(feature = "rt-multi-thread" , not(target_os = "wasi" )))] // Wasi doesn't support threads |
| 9 | #[test] |
| 10 | fn 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] |
| 29 | fn 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 ] |
| 48 | async 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 ] |
| 79 | async 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 | |