Skip to content

Commit

Permalink
don't fire twice when multiple tickers are registered with the clock
Browse files Browse the repository at this point in the history
  • Loading branch information
jvshahid committed May 18, 2018
1 parent e9dc86b commit 02e53af
Show file tree
Hide file tree
Showing 2 changed files with 40 additions and 3 deletions.
34 changes: 34 additions & 0 deletions fakeclock/fake_ticker_test.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package fakeclock_test

import (
"sync/atomic"
"time"

"code.cloudfoundry.org/clock/fakeclock"
Expand Down Expand Up @@ -43,6 +44,39 @@ var _ = Describe("FakeTicker", func() {
Eventually(timeChan).Should(Receive(Equal(initialTime.Add(30 * time.Second))))
})

It("when there are multiple tickers", func() {
const period = 1 * time.Second

ticker1 := fakeClock.NewTicker(period)
ticker2 := fakeClock.NewTicker(period)

// Eventually(ticker.C()).Should(Recieve) make it hard to detect this error
// due to the polling nature of Eventually. We usually end up missing the
// second event and it gets dropped on the floor. Use counters instead to
// make sure we don't miss the second erroneous event
count1 := uint32(0)
count2 := uint32(0)

go func() {
for {
select {
case <-ticker1.C():
atomic.AddUint32(&count1, 1)
case <-ticker2.C():
atomic.AddUint32(&count2, 1)
}
}
}()

fakeClock.Increment(period)

Eventually(func() uint32 { return atomic.LoadUint32(&count1) }).Should(BeEquivalentTo(1))
Eventually(func() uint32 { return atomic.LoadUint32(&count2) }).Should(BeEquivalentTo(1))

Consistently(func() uint32 { return atomic.LoadUint32(&count1) }).Should(BeEquivalentTo(1))
Consistently(func() uint32 { return atomic.LoadUint32(&count2) }).Should(BeEquivalentTo(1))
})

It("should not fire until a period has passed", func() {
const period = 1 * time.Second

Expand Down
9 changes: 6 additions & 3 deletions fakeclock/fake_timer.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,16 +31,19 @@ func (ft *fakeTimer) C() <-chan time.Time {
return ft.channel
}

func (ft *fakeTimer) Reset(d time.Duration) bool {
func (ft *fakeTimer) reset(d time.Duration) bool {
currentTime := ft.clock.Now()

ft.mutex.Lock()
active := !ft.completionTime.IsZero()
ft.completionTime = currentTime.Add(d)
ft.mutex.Unlock()
return active
}

func (ft *fakeTimer) Reset(d time.Duration) bool {
active := ft.reset(d)
ft.clock.addTimeWatcher(ft)

return active
}

Expand Down Expand Up @@ -79,6 +82,6 @@ func (ft *fakeTimer) timeUpdated(now time.Time) {
}

if ft.repeatable() {
ft.Reset(ft.duration)
ft.reset(ft.duration)
}
}

0 comments on commit 02e53af

Please sign in to comment.