From e06640668dabd61449a2d3d1b5607ed1c692d9d6 Mon Sep 17 00:00:00 2001 From: Evgeniy Kulikov Date: Fri, 12 Apr 2019 14:09:49 +0300 Subject: [PATCH] =?UTF-8?q?=F0=9F=90=BF=20Extend=20SortSliceByValue=20with?= =?UTF-8?q?=20more=20types?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- hrw.go | 57 ++++++++++++++++++++++++++++++++++++--- hrw_test.go | 78 ++++++++++++++++++++++++++++++++++++++++++++++------- 2 files changed, 122 insertions(+), 13 deletions(-) diff --git a/hrw.go b/hrw.go index 8c6cce4..7e6bce1 100644 --- a/hrw.go +++ b/hrw.go @@ -86,22 +86,73 @@ func SortSliceByValue(slice interface{}, hash uint64) { case int: var key = make([]byte, 16) slice := slice.([]int) - for i := 0; i < length; i++ { binary.BigEndian.PutUint64(key, uint64(slice[i])) rule = append(rule, weight(Hash(key), hash)) } + case uint: + var key = make([]byte, 16) + slice := slice.([]uint) + for i := 0; i < length; i++ { + binary.BigEndian.PutUint64(key, uint64(slice[i])) + rule = append(rule, weight(Hash(key), hash)) + } + case int8: + slice := slice.([]int8) + for i := 0; i < length; i++ { + key := byte(slice[i]) + rule = append(rule, weight(Hash([]byte{key}), hash)) + } + case uint8: + slice := slice.([]uint8) + for i := 0; i < length; i++ { + key := slice[i] + rule = append(rule, weight(Hash([]byte{key}), hash)) + } + case int16: + var key = make([]byte, 8) + slice := slice.([]int16) + for i := 0; i < length; i++ { + binary.BigEndian.PutUint16(key, uint16(slice[i])) + rule = append(rule, weight(Hash(key), hash)) + } + case uint16: + var key = make([]byte, 8) + slice := slice.([]uint16) + for i := 0; i < length; i++ { + binary.BigEndian.PutUint16(key, slice[i]) + rule = append(rule, weight(Hash(key), hash)) + } case int32: var key = make([]byte, 16) slice := slice.([]int32) - for i := 0; i < length; i++ { binary.BigEndian.PutUint32(key, uint32(slice[i])) rule = append(rule, weight(Hash(key), hash)) } + case uint32: + var key = make([]byte, 16) + slice := slice.([]uint32) + for i := 0; i < length; i++ { + binary.BigEndian.PutUint32(key, slice[i]) + rule = append(rule, weight(Hash(key), hash)) + } + case int64: + var key = make([]byte, 32) + slice := slice.([]int64) + for i := 0; i < length; i++ { + binary.BigEndian.PutUint64(key, uint64(slice[i])) + rule = append(rule, weight(Hash(key), hash)) + } + case uint64: + var key = make([]byte, 32) + slice := slice.([]uint64) + for i := 0; i < length; i++ { + binary.BigEndian.PutUint64(key, slice[i]) + rule = append(rule, weight(Hash(key), hash)) + } case string: slice := slice.([]string) - for i := 0; i < length; i++ { rule = append(rule, weight(hash, Hash([]byte(slice[i])))) diff --git a/hrw_test.go b/hrw_test.go index 32aabcc..2e2fbbe 100644 --- a/hrw_test.go +++ b/hrw_test.go @@ -9,7 +9,14 @@ import ( "testing" ) -type hashString string +type ( + hashString string + unknown byte + slices struct { + actual interface{} + expect interface{} + } +) var testKey = []byte("0xff51afd7ed558ccd") @@ -44,6 +51,7 @@ func Example() { // trying GET six.example.com/examples/object-key // trying GET five.example.com/examples/object-key } + func (h hashString) Hash() uint64 { return Hash([]byte(h)) } @@ -118,8 +126,8 @@ func TestSortSliceByValueFail(t *testing.T) { }) t.Run("must 'fail' for unknown type", func(t *testing.T) { - actual := []byte{1, 2, 3, 4, 5} - expect := []byte{1, 2, 3, 4, 5} + actual := []unknown{1, 2, 3, 4, 5} + expect := []unknown{1, 2, 3, 4, 5} hash := Hash(testKey) SortSliceByValue(actual, hash) if !reflect.DeepEqual(actual, expect) { @@ -139,12 +147,64 @@ func TestSortSliceByValueHasher(t *testing.T) { } func TestSortSliceByValueIntSlice(t *testing.T) { - actual := []int{0, 1, 2, 3, 4, 5} - expect := []int{2, 3, 1, 4, 0, 5} + cases := []slices{ + { + actual: []int{0, 1, 2, 3, 4, 5}, + expect: []int{2, 3, 1, 4, 0, 5}, + }, + + { + actual: []uint{0, 1, 2, 3, 4, 5}, + expect: []uint{2, 3, 1, 4, 0, 5}, + }, + + { + actual: []int8{0, 1, 2, 3, 4, 5}, + expect: []int8{2, 0, 5, 1, 4, 3}, + }, + + { + actual: []uint8{0, 1, 2, 3, 4, 5}, + expect: []uint8{2, 0, 5, 1, 4, 3}, + }, + + { + actual: []int16{0, 1, 2, 3, 4, 5}, + expect: []int16{5, 4, 0, 3, 2, 1}, + }, + + { + actual: []uint16{0, 1, 2, 3, 4, 5}, + expect: []uint16{5, 4, 0, 3, 2, 1}, + }, + + { + actual: []int32{0, 1, 2, 3, 4, 5}, + expect: []int32{1, 3, 5, 4, 2, 0}, + }, + + { + actual: []uint32{0, 1, 2, 3, 4, 5}, + expect: []uint32{1, 3, 5, 4, 2, 0}, + }, + + { + actual: []int64{0, 1, 2, 3, 4, 5}, + expect: []int64{1, 5, 3, 4, 2, 0}, + }, + + { + actual: []uint64{0, 1, 2, 3, 4, 5}, + expect: []uint64{1, 5, 3, 4, 2, 0}, + }, + } hash := Hash(testKey) - SortSliceByValue(actual, hash) - if !reflect.DeepEqual(actual, expect) { - t.Errorf("Was %#v, but expected %#v", actual, expect) + + for _, tc := range cases { + SortSliceByValue(tc.actual, hash) + if !reflect.DeepEqual(tc.actual, tc.expect) { + t.Errorf("Was %#v, but expected %#v", tc.actual, tc.expect) + } } } @@ -326,7 +386,6 @@ func TestUniformDistribution(t *testing.T) { "Chi2 condition for .9 is not met (expected %.2f <= %.2f)", chi2, chiTable[size-1]) } - }) t.Run("sortByInt32Value", func(t *testing.T) { @@ -367,7 +426,6 @@ func TestUniformDistribution(t *testing.T) { "Chi2 condition for .9 is not met (expected %.2f <= %.2f)", chi2, chiTable[size-1]) } - }) t.Run("hash collision", func(t *testing.T) {