Skip to main content

TestClock

Struct TestClock 

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

A static test clock.

Stores the current timestamp internally which can be advanced.

§Threading

This clock is thread-affine; use it only from the thread that created it.

Implementations§

Source§

impl TestClock

Source

pub fn new() -> Self

Creates a new TestClock instance.

Source

pub const fn get_timers(&self) -> &BTreeMap<Ustr, TestTimer>

Returns a reference to the internal timers for the clock.

Source

pub fn advance_time( &mut self, to_time_ns: UnixNanos, set_time: bool, ) -> Vec<TimeEvent>

Advances the internal clock to the specified to_time_ns and optionally sets the clock to that time.

This function ensures that the clock behaves in a non-decreasing manner. If set_time is true, the internal clock will be updated to the value of to_time_ns. Otherwise, the clock will advance without explicitly setting the time.

The method processes active timers, advancing them to to_time_ns, and collects any TimeEvent objects that are triggered as a result. Only timers that are not expired are processed.

§Warnings

Logs a warning if >= 1,000,000 time events are allocated during advancement.

§Panics

Panics if to_time_ns is less than the current internal clock time.

Source

pub fn match_handlers(&self, events: Vec<TimeEvent>) -> Vec<TimeEventHandler>

Matches TimeEvent objects with their corresponding event handlers.

This function takes an events vector of TimeEvent objects, assumes they are already sorted by their ts_event, and matches them with the appropriate callback handler from the internal registry of callbacks. If no specific callback is found for an event, the default callback is used.

§Panics

Panics if the default callback is not set for the clock when matching handlers.

Methods from Deref<Target = AtomicTime>§

pub fn get_time_ns(&self) -> UnixNanos

Returns the current time in nanoseconds, based on the clock’s mode.

  • In real-time mode, calls [AtomicTime::time_since_epoch], ensuring strictly increasing timestamps across threads, using AcqRel semantics for the underlying atomic.
  • In static mode, reads the stored time using Ordering::Acquire. Updates by other threads using [AtomicTime::set_time] or [AtomicTime::increment_time] (Release/AcqRel) will be visible here.
§Thread Safety

The mode check is not atomic with the subsequent read/update. If another thread switches modes between the check and the operation, one stale-mode result may be returned. This is intentional: mode switching is a setup-time operation and should not occur concurrently with time operations.

pub fn get_time_us(&self) -> u64

Returns the current time as microseconds.

pub fn get_time_ms(&self) -> u64

Returns the current time as milliseconds.

pub fn get_time(&self) -> f64

Returns the current time as seconds.

pub fn set_time(&self, time: UnixNanos)

Manually sets a new time for the clock (only possible in static mode).

This uses an atomic store with Ordering::Release, so any thread reading with Ordering::Acquire will see the updated time. This does not enforce a total ordering among all threads, but is enough to ensure that once a thread sees this update, it also sees all writes made before this call in the writing thread.

Typically used in single-threaded scenarios or coordinated concurrency in static mode, since there’s no global ordering across threads.

§Panics

Panics if invoked when in real-time mode.

§Thread Safety

The mode check is not atomic with the subsequent store. If another thread calls make_realtime() between the check and store, the invariant can be violated. This is intentional: mode switching is a setup-time operation and should not occur concurrently with time operations. Callers must ensure mode switches are complete before resuming time operations.

pub fn increment_time(&self, delta: u64) -> Result<UnixNanos, Error>

Increments the current (static-mode) time by delta nanoseconds and returns the updated value.

Internally this uses AtomicU64::try_update with Ordering::AcqRel to ensure the increment is atomic and visible to readers using Acquire loads.

§Errors

Returns an error if the increment would overflow u64::MAX or if called while the clock is in real-time mode.

§Thread Safety

The mode check is not atomic with the subsequent update. If another thread calls make_realtime() between the check and update, the invariant can be violated. This is intentional: mode switching is a setup-time operation and should not occur concurrently with time operations. Callers must ensure mode switches are complete before resuming time operations.

pub fn time_since_epoch(&self) -> UnixNanos

Retrieves and updates the current “real-time” clock, returning a strictly increasing timestamp based on system time.

Internally:

  • We fetch now from SystemTime::now().
  • We do an atomic compare-and-exchange (using Ordering::AcqRel) to ensure the stored timestamp is never less than the last timestamp.

This ensures:

  1. Monotonic increments: The returned timestamp is strictly greater than the previous one (by at least 1 nanosecond).
  2. No backward jumps: If the OS time moves backward, we ignore that shift to preserve monotonicity.
  3. Visibility: In a multi-threaded environment, other threads see the updated value once this compare-and-exchange completes.
§Panics

Panics if the internal counter has reached u64::MAX, which would indicate the process has been running for longer than the representable range (~584 years) or the clock was manually corrupted.

pub fn make_realtime(&self)

Switches the clock to real-time mode (realtime = true).

If transitioning from static mode, the internal counter is reset to the current wall-clock time so that [AtomicTime::time_since_epoch] does not carry forward a timestamp set during static mode (e.g. a backtest far in the future).

