예제 #1
0
func Test_distinctValues_Sort(t *testing.T) {
	values := interfaceValues{
		"2",
		"1",
		float64(2.0),
		float64(1),
		uint64(2),
		uint64(1),
		true,
		false,
	}

	expect := interfaceValues{
		"1",
		"2",
		false,
		true,
		uint64(1),
		float64(1),
		uint64(2),
		float64(2),
	}

	sort.Sort(values)

	if !reflect.DeepEqual(values, expect) {
		t.Errorf("Wrong values. exp %v got %v", spew.Sdump(expect), spew.Sdump(values))
	}
}
예제 #2
0
func TestReduceDistinct(t *testing.T) {
	v1 := interfaceValues{
		"2",
		"1",
		float64(2.0),
		float64(1),
		uint64(2),
		uint64(1),
		true,
		false,
	}

	expect := interfaceValues{
		"1",
		"2",
		false,
		true,
		uint64(1),
		float64(1),
		uint64(2),
		float64(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))
	}
}
예제 #3
0
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))
	}
}
예제 #4
0
// Ensure a SHOW SERVERS statement can be executed.
func TestStatementExecutor_ExecuteStatement_ShowServers(t *testing.T) {
	e := NewStatementExecutor()
	e.Store.NodesFn = func() ([]meta.NodeInfo, error) {
		return []meta.NodeInfo{
			{ID: 1, Host: "node0"},
			{ID: 2, Host: "node1"},
		}, nil
	}
	e.Store.PeersFn = func() ([]string, error) {
		return []string{"node0"}, nil
	}

	if res := e.ExecuteStatement(influxql.MustParseStatement(`SHOW SERVERS`)); res.Err != nil {
		t.Fatal(res.Err)
	} else if !reflect.DeepEqual(res.Series, models.Rows{
		{
			Columns: []string{"id", "cluster_addr", "raft"},
			Values: [][]interface{}{
				{uint64(1), "node0", true},
				{uint64(2), "node1", false},
			},
		},
	}) {
		t.Fatalf("unexpected rows: %s", spew.Sdump(res.Series))
	}
}
예제 #5
0
// Ensure a SHOW GRANTS FOR statement can be executed.
func TestStatementExecutor_ExecuteStatement_ShowGrantsFor(t *testing.T) {
	t.Skip("Intermittent test failure: issue 3028")
	e := NewStatementExecutor()
	e.Store.UserPrivilegesFn = func(username string) (map[string]influxql.Privilege, error) {
		if username != "dejan" {
			t.Fatalf("unexpected username: %s", username)
		}
		return map[string]influxql.Privilege{
			"dejan": influxql.ReadPrivilege,
			"golja": influxql.WritePrivilege,
		}, nil
	}

	if res := e.ExecuteStatement(influxql.MustParseStatement(`SHOW GRANTS FOR dejan`)); res.Err != nil {
		t.Fatal(res.Err)
	} else if !reflect.DeepEqual(res.Series, models.Rows{
		{
			Columns: []string{"database", "privilege"},
			Values: [][]interface{}{
				{"dejan", "READ"},
				{"golja", "WRITE"},
			},
		},
	}) {
		t.Fatalf("unexpected rows: %s", spew.Sdump(res.Series))
	}
}
예제 #6
0
파일: data_test.go 프로젝트: eswdd/bosun
// Ensure shards with deprecated "OwnerIDs" can be decoded.
func TestShardInfo_UnmarshalBinary_OwnerIDs(t *testing.T) {
	// Encode deprecated form to bytes.
	buf, err := proto.Marshal(&internal.ShardInfo{
		ID:       proto.Uint64(1),
		OwnerIDs: []uint64{10, 20, 30},
	})
	if err != nil {
		t.Fatal(err)
	}

	// Decode deprecated form.
	var si meta.ShardInfo
	if err := si.UnmarshalBinary(buf); err != nil {
		t.Fatal(err)
	}

	// Verify data is migrated correctly.
	if !reflect.DeepEqual(si, meta.ShardInfo{
		ID: 1,
		Owners: []meta.ShardOwner{
			{NodeID: 10},
			{NodeID: 20},
			{NodeID: 30},
		},
	}) {
		t.Fatalf("unexpected shard info: %s", spew.Sdump(si))
	}
}
예제 #7
0
func TestMapDistinctNil(t *testing.T) {
	values := MapDistinct(&MapInput{})

	if values != nil {
		t.Errorf("Wrong values. exp nil got %v", spew.Sdump(values))
	}
}
예제 #8
0
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)",
			values: []interface{}{interfaceValues{}},
		},
		{
			name:   "empty mappper (len 2)",
			values: []interface{}{interfaceValues{}, interfaceValues{}},
		},
	}

	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))
		}
	}
}
예제 #9
0
func TestMapCountDistinct(t *testing.T) {
	const ( // prove that we're ignoring seriesKey
		seriesKey1 = "1"
		seriesKey2 = "2"
	)

	const ( // prove that we're ignoring time
		timeId1 = iota + 1
		timeId2
		timeId3
		timeId4
		timeId5
		timeId6
		timeId7
	)

	iter := &testIterator{
		values: []point{
			{seriesKey1, timeId1, uint64(1)},
			{seriesKey1, timeId2, uint64(1)},
			{seriesKey1, timeId3, "1"},
			{seriesKey2, timeId4, uint64(1)},
			{seriesKey2, timeId5, float64(1.0)},
			{seriesKey2, timeId6, "1"},
			{seriesKey2, timeId7, true},
		},
	}

	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))
	}
}
예제 #10
0
func TestMapDistinct(t *testing.T) {
	const ( // prove that we're ignoring seriesKey
		seriesKey1 = "1"
		seriesKey2 = "2"
	)

	const ( // prove that we're ignoring time
		timeId1 = iota + 1
		timeId2
		timeId3
		timeId4
		timeId5
		timeId6
	)

	iter := &testIterator{
		values: []point{
			{seriesKey1, timeId1, uint64(1)},
			{seriesKey1, timeId2, uint64(1)},
			{seriesKey1, timeId3, "1"},
			{seriesKey2, timeId4, uint64(1)},
			{seriesKey2, timeId5, float64(1.0)},
			{seriesKey2, timeId6, "1"},
		},
	}

	values := MapDistinct(iter).(distinctValues)

	if exp, got := 3, len(values); exp != got {
		t.Errorf("Wrong number of values. exp %v got %v", exp, got)
	}

	sort.Sort(values)

	exp := distinctValues{
		uint64(1),
		float64(1),
		"1",
	}

	if !reflect.DeepEqual(values, exp) {
		t.Errorf("Wrong values. exp %v got %v", spew.Sdump(exp), spew.Sdump(values))
	}
}
예제 #11
0
func TestMapCountDistinctNil(t *testing.T) {
	iter := &testIterator{
		values: []point{},
	}

	values := MapCountDistinct(iter)

	if values != nil {
		t.Errorf("Wrong values. exp nil got %v", spew.Sdump(values))
	}
}
예제 #12
0
func TestMapCountDistinct(t *testing.T) {
	const ( // prove that we're ignoring time
		timeId1 = iota + 1
		timeId2
		timeId3
		timeId4
		timeId5
		timeId6
		timeId7
	)

	input := &MapInput{
		Items: []MapItem{
			{Timestamp: timeId1, Value: uint64(1)},
			{Timestamp: timeId2, Value: uint64(1)},
			{Timestamp: timeId3, Value: "1"},
			{Timestamp: timeId4, Value: uint64(1)},
			{Timestamp: timeId5, Value: float64(1.0)},
			{Timestamp: timeId6, Value: "1"},
			{Timestamp: timeId7, Value: true},
		},
	}

	values := MapCountDistinct(input).(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))
	}
}
예제 #13
0
func TestMapDistinct(t *testing.T) {
	const ( // prove that we're ignoring time
		timeId1 = iota + 1
		timeId2
		timeId3
		timeId4
		timeId5
		timeId6
	)

	input := &MapInput{
		Items: []MapItem{
			{Timestamp: timeId1, Value: uint64(1)},
			{Timestamp: timeId2, Value: uint64(1)},
			{Timestamp: timeId3, Value: "1"},
			{Timestamp: timeId4, Value: uint64(1)},
			{Timestamp: timeId5, Value: float64(1.0)},
			{Timestamp: timeId6, Value: "1"},
		},
	}

	values := MapDistinct(input).(interfaceValues)

	if exp, got := 3, len(values); exp != got {
		t.Errorf("Wrong number of values. exp %v got %v", exp, got)
	}

	sort.Sort(values)

	exp := interfaceValues{
		"1",
		uint64(1),
		float64(1),
	}

	if !reflect.DeepEqual(values, exp) {
		t.Errorf("Wrong values. exp %v got %v", spew.Sdump(exp), spew.Sdump(values))
	}
}
예제 #14
0
// Ensure a SHOW SHARDS statement can be executed.
func TestStatementExecutor_ExecuteStatement_ShowShards(t *testing.T) {
	e := NewStatementExecutor()
	e.Store.DatabasesFn = func() ([]meta.DatabaseInfo, error) {
		return []meta.DatabaseInfo{
			{
				Name: "foo",
				RetentionPolicies: []meta.RetentionPolicyInfo{
					{
						Duration: time.Second,
						ShardGroups: []meta.ShardGroupInfo{
							{
								StartTime: time.Unix(0, 0),
								EndTime:   time.Unix(1, 0),
								Shards: []meta.ShardInfo{
									{
										ID: 1,
										Owners: []meta.ShardOwner{
											{NodeID: 1},
											{NodeID: 2},
											{NodeID: 3},
										},
									},
									{
										ID: 2,
									},
								},
							},
						},
					},
				},
			},
		}, nil
	}

	if res := e.ExecuteStatement(influxql.MustParseStatement(`SHOW SHARDS`)); res.Err != nil {
		t.Fatal(res.Err)
	} else if !reflect.DeepEqual(res.Series, models.Rows{
		{
			Name:    "foo",
			Columns: []string{"id", "start_time", "end_time", "expiry_time", "owners"},
			Values: [][]interface{}{
				{uint64(1), "1970-01-01T00:00:00Z", "1970-01-01T00:00:01Z", "1970-01-01T00:00:02Z", "1,2,3"},
				{uint64(2), "1970-01-01T00:00:00Z", "1970-01-01T00:00:01Z", "1970-01-01T00:00:02Z", ""},
			},
		},
	}) {
		t.Fatalf("unexpected rows: %s", spew.Sdump(res.Series))
	}
}
예제 #15
0
// Ensure a SHOW CONTINUOUS QUERIES statement can be executed.
func TestStatementExecutor_ExecuteStatement_ShowContinuousQueries(t *testing.T) {
	e := NewStatementExecutor()
	e.Store.DatabasesFn = func() ([]meta.DatabaseInfo, error) {
		return []meta.DatabaseInfo{
			{
				Name: "db0",
				ContinuousQueries: []meta.ContinuousQueryInfo{
					{Name: "cq0", Query: "SELECT count(field1) INTO db1 FROM db0"},
					{Name: "cq1", Query: "SELECT count(field1) INTO db2 FROM db0"},
				},
			},
			{
				Name: "db1",
				ContinuousQueries: []meta.ContinuousQueryInfo{
					{Name: "cq2", Query: "SELECT count(field1) INTO db3 FROM db1"},
				},
			},
		}, nil
	}

	stmt := influxql.MustParseStatement(`SHOW CONTINUOUS QUERIES`)
	if res := e.ExecuteStatement(stmt); res.Err != nil {
		t.Fatal(res.Err)
	} else if !reflect.DeepEqual(res.Series, models.Rows{
		{
			Name:    "db0",
			Columns: []string{"name", "query"},
			Values: [][]interface{}{
				{"cq0", "SELECT count(field1) INTO db1 FROM db0"},
				{"cq1", "SELECT count(field1) INTO db2 FROM db0"},
			},
		},
		{
			Name:    "db1",
			Columns: []string{"name", "query"},
			Values: [][]interface{}{
				{"cq2", "SELECT count(field1) INTO db3 FROM db1"},
			},
		},
	}) {
		t.Fatalf("unexpected rows: %s", spew.Sdump(res.Series))
	}
}
예제 #16
0
// Ensure a SHOW RETENTION POLICIES statement can be executed.
func TestStatementExecutor_ExecuteStatement_ShowRetentionPolicies(t *testing.T) {
	e := NewStatementExecutor()
	e.Store.DatabaseFn = func(name string) (*meta.DatabaseInfo, error) {
		if name != "db0" {
			t.Fatalf("unexpected name: %s", name)
		}
		return &meta.DatabaseInfo{
			Name: name,
			DefaultRetentionPolicy: "rp1",
			RetentionPolicies: []meta.RetentionPolicyInfo{
				{
					Name:     "rp0",
					Duration: 2 * time.Hour,
					ReplicaN: 3,
				},
				{
					Name:     "rp1",
					Duration: 24 * time.Hour,
					ReplicaN: 1,
				},
			},
		}, nil
	}

	if res := e.ExecuteStatement(influxql.MustParseStatement(`SHOW RETENTION POLICIES ON db0`)); res.Err != nil {
		t.Fatal(res.Err)
	} else if !reflect.DeepEqual(res.Series, models.Rows{
		{
			Columns: []string{"name", "duration", "replicaN", "default"},
			Values: [][]interface{}{
				{"rp0", "2h0m0s", 3, false},
				{"rp1", "24h0m0s", 1, true},
			},
		},
	}) {
		t.Fatalf("unexpected rows: %s", spew.Sdump(res.Series))
	}
}
예제 #17
0
// Ensure a SHOW USERS statement can be executed.
func TestStatementExecutor_ExecuteStatement_ShowUsers(t *testing.T) {
	e := NewStatementExecutor()
	e.Store.UsersFn = func() ([]meta.UserInfo, error) {
		return []meta.UserInfo{
			{Name: "susy", Admin: true},
			{Name: "bob", Admin: false},
		}, nil
	}

	if res := e.ExecuteStatement(influxql.MustParseStatement(`SHOW USERS`)); res.Err != nil {
		t.Fatal(res.Err)
	} else if !reflect.DeepEqual(res.Series, models.Rows{
		{
			Columns: []string{"user", "admin"},
			Values: [][]interface{}{
				{"susy", true},
				{"bob", false},
			},
		},
	}) {
		t.Fatalf("unexpected rows: %s", spew.Sdump(res.Series))
	}
}
예제 #18
0
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))
		}
	}
}
예제 #19
0
// Ensure a SHOW DATABASES statement can be executed.
func TestStatementExecutor_ExecuteStatement_ShowDatabases(t *testing.T) {
	e := NewStatementExecutor()
	e.Store.DatabasesFn = func() ([]meta.DatabaseInfo, error) {
		return []meta.DatabaseInfo{
			{Name: "foo"},
			{Name: "bar"},
		}, nil
	}

	if res := e.ExecuteStatement(influxql.MustParseStatement(`SHOW DATABASES`)); res.Err != nil {
		t.Fatal(res.Err)
	} else if !reflect.DeepEqual(res.Series, models.Rows{
		{
			Name:    "databases",
			Columns: []string{"name"},
			Values: [][]interface{}{
				{"foo"},
				{"bar"},
			},
		},
	}) {
		t.Fatalf("unexpected rows: %s", spew.Sdump(res.Series))
	}
}
예제 #20
0
func TestReduceTopBottom(t *testing.T) {
	tests := []struct {
		name   string
		skip   bool
		values []interface{}
		exp    PositionPoints
		call   *influxql.Call
	}{
		{
			name: "top int64 - single map",
			values: []interface{}{
				PositionPoints{
					{10, int64(99), nil, map[string]string{"host": "a"}},
					{20, int64(88), nil, map[string]string{"host": "a"}},
					{10, int64(53), nil, map[string]string{"host": "b"}},
				},
			},
			exp: PositionPoints{
				PositionPoint{10, int64(99), nil, map[string]string{"host": "a"}},
				PositionPoint{20, int64(88), nil, map[string]string{"host": "a"}},
			},
			call: &influxql.Call{Name: "top", Args: []influxql.Expr{&influxql.VarRef{Val: "field1"}, &influxql.NumberLiteral{Val: 2}}},
		},
		{
			name: "top int64 - double map",
			values: []interface{}{
				PositionPoints{
					{10, int64(99), nil, map[string]string{"host": "a"}},
				},
				PositionPoints{
					{20, int64(88), nil, map[string]string{"host": "a"}},
					{10, int64(53), nil, map[string]string{"host": "b"}},
				},
			},
			exp: PositionPoints{
				PositionPoint{10, int64(99), nil, map[string]string{"host": "a"}},
				PositionPoint{20, int64(88), nil, map[string]string{"host": "a"}},
			},
			call: &influxql.Call{Name: "top", Args: []influxql.Expr{&influxql.VarRef{Val: "field1"}, &influxql.NumberLiteral{Val: 2}}},
		},
		{
			name: "top int64 - double map with nil",
			values: []interface{}{
				PositionPoints{
					{10, int64(99), nil, map[string]string{"host": "a"}},
					{20, int64(88), nil, map[string]string{"host": "a"}},
					{10, int64(53), nil, map[string]string{"host": "b"}},
				},
				nil,
			},
			exp: PositionPoints{
				PositionPoint{10, int64(99), nil, map[string]string{"host": "a"}},
				PositionPoint{20, int64(88), nil, map[string]string{"host": "a"}},
			},
			call: &influxql.Call{Name: "top", Args: []influxql.Expr{&influxql.VarRef{Val: "field1"}, &influxql.NumberLiteral{Val: 2}}},
		},
		{
			name: "top int64 - double map with non-matching tags and tag selected",
			values: []interface{}{
				PositionPoints{
					{10, int64(99), nil, map[string]string{"host": "a"}},
					{20, int64(88), nil, map[string]string{}},
					{10, int64(53), nil, map[string]string{"host": "b"}},
				},
				nil,
			},
			exp: PositionPoints{
				PositionPoint{10, int64(99), nil, map[string]string{"host": "a"}},
				PositionPoint{20, int64(88), nil, map[string]string{}},
			},
			call: &influxql.Call{Name: "top", Args: []influxql.Expr{&influxql.VarRef{Val: "field1"}, &influxql.VarRef{Val: "host"}, &influxql.NumberLiteral{Val: 2}}},
		},
		{
			skip: true,
			name: "top int64 - double map with non-matching tags",
			values: []interface{}{
				PositionPoints{
					{10, int64(99), nil, map[string]string{"host": "a"}},
					{20, int64(88), nil, map[string]string{}},
					{10, int64(53), nil, map[string]string{"host": "b"}},
				},
				nil,
			},
			exp: PositionPoints{
				PositionPoint{10, int64(99), nil, map[string]string{"host": "a"}},
				PositionPoint{20, int64(55), nil, map[string]string{"host": "b"}},
			},
			call: &influxql.Call{Name: "bottom", Args: []influxql.Expr{&influxql.VarRef{Val: "field1"}, &influxql.NumberLiteral{Val: 2}}},
		},
		{
			name: "bottom int64 - single map",
			values: []interface{}{
				PositionPoints{
					{10, int64(53), nil, map[string]string{"host": "b"}},
					{20, int64(88), nil, map[string]string{"host": "a"}},
					{10, int64(99), nil, map[string]string{"host": "a"}},
				},
			},
			exp: PositionPoints{
				PositionPoint{10, int64(53), nil, map[string]string{"host": "b"}},
				PositionPoint{20, int64(88), nil, map[string]string{"host": "a"}},
			},
			call: &influxql.Call{Name: "bottom", Args: []influxql.Expr{&influxql.VarRef{Val: "field1"}, &influxql.NumberLiteral{Val: 2}}},
		},
		{
			name: "bottom int64 - double map",
			values: []interface{}{
				PositionPoints{
					{10, int64(99), nil, map[string]string{"host": "a"}},
				},
				PositionPoints{
					{10, int64(53), nil, map[string]string{"host": "b"}},
					{20, int64(88), nil, map[string]string{"host": "a"}},
				},
			},
			exp: PositionPoints{
				PositionPoint{10, int64(53), nil, map[string]string{"host": "b"}},
				PositionPoint{20, int64(88), nil, map[string]string{"host": "a"}},
			},
			call: &influxql.Call{Name: "bottom", Args: []influxql.Expr{&influxql.VarRef{Val: "field1"}, &influxql.NumberLiteral{Val: 2}}},
		},
		{
			name: "bottom int64 - double map with nil",
			values: []interface{}{
				PositionPoints{
					{10, int64(53), nil, map[string]string{"host": "b"}},
					{20, int64(88), nil, map[string]string{"host": "a"}},
					{10, int64(99), nil, map[string]string{"host": "a"}},
				},
				nil,
			},
			exp: PositionPoints{
				PositionPoint{10, int64(53), nil, map[string]string{"host": "b"}},
				PositionPoint{20, int64(88), nil, map[string]string{"host": "a"}},
			},
			call: &influxql.Call{Name: "bottom", Args: []influxql.Expr{&influxql.VarRef{Val: "field1"}, &influxql.NumberLiteral{Val: 2}}},
		},
		{
			name: "bottom int64 - double map with non-matching tags and tag selected",
			values: []interface{}{
				PositionPoints{
					{10, int64(53), nil, map[string]string{"host": "b"}},
					{20, int64(88), nil, map[string]string{}},
					{10, int64(99), nil, map[string]string{"host": "a"}},
				},
				nil,
			},
			exp: PositionPoints{
				PositionPoint{10, int64(53), nil, map[string]string{"host": "b"}},
				PositionPoint{20, int64(88), nil, map[string]string{}},
			},
			call: &influxql.Call{Name: "bottom", Args: []influxql.Expr{&influxql.VarRef{Val: "field1"}, &influxql.VarRef{Val: "host"}, &influxql.NumberLiteral{Val: 2}}},
		},
		{
			skip: true,
			name: "bottom int64 - double map with non-matching tags",
			values: []interface{}{
				PositionPoints{
					{10, int64(53), nil, map[string]string{"host": "b"}},
					{20, int64(88), nil, map[string]string{}},
					{10, int64(99), nil, map[string]string{"host": "a"}},
				},
				nil,
			},
			exp: PositionPoints{
				PositionPoint{10, int64(99), nil, map[string]string{"host": "a"}},
				PositionPoint{20, int64(55), nil, map[string]string{"host": "b"}},
			},
			call: &influxql.Call{Name: "bottom", Args: []influxql.Expr{&influxql.VarRef{Val: "field1"}, &influxql.NumberLiteral{Val: 2}}},
		},
	}

	for _, test := range tests {
		if test.skip {
			continue
		}
		values := ReduceTopBottom(test.values, test.call)
		t.Logf("Test: %s", test.name)
		if values != nil {
			v, _ := values.(PositionPoints)
			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))
		}
	}
}
예제 #21
0
func TestMapTopBottom(t *testing.T) {
	tests := []struct {
		name  string
		skip  bool
		input *MapInput
		exp   positionOut
		call  *influxql.Call
	}{
		{
			name: "top int64 - basic",
			input: &MapInput{
				TMin: -1,
				Items: []MapItem{
					{Timestamp: 10, Value: int64(53), Tags: map[string]string{"host": "a"}},
					{Timestamp: 20, Value: int64(88), Tags: map[string]string{"host": "a"}},
				},
			},
			exp: positionOut{
				points: PositionPoints{
					{20, int64(88), nil, map[string]string{"host": "a"}},
					{10, int64(53), nil, map[string]string{"host": "a"}},
				},
			},
			call: &influxql.Call{Name: "top", Args: []influxql.Expr{&influxql.VarRef{Val: "field1"}, &influxql.NumberLiteral{Val: 2}}},
		},
		{
			name: "top int64 - tie on value, resolve based on time",
			input: &MapInput{
				TMin: -1,
				Items: []MapItem{
					{Timestamp: 20, Value: int64(99), Tags: map[string]string{"host": "a"}},
					{Timestamp: 10, Value: int64(53), Tags: map[string]string{"host": "a"}},
					{Timestamp: 10, Value: int64(99), Tags: map[string]string{"host": "a"}},
				},
			},
			exp: positionOut{
				callArgs: []string{"host"},
				points: PositionPoints{
					{10, int64(99), nil, map[string]string{"host": "a"}},
					{20, int64(99), nil, map[string]string{"host": "a"}},
				},
			},
			call: &influxql.Call{Name: "top", Args: []influxql.Expr{&influxql.VarRef{Val: "field1"}, &influxql.NumberLiteral{Val: 2}}},
		},
		{
			name: "top mixed numerics - ints",
			input: &MapInput{
				TMin: -1,
				Items: []MapItem{
					{Timestamp: 10, Value: int64(99), Tags: map[string]string{"host": "a"}},
					{Timestamp: 10, Value: int64(53), Tags: map[string]string{"host": "a"}},
					{Timestamp: 20, Value: uint64(88), Tags: map[string]string{"host": "a"}},
				},
			},
			exp: positionOut{
				points: PositionPoints{
					{10, int64(99), nil, map[string]string{"host": "a"}},
					{20, uint64(88), nil, map[string]string{"host": "a"}},
				},
			},
			call: &influxql.Call{Name: "top", Args: []influxql.Expr{&influxql.VarRef{Val: "field1"}, &influxql.NumberLiteral{Val: 2}}},
		},
		{
			name: "top mixed numerics - ints & floats",
			input: &MapInput{
				TMin: -1,
				Items: []MapItem{
					{Timestamp: 10, Value: float64(99), Tags: map[string]string{"host": "a"}},
					{Timestamp: 10, Value: int64(53), Tags: map[string]string{"host": "a"}},
					{Timestamp: 20, Value: uint64(88), Tags: map[string]string{"host": "a"}},
				},
			},
			exp: positionOut{
				points: PositionPoints{
					{10, float64(99), nil, map[string]string{"host": "a"}},
					{20, uint64(88), nil, map[string]string{"host": "a"}},
				},
			},
			call: &influxql.Call{Name: "top", Args: []influxql.Expr{&influxql.VarRef{Val: "field1"}, &influxql.NumberLiteral{Val: 2}}},
		},
		{
			name: "top mixed numerics - ints, floats, & strings",
			input: &MapInput{
				TMin: -1,
				Items: []MapItem{
					{Timestamp: 10, Value: float64(99), Tags: map[string]string{"host": "a"}},
					{Timestamp: 10, Value: int64(53), Tags: map[string]string{"host": "a"}},
					{Timestamp: 20, Value: "88", Tags: map[string]string{"host": "a"}},
				},
			},
			exp: positionOut{
				points: PositionPoints{
					{10, float64(99), nil, map[string]string{"host": "a"}},
					{10, int64(53), nil, map[string]string{"host": "a"}},
				},
			},
			call: &influxql.Call{Name: "top", Args: []influxql.Expr{&influxql.VarRef{Val: "field1"}, &influxql.NumberLiteral{Val: 2}}},
		},
		{
			name: "top bools",
			input: &MapInput{
				TMin: -1,
				Items: []MapItem{
					{Timestamp: 10, Value: true, Tags: map[string]string{"host": "a"}},
					{Timestamp: 10, Value: true, Tags: map[string]string{"host": "a"}},
					{Timestamp: 20, Value: false, Tags: map[string]string{"host": "a"}},
				},
			},
			exp: positionOut{
				points: PositionPoints{
					{10, true, nil, map[string]string{"host": "a"}},
					{10, true, nil, map[string]string{"host": "a"}},
				},
			},
			call: &influxql.Call{Name: "top", Args: []influxql.Expr{&influxql.VarRef{Val: "field1"}, &influxql.NumberLiteral{Val: 2}}},
		},
		{
			name: "bottom int64 - basic",
			input: &MapInput{
				TMin: -1,
				Items: []MapItem{
					{Timestamp: 10, Value: int64(99), Tags: map[string]string{"host": "a"}},
					{Timestamp: 10, Value: int64(53), Tags: map[string]string{"host": "a"}},
					{Timestamp: 20, Value: int64(88), Tags: map[string]string{"host": "a"}},
				},
			},
			exp: positionOut{
				points: PositionPoints{
					{10, int64(53), nil, map[string]string{"host": "a"}},
					{20, int64(88), nil, map[string]string{"host": "a"}},
				},
			},
			call: &influxql.Call{Name: "bottom", Args: []influxql.Expr{&influxql.VarRef{Val: "field1"}, &influxql.NumberLiteral{Val: 2}}},
		},
		{
			name: "bottom int64 - tie on value, resolve based on time",
			input: &MapInput{
				TMin: -1,
				Items: []MapItem{
					{Timestamp: 10, Value: int64(53), Tags: map[string]string{"host": "a"}},
					{Timestamp: 20, Value: int64(53), Tags: map[string]string{"host": "a"}},
					{Timestamp: 20, Value: int64(53), Tags: map[string]string{"host": "a"}},
				},
			},
			exp: positionOut{
				callArgs: []string{"host"},
				points: PositionPoints{
					{10, int64(53), nil, map[string]string{"host": "a"}},
					{20, int64(53), nil, map[string]string{"host": "a"}},
				},
			},
			call: &influxql.Call{Name: "bottom", Args: []influxql.Expr{&influxql.VarRef{Val: "field1"}, &influxql.NumberLiteral{Val: 2}}},
		},
		{
			name: "bottom mixed numerics - ints",
			input: &MapInput{
				TMin: -1,
				Items: []MapItem{
					{Timestamp: 10, Value: int64(99), Tags: map[string]string{"host": "a"}},
					{Timestamp: 10, Value: int64(53), Tags: map[string]string{"host": "a"}},
					{Timestamp: 20, Value: uint64(88), Tags: map[string]string{"host": "a"}},
				},
			},
			exp: positionOut{
				points: PositionPoints{
					{10, int64(53), nil, map[string]string{"host": "a"}},
					{20, uint64(88), nil, map[string]string{"host": "a"}},
				},
			},
			call: &influxql.Call{Name: "bottom", Args: []influxql.Expr{&influxql.VarRef{Val: "field1"}, &influxql.NumberLiteral{Val: 2}}},
		},
		{
			name: "bottom mixed numerics - ints & floats",
			input: &MapInput{
				TMin: -1,
				Items: []MapItem{
					{Timestamp: 10, Value: int64(99), Tags: map[string]string{"host": "a"}},
					{Timestamp: 10, Value: float64(53), Tags: map[string]string{"host": "a"}},
					{Timestamp: 20, Value: uint64(88), Tags: map[string]string{"host": "a"}},
				},
			},
			exp: positionOut{
				points: PositionPoints{
					{10, float64(53), nil, map[string]string{"host": "a"}},
					{20, uint64(88), nil, map[string]string{"host": "a"}},
				},
			},
			call: &influxql.Call{Name: "bottom", Args: []influxql.Expr{&influxql.VarRef{Val: "field1"}, &influxql.NumberLiteral{Val: 2}}},
		},
		{
			name: "bottom mixed numerics - ints, floats, & strings",
			input: &MapInput{
				TMin: -1,
				Items: []MapItem{
					{Timestamp: 10, Value: float64(99), Tags: map[string]string{"host": "a"}},
					{Timestamp: 10, Value: int64(53), Tags: map[string]string{"host": "a"}},
					{Timestamp: 20, Value: "88", Tags: map[string]string{"host": "a"}},
				},
			},
			exp: positionOut{
				points: PositionPoints{
					{10, int64(53), nil, map[string]string{"host": "a"}},
					{10, float64(99), nil, map[string]string{"host": "a"}},
				},
			},
			call: &influxql.Call{Name: "bottom", Args: []influxql.Expr{&influxql.VarRef{Val: "field1"}, &influxql.NumberLiteral{Val: 2}}},
		},
		{
			name: "bottom bools",
			input: &MapInput{
				TMin: -1,
				Items: []MapItem{
					{Timestamp: 10, Value: true, Tags: map[string]string{"host": "a"}},
					{Timestamp: 10, Value: true, Tags: map[string]string{"host": "a"}},
					{Timestamp: 20, Value: false, Tags: map[string]string{"host": "a"}},
				},
			},
			exp: positionOut{
				points: PositionPoints{
					{20, false, nil, map[string]string{"host": "a"}},
					{10, true, nil, map[string]string{"host": "a"}},
				},
			},
			call: &influxql.Call{Name: "bottom", Args: []influxql.Expr{&influxql.VarRef{Val: "field1"}, &influxql.NumberLiteral{Val: 2}}},
		},
	}

	for _, test := range tests {
		if test.skip {
			continue
		}
		lit, _ := test.call.Args[len(test.call.Args)-1].(*influxql.NumberLiteral)
		limit := int(lit.Val)
		fields := topCallArgs(test.call)

		values := MapTopBottom(test.input, limit, fields, len(test.call.Args), test.call.Name).(PositionPoints)
		t.Logf("Test: %s", test.name)
		if exp, got := len(test.exp.points), len(values); exp != got {
			t.Errorf("Wrong number of values. exp %v got %v", exp, got)
		}
		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))
		}
	}
}