import test from 'brittle'
import { parseAvahiLine, Discovery } from '../lib/discovery.js'
import { waitFor } from './helpers.js'
// Captured from `avahi-browse -rpt _cthuloid._tcp` on stortron.
const RESOLVED = '=;enp2s0;IPv4;studiolight;_cthuloid._tcp;local;studiolight.local;192.168.50.89;1337;"proto=2"'
test('resolved line becomes an up event', (t) => {
t.alike(parseAvahiLine(RESOLVED), {
type: 'up', name: 'studiolight', host: 'studiolight.local', addr: '192.168.50.89', port: 1337, proto: 2
})
})
test('removal, browse-only, IPv6 and junk lines', (t) => {
t.alike(parseAvahiLine('-;enp2s0;IPv4;studiolight;_cthuloid._tcp;local'), { type: 'down', name: 'studiolight' })
t.is(parseAvahiLine('+;enp2s0;IPv4;studiolight;_cthuloid._tcp;local'), null, 'unresolved add waits for =')
t.is(parseAvahiLine('=;enp2s0;IPv6;studiolight;_cthuloid._tcp;local;studiolight.local;fe80::1;1337;"proto=2"'), null)
t.is(parseAvahiLine('Failed to create client object: Daemon not running'), null)
t.is(parseAvahiLine(''), null)
})
test('avahi decimal escapes are decoded, missing TXT tolerated', (t) => {
const ev = parseAvahiLine('=;eth0;IPv4;stage\\032left;_cthuloid._tcp;local;stage-left.local;10.0.0.7;1337;')
t.is(ev.name, 'stage left')
t.is(ev.proto, 0)
})
test('Discovery emits up/down from a running browser process', async (t) => {
// A stand-in for avahi-browse: prints an add, a resolve, then a removal.
const script = 'printf "%s\\n" ' +
"'+;e;IPv4;u1;_cthuloid._tcp;local' " +
"'=;e;IPv4;u1;_cthuloid._tcp;local;u1.local;10.0.0.5;1337;\"proto=2\"' " +
"'-;e;IPv4;u1;_cthuloid._tcp;local'; exec sleep 5"
const d = new Discovery({ command: ['sh', '-c', script], respawnMs: 60000 })
const events = []
d.on('up', (u) => events.push(['up', u.name, u.addr]))
d.on('down', (u) => events.push(['down', u.name]))
d.start()
t.ok(await waitFor(() => events.length === 2), 'two events')
t.alike(events, [['up', 'u1', '10.0.0.5'], ['down', 'u1']])
d.stop()
})
test('a missing avahi-browse is reported, not fatal', async (t) => {
const d = new Discovery({ command: ['cthuloid-no-such-binary'], respawnMs: 60000 })
let why = null
d.on('unavailable', (msg) => { why = msg })
d.start()
t.ok(await waitFor(() => why !== null), 'unavailable emitted: ' + why)
d.stop()
})