Documentation
¶
Overview ¶
Package clock implements a library for mocking time.
Usage ¶
Include a Clock variable on your application and initialize it with a Realtime() by default. Then use the Clock for all time-related API calls. So instead of time.NewTimer(), say myClock.NewTimer().
On a test setup, override or inject the variable with a Mock instance and use it to control how the time behaves during each test phase.
To mock context.WithTimeout and context.WithDeadline, use the included Context, TimeoutContext and DeadlineContext methods.
The Context method is also useful in cases where you need to pass a Clock via an 'func(ctx Context, ..)' API you can't change yourself. The FromContext method will then return the associated Clock instance. Alternatively, use the context'ed methods like Sleep(ctx) directly.
All methods are safe for concurrent use.
Index ¶
- func After(ctx context.Context, d time.Duration) <-chan time.Time
- func Context(parent context.Context, c Clock) context.Context
- func DeadlineContext(ctx context.Context, d time.Time) (context.Context, context.CancelFunc)
- func Now(ctx context.Context) time.Time
- func Since(ctx context.Context, t time.Time) time.Duration
- func Sleep(ctx context.Context, d time.Duration)
- func Tick(ctx context.Context, d time.Duration) <-chan time.Time
- func TimeoutContext(ctx context.Context, timeout time.Duration) (context.Context, context.CancelFunc)
- func Until(ctx context.Context, t time.Time) time.Duration
- type Clock
- type Mock
- func (m *Mock) Add(d time.Duration) time.Time
- func (m *Mock) AddNext() (time.Time, time.Duration)
- func (m *Mock) After(d time.Duration) <-chan time.Time
- func (m *Mock) AfterFunc(d time.Duration, f func()) *Timer
- func (m *Mock) DeadlineContext(parent context.Context, d time.Time) (context.Context, context.CancelFunc)
- func (m *Mock) Len() int
- func (m *Mock) NewTicker(d time.Duration) *Ticker
- func (m *Mock) NewTimer(d time.Duration) *Timer
- func (m *Mock) Now() time.Time
- func (m *Mock) Set(t time.Time) time.Duration
- func (m *Mock) Since(t time.Time) time.Duration
- func (m *Mock) Sleep(d time.Duration)
- func (m *Mock) Tick(d time.Duration) <-chan time.Time
- func (m *Mock) TimeoutContext(parent context.Context, timeout time.Duration) (context.Context, context.CancelFunc)
- func (m *Mock) Until(t time.Time) time.Duration
- type Ticker
- type Timer
Examples ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func DeadlineContext ¶
DeadlineContext is a convenience wrapper for FromContext(ctx).DeadlineContext.
func TimeoutContext ¶
func TimeoutContext(ctx context.Context, timeout time.Duration) (context.Context, context.CancelFunc)
TimeoutContext is a convenience wrapper for FromContext(ctx).TimeoutContext.
Types ¶
type Clock ¶
type Clock interface { After(d time.Duration) <-chan time.Time AfterFunc(d time.Duration, f func()) *Timer NewTicker(d time.Duration) *Ticker NewTimer(d time.Duration) *Timer Now() time.Time Since(t time.Time) time.Duration Sleep(d time.Duration) Tick(d time.Duration) <-chan time.Time Until(t time.Time) time.Duration // DeadlineContext returns a copy of the parent context with the associated // Clock deadline adjusted to be no later than d. DeadlineContext(parent context.Context, d time.Time) (context.Context, context.CancelFunc) // TimeoutContext returns DeadlineContext(parent, Now(parent).Add(timeout)). TimeoutContext(parent context.Context, timeout time.Duration) (context.Context, context.CancelFunc) }
Clock represents an interface to the functions in the standard time and context packages.
func FromContext ¶
FromContext returns the Clock associated with the context, or Realtime().
type Mock ¶
Mock implements a Clock that only moves with Add, AddNext and Set.
The clock can be suspended with Lock and resumed with Unlock. While suspended, all attempts to use the API will block.
To increase predictability, all Mock methods acquire and release the Mutex only once during their execution.
func NewMock ¶
NewMock returns a new Mock with current time set to now.
Use Realtime to get the real-time Clock.
Example ¶
package main import ( "fmt" "time" "github.com/joa/clock" ) func main() { // Use clock.Realtime() in production mock := clock.NewMock(time.Date(2018, 1, 1, 10, 0, 0, 0, time.UTC)) fmt.Println("Time is now", mock.Now()) timer := mock.NewTimer(15 * time.Second) mock.Add(25 * time.Second) fmt.Println("Time is now", mock.Now()) fmt.Println("Timeout was", <-timer.C) }
Output: Time is now 2018-01-01 10:00:00 +0000 UTC Time is now 2018-01-01 10:00:25 +0000 UTC Timeout was 2018-01-01 10:00:15 +0000 UTC
func (*Mock) Add ¶
Add advances the current time by duration d and fires all expired timers.
Returns the new current time. To increase predictability and speed, Tickers are ticked only once per call.
func (*Mock) AddNext ¶
AddNext advances the current time to the next available timer deadline and fires all expired timers.
Returns the new current time and the advanced duration.
Example ¶
package main import ( "fmt" "strconv" "strings" "time" "github.com/joa/clock" ) func main() { start := time.Now() mock := clock.NewMock(start) def := mock.Tick(1 * time.Second) fizz := mock.Tick(3 * time.Second) buzz := mock.Tick(5 * time.Second) var items []string for i := 0; i < 20; i++ { mock.AddNext() var item string if (i+1)%3 == 0 { <-fizz item = "Fizz" if (i+1)%5 == 0 { <-buzz item = "FizzBuzz" } } else if (i+1)%5 == 0 { <-buzz item = "Buzz" } else { item = strconv.Itoa(int(mock.Since(start) / time.Second)) } <-def items = append(items, item) } fmt.Println(strings.Join(items, " ")) }
Output: 1 2 Fizz 4 Buzz Fizz 7 8 Fizz Buzz 11 Fizz 13 14 FizzBuzz 16 17 Fizz 19 Buzz
func (*Mock) After ¶
After waits for the duration to elapse and then sends the current time on the returned channel.
A negative or zero duration fires the underlying timer immediately.
func (*Mock) AfterFunc ¶
AfterFunc waits for the duration to elapse and then calls f in its own goroutine. It returns a Timer that can be used to cancel the call using its Stop method.
A negative or zero duration fires the timer immediately.
func (*Mock) DeadlineContext ¶
func (m *Mock) DeadlineContext(parent context.Context, d time.Time) (context.Context, context.CancelFunc)
DeadlineContext implements Clock.
Example ¶
package main import ( "context" "fmt" "time" "github.com/joa/clock" ) func main() { start := time.Date(2018, 1, 1, 10, 0, 0, 0, time.UTC) mock := clock.NewMock(start) fmt.Println("now:", mock.Now()) ctx, cfn := mock.DeadlineContext(context.Background(), start.Add(time.Hour)) defer cfn() fmt.Println("err:", ctx.Err()) dl, _ := ctx.Deadline() mock.Set(dl) fmt.Println("now:", clock.Now(ctx)) <-ctx.Done() fmt.Println("err:", ctx.Err()) }
Output: now: 2018-01-01 10:00:00 +0000 UTC err: <nil> now: 2018-01-01 11:00:00 +0000 UTC err: context deadline exceeded
func (*Mock) NewTicker ¶
NewTicker returns a new Ticker containing a channel that will send the current time with a period specified by the duration d.
func (*Mock) NewTimer ¶
NewTimer creates a new Timer that will send the current time on its channel after at least duration d.
A negative or zero duration fires the timer immediately.
func (*Mock) Set ¶
Set advances the current time to t and fires all expired timers.
Returns the advanced duration. To increase predictability and speed, Tickers are ticked only once per call.
func (*Mock) Sleep ¶
Sleep pauses the current goroutine for at least the duration d.
A negative or zero duration causes Sleep to return immediately.
func (*Mock) Tick ¶
Tick is a convenience wrapper for NewTicker providing access to the ticking channel only.
type Ticker ¶
Ticker represents a time.Ticker.
type Timer ¶
Timer represents a time.Timer.