Test the merge iterator for every type instead of just floats

pull/5196/head
Jonathan A. Sternberg 2016-01-22 14:41:36 -05:00 committed by Ben Johnson
parent 03ad7a4e40
commit 3dd6aa17f3
4 changed files with 335 additions and 46 deletions

View File

@ -0,0 +1,160 @@
// Generated by tmpl
// https://github.com/benbjohnson/tmpl
package influxql_test
import (
"testing"
"github.com/davecgh/go-spew/spew"
"github.com/influxdb/influxdb/influxql"
"github.com/influxdb/influxdb/pkg/deep"
)
// Test implementation of influxql.FloatIterator
type FloatIterator struct {
Points []influxql.FloatPoint
}
// Close is a no-op.
func (itr *FloatIterator) Close() error { return nil }
// Next returns the next value and shifts it off the beginning of the points slice.
func (itr *FloatIterator) Next() *influxql.FloatPoint {
if len(itr.Points) == 0 {
return nil
}
v := &itr.Points[0]
itr.Points = itr.Points[1:]
return v
}
type TestFloatIterator struct {
Iterator influxql.Iterator
Points []influxql.FloatPoint
}
func (ti *TestFloatIterator) run(t *testing.T) {
itr := ti.Iterator.(influxql.FloatIterator)
points := make([]influxql.FloatPoint, 0, len(ti.Points))
for p := itr.Next(); p != nil; p = itr.Next() {
points = append(points, *p)
}
if !deep.Equal(ti.Points, points) {
t.Fatalf("unexpected points: %s %s", spew.Sdump(points), spew.Sdump(ti.Points))
}
}
// Test implementation of influxql.IntegerIterator
type IntegerIterator struct {
Points []influxql.IntegerPoint
}
// Close is a no-op.
func (itr *IntegerIterator) Close() error { return nil }
// Next returns the next value and shifts it off the beginning of the points slice.
func (itr *IntegerIterator) Next() *influxql.IntegerPoint {
if len(itr.Points) == 0 {
return nil
}
v := &itr.Points[0]
itr.Points = itr.Points[1:]
return v
}
type TestIntegerIterator struct {
Iterator influxql.Iterator
Points []influxql.IntegerPoint
}
func (ti *TestIntegerIterator) run(t *testing.T) {
itr := ti.Iterator.(influxql.IntegerIterator)
points := make([]influxql.IntegerPoint, 0, len(ti.Points))
for p := itr.Next(); p != nil; p = itr.Next() {
points = append(points, *p)
}
if !deep.Equal(ti.Points, points) {
t.Fatalf("unexpected points: %s %s", spew.Sdump(points), spew.Sdump(ti.Points))
}
}
// Test implementation of influxql.StringIterator
type StringIterator struct {
Points []influxql.StringPoint
}
// Close is a no-op.
func (itr *StringIterator) Close() error { return nil }
// Next returns the next value and shifts it off the beginning of the points slice.
func (itr *StringIterator) Next() *influxql.StringPoint {
if len(itr.Points) == 0 {
return nil
}
v := &itr.Points[0]
itr.Points = itr.Points[1:]
return v
}
type TestStringIterator struct {
Iterator influxql.Iterator
Points []influxql.StringPoint
}
func (ti *TestStringIterator) run(t *testing.T) {
itr := ti.Iterator.(influxql.StringIterator)
points := make([]influxql.StringPoint, 0, len(ti.Points))
for p := itr.Next(); p != nil; p = itr.Next() {
points = append(points, *p)
}
if !deep.Equal(ti.Points, points) {
t.Fatalf("unexpected points: %s %s", spew.Sdump(points), spew.Sdump(ti.Points))
}
}
// Test implementation of influxql.BooleanIterator
type BooleanIterator struct {
Points []influxql.BooleanPoint
}
// Close is a no-op.
func (itr *BooleanIterator) Close() error { return nil }
// Next returns the next value and shifts it off the beginning of the points slice.
func (itr *BooleanIterator) Next() *influxql.BooleanPoint {
if len(itr.Points) == 0 {
return nil
}
v := &itr.Points[0]
itr.Points = itr.Points[1:]
return v
}
type TestBooleanIterator struct {
Iterator influxql.Iterator
Points []influxql.BooleanPoint
}
func (ti *TestBooleanIterator) run(t *testing.T) {
itr := ti.Iterator.(influxql.BooleanIterator)
points := make([]influxql.BooleanPoint, 0, len(ti.Points))
for p := itr.Next(); p != nil; p = itr.Next() {
points = append(points, *p)
}
if !deep.Equal(ti.Points, points) {
t.Fatalf("unexpected points: %s %s", spew.Sdump(points), spew.Sdump(ti.Points))
}
}

