1/*
2Copyright 2014 The Kubernetes Authors.
3
4Licensed under the Apache License, Version 2.0 (the "License");
5you may not use this file except in compliance with the License.
6You may obtain a copy of the License at
7
8    http://www.apache.org/licenses/LICENSE-2.0
9
10Unless required by applicable law or agreed to in writing, software
11distributed under the License is distributed on an "AS IS" BASIS,
12WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13See the License for the specific language governing permissions and
14limitations under the License.
15*/
16
17package clock
18
19import (
20	"sync"
21	"time"
22)
23
24// PassiveClock allows for injecting fake or real clocks into code
25// that needs to read the current time but does not support scheduling
26// activity in the future.
27type PassiveClock interface {
28	Now() time.Time
29	Since(time.Time) time.Duration
30}
31
32// Clock allows for injecting fake or real clocks into code that
33// needs to do arbitrary things based on time.
34type Clock interface {
35	PassiveClock
36	After(time.Duration) <-chan time.Time
37	AfterFunc(time.Duration, func()) Timer
38	NewTimer(time.Duration) Timer
39	Sleep(time.Duration)
40	NewTicker(time.Duration) Ticker
41}
42
43// RealClock really calls time.Now()
44type RealClock struct{}
45
46// Now returns the current time.
47func (RealClock) Now() time.Time {
48	return time.Now()
49}
50
51// Since returns time since the specified timestamp.
52func (RealClock) Since(ts time.Time) time.Duration {
53	return time.Since(ts)
54}
55
56// After is the same as time.After(d).
57func (RealClock) After(d time.Duration) <-chan time.Time {
58	return time.After(d)
59}
60
61// AfterFunc is the same as time.AfterFunc(d, f).
62func (RealClock) AfterFunc(d time.Duration, f func()) Timer {
63	return &realTimer{
64		timer: time.AfterFunc(d, f),
65	}
66}
67
68// NewTimer returns a new Timer.
69func (RealClock) NewTimer(d time.Duration) Timer {
70	return &realTimer{
71		timer: time.NewTimer(d),
72	}
73}
74
75// NewTicker returns a new Ticker.
76func (RealClock) NewTicker(d time.Duration) Ticker {
77	return &realTicker{
78		ticker: time.NewTicker(d),
79	}
80}
81
82// Sleep pauses the RealClock for duration d.
83func (RealClock) Sleep(d time.Duration) {
84	time.Sleep(d)
85}
86
87// FakePassiveClock implements PassiveClock, but returns an arbitrary time.
88type FakePassiveClock struct {
89	lock sync.RWMutex
90	time time.Time
91}
92
93// FakeClock implements Clock, but returns an arbitrary time.
94type FakeClock struct {
95	FakePassiveClock
96
97	// waiters are waiting for the fake time to pass their specified time
98	waiters []fakeClockWaiter
99}
100
101type fakeClockWaiter struct {
102	targetTime    time.Time
103	stepInterval  time.Duration
104	skipIfBlocked bool
105	destChan      chan time.Time
106	afterFunc     func()
107}
108
109// NewFakePassiveClock returns a new FakePassiveClock.
110func NewFakePassiveClock(t time.Time) *FakePassiveClock {
111	return &FakePassiveClock{
112		time: t,
113	}
114}
115
116// NewFakeClock returns a new FakeClock
117func NewFakeClock(t time.Time) *FakeClock {
118	return &FakeClock{
119		FakePassiveClock: *NewFakePassiveClock(t),
120	}
121}
122
123// Now returns f's time.
124func (f *FakePassiveClock) Now() time.Time {
125	f.lock.RLock()
126	defer f.lock.RUnlock()
127	return f.time
128}
129
130// Since returns time since the time in f.
131func (f *FakePassiveClock) Since(ts time.Time) time.Duration {
132	f.lock.RLock()
133	defer f.lock.RUnlock()
134	return f.time.Sub(ts)
135}
136
137// SetTime sets the time on the FakePassiveClock.
138func (f *FakePassiveClock) SetTime(t time.Time) {
139	f.lock.Lock()
140	defer f.lock.Unlock()
141	f.time = t
142}
143
144// After is the Fake version of time.After(d).
145func (f *FakeClock) After(d time.Duration) <-chan time.Time {
146	f.lock.Lock()
147	defer f.lock.Unlock()
148	stopTime := f.time.Add(d)
149	ch := make(chan time.Time, 1) // Don't block!
150	f.waiters = append(f.waiters, fakeClockWaiter{
151		targetTime: stopTime,
152		destChan:   ch,
153	})
154	return ch
155}
156
157// AfterFunc is the Fake version of time.AfterFunc(d, callback).
158func (f *FakeClock) AfterFunc(d time.Duration, cb func()) Timer {
159	f.lock.Lock()
160	defer f.lock.Unlock()
161	stopTime := f.time.Add(d)
162	ch := make(chan time.Time, 1) // Don't block!
163
164	timer := &fakeTimer{
165		fakeClock: f,
166		waiter: fakeClockWaiter{
167			targetTime: stopTime,
168			destChan:   ch,
169			afterFunc:  cb,
170		},
171	}
172	f.waiters = append(f.waiters, timer.waiter)
173	return timer
174}
175
176// NewTimer is the Fake version of time.NewTimer(d).
177func (f *FakeClock) NewTimer(d time.Duration) Timer {
178	f.lock.Lock()
179	defer f.lock.Unlock()
180	stopTime := f.time.Add(d)
181	ch := make(chan time.Time, 1) // Don't block!
182	timer := &fakeTimer{
183		fakeClock: f,
184		waiter: fakeClockWaiter{
185			targetTime: stopTime,
186			destChan:   ch,
187		},
188	}
189	f.waiters = append(f.waiters, timer.waiter)
190	return timer
191}
192
193// NewTicker returns a new Ticker.
194func (f *FakeClock) NewTicker(d time.Duration) Ticker {
195	f.lock.Lock()
196	defer f.lock.Unlock()
197	tickTime := f.time.Add(d)
198	ch := make(chan time.Time, 1) // hold one tick
199	f.waiters = append(f.waiters, fakeClockWaiter{
200		targetTime:    tickTime,
201		stepInterval:  d,
202		skipIfBlocked: true,
203		destChan:      ch,
204	})
205
206	return &fakeTicker{
207		c: ch,
208	}
209}
210
211// Step moves clock by Duration, notifies anyone that's called After, Tick, or NewTimer
212func (f *FakeClock) Step(d time.Duration) {
213	f.lock.Lock()
214	defer f.lock.Unlock()
215	f.setTimeLocked(f.time.Add(d))
216}
217
218// SetTime sets the time on a FakeClock.
219func (f *FakeClock) SetTime(t time.Time) {
220	f.lock.Lock()
221	defer f.lock.Unlock()
222	f.setTimeLocked(t)
223}
224
225// Actually changes the time and checks any waiters. f must be write-locked.
226func (f *FakeClock) setTimeLocked(t time.Time) {
227	f.time = t
228	newWaiters := make([]fakeClockWaiter, 0, len(f.waiters))
229	for i := range f.waiters {
230		w := &f.waiters[i]
231		if !w.targetTime.After(t) {
232
233			if w.skipIfBlocked {
234				select {
235				case w.destChan <- t:
236				default:
237				}
238			} else {
239				w.destChan <- t
240			}
241
242			if w.afterFunc != nil {
243				w.afterFunc()
244			}
245
246			if w.stepInterval > 0 {
247				for !w.targetTime.After(t) {
248					w.targetTime = w.targetTime.Add(w.stepInterval)
249				}
250				newWaiters = append(newWaiters, *w)
251			}
252
253		} else {
254			newWaiters = append(newWaiters, f.waiters[i])
255		}
256	}
257	f.waiters = newWaiters
258}
259
260// HasWaiters returns true if After or AfterFunc has been called on f but not yet satisfied
261// (so you can write race-free tests).
262func (f *FakeClock) HasWaiters() bool {
263	f.lock.RLock()
264	defer f.lock.RUnlock()
265	return len(f.waiters) > 0
266}
267
268// Sleep pauses the FakeClock for duration d.
269func (f *FakeClock) Sleep(d time.Duration) {
270	f.Step(d)
271}
272
273// IntervalClock implements Clock, but each invocation of Now steps the clock forward the specified duration
274type IntervalClock struct {
275	Time     time.Time
276	Duration time.Duration
277}
278
279// Now returns i's time.
280func (i *IntervalClock) Now() time.Time {
281	i.Time = i.Time.Add(i.Duration)
282	return i.Time
283}
284
285// Since returns time since the time in i.
286func (i *IntervalClock) Since(ts time.Time) time.Duration {
287	return i.Time.Sub(ts)
288}
289
290// After is currently unimplemented, will panic.
291// TODO: make interval clock use FakeClock so this can be implemented.
292func (*IntervalClock) After(d time.Duration) <-chan time.Time {
293	panic("IntervalClock doesn't implement After")
294}
295
296// AfterFunc is currently unimplemented, will panic.
297// TODO: make interval clock use FakeClock so this can be implemented.
298func (*IntervalClock) AfterFunc(d time.Duration, cb func()) Timer {
299	panic("IntervalClock doesn't implement AfterFunc")
300}
301
302// NewTimer is currently unimplemented, will panic.
303// TODO: make interval clock use FakeClock so this can be implemented.
304func (*IntervalClock) NewTimer(d time.Duration) Timer {
305	panic("IntervalClock doesn't implement NewTimer")
306}
307
308// NewTicker is currently unimplemented, will panic.
309// TODO: make interval clock use FakeClock so this can be implemented.
310func (*IntervalClock) NewTicker(d time.Duration) Ticker {
311	panic("IntervalClock doesn't implement NewTicker")
312}
313
314// Sleep is currently unimplemented; will panic.
315func (*IntervalClock) Sleep(d time.Duration) {
316	panic("IntervalClock doesn't implement Sleep")
317}
318
319// Timer allows for injecting fake or real timers into code that
320// needs to do arbitrary things based on time.
321type Timer interface {
322	C() <-chan time.Time
323	Stop() bool
324	Reset(d time.Duration) bool
325}
326
327// realTimer is backed by an actual time.Timer.
328type realTimer struct {
329	timer *time.Timer
330}
331
332// C returns the underlying timer's channel.
333func (r *realTimer) C() <-chan time.Time {
334	return r.timer.C
335}
336
337// Stop calls Stop() on the underlying timer.
338func (r *realTimer) Stop() bool {
339	return r.timer.Stop()
340}
341
342// Reset calls Reset() on the underlying timer.
343func (r *realTimer) Reset(d time.Duration) bool {
344	return r.timer.Reset(d)
345}
346
347// fakeTimer implements Timer based on a FakeClock.
348type fakeTimer struct {
349	fakeClock *FakeClock
350	waiter    fakeClockWaiter
351}
352
353// C returns the channel that notifies when this timer has fired.
354func (f *fakeTimer) C() <-chan time.Time {
355	return f.waiter.destChan
356}
357
358// Stop conditionally stops the timer.  If the timer has neither fired
359// nor been stopped then this call stops the timer and returns true,
360// otherwise this call returns false.  This is like time.Timer::Stop.
361func (f *fakeTimer) Stop() bool {
362	f.fakeClock.lock.Lock()
363	defer f.fakeClock.lock.Unlock()
364	// The timer has already fired or been stopped, unless it is found
365	// among the clock's waiters.
366	stopped := false
367	oldWaiters := f.fakeClock.waiters
368	newWaiters := make([]fakeClockWaiter, 0, len(oldWaiters))
369	seekChan := f.waiter.destChan
370	for i := range oldWaiters {
371		// Identify the timer's fakeClockWaiter by the identity of the
372		// destination channel, nothing else is necessarily unique and
373		// constant since the timer's creation.
374		if oldWaiters[i].destChan == seekChan {
375			stopped = true
376		} else {
377			newWaiters = append(newWaiters, oldWaiters[i])
378		}
379	}
380
381	f.fakeClock.waiters = newWaiters
382
383	return stopped
384}
385
386// Reset conditionally updates the firing time of the timer.  If the
387// timer has neither fired nor been stopped then this call resets the
388// timer to the fake clock's "now" + d and returns true, otherwise
389// it creates a new waiter, adds it to the clock, and returns true.
390//
391// It is not possible to return false, because a fake timer can be reset
392// from any state (waiting to fire, already fired, and stopped).
393//
394// See the GoDoc for time.Timer::Reset for more context on why
395// the return value of Reset() is not useful.
396func (f *fakeTimer) Reset(d time.Duration) bool {
397	f.fakeClock.lock.Lock()
398	defer f.fakeClock.lock.Unlock()
399	waiters := f.fakeClock.waiters
400	seekChan := f.waiter.destChan
401	for i := range waiters {
402		if waiters[i].destChan == seekChan {
403			waiters[i].targetTime = f.fakeClock.time.Add(d)
404			return true
405		}
406	}
407	// No existing waiter, timer has already fired or been reset.
408	// We should still enable Reset() to succeed by creating a
409	// new waiter and adding it to the clock's waiters.
410	newWaiter := fakeClockWaiter{
411		targetTime: f.fakeClock.time.Add(d),
412		destChan:   seekChan,
413	}
414	f.fakeClock.waiters = append(f.fakeClock.waiters, newWaiter)
415	return true
416}
417
418// Ticker defines the Ticker interface
419type Ticker interface {
420	C() <-chan time.Time
421	Stop()
422}
423
424type realTicker struct {
425	ticker *time.Ticker
426}
427
428func (t *realTicker) C() <-chan time.Time {
429	return t.ticker.C
430}
431
432func (t *realTicker) Stop() {
433	t.ticker.Stop()
434}
435
436type fakeTicker struct {
437	c <-chan time.Time
438}
439
440func (t *fakeTicker) C() <-chan time.Time {
441	return t.c
442}
443
444func (t *fakeTicker) Stop() {
445}
446