opentitanlib/test_utils/poll.rs
1// Copyright lowRISC contributors (OpenTitan project).
2// Licensed under the Apache License, Version 2.0, see LICENSE for details.
3// SPDX-License-Identifier: Apache-2.0
4
5//! Helper functions for polling in tests.
6//!
7//! Useful for waiting for results that may not be available immediately.
8
9use std::cmp;
10use std::thread;
11use std::time::{Duration, Instant};
12
13use anyhow::bail;
14
15/// Poll some operation until it returns `true` or a timeout is hit.
16///
17/// The provided function should return `Some(x)` when the condition is met,
18/// or `None` to continue polling.
19///
20/// `delay` can be used to prevent retrying the operation too frequently.
21pub fn poll_until<F>(timeout: Duration, delay: Duration, mut f: F) -> anyhow::Result<()>
22where
23 F: FnMut() -> anyhow::Result<bool>,
24{
25 let start = Instant::now();
26
27 loop {
28 // Check if we've exceeded the timeout before trying the function.
29 if start.elapsed() > timeout {
30 bail!("timed out");
31 }
32
33 // Run the provided function to see if we're finished polling.
34 if f()? {
35 return Ok(());
36 } else {
37 // Delay between polls to prevent thrashing.
38 let remaining = timeout.saturating_sub(start.elapsed());
39 thread::sleep(cmp::min(delay, remaining));
40 }
41 }
42}