Skip to main content

MockClock

Struct MockClock 

Source
pub struct MockClock { /* private fields */ }
Expand description

A controllable clock implementation for testing.

MockClock allows you to adjust logical time, making it useful for testing time-dependent code. Readings are frozen after construction by default. set_time() reanchors the logical time without changing the current progression mode or auto-advance settings. Use this type when the code under test reads the current time through Clock. Use MockNanoClock for code that needs NanoClock. For code that actually sleeps or waits for retry/backoff intervals, inject crate::sleep::MockSleeper separately; advancing a MockClock does not complete mock sleeps.

§Features

  • Align the logical current time to a specific time
  • Advance the clock by a duration
  • Automatically advance time on each call
  • Switch between frozen and monotonic progression
  • Reset to the initial creation state

§Testing guidance

MockClock controls what “now” means to the code under test. It does not model blocking or asynchronous sleeping. If a component needs both a clock and a sleeper, tests should inject both MockClock and crate::sleep::MockSleeper and advance them independently.

§Thread Safety

This type is thread-safe, using Arc<Mutex<>> internally to protect its mutable state.

§Examples

use qubit_clock::{Clock, ControllableClock, MockClock};
use chrono::{DateTime, Duration, Utc};

let clock = MockClock::new();

// Set to a specific time
let fixed_time = DateTime::parse_from_rfc3339(
    "2024-01-01T00:00:00Z"
).unwrap().with_timezone(&Utc);
clock.set_time(fixed_time);
assert_eq!(clock.time(), fixed_time);

// Advance by 1 hour
clock.add_duration(Duration::hours(1));
assert_eq!(clock.time(), fixed_time + Duration::hours(1));

// Reset to initial state
clock.reset();

Implementations§

Source§

impl MockClock

Source

pub fn new() -> Self

Creates a new MockClock.

The clock is initialized with the current system time and remains frozen at that instant until adjusted by the control methods or switched to monotonic progression.

§Returns

A new MockClock instance.

§Examples
use qubit_clock::MockClock;

let clock = MockClock::new();
Source

pub fn with_progression(progression: MockClockProgression) -> Self

Creates a new MockClock with the specified progression mode.

The clock starts at the current system time. In Frozen mode, readings stay fixed until explicitly advanced. In Monotonic mode, readings progress naturally from the initial system time.

§Arguments
  • progression - The initial progression mode.
§Examples
use qubit_clock::{MockClock, MockClockProgression};

let clock = MockClock::with_progression(MockClockProgression::Monotonic);
assert_eq!(clock.progression(), MockClockProgression::Monotonic);
Source

pub fn progression(&self) -> MockClockProgression

Returns the current progression mode.

§Examples
use qubit_clock::{MockClock, MockClockProgression};

let clock = MockClock::new();
assert_eq!(clock.progression(), MockClockProgression::Frozen);
Source

pub fn set_progression(&self, progression: MockClockProgression)

Switches the clock progression mode without changing the current reading.

The current logical reading is first folded into the clock’s base state, so changing between frozen and monotonic modes does not cause an immediate time jump.

§Arguments
  • progression - The new progression mode.
§Examples
use qubit_clock::{MockClock, MockClockProgression};

let clock = MockClock::new();
clock.set_progression(MockClockProgression::Monotonic);
assert_eq!(clock.progression(), MockClockProgression::Monotonic);
Source

pub fn monotonic_progression_enabled(&self) -> bool

Returns whether monotonic progression is enabled.

§Examples
use qubit_clock::MockClock;

let clock = MockClock::new();
assert!(!clock.monotonic_progression_enabled());
Source

pub fn set_monotonic_progression_enabled(&self, enabled: bool)

Enables or disables monotonic progression.

This is a boolean convenience wrapper around set_progression().

§Arguments
  • enabled - true to use monotonic progression, false to freeze.
§Examples
use qubit_clock::MockClock;

let clock = MockClock::new();
clock.set_monotonic_progression_enabled(true);
assert!(clock.monotonic_progression_enabled());
Source

pub fn add_millis(&self, millis: i64, add_every_time: bool)

Adds a fixed amount of milliseconds to the clock.

§Arguments
  • millis - The number of milliseconds to add.
  • add_every_time - If true, the specified milliseconds will be added on every call to millis(). If false, the milliseconds are added only once.
§Examples
use qubit_clock::{Clock, MockClock};

let clock = MockClock::new();
let before = clock.millis();

// Add 1000ms once
clock.add_millis(1000, false);
assert_eq!(clock.millis(), before + 1000);

// Add 100ms on every call
clock.add_millis(100, true);
let t1 = clock.millis();
let t2 = clock.millis();
assert_eq!(t2 - t1, 100);
Source

pub fn advance_millis(&self, millis: i64)

Advances the clock by a fixed amount once.

This method updates the offset used by millis() and time() without enabling auto-advance. If the accumulated offset exceeds the i64 range, it saturates at the nearest boundary.

§Arguments
  • millis - The milliseconds to add once.
§Examples
use qubit_clock::{Clock, MockClock};

let clock = MockClock::new();
let before = clock.millis();
clock.advance_millis(1000);
assert_eq!(clock.millis(), before + 1000);
Source

pub fn set_auto_advance_millis(&self, millis: i64)

Enables auto-advance on each read operation.

After calling this method, each call to millis() or time() returns the current logical time and advances the next read by millis.

§Arguments
  • millis - The milliseconds to advance on each read.
§Examples
use qubit_clock::{Clock, MockClock};

let clock = MockClock::new();
clock.set_auto_advance_millis(100);
let t1 = clock.millis();
let t2 = clock.millis();
assert_eq!(t2 - t1, 100);
Source

pub fn clear_auto_advance(&self)

Disables auto-advance behavior.

This method clears the per-read advance setting. Subsequent read operations will no longer mutate the clock state.

§Examples
use qubit_clock::{Clock, MockClock};

let clock = MockClock::new();
clock.set_auto_advance_millis(100);
let _ = clock.millis();
clock.clear_auto_advance();
let t1 = clock.millis();
let t2 = clock.millis();
assert_eq!(t2, t1);

Trait Implementations§

Source§

impl Clock for MockClock

Source§

fn millis(&self) -> i64

Returns the current time as a Unix timestamp in milliseconds (UTC). Read more
Source§

fn time(&self) -> DateTime<Utc>

Returns the current time as a DateTime<Utc>. Read more
Source§

impl Clone for MockClock

Source§

fn clone(&self) -> MockClock

Returns a duplicate of the value. Read more
1.0.0 (const: unstable) · Source§

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

Performs copy-assignment from source. Read more
Source§

impl ControllableClock for MockClock

Source§

fn set_time(&self, instant: DateTime<Utc>)

Sets or aligns the clock to a specific time. Read more
Source§

fn add_duration(&self, duration: Duration)

Advances the clock by the specified duration. Read more
Source§

fn reset(&self)

Resets the clock to its initial state. Read more
Source§

impl Debug for MockClock

Source§

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

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

impl Default for MockClock

Source§

fn default() -> Self

Returns the “default value” for a type. 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> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

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