test_executors

This crate provides extremely simple, yet useful, async executors. They are primarily useful for writing unit tests without bringing in a full-blown executor such as tokio.
Quick Start
use ;
// Run a simple async function
let result = spin_on;
assert_eq!;
// Run an async function that sleeps
let result = sleep_on;
assert_eq!;
Available Executors
The crate provides three main executors:
spin_on
Polls a future in a busy loop on the current thread. Best for CPU-bound tasks or when latency is critical.
When to Use:
- When you need minimal latency
- For CPU-bound async tasks
- In tests where you want deterministic behavior
- When the future is expected to complete quickly
Performance Note: This executor will consume 100% CPU while waiting. For I/O-bound tasks or long-running futures, consider using sleep_on instead.
use spin_on;
let result = spin_on;
assert_eq!;
sleep_on
Polls a future on the current thread, sleeping between polls. Best for I/O-bound tasks to avoid burning CPU.
When to Use:
- For I/O-bound async tasks
- When you want to avoid burning CPU cycles
- For longer-running futures
- In tests that involve actual async I/O or timers
Implementation Details: The executor will properly handle spurious wakeups and re-poll the future as needed. The waker implementation uses a semaphore to signal readiness.
use sleep_on;
use Future;
use Pin;
use ;
let result = sleep_on;
assert_eq!;
spawn_on
Spawns a future on a new thread and returns immediately without waiting for completion.
This function creates a new OS thread with the given name and runs the future on that thread using sleep_on. The calling thread returns immediately, making this useful for fire-and-forget tasks.
Parameters:
thread_name: The name to give to the spawned thread (must be a static string)future: The future to execute on the new thread
Requirements:
- The future must be
Sendbecause it will be moved to another thread - The future must be
'staticbecause the spawned thread may outlive the caller
Example:
use spawn_on;
use ;
use Duration;
let data = new;
let data_clone = data.clone;
spawn_on;
// Give the spawned thread time to complete
sleep;
// Check the result
assert_eq!;
Panics: Panics if the thread cannot be spawned (e.g., due to resource exhaustion).
See Also:
spawn_localfor a platform-aware version that works on WASM
Platform Support
Native Platforms
All executors work as described above on native platforms (Linux, macOS, Windows, etc.).
WebAssembly Support
This crate has special support for wasm32 targets:
- The
async_testmacro automatically adapts to usewasm-bindgen-teston WASM spawn_localuseswasm_bindgen_futures::spawn_localon WASM targets
Features
async_test Macro
The async_test macro allows you to write async tests that work on both native and WASM targets:
use async_test;
async
Integration with some_executor
This crate implements the some_executor trait for all executors, allowing them to be used in executor-agnostic code:
use SpinRuntime;
use SomeExecutor;
let mut runtime = new;
// Use runtime with some_executor traits
Utilities
The crate also provides utility functions and types:
spawn_local
Spawns a future in a platform-appropriate way without waiting for completion.
This function automatically selects the appropriate executor based on the target platform:
- On native platforms (Linux, macOS, Windows, etc.): Uses
sleep_onto run the future on the current thread - On
wasm32targets: Useswasm_bindgen_futures::spawn_localto integrate with the browser's event loop
Parameters:
future: The future to execute_debug_label: A label for debugging purposes (used for logging context on WASM)
Example:
use spawn_local;
spawn_local;
Platform Behavior:
Native Platforms:
The future is executed immediately on the current thread using sleep_on. This blocks until the future completes.
WebAssembly: The future is scheduled to run on the browser's event loop and this function returns immediately. The future will run when the JavaScript runtime is ready.
Note:
Unlike spawn_on, this function does not require the future to be Send since it may run on the current thread.
poll_once and poll_once_pin
Poll a future exactly once - useful for testing futures or implementing custom executors.
poll_once
Polls a pinned future exactly once and returns the result.
This function is useful for testing futures or implementing custom executors. It creates a no-op waker that does nothing when wake() is called.
Parameters:
future: A pinned mutable reference to the future to poll
Returns:
Poll::Ready(value)if the future completed on this pollPoll::Pendingif the future is not yet ready
Example:
use poll_once;
use Poll;
let mut future = ;
let result = poll_once;
assert_eq!;
Testing Example:
use poll_once;
use Future;
use Pin;
use ;
let mut future = CounterFuture ;
let mut pinned = pin!;
assert_eq!;
assert_eq!;
assert_eq!;
poll_once_pin
Polls a future exactly once after pinning it.
This is a convenience function that takes ownership of the future, pins it, and polls it once. Unlike poll_once, you don't need to pin the future yourself.
Parameters:
future: The future to poll (takes ownership)
Returns:
Poll::Ready(value)if the future completed on this pollPoll::Pendingif the future is not yet ready
Example:
use poll_once_pin;
use Poll;
let future = ;
let result = poll_once_pin;
assert_eq!;
Comparison with poll_once:
use ;
use Poll;
// Using poll_once_pin (takes ownership)
let future1 = async ;
assert_eq!;
// Using poll_once (borrows)
let mut future2 = async ;
let mut pinned = pin!;
assert_eq!;
Limitations:
Since this function takes ownership of the future, you cannot poll it again after calling this function. If you need to poll a future multiple times, use poll_once instead.