Vendor dependencies for 0.3.0 release

This commit is contained in:
2025-09-27 10:29:08 -05:00
parent 0c8d39d483
commit 82ab7f317b
26803 changed files with 16134934 additions and 0 deletions

View File

@@ -0,0 +1,34 @@
use async_executor::LocalExecutor;
use futures_lite::future::{block_on, pending, poll_once};
use futures_lite::pin;
use std::cell::Cell;
#[test]
fn shared_queue_slot() {
block_on(async {
let was_polled = Cell::new(false);
let future = async {
was_polled.set(true);
pending::<()>().await;
};
let ex1 = LocalExecutor::new();
let ex2 = LocalExecutor::new();
// Start the futures for running forever.
let (run1, run2) = (ex1.run(pending::<()>()), ex2.run(pending::<()>()));
pin!(run1);
pin!(run2);
assert!(poll_once(run1.as_mut()).await.is_none());
assert!(poll_once(run2.as_mut()).await.is_none());
// Spawn the future on executor one and then poll executor two.
ex1.spawn(future).detach();
assert!(poll_once(run2).await.is_none());
assert!(!was_polled.get());
// Poll the first one.
assert!(poll_once(run1).await.is_none());
assert!(was_polled.get());
});
}

147
vendor/async-executor/tests/drop.rs vendored Normal file
View File

@@ -0,0 +1,147 @@
#[cfg(not(miri))]
use std::mem;
use std::panic::catch_unwind;
use std::sync::atomic::{AtomicUsize, Ordering};
use std::sync::Mutex;
use std::task::{Poll, Waker};
use async_executor::{Executor, Task};
use futures_lite::future;
use once_cell::sync::Lazy;
#[test]
fn executor_cancels_everything() {
static DROP: AtomicUsize = AtomicUsize::new(0);
static WAKER: Lazy<Mutex<Option<Waker>>> = Lazy::new(Default::default);
let ex = Executor::new();
let task = ex.spawn(async {
let _guard = CallOnDrop(|| {
DROP.fetch_add(1, Ordering::SeqCst);
});
future::poll_fn(|cx| {
*WAKER.lock().unwrap() = Some(cx.waker().clone());
Poll::Pending::<()>
})
.await;
});
future::block_on(ex.tick());
assert!(WAKER.lock().unwrap().is_some());
assert_eq!(DROP.load(Ordering::SeqCst), 0);
drop(ex);
assert_eq!(DROP.load(Ordering::SeqCst), 1);
assert!(catch_unwind(|| future::block_on(task)).is_err());
assert_eq!(DROP.load(Ordering::SeqCst), 1);
}
#[cfg(not(miri))]
#[test]
fn leaked_executor_leaks_everything() {
static DROP: AtomicUsize = AtomicUsize::new(0);
static WAKER: Lazy<Mutex<Option<Waker>>> = Lazy::new(Default::default);
let ex = Executor::new();
let task = ex.spawn(async {
let _guard = CallOnDrop(|| {
DROP.fetch_add(1, Ordering::SeqCst);
});
future::poll_fn(|cx| {
*WAKER.lock().unwrap() = Some(cx.waker().clone());
Poll::Pending::<()>
})
.await;
});
future::block_on(ex.tick());
assert!(WAKER.lock().unwrap().is_some());
assert_eq!(DROP.load(Ordering::SeqCst), 0);
mem::forget(ex);
assert_eq!(DROP.load(Ordering::SeqCst), 0);
assert!(future::block_on(future::poll_once(task)).is_none());
assert_eq!(DROP.load(Ordering::SeqCst), 0);
}
#[test]
fn await_task_after_dropping_executor() {
let s: String = "hello".into();
let ex = Executor::new();
let task: Task<&str> = ex.spawn(async { &*s });
assert!(ex.try_tick());
drop(ex);
assert_eq!(future::block_on(task), "hello");
drop(s);
}
#[test]
fn drop_executor_and_then_drop_finished_task() {
static DROP: AtomicUsize = AtomicUsize::new(0);
let ex = Executor::new();
let task = ex.spawn(async {
CallOnDrop(|| {
DROP.fetch_add(1, Ordering::SeqCst);
})
});
assert!(ex.try_tick());
assert_eq!(DROP.load(Ordering::SeqCst), 0);
drop(ex);
assert_eq!(DROP.load(Ordering::SeqCst), 0);
drop(task);
assert_eq!(DROP.load(Ordering::SeqCst), 1);
}
#[test]
fn drop_finished_task_and_then_drop_executor() {
static DROP: AtomicUsize = AtomicUsize::new(0);
let ex = Executor::new();
let task = ex.spawn(async {
CallOnDrop(|| {
DROP.fetch_add(1, Ordering::SeqCst);
})
});
assert!(ex.try_tick());
assert_eq!(DROP.load(Ordering::SeqCst), 0);
drop(task);
assert_eq!(DROP.load(Ordering::SeqCst), 1);
drop(ex);
assert_eq!(DROP.load(Ordering::SeqCst), 1);
}
#[test]
fn iterator_panics_mid_run() {
let ex = Executor::new();
let panic = std::panic::catch_unwind(|| {
let mut handles = vec![];
ex.spawn_many(
(0..50).map(|i| if i == 25 { panic!() } else { future::ready(i) }),
&mut handles,
)
});
assert!(panic.is_err());
let task = ex.spawn(future::ready(0));
assert_eq!(future::block_on(ex.run(task)), 0);
}
struct CallOnDrop<F: Fn()>(F);
impl<F: Fn()> Drop for CallOnDrop<F> {
fn drop(&mut self) {
(self.0)();
}
}

