clock

package
v1.5.2 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: May 26, 2026 License: Apache-2.0 Imports: 3 Imported by: 0

Documentation

Overview

Package clock provides time abstractions for testable code.

Core interfaces

Clock exposes a single Now() method. OsClock implements it for production (delegates to time.Now); TestClock implements it for tests (allows deterministic time advancement via TestClock.Advance).

SchedulingClock extends Clock with scheduling primitives: SchedulingClock.NewTicker, SchedulingClock.After, SchedulingClock.AfterFunc, and SchedulingClock.Since. Both OsClock and TestClock implement SchedulingClock: OsClock delegates to the standard library's time package, while TestClock drives all scheduling operations from TestClock.Advance for fully deterministic test scenarios.

Upgrading a Clock to SchedulingClock

ToSchedulingClock upgrades any Clock to a SchedulingClock. If the value already implements SchedulingClock, it is returned as-is. Otherwise it is wrapped in an adapter that provides OS-backed scheduling while delegating Now() to the original clock.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type Clock

type Clock interface {
	// Now returns the current time.
	Now() time.Time
}

Clock is a small interface abstracting time operations the package needs. Use this to inject testable/fake clocks in unit tests rather than relying on time.Now directly.

func Default added in v1.0.0

func Default() Clock

Default returns the process default clock.

func OrDefault added in v1.0.0

func OrDefault(c Clock) Clock

OrDefault returns c unless it is nil, in which case the default clock is returned.

type OsClock

type OsClock struct{}

OsClock is a production Clock that delegates to time.Now.

func (OsClock) After added in v1.5.0

func (OsClock) After(d time.Duration) <-chan time.Time

After returns a channel that receives the time after duration d, backed by time.After.

func (OsClock) AfterFunc added in v1.5.0

func (OsClock) AfterFunc(d time.Duration, f func()) Timer

AfterFunc calls f in a new goroutine after duration d, backed by time.AfterFunc.

func (OsClock) NewTicker added in v1.5.0

func (OsClock) NewTicker(d time.Duration) Ticker

NewTicker returns a production ticker backed by time.NewTicker.

func (OsClock) Now

func (OsClock) Now() time.Time

Now returns the current wall-clock time.

func (OsClock) Since added in v1.5.0

func (OsClock) Since(t time.Time) time.Duration

Since returns the time elapsed since t, backed by time.Since.

type SchedulingClock added in v1.5.0

type SchedulingClock interface {
	Clock

	// NewTicker returns a [Ticker] that fires at every interval d.
	// Panics if d <= 0 (same contract as time.NewTicker).
	NewTicker(d time.Duration) Ticker

	// After returns a channel that receives the current time after duration d.
	After(d time.Duration) <-chan time.Time

	// AfterFunc calls f in a new goroutine after duration d and returns a
	// [Timer] that can be used to cancel the call.
	AfterFunc(d time.Duration, f func()) Timer

	// Since returns the time elapsed since t, equivalent to Now().Sub(t).
	Since(t time.Time) time.Duration
}

SchedulingClock extends Clock with scheduling primitives that can be controlled deterministically in tests.

Both OsClock and TestClock implement SchedulingClock: OsClock delegates to the standard library time package, TestClock uses a min-heap scheduler driven by TestClock.Advance.

func ToSchedulingClock added in v1.5.0

func ToSchedulingClock(c Clock) SchedulingClock

ToSchedulingClock upgrades c to a SchedulingClock. If c already implements SchedulingClock it is returned directly; otherwise it is wrapped in an adapter that delegates Now() to c and uses OS-backed scheduling primitives.

Both OsClock and TestClock implement SchedulingClock directly, so this helper is only needed for third-party Clock implementations that do not. The adapter is not appropriate for deterministic test clocks — use a TestClock instead.

type TestClock

type TestClock struct {
	// contains filtered or unexported fields
}

TestClock is a mutex-protected, manually-advancable clock useful for tests. It allows deterministic control of Now() by setting an initial time and advancing it as needed.

TestClock implements SchedulingClock: tickers, timers, and AfterFunc callbacks are driven by TestClock.Advance rather than wall-clock time, making test behaviour fully deterministic.

func NewTestClock

func NewTestClock(initial time.Time) *TestClock

NewTestClock constructs a TestClock seeded to the provided time.

func (*TestClock) Advance

func (c *TestClock) Advance(d time.Duration)

Advance moves the TestClock forward by d, firing any tickers, timers, or AfterFunc callbacks whose deadline falls within [old_now, old_now+d]. Events are fired in deadline order; equal-deadline events are fired in registration order (FIFO).

The mutex is released before delivering tick values or launching AfterFunc goroutines, so callbacks that call Stop, Reset, or Advance are safe.

func (*TestClock) After added in v1.5.0

func (c *TestClock) After(d time.Duration) <-chan time.Time

After returns a channel that receives the current time after duration d. The send is non-blocking (buffered channel, size 1).

func (*TestClock) AfterFunc added in v1.5.0

func (c *TestClock) AfterFunc(d time.Duration, f func()) Timer

AfterFunc calls f in a new goroutine after duration d and returns a Timer that can cancel the call.

func (*TestClock) NewTicker added in v1.5.0

func (c *TestClock) NewTicker(d time.Duration) Ticker

NewTicker returns a Ticker that fires every d. The tick channel has a buffer of 1; if the receiver is slow, ticks are dropped (matching stdlib behaviour).

func (*TestClock) Now

func (c *TestClock) Now() time.Time

Now returns the current time of the TestClock.

func (*TestClock) Set

func (c *TestClock) Set(t time.Time)

Set sets the TestClock to a specific time without firing any scheduled events. Use Advance when you want events to fire.

func (*TestClock) Since added in v1.5.0

func (c *TestClock) Since(t time.Time) time.Duration

Since returns the time elapsed since t, equivalent to c.Now().Sub(t).

type Ticker added in v1.5.0

type Ticker interface {
	// C returns the channel on which ticks are delivered.
	C() <-chan time.Time
	// Stop turns off the ticker. After Stop, no more ticks will be delivered.
	Stop()
}

Ticker is the minimal interface required from a repeating ticker. It mirrors the relevant subset of time.Ticker behind an interface so that implementations (production and test) can be swapped.

type Timer added in v1.5.0

type Timer interface {
	// Stop prevents the timer from firing. It returns true if the call stops
	// the timer, false if the timer has already expired or been stopped.
	Stop() bool
	// Reset changes the timer to expire after duration d. It returns true if
	// the timer had been active, false if the timer had already expired or
	// been stopped. Reset must only be invoked on stopped or expired timers.
	Reset(d time.Duration) bool
}

Timer is the minimal interface required from a one-shot timer. It mirrors the relevant subset of time.Timer behind an interface.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL