Files
rea/tests/boundary/filesystem/referenceSourceQueuedDirectories.test.ts
morlutoandXY-code1 d6e4fe4a4d fix(reference): preserve observed directories and unreadable links
Continue validating child directories observed before a parent enumeration failure. Reconcile unobserved link targets at the reader using canonical path identity and the nearest failed ancestor, preserving exclusions and cancellation.

Refs: #4013, #4053, #4060

Co-authored-by: XY-code1 <1611761391@qq.com>
2026-10-16 04:41:40 +08:00

108 lines
3.4 KiB
TypeScript

import type { Dir, Dirent } from "node:fs";
import { mkdir, symlink, writeFile } from "node:fs/promises";
import { join } from "node:path";
import { expect, it, vi } from "vitest";
import { createTestTempDirectory } from "../../fixtures/temporaryDirectory.js";
import { importReferenceSource } from "../../support/referenceSourceResourceScope.js";
const { opendirMock } = vi.hoisted(() => ({ opendirMock: vi.fn() }));
vi.mock("node:fs/promises", async (importOriginal) => ({
...(await importOriginal<typeof import("node:fs/promises")>()),
opendir: opendirMock,
}));
const directoryHandle = (items: readonly (string | Error | null)[]): Dir => {
let index = 0;
return {
async read() {
const item = items[index++];
if (item instanceof Error) throw item;
return item === null || item === undefined
? null
: ({ name: item } as Dirent);
},
async close() {},
} as unknown as Dir;
};
it.skipIf(process.platform === "win32")(
"traverses directories lstat-observed before their parent enumeration failed",
async () => {
const root = await createTestTempDirectory(
"rea-queued-source-directories-",
);
const container = join(root, "container");
const hidden = join(container, "hidden");
await mkdir(hidden, { recursive: true });
await writeFile(join(container, "visible.txt"), "visible\n");
await writeFile(join(hidden, "target.txt"), "target\n");
await symlink("hidden/target.txt", join(container, "alias-file.txt"));
await symlink("hidden", join(container, "alias-directory"));
const readFailure = Object.assign(
new Error("injected directory read failure"),
{ code: "EIO" },
);
opendirMock.mockImplementation(async (path: string) => {
if (path === root) return directoryHandle(["container", null]);
if (path === container)
return directoryHandle([
"visible.txt",
"hidden",
"alias-file.txt",
"alias-directory",
readFailure,
]);
if (path === hidden) return directoryHandle(["target.txt", null]);
throw new Error(`Unexpected directory traversal: ${path}`);
});
const imported = await importReferenceSource({
root,
caller: "queued-directory-read-failure-test",
policy: { secretPatterns: [] },
});
if (!imported.ok) throw new Error(imported.error.message);
expect(imported.value.inventory_state).toBe("partial");
expect(imported.value.entries).toEqual(
expect.arrayContaining([
expect.objectContaining({
path: "container",
kind: "directory",
tree_state: "unreadable",
}),
expect.objectContaining({
path: "container/hidden",
kind: "directory",
tree_state: "enumerated",
}),
expect.objectContaining({
path: "container/visible.txt",
kind: "file",
content_state: "hashed",
}),
expect.objectContaining({
path: "container/hidden/target.txt",
kind: "file",
content_state: "hashed",
}),
expect.objectContaining({
path: "container/alias-file.txt",
kind: "symlink",
target: "hidden/target.txt",
target_state: "internal",
}),
expect.objectContaining({
path: "container/alias-directory",
kind: "symlink",
target: "hidden",
target_state: "internal",
}),
]),
);
},
);