grafana/pkg/expr/threshold_test.go
Yuriy Tseretyan 2d20c8db7b
Chore: Expression engine to support relative time range (#57474)
* make TimeRange interface and add relative range
* make Execute methods support the current time
* update resample to support relative time range
* update DSNode to support relative time range
* update query service to create queries with absolute time
* make alerting evaluator create relative time ranges
2022-10-26 16:13:58 -04:00

212 lines
4.3 KiB
Go

package expr
import (
"encoding/json"
"testing"
"github.com/stretchr/testify/require"
)
func TestNewThresholdCommand(t *testing.T) {
cmd, err := NewThresholdCommand("B", "A", "is_above", []float64{})
require.Nil(t, err)
require.NotNil(t, cmd)
}
func TestUnmarshalThresholdCommand(t *testing.T) {
type testCase struct {
description string
query string
shouldError bool
expectedError string
}
cases := []testCase{
{
description: "unmarshal proper object",
query: `{
"expression" : "A",
"type": "threshold",
"conditions": [{
"evaluator": {
"type": "gt",
"params": [20, 80]
}
}]
}`,
shouldError: false,
},
{
description: "unmarshal with missing conditions should error",
query: `{
"expression" : "A",
"type": "threshold",
"conditions": []
}`,
shouldError: true,
expectedError: "requires exactly one condition",
},
{
description: "unmarshal with missing conditions should error",
query: `{
"expression" : "A",
"type": "threshold",
"conditions": []
}`,
shouldError: true,
expectedError: "requires exactly one condition",
},
{
description: "unmarshal with unsupported threshold function",
query: `{
"expression" : "A",
"type": "threshold",
"conditions": [{
"evaluator": {
"type": "foo",
"params": [20, 80]
}
}]
}`,
shouldError: true,
expectedError: "expected threshold function to be one of",
},
{
description: "unmarshal with bad expression",
query: `{
"expression" : 0,
"type": "threshold",
"conditions": []
}`,
shouldError: true,
expectedError: "expected threshold variable to be a string",
},
}
for _, tc := range cases {
q := []byte(tc.query)
var qmap = make(map[string]interface{})
require.NoError(t, json.Unmarshal(q, &qmap))
cmd, err := UnmarshalThresholdCommand(&rawNode{
RefID: "",
Query: qmap,
QueryType: "",
DataSource: nil,
})
if tc.shouldError {
require.Nil(t, cmd)
require.NotNil(t, err)
require.Contains(t, err.Error(), tc.expectedError)
} else {
require.Nil(t, err)
require.NotNil(t, cmd)
}
}
}
func TestThresholdCommandVars(t *testing.T) {
cmd, err := NewThresholdCommand("B", "A", "is_above", []float64{})
require.Nil(t, err)
require.Equal(t, cmd.NeedsVars(), []string{"A"})
}
func TestCreateMathExpression(t *testing.T) {
type testCase struct {
description string
expected string
ref string
function string
params []float64
}
cases := []testCase{
{
description: "is above",
ref: "My Ref",
function: "gt",
params: []float64{0},
expected: "${My Ref} > 0.000000",
},
{
description: "is below",
ref: "A",
function: "lt",
params: []float64{0},
expected: "${A} < 0.000000",
},
{
description: "is within",
ref: "B",
function: "within_range",
params: []float64{20, 80},
expected: "${B} > 20.000000 && ${B} < 80.000000",
},
{
description: "is outside",
ref: "B",
function: "outside_range",
params: []float64{20, 80},
expected: "${B} < 20.000000 || ${B} > 80.000000",
},
}
for _, tc := range cases {
t.Run(tc.description, func(t *testing.T) {
expr, err := createMathExpression(tc.ref, tc.function, tc.params)
require.Nil(t, err)
require.NotNil(t, expr)
require.Equal(t, expr, tc.expected)
})
}
t.Run("should error if function is unsupported", func(t *testing.T) {
expr, err := createMathExpression("A", "foo", []float64{0})
require.Equal(t, expr, "")
require.NotNil(t, err)
require.Contains(t, err.Error(), "no such threshold function")
})
}
func TestIsSupportedThresholdFunc(t *testing.T) {
type testCase struct {
function string
supported bool
}
cases := []testCase{
{
function: ThresholdIsAbove,
supported: true,
},
{
function: ThresholdIsBelow,
supported: true,
},
{
function: ThresholdIsWithinRange,
supported: true,
},
{
function: ThresholdIsOutsideRange,
supported: true,
},
{
function: "foo",
supported: false,
},
}
for _, tc := range cases {
t.Run(tc.function, func(t *testing.T) {
supported := IsSupportedThresholdFunc(tc.function)
require.Equal(t, supported, tc.supported)
})
}
}