aboutsummaryrefslogtreecommitdiff
path: root/src/gnunet/service/dht/blocks/filters_test.go
diff options
context:
space:
mode:
Diffstat (limited to 'src/gnunet/service/dht/blocks/filters_test.go')
-rw-r--r--src/gnunet/service/dht/blocks/filters_test.go110
1 files changed, 110 insertions, 0 deletions
diff --git a/src/gnunet/service/dht/blocks/filters_test.go b/src/gnunet/service/dht/blocks/filters_test.go
new file mode 100644
index 0000000..ef1331c
--- /dev/null
+++ b/src/gnunet/service/dht/blocks/filters_test.go
@@ -0,0 +1,110 @@
1// This file is part of gnunet-go, a GNUnet-implementation in Golang.
2// Copyright (C) 2019-2022 Bernd Fix >Y<
3//
4// gnunet-go is free software: you can redistribute it and/or modify it
5// under the terms of the GNU Affero General Public License as published
6// by the Free Software Foundation, either version 3 of the License,
7// or (at your option) any later version.
8//
9// gnunet-go is distributed in the hope that it will be useful, but
10// WITHOUT ANY WARRANTY; without even the implied warranty of
11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12// Affero General Public License for more details.
13//
14// You should have received a copy of the GNU Affero General Public License
15// along with this program. If not, see <http://www.gnu.org/licenses/>.
16//
17// SPDX-License-Identifier: AGPL3.0-or-later
18
19package blocks
20
21import (
22 "bytes"
23 "crypto/rand"
24 "sort"
25 "testing"
26)
27
28type Entry []byte
29
30type EntryList []Entry
31
32func (list EntryList) Len() int { return len(list) }
33func (list EntryList) Swap(i, j int) { list[i], list[j] = list[j], list[i] }
34func (list EntryList) Less(i, j int) bool { return bytes.Compare(list[i], list[j]) < 0 }
35
36func (list EntryList) Contains(e Entry) bool {
37 size := len(list)
38 i := sort.Search(size, func(i int) bool { return bytes.Compare(list[i], e) >= 0 })
39 return i != size
40}
41
42func TestBloomfilter(t *testing.T) {
43 F := 500 // number of expected entries
44
45 // The K-value for the HELLO_BF Bloom filter is always 16. The size S of
46 // the Bloom filter in bytes depends on the number of elements F known to
47 // be filtered at the initiator. If F is zero, the size S is just 8 (bytes).
48 // Otherwise, S is set to the minimum of 2^15 and the lowest power of 2 that
49 // is strictly larger than K*F/4 (in bytes). The wire format of HELLO_BF is
50 // the resulting byte array. In particular, K is never transmitted.
51 S := 1
52 for S < 4*F && S < 32768 {
53 S <<= 1
54 }
55 t.Logf("BloomFilter size in bytes: %d\n", S)
56
57 // generate positives (entries in the set)
58 positives := make(EntryList, F)
59 for i := 0; i < F; i++ {
60 data := make(Entry, 32)
61 if _, err := rand.Read(data); err != nil {
62 t.Fatal(err)
63 }
64 positives[i] = data
65 }
66 sort.Sort(positives)
67
68 // generate negatives (entries outside the set)
69 negatives := make(EntryList, F)
70 for i := 0; i < F; {
71 data := make(Entry, 32)
72 if _, err := rand.Read(data); err != nil {
73 t.Fatal(err)
74 }
75 if !positives.Contains(data) {
76 negatives[i] = data
77 i++
78 }
79 }
80
81 // create BloomFilter
82 bf := NewBloomFilter(S)
83
84 // add positives to bloomfilter
85 for _, e := range positives {
86 bf.Add(e)
87 }
88
89 // check lookup of positives
90 count := 0
91 for _, e := range positives {
92 if !bf.Contains(e) {
93 count++
94 }
95 }
96 if count > 0 {
97 t.Logf("FAILED with %d false-negatives", count)
98 }
99
100 // check lookup of negatives
101 count = 0
102 for _, e := range negatives {
103 if bf.Contains(e) {
104 count++
105 }
106 }
107 if count > 0 {
108 t.Logf("FAILED with %d false-positives", count)
109 }
110}