influxdb/query/functions/histogram_test.go

346 lines
13 KiB
Go

package functions_test
import (
"math"
"testing"
"github.com/influxdata/platform/query"
"github.com/influxdata/platform/query/execute"
"github.com/influxdata/platform/query/execute/executetest"
"github.com/influxdata/platform/query/functions"
"github.com/influxdata/platform/query/querytest"
)
func TestHistogramOperation_Marshaling(t *testing.T) {
data := []byte(`{"id":"histogram","kind":"histogram","spec":{"column":"_value"}}`)
op := &query.Operation{
ID: "histogram",
Spec: &functions.HistogramOpSpec{
Column: "_value",
},
}
querytest.OperationMarshalingTestHelper(t, data, op)
}
func TestHistogram_PassThrough(t *testing.T) {
executetest.TransformationPassThroughTestHelper(t, func(d execute.Dataset, c execute.TableBuilderCache) execute.Transformation {
s := functions.NewHistogramTransformation(
d,
c,
&functions.HistogramProcedureSpec{},
)
return s
})
}
func TestHistogram_Process(t *testing.T) {
testCases := []struct {
name string
spec *functions.HistogramProcedureSpec
data []query.Table
want []*executetest.Table
}{
{
name: "linear",
spec: &functions.HistogramProcedureSpec{HistogramOpSpec: functions.HistogramOpSpec{
Column: "_value",
UpperBoundColumn: "le",
CountColumn: "_value",
Buckets: []float64{0, 10, 20, 30, 40},
}},
data: []query.Table{&executetest.Table{
KeyCols: []string{"_start", "_stop"},
ColMeta: []query.ColMeta{
{Label: "_start", Type: query.TTime},
{Label: "_stop", Type: query.TTime},
{Label: "_time", Type: query.TTime},
{Label: "_value", Type: query.TFloat},
},
Data: [][]interface{}{
{execute.Time(1), execute.Time(3), execute.Time(1), 02.0},
{execute.Time(1), execute.Time(3), execute.Time(2), 31.0},
{execute.Time(1), execute.Time(3), execute.Time(2), 12.0},
{execute.Time(1), execute.Time(3), execute.Time(2), 38.0},
{execute.Time(1), execute.Time(3), execute.Time(2), 24.0},
{execute.Time(1), execute.Time(3), execute.Time(2), 40.0},
{execute.Time(1), execute.Time(3), execute.Time(2), 30.0},
{execute.Time(1), execute.Time(3), execute.Time(2), 28.0},
{execute.Time(1), execute.Time(3), execute.Time(2), 17.0},
{execute.Time(1), execute.Time(3), execute.Time(2), 08.0},
},
}},
want: []*executetest.Table{{
KeyCols: []string{"_start", "_stop"},
ColMeta: []query.ColMeta{
{Label: "_start", Type: query.TTime},
{Label: "_stop", Type: query.TTime},
{Label: "le", Type: query.TFloat},
{Label: "_value", Type: query.TFloat},
},
Data: [][]interface{}{
{execute.Time(1), execute.Time(3), 0.0, 0.0},
{execute.Time(1), execute.Time(3), 10.0, 2.0},
{execute.Time(1), execute.Time(3), 20.0, 4.0},
{execute.Time(1), execute.Time(3), 30.0, 7.0},
{execute.Time(1), execute.Time(3), 40.0, 10.0},
},
}},
},
{
name: "linear+infinity",
spec: &functions.HistogramProcedureSpec{HistogramOpSpec: functions.HistogramOpSpec{
Column: "_value",
UpperBoundColumn: "le",
CountColumn: "_value",
Buckets: []float64{0, 10, 20, 30, 40, math.Inf(1)},
}},
data: []query.Table{&executetest.Table{
KeyCols: []string{"_start", "_stop"},
ColMeta: []query.ColMeta{
{Label: "_start", Type: query.TTime},
{Label: "_stop", Type: query.TTime},
{Label: "_time", Type: query.TTime},
{Label: "_value", Type: query.TFloat},
},
Data: [][]interface{}{
{execute.Time(1), execute.Time(3), execute.Time(1), 02.0},
{execute.Time(1), execute.Time(3), execute.Time(2), 31.0},
{execute.Time(1), execute.Time(3), execute.Time(2), 12.0},
{execute.Time(1), execute.Time(3), execute.Time(2), 38.0},
{execute.Time(1), execute.Time(3), execute.Time(2), 24.0},
{execute.Time(1), execute.Time(3), execute.Time(2), 40.0},
{execute.Time(1), execute.Time(3), execute.Time(2), 30.0},
{execute.Time(1), execute.Time(3), execute.Time(2), 28.0},
{execute.Time(1), execute.Time(3), execute.Time(2), 17.0},
{execute.Time(1), execute.Time(3), execute.Time(2), 08.0},
{execute.Time(1), execute.Time(3), execute.Time(2), 68.0},
},
}},
want: []*executetest.Table{{
KeyCols: []string{"_start", "_stop"},
ColMeta: []query.ColMeta{
{Label: "_start", Type: query.TTime},
{Label: "_stop", Type: query.TTime},
{Label: "le", Type: query.TFloat},
{Label: "_value", Type: query.TFloat},
},
Data: [][]interface{}{
{execute.Time(1), execute.Time(3), 0.0, 0.0},
{execute.Time(1), execute.Time(3), 10.0, 2.0},
{execute.Time(1), execute.Time(3), 20.0, 4.0},
{execute.Time(1), execute.Time(3), 30.0, 7.0},
{execute.Time(1), execute.Time(3), 40.0, 10.0},
{execute.Time(1), execute.Time(3), math.Inf(1), 11.0},
},
}},
},
{
name: "linear+normalize",
spec: &functions.HistogramProcedureSpec{HistogramOpSpec: functions.HistogramOpSpec{
Column: "_value",
UpperBoundColumn: "le",
CountColumn: "_value",
Buckets: []float64{0, 10, 20, 30, 40},
Normalize: true,
}},
data: []query.Table{&executetest.Table{
KeyCols: []string{"_start", "_stop"},
ColMeta: []query.ColMeta{
{Label: "_start", Type: query.TTime},
{Label: "_stop", Type: query.TTime},
{Label: "_time", Type: query.TTime},
{Label: "_value", Type: query.TFloat},
},
Data: [][]interface{}{
{execute.Time(1), execute.Time(3), execute.Time(1), 02.0},
{execute.Time(1), execute.Time(3), execute.Time(2), 31.0},
{execute.Time(1), execute.Time(3), execute.Time(2), 12.0},
{execute.Time(1), execute.Time(3), execute.Time(2), 38.0},
{execute.Time(1), execute.Time(3), execute.Time(2), 24.0},
{execute.Time(1), execute.Time(3), execute.Time(2), 40.0},
{execute.Time(1), execute.Time(3), execute.Time(2), 30.0},
{execute.Time(1), execute.Time(3), execute.Time(2), 28.0},
{execute.Time(1), execute.Time(3), execute.Time(2), 17.0},
{execute.Time(1), execute.Time(3), execute.Time(2), 08.0},
},
}},
want: []*executetest.Table{{
KeyCols: []string{"_start", "_stop"},
ColMeta: []query.ColMeta{
{Label: "_start", Type: query.TTime},
{Label: "_stop", Type: query.TTime},
{Label: "le", Type: query.TFloat},
{Label: "_value", Type: query.TFloat},
},
Data: [][]interface{}{
{execute.Time(1), execute.Time(3), 0.0, 0.0},
{execute.Time(1), execute.Time(3), 10.0, 0.2},
{execute.Time(1), execute.Time(3), 20.0, 0.4},
{execute.Time(1), execute.Time(3), 30.0, 0.7},
{execute.Time(1), execute.Time(3), 40.0, 1.0},
},
}},
},
{
name: "logarithmic",
spec: &functions.HistogramProcedureSpec{HistogramOpSpec: functions.HistogramOpSpec{
Column: "_value",
UpperBoundColumn: "le",
CountColumn: "_value",
Buckets: []float64{1, 2, 4, 8, 16, 32, 64},
}},
data: []query.Table{&executetest.Table{
KeyCols: []string{"_start", "_stop"},
ColMeta: []query.ColMeta{
{Label: "_start", Type: query.TTime},
{Label: "_stop", Type: query.TTime},
{Label: "_time", Type: query.TTime},
{Label: "_value", Type: query.TFloat},
},
Data: [][]interface{}{
{execute.Time(1), execute.Time(3), execute.Time(1), 02.0},
{execute.Time(1), execute.Time(3), execute.Time(2), 31.0},
{execute.Time(1), execute.Time(3), execute.Time(2), 12.0},
{execute.Time(1), execute.Time(3), execute.Time(2), 38.0},
{execute.Time(1), execute.Time(3), execute.Time(2), 24.0},
{execute.Time(1), execute.Time(3), execute.Time(2), 40.0},
{execute.Time(1), execute.Time(3), execute.Time(2), 30.0},
{execute.Time(1), execute.Time(3), execute.Time(2), 28.0},
{execute.Time(1), execute.Time(3), execute.Time(2), 17.0},
{execute.Time(1), execute.Time(3), execute.Time(2), 08.0},
},
}},
want: []*executetest.Table{{
KeyCols: []string{"_start", "_stop"},
ColMeta: []query.ColMeta{
{Label: "_start", Type: query.TTime},
{Label: "_stop", Type: query.TTime},
{Label: "le", Type: query.TFloat},
{Label: "_value", Type: query.TFloat},
},
Data: [][]interface{}{
{execute.Time(1), execute.Time(3), 1.0, 0.0},
{execute.Time(1), execute.Time(3), 2.0, 1.0},
{execute.Time(1), execute.Time(3), 4.0, 1.0},
{execute.Time(1), execute.Time(3), 8.0, 2.0},
{execute.Time(1), execute.Time(3), 16.0, 3.0},
{execute.Time(1), execute.Time(3), 32.0, 8.0},
{execute.Time(1), execute.Time(3), 64.0, 10.0},
},
}},
},
{
name: "logarithmic unsorted",
spec: &functions.HistogramProcedureSpec{HistogramOpSpec: functions.HistogramOpSpec{
Column: "_value",
UpperBoundColumn: "le",
CountColumn: "_value",
Buckets: []float64{1, 64, 2, 4, 16, 8, 32},
}},
data: []query.Table{&executetest.Table{
KeyCols: []string{"_start", "_stop"},
ColMeta: []query.ColMeta{
{Label: "_start", Type: query.TTime},
{Label: "_stop", Type: query.TTime},
{Label: "_time", Type: query.TTime},
{Label: "_value", Type: query.TFloat},
},
Data: [][]interface{}{
{execute.Time(1), execute.Time(3), execute.Time(1), 02.0},
{execute.Time(1), execute.Time(3), execute.Time(2), 31.0},
{execute.Time(1), execute.Time(3), execute.Time(2), 12.0},
{execute.Time(1), execute.Time(3), execute.Time(2), 38.0},
{execute.Time(1), execute.Time(3), execute.Time(2), 24.0},
{execute.Time(1), execute.Time(3), execute.Time(2), 40.0},
{execute.Time(1), execute.Time(3), execute.Time(2), 30.0},
{execute.Time(1), execute.Time(3), execute.Time(2), 28.0},
{execute.Time(1), execute.Time(3), execute.Time(2), 17.0},
{execute.Time(1), execute.Time(3), execute.Time(2), 08.0},
},
}},
want: []*executetest.Table{{
KeyCols: []string{"_start", "_stop"},
ColMeta: []query.ColMeta{
{Label: "_start", Type: query.TTime},
{Label: "_stop", Type: query.TTime},
{Label: "le", Type: query.TFloat},
{Label: "_value", Type: query.TFloat},
},
Data: [][]interface{}{
{execute.Time(1), execute.Time(3), 1.0, 0.0},
{execute.Time(1), execute.Time(3), 2.0, 1.0},
{execute.Time(1), execute.Time(3), 4.0, 1.0},
{execute.Time(1), execute.Time(3), 8.0, 2.0},
{execute.Time(1), execute.Time(3), 16.0, 3.0},
{execute.Time(1), execute.Time(3), 32.0, 8.0},
{execute.Time(1), execute.Time(3), 64.0, 10.0},
},
}},
},
{
name: "fibonacci",
spec: &functions.HistogramProcedureSpec{HistogramOpSpec: functions.HistogramOpSpec{
Column: "_value",
UpperBoundColumn: "le",
CountColumn: "_value",
Buckets: []float64{1, 2, 3, 5, 8, 13, 21, 34, 55},
}},
data: []query.Table{&executetest.Table{
KeyCols: []string{"_start", "_stop"},
ColMeta: []query.ColMeta{
{Label: "_start", Type: query.TTime},
{Label: "_stop", Type: query.TTime},
{Label: "_time", Type: query.TTime},
{Label: "_value", Type: query.TFloat},
},
Data: [][]interface{}{
{execute.Time(1), execute.Time(3), execute.Time(1), 02.0},
{execute.Time(1), execute.Time(3), execute.Time(2), 31.0},
{execute.Time(1), execute.Time(3), execute.Time(2), 12.0},
{execute.Time(1), execute.Time(3), execute.Time(2), 38.0},
{execute.Time(1), execute.Time(3), execute.Time(2), 24.0},
{execute.Time(1), execute.Time(3), execute.Time(2), 40.0},
{execute.Time(1), execute.Time(3), execute.Time(2), 30.0},
{execute.Time(1), execute.Time(3), execute.Time(2), 28.0},
{execute.Time(1), execute.Time(3), execute.Time(2), 17.0},
{execute.Time(1), execute.Time(3), execute.Time(2), 08.0},
},
}},
want: []*executetest.Table{{
KeyCols: []string{"_start", "_stop"},
ColMeta: []query.ColMeta{
{Label: "_start", Type: query.TTime},
{Label: "_stop", Type: query.TTime},
{Label: "le", Type: query.TFloat},
{Label: "_value", Type: query.TFloat},
},
Data: [][]interface{}{
{execute.Time(1), execute.Time(3), 1.0, 0.0},
{execute.Time(1), execute.Time(3), 2.0, 1.0},
{execute.Time(1), execute.Time(3), 3.0, 1.0},
{execute.Time(1), execute.Time(3), 5.0, 1.0},
{execute.Time(1), execute.Time(3), 8.0, 2.0},
{execute.Time(1), execute.Time(3), 13.0, 3.0},
{execute.Time(1), execute.Time(3), 21.0, 4.0},
{execute.Time(1), execute.Time(3), 34.0, 8.0},
{execute.Time(1), execute.Time(3), 55.0, 10.0},
},
}},
},
}
for _, tc := range testCases {
tc := tc
t.Run(tc.name, func(t *testing.T) {
executetest.ProcessTestHelper(
t,
tc.data,
tc.want,
nil,
func(d execute.Dataset, c execute.TableBuilderCache) execute.Transformation {
return functions.NewHistogramTransformation(d, c, tc.spec)
},
)
})
}
}