mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
This is a translation of services/alerting/conditions. Main Changes: - Work with types in SSE (series/number) which are data frames (no more null.Float). - The query part from alerting/conditions is handled by SSE logic - Convey / simplejson removed. - Time range no longer part of "query" in the condition
200 lines
4.0 KiB
Go
200 lines
4.0 KiB
Go
package classic
|
|
|
|
import (
|
|
"context"
|
|
"encoding/json"
|
|
"testing"
|
|
|
|
"github.com/grafana/grafana/pkg/expr/mathexp"
|
|
"github.com/stretchr/testify/require"
|
|
ptr "github.com/xorcare/pointer"
|
|
)
|
|
|
|
func TestUnmarshalConditionCMD(t *testing.T) {
|
|
var tests = []struct {
|
|
name string
|
|
rawJSON string
|
|
expectedCommand *ConditionsCmd
|
|
needsVars []string
|
|
}{
|
|
{
|
|
name: "basic threshold condition",
|
|
rawJSON: `{
|
|
"conditions": [
|
|
{
|
|
"evaluator": {
|
|
"params": [
|
|
2
|
|
],
|
|
"type": "gt"
|
|
},
|
|
"operator": {
|
|
"type": "and"
|
|
},
|
|
"query": {
|
|
"params": [
|
|
"A"
|
|
]
|
|
},
|
|
"reducer": {
|
|
"params": [],
|
|
"type": "avg"
|
|
},
|
|
"type": "query"
|
|
}
|
|
]
|
|
}`,
|
|
expectedCommand: &ConditionsCmd{
|
|
Conditions: []condition{
|
|
{
|
|
QueryRefID: "A",
|
|
Reducer: classicReducer("avg"),
|
|
Operator: "and",
|
|
Evaluator: &thresholdEvaluator{Type: "gt", Threshold: 2},
|
|
},
|
|
},
|
|
},
|
|
needsVars: []string{"A"},
|
|
},
|
|
{
|
|
name: "ranged condition",
|
|
rawJSON: `{
|
|
"conditions": [
|
|
{
|
|
"evaluator": {
|
|
"params": [
|
|
2,
|
|
3
|
|
],
|
|
"type": "within_range"
|
|
},
|
|
"operator": {
|
|
"type": "or"
|
|
},
|
|
"query": {
|
|
"params": [
|
|
"A"
|
|
]
|
|
},
|
|
"reducer": {
|
|
"params": [],
|
|
"type": "diff"
|
|
},
|
|
"type": "query"
|
|
}
|
|
]
|
|
}`,
|
|
expectedCommand: &ConditionsCmd{
|
|
Conditions: []condition{
|
|
{
|
|
QueryRefID: "A",
|
|
Reducer: classicReducer("diff"),
|
|
Operator: "or",
|
|
Evaluator: &rangedEvaluator{Type: "within_range", Lower: 2, Upper: 3},
|
|
},
|
|
},
|
|
},
|
|
needsVars: []string{"A"},
|
|
},
|
|
}
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
var rq map[string]interface{}
|
|
|
|
err := json.Unmarshal([]byte(tt.rawJSON), &rq)
|
|
require.NoError(t, err)
|
|
|
|
cmd, err := UnmarshalConditionsCmd(rq, "")
|
|
require.NoError(t, err)
|
|
require.Equal(t, tt.expectedCommand, cmd)
|
|
|
|
require.Equal(t, tt.needsVars, cmd.NeedsVars())
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestConditionsCmdExecute(t *testing.T) {
|
|
trueNumber := valBasedNumber(ptr.Float64(1))
|
|
falseNumber := valBasedNumber(ptr.Float64(0))
|
|
noDataNumber := valBasedNumber(nil)
|
|
|
|
tests := []struct {
|
|
name string
|
|
vars mathexp.Vars
|
|
conditionsCmd *ConditionsCmd
|
|
resultNumber mathexp.Number
|
|
}{
|
|
{
|
|
name: "single query and single condition",
|
|
vars: mathexp.Vars{
|
|
"A": mathexp.Results{
|
|
Values: []mathexp.Value{
|
|
valBasedSeries(ptr.Float64(30), ptr.Float64(40)),
|
|
},
|
|
},
|
|
},
|
|
conditionsCmd: &ConditionsCmd{
|
|
Conditions: []condition{
|
|
{
|
|
QueryRefID: "A",
|
|
Reducer: classicReducer("avg"),
|
|
Operator: "and",
|
|
Evaluator: &thresholdEvaluator{Type: "gt", Threshold: 34},
|
|
},
|
|
}},
|
|
resultNumber: trueNumber,
|
|
},
|
|
{
|
|
name: "single query and single ranged condition",
|
|
vars: mathexp.Vars{
|
|
"A": mathexp.Results{
|
|
Values: []mathexp.Value{
|
|
valBasedSeries(ptr.Float64(30), ptr.Float64(40)),
|
|
},
|
|
},
|
|
},
|
|
conditionsCmd: &ConditionsCmd{
|
|
Conditions: []condition{
|
|
{
|
|
QueryRefID: "A",
|
|
Reducer: classicReducer("diff"),
|
|
Operator: "and",
|
|
Evaluator: &rangedEvaluator{Type: "within_range", Lower: 2, Upper: 3},
|
|
},
|
|
},
|
|
},
|
|
resultNumber: falseNumber,
|
|
},
|
|
{
|
|
name: "single query with no data",
|
|
vars: mathexp.Vars{
|
|
"A": mathexp.Results{
|
|
Values: []mathexp.Value{},
|
|
},
|
|
},
|
|
conditionsCmd: &ConditionsCmd{
|
|
Conditions: []condition{
|
|
{
|
|
QueryRefID: "A",
|
|
Reducer: classicReducer("avg"),
|
|
Operator: "and",
|
|
Evaluator: &thresholdEvaluator{"gt", 1},
|
|
},
|
|
},
|
|
},
|
|
resultNumber: noDataNumber,
|
|
},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
res, err := tt.conditionsCmd.Execute(context.Background(), tt.vars)
|
|
require.NoError(t, err)
|
|
|
|
require.Equal(t, 1, len(res.Values))
|
|
|
|
require.Equal(t, tt.resultNumber, res.Values[0])
|
|
})
|
|
}
|
|
}
|