Alerting: Improve test coverage for ConditionsCmd (#58603)

This commit is contained in:
George Robinson 2022-11-11 09:27:35 +00:00 committed by GitHub
parent c090de9ed9
commit bd87b46b15
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 514 additions and 330 deletions

View File

@ -6,10 +6,10 @@ import (
"testing" "testing"
"time" "time"
"github.com/grafana/grafana-plugin-sdk-go/data"
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
ptr "github.com/xorcare/pointer" ptr "github.com/xorcare/pointer"
"github.com/grafana/grafana-plugin-sdk-go/data"
"github.com/grafana/grafana/pkg/expr/mathexp" "github.com/grafana/grafana/pkg/expr/mathexp"
) )
@ -20,181 +20,61 @@ func TestConditionsCmd(t *testing.T) {
vars mathexp.Vars vars mathexp.Vars
expected func() mathexp.Results expected func() mathexp.Results
}{{ }{{
name: "single query and single condition", // This test asserts that a single query with condition returns 0 and no matches as the condition
// is not met
name: "single query with condition when condition is not met",
vars: mathexp.Vars{ vars: mathexp.Vars{
"A": mathexp.Results{ "A": mathexp.Results{
Values: []mathexp.Value{ Values: []mathexp.Value{
valBasedSeries(ptr.Float64(30), ptr.Float64(40)), newSeries(ptr.Float64(1), ptr.Float64(5)),
}, },
}, },
}, },
cmd: &ConditionsCmd{ cmd: &ConditionsCmd{
Conditions: []condition{ Conditions: []condition{
{
InputRefID: "A",
Reducer: reducer("avg"),
Operator: "and",
Evaluator: &thresholdEvaluator{Type: "gt", Threshold: 34},
},
}},
expected: func() mathexp.Results {
v := valBasedNumber(ptr.Float64(1))
v.SetMeta([]EvalMatch{{Value: ptr.Float64(35)}})
return mathexp.NewResults(v)
},
}, {
name: "single query and single condition - empty series",
vars: mathexp.Vars{
"A": mathexp.Results{
Values: []mathexp.Value{
valBasedSeries(),
},
},
},
cmd: &ConditionsCmd{
Conditions: []condition{
{
InputRefID: "A",
Reducer: reducer("avg"),
Operator: "and",
Evaluator: &thresholdEvaluator{Type: "gt", Threshold: 34},
},
}},
expected: func() mathexp.Results {
v := valBasedNumber(nil)
v.SetMeta([]EvalMatch{{Metric: "NoData"}})
return mathexp.NewResults(v)
},
}, {
name: "single query and single condition - empty series and not empty series",
vars: mathexp.Vars{
"A": mathexp.Results{
Values: []mathexp.Value{
valBasedSeries(),
valBasedSeries(ptr.Float64(3)),
},
},
},
cmd: &ConditionsCmd{
Conditions: []condition{
{
InputRefID: "A",
Reducer: reducer("avg"),
Operator: "and",
Evaluator: &thresholdEvaluator{Type: "gt", Threshold: .5},
},
}},
expected: func() mathexp.Results {
v := valBasedNumber(ptr.Float64(1))
v.SetMeta([]EvalMatch{{Value: ptr.Float64(3)}})
return mathexp.NewResults(v)
},
}, {
name: "single query and two conditions",
vars: mathexp.Vars{
"A": mathexp.Results{
Values: []mathexp.Value{
valBasedSeries(ptr.Float64(30), ptr.Float64(40)),
},
},
},
cmd: &ConditionsCmd{
Conditions: []condition{
{
InputRefID: "A",
Reducer: reducer("max"),
Evaluator: &thresholdEvaluator{Type: "gt", Threshold: 34},
},
{ {
InputRefID: "A", InputRefID: "A",
Reducer: reducer("min"), Reducer: reducer("min"),
Operator: "or",
Evaluator: &thresholdEvaluator{Type: "gt", Threshold: 12},
},
}},
expected: func() mathexp.Results {
v := valBasedNumber(ptr.Float64(1))
v.SetMeta([]EvalMatch{{Value: ptr.Float64(40)}, {Value: ptr.Float64(30)}})
return mathexp.NewResults(v)
},
}, {
name: "single query and single condition - multiple series (one true, one not == true)",
vars: mathexp.Vars{
"A": mathexp.Results{
Values: []mathexp.Value{
valBasedSeriesWithLabels(data.Labels{"h": "1"}, ptr.Float64(30), ptr.Float64(40)),
valBasedSeries(ptr.Float64(0), ptr.Float64(10)),
},
},
},
cmd: &ConditionsCmd{
Conditions: []condition{
{
InputRefID: "A",
Reducer: reducer("avg"),
Operator: "and", Operator: "and",
Evaluator: &thresholdEvaluator{Type: "gt", Threshold: 34}, Evaluator: &thresholdEvaluator{Type: "gt", Threshold: 2},
}, },
}}, }},
expected: func() mathexp.Results { expected: func() mathexp.Results {
v := valBasedNumber(ptr.Float64(1)) v := newNumber(ptr.Float64(0))
v.SetMeta([]EvalMatch{{Value: ptr.Float64(35), Labels: data.Labels{"h": "1"}}})
return mathexp.NewResults(v)
},
}, {
name: "single query and single condition - multiple series (one not true, one true == true)",
vars: mathexp.Vars{
"A": mathexp.Results{
Values: []mathexp.Value{
valBasedSeries(ptr.Float64(0), ptr.Float64(10)),
valBasedSeries(ptr.Float64(30), ptr.Float64(40)),
},
},
},
cmd: &ConditionsCmd{
Conditions: []condition{
{
InputRefID: "A",
Reducer: reducer("avg"),
Operator: "and",
Evaluator: &thresholdEvaluator{Type: "gt", Threshold: 34},
},
}},
expected: func() mathexp.Results {
v := valBasedNumber(ptr.Float64(1))
v.SetMeta([]EvalMatch{{Value: ptr.Float64(35)}})
return mathexp.NewResults(v)
},
}, {
name: "single query and single condition - multiple series (2 not true == false)",
vars: mathexp.Vars{
"A": mathexp.Results{
Values: []mathexp.Value{
valBasedSeries(ptr.Float64(0), ptr.Float64(10)),
valBasedSeries(ptr.Float64(20), ptr.Float64(30)),
},
},
},
cmd: &ConditionsCmd{
Conditions: []condition{
{
InputRefID: "A",
Reducer: reducer("avg"),
Operator: "and",
Evaluator: &thresholdEvaluator{Type: "gt", Threshold: 34},
},
}},
expected: func() mathexp.Results {
v := valBasedNumber(ptr.Float64(0))
v.SetMeta([]EvalMatch{}) v.SetMeta([]EvalMatch{})
return mathexp.Results{Values: mathexp.Values{v}} return newResults(v)
}, },
}, { }, {
name: "single query and single ranged condition", // This test asserts that a single query with condition returns 1 and the average in the meta as
// the condition is met
name: "single query with condition when condition is met",
vars: mathexp.Vars{ vars: mathexp.Vars{
"A": mathexp.Results{ "A": mathexp.Results{
Values: []mathexp.Value{ Values: []mathexp.Value{
valBasedSeries(ptr.Float64(30), ptr.Float64(40)), newSeries(ptr.Float64(1), ptr.Float64(5)),
},
},
},
cmd: &ConditionsCmd{
Conditions: []condition{
{
InputRefID: "A",
Reducer: reducer("avg"),
Operator: "and",
Evaluator: &thresholdEvaluator{Type: "gt", Threshold: 2},
},
}},
expected: func() mathexp.Results {
v := newNumber(ptr.Float64(1))
v.SetMeta([]EvalMatch{{Value: ptr.Float64(3)}})
return newResults(v)
},
}, {
name: "single query with ranged condition when condition is not met",
vars: mathexp.Vars{
"A": mathexp.Results{
Values: []mathexp.Value{
newSeries(ptr.Float64(1), ptr.Float64(5)),
}, },
}, },
}, },
@ -204,17 +84,41 @@ func TestConditionsCmd(t *testing.T) {
InputRefID: "A", InputRefID: "A",
Reducer: reducer("diff"), Reducer: reducer("diff"),
Operator: "and", Operator: "and",
Evaluator: &rangedEvaluator{Type: "within_range", Lower: 2, Upper: 3}, Evaluator: &rangedEvaluator{Type: "within_range", Lower: 2, Upper: 4},
}, },
}, },
}, },
expected: func() mathexp.Results { expected: func() mathexp.Results {
v := valBasedNumber(ptr.Float64(0)) v := newNumber(ptr.Float64(0))
v.SetMeta([]EvalMatch{}) v.SetMeta([]EvalMatch{})
return mathexp.NewResults(v) return newResults(v)
}, },
}, { }, {
name: "single query with no data", name: "single query with ranged condition when condition is met",
vars: mathexp.Vars{
"A": mathexp.Results{
Values: []mathexp.Value{
newSeries(ptr.Float64(1), ptr.Float64(5)),
},
},
},
cmd: &ConditionsCmd{
Conditions: []condition{
{
InputRefID: "A",
Reducer: reducer("diff"),
Operator: "and",
Evaluator: &rangedEvaluator{Type: "within_range", Lower: 0, Upper: 10},
},
},
},
expected: func() mathexp.Results {
v := newNumber(ptr.Float64(1))
v.SetMeta([]EvalMatch{{Value: ptr.Float64(4)}})
return newResults(v)
},
}, {
name: "single no data query with condition is No Data",
vars: mathexp.Vars{ vars: mathexp.Vars{
"A": mathexp.Results{ "A": mathexp.Results{
Values: []mathexp.Value{mathexp.NoData{}.New()}, Values: []mathexp.Value{mathexp.NoData{}.New()},
@ -224,19 +128,19 @@ func TestConditionsCmd(t *testing.T) {
Conditions: []condition{ Conditions: []condition{
{ {
InputRefID: "A", InputRefID: "A",
Reducer: reducer("avg"), Reducer: reducer("min"),
Operator: "and", Operator: "and",
Evaluator: &thresholdEvaluator{"gt", 1}, Evaluator: &thresholdEvaluator{"gt", 1},
}, },
}, },
}, },
expected: func() mathexp.Results { expected: func() mathexp.Results {
v := valBasedNumber(nil) v := newNumber(nil)
v.SetMeta([]EvalMatch{{Metric: "NoData"}}) v.SetMeta([]EvalMatch{{Metric: "NoData"}})
return mathexp.NewResults(v) return newResults(v)
}, },
}, { }, {
name: "single query with no values", name: "single no values query with condition is No Data",
vars: mathexp.Vars{ vars: mathexp.Vars{
"A": mathexp.Results{ "A": mathexp.Results{
Values: []mathexp.Value{}, Values: []mathexp.Value{},
@ -246,25 +150,307 @@ func TestConditionsCmd(t *testing.T) {
Conditions: []condition{ Conditions: []condition{
{ {
InputRefID: "A", InputRefID: "A",
Reducer: reducer("avg"), Reducer: reducer("min"),
Operator: "and", Operator: "and",
Evaluator: &thresholdEvaluator{"gt", 1}, Evaluator: &thresholdEvaluator{"gt", 1},
}, },
}, },
}, },
expected: func() mathexp.Results { expected: func() mathexp.Results {
v := valBasedNumber(nil) v := newNumber(nil)
v.SetMeta([]EvalMatch{{Metric: "NoData"}}) v.SetMeta([]EvalMatch{{Metric: "NoData"}})
return mathexp.NewResults(v) return newResults(v)
}, },
}, { }, {
name: "should accept numbers", name: "single series no points query with condition returns No Data",
vars: mathexp.Vars{ vars: mathexp.Vars{
"A": mathexp.Results{ "A": mathexp.Results{
Values: []mathexp.Value{ Values: []mathexp.Value{
valBasedNumber(ptr.Float64(5)), newSeries(nil),
valBasedNumber(ptr.Float64(10)), },
valBasedNumber(ptr.Float64(15)), },
},
cmd: &ConditionsCmd{
Conditions: []condition{
{
InputRefID: "A",
Reducer: reducer("min"),
Operator: "and",
Evaluator: &thresholdEvaluator{"gt", 1},
},
},
},
expected: func() mathexp.Results {
v := newNumber(nil)
v.SetMeta([]EvalMatch{{Metric: "NoData"}})
return newResults(v)
},
}, {
name: "single no data query with condition is met has no value",
vars: mathexp.Vars{
"A": mathexp.Results{
Values: []mathexp.Value{mathexp.NoData{}.New()},
},
},
cmd: &ConditionsCmd{
Conditions: []condition{
{
InputRefID: "A",
Reducer: reducer("min"),
Operator: "and",
Evaluator: &noValueEvaluator{},
},
},
},
expected: func() mathexp.Results {
v := newNumber(nil)
// This seems incorrect
v.SetMeta([]EvalMatch{{}, {Metric: "NoData"}})
return newResults(v)
},
}, {
name: "single no values query with condition is met has no value",
vars: mathexp.Vars{
"A": mathexp.Results{
Values: []mathexp.Value{},
},
},
cmd: &ConditionsCmd{
Conditions: []condition{
{
InputRefID: "A",
Reducer: reducer("min"),
Operator: "and",
Evaluator: &noValueEvaluator{},
},
},
},
expected: func() mathexp.Results {
v := newNumber(nil)
// This too seems incorrect, looks like we don't call the evaluator
v.SetMeta([]EvalMatch{{Metric: "NoData"}})
return newResults(v)
},
}, {
name: "single series no points query with condition is met has no value",
vars: mathexp.Vars{
"A": mathexp.Results{
Values: []mathexp.Value{
newSeries(nil),
},
},
},
cmd: &ConditionsCmd{
Conditions: []condition{
{
InputRefID: "A",
Reducer: reducer("min"),
Operator: "and",
Evaluator: &noValueEvaluator{},
},
},
},
expected: func() mathexp.Results {
v := newNumber(nil)
// This seems incorrect
v.SetMeta([]EvalMatch{{}, {Metric: "NoData"}})
return newResults(v)
},
}, {
// This test asserts that a single query with condition returns 1 and the average of the second
// series in the meta because while the first series is No Data the second series contains valid points
name: "single query with condition returns average when one series is no data and the other contains valid points",
vars: mathexp.Vars{
"A": mathexp.Results{
Values: []mathexp.Value{
newSeries(),
newSeries(ptr.Float64(2)),
},
},
},
cmd: &ConditionsCmd{
Conditions: []condition{
{
InputRefID: "A",
Reducer: reducer("min"),
Operator: "and",
Evaluator: &thresholdEvaluator{Type: "gt", Threshold: 1},
},
}},
expected: func() mathexp.Results {
v := newNumber(ptr.Float64(1))
v.SetMeta([]EvalMatch{{Value: ptr.Float64(2)}})
return newResults(v)
},
}, {
name: "single query with condition and no series matches condition",
vars: mathexp.Vars{
"A": mathexp.Results{
Values: []mathexp.Value{
newSeries(ptr.Float64(1), ptr.Float64(5)),
newSeries(ptr.Float64(2), ptr.Float64(10)),
},
},
},
cmd: &ConditionsCmd{
Conditions: []condition{
{
InputRefID: "A",
Reducer: reducer("min"),
Operator: "and",
Evaluator: &thresholdEvaluator{Type: "gt", Threshold: 15},
},
}},
expected: func() mathexp.Results {
v := newNumber(ptr.Float64(0))
v.SetMeta([]EvalMatch{})
return mathexp.Results{Values: mathexp.Values{v}}
},
}, {
name: "single query with condition and one of two series matches condition",
vars: mathexp.Vars{
"A": mathexp.Results{
Values: []mathexp.Value{
newSeries(ptr.Float64(1), ptr.Float64(5)),
newSeriesWithLabels(data.Labels{"foo": "bar"}, ptr.Float64(2), ptr.Float64(10)),
},
},
},
cmd: &ConditionsCmd{
Conditions: []condition{
{
InputRefID: "A",
Reducer: reducer("min"),
Operator: "and",
Evaluator: &thresholdEvaluator{Type: "gt", Threshold: 1},
},
}},
expected: func() mathexp.Results {
v := newNumber(ptr.Float64(1))
v.SetMeta([]EvalMatch{{Value: ptr.Float64(2), Labels: data.Labels{"foo": "bar"}}})
return newResults(v)
},
}, {
name: "single query with condition and both series matches condition",
vars: mathexp.Vars{
"A": mathexp.Results{
Values: []mathexp.Value{
newSeries(ptr.Float64(1), ptr.Float64(5)),
newSeriesWithLabels(data.Labels{"foo": "bar"}, ptr.Float64(2), ptr.Float64(10)),
},
},
},
cmd: &ConditionsCmd{
Conditions: []condition{
{
InputRefID: "A",
Reducer: reducer("min"),
Operator: "and",
Evaluator: &thresholdEvaluator{Type: "gt", Threshold: 0},
},
}},
expected: func() mathexp.Results {
v := newNumber(ptr.Float64(1))
v.SetMeta([]EvalMatch{{
Value: ptr.Float64(1),
}, {
Value: ptr.Float64(2),
Labels: data.Labels{"foo": "bar"},
}})
return newResults(v)
},
}, {
name: "single query with two conditions where left hand side is met",
vars: mathexp.Vars{
"A": mathexp.Results{
Values: []mathexp.Value{
newSeries(ptr.Float64(1), ptr.Float64(5)),
},
},
},
cmd: &ConditionsCmd{
Conditions: []condition{
{
InputRefID: "A",
Reducer: reducer("max"),
Evaluator: &thresholdEvaluator{Type: "gt", Threshold: 2},
},
{
InputRefID: "A",
Reducer: reducer("min"),
Operator: "or",
Evaluator: &thresholdEvaluator{Type: "gt", Threshold: 1},
},
}},
expected: func() mathexp.Results {
v := newNumber(ptr.Float64(1))
v.SetMeta([]EvalMatch{{Value: ptr.Float64(5)}})
return newResults(v)
},
}, {
name: "single query with two conditions where right hand side is met",
vars: mathexp.Vars{
"A": mathexp.Results{
Values: []mathexp.Value{
newSeries(ptr.Float64(1), ptr.Float64(5)),
},
},
},
cmd: &ConditionsCmd{
Conditions: []condition{
{
InputRefID: "A",
Reducer: reducer("max"),
Evaluator: &thresholdEvaluator{Type: "gt", Threshold: 10},
},
{
InputRefID: "A",
Reducer: reducer("min"),
Operator: "or",
Evaluator: &thresholdEvaluator{Type: "gt", Threshold: 0},
},
}},
expected: func() mathexp.Results {
v := newNumber(ptr.Float64(1))
v.SetMeta([]EvalMatch{{Value: ptr.Float64(1)}})
return newResults(v)
},
}, {
name: "single query with two conditions where both are met",
vars: mathexp.Vars{
"A": mathexp.Results{
Values: []mathexp.Value{
newSeries(ptr.Float64(1), ptr.Float64(5)),
},
},
},
cmd: &ConditionsCmd{
Conditions: []condition{
{
InputRefID: "A",
Reducer: reducer("max"),
Evaluator: &thresholdEvaluator{Type: "gt", Threshold: 2},
},
{
InputRefID: "A",
Reducer: reducer("min"),
Operator: "or",
Evaluator: &thresholdEvaluator{Type: "gt", Threshold: 0},
},
}},
expected: func() mathexp.Results {
v := newNumber(ptr.Float64(1))
v.SetMeta([]EvalMatch{{Value: ptr.Float64(5)}, {Value: ptr.Float64(1)}})
return newResults(v)
},
}, {
name: "single instant query with condition where condition is met",
vars: mathexp.Vars{
"A": mathexp.Results{
Values: []mathexp.Value{
newNumber(ptr.Float64(5)),
newNumber(ptr.Float64(10)),
newNumber(ptr.Float64(15)),
}, },
}, },
}, },
@ -279,13 +465,13 @@ func TestConditionsCmd(t *testing.T) {
}, },
}, },
expected: func() mathexp.Results { expected: func() mathexp.Results {
v := valBasedNumber(ptr.Float64(1)) v := newNumber(ptr.Float64(1))
v.SetMeta([]EvalMatch{ v.SetMeta([]EvalMatch{
{Value: ptr.Float64(5)}, {Value: ptr.Float64(5)},
{Value: ptr.Float64(10)}, {Value: ptr.Float64(10)},
{Value: ptr.Float64(15)}, {Value: ptr.Float64(15)},
}) })
return mathexp.NewResults(v) return newResults(v)
}, },
}} }}
@ -293,9 +479,6 @@ func TestConditionsCmd(t *testing.T) {
t.Run(tt.name, func(t *testing.T) { t.Run(tt.name, func(t *testing.T) {
res, err := tt.cmd.Execute(context.Background(), time.Now(), tt.vars) res, err := tt.cmd.Execute(context.Background(), time.Now(), tt.vars)
require.NoError(t, err) require.NoError(t, err)
require.Equal(t, 1, len(res.Values))
require.Equal(t, tt.expected(), res) require.Equal(t, tt.expected(), res)
}) })
} }

