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.
257 lines
6.1 KiB
257 lines
6.1 KiB
const tape = require('tape')
|
|
const dht = require('./')
|
|
const blake2b = require('./lib/blake2b')
|
|
|
|
tape('simple update', function (t) {
|
|
bootstrap(function (port, node) {
|
|
const a = dht({ bootstrap: port })
|
|
const b = dht({ bootstrap: port })
|
|
|
|
a.command('echo', {
|
|
query (data, callback) {
|
|
t.fail('should not query')
|
|
callback(new Error('nope'))
|
|
},
|
|
update (data, callback) {
|
|
t.same(data.value, Buffer.from('Hello, World!'), 'expected data')
|
|
callback(null, data.value)
|
|
}
|
|
})
|
|
|
|
a.ready(function () {
|
|
b.update('echo', a.id, Buffer.from('Hello, World!'), function (err, responses) {
|
|
a.destroy()
|
|
b.destroy()
|
|
node.destroy()
|
|
|
|
t.error(err, 'no errors')
|
|
t.same(responses.length, 1, 'one response')
|
|
t.same(responses[0].value, Buffer.from('Hello, World!'), 'echoed data')
|
|
t.end()
|
|
})
|
|
})
|
|
})
|
|
})
|
|
|
|
tape('simple query', function (t) {
|
|
bootstrap(function (port, node) {
|
|
const a = dht({ bootstrap: port })
|
|
const b = dht({ bootstrap: port })
|
|
|
|
a.command('hello', {
|
|
query (data, callback) {
|
|
t.same(data.value, null, 'expected data')
|
|
callback(null, Buffer.from('world'))
|
|
}
|
|
})
|
|
|
|
a.ready(function () {
|
|
b.query('hello', a.id, function (err, responses) {
|
|
a.destroy()
|
|
b.destroy()
|
|
node.destroy()
|
|
|
|
t.error(err, 'no errors')
|
|
t.same(responses.length, 1, 'one response')
|
|
t.same(responses[0].value, Buffer.from('world'), 'responded')
|
|
t.end()
|
|
})
|
|
})
|
|
})
|
|
})
|
|
|
|
tape('query and update', function (t) {
|
|
bootstrap(function (port, node) {
|
|
const a = dht({ bootstrap: port })
|
|
const b = dht({ bootstrap: port })
|
|
|
|
a.command('hello', {
|
|
query (data, callback) {
|
|
t.same(data.value, null, 'expected query data')
|
|
callback(null, Buffer.from('world'))
|
|
},
|
|
update (data, callback) {
|
|
t.same(data.value, null, 'expected update data')
|
|
callback(null, Buffer.from('world'))
|
|
}
|
|
})
|
|
|
|
a.ready(function () {
|
|
b.queryAndUpdate('hello', a.id, function (err, responses) {
|
|
a.destroy()
|
|
b.destroy()
|
|
node.destroy()
|
|
|
|
t.error(err, 'no errors')
|
|
t.same(responses.length, 2, 'two responses')
|
|
t.same(responses[0].value, Buffer.from('world'), 'responded')
|
|
t.same(responses[1].value, Buffer.from('world'), 'responded')
|
|
t.ok(responses[0].type !== responses[1].type, 'not the same type')
|
|
t.end()
|
|
})
|
|
})
|
|
})
|
|
})
|
|
|
|
tape('swarm query', function (t) {
|
|
bootstrap(function (port, node) {
|
|
const swarm = []
|
|
var closest = 0
|
|
|
|
loop()
|
|
|
|
function done () {
|
|
t.pass('created swarm')
|
|
|
|
const key = blake2b(Buffer.from('hello'))
|
|
const me = dht({ bootstrap: port })
|
|
|
|
me.update('kv', key, Buffer.from('hello'), function (err, responses) {
|
|
t.error(err, 'no error')
|
|
t.same(closest, 20, '20 closest nodes')
|
|
t.same(responses.length, 20, '20 responses')
|
|
|
|
const stream = me.query('kv', key)
|
|
|
|
stream.on('data', function (data) {
|
|
if (data.value) {
|
|
t.same(data.value, Buffer.from('hello'), 'echoed value')
|
|
t.end()
|
|
swarm.forEach(function (node) {
|
|
node.destroy()
|
|
})
|
|
me.destroy()
|
|
node.destroy()
|
|
stream.destroy()
|
|
}
|
|
})
|
|
})
|
|
}
|
|
|
|
function loop () {
|
|
if (swarm.length === 256) return done()
|
|
const node = dht({ bootstrap: port })
|
|
swarm.push(node)
|
|
|
|
var value = null
|
|
|
|
node.command('kv', {
|
|
update (data, cb) {
|
|
closest++
|
|
value = data.value
|
|
cb()
|
|
},
|
|
query (data, cb) {
|
|
cb(null, value)
|
|
}
|
|
})
|
|
|
|
node.ready(loop)
|
|
}
|
|
})
|
|
})
|
|
|
|
tape('holepunch api', function (t) {
|
|
bootstrap(function (port, node) {
|
|
const a = dht({ bootstrap: port })
|
|
const b = dht({ bootstrap: port })
|
|
var holepunched = false
|
|
|
|
a.ready(function () {
|
|
b.ready(function () {
|
|
node.on('holepunch', function (from, to) {
|
|
t.same(from.port, a.address().port)
|
|
t.same(to.port, b.address().port)
|
|
holepunched = true
|
|
})
|
|
a.holepunch({
|
|
host: '127.0.0.1',
|
|
port: b.address().port,
|
|
referrer: {
|
|
host: '127.0.0.1',
|
|
port: node.address().port
|
|
}
|
|
}, function (err) {
|
|
t.error(err, 'no error')
|
|
t.ok(holepunched)
|
|
t.end()
|
|
|
|
node.destroy()
|
|
a.destroy()
|
|
b.destroy()
|
|
})
|
|
})
|
|
})
|
|
})
|
|
})
|
|
|
|
tape('timeouts', function (t) {
|
|
bootstrap(function (port, node) {
|
|
const a = dht({ bootstrap: port, ephemeral: true })
|
|
const b = dht({ bootstrap: port })
|
|
|
|
var tries = 0
|
|
|
|
b.command('nope', {
|
|
update (query, cb) {
|
|
tries++
|
|
t.pass('ignoring update')
|
|
}
|
|
})
|
|
|
|
b.ready(function () {
|
|
a.update('nope', Buffer.alloc(32), function (err) {
|
|
t.ok(err, 'errored')
|
|
t.same(tries, 3)
|
|
t.end()
|
|
node.destroy()
|
|
a.destroy()
|
|
b.destroy()
|
|
})
|
|
})
|
|
})
|
|
})
|
|
|
|
tape('persistent', function (t) {
|
|
bootstrap(function (port, node) {
|
|
const a = dht({ bootstrap: port, ephemeral: true })
|
|
const b = dht({ bootstrap: port })
|
|
a.command('hello', {
|
|
query (data, callback) {
|
|
callback(null, Buffer.from('world'))
|
|
}
|
|
})
|
|
|
|
a.ready(function () {
|
|
b.ready(function () {
|
|
const key = blake2b(Buffer.from('hello'))
|
|
b.query('hello', key, (err, result) => {
|
|
t.error(err)
|
|
t.is(result.length, 0)
|
|
a.persistent((err) => {
|
|
t.error(err)
|
|
b.query('hello', key, (err, result) => {
|
|
t.error(err)
|
|
t.is(result.length, 1)
|
|
t.is(Buffer.compare(result[0].node.id, a.id), 0)
|
|
a.destroy()
|
|
b.destroy()
|
|
node.destroy()
|
|
t.end()
|
|
})
|
|
})
|
|
})
|
|
})
|
|
})
|
|
})
|
|
})
|
|
|
|
function bootstrap (done) {
|
|
const node = dht({
|
|
ephemeral: true
|
|
})
|
|
|
|
node.listen(0, function () {
|
|
done(node.address().port, node)
|
|
})
|
|
}
|
|
|