OverviewFilesCommitsIssuesDocsReleasesPeers

cthuloid / webui / test / discovery.test.js

52 lines · javascript ref:
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()
})