Archilyzer · Source

archilyzer

Archilyzer
git clone https://archilyzer.pages.dev/source/archilyzer.git
Log | Files | Refs | README | LICENSE

commit 85e9f5ead4dcedcf58125963747c8da6d208a346
parent 888034d132a6e812a53185a90d009ca909e6fde8
Author: I Mean I'm Just Saying <imeanimjustsaying@kiwifarms.st>
Date:   Thu, 17 Sep 2026 13:46:21 -0400

storage: a fake findmnt, and the five things a probe can say

A node script in the tests tmpdir reading a control file next to itself —
the e2e fixtures fake bins, scoped to one mkdtemp. It answers the three
questions probeLocation asks and can be told to hang.

Covered: each of the five statuses, both warnings (automount mountpoint and
no fstab entry), a findmnt that times out, and no findmnt at all — the last
two asserting the invariant this module exists for, that a probe failure
costs identity and never availability.

Two test seams paid for here: `findmntTimeoutMs`, so the hang case costs
150 ms rather than three seconds, and `byUuidDir`, which is the only way to
exercise unmounted-vs-absent without plugging a disk in. Exercising it made
`findmnt --fstab` exit 1 land correctly: that non-zero exit IS the answer
"not in fstab", and only a binary that never ran fails open.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

Diffstat:
Acommon/lib/storageVolumes.test.ts | 264+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Mcommon/lib/storageVolumes.ts | 52+++++++++++++++++++++++++++++++++++++++-------------
2 files changed, 303 insertions(+), 13 deletions(-)

