OverviewFilesCommitsIssuesDocsReleasesPeers

pear-git-v3 / test / sidecar-wait.test.js

92 lines · javascript ref:
import test from 'brittle'
import { waitForSidecarSock, needsReregister } from '../lib/sidecar-wait.js'

// A fake clock + sleep so the poll loop runs instantly and
// deterministically — no real timers, no real filesystem.
function fakeTime () {
  let t = 0
  return {
    now: () => t,
    sleep: (ms) => { t += ms; return Promise.resolve() }
  }
}

test('returns true immediately when the socket already exists', async (t) => {
  const clock = fakeTime()
  let calls = 0
  const ok = await waitForSidecarSock({
    sock: '/x/svc.sock',
    exists: () => { calls++; return true },
    now: clock.now,
    sleep: clock.sleep
  })
  t.is(ok, true)
  t.is(calls, 1, 'checks once, never sleeps')
})

test('waits, then returns true once the socket appears (the boot race)', async (t) => {
  const clock = fakeTime()
  let checks = 0
  // Absent for the first 5 polls, then the sidecar creates its socket.
  const ok = await waitForSidecarSock({
    sock: '/x/svc.sock',
    timeoutMs: 120000,
    intervalMs: 1000,
    exists: () => ++checks > 5,
    now: clock.now,
    sleep: clock.sleep
  })
  t.is(ok, true)
  t.is(checks, 6, 'polled until the socket appeared')
  t.is(clock.now(), 5000, 'slept 5 intervals while waiting')
})

test('returns false when the deadline passes (sidecar never comes up)', async (t) => {
  const clock = fakeTime()
  const ok = await waitForSidecarSock({
    sock: '/x/svc.sock',
    timeoutMs: 3000,
    intervalMs: 1000,
    exists: () => false,
    now: clock.now,
    sleep: clock.sleep
  })
  t.is(ok, false)
})

test('bails out early when shouldStop() flips (daemon shutting down)', async (t) => {
  const clock = fakeTime()
  let stopping = false
  let checks = 0
  const ok = await waitForSidecarSock({
    sock: '/x/svc.sock',
    timeoutMs: 120000,
    intervalMs: 1000,
    exists: () => { if (++checks >= 3) stopping = true; return false },
    shouldStop: () => stopping,
    now: clock.now,
    sleep: clock.sleep
  })
  t.is(ok, false, 'stops without waiting for the deadline')
})

test('needsReregister: true when the sidecar has forgotten us', (t) => {
  // Sidecar restarted → in-memory registry empty → found:false.
  t.is(needsReregister({ found: false }, 1234), true, 'found:false → re-register')
  t.is(needsReregister(null, 1234), true, 'null lookup → re-register')
  t.is(needsReregister(undefined, 1234), true, 'undefined → re-register')
})

test('needsReregister: true when a stale entry has a different pid', (t) => {
  t.is(needsReregister({ found: true, pid: 999 }, 1234), true,
    'someone else / previous instance registered → reclaim')
})

test('needsReregister: false when the sidecar already knows this instance', (t) => {
  t.is(needsReregister({ found: true, pid: 1234 }, 1234), false,
    'our pid registered → no churn')
  // pid absent on either side shouldn't force needless re-registration.
  t.is(needsReregister({ found: true }, 1234), false, 'no recorded pid → trust found')
  t.is(needsReregister({ found: true, pid: 999 }, null), false, 'no self pid → trust found')
})