Crates.io | async-time-mock-smol |
lib.rs | async-time-mock-smol |
version | 0.2.0 |
source | src |
created_at | 2023-01-11 23:03:08.247655 |
updated_at | 2024-01-22 23:19:58.907321 |
description | Mockable time for use in async runtimes (smol compatibility). |
homepage | |
repository | |
max_upload_size | |
id | 756745 |
size | 13,411 |
Asynchronous time mocking for the smol runtime based on async-time-mock-core, inspired by the approach described in Mocking Time In Async Rust.
NOTE: This library is still in it's infancy, the API is still likely to change (read: improve). Please leave your feedback and suggestions on GitHub.
ALSO NOTE: This currently implements an API that looks more like from the tokio runtime instead of smol's Timer
API. This might change in the future.
mock
: Enable the mock clock. If you only enable this in tests, this library turns into a thin wrapper around async-std's time functions.stream
: Implement futures_core::stream::Stream
for Interval
use async_time_mock_smol::MockableClock;
use std::{
sync::atomic::{AtomicBool, Ordering},
time::Duration,
};
static HAS_SLEPT: AtomicBool = AtomicBool::new(false);
async fn sleep(clock: MockableClock) {
// Sleep is either mocked or a real smol::Timer::set_after, depending on which variant of `MockableClock` you pass in.
let _guard = clock.sleep(Duration::from_secs(3600)).await;
// Dropping this guard signifies that all the effects of the timer have finished.
// This allows test code to wait until the condition to assert for has happened.
println!("Slept for an hour");
HAS_SLEPT.store(true, Ordering::SeqCst);
}
fn main() {
smol::block_on(
async {
let (clock, controller) = MockableClock::mock(); // In production, you can use MockableClock::Real instead
smol::spawn(sleep(clock)).detach();
controller.advance_time(Duration::from_secs(600)).await;
assert!(!HAS_SLEPT.load(Ordering::SeqCst), "Timer won't trigger after just 10 minutes.");
// advance_time will first trigger the sleep in the task above and then wait until the `_guard` was dropped.
// This ensures that the task had enough time to actually set `HAS_SLEPT` to `true`.
controller.advance_time(Duration::from_secs(3000)).await;
assert!(HAS_SLEPT.load(Ordering::SeqCst), "Timer has triggered after 1 hour.")
}
);
}