engine_test.go 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125
  1. package alerting
  2. import (
  3. "context"
  4. "errors"
  5. "math"
  6. "testing"
  7. "time"
  8. "github.com/grafana/grafana/pkg/setting"
  9. . "github.com/smartystreets/goconvey/convey"
  10. )
  11. type FakeEvalHandler struct {
  12. SuccessCallID int // 0 means never success
  13. CallNb int
  14. }
  15. func NewFakeEvalHandler(successCallID int) *FakeEvalHandler {
  16. return &FakeEvalHandler{
  17. SuccessCallID: successCallID,
  18. CallNb: 0,
  19. }
  20. }
  21. func (handler *FakeEvalHandler) Eval(evalContext *EvalContext) {
  22. handler.CallNb++
  23. if handler.CallNb != handler.SuccessCallID {
  24. evalContext.Error = errors.New("Fake evaluation failure")
  25. }
  26. }
  27. type FakeResultHandler struct{}
  28. func (handler *FakeResultHandler) handle(evalContext *EvalContext) error {
  29. return nil
  30. }
  31. func TestEngineProcessJob(t *testing.T) {
  32. Convey("Alerting engine job processing", t, func() {
  33. engine := &AlertEngine{}
  34. engine.Init()
  35. setting.AlertingEvaluationTimeout = 30 * time.Second
  36. setting.AlertingNotificationTimeout = 30 * time.Second
  37. setting.AlertingMaxAttempts = 3
  38. engine.resultHandler = &FakeResultHandler{}
  39. job := &Job{running: true, Rule: &Rule{}}
  40. Convey("Should trigger retry if needed", func() {
  41. Convey("error + not last attempt -> retry", func() {
  42. engine.evalHandler = NewFakeEvalHandler(0)
  43. for i := 1; i < setting.AlertingMaxAttempts; i++ {
  44. attemptChan := make(chan int, 1)
  45. cancelChan := make(chan context.CancelFunc, setting.AlertingMaxAttempts)
  46. engine.processJob(i, attemptChan, cancelChan, job)
  47. nextAttemptID, more := <-attemptChan
  48. So(nextAttemptID, ShouldEqual, i+1)
  49. So(more, ShouldEqual, true)
  50. So(<-cancelChan, ShouldNotBeNil)
  51. }
  52. })
  53. Convey("error + last attempt -> no retry", func() {
  54. engine.evalHandler = NewFakeEvalHandler(0)
  55. attemptChan := make(chan int, 1)
  56. cancelChan := make(chan context.CancelFunc, setting.AlertingMaxAttempts)
  57. engine.processJob(setting.AlertingMaxAttempts, attemptChan, cancelChan, job)
  58. nextAttemptID, more := <-attemptChan
  59. So(nextAttemptID, ShouldEqual, 0)
  60. So(more, ShouldEqual, false)
  61. So(<-cancelChan, ShouldNotBeNil)
  62. })
  63. Convey("no error -> no retry", func() {
  64. engine.evalHandler = NewFakeEvalHandler(1)
  65. attemptChan := make(chan int, 1)
  66. cancelChan := make(chan context.CancelFunc, setting.AlertingMaxAttempts)
  67. engine.processJob(1, attemptChan, cancelChan, job)
  68. nextAttemptID, more := <-attemptChan
  69. So(nextAttemptID, ShouldEqual, 0)
  70. So(more, ShouldEqual, false)
  71. So(<-cancelChan, ShouldNotBeNil)
  72. })
  73. })
  74. Convey("Should trigger as many retries as needed", func() {
  75. Convey("never success -> max retries number", func() {
  76. expectedAttempts := setting.AlertingMaxAttempts
  77. evalHandler := NewFakeEvalHandler(0)
  78. engine.evalHandler = evalHandler
  79. engine.processJobWithRetry(context.TODO(), job)
  80. So(evalHandler.CallNb, ShouldEqual, expectedAttempts)
  81. })
  82. Convey("always success -> never retry", func() {
  83. expectedAttempts := 1
  84. evalHandler := NewFakeEvalHandler(1)
  85. engine.evalHandler = evalHandler
  86. engine.processJobWithRetry(context.TODO(), job)
  87. So(evalHandler.CallNb, ShouldEqual, expectedAttempts)
  88. })
  89. Convey("some errors before success -> some retries", func() {
  90. expectedAttempts := int(math.Ceil(float64(setting.AlertingMaxAttempts) / 2))
  91. evalHandler := NewFakeEvalHandler(expectedAttempts)
  92. engine.evalHandler = evalHandler
  93. engine.processJobWithRetry(context.TODO(), job)
  94. So(evalHandler.CallNb, ShouldEqual, expectedAttempts)
  95. })
  96. })
  97. })
  98. }