openclaw / src /agents /worktrees /filesystem-native.test.ts
SaylorTwift's picture
SaylorTwift HF Staff
Add files using upload-large-folder tool
e249c6d verified
Raw History Blame Contribute Delete
7.14 kB
import fs from "node:fs/promises";
import path from "node:path";
import { configureFsSafeNative, getFsSafeNativeConfig } from "@openclaw/fs-safe/config";
import { afterEach, assert, beforeEach, describe, expect, it, vi } from "vitest";
import { getApfsCloneId } from "../../../test/helpers/apfs.js";
import { useAutoCleanupTempDirTracker } from "../../../test/helpers/temp-dir.js";
import * as runner from "../../process/exec-runner.js";
import { drainGlobalSingletonLifecycleState } from "../../shared/global-singleton.js";
import { detectWorktreeFilesystemBackend } from "./filesystem-backend.js";
import { nativeWorktreeFilesystem } from "./filesystem-native.js";
describe.skipIf(process.platform !== "darwin")("isolated native worktree operations", () => {
const tempDirs = useAutoCleanupTempDirTracker(afterEach);
const options = { commitGuard: () => {} };
beforeEach(() => {
for (const name of [
"FS_SAFE_NATIVE_MODE",
"OPENCLAW_FS_SAFE_NATIVE_MODE",
"FS_SAFE_PYTHON_MODE",
"OPENCLAW_FS_SAFE_PYTHON_MODE",
]) {
vi.stubEnv(name, undefined);
}
configureFsSafeNative({ mode: "off" });
});
afterEach(async () => {
await drainGlobalSingletonLifecycleState();
vi.restoreAllMocks();
vi.unstubAllEnvs();
});
it("clones and reads provenance with the host's native helper still off", async () => {
const root = tempDirs.make("openclaw-native-policy-");
const backend = await detectWorktreeFilesystemBackend(root, options);
assert(backend);
expect(backend?.id).toBe("apfs");
const source = path.join(root, "source");
const destination = path.join(root, "destination");
await backend.createTemplate(source, options);
await fs.writeFile(path.join(source, "payload"), Buffer.alloc(1024 * 1024, 0x5a));
await backend.cloneTemplate(source, destination, options);
const [original, cloned] = await nativeWorktreeFilesystem.readMetadata(
[path.join(source, "payload"), path.join(destination, "payload")],
options,
);
expect(original?.cloneId).toBe(getApfsCloneId(path.join(source, "payload")));
expect(cloned?.cloneId).toBe(original?.cloneId);
expect(cloned?.ino).not.toBe(original?.ino);
expect(await fs.readFile(path.join(destination, "payload"))).toEqual(
await fs.readFile(path.join(source, "payload")),
);
expect(getFsSafeNativeConfig().mode).toBe("off");
});
it.each(["FS_SAFE_NATIVE_MODE", "OPENCLAW_FS_SAFE_NATIVE_MODE"])(
"honors explicit %s=off in read and write children",
async (name) => {
vi.stubEnv(name, "off");
const root = tempDirs.make("openclaw-native-disabled-");
const source = path.join(root, "source");
const destination = path.join(root, "destination");
await fs.mkdir(source);
await fs.writeFile(path.join(source, "payload"), "source");
expect(await detectWorktreeFilesystemBackend(root, options)).toBeNull();
await expect(
nativeWorktreeFilesystem.copy(source, destination, options),
).rejects.toMatchObject({
code: "helper-unavailable",
});
await expect(fs.access(destination)).rejects.toMatchObject({ code: "ENOENT" });
expect(getFsSafeNativeConfig().mode).toBe("off");
},
);
it.each(["copy", "createSource"])(
"revalidates allocation authority before child %s input",
async (operation) => {
const root = tempDirs.make("openclaw-native-admission-");
const source = path.join(root, "source");
const destination = path.join(root, "destination");
await fs.mkdir(source);
await fs.writeFile(path.join(source, "payload"), "source");
const run = runner.runCommandBuffersWithTimeout;
let authorized = true;
let childPid: number | undefined;
vi.spyOn(runner, "runCommandBuffersWithTimeout").mockImplementation(
(argv, commandOptions) => {
if (typeof commandOptions === "number") {
throw new Error("Native writes need guarded input");
}
return run(argv, {
...commandOptions,
beforeInput(pid) {
childPid = pid;
authorized = false;
commandOptions.beforeInput?.(pid);
},
});
},
);
const writeOptions = {
commitGuard() {
if (!authorized) {
throw new Error("allocation lease lost");
}
},
};
await expect(
operation === "copy"
? nativeWorktreeFilesystem.copy(source, destination, writeOptions)
: nativeWorktreeFilesystem.createSource(destination, writeOptions),
).rejects.toThrow("allocation lease lost");
expect(childPid).toBeGreaterThan(0);
await expect(fs.access(destination)).rejects.toMatchObject({ code: "ENOENT" });
},
);
it("joins an admitted write child after cancellation before returning to cleanup", async () => {
const root = tempDirs.make("openclaw-native-settlement-");
const ready = path.join(root, "ready");
const canceled = path.join(root, "canceled");
const release = path.join(root, "release");
const finished = path.join(root, "finished");
const run = runner.runCommandBuffersWithTimeout;
// A controlled write child makes settlement observable independently of disk speed.
const script = `
import fs from 'node:fs';
import path from 'node:path';
import { setTimeout } from 'node:timers/promises';
import { serialize } from 'node:v8';
const root = process.argv[1];
process.on('SIGTERM', () => fs.writeFileSync(path.join(root, 'canceled'), 'yes'));
JSON.parse(fs.readFileSync(0, 'utf8'));
fs.writeFileSync(path.join(root, 'ready'), 'yes');
while (!fs.existsSync(path.join(root, 'release'))) await setTimeout(10);
fs.writeFileSync(path.join(root, 'finished'), 'yes');
process.stdout.write(serialize({ type: 'written' }));
`;
vi.spyOn(runner, "runCommandBuffersWithTimeout").mockImplementation((_argv, commandOptions) =>
run([process.execPath, "--input-type=module", "--eval", script, root], commandOptions),
);
const controller = new AbortController();
let settled = false;
const pending = nativeWorktreeFilesystem
.copy(path.join(root, "source"), path.join(root, "destination"), {
...options,
signal: controller.signal,
})
.then(
() => undefined,
(error: unknown) => error,
)
.finally(() => {
settled = true;
});
try {
await expect.poll(() => fs.readFile(ready, "utf8").catch(() => "")).toBe("yes");
controller.abort(new Error("allocation canceled"));
await expect.poll(() => fs.readFile(canceled, "utf8").catch(() => "")).toBe("yes");
expect(settled).toBe(false);
await expect(fs.access(finished)).rejects.toMatchObject({ code: "ENOENT" });
} finally {
await fs.writeFile(release, "yes");
await pending;
}
expect(await pending).toMatchObject({ message: "allocation canceled" });
expect(await fs.readFile(finished, "utf8")).toBe("yes");
});
});