Struct MockSleepProvider

Source
pub struct MockSleepProvider {
    state: Arc<Mutex<SleepSchedule>>,
}
👎Deprecated since 0.29.0
Expand description

A dummy SleepProvider instance for testing.

The MockSleepProvider ignores the current time, and instead keeps its own view of the current Instant and SystemTime. You can advance them in-step by calling advance(), and you can simulate jumps in the system clock by calling jump().

This is not for production use.

§Deprecated

This mock time facility has some limitations, notably lack of support for tasks, and a confusing API for controlling the mock time.

New test cases should probably use MockRuntime which incorporates MockSimpletimeProvider.

Comparison of MockSleepProvider with SimpleMockTimeProvider:

  • SimpleMockTimeProvider does not support, or expect the use of, block_advance et al. Instead, the advancement of simulated time is typically done automatically in cooperation with the executor, using MockRuntime’s advance_* methods.

  • Consequently, SimpleMockTimeProvider can be used in test cases that spawn tasks and perform sleeps in them.

  • And, consequently, SimpleMockTimeProvider does not need non-test code to contain calls which are solely related to getting the time mocking to work right.

  • SimpleMockTimeProvider gives correct sleeping locations with MockExecutor‘s dump of sleeping tasks’ stack traces.

  • Conversely, to use SimpleMockTimeProvider in all but the most simple test cases, coordination with the executor is required. This coordination is provided by the integrated MockRuntime; SimpleMockTimeProvider is of limited usefulness by itself.

§Examples

Suppose you’ve written a function that relies on making a connection to the network and possibly timing out:

use tor_rtcompat::{Runtime,SleepProviderExt};
use std::{net::SocketAddr, io::Result, time::Duration, io::Error};
use futures::io::AsyncWriteExt;

async fn say_hi(runtime: impl Runtime, addr: &SocketAddr) -> Result<()> {
   let delay = Duration::new(5,0);
   runtime.timeout(delay, async {
      let mut conn = runtime.connect(addr).await?;
      conn.write_all(b"Hello world!\r\n").await?;
      conn.close().await?;
      Ok::<_,Error>(())
   }).await??;
   Ok(())
}

But how should you test this function?

You might try connecting to a well-known website to test the connection case, and to a well-known black hole to test the timeout case… but that’s a bit undesirable. Your tests might be running in a container with no internet access; and even if they aren’t, it isn’t so great for your tests to rely on the actual state of the internet. Similarly, if you make your timeout too long, your tests might block for a long time; but if your timeout is too short, the tests might fail on a slow machine or on a slow network.

Or, you could solve both of these problems by using tor-rtmock to replace the internet and the passage of time. (Here we’re only replacing the internet.)

use tor_rtmock::{MockSleepRuntime,MockNetRuntime,net::MockNetwork};
use tor_rtcompat::{NetStreamProvider,NetStreamListener};
use futures::io::AsyncReadExt;
use std::net::SocketAddr;
use futures::StreamExt as _;

tor_rtcompat::test_with_all_runtimes!(|rt| async move {

   let addr1 = "198.51.100.7".parse().unwrap();
   let addr2 = "198.51.100.99".parse().unwrap();
   let sockaddr: SocketAddr = "198.51.100.99:101".parse().unwrap();

   // Make a runtime that pretends that we are at the first address...
   let fake_internet = MockNetwork::new();
   let rt1 = fake_internet.builder().add_address(addr1).runtime(rt.clone());
   // ...and one that pretends we're listening at the second address.
   let rt2 = fake_internet.builder().add_address(addr2).runtime(rt);
   let listener = rt2.listen(&sockaddr).await.unwrap();
   let mut incoming_stream = listener.incoming();

   // Now we can test our function!
   let (result1,output) = futures::join!(
          say_hi(rt1, &sockaddr),
          async {
              let (mut conn,addr) = incoming_stream.next().await.unwrap().unwrap();
              assert_eq!(addr.ip(), addr1);
              let mut output = Vec::new();
              conn.read_to_end(&mut output).await.unwrap();
              output
          });

   assert!(result1.is_ok());
   assert_eq!(&output[..], b"Hello world!\r\n");
});

Fields§

§state: Arc<Mutex<SleepSchedule>>
👎Deprecated since 0.29.0

The shared backend for this MockSleepProvider and its futures.

Implementations§

Source§

impl MockSleepProvider

Source

pub fn new(wallclock: SystemTime) -> Self

Create a new MockSleepProvider, starting at a given wall-clock time.

Source

pub async fn advance(&self, dur: Duration)

Advance the simulated timeline forward by dur.

Calling this function will wake any pending futures as appropriate, and yield to the scheduler so they get a chance to run.

§Limitations

This function advances time in one big step. We might instead want to advance in small steps and make sure that each step’s futures can get run before the ones scheduled to run after it.

Source

pub(crate) fn advance_noyield(&self, dur: Duration)

Advance the simulated timeline forward by dur.

Calling this function will wake any pending futures as appropriate, but not yield to the scheduler. Mostly you should call advance instead.

Source

pub fn jump_to(&self, new_wallclock: SystemTime)

Simulate a discontinuity in the system clock, by jumping to new_wallclock.

§Panics

Panics if we have already panicked while holding the lock on the internal timer state, and the lock is poisoned.

Source

pub(crate) 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).

Source

pub(crate) fn should_advance(&mut self) -> bool

Return true if a WaitFor driving this sleep provider should advance time in order for futures blocked on sleeping to make progress.

NOTE: This function has side-effects; if it returns true, the caller is expected to do an advance before calling it again.

Source

pub(crate) fn register_waitfor_waker(&mut self, waker: Waker)

Register a Waker to be woken up when an advance in time is required to make progress.

This is used by WaitFor.

Source

pub(crate) fn clear_waitfor_waker(&mut self)

Remove a previously registered Waker registered with register_waitfor_waker().

Source

pub(crate) fn has_waitfor_waker(&self) -> bool

Returns true if a Waker has been registered with register_waitfor_waker().

This is used to ensure that you don’t have two concurrent WaitFors running.

Trait Implementations§

Source§

impl Clone for MockSleepProvider

Source§

fn clone(&self) -> MockSleepProvider

Returns a duplicate 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 CoarseTimeProvider for MockSleepProvider

Source§

fn now_coarse(&self) -> CoarseInstant

Return the CoarseTimeProvider’s view of the current instant. Read more
Source§

impl Debug for MockSleepProvider

Source§

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

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

impl Default for MockSleepProvider

Source§

fn default() -> Self

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

impl SleepProvider for MockSleepProvider

Source§

type SleepFuture = Sleeping

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

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

Return a future that will be ready after duration has elapsed.
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§

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

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> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

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

Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

§

impl<T> Instrument for T

§

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

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

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> IntoEither for T

Source§

fn into_either(self, into_left: bool) -> Either<Self, Self>

Converts self into a Left variant of Either<Self, Self> if into_left is true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
where F: FnOnce(&Self) -> bool,

Converts self into a Left variant of Either<Self, Self> if into_left(&self) returns true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
§

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

§

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

Wrap a Future with a timeout. Read more
§

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
Source§

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

Source§

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>,

Source§

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>,

Source§

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.
§

impl<T> WithSubscriber for T

§

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
§

fn with_current_subscriber(self) -> WithDispatch<Self>

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

impl<T> ErasedDestructor for T
where T: 'static,

§

impl<T> MaybeSendSync for T