package nip45 import ( "encoding/hex" "math/rand/v2" "testing" "github.com/stretchr/testify/require" ) func TestHyperLogLogBasic(t *testing.T) { rand := rand.New(rand.NewPCG(1, 0)) for _, count := range []int{ 2, 4, 6, 7, 12, 15, 22, 36, 44, 47, 64, 77, 89, 95, 104, 116, 122, 144, 150, 199, 300, 350, 400, 500, 600, 777, 922, 1000, 1500, 2222, 9999, 13600, 80000, 133333, 200000, } { hll := New() for range count { b := make([]byte, 32) for i := range b { b[i] = uint8(rand.UintN(256)) } id := hex.EncodeToString(b) hll.Add(id) } c := hll.Count() res100 := int(c * 100) require.Greater(t, res100, count*85, "result too low (actual %d < %d)", c, count) require.Less(t, res100, count*115, "result too high (actual %d > %d)", c, count) } } func TestHyperLogLogMerge(t *testing.T) { rand := rand.New(rand.NewPCG(2, 0)) for _, count := range []int{ 2, 4, 6, 7, 12, 15, 22, 36, 44, 47, 64, 77, 89, 95, 104, 116, 122, 144, 150, 199, 300, 350, 400, 500, 600, 777, 922, 1000, 1500, 2222, 9999, 13600, 80000, 133333, 200000, } { hllA := New() hllB := New() for range count / 2 { b := make([]byte, 32) for i := range b { b[i] = uint8(rand.UintN(256)) } id := hex.EncodeToString(b) hllA.Add(id) } for range count / 2 { b := make([]byte, 32) for i := range b { b[i] = uint8(rand.UintN(256)) } id := hex.EncodeToString(b) hllB.Add(id) } hll := New() hll.Merge(hllA) hll.Merge(hllB) res100 := int(hll.Count() * 100) require.Greater(t, res100, count*85, "result too low (actual %d < %d)", hll.Count(), count) require.Less(t, res100, count*115, "result too high (actual %d > %d)", hll.Count(), count) } } func TestHyperLogLogMergeComplex(t *testing.T) { rand := rand.New(rand.NewPCG(4, 0)) for _, count := range []int{ 3, 6, 9, 12, 15, 22, 36, 46, 57, 64, 77, 89, 95, 104, 116, 122, 144, 150, 199, 300, 350, 400, 500, 600, 777, 922, 1000, 1500, 2222, 9999, 13600, 80000, 133333, 200000, } { hllA := New() hllB := New() hllC := New() for range count / 3 { b := make([]byte, 32) for i := range b { b[i] = uint8(rand.UintN(256)) } id := hex.EncodeToString(b) hllA.Add(id) hllC.Add(id) } for range count / 3 { b := make([]byte, 32) for i := range b { b[i] = uint8(rand.UintN(256)) } id := hex.EncodeToString(b) hllB.Add(id) hllC.Add(id) } for range count / 3 { b := make([]byte, 32) for i := range b { b[i] = uint8(rand.UintN(256)) } id := hex.EncodeToString(b) hllC.Add(id) hllA.Add(id) } hll := New() hll.Merge(hllA) hll.Merge(hllB) hll.Merge(hllC) res100 := int(hll.Count() * 100) require.Greater(t, res100, count*85, "result too low (actual %d < %d)", hll.Count(), count) require.Less(t, res100, count*115, "result too high (actual %d > %d)", hll.Count(), count) } }