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 }