Expand description
A property-based testing framework for Futures.
§What it tests
- Waker registration – a future that returns
Pendingmust retain or wake theWakerit was given. Forgetting it causes deadlocks. - Waker freshness – a future must accept a new waker on every poll, not cache a stale one.
- Spurious wakeup tolerance – futures must handle being polled without the
driver having made progress, as commonly happens inside
select/join. - Cancel safety – the factory is called multiple times, exercising cancellation between iterations.
§Architecture
A test is defined by two collaborating pieces returned from TestCase::init:
Driver -----> Leaf Future <----- Future
(e.g. tx) (e.g. channel) (from factory)
| ^
| |
+--- drives progress factory called
wakes waker multiple times
Runner randomly interleaves:
poll | drive | spurious poll | swap waker | cancel- Driver – represents the other side of the leaf future under test (e.g. a
channel sender for a receiver future). When it reports progress
(
Poll::Ready), the framework asserts the future’s waker was called.Poll::Pendingmeans no progress was made and skips that assertion. - Factory – an async closure called multiple times to produce the futures
under test. Each call may receive an arbitrary item (see
TestCase::FactoryItem).
Under the hood the runner uses [arbtest] to fuzz the interleaving of these
actions, catching waker bugs that deterministic tests would miss.
§Example
use std::ops::ControlFlow;
use futures_testing::{drive_poll_fn, testcase};
use futures::StreamExt;
let testcase = testcase!(|| {
let (mut tx, mut rx) = futures::channel::mpsc::channel::<u8>(4);
let driver = drive_poll_fn(move |item: u8| {
match tx.try_send(item) {
Ok(()) => std::task::Poll::Ready(ControlFlow::Continue(())),
Err(_) => std::task::Poll::Pending,
}
});
let factory = async move |_: ()| {
let _ = rx.next().await;
};
(driver, factory)
});
futures_testing::tests(testcase).run();Re-exports§
pub use arbitrary;
Macros§
Structs§
- Arbitrary
Default - An
Arbitrarywrapper that constructsTviaDefault. - Async
FnDriver - See
drive_fn - Poll
FnDriver - See
drive_poll_fn - Sink
Driver
Traits§
- Driver
- The other side of the leaf future under test, responsible for making it progress.
- Test
Case - Defines a future to test for waker correctness, along with the
Driverthat makes it progress.
Functions§
- drive_
fn - Construct a
Driverfrom anAsyncFnMut. - drive_
poll_ fn - Construct a
Driverfrom a synchronousFnMut. - drive_
sink - Construct a
Driverfrom aSink. - tests
- Construct the test runner for this
TestCase.