summaryrefslogtreecommitdiffstats
path: root/tokio-current-thread/tests/current_thread.rs
diff options
context:
space:
mode:
Diffstat (limited to 'tokio-current-thread/tests/current_thread.rs')
-rw-r--r--tokio-current-thread/tests/current_thread.rs435
1 files changed, 299 insertions, 136 deletions
diff --git a/tokio-current-thread/tests/current_thread.rs b/tokio-current-thread/tests/current_thread.rs
index 598587fd..a98ed792 100644
--- a/tokio-current-thread/tests/current_thread.rs
+++ b/tokio-current-thread/tests/current_thread.rs
@@ -12,28 +12,49 @@ use std::time::Duration;
use futures::task;
use futures::future::{self, lazy};
+// This is not actually unused --- we need this trait to be in scope for
+// the tests that sue TaskExecutor::current().execute(). The compiler
+// doesn't realise that.
+#[allow(unused_imports)]
+use futures::future::Executor as _futures_Executor;
use futures::prelude::*;
use futures::sync::oneshot;
-#[test]
-fn spawn_from_block_on_all() {
- let cnt = Rc::new(Cell::new(0));
- let c = cnt.clone();
-
- let msg = tokio_current_thread::block_on_all(lazy(move || {
- c.set(1 + c.get());
+mod from_block_on_all {
+ use super::*;
+ fn test<F: Fn(Box<Future<Item=(), Error=()>>) + 'static>(spawn: F) {
+ let cnt = Rc::new(Cell::new(0));
+ let c = cnt.clone();
- // Spawn!
- tokio_current_thread::spawn(lazy(move || {
+ let msg = tokio_current_thread::block_on_all(lazy(move || {
c.set(1 + c.get());
- Ok::<(), ()>(())
- }));
- Ok::<_, ()>("hello")
- })).unwrap();
+ // Spawn!
+ spawn(Box::new(lazy(move || {
+ c.set(1 + c.get());
+ Ok::<(), ()>(())
+ })));
+
+ Ok::<_, ()>("hello")
+ })).unwrap();
- assert_eq!(2, cnt.get());
- assert_eq!(msg, "hello");
+ assert_eq!(2, cnt.get());
+ assert_eq!(msg, "hello");
+ }
+
+ #[test]
+ fn spawn() {
+ test(tokio_current_thread::spawn)
+ }
+
+ #[test]
+ fn execute() {
+ test(|f| {
+ tokio_current_thread::TaskExecutor::current()
+ .execute(f)
+ .unwrap();
+ });
+ }
}
#[test]
@@ -76,39 +97,61 @@ fn spawn_many() {
assert_eq!(cnt.get(), ITER);
}
-#[test]
-fn does_not_set_global_executor_by_default() {
- use tokio_executor::Executor;
+mod does_not_set_global_executor_by_default {
+ use super::*;
- block_on_all(lazy(|| {
- tokio_executor::DefaultExecutor::current()
- .spawn(Box::new(lazy(|| ok())))
- .unwrap_err();
+ fn test<F: Fn(Box<Future<Item=(), Error=()> + Send>) -> Result<(), E> + 'static, E>(spawn: F) {
+ block_on_all(lazy(|| {
+ spawn(Box::new(lazy(|| ok()))).unwrap_err();
+ ok()
+ })).unwrap()
+ }
- ok()
- })).unwrap();
+ #[test]
+ fn spawn() {
+ use tokio_executor::Executor;
+ test(|f| tokio_executor::DefaultExecutor::current().spawn(f))
+ }
+
+ #[test]
+ fn execute() {
+ test(|f| tokio_executor::DefaultExecutor::current().execute(f))
+ }
}
-#[test]
-fn spawn_from_block_on_future() {
- let cnt = Rc::new(Cell::new(0));
+mod from_block_on_future {
+ use super::*;
- let mut tokio_current_thread = CurrentThread::new();
+ fn test<F: Fn(Box<Future<Item = (), Error = ()>>)>(spawn: F) {
+ let cnt = Rc::new(Cell::new(0));
- tokio_current_thread.block_on(lazy(|| {
- let cnt = cnt.clone();
+ let mut tokio_current_thread = CurrentThread::new();
- tokio_current_thread::spawn(lazy(move || {
- cnt.set(1 + cnt.get());
- Ok(())
- }));
+ tokio_current_thread.block_on(lazy(|| {
+ let cnt = cnt.clone();
- Ok::<_, ()>(())
- })).unwrap();
+ spawn(Box::new(lazy(move || {
+ cnt.set(1 + cnt.get());
+ Ok(())
+ })));
- tokio_current_thread.run().unwrap();
+ Ok::<_, ()>(())
+ })).unwrap();
+
+ tokio_current_thread.run().unwrap();
+
+ assert_eq!(1, cnt.get());
+ }
+
+ #[test]
+ fn spawn() {
+ test(tokio_current_thread::spawn);
+ }
- assert_eq!(1, cnt.get());
+ #[test]
+ fn execute() {
+ test(|f| { tokio_current_thread::TaskExecutor::current().execute(f).unwrap(); });
+ }
}
struct Never(Rc<()>);
@@ -122,33 +165,60 @@ impl Future for Never {
}
}
-#[test]
-fn outstanding_tasks_are_dropped_when_executor_is_dropped() {
- let mut rc = Rc::new(());
+mod outstanding_tasks_are_dropped_when_executor_is_dropped {
+ use super::*;
- let mut tokio_current_thread = CurrentThread::new();
- tokio_current_thread.spawn(Never(rc.clone()));
+ fn test<F, G>(spawn: F, dotspawn: G)
+ where
+ F: Fn(Box<Future<Item=(), Error=()>>) + 'static,
+ G: Fn(&mut CurrentThread, Box<Future<Item=(), Error=()>>)
+ {
+ let mut rc = Rc::new(());
- drop(tokio_current_thread);
+ let mut tokio_current_thread = CurrentThread::new();
+ dotspawn(&mut tokio_current_thread, Box::new(Never(rc.clone())));
- // Ensure the daemon is dropped
- assert!(Rc::get_mut(&mut rc).is_some());
+ drop(tokio_current_thread);
- // Using the global spawn fn
+ // Ensure the daemon is dropped
+ assert!(Rc::get_mut(&mut rc).is_some());
- let mut rc = Rc::new(());
+ // Using the global spawn fn
- let mut tokio_current_thread = CurrentThread::new();
+ let mut rc = Rc::new(());
- tokio_current_thread.block_on(lazy(|| {
- tokio_current_thread::spawn(Never(rc.clone()));
- Ok::<_, ()>(())
- })).unwrap();
+ let mut tokio_current_thread = CurrentThread::new();
+
+ tokio_current_thread.block_on(lazy(|| {
+ spawn(Box::new(Never(rc.clone())));
+ Ok::<_, ()>(())
+ })).unwrap();
+
+ drop(tokio_current_thread);
- drop(tokio_current_thread);
+ // Ensure the daemon is dropped
+ assert!(Rc::get_mut(&mut rc).is_some());
+ }
+
+ #[test]
+ fn spawn() {
+ test(tokio_current_thread::spawn, |rt, f| { rt.spawn(f); })
+ }
- // Ensure the daemon is dropped
- assert!(Rc::get_mut(&mut rc).is_some());
+ #[test]
+ fn execute() {
+ test(|f| {
+ tokio_current_thread::TaskExecutor::current()
+ .execute(f)
+ .unwrap();
+ },
+ // Note: `CurrentThread` doesn't currently implement
+ // `futures::Executor`, so we'll call `.spawn(...)` rather than
+ // `.execute(...)` for now. If `CurrentThread` is changed to
+ // implement Executor, change this to `.execute(...).unwrap()`.
+ |rt, f| { rt.spawn(f); }
+ );
+ }
}
#[test]
@@ -163,20 +233,41 @@ fn nesting_run() {
})).unwrap();
}
-#[test]
-#[should_panic]
-fn run_in_future() {
- block_on_all(lazy(|| {
- tokio_current_thread::spawn(lazy(|| {
- block_on_all(lazy(|| {
+mod run_in_future {
+ use super::*;
+
+ #[test]
+ #[should_panic]
+ fn spawn() {
+ block_on_all(lazy(|| {
+ tokio_current_thread::spawn(lazy(|| {
+ block_on_all(lazy(|| {
+ ok()
+ })).unwrap();
ok()
- })).unwrap();
+ }));
ok()
- }));
- ok()
- })).unwrap();
+ })).unwrap();
+ }
+
+ #[test]
+ #[should_panic]
+ fn execute() {
+ block_on_all(lazy(|| {
+ tokio_current_thread::TaskExecutor::current()
+ .execute(lazy(|| {
+ block_on_all(lazy(|| {
+ ok()
+ })).unwrap();
+ ok()
+ }))
+ .unwrap();
+ ok()
+ })).unwrap();
+ }
}
+
#[test]
fn tick_on_infini_future() {
let num = Rc::new(Cell::new(0));
@@ -206,10 +297,8 @@ fn tick_on_infini_future() {
assert_eq!(1, num.get());
}
-#[test]
-fn tasks_are_scheduled_fairly() {
- let state = Rc::new(RefCell::new([0, 0]));
-
+mod tasks_are_scheduled_fairly {
+ use super::*;
struct Spin {
state: Rc<RefCell<[i32; 2]>>,
idx: usize,
@@ -243,97 +332,171 @@ fn tasks_are_scheduled_fairly() {
}
}
- block_on_all(lazy(|| {
- tokio_current_thread::spawn(Spin {
- state: state.clone(),
- idx: 0,
- });
+ fn test<F: Fn(Spin)>(spawn: F) {
+ let state = Rc::new(RefCell::new([0, 0]));
- tokio_current_thread::spawn(Spin {
- state: state,
- idx: 1,
- });
+ block_on_all(lazy(|| {
+ spawn(Spin {
+ state: state.clone(),
+ idx: 0,
+ });
- ok()
- })).unwrap();
+ spawn(Spin {
+ state: state,
+ idx: 1,
+ });
+
+ ok()
+ })).unwrap();
+ }
+
+ #[test]
+ fn spawn() {
+ test(tokio_current_thread::spawn)
+ }
+
+ #[test]
+ fn execute() {
+ test(|f| {
+ tokio_current_thread::TaskExecutor::current()
+ .execute(f)
+ .unwrap();
+ })
+ }
}
-#[test]
-fn spawn_and_turn() {
- let cnt = Rc::new(Cell::new(0));
- let c = cnt.clone();
+mod and_turn {
+ use super::*;
- let mut tokio_current_thread = CurrentThread::new();
+ fn test<F, G>(spawn: F, dotspawn: G)
+ where
+ F: Fn(Box<Future<Item=(), Error=()>>) + 'static,
+ G: Fn(&mut CurrentThread, Box<Future<Item=(), Error=()>>)
+ {
+ let cnt = Rc::new(Cell::new(0));
+ let c = cnt.clone();
- // Spawn a basic task to get the executor to turn
- tokio_current_thread.spawn(lazy(move || {
- Ok(())
- }));
+ let mut tokio_current_thread = CurrentThread::new();
- // Turn once...
- tokio_current_thread.turn(None).unwrap();
+ // Spawn a basic task to get the executor to turn
+ dotspawn(&mut tokio_current_thread, Box::new(lazy(move || {
+ Ok(())
+ })));
- tokio_current_thread.spawn(lazy(move || {
- c.set(1 + c.get());
+ // Turn once...
+ tokio_current_thread.turn(None).unwrap();
- // Spawn!
- tokio_current_thread::spawn(lazy(move || {
+ dotspawn(&mut tokio_current_thread, Box::new(lazy(move || {
c.set(1 + c.get());
- Ok::<(), ()>(())
- }));
- Ok(())
- }));
+ // Spawn!
+ spawn(Box::new(lazy(move || {
+ c.set(1 + c.get());
+ Ok::<(), ()>(())
+ })));
- // This does not run the newly spawned thread
- tokio_current_thread.turn(None).unwrap();
- assert_eq!(1, cnt.get());
+ Ok(())
+ })));
- // This runs the newly spawned thread
- tokio_current_thread.turn(None).unwrap();
- assert_eq!(2, cnt.get());
-}
+ // This does not run the newly spawned thread
+ tokio_current_thread.turn(None).unwrap();
+ assert_eq!(1, cnt.get());
-#[test]
-fn spawn_in_drop() {
- let mut tokio_current_thread = CurrentThread::new();
+ // This runs the newly spawned thread
+ tokio_current_thread.turn(None).unwrap();
+ assert_eq!(2, cnt.get());
+ }
- let (tx, rx) = oneshot::channel();
+ #[test]
+ fn spawn() {
+ test(tokio_current_thread::spawn, |rt, f| { rt.spawn(f); })
+ }
- tokio_current_thread.spawn({
- struct OnDrop<F: FnOnce()>(Option<F>);
+ #[test]
+ fn execute() {
+ test(|f| {
+ tokio_current_thread::TaskExecutor::current()
+ .execute(f)
+ .unwrap();
+ },
+ // Note: `CurrentThread` doesn't currently implement
+ // `futures::Executor`, so we'll call `.spawn(...)` rather than
+ // `.execute(...)` for now. If `CurrentThread` is changed to
+ // implement Executor, change this to `.execute(...).unwrap()`.
+ |rt, f| { rt.spawn(f); }
+ );
+ }
- impl<F: FnOnce()> Drop for OnDrop<F> {
- fn drop(&mut self) {
- (self.0.take().unwrap())();
- }
+
+}
+
+mod in_drop {
+ use super::*;
+ struct OnDrop<F: FnOnce()>(Option<F>);
+
+ impl<F: FnOnce()> Drop for OnDrop<F> {
+ fn drop(&mut self) {
+ (self.0.take().unwrap())();
}
+ }
+
+ struct MyFuture {
+ _data: Box<Any>,
+ }
+
+ impl Future for MyFuture {
+ type Item = ();
+ type Error = ();
- struct MyFuture {
- _data: Box<Any>,
+ fn poll(&mut self) -> Poll<(), ()> {
+ Ok(().into())
}
+ }
- impl Future for MyFuture {
- type Item = ();
- type Error = ();
+ fn test<F, G>(spawn: F, dotspawn: G)
+ where
+ F: Fn(Box<Future<Item=(), Error=()>>) + 'static,
+ G: Fn(&mut CurrentThread, Box<Future<Item=(), Error=()>>)
+ {
+ let mut tokio_current_thread = CurrentThread::new();
+
+ let (tx, rx) = oneshot::channel();
- fn poll(&mut self) -> Poll<(), ()> {
- Ok(().into())
+ dotspawn(&mut tokio_current_thread, Box::new(
+ MyFuture {
+ _data: Box::new(OnDrop(Some(move || {
+ spawn(Box::new(lazy(move || {
+ tx.send(()).unwrap();
+ Ok(())
+ })));
+ }))),
}
- }
+ ));
- MyFuture {
- _data: Box::new(OnDrop(Some(move || {
- tokio_current_thread::spawn(lazy(move || {
- tx.send(()).unwrap();
- Ok(())
- }));
- }))),
- }
- });
+ tokio_current_thread.block_on(rx).unwrap();
+ tokio_current_thread.run().unwrap();
+ }
+
+ #[test]
+ fn spawn() {
+ test(tokio_current_thread::spawn, |rt, f| { rt.spawn(f); })
+ }
+
+ #[test]
+ fn execute() {
+ test(|f| {
+ tokio_current_thread::TaskExecutor::current()
+ .execute(f)
+ .unwrap();
+ },
+ // Note: `CurrentThread` doesn't currently implement
+ // `futures::Executor`, so we'll call `.spawn(...)` rather than
+ // `.execute(...)` for now. If `CurrentThread` is changed to
+ // implement Executor, change this to `.execute(...).unwrap()`.
+ |rt, f| { rt.spawn(f); }
+ );
+ }
- tokio_current_thread.block_on(rx).unwrap();
- tokio_current_thread.run().unwrap();
}
#[test]