influxdb/query/functions/window_test.go

643 lines
28 KiB
Go

package functions_test
import (
"sort"
"strconv"
"testing"
"time"
"github.com/google/go-cmp/cmp"
"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 TestWindow_NewQuery(t *testing.T) {
tests := []querytest.NewQueryTestCase{
{
Name: "from with window",
Raw: `from(db:"mydb") |> window(start:-4h, every:1h)`,
Want: &query.Spec{
Operations: []*query.Operation{
{
ID: "from0",
Spec: &functions.FromOpSpec{
Database: "mydb",
},
},
{
ID: "window1",
Spec: &functions.WindowOpSpec{
Start: query.Time{
Relative: -4 * time.Hour,
IsRelative: true,
},
Every: query.Duration(time.Hour),
Period: query.Duration(time.Hour),
TimeCol: execute.DefaultTimeColLabel,
StartColLabel: execute.DefaultStartColLabel,
StopColLabel: execute.DefaultStopColLabel,
},
},
},
Edges: []query.Edge{
{Parent: "from0", Child: "window1"},
},
},
},
}
for _, tc := range tests {
tc := tc
t.Run(tc.Name, func(t *testing.T) {
t.Parallel()
querytest.NewQueryTestHelper(t, tc)
})
}
}
func TestWindowOperation_Marshaling(t *testing.T) {
//TODO: Test marshalling of triggerspec
data := []byte(`{"id":"window","kind":"window","spec":{"every":"1m","period":"1h","start":"-4h","round":"1s"}}`)
op := &query.Operation{
ID: "window",
Spec: &functions.WindowOpSpec{
Every: query.Duration(time.Minute),
Period: query.Duration(time.Hour),
Start: query.Time{
Relative: -4 * time.Hour,
IsRelative: true,
},
Round: query.Duration(time.Second),
},
}
querytest.OperationMarshalingTestHelper(t, data, op)
}
func TestFixedWindow_PassThrough(t *testing.T) {
executetest.TransformationPassThroughTestHelper(t, func(d execute.Dataset, c execute.TableBuilderCache) execute.Transformation {
fw := functions.NewFixedWindowTransformation(
d,
c,
execute.Bounds{},
execute.Window{
Every: execute.Duration(time.Minute),
Period: execute.Duration(time.Minute),
},
false,
execute.DefaultTimeColLabel,
execute.DefaultStartColLabel,
execute.DefaultStopColLabel,
)
return fw
})
}
func TestFixedWindow_Process(t *testing.T) {
testCases := []struct {
name string
valueCol query.ColMeta
start execute.Time
every, period execute.Duration
num int
want func(start execute.Time) []*executetest.Table
}{
{
name: "nonoverlapping_nonaligned",
valueCol: query.ColMeta{Label: "_value", Type: query.TFloat},
// Use a time that is *not* aligned with the every/period durations of the window
start: execute.Time(time.Date(2017, 10, 10, 10, 10, 10, 10, time.UTC).UnixNano()),
every: execute.Duration(time.Minute),
period: execute.Duration(time.Minute),
num: 15,
want: func(start execute.Time) []*executetest.Table {
return []*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{}{
{start, start + execute.Time(time.Minute), start, 0.0},
{start, start + execute.Time(time.Minute), start + execute.Time(10*time.Second), 1.0},
{start, start + execute.Time(time.Minute), start + execute.Time(20*time.Second), 2.0},
{start, start + execute.Time(time.Minute), start + execute.Time(30*time.Second), 3.0},
{start, start + execute.Time(time.Minute), start + execute.Time(40*time.Second), 4.0},
{start, start + execute.Time(time.Minute), start + execute.Time(50*time.Second), 5.0},
},
},
{
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{}{
{start + execute.Time(1*time.Minute), start + execute.Time(2*time.Minute), start + execute.Time(60*time.Second), 6.0},
{start + execute.Time(1*time.Minute), start + execute.Time(2*time.Minute), start + execute.Time(70*time.Second), 7.0},
{start + execute.Time(1*time.Minute), start + execute.Time(2*time.Minute), start + execute.Time(80*time.Second), 8.0},
{start + execute.Time(1*time.Minute), start + execute.Time(2*time.Minute), start + execute.Time(90*time.Second), 9.0},
{start + execute.Time(1*time.Minute), start + execute.Time(2*time.Minute), start + execute.Time(100*time.Second), 10.0},
{start + execute.Time(1*time.Minute), start + execute.Time(2*time.Minute), start + execute.Time(110*time.Second), 11.0},
},
},
{
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{}{
{start + execute.Time(2*time.Minute), start + execute.Time(3*time.Minute), start + execute.Time(120*time.Second), 12.0},
{start + execute.Time(2*time.Minute), start + execute.Time(3*time.Minute), start + execute.Time(130*time.Second), 13.0},
{start + execute.Time(2*time.Minute), start + execute.Time(3*time.Minute), start + execute.Time(140*time.Second), 14.0},
},
},
}
},
},
{
name: "nonoverlapping_aligned",
valueCol: query.ColMeta{Label: "_value", Type: query.TFloat},
// Use a time that is aligned with the every/period durations of the window
start: execute.Time(time.Date(2017, 10, 10, 10, 0, 0, 0, time.UTC).UnixNano()),
every: execute.Duration(time.Minute),
period: execute.Duration(time.Minute),
num: 15,
want: func(start execute.Time) []*executetest.Table {
return []*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{}{
{start, start + execute.Time(time.Minute), start, 0.0},
{start, start + execute.Time(time.Minute), start + execute.Time(10*time.Second), 1.0},
{start, start + execute.Time(time.Minute), start + execute.Time(20*time.Second), 2.0},
{start, start + execute.Time(time.Minute), start + execute.Time(30*time.Second), 3.0},
{start, start + execute.Time(time.Minute), start + execute.Time(40*time.Second), 4.0},
{start, start + execute.Time(time.Minute), start + execute.Time(50*time.Second), 5.0},
},
},
{
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{}{
{start + execute.Time(1*time.Minute), start + execute.Time(2*time.Minute), start + execute.Time(60*time.Second), 6.0},
{start + execute.Time(1*time.Minute), start + execute.Time(2*time.Minute), start + execute.Time(70*time.Second), 7.0},
{start + execute.Time(1*time.Minute), start + execute.Time(2*time.Minute), start + execute.Time(80*time.Second), 8.0},
{start + execute.Time(1*time.Minute), start + execute.Time(2*time.Minute), start + execute.Time(90*time.Second), 9.0},
{start + execute.Time(1*time.Minute), start + execute.Time(2*time.Minute), start + execute.Time(100*time.Second), 10.0},
{start + execute.Time(1*time.Minute), start + execute.Time(2*time.Minute), start + execute.Time(110*time.Second), 11.0},
},
},
{
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{}{
{start + execute.Time(2*time.Minute), start + execute.Time(3*time.Minute), start + execute.Time(120*time.Second), 12.0},
{start + execute.Time(2*time.Minute), start + execute.Time(3*time.Minute), start + execute.Time(130*time.Second), 13.0},
{start + execute.Time(2*time.Minute), start + execute.Time(3*time.Minute), start + execute.Time(140*time.Second), 14.0},
},
},
}
},
},
{
name: "overlapping_nonaligned",
valueCol: query.ColMeta{Label: "_value", Type: query.TFloat},
// Use a time that is *not* aligned with the every/period durations of the window
start: execute.Time(time.Date(2017, 10, 10, 10, 10, 10, 10, time.UTC).UnixNano()),
every: execute.Duration(time.Minute),
period: execute.Duration(2 * time.Minute),
num: 15,
want: func(start execute.Time) []*executetest.Table {
return []*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{}{
{start, start + execute.Time(time.Minute), start, 0.0},
{start, start + execute.Time(time.Minute), start + execute.Time(10*time.Second), 1.0},
{start, start + execute.Time(time.Minute), start + execute.Time(20*time.Second), 2.0},
{start, start + execute.Time(time.Minute), start + execute.Time(30*time.Second), 3.0},
{start, start + execute.Time(time.Minute), start + execute.Time(40*time.Second), 4.0},
{start, start + execute.Time(time.Minute), start + execute.Time(50*time.Second), 5.0},
},
},
{
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{}{
{start, start + execute.Time(2*time.Minute), start, 0.0},
{start, start + execute.Time(2*time.Minute), start + execute.Time(10*time.Second), 1.0},
{start, start + execute.Time(2*time.Minute), start + execute.Time(20*time.Second), 2.0},
{start, start + execute.Time(2*time.Minute), start + execute.Time(30*time.Second), 3.0},
{start, start + execute.Time(2*time.Minute), start + execute.Time(40*time.Second), 4.0},
{start, start + execute.Time(2*time.Minute), start + execute.Time(50*time.Second), 5.0},
{start, start + execute.Time(2*time.Minute), start + execute.Time(60*time.Second), 6.0},
{start, start + execute.Time(2*time.Minute), start + execute.Time(70*time.Second), 7.0},
{start, start + execute.Time(2*time.Minute), start + execute.Time(80*time.Second), 8.0},
{start, start + execute.Time(2*time.Minute), start + execute.Time(90*time.Second), 9.0},
{start, start + execute.Time(2*time.Minute), start + execute.Time(100*time.Second), 10.0},
{start, start + execute.Time(2*time.Minute), start + execute.Time(110*time.Second), 11.0},
},
},
{
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{}{
{start + execute.Time(1*time.Minute), start + execute.Time(3*time.Minute), start + execute.Time(60*time.Second), 6.0},
{start + execute.Time(1*time.Minute), start + execute.Time(3*time.Minute), start + execute.Time(70*time.Second), 7.0},
{start + execute.Time(1*time.Minute), start + execute.Time(3*time.Minute), start + execute.Time(80*time.Second), 8.0},
{start + execute.Time(1*time.Minute), start + execute.Time(3*time.Minute), start + execute.Time(90*time.Second), 9.0},
{start + execute.Time(1*time.Minute), start + execute.Time(3*time.Minute), start + execute.Time(100*time.Second), 10.0},
{start + execute.Time(1*time.Minute), start + execute.Time(3*time.Minute), start + execute.Time(110*time.Second), 11.0},
{start + execute.Time(1*time.Minute), start + execute.Time(3*time.Minute), start + execute.Time(120*time.Second), 12.0},
{start + execute.Time(1*time.Minute), start + execute.Time(3*time.Minute), start + execute.Time(130*time.Second), 13.0},
{start + execute.Time(1*time.Minute), start + execute.Time(3*time.Minute), start + execute.Time(140*time.Second), 14.0},
},
},
{
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{}{
{start + execute.Time(2*time.Minute), start + execute.Time(4*time.Minute), start + execute.Time(120*time.Second), 12.0},
{start + execute.Time(2*time.Minute), start + execute.Time(4*time.Minute), start + execute.Time(130*time.Second), 13.0},
{start + execute.Time(2*time.Minute), start + execute.Time(4*time.Minute), start + execute.Time(140*time.Second), 14.0},
},
},
}
},
},
{
name: "overlapping_aligned",
valueCol: query.ColMeta{Label: "_value", Type: query.TFloat},
// Use a time that is aligned with the every/period durations of the window
start: execute.Time(time.Date(2017, 10, 10, 10, 0, 0, 0, time.UTC).UnixNano()),
every: execute.Duration(time.Minute),
period: execute.Duration(2 * time.Minute),
num: 15,
want: func(start execute.Time) []*executetest.Table {
return []*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{}{
{start, start + execute.Time(time.Minute), start, 0.0},
{start, start + execute.Time(time.Minute), start + execute.Time(10*time.Second), 1.0},
{start, start + execute.Time(time.Minute), start + execute.Time(20*time.Second), 2.0},
{start, start + execute.Time(time.Minute), start + execute.Time(30*time.Second), 3.0},
{start, start + execute.Time(time.Minute), start + execute.Time(40*time.Second), 4.0},
{start, start + execute.Time(time.Minute), start + execute.Time(50*time.Second), 5.0},
},
},
{
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{}{
{start, start + execute.Time(2*time.Minute), start, 0.0},
{start, start + execute.Time(2*time.Minute), start + execute.Time(10*time.Second), 1.0},
{start, start + execute.Time(2*time.Minute), start + execute.Time(20*time.Second), 2.0},
{start, start + execute.Time(2*time.Minute), start + execute.Time(30*time.Second), 3.0},
{start, start + execute.Time(2*time.Minute), start + execute.Time(40*time.Second), 4.0},
{start, start + execute.Time(2*time.Minute), start + execute.Time(50*time.Second), 5.0},
{start, start + execute.Time(2*time.Minute), start + execute.Time(60*time.Second), 6.0},
{start, start + execute.Time(2*time.Minute), start + execute.Time(70*time.Second), 7.0},
{start, start + execute.Time(2*time.Minute), start + execute.Time(80*time.Second), 8.0},
{start, start + execute.Time(2*time.Minute), start + execute.Time(90*time.Second), 9.0},
{start, start + execute.Time(2*time.Minute), start + execute.Time(100*time.Second), 10.0},
{start, start + execute.Time(2*time.Minute), start + execute.Time(110*time.Second), 11.0},
},
},
{
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{}{
{start + execute.Time(1*time.Minute), start + execute.Time(3*time.Minute), start + execute.Time(60*time.Second), 6.0},
{start + execute.Time(1*time.Minute), start + execute.Time(3*time.Minute), start + execute.Time(70*time.Second), 7.0},
{start + execute.Time(1*time.Minute), start + execute.Time(3*time.Minute), start + execute.Time(80*time.Second), 8.0},
{start + execute.Time(1*time.Minute), start + execute.Time(3*time.Minute), start + execute.Time(90*time.Second), 9.0},
{start + execute.Time(1*time.Minute), start + execute.Time(3*time.Minute), start + execute.Time(100*time.Second), 10.0},
{start + execute.Time(1*time.Minute), start + execute.Time(3*time.Minute), start + execute.Time(110*time.Second), 11.0},
{start + execute.Time(1*time.Minute), start + execute.Time(3*time.Minute), start + execute.Time(120*time.Second), 12.0},
{start + execute.Time(1*time.Minute), start + execute.Time(3*time.Minute), start + execute.Time(130*time.Second), 13.0},
{start + execute.Time(1*time.Minute), start + execute.Time(3*time.Minute), start + execute.Time(140*time.Second), 14.0},
},
},
{
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{}{
{start + execute.Time(2*time.Minute), start + execute.Time(4*time.Minute), start + execute.Time(120*time.Second), 12.0},
{start + execute.Time(2*time.Minute), start + execute.Time(4*time.Minute), start + execute.Time(130*time.Second), 13.0},
{start + execute.Time(2*time.Minute), start + execute.Time(4*time.Minute), start + execute.Time(140*time.Second), 14.0},
},
},
}
},
},
{
name: "underlapping_nonaligned",
valueCol: query.ColMeta{Label: "_value", Type: query.TFloat},
// Use a time that is *not* aligned with the every/period durations of the window
start: execute.Time(time.Date(2017, 10, 10, 10, 10, 10, 10, time.UTC).UnixNano()),
every: execute.Duration(2 * time.Minute),
period: execute.Duration(time.Minute),
num: 24,
want: func(start execute.Time) []*executetest.Table {
return []*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{}{
{start + 1*execute.Time(time.Minute), start + 2*execute.Time(time.Minute), start + execute.Time(60*time.Second), 6.0},
{start + 1*execute.Time(time.Minute), start + 2*execute.Time(time.Minute), start + execute.Time(70*time.Second), 7.0},
{start + 1*execute.Time(time.Minute), start + 2*execute.Time(time.Minute), start + execute.Time(80*time.Second), 8.0},
{start + 1*execute.Time(time.Minute), start + 2*execute.Time(time.Minute), start + execute.Time(90*time.Second), 9.0},
{start + 1*execute.Time(time.Minute), start + 2*execute.Time(time.Minute), start + execute.Time(100*time.Second), 10.0},
{start + 1*execute.Time(time.Minute), start + 2*execute.Time(time.Minute), start + execute.Time(110*time.Second), 11.0},
},
},
{
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{}{
{start + execute.Time(3*time.Minute), start + execute.Time(4*time.Minute), start + execute.Time(180*time.Second), 18.0},
{start + execute.Time(3*time.Minute), start + execute.Time(4*time.Minute), start + execute.Time(190*time.Second), 19.0},
{start + execute.Time(3*time.Minute), start + execute.Time(4*time.Minute), start + execute.Time(200*time.Second), 20.0},
{start + execute.Time(3*time.Minute), start + execute.Time(4*time.Minute), start + execute.Time(210*time.Second), 21.0},
{start + execute.Time(3*time.Minute), start + execute.Time(4*time.Minute), start + execute.Time(220*time.Second), 22.0},
{start + execute.Time(3*time.Minute), start + execute.Time(4*time.Minute), start + execute.Time(230*time.Second), 23.0},
},
},
}
},
},
{
name: "underlapping_aligned",
valueCol: query.ColMeta{Label: "_value", Type: query.TFloat},
// Use a time that is aligned with the every/period durations of the window
start: execute.Time(time.Date(2017, 10, 10, 10, 0, 0, 0, time.UTC).UnixNano()),
every: execute.Duration(2 * time.Minute),
period: execute.Duration(time.Minute),
num: 24,
want: func(start execute.Time) []*executetest.Table {
return []*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{}{
{start + 1*execute.Time(time.Minute), start + 2*execute.Time(time.Minute), start + execute.Time(60*time.Second), 6.0},
{start + 1*execute.Time(time.Minute), start + 2*execute.Time(time.Minute), start + execute.Time(70*time.Second), 7.0},
{start + 1*execute.Time(time.Minute), start + 2*execute.Time(time.Minute), start + execute.Time(80*time.Second), 8.0},
{start + 1*execute.Time(time.Minute), start + 2*execute.Time(time.Minute), start + execute.Time(90*time.Second), 9.0},
{start + 1*execute.Time(time.Minute), start + 2*execute.Time(time.Minute), start + execute.Time(100*time.Second), 10.0},
{start + 1*execute.Time(time.Minute), start + 2*execute.Time(time.Minute), start + execute.Time(110*time.Second), 11.0},
},
},
{
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{}{
{start + execute.Time(3*time.Minute), start + execute.Time(4*time.Minute), start + execute.Time(180*time.Second), 18.0},
{start + execute.Time(3*time.Minute), start + execute.Time(4*time.Minute), start + execute.Time(190*time.Second), 19.0},
{start + execute.Time(3*time.Minute), start + execute.Time(4*time.Minute), start + execute.Time(200*time.Second), 20.0},
{start + execute.Time(3*time.Minute), start + execute.Time(4*time.Minute), start + execute.Time(210*time.Second), 21.0},
{start + execute.Time(3*time.Minute), start + execute.Time(4*time.Minute), start + execute.Time(220*time.Second), 22.0},
{start + execute.Time(3*time.Minute), start + execute.Time(4*time.Minute), start + execute.Time(230*time.Second), 23.0},
},
},
}
},
},
{
name: "nonoverlapping_aligned_int",
valueCol: query.ColMeta{Label: "_value", Type: query.TInt},
// Use a time that is aligned with the every/period durations of the window
start: execute.Time(time.Date(2017, 10, 10, 10, 0, 0, 0, time.UTC).UnixNano()),
every: execute.Duration(time.Minute),
period: execute.Duration(time.Minute),
num: 15,
want: func(start execute.Time) []*executetest.Table {
return []*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.TInt},
},
Data: [][]interface{}{
{start, start + execute.Time(time.Minute), start, int64(0.0)},
{start, start + execute.Time(time.Minute), start + execute.Time(10*time.Second), int64(1)},
{start, start + execute.Time(time.Minute), start + execute.Time(20*time.Second), int64(2)},
{start, start + execute.Time(time.Minute), start + execute.Time(30*time.Second), int64(3)},
{start, start + execute.Time(time.Minute), start + execute.Time(40*time.Second), int64(4)},
{start, start + execute.Time(time.Minute), start + execute.Time(50*time.Second), int64(5)},
},
},
{
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.TInt},
},
Data: [][]interface{}{
{start + execute.Time(1*time.Minute), start + execute.Time(2*time.Minute), start + execute.Time(60*time.Second), int64(6)},
{start + execute.Time(1*time.Minute), start + execute.Time(2*time.Minute), start + execute.Time(70*time.Second), int64(7)},
{start + execute.Time(1*time.Minute), start + execute.Time(2*time.Minute), start + execute.Time(80*time.Second), int64(8)},
{start + execute.Time(1*time.Minute), start + execute.Time(2*time.Minute), start + execute.Time(90*time.Second), int64(9)},
{start + execute.Time(1*time.Minute), start + execute.Time(2*time.Minute), start + execute.Time(100*time.Second), int64(10)},
{start + execute.Time(1*time.Minute), start + execute.Time(2*time.Minute), start + execute.Time(110*time.Second), int64(11)},
},
},
{
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.TInt},
},
Data: [][]interface{}{
{start + execute.Time(2*time.Minute), start + execute.Time(3*time.Minute), start + execute.Time(120*time.Second), int64(12)},
{start + execute.Time(2*time.Minute), start + execute.Time(3*time.Minute), start + execute.Time(130*time.Second), int64(13)},
{start + execute.Time(2*time.Minute), start + execute.Time(3*time.Minute), start + execute.Time(140*time.Second), int64(14)},
},
},
}
},
},
}
for _, tc := range testCases {
tc := tc
t.Run(tc.name, func(t *testing.T) {
start := tc.start
stop := start + execute.Time(time.Hour)
d := executetest.NewDataset(executetest.RandomDatasetID())
c := execute.NewTableBuilderCache(executetest.UnlimitedAllocator)
c.SetTriggerSpec(execute.DefaultTriggerSpec)
fw := functions.NewFixedWindowTransformation(
d,
c,
execute.Bounds{
Start: start,
Stop: stop,
},
execute.Window{
Every: tc.every,
Period: tc.period,
Start: start,
},
false,
execute.DefaultTimeColLabel,
execute.DefaultStartColLabel,
execute.DefaultStopColLabel,
)
table0 := &executetest.Table{
ColMeta: []query.ColMeta{
{Label: "_start", Type: query.TTime},
{Label: "_stop", Type: query.TTime},
{Label: "_time", Type: query.TTime},
tc.valueCol,
},
}
for i := 0; i < tc.num; i++ {
var v interface{}
switch tc.valueCol.Type {
case query.TBool:
v = bool(i%2 == 0)
case query.TInt:
v = int64(i)
case query.TUInt:
v = uint64(i)
case query.TFloat:
v = float64(i)
case query.TString:
v = strconv.Itoa(i)
}
table0.Data = append(table0.Data, []interface{}{
start,
stop,
start + execute.Time(time.Duration(i)*10*time.Second),
v,
})
}
parentID := executetest.RandomDatasetID()
if err := fw.Process(parentID, table0); err != nil {
t.Fatal(err)
}
got, err := executetest.TablesFromCache(c)
if err != nil {
t.Fatal(err)
}
want := tc.want(start)
executetest.NormalizeTables(got)
executetest.NormalizeTables(want)
sort.Sort(executetest.SortedTables(got))
sort.Sort(executetest.SortedTables(want))
if !cmp.Equal(want, got) {
t.Errorf("unexpected tables -want/+got\n%s", cmp.Diff(want, got))
}
})
}
}