From 02e53af36e6c978af692887ed449b74026d76fec Mon Sep 17 00:00:00 2001 From: John Shahid Date: Fri, 18 May 2018 15:58:52 -0400 Subject: [PATCH] don't fire twice when multiple tickers are registered with the clock --- fakeclock/fake_ticker_test.go | 34 ++++++++++++++++++++++++++++++++++ fakeclock/fake_timer.go | 9 ++++++--- 2 files changed, 40 insertions(+), 3 deletions(-) diff --git a/fakeclock/fake_ticker_test.go b/fakeclock/fake_ticker_test.go index f7ed5a8..874a441 100644 --- a/fakeclock/fake_ticker_test.go +++ b/fakeclock/fake_ticker_test.go @@ -1,6 +1,7 @@ package fakeclock_test import ( + "sync/atomic" "time" "code.cloudfoundry.org/clock/fakeclock" @@ -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 diff --git a/fakeclock/fake_timer.go b/fakeclock/fake_timer.go index b412d02..8c6cc0c 100644 --- a/fakeclock/fake_timer.go +++ b/fakeclock/fake_timer.go @@ -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 } @@ -79,6 +82,6 @@ func (ft *fakeTimer) timeUpdated(now time.Time) { } if ft.repeatable() { - ft.Reset(ft.duration) + ft.reset(ft.duration) } }