Skip to content

Commit 30310f8

Browse files
authored
test: add sample network circuit relay tests (libp2p#275)
* test: add sample network circuit relay tests * test: use ephemeral ports
1 parent aa7f2e8 commit 30310f8

File tree

2 files changed

+208
-6
lines changed

2 files changed

+208
-6
lines changed

package.json

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@
3737
"npm": ">=3.0.0"
3838
},
3939
"devDependencies": {
40-
"aegir": "^15.0.0",
40+
"aegir": "^15.1.0",
4141
"chai": "^4.1.2",
4242
"dirty-chai": "^2.0.1",
4343
"libp2p-mplex": "~0.7.0",
@@ -48,6 +48,7 @@
4848
"libp2p-webrtc-star": "~0.14.0",
4949
"libp2p-websockets": "~0.12.0",
5050
"peer-book": "~0.7.0",
51+
"portfinder": "^1.0.16",
5152
"sinon": "^5.0.2",
5253
"webrtcsupport": "^2.2.0"
5354
},
@@ -58,7 +59,7 @@
5859
"hashlru": "^2.2.1",
5960
"interface-connection": "~0.3.2",
6061
"ip-address": "^5.8.9",
61-
"libp2p-circuit": "~0.2.0",
62+
"libp2p-circuit": "~0.2.1",
6263
"libp2p-identify": "~0.7.2",
6364
"lodash.includes": "^4.3.0",
6465
"moving-average": "^1.0.0",

test/circuit-relay.node.js

Lines changed: 205 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,19 +7,21 @@ const expect = chai.expect
77
chai.use(dirtyChai)
88

99
const sinon = require('sinon')
10-
10+
const once = require('once')
1111
const parallel = require('async/parallel')
12+
const series = require('async/series')
1213
const TCP = require('libp2p-tcp')
1314
const WS = require('libp2p-websockets')
15+
const multiplex = require('libp2p-mplex')
1416
const PeerBook = require('peer-book')
17+
const getPorts = require('portfinder').getPorts
1518

1619
const utils = require('./utils')
1720
const createInfos = utils.createInfos
18-
// const tryEcho = utils.tryEcho
1921
const Swarm = require('../src')
2022

