Change:
<!-- Please use this template while reporting a bug and provide as much info as possible. Not doing so may result in your bug not being addressed in a timely manner. Thanks! If the matter is security related, please disclose it privately via --What happened: I was writing a variant of clock.FakeClock, and noticed a couple of bugs in . Look at the pointer comparison in --- the two pointers will never be equal, but the author clearly expected equality when is the index of the fakeClockWaiter corresponding to the fakeTimer. The two pointers will never be equal because one is a pointer into the fakeClock's slice while the other pointer is to a field of the . The consequence of this bug is that the Stop function is ineffective. Also, determines the returned value based on the original copy of the waiter, which --- being a copy --- did not get updated if/when the waiter fired. Note also that does not exercise FakeClock::NewTimer at all. What you expected to happen: I expected FakeClock Timers to work properly. How to reproduce it (as minimally and precisely as possible): Use the TestFakeTimer func introduced in Anything else we need to know?: Environment: Kubernetes version (use ): Cloud provider or hardware configuration: OS (e.g: ): Kernel (e.g. ): Install tools: Network plugin and version (if this is a network-related bug): Others:
The fake timer's Reset() method also does not work correctly.

Discussion:
stepInterval  time.Duration skipIfBlocked bool destChan      chan time.Time <del> fired         bool </del> } func NewFakeClock(t time.Time) *FakeClock {

if w.skipIfBlocked { select { case w.destChan <- t: <del> w.fired = true </del> default: } } else { w.destChan <- t <del> w.fired = true </del> } if w.stepInterval > 0 {

return f.waiter.destChan } <del> // Stop stops the timer and returns true if the timer has not yet fired, or false otherwise. </del> <ins> // Stop conditionally stops the timer.  If the timer has neither fired // nor been stopped then this call stops the timer and returns true, // otherwise this call returns false.  This is like time.Timer::Stop. </ins> func (f *fakeTimer) Stop() bool { f.fakeClock.lock.Lock() defer f.fakeClock.lock.Unlock() <del> newWaiters := make([]fakeClockWaiter, 0, len(f.fakeClock.waiters)) for i := range f.fakeClock.waiters { w := &f.fakeClock.waiters[i] if w != &f.waiter { newWaiters = append(newWaiters, *w) </del> <ins> // The timer has already fired or been stopped, unless it is found // among the clock's waiters. stopped := false oldWaiters := f.fakeClock.waiters newWaiters := make([]fakeClockWaiter, 0, len(oldWaiters)) seekChan := f.waiter.destChan for i := range oldWaiters { // Identify the timer's fakeClockWaiter by the identity of the // destination channel, nothing else is necessarily unique and // constant since the timer's creation. if oldWaiters[i].destChan == seekChan { stopped = true } else { newWaiters = append(newWaiters, oldWaiters[i]) </ins> } } f.fakeClock.waiters = newWaiters <del> return !f.waiter.fired </del> <ins> return stopped </ins> } <del> // Reset resets the timer to the fake clock's "now" + d. It returns true if the timer has not yet // fired, or false otherwise. </del> <ins> // Reset conditionally updates the firing time of the timer.  If the // timer has neither fired nor been stopped then this call resets the // timer to the fake clock's "now" + d and returns true, otherwise // this call returns false.  This is like time.Timer::Reset. </ins> func (f *fakeTimer) Reset(d time.Duration) bool { f.fakeClock.lock.Lock() defer f.fakeClock.lock.Unlock() <del> active := !f.waiter.fired f.waiter.fired = false f.waiter.targetTime = f.fakeClock.time.Add(d) return active </del> <ins> waiters := f.fakeClock.waiters seekChan := f.waiter.destChan for i := range waiters { if waiters[i].destChan == seekChan { waiters[i].targetTime = f.fakeClock.time.Add(d) return true } } return false </ins> } type Ticker interface {

} } <ins> func TestFakeTimer(t *testing.T) { tc := NewFakeClock(time.Now()) if tc.HasWaiters() { t.Errorf("unexpected waiter?") } oneSec := tc.NewTimer(time.Second) twoSec := tc.NewTimer(time.Second * 2) treSec := tc.NewTimer(time.Second * 3) if !tc.HasWaiters() { t.Errorf("unexpected lack of waiter?") } select { case <-oneSec.C(): t.Errorf("unexpected channel read") case <-twoSec.C(): t.Errorf("unexpected channel read") case <-treSec.C(): t.Errorf("unexpected channel read") default: } tc.Step(999999999 * time.Nanosecond) // t=.999,999,999 select { case <-oneSec.C(): t.Errorf("unexpected channel read") case <-twoSec.C(): t.Errorf("unexpected channel read") case <-treSec.C(): t.Errorf("unexpected channel read") default: } tc.Step(time.Nanosecond) // t=1 select { case <-twoSec.C(): t.Errorf("unexpected channel read") case <-treSec.C(): t.Errorf("unexpected channel read") default: } select { case <-oneSec.C(): // Expected! default: t.Errorf("unexpected channel non-read") } tc.Step(time.Nanosecond) // t=1.000,000,001 select { case <-oneSec.C(): t.Errorf("unexpected channel read") case <-twoSec.C(): t.Errorf("unexpected channel read") case <-treSec.C(): t.Errorf("unexpected channel read") default: } if oneSec.Stop() { t.Errorf("Expected oneSec.Stop() to return false") } if !twoSec.Stop() { t.Errorf("Expected twoSec.Stop() to return true") } tc.Step(time.Second) // t=2.000,000,001 select { case <-oneSec.C(): t.Errorf("unexpected channel read") case <-twoSec.C(): t.Errorf("unexpected channel read") case <-treSec.C(): t.Errorf("unexpected channel read") default: } if twoSec.Reset(time.Second) { t.Errorf("Expected twoSec.Reset() to return false") } if !treSec.Reset(time.Second) { t.Errorf("Expected treSec.Reset() to return true") } tc.Step(time.Nanosecond * 999999999) // t=3.0 select { case <-oneSec.C(): t.Errorf("unexpected channel read") case <-twoSec.C(): t.Errorf("unexpected channel read") case <-treSec.C(): t.Errorf("unexpected channel read") default: } tc.Step(time.Nanosecond) // t=3.000,000,001 select { case <-oneSec.C(): t.Errorf("unexpected channel read") case <-twoSec.C(): t.Errorf("unexpected channel read") default: } select { case <-treSec.C(): // Expected! default: t.Errorf("unexpected channel non-read") } } </ins> func TestFakeTick(t *testing.T) { tc := NewFakeClock(time.Now()) if tc.HasWaiters() {