eval_handler_test.go 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168
  1. package alerting
  2. import (
  3. "context"
  4. "testing"
  5. . "github.com/smartystreets/goconvey/convey"
  6. )
  7. type conditionStub struct {
  8. firing bool
  9. operator string
  10. matches []*EvalMatch
  11. noData bool
  12. }
  13. func (c *conditionStub) Eval(context *EvalContext) (*ConditionResult, error) {
  14. return &ConditionResult{Firing: c.firing, EvalMatches: c.matches, Operator: c.operator, NoDataFound: c.noData}, nil
  15. }
  16. func TestAlertingExecutor(t *testing.T) {
  17. Convey("Test alert execution", t, func() {
  18. handler := NewEvalHandler()
  19. Convey("Show return triggered with single passing condition", func() {
  20. context := NewEvalContext(context.TODO(), &Rule{
  21. Conditions: []Condition{&conditionStub{
  22. firing: true,
  23. }},
  24. })
  25. handler.Eval(context)
  26. So(context.Firing, ShouldEqual, true)
  27. So(context.ConditionEvals, ShouldEqual, "true = true")
  28. })
  29. Convey("Show return false with not passing asdf", func() {
  30. context := NewEvalContext(context.TODO(), &Rule{
  31. Conditions: []Condition{
  32. &conditionStub{firing: true, operator: "and", matches: []*EvalMatch{&EvalMatch{}, &EvalMatch{}}},
  33. &conditionStub{firing: false, operator: "and"},
  34. },
  35. })
  36. handler.Eval(context)
  37. So(context.Firing, ShouldEqual, false)
  38. So(context.ConditionEvals, ShouldEqual, "[true AND false] = false")
  39. })
  40. Convey("Show return true if any of the condition is passing with OR operator", func() {
  41. context := NewEvalContext(context.TODO(), &Rule{
  42. Conditions: []Condition{
  43. &conditionStub{firing: true, operator: "and"},
  44. &conditionStub{firing: false, operator: "or"},
  45. },
  46. })
  47. handler.Eval(context)
  48. So(context.Firing, ShouldEqual, true)
  49. So(context.ConditionEvals, ShouldEqual, "[true OR false] = true")
  50. })
  51. Convey("Show return false if any of the condition is failing with AND operator", func() {
  52. context := NewEvalContext(context.TODO(), &Rule{
  53. Conditions: []Condition{
  54. &conditionStub{firing: true, operator: "and"},
  55. &conditionStub{firing: false, operator: "and"},
  56. },
  57. })
  58. handler.Eval(context)
  59. So(context.Firing, ShouldEqual, false)
  60. So(context.ConditionEvals, ShouldEqual, "[true AND false] = false")
  61. })
  62. Convey("Show return true if one condition is failing with nested OR operator", func() {
  63. context := NewEvalContext(context.TODO(), &Rule{
  64. Conditions: []Condition{
  65. &conditionStub{firing: true, operator: "and"},
  66. &conditionStub{firing: true, operator: "and"},
  67. &conditionStub{firing: false, operator: "or"},
  68. },
  69. })
  70. handler.Eval(context)
  71. So(context.Firing, ShouldEqual, true)
  72. So(context.ConditionEvals, ShouldEqual, "[[true AND true] OR false] = true")
  73. })
  74. Convey("Show return false if one condition is passing with nested OR operator", func() {
  75. context := NewEvalContext(context.TODO(), &Rule{
  76. Conditions: []Condition{
  77. &conditionStub{firing: true, operator: "and"},
  78. &conditionStub{firing: false, operator: "and"},
  79. &conditionStub{firing: false, operator: "or"},
  80. },
  81. })
  82. handler.Eval(context)
  83. So(context.Firing, ShouldEqual, false)
  84. So(context.ConditionEvals, ShouldEqual, "[[true AND false] OR false] = false")
  85. })
  86. Convey("Show return false if a condition is failing with nested AND operator", func() {
  87. context := NewEvalContext(context.TODO(), &Rule{
  88. Conditions: []Condition{
  89. &conditionStub{firing: true, operator: "and"},
  90. &conditionStub{firing: false, operator: "and"},
  91. &conditionStub{firing: true, operator: "and"},
  92. },
  93. })
  94. handler.Eval(context)
  95. So(context.Firing, ShouldEqual, false)
  96. So(context.ConditionEvals, ShouldEqual, "[[true AND false] AND true] = false")
  97. })
  98. Convey("Show return true if a condition is passing with nested OR operator", func() {
  99. context := NewEvalContext(context.TODO(), &Rule{
  100. Conditions: []Condition{
  101. &conditionStub{firing: true, operator: "and"},
  102. &conditionStub{firing: false, operator: "or"},
  103. &conditionStub{firing: true, operator: "or"},
  104. },
  105. })
  106. handler.Eval(context)
  107. So(context.Firing, ShouldEqual, true)
  108. So(context.ConditionEvals, ShouldEqual, "[[true OR false] OR true] = true")
  109. })
  110. Convey("Should return no data if one condition has nodata", func() {
  111. context := NewEvalContext(context.TODO(), &Rule{
  112. Conditions: []Condition{
  113. &conditionStub{operator: "and", noData: true},
  114. },
  115. })
  116. handler.Eval(context)
  117. So(context.Firing, ShouldEqual, false)
  118. So(context.NoDataFound, ShouldBeTrue)
  119. })
  120. Convey("Should return no data if both conditions have no data and using AND", func() {
  121. context := NewEvalContext(context.TODO(), &Rule{
  122. Conditions: []Condition{
  123. &conditionStub{operator: "and", noData: true},
  124. &conditionStub{operator: "and", noData: false},
  125. },
  126. })
  127. handler.Eval(context)
  128. So(context.NoDataFound, ShouldBeFalse)
  129. })
  130. Convey("Should not return no data if both conditions have no data and using OR", func() {
  131. context := NewEvalContext(context.TODO(), &Rule{
  132. Conditions: []Condition{
  133. &conditionStub{operator: "or", noData: true},
  134. &conditionStub{operator: "or", noData: false},
  135. },
  136. })
  137. handler.Eval(context)
  138. So(context.NoDataFound, ShouldBeTrue)
  139. })
  140. })
  141. }