github.com/fufuok/balancer@v1.0.0/hash_test.go (about) 1 package balancer 2 3 import ( 4 "strings" 5 "sync" 6 "sync/atomic" 7 "testing" 8 ) 9 10 func TestConsistentHash(t *testing.T) { 11 lb := NewConsistentHash() 12 item := lb.Select() 13 if item != "" { 14 t.Fatalf("hash expected empty, actual %s", item) 15 } 16 17 lb.Add("A") 18 item = lb.Select() 19 if item != "A" { 20 t.Fatalf("hash expected A, actual %s", item) 21 } 22 23 nodes := []string{"A", "B", "C", "D"} 24 lb = NewConsistentHash(nodes) 25 item = lb.Select() 26 if item != "B" { 27 t.Fatalf("hash expected B, actual %s", item) 28 } 29 item = lb.Select() 30 if item != "B" { 31 t.Fatalf("hash expected B, actual %s", item) 32 } 33 item = lb.Select("192.168.1.100") 34 if item != "A" { 35 t.Fatalf("hash expected A, actual %s", item) 36 } 37 item = lb.Select("192.168.1.101") 38 if item != "C" { 39 t.Fatalf("hash expected C, actual %s", item) 40 } 41 item = lb.Select("192.168.1.102") 42 if item != "D" { 43 t.Fatalf("hash expected D, actual %s", item) 44 } 45 item = lb.Select("192.168.1.100") 46 if item != "A" { 47 t.Fatalf("hash expected A, actual %s", item) 48 } 49 item = lb.Select("2400:da00::6666") 50 if item != "C" { 51 t.Fatalf("hash expected C, actual %s", item) 52 } 53 54 for i := 0; i < 2000; i++ { 55 item := lb.Select("192.168.1.100") 56 if item != "A" { 57 t.Fatalf("hash expected A, actual %s", item) 58 } 59 } 60 61 lb.Add("E") 62 lb.Add("C") 63 lb.Add("E") 64 lb.Remove("B") 65 item = lb.Select("192.168.1.100") 66 if item != "A" { 67 t.Fatalf("hash expected A, actual %s", item) 68 } 69 70 all := lb.All().([]string) 71 if strings.Join(all, "") != "ACDECE" { 72 t.Fatalf("hash all() wrong") 73 } 74 75 lb.Remove("E") 76 all = lb.All().([]string) 77 if strings.Join(all, "") != "ACDCE" { 78 t.Fatalf("hash all() wrong") 79 } 80 81 lb.Remove("C", true) 82 all = lb.All().([]string) 83 if strings.Join(all, "") != "ADE" { 84 t.Fatalf("hash all() wrong") 85 } 86 87 lb.RemoveAll() 88 lb.Add("F", 1) 89 all, ok := lb.All().([]string) 90 if !ok || len(all) != 1 { 91 t.Fatal("hash all() wrong") 92 } 93 94 ok = lb.Update([]string{ 95 "X", 96 "Y", 97 }) 98 if ok != true { 99 t.Fatal("hash update wrong") 100 } 101 item = lb.Select() 102 if item != "Y" { 103 t.Fatal("hash update wrong") 104 } 105 item = lb.Select() 106 if item != "Y" { 107 t.Fatal("hash update wrong") 108 } 109 } 110 111 func TestConsistentHash_C(t *testing.T) { 112 var c int64 113 nodes := []string{"A", "B", "C", "D"} 114 lb := NewConsistentHash(nodes) 115 116 var wg sync.WaitGroup 117 for i := 0; i < 500; i++ { 118 wg.Add(1) 119 go func() { 120 defer wg.Done() 121 for j := 0; j < 2000; j++ { 122 switch lb.Select("192.168.1.7") { 123 case "C": 124 atomic.AddInt64(&c, 1) 125 default: 126 } 127 } 128 }() 129 } 130 wg.Wait() 131 132 if atomic.LoadInt64(&c) != 1000000 { 133 t.Fatalf("hash expected C == 1000000, actual C == %d, item: %s", atomic.LoadInt64(&c), lb.Select("192.168.1.7")) 134 } 135 }