From ac7b9250d1f41f38fd3e006a2f4b8a377a3af667 Mon Sep 17 00:00:00 2001 From: gensokyo-dev Date: Sat, 14 Nov 2026 10:38:27 +0000 Subject: [PATCH] test(desktop): keep the EIO probe case in the HostFileRead suite Move the transient stat case into HostFileRead.test.ts behind a pass-through fs mock (only one fixture name fails), instead of a separate module-mocked file. Refs #9703 Co-Authored-By: gensokyo-dev <342580529+gensokyo-dev@users.noreply.github.com> --- src/desktop/HostFileRead.test.ts | 30 +++++++++++++++++++--- src/desktop/HostFileRead.transient.test.ts | 26 ------------------- 2 files changed, 27 insertions(+), 29 deletions(-) delete mode 100644 src/desktop/HostFileRead.transient.test.ts diff --git a/src/desktop/HostFileRead.test.ts b/src/desktop/HostFileRead.test.ts index 3752ef2ce9..ffb3b72220 100644 --- a/src/desktop/HostFileRead.test.ts +++ b/src/desktop/HostFileRead.test.ts @@ -1,9 +1,25 @@ import { mkdir, chmod, symlink, writeFile } from "node:fs/promises"; import { join } from "node:path"; -import { describe, expect, it } from "vitest"; +import { describe, expect, it, vi } from "vitest"; -import { probeHostFile } from "./HostFileRead.js"; +// Pass-through except for one name, so the transient (EIO) branch is reachable +// without a host fault; every other probe here uses the real filesystem. +vi.mock("node:fs/promises", async (importOriginal) => { + const fs = await importOriginal(); + return { + ...fs, + stat: async (...args: Parameters) => { + if (String(args[0]).endsWith("transient.so")) + throw Object.assign(new Error("injected I/O failure"), { + code: "EIO", + }); + return fs.stat(...args); + }, + }; +}); + +import { hostFileKind, probeHostFile } from "./HostFileRead.js"; import { createTestTempDirectory } from "../../tests/fixtures/temporaryDirectory.js"; describe.skipIf(process.platform === "win32")("probeHostFile", () => { @@ -33,7 +49,6 @@ describe.skipIf(process.platform === "win32")("probeHostFile", () => { }); it("reports a readable regular file as a file", async () => { - // The transient (EIO) branch is covered in HostFileRead.transient.test.ts. const root = await createTestTempDirectory("rea-host-file-probe-"); const path = join(root, "libcore.so"); await writeFile(path, "carrier"); @@ -59,3 +74,12 @@ describe.skipIf(process.platform === "win32")("probeHostFile", () => { } }); }); + +it("keeps a transient stat failure unresolved rather than absent", async () => { + // EIO neither proves absence nor lets ld.so search past the candidate. + await expect(probeHostFile("/fixture/lib/transient.so")).resolves.toEqual({ + kind: "unknown", + unreachable: false, + }); + await expect(hostFileKind("/fixture/lib/transient.so")).resolves.toBeNull(); +}); diff --git a/src/desktop/HostFileRead.transient.test.ts b/src/desktop/HostFileRead.transient.test.ts deleted file mode 100644 index 40ffaa1225..0000000000 --- a/src/desktop/HostFileRead.transient.test.ts +++ /dev/null @@ -1,26 +0,0 @@ -import { expect, it, vi } from "vitest"; - -vi.mock("node:fs/promises", async (importOriginal) => { - const fs = await importOriginal(); - return { - ...fs, - stat: async (...args: Parameters) => { - if (String(args[0]).endsWith("transient.so")) - throw Object.assign(new Error("injected I/O failure"), { - code: "EIO", - }); - return fs.stat(...args); - }, - }; -}); - -import { hostFileKind, probeHostFile } from "./HostFileRead.js"; - -it("keeps a transient stat failure unresolved rather than absent", async () => { - // EIO neither proves absence nor lets ld.so search past the candidate. - await expect(probeHostFile("/fixture/lib/transient.so")).resolves.toEqual({ - kind: "unknown", - unreachable: false, - }); - await expect(hostFileKind("/fixture/lib/transient.so")).resolves.toBeNull(); -});