github.com/haraldrudell/parl@v0.4.176/ptime/on-ticker-thread_test.go (about) 1 /* 2 © 2023–present Harald Rudell <harald.rudell@gmail.com> (https://haraldrudell.github.io/haraldrudell/) 3 ISC License 4 */ 5 6 package ptime 7 8 import ( 9 "context" 10 "sync" 11 "testing" 12 "time" 13 14 "github.com/haraldrudell/parl/perrors" 15 ) 16 17 type OnTickerThreadTester struct { 18 ats []time.Time 19 dones []error 20 wg sync.WaitGroup 21 done sync.WaitGroup 22 ctx context.Context 23 } 24 25 func NewOnTickerThreadTester(ctx context.Context, ticks int) (o *OnTickerThreadTester) { 26 ox := OnTickerThreadTester{ctx: ctx} 27 ox.wg.Add(ticks) 28 ox.done.Add(1) 29 return &ox 30 } 31 func (o *OnTickerThreadTester) callback(at time.Time) { 32 o.ats = append(o.ats, at) 33 o.wg.Done() 34 } 35 func (o *OnTickerThreadTester) Done(errp *error) { 36 defer o.done.Done() 37 38 var err error 39 if errp != nil { 40 err = *errp 41 } 42 o.dones = append(o.dones, err) 43 } 44 func (o *OnTickerThreadTester) Context() (ctx context.Context) { 45 return o.ctx 46 } 47 48 func TestOnTickerThread(t *testing.T) { 49 const period = time.Millisecond 50 const minPeriod = period / 2 51 const maxPeriod = 4 * period 52 const ticks = 2 53 54 var ctx, cancel = context.WithCancel(context.Background()) 55 var o = NewOnTickerThreadTester(ctx, ticks) 56 go OnTickerThread(o.callback, period, nil, o) 57 58 // wait for 2 ticks 59 o.wg.Wait() 60 61 // cancel the ticker 62 cancel() 63 // wait for thread to exit 64 o.done.Wait() 65 66 // thread should have exited without error 67 if e := o.dones[0]; e != nil { 68 t.Errorf("thread err: %s", perrors.Short(e)) 69 } 70 // there should be 2 ticks 71 if len(o.ats) != ticks { 72 t.Fatalf("ticks: %d exp %d", len(o.ats), ticks) 73 } 74 // duration should relate to period 75 var duration = o.ats[1].Sub(o.ats[0]) 76 if duration < minPeriod { 77 t.Errorf("duration too short: %s exp %s", duration, period) 78 } else if duration >= maxPeriod { 79 t.Errorf("duration too long: %s exp %s", duration, period) 80 } 81 }