View File

@ -0,0 +1,49 @@
package influxql_test
import (
"testing"
"github.com/davecgh/go-spew/spew"
"github.com/influxdb/influxdb/influxql"
"github.com/influxdb/influxdb/pkg/deep"
)
{{range .}}
// Test implementation of influxql.{{.Name}}Iterator
type {{.Name}}Iterator struct {
Points []influxql.{{.Name}}Point
}
// Close is a no-op.
func (itr *{{.Name}}Iterator) Close() error { return nil }
// Next returns the next value and shifts it off the beginning of the points slice.
func (itr *{{.Name}}Iterator) Next() *influxql.{{.Name}}Point {
if len(itr.Points) == 0 {
return nil
}
v := &itr.Points[0]
itr.Points = itr.Points[1:]
return v
}
type Test{{.Name}}Iterator struct {
Iterator influxql.Iterator
Points []influxql.{{.Name}}Point
}
func (ti *Test{{.Name}}Iterator) run(t *testing.T) {
itr := ti.Iterator.(influxql.{{.Name}}Iterator)
points := make([]influxql.{{.Name}}Point, 0, len(ti.Points))
for p := itr.Next(); p != nil; p = itr.Next() {
points = append(points, *p)
}
if !deep.Equal(ti.Points, points) {
t.Fatalf("unexpected points: %s %s", spew.Sdump(points), spew.Sdump(ti.Points))
}
}
{{end}}

View File