2123
describe(`circuit`, function () {
22-
let swarmA // TCP
24+
let swarmA // TCP and WS
2325
let swarmB // WS
2426
let swarmC // no transports
2527
let dialSpyA
@@ -76,7 +78,7 @@ describe(`circuit`, function () {
7678
expect(swarmB.transports.Circuit).to.exist()
7779
})
7880

79-
it('add /p2p-curcuit addrs on start', (done) => {
81+
it('add /p2p-circuit addrs on start', (done) => {
8082
parallel([
8183
(cb) => swarmA.start(cb),
8284
(cb) => swarmB.start(cb)
@@ -136,4 +138,203 @@ describe(`circuit`, function () {
136138
done()
137139
})
138140
})
141+
142+
describe('in a basic network', () => {
143+
// Create 5 nodes
144+
// Make node 1 act as a Bootstrap node and relay (speak tcp and ws)
145+
// Make nodes 2 & 3 speak tcp only
146+
// Make nodes 4 & 5 speak WS only
147+
// Have all nodes dial node 1
148+
// Each node should get the peers of node 1
149+
// Attempt to dial to each peer
150+
let bootstrapSwitch
151+
let tcpSwitch1
152+
let tcpSwitch2
153+
let wsSwitch1
154+
let wsSwitch2
155+
let bootstrapPeer
156+
let tcpPeer1
157+
let tcpPeer2
158+
let wsPeer1
159+
let wsPeer2
160+
161+
before((done) => createInfos(5, (err, infos) => {
162+
expect(err).to.not.exist()
163+
164+
getPorts(6, (err, ports) => {
165+
expect(err).to.not.exist()
166+
167+
bootstrapPeer = infos[0]
168+
tcpPeer1 = infos[1]
169+
tcpPeer2 = infos[2]
170+
wsPeer1 = infos[3]
171+
wsPeer2 = infos[4]
172+
173+
// Setup the addresses of our nodes
174+
bootstrapPeer.multiaddrs.add(`/ip4/0.0.0.0/tcp/${ports.shift()}`)
175+
bootstrapPeer.multiaddrs.add(`/ip4/0.0.0.0/tcp/${ports.shift()}/ws`)
176+
tcpPeer1.multiaddrs.add(`/ip4/0.0.0.0/tcp/${ports.shift()}`)
177+
tcpPeer2.multiaddrs.add(`/ip4/0.0.0.0/tcp/${ports.shift()}`)
178+
wsPeer1.multiaddrs.add(`/ip4/0.0.0.0/tcp/${ports.shift()}/ws`)
179+
wsPeer2.multiaddrs.add(`/ip4/0.0.0.0/tcp/${ports.shift()}/ws`)
180+
181+
// Setup the bootstrap node with the minimum needed for being a relay
182+
bootstrapSwitch = new Swarm(bootstrapPeer, new PeerBook())
183+
bootstrapSwitch.connection.addStreamMuxer(multiplex)
184+
bootstrapSwitch.connection.reuse()
185+
bootstrapSwitch.connection.enableCircuitRelay({
186+
enabled: true,
187+
// The relay needs to allow hopping
188+
hop: {
189+
enabled: true
190+
}
191+
})
192+
193+
// Setup the tcp1 node with the minimum needed for dialing via a relay
194+
tcpSwitch1 = new Swarm(tcpPeer1, new PeerBook())
195+
tcpSwitch1.connection.addStreamMuxer(multiplex)
196+
tcpSwitch1.connection.reuse()
197+
tcpSwitch1.connection.enableCircuitRelay({
198+
enabled: true
199+
})
200+
201+
// Setup tcp2 node to not be able to dial/listen over relay
202+
tcpSwitch2 = new Swarm(tcpPeer2, new PeerBook())
203+
tcpSwitch2.connection.reuse()
204+
tcpSwitch2.connection.addStreamMuxer(multiplex)
205+
206+
// Setup the ws1 node with the minimum needed for dialing via a relay
207+
wsSwitch1 = new Swarm(wsPeer1, new PeerBook())
208+
wsSwitch1.connection.addStreamMuxer(multiplex)
209+
wsSwitch1.connection.reuse()
210+
wsSwitch1.connection.enableCircuitRelay({
211+
enabled: true
212+
})
213+
214+
// Setup the ws2 node with the minimum needed for dialing via a relay
215+
wsSwitch2 = new Swarm(wsPeer2, new PeerBook())
216+
wsSwitch2.connection.addStreamMuxer(multiplex)
217+
wsSwitch2.connection.reuse()
218+
wsSwitch2.connection.enableCircuitRelay({
219+
enabled: true
220+
})
221+
222+
bootstrapSwitch.transport.add('tcp', new TCP())
223+
bootstrapSwitch.transport.add('ws', new WS())
224+
tcpSwitch1.transport.add('tcp', new TCP())
225+
tcpSwitch2.transport.add('tcp', new TCP())
226+
wsSwitch1.transport.add('ws', new WS())
227+
wsSwitch2.transport.add('ws', new WS())
228+
229+
series([
230+
// start the nodes
231+
(cb) => {
232+
parallel([
233+
(cb) => bootstrapSwitch.start(cb),
234+
(cb) => tcpSwitch1.start(cb),
235+
(cb) => tcpSwitch2.start(cb),
236+
(cb) => wsSwitch1.start(cb),
237+
(cb) => wsSwitch2.start(cb)
238+
], cb)
239+
},
240+
// dial to the bootstrap node
241+
(cb) => {
242+
parallel([
243+
(cb) => tcpSwitch1.dial(bootstrapPeer, cb),
244+
(cb) => tcpSwitch2.dial(bootstrapPeer, cb),
245+
(cb) => wsSwitch1.dial(bootstrapPeer, cb),
246+
(cb) => wsSwitch2.dial(bootstrapPeer, cb)
247+
], cb)
248+
}
249+
], (err) => {
250+
if (err) return done(err)
251+
252+
done = once(done)
253+
// Wait for everyone to connect, before we try relaying
254+
bootstrapSwitch.on('peer-mux-established', () => {
255+
if (bootstrapSwitch._peerBook.getAllArray().length === 4) {
256+
done()
257+
}
258+
})
259+
})
260+
})
261+
}))
262+
263+
after((done) => {
264+
parallel([
265+
(cb) => bootstrapSwitch.stop(cb),
266+
(cb) => tcpSwitch1.stop(cb),
267+
(cb) => tcpSwitch2.stop(cb),
268+
(cb) => wsSwitch1.stop(cb),
269+
(cb) => wsSwitch2.stop(cb)
270+
], done)
271+
})
272+
273+
it('should be able to dial tcp -> tcp', (done) => {
274+
tcpSwitch2.once('peer-mux-established', (peerInfo) => {
275+
expect(peerInfo.id.toB58String()).to.equal(tcpPeer1.id.toB58String())
276+
done()
277+
})
278+
tcpSwitch1.dial(tcpPeer2, (err, connection) => {
279+
expect(err).to.not.exist()
280+
// We're not dialing a protocol, so we won't get a connection back
281+
expect(connection).to.be.undefined()
282+
})
283+
})
284+
285+
it('should be able to dial tcp -> ws over relay', (done) => {
286+
wsSwitch1.once('peer-mux-established', (peerInfo) => {
287+
expect(peerInfo.id.toB58String()).to.equal(tcpPeer1.id.toB58String())
288+
done()
289+
})
290+
tcpSwitch1.dial(wsPeer1, (err, connection) => {
291+
expect(err).to.not.exist()
292+
// We're not dialing a protocol, so we won't get a connection back
293+
expect(connection).to.be.undefined()
294+
})
295+
})
296+
297+
it('should be able to dial ws -> ws', (done) => {
298+
wsSwitch2.once('peer-mux-established', (peerInfo) => {
299+
expect(peerInfo.id.toB58String()).to.equal(wsPeer1.id.toB58String())
300+
done()
301+
})
302+
wsSwitch1.dial(wsPeer2, (err, connection) => {
303+
expect(err).to.not.exist()
304+
// We're not dialing a protocol, so we won't get a connection back
305+
expect(connection).to.be.undefined()
306+
})
307+
})
308+
309+
it('should be able to dial ws -> tcp over relay', (done) => {
310+
tcpSwitch1.once('peer-mux-established', (peerInfo) => {
311+
expect(peerInfo.id.toB58String()).to.equal(wsPeer2.id.toB58String())
312+
expect(Object.keys(tcpSwitch1._peerBook.getAll())).to.include(wsPeer2.id.toB58String())
313+
done()
314+
})
315+
wsSwitch2.dial(tcpPeer1, (err, connection) => {
316+
expect(err).to.not.exist()
317+
// We're not dialing a protocol, so we won't get a connection back
318+
expect(connection).to.be.undefined()
319+
})
320+
})
321+
322+
it('shouldnt be able to dial to a non relay node', (done) => {
323+
// tcpPeer2 doesnt have relay enabled
324+
wsSwitch1.dial(tcpPeer2, (err, connection) => {
325+
expect(err).to.exist()
326+
expect(connection).to.not.exist()
327+
done()
328+
})
329+
})
330+
331+
it('shouldnt be able to dial from a non relay node', (done) => {
332+
// tcpSwitch2 doesnt have relay enabled
333+
tcpSwitch2.dial(wsPeer1, (err, connection) => {
334+
expect(err).to.exist()
335+
expect(connection).to.not.exist()
336+
done()
337+
})
338+
})
339+
})
139340
})

0 commit comments

Comments
 (0)