[go: up one dir, main page]

Struct tor_rtmock::MockRuntime

source ·
pub struct MockRuntime { /* private fields */ }
Expand description

Completely mock runtime

Suitable for test cases that wish to completely control the environment experienced by the code under test.

Restrictions

The test case must advance the mock time explicitly as desired, typically by calling one of the MockRuntime::advance_* methods.

Tests that use this runtime must not interact with the outside world; everything must go through this runtime (and its pieces).

Allowed
  • Inter-future communication facilities from futures or other runtime-agnostic crates.

  • Fast synchronous operations that will complete “immediately” or “quickly”. E.g.: filesystem calls.

  • std::sync::Mutex (assuming the use is deadlock-free in a single-threaded executor, as it should be in all of Arti).

  • Slower operations that are run synchronously (without futures await) provided their completion doesn’t depend on any of the futures we’re running. (These kind of operations are often discouraged in async contexts, because they block the async runtime or its worker threads. But they are often OK in tests.)

  • All facilities provided by this MockExecutor and its trait impls.

Not allowed
  • Direct access to the real-world clock (SystemTime::now, Instant::now). Including coarsetime, which is not mocked. Exception: CPU use measurements.

  • Anything that spawns threads and then communicates with those threads using async Rust facilities (futures).

  • Async sockets, or async use of other kernel-based IPC or network mechanisms.

  • Anything provided by a Rust runtime/executor project (eg anything from Tokio), unless it is definitively established that it’s runtime-agnostic.

Implementations§

source§

impl MockRuntime

source

pub fn mock_task(&self) -> &MockExecutor

Method borrowing MockRuntime::task field. Tasks

source

pub fn mock_sleep(&self) -> &SimpleMockTimeProvider

Method borrowing MockRuntime::sleep field. Time provider

source

pub fn mock_net(&self) -> &MockNetProvider

Method borrowing MockRuntime::net field. Net provider

source§

impl MockRuntime

source

pub fn new() -> Self

Create a new MockRuntime with default parameters

source

pub fn builder() -> MockRuntimeBuilder

Return a builder, for creating a MockRuntime with some parameters manually configured

source

pub fn test_with_various<TC, FUT>(test_case: TC)
where TC: FnMut(MockRuntime) -> FUT, FUT: Future<Output = ()>,

Run a test case with a variety of runtime parameters, to try to find bugs

test_case is an async closure which receives a MockRuntime. It will be run with a number of differently configured executors.

Each run will be preceded by an eprintln! showing the runtime configuration.

Variations

The only variation currently implemented is this:

Both FIFO and LIFO scheduling policies are tested, in the hope that this will help discover ordering-dependent bugs.

source

pub fn try_test_with_various<TC, FUT, E>(test_case: TC) -> Result<(), E>
where TC: FnMut(MockRuntime) -> FUT, FUT: Future<Output = Result<(), E>>,

Run a faillible test case with a variety of runtime parameters, to try to find bugs

test_case is an async closure which receives a MockRuntime. It will be run with a number of differently configured executors.

This function accepts a fallible closure, and returns the first Err to the caller.

See test_with_various() for more details.

source

pub fn spawn_identified( &self, desc: impl Display, fut: impl Future<Output = ()> + Send + 'static ) -> impl Debug + Clone + Send + 'static

Spawn a task and return something to identify it

See MockExecutor::spawn_identified()

source

pub fn spawn_join<T: Debug + Send + 'static>( &self, desc: impl Display, fut: impl Future<Output = T> + Send + 'static ) -> impl Future<Output = T>

Spawn a task and return its output for further usage

See MockExecutor::spawn_join()

source

pub async fn advance_until_stalled(&self)

Run tasks and advance time, until every task except this one is waiting

On return the other tasks won’t be waiting on timeouts, since time will be advanced as needed.

Therefore the other tasks (if any) will be waiting for something that won’t happen by itself, such as a provocation via their APIs from this task.

Panics

See progress_until_stalled

source

pub async fn progress_until_stalled(&self)

