grafana/pkg/services/alerting/conditions/query_interval_test.go
Sofia Papagiannaki 988a120d6d
Search v1: Add support for inherited folder permissions if nested folders are enabled (#63275)
* Add features dependency to SQLBuilder

* Add features dependency to AccessControlDashboardPermissionFilter

* Add test for folder inheritance

* Dashboard permissions: Return recursive query

* Recursive query for inherited folders

* Modify search builder

* Adjust db.SQLBuilder

* Pass flag to SQLbuilder if CTEs are supported

* Add support for mysql < 8.0

* Add benchmarking for search with nested folders

* Set features to AlertStore

* Update pkg/infra/db/sqlbuilder.go

Co-authored-by: Ieva <ieva.vasiljeva@grafana.com>

* Set features to LibraryElementService

* SQLBuilder tests with nested folder flag set

* Apply suggestion from code review

Co-authored-by: IevaVasiljeva <ieva.vasiljeva@grafana.com>
Co-authored-by: Emil Tullstedt <emil.tullstedt@grafana.com>
2023-04-06 11:16:15 +03:00

192 lines
6.6 KiB
Go

package conditions
import (
"context"
"testing"
"github.com/stretchr/testify/require"
"github.com/grafana/grafana/pkg/components/simplejson"
"github.com/grafana/grafana/pkg/infra/db/dbtest"
"github.com/grafana/grafana/pkg/infra/localcache"
"github.com/grafana/grafana/pkg/services/alerting"
"github.com/grafana/grafana/pkg/services/datasources"
fd "github.com/grafana/grafana/pkg/services/datasources/fakes"
"github.com/grafana/grafana/pkg/services/featuremgmt"
"github.com/grafana/grafana/pkg/services/validations"
"github.com/grafana/grafana/pkg/setting"
"github.com/grafana/grafana/pkg/tsdb/intervalv2"
"github.com/grafana/grafana/pkg/tsdb/legacydata"
)
func TestQueryInterval(t *testing.T) {
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)"}`
// no datasource-min-interval
var dataSourceJson *simplejson.Json = nil
timeRange := "5m"
verifier := func(query legacydata.DataSubQuery) {
// 5minutes timerange = 300000milliseconds; default-resolution is 1500pixels,
// so we should have 300000/1500 = 200milliseconds here
require.Equal(t, int64(200), query.IntervalMS)
require.Equal(t, intervalv2.DefaultRes, query.MaxDataPoints)
}
applyScenario(t, timeRange, dataSourceJson, queryModel, verifier)
})
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)"}`
// no datasource-min-interval
var dataSourceJson *simplejson.Json = nil
timeRange := "5m"
verifier := func(query legacydata.DataSubQuery) {
require.Equal(t, int64(123000), query.IntervalMS)
require.Equal(t, intervalv2.DefaultRes, query.MaxDataPoints)
}
applyScenario(t, timeRange, dataSourceJson, queryModel, verifier)
})
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)"}`
// min-interval in datasource-json
dataSourceJson, err := simplejson.NewJson([]byte(`{
"timeInterval": "71s"
}`))
require.Nil(t, err)
timeRange := "5m"
verifier := func(query legacydata.DataSubQuery) {
require.Equal(t, int64(71000), query.IntervalMS)
require.Equal(t, intervalv2.DefaultRes, query.MaxDataPoints)
}
applyScenario(t, timeRange, dataSourceJson, queryModel, verifier)
})
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)"}`
// min-interval in datasource-json
dataSourceJson, err := simplejson.NewJson([]byte(`{
"timeInterval": "71s"
}`))
require.Nil(t, err)
timeRange := "5m"
verifier := func(query legacydata.DataSubQuery) {
// when both panel-min-interval and datasource-min-interval exists,
// panel-min-interval is used
require.Equal(t, int64(19000), query.IntervalMS)
require.Equal(t, intervalv2.DefaultRes, query.MaxDataPoints)
}
applyScenario(t, timeRange, dataSourceJson, queryModel, verifier)
})
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)"}`
// no datasource-min-interval
var dataSourceJson *simplejson.Json = nil
timeRange := "1s"
verifier := func(query legacydata.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.
require.Equal(t, int64(1), query.IntervalMS)
require.Equal(t, intervalv2.DefaultRes, query.MaxDataPoints)
}
applyScenario(t, timeRange, dataSourceJson, queryModel, verifier)
})
})
}
type queryIntervalTestContext struct {
result *alerting.EvalContext
condition *QueryCondition
}
type queryIntervalVerifier func(query legacydata.DataSubQuery)
type fakeIntervalTestReqHandler struct {
//nolint: staticcheck // legacydata.DataResponse deprecated
response legacydata.DataResponse
verifier queryIntervalVerifier
}
//nolint:staticcheck // legacydata.DataResponse deprecated
func (rh fakeIntervalTestReqHandler) HandleRequest(ctx context.Context, dsInfo *datasources.DataSource, query legacydata.DataQuery) (
legacydata.DataResponse, error) {
q := query.Queries[0]
rh.verifier(q)
return rh.response, nil
}
//nolint:staticcheck // legacydata.DataResponse deprecated
func applyScenario(t *testing.T, timeRange string, dataSourceJsonData *simplejson.Json, queryModel string, verifier func(query legacydata.DataSubQuery)) {
t.Run("desc", func(t *testing.T) {
db := dbtest.NewFakeDB()
store := alerting.ProvideAlertStore(db, localcache.ProvideService(), &setting.Cfg{}, nil, featuremgmt.WithFeatures())
ctx := &queryIntervalTestContext{}
ctx.result = &alerting.EvalContext{
Ctx: context.Background(),
Rule: &alerting.Rule{},
RequestValidator: &validations.OSSPluginRequestValidator{},
Store: store,
DatasourceService: &fd.FakeDataSourceService{
DataSources: []*datasources.DataSource{
{ID: 1, Type: datasources.DS_GRAPHITE, JsonData: dataSourceJsonData},
},
},
}
jsonModel, err := simplejson.NewJson([]byte(`{
"type": "query",
"query": {
"params": ["A", "` + timeRange + `", "now"],
"datasourceId": 1,
"model": ` + queryModel + `
},
"reducer":{"type": "avg"},
"evaluator":{"type": "gt", "params": [100]}
}`))
require.Nil(t, err)
condition, err := newQueryCondition(jsonModel, 0)
require.Nil(t, err)
ctx.condition = condition
qr := legacydata.DataQueryResult{}
reqHandler := fakeIntervalTestReqHandler{
response: legacydata.DataResponse{
Results: map[string]legacydata.DataQueryResult{
"A": qr,
},
},
verifier: verifier,
}
_, err = condition.Eval(ctx.result, reqHandler)
require.Nil(t, err)
})
}