mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
Chore: Refactor GoConvey tests in alerting/conditions (#40843)
* refactor goconvery tests * use more meaningful assertion * use more meaningful assertions
This commit is contained in:
parent
bce1011361
commit
24a74cd06e
@ -3,60 +3,59 @@ package conditions
|
||||
import (
|
||||
"testing"
|
||||
|
||||
. "github.com/smartystreets/goconvey/convey"
|
||||
|
||||
"github.com/grafana/grafana/pkg/components/null"
|
||||
"github.com/grafana/grafana/pkg/components/simplejson"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func evaluatorScenario(json string, reducedValue float64, datapoints ...float64) bool {
|
||||
func evaluatorScenario(t *testing.T, json string, reducedValue float64, datapoints ...float64) bool {
|
||||
jsonModel, err := simplejson.NewJson([]byte(json))
|
||||
So(err, ShouldBeNil)
|
||||
require.NoError(t, err)
|
||||
|
||||
evaluator, err := NewAlertEvaluator(jsonModel)
|
||||
So(err, ShouldBeNil)
|
||||
require.NoError(t, err)
|
||||
|
||||
return evaluator.Eval(null.FloatFrom(reducedValue))
|
||||
}
|
||||
|
||||
func TestEvaluators(t *testing.T) {
|
||||
Convey("greater then", t, func() {
|
||||
So(evaluatorScenario(`{"type": "gt", "params": [1] }`, 3), ShouldBeTrue)
|
||||
So(evaluatorScenario(`{"type": "gt", "params": [3] }`, 1), ShouldBeFalse)
|
||||
t.Run("greater then", func(t *testing.T) {
|
||||
require.True(t, evaluatorScenario(t, `{"type": "gt", "params": [1] }`, 3))
|
||||
require.False(t, evaluatorScenario(t, `{"type": "gt", "params": [3] }`, 1))
|
||||
})
|
||||
|
||||
Convey("less then", t, func() {
|
||||
So(evaluatorScenario(`{"type": "lt", "params": [1] }`, 3), ShouldBeFalse)
|
||||
So(evaluatorScenario(`{"type": "lt", "params": [3] }`, 1), ShouldBeTrue)
|
||||
t.Run("less then", func(t *testing.T) {
|
||||
require.False(t, evaluatorScenario(t, `{"type": "lt", "params": [1] }`, 3))
|
||||
require.True(t, evaluatorScenario(t, `{"type": "lt", "params": [3] }`, 1))
|
||||
})
|
||||
|
||||
Convey("within_range", t, func() {
|
||||
So(evaluatorScenario(`{"type": "within_range", "params": [1, 100] }`, 3), ShouldBeTrue)
|
||||
So(evaluatorScenario(`{"type": "within_range", "params": [1, 100] }`, 300), ShouldBeFalse)
|
||||
So(evaluatorScenario(`{"type": "within_range", "params": [100, 1] }`, 3), ShouldBeTrue)
|
||||
So(evaluatorScenario(`{"type": "within_range", "params": [100, 1] }`, 300), ShouldBeFalse)
|
||||
t.Run("within_range", func(t *testing.T) {
|
||||
require.True(t, evaluatorScenario(t, `{"type": "within_range", "params": [1, 100] }`, 3))
|
||||
require.False(t, evaluatorScenario(t, `{"type": "within_range", "params": [1, 100] }`, 300))
|
||||
require.True(t, evaluatorScenario(t, `{"type": "within_range", "params": [100, 1] }`, 3))
|
||||
require.False(t, evaluatorScenario(t, `{"type": "within_range", "params": [100, 1] }`, 300))
|
||||
})
|
||||
|
||||
Convey("outside_range", t, func() {
|
||||
So(evaluatorScenario(`{"type": "outside_range", "params": [1, 100] }`, 1000), ShouldBeTrue)
|
||||
So(evaluatorScenario(`{"type": "outside_range", "params": [1, 100] }`, 50), ShouldBeFalse)
|
||||
So(evaluatorScenario(`{"type": "outside_range", "params": [100, 1] }`, 1000), ShouldBeTrue)
|
||||
So(evaluatorScenario(`{"type": "outside_range", "params": [100, 1] }`, 50), ShouldBeFalse)
|
||||
t.Run("outside_range", func(t *testing.T) {
|
||||
require.True(t, evaluatorScenario(t, `{"type": "outside_range", "params": [1, 100] }`, 1000))
|
||||
require.False(t, evaluatorScenario(t, `{"type": "outside_range", "params": [1, 100] }`, 50))
|
||||
require.True(t, evaluatorScenario(t, `{"type": "outside_range", "params": [100, 1] }`, 1000))
|
||||
require.False(t, evaluatorScenario(t, `{"type": "outside_range", "params": [100, 1] }`, 50))
|
||||
})
|
||||
|
||||
Convey("no_value", t, func() {
|
||||
Convey("should be false if series have values", func() {
|
||||
So(evaluatorScenario(`{"type": "no_value", "params": [] }`, 50), ShouldBeFalse)
|
||||
t.Run("no_value", func(t *testing.T) {
|
||||
t.Run("should be false if series have values", func(t *testing.T) {
|
||||
require.False(t, evaluatorScenario(t, `{"type": "no_value", "params": [] }`, 50))
|
||||
})
|
||||
|
||||
Convey("should be true when the series have no value", func() {
|
||||
t.Run("should be true when the series have no value", func(t *testing.T) {
|
||||
jsonModel, err := simplejson.NewJson([]byte(`{"type": "no_value", "params": [] }`))
|
||||
So(err, ShouldBeNil)
|
||||
require.NoError(t, err)
|
||||
|
||||
evaluator, err := NewAlertEvaluator(jsonModel)
|
||||
So(err, ShouldBeNil)
|
||||
require.NoError(t, err)
|
||||
|
||||
So(evaluator.Eval(null.FloatFromPtr(nil)), ShouldBeTrue)
|
||||
require.True(t, evaluator.Eval(null.FloatFromPtr(nil)))
|
||||
})
|
||||
})
|
||||
}
|
||||
|
@ -12,12 +12,13 @@ import (
|
||||
"github.com/grafana/grafana/pkg/models"
|
||||
"github.com/grafana/grafana/pkg/plugins"
|
||||
"github.com/grafana/grafana/pkg/services/alerting"
|
||||
. "github.com/smartystreets/goconvey/convey"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestQueryInterval(t *testing.T) {
|
||||
Convey("When evaluating query condition, regarding the interval value", t, func() {
|
||||
Convey("Can handle interval-calculation with no panel-min-interval and no datasource-min-interval", func() {
|
||||
t.Run("When evaluating query condition, regarding the interval value", func(t *testing.T) {
|
||||
t.Run("Can handle interval-calculation with no panel-min-interval and no datasource-min-interval", func(t *testing.T) {
|
||||
// no panel-min-interval in the queryModel
|
||||
queryModel := `{"target": "aliasByNode(statsd.fakesite.counters.session_start.mobile.count, 4)"}`
|
||||
|
||||
@ -29,13 +30,13 @@ func TestQueryInterval(t *testing.T) {
|
||||
verifier := func(query plugins.DataSubQuery) {
|
||||
// 5minutes timerange = 300000milliseconds; default-resolution is 1500pixels,
|
||||
// so we should have 300000/1500 = 200milliseconds here
|
||||
So(query.IntervalMS, ShouldEqual, 200)
|
||||
So(query.MaxDataPoints, ShouldEqual, interval.DefaultRes)
|
||||
require.Equal(t, int64(200), query.IntervalMS)
|
||||
require.Equal(t, interval.DefaultRes, query.MaxDataPoints)
|
||||
}
|
||||
|
||||
applyScenario(timeRange, dataSourceJson, queryModel, verifier)
|
||||
applyScenario(t, timeRange, dataSourceJson, queryModel, verifier)
|
||||
})
|
||||
Convey("Can handle interval-calculation with panel-min-interval and no datasource-min-interval", func() {
|
||||
t.Run("Can handle interval-calculation with panel-min-interval and no datasource-min-interval", func(t *testing.T) {
|
||||
// panel-min-interval in the queryModel
|
||||
queryModel := `{"interval":"123s", "target": "aliasByNode(statsd.fakesite.counters.session_start.mobile.count, 4)"}`
|
||||
|
||||
@ -45,13 +46,13 @@ func TestQueryInterval(t *testing.T) {
|
||||
timeRange := "5m"
|
||||
|
||||
verifier := func(query plugins.DataSubQuery) {
|
||||
So(query.IntervalMS, ShouldEqual, 123000)
|
||||
So(query.MaxDataPoints, ShouldEqual, interval.DefaultRes)
|
||||
require.Equal(t, int64(123000), query.IntervalMS)
|
||||
require.Equal(t, interval.DefaultRes, query.MaxDataPoints)
|
||||
}
|
||||
|
||||
applyScenario(timeRange, dataSourceJson, queryModel, verifier)
|
||||
applyScenario(t, timeRange, dataSourceJson, queryModel, verifier)
|
||||
})
|
||||
Convey("Can handle interval-calculation with no panel-min-interval and datasource-min-interval", func() {
|
||||
t.Run("Can handle interval-calculation with no panel-min-interval and datasource-min-interval", func(t *testing.T) {
|
||||
// no panel-min-interval in the queryModel
|
||||
queryModel := `{"target": "aliasByNode(statsd.fakesite.counters.session_start.mobile.count, 4)"}`
|
||||
|
||||
@ -59,18 +60,18 @@ func TestQueryInterval(t *testing.T) {
|
||||
dataSourceJson, err := simplejson.NewJson([]byte(`{
|
||||
"timeInterval": "71s"
|
||||
}`))
|
||||
So(err, ShouldBeNil)
|
||||
require.Nil(t, err)
|
||||
|
||||
timeRange := "5m"
|
||||
|
||||
verifier := func(query plugins.DataSubQuery) {
|
||||
So(query.IntervalMS, ShouldEqual, 71000)
|
||||
So(query.MaxDataPoints, ShouldEqual, interval.DefaultRes)
|
||||
require.Equal(t, int64(71000), query.IntervalMS)
|
||||
require.Equal(t, interval.DefaultRes, query.MaxDataPoints)
|
||||
}
|
||||
|
||||
applyScenario(timeRange, dataSourceJson, queryModel, verifier)
|
||||
applyScenario(t, timeRange, dataSourceJson, queryModel, verifier)
|
||||
})
|
||||
Convey("Can handle interval-calculation with both panel-min-interval and datasource-min-interval", func() {
|
||||
t.Run("Can handle interval-calculation with both panel-min-interval and datasource-min-interval", func(t *testing.T) {
|
||||
// panel-min-interval in the queryModel
|
||||
queryModel := `{"interval":"19s", "target": "aliasByNode(statsd.fakesite.counters.session_start.mobile.count, 4)"}`
|
||||
|
||||
@ -78,21 +79,21 @@ func TestQueryInterval(t *testing.T) {
|
||||
dataSourceJson, err := simplejson.NewJson([]byte(`{
|
||||
"timeInterval": "71s"
|
||||
}`))
|
||||
So(err, ShouldBeNil)
|
||||
require.Nil(t, err)
|
||||
|
||||
timeRange := "5m"
|
||||
|
||||
verifier := func(query plugins.DataSubQuery) {
|
||||
// when both panel-min-interval and datasource-min-interval exists,
|
||||
// panel-min-interval is used
|
||||
So(query.IntervalMS, ShouldEqual, 19000)
|
||||
So(query.MaxDataPoints, ShouldEqual, interval.DefaultRes)
|
||||
require.Equal(t, int64(19000), query.IntervalMS)
|
||||
require.Equal(t, interval.DefaultRes, query.MaxDataPoints)
|
||||
}
|
||||
|
||||
applyScenario(timeRange, dataSourceJson, queryModel, verifier)
|
||||
applyScenario(t, timeRange, dataSourceJson, queryModel, verifier)
|
||||
})
|
||||
|
||||
Convey("Can handle no min-interval, and very small time-ranges, where the default-min-interval=1ms applies", func() {
|
||||
t.Run("Can handle no min-interval, and very small time-ranges, where the default-min-interval=1ms applies", func(t *testing.T) {
|
||||
// no panel-min-interval in the queryModel
|
||||
queryModel := `{"target": "aliasByNode(statsd.fakesite.counters.session_start.mobile.count, 4)"}`
|
||||
|
||||
@ -104,11 +105,11 @@ func TestQueryInterval(t *testing.T) {
|
||||
verifier := func(query plugins.DataSubQuery) {
|
||||
// no min-interval exists, the default-min-interval will be used,
|
||||
// and for such a short time-range this will cause the value to be 1millisecond.
|
||||
So(query.IntervalMS, ShouldEqual, 1)
|
||||
So(query.MaxDataPoints, ShouldEqual, interval.DefaultRes)
|
||||
require.Equal(t, int64(1), query.IntervalMS)
|
||||
require.Equal(t, interval.DefaultRes, query.MaxDataPoints)
|
||||
}
|
||||
|
||||
applyScenario(timeRange, dataSourceJson, queryModel, verifier)
|
||||
applyScenario(t, timeRange, dataSourceJson, queryModel, verifier)
|
||||
})
|
||||
})
|
||||
}
|
||||
@ -135,8 +136,8 @@ func (rh fakeIntervalTestReqHandler) HandleRequest(ctx context.Context, dsInfo *
|
||||
}
|
||||
|
||||
//nolint: staticcheck // plugins.DataResponse deprecated
|
||||
func applyScenario(timeRange string, dataSourceJsonData *simplejson.Json, queryModel string, verifier func(query plugins.DataSubQuery)) {
|
||||
Convey("desc", func() {
|
||||
func applyScenario(t *testing.T, timeRange string, dataSourceJsonData *simplejson.Json, queryModel string, verifier func(query plugins.DataSubQuery)) {
|
||||
t.Run("desc", func(t *testing.T) {
|
||||
bus.AddHandlerCtx("test", func(ctx context.Context, query *models.GetDataSourceQuery) error {
|
||||
query.Result = &models.DataSource{Id: 1, Type: "graphite", JsonData: dataSourceJsonData}
|
||||
return nil
|
||||
@ -159,10 +160,10 @@ func applyScenario(timeRange string, dataSourceJsonData *simplejson.Json, queryM
|
||||
"reducer":{"type": "avg"},
|
||||
"evaluator":{"type": "gt", "params": [100]}
|
||||
}`))
|
||||
So(err, ShouldBeNil)
|
||||
require.Nil(t, err)
|
||||
|
||||
condition, err := newQueryCondition(jsonModel, 0)
|
||||
So(err, ShouldBeNil)
|
||||
require.Nil(t, err)
|
||||
|
||||
ctx.condition = condition
|
||||
|
||||
@ -179,6 +180,6 @@ func applyScenario(timeRange string, dataSourceJsonData *simplejson.Json, queryM
|
||||
|
||||
_, err = condition.Eval(ctx.result, reqHandler)
|
||||
|
||||
So(err, ShouldBeNil)
|
||||
require.Nil(t, err)
|
||||
})
|
||||
}
|
||||
|
@ -17,7 +17,7 @@ import (
|
||||
"github.com/grafana/grafana/pkg/models"
|
||||
"github.com/grafana/grafana/pkg/plugins"
|
||||
"github.com/grafana/grafana/pkg/services/alerting"
|
||||
. "github.com/smartystreets/goconvey/convey"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
"github.com/xorcare/pointer"
|
||||
)
|
||||
@ -33,147 +33,165 @@ func newTimeSeriesPointsFromArgs(values ...float64) plugins.DataTimeSeriesPoints
|
||||
}
|
||||
|
||||
func TestQueryCondition(t *testing.T) {
|
||||
Convey("when evaluating query condition", t, func() {
|
||||
queryConditionScenario("Given avg() and > 100", func(ctx *queryConditionTestContext) {
|
||||
ctx.reducer = `{"type": "avg"}`
|
||||
ctx.evaluator = `{"type": "gt", "params": [100]}`
|
||||
setup := func() *queryConditionTestContext {
|
||||
ctx := &queryConditionTestContext{}
|
||||
bus.AddHandlerCtx("test", func(ctx context.Context, query *models.GetDataSourceQuery) error {
|
||||
query.Result = &models.DataSource{Id: 1, Type: "graphite"}
|
||||
return nil
|
||||
})
|
||||
|
||||
Convey("Can read query condition from json model", func() {
|
||||
_, err := ctx.exec()
|
||||
So(err, ShouldBeNil)
|
||||
ctx.reducer = `{"type":"avg"}`
|
||||
ctx.evaluator = `{"type":"gt","params":[100]}`
|
||||
ctx.result = &alerting.EvalContext{
|
||||
Ctx: context.Background(),
|
||||
Rule: &alerting.Rule{},
|
||||
RequestValidator: &validations.OSSPluginRequestValidator{},
|
||||
}
|
||||
return ctx
|
||||
}
|
||||
|
||||
So(ctx.condition.Query.From, ShouldEqual, "5m")
|
||||
So(ctx.condition.Query.To, ShouldEqual, "now")
|
||||
So(ctx.condition.Query.DatasourceID, ShouldEqual, 1)
|
||||
t.Run("Can read query condition from json model", func(t *testing.T) {
|
||||
ctx := setup()
|
||||
_, err := ctx.exec(t)
|
||||
require.Nil(t, err)
|
||||
|
||||
Convey("Can read query reducer", func() {
|
||||
reducer := ctx.condition.Reducer
|
||||
So(reducer.Type, ShouldEqual, "avg")
|
||||
})
|
||||
require.Equal(t, "5m", ctx.condition.Query.From)
|
||||
require.Equal(t, "now", ctx.condition.Query.To)
|
||||
require.Equal(t, int64(1), ctx.condition.Query.DatasourceID)
|
||||
|
||||
Convey("Can read evaluator", func() {
|
||||
evaluator, ok := ctx.condition.Evaluator.(*thresholdEvaluator)
|
||||
So(ok, ShouldBeTrue)
|
||||
So(evaluator.Type, ShouldEqual, "gt")
|
||||
})
|
||||
})
|
||||
t.Run("Can read query reducer", func(t *testing.T) {
|
||||
reducer := ctx.condition.Reducer
|
||||
require.Equal(t, "avg", reducer.Type)
|
||||
})
|
||||
|
||||
Convey("should fire when avg is above 100", func() {
|
||||
points := newTimeSeriesPointsFromArgs(120, 0)
|
||||
ctx.series = plugins.DataTimeSeriesSlice{plugins.DataTimeSeries{Name: "test1", Points: points}}
|
||||
cr, err := ctx.exec()
|
||||
t.Run("Can read evaluator", func(t *testing.T) {
|
||||
evaluator, ok := ctx.condition.Evaluator.(*thresholdEvaluator)
|
||||
require.True(t, ok)
|
||||
require.Equal(t, "gt", evaluator.Type)
|
||||
})
|
||||
})
|
||||
|
||||
So(err, ShouldBeNil)
|
||||
So(cr.Firing, ShouldBeTrue)
|
||||
})
|
||||
t.Run("should fire when avg is above 100", func(t *testing.T) {
|
||||
ctx := setup()
|
||||
points := newTimeSeriesPointsFromArgs(120, 0)
|
||||
ctx.series = plugins.DataTimeSeriesSlice{plugins.DataTimeSeries{Name: "test1", Points: points}}
|
||||
cr, err := ctx.exec(t)
|
||||
|
||||
Convey("should fire when avg is above 100 on dataframe", func() {
|
||||
ctx.frame = data.NewFrame("",
|
||||
data.NewField("time", nil, []time.Time{time.Now(), time.Now()}),
|
||||
data.NewField("val", nil, []int64{120, 150}),
|
||||
)
|
||||
cr, err := ctx.exec()
|
||||
require.Nil(t, err)
|
||||
require.True(t, cr.Firing)
|
||||
})
|
||||
|
||||
So(err, ShouldBeNil)
|
||||
So(cr.Firing, ShouldBeTrue)
|
||||
})
|
||||
t.Run("should fire when avg is above 100 on dataframe", func(t *testing.T) {
|
||||
ctx := setup()
|
||||
ctx.frame = data.NewFrame("",
|
||||
data.NewField("time", nil, []time.Time{time.Now(), time.Now()}),
|
||||
data.NewField("val", nil, []int64{120, 150}),
|
||||
)
|
||||
cr, err := ctx.exec(t)
|
||||
|
||||
Convey("Should not fire when avg is below 100", func() {
|
||||
points := newTimeSeriesPointsFromArgs(90, 0)
|
||||
ctx.series = plugins.DataTimeSeriesSlice{plugins.DataTimeSeries{Name: "test1", Points: points}}
|
||||
cr, err := ctx.exec()
|
||||
require.Nil(t, err)
|
||||
require.True(t, cr.Firing)
|
||||
})
|
||||
|
||||
So(err, ShouldBeNil)
|
||||
So(cr.Firing, ShouldBeFalse)
|
||||
})
|
||||
t.Run("Should not fire when avg is below 100", func(t *testing.T) {
|
||||
ctx := setup()
|
||||
points := newTimeSeriesPointsFromArgs(90, 0)
|
||||
ctx.series = plugins.DataTimeSeriesSlice{plugins.DataTimeSeries{Name: "test1", Points: points}}
|
||||
cr, err := ctx.exec(t)
|
||||
|
||||
Convey("Should not fire when avg is below 100 on dataframe", func() {
|
||||
ctx.frame = data.NewFrame("",
|
||||
data.NewField("time", nil, []time.Time{time.Now(), time.Now()}),
|
||||
data.NewField("val", nil, []int64{12, 47}),
|
||||
)
|
||||
cr, err := ctx.exec()
|
||||
require.Nil(t, err)
|
||||
require.False(t, cr.Firing)
|
||||
})
|
||||
|
||||
So(err, ShouldBeNil)
|
||||
So(cr.Firing, ShouldBeFalse)
|
||||
})
|
||||
t.Run("Should not fire when avg is below 100 on dataframe", func(t *testing.T) {
|
||||
ctx := setup()
|
||||
ctx.frame = data.NewFrame("",
|
||||
data.NewField("time", nil, []time.Time{time.Now(), time.Now()}),
|
||||
data.NewField("val", nil, []int64{12, 47}),
|
||||
)
|
||||
cr, err := ctx.exec(t)
|
||||
|
||||
Convey("Should fire if only first series matches", func() {
|
||||
ctx.series = plugins.DataTimeSeriesSlice{
|
||||
plugins.DataTimeSeries{Name: "test1", Points: newTimeSeriesPointsFromArgs(120, 0)},
|
||||
plugins.DataTimeSeries{Name: "test2", Points: newTimeSeriesPointsFromArgs(0, 0)},
|
||||
}
|
||||
cr, err := ctx.exec()
|
||||
require.Nil(t, err)
|
||||
require.False(t, cr.Firing)
|
||||
})
|
||||
|
||||
So(err, ShouldBeNil)
|
||||
So(cr.Firing, ShouldBeTrue)
|
||||
})
|
||||
t.Run("Should fire if only first series matches", func(t *testing.T) {
|
||||
ctx := setup()
|
||||
ctx.series = plugins.DataTimeSeriesSlice{
|
||||
plugins.DataTimeSeries{Name: "test1", Points: newTimeSeriesPointsFromArgs(120, 0)},
|
||||
plugins.DataTimeSeries{Name: "test2", Points: newTimeSeriesPointsFromArgs(0, 0)},
|
||||
}
|
||||
cr, err := ctx.exec(t)
|
||||
|
||||
Convey("No series", func() {
|
||||
Convey("Should set NoDataFound when condition is gt", func() {
|
||||
ctx.series = plugins.DataTimeSeriesSlice{}
|
||||
cr, err := ctx.exec()
|
||||
require.Nil(t, err)
|
||||
require.True(t, cr.Firing)
|
||||
})
|
||||
|
||||
So(err, ShouldBeNil)
|
||||
So(cr.Firing, ShouldBeFalse)
|
||||
So(cr.NoDataFound, ShouldBeTrue)
|
||||
})
|
||||
t.Run("No series", func(t *testing.T) {
|
||||
ctx := setup()
|
||||
t.Run("Should set NoDataFound when condition is gt", func(t *testing.T) {
|
||||
ctx.series = plugins.DataTimeSeriesSlice{}
|
||||
cr, err := ctx.exec(t)
|
||||
|
||||
Convey("Should be firing when condition is no_value", func() {
|
||||
ctx.evaluator = `{"type": "no_value", "params": []}`
|
||||
ctx.series = plugins.DataTimeSeriesSlice{}
|
||||
cr, err := ctx.exec()
|
||||
require.Nil(t, err)
|
||||
require.False(t, cr.Firing)
|
||||
require.True(t, cr.NoDataFound)
|
||||
})
|
||||
|
||||
So(err, ShouldBeNil)
|
||||
So(cr.Firing, ShouldBeTrue)
|
||||
})
|
||||
})
|
||||
t.Run("Should be firing when condition is no_value", func(t *testing.T) {
|
||||
ctx.evaluator = `{"type": "no_value", "params": []}`
|
||||
ctx.series = plugins.DataTimeSeriesSlice{}
|
||||
cr, err := ctx.exec(t)
|
||||
|
||||
Convey("Empty series", func() {
|
||||
Convey("Should set Firing if eval match", func() {
|
||||
ctx.evaluator = `{"type": "no_value", "params": []}`
|
||||
ctx.series = plugins.DataTimeSeriesSlice{
|
||||
plugins.DataTimeSeries{Name: "test1", Points: newTimeSeriesPointsFromArgs()},
|
||||
}
|
||||
cr, err := ctx.exec()
|
||||
require.Nil(t, err)
|
||||
require.True(t, cr.Firing)
|
||||
})
|
||||
})
|
||||
|
||||
So(err, ShouldBeNil)
|
||||
So(cr.Firing, ShouldBeTrue)
|
||||
})
|
||||
t.Run("Empty series", func(t *testing.T) {
|
||||
ctx := setup()
|
||||
t.Run("Should set Firing if eval match", func(t *testing.T) {
|
||||
ctx.evaluator = `{"type": "no_value", "params": []}`
|
||||
ctx.series = plugins.DataTimeSeriesSlice{
|
||||
plugins.DataTimeSeries{Name: "test1", Points: newTimeSeriesPointsFromArgs()},
|
||||
}
|
||||
cr, err := ctx.exec(t)
|
||||
|
||||
Convey("Should set NoDataFound both series are empty", func() {
|
||||
ctx.series = plugins.DataTimeSeriesSlice{
|
||||
plugins.DataTimeSeries{Name: "test1", Points: newTimeSeriesPointsFromArgs()},
|
||||
plugins.DataTimeSeries{Name: "test2", Points: newTimeSeriesPointsFromArgs()},
|
||||
}
|
||||
cr, err := ctx.exec()
|
||||
require.Nil(t, err)
|
||||
require.True(t, cr.Firing)
|
||||
})
|
||||
|
||||
So(err, ShouldBeNil)
|
||||
So(cr.NoDataFound, ShouldBeTrue)
|
||||
})
|
||||
t.Run("Should set NoDataFound both series are empty", func(t *testing.T) {
|
||||
ctx.series = plugins.DataTimeSeriesSlice{
|
||||
plugins.DataTimeSeries{Name: "test1", Points: newTimeSeriesPointsFromArgs()},
|
||||
plugins.DataTimeSeries{Name: "test2", Points: newTimeSeriesPointsFromArgs()},
|
||||
}
|
||||
cr, err := ctx.exec(t)
|
||||
|
||||
Convey("Should set NoDataFound both series contains null", func() {
|
||||
ctx.series = plugins.DataTimeSeriesSlice{
|
||||
plugins.DataTimeSeries{Name: "test1", Points: plugins.DataTimeSeriesPoints{plugins.DataTimePoint{null.FloatFromPtr(nil), null.FloatFrom(0)}}},
|
||||
plugins.DataTimeSeries{Name: "test2", Points: plugins.DataTimeSeriesPoints{plugins.DataTimePoint{null.FloatFromPtr(nil), null.FloatFrom(0)}}},
|
||||
}
|
||||
cr, err := ctx.exec()
|
||||
require.Nil(t, err)
|
||||
require.True(t, cr.NoDataFound)
|
||||
})
|
||||
|
||||
So(err, ShouldBeNil)
|
||||
So(cr.NoDataFound, ShouldBeTrue)
|
||||
})
|
||||
t.Run("Should set NoDataFound both series contains null", func(t *testing.T) {
|
||||
ctx.series = plugins.DataTimeSeriesSlice{
|
||||
plugins.DataTimeSeries{Name: "test1", Points: plugins.DataTimeSeriesPoints{plugins.DataTimePoint{null.FloatFromPtr(nil), null.FloatFrom(0)}}},
|
||||
plugins.DataTimeSeries{Name: "test2", Points: plugins.DataTimeSeriesPoints{plugins.DataTimePoint{null.FloatFromPtr(nil), null.FloatFrom(0)}}},
|
||||
}
|
||||
cr, err := ctx.exec(t)
|
||||
|
||||
Convey("Should not set NoDataFound if one series is empty", func() {
|
||||
ctx.series = plugins.DataTimeSeriesSlice{
|
||||
plugins.DataTimeSeries{Name: "test1", Points: newTimeSeriesPointsFromArgs()},
|
||||
plugins.DataTimeSeries{Name: "test2", Points: newTimeSeriesPointsFromArgs(120, 0)},
|
||||
}
|
||||
cr, err := ctx.exec()
|
||||
require.Nil(t, err)
|
||||
require.True(t, cr.NoDataFound)
|
||||
})
|
||||
|
||||
So(err, ShouldBeNil)
|
||||
So(cr.NoDataFound, ShouldBeFalse)
|
||||
})
|
||||
})
|
||||
t.Run("Should not set NoDataFound if one series is empty", func(t *testing.T) {
|
||||
ctx.series = plugins.DataTimeSeriesSlice{
|
||||
plugins.DataTimeSeries{Name: "test1", Points: newTimeSeriesPointsFromArgs()},
|
||||
plugins.DataTimeSeries{Name: "test2", Points: newTimeSeriesPointsFromArgs(120, 0)},
|
||||
}
|
||||
cr, err := ctx.exec(t)
|
||||
|
||||
require.Nil(t, err)
|
||||
require.False(t, cr.NoDataFound)
|
||||
})
|
||||
})
|
||||
}
|
||||
@ -187,10 +205,8 @@ type queryConditionTestContext struct {
|
||||
condition *QueryCondition
|
||||
}
|
||||
|
||||
type queryConditionScenarioFunc func(c *queryConditionTestContext)
|
||||
|
||||
//nolint: staticcheck // plugins.DataPlugin deprecated
|
||||
func (ctx *queryConditionTestContext) exec() (*alerting.ConditionResult, error) {
|
||||
func (ctx *queryConditionTestContext) exec(t *testing.T) (*alerting.ConditionResult, error) {
|
||||
jsonModel, err := simplejson.NewJson([]byte(`{
|
||||
"type": "query",
|
||||
"query": {
|
||||
@ -201,10 +217,10 @@ func (ctx *queryConditionTestContext) exec() (*alerting.ConditionResult, error)
|
||||
"reducer":` + ctx.reducer + `,
|
||||
"evaluator":` + ctx.evaluator + `
|
||||
}`))
|
||||
So(err, ShouldBeNil)
|
||||
require.Nil(t, err)
|
||||
|
||||
condition, err := newQueryCondition(jsonModel, 0)
|
||||
So(err, ShouldBeNil)
|
||||
require.Nil(t, err)
|
||||
|
||||
ctx.condition = condition
|
||||
|
||||
@ -239,24 +255,6 @@ func (rh fakeReqHandler) HandleRequest(context.Context, *models.DataSource, plug
|
||||
return rh.response, nil
|
||||
}
|
||||
|
||||
func queryConditionScenario(desc string, fn queryConditionScenarioFunc) {
|
||||
Convey(desc, func() {
|
||||
bus.AddHandlerCtx("test", func(ctx context.Context, query *models.GetDataSourceQuery) error {
|
||||
query.Result = &models.DataSource{Id: 1, Type: "graphite"}
|
||||
return nil
|
||||
})
|
||||
|
||||
ctx := &queryConditionTestContext{}
|
||||
ctx.result = &alerting.EvalContext{
|
||||
Ctx: context.Background(),
|
||||
Rule: &alerting.Rule{},
|
||||
RequestValidator: &validations.OSSPluginRequestValidator{},
|
||||
}
|
||||
|
||||
fn(ctx)
|
||||
})
|
||||
}
|
||||
|
||||
func TestFrameToSeriesSlice(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
|
@ -4,183 +4,103 @@ import (
|
||||
"math"
|
||||
"testing"
|
||||
|
||||
. "github.com/smartystreets/goconvey/convey"
|
||||
|
||||
"github.com/grafana/grafana/pkg/components/null"
|
||||
"github.com/grafana/grafana/pkg/plugins"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestSimpleReducer(t *testing.T) {
|
||||
Convey("Test simple reducer by calculating", t, func() {
|
||||
Convey("sum", func() {
|
||||
result := testReducer("sum", 1, 2, 3)
|
||||
So(result, ShouldEqual, float64(6))
|
||||
})
|
||||
t.Run("sum", func(t *testing.T) {
|
||||
result := testReducer("sum", 1, 2, 3)
|
||||
require.Equal(t, float64(6), result)
|
||||
})
|
||||
|
||||
Convey("min", func() {
|
||||
result := testReducer("min", 3, 2, 1)
|
||||
So(result, ShouldEqual, float64(1))
|
||||
})
|
||||
t.Run("min", func(t *testing.T) {
|
||||
result := testReducer("min", 3, 2, 1)
|
||||
require.Equal(t, float64(1), result)
|
||||
})
|
||||
|
||||
Convey("max", func() {
|
||||
result := testReducer("max", 1, 2, 3)
|
||||
So(result, ShouldEqual, float64(3))
|
||||
})
|
||||
t.Run("max", func(t *testing.T) {
|
||||
result := testReducer("max", 1, 2, 3)
|
||||
require.Equal(t, float64(3), result)
|
||||
})
|
||||
|
||||
Convey("count", func() {
|
||||
result := testReducer("count", 1, 2, 3000)
|
||||
So(result, ShouldEqual, float64(3))
|
||||
})
|
||||
t.Run("count", func(t *testing.T) {
|
||||
result := testReducer("count", 1, 2, 3000)
|
||||
require.Equal(t, float64(3), result)
|
||||
})
|
||||
|
||||
Convey("last", func() {
|
||||
result := testReducer("last", 1, 2, 3000)
|
||||
So(result, ShouldEqual, float64(3000))
|
||||
})
|
||||
t.Run("last", func(t *testing.T) {
|
||||
result := testReducer("last", 1, 2, 3000)
|
||||
require.Equal(t, float64(3000), result)
|
||||
})
|
||||
|
||||
Convey("median odd amount of numbers", func() {
|
||||
result := testReducer("median", 1, 2, 3000)
|
||||
So(result, ShouldEqual, float64(2))
|
||||
})
|
||||
t.Run("median odd amount of numbers", func(t *testing.T) {
|
||||
result := testReducer("median", 1, 2, 3000)
|
||||
require.Equal(t, float64(2), result)
|
||||
})
|
||||
|
||||
Convey("median even amount of numbers", func() {
|
||||
result := testReducer("median", 1, 2, 4, 3000)
|
||||
So(result, ShouldEqual, float64(3))
|
||||
})
|
||||
t.Run("median even amount of numbers", func(t *testing.T) {
|
||||
result := testReducer("median", 1, 2, 4, 3000)
|
||||
require.Equal(t, float64(3), result)
|
||||
})
|
||||
|
||||
Convey("median with one values", func() {
|
||||
result := testReducer("median", 1)
|
||||
So(result, ShouldEqual, float64(1))
|
||||
})
|
||||
t.Run("median with one values", func(t *testing.T) {
|
||||
result := testReducer("median", 1)
|
||||
require.Equal(t, float64(1), result)
|
||||
})
|
||||
|
||||
Convey("median should ignore null values", func() {
|
||||
reducer := newSimpleReducer("median")
|
||||
t.Run("median should ignore null values", func(t *testing.T) {
|
||||
reducer := newSimpleReducer("median")
|
||||
series := plugins.DataTimeSeries{
|
||||
Name: "test time series",
|
||||
}
|
||||
|
||||
series.Points = append(series.Points, plugins.DataTimePoint{null.FloatFromPtr(nil), null.FloatFrom(1)})
|
||||
series.Points = append(series.Points, plugins.DataTimePoint{null.FloatFromPtr(nil), null.FloatFrom(2)})
|
||||
series.Points = append(series.Points, plugins.DataTimePoint{null.FloatFromPtr(nil), null.FloatFrom(3)})
|
||||
series.Points = append(series.Points, plugins.DataTimePoint{null.FloatFrom(float64(1)), null.FloatFrom(4)})
|
||||
series.Points = append(series.Points, plugins.DataTimePoint{null.FloatFrom(float64(2)), null.FloatFrom(5)})
|
||||
series.Points = append(series.Points, plugins.DataTimePoint{null.FloatFrom(float64(3)), null.FloatFrom(6)})
|
||||
|
||||
result := reducer.Reduce(series)
|
||||
require.Equal(t, true, result.Valid)
|
||||
require.Equal(t, float64(2), result.Float64)
|
||||
})
|
||||
|
||||
t.Run("avg", func(t *testing.T) {
|
||||
result := testReducer("avg", 1, 2, 3)
|
||||
require.Equal(t, float64(2), result)
|
||||
})
|
||||
|
||||
t.Run("avg with only nulls", func(t *testing.T) {
|
||||
reducer := newSimpleReducer("avg")
|
||||
series := plugins.DataTimeSeries{
|
||||
Name: "test time series",
|
||||
}
|
||||
|
||||
series.Points = append(series.Points, plugins.DataTimePoint{null.FloatFromPtr(nil), null.FloatFrom(1)})
|
||||
require.Equal(t, false, reducer.Reduce(series).Valid)
|
||||
})
|
||||
|
||||
t.Run("count_non_null", func(t *testing.T) {
|
||||
t.Run("with null values and real values", func(t *testing.T) {
|
||||
reducer := newSimpleReducer("count_non_null")
|
||||
series := plugins.DataTimeSeries{
|
||||
Name: "test time series",
|
||||
}
|
||||
|
||||
series.Points = append(series.Points, plugins.DataTimePoint{null.FloatFromPtr(nil), null.FloatFrom(1)})
|
||||
series.Points = append(series.Points, plugins.DataTimePoint{null.FloatFromPtr(nil), null.FloatFrom(2)})
|
||||
series.Points = append(series.Points, plugins.DataTimePoint{null.FloatFromPtr(nil), null.FloatFrom(3)})
|
||||
series.Points = append(series.Points, plugins.DataTimePoint{null.FloatFrom(float64(1)), null.FloatFrom(4)})
|
||||
series.Points = append(series.Points, plugins.DataTimePoint{null.FloatFrom(float64(2)), null.FloatFrom(5)})
|
||||
series.Points = append(series.Points, plugins.DataTimePoint{null.FloatFrom(float64(3)), null.FloatFrom(6)})
|
||||
|
||||
result := reducer.Reduce(series)
|
||||
So(result.Valid, ShouldEqual, true)
|
||||
So(result.Float64, ShouldEqual, float64(2))
|
||||
})
|
||||
|
||||
Convey("avg", func() {
|
||||
result := testReducer("avg", 1, 2, 3)
|
||||
So(result, ShouldEqual, float64(2))
|
||||
})
|
||||
|
||||
Convey("avg with only nulls", func() {
|
||||
reducer := newSimpleReducer("avg")
|
||||
series := plugins.DataTimeSeries{
|
||||
Name: "test time series",
|
||||
}
|
||||
|
||||
series.Points = append(series.Points, plugins.DataTimePoint{null.FloatFromPtr(nil), null.FloatFrom(1)})
|
||||
So(reducer.Reduce(series).Valid, ShouldEqual, false)
|
||||
})
|
||||
|
||||
Convey("count_non_null", func() {
|
||||
Convey("with null values and real values", func() {
|
||||
reducer := newSimpleReducer("count_non_null")
|
||||
series := plugins.DataTimeSeries{
|
||||
Name: "test time series",
|
||||
}
|
||||
|
||||
series.Points = append(series.Points, plugins.DataTimePoint{null.FloatFromPtr(nil), null.FloatFrom(1)})
|
||||
series.Points = append(series.Points, plugins.DataTimePoint{null.FloatFromPtr(nil), null.FloatFrom(2)})
|
||||
series.Points = append(series.Points, plugins.DataTimePoint{null.FloatFrom(3), null.FloatFrom(3)})
|
||||
series.Points = append(series.Points, plugins.DataTimePoint{null.FloatFrom(3), null.FloatFrom(4)})
|
||||
|
||||
So(reducer.Reduce(series).Valid, ShouldEqual, true)
|
||||
So(reducer.Reduce(series).Float64, ShouldEqual, 2)
|
||||
})
|
||||
|
||||
Convey("with null values", func() {
|
||||
reducer := newSimpleReducer("count_non_null")
|
||||
series := plugins.DataTimeSeries{
|
||||
Name: "test time series",
|
||||
}
|
||||
|
||||
series.Points = append(series.Points, plugins.DataTimePoint{null.FloatFromPtr(nil), null.FloatFrom(1)})
|
||||
series.Points = append(series.Points, plugins.DataTimePoint{null.FloatFromPtr(nil), null.FloatFrom(2)})
|
||||
|
||||
So(reducer.Reduce(series).Valid, ShouldEqual, false)
|
||||
})
|
||||
})
|
||||
|
||||
Convey("avg of number values and null values should ignore nulls", func() {
|
||||
reducer := newSimpleReducer("avg")
|
||||
series := plugins.DataTimeSeries{
|
||||
Name: "test time series",
|
||||
}
|
||||
|
||||
series.Points = append(series.Points, plugins.DataTimePoint{null.FloatFrom(3), null.FloatFrom(1)})
|
||||
series.Points = append(series.Points, plugins.DataTimePoint{null.FloatFromPtr(nil), null.FloatFrom(2)})
|
||||
series.Points = append(series.Points, plugins.DataTimePoint{null.FloatFromPtr(nil), null.FloatFrom(3)})
|
||||
series.Points = append(series.Points, plugins.DataTimePoint{null.FloatFrom(3), null.FloatFrom(3)})
|
||||
series.Points = append(series.Points, plugins.DataTimePoint{null.FloatFrom(3), null.FloatFrom(4)})
|
||||
|
||||
So(reducer.Reduce(series).Float64, ShouldEqual, float64(3))
|
||||
require.Equal(t, true, reducer.Reduce(series).Valid)
|
||||
require.Equal(t, 2.0, reducer.Reduce(series).Float64)
|
||||
})
|
||||
|
||||
// diff function Test Suite
|
||||
Convey("diff of one positive point", func() {
|
||||
result := testReducer("diff", 30)
|
||||
So(result, ShouldEqual, float64(0))
|
||||
})
|
||||
|
||||
Convey("diff of one negative point", func() {
|
||||
result := testReducer("diff", -30)
|
||||
So(result, ShouldEqual, float64(0))
|
||||
})
|
||||
|
||||
Convey("diff of two positive points[1]", func() {
|
||||
result := testReducer("diff", 30, 40)
|
||||
So(result, ShouldEqual, float64(10))
|
||||
})
|
||||
|
||||
Convey("diff of two positive points[2]", func() {
|
||||
result := testReducer("diff", 30, 20)
|
||||
So(result, ShouldEqual, float64(-10))
|
||||
})
|
||||
|
||||
Convey("diff of two negative points[1]", func() {
|
||||
result := testReducer("diff", -30, -40)
|
||||
So(result, ShouldEqual, float64(-10))
|
||||
})
|
||||
|
||||
Convey("diff of two negative points[2]", func() {
|
||||
result := testReducer("diff", -30, -10)
|
||||
So(result, ShouldEqual, float64(20))
|
||||
})
|
||||
|
||||
Convey("diff of one positive and one negative point", func() {
|
||||
result := testReducer("diff", 30, -40)
|
||||
So(result, ShouldEqual, float64(-70))
|
||||
})
|
||||
|
||||
Convey("diff of one negative and one positive point", func() {
|
||||
result := testReducer("diff", -30, 40)
|
||||
So(result, ShouldEqual, float64(70))
|
||||
})
|
||||
|
||||
Convey("diff of three positive points", func() {
|
||||
result := testReducer("diff", 30, 40, 50)
|
||||
So(result, ShouldEqual, float64(20))
|
||||
})
|
||||
|
||||
Convey("diff of three negative points", func() {
|
||||
result := testReducer("diff", -30, -40, -50)
|
||||
So(result, ShouldEqual, float64(-20))
|
||||
})
|
||||
|
||||
Convey("diff with only nulls", func() {
|
||||
reducer := newSimpleReducer("diff")
|
||||
t.Run("with null values", func(t *testing.T) {
|
||||
reducer := newSimpleReducer("count_non_null")
|
||||
series := plugins.DataTimeSeries{
|
||||
Name: "test time series",
|
||||
}
|
||||
@ -188,212 +108,289 @@ func TestSimpleReducer(t *testing.T) {
|
||||
series.Points = append(series.Points, plugins.DataTimePoint{null.FloatFromPtr(nil), null.FloatFrom(1)})
|
||||
series.Points = append(series.Points, plugins.DataTimePoint{null.FloatFromPtr(nil), null.FloatFrom(2)})
|
||||
|
||||
So(reducer.Reduce(series).Valid, ShouldEqual, false)
|
||||
require.Equal(t, false, reducer.Reduce(series).Valid)
|
||||
})
|
||||
})
|
||||
|
||||
// diff_abs function Test Suite
|
||||
Convey("diff_abs of one positive point", func() {
|
||||
result := testReducer("diff_abs", 30)
|
||||
So(result, ShouldEqual, float64(0))
|
||||
})
|
||||
t.Run("avg of number values and null values should ignore nulls", func(t *testing.T) {
|
||||
reducer := newSimpleReducer("avg")
|
||||
series := plugins.DataTimeSeries{
|
||||
Name: "test time series",
|
||||
}
|
||||
|
||||
Convey("diff_abs of one negative point", func() {
|
||||
result := testReducer("diff_abs", -30)
|
||||
So(result, ShouldEqual, float64(0))
|
||||
})
|
||||
series.Points = append(series.Points, plugins.DataTimePoint{null.FloatFrom(3), null.FloatFrom(1)})
|
||||
series.Points = append(series.Points, plugins.DataTimePoint{null.FloatFromPtr(nil), null.FloatFrom(2)})
|
||||
series.Points = append(series.Points, plugins.DataTimePoint{null.FloatFromPtr(nil), null.FloatFrom(3)})
|
||||
series.Points = append(series.Points, plugins.DataTimePoint{null.FloatFrom(3), null.FloatFrom(4)})
|
||||
|
||||
Convey("diff_abs of two positive points[1]", func() {
|
||||
result := testReducer("diff_abs", 30, 40)
|
||||
So(result, ShouldEqual, float64(10))
|
||||
})
|
||||
require.Equal(t, float64(3), reducer.Reduce(series).Float64)
|
||||
})
|
||||
|
||||
Convey("diff_abs of two positive points[2]", func() {
|
||||
result := testReducer("diff_abs", 30, 20)
|
||||
So(result, ShouldEqual, float64(10))
|
||||
})
|
||||
// diff function Test Suite
|
||||
t.Run("diff of one positive point", func(t *testing.T) {
|
||||
result := testReducer("diff", 30)
|
||||
require.Equal(t, float64(0), result)
|
||||
})
|
||||
|
||||
Convey("diff_abs of two negative points[1]", func() {
|
||||
result := testReducer("diff_abs", -30, -40)
|
||||
So(result, ShouldEqual, float64(10))
|
||||
})
|
||||
t.Run("diff of one negative point", func(t *testing.T) {
|
||||
result := testReducer("diff", -30)
|
||||
require.Equal(t, float64(0), result)
|
||||
})
|
||||
|
||||
Convey("diff_abs of two negative points[2]", func() {
|
||||
result := testReducer("diff_abs", -30, -10)
|
||||
So(result, ShouldEqual, float64(20))
|
||||
})
|
||||
t.Run("diff of two positive points[1]", func(t *testing.T) {
|
||||
result := testReducer("diff", 30, 40)
|
||||
require.Equal(t, float64(10), result)
|
||||
})
|
||||
|
||||
Convey("diff_abs of one positive and one negative point", func() {
|
||||
result := testReducer("diff_abs", 30, -40)
|
||||
So(result, ShouldEqual, float64(70))
|
||||
})
|
||||
t.Run("diff of two positive points[2]", func(t *testing.T) {
|
||||
result := testReducer("diff", 30, 20)
|
||||
require.Equal(t, float64(-10), result)
|
||||
})
|
||||
|
||||
Convey("diff_abs of one negative and one positive point", func() {
|
||||
result := testReducer("diff_abs", -30, 40)
|
||||
So(result, ShouldEqual, float64(70))
|
||||
})
|
||||
t.Run("diff of two negative points[1]", func(t *testing.T) {
|
||||
result := testReducer("diff", -30, -40)
|
||||
require.Equal(t, float64(-10), result)
|
||||
})
|
||||
|
||||
Convey("diff_abs of three positive points", func() {
|
||||
result := testReducer("diff_abs", 30, 40, 50)
|
||||
So(result, ShouldEqual, float64(20))
|
||||
})
|
||||
t.Run("diff of two negative points[2]", func(t *testing.T) {
|
||||
result := testReducer("diff", -30, -10)
|
||||
require.Equal(t, float64(20), result)
|
||||
})
|
||||
|
||||
Convey("diff_abs of three negative points", func() {
|
||||
result := testReducer("diff_abs", -30, -40, -50)
|
||||
So(result, ShouldEqual, float64(20))
|
||||
})
|
||||
t.Run("diff of one positive and one negative point", func(t *testing.T) {
|
||||
result := testReducer("diff", 30, -40)
|
||||
require.Equal(t, float64(-70), result)
|
||||
})
|
||||
|
||||
Convey("diff_abs with only nulls", func() {
|
||||
reducer := newSimpleReducer("diff_abs")
|
||||
series := plugins.DataTimeSeries{
|
||||
Name: "test time series",
|
||||
}
|
||||
t.Run("diff of one negative and one positive point", func(t *testing.T) {
|
||||
result := testReducer("diff", -30, 40)
|
||||
require.Equal(t, float64(70), result)
|
||||
})
|
||||
|
||||
series.Points = append(series.Points, plugins.DataTimePoint{null.FloatFromPtr(nil), null.FloatFrom(1)})
|
||||
series.Points = append(series.Points, plugins.DataTimePoint{null.FloatFromPtr(nil), null.FloatFrom(2)})
|
||||
t.Run("diff of three positive points", func(t *testing.T) {
|
||||
result := testReducer("diff", 30, 40, 50)
|
||||
require.Equal(t, float64(20), result)
|
||||
})
|
||||
|
||||
So(reducer.Reduce(series).Valid, ShouldEqual, false)
|
||||
})
|
||||
t.Run("diff of three negative points", func(t *testing.T) {
|
||||
result := testReducer("diff", -30, -40, -50)
|
||||
require.Equal(t, float64(-20), result)
|
||||
})
|
||||
|
||||
// percent_diff function Test Suite
|
||||
Convey("percent_diff of one positive point", func() {
|
||||
result := testReducer("percent_diff", 30)
|
||||
So(result, ShouldEqual, float64(0))
|
||||
})
|
||||
t.Run("diff with only nulls", func(t *testing.T) {
|
||||
reducer := newSimpleReducer("diff")
|
||||
series := plugins.DataTimeSeries{
|
||||
Name: "test time series",
|
||||
}
|
||||
|
||||
Convey("percent_diff of one negative point", func() {
|
||||
result := testReducer("percent_diff", -30)
|
||||
So(result, ShouldEqual, float64(0))
|
||||
})
|
||||
series.Points = append(series.Points, plugins.DataTimePoint{null.FloatFromPtr(nil), null.FloatFrom(1)})
|
||||
series.Points = append(series.Points, plugins.DataTimePoint{null.FloatFromPtr(nil), null.FloatFrom(2)})
|
||||
|
||||
Convey("percent_diff of two positive points[1]", func() {
|
||||
result := testReducer("percent_diff", 30, 40)
|
||||
So(result, ShouldEqual, float64(33.33333333333333))
|
||||
})
|
||||
require.Equal(t, false, reducer.Reduce(series).Valid)
|
||||
})
|
||||
|
||||
Convey("percent_diff of two positive points[2]", func() {
|
||||
result := testReducer("percent_diff", 30, 20)
|
||||
So(result, ShouldEqual, float64(-33.33333333333333))
|
||||
})
|
||||
// diff_abs function Test Suite
|
||||
t.Run("diff_abs of one positive point", func(t *testing.T) {
|
||||
result := testReducer("diff_abs", 30)
|
||||
require.Equal(t, float64(0), result)
|
||||
})
|
||||
|
||||
Convey("percent_diff of two negative points[1]", func() {
|
||||
result := testReducer("percent_diff", -30, -40)
|
||||
So(result, ShouldEqual, float64(-33.33333333333333))
|
||||
})
|
||||
t.Run("diff_abs of one negative point", func(t *testing.T) {
|
||||
result := testReducer("diff_abs", -30)
|
||||
require.Equal(t, float64(0), result)
|
||||
})
|
||||
|
||||
Convey("percent_diff of two negative points[2]", func() {
|
||||
result := testReducer("percent_diff", -30, -10)
|
||||
So(result, ShouldEqual, float64(66.66666666666666))
|
||||
})
|
||||
t.Run("diff_abs of two positive points[1]", func(t *testing.T) {
|
||||
result := testReducer("diff_abs", 30, 40)
|
||||
require.Equal(t, float64(10), result)
|
||||
})
|
||||
|
||||
Convey("percent_diff of one positive and one negative point", func() {
|
||||
result := testReducer("percent_diff", 30, -40)
|
||||
So(result, ShouldEqual, float64(-233.33333333333334))
|
||||
})
|
||||
t.Run("diff_abs of two positive points[2]", func(t *testing.T) {
|
||||
result := testReducer("diff_abs", 30, 20)
|
||||
require.Equal(t, float64(10), result)
|
||||
})
|
||||
|
||||
Convey("percent_diff of one negative and one positive point", func() {
|
||||
result := testReducer("percent_diff", -30, 40)
|
||||
So(result, ShouldEqual, float64(233.33333333333334))
|
||||
})
|
||||
t.Run("diff_abs of two negative points[1]", func(t *testing.T) {
|
||||
result := testReducer("diff_abs", -30, -40)
|
||||
require.Equal(t, float64(10), result)
|
||||
})
|
||||
|
||||
Convey("percent_diff of three positive points", func() {
|
||||
result := testReducer("percent_diff", 30, 40, 50)
|
||||
So(result, ShouldEqual, float64(66.66666666666666))
|
||||
})
|
||||
t.Run("diff_abs of two negative points[2]", func(t *testing.T) {
|
||||
result := testReducer("diff_abs", -30, -10)
|
||||
require.Equal(t, float64(20), result)
|
||||
})
|
||||
|
||||
Convey("percent_diff of three negative points", func() {
|
||||
result := testReducer("percent_diff", -30, -40, -50)
|
||||
So(result, ShouldEqual, float64(-66.66666666666666))
|
||||
})
|
||||
t.Run("diff_abs of one positive and one negative point", func(t *testing.T) {
|
||||
result := testReducer("diff_abs", 30, -40)
|
||||
require.Equal(t, float64(70), result)
|
||||
})
|
||||
|
||||
Convey("percent_diff with only nulls", func() {
|
||||
reducer := newSimpleReducer("percent_diff")
|
||||
series := plugins.DataTimeSeries{
|
||||
Name: "test time series",
|
||||
}
|
||||
t.Run("diff_abs of one negative and one positive point", func(t *testing.T) {
|
||||
result := testReducer("diff_abs", -30, 40)
|
||||
require.Equal(t, float64(70), result)
|
||||
})
|
||||
|
||||
series.Points = append(series.Points, plugins.DataTimePoint{null.FloatFromPtr(nil), null.FloatFrom(1)})
|
||||
series.Points = append(series.Points, plugins.DataTimePoint{null.FloatFromPtr(nil), null.FloatFrom(2)})
|
||||
t.Run("diff_abs of three positive points", func(t *testing.T) {
|
||||
result := testReducer("diff_abs", 30, 40, 50)
|
||||
require.Equal(t, float64(20), result)
|
||||
})
|
||||
|
||||
So(reducer.Reduce(series).Valid, ShouldEqual, false)
|
||||
})
|
||||
t.Run("diff_abs of three negative points", func(t *testing.T) {
|
||||
result := testReducer("diff_abs", -30, -40, -50)
|
||||
require.Equal(t, float64(20), result)
|
||||
})
|
||||
|
||||
// percent_diff_abs function Test Suite
|
||||
Convey("percent_diff_abs_abs of one positive point", func() {
|
||||
result := testReducer("percent_diff_abs", 30)
|
||||
So(result, ShouldEqual, float64(0))
|
||||
})
|
||||
t.Run("diff_abs with only nulls", func(t *testing.T) {
|
||||
reducer := newSimpleReducer("diff_abs")
|
||||
series := plugins.DataTimeSeries{
|
||||
Name: "test time series",
|
||||
}
|
||||
|
||||
Convey("percent_diff_abs of one negative point", func() {
|
||||
result := testReducer("percent_diff_abs", -30)
|
||||
So(result, ShouldEqual, float64(0))
|
||||
})
|
||||
series.Points = append(series.Points, plugins.DataTimePoint{null.FloatFromPtr(nil), null.FloatFrom(1)})
|
||||
series.Points = append(series.Points, plugins.DataTimePoint{null.FloatFromPtr(nil), null.FloatFrom(2)})
|
||||
|
||||
Convey("percent_diff_abs of two positive points[1]", func() {
|
||||
result := testReducer("percent_diff_abs", 30, 40)
|
||||
So(result, ShouldEqual, float64(33.33333333333333))
|
||||
})
|
||||
require.Equal(t, false, reducer.Reduce(series).Valid)
|
||||
})
|
||||
|
||||
Convey("percent_diff_abs of two positive points[2]", func() {
|
||||
result := testReducer("percent_diff_abs", 30, 20)
|
||||
So(result, ShouldEqual, float64(33.33333333333333))
|
||||
})
|
||||
// percent_diff function Test Suite
|
||||
t.Run("percent_diff of one positive point", func(t *testing.T) {
|
||||
result := testReducer("percent_diff", 30)
|
||||
require.Equal(t, float64(0), result)
|
||||
})
|
||||
|
||||
Convey("percent_diff_abs of two negative points[1]", func() {
|
||||
result := testReducer("percent_diff_abs", -30, -40)
|
||||
So(result, ShouldEqual, float64(33.33333333333333))
|
||||
})
|
||||
t.Run("percent_diff of one negative point", func(t *testing.T) {
|
||||
result := testReducer("percent_diff", -30)
|
||||
require.Equal(t, float64(0), result)
|
||||
})
|
||||
|
||||
Convey("percent_diff_abs of two negative points[2]", func() {
|
||||
result := testReducer("percent_diff_abs", -30, -10)
|
||||
So(result, ShouldEqual, float64(66.66666666666666))
|
||||
})
|
||||
t.Run("percent_diff of two positive points[1]", func(t *testing.T) {
|
||||
result := testReducer("percent_diff", 30, 40)
|
||||
require.Equal(t, float64(33.33333333333333), result)
|
||||
})
|
||||
|
||||
Convey("percent_diff_abs of one positive and one negative point", func() {
|
||||
result := testReducer("percent_diff_abs", 30, -40)
|
||||
So(result, ShouldEqual, float64(233.33333333333334))
|
||||
})
|
||||
t.Run("percent_diff of two positive points[2]", func(t *testing.T) {
|
||||
result := testReducer("percent_diff", 30, 20)
|
||||
require.Equal(t, float64(-33.33333333333333), result)
|
||||
})
|
||||
|
||||
Convey("percent_diff_abs of one negative and one positive point", func() {
|
||||
result := testReducer("percent_diff_abs", -30, 40)
|
||||
So(result, ShouldEqual, float64(233.33333333333334))
|
||||
})
|
||||
t.Run("percent_diff of two negative points[1]", func(t *testing.T) {
|
||||
result := testReducer("percent_diff", -30, -40)
|
||||
require.Equal(t, float64(-33.33333333333333), result)
|
||||
})
|
||||
|
||||
Convey("percent_diff_abs of three positive points", func() {
|
||||
result := testReducer("percent_diff_abs", 30, 40, 50)
|
||||
So(result, ShouldEqual, float64(66.66666666666666))
|
||||
})
|
||||
t.Run("percent_diff of two negative points[2]", func(t *testing.T) {
|
||||
result := testReducer("percent_diff", -30, -10)
|
||||
require.Equal(t, float64(66.66666666666666), result)
|
||||
})
|
||||
|
||||
Convey("percent_diff_abs of three negative points", func() {
|
||||
result := testReducer("percent_diff_abs", -30, -40, -50)
|
||||
So(result, ShouldEqual, float64(66.66666666666666))
|
||||
})
|
||||
t.Run("percent_diff of one positive and one negative point", func(t *testing.T) {
|
||||
result := testReducer("percent_diff", 30, -40)
|
||||
require.Equal(t, float64(-233.33333333333334), result)
|
||||
})
|
||||
|
||||
Convey("percent_diff_abs with only nulls", func() {
|
||||
reducer := newSimpleReducer("percent_diff_abs")
|
||||
series := plugins.DataTimeSeries{
|
||||
Name: "test time series",
|
||||
}
|
||||
t.Run("percent_diff of one negative and one positive point", func(t *testing.T) {
|
||||
result := testReducer("percent_diff", -30, 40)
|
||||
require.Equal(t, float64(233.33333333333334), result)
|
||||
})
|
||||
|
||||
series.Points = append(series.Points, plugins.DataTimePoint{null.FloatFromPtr(nil), null.FloatFrom(1)})
|
||||
series.Points = append(series.Points, plugins.DataTimePoint{null.FloatFromPtr(nil), null.FloatFrom(2)})
|
||||
t.Run("percent_diff of three positive points", func(t *testing.T) {
|
||||
result := testReducer("percent_diff", 30, 40, 50)
|
||||
require.Equal(t, float64(66.66666666666666), result)
|
||||
})
|
||||
|
||||
So(reducer.Reduce(series).Valid, ShouldEqual, false)
|
||||
})
|
||||
t.Run("percent_diff of three negative points", func(t *testing.T) {
|
||||
result := testReducer("percent_diff", -30, -40, -50)
|
||||
require.Equal(t, float64(-66.66666666666666), result)
|
||||
})
|
||||
|
||||
Convey("min should work with NaNs", func() {
|
||||
result := testReducer("min", math.NaN(), math.NaN(), math.NaN())
|
||||
So(result, ShouldEqual, float64(0))
|
||||
})
|
||||
t.Run("percent_diff with only nulls", func(t *testing.T) {
|
||||
reducer := newSimpleReducer("percent_diff")
|
||||
series := plugins.DataTimeSeries{
|
||||
Name: "test time series",
|
||||
}
|
||||
|
||||
Convey("isValid should treat NaN as invalid", func() {
|
||||
result := isValid(null.FloatFrom(math.NaN()))
|
||||
So(result, ShouldBeFalse)
|
||||
})
|
||||
series.Points = append(series.Points, plugins.DataTimePoint{null.FloatFromPtr(nil), null.FloatFrom(1)})
|
||||
series.Points = append(series.Points, plugins.DataTimePoint{null.FloatFromPtr(nil), null.FloatFrom(2)})
|
||||
|
||||
Convey("isValid should treat invalid null.Float as invalid", func() {
|
||||
result := isValid(null.FloatFromPtr(nil))
|
||||
So(result, ShouldBeFalse)
|
||||
})
|
||||
require.Equal(t, false, reducer.Reduce(series).Valid)
|
||||
})
|
||||
|
||||
// percent_diff_abs function Test Suite
|
||||
t.Run("percent_diff_abs_abs of one positive point", func(t *testing.T) {
|
||||
result := testReducer("percent_diff_abs", 30)
|
||||
require.Equal(t, float64(0), result)
|
||||
})
|
||||
|
||||
t.Run("percent_diff_abs of one negative point", func(t *testing.T) {
|
||||
result := testReducer("percent_diff_abs", -30)
|
||||
require.Equal(t, float64(0), result)
|
||||
})
|
||||
|
||||
t.Run("percent_diff_abs of two positive points[1]", func(t *testing.T) {
|
||||
result := testReducer("percent_diff_abs", 30, 40)
|
||||
require.Equal(t, float64(33.33333333333333), result)
|
||||
})
|
||||
|
||||
t.Run("percent_diff_abs of two positive points[2]", func(t *testing.T) {
|
||||
result := testReducer("percent_diff_abs", 30, 20)
|
||||
require.Equal(t, float64(33.33333333333333), result)
|
||||
})
|
||||
|
||||
t.Run("percent_diff_abs of two negative points[1]", func(t *testing.T) {
|
||||
result := testReducer("percent_diff_abs", -30, -40)
|
||||
require.Equal(t, float64(33.33333333333333), result)
|
||||
})
|
||||
|
||||
t.Run("percent_diff_abs of two negative points[2]", func(t *testing.T) {
|
||||
result := testReducer("percent_diff_abs", -30, -10)
|
||||
require.Equal(t, float64(66.66666666666666), result)
|
||||
})
|
||||
|
||||
t.Run("percent_diff_abs of one positive and one negative point", func(t *testing.T) {
|
||||
result := testReducer("percent_diff_abs", 30, -40)
|
||||
require.Equal(t, float64(233.33333333333334), result)
|
||||
})
|
||||
|
||||
t.Run("percent_diff_abs of one negative and one positive point", func(t *testing.T) {
|
||||
result := testReducer("percent_diff_abs", -30, 40)
|
||||
require.Equal(t, float64(233.33333333333334), result)
|
||||
})
|
||||
|
||||
t.Run("percent_diff_abs of three positive points", func(t *testing.T) {
|
||||
result := testReducer("percent_diff_abs", 30, 40, 50)
|
||||
require.Equal(t, float64(66.66666666666666), result)
|
||||
})
|
||||
|
||||
t.Run("percent_diff_abs of three negative points", func(t *testing.T) {
|
||||
result := testReducer("percent_diff_abs", -30, -40, -50)
|
||||
require.Equal(t, float64(66.66666666666666), result)
|
||||
})
|
||||
|
||||
t.Run("percent_diff_abs with only nulls", func(t *testing.T) {
|
||||
reducer := newSimpleReducer("percent_diff_abs")
|
||||
series := plugins.DataTimeSeries{
|
||||
Name: "test time series",
|
||||
}
|
||||
|
||||
series.Points = append(series.Points, plugins.DataTimePoint{null.FloatFromPtr(nil), null.FloatFrom(1)})
|
||||
series.Points = append(series.Points, plugins.DataTimePoint{null.FloatFromPtr(nil), null.FloatFrom(2)})
|
||||
|
||||
require.Equal(t, false, reducer.Reduce(series).Valid)
|
||||
})
|
||||
|
||||
t.Run("min should work with NaNs", func(t *testing.T) {
|
||||
result := testReducer("min", math.NaN(), math.NaN(), math.NaN())
|
||||
require.Equal(t, float64(0), result)
|
||||
})
|
||||
|
||||
t.Run("isValid should treat NaN as invalid", func(t *testing.T) {
|
||||
result := isValid(null.FloatFrom(math.NaN()))
|
||||
require.False(t, result)
|
||||
})
|
||||
|
||||
t.Run("isValid should treat invalid null.Float as invalid", func(t *testing.T) {
|
||||
result := isValid(null.FloatFromPtr(nil))
|
||||
require.False(t, result)
|
||||
})
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user