summaryrefslogtreecommitdiffstats
path: root/tokio-test
diff options
context:
space:
mode:
authorCarl Lerche <me@carllerche.com>2019-11-12 15:23:40 -0800
committerGitHub <noreply@github.com>2019-11-12 15:23:40 -0800
commit27e5b41067d01c0c9fac230c5addb58034201a63 (patch)
treef9bd8333dfe1853dfe1d8710b4dc966bd8555d54 /tokio-test
parente3df2eafd32e6f813d08617f0e2cd7abbc05c2b1 (diff)
reorganize modules (#1766)
This patch started as an effort to make `time::Timer` private. However, in an effort to get the build compiling again, more and more changes were made. This probably should have been broken up, but here we are. I will attempt to summarize the changes here. * Feature flags are reorganized to make clearer. `net-driver` becomes `io-driver`. `rt-current-thread` becomes `rt-core`. * The `Runtime` can be created without any executor. This replaces `enter`. It also allows creating I/O / time drivers that are standalone. * `tokio::timer` is renamed to `tokio::time`. This brings it in line with `std`. * `tokio::timer::Timer` is renamed to `Driver` and made private. * The `clock` module is removed. Instead, an `Instant` type is provided. This type defaults to calling `std::time::Instant`. A `test-util` feature flag can be used to enable hooking into time. * The `blocking` module is moved to the top level and is cleaned up. * The `task` module is moved to the top level. * The thread-pool's in-place blocking implementation is cleaned up. * `runtime::Spawner` is renamed to `runtime::Handle` and can be used to "enter" a runtime context.
Diffstat (limited to 'tokio-test')
-rw-r--r--tokio-test/Cargo.toml2
-rw-r--r--tokio-test/src/clock.rs277
-rw-r--r--tokio-test/src/io.rs14
-rw-r--r--tokio-test/src/lib.rs1
-rw-r--r--tokio-test/tests/block_on.rs4
-rw-r--r--tokio-test/tests/clock.rs25
6 files changed, 7 insertions, 316 deletions
diff --git a/tokio-test/Cargo.toml b/tokio-test/Cargo.toml
index ad0a567a..60cb3e50 100644
--- a/tokio-test/Cargo.toml
+++ b/tokio-test/Cargo.toml
@@ -20,7 +20,7 @@ Testing utilities for Tokio- and futures-based code
categories = ["asynchronous", "testing"]
[dependencies]
-tokio = { version = "=0.2.0-alpha.6", path = "../tokio" }
+tokio = { version = "=0.2.0-alpha.6", path = "../tokio", features = ["test-util"] }
bytes = "0.4"
futures-core = "0.3.0"
diff --git a/tokio-test/src/clock.rs b/tokio-test/src/clock.rs
deleted file mode 100644
index d2f29249..00000000
--- a/tokio-test/src/clock.rs
+++ /dev/null
@@ -1,277 +0,0 @@
-//! A mocked clock for use with `tokio::time` based futures.
-//!
-//! # Example
-//!
-//! ```
-//! use tokio::time::{clock, delay};
-//! use tokio_test::{assert_ready, assert_pending, task};
-//!
-//! use std::time::Duration;
-//!
-//! tokio_test::clock::mock(|handle| {
-//! let mut task = task::spawn(async {
-//! delay(clock::now() + Duration::from_secs(1)).await
-//! });
-//!
-//! assert_pending!(task.poll());
-//!
-//! handle.advance(Duration::from_secs(1));
-//!
-//! assert_ready!(task.poll());
-//! });
-//! ```
-
-use tokio::runtime::{Park, Unpark};
-use tokio::time::clock::{Clock, Now};
-use tokio::time::Timer;
-
-use std::marker::PhantomData;
-use std::rc::Rc;
-use std::sync::{Arc, Mutex};
-use std::time::{Duration, Instant};
-
-/// Run the provided closure with a `MockClock` that starts at the current time.
-pub fn mock<F, R>(f: F) -> R
-where
- F: FnOnce(&mut Handle) -> R,
-{
- let mut mock = MockClock::new();
- mock.enter(f)
-}
-
-/// Run the provided closure with a `MockClock` that starts at the provided `Instant`.
-pub fn mock_at<F, R>(instant: Instant, f: F) -> R
-where
- F: FnOnce(&mut Handle) -> R,
-{
- let mut mock = MockClock::with_instant(instant);
- mock.enter(f)
-}
-
-/// Mock clock for use with `tokio-timer` futures.
-///
-/// A mock timer that is able to advance and wake after a
-/// certain duration.
-#[derive(Debug)]
-pub struct MockClock {
- time: MockTime,
- clock: Clock,
-}
-
-/// A handle to the `MockClock`.
-#[derive(Debug)]
-pub struct Handle {
- timer: Timer<MockPark>,
- time: MockTime,
-}
-
-type Inner = Arc<Mutex<State>>;
-
-#[derive(Debug, Clone)]
-struct MockTime {
- inner: Inner,
- _pd: PhantomData<Rc<()>>,
-}
-
-#[derive(Debug)]
-struct MockNow {
- inner: Inner,
-}
-
-#[derive(Debug)]
-struct MockPark {
- inner: Inner,
- _pd: PhantomData<Rc<()>>,
-}
-
-#[derive(Debug)]
-struct MockUnpark {
- inner: Inner,
-}
-
-#[derive(Debug)]
-struct State {
- base: Instant,
- advance: Duration,
- unparked: bool,
- park_for: Option<Duration>,
-}
-
-impl MockClock {
- /// Create a new `MockClock` with the current time.
- pub fn new() -> Self {
- MockClock::with_instant(Instant::now())
- }
-
- /// Create a `MockClock` with its current time at a duration from now
- ///
- /// This will create a clock with `Instant::now() + duration` as the current time.
- pub fn with_duration(duration: Duration) -> Self {
- let instant = Instant::now() + duration;
- MockClock::with_instant(instant)
- }
-
- /// Create a `MockClock` that sets its current time as the `Instant` provided.
- pub fn with_instant(instant: Instant) -> Self {
- let time = MockTime::new(instant);
- let clock = Clock::new_with_now(time.mock_now());
-
- MockClock { time, clock }
- }
-
- /// Enter the `MockClock` context.
- pub fn enter<F, R>(&mut self, f: F) -> R
- where
- F: FnOnce(&mut Handle) -> R,
- {
- tokio::time::clock::with_default(&self.clock, || {
- let park = self.time.mock_park();
- let timer = Timer::new(park);
- let handle = timer.handle();
- let time = self.time.clone();
-
- let _timer = tokio::time::set_default(&handle);
- let mut handle = Handle::new(timer, time);
- f(&mut handle)
- // lazy(|| Ok::<_, ()>(f(&mut handle))).wait().unwrap()
- })
- }
-}
-
-impl Default for MockClock {
- fn default() -> Self {
- Self::new()
- }
-}
-
-impl Handle {
- pub(self) fn new(timer: Timer<MockPark>, time: MockTime) -> Self {
- Handle { timer, time }
- }
-
- /// Turn the internal timer and mock park for the provided duration.
- pub fn turn(&mut self) {
- self.timer.turn(None).unwrap();
- }
-
- /// Turn the internal timer and mock park for the provided duration.
- pub fn turn_for(&mut self, duration: Duration) {
- self.timer.turn(Some(duration)).unwrap();
- }
-
- /// Advance the `MockClock` by the provided duration.
- pub fn advance(&mut self, duration: Duration) {
- let inner = self.timer.get_park().inner.clone();
- let deadline = inner.lock().unwrap().now() + duration;
-
- while inner.lock().unwrap().now() < deadline {
- let dur = deadline - inner.lock().unwrap().now();
- self.turn_for(dur);
- }
- }
-
- /// Returns the total amount of time the time has been advanced.
- pub fn advanced(&self) -> Duration {
- self.time.inner.lock().unwrap().advance
- }
-
- /// Get the currently mocked time
- pub fn now(&mut self) -> Instant {
- self.time.now()
- }
-
- /// Turn the internal timer once, but force "parking" for `duration` regardless of any pending
- /// timeouts
- pub fn park_for(&mut self, duration: Duration) {
- self.time.inner.lock().unwrap().park_for = Some(duration);
- self.turn()
- }
-}
-
-impl MockTime {
- pub(crate) fn new(now: Instant) -> MockTime {
- let state = State {
- base: now,
- advance: Duration::default(),
- unparked: false,
- park_for: None,
- };
-
- MockTime {
- inner: Arc::new(Mutex::new(state)),
- _pd: PhantomData,
- }
- }
-
- pub(crate) fn mock_now(&self) -> MockNow {
- let inner = self.inner.clone();
- MockNow { inner }
- }
-
- pub(crate) fn mock_park(&self) -> MockPark {
- let inner = self.inner.clone();
- MockPark {
- inner,
- _pd: PhantomData,
- }
- }
-
- pub(crate) fn now(&self) -> Instant {
- self.inner.lock().unwrap().now()
- }
-}
-
-impl State {
- fn now(&self) -> Instant {
- self.base + self.advance
- }
-
- fn advance(&mut self, duration: Duration) {
- self.advance += duration;
- }
-}
-
-impl Park for MockPark {
- type Unpark = MockUnpark;
- type Error = ();
-
- fn unpark(&self) -> Self::Unpark {
- let inner = self.inner.clone();
- MockUnpark { inner }
- }
-
- fn park(&mut self) -> Result<(), Self::Error> {
- let mut inner = self.inner.lock().map_err(|_| ())?;
-
- let duration = inner.park_for.take().expect("call park_for first");
-
- inner.advance(duration);
- Ok(())
- }
-
- fn park_timeout(&mut self, duration: Duration) -> Result<(), Self::Error> {
- let mut inner = self.inner.lock().unwrap();
-
- if let Some(duration) = inner.park_for.take() {
- inner.advance(duration);
- } else {
- inner.advance(duration);
- }
-
- Ok(())
- }
-}
-
-impl Unpark for MockUnpark {
- fn unpark(&self) {
- if let Ok(mut inner) = self.inner.lock() {
- inner.unparked = true;
- }
- }
-}
-
-impl Now for MockNow {
- fn now(&self) -> Instant {
- self.inner.lock().unwrap().now()
- }
-}
diff --git a/tokio-test/src/io.rs b/tokio-test/src/io.rs
index a073193c..1d42dd03 100644
--- a/tokio-test/src/io.rs
+++ b/tokio-test/src/io.rs
@@ -18,7 +18,7 @@
use tokio::io::{AsyncRead, AsyncWrite};
use tokio::sync::mpsc;
-use tokio::time::{clock, timer, Delay};
+use tokio::time::{self, Delay, Duration, Instant};
use bytes::Buf;
use futures_core::ready;
@@ -26,7 +26,6 @@ use std::collections::VecDeque;
use std::future::Future;
use std::pin::Pin;
use std::task::{self, Poll, Waker};
-use std::time::{Duration, Instant};
use std::{cmp, io};
/// An I/O object that follows a predefined script.
@@ -62,8 +61,6 @@ enum Action {
struct Inner {
actions: VecDeque<Action>,
waiting: Option<Instant>,
-
- timer_handle: timer::Handle,
sleep: Option<Delay>,
read_wait: Option<Waker>,
rx: mpsc::UnboundedReceiver<Action>,
@@ -145,7 +142,6 @@ impl Inner {
let inner = Inner {
actions,
- timer_handle: timer::Handle::default(),
sleep: None,
read_wait: None,
rx,
@@ -301,8 +297,8 @@ impl AsyncRead for Mock {
match self.inner.read(buf) {
Err(ref e) if e.kind() == io::ErrorKind::WouldBlock => {
if let Some(rem) = self.inner.remaining_wait() {
- let until = clock::now() + rem;
- self.inner.sleep = Some(self.inner.timer_handle.delay(until));
+ let until = Instant::now() + rem;
+ self.inner.sleep = Some(time::delay(until));
} else {
self.inner.read_wait = Some(cx.waker().clone());
return Poll::Pending;
@@ -343,8 +339,8 @@ impl AsyncWrite for Mock {
match self.inner.write(buf) {
Err(ref e) if e.kind() == io::ErrorKind::WouldBlock => {
if let Some(rem) = self.inner.remaining_wait() {
- let until = clock::now() + rem;
- self.inner.sleep = Some(self.inner.timer_handle.delay(until));
+ let until = Instant::now() + rem;
+ self.inner.sleep = Some(time::delay(until));
} else {
panic!("unexpected WouldBlock");
}
diff --git a/tokio-test/src/lib.rs b/tokio-test/src/lib.rs
index 749112d8..e6e9019e 100644
--- a/tokio-test/src/lib.rs
+++ b/tokio-test/src/lib.rs
@@ -13,7 +13,6 @@
//! Tokio and Futures based testing utilites
-pub mod clock;
pub mod io;
mod macros;
pub mod task;
diff --git a/tokio-test/tests/block_on.rs b/tokio-test/tests/block_on.rs
index c361d500..3c0fe32f 100644
--- a/tokio-test/tests/block_on.rs
+++ b/tokio-test/tests/block_on.rs
@@ -1,10 +1,8 @@
#![warn(rust_2018_idioms)]
-use tokio::time::delay;
+use tokio::time::{delay, Duration, Instant};
use tokio_test::block_on;
-use std::time::{Duration, Instant};
-
#[test]
fn async_block() {
assert_eq!(4, block_on(async { 4 }));
diff --git a/tokio-test/tests/clock.rs b/tokio-test/tests/clock.rs
deleted file mode 100644
index d9d2fcfc..00000000
--- a/tokio-test/tests/clock.rs
+++ /dev/null
@@ -1,25 +0,0 @@
-#![warn(rust_2018_idioms)]
-
-use tokio::time::delay;
-use tokio_test::clock::MockClock;
-use tokio_test::task;
-use tokio_test::{assert_pending, assert_ready};
-
-use std::time::{Duration, Instant};
-
-#[test]
-fn clock() {
- let mut mock = MockClock::new();
-
- mock.enter(|handle| {
- let deadline = Instant::now() + Duration::from_secs(1);
- let mut delay = task::spawn(delay(deadline));
-
- assert_pending!(delay.poll());
-
- handle.advance(Duration::from_secs(2));
-
- assert!(delay.is_woken());
- assert_ready!(delay.poll());
- });
-}