diff --git a/tokio-test/Cargo.toml b/tokio-test/Cargo.toml index 92573a839..1ebbf94f5 100644 --- a/tokio-test/Cargo.toml +++ b/tokio-test/Cargo.toml @@ -22,13 +22,13 @@ categories = ["asynchronous", "testing"] publish = false [dependencies] -assertive = { git = "http://github.com/carllerche/assertive" } pin-convert = "0.1.0" tokio-executor = { version = "0.2.0", path = "../tokio-executor" } tokio-io = { version = "0.2.0", path = "../tokio-io" } tokio-sync = { version = "0.2.0", path = "../tokio-sync" } tokio-timer = { version = "0.3.0", path = "../tokio-timer" } -futures-core-preview = "0.3.0-alpha.17" +futures-core-preview = "=0.3.0-alpha.17" [dev-dependencies] tokio = { path = "../tokio" } +futures-util-preview = "=0.3.0-alpha.17" diff --git a/tokio-test/src/clock.rs b/tokio-test/src/clock.rs index 9c1ebb82e..a9badd369 100644 --- a/tokio-test/src/clock.rs +++ b/tokio-test/src/clock.rs @@ -2,7 +2,7 @@ //! //! # Example //! -//! ``` +//! ```ignore //! use tokio_test::clock; //! use tokio_test::{assert_ready, assert_not_ready}; //! use tokio_timer::Delay; diff --git a/tokio-test/src/lib.rs b/tokio-test/src/lib.rs index 7cfd428c7..5f81b556a 100644 --- a/tokio-test/src/lib.rs +++ b/tokio-test/src/lib.rs @@ -12,7 +12,7 @@ //! //! # Example //! -//! ``` +//! ```ignore //! # use futures::{Future, future}; //! use tokio_test::assert_ready; //! @@ -25,8 +25,6 @@ pub mod io; mod macros; pub mod task; -pub use assertive::{assert_err, assert_ok}; - /* #[doc(hidden)] pub mod codegen { diff --git a/tokio-test/src/macros.rs b/tokio-test/src/macros.rs index acf5f5516..f563fe515 100644 --- a/tokio-test/src/macros.rs +++ b/tokio-test/src/macros.rs @@ -1,6 +1,29 @@ //! A collection of useful macros for testing futures and tokio based code /// Assert a `Poll` is ready, returning the value. +/// +/// This will invoke `panic!` if the provided `Poll` does not evaluate to `Poll::Ready` at +/// runtime. +/// +/// # Custom Messages +/// +/// This macro has a second form, where a custom panic message can be provided with or without +/// arguments for formatting. +/// +/// # Examples +/// +/// ``` +/// use std::future::Future; +/// use futures_util::{future, pin_mut}; +/// use tokio_test::{assert_ready, task}; +/// +/// task::mock(|cx| { +/// let fut = future::ready(()); +/// +/// pin_mut!(fut); +/// assert_ready!(fut.poll(cx)); +/// }) +/// ``` #[macro_export] macro_rules! assert_ready { ($e:expr) => {{ @@ -23,6 +46,29 @@ macro_rules! assert_ready { } /// Assert a `Poll>` is ready and `Ok`, returning the value. +/// +/// This will invoke `panic!` if the provided `Poll` does not evaluate to `Poll::Ready(Ok(..))` at +/// runtime. +/// +/// # Custom Messages +/// +/// This macro has a second form, where a custom panic message can be provided with or without +/// arguments for formatting. +/// +/// # Examples +/// +/// ``` +/// use std::future::Future; +/// use futures_util::{future, pin_mut}; +/// use tokio_test::{assert_ready_ok, task}; +/// +/// task::mock(|cx| { +/// let fut = future::ok::<_, ()>(()); +/// +/// pin_mut!(fut); +/// assert_ready_ok!(fut.poll(cx)); +/// }) +/// ``` #[macro_export] macro_rules! assert_ready_ok { ($e:expr) => {{ @@ -38,6 +84,29 @@ macro_rules! assert_ready_ok { } /// Assert a `Poll>` is ready and `Err`, returning the error. +/// +/// This will invoke `panic!` if the provided `Poll` does not evaluate to `Poll::Ready(Err(..))` at +/// runtime. +/// +/// # Custom Messages +/// +/// This macro has a second form, where a custom panic message can be provided with or without +/// arguments for formatting. +/// +/// # Examples +/// +/// ``` +/// use std::future::Future; +/// use futures_util::{future, pin_mut}; +/// use tokio_test::{assert_ready_err, task}; +/// +/// task::mock(|cx| { +/// let fut = future::err::<(), _>(()); +/// +/// pin_mut!(fut); +/// assert_ready_err!(fut.poll(cx)); +/// }) +/// ``` #[macro_export] macro_rules! assert_ready_err { ($e:expr) => {{ @@ -52,7 +121,31 @@ macro_rules! assert_ready_err { }}; } -/// Asset a `Poll` is pending. +/// Assert a `Poll` is pending. +/// +/// This will invoke `panic!` if the provided `Poll` does not evaluate to `Poll::Pending` at +/// runtime. +/// +/// # Custom Messages +/// +/// This macro has a second form, where a custom panic message can be provided with or without +/// arguments for formatting. +/// +/// # Examples +/// +/// ``` +/// use std::future::Future; +/// use std::task::Poll; +/// use futures_util::{future, pin_mut}; +/// use tokio_test::{assert_pending, task}; +/// +/// task::mock(|cx| { +/// let fut = future::pending::<()>(); +/// +/// pin_mut!(fut); +/// assert_pending!(fut.poll(cx)); +/// }) +/// ``` #[macro_export] macro_rules! assert_pending { ($e:expr) => {{ @@ -75,6 +168,29 @@ macro_rules! assert_pending { } /// Assert if a poll is ready and check for equality on the value +/// +/// This will invoke `panic!` if the provided `Poll` does not evaluate to `Poll::Ready` at +/// runtime and the value produced does not partially equal the expected value. +/// +/// # Custom Messages +/// +/// This macro has a second form, where a custom panic message can be provided with or without +/// arguments for formatting. +/// +/// # Examples +/// +/// ``` +/// use std::future::Future; +/// use futures_util::{future, pin_mut}; +/// use tokio_test::{assert_ready_eq, task}; +/// +/// task::mock(|cx| { +/// let fut = future::ready(42); +/// +/// pin_mut!(fut); +/// assert_ready_eq!(fut.poll(cx), 42); +/// }) +/// ``` #[macro_export] macro_rules! assert_ready_eq { ($e:expr, $expect:expr) => { @@ -87,3 +203,87 @@ macro_rules! assert_ready_eq { assert_eq!(val, $expect, $($msg),*) }; } + +/// Asserts that the expression evaluates to `Ok` and returns the value. +/// +/// This will invoke the `panic!` macro if the provided expression does not evaluate to `Ok` at +/// runtime. +/// +/// # Custom Messages +/// +/// This macro has a second form, where a custom panic message can be provided with or without +/// arguments for formatting. +/// +/// # Examples +/// +/// ``` +/// use tokio_test::assert_ok; +/// +/// let n: u32 = assert_ok!("123".parse()); +/// +/// let s = "123"; +/// let n: u32 = assert_ok!(s.parse(), "testing parsing {:?} as a u32", s); +/// ``` +#[macro_export] +macro_rules! assert_ok { + ($e:expr) => { + assert_ok!($e,) + }; + ($e:expr,) => {{ + use std::result::Result::*; + match $e { + Ok(v) => v, + Err(e) => panic!("assertion failed: Err({:?})", e), + } + }}; + ($e:expr, $($arg:tt)+) => {{ + use std::result::Result::*; + match $e { + Ok(v) => v, + Err(e) => panic!("assertion failed: Err({:?}): {}", e, format_args!($($arg)+)), + } + }}; +} + +/// Asserts that the expression evaluates to `Err` and returns the error. +/// +/// This will invoke the `panic!` macro if the provided expression does not evaluate to `Err` at +/// runtime. +/// +/// # Custom Messages +/// +/// This macro has a second form, where a custom panic message can be provided with or without +/// arguments for formatting. +/// +/// # Examples +/// +/// ``` +/// use tokio_test::assert_err; +/// use std::str::FromStr; +/// +/// +/// let err = assert_err!(u32::from_str("fail")); +/// +/// let msg = "fail"; +/// let err = assert_err!(u32::from_str(msg), "testing parsing {:?} as u32", msg); +/// ``` +#[macro_export] +macro_rules! assert_err { + ($e:expr) => { + assert_err!($e,); + }; + ($e:expr,) => {{ + use std::result::Result::*; + match $e { + Ok(v) => panic!("assertion failed: Ok({:?})", v), + Err(e) => e, + } + }}; + ($e:expr, $($arg:tt)+) => {{ + use std::result::Result::*; + match $e { + Ok(v) => panic!("assertion failed: Ok({:?}): {}", v, format_args!($($arg)+)), + Err(e) => e, + } + }}; +} diff --git a/tokio-test/src/task.rs b/tokio-test/src/task.rs index f715ef342..e7d6c811d 100644 --- a/tokio-test/src/task.rs +++ b/tokio-test/src/task.rs @@ -5,7 +5,7 @@ //! This example will use the `MockTask` to set the current task on //! poll. //! -//! ``` +//! ```ignore //! # use tokio_test::assert_ready_eq; //! # use tokio_test::task::MockTask; //! # use futures::{sync::mpsc, Stream, Sink, Future, Async}; @@ -26,10 +26,34 @@ use std::pin::Pin; use std::sync::{Arc, Condvar, Mutex}; use std::task::{Context, Poll, RawWaker, RawWakerVTable, Waker}; +/// Run the provided closure in a `MockTask` context. +/// +/// # Examples +/// +/// ``` +/// use std::future::Future; +/// use futures_util::{future, pin_mut}; +/// use tokio_test::task; +/// +/// task::mock(|cx| { +/// let fut = future::ready(()); +/// +/// pin_mut!(fut); +/// assert!(fut.poll(cx).is_ready()); +/// }) +/// ``` +pub fn mock(f: F) -> R +where + F: Fn(&mut Context<'_>) -> R, +{ + let mut task = MockTask::new(); + task.enter(|cx| f(cx)) +} + /// Mock task /// /// A mock task is able to intercept and track wake notifications. -#[derive(Debug)] +#[derive(Debug, Clone)] pub struct MockTask { waker: Arc, }