You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

215 lines
4.6 KiB

const tape = require('tape')
const DHT = require('./')
tape('make tiny swarm', async function (t) {
const swarm = await makeSwarm(2)
t.pass('could make swarm')
destroy(swarm)
})
tape('make bigger swarm', async function (t) {
const swarm = await makeSwarm(500)
const targetNode = swarm[25]
let q = swarm[499].query(targetNode.id, 'find_node', null)
let messages = 0
let found = false
for await (const data of q) {
messages++
if (data.id && data.id.equals(targetNode.id)) {
found = true
break
}
}
t.ok(found, 'found target in ' + messages + ' message(s)')
q = swarm[490].query(targetNode.id, 'find_node', null, { closest: q.closest })
messages = 0
found = false
for await (const data of q) {
messages++
if (data.id && data.id.equals(targetNode.id)) {
found = true
break
}
}
t.ok(found, 'found target again in ' + messages + ' message(s)')
const { type, host, port } = swarm[490].remoteAddress()
t.same(type, DHT.NAT_OPEN)
t.same(port, swarm[490].address().port)
t.ok(host)
destroy(swarm)
})
tape('commit after query', async function (t) {
const swarm = await makeSwarm(100)
let commits = 0
for (const node of swarm) {
node.on('request', function (req) {
if (req.command === 'before') {
return req.reply(null)
}
if (req.command === 'after' && req.commit) {
commits++
return req.reply(null)
}
})
}
const q = swarm[42].query(swarm[0].table.id, 'before', null, {
commit (node, dht, query) {
return dht.request(query.target, 'after', null, node)
}
})
await q.finished()
t.same(commits, swarm[42].table.k)
destroy(swarm)
})
tape('map query stream', async function (t) {
const swarm = await makeSwarm(10)
const expected = []
const q = swarm[0].query(swarm[0].table.id, 'find_node', null, {
map (data) {
if (expected.length > 3) return null
expected.push(data.id)
return data.id
}
})
const buf = []
q.on('data', (data) => buf.push(data))
await q.finished()
t.same(buf, expected)
destroy(swarm)
})
tape('timeouts', async function (t) {
const [bootstrap, a, b] = await makeSwarm(3)
let tries = 0
b.on('request', function (req) {
if (req.command === 'nope') {
tries++
t.pass('ignoring request')
}
})
const q = a.query(Buffer.alloc(32), 'nope')
await q.finished()
t.same(tries, 4)
bootstrap.destroy()
a.destroy()
b.destroy()
})
tape('timeouts when commiting', async function (t) {
const [bootstrap, a, b] = await makeSwarm(3)
let tries = 0
b.on('request', function (req) {
if (req.command === 'nope') {
tries++
t.pass('ignoring request')
}
})
const q = a.query(Buffer.alloc(32), 'nope', null, { commit: true })
let error = null
try {
await q.finished()
} catch (err) {
error = err
}
t.ok(error, 'commit should fail')
t.same(tries, 4)
bootstrap.destroy()
a.destroy()
b.destroy()
})
tape('toArray', async function (t) {
const [bootstrap, a, b] = await makeSwarm(3)
t.same(a.toArray(), [{ host: '127.0.0.1', port: b.address().port }])
t.same(b.toArray(), [{ host: '127.0.0.1', port: a.address().port }])
t.same(bootstrap.toArray().sort(), [{ host: '127.0.0.1', port: a.address().port }, { host: '127.0.0.1', port: b.address().port }].sort())
a.destroy()
b.destroy()
bootstrap.destroy()
})
tape('addNode / nodes option', async function (t) {
const [bootstrap, a] = await makeSwarm(2)
a.on('request', function (req) {
t.same(req.value, null, 'expected data')
req.reply(Buffer.from('world'))
})
await bootstrap.ready()
await a.ready()
const b = new DHT({ ephemeral: false, nodes: [{ host: '127.0.0.1', port: a.address().port }] })
await b.ready()
const bNodes = b.toArray()
t.deepEqual(bNodes, [{ host: '127.0.0.1', port: a.address().port }])
const responses = []
for await (const data of b.query(a.id, 'hello')) {
responses.push(data)
}
t.same(responses.length, 1, 'one response')
t.same(responses[0].value, Buffer.from('world'), 'responded')
const aNodes = a.toArray()
t.deepEqual(aNodes, [{ host: '127.0.0.1', port: b.address().port }])
a.destroy()
b.destroy()
bootstrap.destroy()
})
function destroy (list) {
for (const node of list) node.destroy()
}
async function makeSwarm (n) {
const node = new DHT()
await node.bind(0)
const all = [node]
const bootstrap = ['localhost:' + node.address().port]
while (all.length < n) {
const node = new DHT({ ephemeral: false, bootstrap })
await node.ready()
all.push(node)
}
return all
}