go.charczuk.com@v0.0.0-20240327042549-bc490516bd1a/sdk/consistenthash/main_test.go (about) 1 /* 2 3 Copyright (c) 2023 - Present. Will Charczuk. All rights reserved. 4 Use of this source code is governed by a MIT license that can be found in the LICENSE file at the root of the repository. 5 6 */ 7 8 package consistenthash 9 10 import ( 11 "fmt" 12 "strings" 13 "testing" 14 15 . "go.charczuk.com/sdk/assert" 16 ) 17 18 func assignmentCounts(assignments map[string][]string) map[string]int { 19 output := make(map[string]int) 20 for bucket, items := range assignments { 21 output[bucket] = len(items) 22 } 23 return output 24 } 25 26 // setsAreDisjoint asserts that a given list of sets has no overlapping items with any of the other sets. 27 // 28 // this is helpful to prove that there are no duplicated items within sets. 29 func setsAreDisjoint(t *testing.T, itemSets ...[]string) { 30 t.Helper() 31 for thisSetIndex, thisSet := range itemSets { 32 for _, thisItem := range thisSet { 33 for otherSetIndex, otherSet := range itemSets { 34 if thisSetIndex != otherSetIndex { 35 for _, otherItem := range otherSet { 36 ItsEqual(t, true, thisItem != otherItem) 37 } 38 } 39 } 40 } 41 } 42 } 43 44 func itemsExistInSets(t *testing.T, items []string, sets ...[]string) { 45 t.Helper() 46 for _, item := range items { 47 ItsEqual(t, true, findItem(item, sets...), fmt.Sprintf("Item was not found in any supplied sets: %s", item)) 48 } 49 } 50 51 func setsAreEvenlySized(t *testing.T, itemCount int, sets ...[]string) { 52 t.Helper() 53 54 setCount := len(sets) 55 itemsPerSet := itemCount / setCount 56 minSize := 0 57 maxSize := itemsPerSet + 10 58 for _, set := range sets { 59 ItsEqual(t, true, len(set) >= minSize && len(set) <= maxSize, fmt.Sprintf("sets should be between %d and %d in size, actual: %d", minSize, maxSize, len(set))) 60 } 61 } 62 63 // itsConsistent asserts that a given before and after set differ by fewer movements a given maximum delta. 64 func itsConsistent(t *testing.T, old, new []string, maxDelta int) { 65 t.Helper() 66 var delta int 67 for _, oldItem := range old { 68 if !findItem(oldItem, new) { 69 delta++ 70 } 71 } 72 ItsEqual(t, true, delta <= maxDelta, fmt.Sprintf("The item arrays should differ only by %d items (differed by %d items)\n\told: %s\n\tnew: %s\n", maxDelta, delta, strings.Join(old, ", "), strings.Join(new, ", "))) 73 } 74 75 func findItem(item string, assignments ...[]string) bool { 76 for _, assignment := range assignments { 77 for _, assignmentItem := range assignment { 78 if item == assignmentItem { 79 return true 80 } 81 } 82 } 83 return false 84 } 85 86 func assignmentsAreEqual(t *testing.T, oldAssignments, newAssignments map[string][]string) { 87 t.Helper() 88 if len(oldAssignments) != len(newAssignments) { 89 t.Fatalf("assignments are not equal; length of maps differ: %d vs. %d", len(oldAssignments), len(newAssignments)) 90 } 91 for oldBucketName, oldBucket := range oldAssignments { 92 newBucket, ok := newAssignments[oldBucketName] 93 if !ok { 94 t.Fatalf("assignments are not equal; old bucket %s not found in new assignments", oldBucketName) 95 } 96 if len(oldBucket) != len(newBucket) { 97 t.Fatalf("assignments are not equal; length of assignment lists for %s differ: %d vs. %d", oldBucketName, len(oldBucket), len(newBucket)) 98 } 99 for _, oldBucketItem := range oldBucket { 100 if !findItem(oldBucketItem, newBucket) { 101 t.Fatalf("assignments are not equal; old bucket %s item %s not found in new bucket", oldBucketName, oldBucketItem) 102 } 103 } 104 } 105 }