grafana/pkg/expr/classic/classic_test.go
Kyle Brandt a488ab8393
SSE: Add "Classic Condition" on backend (#31511)
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
2021-03-02 13:51:33 -05:00

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])
})
}
}