Documentation
¶
Index ¶
- Constants
- Variables
- func ContextWithClock(ctx context.Context, c Clock) context.Context
- func ContextWithDeadline(ctx context.Context, t time.Time) (context.Context, context.CancelFunc)
- func ContextWithDeadlineCause(ctx context.Context, t time.Time, cause error) (context.Context, context.CancelFunc)
- func ContextWithTimeout(ctx context.Context, d time.Duration) (context.Context, context.CancelFunc)
- func ContextWithTimeoutCause(ctx context.Context, d time.Duration, cause error) (context.Context, context.CancelFunc)
- func Sleep(ctx context.Context, d Duration)
- func Tick(ctx context.Context, d Duration) <-chan Time
- type Clock
- type ClockOption
- type Duration
- type Location
- type MockClock
- type Month
- type ParseError
- type Ticker
- type Time
- type Timer
- type Weekday
Examples ¶
Constants ¶
const ( // durations Day = time.Hour * 24 Hour = time.Hour Microsecond = time.Microsecond Millisecond = time.Millisecond Minute = time.Minute Nanosecond = time.Nanosecond Second = time.Second Week = time.Hour * 24 * 7 // date/time formats Layout = time.Layout // The reference time, in numerical order ANSIC = time.ANSIC DateOnly = time.DateOnly DateTime = time.DateTime RFC822 = time.RFC822 RFC822Z = time.RFC822Z // RFC822 with numeric zone RFC850 = time.RFC850 RFC1123 = time.RFC1123 RFC1123Z = time.RFC1123Z // RFC1123 with numeric zone RFC3339 = time.RFC3339 RFC3339Nano = time.RFC3339Nano Kitchen = time.Kitchen RubyDate = time.RubyDate Stamp = time.Stamp StampMilli = time.StampMilli StampMicro = time.StampMicro StampNano = time.StampNano TimeOnly = time.TimeOnly UnixDate = time.UnixDate )
Variables ¶
var ( // the following functions are aliases for the corresponding functions in the standard time package Date = time.Date Parse = time.Parse ParseDuration = time.ParseDuration ParseInLocation = time.ParseInLocation Unix = time.Unix UnixMicro = time.UnixMicro UnixMilli = time.UnixMilli )
Functions ¶
func ContextWithClock ¶
ContextWithClock returns a new context containing a given clock.
- If the context already contains a clock the function panics with ErrClockAlreadyExists.
- If the given clock is nil a new context is returned with the system clock added.
func ContextWithDeadline ¶
ContextWithDeadline returns a new context with the given deadline. If the given time is in the past, the returned context is already done.
The deadline is set using the clock in the given context. If there is no clock in the context the system clock is used and the result is the same as calling context.WithDeadline.
If the context contains a mock clock, the deadline will expire when that mock clock is advanced to the deadline or later.
func ContextWithDeadlineCause ¶
func ContextWithDeadlineCause(ctx context.Context, t time.Time, cause error) (context.Context, context.CancelFunc)
ContextWithDeadlineCause returns a new context with the given deadline and cause. If the given time is in the past, the returned context is already done.
The cause is used to set the context error.
The deadline is set using the clock in the given context. If there is no clock in the context the system clock is used and the result is the same as calling context.WithDeadlineCause.
If the context contains a mock clock, the deadline will expire when that mock clock is advanced to the deadline or later.
func ContextWithTimeout ¶
ContextWithTimeout returns a new context with the given timeout. If the given duration is zero or negative, the returned context is already done.
The timeout is set using the clock in the given context. If there is no clock in the context the system clock is used and the result is the same as calling context.WithTimeout.
If the context contains a mock clock, the timeout will expire when that mock clock is advanced by at least the given duration from its current time.
func ContextWithTimeoutCause ¶
func ContextWithTimeoutCause(ctx context.Context, d time.Duration, cause error) (context.Context, context.CancelFunc)
ContextWithTimeoutCause returns a new context with the given timeout and cause. If the given duration is zero or negative, the returned context is already done.
The cause is used to set the context error.
The timeout is set using the clock in the given context. If there is no clock in the context the system clock is used and the result is the same as calling context.WithTimeoutCause.
If the context contains a mock clock, the timeout will expire when that mock clock is advanced by at least the given duration from its current time. The cause is used to set the context error.
Types ¶
type Clock ¶
type Clock interface {
// After returns a channel that will send the current time after at least
// duration d.
After(d time.Duration) <-chan time.Time
// AfterFunc waits for the duration to elapse and then calls f in its own
// goroutine. It returns a Timer that can be used to stop the countdown
// or to reset the Timer to run at a different time.
//
// If the Timer is stopped, the function f will not be called.
AfterFunc(d time.Duration, f func()) *Timer
// NewTicker returns a new Ticker that will send the current time on its
// channel after each tick. The duration d must be greater than zero; if
// d <= 0, NewTicker will panic.
//
// The duration of the Ticker can be modified using the Reset method
//
// The Ticker will continue ticking until Stop is called on it.
NewTicker(d time.Duration) *Ticker
// NewTimer returns a new Timer that will send the current time on its
// channel after the duration d. The duration d must be greater than zero;
// if d <= 0, NewTimer will panic.
//
// The duration of the Timer can be modified using the Reset method.
//
// The Timer will tick at the designated time unless Stop is called on it
// beforehand. A stopped Timer will resume if it is reset.
NewTimer(d time.Duration) *Timer
// Now returns the current time.
Now() time.Time
// Since returns the duration since t, according to the current time. It is
// shorthand for time.Since(c.Now()).
Since(t time.Time) time.Duration
// Sleep pauses the calling goroutine for at least the duration d.
Sleep(d time.Duration)
// Tick returns a channel that will send the current time after each tick.
// Unlike NewTicker, if the duration d is zero or negative, Tick will return
// a nil channel and will not panic.
Tick(d time.Duration) <-chan time.Time
// Until returns the duration until t, according to the current time. It is
// shorthand for time.Until(c.Now()).
Until(t time.Time) time.Duration
// ContextWithDeadline returns a new context with the given deadline. If the
// given time is in the past, the returned context is already done.
//
// This function should be used in preference over context.WithDeadline
// to ensure that code relying on the deadline behaves correctly under test
// conditions which may provide a mock clock in the parent context.
ContextWithDeadline(ctx context.Context, d time.Time) (context.Context, context.CancelFunc)
// ContextWithDeadlineCause returns a new context with the given deadline and
// cause. If the given time is in the past, the returned context is already
// done.
//
// The cause is used to set the context error.
//
// This function should be used in preference over context.WithDeadlineCause
// to ensure that code relying on the deadline behaves correctly under test
// conditions which may provide a mock clock in the parent context.
ContextWithDeadlineCause(ctx context.Context, d time.Time, cause error) (context.Context, context.CancelFunc)
// ContextWithTimeout returns a new context with the given timeout. If the
// given duration is zero or negative, the returned context is already done.
//
// This function should be used in preference over context.WithTimeout
// to ensure that code relying on the timeout behaves correctly under test
// conditions which may provide a mock clock in the parent context.
ContextWithTimeout(ctx context.Context, d time.Duration) (context.Context, context.CancelFunc)
// ContextWithTimeoutCause returns a new context with the given timeout and
// cause. If the given duration is zero or negative, the returned context is
// already done.
//
// The cause is used to set the context error.
//
// This function should be used in preference over context.WithTimeoutCause
// to ensure that code relying on the timeout behaves correctly under test
// conditions which may provide a mock clock in the parent context.
ContextWithTimeoutCause(ctx context.Context, d time.Duration, cause error) (context.Context, context.CancelFunc)
}
Clock represents an interface described by the functions in the time package of the standard library. It extends the time package with additional methods to create contexts with deadlines and timeouts based on the clock providing the interface.
This allows for the creation of mock clocks for testing purposes through an API that is similar to and consistent with that of the system clock in the standard library `time` package.
func ClockFromContext ¶
ClockFromContext returns the Clock in the given context. If no Clock is in the context the system clock is returned.
func SystemClock ¶
func SystemClock() Clock
SystemClock returns a clock implementation that uses the `time` package functions of the standard library.
func TryClockFromContext ¶
TryClockFromContext returns the Clock in the given context or nil if no Clock is present.
type ClockOption ¶
type ClockOption func(*mockClock)
ClockOption represents an option that can be passed to NewMockClock.
func AtNow ¶
func AtNow() ClockOption
AtNow is a convenience for AtTime(time.Now()).
This may be useful for testing purposes when you want to start the clock at the current time whilst retaining the ability to control the advancement of time.
The time is set in the location of the clock.
func AtTime ¶
func AtTime(t time.Time) ClockOption
AtTime sets the initial time of the mock clock.
This may be useful for testing purposes when you want to start the clock at a particular time whilst retaining the ability to control the advancement of time. The time is set in the location of the clock.
Default ¶
1970-01-01 00:00:00 +0000 UTC (in the location of the clock)
func DropsTicks ¶
func DropsTicks() ClockOption
DropsTicks sets the mock clock to drop ticks when the clock is advanced. That is, if the clock is advanced by a duration that would ordinarily result in a ticker being triggered more than once, the clock will only trigger a single tick event for the final tick.
Example ¶
When a ticker is set to tick every 300 ms and the clock is advanced by 1s:
in normal operation, the ticker will be triggered at 300ms, 600ms and 900ms.
with DropsTicks applied, the clock will only send a tick event for the final tick at 900ms.
This may be used to simulate a reader that is reading from a Ticker and failing to "keep up". This is not ideal since it is using the clock to simulate the reader behaviour but may be easier than contriving that reader behaviour in other ways for testing purposes.
Default ¶
not set/disabled
func InLocation ¶
func InLocation(loc *time.Location) ClockOption
InLocation sets the mock clock to the given location; the time returned by Now() will be in this location.
It is not normally necessary to set the location of the clock but may be useful when you want to start the clock in a particular location whilst retaining the ability to control the advancement of time.
Default ¶
UTC
func StartRunning ¶
func StartRunning() ClockOption
StartRunning sets the mock clock to start in a running state. In this state the clock is advanced by elapsed time whenever Now() is obtained from the clock or when Update() is explicitly called.
AdvanceBy() and AdvanceTo() are not supported when the clock is in a running state and will panic.
This more closely mimics the behaviour of a real clock but means that tests will run in real-time; this is not recommended for most tests as it will make them run more slowly than they might.
Default ¶
not set / stopped
func Yielding ¶
func Yielding(d time.Duration) ClockOption
Yielding sets a duration for which the calling goroutine will be suspended when performing operations such as advancing the clock or adding a timer or ticker.
This allows other goroutines to be scheduled at times when it may be useful for a test. The duration should rarely need to be changed and should not be set to a value that is too high as this will cause a test to run more slowly than it might.
To disable this behaviour (not recommended) set the duration to 0.
Default ¶
1ms
type Duration ¶
the following types are aliases for the corresponding types in the standard time package
type MockClock ¶
type MockClock interface {
// MockClock is a mock implementation of the time.Clock interface.
Clock
// AdvanceBy moves the current time of the mock clock forward by a
// specified duration, triggering any timers or tickers that would have
// been triggered during that passage of time.
//
// Calling this method while the clock is running will result in a panic.
AdvanceBy(d time.Duration)
// AdvanceTo moves the current time of the mock clock to a specific time,
// triggering any timers or tickers that would have been triggered during
// that passage of time.
//
// Calling this method while the clock is running will result in a panic.
AdvanceTo(t time.Time)
// CreatedAt returns the mocked time at which the clock was started when created.
CreatedAt() time.Time
// IsRunning returns true if the clock is in a running state.
// In this state the clock is advanced by elapsed time whenever Now()
// is obtained from the clock or when Update() is explicitly called.
// AdvanceBy() and AdvanceTo() are not supported when the clock is in a
// running state and will panic.
//
// This more closely mimics the behaviour of a real clock but tests using
// a running clock may be less deterministic and run more slowly than
// they might.
IsRunning() bool
// SinceCreated returns the elapsed mock time since the clock was created.
// This is the same as calling clock.Since(clock.CreatedAt()).
SinceCreated() time.Duration
// Stop stops the clock from advancing automatically. Every call to
// Stop() must be matched with a call to Start() to resume automatic
// advancement.
//
// A MockClock is initially created in stopped mode unless the StartRunning
// option is specified when initialising the clock.
Stop()
// Start resumes automatic advancement of the clock. Every call to
// Start() must be matched with a call to Stop() to stop automatic
// advancement.
//
// A MockClock is initially created in stopped mode unless the StartRunning
// option is specified when initialising the clock. i.e. if the clock
// is created in stopped mode, an initial call to Start() is required to
// start the clock.
Start()
// Update moves the current time of the mock clock forward by a duration
// corresponding to the passage of real-time since it was last updated,
// triggering any timers or tickers that would have been triggered during
// that passage of time.
//
// Calling this method while the clock is stopped will result in a panic.
Update()
}
MockClock extends the Clock interface with methods to manipulate the current time of the clock. In normal use, the underlying clock time is advanced only when explicitly directed to do so using AdvanceBy() or AdvanceTo() methods; this is "stopped" mode.
When the clock is "running" the current time is advanced semi-automatically by the passage of real-time since the last time the clock was updated. In "running" mode, the clock is advanced any time that Now() is called, or by calling Update().
It is used to simulate the passage of time in tests.
func ContextWithMockClock ¶
ContextWithMockClock returns a new context with a mock clock configured with the given options. If the parent context already has a clock the function panics with ErrClockAlreadyExists.
This function is provided as a convenience when writing tests requiring a mock clock.
func NewMockClock ¶
func NewMockClock(options ...ClockOption) MockClock
NewMockClock returns an instance of a mock clock.
The default settings on a new clock are:
- inital time set to the UNIX epoch (00:00:00 UTC on Thursday, 1 Jan 1970)
- stopped; advance with AdvanceBy() or AdvanceTo()
- does not drop ticks
- sleeps the calling goroutine for 1ms on various operations
When stopped, the clock must be explicitly advanced using AdvanceBy() or AdvanceTo(). When not stopped Update() may be used to advance the clock by the elapsed real-time since the last advancement.
The clock can be customised using the provided options:
AtNow() sets the initial time of the mock clock to the current time;
AtTime(t time.Time) sets the initial time of the mock clock;
DropsTicks() sets the clock to fire tickers only once where multiple ticks would have been triggered by a single advance of the clock
WithYield(d time.Duration) sets a duration for which the calling goroutine is suspended before and after each advancement of the clock.
StartRunning() sets the mock clock to start in a running state; in the running state the clock is advanced by elapsed time whenever Now() is obtained from the clock or when Update() is explicitly called. AdvanceBy() and AdvanceTo() are not supported in the running state and will panic.
type ParseError ¶
type ParseError = time.ParseError
type Ticker ¶
type Ticker struct {
// wraps a time.Timer in normal use; for a mock, this is non-nil but is
// used only as a container for the <-chan time.Time read-only reference
// to the mock timer's channel.
*time.Ticker
// contains filtered or unexported fields
}
Ticker represents a ticker; it may be obtained from SystemClock() or a mock obtained from a MockClock.
Usage is the same in either case and is identical to the time.Ticker type in the standard library: the time of each "tick" is read from the channel `C` provided on the Ticker.
A ticker created from a mock clock will tick when the associated mock clock is advanced to (or beyond) the next tick time.
If a mock clock is advanced by a duration that is greater than the period of the ticker, the ticker will tick at each interval unless the clock was configured to drop ticks. In that case, the Ticker will tick only once at the last time at/before the time advanced to.
Example ¶
package main
import (
"fmt"
"math"
"github.com/blugnu/time"
)
func main() {
// using the system clock
clock := time.SystemClock()
start := clock.Now()
// create a ticker that ticks every 100ms
ticker := clock.NewTicker(100 * time.Millisecond)
defer ticker.Stop()
// output the number and time (since starting) of each tick
n := 0
go func() {
for range ticker.C {
n++
fmt.Printf("fire %d @ ~%dms\n", n, 10*int(math.Trunc(float64(clock.Since(start).Milliseconds())/10)))
}
}()
// wait for a little over 500ms
clock.Sleep(510 * time.Millisecond)
}
Output: fire 1 @ ~100ms fire 2 @ ~200ms fire 3 @ ~300ms fire 4 @ ~400ms fire 5 @ ~500ms
func (*Ticker) Reset ¶
Reset resets the ticker to the specified duration.
If the Ticker has been stopped it is restarted with the new duration.
If the Ticker is already running it will be reset to the new duration; the next tick will occur at the specified duration from the current time.
the function panics if the given duration is zero or negative, or if the Ticker has not been initialized, .
type Timer ¶
type Timer struct {
// wraps a time.Timer in normal use; for a mock, this is non-nil but is
// used only as a container for the <-chan time.Time read-only reference
// to the mock timer's channel.
*time.Timer
// contains filtered or unexported fields
}
Timer represents a timer; it may obtained from the SystemClock() or a mock obtained from a MockClock.
Usage is the same in either case and is identical to the time.Timer type in the standard library: the time of the timer is read from the channel `C` provided on the Timer.
A timer created from a mock clock will tick when the associated mock clock is advanced to (or beyond) the time specified on the Timer.