2015-09-01 21:25:59 +00:00
|
|
|
package tsdb
|
2015-04-23 05:50:29 +00:00
|
|
|
|
2015-05-12 20:34:12 +00:00
|
|
|
import (
|
2015-05-14 16:55:17 +00:00
|
|
|
"reflect"
|
2015-05-12 20:34:12 +00:00
|
|
|
"testing"
|
|
|
|
"time"
|
2015-05-14 16:55:17 +00:00
|
|
|
|
|
|
|
"github.com/davecgh/go-spew/spew"
|
2015-09-01 21:25:59 +00:00
|
|
|
"github.com/influxdb/influxdb/influxql"
|
2015-05-12 20:34:12 +00:00
|
|
|
)
|
2015-05-12 16:37:58 +00:00
|
|
|
|
2015-05-04 21:59:39 +00:00
|
|
|
import "sort"
|
2015-04-23 05:50:29 +00:00
|
|
|
|
2015-09-01 21:25:59 +00:00
|
|
|
type testPoint struct {
|
2015-05-29 20:12:00 +00:00
|
|
|
seriesKey string
|
|
|
|
time int64
|
|
|
|
value interface{}
|
2015-08-28 21:17:18 +00:00
|
|
|
tags map[string]string
|
2015-04-23 05:50:29 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
type testIterator struct {
|
2015-09-01 21:25:59 +00:00
|
|
|
values []testPoint
|
2015-09-04 13:04:35 +00:00
|
|
|
lastTags map[string]string
|
|
|
|
nextFunc func() (timestamp int64, value interface{})
|
|
|
|
tagsFunc func() map[string]string
|
|
|
|
tMinFunc func() int64
|
2015-04-23 05:50:29 +00:00
|
|
|
}
|
|
|
|
|
2015-07-22 09:35:35 +00:00
|
|
|
func (t *testIterator) Next() (timestamp int64, value interface{}) {
|
2015-08-28 21:17:18 +00:00
|
|
|
if t.nextFunc != nil {
|
|
|
|
return t.nextFunc()
|
|
|
|
}
|
2015-04-23 05:50:29 +00:00
|
|
|
if len(t.values) > 0 {
|
|
|
|
v := t.values[0]
|
2015-08-28 21:17:18 +00:00
|
|
|
t.lastTags = t.values[0].tags
|
2015-04-23 05:50:29 +00:00
|
|
|
t.values = t.values[1:]
|
2015-07-22 09:35:35 +00:00
|
|
|
return v.time, v.value
|
2015-04-23 05:50:29 +00:00
|
|
|
}
|
2015-05-14 16:55:17 +00:00
|
|
|
|
2015-07-22 09:35:35 +00:00
|
|
|
return -1, nil
|
2015-04-23 05:50:29 +00:00
|
|
|
}
|
|
|
|
|
2015-08-27 21:12:11 +00:00
|
|
|
func (t *testIterator) Tags() map[string]string {
|
2015-08-28 21:17:18 +00:00
|
|
|
if t.tagsFunc != nil {
|
|
|
|
return t.tagsFunc()
|
|
|
|
}
|
|
|
|
return t.lastTags
|
2015-08-27 21:12:11 +00:00
|
|
|
}
|
|
|
|
|
2015-09-04 12:57:34 +00:00
|
|
|
func (t *testIterator) TMin() int64 {
|
2015-09-04 13:04:35 +00:00
|
|
|
if t.tMinFunc != nil {
|
|
|
|
return t.tMinFunc()
|
2015-09-03 20:04:47 +00:00
|
|
|
}
|
|
|
|
return -1
|
|
|
|
}
|
|
|
|
|
2015-04-23 05:50:29 +00:00
|
|
|
func TestMapMeanNoValues(t *testing.T) {
|
|
|
|
iter := &testIterator{}
|
|
|
|
if got := MapMean(iter); got != nil {
|
|
|
|
t.Errorf("output mismatch: exp nil got %v", got)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestMapMean(t *testing.T) {
|
|
|
|
|
|
|
|
tests := []struct {
|
2015-09-01 21:25:59 +00:00
|
|
|
input []testPoint
|
2015-04-23 05:50:29 +00:00
|
|
|
output *meanMapOutput
|
|
|
|
}{
|
2015-09-02 17:47:58 +00:00
|
|
|
{ // Single point
|
2015-09-01 21:25:59 +00:00
|
|
|
input: []testPoint{testPoint{"0", 1, 1.0, nil}},
|
2015-06-10 03:06:19 +00:00
|
|
|
output: &meanMapOutput{1, 1, Float64Type},
|
2015-04-23 05:50:29 +00:00
|
|
|
},
|
2015-09-02 17:47:58 +00:00
|
|
|
{ // Two points
|
2015-09-01 21:25:59 +00:00
|
|
|
input: []testPoint{
|
|
|
|
testPoint{"0", 1, 2.0, nil},
|
|
|
|
testPoint{"0", 2, 8.0, nil},
|
2015-04-23 05:50:29 +00:00
|
|
|
},
|
2015-06-10 03:06:19 +00:00
|
|
|
output: &meanMapOutput{2, 5.0, Float64Type},
|
2015-04-23 05:50:29 +00:00
|
|
|
},
|
|
|
|
}
|
|
|
|
|
|
|
|
for _, test := range tests {
|
|
|
|
iter := &testIterator{
|
|
|
|
values: test.input,
|
|
|
|
}
|
|
|
|
|
|
|
|
got := MapMean(iter)
|
|
|
|
if got == nil {
|
|
|
|
t.Fatalf("MapMean(%v): output mismatch: exp %v got %v", test.input, test.output, got)
|
|
|
|
}
|
|
|
|
|
|
|
|
if got.(*meanMapOutput).Count != test.output.Count || got.(*meanMapOutput).Mean != test.output.Mean {
|
|
|
|
t.Errorf("output mismatch: exp %v got %v", test.output, got)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2015-04-23 16:49:16 +00:00
|
|
|
|
2015-05-12 16:37:58 +00:00
|
|
|
func TestInitializeMapFuncDerivative(t *testing.T) {
|
|
|
|
|
2015-05-13 20:03:58 +00:00
|
|
|
for _, fn := range []string{"derivative", "non_negative_derivative"} {
|
|
|
|
// Single field arg should return MapEcho
|
2015-09-01 21:25:59 +00:00
|
|
|
c := &influxql.Call{
|
2015-05-13 20:03:58 +00:00
|
|
|
Name: fn,
|
2015-09-01 21:25:59 +00:00
|
|
|
Args: []influxql.Expr{
|
|
|
|
&influxql.VarRef{Val: " field1"},
|
|
|
|
&influxql.DurationLiteral{Val: time.Hour},
|
2015-05-13 20:03:58 +00:00
|
|
|
},
|
|
|
|
}
|
2015-05-12 16:37:58 +00:00
|
|
|
|
2015-08-31 21:04:53 +00:00
|
|
|
_, err := InitializeMapFunc(c)
|
2015-05-13 20:03:58 +00:00
|
|
|
if err != nil {
|
|
|
|
t.Errorf("InitializeMapFunc(%v) unexpected error. got %v", c, err)
|
|
|
|
}
|
2015-05-12 16:37:58 +00:00
|
|
|
|
2015-05-13 20:03:58 +00:00
|
|
|
// Nested Aggregate func should return the map func for the nested aggregate
|
2015-09-01 21:25:59 +00:00
|
|
|
c = &influxql.Call{
|
2015-05-13 20:03:58 +00:00
|
|
|
Name: fn,
|
2015-09-01 21:25:59 +00:00
|
|
|
Args: []influxql.Expr{
|
|
|
|
&influxql.Call{Name: "mean", Args: []influxql.Expr{&influxql.VarRef{Val: "field1"}}},
|
|
|
|
&influxql.DurationLiteral{Val: time.Hour},
|
2015-05-13 20:03:58 +00:00
|
|
|
},
|
|
|
|
}
|
|
|
|
|
2015-09-02 17:47:58 +00:00
|
|
|
_, err = InitializeMapFunc(c)
|
2015-05-13 20:03:58 +00:00
|
|
|
if err != nil {
|
|
|
|
t.Errorf("InitializeMapFunc(%v) unexpected error. got %v", c, err)
|
|
|
|
}
|
2015-05-12 16:37:58 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-04-23 17:10:19 +00:00
|
|
|
func TestReducePercentileNil(t *testing.T) {
|
|
|
|
|
|
|
|
input := []interface{}{
|
|
|
|
nil,
|
|
|
|
}
|
|
|
|
|
2015-08-31 16:27:42 +00:00
|
|
|
// ReducePercentile should ignore nil values when calculating the percentile
|
2015-09-01 21:25:59 +00:00
|
|
|
got := ReducePercentile(input, &influxql.Call{Name: "top", Args: []influxql.Expr{&influxql.VarRef{Val: "field1"}, &influxql.NumberLiteral{Val: 100}}})
|
2015-04-23 17:10:19 +00:00
|
|
|
if got != nil {
|
|
|
|
t.Fatalf("ReducePercentile(100) returned wrong type. exp nil got %v", got)
|
|
|
|
}
|
|
|
|
}
|
2015-05-04 21:59:39 +00:00
|
|
|
|
2015-05-14 16:55:17 +00:00
|
|
|
func TestMapDistinct(t *testing.T) {
|
2015-05-29 20:12:00 +00:00
|
|
|
const ( // prove that we're ignoring seriesKey
|
|
|
|
seriesKey1 = "1"
|
|
|
|
seriesKey2 = "2"
|
2015-05-14 16:55:17 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
const ( // prove that we're ignoring time
|
|
|
|
timeId1 = iota + 1
|
|
|
|
timeId2
|
|
|
|
timeId3
|
|
|
|
timeId4
|
|
|
|
timeId5
|
|
|
|
timeId6
|
|
|
|
)
|
|
|
|
|
|
|
|
iter := &testIterator{
|
2015-09-01 21:25:59 +00:00
|
|
|
values: []testPoint{
|
2015-08-28 21:17:18 +00:00
|
|
|
{seriesKey1, timeId1, uint64(1), nil},
|
|
|
|
{seriesKey1, timeId2, uint64(1), nil},
|
|
|
|
{seriesKey1, timeId3, "1", nil},
|
|
|
|
{seriesKey2, timeId4, uint64(1), nil},
|
|
|
|
{seriesKey2, timeId5, float64(1.0), nil},
|
|
|
|
{seriesKey2, timeId6, "1", nil},
|
2015-05-14 16:55:17 +00:00
|
|
|
},
|
|
|
|
}
|
|
|
|
|
2015-08-28 21:17:18 +00:00
|
|
|
values := MapDistinct(iter).(interfaceValues)
|
2015-05-14 16:55:17 +00:00
|
|
|
|
|
|
|
if exp, got := 3, len(values); exp != got {
|
|
|
|
t.Errorf("Wrong number of values. exp %v got %v", exp, got)
|
|
|
|
}
|
|
|
|
|
|
|
|
sort.Sort(values)
|
|
|
|
|
2015-08-28 21:17:18 +00:00
|
|
|
exp := interfaceValues{
|
2015-05-14 16:55:17 +00:00
|
|
|
uint64(1),
|
|
|
|
float64(1),
|
|
|
|
"1",
|
|
|
|
}
|
|
|
|
|
|
|
|
if !reflect.DeepEqual(values, exp) {
|
|
|
|
t.Errorf("Wrong values. exp %v got %v", spew.Sdump(exp), spew.Sdump(values))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-05-14 17:14:47 +00:00
|
|
|
func TestMapDistinctNil(t *testing.T) {
|
|
|
|
iter := &testIterator{
|
2015-09-01 21:25:59 +00:00
|
|
|
values: []testPoint{},
|
2015-05-14 17:14:47 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
values := MapDistinct(iter)
|
|
|
|
|
|
|
|
if values != nil {
|
|
|
|
t.Errorf("Wrong values. exp nil got %v", spew.Sdump(values))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestReduceDistinct(t *testing.T) {
|
2015-08-28 21:17:18 +00:00
|
|
|
v1 := interfaceValues{
|
2015-05-14 17:14:47 +00:00
|
|
|
"2",
|
|
|
|
"1",
|
|
|
|
float64(2.0),
|
|
|
|
float64(1),
|
|
|
|
uint64(2),
|
|
|
|
uint64(1),
|
|
|
|
true,
|
|
|
|
false,
|
|
|
|
}
|
|
|
|
|
2015-08-28 21:17:18 +00:00
|
|
|
expect := interfaceValues{
|
2015-05-14 17:14:47 +00:00
|
|
|
uint64(1),
|
|
|
|
float64(1),
|
|
|
|
uint64(2),
|
|
|
|
float64(2),
|
|
|
|
false,
|
|
|
|
true,
|
|
|
|
"1",
|
|
|
|
"2",
|
|
|
|
}
|
|
|
|
|
|
|
|
got := ReduceDistinct([]interface{}{v1, v1, expect})
|
|
|
|
|
|
|
|
if !reflect.DeepEqual(got, expect) {
|
|
|
|
t.Errorf("Wrong values. exp %v got %v", spew.Sdump(expect), spew.Sdump(got))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestReduceDistinctNil(t *testing.T) {
|
|
|
|
tests := []struct {
|
|
|
|
name string
|
|
|
|
values []interface{}
|
|
|
|
}{
|
|
|
|
{
|
|
|
|
name: "nil values",
|
|
|
|
values: nil,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "nil mapper",
|
|
|
|
values: []interface{}{nil},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "no mappers",
|
|
|
|
values: []interface{}{},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "empty mappper (len 1)",
|
2015-08-28 21:17:18 +00:00
|
|
|
values: []interface{}{interfaceValues{}},
|
2015-05-14 17:14:47 +00:00
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "empty mappper (len 2)",
|
2015-08-28 21:17:18 +00:00
|
|
|
values: []interface{}{interfaceValues{}, interfaceValues{}},
|
2015-05-14 17:14:47 +00:00
|
|
|
},
|
|
|
|
}
|
|
|
|
|
|
|
|
for _, test := range tests {
|
|
|
|
t.Log(test.name)
|
|
|
|
got := ReduceDistinct(test.values)
|
|
|
|
if got != nil {
|
|
|
|
t.Errorf("Wrong values. exp nil got %v", spew.Sdump(got))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2015-05-14 16:55:17 +00:00
|
|
|
|
|
|
|
func Test_distinctValues_Sort(t *testing.T) {
|
2015-08-28 21:17:18 +00:00
|
|
|
values := interfaceValues{
|
2015-05-14 16:55:17 +00:00
|
|
|
"2",
|
|
|
|
"1",
|
|
|
|
float64(2.0),
|
|
|
|
float64(1),
|
|
|
|
uint64(2),
|
|
|
|
uint64(1),
|
|
|
|
true,
|
|
|
|
false,
|
|
|
|
}
|
|
|
|
|
2015-08-28 21:17:18 +00:00
|
|
|
expect := interfaceValues{
|
2015-05-14 16:55:17 +00:00
|
|
|
uint64(1),
|
|
|
|
float64(1),
|
|
|
|
uint64(2),
|
|
|
|
float64(2),
|
|
|
|
false,
|
|
|
|
true,
|
|
|
|
"1",
|
|
|
|
"2",
|
|
|
|
}
|
|
|
|
|
|
|
|
sort.Sort(values)
|
|
|
|
|
|
|
|
if !reflect.DeepEqual(values, expect) {
|
|
|
|
t.Errorf("Wrong values. exp %v got %v", spew.Sdump(expect), spew.Sdump(values))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-05-19 16:31:49 +00:00
|
|
|
func TestMapCountDistinct(t *testing.T) {
|
2015-05-29 20:12:00 +00:00
|
|
|
const ( // prove that we're ignoring seriesKey
|
|
|
|
seriesKey1 = "1"
|
|
|
|
seriesKey2 = "2"
|
2015-05-19 16:31:49 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
const ( // prove that we're ignoring time
|
|
|
|
timeId1 = iota + 1
|
|
|
|
timeId2
|
|
|
|
timeId3
|
|
|
|
timeId4
|
|
|
|
timeId5
|
|
|
|
timeId6
|
|
|
|
timeId7
|
|
|
|
)
|
|
|
|
|
|
|
|
iter := &testIterator{
|
2015-09-01 21:25:59 +00:00
|
|
|
values: []testPoint{
|
2015-08-28 21:17:18 +00:00
|
|
|
{seriesKey1, timeId1, uint64(1), nil},
|
|
|
|
{seriesKey1, timeId2, uint64(1), nil},
|
|
|
|
{seriesKey1, timeId3, "1", nil},
|
|
|
|
{seriesKey2, timeId4, uint64(1), nil},
|
|
|
|
{seriesKey2, timeId5, float64(1.0), nil},
|
|
|
|
{seriesKey2, timeId6, "1", nil},
|
|
|
|
{seriesKey2, timeId7, true, nil},
|
2015-05-19 16:31:49 +00:00
|
|
|
},
|
|
|
|
}
|
|
|
|
|
|
|
|
values := MapCountDistinct(iter).(map[interface{}]struct{})
|
|
|
|
|
|
|
|
if exp, got := 4, len(values); exp != got {
|
|
|
|
t.Errorf("Wrong number of values. exp %v got %v", exp, got)
|
|
|
|
}
|
|
|
|
|
|
|
|
exp := map[interface{}]struct{}{
|
|
|
|
uint64(1): struct{}{},
|
|
|
|
float64(1): struct{}{},
|
|
|
|
"1": struct{}{},
|
|
|
|
true: struct{}{},
|
|
|
|
}
|
|
|
|
|
|
|
|
if !reflect.DeepEqual(values, exp) {
|
|
|
|
t.Errorf("Wrong values. exp %v got %v", spew.Sdump(exp), spew.Sdump(values))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestMapCountDistinctNil(t *testing.T) {
|
|
|
|
iter := &testIterator{
|
2015-09-01 21:25:59 +00:00
|
|
|
values: []testPoint{},
|
2015-05-19 16:31:49 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
values := MapCountDistinct(iter)
|
|
|
|
|
|
|
|
if values != nil {
|
|
|
|
t.Errorf("Wrong values. exp nil got %v", spew.Sdump(values))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestReduceCountDistinct(t *testing.T) {
|
|
|
|
v1 := map[interface{}]struct{}{
|
|
|
|
"2": struct{}{},
|
|
|
|
"1": struct{}{},
|
|
|
|
float64(2.0): struct{}{},
|
|
|
|
float64(1): struct{}{},
|
|
|
|
uint64(2): struct{}{},
|
|
|
|
uint64(1): struct{}{},
|
|
|
|
true: struct{}{},
|
|
|
|
false: struct{}{},
|
|
|
|
}
|
|
|
|
|
|
|
|
v2 := map[interface{}]struct{}{
|
|
|
|
uint64(1): struct{}{},
|
|
|
|
float64(1): struct{}{},
|
|
|
|
uint64(2): struct{}{},
|
|
|
|
float64(2): struct{}{},
|
|
|
|
false: struct{}{},
|
|
|
|
true: struct{}{},
|
|
|
|
"1": struct{}{},
|
|
|
|
"2": struct{}{},
|
|
|
|
}
|
|
|
|
|
|
|
|
exp := 8
|
|
|
|
got := ReduceCountDistinct([]interface{}{v1, v1, v2})
|
|
|
|
|
|
|
|
if !reflect.DeepEqual(got, exp) {
|
|
|
|
t.Errorf("Wrong values. exp %v got %v", spew.Sdump(exp), spew.Sdump(got))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestReduceCountDistinctNil(t *testing.T) {
|
|
|
|
emptyResults := make(map[interface{}]struct{})
|
|
|
|
tests := []struct {
|
|
|
|
name string
|
|
|
|
values []interface{}
|
|
|
|
}{
|
|
|
|
{
|
|
|
|
name: "nil values",
|
|
|
|
values: nil,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "nil mapper",
|
|
|
|
values: []interface{}{nil},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "no mappers",
|
|
|
|
values: []interface{}{},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "empty mappper (len 1)",
|
|
|
|
values: []interface{}{emptyResults},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "empty mappper (len 2)",
|
|
|
|
values: []interface{}{emptyResults, emptyResults},
|
|
|
|
},
|
|
|
|
}
|
|
|
|
|
|
|
|
for _, test := range tests {
|
|
|
|
t.Log(test.name)
|
|
|
|
got := ReduceCountDistinct(test.values)
|
|
|
|
if got != 0 {
|
|
|
|
t.Errorf("Wrong values. exp nil got %v", spew.Sdump(got))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-05-04 21:59:39 +00:00
|
|
|
var getSortedRangeData = []float64{
|
|
|
|
60, 61, 62, 63, 64, 65, 66, 67, 68, 69,
|
|
|
|
20, 21, 22, 23, 24, 25, 26, 27, 28, 29,
|
|
|
|
0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
|
|
|
|
40, 41, 42, 43, 44, 45, 46, 47, 48, 49,
|
|
|
|
10, 11, 12, 13, 14, 15, 16, 17, 18, 19,
|
|
|
|
50, 51, 52, 53, 54, 55, 56, 57, 58, 59,
|
|
|
|
30, 31, 32, 33, 34, 35, 36, 37, 38, 39,
|
|
|
|
}
|
|
|
|
|
|
|
|
var getSortedRangeTests = []struct {
|
|
|
|
name string
|
|
|
|
data []float64
|
|
|
|
start int
|
|
|
|
count int
|
|
|
|
expected []float64
|
|
|
|
}{
|
|
|
|
{"first 5", getSortedRangeData, 0, 5, []float64{0, 1, 2, 3, 4}},
|
|
|
|
{"0 length", getSortedRangeData, 8, 0, []float64{}},
|
|
|
|
{"past end of data", getSortedRangeData, len(getSortedRangeData) - 3, 5, []float64{67, 68, 69}},
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestGetSortedRange(t *testing.T) {
|
|
|
|
for _, tt := range getSortedRangeTests {
|
|
|
|
results := getSortedRange(tt.data, tt.start, tt.count)
|
|
|
|
if len(results) != len(tt.expected) {
|
2015-05-30 14:57:27 +00:00
|
|
|
t.Errorf("Test %s error. Expected getSortedRange to return %v but got %v", tt.name, tt.expected, results)
|
2015-05-04 21:59:39 +00:00
|
|
|
}
|
2015-09-01 21:25:59 +00:00
|
|
|
for i, testPoint := range tt.expected {
|
|
|
|
if testPoint != results[i] {
|
|
|
|
t.Errorf("Test %s error. getSortedRange returned wrong result for index %v. Expected %v but got %v", tt.name, i, testPoint, results[i])
|
2015-05-04 21:59:39 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
var benchGetSortedRangeResults []float64
|
|
|
|
|
|
|
|
func BenchmarkGetSortedRangeByPivot(b *testing.B) {
|
|
|
|
data := make([]float64, len(getSortedRangeData))
|
|
|
|
var results []float64
|
|
|
|
for i := 0; i < b.N; i++ {
|
|
|
|
copy(data, getSortedRangeData)
|
|
|
|
results = getSortedRange(data, 8, 15)
|
|
|
|
}
|
|
|
|
benchGetSortedRangeResults = results
|
|
|
|
}
|
|
|
|
|
|
|
|
func BenchmarkGetSortedRangeBySort(b *testing.B) {
|
|
|
|
data := make([]float64, len(getSortedRangeData))
|
|
|
|
var results []float64
|
|
|
|
for i := 0; i < b.N; i++ {
|
|
|
|
copy(data, getSortedRangeData)
|
|
|
|
sort.Float64s(data)
|
|
|
|
results = data[8:23]
|
|
|
|
}
|
|
|
|
benchGetSortedRangeResults = results
|
|
|
|
}
|
2015-08-28 21:17:18 +00:00
|
|
|
|
|
|
|
func TestMapTop(t *testing.T) {
|
|
|
|
tests := []struct {
|
|
|
|
name string
|
|
|
|
skip bool
|
|
|
|
iter *testIterator
|
2015-08-31 22:34:00 +00:00
|
|
|
exp positionOut
|
2015-09-01 21:25:59 +00:00
|
|
|
call *influxql.Call
|
2015-08-28 21:17:18 +00:00
|
|
|
}{
|
|
|
|
{
|
|
|
|
name: "int64 - basic",
|
|
|
|
iter: &testIterator{
|
2015-09-01 21:25:59 +00:00
|
|
|
values: []testPoint{
|
2015-08-28 21:17:18 +00:00
|
|
|
{"", 10, int64(99), map[string]string{"host": "a"}},
|
|
|
|
{"", 10, int64(53), map[string]string{"host": "b"}},
|
|
|
|
{"", 20, int64(88), map[string]string{"host": "a"}},
|
|
|
|
},
|
|
|
|
},
|
2015-08-31 22:34:00 +00:00
|
|
|
exp: positionOut{
|
|
|
|
points: PositionPoints{
|
2015-09-04 16:42:46 +00:00
|
|
|
PositionPoint{10, int64(99), map[string]string{"host": "a"}},
|
|
|
|
PositionPoint{20, int64(88), map[string]string{"host": "a"}},
|
2015-08-28 21:17:18 +00:00
|
|
|
},
|
|
|
|
},
|
2015-09-01 21:25:59 +00:00
|
|
|
call: &influxql.Call{Name: "top", Args: []influxql.Expr{&influxql.VarRef{Val: "field1"}, &influxql.NumberLiteral{Val: 2}}},
|
2015-08-28 21:17:18 +00:00
|
|
|
},
|
|
|
|
{
|
2015-09-03 20:04:47 +00:00
|
|
|
name: "int64 - basic with tag",
|
2015-08-28 21:17:18 +00:00
|
|
|
iter: &testIterator{
|
2015-09-01 21:25:59 +00:00
|
|
|
values: []testPoint{
|
2015-08-28 21:17:18 +00:00
|
|
|
{"", 10, int64(99), map[string]string{"host": "a"}},
|
2015-09-03 20:04:47 +00:00
|
|
|
{"", 20, int64(53), map[string]string{"host": "b"}},
|
|
|
|
{"", 30, int64(88), map[string]string{"host": "a"}},
|
2015-08-28 21:17:18 +00:00
|
|
|
},
|
|
|
|
},
|
2015-08-31 22:34:00 +00:00
|
|
|
exp: positionOut{
|
2015-08-28 21:17:18 +00:00
|
|
|
callArgs: []string{"host"},
|
2015-08-31 22:34:00 +00:00
|
|
|
points: PositionPoints{
|
2015-09-04 16:42:46 +00:00
|
|
|
PositionPoint{10, int64(99), map[string]string{"host": "a"}},
|
|
|
|
PositionPoint{20, int64(53), map[string]string{"host": "b"}},
|
2015-08-28 21:17:18 +00:00
|
|
|
},
|
|
|
|
},
|
2015-09-01 21:25:59 +00:00
|
|
|
call: &influxql.Call{Name: "top", Args: []influxql.Expr{&influxql.VarRef{Val: "field1"}, &influxql.VarRef{Val: "host"}, &influxql.NumberLiteral{Val: 2}}},
|
2015-08-28 21:17:18 +00:00
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "int64 - tie on value, resolve based on time",
|
|
|
|
iter: &testIterator{
|
2015-09-01 21:25:59 +00:00
|
|
|
values: []testPoint{
|
2015-08-28 21:17:18 +00:00
|
|
|
{"", 20, int64(99), map[string]string{"host": "a"}},
|
2015-09-03 20:04:47 +00:00
|
|
|
{"", 10, int64(53), map[string]string{"host": "a"}},
|
2015-08-28 21:17:18 +00:00
|
|
|
{"", 10, int64(99), map[string]string{"host": "a"}},
|
|
|
|
},
|
|
|
|
},
|
2015-08-31 22:34:00 +00:00
|
|
|
exp: positionOut{
|
2015-08-28 21:17:18 +00:00
|
|
|
callArgs: []string{"host"},
|
2015-08-31 22:34:00 +00:00
|
|
|
points: PositionPoints{
|
2015-09-04 16:42:46 +00:00
|
|
|
PositionPoint{10, int64(99), map[string]string{"host": "a"}},
|
|
|
|
PositionPoint{20, int64(99), map[string]string{"host": "a"}},
|
2015-08-28 21:17:18 +00:00
|
|
|
},
|
|
|
|
},
|
2015-09-01 21:25:59 +00:00
|
|
|
call: &influxql.Call{Name: "top", Args: []influxql.Expr{&influxql.VarRef{Val: "field1"}, &influxql.VarRef{Val: "host"}, &influxql.NumberLiteral{Val: 2}}},
|
2015-08-28 21:17:18 +00:00
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "int64 - tie on value, time, resolve based on tags",
|
|
|
|
iter: &testIterator{
|
2015-09-01 21:25:59 +00:00
|
|
|
values: []testPoint{
|
2015-08-28 21:17:18 +00:00
|
|
|
{"", 10, int64(99), map[string]string{"host": "b"}},
|
|
|
|
{"", 10, int64(99), map[string]string{"host": "a"}},
|
|
|
|
{"", 20, int64(88), map[string]string{"host": "a"}},
|
|
|
|
},
|
|
|
|
},
|
2015-08-31 22:34:00 +00:00
|
|
|
exp: positionOut{
|
2015-08-28 21:17:18 +00:00
|
|
|
callArgs: []string{"host"},
|
2015-08-31 22:34:00 +00:00
|
|
|
points: PositionPoints{
|
2015-09-04 16:42:46 +00:00
|
|
|
PositionPoint{10, int64(99), map[string]string{"host": "a"}},
|
|
|
|
PositionPoint{10, int64(99), map[string]string{"host": "b"}},
|
2015-08-28 21:17:18 +00:00
|
|
|
},
|
|
|
|
},
|
2015-09-01 21:25:59 +00:00
|
|
|
call: &influxql.Call{Name: "top", Args: []influxql.Expr{&influxql.VarRef{Val: "field1"}, &influxql.VarRef{Val: "host"}, &influxql.NumberLiteral{Val: 2}}},
|
2015-08-28 21:17:18 +00:00
|
|
|
},
|
2015-08-28 21:27:34 +00:00
|
|
|
{
|
|
|
|
name: "mixed numerics - ints",
|
|
|
|
iter: &testIterator{
|
2015-09-01 21:25:59 +00:00
|
|
|
values: []testPoint{
|
2015-08-28 21:27:34 +00:00
|
|
|
{"", 10, int64(99), map[string]string{"host": "a"}},
|
|
|
|
{"", 10, int64(53), map[string]string{"host": "b"}},
|
|
|
|
{"", 20, uint64(88), map[string]string{"host": "a"}},
|
|
|
|
},
|
|
|
|
},
|
2015-08-31 22:34:00 +00:00
|
|
|
exp: positionOut{
|
|
|
|
points: PositionPoints{
|
2015-09-04 16:42:46 +00:00
|
|
|
PositionPoint{10, int64(99), map[string]string{"host": "a"}},
|
|
|
|
PositionPoint{20, uint64(88), map[string]string{"host": "a"}},
|
2015-08-28 21:27:34 +00:00
|
|
|
},
|
|
|
|
},
|
2015-09-01 21:25:59 +00:00
|
|
|
call: &influxql.Call{Name: "top", Args: []influxql.Expr{&influxql.VarRef{Val: "field1"}, &influxql.NumberLiteral{Val: 2}}},
|
2015-08-28 21:27:34 +00:00
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "mixed numerics - ints & floats",
|
|
|
|
iter: &testIterator{
|
2015-09-01 21:25:59 +00:00
|
|
|
values: []testPoint{
|
2015-08-28 21:27:34 +00:00
|
|
|
{"", 10, float64(99), map[string]string{"host": "a"}},
|
|
|
|
{"", 10, int64(53), map[string]string{"host": "b"}},
|
|
|
|
{"", 20, uint64(88), map[string]string{"host": "a"}},
|
|
|
|
},
|
|
|
|
},
|
2015-08-31 22:34:00 +00:00
|
|
|
exp: positionOut{
|
|
|
|
points: PositionPoints{
|
2015-09-04 16:42:46 +00:00
|
|
|
PositionPoint{10, float64(99), map[string]string{"host": "a"}},
|
|
|
|
PositionPoint{20, uint64(88), map[string]string{"host": "a"}},
|
2015-08-28 21:27:34 +00:00
|
|
|
},
|
|
|
|
},
|
2015-09-01 21:25:59 +00:00
|
|
|
call: &influxql.Call{Name: "top", Args: []influxql.Expr{&influxql.VarRef{Val: "field1"}, &influxql.NumberLiteral{Val: 2}}},
|
2015-08-28 21:27:34 +00:00
|
|
|
},
|
2015-08-31 15:49:19 +00:00
|
|
|
{
|
|
|
|
name: "mixed numerics - ints, floats, & strings",
|
|
|
|
iter: &testIterator{
|
2015-09-01 21:25:59 +00:00
|
|
|
values: []testPoint{
|
2015-08-31 15:49:19 +00:00
|
|
|
{"", 10, float64(99), map[string]string{"host": "a"}},
|
|
|
|
{"", 10, int64(53), map[string]string{"host": "b"}},
|
|
|
|
{"", 20, "88", map[string]string{"host": "a"}},
|
|
|
|
},
|
|
|
|
},
|
2015-08-31 22:34:00 +00:00
|
|
|
exp: positionOut{
|
|
|
|
points: PositionPoints{
|
2015-09-04 16:42:46 +00:00
|
|
|
PositionPoint{10, float64(99), map[string]string{"host": "a"}},
|
|
|
|
PositionPoint{10, int64(53), map[string]string{"host": "b"}},
|
2015-08-31 15:49:19 +00:00
|
|
|
},
|
|
|
|
},
|
2015-09-01 21:25:59 +00:00
|
|
|
call: &influxql.Call{Name: "top", Args: []influxql.Expr{&influxql.VarRef{Val: "field1"}, &influxql.NumberLiteral{Val: 2}}},
|
2015-08-31 15:49:19 +00:00
|
|
|
},
|
2015-08-31 15:51:49 +00:00
|
|
|
{
|
|
|
|
name: "bools",
|
|
|
|
iter: &testIterator{
|
2015-09-01 21:25:59 +00:00
|
|
|
values: []testPoint{
|
2015-08-31 15:51:49 +00:00
|
|
|
{"", 10, true, map[string]string{"host": "a"}},
|
|
|
|
{"", 10, true, map[string]string{"host": "b"}},
|
|
|
|
{"", 20, false, map[string]string{"host": "a"}},
|
|
|
|
},
|
|
|
|
},
|
2015-08-31 22:34:00 +00:00
|
|
|
exp: positionOut{
|
|
|
|
points: PositionPoints{
|
2015-09-04 16:42:46 +00:00
|
|
|
PositionPoint{10, true, map[string]string{"host": "a"}},
|
|
|
|
PositionPoint{10, true, map[string]string{"host": "b"}},
|
2015-08-31 15:51:49 +00:00
|
|
|
},
|
|
|
|
},
|
2015-09-01 21:25:59 +00:00
|
|
|
call: &influxql.Call{Name: "top", Args: []influxql.Expr{&influxql.VarRef{Val: "field1"}, &influxql.NumberLiteral{Val: 2}}},
|
2015-08-31 15:51:49 +00:00
|
|
|
},
|
2015-08-28 21:17:18 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
for _, test := range tests {
|
|
|
|
if test.skip {
|
|
|
|
continue
|
|
|
|
}
|
2015-08-31 22:34:00 +00:00
|
|
|
values := MapTop(test.iter, test.call).(PositionPoints)
|
2015-08-31 15:49:19 +00:00
|
|
|
t.Logf("Test: %s", test.name)
|
2015-08-31 22:34:00 +00:00
|
|
|
if exp, got := len(test.exp.points), len(values); exp != got {
|
2015-08-28 21:17:18 +00:00
|
|
|
t.Errorf("Wrong number of values. exp %v got %v", exp, got)
|
|
|
|
}
|
2015-08-31 22:34:00 +00:00
|
|
|
if !reflect.DeepEqual(values, test.exp.points) {
|
|
|
|
t.Errorf("Wrong values. \nexp\n %v\ngot\n %v", spew.Sdump(test.exp.points), spew.Sdump(values))
|
2015-08-28 21:17:18 +00:00
|
|
|
}
|
2015-08-31 19:20:46 +00:00
|
|
|
}
|
|
|
|
}
|
2015-08-28 21:17:18 +00:00
|
|
|
|
2015-08-31 19:20:46 +00:00
|
|
|
func TestReduceTop(t *testing.T) {
|
|
|
|
tests := []struct {
|
|
|
|
name string
|
|
|
|
skip bool
|
|
|
|
values []interface{}
|
2015-08-31 22:34:00 +00:00
|
|
|
exp PositionPoints
|
2015-09-01 21:25:59 +00:00
|
|
|
call *influxql.Call
|
2015-08-31 19:20:46 +00:00
|
|
|
}{
|
|
|
|
{
|
|
|
|
name: "int64 - single map",
|
|
|
|
values: []interface{}{
|
2015-08-31 22:34:00 +00:00
|
|
|
PositionPoints{
|
2015-08-31 19:20:46 +00:00
|
|
|
{10, int64(99), map[string]string{"host": "a"}},
|
|
|
|
{10, int64(53), map[string]string{"host": "b"}},
|
|
|
|
{20, int64(88), map[string]string{"host": "a"}},
|
|
|
|
},
|
|
|
|
},
|
2015-08-31 22:34:00 +00:00
|
|
|
exp: PositionPoints{
|
2015-09-04 16:42:46 +00:00
|
|
|
PositionPoint{10, int64(99), map[string]string{"host": "a"}},
|
|
|
|
PositionPoint{20, int64(88), map[string]string{"host": "a"}},
|
2015-08-31 19:20:46 +00:00
|
|
|
},
|
2015-09-01 21:25:59 +00:00
|
|
|
call: &influxql.Call{Name: "top", Args: []influxql.Expr{&influxql.VarRef{Val: "field1"}, &influxql.NumberLiteral{Val: 2}}},
|
2015-08-31 19:20:46 +00:00
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "int64 - double map",
|
|
|
|
values: []interface{}{
|
2015-08-31 22:34:00 +00:00
|
|
|
PositionPoints{
|
2015-08-31 19:20:46 +00:00
|
|
|
{10, int64(99), map[string]string{"host": "a"}},
|
|
|
|
},
|
2015-08-31 22:34:00 +00:00
|
|
|
PositionPoints{
|
2015-08-31 19:20:46 +00:00
|
|
|
{10, int64(53), map[string]string{"host": "b"}},
|
|
|
|
{20, int64(88), map[string]string{"host": "a"}},
|
|
|
|
},
|
|
|
|
},
|
2015-08-31 22:34:00 +00:00
|
|
|
exp: PositionPoints{
|
2015-09-04 16:42:46 +00:00
|
|
|
PositionPoint{10, int64(99), map[string]string{"host": "a"}},
|
|
|
|
PositionPoint{20, int64(88), map[string]string{"host": "a"}},
|
2015-08-31 19:20:46 +00:00
|
|
|
},
|
2015-09-01 21:25:59 +00:00
|
|
|
call: &influxql.Call{Name: "top", Args: []influxql.Expr{&influxql.VarRef{Val: "field1"}, &influxql.NumberLiteral{Val: 2}}},
|
2015-08-31 19:20:46 +00:00
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "int64 - double map with nil",
|
|
|
|
values: []interface{}{
|
2015-08-31 22:34:00 +00:00
|
|
|
PositionPoints{
|
2015-08-31 19:20:46 +00:00
|
|
|
{10, int64(99), map[string]string{"host": "a"}},
|
|
|
|
{10, int64(53), map[string]string{"host": "b"}},
|
|
|
|
{20, int64(88), map[string]string{"host": "a"}},
|
|
|
|
},
|
|
|
|
nil,
|
|
|
|
},
|
2015-08-31 22:34:00 +00:00
|
|
|
exp: PositionPoints{
|
2015-09-04 16:42:46 +00:00
|
|
|
PositionPoint{10, int64(99), map[string]string{"host": "a"}},
|
|
|
|
PositionPoint{20, int64(88), map[string]string{"host": "a"}},
|
2015-08-31 19:20:46 +00:00
|
|
|
},
|
2015-09-01 21:25:59 +00:00
|
|
|
call: &influxql.Call{Name: "top", Args: []influxql.Expr{&influxql.VarRef{Val: "field1"}, &influxql.NumberLiteral{Val: 2}}},
|
2015-08-31 19:20:46 +00:00
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "int64 - double map with non-matching tags and tag selected",
|
|
|
|
values: []interface{}{
|
2015-08-31 22:34:00 +00:00
|
|
|
PositionPoints{
|
2015-08-31 19:20:46 +00:00
|
|
|
{10, int64(99), map[string]string{"host": "a"}},
|
|
|
|
{10, int64(53), map[string]string{"host": "b"}},
|
|
|
|
{20, int64(88), map[string]string{}},
|
|
|
|
},
|
|
|
|
nil,
|
|
|
|
},
|
2015-08-31 22:34:00 +00:00
|
|
|
exp: PositionPoints{
|
2015-09-04 16:42:46 +00:00
|
|
|
PositionPoint{10, int64(99), map[string]string{"host": "a"}},
|
|
|
|
PositionPoint{20, int64(88), map[string]string{}},
|
2015-08-31 19:20:46 +00:00
|
|
|
},
|
2015-09-01 21:25:59 +00:00
|
|
|
call: &influxql.Call{Name: "top", Args: []influxql.Expr{&influxql.VarRef{Val: "field1"}, &influxql.VarRef{Val: "host"}, &influxql.NumberLiteral{Val: 2}}},
|
2015-08-31 19:20:46 +00:00
|
|
|
},
|
|
|
|
{
|
2015-08-31 19:22:10 +00:00
|
|
|
skip: true,
|
2015-08-31 19:20:46 +00:00
|
|
|
name: "int64 - double map with non-matching tags",
|
|
|
|
values: []interface{}{
|
2015-08-31 22:34:00 +00:00
|
|
|
PositionPoints{
|
2015-08-31 19:20:46 +00:00
|
|
|
{10, int64(99), map[string]string{"host": "a"}},
|
|
|
|
{10, int64(53), map[string]string{"host": "b"}},
|
|
|
|
{20, int64(88), map[string]string{}},
|
|
|
|
},
|
|
|
|
nil,
|
|
|
|
},
|
2015-08-31 22:34:00 +00:00
|
|
|
exp: PositionPoints{
|
2015-09-04 16:42:46 +00:00
|
|
|
PositionPoint{10, int64(99), map[string]string{"host": "a"}},
|
|
|
|
PositionPoint{20, int64(55), map[string]string{"host": "b"}},
|
2015-08-31 19:20:46 +00:00
|
|
|
},
|
2015-09-01 21:25:59 +00:00
|
|
|
call: &influxql.Call{Name: "top", Args: []influxql.Expr{&influxql.VarRef{Val: "field1"}, &influxql.NumberLiteral{Val: 2}}},
|
2015-08-31 19:20:46 +00:00
|
|
|
},
|
2015-08-28 21:17:18 +00:00
|
|
|
}
|
|
|
|
|
2015-08-31 19:20:46 +00:00
|
|
|
for _, test := range tests {
|
|
|
|
if test.skip {
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
values := ReduceTop(test.values, test.call)
|
|
|
|
t.Logf("Test: %s", test.name)
|
|
|
|
if values != nil {
|
2015-08-31 22:34:00 +00:00
|
|
|
v, _ := values.(PositionPoints)
|
2015-08-31 19:20:46 +00:00
|
|
|
if exp, got := len(test.exp), len(v); exp != got {
|
|
|
|
t.Errorf("Wrong number of values. exp %v got %v", exp, got)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if !reflect.DeepEqual(values, test.exp) {
|
|
|
|
t.Errorf("Wrong values. \nexp\n %v\ngot\n %v", spew.Sdump(test.exp), spew.Sdump(values))
|
|
|
|
}
|
|
|
|
}
|
2015-08-28 21:17:18 +00:00
|
|
|
}
|