clock/clock.go (48 lines of code) (raw):
// Copyright 2017 Google Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package clock
import (
"time"
)
// Clock is a simple interface that returns a "current" timestamp. This will generally be the
// current time, but the Clock interface can be mocked during testing to make testing time-sensitive
// components deterministic.
type Clock interface {
// Now returns the current time, as defined by this Clock.
Now() time.Time
// NewTimer creates a new Timer associated with this Clock.
NewTimer(d time.Duration) Timer
// NewTimerAt creates a new Timer that fires at or after the given time.
NewTimerAt(at time.Time) Timer
}
// Timer mimics a time.Timer, providing a channel that delivers a signal after a certain amount of
// time has elapsed. When associated with a MockClock, Timer delivers its signal when the
// MockClock's time is programmatically set to a certain point.
type Timer interface {
// GetC returns this Timer's signal channel. For real clocks, this simply returns a time.Timer.C.
GetC() <-chan time.Time
// Stop stops the timer. Like time.Timer.Stop(), it returns true if the call stops the timer,
// false if the timer has already expired or been stopped. See documentation for time.Timer.Stop()
// for more information about this method's behavior.
Stop() bool
}
// NewClock creates a new Clock instance that returns the current time.
func NewClock() Clock {
return &realClock{}
}
// NewStoppedTimer creates a Timer that will never fire.
func NewStoppedTimer() Timer {
return &stoppedTimer{c: make(chan time.Time)}
}
type stoppedTimer struct {
c chan time.Time
}
func (t *stoppedTimer) GetC() <-chan time.Time {
return t.c
}
func (t *stoppedTimer) Stop() bool {
return false
}
type realClock struct{}
func (rc *realClock) Now() time.Time {
return time.Now()
}
func (rc *realClock) NewTimer(d time.Duration) Timer {
return &realTimer{t: time.NewTimer(d)}
}
func (rc *realClock) NewTimerAt(at time.Time) Timer {
duration := at.Sub(time.Now())
return &realTimer{t: time.NewTimer(duration)}
}
type realTimer struct {
t *time.Timer
}
func (t *realTimer) GetC() <-chan time.Time {
return t.t.C
}
func (t *realTimer) Stop() bool {
return t.t.Stop()
}