2016-10-27 15:47:41 +00:00
|
|
|
package tsi1_test
|
|
|
|
|
|
|
|
import (
|
2016-11-03 17:05:48 +00:00
|
|
|
"bytes"
|
2016-12-15 15:31:18 +00:00
|
|
|
"io/ioutil"
|
2016-10-27 15:47:41 +00:00
|
|
|
"reflect"
|
|
|
|
"testing"
|
|
|
|
|
2016-11-08 21:07:01 +00:00
|
|
|
"github.com/influxdata/influxdb/influxql"
|
2016-10-27 15:47:41 +00:00
|
|
|
"github.com/influxdata/influxdb/models"
|
2016-11-15 16:20:00 +00:00
|
|
|
"github.com/influxdata/influxdb/tsdb/index/tsi1"
|
2016-10-27 15:47:41 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
// Ensure iterator can operate over an in-memory list of elements.
|
|
|
|
func TestMeasurementIterator(t *testing.T) {
|
2016-10-31 14:46:07 +00:00
|
|
|
elems := []MeasurementElem{
|
|
|
|
MeasurementElem{name: []byte("cpu"), deleted: true},
|
|
|
|
MeasurementElem{name: []byte("mem")},
|
2016-10-27 15:47:41 +00:00
|
|
|
}
|
|
|
|
|
2016-10-31 14:46:07 +00:00
|
|
|
itr := MeasurementIterator{Elems: elems}
|
2016-10-27 15:47:41 +00:00
|
|
|
if e := itr.Next(); !reflect.DeepEqual(&elems[0], e) {
|
|
|
|
t.Fatalf("unexpected elem(0): %#v", e)
|
|
|
|
} else if e := itr.Next(); !reflect.DeepEqual(&elems[1], e) {
|
|
|
|
t.Fatalf("unexpected elem(1): %#v", e)
|
|
|
|
} else if e := itr.Next(); e != nil {
|
|
|
|
t.Fatalf("expected nil elem: %#v", e)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Ensure iterator can merge multiple iterators together.
|
|
|
|
func TestMergeMeasurementIterators(t *testing.T) {
|
|
|
|
itr := tsi1.MergeMeasurementIterators(
|
2016-10-31 14:46:07 +00:00
|
|
|
&MeasurementIterator{Elems: []MeasurementElem{
|
|
|
|
{name: []byte("aaa")},
|
|
|
|
{name: []byte("bbb"), deleted: true},
|
|
|
|
{name: []byte("ccc")},
|
|
|
|
}},
|
|
|
|
&MeasurementIterator{},
|
|
|
|
&MeasurementIterator{Elems: []MeasurementElem{
|
|
|
|
{name: []byte("bbb")},
|
|
|
|
{name: []byte("ccc"), deleted: true},
|
|
|
|
{name: []byte("ddd")},
|
|
|
|
}},
|
2016-10-27 15:47:41 +00:00
|
|
|
)
|
|
|
|
|
2016-11-03 17:05:48 +00:00
|
|
|
if e := itr.Next(); !bytes.Equal(e.Name(), []byte("aaa")) || e.Deleted() {
|
|
|
|
t.Fatalf("unexpected elem(0): %s/%v", e.Name(), e.Deleted())
|
|
|
|
} else if e := itr.Next(); !bytes.Equal(e.Name(), []byte("bbb")) || !e.Deleted() {
|
|
|
|
t.Fatalf("unexpected elem(1): %s/%v", e.Name(), e.Deleted())
|
|
|
|
} else if e := itr.Next(); !bytes.Equal(e.Name(), []byte("ccc")) || e.Deleted() {
|
|
|
|
t.Fatalf("unexpected elem(2): %s/%v", e.Name(), e.Deleted())
|
|
|
|
} else if e := itr.Next(); !bytes.Equal(e.Name(), []byte("ddd")) || e.Deleted() {
|
|
|
|
t.Fatalf("unexpected elem(3): %s/%v", e.Name(), e.Deleted())
|
2016-10-27 15:47:41 +00:00
|
|
|
} else if e := itr.Next(); e != nil {
|
|
|
|
t.Fatalf("expected nil elem: %#v", e)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Ensure iterator can operate over an in-memory list of tag key elements.
|
|
|
|
func TestTagKeyIterator(t *testing.T) {
|
2016-10-31 14:46:07 +00:00
|
|
|
elems := []TagKeyElem{
|
|
|
|
{key: []byte("aaa"), deleted: true},
|
|
|
|
{key: []byte("bbb")},
|
2016-10-27 15:47:41 +00:00
|
|
|
}
|
|
|
|
|
2016-10-31 14:46:07 +00:00
|
|
|
itr := TagKeyIterator{Elems: elems}
|
2016-10-27 15:47:41 +00:00
|
|
|
if e := itr.Next(); !reflect.DeepEqual(&elems[0], e) {
|
|
|
|
t.Fatalf("unexpected elem(0): %#v", e)
|
|
|
|
} else if e := itr.Next(); !reflect.DeepEqual(&elems[1], e) {
|
|
|
|
t.Fatalf("unexpected elem(1): %#v", e)
|
|
|
|
} else if e := itr.Next(); e != nil {
|
|
|
|
t.Fatalf("expected nil elem: %#v", e)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Ensure iterator can merge multiple iterators together.
|
|
|
|
func TestMergeTagKeyIterators(t *testing.T) {
|
|
|
|
itr := tsi1.MergeTagKeyIterators(
|
2016-10-31 14:46:07 +00:00
|
|
|
&TagKeyIterator{Elems: []TagKeyElem{
|
|
|
|
{key: []byte("aaa")},
|
|
|
|
{key: []byte("bbb"), deleted: true},
|
|
|
|
{key: []byte("ccc")},
|
|
|
|
}},
|
|
|
|
&TagKeyIterator{},
|
|
|
|
&TagKeyIterator{Elems: []TagKeyElem{
|
|
|
|
{key: []byte("bbb")},
|
|
|
|
{key: []byte("ccc"), deleted: true},
|
|
|
|
{key: []byte("ddd")},
|
|
|
|
}},
|
2016-10-27 15:47:41 +00:00
|
|
|
)
|
|
|
|
|
2016-11-03 17:05:48 +00:00
|
|
|
if e := itr.Next(); !bytes.Equal(e.Key(), []byte("aaa")) || e.Deleted() {
|
|
|
|
t.Fatalf("unexpected elem(0): %s/%v", e.Key(), e.Deleted())
|
|
|
|
} else if e := itr.Next(); !bytes.Equal(e.Key(), []byte("bbb")) || !e.Deleted() {
|
|
|
|
t.Fatalf("unexpected elem(1): %s/%v", e.Key(), e.Deleted())
|
|
|
|
} else if e := itr.Next(); !bytes.Equal(e.Key(), []byte("ccc")) || e.Deleted() {
|
|
|
|
t.Fatalf("unexpected elem(2): %s/%v", e.Key(), e.Deleted())
|
|
|
|
} else if e := itr.Next(); !bytes.Equal(e.Key(), []byte("ddd")) || e.Deleted() {
|
|
|
|
t.Fatalf("unexpected elem(3): %s/%v", e.Key(), e.Deleted())
|
2016-10-27 15:47:41 +00:00
|
|
|
} else if e := itr.Next(); e != nil {
|
|
|
|
t.Fatalf("expected nil elem: %#v", e)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Ensure iterator can operate over an in-memory list of tag value elements.
|
|
|
|
func TestTagValueIterator(t *testing.T) {
|
2016-10-31 14:46:07 +00:00
|
|
|
elems := []TagValueElem{
|
|
|
|
{value: []byte("aaa"), deleted: true},
|
|
|
|
{value: []byte("bbb")},
|
2016-10-27 15:47:41 +00:00
|
|
|
}
|
|
|
|
|
2016-10-31 14:46:07 +00:00
|
|
|
itr := &TagValueIterator{Elems: elems}
|
2016-10-27 15:47:41 +00:00
|
|
|
if e := itr.Next(); !reflect.DeepEqual(&elems[0], e) {
|
|
|
|
t.Fatalf("unexpected elem(0): %#v", e)
|
|
|
|
} else if e := itr.Next(); !reflect.DeepEqual(&elems[1], e) {
|
|
|
|
t.Fatalf("unexpected elem(1): %#v", e)
|
|
|
|
} else if e := itr.Next(); e != nil {
|
|
|
|
t.Fatalf("expected nil elem: %#v", e)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Ensure iterator can merge multiple iterators together.
|
|
|
|
func TestMergeTagValueIterators(t *testing.T) {
|
|
|
|
itr := tsi1.MergeTagValueIterators(
|
2016-10-31 14:46:07 +00:00
|
|
|
&TagValueIterator{Elems: []TagValueElem{
|
|
|
|
{value: []byte("aaa")},
|
|
|
|
{value: []byte("bbb"), deleted: true},
|
|
|
|
{value: []byte("ccc")},
|
|
|
|
}},
|
|
|
|
&TagValueIterator{},
|
|
|
|
&TagValueIterator{Elems: []TagValueElem{
|
|
|
|
{value: []byte("bbb")},
|
|
|
|
{value: []byte("ccc"), deleted: true},
|
|
|
|
{value: []byte("ddd")},
|
|
|
|
}},
|
2016-10-27 15:47:41 +00:00
|
|
|
)
|
|
|
|
|
2016-11-03 17:05:48 +00:00
|
|
|
if e := itr.Next(); !bytes.Equal(e.Value(), []byte("aaa")) || e.Deleted() {
|
|
|
|
t.Fatalf("unexpected elem(0): %s/%v", e.Value(), e.Deleted())
|
|
|
|
} else if e := itr.Next(); !bytes.Equal(e.Value(), []byte("bbb")) || !e.Deleted() {
|
|
|
|
t.Fatalf("unexpected elem(1): %s/%v", e.Value(), e.Deleted())
|
|
|
|
} else if e := itr.Next(); !bytes.Equal(e.Value(), []byte("ccc")) || e.Deleted() {
|
|
|
|
t.Fatalf("unexpected elem(2): %s/%v", e.Value(), e.Deleted())
|
|
|
|
} else if e := itr.Next(); !bytes.Equal(e.Value(), []byte("ddd")) || e.Deleted() {
|
|
|
|
t.Fatalf("unexpected elem(3): %s/%v", e.Value(), e.Deleted())
|
2016-10-27 15:47:41 +00:00
|
|
|
} else if e := itr.Next(); e != nil {
|
|
|
|
t.Fatalf("expected nil elem: %#v", e)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Ensure iterator can operate over an in-memory list of series.
|
|
|
|
func TestSeriesIterator(t *testing.T) {
|
2016-10-31 14:46:07 +00:00
|
|
|
elems := []SeriesElem{
|
|
|
|
{name: []byte("cpu"), tags: models.Tags{{Key: []byte("region"), Value: []byte("us-east")}}, deleted: true},
|
|
|
|
{name: []byte("mem")},
|
2016-10-27 15:47:41 +00:00
|
|
|
}
|
|
|
|
|
2016-10-31 14:46:07 +00:00
|
|
|
itr := SeriesIterator{Elems: elems}
|
2016-10-27 15:47:41 +00:00
|
|
|
if e := itr.Next(); !reflect.DeepEqual(&elems[0], e) {
|
|
|
|
t.Fatalf("unexpected elem(0): %#v", e)
|
|
|
|
} else if e := itr.Next(); !reflect.DeepEqual(&elems[1], e) {
|
|
|
|
t.Fatalf("unexpected elem(1): %#v", e)
|
|
|
|
} else if e := itr.Next(); e != nil {
|
|
|
|
t.Fatalf("expected nil elem: %#v", e)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Ensure iterator can merge multiple iterators together.
|
|
|
|
func TestMergeSeriesIterators(t *testing.T) {
|
|
|
|
itr := tsi1.MergeSeriesIterators(
|
2016-10-31 14:46:07 +00:00
|
|
|
&SeriesIterator{Elems: []SeriesElem{
|
|
|
|
{name: []byte("aaa"), tags: models.Tags{{Key: []byte("region"), Value: []byte("us-east")}}, deleted: true},
|
|
|
|
{name: []byte("bbb"), deleted: true},
|
|
|
|
{name: []byte("ccc")},
|
|
|
|
}},
|
|
|
|
&SeriesIterator{},
|
|
|
|
&SeriesIterator{Elems: []SeriesElem{
|
|
|
|
{name: []byte("aaa"), tags: models.Tags{{Key: []byte("region"), Value: []byte("us-east")}}},
|
|
|
|
{name: []byte("aaa"), tags: models.Tags{{Key: []byte("region"), Value: []byte("us-west")}}},
|
|
|
|
{name: []byte("bbb")},
|
|
|
|
{name: []byte("ccc"), deleted: true},
|
|
|
|
{name: []byte("ddd")},
|
|
|
|
}},
|
2016-10-27 15:47:41 +00:00
|
|
|
)
|
|
|
|
|
2016-10-31 14:46:07 +00:00
|
|
|
if e := itr.Next(); !reflect.DeepEqual(e, &SeriesElem{name: []byte("aaa"), tags: models.Tags{{Key: []byte("region"), Value: []byte("us-east")}}, deleted: true}) {
|
2016-10-27 15:47:41 +00:00
|
|
|
t.Fatalf("unexpected elem(0): %#v", e)
|
2016-10-31 14:46:07 +00:00
|
|
|
} else if e := itr.Next(); !reflect.DeepEqual(e, &SeriesElem{name: []byte("aaa"), tags: models.Tags{{Key: []byte("region"), Value: []byte("us-west")}}}) {
|
2016-10-27 15:47:41 +00:00
|
|
|
t.Fatalf("unexpected elem(1): %#v", e)
|
2016-10-31 14:46:07 +00:00
|
|
|
} else if e := itr.Next(); !reflect.DeepEqual(e, &SeriesElem{name: []byte("bbb"), deleted: true}) {
|
2016-10-27 15:47:41 +00:00
|
|
|
t.Fatalf("unexpected elem(2): %#v", e)
|
2016-10-31 14:46:07 +00:00
|
|
|
} else if e := itr.Next(); !reflect.DeepEqual(e, &SeriesElem{name: []byte("ccc")}) {
|
2016-10-27 15:47:41 +00:00
|
|
|
t.Fatalf("unexpected elem(3): %#v", e)
|
2016-10-31 14:46:07 +00:00
|
|
|
} else if e := itr.Next(); !reflect.DeepEqual(e, &SeriesElem{name: []byte("ddd")}) {
|
2016-10-27 15:47:41 +00:00
|
|
|
t.Fatalf("unexpected elem(4): %#v", e)
|
|
|
|
} else if e := itr.Next(); e != nil {
|
|
|
|
t.Fatalf("expected nil elem: %#v", e)
|
|
|
|
}
|
|
|
|
}
|
2016-10-31 14:46:07 +00:00
|
|
|
|
|
|
|
// MeasurementElem represents a test implementation of tsi1.MeasurementElem.
|
|
|
|
type MeasurementElem struct {
|
|
|
|
name []byte
|
|
|
|
deleted bool
|
|
|
|
}
|
|
|
|
|
|
|
|
func (e *MeasurementElem) Name() []byte { return e.name }
|
|
|
|
func (e *MeasurementElem) Deleted() bool { return e.deleted }
|
|
|
|
func (e *MeasurementElem) TagKeyIterator() tsi1.TagKeyIterator { return nil }
|
|
|
|
|
|
|
|
// MeasurementIterator represents an iterator over a slice of measurements.
|
|
|
|
type MeasurementIterator struct {
|
|
|
|
Elems []MeasurementElem
|
|
|
|
}
|
|
|
|
|
|
|
|
// Next returns the next element in the iterator.
|
|
|
|
func (itr *MeasurementIterator) Next() (e tsi1.MeasurementElem) {
|
|
|
|
if len(itr.Elems) == 0 {
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
e, itr.Elems = &itr.Elems[0], itr.Elems[1:]
|
|
|
|
return e
|
|
|
|
}
|
|
|
|
|
|
|
|
// TagKeyElem represents a test implementation of tsi1.TagKeyElem.
|
|
|
|
type TagKeyElem struct {
|
|
|
|
key []byte
|
|
|
|
deleted bool
|
|
|
|
}
|
|
|
|
|
|
|
|
func (e *TagKeyElem) Key() []byte { return e.key }
|
|
|
|
func (e *TagKeyElem) Deleted() bool { return e.deleted }
|
|
|
|
func (e *TagKeyElem) TagValueIterator() tsi1.TagValueIterator { return nil }
|
|
|
|
|
|
|
|
// TagKeyIterator represents an iterator over a slice of tag keys.
|
|
|
|
type TagKeyIterator struct {
|
|
|
|
Elems []TagKeyElem
|
|
|
|
}
|
|
|
|
|
|
|
|
// Next returns the next element in the iterator.
|
|
|
|
func (itr *TagKeyIterator) Next() (e tsi1.TagKeyElem) {
|
|
|
|
if len(itr.Elems) == 0 {
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
e, itr.Elems = &itr.Elems[0], itr.Elems[1:]
|
|
|
|
return e
|
|
|
|
}
|
|
|
|
|
|
|
|
// TagValueElem represents a test implementation of tsi1.TagValueElem.
|
|
|
|
type TagValueElem struct {
|
|
|
|
value []byte
|
|
|
|
deleted bool
|
|
|
|
}
|
|
|
|
|
|
|
|
func (e *TagValueElem) Value() []byte { return e.value }
|
|
|
|
func (e *TagValueElem) Deleted() bool { return e.deleted }
|
|
|
|
func (e *TagValueElem) SeriesIterator() tsi1.SeriesIterator { return nil }
|
|
|
|
|
|
|
|
// TagValueIterator represents an iterator over a slice of tag values.
|
|
|
|
type TagValueIterator struct {
|
|
|
|
Elems []TagValueElem
|
|
|
|
}
|
|
|
|
|
|
|
|
// Next returns the next element in the iterator.
|
|
|
|
func (itr *TagValueIterator) Next() (e tsi1.TagValueElem) {
|
|
|
|
if len(itr.Elems) == 0 {
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
e, itr.Elems = &itr.Elems[0], itr.Elems[1:]
|
|
|
|
return e
|
|
|
|
}
|
|
|
|
|
|
|
|
// SeriesElem represents a test implementation of tsi1.SeriesElem.
|
|
|
|
type SeriesElem struct {
|
|
|
|
name []byte
|
|
|
|
tags models.Tags
|
|
|
|
deleted bool
|
2016-11-08 21:07:01 +00:00
|
|
|
expr influxql.Expr
|
2016-10-31 14:46:07 +00:00
|
|
|
}
|
|
|
|
|
2016-11-08 21:07:01 +00:00
|
|
|
func (e *SeriesElem) Name() []byte { return e.name }
|
|
|
|
func (e *SeriesElem) Tags() models.Tags { return e.tags }
|
|
|
|
func (e *SeriesElem) Deleted() bool { return e.deleted }
|
|
|
|
func (e *SeriesElem) Expr() influxql.Expr { return e.expr }
|
2016-10-31 14:46:07 +00:00
|
|
|
|
|
|
|
// SeriesIterator represents an iterator over a slice of tag values.
|
|
|
|
type SeriesIterator struct {
|
|
|
|
Elems []SeriesElem
|
|
|
|
}
|
|
|
|
|
|
|
|
// Next returns the next element in the iterator.
|
|
|
|
func (itr *SeriesIterator) Next() (e tsi1.SeriesElem) {
|
|
|
|
if len(itr.Elems) == 0 {
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
e, itr.Elems = &itr.Elems[0], itr.Elems[1:]
|
|
|
|
return e
|
|
|
|
}
|
2016-12-15 15:31:18 +00:00
|
|
|
|
|
|
|
// MustTempDir returns a temporary directory. Panic on error.
|
|
|
|
func MustTempDir() string {
|
|
|
|
path, err := ioutil.TempDir("", "tsi-")
|
|
|
|
if err != nil {
|
|
|
|
panic(err)
|
|
|
|
}
|
|
|
|
return path
|
|
|
|
}
|