eval_context_test.go 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153
  1. package alerting
  2. import (
  3. "context"
  4. "errors"
  5. "testing"
  6. "time"
  7. "github.com/grafana/grafana/pkg/models"
  8. )
  9. func TestStateIsUpdatedWhenNeeded(t *testing.T) {
  10. ctx := NewEvalContext(context.TODO(), &Rule{Conditions: []Condition{&conditionStub{firing: true}}})
  11. t.Run("ok -> alerting", func(t *testing.T) {
  12. ctx.PrevAlertState = models.AlertStateOK
  13. ctx.Rule.State = models.AlertStateAlerting
  14. if !ctx.ShouldUpdateAlertState() {
  15. t.Fatalf("expected should updated to be true")
  16. }
  17. })
  18. t.Run("ok -> ok", func(t *testing.T) {
  19. ctx.PrevAlertState = models.AlertStateOK
  20. ctx.Rule.State = models.AlertStateOK
  21. if ctx.ShouldUpdateAlertState() {
  22. t.Fatalf("expected should updated to be false")
  23. }
  24. })
  25. }
  26. func TestGetStateFromEvalContext(t *testing.T) {
  27. tcs := []struct {
  28. name string
  29. expected models.AlertStateType
  30. applyFn func(ec *EvalContext)
  31. focus bool
  32. }{
  33. {
  34. name: "ok -> alerting",
  35. expected: models.AlertStateAlerting,
  36. applyFn: func(ec *EvalContext) {
  37. ec.Firing = true
  38. ec.PrevAlertState = models.AlertStateOK
  39. },
  40. },
  41. {
  42. name: "ok -> error(alerting)",
  43. expected: models.AlertStateAlerting,
  44. applyFn: func(ec *EvalContext) {
  45. ec.PrevAlertState = models.AlertStateOK
  46. ec.Error = errors.New("test error")
  47. ec.Rule.ExecutionErrorState = models.ExecutionErrorSetAlerting
  48. },
  49. },
  50. {
  51. name: "ok -> pending. since its been firing for less than FOR",
  52. expected: models.AlertStatePending,
  53. applyFn: func(ec *EvalContext) {
  54. ec.PrevAlertState = models.AlertStateOK
  55. ec.Firing = true
  56. ec.Rule.LastStateChange = time.Now().Add(-time.Minute * 2)
  57. ec.Rule.For = time.Minute * 5
  58. },
  59. },
  60. {
  61. name: "ok -> alerting. since its been firing for more than FOR",
  62. expected: models.AlertStateAlerting,
  63. applyFn: func(ec *EvalContext) {
  64. ec.PrevAlertState = models.AlertStateOK
  65. ec.Firing = true
  66. ec.Rule.LastStateChange = time.Now().Add(-(time.Hour * 5))
  67. ec.Rule.For = time.Minute * 2
  68. },
  69. },
  70. {
  71. name: "alerting -> alerting. should not update regardless of FOR",
  72. expected: models.AlertStateAlerting,
  73. applyFn: func(ec *EvalContext) {
  74. ec.PrevAlertState = models.AlertStateAlerting
  75. ec.Firing = true
  76. ec.Rule.LastStateChange = time.Now().Add(-time.Minute * 5)
  77. ec.Rule.For = time.Minute * 2
  78. },
  79. },
  80. {
  81. name: "ok -> ok. should not update regardless of FOR",
  82. expected: models.AlertStateOK,
  83. applyFn: func(ec *EvalContext) {
  84. ec.PrevAlertState = models.AlertStateOK
  85. ec.Rule.LastStateChange = time.Now().Add(-time.Minute * 5)
  86. ec.Rule.For = time.Minute * 2
  87. },
  88. },
  89. {
  90. name: "ok -> error(keep_last)",
  91. expected: models.AlertStateOK,
  92. applyFn: func(ec *EvalContext) {
  93. ec.PrevAlertState = models.AlertStateOK
  94. ec.Error = errors.New("test error")
  95. ec.Rule.ExecutionErrorState = models.ExecutionErrorKeepState
  96. },
  97. },
  98. {
  99. name: "pending -> error(keep_last)",
  100. expected: models.AlertStatePending,
  101. applyFn: func(ec *EvalContext) {
  102. ec.PrevAlertState = models.AlertStatePending
  103. ec.Error = errors.New("test error")
  104. ec.Rule.ExecutionErrorState = models.ExecutionErrorKeepState
  105. },
  106. },
  107. {
  108. name: "ok -> no_data(alerting)",
  109. expected: models.AlertStateAlerting,
  110. applyFn: func(ec *EvalContext) {
  111. ec.PrevAlertState = models.AlertStateOK
  112. ec.Rule.NoDataState = models.NoDataSetAlerting
  113. ec.NoDataFound = true
  114. },
  115. },
  116. {
  117. name: "ok -> no_data(keep_last)",
  118. expected: models.AlertStateOK,
  119. applyFn: func(ec *EvalContext) {
  120. ec.PrevAlertState = models.AlertStateOK
  121. ec.Rule.NoDataState = models.NoDataKeepState
  122. ec.NoDataFound = true
  123. },
  124. },
  125. {
  126. name: "pending -> no_data(keep_last)",
  127. expected: models.AlertStatePending,
  128. applyFn: func(ec *EvalContext) {
  129. ec.PrevAlertState = models.AlertStatePending
  130. ec.Rule.NoDataState = models.NoDataKeepState
  131. ec.NoDataFound = true
  132. },
  133. },
  134. }
  135. for _, tc := range tcs {
  136. ctx := NewEvalContext(context.TODO(), &Rule{Conditions: []Condition{&conditionStub{firing: true}}})
  137. tc.applyFn(ctx)
  138. have := ctx.GetNewState()
  139. if have != tc.expected {
  140. t.Errorf("failed: %s \n expected '%s' have '%s'\n", tc.name, tc.expected, string(have))
  141. }
  142. }
  143. }