View File

@ -18,25 +18,25 @@ func TestThresholdEvaluator(t *testing.T) {
{ {
name: "value 3 is gt 1: true", name: "value 3 is gt 1: true",
evaluator: &thresholdEvaluator{"gt", 1}, evaluator: &thresholdEvaluator{"gt", 1},
inputNumber: valBasedNumber(ptr.Float64(3)), inputNumber: newNumber(ptr.Float64(3)),
expected: true, expected: true,
}, },
{ {
name: "value 1 is gt 3: false", name: "value 1 is gt 3: false",
evaluator: &thresholdEvaluator{"gt", 3}, evaluator: &thresholdEvaluator{"gt", 3},
inputNumber: valBasedNumber(ptr.Float64(1)), inputNumber: newNumber(ptr.Float64(1)),
expected: false, expected: false,
}, },
{ {
name: "value 3 is lt 1: true", name: "value 3 is lt 1: true",
evaluator: &thresholdEvaluator{"lt", 1}, evaluator: &thresholdEvaluator{"lt", 1},
inputNumber: valBasedNumber(ptr.Float64(3)), inputNumber: newNumber(ptr.Float64(3)),
expected: false, expected: false,
}, },
{ {
name: "value 1 is lt 3: false", name: "value 1 is lt 3: false",
evaluator: &thresholdEvaluator{"lt", 3}, evaluator: &thresholdEvaluator{"lt", 3},
inputNumber: valBasedNumber(ptr.Float64(1)), inputNumber: newNumber(ptr.Float64(1)),
expected: true, expected: true,
}, },
} }
@ -59,50 +59,50 @@ func TestRangedEvaluator(t *testing.T) {
{ {
name: "value 3 is within range 1, 100: true", name: "value 3 is within range 1, 100: true",
evaluator: &rangedEvaluator{"within_range", 1, 100}, evaluator: &rangedEvaluator{"within_range", 1, 100},
inputNumber: valBasedNumber(ptr.Float64(3)), inputNumber: newNumber(ptr.Float64(3)),
expected: true, expected: true,
}, },
{ {
name: "value 300 is within range 1, 100: false", name: "value 300 is within range 1, 100: false",
evaluator: &rangedEvaluator{"within_range", 1, 100}, evaluator: &rangedEvaluator{"within_range", 1, 100},
inputNumber: valBasedNumber(ptr.Float64(300)), inputNumber: newNumber(ptr.Float64(300)),
expected: false, expected: false,
}, },
{ {
name: "value 3 is within range 100, 1: true", name: "value 3 is within range 100, 1: true",
evaluator: &rangedEvaluator{"within_range", 100, 1}, evaluator: &rangedEvaluator{"within_range", 100, 1},
inputNumber: valBasedNumber(ptr.Float64(3)), inputNumber: newNumber(ptr.Float64(3)),
expected: true, expected: true,
}, },
{ {
name: "value 300 is within range 100, 1: false", name: "value 300 is within range 100, 1: false",
evaluator: &rangedEvaluator{"within_range", 100, 1}, evaluator: &rangedEvaluator{"within_range", 100, 1},
inputNumber: valBasedNumber(ptr.Float64(300)), inputNumber: newNumber(ptr.Float64(300)),
expected: false, expected: false,
}, },
// outside // outside
{ {
name: "value 1000 is outside range 1, 100: true", name: "value 1000 is outside range 1, 100: true",
evaluator: &rangedEvaluator{"outside_range", 1, 100}, evaluator: &rangedEvaluator{"outside_range", 1, 100},
inputNumber: valBasedNumber(ptr.Float64(1000)), inputNumber: newNumber(ptr.Float64(1000)),
expected: true, expected: true,
}, },
{ {
name: "value 50 is outside range 1, 100: false", name: "value 50 is outside range 1, 100: false",
evaluator: &rangedEvaluator{"outside_range", 1, 100}, evaluator: &rangedEvaluator{"outside_range", 1, 100},
inputNumber: valBasedNumber(ptr.Float64(50)), inputNumber: newNumber(ptr.Float64(50)),
expected: false, expected: false,
}, },
{ {
name: "value 1000 is outside range 100, 1: true", name: "value 1000 is outside range 100, 1: true",
evaluator: &rangedEvaluator{"outside_range", 100, 1}, evaluator: &rangedEvaluator{"outside_range", 100, 1},
inputNumber: valBasedNumber(ptr.Float64(1000)), inputNumber: newNumber(ptr.Float64(1000)),
expected: true, expected: true,
}, },
{ {
name: "value 50 is outside range 100, 1: false", name: "value 50 is outside range 100, 1: false",
evaluator: &rangedEvaluator{"outside_range", 100, 1}, evaluator: &rangedEvaluator{"outside_range", 100, 1},
inputNumber: valBasedNumber(ptr.Float64(50)), inputNumber: newNumber(ptr.Float64(50)),
expected: false, expected: false,
}, },
} }
@ -124,13 +124,13 @@ func TestNoValueEvaluator(t *testing.T) {
{ {
name: "value 50 is no_value: false", name: "value 50 is no_value: false",
evaluator: &noValueEvaluator{}, evaluator: &noValueEvaluator{},
inputNumber: valBasedNumber(ptr.Float64(50)), inputNumber: newNumber(ptr.Float64(50)),
expected: false, expected: false,
}, },
{ {
name: "value nil is no_value: true", name: "value nil is no_value: true",
evaluator: &noValueEvaluator{}, evaluator: &noValueEvaluator{},
inputNumber: valBasedNumber(nil), inputNumber: newNumber(nil),
expected: true, expected: true,
}, },
} }

