mirror of
https://github.com/coder/coder.git
synced 2026-09-24 15:04:27 +08:00
chore: add Now, Since, AfterFunc to clock; use clock for configmaps test (#13476)
* chore: add Now, Since, AfterFunc to clock; use clock for configmaps test * chore: update flake.nix vendor hash Signed-off-by: Spike Curtis <spike@coder.com> --------- Signed-off-by: Spike Curtis <spike@coder.com>
This commit is contained in:
@@ -17,6 +17,15 @@ type Clock interface {
|
||||
// NewTimer creates a new Timer that will send the current time on its channel after at least
|
||||
// duration d.
|
||||
NewTimer(d time.Duration, tags ...string) *Timer
|
||||
// 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. The returned Timer's C
|
||||
// field is not used and will be nil.
|
||||
AfterFunc(d time.Duration, f func(), tags ...string) *Timer
|
||||
|
||||
// Now returns the current local time.
|
||||
Now(tags ...string) time.Time
|
||||
// Since returns the time elapsed since t. It is shorthand for Clock.Now().Sub(t).
|
||||
Since(t time.Time, tags ...string) time.Duration
|
||||
}
|
||||
|
||||
// Waiter can be waited on for an error.
|
||||
|
||||
+63
-4
@@ -71,6 +71,46 @@ func (m *Mock) NewTimer(d time.Duration, tags ...string) *Timer {
|
||||
return t
|
||||
}
|
||||
|
||||
func (m *Mock) AfterFunc(d time.Duration, f func(), tags ...string) *Timer {
|
||||
if d < 0 {
|
||||
panic("duration must be positive or zero")
|
||||
}
|
||||
m.mu.Lock()
|
||||
defer m.mu.Unlock()
|
||||
m.matchCallLocked(&Call{
|
||||
fn: clockFunctionAfterFunc,
|
||||
Duration: d,
|
||||
Tags: tags,
|
||||
})
|
||||
t := &Timer{
|
||||
nxt: m.cur.Add(d),
|
||||
fn: f,
|
||||
mock: m,
|
||||
}
|
||||
m.addTimerLocked(t)
|
||||
return t
|
||||
}
|
||||
|
||||
func (m *Mock) Now(tags ...string) time.Time {
|
||||
m.mu.Lock()
|
||||
defer m.mu.Unlock()
|
||||
m.matchCallLocked(&Call{
|
||||
fn: clockFunctionNow,
|
||||
Tags: tags,
|
||||
})
|
||||
return m.cur
|
||||
}
|
||||
|
||||
func (m *Mock) Since(t time.Time, tags ...string) time.Duration {
|
||||
m.mu.Lock()
|
||||
defer m.mu.Unlock()
|
||||
m.matchCallLocked(&Call{
|
||||
fn: clockFunctionSince,
|
||||
Tags: tags,
|
||||
})
|
||||
return m.cur.Sub(t)
|
||||
}
|
||||
|
||||
func (m *Mock) addTimerLocked(t *Timer) {
|
||||
m.all = append(m.all, t)
|
||||
m.recomputeNextLocked()
|
||||
@@ -142,9 +182,13 @@ func (m *Mock) matchCallLocked(c *Call) {
|
||||
m.mu.Lock()
|
||||
}
|
||||
|
||||
// AdvanceWaiter is returned from Advance and Set calls and allows you to wait for tick functions of
|
||||
// tickers created using TickerFunc to complete. If multiple timers or tickers trigger
|
||||
// simultaneously, they are all run on separate go routines.
|
||||
// AdvanceWaiter is returned from Advance and Set calls and allows you to wait for:
|
||||
//
|
||||
// - tick functions of tickers created using NewContextTicker
|
||||
// - functions passed to AfterFunc
|
||||
//
|
||||
// to complete. If multiple timers or tickers trigger simultaneously, they are all run on separate
|
||||
// go routines.
|
||||
type AdvanceWaiter struct {
|
||||
ch chan struct{}
|
||||
}
|
||||
@@ -191,7 +235,7 @@ func (m *Mock) Advance(d time.Duration) AdvanceWaiter {
|
||||
|
||||
func (m *Mock) advanceLocked(d time.Duration) {
|
||||
if m.advancing {
|
||||
panic("multiple simultaneous calls to Advance not supported")
|
||||
panic("multiple simultaneous calls to Advance/Set not supported")
|
||||
}
|
||||
m.advancing = true
|
||||
defer func() {
|
||||
@@ -263,6 +307,10 @@ func (t Trapper) NewTimer(tags ...string) *Trap {
|
||||
return t.mock.newTrap(clockFunctionNewTimer, tags)
|
||||
}
|
||||
|
||||
func (t Trapper) AfterFunc(tags ...string) *Trap {
|
||||
return t.mock.newTrap(clockFunctionAfterFunc, tags)
|
||||
}
|
||||
|
||||
func (t Trapper) TimerStop(tags ...string) *Trap {
|
||||
return t.mock.newTrap(clockFunctionTimerStop, tags)
|
||||
}
|
||||
@@ -279,6 +327,14 @@ func (t Trapper) TickerFuncWait(tags ...string) *Trap {
|
||||
return t.mock.newTrap(clockFunctionTickerFuncWait, tags)
|
||||
}
|
||||
|
||||
func (t Trapper) Now(tags ...string) *Trap {
|
||||
return t.mock.newTrap(clockFunctionNow, tags)
|
||||
}
|
||||
|
||||
func (t Trapper) Since(tags ...string) *Trap {
|
||||
return t.mock.newTrap(clockFunctionSince, tags)
|
||||
}
|
||||
|
||||
func (m *Mock) Trap() Trapper {
|
||||
return Trapper{m}
|
||||
}
|
||||
@@ -386,10 +442,13 @@ type clockFunction int
|
||||
|
||||
const (
|
||||
clockFunctionNewTimer clockFunction = iota
|
||||
clockFunctionAfterFunc
|
||||
clockFunctionTimerStop
|
||||
clockFunctionTimerReset
|
||||
clockFunctionTickerFunc
|
||||
clockFunctionTickerFuncWait
|
||||
clockFunctionNow
|
||||
clockFunctionSince
|
||||
)
|
||||
|
||||
type callArg func(c *Call)
|
||||
|
||||
@@ -55,4 +55,17 @@ func (realClock) NewTimer(d time.Duration, _ ...string) *Timer {
|
||||
return &Timer{C: rt.C, timer: rt}
|
||||
}
|
||||
|
||||
func (realClock) AfterFunc(d time.Duration, f func(), _ ...string) *Timer {
|
||||
rt := time.AfterFunc(d, f)
|
||||
return &Timer{C: rt.C, timer: rt}
|
||||
}
|
||||
|
||||
func (realClock) Now(_ ...string) time.Time {
|
||||
return time.Now()
|
||||
}
|
||||
|
||||
func (realClock) Since(t time.Time, _ ...string) time.Duration {
|
||||
return time.Since(t)
|
||||
}
|
||||
|
||||
var _ Clock = realClock{}
|
||||
|
||||
+2
-1
@@ -18,9 +18,10 @@ func (t *Timer) fire(tt time.Time) {
|
||||
panic("mock timer fired at wrong time")
|
||||
}
|
||||
t.mock.removeTimer(t)
|
||||
t.c <- tt
|
||||
if t.fn != nil {
|
||||
t.fn()
|
||||
} else {
|
||||
t.c <- tt
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user