invoices/test: add test clock
This commit is contained in:
parent
499f2b16cf
commit
56958493fe
77
invoices/clock_test.go
Normal file
77
invoices/clock_test.go
Normal file
@ -0,0 +1,77 @@
|
||||
package invoices
|
||||
|
||||
import (
|
||||
"sync"
|
||||
"time"
|
||||
)
|
||||
|
||||
// testClock can be used in tests to mock time.
|
||||
type testClock struct {
|
||||
currentTime time.Time
|
||||
timeChanMap map[time.Time][]chan time.Time
|
||||
timeLock sync.Mutex
|
||||
}
|
||||
|
||||
// newTestClock returns a new test clock.
|
||||
func newTestClock(startTime time.Time) *testClock {
|
||||
return &testClock{
|
||||
currentTime: startTime,
|
||||
timeChanMap: make(map[time.Time][]chan time.Time),
|
||||
}
|
||||
}
|
||||
|
||||
// now returns the current (test) time.
|
||||
func (c *testClock) now() time.Time {
|
||||
c.timeLock.Lock()
|
||||
defer c.timeLock.Unlock()
|
||||
|
||||
return c.currentTime
|
||||
}
|
||||
|
||||
// tickAfter returns a channel that will receive a tick at the specified time.
|
||||
func (c *testClock) tickAfter(duration time.Duration) <-chan time.Time {
|
||||
c.timeLock.Lock()
|
||||
defer c.timeLock.Unlock()
|
||||
|
||||
triggerTime := c.currentTime.Add(duration)
|
||||
log.Debugf("tickAfter called: duration=%v, trigger_time=%v",
|
||||
duration, triggerTime)
|
||||
|
||||
ch := make(chan time.Time, 1)
|
||||
|
||||
// If already expired, tick immediately.
|
||||
if !triggerTime.After(c.currentTime) {
|
||||
ch <- c.currentTime
|
||||
return ch
|
||||
}
|
||||
|
||||
// Otherwise store the channel until the trigger time is there.
|
||||
chans := c.timeChanMap[triggerTime]
|
||||
chans = append(chans, ch)
|
||||
c.timeChanMap[triggerTime] = chans
|
||||
|
||||
return ch
|
||||
}
|
||||
|
||||
// setTime sets the (test) time and triggers tick channels when they expire.
|
||||
func (c *testClock) setTime(now time.Time) {
|
||||
c.timeLock.Lock()
|
||||
defer c.timeLock.Unlock()
|
||||
|
||||
c.currentTime = now
|
||||
remainingChans := make(map[time.Time][]chan time.Time)
|
||||
for triggerTime, chans := range c.timeChanMap {
|
||||
// If the trigger time is still in the future, keep this channel
|
||||
// in the channel map for later.
|
||||
if triggerTime.After(now) {
|
||||
remainingChans[triggerTime] = chans
|
||||
continue
|
||||
}
|
||||
|
||||
for _, c := range chans {
|
||||
c <- now
|
||||
}
|
||||
}
|
||||
|
||||
c.timeChanMap = remainingChans
|
||||
}
|
Loading…
Reference in New Issue
Block a user