From bd191687f07bd8b7032fbdcf0f992040ba6ca27e Mon Sep 17 00:00:00 2001 From: Taiki Endo Date: Mon, 21 Mar 2022 20:53:57 +0900 Subject: [PATCH] Run more tests with Miri (#2584) --- .github/workflows/ci.yml | 4 +- futures-executor/Cargo.toml | 2 +- futures-executor/src/thread_pool.rs | 28 ++++++++----- futures-executor/tests/local_pool.rs | 3 ++ futures-util/src/task/spawn.rs | 9 ++-- futures/src/lib.rs | 4 +- futures/tests/eventual.rs | 9 ++-- futures/tests/future_shared.rs | 1 - futures/tests/lock_mutex.rs | 50 ++++++++++++----------- futures/tests/macro_comma_support.rs | 1 - futures/tests/recurse.rs | 1 - futures/tests/sink.rs | 1 - futures/tests/stream_futures_ordered.rs | 2 - futures/tests/stream_futures_unordered.rs | 2 - futures/tests/stream_try_stream.rs | 2 - 15 files changed, 64 insertions(+), 55 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index dfb7eea4ff..110b1b7c0a 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -273,10 +273,10 @@ jobs: - uses: actions/checkout@v2 - name: Install Rust run: rustup toolchain install nightly --component miri && rustup default nightly - # futures-executor uses boxed futures so many tests trigger https://github.com/rust-lang/miri/issues/1038 - - run: cargo miri test --workspace --exclude futures-executor --all-features + - run: cargo miri test --workspace --all-features env: MIRIFLAGS: -Zmiri-check-number-validity -Zmiri-symbolic-alignment-check -Zmiri-tag-raw-pointers -Zmiri-disable-isolation + RUSTFLAGS: ${{ env.RUSTFLAGS }} -Z randomize-layout san: name: cargo test -Z sanitizer=${{ matrix.sanitizer }} diff --git a/futures-executor/Cargo.toml b/futures-executor/Cargo.toml index dae5f22e77..e1ce688581 100644 --- a/futures-executor/Cargo.toml +++ b/futures-executor/Cargo.toml @@ -22,7 +22,7 @@ futures-util = { path = "../futures-util", version = "0.3.21", default-features num_cpus = { version = "1.8.0", optional = true } [dev-dependencies] -futures = { path = "../futures" } +futures = { path = "../futures", features = ["thread-pool"] } [package.metadata.docs.rs] all-features = true diff --git a/futures-executor/src/thread_pool.rs b/futures-executor/src/thread_pool.rs index 3eca9d1440..8c93b476bc 100644 --- a/futures-executor/src/thread_pool.rs +++ b/futures-executor/src/thread_pool.rs @@ -108,12 +108,15 @@ impl ThreadPool { /// completion. /// /// ``` + /// # { /// use futures::executor::ThreadPool; /// /// let pool = ThreadPool::new().unwrap(); /// /// let future = async { /* ... */ }; /// pool.spawn_ok(future); + /// # } + /// # std::thread::sleep(std::time::Duration::from_secs(1)); // wait for background threads closed /// ``` /// /// > **Note**: This method is similar to `SpawnExt::spawn`, except that @@ -359,16 +362,19 @@ mod tests { #[test] fn test_drop_after_start() { - let (tx, rx) = mpsc::sync_channel(2); - let _cpu_pool = ThreadPoolBuilder::new() - .pool_size(2) - .after_start(move |_| tx.send(1).unwrap()) - .create() - .unwrap(); - - // After ThreadPoolBuilder is deconstructed, the tx should be dropped - // so that we can use rx as an iterator. - let count = rx.into_iter().count(); - assert_eq!(count, 2); + { + let (tx, rx) = mpsc::sync_channel(2); + let _cpu_pool = ThreadPoolBuilder::new() + .pool_size(2) + .after_start(move |_| tx.send(1).unwrap()) + .create() + .unwrap(); + + // After ThreadPoolBuilder is deconstructed, the tx should be dropped + // so that we can use rx as an iterator. + let count = rx.into_iter().count(); + assert_eq!(count, 2); + } + std::thread::sleep(std::time::Duration::from_secs(1)); // wait for background threads closed } } diff --git a/futures-executor/tests/local_pool.rs b/futures-executor/tests/local_pool.rs index 9b1316b998..8e5e27981d 100644 --- a/futures-executor/tests/local_pool.rs +++ b/futures-executor/tests/local_pool.rs @@ -288,6 +288,9 @@ fn run_until_stalled_runs_spawned_sub_futures() { #[test] fn run_until_stalled_executes_all_ready() { + #[cfg(miri)] + const ITER: usize = 50; + #[cfg(not(miri))] const ITER: usize = 200; const PER_ITER: usize = 3; diff --git a/futures-util/src/task/spawn.rs b/futures-util/src/task/spawn.rs index 87ca360516..8e78717c27 100644 --- a/futures-util/src/task/spawn.rs +++ b/futures-util/src/task/spawn.rs @@ -34,7 +34,7 @@ pub trait SpawnExt: Spawn { /// today. Feel free to use this method in the meantime. /// /// ``` - /// # if cfg!(miri) { return; } // https://github.com/rust-lang/miri/issues/1038 + /// # { /// use futures::executor::ThreadPool; /// use futures::task::SpawnExt; /// @@ -42,6 +42,8 @@ pub trait SpawnExt: Spawn { /// /// let future = async { /* ... */ }; /// executor.spawn(future).unwrap(); + /// # } + /// # std::thread::sleep(std::time::Duration::from_secs(1)); // wait for background threads closed /// ``` #[cfg(feature = "alloc")] fn spawn(&self, future: Fut) -> Result<(), SpawnError> @@ -59,7 +61,7 @@ pub trait SpawnExt: Spawn { /// resolves to the output of the spawned future. /// /// ``` - /// # if cfg!(miri) { return; } // https://github.com/rust-lang/miri/issues/1038 + /// # { /// use futures::executor::{block_on, ThreadPool}; /// use futures::future; /// use futures::task::SpawnExt; @@ -69,6 +71,8 @@ pub trait SpawnExt: Spawn { /// let future = future::ready(1); /// let join_handle_fut = executor.spawn_with_handle(future).unwrap(); /// assert_eq!(block_on(join_handle_fut), 1); + /// # } + /// # std::thread::sleep(std::time::Duration::from_secs(1)); // wait for background threads closed /// ``` #[cfg(feature = "channel")] #[cfg_attr(docsrs, doc(cfg(feature = "channel")))] @@ -138,7 +142,6 @@ pub trait LocalSpawnExt: LocalSpawn { /// resolves to the output of the spawned future. /// /// ``` - /// # if cfg!(miri) { return; } // https://github.com/rust-lang/miri/issues/1038 /// use futures::executor::LocalPool; /// use futures::task::LocalSpawnExt; /// diff --git a/futures/src/lib.rs b/futures/src/lib.rs index b8ebc614e2..3ae9091dca 100644 --- a/futures/src/lib.rs +++ b/futures/src/lib.rs @@ -25,13 +25,13 @@ //! within macros and keywords such as async and await!. //! //! ```rust -//! # if cfg!(miri) { return; } // https://github.com/rust-lang/miri/issues/1038 //! # use futures::channel::mpsc; //! # use futures::executor; ///standard executors to provide a context for futures and streams //! # use futures::executor::ThreadPool; //! # use futures::StreamExt; //! # //! fn main() { +//! # { //! let pool = ThreadPool::new().expect("Failed to build pool"); //! let (tx, rx) = mpsc::unbounded::(); //! @@ -73,6 +73,8 @@ //! let values: Vec = executor::block_on(fut_values); //! //! println!("Values={:?}", values); +//! # } +//! # std::thread::sleep(std::time::Duration::from_secs(1)); // wait for background threads closed //! } //! ``` //! diff --git a/futures/tests/eventual.rs b/futures/tests/eventual.rs index 34613806c4..96e21a12a4 100644 --- a/futures/tests/eventual.rs +++ b/futures/tests/eventual.rs @@ -1,5 +1,3 @@ -#![cfg(not(miri))] // https://github.com/rust-lang/miri/issues/1038 - use futures::channel::oneshot; use futures::executor::ThreadPool; use futures::future::{self, ok, Future, FutureExt, TryFutureExt}; @@ -136,6 +134,11 @@ fn select3() { #[test] fn select4() { + #[cfg(miri)] + const N: usize = 100; + #[cfg(not(miri))] + const N: usize = 10000; + let (tx, rx) = mpsc::channel::>(); let t = thread::spawn(move || { @@ -145,7 +148,7 @@ fn select4() { }); let (tx2, rx2) = mpsc::channel(); - for _ in 0..10000 { + for _ in 0..N { let (c1, p1) = oneshot::channel::(); let (c2, p2) = oneshot::channel::(); diff --git a/futures/tests/future_shared.rs b/futures/tests/future_shared.rs index 20a021bc35..6bf43d23cf 100644 --- a/futures/tests/future_shared.rs +++ b/futures/tests/future_shared.rs @@ -97,7 +97,6 @@ fn drop_in_poll() { assert_eq!(block_on(future1), 1); } -#[cfg_attr(miri, ignore)] // https://github.com/rust-lang/miri/issues/1038 #[test] fn peek() { let mut local_pool = LocalPool::new(); diff --git a/futures/tests/lock_mutex.rs b/futures/tests/lock_mutex.rs index c92ef50ad8..0bd2607565 100644 --- a/futures/tests/lock_mutex.rs +++ b/futures/tests/lock_mutex.rs @@ -34,34 +34,36 @@ fn mutex_wakes_waiters() { assert!(waiter.poll_unpin(&mut panic_context()).is_ready()); } -#[cfg_attr(miri, ignore)] // https://github.com/rust-lang/miri/issues/1038 #[test] fn mutex_contested() { - let (tx, mut rx) = mpsc::unbounded(); - let pool = ThreadPool::builder().pool_size(16).create().unwrap(); + { + let (tx, mut rx) = mpsc::unbounded(); + let pool = ThreadPool::builder().pool_size(16).create().unwrap(); - let tx = Arc::new(tx); - let mutex = Arc::new(Mutex::new(0)); + let tx = Arc::new(tx); + let mutex = Arc::new(Mutex::new(0)); - let num_tasks = 1000; - for _ in 0..num_tasks { - let tx = tx.clone(); - let mutex = mutex.clone(); - pool.spawn(async move { - let mut lock = mutex.lock().await; - ready(()).pending_once().await; - *lock += 1; - tx.unbounded_send(()).unwrap(); - drop(lock); - }) - .unwrap(); - } - - block_on(async { + let num_tasks = 1000; for _ in 0..num_tasks { - rx.next().await.unwrap(); + let tx = tx.clone(); + let mutex = mutex.clone(); + pool.spawn(async move { + let mut lock = mutex.lock().await; + ready(()).pending_once().await; + *lock += 1; + tx.unbounded_send(()).unwrap(); + drop(lock); + }) + .unwrap(); } - let lock = mutex.lock().await; - assert_eq!(num_tasks, *lock); - }) + + block_on(async { + for _ in 0..num_tasks { + rx.next().await.unwrap(); + } + let lock = mutex.lock().await; + assert_eq!(num_tasks, *lock); + }); + } + std::thread::sleep(std::time::Duration::from_secs(1)); // wait for background threads closed } diff --git a/futures/tests/macro_comma_support.rs b/futures/tests/macro_comma_support.rs index 3b082d211f..85871e98be 100644 --- a/futures/tests/macro_comma_support.rs +++ b/futures/tests/macro_comma_support.rs @@ -14,7 +14,6 @@ fn ready() { })) } -#[cfg_attr(miri, ignore)] // https://github.com/rust-lang/miri/issues/1038 #[test] fn poll() { use futures::poll; diff --git a/futures/tests/recurse.rs b/futures/tests/recurse.rs index f06524f85a..d81753c9d7 100644 --- a/futures/tests/recurse.rs +++ b/futures/tests/recurse.rs @@ -3,7 +3,6 @@ use futures::future::{self, BoxFuture, FutureExt}; use std::sync::mpsc; use std::thread; -#[cfg_attr(miri, ignore)] // https://github.com/rust-lang/miri/issues/1038 #[test] fn lots() { #[cfg(not(futures_sanitizer))] diff --git a/futures/tests/sink.rs b/futures/tests/sink.rs index dc826bda98..f3cf11b931 100644 --- a/futures/tests/sink.rs +++ b/futures/tests/sink.rs @@ -288,7 +288,6 @@ fn mpsc_blocking_start_send() { // test `flush` by using `with` to make the first insertion into a sink block // until a oneshot is completed -#[cfg_attr(miri, ignore)] // https://github.com/rust-lang/miri/issues/1038 #[test] fn with_flush() { let (tx, rx) = oneshot::channel(); diff --git a/futures/tests/stream_futures_ordered.rs b/futures/tests/stream_futures_ordered.rs index 84e0bcc1df..7506c65a63 100644 --- a/futures/tests/stream_futures_ordered.rs +++ b/futures/tests/stream_futures_ordered.rs @@ -26,7 +26,6 @@ fn works_1() { assert_eq!(None, iter.next()); } -#[cfg_attr(miri, ignore)] // https://github.com/rust-lang/miri/issues/1038 #[test] fn works_2() { let (a_tx, a_rx) = oneshot::channel::(); @@ -55,7 +54,6 @@ fn from_iterator() { assert_eq!(block_on(stream.collect::>()), vec![1, 2, 3]); } -#[cfg_attr(miri, ignore)] // https://github.com/rust-lang/miri/issues/1038 #[test] fn queue_never_unblocked() { let (_a_tx, a_rx) = oneshot::channel::>(); diff --git a/futures/tests/stream_futures_unordered.rs b/futures/tests/stream_futures_unordered.rs index 398170a7cf..b568280479 100644 --- a/futures/tests/stream_futures_unordered.rs +++ b/futures/tests/stream_futures_unordered.rs @@ -56,7 +56,6 @@ fn works_1() { assert_eq!(None, iter.next()); } -#[cfg_attr(miri, ignore)] // https://github.com/rust-lang/miri/issues/1038 #[test] fn works_2() { let (a_tx, a_rx) = oneshot::channel::(); @@ -86,7 +85,6 @@ fn from_iterator() { assert_eq!(block_on(stream.collect::>()), vec![1, 2, 3]); } -#[cfg_attr(miri, ignore)] // https://github.com/rust-lang/miri/issues/1038 #[test] fn finished_future() { let (_a_tx, a_rx) = oneshot::channel::(); diff --git a/futures/tests/stream_try_stream.rs b/futures/tests/stream_try_stream.rs index d83fc54b1c..194e74db74 100644 --- a/futures/tests/stream_try_stream.rs +++ b/futures/tests/stream_try_stream.rs @@ -1,5 +1,3 @@ -#![cfg(not(miri))] // https://github.com/rust-lang/miri/issues/1038 - use futures::{ stream::{self, StreamExt, TryStreamExt}, task::Poll,