多租户更改
This commit is contained in:
@@ -0,0 +1,183 @@
|
||||
package ringhash_test
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"hash/crc32"
|
||||
"hash/fnv"
|
||||
"testing"
|
||||
|
||||
"github.com/tinode/chat/server/ringhash"
|
||||
)
|
||||
|
||||
func TestHashing(t *testing.T) {
|
||||
|
||||
// Ring with 3 elements hashed by crc32.ChecksumIEEE
|
||||
ring := ringhash.New(3, crc32.ChecksumIEEE)
|
||||
ring.Add("A", "B", "C")
|
||||
|
||||
// The ring contains:
|
||||
// B0 = 105710768 -> B
|
||||
// B1 = 525743601 -> B
|
||||
// B2 = 880502322 -> B
|
||||
// C2 = 1132222116 -> C
|
||||
// C1 = 1750140263 -> C
|
||||
// C0 = 1900688422 -> C
|
||||
// A1 = 2254398539 -> A
|
||||
// A0 = 2672055562 -> A
|
||||
// A2 = 2909943688 -> A
|
||||
|
||||
// Key=A, Hash=3554254475 -> B0
|
||||
// Key=B, Hash=1255198513 -> C1
|
||||
// Key=C, Hash=1037565863 -> C2
|
||||
// Key=D, Hash=2746444292 -> A2
|
||||
// Key=E, Hash=3568589458 -> B0
|
||||
// Key=F, Hash=1304234792 -> C1
|
||||
|
||||
testHashes := map[string]string{
|
||||
"A": "B",
|
||||
"B": "C",
|
||||
"C": "C",
|
||||
"D": "A",
|
||||
"E": "B",
|
||||
"F": "C",
|
||||
}
|
||||
|
||||
for k, v := range testHashes {
|
||||
n := ring.Get(k)
|
||||
if n != v {
|
||||
t.Errorf("Key '%s', expecting '%s', got '%s'", k, v, n)
|
||||
}
|
||||
}
|
||||
|
||||
ring.Add("X")
|
||||
// Adding
|
||||
// X0 = 4214226378
|
||||
// X1 = 3795111051
|
||||
// X2 = 3373899592
|
||||
|
||||
// Changes to mapping:
|
||||
testHashes["A"] = "X"
|
||||
testHashes["E"] = "X"
|
||||
|
||||
for k, v := range testHashes {
|
||||
n := ring.Get(k)
|
||||
if n != v {
|
||||
t.Errorf("Key '%s, expecting %s, got %s", k, v, n)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestConsistency(t *testing.T) {
|
||||
ring1 := ringhash.New(3, nil)
|
||||
ring2 := ringhash.New(3, nil)
|
||||
|
||||
ring1.Add("owl", "crow", "sparrow")
|
||||
ring2.Add("sparrow", "owl", "crow")
|
||||
|
||||
if ring1.Get("duck") != ring2.Get("duck") {
|
||||
t.Error("'duck' should map to 'sparrow' in both cases")
|
||||
}
|
||||
|
||||
// Collision test: these strings generate CRC32 collisions
|
||||
// Google's implementation fails this test.
|
||||
// 0VXGD 0BGABAA
|
||||
// 0VXGG 0BGABAB
|
||||
// 0VXGF 0BGABAC
|
||||
// 0VXGA 0BGABAD
|
||||
// 0VXGC 0BGABAF
|
||||
// 0VXGB 0BGABAG
|
||||
// 0VXGM 0BGABAH
|
||||
// 0VXGL 0BGABAI
|
||||
// 0VXGO 0BGABAJ
|
||||
// 0VXGN 0BGABAK
|
||||
// 0VXGI 0BGABAL
|
||||
|
||||
ring1 = ringhash.New(1, crc32.ChecksumIEEE)
|
||||
ring2 = ringhash.New(1, crc32.ChecksumIEEE)
|
||||
|
||||
ring1.Add("VXGD", "BGABAA", "VXGG", "BGABAB", "VXGF", "BGABAC")
|
||||
ring2.Add("BGABAA", "VXGD", "BGABAB", "VXGG", "BGABAC", "VXGF")
|
||||
|
||||
str := []string{
|
||||
"datsam", "kGmVht", "dSPmEr", "RloWQr", "WFkAkG", "gLBNPX", "twEwll", "RnRdaf",
|
||||
"ruEMuJ", "ZvXJsJ", "xjQzKD", "CKfSFg", "BMKMvM", "PSzYdC", "CsxqTR", "IbzdXz",
|
||||
"xdnZGj", "VdHcVp", "iVgIvH", "bZsTIX", "CyRBUO", "ylgEGS", "vOTwJD", "JZbyFU",
|
||||
"Hayrly", "jQQkOV", "NEVjlJ", "SkJfie", "HrdJuL", "ASwkXH", "UwJOmo", "nfbrxA",
|
||||
}
|
||||
for _, key := range str {
|
||||
if ring1.Get(key) != ring2.Get(key) {
|
||||
t.Errorf("'%s' should map to the same bin in both cases", key)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestSignature(t *testing.T) {
|
||||
ring1 := ringhash.New(4, nil)
|
||||
ring2 := ringhash.New(4, nil)
|
||||
|
||||
ring1.Add("owl", "crow", "sparrow")
|
||||
ring2.Add("sparrow", "owl", "crow")
|
||||
|
||||
if ring1.Signature() != ring2.Signature() {
|
||||
t.Error("Signatures must be identical")
|
||||
}
|
||||
|
||||
ring1 = ringhash.New(4, nil)
|
||||
ring2 = ringhash.New(5, nil)
|
||||
|
||||
ring1.Add("owl", "crow", "sparrow")
|
||||
ring2.Add("owl", "crow", "sparrow")
|
||||
|
||||
if ring1.Signature() == ring2.Signature() {
|
||||
t.Error("Signatures must be different - different count of replicas")
|
||||
}
|
||||
|
||||
ring1 = ringhash.New(4, nil)
|
||||
ring2 = ringhash.New(4, nil)
|
||||
|
||||
ring1.Add("owl", "crow", "sparrow")
|
||||
ring2.Add("owl", "crow", "sparrow", "crane")
|
||||
|
||||
if ring1.Signature() == ring2.Signature() {
|
||||
t.Error("Signatures must be different - different keys")
|
||||
}
|
||||
|
||||
fnvHashfunc := func(data []byte) uint32 {
|
||||
hash := fnv.New32a()
|
||||
hash.Write(data)
|
||||
return hash.Sum32()
|
||||
}
|
||||
|
||||
ring1 = ringhash.New(4, nil)
|
||||
ring2 = ringhash.New(4, fnvHashfunc)
|
||||
|
||||
ring1.Add("owl", "crow", "sparrow")
|
||||
ring2.Add("owl", "crow", "sparrow")
|
||||
|
||||
if ring1.Signature() == ring2.Signature() {
|
||||
t.Error("Signatures must be different - different hash functions")
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkGet8(b *testing.B) { benchmarkGet(b, 8) }
|
||||
func BenchmarkGet32(b *testing.B) { benchmarkGet(b, 32) }
|
||||
func BenchmarkGet128(b *testing.B) { benchmarkGet(b, 128) }
|
||||
func BenchmarkGet512(b *testing.B) { benchmarkGet(b, 512) }
|
||||
|
||||
func benchmarkGet(b *testing.B, keycount int) {
|
||||
|
||||
ring := ringhash.New(53, nil)
|
||||
|
||||
var ids []string
|
||||
for i := range keycount {
|
||||
ids = append(ids, fmt.Sprintf("id=%d", i))
|
||||
}
|
||||
|
||||
ring.Add(ids...)
|
||||
|
||||
b.ResetTimer()
|
||||
|
||||
for i := range b.N {
|
||||
ring.Get(ids[i&(keycount-1)])
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user