Skip to content

Commit 3251666

Browse files
committed
test(client): add tests for multiaddr parsing and peer connection handling
1 parent 9fd1be5 commit 3251666

File tree

1 file changed

+334
-0
lines changed

1 file changed

+334
-0
lines changed

client_helpers_test.go

Lines changed: 334 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,334 @@
1+
package p2p
2+
3+
import (
4+
"context"
5+
"testing"
6+
"time"
7+
8+
"github.com/libp2p/go-libp2p"
9+
"github.com/libp2p/go-libp2p/core/host"
10+
"github.com/libp2p/go-libp2p/core/peer"
11+
"github.com/stretchr/testify/assert"
12+
"github.com/stretchr/testify/require"
13+
)
14+
15+
func TestParseMultiaddrs(t *testing.T) {
16+
tests := []struct {
17+
name string
18+
addrs []string
19+
expectedCount int
20+
description string
21+
}{
22+
{
23+
name: "valid multiaddrs",
24+
addrs: []string{"/ip4/127.0.0.1/tcp/4001", "/ip6/::1/tcp/4001"},
25+
expectedCount: 2,
26+
description: "valid multiaddrs should be parsed successfully",
27+
},
28+
{
29+
name: "single valid multiaddr",
30+
addrs: []string{"/ip4/192.168.1.1/tcp/4001"},
31+
expectedCount: 1,
32+
description: "single multiaddr should be parsed",
33+
},
34+
{
35+
name: "empty array",
36+
addrs: []string{},
37+
expectedCount: 0,
38+
description: "empty array should return empty result",
39+
},
40+
{
41+
name: "nil array",
42+
addrs: nil,
43+
expectedCount: 0,
44+
description: "nil array should return empty result",
45+
},
46+
{
47+
name: "invalid multiaddr",
48+
addrs: []string{"not-a-valid-multiaddr"},
49+
expectedCount: 0,
50+
description: "invalid multiaddrs should be skipped",
51+
},
52+
{
53+
name: "mixed valid and invalid",
54+
addrs: []string{"/ip4/127.0.0.1/tcp/4001", "invalid", "/ip6/::1/tcp/4001"},
55+
expectedCount: 2,
56+
description: "only valid multiaddrs should be included",
57+
},
58+
{
59+
name: "empty string",
60+
addrs: []string{""},
61+
expectedCount: 0,
62+
description: "empty string should be skipped",
63+
},
64+
{
65+
name: "complex multiaddr",
66+
addrs: []string{"/ip4/192.168.1.1/tcp/4001/p2p/QmYyQSo1c1Ym7orWxLYvCrM2EmxFTANf8wXmmE7DWjhx5N"},
67+
expectedCount: 1,
68+
description: "complex multiaddr with peer ID should be parsed",
69+
},
70+
}
71+
72+
for _, tt := range tests {
73+
t.Run(tt.name, func(t *testing.T) {
74+
result := parseMultiaddrs(tt.addrs)
75+
76+
assert.Len(t, result, tt.expectedCount, tt.description)
77+
})
78+
}
79+
}
80+
81+
func TestConnectToCachedPeers(t *testing.T) {
82+
tests := []struct {
83+
name string
84+
setupPeers func() []cachedPeer
85+
description string
86+
}{
87+
{
88+
name: "empty cached peers",
89+
setupPeers: func() []cachedPeer {
90+
return []cachedPeer{}
91+
},
92+
description: "should handle empty peer list without error",
93+
},
94+
{
95+
name: "nil cached peers",
96+
setupPeers: func() []cachedPeer {
97+
return nil
98+
},
99+
description: "should handle nil peer list without error",
100+
},
101+
{
102+
name: "invalid peer ID",
103+
setupPeers: func() []cachedPeer {
104+
return []cachedPeer{
105+
{
106+
ID: "invalid-peer-id",
107+
Name: "test",
108+
Addrs: []string{"/ip4/127.0.0.1/tcp/4001"},
109+
},
110+
}
111+
},
112+
description: "should skip peers with invalid IDs",
113+
},
114+
{
115+
name: "empty addresses",
116+
setupPeers: func() []cachedPeer {
117+
return []cachedPeer{
118+
{
119+
ID: "QmYyQSo1c1Ym7orWxLYvCrM2EmxFTANf8wXmmE7DWjhx5N",
120+
Name: "test",
121+
Addrs: []string{},
122+
},
123+
}
124+
},
125+
description: "should skip peers with no addresses",
126+
},
127+
{
128+
name: "invalid multiaddrs",
129+
setupPeers: func() []cachedPeer {
130+
return []cachedPeer{
131+
{
132+
ID: "QmYyQSo1c1Ym7orWxLYvCrM2EmxFTANf8wXmmE7DWjhx5N",
133+
Name: "test",
134+
Addrs: []string{"invalid-multiaddr"},
135+
},
136+
}
137+
},
138+
description: "should skip peers with invalid multiaddrs",
139+
},
140+
}
141+
142+
for _, tt := range tests {
143+
t.Run(tt.name, func(t *testing.T) {
144+
// Create a test host
145+
privKey, err := GeneratePrivateKey()
146+
require.NoError(t, err)
147+
148+
h, err := libp2p.New(libp2p.Identity(privKey))
149+
require.NoError(t, err)
150+
defer func() {
151+
closeErr := h.Close()
152+
require.NoError(t, closeErr)
153+
}()
154+
155+
ctx := context.Background()
156+
logger := &DefaultLogger{}
157+
peers := tt.setupPeers()
158+
159+
// Should not panic
160+
connectToCachedPeers(ctx, h, peers, logger)
161+
})
162+
}
163+
}
164+
165+
func TestConnectToDiscoveredPeer(t *testing.T) {
166+
tests := []struct {
167+
name string
168+
setupFunc func(*testing.T, host.Host) peer.AddrInfo
169+
description string
170+
}{
171+
{
172+
name: "peer with no addresses",
173+
setupFunc: func(t *testing.T, _ host.Host) peer.AddrInfo {
174+
peerID := generateTestPeerID(t)
175+
return peer.AddrInfo{
176+
ID: peerID,
177+
Addrs: nil,
178+
}
179+
},
180+
description: "should skip peers with no addresses",
181+
},
182+
{
183+
name: "self peer",
184+
setupFunc: func(_ *testing.T, h host.Host) peer.AddrInfo {
185+
return peer.AddrInfo{
186+
ID: h.ID(),
187+
Addrs: nil,
188+
}
189+
},
190+
description: "should skip self peer",
191+
},
192+
}
193+
194+
for _, tt := range tests {
195+
t.Run(tt.name, func(t *testing.T) {
196+
privKey, err := GeneratePrivateKey()
197+
require.NoError(t, err)
198+
199+
config := Config{
200+
Name: testPeerName,
201+
PrivateKey: privKey,
202+
}
203+
204+
cl, err := NewClient(config)
205+
require.NoError(t, err)
206+
defer func() {
207+
closeErr := cl.Close()
208+
require.NoError(t, closeErr)
209+
}()
210+
211+
c := cl.(*client)
212+
ctx := context.Background()
213+
214+
peerInfo := tt.setupFunc(t, c.host)
215+
216+
// Should not panic
217+
c.connectToDiscoveredPeer(ctx, peerInfo)
218+
})
219+
}
220+
}
221+
222+
func TestShouldLogConnectionErrorAllCases(t *testing.T) {
223+
privKey, err := GeneratePrivateKey()
224+
require.NoError(t, err)
225+
226+
config := Config{
227+
Name: testPeerName,
228+
PrivateKey: privKey,
229+
}
230+
231+
cl, err := NewClient(config)
232+
require.NoError(t, err)
233+
defer func() {
234+
closeErr := cl.Close()
235+
require.NoError(t, closeErr)
236+
}()
237+
238+
c := cl.(*client)
239+
240+
tests := []struct {
241+
name string
242+
error error
243+
shouldLog bool
244+
}{
245+
{
246+
name: "connection refused",
247+
error: &mockError{msg: "connection refused"},
248+
shouldLog: false,
249+
},
250+
{
251+
name: "rate limit exceeded",
252+
error: &mockError{msg: "rate limit exceeded"},
253+
shouldLog: false,
254+
},
255+
{
256+
name: "NO_RESERVATION",
257+
error: &mockError{msg: "NO_RESERVATION"},
258+
shouldLog: false,
259+
},
260+
{
261+
name: "concurrent active dial",
262+
error: &mockError{msg: "concurrent active dial"},
263+
shouldLog: false,
264+
},
265+
{
266+
name: "all dials failed",
267+
error: &mockError{msg: "all dials failed"},
268+
shouldLog: false,
269+
},
270+
{
271+
name: "unknown error",
272+
error: &mockError{msg: "some other error"},
273+
shouldLog: true,
274+
},
275+
}
276+
277+
for _, tt := range tests {
278+
t.Run(tt.name, func(t *testing.T) {
279+
result := c.shouldLogConnectionError(tt.error)
280+
assert.Equal(t, tt.shouldLog, result)
281+
})
282+
}
283+
}
284+
285+
func TestDiscoveryNotifeeHandlePeerFound(t *testing.T) {
286+
tests := []struct {
287+
name string
288+
setupFunc func(*testing.T, host.Host) peer.AddrInfo
289+
description string
290+
}{
291+
{
292+
name: "self peer should be ignored",
293+
setupFunc: func(_ *testing.T, h host.Host) peer.AddrInfo {
294+
return peer.AddrInfo{
295+
ID: h.ID(),
296+
Addrs: h.Addrs(),
297+
}
298+
},
299+
description: "should not connect to self",
300+
},
301+
}
302+
303+
for _, tt := range tests {
304+
t.Run(tt.name, func(t *testing.T) {
305+
// Create a test host
306+
privKey, err := GeneratePrivateKey()
307+
require.NoError(t, err)
308+
309+
h, err := libp2p.New(libp2p.Identity(privKey))
310+
require.NoError(t, err)
311+
defer func() {
312+
closeErr := h.Close()
313+
require.NoError(t, closeErr)
314+
}()
315+
316+
ctx := context.Background()
317+
logger := &DefaultLogger{}
318+
319+
notifee := &discoveryNotifee{
320+
h: h,
321+
ctx: ctx,
322+
logger: logger,
323+
}
324+
325+
peerInfo := tt.setupFunc(t, h)
326+
327+
// Should not panic
328+
notifee.HandlePeerFound(peerInfo)
329+
330+
// Give a moment for any async operations
331+
time.Sleep(50 * time.Millisecond)
332+
})
333+
}
334+
}

0 commit comments

Comments
 (0)