Documentation
¶
Index ¶
- func IsSystemClock(c Clock) bool
- func With(ctx context.Context, c Clock) context.Context
- type Clock
- type FakeClock
- func (fc *FakeClock) Add(d time.Duration) (now time.Time)
- func (fc *FakeClock) After(d time.Duration) <-chan time.Time
- func (fc *FakeClock) AfterFunc(d time.Duration, f func()) Timer
- func (fc *FakeClock) NewTicker(d time.Duration) Ticker
- func (fc *FakeClock) NewTimer(d time.Duration) Timer
- func (fc *FakeClock) NotifyOnSleep(ch chan<- Sleeper)
- func (fc *FakeClock) NotifyOnTicker(ch chan<- FakeTicker)
- func (fc *FakeClock) NotifyOnTimer(ch chan<- FakeTimer)
- func (fc *FakeClock) Now() (n time.Time)
- func (fc *FakeClock) Set(t time.Time)
- func (fc *FakeClock) Since(t time.Time) (d time.Duration)
- func (fc *FakeClock) Sleep(d time.Duration)
- func (fc *FakeClock) StopOnSleep(ch chan<- Sleeper)
- func (fc *FakeClock) StopOnTicker(ch chan<- FakeTicker)
- func (fc *FakeClock) StopOnTimer(ch chan<- FakeTimer)
- func (fc *FakeClock) Tick(d time.Duration) <-chan time.Time
- func (fc *FakeClock) Until(t time.Time) (d time.Duration)
- type FakeTicker
- type FakeTimer
- type Sleeper
- type Ticker
- type Timer
Examples ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func IsSystemClock ¶ added in v0.1.1
IsSystemClock tests if c is actually a Clock returned by SystemClock(). This function is primarily useful in test code to verify that production code correctly initializes itself.
Types ¶
type Clock ¶
type Clock interface {
// Now returns ths instance's notion of the current time.
Now() time.Time
// Since returns the duration since this instance's current time.
Since(t time.Time) time.Duration
// Until returns the duration between this instance's current time and
// the given time.
Until(t time.Time) time.Duration
// Sleep blocks until this Clock believes that the given
// time duration has elapsed.
Sleep(time.Duration)
// After returns a timer channel with the same semantics as time.After.
// Since the underlying Timer is not returned, the timer cannot be stopped.
After(time.Duration) <-chan time.Time
// AfterFunc invokes the given function after the specified duration.
// The returned Timer can be used to halt execution.
AfterFunc(time.Duration, func()) Timer
// Tick returns a ticker channel with the same semantics as time.Tick.
Tick(time.Duration) <-chan time.Time
// NewTicker produces a Ticker which emits events at the given interval.
NewTicker(time.Duration) Ticker
// NewTimer produces a Timer which emits its single event at the given
// duration in the future.
NewTimer(time.Duration) Timer
}
Clock represents a standard set of time operations. Implementations are drop-in replacements for the time package.
A typical use case is to establish a Clock using SystemClock() in production code. Test code can then alter the injected instance to a *FakeClock after the fact.
func Get ¶
Get obtains a Clock from a context. This function always returns a valid Clock. If no clock is associated with the given context, the SystemClock is returned.
func SystemClock ¶
func SystemClock() Clock
SystemClock returns a Clock implementation backed by the time package.
type FakeClock ¶
type FakeClock struct {
// contains filtered or unexported fields
}
FakeClock is a Clock implementation that allows control over how the clock is updated. The Add and Set methods control a FakeClock's notion of the current time in addition to affecting the various objects created through this clock, e.g. Timer.
func NewFakeClock ¶
NewFakeClock creates a FakeClock that uses the given time as the initial current time.
func (*FakeClock) Add ¶
Add updates this fake clock's current time. The duration can be nonpositive, in which case the clock moves backwards or is unaffected.
Anytime a FakeClock's current time changes via this method or Set, any objects created through this clock are updated as appropriate.
func (*FakeClock) AfterFunc ¶
AfterFunc schedules a function to execute after this FakeClock has been advanced by at least the given duration. The returned Timer can be used to cancel the execution, as with time.AfterFunc. The returned Timer from this method is always a *FakeTimer, and its C() method always returns nil.
The Timer returned by this method can always be cast to a FakeTimer.
func (*FakeClock) NewTicker ¶
NewTicker creates a Ticker that fires when this FakeClock is advanced by increments of the given duration. The returned ticker can be stopped or reset in the usual fashion.
The Ticker returned from this method can always be cast to a FakeTicker.
Example ¶
fc := NewFakeClock(time.Now())
// to coordinate with another goroutine, use NotifyOnTicker
onTicker := make(chan FakeTicker)
fc.NotifyOnTicker(onTicker)
// create a context to control termination of our code under test
ctx, cancel := context.WithCancel(context.Background())
// spawn our code under test in a separate goroutine
done := make(chan struct{})
receivedTick := make(chan struct{})
go func() {
defer close(done)
t := fc.NewTicker(20 * time.Second)
for {
select {
case <-t.C():
fmt.Println("tick")
receivedTick <- struct{}{}
case <-ctx.Done():
fmt.Println("code under test has been canceled")
return
}
}
}()
// ensure that production code has reached the point where it's
// waiting on a ticker
ft := <-onTicker
fmt.Println("code under test is now waiting for ticks on", fc.Until(ft.When()))
// force a tick by advancing the clock
fc.Set(ft.When())
<-receivedTick
// can also force a tick directly
ft.Fire()
<-receivedTick
// moving the clock backwards doesn't result in ticks
fc.Add(-time.Hour)
// all done testing
cancel()
// ensure that the goroutine finishes before we exit
<-done
Output: code under test is now waiting for ticks on 20s tick tick code under test has been canceled
func (*FakeClock) NewTimer ¶
NewTimer creates a Timer that fires when this FakeClock has been advanced by at least the given duration. The returned timer can be stopped or reset in the usual fashion, which will affect what happens when the FakeClock is advanced.
The Timer returned by this method can always be cast to a FakeTimer.
Example ¶
fc := NewFakeClock(time.Now())
// to coordinate with another goroutine, use NotifyOnTimer
onTimer := make(chan FakeTimer)
fc.NotifyOnTimer(onTimer)
// spawn our code under test in a separate goroutine
done := make(chan struct{})
go func() {
defer close(done)
t := fc.NewTimer(10 * time.Minute)
<-t.C()
fmt.Println("code under test is no longer waiting")
}()
// ensure that production code has reached the point where it's
// waiting on a timer
ft := <-onTimer
fmt.Println("code under test is now waiting for", fc.Until(ft.When()))
// the clock can be advanced less than the timer interval with no effect
fc.Add(time.Millisecond)
// the clock can also be turned backward, again with no effect
fc.Add(-2 * time.Hour)
// force our code under test to stop waiting
ft.Fire()
// ensure that the goroutine finishes before we exit
<-done
Output: code under test is now waiting for 10m0s code under test is no longer waiting
func (*FakeClock) NotifyOnSleep ¶ added in v0.0.2
NotifyOnSleep registers a channel that receives the intervals for any goroutine which invokes Sleep. Calling code must service the channel promptly, as Sleep does not drop events sent to this channel.
A sleep channel is useful when testing concurrent code where test code needs to block waiting for a sleeper before modifying this FakeClock's time. When used for this purpose, be sure to register a sleep channel before invoking Sleep, usually in test setup code.
func (*FakeClock) NotifyOnTicker ¶ added in v0.0.2
func (fc *FakeClock) NotifyOnTicker(ch chan<- FakeTicker)
NotifyOnTicker registers a channel that receives the intervals for any tickers created through this fake clock. This includes implicit tickers, such as Tick.
Test code that uses this method can be notified when code under test creates tickers.
func (*FakeClock) NotifyOnTimer ¶ added in v0.0.2
NotifyOnTimer registers a channel that receives the intervals for any timers created through this fake clock. This includes implicit timers, such as with After and AfterFunc.
Test code that uses this method can be notified when code under test creates timers.
func (*FakeClock) Set ¶
Set is similar to Add, except that it sets an absolute time instead of moving this fake clock's time by a certain delta.
A common use case is to force the firing of an object by passing its When value.
func (*FakeClock) Since ¶
Since returns the duration from the given time to this FakeClock's current time. This method is atomic with respect to the other methods of this instance.
func (*FakeClock) Sleep ¶
Sleep blocks until this clock is advanced sufficiently so that the given duration elapses. If d is nonpositive, this function immediately returns exactly as with time.Sleep. However, in all cases a Sleeper is dispatched to any channels registered with NotifyOnSleep.
If d is positive, then any channel registered with NotifyOnSleep will receive d prior to blocking.
Example ¶
fc := NewFakeClock(time.Now())
// to coordinate with another goroutine, use NotifyOnSleep
onSleep := make(chan Sleeper)
fc.NotifyOnSleep(onSleep)
// spawn our code under test in a separate goroutine
done := make(chan struct{})
go func() {
defer close(done)
fc.Sleep(5 * time.Second)
fmt.Println("code under test has awakened")
}()
// ensure that production code has reached the point where it's sleeping
s := <-onSleep
fmt.Println("code under test is now sleeping for", fc.Until(s.When()))
// wakeup our production code
fc.Add(5 * time.Second)
// ensure that the goroutine finishes before we exit
<-done
Output: code under test is now sleeping for 5s code under test has awakened
func (*FakeClock) StopOnSleep ¶ added in v0.0.2
StopOnSleep removes a channel from the list of channels that receive notifications for Sleep. If the given channel is not present, this method does nothing.
func (*FakeClock) StopOnTicker ¶ added in v0.0.2
func (fc *FakeClock) StopOnTicker(ch chan<- FakeTicker)
StopOnTicker removes a channel from the list of channels that receive notifications for timers. If the given channel is not present, this method does nothing.
func (*FakeClock) StopOnTimer ¶ added in v0.0.2
StopOnTimer removes a channel from the list of channels that receive notifications for timers. If the given channel is not present, this method does nothing.
type FakeTicker ¶
type FakeTicker interface {
Ticker
// When returns the next time at which a tick will fire. This value will
// change after each tick or if this ticker is reset.
When() time.Time
// Fire forcibly sends a tick, unless this ticker is not active. This
// method returns true if the tick was sent, false if this ticker had been stopped.
//
// This method does not update the fake clock's current time or the
// return value from When. If the actual time for each tick is important
// to production code, force ticks to fire by using FakeClock.Set and passing
// the value returned by When.
Fire() bool
}
FakeTicker represents a Ticker which can be manually controlled, either by advancing its containing fake clock or through methods of this interface.
type FakeTimer ¶
type FakeTimer interface {
Timer
// When returns the absolute time at which this timer fires its
// event. This value will be affected by Reset.
When() time.Time
// Fire forces this FakeTimer to fire its event. Neither the containing
// fake clock nor the value returned by When are affected by this method.
// If the actual clock time is important to timer code, test code can
// make the timer fire by invoking FakeClock.Set and passing the value
// returned by When.
//
// This method returns true if this timer had been active, false if
// the timer had already fired.
Fire() bool
}
FakeTimer is a Timer which can be manually controlled by either advancing its containing FakeClock or by methods of this interface.
type Sleeper ¶ added in v0.1.0
type Sleeper interface {
// When returns the point in time at which the sleeping goroutine will
// wake up. This value will be the duration passed to Sleep added to
// the containing FakeClock's Now().
When() time.Time
// Wakeup forces the sleeping goroutine to awaken. Neither the fake clock's
// notion of the current time nor this Sleeper's When time are affected
// by this method. This method is idempotent: invoking it more than once
// has no further effect.
//
// If the fake clock's time is important to update as a result of sleeping,
// use FakeClock.Set with the value of When.
Wakeup() bool
}
Sleeper represents a handle to a goroutine that is blocked in a fake clock's Sleep method. Test code can get access to a Sleeper by calling NotifyOnSleep.
type Ticker ¶
type Ticker interface {
// C returns the channel on which this ticker sends ticks. This method
// always returns a non-nil channel.
//
// As with the time package, slow clients may miss ticks. If this channel's
// buffer is full when it's time to send another tick, that new tick is dropped.
C() <-chan time.Time
// Reset reschedules or reactivates this Ticker so that it begins firing
// ticks on the new interval.
Reset(time.Duration)
// Stop halts future ticks.
Stop()
}
Ticker represents a source of time events that occur at some interval. This type corresponds to *time.Ticker.
type Timer ¶
type Timer interface {
// C returns the channel on which this timer sends time events. Note that if
// this Timer was created via AfterFunc, this method returns nil.
C() <-chan time.Time
// Reset either (1) reschedules this Timer to fire after the given duration from Now(), or
// (2) schedules this Timer to fire again after the given duration from Now().
//
// IMPORTANT: The return value for this method is consistent with time.Timer. All
// the same caveats apply. In particular, it's generally not possible to use the
// return value from this method correctly.
Reset(time.Duration) bool
// Stop prevents this Timer from firing if it hasn't already. If this timer hadn't
// fired yet, this method returns true to indicate that this Timer was, in fact, stopped.
// Otherwise, this method return false, indicating that this Timer had already fired.
Stop() bool
}
Timer represents a source of an event that happens once, at a set point in time. This type corresponds to *time.Timer.