-
Notifications
You must be signed in to change notification settings - Fork 3
/
diversity_filter_test.go
206 lines (172 loc) · 7.13 KB
/
diversity_filter_test.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
package zikade
import (
"context"
"testing"
"github.com/libp2p/go-libp2p"
"github.com/libp2p/go-libp2p-kbucket/peerdiversity"
"github.com/libp2p/go-libp2p/core/peer"
ma "github.com/multiformats/go-multiaddr"
"github.com/probe-lab/go-libdht/kad/triert"
"github.com/probe-lab/zikade/kadt"
"github.com/stretchr/testify/require"
"github.com/stretchr/testify/suite"
)
type DiversityFilterTestSuite struct {
suite.Suite
Peers map[string]peer.AddrInfo
}
// SetupTest parses the input peers and stores them in the suite.Peers map. The
// peers are then used to test the diversity filter.
func (suite *DiversityFilterTestSuite) SetupTest() {
type peerInfo struct {
ID string
Addrs []string
}
var inputPeers []peerInfo = []peerInfo{ // first bits of Kad Key, bucket index wrt. 1EoooPEER1
{"1EoooPEER1", []string{"/ip4/0.0.0.0/tcp/4001"}}, // 0100 1101
{"1EoooPEER2", []string{"/ip4/1.1.1.1/tcp/4001"}}, // 1110 -> b0
{"1EoooPEER3", []string{"/ip4/1.1.64.64/tcp/4001"}}, // 0110 -> b2
{"1EoooPEER4", []string{"/ip4/1.1.128.128/tcp/4001"}}, // 0110 -> b2
{"1EoooPEER5", []string{"/ip4/1.1.192.192/tcp/4001"}}, // 0100 1110 -> b6
{"1EoooPEER6", []string{"/ip4/1.1.2.2/tcp/4001"}}, // 1010 -> b0
{"1EoooPEER7", []string{"/ip4/1.2.1.1/tcp/4001"}}, // 0000 -> b1
{"1EoooPEER8", []string{"/ip4/1.1.255.255/tcp/4001"}}, // 0111 -> b2
{"1EoooPEER9", []string{}}, // 1111 -> b0
{"1EooPEER11", []string{"/ip6/2000:1234::/tcp/4001", "/ip4/1.1.3.3/tcp/4001"}}, // 1100 -> b0
{"1EooPEER12", []string{"/ip6/2000:1234::1/tcp/4001"}}, // 0001 -> b1
{"1EooPEER13", []string{"/ip6/2000:1234:5678::/tcp/4001"}}, // 0110 -> b2
{"1EooPEER14", []string{"/ip6/2000:1234::2/tcp/4001", "/ip4/3.3.3.3/tcp/4001"}}, // 0000 -> b1
{"1EooPEER15", []string{"/ip6/2000:1234:5678::1/tcp/4001"}}, // 0000 -> b1
}
suite.Peers = make(map[string]peer.AddrInfo)
for _, p := range inputPeers {
pid, err := peer.Decode(p.ID)
if err != nil {
panic(err)
}
addrs := make([]ma.Multiaddr, 0, len(p.Addrs))
for _, a := range p.Addrs {
addr, err := ma.NewMultiaddr(a)
if err != nil {
panic(err)
}
addrs = append(addrs, addr)
}
suite.Peers[p.ID] = peer.AddrInfo{ID: pid, Addrs: addrs}
}
}
// In order for 'go test' to run this suite, we need to create
// a normal test function and pass our suite to suite.Run
func TestDiversityFilterTestSuite(t *testing.T) {
suite.Run(t, new(DiversityFilterTestSuite))
}
func (suite *DiversityFilterTestSuite) TestRtPeerIPGroupFilter() {
t := suite.T()
gf := newRtPeerIPGroupFilter(2, 3, func(p peer.ID) []ma.Multiaddr {
for _, pi := range suite.Peers {
if pi.ID == p {
return pi.Addrs
}
}
return nil
})
filter, err := peerdiversity.NewFilter(gf, "triert/diversity",
func(p peer.ID) int {
return kadt.PeerID(suite.Peers["1EoooPEER1"].ID).Key().CommonPrefixLength(
kadt.PeerID(p).Key())
})
require.NoError(t, err)
// generate routing table using 1EoooPEER1 as the local peer, and the
// diversity filter
rtcfg := &triert.Config[kadt.Key, kadt.PeerID]{
NodeFilter: &TrieRTPeerDiversityFilter{Filter: filter},
}
rt, err := triert.New[kadt.Key, kadt.PeerID](
kadt.PeerID(suite.Peers["1EoooPEER1"].ID), rtcfg)
require.NoError(t, err)
// add 3 peers with the same IP group (1.1.0.0/16)
success := rt.AddNode(kadt.PeerID(suite.Peers["1EoooPEER2"].ID))
require.True(t, success)
success = rt.AddNode(kadt.PeerID(suite.Peers["1EoooPEER3"].ID))
require.True(t, success)
success = rt.AddNode(kadt.PeerID(suite.Peers["1EoooPEER4"].ID))
require.True(t, success)
// add another peer with the same IP group (1.1.0.0/16) will fail
// (maxForTable = 3)
success = rt.AddNode(kadt.PeerID(suite.Peers["1EoooPEER5"].ID))
require.False(t, success)
// remove 1EoooPEER2 from the routing table
success = rt.RemoveKey(kadt.PeerID(suite.Peers["1EoooPEER2"].ID).Key())
require.True(t, success)
// adding 1EoooPEER8 will fail, because it falls in the same bucket (2) as
// 1EoooPEER3 and 1EoooPEER4 and it has the same IP group (maxPerCpl = 2)
success = rt.AddNode(kadt.PeerID(suite.Peers["1EoooPEER8"].ID))
require.False(t, success)
// adding 1EoooPEER6 will succeed, because it belongs to bucket 0, which has
// no other peers using the same IP group
success = rt.AddNode(kadt.PeerID(suite.Peers["1EoooPEER6"].ID))
require.True(t, success)
// adding 1EoooPEER7 will succeed, because it doesn't share the same IP
// group with any other peer in the routing table
success = rt.AddNode(kadt.PeerID(suite.Peers["1EoooPEER7"].ID))
require.True(t, success)
// removing the last peer from an IP group
success = rt.RemoveKey(kadt.PeerID(suite.Peers["1EoooPEER7"].ID).Key())
require.True(t, success)
// adding 1EoooPEER9 will fail, because it doesn't have a valid multiaddr
success = rt.AddNode(kadt.PeerID(suite.Peers["1EoooPEER9"].ID))
require.False(t, success)
// adding 1EooPEER11 will fail, because out of its 2 multiaddrs, one belongs
// to an IP group that already has 3 peers in the routing table
success = rt.AddNode(kadt.PeerID(suite.Peers["1EooPEER11"].ID))
require.False(t, success)
// adding 1EooPEER12 will succeed, because it is the first peer in its
// ip6 group
success = rt.AddNode(kadt.PeerID(suite.Peers["1EooPEER12"].ID))
require.True(t, success)
// adding 1EooPEER14 will succeed because both its multiaddrs belong to non
// full ip groups
success = rt.AddNode(kadt.PeerID(suite.Peers["1EooPEER14"].ID))
require.True(t, success)
// adding 1EooPEER15 will fail because its ip6 group is full for cpl = 1
success = rt.AddNode(kadt.PeerID(suite.Peers["1EooPEER15"].ID))
require.False(t, success)
// adding 1EooPEER13 will succeed, because even tough it shares the same
// ip6 group with 1EooPEER15, it has a different cpl
success = rt.AddNode(kadt.PeerID(suite.Peers["1EooPEER13"].ID))
require.True(t, success)
}
// TestRTPeerDiversityFilter tests the TrieRTPeerDiversityFilter implementation
func TestRTPeerDiversityFilter(t *testing.T) {
ctx := context.Background()
listenOpt := libp2p.ListenAddrStrings("/ip4/127.0.0.1/tcp/0")
h := newTestHost(t, listenOpt)
// create 2 remote peers
h1 := newTestHost(t, listenOpt)
h2 := newTestHost(t, listenOpt)
// clean up after ourselves
t.Cleanup(func() {
require.NoError(t, h.Close())
require.NoError(t, h1.Close())
require.NoError(t, h2.Close())
})
// create peer filter and routing table
peerFilter, err := NewRTPeerDiversityFilter(h, 1, 1)
require.NoError(t, err)
rtcfg := &triert.Config[kadt.Key, kadt.PeerID]{
NodeFilter: peerFilter,
}
rt, err := triert.New[kadt.Key, kadt.PeerID](kadt.PeerID(h.ID()), rtcfg)
require.NoError(t, err)
// connect h to h1 and h2
err = h.Connect(ctx, peer.AddrInfo{ID: h1.ID(), Addrs: h1.Addrs()})
require.NoError(t, err)
err = h.Connect(ctx, peer.AddrInfo{ID: h2.ID(), Addrs: h2.Addrs()})
require.NoError(t, err)
// try to add h1 to the routing table. succeeds because it is the first peer
success := rt.AddNode(kadt.PeerID(h1.ID()))
require.True(t, success)
// try to add h2 to the routing table. fails because it is the second peer
success = rt.AddNode(kadt.PeerID(h2.ID()))
require.False(t, success)
}