OverviewFilesCommitsIssuesDocsReleasesPeers

keet-daemon / test / spawn-and-connect.test.js

79 lines · javascript ref:
// Smoke test: can keet-daemon start on FRESH storage and accept a UDS connection?
//
// Decouples the keet-core 4.x migration work from CI. Run locally with:
//   cd <a-dir-with-a-working-node_modules> && bare test/spawn-and-connect.test.js
// or from inside the installed hyper-tps tree:
//   cd /home/fleeky/.local/share/store/apps/hyper-tps && bare node_modules/keet-daemon/test/spawn-and-connect.test.js
//
// Times out and fails with a useful stderr line if startDaemon() never resolves
// (the historical failure mode is keet-core throwing during ready()).

import test from 'brittle'
import fs from 'fs'
import path from 'path'
import os from 'os'
import net from 'net'
import { startDaemon } from '../index.js'

function tmpDir () {
  const p = path.join(os.tmpdir(), 'kd-test-' + Math.random().toString(16).slice(2))
  fs.mkdirSync(p, { recursive: true })
  return p
}

test('keet-daemon spawns on fresh storage and listens on UDS', async (t) => {
  const storage = tmpDir()
  const sockPath = '/tmp/keet-daemon-test-' + Math.random().toString(16).slice(2) + '.sock'
  try { fs.unlinkSync(sockPath) } catch {}

  t.teardown(async () => {
    try { fs.unlinkSync(sockPath) } catch {}
    try { fs.rmSync(storage, { recursive: true, force: true }) } catch {}
  })

  // Hard time-cap. If startDaemon() never resolves, fail with a clear message
  // instead of hanging the test runner.
  let daemon = null
  const startResult = await Promise.race([
    startDaemon({ storage, socketPath: sockPath, debug: false })
      .then(d => ({ ok: true, daemon: d }))
      .catch(err => ({ ok: false, err })),
    new Promise(resolve => setTimeout(() => resolve({ ok: false, err: new Error('startDaemon timeout 30s') }), 30000))
  ])

  if (!startResult.ok) {
    console.error('[test] startDaemon failed:')
    console.error('[test] message:', startResult.err.message)
    if (startResult.err.code) console.error('[test] code:', startResult.err.code)
    if (startResult.err.stack) console.error('[test] stack:', startResult.err.stack)
  }
  t.ok(startResult.ok, 'startDaemon returned without throwing')
  if (!startResult.ok) return

  daemon = startResult.daemon
  t.teardown(async () => { try { await daemon?.close?.() } catch {} })

  // The UDS socket should exist after start
  t.ok(fs.existsSync(sockPath), 'UDS socket file exists at ' + sockPath)

  // And should accept a connection
  const connectResult = await new Promise(resolve => {
    const sock = net.createConnection(sockPath)
    const timer = setTimeout(() => {
      sock.destroy()
      resolve({ ok: false, err: 'connect timeout' })
    }, 3000)
    sock.once('connect', () => {
      clearTimeout(timer)
      sock.destroy()
      resolve({ ok: true })
    })
    sock.once('error', err => {
      clearTimeout(timer)
      resolve({ ok: false, err: err.message })
    })
  })
  if (!connectResult.ok) console.error('[test] UDS connect failed:', connectResult.err)
  t.ok(connectResult.ok, 'UDS socket accepts a connection')
})