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