Skip to main content

sequoia_async/
testing.rs

1#![forbid(unsafe_code)]
2
3use std::time::{Duration, Instant};
4
5pub fn drain_until<R>(rt: &R, timeout: Duration) -> usize
6where
7    R: TestDrain,
8{
9    let deadline = Instant::now() + timeout;
10    loop {
11        let n = rt.test_drain();
12        if n > 0 || Instant::now() >= deadline {
13            return n;
14        }
15        std::thread::sleep(Duration::from_millis(2));
16    }
17}
18
19pub fn run_until<R>(rt: &R, timeout: Duration, mut predicate: impl FnMut() -> bool) -> bool
20where
21    R: TestDrain,
22{
23    let deadline = Instant::now() + timeout;
24    while Instant::now() < deadline {
25        rt.test_drain();
26        if predicate() {
27            return true;
28        }
29        std::thread::sleep(Duration::from_millis(2));
30    }
31    rt.test_drain();
32    predicate()
33}
34
35pub trait TestDrain {
36    fn test_drain(&self) -> usize;
37}
38
39impl TestDrain for crate::runtime::AsyncRuntime {
40    fn test_drain(&self) -> usize {
41        self.drain()
42    }
43}
44
45#[cfg(test)]
46mod tests {
47    use super::*;
48
49    struct Counter {
50        n: std::cell::Cell<usize>,
51        fire_at: usize,
52    }
53
54    impl TestDrain for Counter {
55        fn test_drain(&self) -> usize {
56            let n = self.n.get() + 1;
57            self.n.set(n);
58            if n >= self.fire_at { 1 } else { 0 }
59        }
60    }
61
62    #[test]
63    fn drain_until_returns_on_fire() {
64        let c = Counter {
65            n: std::cell::Cell::new(0),
66            fire_at: 3,
67        };
68        assert_eq!(drain_until(&c, Duration::from_secs(2)), 1);
69    }
70
71    #[test]
72    fn run_until_respects_predicate() {
73        let c = Counter {
74            n: std::cell::Cell::new(0),
75            fire_at: 100,
76        };
77        assert!(!run_until(&c, Duration::from_millis(10), || false));
78    }
79}