Uses Ordering::SeqCst for the mode flag to ensure global ordering.

§Thread Safety

The mode swap and the counter reset are two separate atomic operations. A thread reading between them can observe real-time mode with the stale static-mode counter and return a timestamp derived from it (potentially far in the future), after which the reset moves the clock backwards. Mode switching is a setup-time operation and must not run concurrently with time reads.

pub fn make_static(&self)

Switches the clock to static mode (realtime = false).

If transitioning from real-time mode, the internal counter is snapshotted to the current wall-clock time so that subsequent static reads return a reasonable value rather than a stale or zero placeholder.

Uses Ordering::SeqCst for the mode flag to ensure global ordering.

§Thread Safety

The mode swap and the counter snapshot are two separate atomic operations; see [AtomicTime::make_realtime] for the race this implies. Mode switching is a setup-time operation and must not run concurrently with time reads.

Trait Implementations§

Source§

impl Clock for TestClock

Source§

fn get_handler(&self, event: TimeEvent) -> TimeEventHandler

Returns the handler for the given TimeEvent.

§Panics

Panics if no event-specific or default callback has been registered for the event.

Source§

fn timestamp_ns(&self) -> UnixNanos

Returns the current UNIX timestamp in nanoseconds (ns).
Source§

fn timestamp_us(&self) -> u64

Returns the current UNIX timestamp in microseconds (μs).
Source§

fn timestamp_ms(&self) -> u64

Returns the current UNIX timestamp in milliseconds (ms).
Source§

fn timestamp(&self) -> f64

Returns the current UNIX timestamp in seconds.
Source§

fn timer_names(&self) -> Vec<&str>

Returns the names of active timers in the clock.
Source§

fn timer_count(&self) -> usize

Returns the count of active timers in the clock.
Source§

fn timer_exists(&self, name: &Ustr) -> bool

If a timer with the name exists.
Source§

fn register_default_handler(&mut self, callback: TimeEventCallback)

Register a default event handler for the clock. If a timer does not have an event handler, then this handler is used.
Source§

fn cancel_default_handler(&mut self)

Cancel the registered default event handler (if any). Read more
Source§

fn cancel_callbacks(&mut self)

Cancel all registered named event callbacks. Read more
Source§

fn set_time_alert_ns( &mut self, name: &str, alert_time_ns: UnixNanos, callback: Option<TimeEventCallback>, allow_past: Option<bool>, ) -> Result<()>

Set a timer to alert at the specified time. Read more
Source§

fn set_timer_ns( &mut self, name: &str, interval_ns: u64, start_time_ns: Option<UnixNanos>, stop_time_ns: Option<UnixNanos>, callback: Option<TimeEventCallback>, allow_past: Option<bool>, fire_immediately: Option<bool>, ) -> Result<()>

Set a timer to fire time events at every interval between start and stop time. Read more
Source§

fn next_time_ns(&self, name: &str) -> Option<UnixNanos>

Returns the time interval in which the timer name is triggered. Read more
Source§

fn cancel_timer(&mut self, name: &str)

Cancels the timer with name.
Source§

fn cancel_timers(&mut self)

Cancels all timers.
Source§

fn reset(&mut self)

Resets the clock by clearing it’s internal state.
Source§

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

Returns the current date and time as a timezone-aware DateTime<UTC>.
Source§

fn set_time_alert( &mut self, name: &str, alert_time: DateTime<Utc>, callback: Option<TimeEventCallback>, allow_past: Option<bool>, ) -> Result<()>

Set a timer to alert at the specified time. Read more
Source§

fn set_timer( &mut self, name: &str, interval: Duration, start_time: Option<DateTime<Utc>>, stop_time: Option<DateTime<Utc>>, callback: Option<TimeEventCallback>, allow_past: Option<bool>, fire_immediately: Option<bool>, ) -> Result<()>

Set a timer to fire time events at every interval between start and stop time. Read more
Source§

impl Debug for TestClock

Source§

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

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

impl Default for TestClock

Source§

fn default() -> Self

Creates a new default TestClock instance.

Source§

impl Deref for TestClock

Source§

type Target = AtomicTime

The resulting type after dereferencing.
Source§

fn deref(&self) -> &Self::Target

Dereferences the value.

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
§

impl<ST, DT> CastableFrom<ST, Initialized, Initialized> for DT
where ST: ?Sized, DT: ?Sized,

§

impl<ST, DT> CastableFrom<ST, Uninit, Uninit> for DT
where ST: ?Sized, DT: ?Sized,

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.

§

impl<T> Read<Exclusive, BecauseExclusive> for T
where T: ?Sized,

Source§

impl<P, T> Receiver for P
where P: Deref<Target = T> + ?Sized, T: ?Sized,

Source§

type Target = T

🔬This is a nightly-only experimental API. (arbitrary_self_types)
The target type on which the method may be called.
Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
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> Ungil for T
where T: Send,

§

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