influxdb/tsdb/cursors/schema_test.go

311 lines
5.8 KiB
Go

package cursors_test
import (
"math/rand"
"sort"
"testing"
"github.com/influxdata/influxdb/v2/pkg/testing/assert"
"github.com/influxdata/influxdb/v2/tsdb/cursors"
)
// Verifies FieldType precedence behavior is equivalent to influxql.DataType#LessThan
func TestFieldTypeDataTypePrecedenceEquivalence(t *testing.T) {
var fieldTypes = []cursors.FieldType{
cursors.Float,
cursors.Integer,
cursors.Unsigned,
cursors.Boolean,
cursors.String,
cursors.Undefined,
}
for _, fta := range fieldTypes {
for _, ftb := range fieldTypes {
if fta == ftb {
continue
}
got := fta.IsLower(ftb)
exp := cursors.FieldTypeToDataType(fta).LessThan(cursors.FieldTypeToDataType(ftb))
assert.Equal(t, got, exp, "failed %s.LessThan(%s)", fta.String(), ftb.String())
}
}
}
// Verifies sorting behavior of MeasurementFieldSlice
func TestMeasurementFieldSliceSort(t *testing.T) {
mfs := func(d ...cursors.MeasurementField) cursors.MeasurementFieldSlice {
return d
}
mf := func(key string, timestamp int64, ft cursors.FieldType) cursors.MeasurementField {
return cursors.MeasurementField{
Key: key,
Type: ft,
Timestamp: timestamp,
}
}
fltF := func(key string, ts int64) cursors.MeasurementField {
return mf(key, ts, cursors.Float)
}
intF := func(key string, ts int64) cursors.MeasurementField {
return mf(key, ts, cursors.Integer)
}
strF := func(key string, ts int64) cursors.MeasurementField {
return mf(key, ts, cursors.String)
}
blnF := func(key string, ts int64) cursors.MeasurementField {
return mf(key, ts, cursors.Boolean)
}
cases := []struct {
name string
in cursors.MeasurementFieldSlice
exp cursors.MeasurementFieldSlice
}{
{
name: "keys:diff types:same ts:same",
in: mfs(
fltF("bbb", 0),
fltF("aaa", 0),
fltF("ccc", 0),
),
exp: mfs(
fltF("aaa", 0),
fltF("bbb", 0),
fltF("ccc", 0),
),
},
{
name: "keys:same types:same ts:diff",
in: mfs(
fltF("aaa", 10),
fltF("ccc", 20),
fltF("aaa", 0),
fltF("ccc", 0),
),
exp: mfs(
fltF("aaa", 0),
fltF("aaa", 10),
fltF("ccc", 0),
fltF("ccc", 20),
),
},
{
name: "keys:same types:diff ts:same",
in: mfs(
strF("aaa", 0),
intF("aaa", 0),
fltF("aaa", 0),
blnF("aaa", 0),
),
exp: mfs(
blnF("aaa", 0),
strF("aaa", 0),
intF("aaa", 0),
fltF("aaa", 0),
),
},
{
name: "keys:same types:diff ts:diff",
in: mfs(
strF("aaa", 20),
intF("aaa", 10),
fltF("aaa", 0),
blnF("aaa", 30),
),
exp: mfs(
fltF("aaa", 0),
intF("aaa", 10),
strF("aaa", 20),
blnF("aaa", 30),
),
},
{
name: "keys:diff types:diff ts:diff",
in: mfs(
intF("ccc", 10),
blnF("fff", 30),
strF("aaa", 20),
fltF("ddd", 0),
),
exp: mfs(
strF("aaa", 20),
intF("ccc", 10),
fltF("ddd", 0),
blnF("fff", 30),
),
},
{
name: "keys:many types:many ts:same",
in: mfs(
intF("ccc", 10),
blnF("fff", 30),
strF("aaa", 20),
fltF("ddd", 0),
fltF("ccc", 10),
strF("fff", 30),
intF("aaa", 20),
blnF("ddd", 0),
),
exp: mfs(
strF("aaa", 20),
intF("aaa", 20),
intF("ccc", 10),
fltF("ccc", 10),
blnF("ddd", 0),
fltF("ddd", 0),
blnF("fff", 30),
strF("fff", 30),
),
},
}
for _, tc := range cases {
t.Run(tc.name, func(t *testing.T) {
got := tc.in
// randomize order using fixed seed to
// ensure tests are deterministic on a given platform
seededRand := rand.New(rand.NewSource(100))
for i := 0; i < 5; i++ {
seededRand.Shuffle(len(got), func(i, j int) {
got[i], got[j] = got[j], got[i]
})
sort.Sort(got)
assert.Equal(t, got, tc.exp, "failed at index", i)
}
})
}
}
func TestMeasurementFieldSlice_UniqueByKey(t *testing.T) {
mfs := func(d ...cursors.MeasurementField) cursors.MeasurementFieldSlice {
return d
}
mf := func(key string, timestamp int64, ft cursors.FieldType) cursors.MeasurementField {
return cursors.MeasurementField{
Key: key,
Type: ft,
Timestamp: timestamp,
}
}
fltF := func(key string, ts int64) cursors.MeasurementField {
return mf(key, ts, cursors.Float)
}
t.Run("multiple start end", func(t *testing.T) {
got := mfs(
fltF("aaa", 0),
fltF("aaa", 10),
fltF("bbb", 10),
fltF("ccc", 10),
fltF("ccc", 20),
)
exp := mfs(
fltF("aaa", 0),
fltF("bbb", 10),
fltF("ccc", 10),
)
got.UniqueByKey()
assert.Equal(t, got, exp)
})
t.Run("multiple at end", func(t *testing.T) {
got := mfs(
fltF("aaa", 0),
fltF("bbb", 10),
fltF("ccc", 10),
fltF("ccc", 20),
fltF("ccc", 30),
)
exp := mfs(
fltF("aaa", 0),
fltF("bbb", 10),
fltF("ccc", 10),
)
got.UniqueByKey()
assert.Equal(t, got, exp)
})
t.Run("no duplicates many", func(t *testing.T) {
got := mfs(
fltF("aaa", 0),
fltF("bbb", 10),
fltF("ccc", 20),
)
exp := mfs(
fltF("aaa", 0),
fltF("bbb", 10),
fltF("ccc", 20),
)
got.UniqueByKey()
assert.Equal(t, got, exp)
})
t.Run("no duplicates two elements", func(t *testing.T) {
got := mfs(
fltF("aaa", 0),
fltF("bbb", 10),
)
exp := mfs(
fltF("aaa", 0),
fltF("bbb", 10),
)
got.UniqueByKey()
assert.Equal(t, got, exp)
})
t.Run("duplicates one key", func(t *testing.T) {
got := mfs(
fltF("aaa", 0),
fltF("aaa", 10),
fltF("aaa", 10),
fltF("aaa", 10),
fltF("aaa", 10),
fltF("aaa", 10),
)
exp := mfs(
fltF("aaa", 0),
)
got.UniqueByKey()
assert.Equal(t, got, exp)
})
t.Run("one element", func(t *testing.T) {
got := mfs(
fltF("aaa", 0),
)
exp := mfs(
fltF("aaa", 0),
)
got.UniqueByKey()
assert.Equal(t, got, exp)
})
t.Run("empty", func(t *testing.T) {
got := mfs()
exp := mfs()
got.UniqueByKey()
assert.Equal(t, got, exp)
})
}