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