@ -13,9 +13,12 @@ import (
"github.com/influxdb/influxdb/pkg/deep"
)
//go:generate tmpl -data=@tmpldata iterator.gen_test.go.tmpl
// Ensure that a set of iterators can be merged together, sorted by window and name/tag.
func TestMergeIterator(t *testing.T) {
itr := influxql.NewMergeIterator([]influxql.Iterator{
func TestMergeIterator_Float(t *testing.T) {
test := TestFloatIterator{
Iterator: influxql.NewMergeIterator([]influxql.Iterator{
&FloatIterator{Points: []influxql.FloatPoint{
{Name: "cpu", Tags: ParseTags("host=A"), Time: 0, Value: 1},
{Name: "cpu", Tags: ParseTags("host=B"), Time: 1, Value: 2},
@ -32,26 +35,120 @@ func TestMergeIterator(t *testing.T) {
Duration: 10 * time.Nanosecond,
},
Ascending: true,
}).(influxql.FloatIterator)
}),
Points: []influxql.FloatPoint{
{Name: "cpu", Tags: ParseTags("host=A"), Time: 0, Value: 1},
{Name: "cpu", Tags: ParseTags("host=B"), Time: 1, Value: 2},
{Name: "cpu", Tags: ParseTags("host=A"), Time: 12, Value: 3},
{Name: "cpu", Tags: ParseTags("host=B"), Time: 11, Value: 5},
{Name: "cpu", Tags: ParseTags("host=B"), Time: 13, Value: 6},
{Name: "cpu", Tags: ParseTags("host=A"), Time: 20, Value: 7},
{Name: "cpu", Tags: ParseTags("host=A"), Time: 30, Value: 4},
},
}
test.run(t)
}
if p := itr.Next(); !reflect.DeepEqual(p, &influxql.FloatPoint{Name: "cpu", Tags: ParseTags("host=A"), Time: 0, Value: 1}) {
t.Fatalf("unexpected point: %#v", p)
} else if p = itr.Next(); !reflect.DeepEqual(p, &influxql.FloatPoint{Name: "cpu", Tags: ParseTags("host=B"), Time: 1, Value: 2}) {
t.Fatalf("unexpected point: %#v", p)
// Ensure that a set of iterators can be merged together, sorted by window and name/tag.
func TestMergeIterator_Integer(t *testing.T) {
test := TestIntegerIterator{
Iterator: influxql.NewMergeIterator([]influxql.Iterator{
&IntegerIterator{Points: []influxql.IntegerPoint{
{Name: "cpu", Tags: ParseTags("host=A"), Time: 0, Value: 1},
{Name: "cpu", Tags: ParseTags("host=B"), Time: 1, Value: 2},
{Name: "cpu", Tags: ParseTags("host=A"), Time: 12, Value: 3},
{Name: "cpu", Tags: ParseTags("host=A"), Time: 30, Value: 4},
}},
&IntegerIterator{Points: []influxql.IntegerPoint{
{Name: "cpu", Tags: ParseTags("host=B"), Time: 11, Value: 5},
{Name: "cpu", Tags: ParseTags("host=B"), Time: 13, Value: 6},
{Name: "cpu", Tags: ParseTags("host=A"), Time: 20, Value: 7},
}},
}, influxql.IteratorOptions{
Interval: influxql.Interval{
Duration: 10 * time.Nanosecond,
},
Ascending: true,
}),
Points: []influxql.IntegerPoint{
{Name: "cpu", Tags: ParseTags("host=A"), Time: 0, Value: 1},
{Name: "cpu", Tags: ParseTags("host=B"), Time: 1, Value: 2},
{Name: "cpu", Tags: ParseTags("host=A"), Time: 12, Value: 3},
{Name: "cpu", Tags: ParseTags("host=B"), Time: 11, Value: 5},
{Name: "cpu", Tags: ParseTags("host=B"), Time: 13, Value: 6},
{Name: "cpu", Tags: ParseTags("host=A"), Time: 20, Value: 7},
{Name: "cpu", Tags: ParseTags("host=A"), Time: 30, Value: 4},
},
}
if p := itr.Next(); !reflect.DeepEqual(p, &influxql.FloatPoint{Name: "cpu", Tags: ParseTags("host=A"), Time: 12, Value: 3}) {
t.Fatalf("unexpected point: %#v", p)
} else if p = itr.Next(); !reflect.DeepEqual(p, &influxql.FloatPoint{Name: "cpu", Tags: ParseTags("host=B"), Time: 11, Value: 5}) {
t.Fatalf("unexpected point: %#v", p)
} else if p := itr.Next(); !reflect.DeepEqual(p, &influxql.FloatPoint{Name: "cpu", Tags: ParseTags("host=B"), Time: 13, Value: 6}) {
t.Fatalf("unexpected point: %#v", p)
test.run(t)
}
if p := itr.Next(); !reflect.DeepEqual(p, &influxql.FloatPoint{Name: "cpu", Tags: ParseTags("host=A"), Time: 20, Value: 7}) {
t.Fatalf("unexpected point: %#v", p)
// Ensure that a set of iterators can be merged together, sorted by window and name/tag.
func TestMergeIterator_String(t *testing.T) {
test := TestStringIterator{
Iterator: influxql.NewMergeIterator([]influxql.Iterator{
&StringIterator{Points: []influxql.StringPoint{
{Name: "cpu", Tags: ParseTags("host=A"), Time: 0, Value: "a"},
{Name: "cpu", Tags: ParseTags("host=B"), Time: 1, Value: "b"},
{Name: "cpu", Tags: ParseTags("host=A"), Time: 12, Value: "c"},
{Name: "cpu", Tags: ParseTags("host=A"), Time: 30, Value: "d"},
}},
&StringIterator{Points: []influxql.StringPoint{
{Name: "cpu", Tags: ParseTags("host=B"), Time: 11, Value: "e"},
{Name: "cpu", Tags: ParseTags("host=B"), Time: 13, Value: "f"},
{Name: "cpu", Tags: ParseTags("host=A"), Time: 20, Value: "g"},
}},
}, influxql.IteratorOptions{
Interval: influxql.Interval{
Duration: 10 * time.Nanosecond,
},
Ascending: true,
}),
Points: []influxql.StringPoint{
{Name: "cpu", Tags: ParseTags("host=A"), Time: 0, Value: "a"},
{Name: "cpu", Tags: ParseTags("host=B"), Time: 1, Value: "b"},
{Name: "cpu", Tags: ParseTags("host=A"), Time: 12, Value: "c"},
{Name: "cpu", Tags: ParseTags("host=B"), Time: 11, Value: "e"},
{Name: "cpu", Tags: ParseTags("host=B"), Time: 13, Value: "f"},
{Name: "cpu", Tags: ParseTags("host=A"), Time: 20, Value: "g"},
{Name: "cpu", Tags: ParseTags("host=A"), Time: 30, Value: "d"},
},
}
if p := itr.Next(); !reflect.DeepEqual(p, &influxql.FloatPoint{Name: "cpu", Tags: ParseTags("host=A"), Time: 30, Value: 4}) {
t.Fatalf("unexpected point: %#v", p)
test.run(t)
}
// Ensure that a set of iterators can be merged together, sorted by window and name/tag.
func TestMergeIterator_Boolean(t *testing.T) {
test := TestBooleanIterator{
Iterator: influxql.NewMergeIterator([]influxql.Iterator{
&BooleanIterator{Points: []influxql.BooleanPoint{
{Name: "cpu", Tags: ParseTags("host=A"), Time: 0, Value: true},
{Name: "cpu", Tags: ParseTags("host=B"), Time: 1, Value: false},
{Name: "cpu", Tags: ParseTags("host=A"), Time: 12, Value: true},
{Name: "cpu", Tags: ParseTags("host=A"), Time: 30, Value: false},
}},
&BooleanIterator{Points: []influxql.BooleanPoint{
{Name: "cpu", Tags: ParseTags("host=B"), Time: 11, Value: true},
{Name: "cpu", Tags: ParseTags("host=B"), Time: 13, Value: false},
{Name: "cpu", Tags: ParseTags("host=A"), Time: 20, Value: true},
}},
}, influxql.IteratorOptions{
Interval: influxql.Interval{
Duration: 10 * time.Nanosecond,
},
Ascending: true,
}),
Points: []influxql.BooleanPoint{
{Name: "cpu", Tags: ParseTags("host=A"), Time: 0, Value: true},
{Name: "cpu", Tags: ParseTags("host=B"), Time: 1, Value: false},
{Name: "cpu", Tags: ParseTags("host=A"), Time: 12, Value: true},
{Name: "cpu", Tags: ParseTags("host=B"), Time: 11, Value: true},
{Name: "cpu", Tags: ParseTags("host=B"), Time: 13, Value: false},
{Name: "cpu", Tags: ParseTags("host=A"), Time: 20, Value: true},
{Name: "cpu", Tags: ParseTags("host=A"), Time: 30, Value: false},
},
}
test.run(t)
}
func TestMergeIterator_Nil(t *testing.T) {
@ -223,25 +320,6 @@ func (ic *IteratorCreator) FieldDimensions(sources influxql.Sources) (fields, di
return ic.FieldDimensionsFn(sources)
}
// Test implementation of influxql.FloatIterator.
type FloatIterator struct {
Points []influxql.FloatPoint
}
// Close is a no-op.
func (itr *FloatIterator) Close() error { return nil }
// Next returns the next value and shifts it off the beginning of the points slice.
func (itr *FloatIterator) Next() *influxql.FloatPoint {
if len(itr.Points) == 0 {
return nil
}
v := &itr.Points[0]
itr.Points = itr.Points[1:]
return v
}
// GenerateFloatIterator creates a FloatIterator with random data.
func GenerateFloatIterator(rand *rand.Rand, valueN int) *FloatIterator {
const interval = 10 * time.Second

View File

@ -140,6 +140,8 @@ func deepValueEqual(v1, v2 reflect.Value, visited map[visit]bool, depth int) boo
return true
}
return f1 == f2
case reflect.Bool:
return v1.Bool() == v2.Bool()
default:
panic(fmt.Sprintf("cannot compare type: %s", v1.Kind().String()))
}