40 lines
3.5 KiB
TypeScript
40 lines
3.5 KiB
TypeScript
import { describe, expect, it, afterEach } from "vitest";
|
|
import { mkdtempSync, mkdirSync, chmodSync, writeFileSync, linkSync, symlinkSync, rmSync } from "node:fs";
|
|
import { join } from "node:path";
|
|
import { createRequire } from "node:module";
|
|
const require = createRequire(import.meta.url);
|
|
import { WorkspaceFsAtV1 } from "../src/workspaces/workspace-fs-at.js";
|
|
const roots: string[] = [];
|
|
function openAbsolute(fs: WorkspaceFsAtV1, path: string) { let d = fs.openRoot(); for (const component of path.split("/").filter(Boolean)) { const next = fs.openDirectoryAt(d, component); d.close(); d = next; } return d; }
|
|
afterEach(() => { for (const root of roots.splice(0)) rmSync(root, { recursive: true, force: true }); });
|
|
|
|
describe("workspace fs-at native seam", () => {
|
|
it("exposes only opaque filesystem operations and preserves exact stat identity", () => {
|
|
const root = mkdtempSync(join(process.cwd(), "thoth-fsat-")); roots.push(root); mkdirSync(join(root, "private"), { mode: 0o700 });
|
|
const fs = new WorkspaceFsAtV1(); const d = openAbsolute(fs, root); const child = fs.openDirectoryAt(d, "private");
|
|
expect(child.stat().mode & 0o170000).toBe(0o040000);
|
|
expect(Object.keys(require("../native/workspace-fs-at/build/Release/workspace_fs_at.node"))).toEqual(["openat", "mkdirat", "fstatat", "fsyncDirectory", "close"]);
|
|
expect((child as unknown as Record<string, unknown>)._raw).toBeUndefined();
|
|
child.close(); d.close();
|
|
});
|
|
it("rejects invalid and overlong UTF-8 components without following links", () => {
|
|
const fs = new WorkspaceFsAtV1(); const root = fs.openRoot();
|
|
for (const name of ["", ".", "..", "a/b", "a\0b", "é".repeat(128)]) expect(() => fs.openDirectoryAt(root, name)).toThrow();
|
|
expect(() => fs.openDirectoryAt(root, "does-not-exist")).toThrow(); root.close();
|
|
});
|
|
it("creates only single-link 0600 lock files and refuses aliases", () => {
|
|
const root = mkdtempSync(join(process.cwd(), "thoth-fsat-")); roots.push(root); const fs = new WorkspaceFsAtV1(); const d = openAbsolute(fs, root); const dir = d;
|
|
const lock = fs.openOrCreateLockAt(dir, "writer.lock", 0o600); expect(lock.stat().mode & 0o777).toBe(0o600); expect(lock.stat().nlink).toBe(1n); lock.close(); dir.close(); d.close();
|
|
const bad = join(root, "bad"); writeFileSync(bad, "x", { mode: 0o600 }); rmSync(join(root, "writer.lock")); linkSync(bad, join(root, "writer.lock"));
|
|
const d2 = openAbsolute(fs, root); expect(() => fs.openOrCreateLockAt(d2, "writer.lock", 0o600)).toThrow(); d2.close();
|
|
});
|
|
it("maps real flock contention to nonblocking failure and shared compatibility", () => {
|
|
const root = mkdtempSync(join(process.cwd(), "thoth-fsat-")); roots.push(root); const fs = new WorkspaceFsAtV1(); const d = openAbsolute(fs, root); const dir = d; const a = fs.openOrCreateLockAt(dir, "writer.lock", 0o600); const b = fs.openOrCreateLockAt(dir, "writer.lock", 0o600);
|
|
fs.flockOwnedLock(a, "exclusive", "nonblocking"); expect(() => fs.flockOwnedLock(b, "shared", "nonblocking")).toThrow(); a.close(); fs.flockOwnedLock(b, "exclusive", "nonblocking"); b.close(); dir.close(); d.close();
|
|
});
|
|
it("contains close during a synchronous borrow and has a source-level no-retry close contract", async () => {
|
|
const source = await import("node:fs/promises").then(() => require("node:fs").readFileSync("native/workspace-fs-at/workspace_fs_at.cc", "utf8"));
|
|
expect(source).toContain("ERR_WORKSPACE_FS_AT_CLOSE_UNCERTAIN"); expect(source).not.toMatch(/do\s*\{[^}]*close\([^)]*\)[^}]*\}\s*while[^;]*EINTR/s);
|
|
});
|
|
});
|