//! Declare MockSleepRuntime. use crate::time::MockSleepProvider; use tor_rtcompat::{Runtime, SleepProvider, SpawnBlocking, TcpProvider, TlsProvider}; use async_trait::async_trait; use futures::task::{FutureObj, Spawn, SpawnError}; use futures::Future; use std::io::Result as IoResult; use std::net::SocketAddr; use std::time::{Duration, Instant, SystemTime}; /// A wrapper Runtime that overrides the SleepProvider trait for the /// underlying runtime. #[derive(Clone)] pub struct MockSleepRuntime { /// The underlying runtime. Most calls get delegated here. runtime: R, /// A MockSleepProvider. Time-related calls get delegated here. sleep: MockSleepProvider, } impl MockSleepRuntime { /// Create a new runtime that wraps `runtime`, but overrides /// its view of time with a [`MockSleepProvider`]. pub fn new(runtime: R) -> Self { let sleep = MockSleepProvider::new(SystemTime::now()); MockSleepRuntime { runtime, sleep } } /// Return a reference to the underlying runtime. pub fn inner(&self) -> &R { &self.runtime } /// Return a reference to the [`MockSleepProvider`] pub fn mock_sleep(&self) -> &MockSleepProvider { &self.sleep } /// See [`MockSleepProvider::advance()`] pub async fn advance(&self, dur: Duration) { self.sleep.advance(dur).await; } /// See [`MockSleepProvider::jump_to()`] pub fn jump_to(&self, new_wallclock: SystemTime) { self.sleep.jump_to(new_wallclock); } } impl Spawn for MockSleepRuntime { fn spawn_obj(&self, future: FutureObj<'static, ()>) -> Result<(), SpawnError> { self.runtime.spawn_obj(future) } } impl SpawnBlocking for MockSleepRuntime { fn block_on(&self, future: F) -> F::Output { self.runtime.block_on(future) } } #[async_trait] impl TcpProvider for MockSleepRuntime { type TcpStream = R::TcpStream; type TcpListener = R::TcpListener; async fn connect(&self, addr: &SocketAddr) -> IoResult { self.runtime.connect(addr).await } async fn listen(&self, addr: &SocketAddr) -> IoResult { self.runtime.listen(addr).await } } impl TlsProvider for MockSleepRuntime { type Connector = R::Connector; type TlsStream = R::TlsStream; fn tls_connector(&self) -> Self::Connector { self.runtime.tls_connector() } } impl SleepProvider for MockSleepRuntime { type SleepFuture = crate::time::Sleeping; fn sleep(&self, dur: Duration) -> Self::SleepFuture { self.sleep.sleep(dur) } fn now(&self) -> Instant { self.sleep.now() } fn wallclock(&self) -> SystemTime { self.sleep.wallclock() } }