Skip to content

Commit 6fd681d

Browse files
authored
test: restore tests from #2313 (#2328)
Reinstates tests removed as part of #2313
1 parent 5def667 commit 6fd681d

File tree

5 files changed

+421
-0
lines changed

5 files changed

+421
-0
lines changed

packages/integration-tests/package.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@
3636
"@chainsafe/libp2p-gossipsub": "^11.0.0",
3737
"@chainsafe/libp2p-noise": "^14.0.0",
3838
"@chainsafe/libp2p-yamux": "^6.0.1",
39+
"@libp2p/bootstrap": "^10.0.7",
3940
"@libp2p/circuit-relay-v2": "^1.0.0",
4041
"@libp2p/crypto": "^3.0.2",
4142
"@libp2p/daemon-client": "^8.0.1",
@@ -50,6 +51,7 @@
5051
"@libp2p/interop": "^10.0.0",
5152
"@libp2p/kad-dht": "^12.0.0",
5253
"@libp2p/logger": "^4.0.1",
54+
"@libp2p/mdns": "^10.0.7",
5355
"@libp2p/mplex": "^10.0.0",
5456
"@libp2p/peer-id": "^4.0.0",
5557
"@libp2p/peer-id-factory": "^4.0.1",
Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
/* eslint-env mocha */
2+
3+
import { bootstrap } from '@libp2p/bootstrap'
4+
import { TypedEventEmitter, peerDiscoverySymbol } from '@libp2p/interface'
5+
import { createEd25519PeerId } from '@libp2p/peer-id-factory'
6+
import { webSockets } from '@libp2p/websockets'
7+
import { multiaddr } from '@multiformats/multiaddr'
8+
import { expect } from 'aegir/chai'
9+
import { createLibp2p } from 'libp2p'
10+
import defer from 'p-defer'
11+
import sinon from 'sinon'
12+
import type { Libp2p, PeerDiscovery, PeerDiscoveryEvents, PeerId } from '@libp2p/interface'
13+
14+
const listenAddr = multiaddr('/ip4/127.0.0.1/tcp/0/ws')
15+
16+
class TestPeerDiscovery extends TypedEventEmitter<PeerDiscoveryEvents> implements PeerDiscovery {
17+
get [peerDiscoverySymbol] (): PeerDiscovery {
18+
return this
19+
}
20+
21+
readonly [Symbol.toStringTag] = '@libp2p/test-peer-discovery'
22+
}
23+
24+
describe('bootstrap', () => {
25+
let peerId: PeerId
26+
let remotePeerId1: PeerId
27+
let remotePeerId2: PeerId
28+
let libp2p: Libp2p
29+
30+
beforeEach(async () => {
31+
[peerId, remotePeerId1, remotePeerId2] = await Promise.all([
32+
createEd25519PeerId(),
33+
createEd25519PeerId(),
34+
createEd25519PeerId()
35+
])
36+
})
37+
38+
afterEach(async () => {
39+
if (libp2p != null) {
40+
await libp2p.stop()
41+
}
42+
})
43+
44+
it('should ignore self on discovery', async () => {
45+
const discovery = new TestPeerDiscovery()
46+
47+
libp2p = await createLibp2p({
48+
peerId,
49+
peerDiscovery: [
50+
() => discovery
51+
]
52+
})
53+
54+
await libp2p.start()
55+
const discoverySpy = sinon.spy()
56+
libp2p.addEventListener('peer:discovery', discoverySpy)
57+
discovery.safeDispatchEvent('peer', {
58+
detail: {
59+
id: libp2p.peerId,
60+
multiaddrs: [],
61+
protocols: []
62+
}
63+
})
64+
65+
expect(discoverySpy.called).to.eql(false)
66+
})
67+
68+
it('bootstrap should discover all peers in the list', async () => {
69+
const deferred = defer()
70+
71+
const bootstrappers = [
72+
`${listenAddr.toString()}/p2p/${remotePeerId1.toString()}`,
73+
`${listenAddr.toString()}/p2p/${remotePeerId2.toString()}`
74+
]
75+
76+
libp2p = await createLibp2p({
77+
transports: [
78+
webSockets()
79+
],
80+
peerDiscovery: [
81+
bootstrap({
82+
list: bootstrappers
83+
})
84+
]
85+
})
86+
87+
const expectedPeers = new Set([
88+
remotePeerId1.toString(),
89+
remotePeerId2.toString()
90+
])
91+
92+
libp2p.addEventListener('peer:discovery', (evt) => {
93+
const { id } = evt.detail
94+
95+
expectedPeers.delete(id.toString())
96+
if (expectedPeers.size === 0) {
97+
libp2p.removeEventListener('peer:discovery')
98+
deferred.resolve()
99+
}
100+
})
101+
102+
await libp2p.start()
103+
104+
return deferred.promise
105+
})
106+
})
Lines changed: 222 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,222 @@
1+
/* eslint-env mocha */
2+
3+
import { yamux } from '@chainsafe/libp2p-yamux'
4+
import { kadDHT, passthroughMapper } from '@libp2p/kad-dht'
5+
import { mplex } from '@libp2p/mplex'
6+
import { createEd25519PeerId } from '@libp2p/peer-id-factory'
7+
import { plaintext } from '@libp2p/plaintext'
8+
import { tcp } from '@libp2p/tcp'
9+
import { multiaddr } from '@multiformats/multiaddr'
10+
import { expect } from 'aegir/chai'
11+
import { createLibp2p } from 'libp2p'
12+
import pDefer from 'p-defer'
13+
import pWaitFor from 'p-wait-for'
14+
import { fromString as uint8ArrayFromString } from 'uint8arrays/from-string'
15+
import type { Libp2p, PeerId } from '@libp2p/interface'
16+
import type { KadDHT } from '@libp2p/kad-dht'
17+
import type { Multiaddr } from '@multiformats/multiaddr'
18+
import type { Libp2pOptions } from 'libp2p'
19+
20+
export const subsystemMulticodecs = [
21+
'/test/kad/1.0.0',
22+
'/other/1.0.0'
23+
]
24+
25+
const listenAddr = multiaddr('/ip4/127.0.0.1/tcp/8000')
26+
const remoteListenAddr = multiaddr('/ip4/127.0.0.1/tcp/8001')
27+
28+
async function getRemoteAddr (remotePeerId: PeerId, libp2p: Libp2p): Promise<Multiaddr> {
29+
const { addresses } = await libp2p.peerStore.get(remotePeerId)
30+
31+
if (addresses.length === 0) {
32+
throw new Error('No addrs found')
33+
}
34+
35+
const addr = addresses[0]
36+
37+
return addr.multiaddr.encapsulate(`/p2p/${remotePeerId.toString()}`)
38+
}
39+
40+
describe('DHT subsystem operates correctly', () => {
41+
let peerId: PeerId
42+
let remotePeerId: PeerId
43+
let libp2p: Libp2p<{ dht: KadDHT }>
44+
let remoteLibp2p: Libp2p<{ dht: KadDHT }>
45+
let remAddr: Multiaddr
46+
47+
beforeEach(async () => {
48+
[peerId, remotePeerId] = await Promise.all([
49+
createEd25519PeerId(),
50+
createEd25519PeerId()
51+
])
52+
})
53+
54+
describe('dht started before connect', () => {
55+
beforeEach(async () => {
56+
libp2p = await createLibp2p({
57+
peerId,
58+
addresses: {
59+
listen: [listenAddr.toString()]
60+
},
61+
transports: [
62+
tcp()
63+
],
64+
connectionEncryption: [
65+
plaintext()
66+
],
67+
streamMuxers: [
68+
yamux(),
69+
mplex()
70+
],
71+
services: {
72+
dht: kadDHT({
73+
protocol: subsystemMulticodecs[0],
74+
peerInfoMapper: passthroughMapper,
75+
allowQueryWithZeroPeers: true
76+
})
77+
}
78+
})
79+
80+
remoteLibp2p = await createLibp2p({
81+
peerId: remotePeerId,
82+
addresses: {
83+
listen: [remoteListenAddr.toString()]
84+
},
85+
transports: [
86+
tcp()
87+
],
88+
connectionEncryption: [
89+
plaintext()
90+
],
91+
streamMuxers: [
92+
yamux(),
93+
mplex()
94+
],
95+
services: {
96+
dht: kadDHT({
97+
protocol: subsystemMulticodecs[0],
98+
peerInfoMapper: passthroughMapper,
99+
allowQueryWithZeroPeers: true
100+
})
101+
}
102+
})
103+
104+
await Promise.all([
105+
libp2p.start(),
106+
remoteLibp2p.start()
107+
])
108+
109+
await libp2p.peerStore.patch(remotePeerId, {
110+
multiaddrs: [remoteListenAddr]
111+
})
112+
remAddr = await getRemoteAddr(remotePeerId, libp2p)
113+
})
114+
115+
afterEach(async () => {
116+
if (libp2p != null) {
117+
await libp2p.stop()
118+
}
119+
120+
if (remoteLibp2p != null) {
121+
await remoteLibp2p.stop()
122+
}
123+
})
124+
125+
it('should get notified of connected peers on dial', async () => {
126+
const stream = await libp2p.dialProtocol(remAddr, subsystemMulticodecs)
127+
128+
expect(stream).to.exist()
129+
130+
return Promise.all([
131+
// @ts-expect-error private field
132+
pWaitFor(() => libp2p.services.dht.routingTable.size === 1),
133+
// @ts-expect-error private field
134+
pWaitFor(() => remoteLibp2p.services.dht.routingTable.size === 1)
135+
])
136+
})
137+
138+
it('should put on a peer and get from the other', async () => {
139+
const key = uint8ArrayFromString('hello')
140+
const value = uint8ArrayFromString('world')
141+
142+
await libp2p.dialProtocol(remotePeerId, subsystemMulticodecs)
143+
await Promise.all([
144+
// @ts-expect-error private field
145+
pWaitFor(() => libp2p.services.dht.routingTable.size === 1),
146+
// @ts-expect-error private field
147+
pWaitFor(() => remoteLibp2p.services.dht.routingTable.size === 1)
148+
])
149+
150+
await libp2p.contentRouting.put(key, value)
151+
152+
const fetchedValue = await remoteLibp2p.contentRouting.get(key)
153+
expect(fetchedValue).to.equalBytes(value)
154+
})
155+
})
156+
157+
it('kad-dht should discover other peers', async () => {
158+
const remotePeerId1 = await createEd25519PeerId()
159+
const remotePeerId2 = await createEd25519PeerId()
160+
161+
const deferred = pDefer()
162+
163+
const getConfig = (peerId: PeerId): Libp2pOptions<{ dht: KadDHT }> => ({
164+
peerId,
165+
addresses: {
166+
listen: [
167+
listenAddr.toString()
168+
]
169+
},
170+
services: {
171+
dht: kadDHT({
172+
protocol: subsystemMulticodecs[0],
173+
peerInfoMapper: passthroughMapper,
174+
allowQueryWithZeroPeers: true
175+
})
176+
}
177+
})
178+
179+
const localConfig = getConfig(peerId)
180+
181+
libp2p = await createLibp2p(localConfig)
182+
183+
const remoteLibp2p1 = await createLibp2p(getConfig(remotePeerId1))
184+
const remoteLibp2p2 = await createLibp2p(getConfig(remotePeerId2))
185+
186+
libp2p.addEventListener('peer:discovery', (evt) => {
187+
const { id } = evt.detail
188+
189+
if (id.equals(remotePeerId1)) {
190+
libp2p.removeEventListener('peer:discovery')
191+
deferred.resolve()
192+
}
193+
})
194+
195+
await Promise.all([
196+
libp2p.start(),
197+
remoteLibp2p1.start(),
198+
remoteLibp2p2.start()
199+
])
200+
201+
await libp2p.peerStore.patch(remotePeerId1, {
202+
multiaddrs: remoteLibp2p1.getMultiaddrs()
203+
})
204+
await remoteLibp2p2.peerStore.patch(remotePeerId1, {
205+
multiaddrs: remoteLibp2p1.getMultiaddrs()
206+
})
207+
208+
// Topology:
209+
// A -> B
210+
// C -> B
211+
await Promise.all([
212+
libp2p.dial(remotePeerId1),
213+
remoteLibp2p2.dial(remotePeerId1)
214+
])
215+
216+
await deferred.promise
217+
return Promise.all([
218+
remoteLibp2p1.stop(),
219+
remoteLibp2p2.stop()
220+
])
221+
})
222+
})

0 commit comments

Comments
 (0)