blob: 1668946b5a367321b14a8a2e89780ff02e996f87 [file]
// Licensed to Apache Software Foundation (ASF) under one or more contributor
// license agreements. See the NOTICE file distributed with
// this work for additional information regarding copyright
// ownership. Apache Software Foundation (ASF) licenses this file to you under
// the Apache License, Version 2.0 (the "License"); you may
// not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
package node
import (
"testing"
"github.com/stretchr/testify/assert"
commonv1 "github.com/apache/skywalking-banyandb/api/proto/banyandb/common/v1"
databasev1 "github.com/apache/skywalking-banyandb/api/proto/banyandb/database/v1"
"github.com/apache/skywalking-banyandb/banyand/metadata/schema"
)
func TestPickEmptySelector(t *testing.T) {
selector := NewRoundRobinSelector("test", nil)
setupGroup(selector)
_, err := selector.Pick("group1", "", 0, 0)
assert.Error(t, err)
}
func TestPickUnknownGroup(t *testing.T) {
selector := NewRoundRobinSelector("test", nil)
_, err := selector.Pick("group1", "", 0, 0)
assert.Error(t, err)
setupGroup(selector)
_, err = selector.Pick("group1", "", 100, 0)
assert.Error(t, err)
}
func TestPickSingleSelection(t *testing.T) {
selector := NewRoundRobinSelector("test", nil)
setupGroup(selector)
selector.AddNode(&databasev1.Node{Metadata: &commonv1.Metadata{Name: "node1"}})
node, err := selector.Pick("group1", "", 0, 0)
assert.NoError(t, err)
assert.Equal(t, "node1", node)
}
func TestPickMultipleSelections(t *testing.T) {
selector := NewRoundRobinSelector("test", nil)
setupGroup(selector)
selector.AddNode(&databasev1.Node{Metadata: &commonv1.Metadata{Name: "node1"}})
selector.AddNode(&databasev1.Node{Metadata: &commonv1.Metadata{Name: "node2"}})
_, err := selector.Pick("group1", "", 1, 0)
assert.NoError(t, err)
node1, err := selector.Pick("group1", "", 0, 0)
assert.NoError(t, err)
node2, err := selector.Pick("group1", "", 1, 0)
assert.NoError(t, err)
assert.NotEqual(t, node1, node2, "Different shardIDs in the same group should not result in the same node")
}
func TestPickNodeRemoval(t *testing.T) {
selector := NewRoundRobinSelector("test", nil)
setupGroup(selector)
selector.AddNode(&databasev1.Node{Metadata: &commonv1.Metadata{Name: "node1"}})
selector.AddNode(&databasev1.Node{Metadata: &commonv1.Metadata{Name: "node2"}})
selector.RemoveNode(&databasev1.Node{Metadata: &commonv1.Metadata{Name: "node1"}})
node, err := selector.Pick("group1", "", 0, 0)
assert.NoError(t, err)
assert.Equal(t, "node2", node)
}
func TestPickConsistentSelectionAfterRemoval(t *testing.T) {
selector := NewRoundRobinSelector("test", nil)
setupGroup(selector)
selector.AddNode(&databasev1.Node{Metadata: &commonv1.Metadata{Name: "node1"}})
selector.AddNode(&databasev1.Node{Metadata: &commonv1.Metadata{Name: "node2"}})
selector.AddNode(&databasev1.Node{Metadata: &commonv1.Metadata{Name: "node3"}})
_, err := selector.Pick("group1", "", 0, 0)
assert.NoError(t, err)
_, err = selector.Pick("group1", "", 1, 0)
assert.NoError(t, err)
node, err := selector.Pick("group1", "", 1, 0)
assert.NoError(t, err)
assert.Equal(t, "node2", node)
selector.RemoveNode(&databasev1.Node{Metadata: &commonv1.Metadata{Name: "node2"}})
node, err = selector.Pick("group1", "", 1, 0)
assert.NoError(t, err)
assert.Equal(t, "node3", node)
}
func TestCleanupGroup(t *testing.T) {
selector := &roundRobinSelector{
nodes: make([]string, 0),
}
setupGroup(selector)
selector.AddNode(&databasev1.Node{Metadata: &commonv1.Metadata{Name: "node1"}})
selector.AddNode(&databasev1.Node{Metadata: &commonv1.Metadata{Name: "node2"}})
_, err := selector.Pick("group1", "", 0, 0)
assert.NoError(t, err)
selector.OnDelete(groupSchema)
_, err = selector.Pick("group1", "", 0, 0)
assert.Error(t, err)
}
func TestSortNodeEntries(t *testing.T) {
selector := &roundRobinSelector{
nodes: make([]string, 0),
}
setupGroup(selector)
selector.AddNode(&databasev1.Node{Metadata: &commonv1.Metadata{Name: "node3"}})
selector.AddNode(&databasev1.Node{Metadata: &commonv1.Metadata{Name: "node1"}})
selector.AddNode(&databasev1.Node{Metadata: &commonv1.Metadata{Name: "node2"}})
assert.EqualValues(t, []string{"node1", "node2", "node3"}, selector.nodes)
}
func TestStringer(t *testing.T) {
selector := NewRoundRobinSelector("test", nil)
assert.Empty(t, selector.String())
setupGroup(selector)
assert.NotEmpty(t, selector.String())
selector.AddNode(&databasev1.Node{Metadata: &commonv1.Metadata{Name: "node3"}})
selector.AddNode(&databasev1.Node{Metadata: &commonv1.Metadata{Name: "node1"}})
selector.AddNode(&databasev1.Node{Metadata: &commonv1.Metadata{Name: "node2"}})
assert.NotEmpty(t, selector.String())
}
func TestChangeShard(t *testing.T) {
s := NewRoundRobinSelector("test", nil)
selector := s.(*roundRobinSelector)
setupGroup(selector)
selector.AddNode(&databasev1.Node{Metadata: &commonv1.Metadata{Name: "node1"}})
selector.AddNode(&databasev1.Node{Metadata: &commonv1.Metadata{Name: "node2"}})
_, err := selector.Pick("group1", "", 0, 0)
assert.NoError(t, err)
_, err = selector.Pick("group1", "", 1, 0)
assert.NoError(t, err)
// Reduce shard number to 1
selector.OnAddOrUpdate(groupSchema1)
_, err = selector.Pick("group1", "", 0, 0)
assert.NoError(t, err)
_, err = selector.Pick("group1", "", 1, 0)
assert.Error(t, err)
// Restore shard number to 2
setupGroup(selector)
node1, err := selector.Pick("group1", "", 0, 0)
assert.NoError(t, err)
node2, err := selector.Pick("group1", "", 1, 0)
assert.NoError(t, err)
assert.NotEqual(t, node1, node2)
}
var (
groupSchema = schema.Metadata{
TypeMeta: schema.TypeMeta{
Kind: schema.KindGroup,
},
Spec: &commonv1.Group{
Metadata: &commonv1.Metadata{
Name: "group1",
},
Catalog: commonv1.Catalog_CATALOG_MEASURE,
ResourceOpts: &commonv1.ResourceOpts{
ShardNum: 2,
},
},
}
groupSchema1 = schema.Metadata{
TypeMeta: schema.TypeMeta{
Kind: schema.KindGroup,
},
Spec: &commonv1.Group{
Metadata: &commonv1.Metadata{
Name: "group1",
},
Catalog: commonv1.Catalog_CATALOG_MEASURE,
ResourceOpts: &commonv1.ResourceOpts{
ShardNum: 1,
},
},
}
)
func setupGroup(selector Selector) {
selector.(*roundRobinSelector).OnAddOrUpdate(groupSchema)
}