diff --git a/common/lib/storageVolumes.test.ts b/common/lib/storageVolumes.test.ts @@ -0,0 +1,264 @@ +import test from "node:test"; +import assert from "node:assert/strict"; +import path from "node:path"; +import { tmpdir } from "node:os"; +import { chmod, mkdir, mkdtemp, rm, writeFile } from "node:fs/promises"; +import { probeLocation, type VolumeBins } from "./storageVolumes"; +import type { StorageLocation } from "./storageLocations"; + +// THE FAKE FINDMNT. A real one would need a real disk; this one is a node +// script that reads a control file next to itself and answers the three +// questions probeLocation asks (`-T <path>`, `-S UUID=`, `--fstab -S UUID=`). +// Same idea as the e2e fixtures' fake bins (editor/e2e/fixtures/bin), scoped to +// one mkdtemp so nothing leaks between tests. +const FAKE = `#!/usr/bin/env node +import { readFileSync } from "node:fs"; +import path from "node:path"; +const control = JSON.parse( + readFileSync(path.join(import.meta.dirname, "control.json"), "utf8"), +); +const argv = process.argv.slice(2); +if (control.sleepMs) { + // Busy-wait: a sleeping child that ignores SIGTERM is not what we are + // testing, and Atomics.wait is the portable blocking sleep. + Atomics.wait(new Int32Array(new SharedArrayBuffer(4)), 0, 0, control.sleepMs); +} +if (argv.includes("--fstab")) { + if (!control.fstab) process.exit(1); + process.stdout.write(control.fstab + "\\n"); + process.exit(0); +} +if (argv.includes("-S")) { + if (!control.uuidTarget) process.exit(1); + process.stdout.write(control.uuidTarget + "\\n"); + process.exit(0); +} +if (control.identity === null) process.exit(1); +process.stdout.write( + JSON.stringify({ filesystems: [control.identity] }) + "\\n", +); +`; + +type Control = { + // What `findmnt -J -T <root>` answers; null = exit 1. + identity?: Record<string, unknown> | null; + // What `findmnt -rn -S UUID=… -o TARGET` answers; absent = exit 1 (nowhere). + uuidTarget?: string; + // What `findmnt --fstab -S UUID=…` answers; absent = exit 1 (not in fstab). + fstab?: string; + sleepMs?: number; +}; + +type Harness = { + dir: string; + bins: VolumeBins; + // Directory standing in for /dev/disk/by-uuid. + byUuidDir: string; + control: (c: Control) => Promise<void>; +}; + +async function withHarness(fn: (h: Harness) => Promise<void>): Promise<void> { + const dir = await mkdtemp(path.join(tmpdir(), "ttb-volumes-")); + const bin = path.join(dir, "fake-findmnt.mjs"); + await writeFile(bin, FAKE); + await chmod(bin, 0o755); + const byUuidDir = path.join(dir, "by-uuid"); + await mkdir(byUuidDir, { recursive: true }); + try { + await fn({ + dir, + byUuidDir, + bins: { findmntBin: bin, udisksctlBin: path.join(dir, "no-udisksctl") }, + control: (c) => + writeFile(path.join(dir, "control.json"), JSON.stringify(c)), + }); + } finally { + await rm(dir, { recursive: true, force: true }); + } +} + +const UUID = "11111111-2222-3333-4444-555555555555"; + +function loc(root: string, withVolume = false): StorageLocation { + return { + id: "platter", + label: "Platter", + root, + autoRepoint: false, + ...(withVolume + ? { + volume: { + uuid: UUID, + fstype: "ext4", + mountpoint: "/mnt/platter", + relPath: "archilyzer-media", + }, + } + : {}), + }; +} + +test("available: the root is a directory, with identity and free bytes", async () => { + await withHarness(async (h) => { + const root = path.join(h.dir, "mnt", "platter", "archilyzer-media"); + await mkdir(root, { recursive: true }); + await h.control({ + identity: { + target: path.join(h.dir, "mnt", "platter"), + fstype: "ext4", + label: "PLATTER", + uuid: UUID, + }, + fstab: `UUID=${UUID}`, + }); + const p = await probeLocation(loc(root), h.bins, { + byUuidDir: h.byUuidDir, + }); + assert.equal(p.status, "available"); + assert.equal(p.identity.known, true); + assert.equal(p.identity.known && p.identity.uuid, UUID); + assert.equal(p.identity.known && p.identity.label, "PLATTER"); + // root === join(mountpoint, relPath), the invariant a re-point relies on. + assert.equal(p.identity.known && p.identity.relPath, "archilyzer-media"); + assert.ok((p.freeBytes ?? 0) > 0); + // In fstab and not an automount: nothing to warn about. + assert.equal(p.warning, undefined); + }); +}); + +test("available: an automounted root warns, and names its fstab line", async () => { + await withHarness(async (h) => { + const root = path.join(h.dir, "auto"); + await mkdir(root, { recursive: true }); + await h.control({ + // udisks mounts under /run/media/<user>/<uuid>. The mountpoint is what + // gives it away; the fstab query is not even made. + identity: { target: "/run/media/user/" + UUID, fstype: "ext4", uuid: UUID }, + fstab: `UUID=${UUID}`, + }); + const p = await probeLocation(loc(root), h.bins, { + byUuidDir: h.byUuidDir, + }); + assert.equal(p.status, "available"); + assert.match(p.warning ?? "", /automount/); + assert.match(p.warning ?? "", new RegExp(`UUID=${UUID} /mnt/platter ext4`)); + }); +}); + +test("available: a mount with no fstab entry warns too", async () => { + await withHarness(async (h) => { + const root = path.join(h.dir, "hand-mounted"); + await mkdir(root, { recursive: true }); + await h.control({ + identity: { target: root, fstype: "ext4", uuid: UUID }, + // No `fstab` key: the fake exits 1, as findmnt --fstab does. + }); + const p = await probeLocation(loc(root), h.bins, { + byUuidDir: h.byUuidDir, + }); + assert.equal(p.status, "available"); + assert.match(p.warning ?? "", /may not be present at boot/); + }); +}); + +test("mounted-elsewhere: the recorded uuid is up under another mountpoint", async () => { + await withHarness(async (h) => { + await h.control({ uuidTarget: "/run/media/user/" + UUID }); + const p = await probeLocation( + loc(path.join(h.dir, "gone", "archilyzer-media"), true), + h.bins, + { byUuidDir: h.byUuidDir }, + ); + assert.equal(p.status, "mounted-elsewhere"); + assert.equal( + p.candidateRoot, + `/run/media/user/${UUID}/archilyzer-media`, + ); + // The sighting is live enough to write back as the location's volume. + assert.equal(p.identity.known && p.identity.mountpoint, `/run/media/user/${UUID}`); + assert.equal(p.identity.known && p.identity.fstype, "ext4"); + assert.equal(p.freeBytes, undefined); + }); +}); + +test("unmounted: the disk is attached but nothing has mounted it", async () => { + await withHarness(async (h) => { + await h.control({}); + await writeFile(path.join(h.byUuidDir, UUID), ""); + const p = await probeLocation(loc(path.join(h.dir, "gone"), true), h.bins, { + byUuidDir: h.byUuidDir, + }); + assert.equal(p.status, "unmounted"); + assert.equal(p.identity.known, false); + }); +}); + +test("absent: the uuid is nowhere on this machine", async () => { + await withHarness(async (h) => { + await h.control({}); + const p = await probeLocation(loc(path.join(h.dir, "gone"), true), h.bins, { + byUuidDir: h.byUuidDir, + }); + assert.equal(p.status, "absent"); + }); +}); + +test("missing: no root and no identity to look for", async () => { + await withHarness(async (h) => { + await h.control({}); + const p = await probeLocation(loc(path.join(h.dir, "gone")), h.bins, { + byUuidDir: h.byUuidDir, + }); + assert.equal(p.status, "missing"); + assert.equal(p.identity.known, false); + }); +}); + +test("a findmnt that hangs times out, and the root stays available", async () => { + await withHarness(async (h) => { + const root = path.join(h.dir, "slow"); + await mkdir(root, { recursive: true }); + await h.control({ + sleepMs: 2_000, + identity: { target: root, fstype: "ext4", uuid: UUID }, + }); + const p = await probeLocation(loc(root), h.bins, { + findmntTimeoutMs: 150, + byUuidDir: h.byUuidDir, + }); + // THE POINT: a wedged automounter costs identity, never availability. + assert.equal(p.status, "available"); + assert.equal(p.identity.known, false); + assert.equal(p.warning, undefined); + assert.ok((p.freeBytes ?? 0) > 0); + }); +}); + +test("no findmnt at all: identity unknown, status still from stat", async () => { + await withHarness(async (h) => { + const root = path.join(h.dir, "container-bind-mount"); + await mkdir(root, { recursive: true }); + await h.control({}); + const p = await probeLocation( + loc(root), + { findmntBin: path.join(h.dir, "definitely-not-installed"), udisksctlBin: "x" }, + { byUuidDir: h.byUuidDir }, + ); + // This is the Docker case: no util-linux view of the volume, a perfectly + // healthy bind-mounted root. It must never read as unreachable. + assert.equal(p.status, "available"); + assert.equal(p.identity.known, false); + }); +}); + +test("a root that exists but is a file is not available", async () => { + await withHarness(async (h) => { + const root = path.join(h.dir, "not-a-dir"); + await writeFile(root, ""); + await h.control({}); + const p = await probeLocation(loc(root), h.bins, { + byUuidDir: h.byUuidDir, + }); + assert.equal(p.status, "missing"); + }); +}); diff --git a/common/lib/storageVolumes.ts b/common/lib/storageVolumes.ts @@ -63,12 +63,33 @@ export const FINDMNT_TIMEOUT_MS = 3_000; // udisksctl talks to a daemon over D-Bus and then waits for a real mount. export const MOUNT_TIMEOUT_MS = 15_000; -// Test seam ONLY. Production callers pass nothing and get the constants above; -// the unit tests shorten the findmnt timeout so the "fake binary that sleeps" -// case does not cost the suite three seconds. -export type ProbeOptions = { findmntTimeoutMs?: number }; +// The kernel's stable-name directory for volumes. A location's UUID has an +// entry here whenever the disk is attached, mounted or not — which is the whole +// difference between "unmounted" and "absent". +export const BY_UUID_DIR = "/dev/disk/by-uuid"; -type Run = { ok: boolean; stdout: string; stderr: string }; +// Test seams ONLY. Production callers pass nothing and get the constants above; +// the unit tests shorten the findmnt timeout (so the "fake binary that sleeps" +// case does not cost the suite three seconds) and point `byUuidDir` at a tmp +// directory, which is the only way to exercise unmounted-vs-absent without +// plugging a disk in. +export type ProbeOptions = { + findmntTimeoutMs?: number; + byUuidDir?: string; +}; + +type Run = { + ok: boolean; + // undefined = the binary never ran to completion (not installed, or killed + // by the timeout). A NUMBER is an answer from findmnt itself, and the + // difference matters: `findmnt --fstab` exits 1 to MEAN "no such entry", + // which is a fact, while a missing binary means "I could not ask", which is + // not. Conflating them would warn about fstab on every location in a + // container. + exitCode: number | undefined; + stdout: string; + stderr: string; +}; async function run( bin: string, @@ -81,14 +102,16 @@ async function run( reject: false, timeout, }); + const exitCode = res.timedOut ? undefined : (res.exitCode ?? undefined); return { - ok: res.exitCode === 0 && !res.timedOut, + ok: exitCode === 0, + exitCode, stdout: typeof res.stdout === "string" ? res.stdout : "", stderr: typeof res.stderr === "string" ? res.stderr : "", }; } catch { // ENOENT on the binary itself lands here in some execa paths. Same answer. - return { ok: false, stdout: "", stderr: "" }; + return { ok: false, exitCode: undefined, stdout: "", stderr: "" }; } } @@ -160,9 +183,11 @@ async function mountpointOfUuid( return first ?? ""; } -// `findmnt --fstab -S UUID=<u>` exits 1 when the volume has no fstab entry. -// FAILS OPEN TO "yes, it is in fstab": a missing findmnt must not produce a -// warning on every location on the page. +// `findmnt --fstab -S UUID=<u>` exits 1 when the volume has no fstab entry — +// that non-zero exit is the ANSWER, not a failure, which is why this reads +// `exitCode` and not `ok`. FAILS OPEN TO "yes, it is in fstab" only when the +// binary never ran: a missing findmnt must not warn about fstab on every +// location on the page. async function isInFstab( uuid: string, bins: VolumeBins, @@ -173,7 +198,8 @@ async function isInFstab( ["--fstab", "-S", `UUID=${uuid}`], timeoutMs, ); - return res.ok ? res.stdout.trim() !== "" : true; + if (res.exitCode === undefined) return true; + return res.exitCode === 0 && res.stdout.trim() !== ""; } function automountWarning( @@ -264,7 +290,7 @@ export async function probeLocation( // symlink the kernel maintains; lstat it so a dangling link still counts as // "the udev entry is there". try { - await lstat(path.join("/dev/disk/by-uuid", uuid)); + await lstat(path.join(opts.byUuidDir ?? BY_UUID_DIR, uuid)); return { status: "unmounted", identity: { known: false } }; } catch { return { status: "absent", identity: { known: false } }; @@ -315,7 +341,7 @@ export async function mountByUuid( } const res = await run( bins.udisksctlBin, - ["mount", "-b", path.join("/dev/disk/by-uuid", uuid)], + ["mount", "-b", path.join(BY_UUID_DIR, uuid)], MOUNT_TIMEOUT_MS, ); if (!res.ok) {