From 78e126f0f7b01856b9e24ece38c1cfe59d0439e9 Mon Sep 17 00:00:00 2001 From: Theodore Wahle Date: Mon, 21 Sep 2020 11:34:51 -0700 Subject: [PATCH 1/5] Added Graphite's interpolate function --- .../graphite/native/builtin_functions.go | 49 ++++++++++++++++- .../graphite/native/builtin_functions_test.go | 52 +++++++++++++++++++ 2 files changed, 99 insertions(+), 2 deletions(-) diff --git a/src/query/graphite/native/builtin_functions.go b/src/query/graphite/native/builtin_functions.go index a8541e7c0f..c4eb76a21d 100644 --- a/src/query/graphite/native/builtin_functions.go +++ b/src/query/graphite/native/builtin_functions.go @@ -557,8 +557,8 @@ func lowestCurrent(_ *common.Context, input singlePathSpec, n int) (ts.SeriesLis type windowSizeFunc func(stepSize int) int type windowSizeParsed struct { - deltaValue time.Duration - stringValue string + deltaValue time.Duration + stringValue string windowSizeFunc windowSizeFunc } @@ -861,6 +861,48 @@ func logarithm(ctx *common.Context, input singlePathSpec, base int) (ts.SeriesLi return r, nil } +func interpolate(ctx *common.Context, input singlePathSpec, limit int) (ts.SeriesList, error) { + output := make([]*ts.Series, 0, len(input.Values)) + for _, series := range input.Values { + consecutiveNaNs := 0 + numSteps := series.Len() + vals := ts.NewValues(ctx, series.MillisPerStep(), numSteps) + + for i := 0; i < numSteps; i++ { + value := series.ValueAt(i) + vals.SetValueAt(i, value) + + if i == 0 { + continue + } else if math.IsNaN(value) { + consecutiveNaNs++ + } else if consecutiveNaNs == 0 { // have a value but no need to interpolate + continue + } else if math.IsNaN(series.ValueAt(i - consecutiveNaNs - 1)) { //have a value but can't interpolate: reset count + consecutiveNaNs = 0 + continue + } else { + if limit == -1 || consecutiveNaNs <= limit { + for index := i - consecutiveNaNs; index < i; index++ { + lastGoodVal := series.ValueAt(i - consecutiveNaNs - 1) + v := lastGoodVal + float64(index-(i-consecutiveNaNs-1)) * (value-lastGoodVal) /float64(consecutiveNaNs+1) + vals.SetValueAt(index, v) + + } + consecutiveNaNs = 0 + } + } + } + + name := fmt.Sprintf("interpolate(%s)", series.Name()) + newSeries := ts.NewSeries(ctx, name, series.StartTime(), vals) + output = append(output, newSeries) + } + r := ts.SeriesList(input) + r.Values = output + return r, nil +} + // group takes an arbitrary number of pathspecs and adds them to a single timeseries array. // This function is used to pass multiple pathspecs to a function which only takes one func group(_ *common.Context, input multiplePathSpecs) (ts.SeriesList, error) { @@ -1902,6 +1944,9 @@ func init() { MustRegisterFunction(holtWintersForecast) MustRegisterFunction(identity) MustRegisterFunction(integral) + MustRegisterFunction(interpolate).WithDefaultParams(map[uint8]interface{}{ + 2: -1, // limit + }) MustRegisterFunction(isNonNull) MustRegisterFunction(keepLastValue).WithDefaultParams(map[uint8]interface{}{ 2: -1, // limit diff --git a/src/query/graphite/native/builtin_functions_test.go b/src/query/graphite/native/builtin_functions_test.go index 29013c5c92..f4693a4a9a 100644 --- a/src/query/graphite/native/builtin_functions_test.go +++ b/src/query/graphite/native/builtin_functions_test.go @@ -1699,6 +1699,57 @@ func TestIntegral(t *testing.T) { } } +// Takes one metric or a wildcard seriesList, and optionally a limit to the number of ‘None’ values +// to skip over. Continues the line with the last received value when gaps (‘None’ values) +// appear in your data, rather than breaking your line. +func TestInterpolate(t *testing.T) { + ctx := common.NewTestContext() + defer ctx.Close() + + tests := []struct { + values []float64 + output []float64 + }{ + { + []float64{1.0,2.0,3.0,4.0,5.0,6.0,7.0,8.0,9.0,10.0,11.0,12.0,13.0,14.0,15.0,16.0,17.0,18.0,19.0,20.0}, + []float64{1.0,2.0,3.0,4.0,5.0,6.0,7.0,8.0,9.0,10.0,11.0,12.0,13.0,14.0,15.0,16.0,17.0,18.0,19.0,20.0}, + }, + { + []float64{math.NaN(),2.0,math.NaN(),4.0,math.NaN(),6.0,math.NaN(),8.0,math.NaN(),10.0,math.NaN(),12.0,math.NaN(),14.0,math.NaN(),16.0,math.NaN(),18.0,math.NaN(),20.0}, + []float64{math.NaN(),2.0,3.0,4.0,5.0,6.0,7.0,8.0,9.0,10.0,11.0,12.0,13.0,14.0,15.0,16.0,17.0,18.0,19.0,20.0}, + }, + { + []float64{1.0,2.0,math.NaN(),math.NaN(),math.NaN(),6.0,7.0,8.0,9.0,10.0,11.0,12.0,13.0,14.0,15.0,16.0,17.0,math.NaN(),math.NaN(),math.NaN()}, + []float64{1.0,2.0,3.0,4.0,5.0,6.0,7.0,8.0,9.0,10.0,11.0,12.0,13.0,14.0,15.0,16.0,17.0,math.NaN(), math.NaN(), math.NaN()}, + }, + { + []float64{1.0,2.0,3.0,4.0,math.NaN(),6.0,math.NaN(),math.NaN(),9.0,10.0,11.0,math.NaN(),13.0,math.NaN(),math.NaN(),math.NaN(),math.NaN(),18.0,19.0,20.0}, + []float64{1.0,2.0,3.0,4.0,5.0,6.0,7.0,8.0,9.0,10.0,11.0,12.0,13.0,14.0,15.0,16.0,17.0,18.0,19.0,20.0}, + }, + { + []float64{1.0,2.0,math.NaN(),math.NaN(),math.NaN(),6.0,7.0,8.0,9.0,10.0,11.0,12.0,13.0,14.0,15.0,16.0,17.0,18.0,math.NaN(),math.NaN()}, + []float64{1.0,2.0,3.0,4.0,5.0,6.0,7.0,8.0,9.0,10.0,11.0,12.0,13.0,14.0,15.0,16.0,17.0,18.0,math.NaN(), math.NaN()}, + }, + } + + start := time.Now() + step := 100 + for _, test := range tests { + input := []common.TestSeries{{"foo", test.values}} + expected := []common.TestSeries{{"interpolate(foo)", test.output}} + timeSeries := generateSeriesList(ctx, start, input, step) + output, err := interpolate(ctx, singlePathSpec{ + Values: timeSeries, + }, + -1) + require.NoError(t, err) + common.CompareOutputsAndExpected(t, step, start, + expected, output.Values) + } +} + + + func TestDerivative(t *testing.T) { ctx := common.NewTestContext() defer ctx.Close() @@ -2944,6 +2995,7 @@ func TestFunctionsRegistered(t *testing.T) { "holtWintersForecast", "identity", "integral", + "interpolate", "isNonNull", "keepLastValue", "legendValue", From 5283b9335b7eed63ea9bb16ea8e4cc27c450110b Mon Sep 17 00:00:00 2001 From: Theodore Wahle Date: Mon, 21 Sep 2020 11:37:30 -0700 Subject: [PATCH 2/5] Ran go fmt --- .../graphite/native/builtin_functions.go | 5 +++- .../graphite/native/builtin_functions_test.go | 27 ++++++++----------- 2 files changed, 15 insertions(+), 17 deletions(-) diff --git a/src/query/graphite/native/builtin_functions.go b/src/query/graphite/native/builtin_functions.go index c4eb76a21d..0324bb0f98 100644 --- a/src/query/graphite/native/builtin_functions.go +++ b/src/query/graphite/native/builtin_functions.go @@ -861,6 +861,9 @@ func logarithm(ctx *common.Context, input singlePathSpec, base int) (ts.SeriesLi return r, nil } +// Takes one metric or a wildcard seriesList, and optionally a limit to the number of ‘None’ values +// to skip over. Continues the line with the last received value when gaps (‘None’ values) +// appear in your data, rather than breaking your line. func interpolate(ctx *common.Context, input singlePathSpec, limit int) (ts.SeriesList, error) { output := make([]*ts.Series, 0, len(input.Values)) for _, series := range input.Values { @@ -885,7 +888,7 @@ func interpolate(ctx *common.Context, input singlePathSpec, limit int) (ts.Serie if limit == -1 || consecutiveNaNs <= limit { for index := i - consecutiveNaNs; index < i; index++ { lastGoodVal := series.ValueAt(i - consecutiveNaNs - 1) - v := lastGoodVal + float64(index-(i-consecutiveNaNs-1)) * (value-lastGoodVal) /float64(consecutiveNaNs+1) + v := lastGoodVal + float64(index-(i-consecutiveNaNs-1))*(value-lastGoodVal)/float64(consecutiveNaNs+1) vals.SetValueAt(index, v) } diff --git a/src/query/graphite/native/builtin_functions_test.go b/src/query/graphite/native/builtin_functions_test.go index f4693a4a9a..d320543125 100644 --- a/src/query/graphite/native/builtin_functions_test.go +++ b/src/query/graphite/native/builtin_functions_test.go @@ -1699,9 +1699,6 @@ func TestIntegral(t *testing.T) { } } -// Takes one metric or a wildcard seriesList, and optionally a limit to the number of ‘None’ values -// to skip over. Continues the line with the last received value when gaps (‘None’ values) -// appear in your data, rather than breaking your line. func TestInterpolate(t *testing.T) { ctx := common.NewTestContext() defer ctx.Close() @@ -1711,24 +1708,24 @@ func TestInterpolate(t *testing.T) { output []float64 }{ { - []float64{1.0,2.0,3.0,4.0,5.0,6.0,7.0,8.0,9.0,10.0,11.0,12.0,13.0,14.0,15.0,16.0,17.0,18.0,19.0,20.0}, - []float64{1.0,2.0,3.0,4.0,5.0,6.0,7.0,8.0,9.0,10.0,11.0,12.0,13.0,14.0,15.0,16.0,17.0,18.0,19.0,20.0}, + []float64{1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 11.0, 12.0, 13.0, 14.0, 15.0, 16.0, 17.0, 18.0, 19.0, 20.0}, + []float64{1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 11.0, 12.0, 13.0, 14.0, 15.0, 16.0, 17.0, 18.0, 19.0, 20.0}, }, { - []float64{math.NaN(),2.0,math.NaN(),4.0,math.NaN(),6.0,math.NaN(),8.0,math.NaN(),10.0,math.NaN(),12.0,math.NaN(),14.0,math.NaN(),16.0,math.NaN(),18.0,math.NaN(),20.0}, - []float64{math.NaN(),2.0,3.0,4.0,5.0,6.0,7.0,8.0,9.0,10.0,11.0,12.0,13.0,14.0,15.0,16.0,17.0,18.0,19.0,20.0}, + []float64{math.NaN(), 2.0, math.NaN(), 4.0, math.NaN(), 6.0, math.NaN(), 8.0, math.NaN(), 10.0, math.NaN(), 12.0, math.NaN(), 14.0, math.NaN(), 16.0, math.NaN(), 18.0, math.NaN(), 20.0}, + []float64{math.NaN(), 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 11.0, 12.0, 13.0, 14.0, 15.0, 16.0, 17.0, 18.0, 19.0, 20.0}, }, { - []float64{1.0,2.0,math.NaN(),math.NaN(),math.NaN(),6.0,7.0,8.0,9.0,10.0,11.0,12.0,13.0,14.0,15.0,16.0,17.0,math.NaN(),math.NaN(),math.NaN()}, - []float64{1.0,2.0,3.0,4.0,5.0,6.0,7.0,8.0,9.0,10.0,11.0,12.0,13.0,14.0,15.0,16.0,17.0,math.NaN(), math.NaN(), math.NaN()}, + []float64{1.0, 2.0, math.NaN(), math.NaN(), math.NaN(), 6.0, 7.0, 8.0, 9.0, 10.0, 11.0, 12.0, 13.0, 14.0, 15.0, 16.0, 17.0, math.NaN(), math.NaN(), math.NaN()}, + []float64{1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 11.0, 12.0, 13.0, 14.0, 15.0, 16.0, 17.0, math.NaN(), math.NaN(), math.NaN()}, }, { - []float64{1.0,2.0,3.0,4.0,math.NaN(),6.0,math.NaN(),math.NaN(),9.0,10.0,11.0,math.NaN(),13.0,math.NaN(),math.NaN(),math.NaN(),math.NaN(),18.0,19.0,20.0}, - []float64{1.0,2.0,3.0,4.0,5.0,6.0,7.0,8.0,9.0,10.0,11.0,12.0,13.0,14.0,15.0,16.0,17.0,18.0,19.0,20.0}, + []float64{1.0, 2.0, 3.0, 4.0, math.NaN(), 6.0, math.NaN(), math.NaN(), 9.0, 10.0, 11.0, math.NaN(), 13.0, math.NaN(), math.NaN(), math.NaN(), math.NaN(), 18.0, 19.0, 20.0}, + []float64{1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 11.0, 12.0, 13.0, 14.0, 15.0, 16.0, 17.0, 18.0, 19.0, 20.0}, }, { - []float64{1.0,2.0,math.NaN(),math.NaN(),math.NaN(),6.0,7.0,8.0,9.0,10.0,11.0,12.0,13.0,14.0,15.0,16.0,17.0,18.0,math.NaN(),math.NaN()}, - []float64{1.0,2.0,3.0,4.0,5.0,6.0,7.0,8.0,9.0,10.0,11.0,12.0,13.0,14.0,15.0,16.0,17.0,18.0,math.NaN(), math.NaN()}, + []float64{1.0, 2.0, math.NaN(), math.NaN(), math.NaN(), 6.0, 7.0, 8.0, 9.0, 10.0, 11.0, 12.0, 13.0, 14.0, 15.0, 16.0, 17.0, 18.0, math.NaN(), math.NaN()}, + []float64{1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 11.0, 12.0, 13.0, 14.0, 15.0, 16.0, 17.0, 18.0, math.NaN(), math.NaN()}, }, } @@ -1741,15 +1738,13 @@ func TestInterpolate(t *testing.T) { output, err := interpolate(ctx, singlePathSpec{ Values: timeSeries, }, - -1) + -1) require.NoError(t, err) common.CompareOutputsAndExpected(t, step, start, expected, output.Values) } } - - func TestDerivative(t *testing.T) { ctx := common.NewTestContext() defer ctx.Close() From 1f9ce3ae233520a44da649819c94865effe8f488 Mon Sep 17 00:00:00 2001 From: teddywahle <69990143+teddywahle@users.noreply.github.com> Date: Tue, 29 Sep 2020 20:22:12 -0700 Subject: [PATCH 3/5] Update src/query/graphite/native/builtin_functions.go Co-authored-by: arnikola --- .../graphite/native/builtin_functions.go | 47 ++++++++++++------- 1 file changed, 29 insertions(+), 18 deletions(-) diff --git a/src/query/graphite/native/builtin_functions.go b/src/query/graphite/native/builtin_functions.go index 3258939519..bd7a368aa3 100644 --- a/src/query/graphite/native/builtin_functions.go +++ b/src/query/graphite/native/builtin_functions.go @@ -1053,34 +1053,45 @@ func logarithm(ctx *common.Context, input singlePathSpec, base int) (ts.SeriesLi func interpolate(ctx *common.Context, input singlePathSpec, limit int) (ts.SeriesList, error) { output := make([]*ts.Series, 0, len(input.Values)) for _, series := range input.Values { - consecutiveNaNs := 0 - numSteps := series.Len() - vals := ts.NewValues(ctx, series.MillisPerStep(), numSteps) + var ( + consecutiveNaNs = 0 + numSteps = series.Len() + vals = ts.NewValues(ctx, series.MillisPerStep(), numSteps) + firstNonNan = false + ) for i := 0; i < numSteps; i++ { value := series.ValueAt(i) vals.SetValueAt(i, value) - if i == 0 { - continue - } else if math.IsNaN(value) { + if math.IsNaN(value) { + if !firstNonNan { + continue + } + consecutiveNaNs++ - } else if consecutiveNaNs == 0 { // have a value but no need to interpolate - continue - } else if math.IsNaN(series.ValueAt(i - consecutiveNaNs - 1)) { //have a value but can't interpolate: reset count - consecutiveNaNs = 0 + if limit >= 0 && consecutiveNaNs > limit { + consecutiveNaNs = 0 + } + continue } else { - if limit == -1 || consecutiveNaNs <= limit { - for index := i - consecutiveNaNs; index < i; index++ { - lastGoodVal := series.ValueAt(i - consecutiveNaNs - 1) - v := lastGoodVal + float64(index-(i-consecutiveNaNs-1))*(value-lastGoodVal)/float64(consecutiveNaNs+1) - vals.SetValueAt(index, v) + firstNonNan = true + } - } - consecutiveNaNs = 0 - } + if consecutiveNaNs == 0 { + // have a value but no need to interpolate + continue } + + interpolated := series.ValueAt(i - consecutiveNaNs - 1) + interpolateStep := (value - interpolated) / float64(consecutiveNaNs+1) + for index := i - consecutiveNaNs; index < i; index++ { + interpolated = interpolated + interpolateStep + vals.SetValueAt(index, interpolated) + } + + consecutiveNaNs = 0 } name := fmt.Sprintf("interpolate(%s)", series.Name()) From db595837b213f2a0f890b38004b86bc6edda00d9 Mon Sep 17 00:00:00 2001 From: teddywahle Date: Wed, 30 Sep 2020 10:59:32 -0700 Subject: [PATCH 4/5] Added i=0 test case --- src/query/graphite/native/builtin_functions.go | 6 ++++-- .../graphite/native/builtin_functions_test.go | 16 +++++++++++++--- 2 files changed, 17 insertions(+), 5 deletions(-) diff --git a/src/query/graphite/native/builtin_functions.go b/src/query/graphite/native/builtin_functions.go index bd7a368aa3..059701313c 100644 --- a/src/query/graphite/native/builtin_functions.go +++ b/src/query/graphite/native/builtin_functions.go @@ -1047,9 +1047,11 @@ func logarithm(ctx *common.Context, input singlePathSpec, base int) (ts.SeriesLi return r, nil } -// Takes one metric or a wildcard seriesList, and optionally a limit to the number of ‘None’ values +// interpolate takes one metric or a wildcard seriesList, and optionally a limit to the number of ‘None’ values // to skip over. Continues the line with the last received value when gaps (‘None’ values) // appear in your data, rather than breaking your line. +// +// interpolate will not interpolate at the beginning or end of a series, only in the middle func interpolate(ctx *common.Context, input singlePathSpec, limit int) (ts.SeriesList, error) { output := make([]*ts.Series, 0, len(input.Values)) for _, series := range input.Values { @@ -2267,7 +2269,7 @@ func init() { MustRegisterFunction(identity) MustRegisterFunction(integral) MustRegisterFunction(integralByInterval) - MustRegisterFunction(interpolate).WithDefaultParams(map[uint8]interface{}{ + MustRegisterFunction(interpolate).WithDefaultParams(map[uint8]interface{}{ 2: -1, // limit }) MustRegisterFunction(isNonNull) diff --git a/src/query/graphite/native/builtin_functions_test.go b/src/query/graphite/native/builtin_functions_test.go index 1960145bb1..295ab7261c 100644 --- a/src/query/graphite/native/builtin_functions_test.go +++ b/src/query/graphite/native/builtin_functions_test.go @@ -1948,26 +1948,37 @@ func TestInterpolate(t *testing.T) { tests := []struct { values []float64 output []float64 + limit int }{ { []float64{1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 11.0, 12.0, 13.0, 14.0, 15.0, 16.0, 17.0, 18.0, 19.0, 20.0}, []float64{1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 11.0, 12.0, 13.0, 14.0, 15.0, 16.0, 17.0, 18.0, 19.0, 20.0}, + -1, }, { []float64{math.NaN(), 2.0, math.NaN(), 4.0, math.NaN(), 6.0, math.NaN(), 8.0, math.NaN(), 10.0, math.NaN(), 12.0, math.NaN(), 14.0, math.NaN(), 16.0, math.NaN(), 18.0, math.NaN(), 20.0}, []float64{math.NaN(), 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 11.0, 12.0, 13.0, 14.0, 15.0, 16.0, 17.0, 18.0, 19.0, 20.0}, + -1, }, { []float64{1.0, 2.0, math.NaN(), math.NaN(), math.NaN(), 6.0, 7.0, 8.0, 9.0, 10.0, 11.0, 12.0, 13.0, 14.0, 15.0, 16.0, 17.0, math.NaN(), math.NaN(), math.NaN()}, []float64{1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 11.0, 12.0, 13.0, 14.0, 15.0, 16.0, 17.0, math.NaN(), math.NaN(), math.NaN()}, + -1, }, { []float64{1.0, 2.0, 3.0, 4.0, math.NaN(), 6.0, math.NaN(), math.NaN(), 9.0, 10.0, 11.0, math.NaN(), 13.0, math.NaN(), math.NaN(), math.NaN(), math.NaN(), 18.0, 19.0, 20.0}, []float64{1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 11.0, 12.0, 13.0, 14.0, 15.0, 16.0, 17.0, 18.0, 19.0, 20.0}, + -1, }, { []float64{1.0, 2.0, math.NaN(), math.NaN(), math.NaN(), 6.0, 7.0, 8.0, 9.0, 10.0, 11.0, 12.0, 13.0, 14.0, 15.0, 16.0, 17.0, 18.0, math.NaN(), math.NaN()}, []float64{1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 11.0, 12.0, 13.0, 14.0, 15.0, 16.0, 17.0, 18.0, math.NaN(), math.NaN()}, + -1, + }, + { + []float64{1.0, 2.0, math.NaN(), math.NaN(), math.NaN(), math.NaN(), math.NaN(), 8.0, 9.0, 10.0, 11.0, 12.0, 13.0, 14.0, 15.0, 16.0, 17.0, 18.0, math.NaN(), math.NaN()}, + []float64{1.0, 2.0, math.NaN(), math.NaN(), math.NaN(), math.NaN(), math.NaN(), 8.0, 9.0, 10.0, 11.0, 12.0, 13.0, 14.0, 15.0, 16.0, 17.0, 18.0, math.NaN(), math.NaN()}, + 3, }, } @@ -1979,12 +1990,11 @@ func TestInterpolate(t *testing.T) { timeSeries := generateSeriesList(ctx, start, input, step) output, err := interpolate(ctx, singlePathSpec{ Values: timeSeries, - }, - -1) + }, test.limit) require.NoError(t, err) common.CompareOutputsAndExpected(t, step, start, expected, output.Values) - } + } } func TestIntegralByInterval(t *testing.T) { From c7a0a1d0dbd1106351618c7d6030658b9f3d8ef1 Mon Sep 17 00:00:00 2001 From: teddywahle Date: Wed, 30 Sep 2020 11:02:41 -0700 Subject: [PATCH 5/5] added preceding NaNs test case --- src/query/graphite/native/builtin_functions_test.go | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/query/graphite/native/builtin_functions_test.go b/src/query/graphite/native/builtin_functions_test.go index 295ab7261c..e7acf2e271 100644 --- a/src/query/graphite/native/builtin_functions_test.go +++ b/src/query/graphite/native/builtin_functions_test.go @@ -1980,6 +1980,11 @@ func TestInterpolate(t *testing.T) { []float64{1.0, 2.0, math.NaN(), math.NaN(), math.NaN(), math.NaN(), math.NaN(), 8.0, 9.0, 10.0, 11.0, 12.0, 13.0, 14.0, 15.0, 16.0, 17.0, 18.0, math.NaN(), math.NaN()}, 3, }, + { + []float64{math.NaN(), math.NaN(), math.NaN(), math.NaN(), math.NaN(), 6.0, 7.0, 8.0, 9.0, 10.0, 11.0, 12.0, 13.0, 14.0, 15.0, 16.0, 17.0, 18.0, 19.0, 20.0}, + []float64{math.NaN(), math.NaN(), math.NaN(), math.NaN(), math.NaN(), 6.0, 7.0, 8.0, 9.0, 10.0, 11.0, 12.0, 13.0, 14.0, 15.0, 16.0, 17.0, 18.0, 19.0, 20.0}, + -1, + }, } start := time.Now()