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  }