Run tasks in the current executor until every task except this one is waiting

Calls MockExecutor::progress_until_stalled().

Restriction - no automatic time advance

The mocked time will not be automatically advanced.

Usually (and especially if the tasks under test are waiting for timeouts or periodic events) you must use advance_by() or advance_until() to ensure the simulated time progresses as required.

Panics

Might malfunction or panic if more than one such call is running at once.

(Ie, you must .await or drop the returned Future before calling this method again.)

Must be called and awaited within a future being run by self.

source

pub async fn advance_until(&self, limit: Instant) -> Option<Duration>

Run tasks and advance time up to at most limit

Will return when all other tasks are either:

  • Waiting on a timeout that will fire strictly after limit, (return value is the time until the earliest such)
  • Waiting for something else that won’t happen by itself. (return value is None)

Like advance_until_stalled but stops when the mock time reaches limit.

Panics

Panics if the time somehow advances beyond limit. (This function won’t do that, but maybe it was beyond limit on entry, or another task advanced the clock.)

And, see progress_until_stalled

source

pub async fn advance_by(&self, dur: Duration) -> Option<Duration>

Advances time by dur, firing time events and other tasks in order

Prefer this to SimpleMockTimeProvider::advance(); it works more faithfully.

Specifically, it advances time in successive stages, so that timeouts occur sequentially, in the right order.

Panics

Can panic if the mock time is advanced by other tasks.

And, see progress_until_stalled

source

pub fn jump_wallclock(&self, new_wallclock: SystemTime)

source

pub fn time_until_next_timeout(&self) -> Option<Duration>

Return the amount of virtual time until the next timeout should elapse.

If there are no more timeouts, return None.

If the next timeout should elapse right now, return Some(0). However, if other tasks are proceeding, typically in that situation those other tasks will wake, so a Some(0) return won’t be visible. In test cases, detect immediate timeouts by detecting what your task does after the timeout occurs.

Likewise whether this function returns None or Some(...) can depend on whether tasks have actually yet polled various futures. The answer should be correct after progress_until_stalled.

Trait Implementations§

source§

impl BlockOn for MockRuntime

source§

fn block_on<F: Future>(&self, future: F) -> F::Output

Run future until it is ready, and return its output.
source§

impl Clone for MockRuntime

source§

fn clone(&self) -> MockRuntime

Returns a copy of the value. Read more
1.0.0 · source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
source§

impl Debug for MockRuntime

source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
source§

impl Default for MockRuntime

source§

fn default() -> MockRuntime

Returns the “default value” for a type. Read more
source§

impl SleepProvider for MockRuntime

§

type SleepFuture = <SimpleMockTimeProvider as SleepProvider>::SleepFuture

A future returned by SleepProvider::sleep()
source§

fn sleep(&self, dur: Duration) -> Self::SleepFuture

Return a future that will be ready after duration has elapsed.
source§

fn now(&self) -> Instant

Return the SleepProvider’s view of the current instant. Read more
source§

fn wallclock(&self) -> SystemTime

Return the SleepProvider’s view of the current wall-clock time. Read more
source§

fn block_advance<T: Into<String>>(&self, reason: T)

Signify that a test running under mock time shouldn’t advance time yet, with a given unique reason string. This is useful for making sure (mock) time doesn’t advance while things that might require some (real-world) time to complete do so, such as spawning a task on another thread. Read more
source§

fn release_advance<T: Into<String>>(&self, reason: T)

Signify that the reason to withhold time advancing provided in a call to block_advance no longer exists, and it’s fine to move time forward if nothing else is blocking advances. Read more
source§

fn allow_one_advance(&self, dur: Duration)

Allow a test running under mock time to advance time by the provided duration, even if the above block_advance API has been used. Read more
source§

impl Spawn for MockRuntime

source§

