|
|
@ -1,15 +1,14 @@ |
|
|
|
const tape = require('tape') |
|
|
|
const test = require('brittle') |
|
|
|
const dgram = require('dgram') |
|
|
|
const DHT = require('./') |
|
|
|
|
|
|
|
tape('make tiny swarm', async function (t) { |
|
|
|
const swarm = await makeSwarm(2) |
|
|
|
test('make tiny swarm', async function (t) { |
|
|
|
await makeSwarm(2, t) |
|
|
|
t.pass('could make swarm') |
|
|
|
destroy(swarm) |
|
|
|
}) |
|
|
|
|
|
|
|
tape('make bigger swarm', async function (t) { |
|
|
|
const swarm = await makeSwarm(500) |
|
|
|
test('make bigger swarm', async function (t) { |
|
|
|
const swarm = await makeSwarm(500, t) |
|
|
|
|
|
|
|
const targetNode = swarm[25] |
|
|
|
const target = targetNode.id |
|
|
@ -59,15 +58,13 @@ tape('make bigger swarm', async function (t) { |
|
|
|
|
|
|
|
const { firewalled, host, port } = swarm[490] |
|
|
|
|
|
|
|
t.same(firewalled, false) |
|
|
|
t.same(port, swarm[490].address().port) |
|
|
|
t.is(firewalled, false) |
|
|
|
t.is(port, swarm[490].address().port) |
|
|
|
t.ok(host) |
|
|
|
|
|
|
|
destroy(swarm) |
|
|
|
}) |
|
|
|
|
|
|
|
tape('commit after query', async function (t) { |
|
|
|
const swarm = await makeSwarm(100) |
|
|
|
test('commit after query', async function (t) { |
|
|
|
const swarm = await makeSwarm(100, t) |
|
|
|
|
|
|
|
let commits = 0 |
|
|
|
|
|
|
@ -91,13 +88,11 @@ tape('commit after query', async function (t) { |
|
|
|
|
|
|
|
await q.finished() |
|
|
|
|
|
|
|
t.same(commits, swarm[42].table.k) |
|
|
|
|
|
|
|
destroy(swarm) |
|
|
|
t.is(commits, swarm[42].table.k) |
|
|
|
}) |
|
|
|
|
|
|
|
tape('map query stream', async function (t) { |
|
|
|
const swarm = await makeSwarm(10) |
|
|
|
test('map query stream', async function (t) { |
|
|
|
const swarm = await makeSwarm(10, t) |
|
|
|
|
|
|
|
const expected = [] |
|
|
|
const q = swarm[0].query({ command: 'find_node', target: swarm[0].table.id }, { |
|
|
@ -114,13 +109,11 @@ tape('map query stream', async function (t) { |
|
|
|
await q.finished() |
|
|
|
|
|
|
|
t.ok(expected.length > 0) |
|
|
|
t.same(buf, expected) |
|
|
|
|
|
|
|
destroy(swarm) |
|
|
|
t.alike(buf, expected) |
|
|
|
}) |
|
|
|
|
|
|
|
tape('timeouts', async function (t) { |
|
|
|
const [bootstrap, a, b] = await makeSwarm(3) |
|
|
|
test('timeouts', async function (t) { |
|
|
|
const [, a, b] = await makeSwarm(3, t) |
|
|
|
let tries = 0 |
|
|
|
|
|
|
|
b.on('request', function (req) { |
|
|
@ -133,15 +126,11 @@ tape('timeouts', async function (t) { |
|
|
|
const q = a.query({ command: 'nope', target: Buffer.alloc(32) }) |
|
|
|
await q.finished() |
|
|
|
|
|
|
|
t.same(tries, 3) |
|
|
|
|
|
|
|
bootstrap.destroy() |
|
|
|
a.destroy() |
|
|
|
b.destroy() |
|
|
|
t.is(tries, 3) |
|
|
|
}) |
|
|
|
|
|
|
|
tape('request with/without retries', async function (t) { |
|
|
|
const [bootstrap, a, b] = await makeSwarm(3) |
|
|
|
test('request with/without retries', async function (t) { |
|
|
|
const [, a, b] = await makeSwarm(3, t) |
|
|
|
let tries = 0 |
|
|
|
|
|
|
|
b.on('request', function (req) { |
|
|
@ -157,7 +146,7 @@ tape('request with/without retries', async function (t) { |
|
|
|
// do nothing
|
|
|
|
} |
|
|
|
|
|
|
|
t.same(tries, 3) |
|
|
|
t.is(tries, 3) |
|
|
|
|
|
|
|
try { |
|
|
|
await a.request({ command: 'nope' }, { host: '127.0.0.1', port: b.address().port }, { retry: false }) |
|
|
@ -165,15 +154,11 @@ tape('request with/without retries', async function (t) { |
|
|
|
// do nothing
|
|
|
|
} |
|
|
|
|
|
|
|
t.same(tries, 4) |
|
|
|
|
|
|
|
bootstrap.destroy() |
|
|
|
a.destroy() |
|
|
|
b.destroy() |
|
|
|
t.is(tries, 4) |
|
|
|
}) |
|
|
|
|
|
|
|
tape('reply onflush', async function (t) { |
|
|
|
const [bootstrap, a, b] = await makeSwarm(3) |
|
|
|
test('reply onflush', async function (t) { |
|
|
|
const [, a, b] = await makeSwarm(3, t) |
|
|
|
|
|
|
|
let flushed = false |
|
|
|
|
|
|
@ -187,14 +172,10 @@ tape('reply onflush', async function (t) { |
|
|
|
|
|
|
|
await a.request({ command: 'hello' }, { host: '127.0.0.1', port: b.address().port }) |
|
|
|
t.ok(flushed) |
|
|
|
|
|
|
|
bootstrap.destroy() |
|
|
|
a.destroy() |
|
|
|
b.destroy() |
|
|
|
}) |
|
|
|
|
|
|
|
tape('shorthand commit', async function (t) { |
|
|
|
const swarm = await makeSwarm(40) |
|
|
|
test('shorthand commit', async function (t) { |
|
|
|
const swarm = await makeSwarm(40, t) |
|
|
|
|
|
|
|
let tokens = 0 |
|
|
|
let notTokens = 0 |
|
|
@ -211,13 +192,11 @@ tape('shorthand commit', async function (t) { |
|
|
|
|
|
|
|
await q.finished() |
|
|
|
|
|
|
|
t.same(tokens, 20) |
|
|
|
t.is(tokens, 20) |
|
|
|
t.ok(notTokens >= tokens) |
|
|
|
|
|
|
|
destroy(swarm) |
|
|
|
}) |
|
|
|
|
|
|
|
tape('after ready it is always bound', async function (t) { |
|
|
|
test('after ready it is always bound', async function (t) { |
|
|
|
t.plan(2) |
|
|
|
|
|
|
|
const node = new DHT() |
|
|
@ -231,11 +210,11 @@ tape('after ready it is always bound', async function (t) { |
|
|
|
|
|
|
|
t.ok(typeof addr.port, 'is number') |
|
|
|
|
|
|
|
node.destroy() |
|
|
|
await node.destroy() |
|
|
|
}) |
|
|
|
|
|
|
|
tape('timeouts when commiting', async function (t) { |
|
|
|
const [bootstrap, a, b] = await makeSwarm(3) |
|
|
|
test('timeouts when commiting', async function (t) { |
|
|
|
const [, a, b] = await makeSwarm(3, t) |
|
|
|
let tries = 0 |
|
|
|
|
|
|
|
b.on('request', function (req) { |
|
|
@ -255,30 +234,22 @@ tape('timeouts when commiting', async function (t) { |
|
|
|
} |
|
|
|
|
|
|
|
t.ok(error, 'commit should fail') |
|
|
|
t.same(tries, 3) |
|
|
|
|
|
|
|
bootstrap.destroy() |
|
|
|
a.destroy() |
|
|
|
b.destroy() |
|
|
|
t.is(tries, 3) |
|
|
|
}) |
|
|
|
|
|
|
|
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()) |
|
|
|
test('toArray', async function (t) { |
|
|
|
const [bootstrap, a, b] = await makeSwarm(3, t) |
|
|
|
|
|
|
|
a.destroy() |
|
|
|
b.destroy() |
|
|
|
bootstrap.destroy() |
|
|
|
t.alike(a.toArray(), [{ host: '127.0.0.1', port: b.address().port }]) |
|
|
|
t.alike(b.toArray(), [{ host: '127.0.0.1', port: a.address().port }]) |
|
|
|
t.alike(bootstrap.toArray().sort(), [{ host: '127.0.0.1', port: a.address().port }, { host: '127.0.0.1', port: b.address().port }].sort()) |
|
|
|
}) |
|
|
|
|
|
|
|
tape('addNode / nodes option', async function (t) { |
|
|
|
const [bootstrap, a] = await makeSwarm(2) |
|
|
|
test('addNode / nodes option', async function (t) { |
|
|
|
const [bootstrap, a] = await makeSwarm(2, t) |
|
|
|
|
|
|
|
a.on('request', function (req) { |
|
|
|
t.same(req.value, null, 'expected data') |
|
|
|
t.is(req.value, null, 'expected data') |
|
|
|
req.reply(Buffer.from('world')) |
|
|
|
}) |
|
|
|
|
|
|
@ -290,75 +261,64 @@ tape('addNode / nodes option', async function (t) { |
|
|
|
|
|
|
|
const bNodes = b.toArray() |
|
|
|
|
|
|
|
t.same(bNodes, [{ host: '127.0.0.1', port: a.address().port }]) |
|
|
|
t.alike(bNodes, [{ host: '127.0.0.1', port: a.address().port }]) |
|
|
|
|
|
|
|
const responses = [] |
|
|
|
for await (const data of b.query({ command: 'hello', target: a.id })) { |
|
|
|
responses.push(data) |
|
|
|
} |
|
|
|
|
|
|
|
t.same(responses.length, 1, 'one response') |
|
|
|
t.same(responses[0].value, Buffer.from('world'), 'responded') |
|
|
|
t.is(responses.length, 1, 'one response') |
|
|
|
t.alike(responses[0].value, Buffer.from('world'), 'responded') |
|
|
|
|
|
|
|
const aNodes = a.toArray() |
|
|
|
|
|
|
|
t.same(aNodes, [{ host: '127.0.0.1', port: b.address().port }]) |
|
|
|
t.alike(aNodes, [{ host: '127.0.0.1', port: b.address().port }]) |
|
|
|
|
|
|
|
a.destroy() |
|
|
|
b.destroy() |
|
|
|
bootstrap.destroy() |
|
|
|
await b.destroy() |
|
|
|
}) |
|
|
|
|
|
|
|
tape('set bind', async function (t) { |
|
|
|
test('set bind', async function (t) { |
|
|
|
const port = await freePort() |
|
|
|
|
|
|
|
const a = new DHT({ bind: port, firewalled: false }) |
|
|
|
await a.ready() |
|
|
|
|
|
|
|
t.same(a.address().port, port, 'bound to explicit port') |
|
|
|
t.alike(a.address().port, port, 'bound to explicit port') |
|
|
|
|
|
|
|
const b = new DHT({ bind: port }) |
|
|
|
await b.ready() |
|
|
|
|
|
|
|
t.notSame(b.address().port, port, 'bound to different port as explicit one is taken') |
|
|
|
t.not(b.address().port, port, 'bound to different port as explicit one is taken') |
|
|
|
|
|
|
|
a.destroy() |
|
|
|
b.destroy() |
|
|
|
await a.destroy() |
|
|
|
await b.destroy() |
|
|
|
}) |
|
|
|
|
|
|
|
tape('relay', async function (t) { |
|
|
|
const [bootstrap, a, b, c] = await makeSwarm(4) |
|
|
|
test('relay', async function (t) { |
|
|
|
const [, a, b, c] = await makeSwarm(4, t) |
|
|
|
|
|
|
|
b.on('request', function (req) { |
|
|
|
t.same(req.command, 'route', 'b got request') |
|
|
|
t.same(req.from.port, a.address().port, 'from a') |
|
|
|
t.is(req.command, 'route', 'b got request') |
|
|
|
t.is(req.from.port, a.address().port, 'from a') |
|
|
|
const value = Buffer.concat([req.value, Buffer.from('b')]) |
|
|
|
req.relay(value, { host: '127.0.0.1', port: c.address().port }) |
|
|
|
}) |
|
|
|
|
|
|
|
c.on('request', function (req) { |
|
|
|
t.same(req.command, 'route', 'c got request') |
|
|
|
t.same(req.from.port, b.address().port, 'from b') |
|
|
|
t.is(req.command, 'route', 'c got request') |
|
|
|
t.is(req.from.port, b.address().port, 'from b') |
|
|
|
const value = Buffer.concat([req.value, Buffer.from('c')]) |
|
|
|
req.reply(value, { to: { host: '127.0.0.1', port: a.address().port } }) |
|
|
|
}) |
|
|
|
|
|
|
|
const res = await a.request({ command: 'route', value: Buffer.from('a') }, { host: '127.0.0.1', port: b.address().port }) |
|
|
|
|
|
|
|
t.same(res.value, Buffer.from('abc')) |
|
|
|
t.same(res.from.port, c.address().port) |
|
|
|
t.same(res.to.port, a.address().port) |
|
|
|
|
|
|
|
bootstrap.destroy() |
|
|
|
a.destroy() |
|
|
|
b.destroy() |
|
|
|
c.destroy() |
|
|
|
t.alike(res.value, Buffer.from('abc')) |
|
|
|
t.is(res.from.port, c.address().port) |
|
|
|
t.is(res.to.port, a.address().port) |
|
|
|
}) |
|
|
|
|
|
|
|
function destroy (list) { |
|
|
|
for (const node of list) node.destroy() |
|
|
|
} |
|
|
|
|
|
|
|
function freePort () { |
|
|
|
return new Promise(resolve => { |
|
|
|
const socket = dgram.createSocket('udp4') |
|
|
@ -371,7 +331,7 @@ function freePort () { |
|
|
|
}) |
|
|
|
} |
|
|
|
|
|
|
|
async function makeSwarm (n) { |
|
|
|
async function makeSwarm (n, t) { |
|
|
|
const node = DHT.bootstrapper() |
|
|
|
await node.ready() |
|
|
|
const all = [node] |
|
|
@ -381,5 +341,8 @@ async function makeSwarm (n) { |
|
|
|
await node.ready() |
|
|
|
all.push(node) |
|
|
|
} |
|
|
|
t.teardown(async function () { |
|
|
|
for (const node of all) await node.destroy() |
|
|
|
}) |
|
|
|
return all |
|
|
|
} |
|
|
|