123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178 |
- package internal
- import (
- "errors"
- "sort"
- "strconv"
- "testing"
- "zero/core/mathx"
- "github.com/golang/mock/gomock"
- "github.com/stretchr/testify/assert"
- )
- func TestConsistent_addConn(t *testing.T) {
- b := NewConsistentBalancer(func(server string) (interface{}, error) {
- return mockConn{
- server: server,
- }, nil
- }, func(server string, conn interface{}) error {
- return errors.New("error")
- }, func(kv KV) string {
- return kv.Key
- })
- assert.Nil(t, b.AddConn(KV{
- Key: "thekey1",
- Val: "thevalue",
- }))
- assert.EqualValues(t, map[string]interface{}{
- "thekey1": mockConn{server: "thevalue"},
- }, b.conns)
- assert.EqualValues(t, map[string][]string{
- "thevalue": {"thekey1"},
- }, b.servers)
- assert.EqualValues(t, map[string]string{
- "thekey1": "thevalue",
- }, b.mapping)
- assert.Nil(t, b.AddConn(KV{
- Key: "thekey2",
- Val: "thevalue",
- }))
- assert.EqualValues(t, map[string]interface{}{
- "thekey1": mockConn{server: "thevalue"},
- "thekey2": mockConn{server: "thevalue"},
- }, b.conns)
- assert.EqualValues(t, map[string][]string{
- "thevalue": {"thekey1", "thekey2"},
- }, b.servers)
- assert.EqualValues(t, map[string]string{
- "thekey1": "thevalue",
- "thekey2": "thevalue",
- }, b.mapping)
- assert.False(t, b.IsEmpty())
- b.RemoveKey("thekey1")
- assert.EqualValues(t, map[string]interface{}{
- "thekey2": mockConn{server: "thevalue"},
- }, b.conns)
- assert.EqualValues(t, map[string][]string{
- "thevalue": {"thekey2"},
- }, b.servers)
- assert.EqualValues(t, map[string]string{
- "thekey2": "thevalue",
- }, b.mapping)
- assert.False(t, b.IsEmpty())
- b.RemoveKey("thekey2")
- assert.Equal(t, 0, len(b.conns))
- assert.EqualValues(t, map[string][]string{}, b.servers)
- assert.EqualValues(t, map[string]string{}, b.mapping)
- assert.True(t, b.IsEmpty())
- }
- func TestConsistent_addConnError(t *testing.T) {
- b := NewConsistentBalancer(func(server string) (interface{}, error) {
- return nil, errors.New("error")
- }, func(server string, conn interface{}) error {
- return nil
- }, func(kv KV) string {
- return kv.Key
- })
- assert.NotNil(t, b.AddConn(KV{
- Key: "thekey1",
- Val: "thevalue",
- }))
- assert.Equal(t, 0, len(b.conns))
- assert.EqualValues(t, map[string][]string{}, b.servers)
- assert.EqualValues(t, map[string]string{}, b.mapping)
- }
- func TestConsistent_next(t *testing.T) {
- b := NewConsistentBalancer(func(server string) (interface{}, error) {
- return mockConn{
- server: server,
- }, nil
- }, func(server string, conn interface{}) error {
- return errors.New("error")
- }, func(kv KV) string {
- return kv.Key
- })
- b.initialize()
- _, ok := b.Next("any")
- assert.False(t, ok)
- const size = 100
- for i := 0; i < size; i++ {
- assert.Nil(t, b.AddConn(KV{
- Key: "thekey/" + strconv.Itoa(i),
- Val: "thevalue/" + strconv.Itoa(i),
- }))
- }
- m := make(map[interface{}]int)
- const total = 10000
- for i := 0; i < total; i++ {
- val, ok := b.Next(strconv.Itoa(i))
- assert.True(t, ok)
- m[val]++
- }
- entropy := mathx.CalcEntropy(m, total)
- assert.Equal(t, size, len(m))
- assert.True(t, entropy > .95)
- for i := 0; i < size; i++ {
- b.RemoveKey("thekey/" + strconv.Itoa(i))
- }
- _, ok = b.Next()
- assert.False(t, ok)
- }
- func TestConsistentBalancer_Listener(t *testing.T) {
- ctrl := gomock.NewController(t)
- defer ctrl.Finish()
- b := NewConsistentBalancer(func(server string) (interface{}, error) {
- return mockConn{
- server: server,
- }, nil
- }, func(server string, conn interface{}) error {
- return nil
- }, func(kv KV) string {
- return kv.Key
- })
- assert.Nil(t, b.AddConn(KV{
- Key: "key1",
- Val: "val1",
- }))
- assert.Nil(t, b.AddConn(KV{
- Key: "key2",
- Val: "val2",
- }))
- listener := NewMockListener(ctrl)
- listener.EXPECT().OnUpdate(gomock.Any(), gomock.Any(), "key2").Do(func(keys, vals, _ interface{}) {
- sort.Strings(keys.([]string))
- sort.Strings(vals.([]string))
- assert.EqualValues(t, []string{"key1", "key2"}, keys)
- assert.EqualValues(t, []string{"val1", "val2"}, vals)
- })
- b.setListener(listener)
- b.notify("key2")
- }
- func TestConsistentBalancer_remove(t *testing.T) {
- b := NewConsistentBalancer(func(server string) (interface{}, error) {
- return mockConn{
- server: server,
- }, nil
- }, func(server string, conn interface{}) error {
- return nil
- }, func(kv KV) string {
- return kv.Key
- })
- assert.Nil(t, b.handlePrevious(nil))
- assert.Nil(t, b.handlePrevious([]string{"any"}))
- }
|