fn spawn_obj(&self, future: FutureObj<'static, ()>) -> Result<(), SpawnError>

Spawns a future that will be run to completion. Read more
§

fn status(&self) -> Result<(), SpawnError>

Determines whether the executor is able to spawn new tasks. Read more
source§

impl TcpProvider for MockRuntime

§

type TcpStream = <MockNetProvider as TcpProvider>::TcpStream

The type for the TCP connections returned by Self::connect().
§

type TcpListener = <MockNetProvider as TcpProvider>::TcpListener

The type for the TCP listeners returned by Self::listen().
source§

fn connect<'life0, 'life1, 'async_trait>( &'life0 self, addr: &'life1 SocketAddr ) -> Pin<Box<dyn Future<Output = IoResult<Self::TcpStream>> + Send + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait,

Launch a TCP connection to a given socket address. Read more
source§

fn listen<'life0, 'life1, 'async_trait>( &'life0 self, addr: &'life1 SocketAddr ) -> Pin<Box<dyn Future<Output = IoResult<Self::TcpListener>> + Send + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait,

Open a TCP listener on a given socket address.
source§

impl TlsProvider<<MockNetProvider as TcpProvider>::TcpStream> for MockRuntime

§

type Connector = <MockNetProvider as TlsProvider<<MockNetProvider as TcpProvider>::TcpStream>>::Connector

The Connector object that this provider can return.
§

type TlsStream = <MockNetProvider as TlsProvider<<MockNetProvider as TcpProvider>::TcpStream>>::TlsStream

The type of the stream returned by that connector.
source§

fn tls_connector(&self) -> Self::Connector

Return a TLS connector for use with this runtime.
source§

impl UdpProvider for MockRuntime

§

type UdpSocket = <MockNetProvider as UdpProvider>::UdpSocket

The type of Udp Socket returned by Self::bind()
source§

fn bind<'life0, 'life1, 'async_trait>( &'life0 self, addr: &'life1 SocketAddr ) -> Pin<Box<dyn Future<Output = IoResult<Self::UdpSocket>> + Send + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait,

Bind a local port to send and receive packets from

Auto Trait Implementations§

Blanket Implementations§

source§

impl<T> Any for T
where T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Borrow<T> for T
where T: ?Sized,

source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
source§

impl<T> From<T> for T

source§

fn from(t: T) -> T

Returns the argument unchanged.

source§

impl<T> Instrument for T

source§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided Span, returning an Instrumented wrapper. Read more
source§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
source§

impl<T, U> Into<U> for T
where U: From<T>,

source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

source§

impl<T> SleepProviderExt for T
where T: SleepProvider,

source§

fn timeout<F>( &self, duration: Duration, future: F ) -> Timeout<F, Self::SleepFuture>
where F: Future,

Wrap a Future with a timeout. Read more
source§

fn sleep_until_wallclock( &self, when: SystemTime ) -> SleepUntilWallclock<'_, Self>

Pause until the wall-clock is at when or later, trying to recover from clock jumps. Read more
§

impl<Sp> SpawnExt for Sp
where Sp: Spawn + ?Sized,

§

fn spawn<Fut>(&self, future: Fut) -> Result<(), SpawnError>
where Fut: Future<Output = ()> + Send + 'static,

Available on crate feature alloc only.
Spawns a task that polls the given future with output () to completion. Read more
§

fn spawn_with_handle<Fut>( &self, future: Fut ) -> Result<RemoteHandle<<Fut as Future>::Output>, SpawnError>
where Fut: Future + Send + 'static, <Fut as Future>::Output: Send,

Available on crate features channel and std only.
Spawns a task that polls the given future to completion and returns a future that resolves to the spawned future’s output. Read more
source§

impl<T> ToOwned for T
where T: Clone,

§

type Owned = T

The resulting type after obtaining ownership.
source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

§

type Error = Infallible

The type returned in the event of a conversion error.
source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
source§

impl<T> WithSubscriber for T

source§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a WithDispatch wrapper. Read more
source§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a WithDispatch wrapper. Read more
source§

impl<T> Runtime for T
where T: Sync + Send + Spawn + BlockOn + Clone + SleepProvider + TcpProvider + TlsProvider<<T as TcpProvider>::TcpStream> + UdpProvider + Debug + 'static,