package times import ( "sort" "time" ) type clockState struct { current time.Time chans map[time.Time][]chan<- time.Time chantlist []time.Time } type test struct { state chan clockState } func makeTestClock(initial time.Time) test { s := make(chan clockState, 1) s <- clockState{ current: initial, chans: make(map[time.Time][]chan<- time.Time), } return test{state: s} } func triggerChans(s clockState) clockState { for len(s.chantlist) > 0 && !s.chantlist[0].After(s.current) { var ct time.Time ct, s.chantlist = s.chantlist[0], s.chantlist[1:] for _, c := range s.chans[ct] { c <- s.current } delete(s.chans, ct) } return s } func (t test) now() time.Time { s := <-t.state defer func() { t.state <- s }() return s.current } func (t test) after(d time.Duration) <-chan time.Time { s := <-t.state defer func() { t.state <- s }() c := make(chan time.Time, 1) ct := s.current.Add(d) if !ct.After(s.current) { c <- s.current return c } _, ctset := s.chans[ct] s.chans[ct] = append(s.chans[ct], c) if !ctset { s.chantlist = append(s.chantlist, ct) sort.Slice(s.chantlist, func(i, j int) bool { return s.chantlist[i].Before(s.chantlist[j]) }) } return c } func (t test) pass(d time.Duration) { s := <-t.state defer func() { t.state <- s }() if d < 0 { d = 0 } s.current = s.current.Add(d) s = triggerChans(s) } func (t test) jump(to time.Time) { s := <-t.state defer func() { t.state <- s }() if to.Before(s.current) { return } s.current = to s = triggerChans(s) }