108 lines
3.0 KiB
JavaScript
108 lines
3.0 KiB
JavaScript
/**
|
|
* Integration: HyperDHT + protomux-rpc protocol (no Docker required).
|
|
*/
|
|
import test from 'brittle'
|
|
import DHT from 'hyperdht'
|
|
import createTestnet from 'hyperdht/testnet.js'
|
|
import ProtomuxRPC from 'protomux-rpc'
|
|
import { PROTOCOL, Methods, Pushes } from '../shared/protocol.js'
|
|
import { encodings } from '../shared/encodings.js'
|
|
|
|
test('protomux-rpc over HyperDHT: request + push', async (t) => {
|
|
t.plan(5)
|
|
|
|
const testnet = await createTestnet()
|
|
const { bootstrap } = testnet
|
|
|
|
const serverDht = new DHT({ bootstrap })
|
|
const keyPair = DHT.keyPair()
|
|
const server = serverDht.createServer()
|
|
|
|
let pushed = false
|
|
|
|
server.on('connection', (socket) => {
|
|
const rpc = new ProtomuxRPC(socket, {
|
|
id: keyPair.publicKey,
|
|
protocol: PROTOCOL,
|
|
...encodings,
|
|
})
|
|
|
|
rpc.respond(Methods.ping, encodings, () => ({ success: true, pong: Date.now() }))
|
|
rpc.respond(Methods.listContainers, encodings, () => ({
|
|
type: 'containers',
|
|
data: [{ Id: 'abc', Names: ['/demo'] }],
|
|
}))
|
|
|
|
// After client is up, push stats (simulates server broadcast)
|
|
setTimeout(() => {
|
|
rpc.event(Pushes.allStats, {
|
|
type: 'allStats',
|
|
data: [{ id: 'abc', cpu: 1.5, memory: 1024 }],
|
|
}, encodings)
|
|
}, 50)
|
|
})
|
|
|
|
await server.listen(keyPair)
|
|
|
|
const clientDht = new DHT({ bootstrap })
|
|
const socket = clientDht.connect(keyPair.publicKey)
|
|
|
|
await new Promise((resolve, reject) => {
|
|
const timer = setTimeout(() => reject(new Error('connect timeout')), 15000)
|
|
const done = () => {
|
|
clearTimeout(timer)
|
|
resolve()
|
|
}
|
|
socket.once('connect', done)
|
|
socket.once('open', done)
|
|
socket.once('error', (err) => {
|
|
clearTimeout(timer)
|
|
reject(err)
|
|
})
|
|
})
|
|
|
|
const rpc = new ProtomuxRPC(socket, {
|
|
id: keyPair.publicKey,
|
|
protocol: PROTOCOL,
|
|
...encodings,
|
|
})
|
|
|
|
rpc.respond(Pushes.allStats, encodings, (payload) => {
|
|
pushed = true
|
|
t.is(payload.type, 'allStats')
|
|
t.is(payload.data[0].id, 'abc')
|
|
return null
|
|
})
|
|
|
|
const pong = await rpc.request(Methods.ping, {}, encodings)
|
|
t.ok(pong.success)
|
|
|
|
const list = await rpc.request(Methods.listContainers, {}, encodings)
|
|
t.is(list.type, 'containers')
|
|
|
|
// Wait for push
|
|
await new Promise((r) => setTimeout(r, 200))
|
|
t.ok(pushed)
|
|
|
|
socket.destroy()
|
|
await server.close()
|
|
await serverDht.destroy()
|
|
await clientDht.destroy()
|
|
await testnet.destroy()
|
|
})
|
|
|
|
test('protocol method names are stable strings', (t) => {
|
|
t.is(Methods.listContainers, 'listContainers')
|
|
t.is(Methods.startTerminal, 'startTerminal')
|
|
t.is(Methods.killContainer, 'killContainer')
|
|
t.is(Methods.containerTop, 'containerTop')
|
|
t.is(Methods.updateContainer, 'updateContainer')
|
|
t.is(Methods.getSystemDf, 'getSystemDf')
|
|
t.is(Methods.handshake, 'handshake')
|
|
t.is(Pushes.containers, 'push:containers')
|
|
t.is(Pushes.pullProgress, 'push:pullProgress')
|
|
t.is(Pushes.buildProgress, 'push:buildProgress')
|
|
t.is(Pushes.dockerEvent, 'push:dockerEvent')
|
|
t.is(PROTOCOL, 'peardock/rpc')
|
|
})
|