js-libp2p/test/circuit/dialer.spec.js
Alex Potsides ae6af20e8e fix: pubsub promisify (#456)
* fix: allow pubsub sub/unsub via promises

* chore: fix linting errors
2019-09-24 14:02:07 +02:00

304 lines
8.8 KiB
JavaScript

/* eslint-env mocha */
/* eslint max-nested-callbacks: ["error", 5] */
'use strict'
const Dialer = require('../../src/circuit/circuit/dialer')
const nodes = require('./fixtures/nodes')
const Connection = require('interface-connection').Connection
const multiaddr = require('multiaddr')
const PeerInfo = require('peer-info')
const PeerId = require('peer-id')
const pull = require('pull-stream/pull')
const values = require('pull-stream/sources/values')
const asyncMap = require('pull-stream/throughs/async-map')
const pair = require('pull-pair/duplex')
const pb = require('pull-protocol-buffers')
const proto = require('../../src/circuit/protocol')
const utilsFactory = require('../../src/circuit/circuit/utils')
const sinon = require('sinon')
const chai = require('chai')
const dirtyChai = require('dirty-chai')
const expect = chai.expect
chai.use(dirtyChai)
describe('dialer tests', function () {
let dialer
beforeEach(() => {
dialer = sinon.createStubInstance(Dialer)
})
afterEach(() => {
sinon.restore()
})
describe('.dial', function () {
beforeEach(function () {
dialer.relayPeers = new Map()
dialer.relayPeers.set(nodes.node2.id, new Connection())
dialer.relayPeers.set(nodes.node3.id, new Connection())
dialer.dial.callThrough()
})
it('fail on non circuit addr', function () {
const dstMa = multiaddr(`/ipfs/${nodes.node4.id}`)
expect(() => dialer.dial(dstMa, (err) => {
err.to.match(/invalid circuit address/)
}))
})
it('dial a peer', function (done) {
const dstMa = multiaddr(`/p2p-circuit/ipfs/${nodes.node3.id}`)
dialer._dialPeer.callsFake(function (dstMa, relay, callback) {
return callback(null, dialer.relayPeers.get(nodes.node3.id))
})
dialer.dial(dstMa, (err, conn) => {
expect(err).to.not.exist()
expect(conn).to.be.an.instanceOf(Connection)
done()
})
})
it('dial a peer over the specified relay', function (done) {
const dstMa = multiaddr(`/ipfs/${nodes.node3.id}/p2p-circuit/ipfs/${nodes.node4.id}`)
dialer._dialPeer.callsFake(function (dstMa, relay, callback) {
expect(relay.toString()).to.equal(`/ipfs/${nodes.node3.id}`)
return callback(null, new Connection())
})
dialer.dial(dstMa, (err, conn) => {
expect(err).to.not.exist()
expect(conn).to.be.an.instanceOf(Connection)
done()
})
})
})
describe('.canHop', function () {
let fromConn = null
const peer = new PeerInfo(PeerId.createFromB58String('QmQWqGdndSpAkxfk8iyiJyz3XXGkrDNujvc8vEst3baubA'))
let p = null
beforeEach(function () {
p = pair()
fromConn = new Connection(p[0])
dialer.relayPeers = new Map()
dialer.relayConns = new Map()
dialer.utils = utilsFactory({})
dialer.canHop.callThrough()
dialer._dialRelayHelper.callThrough()
})
it('should handle successful CAN_HOP', (done) => {
dialer._dialRelay.callsFake((_, cb) => {
pull(
values([{
type: proto.CircuitRelay.type.HOP,
code: proto.CircuitRelay.Status.SUCCESS
}]),
pb.encode(proto.CircuitRelay),
p[1]
)
cb(null, fromConn)
})
dialer.canHop(peer, (err) => {
expect(err).to.not.exist()
expect(dialer.relayPeers.has(peer.id.toB58String())).to.be.ok()
done()
})
})
it('should handle failed CAN_HOP', function (done) {
dialer._dialRelay.callsFake((_, cb) => {
pull(
values([{
type: proto.CircuitRelay.type.HOP,
code: proto.CircuitRelay.Status.HOP_CANT_SPEAK_RELAY
}]),
pb.encode(proto.CircuitRelay),
p[1]
)
cb(null, fromConn)
})
dialer.canHop(peer, (err) => {
expect(err).to.exist()
expect(dialer.relayPeers.has(peer.id.toB58String())).not.to.be.ok()
done()
})
})
})
describe('._dialPeer', function () {
beforeEach(function () {
dialer.relayPeers = new Map()
dialer.relayPeers.set(nodes.node1.id, new Connection())
dialer.relayPeers.set(nodes.node2.id, new Connection())
dialer.relayPeers.set(nodes.node3.id, new Connection())
dialer._dialPeer.callThrough()
})
it('should dial a peer over any relay', function (done) {
const dstMa = multiaddr(`/ipfs/${nodes.node4.id}`)
dialer._negotiateRelay.callsFake(function (conn, dstMa, callback) {
if (conn === dialer.relayPeers.get(nodes.node3.id)) {
return callback(null, dialer.relayPeers.get(nodes.node3.id))
}
callback(new Error('error'))
})
dialer._dialPeer(dstMa, (err, conn) => {
expect(err).to.not.exist()
expect(conn).to.be.an.instanceOf(Connection)
expect(conn).to.deep.equal(dialer.relayPeers.get(nodes.node3.id))
done()
})
})
it('should fail dialing a peer over any relay', function (done) {
const dstMa = multiaddr(`/ipfs/${nodes.node4.id}`)
dialer._negotiateRelay.callsFake(function (conn, dstMa, callback) {
callback(new Error('error'))
})
dialer._dialPeer(dstMa, (err, conn) => {
expect(conn).to.be.undefined()
expect(err).to.not.be.null()
expect(err).to.equal('no relay peers were found or all relays failed to dial')
done()
})
})
})
describe('._negotiateRelay', function () {
const dstMa = multiaddr(`/ipfs/${nodes.node4.id}`)
let conn = null
let peer = null
let p = null
before((done) => {
PeerId.createFromJSON(nodes.node4, (_, peerId) => {
PeerInfo.create(peerId, (err, peerInfo) => {
peer = peerInfo
peer.multiaddrs.add('/p2p-circuit/ipfs/QmSswe1dCFRepmhjAMR5VfHeokGLcvVggkuDJm7RMfJSrE')
done(err)
})
})
})
beforeEach(() => {
dialer.swarm = {
_peerInfo: peer
}
dialer.utils = utilsFactory({})
dialer.relayConns = new Map()
dialer._negotiateRelay.callThrough()
dialer._dialRelayHelper.callThrough()
peer = new PeerInfo(PeerId.createFromB58String('QmSswe1dCFRepmhjAMR5VfHeokGLcvVggkuDJm7RMfJSrE'))
p = pair()
conn = new Connection(p[1])
})
it('should write the correct dst addr', function (done) {
dialer._dialRelay.callsFake((_, cb) => {
pull(
p[0],
pb.decode(proto.CircuitRelay),
asyncMap((msg, cb) => {
expect(msg.dstPeer.addrs[0]).to.deep.equal(dstMa.buffer)
cb(null, {
type: proto.CircuitRelay.Type.STATUS,
code: proto.CircuitRelay.Status.SUCCESS
})
}),
pb.encode(proto.CircuitRelay),
p[0]
)
cb(null, conn)
})
dialer._negotiateRelay(peer, dstMa, done)
})
it('should negotiate relay', function (done) {
dialer._dialRelay.callsFake((_, cb) => {
pull(
p[0],
pb.decode(proto.CircuitRelay),
asyncMap((msg, cb) => {
expect(msg.dstPeer.addrs[0]).to.deep.equal(dstMa.buffer)
cb(null, {
type: proto.CircuitRelay.Type.STATUS,
code: proto.CircuitRelay.Status.SUCCESS
})
}),
pb.encode(proto.CircuitRelay),
p[0]
)
cb(null, conn)
})
dialer._negotiateRelay(peer, dstMa, (err, conn) => {
expect(err).to.not.exist()
expect(conn).to.be.instanceOf(Connection)
done()
})
})
it('should fail with an invalid peer id', function (done) {
const dstMa = multiaddr('/ip4/127.0.0.1/tcp/4001')
dialer._dialRelay.callsFake((_, cb) => {
pull(
p[0],
pb.decode(proto.CircuitRelay),
asyncMap((msg, cb) => {
expect(msg.dstPeer.addrs[0]).to.deep.equal(dstMa.buffer)
cb(null, {
type: proto.CircuitRelay.Type.STATUS,
code: proto.CircuitRelay.Status.SUCCESS
})
}),
pb.encode(proto.CircuitRelay),
p[0]
)
cb(null, conn)
})
dialer._negotiateRelay(peer, dstMa, (err, conn) => {
expect(err).to.exist()
expect(conn).to.not.exist()
done()
})
})
it('should handle failed relay negotiation', function (done) {
dialer._dialRelay.callsFake((_, cb) => {
cb(null, conn)
pull(
values([{
type: proto.CircuitRelay.Type.STATUS,
code: proto.CircuitRelay.Status.MALFORMED_MESSAGE
}]),
pb.encode(proto.CircuitRelay),
p[0]
)
})
dialer._negotiateRelay(peer, dstMa, (err, conn) => {
expect(err).to.not.be.null()
expect(err).to.be.an.instanceOf(Error)
expect(err.message).to.be.equal('Got 400 error code trying to dial over relay')
done()
})
})
})
})