Skip to content

Commit 93890c8

Browse files
authored
test: re-enable interop tests (#2297)
Now that gossipsub has been updated, revert changes from #2285
1 parent 1d16bca commit 93890c8

File tree

2 files changed

+240
-0
lines changed

2 files changed

+240
-0
lines changed

packages/integration-tests/package.json

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,18 +29,27 @@
2929
"test:firefox": "aegir test -t browser -- --browser firefox",
3030
"test:firefox-webworker": "aegir test -t webworker -- --browser firefox",
3131
"test:node": "aegir test -t node --cov",
32+
"test:interop": "aegir test -t node -f dist/test/interop.js",
3233
"dep-check": "aegir dep-check"
3334
},
3435
"devDependencies": {
36+
"@chainsafe/libp2p-gossipsub": "^11.0.0",
3537
"@chainsafe/libp2p-noise": "^14.0.0",
3638
"@chainsafe/libp2p-yamux": "^6.0.1",
3739
"@libp2p/circuit-relay-v2": "^1.0.0",
40+
"@libp2p/crypto": "^2.0.8",
41+
"@libp2p/daemon-client": "^8.0.1",
42+
"@libp2p/daemon-server": "^7.0.1",
3843
"@libp2p/dcutr": "^1.0.0",
3944
"@libp2p/fetch": "^1.0.0",
45+
"@libp2p/floodsub": "^9.0.0",
4046
"@libp2p/identify": "^1.0.0",
4147
"@libp2p/interface": "^1.0.0",
4248
"@libp2p/interface-compliance-tests": "^5.0.0",
4349
"@libp2p/interface-internal": "^1.0.0",
50+
"@libp2p/interop": "^10.0.0",
51+
"@libp2p/kad-dht": "^11.0.5",
52+
"@libp2p/logger": "^4.0.1",
4453
"@libp2p/mplex": "^10.0.0",
4554
"@libp2p/peer-id": "^4.0.0",
4655
"@libp2p/peer-id-factory": "^3.0.8",
@@ -53,6 +62,8 @@
5362
"@multiformats/multiaddr": "^12.1.10",
5463
"aegir": "^41.0.2",
5564
"delay": "^6.0.0",
65+
"execa": "^8.0.1",
66+
"go-libp2p": "^1.1.1",
5667
"it-all": "^3.0.3",
5768
"it-pipe": "^3.0.1",
5869
"libp2p": "^1.0.0",
Lines changed: 229 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,229 @@
1+
import fs from 'fs'
2+
import { gossipsub } from '@chainsafe/libp2p-gossipsub'
3+
import { noise } from '@chainsafe/libp2p-noise'
4+
import { yamux } from '@chainsafe/libp2p-yamux'
5+
import { circuitRelayServer, circuitRelayTransport } from '@libp2p/circuit-relay-v2'
6+
import { unmarshalPrivateKey } from '@libp2p/crypto/keys'
7+
import { createClient } from '@libp2p/daemon-client'
8+
import { createServer } from '@libp2p/daemon-server'
9+
import { floodsub } from '@libp2p/floodsub'
10+
import { identify } from '@libp2p/identify'
11+
import { contentRoutingSymbol, peerDiscoverySymbol, peerRoutingSymbol } from '@libp2p/interface'
12+
import { interopTests } from '@libp2p/interop'
13+
import { kadDHT } from '@libp2p/kad-dht'
14+
import { logger } from '@libp2p/logger'
15+
import { mplex } from '@libp2p/mplex'
16+
import { peerIdFromKeys } from '@libp2p/peer-id'
17+
import { tcp } from '@libp2p/tcp'
18+
import { multiaddr } from '@multiformats/multiaddr'
19+
import { execa } from 'execa'
20+
import { path as p2pd } from 'go-libp2p'
21+
import { createLibp2p, type Libp2pOptions, type ServiceFactoryMap } from 'libp2p'
22+
import pDefer from 'p-defer'
23+
import type { ServiceMap, PeerId } from '@libp2p/interface'
24+
import type { SpawnOptions, Daemon, DaemonFactory } from '@libp2p/interop'
25+
26+
/**
27+
* @packageDocumentation
28+
*
29+
* To enable debug logging, run the tests with the following env vars:
30+
*
31+
* ```console
32+
* DEBUG=libp2p*,go-libp2p:* npm run test:interop
33+
* ```
34+
*/
35+
36+
async function createGoPeer (options: SpawnOptions): Promise<Daemon> {
37+
const controlPort = Math.floor(Math.random() * (50000 - 10000 + 1)) + 10000
38+
const apiAddr = multiaddr(`/ip4/127.0.0.1/tcp/${controlPort}`)
39+
40+
const log = logger(`go-libp2p:${controlPort}`)
41+
42+
const opts = [
43+
`-listen=${apiAddr.toString()}`
44+
]
45+
46+
if (options.noListen === true) {
47+
opts.push('-noListenAddrs')
48+
} else {
49+
opts.push('-hostAddrs=/ip4/127.0.0.1/tcp/0')
50+
}
51+
52+
if (options.noise === true) {
53+
opts.push('-noise=true')
54+
}
55+
56+
if (options.dht === true) {
57+
opts.push('-dhtServer')
58+
}
59+
60+
if (options.relay === true) {
61+
opts.push('-relay')
62+
}
63+
64+
if (options.pubsub === true) {
65+
opts.push('-pubsub')
66+
}
67+
68+
if (options.pubsubRouter != null) {
69+
opts.push(`-pubsubRouter=${options.pubsubRouter}`)
70+
}
71+
72+
if (options.key != null) {
73+
opts.push(`-id=${options.key}`)
74+
}
75+
76+
if (options.muxer === 'mplex') {
77+
opts.push('-muxer=mplex')
78+
} else {
79+
opts.push('-muxer=yamux')
80+
}
81+
82+
const deferred = pDefer()
83+
const proc = execa(p2pd(), opts, {
84+
env: {
85+
GOLOG_LOG_LEVEL: 'debug'
86+
}
87+
})
88+
89+
proc.stdout?.on('data', (buf: Buffer) => {
90+
const str = buf.toString()
91+
log(str)
92+
93+
// daemon has started
94+
if (str.includes('Control socket:')) {
95+
deferred.resolve()
96+
}
97+
})
98+
99+
proc.stderr?.on('data', (buf) => {
100+
log.error(buf.toString())
101+
})
102+
103+
await deferred.promise
104+
105+
return {
106+
client: createClient(apiAddr),
107+
stop: async () => {
108+
proc.kill()
109+
}
110+
}
111+
}
112+
113+
async function createJsPeer (options: SpawnOptions): Promise<Daemon> {
114+
let peerId: PeerId | undefined
115+
116+
if (options.key != null) {
117+
const keyFile = fs.readFileSync(options.key)
118+
const privateKey = await unmarshalPrivateKey(keyFile)
119+
peerId = await peerIdFromKeys(privateKey.public.bytes, privateKey.bytes)
120+
}
121+
122+
const opts: Libp2pOptions<ServiceMap> = {
123+
peerId,
124+
addresses: {
125+
listen: options.noListen === true ? [] : ['/ip4/127.0.0.1/tcp/0']
126+
},
127+
transports: [tcp(), circuitRelayTransport()],
128+
streamMuxers: [],
129+
connectionEncryption: [noise()],
130+
connectionManager: {
131+
minConnections: 0
132+
}
133+
}
134+
135+
const services: ServiceFactoryMap = {
136+
identify: identify()
137+
}
138+
139+
if (options.muxer === 'mplex') {
140+
opts.streamMuxers?.push(mplex())
141+
} else {
142+
opts.streamMuxers?.push(yamux())
143+
}
144+
145+
if (options.pubsub === true) {
146+
if (options.pubsubRouter === 'floodsub') {
147+
services.pubsub = floodsub()
148+
} else {
149+
services.pubsub = gossipsub()
150+
}
151+
}
152+
153+
if (options.relay === true) {
154+
services.relay = circuitRelayServer()
155+
}
156+
157+
if (options.dht === true) {
158+
services.dht = (components: any) => {
159+
const dht: any = kadDHT({
160+
clientMode: false
161+
})(components)
162+
163+
// go-libp2p-daemon only has the older single-table DHT instead of the dual
164+
// lan/wan version found in recent go-ipfs versions. unfortunately it's been
165+
// abandoned so here we simulate the older config with the js implementation
166+
const lan: any = dht.lan
167+
168+
const protocol = '/ipfs/kad/1.0.0'
169+
lan.protocol = protocol
170+
lan.network.protocol = protocol
171+
lan.topologyListener.protocol = protocol
172+
173+
Object.defineProperties(lan, {
174+
[contentRoutingSymbol]: {
175+
get () {
176+
return dht[contentRoutingSymbol]
177+
}
178+
},
179+
[peerRoutingSymbol]: {
180+
get () {
181+
return dht[peerRoutingSymbol]
182+
}
183+
},
184+
[peerDiscoverySymbol]: {
185+
get () {
186+
return dht[peerDiscoverySymbol]
187+
}
188+
}
189+
})
190+
191+
return lan
192+
}
193+
}
194+
195+
const node: any = await createLibp2p({
196+
...opts,
197+
services
198+
})
199+
200+
const server = createServer(multiaddr('/ip4/0.0.0.0/tcp/0'), node)
201+
await server.start()
202+
203+
return {
204+
client: createClient(server.getMultiaddr()),
205+
stop: async () => {
206+
await server.stop()
207+
await node.stop()
208+
}
209+
}
210+
}
211+
212+
async function main (): Promise<void> {
213+
const factory: DaemonFactory = {
214+
async spawn (options: SpawnOptions) {
215+
if (options.type === 'go') {
216+
return createGoPeer(options)
217+
}
218+
219+
return createJsPeer(options)
220+
}
221+
}
222+
223+
await interopTests(factory)
224+
}
225+
226+
main().catch(err => {
227+
console.error(err) // eslint-disable-line no-console
228+
process.exit(1)
229+
})

0 commit comments

Comments
 (0)