OverviewFilesCommitsIssuesDocsReleasesPeers

pgh / test / preflight.test.js

78 lines · javascript ref:
// Tests for the filesystem preflight (lib/preflight.js).
//
// pgh requires a POSIX filesystem with unix domain sockets + symlinks
// (hardlinks are a soft dedup optimization). The preflight probes a dir and
// reports capability so `pgh init` can fail fast on exfat/NTFS/FAT or the WSL
// /mnt Windows-drive bridge instead of crashing mid-materialize / on UDS bind.
//
// We can't mount an unsupported fs in CI, so these tests assert the happy path
// on the real (POSIX) test fs and the report/format shape.

import test from 'brittle'
import { mkdtempSync, rmSync } from '#node:fs'
import { tmpdir } from '#node:os'
import { join } from '#node:path'

import { checkFilesystem, formatReport } from '../lib/preflight.js'

test('checkFilesystem: passes on a normal POSIX fs', async (t) => {
  const dir = mkdtempSync(join(tmpdir(), 'pgh-preflight-'))
  try {
    const r = await checkFilesystem(dir)
    t.ok(r.ok, 'ok on POSIX fs')
    t.ok(r.symlink, 'symlinks supported')
    t.ok(r.unixSocket, 'unix sockets supported')
    t.ok(r.hardlink, 'hardlinks supported')
    t.is(r.errors.length, 0, 'no errors')
  } finally {
    rmSync(dir, { recursive: true, force: true })
  }
})

test('checkFilesystem: cleans up its scratch dir', async (t) => {
  const { readdirSync } = await import('#node:fs')
  const dir = mkdtempSync(join(tmpdir(), 'pgh-preflight-'))
  try {
    await checkFilesystem(dir)
    const leftovers = readdirSync(dir).filter((n) => n.startsWith('.pgh-fscheck-'))
    t.is(leftovers.length, 0, 'no .pgh-fscheck- scratch dir left behind')
  } finally {
    rmSync(dir, { recursive: true, force: true })
  }
})

test('checkFilesystem: does not flag a normal dir as a Windows drive', async (t) => {
  const dir = mkdtempSync(join(tmpdir(), 'pgh-preflight-'))
  try {
    const r = await checkFilesystem(dir)
    t.absent(r.onWindowsDrive, 'tmpdir is not under /mnt')
  } finally {
    rmSync(dir, { recursive: true, force: true })
  }
})

test('formatReport: ok=true report renders all three capabilities', (t) => {
  const r = { ok: true, hardlink: true, symlink: true, unixSocket: true, onWindowsDrive: false, errors: [] }
  const out = formatReport(r, '/some/store')
  t.ok(out.includes('unix sockets: ok'), 'unix sockets line')
  t.ok(out.includes('symlinks:     ok'), 'symlinks line')
  t.ok(out.includes('hardlinks:    ok'), 'hardlinks line')
  t.absent(out.includes('required'), 'no required-marker when ok')
})

test('formatReport: failures are marked required, hardlink-loss noted, /mnt warned', (t) => {
  const r = {
    ok: false,
    hardlink: false,
    symlink: false,
    unixSocket: false,
    onWindowsDrive: true,
    errors: ['symlinks not supported (EPERM)', 'unix domain sockets not supported']
  }
  const out = formatReport(r, '/mnt/c/store')
  t.ok(out.includes('unix sockets: NO'), 'unix sockets NO')
  t.ok(out.includes('required'), 'required marker present for missing hard reqs')
  t.ok(out.includes('dedup disabled'), 'hardlink loss noted')
  t.ok(out.includes('Windows drive'), 'windows-drive warning present')
})