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}