View File

@@ -0,0 +1,99 @@
//! Test for larger tasks.
use async_executor::Executor;
use futures_lite::future::{self, block_on};
use futures_lite::prelude::*;
use std::sync::Arc;
use std::thread;
use std::time::Duration;
fn do_run<Fut: Future<Output = ()>>(mut f: impl FnMut(Arc<Executor<'static>>) -> Fut) {
// This should not run for longer than two minutes.
#[cfg(not(miri))]
let _stop_timeout = {
let (stop_timeout, stopper) = async_channel::bounded::<()>(1);
thread::spawn(move || {
block_on(async move {
let timeout = async {
async_io::Timer::after(Duration::from_secs(2 * 60)).await;
eprintln!("test timed out after 2m");
std::process::exit(1)
};
let _ = stopper.recv().or(timeout).await;
})
});
stop_timeout
};
let ex = Arc::new(Executor::new());
// Test 1: Use the `run` command.
block_on(ex.run(f(ex.clone())));
// Test 2: Loop on `tick`.
block_on(async {
let ticker = async {
loop {
ex.tick().await;
}
};
f(ex.clone()).or(ticker).await
});
// Test 3: Run on many threads.
thread::scope(|scope| {
let (_signal, shutdown) = async_channel::bounded::<()>(1);
for _ in 0..16 {
let shutdown = shutdown.clone();
let ex = &ex;
scope.spawn(move || block_on(ex.run(shutdown.recv())));
}
block_on(f(ex.clone()));
});
// Test 4: Tick loop on many threads.
thread::scope(|scope| {
let (_signal, shutdown) = async_channel::bounded::<()>(1);
for _ in 0..16 {
let shutdown = shutdown.clone();
let ex = &ex;
scope.spawn(move || {
block_on(async move {
let ticker = async {
loop {
ex.tick().await;
}
};
shutdown.recv().or(ticker).await
})
});
}
block_on(f(ex.clone()));
});
}
#[test]
fn smoke() {
do_run(|ex| async move { ex.spawn(async {}).await });
}
#[test]
fn yield_now() {
do_run(|ex| async move { ex.spawn(future::yield_now()).await })
}
#[test]
fn timer() {
do_run(|ex| async move {
ex.spawn(async_io::Timer::after(Duration::from_millis(5)))
.await;
})
}

View File

@@ -0,0 +1,24 @@
use async_executor::Executor;
use futures_lite::{future, pin};
#[test]
fn two_queues() {
future::block_on(async {
// Create an executor with two runners.
let ex = Executor::new();
let (run1, run2) = (
ex.run(future::pending::<()>()),
ex.run(future::pending::<()>()),
);
let mut run1 = Box::pin(run1);
pin!(run2);
// Poll them both.
assert!(future::poll_once(run1.as_mut()).await.is_none());
assert!(future::poll_once(run2.as_mut()).await.is_none());
// Drop the first one, which should leave the local queue in the `None` state.
drop(run1);
assert!(future::poll_once(run2.as_mut()).await.is_none());
});
}

View File

@@ -0,0 +1,14 @@
use async_executor::Executor;
use futures_lite::{future, prelude::*};
#[test]
fn test_panic_propagation() {
let ex = Executor::new();
let task = ex.spawn(async { panic!("should be caught by the task") });
// Running the executor should not panic.
assert!(ex.try_tick());
// Polling the task should.
assert!(future::block_on(task.catch_unwind()).is_err());
}

View File

@@ -0,0 +1,45 @@
use async_executor::{Executor, LocalExecutor};
use futures_lite::future;
#[cfg(not(miri))]
const READY_COUNT: usize = 50_000;
#[cfg(miri)]
const READY_COUNT: usize = 505;
#[test]
fn spawn_many() {
future::block_on(async {
let ex = Executor::new();
// Spawn a lot of tasks.
let mut tasks = vec![];
ex.spawn_many((0..READY_COUNT).map(future::ready), &mut tasks);
// Run all of the tasks in parallel.
ex.run(async move {
for (i, task) in tasks.into_iter().enumerate() {
assert_eq!(task.await, i);
}
})
.await;
});
}
#[test]
fn spawn_many_local() {
future::block_on(async {
let ex = LocalExecutor::new();
// Spawn a lot of tasks.
let mut tasks = vec![];
ex.spawn_many((0..READY_COUNT).map(future::ready), &mut tasks);
// Run all of the tasks in parallel.
ex.run(async move {
for (i, task) in tasks.into_iter().enumerate() {
assert_eq!(task.await, i);
}
})
.await;
});
}