query_test.go 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120
  1. package conditions
  2. import (
  3. "testing"
  4. "github.com/grafana/grafana/pkg/bus"
  5. "github.com/grafana/grafana/pkg/components/simplejson"
  6. m "github.com/grafana/grafana/pkg/models"
  7. "github.com/grafana/grafana/pkg/services/alerting"
  8. "github.com/grafana/grafana/pkg/tsdb"
  9. . "github.com/smartystreets/goconvey/convey"
  10. )
  11. func TestQueryCondition(t *testing.T) {
  12. Convey("when evaluating query condition", t, func() {
  13. queryConditionScenario("Given avg() and > 100", func(ctx *queryConditionTestContext) {
  14. ctx.reducer = `{"type": "avg"}`
  15. ctx.evaluator = `{"type": "gt", "params": [100]}`
  16. Convey("Can read query condition from json model", func() {
  17. ctx.exec()
  18. So(ctx.condition.Query.From, ShouldEqual, "5m")
  19. So(ctx.condition.Query.To, ShouldEqual, "now")
  20. So(ctx.condition.Query.DatasourceId, ShouldEqual, 1)
  21. Convey("Can read query reducer", func() {
  22. reducer, ok := ctx.condition.Reducer.(*SimpleReducer)
  23. So(ok, ShouldBeTrue)
  24. So(reducer.Type, ShouldEqual, "avg")
  25. })
  26. Convey("Can read evaluator", func() {
  27. evaluator, ok := ctx.condition.Evaluator.(*ThresholdEvaluator)
  28. So(ok, ShouldBeTrue)
  29. So(evaluator.Type, ShouldEqual, "gt")
  30. })
  31. })
  32. Convey("should fire when avg is above 100", func() {
  33. one := float64(120)
  34. two := float64(0)
  35. ctx.series = tsdb.TimeSeriesSlice{tsdb.NewTimeSeries("test1", [][2]*float64{{&one, &two}})}
  36. ctx.exec()
  37. So(ctx.result.Error, ShouldBeNil)
  38. So(ctx.result.Firing, ShouldBeTrue)
  39. })
  40. Convey("Should not fire when avg is below 100", func() {
  41. one := float64(90)
  42. two := float64(0)
  43. ctx.series = tsdb.TimeSeriesSlice{tsdb.NewTimeSeries("test1", [][2]*float64{{&one, &two}})}
  44. ctx.exec()
  45. So(ctx.result.Error, ShouldBeNil)
  46. So(ctx.result.Firing, ShouldBeFalse)
  47. })
  48. })
  49. })
  50. }
  51. type queryConditionTestContext struct {
  52. reducer string
  53. evaluator string
  54. series tsdb.TimeSeriesSlice
  55. result *alerting.EvalContext
  56. condition *QueryCondition
  57. }
  58. type queryConditionScenarioFunc func(c *queryConditionTestContext)
  59. func (ctx *queryConditionTestContext) exec() {
  60. jsonModel, err := simplejson.NewJson([]byte(`{
  61. "type": "query",
  62. "query": {
  63. "params": ["A", "5m", "now"],
  64. "datasourceId": 1,
  65. "model": {"target": "aliasByNode(statsd.fakesite.counters.session_start.mobile.count, 4)"}
  66. },
  67. "reducer":` + ctx.reducer + `,
  68. "evaluator":` + ctx.evaluator + `
  69. }`))
  70. So(err, ShouldBeNil)
  71. condition, err := NewQueryCondition(jsonModel, 0)
  72. So(err, ShouldBeNil)
  73. ctx.condition = condition
  74. condition.HandleRequest = func(req *tsdb.Request) (*tsdb.Response, error) {
  75. return &tsdb.Response{
  76. Results: map[string]*tsdb.QueryResult{
  77. "A": {Series: ctx.series},
  78. },
  79. }, nil
  80. }
  81. condition.Eval(ctx.result)
  82. }
  83. func queryConditionScenario(desc string, fn queryConditionScenarioFunc) {
  84. Convey(desc, func() {
  85. bus.AddHandler("test", func(query *m.GetDataSourceByIdQuery) error {
  86. query.Result = &m.DataSource{Id: 1, Type: "graphite"}
  87. return nil
  88. })
  89. ctx := &queryConditionTestContext{}
  90. ctx.result = &alerting.EvalContext{
  91. Rule: &alerting.Rule{},
  92. }
  93. fn(ctx)
  94. })
  95. }