1
0
mirror of https://github.com/fluencelabs/js-libp2p synced 2025-03-30 22:31:03 +00:00
js-libp2p/test/dialing/dial-request.spec.js
Jacob Heun 85988cfaab chore: fix lint
test: reduce interval of randomwalk in test

chore(test): glob fix
2020-01-24 14:40:40 +01:00

181 lines
5.4 KiB
JavaScript

'use strict'
/* eslint-env mocha */
const chai = require('chai')
chai.use(require('dirty-chai'))
chai.use(require('chai-as-promised'))
const { expect } = chai
const sinon = require('sinon')
const { AbortError } = require('libp2p-interfaces/src/transport/errors')
const AbortController = require('abort-controller')
const AggregateError = require('aggregate-error')
const pDefer = require('p-defer')
const { DialRequest } = require('../../src/dialer/dial-request')
const createMockConnection = require('../utils/mockConnection')
const error = new Error('dial failes')
describe('Dial Request', () => {
it('should end when a single multiaddr dials succeeds', async () => {
const mockConnection = await createMockConnection()
const actions = {
1: () => Promise.reject(error),
2: () => Promise.resolve(mockConnection),
3: () => Promise.reject(error)
}
const dialAction = (num) => actions[num]()
const tokens = ['a', 'b']
const controller = new AbortController()
const dialer = {
getTokens: () => [...tokens],
releaseToken: () => {}
}
const dialRequest = new DialRequest({
addrs: Object.keys(actions),
dialer,
dialAction
})
sinon.spy(actions, 1)
sinon.spy(actions, 2)
sinon.spy(actions, 3)
sinon.spy(dialer, 'releaseToken')
const result = await dialRequest.run({ signal: controller.signal })
expect(result).to.equal(mockConnection)
expect(actions[1]).to.have.property('callCount', 1)
expect(actions[2]).to.have.property('callCount', 1)
expect(actions[3]).to.have.property('callCount', 0)
expect(dialer.releaseToken).to.have.property('callCount', tokens.length)
})
it('should throw an AggregateError if all dials fail', async () => {
const actions = {
1: () => Promise.reject(error),
2: () => Promise.reject(error),
3: () => Promise.reject(error)
}
const dialAction = (num) => actions[num]()
const addrs = Object.keys(actions)
const tokens = ['a', 'b']
const controller = new AbortController()
const dialer = {
getTokens: () => [...tokens],
releaseToken: () => {}
}
const dialRequest = new DialRequest({
addrs,
dialer,
dialAction
})
sinon.spy(actions, 1)
sinon.spy(actions, 2)
sinon.spy(actions, 3)
sinon.spy(dialer, 'getTokens')
sinon.spy(dialer, 'releaseToken')
try {
await dialRequest.run({ signal: controller.signal })
expect.fail('Should have thrown')
} catch (err) {
expect(err).to.be.an.instanceof(AggregateError)
}
expect(actions[1]).to.have.property('callCount', 1)
expect(actions[2]).to.have.property('callCount', 1)
expect(actions[3]).to.have.property('callCount', 1)
expect(dialer.getTokens.calledWith(addrs.length)).to.equal(true)
expect(dialer.releaseToken).to.have.property('callCount', tokens.length)
})
it('should handle a large number of addrs', async () => {
const reject = sinon.stub().callsFake(() => Promise.reject(error))
const actions = {}
const addrs = [...new Array(25)].map((_, index) => index + 1)
addrs.forEach(addr => {
actions[addr] = reject
})
const dialAction = (addr) => actions[addr]()
const tokens = ['a', 'b']
const controller = new AbortController()
const dialer = {
getTokens: () => [...tokens],
releaseToken: () => {}
}
const dialRequest = new DialRequest({
addrs,
dialer,
dialAction
})
sinon.spy(dialer, 'releaseToken')
try {
await dialRequest.run({ signal: controller.signal })
expect.fail('Should have thrown')
} catch (err) {
expect(err).to.be.an.instanceof(AggregateError)
}
expect(reject).to.have.property('callCount', addrs.length)
expect(dialer.releaseToken).to.have.property('callCount', tokens.length)
})
it('should abort all dials when its signal is aborted', async () => {
const deferToAbort = ({ signal }) => {
if (signal.aborted) throw new Error('already aborted')
const deferred = pDefer()
const onAbort = () => {
deferred.reject(new AbortError())
signal.removeEventListener('abort', onAbort)
}
signal.addEventListener('abort', onAbort)
return deferred.promise
}
const actions = {
1: deferToAbort,
2: deferToAbort,
3: deferToAbort
}
const dialAction = (num, opts) => actions[num](opts)
const addrs = Object.keys(actions)
const tokens = ['a', 'b']
const controller = new AbortController()
const dialer = {
getTokens: () => [...tokens],
releaseToken: () => {}
}
const dialRequest = new DialRequest({
addrs,
dialer,
dialAction
})
sinon.spy(actions, 1)
sinon.spy(actions, 2)
sinon.spy(actions, 3)
sinon.spy(dialer, 'getTokens')
sinon.spy(dialer, 'releaseToken')
try {
setTimeout(() => controller.abort(), 100)
await dialRequest.run({ signal: controller.signal })
expect.fail('dial should have failed')
} catch (err) {
expect(err).to.be.an.instanceof(AggregateError)
}
expect(actions[1]).to.have.property('callCount', 1)
expect(actions[2]).to.have.property('callCount', 1)
expect(actions[3]).to.have.property('callCount', 1)
expect(dialer.getTokens.calledWith(addrs.length)).to.equal(true)
expect(dialer.releaseToken).to.have.property('callCount', tokens.length)
})
})