mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-07-25 20:53:33 +00:00
Merge pull request #78808 from MikeSpreitzer/issue-78807
Fixed clock.fakeTimer.Stop and Reset
This commit is contained in:
commit
f4a33c1997
@ -80,7 +80,6 @@ type fakeClockWaiter struct {
|
|||||||
stepInterval time.Duration
|
stepInterval time.Duration
|
||||||
skipIfBlocked bool
|
skipIfBlocked bool
|
||||||
destChan chan time.Time
|
destChan chan time.Time
|
||||||
fired bool
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewFakeClock(t time.Time) *FakeClock {
|
func NewFakeClock(t time.Time) *FakeClock {
|
||||||
@ -175,12 +174,10 @@ func (f *FakeClock) setTimeLocked(t time.Time) {
|
|||||||
if w.skipIfBlocked {
|
if w.skipIfBlocked {
|
||||||
select {
|
select {
|
||||||
case w.destChan <- t:
|
case w.destChan <- t:
|
||||||
w.fired = true
|
|
||||||
default:
|
default:
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
w.destChan <- t
|
w.destChan <- t
|
||||||
w.fired = true
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if w.stepInterval > 0 {
|
if w.stepInterval > 0 {
|
||||||
@ -287,36 +284,50 @@ func (f *fakeTimer) C() <-chan time.Time {
|
|||||||
return f.waiter.destChan
|
return f.waiter.destChan
|
||||||
}
|
}
|
||||||
|
|
||||||
// Stop stops the timer and returns true if the timer has not yet fired, or false otherwise.
|
// 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.
|
||||||
func (f *fakeTimer) Stop() bool {
|
func (f *fakeTimer) Stop() bool {
|
||||||
f.fakeClock.lock.Lock()
|
f.fakeClock.lock.Lock()
|
||||||
defer f.fakeClock.lock.Unlock()
|
defer f.fakeClock.lock.Unlock()
|
||||||
|
// The timer has already fired or been stopped, unless it is found
|
||||||
newWaiters := make([]fakeClockWaiter, 0, len(f.fakeClock.waiters))
|
// among the clock's waiters.
|
||||||
for i := range f.fakeClock.waiters {
|
stopped := false
|
||||||
w := &f.fakeClock.waiters[i]
|
oldWaiters := f.fakeClock.waiters
|
||||||
if w != &f.waiter {
|
newWaiters := make([]fakeClockWaiter, 0, len(oldWaiters))
|
||||||
newWaiters = append(newWaiters, *w)
|
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])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
f.fakeClock.waiters = newWaiters
|
f.fakeClock.waiters = newWaiters
|
||||||
|
|
||||||
return !f.waiter.fired
|
return stopped
|
||||||
}
|
}
|
||||||
|
|
||||||
// Reset resets the timer to the fake clock's "now" + d. It returns true if the timer has not yet
|
// Reset conditionally updates the firing time of the timer. If the
|
||||||
// fired, or false otherwise.
|
// 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.
|
||||||
func (f *fakeTimer) Reset(d time.Duration) bool {
|
func (f *fakeTimer) Reset(d time.Duration) bool {
|
||||||
f.fakeClock.lock.Lock()
|
f.fakeClock.lock.Lock()
|
||||||
defer f.fakeClock.lock.Unlock()
|
defer f.fakeClock.lock.Unlock()
|
||||||
|
waiters := f.fakeClock.waiters
|
||||||
active := !f.waiter.fired
|
seekChan := f.waiter.destChan
|
||||||
|
for i := range waiters {
|
||||||
f.waiter.fired = false
|
if waiters[i].destChan == seekChan {
|
||||||
f.waiter.targetTime = f.fakeClock.time.Add(d)
|
waiters[i].targetTime = f.fakeClock.time.Add(d)
|
||||||
|
return true
|
||||||
return active
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
type Ticker interface {
|
type Ticker interface {
|
||||||
|
@ -117,6 +117,108 @@ func TestFakeAfter(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestFakeTick(t *testing.T) {
|
func TestFakeTick(t *testing.T) {
|
||||||
tc := NewFakeClock(time.Now())
|
tc := NewFakeClock(time.Now())
|
||||||
if tc.HasWaiters() {
|
if tc.HasWaiters() {
|
||||||
|
Loading…
Reference in New Issue
Block a user