View File

@ -5,10 +5,11 @@ import (
"testing" "testing"
"time" "time"
"github.com/grafana/grafana-plugin-sdk-go/data"
"github.com/grafana/grafana/pkg/expr/mathexp"
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
ptr "github.com/xorcare/pointer" ptr "github.com/xorcare/pointer"
"github.com/grafana/grafana-plugin-sdk-go/data"
"github.com/grafana/grafana/pkg/expr/mathexp"
) )
func TestReducer(t *testing.T) { func TestReducer(t *testing.T) {
@ -21,98 +22,98 @@ func TestReducer(t *testing.T) {
{ {
name: "sum", name: "sum",
reducer: reducer("sum"), reducer: reducer("sum"),
inputSeries: valBasedSeries(ptr.Float64(1), ptr.Float64(2), ptr.Float64(3)), inputSeries: newSeries(ptr.Float64(1), ptr.Float64(2), ptr.Float64(3)),
expectedNumber: valBasedNumber(ptr.Float64(6)), expectedNumber: newNumber(ptr.Float64(6)),
}, },
{ {
name: "min", name: "min",
reducer: reducer("min"), reducer: reducer("min"),
inputSeries: valBasedSeries(ptr.Float64(3), ptr.Float64(2), ptr.Float64(1)), inputSeries: newSeries(ptr.Float64(3), ptr.Float64(2), ptr.Float64(1)),
expectedNumber: valBasedNumber(ptr.Float64(1)), expectedNumber: newNumber(ptr.Float64(1)),
}, },
{ {
name: "min with NaNs only", name: "min with NaNs only",
reducer: reducer("min"), reducer: reducer("min"),
inputSeries: valBasedSeries(ptr.Float64(math.NaN()), ptr.Float64(math.NaN()), ptr.Float64(math.NaN())), inputSeries: newSeries(ptr.Float64(math.NaN()), ptr.Float64(math.NaN()), ptr.Float64(math.NaN())),
expectedNumber: valBasedNumber(nil), expectedNumber: newNumber(nil),
}, },
{ {
name: "max", name: "max",
reducer: reducer("max"), reducer: reducer("max"),
inputSeries: valBasedSeries(ptr.Float64(1), ptr.Float64(2), ptr.Float64(3)), inputSeries: newSeries(ptr.Float64(1), ptr.Float64(2), ptr.Float64(3)),
expectedNumber: valBasedNumber(ptr.Float64(3)), expectedNumber: newNumber(ptr.Float64(3)),
}, },
{ {
name: "count", name: "count",
reducer: reducer("count"), reducer: reducer("count"),
inputSeries: valBasedSeries(ptr.Float64(1), ptr.Float64(2), ptr.Float64(3000)), inputSeries: newSeries(ptr.Float64(1), ptr.Float64(2), ptr.Float64(3000)),
expectedNumber: valBasedNumber(ptr.Float64(3)), expectedNumber: newNumber(ptr.Float64(3)),
}, },
{ {
name: "last", name: "last",
reducer: reducer("last"), reducer: reducer("last"),
inputSeries: valBasedSeries(ptr.Float64(1), ptr.Float64(2), ptr.Float64(3000)), inputSeries: newSeries(ptr.Float64(1), ptr.Float64(2), ptr.Float64(3000)),
expectedNumber: valBasedNumber(ptr.Float64(3000)), expectedNumber: newNumber(ptr.Float64(3000)),
}, },
{ {
name: "median with odd amount of numbers", name: "median with odd amount of numbers",
reducer: reducer("median"), reducer: reducer("median"),
inputSeries: valBasedSeries(ptr.Float64(1), ptr.Float64(2), ptr.Float64(3000)), inputSeries: newSeries(ptr.Float64(1), ptr.Float64(2), ptr.Float64(3000)),
expectedNumber: valBasedNumber(ptr.Float64(2)), expectedNumber: newNumber(ptr.Float64(2)),
}, },
{ {
name: "median with even amount of numbers", name: "median with even amount of numbers",
reducer: reducer("median"), reducer: reducer("median"),
inputSeries: valBasedSeries(ptr.Float64(1), ptr.Float64(2), ptr.Float64(4), ptr.Float64(3000)), inputSeries: newSeries(ptr.Float64(1), ptr.Float64(2), ptr.Float64(4), ptr.Float64(3000)),
expectedNumber: valBasedNumber(ptr.Float64(3)), expectedNumber: newNumber(ptr.Float64(3)),
}, },
{ {
name: "median with one value", name: "median with one value",
reducer: reducer("median"), reducer: reducer("median"),
inputSeries: valBasedSeries(ptr.Float64(1)), inputSeries: newSeries(ptr.Float64(1)),
expectedNumber: valBasedNumber(ptr.Float64(1)), expectedNumber: newNumber(ptr.Float64(1)),
}, },
{ {
name: "median should ignore null values", name: "median should ignore null values",
reducer: reducer("median"), reducer: reducer("median"),
inputSeries: valBasedSeries(nil, nil, nil, ptr.Float64(1), ptr.Float64(2), ptr.Float64(3)), inputSeries: newSeries(nil, nil, nil, ptr.Float64(1), ptr.Float64(2), ptr.Float64(3)),
expectedNumber: valBasedNumber(ptr.Float64(2)), expectedNumber: newNumber(ptr.Float64(2)),
}, },
{ {
name: "avg", name: "avg",
reducer: reducer("avg"), reducer: reducer("avg"),
inputSeries: valBasedSeries(ptr.Float64(1), ptr.Float64(2), ptr.Float64(3)), inputSeries: newSeries(ptr.Float64(1), ptr.Float64(2), ptr.Float64(3)),
expectedNumber: valBasedNumber(ptr.Float64(2)), expectedNumber: newNumber(ptr.Float64(2)),
}, },
{ {
name: "avg with only nulls", name: "avg with only nulls",
reducer: reducer("avg"), reducer: reducer("avg"),
inputSeries: valBasedSeries(nil), inputSeries: newSeries(nil),
expectedNumber: valBasedNumber(nil), expectedNumber: newNumber(nil),
}, },
{ {
name: "avg of number values and null values should ignore nulls", name: "avg of number values and null values should ignore nulls",
reducer: reducer("avg"), reducer: reducer("avg"),
inputSeries: valBasedSeries(ptr.Float64(3), nil, nil, ptr.Float64(3)), inputSeries: newSeries(ptr.Float64(3), nil, nil, ptr.Float64(3)),
expectedNumber: valBasedNumber(ptr.Float64(3)), expectedNumber: newNumber(ptr.Float64(3)),
}, },
{ {
name: "count_non_null with mixed null/real values", name: "count_non_null with mixed null/real values",
reducer: reducer("count_non_null"), reducer: reducer("count_non_null"),
inputSeries: valBasedSeries(nil, nil, ptr.Float64(3), ptr.Float64(4)), inputSeries: newSeries(nil, nil, ptr.Float64(3), ptr.Float64(4)),
expectedNumber: valBasedNumber(ptr.Float64(2)), expectedNumber: newNumber(ptr.Float64(2)),
}, },
{ {
name: "count_non_null with mixed null/real values", name: "count_non_null with mixed null/real values",
reducer: reducer("count_non_null"), reducer: reducer("count_non_null"),
inputSeries: valBasedSeries(nil, nil, ptr.Float64(3), ptr.Float64(4)), inputSeries: newSeries(nil, nil, ptr.Float64(3), ptr.Float64(4)),
expectedNumber: valBasedNumber(ptr.Float64(2)), expectedNumber: newNumber(ptr.Float64(2)),
}, },
{ {
name: "count_non_null with no values", name: "count_non_null with no values",
reducer: reducer("count_non_null"), reducer: reducer("count_non_null"),
inputSeries: valBasedSeries(nil, nil), inputSeries: newSeries(nil, nil),
expectedNumber: valBasedNumber(nil), expectedNumber: newNumber(nil),
}, },
} }
@ -133,58 +134,58 @@ func TestDiffReducer(t *testing.T) {
}{ }{
{ {
name: "diff of one positive point", name: "diff of one positive point",
inputSeries: valBasedSeries(ptr.Float64(30)), inputSeries: newSeries(ptr.Float64(30)),
expectedNumber: valBasedNumber(ptr.Float64(0)), expectedNumber: newNumber(ptr.Float64(0)),
}, },
{ {
name: "diff of one negative point", name: "diff of one negative point",
inputSeries: valBasedSeries(ptr.Float64(-30)), inputSeries: newSeries(ptr.Float64(-30)),
expectedNumber: valBasedNumber(ptr.Float64(0)), expectedNumber: newNumber(ptr.Float64(0)),
}, },
{ {
name: "diff two positive points [1]", name: "diff two positive points [1]",
inputSeries: valBasedSeries(ptr.Float64(30), ptr.Float64(40)), inputSeries: newSeries(ptr.Float64(30), ptr.Float64(40)),
expectedNumber: valBasedNumber(ptr.Float64(10)), expectedNumber: newNumber(ptr.Float64(10)),
}, },
{ {
name: "diff two positive points [2]", name: "diff two positive points [2]",
inputSeries: valBasedSeries(ptr.Float64(30), ptr.Float64(20)), inputSeries: newSeries(ptr.Float64(30), ptr.Float64(20)),
expectedNumber: valBasedNumber(ptr.Float64(-10)), expectedNumber: newNumber(ptr.Float64(-10)),
}, },
{ {
name: "diff two negative points [1]", name: "diff two negative points [1]",
inputSeries: valBasedSeries(ptr.Float64(-30), ptr.Float64(-40)), inputSeries: newSeries(ptr.Float64(-30), ptr.Float64(-40)),
expectedNumber: valBasedNumber(ptr.Float64(-10)), expectedNumber: newNumber(ptr.Float64(-10)),
}, },
{ {
name: "diff two negative points [2]", name: "diff two negative points [2]",
inputSeries: valBasedSeries(ptr.Float64(-30), ptr.Float64(-10)), inputSeries: newSeries(ptr.Float64(-30), ptr.Float64(-10)),
expectedNumber: valBasedNumber(ptr.Float64(20)), expectedNumber: newNumber(ptr.Float64(20)),
}, },
{ {
name: "diff of one positive and one negative point", name: "diff of one positive and one negative point",
inputSeries: valBasedSeries(ptr.Float64(30), ptr.Float64(-40)), inputSeries: newSeries(ptr.Float64(30), ptr.Float64(-40)),
expectedNumber: valBasedNumber(ptr.Float64(-70)), expectedNumber: newNumber(ptr.Float64(-70)),
}, },
{ {
name: "diff of one negative and one positive point", name: "diff of one negative and one positive point",
inputSeries: valBasedSeries(ptr.Float64(-30), ptr.Float64(40)), inputSeries: newSeries(ptr.Float64(-30), ptr.Float64(40)),
expectedNumber: valBasedNumber(ptr.Float64(70)), expectedNumber: newNumber(ptr.Float64(70)),
}, },
{ {
name: "diff of three positive points", name: "diff of three positive points",
inputSeries: valBasedSeries(ptr.Float64(30), ptr.Float64(40), ptr.Float64(50)), inputSeries: newSeries(ptr.Float64(30), ptr.Float64(40), ptr.Float64(50)),
expectedNumber: valBasedNumber(ptr.Float64(20)), expectedNumber: newNumber(ptr.Float64(20)),
}, },
{ {
name: "diff of three negative points", name: "diff of three negative points",
inputSeries: valBasedSeries(ptr.Float64(-30), ptr.Float64(-40), ptr.Float64(-50)), inputSeries: newSeries(ptr.Float64(-30), ptr.Float64(-40), ptr.Float64(-50)),
expectedNumber: valBasedNumber(ptr.Float64(-20)), expectedNumber: newNumber(ptr.Float64(-20)),
}, },
{ {
name: "diff with only nulls", name: "diff with only nulls",
inputSeries: valBasedSeries(nil, nil), inputSeries: newSeries(nil, nil),
expectedNumber: valBasedNumber(nil), expectedNumber: newNumber(nil),
}, },
} }
for _, tt := range tests { for _, tt := range tests {
@ -203,58 +204,58 @@ func TestDiffAbsReducer(t *testing.T) {
}{ }{
{ {
name: "diff_abs of one positive point", name: "diff_abs of one positive point",
inputSeries: valBasedSeries(ptr.Float64(30)), inputSeries: newSeries(ptr.Float64(30)),
expectedNumber: valBasedNumber(ptr.Float64(0)), expectedNumber: newNumber(ptr.Float64(0)),
}, },
{ {
name: "diff_abs of one negative point", name: "diff_abs of one negative point",
inputSeries: valBasedSeries(ptr.Float64(-30)), inputSeries: newSeries(ptr.Float64(-30)),
expectedNumber: valBasedNumber(ptr.Float64(0)), expectedNumber: newNumber(ptr.Float64(0)),
}, },
{ {
name: "diff_abs two positive points [1]", name: "diff_abs two positive points [1]",
inputSeries: valBasedSeries(ptr.Float64(30), ptr.Float64(40)), inputSeries: newSeries(ptr.Float64(30), ptr.Float64(40)),
expectedNumber: valBasedNumber(ptr.Float64(10)), expectedNumber: newNumber(ptr.Float64(10)),
}, },
{ {
name: "diff_abs two positive points [2]", name: "diff_abs two positive points [2]",
inputSeries: valBasedSeries(ptr.Float64(30), ptr.Float64(20)), inputSeries: newSeries(ptr.Float64(30), ptr.Float64(20)),
expectedNumber: valBasedNumber(ptr.Float64(10)), expectedNumber: newNumber(ptr.Float64(10)),
}, },
{ {
name: "diff_abs two negative points [1]", name: "diff_abs two negative points [1]",
inputSeries: valBasedSeries(ptr.Float64(-30), ptr.Float64(-40)), inputSeries: newSeries(ptr.Float64(-30), ptr.Float64(-40)),
expectedNumber: valBasedNumber(ptr.Float64(10)), expectedNumber: newNumber(ptr.Float64(10)),
}, },
{ {
name: "diff_abs two negative points [2]", name: "diff_abs two negative points [2]",
inputSeries: valBasedSeries(ptr.Float64(-30), ptr.Float64(-10)), inputSeries: newSeries(ptr.Float64(-30), ptr.Float64(-10)),
expectedNumber: valBasedNumber(ptr.Float64(20)), expectedNumber: newNumber(ptr.Float64(20)),
}, },
{ {
name: "diff_abs of one positive and one negative point", name: "diff_abs of one positive and one negative point",
inputSeries: valBasedSeries(ptr.Float64(30), ptr.Float64(-40)), inputSeries: newSeries(ptr.Float64(30), ptr.Float64(-40)),
expectedNumber: valBasedNumber(ptr.Float64(70)), expectedNumber: newNumber(ptr.Float64(70)),
}, },
{ {
name: "diff_abs of one negative and one positive point", name: "diff_abs of one negative and one positive point",
inputSeries: valBasedSeries(ptr.Float64(-30), ptr.Float64(40)), inputSeries: newSeries(ptr.Float64(-30), ptr.Float64(40)),
expectedNumber: valBasedNumber(ptr.Float64(70)), expectedNumber: newNumber(ptr.Float64(70)),
}, },
{ {
name: "diff_abs of three positive points", name: "diff_abs of three positive points",
inputSeries: valBasedSeries(ptr.Float64(30), ptr.Float64(40), ptr.Float64(50)), inputSeries: newSeries(ptr.Float64(30), ptr.Float64(40), ptr.Float64(50)),
expectedNumber: valBasedNumber(ptr.Float64(20)), expectedNumber: newNumber(ptr.Float64(20)),
}, },
{ {
name: "diff_abs of three negative points", name: "diff_abs of three negative points",
inputSeries: valBasedSeries(ptr.Float64(-30), ptr.Float64(-40), ptr.Float64(-50)), inputSeries: newSeries(ptr.Float64(-30), ptr.Float64(-40), ptr.Float64(-50)),
expectedNumber: valBasedNumber(ptr.Float64(20)), expectedNumber: newNumber(ptr.Float64(20)),
}, },
{ {
name: "diff_abs with only nulls", name: "diff_abs with only nulls",
inputSeries: valBasedSeries(nil, nil), inputSeries: newSeries(nil, nil),
expectedNumber: valBasedNumber(nil), expectedNumber: newNumber(nil),
}, },
} }
for _, tt := range tests { for _, tt := range tests {
@ -273,58 +274,58 @@ func TestPercentDiffReducer(t *testing.T) {
}{ }{
{ {
name: "percent_diff of one positive point", name: "percent_diff of one positive point",
inputSeries: valBasedSeries(ptr.Float64(30)), inputSeries: newSeries(ptr.Float64(30)),
expectedNumber: valBasedNumber(ptr.Float64(0)), expectedNumber: newNumber(ptr.Float64(0)),
}, },
{ {
name: "percent_diff of one negative point", name: "percent_diff of one negative point",
inputSeries: valBasedSeries(ptr.Float64(-30)), inputSeries: newSeries(ptr.Float64(-30)),
expectedNumber: valBasedNumber(ptr.Float64(0)), expectedNumber: newNumber(ptr.Float64(0)),
}, },
{ {
name: "percent_diff two positive points [1]", name: "percent_diff two positive points [1]",
inputSeries: valBasedSeries(ptr.Float64(30), ptr.Float64(40)), inputSeries: newSeries(ptr.Float64(30), ptr.Float64(40)),
expectedNumber: valBasedNumber(ptr.Float64(33.33333333333333)), expectedNumber: newNumber(ptr.Float64(33.33333333333333)),
}, },
{ {
name: "percent_diff two positive points [2]", name: "percent_diff two positive points [2]",
inputSeries: valBasedSeries(ptr.Float64(30), ptr.Float64(20)), inputSeries: newSeries(ptr.Float64(30), ptr.Float64(20)),
expectedNumber: valBasedNumber(ptr.Float64(-33.33333333333333)), expectedNumber: newNumber(ptr.Float64(-33.33333333333333)),
}, },
{ {
name: "percent_diff two negative points [1]", name: "percent_diff two negative points [1]",
inputSeries: valBasedSeries(ptr.Float64(-30), ptr.Float64(-40)), inputSeries: newSeries(ptr.Float64(-30), ptr.Float64(-40)),
expectedNumber: valBasedNumber(ptr.Float64(-33.33333333333333)), expectedNumber: newNumber(ptr.Float64(-33.33333333333333)),
}, },
{ {
name: "percent_diff two negative points [2]", name: "percent_diff two negative points [2]",
inputSeries: valBasedSeries(ptr.Float64(-30), ptr.Float64(-10)), inputSeries: newSeries(ptr.Float64(-30), ptr.Float64(-10)),
expectedNumber: valBasedNumber(ptr.Float64(66.66666666666666)), expectedNumber: newNumber(ptr.Float64(66.66666666666666)),
}, },
{ {
name: "percent_diff of one positive and one negative point", name: "percent_diff of one positive and one negative point",
inputSeries: valBasedSeries(ptr.Float64(30), ptr.Float64(-40)), inputSeries: newSeries(ptr.Float64(30), ptr.Float64(-40)),
expectedNumber: valBasedNumber(ptr.Float64(-233.33333333333334)), expectedNumber: newNumber(ptr.Float64(-233.33333333333334)),
}, },
{ {
name: "percent_diff of one negative and one positive point", name: "percent_diff of one negative and one positive point",
inputSeries: valBasedSeries(ptr.Float64(-30), ptr.Float64(40)), inputSeries: newSeries(ptr.Float64(-30), ptr.Float64(40)),
expectedNumber: valBasedNumber(ptr.Float64(233.33333333333334)), expectedNumber: newNumber(ptr.Float64(233.33333333333334)),
}, },
{ {
name: "percent_diff of three positive points", name: "percent_diff of three positive points",
inputSeries: valBasedSeries(ptr.Float64(30), ptr.Float64(40), ptr.Float64(50)), inputSeries: newSeries(ptr.Float64(30), ptr.Float64(40), ptr.Float64(50)),
expectedNumber: valBasedNumber(ptr.Float64(66.66666666666666)), expectedNumber: newNumber(ptr.Float64(66.66666666666666)),
}, },
{ {
name: "percent_diff of three negative points", name: "percent_diff of three negative points",
inputSeries: valBasedSeries(ptr.Float64(-30), ptr.Float64(-40), ptr.Float64(-50)), inputSeries: newSeries(ptr.Float64(-30), ptr.Float64(-40), ptr.Float64(-50)),
expectedNumber: valBasedNumber(ptr.Float64(-66.66666666666666)), expectedNumber: newNumber(ptr.Float64(-66.66666666666666)),
}, },
{ {
name: "percent_diff with only nulls", name: "percent_diff with only nulls",
inputSeries: valBasedSeries(nil, nil), inputSeries: newSeries(nil, nil),
expectedNumber: valBasedNumber(nil), expectedNumber: newNumber(nil),
}, },
} }
for _, tt := range tests { for _, tt := range tests {
@ -343,58 +344,58 @@ func TestPercentDiffAbsReducer(t *testing.T) {
}{ }{
{ {
name: "percent_diff_abs of one positive point", name: "percent_diff_abs of one positive point",
inputSeries: valBasedSeries(ptr.Float64(30)), inputSeries: newSeries(ptr.Float64(30)),
expectedNumber: valBasedNumber(ptr.Float64(0)), expectedNumber: newNumber(ptr.Float64(0)),
}, },
{ {
name: "percent_diff_abs of one negative point", name: "percent_diff_abs of one negative point",
inputSeries: valBasedSeries(ptr.Float64(-30)), inputSeries: newSeries(ptr.Float64(-30)),
expectedNumber: valBasedNumber(ptr.Float64(0)), expectedNumber: newNumber(ptr.Float64(0)),
}, },
{ {
name: "percent_diff_abs two positive points [1]", name: "percent_diff_abs two positive points [1]",
inputSeries: valBasedSeries(ptr.Float64(30), ptr.Float64(40)), inputSeries: newSeries(ptr.Float64(30), ptr.Float64(40)),
expectedNumber: valBasedNumber(ptr.Float64(33.33333333333333)), expectedNumber: newNumber(ptr.Float64(33.33333333333333)),
}, },
{ {
name: "percent_diff_abs two positive points [2]", name: "percent_diff_abs two positive points [2]",
inputSeries: valBasedSeries(ptr.Float64(30), ptr.Float64(20)), inputSeries: newSeries(ptr.Float64(30), ptr.Float64(20)),
expectedNumber: valBasedNumber(ptr.Float64(33.33333333333333)), expectedNumber: newNumber(ptr.Float64(33.33333333333333)),
}, },
{ {
name: "percent_diff_abs two negative points [1]", name: "percent_diff_abs two negative points [1]",
inputSeries: valBasedSeries(ptr.Float64(-30), ptr.Float64(-40)), inputSeries: newSeries(ptr.Float64(-30), ptr.Float64(-40)),
expectedNumber: valBasedNumber(ptr.Float64(33.33333333333333)), expectedNumber: newNumber(ptr.Float64(33.33333333333333)),
}, },
{ {
name: "percent_diff_abs two negative points [2]", name: "percent_diff_abs two negative points [2]",
inputSeries: valBasedSeries(ptr.Float64(-30), ptr.Float64(-10)), inputSeries: newSeries(ptr.Float64(-30), ptr.Float64(-10)),
expectedNumber: valBasedNumber(ptr.Float64(66.66666666666666)), expectedNumber: newNumber(ptr.Float64(66.66666666666666)),
}, },
{ {
name: "percent_diff_abs of one positive and one negative point", name: "percent_diff_abs of one positive and one negative point",
inputSeries: valBasedSeries(ptr.Float64(30), ptr.Float64(-40)), inputSeries: newSeries(ptr.Float64(30), ptr.Float64(-40)),
expectedNumber: valBasedNumber(ptr.Float64(233.33333333333334)), expectedNumber: newNumber(ptr.Float64(233.33333333333334)),
}, },
{ {
name: "percent_diff_abs of one negative and one positive point", name: "percent_diff_abs of one negative and one positive point",
inputSeries: valBasedSeries(ptr.Float64(-30), ptr.Float64(40)), inputSeries: newSeries(ptr.Float64(-30), ptr.Float64(40)),
expectedNumber: valBasedNumber(ptr.Float64(233.33333333333334)), expectedNumber: newNumber(ptr.Float64(233.33333333333334)),
}, },
{ {
name: "percent_diff_abs of three positive points", name: "percent_diff_abs of three positive points",
inputSeries: valBasedSeries(ptr.Float64(30), ptr.Float64(40), ptr.Float64(50)), inputSeries: newSeries(ptr.Float64(30), ptr.Float64(40), ptr.Float64(50)),
expectedNumber: valBasedNumber(ptr.Float64(66.66666666666666)), expectedNumber: newNumber(ptr.Float64(66.66666666666666)),
}, },
{ {
name: "percent_diff_abs of three negative points", name: "percent_diff_abs of three negative points",
inputSeries: valBasedSeries(ptr.Float64(-30), ptr.Float64(-40), ptr.Float64(-50)), inputSeries: newSeries(ptr.Float64(-30), ptr.Float64(-40), ptr.Float64(-50)),
expectedNumber: valBasedNumber(ptr.Float64(66.66666666666666)), expectedNumber: newNumber(ptr.Float64(66.66666666666666)),
}, },
{ {
name: "percent_diff_abs with only nulls", name: "percent_diff_abs with only nulls",
inputSeries: valBasedSeries(nil, nil), inputSeries: newSeries(nil, nil),
expectedNumber: valBasedNumber(nil), expectedNumber: newNumber(nil),
}, },
} }
for _, tt := range tests { for _, tt := range tests {
@ -405,24 +406,28 @@ func TestPercentDiffAbsReducer(t *testing.T) {
} }
} }
func valBasedSeries(vals ...*float64) mathexp.Series { func newNumber(f *float64) mathexp.Number {
newSeries := mathexp.NewSeries("", nil, len(vals)) num := mathexp.NewNumber("", nil)
for idx, f := range vals { num.SetValue(f)
newSeries.SetPoint(idx, time.Unix(int64(idx), 0), f) return num
}
return newSeries
} }
func valBasedSeriesWithLabels(l data.Labels, vals ...*float64) mathexp.Series { func newSeries(points ...*float64) mathexp.Series {
newSeries := mathexp.NewSeries("", l, len(vals)) series := mathexp.NewSeries("", nil, len(points))
for idx, f := range vals { for idx, point := range points {
newSeries.SetPoint(idx, time.Unix(int64(idx), 0), f) series.SetPoint(idx, time.Unix(int64(idx), 0), point)
} }
return newSeries return series
} }
func valBasedNumber(f *float64) mathexp.Number { func newSeriesWithLabels(labels data.Labels, values ...*float64) mathexp.Series {
newNumber := mathexp.NewNumber("", nil) series := mathexp.NewSeries("", labels, len(values))
newNumber.SetValue(f) for idx, value := range values {
return newNumber series.SetPoint(idx, time.Unix(int64(idx), 0), value)
}
return series
}
func newResults(values ...mathexp.Value) mathexp.Results {
return mathexp.Results{Values: values}
} }

View File

@ -11,10 +11,6 @@ type Results struct {
Values Values Values Values
} }
func NewResults(values ...Value) Results {
return Results{Values: values}
}
// Values is a slice of Value interfaces // Values is a slice of Value interfaces
type Values []Value type Values []Value