consistentbalancer_test.go 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178
  1. package internal
  2. import (
  3. "errors"
  4. "sort"
  5. "strconv"
  6. "testing"
  7. "zero/core/mathx"
  8. "github.com/golang/mock/gomock"
  9. "github.com/stretchr/testify/assert"
  10. )
  11. func TestConsistent_addConn(t *testing.T) {
  12. b := NewConsistentBalancer(func(server string) (interface{}, error) {
  13. return mockConn{
  14. server: server,
  15. }, nil
  16. }, func(server string, conn interface{}) error {
  17. return errors.New("error")
  18. }, func(kv KV) string {
  19. return kv.Key
  20. })
  21. assert.Nil(t, b.AddConn(KV{
  22. Key: "thekey1",
  23. Val: "thevalue",
  24. }))
  25. assert.EqualValues(t, map[string]interface{}{
  26. "thekey1": mockConn{server: "thevalue"},
  27. }, b.conns)
  28. assert.EqualValues(t, map[string][]string{
  29. "thevalue": {"thekey1"},
  30. }, b.servers)
  31. assert.EqualValues(t, map[string]string{
  32. "thekey1": "thevalue",
  33. }, b.mapping)
  34. assert.Nil(t, b.AddConn(KV{
  35. Key: "thekey2",
  36. Val: "thevalue",
  37. }))
  38. assert.EqualValues(t, map[string]interface{}{
  39. "thekey1": mockConn{server: "thevalue"},
  40. "thekey2": mockConn{server: "thevalue"},
  41. }, b.conns)
  42. assert.EqualValues(t, map[string][]string{
  43. "thevalue": {"thekey1", "thekey2"},
  44. }, b.servers)
  45. assert.EqualValues(t, map[string]string{
  46. "thekey1": "thevalue",
  47. "thekey2": "thevalue",
  48. }, b.mapping)
  49. assert.False(t, b.IsEmpty())
  50. b.RemoveKey("thekey1")
  51. assert.EqualValues(t, map[string]interface{}{
  52. "thekey2": mockConn{server: "thevalue"},
  53. }, b.conns)
  54. assert.EqualValues(t, map[string][]string{
  55. "thevalue": {"thekey2"},
  56. }, b.servers)
  57. assert.EqualValues(t, map[string]string{
  58. "thekey2": "thevalue",
  59. }, b.mapping)
  60. assert.False(t, b.IsEmpty())
  61. b.RemoveKey("thekey2")
  62. assert.Equal(t, 0, len(b.conns))
  63. assert.EqualValues(t, map[string][]string{}, b.servers)
  64. assert.EqualValues(t, map[string]string{}, b.mapping)
  65. assert.True(t, b.IsEmpty())
  66. }
  67. func TestConsistent_addConnError(t *testing.T) {
  68. b := NewConsistentBalancer(func(server string) (interface{}, error) {
  69. return nil, errors.New("error")
  70. }, func(server string, conn interface{}) error {
  71. return nil
  72. }, func(kv KV) string {
  73. return kv.Key
  74. })
  75. assert.NotNil(t, b.AddConn(KV{
  76. Key: "thekey1",
  77. Val: "thevalue",
  78. }))
  79. assert.Equal(t, 0, len(b.conns))
  80. assert.EqualValues(t, map[string][]string{}, b.servers)
  81. assert.EqualValues(t, map[string]string{}, b.mapping)
  82. }
  83. func TestConsistent_next(t *testing.T) {
  84. b := NewConsistentBalancer(func(server string) (interface{}, error) {
  85. return mockConn{
  86. server: server,
  87. }, nil
  88. }, func(server string, conn interface{}) error {
  89. return errors.New("error")
  90. }, func(kv KV) string {
  91. return kv.Key
  92. })
  93. b.initialize()
  94. _, ok := b.Next("any")
  95. assert.False(t, ok)
  96. const size = 100
  97. for i := 0; i < size; i++ {
  98. assert.Nil(t, b.AddConn(KV{
  99. Key: "thekey/" + strconv.Itoa(i),
  100. Val: "thevalue/" + strconv.Itoa(i),
  101. }))
  102. }
  103. m := make(map[interface{}]int)
  104. const total = 10000
  105. for i := 0; i < total; i++ {
  106. val, ok := b.Next(strconv.Itoa(i))
  107. assert.True(t, ok)
  108. m[val]++
  109. }
  110. entropy := mathx.CalcEntropy(m, total)
  111. assert.Equal(t, size, len(m))
  112. assert.True(t, entropy > .95)
  113. for i := 0; i < size; i++ {
  114. b.RemoveKey("thekey/" + strconv.Itoa(i))
  115. }
  116. _, ok = b.Next()
  117. assert.False(t, ok)
  118. }
  119. func TestConsistentBalancer_Listener(t *testing.T) {
  120. ctrl := gomock.NewController(t)
  121. defer ctrl.Finish()
  122. b := NewConsistentBalancer(func(server string) (interface{}, error) {
  123. return mockConn{
  124. server: server,
  125. }, nil
  126. }, func(server string, conn interface{}) error {
  127. return nil
  128. }, func(kv KV) string {
  129. return kv.Key
  130. })
  131. assert.Nil(t, b.AddConn(KV{
  132. Key: "key1",
  133. Val: "val1",
  134. }))
  135. assert.Nil(t, b.AddConn(KV{
  136. Key: "key2",
  137. Val: "val2",
  138. }))
  139. listener := NewMockListener(ctrl)
  140. listener.EXPECT().OnUpdate(gomock.Any(), gomock.Any(), "key2").Do(func(keys, vals, _ interface{}) {
  141. sort.Strings(keys.([]string))
  142. sort.Strings(vals.([]string))
  143. assert.EqualValues(t, []string{"key1", "key2"}, keys)
  144. assert.EqualValues(t, []string{"val1", "val2"}, vals)
  145. })
  146. b.setListener(listener)
  147. b.notify("key2")
  148. }
  149. func TestConsistentBalancer_remove(t *testing.T) {
  150. b := NewConsistentBalancer(func(server string) (interface{}, error) {
  151. return mockConn{
  152. server: server,
  153. }, nil
  154. }, func(server string, conn interface{}) error {
  155. return nil
  156. }, func(kv KV) string {
  157. return kv.Key
  158. })
  159. assert.Nil(t, b.handlePrevious(nil))
  160. assert.Nil(t, b.handlePrevious([]string{"any"}))
  161. }