ticker_test.go 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121
  1. package alerting
  2. import (
  3. "testing"
  4. "time"
  5. "github.com/benbjohnson/clock"
  6. )
  7. func inspectTick(tick time.Time, last time.Time, offset time.Duration, t *testing.T) {
  8. if !tick.Equal(last.Add(time.Duration(1) * time.Second)) {
  9. t.Fatalf("expected a tick 1 second more than prev, %s. got: %s", last, tick)
  10. }
  11. }
  12. // returns the new last tick seen
  13. func assertAdvanceUntil(ticker *Ticker, last, desiredLast time.Time, offset, wait time.Duration, t *testing.T) time.Time {
  14. for {
  15. select {
  16. case tick := <-ticker.C:
  17. inspectTick(tick, last, offset, t)
  18. last = tick
  19. case <-time.NewTimer(wait).C:
  20. if last.Before(desiredLast) {
  21. t.Fatalf("waited %s for ticker to advance to %s, but only went up to %s", wait, desiredLast, last)
  22. }
  23. if last.After(desiredLast) {
  24. t.Fatalf("timer advanced too far. should only have gone up to %s, but it went up to %s", desiredLast, last)
  25. }
  26. return last
  27. }
  28. }
  29. }
  30. func assertNoAdvance(ticker *Ticker, desiredLast time.Time, wait time.Duration, t *testing.T) {
  31. for {
  32. select {
  33. case tick := <-ticker.C:
  34. t.Fatalf("timer should have stayed at %s, instead it advanced to %s", desiredLast, tick)
  35. case <-time.NewTimer(wait).C:
  36. return
  37. }
  38. }
  39. }
  40. func TestTickerRetro1Hour(t *testing.T) {
  41. offset := time.Duration(10) * time.Second
  42. last := time.Unix(0, 0)
  43. mock := clock.NewMock()
  44. mock.Add(time.Duration(1) * time.Hour)
  45. desiredLast := mock.Now().Add(-offset)
  46. ticker := NewTicker(last, offset, mock)
  47. last = assertAdvanceUntil(ticker, last, desiredLast, offset, time.Duration(10)*time.Millisecond, t)
  48. assertNoAdvance(ticker, last, time.Duration(500)*time.Millisecond, t)
  49. }
  50. func TestAdvanceWithUpdateOffset(t *testing.T) {
  51. offset := time.Duration(10) * time.Second
  52. last := time.Unix(0, 0)
  53. mock := clock.NewMock()
  54. mock.Add(time.Duration(1) * time.Hour)
  55. desiredLast := mock.Now().Add(-offset)
  56. ticker := NewTicker(last, offset, mock)
  57. last = assertAdvanceUntil(ticker, last, desiredLast, offset, time.Duration(10)*time.Millisecond, t)
  58. assertNoAdvance(ticker, last, time.Duration(500)*time.Millisecond, t)
  59. // lowering offset should see a few more ticks
  60. offset = time.Duration(5) * time.Second
  61. ticker.updateOffset(offset)
  62. desiredLast = mock.Now().Add(-offset)
  63. last = assertAdvanceUntil(ticker, last, desiredLast, offset, time.Duration(9)*time.Millisecond, t)
  64. assertNoAdvance(ticker, last, time.Duration(500)*time.Millisecond, t)
  65. // advancing clock should see even more ticks
  66. mock.Add(time.Duration(1) * time.Hour)
  67. desiredLast = mock.Now().Add(-offset)
  68. last = assertAdvanceUntil(ticker, last, desiredLast, offset, time.Duration(8)*time.Millisecond, t)
  69. assertNoAdvance(ticker, last, time.Duration(500)*time.Millisecond, t)
  70. }
  71. func getCase(lastSeconds, offsetSeconds int) (time.Time, time.Duration) {
  72. last := time.Unix(int64(lastSeconds), 0)
  73. offset := time.Duration(offsetSeconds) * time.Second
  74. return last, offset
  75. }
  76. func TestTickerNoAdvance(t *testing.T) {
  77. // it's 00:01:00 now. what are some cases where we don't want the ticker to advance?
  78. mock := clock.NewMock()
  79. mock.Add(time.Duration(60) * time.Second)
  80. type Case struct {
  81. last int
  82. offset int
  83. }
  84. // note that some cases add up to now, others go into the future
  85. cases := []Case{
  86. {50, 10},
  87. {50, 30},
  88. {59, 1},
  89. {59, 10},
  90. {59, 30},
  91. {60, 1},
  92. {60, 10},
  93. {60, 30},
  94. {90, 1},
  95. {90, 10},
  96. {90, 30},
  97. }
  98. for _, c := range cases {
  99. last, offset := getCase(c.last, c.offset)
  100. ticker := NewTicker(last, offset, mock)
  101. assertNoAdvance(ticker, last, time.Duration(500)*time.Millisecond, t)
  102. }
  103. }