import { test } from "node:test"; import assert from "node:assert/strict"; import type { StorageLocation } from "../lib/storageLocations"; import type { LocationRollup, MemoizedProbe } from "../controller/storageLocations"; import type { RegistryReader } from "./inputs"; import { buildStorageRows, storageClipsText, type StorageActionKind, type StorageRow, } from "./storage"; // Run with: // pnpm --filter yt-dlp-transcript-common exec tsx --test views/storage.test.ts const NOW = 1_700_000_000_000; function loc( id: string, root: string, extra: Partial = {}, ): StorageLocation { return { id, label: id.toUpperCase(), root, autoRepoint: false, ...extra }; } function rollup(partial: Partial): LocationRollup { return { locationId: partial.locationId ?? "x", slugs: partial.slugs ?? [], total: partial.total ?? 0, bytes: partial.bytes ?? 0, unknownBytes: partial.unknownBytes ?? 0, clipsBytes: partial.clipsBytes ?? 0, textBytes: partial.textBytes ?? 0, unknownTextBytes: partial.unknownTextBytes ?? 0, ok: partial.ok ?? 0, unreachable: partial.unreachable ?? 0, moving: partial.moving ?? 0, legacy: partial.legacy ?? 0, }; } const NO_JOBS: RegistryReader = { list: () => [], get: () => undefined, } as unknown as RegistryReader; function registryWith(jobs: Array>): RegistryReader { return { list: () => jobs, get: () => undefined } as unknown as RegistryReader; } function action(row: StorageRow, kind: StorageActionKind) { const found = row.actions.find((a) => a.kind === kind); assert.ok(found, `no ${kind} action on row ${row.id}`); return found; } test("an available location reports identity, free bytes, counts and a fresh probe", () => { const probe: MemoizedProbe = { status: "available", identity: { known: true, uuid: "09b5", fstype: "ext4", label: "platter", mountpoint: "/run/media/operator/09b5", relPath: "archilyzer-media", }, freeBytes: 1024, warning: "automount — may not be present at boot", probedAt: NOW - 4_000, }; const { rows } = buildStorageRows({ locations: [loc("cold", "/run/media/operator/09b5/archilyzer-media")], defaultLocationId: "cold", probes: { cold: probe }, rollups: { cold: rollup({ locationId: "cold", total: 3, ok: 2, unreachable: 1 }) }, registry: NO_JOBS, now: NOW, }); const row = rows[0]; assert.equal(row.statusLabel, "Available"); assert.equal(row.label, "COLD"); assert.equal(row.isDefault, true); assert.equal( row.identity, "platter · ext4 · UUID 09b5 · at /run/media/operator/09b5", ); assert.equal(row.freeBytes, 1024); assert.equal(row.lastProbeAgeMs, 4_000); assert.equal(row.channelsText, "2 ok / 1 unreachable / 0 moving"); assert.match(row.warning ?? "", /automount/); assert.equal(action(row, "refresh").offered, true); assert.equal(action(row, "edit").offered, true); // Nothing is wrong, so there is nothing to re-point or mount. assert.equal(action(row, "repoint").offered, false); assert.match(action(row, "repoint").withheld ?? "", /nothing to re-point/); assert.equal(action(row, "mount").offered, false); }); test("a probe with no freeBytes renders as absent, not as zero", () => { const { rows } = buildStorageRows({ locations: [loc("cold", "/mnt/cold")], defaultLocationId: "", probes: { cold: { status: "available", identity: { known: false }, probedAt: NOW }, }, rollups: {}, registry: NO_JOBS, now: NOW, }); assert.equal(rows[0].freeBytes, undefined); // An unknown identity is not a fault: no problem is reported for it. assert.equal(rows[0].identity, null); assert.equal(rows[0].status, "available"); }); test("mounted-elsewhere offers Re-point named after the candidate root", () => { const { rows } = buildStorageRows({ locations: [loc("cold", "/mnt/platter/media", { volume: { uuid: "09b5", mountpoint: "/mnt/platter", relPath: "media" }, })], defaultLocationId: "cold", probes: { cold: { status: "mounted-elsewhere", identity: { known: true, uuid: "09b5", mountpoint: "/run/media/operator/09b5", relPath: "media", }, candidateRoot: "/run/media/operator/09b5/media", probedAt: NOW, }, }, rollups: { cold: rollup({ locationId: "cold", total: 2, unreachable: 2 }) }, registry: NO_JOBS, now: NOW, }); const row = rows[0]; assert.equal(row.statusLabel, "Mounted elsewhere"); assert.equal(row.candidateRoot, "/run/media/operator/09b5/media"); const repoint = action(row, "repoint"); assert.equal(repoint.offered, true); assert.equal(repoint.label, "Re-point to /run/media/operator/09b5/media"); assert.equal(repoint.newRoot, "/run/media/operator/09b5/media"); // Two channels live there, so Delete is refused with the count and the root. const del = action(row, "delete"); assert.equal(del.offered, false); assert.match(del.withheld ?? "", /2 channel\(s\) still have their media under \/mnt\/platter\/media/); }); test("mounted-elsewhere with no candidate root withholds Re-point with the reason", () => { const { rows } = buildStorageRows({ locations: [loc("cold", "/mnt/platter/media")], defaultLocationId: "", probes: { cold: { status: "mounted-elsewhere", identity: { known: false }, probedAt: NOW, }, }, rollups: {}, registry: NO_JOBS, now: NOW, }); const repoint = action(rows[0], "repoint"); assert.equal(repoint.offered, false); assert.match(repoint.withheld ?? "", /could not work out where the root would be/); }); test("Mount is offered only for an unmounted volume with udisksctl present", () => { const inputs = { locations: [loc("cold", "/mnt/platter/media", { volume: { uuid: "09b5", mountpoint: "/mnt/platter", relPath: "media" }, })], defaultLocationId: "", probes: { cold: { status: "unmounted" as const, identity: { known: false as const }, probedAt: NOW, }, }, rollups: {}, registry: NO_JOBS, now: NOW, }; const withBin = buildStorageRows({ ...inputs, udisksctlAvailable: true }); const mount = action(withBin.rows[0], "mount"); assert.equal(mount.offered, true); assert.equal(mount.uuid, "09b5"); const withoutBin = buildStorageRows({ ...inputs, udisksctlAvailable: false }); const refused = action(withoutBin.rows[0], "mount"); assert.equal(refused.offered, false); assert.match(refused.withheld ?? "", /udisksctl is not available/); // Absent means the disk is not attached, and the copy says so rather than // blaming the binary. const absent = buildStorageRows({ ...inputs, udisksctlAvailable: true, probes: { cold: { status: "absent", identity: { known: false }, probedAt: NOW }, }, }); assert.match(action(absent.rows[0], "mount").withheld ?? "", /not attached/); }); test("Delete is offered once no channel is left on the root", () => { const { rows } = buildStorageRows({ locations: [loc("cold", "/mnt/cold")], defaultLocationId: "", probes: { cold: { status: "available", identity: { known: false }, probedAt: NOW }, }, rollups: { cold: rollup({ locationId: "cold" }) }, registry: NO_JOBS, now: NOW, }); assert.equal(action(rows[0], "delete").offered, true); }); test("a running re-point withholds every action on every row, with the job id", () => { const { rows } = buildStorageRows({ locations: [loc("cold", "/mnt/cold"), loc("warm", "/mnt/warm")], defaultLocationId: "cold", probes: { cold: { status: "available", identity: { known: false }, probedAt: NOW }, warm: { status: "unmounted", identity: { known: false }, probedAt: NOW, }, }, rollups: {}, registry: registryWith([ { id: "job-7", kind: "repoint-storage-location", status: "running" }, ]), udisksctlAvailable: true, now: NOW, }); for (const row of rows) { assert.match(row.busy ?? "", /job-7/); for (const a of row.actions) { assert.equal(a.offered, false, `${row.id}/${a.kind} should be withheld`); assert.match(a.withheld ?? "", /job-7/); } } }); test("a location that has never been probed reads as missing, not as a gap", () => { const { rows } = buildStorageRows({ locations: [loc("cold", "/mnt/cold")], defaultLocationId: "", probes: {}, rollups: {}, registry: NO_JOBS, now: NOW, }); assert.equal(rows[0].status, "missing"); assert.equal(rows[0].statusLabel, "Missing"); assert.equal(rows[0].identity, null); assert.equal(rows[0].lastProbeAgeMs, 0); assert.equal(rows[0].channelsText, "0 ok / 0 unreachable / 0 moving"); }); const GB = 1024 ** 3; test("bytes travel with the count of channels that could not be measured", () => { const { rows, bytesOnLocation, bytesInPlace } = buildStorageRows({ locations: [loc("cold", "/mnt/cold")], internal: { root: "/corpus/channels", freeBytes: 67 * GB }, defaultLocationId: "cold", probes: {}, rollups: { cold: rollup({ locationId: "cold", total: 3, ok: 3, bytes: 1500 * GB }), internal: rollup({ locationId: "internal", total: 5, ok: 5, bytes: 523 * GB, unknownBytes: 2, }), }, registry: NO_JOBS, now: NOW, }); // The internal row is FIRST — it is the row with the problem. assert.equal(rows[0].id, "internal"); assert.equal(rows[0].kind, "internal"); assert.equal(rows[0].root, "/corpus/channels"); assert.equal(rows[0].freeBytes, 67 * GB); assert.equal(rows[0].bytes, 523 * GB); assert.equal(rows[0].bytesText, "523.00 GB + 2 unmeasured"); assert.equal(rows[1].bytesText, "1.46 TB"); assert.equal(bytesInPlace, 523 * GB); assert.deepEqual(bytesOnLocation, { internal: 523 * GB, cold: 1500 * GB, }); }); // A ZERO THAT NOBODY MEASURED IS NOT A ZERO. A fresh corpus whose channels have // never had a report would otherwise say a 2 TB drive holds 0 B. test("nothing measured says so instead of claiming an empty drive", () => { const { rows } = buildStorageRows({ locations: [loc("cold", "/mnt/cold")], defaultLocationId: "", probes: {}, rollups: { cold: rollup({ locationId: "cold", total: 4, ok: 4, unknownBytes: 4 }), }, registry: NO_JOBS, now: NOW, }); assert.equal(rows[0].bytesText, "size unknown until Refresh report"); }); test("the internal row offers nothing, and says why for each", () => { const { rows } = buildStorageRows({ locations: [], internal: { root: "/corpus/channels" }, defaultLocationId: "", probes: {}, rollups: {}, registry: NO_JOBS, now: NOW, }); assert.equal(rows.length, 1); assert.equal(rows[0].status, "available"); assert.equal(rows[0].freeBytes, undefined); for (const a of rows[0].actions) { assert.equal(a.offered, false, a.kind); assert.match(a.withheld ?? "", /not a configured location/); } }); test("every row links to its own channel list, biggest first", () => { const { rows } = buildStorageRows({ locations: [loc("cold", "/mnt/cold")], internal: { root: "/corpus/channels" }, defaultLocationId: "", probes: {}, rollups: {}, registry: NO_JOBS, now: NOW, }); assert.equal(rows[0].channelsHref, "/channels?location=internal&sort=size"); assert.equal(rows[1].channelsHref, "/channels?location=cold&sort=size"); }); test("no internal input means no internal row (a caller that wants only the locations)", () => { const { rows, bytesInPlace } = buildStorageRows({ locations: [loc("cold", "/mnt/cold")], defaultLocationId: "", probes: {}, rollups: {}, registry: NO_JOBS, now: NOW, }); assert.deepEqual( rows.map((r) => r.id), ["cold"], ); assert.equal(bytesInPlace, 0); }); test("the clip-window line is rendered only when there are windows", () => { // Zero is not rendered: "0 B in clip windows" on every drive that has never // been walked by a report is noise on the one page where a byte figure is // supposed to mean something. assert.equal(storageClipsText(0), ""); assert.equal(storageClipsText(-1), ""); assert.match(storageClipsText(5 * 1024 ** 3), /5\.00 GB of it is fetched/); }); // RELEASE 17: a location holds the media tier of the channels on it, and // nothing else — their text and clip windows never leave the corpus volume, so // they are counted on the internal row, whose breakdown says so. test("a location row carries the media tier only; the internal row holds every channel's text and clips", () => { const payload = buildStorageRows({ locations: [loc("cold", "/mnt/cold")], internal: { root: "/corpus/channels", corpus: { textBytes: 3 * GB, clipsBytes: 2 * GB, unknown: 0 }, }, defaultLocationId: "", probes: {}, rollups: { cold: rollup({ locationId: "cold", total: 2, bytes: 10 * GB, clipsBytes: 1 * GB, textBytes: 1 * GB, ok: 2, }), internal: rollup({ locationId: "internal", total: 1, ok: 1, bytes: 5 * GB }), }, registry: NO_JOBS, udisksctlAvailable: false, now: 0, }); const cold = payload.rows.find((r) => r.id === "cold"); assert.equal(cold?.bytes, 10 * GB); assert.equal(cold?.clipsBytes, 0); assert.equal(cold?.clipsText, ""); assert.equal(cold?.tiersText, ""); const internal = payload.rows.find((r) => r.id === "internal"); // 5 GB of in-place media + 3 GB of text + 2 GB of clips. assert.equal(internal?.bytes, 10 * GB); assert.equal(internal?.clipsBytes, 2 * GB); assert.match(String(internal?.clipsText), /2\.00 GB of it is fetched clip windows/); assert.equal( internal?.tiersText, "text 3.00 GB + clips 2.00 GB on the corpus volume, plus 5.00 GB media of in-place channels", ); assert.equal(payload.bytesInPlace, 10 * GB); }); test("an old report's missing text figure is unknown on the internal row, never 0", () => { const { rows } = buildStorageRows({ locations: [], internal: { root: "/corpus/channels", corpus: { textBytes: 1 * GB, clipsBytes: 0, unknown: 2 }, }, defaultLocationId: "", probes: {}, rollups: { internal: rollup({ locationId: "internal", total: 3, ok: 3, bytes: 4 * GB, unknownBytes: 1 }), }, registry: NO_JOBS, now: 0, }); assert.equal(rows[0].bytes, 5 * GB); assert.equal(rows[0].unknownBytes, 3); assert.equal(rows[0].bytesText, "5.00 GB + 3 unmeasured"); }); test("the corpus row names legacy channels to migrate, never as unmeasured", () => { const { rows } = buildStorageRows({ locations: [], internal: { root: "/corpus/channels", corpus: { textBytes: 1 * GB, clipsBytes: 0, unknown: 0, legacy: 2 }, }, defaultLocationId: "", probes: {}, rollups: { internal: rollup({ locationId: "internal", total: 1, ok: 1, bytes: 1 * GB }) }, registry: NO_JOBS, now: 0, }); assert.equal(rows[0].unknownBytes, 0); assert.equal(rows[0].bytesText, "2.00 GB"); assert.match(rows[0].tiersText, /legacy \(2 to migrate\)/); }); test("a legacy channel counts as unreachable, with how many are to migrate", () => { const { rows } = buildStorageRows({ locations: [loc("cold", "/mnt/cold")], defaultLocationId: "", probes: {}, rollups: { cold: rollup({ locationId: "cold", total: 3, ok: 1, unreachable: 2, legacy: 2 }), }, registry: NO_JOBS, now: 0, }); assert.equal(rows[0].channels.legacy, 2); assert.equal(rows[0].channelsText, "1 ok / 2 unreachable (2 to migrate) / 0 moving"); }); test("a location whose drive is not answering reads so, and says since when", () => { const { rows } = buildStorageRows({ locations: [loc("cold", "/mnt/cold")], defaultLocationId: "", probes: { cold: { status: "stalled", identity: { known: false }, probedAt: NOW }, }, notAnswering: { cold: "not answering since 11:35 — a stat of its root did not answer within 3 s." }, rollups: { cold: rollup({ locationId: "cold", total: 2, unreachable: 2 }) }, registry: NO_JOBS, now: NOW, }); const row = rows[0]; assert.equal(row.status, "stalled"); assert.equal(row.statusLabel, "Not answering"); assert.match(String(row.notAnswering), /^not answering since 11:35/); assert.equal(row.freeBytes, undefined); // Neither re-point nor mount is offered for a drive that is here and stalled. assert.equal(action(row, "repoint").offered, false); assert.match(String(action(row, "repoint").withheld), /not answering/); assert.equal(action(row, "mount").offered, false); // A row with no entry says nothing. const quiet = buildStorageRows({ locations: [loc("cold", "/mnt/cold")], defaultLocationId: "", probes: {}, rollups: {}, registry: NO_JOBS, now: NOW, }).rows[0]; assert.equal(quiet.notAnswering, undefined); });