1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
//! Clocks, delays, and tests that do not have to wait for real time.
//!
//! Arty re-exports [`Clock`](crate::time::Clock) and, with `test-util`,
//! [`ClockControl`](crate::time::ClockControl) through `arty::time`. Use
//! [`tick`] directly for delay and timeout futures, extension traits,
//! stopwatches, and periodic timers. The `time` feature works without an Arty
//! runtime; `rt` also enables time and drives timers for its workers.
//!
//! # Use the task's clock
//!
//! Each task gets a clock through [`Builtins::clock`](crate::task::Builtins::clock).
//! Use a stopwatch for elapsed time and `system_time()` for a wall-clock
//! timestamp, which can change independently of elapsed time.
//!
//! ```
//! use std::future::pending;
//! use std::time::Duration;
//!
//! use arty::task::Builtins;
//! use tick::FutureExt;
//!
//! # #[arty::main]
//! # async fn main(cx: Builtins) {
//! let watch = cx.clock().stopwatch();
//! cx.clock().delay(Duration::from_millis(1)).await;
//! assert!(watch.elapsed() >= Duration::from_millis(1));
//!
//! let result = pending::<()>()
//! .timeout(cx.clock(), Duration::from_millis(1))
//! .await;
//! assert!(result.is_err());
//! # }
//! ```
//!
//! A busy worker may resume a task later than the requested delay. A timeout
//! limits how long you wait for a result; it does not cancel a spawned task.
//!
//! # Control time in tests
//!
//! Enable `test-util` in an Arty dev-dependency. A second
//! [`ClockControl`](crate::time::ClockControl) parameter to
//! [`arty::test`](crate::test) gives the test control over its runtime's clocks.
//! Time starts at the UNIX epoch and does not advance automatically.
//!
//! A delay starts its timer when first polled. Poll it before advancing time:
//!
//! ```test_harness
//! use std::future::{Future, poll_fn};
//! use std::pin::pin;
//! use std::task::Poll;
//! use std::time::Duration;
//!
//! use arty::task::Builtins;
//! use arty::time::ClockControl;
//!
//! #[arty::test]
//! async fn controlled_delay(cx: Builtins, control: ClockControl) {
//! let watch = cx.clock().stopwatch();
//! let mut delay = pin!(cx.clock().delay(Duration::from_secs(30)));
//! poll_fn(|context| {
//! assert!(delay.as_mut().poll(context).is_pending());
//! Poll::Ready(())
//! })
//! .await;
//! control.advance(Duration::from_secs(30));
//! assert_eq!(watch.elapsed(), Duration::from_secs(30));
//! delay.await;
//! }
//! ```
//!
//! `auto_advance_timers(true)` is convenient for one delay after another, but
//! it advances eagerly and does not guarantee concurrent timers finish in order.
//! Advance time explicitly when ordering matters. `auto_advance(duration)`
//! instead advances time on reads.
//!
//! `ClockControl` can be combined with `workers`. For a custom runtime builder,
//! create the control in a synchronous test and pass a clone to
//! [`RuntimeBuilder::clock`](crate::runtime::RuntimeBuilder::clock).
//!
//! # Without an Arty runtime
//!
//! Enabling `time` alone does not start a timer driver.
//! The underlying `tick::SimpleClock` reads time without a driver, but delays
//! on [`Clock`](crate::time::Clock) need a driver or controlled time. See
//! [`tick`] for using these clocks outside Arty.