github.com/ava-labs/avalanchego@v1.11.11/network/p2p/gossip/bloom_test.go (about) 1 // Copyright (C) 2019-2024, Ava Labs, Inc. All rights reserved. 2 // See the file LICENSE for licensing terms. 3 4 package gossip 5 6 import ( 7 "slices" 8 "testing" 9 10 "github.com/prometheus/client_golang/prometheus" 11 "github.com/prometheus/client_golang/prometheus/testutil" 12 "github.com/stretchr/testify/require" 13 14 "github.com/ava-labs/avalanchego/ids" 15 ) 16 17 func TestBloomFilterRefresh(t *testing.T) { 18 tests := []struct { 19 name string 20 minTargetElements int 21 targetFalsePositiveProbability float64 22 resetFalsePositiveProbability float64 23 resetCount uint64 24 add []*testTx 25 expected []*testTx 26 }{ 27 { 28 name: "no refresh", 29 minTargetElements: 1, 30 targetFalsePositiveProbability: 0.01, 31 resetFalsePositiveProbability: 1, 32 resetCount: 0, // maxCount = 9223372036854775807 33 add: []*testTx{ 34 {id: ids.ID{0}}, 35 {id: ids.ID{1}}, 36 {id: ids.ID{2}}, 37 }, 38 expected: []*testTx{ 39 {id: ids.ID{0}}, 40 {id: ids.ID{1}}, 41 {id: ids.ID{2}}, 42 }, 43 }, 44 { 45 name: "refresh", 46 minTargetElements: 1, 47 targetFalsePositiveProbability: 0.01, 48 resetFalsePositiveProbability: 0.0000000000000001, // maxCount = 1 49 resetCount: 1, 50 add: []*testTx{ 51 {id: ids.ID{0}}, 52 {id: ids.ID{1}}, 53 {id: ids.ID{2}}, 54 }, 55 expected: []*testTx{ 56 {id: ids.ID{2}}, 57 }, 58 }, 59 { 60 name: "multiple refresh", 61 minTargetElements: 1, 62 targetFalsePositiveProbability: 0.01, 63 resetFalsePositiveProbability: 0.0000000000000001, // maxCount = 1 64 resetCount: 2, 65 add: []*testTx{ 66 {id: ids.ID{0}}, 67 {id: ids.ID{1}}, 68 {id: ids.ID{2}}, 69 {id: ids.ID{3}}, 70 {id: ids.ID{4}}, 71 }, 72 expected: []*testTx{ 73 {id: ids.ID{4}}, 74 }, 75 }, 76 } 77 78 for _, tt := range tests { 79 t.Run(tt.name, func(t *testing.T) { 80 require := require.New(t) 81 bloom, err := NewBloomFilter(prometheus.NewRegistry(), "", tt.minTargetElements, tt.targetFalsePositiveProbability, tt.resetFalsePositiveProbability) 82 require.NoError(err) 83 84 var resetCount uint64 85 for _, item := range tt.add { 86 bloomBytes, saltBytes := bloom.Marshal() 87 initialBloomBytes := slices.Clone(bloomBytes) 88 initialSaltBytes := slices.Clone(saltBytes) 89 90 reset, err := ResetBloomFilterIfNeeded(bloom, len(tt.add)) 91 require.NoError(err) 92 if reset { 93 resetCount++ 94 } 95 bloom.Add(item) 96 97 require.Equal(initialBloomBytes, bloomBytes) 98 require.Equal(initialSaltBytes, saltBytes) 99 } 100 101 require.Equal(tt.resetCount, resetCount) 102 require.Equal(float64(tt.resetCount+1), testutil.ToFloat64(bloom.metrics.ResetCount)) 103 for _, expected := range tt.expected { 104 require.True(bloom.Has(expected)) 105 } 106 }) 107 } 108 }