js-libp2p/test/peer-routing/peer-routing.node.js
2020-05-28 12:37:48 +02:00

214 lines
5.5 KiB
JavaScript

'use strict'
/* eslint-env mocha */
const chai = require('chai')
chai.use(require('dirty-chai'))
const { expect } = chai
const nock = require('nock')
const sinon = require('sinon')
const pDefer = require('p-defer')
const mergeOptions = require('merge-options')
const DelegatedPeerRouter = require('libp2p-delegated-peer-routing')
const peerUtils = require('../utils/creators/peer')
const { baseOptions, routingOptions } = require('./utils')
describe('peer-routing', () => {
describe('no routers', () => {
let node
before(async () => {
[node] = await peerUtils.createPeer({
config: baseOptions
})
})
it('.findPeer should return an error', async () => {
await expect(node.peerRouting.findPeer('a cid'))
.to.eventually.be.rejected()
.and.to.have.property('code', 'NO_ROUTERS_AVAILABLE')
})
})
describe('via dht router', () => {
const number = 5
let nodes
before(async () => {
nodes = await peerUtils.createPeer({
number,
config: routingOptions
})
// Ring dial
await Promise.all(
nodes.map((peer, i) => peer.dial(nodes[(i + 1) % number].peerId))
)
})
after(() => {
sinon.restore()
})
after(() => Promise.all(nodes.map((n) => n.stop())))
it('should use the nodes dht', () => {
const deferred = pDefer()
sinon.stub(nodes[0]._dht, 'findPeer').callsFake(() => {
deferred.resolve()
return nodes[1].peerId
})
nodes[0].peerRouting.findPeer()
return deferred.promise
})
})
describe('via delegate router', () => {
let node
let delegate
beforeEach(async () => {
delegate = new DelegatedPeerRouter({
host: '0.0.0.0',
protocol: 'http',
port: 60197
})
;[node] = await peerUtils.createPeer({
config: mergeOptions(baseOptions, {
modules: {
peerRouting: [delegate]
},
config: {
dht: {
enabled: false
}
}
})
})
})
afterEach(() => {
nock.cleanAll()
sinon.restore()
})
afterEach(() => node.stop())
it('should use the delegate router to find peers', async () => {
const deferred = pDefer()
sinon.stub(delegate, 'findPeer').callsFake(() => {
deferred.resolve()
return 'fake peer-id'
})
await node.peerRouting.findPeer()
return deferred.promise
})
it('should be able to find a peer', async () => {
const peerKey = 'QmTp9VkYvnHyrqKQuFPiuZkiX9gPcqj6x5LJ1rmWuSySnL'
const mockApi = nock('http://0.0.0.0:60197')
.post('/api/v0/dht/findpeer')
.query(true)
.reply(200, `{"Extra":"","ID":"some other id","Responses":null,"Type":0}\n{"Extra":"","ID":"","Responses":[{"Addrs":["/ip4/127.0.0.1/tcp/4001"],"ID":"${peerKey}"}],"Type":2}\n`, [
'Content-Type', 'application/json',
'X-Chunked-Output', '1'
])
const peer = await node.peerRouting.findPeer(peerKey)
expect(peer.id).to.equal(peerKey)
expect(mockApi.isDone()).to.equal(true)
})
it('should error when a peer cannot be found', async () => {
const peerKey = 'key of a peer not on the network'
const mockApi = nock('http://0.0.0.0:60197')
.post('/api/v0/dht/findpeer')
.query(true)
.reply(200, '{"Extra":"","ID":"some other id","Responses":null,"Type":6}\n{"Extra":"","ID":"yet another id","Responses":null,"Type":0}\n{"Extra":"routing:not found","ID":"","Responses":null,"Type":3}\n', [
'Content-Type', 'application/json',
'X-Chunked-Output', '1'
])
await expect(node.peerRouting.findPeer(peerKey))
.to.eventually.be.rejected()
expect(mockApi.isDone()).to.equal(true)
})
it('should handle errors from the api', async () => {
const peerKey = 'key of a peer not on the network'
const mockApi = nock('http://0.0.0.0:60197')
.post('/api/v0/dht/findpeer')
.query(true)
.reply(502)
await expect(node.peerRouting.findPeer(peerKey))
.to.eventually.be.rejected()
expect(mockApi.isDone()).to.equal(true)
})
})
describe('via dht and delegate routers', () => {
let node
let delegate
beforeEach(async () => {
delegate = new DelegatedPeerRouter({
host: '0.0.0.0',
protocol: 'http',
port: 60197
})
;[node] = await peerUtils.createPeer({
config: mergeOptions(routingOptions, {
modules: {
peerRouting: [delegate]
}
})
})
})
afterEach(() => {
sinon.restore()
})
afterEach(() => node.stop())
it('should only use the dht if it finds the peer', async () => {
const dhtDeferred = pDefer()
sinon.stub(node._dht, 'findPeer').callsFake(() => {
dhtDeferred.resolve()
return { id: node.peerId }
})
sinon.stub(delegate, 'findPeer').callsFake(() => {
throw new Error('the delegate should not have been called')
})
await node.peerRouting.findPeer('a peer id')
await dhtDeferred.promise
})
it('should use the delegate if the dht fails to find the peer', async () => {
const results = [true]
sinon.stub(node._dht, 'findPeer').callsFake(() => {})
sinon.stub(delegate, 'findPeer').callsFake(() => {
return results
})
const peer = await node.peerRouting.findPeer('a peer id')
expect(peer).to.eql(results)
})
})
})