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 ¶
- type Clock
- type OsClock
- type SchedulingClock
- type TestClock
- func (c *TestClock) Advance(d time.Duration)
- func (c *TestClock) After(d time.Duration) <-chan time.Time
- func (c *TestClock) AfterFunc(d time.Duration, f func()) Timer
- func (c *TestClock) NewTicker(d time.Duration) Ticker
- func (c *TestClock) Now() time.Time
- func (c *TestClock) Set(t time.Time)
- func (c *TestClock) Since(t time.Time) time.Duration
- type Ticker
- type Timer
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type Clock ¶
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.
type OsClock ¶
type OsClock struct{}
OsClock is a production Clock that delegates to time.Now.
func (OsClock) After ¶ added in v1.5.0
After returns a channel that receives the time after duration d, backed by time.After.
func (OsClock) AfterFunc ¶ added in v1.5.0
AfterFunc calls f in a new goroutine after duration d, backed by time.AfterFunc.
func (OsClock) NewTicker ¶ added in v1.5.0
NewTicker returns a production ticker backed by time.NewTicker.
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 ¶
NewTestClock constructs a TestClock seeded to the provided time.
func (*TestClock) Advance ¶
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
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
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
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).
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.